From b1c00dcd0ae51d201f772e7f5fa61acae436a2cf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 8 Jun 2004 21:50:14 +0000 Subject: [PATCH 0001/1514] Create trunk directory git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1 fefdeb5f-60dc-0310-8127-8f9354f1896f From 9cb0b933e260008c6a03e24a4a149f726b8d86b2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 8 Jun 2004 23:54:24 +0000 Subject: [PATCH 0002/1514] initial commit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@3 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile | 10 ++ src/client.c | 32 ++++ src/client.h | 21 +++ src/core.c | 81 +++++++++ src/core.h | 21 +++ src/idxset.c | 329 +++++++++++++++++++++++++++++++++ src/idxset.h | 28 +++ src/inputstream.c | 50 ++++++ src/inputstream.h | 25 +++ src/iochannel.c | 158 ++++++++++++++++ src/iochannel.h | 20 +++ src/main.c | 26 +++ src/mainloop.c | 331 ++++++++++++++++++++++++++++++++++ src/mainloop.h | 38 ++++ src/memblock.c | 67 +++++++ src/memblock.h | 31 ++++ src/memblockq.c | 156 ++++++++++++++++ src/memblockq.h | 24 +++ src/module.c | 98 ++++++++++ src/module.h | 27 +++ src/oss.c | 30 ++++ src/outputstream.c | 41 +++++ src/outputstream.h | 22 +++ src/packet.c | 29 +++ src/packet.h | 18 ++ src/protocol-native-tcp.c | 19 ++ src/protocol-native-unix.c | 27 +++ src/protocol-native.c | 49 +++++ src/protocol-native.h | 9 + src/protocol-simple-tcp.c | 24 +++ src/protocol-simple.c | 173 ++++++++++++++++++ src/protocol-simple.h | 17 ++ src/pstream.c | 359 +++++++++++++++++++++++++++++++++++++ src/pstream.h | 22 +++ src/queue.c | 77 ++++++++ src/queue.h | 13 ++ src/sample.c | 80 +++++++++ src/sample.h | 35 ++++ src/sink-pipe.c | 155 ++++++++++++++++ src/sink.c | 217 ++++++++++++++++++++++ src/sink.h | 38 ++++ src/socket-server.c | 157 ++++++++++++++++ src/socket-server.h | 18 ++ src/source.c | 58 ++++++ src/source.h | 30 ++++ src/strbuf.c | 122 +++++++++++++ src/strbuf.h | 13 ++ 47 files changed, 3425 insertions(+) create mode 100644 src/Makefile create mode 100644 src/client.c create mode 100644 src/client.h create mode 100644 src/core.c create mode 100644 src/core.h create mode 100644 src/idxset.c create mode 100644 src/idxset.h create mode 100644 src/inputstream.c create mode 100644 src/inputstream.h create mode 100644 src/iochannel.c create mode 100644 src/iochannel.h create mode 100644 src/main.c create mode 100644 src/mainloop.c create mode 100644 src/mainloop.h create mode 100644 src/memblock.c create mode 100644 src/memblock.h create mode 100644 src/memblockq.c create mode 100644 src/memblockq.h create mode 100644 src/module.c create mode 100644 src/module.h create mode 100644 src/oss.c create mode 100644 src/outputstream.c create mode 100644 src/outputstream.h create mode 100644 src/packet.c create mode 100644 src/packet.h create mode 100644 src/protocol-native-tcp.c create mode 100644 src/protocol-native-unix.c create mode 100644 src/protocol-native.c create mode 100644 src/protocol-native.h create mode 100644 src/protocol-simple-tcp.c create mode 100644 src/protocol-simple.c create mode 100644 src/protocol-simple.h create mode 100644 src/pstream.c create mode 100644 src/pstream.h create mode 100644 src/queue.c create mode 100644 src/queue.h create mode 100644 src/sample.c create mode 100644 src/sample.h create mode 100644 src/sink-pipe.c create mode 100644 src/sink.c create mode 100644 src/sink.h create mode 100644 src/socket-server.c create mode 100644 src/socket-server.h create mode 100644 src/source.c create mode 100644 src/source.h create mode 100644 src/strbuf.c create mode 100644 src/strbuf.h diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 000000000..366e84e6a --- /dev/null +++ b/src/Makefile @@ -0,0 +1,10 @@ +CFLAGS=-Wall -pipe -ansi -D_GNU_SOURCE + +all: idxset.o queue.o strbuf.o mainloop.o iochannel.o packet.o \ + memblock.o sample.o socket-server.o memblockq.o client.o \ + core.o main.o outputstream.o inputstream.o source.o sink.o \ + pstream.o protocol-simple.o protocol-simple-tcp.o sink-pipe.o \ + module.o + +clean: + rm -f *.o diff --git a/src/client.c b/src/client.c new file mode 100644 index 000000000..56d857344 --- /dev/null +++ b/src/client.c @@ -0,0 +1,32 @@ +#include +#include +#include + +#include "client.h" + +struct client *client_new(struct core *core, const char *protocol_name, char *name) { + struct client *c; + int r; + assert(core); + + c = malloc(sizeof(struct client)); + assert(c); + c->protocol_name = protocol_name; + c->name = name ? strdup(name) : NULL; + c->kill = NULL; + c->userdata = NULL; + c->core = core; + + r = idxset_put(core->clients, c, &c->index); + assert(c->index != IDXSET_INVALID && r >= 0); + + return c; +} + +void client_free(struct client *c) { + assert(c && c->core); + + idxset_remove_by_data(c->core->clients, c, NULL); + free(c->name); + free(c); +} diff --git a/src/client.h b/src/client.h new file mode 100644 index 000000000..7128a452b --- /dev/null +++ b/src/client.h @@ -0,0 +1,21 @@ +#ifndef fooclienthfoo +#define fooclienthfoo + +#include "core.h" + +struct client { + char *name; + uint32_t index; + + const char *protocol_name; + + void *userdata; + void (*kill)(struct client *c); + + struct core *core; +}; + +struct client *client_new(struct core *c, const char *protocol_name, char *name); +void client_free(struct client *c); + +#endif diff --git a/src/core.c b/src/core.c new file mode 100644 index 000000000..7cfa66e3f --- /dev/null +++ b/src/core.c @@ -0,0 +1,81 @@ +#include +#include +#include + +#include "core.h" +#include "module.h" +#include "sink.h" +#include "source.h" + +struct core* core_new(struct mainloop *m) { + struct core* c; + c = malloc(sizeof(struct core)); + assert(c); + + c->mainloop = m; + c->clients = idxset_new(NULL, NULL); + c->sinks = idxset_new(NULL, NULL); + c->sources = idxset_new(NULL, NULL); + c->output_streams = idxset_new(NULL, NULL); + c->input_streams = idxset_new(NULL, NULL); + + c->default_source_index = c->default_sink_index = IDXSET_INVALID; + + c->modules = NULL; + + return c; +}; + +void core_free(struct core *c) { + assert(c); + + module_unload_all(c); + assert(!c->modules); + + assert(idxset_isempty(c->clients)); + idxset_free(c->clients, NULL, NULL); + + assert(idxset_isempty(c->sinks)); + idxset_free(c->sinks, NULL, NULL); + + assert(idxset_isempty(c->sources)); + idxset_free(c->sources, NULL, NULL); + + assert(idxset_isempty(c->output_streams)); + idxset_free(c->output_streams, NULL, NULL); + + assert(idxset_isempty(c->input_streams)); + idxset_free(c->input_streams, NULL, NULL); + + free(c); +}; + +struct sink* core_get_default_sink(struct core *c) { + struct sink *sink; + assert(c); + + if ((sink = idxset_get_by_index(c->sinks, c->default_sink_index))) + return sink; + + if (!(sink = idxset_rrobin(c->sinks, NULL))) + return NULL; + + fprintf(stderr, "Default sink vanished, setting to %u\n", sink->index); + c->default_sink_index = sink->index; + return sink; +} + +struct source* core_get_default_source(struct core *c) { + struct source *source; + assert(c); + + if ((source = idxset_get_by_index(c->sources, c->default_source_index))) + return source; + + if (!(source = idxset_rrobin(c->sources, NULL))) + return NULL; + + fprintf(stderr, "Default source vanished, setting to %u\n", source->index); + c->default_source_index = source->index; + return source; +} diff --git a/src/core.h b/src/core.h new file mode 100644 index 000000000..649c9dbad --- /dev/null +++ b/src/core.h @@ -0,0 +1,21 @@ +#ifndef foocorehfoo +#define foocorehfoo + +#include "idxset.h" +#include "mainloop.h" + +struct core { + struct mainloop *mainloop; + + struct idxset *clients, *sinks, *sources, *output_streams, *input_streams, *modules; + + uint32_t default_source_index, default_sink_index; +}; + +struct core* core_new(struct mainloop *m); +void core_free(struct core*c); + +struct sink* core_get_default_sink(struct core *c); +struct source* core_get_default_source(struct core *c); + +#endif diff --git a/src/idxset.c b/src/idxset.c new file mode 100644 index 000000000..eaea34f46 --- /dev/null +++ b/src/idxset.c @@ -0,0 +1,329 @@ +#include +#include +#include + +#include "idxset.h" + +struct idxset_entry { + void *data; + uint32_t index; + unsigned hash_value; + + struct idxset_entry *hash_prev, *hash_next; + struct idxset_entry* iterate_prev, *iterate_next; +}; + +struct idxset { + unsigned (*hash_func) (void *p); + int (*compare_func)(void *a, void *b); + + unsigned hash_table_size, n_entries; + struct idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail, *rrobin; + uint32_t index, start_index, array_size; +}; + +static unsigned trivial_hash_func(void *p) { + return (unsigned) p; +} + +static int trivial_compare_func(void *a, void *b) { + return !(a == b); +} + +struct idxset* idxset_new(unsigned (*hash_func) (void *p), int (*compare_func) (void*a, void*b)) { + struct idxset *s; + + s = malloc(sizeof(struct idxset)); + assert(s); + s->hash_func = hash_func ? hash_func : trivial_hash_func; + s->compare_func = compare_func ? compare_func : trivial_compare_func; + s->hash_table_size = 1023; + s->hash_table = malloc(sizeof(struct idxset_entry*)*s->hash_table_size); + assert(s->hash_table); + s->array = NULL; + s->array_size = 0; + s->index = 0; + s->start_index = 0; + s->n_entries = 0; + + s->iterate_list_head = s->iterate_list_tail = NULL; + + return s; +} + +void idxset_free(struct idxset *s, void (*free_func) (void *p, void *userdata), void *userdata) { + assert(s); + + if (free_func) { + while (s->iterate_list_head) { + struct idxset_entry *e = s->iterate_list_head; + s->iterate_list_head = s->iterate_list_head->iterate_next; + + if (free_func) + free_func(e->data, userdata); + free(e); + } + } + + free(s->hash_table); + free(s->array); + free(s); +} + +static struct idxset_entry* hash_scan(struct idxset *s, struct idxset_entry* e, void *p) { + assert(p); + + assert(s->compare_func); + for (; e; e = e->hash_next) + if (s->compare_func(e->data, p)) + return e; + + return NULL; +} + +static void extend_array(struct idxset *s, uint32_t index) { + uint32_t i, j, l; + struct idxset_entry** n; + assert(index >= s->start_index ); + + if (index <= s->start_index + s->array_size) + return; + + for (i = 0; i < s->array_size; i++) + if (s->array[i]) + break; + + l = index - s->start_index - i + 100; + n = malloc(sizeof(struct hash_table_entry*)*l); + assert(n); + memset(n, 0, sizeof(struct hash_table_entry*)*l); + + for (j = 0; j < s->array_size-i; j++) + n[j] = s->array[i+j]; + + free(s->array); + + s->array = n; + s->array_size = l; + s->start_index += i; +} + +static struct idxset_entry** array_index(struct idxset*s, uint32_t index) { + + if (index >= s->start_index + s->array_size) + return NULL; + + if (index < s->start_index) + return NULL; + + return s->array + (index - s->start_index); +} + +int idxset_put(struct idxset*s, void *p, uint32_t *index) { + unsigned h; + struct idxset_entry *e, **a; + assert(s && p); + + assert(s->hash_func); + h = s->hash_func(p) % s->hash_table_size; + + assert(s->hash_table); + if ((e = hash_scan(s, s->hash_table[h], p))) { + if (index) + *index = e->index; + + return -1; + } + + e = malloc(sizeof(struct idxset_entry)); + assert(e); + + e->data = p; + e->index = s->index++; + e->hash_value = h; + + /* Insert into hash table */ + e->hash_next = s->hash_table[h]; + e->hash_prev = NULL; + if (s->hash_table[h]) + s->hash_table[h]->hash_prev = e; + s->hash_table[h] = e; + + /* Insert into array */ + extend_array(s, s->index); + a = array_index(s, s->index); + assert(a && !*a); + *a = e; + + /* Insert into linked list */ + e->iterate_next = NULL; + e->iterate_prev = s->iterate_list_tail; + if (s->iterate_list_tail) { + assert(s->iterate_list_head); + s->iterate_list_tail->iterate_next = e; + } else { + assert(!s->iterate_list_head); + s->iterate_list_head = e; + } + s->iterate_list_tail = e; + + s->n_entries++; + assert(s->n_entries >= 1); + + if (index) + *index = e->index; + + return 0; +} + +void* idxset_get_by_index(struct idxset*s, uint32_t index) { + struct idxset_entry **a; + assert(s); + + if (!(a = array_index(s, index))) + return NULL; + + return (*a)->data; +} + +void* idxset_get_by_data(struct idxset*s, void *p, uint32_t *index) { + unsigned h; + struct idxset_entry *e; + assert(s && p); + + assert(s->hash_func); + h = s->hash_func(p) % s->hash_table_size; + + assert(s->hash_table); + if (!(e = hash_scan(s, s->hash_table[h], p))) + return NULL; + + if (index) + *index = e->index; + + return e->data; +} + +static void remove_entry(struct idxset *s, struct idxset_entry *e) { + struct idxset_entry **a; + assert(s && e); + + /* Remove from array */ + a = array_index(s, s->index); + assert(a && *a == e); + *a = NULL; + + /* Remove from linked list */ + if (e->iterate_next) + e->iterate_next->iterate_prev = e->iterate_prev; + else + s->iterate_list_tail = e->iterate_prev; + + if (e->iterate_prev) + e->iterate_prev->iterate_next = e->iterate_next; + else + s->iterate_list_head = e->iterate_next; + + /* Remove from hash table */ + if (e->hash_next) + e->hash_next->hash_prev = e->hash_prev; + + if (e->hash_prev) + e->hash_prev->hash_next = e->hash_next; + else + s->hash_table[e->hash_value] = e->hash_next; + + if (s->rrobin == e) + s->rrobin = NULL; + + free(e); + + assert(s->n_entries >= 1); + s->n_entries--; +} + +void* idxset_remove_by_index(struct idxset*s, uint32_t index) { + struct idxset_entry **a; + void *data; + + assert(s); + + if (!(a = array_index(s, index))) + return NULL; + + data = (*a)->data; + remove_entry(s, *a); + + return data; +} + +void* idxset_remove_by_data(struct idxset*s, void *data, uint32_t *index) { + struct idxset_entry *e; + unsigned h; + + assert(s->hash_func); + h = s->hash_func(data) % s->hash_table_size; + + assert(s->hash_table); + if (!(e = hash_scan(s, s->hash_table[h], data))) + return NULL; + + data = e->data; + if (index) + *index = e->index; + + remove_entry(s, e); + + return data; +} + +void* idxset_rrobin(struct idxset *s, uint32_t *index) { + assert(s && index); + + if (s->rrobin) + s->rrobin = s->rrobin->iterate_next; + + if (!s->rrobin) + s->rrobin = s->iterate_list_head; + + if (!s->rrobin) + return NULL; + + if (index) + *index = s->rrobin->index; + + return s->rrobin->data; +} + +int idxset_foreach(struct idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata) { + struct idxset_entry *e; + assert(s && func); + + e = s->iterate_list_head; + while (e) { + int del = 0, r; + struct idxset_entry *n = e->iterate_next; + + r = func(e->data, e->index, &del, userdata); + + if (del) + remove_entry(s, e); + + if (r < 0) + return r; + + e = n; + } + + return 0; +} + +unsigned idxset_ncontents(struct idxset*s) { + assert(s); + return s->n_entries; +} + +int idxset_isempty(struct idxset *s) { + assert(s); + return s->n_entries == 0; +} diff --git a/src/idxset.h b/src/idxset.h new file mode 100644 index 000000000..f649e23e7 --- /dev/null +++ b/src/idxset.h @@ -0,0 +1,28 @@ +#ifndef fooidxsethfoo +#define fooidxsethfoo + +#include + +#define IDXSET_INVALID ((uint32_t) -1) + +struct idxset; + +struct idxset* idxset_new(unsigned (*hash_func) (void *p), int (*compare_func) (void*a, void*b)); +void idxset_free(struct idxset *s, void (*free_func) (void *p, void *userdata), void *userdata); + +int idxset_put(struct idxset*s, void *p, uint32_t *index); + +void* idxset_get_by_index(struct idxset*s, uint32_t index); +void* idxset_get_by_data(struct idxset*s, void *p, uint32_t *index); + +void* idxset_remove_by_index(struct idxset*s, uint32_t index); +void* idxset_remove_by_data(struct idxset*s, void *p, uint32_t *index); + +void* idxset_rrobin(struct idxset *s, uint32_t *index); + +int idxset_foreach(struct idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata); + +unsigned idxset_ncontents(struct idxset*s); +int idxset_isempty(struct idxset *s); + +#endif diff --git a/src/inputstream.c b/src/inputstream.c new file mode 100644 index 000000000..c7b4b4c7a --- /dev/null +++ b/src/inputstream.c @@ -0,0 +1,50 @@ +#include +#include +#include + +#include "inputstream.h" + +struct input_stream* input_stream_new(struct sink *s, struct sample_spec *spec, const char *name) { + struct input_stream *i; + int r; + assert(s && spec); + + i = malloc(sizeof(struct input_stream)); + assert(i); + i->name = name ? strdup(name) : NULL; + i->sink = s; + i->spec = *spec; + + i->memblockq = memblockq_new(bytes_per_second(spec)*5, sample_size(spec)); + assert(i->memblockq); + + assert(s->core); + r = idxset_put(s->core->input_streams, i, &i->index); + assert(r == 0 && i->index != IDXSET_INVALID); + r = idxset_put(s->input_streams, i, NULL); + assert(r == 0); + + return i; +} + +void input_stream_free(struct input_stream* i) { + assert(i); + + memblockq_free(i->memblockq); + + assert(i->sink && i->sink->core); + idxset_remove_by_data(i->sink->core->input_streams, i, NULL); + idxset_remove_by_data(i->sink->input_streams, i, NULL); + + free(i->name); + free(i); +} + +void input_stream_notify(struct input_stream *i) { + assert(i); + + if (memblockq_is_empty(i->memblockq)) + return; + + sink_notify(i->sink); +} diff --git a/src/inputstream.h b/src/inputstream.h new file mode 100644 index 000000000..0353799e8 --- /dev/null +++ b/src/inputstream.h @@ -0,0 +1,25 @@ +#ifndef fooinputstreamhfoo +#define fooinputstreamhfoo + +#include + +#include "sink.h" +#include "sample.h" +#include "memblockq.h" + +struct input_stream { + char *name; + uint32_t index; + + struct sink *sink; + struct sample_spec spec; + + struct memblockq *memblockq; +}; + +struct input_stream* input_stream_new(struct sink *s, struct sample_spec *spec, const char *name); +void input_stream_free(struct input_stream* i); + +void input_stream_notify(struct input_stream *i); + +#endif diff --git a/src/iochannel.c b/src/iochannel.c new file mode 100644 index 000000000..db9717a96 --- /dev/null +++ b/src/iochannel.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include + +#include "iochannel.h" + +struct iochannel { + int ifd, ofd; + struct mainloop* mainloop; + + void (*callback)(struct iochannel*io, void *userdata); + void*userdata; + + int readable; + int writable; + + struct mainloop_source* input_source, *output_source; +}; + +static void enable_mainloop_sources(struct iochannel *io) { + assert(io); + + if (io->input_source == io->output_source) { + enum mainloop_io_event e = MAINLOOP_IO_EVENT_NULL; + assert(io->input_source); + + if (!io->readable) + e |= MAINLOOP_IO_EVENT_IN; + if (!io->writable) + e |= MAINLOOP_IO_EVENT_OUT; + + mainloop_source_io_set_events(io->input_source, e); + } else { + if (io->input_source) + mainloop_source_io_set_events(io->input_source, io->readable ? MAINLOOP_IO_EVENT_NULL : MAINLOOP_IO_EVENT_IN); + if (io->output_source) + mainloop_source_io_set_events(io->output_source, io->writable ? MAINLOOP_IO_EVENT_NULL : MAINLOOP_IO_EVENT_OUT); + } +} + +static void callback(struct mainloop_source*s, int fd, enum mainloop_io_event events, void *userdata) { + struct iochannel *io = userdata; + int changed; + assert(s && fd >= 0 && userdata); + + if (events & MAINLOOP_IO_EVENT_IN && !io->readable) { + io->readable = 1; + changed = 1; + } + + if (events & MAINLOOP_IO_EVENT_OUT && !io->writable) { + io->writable = 1; + changed = 1; + } + + if (changed) { + enable_mainloop_sources(io); + + if (io->callback) + io->callback(io, io->userdata); + } +} + +static void make_nonblock_fd(int fd) { + int v; + + if ((v = fcntl(fd, F_GETFL)) >= 0) + if (!(v & O_NONBLOCK)) + fcntl(fd, F_SETFL, v|O_NONBLOCK); +} + +struct iochannel* iochannel_new(struct mainloop*m, int ifd, int ofd) { + struct iochannel *io; + assert(m && (ifd >= 0 || ofd >= 0)); + + io = malloc(sizeof(struct iochannel)); + io->ifd = ifd; + io->ofd = ofd; + io->mainloop = m; + + io->userdata = NULL; + io->callback = NULL; + io->readable = 0; + io->writable = 0; + + if (ifd == ofd) { + assert(ifd >= 0); + make_nonblock_fd(io->ifd); + io->input_source = io->output_source = mainloop_source_new_io(m, ifd, MAINLOOP_IO_EVENT_IN|MAINLOOP_IO_EVENT_OUT, callback, io); + } else { + + if (ifd >= 0) { + make_nonblock_fd(io->ifd); + io->input_source = mainloop_source_new_io(m, ifd, MAINLOOP_IO_EVENT_IN, callback, io); + } else + io->input_source = NULL; + + if (ofd >= 0) { + make_nonblock_fd(io->ofd); + io->output_source = mainloop_source_new_io(m, ofd, MAINLOOP_IO_EVENT_OUT, callback, io); + } else + io->output_source = NULL; + } + + return io; +} + +void iochannel_free(struct iochannel*io) { + assert(io); + + if (io->ifd >= 0) + close(io->ifd); + if (io->ofd >= 0 && io->ofd != io->ifd) + close(io->ofd); + + if (io->input_source) + mainloop_source_free(io->input_source); + if (io->output_source) + mainloop_source_free(io->output_source); + + free(io); +} + +int iochannel_is_readable(struct iochannel*io) { + assert(io); + return io->readable; +} + +int iochannel_is_writable(struct iochannel*io) { + assert(io); + return io->writable; +} + +ssize_t iochannel_write(struct iochannel*io, const void*data, size_t l) { + ssize_t r; + assert(io && data && l && io->ofd >= 0); + + if ((r = write(io->ofd, data, l)) >= 0) { + io->writable = 0; + enable_mainloop_sources(io); + } + + return r; +} + +ssize_t iochannel_read(struct iochannel*io, void*data, size_t l) { + ssize_t r; + + assert(io && data && l && io->ifd >= 0); + + if ((r = read(io->ifd, data, l)) >= 0) { + io->readable = 0; + enable_mainloop_sources(io); + } + + return r; +} diff --git a/src/iochannel.h b/src/iochannel.h new file mode 100644 index 000000000..f97fabbab --- /dev/null +++ b/src/iochannel.h @@ -0,0 +1,20 @@ +#ifndef fooiochannelhfoo +#define fooiochannelhfoo + +#include +#include "mainloop.h" + +struct iochannel; + +struct iochannel* iochannel_new(struct mainloop*m, int ifd, int ofd); +void iochannel_free(struct iochannel*io); + +ssize_t iochannel_write(struct iochannel*io, const void*data, size_t l); +ssize_t iochannel_read(struct iochannel*io, void*data, size_t l); + +int iochannel_is_readable(struct iochannel*io); +int iochannel_is_writable(struct iochannel*io); + +void iochannel_set_callback(struct iochannel*io, void (*callback)(struct iochannel*io, void *userdata), void *userdata); + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 000000000..3104c2649 --- /dev/null +++ b/src/main.c @@ -0,0 +1,26 @@ +#include +#include + +#include "core.h" +#include "mainloop.h" +#include "module.h" + +int main(int argc, char *argv[]) { + struct mainloop *m; + struct core *c; + + m = mainloop_new(); + assert(m); + c = core_new(m); + assert(c); + + module_load(c, "sink-pipe", NULL); + module_load(c, "protocol-simple-tcp", NULL); + + mainloop_run(m); + + core_free(c); + mainloop_free(m); + + return 0; +} diff --git a/src/mainloop.c b/src/mainloop.c new file mode 100644 index 000000000..d043ce90a --- /dev/null +++ b/src/mainloop.c @@ -0,0 +1,331 @@ +#include +#include +#include +#include + +#include "mainloop.h" + +struct mainloop_source { + struct mainloop_source *next; + struct mainloop *mainloop; + enum mainloop_source_type type; + + int enabled; + int dead; + void *userdata; + + struct { + int fd; + enum mainloop_io_event events; + void (*callback)(struct mainloop_source*s, int fd, enum mainloop_io_event event, void *userdata); + struct pollfd pollfd; + } io; + + struct { + void (*callback)(struct mainloop_source*s, void *userdata); + } prepare; + + struct { + void (*callback)(struct mainloop_source*s, void *userdata); + } idle; +}; + +struct mainloop_source_list { + struct mainloop_source *sources; + int n_sources; + int dead_sources; +}; + +struct mainloop { + struct mainloop_source_list io_sources, prepare_sources, idle_sources; + + struct pollfd *pollfds; + int max_pollfds, n_pollfds; + int rebuild_pollfds; + + int quit; + int running; +}; + +struct mainloop *mainloop_new(void) { + struct mainloop *m; + + m = malloc(sizeof(struct mainloop)); + assert(m); + memset(m, 0, sizeof(struct mainloop)); + + return m; +} + +static void free_sources(struct mainloop_source_list *l, int all) { + struct mainloop_source *s, *p; + assert(l); + + if (!l->dead_sources) + return; + + p = NULL; + s = l->sources; + while (s) { + if (all || s->dead) { + struct mainloop_source *t = s; + s = s->next; + + if (p) + p->next = s; + else + l->sources = s; + + free(t); + } else { + p = s; + s = s->next; + } + } + + l->dead_sources = 0; + + if (all) { + assert(l->sources); + l->n_sources = 0; + } +} + +void mainloop_free(struct mainloop* m) { + assert(m); + free_sources(&m->io_sources, 1); + free_sources(&m->prepare_sources, 1); + free_sources(&m->idle_sources, 1); + free(m->pollfds); +} + +static void rebuild_pollfds(struct mainloop *m) { + struct mainloop_source*s; + struct pollfd *p; + + if (m->max_pollfds < m->io_sources.n_sources) { + m->max_pollfds = m->io_sources.n_sources*2; + m->pollfds = realloc(m->pollfds, sizeof(struct pollfd)*m->max_pollfds); + } + + m->n_pollfds = 0; + p = m->pollfds; + for (s = m->io_sources.sources; s; s = s->next) { + assert(s->type == MAINLOOP_SOURCE_TYPE_IO); + if (!s->dead && s->enabled && s->io.events != MAINLOOP_IO_EVENT_NULL) { + *(p++) = s->io.pollfd; + m->n_pollfds++; + } + } +} + +static void dispatch_pollfds(struct mainloop *m) { + int i; + struct pollfd *p; + struct mainloop_source *s; + /* This loop assumes that m->sources and m->pollfds have the same + * order and that m->pollfds is a subset of m->sources! */ + + s = m->io_sources.sources; + for (p = m->pollfds, i = 0; i < m->n_pollfds; p++, i++) { + for (;;) { + assert(s && s->type == MAINLOOP_SOURCE_TYPE_IO); + + if (p->fd == s->io.fd) { + if (!s->dead && s->enabled) { + enum mainloop_io_event e = (p->revents & POLLIN ? MAINLOOP_IO_EVENT_IN : 0) | (p->revents & POLLOUT ? MAINLOOP_IO_EVENT_OUT : 0); + if (e) { + assert(s->io.callback); + s->io.callback(s, s->io.fd, e, s->userdata); + } + } + + break; + } + s = s->next; + } + } +} + +int mainloop_iterate(struct mainloop *m, int block) { + struct mainloop_source *s; + int c; + assert(m && !m->running); + + if(m->quit) + return m->quit; + + free_sources(&m->io_sources, 0); + free_sources(&m->prepare_sources, 0); + free_sources(&m->idle_sources, 0); + + for (s = m->prepare_sources.sources; s; s = s->next) { + assert(!s->dead && s->type == MAINLOOP_SOURCE_TYPE_PREPARE); + if (s->enabled) { + assert(s->prepare.callback); + s->prepare.callback(s, s->userdata); + } + } + + if (m->rebuild_pollfds) + rebuild_pollfds(m); + + m->running = 1; + + if ((c = poll(m->pollfds, m->n_pollfds, (block && !m->idle_sources.n_sources) ? -1 : 0)) > 0) + dispatch_pollfds(m); + else if (c == 0) { + for (s = m->idle_sources.sources; s; s = s->next) { + assert(!s->dead && s->type == MAINLOOP_SOURCE_TYPE_IDLE); + if (s->enabled) { + assert(s->idle.callback); + s->idle.callback(s, s->userdata); + } + } + } + + m->running = 0; + return c < 0 ? -1 : 0; +} + +int mainloop_run(struct mainloop *m) { + int r; + while (!(r = mainloop_iterate(m, 1))); + return r; +} + +void mainloop_quit(struct mainloop *m, int r) { + assert(m); + m->quit = r; +} + +static struct mainloop_source_list* get_source_list(struct mainloop *m, enum mainloop_source_type type) { + struct mainloop_source_list *l; + + switch(type) { + case MAINLOOP_SOURCE_TYPE_IO: + l = &m->io_sources; + break; + case MAINLOOP_SOURCE_TYPE_PREPARE: + l = &m->prepare_sources; + break; + case MAINLOOP_SOURCE_TYPE_IDLE: + l = &m->idle_sources; + break; + default: + l = NULL; + break; + } + + return l; +} + +static struct mainloop_source *source_new(struct mainloop*m, enum mainloop_source_type type) { + struct mainloop_source_list *l; + struct mainloop_source* s; + assert(m); + + s = malloc(sizeof(struct mainloop_source)); + assert(s); + memset(s, 0, sizeof(struct mainloop_source)); + + s->type = type; + s->mainloop = m; + + l = get_source_list(m, type); + assert(l); + + s->next = l->sources; + l->sources = s; + l->n_sources++; + return s; +} + +struct mainloop_source* mainloop_source_new_io(struct mainloop*m, int fd, enum mainloop_io_event event, void (*callback)(struct mainloop_source*s, int fd, enum mainloop_io_event event, void *userdata), void *userdata) { + struct mainloop_source* s; + assert(m && fd>=0 && callback); + + s = source_new(m, MAINLOOP_SOURCE_TYPE_IO); + + s->io.fd = fd; + s->io.events = event; + s->io.callback = callback; + s->userdata = userdata; + s->io.pollfd.fd = fd; + s->io.pollfd.events = (event & MAINLOOP_IO_EVENT_IN ? POLLIN : 0) | (event & MAINLOOP_IO_EVENT_OUT ? POLLOUT : 0); + s->io.pollfd.revents = 0; + + s->enabled = 1; + + m->rebuild_pollfds = 1; + return s; +} + +struct mainloop_source* mainloop_source_new_prepare(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata) { + struct mainloop_source* s; + assert(m && callback); + + s = source_new(m, MAINLOOP_SOURCE_TYPE_PREPARE); + + s->prepare.callback = callback; + s->userdata = userdata; + s->enabled = 1; + return s; +} + +struct mainloop_source* mainloop_source_new_idle(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata) { + struct mainloop_source* s; + assert(m && callback); + + s = source_new(m, MAINLOOP_SOURCE_TYPE_IDLE); + + s->prepare.callback = callback; + s->userdata = userdata; + s->enabled = 1; + return s; +} + +void mainloop_source_free(struct mainloop_source*s) { + struct mainloop_source_list *l; + assert(s && !s->dead); + s->dead = 1; + + assert(s->mainloop); + l = get_source_list(s->mainloop, s->type); + assert(l); + + l->n_sources--; + l->dead_sources = 1; + + if (s->type == MAINLOOP_SOURCE_TYPE_IO) + s->mainloop->rebuild_pollfds = 1; +} + +void mainloop_source_enable(struct mainloop_source*s, int b) { + assert(s && !s->dead); + + if (s->type == MAINLOOP_SOURCE_TYPE_IO && ((s->enabled && !b) || (!s->enabled && b))) { + assert(s->mainloop); + s->mainloop->rebuild_pollfds = 1; + } + + s->enabled = b; +} + +void mainloop_source_io_set_events(struct mainloop_source*s, enum mainloop_io_event events) { + assert(s && !s->dead && s->type == MAINLOOP_SOURCE_TYPE_IO); + + if ((s->io.events && !events) || (!s->io.events && events)) { + assert(s->mainloop); + s->mainloop->rebuild_pollfds = 1; + } + + s->io.events = events; + s->io.pollfd.events = ((events & MAINLOOP_IO_EVENT_IN) ? POLLIN : 0) | ((events & MAINLOOP_IO_EVENT_OUT) ? POLLOUT : 0); +} + +struct mainloop *mainloop_source_get_mainloop(struct mainloop_source *s) { + assert(s); + + return s->mainloop; +} diff --git a/src/mainloop.h b/src/mainloop.h new file mode 100644 index 000000000..72376c727 --- /dev/null +++ b/src/mainloop.h @@ -0,0 +1,38 @@ +#ifndef foomainloophfoo +#define foomainloophfoo + +struct mainloop; +struct mainloop_source; + +enum mainloop_io_event { + MAINLOOP_IO_EVENT_NULL = 0, + MAINLOOP_IO_EVENT_IN = 1, + MAINLOOP_IO_EVENT_OUT = 2, + MAINLOOP_IO_EVENT_BOTH = 3 +}; + +enum mainloop_source_type { + MAINLOOP_SOURCE_TYPE_IO, + MAINLOOP_SOURCE_TYPE_PREPARE, + MAINLOOP_SOURCE_TYPE_IDLE +}; + +struct mainloop *mainloop_new(void); +void mainloop_free(struct mainloop* m); + +int mainloop_iterate(struct mainloop *m, int block); +int mainloop_run(struct mainloop *m); +void mainloop_quit(struct mainloop *m, int r); + +struct mainloop_source* mainloop_source_new_io(struct mainloop*m, int fd, enum mainloop_io_event event, void (*callback)(struct mainloop_source*s, int fd, enum mainloop_io_event event, void *userdata), void *userdata); +struct mainloop_source* mainloop_source_new_prepare(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata); +struct mainloop_source* mainloop_source_new_idle(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata); + +void mainloop_source_free(struct mainloop_source*s); +void mainloop_source_enable(struct mainloop_source*s, int b); + +void mainloop_source_io_set_events(struct mainloop_source*s, enum mainloop_io_event event); + +struct mainloop *mainloop_source_get_mainloop(struct mainloop_source *s); + +#endif diff --git a/src/memblock.c b/src/memblock.c new file mode 100644 index 000000000..3bef4944f --- /dev/null +++ b/src/memblock.c @@ -0,0 +1,67 @@ +#include +#include +#include + +#include "memblock.h" + +struct memblock *memblock_new(size_t length) { + struct memblock *b = malloc(sizeof(struct memblock)+length); + b->type = MEMBLOCK_APPENDED; + b->ref = 1; + b->length = length; + b->data = b+1; + return b; +} + +struct memblock *memblock_new_fixed(void *d, size_t length) { + struct memblock *b = malloc(sizeof(struct memblock)); + b->type = MEMBLOCK_FIXED; + b->ref = 1; + b->length = length; + b->data = d; + return b; +} + +struct memblock *memblock_new_dynamic(void *d, size_t length) { + struct memblock *b = malloc(sizeof(struct memblock)); + b->type = MEMBLOCK_DYNAMIC; + b->ref = 1; + b->length = length; + b->data = d; + return b; +} + +struct memblock* memblock_ref(struct memblock*b) { + assert(b && b->ref >= 1); + b->ref++; + return b; +} + +void memblock_unref(struct memblock*b) { + assert(b && b->ref >= 1); + b->ref--; + + if (b->ref == 0) { + if (b->type == MEMBLOCK_DYNAMIC) + free(b->data); + free(b); + } +} + +void memblock_unref_fixed(struct memblock *b) { + void *d; + + assert(b && b->ref >= 1); + + if (b->ref == 1) { + memblock_unref(b); + return; + } + + d = malloc(b->length); + assert(d); + memcpy(d, b->data, b->length); + b->data = d; + b->type = MEMBLOCK_DYNAMIC; +} + diff --git a/src/memblock.h b/src/memblock.h new file mode 100644 index 000000000..48e87286d --- /dev/null +++ b/src/memblock.h @@ -0,0 +1,31 @@ +#ifndef foomemblockhfoo +#define foomemblockhfoo + +#include + +enum memblock_type { MEMBLOCK_FIXED, MEMBLOCK_APPENDED, MEMBLOCK_DYNAMIC }; + +struct memblock { + enum memblock_type type; + unsigned ref; + size_t length; + void *data; +}; + +struct memchunk { + struct memblock *memblock; + size_t index, length; +}; + +struct memblock *memblock_new(size_t length); +struct memblock *memblock_new_fixed(void *data, size_t length); +struct memblock *memblock_new_dynamic(void *data, size_t length); + +void memblock_unref(struct memblock*b); +struct memblock* memblock_ref(struct memblock*b); + +void memblock_unref_fixed(struct memblock*b); + +#define memblock_assert_exclusive(b) assert((b)->ref == 1) + +#endif diff --git a/src/memblockq.c b/src/memblockq.c new file mode 100644 index 000000000..1424c5567 --- /dev/null +++ b/src/memblockq.c @@ -0,0 +1,156 @@ +#include +#include + +#include "memblockq.h" + +struct memblock_list { + struct memblock_list *next; + struct memchunk chunk; +}; + +struct memblockq { + struct memblock_list *blocks, *blocks_tail; + unsigned n_blocks; + size_t total_length; + size_t maxlength; + size_t base; +}; + +struct memblockq* memblockq_new(size_t maxlength, size_t base) { + struct memblockq* bq; + assert(maxlength && base); + + bq = malloc(sizeof(struct memblockq)); + assert(bq); + bq->blocks = bq->blocks_tail = 0; + bq->n_blocks = 0; + bq->total_length = 0; + bq->base = base; + bq->maxlength = ((maxlength+base-1)/base)*base; + assert(bq->maxlength >= base); + return bq; +} + +void memblockq_free(struct memblockq* bq) { + struct memblock_list *l; + assert(bq); + + while ((l = bq->blocks)) { + bq->blocks = l->next; + memblock_unref(l->chunk.memblock); + free(l); + } + + free(bq); +} + +void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta) { + struct memblock_list *q; + assert(bq && chunk && chunk->memblock && chunk->index); + + q = malloc(sizeof(struct memblock_list)); + assert(q); + + q->chunk = *chunk; + memblock_ref(q->chunk.memblock); + assert(q->chunk.index+q->chunk.length <= q->chunk.memblock->length); + q->next = NULL; + + if (bq->blocks_tail) + bq->blocks_tail->next = q; + else + bq->blocks = q; + + bq->blocks_tail = q; + + bq->n_blocks++; + bq->total_length += chunk->length; + + memblockq_shorten(bq, bq->maxlength); +} + +int memblockq_peek(struct memblockq* bq, struct memchunk *chunk) { + assert(bq && chunk); + + if (!bq->blocks) + return -1; + + *chunk = bq->blocks->chunk; + memblock_ref(chunk->memblock); + return 0; +} + +int memblockq_pop(struct memblockq* bq, struct memchunk *chunk) { + struct memblock_list *q; + + assert(bq && chunk); + + if (!bq->blocks) + return -1; + + q = bq->blocks; + bq->blocks = bq->blocks->next; + + *chunk = q->chunk; + + bq->n_blocks--; + bq->total_length -= chunk->length; + + free(q); + return 0; +} + +void memblockq_drop(struct memblockq *bq, size_t length) { + assert(bq); + + while (length > 0) { + size_t l = length; + assert(bq->blocks && bq->total_length >= length); + + if (l > bq->blocks->chunk.length) + l = bq->blocks->chunk.length; + + bq->blocks->chunk.index += l; + bq->blocks->chunk.length -= l; + bq->total_length -= l; + + if (bq->blocks->chunk.length == 0) { + struct memblock_list *q; + + q = bq->blocks; + bq->blocks = bq->blocks->next; + memblock_unref(q->chunk.memblock); + free(q); + + bq->n_blocks--; + } + + length -= l; + } +} + +void memblockq_shorten(struct memblockq *bq, size_t length) { + size_t l; + assert(bq); + + if (bq->total_length <= length) + return; + + l = bq->total_length - length; + l /= bq->base; + l *= bq->base; + + memblockq_drop(bq, l); +} + + +void memblockq_empty(struct memblockq *bq) { + assert(bq); + memblockq_shorten(bq, 0); +} + +int memblockq_is_empty(struct memblockq *bq) { + assert(bq); + + return bq->total_length >= bq->base; +} diff --git a/src/memblockq.h b/src/memblockq.h new file mode 100644 index 000000000..75c5e59ee --- /dev/null +++ b/src/memblockq.h @@ -0,0 +1,24 @@ +#ifndef foomemblockqhfoo +#define foomemblockqhfoo + +#include + +#include "memblock.h" + +struct memblockq; + +struct memblockq* memblockq_new(size_t maxlength, size_t base); +void memblockq_free(struct memblockq* bq); + +void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta); + +int memblockq_pop(struct memblockq* bq, struct memchunk *chunk); +int memblockq_peek(struct memblockq* bq, struct memchunk *chunk); +void memblockq_drop(struct memblockq *bq, size_t length); + +void memblockq_shorten(struct memblockq *bq, size_t length); +void memblockq_empty(struct memblockq *bq); + +int memblockq_is_empty(struct memblockq *bq); + +#endif diff --git a/src/module.c b/src/module.c new file mode 100644 index 000000000..bcd0b6c04 --- /dev/null +++ b/src/module.c @@ -0,0 +1,98 @@ +#include +#include + +#include "module.h" + +struct module* module_load(struct core *c, const char *name, const char *argument) { + struct module *m = NULL; + + assert(c && name); + + m = malloc(sizeof(struct module)); + assert(m); + + if (!(m->dl = lt_dlopenext(name))) + goto fail; + + if (!(m->init = lt_dlsym(m->dl, "module_init"))) + goto fail; + + if (!(m->done = lt_dlsym(m->dl, "module_done"))) + goto fail; + + m->name = strdup(name); + m->argument = argument ? strdup(argument) : NULL; + m->userdata = NULL; + + assert(m->init); + if (m->init(c, m) < 0) + goto fail; + + if (!c->modules) + c->modules = idxset_new(NULL, NULL); + + assert(c->modules); + r = idxset_put(c->modules, m, &m->index); + assert(r >= 0 && m->index != IDXSET_INVALID); + return m; + +fail: + if (m) { + if (m->dl) + lt_dlclose(m->dl); + + free(m); + } + + return NULL; +} + +static void module_free(struct module *m) { + assert(m && m->done); + m->done(c, m); + + lt_dlcose(m->dl); + free(m->name); + free(m->argument); + free(m); +} + +void module_unload(struct core *c, struct module *m) { + struct module *m; + assert(c && index != IDXSET_INVALID); + + assert(c->modules); + if (!(m = idxset_remove_by_data(c->modules, m, NULL))) + return; + + module_free(m); +} + +void module_unload_by_index(struct core *c, guint32_t index) { + struct module *m; + assert(c && index != IDXSET_INVALID); + + assert(c->modules); + if (!(m = idxset_remove_by_index(c->modules, index))) + return; + + module_free(m); +} + + +void free_callback(void *p, void *userdata) { + struct module *m = p; + assert(m); + module_free(m); +} + +void module_unload_all(struct core *c) { + assert(c); + + if (!c->modules) + return; + + idxset_free(c->modules, free_callback, NULL); + c->modules = NULL; +} + diff --git a/src/module.h b/src/module.h new file mode 100644 index 000000000..d0dfa0454 --- /dev/null +++ b/src/module.h @@ -0,0 +1,27 @@ +#ifndef foomodulehfoo +#define foomodulehfoo + +#include +#include + +#include "core.h" + +struct module { + char *name, *argument; + uint32_t index; + + lt_dlhandle *dl; + + int (*init)(struct core *c, struct module*m); + void (*done)(struct core *c, struct module*m); + + void *userdata; +}; + +struct module* module_load(struct core *c, const char *name, const char*argument); +void module_unload(struct core *c, struct module *m); +void module_unload_by_index(struct core *c, uint32_t index); + +void module_unload_all(struct core *c); + +#endif diff --git a/src/oss.c b/src/oss.c new file mode 100644 index 000000000..42e60360b --- /dev/null +++ b/src/oss.c @@ -0,0 +1,30 @@ +#include "module.h" + +struct userdata { + struct sink *sink; + struct source *source; + int fd; +}; + +int module_init(struct core *c, struct module*m) { + struct userdata *u; + assert(c && m); + + u = malloc(sizeof(struct userdata)); + assert(u); + memset(u, 0, sizeof(struct userdata)); + m->userdata = u; + + return 0; +} + +void module_done(struct core *c, struct module*m) { + struct userdata *u; + assert(c && m); + + u = m->userdata; + + sink_free(u->sink); + source_free(u->source); + free(u); +} diff --git a/src/outputstream.c b/src/outputstream.c new file mode 100644 index 000000000..ffec77da9 --- /dev/null +++ b/src/outputstream.c @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "outputstream.h" + +struct output_stream* output_stream_new(struct source *s, struct sample_spec *spec, const char *name) { + struct output_stream *o; + int r; + assert(s && spec); + + o = malloc(sizeof(struct output_stream)); + assert(o); + o->name = name ? strdup(name) : NULL; + o->source = s; + o->spec = *spec; + + o->memblockq = memblockq_new(bytes_per_second(spec)*5, sample_size(spec)); + assert(o->memblockq); + + assert(s->core); + r = idxset_put(s->core->output_streams, o, &o->index); + assert(r == 0 && o->index != IDXSET_INVALID); + r = idxset_put(s->output_streams, o, NULL); + assert(r == 0); + + return o; +} + +void output_stream_free(struct output_stream* o) { + assert(o); + + memblockq_free(o->memblockq); + + assert(o->source && o->source->core); + idxset_remove_by_data(o->source->core->output_streams, o, NULL); + idxset_remove_by_data(o->source->output_streams, o, NULL); + + free(o->name); + free(o); +} diff --git a/src/outputstream.h b/src/outputstream.h new file mode 100644 index 000000000..410543410 --- /dev/null +++ b/src/outputstream.h @@ -0,0 +1,22 @@ +#ifndef foooutputstreamhfoo +#define foooutputstreamhfoo + +#include +#include "source.h" +#include "sample.h" +#include "memblockq.h" + +struct output_stream { + char *name; + uint32_t index; + + struct source *source; + struct sample_spec spec; + + struct memblockq *memblockq; +}; + +struct output_stream* output_stream_new(struct source *s, struct sample_spec *spec, const char *name); +void output_stream_free(struct output_stream* o); + +#endif diff --git a/src/packet.c b/src/packet.c new file mode 100644 index 000000000..086e4b2a8 --- /dev/null +++ b/src/packet.c @@ -0,0 +1,29 @@ +#include +#include + +#include "packet.h" + +struct packet* packet_new(uint32_t length) { + struct packet *p; + assert(length); + p = malloc(sizeof(struct packet)+length); + assert(p); + + p->ref = 1; + p->length = length; + return p; +} + +struct packet* packet_ref(struct packet *p) { + assert(p && p->ref >= 1); + p->ref++; + return p; +} + +void packet_unref(struct packet *p) { + assert(p && p->ref >= 1); + p->ref--; + + if (p->ref == 0) + free(p); +} diff --git a/src/packet.h b/src/packet.h new file mode 100644 index 000000000..781c0e66a --- /dev/null +++ b/src/packet.h @@ -0,0 +1,18 @@ +#ifndef foopackethfoo +#define foopackethfoo + +#include +#include + +struct packet { + unsigned ref; + size_t length; + uint8_t data[]; +}; + +struct packet* packet_new(uint32_t length); + +struct packet* packet_ref(struct packet *p); +void packet_unref(struct packet *p); + +#endif diff --git a/src/protocol-native-tcp.c b/src/protocol-native-tcp.c new file mode 100644 index 000000000..b33f3e15b --- /dev/null +++ b/src/protocol-native-tcp.c @@ -0,0 +1,19 @@ +#include "module.h" + +int module_init(struct core *c, struct module*m) { + struct socket_server *s; + assert(c && m); + + if (!(s = socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, 4711))) + return -1; + + m->userdata = protocol_native_new(s); + assert(m->userdata); + return 0; +} + +void module_done(struct core *c, struct module*m) { + assert(c && m); + + protocol_native_free(m->userdata); +} diff --git a/src/protocol-native-unix.c b/src/protocol-native-unix.c new file mode 100644 index 000000000..a18965cdd --- /dev/null +++ b/src/protocol-native-unix.c @@ -0,0 +1,27 @@ +#include "module.h" + +int module_init(struct core *c, struct module*m) { + struct fn[PATH_MAX]; + struct socket_server *s; + char *t; + assert(c && m); + + if (!(t = getenv("TMP"))) + if (!(t = getenv("TEMP"))) + t = "/tmp"; + + snprintf(fn, sizeof(fn), "%s/foosock", t); + + if (!(s = socket_server_new_unix(c->mainloop, fn))) + return -1; + + m->userdata = protocol_native_new(s); + assert(m->userdata); + return 0; +} + +void module_done(struct core *c, struct module*m) { + assert(c && m); + + protocol_native_free(m->userdata); +} diff --git a/src/protocol-native.c b/src/protocol-native.c new file mode 100644 index 000000000..bdb693558 --- /dev/null +++ b/src/protocol-native.c @@ -0,0 +1,49 @@ +#include "protocol-native.h" + +struct protocol_native { + struct socket_server*server; + struct idxset *connection; +}; + +struct stream_info { + guint32_t tag; + + union { + struct output_stream *output_stream; + struct input_stream *input_stream; + } +}; + +struct connection { + struct client *client; + struct serializer *serializer; + + +}; + +static void on_connection(struct socket_server *server, struct iochannel *io, void *userdata) { + struct protocol_native *p = userdata; + assert(server && io && p && p->server == server); + + +} + +struct protocol_native* protocol_native(struct socket_server *server) { + struct protocol_native *p; + assert(server); + + p = malloc(sizeof(struct protocol_native)); + assert(p); + + p->server = server; + socket_server_set_callback(p->server, callback, p); + + return p; +} + +void protocol_native_free(struct protocol_native *p) { + assert(p); + + socket_server_free(p->server); + free(p); +} diff --git a/src/protocol-native.h b/src/protocol-native.h new file mode 100644 index 000000000..bdad03b45 --- /dev/null +++ b/src/protocol-native.h @@ -0,0 +1,9 @@ +#ifndef fooprotocolnativehfoo +#define fooprotocolnativehfoo + +struct protocol_native; + +struct protocol_native* protocol_native(struct socket_server *server); +void protocol_native_free(struct protocol_native *n); + +#endif diff --git a/src/protocol-simple-tcp.c b/src/protocol-simple-tcp.c new file mode 100644 index 000000000..e71d71420 --- /dev/null +++ b/src/protocol-simple-tcp.c @@ -0,0 +1,24 @@ +#include +#include + +#include "module.h" +#include "socket-server.h" +#include "protocol-simple.h" + +int module_init(struct core *c, struct module*m) { + struct socket_server *s; + assert(c && m); + + if (!(s = socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, 4712))) + return -1; + + m->userdata = protocol_simple_new(c, s, PROTOCOL_SIMPLE_PLAYBACK); + assert(m->userdata); + return 0; +} + +void module_done(struct core *c, struct module*m) { + assert(c && m); + + protocol_simple_free(m->userdata); +} diff --git a/src/protocol-simple.c b/src/protocol-simple.c new file mode 100644 index 000000000..3335bc149 --- /dev/null +++ b/src/protocol-simple.c @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include + +#include "inputstream.h" +#include "outputstream.h" +#include "protocol-simple.h" +#include "client.h" + +struct connection { + struct protocol_simple *protocol; + struct iochannel *io; + struct input_stream *istream; + struct output_stream *ostream; + struct client *client; +}; + +struct protocol_simple { + struct core *core; + struct socket_server*server; + struct idxset *connections; + enum protocol_simple_mode mode; +}; + +#define BUFSIZE PIPE_BUF + +static void free_connection(void *data, void *userdata) { + struct connection *c = data; + assert(data); + + if (c->istream) + input_stream_free(c->istream); + if (c->ostream) + output_stream_free(c->ostream); + + client_free(c->client); + + iochannel_free(c->io); + free(c); +} + +static void io_callback(struct iochannel*io, void *userdata) { + struct connection *c = userdata; + assert(io && c); + + if (c->istream && iochannel_is_readable(io)) { + struct memchunk chunk; + ssize_t r; + + chunk.memblock = memblock_new(BUFSIZE); + assert(chunk.memblock); + + if ((r = iochannel_read(io, chunk.memblock->data, BUFSIZE)) <= 0) { + fprintf(stderr, "read(): %s\n", r == 0 ? "EOF" : strerror(errno)); + memblock_unref(chunk.memblock); + goto fail; + } + + chunk.memblock->length = r; + chunk.length = r; + chunk.index = 0; + + memblockq_push(c->istream->memblockq, &chunk, 0); + input_stream_notify(c->istream); + memblock_unref(chunk.memblock); + } + + if (c->ostream && iochannel_is_writable(io)) { + struct memchunk chunk; + ssize_t r; + + memblockq_peek(c->ostream->memblockq, &chunk); + assert(chunk.memblock && chunk.length); + + if ((r = iochannel_write(io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { + fprintf(stderr, "write(): %s\n", strerror(errno)); + memblock_unref(chunk.memblock); + goto fail; + } + + memblockq_drop(c->ostream->memblockq, r); + memblock_unref(chunk.memblock); + } + + return; + +fail: + idxset_remove_by_data(c->protocol->connections, c, NULL); + free_connection(c, NULL); +} + +static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { + struct protocol_simple *p = userdata; + struct connection *c = NULL; + assert(s && io && p); + + c = malloc(sizeof(struct connection)); + assert(c); + c->io = io; + c->istream = NULL; + c->ostream = NULL; + c->protocol = p; + + if (p->mode & PROTOCOL_SIMPLE_RECORD) { + struct source *source; + + if (!(source = core_get_default_source(p->core))) { + fprintf(stderr, "Failed to get default source.\n"); + goto fail; + } + + c->ostream = output_stream_new(source, &DEFAULT_SAMPLE_SPEC, c->client->name); + assert(c->ostream); + } + + if (p->mode & PROTOCOL_SIMPLE_PLAYBACK) { + struct sink *sink; + + if (!(sink = core_get_default_sink(p->core))) { + fprintf(stderr, "Failed to get default sink.\n"); + goto fail; + } + + c->istream = input_stream_new(sink, &DEFAULT_SAMPLE_SPEC, c->client->name); + assert(c->istream); + } + + c->client = client_new(p->core, "SIMPLE", "Client"); + assert(c->client); + + iochannel_set_callback(c->io, io_callback, c); + idxset_put(p->connections, c, NULL); + return; + +fail: + if (c) { + if (c->istream) + input_stream_free(c->istream); + if (c->ostream) + output_stream_free(c->ostream); + + iochannel_free(c->io); + free(c); + } +} + +struct protocol_simple* protocol_simple_new(struct core *core, struct socket_server *server, enum protocol_simple_mode mode) { + struct protocol_simple* p; + assert(core && server && mode <= PROTOCOL_SIMPLE_DUPLEX && mode > 0); + + p = malloc(sizeof(struct protocol_simple)); + assert(p); + p->core = core; + p->server = server; + p->connections = idxset_new(NULL, NULL); + p->mode = mode; + + socket_server_set_callback(p->server, on_connection, p); + + return p; +} + + +void protocol_simple_free(struct protocol_simple *p) { + assert(p); + + idxset_free(p->connections, free_connection, NULL); + socket_server_free(p->server); + free(p); +} diff --git a/src/protocol-simple.h b/src/protocol-simple.h new file mode 100644 index 000000000..f62104361 --- /dev/null +++ b/src/protocol-simple.h @@ -0,0 +1,17 @@ +#ifndef fooprotocolsimplehfoo +#define fooprotocolsimplehfoo + +#include "socket-server.h" + +struct protocol_simple; + +enum protocol_simple_mode { + PROTOCOL_SIMPLE_RECORD = 1, + PROTOCOL_SIMPLE_PLAYBACK = 2, + PROTOCOL_SIMPLE_DUPLEX = 3 +}; + +struct protocol_simple* protocol_simple_new(struct core *core, struct socket_server *server, enum protocol_simple_mode mode); +void protocol_simple_free(struct protocol_simple *n); + +#endif diff --git a/src/pstream.c b/src/pstream.c new file mode 100644 index 000000000..083ebc22c --- /dev/null +++ b/src/pstream.c @@ -0,0 +1,359 @@ +#include +#include + +#include "pstream.h" +#include "queue.h" + +enum pstream_descriptor_index { + PSTREAM_DESCRIPTOR_LENGTH, + PSTREAM_DESCRIPTOR_CHANNEL, + PSTREAM_DESCRIPTOR_DELTA, + PSTREAM_DESCRIPTOR_MAX +}; + +typedef uint32_t pstream_descriptor[PSTREAM_DESCRIPTOR_MAX]; + +#define PSTREAM_DESCRIPTOR_SIZE (PSTREAM_DESCRIPTOR_MAX*sizeof(uint32_t)) +#define FRAME_SIZE_MAX (1024*64) + +struct item_info { + enum { PSTREAM_ITEM_PACKET, PSTREAM_ITEM_MEMBLOCK } type; + + /* memblock info */ + struct memchunk chunk; + uint32_t channel; + int32_t delta; + + /* packet info */ + struct packet *packet; +}; + +struct pstream { + struct mainloop *mainloop; + struct mainloop_source *mainloop_source; + struct iochannel *io; + struct queue *send_queue; + + int dead; + + struct { + struct item_info* current; + pstream_descriptor descriptor; + void *data; + size_t index; + } write; + + void (*send_callback) (struct pstream *p, void *userdata); + void *send_callback_userdata; + + struct { + struct memblock *memblock; + struct packet *packet; + pstream_descriptor descriptor; + void *data; + size_t index; + } read; + + void (*recieve_packet_callback) (struct pstream *p, struct packet *packet, void *userdata); + void *recieve_packet_callback_userdata; + + void (*recieve_memblock_callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata); + void *recieve_memblock_callback_userdata; +}; + +static void do_write(struct pstream *p); +static void do_read(struct pstream *p); + +static void io_callback(struct iochannel*io, void *userdata) { + struct pstream *p = userdata; + assert(p && p->io == io); + do_write(p); + do_read(p); +} + +static void prepare_callback(struct mainloop_source *s, void*userdata) { + struct pstream *p = userdata; + assert(p && p->mainloop_source == s); + do_write(p); + do_read(p); +} + +struct pstream *pstream_new(struct mainloop *m, struct iochannel *io) { + struct pstream *p; + assert(io); + + p = malloc(sizeof(struct pstream)); + assert(p); + + p->io = io; + iochannel_set_callback(io, io_callback, p); + + p->dead = 0; + + p->mainloop = m; + p->mainloop_source = mainloop_source_new_prepare(m, prepare_callback, p); + mainloop_source_enable(p->mainloop_source, 0); + + p->send_queue = queue_new(); + assert(p->send_queue); + + p->write.current = NULL; + p->write.index = 0; + + p->read.memblock = NULL; + p->read.packet = NULL; + p->read.index = 0; + + p->send_callback = NULL; + p->send_callback_userdata = NULL; + + p->recieve_packet_callback = NULL; + p->recieve_packet_callback_userdata = NULL; + + p->recieve_memblock_callback = NULL; + p->recieve_memblock_callback_userdata = NULL; + + return p; +} + +static void item_free(void *item, void *p) { + struct item_info *i = item; + assert(i); + + if (i->type == PSTREAM_ITEM_PACKET) { + assert(i->chunk.memblock); + memblock_unref(i->chunk.memblock); + } else { + assert(i->type == PSTREAM_ITEM_MEMBLOCK); + assert(i->packet); + packet_unref(i->packet); + } + + free(i); +} + +void pstream_free(struct pstream *p) { + assert(p); + + iochannel_free(p->io); + queue_free(p->send_queue, item_free, NULL); + + if (p->write.current) + item_free(p->write.current, NULL); + + if (p->read.memblock) + memblock_unref(p->read.memblock); + + if (p->read.packet) + packet_unref(p->read.packet); + + mainloop_source_free(p->mainloop_source); + free(p); +} + +void pstream_set_send_callback(struct pstream*p, void (*callback) (struct pstream *p, void *userdata), void *userdata) { + assert(p && callback); + + p->send_callback = callback; + p->send_callback_userdata = userdata; +} + +void pstream_send_packet(struct pstream*p, struct packet *packet) { + struct item_info *i; + assert(p && packet); + + i = malloc(sizeof(struct item_info)); + assert(i); + i->type = PSTREAM_ITEM_PACKET; + i->packet = packet; + + queue_push(p->send_queue, i); + mainloop_source_enable(p->mainloop_source, 1); +} + +void pstream_send_memblock(struct pstream*p, uint32_t channel, int32_t delta, struct memchunk *chunk) { + struct item_info *i; + assert(p && channel && chunk); + + i = malloc(sizeof(struct item_info)); + assert(i); + i->type = PSTREAM_ITEM_MEMBLOCK; + i->chunk = *chunk; + i->channel = channel; + i->delta = delta; + + queue_push(p->send_queue, i); + mainloop_source_enable(p->mainloop_source, 1); +} + +void pstream_set_recieve_packet_callback(struct pstream *p, void (*callback) (struct pstream *p, struct packet *packet, void *userdata), void *userdata) { + assert(p && callback); + + p->recieve_packet_callback = callback; + p->recieve_packet_callback_userdata = userdata; +} + +void pstream_set_recieve_memblock_callback(struct pstream *p, void (*callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata), void *userdata) { + assert(p && callback); + + p->recieve_memblock_callback = callback; + p->recieve_memblock_callback_userdata = userdata; +} + +static void prepare_next_write_item(struct pstream *p) { + assert(p); + + if (!(p->write.current = queue_pop(p->send_queue))) + return; + + p->write.index = 0; + + if (p->write.current->type == PSTREAM_ITEM_PACKET) { + assert(p->write.current->packet); + p->write.data = p->write.current->packet->data; + p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] = p->write.current->packet->length; + p->write.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] = 0; + p->write.descriptor[PSTREAM_DESCRIPTOR_DELTA] = 0; + } else { + assert(p->write.current->type == PSTREAM_ITEM_MEMBLOCK && p->write.current->chunk.memblock); + p->write.data = p->write.current->chunk.memblock->data + p->write.current->chunk.index; + p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] = p->write.current->chunk.length; + p->write.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] = p->write.current->channel; + p->write.descriptor[PSTREAM_DESCRIPTOR_DELTA] = p->write.current->delta; + } +} + +static void do_write(struct pstream *p) { + void *d; + size_t l; + ssize_t r; + assert(p); + + mainloop_source_enable(p->mainloop_source, 0); + + if (p->dead || !iochannel_is_writable(p->io)) + return; + + if (!p->write.current) + prepare_next_write_item(p); + + if (!p->write.current) + return; + + assert(p->write.data); + + if (p->write.index < PSTREAM_DESCRIPTOR_SIZE) { + d = (void*) p->write.descriptor + p->write.index; + l = PSTREAM_DESCRIPTOR_SIZE - p->write.index; + } else { + d = (void*) p->write.data + p->write.index - PSTREAM_DESCRIPTOR_SIZE; + l = p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] - p->write.index - PSTREAM_DESCRIPTOR_SIZE; + } + + if ((r = iochannel_write(p->io, d, l)) < 0) { + p->dead = 1; + return; + } + + p->write.index += r; + + if (p->write.index >= PSTREAM_DESCRIPTOR_SIZE+p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) { + assert(p->write.current); + item_free(p->write.current, (void *) 1); + p->write.current = NULL; + + if (p->send_callback && queue_is_empty(p->send_queue)) + p->send_callback(p, p->send_callback_userdata); + } +} + +static void do_read(struct pstream *p) { + void *d; + size_t l; + ssize_t r; + assert(p); + + mainloop_source_enable(p->mainloop_source, 0); + + if (p->dead || !iochannel_is_readable(p->io)) + return; + + if (p->read.index < PSTREAM_DESCRIPTOR_SIZE) { + d = (void*) p->read.descriptor + p->read.index; + l = PSTREAM_DESCRIPTOR_SIZE - p->read.index; + } else { + assert(p->read.data); + d = (void*) p->read.data + p->read.index - PSTREAM_DESCRIPTOR_SIZE; + l = p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH] - p->read.index - PSTREAM_DESCRIPTOR_SIZE; + } + + if ((r = iochannel_read(p->io, d, l)) <= 0) { + p->dead = 1; + return; + } + + p->read.index += r; + + if (p->read.index == PSTREAM_DESCRIPTOR_SIZE) { + /* Reading of frame descriptor complete */ + + /* Frame size too large */ + if (p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH] > FRAME_SIZE_MAX) { + p->dead = 1; + return; + } + + assert(!p->read.packet && !p->read.memblock); + + if (p->read.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] == 0) { + /* Frame is a packet frame */ + p->read.packet = packet_new(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]); + assert(p->read.packet); + p->read.data = p->read.packet->data; + } else { + /* Frame is a memblock frame */ + p->read.memblock = memblock_new(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]); + assert(p->read.memblock); + p->read.data = p->read.memblock->data; + } + + } else if (p->read.index > PSTREAM_DESCRIPTOR_SIZE) { + /* Frame payload available */ + + if (p->read.memblock && p->recieve_memblock_callback) { /* Is this memblockd data? Than pass it to the user */ + size_t l; + + l = p->read.index - r < PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PSTREAM_DESCRIPTOR_SIZE : r; + + if (l > 0) { + struct memchunk chunk; + + chunk.memblock = p->read.memblock; + chunk.index = p->read.index - PSTREAM_DESCRIPTOR_SIZE - l; + chunk.length = l; + + p->recieve_memblock_callback(p, p->read.descriptor[PSTREAM_DESCRIPTOR_CHANNEL], (int32_t) p->read.descriptor[PSTREAM_DESCRIPTOR_DELTA], &chunk, p->recieve_memblock_callback_userdata); + } + } + + /* Frame complete */ + if (p->read.index >= p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH] + PSTREAM_DESCRIPTOR_SIZE) { + if (p->read.memblock) { + assert(!p->read.packet); + + memblock_unref(p->read.memblock); + p->read.memblock = NULL; + } else { + assert(p->read.packet); + + if (p->recieve_packet_callback) + p->recieve_packet_callback(p, p->read.packet, p->recieve_packet_callback_userdata); + + packet_unref(p->read.packet); + p->read.packet = NULL; + } + + p->read.index = 0; + } + } +} diff --git a/src/pstream.h b/src/pstream.h new file mode 100644 index 000000000..c0b574967 --- /dev/null +++ b/src/pstream.h @@ -0,0 +1,22 @@ +#ifndef foopstreamhfoo +#define foopstreamhfoo + +#include + +#include "packet.h" +#include "memblock.h" +#include "iochannel.h" + +struct pstream; + +struct pstream* pstream_new(struct mainloop *m, struct iochannel *io); +void pstream_free(struct pstream*p); + +void pstream_set_send_callback(struct pstream*p, void (*callback) (struct pstream *p, void *userdata), void *userdata); +void pstream_send_packet(struct pstream*p, struct packet *packet); +void pstream_send_memblock(struct pstream*p, uint32_t channel, int32_t delta, struct memchunk *chunk); + +void pstream_set_recieve_packet_callback(struct pstream *p, void (*callback) (struct pstream *p, struct packet *packet, void *userdata), void *userdata); +void pstream_set_recieve_memblock_callback(struct pstream *p, void (*callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata), void *userdata); + +#endif diff --git a/src/queue.c b/src/queue.c new file mode 100644 index 000000000..90823ae6f --- /dev/null +++ b/src/queue.c @@ -0,0 +1,77 @@ +#include +#include + +#include "queue.h" + +struct queue_entry { + struct queue_entry *next; + void *data; +}; + +struct queue { + struct queue_entry *front, *back; + unsigned length; +}; + +struct queue* queue_new(void) { + struct queue *q = malloc(sizeof(struct queue)); + assert(q); + q->front = q->back = NULL; + q->length = 0; + return q; +} + +void queue_free(struct queue* q, void (*destroy)(void *p, void *userdata), void *userdata) { + struct queue_entry *e; + assert(q); + + e = q->front; + while (e) { + struct queue_entry *n = e->next; + + if (destroy) + destroy(e->data, userdata); + + free(e); + e = n; + } + + free(q); +} + +void queue_push(struct queue *q, void *p) { + struct queue_entry *e; + + e = malloc(sizeof(struct queue_entry)); + + e->data = p; + e->next = NULL; + + if (q->back) + q->back->next = e; + else { + assert(!q->front); + q->front = e; + } + + q->back = e; + q->length++; +} + +void* queue_pop(struct queue *q) { + void *p; + struct queue_entry *e; + assert(q); + + if (!(e = q->front)) + return NULL; + + q->front = e->next; + if (q->back == e) + q->back = NULL; + + p = e->data; + free(e); + + return p; +} diff --git a/src/queue.h b/src/queue.h new file mode 100644 index 000000000..6b371a81c --- /dev/null +++ b/src/queue.h @@ -0,0 +1,13 @@ +#ifndef fooqueuehfoo +#define fooqueuehfoo + +struct queue; + +struct queue* queue_new(void); +void queue_free(struct queue* q, void (*destroy)(void *p, void *userdata), void *userdata); +void queue_push(struct queue *q, void *p); +void* queue_pop(struct queue *q); + +int queue_is_empty(struct queue *q); + +#endif diff --git a/src/sample.c b/src/sample.c new file mode 100644 index 000000000..74a54937b --- /dev/null +++ b/src/sample.c @@ -0,0 +1,80 @@ +#include +#include + +#include "sample.h" + +struct sample_spec default_sample_spec = { + .format = SAMPLE_S16NE, + .rate = 44100, + .channels = 2 +}; + +struct memblock *silence(struct memblock* b, struct sample_spec *spec) { + char c; + assert(b && spec); + memblock_assert_exclusive(b); + + switch (spec->format) { + case SAMPLE_U8: + c = 127; + break; + case SAMPLE_S16LE: + case SAMPLE_S16BE: + case SAMPLE_FLOAT32: + c = 0; + break; + case SAMPLE_ALAW: + case SAMPLE_ULAW: + c = 80; + break; + } + + memset(b->data, c, b->length); + return b; +} + +void add_clip(struct memchunk *target, struct memchunk *chunk, struct sample_spec *spec) { + int16_t *p, *d; + size_t i; + assert(target && target->memblock && chunk && chunk->memblock && spec); + assert(spec->format == SAMPLE_S16NE); + assert((target->length & 1) == 0); + + d = target->memblock->data + target->index; + p = chunk->memblock->data + chunk->index; + + for (i = 0; i < target->length && i < chunk->length; i++) { + int32_t r = (int32_t) *d + (int32_t) *p; + if (r < -0x8000) r = 0x8000; + if (r > 0x7FFF) r = 0x7FFF; + *d = (int16_t) r; + } +} + +size_t sample_size(struct sample_spec *spec) { + assert(spec); + size_t b; + + switch (spec->format) { + case SAMPLE_U8: + case SAMPLE_ULAW: + case SAMPLE_ALAW: + b = 1; + break; + case SAMPLE_S16LE: + case SAMPLE_S16BE: + b = 2; + break; + case SAMPLE_FLOAT32: + b = 4; + break; + } + + return b * spec->channels; +} + +size_t bytes_per_second(struct sample_spec *spec) { + assert(spec); + return spec->rate*sample_size(spec); +} + diff --git a/src/sample.h b/src/sample.h new file mode 100644 index 000000000..ecbe33f28 --- /dev/null +++ b/src/sample.h @@ -0,0 +1,35 @@ +#ifndef foosamplehfoo +#define foosamplehfoo + +#include + +#include "memblock.h" + +enum sample_format { + SAMPLE_U8, + SAMPLE_ALAW, + SAMPLE_ULAW, + SAMPLE_S16LE, + SAMPLE_S16BE, + SAMPLE_FLOAT32 +}; + +#define SAMPLE_S16NE SAMPLE_S16LE + +struct sample_spec { + enum sample_format format; + uint32_t rate; + uint32_t channels; +}; + +#define DEFAULT_SAMPLE_SPEC default_sample_spec + +extern struct sample_spec default_sample_spec; + +struct memblock *silence(struct memblock* b, struct sample_spec *spec); +void add_clip(struct memchunk *target, struct memchunk *chunk, struct sample_spec *spec); + +size_t bytes_per_second(struct sample_spec *spec); +size_t sample_size(struct sample_spec *spec); + +#endif diff --git a/src/sink-pipe.c b/src/sink-pipe.c new file mode 100644 index 000000000..4a8348f8c --- /dev/null +++ b/src/sink-pipe.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iochannel.h" +#include "sink.h" +#include "module.h" + +struct userdata { + struct sink *sink; + struct iochannel *io; + struct core *core; + struct mainloop_source *mainloop_source; + + struct memchunk memchunk; +}; + +static void do_write(struct userdata *u) { + ssize_t r; + assert(u); + + mainloop_source_enable(u->mainloop_source, 0); + + if (!iochannel_is_writable(u->io)) + return; + + if (!u->memchunk.length) + if (sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) + return; + + assert(u->memchunk.memblock && u->memchunk.length); + + if ((r = iochannel_write(u->io, u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { + fprintf(stderr, "write() failed: %s\n", strerror(errno)); + return; + } + + u->memchunk.index += r; + u->memchunk.length -= r; + + if (u->memchunk.length <= 0) { + memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; + } +} + +static void notify_callback(struct sink*s, void *userdata) { + struct userdata *u = userdata; + assert(u); + + if (iochannel_is_writable(u->io)) + mainloop_source_enable(u->mainloop_source, 1); +} + +static void prepare_callback(struct mainloop_source *src, void *userdata) { + struct userdata *u = userdata; + assert(u); + do_write(u); +} + +static void io_callback(struct iochannel *io, void*userdata) { + struct userdata *u = userdata; + assert(u); + do_write(u); +} + +int module_init(struct core *c, struct module*m) { + struct userdata *u = NULL; + struct stat st; + struct sink *sink; + char *p; + int fd = -1; + const static struct sample_spec ss = { + .format = SAMPLE_S16NE, + .rate = 44100, + .channels = 2, + }; + assert(c && m); + + mkfifo((p = m->argument ? m->argument : "/tmp/musicfifo"), 0777); + + if ((fd = open(p, O_RDWR) < 0)) { + fprintf(stderr, "open('%s'): %s\n", p, strerror(errno)); + goto fail; + } + + if (fstat(fd, &st) < 0) { + fprintf(stderr, "fstat('%s'): %s\n", p, strerror(errno)); + goto fail; + } + + if (!S_ISFIFO(st.st_mode)) { + fprintf(stderr, "'%s' is not a FIFO\n", p); + goto fail; + } + + if (!(sink = sink_new(c, "fifo", &ss))) { + fprintf(stderr, "Failed to allocate new sink!\n"); + goto fail; + } + + u = malloc(sizeof(struct userdata)); + assert(u); + + u->core = c; + u->sink = sink; + sink_set_notify_callback(sink, notify_callback, u); + + u->io = iochannel_new(c->mainloop, -1, fd); + assert(u->io); + iochannel_set_callback(u->io, io_callback, u); + + u->memchunk.memblock = NULL; + u->memchunk.length = 0; + + u->mainloop_source = mainloop_source_new_prepare(c->mainloop, prepare_callback, u); + assert(u->mainloop_source); + mainloop_source_enable(u->mainloop_source, 0); + + m->userdata = u; + + + return 0; + +fail: + if (fd >= 0) + close(fd); + + if (u) + free(u); + + return -1; +} + +void module_done(struct core *c, struct module*m) { + struct userdata *u; + assert(c && m); + + u = m->userdata; + assert(u); + + if (u->memchunk.memblock) + memblock_unref(u->memchunk.memblock); + + sink_free(u->sink); + iochannel_free(u->io); + mainloop_source_free(u->mainloop_source); + free(u); +} diff --git a/src/sink.c b/src/sink.c new file mode 100644 index 000000000..ac387c78c --- /dev/null +++ b/src/sink.c @@ -0,0 +1,217 @@ +#include +#include +#include +#include + +#include "sink.h" +#include "inputstream.h" + +struct sink* sink_new(struct core *core, const char *name, const struct sample_spec *spec) { + struct sink *s; + char *n = NULL; + int r; + assert(core && spec); + + s = malloc(sizeof(struct sink)); + assert(s); + + s->name = name ? strdup(name) : NULL; + r = idxset_put(core->sinks, s, &s->index); + assert(s->index != IDXSET_INVALID && r >= 0); + + s->core = core; + s->sample_spec = *spec; + s->input_streams = idxset_new(NULL, NULL); + + if (name) { + n = malloc(strlen(name)+9); + sprintf(n, "%s_monitor", name); + } + + s->monitor_source = source_new(core, n, spec); + s->volume = 0xFF; + + s->notify_callback = NULL; + s->userdata = NULL; + + return s; +} + +void sink_free(struct sink *s) { + struct input_stream *i; + assert(s); + + idxset_remove_by_data(s->core->sinks, s, NULL); + source_free(s->monitor_source); + + while ((i = idxset_rrobin(s->input_streams, NULL))) + input_stream_free(i); + + free(s->name); + free(s); +} + +struct pass1_info { + size_t maxlength; + unsigned count; + struct input_stream *last_input_stream; +}; + +static int get_max_length(void *p, uint32_t index, int *del, void*userdata) { + struct memchunk chunk; + struct pass1_info *info = userdata; + struct input_stream*i = p; + assert(info && i); + + if (memblockq_peek(i->memblockq, &chunk) != 0) + return 0; + + assert(chunk.length); + + if (info->maxlength > chunk.length) + info->maxlength = chunk.length; + + info->count++; + info->last_input_stream = i; + + return 0; +} + +struct pass2_info { + struct memchunk *chunk; + struct sample_spec *spec; +}; + +static int do_mix(void *p, uint32_t index, int *del, void*userdata) { + struct memchunk chunk; + struct pass2_info *info = userdata; + struct input_stream*i = p; + assert(info && info->chunk && info->chunk->memblock && i && info->spec); + + if (memblockq_peek(i->memblockq, &chunk) != 0) + return 0; + + memblock_assert_exclusive(info->chunk->memblock); + assert(chunk.length && chunk.length <= info->chunk->memblock->length - info->chunk->index); + + add_clip(info->chunk, &chunk, info->spec); + return 0; +} + +int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *result) { + struct pass1_info pass1_info; + struct pass2_info pass2_info; + assert(s && target && result); + memblock_assert_exclusive(target); + + /* Calculate how many bytes to mix */ + pass1_info.maxlength = target->length; + pass1_info.count = 0; + + idxset_foreach(s->input_streams, get_max_length, &pass1_info); + assert(pass1_info.maxlength); + + /* No data to mix */ + if (pass1_info.count == 0) + return -1; + + /* A shortcut if only a single input stream is connected */ + if (pass1_info.count == 1) { + struct input_stream *i = pass1_info.last_input_stream; + struct memchunk chunk; + size_t l; + + assert(i); + + if (memblockq_peek(i->memblockq, &chunk) != 0) + return -1; + + l = target->length < chunk.length ? target->length : chunk.length; + memcpy(target->data, result->memblock+result->index, l); + target->length = l; + memblock_unref(chunk.memblock); + memblockq_drop(i->memblockq, l); + + result->memblock = target; + result->length = l; + result->index = 0; + return 0; + } + + /* Do the real mixing */ + result->memblock = silence(target, &s->sample_spec); + result->index = 0; + result->length = pass1_info.maxlength; + pass2_info.chunk = result; + pass2_info.spec = &s->sample_spec; + idxset_foreach(s->input_streams, do_mix, &pass2_info); + + assert(s->monitor_source); + source_post(s->monitor_source, result); + + return 0; +} + +int sink_render(struct sink*s, size_t length, struct memchunk *result) { + struct pass1_info pass1_info; + struct pass2_info pass2_info; + assert(s && result); + + if (!length) + length = (size_t) -1; + + /* Calculate how many bytes to mix */ + pass1_info.maxlength = length; + pass1_info.count = 0; + + idxset_foreach(s->input_streams, get_max_length, &pass1_info); + assert(pass1_info.maxlength); + + /* No data to mix */ + if (pass1_info.count == 0) + return -1; + + if (pass1_info.count == 1) { + struct input_stream *i = pass1_info.last_input_stream; + size_t l; + + assert(i); + + if (memblockq_peek(i->memblockq, result) != 0) + return -1; + + l = length < result->length ? length : result->length; + result->length = l; + memblockq_drop(i->memblockq, l); + return 0; + } + + /* Do the mixing */ + result->memblock = silence(memblock_new(result->length), &s->sample_spec); + result->index = 0; + result->length = pass1_info.maxlength; + pass2_info.chunk = result; + pass2_info.spec = &s->sample_spec; + idxset_foreach(s->input_streams, do_mix, &pass2_info); + + assert(s->monitor_source); + + source_post(s->monitor_source, result); + return 0; +} + +void sink_notify(struct sink*s) { + assert(s); + + if (s->notify_callback) + s->notify_callback(s, s->userdata); +} + +void sink_set_notify_callback(struct sink *s, void (*notify_callback)(struct sink*sink, void *userdata), void *userdata) { + assert(s && notify_callback); + + s->notify_callback = notify_callback; + s->userdata = userdata; +} + + diff --git a/src/sink.h b/src/sink.h new file mode 100644 index 000000000..a6f98005a --- /dev/null +++ b/src/sink.h @@ -0,0 +1,38 @@ +#ifndef foosinkhfoo +#define foosinkhfoo + +struct sink; + +#include + +#include "core.h" +#include "sample.h" +#include "idxset.h" +#include "source.h" + +struct sink { + char *name; + uint32_t index; + + struct core *core; + struct sample_spec sample_spec; + struct idxset *input_streams; + + struct source *monitor_source; + + uint8_t volume; + + void (*notify_callback)(struct sink*sink, void *userdata); + void *userdata; +}; + +struct sink* sink_new(struct core *core, const char *name, const struct sample_spec *spec); +void sink_free(struct sink* s); + +int sink_render(struct sink*s, size_t length, struct memchunk *result); +int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *result); + +void sink_notify(struct sink*s); +void sink_set_notify_callback(struct sink *s, void (*notify_callback)(struct sink*sink, void *userdata), void *userdata); + +#endif diff --git a/src/socket-server.c b/src/socket-server.c new file mode 100644 index 000000000..2a1db9a03 --- /dev/null +++ b/src/socket-server.c @@ -0,0 +1,157 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socket-server.h" + +struct socket_server { + int fd; + char *filename; + + void (*on_connection)(struct socket_server*s, struct iochannel *io, void *userdata); + void *userdata; + + struct mainloop_source *mainloop_source; +}; + +static void callback(struct mainloop_source*src, int fd, enum mainloop_io_event event, void *userdata) { + struct socket_server *s = userdata; + struct iochannel *io; + int nfd; + assert(src && fd >= 0 && fd == s->fd && event == MAINLOOP_IO_EVENT_IN && s); + + if ((nfd = accept(fd, NULL, NULL)) < 0) { + fprintf(stderr, "accept(): %s\n", strerror(errno)); + return; + } + + if (!s->on_connection) { + close(nfd); + return; + } + + io = iochannel_new(mainloop_source_get_mainloop(src), nfd, nfd); + assert(io); + s->on_connection(s, io, s->userdata); +} + +struct socket_server* socket_server_new(struct mainloop *m, int fd) { + struct socket_server *s; + assert(m && fd >= 0); + + s = malloc(sizeof(struct socket_server)); + assert(s); + s->fd = fd; + s->filename = NULL; + s->on_connection = NULL; + s->userdata = NULL; + + s->mainloop_source = mainloop_source_new_io(m, fd, MAINLOOP_IO_EVENT_IN, callback, s); + assert(s->mainloop_source); + + return s; +} + +struct socket_server* socket_server_new_unix(struct mainloop *m, const char *filename) { + int fd = -1; + struct sockaddr_un sa; + struct socket_server *s; + + assert(m && filename); + + if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "socket(): %s\n", strerror(errno)); + goto fail; + } + + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); + sa.sun_path[sizeof(sa.sun_path) - 1] = 0; + + if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { + fprintf(stderr, "bind(): %s\n", strerror(errno)); + goto fail; + } + + if (listen(fd, 5) < 0) { + fprintf(stderr, "listen(): %s\n", strerror(errno)); + goto fail; + } + + s = socket_server_new(m, fd); + assert(s); + + s->filename = strdup(filename); + assert(s->filename); + + return s; + +fail: + if (fd >= 0) + close(fd); + + return NULL; +} + +struct socket_server* socket_server_new_ipv4(struct mainloop *m, uint32_t address, uint16_t port) { + int fd = -1; + struct sockaddr_in sa; + + assert(m && port); + + if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "socket(): %s\n", strerror(errno)); + goto fail; + } + + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + sa.sin_addr.s_addr = htonl(address); + + if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { + fprintf(stderr, "bind(): %s\n", strerror(errno)); + goto fail; + } + + if (listen(fd, 5) < 0) { + fprintf(stderr, "listen(): %s\n", strerror(errno)); + goto fail; + } + + return socket_server_new(m, fd); + +fail: + if (fd >= 0) + close(fd); + + return NULL; +} + +void socket_server_free(struct socket_server*s) { + assert(s); + close(s->fd); + + if (s->filename) { + unlink(s->filename); + free(s->filename); + } + + mainloop_source_free(s->mainloop_source); + + free(s); +} + +void socket_server_set_callback(struct socket_server*s, void (*on_connection)(struct socket_server*s, struct iochannel *io, void *userdata), void *userdata) { + assert(s); + + s->on_connection = on_connection; + s->userdata = userdata; +} diff --git a/src/socket-server.h b/src/socket-server.h new file mode 100644 index 000000000..4814fc626 --- /dev/null +++ b/src/socket-server.h @@ -0,0 +1,18 @@ +#ifndef foosocketserverhfoo +#define foosocketserverhfoo + +#include +#include "mainloop.h" +#include "iochannel.h" + +struct socket_server; + +struct socket_server* socket_server_new(struct mainloop *m, int fd); +struct socket_server* socket_server_new_unix(struct mainloop *m, const char *filename); +struct socket_server* socket_server_new_ipv4(struct mainloop *m, uint32_t address, uint16_t port); + +void socket_server_free(struct socket_server*s); + +void socket_server_set_callback(struct socket_server*s, void (*on_connection)(struct socket_server*s, struct iochannel *io, void *userdata), void *userdata); + +#endif diff --git a/src/source.c b/src/source.c new file mode 100644 index 000000000..2f34c461e --- /dev/null +++ b/src/source.c @@ -0,0 +1,58 @@ +#include +#include +#include + +#include "source.h" +#include "outputstream.h" + +struct source* source_new(struct core *core, const char *name, const struct sample_spec *spec) { + struct source *s; + int r; + assert(core && spec); + + s = malloc(sizeof(struct source)); + assert(s); + + s->name = name ? strdup(name) : NULL; + r = idxset_put(core->sources, s, &s->index); + assert(s->index != IDXSET_INVALID && r >= 0); + + s->core = core; + s->sample_spec = *spec; + s->output_streams = idxset_new(NULL, NULL); + + s->link_change_callback = NULL; + s->userdata = NULL; + + return s; +} + +static void do_free(void *p, void *userdata) { + struct output_stream *o = p; + assert(o); + output_stream_free(o); +}; + +void source_free(struct source *s) { + assert(s); + + idxset_remove_by_data(s->core->sources, s, NULL); + idxset_free(s->output_streams, do_free, NULL); + free(s->name); + free(s); +} + +static int do_post(void *p, uint32_t index, int *del, void*userdata) { + struct memchunk *chunk = userdata; + struct output_stream *o = p; + assert(o && o->memblockq && index && del && chunk); + + memblockq_push(o->memblockq, chunk, 0); + return 0; +} + +void source_post(struct source*s, struct memchunk *chunk) { + assert(s && chunk); + + idxset_foreach(s->output_streams, do_post, chunk); +} diff --git a/src/source.h b/src/source.h new file mode 100644 index 000000000..3beb3f963 --- /dev/null +++ b/src/source.h @@ -0,0 +1,30 @@ +#ifndef foosourcehfoo +#define foosourcehfoo + +struct source; + +#include +#include "core.h" +#include "sample.h" +#include "idxset.h" +#include "memblock.h" + +struct source { + char *name; + uint32_t index; + + struct core *core; + struct sample_spec sample_spec; + struct idxset *output_streams; + + void (*link_change_callback)(struct source*source, void *userdata); + void *userdata; +}; + +struct source* source_new(struct core *core, const char *name, const struct sample_spec *spec); +void source_free(struct source *s); + +/* Pass a new memory block to all output streams */ +void source_post(struct source*s, struct memchunk *b); + +#endif diff --git a/src/strbuf.c b/src/strbuf.c new file mode 100644 index 000000000..7c8b965de --- /dev/null +++ b/src/strbuf.c @@ -0,0 +1,122 @@ +#ifndef foostrbufhfoo +#define foostrbufhfoo + +#include +#include +#include +#include +#include +#include + +struct chunk { + struct chunk *next; + char text[]; +}; + +struct strbuf { + size_t length; + struct chunk *head, *tail; +}; + +struct strbuf *strbuf_new(void) { + struct strbuf *sb = malloc(sizeof(struct strbuf)); + assert(sb); + sb->length = 0; + sb->head = sb->tail = NULL; + return sb; +} + +void strbuf_free(struct strbuf *sb) { + assert(sb); + while (sb->head) { + struct chunk *c = sb->head; + sb->head = sb->head->next; + free(c); + } + + free(sb); +} + +char *strbuf_tostring(struct strbuf *sb) { + char *t, *e; + struct chunk *c; + assert(sb); + + t = malloc(sb->length+1); + assert(t); + + e = t; + *e = 0; + for (c = sb->head; c; c = c->next) { + strcpy(e, c->text); + e = strchr(e, 0); + } + + return t; +} + +void strbuf_puts(struct strbuf *sb, const char *t) { + struct chunk *c; + size_t l; + assert(sb && t); + + l = strlen(t); + c = malloc(sizeof(struct chunk)+l); + assert(c); + + c->next = NULL; + strcpy(c->text, t); + + if (sb->tail) { + assert(sb->head); + sb->tail->next = c; + } else { + assert(!sb->head); + sb->head = c; + } + + sb->tail = c; + sb->length += l; +} + +int strbuf_printf(struct strbuf *sb, const char *format, ...) { + int r, size = 100; + struct chunk *c = NULL; + + assert(sb); + + for(;;) { + va_list ap; + + c = realloc(c, sizeof(struct chunk)+size); + assert(c); + + va_start(ap, format); + r = vsnprintf(c->text, size, format, ap); + va_end(ap); + + if (r > -1 && r < size) { + c->next = NULL; + + if (sb->tail) { + assert(sb->head); + sb->tail->next = c; + } else { + assert(!sb->head); + sb->head = c; + } + + sb->tail = c; + sb->length += r; + + return r; + } + + if (r > -1) /* glibc 2.1 */ + size = r+1; + else /* glibc 2.0 */ + size *= 2; + } +} + +#endif diff --git a/src/strbuf.h b/src/strbuf.h new file mode 100644 index 000000000..6ad582a31 --- /dev/null +++ b/src/strbuf.h @@ -0,0 +1,13 @@ +#ifndef foostrbufhfoo +#define foostrbufhfoo + +struct strbuf; + +struct strbuf *strbuf_new(void); +void strbuf_free(struct strbuf *sb); +char *strbuf_tostring(struct strbuf *sb); + +int strbuf_printf(struct strbuf *sb, const char *format, ...); +void strbuf_puts(struct strbuf *sb, const char *t); + +#endif From a5daff7859c3a8904cb379c59f3cefbaae4f57f2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 10 Jun 2004 23:22:16 +0000 Subject: [PATCH 0003/1514] make it compile git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@4 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/module.c | 15 +++++++++------ src/module.h | 3 ++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/module.c b/src/module.c index bcd0b6c04..94a431243 100644 --- a/src/module.c +++ b/src/module.c @@ -1,10 +1,12 @@ #include #include +#include #include "module.h" struct module* module_load(struct core *c, const char *name, const char *argument) { struct module *m = NULL; + int r; assert(c && name); @@ -23,6 +25,7 @@ struct module* module_load(struct core *c, const char *name, const char *argumen m->name = strdup(name); m->argument = argument ? strdup(argument) : NULL; m->userdata = NULL; + m->core = c; assert(m->init); if (m->init(c, m) < 0) @@ -30,6 +33,7 @@ struct module* module_load(struct core *c, const char *name, const char *argumen if (!c->modules) c->modules = idxset_new(NULL, NULL); + assert(c->modules); r = idxset_put(c->modules, m, &m->index); @@ -48,18 +52,17 @@ fail: } static void module_free(struct module *m) { - assert(m && m->done); - m->done(c, m); + assert(m && m->done && m->core); + m->done(m->core, m); - lt_dlcose(m->dl); + lt_dlclose(m->dl); free(m->name); free(m->argument); free(m); } void module_unload(struct core *c, struct module *m) { - struct module *m; - assert(c && index != IDXSET_INVALID); + assert(c && m); assert(c->modules); if (!(m = idxset_remove_by_data(c->modules, m, NULL))) @@ -68,7 +71,7 @@ void module_unload(struct core *c, struct module *m) { module_free(m); } -void module_unload_by_index(struct core *c, guint32_t index) { +void module_unload_by_index(struct core *c, uint32_t index) { struct module *m; assert(c && index != IDXSET_INVALID); diff --git a/src/module.h b/src/module.h index d0dfa0454..4ecef86e8 100644 --- a/src/module.h +++ b/src/module.h @@ -7,10 +7,11 @@ #include "core.h" struct module { + struct core *core; char *name, *argument; uint32_t index; - lt_dlhandle *dl; + lt_dlhandle dl; int (*init)(struct core *c, struct module*m); void (*done)(struct core *c, struct module*m); From 9e3ad2380a28a7473a1dfa9ae41697ebacfd85cc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Jun 2004 00:33:43 +0000 Subject: [PATCH 0004/1514] autoconf git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@5 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 23 +++++++++++++++++++++ bootstrap.sh | 39 +++++++++++++++++++++++++++++++++++ configure.ac | 49 +++++++++++++++++++++++++++++++++++++++++++ src/Makefile | 10 --------- src/Makefile.am | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 7 +++++++ src/sample.c | 4 ++-- 7 files changed, 175 insertions(+), 12 deletions(-) create mode 100644 Makefile.am create mode 100755 bootstrap.sh create mode 100644 configure.ac delete mode 100644 src/Makefile create mode 100644 src/Makefile.am diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 000000000..7266cba57 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,23 @@ +# $Id$ +# +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +EXTRA_DIST = bootstrap.sh +SUBDIRS=src + +distcleancheck: + @: diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 000000000..f26ceb15d --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# $Id$ + +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +if [ "x$1" = "xam" ] ; then + set -ex + automake -a -c --foreign + ./config.status +else + set -ex + + rm -rf autom4te.cache + rm -f config.cache + + aclocal + libtoolize -c --force + autoheader + automake -a -c + autoconf -Wall + + ./configure --sysconfdir=/etc "$@" + + make clean +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..de1a94ff7 --- /dev/null +++ b/configure.ac @@ -0,0 +1,49 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +# $Id$ + +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +AC_PREREQ(2.57) +AC_INIT([polypaudio],[0.0],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_CONFIG_SRCDIR([src/main.c]) +AC_CONFIG_HEADERS([config.h]) +AM_INIT_AUTOMAKE([foreign -Wall]) + +AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) + +if type -p stow > /dev/null && test -d /usr/local/stow ; then + AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) + ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}" +fi + +# Checks for programs. +AC_PROG_CC +AC_LIBLTDL_INSTALLABLE +AC_SUBST(INCLTDL) +AC_SUBST(LIBLTDL) +AC_LIBTOOL_DLOPEN +AC_PROG_LIBTOOL + +# If using GCC specifiy some additional parameters +if test "x$GCC" = "xyes" ; then + CFLAGS="$CFLAGS -pipe -Wall" +fi + +AC_CONFIG_FILES([Makefile src/Makefile]) +AC_OUTPUT diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 366e84e6a..000000000 --- a/src/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -CFLAGS=-Wall -pipe -ansi -D_GNU_SOURCE - -all: idxset.o queue.o strbuf.o mainloop.o iochannel.o packet.o \ - memblock.o sample.o socket-server.o memblockq.o client.o \ - core.o main.o outputstream.o inputstream.o source.o sink.o \ - pstream.o protocol-simple.o protocol-simple-tcp.o sink-pipe.o \ - module.o - -clean: - rm -f *.o diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 000000000..c64babb39 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,55 @@ +# $Id: Makefile.am 27 2003-10-22 22:34:06Z lennart $ +# +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +AM_CFLAGS=-ansi -D_GNU_SOURCE + +bin_PROGRAMS = polypaudio + +pkglib_LTLIBRARIES=protocol-simple.la protocol-simple-tcp.la \ + socket-server.la sink-pipe.la pstream.la iochannel.la packet.la + +polypaudio_SOURCES = idxset.c queue.c strbuf.c mainloop.c \ + memblock.c sample.c memblockq.c client.c \ + core.c main.c outputstream.c inputstream.c source.c sink.c \ + module.c +polypaudio_INCLUDES = $(INCLTDL) +polypaudio_LDADD = $(LIBLTDL) +polypaudio_LDFLAGS=-export-dynamic + +protocol_simple_la_SOURCES = protocol-simple.c +protocol_simple_la_LDFLAGS = -module -avoid-version + +protocol_simple_tcp_la_SOURCES = protocol-simple-tcp.c +protocol_simple_tcp_la_LDFLAGS = -module -avoid-version +protocol_simple_tcp_la_LIBADD = protocol-simple.la socket-server.la + +socket_server_la_SOURCES = socket-server.c +socket_server_la_LDFLAGS = -module -avoid-version + +sink_pipe_la_SOURCES = sink-pipe.c +sink_pipe_la_LDFLAGS = -module -avoid-version + +pstream_la_SOURCES = pstream.c +pstream_la_LDFLAGS = -module -avoid-version + +iochannel_la_SOURCES = pstream.c +iochannel_la_LDFLAGS = -module -avoid-version + +packet_la_SOURCES = pstream.c +packet_la_LDFLAGS = -module -avoid-version + diff --git a/src/main.c b/src/main.c index 3104c2649..0785b39c6 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ #include #include +#include #include "core.h" #include "mainloop.h" @@ -8,7 +9,11 @@ int main(int argc, char *argv[]) { struct mainloop *m; struct core *c; + int r; + r = lt_dlinit(); + assert(r == 0); + m = mainloop_new(); assert(m); c = core_new(m); @@ -21,6 +26,8 @@ int main(int argc, char *argv[]) { core_free(c); mainloop_free(m); + + lt_dlexit(); return 0; } diff --git a/src/sample.c b/src/sample.c index 74a54937b..2e46eac76 100644 --- a/src/sample.c +++ b/src/sample.c @@ -10,7 +10,7 @@ struct sample_spec default_sample_spec = { }; struct memblock *silence(struct memblock* b, struct sample_spec *spec) { - char c; + char c = 0; assert(b && spec); memblock_assert_exclusive(b); @@ -53,7 +53,7 @@ void add_clip(struct memchunk *target, struct memchunk *chunk, struct sample_spe size_t sample_size(struct sample_spec *spec) { assert(spec); - size_t b; + size_t b = 1; switch (spec->format) { case SAMPLE_U8: From 8584356bbcd0690e3094ad256646838b8b41a103 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Jun 2004 12:01:41 +0000 Subject: [PATCH 0005/1514] ignore fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@6 fefdeb5f-60dc-0310-8127-8f9354f1896f From aae40dcea260296d7d02d185b42f9275f34cb238 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Jun 2004 17:18:40 +0000 Subject: [PATCH 0006/1514] module dependencie foo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@7 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/module.c | 70 +++++++++++++++++++++++++++++++++- src/module.h | 7 ++++ src/protocol-simple-tcp.moddep | 2 + src/protocol-simple.moddep | 1 + src/sink-pipe.moddep | 1 + src/socket-server.moddep | 1 + 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/protocol-simple-tcp.moddep create mode 100644 src/protocol-simple.moddep create mode 100644 src/sink-pipe.moddep create mode 100644 src/socket-server.moddep diff --git a/src/module.c b/src/module.c index 94a431243..4aa9fd681 100644 --- a/src/module.c +++ b/src/module.c @@ -1,9 +1,68 @@ +#include +#include #include #include #include #include "module.h" + +static void free_deps(struct dependency_module** deps) { + assert(deps); + + while (*deps) { + struct dependency_module *next = (*deps)->next; + lt_dlclose((*deps)->dl); + free(deps); + *deps = next; + } +} + +static int load_deps(const char *fname, struct dependency_module **deps) { + char line[PATH_MAX]; + FILE *f; + char depfile[PATH_MAX]; + assert(fname && deps); + + snprintf(depfile, sizeof(depfile), "%s.moddep", fname); + + if (!(f = fopen(depfile, "r"))) + return -1; + + while (fgets(line, sizeof(line)-1, f)) { + lt_dlhandle dl; + char *p; + size_t l; + struct dependency_module* d; + + p = line + strspn(line, " \t"); + + l = strlen(p); + if (p[l-1] == '\n') + p[l-1] = 0; + + if (*p == '#' || *p == 0) + continue; + + load_deps(p, deps); + + if (!(dl = lt_dlopenext(p))) { + free_deps(deps); + fclose(f); + return -1; + } + + d = malloc(sizeof(struct dependency_module)); + assert(d); + d->dl = dl; + d->next = *deps; + *deps = d; + } + + fclose(f); + return 0; +} + struct module* module_load(struct core *c, const char *name, const char *argument) { struct module *m = NULL; int r; @@ -13,6 +72,12 @@ struct module* module_load(struct core *c, const char *name, const char *argumen m = malloc(sizeof(struct module)); assert(m); + m->dl = NULL; + + m->dependencies = NULL; + if (load_deps(name, &m->dependencies) < 0) + goto fail; + if (!(m->dl = lt_dlopenext(name))) goto fail; @@ -33,7 +98,6 @@ struct module* module_load(struct core *c, const char *name, const char *argumen if (!c->modules) c->modules = idxset_new(NULL, NULL); - assert(c->modules); r = idxset_put(c->modules, m, &m->index); @@ -45,6 +109,7 @@ fail: if (m->dl) lt_dlclose(m->dl); + free_deps(&m->dependencies); free(m); } @@ -56,11 +121,13 @@ static void module_free(struct module *m) { m->done(m->core, m); lt_dlclose(m->dl); + free_deps(&m->dependencies); free(m->name); free(m->argument); free(m); } + void module_unload(struct core *c, struct module *m) { assert(c && m); @@ -82,7 +149,6 @@ void module_unload_by_index(struct core *c, uint32_t index) { module_free(m); } - void free_callback(void *p, void *userdata) { struct module *m = p; assert(m); diff --git a/src/module.h b/src/module.h index 4ecef86e8..d16c25cda 100644 --- a/src/module.h +++ b/src/module.h @@ -6,12 +6,19 @@ #include "core.h" +struct dependency_module { + lt_dlhandle dl; + struct dependency_module *next; +}; + struct module { struct core *core; char *name, *argument; uint32_t index; lt_dlhandle dl; + struct dependency_module *dependencies; + int (*init)(struct core *c, struct module*m); void (*done)(struct core *c, struct module*m); diff --git a/src/protocol-simple-tcp.moddep b/src/protocol-simple-tcp.moddep new file mode 100644 index 000000000..88f964a0e --- /dev/null +++ b/src/protocol-simple-tcp.moddep @@ -0,0 +1,2 @@ +socket-server +protocol-simple diff --git a/src/protocol-simple.moddep b/src/protocol-simple.moddep new file mode 100644 index 000000000..c49501d8e --- /dev/null +++ b/src/protocol-simple.moddep @@ -0,0 +1 @@ +socket-server diff --git a/src/sink-pipe.moddep b/src/sink-pipe.moddep new file mode 100644 index 000000000..6958f9fc0 --- /dev/null +++ b/src/sink-pipe.moddep @@ -0,0 +1 @@ +iochannel diff --git a/src/socket-server.moddep b/src/socket-server.moddep new file mode 100644 index 000000000..6958f9fc0 --- /dev/null +++ b/src/socket-server.moddep @@ -0,0 +1 @@ +iochannel From 7dfeb1fc745757f1c2b7bf43bae80cf0f49fc9a6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Jun 2004 21:30:16 +0000 Subject: [PATCH 0007/1514] make the whole stuff run and clean it self up again git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@8 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 39 +++++++------- src/idxset.c | 8 +-- src/iochannel.c | 6 +++ src/main.c | 10 ++++ src/mainloop.c | 138 ++++++++++++++++++++++++++++++++++++++++++++---- src/mainloop.h | 4 +- src/module.c | 69 ++---------------------- src/module.h | 2 - src/sink-pipe.c | 2 +- src/sink.c | 9 ++-- src/source.c | 6 +++ 11 files changed, 189 insertions(+), 104 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index c64babb39..485513df9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,8 +20,8 @@ AM_CFLAGS=-ansi -D_GNU_SOURCE bin_PROGRAMS = polypaudio -pkglib_LTLIBRARIES=protocol-simple.la protocol-simple-tcp.la \ - socket-server.la sink-pipe.la pstream.la iochannel.la packet.la +pkglib_LTLIBRARIES=libprotocol-simple.la protocol-simple-tcp.la \ + libsocket-server.la sink-pipe.la libpstream.la libiochannel.la libpacket.la polypaudio_SOURCES = idxset.c queue.c strbuf.c mainloop.c \ memblock.c sample.c memblockq.c client.c \ @@ -31,25 +31,28 @@ polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(LIBLTDL) polypaudio_LDFLAGS=-export-dynamic -protocol_simple_la_SOURCES = protocol-simple.c -protocol_simple_la_LDFLAGS = -module -avoid-version +libprotocol_simple_la_SOURCES = protocol-simple.c +libprotocol_simple_la_LDFLAGS = -avoid-version +libprotocol_simple_la_LIBADD = libsocket-server.la libiochannel.la + +libsocket_server_la_SOURCES = socket-server.c +libsocket_server_la_LDFLAGS = -avoid-version +libsocket_server_la_LIBADD = libiochannel.la + +libpstream_la_SOURCES = pstream.c +libpstream_la_LDFLAGS = -avoid-version +libpstream_la_LIBADD = libpacket.la + +libiochannel_la_SOURCES = iochannel.c +libiochannel_la_LDFLAGS = -avoid-version + +libpacket_la_SOURCES = packet.c +libpacket_la_LDFLAGS = -avoid-version protocol_simple_tcp_la_SOURCES = protocol-simple-tcp.c protocol_simple_tcp_la_LDFLAGS = -module -avoid-version -protocol_simple_tcp_la_LIBADD = protocol-simple.la socket-server.la - -socket_server_la_SOURCES = socket-server.c -socket_server_la_LDFLAGS = -module -avoid-version +protocol_simple_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la sink_pipe_la_SOURCES = sink-pipe.c sink_pipe_la_LDFLAGS = -module -avoid-version - -pstream_la_SOURCES = pstream.c -pstream_la_LDFLAGS = -module -avoid-version - -iochannel_la_SOURCES = pstream.c -iochannel_la_LDFLAGS = -module -avoid-version - -packet_la_SOURCES = pstream.c -packet_la_LDFLAGS = -module -avoid-version - +sink_pipe_la_LIBADD = libiochannel.la diff --git a/src/idxset.c b/src/idxset.c index eaea34f46..f0d7ad879 100644 --- a/src/idxset.c +++ b/src/idxset.c @@ -27,7 +27,7 @@ static unsigned trivial_hash_func(void *p) { } static int trivial_compare_func(void *a, void *b) { - return !(a == b); + return a != b; } struct idxset* idxset_new(unsigned (*hash_func) (void *p), int (*compare_func) (void*a, void*b)) { @@ -40,11 +40,13 @@ struct idxset* idxset_new(unsigned (*hash_func) (void *p), int (*compare_func) ( s->hash_table_size = 1023; s->hash_table = malloc(sizeof(struct idxset_entry*)*s->hash_table_size); assert(s->hash_table); + memset(s->hash_table, 0, sizeof(struct idxset_entry*)*s->hash_table_size); s->array = NULL; s->array_size = 0; s->index = 0; s->start_index = 0; s->n_entries = 0; + s->rrobin = NULL; s->iterate_list_head = s->iterate_list_tail = NULL; @@ -75,7 +77,7 @@ static struct idxset_entry* hash_scan(struct idxset *s, struct idxset_entry* e, assert(s->compare_func); for (; e; e = e->hash_next) - if (s->compare_func(e->data, p)) + if (s->compare_func(e->data, p) == 0) return e; return NULL; @@ -278,7 +280,7 @@ void* idxset_remove_by_data(struct idxset*s, void *data, uint32_t *index) { } void* idxset_rrobin(struct idxset *s, uint32_t *index) { - assert(s && index); + assert(s); if (s->rrobin) s->rrobin = s->rrobin->iterate_next; diff --git a/src/iochannel.c b/src/iochannel.c index db9717a96..aa7de714e 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -156,3 +156,9 @@ ssize_t iochannel_read(struct iochannel*io, void*data, size_t l) { return r; } + +void iochannel_set_callback(struct iochannel*io, void (*callback)(struct iochannel*io, void *userdata), void *userdata) { + assert(io); + io->callback = callback; + io->userdata = userdata; +} diff --git a/src/main.c b/src/main.c index 0785b39c6..436dd30ba 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -6,6 +8,11 @@ #include "mainloop.h" #include "module.h" +static void signal_callback(struct mainloop_source *m, int sig, void *userdata) { + mainloop_quit(mainloop_source_get_mainloop(m), -1); + fprintf(stderr, "Got signal.\n"); +} + int main(int argc, char *argv[]) { struct mainloop *m; struct core *c; @@ -19,6 +26,9 @@ int main(int argc, char *argv[]) { c = core_new(m); assert(c); + mainloop_source_new_signal(m, SIGINT, signal_callback, NULL); + signal(SIGPIPE, SIG_IGN); + module_load(c, "sink-pipe", NULL); module_load(c, "protocol-simple-tcp", NULL); diff --git a/src/mainloop.c b/src/mainloop.c index d043ce90a..0f5811f2f 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -1,7 +1,11 @@ +#include +#include #include #include #include #include +#include +#include #include "mainloop.h" @@ -28,6 +32,12 @@ struct mainloop_source { struct { void (*callback)(struct mainloop_source*s, void *userdata); } idle; + + struct { + int sig; + struct sigaction sigaction; + void (*callback)(struct mainloop_source*s, int sig, void *userdata); + } signal; }; struct mainloop_source_list { @@ -37,7 +47,7 @@ struct mainloop_source_list { }; struct mainloop { - struct mainloop_source_list io_sources, prepare_sources, idle_sources; + struct mainloop_source_list io_sources, prepare_sources, idle_sources, signal_sources; struct pollfd *pollfds; int max_pollfds, n_pollfds; @@ -45,14 +55,43 @@ struct mainloop { int quit; int running; + int signal_pipe[2]; + struct pollfd signal_pollfd; }; +static int signal_pipe = -1; + +static void signal_func(int sig) { + if (signal_pipe >= 0) + write(signal_pipe, &sig, sizeof(sig)); +} + +static void make_nonblock(int fd) { + int v; + + if ((v = fcntl(fd, F_GETFL)) >= 0) + fcntl(fd, F_SETFL, v|O_NONBLOCK); +} + + struct mainloop *mainloop_new(void) { + int r; struct mainloop *m; m = malloc(sizeof(struct mainloop)); assert(m); memset(m, 0, sizeof(struct mainloop)); + + r = pipe(m->signal_pipe); + assert(r >= 0 && m->signal_pipe[0] >= 0 && m->signal_pipe[1] >= 0); + + make_nonblock(m->signal_pipe[0]); + make_nonblock(m->signal_pipe[1]); + + signal_pipe = m->signal_pipe[1]; + m->signal_pollfd.fd = m->signal_pipe[0]; + m->signal_pollfd.events = POLLIN; + m->signal_pollfd.revents = 0; return m; } @@ -61,7 +100,7 @@ static void free_sources(struct mainloop_source_list *l, int all) { struct mainloop_source *s, *p; assert(l); - if (!l->dead_sources) + if (!all && !l->dead_sources) return; p = NULL; @@ -86,7 +125,7 @@ static void free_sources(struct mainloop_source_list *l, int all) { l->dead_sources = 0; if (all) { - assert(l->sources); + assert(!l->sources); l->n_sources = 0; } } @@ -96,15 +135,23 @@ void mainloop_free(struct mainloop* m) { free_sources(&m->io_sources, 1); free_sources(&m->prepare_sources, 1); free_sources(&m->idle_sources, 1); + free_sources(&m->signal_sources, 1); + + if (signal_pipe == m->signal_pipe[1]) + signal_pipe = -1; + close(m->signal_pipe[0]); + close(m->signal_pipe[1]); + free(m->pollfds); + free(m); } static void rebuild_pollfds(struct mainloop *m) { struct mainloop_source*s; struct pollfd *p; - if (m->max_pollfds < m->io_sources.n_sources) { - m->max_pollfds = m->io_sources.n_sources*2; + if (m->max_pollfds < m->io_sources.n_sources+1) { + m->max_pollfds = (m->io_sources.n_sources+1)*2; m->pollfds = realloc(m->pollfds, sizeof(struct pollfd)*m->max_pollfds); } @@ -117,6 +164,9 @@ static void rebuild_pollfds(struct mainloop *m) { m->n_pollfds++; } } + + *(p++) = m->signal_pollfd; + m->n_pollfds++; } static void dispatch_pollfds(struct mainloop *m) { @@ -128,10 +178,42 @@ static void dispatch_pollfds(struct mainloop *m) { s = m->io_sources.sources; for (p = m->pollfds, i = 0; i < m->n_pollfds; p++, i++) { - for (;;) { - assert(s && s->type == MAINLOOP_SOURCE_TYPE_IO); + if (!p->revents) + continue; + + if (p->fd == m->signal_pipe[0]) { + /* Event from signal pipe */ + + if (p->revents & POLLIN) { + int sig; + ssize_t r; + r = read(m->signal_pipe[0], &sig, sizeof(sig)); + assert((r < 0 && errno == EAGAIN) || r == sizeof(sig)); - if (p->fd == s->io.fd) { + if (r == sizeof(sig)) { + struct mainloop_source *l = m->signal_sources.sources; + while (l) { + assert(l->type == MAINLOOP_SOURCE_TYPE_SIGNAL); + + if (l->signal.sig == sig && l->enabled && !l->dead) { + assert(l->signal.callback); + l->signal.callback(l, sig, l->userdata); + } + + l = l->next; + } + } + } + + } else { + /* Event from I/O source */ + + for (; s; s = s->next) { + if (p->fd != s->io.fd) + continue; + + assert(s->type == MAINLOOP_SOURCE_TYPE_IO); + if (!s->dead && s->enabled) { enum mainloop_io_event e = (p->revents & POLLIN ? MAINLOOP_IO_EVENT_IN : 0) | (p->revents & POLLOUT ? MAINLOOP_IO_EVENT_OUT : 0); if (e) { @@ -142,7 +224,6 @@ static void dispatch_pollfds(struct mainloop *m) { break; } - s = s->next; } } } @@ -172,7 +253,11 @@ int mainloop_iterate(struct mainloop *m, int block) { m->running = 1; - if ((c = poll(m->pollfds, m->n_pollfds, (block && !m->idle_sources.n_sources) ? -1 : 0)) > 0) + do { + c = poll(m->pollfds, m->n_pollfds, (block && !m->idle_sources.n_sources) ? -1 : 0); + } while (c < 0 && errno == EINTR); + + if (c > 0) dispatch_pollfds(m); else if (c == 0) { for (s = m->idle_sources.sources; s; s = s->next) { @@ -212,6 +297,9 @@ static struct mainloop_source_list* get_source_list(struct mainloop *m, enum mai case MAINLOOP_SOURCE_TYPE_IDLE: l = &m->idle_sources; break; + case MAINLOOP_SOURCE_TYPE_SIGNAL: + l = &m->signal_sources; + break; default: l = NULL; break; @@ -279,7 +367,33 @@ struct mainloop_source* mainloop_source_new_idle(struct mainloop*m, void (*callb s = source_new(m, MAINLOOP_SOURCE_TYPE_IDLE); - s->prepare.callback = callback; + s->idle.callback = callback; + s->userdata = userdata; + s->enabled = 1; + return s; +} + +struct mainloop_source* mainloop_source_new_signal(struct mainloop*m, int sig, void (*callback)(struct mainloop_source *s, int sig, void*userdata), void*userdata) { + struct mainloop_source* s; + struct sigaction save_sa, sa; + + assert(m && callback); + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_func; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + + memset(&save_sa, 0, sizeof(save_sa)); + + if (sigaction(sig, &sa, &save_sa) < 0) + return NULL; + + s = source_new(m, MAINLOOP_SOURCE_TYPE_SIGNAL); + s->signal.sig = sig; + s->signal.sigaction = save_sa; + + s->signal.callback = callback; s->userdata = userdata; s->enabled = 1; return s; @@ -299,6 +413,8 @@ void mainloop_source_free(struct mainloop_source*s) { if (s->type == MAINLOOP_SOURCE_TYPE_IO) s->mainloop->rebuild_pollfds = 1; + else if (s->type == MAINLOOP_SOURCE_TYPE_SIGNAL) + sigaction(s->signal.sig, &s->signal.sigaction, NULL); } void mainloop_source_enable(struct mainloop_source*s, int b) { diff --git a/src/mainloop.h b/src/mainloop.h index 72376c727..3c6d7e37c 100644 --- a/src/mainloop.h +++ b/src/mainloop.h @@ -14,7 +14,8 @@ enum mainloop_io_event { enum mainloop_source_type { MAINLOOP_SOURCE_TYPE_IO, MAINLOOP_SOURCE_TYPE_PREPARE, - MAINLOOP_SOURCE_TYPE_IDLE + MAINLOOP_SOURCE_TYPE_IDLE, + MAINLOOP_SOURCE_TYPE_SIGNAL }; struct mainloop *mainloop_new(void); @@ -27,6 +28,7 @@ void mainloop_quit(struct mainloop *m, int r); struct mainloop_source* mainloop_source_new_io(struct mainloop*m, int fd, enum mainloop_io_event event, void (*callback)(struct mainloop_source*s, int fd, enum mainloop_io_event event, void *userdata), void *userdata); struct mainloop_source* mainloop_source_new_prepare(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata); struct mainloop_source* mainloop_source_new_idle(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata); +struct mainloop_source* mainloop_source_new_signal(struct mainloop*m, int sig, void (*callback)(struct mainloop_source *s, int sig, void*userdata), void*userdata); void mainloop_source_free(struct mainloop_source*s); void mainloop_source_enable(struct mainloop_source*s, int b); diff --git a/src/module.c b/src/module.c index 4aa9fd681..62204e4c2 100644 --- a/src/module.c +++ b/src/module.c @@ -3,66 +3,10 @@ #include #include #include +#include #include "module.h" - -static void free_deps(struct dependency_module** deps) { - assert(deps); - - while (*deps) { - struct dependency_module *next = (*deps)->next; - lt_dlclose((*deps)->dl); - free(deps); - *deps = next; - } -} - -static int load_deps(const char *fname, struct dependency_module **deps) { - char line[PATH_MAX]; - FILE *f; - char depfile[PATH_MAX]; - assert(fname && deps); - - snprintf(depfile, sizeof(depfile), "%s.moddep", fname); - - if (!(f = fopen(depfile, "r"))) - return -1; - - while (fgets(line, sizeof(line)-1, f)) { - lt_dlhandle dl; - char *p; - size_t l; - struct dependency_module* d; - - p = line + strspn(line, " \t"); - - l = strlen(p); - if (p[l-1] == '\n') - p[l-1] = 0; - - if (*p == '#' || *p == 0) - continue; - - load_deps(p, deps); - - if (!(dl = lt_dlopenext(p))) { - free_deps(deps); - fclose(f); - return -1; - } - - d = malloc(sizeof(struct dependency_module)); - assert(d); - d->dl = dl; - d->next = *deps; - *deps = d; - } - - fclose(f); - return 0; -} - struct module* module_load(struct core *c, const char *name, const char *argument) { struct module *m = NULL; int r; @@ -72,12 +16,6 @@ struct module* module_load(struct core *c, const char *name, const char *argumen m = malloc(sizeof(struct module)); assert(m); - m->dl = NULL; - - m->dependencies = NULL; - if (load_deps(name, &m->dependencies) < 0) - goto fail; - if (!(m->dl = lt_dlopenext(name))) goto fail; @@ -106,10 +44,12 @@ struct module* module_load(struct core *c, const char *name, const char *argumen fail: if (m) { + free(m->argument); + free(m->name); + if (m->dl) lt_dlclose(m->dl); - free_deps(&m->dependencies); free(m); } @@ -121,7 +61,6 @@ static void module_free(struct module *m) { m->done(m->core, m); lt_dlclose(m->dl); - free_deps(&m->dependencies); free(m->name); free(m->argument); free(m); diff --git a/src/module.h b/src/module.h index d16c25cda..980821945 100644 --- a/src/module.h +++ b/src/module.h @@ -17,8 +17,6 @@ struct module { uint32_t index; lt_dlhandle dl; - struct dependency_module *dependencies; - int (*init)(struct core *c, struct module*m); void (*done)(struct core *c, struct module*m); diff --git a/src/sink-pipe.c b/src/sink-pipe.c index 4a8348f8c..78ea7bf2a 100644 --- a/src/sink-pipe.c +++ b/src/sink-pipe.c @@ -85,7 +85,7 @@ int module_init(struct core *c, struct module*m) { mkfifo((p = m->argument ? m->argument : "/tmp/musicfifo"), 0777); - if ((fd = open(p, O_RDWR) < 0)) { + if ((fd = open(p, O_RDWR)) < 0) { fprintf(stderr, "open('%s'): %s\n", p, strerror(errno)); goto fail; } diff --git a/src/sink.c b/src/sink.c index ac387c78c..0e68cf8b2 100644 --- a/src/sink.c +++ b/src/sink.c @@ -29,6 +29,8 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s } s->monitor_source = source_new(core, n, spec); + free(n); + s->volume = 0xFF; s->notify_callback = NULL; @@ -41,12 +43,13 @@ void sink_free(struct sink *s) { struct input_stream *i; assert(s); + while ((i = idxset_rrobin(s->input_streams, NULL))) + input_stream_free(i); + idxset_free(s->input_streams, NULL, NULL); + idxset_remove_by_data(s->core->sinks, s, NULL); source_free(s->monitor_source); - while ((i = idxset_rrobin(s->input_streams, NULL))) - input_stream_free(i); - free(s->name); free(s); } diff --git a/src/source.c b/src/source.c index 2f34c461e..98df2447b 100644 --- a/src/source.c +++ b/src/source.c @@ -34,10 +34,16 @@ static void do_free(void *p, void *userdata) { }; void source_free(struct source *s) { + struct output_stream *o; assert(s); + while ((o = idxset_rrobin(s->output_streams, NULL))) + output_stream_free(o); + idxset_free(s->output_streams, NULL, NULL); + idxset_remove_by_data(s->core->sources, s, NULL); idxset_free(s->output_streams, do_free, NULL); + free(s->name); free(s); } From edfad835cb7e4ab9f62de81cf4bf6b6ad9610b02 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Jun 2004 21:30:51 +0000 Subject: [PATCH 0008/1514] remove moddep files (since they are obsolete) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@9 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/protocol-simple-tcp.moddep | 2 -- src/protocol-simple.moddep | 1 - src/sink-pipe.moddep | 1 - src/socket-server.moddep | 1 - 4 files changed, 5 deletions(-) delete mode 100644 src/protocol-simple-tcp.moddep delete mode 100644 src/protocol-simple.moddep delete mode 100644 src/sink-pipe.moddep delete mode 100644 src/socket-server.moddep diff --git a/src/protocol-simple-tcp.moddep b/src/protocol-simple-tcp.moddep deleted file mode 100644 index 88f964a0e..000000000 --- a/src/protocol-simple-tcp.moddep +++ /dev/null @@ -1,2 +0,0 @@ -socket-server -protocol-simple diff --git a/src/protocol-simple.moddep b/src/protocol-simple.moddep deleted file mode 100644 index c49501d8e..000000000 --- a/src/protocol-simple.moddep +++ /dev/null @@ -1 +0,0 @@ -socket-server diff --git a/src/sink-pipe.moddep b/src/sink-pipe.moddep deleted file mode 100644 index 6958f9fc0..000000000 --- a/src/sink-pipe.moddep +++ /dev/null @@ -1 +0,0 @@ -iochannel diff --git a/src/socket-server.moddep b/src/socket-server.moddep deleted file mode 100644 index 6958f9fc0..000000000 --- a/src/socket-server.moddep +++ /dev/null @@ -1 +0,0 @@ -iochannel From c8cf0c1ce9cf1b38b302ae4a2a6fa798fef85f08 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Jun 2004 18:38:50 +0000 Subject: [PATCH 0009/1514] a bunch of fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@10 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/idxset.c | 7 +++++-- src/iochannel.c | 8 ++++---- src/mainloop.c | 6 ++++-- src/memblockq.c | 4 ++-- src/protocol-simple.c | 9 ++++++--- src/sink.c | 2 ++ src/socket-server.c | 6 +++++- src/source.c | 7 ------- 8 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/idxset.c b/src/idxset.c index f0d7ad879..fe447ac6d 100644 --- a/src/idxset.c +++ b/src/idxset.c @@ -152,8 +152,8 @@ int idxset_put(struct idxset*s, void *p, uint32_t *index) { s->hash_table[h] = e; /* Insert into array */ - extend_array(s, s->index); - a = array_index(s, s->index); + extend_array(s, e->index); + a = array_index(s, e->index); assert(a && !*a); *a = e; @@ -185,6 +185,9 @@ void* idxset_get_by_index(struct idxset*s, uint32_t index) { if (!(a = array_index(s, index))) return NULL; + if (!*a) + return NULL; + return (*a)->data; } diff --git a/src/iochannel.c b/src/iochannel.c index aa7de714e..2044d5615 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -41,15 +41,15 @@ static void enable_mainloop_sources(struct iochannel *io) { static void callback(struct mainloop_source*s, int fd, enum mainloop_io_event events, void *userdata) { struct iochannel *io = userdata; - int changed; + int changed = 0; assert(s && fd >= 0 && userdata); - if (events & MAINLOOP_IO_EVENT_IN && !io->readable) { + if ((events & MAINLOOP_IO_EVENT_IN) && !io->readable) { io->readable = 1; changed = 1; } - if (events & MAINLOOP_IO_EVENT_OUT && !io->writable) { + if ((events & MAINLOOP_IO_EVENT_OUT) && !io->writable) { io->writable = 1; changed = 1; } @@ -116,7 +116,7 @@ void iochannel_free(struct iochannel*io) { if (io->input_source) mainloop_source_free(io->input_source); - if (io->output_source) + if (io->output_source && io->output_source != io->input_source) mainloop_source_free(io->output_source); free(io); diff --git a/src/mainloop.c b/src/mainloop.c index 0f5811f2f..2992673ac 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -248,8 +248,10 @@ int mainloop_iterate(struct mainloop *m, int block) { } } - if (m->rebuild_pollfds) + if (m->rebuild_pollfds) { rebuild_pollfds(m); + m->rebuild_pollfds = 0; + } m->running = 1; @@ -431,7 +433,7 @@ void mainloop_source_enable(struct mainloop_source*s, int b) { void mainloop_source_io_set_events(struct mainloop_source*s, enum mainloop_io_event events) { assert(s && !s->dead && s->type == MAINLOOP_SOURCE_TYPE_IO); - if ((s->io.events && !events) || (!s->io.events && events)) { + if (s->io.events != events) { assert(s->mainloop); s->mainloop->rebuild_pollfds = 1; } diff --git a/src/memblockq.c b/src/memblockq.c index 1424c5567..a422cf093 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -46,7 +46,7 @@ void memblockq_free(struct memblockq* bq) { void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta) { struct memblock_list *q; - assert(bq && chunk && chunk->memblock && chunk->index); + assert(bq && chunk && chunk->memblock && chunk->length); q = malloc(sizeof(struct memblock_list)); assert(q); @@ -152,5 +152,5 @@ void memblockq_empty(struct memblockq *bq) { int memblockq_is_empty(struct memblockq *bq) { assert(bq); - return bq->total_length >= bq->base; + return bq->total_length < bq->base; } diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 3335bc149..e930f9aee 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -103,7 +103,10 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->istream = NULL; c->ostream = NULL; c->protocol = p; - + + c->client = client_new(p->core, "SIMPLE", "Client"); + assert(c->client); + if (p->mode & PROTOCOL_SIMPLE_RECORD) { struct source *source; @@ -128,8 +131,6 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us assert(c->istream); } - c->client = client_new(p->core, "SIMPLE", "Client"); - assert(c->client); iochannel_set_callback(c->io, io_callback, c); idxset_put(p->connections, c, NULL); @@ -137,6 +138,8 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us fail: if (c) { + if (c->client) + client_free(c->client); if (c->istream) input_stream_free(c->istream); if (c->ostream) diff --git a/src/sink.c b/src/sink.c index 0e68cf8b2..02ca3468a 100644 --- a/src/sink.c +++ b/src/sink.c @@ -77,6 +77,8 @@ static int get_max_length(void *p, uint32_t index, int *del, void*userdata) { info->count++; info->last_input_stream = i; + memblock_unref(chunk.memblock); + return 0; } diff --git a/src/socket-server.c b/src/socket-server.c index 2a1db9a03..6ad225e39 100644 --- a/src/socket-server.c +++ b/src/socket-server.c @@ -104,6 +104,7 @@ fail: struct socket_server* socket_server_new_ipv4(struct mainloop *m, uint32_t address, uint16_t port) { int fd = -1; struct sockaddr_in sa; + int on = 1; assert(m && port); @@ -112,10 +113,13 @@ struct socket_server* socket_server_new_ipv4(struct mainloop *m, uint32_t addres goto fail; } + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) + fprintf(stderr, "setsockopt(): %s\n", strerror(errno)); + sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(address); - + if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { fprintf(stderr, "bind(): %s\n", strerror(errno)); goto fail; diff --git a/src/source.c b/src/source.c index 98df2447b..a1e7b2458 100644 --- a/src/source.c +++ b/src/source.c @@ -27,12 +27,6 @@ struct source* source_new(struct core *core, const char *name, const struct samp return s; } -static void do_free(void *p, void *userdata) { - struct output_stream *o = p; - assert(o); - output_stream_free(o); -}; - void source_free(struct source *s) { struct output_stream *o; assert(s); @@ -42,7 +36,6 @@ void source_free(struct source *s) { idxset_free(s->output_streams, NULL, NULL); idxset_remove_by_data(s->core->sources, s, NULL); - idxset_free(s->output_streams, do_free, NULL); free(s->name); free(s); From 5ce204829fe6706a5edaec50769abf7eed266656 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Jun 2004 20:30:50 +0000 Subject: [PATCH 0010/1514] more cleanups git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@11 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/client.c | 14 +++++++++++- src/client.h | 15 ++++++++++-- src/core.c | 6 ++--- src/idxset.c | 53 +++++++++++++++++++++++++------------------ src/idxset.h | 7 ++++++ src/inputstream.c | 18 ++++++++++++++- src/inputstream.h | 17 +++++++++++++- src/memblockq.c | 2 ++ src/outputstream.c | 16 +++++++++++++ src/outputstream.h | 5 ++++ src/protocol-simple.c | 32 +++++++++++++++++++++++--- src/sink.c | 9 +++++--- src/source.c | 7 ++++-- 13 files changed, 162 insertions(+), 39 deletions(-) diff --git a/src/client.c b/src/client.c index 56d857344..3dd37668c 100644 --- a/src/client.c +++ b/src/client.c @@ -14,7 +14,7 @@ struct client *client_new(struct core *core, const char *protocol_name, char *na c->protocol_name = protocol_name; c->name = name ? strdup(name) : NULL; c->kill = NULL; - c->userdata = NULL; + c->kill_userdata = NULL; c->core = core; r = idxset_put(core->clients, c, &c->index); @@ -30,3 +30,15 @@ void client_free(struct client *c) { free(c->name); free(c); } + +void client_set_kill_callback(struct client *c, void (*kill)(struct client *c, void *userdata), void *userdata) { + assert(c && kill); + c->kill = kill; + c->kill_userdata = userdata; +} + +void client_kill(struct client *c) { + assert(c); + c->kill(c, c->kill_userdata); +} + diff --git a/src/client.h b/src/client.h index 7128a452b..8d9e519c0 100644 --- a/src/client.h +++ b/src/client.h @@ -9,13 +9,24 @@ struct client { const char *protocol_name; - void *userdata; - void (*kill)(struct client *c); + void *kill_userdata; + void (*kill)(struct client *c, void *userdata); struct core *core; }; struct client *client_new(struct core *c, const char *protocol_name, char *name); + +/* This function should be called only by the code that created the client */ void client_free(struct client *c); +/* The registrant of the client should call this function to set a + * callback function which is called when destruction of the client is + * requested */ +void client_set_kill_callback(struct client *c, void (*kill)(struct client *c, void *userdata), void *userdata); + +/* Code that didn't create the client should call this function to + * request destruction of the client */ +void client_kill(struct client *c); + #endif diff --git a/src/core.c b/src/core.c index 7cfa66e3f..0457f4f3e 100644 --- a/src/core.c +++ b/src/core.c @@ -57,11 +57,10 @@ struct sink* core_get_default_sink(struct core *c) { if ((sink = idxset_get_by_index(c->sinks, c->default_sink_index))) return sink; - if (!(sink = idxset_rrobin(c->sinks, NULL))) + if (!(sink = idxset_first(c->sinks, &c->default_sink_index))) return NULL; fprintf(stderr, "Default sink vanished, setting to %u\n", sink->index); - c->default_sink_index = sink->index; return sink; } @@ -72,10 +71,9 @@ struct source* core_get_default_source(struct core *c) { if ((source = idxset_get_by_index(c->sources, c->default_source_index))) return source; - if (!(source = idxset_rrobin(c->sources, NULL))) + if (!(source = idxset_first(c->sources, &c->default_source_index))) return NULL; fprintf(stderr, "Default source vanished, setting to %u\n", source->index); - c->default_source_index = source->index; return source; } diff --git a/src/idxset.c b/src/idxset.c index fe447ac6d..4442190d7 100644 --- a/src/idxset.c +++ b/src/idxset.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -18,7 +19,7 @@ struct idxset { int (*compare_func)(void *a, void *b); unsigned hash_table_size, n_entries; - struct idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail, *rrobin; + struct idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail; uint32_t index, start_index, array_size; }; @@ -46,7 +47,6 @@ struct idxset* idxset_new(unsigned (*hash_func) (void *p), int (*compare_func) ( s->index = 0; s->start_index = 0; s->n_entries = 0; - s->rrobin = NULL; s->iterate_list_head = s->iterate_list_tail = NULL; @@ -86,9 +86,9 @@ static struct idxset_entry* hash_scan(struct idxset *s, struct idxset_entry* e, static void extend_array(struct idxset *s, uint32_t index) { uint32_t i, j, l; struct idxset_entry** n; - assert(index >= s->start_index ); + assert(index >= s->start_index); - if (index <= s->start_index + s->array_size) + if (index < s->start_index + s->array_size) return; for (i = 0; i < s->array_size; i++) @@ -111,13 +111,12 @@ static void extend_array(struct idxset *s, uint32_t index) { } static struct idxset_entry** array_index(struct idxset*s, uint32_t index) { - if (index >= s->start_index + s->array_size) return NULL; if (index < s->start_index) return NULL; - + return s->array + (index - s->start_index); } @@ -214,8 +213,8 @@ static void remove_entry(struct idxset *s, struct idxset_entry *e) { assert(s && e); /* Remove from array */ - a = array_index(s, s->index); - assert(a && *a == e); + a = array_index(s, e->index); + assert(a && *a && *a == e); *a = NULL; /* Remove from linked list */ @@ -238,9 +237,6 @@ static void remove_entry(struct idxset *s, struct idxset_entry *e) { else s->hash_table[e->hash_value] = e->hash_next; - if (s->rrobin == e) - s->rrobin = NULL; - free(e); assert(s->n_entries >= 1); @@ -265,7 +261,7 @@ void* idxset_remove_by_index(struct idxset*s, uint32_t index) { void* idxset_remove_by_data(struct idxset*s, void *data, uint32_t *index) { struct idxset_entry *e; unsigned h; - + assert(s->hash_func); h = s->hash_func(data) % s->hash_table_size; @@ -283,23 +279,36 @@ void* idxset_remove_by_data(struct idxset*s, void *data, uint32_t *index) { } void* idxset_rrobin(struct idxset *s, uint32_t *index) { + struct idxset_entry **a, *e = NULL; + assert(s && index); + + if ((a = array_index(s, *index)) && *a) + e = (*a)->iterate_next; + + if (!e) + e = s->iterate_list_head; + + if (!e) + return NULL; + + if (index) + *index = e->index; + + return e->data; +} + +void* idxset_first(struct idxset *s, uint32_t *index) { assert(s); - if (s->rrobin) - s->rrobin = s->rrobin->iterate_next; - - if (!s->rrobin) - s->rrobin = s->iterate_list_head; - - if (!s->rrobin) + if (!s->iterate_list_head) return NULL; if (index) - *index = s->rrobin->index; - - return s->rrobin->data; + *index = s->iterate_list_head->index; + return s->iterate_list_head->data; } + int idxset_foreach(struct idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata) { struct idxset_entry *e; assert(s && func); diff --git a/src/idxset.h b/src/idxset.h index f649e23e7..fdcb7b54b 100644 --- a/src/idxset.h +++ b/src/idxset.h @@ -18,8 +18,15 @@ void* idxset_get_by_data(struct idxset*s, void *p, uint32_t *index); void* idxset_remove_by_index(struct idxset*s, uint32_t index); void* idxset_remove_by_data(struct idxset*s, void *p, uint32_t *index); +/* This may be used to iterate through all entries. When called with + an invalid index value it returns the first entry, otherwise the + next following. The function is best called with *index = + IDXSET_VALID first. */ void* idxset_rrobin(struct idxset *s, uint32_t *index); +/* Return the oldest entry in the idxset */ +void* idxset_first(struct idxset *s, uint32_t *index); + int idxset_foreach(struct idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata); unsigned idxset_ncontents(struct idxset*s); diff --git a/src/inputstream.c b/src/inputstream.c index c7b4b4c7a..817192886 100644 --- a/src/inputstream.c +++ b/src/inputstream.c @@ -14,6 +14,8 @@ struct input_stream* input_stream_new(struct sink *s, struct sample_spec *spec, i->name = name ? strdup(name) : NULL; i->sink = s; i->spec = *spec; + i->kill = NULL; + i->kill_userdata = NULL; i->memblockq = memblockq_new(bytes_per_second(spec)*5, sample_size(spec)); assert(i->memblockq); @@ -40,7 +42,7 @@ void input_stream_free(struct input_stream* i) { free(i); } -void input_stream_notify(struct input_stream *i) { +void input_stream_notify_sink(struct input_stream *i) { assert(i); if (memblockq_is_empty(i->memblockq)) @@ -48,3 +50,17 @@ void input_stream_notify(struct input_stream *i) { sink_notify(i->sink); } + +void input_stream_set_kill_callback(struct input_stream *i, void (*kill)(struct input_stream*i, void *userdata), void *userdata) { + assert(i && kill); + i->kill = kill; + i->kill_userdata = userdata; +} + + +void input_stream_kill(struct input_stream*i) { + assert(i); + + if (i->kill) + i->kill(i, i->kill_userdata); +} diff --git a/src/inputstream.h b/src/inputstream.h index 0353799e8..a258c3d14 100644 --- a/src/inputstream.h +++ b/src/inputstream.h @@ -15,11 +15,26 @@ struct input_stream { struct sample_spec spec; struct memblockq *memblockq; + + void (*kill)(struct input_stream* i, void *userdata); + void *kill_userdata; }; struct input_stream* input_stream_new(struct sink *s, struct sample_spec *spec, const char *name); void input_stream_free(struct input_stream* i); -void input_stream_notify(struct input_stream *i); +/* This function notifies the attached sink that new data is available + * in the memblockq */ +void input_stream_notify_sink(struct input_stream *i); + + +/* The registrant of the input stream should call this function to set a + * callback function which is called when destruction of the input stream is + * requested */ +void input_stream_set_kill_callback(struct input_stream *c, void (*kill)(struct input_stream*i, void *userdata), void *userdata); + +/* Code that didn't create the input stream should call this function to + * request destruction of it */ +void input_stream_kill(struct input_stream *c); #endif diff --git a/src/memblockq.c b/src/memblockq.c index a422cf093..6437dd5b3 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -119,6 +119,8 @@ void memblockq_drop(struct memblockq *bq, size_t length) { q = bq->blocks; bq->blocks = bq->blocks->next; + if (bq->blocks == NULL) + bq->blocks_tail = NULL; memblock_unref(q->chunk.memblock); free(q); diff --git a/src/outputstream.c b/src/outputstream.c index ffec77da9..c6681d293 100644 --- a/src/outputstream.c +++ b/src/outputstream.c @@ -14,6 +14,8 @@ struct output_stream* output_stream_new(struct source *s, struct sample_spec *sp o->name = name ? strdup(name) : NULL; o->source = s; o->spec = *spec; + o->kill = NULL; + o->kill_userdata = NULL; o->memblockq = memblockq_new(bytes_per_second(spec)*5, sample_size(spec)); assert(o->memblockq); @@ -39,3 +41,17 @@ void output_stream_free(struct output_stream* o) { free(o->name); free(o); } + +void output_stream_set_kill_callback(struct output_stream *i, void (*kill)(struct output_stream*i, void *userdata), void *userdata) { + assert(i && kill); + i->kill = kill; + i->kill_userdata = userdata; +} + + +void output_stream_kill(struct output_stream*i) { + assert(i); + + if (i->kill) + i->kill(i, i->kill_userdata); +} diff --git a/src/outputstream.h b/src/outputstream.h index 410543410..c6c0a717e 100644 --- a/src/outputstream.h +++ b/src/outputstream.h @@ -14,9 +14,14 @@ struct output_stream { struct sample_spec spec; struct memblockq *memblockq; + void (*kill)(struct output_stream* i, void *userdata); + void *kill_userdata; }; struct output_stream* output_stream_new(struct source *s, struct sample_spec *spec, const char *name); void output_stream_free(struct output_stream* o); +void output_stream_set_kill_callback(struct output_stream *i, void (*kill)(struct output_stream*i, void *userdata), void *userdata); +void output_stream_kill(struct output_stream*i); + #endif diff --git a/src/protocol-simple.c b/src/protocol-simple.c index e930f9aee..ec121faa1 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -42,6 +42,30 @@ static void free_connection(void *data, void *userdata) { free(c); } +static void destroy_connection(struct connection *c) { + assert(c && c->protocol); + idxset_remove_by_data(c->protocol->connections, c, NULL); + free_connection(c, NULL); +} + +static void istream_kill_cb(struct input_stream *i, void *userdata) { + struct connection *c = userdata; + assert(i && c); + destroy_connection(c); +} + +static void ostream_kill_cb(struct output_stream *o, void *userdata) { + struct connection *c = userdata; + assert(o && c); + destroy_connection(c); +} + +static void client_kill_cb(struct client *client, void*userdata) { + struct connection *c= userdata; + assert(client && c); + destroy_connection(c); +} + static void io_callback(struct iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c); @@ -64,7 +88,7 @@ static void io_callback(struct iochannel*io, void *userdata) { chunk.index = 0; memblockq_push(c->istream->memblockq, &chunk, 0); - input_stream_notify(c->istream); + input_stream_notify_sink(c->istream); memblock_unref(chunk.memblock); } @@ -88,8 +112,7 @@ static void io_callback(struct iochannel*io, void *userdata) { return; fail: - idxset_remove_by_data(c->protocol->connections, c, NULL); - free_connection(c, NULL); + destroy_connection(c); } static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { @@ -106,6 +129,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->client = client_new(p->core, "SIMPLE", "Client"); assert(c->client); + client_set_kill_callback(c->client, client_kill_cb, c); if (p->mode & PROTOCOL_SIMPLE_RECORD) { struct source *source; @@ -117,6 +141,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->ostream = output_stream_new(source, &DEFAULT_SAMPLE_SPEC, c->client->name); assert(c->ostream); + output_stream_set_kill_callback(c->ostream, ostream_kill_cb, c); } if (p->mode & PROTOCOL_SIMPLE_PLAYBACK) { @@ -129,6 +154,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->istream = input_stream_new(sink, &DEFAULT_SAMPLE_SPEC, c->client->name); assert(c->istream); + input_stream_set_kill_callback(c->istream, istream_kill_cb, c); } diff --git a/src/sink.c b/src/sink.c index 02ca3468a..dfe1bcb98 100644 --- a/src/sink.c +++ b/src/sink.c @@ -40,11 +40,14 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s } void sink_free(struct sink *s) { - struct input_stream *i; + struct input_stream *i, *j = NULL; assert(s); - while ((i = idxset_rrobin(s->input_streams, NULL))) - input_stream_free(i); + while ((i = idxset_first(s->input_streams, NULL))) { + assert(i != j); + input_stream_kill(i); + j = i; + } idxset_free(s->input_streams, NULL, NULL); idxset_remove_by_data(s->core->sinks, s, NULL); diff --git a/src/source.c b/src/source.c index a1e7b2458..2d5e9bbde 100644 --- a/src/source.c +++ b/src/source.c @@ -28,11 +28,14 @@ struct source* source_new(struct core *core, const char *name, const struct samp } void source_free(struct source *s) { - struct output_stream *o; + struct output_stream *o, *j = NULL; assert(s); - while ((o = idxset_rrobin(s->output_streams, NULL))) + while ((o = idxset_first(s->output_streams, NULL))) { + assert(o != j); output_stream_free(o); + j = o; + } idxset_free(s->output_streams, NULL, NULL); idxset_remove_by_data(s->core->sources, s, NULL); From 0575fc66e9b175fef129a250697f07d7053e9108 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Jun 2004 20:34:33 +0000 Subject: [PATCH 0011/1514] remove oss.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@12 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/oss.c | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 src/oss.c diff --git a/src/oss.c b/src/oss.c deleted file mode 100644 index 42e60360b..000000000 --- a/src/oss.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "module.h" - -struct userdata { - struct sink *sink; - struct source *source; - int fd; -}; - -int module_init(struct core *c, struct module*m) { - struct userdata *u; - assert(c && m); - - u = malloc(sizeof(struct userdata)); - assert(u); - memset(u, 0, sizeof(struct userdata)); - m->userdata = u; - - return 0; -} - -void module_done(struct core *c, struct module*m) { - struct userdata *u; - assert(c && m); - - u = m->userdata; - - sink_free(u->sink); - source_free(u->source); - free(u); -} From f78e9b68cbc45015af05db497d1547c0e02d2751 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Jun 2004 22:47:12 +0000 Subject: [PATCH 0012/1514] commit some work and rename git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@13 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 + src/mainloop.c | 27 +- src/mainloop.h | 4 +- src/module-oss.c | 234 ++++++++++++++++++ ...ple-tcp.c => module-simple-protocol-tcp.c} | 0 src/pstream.c | 2 +- src/sink-pipe.c | 25 +- 7 files changed, 268 insertions(+), 28 deletions(-) create mode 100644 src/module-oss.c rename src/{protocol-simple-tcp.c => module-simple-protocol-tcp.c} (100%) diff --git a/src/Makefile.am b/src/Makefile.am index 485513df9..d249964bb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,3 +56,7 @@ protocol_simple_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la sink_pipe_la_SOURCES = sink-pipe.c sink_pipe_la_LDFLAGS = -module -avoid-version sink_pipe_la_LIBADD = libiochannel.la + +sink_oss_la_SOURCES = sink-pipe.c +sink_oss_la_LDFLAGS = -module -avoid-version +sink_oss_la_LIBADD = libiochannel.la diff --git a/src/mainloop.c b/src/mainloop.c index 2992673ac..37dbdb120 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -27,7 +27,7 @@ struct mainloop_source { struct { void (*callback)(struct mainloop_source*s, void *userdata); - } prepare; + } fixed; struct { void (*callback)(struct mainloop_source*s, void *userdata); @@ -47,7 +47,7 @@ struct mainloop_source_list { }; struct mainloop { - struct mainloop_source_list io_sources, prepare_sources, idle_sources, signal_sources; + struct mainloop_source_list io_sources, fixed_sources, idle_sources, signal_sources; struct pollfd *pollfds; int max_pollfds, n_pollfds; @@ -133,7 +133,7 @@ static void free_sources(struct mainloop_source_list *l, int all) { void mainloop_free(struct mainloop* m) { assert(m); free_sources(&m->io_sources, 1); - free_sources(&m->prepare_sources, 1); + free_sources(&m->fixed_sources, 1); free_sources(&m->idle_sources, 1); free_sources(&m->signal_sources, 1); @@ -237,14 +237,15 @@ int mainloop_iterate(struct mainloop *m, int block) { return m->quit; free_sources(&m->io_sources, 0); - free_sources(&m->prepare_sources, 0); + free_sources(&m->fixed_sources, 0); free_sources(&m->idle_sources, 0); + free_sources(&m->signal_sources, 0); - for (s = m->prepare_sources.sources; s; s = s->next) { - assert(!s->dead && s->type == MAINLOOP_SOURCE_TYPE_PREPARE); + for (s = m->fixed_sources.sources; s; s = s->next) { + assert(!s->dead && s->type == MAINLOOP_SOURCE_TYPE_FIXED); if (s->enabled) { - assert(s->prepare.callback); - s->prepare.callback(s, s->userdata); + assert(s->fixed.callback); + s->fixed.callback(s, s->userdata); } } @@ -293,8 +294,8 @@ static struct mainloop_source_list* get_source_list(struct mainloop *m, enum mai case MAINLOOP_SOURCE_TYPE_IO: l = &m->io_sources; break; - case MAINLOOP_SOURCE_TYPE_PREPARE: - l = &m->prepare_sources; + case MAINLOOP_SOURCE_TYPE_FIXED: + l = &m->fixed_sources; break; case MAINLOOP_SOURCE_TYPE_IDLE: l = &m->idle_sources; @@ -351,13 +352,13 @@ struct mainloop_source* mainloop_source_new_io(struct mainloop*m, int fd, enum m return s; } -struct mainloop_source* mainloop_source_new_prepare(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata) { +struct mainloop_source* mainloop_source_new_fixed(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata) { struct mainloop_source* s; assert(m && callback); - s = source_new(m, MAINLOOP_SOURCE_TYPE_PREPARE); + s = source_new(m, MAINLOOP_SOURCE_TYPE_FIXED); - s->prepare.callback = callback; + s->fixed.callback = callback; s->userdata = userdata; s->enabled = 1; return s; diff --git a/src/mainloop.h b/src/mainloop.h index 3c6d7e37c..3fe26fd0e 100644 --- a/src/mainloop.h +++ b/src/mainloop.h @@ -13,7 +13,7 @@ enum mainloop_io_event { enum mainloop_source_type { MAINLOOP_SOURCE_TYPE_IO, - MAINLOOP_SOURCE_TYPE_PREPARE, + MAINLOOP_SOURCE_TYPE_FIXED, MAINLOOP_SOURCE_TYPE_IDLE, MAINLOOP_SOURCE_TYPE_SIGNAL }; @@ -26,7 +26,7 @@ int mainloop_run(struct mainloop *m); void mainloop_quit(struct mainloop *m, int r); struct mainloop_source* mainloop_source_new_io(struct mainloop*m, int fd, enum mainloop_io_event event, void (*callback)(struct mainloop_source*s, int fd, enum mainloop_io_event event, void *userdata), void *userdata); -struct mainloop_source* mainloop_source_new_prepare(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata); +struct mainloop_source* mainloop_source_new_fixed(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata); struct mainloop_source* mainloop_source_new_idle(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata); struct mainloop_source* mainloop_source_new_signal(struct mainloop*m, int sig, void (*callback)(struct mainloop_source *s, int sig, void*userdata), void*userdata); diff --git a/src/module-oss.c b/src/module-oss.c new file mode 100644 index 000000000..b2b106b41 --- /dev/null +++ b/src/module-oss.c @@ -0,0 +1,234 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iochannel.h" +#include "sink.h" +#include "source.h" +#include "module.h" + +struct userdata { + struct sink *sink; + struct source *source; + struct iochannel *io; + struct core *core; + + struct memchunk memchunk, silence; + + uint32_t fragment_size; +}; + +static void do_write(struct userdata *u) { + struct memchunk *memchunk; + ssize_t r; + assert(u); + + if (!iochannel_is_writable(u->io)) + return; + + if (!u->memchunk.length) { + if (sink_render(u->sink, fragment_size, &u->memchunk) < 0) + memchunk = &u->silence; + else + memchunk = &u->memchunk; + } + + assert(memchunk->memblock && memchunk->length); + + if ((r = iochannel_write(u->io, memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { + fprintf(stderr, "write() failed: %s\n", strerror(errno)); + return; + } + + if (memchunk == &u->silence) + assert(r % u->sample_size == 0); + else { + u->memchunk.index += r; + u->memchunk.length -= r; + + if (u->memchunk.length <= 0) { + memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; + } + } +} + +static void do_read(struct userdata *u) { + struct memchunk memchunk; + ssize_t r; + assert(u); + + if (!iochannel_is_readable(u->io)) + return; + + memchunk.memblock = memblock_new(u->fragment_size); + assert(memchunk.memblock); + if ((r = iochannel_read(u->io, memchunk.memblock->data, memchunk->memblock->length)) < 0) { + memblock_unref(memchunk.memblock); + fprintf(stderr, "read() failed: %s\n", strerror(errno)); + return; + } + + assert(r < memchunk->memblock->length); + memchunk.length = memchunk.memblock->length = r; + memchunk.index = 0; + + source_post(u->source, &memchunk); + memblock_unref(memchunk.memblock); +}; + +static void io_callback(struct iochannel *io, void*userdata) { + struct userdata *u = userdata; + assert(u); + do_write(u); + do_read(u); +} + +int module_init(struct core *c, struct module*m) { + struct userdata *u = NULL; + struct stat st; + char *p; + int fd = -1; + int format, channels, speed, frag_size; + int m; + const static struct sample_spec ss; + assert(c && m); + + p = m->argument ? m->argument : "/dev/dsp"; + if ((fd = open(p, m = O_RDWR)) >= 0) { + int caps; + + ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); + + if (ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) < 0) { + fprintf(stderr, "SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); + goto fail; + } + + if (!(caps & DSP_CAP_DUPLEX)) { + close(fd); + fd = -1; + } + } + + if (fd < 0) { + if ((fd = open(p, m = O_WRONLY)) < 0) { + if ((fd = open(p, m = O_RDONLY)) < 0) { + fprintf(stderr, "open('%s'): %s\n", p, strerror(errno)); + goto fail; + } + } + } + + frags = 0x7fff0000 | (10 << 16); /* 1024 bytes fragment size */ + if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frags) < 0) { + fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); + goto fail; + } + + format = AFMT_S16_NE; + if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_S16_NE) { + int f = AFMT_S16_NE == AFMT_S16_LE ? AFMT_S16_BE : AFMT_S16_LE; + format = f; + if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != f) { + format = AFMT_U8; + if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_U8) { + fprintf(stderr, "SNDCTL_DSP_SETFMT: %s\n", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); + goto fail; + } else + ss.format = SAMPLE_U8; + } else + ss.format = f == AFMT_S16_LE ? SAMPLE_S16LE : SAMPLE_S16BE; + } else + ss.format = SAMPLE_S16NE; + + channels = 2; + if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { + fprintf(stderr, "SNDCTL_DSP_CHANNELS: %s\n", strerror(errno)); + goto fail; + } + assert(channels); + ss.channels = channels; + + speed = 44100; + if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { + fprintf(stderr, "SNDCTL_DSP_SPEED: %s\n", strerror(errno)); + goto fail; + } + assert(speed); + ss.rate = speed; + + if (ioctl(fd, SNCTL_DSP_GETBLKSIZE, &frag_size) < 0) { + fprintf(stderr, "SNDCTL_DSP_GETBLKSIZE: %s\n", strerror(errno)); + goto fail; + } + + assert(frag_size); + + u = malloc(sizeof(struct userdata)); + assert(u); + + u->core = c; + + if (m != O_RDONLY) { + u->sink = sink_new(c, "dsp", &ss); + assert(u->sink); + } else + u->sink = NULL; + + if (m != O_WRONLY) { + u->source = source_new(c, "dsp", &ss); + assert(u->source); + } else + u->source = NULL; + + assert(u->source || u->sink); + + u->io = iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0); + assert(u->io); + iochannel_set_callback(u->io, io_callback, u); + + u->memchunk.memblock = NULL; + u->memchunk.length = 0; + + u->fragment_size = frag_size; + u->silence.memblock = memblock_new(u->fragment_size); + assert(u->silence); + u->silence.length = u->fragment_size; + u->silence.index = 0; + + m->userdata = u; + + return 0; + +fail: + if (fd >= 0) + close(fd); + + return -1; +} + +void module_done(struct core *c, struct module*m) { + struct userdata *u; + assert(c && m); + + u = m->userdata; + assert(u); + + if (u->memchunk.memblock) + memblock_unref(u->memchunk.memblock); + if (u->silence.memblock) + memblock_unref(u->silence.memblock); + + sink_free(u->sink); + source_free(u->source); + iochannel_free(u->io); + free(u); +} diff --git a/src/protocol-simple-tcp.c b/src/module-simple-protocol-tcp.c similarity index 100% rename from src/protocol-simple-tcp.c rename to src/module-simple-protocol-tcp.c diff --git a/src/pstream.c b/src/pstream.c index 083ebc22c..0336d161e 100644 --- a/src/pstream.c +++ b/src/pstream.c @@ -91,7 +91,7 @@ struct pstream *pstream_new(struct mainloop *m, struct iochannel *io) { p->dead = 0; p->mainloop = m; - p->mainloop_source = mainloop_source_new_prepare(m, prepare_callback, p); + p->mainloop_source = mainloop_source_new_fixed(m, prepare_callback, p); mainloop_source_enable(p->mainloop_source, 0); p->send_queue = queue_new(); diff --git a/src/sink-pipe.c b/src/sink-pipe.c index 78ea7bf2a..e63a7a86f 100644 --- a/src/sink-pipe.c +++ b/src/sink-pipe.c @@ -13,6 +13,8 @@ #include "module.h" struct userdata { + char *filename; + struct sink *sink; struct iochannel *io; struct core *core; @@ -73,7 +75,6 @@ static void io_callback(struct iochannel *io, void*userdata) { int module_init(struct core *c, struct module*m) { struct userdata *u = NULL; struct stat st; - struct sink *sink; char *p; int fd = -1; const static struct sample_spec ss = { @@ -100,17 +101,16 @@ int module_init(struct core *c, struct module*m) { goto fail; } - if (!(sink = sink_new(c, "fifo", &ss))) { - fprintf(stderr, "Failed to allocate new sink!\n"); - goto fail; - } u = malloc(sizeof(struct userdata)); assert(u); + u->filename = strdup(p); + assert(u->filename); u->core = c; - u->sink = sink; - sink_set_notify_callback(sink, notify_callback, u); + u->sink = sink_new(c, "fifo", &ss); + assert(u->sink); + sink_set_notify_callback(u->sink, notify_callback, u); u->io = iochannel_new(c->mainloop, -1, fd); assert(u->io); @@ -119,22 +119,18 @@ int module_init(struct core *c, struct module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; - u->mainloop_source = mainloop_source_new_prepare(c->mainloop, prepare_callback, u); + u->mainloop_source = mainloop_source_new_fixed(c->mainloop, prepare_callback, u); assert(u->mainloop_source); mainloop_source_enable(u->mainloop_source, 0); m->userdata = u; - return 0; fail: if (fd >= 0) close(fd); - if (u) - free(u); - return -1; } @@ -151,5 +147,10 @@ void module_done(struct core *c, struct module*m) { sink_free(u->sink); iochannel_free(u->io); mainloop_source_free(u->mainloop_source); + + assert(u->filename); + unlink(u->filename); + free(u->filename); + free(u); } From bfcde99a8f7fe31be504e1d55c4a065c760bb533 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Jun 2004 22:47:29 +0000 Subject: [PATCH 0013/1514] rename some more git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@14 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/{sink-pipe.c => module-pipe-sink.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{sink-pipe.c => module-pipe-sink.c} (100%) diff --git a/src/sink-pipe.c b/src/module-pipe-sink.c similarity index 100% rename from src/sink-pipe.c rename to src/module-pipe-sink.c From 1a5060720d67fa6e4d4cb3b08c5067ec5216b0fd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 15 Jun 2004 00:29:01 +0000 Subject: [PATCH 0014/1514] oss output works git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@15 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 23 ++++----- src/inputstream.c | 20 +++++++- src/inputstream.h | 14 +++++- src/main.c | 5 +- src/memblockq.c | 30 ++++++++++-- src/memblockq.h | 5 +- src/module-oss.c | 63 +++++++++++++++---------- src/outputstream.c | 2 +- src/protocol-simple.c | 105 +++++++++++++++++++++++++----------------- src/sink.c | 20 +++++--- src/sink.h | 4 +- src/todo | 16 +++++++ 12 files changed, 207 insertions(+), 100 deletions(-) create mode 100644 src/todo diff --git a/src/Makefile.am b/src/Makefile.am index d249964bb..f09538462 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,8 +20,9 @@ AM_CFLAGS=-ansi -D_GNU_SOURCE bin_PROGRAMS = polypaudio -pkglib_LTLIBRARIES=libprotocol-simple.la protocol-simple-tcp.la \ - libsocket-server.la sink-pipe.la libpstream.la libiochannel.la libpacket.la +pkglib_LTLIBRARIES=libprotocol-simple.la module-simple-protocol-tcp.la \ + libsocket-server.la module-pipe-sink.la libpstream.la libiochannel.la \ + libpacket.la module-oss.la polypaudio_SOURCES = idxset.c queue.c strbuf.c mainloop.c \ memblock.c sample.c memblockq.c client.c \ @@ -49,14 +50,14 @@ libiochannel_la_LDFLAGS = -avoid-version libpacket_la_SOURCES = packet.c libpacket_la_LDFLAGS = -avoid-version -protocol_simple_tcp_la_SOURCES = protocol-simple-tcp.c -protocol_simple_tcp_la_LDFLAGS = -module -avoid-version -protocol_simple_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la +module_simple_protocol_tcp_la_SOURCES = module-simple-protocol-tcp.c +module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version +module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la -sink_pipe_la_SOURCES = sink-pipe.c -sink_pipe_la_LDFLAGS = -module -avoid-version -sink_pipe_la_LIBADD = libiochannel.la +module_pipe_sink_la_SOURCES = module-pipe-sink.c +module_pipe_sink_la_LDFLAGS = -module -avoid-version +module_pipe_sink_la_LIBADD = libiochannel.la -sink_oss_la_SOURCES = sink-pipe.c -sink_oss_la_LDFLAGS = -module -avoid-version -sink_oss_la_LIBADD = libiochannel.la +module_oss_la_SOURCES = module-oss.c +module_oss_la_LDFLAGS = -module -avoid-version +module_oss_la_LIBADD = libiochannel.la diff --git a/src/inputstream.c b/src/inputstream.c index 817192886..7ece3b5c9 100644 --- a/src/inputstream.c +++ b/src/inputstream.c @@ -14,10 +14,13 @@ struct input_stream* input_stream_new(struct sink *s, struct sample_spec *spec, i->name = name ? strdup(name) : NULL; i->sink = s; i->spec = *spec; + i->kill = NULL; i->kill_userdata = NULL; + i->notify = NULL; + i->notify_userdata = NULL; - i->memblockq = memblockq_new(bytes_per_second(spec)*5, sample_size(spec)); + i->memblockq = memblockq_new(bytes_per_second(spec)*5, sample_size(spec), (size_t) -1); assert(i->memblockq); assert(s->core); @@ -45,7 +48,7 @@ void input_stream_free(struct input_stream* i) { void input_stream_notify_sink(struct input_stream *i) { assert(i); - if (memblockq_is_empty(i->memblockq)) + if (!memblockq_is_readable(i->memblockq)) return; sink_notify(i->sink); @@ -64,3 +67,16 @@ void input_stream_kill(struct input_stream*i) { if (i->kill) i->kill(i, i->kill_userdata); } + +void input_stream_set_notify_callback(struct input_stream *i, void (*notify)(struct input_stream*i, void *userdata), void *userdata) { + assert(i && notify); + + i->notify = notify; + i->notify_userdata = userdata; +} + +void input_stream_notify(struct input_stream *i) { + assert(i); + if (i->notify) + i->notify(i, i->notify_userdata); +} diff --git a/src/inputstream.h b/src/inputstream.h index a258c3d14..544c33188 100644 --- a/src/inputstream.h +++ b/src/inputstream.h @@ -18,6 +18,9 @@ struct input_stream { void (*kill)(struct input_stream* i, void *userdata); void *kill_userdata; + + void (*notify)(struct input_stream*i, void *userdata); + void *notify_userdata; }; struct input_stream* input_stream_new(struct sink *s, struct sample_spec *spec, const char *name); @@ -31,10 +34,17 @@ void input_stream_notify_sink(struct input_stream *i); /* The registrant of the input stream should call this function to set a * callback function which is called when destruction of the input stream is * requested */ -void input_stream_set_kill_callback(struct input_stream *c, void (*kill)(struct input_stream*i, void *userdata), void *userdata); +void input_stream_set_kill_callback(struct input_stream *i, void (*kill)(struct input_stream*i, void *userdata), void *userdata); /* Code that didn't create the input stream should call this function to * request destruction of it */ -void input_stream_kill(struct input_stream *c); +void input_stream_kill(struct input_stream *i); + +/* Notify the code that created this input stream that some data has + * been removed from the memblockq */ +void input_stream_set_notify_callback(struct input_stream *i, void (*notify)(struct input_stream*i, void *userdata), void *userdata); + +void input_stream_notify(struct input_stream *i); + #endif diff --git a/src/main.c b/src/main.c index 436dd30ba..d54bee0a5 100644 --- a/src/main.c +++ b/src/main.c @@ -29,8 +29,9 @@ int main(int argc, char *argv[]) { mainloop_source_new_signal(m, SIGINT, signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - module_load(c, "sink-pipe", NULL); - module_load(c, "protocol-simple-tcp", NULL); + module_load(c, "module-oss", NULL); + module_load(c, "module-pipe-sink", NULL); + module_load(c, "module-simple-protocol-tcp", NULL); mainloop_run(m); diff --git a/src/memblockq.c b/src/memblockq.c index 6437dd5b3..b25adc654 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -1,3 +1,4 @@ +#include #include #include @@ -14,9 +15,10 @@ struct memblockq { size_t total_length; size_t maxlength; size_t base; + size_t prebuf; }; -struct memblockq* memblockq_new(size_t maxlength, size_t base) { +struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { struct memblockq* bq; assert(maxlength && base); @@ -27,6 +29,11 @@ struct memblockq* memblockq_new(size_t maxlength, size_t base) { bq->total_length = 0; bq->base = base; bq->maxlength = ((maxlength+base-1)/base)*base; + bq->prebuf = prebuf == (size_t) -1 ? bq->maxlength/2 : prebuf; + + if (bq->prebuf > bq->maxlength) + bq->prebuf = bq->maxlength; + assert(bq->maxlength >= base); return bq; } @@ -72,9 +79,11 @@ void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta) int memblockq_peek(struct memblockq* bq, struct memchunk *chunk) { assert(bq && chunk); - if (!bq->blocks) + if (!bq->blocks || bq->total_length < bq->prebuf) return -1; + bq->prebuf = 0; + *chunk = bq->blocks->chunk; memblock_ref(chunk->memblock); return 0; @@ -85,9 +94,11 @@ int memblockq_pop(struct memblockq* bq, struct memchunk *chunk) { assert(bq && chunk); - if (!bq->blocks) + if (!bq->blocks || bq->total_length < bq->prebuf) return -1; + bq->prebuf = 0; + q = bq->blocks; bq->blocks = bq->blocks->next; @@ -138,6 +149,8 @@ void memblockq_shorten(struct memblockq *bq, size_t length) { if (bq->total_length <= length) return; + fprintf(stderr, "Warning! memblockq_shorten()\n"); + l = bq->total_length - length; l /= bq->base; l *= bq->base; @@ -151,8 +164,15 @@ void memblockq_empty(struct memblockq *bq) { memblockq_shorten(bq, 0); } -int memblockq_is_empty(struct memblockq *bq) { +int memblockq_is_readable(struct memblockq *bq) { assert(bq); - return bq->total_length < bq->base; + return bq->total_length >= bq->prebuf; +} + +int memblockq_is_writable(struct memblockq *bq, size_t length) { + assert(bq); + + assert(length <= bq->maxlength); + return bq->total_length + length <= bq->maxlength; } diff --git a/src/memblockq.h b/src/memblockq.h index 75c5e59ee..48050d49d 100644 --- a/src/memblockq.h +++ b/src/memblockq.h @@ -7,7 +7,7 @@ struct memblockq; -struct memblockq* memblockq_new(size_t maxlength, size_t base); +struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf); void memblockq_free(struct memblockq* bq); void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta); @@ -19,6 +19,7 @@ void memblockq_drop(struct memblockq *bq, size_t length); void memblockq_shorten(struct memblockq *bq, size_t length); void memblockq_empty(struct memblockq *bq); -int memblockq_is_empty(struct memblockq *bq); +int memblockq_is_readable(struct memblockq *bq); +int memblockq_is_writable(struct memblockq *bq, size_t length); #endif diff --git a/src/module-oss.c b/src/module-oss.c index b2b106b41..7a1482e7f 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -1,4 +1,5 @@ -#include +#include +#include #include #include #include @@ -22,7 +23,7 @@ struct userdata { struct memchunk memchunk, silence; - uint32_t fragment_size; + uint32_t in_fragment_size, out_fragment_size, sample_size; }; static void do_write(struct userdata *u) { @@ -34,7 +35,7 @@ static void do_write(struct userdata *u) { return; if (!u->memchunk.length) { - if (sink_render(u->sink, fragment_size, &u->memchunk) < 0) + if (sink_render(u->sink, u->out_fragment_size, &u->memchunk) < 0) memchunk = &u->silence; else memchunk = &u->memchunk; @@ -68,15 +69,15 @@ static void do_read(struct userdata *u) { if (!iochannel_is_readable(u->io)) return; - memchunk.memblock = memblock_new(u->fragment_size); + memchunk.memblock = memblock_new(u->in_fragment_size); assert(memchunk.memblock); - if ((r = iochannel_read(u->io, memchunk.memblock->data, memchunk->memblock->length)) < 0) { + if ((r = iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { memblock_unref(memchunk.memblock); fprintf(stderr, "read() failed: %s\n", strerror(errno)); return; } - assert(r < memchunk->memblock->length); + assert(r <= memchunk.memblock->length); memchunk.length = memchunk.memblock->length = r; memchunk.index = 0; @@ -92,17 +93,17 @@ static void io_callback(struct iochannel *io, void*userdata) { } int module_init(struct core *c, struct module*m) { + struct audio_buf_info info; struct userdata *u = NULL; - struct stat st; char *p; int fd = -1; - int format, channels, speed, frag_size; - int m; - const static struct sample_spec ss; + int format, channels, speed, frag_size, in_frag_size, out_frag_size; + int mode; + struct sample_spec ss; assert(c && m); p = m->argument ? m->argument : "/dev/dsp"; - if ((fd = open(p, m = O_RDWR)) >= 0) { + if ((fd = open(p, mode = O_RDWR)) >= 0) { int caps; ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); @@ -119,16 +120,16 @@ int module_init(struct core *c, struct module*m) { } if (fd < 0) { - if ((fd = open(p, m = O_WRONLY)) < 0) { - if ((fd = open(p, m = O_RDONLY)) < 0) { + if ((fd = open(p, mode = O_WRONLY)) < 0) { + if ((fd = open(p, mode = O_RDONLY)) < 0) { fprintf(stderr, "open('%s'): %s\n", p, strerror(errno)); goto fail; } } } - - frags = 0x7fff0000 | (10 << 16); /* 1024 bytes fragment size */ - if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frags) < 0) { + + frag_size = ((int) 0x7ffff << 4) | 10; /* nfrags = 4; frag_size = 2^10 */ + if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag_size) < 0) { fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); goto fail; } @@ -165,25 +166,35 @@ int module_init(struct core *c, struct module*m) { assert(speed); ss.rate = speed; - if (ioctl(fd, SNCTL_DSP_GETBLKSIZE, &frag_size) < 0) { + if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) { fprintf(stderr, "SNDCTL_DSP_GETBLKSIZE: %s\n", strerror(errno)); goto fail; } - assert(frag_size); - + in_frag_size = out_frag_size = frag_size; + + if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { + fprintf(stderr, "INPUT: %u fragments of size %u.\n", info.fragstotal, info.fragsize); + in_frag_size = info.fragsize; + } + + if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { + fprintf(stderr, "OUTUT: %u fragments of size %u.\n", info.fragstotal, info.fragsize); + out_frag_size = info.fragsize; + } + u = malloc(sizeof(struct userdata)); assert(u); u->core = c; - if (m != O_RDONLY) { + if (mode != O_RDONLY) { u->sink = sink_new(c, "dsp", &ss); assert(u->sink); } else u->sink = NULL; - if (m != O_WRONLY) { + if (mode != O_WRONLY) { u->source = source_new(c, "dsp", &ss); assert(u->source); } else @@ -197,11 +208,13 @@ int module_init(struct core *c, struct module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; + u->sample_size = sample_size(&ss); - u->fragment_size = frag_size; - u->silence.memblock = memblock_new(u->fragment_size); - assert(u->silence); - u->silence.length = u->fragment_size; + u->out_fragment_size = out_frag_size; + u->in_fragment_size = in_frag_size; + u->silence.memblock = memblock_new(u->silence.length = u->out_fragment_size); + assert(u->silence.memblock); + silence(u->silence.memblock, &ss); u->silence.index = 0; m->userdata = u; diff --git a/src/outputstream.c b/src/outputstream.c index c6681d293..c3f68a0ee 100644 --- a/src/outputstream.c +++ b/src/outputstream.c @@ -17,7 +17,7 @@ struct output_stream* output_stream_new(struct source *s, struct sample_spec *sp o->kill = NULL; o->kill_userdata = NULL; - o->memblockq = memblockq_new(bytes_per_second(spec)*5, sample_size(spec)); + o->memblockq = memblockq_new(bytes_per_second(spec)*5, sample_size(spec), (size_t) -1); assert(o->memblockq); assert(s->core); diff --git a/src/protocol-simple.c b/src/protocol-simple.c index ec121faa1..1c462b397 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -66,53 +66,73 @@ static void client_kill_cb(struct client *client, void*userdata) { destroy_connection(c); } +static int do_read(struct connection *c) { + struct memchunk chunk; + ssize_t r; + + if (!iochannel_is_readable(c->io)) + return 0; + + if (!c->istream || !memblockq_is_writable(c->istream->memblockq, BUFSIZE)) + return 0; + + chunk.memblock = memblock_new(BUFSIZE); + assert(chunk.memblock); + + if ((r = iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) { + fprintf(stderr, "read(): %s\n", r == 0 ? "EOF" : strerror(errno)); + memblock_unref(chunk.memblock); + return -1; + } + + chunk.memblock->length = r; + chunk.length = r; + chunk.index = 0; + + memblockq_push(c->istream->memblockq, &chunk, 0); + input_stream_notify_sink(c->istream); + memblock_unref(chunk.memblock); + return 0; +} + +static int do_write(struct connection *c) { + struct memchunk chunk; + ssize_t r; + + if (!iochannel_is_writable(c->io)) + return 0; + + if (!c->ostream) + return 0; + + memblockq_peek(c->ostream->memblockq, &chunk); + assert(chunk.memblock && chunk.length); + + if ((r = iochannel_write(c->io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { + fprintf(stderr, "write(): %s\n", strerror(errno)); + memblock_unref(chunk.memblock); + return -1; + } + + memblockq_drop(c->ostream->memblockq, r); + memblock_unref(chunk.memblock); + return 0; +} + static void io_callback(struct iochannel*io, void *userdata) { struct connection *c = userdata; - assert(io && c); + assert(io && c && c->io == io); - if (c->istream && iochannel_is_readable(io)) { - struct memchunk chunk; - ssize_t r; + if (do_read(c) < 0 || do_write(c) < 0) + destroy_connection(c); +} - chunk.memblock = memblock_new(BUFSIZE); - assert(chunk.memblock); - - if ((r = iochannel_read(io, chunk.memblock->data, BUFSIZE)) <= 0) { - fprintf(stderr, "read(): %s\n", r == 0 ? "EOF" : strerror(errno)); - memblock_unref(chunk.memblock); - goto fail; - } - - chunk.memblock->length = r; - chunk.length = r; - chunk.index = 0; - - memblockq_push(c->istream->memblockq, &chunk, 0); - input_stream_notify_sink(c->istream); - memblock_unref(chunk.memblock); - } - - if (c->ostream && iochannel_is_writable(io)) { - struct memchunk chunk; - ssize_t r; - - memblockq_peek(c->ostream->memblockq, &chunk); - assert(chunk.memblock && chunk.length); - - if ((r = iochannel_write(io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { - fprintf(stderr, "write(): %s\n", strerror(errno)); - memblock_unref(chunk.memblock); - goto fail; - } - - memblockq_drop(c->ostream->memblockq, r); - memblock_unref(chunk.memblock); - } - - return; +static void istream_notify_cb(struct input_stream *i, void *userdata) { + struct connection*c = userdata; + assert(i && c && c->istream == i); -fail: - destroy_connection(c); + if (do_read(c) < 0) + destroy_connection(c); } static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { @@ -155,6 +175,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->istream = input_stream_new(sink, &DEFAULT_SAMPLE_SPEC, c->client->name); assert(c->istream); input_stream_set_kill_callback(c->istream, istream_kill_cb, c); + input_stream_set_notify_callback(c->istream, istream_notify_cb, c); } diff --git a/src/sink.c b/src/sink.c index dfe1bcb98..f2d5373d9 100644 --- a/src/sink.c +++ b/src/sink.c @@ -33,8 +33,8 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s s->volume = 0xFF; - s->notify_callback = NULL; - s->userdata = NULL; + s->notify = NULL; + s->notify_userdata = NULL; return s; } @@ -103,6 +103,10 @@ static int do_mix(void *p, uint32_t index, int *del, void*userdata) { assert(chunk.length && chunk.length <= info->chunk->memblock->length - info->chunk->index); add_clip(info->chunk, &chunk, info->spec); + memblock_unref(chunk.memblock); + memblockq_drop(i->memblockq, info->chunk->length); + + input_stream_notify(i); return 0; } @@ -139,6 +143,8 @@ int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *re target->length = l; memblock_unref(chunk.memblock); memblockq_drop(i->memblockq, l); + + input_stream_notify(i); result->memblock = target; result->length = l; @@ -191,6 +197,8 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result) { l = length < result->length ? length : result->length; result->length = l; memblockq_drop(i->memblockq, l); + input_stream_notify(i); + return 0; } @@ -211,15 +219,15 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result) { void sink_notify(struct sink*s) { assert(s); - if (s->notify_callback) - s->notify_callback(s, s->userdata); + if (s->notify) + s->notify(s, s->notify_userdata); } void sink_set_notify_callback(struct sink *s, void (*notify_callback)(struct sink*sink, void *userdata), void *userdata) { assert(s && notify_callback); - s->notify_callback = notify_callback; - s->userdata = userdata; + s->notify = notify_callback; + s->notify_userdata = userdata; } diff --git a/src/sink.h b/src/sink.h index a6f98005a..1678fc75e 100644 --- a/src/sink.h +++ b/src/sink.h @@ -22,8 +22,8 @@ struct sink { uint8_t volume; - void (*notify_callback)(struct sink*sink, void *userdata); - void *userdata; + void (*notify)(struct sink*sink, void *userdata); + void *notify_userdata; }; struct sink* sink_new(struct core *core, const char *name, const struct sample_spec *spec); diff --git a/src/todo b/src/todo new file mode 100644 index 000000000..d4cc5f18c --- /dev/null +++ b/src/todo @@ -0,0 +1,16 @@ +- mixing +- resampling +- native protocol/library +- oss/mmap +- esound prodocol +- config-parser +-- 0.1 +- future cancellation +- client-ui + +drivers: +- libao +- xmms +- portaudio +- mplayer +- python From 98f41f1e70e66dcfc4c457ae47bffb07ed83947f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 15 Jun 2004 15:17:22 +0000 Subject: [PATCH 0015/1514] minor work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@16 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/inputstream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inputstream.c b/src/inputstream.c index 7ece3b5c9..6bc841acf 100644 --- a/src/inputstream.c +++ b/src/inputstream.c @@ -20,7 +20,7 @@ struct input_stream* input_stream_new(struct sink *s, struct sample_spec *spec, i->notify = NULL; i->notify_userdata = NULL; - i->memblockq = memblockq_new(bytes_per_second(spec)*5, sample_size(spec), (size_t) -1); + i->memblockq = memblockq_new(bytes_per_second(spec)/2, sample_size(spec), (size_t) -1); assert(i->memblockq); assert(s->core); From 78f386ad45dc046d673fca5441dff188a7297059 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 15 Jun 2004 15:18:33 +0000 Subject: [PATCH 0016/1514] more work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@17 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/client.c | 4 + src/core.c | 4 +- src/main.c | 12 +- src/memblock.c | 38 ++++ src/memblock.h | 7 + src/memblockq.c | 2 + src/memblockq.h | 1 + src/module-oss.c | 26 ++- src/module.c | 6 + src/protocol-simple.c | 4 +- src/sample.c | 53 +++-- src/sample.h | 10 +- src/sink.c | 285 +++++++++++-------------- src/sink.h | 13 +- src/{inputstream.c => sinkinput.c} | 0 src/{inputstream.h => sinkinput.h} | 0 src/source.c | 5 + src/{outputstream.c => sourceoutput.c} | 0 src/{outputstream.h => sourceoutput.h} | 0 19 files changed, 269 insertions(+), 201 deletions(-) rename src/{inputstream.c => sinkinput.c} (100%) rename src/{inputstream.h => sinkinput.h} (100%) rename src/{outputstream.c => sourceoutput.c} (100%) rename src/{outputstream.h => sourceoutput.h} (100%) diff --git a/src/client.c b/src/client.c index 3dd37668c..578d51c32 100644 --- a/src/client.c +++ b/src/client.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -19,6 +20,8 @@ struct client *client_new(struct core *core, const char *protocol_name, char *na r = idxset_put(core->clients, c, &c->index); assert(c->index != IDXSET_INVALID && r >= 0); + + fprintf(stderr, "client: created %u \"%s\"\n", c->index, c->name); return c; } @@ -27,6 +30,7 @@ void client_free(struct client *c) { assert(c && c->core); idxset_remove_by_data(c->core->clients, c, NULL); + fprintf(stderr, "client: freed %u \"%s\"\n", c->index, c->name); free(c->name); free(c); } diff --git a/src/core.c b/src/core.c index 0457f4f3e..2e67118a9 100644 --- a/src/core.c +++ b/src/core.c @@ -60,7 +60,7 @@ struct sink* core_get_default_sink(struct core *c) { if (!(sink = idxset_first(c->sinks, &c->default_sink_index))) return NULL; - fprintf(stderr, "Default sink vanished, setting to %u\n", sink->index); + fprintf(stderr, "core: default sink vanished, setting to %u.\n", sink->index); return sink; } @@ -74,6 +74,6 @@ struct source* core_get_default_source(struct core *c) { if (!(source = idxset_first(c->sources, &c->default_source_index))) return NULL; - fprintf(stderr, "Default source vanished, setting to %u\n", source->index); + fprintf(stderr, "core: default source vanished, setting to %u.\n", source->index); return source; } diff --git a/src/main.c b/src/main.c index d54bee0a5..a42eaa828 100644 --- a/src/main.c +++ b/src/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "core.h" #include "mainloop.h" @@ -10,7 +11,7 @@ static void signal_callback(struct mainloop_source *m, int sig, void *userdata) { mainloop_quit(mainloop_source_get_mainloop(m), -1); - fprintf(stderr, "Got signal.\n"); + fprintf(stderr, "main: got signal.\n"); } int main(int argc, char *argv[]) { @@ -29,10 +30,17 @@ int main(int argc, char *argv[]) { mainloop_source_new_signal(m, SIGINT, signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - module_load(c, "module-oss", NULL); + module_load(c, "module-oss", "/dev/dsp1"); module_load(c, "module-pipe-sink", NULL); module_load(c, "module-simple-protocol-tcp", NULL); + + fprintf(stderr, "main: mainloop entry.\n"); + while (mainloop_iterate(m, 1) == 0); +/* fprintf(stderr, "main: %u blocks\n", n_blocks);*/ + fprintf(stderr, "main: mainloop exit.\n"); + + mainloop_run(m); core_free(c); diff --git a/src/memblock.c b/src/memblock.c index 3bef4944f..2d3467697 100644 --- a/src/memblock.c +++ b/src/memblock.c @@ -1,15 +1,22 @@ +#include #include #include #include +#include +#include #include "memblock.h" +unsigned n_blocks = 0; + struct memblock *memblock_new(size_t length) { struct memblock *b = malloc(sizeof(struct memblock)+length); b->type = MEMBLOCK_APPENDED; b->ref = 1; b->length = length; b->data = b+1; + n_blocks++; + timerclear(&b->stamp); return b; } @@ -19,6 +26,8 @@ struct memblock *memblock_new_fixed(void *d, size_t length) { b->ref = 1; b->length = length; b->data = d; + n_blocks++; + timerclear(&b->stamp); return b; } @@ -28,6 +37,8 @@ struct memblock *memblock_new_dynamic(void *d, size_t length) { b->ref = 1; b->length = length; b->data = d; + n_blocks++; + timerclear(&b->stamp); return b; } @@ -45,6 +56,7 @@ void memblock_unref(struct memblock*b) { if (b->type == MEMBLOCK_DYNAMIC) free(b->data); free(b); + n_blocks--; } } @@ -65,3 +77,29 @@ void memblock_unref_fixed(struct memblock *b) { b->type = MEMBLOCK_DYNAMIC; } +void memblock_stamp(struct memblock*b) { + assert(b); + gettimeofday(&b->stamp, NULL); +} + +uint32_t memblock_age(struct memblock*b) { + assert(b); + struct timeval tv; + uint32_t r; + + if (b->stamp.tv_sec == 0) + return (suseconds_t) -1; + + gettimeofday(&tv, NULL); + + /*fprintf(stderr, "memblock: (%lu,%lu) -- (%lu,%lu)\r", b->stamp.tv_sec, b->stamp.tv_usec, tv.tv_sec, tv.tv_usec);*/ + + r = (tv.tv_sec-b->stamp.tv_sec) * 1000000; + + if (tv.tv_usec >= b->stamp.tv_usec) + r += tv.tv_usec - b->stamp.tv_usec; + else + r -= b->stamp.tv_usec - tv.tv_usec; + + return r; +} diff --git a/src/memblock.h b/src/memblock.h index 48e87286d..c0fb6708e 100644 --- a/src/memblock.h +++ b/src/memblock.h @@ -2,6 +2,7 @@ #define foomemblockhfoo #include +#include enum memblock_type { MEMBLOCK_FIXED, MEMBLOCK_APPENDED, MEMBLOCK_DYNAMIC }; @@ -10,6 +11,7 @@ struct memblock { unsigned ref; size_t length; void *data; + struct timeval stamp; }; struct memchunk { @@ -26,6 +28,11 @@ struct memblock* memblock_ref(struct memblock*b); void memblock_unref_fixed(struct memblock*b); +void memblock_stamp(struct memblock*b); +uint32_t memblock_age(struct memblock*b); + #define memblock_assert_exclusive(b) assert((b)->ref == 1) +extern unsigned n_blocks; + #endif diff --git a/src/memblockq.c b/src/memblockq.c index b25adc654..3c0d43267 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -18,6 +18,7 @@ struct memblockq { size_t prebuf; }; + struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { struct memblockq* bq; assert(maxlength && base); @@ -35,6 +36,7 @@ struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { bq->prebuf = bq->maxlength; assert(bq->maxlength >= base); + return bq; } diff --git a/src/memblockq.h b/src/memblockq.h index 48050d49d..25c2f2d40 100644 --- a/src/memblockq.h +++ b/src/memblockq.h @@ -22,4 +22,5 @@ void memblockq_empty(struct memblockq *bq); int memblockq_is_readable(struct memblockq *bq); int memblockq_is_writable(struct memblockq *bq, size_t length); + #endif diff --git a/src/module-oss.c b/src/module-oss.c index 7a1482e7f..07a407d8e 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -31,7 +31,7 @@ static void do_write(struct userdata *u) { ssize_t r; assert(u); - if (!iochannel_is_writable(u->io)) + if (!u->sink || !iochannel_is_writable(u->io)) return; if (!u->memchunk.length) { @@ -66,7 +66,7 @@ static void do_read(struct userdata *u) { ssize_t r; assert(u); - if (!iochannel_is_readable(u->io)) + if (!u->source || !iochannel_is_readable(u->io)) return; memchunk.memblock = memblock_new(u->in_fragment_size); @@ -103,7 +103,7 @@ int module_init(struct core *c, struct module*m) { assert(c && m); p = m->argument ? m->argument : "/dev/dsp"; - if ((fd = open(p, mode = O_RDWR)) >= 0) { + if ((fd = open(p, (mode = O_RDWR)|O_NDELAY)) >= 0) { int caps; ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); @@ -120,15 +120,17 @@ int module_init(struct core *c, struct module*m) { } if (fd < 0) { - if ((fd = open(p, mode = O_WRONLY)) < 0) { - if ((fd = open(p, mode = O_RDONLY)) < 0) { + if ((fd = open(p, (mode = O_WRONLY)|O_NDELAY)) < 0) { + if ((fd = open(p, (mode = O_RDONLY)|O_NDELAY)) < 0) { fprintf(stderr, "open('%s'): %s\n", p, strerror(errno)); goto fail; } } } + + fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); - frag_size = ((int) 0x7ffff << 4) | 10; /* nfrags = 4; frag_size = 2^10 */ + frag_size = ((int) 4 << 16) | 10; /* nfrags = 4; frag_size = 2^10 */ if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag_size) < 0) { fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); goto fail; @@ -174,12 +176,12 @@ int module_init(struct core *c, struct module*m) { in_frag_size = out_frag_size = frag_size; if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { - fprintf(stderr, "INPUT: %u fragments of size %u.\n", info.fragstotal, info.fragsize); + fprintf(stderr, "module-oss: input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); in_frag_size = info.fragsize; } if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { - fprintf(stderr, "OUTUT: %u fragments of size %u.\n", info.fragstotal, info.fragsize); + fprintf(stderr, "module-oss: output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); out_frag_size = info.fragsize; } @@ -239,9 +241,11 @@ void module_done(struct core *c, struct module*m) { memblock_unref(u->memchunk.memblock); if (u->silence.memblock) memblock_unref(u->silence.memblock); - - sink_free(u->sink); - source_free(u->source); + + if (u->sink) + sink_free(u->sink); + if (u->source) + source_free(u->source); iochannel_free(u->io); free(u); } diff --git a/src/module.c b/src/module.c index 62204e4c2..7f2bc218e 100644 --- a/src/module.c +++ b/src/module.c @@ -40,6 +40,9 @@ struct module* module_load(struct core *c, const char *name, const char *argumen assert(c->modules); r = idxset_put(c->modules, m, &m->index); assert(r >= 0 && m->index != IDXSET_INVALID); + + fprintf(stderr, "module: loaded %u \"%s\" with argument \"%s\".\n", m->index, m->name, m->argument); + return m; fail: @@ -61,6 +64,9 @@ static void module_free(struct module *m) { m->done(m->core, m); lt_dlclose(m->dl); + + fprintf(stderr, "module: unloaded %u \"%s\".\n", m->index, m->name); + free(m->name); free(m->argument); free(m); diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 1c462b397..d34a5d021 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -78,13 +78,15 @@ static int do_read(struct connection *c) { chunk.memblock = memblock_new(BUFSIZE); assert(chunk.memblock); + + memblock_stamp(chunk.memblock); if ((r = iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) { fprintf(stderr, "read(): %s\n", r == 0 ? "EOF" : strerror(errno)); memblock_unref(chunk.memblock); return -1; } - + chunk.memblock->length = r; chunk.length = r; chunk.index = 0; diff --git a/src/sample.c b/src/sample.c index 2e46eac76..6a0002282 100644 --- a/src/sample.c +++ b/src/sample.c @@ -33,24 +33,6 @@ struct memblock *silence(struct memblock* b, struct sample_spec *spec) { return b; } -void add_clip(struct memchunk *target, struct memchunk *chunk, struct sample_spec *spec) { - int16_t *p, *d; - size_t i; - assert(target && target->memblock && chunk && chunk->memblock && spec); - assert(spec->format == SAMPLE_S16NE); - assert((target->length & 1) == 0); - - d = target->memblock->data + target->index; - p = chunk->memblock->data + chunk->index; - - for (i = 0; i < target->length && i < chunk->length; i++) { - int32_t r = (int32_t) *d + (int32_t) *p; - if (r < -0x8000) r = 0x8000; - if (r > 0x7FFF) r = 0x7FFF; - *d = (int16_t) r; - } -} - size_t sample_size(struct sample_spec *spec) { assert(spec); size_t b = 1; @@ -78,3 +60,38 @@ size_t bytes_per_second(struct sample_spec *spec) { return spec->rate*sample_size(spec); } +size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct sample_spec *spec) { + unsigned c, d; + assert(chunks && target && spec); + assert(spec->format == SAMPLE_S16NE); + + for (d = 0;; d += sizeof(int16_t)) { + int32_t sum = 0; + + if (d >= length) + return d; + + for (c = 0; c < nchannels; c++) { + int32_t v; + uint8_t volume = channels[c].volume; + + if (d >= channels[c].chunk.length) + return d; + + if (volume == 0) + v = 0; + else { + v = *((int16_t*) (channels[c].chunk->memblock->data + channels[c].chunk->index + d)); + + if (volume != 0xFF) + v = v*volume/0xFF; + } + + sum += v; + } + + if (sum < -0x8000) sum = -0x8000; + if (sum > 0x7FFF) sum = 0x7FFF; + *(data++) = sum; + } +} diff --git a/src/sample.h b/src/sample.h index ecbe33f28..651788bae 100644 --- a/src/sample.h +++ b/src/sample.h @@ -27,7 +27,15 @@ struct sample_spec { extern struct sample_spec default_sample_spec; struct memblock *silence(struct memblock* b, struct sample_spec *spec); -void add_clip(struct memchunk *target, struct memchunk *chunk, struct sample_spec *spec); + + +struct mix_info { + struct memchunk chunk; + uint8_t volume; + void *userdata; +}; + +size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct sample_spec *spec) { size_t bytes_per_second(struct sample_spec *spec); size_t sample_size(struct sample_spec *spec); diff --git a/src/sink.c b/src/sink.c index f2d5373d9..82cde8f29 100644 --- a/src/sink.c +++ b/src/sink.c @@ -21,7 +21,7 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s s->core = core; s->sample_spec = *spec; - s->input_streams = idxset_new(NULL, NULL); + s->inputs = idxset_new(NULL, NULL); if (name) { n = malloc(strlen(name)+9); @@ -36,186 +36,32 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s s->notify = NULL; s->notify_userdata = NULL; + fprintf(stderr, "sink: created %u \"%s\".\n", s->index, s->name); + return s; } void sink_free(struct sink *s) { - struct input_stream *i, *j = NULL; + struct sink_input *i, *j = NULL; assert(s); - while ((i = idxset_first(s->input_streams, NULL))) { - assert(i != j); - input_stream_kill(i); + while ((i = idxset_first(s->inputs, NULL))) { + assert(i != j && i->kill); + i->kill(i); j = i; } - idxset_free(s->input_streams, NULL, NULL); + + idxset_free(s->inputs, NULL, NULL); idxset_remove_by_data(s->core->sinks, s, NULL); source_free(s->monitor_source); + fprintf(stderr, "sink: freed %u \"%s\"\n", s->index, s->name); + free(s->name); free(s); } -struct pass1_info { - size_t maxlength; - unsigned count; - struct input_stream *last_input_stream; -}; - -static int get_max_length(void *p, uint32_t index, int *del, void*userdata) { - struct memchunk chunk; - struct pass1_info *info = userdata; - struct input_stream*i = p; - assert(info && i); - - if (memblockq_peek(i->memblockq, &chunk) != 0) - return 0; - - assert(chunk.length); - - if (info->maxlength > chunk.length) - info->maxlength = chunk.length; - - info->count++; - info->last_input_stream = i; - - memblock_unref(chunk.memblock); - - return 0; -} - -struct pass2_info { - struct memchunk *chunk; - struct sample_spec *spec; -}; - -static int do_mix(void *p, uint32_t index, int *del, void*userdata) { - struct memchunk chunk; - struct pass2_info *info = userdata; - struct input_stream*i = p; - assert(info && info->chunk && info->chunk->memblock && i && info->spec); - - if (memblockq_peek(i->memblockq, &chunk) != 0) - return 0; - - memblock_assert_exclusive(info->chunk->memblock); - assert(chunk.length && chunk.length <= info->chunk->memblock->length - info->chunk->index); - - add_clip(info->chunk, &chunk, info->spec); - memblock_unref(chunk.memblock); - memblockq_drop(i->memblockq, info->chunk->length); - - input_stream_notify(i); - return 0; -} - -int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *result) { - struct pass1_info pass1_info; - struct pass2_info pass2_info; - assert(s && target && result); - memblock_assert_exclusive(target); - - /* Calculate how many bytes to mix */ - pass1_info.maxlength = target->length; - pass1_info.count = 0; - - idxset_foreach(s->input_streams, get_max_length, &pass1_info); - assert(pass1_info.maxlength); - - /* No data to mix */ - if (pass1_info.count == 0) - return -1; - - /* A shortcut if only a single input stream is connected */ - if (pass1_info.count == 1) { - struct input_stream *i = pass1_info.last_input_stream; - struct memchunk chunk; - size_t l; - - assert(i); - - if (memblockq_peek(i->memblockq, &chunk) != 0) - return -1; - - l = target->length < chunk.length ? target->length : chunk.length; - memcpy(target->data, result->memblock+result->index, l); - target->length = l; - memblock_unref(chunk.memblock); - memblockq_drop(i->memblockq, l); - - input_stream_notify(i); - - result->memblock = target; - result->length = l; - result->index = 0; - return 0; - } - - /* Do the real mixing */ - result->memblock = silence(target, &s->sample_spec); - result->index = 0; - result->length = pass1_info.maxlength; - pass2_info.chunk = result; - pass2_info.spec = &s->sample_spec; - idxset_foreach(s->input_streams, do_mix, &pass2_info); - - assert(s->monitor_source); - source_post(s->monitor_source, result); - - return 0; -} - -int sink_render(struct sink*s, size_t length, struct memchunk *result) { - struct pass1_info pass1_info; - struct pass2_info pass2_info; - assert(s && result); - - if (!length) - length = (size_t) -1; - - /* Calculate how many bytes to mix */ - pass1_info.maxlength = length; - pass1_info.count = 0; - - idxset_foreach(s->input_streams, get_max_length, &pass1_info); - assert(pass1_info.maxlength); - - /* No data to mix */ - if (pass1_info.count == 0) - return -1; - - if (pass1_info.count == 1) { - struct input_stream *i = pass1_info.last_input_stream; - size_t l; - - assert(i); - - if (memblockq_peek(i->memblockq, result) != 0) - return -1; - - l = length < result->length ? length : result->length; - result->length = l; - memblockq_drop(i->memblockq, l); - input_stream_notify(i); - - return 0; - } - - /* Do the mixing */ - result->memblock = silence(memblock_new(result->length), &s->sample_spec); - result->index = 0; - result->length = pass1_info.maxlength; - pass2_info.chunk = result; - pass2_info.spec = &s->sample_spec; - idxset_foreach(s->input_streams, do_mix, &pass2_info); - - assert(s->monitor_source); - - source_post(s->monitor_source, result); - return 0; -} - void sink_notify(struct sink*s) { assert(s); @@ -230,4 +76,113 @@ void sink_set_notify_callback(struct sink *s, void (*notify_callback)(struct sin s->notify_userdata = userdata; } +static unsigned fill_mix_info(struct sink *s, struct mix_info *info, unsigned maxinfo) { + uint32_t index = IDXSET_ANY; + struct sink_input *i; + unsigned n; + + assert(s && info); + while (maxinfo > 0 && i = idxset_rrobin(s->inputs, &index)) { + assert(i->peek); + if (i->peek(i, &info->chunk, &info->volume) < 0) + continue; + + assert(info->chunk.memblock && info->chunk.memblock->data && info->chunk.length); + info->userdata = i; + + info++; + maxinfo--; + n++; + } + + return n; +} + +static void inputs_drop(struct sink *s, struct mix_info *info, unsigned maxinfo, size_t length) { + assert(s && info); + + for (; maxinfo > 0; maxinfo--, info++) { + struct sink_input *i = info->userdata; + assert(i && info->chunk.memblock); + + memblock_unref(info->chunk.memblock); + assert(i->drop); + i->drop(i, length); + } +} + +int sink_render(struct sink*s, size_t length, struct memchunk *result) { + struct mix_info info[MAX_MIX_CHANNELS]; + unsigned n; + size_t l; + assert(s && length && result); + + n = fill_mix_info(s, info, MAX_MIX_CHANNELS); + + if (n <= 0) + return -1; + + if (n == 1) { + struct sink_info *i = info[0].userdata; + assert(i && b); + *result = info[0].chunk; + memblock_ref(result->memblock); + + if (result->length > length) + result->length = length; + + l = result->length; + } else { + result->memblock = memblock_new(length); + assert(result->memblock); + + result->length = l = mix_chunks(info, n, result->memblock->data, length, &s->sample_spec); + result->index = 0; + + assert(l); + } + + inputs_drop(s, info, n, l); + return 0; +} + +int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *result) { + struct mix_info info[MAX_MIX_CHANNELS]; + unsigned n; + size_t l; + assert(s && target && target->length && target->data && result); + + n = fill_mix_info(s, info, MAX_MIX_CHANNELS); + + if (n <= 0) + return -1; + + if (n == 1) { + struct sink_info *i = info[0].userdata; + assert(i && b); + + l = target->length; + if (l > info[0].chunk.length) + l = info[0].chunk.length; + + result->memblock = target; + memcpy(target->data, info[0].chunk.memblock->data + info[0].chunk.index, l); + result->length = target->length = l; + result->index = 0; + + if (result->length > length) + result->length = length; + + l = result->length; + } else { + + result->memblock = target; + result->length = l = mix_chunks(info, n, target->data, target->length, &s->sample_spec); + result->index = 0; + assert(l); + } + + inputs_drop(s, info, n, l); + return 0; +} diff --git a/src/sink.h b/src/sink.h index 1678fc75e..bd43d49de 100644 --- a/src/sink.h +++ b/src/sink.h @@ -10,13 +10,24 @@ struct sink; #include "idxset.h" #include "source.h" + +struct sink_input { + int (*peek) (struct sink_input *i, struct memchunk *chunk, uint8_t *volume); + void (*drop) (struct sink_input *i, size_t length); + void (*kill) (struct sink_input *i); + + void *userdata; + int index; + struct sink *sink; +}; + struct sink { char *name; uint32_t index; struct core *core; struct sample_spec sample_spec; - struct idxset *input_streams; + struct idxset *inputs; struct source *monitor_source; diff --git a/src/inputstream.c b/src/sinkinput.c similarity index 100% rename from src/inputstream.c rename to src/sinkinput.c diff --git a/src/inputstream.h b/src/sinkinput.h similarity index 100% rename from src/inputstream.h rename to src/sinkinput.h diff --git a/src/source.c b/src/source.c index 2d5e9bbde..a7fc9a64f 100644 --- a/src/source.c +++ b/src/source.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -24,6 +25,8 @@ struct source* source_new(struct core *core, const char *name, const struct samp s->link_change_callback = NULL; s->userdata = NULL; + fprintf(stderr, "source: created %u \"%s\"\n", s->index, s->name); + return s; } @@ -40,6 +43,8 @@ void source_free(struct source *s) { idxset_remove_by_data(s->core->sources, s, NULL); + fprintf(stderr, "source: freed %u \"%s\"\n", s->index, s->name); + free(s->name); free(s); } diff --git a/src/outputstream.c b/src/sourceoutput.c similarity index 100% rename from src/outputstream.c rename to src/sourceoutput.c diff --git a/src/outputstream.h b/src/sourceoutput.h similarity index 100% rename from src/outputstream.h rename to src/sourceoutput.h From b24546bedee168778a7aef11200dfb0378dfae43 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 15 Jun 2004 17:05:03 +0000 Subject: [PATCH 0017/1514] cleanup git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@18 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- src/client.c | 16 ++-- src/client.h | 15 ++-- src/core.c | 12 +-- src/core.h | 2 +- src/idxset.c | 21 +++++- src/idxset.h | 2 + src/module-pipe-sink.c | 11 +-- src/protocol-simple.c | 165 ++++++++++++++++++++++++++--------------- src/sample.c | 15 +++- src/sample.h | 2 +- src/sink.c | 49 +++++------- src/sink.h | 20 +---- src/sinkinput.c | 62 ++++------------ src/sinkinput.h | 40 +++------- src/source.c | 35 +++++---- src/source.h | 8 +- src/sourceoutput.c | 38 ++++------ src/sourceoutput.h | 23 +++--- 19 files changed, 261 insertions(+), 277 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index f09538462..40e2039d4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,7 @@ pkglib_LTLIBRARIES=libprotocol-simple.la module-simple-protocol-tcp.la \ polypaudio_SOURCES = idxset.c queue.c strbuf.c mainloop.c \ memblock.c sample.c memblockq.c client.c \ - core.c main.c outputstream.c inputstream.c source.c sink.c \ + core.c main.c sourceoutput.c sinkinput.c source.c sink.c \ module.c polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(LIBLTDL) diff --git a/src/client.c b/src/client.c index 578d51c32..1b84c6bf5 100644 --- a/src/client.c +++ b/src/client.c @@ -12,11 +12,12 @@ struct client *client_new(struct core *core, const char *protocol_name, char *na c = malloc(sizeof(struct client)); assert(c); - c->protocol_name = protocol_name; c->name = name ? strdup(name) : NULL; - c->kill = NULL; - c->kill_userdata = NULL; c->core = core; + c->protocol_name = protocol_name; + + c->kill = NULL; + c->userdata = NULL; r = idxset_put(core->clients, c, &c->index); assert(c->index != IDXSET_INVALID && r >= 0); @@ -35,14 +36,9 @@ void client_free(struct client *c) { free(c); } -void client_set_kill_callback(struct client *c, void (*kill)(struct client *c, void *userdata), void *userdata) { - assert(c && kill); - c->kill = kill; - c->kill_userdata = userdata; -} - void client_kill(struct client *c) { assert(c); - c->kill(c, c->kill_userdata); + if (c->kill) + c->kill(c); } diff --git a/src/client.h b/src/client.h index 8d9e519c0..556b5fb3d 100644 --- a/src/client.h +++ b/src/client.h @@ -4,15 +4,15 @@ #include "core.h" struct client { - char *name; uint32_t index; - + + char *name; + struct core *core; const char *protocol_name; - void *kill_userdata; - void (*kill)(struct client *c, void *userdata); + void (*kill)(struct client *c); - struct core *core; + void *userdata; }; struct client *client_new(struct core *c, const char *protocol_name, char *name); @@ -20,11 +20,6 @@ struct client *client_new(struct core *c, const char *protocol_name, char *name) /* This function should be called only by the code that created the client */ void client_free(struct client *c); -/* The registrant of the client should call this function to set a - * callback function which is called when destruction of the client is - * requested */ -void client_set_kill_callback(struct client *c, void (*kill)(struct client *c, void *userdata), void *userdata); - /* Code that didn't create the client should call this function to * request destruction of the client */ void client_kill(struct client *c); diff --git a/src/core.c b/src/core.c index 2e67118a9..0bc13a5b9 100644 --- a/src/core.c +++ b/src/core.c @@ -16,8 +16,8 @@ struct core* core_new(struct mainloop *m) { c->clients = idxset_new(NULL, NULL); c->sinks = idxset_new(NULL, NULL); c->sources = idxset_new(NULL, NULL); - c->output_streams = idxset_new(NULL, NULL); - c->input_streams = idxset_new(NULL, NULL); + c->source_outputs = idxset_new(NULL, NULL); + c->sink_inputs = idxset_new(NULL, NULL); c->default_source_index = c->default_sink_index = IDXSET_INVALID; @@ -41,11 +41,11 @@ void core_free(struct core *c) { assert(idxset_isempty(c->sources)); idxset_free(c->sources, NULL, NULL); - assert(idxset_isempty(c->output_streams)); - idxset_free(c->output_streams, NULL, NULL); + assert(idxset_isempty(c->source_outputs)); + idxset_free(c->source_outputs, NULL, NULL); - assert(idxset_isempty(c->input_streams)); - idxset_free(c->input_streams, NULL, NULL); + assert(idxset_isempty(c->sink_inputs)); + idxset_free(c->sink_inputs, NULL, NULL); free(c); }; diff --git a/src/core.h b/src/core.h index 649c9dbad..a8a140b89 100644 --- a/src/core.h +++ b/src/core.h @@ -7,7 +7,7 @@ struct core { struct mainloop *mainloop; - struct idxset *clients, *sinks, *sources, *output_streams, *input_streams, *modules; + struct idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules; uint32_t default_source_index, default_sink_index; }; diff --git a/src/idxset.c b/src/idxset.c index 4442190d7..ea609f601 100644 --- a/src/idxset.c +++ b/src/idxset.c @@ -291,9 +291,7 @@ void* idxset_rrobin(struct idxset *s, uint32_t *index) { if (!e) return NULL; - if (index) - *index = e->index; - + *index = e->index; return e->data; } @@ -308,6 +306,22 @@ void* idxset_first(struct idxset *s, uint32_t *index) { return s->iterate_list_head->data; } +void *idxset_next(struct idxset *s, uint32_t *index) { + struct idxset_entry **a, *e = NULL; + assert(s && index); + + if ((a = array_index(s, *index)) && *a) + e = (*a)->iterate_next; + + if (e) { + *index = e->index; + return e->data; + } else { + *index = IDXSET_INVALID; + return NULL; + } +} + int idxset_foreach(struct idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata) { struct idxset_entry *e; @@ -341,3 +355,4 @@ int idxset_isempty(struct idxset *s) { assert(s); return s->n_entries == 0; } + diff --git a/src/idxset.h b/src/idxset.h index fdcb7b54b..90b9d2478 100644 --- a/src/idxset.h +++ b/src/idxset.h @@ -26,10 +26,12 @@ void* idxset_rrobin(struct idxset *s, uint32_t *index); /* Return the oldest entry in the idxset */ void* idxset_first(struct idxset *s, uint32_t *index); +void *idxset_next(struct idxset *s, uint32_t *index); int idxset_foreach(struct idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata); unsigned idxset_ncontents(struct idxset*s); int idxset_isempty(struct idxset *s); + #endif diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index e63a7a86f..c0a903e94 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -52,9 +52,9 @@ static void do_write(struct userdata *u) { } } -static void notify_callback(struct sink*s, void *userdata) { - struct userdata *u = userdata; - assert(u); +static void notify_cb(struct sink*s) { + struct userdata *u = s->userdata; + assert(s && u); if (iochannel_is_writable(u->io)) mainloop_source_enable(u->mainloop_source, 1); @@ -77,7 +77,7 @@ int module_init(struct core *c, struct module*m) { struct stat st; char *p; int fd = -1; - const static struct sample_spec ss = { + static const struct sample_spec ss = { .format = SAMPLE_S16NE, .rate = 44100, .channels = 2, @@ -110,7 +110,8 @@ int module_init(struct core *c, struct module*m) { u->core = c; u->sink = sink_new(c, "fifo", &ss); assert(u->sink); - sink_set_notify_callback(u->sink, notify_callback, u); + u->sink->notify = notify_cb; + u->sink->userdata = u; u->io = iochannel_new(c->mainloop, -1, fd); assert(u->io); diff --git a/src/protocol-simple.c b/src/protocol-simple.c index d34a5d021..1803936e4 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -5,17 +5,18 @@ #include #include -#include "inputstream.h" -#include "outputstream.h" +#include "sinkinput.h" +#include "sourceoutput.h" #include "protocol-simple.h" #include "client.h" struct connection { struct protocol_simple *protocol; struct iochannel *io; - struct input_stream *istream; - struct output_stream *ostream; + struct sink_input *sink_input; + struct source_output *source_output; struct client *client; + struct memblockq *input_memblockq, *output_memblockq; }; struct protocol_simple { @@ -31,14 +32,18 @@ static void free_connection(void *data, void *userdata) { struct connection *c = data; assert(data); - if (c->istream) - input_stream_free(c->istream); - if (c->ostream) - output_stream_free(c->ostream); - - client_free(c->client); - - iochannel_free(c->io); + if (c->sink_input) + sink_input_free(c->sink_input); + if (c->source_output) + source_output_free(c->source_output); + if (c->client) + client_free(c->client); + if (c->io) + iochannel_free(c->io); + if (c->input_memblockq) + memblockq_free(c->input_memblockq); + if (c->output_memblockq) + memblockq_free(c->output_memblockq); free(c); } @@ -48,24 +53,6 @@ static void destroy_connection(struct connection *c) { free_connection(c, NULL); } -static void istream_kill_cb(struct input_stream *i, void *userdata) { - struct connection *c = userdata; - assert(i && c); - destroy_connection(c); -} - -static void ostream_kill_cb(struct output_stream *o, void *userdata) { - struct connection *c = userdata; - assert(o && c); - destroy_connection(c); -} - -static void client_kill_cb(struct client *client, void*userdata) { - struct connection *c= userdata; - assert(client && c); - destroy_connection(c); -} - static int do_read(struct connection *c) { struct memchunk chunk; ssize_t r; @@ -73,7 +60,7 @@ static int do_read(struct connection *c) { if (!iochannel_is_readable(c->io)) return 0; - if (!c->istream || !memblockq_is_writable(c->istream->memblockq, BUFSIZE)) + if (!c->sink_input || !memblockq_is_writable(c->input_memblockq, BUFSIZE)) return 0; chunk.memblock = memblock_new(BUFSIZE); @@ -90,10 +77,11 @@ static int do_read(struct connection *c) { chunk.memblock->length = r; chunk.length = r; chunk.index = 0; - - memblockq_push(c->istream->memblockq, &chunk, 0); - input_stream_notify_sink(c->istream); + + assert(c->input_memblockq); + memblockq_push(c->input_memblockq, &chunk, 0); memblock_unref(chunk.memblock); + sink_notify(c->sink_input->sink); return 0; } @@ -104,10 +92,11 @@ static int do_write(struct connection *c) { if (!iochannel_is_writable(c->io)) return 0; - if (!c->ostream) + if (!c->source_output) return 0; - memblockq_peek(c->ostream->memblockq, &chunk); + assert(c->output_memblockq); + memblockq_peek(c->output_memblockq, &chunk); assert(chunk.memblock && chunk.length); if ((r = iochannel_write(c->io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { @@ -116,11 +105,63 @@ static int do_write(struct connection *c) { return -1; } - memblockq_drop(c->ostream->memblockq, r); + memblockq_drop(c->output_memblockq, r); memblock_unref(chunk.memblock); return 0; } +/*** sink_input callbacks ***/ + +static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk, uint8_t *volume) { + struct connection*c = i->userdata; + assert(i && c && chunk && volume); + + if (memblockq_peek(c->input_memblockq, chunk) < 0) + return -1; + + *volume = 0xFF; + return 0; +} + +static void sink_input_drop_cb(struct sink_input *i, size_t length) { + struct connection*c = i->userdata; + assert(i && c && length); + + memblockq_drop(c->input_memblockq, length); + + if (do_read(c) < 0) + destroy_connection(c); +} + +static void sink_input_kill_cb(struct sink_input *i) { + assert(i && i->userdata); + destroy_connection((struct connection *) i->userdata); +} + +/*** source_output callbacks ***/ + +static void source_output_push_cb(struct source_output *o, struct memchunk *chunk) { + struct connection *c = o->userdata; + assert(o && c && chunk); + + memblockq_push(c->output_memblockq, chunk, 0); +} + +static void source_output_kill_cb(struct source_output *o) { + assert(o && o->userdata); + destroy_connection((struct connection *) o->userdata); +} + + +/*** client callbacks ***/ + +static void client_kill_cb(struct client *c) { + assert(c && c->userdata); + destroy_connection((struct connection *) c->userdata); +} + +/*** iochannel callbacks ***/ + static void io_callback(struct iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); @@ -129,13 +170,7 @@ static void io_callback(struct iochannel*io, void *userdata) { destroy_connection(c); } -static void istream_notify_cb(struct input_stream *i, void *userdata) { - struct connection*c = userdata; - assert(i && c && c->istream == i); - - if (do_read(c) < 0) - destroy_connection(c); -} +/*** socket_server callbacks */ static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { struct protocol_simple *p = userdata; @@ -145,39 +180,53 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c = malloc(sizeof(struct connection)); assert(c); c->io = io; - c->istream = NULL; - c->ostream = NULL; + c->sink_input = NULL; + c->source_output = NULL; + c->input_memblockq = c->output_memblockq = NULL; c->protocol = p; c->client = client_new(p->core, "SIMPLE", "Client"); assert(c->client); - client_set_kill_callback(c->client, client_kill_cb, c); + c->client->kill = client_kill_cb; + c->client->userdata = c; if (p->mode & PROTOCOL_SIMPLE_RECORD) { struct source *source; + size_t l; if (!(source = core_get_default_source(p->core))) { fprintf(stderr, "Failed to get default source.\n"); goto fail; } - c->ostream = output_stream_new(source, &DEFAULT_SAMPLE_SPEC, c->client->name); - assert(c->ostream); - output_stream_set_kill_callback(c->ostream, ostream_kill_cb, c); + c->source_output = source_output_new(source, &DEFAULT_SAMPLE_SPEC, c->client->name); + assert(c->source_output); + c->source_output->push = source_output_push_cb; + c->source_output->kill = source_output_kill_cb; + c->source_output->userdata = c; + + l = 5*bytes_per_second(&DEFAULT_SAMPLE_SPEC); + c->output_memblockq = memblockq_new(l, sample_size(&DEFAULT_SAMPLE_SPEC), l/2); } if (p->mode & PROTOCOL_SIMPLE_PLAYBACK) { struct sink *sink; + size_t l; if (!(sink = core_get_default_sink(p->core))) { fprintf(stderr, "Failed to get default sink.\n"); goto fail; } - c->istream = input_stream_new(sink, &DEFAULT_SAMPLE_SPEC, c->client->name); - assert(c->istream); - input_stream_set_kill_callback(c->istream, istream_kill_cb, c); - input_stream_set_notify_callback(c->istream, istream_notify_cb, c); + c->sink_input = sink_input_new(sink, &DEFAULT_SAMPLE_SPEC, c->client->name); + assert(c->sink_input); + c->sink_input->peek = sink_input_peek_cb; + c->sink_input->drop = sink_input_drop_cb; + c->sink_input->kill = sink_input_kill_cb; + c->sink_input->userdata = c; + + l = 5*bytes_per_second(&DEFAULT_SAMPLE_SPEC); + c->input_memblockq = memblockq_new(l, sample_size(&DEFAULT_SAMPLE_SPEC), l/2); } @@ -187,13 +236,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us fail: if (c) { - if (c->client) - client_free(c->client); - if (c->istream) - input_stream_free(c->istream); - if (c->ostream) - output_stream_free(c->ostream); - + free_connection(c, NULL); iochannel_free(c->io); free(c); } diff --git a/src/sample.c b/src/sample.c index 6a0002282..21c046285 100644 --- a/src/sample.c +++ b/src/sample.c @@ -60,9 +60,9 @@ size_t bytes_per_second(struct sample_spec *spec) { return spec->rate*sample_size(spec); } -size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct sample_spec *spec) { +size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct sample_spec *spec, uint8_t volume) { unsigned c, d; - assert(chunks && target && spec); + assert(channels && data && length && spec); assert(spec->format == SAMPLE_S16NE); for (d = 0;; d += sizeof(int16_t)) { @@ -81,7 +81,7 @@ size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, si if (volume == 0) v = 0; else { - v = *((int16_t*) (channels[c].chunk->memblock->data + channels[c].chunk->index + d)); + v = *((int16_t*) (channels[c].chunk.memblock->data + channels[c].chunk.index + d)); if (volume != 0xFF) v = v*volume/0xFF; @@ -90,8 +90,15 @@ size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, si sum += v; } + if (volume == 0) + sum = 0; + else if (volume != 0xFF) + sum = sum*volume/0xFF; + if (sum < -0x8000) sum = -0x8000; if (sum > 0x7FFF) sum = 0x7FFF; - *(data++) = sum; + + *((int16_t*) data) = sum; + data += sizeof(int16_t); } } diff --git a/src/sample.h b/src/sample.h index 651788bae..f8ba66983 100644 --- a/src/sample.h +++ b/src/sample.h @@ -35,7 +35,7 @@ struct mix_info { void *userdata; }; -size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct sample_spec *spec) { +size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct sample_spec *spec, uint8_t volume); size_t bytes_per_second(struct sample_spec *spec); size_t sample_size(struct sample_spec *spec); diff --git a/src/sink.c b/src/sink.c index 82cde8f29..951191dd4 100644 --- a/src/sink.c +++ b/src/sink.c @@ -4,7 +4,9 @@ #include #include "sink.h" -#include "inputstream.h" +#include "sinkinput.h" + +#define MAX_MIX_CHANNELS 32 struct sink* sink_new(struct core *core, const char *name, const struct sample_spec *spec) { struct sink *s; @@ -16,9 +18,6 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s assert(s); s->name = name ? strdup(name) : NULL; - r = idxset_put(core->sinks, s, &s->index); - assert(s->index != IDXSET_INVALID && r >= 0); - s->core = core; s->sample_spec = *spec; s->inputs = idxset_new(NULL, NULL); @@ -34,8 +33,11 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s s->volume = 0xFF; s->notify = NULL; - s->notify_userdata = NULL; + s->userdata = NULL; + r = idxset_put(core->sinks, s, &s->index); + assert(s->index != IDXSET_INVALID && r >= 0); + fprintf(stderr, "sink: created %u \"%s\".\n", s->index, s->name); return s; @@ -46,15 +48,14 @@ void sink_free(struct sink *s) { assert(s); while ((i = idxset_first(s->inputs, NULL))) { - assert(i != j && i->kill); - i->kill(i); + assert(i != j); + sink_input_kill(i); j = i; } - idxset_free(s->inputs, NULL, NULL); - - idxset_remove_by_data(s->core->sinks, s, NULL); + source_free(s->monitor_source); + idxset_remove_by_data(s->core->sinks, s, NULL); fprintf(stderr, "sink: freed %u \"%s\"\n", s->index, s->name); @@ -66,24 +67,17 @@ void sink_notify(struct sink*s) { assert(s); if (s->notify) - s->notify(s, s->notify_userdata); -} - -void sink_set_notify_callback(struct sink *s, void (*notify_callback)(struct sink*sink, void *userdata), void *userdata) { - assert(s && notify_callback); - - s->notify = notify_callback; - s->notify_userdata = userdata; + s->notify(s); } static unsigned fill_mix_info(struct sink *s, struct mix_info *info, unsigned maxinfo) { - uint32_t index = IDXSET_ANY; + uint32_t index = IDXSET_INVALID; struct sink_input *i; - unsigned n; + unsigned n = 0; assert(s && info); - while (maxinfo > 0 && i = idxset_rrobin(s->inputs, &index)) { + for (i = idxset_first(s->inputs, &index); maxinfo > 0 && i; i = idxset_next(s->inputs, &index)) { assert(i->peek); if (i->peek(i, &info->chunk, &info->volume) < 0) continue; @@ -125,7 +119,7 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result) { if (n == 1) { struct sink_info *i = info[0].userdata; - assert(i && b); + assert(i); *result = info[0].chunk; memblock_ref(result->memblock); @@ -137,7 +131,7 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result) { result->memblock = memblock_new(length); assert(result->memblock); - result->length = l = mix_chunks(info, n, result->memblock->data, length, &s->sample_spec); + result->length = l = mix_chunks(info, n, result->memblock->data, length, &s->sample_spec, s->volume); result->index = 0; assert(l); @@ -160,7 +154,7 @@ int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *re if (n == 1) { struct sink_info *i = info[0].userdata; - assert(i && b); + assert(i); l = target->length; if (l > info[0].chunk.length) @@ -170,15 +164,10 @@ int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *re memcpy(target->data, info[0].chunk.memblock->data + info[0].chunk.index, l); result->length = target->length = l; result->index = 0; - - if (result->length > length) - result->length = length; - - l = result->length; } else { result->memblock = target; - result->length = l = mix_chunks(info, n, target->data, target->length, &s->sample_spec); + result->length = l = mix_chunks(info, n, target->data, target->length, &s->sample_spec, s->volume); result->index = 0; assert(l); } diff --git a/src/sink.h b/src/sink.h index bd43d49de..ccfa25901 100644 --- a/src/sink.h +++ b/src/sink.h @@ -10,21 +10,10 @@ struct sink; #include "idxset.h" #include "source.h" - -struct sink_input { - int (*peek) (struct sink_input *i, struct memchunk *chunk, uint8_t *volume); - void (*drop) (struct sink_input *i, size_t length); - void (*kill) (struct sink_input *i); - - void *userdata; - int index; - struct sink *sink; -}; - struct sink { - char *name; uint32_t index; - + + char *name; struct core *core; struct sample_spec sample_spec; struct idxset *inputs; @@ -33,8 +22,8 @@ struct sink { uint8_t volume; - void (*notify)(struct sink*sink, void *userdata); - void *notify_userdata; + void (*notify)(struct sink*sink); + void *userdata; }; struct sink* sink_new(struct core *core, const char *name, const struct sample_spec *spec); @@ -44,6 +33,5 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result); int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *result); void sink_notify(struct sink*s); -void sink_set_notify_callback(struct sink *s, void (*notify_callback)(struct sink*sink, void *userdata), void *userdata); #endif diff --git a/src/sinkinput.c b/src/sinkinput.c index 6bc841acf..ae7b27ff7 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -2,81 +2,47 @@ #include #include -#include "inputstream.h" +#include "sinkinput.h" -struct input_stream* input_stream_new(struct sink *s, struct sample_spec *spec, const char *name) { - struct input_stream *i; +struct sink_input* sink_input_new(struct sink *s, struct sample_spec *spec, const char *name) { + struct sink_input *i; int r; assert(s && spec); - i = malloc(sizeof(struct input_stream)); + i = malloc(sizeof(struct sink_input)); assert(i); i->name = name ? strdup(name) : NULL; i->sink = s; i->spec = *spec; + i->peek = NULL; + i->drop = NULL; i->kill = NULL; - i->kill_userdata = NULL; - i->notify = NULL; - i->notify_userdata = NULL; + i->userdata = NULL; - i->memblockq = memblockq_new(bytes_per_second(spec)/2, sample_size(spec), (size_t) -1); - assert(i->memblockq); - assert(s->core); - r = idxset_put(s->core->input_streams, i, &i->index); + r = idxset_put(s->core->sink_inputs, i, &i->index); assert(r == 0 && i->index != IDXSET_INVALID); - r = idxset_put(s->input_streams, i, NULL); + r = idxset_put(s->inputs, i, NULL); assert(r == 0); return i; } -void input_stream_free(struct input_stream* i) { +void sink_input_free(struct sink_input* i) { assert(i); - memblockq_free(i->memblockq); - assert(i->sink && i->sink->core); - idxset_remove_by_data(i->sink->core->input_streams, i, NULL); - idxset_remove_by_data(i->sink->input_streams, i, NULL); + idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL); + idxset_remove_by_data(i->sink->inputs, i, NULL); free(i->name); free(i); } -void input_stream_notify_sink(struct input_stream *i) { - assert(i); - - if (!memblockq_is_readable(i->memblockq)) - return; - - sink_notify(i->sink); -} - -void input_stream_set_kill_callback(struct input_stream *i, void (*kill)(struct input_stream*i, void *userdata), void *userdata) { - assert(i && kill); - i->kill = kill; - i->kill_userdata = userdata; -} - - -void input_stream_kill(struct input_stream*i) { +void sink_input_kill(struct sink_input*i) { assert(i); if (i->kill) - i->kill(i, i->kill_userdata); -} - -void input_stream_set_notify_callback(struct input_stream *i, void (*notify)(struct input_stream*i, void *userdata), void *userdata) { - assert(i && notify); - - i->notify = notify; - i->notify_userdata = userdata; -} - -void input_stream_notify(struct input_stream *i) { - assert(i); - if (i->notify) - i->notify(i, i->notify_userdata); + i->kill(i); } diff --git a/src/sinkinput.h b/src/sinkinput.h index 544c33188..5e71d2108 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -1,5 +1,5 @@ -#ifndef fooinputstreamhfoo -#define fooinputstreamhfoo +#ifndef foosinkinputhfoo +#define foosinkinputhfoo #include @@ -7,44 +7,26 @@ #include "sample.h" #include "memblockq.h" -struct input_stream { - char *name; +struct sink_input { uint32_t index; + char *name; struct sink *sink; struct sample_spec spec; - struct memblockq *memblockq; + int (*peek) (struct sink_input *i, struct memchunk *chunk, uint8_t *volume); + void (*drop) (struct sink_input *i, size_t length); + void (*kill) (struct sink_input *i); - void (*kill)(struct input_stream* i, void *userdata); - void *kill_userdata; - - void (*notify)(struct input_stream*i, void *userdata); - void *notify_userdata; + void *userdata; }; -struct input_stream* input_stream_new(struct sink *s, struct sample_spec *spec, const char *name); -void input_stream_free(struct input_stream* i); - -/* This function notifies the attached sink that new data is available - * in the memblockq */ -void input_stream_notify_sink(struct input_stream *i); - - -/* The registrant of the input stream should call this function to set a - * callback function which is called when destruction of the input stream is - * requested */ -void input_stream_set_kill_callback(struct input_stream *i, void (*kill)(struct input_stream*i, void *userdata), void *userdata); +struct sink_input* sink_input_new(struct sink *s, struct sample_spec *spec, const char *name); +void sink_input_free(struct sink_input* i); /* Code that didn't create the input stream should call this function to * request destruction of it */ -void input_stream_kill(struct input_stream *i); - -/* Notify the code that created this input stream that some data has - * been removed from the memblockq */ -void input_stream_set_notify_callback(struct input_stream *i, void (*notify)(struct input_stream*i, void *userdata), void *userdata); - -void input_stream_notify(struct input_stream *i); +void sink_input_kill(struct sink_input *i); #endif diff --git a/src/source.c b/src/source.c index a7fc9a64f..e01e9f836 100644 --- a/src/source.c +++ b/src/source.c @@ -4,7 +4,7 @@ #include #include "source.h" -#include "outputstream.h" +#include "sourceoutput.h" struct source* source_new(struct core *core, const char *name, const struct sample_spec *spec) { struct source *s; @@ -15,31 +15,31 @@ struct source* source_new(struct core *core, const char *name, const struct samp assert(s); s->name = name ? strdup(name) : NULL; - r = idxset_put(core->sources, s, &s->index); - assert(s->index != IDXSET_INVALID && r >= 0); - s->core = core; s->sample_spec = *spec; - s->output_streams = idxset_new(NULL, NULL); + s->outputs = idxset_new(NULL, NULL); - s->link_change_callback = NULL; + s->notify = NULL; s->userdata = NULL; + r = idxset_put(core->sources, s, &s->index); + assert(s->index != IDXSET_INVALID && r >= 0); + fprintf(stderr, "source: created %u \"%s\"\n", s->index, s->name); return s; } void source_free(struct source *s) { - struct output_stream *o, *j = NULL; + struct source_output *o, *j = NULL; assert(s); - while ((o = idxset_first(s->output_streams, NULL))) { + while ((o = idxset_first(s->outputs, NULL))) { assert(o != j); - output_stream_free(o); + source_output_kill(o); j = o; } - idxset_free(s->output_streams, NULL, NULL); + idxset_free(s->outputs, NULL, NULL); idxset_remove_by_data(s->core->sources, s, NULL); @@ -49,17 +49,24 @@ void source_free(struct source *s) { free(s); } +void source_notify(struct source*s) { + assert(s); + + if (s->notify) + s->notify(s); +} + static int do_post(void *p, uint32_t index, int *del, void*userdata) { struct memchunk *chunk = userdata; - struct output_stream *o = p; - assert(o && o->memblockq && index && del && chunk); + struct source_output *o = p; + assert(o && o->push && index && del && chunk); - memblockq_push(o->memblockq, chunk, 0); + o->push(o, chunk); return 0; } void source_post(struct source*s, struct memchunk *chunk) { assert(s && chunk); - idxset_foreach(s->output_streams, do_post, chunk); + idxset_foreach(s->outputs, do_post, chunk); } diff --git a/src/source.h b/src/source.h index 3beb3f963..1442b9f01 100644 --- a/src/source.h +++ b/src/source.h @@ -10,14 +10,14 @@ struct source; #include "memblock.h" struct source { - char *name; uint32_t index; + char *name; struct core *core; struct sample_spec sample_spec; - struct idxset *output_streams; + struct idxset *outputs; - void (*link_change_callback)(struct source*source, void *userdata); + void (*notify)(struct source*source); void *userdata; }; @@ -27,4 +27,6 @@ void source_free(struct source *s); /* Pass a new memory block to all output streams */ void source_post(struct source*s, struct memchunk *b); +void source_notify(struct source *s); + #endif diff --git a/src/sourceoutput.c b/src/sourceoutput.c index c3f68a0ee..d4e7a50f2 100644 --- a/src/sourceoutput.c +++ b/src/sourceoutput.c @@ -2,56 +2,46 @@ #include #include -#include "outputstream.h" +#include "sourceoutput.h" -struct output_stream* output_stream_new(struct source *s, struct sample_spec *spec, const char *name) { - struct output_stream *o; +struct source_output* source_output_new(struct source *s, struct sample_spec *spec, const char *name) { + struct source_output *o; int r; assert(s && spec); - o = malloc(sizeof(struct output_stream)); + o = malloc(sizeof(struct source_output)); assert(o); o->name = name ? strdup(name) : NULL; o->source = s; o->spec = *spec; - o->kill = NULL; - o->kill_userdata = NULL; - o->memblockq = memblockq_new(bytes_per_second(spec)*5, sample_size(spec), (size_t) -1); - assert(o->memblockq); + o->push = NULL; + o->kill = NULL; + o->userdata = NULL; assert(s->core); - r = idxset_put(s->core->output_streams, o, &o->index); + r = idxset_put(s->core->source_outputs, o, &o->index); assert(r == 0 && o->index != IDXSET_INVALID); - r = idxset_put(s->output_streams, o, NULL); + r = idxset_put(s->outputs, o, NULL); assert(r == 0); return o; } -void output_stream_free(struct output_stream* o) { +void source_output_free(struct source_output* o) { assert(o); - memblockq_free(o->memblockq); - assert(o->source && o->source->core); - idxset_remove_by_data(o->source->core->output_streams, o, NULL); - idxset_remove_by_data(o->source->output_streams, o, NULL); + idxset_remove_by_data(o->source->core->source_outputs, o, NULL); + idxset_remove_by_data(o->source->outputs, o, NULL); free(o->name); free(o); } -void output_stream_set_kill_callback(struct output_stream *i, void (*kill)(struct output_stream*i, void *userdata), void *userdata) { - assert(i && kill); - i->kill = kill; - i->kill_userdata = userdata; -} - - -void output_stream_kill(struct output_stream*i) { +void source_output_kill(struct source_output*i) { assert(i); if (i->kill) - i->kill(i, i->kill_userdata); + i->kill(i); } diff --git a/src/sourceoutput.h b/src/sourceoutput.h index c6c0a717e..fecfea347 100644 --- a/src/sourceoutput.h +++ b/src/sourceoutput.h @@ -1,27 +1,28 @@ -#ifndef foooutputstreamhfoo -#define foooutputstreamhfoo +#ifndef foosourceoutputhfoo +#define foosourceoutputhfoo #include + #include "source.h" #include "sample.h" #include "memblockq.h" -struct output_stream { - char *name; +struct source_output { uint32_t index; + char *name; struct source *source; struct sample_spec spec; - struct memblockq *memblockq; - void (*kill)(struct output_stream* i, void *userdata); - void *kill_userdata; + void (*push)(struct source_output *o, struct memchunk *chunk); + void (*kill)(struct source_output* o); + + void *userdata; }; -struct output_stream* output_stream_new(struct source *s, struct sample_spec *spec, const char *name); -void output_stream_free(struct output_stream* o); +struct source_output* source_output_new(struct source *s, struct sample_spec *spec, const char *name); +void source_output_free(struct source_output* o); -void output_stream_set_kill_callback(struct output_stream *i, void (*kill)(struct output_stream*i, void *userdata), void *userdata); -void output_stream_kill(struct output_stream*i); +void source_output_kill(struct source_output*o); #endif From a8f788111cb0b18ca3517a51657881d5ffcfabae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 15 Jun 2004 17:19:20 +0000 Subject: [PATCH 0018/1514] fix mixing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@19 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/module-oss.c | 2 +- src/todo | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/module-oss.c b/src/module-oss.c index 07a407d8e..bb8112b02 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -130,7 +130,7 @@ int module_init(struct core *c, struct module*m) { fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); - frag_size = ((int) 4 << 16) | 10; /* nfrags = 4; frag_size = 2^10 */ + frag_size = ((int) 12 << 16) | 10; /* nfrags = 12; frag_size = 2^10 */ if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag_size) < 0) { fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); goto fail; diff --git a/src/todo b/src/todo index d4cc5f18c..563ab804b 100644 --- a/src/todo +++ b/src/todo @@ -1,4 +1,6 @@ - mixing +- latenzoptimierung +- optimierung von rebuild_pollfds() - resampling - native protocol/library - oss/mmap From 4b86ff0e6cfea2c34be71ebe1102eb307bd5dc0b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 16 Jun 2004 00:05:30 +0000 Subject: [PATCH 0019/1514] got mmap oss output working git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@20 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 11 +- src/main.c | 3 +- src/memblock.c | 31 ---- src/memblock.h | 4 - src/memblockq.c | 48 +++++- src/memblockq.h | 1 + src/module-oss-mmap.c | 369 ++++++++++++++++++++++++++++++++++++++++++ src/module-oss.c | 60 ++++--- src/oss.c | 48 ++++++ src/oss.h | 8 + src/protocol-simple.c | 21 ++- src/sample.c | 21 ++- src/sample.h | 5 +- src/sink.c | 67 ++++++-- src/sink.h | 6 +- src/source.c | 2 +- src/todo | 14 +- 17 files changed, 607 insertions(+), 112 deletions(-) create mode 100644 src/module-oss-mmap.c create mode 100644 src/oss.c create mode 100644 src/oss.h diff --git a/src/Makefile.am b/src/Makefile.am index 40e2039d4..8ce5202dc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,7 +22,7 @@ bin_PROGRAMS = polypaudio pkglib_LTLIBRARIES=libprotocol-simple.la module-simple-protocol-tcp.la \ libsocket-server.la module-pipe-sink.la libpstream.la libiochannel.la \ - libpacket.la module-oss.la + libpacket.la module-oss.la module-oss-mmap.la liboss.la polypaudio_SOURCES = idxset.c queue.c strbuf.c mainloop.c \ memblock.c sample.c memblockq.c client.c \ @@ -50,6 +50,9 @@ libiochannel_la_LDFLAGS = -avoid-version libpacket_la_SOURCES = packet.c libpacket_la_LDFLAGS = -avoid-version +liboss_la_SOURCES = oss.c +liboss_la_LDFLAGS = -avoid-version + module_simple_protocol_tcp_la_SOURCES = module-simple-protocol-tcp.c module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la @@ -60,4 +63,8 @@ module_pipe_sink_la_LIBADD = libiochannel.la module_oss_la_SOURCES = module-oss.c module_oss_la_LDFLAGS = -module -avoid-version -module_oss_la_LIBADD = libiochannel.la +module_oss_la_LIBADD = libiochannel.la liboss.la + +module_oss_mmap_la_SOURCES = module-oss-mmap.c +module_oss_mmap_la_LDFLAGS = -module -avoid-version +module_oss_mmap_la_LIBADD = libiochannel.la liboss.la diff --git a/src/main.c b/src/main.c index a42eaa828..bce078231 100644 --- a/src/main.c +++ b/src/main.c @@ -30,11 +30,10 @@ int main(int argc, char *argv[]) { mainloop_source_new_signal(m, SIGINT, signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - module_load(c, "module-oss", "/dev/dsp1"); + module_load(c, "module-oss-mmap", "/dev/dsp1"); module_load(c, "module-pipe-sink", NULL); module_load(c, "module-simple-protocol-tcp", NULL); - fprintf(stderr, "main: mainloop entry.\n"); while (mainloop_iterate(m, 1) == 0); /* fprintf(stderr, "main: %u blocks\n", n_blocks);*/ diff --git a/src/memblock.c b/src/memblock.c index 2d3467697..6f05918a0 100644 --- a/src/memblock.c +++ b/src/memblock.c @@ -2,8 +2,6 @@ #include #include #include -#include -#include #include "memblock.h" @@ -16,7 +14,6 @@ struct memblock *memblock_new(size_t length) { b->length = length; b->data = b+1; n_blocks++; - timerclear(&b->stamp); return b; } @@ -27,7 +24,6 @@ struct memblock *memblock_new_fixed(void *d, size_t length) { b->length = length; b->data = d; n_blocks++; - timerclear(&b->stamp); return b; } @@ -38,7 +34,6 @@ struct memblock *memblock_new_dynamic(void *d, size_t length) { b->length = length; b->data = d; n_blocks++; - timerclear(&b->stamp); return b; } @@ -77,29 +72,3 @@ void memblock_unref_fixed(struct memblock *b) { b->type = MEMBLOCK_DYNAMIC; } -void memblock_stamp(struct memblock*b) { - assert(b); - gettimeofday(&b->stamp, NULL); -} - -uint32_t memblock_age(struct memblock*b) { - assert(b); - struct timeval tv; - uint32_t r; - - if (b->stamp.tv_sec == 0) - return (suseconds_t) -1; - - gettimeofday(&tv, NULL); - - /*fprintf(stderr, "memblock: (%lu,%lu) -- (%lu,%lu)\r", b->stamp.tv_sec, b->stamp.tv_usec, tv.tv_sec, tv.tv_usec);*/ - - r = (tv.tv_sec-b->stamp.tv_sec) * 1000000; - - if (tv.tv_usec >= b->stamp.tv_usec) - r += tv.tv_usec - b->stamp.tv_usec; - else - r -= b->stamp.tv_usec - tv.tv_usec; - - return r; -} diff --git a/src/memblock.h b/src/memblock.h index c0fb6708e..52f1fe500 100644 --- a/src/memblock.h +++ b/src/memblock.h @@ -11,7 +11,6 @@ struct memblock { unsigned ref; size_t length; void *data; - struct timeval stamp; }; struct memchunk { @@ -28,9 +27,6 @@ struct memblock* memblock_ref(struct memblock*b); void memblock_unref_fixed(struct memblock*b); -void memblock_stamp(struct memblock*b); -uint32_t memblock_age(struct memblock*b); - #define memblock_assert_exclusive(b) assert((b)->ref == 1) extern unsigned n_blocks; diff --git a/src/memblockq.c b/src/memblockq.c index 3c0d43267..9e9c109f4 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -7,18 +9,17 @@ struct memblock_list { struct memblock_list *next; struct memchunk chunk; + struct timeval stamp; }; struct memblockq { struct memblock_list *blocks, *blocks_tail; unsigned n_blocks; - size_t total_length; - size_t maxlength; - size_t base; - size_t prebuf; + size_t total_length, maxlength, base, prebuf; + int measure_latency; + uint32_t latency; }; - struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { struct memblockq* bq; assert(maxlength && base); @@ -37,6 +38,9 @@ struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { assert(bq->maxlength >= base); + bq->measure_latency = 1; + bq->latency = 0; + return bq; } @@ -60,6 +64,11 @@ void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta) q = malloc(sizeof(struct memblock_list)); assert(q); + if (bq->measure_latency) + gettimeofday(&q->stamp, NULL); + else + timerclear(&q->stamp); + q->chunk = *chunk; memblock_ref(q->chunk.memblock); assert(q->chunk.index+q->chunk.length <= q->chunk.memblock->length); @@ -113,6 +122,26 @@ int memblockq_pop(struct memblockq* bq, struct memchunk *chunk) { return 0; } +static uint32_t age(struct timeval *tv) { + assert(tv); + struct timeval now; + uint32_t r; + + if (tv->tv_sec == 0) + return 0; + + gettimeofday(&now, NULL); + + r = (now.tv_sec-tv->tv_sec) * 1000000; + + if (now.tv_usec >= tv->tv_usec) + r += now.tv_usec - tv->tv_usec; + else + r -= tv->tv_usec - now.tv_usec; + + return r; +} + void memblockq_drop(struct memblockq *bq, size_t length) { assert(bq); @@ -122,7 +151,10 @@ void memblockq_drop(struct memblockq *bq, size_t length) { if (l > bq->blocks->chunk.length) l = bq->blocks->chunk.length; - + + if (bq->measure_latency) + bq->latency = age(&bq->blocks->stamp); + bq->blocks->chunk.index += l; bq->blocks->chunk.length -= l; bq->total_length -= l; @@ -178,3 +210,7 @@ int memblockq_is_writable(struct memblockq *bq, size_t length) { assert(length <= bq->maxlength); return bq->total_length + length <= bq->maxlength; } + +uint32_t memblockq_get_latency(struct memblockq *bq) { + return bq->latency; +} diff --git a/src/memblockq.h b/src/memblockq.h index 25c2f2d40..9543b40a6 100644 --- a/src/memblockq.h +++ b/src/memblockq.h @@ -22,5 +22,6 @@ void memblockq_empty(struct memblockq *bq); int memblockq_is_readable(struct memblockq *bq); int memblockq_is_writable(struct memblockq *bq, size_t length); +uint32_t memblockq_get_latency(struct memblockq *bq); #endif diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c new file mode 100644 index 000000000..bfc3a6fa1 --- /dev/null +++ b/src/module-oss-mmap.c @@ -0,0 +1,369 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iochannel.h" +#include "sink.h" +#include "source.h" +#include "module.h" +#include "oss.h" + +struct userdata { + struct sink *sink; + struct source *source; + struct core *core; + struct sample_spec sample_spec; + + size_t in_fragment_size, out_fragment_size, in_fragments, out_fragments, sample_size, out_fill; + uint32_t sample_usec; + + int fd; + + void *in_mmap, *out_mmap; + size_t in_mmap_length, out_mmap_length; + + struct mainloop_source *mainloop_source; + + struct memblock **in_memblocks, **out_memblocks; + unsigned out_current, in_current; +}; + +void module_done(struct core *c, struct module*m); + +static void out_clear_memblocks(struct userdata*u, unsigned n) { + unsigned i = u->out_current; + assert(u && u->out_memblocks); + + if (n > u->out_fragments) + n = u->out_fragments; + + while (n > 0) { + if (u->out_memblocks[i]) { + memblock_unref_fixed(u->out_memblocks[i]); + u->out_memblocks[i] = NULL; + } + + i++; + while (i >= u->out_fragments) + i -= u->out_fragments; + + n--; + } +} + +static void out_fill_memblocks(struct userdata *u, unsigned n) { + assert(u && u->out_memblocks); + + while (n > 0) { + struct memchunk chunk; + + if (!u->out_memblocks[u->out_current]) { + + u->out_memblocks[u->out_current] = chunk.memblock = memblock_new_fixed(u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size); + chunk.length = chunk.memblock->length; + chunk.index = 0; + + sink_render_into_full(u->sink, &chunk); + } + + u->out_current++; + while (u->out_current >= u->out_fragments) + u->out_current -= u->out_fragments; + + n--; + } +} + +static void do_write(struct userdata *u) { + struct count_info info; + assert(u && u->sink); + + if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { + fprintf(stderr, "SNDCTL_DSP_GETOPTR: %s\n", strerror(errno)); + return; + } + + u->out_fill = (u->out_fragment_size * u->out_fragments) - (info.ptr % u->out_fragment_size); + + if (!info.blocks) + return; + + out_clear_memblocks(u, info.blocks); + out_fill_memblocks(u, info.blocks); + +} + +static void in_post_memblocks(struct userdata *u, unsigned n) { + assert(u && u->in_memblocks); + + while (n > 0) { + struct memchunk chunk; + + if (!u->in_memblocks[u->in_current]) { + u->in_memblocks[u->in_current] = chunk.memblock = memblock_new_fixed(u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size); + chunk.length = chunk.memblock->length; + chunk.index = 0; + + source_post(u->source, &chunk); + } + + u->in_current++; + while (u->in_current >= u->in_fragments) + u->in_current -= u->in_fragments; + + n--; + } +} + +static void in_clear_memblocks(struct userdata*u, unsigned n) { + unsigned i = u->in_current; + assert(u && u->in_memblocks); + + if (n > u->in_fragments) + n = u->in_fragments; + + while (n > 0) { + if (u->in_memblocks[i]) { + memblock_unref_fixed(u->in_memblocks[i]); + u->in_memblocks[i] = NULL; + } + + i++; + while (i >= u->in_fragments) + i -= u->in_fragments; + + n--; + } +} + +static void do_read(struct userdata *u) { + struct count_info info; + assert(u && u->source); + + if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { + fprintf(stderr, "SNDCTL_DSP_GETIPTR: %s\n", strerror(errno)); + return; + } + + if (!info.blocks) + return; + + in_post_memblocks(u, info.blocks); + in_clear_memblocks(u, u->in_fragments/2); +}; + +static void io_callback(struct mainloop_source*s, int fd, enum mainloop_io_event event, void *userdata) { + struct userdata *u = userdata; + + if (event & MAINLOOP_IO_EVENT_IN) + do_read(u); + if (event & MAINLOOP_IO_EVENT_OUT) + do_write(u); +} + +static uint32_t sink_get_latency_cb(struct sink *s) { + struct userdata *u = s->userdata; + assert(s && u); + + do_write(u); + return u->out_fill/u->sample_size*u->sample_usec; +} + +int module_init(struct core *c, struct module*m) { + struct audio_buf_info info; + struct userdata *u = NULL; + char *p; + int frag_size; + int mode, caps, caps_read = 0; + int enable_bits = 0, zero = 0; + assert(c && m); + + m->userdata = u = malloc(sizeof(struct userdata)); + assert(u); + memset(u, 0, sizeof(struct userdata)); + u->fd = -1; + u->core = c; + + p = m->argument ? m->argument : "/dev/dsp"; + if ((u->fd = open(p, (mode = O_RDWR)|O_NDELAY)) >= 0) { + ioctl(u->fd, SNDCTL_DSP_SETDUPLEX, 0); + + if (ioctl(u->fd, SNDCTL_DSP_GETCAPS, &caps) < 0) { + fprintf(stderr, "SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); + goto fail; + } + + if (!(caps & DSP_CAP_DUPLEX)) { + close(u->fd); + u->fd = -1; + } else + caps_read = 1; + } + + if (u->fd < 0) { + if ((u->fd = open(p, (mode = O_WRONLY)|O_NDELAY)) < 0) { + if ((u->fd = open(p, (mode = O_RDONLY)|O_NDELAY)) < 0) { + fprintf(stderr, "open('%s'): %s\n", p, strerror(errno)); + goto fail; + } + } + } + + if (!caps_read) { + if (ioctl(u->fd, SNDCTL_DSP_GETCAPS, &caps) < 0) { + fprintf(stderr, "SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); + goto fail; + } + } + + if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_REALTIME) || !(caps & DSP_CAP_TRIGGER)) { + fprintf(stderr, "OSS device not mmap capable.\n"); + goto fail; + } + + fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + + frag_size = ((int) 12 << 16) | 10; /* nfrags = 12; frag_size = 2^10 */ + if (ioctl(u->fd, SNDCTL_DSP_SETFRAGMENT, &frag_size) < 0) { + fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); + goto fail; + } + + if (oss_auto_format(u->fd, &u->sample_spec) < 0) + goto fail; + + if (mode != O_WRONLY) { + if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { + fprintf(stderr, "SNDCTL_DSP_GETISPACE: %s\n", strerror(errno)); + goto fail; + } + + fprintf(stderr, "module-oss-mmap: input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + u->in_mmap_length = (u->in_fragment_size = info.fragsize) * (u->in_fragments = info.fragstotal); + + if ((u->in_mmap = mmap(NULL, u->in_mmap_length, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { + if (mode == O_RDWR) { + fprintf(stderr, "module-oss-mmap: mmap failed for input. Changing to O_WRONLY mode.\n"); + mode = O_WRONLY; + } else { + fprintf(stderr, "modeule-oss-mmap: mmap(): %s\n", strerror(errno)); + goto fail; + } + } else { + + u->source = source_new(c, "dsp", &u->sample_spec); + assert(u->source); + u->source->userdata = u; + + u->in_memblocks = malloc(sizeof(struct memblock *)*u->in_fragments); + memset(u->in_memblocks, 0, sizeof(struct memblock *)*u->in_fragments); + + enable_bits |= PCM_ENABLE_INPUT; + } + } + + if (m != O_RDONLY) { + if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { + fprintf(stderr, "SNDCTL_DSP_GETOSPACE: %s\n", strerror(errno)); + goto fail; + } + + fprintf(stderr, "module-oss: output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + u->out_mmap_length = (u->out_fragment_size = info.fragsize) * (u->out_fragments = info.fragstotal); + + if ((u->out_mmap = mmap(NULL, u->out_mmap_length, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { + if (mode == O_RDWR) { + fprintf(stderr, "module-oss-mmap: mmap filed for output. Changing to O_RDONLY mode.\n"); + mode = O_RDONLY; + } else { + fprintf(stderr, "modeule-oss-mmap: mmap(): %s\n", strerror(errno)); + goto fail; + } + } else { + silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); + + u->sink = sink_new(c, "dsp", &u->sample_spec); + assert(u->sink); + u->sink->get_latency = sink_get_latency_cb; + u->sink->userdata = u; + + u->out_memblocks = malloc(sizeof(struct memblock *)*u->out_fragments); + memset(u->out_memblocks, 0, sizeof(struct memblock *)*u->out_fragments); + + enable_bits |= PCM_ENABLE_OUTPUT; + } + } + + zero = 0; + if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero) < 0) { + fprintf(stderr, "SNDCTL_DSP_SETTRIGGER: %s\n", strerror(errno)); + goto fail; + } + + if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0) { + fprintf(stderr, "SNDCTL_DSP_SETTRIGGER: %s\n", strerror(errno)); + goto fail; + } + + assert(u->source || u->sink); + + u->sample_size = sample_size(&u->sample_spec); + u->sample_usec = 1000000/u->sample_spec.rate; + + u->mainloop_source = mainloop_source_new_io(c->mainloop, u->fd, (u->source ? MAINLOOP_IO_EVENT_IN : 0) | (u->sink ? MAINLOOP_IO_EVENT_OUT : 0), io_callback, u); + assert(u->mainloop_source); + + return 0; + +fail: + module_done(c, m); + + return -1; +} + +void module_done(struct core *c, struct module*m) { + struct userdata *u; + assert(c && m); + + u = m->userdata; + assert(u); + + if (u->out_memblocks) { + out_clear_memblocks(u, u->out_fragments); + free(u->out_memblocks); + } + + if (u->in_memblocks) { + in_clear_memblocks(u, u->in_fragments); + free(u->in_memblocks); + } + + if (u->in_mmap && u->in_mmap != MAP_FAILED) + munmap(u->in_mmap, u->in_mmap_length); + + if (u->out_mmap && u->out_mmap != MAP_FAILED) + munmap(u->out_mmap, u->out_mmap_length); + + if (u->sink) + sink_free(u->sink); + + if (u->source) + source_free(u->source); + + if (u->mainloop_source) + mainloop_source_free(u->mainloop_source); + + if (u->fd >= 0) + close(u->fd); + + free(u); +} diff --git a/src/module-oss.c b/src/module-oss.c index bb8112b02..170d864d7 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -14,6 +14,8 @@ #include "sink.h" #include "source.h" #include "module.h" +#include "oss.h" +#include "sample.h" struct userdata { struct sink *sink; @@ -23,7 +25,9 @@ struct userdata { struct memchunk memchunk, silence; - uint32_t in_fragment_size, out_fragment_size, sample_size; + uint32_t in_fragment_size, out_fragment_size, sample_size, sample_usec; + + int fd; }; static void do_write(struct userdata *u) { @@ -92,12 +96,26 @@ static void io_callback(struct iochannel *io, void*userdata) { do_read(u); } +static uint32_t sink_get_latency_cb(struct sink *s) { + int arg; + struct userdata *u = s->userdata; + assert(s && u); + + if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) { + fprintf(stderr, "module-oss: device doesn't support SNDCTL_DSP_GETODELAY.\n"); + s->get_latency = NULL; + return 0; + } + + return arg/u->sample_size*u->sample_usec; +} + int module_init(struct core *c, struct module*m) { struct audio_buf_info info; struct userdata *u = NULL; char *p; int fd = -1; - int format, channels, speed, frag_size, in_frag_size, out_frag_size; + int frag_size, in_frag_size, out_frag_size; int mode; struct sample_spec ss; assert(c && m); @@ -136,37 +154,8 @@ int module_init(struct core *c, struct module*m) { goto fail; } - format = AFMT_S16_NE; - if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_S16_NE) { - int f = AFMT_S16_NE == AFMT_S16_LE ? AFMT_S16_BE : AFMT_S16_LE; - format = f; - if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != f) { - format = AFMT_U8; - if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_U8) { - fprintf(stderr, "SNDCTL_DSP_SETFMT: %s\n", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); - goto fail; - } else - ss.format = SAMPLE_U8; - } else - ss.format = f == AFMT_S16_LE ? SAMPLE_S16LE : SAMPLE_S16BE; - } else - ss.format = SAMPLE_S16NE; - - channels = 2; - if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { - fprintf(stderr, "SNDCTL_DSP_CHANNELS: %s\n", strerror(errno)); + if (oss_auto_format(fd, &ss) < 0) goto fail; - } - assert(channels); - ss.channels = channels; - - speed = 44100; - if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { - fprintf(stderr, "SNDCTL_DSP_SPEED: %s\n", strerror(errno)); - goto fail; - } - assert(speed); - ss.rate = speed; if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) { fprintf(stderr, "SNDCTL_DSP_GETBLKSIZE: %s\n", strerror(errno)); @@ -193,12 +182,15 @@ int module_init(struct core *c, struct module*m) { if (mode != O_RDONLY) { u->sink = sink_new(c, "dsp", &ss); assert(u->sink); + u->sink->get_latency = sink_get_latency_cb; + u->sink->userdata = u; } else u->sink = NULL; if (mode != O_WRONLY) { u->source = source_new(c, "dsp", &ss); assert(u->source); + u->source->userdata = u; } else u->source = NULL; @@ -207,16 +199,18 @@ int module_init(struct core *c, struct module*m) { u->io = iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0); assert(u->io); iochannel_set_callback(u->io, io_callback, u); + u->fd = fd; u->memchunk.memblock = NULL; u->memchunk.length = 0; u->sample_size = sample_size(&ss); + u->sample_usec = 1000000/ss.rate; u->out_fragment_size = out_frag_size; u->in_fragment_size = in_frag_size; u->silence.memblock = memblock_new(u->silence.length = u->out_fragment_size); assert(u->silence.memblock); - silence(u->silence.memblock, &ss); + silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; m->userdata = u; diff --git a/src/oss.c b/src/oss.c new file mode 100644 index 000000000..7b1315c00 --- /dev/null +++ b/src/oss.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include + +#include "oss.h" + +int oss_auto_format(int fd, struct sample_spec *ss) { + int format, channels, speed; + + assert(fd >= 0 && ss); + + format = AFMT_S16_NE; + if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_S16_NE) { + int f = AFMT_S16_NE == AFMT_S16_LE ? AFMT_S16_BE : AFMT_S16_LE; + format = f; + if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != f) { + format = AFMT_U8; + if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_U8) { + fprintf(stderr, "SNDCTL_DSP_SETFMT: %s\n", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); + return -1; + } else + ss->format = SAMPLE_U8; + } else + ss->format = f == AFMT_S16_LE ? SAMPLE_S16LE : SAMPLE_S16BE; + } else + ss->format = SAMPLE_S16NE; + + channels = 2; + if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { + fprintf(stderr, "SNDCTL_DSP_CHANNELS: %s\n", strerror(errno)); + return -1; + } + assert(channels); + ss->channels = channels; + + speed = 44100; + if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { + fprintf(stderr, "SNDCTL_DSP_SPEED: %s\n", strerror(errno)); + return -1; + } + assert(speed); + ss->rate = speed; + + return 0; +} diff --git a/src/oss.h b/src/oss.h new file mode 100644 index 000000000..35d2dd023 --- /dev/null +++ b/src/oss.h @@ -0,0 +1,8 @@ +#ifndef fooosshfoo +#define fooosshfoo + +#include "sample.h" + +int oss_auto_format(int fd, struct sample_spec *ss); + +#endif diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 1803936e4..f779a56a0 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -56,6 +56,7 @@ static void destroy_connection(struct connection *c) { static int do_read(struct connection *c) { struct memchunk chunk; ssize_t r; + uint32_t u1, u2; if (!iochannel_is_readable(c->io)) return 0; @@ -66,8 +67,6 @@ static int do_read(struct connection *c) { chunk.memblock = memblock_new(BUFSIZE); assert(chunk.memblock); - memblock_stamp(chunk.memblock); - if ((r = iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) { fprintf(stderr, "read(): %s\n", r == 0 ? "EOF" : strerror(errno)); memblock_unref(chunk.memblock); @@ -82,6 +81,13 @@ static int do_read(struct connection *c) { memblockq_push(c->input_memblockq, &chunk, 0); memblock_unref(chunk.memblock); sink_notify(c->sink_input->sink); + + + u1 = memblockq_get_latency(c->input_memblockq); + u2 = sink_get_latency(c->sink_input->sink); + + fprintf(stderr, "latency: %u+%u=%u\r", u1, u2, u1+u2); + return 0; } @@ -96,7 +102,9 @@ static int do_write(struct connection *c) { return 0; assert(c->output_memblockq); - memblockq_peek(c->output_memblockq, &chunk); + if (memblockq_peek(c->output_memblockq, &chunk) < 0) + return 0; + assert(chunk.memblock && chunk.length); if ((r = iochannel_write(c->io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { @@ -145,6 +153,9 @@ static void source_output_push_cb(struct source_output *o, struct memchunk *chun assert(o && c && chunk); memblockq_push(c->output_memblockq, chunk, 0); + + if (do_write(c) < 0) + destroy_connection(c); } static void source_output_kill_cb(struct source_output *o) { @@ -205,7 +216,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->source_output->kill = source_output_kill_cb; c->source_output->userdata = c; - l = 5*bytes_per_second(&DEFAULT_SAMPLE_SPEC); + l = 5*bytes_per_second(&DEFAULT_SAMPLE_SPEC); /* 5s */ c->output_memblockq = memblockq_new(l, sample_size(&DEFAULT_SAMPLE_SPEC), l/2); } @@ -225,7 +236,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->sink_input->kill = sink_input_kill_cb; c->sink_input->userdata = c; - l = 5*bytes_per_second(&DEFAULT_SAMPLE_SPEC); + l = bytes_per_second(&DEFAULT_SAMPLE_SPEC)/2; /* half a second */ c->input_memblockq = memblockq_new(l, sample_size(&DEFAULT_SAMPLE_SPEC), l/2); } diff --git a/src/sample.c b/src/sample.c index 21c046285..81fe69918 100644 --- a/src/sample.c +++ b/src/sample.c @@ -9,10 +9,22 @@ struct sample_spec default_sample_spec = { .channels = 2 }; -struct memblock *silence(struct memblock* b, struct sample_spec *spec) { - char c = 0; - assert(b && spec); +struct memblock *silence_memblock(struct memblock* b, struct sample_spec *spec) { + assert(b && b->data && spec); memblock_assert_exclusive(b); + silence_memory(b->data, b->length, spec); + return b; +} + +void silence_memchunk(struct memchunk *c, struct sample_spec *spec) { + assert(c && c->memblock && c->memblock->data && spec && c->length); + memblock_assert_exclusive(c->memblock); + silence_memory(c->memblock->data+c->index, c->length, spec); +} + +void silence_memory(void *p, size_t length, struct sample_spec *spec) { + char c = 0; + assert(p && length && spec); switch (spec->format) { case SAMPLE_U8: @@ -29,8 +41,7 @@ struct memblock *silence(struct memblock* b, struct sample_spec *spec) { break; } - memset(b->data, c, b->length); - return b; + memset(p, c, length); } size_t sample_size(struct sample_spec *spec) { diff --git a/src/sample.h b/src/sample.h index f8ba66983..23fc08832 100644 --- a/src/sample.h +++ b/src/sample.h @@ -26,8 +26,9 @@ struct sample_spec { extern struct sample_spec default_sample_spec; -struct memblock *silence(struct memblock* b, struct sample_spec *spec); - +struct memblock *silence_memblock(struct memblock* b, struct sample_spec *spec); +void silence_memchunk(struct memchunk *c, struct sample_spec *spec); +void silence_memory(void *p, size_t length, struct sample_spec *spec); struct mix_info { struct memchunk chunk; diff --git a/src/sink.c b/src/sink.c index 951191dd4..4d3206d82 100644 --- a/src/sink.c +++ b/src/sink.c @@ -33,6 +33,7 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s s->volume = 0xFF; s->notify = NULL; + s->get_latency = NULL; s->userdata = NULL; r = idxset_put(core->sinks, s, &s->index); @@ -138,14 +139,18 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result) { } inputs_drop(s, info, n, l); + + assert(s->monitor_source); + source_post(s->monitor_source, result); + return 0; } -int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *result) { +int sink_render_into(struct sink*s, struct memchunk *target) { struct mix_info info[MAX_MIX_CHANNELS]; unsigned n; size_t l; - assert(s && target && target->length && target->data && result); + assert(s && target && target->length && target->memblock && target->memblock->data); n = fill_mix_info(s, info, MAX_MIX_CHANNELS); @@ -160,18 +165,52 @@ int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *re if (l > info[0].chunk.length) l = info[0].chunk.length; - result->memblock = target; - memcpy(target->data, info[0].chunk.memblock->data + info[0].chunk.index, l); - result->length = target->length = l; - result->index = 0; - } else { - - result->memblock = target; - result->length = l = mix_chunks(info, n, target->data, target->length, &s->sample_spec, s->volume); - result->index = 0; - assert(l); - } - + memcpy(target->memblock->data+target->index, info[0].chunk.memblock->data + info[0].chunk.index, l); + target->length = l; + } else + target->length = l = mix_chunks(info, n, target->memblock->data+target->index, target->length, &s->sample_spec, s->volume); + + assert(l); inputs_drop(s, info, n, l); + + assert(s->monitor_source); + source_post(s->monitor_source, target); + return 0; } + +void sink_render_into_full(struct sink *s, struct memchunk *target) { + struct memchunk chunk; + size_t l, d; + assert(s && target && target->memblock && target->length && target->memblock->data); + + l = target->length; + d = 0; + while (l > 0) { + chunk = *target; + chunk.index += d; + chunk.length -= d; + + if (sink_render_into(s, &chunk) < 0) + break; + + d += chunk.length; + l -= chunk.length; + } + + if (l > 0) { + chunk = *target; + chunk.index += d; + chunk.length -= d; + silence_memchunk(&chunk, &s->sample_spec); + } +} + +uint32_t sink_get_latency(struct sink *s) { + assert(s); + + if (!s->get_latency) + return 0; + + return s->get_latency(s); +} diff --git a/src/sink.h b/src/sink.h index ccfa25901..1a9fb8caa 100644 --- a/src/sink.h +++ b/src/sink.h @@ -23,6 +23,7 @@ struct sink { uint8_t volume; void (*notify)(struct sink*sink); + uint32_t (*get_latency)(struct sink *s); void *userdata; }; @@ -30,7 +31,10 @@ struct sink* sink_new(struct core *core, const char *name, const struct sample_s void sink_free(struct sink* s); int sink_render(struct sink*s, size_t length, struct memchunk *result); -int sink_render_into(struct sink*s, struct memblock *target, struct memchunk *result); +int sink_render_into(struct sink*s, struct memchunk *target); +void sink_render_into_full(struct sink *s, struct memchunk *target); + +uint32_t sink_get_latency(struct sink *s); void sink_notify(struct sink*s); diff --git a/src/source.c b/src/source.c index e01e9f836..c950b54d5 100644 --- a/src/source.c +++ b/src/source.c @@ -59,7 +59,7 @@ void source_notify(struct source*s) { static int do_post(void *p, uint32_t index, int *del, void*userdata) { struct memchunk *chunk = userdata; struct source_output *o = p; - assert(o && o->push && index && del && chunk); + assert(o && o->push && del && chunk); o->push(o, chunk); return 0; diff --git a/src/todo b/src/todo index 563ab804b..2ff7cc6a9 100644 --- a/src/todo +++ b/src/todo @@ -1,12 +1,11 @@ -- mixing -- latenzoptimierung -- optimierung von rebuild_pollfds() -- resampling +- simple control protocol - native protocol/library -- oss/mmap -- esound prodocol +- resampling +- esound protocol - config-parser +- record-testing -- 0.1 +- optimierung von rebuild_pollfds() - future cancellation - client-ui @@ -16,3 +15,6 @@ drivers: - portaudio - mplayer - python + +modules: +- alsa? From eb946dbdbeda66b95039b1e5ada3b9006dc33c8c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 16 Jun 2004 00:05:47 +0000 Subject: [PATCH 0020/1514] configure fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@21 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index de1a94ff7..16376902b 100644 --- a/configure.ac +++ b/configure.ac @@ -42,7 +42,7 @@ AC_PROG_LIBTOOL # If using GCC specifiy some additional parameters if test "x$GCC" = "xyes" ; then - CFLAGS="$CFLAGS -pipe -Wall" + CFLAGS="$CFLAGS -pipe -Wall -W" fi AC_CONFIG_FILES([Makefile src/Makefile]) From 993d1bce74f4cc5be2bfa69a467aae106e2194ab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Jun 2004 00:22:37 +0000 Subject: [PATCH 0021/1514] basic cli interface git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@22 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 35 ++++++-- src/cli.c | 83 ++++++++++++++++++ src/cli.h | 14 ++++ src/client.c | 18 ++++ src/client.h | 3 +- src/core.c | 27 ------ src/core.h | 3 - src/ioline.c | 190 ++++++++++++++++++++++++++++++++++++++++++ src/ioline.h | 14 ++++ src/main.c | 4 +- src/main.h | 6 ++ src/module-cli.c | 34 ++++++++ src/module.c | 17 ++++ src/module.h | 7 +- src/protocol-simple.c | 4 +- src/sink.c | 36 ++++++++ src/sink.h | 6 ++ src/source.c | 35 ++++++++ src/source.h | 4 + src/strbuf.c | 13 +-- src/strbuf.h | 1 + 21 files changed, 505 insertions(+), 49 deletions(-) create mode 100644 src/cli.c create mode 100644 src/cli.h create mode 100644 src/ioline.c create mode 100644 src/ioline.h create mode 100644 src/main.h create mode 100644 src/module-cli.c diff --git a/src/Makefile.am b/src/Makefile.am index 8ce5202dc..5afc5bc08 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,12 +22,25 @@ bin_PROGRAMS = polypaudio pkglib_LTLIBRARIES=libprotocol-simple.la module-simple-protocol-tcp.la \ libsocket-server.la module-pipe-sink.la libpstream.la libiochannel.la \ - libpacket.la module-oss.la module-oss-mmap.la liboss.la + libpacket.la module-oss.la module-oss-mmap.la liboss.la libioline.la \ + libcli.la module-cli.la + +polypaudio_SOURCES = idxset.c idxset.h \ + queue.c queue.h \ + strbuf.c strbuf.h \ + mainloop.c mainloop.h \ + memblock.c memblock.h \ + sample.c sample.h \ + memblockq.c memblockq.h \ + client.c client.h \ + core.c core.h \ + main.c main.h \ + sourceoutput.c sourceoutput.h \ + sinkinput.c sinkinput.h \ + source.c source.h \ + sink.c sink.h \ + module.c module.h -polypaudio_SOURCES = idxset.c queue.c strbuf.c mainloop.c \ - memblock.c sample.c memblockq.c client.c \ - core.c main.c sourceoutput.c sinkinput.c source.c sink.c \ - module.c polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(LIBLTDL) polypaudio_LDFLAGS=-export-dynamic @@ -53,6 +66,14 @@ libpacket_la_LDFLAGS = -avoid-version liboss_la_SOURCES = oss.c liboss_la_LDFLAGS = -avoid-version +libioline_la_SOURCES = ioline.c +libioline_la_LDFLAGS = -avoid-version +libioline_la_LIBADD = libiochannel.la + +libcli_la_SOURCES = cli.c +libcli_la_LDFLAGS = -avoid-version +libcli_la_LIBADD = libiochannel.la libioline.la + module_simple_protocol_tcp_la_SOURCES = module-simple-protocol-tcp.c module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la @@ -68,3 +89,7 @@ module_oss_la_LIBADD = libiochannel.la liboss.la module_oss_mmap_la_SOURCES = module-oss-mmap.c module_oss_mmap_la_LDFLAGS = -module -avoid-version module_oss_mmap_la_LIBADD = libiochannel.la liboss.la + +module_cli_la_SOURCES = module-cli.c +module_cli_la_LDFLAGS = -module -avoid-version +module_cli_la_LIBADD = libcli.la libiochannel.la diff --git a/src/cli.c b/src/cli.c new file mode 100644 index 000000000..9aad7f569 --- /dev/null +++ b/src/cli.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include + +#include "ioline.h" +#include "cli.h" +#include "module.h" +#include "sink.h" +#include "source.h" +#include "client.h" + +struct cli { + struct core *core; + struct ioline *line; + + void (*eof_callback)(struct cli *c, void *userdata); + void *userdata; +}; + +static void line_callback(struct ioline *line, const char *s, void *userdata); + +struct cli* cli_new(struct core *core, struct iochannel *io) { + struct cli *c; + assert(io); + + c = malloc(sizeof(struct cli)); + assert(c); + c->core = core; + c->line = ioline_new(io); + assert(c->line); + + c->userdata = NULL; + c->eof_callback = NULL; + + ioline_set_callback(c->line, line_callback, c); + ioline_puts(c->line, "Welcome to polypaudio!\n> "); + + return c; +} + +void cli_free(struct cli *c) { + assert(c); + ioline_free(c->line); + free(c); +} + +static void line_callback(struct ioline *line, const char *s, void *userdata) { + struct cli *c = userdata; + char *t = NULL; + assert(line && c); + + if (!s) { + fprintf(stderr, "CLI client exited\n"); + if (c->eof_callback) + c->eof_callback(c, c->userdata); + + return; + } + + if (!strcmp(s, "modules")) + ioline_puts(line, (t = module_list_to_string(c->core))); + else if (!strcmp(s, "sources")) + ioline_puts(line, (t = source_list_to_string(c->core))); + else if (!strcmp(s, "sinks")) + ioline_puts(line, (t = sink_list_to_string(c->core))); + else if (!strcmp(s, "clients")) + ioline_puts(line, (t = client_list_to_string(c->core))); + else if (!strcmp(s, "exit")) { + assert(c->core && c->core->mainloop); + mainloop_quit(c->core->mainloop, -1); + } else if (*s) + ioline_puts(line, "Unknown command\n"); + + free(t); + ioline_puts(line, "> "); +} + +void cli_set_eof_callback(struct cli *c, void (*cb)(struct cli*c, void *userdata), void *userdata) { + assert(c && cb); + c->eof_callback = cb; + c->userdata = userdata; +} diff --git a/src/cli.h b/src/cli.h new file mode 100644 index 000000000..f1b74397b --- /dev/null +++ b/src/cli.h @@ -0,0 +1,14 @@ +#ifndef fooclihfoo +#define fooclihfoo + +#include "iochannel.h" +#include "core.h" + +struct cli; + +struct cli* cli_new(struct core *core, struct iochannel *io); +void cli_free(struct cli *cli); + +void cli_set_eof_callback(struct cli *cli, void (*cb)(struct cli*c, void *userdata), void *userdata); + +#endif diff --git a/src/client.c b/src/client.c index 1b84c6bf5..4c8a04910 100644 --- a/src/client.c +++ b/src/client.c @@ -4,6 +4,7 @@ #include #include "client.h" +#include "strbuf.h" struct client *client_new(struct core *core, const char *protocol_name, char *name) { struct client *c; @@ -42,3 +43,20 @@ void client_kill(struct client *c) { c->kill(c); } +char *client_list_to_string(struct core *c) { + struct strbuf *s; + struct client *client; + uint32_t index = IDXSET_INVALID; + assert(c); + + s = strbuf_new(); + assert(s); + + strbuf_printf(s, "%u client(s).\n", idxset_ncontents(c->clients)); + + for (client = idxset_first(c->clients, &index); client; client = idxset_next(c->clients, &index)) + strbuf_printf(s, " index: %u, name: <%s>, protocol_name: <%s>\n", client->index, client->name, client->protocol_name); + + return strbuf_tostring_free(s); +} + diff --git a/src/client.h b/src/client.h index 556b5fb3d..481720518 100644 --- a/src/client.h +++ b/src/client.h @@ -11,7 +11,6 @@ struct client { const char *protocol_name; void (*kill)(struct client *c); - void *userdata; }; @@ -24,4 +23,6 @@ void client_free(struct client *c); * request destruction of the client */ void client_kill(struct client *c); +char *client_list_to_string(struct core *c); + #endif diff --git a/src/core.c b/src/core.c index 0bc13a5b9..50248501a 100644 --- a/src/core.c +++ b/src/core.c @@ -50,30 +50,3 @@ void core_free(struct core *c) { free(c); }; -struct sink* core_get_default_sink(struct core *c) { - struct sink *sink; - assert(c); - - if ((sink = idxset_get_by_index(c->sinks, c->default_sink_index))) - return sink; - - if (!(sink = idxset_first(c->sinks, &c->default_sink_index))) - return NULL; - - fprintf(stderr, "core: default sink vanished, setting to %u.\n", sink->index); - return sink; -} - -struct source* core_get_default_source(struct core *c) { - struct source *source; - assert(c); - - if ((source = idxset_get_by_index(c->sources, c->default_source_index))) - return source; - - if (!(source = idxset_first(c->sources, &c->default_source_index))) - return NULL; - - fprintf(stderr, "core: default source vanished, setting to %u.\n", source->index); - return source; -} diff --git a/src/core.h b/src/core.h index a8a140b89..f6f794b99 100644 --- a/src/core.h +++ b/src/core.h @@ -15,7 +15,4 @@ struct core { struct core* core_new(struct mainloop *m); void core_free(struct core*c); -struct sink* core_get_default_sink(struct core *c); -struct source* core_get_default_source(struct core *c); - #endif diff --git a/src/ioline.c b/src/ioline.c new file mode 100644 index 000000000..c37737a6d --- /dev/null +++ b/src/ioline.c @@ -0,0 +1,190 @@ +#include +#include +#include +#include +#include + +#include "ioline.h" + +#define BUFFER_LIMIT (64*1024) +#define READ_SIZE (1024) + +struct ioline { + struct iochannel *io; + int dead; + + char *wbuf; + size_t wbuf_length, wbuf_index, wbuf_valid_length; + + char *rbuf; + size_t rbuf_length, rbuf_index, rbuf_valid_length; + + void (*callback)(struct ioline*io, const char *s, void *userdata); + void *userdata; +}; + +static void io_callback(struct iochannel*io, void *userdata); +static int do_write(struct ioline *l); + +struct ioline* ioline_new(struct iochannel *io) { + struct ioline *l; + assert(io); + + l = malloc(sizeof(struct ioline)); + assert(l); + l->io = io; + l->dead = 0; + + l->wbuf = NULL; + l->wbuf_length = l->wbuf_index = l->wbuf_valid_length = 0; + + l->rbuf = NULL; + l->rbuf_length = l->rbuf_index = l->rbuf_valid_length = 0; + + l->callback = NULL; + l->userdata = NULL; + + iochannel_set_callback(io, io_callback, l); + + return l; +} + +void ioline_free(struct ioline *l) { + assert(l); + iochannel_free(l->io); + free(l->wbuf); + free(l->rbuf); + free(l); +} + +void ioline_puts(struct ioline *l, const char *c) { + size_t len; + assert(l && c); + + len = strlen(c); + if (len > BUFFER_LIMIT - l->wbuf_valid_length) + len = BUFFER_LIMIT - l->wbuf_valid_length; + + if (!len) + return; + + if (len > l->wbuf_length - l->wbuf_valid_length) { + size_t n = l->wbuf_valid_length+len; + char *new = malloc(n); + if (l->wbuf) { + memcpy(new, l->wbuf+l->wbuf_index, l->wbuf_valid_length); + free(l->wbuf); + } + l->wbuf = new; + l->wbuf_length = n; + l->wbuf_index = 0; + } else if (len > l->wbuf_length - l->wbuf_valid_length - l->wbuf_index) { + memmove(l->wbuf, l->wbuf+l->wbuf_index, l->wbuf_valid_length); + l->wbuf_index = 0; + } + + memcpy(l->wbuf+l->wbuf_index+l->wbuf_valid_length, c, len); + l->wbuf_valid_length += len; + + do_write(l); +} + +void ioline_set_callback(struct ioline*l, void (*callback)(struct ioline*io, const char *s, void *userdata), void *userdata) { + assert(l && callback); + l->callback = callback; + l->userdata = userdata; +} + +static int do_read(struct ioline *l) { + ssize_t r; + size_t m, len; + char *p, *e; + assert(l); + + if (!iochannel_is_readable(l->io)) + return 0; + + len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; + + if (len < READ_SIZE) { + size_t n = l->rbuf_valid_length+READ_SIZE; + + if (n >= BUFFER_LIMIT) + n = BUFFER_LIMIT; + + if (l->rbuf_length >= n) { + if (l->rbuf_valid_length) + memmove(l->rbuf, l->rbuf+l->rbuf_index, l->rbuf_valid_length); + } else { + char *new = malloc(n); + if (l->rbuf_valid_length) + memcpy(new, l->rbuf+l->rbuf_index, l->rbuf_valid_length); + free(l->rbuf); + l->rbuf = new; + l->rbuf_length = n; + } + + l->rbuf_index = 0; + } + + len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; + + if ((r = iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) + return -1; + + e = memchr(l->rbuf+l->rbuf_index+l->rbuf_valid_length, '\n', r); + l->rbuf_valid_length += r; + + if (!e && l->rbuf_valid_length >= BUFFER_LIMIT) + e = l->rbuf+BUFFER_LIMIT-1; + + *e = 0; + p = l->rbuf+l->rbuf_index; + m = strlen(p); + + if (l->callback) + l->callback(l, p, l->userdata); + + l->rbuf_index += m+1; + l->rbuf_valid_length -= m+1; + + if (l->rbuf_valid_length == 0) + l->rbuf_index = 0; + + return 0; +} + +static int do_write(struct ioline *l) { + ssize_t r; + assert(l); + + if (!l->wbuf_valid_length || !iochannel_is_writable(l->io)) + return 0; + + if ((r = iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) + return -1; + + l->wbuf_valid_length -= r; + if (l->wbuf_valid_length == 0) + l->wbuf_index = 0; + + return 0; +} + +static void io_callback(struct iochannel*io, void *userdata) { + struct ioline *l = userdata; + assert(io && l); + + if (!l->dead && do_read(l) < 0) + goto fail; + + if (!l->dead && do_write(l) < 0) + goto fail; + + return; + +fail: + if (l->callback) + l->callback(l, NULL, l->userdata); + l->dead = 1; +} diff --git a/src/ioline.h b/src/ioline.h new file mode 100644 index 000000000..55d7d4a38 --- /dev/null +++ b/src/ioline.h @@ -0,0 +1,14 @@ +#ifndef fooiolinehfoo +#define fooiolinehfoo + +#include "iochannel.h" + +struct ioline; + +struct ioline* ioline_new(struct iochannel *io); +void ioline_free(struct ioline *l); + +void ioline_puts(struct ioline *s, const char *c); +void ioline_set_callback(struct ioline*io, void (*callback)(struct ioline*io, const char *s, void *userdata), void *userdata); + +#endif diff --git a/src/main.c b/src/main.c index bce078231..f35505ecb 100644 --- a/src/main.c +++ b/src/main.c @@ -9,6 +9,8 @@ #include "mainloop.h" #include "module.h" +int stdin_inuse = 0, stdout_inuse = 0; + static void signal_callback(struct mainloop_source *m, int sig, void *userdata) { mainloop_quit(mainloop_source_get_mainloop(m), -1); fprintf(stderr, "main: got signal.\n"); @@ -33,12 +35,12 @@ int main(int argc, char *argv[]) { module_load(c, "module-oss-mmap", "/dev/dsp1"); module_load(c, "module-pipe-sink", NULL); module_load(c, "module-simple-protocol-tcp", NULL); + module_load(c, "module-cli", NULL); fprintf(stderr, "main: mainloop entry.\n"); while (mainloop_iterate(m, 1) == 0); /* fprintf(stderr, "main: %u blocks\n", n_blocks);*/ fprintf(stderr, "main: mainloop exit.\n"); - mainloop_run(m); diff --git a/src/main.h b/src/main.h new file mode 100644 index 000000000..c4bea049a --- /dev/null +++ b/src/main.h @@ -0,0 +1,6 @@ +#ifndef foomainhfoo +#define foomainhfoo + +extern int stdin_inuse, stdout_inuse; + +#endif diff --git a/src/module-cli.c b/src/module-cli.c new file mode 100644 index 000000000..4af37f67b --- /dev/null +++ b/src/module-cli.c @@ -0,0 +1,34 @@ +#include +#include +#include + +#include "main.h" +#include "module.h" +#include "iochannel.h" +#include "cli.h" + +int module_init(struct core *c, struct module*m) { + struct iochannel *io; + assert(c && m); + + if (stdin_inuse || stdout_inuse) { + fprintf(stderr, "STDIN/STDUSE already used\n"); + return -1; + } + + stdin_inuse = stdout_inuse = 1; + io = iochannel_new(c->mainloop, STDIN_FILENO, STDOUT_FILENO); + assert(io); + + m->userdata = cli_new(c, io); + assert(m->userdata); + return 0; +} + +void module_done(struct core *c, struct module*m) { + assert(c && m); + + cli_free(m->userdata); + assert(stdin_inuse && stdout_inuse); + stdin_inuse = stdout_inuse = 0; +} diff --git a/src/module.c b/src/module.c index 7f2bc218e..0be7f5ed3 100644 --- a/src/module.c +++ b/src/module.c @@ -6,6 +6,7 @@ #include #include "module.h" +#include "strbuf.h" struct module* module_load(struct core *c, const char *name, const char *argument) { struct module *m = NULL; @@ -110,3 +111,19 @@ void module_unload_all(struct core *c) { c->modules = NULL; } +char *module_list_to_string(struct core *c) { + struct strbuf *s; + struct module *m; + uint32_t index = IDXSET_INVALID; + assert(c); + + s = strbuf_new(); + assert(s); + + strbuf_printf(s, "%u module(s) loaded.\n", idxset_ncontents(c->modules)); + + for (m = idxset_first(c->modules, &index); m; m = idxset_next(c->modules, &index)) + strbuf_printf(s, " index: %u, name: <%s>, argument: <%s>\n", m->index, m->name, m->argument); + + return strbuf_tostring_free(s); +} diff --git a/src/module.h b/src/module.h index 980821945..709c7f55c 100644 --- a/src/module.h +++ b/src/module.h @@ -6,11 +6,6 @@ #include "core.h" -struct dependency_module { - lt_dlhandle dl; - struct dependency_module *next; -}; - struct module { struct core *core; char *name, *argument; @@ -30,4 +25,6 @@ void module_unload_by_index(struct core *c, uint32_t index); void module_unload_all(struct core *c); +char *module_list_to_string(struct core *c); + #endif diff --git a/src/protocol-simple.c b/src/protocol-simple.c index f779a56a0..3563419ea 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -205,7 +205,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us struct source *source; size_t l; - if (!(source = core_get_default_source(p->core))) { + if (!(source = source_get_default(p->core))) { fprintf(stderr, "Failed to get default source.\n"); goto fail; } @@ -224,7 +224,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us struct sink *sink; size_t l; - if (!(sink = core_get_default_sink(p->core))) { + if (!(sink = sink_get_default(p->core))) { fprintf(stderr, "Failed to get default sink.\n"); goto fail; } diff --git a/src/sink.c b/src/sink.c index 4d3206d82..89f5e0880 100644 --- a/src/sink.c +++ b/src/sink.c @@ -5,6 +5,7 @@ #include "sink.h" #include "sinkinput.h" +#include "strbuf.h" #define MAX_MIX_CHANNELS 32 @@ -214,3 +215,38 @@ uint32_t sink_get_latency(struct sink *s) { return s->get_latency(s); } + +struct sink* sink_get_default(struct core *c) { + struct sink *sink; + assert(c); + + if ((sink = idxset_get_by_index(c->sinks, c->default_sink_index))) + return sink; + + if (!(sink = idxset_first(c->sinks, &c->default_sink_index))) + return NULL; + + fprintf(stderr, "core: default sink vanished, setting to %u.\n", sink->index); + return sink; +} + +char *sink_list_to_string(struct core *c) { + struct strbuf *s; + struct sink *sink, *default_sink; + uint32_t index = IDXSET_INVALID; + assert(c); + + s = strbuf_new(); + assert(s); + + strbuf_printf(s, "%u sink(s) available.\n", idxset_ncontents(c->sinks)); + + default_sink = sink_get_default(c); + + for (sink = idxset_first(c->sinks, &index); sink; sink = idxset_next(c->sinks, &index)) { + assert(sink->monitor_source); + strbuf_printf(s, " %c index: %u, name: <%s>, volume: <0x%02x>, latency: <%u usec>, monitor_source: <%u>\n", sink == default_sink ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, sink_get_latency(sink), sink->monitor_source->index); + } + + return strbuf_tostring_free(s); +} diff --git a/src/sink.h b/src/sink.h index 1a9fb8caa..394abb5ba 100644 --- a/src/sink.h +++ b/src/sink.h @@ -38,4 +38,10 @@ uint32_t sink_get_latency(struct sink *s); void sink_notify(struct sink*s); +char *sink_list_to_string(struct core *core); + +struct sink* sink_get_default(struct core *c); + + + #endif diff --git a/src/source.c b/src/source.c index c950b54d5..44d775327 100644 --- a/src/source.c +++ b/src/source.c @@ -5,6 +5,7 @@ #include "source.h" #include "sourceoutput.h" +#include "strbuf.h" struct source* source_new(struct core *core, const char *name, const struct sample_spec *spec) { struct source *s; @@ -70,3 +71,37 @@ void source_post(struct source*s, struct memchunk *chunk) { idxset_foreach(s->outputs, do_post, chunk); } + +struct source* source_get_default(struct core *c) { + struct source *source; + assert(c); + + if ((source = idxset_get_by_index(c->sources, c->default_source_index))) + return source; + + if (!(source = idxset_first(c->sources, &c->default_source_index))) + return NULL; + + fprintf(stderr, "core: default source vanished, setting to %u.\n", source->index); + return source; +} + +char *source_list_to_string(struct core *c) { + struct strbuf *s; + struct source *source, *default_source; + uint32_t index = IDXSET_INVALID; + assert(c); + + s = strbuf_new(); + assert(s); + + strbuf_printf(s, "%u source(s) available.\n", idxset_ncontents(c->sources)); + + default_source = source_get_default(c); + + for (source = idxset_first(c->sources, &index); source; source = idxset_next(c->sources, &index)) + strbuf_printf(s, " %c index: %u, name: <%s>\n", source == default_source ? '*' : ' ', source->index, source->name); + + return strbuf_tostring_free(s); +} + diff --git a/src/source.h b/src/source.h index 1442b9f01..078fb1c9a 100644 --- a/src/source.h +++ b/src/source.h @@ -29,4 +29,8 @@ void source_post(struct source*s, struct memchunk *b); void source_notify(struct source *s); +char *source_list_to_string(struct core *c); + +struct source* source_get_default(struct core *c); + #endif diff --git a/src/strbuf.c b/src/strbuf.c index 7c8b965de..97c451c17 100644 --- a/src/strbuf.c +++ b/src/strbuf.c @@ -1,6 +1,3 @@ -#ifndef foostrbufhfoo -#define foostrbufhfoo - #include #include #include @@ -55,6 +52,14 @@ char *strbuf_tostring(struct strbuf *sb) { return t; } +char *strbuf_tostring_free(struct strbuf *sb) { + char *t; + assert(sb); + t = strbuf_tostring(sb); + strbuf_free(sb); + return t; +} + void strbuf_puts(struct strbuf *sb, const char *t) { struct chunk *c; size_t l; @@ -118,5 +123,3 @@ int strbuf_printf(struct strbuf *sb, const char *format, ...) { size *= 2; } } - -#endif diff --git a/src/strbuf.h b/src/strbuf.h index 6ad582a31..f530a0dcf 100644 --- a/src/strbuf.h +++ b/src/strbuf.h @@ -6,6 +6,7 @@ struct strbuf; struct strbuf *strbuf_new(void); void strbuf_free(struct strbuf *sb); char *strbuf_tostring(struct strbuf *sb); +char *strbuf_tostring_free(struct strbuf *sb); int strbuf_printf(struct strbuf *sb, const char *format, ...); void strbuf_puts(struct strbuf *sb, const char *t); From 382e7aefd471a4600010a04e6497d4bfd2fd8663 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Jun 2004 17:12:50 +0000 Subject: [PATCH 0022/1514] some more work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@23 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/cli.c | 28 +++++++++++++++++++++++++--- src/memblock.c | 16 +++++++++++----- src/memblock.h | 2 +- src/memblockq.c | 24 +++++++++++++++--------- src/memblockq.h | 3 ++- src/module-oss.c | 7 +++---- src/protocol-simple.c | 21 ++++++++++----------- src/sample.c | 6 ++++++ src/sample.h | 1 + src/sink.c | 4 +++- src/sinkinput.c | 39 +++++++++++++++++++++++++++++++++++++++ src/sinkinput.h | 7 ++++++- src/sourceoutput.c | 23 +++++++++++++++++++++++ src/sourceoutput.h | 2 ++ 14 files changed, 147 insertions(+), 36 deletions(-) diff --git a/src/cli.c b/src/cli.c index 9aad7f569..4a1981410 100644 --- a/src/cli.c +++ b/src/cli.c @@ -9,6 +9,8 @@ #include "sink.h" #include "source.h" #include "client.h" +#include "sinkinput.h" +#include "sourceoutput.h" struct cli { struct core *core; @@ -34,7 +36,7 @@ struct cli* cli_new(struct core *core, struct iochannel *io) { c->eof_callback = NULL; ioline_set_callback(c->line, line_callback, c); - ioline_puts(c->line, "Welcome to polypaudio!\n> "); + ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n> "); return c; } @@ -66,10 +68,30 @@ static void line_callback(struct ioline *line, const char *s, void *userdata) { ioline_puts(line, (t = sink_list_to_string(c->core))); else if (!strcmp(s, "clients")) ioline_puts(line, (t = client_list_to_string(c->core))); - else if (!strcmp(s, "exit")) { + else if (!strcmp(s, "source_outputs")) + ioline_puts(line, (t = source_output_list_to_string(c->core))); + else if (!strcmp(s, "sink_inputs")) + ioline_puts(line, (t = sink_input_list_to_string(c->core))); + else if (!strcmp(s, "stat")) { + char txt[256]; + snprintf(txt, sizeof(txt), "Memory blocks allocated: %u, total size: %u bytes.\n", memblock_count, memblock_total); + ioline_puts(line, txt); + } else if (!strcmp(s, "exit")) { assert(c->core && c->core->mainloop); mainloop_quit(c->core->mainloop, -1); - } else if (*s) + } else if (!strcmp(s, "help")) + ioline_puts(line, + "Available commands:\n" + " modules\t\tlist modules\n" + " sinks\t\tlist sinks\n" + " sources\t\tlist sources\n" + " clients\t\tlist clients\n" + " source_outputs\tlist source outputs\n" + " sink_inputs\t\tlist sink inputs\n" + " stat\t\tshow memblock statistics\n" + " exit\t\tterminate the daemon\n" + " help\t\tshow this help\n"); + else if (*s) ioline_puts(line, "Unknown command\n"); free(t); diff --git a/src/memblock.c b/src/memblock.c index 6f05918a0..067243c57 100644 --- a/src/memblock.c +++ b/src/memblock.c @@ -5,7 +5,7 @@ #include "memblock.h" -unsigned n_blocks = 0; +unsigned memblock_count = 0, memblock_total = 0; struct memblock *memblock_new(size_t length) { struct memblock *b = malloc(sizeof(struct memblock)+length); @@ -13,7 +13,8 @@ struct memblock *memblock_new(size_t length) { b->ref = 1; b->length = length; b->data = b+1; - n_blocks++; + memblock_count++; + memblock_total += length; return b; } @@ -23,7 +24,8 @@ struct memblock *memblock_new_fixed(void *d, size_t length) { b->ref = 1; b->length = length; b->data = d; - n_blocks++; + memblock_count++; + memblock_total += length; return b; } @@ -33,7 +35,8 @@ struct memblock *memblock_new_dynamic(void *d, size_t length) { b->ref = 1; b->length = length; b->data = d; - n_blocks++; + memblock_count++; + memblock_total += length; return b; } @@ -50,8 +53,11 @@ void memblock_unref(struct memblock*b) { if (b->ref == 0) { if (b->type == MEMBLOCK_DYNAMIC) free(b->data); + + memblock_count--; + memblock_total -= b->length; + free(b); - n_blocks--; } } diff --git a/src/memblock.h b/src/memblock.h index 52f1fe500..cba111016 100644 --- a/src/memblock.h +++ b/src/memblock.h @@ -29,6 +29,6 @@ void memblock_unref_fixed(struct memblock*b); #define memblock_assert_exclusive(b) assert((b)->ref == 1) -extern unsigned n_blocks; +extern unsigned memblock_count, memblock_total; #endif diff --git a/src/memblockq.c b/src/memblockq.c index 9e9c109f4..10c59e507 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -16,8 +16,8 @@ struct memblockq { struct memblock_list *blocks, *blocks_tail; unsigned n_blocks; size_t total_length, maxlength, base, prebuf; - int measure_latency; - uint32_t latency; + int measure_delay; + uint32_t delay; }; struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { @@ -38,8 +38,8 @@ struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { assert(bq->maxlength >= base); - bq->measure_latency = 1; - bq->latency = 0; + bq->measure_delay = 0; + bq->delay = 0; return bq; } @@ -64,7 +64,7 @@ void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta) q = malloc(sizeof(struct memblock_list)); assert(q); - if (bq->measure_latency) + if (bq->measure_delay) gettimeofday(&q->stamp, NULL); else timerclear(&q->stamp); @@ -152,8 +152,8 @@ void memblockq_drop(struct memblockq *bq, size_t length) { if (l > bq->blocks->chunk.length) l = bq->blocks->chunk.length; - if (bq->measure_latency) - bq->latency = age(&bq->blocks->stamp); + if (bq->measure_delay) + bq->delay = age(&bq->blocks->stamp); bq->blocks->chunk.index += l; bq->blocks->chunk.length -= l; @@ -211,6 +211,12 @@ int memblockq_is_writable(struct memblockq *bq, size_t length) { return bq->total_length + length <= bq->maxlength; } -uint32_t memblockq_get_latency(struct memblockq *bq) { - return bq->latency; +uint32_t memblockq_get_delay(struct memblockq *bq) { + assert(bq); + return bq->delay; +} + +uint32_t memblockq_get_length(struct memblockq *bq) { + assert(bq); + return bq->total_length; } diff --git a/src/memblockq.h b/src/memblockq.h index 9543b40a6..0a68ddaff 100644 --- a/src/memblockq.h +++ b/src/memblockq.h @@ -22,6 +22,7 @@ void memblockq_empty(struct memblockq *bq); int memblockq_is_readable(struct memblockq *bq); int memblockq_is_writable(struct memblockq *bq, size_t length); -uint32_t memblockq_get_latency(struct memblockq *bq); +uint32_t memblockq_get_delay(struct memblockq *bq); +uint32_t memblockq_get_length(struct memblockq *bq); #endif diff --git a/src/module-oss.c b/src/module-oss.c index 170d864d7..fab5c8c55 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -25,7 +25,7 @@ struct userdata { struct memchunk memchunk, silence; - uint32_t in_fragment_size, out_fragment_size, sample_size, sample_usec; + uint32_t in_fragment_size, out_fragment_size, sample_size; int fd; }; @@ -99,7 +99,7 @@ static void io_callback(struct iochannel *io, void*userdata) { static uint32_t sink_get_latency_cb(struct sink *s) { int arg; struct userdata *u = s->userdata; - assert(s && u); + assert(s && u && u->sink); if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) { fprintf(stderr, "module-oss: device doesn't support SNDCTL_DSP_GETODELAY.\n"); @@ -107,7 +107,7 @@ static uint32_t sink_get_latency_cb(struct sink *s) { return 0; } - return arg/u->sample_size*u->sample_usec; + return samples_usec(arg, &s->sample_spec); } int module_init(struct core *c, struct module*m) { @@ -204,7 +204,6 @@ int module_init(struct core *c, struct module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; u->sample_size = sample_size(&ss); - u->sample_usec = 1000000/ss.rate; u->out_fragment_size = out_frag_size; u->in_fragment_size = in_frag_size; diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 3563419ea..a0a996cbd 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -56,7 +56,6 @@ static void destroy_connection(struct connection *c) { static int do_read(struct connection *c) { struct memchunk chunk; ssize_t r; - uint32_t u1, u2; if (!iochannel_is_readable(c->io)) return 0; @@ -81,12 +80,6 @@ static int do_read(struct connection *c) { memblockq_push(c->input_memblockq, &chunk, 0); memblock_unref(chunk.memblock); sink_notify(c->sink_input->sink); - - - u1 = memblockq_get_latency(c->input_memblockq); - u2 = sink_get_latency(c->sink_input->sink); - - fprintf(stderr, "latency: %u+%u=%u\r", u1, u2, u1+u2); return 0; } @@ -120,14 +113,13 @@ static int do_write(struct connection *c) { /*** sink_input callbacks ***/ -static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk, uint8_t *volume) { +static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk) { struct connection*c = i->userdata; - assert(i && c && chunk && volume); + assert(i && c && chunk); if (memblockq_peek(c->input_memblockq, chunk) < 0) return -1; - *volume = 0xFF; return 0; } @@ -146,6 +138,13 @@ static void sink_input_kill_cb(struct sink_input *i) { destroy_connection((struct connection *) i->userdata); } + +static uint32_t sink_input_get_latency_cb(struct sink_input *i) { + struct connection*c = i->userdata; + assert(i && c); + return samples_usec(memblockq_get_length(c->input_memblockq), &DEFAULT_SAMPLE_SPEC); +} + /*** source_output callbacks ***/ static void source_output_push_cb(struct source_output *o, struct memchunk *chunk) { @@ -163,7 +162,6 @@ static void source_output_kill_cb(struct source_output *o) { destroy_connection((struct connection *) o->userdata); } - /*** client callbacks ***/ static void client_kill_cb(struct client *c) { @@ -234,6 +232,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; c->sink_input->kill = sink_input_kill_cb; + c->sink_input->get_latency = sink_input_get_latency_cb; c->sink_input->userdata = c; l = bytes_per_second(&DEFAULT_SAMPLE_SPEC)/2; /* half a second */ diff --git a/src/sample.c b/src/sample.c index 81fe69918..c270f255d 100644 --- a/src/sample.c +++ b/src/sample.c @@ -113,3 +113,9 @@ size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, si data += sizeof(int16_t); } } + +uint32_t samples_usec(size_t length, struct sample_spec *spec) { + assert(spec); + + return (uint32_t) (((double) length /sample_size(spec))/spec->rate*1000000); +} diff --git a/src/sample.h b/src/sample.h index 23fc08832..5ed740e48 100644 --- a/src/sample.h +++ b/src/sample.h @@ -40,5 +40,6 @@ size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, si size_t bytes_per_second(struct sample_spec *spec); size_t sample_size(struct sample_spec *spec); +uint32_t samples_usec(size_t length, struct sample_spec *spec); #endif diff --git a/src/sink.c b/src/sink.c index 89f5e0880..cd12b463f 100644 --- a/src/sink.c +++ b/src/sink.c @@ -81,9 +81,11 @@ static unsigned fill_mix_info(struct sink *s, struct mix_info *info, unsigned ma for (i = idxset_first(s->inputs, &index); maxinfo > 0 && i; i = idxset_next(s->inputs, &index)) { assert(i->peek); - if (i->peek(i, &info->chunk, &info->volume) < 0) + if (i->peek(i, &info->chunk) < 0) continue; + info->volume = i->volume; + assert(info->chunk.memblock && info->chunk.memblock->data && info->chunk.length); info->userdata = i; diff --git a/src/sinkinput.c b/src/sinkinput.c index ae7b27ff7..f589b4d96 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -3,6 +3,7 @@ #include #include "sinkinput.h" +#include "strbuf.h" struct sink_input* sink_input_new(struct sink *s, struct sample_spec *spec, const char *name) { struct sink_input *i; @@ -18,6 +19,7 @@ struct sink_input* sink_input_new(struct sink *s, struct sample_spec *spec, cons i->peek = NULL; i->drop = NULL; i->kill = NULL; + i->get_latency = NULL; i->userdata = NULL; assert(s->core); @@ -46,3 +48,40 @@ void sink_input_kill(struct sink_input*i) { if (i->kill) i->kill(i); } + +char *sink_input_list_to_string(struct core *c) { + struct strbuf *s; + struct sink_input *i; + uint32_t index = IDXSET_INVALID; + assert(c); + + s = strbuf_new(); + assert(s); + + strbuf_printf(s, "%u sink input(s) available.\n", idxset_ncontents(c->sink_inputs)); + + for (i = idxset_first(c->sink_inputs, &index); i; i = idxset_next(c->sink_inputs, &index)) { + assert(i->sink); + strbuf_printf(s, " index: %u, name: <%s>, sink: <%u>; volume: <0x%02x>, latency: <%u usec>\n", + i->index, + i->name, + i->sink->index, + (unsigned) i->volume, + sink_input_get_latency(i)); + } + + return strbuf_tostring_free(s); +} + +uint32_t sink_input_get_latency(struct sink_input *i) { + uint32_t l = 0; + + assert(i); + if (i->get_latency) + l += i->get_latency(i); + + assert(i->sink); + l += sink_get_latency(i->sink); + + return l; +} diff --git a/src/sinkinput.h b/src/sinkinput.h index 5e71d2108..f62070c48 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -13,10 +13,13 @@ struct sink_input { char *name; struct sink *sink; struct sample_spec spec; + uint8_t volume; - int (*peek) (struct sink_input *i, struct memchunk *chunk, uint8_t *volume); + int (*peek) (struct sink_input *i, struct memchunk *chunk); void (*drop) (struct sink_input *i, size_t length); void (*kill) (struct sink_input *i); + uint32_t (*get_latency) (struct sink_input *i); + void *userdata; }; @@ -28,5 +31,7 @@ void sink_input_free(struct sink_input* i); * request destruction of it */ void sink_input_kill(struct sink_input *i); +uint32_t sink_input_get_latency(struct sink_input *i); +char *sink_input_list_to_string(struct core *c); #endif diff --git a/src/sourceoutput.c b/src/sourceoutput.c index d4e7a50f2..8021b522b 100644 --- a/src/sourceoutput.c +++ b/src/sourceoutput.c @@ -3,6 +3,7 @@ #include #include "sourceoutput.h" +#include "strbuf.h" struct source_output* source_output_new(struct source *s, struct sample_spec *spec, const char *name) { struct source_output *o; @@ -45,3 +46,25 @@ void source_output_kill(struct source_output*i) { if (i->kill) i->kill(i); } + +char *source_output_list_to_string(struct core *c) { + struct strbuf *s; + struct source_output *o; + uint32_t index = IDXSET_INVALID; + assert(c); + + s = strbuf_new(); + assert(s); + + strbuf_printf(s, "%u source outputs(s) available.\n", idxset_ncontents(c->source_outputs)); + + for (o = idxset_first(c->source_outputs, &index); o; o = idxset_next(c->source_outputs, &index)) { + assert(o->source); + strbuf_printf(s, " %c index: %u, name: <%s>, source: <%u>\n", + o->index, + o->name, + o->source->index); + } + + return strbuf_tostring_free(s); +} diff --git a/src/sourceoutput.h b/src/sourceoutput.h index fecfea347..359ff1511 100644 --- a/src/sourceoutput.h +++ b/src/sourceoutput.h @@ -25,4 +25,6 @@ void source_output_free(struct source_output* o); void source_output_kill(struct source_output*o); +char *source_output_list_to_string(struct core *c); + #endif From 56f8c953dd609bc5c94011fe4acdd9ef6b875747 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Jun 2004 01:01:09 +0000 Subject: [PATCH 0023/1514] some more work on the cli git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@24 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 27 ++++-- src/cli.c | 240 ++++++++++++++++++++++++++++++++++++++++-------- src/dynarray.c | 73 +++++++++++++++ src/dynarray.h | 16 ++++ src/mainloop.c | 33 ++++++- src/mainloop.h | 2 + src/module.c | 30 +++++- src/module.h | 3 + src/sinkinput.c | 2 + src/strbuf.c | 12 ++- src/todo | 3 +- src/tokenizer.c | 64 +++++++++++++ src/tokenizer.h | 11 +++ 13 files changed, 458 insertions(+), 58 deletions(-) create mode 100644 src/dynarray.c create mode 100644 src/dynarray.h create mode 100644 src/tokenizer.c create mode 100644 src/tokenizer.h diff --git a/src/Makefile.am b/src/Makefile.am index 5afc5bc08..9ec640c21 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,7 +23,7 @@ bin_PROGRAMS = polypaudio pkglib_LTLIBRARIES=libprotocol-simple.la module-simple-protocol-tcp.la \ libsocket-server.la module-pipe-sink.la libpstream.la libiochannel.la \ libpacket.la module-oss.la module-oss-mmap.la liboss.la libioline.la \ - libcli.la module-cli.la + libcli.la module-cli.la libtokenizer.la libdynarray.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -45,35 +45,42 @@ polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(LIBLTDL) polypaudio_LDFLAGS=-export-dynamic -libprotocol_simple_la_SOURCES = protocol-simple.c +libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version libprotocol_simple_la_LIBADD = libsocket-server.la libiochannel.la -libsocket_server_la_SOURCES = socket-server.c +libsocket_server_la_SOURCES = socket-server.c socket-server.h libsocket_server_la_LDFLAGS = -avoid-version libsocket_server_la_LIBADD = libiochannel.la -libpstream_la_SOURCES = pstream.c +libpstream_la_SOURCES = pstream.c pstream.h libpstream_la_LDFLAGS = -avoid-version libpstream_la_LIBADD = libpacket.la -libiochannel_la_SOURCES = iochannel.c +libiochannel_la_SOURCES = iochannel.c iochannel.h libiochannel_la_LDFLAGS = -avoid-version -libpacket_la_SOURCES = packet.c +libpacket_la_SOURCES = packet.c packet.h libpacket_la_LDFLAGS = -avoid-version -liboss_la_SOURCES = oss.c +liboss_la_SOURCES = oss.c oss.h liboss_la_LDFLAGS = -avoid-version -libioline_la_SOURCES = ioline.c +libioline_la_SOURCES = ioline.c ioline.h libioline_la_LDFLAGS = -avoid-version libioline_la_LIBADD = libiochannel.la -libcli_la_SOURCES = cli.c +libcli_la_SOURCES = cli.c cli.h libcli_la_LDFLAGS = -avoid-version libcli_la_LIBADD = libiochannel.la libioline.la +libdynarray_la_SOURCES = dynarray.c dynarray.h +libdynarray_la_LDFLAGS = -avoid-version + +libtokenizer_la_SOURCES = tokenizer.c tokenizer.h +libtokenizer_la_LDFLAGS = -avoid-version +libtokenizer_la_LIBADD = libdynarray.la + module_simple_protocol_tcp_la_SOURCES = module-simple-protocol-tcp.c module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la @@ -92,4 +99,4 @@ module_oss_mmap_la_LIBADD = libiochannel.la liboss.la module_cli_la_SOURCES = module-cli.c module_cli_la_LDFLAGS = -module -avoid-version -module_cli_la_LIBADD = libcli.la libiochannel.la +module_cli_la_LIBADD = libcli.la libiochannel.la libtokenizer.la diff --git a/src/cli.c b/src/cli.c index 4a1981410..4f67f8b72 100644 --- a/src/cli.c +++ b/src/cli.c @@ -11,6 +11,8 @@ #include "client.h" #include "sinkinput.h" #include "sourceoutput.h" +#include "tokenizer.h" +#include "strbuf.h" struct cli { struct core *core; @@ -20,8 +22,46 @@ struct cli { void *userdata; }; +struct command { + const char *name; + void (*proc) (struct cli *cli, struct tokenizer*t); + const char *help; + unsigned args; +}; + static void line_callback(struct ioline *line, const char *s, void *userdata); +static void cli_command_exit(struct cli *c, struct tokenizer *t); +static void cli_command_help(struct cli *c, struct tokenizer *t); +static void cli_command_modules(struct cli *c, struct tokenizer *t); +static void cli_command_clients(struct cli *c, struct tokenizer *t); +static void cli_command_sinks(struct cli *c, struct tokenizer *t); +static void cli_command_sources(struct cli *c, struct tokenizer *t); +static void cli_command_sink_inputs(struct cli *c, struct tokenizer *t); +static void cli_command_source_outputs(struct cli *c, struct tokenizer *t); +static void cli_command_stat(struct cli *c, struct tokenizer *t); +static void cli_command_info(struct cli *c, struct tokenizer *t); +static void cli_command_load(struct cli *c, struct tokenizer *t); +static void cli_command_unload(struct cli *c, struct tokenizer *t); + +static const struct command commands[] = { + { "exit", cli_command_exit, "Terminate the daemon", 1 }, + { "help", cli_command_help, "Show this help", 1 }, + { "modules", cli_command_modules, "List loaded modules", 1 }, + { "sinks", cli_command_sinks, "List loaded sinks", 1 }, + { "sources", cli_command_sources, "List loaded sources", 1 }, + { "clients", cli_command_clients, "List loaded clients", 1 }, + { "sink_inputs", cli_command_sink_inputs, "List sink inputs", 1 }, + { "source_outputs", cli_command_source_outputs, "List source outputs", 1 }, + { "stat", cli_command_stat, "Show memory block statistics", 1 }, + { "info", cli_command_info, "Show comprehensive status", 1 }, + { "load", cli_command_load, "Load a module (given by name and arguments)", 3 }, + { "unload", cli_command_unload, "Unload a module (specified by index)", 2 }, + { NULL, NULL, NULL, 0 } +}; + +static const char prompt[] = ">>> "; + struct cli* cli_new(struct core *core, struct iochannel *io) { struct cli *c; assert(io); @@ -36,7 +76,8 @@ struct cli* cli_new(struct core *core, struct iochannel *io) { c->eof_callback = NULL; ioline_set_callback(c->line, line_callback, c); - ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n> "); + ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"); + ioline_puts(c->line, prompt); return c; } @@ -49,7 +90,8 @@ void cli_free(struct cli *c) { static void line_callback(struct ioline *line, const char *s, void *userdata) { struct cli *c = userdata; - char *t = NULL; + const char *cs; + const char delimiter[] = " \t\n\r"; assert(line && c); if (!s) { @@ -60,42 +102,29 @@ static void line_callback(struct ioline *line, const char *s, void *userdata) { return; } - if (!strcmp(s, "modules")) - ioline_puts(line, (t = module_list_to_string(c->core))); - else if (!strcmp(s, "sources")) - ioline_puts(line, (t = source_list_to_string(c->core))); - else if (!strcmp(s, "sinks")) - ioline_puts(line, (t = sink_list_to_string(c->core))); - else if (!strcmp(s, "clients")) - ioline_puts(line, (t = client_list_to_string(c->core))); - else if (!strcmp(s, "source_outputs")) - ioline_puts(line, (t = source_output_list_to_string(c->core))); - else if (!strcmp(s, "sink_inputs")) - ioline_puts(line, (t = sink_input_list_to_string(c->core))); - else if (!strcmp(s, "stat")) { - char txt[256]; - snprintf(txt, sizeof(txt), "Memory blocks allocated: %u, total size: %u bytes.\n", memblock_count, memblock_total); - ioline_puts(line, txt); - } else if (!strcmp(s, "exit")) { - assert(c->core && c->core->mainloop); - mainloop_quit(c->core->mainloop, -1); - } else if (!strcmp(s, "help")) - ioline_puts(line, - "Available commands:\n" - " modules\t\tlist modules\n" - " sinks\t\tlist sinks\n" - " sources\t\tlist sources\n" - " clients\t\tlist clients\n" - " source_outputs\tlist source outputs\n" - " sink_inputs\t\tlist sink inputs\n" - " stat\t\tshow memblock statistics\n" - " exit\t\tterminate the daemon\n" - " help\t\tshow this help\n"); - else if (*s) - ioline_puts(line, "Unknown command\n"); + cs = s+strspn(s, delimiter); + if (*cs && *cs != '#') { + const struct command*command; + int unknown = 1; + size_t l; + + l = strcspn(s, delimiter); - free(t); - ioline_puts(line, "> "); + for (command = commands; command->name; command++) + if (!strncmp(s, command->name, l)) { + struct tokenizer *t = tokenizer_new(s, command->args); + assert(t); + command->proc(c, t); + tokenizer_free(t); + unknown = 0; + break; + } + + if (unknown) + ioline_puts(line, "Unknown command\n"); + } + + ioline_puts(c->line, prompt); } void cli_set_eof_callback(struct cli *c, void (*cb)(struct cli*c, void *userdata), void *userdata) { @@ -103,3 +132,140 @@ void cli_set_eof_callback(struct cli *c, void (*cb)(struct cli*c, void *userdata c->eof_callback = cb; c->userdata = userdata; } + +static void cli_command_exit(struct cli *c, struct tokenizer *t) { + assert(c && c->core && c->core->mainloop && t); + mainloop_quit(c->core->mainloop, -1); +} + +static void cli_command_help(struct cli *c, struct tokenizer *t) { + const struct command*command; + struct strbuf *strbuf; + char *p; + assert(c && t); + + strbuf = strbuf_new(); + assert(strbuf); + + strbuf_puts(strbuf, "Available commands:\n"); + + for (command = commands; command->name; command++) + strbuf_printf(strbuf, " %-20s %s\n", command->name, command->help); + + ioline_puts(c->line, p = strbuf_tostring_free(strbuf)); + free(p); +} + +static void cli_command_modules(struct cli *c, struct tokenizer *t) { + char *s; + assert(c && t); + s = module_list_to_string(c->core); + assert(s); + ioline_puts(c->line, s); + free(s); +} + +static void cli_command_clients(struct cli *c, struct tokenizer *t) { + char *s; + assert(c && t); + s = client_list_to_string(c->core); + assert(s); + ioline_puts(c->line, s); + free(s); +} + +static void cli_command_sinks(struct cli *c, struct tokenizer *t) { + char *s; + assert(c && t); + s = sink_list_to_string(c->core); + assert(s); + ioline_puts(c->line, s); + free(s); +} + +static void cli_command_sources(struct cli *c, struct tokenizer *t) { + char *s; + assert(c && t); + s = source_list_to_string(c->core); + assert(s); + ioline_puts(c->line, s); + free(s); +} + +static void cli_command_sink_inputs(struct cli *c, struct tokenizer *t) { + char *s; + assert(c && t); + s = sink_input_list_to_string(c->core); + assert(s); + ioline_puts(c->line, s); + free(s); +} + +static void cli_command_source_outputs(struct cli *c, struct tokenizer *t) { + char *s; + assert(c && t); + s = source_output_list_to_string(c->core); + assert(s); + ioline_puts(c->line, s); + free(s); +} + +static void cli_command_stat(struct cli *c, struct tokenizer *t) { + char txt[256]; + assert(c && t); + snprintf(txt, sizeof(txt), "Memory blocks allocated: %u, total size: %u bytes.\n", memblock_count, memblock_total); + ioline_puts(c->line, txt); +} + +static void cli_command_info(struct cli *c, struct tokenizer *t) { + assert(c && t); + cli_command_stat(c, t); + cli_command_modules(c, t); + cli_command_sources(c, t); + cli_command_sinks(c, t); + cli_command_clients(c, t); + cli_command_sink_inputs(c, t); + cli_command_source_outputs(c, t); +} + +static void cli_command_load(struct cli *c, struct tokenizer *t) { + struct module *m; + const char *name; + char txt[256]; + assert(c && t); + + if (!(name = tokenizer_get(t, 1))) { + ioline_puts(c->line, "You need to specfiy the module name and optionally arguments.\n"); + return; + } + + if (!(m = module_load(c->core, name, tokenizer_get(t, 2)))) { + ioline_puts(c->line, "Module load failed.\n"); + return; + } + + snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index); + ioline_puts(c->line, txt); +} + +static void cli_command_unload(struct cli *c, struct tokenizer *t) { + struct module *m; + uint32_t index; + const char *i; + char *e; + assert(c && t); + + if (!(i = tokenizer_get(t, 1))) { + ioline_puts(c->line, "You need to specfiy the module index.\n"); + return; + } + + index = (uint32_t) strtoul(i, &e, 10); + if (*e || !(m = idxset_get_by_index(c->core->modules, index))) { + ioline_puts(c->line, "Invalid module index.\n"); + return; + } + + module_unload_request(c->core, m); +} + diff --git a/src/dynarray.c b/src/dynarray.c new file mode 100644 index 000000000..9a7060eec --- /dev/null +++ b/src/dynarray.c @@ -0,0 +1,73 @@ +#include +#include +#include + +#include "dynarray.h" + +struct dynarray { + void **data; + unsigned n_allocated, n_entries; +}; + +struct dynarray* dynarray_new(void) { + struct dynarray *a; + a = malloc(sizeof(struct dynarray)); + assert(a); + a->data = NULL; + a->n_entries = 0; + a->n_allocated = 0; + return a; +} + +void dynarray_free(struct dynarray* a, void (*func)(void *p, void *userdata), void *userdata) { + unsigned i; + assert(a); + + if (func) + for (i = 0; i < a->n_entries; i++) + if (a->data[i]) + func(a->data[i], userdata); + + free(a->data); + free(a); +} + +void dynarray_put(struct dynarray*a, unsigned i, void *p) { + assert(a); + + if (i >= a->n_allocated) { + unsigned n; + + if (!p) + return; + + n = i+100; + a->data = realloc(a->data, sizeof(void*)*n); + memset(a->data+a->n_allocated, 0, sizeof(void*)*(n-a->n_allocated)); + a->n_allocated = n; + } + + a->data[i] = p; + + if (i >= a->n_entries) + a->n_entries = i+1; +} + +unsigned dynarray_append(struct dynarray*a, void *p) { + unsigned i = a->n_entries; + dynarray_put(a, i, p); + return i; +} + +void *dynarray_get(struct dynarray*a, unsigned i) { + assert(a); + if (i >= a->n_allocated) + return NULL; + assert(a->data); + return a->data[i]; +} + +unsigned dynarray_ncontents(struct dynarray*a) { + assert(a); + return a->n_entries; +} diff --git a/src/dynarray.h b/src/dynarray.h new file mode 100644 index 000000000..9ab861ce4 --- /dev/null +++ b/src/dynarray.h @@ -0,0 +1,16 @@ +#ifndef foodynarrayhfoo +#define foodynarrayhfoo + +struct dynarray; + +struct dynarray* dynarray_new(void); +void dynarray_free(struct dynarray* a, void (*func)(void *p, void *userdata), void *userdata); + +void dynarray_put(struct dynarray*a, unsigned i, void *p); +unsigned dynarray_append(struct dynarray*a, void *p); + +void *dynarray_get(struct dynarray*a, unsigned i); + +unsigned dynarray_ncontents(struct dynarray*a); + +#endif diff --git a/src/mainloop.c b/src/mainloop.c index 37dbdb120..fba0461c8 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -242,8 +242,8 @@ int mainloop_iterate(struct mainloop *m, int block) { free_sources(&m->signal_sources, 0); for (s = m->fixed_sources.sources; s; s = s->next) { - assert(!s->dead && s->type == MAINLOOP_SOURCE_TYPE_FIXED); - if (s->enabled) { + assert(s->type == MAINLOOP_SOURCE_TYPE_FIXED); + if (!s->dead && s->enabled) { assert(s->fixed.callback); s->fixed.callback(s, s->userdata); } @@ -264,8 +264,8 @@ int mainloop_iterate(struct mainloop *m, int block) { dispatch_pollfds(m); else if (c == 0) { for (s = m->idle_sources.sources; s; s = s->next) { - assert(!s->dead && s->type == MAINLOOP_SOURCE_TYPE_IDLE); - if (s->enabled) { + assert(s->type == MAINLOOP_SOURCE_TYPE_IDLE); + if (!s->dead && s->enabled) { assert(s->idle.callback); s->idle.callback(s, s->userdata); } @@ -448,3 +448,28 @@ struct mainloop *mainloop_source_get_mainloop(struct mainloop_source *s) { return s->mainloop; } + +struct once_info { + void (*callback)(void *userdata); + void *userdata; +}; + +static void once_callback(struct mainloop_source *s, void *userdata) { + struct once_info *i = userdata; + assert(s && i && i->callback); + i->callback(i->userdata); + mainloop_source_free(s); + free(i); +} + +void mainloop_once(struct mainloop*m, void (*callback)(void *userdata), void *userdata) { + struct once_info *i; + assert(m && callback); + + i = malloc(sizeof(struct once_info)); + assert(i); + i->callback = callback; + i->userdata = userdata; + + mainloop_source_new_fixed(m, once_callback, i); +} diff --git a/src/mainloop.h b/src/mainloop.h index 3fe26fd0e..c1bfc62af 100644 --- a/src/mainloop.h +++ b/src/mainloop.h @@ -30,6 +30,8 @@ struct mainloop_source* mainloop_source_new_fixed(struct mainloop*m, void (*call struct mainloop_source* mainloop_source_new_idle(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata); struct mainloop_source* mainloop_source_new_signal(struct mainloop*m, int sig, void (*callback)(struct mainloop_source *s, int sig, void*userdata), void*userdata); +void mainloop_once(struct mainloop*m, void (*callback)(void *userdata), void *userdata); + void mainloop_source_free(struct mainloop_source*s); void mainloop_source_enable(struct mainloop_source*s, int b); diff --git a/src/module.c b/src/module.c index 0be7f5ed3..c6de1751a 100644 --- a/src/module.c +++ b/src/module.c @@ -17,6 +17,9 @@ struct module* module_load(struct core *c, const char *name, const char *argumen m = malloc(sizeof(struct module)); assert(m); + m->name = strdup(name); + m->argument = argument ? strdup(argument) : NULL; + if (!(m->dl = lt_dlopenext(name))) goto fail; @@ -26,8 +29,6 @@ struct module* module_load(struct core *c, const char *name, const char *argumen if (!(m->done = lt_dlsym(m->dl, "module_done"))) goto fail; - m->name = strdup(name); - m->argument = argument ? strdup(argument) : NULL; m->userdata = NULL; m->core = c; @@ -127,3 +128,28 @@ char *module_list_to_string(struct core *c) { return strbuf_tostring_free(s); } + + +struct once_info { + struct core *core; + uint32_t index; +}; + + +void module_unload_once_callback(void *userdata) { + struct once_info *i = userdata; + assert(i); + module_unload_by_index(i->core, i->index); + free(i); +} + +void module_unload_request(struct core *c, struct module *m) { + struct once_info *i; + assert(c && m); + + i = malloc(sizeof(struct once_info)); + assert(i); + i->core = c; + i->index = m->index; + mainloop_once(c->mainloop, module_unload_once_callback, i); +} diff --git a/src/module.h b/src/module.h index 709c7f55c..cdb613476 100644 --- a/src/module.h +++ b/src/module.h @@ -27,4 +27,7 @@ void module_unload_all(struct core *c); char *module_list_to_string(struct core *c); +void module_unload_request(struct core *c, struct module *m); + + #endif diff --git a/src/sinkinput.c b/src/sinkinput.c index f589b4d96..2e6a8c366 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -22,6 +22,8 @@ struct sink_input* sink_input_new(struct sink *s, struct sample_spec *spec, cons i->get_latency = NULL; i->userdata = NULL; + i->volume = 0xFF; + assert(s->core); r = idxset_put(s->core->sink_inputs, i, &i->index); assert(r == 0 && i->index != IDXSET_INVALID); diff --git a/src/strbuf.c b/src/strbuf.c index 97c451c17..9ce67ec30 100644 --- a/src/strbuf.c +++ b/src/strbuf.c @@ -7,6 +7,7 @@ struct chunk { struct chunk *next; + size_t length; char text[]; }; @@ -43,12 +44,13 @@ char *strbuf_tostring(struct strbuf *sb) { assert(t); e = t; - *e = 0; for (c = sb->head; c; c = c->next) { - strcpy(e, c->text); - e = strchr(e, 0); + memcpy(e, c->text, c->length); + e += c->length; } + *e = 0; + return t; } @@ -70,7 +72,8 @@ void strbuf_puts(struct strbuf *sb, const char *t) { assert(c); c->next = NULL; - strcpy(c->text, t); + c->length = l; + memcpy(c->text, t, l); if (sb->tail) { assert(sb->head); @@ -101,6 +104,7 @@ int strbuf_printf(struct strbuf *sb, const char *format, ...) { va_end(ap); if (r > -1 && r < size) { + c->length = r; c->next = NULL; if (sb->tail) { diff --git a/src/todo b/src/todo index 2ff7cc6a9..7e60ac3bf 100644 --- a/src/todo +++ b/src/todo @@ -1,4 +1,5 @@ -- simple control protocol +- +- simple control protocol: kill client/input/output; set_volume - native protocol/library - resampling - esound protocol diff --git a/src/tokenizer.c b/src/tokenizer.c new file mode 100644 index 000000000..0d266a9a5 --- /dev/null +++ b/src/tokenizer.c @@ -0,0 +1,64 @@ +#include +#include +#include + +#include "tokenizer.h" +#include "dynarray.h" + +struct tokenizer { + struct dynarray *dynarray; +}; + +static void token_free(void *p, void *userdata) { + free(p); +} + +static void parse(struct dynarray*a, const char *s, unsigned args) { + int infty = 0; + const char delimiter[] = " \t\n\r"; + const char *p; + assert(a && s); + + if (args == 0) + infty = 1; + + p = s+strspn(s, delimiter); + while (*p && (infty || args >= 2)) { + size_t l = strcspn(p, delimiter); + char *n = strndup(p, l); + assert(n); + dynarray_append(a, n); + p += l; + p += strspn(p, delimiter); + args--; + } + + if (args && *p) { + char *n = strdup(p); + assert(n); + dynarray_append(a, n); + } +} + +struct tokenizer* tokenizer_new(const char *s, unsigned args) { + struct tokenizer *t; + + t = malloc(sizeof(struct tokenizer)); + assert(t); + t->dynarray = dynarray_new(); + assert(t->dynarray); + + parse(t->dynarray, s, args); + return t; +} + +void tokenizer_free(struct tokenizer *t) { + assert(t); + dynarray_free(t->dynarray, token_free, NULL); + free(t); +} + +const char *tokenizer_get(struct tokenizer *t, unsigned i) { + assert(t); + return dynarray_get(t->dynarray, i); +} diff --git a/src/tokenizer.h b/src/tokenizer.h new file mode 100644 index 000000000..c71ae7900 --- /dev/null +++ b/src/tokenizer.h @@ -0,0 +1,11 @@ +#ifndef footokenizerhfoo +#define footokenizerhfoo + +struct tokenizer; + +struct tokenizer* tokenizer_new(const char *s, unsigned args); +void tokenizer_free(struct tokenizer *t); + +const char *tokenizer_get(struct tokenizer *t, unsigned i); + +#endif From b4e3f5c5c5fb1cb0ddb10d123d69c211516c4ac7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Jun 2004 18:41:24 +0000 Subject: [PATCH 0024/1514] add simple ptorocol with unix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@25 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 11 +++++++++-- ...simple-protocol-tcp.c => module-simple-protocol.c} | 5 +++++ src/todo | 9 +++++---- 3 files changed, 19 insertions(+), 6 deletions(-) rename src/{module-simple-protocol-tcp.c => module-simple-protocol.c} (81%) diff --git a/src/Makefile.am b/src/Makefile.am index 9ec640c21..59e615682 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,7 +23,8 @@ bin_PROGRAMS = polypaudio pkglib_LTLIBRARIES=libprotocol-simple.la module-simple-protocol-tcp.la \ libsocket-server.la module-pipe-sink.la libpstream.la libiochannel.la \ libpacket.la module-oss.la module-oss-mmap.la liboss.la libioline.la \ - libcli.la module-cli.la libtokenizer.la libdynarray.la + libcli.la module-cli.la libtokenizer.la libdynarray.la \ + module-simple-protocol-unix.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -81,10 +82,16 @@ libtokenizer_la_SOURCES = tokenizer.c tokenizer.h libtokenizer_la_LDFLAGS = -avoid-version libtokenizer_la_LIBADD = libdynarray.la -module_simple_protocol_tcp_la_SOURCES = module-simple-protocol-tcp.c +module_simple_protocol_tcp_la_SOURCES = module-simple-protocol.c +module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS $(AM_CFLAGS) module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la +module_simple_protocol_unix_la_SOURCES = module-simple-protocol.c +module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS $(AM_CFLAGS) +module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version +module_simple_protocol_unix_la_LIBADD = libprotocol-simple.la libiochannel.la + module_pipe_sink_la_SOURCES = module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version module_pipe_sink_la_LIBADD = libiochannel.la diff --git a/src/module-simple-protocol-tcp.c b/src/module-simple-protocol.c similarity index 81% rename from src/module-simple-protocol-tcp.c rename to src/module-simple-protocol.c index e71d71420..c25ff06a6 100644 --- a/src/module-simple-protocol-tcp.c +++ b/src/module-simple-protocol.c @@ -9,8 +9,13 @@ int module_init(struct core *c, struct module*m) { struct socket_server *s; assert(c && m); +#ifdef USE_TCP_SOCKETS if (!(s = socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, 4712))) return -1; +#else + if (!(s = socket_server_new_unix(c->mainloop, "/tmp/polypsimple"))) + return -1; +#endif m->userdata = protocol_simple_new(c, s, PROTOCOL_SIMPLE_PLAYBACK); assert(m->userdata); diff --git a/src/todo b/src/todo index 7e60ac3bf..87b5c304c 100644 --- a/src/todo +++ b/src/todo @@ -1,14 +1,15 @@ -- -- simple control protocol: kill client/input/output; set_volume +- cli protocol - native protocol/library +- simple control protocol: kill client/input/output; set_volume - resampling - esound protocol -- config-parser -- record-testing +- config parser +- record testing -- 0.1 - optimierung von rebuild_pollfds() - future cancellation - client-ui +- clip cache drivers: - libao From 787bf6cb64efaa502dfcc8c2631a8d577d591a23 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Jun 2004 18:51:30 +0000 Subject: [PATCH 0025/1514] minor work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@26 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 20 +++++++++++++++----- src/module-simple-protocol.c | 19 ++++++++++++++++++- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 59e615682..fc7b39336 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,8 @@ pkglib_LTLIBRARIES=libprotocol-simple.la module-simple-protocol-tcp.la \ libsocket-server.la module-pipe-sink.la libpstream.la libiochannel.la \ libpacket.la module-oss.la module-oss-mmap.la liboss.la libioline.la \ libcli.la module-cli.la libtokenizer.la libdynarray.la \ - module-simple-protocol-unix.la + module-simple-protocol-unix.la module-cli-protocol-tcp.la \ + libprotocol-cli.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -82,16 +83,25 @@ libtokenizer_la_SOURCES = tokenizer.c tokenizer.h libtokenizer_la_LDFLAGS = -avoid-version libtokenizer_la_LIBADD = libdynarray.la -module_simple_protocol_tcp_la_SOURCES = module-simple-protocol.c -module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS $(AM_CFLAGS) +libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h +libprotocol_cli_la_LDFLAGS = -avoid-version +libprotocol_cli_la_LIBADD = libsocket-server.la libiochannel.la libcli.la + +module_simple_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la -module_simple_protocol_unix_la_SOURCES = module-simple-protocol.c -module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS $(AM_CFLAGS) +module_simple_protocol_unix_la_SOURCES = module-protocol-stub.c +module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version module_simple_protocol_unix_la_LIBADD = libprotocol-simple.la libiochannel.la +module_cli_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) +module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version +module_cli_protocol_tcp_la_LIBADD = libprotocol-cli.la libiochannel.la + module_pipe_sink_la_SOURCES = module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version module_pipe_sink_la_LIBADD = libiochannel.la diff --git a/src/module-simple-protocol.c b/src/module-simple-protocol.c index c25ff06a6..905594c61 100644 --- a/src/module-simple-protocol.c +++ b/src/module-simple-protocol.c @@ -3,7 +3,19 @@ #include "module.h" #include "socket-server.h" -#include "protocol-simple.h" + +#ifdef USE_PROTOCOL_SIMPLE + #include "protocol-simple.h" + #define protocol_free protcol_simple_free +#else + #ifdef USE_PROTOCOL_CLI + #include "protocol-cli.h" + #define protocol_new protocol_cli_new + #define protocol_free protocol_cli_free + #else + #error "Broken build system" + #endif +#endif int module_init(struct core *c, struct module*m) { struct socket_server *s; @@ -17,7 +29,12 @@ int module_init(struct core *c, struct module*m) { return -1; #endif +#ifdef USE_PROTOCOL_SIMPLE m->userdata = protocol_simple_new(c, s, PROTOCOL_SIMPLE_PLAYBACK); +#else + m->userdata = protocol_new(c, s); +#endif + assert(m->userdata); return 0; } From 6eddcc2f856e2b8910046702e0a096e75942c2d6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Jun 2004 18:51:46 +0000 Subject: [PATCH 0026/1514] rename module-simple-protocol to module-protocol-stub git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@27 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/{module-simple-protocol.c => module-protocol-stub.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{module-simple-protocol.c => module-protocol-stub.c} (100%) diff --git a/src/module-simple-protocol.c b/src/module-protocol-stub.c similarity index 100% rename from src/module-simple-protocol.c rename to src/module-protocol-stub.c From 81447ed392e57f822e09cf648cb16732a3e3773f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Jun 2004 19:27:47 +0000 Subject: [PATCH 0027/1514] cli protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@28 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/cli.c | 2 +- src/iochannel.c | 18 +++++++++--- src/iochannel.h | 2 ++ src/module-cli.c | 1 + src/module-protocol-stub.c | 8 ++++-- src/protocol-cli.c | 59 ++++++++++++++++++++++++++++++++++++++ src/protocol-cli.h | 12 ++++++++ 7 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 src/protocol-cli.c create mode 100644 src/protocol-cli.h diff --git a/src/cli.c b/src/cli.c index 4f67f8b72..ec484ace3 100644 --- a/src/cli.c +++ b/src/cli.c @@ -111,7 +111,7 @@ static void line_callback(struct ioline *line, const char *s, void *userdata) { l = strcspn(s, delimiter); for (command = commands; command->name; command++) - if (!strncmp(s, command->name, l)) { + if (strlen(command->name) == l && !strncmp(s, command->name, l)) { struct tokenizer *t = tokenizer_new(s, command->args); assert(t); command->proc(c, t); diff --git a/src/iochannel.c b/src/iochannel.c index 2044d5615..f0c4c4998 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -15,6 +15,8 @@ struct iochannel { int readable; int writable; + int no_close; + struct mainloop_source* input_source, *output_source; }; @@ -83,6 +85,7 @@ struct iochannel* iochannel_new(struct mainloop*m, int ifd, int ofd) { io->callback = NULL; io->readable = 0; io->writable = 0; + io->no_close = 0; if (ifd == ofd) { assert(ifd >= 0); @@ -109,10 +112,12 @@ struct iochannel* iochannel_new(struct mainloop*m, int ifd, int ofd) { void iochannel_free(struct iochannel*io) { assert(io); - if (io->ifd >= 0) - close(io->ifd); - if (io->ofd >= 0 && io->ofd != io->ifd) - close(io->ofd); + if (!io->no_close) { + if (io->ifd >= 0) + close(io->ifd); + if (io->ofd >= 0 && io->ofd != io->ifd) + close(io->ofd); + } if (io->input_source) mainloop_source_free(io->input_source); @@ -162,3 +167,8 @@ void iochannel_set_callback(struct iochannel*io, void (*callback)(struct iochann io->callback = callback; io->userdata = userdata; } + +void iochannel_set_noclose(struct iochannel*io, int b) { + assert(io); + io->no_close = b; +} diff --git a/src/iochannel.h b/src/iochannel.h index f97fabbab..8ed8b8789 100644 --- a/src/iochannel.h +++ b/src/iochannel.h @@ -15,6 +15,8 @@ ssize_t iochannel_read(struct iochannel*io, void*data, size_t l); int iochannel_is_readable(struct iochannel*io); int iochannel_is_writable(struct iochannel*io); +void iochannel_set_noclose(struct iochannel*io, int b); + void iochannel_set_callback(struct iochannel*io, void (*callback)(struct iochannel*io, void *userdata), void *userdata); #endif diff --git a/src/module-cli.c b/src/module-cli.c index 4af37f67b..883f4f53b 100644 --- a/src/module-cli.c +++ b/src/module-cli.c @@ -19,6 +19,7 @@ int module_init(struct core *c, struct module*m) { stdin_inuse = stdout_inuse = 1; io = iochannel_new(c->mainloop, STDIN_FILENO, STDOUT_FILENO); assert(io); + iochannel_set_noclose(io, 1); m->userdata = cli_new(c, io); assert(m->userdata); diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 905594c61..9cbf236ec 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -6,12 +6,14 @@ #ifdef USE_PROTOCOL_SIMPLE #include "protocol-simple.h" - #define protocol_free protcol_simple_free + #define protocol_free protocol_simple_free + #define IPV4_PORT 4712 #else #ifdef USE_PROTOCOL_CLI #include "protocol-cli.h" #define protocol_new protocol_cli_new #define protocol_free protocol_cli_free + #define IPV4_PORT 4711 #else #error "Broken build system" #endif @@ -22,7 +24,7 @@ int module_init(struct core *c, struct module*m) { assert(c && m); #ifdef USE_TCP_SOCKETS - if (!(s = socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, 4712))) + if (!(s = socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, IPV4_PORT))) return -1; #else if (!(s = socket_server_new_unix(c->mainloop, "/tmp/polypsimple"))) @@ -42,5 +44,5 @@ int module_init(struct core *c, struct module*m) { void module_done(struct core *c, struct module*m) { assert(c && m); - protocol_simple_free(m->userdata); + protocol_free(m->userdata); } diff --git a/src/protocol-cli.c b/src/protocol-cli.c new file mode 100644 index 000000000..c0c93d981 --- /dev/null +++ b/src/protocol-cli.c @@ -0,0 +1,59 @@ +#include +#include + +#include "protocol-cli.h" +#include "cli.h" + +struct protocol_cli { + struct core *core; + struct socket_server*server; + struct idxset *connections; +}; + +static void cli_eof_cb(struct cli*c, void*userdata) { + struct protocol_cli *p = userdata; + assert(c && p); + + idxset_remove_by_data(p->connections, c, NULL); + cli_free(c); +} + +static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { + struct protocol_cli *p = userdata; + struct cli *c; + assert(s && io && p); + + c = cli_new(p->core, io); + assert(c); + cli_set_eof_callback(c, cli_eof_cb, p); + + idxset_put(p->connections, c, NULL); +} + +struct protocol_cli* protocol_cli_new(struct core *core, struct socket_server *server) { + struct protocol_cli* p; + assert(core && server); + + p = malloc(sizeof(struct protocol_cli)); + assert(p); + p->core = core; + p->server = server; + p->connections = idxset_new(NULL, NULL); + + socket_server_set_callback(p->server, on_connection, p); + + return p; +} + +static void free_connection(void *p, void *userdata) { + assert(p); + cli_free(p); +} + +void protocol_cli_free(struct protocol_cli *p) { + assert(p); + + idxset_free(p->connections, free_connection, NULL); + socket_server_free(p->server); + free(p); +} diff --git a/src/protocol-cli.h b/src/protocol-cli.h new file mode 100644 index 000000000..8c150ce15 --- /dev/null +++ b/src/protocol-cli.h @@ -0,0 +1,12 @@ +#ifndef fooprotocolclihfoo +#define fooprotocolclihfoo + +#include "core.h" +#include "socket-server.h" + +struct protocol_cli; + +struct protocol_cli* protocol_cli_new(struct core *core, struct socket_server *server); +void protocol_cli_free(struct protocol_cli *n); + +#endif From a84f38e6117426a37da2f20b16b587672ee8f9d6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Jun 2004 19:28:26 +0000 Subject: [PATCH 0028/1514] mofiy keyword expansion git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@29 fefdeb5f-60dc-0310-8127-8f9354f1896f From eecf602476ff5b51bdc08f8fd0e4aa70d2b0ef5a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 20 Jun 2004 01:12:13 +0000 Subject: [PATCH 0029/1514] partial implementation of native protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@30 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 27 ++- src/module-protocol-stub.c | 13 +- src/packet.c | 21 ++- src/packet.h | 6 +- src/protocol-native-tcp.c | 19 -- src/protocol-native-unix.c | 27 --- src/protocol-native.c | 355 ++++++++++++++++++++++++++++++++++--- src/protocol-native.h | 5 +- src/protocol-simple.c | 1 + src/pstream.c | 95 ++++++---- src/pstream.h | 6 +- src/sample.h | 2 +- src/sinkinput.h | 1 - src/tagstruct.c | 187 +++++++++++++++++++ src/tagstruct.h | 30 ++++ src/todo | 1 - 16 files changed, 683 insertions(+), 113 deletions(-) delete mode 100644 src/protocol-native-tcp.c delete mode 100644 src/protocol-native-unix.c create mode 100644 src/tagstruct.c create mode 100644 src/tagstruct.h diff --git a/src/Makefile.am b/src/Makefile.am index fc7b39336..443a25f23 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -# $Id: Makefile.am 27 2003-10-22 22:34:06Z lennart $ +# $Id$ # # This file is part of polypaudio. # @@ -25,7 +25,8 @@ pkglib_LTLIBRARIES=libprotocol-simple.la module-simple-protocol-tcp.la \ libpacket.la module-oss.la module-oss-mmap.la liboss.la libioline.la \ libcli.la module-cli.la libtokenizer.la libdynarray.la \ module-simple-protocol-unix.la module-cli-protocol-tcp.la \ - libprotocol-cli.la + libprotocol-cli.la libprotocol-native.la module-native-protocol-tcp.la \ + module-native-protocol-unix.la module-cli-protocol-unix.la libtagstruct.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -87,6 +88,13 @@ libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h libprotocol_cli_la_LDFLAGS = -avoid-version libprotocol_cli_la_LIBADD = libsocket-server.la libiochannel.la libcli.la +libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h +libprotocol_native_la_LDFLAGS = -avoid-version +libprotocol_native_la_LIBADD = libsocket-server.la libiochannel.la libpacket.la libpstream.la + +libtagstruct_la_SOURCES = tagstruct.c tagstruct.h +libtagstruct_la_LDFLAGS = -avoid-version + module_simple_protocol_tcp_la_SOURCES = module-protocol-stub.c module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version @@ -102,6 +110,21 @@ module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CF module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version module_cli_protocol_tcp_la_LIBADD = libprotocol-cli.la libiochannel.la +module_cli_protocol_unix_la_SOURCES = module-protocol-stub.c +module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) +module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version +module_cli_protocol_unix_la_LIBADD = libprotocol-cli.la libiochannel.la + +module_native_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) +module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version +module_native_protocol_tcp_la_LIBADD = libprotocol-native.la libiochannel.la libtagstruct.la + +module_native_protocol_unix_la_SOURCES = module-protocol-stub.c +module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) +module_native_protocol_unix_la_LDFLAGS = -module -avoid-version +module_native_protocol_unix_la_LIBADD = libprotocol-native.la libiochannel.la libtagstruct.la + module_pipe_sink_la_SOURCES = module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version module_pipe_sink_la_LIBADD = libiochannel.la diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 9cbf236ec..2387017c9 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -7,15 +7,22 @@ #ifdef USE_PROTOCOL_SIMPLE #include "protocol-simple.h" #define protocol_free protocol_simple_free - #define IPV4_PORT 4712 + #define IPV4_PORT 4711 #else #ifdef USE_PROTOCOL_CLI #include "protocol-cli.h" #define protocol_new protocol_cli_new #define protocol_free protocol_cli_free - #define IPV4_PORT 4711 + #define IPV4_PORT 4712 #else - #error "Broken build system" + #ifdef USE_PROTOCOL_NATIVE + #include "protocol-native.h" + #define protocol_new protocol_native_new + #define protocol_free protocol_native_free + #define IPV4_PORT 4713 + #else + #error "Broken build system" + #endif #endif #endif diff --git a/src/packet.c b/src/packet.c index 086e4b2a8..47fce9194 100644 --- a/src/packet.c +++ b/src/packet.c @@ -3,7 +3,7 @@ #include "packet.h" -struct packet* packet_new(uint32_t length) { +struct packet* packet_new(size_t length) { struct packet *p; assert(length); p = malloc(sizeof(struct packet)+length); @@ -11,9 +11,23 @@ struct packet* packet_new(uint32_t length) { p->ref = 1; p->length = length; + p->data = (uint8_t*) (p+1); + p->type = PACKET_APPENDED; return p; } +struct packet* packet_dynamic(uint8_t* data, size_t length) { + struct packet *p; + assert(data && length); + p = malloc(sizeof(struct packet)); + assert(p); + + p->ref = 1; + p->length = length; + p->data = data; + p->type = PACKET_DYNAMIC; +} + struct packet* packet_ref(struct packet *p) { assert(p && p->ref >= 1); p->ref++; @@ -24,6 +38,9 @@ void packet_unref(struct packet *p) { assert(p && p->ref >= 1); p->ref--; - if (p->ref == 0) + if (p->ref == 0) { + if (p->type == PACKET_DYNAMIC) + free(p->data); free(p); + } } diff --git a/src/packet.h b/src/packet.h index 781c0e66a..7e2e00669 100644 --- a/src/packet.h +++ b/src/packet.h @@ -5,12 +5,14 @@ #include struct packet { + enum { PACKET_APPENDED, PACKET_DYNAMIC } type; unsigned ref; size_t length; - uint8_t data[]; + uint8_t *data; }; -struct packet* packet_new(uint32_t length); +struct packet* packet_new(size_t length); +struct packet* packet_new_dynamic(uint8_t* data, size_t length); struct packet* packet_ref(struct packet *p); void packet_unref(struct packet *p); diff --git a/src/protocol-native-tcp.c b/src/protocol-native-tcp.c deleted file mode 100644 index b33f3e15b..000000000 --- a/src/protocol-native-tcp.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "module.h" - -int module_init(struct core *c, struct module*m) { - struct socket_server *s; - assert(c && m); - - if (!(s = socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, 4711))) - return -1; - - m->userdata = protocol_native_new(s); - assert(m->userdata); - return 0; -} - -void module_done(struct core *c, struct module*m) { - assert(c && m); - - protocol_native_free(m->userdata); -} diff --git a/src/protocol-native-unix.c b/src/protocol-native-unix.c deleted file mode 100644 index a18965cdd..000000000 --- a/src/protocol-native-unix.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "module.h" - -int module_init(struct core *c, struct module*m) { - struct fn[PATH_MAX]; - struct socket_server *s; - char *t; - assert(c && m); - - if (!(t = getenv("TMP"))) - if (!(t = getenv("TEMP"))) - t = "/tmp"; - - snprintf(fn, sizeof(fn), "%s/foosock", t); - - if (!(s = socket_server_new_unix(c->mainloop, fn))) - return -1; - - m->userdata = protocol_native_new(s); - assert(m->userdata); - return 0; -} - -void module_done(struct core *c, struct module*m) { - assert(c && m); - - protocol_native_free(m->userdata); -} diff --git a/src/protocol-native.c b/src/protocol-native.c index bdb693558..e9cca7c18 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -1,49 +1,364 @@ -#include "protocol-native.h" +#include +#include +#include -struct protocol_native { - struct socket_server*server; - struct idxset *connection; +#include "protocol-native.h" +#include "packet.h" +#include "client.h" +#include "sourceoutput.h" +#include "sinkinput.h" +#include "pstream.h" +#include "tagstruct.h" + +struct connection; +struct protocol_native; + +enum { + COMMAND_ERROR, + COMMAND_REPLY, + COMMAND_CREATE_PLAYBACK_STREAM, + COMMAND_DELETE_PLAYBACK_STREAM, + COMMAND_CREATE_RECORD_STREAM, + COMMAND_DELETE_RECORD_STREAM, + COMMAND_EXIT, + COMMAND_MAX }; -struct stream_info { - guint32_t tag; - - union { - struct output_stream *output_stream; - struct input_stream *input_stream; - } +enum { + ERROR_ACCESS, + ERROR_COMMAND, + ERROR_ARGUMENT, + ERROR_EXIST +}; + +struct record_stream { + struct connection *connection; + uint32_t index; + struct source_output *source_output; + struct memblockq *memblockq; +}; + +struct playback_stream { + struct connection *connection; + uint32_t index; + struct sink_input *sink_input; + struct memblockq *memblockq; }; struct connection { + int authorized; + struct protocol_native *protocol; struct client *client; - struct serializer *serializer; - - + struct pstream *pstream; + struct idxset *record_streams, *playback_streams; }; -static void on_connection(struct socket_server *server, struct iochannel *io, void *userdata) { - struct protocol_native *p = userdata; - assert(server && io && p && p->server == server); +struct protocol_native { + int public; + struct core *core; + struct socket_server *server; + struct idxset *connections; +}; +static void record_stream_free(struct record_stream* r) { + assert(r && r->connection); + + idxset_remove_by_data(r->connection->record_streams, r, NULL); + source_output_free(r->source_output); + memblockq_free(r->memblockq); + free(r); +} + +static struct playback_stream* playback_stream_new(struct connection *c, struct sink *sink, struct sample_spec *ss, const char *name, size_t maxlength, size_t prebuf) { + struct playback_stream *s; + + s = malloc(sizeof(struct playback_stream)); + assert (s); + s->connection = c; + s->sink_input = sink_input_new(sink, ss, name); + assert(s->sink_input); + s->memblockq = memblockq_new(maxlength, sample_size(ss), prebuf); + assert(s->memblockq); + + idxset_put(c->playback_streams, s, &s->index); + return s; +} + +static void playback_stream_free(struct playback_stream* p) { + assert(p && p->connection); + + idxset_remove_by_data(p->connection->playback_streams, p, NULL); + sink_input_free(p->sink_input); + memblockq_free(p->memblockq); + free(p); +} + +static void connection_free(struct connection *c) { + struct record_stream *r; + struct playback_stream *p; + assert(c && c->protocol); + + idxset_remove_by_data(c->protocol->connections, c, NULL); + pstream_free(c->pstream); + while ((r = idxset_first(c->record_streams, NULL))) + record_stream_free(r); + idxset_free(c->record_streams, NULL, NULL); + + while ((p = idxset_first(c->playback_streams, NULL))) + playback_stream_free(p); + idxset_free(c->playback_streams, NULL, NULL); + + client_free(c->client); + free(c); +} + +/*** pstream callbacks ***/ + +static void send_tagstruct(struct pstream *p, struct tagstruct *t) { + size_t length; + uint8_t *data; + struct packet *packet; + assert(p && t); + + data = tagstruct_free_data(t, &length); + assert(data && length); + packet = packet_new_dynamic(data, length); + assert(packet); + pstream_send_packet(p, packet); + packet_unref(packet); +} + +static void send_error(struct pstream *p, uint32_t tag, uint32_t error) { + struct tagstruct *t = tagstruct_new(NULL, 0); + assert(t); + tagstruct_putu32(t, COMMAND_ERROR); + tagstruct_putu32(t, tag); + tagstruct_putu32(t, error); + send_tagstruct(p, t); +} + +static void send_simple_ack(struct pstream *p, uint32_t tag) { + struct tagstruct *t = tagstruct_new(NULL, 0); + assert(t); + tagstruct_putu32(t, COMMAND_REPLY); + tagstruct_putu32(t, tag); + send_tagstruct(p, t); +} + +struct command { + int (*func)(struct connection *c, uint32_t tag, struct tagstruct *t); +}; + +static int command_create_playback_stream(struct connection *c, uint32_t tag, struct tagstruct *t) { + struct playback_stream *s; + size_t maxlength, prebuf; + uint32_t sink_index; + const char *name; + struct sample_spec ss; + struct tagstruct *reply; + struct sink *sink; + assert(c && t && c->protocol && c->protocol->core); + + if (tagstruct_gets(t, &name) < 0 || + tagstruct_get_sample_spec(t, &ss) < 0 || + tagstruct_getu32(t, &sink_index) < 0 || + tagstruct_getu32(t, &maxlength) < 0 || + tagstruct_getu32(t, &prebuf) < 0 || + !tagstruct_eof(t)) + return -1; + + if (!c->authorized) { + send_error(c->pstream, tag, ERROR_ACCESS); + return 0; + } + + if (sink_index == (uint32_t) -1) + sink = sink_get_default(c->protocol->core); + else + sink = idxset_get_by_index(c->protocol->core->sinks, sink_index); + + if (!sink) { + send_error(c->pstream, tag, ERROR_EXIST); + return 0; + } + + if (!(s = playback_stream_new(c, sink, &ss, name, maxlength, prebuf))) { + send_error(c->pstream, tag, ERROR_ARGUMENT); + return 0; + } + + reply = tagstruct_new(NULL, 0); + assert(reply); + tagstruct_putu32(reply, COMMAND_REPLY); + tagstruct_putu32(reply, tag); + tagstruct_putu32(reply, s->index); + send_tagstruct(c->pstream, reply); + return 0; +} + +static int command_delete_playback_stream(struct connection *c, uint32_t tag, struct tagstruct *t) { + uint32_t channel; + struct playback_stream *s; + assert(c && t); + + if (tagstruct_getu32(t, &channel) < 0 || + !tagstruct_eof(t)) + return -1; + + if (!c->authorized) { + send_error(c->pstream, tag, ERROR_ACCESS); + return 0; + } + + if (!(s = idxset_get_by_index(c->playback_streams, channel))) { + send_error(c->pstream, tag, ERROR_EXIST); + return 0; + } + + send_simple_ack(c->pstream, tag); + return 0; +} + +static int command_exit(struct connection *c, uint32_t tag, struct tagstruct *t) { + assert(c && t); + + if (!tagstruct_eof(t)) + return -1; + + if (!c->authorized) { + send_error(c->pstream, tag, ERROR_ACCESS); + return 0; + } + + assert(c->protocol && c->protocol->core); + mainloop_quit(c->protocol->core->mainloop, -1); + send_simple_ack(c->pstream, tag); /* nonsense */ + return 0; +} + +static const struct command commands[] = { + [COMMAND_ERROR] = { NULL }, + [COMMAND_REPLY] = { NULL }, + [COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream }, + [COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_playback_stream }, + [COMMAND_CREATE_RECORD_STREAM] = { NULL }, + [COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [COMMAND_EXIT] = { command_exit }, +}; + +static int packet_callback(struct pstream *p, struct packet *packet, void *userdata) { + struct connection *c = userdata; + uint32_t tag, command; + struct tagstruct *ts = NULL; + assert(p && packet && packet->data && c); + + if (packet->length <= 8) + goto fail; + + ts = tagstruct_new(packet->data, packet->length); + assert(ts); + + if (tagstruct_getu32(ts, &command) < 0 || + tagstruct_getu32(ts, &tag) < 0) + goto fail; + + if (command >= COMMAND_MAX || !commands[command].func) + send_error(p, tag, ERROR_COMMAND); + else if (commands[command].func(c, tag, ts) < 0) + goto fail; + + tagstruct_free(ts); + + return 0; + +fail: + if (ts) + tagstruct_free(ts); + + fprintf(stderr, "protocol-native: invalid packet.\n"); + return -1; } -struct protocol_native* protocol_native(struct socket_server *server) { +static int memblock_callback(struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata) { + struct connection *c = userdata; + struct playback_stream *stream; + assert(p && chunk && userdata); + + if (!(stream = idxset_get_by_index(c->playback_streams, channel))) { + fprintf(stderr, "protocol-native: client sent block for invalid stream.\n"); + return -1; + } + + memblockq_push(stream->memblockq, chunk, delta); + assert(stream->sink_input); + sink_notify(stream->sink_input->sink); + + return 0; +} + +static void die_callback(struct pstream *p, void *userdata) { + struct connection *c = userdata; + assert(p && c); + connection_free(c); + + fprintf(stderr, "protocol-native: connection died.\n"); +} + +/*** socket server callbacks ***/ + +static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { + struct protocol_native *p = userdata; + struct connection *c; + assert(s && io && p); + + c = malloc(sizeof(struct connection)); + assert(c); + c->authorized = p->public; + c->protocol = p; + assert(p->core); + c->client = client_new(p->core, "NATIVE", "Client"); + assert(c->client); + c->pstream = pstream_new(p->core->mainloop, io); + assert(c->pstream); + + pstream_set_recieve_packet_callback(c->pstream, packet_callback, c); + pstream_set_recieve_memblock_callback(c->pstream, memblock_callback, c); + pstream_set_die_callback(c->pstream, die_callback, c); + + c->record_streams = idxset_new(NULL, NULL); + c->playback_streams = idxset_new(NULL, NULL); + assert(c->record_streams && c->playback_streams); + + idxset_put(p->connections, c, NULL); +} + +/*** module entry points ***/ + +struct protocol_native* protocol_native_new(struct core *core, struct socket_server *server) { struct protocol_native *p; - assert(server); + assert(core && server); p = malloc(sizeof(struct protocol_native)); assert(p); + p->public = 1; p->server = server; - socket_server_set_callback(p->server, callback, p); + p->core = core; + p->connections = idxset_new(NULL, NULL); + socket_server_set_callback(p->server, on_connection, p); + return p; } void protocol_native_free(struct protocol_native *p) { + struct connection *c; assert(p); + while ((c = idxset_first(p->connections, NULL))) + connection_free(c); + idxset_free(p->connections, NULL, NULL); socket_server_free(p->server); free(p); } diff --git a/src/protocol-native.h b/src/protocol-native.h index bdad03b45..88283e1c1 100644 --- a/src/protocol-native.h +++ b/src/protocol-native.h @@ -1,9 +1,12 @@ #ifndef fooprotocolnativehfoo #define fooprotocolnativehfoo +#include "core.h" +#include "socket-server.h" + struct protocol_native; -struct protocol_native* protocol_native(struct socket_server *server); +struct protocol_native* protocol_native_new(struct core*core, struct socket_server *server); void protocol_native_free(struct protocol_native *n); #endif diff --git a/src/protocol-simple.c b/src/protocol-simple.c index a0a996cbd..8e4246cd7 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -79,6 +79,7 @@ static int do_read(struct connection *c) { assert(c->input_memblockq); memblockq_push(c->input_memblockq, &chunk, 0); memblock_unref(chunk.memblock); + assert(c->sink_input); sink_notify(c->sink_input->sink); return 0; diff --git a/src/pstream.c b/src/pstream.c index 0336d161e..a63e126d1 100644 --- a/src/pstream.c +++ b/src/pstream.c @@ -1,5 +1,6 @@ #include #include +#include #include "pstream.h" #include "queue.h" @@ -35,6 +36,8 @@ struct pstream { struct queue *send_queue; int dead; + void (*die_callback) (struct pstream *p, void *userdad); + void *die_callback_userdata; struct { struct item_info* current; @@ -54,10 +57,10 @@ struct pstream { size_t index; } read; - void (*recieve_packet_callback) (struct pstream *p, struct packet *packet, void *userdata); + int (*recieve_packet_callback) (struct pstream *p, struct packet *packet, void *userdata); void *recieve_packet_callback_userdata; - void (*recieve_memblock_callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata); + int (*recieve_memblock_callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata); void *recieve_memblock_callback_userdata; }; @@ -89,6 +92,8 @@ struct pstream *pstream_new(struct mainloop *m, struct iochannel *io) { iochannel_set_callback(io, io_callback, p); p->dead = 0; + p->die_callback = NULL; + p->die_callback_userdata = NULL; p->mainloop = m; p->mainloop_source = mainloop_source_new_fixed(m, prepare_callback, p); @@ -165,7 +170,7 @@ void pstream_send_packet(struct pstream*p, struct packet *packet) { i = malloc(sizeof(struct item_info)); assert(i); i->type = PSTREAM_ITEM_PACKET; - i->packet = packet; + i->packet = packet_ref(packet); queue_push(p->send_queue, i); mainloop_source_enable(p->mainloop_source, 1); @@ -182,18 +187,20 @@ void pstream_send_memblock(struct pstream*p, uint32_t channel, int32_t delta, st i->channel = channel; i->delta = delta; + memblock_ref(i->chunk.memblock); + queue_push(p->send_queue, i); mainloop_source_enable(p->mainloop_source, 1); } -void pstream_set_recieve_packet_callback(struct pstream *p, void (*callback) (struct pstream *p, struct packet *packet, void *userdata), void *userdata) { +void pstream_set_recieve_packet_callback(struct pstream *p, int (*callback) (struct pstream *p, struct packet *packet, void *userdata), void *userdata) { assert(p && callback); p->recieve_packet_callback = callback; p->recieve_packet_callback_userdata = userdata; } -void pstream_set_recieve_memblock_callback(struct pstream *p, void (*callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata), void *userdata) { +void pstream_set_recieve_memblock_callback(struct pstream *p, int (*callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata), void *userdata) { assert(p && callback); p->recieve_memblock_callback = callback; @@ -211,15 +218,15 @@ static void prepare_next_write_item(struct pstream *p) { if (p->write.current->type == PSTREAM_ITEM_PACKET) { assert(p->write.current->packet); p->write.data = p->write.current->packet->data; - p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] = p->write.current->packet->length; + p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length); p->write.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] = 0; p->write.descriptor[PSTREAM_DESCRIPTOR_DELTA] = 0; } else { assert(p->write.current->type == PSTREAM_ITEM_MEMBLOCK && p->write.current->chunk.memblock); p->write.data = p->write.current->chunk.memblock->data + p->write.current->chunk.index; - p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] = p->write.current->chunk.length; - p->write.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] = p->write.current->channel; - p->write.descriptor[PSTREAM_DESCRIPTOR_DELTA] = p->write.current->delta; + p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); + p->write.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] = htonl(p->write.current->channel); + p->write.descriptor[PSTREAM_DESCRIPTOR_DELTA] = htonl(p->write.current->delta); } } @@ -247,17 +254,15 @@ static void do_write(struct pstream *p) { l = PSTREAM_DESCRIPTOR_SIZE - p->write.index; } else { d = (void*) p->write.data + p->write.index - PSTREAM_DESCRIPTOR_SIZE; - l = p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] - p->write.index - PSTREAM_DESCRIPTOR_SIZE; + l = ntohl(p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) - p->write.index - PSTREAM_DESCRIPTOR_SIZE; } - if ((r = iochannel_write(p->io, d, l)) < 0) { - p->dead = 1; - return; - } + if ((r = iochannel_write(p->io, d, l)) < 0) + goto die; p->write.index += r; - if (p->write.index >= PSTREAM_DESCRIPTOR_SIZE+p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) { + if (p->write.index >= PSTREAM_DESCRIPTOR_SIZE+ntohl(p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH])) { assert(p->write.current); item_free(p->write.current, (void *) 1); p->write.current = NULL; @@ -265,6 +270,13 @@ static void do_write(struct pstream *p) { if (p->send_callback && queue_is_empty(p->send_queue)) p->send_callback(p, p->send_callback_userdata); } + + return; + +die: + p->dead = 1; + if (p->die_callback) + p->die_callback(p, p->die_callback_userdata); } static void do_read(struct pstream *p) { @@ -284,35 +296,31 @@ static void do_read(struct pstream *p) { } else { assert(p->read.data); d = (void*) p->read.data + p->read.index - PSTREAM_DESCRIPTOR_SIZE; - l = p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH] - p->read.index - PSTREAM_DESCRIPTOR_SIZE; - } - - if ((r = iochannel_read(p->io, d, l)) <= 0) { - p->dead = 1; - return; + l = ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) - p->read.index - PSTREAM_DESCRIPTOR_SIZE; } + if ((r = iochannel_read(p->io, d, l)) <= 0) + goto die; + p->read.index += r; if (p->read.index == PSTREAM_DESCRIPTOR_SIZE) { /* Reading of frame descriptor complete */ /* Frame size too large */ - if (p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH] > FRAME_SIZE_MAX) { - p->dead = 1; - return; - } + if (ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) > FRAME_SIZE_MAX) + goto die; assert(!p->read.packet && !p->read.memblock); - if (p->read.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] == 0) { + if (ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_CHANNEL]) == 0) { /* Frame is a packet frame */ - p->read.packet = packet_new(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]); + p->read.packet = packet_new(ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH])); assert(p->read.packet); p->read.data = p->read.packet->data; } else { /* Frame is a memblock frame */ - p->read.memblock = memblock_new(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]); + p->read.memblock = memblock_new(ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH])); assert(p->read.memblock); p->read.data = p->read.memblock->data; } @@ -320,7 +328,7 @@ static void do_read(struct pstream *p) { } else if (p->read.index > PSTREAM_DESCRIPTOR_SIZE) { /* Frame payload available */ - if (p->read.memblock && p->recieve_memblock_callback) { /* Is this memblockd data? Than pass it to the user */ + if (p->read.memblock && p->recieve_memblock_callback) { /* Is this memblock data? Than pass it to the user */ size_t l; l = p->read.index - r < PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PSTREAM_DESCRIPTOR_SIZE : r; @@ -332,28 +340,51 @@ static void do_read(struct pstream *p) { chunk.index = p->read.index - PSTREAM_DESCRIPTOR_SIZE - l; chunk.length = l; - p->recieve_memblock_callback(p, p->read.descriptor[PSTREAM_DESCRIPTOR_CHANNEL], (int32_t) p->read.descriptor[PSTREAM_DESCRIPTOR_DELTA], &chunk, p->recieve_memblock_callback_userdata); + if (p->recieve_memblock_callback(p, + ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_CHANNEL]), + (int32_t) ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_DELTA]), + &chunk, + p->recieve_memblock_callback_userdata) < 0) + goto die; } } /* Frame complete */ - if (p->read.index >= p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH] + PSTREAM_DESCRIPTOR_SIZE) { + if (p->read.index >= ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) + PSTREAM_DESCRIPTOR_SIZE) { if (p->read.memblock) { assert(!p->read.packet); memblock_unref(p->read.memblock); p->read.memblock = NULL; } else { + int r = 0; assert(p->read.packet); if (p->recieve_packet_callback) - p->recieve_packet_callback(p, p->read.packet, p->recieve_packet_callback_userdata); + r = p->recieve_packet_callback(p, p->read.packet, p->recieve_packet_callback_userdata); packet_unref(p->read.packet); p->read.packet = NULL; + + if (r < 0) + goto die; } p->read.index = 0; } } + + return; + +die: + p->dead = 1; + if (p->die_callback) + p->die_callback(p, p->die_callback_userdata); + +} + +void pstream_set_die_callback(struct pstream *p, void (*callback)(struct pstream *p, void *userdata), void *userdata) { + assert(p && callback); + p->die_callback = callback; + p->die_callback_userdata = userdata; } diff --git a/src/pstream.h b/src/pstream.h index c0b574967..7113681ea 100644 --- a/src/pstream.h +++ b/src/pstream.h @@ -16,7 +16,9 @@ void pstream_set_send_callback(struct pstream*p, void (*callback) (struct pstrea void pstream_send_packet(struct pstream*p, struct packet *packet); void pstream_send_memblock(struct pstream*p, uint32_t channel, int32_t delta, struct memchunk *chunk); -void pstream_set_recieve_packet_callback(struct pstream *p, void (*callback) (struct pstream *p, struct packet *packet, void *userdata), void *userdata); -void pstream_set_recieve_memblock_callback(struct pstream *p, void (*callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata), void *userdata); +void pstream_set_recieve_packet_callback(struct pstream *p, int (*callback) (struct pstream *p, struct packet *packet, void *userdata), void *userdata); +void pstream_set_recieve_memblock_callback(struct pstream *p, int (*callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata), void *userdata); + +void pstream_set_die_callback(struct pstream *p, void (*callback)(struct pstream *p, void *userdata), void *userdata); #endif diff --git a/src/sample.h b/src/sample.h index 5ed740e48..b2f13cc49 100644 --- a/src/sample.h +++ b/src/sample.h @@ -19,7 +19,7 @@ enum sample_format { struct sample_spec { enum sample_format format; uint32_t rate; - uint32_t channels; + uint8_t channels; }; #define DEFAULT_SAMPLE_SPEC default_sample_spec diff --git a/src/sinkinput.h b/src/sinkinput.h index f62070c48..389d832dd 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -19,7 +19,6 @@ struct sink_input { void (*drop) (struct sink_input *i, size_t length); void (*kill) (struct sink_input *i); uint32_t (*get_latency) (struct sink_input *i); - void *userdata; }; diff --git a/src/tagstruct.c b/src/tagstruct.c new file mode 100644 index 000000000..429dd4088 --- /dev/null +++ b/src/tagstruct.c @@ -0,0 +1,187 @@ +#include +#include +#include +#include + +#include "tagstruct.h" + +enum tags { + TAG_STRING = 't', + TAG_U32 = 'L', + TAG_S32 = 'l', + TAG_U16 = 'S', + TAG_S16 = 's', + TAG_U8 = 'B', + TAG_S8 = 'b', + TAG_SAMPLE_SPEC = 'a' +}; + +struct tagstruct { + uint8_t *data; + size_t length, allocated; + size_t rindex; + + int dynamic; +}; + +struct tagstruct *tagstruct_new(const uint8_t* data, size_t length) { + struct tagstruct*t; + + assert(!data || (data && length)); + + t = malloc(sizeof(struct tagstruct)); + assert(t); + t->data = (uint8_t*) data; + t->allocated = t->length = data ? length : 0; + t->rindex = 0; + t->dynamic = !!data; + return t; +} + +void tagstruct_free(struct tagstruct*t) { + assert(t); + if (t->dynamic) + free(t->data); + free(t); +} + +uint8_t* tagstruct_free_data(struct tagstruct*t, size_t *l) { + uint8_t *p; + assert(t && t->dynamic && l); + p = t->data; + *l = t->length; + free(t); + return p; +} + +static void extend(struct tagstruct*t, size_t l) { + assert(t && t->dynamic); + + if (t->allocated <= l) + return; + + t->data = realloc(t->data, t->allocated = l+100); + assert(t->data); +} + +void tagstruct_puts(struct tagstruct*t, const char *s) { + size_t l; + assert(t && s); + l = strlen(s)+2; + extend(t, l); + t->data[t->length] = TAG_STRING; + strcpy(t->data+t->length+1, s); + t->length += l; +} + +void tagstruct_putu32(struct tagstruct*t, uint32_t i) { + assert(t && i); + extend(t, 5); + t->data[t->length] = TAG_U32; + *((uint32_t*) (t->data+t->length+1)) = htonl(i); + t->length += 5; +} + +void tagstruct_putu8(struct tagstruct*t, uint8_t c) { + assert(t && c); + extend(t, 2); + t->data[t->length] = TAG_U8; + *(t->data+t->length+1) = c; + t->length += 2; +} + +void tagstruct_put_sample_spec(struct tagstruct *t, struct sample_spec *ss) { + assert(t && ss); + extend(t, 7); + t->data[t->length] = TAG_SAMPLE_SPEC; + t->data[t->length+1] = (uint8_t) ss->format; + t->data[t->length+2] = ss->channels; + *(uint32_t*) (t->data+t->length+3) = htonl(ss->rate); + t->length += 7; +} + +int tagstruct_gets(struct tagstruct*t, const char **s) { + int error = 0; + size_t n; + char *c; + assert(t && s); + + if (t->rindex+2 > t->length) + return -1; + + if (t->data[t->rindex] != TAG_STRING) + return -1; + + error = 1; + for (n = 0, c = (char*) (t->data+t->rindex+1); n < t->length-t->rindex-1; c++) + if (!*c) { + error = 0; + break; + } + + if (error) + return -1; + + *s = (char*) (t->data+t->rindex+1); + + t->rindex += n+1; + return 0; +} + +int tagstruct_getu32(struct tagstruct*t, uint32_t *i) { + assert(t && i); + + if (t->rindex+5 > t->length) + return -1; + + if (t->data[t->rindex] != TAG_U32) + return -1; + + *i = ntohl(*((uint32_t*) (t->data+t->rindex+1))); + t->rindex += 5; + return 0; +} + +int tagstruct_getu8(struct tagstruct*t, uint8_t *c) { + assert(t && c); + + if (t->rindex+2 > t->length) + return -1; + + if (t->data[t->rindex] != TAG_U8) + return -1; + + *c = t->data[t->rindex+1]; + t->rindex +=2; + return 0; +} + +int tagstruct_get_sample_spec(struct tagstruct *t, struct sample_spec *ss) { + assert(t && ss); + + if (t->rindex+7 > t->length) + return -1; + + if (t->data[t->rindex] != TAG_SAMPLE_SPEC) + return -1; + + ss->format = t->data[t->rindex+1]; + ss->channels = t->data[t->rindex+2]; + ss->rate = ntohl(*(uint32_t*) (t->data+t->rindex+3)); + + t->rindex += 7; + return 0; +} + + +int tagstruct_eof(struct tagstruct*t) { + assert(t); + return t->rindex >= t->length; +} + +const uint8_t* tagstruct_data(struct tagstruct*t, size_t *l) { + assert(t && t->dynamic && l); + *l = t->length; + return t->data; +} + diff --git a/src/tagstruct.h b/src/tagstruct.h new file mode 100644 index 000000000..5572c64c6 --- /dev/null +++ b/src/tagstruct.h @@ -0,0 +1,30 @@ +#ifndef footagstructhfoo +#define footagstructhfoo + +#include +#include + +#include "sample.h" + +struct tagstruct; + +struct tagstruct *tagstruct_new(const uint8_t* data, size_t length); +void tagstruct_free(struct tagstruct*t); +uint8_t* tagstruct_free_data(struct tagstruct*t, size_t *l); + +void tagstruct_puts(struct tagstruct*t, const char *s); +void tagstruct_putu32(struct tagstruct*t, uint32_t i); +void tagstruct_putu8(struct tagstruct*t, uint8_t c); +void tagstruct_put_sample_spec(struct tagstruct *t, struct sample_spec *ss); + +int tagstruct_gets(struct tagstruct*t, const char **s); +int tagstruct_getu32(struct tagstruct*t, uint32_t *i); +int tagstruct_getu8(struct tagstruct*t, uint8_t *c); +int tagstruct_get_sample_spec(struct tagstruct *t, struct sample_spec *ss); + +int tagstruct_eof(struct tagstruct*t); +const uint8_t* tagstruct_data(struct tagstruct*t, size_t *l); + + + +#endif diff --git a/src/todo b/src/todo index 87b5c304c..aeb7ae5fc 100644 --- a/src/todo +++ b/src/todo @@ -1,4 +1,3 @@ -- cli protocol - native protocol/library - simple control protocol: kill client/input/output; set_volume - resampling From acb25b35102dfca08f66e155560f6c99cb8fa841 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 Jun 2004 23:17:30 +0000 Subject: [PATCH 0030/1514] main part of the native protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@31 fefdeb5f-60dc-0310-8127-8f9354f1896f --- bootstrap.sh | 2 +- configure.ac | 2 +- src/Makefile.am | 57 ++- src/cli.c | 12 +- src/core.c | 2 +- src/core.h | 6 +- src/iochannel.c | 52 +-- src/iochannel.h | 6 +- src/main.c | 36 +- src/mainloop-api.c | 35 ++ src/mainloop-api.h | 43 +++ src/mainloop-signal.c | 138 +++++++ src/mainloop-signal.h | 12 + src/mainloop.c | 754 ++++++++++++++++++++----------------- src/mainloop.h | 40 +- src/memblockq.c | 9 + src/memblockq.h | 2 + src/module-oss-mmap.c | 23 +- src/module-oss.c | 10 +- src/module-pipe-sink.c | 20 +- src/module.c | 2 +- src/oss.c | 2 +- src/oss.h | 2 +- src/pacat.c | 169 +++++++++ src/packet.c | 3 +- src/pdispatch.c | 149 ++++++++ src/pdispatch.h | 22 ++ src/polyp.c | 451 ++++++++++++++++++++++ src/polyp.h | 53 +++ src/polypdef.h | 18 + src/protocol-cli.c | 5 +- src/protocol-native-spec.h | 29 ++ src/protocol-native.c | 232 ++++++------ src/protocol-simple.c | 22 +- src/pstream-util.c | 35 ++ src/pstream-util.h | 14 + src/pstream.c | 34 +- src/pstream.h | 3 +- src/queue.c | 7 + src/sample-util.c | 88 +++++ src/sample-util.h | 23 ++ src/sample.c | 94 +---- src/sample.h | 31 +- src/simple.c | 120 ++++++ src/simple.h | 25 ++ src/sink.c | 3 +- src/sink.h | 4 +- src/sinkinput.c | 4 +- src/sinkinput.h | 4 +- src/socket-client.c | 177 +++++++++ src/socket-client.h | 17 + src/socket-server.c | 21 +- src/socket-server.h | 8 +- src/source.c | 2 +- src/source.h | 4 +- src/sourceoutput.c | 4 +- src/sourceoutput.h | 4 +- src/tagstruct.c | 4 +- src/tagstruct.h | 4 +- src/todo | 4 +- src/util.c | 62 +++ src/util.h | 8 + 62 files changed, 2473 insertions(+), 755 deletions(-) create mode 100644 src/mainloop-api.c create mode 100644 src/mainloop-api.h create mode 100644 src/mainloop-signal.c create mode 100644 src/mainloop-signal.h create mode 100644 src/pacat.c create mode 100644 src/pdispatch.c create mode 100644 src/pdispatch.h create mode 100644 src/polyp.c create mode 100644 src/polyp.h create mode 100644 src/polypdef.h create mode 100644 src/protocol-native-spec.h create mode 100644 src/pstream-util.c create mode 100644 src/pstream-util.h create mode 100644 src/sample-util.c create mode 100644 src/sample-util.h create mode 100644 src/simple.c create mode 100644 src/simple.h create mode 100644 src/socket-client.c create mode 100644 src/socket-client.h create mode 100644 src/util.c create mode 100644 src/util.h diff --git a/bootstrap.sh b/bootstrap.sh index f26ceb15d..c9880d85e 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -33,7 +33,7 @@ else automake -a -c autoconf -Wall - ./configure --sysconfdir=/etc "$@" + CFLAGS="-g -O0" ./configure --sysconfdir=/etc "$@" make clean fi diff --git a/configure.ac b/configure.ac index 16376902b..3a14a061f 100644 --- a/configure.ac +++ b/configure.ac @@ -42,7 +42,7 @@ AC_PROG_LIBTOOL # If using GCC specifiy some additional parameters if test "x$GCC" = "xyes" ; then - CFLAGS="$CFLAGS -pipe -Wall -W" + CFLAGS="$CFLAGS -pipe -Wall -W -Wno-unused-parameter" fi AC_CONFIG_FILES([Makefile src/Makefile]) diff --git a/src/Makefile.am b/src/Makefile.am index 443a25f23..6ad1488f4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,31 +18,39 @@ AM_CFLAGS=-ansi -D_GNU_SOURCE -bin_PROGRAMS = polypaudio +bin_PROGRAMS = polypaudio pacat -pkglib_LTLIBRARIES=libprotocol-simple.la module-simple-protocol-tcp.la \ - libsocket-server.la module-pipe-sink.la libpstream.la libiochannel.la \ +pkglib_LTLIBRARIES=libiochannel.la libsocket-server.la libsocket-client.la \ + libprotocol-simple.la module-simple-protocol-tcp.la \ + module-pipe-sink.la libpstream.la \ libpacket.la module-oss.la module-oss-mmap.la liboss.la libioline.la \ libcli.la module-cli.la libtokenizer.la libdynarray.la \ module-simple-protocol-unix.la module-cli-protocol-tcp.la \ - libprotocol-cli.la libprotocol-native.la module-native-protocol-tcp.la \ - module-native-protocol-unix.la module-cli-protocol-unix.la libtagstruct.la + libprotocol-cli.la module-cli-protocol-unix.la libtagstruct.la \ + libpdispatch.la libprotocol-native.la libpstream-util.la \ + module-native-protocol-tcp.la module-native-protocol-unix.la \ + libpolyp.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ strbuf.c strbuf.h \ + main.c main.h \ mainloop.c mainloop.h \ memblock.c memblock.h \ sample.c sample.h \ + sample-util.c sample-util.h \ memblockq.c memblockq.h \ client.c client.h \ core.c core.h \ - main.c main.h \ sourceoutput.c sourceoutput.h \ sinkinput.c sinkinput.h \ source.c source.h \ sink.c sink.h \ - module.c module.h + module.c module.h \ + mainloop-signal.c mainloop-signal.h \ + mainloop-api.c mainloop-api.h \ + util.c util.h +polypaudio_CFLAGS = $(AM_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(LIBLTDL) @@ -56,10 +64,22 @@ libsocket_server_la_SOURCES = socket-server.c socket-server.h libsocket_server_la_LDFLAGS = -avoid-version libsocket_server_la_LIBADD = libiochannel.la +libsocket_client_la_SOURCES = socket-client.c socket-client.h +libsocket_client_la_LDFLAGS = -avoid-version +libsocket_client_la_LIBADD = libiochannel.la + libpstream_la_SOURCES = pstream.c pstream.h libpstream_la_LDFLAGS = -avoid-version libpstream_la_LIBADD = libpacket.la +libpstream_util_la_SOURCES = pstream-util.c pstream-util.h +libpstream_util_la_LDFLAGS = -avoid-version +libpstream_util_la_LIBADD = libpstream.la libtagstruct.la + +libpdispatch_la_SOURCES = pdispatch.c pdispatch.h +libpdispatch_la_LDFLAGS = -avoid-version +libpdispatch_la_LIBADD = libpacket.la libtagstruct.la + libiochannel_la_SOURCES = iochannel.c iochannel.h libiochannel_la_LDFLAGS = -avoid-version @@ -90,7 +110,7 @@ libprotocol_cli_la_LIBADD = libsocket-server.la libiochannel.la libcli.la libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = libsocket-server.la libiochannel.la libpacket.la libpstream.la +libprotocol_native_la_LIBADD = libsocket-server.la libiochannel.la libpacket.la libpstream.la libpstream-util.la libtagstruct_la_SOURCES = tagstruct.c tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version @@ -140,3 +160,24 @@ module_oss_mmap_la_LIBADD = libiochannel.la liboss.la module_cli_la_SOURCES = module-cli.c module_cli_la_LDFLAGS = -module -avoid-version module_cli_la_LIBADD = libcli.la libiochannel.la libtokenizer.la + +libpolyp_la_SOURCES = polyp.c polyp.h \ + polypdef.h \ + tagstruct.c tagstruct.h \ + iochannel.c iochannel.h \ + pstream.c pstream.h \ + pstream-util.c pstream-util.h \ + pdispatch.c pdispatch.h \ + protocol-native-spec.h \ + mainloop-api.c mainloop-api.h \ + mainloop.c mainloop.h \ + idxset.c idxset.h \ + util.c util.h \ + memblock.c memblock.h \ + socket-client.c socket-client.h \ + packet.c packet.h \ + queue.c queue.h \ + dynarray.c dynarray.h + +pacat_SOURCES = pacat.c +pacat_LDADD = libpolyp.la diff --git a/src/cli.c b/src/cli.c index ec484ace3..091623510 100644 --- a/src/cli.c +++ b/src/cli.c @@ -20,6 +20,8 @@ struct cli { void (*eof_callback)(struct cli *c, void *userdata); void *userdata; + + struct client *client; }; struct command { @@ -63,6 +65,7 @@ static const struct command commands[] = { static const char prompt[] = ">>> "; struct cli* cli_new(struct core *core, struct iochannel *io) { + char cname[256]; struct cli *c; assert(io); @@ -75,16 +78,21 @@ struct cli* cli_new(struct core *core, struct iochannel *io) { c->userdata = NULL; c->eof_callback = NULL; + iochannel_peer_to_string(io, cname, sizeof(cname)); + c->client = client_new(core, "CLI", cname); + assert(c->client); + ioline_set_callback(c->line, line_callback, c); ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"); ioline_puts(c->line, prompt); - + return c; } void cli_free(struct cli *c) { assert(c); ioline_free(c->line); + client_free(c->client); free(c); } @@ -135,7 +143,7 @@ void cli_set_eof_callback(struct cli *c, void (*cb)(struct cli*c, void *userdata static void cli_command_exit(struct cli *c, struct tokenizer *t) { assert(c && c->core && c->core->mainloop && t); - mainloop_quit(c->core->mainloop, -1); + c->core->mainloop->quit(c->core->mainloop, 0); } static void cli_command_help(struct cli *c, struct tokenizer *t) { diff --git a/src/core.c b/src/core.c index 50248501a..d9df38e1e 100644 --- a/src/core.c +++ b/src/core.c @@ -7,7 +7,7 @@ #include "sink.h" #include "source.h" -struct core* core_new(struct mainloop *m) { +struct core* core_new(struct pa_mainloop_api *m) { struct core* c; c = malloc(sizeof(struct core)); assert(c); diff --git a/src/core.h b/src/core.h index f6f794b99..8c4c6233d 100644 --- a/src/core.h +++ b/src/core.h @@ -2,17 +2,17 @@ #define foocorehfoo #include "idxset.h" -#include "mainloop.h" +#include "mainloop-api.h" struct core { - struct mainloop *mainloop; + struct pa_mainloop_api *mainloop; struct idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules; uint32_t default_source_index, default_sink_index; }; -struct core* core_new(struct mainloop *m); +struct core* core_new(struct pa_mainloop_api *m); void core_free(struct core*c); #endif diff --git a/src/iochannel.c b/src/iochannel.c index f0c4c4998..910b7e0b3 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -4,10 +4,11 @@ #include #include "iochannel.h" +#include "util.h" struct iochannel { int ifd, ofd; - struct mainloop* mainloop; + struct pa_mainloop_api* mainloop; void (*callback)(struct iochannel*io, void *userdata); void*userdata; @@ -17,43 +18,45 @@ struct iochannel { int no_close; - struct mainloop_source* input_source, *output_source; + void* input_source, *output_source; }; static void enable_mainloop_sources(struct iochannel *io) { assert(io); if (io->input_source == io->output_source) { - enum mainloop_io_event e = MAINLOOP_IO_EVENT_NULL; + enum pa_mainloop_api_io_events e = PA_MAINLOOP_API_IO_EVENT_NULL; assert(io->input_source); if (!io->readable) - e |= MAINLOOP_IO_EVENT_IN; + e |= PA_MAINLOOP_API_IO_EVENT_INPUT; if (!io->writable) - e |= MAINLOOP_IO_EVENT_OUT; + e |= PA_MAINLOOP_API_IO_EVENT_OUTPUT; - mainloop_source_io_set_events(io->input_source, e); + io->mainloop->enable_io(io->mainloop, io->input_source, e); } else { if (io->input_source) - mainloop_source_io_set_events(io->input_source, io->readable ? MAINLOOP_IO_EVENT_NULL : MAINLOOP_IO_EVENT_IN); + io->mainloop->enable_io(io->mainloop, io->input_source, io->readable ? PA_MAINLOOP_API_IO_EVENT_NULL : PA_MAINLOOP_API_IO_EVENT_INPUT); if (io->output_source) - mainloop_source_io_set_events(io->output_source, io->writable ? MAINLOOP_IO_EVENT_NULL : MAINLOOP_IO_EVENT_OUT); + io->mainloop->enable_io(io->mainloop, io->output_source, io->writable ? PA_MAINLOOP_API_IO_EVENT_NULL : PA_MAINLOOP_API_IO_EVENT_OUTPUT); } } -static void callback(struct mainloop_source*s, int fd, enum mainloop_io_event events, void *userdata) { +static void callback(struct pa_mainloop_api* m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { struct iochannel *io = userdata; int changed = 0; - assert(s && fd >= 0 && userdata); + assert(m && fd >= 0 && events && userdata); - if ((events & MAINLOOP_IO_EVENT_IN) && !io->readable) { + if ((events & PA_MAINLOOP_API_IO_EVENT_INPUT) && !io->readable) { io->readable = 1; changed = 1; + assert(id == io->input_source); } - if ((events & MAINLOOP_IO_EVENT_OUT) && !io->writable) { + if ((events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) && !io->writable) { io->writable = 1; changed = 1; + assert(id == io->output_source); } if (changed) { @@ -64,15 +67,7 @@ static void callback(struct mainloop_source*s, int fd, enum mainloop_io_event ev } } -static void make_nonblock_fd(int fd) { - int v; - - if ((v = fcntl(fd, F_GETFL)) >= 0) - if (!(v & O_NONBLOCK)) - fcntl(fd, F_SETFL, v|O_NONBLOCK); -} - -struct iochannel* iochannel_new(struct mainloop*m, int ifd, int ofd) { +struct iochannel* iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd) { struct iochannel *io; assert(m && (ifd >= 0 || ofd >= 0)); @@ -90,18 +85,18 @@ struct iochannel* iochannel_new(struct mainloop*m, int ifd, int ofd) { if (ifd == ofd) { assert(ifd >= 0); make_nonblock_fd(io->ifd); - io->input_source = io->output_source = mainloop_source_new_io(m, ifd, MAINLOOP_IO_EVENT_IN|MAINLOOP_IO_EVENT_OUT, callback, io); + io->input_source = io->output_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_BOTH, callback, io); } else { if (ifd >= 0) { make_nonblock_fd(io->ifd); - io->input_source = mainloop_source_new_io(m, ifd, MAINLOOP_IO_EVENT_IN, callback, io); + io->input_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, io); } else io->input_source = NULL; if (ofd >= 0) { make_nonblock_fd(io->ofd); - io->output_source = mainloop_source_new_io(m, ofd, MAINLOOP_IO_EVENT_OUT, callback, io); + io->output_source = m->source_io(m, ofd, PA_MAINLOOP_API_IO_EVENT_OUTPUT, callback, io); } else io->output_source = NULL; } @@ -120,9 +115,9 @@ void iochannel_free(struct iochannel*io) { } if (io->input_source) - mainloop_source_free(io->input_source); + io->mainloop->cancel_io(io->mainloop, io->input_source); if (io->output_source && io->output_source != io->input_source) - mainloop_source_free(io->output_source); + io->mainloop->cancel_io(io->mainloop, io->output_source); free(io); } @@ -172,3 +167,8 @@ void iochannel_set_noclose(struct iochannel*io, int b) { assert(io); io->no_close = b; } + +void iochannel_peer_to_string(struct iochannel*io, char*s, size_t l) { + assert(io && s && l); + peer_to_string(s, l, io->ifd); +} diff --git a/src/iochannel.h b/src/iochannel.h index 8ed8b8789..b0465a194 100644 --- a/src/iochannel.h +++ b/src/iochannel.h @@ -2,11 +2,11 @@ #define fooiochannelhfoo #include -#include "mainloop.h" +#include "mainloop-api.h" struct iochannel; -struct iochannel* iochannel_new(struct mainloop*m, int ifd, int ofd); +struct iochannel* iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd); void iochannel_free(struct iochannel*io); ssize_t iochannel_write(struct iochannel*io, const void*data, size_t l); @@ -19,4 +19,6 @@ void iochannel_set_noclose(struct iochannel*io, int b); void iochannel_set_callback(struct iochannel*io, void (*callback)(struct iochannel*io, void *userdata), void *userdata); +void iochannel_peer_to_string(struct iochannel*io, char*s, size_t l); + #endif diff --git a/src/main.c b/src/main.c index f35505ecb..ef25b5e30 100644 --- a/src/main.c +++ b/src/main.c @@ -8,46 +8,52 @@ #include "core.h" #include "mainloop.h" #include "module.h" +#include "mainloop-signal.h" int stdin_inuse = 0, stdout_inuse = 0; -static void signal_callback(struct mainloop_source *m, int sig, void *userdata) { - mainloop_quit(mainloop_source_get_mainloop(m), -1); +static struct pa_mainloop *mainloop; + +static void signal_callback(void *id, int sig, void *userdata) { + struct pa_mainloop_api* m = pa_mainloop_get_api(mainloop); + m->quit(m, 1); fprintf(stderr, "main: got signal.\n"); } int main(int argc, char *argv[]) { - struct mainloop *m; struct core *c; - int r; + int r, retval = 0; r = lt_dlinit(); assert(r == 0); - m = mainloop_new(); - assert(m); - c = core_new(m); - assert(c); + mainloop = pa_mainloop_new(); + assert(mainloop); - mainloop_source_new_signal(m, SIGINT, signal_callback, NULL); + r = pa_signal_init(pa_mainloop_get_api(mainloop)); + assert(r == 0); + pa_signal_register(SIGINT, signal_callback, NULL); signal(SIGPIPE, SIG_IGN); + c = core_new(pa_mainloop_get_api(mainloop)); + assert(c); + module_load(c, "module-oss-mmap", "/dev/dsp1"); module_load(c, "module-pipe-sink", NULL); module_load(c, "module-simple-protocol-tcp", NULL); module_load(c, "module-cli", NULL); fprintf(stderr, "main: mainloop entry.\n"); - while (mainloop_iterate(m, 1) == 0); -/* fprintf(stderr, "main: %u blocks\n", n_blocks);*/ + if (pa_mainloop_run(mainloop, &retval) < 0) + retval = 1; fprintf(stderr, "main: mainloop exit.\n"); - - mainloop_run(m); core_free(c); - mainloop_free(m); + + pa_signal_done(); + pa_mainloop_free(mainloop); lt_dlexit(); - return 0; + return retval; } diff --git a/src/mainloop-api.c b/src/mainloop-api.c new file mode 100644 index 000000000..6caa0c25e --- /dev/null +++ b/src/mainloop-api.c @@ -0,0 +1,35 @@ +#include +#include +#include "mainloop-api.h" + +struct once_info { + void (*callback)(void *userdata); + void *userdata; +}; + +static void once_callback(struct pa_mainloop_api *api, void *id, void *userdata) { + struct once_info *i = userdata; + assert(api && i && i->callback); + i->callback(i->userdata); + assert(api->cancel_fixed); + api->cancel_fixed(api, id); + free(i); +} + +void pa_mainloop_api_once(struct pa_mainloop_api* api, void (*callback)(void *userdata), void *userdata) { + struct once_info *i; + void *id; + assert(api && callback); + + i = malloc(sizeof(struct once_info)); + assert(i); + i->callback = callback; + i->userdata = userdata; + + assert(api->source_fixed); + id = api->source_fixed(api, once_callback, i); + assert(id); + + /* Note: if the mainloop is destroyed before once_callback() was called, some memory is leaked. */ +} + diff --git a/src/mainloop-api.h b/src/mainloop-api.h new file mode 100644 index 000000000..96dacc22e --- /dev/null +++ b/src/mainloop-api.h @@ -0,0 +1,43 @@ +#ifndef foomainloopapihfoo +#define foomainloopapihfoo + +#include +#include + +enum pa_mainloop_api_io_events { + PA_MAINLOOP_API_IO_EVENT_NULL = 0, + PA_MAINLOOP_API_IO_EVENT_INPUT = 1, + PA_MAINLOOP_API_IO_EVENT_OUTPUT = 2, + PA_MAINLOOP_API_IO_EVENT_BOTH = 3 +}; + +struct pa_mainloop_api { + void *userdata; + + /* IO sources */ + void* (*source_io)(struct pa_mainloop_api*a, int fd, enum pa_mainloop_api_io_events events, void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata); + void (*enable_io)(struct pa_mainloop_api*a, void* id, enum pa_mainloop_api_io_events events); + void (*cancel_io)(struct pa_mainloop_api*a, void* id); + + /* Fixed sources */ + void* (*source_fixed)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata); + void (*enable_fixed)(struct pa_mainloop_api*a, void* id, int b); + void (*cancel_fixed)(struct pa_mainloop_api*a, void* id); + + /* Idle sources */ + void* (*source_idle)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata); + void (*enable_idle)(struct pa_mainloop_api*a, void* id, int b); + void (*cancel_idle)(struct pa_mainloop_api*a, void* id); + + /* Time sources */ + void* (*source_time)(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, void *id, const struct timeval *tv, void *userdata), void *userdata); + void (*enable_time)(struct pa_mainloop_api*a, void *id, const struct timeval *tv); + void (*cancel_time)(struct pa_mainloop_api*a, void* id); + + /* Exit mainloop */ + void (*quit)(struct pa_mainloop_api*a, int retval); +}; + +void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(void *userdata), void *userdata); + +#endif diff --git a/src/mainloop-signal.c b/src/mainloop-signal.c new file mode 100644 index 000000000..dcc72f69c --- /dev/null +++ b/src/mainloop-signal.c @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "mainloop-signal.h" +#include "util.h" + +struct signal_info { + int sig; + struct sigaction saved_sigaction; + void (*callback) (void *id, int signal, void *userdata); + void *userdata; + struct signal_info *previous, *next; +}; + +static struct pa_mainloop_api *api = NULL; +static int signal_pipe[2] = { -1, -1 }; +static void* mainloop_source = NULL; +static struct signal_info *signals = NULL; + +static void signal_handler(int sig) { + write(signal_pipe[1], &sig, sizeof(sig)); +} + +static void callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { + assert(a && id && events == PA_MAINLOOP_API_IO_EVENT_INPUT && id == mainloop_source && fd == signal_pipe[0]); + + for (;;) { + ssize_t r; + int sig; + struct signal_info*s; + + if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { + if (errno == EAGAIN) + return; + + fprintf(stderr, "signal.c: read(): %s\n", strerror(errno)); + return; + } + + if (r != sizeof(sig)) { + fprintf(stderr, "signal.c: short read()\n"); + return; + } + + for (s = signals; s; s = s->next) + if (s->sig == sig) { + assert(s->callback); + s->callback(s, sig, s->userdata); + break; + } + } +} + +int pa_signal_init(struct pa_mainloop_api *a) { + assert(a); + if (pipe(signal_pipe) < 0) { + fprintf(stderr, "pipe() failed: %s\n", strerror(errno)); + return -1; + } + + make_nonblock_fd(signal_pipe[0]); + make_nonblock_fd(signal_pipe[1]); + + api = a; + mainloop_source = api->source_io(api, signal_pipe[0], PA_MAINLOOP_API_IO_EVENT_INPUT, callback, NULL); + assert(mainloop_source); + return 0; +} + +void pa_signal_done(void) { + assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && mainloop_source); + + api->cancel_io(api, mainloop_source); + mainloop_source = NULL; + + close(signal_pipe[0]); + close(signal_pipe[1]); + signal_pipe[0] = signal_pipe[1] = -1; + + while (signals) + pa_signal_unregister(signals); + + api = NULL; +} + +void* pa_signal_register(int sig, void (*callback) (void *id, int signal, void *userdata), void *userdata) { + struct signal_info *s = NULL; + struct sigaction sa; + assert(sig > 0 && callback); + + for (s = signals; s; s = s->next) + if (s->sig == sig) + goto fail; + + s = malloc(sizeof(struct signal_info)); + assert(s); + s->sig = sig; + s->callback = callback; + s->userdata = userdata; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + if (sigaction(sig, &sa, &s->saved_sigaction) < 0) + goto fail; + + s->previous = NULL; + s->next = signals; + signals = s; + + return s; +fail: + if (s) + free(s); + return NULL; +} + +void pa_signal_unregister(void *id) { + struct signal_info *s = id; + assert(s); + + if (s->next) + s->next->previous = s->previous; + if (s->previous) + s->previous->next = s->next; + else + signals = s->next; + + sigaction(s->sig, &s->saved_sigaction, NULL); + free(s); +} diff --git a/src/mainloop-signal.h b/src/mainloop-signal.h new file mode 100644 index 000000000..e3e2364d5 --- /dev/null +++ b/src/mainloop-signal.h @@ -0,0 +1,12 @@ +#ifndef foomainloopsignalhfoo +#define foomainloopsignalhfoo + +#include "mainloop-api.h" + +int pa_signal_init(struct pa_mainloop_api *api); +void pa_signal_done(void); + +void* pa_signal_register(int signal, void (*callback) (void *id, int signal, void *userdata), void *userdata); +void pa_signal_unregister(void *id); + +#endif diff --git a/src/mainloop.c b/src/mainloop.c index fba0461c8..a1758c658 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -8,468 +9,515 @@ #include #include "mainloop.h" +#include "util.h" +#include "idxset.h" -struct mainloop_source { - struct mainloop_source *next; - struct mainloop *mainloop; - enum mainloop_source_type type; - - int enabled; +struct mainloop_source_header { + struct pa_mainloop *mainloop; int dead; +}; + +struct mainloop_source_io { + struct mainloop_source_header header; + + int fd; + enum pa_mainloop_api_io_events events; + void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata); void *userdata; - struct { - int fd; - enum mainloop_io_event events; - void (*callback)(struct mainloop_source*s, int fd, enum mainloop_io_event event, void *userdata); - struct pollfd pollfd; - } io; - - struct { - void (*callback)(struct mainloop_source*s, void *userdata); - } fixed; - - struct { - void (*callback)(struct mainloop_source*s, void *userdata); - } idle; - - struct { - int sig; - struct sigaction sigaction; - void (*callback)(struct mainloop_source*s, int sig, void *userdata); - } signal; + struct pollfd *pollfd; }; -struct mainloop_source_list { - struct mainloop_source *sources; - int n_sources; - int dead_sources; +struct mainloop_source_fixed_or_idle { + struct mainloop_source_header header; + int enabled; + + void (*callback)(struct pa_mainloop_api*a, void *id, void *userdata); + void *userdata; }; -struct mainloop { - struct mainloop_source_list io_sources, fixed_sources, idle_sources, signal_sources; +struct mainloop_source_time { + struct mainloop_source_header header; + int enabled; + struct timeval timeval; + void (*callback)(struct pa_mainloop_api*a, void *id, const struct timeval*tv, void *userdata); + void *userdata; +}; + +struct pa_mainloop { + struct idxset *io_sources, *fixed_sources, *idle_sources, *time_sources; + int io_sources_scan_dead, fixed_sources_scan_dead, idle_sources_scan_dead, time_sources_scan_dead; + struct pollfd *pollfds; - int max_pollfds, n_pollfds; + unsigned max_pollfds, n_pollfds; int rebuild_pollfds; - int quit; - int running; - int signal_pipe[2]; - struct pollfd signal_pollfd; + int quit, running, retval; + struct pa_mainloop_api api; }; -static int signal_pipe = -1; +static void setup_api(struct pa_mainloop *m); -static void signal_func(int sig) { - if (signal_pipe >= 0) - write(signal_pipe, &sig, sizeof(sig)); -} +struct pa_mainloop *pa_mainloop_new(void) { + struct pa_mainloop *m; -static void make_nonblock(int fd) { - int v; - - if ((v = fcntl(fd, F_GETFL)) >= 0) - fcntl(fd, F_SETFL, v|O_NONBLOCK); -} - - -struct mainloop *mainloop_new(void) { - int r; - struct mainloop *m; - - m = malloc(sizeof(struct mainloop)); + m = malloc(sizeof(struct pa_mainloop)); assert(m); - memset(m, 0, sizeof(struct mainloop)); - r = pipe(m->signal_pipe); - assert(r >= 0 && m->signal_pipe[0] >= 0 && m->signal_pipe[1] >= 0); + m->io_sources = idxset_new(NULL, NULL); + m->fixed_sources = idxset_new(NULL, NULL); + m->idle_sources = idxset_new(NULL, NULL); + m->time_sources = idxset_new(NULL, NULL); - make_nonblock(m->signal_pipe[0]); - make_nonblock(m->signal_pipe[1]); + assert(m->io_sources && m->fixed_sources && m->idle_sources && m->time_sources); + + m->io_sources_scan_dead = m->fixed_sources_scan_dead = m->idle_sources_scan_dead = m->time_sources_scan_dead = 0; - signal_pipe = m->signal_pipe[1]; - m->signal_pollfd.fd = m->signal_pipe[0]; - m->signal_pollfd.events = POLLIN; - m->signal_pollfd.revents = 0; + m->pollfds = NULL; + m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0; + + m->quit = m->running = m->retval = 0; + + setup_api(m); return m; } -static void free_sources(struct mainloop_source_list *l, int all) { - struct mainloop_source *s, *p; - assert(l); +static int foreach(void *p, uint32_t index, int *del, void*userdata) { + struct mainloop_source_header *h = p; + int *all = userdata; + assert(p && del && all); - if (!all && !l->dead_sources) - return; - - p = NULL; - s = l->sources; - while (s) { - if (all || s->dead) { - struct mainloop_source *t = s; - s = s->next; - - if (p) - p->next = s; - else - l->sources = s; - - free(t); - } else { - p = s; - s = s->next; - } + if (*all || h->dead) { + free(h); + *del = 1; } - l->dead_sources = 0; + return 0; +}; - if (all) { - assert(!l->sources); - l->n_sources = 0; - } -} - -void mainloop_free(struct mainloop* m) { +void pa_mainloop_free(struct pa_mainloop* m) { + int all = 1; assert(m); - free_sources(&m->io_sources, 1); - free_sources(&m->fixed_sources, 1); - free_sources(&m->idle_sources, 1); - free_sources(&m->signal_sources, 1); + idxset_foreach(m->io_sources, foreach, &all); + idxset_foreach(m->fixed_sources, foreach, &all); + idxset_foreach(m->idle_sources, foreach, &all); + idxset_foreach(m->time_sources, foreach, &all); + + idxset_free(m->io_sources, NULL, NULL); + idxset_free(m->fixed_sources, NULL, NULL); + idxset_free(m->idle_sources, NULL, NULL); + idxset_free(m->time_sources, NULL, NULL); - if (signal_pipe == m->signal_pipe[1]) - signal_pipe = -1; - close(m->signal_pipe[0]); - close(m->signal_pipe[1]); - free(m->pollfds); free(m); } -static void rebuild_pollfds(struct mainloop *m) { - struct mainloop_source*s; +static void scan_dead(struct pa_mainloop *m) { + int all = 0; + assert(m); + if (m->io_sources_scan_dead) + idxset_foreach(m->io_sources, foreach, &all); + if (m->fixed_sources_scan_dead) + idxset_foreach(m->fixed_sources, foreach, &all); + if (m->idle_sources_scan_dead) + idxset_foreach(m->idle_sources, foreach, &all); + if (m->time_sources_scan_dead) + idxset_foreach(m->time_sources, foreach, &all); +} + +static void rebuild_pollfds(struct pa_mainloop *m) { + struct mainloop_source_io*s; struct pollfd *p; - - if (m->max_pollfds < m->io_sources.n_sources+1) { - m->max_pollfds = (m->io_sources.n_sources+1)*2; - m->pollfds = realloc(m->pollfds, sizeof(struct pollfd)*m->max_pollfds); + uint32_t index = IDXSET_INVALID; + unsigned l; + + l = idxset_ncontents(m->io_sources); + if (m->max_pollfds < l) { + m->pollfds = realloc(m->pollfds, sizeof(struct pollfd)*l); + m->max_pollfds = l; } m->n_pollfds = 0; p = m->pollfds; - for (s = m->io_sources.sources; s; s = s->next) { - assert(s->type == MAINLOOP_SOURCE_TYPE_IO); - if (!s->dead && s->enabled && s->io.events != MAINLOOP_IO_EVENT_NULL) { - *(p++) = s->io.pollfd; - m->n_pollfds++; + for (s = idxset_first(m->io_sources, &index); s; s = idxset_next(m->io_sources, &index)) { + if (s->header.dead) { + s->pollfd = NULL; + continue; } - } - *(p++) = m->signal_pollfd; - m->n_pollfds++; + s->pollfd = p; + p->fd = s->fd; + p->events = ((s->events & PA_MAINLOOP_API_IO_EVENT_INPUT) ? POLLIN : 0) | ((s->events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) ? POLLOUT : 0); + p->revents = 0; + + p++; + m->n_pollfds++; + } } -static void dispatch_pollfds(struct mainloop *m) { - int i; - struct pollfd *p; - struct mainloop_source *s; - /* This loop assumes that m->sources and m->pollfds have the same - * order and that m->pollfds is a subset of m->sources! */ +static void dispatch_pollfds(struct pa_mainloop *m) { + uint32_t index = IDXSET_INVALID; + struct mainloop_source_io *s; - s = m->io_sources.sources; - for (p = m->pollfds, i = 0; i < m->n_pollfds; p++, i++) { - if (!p->revents) + for (s = idxset_first(m->io_sources, &index); s; s = idxset_next(m->io_sources, &index)) { + if (s->header.dead || !s->events || !s->pollfd || !s->pollfd->revents) + continue; + + assert(s->pollfd->revents <= s->pollfd->events && s->pollfd->fd == s->fd && s->callback); + s->callback(&m->api, s, s->fd, ((s->pollfd->revents & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | ((s->pollfd->revents & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), s->userdata); + } +} + +static void run_fixed_or_idle(struct pa_mainloop *m, struct idxset *i) { + uint32_t index = IDXSET_INVALID; + struct mainloop_source_fixed_or_idle *s; + + for (s = idxset_first(i, &index); s; s = idxset_next(i, &index)) { + if (s->header.dead || !s->enabled) continue; - if (p->fd == m->signal_pipe[0]) { - /* Event from signal pipe */ + assert(s->callback); + s->callback(&m->api, s, s->userdata); + } +} - if (p->revents & POLLIN) { - int sig; - ssize_t r; - r = read(m->signal_pipe[0], &sig, sizeof(sig)); - assert((r < 0 && errno == EAGAIN) || r == sizeof(sig)); +static int calc_next_timeout(struct pa_mainloop *m) { + uint32_t index = IDXSET_INVALID; + struct mainloop_source_time *s; + struct timeval now; + int t = -1; + + if (idxset_isempty(m->time_sources)) + return -1; + + gettimeofday(&now, NULL); + + for (s = idxset_first(m->time_sources, &index); s; s = idxset_next(m->time_sources, &index)) { + int tmp; + + if (s->header.dead || !s->enabled) + continue; + + if (s->timeval.tv_sec < now.tv_sec || (s->timeval.tv_sec == now.tv_sec && s->timeval.tv_usec <= now.tv_usec)) + return 0; + + tmp = (s->timeval.tv_sec - now.tv_sec)*1000; - if (r == sizeof(sig)) { - struct mainloop_source *l = m->signal_sources.sources; - while (l) { - assert(l->type == MAINLOOP_SOURCE_TYPE_SIGNAL); - - if (l->signal.sig == sig && l->enabled && !l->dead) { - assert(l->signal.callback); - l->signal.callback(l, sig, l->userdata); - } - - l = l->next; - } - } - } + if (s->timeval.tv_usec > now.tv_usec) + tmp += (s->timeval.tv_usec - now.tv_usec)/1000; + else + tmp -= (now.tv_usec - s->timeval.tv_usec)/1000; - } else { - /* Event from I/O source */ + if (tmp == 0) + return 0; + else if (tmp < t) + t = tmp; + } - for (; s; s = s->next) { - if (p->fd != s->io.fd) - continue; - - assert(s->type == MAINLOOP_SOURCE_TYPE_IO); + return t; +} - if (!s->dead && s->enabled) { - enum mainloop_io_event e = (p->revents & POLLIN ? MAINLOOP_IO_EVENT_IN : 0) | (p->revents & POLLOUT ? MAINLOOP_IO_EVENT_OUT : 0); - if (e) { - assert(s->io.callback); - s->io.callback(s, s->io.fd, e, s->userdata); - } - } +static void dispatch_timeout(struct pa_mainloop *m) { + uint32_t index = IDXSET_INVALID; + struct mainloop_source_time *s; + struct timeval now; + assert(m); - break; - } + if (idxset_isempty(m->time_sources)) + return; + + gettimeofday(&now, NULL); + for (s = idxset_first(m->time_sources, &index); s; s = idxset_next(m->time_sources, &index)) { + + if (s->header.dead || !s->enabled) + continue; + + if (s->timeval.tv_sec < now.tv_sec || (s->timeval.tv_sec == now.tv_sec && s->timeval.tv_usec <= now.tv_usec)) { + assert(s->callback); + + s->enabled = 0; + s->callback(&m->api, s, &s->timeval, s->userdata); } } } -int mainloop_iterate(struct mainloop *m, int block) { - struct mainloop_source *s; - int c; +static int any_idle_sources(struct pa_mainloop *m) { + struct mainloop_source_fixed_or_idle *s; + uint32_t index; + assert(m); + + for (s = idxset_first(m->idle_sources, &index); s; s = idxset_next(m->idle_sources, &index)) + if (!s->header.dead && s->enabled) + return 1; + + return 0; +} + +int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { + int r, idle; assert(m && !m->running); - if(m->quit) - return m->quit; - - free_sources(&m->io_sources, 0); - free_sources(&m->fixed_sources, 0); - free_sources(&m->idle_sources, 0); - free_sources(&m->signal_sources, 0); - - for (s = m->fixed_sources.sources; s; s = s->next) { - assert(s->type == MAINLOOP_SOURCE_TYPE_FIXED); - if (!s->dead && s->enabled) { - assert(s->fixed.callback); - s->fixed.callback(s, s->userdata); - } + if(m->quit) { + if (retval) + *retval = m->retval; + return 1; } + m->running = 1; + + scan_dead(m); + run_fixed_or_idle(m, m->fixed_sources); + if (m->rebuild_pollfds) { rebuild_pollfds(m); m->rebuild_pollfds = 0; } - m->running = 1; + idle = any_idle_sources(m); do { - c = poll(m->pollfds, m->n_pollfds, (block && !m->idle_sources.n_sources) ? -1 : 0); - } while (c < 0 && errno == EINTR); - - if (c > 0) + int t; + + if (!block || idle) + t = 0; + else + t = calc_next_timeout(m); + + r = poll(m->pollfds, m->n_pollfds, t); + } while (r < 0 && errno == EINTR); + + dispatch_timeout(m); + + if (r > 0) dispatch_pollfds(m); - else if (c == 0) { - for (s = m->idle_sources.sources; s; s = s->next) { - assert(s->type == MAINLOOP_SOURCE_TYPE_IDLE); - if (!s->dead && s->enabled) { - assert(s->idle.callback); - s->idle.callback(s, s->userdata); - } - } - } + else if (r == 0 && idle) + run_fixed_or_idle(m, m->idle_sources); + else if (r < 0) + fprintf(stderr, "select(): %s\n", strerror(errno)); m->running = 0; - return c < 0 ? -1 : 0; + return r < 0 ? -1 : 0; } -int mainloop_run(struct mainloop *m) { +int pa_mainloop_run(struct pa_mainloop *m, int *retval) { int r; - while (!(r = mainloop_iterate(m, 1))); + while ((r = pa_mainloop_iterate(m, 1, retval)) == 0); return r; } -void mainloop_quit(struct mainloop *m, int r) { +void pa_mainloop_quit(struct pa_mainloop *m, int r) { assert(m); m->quit = r; } -static struct mainloop_source_list* get_source_list(struct mainloop *m, enum mainloop_source_type type) { - struct mainloop_source_list *l; - - switch(type) { - case MAINLOOP_SOURCE_TYPE_IO: - l = &m->io_sources; - break; - case MAINLOOP_SOURCE_TYPE_FIXED: - l = &m->fixed_sources; - break; - case MAINLOOP_SOURCE_TYPE_IDLE: - l = &m->idle_sources; - break; - case MAINLOOP_SOURCE_TYPE_SIGNAL: - l = &m->signal_sources; - break; - default: - l = NULL; - break; - } - - return l; -} +/* IO sources */ +static void* mainloop_source_io(struct pa_mainloop_api*a, int fd, enum pa_mainloop_api_io_events events, void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata) { + struct pa_mainloop *m; + struct mainloop_source_io *s; + assert(a && a->userdata && fd >= 0 && callback); + m = a->userdata; + assert(a == &m->api); -static struct mainloop_source *source_new(struct mainloop*m, enum mainloop_source_type type) { - struct mainloop_source_list *l; - struct mainloop_source* s; - assert(m); - - s = malloc(sizeof(struct mainloop_source)); + s = malloc(sizeof(struct mainloop_source_io)); assert(s); - memset(s, 0, sizeof(struct mainloop_source)); + s->header.mainloop = m; + s->header.dead = 0; - s->type = type; - s->mainloop = m; - - l = get_source_list(m, type); - assert(l); - - s->next = l->sources; - l->sources = s; - l->n_sources++; - return s; -} - -struct mainloop_source* mainloop_source_new_io(struct mainloop*m, int fd, enum mainloop_io_event event, void (*callback)(struct mainloop_source*s, int fd, enum mainloop_io_event event, void *userdata), void *userdata) { - struct mainloop_source* s; - assert(m && fd>=0 && callback); - - s = source_new(m, MAINLOOP_SOURCE_TYPE_IO); - - s->io.fd = fd; - s->io.events = event; - s->io.callback = callback; + s->fd = fd; + s->events = events; + s->callback = callback; s->userdata = userdata; - s->io.pollfd.fd = fd; - s->io.pollfd.events = (event & MAINLOOP_IO_EVENT_IN ? POLLIN : 0) | (event & MAINLOOP_IO_EVENT_OUT ? POLLOUT : 0); - s->io.pollfd.revents = 0; - - s->enabled = 1; + s->pollfd = NULL; + idxset_put(m->io_sources, s, NULL); m->rebuild_pollfds = 1; return s; } -struct mainloop_source* mainloop_source_new_fixed(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata) { - struct mainloop_source* s; - assert(m && callback); +static void mainloop_enable_io(struct pa_mainloop_api*a, void* id, enum pa_mainloop_api_io_events events) { + struct pa_mainloop *m; + struct mainloop_source_io *s = id; + assert(a && a->userdata && s && !s->header.dead); + m = a->userdata; + assert(a == &m->api && s->header.mainloop == m); - s = source_new(m, MAINLOOP_SOURCE_TYPE_FIXED); + s->events = events; + if (s->pollfd) + s->pollfd->events = ((s->events & PA_MAINLOOP_API_IO_EVENT_INPUT) ? POLLIN : 0) | ((s->events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) ? POLLOUT : 0); +} + +static void mainloop_cancel_io(struct pa_mainloop_api*a, void* id) { + struct pa_mainloop *m; + struct mainloop_source_io *s = id; + assert(a && a->userdata && s && !s->header.dead); + m = a->userdata; + assert(a == &m->api && s->header.mainloop == m); + + s->header.dead = 1; + m->io_sources_scan_dead = 1; +} + +/* Fixed sources */ +static void* mainloop_source_fixed(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata) { + struct pa_mainloop *m; + struct mainloop_source_fixed_or_idle *s; + assert(a && a->userdata && callback); + m = a->userdata; + assert(a == &m->api); + + s = malloc(sizeof(struct mainloop_source_fixed_or_idle)); + assert(s); + s->header.mainloop = m; + s->header.dead = 0; - s->fixed.callback = callback; - s->userdata = userdata; s->enabled = 1; + s->callback = callback; + s->userdata = userdata; + + idxset_put(m->fixed_sources, s, NULL); return s; } -struct mainloop_source* mainloop_source_new_idle(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata) { - struct mainloop_source* s; - assert(m && callback); - - s = source_new(m, MAINLOOP_SOURCE_TYPE_IDLE); - - s->idle.callback = callback; - s->userdata = userdata; - s->enabled = 1; - return s; -} - -struct mainloop_source* mainloop_source_new_signal(struct mainloop*m, int sig, void (*callback)(struct mainloop_source *s, int sig, void*userdata), void*userdata) { - struct mainloop_source* s; - struct sigaction save_sa, sa; - - assert(m && callback); - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = signal_func; - sa.sa_flags = SA_RESTART; - sigemptyset(&sa.sa_mask); - - memset(&save_sa, 0, sizeof(save_sa)); - - if (sigaction(sig, &sa, &save_sa) < 0) - return NULL; - - s = source_new(m, MAINLOOP_SOURCE_TYPE_SIGNAL); - s->signal.sig = sig; - s->signal.sigaction = save_sa; - - s->signal.callback = callback; - s->userdata = userdata; - s->enabled = 1; - return s; -} - -void mainloop_source_free(struct mainloop_source*s) { - struct mainloop_source_list *l; - assert(s && !s->dead); - s->dead = 1; - - assert(s->mainloop); - l = get_source_list(s->mainloop, s->type); - assert(l); - - l->n_sources--; - l->dead_sources = 1; - - if (s->type == MAINLOOP_SOURCE_TYPE_IO) - s->mainloop->rebuild_pollfds = 1; - else if (s->type == MAINLOOP_SOURCE_TYPE_SIGNAL) - sigaction(s->signal.sig, &s->signal.sigaction, NULL); -} - -void mainloop_source_enable(struct mainloop_source*s, int b) { - assert(s && !s->dead); - - if (s->type == MAINLOOP_SOURCE_TYPE_IO && ((s->enabled && !b) || (!s->enabled && b))) { - assert(s->mainloop); - s->mainloop->rebuild_pollfds = 1; - } +static void mainloop_enable_fixed(struct pa_mainloop_api*a, void* id, int b) { + struct pa_mainloop *m; + struct mainloop_source_fixed_or_idle *s = id; + assert(a && a->userdata && s && !s->header.dead); + m = a->userdata; + assert(a == &m->api); s->enabled = b; } -void mainloop_source_io_set_events(struct mainloop_source*s, enum mainloop_io_event events) { - assert(s && !s->dead && s->type == MAINLOOP_SOURCE_TYPE_IO); +static void mainloop_cancel_fixed(struct pa_mainloop_api*a, void* id) { + struct pa_mainloop *m; + struct mainloop_source_fixed_or_idle *s = id; + assert(a && a->userdata && s && !s->header.dead); + m = a->userdata; + assert(a == &m->api); - if (s->io.events != events) { - assert(s->mainloop); - s->mainloop->rebuild_pollfds = 1; - } - - s->io.events = events; - s->io.pollfd.events = ((events & MAINLOOP_IO_EVENT_IN) ? POLLIN : 0) | ((events & MAINLOOP_IO_EVENT_OUT) ? POLLOUT : 0); + s->header.dead = 1; + m->fixed_sources_scan_dead = 1; } -struct mainloop *mainloop_source_get_mainloop(struct mainloop_source *s) { +/* Idle sources */ +static void* mainloop_source_idle(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata) { + struct pa_mainloop *m; + struct mainloop_source_fixed_or_idle *s; + assert(a && a->userdata && callback); + m = a->userdata; + assert(a == &m->api); + + s = malloc(sizeof(struct mainloop_source_fixed_or_idle)); assert(s); + s->header.mainloop = m; + s->header.dead = 0; - return s->mainloop; + s->enabled = 1; + s->callback = callback; + s->userdata = userdata; + + idxset_put(m->idle_sources, s, NULL); + return s; } -struct once_info { - void (*callback)(void *userdata); - void *userdata; -}; +static void mainloop_cancel_idle(struct pa_mainloop_api*a, void* id) { + struct pa_mainloop *m; + struct mainloop_source_fixed_or_idle *s = id; + assert(a && a->userdata && s && !s->header.dead); + m = a->userdata; + assert(a == &m->api); -static void once_callback(struct mainloop_source *s, void *userdata) { - struct once_info *i = userdata; - assert(s && i && i->callback); - i->callback(i->userdata); - mainloop_source_free(s); - free(i); + s->header.dead = 1; + m->idle_sources_scan_dead = 1; } -void mainloop_once(struct mainloop*m, void (*callback)(void *userdata), void *userdata) { - struct once_info *i; - assert(m && callback); +/* Time sources */ +static void* mainloop_source_time(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, void *id, const struct timeval *tv, void *userdata), void *userdata) { + struct pa_mainloop *m; + struct mainloop_source_time *s; + assert(a && a->userdata && callback); + m = a->userdata; + assert(a == &m->api); - i = malloc(sizeof(struct once_info)); - assert(i); - i->callback = callback; - i->userdata = userdata; + s = malloc(sizeof(struct mainloop_source_time)); + assert(s); + s->header.mainloop = m; + s->header.dead = 0; + + s->enabled = !!tv; + if (tv) + s->timeval = *tv; + + s->callback = callback; + s->userdata = userdata; + + idxset_put(m->time_sources, s, NULL); + return s; +} + +static void mainloop_enable_time(struct pa_mainloop_api*a, void *id, const struct timeval *tv) { + struct pa_mainloop *m; + struct mainloop_source_time *s = id; + assert(a && a->userdata && s && !s->header.dead); + m = a->userdata; + assert(a == &m->api); + + if (tv) { + s->enabled = 1; + s->timeval = *tv; + } else + s->enabled = 0; +} + +static void mainloop_cancel_time(struct pa_mainloop_api*a, void* id) { + struct pa_mainloop *m; + struct mainloop_source_time *s = id; + assert(a && a->userdata && s && !s->header.dead); + m = a->userdata; + assert(a == &m->api); + + s->header.dead = 1; + m->time_sources_scan_dead = 1; + +} + +static void mainloop_quit(struct pa_mainloop_api*a, int retval) { + struct pa_mainloop *m; + assert(a && a->userdata); + m = a->userdata; + assert(a == &m->api); + + m->quit = 1; + m->retval = retval; +} - mainloop_source_new_fixed(m, once_callback, i); +static void setup_api(struct pa_mainloop *m) { + assert(m); + + m->api.userdata = m; + m->api.source_io = mainloop_source_io; + m->api.enable_io = mainloop_enable_io; + m->api.cancel_io = mainloop_cancel_io; + + m->api.source_fixed = mainloop_source_fixed; + m->api.enable_fixed = mainloop_enable_fixed; + m->api.cancel_fixed = mainloop_cancel_fixed; + + m->api.source_idle = mainloop_source_idle; + m->api.enable_idle = mainloop_enable_fixed; /* (!) */ + m->api.cancel_idle = mainloop_cancel_idle; + + m->api.source_time = mainloop_source_time; + m->api.enable_time = mainloop_enable_time; + m->api.cancel_time = mainloop_cancel_time; + + m->api.quit = mainloop_quit; } + +struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m) { + assert(m); + return &m->api; +} + diff --git a/src/mainloop.h b/src/mainloop.h index c1bfc62af..7837636f9 100644 --- a/src/mainloop.h +++ b/src/mainloop.h @@ -1,42 +1,16 @@ #ifndef foomainloophfoo #define foomainloophfoo -struct mainloop; -struct mainloop_source; +#include "mainloop-api.h" -enum mainloop_io_event { - MAINLOOP_IO_EVENT_NULL = 0, - MAINLOOP_IO_EVENT_IN = 1, - MAINLOOP_IO_EVENT_OUT = 2, - MAINLOOP_IO_EVENT_BOTH = 3 -}; +struct pa_mainloop; -enum mainloop_source_type { - MAINLOOP_SOURCE_TYPE_IO, - MAINLOOP_SOURCE_TYPE_FIXED, - MAINLOOP_SOURCE_TYPE_IDLE, - MAINLOOP_SOURCE_TYPE_SIGNAL -}; +struct pa_mainloop *pa_mainloop_new(void); +void pa_mainloop_free(struct pa_mainloop* m); -struct mainloop *mainloop_new(void); -void mainloop_free(struct mainloop* m); +int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval); +int pa_mainloop_run(struct pa_mainloop *m, int *retval); -int mainloop_iterate(struct mainloop *m, int block); -int mainloop_run(struct mainloop *m); -void mainloop_quit(struct mainloop *m, int r); - -struct mainloop_source* mainloop_source_new_io(struct mainloop*m, int fd, enum mainloop_io_event event, void (*callback)(struct mainloop_source*s, int fd, enum mainloop_io_event event, void *userdata), void *userdata); -struct mainloop_source* mainloop_source_new_fixed(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata); -struct mainloop_source* mainloop_source_new_idle(struct mainloop*m, void (*callback)(struct mainloop_source *s, void*userdata), void*userdata); -struct mainloop_source* mainloop_source_new_signal(struct mainloop*m, int sig, void (*callback)(struct mainloop_source *s, int sig, void*userdata), void*userdata); - -void mainloop_once(struct mainloop*m, void (*callback)(void *userdata), void *userdata); - -void mainloop_source_free(struct mainloop_source*s); -void mainloop_source_enable(struct mainloop_source*s, int b); - -void mainloop_source_io_set_events(struct mainloop_source*s, enum mainloop_io_event event); - -struct mainloop *mainloop_source_get_mainloop(struct mainloop_source *s); +struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m); #endif diff --git a/src/memblockq.c b/src/memblockq.c index 10c59e507..9a601c3ae 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -220,3 +220,12 @@ uint32_t memblockq_get_length(struct memblockq *bq) { assert(bq); return bq->total_length; } + +uint32_t memblockq_missing_to(struct memblockq *bq, size_t qlen) { + assert(bq && qlen); + + if (bq->total_length >= qlen) + return 0; + + return qlen - bq->total_length; +} diff --git a/src/memblockq.h b/src/memblockq.h index 0a68ddaff..a681ff080 100644 --- a/src/memblockq.h +++ b/src/memblockq.h @@ -25,4 +25,6 @@ int memblockq_is_writable(struct memblockq *bq, size_t length); uint32_t memblockq_get_delay(struct memblockq *bq); uint32_t memblockq_get_length(struct memblockq *bq); +uint32_t memblockq_missing_to(struct memblockq *bq, size_t qlen); + #endif diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index bfc3a6fa1..b70ea6bda 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -16,15 +16,15 @@ #include "source.h" #include "module.h" #include "oss.h" +#include "sample-util.h" struct userdata { struct sink *sink; struct source *source; struct core *core; - struct sample_spec sample_spec; + struct pa_sample_spec sample_spec; - size_t in_fragment_size, out_fragment_size, in_fragments, out_fragments, sample_size, out_fill; - uint32_t sample_usec; + size_t in_fragment_size, out_fragment_size, in_fragments, out_fragments, out_fill; int fd; @@ -161,12 +161,14 @@ static void do_read(struct userdata *u) { in_clear_memblocks(u, u->in_fragments/2); }; -static void io_callback(struct mainloop_source*s, int fd, enum mainloop_io_event event, void *userdata) { +static void io_callback(struct pa_mainloop_api *m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { struct userdata *u = userdata; - if (event & MAINLOOP_IO_EVENT_IN) + assert (u && u->core->mainloop == m && u->mainloop_source == id); + + if (events & PA_MAINLOOP_API_IO_EVENT_INPUT) do_read(u); - if (event & MAINLOOP_IO_EVENT_OUT) + if (events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) do_write(u); } @@ -175,7 +177,7 @@ static uint32_t sink_get_latency_cb(struct sink *s) { assert(s && u); do_write(u); - return u->out_fill/u->sample_size*u->sample_usec; + return pa_samples_usec(u->out_fill, &s->sample_spec); } int module_init(struct core *c, struct module*m) { @@ -316,10 +318,7 @@ int module_init(struct core *c, struct module*m) { assert(u->source || u->sink); - u->sample_size = sample_size(&u->sample_spec); - u->sample_usec = 1000000/u->sample_spec.rate; - - u->mainloop_source = mainloop_source_new_io(c->mainloop, u->fd, (u->source ? MAINLOOP_IO_EVENT_IN : 0) | (u->sink ? MAINLOOP_IO_EVENT_OUT : 0), io_callback, u); + u->mainloop_source = c->mainloop->source_io(c->mainloop, u->fd, (u->source ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | (u->sink ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), io_callback, u); assert(u->mainloop_source); return 0; @@ -360,7 +359,7 @@ void module_done(struct core *c, struct module*m) { source_free(u->source); if (u->mainloop_source) - mainloop_source_free(u->mainloop_source); + u->core->mainloop->cancel_io(u->core->mainloop, u->mainloop_source); if (u->fd >= 0) close(u->fd); diff --git a/src/module-oss.c b/src/module-oss.c index fab5c8c55..4f3075453 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -15,7 +15,7 @@ #include "source.h" #include "module.h" #include "oss.h" -#include "sample.h" +#include "sample-util.h" struct userdata { struct sink *sink; @@ -81,7 +81,7 @@ static void do_read(struct userdata *u) { return; } - assert(r <= memchunk.memblock->length); + assert(r <= (ssize_t) memchunk.memblock->length); memchunk.length = memchunk.memblock->length = r; memchunk.index = 0; @@ -107,7 +107,7 @@ static uint32_t sink_get_latency_cb(struct sink *s) { return 0; } - return samples_usec(arg, &s->sample_spec); + return pa_samples_usec(arg, &s->sample_spec); } int module_init(struct core *c, struct module*m) { @@ -117,7 +117,7 @@ int module_init(struct core *c, struct module*m) { int fd = -1; int frag_size, in_frag_size, out_frag_size; int mode; - struct sample_spec ss; + struct pa_sample_spec ss; assert(c && m); p = m->argument ? m->argument : "/dev/dsp"; @@ -203,7 +203,7 @@ int module_init(struct core *c, struct module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; - u->sample_size = sample_size(&ss); + u->sample_size = pa_sample_size(&ss); u->out_fragment_size = out_frag_size; u->in_fragment_size = in_frag_size; diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index c0a903e94..9dcf5d231 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -18,7 +18,8 @@ struct userdata { struct sink *sink; struct iochannel *io; struct core *core; - struct mainloop_source *mainloop_source; + void *mainloop_source; + struct pa_mainloop_api *mainloop; struct memchunk memchunk; }; @@ -27,7 +28,7 @@ static void do_write(struct userdata *u) { ssize_t r; assert(u); - mainloop_source_enable(u->mainloop_source, 0); + u->mainloop->enable_fixed(u->mainloop, u->mainloop_source, 0); if (!iochannel_is_writable(u->io)) return; @@ -57,10 +58,10 @@ static void notify_cb(struct sink*s) { assert(s && u); if (iochannel_is_writable(u->io)) - mainloop_source_enable(u->mainloop_source, 1); + u->mainloop->enable_fixed(u->mainloop, u->mainloop_source, 1); } -static void prepare_callback(struct mainloop_source *src, void *userdata) { +static void fixed_callback(struct pa_mainloop_api *m, void *id, void *userdata) { struct userdata *u = userdata; assert(u); do_write(u); @@ -77,7 +78,7 @@ int module_init(struct core *c, struct module*m) { struct stat st; char *p; int fd = -1; - static const struct sample_spec ss = { + static const struct pa_sample_spec ss = { .format = SAMPLE_S16NE, .rate = 44100, .channels = 2, @@ -120,10 +121,11 @@ int module_init(struct core *c, struct module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; - u->mainloop_source = mainloop_source_new_fixed(c->mainloop, prepare_callback, u); + u->mainloop = c->mainloop; + u->mainloop_source = u->mainloop->source_fixed(u->mainloop, fixed_callback, u); assert(u->mainloop_source); - mainloop_source_enable(u->mainloop_source, 0); - + u->mainloop->enable_fixed(u->mainloop, u->mainloop_source, 0); + m->userdata = u; return 0; @@ -147,7 +149,7 @@ void module_done(struct core *c, struct module*m) { sink_free(u->sink); iochannel_free(u->io); - mainloop_source_free(u->mainloop_source); + u->mainloop->cancel_fixed(u->mainloop, u->mainloop_source); assert(u->filename); unlink(u->filename); diff --git a/src/module.c b/src/module.c index c6de1751a..883a22df9 100644 --- a/src/module.c +++ b/src/module.c @@ -151,5 +151,5 @@ void module_unload_request(struct core *c, struct module *m) { assert(i); i->core = c; i->index = m->index; - mainloop_once(c->mainloop, module_unload_once_callback, i); + pa_mainloop_api_once(c->mainloop, module_unload_once_callback, i); } diff --git a/src/oss.c b/src/oss.c index 7b1315c00..02bf8cd1c 100644 --- a/src/oss.c +++ b/src/oss.c @@ -7,7 +7,7 @@ #include "oss.h" -int oss_auto_format(int fd, struct sample_spec *ss) { +int oss_auto_format(int fd, struct pa_sample_spec *ss) { int format, channels, speed; assert(fd >= 0 && ss); diff --git a/src/oss.h b/src/oss.h index 35d2dd023..34ac9c669 100644 --- a/src/oss.h +++ b/src/oss.h @@ -3,6 +3,6 @@ #include "sample.h" -int oss_auto_format(int fd, struct sample_spec *ss); +int oss_auto_format(int fd, struct pa_sample_spec *ss); #endif diff --git a/src/pacat.c b/src/pacat.c new file mode 100644 index 000000000..5f5a373bb --- /dev/null +++ b/src/pacat.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include + +#include "polyp.h" +#include "mainloop.h" + +static struct pa_context *context = NULL; +static struct pa_stream *stream = NULL; +static struct pa_mainloop_api *mainloop_api = NULL; + +static void *buffer = NULL; +static size_t buffer_length = 0, buffer_index = 0; + +static void* stdin_source = NULL; + +static void context_die_callback(struct pa_context *c, void *userdata) { + assert(c); + fprintf(stderr, "Connection to server shut down, exiting.\n"); + mainloop_api->quit(mainloop_api, 1); +} + +static void stream_die_callback(struct pa_stream *s, void *userdata) { + assert(s); + fprintf(stderr, "Stream deleted, exiting.\n"); + mainloop_api->quit(mainloop_api, 1); +} + +static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { + size_t l; + assert(s && length); + + mainloop_api->enable_io(mainloop_api, stdin_source, PA_STREAM_PLAYBACK); + + if (!buffer) + return; + + assert(buffer_length); + + l = length; + if (l > buffer_length) + l = buffer_length; + + pa_stream_write(s, buffer+buffer_index, l); + buffer_length -= l; + buffer_index += l; + + if (!buffer_length) { + free(buffer); + buffer = NULL; + buffer_index = buffer_length = 0; + } +} + +static void stream_complete_callback(struct pa_context*c, struct pa_stream *s, void *userdata) { + assert(c); + + if (!s) { + fprintf(stderr, "Stream creation failed.\n"); + mainloop_api->quit(mainloop_api, 1); + } + + stream = s; + pa_stream_set_die_callback(stream, stream_die_callback, NULL); + pa_stream_set_write_callback(stream, stream_write_callback, NULL); +} + +static void context_complete_callback(struct pa_context *c, int success, void *userdata) { + static const struct pa_sample_spec ss = { + .format = SAMPLE_S16NE, + .rate = 44100, + .channels = 2 + }; + + assert(c && !stream); + + if (!success) { + fprintf(stderr, "Connection failed\n"); + goto fail; + } + + if (pa_stream_new(c, PA_STREAM_PLAYBACK, NULL, "pacat", &ss, NULL, stream_complete_callback, NULL) < 0) { + fprintf(stderr, "pa_stream_new() failed.\n"); + goto fail; + } + + return; + +fail: + mainloop_api->quit(mainloop_api, 1); +} + +static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { + size_t l; + ssize_t r; + assert(a == mainloop_api && id && fd == STDIN_FILENO && events == PA_MAINLOOP_API_IO_EVENT_INPUT); + + if (buffer) { + mainloop_api->enable_io(mainloop_api, stdin_source, PA_MAINLOOP_API_IO_EVENT_NULL); + return; + } + + if (!(l = pa_stream_writable_size(stream))) + l = 4096; + buffer = malloc(l); + assert(buffer); + if ((r = read(fd, buffer, l)) <= 0) { + if (r == 0) + mainloop_api->quit(mainloop_api, 0); + else { + fprintf(stderr, "read() failed: %s\n", strerror(errno)); + mainloop_api->quit(mainloop_api, 1); + } + + return; + } + + buffer_length = r; + buffer_index = 0; +} + +int main(int argc, char *argv[]) { + struct pa_mainloop* m; + int ret = 1; + + if (!(m = pa_mainloop_new())) { + fprintf(stderr, "pa_mainloop_new() failed.\n"); + goto quit; + } + + mainloop_api = pa_mainloop_get_api(m); + + if (!(stdin_source = mainloop_api->source_io(mainloop_api, STDIN_FILENO, PA_MAINLOOP_API_IO_EVENT_INPUT, stdin_callback, NULL))) { + fprintf(stderr, "source_io() failed.\n"); + goto quit; + } + + if (!(context = pa_context_new(mainloop_api, argv[0]))) { + fprintf(stderr, "pa_context_new() failed.\n"); + goto quit; + } + + if (pa_context_connect(context, NULL, context_complete_callback, NULL) < 0) { + fprintf(stderr, "pa_context_connext() failed.\n"); + goto quit; + } + + pa_context_set_die_callback(context, context_die_callback, NULL); + + if (pa_mainloop_run(m, &ret) < 0) { + fprintf(stderr, "pa_mainloop_run() failed.\n"); + goto quit; + } + +quit: + if (stream) + pa_stream_free(stream); + if (context) + pa_context_free(context); + if (m) + pa_mainloop_free(m); + if (buffer) + free(buffer); + + return ret; +} diff --git a/src/packet.c b/src/packet.c index 47fce9194..0f966d9a7 100644 --- a/src/packet.c +++ b/src/packet.c @@ -16,7 +16,7 @@ struct packet* packet_new(size_t length) { return p; } -struct packet* packet_dynamic(uint8_t* data, size_t length) { +struct packet* packet_new_dynamic(uint8_t* data, size_t length) { struct packet *p; assert(data && length); p = malloc(sizeof(struct packet)); @@ -26,6 +26,7 @@ struct packet* packet_dynamic(uint8_t* data, size_t length) { p->length = length; p->data = data; p->type = PACKET_DYNAMIC; + return p; } struct packet* packet_ref(struct packet *p) { diff --git a/src/pdispatch.c b/src/pdispatch.c new file mode 100644 index 000000000..48b6639d2 --- /dev/null +++ b/src/pdispatch.c @@ -0,0 +1,149 @@ +#include +#include +#include +#include "pdispatch.h" +#include "protocol-native-spec.h" + +struct reply_info { + struct pdispatch *pdispatch; + struct reply_info *next, *previous; + int (*callback)(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); + void *userdata; + uint32_t tag; + void *mainloop_timeout; +}; + +struct pdispatch { + struct pa_mainloop_api *mainloop; + const struct pdispatch_command *command_table; + unsigned n_commands; + struct reply_info *replies; +}; + +static void reply_info_free(struct reply_info *r) { + assert(r && r->pdispatch && r->pdispatch->mainloop); + r->pdispatch->mainloop->cancel_time(r->pdispatch->mainloop, r->mainloop_timeout); + + if (r->previous) + r->previous->next = r->next; + else + r->pdispatch->replies = r->next; + + if (r->next) + r->next->previous = r->previous; + + free(r); +} + +struct pdispatch* pdispatch_new(struct pa_mainloop_api *mainloop, const struct pdispatch_command*table, unsigned entries) { + struct pdispatch *pd; + assert(mainloop); + + assert((entries && table) || (!entries && !table)); + + pd = malloc(sizeof(struct pdispatch)); + assert(pd); + pd->mainloop = mainloop; + pd->command_table = table; + pd->n_commands = entries; + return pd; +} + +void pdispatch_free(struct pdispatch *pd) { + assert(pd); + while (pd->replies) + reply_info_free(pd->replies); + free(pd); +} + +int pdispatch_run(struct pdispatch *pd, struct packet*packet, void *userdata) { + uint32_t tag, command; + assert(pd && packet); + struct tagstruct *ts = NULL; + assert(pd && packet && packet->data); + + if (packet->length <= 8) + goto fail; + + ts = tagstruct_new(packet->data, packet->length); + assert(ts); + + if (tagstruct_getu32(ts, &command) < 0 || + tagstruct_getu32(ts, &tag) < 0) + goto fail; + + if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) { + struct reply_info *r; + int done = 0; + + for (r = pd->replies; r; r = r->next) { + if (r->tag == tag) { + int ret = r->callback(r->pdispatch, command, tag, ts, r->userdata); + reply_info_free(r); + + if (ret < 0) + goto fail; + + done = 1; + break; + } + } + + if (!done) + goto fail; + + } else if (pd->command_table && command < pd->n_commands) { + const struct pdispatch_command *c = pd->command_table+command; + + if (!c->proc) + goto fail; + + if (c->proc(pd, command, tag, ts, userdata) < 0) + goto fail; + } else + goto fail; + + tagstruct_free(ts); + + return 0; + +fail: + if (ts) + tagstruct_free(ts); + + fprintf(stderr, "protocol-native: invalid packet.\n"); + return -1; +} + +static void timeout_callback(struct pa_mainloop_api*m, void *id, const struct timeval *tv, void *userdata) { + struct reply_info*r = userdata; + assert (r && r->mainloop_timeout == id && r->pdispatch && r->pdispatch->mainloop == m && r->callback); + + r->callback(r->pdispatch, PA_COMMAND_TIMEOUT, r->tag, NULL, r->userdata); + reply_info_free(r); +} + +void pdispatch_register_reply(struct pdispatch *pd, uint32_t tag, int timeout, int (*cb)(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata), void *userdata) { + struct reply_info *r; + struct timeval tv; + assert(pd && cb); + + r = malloc(sizeof(struct reply_info)); + assert(r); + r->pdispatch = pd; + r->callback = cb; + r->userdata = userdata; + r->tag = tag; + + gettimeofday(&tv, NULL); + tv.tv_sec += timeout; + + r->mainloop_timeout = pd->mainloop->source_time(pd->mainloop, &tv, timeout_callback, r); + assert(r->mainloop_timeout); + + r->previous = NULL; + r->next = pd->replies; + if (r->next) + r->next->previous = r; + pd->replies = r; +} diff --git a/src/pdispatch.h b/src/pdispatch.h new file mode 100644 index 000000000..466da9a46 --- /dev/null +++ b/src/pdispatch.h @@ -0,0 +1,22 @@ +#ifndef foopdispatchhfoo +#define foopdispatchhfoo + +#include +#include "tagstruct.h" +#include "packet.h" +#include "mainloop-api.h" + +struct pdispatch; + +struct pdispatch_command { + int (*proc)(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); +}; + +struct pdispatch* pdispatch_new(struct pa_mainloop_api *m, const struct pdispatch_command*table, unsigned entries); +void pdispatch_free(struct pdispatch *pd); + +int pdispatch_run(struct pdispatch *pd, struct packet*p, void *userdata); + +void pdispatch_register_reply(struct pdispatch *pd, uint32_t tag, int timeout, int (*cb)(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata), void *userdata); + +#endif diff --git a/src/polyp.c b/src/polyp.c new file mode 100644 index 000000000..fdff7f9c3 --- /dev/null +++ b/src/polyp.c @@ -0,0 +1,451 @@ +#include +#include +#include +#include + +#include "polyp.h" +#include "protocol-native-spec.h" +#include "pdispatch.h" +#include "pstream.h" +#include "dynarray.h" +#include "socket-client.h" +#include "pstream-util.h" + +#define DEFAULT_QUEUE_LENGTH 10240 +#define DEFAULT_MAX_LENGTH 20480 +#define DEFAULT_PREBUF 4096 +#define DEFAULT_TIMEOUT 5 + +struct pa_context { + char *name; + struct pa_mainloop_api* mainloop; + struct socket_client *client; + struct pstream *pstream; + struct pdispatch *pdispatch; + struct dynarray *streams; + struct pa_stream *first_stream; + uint32_t ctag; + uint32_t errno; + enum { CONTEXT_UNCONNECTED, CONTEXT_CONNECTING, CONTEXT_READY, CONTEXT_DEAD} state; + + void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); + void *connect_complete_userdata; + + void (*die_callback)(struct pa_context*c, void *userdata); + void *die_userdata; +}; + +struct pa_stream { + struct pa_context *context; + struct pa_stream *next, *previous; + uint32_t channel; + int channel_valid; + enum pa_stream_direction direction; + enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; + uint32_t requested_bytes; + + void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); + void *read_userdata; + + void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); + void *write_userdata; + + void (*create_complete_callback)(struct pa_context*c, struct pa_stream *s, void *userdata); + void *create_complete_userdata; + + void (*die_callback)(struct pa_stream*c, void *userdata); + void *die_userdata; +}; + +static int command_request(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); + +static const struct pdispatch_command command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = { NULL }, + [PA_COMMAND_REPLY] = { NULL }, + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_EXIT] = { NULL }, + [PA_COMMAND_REQUEST] = { command_request }, +}; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { + assert(mainloop && name); + struct pa_context *c; + c = malloc(sizeof(struct pa_context)); + assert(c); + c->name = strdup(name); + c->mainloop = mainloop; + c->client = NULL; + c->pstream = NULL; + c->pdispatch = NULL; + c->streams = dynarray_new(); + assert(c->streams); + c->first_stream = NULL; + c->errno = PA_ERROR_OK; + c->state = CONTEXT_UNCONNECTED; + c->ctag = 0; + + c->connect_complete_callback = NULL; + c->connect_complete_userdata = NULL; + + c->die_callback = NULL; + c->die_userdata = NULL; + + return c; +} + +void pa_context_free(struct pa_context *c) { + assert(c); + + while (c->first_stream) + pa_stream_free(c->first_stream); + + if (c->client) + socket_client_free(c->client); + if (c->pdispatch) + pdispatch_free(c->pdispatch); + if (c->pstream) + pstream_free(c->pstream); + if (c->streams) + dynarray_free(c->streams, NULL, NULL); + + free(c->name); + free(c); +} + +static void stream_dead(struct pa_stream *s) { + if (s->state == STREAM_DEAD) + return; + + s->state = STREAM_DEAD; + if (s->die_callback) + s->die_callback(s, s->die_userdata); +} + +static void context_dead(struct pa_context *c) { + struct pa_stream *s; + assert(c); + + for (s = c->first_stream; s; s = s->next) + stream_dead(s); + + if (c->state == CONTEXT_DEAD) + return; + + c->state = CONTEXT_DEAD; + if (c->die_callback) + c->die_callback(c, c->die_userdata); +} + +static void pstream_die_callback(struct pstream *p, void *userdata) { + struct pa_context *c = userdata; + assert(p && c); + + assert(c->state != CONTEXT_DEAD); + + c->state = CONTEXT_DEAD; + + context_dead(c); +} + +static int pstream_packet_callback(struct pstream *p, struct packet *packet, void *userdata) { + struct pa_context *c = userdata; + assert(p && packet && c); + + if (pdispatch_run(c->pdispatch, packet, c) < 0) { + fprintf(stderr, "polyp.c: invalid packet.\n"); + return -1; + } + + return 0; +} + +static int pstream_memblock_callback(struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + assert(p && chunk && c && chunk->memblock && chunk->memblock->data); + + if (!(s = dynarray_get(c->streams, channel))) + return -1; + + if (s->read_callback) + s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); + + return 0; +} + +static void on_connection(struct socket_client *client, struct iochannel*io, void *userdata) { + struct pa_context *c = userdata; + assert(client && io && c && c->state == CONTEXT_CONNECTING); + + socket_client_free(client); + c->client = NULL; + + if (!io) { + c->errno = PA_ERROR_CONNECTIONREFUSED; + c->state = CONTEXT_UNCONNECTED; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + c->pstream = pstream_new(c->mainloop, io); + assert(c->pstream); + pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + + c->pdispatch = pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); + assert(c->pdispatch); + + c->state = CONTEXT_READY; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 1, c->connect_complete_userdata); +} + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { + assert(c && c->state == CONTEXT_UNCONNECTED); + + assert(!c->client); + if (!(c->client = socket_client_new_unix(c->mainloop, server))) { + c->errno = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + + c->connect_complete_callback = complete; + c->connect_complete_userdata = userdata; + + socket_client_set_callback(c->client, on_connection, c); + c->state = CONTEXT_CONNECTING; + + return 0; +} + +int pa_context_is_dead(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_DEAD; +} + +int pa_context_is_ready(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_READY; +} + +int pa_context_errno(struct pa_context *c) { + assert(c); + return c->errno; +} + +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { + assert(c); + c->die_callback = cb; + c->die_userdata = userdata; +} + +static int command_request(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata) { + struct pa_stream *s; + struct pa_context *c = userdata; + uint32_t bytes, channel; + assert(pd && command == PA_COMMAND_REQUEST && t && s); + + if (tagstruct_getu32(t, &channel) < 0 || + tagstruct_getu32(t, &bytes) < 0 || + tagstruct_eof(t)) { + c->errno = PA_ERROR_PROTOCOL; + return -1; + } + + if (!(s = dynarray_get(c->streams, channel))) { + c->errno = PA_ERROR_PROTOCOL; + return -1; + } + + s->requested_bytes += bytes; + + if (s->requested_bytes && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); + + return 0; +} + +static int create_playback_callback(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata) { + int ret = 0; + struct pa_stream *s = userdata; + assert(pd && s && s->state == STREAM_CREATING); + + if (command != PA_COMMAND_REPLY) { + struct pa_context *c = s->context; + assert(c); + + if (command == PA_COMMAND_ERROR && tagstruct_getu32(t, &s->context->errno) < 0) { + s->context->errno = PA_ERROR_PROTOCOL; + ret = -1; + } else if (command == PA_COMMAND_TIMEOUT) { + s->context->errno = PA_ERROR_TIMEOUT; + ret = -1; + } + + goto fail; + } + + if (tagstruct_getu32(t, &s->channel) < 0 || + tagstruct_eof(t)) { + s->context->errno = PA_ERROR_PROTOCOL; + ret = -1; + goto fail; + } + + s->channel_valid = 1; + dynarray_put(s->context->streams, s->channel, s); + + s->state = STREAM_READY; + assert(s->create_complete_callback); + s->create_complete_callback(s->context, s, s->create_complete_userdata); + return 0; + +fail: + assert(s->create_complete_callback); + s->create_complete_callback(s->context, NULL, s->create_complete_userdata); + pa_stream_free(s); + return ret; +} + +int pa_stream_new( + struct pa_context *c, + enum pa_stream_direction dir, + const char *dev, + const char *name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr, + void (*complete) (struct pa_context*c, struct pa_stream *s, void *userdata), + void *userdata) { + + struct pa_stream *s; + struct tagstruct *t; + uint32_t tag; + + assert(c && name && ss && c->state == CONTEXT_READY && complete); + + s = malloc(sizeof(struct pa_stream)); + assert(s); + s->context = c; + + s->read_callback = NULL; + s->read_userdata = NULL; + s->write_callback = NULL; + s->write_userdata = NULL; + s->die_callback = NULL; + s->die_userdata = NULL; + s->create_complete_callback = complete; + s->create_complete_userdata = NULL; + + s->state = STREAM_CREATING; + s->requested_bytes = 0; + s->channel = 0; + s->channel_valid = 0; + s->direction = dir; + + t = tagstruct_new(NULL, 0); + assert(t); + + tagstruct_putu32(t, dir == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + tagstruct_putu32(t, tag = c->ctag++); + tagstruct_puts(t, name); + tagstruct_put_sample_spec(t, ss); + tagstruct_putu32(t, (uint32_t) -1); + tagstruct_putu32(t, attr ? attr->queue_length : DEFAULT_QUEUE_LENGTH); + tagstruct_putu32(t, attr ? attr->max_length : DEFAULT_MAX_LENGTH); + tagstruct_putu32(t, attr ? attr->prebuf : DEFAULT_PREBUF); + + pstream_send_tagstruct(c->pstream, t); + + pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_playback_callback, s); + + s->next = c->first_stream; + if (s->next) + s->next->previous = s; + s->previous = NULL; + c->first_stream = s; + + return 0; +} + +void pa_stream_free(struct pa_stream *s) { + assert(s && s->context); + + if (s->channel_valid) { + struct tagstruct *t = tagstruct_new(NULL, 0); + assert(t); + + tagstruct_putu32(t, PA_COMMAND_DELETE_PLAYBACK_STREAM); + tagstruct_putu32(t, s->context->ctag++); + tagstruct_putu32(t, s->channel); + pstream_send_tagstruct(s->context->pstream, t); + } + + if (s->channel_valid) + dynarray_put(s->context->streams, s->channel, NULL); + + if (s->next) + s->next->previous = s->previous; + if (s->previous) + s->previous->next = s->next; + else + s->context->first_stream = s->next; + + free(s); +} + +void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { + assert(s && cb); + s->write_callback = cb; + s->write_userdata = userdata; +} + +void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { + struct memchunk chunk; + assert(s && s->context && data && length); + + chunk.memblock = memblock_new(length); + assert(chunk.memblock && chunk.memblock->data); + memcpy(chunk.memblock->data, data, length); + chunk.index = 0; + chunk.length = length; + + pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + + if (length < s->requested_bytes) + s->requested_bytes -= length; + else + s->requested_bytes = 0; +} + +size_t pa_stream_writable_size(struct pa_stream *s) { + assert(s); + return s->requested_bytes; +} + +void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { + assert(s && cb); + s->read_callback = cb; + s->read_userdata = userdata; +} + +int pa_stream_is_dead(struct pa_stream *s) { + return s->state == STREAM_DEAD; +} + +int pa_stream_is_ready(struct pa_stream*s) { + return s->state == STREAM_READY; +} + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { + assert(s); + s->die_callback = cb; + s->die_userdata = userdata; +} diff --git a/src/polyp.h b/src/polyp.h new file mode 100644 index 000000000..171e3bdf8 --- /dev/null +++ b/src/polyp.h @@ -0,0 +1,53 @@ +#ifndef foopolyphfoo +#define foopolyphfoo + +#include + +#include "sample.h" +#include "polypdef.h" +#include "mainloop-api.h" + +struct pa_context; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); + +int pa_context_connect( + struct pa_context *c, + const char *server, + void (*complete) (struct pa_context*c, int success, void *userdata), + void *userdata); + +void pa_context_free(struct pa_context *c); + +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); + +int pa_context_is_dead(struct pa_context *c); +int pa_context_is_ready(struct pa_context *c); +int pa_contect_errno(struct pa_context *c); + +struct pa_stream; + +int pa_stream_new( + struct pa_context *c, + enum pa_stream_direction dir, + const char *dev, + const char *name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr, + void (*complete) (struct pa_context*c, struct pa_stream *s, void *userdata), + void *userdata); + +void pa_stream_free(struct pa_stream *p); + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); + +void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); +void pa_stream_write(struct pa_stream *p, const void *data, size_t length); +size_t pa_stream_writable_size(struct pa_stream *p); + +void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); + +int pa_stream_is_dead(struct pa_stream *p); +int pa_stream_is_ready(struct pa_stream*p); + +#endif diff --git a/src/polypdef.h b/src/polypdef.h new file mode 100644 index 000000000..aa6e6bf64 --- /dev/null +++ b/src/polypdef.h @@ -0,0 +1,18 @@ +#ifndef foopolypdefhfoo +#define foopolypdefhfoo + +#include + +enum pa_stream_direction { + PA_STREAM_PLAYBACK, + PA_STREAM_RECORD +}; + +struct pa_buffer_attr { + uint32_t queue_length; + uint32_t max_length; + uint32_t prebuf; +}; + + +#endif diff --git a/src/protocol-cli.c b/src/protocol-cli.c index c0c93d981..b6460fecf 100644 --- a/src/protocol-cli.c +++ b/src/protocol-cli.c @@ -12,8 +12,7 @@ struct protocol_cli { static void cli_eof_cb(struct cli*c, void*userdata) { struct protocol_cli *p = userdata; - assert(c && p); - + assert(p); idxset_remove_by_data(p->connections, c, NULL); cli_free(c); } @@ -22,7 +21,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us struct protocol_cli *p = userdata; struct cli *c; assert(s && io && p); - + c = cli_new(p->core, io); assert(c); cli_set_eof_callback(c, cli_eof_cb, p); diff --git a/src/protocol-native-spec.h b/src/protocol-native-spec.h new file mode 100644 index 000000000..df11ae3c6 --- /dev/null +++ b/src/protocol-native-spec.h @@ -0,0 +1,29 @@ +#ifndef fooprotocolnativespech +#define fooprotocolnativespech + +enum { + PA_COMMAND_ERROR, + PA_COMMAND_TIMEOUT, /* pseudo command */ + PA_COMMAND_REPLY, + PA_COMMAND_CREATE_PLAYBACK_STREAM, + PA_COMMAND_DELETE_PLAYBACK_STREAM, + PA_COMMAND_CREATE_RECORD_STREAM, + PA_COMMAND_DELETE_RECORD_STREAM, + PA_COMMAND_EXIT, + PA_COMMAND_REQUEST, + PA_COMMAND_MAX +}; + +enum { + PA_ERROR_OK, + PA_ERROR_ACCESS, + PA_ERROR_COMMAND, + PA_ERROR_INVALID, + PA_ERROR_EXIST, + PA_ERROR_NOENTITY, + PA_ERROR_CONNECTIONREFUSED, + PA_ERROR_PROTOCOL, + PA_ERROR_TIMEOUT +}; + +#endif diff --git a/src/protocol-native.c b/src/protocol-native.c index e9cca7c18..a39880b89 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -3,34 +3,19 @@ #include #include "protocol-native.h" +#include "protocol-native-spec.h" #include "packet.h" #include "client.h" #include "sourceoutput.h" #include "sinkinput.h" #include "pstream.h" #include "tagstruct.h" +#include "pdispatch.h" +#include "pstream-util.h" struct connection; struct protocol_native; -enum { - COMMAND_ERROR, - COMMAND_REPLY, - COMMAND_CREATE_PLAYBACK_STREAM, - COMMAND_DELETE_PLAYBACK_STREAM, - COMMAND_CREATE_RECORD_STREAM, - COMMAND_DELETE_RECORD_STREAM, - COMMAND_EXIT, - COMMAND_MAX -}; - -enum { - ERROR_ACCESS, - ERROR_COMMAND, - ERROR_ARGUMENT, - ERROR_EXIST -}; - struct record_stream { struct connection *connection; uint32_t index; @@ -41,6 +26,7 @@ struct record_stream { struct playback_stream { struct connection *connection; uint32_t index; + size_t qlength; struct sink_input *sink_input; struct memblockq *memblockq; }; @@ -50,6 +36,7 @@ struct connection { struct protocol_native *protocol; struct client *client; struct pstream *pstream; + struct pdispatch *pdispatch; struct idxset *record_streams, *playback_streams; }; @@ -60,6 +47,29 @@ struct protocol_native { struct idxset *connections; }; +static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk); +static void sink_input_drop_cb(struct sink_input *i, size_t length); +static void sink_input_kill_cb(struct sink_input *i); +static uint32_t sink_input_get_latency_cb(struct sink_input *i); + +static void request_bytes(struct playback_stream*s); + +static int command_exit(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); +static int command_create_playback_stream(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); +static int command_delete_playback_stream(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); + +static const struct pdispatch_command command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = { NULL }, + [PA_COMMAND_REPLY] = { NULL }, + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream }, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_playback_stream }, + [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_EXIT] = { command_exit }, +}; + +/* structure management */ + static void record_stream_free(struct record_stream* r) { assert(r && r->connection); @@ -69,18 +79,28 @@ static void record_stream_free(struct record_stream* r) { free(r); } -static struct playback_stream* playback_stream_new(struct connection *c, struct sink *sink, struct sample_spec *ss, const char *name, size_t maxlength, size_t prebuf) { +static struct playback_stream* playback_stream_new(struct connection *c, struct sink *sink, struct pa_sample_spec *ss, const char *name, size_t qlen, size_t maxlength, size_t prebuf) { struct playback_stream *s; + assert(c && sink && s && name && qlen && maxlength && prebuf); s = malloc(sizeof(struct playback_stream)); assert (s); s->connection = c; + s->qlength = qlen; + s->sink_input = sink_input_new(sink, ss, name); assert(s->sink_input); - s->memblockq = memblockq_new(maxlength, sample_size(ss), prebuf); + s->sink_input->peek = sink_input_peek_cb; + s->sink_input->drop = sink_input_drop_cb; + s->sink_input->kill = sink_input_kill_cb; + s->sink_input->get_latency = sink_input_get_latency_cb; + s->sink_input->userdata = s; + + s->memblockq = memblockq_new(maxlength, pa_sample_size(ss), prebuf); assert(s->memblockq); idxset_put(c->playback_streams, s, &s->index); + request_bytes(s); return s; } @@ -99,7 +119,6 @@ static void connection_free(struct connection *c) { assert(c && c->protocol); idxset_remove_by_data(c->protocol->connections, c, NULL); - pstream_free(c->pstream); while ((r = idxset_first(c->record_streams, NULL))) record_stream_free(r); idxset_free(c->record_streams, NULL, NULL); @@ -108,67 +127,90 @@ static void connection_free(struct connection *c) { playback_stream_free(p); idxset_free(c->playback_streams, NULL, NULL); + pdispatch_free(c->pdispatch); + pstream_free(c->pstream); client_free(c->client); free(c); } -/*** pstream callbacks ***/ +static void request_bytes(struct playback_stream *s) { + struct tagstruct *t; + size_t l; + assert(s); -static void send_tagstruct(struct pstream *p, struct tagstruct *t) { - size_t length; - uint8_t *data; - struct packet *packet; - assert(p && t); + if (!(l = memblockq_missing_to(s->memblockq, s->qlength))) + return; - data = tagstruct_free_data(t, &length); - assert(data && length); - packet = packet_new_dynamic(data, length); - assert(packet); - pstream_send_packet(p, packet); - packet_unref(packet); -} - -static void send_error(struct pstream *p, uint32_t tag, uint32_t error) { - struct tagstruct *t = tagstruct_new(NULL, 0); + t = tagstruct_new(NULL, 0); assert(t); - tagstruct_putu32(t, COMMAND_ERROR); - tagstruct_putu32(t, tag); - tagstruct_putu32(t, error); - send_tagstruct(p, t); + tagstruct_putu32(t, PA_COMMAND_REQUEST); + tagstruct_putu32(t, s->index); + tagstruct_putu32(t, l); + pstream_send_tagstruct(s->connection->pstream, t); } -static void send_simple_ack(struct pstream *p, uint32_t tag) { - struct tagstruct *t = tagstruct_new(NULL, 0); - assert(t); - tagstruct_putu32(t, COMMAND_REPLY); - tagstruct_putu32(t, tag); - send_tagstruct(p, t); -} +/*** sinkinput callbacks ***/ -struct command { - int (*func)(struct connection *c, uint32_t tag, struct tagstruct *t); -}; - -static int command_create_playback_stream(struct connection *c, uint32_t tag, struct tagstruct *t) { +static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk) { struct playback_stream *s; - size_t maxlength, prebuf; + assert(i && i->userdata && chunk); + s = i->userdata; + + if (memblockq_peek(s->memblockq, chunk) < 0) + return -1; + + return 0; +} + +static void sink_input_drop_cb(struct sink_input *i, size_t length) { + struct playback_stream *s; + assert(i && i->userdata && length); + s = i->userdata; + + memblockq_drop(s->memblockq, length); + request_bytes(s); +} + +static void sink_input_kill_cb(struct sink_input *i) { + struct playback_stream *s; + assert(i && i->userdata); + s = i->userdata; + + playback_stream_free(s); +} + +static uint32_t sink_input_get_latency_cb(struct sink_input *i) { + struct playback_stream *s; + assert(i && i->userdata); + s = i->userdata; + + return pa_samples_usec(memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); +} + +/*** pdispatch callbacks ***/ + +static int command_create_playback_stream(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata) { + struct connection *c = userdata; + struct playback_stream *s; + size_t maxlength, prebuf, qlength; uint32_t sink_index; const char *name; - struct sample_spec ss; + struct pa_sample_spec ss; struct tagstruct *reply; struct sink *sink; assert(c && t && c->protocol && c->protocol->core); if (tagstruct_gets(t, &name) < 0 || tagstruct_get_sample_spec(t, &ss) < 0 || - tagstruct_getu32(t, &sink_index) < 0 || + tagstruct_getu32(t, &sink_index) < 0 || + tagstruct_getu32(t, &qlength) < 0 || tagstruct_getu32(t, &maxlength) < 0 || tagstruct_getu32(t, &prebuf) < 0 || !tagstruct_eof(t)) return -1; if (!c->authorized) { - send_error(c->pstream, tag, ERROR_ACCESS); + pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); return 0; } @@ -178,25 +220,28 @@ static int command_create_playback_stream(struct connection *c, uint32_t tag, st sink = idxset_get_by_index(c->protocol->core->sinks, sink_index); if (!sink) { - send_error(c->pstream, tag, ERROR_EXIST); + pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); return 0; } - if (!(s = playback_stream_new(c, sink, &ss, name, maxlength, prebuf))) { - send_error(c->pstream, tag, ERROR_ARGUMENT); + if (!(s = playback_stream_new(c, sink, &ss, name, qlength, maxlength, prebuf))) { + pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); return 0; } reply = tagstruct_new(NULL, 0); assert(reply); - tagstruct_putu32(reply, COMMAND_REPLY); + tagstruct_putu32(reply, PA_COMMAND_REPLY); tagstruct_putu32(reply, tag); tagstruct_putu32(reply, s->index); - send_tagstruct(c->pstream, reply); + assert(s->sink_input); + tagstruct_putu32(reply, s->sink_input->index); + pstream_send_tagstruct(c->pstream, reply); return 0; } -static int command_delete_playback_stream(struct connection *c, uint32_t tag, struct tagstruct *t) { +static int command_delete_playback_stream(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata) { + struct connection *c = userdata; uint32_t channel; struct playback_stream *s; assert(c && t); @@ -206,78 +251,50 @@ static int command_delete_playback_stream(struct connection *c, uint32_t tag, st return -1; if (!c->authorized) { - send_error(c->pstream, tag, ERROR_ACCESS); + pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); return 0; } if (!(s = idxset_get_by_index(c->playback_streams, channel))) { - send_error(c->pstream, tag, ERROR_EXIST); + pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); return 0; } - send_simple_ack(c->pstream, tag); + pstream_send_simple_ack(c->pstream, tag); return 0; } -static int command_exit(struct connection *c, uint32_t tag, struct tagstruct *t) { +static int command_exit(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata) { + struct connection *c = userdata; assert(c && t); if (!tagstruct_eof(t)) return -1; if (!c->authorized) { - send_error(c->pstream, tag, ERROR_ACCESS); + pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); return 0; } - assert(c->protocol && c->protocol->core); - mainloop_quit(c->protocol->core->mainloop, -1); - send_simple_ack(c->pstream, tag); /* nonsense */ + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop); + c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0); + pstream_send_simple_ack(c->pstream, tag); /* nonsense */ return 0; } -static const struct command commands[] = { - [COMMAND_ERROR] = { NULL }, - [COMMAND_REPLY] = { NULL }, - [COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream }, - [COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_playback_stream }, - [COMMAND_CREATE_RECORD_STREAM] = { NULL }, - [COMMAND_DELETE_RECORD_STREAM] = { NULL }, - [COMMAND_EXIT] = { command_exit }, -}; +/*** pstream callbacks ***/ + static int packet_callback(struct pstream *p, struct packet *packet, void *userdata) { struct connection *c = userdata; - uint32_t tag, command; - struct tagstruct *ts = NULL; assert(p && packet && packet->data && c); - if (packet->length <= 8) - goto fail; - - ts = tagstruct_new(packet->data, packet->length); - assert(ts); - - if (tagstruct_getu32(ts, &command) < 0 || - tagstruct_getu32(ts, &tag) < 0) - goto fail; - - if (command >= COMMAND_MAX || !commands[command].func) - send_error(p, tag, ERROR_COMMAND); - else if (commands[command].func(c, tag, ts) < 0) - goto fail; + if (pdispatch_run(c->pdispatch, packet, c) < 0) { + fprintf(stderr, "protocol-native: invalid packet.\n"); + return -1; + } - tagstruct_free(ts); - return 0; - -fail: - if (ts) - tagstruct_free(ts); - - fprintf(stderr, "protocol-native: invalid packet.\n"); - return -1; - } static int memblock_callback(struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata) { @@ -326,6 +343,9 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us pstream_set_recieve_memblock_callback(c->pstream, memblock_callback, c); pstream_set_die_callback(c->pstream, die_callback, c); + c->pdispatch = pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX); + assert(c->pdispatch); + c->record_streams = idxset_new(NULL, NULL); c->playback_streams = idxset_new(NULL, NULL); assert(c->record_streams && c->playback_streams); diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 8e4246cd7..c8c458548 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -9,6 +9,7 @@ #include "sourceoutput.h" #include "protocol-simple.h" #include "client.h" +#include "sample-util.h" struct connection { struct protocol_simple *protocol; @@ -115,9 +116,10 @@ static int do_write(struct connection *c) { /*** sink_input callbacks ***/ static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk) { - struct connection*c = i->userdata; - assert(i && c && chunk); - + struct connection*c; + assert(i && i->userdata && chunk); + c = i->userdata; + if (memblockq_peek(c->input_memblockq, chunk) < 0) return -1; @@ -143,7 +145,7 @@ static void sink_input_kill_cb(struct sink_input *i) { static uint32_t sink_input_get_latency_cb(struct sink_input *i) { struct connection*c = i->userdata; assert(i && c); - return samples_usec(memblockq_get_length(c->input_memblockq), &DEFAULT_SAMPLE_SPEC); + return pa_samples_usec(memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); } /*** source_output callbacks ***/ @@ -185,6 +187,7 @@ static void io_callback(struct iochannel*io, void *userdata) { static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { struct protocol_simple *p = userdata; struct connection *c = NULL; + char cname[256]; assert(s && io && p); c = malloc(sizeof(struct connection)); @@ -195,7 +198,8 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->input_memblockq = c->output_memblockq = NULL; c->protocol = p; - c->client = client_new(p->core, "SIMPLE", "Client"); + iochannel_peer_to_string(io, cname, sizeof(cname)); + c->client = client_new(p->core, "SIMPLE", cname); assert(c->client); c->client->kill = client_kill_cb; c->client->userdata = c; @@ -215,8 +219,8 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->source_output->kill = source_output_kill_cb; c->source_output->userdata = c; - l = 5*bytes_per_second(&DEFAULT_SAMPLE_SPEC); /* 5s */ - c->output_memblockq = memblockq_new(l, sample_size(&DEFAULT_SAMPLE_SPEC), l/2); + l = 5*pa_bytes_per_second(&DEFAULT_SAMPLE_SPEC); /* 5s */ + c->output_memblockq = memblockq_new(l, pa_sample_size(&DEFAULT_SAMPLE_SPEC), l/2); } if (p->mode & PROTOCOL_SIMPLE_PLAYBACK) { @@ -236,8 +240,8 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->sink_input->get_latency = sink_input_get_latency_cb; c->sink_input->userdata = c; - l = bytes_per_second(&DEFAULT_SAMPLE_SPEC)/2; /* half a second */ - c->input_memblockq = memblockq_new(l, sample_size(&DEFAULT_SAMPLE_SPEC), l/2); + l = pa_bytes_per_second(&DEFAULT_SAMPLE_SPEC)/2; /* half a second */ + c->input_memblockq = memblockq_new(l, pa_sample_size(&DEFAULT_SAMPLE_SPEC), l/2); } diff --git a/src/pstream-util.c b/src/pstream-util.c new file mode 100644 index 000000000..2fab2b61c --- /dev/null +++ b/src/pstream-util.c @@ -0,0 +1,35 @@ +#include + +#include "protocol-native-spec.h" +#include "pstream-util.h" + +void pstream_send_tagstruct(struct pstream *p, struct tagstruct *t) { + size_t length; + uint8_t *data; + struct packet *packet; + assert(p && t); + + data = tagstruct_free_data(t, &length); + assert(data && length); + packet = packet_new_dynamic(data, length); + assert(packet); + pstream_send_packet(p, packet); + packet_unref(packet); +} + +void pstream_send_error(struct pstream *p, uint32_t tag, uint32_t error) { + struct tagstruct *t = tagstruct_new(NULL, 0); + assert(t); + tagstruct_putu32(t, PA_COMMAND_ERROR); + tagstruct_putu32(t, tag); + tagstruct_putu32(t, error); + pstream_send_tagstruct(p, t); +} + +void pstream_send_simple_ack(struct pstream *p, uint32_t tag) { + struct tagstruct *t = tagstruct_new(NULL, 0); + assert(t); + tagstruct_putu32(t, PA_COMMAND_REPLY); + tagstruct_putu32(t, tag); + pstream_send_tagstruct(p, t); +} diff --git a/src/pstream-util.h b/src/pstream-util.h new file mode 100644 index 000000000..4e64a95c0 --- /dev/null +++ b/src/pstream-util.h @@ -0,0 +1,14 @@ +#ifndef foopstreamutilhfoo +#define foopstreamutilhfoo + +#include +#include "pstream.h" +#include "tagstruct.h" + +/* The tagstruct is freed!*/ +void pstream_send_tagstruct(struct pstream *p, struct tagstruct *t); + +void pstream_send_error(struct pstream *p, uint32_t tag, uint32_t error); +void pstream_send_simple_ack(struct pstream *p, uint32_t tag); + +#endif diff --git a/src/pstream.c b/src/pstream.c index a63e126d1..4a3a648b1 100644 --- a/src/pstream.c +++ b/src/pstream.c @@ -30,7 +30,7 @@ struct item_info { }; struct pstream { - struct mainloop *mainloop; + struct pa_mainloop_api *mainloop; struct mainloop_source *mainloop_source; struct iochannel *io; struct queue *send_queue; @@ -70,18 +70,24 @@ static void do_read(struct pstream *p); static void io_callback(struct iochannel*io, void *userdata) { struct pstream *p = userdata; assert(p && p->io == io); + + p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0); + do_write(p); do_read(p); } -static void prepare_callback(struct mainloop_source *s, void*userdata) { +static void fixed_callback(struct pa_mainloop_api *m, void *id, void*userdata) { struct pstream *p = userdata; - assert(p && p->mainloop_source == s); + assert(p && p->mainloop_source == id && p->mainloop == m); + + p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0); + do_write(p); do_read(p); } -struct pstream *pstream_new(struct mainloop *m, struct iochannel *io) { +struct pstream *pstream_new(struct pa_mainloop_api *m, struct iochannel *io) { struct pstream *p; assert(io); @@ -96,8 +102,8 @@ struct pstream *pstream_new(struct mainloop *m, struct iochannel *io) { p->die_callback_userdata = NULL; p->mainloop = m; - p->mainloop_source = mainloop_source_new_fixed(m, prepare_callback, p); - mainloop_source_enable(p->mainloop_source, 0); + p->mainloop_source = m->source_fixed(m, fixed_callback, p); + m->enable_fixed(m, p->mainloop_source, 0); p->send_queue = queue_new(); assert(p->send_queue); @@ -152,7 +158,7 @@ void pstream_free(struct pstream *p) { if (p->read.packet) packet_unref(p->read.packet); - mainloop_source_free(p->mainloop_source); + p->mainloop->cancel_fixed(p->mainloop, p->mainloop_source); free(p); } @@ -173,7 +179,7 @@ void pstream_send_packet(struct pstream*p, struct packet *packet) { i->packet = packet_ref(packet); queue_push(p->send_queue, i); - mainloop_source_enable(p->mainloop_source, 1); + p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1); } void pstream_send_memblock(struct pstream*p, uint32_t channel, int32_t delta, struct memchunk *chunk) { @@ -190,7 +196,7 @@ void pstream_send_memblock(struct pstream*p, uint32_t channel, int32_t delta, st memblock_ref(i->chunk.memblock); queue_push(p->send_queue, i); - mainloop_source_enable(p->mainloop_source, 1); + p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1); } void pstream_set_recieve_packet_callback(struct pstream *p, int (*callback) (struct pstream *p, struct packet *packet, void *userdata), void *userdata) { @@ -219,7 +225,7 @@ static void prepare_next_write_item(struct pstream *p) { assert(p->write.current->packet); p->write.data = p->write.current->packet->data; p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length); - p->write.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] = 0; + p->write.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1); p->write.descriptor[PSTREAM_DESCRIPTOR_DELTA] = 0; } else { assert(p->write.current->type == PSTREAM_ITEM_MEMBLOCK && p->write.current->chunk.memblock); @@ -236,8 +242,6 @@ static void do_write(struct pstream *p) { ssize_t r; assert(p); - mainloop_source_enable(p->mainloop_source, 0); - if (p->dead || !iochannel_is_writable(p->io)) return; @@ -285,8 +289,6 @@ static void do_read(struct pstream *p) { ssize_t r; assert(p); - mainloop_source_enable(p->mainloop_source, 0); - if (p->dead || !iochannel_is_readable(p->io)) return; @@ -313,7 +315,7 @@ static void do_read(struct pstream *p) { assert(!p->read.packet && !p->read.memblock); - if (ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_CHANNEL]) == 0) { + if (ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_CHANNEL]) == (uint32_t) -1) { /* Frame is a packet frame */ p->read.packet = packet_new(ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH])); assert(p->read.packet); @@ -331,7 +333,7 @@ static void do_read(struct pstream *p) { if (p->read.memblock && p->recieve_memblock_callback) { /* Is this memblock data? Than pass it to the user */ size_t l; - l = p->read.index - r < PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PSTREAM_DESCRIPTOR_SIZE : r; + l = (p->read.index - r) < PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PSTREAM_DESCRIPTOR_SIZE : (size_t) r; if (l > 0) { struct memchunk chunk; diff --git a/src/pstream.h b/src/pstream.h index 7113681ea..d418908e0 100644 --- a/src/pstream.h +++ b/src/pstream.h @@ -6,10 +6,11 @@ #include "packet.h" #include "memblock.h" #include "iochannel.h" +#include "mainloop-api.h" struct pstream; -struct pstream* pstream_new(struct mainloop *m, struct iochannel *io); +struct pstream* pstream_new(struct pa_mainloop_api *m, struct iochannel *io); void pstream_free(struct pstream*p); void pstream_set_send_callback(struct pstream*p, void (*callback) (struct pstream *p, void *userdata), void *userdata); diff --git a/src/queue.c b/src/queue.c index 90823ae6f..5c2e7a67d 100644 --- a/src/queue.c +++ b/src/queue.c @@ -73,5 +73,12 @@ void* queue_pop(struct queue *q) { p = e->data; free(e); + q->length--; + return p; } + +int queue_is_empty(struct queue *q) { + assert(q); + return q->length == 0; +} diff --git a/src/sample-util.c b/src/sample-util.c new file mode 100644 index 000000000..7a3c267a8 --- /dev/null +++ b/src/sample-util.c @@ -0,0 +1,88 @@ +#include +#include + +#include "sample-util.h" + +struct pa_sample_spec default_sample_spec = { + .format = SAMPLE_S16NE, + .rate = 44100, + .channels = 2 +}; + +struct memblock *silence_memblock(struct memblock* b, struct pa_sample_spec *spec) { + assert(b && b->data && spec); + memblock_assert_exclusive(b); + silence_memory(b->data, b->length, spec); + return b; +} + +void silence_memchunk(struct memchunk *c, struct pa_sample_spec *spec) { + assert(c && c->memblock && c->memblock->data && spec && c->length); + memblock_assert_exclusive(c->memblock); + silence_memory(c->memblock->data+c->index, c->length, spec); +} + +void silence_memory(void *p, size_t length, struct pa_sample_spec *spec) { + char c = 0; + assert(p && length && spec); + + switch (spec->format) { + case SAMPLE_U8: + c = 127; + break; + case SAMPLE_S16LE: + case SAMPLE_S16BE: + case SAMPLE_FLOAT32: + c = 0; + break; + case SAMPLE_ALAW: + case SAMPLE_ULAW: + c = 80; + break; + } + + memset(p, c, length); +} + +size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct pa_sample_spec *spec, uint8_t volume) { + unsigned c, d; + assert(channels && data && length && spec); + assert(spec->format == SAMPLE_S16NE); + + for (d = 0;; d += sizeof(int16_t)) { + int32_t sum = 0; + + if (d >= length) + return d; + + for (c = 0; c < nchannels; c++) { + int32_t v; + uint8_t volume = channels[c].volume; + + if (d >= channels[c].chunk.length) + return d; + + if (volume == 0) + v = 0; + else { + v = *((int16_t*) (channels[c].chunk.memblock->data + channels[c].chunk.index + d)); + + if (volume != 0xFF) + v = v*volume/0xFF; + } + + sum += v; + } + + if (volume == 0) + sum = 0; + else if (volume != 0xFF) + sum = sum*volume/0xFF; + + if (sum < -0x8000) sum = -0x8000; + if (sum > 0x7FFF) sum = 0x7FFF; + + *((int16_t*) data) = sum; + data += sizeof(int16_t); + } +} diff --git a/src/sample-util.h b/src/sample-util.h new file mode 100644 index 000000000..0a3f7c894 --- /dev/null +++ b/src/sample-util.h @@ -0,0 +1,23 @@ +#ifndef foosampleutilhfoo +#define foosampleutilhfoo + +#include "sample.h" +#include "memblock.h" + +#define DEFAULT_SAMPLE_SPEC default_sample_spec + +extern struct pa_sample_spec default_sample_spec; + +struct memblock *silence_memblock(struct memblock* b, struct pa_sample_spec *spec); +void silence_memchunk(struct memchunk *c, struct pa_sample_spec *spec); +void silence_memory(void *p, size_t length, struct pa_sample_spec *spec); + +struct mix_info { + struct memchunk chunk; + uint8_t volume; + void *userdata; +}; + +size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct pa_sample_spec *spec, uint8_t volume); + +#endif diff --git a/src/sample.c b/src/sample.c index c270f255d..2454630cf 100644 --- a/src/sample.c +++ b/src/sample.c @@ -1,50 +1,8 @@ -#include #include #include "sample.h" -struct sample_spec default_sample_spec = { - .format = SAMPLE_S16NE, - .rate = 44100, - .channels = 2 -}; - -struct memblock *silence_memblock(struct memblock* b, struct sample_spec *spec) { - assert(b && b->data && spec); - memblock_assert_exclusive(b); - silence_memory(b->data, b->length, spec); - return b; -} - -void silence_memchunk(struct memchunk *c, struct sample_spec *spec) { - assert(c && c->memblock && c->memblock->data && spec && c->length); - memblock_assert_exclusive(c->memblock); - silence_memory(c->memblock->data+c->index, c->length, spec); -} - -void silence_memory(void *p, size_t length, struct sample_spec *spec) { - char c = 0; - assert(p && length && spec); - - switch (spec->format) { - case SAMPLE_U8: - c = 127; - break; - case SAMPLE_S16LE: - case SAMPLE_S16BE: - case SAMPLE_FLOAT32: - c = 0; - break; - case SAMPLE_ALAW: - case SAMPLE_ULAW: - c = 80; - break; - } - - memset(p, c, length); -} - -size_t sample_size(struct sample_spec *spec) { +size_t pa_sample_size(struct pa_sample_spec *spec) { assert(spec); size_t b = 1; @@ -66,56 +24,14 @@ size_t sample_size(struct sample_spec *spec) { return b * spec->channels; } -size_t bytes_per_second(struct sample_spec *spec) { +size_t pa_bytes_per_second(struct pa_sample_spec *spec) { assert(spec); - return spec->rate*sample_size(spec); + return spec->rate*pa_sample_size(spec); } -size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct sample_spec *spec, uint8_t volume) { - unsigned c, d; - assert(channels && data && length && spec); - assert(spec->format == SAMPLE_S16NE); - for (d = 0;; d += sizeof(int16_t)) { - int32_t sum = 0; - - if (d >= length) - return d; - - for (c = 0; c < nchannels; c++) { - int32_t v; - uint8_t volume = channels[c].volume; - - if (d >= channels[c].chunk.length) - return d; - - if (volume == 0) - v = 0; - else { - v = *((int16_t*) (channels[c].chunk.memblock->data + channels[c].chunk.index + d)); - - if (volume != 0xFF) - v = v*volume/0xFF; - } - - sum += v; - } - - if (volume == 0) - sum = 0; - else if (volume != 0xFF) - sum = sum*volume/0xFF; - - if (sum < -0x8000) sum = -0x8000; - if (sum > 0x7FFF) sum = 0x7FFF; - - *((int16_t*) data) = sum; - data += sizeof(int16_t); - } -} - -uint32_t samples_usec(size_t length, struct sample_spec *spec) { +uint32_t pa_samples_usec(size_t length, struct pa_sample_spec *spec) { assert(spec); - return (uint32_t) (((double) length /sample_size(spec))/spec->rate*1000000); + return (uint32_t) (((double) length /pa_sample_size(spec))/spec->rate*1000000); } diff --git a/src/sample.h b/src/sample.h index b2f13cc49..a4a973bf1 100644 --- a/src/sample.h +++ b/src/sample.h @@ -2,10 +2,9 @@ #define foosamplehfoo #include +#include -#include "memblock.h" - -enum sample_format { +enum pa_sample_format { SAMPLE_U8, SAMPLE_ALAW, SAMPLE_ULAW, @@ -16,30 +15,14 @@ enum sample_format { #define SAMPLE_S16NE SAMPLE_S16LE -struct sample_spec { - enum sample_format format; +struct pa_sample_spec { + enum pa_sample_format format; uint32_t rate; uint8_t channels; }; -#define DEFAULT_SAMPLE_SPEC default_sample_spec - -extern struct sample_spec default_sample_spec; - -struct memblock *silence_memblock(struct memblock* b, struct sample_spec *spec); -void silence_memchunk(struct memchunk *c, struct sample_spec *spec); -void silence_memory(void *p, size_t length, struct sample_spec *spec); - -struct mix_info { - struct memchunk chunk; - uint8_t volume; - void *userdata; -}; - -size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct sample_spec *spec, uint8_t volume); - -size_t bytes_per_second(struct sample_spec *spec); -size_t sample_size(struct sample_spec *spec); -uint32_t samples_usec(size_t length, struct sample_spec *spec); +size_t pa_bytes_per_second(struct pa_sample_spec *spec); +size_t pa_sample_size(struct pa_sample_spec *spec); +uint32_t pa_samples_usec(size_t length, struct pa_sample_spec *spec); #endif diff --git a/src/simple.c b/src/simple.c new file mode 100644 index 000000000..a90d22bde --- /dev/null +++ b/src/simple.c @@ -0,0 +1,120 @@ +#include "simple.h" +#include "polyp.h" +#include "mainloop.h" + +struct pa_simple { + struct mainloop *mainloop; + struct pa_context *context; + struct pa_stream *stream; + + size_t requested; + int dead; +}; + +static void playback_callback(struct pa_stream *p, size_t length, void *userdata) { + struct pa_stream *sp = userdata; + assert(p && length && sp); + + sp->requested = length; +} + +struct pa_simple* pa_simple_new( + const char *server, + const char *name, + enum pa_stream_direction dir, + const char *dev, + const char *stream_name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr) { + + struct pa_simple *p; + assert(ss); + + p = malloc(sizeof(struct pa_simple)); + assert(p); + p->context = NULL; + p->stream = NULL; + p->mainloop = pa_mainloop_new(); + assert(p->mainloop); + p->requested = 0; + p->dead = 0; + + if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name))) + goto fail; + + if (pa_context_connect(c, server, NULL, NULL) < 0) + goto fail; + + while (!pa_context_is_ready(c)) { + if (pa_context_is_dead(c)) + goto fail; + + if (mainloop_iterate(p->mainloop) < 0) + goto fail; + } + + if (!(p->stream = pa_stream_new(p->context, dir, sink, stream_name, ss, attr, NULL, NULL))) + goto fail; + + while (!pa_stream_is_ready(c)) { + if (pa_stream_is_dead(c)) + goto fail; + + if (mainloop_iterate(p->mainloop) < 0) + goto fail; + } + + pa_stream_set_write_callback(p->stream, playback_callback, p); + + return p; + +fail: + pa_simple_free(p); + return NULL; +} + +void pa_simple_free(struct pa_simple *s) { + assert(s); + + if (s->stream) + pa_stream_free(s->stream); + + if (s->context) + pa_context_free(s->context); + + if (s->mainloop) + mainloop_free(s->mainloop); + + free(s); +} + +int pa_simple_write(struct pa_simple *s, const void*data, size_t length) { + assert(s && data); + + while (length > 0) { + size_t l; + + while (!s->requested) { + if (pa_context_is_dead(c)) + return -1; + + if (mainloop_iterate(s->mainloop) < 0) + return -1; + } + + l = length; + if (l > s->requested) + l = s->requested; + + pa_stream_write(s->stream, data, l); + data += l; + length -= l; + s->requested = -l; + } + + return 0; +} + +int pa_simple_read(struct pa_simple *s, const void*data, size_t length) { + assert(0); +} diff --git a/src/simple.h b/src/simple.h new file mode 100644 index 000000000..80693056f --- /dev/null +++ b/src/simple.h @@ -0,0 +1,25 @@ +#ifndef foosimplehfoo +#define foosimplehfoo + +#include + +#include "sample.h" +#include "polypdef.h" + +struct pa_simple; + +struct pa_simple* pa_simple_new( + const char *server, + const char *name, + enum pa_stream_direction dir, + const char *dev, + const char *stream_name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr); + +void pa_simple_free(struct pa_simple *s); + +int pa_simple_write(struct pa_simple *s, const void*data, size_t length); +int pa_simple_read(struct pa_simple *s, const void*data, size_t length); + +#endif diff --git a/src/sink.c b/src/sink.c index cd12b463f..a334424c2 100644 --- a/src/sink.c +++ b/src/sink.c @@ -6,10 +6,11 @@ #include "sink.h" #include "sinkinput.h" #include "strbuf.h" +#include "sample-util.h" #define MAX_MIX_CHANNELS 32 -struct sink* sink_new(struct core *core, const char *name, const struct sample_spec *spec) { +struct sink* sink_new(struct core *core, const char *name, const struct pa_sample_spec *spec) { struct sink *s; char *n = NULL; int r; diff --git a/src/sink.h b/src/sink.h index 394abb5ba..d9f80059d 100644 --- a/src/sink.h +++ b/src/sink.h @@ -15,7 +15,7 @@ struct sink { char *name; struct core *core; - struct sample_spec sample_spec; + struct pa_sample_spec sample_spec; struct idxset *inputs; struct source *monitor_source; @@ -27,7 +27,7 @@ struct sink { void *userdata; }; -struct sink* sink_new(struct core *core, const char *name, const struct sample_spec *spec); +struct sink* sink_new(struct core *core, const char *name, const struct pa_sample_spec *spec); void sink_free(struct sink* s); int sink_render(struct sink*s, size_t length, struct memchunk *result); diff --git a/src/sinkinput.c b/src/sinkinput.c index 2e6a8c366..b81c9c713 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -5,7 +5,7 @@ #include "sinkinput.h" #include "strbuf.h" -struct sink_input* sink_input_new(struct sink *s, struct sample_spec *spec, const char *name) { +struct sink_input* sink_input_new(struct sink *s, struct pa_sample_spec *spec, const char *name) { struct sink_input *i; int r; assert(s && spec); @@ -14,7 +14,7 @@ struct sink_input* sink_input_new(struct sink *s, struct sample_spec *spec, cons assert(i); i->name = name ? strdup(name) : NULL; i->sink = s; - i->spec = *spec; + i->sample_spec = *spec; i->peek = NULL; i->drop = NULL; diff --git a/src/sinkinput.h b/src/sinkinput.h index 389d832dd..f04ecb952 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -12,7 +12,7 @@ struct sink_input { char *name; struct sink *sink; - struct sample_spec spec; + struct pa_sample_spec sample_spec; uint8_t volume; int (*peek) (struct sink_input *i, struct memchunk *chunk); @@ -23,7 +23,7 @@ struct sink_input { void *userdata; }; -struct sink_input* sink_input_new(struct sink *s, struct sample_spec *spec, const char *name); +struct sink_input* sink_input_new(struct sink *s, struct pa_sample_spec *spec, const char *name); void sink_input_free(struct sink_input* i); /* Code that didn't create the input stream should call this function to diff --git a/src/socket-client.c b/src/socket-client.c new file mode 100644 index 000000000..812c43f3e --- /dev/null +++ b/src/socket-client.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socket-client.h" +#include "util.h" + +struct socket_client { + struct pa_mainloop_api *mainloop; + int fd; + + void *io_source, *fixed_source; + void (*callback)(struct socket_client*c, struct iochannel *io, void *userdata); + void *userdata; +}; + +static struct socket_client*socket_client_new(struct pa_mainloop_api *m) { + struct socket_client *c; + assert(m); + + c = malloc(sizeof(struct socket_client)); + assert(c); + c->mainloop = m; + c->fd = -1; + c->io_source = c->fixed_source = NULL; + c->callback = NULL; + c->userdata = NULL; + return c; +} + +static void do_call(struct socket_client *c) { + struct iochannel *io; + int error, lerror; + assert(c && c->callback); + + lerror = sizeof(error); + if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &error, &lerror) < 0) { + fprintf(stderr, "getsockopt(): %s\n", strerror(errno)); + goto failed; + } + + if (lerror != sizeof(error)) { + fprintf(stderr, "getsocktop() returned invalid size.\n"); + goto failed; + } + + if (error != 0) { + fprintf(stderr, "connect(): %s\n", strerror(error)); + goto failed; + } + + io = iochannel_new(c->mainloop, c->fd, c->fd); + assert(io); + c->fd = -1; + c->callback(c, io, c->userdata); + + return; + +failed: + close(c->fd); + c->fd = -1; + c->callback(c, NULL, c->userdata); + return; +} + +static void connect_fixed_cb(struct pa_mainloop_api *m, void *id, void *userdata) { + struct socket_client *c = userdata; + assert(m && c && c->fixed_source == id); + m->cancel_fixed(m, c->fixed_source); + c->fixed_source = NULL; + do_call(c); +} + +static void connect_io_cb(struct pa_mainloop_api*m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { + struct socket_client *c = userdata; + assert(m && c && c->io_source == id && fd >= 0 && events == PA_MAINLOOP_API_IO_EVENT_OUTPUT); + m->cancel_io(m, c->io_source); + c->io_source = NULL; + do_call(c); +} + +static int do_connect(struct socket_client *c, const struct sockaddr *sa, socklen_t len) { + int r; + assert(c && sa && len); + + make_nonblock_fd(c->fd); + + if ((r = connect(c->fd, sa, len)) < 0) { + if (r != EINPROGRESS) { + fprintf(stderr, "connect(): %s\n", strerror(errno)); + return -1; + } + + c->io_source = c->mainloop->source_io(c->mainloop, c->fd, PA_MAINLOOP_API_IO_EVENT_OUTPUT, connect_io_cb, c); + assert(c->io_source); + } else { + c->fixed_source = c->mainloop->source_fixed(c->mainloop, connect_fixed_cb, c); + assert(c->io_source); + } + + return 0; +} + +struct socket_client* socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port) { + struct socket_client *c; + struct sockaddr_in sa; + + c = socket_client_new(m); + assert(c); + + if ((c->fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "socket(): %s\n", strerror(errno)); + goto fail; + } + + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + sa.sin_addr.s_addr = htonl(address); + + if (do_connect(c, (struct sockaddr*) &sa, sizeof(sa)) < 0) + goto fail; + + return c; + +fail: + socket_client_free(c); + return NULL; +} + +struct socket_client* socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) { + struct socket_client *c; + struct sockaddr_un sa; + + c = socket_client_new(m); + assert(c); + + if ((c->fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "socket(): %s\n", strerror(errno)); + goto fail; + } + + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); + sa.sun_path[sizeof(sa.sun_path) - 1] = 0; + + if (do_connect(c, (struct sockaddr*) &sa, sizeof(sa)) < 0) + goto fail; + + return c; + +fail: + socket_client_free(c); + return NULL; +} + +void socket_client_free(struct socket_client *c) { + assert(c && c->mainloop); + if (c->io_source) + c->mainloop->cancel_io(c->mainloop, c->io_source); + if (c->fixed_source) + c->mainloop->cancel_fixed(c->mainloop, c->fixed_source); + if (c->fd >= 0) + close(c->fd); + free(c); +} + +void socket_client_set_callback(struct socket_client *c, void (*on_connection)(struct socket_client *c, struct iochannel*io, void *userdata), void *userdata) { + assert(c); + c->callback = on_connection; + c->userdata = userdata; +} diff --git a/src/socket-client.h b/src/socket-client.h new file mode 100644 index 000000000..4de01e349 --- /dev/null +++ b/src/socket-client.h @@ -0,0 +1,17 @@ +#ifndef foosocketclienthfoo +#define foosocketclienthfoo + +#include +#include "mainloop-api.h" +#include "iochannel.h" + +struct socket_client; + +struct socket_client* socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); +struct socket_client* socket_client_new_unix(struct pa_mainloop_api *m, const char *filename); + +void socket_client_free(struct socket_client *c); + +void socket_client_set_callback(struct socket_client *c, void (*on_connection)(struct socket_client *c, struct iochannel*io, void *userdata), void *userdata); + +#endif diff --git a/src/socket-server.c b/src/socket-server.c index 6ad225e39..87fe14768 100644 --- a/src/socket-server.c +++ b/src/socket-server.c @@ -19,14 +19,15 @@ struct socket_server { void (*on_connection)(struct socket_server*s, struct iochannel *io, void *userdata); void *userdata; - struct mainloop_source *mainloop_source; + void *mainloop_source; + struct pa_mainloop_api *mainloop; }; -static void callback(struct mainloop_source*src, int fd, enum mainloop_io_event event, void *userdata) { +static void callback(struct pa_mainloop_api *mainloop, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { struct socket_server *s = userdata; struct iochannel *io; int nfd; - assert(src && fd >= 0 && fd == s->fd && event == MAINLOOP_IO_EVENT_IN && s); + assert(s && s->mainloop == mainloop && s->mainloop_source == id && id && fd >= 0 && fd == s->fd && events == PA_MAINLOOP_API_IO_EVENT_INPUT); if ((nfd = accept(fd, NULL, NULL)) < 0) { fprintf(stderr, "accept(): %s\n", strerror(errno)); @@ -38,12 +39,12 @@ static void callback(struct mainloop_source*src, int fd, enum mainloop_io_event return; } - io = iochannel_new(mainloop_source_get_mainloop(src), nfd, nfd); + io = iochannel_new(s->mainloop, nfd, nfd); assert(io); s->on_connection(s, io, s->userdata); } -struct socket_server* socket_server_new(struct mainloop *m, int fd) { +struct socket_server* socket_server_new(struct pa_mainloop_api *m, int fd) { struct socket_server *s; assert(m && fd >= 0); @@ -54,13 +55,14 @@ struct socket_server* socket_server_new(struct mainloop *m, int fd) { s->on_connection = NULL; s->userdata = NULL; - s->mainloop_source = mainloop_source_new_io(m, fd, MAINLOOP_IO_EVENT_IN, callback, s); + s->mainloop = m; + s->mainloop_source = m->source_io(m, fd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, s); assert(s->mainloop_source); return s; } -struct socket_server* socket_server_new_unix(struct mainloop *m, const char *filename) { +struct socket_server* socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) { int fd = -1; struct sockaddr_un sa; struct socket_server *s; @@ -101,7 +103,7 @@ fail: return NULL; } -struct socket_server* socket_server_new_ipv4(struct mainloop *m, uint32_t address, uint16_t port) { +struct socket_server* socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port) { int fd = -1; struct sockaddr_in sa; int on = 1; @@ -148,7 +150,8 @@ void socket_server_free(struct socket_server*s) { free(s->filename); } - mainloop_source_free(s->mainloop_source); + + s->mainloop->cancel_io(s->mainloop, s->mainloop_source); free(s); } diff --git a/src/socket-server.h b/src/socket-server.h index 4814fc626..80895f8db 100644 --- a/src/socket-server.h +++ b/src/socket-server.h @@ -2,14 +2,14 @@ #define foosocketserverhfoo #include -#include "mainloop.h" +#include "mainloop-api.h" #include "iochannel.h" struct socket_server; -struct socket_server* socket_server_new(struct mainloop *m, int fd); -struct socket_server* socket_server_new_unix(struct mainloop *m, const char *filename); -struct socket_server* socket_server_new_ipv4(struct mainloop *m, uint32_t address, uint16_t port); +struct socket_server* socket_server_new(struct pa_mainloop_api *m, int fd); +struct socket_server* socket_server_new_unix(struct pa_mainloop_api *m, const char *filename); +struct socket_server* socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); void socket_server_free(struct socket_server*s); diff --git a/src/source.c b/src/source.c index 44d775327..21ac24f35 100644 --- a/src/source.c +++ b/src/source.c @@ -7,7 +7,7 @@ #include "sourceoutput.h" #include "strbuf.h" -struct source* source_new(struct core *core, const char *name, const struct sample_spec *spec) { +struct source* source_new(struct core *core, const char *name, const struct pa_sample_spec *spec) { struct source *s; int r; assert(core && spec); diff --git a/src/source.h b/src/source.h index 078fb1c9a..04f3984f7 100644 --- a/src/source.h +++ b/src/source.h @@ -14,14 +14,14 @@ struct source { char *name; struct core *core; - struct sample_spec sample_spec; + struct pa_sample_spec sample_spec; struct idxset *outputs; void (*notify)(struct source*source); void *userdata; }; -struct source* source_new(struct core *core, const char *name, const struct sample_spec *spec); +struct source* source_new(struct core *core, const char *name, const struct pa_sample_spec *spec); void source_free(struct source *s); /* Pass a new memory block to all output streams */ diff --git a/src/sourceoutput.c b/src/sourceoutput.c index 8021b522b..e2e1dacc3 100644 --- a/src/sourceoutput.c +++ b/src/sourceoutput.c @@ -5,7 +5,7 @@ #include "sourceoutput.h" #include "strbuf.h" -struct source_output* source_output_new(struct source *s, struct sample_spec *spec, const char *name) { +struct source_output* source_output_new(struct source *s, struct pa_sample_spec *spec, const char *name) { struct source_output *o; int r; assert(s && spec); @@ -14,7 +14,7 @@ struct source_output* source_output_new(struct source *s, struct sample_spec *sp assert(o); o->name = name ? strdup(name) : NULL; o->source = s; - o->spec = *spec; + o->sample_spec = *spec; o->push = NULL; o->kill = NULL; diff --git a/src/sourceoutput.h b/src/sourceoutput.h index 359ff1511..50cb9caf5 100644 --- a/src/sourceoutput.h +++ b/src/sourceoutput.h @@ -12,7 +12,7 @@ struct source_output { char *name; struct source *source; - struct sample_spec spec; + struct pa_sample_spec sample_spec; void (*push)(struct source_output *o, struct memchunk *chunk); void (*kill)(struct source_output* o); @@ -20,7 +20,7 @@ struct source_output { void *userdata; }; -struct source_output* source_output_new(struct source *s, struct sample_spec *spec, const char *name); +struct source_output* source_output_new(struct source *s, struct pa_sample_spec *spec, const char *name); void source_output_free(struct source_output* o); void source_output_kill(struct source_output*o); diff --git a/src/tagstruct.c b/src/tagstruct.c index 429dd4088..47e17839b 100644 --- a/src/tagstruct.c +++ b/src/tagstruct.c @@ -90,7 +90,7 @@ void tagstruct_putu8(struct tagstruct*t, uint8_t c) { t->length += 2; } -void tagstruct_put_sample_spec(struct tagstruct *t, struct sample_spec *ss) { +void tagstruct_put_sample_spec(struct tagstruct *t, const struct pa_sample_spec *ss) { assert(t && ss); extend(t, 7); t->data[t->length] = TAG_SAMPLE_SPEC; @@ -156,7 +156,7 @@ int tagstruct_getu8(struct tagstruct*t, uint8_t *c) { return 0; } -int tagstruct_get_sample_spec(struct tagstruct *t, struct sample_spec *ss) { +int tagstruct_get_sample_spec(struct tagstruct *t, struct pa_sample_spec *ss) { assert(t && ss); if (t->rindex+7 > t->length) diff --git a/src/tagstruct.h b/src/tagstruct.h index 5572c64c6..9f6a0bf4a 100644 --- a/src/tagstruct.h +++ b/src/tagstruct.h @@ -15,12 +15,12 @@ uint8_t* tagstruct_free_data(struct tagstruct*t, size_t *l); void tagstruct_puts(struct tagstruct*t, const char *s); void tagstruct_putu32(struct tagstruct*t, uint32_t i); void tagstruct_putu8(struct tagstruct*t, uint8_t c); -void tagstruct_put_sample_spec(struct tagstruct *t, struct sample_spec *ss); +void tagstruct_put_sample_spec(struct tagstruct *t, const struct pa_sample_spec *ss); int tagstruct_gets(struct tagstruct*t, const char **s); int tagstruct_getu32(struct tagstruct*t, uint32_t *i); int tagstruct_getu8(struct tagstruct*t, uint8_t *c); -int tagstruct_get_sample_spec(struct tagstruct *t, struct sample_spec *ss); +int tagstruct_get_sample_spec(struct tagstruct *t, struct pa_sample_spec *ss); int tagstruct_eof(struct tagstruct*t); const uint8_t* tagstruct_data(struct tagstruct*t, size_t *l); diff --git a/src/todo b/src/todo index aeb7ae5fc..47344ab42 100644 --- a/src/todo +++ b/src/todo @@ -1,8 +1,10 @@ +- sync() function in native library +- name registrar - native protocol/library - simple control protocol: kill client/input/output; set_volume - resampling - esound protocol -- config parser +- config parser/cmdline - record testing -- 0.1 - optimierung von rebuild_pollfds() diff --git a/src/util.c b/src/util.c new file mode 100644 index 000000000..0383a0ad7 --- /dev/null +++ b/src/util.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include + +#include "util.h" + +void make_nonblock_fd(int fd) { + int v; + + if ((v = fcntl(fd, F_GETFL)) >= 0) + if (!(v & O_NONBLOCK)) + fcntl(fd, F_SETFL, v|O_NONBLOCK); +} + +void peer_to_string(char *c, size_t l, int fd) { + struct stat st; + + assert(c && l && fd >= 0); + + if (fstat(fd, &st) < 0) { + snprintf(c, l, "Invalid client fd"); + return; + } + + if (S_ISSOCK(st.st_mode)) { + union { + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_un un; + } sa; + socklen_t sa_len = sizeof(sa); + + if (getpeername(fd, &sa.sa, &sa_len) >= 0) { + + if (sa.sa.sa_family == AF_INET) { + uint32_t ip = ntohl(sa.in.sin_addr.s_addr); + + snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u", + ip >> 24, + (ip >> 16) & 0xFF, + (ip >> 8) & 0xFF, + ip & 0xFF, + ntohs(sa.in.sin_port)); + return; + } else if (sa.sa.sa_family == AF_LOCAL) { + snprintf(c, l, "UNIX client for %s", sa.un.sun_path); + return; + } + + } + snprintf(c, l, "Unknown network client"); + return; + } else if (S_ISCHR(st.st_mode) && (fd == 0 || fd == 1)) { + snprintf(c, l, "STDIN/STDOUT client"); + return; + } + + snprintf(c, l, "Unknown client"); +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 000000000..830ee2e0c --- /dev/null +++ b/src/util.h @@ -0,0 +1,8 @@ +#ifndef fooutilhfoo +#define fooutilhfoo + +void make_nonblock_fd(int fd); + +void peer_to_string(char *c, size_t l, int fd); + +#endif From 3b50a7c1294eedcab0907da453570bb696862d2b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 Jun 2004 23:18:14 +0000 Subject: [PATCH 0031/1514] ignore some more stuff git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@32 fefdeb5f-60dc-0310-8127-8f9354f1896f From b9e0fa84f3a327ffc395ac184686a78a95c2bb3b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 Jun 2004 23:38:33 +0000 Subject: [PATCH 0032/1514] minor compile work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@33 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp.c | 3 ++- src/socket-client.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/polyp.c b/src/polyp.c index fdff7f9c3..a373841a3 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -15,6 +15,7 @@ #define DEFAULT_MAX_LENGTH 20480 #define DEFAULT_PREBUF 4096 #define DEFAULT_TIMEOUT 5 +#define DEFAULT_SERVER "/tmp/foo" struct pa_context { char *name; @@ -212,7 +213,7 @@ int pa_context_connect(struct pa_context *c, const char *server, void (*complete assert(c && c->state == CONTEXT_UNCONNECTED); assert(!c->client); - if (!(c->client = socket_client_new_unix(c->mainloop, server))) { + if (!(c->client = socket_client_new_unix(c->mainloop, server ? server : DEFAULT_SERVER))) { c->errno = PA_ERROR_CONNECTIONREFUSED; return -1; } diff --git a/src/socket-client.c b/src/socket-client.c index 812c43f3e..42859392c 100644 --- a/src/socket-client.c +++ b/src/socket-client.c @@ -110,6 +110,7 @@ static int do_connect(struct socket_client *c, const struct sockaddr *sa, sockle struct socket_client* socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port) { struct socket_client *c; struct sockaddr_in sa; + assert(m && address && port); c = socket_client_new(m); assert(c); @@ -136,6 +137,7 @@ fail: struct socket_client* socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) { struct socket_client *c; struct sockaddr_un sa; + assert(m && filename); c = socket_client_new(m); assert(c); From c050d7254c13c22baafb71c127e56eb1d5f6ffdb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 Jun 2004 23:40:39 +0000 Subject: [PATCH 0033/1514] rename oss.[ch] to oss-util.[ch] git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@34 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/{oss.c => oss-util.c} | 0 src/{oss.h => oss-util.h} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/{oss.c => oss-util.c} (100%) rename src/{oss.h => oss-util.h} (100%) diff --git a/src/oss.c b/src/oss-util.c similarity index 100% rename from src/oss.c rename to src/oss-util.c diff --git a/src/oss.h b/src/oss-util.h similarity index 100% rename from src/oss.h rename to src/oss-util.h From a1b59db7127f328820336837c8f9f215e923dc8d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 Jun 2004 23:43:42 +0000 Subject: [PATCH 0034/1514] make rename of oss.[ch] to oss-util.[ch] complete git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@35 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 12 ++++++------ src/module-oss-mmap.c | 2 +- src/module-oss.c | 2 +- src/oss-util.c | 2 +- src/oss-util.h | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 6ad1488f4..c3a33ce3d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,12 +23,12 @@ bin_PROGRAMS = polypaudio pacat pkglib_LTLIBRARIES=libiochannel.la libsocket-server.la libsocket-client.la \ libprotocol-simple.la module-simple-protocol-tcp.la \ module-pipe-sink.la libpstream.la \ - libpacket.la module-oss.la module-oss-mmap.la liboss.la libioline.la \ + libpacket.la module-oss.la module-oss-mmap.la liboss-util.la libioline.la \ libcli.la module-cli.la libtokenizer.la libdynarray.la \ module-simple-protocol-unix.la module-cli-protocol-tcp.la \ libprotocol-cli.la module-cli-protocol-unix.la libtagstruct.la \ libpdispatch.la libprotocol-native.la libpstream-util.la \ - module-native-protocol-tcp.la module-native-protocol-unix.la \ + module-native-protocol-tcp.la module-native-protocol-unix.la \ libpolyp.la polypaudio_SOURCES = idxset.c idxset.h \ @@ -86,8 +86,8 @@ libiochannel_la_LDFLAGS = -avoid-version libpacket_la_SOURCES = packet.c packet.h libpacket_la_LDFLAGS = -avoid-version -liboss_la_SOURCES = oss.c oss.h -liboss_la_LDFLAGS = -avoid-version +liboss_util_la_SOURCES = oss-util.c oss-util.h +liboss_util_la_LDFLAGS = -avoid-version libioline_la_SOURCES = ioline.c ioline.h libioline_la_LDFLAGS = -avoid-version @@ -151,11 +151,11 @@ module_pipe_sink_la_LIBADD = libiochannel.la module_oss_la_SOURCES = module-oss.c module_oss_la_LDFLAGS = -module -avoid-version -module_oss_la_LIBADD = libiochannel.la liboss.la +module_oss_la_LIBADD = libiochannel.la liboss-util.la module_oss_mmap_la_SOURCES = module-oss-mmap.c module_oss_mmap_la_LDFLAGS = -module -avoid-version -module_oss_mmap_la_LIBADD = libiochannel.la liboss.la +module_oss_mmap_la_LIBADD = libiochannel.la liboss-util.la module_cli_la_SOURCES = module-cli.c module_cli_la_LDFLAGS = -module -avoid-version diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index b70ea6bda..f08dd7d3c 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -15,7 +15,7 @@ #include "sink.h" #include "source.h" #include "module.h" -#include "oss.h" +#include "oss-util.h" #include "sample-util.h" struct userdata { diff --git a/src/module-oss.c b/src/module-oss.c index 4f3075453..b5d1427a4 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -14,7 +14,7 @@ #include "sink.h" #include "source.h" #include "module.h" -#include "oss.h" +#include "oss-util.h" #include "sample-util.h" struct userdata { diff --git a/src/oss-util.c b/src/oss-util.c index 02bf8cd1c..bf6b62e29 100644 --- a/src/oss-util.c +++ b/src/oss-util.c @@ -5,7 +5,7 @@ #include #include -#include "oss.h" +#include "oss-util.h" int oss_auto_format(int fd, struct pa_sample_spec *ss) { int format, channels, speed; diff --git a/src/oss-util.h b/src/oss-util.h index 34ac9c669..5fc08b0ba 100644 --- a/src/oss-util.h +++ b/src/oss-util.h @@ -1,5 +1,5 @@ -#ifndef fooosshfoo -#define fooosshfoo +#ifndef fooossutilhfoo +#define fooossutilhfoo #include "sample.h" From 1ad4ff1ca446fafb3abe9353a4048893dd3d9b77 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 24 Jun 2004 23:27:06 +0000 Subject: [PATCH 0035/1514] some fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@36 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 ++-- src/main.c | 7 ++++++- src/module-protocol-stub.c | 5 ++++- src/pdispatch.c | 1 + src/polyp.c | 2 +- src/socket-client.c | 2 +- src/tagstruct.c | 8 ++++---- 7 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index c3a33ce3d..75da02c17 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,7 +28,7 @@ pkglib_LTLIBRARIES=libiochannel.la libsocket-server.la libsocket-client.la \ module-simple-protocol-unix.la module-cli-protocol-tcp.la \ libprotocol-cli.la module-cli-protocol-unix.la libtagstruct.la \ libpdispatch.la libprotocol-native.la libpstream-util.la \ - module-native-protocol-tcp.la module-native-protocol-unix.la \ + module-native-protocol-tcp.la module-native-protocol-unix.la \ libpolyp.la polypaudio_SOURCES = idxset.c idxset.h \ @@ -110,7 +110,7 @@ libprotocol_cli_la_LIBADD = libsocket-server.la libiochannel.la libcli.la libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = libsocket-server.la libiochannel.la libpacket.la libpstream.la libpstream-util.la +libprotocol_native_la_LIBADD = libsocket-server.la libiochannel.la libpacket.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct_la_SOURCES = tagstruct.c tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version diff --git a/src/main.c b/src/main.c index ef25b5e30..0fe333e0e 100644 --- a/src/main.c +++ b/src/main.c @@ -39,8 +39,13 @@ int main(int argc, char *argv[]) { assert(c); module_load(c, "module-oss-mmap", "/dev/dsp1"); - module_load(c, "module-pipe-sink", NULL); +/* module_load(c, "module-pipe-sink", NULL); module_load(c, "module-simple-protocol-tcp", NULL); + module_load(c, "module-simple-protocol-unix", NULL);*/ + module_load(c, "module-cli-protocol-tcp", NULL); +/* module_load(c, "module-cli-protocol-unix", NULL); + module_load(c, "module-native-protocol-tcp", NULL);*/ + module_load(c, "module-native-protocol-unix", NULL); module_load(c, "module-cli", NULL); fprintf(stderr, "main: mainloop entry.\n"); diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 2387017c9..97bf5ef3c 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -8,18 +8,21 @@ #include "protocol-simple.h" #define protocol_free protocol_simple_free #define IPV4_PORT 4711 + #define UNIX_SOCKET "/tmp/polypaudio_simple" #else #ifdef USE_PROTOCOL_CLI #include "protocol-cli.h" #define protocol_new protocol_cli_new #define protocol_free protocol_cli_free #define IPV4_PORT 4712 + #define UNIX_SOCKET "/tmp/polypaudio_cli" #else #ifdef USE_PROTOCOL_NATIVE #include "protocol-native.h" #define protocol_new protocol_native_new #define protocol_free protocol_native_free #define IPV4_PORT 4713 + #define UNIX_SOCKET "/tmp/polypaudio_native" #else #error "Broken build system" #endif @@ -34,7 +37,7 @@ int module_init(struct core *c, struct module*m) { if (!(s = socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, IPV4_PORT))) return -1; #else - if (!(s = socket_server_new_unix(c->mainloop, "/tmp/polypsimple"))) + if (!(s = socket_server_new_unix(c->mainloop, UNIX_SOCKET))) return -1; #endif diff --git a/src/pdispatch.c b/src/pdispatch.c index 48b6639d2..15f4b1b50 100644 --- a/src/pdispatch.c +++ b/src/pdispatch.c @@ -46,6 +46,7 @@ struct pdispatch* pdispatch_new(struct pa_mainloop_api *mainloop, const struct p pd->mainloop = mainloop; pd->command_table = table; pd->n_commands = entries; + pd->replies = NULL; return pd; } diff --git a/src/polyp.c b/src/polyp.c index a373841a3..69b85c210 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -15,7 +15,7 @@ #define DEFAULT_MAX_LENGTH 20480 #define DEFAULT_PREBUF 4096 #define DEFAULT_TIMEOUT 5 -#define DEFAULT_SERVER "/tmp/foo" +#define DEFAULT_SERVER "/tmp/polypaudio_native" struct pa_context { char *name; diff --git a/src/socket-client.c b/src/socket-client.c index 42859392c..b10f8ab1a 100644 --- a/src/socket-client.c +++ b/src/socket-client.c @@ -101,7 +101,7 @@ static int do_connect(struct socket_client *c, const struct sockaddr *sa, sockle assert(c->io_source); } else { c->fixed_source = c->mainloop->source_fixed(c->mainloop, connect_fixed_cb, c); - assert(c->io_source); + assert(c->fixed_source); } return 0; diff --git a/src/tagstruct.c b/src/tagstruct.c index 47e17839b..407440d35 100644 --- a/src/tagstruct.c +++ b/src/tagstruct.c @@ -34,7 +34,7 @@ struct tagstruct *tagstruct_new(const uint8_t* data, size_t length) { t->data = (uint8_t*) data; t->allocated = t->length = data ? length : 0; t->rindex = 0; - t->dynamic = !!data; + t->dynamic = !data; return t; } @@ -57,7 +57,7 @@ uint8_t* tagstruct_free_data(struct tagstruct*t, size_t *l) { static void extend(struct tagstruct*t, size_t l) { assert(t && t->dynamic); - if (t->allocated <= l) + if (l <= t->allocated) return; t->data = realloc(t->data, t->allocated = l+100); @@ -75,7 +75,7 @@ void tagstruct_puts(struct tagstruct*t, const char *s) { } void tagstruct_putu32(struct tagstruct*t, uint32_t i) { - assert(t && i); + assert(t); extend(t, 5); t->data[t->length] = TAG_U32; *((uint32_t*) (t->data+t->length+1)) = htonl(i); @@ -83,7 +83,7 @@ void tagstruct_putu32(struct tagstruct*t, uint32_t i) { } void tagstruct_putu8(struct tagstruct*t, uint8_t c) { - assert(t && c); + assert(t); extend(t, 2); t->data[t->length] = TAG_U8; *(t->data+t->length+1) = c; From 57dc42709fa258844db05f2042dfffe6ca8ade8b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 27 Jun 2004 17:50:02 +0000 Subject: [PATCH 0036/1514] many fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@37 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/mainloop.c | 12 ++++++++---- src/pacat.c | 32 ++++++++++++++++++++------------ src/pdispatch.c | 5 +++-- src/polyp.c | 16 ++++++++++++---- src/protocol-native.c | 24 +++++++++++++++++++++--- src/pstream.c | 10 +++++----- src/tagstruct.c | 4 ++-- 7 files changed, 71 insertions(+), 32 deletions(-) diff --git a/src/mainloop.c b/src/mainloop.c index a1758c658..8629add2d 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -162,11 +162,14 @@ static void dispatch_pollfds(struct pa_mainloop *m) { struct mainloop_source_io *s; for (s = idxset_first(m->io_sources, &index); s; s = idxset_next(m->io_sources, &index)) { - if (s->header.dead || !s->events || !s->pollfd || !s->pollfd->revents) + if (s->header.dead || !s->pollfd || !s->pollfd->revents) continue; - assert(s->pollfd->revents <= s->pollfd->events && s->pollfd->fd == s->fd && s->callback); - s->callback(&m->api, s, s->fd, ((s->pollfd->revents & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | ((s->pollfd->revents & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), s->userdata); + assert(s->pollfd->fd == s->fd && s->callback); + s->callback(&m->api, s, s->fd, + ((s->pollfd->revents & (POLLIN|POLLHUP|POLLERR)) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | + ((s->pollfd->revents & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), s->userdata); + s->pollfd->revents = 0; } } @@ -212,7 +215,7 @@ static int calc_next_timeout(struct pa_mainloop *m) { if (tmp == 0) return 0; - else if (tmp < t) + else if (t == -1 || tmp < t) t = tmp; } @@ -357,6 +360,7 @@ static void mainloop_cancel_io(struct pa_mainloop_api*a, void* id) { s->header.dead = 1; m->io_sources_scan_dead = 1; + m->rebuild_pollfds = 1; } /* Fixed sources */ diff --git a/src/pacat.c b/src/pacat.c index 5f5a373bb..5ee1b866c 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -29,22 +29,15 @@ static void stream_die_callback(struct pa_stream *s, void *userdata) { mainloop_api->quit(mainloop_api, 1); } -static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { +static void do_write(size_t length) { size_t l; - assert(s && length); - - mainloop_api->enable_io(mainloop_api, stdin_source, PA_STREAM_PLAYBACK); - - if (!buffer) - return; - - assert(buffer_length); + assert(buffer && buffer_length); l = length; if (l > buffer_length) l = buffer_length; - pa_stream_write(s, buffer+buffer_index, l); + pa_stream_write(stream, buffer+buffer_index, l); buffer_length -= l; buffer_index += l; @@ -55,12 +48,24 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user } } +static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { + assert(s && length); + + mainloop_api->enable_io(mainloop_api, stdin_source, PA_MAINLOOP_API_IO_EVENT_INPUT); + + if (!buffer) + return; + + do_write(length); +} + static void stream_complete_callback(struct pa_context*c, struct pa_stream *s, void *userdata) { assert(c); if (!s) { fprintf(stderr, "Stream creation failed.\n"); mainloop_api->quit(mainloop_api, 1); + return; } stream = s; @@ -94,7 +99,7 @@ fail: } static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { - size_t l; + size_t l, w = 0; ssize_t r; assert(a == mainloop_api && id && fd == STDIN_FILENO && events == PA_MAINLOOP_API_IO_EVENT_INPUT); @@ -103,7 +108,7 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m return; } - if (!(l = pa_stream_writable_size(stream))) + if (!stream || !(l = w = pa_stream_writable_size(stream))) l = 4096; buffer = malloc(l); assert(buffer); @@ -120,6 +125,9 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m buffer_length = r; buffer_index = 0; + + if (w) + do_write(w); } int main(int argc, char *argv[]) { diff --git a/src/pdispatch.c b/src/pdispatch.c index 15f4b1b50..65dcd747c 100644 --- a/src/pdispatch.c +++ b/src/pdispatch.c @@ -22,7 +22,9 @@ struct pdispatch { static void reply_info_free(struct reply_info *r) { assert(r && r->pdispatch && r->pdispatch->mainloop); - r->pdispatch->mainloop->cancel_time(r->pdispatch->mainloop, r->mainloop_timeout); + + if (r->pdispatch) + r->pdispatch->mainloop->cancel_time(r->pdispatch->mainloop, r->mainloop_timeout); if (r->previous) r->previous->next = r->next; @@ -112,7 +114,6 @@ fail: if (ts) tagstruct_free(ts); - fprintf(stderr, "protocol-native: invalid packet.\n"); return -1; } diff --git a/src/polyp.c b/src/polyp.c index 69b85c210..c298d46d2 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -14,7 +14,7 @@ #define DEFAULT_QUEUE_LENGTH 10240 #define DEFAULT_MAX_LENGTH 20480 #define DEFAULT_PREBUF 4096 -#define DEFAULT_TIMEOUT 5 +#define DEFAULT_TIMEOUT (5*60) #define DEFAULT_SERVER "/tmp/polypaudio_native" struct pa_context { @@ -39,6 +39,7 @@ struct pa_context { struct pa_stream { struct pa_context *context; struct pa_stream *next, *previous; + uint32_t device_index; uint32_t channel; int channel_valid; enum pa_stream_direction direction; @@ -252,11 +253,11 @@ static int command_request(struct pdispatch *pd, uint32_t command, uint32_t tag, struct pa_stream *s; struct pa_context *c = userdata; uint32_t bytes, channel; - assert(pd && command == PA_COMMAND_REQUEST && t && s); + assert(pd && command == PA_COMMAND_REQUEST && t && c); if (tagstruct_getu32(t, &channel) < 0 || tagstruct_getu32(t, &bytes) < 0 || - tagstruct_eof(t)) { + !tagstruct_eof(t)) { c->errno = PA_ERROR_PROTOCOL; return -1; } @@ -266,6 +267,8 @@ static int command_request(struct pdispatch *pd, uint32_t command, uint32_t tag, return -1; } + fprintf(stderr, "Requested %u bytes\n", bytes); + s->requested_bytes += bytes; if (s->requested_bytes && s->write_callback) @@ -295,7 +298,8 @@ static int create_playback_callback(struct pdispatch *pd, uint32_t command, uint } if (tagstruct_getu32(t, &s->channel) < 0 || - tagstruct_eof(t)) { + tagstruct_getu32(t, &s->device_index) < 0 || + !tagstruct_eof(t)) { s->context->errno = PA_ERROR_PROTOCOL; ret = -1; goto fail; @@ -349,6 +353,7 @@ int pa_stream_new( s->requested_bytes = 0; s->channel = 0; s->channel_valid = 0; + s->device_index = (uint32_t) -1; s->direction = dir; t = tagstruct_new(NULL, 0); @@ -419,7 +424,10 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { chunk.length = length; pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + memblock_unref(chunk.memblock); + fprintf(stderr, "Sent %u bytes\n", length); + if (length < s->requested_bytes) s->requested_bytes -= length; else diff --git a/src/protocol-native.c b/src/protocol-native.c index a39880b89..b8a461ae6 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -29,6 +29,7 @@ struct playback_stream { size_t qlength; struct sink_input *sink_input; struct memblockq *memblockq; + size_t requested_bytes; }; struct connection { @@ -81,7 +82,7 @@ static void record_stream_free(struct record_stream* r) { static struct playback_stream* playback_stream_new(struct connection *c, struct sink *sink, struct pa_sample_spec *ss, const char *name, size_t qlen, size_t maxlength, size_t prebuf) { struct playback_stream *s; - assert(c && sink && s && name && qlen && maxlength && prebuf); + assert(c && sink && ss && name && qlen && maxlength && prebuf); s = malloc(sizeof(struct playback_stream)); assert (s); @@ -99,8 +100,9 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct s->memblockq = memblockq_new(maxlength, pa_sample_size(ss), prebuf); assert(s->memblockq); + s->requested_bytes = 0; + idxset_put(c->playback_streams, s, &s->index); - request_bytes(s); return s; } @@ -141,12 +143,21 @@ static void request_bytes(struct playback_stream *s) { if (!(l = memblockq_missing_to(s->memblockq, s->qlength))) return; + if (l <= s->requested_bytes) + return; + + l -= s->requested_bytes; + s->requested_bytes += l; + t = tagstruct_new(NULL, 0); assert(t); tagstruct_putu32(t, PA_COMMAND_REQUEST); + tagstruct_putu32(t, (uint32_t) -1); /* tag */ tagstruct_putu32(t, s->index); tagstruct_putu32(t, l); pstream_send_tagstruct(s->connection->pstream, t); + + fprintf(stderr, "Requesting %u bytes\n", l); } /*** sinkinput callbacks ***/ @@ -237,6 +248,7 @@ static int command_create_playback_stream(struct pdispatch *pd, uint32_t command assert(s->sink_input); tagstruct_putu32(reply, s->sink_input->index); pstream_send_tagstruct(c->pstream, reply); + request_bytes(s); return 0; } @@ -284,7 +296,6 @@ static int command_exit(struct pdispatch *pd, uint32_t command, uint32_t tag, st /*** pstream callbacks ***/ - static int packet_callback(struct pstream *p, struct packet *packet, void *userdata) { struct connection *c = userdata; assert(p && packet && packet->data && c); @@ -307,10 +318,17 @@ static int memblock_callback(struct pstream *p, uint32_t channel, int32_t delta, return -1; } + if (chunk->length >= stream->requested_bytes) + stream->requested_bytes = 0; + else + stream->requested_bytes -= chunk->length; + memblockq_push(stream->memblockq, chunk, delta); assert(stream->sink_input); sink_notify(stream->sink_input->sink); + fprintf(stderr, "Recieved %u bytes.\n", chunk->length); + return 0; } diff --git a/src/pstream.c b/src/pstream.c index 4a3a648b1..e3f598161 100644 --- a/src/pstream.c +++ b/src/pstream.c @@ -131,11 +131,11 @@ static void item_free(void *item, void *p) { struct item_info *i = item; assert(i); - if (i->type == PSTREAM_ITEM_PACKET) { + if (i->type == PSTREAM_ITEM_MEMBLOCK) { assert(i->chunk.memblock); memblock_unref(i->chunk.memblock); } else { - assert(i->type == PSTREAM_ITEM_MEMBLOCK); + assert(i->type == PSTREAM_ITEM_PACKET); assert(i->packet); packet_unref(i->packet); } @@ -184,7 +184,7 @@ void pstream_send_packet(struct pstream*p, struct packet *packet) { void pstream_send_memblock(struct pstream*p, uint32_t channel, int32_t delta, struct memchunk *chunk) { struct item_info *i; - assert(p && channel && chunk); + assert(p && channel != (uint32_t) -1 && chunk); i = malloc(sizeof(struct item_info)); assert(i); @@ -258,7 +258,7 @@ static void do_write(struct pstream *p) { l = PSTREAM_DESCRIPTOR_SIZE - p->write.index; } else { d = (void*) p->write.data + p->write.index - PSTREAM_DESCRIPTOR_SIZE; - l = ntohl(p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) - p->write.index - PSTREAM_DESCRIPTOR_SIZE; + l = ntohl(p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PSTREAM_DESCRIPTOR_SIZE); } if ((r = iochannel_write(p->io, d, l)) < 0) @@ -298,7 +298,7 @@ static void do_read(struct pstream *p) { } else { assert(p->read.data); d = (void*) p->read.data + p->read.index - PSTREAM_DESCRIPTOR_SIZE; - l = ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) - p->read.index - PSTREAM_DESCRIPTOR_SIZE; + l = ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PSTREAM_DESCRIPTOR_SIZE); } if ((r = iochannel_read(p->io, d, l)) <= 0) diff --git a/src/tagstruct.c b/src/tagstruct.c index 407440d35..e6d6b2b25 100644 --- a/src/tagstruct.c +++ b/src/tagstruct.c @@ -113,7 +113,7 @@ int tagstruct_gets(struct tagstruct*t, const char **s) { return -1; error = 1; - for (n = 0, c = (char*) (t->data+t->rindex+1); n < t->length-t->rindex-1; c++) + for (n = 0, c = (char*) (t->data+t->rindex+1); t->rindex+1+n < t->length; n++, c++) if (!*c) { error = 0; break; @@ -124,7 +124,7 @@ int tagstruct_gets(struct tagstruct*t, const char **s) { *s = (char*) (t->data+t->rindex+1); - t->rindex += n+1; + t->rindex += n+2; return 0; } From 010378643e89e2ca4ea3502cb7dc6d8e16480832 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 27 Jun 2004 20:00:26 +0000 Subject: [PATCH 0037/1514] make native playback work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@38 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/iochannel.c | 2 +- src/ioline.c | 29 +++++++++++++++++------------ src/polyp.c | 4 ++-- src/protocol-native.c | 4 ++-- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/iochannel.c b/src/iochannel.c index 910b7e0b3..fa55875f2 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -116,7 +116,7 @@ void iochannel_free(struct iochannel*io) { if (io->input_source) io->mainloop->cancel_io(io->mainloop, io->input_source); - if (io->output_source && io->output_source != io->input_source) + if (io->output_source && (io->output_source != io->input_source)) io->mainloop->cancel_io(io->mainloop, io->output_source); free(io); diff --git a/src/ioline.c b/src/ioline.c index c37737a6d..ada9cee07 100644 --- a/src/ioline.c +++ b/src/ioline.c @@ -98,7 +98,7 @@ void ioline_set_callback(struct ioline*l, void (*callback)(struct ioline*io, con static int do_read(struct ioline *l) { ssize_t r; size_t m, len; - char *p, *e; + char *e; assert(l); if (!iochannel_is_readable(l->io)) @@ -135,21 +135,26 @@ static int do_read(struct ioline *l) { e = memchr(l->rbuf+l->rbuf_index+l->rbuf_valid_length, '\n', r); l->rbuf_valid_length += r; - if (!e && l->rbuf_valid_length >= BUFFER_LIMIT) + if (!e &&l->rbuf_valid_length >= BUFFER_LIMIT) e = l->rbuf+BUFFER_LIMIT-1; + + if (e) { + char *p; - *e = 0; - p = l->rbuf+l->rbuf_index; - m = strlen(p); + *e = 0; + + p = l->rbuf+l->rbuf_index; + m = strlen(p); - if (l->callback) - l->callback(l, p, l->userdata); + if (l->callback) + l->callback(l, p, l->userdata); - l->rbuf_index += m+1; - l->rbuf_valid_length -= m+1; + l->rbuf_index += m+1; + l->rbuf_valid_length -= m+1; - if (l->rbuf_valid_length == 0) - l->rbuf_index = 0; + if (l->rbuf_valid_length == 0) + l->rbuf_index = 0; + } return 0; } @@ -184,7 +189,7 @@ static void io_callback(struct iochannel*io, void *userdata) { return; fail: + l->dead = 1; if (l->callback) l->callback(l, NULL, l->userdata); - l->dead = 1; } diff --git a/src/polyp.c b/src/polyp.c index c298d46d2..c2d1d8229 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -267,7 +267,7 @@ static int command_request(struct pdispatch *pd, uint32_t command, uint32_t tag, return -1; } - fprintf(stderr, "Requested %u bytes\n", bytes); + /*fprintf(stderr, "Requested %u bytes\n", bytes);*/ s->requested_bytes += bytes; @@ -426,7 +426,7 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); memblock_unref(chunk.memblock); - fprintf(stderr, "Sent %u bytes\n", length); + /*fprintf(stderr, "Sent %u bytes\n", length);*/ if (length < s->requested_bytes) s->requested_bytes -= length; diff --git a/src/protocol-native.c b/src/protocol-native.c index b8a461ae6..27b547a60 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -157,7 +157,7 @@ static void request_bytes(struct playback_stream *s) { tagstruct_putu32(t, l); pstream_send_tagstruct(s->connection->pstream, t); - fprintf(stderr, "Requesting %u bytes\n", l); +/* fprintf(stderr, "Requesting %u bytes\n", l);*/ } /*** sinkinput callbacks ***/ @@ -327,7 +327,7 @@ static int memblock_callback(struct pstream *p, uint32_t channel, int32_t delta, assert(stream->sink_input); sink_notify(stream->sink_input->sink); - fprintf(stderr, "Recieved %u bytes.\n", chunk->length); + /*fprintf(stderr, "Recieved %u bytes.\n", chunk->length);*/ return 0; } From a74cd2a1bd92eac6a4140d0794ac4b557be6c133 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 27 Jun 2004 22:42:17 +0000 Subject: [PATCH 0038/1514] add name registrar git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@39 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 5 +- src/core.c | 4 ++ src/core.h | 3 + src/hashset.c | 145 +++++++++++++++++++++++++++++++++++++++++ src/hashset.h | 16 +++++ src/idxset.c | 28 ++++++-- src/idxset.h | 8 ++- src/module-oss-mmap.c | 4 +- src/module-oss.c | 4 +- src/module-pipe-sink.c | 2 +- src/namereg.c | 97 +++++++++++++++++++++++++++ src/namereg.h | 17 +++++ src/sink.c | 15 ++++- src/sink.h | 2 +- src/source.c | 12 +++- src/source.h | 2 +- src/todo | 16 +++-- 17 files changed, 354 insertions(+), 26 deletions(-) create mode 100644 src/hashset.c create mode 100644 src/hashset.h create mode 100644 src/namereg.c create mode 100644 src/namereg.h diff --git a/src/Makefile.am b/src/Makefile.am index 75da02c17..a67f395e8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,7 +49,10 @@ polypaudio_SOURCES = idxset.c idxset.h \ module.c module.h \ mainloop-signal.c mainloop-signal.h \ mainloop-api.c mainloop-api.h \ - util.c util.h + util.c util.h \ + hashset.c hashset.h \ + namereg.c namereg.h + polypaudio_CFLAGS = $(AM_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) diff --git a/src/core.c b/src/core.c index d9df38e1e..ec38da910 100644 --- a/src/core.c +++ b/src/core.c @@ -6,6 +6,7 @@ #include "module.h" #include "sink.h" #include "source.h" +#include "namereg.h" struct core* core_new(struct pa_mainloop_api *m) { struct core* c; @@ -22,6 +23,7 @@ struct core* core_new(struct pa_mainloop_api *m) { c->default_source_index = c->default_sink_index = IDXSET_INVALID; c->modules = NULL; + c->namereg = NULL; return c; }; @@ -47,6 +49,8 @@ void core_free(struct core *c) { assert(idxset_isempty(c->sink_inputs)); idxset_free(c->sink_inputs, NULL, NULL); + namereg_free(c); + free(c); }; diff --git a/src/core.h b/src/core.h index 8c4c6233d..289bec85d 100644 --- a/src/core.h +++ b/src/core.h @@ -2,6 +2,7 @@ #define foocorehfoo #include "idxset.h" +#include "hashset.h" #include "mainloop-api.h" struct core { @@ -9,6 +10,8 @@ struct core { struct idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules; + struct hashset *namereg; + uint32_t default_source_index, default_sink_index; }; diff --git a/src/hashset.c b/src/hashset.c new file mode 100644 index 000000000..298650d5d --- /dev/null +++ b/src/hashset.c @@ -0,0 +1,145 @@ +#include +#include +#include + +#include "hashset.h" +#include "idxset.h" + +struct hashset_entry { + struct hashset_entry *next, *previous, *bucket_next, *bucket_previous; + unsigned hash; + const void *key; + void *value; +}; + +struct hashset { + unsigned size; + struct hashset_entry **data; + struct hashset_entry *first_entry; + + unsigned n_entries; + unsigned (*hash_func) (const void *p); + int (*compare_func) (const void*a, const void*b); +}; + +struct hashset *hashset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { + struct hashset *h; + h = malloc(sizeof(struct hashset)); + assert(h); + h->data = malloc(sizeof(struct hashset_entry*)*(h->size = 1023)); + assert(h->data); + memset(h->data, 0, sizeof(struct hashset_entry*)*(h->size = 1023)); + h->first_entry = NULL; + h->n_entries = 0; + h->hash_func = hash_func ? hash_func : idxset_trivial_hash_func; + h->compare_func = compare_func ? compare_func : idxset_trivial_compare_func; + return h; +} + +static void remove(struct hashset *h, struct hashset_entry *e) { + assert(e); + + if (e->next) + e->next->previous = e->previous; + if (e->previous) + e->previous->next = e->next; + else + h->first_entry = e->next; + + if (e->bucket_next) + e->bucket_next->bucket_previous = e->bucket_previous; + if (e->bucket_previous) + e->bucket_previous->bucket_next = e->bucket_next; + else + h->data[e->hash] = e->bucket_next; + + free(e); + h->n_entries--; +} + +void hashset_free(struct hashset*h, void (*free_func)(void *p, void *userdata), void *userdata) { + assert(h); + + while (h->first_entry) { + if (free_func) + free_func(h->first_entry->value, userdata); + remove(h, h->first_entry); + } + + free(h->data); + free(h); +} + +static struct hashset_entry *get(struct hashset *h, unsigned hash, const void *key) { + struct hashset_entry *e; + + for (e = h->data[hash]; e; e = e->bucket_next) + if (h->compare_func(e->key, key) == 0) + return e; + + return NULL; +} + +int hashset_put(struct hashset *h, const void *key, void *value) { + struct hashset_entry *e; + unsigned hash; + assert(h && key); + + hash = h->hash_func(key) % h->size; + + if ((e = get(h, hash, key))) + return -1; + + e = malloc(sizeof(struct hashset_entry)); + assert(e); + + e->hash = hash; + e->key = key; + e->value = value; + + e->previous = NULL; + e->next = h->first_entry; + if (h->first_entry) + h->first_entry->previous = e; + h->first_entry = e; + + e->bucket_previous = NULL; + e->bucket_next = h->data[hash]; + if (h->data[hash]) + h->data[hash]->bucket_previous = e; + h->data[hash] = e; + + h->n_entries ++; + return 0; +} + +void* hashset_get(struct hashset *h, const void *key) { + unsigned hash; + struct hashset_entry *e; + assert(h && key); + + hash = h->hash_func(key) % h->size; + + if (!(e = get(h, hash, key))) + return NULL; + + return e->value; +} + +int hashset_remove(struct hashset *h, const void *key) { + struct hashset_entry *e; + unsigned hash; + assert(h && key); + + hash = h->hash_func(key) % h->size; + + if (!(e = get(h, hash, key))) + return 1; + + remove(h, e); + return 0; +} + +unsigned hashset_ncontents(struct hashset *h) { + return h->n_entries; +} diff --git a/src/hashset.h b/src/hashset.h new file mode 100644 index 000000000..7e035c02e --- /dev/null +++ b/src/hashset.h @@ -0,0 +1,16 @@ +#ifndef foohashsethfoo +#define foohashsethfoo + +struct hashset; + +struct hashset *hashset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); +void hashset_free(struct hashset*, void (*free_func)(void *p, void *userdata), void *userdata); + +int hashset_put(struct hashset *h, const void *key, void *value); +void* hashset_get(struct hashset *h, const void *key); + +int hashset_remove(struct hashset *h, const void *key); + +unsigned hashset_ncontents(struct hashset *h); + +#endif diff --git a/src/idxset.c b/src/idxset.c index ea609f601..090bfc726 100644 --- a/src/idxset.c +++ b/src/idxset.c @@ -15,29 +15,43 @@ struct idxset_entry { }; struct idxset { - unsigned (*hash_func) (void *p); - int (*compare_func)(void *a, void *b); + unsigned (*hash_func) (const void *p); + int (*compare_func)(const void *a, const void *b); unsigned hash_table_size, n_entries; struct idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail; uint32_t index, start_index, array_size; }; -static unsigned trivial_hash_func(void *p) { +unsigned idxset_string_hash_func(const void *p) { + unsigned hash = 0; + const char *c; + + for (c = p; *c; c++) + hash = 31 * hash + *c; + + return hash; +} + +int idxset_string_compare_func(const void *a, const void *b) { + return strcmp(a, b); +} + +unsigned idxset_trivial_hash_func(const void *p) { return (unsigned) p; } -static int trivial_compare_func(void *a, void *b) { +int idxset_trivial_compare_func(const void *a, const void *b) { return a != b; } -struct idxset* idxset_new(unsigned (*hash_func) (void *p), int (*compare_func) (void*a, void*b)) { +struct idxset* idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { struct idxset *s; s = malloc(sizeof(struct idxset)); assert(s); - s->hash_func = hash_func ? hash_func : trivial_hash_func; - s->compare_func = compare_func ? compare_func : trivial_compare_func; + s->hash_func = hash_func ? hash_func : idxset_trivial_hash_func; + s->compare_func = compare_func ? compare_func : idxset_trivial_compare_func; s->hash_table_size = 1023; s->hash_table = malloc(sizeof(struct idxset_entry*)*s->hash_table_size); assert(s->hash_table); diff --git a/src/idxset.h b/src/idxset.h index 90b9d2478..615039776 100644 --- a/src/idxset.h +++ b/src/idxset.h @@ -5,9 +5,15 @@ #define IDXSET_INVALID ((uint32_t) -1) +unsigned idxset_trivial_hash_func(const void *p); +int idxset_trivial_compare_func(const void *a, const void *b); + +unsigned idxset_string_hash_func(const void *p); +int idxset_string_compare_func(const void *a, const void *b); + struct idxset; -struct idxset* idxset_new(unsigned (*hash_func) (void *p), int (*compare_func) (void*a, void*b)); +struct idxset* idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); void idxset_free(struct idxset *s, void (*free_func) (void *p, void *userdata), void *userdata); int idxset_put(struct idxset*s, void *p, uint32_t *index); diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index f08dd7d3c..3997c4907 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -262,7 +262,7 @@ int module_init(struct core *c, struct module*m) { } } else { - u->source = source_new(c, "dsp", &u->sample_spec); + u->source = source_new(c, "dsp", 0, &u->sample_spec); assert(u->source); u->source->userdata = u; @@ -293,7 +293,7 @@ int module_init(struct core *c, struct module*m) { } else { silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); - u->sink = sink_new(c, "dsp", &u->sample_spec); + u->sink = sink_new(c, "dsp", 0, &u->sample_spec); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; diff --git a/src/module-oss.c b/src/module-oss.c index b5d1427a4..75082a7fd 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -180,7 +180,7 @@ int module_init(struct core *c, struct module*m) { u->core = c; if (mode != O_RDONLY) { - u->sink = sink_new(c, "dsp", &ss); + u->sink = sink_new(c, "dsp", 0, &ss); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; @@ -188,7 +188,7 @@ int module_init(struct core *c, struct module*m) { u->sink = NULL; if (mode != O_WRONLY) { - u->source = source_new(c, "dsp", &ss); + u->source = source_new(c, "dsp", 0, &ss); assert(u->source); u->source->userdata = u; } else diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index 9dcf5d231..6cc4de882 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -109,7 +109,7 @@ int module_init(struct core *c, struct module*m) { u->filename = strdup(p); assert(u->filename); u->core = c; - u->sink = sink_new(c, "fifo", &ss); + u->sink = sink_new(c, "fifo", 0, &ss); assert(u->sink); u->sink->notify = notify_cb; u->sink->userdata = u; diff --git a/src/namereg.c b/src/namereg.c new file mode 100644 index 000000000..b286171db --- /dev/null +++ b/src/namereg.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include + +#include "namereg.h" + +struct namereg_entry { + enum namereg_type type; + char *name; + void *data; +}; + +void namereg_free(struct core *c) { + assert(c); + if (!c->namereg) + return; + assert(hashset_ncontents(c->namereg) == 0); + hashset_free(c->namereg, NULL, NULL); +} + +const char *namereg_register(struct core *c, const char *name, enum namereg_type type, void *data, int fail) { + struct namereg_entry *e; + char *n = NULL; + int r; + + assert(c && name && data); + + if (!c->namereg) { + c->namereg = hashset_new(idxset_string_hash_func, idxset_string_compare_func); + assert(c->namereg); + } + + if ((e = hashset_get(c->namereg, name)) && fail) + return NULL; + + if (!e) + n = strdup(name); + else { + unsigned i; + size_t l = strlen(name); + n = malloc(l+3); + assert(n); + + for (i = 1; i <= 99; i++) { + snprintf(n, l+2, "%s%u", name, i); + + if (!(e = hashset_get(c->namereg, n))) + break; + } + + if (e) { + free(n); + return NULL; + } + } + + assert(n); + e = malloc(sizeof(struct namereg_entry)); + assert(e); + e->type = type; + e->name = n; + e->data = data; + + r = hashset_put(c->namereg, e->name, e); + assert (r >= 0); + + return e->name; + +} + +void namereg_unregister(struct core *c, const char *name) { + struct namereg_entry *e; + int r; + assert(c && name); + + e = hashset_get(c->namereg, name); + assert(e); + + r = hashset_remove(c->namereg, name); + assert(r >= 0); + + free(e->name); + free(e); +} + +void* namereg_get(struct core *c, const char *name, enum namereg_type type) { + struct namereg_entry *e; + assert(c && name); + + if (!(e = hashset_get(c->namereg, name))) + if (e->type == e->type) + return e->data; + + return NULL; +} diff --git a/src/namereg.h b/src/namereg.h new file mode 100644 index 000000000..5632143b7 --- /dev/null +++ b/src/namereg.h @@ -0,0 +1,17 @@ +#ifndef foonamereghfoo +#define foonamereghfoo + +#include "core.h" + +enum namereg_type { + NAMEREG_SINK, + NAMEREG_SOURCE +}; + +void namereg_free(struct core *c); + +const char *namereg_register(struct core *c, const char *name, enum namereg_type type, void *data, int fail); +void namereg_unregister(struct core *c, const char *name); +void* namereg_get(struct core *c, const char *name, enum namereg_type type); + +#endif diff --git a/src/sink.c b/src/sink.c index a334424c2..5ab1a7a78 100644 --- a/src/sink.c +++ b/src/sink.c @@ -7,10 +7,11 @@ #include "sinkinput.h" #include "strbuf.h" #include "sample-util.h" +#include "namereg.h" #define MAX_MIX_CHANNELS 32 -struct sink* sink_new(struct core *core, const char *name, const struct pa_sample_spec *spec) { +struct sink* sink_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec) { struct sink *s; char *n = NULL; int r; @@ -18,8 +19,13 @@ struct sink* sink_new(struct core *core, const char *name, const struct pa_sampl s = malloc(sizeof(struct sink)); assert(s); + + if (!(name = namereg_register(core, name, NAMEREG_SINK, s, fail))) { + free(s); + return NULL; + } - s->name = name ? strdup(name) : NULL; + s->name = strdup(name); s->core = core; s->sample_spec = *spec; s->inputs = idxset_new(NULL, NULL); @@ -29,7 +35,8 @@ struct sink* sink_new(struct core *core, const char *name, const struct pa_sampl sprintf(n, "%s_monitor", name); } - s->monitor_source = source_new(core, n, spec); + s->monitor_source = source_new(core, n, 0, spec); + assert(s->monitor_source); free(n); s->volume = 0xFF; @@ -50,6 +57,8 @@ void sink_free(struct sink *s) { struct sink_input *i, *j = NULL; assert(s); + namereg_unregister(s->core, s->name); + while ((i = idxset_first(s->inputs, NULL))) { assert(i != j); sink_input_kill(i); diff --git a/src/sink.h b/src/sink.h index d9f80059d..a5b1ff68e 100644 --- a/src/sink.h +++ b/src/sink.h @@ -27,7 +27,7 @@ struct sink { void *userdata; }; -struct sink* sink_new(struct core *core, const char *name, const struct pa_sample_spec *spec); +struct sink* sink_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec); void sink_free(struct sink* s); int sink_render(struct sink*s, size_t length, struct memchunk *result); diff --git a/src/source.c b/src/source.c index 21ac24f35..deacfb3d6 100644 --- a/src/source.c +++ b/src/source.c @@ -6,8 +6,9 @@ #include "source.h" #include "sourceoutput.h" #include "strbuf.h" +#include "namereg.h" -struct source* source_new(struct core *core, const char *name, const struct pa_sample_spec *spec) { +struct source* source_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec) { struct source *s; int r; assert(core && spec); @@ -15,7 +16,12 @@ struct source* source_new(struct core *core, const char *name, const struct pa_s s = malloc(sizeof(struct source)); assert(s); - s->name = name ? strdup(name) : NULL; + if (!(name = namereg_register(core, name, NAMEREG_SOURCE, s, fail))) { + free(s); + return NULL; + } + + s->name = strdup(name); s->core = core; s->sample_spec = *spec; s->outputs = idxset_new(NULL, NULL); @@ -35,6 +41,8 @@ void source_free(struct source *s) { struct source_output *o, *j = NULL; assert(s); + namereg_unregister(s->core, s->name); + while ((o = idxset_first(s->outputs, NULL))) { assert(o != j); source_output_kill(o); diff --git a/src/source.h b/src/source.h index 04f3984f7..afae5a68b 100644 --- a/src/source.h +++ b/src/source.h @@ -21,7 +21,7 @@ struct source { void *userdata; }; -struct source* source_new(struct core *core, const char *name, const struct pa_sample_spec *spec); +struct source* source_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec); void source_free(struct source *s); /* Pass a new memory block to all output streams */ diff --git a/src/todo b/src/todo index 47344ab42..78768be0f 100644 --- a/src/todo +++ b/src/todo @@ -1,13 +1,19 @@ -- sync() function in native library -- name registrar -- native protocol/library -- simple control protocol: kill client/input/output; set_volume +- native library/protocol: + recording + sync() function + more functions +- simple library +- simple control protocol: + kill client/input/output + set_volume - resampling +- volume adjust on single sink input +- fp volume scaling (both < and > 1) - esound protocol - config parser/cmdline - record testing + -- 0.1 -- optimierung von rebuild_pollfds() - future cancellation - client-ui - clip cache From ef422fa4ae626e9638ca70d1c56f27e701dd69c2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Jun 2004 16:48:37 +0000 Subject: [PATCH 0039/1514] esound protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@40 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 31 ++- src/client.c | 6 + src/client.h | 2 + src/esound-spec.h | 191 +++++++++++++++ src/main.c | 9 +- src/module-pipe-sink.c | 2 +- src/module-protocol-stub.c | 39 +++- src/oss-util.c | 6 +- src/pacat.c | 2 +- src/protocol-esound.c | 462 +++++++++++++++++++++++++++++++++++++ src/protocol-esound.h | 12 + src/protocol-native.c | 1 + src/protocol-simple.c | 3 +- src/sample-util.c | 18 +- src/sample.c | 26 ++- src/sample.h | 17 +- src/util.c | 23 ++ src/util.h | 2 + 18 files changed, 806 insertions(+), 46 deletions(-) create mode 100644 src/esound-spec.h create mode 100644 src/protocol-esound.c create mode 100644 src/protocol-esound.h diff --git a/src/Makefile.am b/src/Makefile.am index a67f395e8..af4478be6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,7 +29,8 @@ pkglib_LTLIBRARIES=libiochannel.la libsocket-server.la libsocket-client.la \ libprotocol-cli.la module-cli-protocol-unix.la libtagstruct.la \ libpdispatch.la libprotocol-native.la libpstream-util.la \ module-native-protocol-tcp.la module-native-protocol-unix.la \ - libpolyp.la + libpolyp.la libprotocol-esound.la module-esound-protocol-unix.la \ + module-esound-protocol-tcp.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -113,40 +114,54 @@ libprotocol_cli_la_LIBADD = libsocket-server.la libiochannel.la libcli.la libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = libsocket-server.la libiochannel.la libpacket.la libpstream.la libpstream-util.la libpdispatch.la +libprotocol_native_la_LIBADD = libsocket-server.la libiochannel.la libpacket.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libtagstruct_la_SOURCES = tagstruct.c tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version +libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h protocol-esound-spec.h +libprotocol_esound_la_LDFLAGS = -avoid-version +libprotocol_esound_la_LIBADD = libsocket-server.la libiochannel.la + module_simple_protocol_tcp_la_SOURCES = module-protocol-stub.c module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libiochannel.la +module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libsocket-server.la module_simple_protocol_unix_la_SOURCES = module-protocol-stub.c module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version -module_simple_protocol_unix_la_LIBADD = libprotocol-simple.la libiochannel.la +module_simple_protocol_unix_la_LIBADD = libprotocol-simple.la libsocket-server.la module_cli_protocol_tcp_la_SOURCES = module-protocol-stub.c module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_cli_protocol_tcp_la_LIBADD = libprotocol-cli.la libiochannel.la +module_cli_protocol_tcp_la_LIBADD = libprotocol-cli.la libsocket-server.la module_cli_protocol_unix_la_SOURCES = module-protocol-stub.c module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version -module_cli_protocol_unix_la_LIBADD = libprotocol-cli.la libiochannel.la +module_cli_protocol_unix_la_LIBADD = libprotocol-cli.la libsocket-server.la module_native_protocol_tcp_la_SOURCES = module-protocol-stub.c module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_native_protocol_tcp_la_LIBADD = libprotocol-native.la libiochannel.la libtagstruct.la +module_native_protocol_tcp_la_LIBADD = libprotocol-native.la libsocket-server.la module_native_protocol_unix_la_SOURCES = module-protocol-stub.c module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_unix_la_LDFLAGS = -module -avoid-version -module_native_protocol_unix_la_LIBADD = libprotocol-native.la libiochannel.la libtagstruct.la +module_native_protocol_unix_la_LIBADD = libprotocol-native.la libsocket-server.la + +module_esound_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) +module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version +module_esound_protocol_tcp_la_LIBADD = libprotocol-esound.la libsocket-server.la + +module_esound_protocol_unix_la_SOURCES = module-protocol-stub.c +module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) +module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version +module_esound_protocol_unix_la_LIBADD = libprotocol-esound.la libsocket-server.la module_pipe_sink_la_SOURCES = module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version diff --git a/src/client.c b/src/client.c index 4c8a04910..376912832 100644 --- a/src/client.c +++ b/src/client.c @@ -60,3 +60,9 @@ char *client_list_to_string(struct core *c) { return strbuf_tostring_free(s); } + +void client_rename(struct client *c, const char *name) { + assert(c); + free(c->name); + c->name = name ? strdup(name) : NULL; +} diff --git a/src/client.h b/src/client.h index 481720518..39167ee79 100644 --- a/src/client.h +++ b/src/client.h @@ -25,4 +25,6 @@ void client_kill(struct client *c); char *client_list_to_string(struct core *c); +void client_rename(struct client *c, const char *name); + #endif diff --git a/src/esound-spec.h b/src/esound-spec.h new file mode 100644 index 000000000..1c2dc0222 --- /dev/null +++ b/src/esound-spec.h @@ -0,0 +1,191 @@ +#ifndef fooesoundhfoo +#define fooesoundhfoo + +/* Most of the following is blatantly stolen from esound. */ + + +/* path and name of the default EsounD domain socket */ +#define ESD_UNIX_SOCKET_DIR "/tmp/.esd" +#define ESD_UNIX_SOCKET_NAME "/tmp/.esd/socket" + +/* length of the audio buffer size */ +#define ESD_BUF_SIZE (4 * 1024) +/* maximum size we can write(). Otherwise we might overflow */ +#define ESD_MAX_WRITE_SIZE (21 * 4096) + +/* length of the authorization key, octets */ +#define ESD_KEY_LEN (16) + +/* default port for the EsounD server */ +#define ESD_DEFAULT_PORT (16001) + +/* default sample rate for the EsounD server */ +#define ESD_DEFAULT_RATE (44100) + +/* maximum length of a stream/sample name */ +#define ESD_NAME_MAX (128) + +/* a magic number to identify the relative endianness of a client */ +#define ESD_ENDIAN_KEY ((uint32_t) (('E' << 24) + ('N' << 16) + ('D' << 8) + ('N'))) + +#define ESD_VOLUME_BASE (256) + + +/*************************************/ +/* what can we do to/with the EsounD */ +enum esd_proto { + ESD_PROTO_CONNECT, /* implied on inital client connection */ + + /* pseudo "security" functionality */ + ESD_PROTO_LOCK, /* disable "foreign" client connections */ + ESD_PROTO_UNLOCK, /* enable "foreign" client connections */ + + /* stream functionality: play, record, monitor */ + ESD_PROTO_STREAM_PLAY, /* play all following data as a stream */ + ESD_PROTO_STREAM_REC, /* record data from card as a stream */ + ESD_PROTO_STREAM_MON, /* send mixed buffer output as a stream */ + + /* sample functionality: cache, free, play, loop, EOL, kill */ + ESD_PROTO_SAMPLE_CACHE, /* cache a sample in the server */ + ESD_PROTO_SAMPLE_FREE, /* release a sample in the server */ + ESD_PROTO_SAMPLE_PLAY, /* play a cached sample */ + ESD_PROTO_SAMPLE_LOOP, /* loop a cached sample, til eoloop */ + ESD_PROTO_SAMPLE_STOP, /* stop a looping sample when done */ + ESD_PROTO_SAMPLE_KILL, /* stop the looping sample immed. */ + + /* free and reclaim /dev/dsp functionality */ + ESD_PROTO_STANDBY, /* release /dev/dsp and ignore all data */ + ESD_PROTO_RESUME, /* reclaim /dev/dsp and play sounds again */ + + /* TODO: move these to a more logical place. NOTE: will break the protocol */ + ESD_PROTO_SAMPLE_GETID, /* get the ID for an already-cached sample */ + ESD_PROTO_STREAM_FILT, /* filter mixed buffer output as a stream */ + + /* esd remote management */ + ESD_PROTO_SERVER_INFO, /* get server info (ver, sample rate, format) */ + ESD_PROTO_ALL_INFO, /* get all info (server info, players, samples) */ + ESD_PROTO_SUBSCRIBE, /* track new and removed players and samples */ + ESD_PROTO_UNSUBSCRIBE, /* stop tracking updates */ + + /* esd remote control */ + ESD_PROTO_STREAM_PAN, /* set stream panning */ + ESD_PROTO_SAMPLE_PAN, /* set default sample panning */ + + /* esd status */ + ESD_PROTO_STANDBY_MODE, /* see if server is in standby, autostandby, etc */ + + /* esd latency */ + ESD_PROTO_LATENCY, /* retrieve latency between write()'s and output */ + + ESD_PROTO_MAX /* for bounds checking */ +}; + +/******************/ +/* The EsounD api */ + +/* the properties of a sound buffer are logically or'd */ + +/* bits of stream/sample data */ +#define ESD_MASK_BITS ( 0x000F ) +#define ESD_BITS8 ( 0x0000 ) +#define ESD_BITS16 ( 0x0001 ) + +/* how many interleaved channels of data */ +#define ESD_MASK_CHAN ( 0x00F0 ) +#define ESD_MONO ( 0x0010 ) +#define ESD_STEREO ( 0x0020 ) + +/* whether it's a stream or a sample */ +#define ESD_MASK_MODE ( 0x0F00 ) +#define ESD_STREAM ( 0x0000 ) +#define ESD_SAMPLE ( 0x0100 ) +#define ESD_ADPCM ( 0x0200 ) /* TODO: anyone up for this? =P */ + +/* the function of the stream/sample, and common functions */ +#define ESD_MASK_FUNC ( 0xF000 ) +#define ESD_PLAY ( 0x1000 ) +/* functions for streams only */ +#define ESD_MONITOR ( 0x0000 ) +#define ESD_RECORD ( 0x2000 ) +/* functions for samples only */ +#define ESD_STOP ( 0x0000 ) +#define ESD_LOOP ( 0x2000 ) + +typedef int esd_format_t; +typedef int esd_proto_t; + +/*******************************************************************/ +/* esdmgr.c - functions to implement a "sound manager" for esd */ + +/* structures to retrieve information about streams/samples from the server */ +typedef struct esd_server_info { + + int version; /* server version encoded as an int */ + esd_format_t format; /* magic int with the format info */ + int rate; /* sample rate */ + +} esd_server_info_t; + +typedef struct esd_player_info { + + struct esd_player_info *next; /* point to next entry in list */ + esd_server_info_t *server; /* the server that contains this stream */ + + int source_id; /* either a stream fd or sample id */ + char name[ ESD_NAME_MAX ]; /* name of stream for remote control */ + int rate; /* sample rate */ + int left_vol_scale; /* volume scaling */ + int right_vol_scale; + + esd_format_t format; /* magic int with the format info */ + +} esd_player_info_t; + +typedef struct esd_sample_info { + + struct esd_sample_info *next; /* point to next entry in list */ + esd_server_info_t *server; /* the server that contains this sample */ + + int sample_id; /* either a stream fd or sample id */ + char name[ ESD_NAME_MAX ]; /* name of stream for remote control */ + int rate; /* sample rate */ + int left_vol_scale; /* volume scaling */ + int right_vol_scale; + + esd_format_t format; /* magic int with the format info */ + int length; /* total buffer length */ + +} esd_sample_info_t; + +typedef struct esd_info { + + esd_server_info_t *server; + esd_player_info_t *player_list; + esd_sample_info_t *sample_list; + +} esd_info_t; + +enum esd_standby_mode { + ESM_ERROR, ESM_ON_STANDBY, ESM_ON_AUTOSTANDBY, ESM_RUNNING +}; +typedef int esd_standby_mode_t; + +enum esd_client_state { + ESD_STREAMING_DATA, /* data from here on is streamed data */ + ESD_CACHING_SAMPLE, /* midway through caching a sample */ + ESD_NEEDS_REQDATA, /* more data needed to complere request */ + ESD_NEXT_REQUEST, /* proceed to next request */ + ESD_CLIENT_STATE_MAX /* place holder */ +}; +typedef int esd_client_state_t; + +/* switch endian order for cross platform playing */ +#define swap_endian_32(x) ((x >> 24) | ((x >> 8) & 0xFF00) | (((x & 0xFF00) << 8)) | (x << 24)) + +/* the endian key is transferred in binary, if it's read into int, */ +/* and matches ESD_ENDIAN_KEY (ENDN), then the endianness of the */ +/* server and the client match; if it's SWAP_ENDIAN_KEY, swap data */ +#define ESD_SWAP_ENDIAN_KEY ((uint32_t) swap_endian_32(ESD_ENDIAN_KEY)) + + +#endif diff --git a/src/main.c b/src/main.c index 0fe333e0e..e50321f8d 100644 --- a/src/main.c +++ b/src/main.c @@ -41,11 +41,12 @@ int main(int argc, char *argv[]) { module_load(c, "module-oss-mmap", "/dev/dsp1"); /* module_load(c, "module-pipe-sink", NULL); module_load(c, "module-simple-protocol-tcp", NULL); - module_load(c, "module-simple-protocol-unix", NULL);*/ + module_load(c, "module-simple-protocol-unix", NULL); module_load(c, "module-cli-protocol-tcp", NULL); -/* module_load(c, "module-cli-protocol-unix", NULL); - module_load(c, "module-native-protocol-tcp", NULL);*/ - module_load(c, "module-native-protocol-unix", NULL); + module_load(c, "module-cli-protocol-unix", NULL); + module_load(c, "module-native-protocol-tcp", NULL); + module_load(c, "module-native-protocol-unix", NULL);*/ + module_load(c, "module-esound-protocol-tcp", NULL); module_load(c, "module-cli", NULL); fprintf(stderr, "main: mainloop entry.\n"); diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index 6cc4de882..9747c3307 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -79,7 +79,7 @@ int module_init(struct core *c, struct module*m) { char *p; int fd = -1; static const struct pa_sample_spec ss = { - .format = SAMPLE_S16NE, + .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2, }; diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 97bf5ef3c..29ce6b18c 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -1,31 +1,47 @@ +#include #include #include +#include #include "module.h" #include "socket-server.h" +#include "util.h" #ifdef USE_PROTOCOL_SIMPLE #include "protocol-simple.h" #define protocol_free protocol_simple_free #define IPV4_PORT 4711 - #define UNIX_SOCKET "/tmp/polypaudio_simple" + #define UNIX_SOCKET_DIR "/tmp/polypaudio" + #define UNIX_SOCKET "/tmp/polypaudio/simple" #else #ifdef USE_PROTOCOL_CLI #include "protocol-cli.h" #define protocol_new protocol_cli_new #define protocol_free protocol_cli_free #define IPV4_PORT 4712 - #define UNIX_SOCKET "/tmp/polypaudio_cli" + #define UNIX_SOCKET_DIR "/tmp/polypaudio" + #define UNIX_SOCKET "/tmp/polypaudio/cli" #else #ifdef USE_PROTOCOL_NATIVE #include "protocol-native.h" #define protocol_new protocol_native_new #define protocol_free protocol_native_free #define IPV4_PORT 4713 - #define UNIX_SOCKET "/tmp/polypaudio_native" + #define UNIX_SOCKET_DIR "/tmp/polypaudio" + #define UNIX_SOCKET "/tmp/polypaudio/native" #else - #error "Broken build system" - #endif + #ifdef USE_PROTOCOL_ESOUND + #include "protocol-esound.h" + #include "esound-spec.h" + #define protocol_new protocol_esound_new + #define protocol_free protocol_esound_free + #define IPV4_PORT ESD_DEFAULT_PORT + #define UNIX_SOCKET_DIR ESD_UNIX_SOCKET_DIR + #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME + #else + #error "Broken build system" + #endif + #endif #endif #endif @@ -37,8 +53,15 @@ int module_init(struct core *c, struct module*m) { if (!(s = socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, IPV4_PORT))) return -1; #else - if (!(s = socket_server_new_unix(c->mainloop, UNIX_SOCKET))) + if (make_secure_dir(UNIX_SOCKET_DIR) < 0) { + fprintf(stderr, "Failed to create secure socket directory.\n"); return -1; + } + + if (!(s = socket_server_new_unix(c->mainloop, UNIX_SOCKET))) { + rmdir(UNIX_SOCKET_DIR); + return -1; + } #endif #ifdef USE_PROTOCOL_SIMPLE @@ -55,4 +78,8 @@ void module_done(struct core *c, struct module*m) { assert(c && m); protocol_free(m->userdata); + +#ifndef USE_TCP_SOCKETS + rmdir(UNIX_SOCKET_DIR); +#endif } diff --git a/src/oss-util.c b/src/oss-util.c index bf6b62e29..d3a5fecbb 100644 --- a/src/oss-util.c +++ b/src/oss-util.c @@ -22,11 +22,11 @@ int oss_auto_format(int fd, struct pa_sample_spec *ss) { fprintf(stderr, "SNDCTL_DSP_SETFMT: %s\n", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); return -1; } else - ss->format = SAMPLE_U8; + ss->format = PA_SAMPLE_U8; } else - ss->format = f == AFMT_S16_LE ? SAMPLE_S16LE : SAMPLE_S16BE; + ss->format = f == AFMT_S16_LE ? PA_SAMPLE_S16LE : PA_SAMPLE_S16BE; } else - ss->format = SAMPLE_S16NE; + ss->format = PA_SAMPLE_S16NE; channels = 2; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { diff --git a/src/pacat.c b/src/pacat.c index 5ee1b866c..fbd1d081e 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -75,7 +75,7 @@ static void stream_complete_callback(struct pa_context*c, struct pa_stream *s, v static void context_complete_callback(struct pa_context *c, int success, void *userdata) { static const struct pa_sample_spec ss = { - .format = SAMPLE_S16NE, + .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 }; diff --git a/src/protocol-esound.c b/src/protocol-esound.c new file mode 100644 index 000000000..1668ef550 --- /dev/null +++ b/src/protocol-esound.c @@ -0,0 +1,462 @@ +#include +#include +#include +#include +#include +#include + +#include "protocol-esound.h" +#include "esound-spec.h" +#include "memblock.h" +#include "client.h" +#include "sinkinput.h" +#include "sink.h" +#include "sample.h" + +/* This is heavily based on esound's code */ + +struct connection { + struct protocol_esound *protocol; + struct iochannel *io; + struct client *client; + int authorized, swap_byte_order; + void *read_data; + size_t read_data_alloc, read_data_length; + void *write_data; + size_t write_data_alloc, write_data_index, write_data_length; + esd_proto_t request; + esd_client_state_t state; + struct sink_input *sink_input; + struct memblockq *input_memblockq; +}; + +struct protocol_esound { + int public; + struct core *core; + struct socket_server *server; + struct idxset *connections; +}; + +typedef struct proto_handler { + size_t data_length; + int (*proc)(struct connection *c, const void *data, size_t length); + const char *description; +} esd_proto_handler_info_t; + +#define BUFSIZE PIPE_BUF + +static void sink_input_drop_cb(struct sink_input *i, size_t length); +static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk); +static void sink_input_kill_cb(struct sink_input *i); +static uint32_t sink_input_get_latency_cb(struct sink_input *i); + +static int esd_proto_connect(struct connection *c, const void *data, size_t length); +static int esd_proto_stream_play(struct connection *c, const void *data, size_t length); +static int esd_proto_stream_record(struct connection *c, const void *data, size_t length); + +static int do_write(struct connection *c); + +/* the big map of protocol handler info */ +static struct proto_handler proto_map[ESD_PROTO_MAX] = { + { ESD_KEY_LEN + sizeof(int), &esd_proto_connect, "connect" }, + { ESD_KEY_LEN + sizeof(int), NULL, "lock" }, + { ESD_KEY_LEN + sizeof(int), NULL, "unlock" }, + + { ESD_NAME_MAX + 2 * sizeof(int), &esd_proto_stream_play, "stream play" }, + { ESD_NAME_MAX + 2 * sizeof(int), &esd_proto_stream_record, "stream rec" }, + { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream mon" }, + + { ESD_NAME_MAX + 3 * sizeof(int), NULL, "sample cache" }, + { sizeof(int), NULL, "sample free" }, + { sizeof(int), NULL, "sample play" }, + { sizeof(int), NULL, "sample loop" }, + { sizeof(int), NULL, "sample stop" }, + { -1, NULL, "TODO: sample kill" }, + + { ESD_KEY_LEN + sizeof(int), NULL, "standby" }, + { ESD_KEY_LEN + sizeof(int), NULL, "resume" }, + + { ESD_NAME_MAX, NULL, "sample getid" }, + { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream filter" }, + + { sizeof(int), NULL, "server info" }, + { sizeof(int), NULL, "all info" }, + { -1, NULL, "TODO: subscribe" }, + { -1, NULL, "TODO: unsubscribe" }, + + { 3 * sizeof(int), NULL, "stream pan"}, + { 3 * sizeof(int), NULL, "sample pan" }, + + { sizeof(int), NULL, "standby mode" }, + { 0, NULL, "get latency" } +}; + + +static void connection_free(struct connection *c) { + assert(c); + idxset_remove_by_data(c->protocol->connections, c, NULL); + + client_free(c->client); + + if (c->sink_input) + sink_input_free(c->sink_input); + if (c->input_memblockq) + memblockq_free(c->input_memblockq); + + free(c->read_data); + free(c->write_data); + + iochannel_free(c->io); + free(c); +} + +static struct sink* get_output_sink(struct protocol_esound *p) { + assert(p); + return sink_get_default(p->core); +} + +static void* connection_write(struct connection *c, size_t length) { + size_t t, i; + assert(c); + + t = c->write_data_length+length; + + if (c->write_data_alloc < t) + c->write_data = realloc(c->write_data, c->write_data_alloc = t); + + assert(c->write_data); + + i = c->write_data_length; + c->write_data_length += length; + + return c->write_data+i; +} + +/*** esound commands ***/ + +static int esd_proto_connect(struct connection *c, const void *data, size_t length) { + uint32_t ekey; + int *ok; + assert(length == (ESD_KEY_LEN + sizeof(uint32_t))); + + c->authorized = 1; + + ekey = *(uint32_t*)(data+ESD_KEY_LEN); + if (ekey == ESD_ENDIAN_KEY) + c->swap_byte_order = 0; + else if (ekey == ESD_SWAP_ENDIAN_KEY) + c->swap_byte_order = 1; + else { + fprintf(stderr, "protocol-esound.c: client sent invalid endian key\n"); + return -1; + } + + ok = connection_write(c, sizeof(int)); + assert(ok); + *ok = 1; + + do_write(c); + + return 0; +} + +static int esd_proto_stream_play(struct connection *c, const void *data, size_t length) { + char name[ESD_NAME_MAX]; + int format, rate; + struct sink *sink; + struct pa_sample_spec ss; + assert(length == (sizeof(int)*2+ESD_NAME_MAX)); + + format = *(int*)data; + rate = *((int*)data + 1); + + if (c->swap_byte_order) + format = swap_endian_32(format); + if (c->swap_byte_order) + rate = swap_endian_32(rate); + + ss.rate = rate; + ss.channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1; + ss.format = ((format & ESD_MASK_BITS) == ESD_BITS16) ? PA_SAMPLE_S16NE : PA_SAMPLE_U8; + + if (!pa_sample_spec_valid(&ss)) + return -1; + + if (!(sink = get_output_sink(c->protocol))) + return -1; + + strncpy(name, data + sizeof(int)*2, sizeof(name)); + name[sizeof(name)-1] = 0; + + client_rename(c->client, name); + + assert(!c->input_memblockq); + c->input_memblockq = memblockq_new(1024*10, pa_sample_size(&ss), 1024*2); + assert(c->input_memblockq); + + assert(!c->sink_input); + c->sink_input = sink_input_new(sink, &ss, name); + assert(c->sink_input); + + c->sink_input->peek = sink_input_peek_cb; + c->sink_input->drop = sink_input_drop_cb; + c->sink_input->kill = sink_input_kill_cb; + c->sink_input->get_latency = sink_input_get_latency_cb; + c->sink_input->userdata = c; + + c->state = ESD_STREAMING_DATA; + + return 0; +} + +static int esd_proto_stream_record(struct connection *c, const void *data, size_t length) { + assert(0); +} + +/*** client callbacks ***/ + +static void client_kill_cb(struct client *c) { + assert(c && c->userdata); + connection_free(c->userdata); +} + +/*** iochannel callbacks ***/ + +static int do_read(struct connection *c) { + assert(c && c->io); + + if (!iochannel_is_readable(c->io)) + return 0; + + if (c->state == ESD_NEXT_REQUEST) { + ssize_t r; + assert(c->read_data_length < sizeof(c->request)); + + if ((r = iochannel_read(c->io, ((void*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { + fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + return -1; + } + + if ((c->read_data_length+= r) >= sizeof(c->request)) { + struct proto_handler *handler; + + if (c->swap_byte_order) + c->request = swap_endian_32(c->request); + + if (c->request < ESD_PROTO_CONNECT || c->request > ESD_PROTO_MAX) { + fprintf(stderr, "protocol-esound.c: recieved invalid request.\n"); + return -1; + } + + handler = proto_map+c->request; + + if (!handler->proc) { + fprintf(stderr, "protocol-sound.c: recieved unimplemented request.\n"); + return -1; + } + + if (handler->data_length == 0) { + c->read_data_length = 0; + + if (handler->proc(c, NULL, 0) < 0) + return -1; + + } else { + if (c->read_data_alloc < handler->data_length) + c->read_data = realloc(c->read_data, c->read_data_alloc = handler->data_length); + assert(c->read_data); + + c->state = ESD_NEEDS_REQDATA; + c->read_data_length = 0; + } + } + + } else if (c->state == ESD_NEEDS_REQDATA) { + ssize_t r; + struct proto_handler *handler = proto_map+c->request; + + assert(handler->proc); + + assert(c->read_data && c->read_data_length < handler->data_length); + + if ((r = iochannel_read(c->io, c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { + fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + return -1; + } + + if ((c->read_data_length+= r) >= handler->data_length) { + size_t l = c->read_data_length; + assert(handler->proc); + + c->state = ESD_NEXT_REQUEST; + c->read_data_length = 0; + + if (handler->proc(c, c->read_data, l) < 0) + return -1; + } + } else if (c->state == ESD_STREAMING_DATA) { + struct memchunk chunk; + ssize_t r; + + assert(c->input_memblockq); + + if (!memblockq_is_writable(c->input_memblockq, BUFSIZE)) + return 0; + + chunk.memblock = memblock_new(BUFSIZE); + assert(chunk.memblock && chunk.memblock->data); + + if ((r = iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) { + fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + memblock_unref(chunk.memblock); + return -1; + } + + chunk.memblock->length = chunk.length = r; + chunk.index = 0; + + assert(c->input_memblockq); + memblockq_push(c->input_memblockq, &chunk, 0); + memblock_unref(chunk.memblock); + assert(c->sink_input); + sink_notify(c->sink_input->sink); + } else + assert(0); + + return 0; +} + +static int do_write(struct connection *c) { + ssize_t r; + assert(c && c->io); + + if (!iochannel_is_writable(c->io)) + return 0; + + if (!c->write_data_length) + return 0; + + assert(c->write_data_index < c->write_data_length); + if ((r = iochannel_write(c->io, c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { + fprintf(stderr, "protocol-esound.c: write() failed: %s\n", strerror(errno)); + return -1; + } + + if ((c->write_data_index +=r) >= c->write_data_length) + c->write_data_length = c->write_data_index = 0; + + return 0; +} + +static void io_callback(struct iochannel*io, void *userdata) { + struct connection *c = userdata; + assert(io && c && c->io == io); + + if (do_read(c) < 0 || do_write(c) < 0) + connection_free(c); +} + +/*** sink_input callbacks ***/ + +static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk) { + struct connection*c; + assert(i && i->userdata && chunk); + c = i->userdata; + + if (memblockq_peek(c->input_memblockq, chunk) < 0) + return -1; + + return 0; +} + +static void sink_input_drop_cb(struct sink_input *i, size_t length) { + struct connection*c = i->userdata; + assert(i && c && length); + + memblockq_drop(c->input_memblockq, length); + + if (do_read(c) < 0) + connection_free(c); +} + +static void sink_input_kill_cb(struct sink_input *i) { + assert(i && i->userdata); + connection_free((struct connection *) i->userdata); +} + + +static uint32_t sink_input_get_latency_cb(struct sink_input *i) { + struct connection*c = i->userdata; + assert(i && c); + return pa_samples_usec(memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); +} + +/*** socket server callback ***/ + +static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { + struct connection *c; + char cname[256]; + assert(s && io && userdata); + + c = malloc(sizeof(struct connection)); + assert(c); + c->protocol = userdata; + c->io = io; + iochannel_set_callback(c->io, io_callback, c); + + iochannel_peer_to_string(io, cname, sizeof(cname)); + assert(c->protocol->core); + c->client = client_new(c->protocol->core, "ESOUND", cname); + assert(c->client); + c->client->kill = client_kill_cb; + c->client->userdata = c; + + c->authorized = c->protocol->public; + c->swap_byte_order = 0; + + c->read_data_length = 0; + c->read_data = malloc(c->read_data_alloc = proto_map[ESD_PROTO_CONNECT].data_length); + assert(c->read_data); + + c->write_data_length = c->write_data_index = c->write_data_alloc = 0; + c->write_data = NULL; + + c->state = ESD_NEEDS_REQDATA; + c->request = ESD_PROTO_CONNECT; + + c->sink_input = NULL; + c->input_memblockq = NULL; + + idxset_put(c->protocol->connections, c, NULL); +} + +/*** entry points ***/ + +struct protocol_esound* protocol_esound_new(struct core*core, struct socket_server *server) { + struct protocol_esound *p; + assert(core && server); + + p = malloc(sizeof(struct protocol_esound)); + assert(p); + p->public = 1; + p->server = server; + p->core = core; + p->connections = idxset_new(NULL, NULL); + assert(p->connections); + + socket_server_set_callback(p->server, on_connection, p); + + return p; +} + +void protocol_esound_free(struct protocol_esound *p) { + struct connection *c; + assert(p); + + while ((c = idxset_first(p->connections, NULL))) + connection_free(c); + + idxset_free(p->connections, NULL, NULL); + socket_server_free(p->server); + free(p); +} diff --git a/src/protocol-esound.h b/src/protocol-esound.h new file mode 100644 index 000000000..2600cfae4 --- /dev/null +++ b/src/protocol-esound.h @@ -0,0 +1,12 @@ +#ifndef fooprotocolesoundhfoo +#define fooprotocolesoundhfoo + +#include "core.h" +#include "socket-server.h" + +struct protocol_esound; + +struct protocol_esound* protocol_esound_new(struct core*core, struct socket_server *server); +void protocol_esound_free(struct protocol_esound *p); + +#endif diff --git a/src/protocol-native.c b/src/protocol-native.c index 27b547a60..9af438a93 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -384,6 +384,7 @@ struct protocol_native* protocol_native_new(struct core *core, struct socket_ser p->server = server; p->core = core; p->connections = idxset_new(NULL, NULL); + assert(p->connections); socket_server_set_callback(p->server, on_connection, p); diff --git a/src/protocol-simple.c b/src/protocol-simple.c index c8c458548..80249eef0 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -73,8 +73,7 @@ static int do_read(struct connection *c) { return -1; } - chunk.memblock->length = r; - chunk.length = r; + chunk.memblock->length = chunk.length = r; chunk.index = 0; assert(c->input_memblockq); diff --git a/src/sample-util.c b/src/sample-util.c index 7a3c267a8..ff14548c1 100644 --- a/src/sample-util.c +++ b/src/sample-util.c @@ -4,7 +4,7 @@ #include "sample-util.h" struct pa_sample_spec default_sample_spec = { - .format = SAMPLE_S16NE, + .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 }; @@ -27,18 +27,20 @@ void silence_memory(void *p, size_t length, struct pa_sample_spec *spec) { assert(p && length && spec); switch (spec->format) { - case SAMPLE_U8: + case PA_SAMPLE_U8: c = 127; break; - case SAMPLE_S16LE: - case SAMPLE_S16BE: - case SAMPLE_FLOAT32: + case PA_SAMPLE_S16LE: + case PA_SAMPLE_S16BE: + case PA_SAMPLE_FLOAT32: c = 0; break; - case SAMPLE_ALAW: - case SAMPLE_ULAW: + case PA_SAMPLE_ALAW: + case PA_SAMPLE_ULAW: c = 80; break; + default: + assert(0); } memset(p, c, length); @@ -47,7 +49,7 @@ void silence_memory(void *p, size_t length, struct pa_sample_spec *spec) { size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct pa_sample_spec *spec, uint8_t volume) { unsigned c, d; assert(channels && data && length && spec); - assert(spec->format == SAMPLE_S16NE); + assert(spec->format == PA_SAMPLE_S16NE); for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; diff --git a/src/sample.c b/src/sample.c index 2454630cf..b0d0cdbd0 100644 --- a/src/sample.c +++ b/src/sample.c @@ -7,18 +7,20 @@ size_t pa_sample_size(struct pa_sample_spec *spec) { size_t b = 1; switch (spec->format) { - case SAMPLE_U8: - case SAMPLE_ULAW: - case SAMPLE_ALAW: + case PA_SAMPLE_U8: + case PA_SAMPLE_ULAW: + case PA_SAMPLE_ALAW: b = 1; break; - case SAMPLE_S16LE: - case SAMPLE_S16BE: + case PA_SAMPLE_S16LE: + case PA_SAMPLE_S16BE: b = 2; break; - case SAMPLE_FLOAT32: + case PA_SAMPLE_FLOAT32: b = 4; break; + default: + assert(0); } return b * spec->channels; @@ -35,3 +37,15 @@ uint32_t pa_samples_usec(size_t length, struct pa_sample_spec *spec) { return (uint32_t) (((double) length /pa_sample_size(spec))/spec->rate*1000000); } + +int pa_sample_spec_valid(struct pa_sample_spec *spec) { + assert(spec); + + if (!spec->rate || !spec->channels) + return 0; + + if (spec->format <= 0 || spec->format >= PA_SAMPLE_MAX) + return 0; + + return 1; +} diff --git a/src/sample.h b/src/sample.h index a4a973bf1..697937e05 100644 --- a/src/sample.h +++ b/src/sample.h @@ -5,15 +5,16 @@ #include enum pa_sample_format { - SAMPLE_U8, - SAMPLE_ALAW, - SAMPLE_ULAW, - SAMPLE_S16LE, - SAMPLE_S16BE, - SAMPLE_FLOAT32 + PA_SAMPLE_U8, + PA_SAMPLE_ALAW, + PA_SAMPLE_ULAW, + PA_SAMPLE_S16LE, + PA_SAMPLE_S16BE, + PA_SAMPLE_FLOAT32, + PA_SAMPLE_MAX }; -#define SAMPLE_S16NE SAMPLE_S16LE +#define PA_SAMPLE_S16NE PA_SAMPLE_S16LE struct pa_sample_spec { enum pa_sample_format format; @@ -25,4 +26,6 @@ size_t pa_bytes_per_second(struct pa_sample_spec *spec); size_t pa_sample_size(struct pa_sample_spec *spec); uint32_t pa_samples_usec(size_t length, struct pa_sample_spec *spec); +int pa_sample_spec_valid(struct pa_sample_spec *spec); + #endif diff --git a/src/util.c b/src/util.c index 0383a0ad7..953504218 100644 --- a/src/util.c +++ b/src/util.c @@ -1,9 +1,12 @@ +#include #include #include #include #include #include #include +#include +#include #include "util.h" @@ -60,3 +63,23 @@ void peer_to_string(char *c, size_t l, int fd) { snprintf(c, l, "Unknown client"); } + +int make_secure_dir(const char* dir) { + struct stat st; + + if (mkdir(dir, 0700) < 0) + if (errno != EEXIST) + return -1; + + if (lstat(dir, &st) < 0) + goto fail; + + if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700)) + goto fail; + + return 0; + +fail: + rmdir(dir); + return -1; +} diff --git a/src/util.h b/src/util.h index 830ee2e0c..2a5071989 100644 --- a/src/util.h +++ b/src/util.h @@ -5,4 +5,6 @@ void make_nonblock_fd(int fd); void peer_to_string(char *c, size_t l, int fd); +int make_secure_dir(const char* dir); + #endif From e31bac02573cc3090cac5816bea62a2fea888399 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Jun 2004 18:50:14 +0000 Subject: [PATCH 0040/1514] extended esound protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@41 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/protocol-esound.c | 111 ++++++++++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 25 deletions(-) diff --git a/src/protocol-esound.c b/src/protocol-esound.c index 1668ef550..5db7a13f4 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -35,6 +35,7 @@ struct protocol_esound { struct core *core; struct socket_server *server; struct idxset *connections; + uint32_t sink_index; }; typedef struct proto_handler { @@ -43,6 +44,9 @@ typedef struct proto_handler { const char *description; } esd_proto_handler_info_t; +#define MEMBLOCKQ_LENGTH (10*1204) +#define MEMBLOCKQ_PREBUF (2*1024) + #define BUFSIZE PIPE_BUF static void sink_input_drop_cb(struct sink_input *i, size_t length); @@ -53,42 +57,44 @@ static uint32_t sink_input_get_latency_cb(struct sink_input *i); static int esd_proto_connect(struct connection *c, const void *data, size_t length); static int esd_proto_stream_play(struct connection *c, const void *data, size_t length); static int esd_proto_stream_record(struct connection *c, const void *data, size_t length); +static int esd_proto_get_latency(struct connection *c, const void *data, size_t length); +static int esd_proto_server_info(struct connection *c, const void *data, size_t length); static int do_write(struct connection *c); /* the big map of protocol handler info */ static struct proto_handler proto_map[ESD_PROTO_MAX] = { - { ESD_KEY_LEN + sizeof(int), &esd_proto_connect, "connect" }, - { ESD_KEY_LEN + sizeof(int), NULL, "lock" }, - { ESD_KEY_LEN + sizeof(int), NULL, "unlock" }, + { ESD_KEY_LEN + sizeof(int), esd_proto_connect, "connect" }, + { ESD_KEY_LEN + sizeof(int), NULL, "lock" }, + { ESD_KEY_LEN + sizeof(int), NULL, "unlock" }, - { ESD_NAME_MAX + 2 * sizeof(int), &esd_proto_stream_play, "stream play" }, - { ESD_NAME_MAX + 2 * sizeof(int), &esd_proto_stream_record, "stream rec" }, + { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_play, "stream play" }, + { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream rec" }, { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream mon" }, { ESD_NAME_MAX + 3 * sizeof(int), NULL, "sample cache" }, - { sizeof(int), NULL, "sample free" }, - { sizeof(int), NULL, "sample play" }, - { sizeof(int), NULL, "sample loop" }, - { sizeof(int), NULL, "sample stop" }, - { -1, NULL, "TODO: sample kill" }, + { sizeof(int), NULL, "sample free" }, + { sizeof(int), NULL, "sample play" }, + { sizeof(int), NULL, "sample loop" }, + { sizeof(int), NULL, "sample stop" }, + { -1, NULL, "TODO: sample kill" }, - { ESD_KEY_LEN + sizeof(int), NULL, "standby" }, - { ESD_KEY_LEN + sizeof(int), NULL, "resume" }, + { ESD_KEY_LEN + sizeof(int), NULL, "standby" }, + { ESD_KEY_LEN + sizeof(int), NULL, "resume" }, - { ESD_NAME_MAX, NULL, "sample getid" }, + { ESD_NAME_MAX, NULL, "sample getid" }, { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream filter" }, - { sizeof(int), NULL, "server info" }, - { sizeof(int), NULL, "all info" }, - { -1, NULL, "TODO: subscribe" }, - { -1, NULL, "TODO: unsubscribe" }, + { sizeof(int), esd_proto_server_info, "server info" }, + { sizeof(int), NULL, "all info" }, + { -1, NULL, "TODO: subscribe" }, + { -1, NULL, "TODO: unsubscribe" }, - { 3 * sizeof(int), NULL, "stream pan"}, - { 3 * sizeof(int), NULL, "sample pan" }, - - { sizeof(int), NULL, "standby mode" }, - { 0, NULL, "get latency" } + { 3 * sizeof(int), NULL, "stream pan"}, + { 3 * sizeof(int), NULL, "sample pan" }, + + { sizeof(int), NULL, "standby mode" }, + { 0, esd_proto_get_latency, "get latency" } }; @@ -111,8 +117,18 @@ static void connection_free(struct connection *c) { } static struct sink* get_output_sink(struct protocol_esound *p) { + struct sink *s; assert(p); - return sink_get_default(p->core); + + if (!(s = idxset_get_by_index(p->core->sinks, p->sink_index))) + s = sink_get_default(p->core); + + if (s->index) + p->sink_index = s->index; + else + p->sink_index = IDXSET_INVALID; + + return s; } static void* connection_write(struct connection *c, size_t length) { @@ -191,7 +207,7 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t client_rename(c->client, name); assert(!c->input_memblockq); - c->input_memblockq = memblockq_new(1024*10, pa_sample_size(&ss), 1024*2); + c->input_memblockq = memblockq_new(MEMBLOCKQ_LENGTH, pa_sample_size(&ss), MEMBLOCKQ_PREBUF); assert(c->input_memblockq); assert(!c->sink_input); @@ -210,9 +226,53 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t } static int esd_proto_stream_record(struct connection *c, const void *data, size_t length) { + assert(c && data && length == (sizeof(int)*2+ESD_NAME_MAX)); + assert(0); } +static int esd_proto_get_latency(struct connection *c, const void *data, size_t length) { + struct sink *sink; + int latency, *lag; + assert(c && data && length == 0); + + if (!(sink = get_output_sink(c->protocol))) + latency = 0; + else { + float usec = sink_get_latency(sink); + usec += pa_samples_usec(MEMBLOCKQ_LENGTH, &sink->sample_spec); + latency = (int) (usec*441/10000); + } + + lag = connection_write(c, sizeof(int)); + assert(lag); + *lag = c->swap_byte_order ? swap_endian_32(latency) : latency; + + do_write(c); + return 0; +} + +static int esd_proto_server_info(struct connection *c, const void *data, size_t length) { + int rate = 44100, format = ESD_STEREO|ESD_BITS16; + int *response; + struct sink *sink; + assert(c && data && length == sizeof(int)); + + if ((sink = get_output_sink(c->protocol))) { + rate = sink->sample_spec.rate; + format = (sink->sample_spec.format == PA_SAMPLE_U8) ? ESD_BITS8 : ESD_BITS16; + format |= (sink->sample_spec.channels >= 2) ? ESD_STEREO : ESD_MONO; + } + + response = connection_write(c, sizeof(int)*3); + assert(response); + *(response++) = 0; + *(response++) = c->swap_byte_order ? swap_endian_32(rate) : rate; + *(response++) = c->swap_byte_order ? swap_endian_32(format) : format; + do_write(c); + return 0; +} + /*** client callbacks ***/ static void client_kill_cb(struct client *c) { @@ -426,7 +486,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->sink_input = NULL; c->input_memblockq = NULL; - + idxset_put(c->protocol->connections, c, NULL); } @@ -443,6 +503,7 @@ struct protocol_esound* protocol_esound_new(struct core*core, struct socket_serv p->core = core; p->connections = idxset_new(NULL, NULL); assert(p->connections); + p->sink_index = IDXSET_INVALID; socket_server_set_callback(p->server, on_connection, p); From d571be6f5109ff5b256e4c14f391c916264f0a8e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Jun 2004 20:37:24 +0000 Subject: [PATCH 0041/1514] volume work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@42 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/cli.c | 97 +++++++++++++++++++++++++++++++++++++++++------ src/main.c | 2 +- src/memblock.c | 14 +++++++ src/memblock.h | 2 + src/namereg.c | 18 ++++++++- src/sample-util.c | 54 ++++++++++++++++++++++---- src/sample-util.h | 11 +++++- src/sink.c | 22 ++++++++++- src/sink.h | 2 +- src/sinkinput.c | 5 ++- src/sinkinput.h | 2 +- src/todo | 9 +++-- 12 files changed, 203 insertions(+), 35 deletions(-) diff --git a/src/cli.c b/src/cli.c index 091623510..10e780cde 100644 --- a/src/cli.c +++ b/src/cli.c @@ -13,6 +13,7 @@ #include "sourceoutput.h" #include "tokenizer.h" #include "strbuf.h" +#include "namereg.h" struct cli { struct core *core; @@ -45,20 +46,24 @@ static void cli_command_stat(struct cli *c, struct tokenizer *t); static void cli_command_info(struct cli *c, struct tokenizer *t); static void cli_command_load(struct cli *c, struct tokenizer *t); static void cli_command_unload(struct cli *c, struct tokenizer *t); +static void cli_command_sink_volume(struct cli *c, struct tokenizer *t); +static void cli_command_sink_input_volume(struct cli *c, struct tokenizer *t); static const struct command commands[] = { - { "exit", cli_command_exit, "Terminate the daemon", 1 }, - { "help", cli_command_help, "Show this help", 1 }, - { "modules", cli_command_modules, "List loaded modules", 1 }, - { "sinks", cli_command_sinks, "List loaded sinks", 1 }, - { "sources", cli_command_sources, "List loaded sources", 1 }, - { "clients", cli_command_clients, "List loaded clients", 1 }, - { "sink_inputs", cli_command_sink_inputs, "List sink inputs", 1 }, - { "source_outputs", cli_command_source_outputs, "List source outputs", 1 }, - { "stat", cli_command_stat, "Show memory block statistics", 1 }, - { "info", cli_command_info, "Show comprehensive status", 1 }, - { "load", cli_command_load, "Load a module (given by name and arguments)", 3 }, - { "unload", cli_command_unload, "Unload a module (specified by index)", 2 }, + { "exit", cli_command_exit, "Terminate the daemon", 1 }, + { "help", cli_command_help, "Show this help", 1 }, + { "modules", cli_command_modules, "List loaded modules", 1 }, + { "sinks", cli_command_sinks, "List loaded sinks", 1 }, + { "sources", cli_command_sources, "List loaded sources", 1 }, + { "clients", cli_command_clients, "List loaded clients", 1 }, + { "sink_inputs", cli_command_sink_inputs, "List sink inputs", 1 }, + { "source_outputs", cli_command_source_outputs, "List source outputs", 1 }, + { "stat", cli_command_stat, "Show memory block statistics", 1 }, + { "info", cli_command_info, "Show comprehensive status", 1 }, + { "load", cli_command_load, "Load a module (args: name, arguments)", 3}, + { "unload", cli_command_unload, "Unload a module (args: index)", 2}, + { "sink_volume", cli_command_sink_volume, "Set the volume of a sink (args: sink, volume)", 3}, + { "sink_input_volume", cli_command_sink_input_volume, "Set the volume of a sink input (args: sink input, volume)", 3}, { NULL, NULL, NULL, 0 } }; @@ -277,3 +282,71 @@ static void cli_command_unload(struct cli *c, struct tokenizer *t) { module_unload_request(c->core, m); } + +static void cli_command_sink_volume(struct cli *c, struct tokenizer *t) { + const char *n, *v; + char *x = NULL; + struct sink *sink; + long volume; + + if (!(n = tokenizer_get(t, 1))) { + ioline_puts(c->line, "You need to specify a sink either by its name or its index.\n"); + return; + } + + if (!(v = tokenizer_get(t, 2))) { + ioline_puts(c->line, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); + return; + } + + volume = strtol(v, &x, 0); + if (!x || *x != 0 || volume < 0) { + ioline_puts(c->line, "Failed to parse volume.\n"); + return; + } + + if (!(sink = namereg_get(c->core, n, NAMEREG_SINK))) { + ioline_puts(c->line, "No sink found by this name or index.\n"); + return; + } + + sink->volume = (uint32_t) volume; +} + +static void cli_command_sink_input_volume(struct cli *c, struct tokenizer *t) { + const char *n, *v; + char *x = NULL; + struct sink_input *si; + long index, volume; + + if (!(n = tokenizer_get(t, 1))) { + ioline_puts(c->line, "You need to specify a sink input by its index.\n"); + return; + } + + index = strtol(n, &x, 0); + if (!x || *x != 0 || index < 0) { + ioline_puts(c->line, "Failed to parse index.\n"); + return; + } + + if (!(v = tokenizer_get(t, 2))) { + ioline_puts(c->line, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); + return; + } + + x = NULL; + volume = strtol(v, &x, 0); + if (!x || *x != 0 || volume < 0) { + ioline_puts(c->line, "Failed to parse volume.\n"); + return; + } + + if (!(si = idxset_get_by_index(c->core->sink_inputs, (uint32_t) index))) { + ioline_puts(c->line, "No sink input found with this index.\n"); + return; + } + + si->volume = (uint32_t) volume; +} + diff --git a/src/main.c b/src/main.c index e50321f8d..3512c5bab 100644 --- a/src/main.c +++ b/src/main.c @@ -38,7 +38,7 @@ int main(int argc, char *argv[]) { c = core_new(pa_mainloop_get_api(mainloop)); assert(c); - module_load(c, "module-oss-mmap", "/dev/dsp1"); + module_load(c, "module-oss", "/dev/dsp1"); /* module_load(c, "module-pipe-sink", NULL); module_load(c, "module-simple-protocol-tcp", NULL); module_load(c, "module-simple-protocol-unix", NULL); diff --git a/src/memblock.c b/src/memblock.c index 067243c57..79fe2977b 100644 --- a/src/memblock.c +++ b/src/memblock.c @@ -78,3 +78,17 @@ void memblock_unref_fixed(struct memblock *b) { b->type = MEMBLOCK_DYNAMIC; } +void memchunk_make_writable(struct memchunk *c) { + struct memblock *n; + assert(c && c->memblock && c->memblock->ref >= 1); + + if (c->memblock->ref == 1) + return; + + n = memblock_new(c->length); + assert(n); + memcpy(n->data, c->memblock->data+c->index, c->length); + memblock_unref(c->memblock); + c->memblock = n; + c->index = 0; +} diff --git a/src/memblock.h b/src/memblock.h index cba111016..0c215e85b 100644 --- a/src/memblock.h +++ b/src/memblock.h @@ -29,6 +29,8 @@ void memblock_unref_fixed(struct memblock*b); #define memblock_assert_exclusive(b) assert((b)->ref == 1) +void memchunk_make_writable(struct memchunk *c); + extern unsigned memblock_count, memblock_total; #endif diff --git a/src/namereg.c b/src/namereg.c index b286171db..0af461894 100644 --- a/src/namereg.c +++ b/src/namereg.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -87,11 +88,24 @@ void namereg_unregister(struct core *c, const char *name) { void* namereg_get(struct core *c, const char *name, enum namereg_type type) { struct namereg_entry *e; + uint32_t index; + char *x = NULL; + void *d = NULL; assert(c && name); - if (!(e = hashset_get(c->namereg, name))) + if ((e = hashset_get(c->namereg, name))) if (e->type == e->type) return e->data; - return NULL; + index = (uint32_t) strtol(name, &x, 0); + + if (!x || *x != 0) + return NULL; + + if (type == NAMEREG_SINK) + d = idxset_get_by_index(c->sinks, index); + else if (type == NAMEREG_SOURCE) + d = idxset_get_by_index(c->sources, index); + + return d; } diff --git a/src/sample-util.c b/src/sample-util.c index ff14548c1..09511a3c1 100644 --- a/src/sample-util.c +++ b/src/sample-util.c @@ -1,3 +1,4 @@ +#include #include #include @@ -46,7 +47,7 @@ void silence_memory(void *p, size_t length, struct pa_sample_spec *spec) { memset(p, c, length); } -size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct pa_sample_spec *spec, uint8_t volume) { +size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct pa_sample_spec *spec, uint32_t volume) { unsigned c, d; assert(channels && data && length && spec); assert(spec->format == PA_SAMPLE_S16NE); @@ -59,27 +60,27 @@ size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, si for (c = 0; c < nchannels; c++) { int32_t v; - uint8_t volume = channels[c].volume; + uint32_t volume = channels[c].volume; if (d >= channels[c].chunk.length) return d; - if (volume == 0) + if (volume == VOLUME_MUTE) v = 0; else { v = *((int16_t*) (channels[c].chunk.memblock->data + channels[c].chunk.index + d)); - if (volume != 0xFF) - v = v*volume/0xFF; + if (volume != VOLUME_NORM) + v = (int32_t) ((float)v*volume/VOLUME_NORM); } sum += v; } - if (volume == 0) + if (volume == VOLUME_MUTE) sum = 0; - else if (volume != 0xFF) - sum = sum*volume/0xFF; + else if (volume != VOLUME_NORM) + sum = (int32_t) ((float) sum*volume/VOLUME_NORM); if (sum < -0x8000) sum = -0x8000; if (sum > 0x7FFF) sum = 0x7FFF; @@ -88,3 +89,40 @@ size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, si data += sizeof(int16_t); } } + + +void volume_memchunk(struct memchunk*c, struct pa_sample_spec *spec, uint32_t volume) { + int16_t *d; + size_t n; + assert(c && spec && (c->length % pa_sample_size(spec) == 0)); + assert(spec->format == PA_SAMPLE_S16NE); + memblock_assert_exclusive(c->memblock); + + if (volume == VOLUME_NORM) + return; + + if (volume == VOLUME_MUTE) { + silence_memchunk(c, spec); + return; + } + + for (d = (c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + int32_t t = (int32_t)(*d); + + t *= volume; + t /= VOLUME_NORM; + + if (t < -0x8000) t = -0x8000; + if (t > 0x7FFF) t = 0x7FFF; + + *d = (int16_t) t; + } +} + +uint32_t volume_multiply(uint32_t a, uint32_t b) { + uint64_t p = a; + p *= b; + p /= VOLUME_NORM; + + return (uint32_t) p; +} diff --git a/src/sample-util.h b/src/sample-util.h index 0a3f7c894..2f2539d0a 100644 --- a/src/sample-util.h +++ b/src/sample-util.h @@ -8,16 +8,23 @@ extern struct pa_sample_spec default_sample_spec; +#define VOLUME_NORM (0x100) +#define VOLUME_MUTE (0) + struct memblock *silence_memblock(struct memblock* b, struct pa_sample_spec *spec); void silence_memchunk(struct memchunk *c, struct pa_sample_spec *spec); void silence_memory(void *p, size_t length, struct pa_sample_spec *spec); struct mix_info { struct memchunk chunk; - uint8_t volume; + uint32_t volume; void *userdata; }; -size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct pa_sample_spec *spec, uint8_t volume); +size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct pa_sample_spec *spec, uint32_t volume); + +void volume_memchunk(struct memchunk*c, struct pa_sample_spec *spec, uint32_t volume); + +uint32_t volume_multiply(uint32_t a, uint32_t b); #endif diff --git a/src/sink.c b/src/sink.c index 5ab1a7a78..8a510f1b6 100644 --- a/src/sink.c +++ b/src/sink.c @@ -39,7 +39,7 @@ struct sink* sink_new(struct core *core, const char *name, int fail, const struc assert(s->monitor_source); free(n); - s->volume = 0xFF; + s->volume = VOLUME_NORM; s->notify = NULL; s->get_latency = NULL; @@ -132,6 +132,7 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result) { return -1; if (n == 1) { + uint32_t volume = VOLUME_NORM; struct sink_info *i = info[0].userdata; assert(i); *result = info[0].chunk; @@ -141,6 +142,14 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result) { result->length = length; l = result->length; + + if (s->volume != VOLUME_NORM || info[0].volume != VOLUME_NORM) + volume = volume_multiply(s->volume, info[0].volume); + + if (volume != VOLUME_NORM) { + memchunk_make_writable(result); + volume_memchunk(result, &s->sample_spec, volume); + } } else { result->memblock = memblock_new(length); assert(result->memblock); @@ -164,6 +173,7 @@ int sink_render_into(struct sink*s, struct memchunk *target) { unsigned n; size_t l; assert(s && target && target->length && target->memblock && target->memblock->data); + memblock_assert_exclusive(target->memblock); n = fill_mix_info(s, info, MAX_MIX_CHANNELS); @@ -171,6 +181,7 @@ int sink_render_into(struct sink*s, struct memchunk *target) { return -1; if (n == 1) { + uint32_t volume = VOLUME_NORM; struct sink_info *i = info[0].userdata; assert(i); @@ -180,6 +191,12 @@ int sink_render_into(struct sink*s, struct memchunk *target) { memcpy(target->memblock->data+target->index, info[0].chunk.memblock->data + info[0].chunk.index, l); target->length = l; + + if (s->volume != VOLUME_NORM || info[0].volume != VOLUME_NORM) + volume = volume_multiply(s->volume, info[0].volume); + + if (volume != VOLUME_NORM) + volume_memchunk(target, &s->sample_spec, volume); } else target->length = l = mix_chunks(info, n, target->memblock->data+target->index, target->length, &s->sample_spec, s->volume); @@ -257,8 +274,9 @@ char *sink_list_to_string(struct core *c) { for (sink = idxset_first(c->sinks, &index); sink; sink = idxset_next(c->sinks, &index)) { assert(sink->monitor_source); - strbuf_printf(s, " %c index: %u, name: <%s>, volume: <0x%02x>, latency: <%u usec>, monitor_source: <%u>\n", sink == default_sink ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, sink_get_latency(sink), sink->monitor_source->index); + strbuf_printf(s, " %c index: %u, name: <%s>, volume: <0x%04x>, latency: <%u usec>, monitor_source: <%u>\n", sink == default_sink ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, sink_get_latency(sink), sink->monitor_source->index); } return strbuf_tostring_free(s); } + diff --git a/src/sink.h b/src/sink.h index a5b1ff68e..f251c0b96 100644 --- a/src/sink.h +++ b/src/sink.h @@ -20,7 +20,7 @@ struct sink { struct source *monitor_source; - uint8_t volume; + uint32_t volume; void (*notify)(struct sink*sink); uint32_t (*get_latency)(struct sink *s); diff --git a/src/sinkinput.c b/src/sinkinput.c index b81c9c713..54bc98a61 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -4,6 +4,7 @@ #include "sinkinput.h" #include "strbuf.h" +#include "sample-util.h" struct sink_input* sink_input_new(struct sink *s, struct pa_sample_spec *spec, const char *name) { struct sink_input *i; @@ -22,7 +23,7 @@ struct sink_input* sink_input_new(struct sink *s, struct pa_sample_spec *spec, c i->get_latency = NULL; i->userdata = NULL; - i->volume = 0xFF; + i->volume = VOLUME_NORM; assert(s->core); r = idxset_put(s->core->sink_inputs, i, &i->index); @@ -64,7 +65,7 @@ char *sink_input_list_to_string(struct core *c) { for (i = idxset_first(c->sink_inputs, &index); i; i = idxset_next(c->sink_inputs, &index)) { assert(i->sink); - strbuf_printf(s, " index: %u, name: <%s>, sink: <%u>; volume: <0x%02x>, latency: <%u usec>\n", + strbuf_printf(s, " index: %u, name: <%s>, sink: <%u>; volume: <0x%04x>, latency: <%u usec>\n", i->index, i->name, i->sink->index, diff --git a/src/sinkinput.h b/src/sinkinput.h index f04ecb952..4fe39e2af 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -13,7 +13,7 @@ struct sink_input { char *name; struct sink *sink; struct pa_sample_spec sample_spec; - uint8_t volume; + uint32_t volume; int (*peek) (struct sink_input *i, struct memchunk *chunk); void (*drop) (struct sink_input *i, size_t length); diff --git a/src/todo b/src/todo index 78768be0f..e1cdb9f13 100644 --- a/src/todo +++ b/src/todo @@ -2,16 +2,17 @@ recording sync() function more functions +- esound protocol: + recording +- split oss-dma? - simple library - simple control protocol: kill client/input/output - set_volume - resampling -- volume adjust on single sink input -- fp volume scaling (both < and > 1) -- esound protocol - config parser/cmdline - record testing +- mixing/volume +- kill() routines in all modules -- 0.1 - future cancellation From 961fb4466a9396a11f1a9a6e7d4193409b8949d6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 30 Jun 2004 00:00:52 +0000 Subject: [PATCH 0042/1514] latency esound volume changing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@43 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/esound-spec.h | 1 + src/main.c | 2 +- src/protocol-esound.c | 131 +++++++++++++++++++++++++++++++++++------- src/socket-client.c | 4 ++ src/socket-server.c | 8 +++ src/util.c | 41 +++++++++++++ src/util.h | 3 + 7 files changed, 167 insertions(+), 23 deletions(-) diff --git a/src/esound-spec.h b/src/esound-spec.h index 1c2dc0222..f7a4d3db5 100644 --- a/src/esound-spec.h +++ b/src/esound-spec.h @@ -181,6 +181,7 @@ typedef int esd_client_state_t; /* switch endian order for cross platform playing */ #define swap_endian_32(x) ((x >> 24) | ((x >> 8) & 0xFF00) | (((x & 0xFF00) << 8)) | (x << 24)) +#define maybe_swap_endian_32(c,x) ((c) ? swap_endian_32(x) : x) /* the endian key is transferred in binary, if it's read into int, */ /* and matches ESD_ENDIAN_KEY (ENDN), then the endianness of the */ diff --git a/src/main.c b/src/main.c index 3512c5bab..e50321f8d 100644 --- a/src/main.c +++ b/src/main.c @@ -38,7 +38,7 @@ int main(int argc, char *argv[]) { c = core_new(pa_mainloop_get_api(mainloop)); assert(c); - module_load(c, "module-oss", "/dev/dsp1"); + module_load(c, "module-oss-mmap", "/dev/dsp1"); /* module_load(c, "module-pipe-sink", NULL); module_load(c, "module-simple-protocol-tcp", NULL); module_load(c, "module-simple-protocol-unix", NULL); diff --git a/src/protocol-esound.c b/src/protocol-esound.c index 5db7a13f4..56c852856 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -16,6 +16,7 @@ /* This is heavily based on esound's code */ struct connection { + uint32_t index; struct protocol_esound *protocol; struct iochannel *io; struct client *client; @@ -36,6 +37,7 @@ struct protocol_esound { struct socket_server *server; struct idxset *connections; uint32_t sink_index; + unsigned n_player; }; typedef struct proto_handler { @@ -47,7 +49,7 @@ typedef struct proto_handler { #define MEMBLOCKQ_LENGTH (10*1204) #define MEMBLOCKQ_PREBUF (2*1024) -#define BUFSIZE PIPE_BUF +#define BUFSIZE (1024) static void sink_input_drop_cb(struct sink_input *i, size_t length); static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk); @@ -59,6 +61,8 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t static int esd_proto_stream_record(struct connection *c, const void *data, size_t length); static int esd_proto_get_latency(struct connection *c, const void *data, size_t length); static int esd_proto_server_info(struct connection *c, const void *data, size_t length); +static int esd_proto_all_info(struct connection *c, const void *data, size_t length); +static int esd_proto_stream_pan(struct connection *c, const void *data, size_t length); static int do_write(struct connection *c); @@ -86,11 +90,11 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream filter" }, { sizeof(int), esd_proto_server_info, "server info" }, - { sizeof(int), NULL, "all info" }, + { sizeof(int), esd_proto_all_info, "all info" }, { -1, NULL, "TODO: subscribe" }, { -1, NULL, "TODO: unsubscribe" }, - { 3 * sizeof(int), NULL, "stream pan"}, + { 3 * sizeof(int), esd_proto_stream_pan, "stream pan"}, { 3 * sizeof(int), NULL, "sample pan" }, { sizeof(int), NULL, "standby mode" }, @@ -102,6 +106,9 @@ static void connection_free(struct connection *c) { assert(c); idxset_remove_by_data(c->protocol->connections, c, NULL); + if (c->state == ESD_STREAMING_DATA) + c->protocol->n_player--; + client_free(c->client); if (c->sink_input) @@ -170,9 +177,6 @@ static int esd_proto_connect(struct connection *c, const void *data, size_t leng ok = connection_write(c, sizeof(int)); assert(ok); *ok = 1; - - do_write(c); - return 0; } @@ -183,13 +187,8 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t struct pa_sample_spec ss; assert(length == (sizeof(int)*2+ESD_NAME_MAX)); - format = *(int*)data; - rate = *((int*)data + 1); - - if (c->swap_byte_order) - format = swap_endian_32(format); - if (c->swap_byte_order) - rate = swap_endian_32(rate); + format = maybe_swap_endian_32(c->swap_byte_order, *(int*)data); + rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); ss.rate = rate; ss.channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1; @@ -222,6 +221,8 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t c->state = ESD_STREAMING_DATA; + c->protocol->n_player++; + return 0; } @@ -234,21 +235,19 @@ static int esd_proto_stream_record(struct connection *c, const void *data, size_ static int esd_proto_get_latency(struct connection *c, const void *data, size_t length) { struct sink *sink; int latency, *lag; - assert(c && data && length == 0); + assert(c && !data && length == 0); if (!(sink = get_output_sink(c->protocol))) latency = 0; else { float usec = sink_get_latency(sink); - usec += pa_samples_usec(MEMBLOCKQ_LENGTH, &sink->sample_spec); - latency = (int) (usec*441/10000); + usec += pa_samples_usec(MEMBLOCKQ_LENGTH-BUFSIZE, &sink->sample_spec); + latency = (int) ((usec*44100)/1000000); } lag = connection_write(c, sizeof(int)); assert(lag); *lag = c->swap_byte_order ? swap_endian_32(latency) : latency; - - do_write(c); return 0; } @@ -267,9 +266,94 @@ static int esd_proto_server_info(struct connection *c, const void *data, size_t response = connection_write(c, sizeof(int)*3); assert(response); *(response++) = 0; - *(response++) = c->swap_byte_order ? swap_endian_32(rate) : rate; - *(response++) = c->swap_byte_order ? swap_endian_32(format) : format; - do_write(c); + *(response++) = maybe_swap_endian_32(c->swap_byte_order, rate); + *(response++) = maybe_swap_endian_32(c->swap_byte_order, format); + return 0; +} + +static int esd_proto_all_info(struct connection *c, const void *data, size_t length) { + void *response; + size_t t, k, s; + struct connection *conn; + size_t index = IDXSET_INVALID; + assert(c && data && length == sizeof(int)); + + if (esd_proto_server_info(c, data, length) < 0) + return -1; + + k = sizeof(int)*5+ESD_NAME_MAX; + s = sizeof(int)*6+ESD_NAME_MAX; + response = connection_write(c, (t = s+k*(c->protocol->n_player+1))); + assert(k); + + for (conn = idxset_first(c->protocol->connections, &index); conn; conn = idxset_next(c->protocol->connections, &index)) { + int format = ESD_BITS16 | ESD_STEREO, rate = 44100, volume = 0xFF; + + if (conn->state != ESD_STREAMING_DATA) + continue; + + assert(t >= s+k+k); + + if (conn->sink_input) { + rate = conn->sink_input->sample_spec.rate; + volume = (conn->sink_input->volume*0xFF)/0x100; + format = (conn->sink_input->sample_spec.format == PA_SAMPLE_U8) ? ESD_BITS8 : ESD_BITS16; + format |= (conn->sink_input->sample_spec.channels >= 2) ? ESD_STEREO : ESD_MONO; + } + + /* id */ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (int) conn->index); + response += sizeof(int); + + /* name */ + assert(conn->client); + strncpy(response, conn->client->name, ESD_NAME_MAX); + response += ESD_NAME_MAX; + + /* rate */ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, rate); + response += sizeof(int); + + /* left */ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, volume); + response += sizeof(int); + + /*right*/ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, volume); + response += sizeof(int); + + /*format*/ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, format); + response += sizeof(int); + + t-= k; + } + + assert(t == s+k); + memset(response, 0, t); + return 0; +} + +static int esd_proto_stream_pan(struct connection *c, const void *data, size_t length) { + int *ok; + uint32_t index, volume; + struct connection *conn; + assert(c && data && length == sizeof(int)*3); + + index = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(int*)data); + volume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); + volume = (volume*0x100)/0xFF; + + ok = connection_write(c, sizeof(int)); + assert(ok); + + if ((conn = idxset_get_by_index(c->protocol->connections, index))) { + assert(conn->sink_input); + conn->sink_input->volume = volume; + *ok = 1; + } else + *ok = 0; + return 0; } @@ -380,6 +464,7 @@ static int do_read(struct connection *c) { memblock_unref(chunk.memblock); assert(c->sink_input); sink_notify(c->sink_input->sink); + } else assert(0); @@ -487,7 +572,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->sink_input = NULL; c->input_memblockq = NULL; - idxset_put(c->protocol->connections, c, NULL); + idxset_put(c->protocol->connections, c, &c->index); } /*** entry points ***/ @@ -505,6 +590,8 @@ struct protocol_esound* protocol_esound_new(struct core*core, struct socket_serv assert(p->connections); p->sink_index = IDXSET_INVALID; + p->n_player = 0; + socket_server_set_callback(p->server, on_connection, p); return p; diff --git a/src/socket-client.c b/src/socket-client.c index b10f8ab1a..95c76813e 100644 --- a/src/socket-client.c +++ b/src/socket-client.c @@ -120,6 +120,8 @@ struct socket_client* socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t goto fail; } + make_tcp_socket_low_delay(c->fd); + sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(address); @@ -147,6 +149,8 @@ struct socket_client* socket_client_new_unix(struct pa_mainloop_api *m, const ch goto fail; } + make_socket_low_delay(c->fd); + sa.sun_family = AF_LOCAL; strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); sa.sun_path[sizeof(sa.sun_path) - 1] = 0; diff --git a/src/socket-server.c b/src/socket-server.c index 87fe14768..bd590f3cb 100644 --- a/src/socket-server.c +++ b/src/socket-server.c @@ -11,6 +11,7 @@ #include #include "socket-server.h" +#include "util.h" struct socket_server { int fd; @@ -39,6 +40,9 @@ static void callback(struct pa_mainloop_api *mainloop, void *id, int fd, enum pa return; } + /* There should be a check for socket type here */ + make_tcp_socket_low_delay(fd); + io = iochannel_new(s->mainloop, nfd, nfd); assert(io); s->on_connection(s, io, s->userdata); @@ -78,6 +82,8 @@ struct socket_server* socket_server_new_unix(struct pa_mainloop_api *m, const ch strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); sa.sun_path[sizeof(sa.sun_path) - 1] = 0; + make_socket_low_delay(fd); + if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { fprintf(stderr, "bind(): %s\n", strerror(errno)); goto fail; @@ -117,6 +123,8 @@ struct socket_server* socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) fprintf(stderr, "setsockopt(): %s\n", strerror(errno)); + + make_tcp_socket_low_delay(fd); sa.sin_family = AF_INET; sa.sin_port = htons(port); diff --git a/src/util.c b/src/util.c index 953504218..8f4443360 100644 --- a/src/util.c +++ b/src/util.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "util.h" @@ -83,3 +85,42 @@ fail: rmdir(dir); return -1; } + +int make_socket_low_delay(int fd) { + int ret = 0, buf_size, priority; + + assert(fd >= 0); + + buf_size = 1024; + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)) < 0) + ret = -1; + + buf_size = 1024; + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size)) < 0) + ret = -1; + + priority = 7; + if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0) + ret = -1; + + return ret; +} + +int make_tcp_socket_low_delay(int fd) { + int ret, tos, on; + + assert(fd >= 0); + + ret = make_socket_low_delay(fd); + + on = 1; + if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) + ret = -1; + + tos = IPTOS_LOWDELAY; + if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0) + ret = -1; + + return ret; + +} diff --git a/src/util.h b/src/util.h index 2a5071989..8e9a3796f 100644 --- a/src/util.h +++ b/src/util.h @@ -7,4 +7,7 @@ void peer_to_string(char *c, size_t l, int fd); int make_secure_dir(const char* dir); +int make_socket_low_delay(int fd); +int make_tcp_socket_low_delay(int fd); + #endif From 13b35a2489e7e1d6341effe6e25b8cb8a0a94a02 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 2 Jul 2004 18:47:03 +0000 Subject: [PATCH 0043/1514] add resampler git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@44 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 11 +-- src/endianmacros.h | 41 ++++++++++++ src/iochannel.c | 2 +- src/resampler.c | 162 +++++++++++++++++++++++++++++++++++++++++++++ src/resampler.h | 15 +++++ src/sample.c | 8 +-- src/sample.h | 12 ++-- src/sconv.c | 99 +++++++++++++++++++++++++++ src/sconv.h | 14 ++++ src/sinkinput.c | 1 + src/sinkinput.h | 3 + src/todo | 5 +- 12 files changed, 357 insertions(+), 16 deletions(-) create mode 100644 src/endianmacros.h create mode 100644 src/resampler.c create mode 100644 src/resampler.h create mode 100644 src/sconv.c create mode 100644 src/sconv.h diff --git a/src/Makefile.am b/src/Makefile.am index af4478be6..7982802ea 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -52,12 +52,13 @@ polypaudio_SOURCES = idxset.c idxset.h \ mainloop-api.c mainloop-api.h \ util.c util.h \ hashset.c hashset.h \ - namereg.c namereg.h - -polypaudio_CFLAGS = $(AM_CFLAGS) - + namereg.c namereg.h \ + sconv.c sconv.h \ + resampler.c resampler.h \ + endianmacros.h +polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) -polypaudio_LDADD = $(LIBLTDL) +polypaudio_LDADD = $(LIBLTDL) $(LIBSAMPLERATE_LIBS) polypaudio_LDFLAGS=-export-dynamic libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h diff --git a/src/endianmacros.h b/src/endianmacros.h new file mode 100644 index 000000000..2394b3e89 --- /dev/null +++ b/src/endianmacros.h @@ -0,0 +1,41 @@ +#ifndef fooendianmacroshfoo +#define fooendianmacroshfoo + +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define INT16_SWAP(x) ((int16_t)(((int16_t) x >> 8) | ((int16_t) x << 8))) +#define UINT16_SWAP(x) ((uint16_t)(((uint16_t) x >> 8) | ((uint16_t) x << 8))) +#define INT32_SWAP(x) ((int32_t)(((int32_t) x >> 24) | ((int32_t) x << 24) | (((int32_t) x & 0xFF00) << 16) | (((int32_t) x) >> 16) & 0xFF00)) +#define UINT32_SWAP(x) ((uint32_t)(((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 16) | (((uint32_t) x) >> 16) & 0xFF00)) + +#ifdef WORDS_BIGENDIAN + #define INT16_FROM_LE(x) INT16_SWAP(x) + #define INT16_FROM_BE(x) ((int16_t)(x)) + #define INT16_TO_LE(x) INT16_SWAP(x) + #define INT16_TO_BE(x) ((int16_t)(x)) + + #define UINT16_FROM_LE(x) UINT16_SWAP(x) + #define UINT16_FROM_BE(x) ((uint16_t)(x)) + #define INT32_FROM_LE(x) INT32_SWAP(x) + #define INT32_FROM_BE(x) ((int32_t)(x)) + #define UINT32_FROM_LE(x) UINT32_SWAP(x) + #define UINT32_FROM_BE(x) ((uint32_t)(x)) +#else + #define INT16_FROM_LE(x) ((int16_t)(x)) + #define INT16_FROM_BE(x) INT16_SWAP(x) + #define INT16_TO_LE(x) ((int16_t)(x)) + #define INT16_TO_BE(x) INT16_SWAP(x) + + #define UINT16_FROM_LE(x) ((uint16_t)(x)) + #define UINT16_FROM_BE(x) UINT16_SWAP(x) + #define INT32_FROM_LE(x) ((int32_t)(x)) + #define INT32_FROM_BE(x) INT32_SWAP(x) + #define UINT32_FROM_LE(x) ((uint32_t)(x)) + #define UINT32_FROM_BE(x) UINT32_SWAP(x) +#endif + +#endif diff --git a/src/iochannel.c b/src/iochannel.c index fa55875f2..25d6b05ec 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -1,6 +1,6 @@ +#include #include #include -#include #include #include "iochannel.h" diff --git a/src/resampler.c b/src/resampler.c new file mode 100644 index 000000000..aa37f1acd --- /dev/null +++ b/src/resampler.c @@ -0,0 +1,162 @@ +#include +#include + +#include + +#include "resampler.h" +#include "sconv.h" + +struct resampler { + struct pa_sample_spec i_ss, o_ss; + float* i_buf, *o_buf; + unsigned i_alloc, o_alloc; + size_t i_sz, o_sz; + + int channels; + + convert_to_float32_func_t to_float32_func; + convert_from_float32_func_t from_float32_func; + SRC_STATE *src_state; +}; + +struct resampler* resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b) { + struct resampler *r; + int err; + assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b)); + + if (a->channels != b->channels && a->channels != 1 && b->channels != 1) + goto fail; + + if (a->format == PA_SAMPLE_ALAW || a->format == PA_SAMPLE_ULAW || b->format == PA_SAMPLE_ALAW || b->format == PA_SAMPLE_ULAW) + goto fail; + + r->channels = a->channels; + if (b->channels < r->channels) + r->channels = b->channels; + + r = malloc(sizeof(struct resampler)); + assert(r); + r->i_buf = r->o_buf = NULL; + r->i_alloc = r->o_alloc = 0; + + if (a->rate != b->rate) { + r->src_state = src_new(SRC_SINC_FASTEST, r->channels, &err); + if (err != 0 || !r->src_state) + goto fail; + } else + r->src_state = NULL; + + r->i_ss = *a; + r->o_ss = *b; + + r->i_sz = pa_sample_size(a); + r->o_sz = pa_sample_size(b); + + r->to_float32_func = get_convert_to_float32_function(a->format); + r->from_float32_func = get_convert_from_float32_function(b->format); + + assert(r->to_float32_func && r->from_float32_func); + + return r; + +fail: + if (r) + free(r); + + return NULL; +} + +void resampler_free(struct resampler *r) { + assert(r); + if (r->src_state) + src_delete(r->src_state); + free(r->i_buf); + free(r->o_buf); + free(r); +} + +size_t resampler_request(struct resampler *r, size_t out_length) { + assert(r && (out_length % r->o_sz) == 0); + + return (((out_length / r->o_sz)*r->i_ss.rate)/r->o_ss.rate) * r->i_sz; +} + + +int resampler_run(struct resampler *r, struct memchunk *in, struct memchunk *out) { + unsigned i_nchannels, o_nchannels, ins, ons, eff_ins, eff_ons; + float *cbuf; + size_t in_bytes_used = 0; + assert(r && in && out && in->length && in->memblock); + + /* How many input samples? */ + ins = in->length/r->i_sz; + + /* How much space for output samples? */ + if (r->src_state) + ons = (ins*r->o_ss.rate/r->i_ss.rate)+1024; + else + ons = ins; + + /* How many channels? */ + if (r->i_ss.channels == r->o_ss.channels) { + i_nchannels = o_nchannels = 1; + eff_ins = ins*r->i_ss.channels; /* effective samples */ + eff_ons = ons*r->o_ss.channels; + } else { + i_nchannels = r->i_ss.channels; + o_nchannels = r->o_ss.channels; + eff_ins = ins; + eff_ons = ons; + } + + out->memblock = memblock_new(out->length = (ons*r->o_sz)); + out->index = 0; + assert(out->memblock); + + if (r->i_alloc < eff_ins) + r->i_buf = realloc(r->i_buf, sizeof(float) * (r->i_alloc = eff_ins)); + assert(r->i_buf); + + r->to_float32_func(eff_ins, in->memblock->data+in->index, i_nchannels, r->i_buf); + + if (r->src_state) { + int ret; + SRC_DATA data; + + if (r->o_alloc < eff_ons) + r->o_buf = realloc(r->o_buf, sizeof(float) * (r->o_alloc = eff_ons)); + assert(r->o_buf); + + data.data_in = r->i_buf; + data.input_frames = ins; + + data.data_out = r->o_buf; + data.output_frames = ons; + + data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; + data.end_of_input = 0; + + ret = src_process(r->src_state, &data); + assert(ret == 0); + + in_bytes_used = data.input_frames_used*r->i_sz; + cbuf = r->o_buf; + ons = data.output_frames_gen; + + if (r->i_ss.channels == r->o_ss.channels) + eff_ons = ons*r->o_ss.channels; + else + eff_ons = ons; + } else { + in_bytes_used = ins*r->i_sz; + cbuf = r->i_buf; + } + + assert(in_bytes_used < in->length); + in->index += in_bytes_used; + in->length -= in_bytes_used; + + r->from_float32_func(eff_ons, cbuf, out->memblock->data+out->index, o_nchannels); + out->length = ons*r->o_sz; + return 0; +} diff --git a/src/resampler.h b/src/resampler.h new file mode 100644 index 000000000..000f73ced --- /dev/null +++ b/src/resampler.h @@ -0,0 +1,15 @@ +#ifndef fooresamplerhfoo +#define fooresamplerhfoo + +#include "sample.h" +#include "memblock.h" + +struct resampler; + +struct resampler* resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b); +void resampler_free(struct resampler *r); + +size_t resampler_request(struct resampler *r, size_t out_length); +int resampler_run(struct resampler *r, struct memchunk *in, struct memchunk *out); + +#endif diff --git a/src/sample.c b/src/sample.c index b0d0cdbd0..497358fae 100644 --- a/src/sample.c +++ b/src/sample.c @@ -2,7 +2,7 @@ #include "sample.h" -size_t pa_sample_size(struct pa_sample_spec *spec) { +size_t pa_sample_size(const struct pa_sample_spec *spec) { assert(spec); size_t b = 1; @@ -26,19 +26,19 @@ size_t pa_sample_size(struct pa_sample_spec *spec) { return b * spec->channels; } -size_t pa_bytes_per_second(struct pa_sample_spec *spec) { +size_t pa_bytes_per_second(const struct pa_sample_spec *spec) { assert(spec); return spec->rate*pa_sample_size(spec); } -uint32_t pa_samples_usec(size_t length, struct pa_sample_spec *spec) { +uint32_t pa_samples_usec(size_t length, const struct pa_sample_spec *spec) { assert(spec); return (uint32_t) (((double) length /pa_sample_size(spec))/spec->rate*1000000); } -int pa_sample_spec_valid(struct pa_sample_spec *spec) { +int pa_sample_spec_valid(const struct pa_sample_spec *spec) { assert(spec); if (!spec->rate || !spec->channels) diff --git a/src/sample.h b/src/sample.h index 697937e05..1fd764d7e 100644 --- a/src/sample.h +++ b/src/sample.h @@ -14,7 +14,11 @@ enum pa_sample_format { PA_SAMPLE_MAX }; +#ifdef WORDS_BIGENDIAN +#define PA_SAMPLE_S16NE PA_SAMPLE_S16BE +#else #define PA_SAMPLE_S16NE PA_SAMPLE_S16LE +#endif struct pa_sample_spec { enum pa_sample_format format; @@ -22,10 +26,10 @@ struct pa_sample_spec { uint8_t channels; }; -size_t pa_bytes_per_second(struct pa_sample_spec *spec); -size_t pa_sample_size(struct pa_sample_spec *spec); -uint32_t pa_samples_usec(size_t length, struct pa_sample_spec *spec); +size_t pa_bytes_per_second(const struct pa_sample_spec *spec); +size_t pa_sample_size(const struct pa_sample_spec *spec); +uint32_t pa_samples_usec(size_t length, const struct pa_sample_spec *spec); -int pa_sample_spec_valid(struct pa_sample_spec *spec); +int pa_sample_spec_valid(const struct pa_sample_spec *spec); #endif diff --git a/src/sconv.c b/src/sconv.c new file mode 100644 index 000000000..11438b410 --- /dev/null +++ b/src/sconv.c @@ -0,0 +1,99 @@ +#include +#include +#include "endianmacros.h" +#include "sconv.h" + +static void s16le_to_float32(unsigned n, const void *a, unsigned an, float *b) { + const int16_t *ca = a; + assert(n && a && an && b); + + for (; n > 0; n--) { + unsigned i; + float sum = 0; + + for (i = 0; i < an; i++) { + int16_t s = *(ca++); + sum += ((float) INT16_FROM_LE(s))/0x7FFF; + } + + if (sum > 1) + sum = 1; + if (sum < -1) + sum = -1; + + *(b++) = sum; + } +} + +static void s16le_from_float32(unsigned n, const float *a, void *b, unsigned bn) { + int16_t *cb = b; + assert(n && a && b && bn); + + for (; n > 0; n--) { + unsigned i; + int16_t s; + float v = *(a++); + + if (v > 1) + v = 1; + if (v < -1) + v = -1; + + s = (int16_t) (v * 0x7FFF); + + for (i = 0; i < bn; i++) + *(cb++) = INT16_TO_LE(v); + } +} + +static void float32_to_float32(unsigned n, const void *a, unsigned an, float *b) { + unsigned i; + const float *ca = a; + assert(n && a && an && b); + for (; n > 0; n--) { + float sum = 0; + + for (i = 0; i < an; i++) + sum += *(ca++); + + if (sum > 1) + sum = 1; + if (sum < -1) + sum = -1; + + *(b++) = sum; + } +} + +static void float32_from_float32(unsigned n, const float *a, void *b, unsigned bn) { + unsigned i; + float *cb = b; + assert(n && a && b && bn); + for (; n > 0; n--) { + float v = *(a++); + for (i = 0; i < bn; i++) + *(cb++) = v; + } +} + +convert_to_float32_func_t get_convert_to_float32_function(enum pa_sample_format f) { + switch(f) { + case PA_SAMPLE_S16LE: + return s16le_to_float32; + case PA_SAMPLE_FLOAT32: + return float32_to_float32; + default: + return NULL; + } +} + +convert_from_float32_func_t get_convert_from_float32_function(enum pa_sample_format f) { + switch(f) { + case PA_SAMPLE_S16LE: + return s16le_from_float32; + case PA_SAMPLE_FLOAT32: + return float32_from_float32; + default: + return NULL; + } +} diff --git a/src/sconv.h b/src/sconv.h new file mode 100644 index 000000000..8667d2ae1 --- /dev/null +++ b/src/sconv.h @@ -0,0 +1,14 @@ +#ifndef foosconvhfoo +#define foosconvhfoo + +#include "sample.h" + +typedef void (*convert_to_float32_func_t)(unsigned n, const void *a, unsigned an, float *b); +typedef void (*convert_from_float32_func_t)(unsigned n, const float *a, void *b, unsigned bn); + +convert_to_float32_func_t get_convert_to_float32_function(enum pa_sample_format f); +convert_from_float32_func_t get_convert_from_float32_function(enum pa_sample_format f); + + + +#endif diff --git a/src/sinkinput.c b/src/sinkinput.c index 54bc98a61..dd0504d01 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -88,3 +88,4 @@ uint32_t sink_input_get_latency(struct sink_input *i) { return l; } + diff --git a/src/sinkinput.h b/src/sinkinput.h index 4fe39e2af..e3114d94c 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -33,4 +33,7 @@ void sink_input_kill(struct sink_input *i); uint32_t sink_input_get_latency(struct sink_input *i); char *sink_input_list_to_string(struct core *c); + + + #endif diff --git a/src/todo b/src/todo index e1cdb9f13..0dd999a11 100644 --- a/src/todo +++ b/src/todo @@ -4,20 +4,21 @@ more functions - esound protocol: recording -- split oss-dma? +- move more stuff from module-oss[-dma] to liboss-util - simple library - simple control protocol: kill client/input/output +- kill() routines in all modules - resampling - config parser/cmdline - record testing - mixing/volume -- kill() routines in all modules -- 0.1 - future cancellation - client-ui - clip cache +- autoloading/autounloading drivers: - libao From 741aa44ffc8afd63cd29e5ae46f778dc68340df8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 3 Jul 2004 00:19:17 +0000 Subject: [PATCH 0044/1514] add resampling git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@45 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 ++-- src/iochannel.c | 6 ++-- src/main.c | 12 ++++---- src/memblock.c | 14 --------- src/memblock.h | 7 ----- src/memblockq.c | 41 +++++++++++++++++++++++-- src/memblockq.h | 27 +++++++++++++++-- src/pacat.c | 2 +- src/polyp.c | 2 +- src/protocol-esound.c | 6 ++-- src/protocol-native.c | 4 +-- src/protocol-simple.c | 57 +++++++++++++++++------------------ src/pstream.h | 1 + src/resampler.c | 23 +++++--------- src/resampler.h | 3 +- src/sample-util.h | 1 + src/sample.c | 6 ++++ src/sample.h | 2 +- src/sink.c | 8 ++--- src/sinkinput.c | 70 +++++++++++++++++++++++++++++++++++++++++-- src/sinkinput.h | 10 +++++-- src/source.c | 2 +- src/source.h | 1 + src/sourceoutput.c | 29 +++++++++++++++++- src/sourceoutput.h | 9 ++++-- src/todo | 17 +++++------ 26 files changed, 251 insertions(+), 115 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 7982802ea..ec2344815 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -55,7 +55,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ namereg.c namereg.h \ sconv.c sconv.h \ resampler.c resampler.h \ - endianmacros.h + endianmacros.h \ + memchunk.c memchunk.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(LIBLTDL) $(LIBSAMPLERATE_LIBS) @@ -196,7 +197,8 @@ libpolyp_la_SOURCES = polyp.c polyp.h \ socket-client.c socket-client.h \ packet.c packet.h \ queue.c queue.h \ - dynarray.c dynarray.h + dynarray.c dynarray.h \ + memchunk.c memchunk.h pacat_SOURCES = pacat.c pacat_LDADD = libpolyp.la diff --git a/src/iochannel.c b/src/iochannel.c index 25d6b05ec..a133fdefa 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -15,7 +15,7 @@ struct iochannel { int readable; int writable; - + int no_close; void* input_source, *output_source; @@ -147,8 +147,8 @@ ssize_t iochannel_write(struct iochannel*io, const void*data, size_t l) { ssize_t iochannel_read(struct iochannel*io, void*data, size_t l) { ssize_t r; - assert(io && data && l && io->ifd >= 0); - + assert(io && data && io->ifd >= 0); + if ((r = read(io->ifd, data, l)) >= 0) { io->readable = 0; enable_mainloop_sources(io); diff --git a/src/main.c b/src/main.c index e50321f8d..67109682a 100644 --- a/src/main.c +++ b/src/main.c @@ -38,15 +38,15 @@ int main(int argc, char *argv[]) { c = core_new(pa_mainloop_get_api(mainloop)); assert(c); - module_load(c, "module-oss-mmap", "/dev/dsp1"); -/* module_load(c, "module-pipe-sink", NULL); + module_load(c, "module-oss-mmap", "/dev/dsp"); +/* module_load(c, "module-pipe-sink", NULL);*/ module_load(c, "module-simple-protocol-tcp", NULL); - module_load(c, "module-simple-protocol-unix", NULL); +/* module_load(c, "module-simple-protocol-unix", NULL); module_load(c, "module-cli-protocol-tcp", NULL); module_load(c, "module-cli-protocol-unix", NULL); - module_load(c, "module-native-protocol-tcp", NULL); - module_load(c, "module-native-protocol-unix", NULL);*/ - module_load(c, "module-esound-protocol-tcp", NULL); + module_load(c, "module-native-protocol-tcp", NULL);*/ + module_load(c, "module-native-protocol-unix", NULL); +/* module_load(c, "module-esound-protocol-tcp", NULL);*/ module_load(c, "module-cli", NULL); fprintf(stderr, "main: mainloop entry.\n"); diff --git a/src/memblock.c b/src/memblock.c index 79fe2977b..067243c57 100644 --- a/src/memblock.c +++ b/src/memblock.c @@ -78,17 +78,3 @@ void memblock_unref_fixed(struct memblock *b) { b->type = MEMBLOCK_DYNAMIC; } -void memchunk_make_writable(struct memchunk *c) { - struct memblock *n; - assert(c && c->memblock && c->memblock->ref >= 1); - - if (c->memblock->ref == 1) - return; - - n = memblock_new(c->length); - assert(n); - memcpy(n->data, c->memblock->data+c->index, c->length); - memblock_unref(c->memblock); - c->memblock = n; - c->index = 0; -} diff --git a/src/memblock.h b/src/memblock.h index 0c215e85b..e4a578b80 100644 --- a/src/memblock.h +++ b/src/memblock.h @@ -13,11 +13,6 @@ struct memblock { void *data; }; -struct memchunk { - struct memblock *memblock; - size_t index, length; -}; - struct memblock *memblock_new(size_t length); struct memblock *memblock_new_fixed(void *data, size_t length); struct memblock *memblock_new_dynamic(void *data, size_t length); @@ -29,8 +24,6 @@ void memblock_unref_fixed(struct memblock*b); #define memblock_assert_exclusive(b) assert((b)->ref == 1) -void memchunk_make_writable(struct memchunk *c); - extern unsigned memblock_count, memblock_total; #endif diff --git a/src/memblockq.c b/src/memblockq.c index 9a601c3ae..cab02bed7 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -18,6 +18,7 @@ struct memblockq { size_t total_length, maxlength, base, prebuf; int measure_delay; uint32_t delay; + struct mcalign *mcalign; }; struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { @@ -40,6 +41,8 @@ struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { bq->measure_delay = 0; bq->delay = 0; + + bq->mcalign = NULL; return bq; } @@ -48,6 +51,9 @@ void memblockq_free(struct memblockq* bq) { struct memblock_list *l; assert(bq); + if (bq->mcalign) + mcalign_free(bq->mcalign); + while ((l = bq->blocks)) { bq->blocks = l->next; memblock_unref(l->chunk.memblock); @@ -57,9 +63,9 @@ void memblockq_free(struct memblockq* bq) { free(bq); } -void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta) { +void memblockq_push(struct memblockq* bq, const struct memchunk *chunk, size_t delta) { struct memblock_list *q; - assert(bq && chunk && chunk->memblock && chunk->length); + assert(bq && chunk && chunk->memblock && chunk->length && (chunk->length % bq->base) == 0); q = malloc(sizeof(struct memblock_list)); assert(q); @@ -97,9 +103,14 @@ int memblockq_peek(struct memblockq* bq, struct memchunk *chunk) { *chunk = bq->blocks->chunk; memblock_ref(chunk->memblock); + + if (chunk->memblock->ref != 2) + fprintf(stderr, "block %p with ref %u peeked.\n", chunk->memblock, chunk->memblock->ref); + return 0; } +/* int memblockq_pop(struct memblockq* bq, struct memchunk *chunk) { struct memblock_list *q; @@ -121,6 +132,7 @@ int memblockq_pop(struct memblockq* bq, struct memchunk *chunk) { free(q); return 0; } +*/ static uint32_t age(struct timeval *tv) { assert(tv); @@ -143,7 +155,7 @@ static uint32_t age(struct timeval *tv) { } void memblockq_drop(struct memblockq *bq, size_t length) { - assert(bq); + assert(bq && length && (length % bq->base) == 0); while (length > 0) { size_t l = length; @@ -229,3 +241,26 @@ uint32_t memblockq_missing_to(struct memblockq *bq, size_t qlen) { return qlen - bq->total_length; } + +void memblockq_push_align(struct memblockq* bq, const struct memchunk *chunk, size_t delta) { + struct memchunk rchunk; + assert(bq && chunk && bq->base); + + if (bq->base == 1) { + memblockq_push(bq, chunk, delta); + return; + } + + if (!bq->mcalign) { + bq->mcalign = mcalign_new(bq->base); + assert(bq->mcalign); + } + + mcalign_push(bq->mcalign, chunk); + + while (mcalign_pop(bq->mcalign, &rchunk) >= 0) { + memblockq_push(bq, &rchunk, delta); + memblock_unref(rchunk.memblock); + delta = 0; + } +} diff --git a/src/memblockq.h b/src/memblockq.h index a681ff080..d19aac0e6 100644 --- a/src/memblockq.h +++ b/src/memblockq.h @@ -4,27 +4,48 @@ #include #include "memblock.h" +#include "memchunk.h" struct memblockq; +/* Parameters: the maximum length of the memblock queue, a base value +for all operations (that is, all byte operations shall work on +multiples of this base value) and an amount of bytes to prebuffer +before having memblockq_peek() succeed. */ struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf); -void memblockq_free(struct memblockq* bq); +void memblockq_free(struct memblockq*bq); -void memblockq_push(struct memblockq* bq, struct memchunk *chunk, size_t delta); +/* Push a new memory chunk into the queue. Optionally specify a value for future cancellation. This is currently not implemented, however! */ +void memblockq_push(struct memblockq* bq, const struct memchunk *chunk, size_t delta); -int memblockq_pop(struct memblockq* bq, struct memchunk *chunk); +/* Same as memblockq_push(), however chunks are filtered through a mcalign object, and thus aligned to multiples of base */ +void memblockq_push_align(struct memblockq* bq, const struct memchunk *chunk, size_t delta); + +/* Return a copy of the next memory chunk in the queue. It is not removed from the queue */ int memblockq_peek(struct memblockq* bq, struct memchunk *chunk); + +/* Drop the specified bytes from the queue */ void memblockq_drop(struct memblockq *bq, size_t length); +/* Shorten the memblockq to the specified length by dropping data at the end of the queue */ void memblockq_shorten(struct memblockq *bq, size_t length); + +/* Empty the memblockq */ void memblockq_empty(struct memblockq *bq); +/* Test if the memblockq is currently readable, that is, more data than base */ int memblockq_is_readable(struct memblockq *bq); + +/* Test if the memblockq is currently writable for the specified amount of bytes */ int memblockq_is_writable(struct memblockq *bq, size_t length); +/* The time memory chunks stay in the queue until they are removed completely in usecs */ uint32_t memblockq_get_delay(struct memblockq *bq); + +/* Return the length of the queue in bytes */ uint32_t memblockq_get_length(struct memblockq *bq); +/* Return how many bytes are missing in queue to the specified fill amount */ uint32_t memblockq_missing_to(struct memblockq *bq, size_t qlen); #endif diff --git a/src/pacat.c b/src/pacat.c index fbd1d081e..ccad01890 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -77,7 +77,7 @@ static void context_complete_callback(struct pa_context *c, int success, void *u static const struct pa_sample_spec ss = { .format = PA_SAMPLE_S16NE, .rate = 44100, - .channels = 2 + .channels = 1 }; assert(c && !stream); diff --git a/src/polyp.c b/src/polyp.c index c2d1d8229..32974fc44 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -15,7 +15,7 @@ #define DEFAULT_MAX_LENGTH 20480 #define DEFAULT_PREBUF 4096 #define DEFAULT_TIMEOUT (5*60) -#define DEFAULT_SERVER "/tmp/polypaudio_native" +#define DEFAULT_SERVER "/tmp/polypaudio/native" struct pa_context { char *name; diff --git a/src/protocol-esound.c b/src/protocol-esound.c index 56c852856..12d6f38c1 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -210,7 +210,7 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t assert(c->input_memblockq); assert(!c->sink_input); - c->sink_input = sink_input_new(sink, &ss, name); + c->sink_input = sink_input_new(sink, name, &ss); assert(c->sink_input); c->sink_input->peek = sink_input_peek_cb; @@ -218,7 +218,7 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t c->sink_input->kill = sink_input_kill_cb; c->sink_input->get_latency = sink_input_get_latency_cb; c->sink_input->userdata = c; - + c->state = ESD_STREAMING_DATA; c->protocol->n_player++; @@ -460,7 +460,7 @@ static int do_read(struct connection *c) { chunk.index = 0; assert(c->input_memblockq); - memblockq_push(c->input_memblockq, &chunk, 0); + memblockq_push_align(c->input_memblockq, &chunk, 0); memblock_unref(chunk.memblock); assert(c->sink_input); sink_notify(c->sink_input->sink); diff --git a/src/protocol-native.c b/src/protocol-native.c index 9af438a93..425f4ba46 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -89,7 +89,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct s->connection = c; s->qlength = qlen; - s->sink_input = sink_input_new(sink, ss, name); + s->sink_input = sink_input_new(sink, name, ss); assert(s->sink_input); s->sink_input->peek = sink_input_peek_cb; s->sink_input->drop = sink_input_drop_cb; @@ -323,7 +323,7 @@ static int memblock_callback(struct pstream *p, uint32_t channel, int32_t delta, else stream->requested_bytes -= chunk->length; - memblockq_push(stream->memblockq, chunk, delta); + memblockq_push_align(stream->memblockq, chunk, delta); assert(stream->sink_input); sink_notify(stream->sink_input->sink); diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 80249eef0..a7f3eb7e7 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -25,14 +25,16 @@ struct protocol_simple { struct socket_server*server; struct idxset *connections; enum protocol_simple_mode mode; + struct pa_sample_spec sample_spec; }; #define BUFSIZE PIPE_BUF -static void free_connection(void *data, void *userdata) { - struct connection *c = data; - assert(data); - +static void connection_free(struct connection *c) { + assert(c); + + idxset_remove_by_data(c->protocol->connections, c, NULL); + if (c->sink_input) sink_input_free(c->sink_input); if (c->source_output) @@ -47,13 +49,6 @@ static void free_connection(void *data, void *userdata) { memblockq_free(c->output_memblockq); free(c); } - -static void destroy_connection(struct connection *c) { - assert(c && c->protocol); - idxset_remove_by_data(c->protocol->connections, c, NULL); - free_connection(c, NULL); -} - static int do_read(struct connection *c) { struct memchunk chunk; ssize_t r; @@ -77,7 +72,7 @@ static int do_read(struct connection *c) { chunk.index = 0; assert(c->input_memblockq); - memblockq_push(c->input_memblockq, &chunk, 0); + memblockq_push_align(c->input_memblockq, &chunk, 0); memblock_unref(chunk.memblock); assert(c->sink_input); sink_notify(c->sink_input->sink); @@ -132,12 +127,12 @@ static void sink_input_drop_cb(struct sink_input *i, size_t length) { memblockq_drop(c->input_memblockq, length); if (do_read(c) < 0) - destroy_connection(c); + connection_free(c); } static void sink_input_kill_cb(struct sink_input *i) { assert(i && i->userdata); - destroy_connection((struct connection *) i->userdata); + connection_free((struct connection *) i->userdata); } @@ -149,26 +144,26 @@ static uint32_t sink_input_get_latency_cb(struct sink_input *i) { /*** source_output callbacks ***/ -static void source_output_push_cb(struct source_output *o, struct memchunk *chunk) { +static void source_output_push_cb(struct source_output *o, const struct memchunk *chunk) { struct connection *c = o->userdata; assert(o && c && chunk); memblockq_push(c->output_memblockq, chunk, 0); if (do_write(c) < 0) - destroy_connection(c); + connection_free(c); } static void source_output_kill_cb(struct source_output *o) { assert(o && o->userdata); - destroy_connection((struct connection *) o->userdata); + connection_free((struct connection *) o->userdata); } /*** client callbacks ***/ static void client_kill_cb(struct client *c) { assert(c && c->userdata); - destroy_connection((struct connection *) c->userdata); + connection_free((struct connection *) c->userdata); } /*** iochannel callbacks ***/ @@ -178,7 +173,7 @@ static void io_callback(struct iochannel*io, void *userdata) { assert(io && c && c->io == io); if (do_read(c) < 0 || do_write(c) < 0) - destroy_connection(c); + connection_free(c); } /*** socket_server callbacks */ @@ -212,14 +207,14 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us goto fail; } - c->source_output = source_output_new(source, &DEFAULT_SAMPLE_SPEC, c->client->name); + c->source_output = source_output_new(source, c->client->name, &p->sample_spec); assert(c->source_output); c->source_output->push = source_output_push_cb; c->source_output->kill = source_output_kill_cb; c->source_output->userdata = c; l = 5*pa_bytes_per_second(&DEFAULT_SAMPLE_SPEC); /* 5s */ - c->output_memblockq = memblockq_new(l, pa_sample_size(&DEFAULT_SAMPLE_SPEC), l/2); + c->output_memblockq = memblockq_new(l, pa_sample_size(&p->sample_spec), l/2); } if (p->mode & PROTOCOL_SIMPLE_PLAYBACK) { @@ -231,7 +226,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us goto fail; } - c->sink_input = sink_input_new(sink, &DEFAULT_SAMPLE_SPEC, c->client->name); + c->sink_input = sink_input_new(sink, c->client->name, &p->sample_spec); assert(c->sink_input); c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; @@ -240,7 +235,7 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->sink_input->userdata = c; l = pa_bytes_per_second(&DEFAULT_SAMPLE_SPEC)/2; /* half a second */ - c->input_memblockq = memblockq_new(l, pa_sample_size(&DEFAULT_SAMPLE_SPEC), l/2); + c->input_memblockq = memblockq_new(l, pa_sample_size(&p->sample_spec), l/2); } @@ -249,11 +244,8 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us return; fail: - if (c) { - free_connection(c, NULL); - iochannel_free(c->io); - free(c); - } + if (c) + connection_free(c); } struct protocol_simple* protocol_simple_new(struct core *core, struct socket_server *server, enum protocol_simple_mode mode) { @@ -266,6 +258,7 @@ struct protocol_simple* protocol_simple_new(struct core *core, struct socket_ser p->server = server; p->connections = idxset_new(NULL, NULL); p->mode = mode; + p->sample_spec = DEFAULT_SAMPLE_SPEC; socket_server_set_callback(p->server, on_connection, p); @@ -274,9 +267,15 @@ struct protocol_simple* protocol_simple_new(struct core *core, struct socket_ser void protocol_simple_free(struct protocol_simple *p) { + struct connection *c; assert(p); - idxset_free(p->connections, free_connection, NULL); + while((c = idxset_first(p->connections, NULL))) + connection_free(c); + + idxset_free(p->connections, NULL, NULL); + socket_server_free(p->server); free(p); } + diff --git a/src/pstream.h b/src/pstream.h index d418908e0..a623156aa 100644 --- a/src/pstream.h +++ b/src/pstream.h @@ -7,6 +7,7 @@ #include "memblock.h" #include "iochannel.h" #include "mainloop-api.h" +#include "memchunk.h" struct pstream; diff --git a/src/resampler.c b/src/resampler.c index aa37f1acd..c2d791741 100644 --- a/src/resampler.c +++ b/src/resampler.c @@ -30,12 +30,13 @@ struct resampler* resampler_new(const struct pa_sample_spec *a, const struct pa_ if (a->format == PA_SAMPLE_ALAW || a->format == PA_SAMPLE_ULAW || b->format == PA_SAMPLE_ALAW || b->format == PA_SAMPLE_ULAW) goto fail; + r = malloc(sizeof(struct resampler)); + assert(r); + r->channels = a->channels; if (b->channels < r->channels) r->channels = b->channels; - r = malloc(sizeof(struct resampler)); - assert(r); r->i_buf = r->o_buf = NULL; r->i_alloc = r->o_alloc = 0; @@ -82,11 +83,10 @@ size_t resampler_request(struct resampler *r, size_t out_length) { } -int resampler_run(struct resampler *r, struct memchunk *in, struct memchunk *out) { +void resampler_run(struct resampler *r, const struct memchunk *in, struct memchunk *out) { unsigned i_nchannels, o_nchannels, ins, ons, eff_ins, eff_ons; float *cbuf; - size_t in_bytes_used = 0; - assert(r && in && out && in->length && in->memblock); + assert(r && in && out && in->length && in->memblock && (in->length % r->i_sz) == 0); /* How many input samples? */ ins = in->length/r->i_sz; @@ -138,8 +138,8 @@ int resampler_run(struct resampler *r, struct memchunk *in, struct memchunk *out ret = src_process(r->src_state, &data); assert(ret == 0); - - in_bytes_used = data.input_frames_used*r->i_sz; + assert((unsigned) data.input_frames_used == ins); + cbuf = r->o_buf; ons = data.output_frames_gen; @@ -147,16 +147,9 @@ int resampler_run(struct resampler *r, struct memchunk *in, struct memchunk *out eff_ons = ons*r->o_ss.channels; else eff_ons = ons; - } else { - in_bytes_used = ins*r->i_sz; + } else cbuf = r->i_buf; - } - assert(in_bytes_used < in->length); - in->index += in_bytes_used; - in->length -= in_bytes_used; - r->from_float32_func(eff_ons, cbuf, out->memblock->data+out->index, o_nchannels); out->length = ons*r->o_sz; - return 0; } diff --git a/src/resampler.h b/src/resampler.h index 000f73ced..257ba6628 100644 --- a/src/resampler.h +++ b/src/resampler.h @@ -3,6 +3,7 @@ #include "sample.h" #include "memblock.h" +#include "memchunk.h" struct resampler; @@ -10,6 +11,6 @@ struct resampler* resampler_new(const struct pa_sample_spec *a, const struct pa_ void resampler_free(struct resampler *r); size_t resampler_request(struct resampler *r, size_t out_length); -int resampler_run(struct resampler *r, struct memchunk *in, struct memchunk *out); +void resampler_run(struct resampler *r, const struct memchunk *in, struct memchunk *out); #endif diff --git a/src/sample-util.h b/src/sample-util.h index 2f2539d0a..bc51e5246 100644 --- a/src/sample-util.h +++ b/src/sample-util.h @@ -3,6 +3,7 @@ #include "sample.h" #include "memblock.h" +#include "memchunk.h" #define DEFAULT_SAMPLE_SPEC default_sample_spec diff --git a/src/sample.c b/src/sample.c index 497358fae..706880e46 100644 --- a/src/sample.c +++ b/src/sample.c @@ -49,3 +49,9 @@ int pa_sample_spec_valid(const struct pa_sample_spec *spec) { return 1; } + +int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b) { + assert(a && b); + + return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels); +} diff --git a/src/sample.h b/src/sample.h index 1fd764d7e..fcb0e6e12 100644 --- a/src/sample.h +++ b/src/sample.h @@ -29,7 +29,7 @@ struct pa_sample_spec { size_t pa_bytes_per_second(const struct pa_sample_spec *spec); size_t pa_sample_size(const struct pa_sample_spec *spec); uint32_t pa_samples_usec(size_t length, const struct pa_sample_spec *spec); - int pa_sample_spec_valid(const struct pa_sample_spec *spec); +int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b); #endif diff --git a/src/sink.c b/src/sink.c index 8a510f1b6..2ecb64452 100644 --- a/src/sink.c +++ b/src/sink.c @@ -90,8 +90,7 @@ static unsigned fill_mix_info(struct sink *s, struct mix_info *info, unsigned ma assert(s && info); for (i = idxset_first(s->inputs, &index); maxinfo > 0 && i; i = idxset_next(s->inputs, &index)) { - assert(i->peek); - if (i->peek(i, &info->chunk) < 0) + if (sink_input_peek(i, &info->chunk) < 0) continue; info->volume = i->volume; @@ -115,11 +114,10 @@ static void inputs_drop(struct sink *s, struct mix_info *info, unsigned maxinfo, assert(i && info->chunk.memblock); memblock_unref(info->chunk.memblock); - assert(i->drop); - i->drop(i, length); + sink_input_drop(i, length); } } - + int sink_render(struct sink*s, size_t length, struct memchunk *result) { struct mix_info info[MAX_MIX_CHANNELS]; unsigned n; diff --git a/src/sinkinput.c b/src/sinkinput.c index dd0504d01..c9614a5f6 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -6,11 +6,18 @@ #include "strbuf.h" #include "sample-util.h" -struct sink_input* sink_input_new(struct sink *s, struct pa_sample_spec *spec, const char *name) { +#define CONVERT_BUFFER_LENGTH 4096 + +struct sink_input* sink_input_new(struct sink *s, const char *name, const struct pa_sample_spec *spec) { struct sink_input *i; + struct resampler *resampler = NULL; int r; assert(s && spec); + if (!pa_sample_spec_equal(spec, &s->sample_spec)) + if (!(resampler = resampler_new(spec, &s->sample_spec))) + return NULL; + i = malloc(sizeof(struct sink_input)); assert(i); i->name = name ? strdup(name) : NULL; @@ -25,12 +32,16 @@ struct sink_input* sink_input_new(struct sink *s, struct pa_sample_spec *spec, c i->volume = VOLUME_NORM; + i->resampled_chunk.memblock = NULL; + i->resampled_chunk.index = i->resampled_chunk.length = 0; + i->resampler = resampler; + assert(s->core); r = idxset_put(s->core->sink_inputs, i, &i->index); assert(r == 0 && i->index != IDXSET_INVALID); r = idxset_put(s->inputs, i, NULL); assert(r == 0); - + return i; } @@ -40,6 +51,11 @@ void sink_input_free(struct sink_input* i) { assert(i->sink && i->sink->core); idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL); idxset_remove_by_data(i->sink->inputs, i, NULL); + + if (i->resampled_chunk.memblock) + memblock_unref(i->resampled_chunk.memblock); + if (i->resampler) + resampler_free(i->resampler); free(i->name); free(i); @@ -89,3 +105,53 @@ uint32_t sink_input_get_latency(struct sink_input *i) { return l; } + +int sink_input_peek(struct sink_input *i, struct memchunk *chunk) { + assert(i && chunk && i->peek && i->drop); + + if (!i->resampler) + return i->peek(i, chunk); + + if (!i->resampled_chunk.memblock) { + struct memchunk tchunk; + size_t l; + int ret; + + if ((ret = i->peek(i, &tchunk)) < 0) + return ret; + + l = resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); + if (tchunk.length > l) + tchunk.length = l; + + i->drop(i, tchunk.length); + + resampler_run(i->resampler, &tchunk, &i->resampled_chunk); + memblock_unref(tchunk.memblock); + } + + assert(i->resampled_chunk.memblock && i->resampled_chunk.length); + *chunk = i->resampled_chunk; + memblock_ref(i->resampled_chunk.memblock); + return 0; +} + +void sink_input_drop(struct sink_input *i, size_t length) { + assert(i && length); + + if (!i->resampler) { + i->drop(i, length); + return; + } + + assert(i->resampled_chunk.memblock && i->resampled_chunk.length >= length); + + i->resampled_chunk.index += length; + i->resampled_chunk.length -= length; + + if (!i->resampled_chunk.length) { + memblock_unref(i->resampled_chunk.memblock); + i->resampled_chunk.memblock = NULL; + i->resampled_chunk.index = i->resampled_chunk.length = 0; + } +} diff --git a/src/sinkinput.h b/src/sinkinput.h index e3114d94c..8899a9edb 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -6,6 +6,7 @@ #include "sink.h" #include "sample.h" #include "memblockq.h" +#include "resampler.h" struct sink_input { uint32_t index; @@ -21,9 +22,12 @@ struct sink_input { uint32_t (*get_latency) (struct sink_input *i); void *userdata; + + struct memchunk resampled_chunk; + struct resampler *resampler; }; -struct sink_input* sink_input_new(struct sink *s, struct pa_sample_spec *spec, const char *name); +struct sink_input* sink_input_new(struct sink *s, const char *name, const struct pa_sample_spec *spec); void sink_input_free(struct sink_input* i); /* Code that didn't create the input stream should call this function to @@ -33,7 +37,7 @@ void sink_input_kill(struct sink_input *i); uint32_t sink_input_get_latency(struct sink_input *i); char *sink_input_list_to_string(struct core *c); - - +int sink_input_peek(struct sink_input *i, struct memchunk *chunk); +void sink_input_drop(struct sink_input *i, size_t length); #endif diff --git a/src/source.c b/src/source.c index deacfb3d6..f3eeb5169 100644 --- a/src/source.c +++ b/src/source.c @@ -70,7 +70,7 @@ static int do_post(void *p, uint32_t index, int *del, void*userdata) { struct source_output *o = p; assert(o && o->push && del && chunk); - o->push(o, chunk); + source_output_push(o, chunk); return 0; } diff --git a/src/source.h b/src/source.h index afae5a68b..186271c05 100644 --- a/src/source.h +++ b/src/source.h @@ -8,6 +8,7 @@ struct source; #include "sample.h" #include "idxset.h" #include "memblock.h" +#include "memchunk.h" struct source { uint32_t index; diff --git a/src/sourceoutput.c b/src/sourceoutput.c index e2e1dacc3..e0ed07984 100644 --- a/src/sourceoutput.c +++ b/src/sourceoutput.c @@ -5,11 +5,16 @@ #include "sourceoutput.h" #include "strbuf.h" -struct source_output* source_output_new(struct source *s, struct pa_sample_spec *spec, const char *name) { +struct source_output* source_output_new(struct source *s, const char *name, const struct pa_sample_spec *spec) { struct source_output *o; + struct resampler *resampler = NULL; int r; assert(s && spec); + if (!pa_sample_spec_equal(&s->sample_spec, spec)) + if (!(resampler = resampler_new(&s->sample_spec, spec))) + return NULL; + o = malloc(sizeof(struct source_output)); assert(o); o->name = name ? strdup(name) : NULL; @@ -19,6 +24,7 @@ struct source_output* source_output_new(struct source *s, struct pa_sample_spec o->push = NULL; o->kill = NULL; o->userdata = NULL; + o->resampler = resampler; assert(s->core); r = idxset_put(s->core->source_outputs, o, &o->index); @@ -35,6 +41,9 @@ void source_output_free(struct source_output* o) { assert(o->source && o->source->core); idxset_remove_by_data(o->source->core->source_outputs, o, NULL); idxset_remove_by_data(o->source->outputs, o, NULL); + + if (o->resampler) + resampler_free(o->resampler); free(o->name); free(o); @@ -68,3 +77,21 @@ char *source_output_list_to_string(struct core *c) { return strbuf_tostring_free(s); } + +void source_output_push(struct source_output *o, const struct memchunk *chunk) { + struct memchunk rchunk; + assert(o && chunk && chunk->length && o->push); + + if (!o->resampler) { + o->push(o, chunk); + return; + } + + resampler_run(o->resampler, chunk, &rchunk); + if (!rchunk.length) + return; + + assert(rchunk.memblock); + o->push(o, &rchunk); + memblock_unref(rchunk.memblock); +} diff --git a/src/sourceoutput.h b/src/sourceoutput.h index 50cb9caf5..4db2362de 100644 --- a/src/sourceoutput.h +++ b/src/sourceoutput.h @@ -6,6 +6,7 @@ #include "source.h" #include "sample.h" #include "memblockq.h" +#include "resampler.h" struct source_output { uint32_t index; @@ -14,17 +15,21 @@ struct source_output { struct source *source; struct pa_sample_spec sample_spec; - void (*push)(struct source_output *o, struct memchunk *chunk); + void (*push)(struct source_output *o, const struct memchunk *chunk); void (*kill)(struct source_output* o); + struct resampler* resampler; + void *userdata; }; -struct source_output* source_output_new(struct source *s, struct pa_sample_spec *spec, const char *name); +struct source_output* source_output_new(struct source *s, const char *name, const struct pa_sample_spec *spec); void source_output_free(struct source_output* o); void source_output_kill(struct source_output*o); char *source_output_list_to_string(struct core *c); +void source_output_push(struct source_output *o, const struct memchunk *chunk); + #endif diff --git a/src/todo b/src/todo index 0dd999a11..0f88b0437 100644 --- a/src/todo +++ b/src/todo @@ -1,20 +1,17 @@ +- recording (general, simple, esound, native) +- make it embedable (add pa_ prefix too all identifiers) - native library/protocol: - recording sync() function more functions -- esound protocol: - recording -- move more stuff from module-oss[-dma] to liboss-util - simple library -- simple control protocol: - kill client/input/output - kill() routines in all modules -- resampling +- command line protocol: + kill client/input/output - config parser/cmdline -- record testing -- mixing/volume +- move more stuff from module-oss[-dma] to liboss-util +- svn-id and license in every file --- 0.1 +-- post 0.1 - future cancellation - client-ui - clip cache From 253c540e84a261d37721e9b8a0ed5c5222111adb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 3 Jul 2004 00:19:40 +0000 Subject: [PATCH 0045/1514] forgot to add memchunk.[ch] git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@46 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/memchunk.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ src/memchunk.h | 20 ++++++++ 2 files changed, 144 insertions(+) create mode 100644 src/memchunk.c create mode 100644 src/memchunk.h diff --git a/src/memchunk.c b/src/memchunk.c new file mode 100644 index 000000000..faee45086 --- /dev/null +++ b/src/memchunk.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include + +#include "memchunk.h" + +void memchunk_make_writable(struct memchunk *c) { + struct memblock *n; + assert(c && c->memblock && c->memblock->ref >= 1); + + if (c->memblock->ref == 1) + return; + + n = memblock_new(c->length); + assert(n); + memcpy(n->data, c->memblock->data+c->index, c->length); + memblock_unref(c->memblock); + c->memblock = n; + c->index = 0; +} + + +struct mcalign { + size_t base; + struct memchunk chunk; + uint8_t *buffer; + size_t buffer_fill; +}; + +struct mcalign *mcalign_new(size_t base) { + struct mcalign *m; + assert(base); + + m = malloc(sizeof(struct mcalign)); + assert(m); + m->base = base; + m->chunk.memblock = NULL; + m->chunk.length = m->chunk.index = 0; + m->buffer = NULL; + m->buffer_fill = 0; + return m; +} + +void mcalign_free(struct mcalign *m) { + assert(m); + + free(m->buffer); + + if (m->chunk.memblock) + memblock_unref(m->chunk.memblock); + + free(m); +} + +void mcalign_push(struct mcalign *m, const struct memchunk *c) { + assert(m && c && !m->chunk.memblock && c->memblock && c->length); + + m->chunk = *c; + memblock_ref(m->chunk.memblock); +} + +int mcalign_pop(struct mcalign *m, struct memchunk *c) { + assert(m && c && m->base > m->buffer_fill); + int ret; + + if (!m->chunk.memblock) + return -1; + + if (m->buffer_fill) { + size_t l = m->base - m->buffer_fill; + if (l > m->chunk.length) + l = m->chunk.length; + assert(m->buffer && l); + + memcpy(m->buffer + m->buffer_fill, m->chunk.memblock->data + m->chunk.index, l); + m->buffer_fill += l; + m->chunk.index += l; + m->chunk.length -= l; + + if (m->chunk.length == 0) { + m->chunk.length = m->chunk.index = 0; + memblock_unref(m->chunk.memblock); + m->chunk.memblock = NULL; + } + + assert(m->buffer_fill <= m->base); + if (m->buffer_fill == m->base) { + c->memblock = memblock_new_dynamic(m->buffer, m->base); + assert(c->memblock); + c->index = 0; + c->length = m->base; + m->buffer = NULL; + m->buffer_fill = 0; + + return 0; + } + + return -1; + } + + m->buffer_fill = m->chunk.length % m->base; + + if (m->buffer_fill) { + assert(!m->buffer); + m->buffer = malloc(m->base); + assert(m->buffer); + m->chunk.length -= m->buffer_fill; + memcpy(m->buffer, m->chunk.memblock->data + m->chunk.index + m->chunk.length, m->buffer_fill); + } + + if (m->chunk.length) { + *c = m->chunk; + memblock_ref(c->memblock); + ret = 0; + } else + ret = -1; + + m->chunk.length = m->chunk.index = 0; + memblock_unref(m->chunk.memblock); + m->chunk.memblock = NULL; + + return ret; +} diff --git a/src/memchunk.h b/src/memchunk.h new file mode 100644 index 000000000..d395cf2c3 --- /dev/null +++ b/src/memchunk.h @@ -0,0 +1,20 @@ +#ifndef foomemchunkhfoo +#define foomemchunkhfoo + +#include "memblock.h" + +struct memchunk { + struct memblock *memblock; + size_t index, length; +}; + +void memchunk_make_writable(struct memchunk *c); + +struct mcalign; + +struct mcalign *mcalign_new(size_t base); +void mcalign_free(struct mcalign *m); +void mcalign_push(struct mcalign *m, const struct memchunk *c); +int mcalign_pop(struct mcalign *m, struct memchunk *c); + +#endif From 3ac2437abd693839a7abb78f1e16f82f91712242 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 3 Jul 2004 00:20:06 +0000 Subject: [PATCH 0046/1514] add libsamplerate dependency git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@47 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configure.ac b/configure.ac index 3a14a061f..647bfab7c 100644 --- a/configure.ac +++ b/configure.ac @@ -40,6 +40,12 @@ AC_SUBST(LIBLTDL) AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL +AC_C_BIGENDIAN + +PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) +AC_SUBST(LIBSAMPLERATE_CFLAGS) +AC_SUBST(LIBSAMPLERATE_LIBS) + # If using GCC specifiy some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -Wall -W -Wno-unused-parameter" From a8a5ab1c79c0b6567ecc98343ff1ae944f2285b9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 3 Jul 2004 00:32:31 +0000 Subject: [PATCH 0047/1514] fix minor typo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@48 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/main.c | 2 +- src/module-oss-mmap.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index 67109682a..d10ce0d52 100644 --- a/src/main.c +++ b/src/main.c @@ -38,7 +38,7 @@ int main(int argc, char *argv[]) { c = core_new(pa_mainloop_get_api(mainloop)); assert(c); - module_load(c, "module-oss-mmap", "/dev/dsp"); + module_load(c, "module-oss-mmap", "/dev/dsp1"); /* module_load(c, "module-pipe-sink", NULL);*/ module_load(c, "module-simple-protocol-tcp", NULL); /* module_load(c, "module-simple-protocol-unix", NULL); diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index 3997c4907..3f69e05b7 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -273,7 +273,7 @@ int module_init(struct core *c, struct module*m) { } } - if (m != O_RDONLY) { + if (mode != O_RDONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { fprintf(stderr, "SNDCTL_DSP_GETOSPACE: %s\n", strerror(errno)); goto fail; From e61c2dddb7bc392ab4073d5691870615ada82922 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 3 Jul 2004 23:35:12 +0000 Subject: [PATCH 0048/1514] add pa_ prefix to all identifiers. fix downsampling/resampling add support for U8 samples git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@49 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 45 +++++-- src/cli.c | 248 ++++++++++++++++++------------------- src/cli.h | 8 +- src/client.c | 36 +++--- src/client.h | 16 +-- src/core.c | 44 +++---- src/core.h | 10 +- src/dynarray.c | 20 +-- src/dynarray.h | 14 +-- src/hashset.c | 26 ++-- src/hashset.h | 14 +-- src/idxset.c | 54 ++++---- src/idxset.h | 41 +++--- src/iochannel.c | 38 +++--- src/iochannel.h | 20 +-- src/ioline.c | 42 +++---- src/ioline.h | 10 +- src/main.c | 28 ++--- src/main.h | 2 +- src/mainloop-signal.c | 4 +- src/mainloop.c | 72 +++++------ src/memblock.c | 48 +++---- src/memblock.h | 22 ++-- src/memblockq.c | 74 +++++------ src/memblockq.h | 40 +++--- src/memchunk.c | 36 +++--- src/memchunk.h | 16 +-- src/module-cli.c | 22 ++-- src/module-oss-mmap.c | 52 ++++---- src/module-oss.c | 66 +++++----- src/module-pipe-sink.c | 38 +++--- src/module-protocol-stub.c | 28 ++--- src/module.c | 66 +++++----- src/module.h | 20 +-- src/namereg.c | 36 +++--- src/namereg.h | 14 +-- src/oss-util.c | 2 +- src/oss-util.h | 2 +- src/pacat.c | 4 +- src/packet.c | 22 ++-- src/packet.h | 12 +- src/pdispatch.c | 34 ++--- src/pdispatch.h | 14 +-- src/polyp.c | 116 ++++++++--------- src/protocol-cli.c | 46 +++---- src/protocol-cli.h | 6 +- src/protocol-esound.c | 142 ++++++++++----------- src/protocol-esound.h | 6 +- src/protocol-native.c | 228 +++++++++++++++++----------------- src/protocol-native.h | 6 +- src/protocol-simple.c | 152 +++++++++++------------ src/protocol-simple.h | 14 +-- src/pstream-util.c | 34 ++--- src/pstream-util.h | 6 +- src/pstream.c | 184 +++++++++++++-------------- src/pstream.h | 18 +-- src/queue.c | 14 +-- src/queue.h | 12 +- src/resampler.c | 24 ++-- src/resampler.h | 10 +- src/sample-util.c | 46 +++---- src/sample-util.h | 24 ++-- src/sample.c | 17 ++- src/sample.h | 2 + src/sconv-s16be.c | 9 ++ src/sconv-s16be.h | 7 ++ src/sconv-s16le.c | 57 +++++++++ src/sconv-s16le.h | 7 ++ src/sconv.c | 53 +++++--- src/sconv.h | 10 +- src/sink.c | 144 ++++++++++----------- src/sink.h | 32 ++--- src/sinkinput.c | 75 +++++------ src/sinkinput.h | 30 ++--- src/socket-client.c | 48 +++---- src/socket-client.h | 10 +- src/socket-server.c | 48 ++++--- src/socket-server.h | 12 +- src/source.c | 72 +++++------ src/source.h | 22 ++-- src/sourceoutput.c | 58 ++++----- src/sourceoutput.h | 20 +-- src/strbuf.c | 20 +-- src/strbuf.h | 14 +-- src/tagstruct.c | 34 ++--- src/tagstruct.h | 28 ++--- src/todo | 3 +- src/tokenizer.c | 26 ++-- src/tokenizer.h | 8 +- src/util.c | 12 +- src/util.h | 12 +- 91 files changed, 1795 insertions(+), 1643 deletions(-) create mode 100644 src/sconv-s16be.c create mode 100644 src/sconv-s16be.h create mode 100644 src/sconv-s16le.c create mode 100644 src/sconv-s16le.h diff --git a/src/Makefile.am b/src/Makefile.am index ec2344815..167bc91c5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,17 +20,36 @@ AM_CFLAGS=-ansi -D_GNU_SOURCE bin_PROGRAMS = polypaudio pacat -pkglib_LTLIBRARIES=libiochannel.la libsocket-server.la libsocket-client.la \ - libprotocol-simple.la module-simple-protocol-tcp.la \ - module-pipe-sink.la libpstream.la \ - libpacket.la module-oss.la module-oss-mmap.la liboss-util.la libioline.la \ - libcli.la module-cli.la libtokenizer.la libdynarray.la \ - module-simple-protocol-unix.la module-cli-protocol-tcp.la \ - libprotocol-cli.la module-cli-protocol-unix.la libtagstruct.la \ - libpdispatch.la libprotocol-native.la libpstream-util.la \ - module-native-protocol-tcp.la module-native-protocol-unix.la \ - libpolyp.la libprotocol-esound.la module-esound-protocol-unix.la \ - module-esound-protocol-tcp.la +pkglib_LTLIBRARIES=libiochannel.la \ + libsocket-server.la \ + libsocket-client.la \ + libpstream.la \ + libpacket.la \ + liboss-util.la \ + libioline.la \ + libcli.la \ + libtokenizer.la \ + libdynarray.la \ + libprotocol-cli.la \ + libtagstruct.la \ + libpstream-util.la \ + libpdispatch.la \ + libprotocol-simple.la \ + libprotocol-esound.la \ + libprotocol-native.la \ + module-cli.la \ + module-cli-protocol-tcp.la \ + module-cli-protocol-unix.la \ + module-pipe-sink.la \ + module-oss.la \ + module-oss-mmap.la \ + module-simple-protocol-tcp.la \ + module-simple-protocol-unix.la \ + module-esound-protocol-tcp.la \ + module-esound-protocol-unix.la \ + module-native-protocol-tcp.la \ + module-native-protocol-unix.la \ + libpolyp.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -56,7 +75,9 @@ polypaudio_SOURCES = idxset.c idxset.h \ sconv.c sconv.h \ resampler.c resampler.h \ endianmacros.h \ - memchunk.c memchunk.h + memchunk.c memchunk.h \ + sconv-s16le.c sconv-s16le.h \ + sconv-s16be.c sconv-s16be.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(LIBLTDL) $(LIBSAMPLERATE_LIBS) diff --git a/src/cli.c b/src/cli.c index 10e780cde..659523b1d 100644 --- a/src/cli.c +++ b/src/cli.c @@ -15,94 +15,94 @@ #include "strbuf.h" #include "namereg.h" -struct cli { - struct core *core; - struct ioline *line; +struct pa_cli { + struct pa_core *core; + struct pa_ioline *line; - void (*eof_callback)(struct cli *c, void *userdata); + void (*eof_callback)(struct pa_cli *c, void *userdata); void *userdata; - struct client *client; + struct pa_client *client; }; struct command { const char *name; - void (*proc) (struct cli *cli, struct tokenizer*t); + void (*proc) (struct pa_cli *cli, struct pa_tokenizer*t); const char *help; unsigned args; }; -static void line_callback(struct ioline *line, const char *s, void *userdata); +static void line_callback(struct pa_ioline *line, const char *s, void *userdata); -static void cli_command_exit(struct cli *c, struct tokenizer *t); -static void cli_command_help(struct cli *c, struct tokenizer *t); -static void cli_command_modules(struct cli *c, struct tokenizer *t); -static void cli_command_clients(struct cli *c, struct tokenizer *t); -static void cli_command_sinks(struct cli *c, struct tokenizer *t); -static void cli_command_sources(struct cli *c, struct tokenizer *t); -static void cli_command_sink_inputs(struct cli *c, struct tokenizer *t); -static void cli_command_source_outputs(struct cli *c, struct tokenizer *t); -static void cli_command_stat(struct cli *c, struct tokenizer *t); -static void cli_command_info(struct cli *c, struct tokenizer *t); -static void cli_command_load(struct cli *c, struct tokenizer *t); -static void cli_command_unload(struct cli *c, struct tokenizer *t); -static void cli_command_sink_volume(struct cli *c, struct tokenizer *t); -static void cli_command_sink_input_volume(struct cli *c, struct tokenizer *t); +static void pa_cli_command_exit(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_help(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_modules(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_clients(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_sinks(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_sources(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_sink_inputs(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_source_outputs(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_stat(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_info(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_load(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_unload(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_sink_volume(struct pa_cli *c, struct pa_tokenizer *t); +static void pa_cli_command_sink_input_volume(struct pa_cli *c, struct pa_tokenizer *t); static const struct command commands[] = { - { "exit", cli_command_exit, "Terminate the daemon", 1 }, - { "help", cli_command_help, "Show this help", 1 }, - { "modules", cli_command_modules, "List loaded modules", 1 }, - { "sinks", cli_command_sinks, "List loaded sinks", 1 }, - { "sources", cli_command_sources, "List loaded sources", 1 }, - { "clients", cli_command_clients, "List loaded clients", 1 }, - { "sink_inputs", cli_command_sink_inputs, "List sink inputs", 1 }, - { "source_outputs", cli_command_source_outputs, "List source outputs", 1 }, - { "stat", cli_command_stat, "Show memory block statistics", 1 }, - { "info", cli_command_info, "Show comprehensive status", 1 }, - { "load", cli_command_load, "Load a module (args: name, arguments)", 3}, - { "unload", cli_command_unload, "Unload a module (args: index)", 2}, - { "sink_volume", cli_command_sink_volume, "Set the volume of a sink (args: sink, volume)", 3}, - { "sink_input_volume", cli_command_sink_input_volume, "Set the volume of a sink input (args: sink input, volume)", 3}, + { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, + { "help", pa_cli_command_help, "Show this help", 1 }, + { "modules", pa_cli_command_modules, "List loaded modules", 1 }, + { "sinks", pa_cli_command_sinks, "List loaded sinks", 1 }, + { "sources", pa_cli_command_sources, "List loaded sources", 1 }, + { "clients", pa_cli_command_clients, "List loaded clients", 1 }, + { "sink_inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 }, + { "source_outputs", pa_cli_command_source_outputs, "List source outputs", 1 }, + { "stat", pa_cli_command_stat, "Show memory block statistics", 1 }, + { "info", pa_cli_command_info, "Show comprehensive status", 1 }, + { "load", pa_cli_command_load, "Load a module (args: name, arguments)", 3}, + { "unload", pa_cli_command_unload, "Unload a module (args: index)", 2}, + { "sink_volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: sink, volume)", 3}, + { "sink_input_volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: sink input, volume)", 3}, { NULL, NULL, NULL, 0 } }; static const char prompt[] = ">>> "; -struct cli* cli_new(struct core *core, struct iochannel *io) { +struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io) { char cname[256]; - struct cli *c; + struct pa_cli *c; assert(io); - c = malloc(sizeof(struct cli)); + c = malloc(sizeof(struct pa_cli)); assert(c); c->core = core; - c->line = ioline_new(io); + c->line = pa_ioline_new(io); assert(c->line); c->userdata = NULL; c->eof_callback = NULL; - iochannel_peer_to_string(io, cname, sizeof(cname)); - c->client = client_new(core, "CLI", cname); + pa_iochannel_peer_to_string(io, cname, sizeof(cname)); + c->client = pa_client_new(core, "CLI", cname); assert(c->client); - ioline_set_callback(c->line, line_callback, c); - ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"); - ioline_puts(c->line, prompt); + pa_ioline_set_callback(c->line, line_callback, c); + pa_ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"); + pa_ioline_puts(c->line, prompt); return c; } -void cli_free(struct cli *c) { +void pa_cli_free(struct pa_cli *c) { assert(c); - ioline_free(c->line); - client_free(c->client); + pa_ioline_free(c->line); + pa_client_free(c->client); free(c); } -static void line_callback(struct ioline *line, const char *s, void *userdata) { - struct cli *c = userdata; +static void line_callback(struct pa_ioline *line, const char *s, void *userdata) { + struct pa_cli *c = userdata; const char *cs; const char delimiter[] = " \t\n\r"; assert(line && c); @@ -125,225 +125,225 @@ static void line_callback(struct ioline *line, const char *s, void *userdata) { for (command = commands; command->name; command++) if (strlen(command->name) == l && !strncmp(s, command->name, l)) { - struct tokenizer *t = tokenizer_new(s, command->args); + struct pa_tokenizer *t = pa_tokenizer_new(s, command->args); assert(t); command->proc(c, t); - tokenizer_free(t); + pa_tokenizer_free(t); unknown = 0; break; } if (unknown) - ioline_puts(line, "Unknown command\n"); + pa_ioline_puts(line, "Unknown command\n"); } - ioline_puts(c->line, prompt); + pa_ioline_puts(c->line, prompt); } -void cli_set_eof_callback(struct cli *c, void (*cb)(struct cli*c, void *userdata), void *userdata) { +void pa_cli_set_eof_callback(struct pa_cli *c, void (*cb)(struct pa_cli*c, void *userdata), void *userdata) { assert(c && cb); c->eof_callback = cb; c->userdata = userdata; } -static void cli_command_exit(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_exit(struct pa_cli *c, struct pa_tokenizer *t) { assert(c && c->core && c->core->mainloop && t); c->core->mainloop->quit(c->core->mainloop, 0); } -static void cli_command_help(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_help(struct pa_cli *c, struct pa_tokenizer *t) { const struct command*command; - struct strbuf *strbuf; + struct pa_strbuf *pa_strbuf; char *p; assert(c && t); - strbuf = strbuf_new(); - assert(strbuf); + pa_strbuf = pa_strbuf_new(); + assert(pa_strbuf); - strbuf_puts(strbuf, "Available commands:\n"); + pa_strbuf_puts(pa_strbuf, "Available commands:\n"); for (command = commands; command->name; command++) - strbuf_printf(strbuf, " %-20s %s\n", command->name, command->help); + pa_strbuf_printf(pa_strbuf, " %-20s %s\n", command->name, command->help); - ioline_puts(c->line, p = strbuf_tostring_free(strbuf)); + pa_ioline_puts(c->line, p = pa_strbuf_tostring_free(pa_strbuf)); free(p); } -static void cli_command_modules(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_modules(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); - s = module_list_to_string(c->core); + s = pa_module_list_to_string(c->core); assert(s); - ioline_puts(c->line, s); + pa_ioline_puts(c->line, s); free(s); } -static void cli_command_clients(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_clients(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); - s = client_list_to_string(c->core); + s = pa_client_list_to_string(c->core); assert(s); - ioline_puts(c->line, s); + pa_ioline_puts(c->line, s); free(s); } -static void cli_command_sinks(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_sinks(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); - s = sink_list_to_string(c->core); + s = pa_sink_list_to_string(c->core); assert(s); - ioline_puts(c->line, s); + pa_ioline_puts(c->line, s); free(s); } -static void cli_command_sources(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_sources(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); - s = source_list_to_string(c->core); + s = pa_source_list_to_string(c->core); assert(s); - ioline_puts(c->line, s); + pa_ioline_puts(c->line, s); free(s); } -static void cli_command_sink_inputs(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_sink_inputs(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); - s = sink_input_list_to_string(c->core); + s = pa_sink_input_list_to_string(c->core); assert(s); - ioline_puts(c->line, s); + pa_ioline_puts(c->line, s); free(s); } -static void cli_command_source_outputs(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_source_outputs(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); - s = source_output_list_to_string(c->core); + s = pa_source_output_list_to_string(c->core); assert(s); - ioline_puts(c->line, s); + pa_ioline_puts(c->line, s); free(s); } -static void cli_command_stat(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_stat(struct pa_cli *c, struct pa_tokenizer *t) { char txt[256]; assert(c && t); - snprintf(txt, sizeof(txt), "Memory blocks allocated: %u, total size: %u bytes.\n", memblock_count, memblock_total); - ioline_puts(c->line, txt); + snprintf(txt, sizeof(txt), "Memory blocks allocated: %u, total size: %u bytes.\n", pa_memblock_count, pa_memblock_total); + pa_ioline_puts(c->line, txt); } -static void cli_command_info(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_info(struct pa_cli *c, struct pa_tokenizer *t) { assert(c && t); - cli_command_stat(c, t); - cli_command_modules(c, t); - cli_command_sources(c, t); - cli_command_sinks(c, t); - cli_command_clients(c, t); - cli_command_sink_inputs(c, t); - cli_command_source_outputs(c, t); + pa_cli_command_stat(c, t); + pa_cli_command_modules(c, t); + pa_cli_command_sources(c, t); + pa_cli_command_sinks(c, t); + pa_cli_command_clients(c, t); + pa_cli_command_sink_inputs(c, t); + pa_cli_command_source_outputs(c, t); } -static void cli_command_load(struct cli *c, struct tokenizer *t) { - struct module *m; +static void pa_cli_command_load(struct pa_cli *c, struct pa_tokenizer *t) { + struct pa_module *m; const char *name; char txt[256]; assert(c && t); - if (!(name = tokenizer_get(t, 1))) { - ioline_puts(c->line, "You need to specfiy the module name and optionally arguments.\n"); + if (!(name = pa_tokenizer_get(t, 1))) { + pa_ioline_puts(c->line, "You need to specfiy the module name and optionally arguments.\n"); return; } - if (!(m = module_load(c->core, name, tokenizer_get(t, 2)))) { - ioline_puts(c->line, "Module load failed.\n"); + if (!(m = pa_module_load(c->core, name, pa_tokenizer_get(t, 2)))) { + pa_ioline_puts(c->line, "Module load failed.\n"); return; } snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index); - ioline_puts(c->line, txt); + pa_ioline_puts(c->line, txt); } -static void cli_command_unload(struct cli *c, struct tokenizer *t) { - struct module *m; +static void pa_cli_command_unload(struct pa_cli *c, struct pa_tokenizer *t) { + struct pa_module *m; uint32_t index; const char *i; char *e; assert(c && t); - if (!(i = tokenizer_get(t, 1))) { - ioline_puts(c->line, "You need to specfiy the module index.\n"); + if (!(i = pa_tokenizer_get(t, 1))) { + pa_ioline_puts(c->line, "You need to specfiy the module index.\n"); return; } index = (uint32_t) strtoul(i, &e, 10); - if (*e || !(m = idxset_get_by_index(c->core->modules, index))) { - ioline_puts(c->line, "Invalid module index.\n"); + if (*e || !(m = pa_idxset_get_by_index(c->core->modules, index))) { + pa_ioline_puts(c->line, "Invalid module index.\n"); return; } - module_unload_request(c->core, m); + pa_module_unload_request(c->core, m); } -static void cli_command_sink_volume(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_sink_volume(struct pa_cli *c, struct pa_tokenizer *t) { const char *n, *v; char *x = NULL; - struct sink *sink; + struct pa_sink *sink; long volume; - if (!(n = tokenizer_get(t, 1))) { - ioline_puts(c->line, "You need to specify a sink either by its name or its index.\n"); + if (!(n = pa_tokenizer_get(t, 1))) { + pa_ioline_puts(c->line, "You need to specify a sink either by its name or its index.\n"); return; } - if (!(v = tokenizer_get(t, 2))) { - ioline_puts(c->line, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); + if (!(v = pa_tokenizer_get(t, 2))) { + pa_ioline_puts(c->line, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); return; } volume = strtol(v, &x, 0); if (!x || *x != 0 || volume < 0) { - ioline_puts(c->line, "Failed to parse volume.\n"); + pa_ioline_puts(c->line, "Failed to parse volume.\n"); return; } - if (!(sink = namereg_get(c->core, n, NAMEREG_SINK))) { - ioline_puts(c->line, "No sink found by this name or index.\n"); + if (!(sink = pa_namereg_get(c->core, n, PA_NAMEREG_SINK))) { + pa_ioline_puts(c->line, "No sink found by this name or index.\n"); return; } sink->volume = (uint32_t) volume; } -static void cli_command_sink_input_volume(struct cli *c, struct tokenizer *t) { +static void pa_cli_command_sink_input_volume(struct pa_cli *c, struct pa_tokenizer *t) { const char *n, *v; char *x = NULL; - struct sink_input *si; + struct pa_sink_input *si; long index, volume; - if (!(n = tokenizer_get(t, 1))) { - ioline_puts(c->line, "You need to specify a sink input by its index.\n"); + if (!(n = pa_tokenizer_get(t, 1))) { + pa_ioline_puts(c->line, "You need to specify a sink input by its index.\n"); return; } index = strtol(n, &x, 0); if (!x || *x != 0 || index < 0) { - ioline_puts(c->line, "Failed to parse index.\n"); + pa_ioline_puts(c->line, "Failed to parse index.\n"); return; } - if (!(v = tokenizer_get(t, 2))) { - ioline_puts(c->line, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); + if (!(v = pa_tokenizer_get(t, 2))) { + pa_ioline_puts(c->line, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); return; } x = NULL; volume = strtol(v, &x, 0); if (!x || *x != 0 || volume < 0) { - ioline_puts(c->line, "Failed to parse volume.\n"); + pa_ioline_puts(c->line, "Failed to parse volume.\n"); return; } - if (!(si = idxset_get_by_index(c->core->sink_inputs, (uint32_t) index))) { - ioline_puts(c->line, "No sink input found with this index.\n"); + if (!(si = pa_idxset_get_by_index(c->core->sink_inputs, (uint32_t) index))) { + pa_ioline_puts(c->line, "No sink input found with this index.\n"); return; } diff --git a/src/cli.h b/src/cli.h index f1b74397b..80d9fec7c 100644 --- a/src/cli.h +++ b/src/cli.h @@ -4,11 +4,11 @@ #include "iochannel.h" #include "core.h" -struct cli; +struct pa_cli; -struct cli* cli_new(struct core *core, struct iochannel *io); -void cli_free(struct cli *cli); +struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io); +void pa_cli_free(struct pa_cli *cli); -void cli_set_eof_callback(struct cli *cli, void (*cb)(struct cli*c, void *userdata), void *userdata); +void pa_cli_set_eof_callback(struct pa_cli *cli, void (*cb)(struct pa_cli*c, void *userdata), void *userdata); #endif diff --git a/src/client.c b/src/client.c index 376912832..eb06c52fb 100644 --- a/src/client.c +++ b/src/client.c @@ -6,12 +6,12 @@ #include "client.h" #include "strbuf.h" -struct client *client_new(struct core *core, const char *protocol_name, char *name) { - struct client *c; +struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, char *name) { + struct pa_client *c; int r; assert(core); - c = malloc(sizeof(struct client)); + c = malloc(sizeof(struct pa_client)); assert(c); c->name = name ? strdup(name) : NULL; c->core = core; @@ -20,48 +20,48 @@ struct client *client_new(struct core *core, const char *protocol_name, char *na c->kill = NULL; c->userdata = NULL; - r = idxset_put(core->clients, c, &c->index); - assert(c->index != IDXSET_INVALID && r >= 0); + r = pa_idxset_put(core->clients, c, &c->index); + assert(c->index != PA_IDXSET_INVALID && r >= 0); fprintf(stderr, "client: created %u \"%s\"\n", c->index, c->name); return c; } -void client_free(struct client *c) { +void pa_client_free(struct pa_client *c) { assert(c && c->core); - idxset_remove_by_data(c->core->clients, c, NULL); + pa_idxset_remove_by_data(c->core->clients, c, NULL); fprintf(stderr, "client: freed %u \"%s\"\n", c->index, c->name); free(c->name); free(c); } -void client_kill(struct client *c) { +void pa_client_kill(struct pa_client *c) { assert(c); if (c->kill) c->kill(c); } -char *client_list_to_string(struct core *c) { - struct strbuf *s; - struct client *client; - uint32_t index = IDXSET_INVALID; +char *pa_client_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_client *client; + uint32_t index = PA_IDXSET_INVALID; assert(c); - s = strbuf_new(); + s = pa_strbuf_new(); assert(s); - strbuf_printf(s, "%u client(s).\n", idxset_ncontents(c->clients)); + pa_strbuf_printf(s, "%u client(s).\n", pa_idxset_ncontents(c->clients)); - for (client = idxset_first(c->clients, &index); client; client = idxset_next(c->clients, &index)) - strbuf_printf(s, " index: %u, name: <%s>, protocol_name: <%s>\n", client->index, client->name, client->protocol_name); + for (client = pa_idxset_first(c->clients, &index); client; client = pa_idxset_next(c->clients, &index)) + pa_strbuf_printf(s, " index: %u, name: <%s>, protocol_name: <%s>\n", client->index, client->name, client->protocol_name); - return strbuf_tostring_free(s); + return pa_strbuf_tostring_free(s); } -void client_rename(struct client *c, const char *name) { +void pa_client_rename(struct pa_client *c, const char *name) { assert(c); free(c->name); c->name = name ? strdup(name) : NULL; diff --git a/src/client.h b/src/client.h index 39167ee79..4ca8d96ec 100644 --- a/src/client.h +++ b/src/client.h @@ -3,28 +3,28 @@ #include "core.h" -struct client { +struct pa_client { uint32_t index; char *name; - struct core *core; + struct pa_core *core; const char *protocol_name; - void (*kill)(struct client *c); + void (*kill)(struct pa_client *c); void *userdata; }; -struct client *client_new(struct core *c, const char *protocol_name, char *name); +struct pa_client *pa_client_new(struct pa_core *c, const char *protocol_name, char *name); /* This function should be called only by the code that created the client */ -void client_free(struct client *c); +void pa_client_free(struct pa_client *c); /* Code that didn't create the client should call this function to * request destruction of the client */ -void client_kill(struct client *c); +void pa_client_kill(struct pa_client *c); -char *client_list_to_string(struct core *c); +char *pa_client_list_to_string(struct pa_core *c); -void client_rename(struct client *c, const char *name); +void pa_client_rename(struct pa_client *c, const char *name); #endif diff --git a/src/core.c b/src/core.c index ec38da910..461590377 100644 --- a/src/core.c +++ b/src/core.c @@ -8,19 +8,19 @@ #include "source.h" #include "namereg.h" -struct core* core_new(struct pa_mainloop_api *m) { - struct core* c; - c = malloc(sizeof(struct core)); +struct pa_core* pa_core_new(struct pa_mainloop_api *m) { + struct pa_core* c; + c = malloc(sizeof(struct pa_core)); assert(c); c->mainloop = m; - c->clients = idxset_new(NULL, NULL); - c->sinks = idxset_new(NULL, NULL); - c->sources = idxset_new(NULL, NULL); - c->source_outputs = idxset_new(NULL, NULL); - c->sink_inputs = idxset_new(NULL, NULL); + c->clients = pa_idxset_new(NULL, NULL); + c->sinks = pa_idxset_new(NULL, NULL); + c->sources = pa_idxset_new(NULL, NULL); + c->source_outputs = pa_idxset_new(NULL, NULL); + c->sink_inputs = pa_idxset_new(NULL, NULL); - c->default_source_index = c->default_sink_index = IDXSET_INVALID; + c->default_source_index = c->default_sink_index = PA_IDXSET_INVALID; c->modules = NULL; c->namereg = NULL; @@ -28,28 +28,28 @@ struct core* core_new(struct pa_mainloop_api *m) { return c; }; -void core_free(struct core *c) { +void pa_core_free(struct pa_core *c) { assert(c); - module_unload_all(c); + pa_module_unload_all(c); assert(!c->modules); - assert(idxset_isempty(c->clients)); - idxset_free(c->clients, NULL, NULL); + assert(pa_idxset_isempty(c->clients)); + pa_idxset_free(c->clients, NULL, NULL); - assert(idxset_isempty(c->sinks)); - idxset_free(c->sinks, NULL, NULL); + assert(pa_idxset_isempty(c->sinks)); + pa_idxset_free(c->sinks, NULL, NULL); - assert(idxset_isempty(c->sources)); - idxset_free(c->sources, NULL, NULL); + assert(pa_idxset_isempty(c->sources)); + pa_idxset_free(c->sources, NULL, NULL); - assert(idxset_isempty(c->source_outputs)); - idxset_free(c->source_outputs, NULL, NULL); + assert(pa_idxset_isempty(c->source_outputs)); + pa_idxset_free(c->source_outputs, NULL, NULL); - assert(idxset_isempty(c->sink_inputs)); - idxset_free(c->sink_inputs, NULL, NULL); + assert(pa_idxset_isempty(c->sink_inputs)); + pa_idxset_free(c->sink_inputs, NULL, NULL); - namereg_free(c); + pa_namereg_free(c); free(c); }; diff --git a/src/core.h b/src/core.h index 289bec85d..8eb638d94 100644 --- a/src/core.h +++ b/src/core.h @@ -5,17 +5,17 @@ #include "hashset.h" #include "mainloop-api.h" -struct core { +struct pa_core { struct pa_mainloop_api *mainloop; - struct idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules; + struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules; - struct hashset *namereg; + struct pa_hashset *namereg; uint32_t default_source_index, default_sink_index; }; -struct core* core_new(struct pa_mainloop_api *m); -void core_free(struct core*c); +struct pa_core* pa_core_new(struct pa_mainloop_api *m); +void pa_core_free(struct pa_core*c); #endif diff --git a/src/dynarray.c b/src/dynarray.c index 9a7060eec..7f34eef82 100644 --- a/src/dynarray.c +++ b/src/dynarray.c @@ -4,14 +4,14 @@ #include "dynarray.h" -struct dynarray { +struct pa_dynarray { void **data; unsigned n_allocated, n_entries; }; -struct dynarray* dynarray_new(void) { - struct dynarray *a; - a = malloc(sizeof(struct dynarray)); +struct pa_dynarray* pa_dynarray_new(void) { + struct pa_dynarray *a; + a = malloc(sizeof(struct pa_dynarray)); assert(a); a->data = NULL; a->n_entries = 0; @@ -19,7 +19,7 @@ struct dynarray* dynarray_new(void) { return a; } -void dynarray_free(struct dynarray* a, void (*func)(void *p, void *userdata), void *userdata) { +void pa_dynarray_free(struct pa_dynarray* a, void (*func)(void *p, void *userdata), void *userdata) { unsigned i; assert(a); @@ -32,7 +32,7 @@ void dynarray_free(struct dynarray* a, void (*func)(void *p, void *userdata), vo free(a); } -void dynarray_put(struct dynarray*a, unsigned i, void *p) { +void pa_dynarray_put(struct pa_dynarray*a, unsigned i, void *p) { assert(a); if (i >= a->n_allocated) { @@ -53,13 +53,13 @@ void dynarray_put(struct dynarray*a, unsigned i, void *p) { a->n_entries = i+1; } -unsigned dynarray_append(struct dynarray*a, void *p) { +unsigned pa_dynarray_append(struct pa_dynarray*a, void *p) { unsigned i = a->n_entries; - dynarray_put(a, i, p); + pa_dynarray_put(a, i, p); return i; } -void *dynarray_get(struct dynarray*a, unsigned i) { +void *pa_dynarray_get(struct pa_dynarray*a, unsigned i) { assert(a); if (i >= a->n_allocated) return NULL; @@ -67,7 +67,7 @@ void *dynarray_get(struct dynarray*a, unsigned i) { return a->data[i]; } -unsigned dynarray_ncontents(struct dynarray*a) { +unsigned pa_dynarray_ncontents(struct pa_dynarray*a) { assert(a); return a->n_entries; } diff --git a/src/dynarray.h b/src/dynarray.h index 9ab861ce4..fab3841df 100644 --- a/src/dynarray.h +++ b/src/dynarray.h @@ -1,16 +1,16 @@ #ifndef foodynarrayhfoo #define foodynarrayhfoo -struct dynarray; +struct pa_dynarray; -struct dynarray* dynarray_new(void); -void dynarray_free(struct dynarray* a, void (*func)(void *p, void *userdata), void *userdata); +struct pa_dynarray* pa_dynarray_new(void); +void pa_dynarray_free(struct pa_dynarray* a, void (*func)(void *p, void *userdata), void *userdata); -void dynarray_put(struct dynarray*a, unsigned i, void *p); -unsigned dynarray_append(struct dynarray*a, void *p); +void pa_dynarray_put(struct pa_dynarray*a, unsigned i, void *p); +unsigned pa_dynarray_append(struct pa_dynarray*a, void *p); -void *dynarray_get(struct dynarray*a, unsigned i); +void *pa_dynarray_get(struct pa_dynarray*a, unsigned i); -unsigned dynarray_ncontents(struct dynarray*a); +unsigned pa_dynarray_ncontents(struct pa_dynarray*a); #endif diff --git a/src/hashset.c b/src/hashset.c index 298650d5d..4815a13a4 100644 --- a/src/hashset.c +++ b/src/hashset.c @@ -12,7 +12,7 @@ struct hashset_entry { void *value; }; -struct hashset { +struct pa_hashset { unsigned size; struct hashset_entry **data; struct hashset_entry *first_entry; @@ -22,21 +22,21 @@ struct hashset { int (*compare_func) (const void*a, const void*b); }; -struct hashset *hashset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { - struct hashset *h; - h = malloc(sizeof(struct hashset)); +struct pa_hashset *pa_hashset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { + struct pa_hashset *h; + h = malloc(sizeof(struct pa_hashset)); assert(h); h->data = malloc(sizeof(struct hashset_entry*)*(h->size = 1023)); assert(h->data); memset(h->data, 0, sizeof(struct hashset_entry*)*(h->size = 1023)); h->first_entry = NULL; h->n_entries = 0; - h->hash_func = hash_func ? hash_func : idxset_trivial_hash_func; - h->compare_func = compare_func ? compare_func : idxset_trivial_compare_func; + h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; + h->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; return h; } -static void remove(struct hashset *h, struct hashset_entry *e) { +static void remove(struct pa_hashset *h, struct hashset_entry *e) { assert(e); if (e->next) @@ -57,7 +57,7 @@ static void remove(struct hashset *h, struct hashset_entry *e) { h->n_entries--; } -void hashset_free(struct hashset*h, void (*free_func)(void *p, void *userdata), void *userdata) { +void pa_hashset_free(struct pa_hashset*h, void (*free_func)(void *p, void *userdata), void *userdata) { assert(h); while (h->first_entry) { @@ -70,7 +70,7 @@ void hashset_free(struct hashset*h, void (*free_func)(void *p, void *userdata), free(h); } -static struct hashset_entry *get(struct hashset *h, unsigned hash, const void *key) { +static struct hashset_entry *get(struct pa_hashset *h, unsigned hash, const void *key) { struct hashset_entry *e; for (e = h->data[hash]; e; e = e->bucket_next) @@ -80,7 +80,7 @@ static struct hashset_entry *get(struct hashset *h, unsigned hash, const void *k return NULL; } -int hashset_put(struct hashset *h, const void *key, void *value) { +int pa_hashset_put(struct pa_hashset *h, const void *key, void *value) { struct hashset_entry *e; unsigned hash; assert(h && key); @@ -113,7 +113,7 @@ int hashset_put(struct hashset *h, const void *key, void *value) { return 0; } -void* hashset_get(struct hashset *h, const void *key) { +void* pa_hashset_get(struct pa_hashset *h, const void *key) { unsigned hash; struct hashset_entry *e; assert(h && key); @@ -126,7 +126,7 @@ void* hashset_get(struct hashset *h, const void *key) { return e->value; } -int hashset_remove(struct hashset *h, const void *key) { +int pa_hashset_remove(struct pa_hashset *h, const void *key) { struct hashset_entry *e; unsigned hash; assert(h && key); @@ -140,6 +140,6 @@ int hashset_remove(struct hashset *h, const void *key) { return 0; } -unsigned hashset_ncontents(struct hashset *h) { +unsigned pa_hashset_ncontents(struct pa_hashset *h) { return h->n_entries; } diff --git a/src/hashset.h b/src/hashset.h index 7e035c02e..a6ece8bf7 100644 --- a/src/hashset.h +++ b/src/hashset.h @@ -1,16 +1,16 @@ #ifndef foohashsethfoo #define foohashsethfoo -struct hashset; +struct pa_hashset; -struct hashset *hashset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); -void hashset_free(struct hashset*, void (*free_func)(void *p, void *userdata), void *userdata); +struct pa_hashset *pa_hashset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); +void pa_hashset_free(struct pa_hashset*, void (*free_func)(void *p, void *userdata), void *userdata); -int hashset_put(struct hashset *h, const void *key, void *value); -void* hashset_get(struct hashset *h, const void *key); +int pa_hashset_put(struct pa_hashset *h, const void *key, void *value); +void* pa_hashset_get(struct pa_hashset *h, const void *key); -int hashset_remove(struct hashset *h, const void *key); +int pa_hashset_remove(struct pa_hashset *h, const void *key); -unsigned hashset_ncontents(struct hashset *h); +unsigned pa_hashset_ncontents(struct pa_hashset *h); #endif diff --git a/src/idxset.c b/src/idxset.c index 090bfc726..ba740250a 100644 --- a/src/idxset.c +++ b/src/idxset.c @@ -14,7 +14,7 @@ struct idxset_entry { struct idxset_entry* iterate_prev, *iterate_next; }; -struct idxset { +struct pa_idxset { unsigned (*hash_func) (const void *p); int (*compare_func)(const void *a, const void *b); @@ -23,7 +23,7 @@ struct idxset { uint32_t index, start_index, array_size; }; -unsigned idxset_string_hash_func(const void *p) { +unsigned pa_idxset_string_hash_func(const void *p) { unsigned hash = 0; const char *c; @@ -33,25 +33,25 @@ unsigned idxset_string_hash_func(const void *p) { return hash; } -int idxset_string_compare_func(const void *a, const void *b) { +int pa_idxset_string_compare_func(const void *a, const void *b) { return strcmp(a, b); } -unsigned idxset_trivial_hash_func(const void *p) { +unsigned pa_idxset_trivial_hash_func(const void *p) { return (unsigned) p; } -int idxset_trivial_compare_func(const void *a, const void *b) { +int pa_idxset_trivial_compare_func(const void *a, const void *b) { return a != b; } -struct idxset* idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { - struct idxset *s; +struct pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { + struct pa_idxset *s; - s = malloc(sizeof(struct idxset)); + s = malloc(sizeof(struct pa_idxset)); assert(s); - s->hash_func = hash_func ? hash_func : idxset_trivial_hash_func; - s->compare_func = compare_func ? compare_func : idxset_trivial_compare_func; + s->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; + s->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; s->hash_table_size = 1023; s->hash_table = malloc(sizeof(struct idxset_entry*)*s->hash_table_size); assert(s->hash_table); @@ -67,7 +67,7 @@ struct idxset* idxset_new(unsigned (*hash_func) (const void *p), int (*compare_f return s; } -void idxset_free(struct idxset *s, void (*free_func) (void *p, void *userdata), void *userdata) { +void pa_idxset_free(struct pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata) { assert(s); if (free_func) { @@ -86,7 +86,7 @@ void idxset_free(struct idxset *s, void (*free_func) (void *p, void *userdata), free(s); } -static struct idxset_entry* hash_scan(struct idxset *s, struct idxset_entry* e, void *p) { +static struct idxset_entry* hash_scan(struct pa_idxset *s, struct idxset_entry* e, void *p) { assert(p); assert(s->compare_func); @@ -97,7 +97,7 @@ static struct idxset_entry* hash_scan(struct idxset *s, struct idxset_entry* e, return NULL; } -static void extend_array(struct idxset *s, uint32_t index) { +static void extend_array(struct pa_idxset *s, uint32_t index) { uint32_t i, j, l; struct idxset_entry** n; assert(index >= s->start_index); @@ -124,7 +124,7 @@ static void extend_array(struct idxset *s, uint32_t index) { s->start_index += i; } -static struct idxset_entry** array_index(struct idxset*s, uint32_t index) { +static struct idxset_entry** array_index(struct pa_idxset*s, uint32_t index) { if (index >= s->start_index + s->array_size) return NULL; @@ -134,7 +134,7 @@ static struct idxset_entry** array_index(struct idxset*s, uint32_t index) { return s->array + (index - s->start_index); } -int idxset_put(struct idxset*s, void *p, uint32_t *index) { +int pa_idxset_put(struct pa_idxset*s, void *p, uint32_t *index) { unsigned h; struct idxset_entry *e, **a; assert(s && p); @@ -191,7 +191,7 @@ int idxset_put(struct idxset*s, void *p, uint32_t *index) { return 0; } -void* idxset_get_by_index(struct idxset*s, uint32_t index) { +void* pa_idxset_get_by_index(struct pa_idxset*s, uint32_t index) { struct idxset_entry **a; assert(s); @@ -204,7 +204,7 @@ void* idxset_get_by_index(struct idxset*s, uint32_t index) { return (*a)->data; } -void* idxset_get_by_data(struct idxset*s, void *p, uint32_t *index) { +void* pa_idxset_get_by_data(struct pa_idxset*s, void *p, uint32_t *index) { unsigned h; struct idxset_entry *e; assert(s && p); @@ -222,7 +222,7 @@ void* idxset_get_by_data(struct idxset*s, void *p, uint32_t *index) { return e->data; } -static void remove_entry(struct idxset *s, struct idxset_entry *e) { +static void remove_entry(struct pa_idxset *s, struct idxset_entry *e) { struct idxset_entry **a; assert(s && e); @@ -257,7 +257,7 @@ static void remove_entry(struct idxset *s, struct idxset_entry *e) { s->n_entries--; } -void* idxset_remove_by_index(struct idxset*s, uint32_t index) { +void* pa_idxset_remove_by_index(struct pa_idxset*s, uint32_t index) { struct idxset_entry **a; void *data; @@ -272,7 +272,7 @@ void* idxset_remove_by_index(struct idxset*s, uint32_t index) { return data; } -void* idxset_remove_by_data(struct idxset*s, void *data, uint32_t *index) { +void* pa_idxset_remove_by_data(struct pa_idxset*s, void *data, uint32_t *index) { struct idxset_entry *e; unsigned h; @@ -292,7 +292,7 @@ void* idxset_remove_by_data(struct idxset*s, void *data, uint32_t *index) { return data; } -void* idxset_rrobin(struct idxset *s, uint32_t *index) { +void* pa_idxset_rrobin(struct pa_idxset *s, uint32_t *index) { struct idxset_entry **a, *e = NULL; assert(s && index); @@ -309,7 +309,7 @@ void* idxset_rrobin(struct idxset *s, uint32_t *index) { return e->data; } -void* idxset_first(struct idxset *s, uint32_t *index) { +void* pa_idxset_first(struct pa_idxset *s, uint32_t *index) { assert(s); if (!s->iterate_list_head) @@ -320,7 +320,7 @@ void* idxset_first(struct idxset *s, uint32_t *index) { return s->iterate_list_head->data; } -void *idxset_next(struct idxset *s, uint32_t *index) { +void *pa_idxset_next(struct pa_idxset *s, uint32_t *index) { struct idxset_entry **a, *e = NULL; assert(s && index); @@ -331,13 +331,13 @@ void *idxset_next(struct idxset *s, uint32_t *index) { *index = e->index; return e->data; } else { - *index = IDXSET_INVALID; + *index = PA_IDXSET_INVALID; return NULL; } } -int idxset_foreach(struct idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata) { +int pa_idxset_foreach(struct pa_idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata) { struct idxset_entry *e; assert(s && func); @@ -360,12 +360,12 @@ int idxset_foreach(struct idxset*s, int (*func)(void *p, uint32_t index, int *de return 0; } -unsigned idxset_ncontents(struct idxset*s) { +unsigned pa_idxset_ncontents(struct pa_idxset*s) { assert(s); return s->n_entries; } -int idxset_isempty(struct idxset *s) { +int pa_idxset_isempty(struct pa_idxset *s) { assert(s); return s->n_entries == 0; } diff --git a/src/idxset.h b/src/idxset.h index 615039776..be5bb2948 100644 --- a/src/idxset.h +++ b/src/idxset.h @@ -3,41 +3,40 @@ #include -#define IDXSET_INVALID ((uint32_t) -1) +#define PA_IDXSET_INVALID ((uint32_t) -1) -unsigned idxset_trivial_hash_func(const void *p); -int idxset_trivial_compare_func(const void *a, const void *b); +unsigned pa_idxset_trivial_hash_func(const void *p); +int pa_idxset_trivial_compare_func(const void *a, const void *b); -unsigned idxset_string_hash_func(const void *p); -int idxset_string_compare_func(const void *a, const void *b); +unsigned pa_idxset_string_hash_func(const void *p); +int pa_idxset_string_compare_func(const void *a, const void *b); -struct idxset; +struct pa_idxset; -struct idxset* idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); -void idxset_free(struct idxset *s, void (*free_func) (void *p, void *userdata), void *userdata); +struct pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); +void pa_idxset_free(struct pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata); -int idxset_put(struct idxset*s, void *p, uint32_t *index); +int pa_idxset_put(struct pa_idxset*s, void *p, uint32_t *index); -void* idxset_get_by_index(struct idxset*s, uint32_t index); -void* idxset_get_by_data(struct idxset*s, void *p, uint32_t *index); +void* pa_idxset_get_by_index(struct pa_idxset*s, uint32_t index); +void* pa_idxset_get_by_data(struct pa_idxset*s, void *p, uint32_t *index); -void* idxset_remove_by_index(struct idxset*s, uint32_t index); -void* idxset_remove_by_data(struct idxset*s, void *p, uint32_t *index); +void* pa_idxset_remove_by_index(struct pa_idxset*s, uint32_t index); +void* pa_idxset_remove_by_data(struct pa_idxset*s, void *p, uint32_t *index); /* This may be used to iterate through all entries. When called with an invalid index value it returns the first entry, otherwise the next following. The function is best called with *index = - IDXSET_VALID first. */ -void* idxset_rrobin(struct idxset *s, uint32_t *index); + PA_IDXSET_VALID first. */ +void* pa_idxset_rrobin(struct pa_idxset *s, uint32_t *index); /* Return the oldest entry in the idxset */ -void* idxset_first(struct idxset *s, uint32_t *index); -void *idxset_next(struct idxset *s, uint32_t *index); +void* pa_idxset_first(struct pa_idxset *s, uint32_t *index); +void *pa_idxset_next(struct pa_idxset *s, uint32_t *index); -int idxset_foreach(struct idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata); - -unsigned idxset_ncontents(struct idxset*s); -int idxset_isempty(struct idxset *s); +int pa_idxset_foreach(struct pa_idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata); +unsigned pa_idxset_ncontents(struct pa_idxset*s); +int pa_idxset_isempty(struct pa_idxset *s); #endif diff --git a/src/iochannel.c b/src/iochannel.c index a133fdefa..afa94cff1 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -6,11 +6,11 @@ #include "iochannel.h" #include "util.h" -struct iochannel { +struct pa_iochannel { int ifd, ofd; struct pa_mainloop_api* mainloop; - void (*callback)(struct iochannel*io, void *userdata); + void (*callback)(struct pa_iochannel*io, void *userdata); void*userdata; int readable; @@ -21,7 +21,7 @@ struct iochannel { void* input_source, *output_source; }; -static void enable_mainloop_sources(struct iochannel *io) { +static void enable_mainloop_sources(struct pa_iochannel *io) { assert(io); if (io->input_source == io->output_source) { @@ -43,7 +43,7 @@ static void enable_mainloop_sources(struct iochannel *io) { } static void callback(struct pa_mainloop_api* m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { - struct iochannel *io = userdata; + struct pa_iochannel *io = userdata; int changed = 0; assert(m && fd >= 0 && events && userdata); @@ -67,11 +67,11 @@ static void callback(struct pa_mainloop_api* m, void *id, int fd, enum pa_mainlo } } -struct iochannel* iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd) { - struct iochannel *io; +struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd) { + struct pa_iochannel *io; assert(m && (ifd >= 0 || ofd >= 0)); - io = malloc(sizeof(struct iochannel)); + io = malloc(sizeof(struct pa_iochannel)); io->ifd = ifd; io->ofd = ofd; io->mainloop = m; @@ -84,18 +84,18 @@ struct iochannel* iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd) { if (ifd == ofd) { assert(ifd >= 0); - make_nonblock_fd(io->ifd); + pa_make_nonblock_fd(io->ifd); io->input_source = io->output_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_BOTH, callback, io); } else { if (ifd >= 0) { - make_nonblock_fd(io->ifd); + pa_make_nonblock_fd(io->ifd); io->input_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, io); } else io->input_source = NULL; if (ofd >= 0) { - make_nonblock_fd(io->ofd); + pa_make_nonblock_fd(io->ofd); io->output_source = m->source_io(m, ofd, PA_MAINLOOP_API_IO_EVENT_OUTPUT, callback, io); } else io->output_source = NULL; @@ -104,7 +104,7 @@ struct iochannel* iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd) { return io; } -void iochannel_free(struct iochannel*io) { +void pa_iochannel_free(struct pa_iochannel*io) { assert(io); if (!io->no_close) { @@ -122,17 +122,17 @@ void iochannel_free(struct iochannel*io) { free(io); } -int iochannel_is_readable(struct iochannel*io) { +int pa_iochannel_is_readable(struct pa_iochannel*io) { assert(io); return io->readable; } -int iochannel_is_writable(struct iochannel*io) { +int pa_iochannel_is_writable(struct pa_iochannel*io) { assert(io); return io->writable; } -ssize_t iochannel_write(struct iochannel*io, const void*data, size_t l) { +ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) { ssize_t r; assert(io && data && l && io->ofd >= 0); @@ -144,7 +144,7 @@ ssize_t iochannel_write(struct iochannel*io, const void*data, size_t l) { return r; } -ssize_t iochannel_read(struct iochannel*io, void*data, size_t l) { +ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l) { ssize_t r; assert(io && data && io->ifd >= 0); @@ -157,18 +157,18 @@ ssize_t iochannel_read(struct iochannel*io, void*data, size_t l) { return r; } -void iochannel_set_callback(struct iochannel*io, void (*callback)(struct iochannel*io, void *userdata), void *userdata) { +void pa_iochannel_set_callback(struct pa_iochannel*io, void (*callback)(struct pa_iochannel*io, void *userdata), void *userdata) { assert(io); io->callback = callback; io->userdata = userdata; } -void iochannel_set_noclose(struct iochannel*io, int b) { +void pa_iochannel_set_noclose(struct pa_iochannel*io, int b) { assert(io); io->no_close = b; } -void iochannel_peer_to_string(struct iochannel*io, char*s, size_t l) { +void pa_iochannel_peer_to_string(struct pa_iochannel*io, char*s, size_t l) { assert(io && s && l); - peer_to_string(s, l, io->ifd); + pa_peer_to_string(s, l, io->ifd); } diff --git a/src/iochannel.h b/src/iochannel.h index b0465a194..c550af19a 100644 --- a/src/iochannel.h +++ b/src/iochannel.h @@ -4,21 +4,21 @@ #include #include "mainloop-api.h" -struct iochannel; +struct pa_iochannel; -struct iochannel* iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd); -void iochannel_free(struct iochannel*io); +struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd); +void pa_iochannel_free(struct pa_iochannel*io); -ssize_t iochannel_write(struct iochannel*io, const void*data, size_t l); -ssize_t iochannel_read(struct iochannel*io, void*data, size_t l); +ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l); +ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l); -int iochannel_is_readable(struct iochannel*io); -int iochannel_is_writable(struct iochannel*io); +int pa_iochannel_is_readable(struct pa_iochannel*io); +int pa_iochannel_is_writable(struct pa_iochannel*io); -void iochannel_set_noclose(struct iochannel*io, int b); +void pa_iochannel_set_noclose(struct pa_iochannel*io, int b); -void iochannel_set_callback(struct iochannel*io, void (*callback)(struct iochannel*io, void *userdata), void *userdata); +void pa_iochannel_set_callback(struct pa_iochannel*io, void (*callback)(struct pa_iochannel*io, void *userdata), void *userdata); -void iochannel_peer_to_string(struct iochannel*io, char*s, size_t l); +void pa_iochannel_peer_to_string(struct pa_iochannel*io, char*s, size_t l); #endif diff --git a/src/ioline.c b/src/ioline.c index ada9cee07..ab7cb5176 100644 --- a/src/ioline.c +++ b/src/ioline.c @@ -9,8 +9,8 @@ #define BUFFER_LIMIT (64*1024) #define READ_SIZE (1024) -struct ioline { - struct iochannel *io; +struct pa_ioline { + struct pa_iochannel *io; int dead; char *wbuf; @@ -19,18 +19,18 @@ struct ioline { char *rbuf; size_t rbuf_length, rbuf_index, rbuf_valid_length; - void (*callback)(struct ioline*io, const char *s, void *userdata); + void (*callback)(struct pa_ioline*io, const char *s, void *userdata); void *userdata; }; -static void io_callback(struct iochannel*io, void *userdata); -static int do_write(struct ioline *l); +static void io_callback(struct pa_iochannel*io, void *userdata); +static int do_write(struct pa_ioline *l); -struct ioline* ioline_new(struct iochannel *io) { - struct ioline *l; +struct pa_ioline* pa_ioline_new(struct pa_iochannel *io) { + struct pa_ioline *l; assert(io); - l = malloc(sizeof(struct ioline)); + l = malloc(sizeof(struct pa_ioline)); assert(l); l->io = io; l->dead = 0; @@ -44,20 +44,20 @@ struct ioline* ioline_new(struct iochannel *io) { l->callback = NULL; l->userdata = NULL; - iochannel_set_callback(io, io_callback, l); + pa_iochannel_set_callback(io, io_callback, l); return l; } -void ioline_free(struct ioline *l) { +void pa_ioline_free(struct pa_ioline *l) { assert(l); - iochannel_free(l->io); + pa_iochannel_free(l->io); free(l->wbuf); free(l->rbuf); free(l); } -void ioline_puts(struct ioline *l, const char *c) { +void pa_ioline_puts(struct pa_ioline *l, const char *c) { size_t len; assert(l && c); @@ -89,19 +89,19 @@ void ioline_puts(struct ioline *l, const char *c) { do_write(l); } -void ioline_set_callback(struct ioline*l, void (*callback)(struct ioline*io, const char *s, void *userdata), void *userdata) { +void pa_ioline_set_callback(struct pa_ioline*l, void (*callback)(struct pa_ioline*io, const char *s, void *userdata), void *userdata) { assert(l && callback); l->callback = callback; l->userdata = userdata; } -static int do_read(struct ioline *l) { +static int do_read(struct pa_ioline *l) { ssize_t r; size_t m, len; char *e; assert(l); - if (!iochannel_is_readable(l->io)) + if (!pa_iochannel_is_readable(l->io)) return 0; len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; @@ -129,7 +129,7 @@ static int do_read(struct ioline *l) { len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; - if ((r = iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) + if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) return -1; e = memchr(l->rbuf+l->rbuf_index+l->rbuf_valid_length, '\n', r); @@ -159,14 +159,14 @@ static int do_read(struct ioline *l) { return 0; } -static int do_write(struct ioline *l) { +static int do_write(struct pa_ioline *l) { ssize_t r; assert(l); - if (!l->wbuf_valid_length || !iochannel_is_writable(l->io)) + if (!l->wbuf_valid_length || !pa_iochannel_is_writable(l->io)) return 0; - if ((r = iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) + if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) return -1; l->wbuf_valid_length -= r; @@ -176,8 +176,8 @@ static int do_write(struct ioline *l) { return 0; } -static void io_callback(struct iochannel*io, void *userdata) { - struct ioline *l = userdata; +static void io_callback(struct pa_iochannel*io, void *userdata) { + struct pa_ioline *l = userdata; assert(io && l); if (!l->dead && do_read(l) < 0) diff --git a/src/ioline.h b/src/ioline.h index 55d7d4a38..ba7cf5406 100644 --- a/src/ioline.h +++ b/src/ioline.h @@ -3,12 +3,12 @@ #include "iochannel.h" -struct ioline; +struct pa_ioline; -struct ioline* ioline_new(struct iochannel *io); -void ioline_free(struct ioline *l); +struct pa_ioline* pa_ioline_new(struct pa_iochannel *io); +void pa_ioline_free(struct pa_ioline *l); -void ioline_puts(struct ioline *s, const char *c); -void ioline_set_callback(struct ioline*io, void (*callback)(struct ioline*io, const char *s, void *userdata), void *userdata); +void pa_ioline_puts(struct pa_ioline *s, const char *c); +void pa_ioline_set_callback(struct pa_ioline*io, void (*callback)(struct pa_ioline*io, const char *s, void *userdata), void *userdata); #endif diff --git a/src/main.c b/src/main.c index d10ce0d52..be75b3726 100644 --- a/src/main.c +++ b/src/main.c @@ -10,7 +10,7 @@ #include "module.h" #include "mainloop-signal.h" -int stdin_inuse = 0, stdout_inuse = 0; +int pa_stdin_inuse = 0, pa_stdout_inuse = 0; static struct pa_mainloop *mainloop; @@ -21,7 +21,7 @@ static void signal_callback(void *id, int sig, void *userdata) { } int main(int argc, char *argv[]) { - struct core *c; + struct pa_core *c; int r, retval = 0; r = lt_dlinit(); @@ -35,26 +35,26 @@ int main(int argc, char *argv[]) { pa_signal_register(SIGINT, signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - c = core_new(pa_mainloop_get_api(mainloop)); + c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); - module_load(c, "module-oss-mmap", "/dev/dsp1"); -/* module_load(c, "module-pipe-sink", NULL);*/ - module_load(c, "module-simple-protocol-tcp", NULL); -/* module_load(c, "module-simple-protocol-unix", NULL); - module_load(c, "module-cli-protocol-tcp", NULL); - module_load(c, "module-cli-protocol-unix", NULL); - module_load(c, "module-native-protocol-tcp", NULL);*/ - module_load(c, "module-native-protocol-unix", NULL); -/* module_load(c, "module-esound-protocol-tcp", NULL);*/ - module_load(c, "module-cli", NULL); + pa_module_load(c, "module-oss", "/dev/dsp"); +/* pa_module_load(c, "module-pipe-sink", NULL);*/ + pa_module_load(c, "module-simple-protocol-tcp", NULL); +/* pa_module_load(c, "module-simple-protocol-unix", NULL); + pa_module_load(c, "module-cli-protocol-tcp", NULL); + pa_module_load(c, "module-cli-protocol-unix", NULL); + pa_module_load(c, "module-native-protocol-tcp", NULL);*/ + pa_module_load(c, "module-native-protocol-unix", NULL); +/* pa_module_load(c, "module-esound-protocol-tcp", NULL);*/ + pa_module_load(c, "module-cli", NULL); fprintf(stderr, "main: mainloop entry.\n"); if (pa_mainloop_run(mainloop, &retval) < 0) retval = 1; fprintf(stderr, "main: mainloop exit.\n"); - core_free(c); + pa_core_free(c); pa_signal_done(); pa_mainloop_free(mainloop); diff --git a/src/main.h b/src/main.h index c4bea049a..35333bbf9 100644 --- a/src/main.h +++ b/src/main.h @@ -1,6 +1,6 @@ #ifndef foomainhfoo #define foomainhfoo -extern int stdin_inuse, stdout_inuse; +extern int pa_stdin_inuse, pa_stdout_inuse; #endif diff --git a/src/mainloop-signal.c b/src/mainloop-signal.c index dcc72f69c..3c55f8000 100644 --- a/src/mainloop-signal.c +++ b/src/mainloop-signal.c @@ -63,8 +63,8 @@ int pa_signal_init(struct pa_mainloop_api *a) { return -1; } - make_nonblock_fd(signal_pipe[0]); - make_nonblock_fd(signal_pipe[1]); + pa_make_nonblock_fd(signal_pipe[0]); + pa_make_nonblock_fd(signal_pipe[1]); api = a; mainloop_source = api->source_io(api, signal_pipe[0], PA_MAINLOOP_API_IO_EVENT_INPUT, callback, NULL); diff --git a/src/mainloop.c b/src/mainloop.c index 8629add2d..4755cc8fb 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -46,7 +46,7 @@ struct mainloop_source_time { }; struct pa_mainloop { - struct idxset *io_sources, *fixed_sources, *idle_sources, *time_sources; + struct pa_idxset *io_sources, *fixed_sources, *idle_sources, *time_sources; int io_sources_scan_dead, fixed_sources_scan_dead, idle_sources_scan_dead, time_sources_scan_dead; struct pollfd *pollfds; @@ -65,10 +65,10 @@ struct pa_mainloop *pa_mainloop_new(void) { m = malloc(sizeof(struct pa_mainloop)); assert(m); - m->io_sources = idxset_new(NULL, NULL); - m->fixed_sources = idxset_new(NULL, NULL); - m->idle_sources = idxset_new(NULL, NULL); - m->time_sources = idxset_new(NULL, NULL); + m->io_sources = pa_idxset_new(NULL, NULL); + m->fixed_sources = pa_idxset_new(NULL, NULL); + m->idle_sources = pa_idxset_new(NULL, NULL); + m->time_sources = pa_idxset_new(NULL, NULL); assert(m->io_sources && m->fixed_sources && m->idle_sources && m->time_sources); @@ -100,15 +100,15 @@ static int foreach(void *p, uint32_t index, int *del, void*userdata) { void pa_mainloop_free(struct pa_mainloop* m) { int all = 1; assert(m); - idxset_foreach(m->io_sources, foreach, &all); - idxset_foreach(m->fixed_sources, foreach, &all); - idxset_foreach(m->idle_sources, foreach, &all); - idxset_foreach(m->time_sources, foreach, &all); + pa_idxset_foreach(m->io_sources, foreach, &all); + pa_idxset_foreach(m->fixed_sources, foreach, &all); + pa_idxset_foreach(m->idle_sources, foreach, &all); + pa_idxset_foreach(m->time_sources, foreach, &all); - idxset_free(m->io_sources, NULL, NULL); - idxset_free(m->fixed_sources, NULL, NULL); - idxset_free(m->idle_sources, NULL, NULL); - idxset_free(m->time_sources, NULL, NULL); + pa_idxset_free(m->io_sources, NULL, NULL); + pa_idxset_free(m->fixed_sources, NULL, NULL); + pa_idxset_free(m->idle_sources, NULL, NULL); + pa_idxset_free(m->time_sources, NULL, NULL); free(m->pollfds); free(m); @@ -118,22 +118,22 @@ static void scan_dead(struct pa_mainloop *m) { int all = 0; assert(m); if (m->io_sources_scan_dead) - idxset_foreach(m->io_sources, foreach, &all); + pa_idxset_foreach(m->io_sources, foreach, &all); if (m->fixed_sources_scan_dead) - idxset_foreach(m->fixed_sources, foreach, &all); + pa_idxset_foreach(m->fixed_sources, foreach, &all); if (m->idle_sources_scan_dead) - idxset_foreach(m->idle_sources, foreach, &all); + pa_idxset_foreach(m->idle_sources, foreach, &all); if (m->time_sources_scan_dead) - idxset_foreach(m->time_sources, foreach, &all); + pa_idxset_foreach(m->time_sources, foreach, &all); } static void rebuild_pollfds(struct pa_mainloop *m) { struct mainloop_source_io*s; struct pollfd *p; - uint32_t index = IDXSET_INVALID; + uint32_t index = PA_IDXSET_INVALID; unsigned l; - l = idxset_ncontents(m->io_sources); + l = pa_idxset_ncontents(m->io_sources); if (m->max_pollfds < l) { m->pollfds = realloc(m->pollfds, sizeof(struct pollfd)*l); m->max_pollfds = l; @@ -141,7 +141,7 @@ static void rebuild_pollfds(struct pa_mainloop *m) { m->n_pollfds = 0; p = m->pollfds; - for (s = idxset_first(m->io_sources, &index); s; s = idxset_next(m->io_sources, &index)) { + for (s = pa_idxset_first(m->io_sources, &index); s; s = pa_idxset_next(m->io_sources, &index)) { if (s->header.dead) { s->pollfd = NULL; continue; @@ -158,10 +158,10 @@ static void rebuild_pollfds(struct pa_mainloop *m) { } static void dispatch_pollfds(struct pa_mainloop *m) { - uint32_t index = IDXSET_INVALID; + uint32_t index = PA_IDXSET_INVALID; struct mainloop_source_io *s; - for (s = idxset_first(m->io_sources, &index); s; s = idxset_next(m->io_sources, &index)) { + for (s = pa_idxset_first(m->io_sources, &index); s; s = pa_idxset_next(m->io_sources, &index)) { if (s->header.dead || !s->pollfd || !s->pollfd->revents) continue; @@ -173,11 +173,11 @@ static void dispatch_pollfds(struct pa_mainloop *m) { } } -static void run_fixed_or_idle(struct pa_mainloop *m, struct idxset *i) { - uint32_t index = IDXSET_INVALID; +static void run_fixed_or_idle(struct pa_mainloop *m, struct pa_idxset *i) { + uint32_t index = PA_IDXSET_INVALID; struct mainloop_source_fixed_or_idle *s; - for (s = idxset_first(i, &index); s; s = idxset_next(i, &index)) { + for (s = pa_idxset_first(i, &index); s; s = pa_idxset_next(i, &index)) { if (s->header.dead || !s->enabled) continue; @@ -187,17 +187,17 @@ static void run_fixed_or_idle(struct pa_mainloop *m, struct idxset *i) { } static int calc_next_timeout(struct pa_mainloop *m) { - uint32_t index = IDXSET_INVALID; + uint32_t index = PA_IDXSET_INVALID; struct mainloop_source_time *s; struct timeval now; int t = -1; - if (idxset_isempty(m->time_sources)) + if (pa_idxset_isempty(m->time_sources)) return -1; gettimeofday(&now, NULL); - for (s = idxset_first(m->time_sources, &index); s; s = idxset_next(m->time_sources, &index)) { + for (s = pa_idxset_first(m->time_sources, &index); s; s = pa_idxset_next(m->time_sources, &index)) { int tmp; if (s->header.dead || !s->enabled) @@ -223,16 +223,16 @@ static int calc_next_timeout(struct pa_mainloop *m) { } static void dispatch_timeout(struct pa_mainloop *m) { - uint32_t index = IDXSET_INVALID; + uint32_t index = PA_IDXSET_INVALID; struct mainloop_source_time *s; struct timeval now; assert(m); - if (idxset_isempty(m->time_sources)) + if (pa_idxset_isempty(m->time_sources)) return; gettimeofday(&now, NULL); - for (s = idxset_first(m->time_sources, &index); s; s = idxset_next(m->time_sources, &index)) { + for (s = pa_idxset_first(m->time_sources, &index); s; s = pa_idxset_next(m->time_sources, &index)) { if (s->header.dead || !s->enabled) continue; @@ -251,7 +251,7 @@ static int any_idle_sources(struct pa_mainloop *m) { uint32_t index; assert(m); - for (s = idxset_first(m->idle_sources, &index); s; s = idxset_next(m->idle_sources, &index)) + for (s = pa_idxset_first(m->idle_sources, &index); s; s = pa_idxset_next(m->idle_sources, &index)) if (!s->header.dead && s->enabled) return 1; @@ -334,7 +334,7 @@ static void* mainloop_source_io(struct pa_mainloop_api*a, int fd, enum pa_mainlo s->userdata = userdata; s->pollfd = NULL; - idxset_put(m->io_sources, s, NULL); + pa_idxset_put(m->io_sources, s, NULL); m->rebuild_pollfds = 1; return s; } @@ -380,7 +380,7 @@ static void* mainloop_source_fixed(struct pa_mainloop_api*a, void (*callback) (s s->callback = callback; s->userdata = userdata; - idxset_put(m->fixed_sources, s, NULL); + pa_idxset_put(m->fixed_sources, s, NULL); return s; } @@ -422,7 +422,7 @@ static void* mainloop_source_idle(struct pa_mainloop_api*a, void (*callback) (st s->callback = callback; s->userdata = userdata; - idxset_put(m->idle_sources, s, NULL); + pa_idxset_put(m->idle_sources, s, NULL); return s; } @@ -457,7 +457,7 @@ static void* mainloop_source_time(struct pa_mainloop_api*a, const struct timeval s->callback = callback; s->userdata = userdata; - idxset_put(m->time_sources, s, NULL); + pa_idxset_put(m->time_sources, s, NULL); return s; } diff --git a/src/memblock.c b/src/memblock.c index 067243c57..af57e3a48 100644 --- a/src/memblock.c +++ b/src/memblock.c @@ -5,69 +5,69 @@ #include "memblock.h" -unsigned memblock_count = 0, memblock_total = 0; +unsigned pa_memblock_count = 0, pa_memblock_total = 0; -struct memblock *memblock_new(size_t length) { - struct memblock *b = malloc(sizeof(struct memblock)+length); - b->type = MEMBLOCK_APPENDED; +struct pa_memblock *pa_memblock_new(size_t length) { + struct pa_memblock *b = malloc(sizeof(struct pa_memblock)+length); + b->type = PA_MEMBLOCK_APPENDED; b->ref = 1; b->length = length; b->data = b+1; - memblock_count++; - memblock_total += length; + pa_memblock_count++; + pa_memblock_total += length; return b; } -struct memblock *memblock_new_fixed(void *d, size_t length) { - struct memblock *b = malloc(sizeof(struct memblock)); - b->type = MEMBLOCK_FIXED; +struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length) { + struct pa_memblock *b = malloc(sizeof(struct pa_memblock)); + b->type = PA_MEMBLOCK_FIXED; b->ref = 1; b->length = length; b->data = d; - memblock_count++; - memblock_total += length; + pa_memblock_count++; + pa_memblock_total += length; return b; } -struct memblock *memblock_new_dynamic(void *d, size_t length) { - struct memblock *b = malloc(sizeof(struct memblock)); - b->type = MEMBLOCK_DYNAMIC; +struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length) { + struct pa_memblock *b = malloc(sizeof(struct pa_memblock)); + b->type = PA_MEMBLOCK_DYNAMIC; b->ref = 1; b->length = length; b->data = d; - memblock_count++; - memblock_total += length; + pa_memblock_count++; + pa_memblock_total += length; return b; } -struct memblock* memblock_ref(struct memblock*b) { +struct pa_memblock* pa_memblock_ref(struct pa_memblock*b) { assert(b && b->ref >= 1); b->ref++; return b; } -void memblock_unref(struct memblock*b) { +void pa_memblock_unref(struct pa_memblock*b) { assert(b && b->ref >= 1); b->ref--; if (b->ref == 0) { - if (b->type == MEMBLOCK_DYNAMIC) + if (b->type == PA_MEMBLOCK_DYNAMIC) free(b->data); - memblock_count--; - memblock_total -= b->length; + pa_memblock_count--; + pa_memblock_total -= b->length; free(b); } } -void memblock_unref_fixed(struct memblock *b) { +void pa_memblock_unref_fixed(struct pa_memblock *b) { void *d; assert(b && b->ref >= 1); if (b->ref == 1) { - memblock_unref(b); + pa_memblock_unref(b); return; } @@ -75,6 +75,6 @@ void memblock_unref_fixed(struct memblock *b) { assert(d); memcpy(d, b->data, b->length); b->data = d; - b->type = MEMBLOCK_DYNAMIC; + b->type = PA_MEMBLOCK_DYNAMIC; } diff --git a/src/memblock.h b/src/memblock.h index e4a578b80..acdae0479 100644 --- a/src/memblock.h +++ b/src/memblock.h @@ -4,26 +4,26 @@ #include #include -enum memblock_type { MEMBLOCK_FIXED, MEMBLOCK_APPENDED, MEMBLOCK_DYNAMIC }; +enum pa_memblock_type { PA_MEMBLOCK_FIXED, PA_MEMBLOCK_APPENDED, PA_MEMBLOCK_DYNAMIC }; -struct memblock { - enum memblock_type type; +struct pa_memblock { + enum pa_memblock_type type; unsigned ref; size_t length; void *data; }; -struct memblock *memblock_new(size_t length); -struct memblock *memblock_new_fixed(void *data, size_t length); -struct memblock *memblock_new_dynamic(void *data, size_t length); +struct pa_memblock *pa_memblock_new(size_t length); +struct pa_memblock *pa_memblock_new_fixed(void *data, size_t length); +struct pa_memblock *pa_memblock_new_dynamic(void *data, size_t length); -void memblock_unref(struct memblock*b); -struct memblock* memblock_ref(struct memblock*b); +void pa_memblock_unref(struct pa_memblock*b); +struct pa_memblock* pa_memblock_ref(struct pa_memblock*b); -void memblock_unref_fixed(struct memblock*b); +void pa_memblock_unref_fixed(struct pa_memblock*b); -#define memblock_assert_exclusive(b) assert((b)->ref == 1) +#define pa_memblock_assert_exclusive(b) assert((b)->ref == 1) -extern unsigned memblock_count, memblock_total; +extern unsigned pa_memblock_count, pa_memblock_total; #endif diff --git a/src/memblockq.c b/src/memblockq.c index cab02bed7..b70a67ffe 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -8,24 +8,24 @@ struct memblock_list { struct memblock_list *next; - struct memchunk chunk; + struct pa_memchunk chunk; struct timeval stamp; }; -struct memblockq { +struct pa_memblockq { struct memblock_list *blocks, *blocks_tail; unsigned n_blocks; size_t total_length, maxlength, base, prebuf; int measure_delay; uint32_t delay; - struct mcalign *mcalign; + struct pa_mcalign *mcalign; }; -struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { - struct memblockq* bq; +struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t base, size_t prebuf) { + struct pa_memblockq* bq; assert(maxlength && base); - bq = malloc(sizeof(struct memblockq)); + bq = malloc(sizeof(struct pa_memblockq)); assert(bq); bq->blocks = bq->blocks_tail = 0; bq->n_blocks = 0; @@ -47,23 +47,23 @@ struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf) { return bq; } -void memblockq_free(struct memblockq* bq) { +void pa_memblockq_free(struct pa_memblockq* bq) { struct memblock_list *l; assert(bq); if (bq->mcalign) - mcalign_free(bq->mcalign); + pa_mcalign_free(bq->mcalign); while ((l = bq->blocks)) { bq->blocks = l->next; - memblock_unref(l->chunk.memblock); + pa_memblock_unref(l->chunk.memblock); free(l); } free(bq); } -void memblockq_push(struct memblockq* bq, const struct memchunk *chunk, size_t delta) { +void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta) { struct memblock_list *q; assert(bq && chunk && chunk->memblock && chunk->length && (chunk->length % bq->base) == 0); @@ -76,7 +76,7 @@ void memblockq_push(struct memblockq* bq, const struct memchunk *chunk, size_t d timerclear(&q->stamp); q->chunk = *chunk; - memblock_ref(q->chunk.memblock); + pa_memblock_ref(q->chunk.memblock); assert(q->chunk.index+q->chunk.length <= q->chunk.memblock->length); q->next = NULL; @@ -90,10 +90,10 @@ void memblockq_push(struct memblockq* bq, const struct memchunk *chunk, size_t d bq->n_blocks++; bq->total_length += chunk->length; - memblockq_shorten(bq, bq->maxlength); + pa_memblockq_shorten(bq, bq->maxlength); } -int memblockq_peek(struct memblockq* bq, struct memchunk *chunk) { +int pa_memblockq_peek(struct pa_memblockq* bq, struct pa_memchunk *chunk) { assert(bq && chunk); if (!bq->blocks || bq->total_length < bq->prebuf) @@ -102,16 +102,16 @@ int memblockq_peek(struct memblockq* bq, struct memchunk *chunk) { bq->prebuf = 0; *chunk = bq->blocks->chunk; - memblock_ref(chunk->memblock); + pa_memblock_ref(chunk->memblock); - if (chunk->memblock->ref != 2) - fprintf(stderr, "block %p with ref %u peeked.\n", chunk->memblock, chunk->memblock->ref); +/* if (chunk->memblock->ref != 2) */ +/* fprintf(stderr, "block %p with ref %u peeked.\n", chunk->memblock, chunk->memblock->ref); */ return 0; } /* -int memblockq_pop(struct memblockq* bq, struct memchunk *chunk) { +int memblockq_pop(struct memblockq* bq, struct pa_memchunk *chunk) { struct memblock_list *q; assert(bq && chunk); @@ -154,7 +154,7 @@ static uint32_t age(struct timeval *tv) { return r; } -void memblockq_drop(struct memblockq *bq, size_t length) { +void pa_memblockq_drop(struct pa_memblockq *bq, size_t length) { assert(bq && length && (length % bq->base) == 0); while (length > 0) { @@ -178,7 +178,7 @@ void memblockq_drop(struct memblockq *bq, size_t length) { bq->blocks = bq->blocks->next; if (bq->blocks == NULL) bq->blocks_tail = NULL; - memblock_unref(q->chunk.memblock); + pa_memblock_unref(q->chunk.memblock); free(q); bq->n_blocks--; @@ -188,52 +188,52 @@ void memblockq_drop(struct memblockq *bq, size_t length) { } } -void memblockq_shorten(struct memblockq *bq, size_t length) { +void pa_memblockq_shorten(struct pa_memblockq *bq, size_t length) { size_t l; assert(bq); if (bq->total_length <= length) return; - fprintf(stderr, "Warning! memblockq_shorten()\n"); + fprintf(stderr, "Warning! pa_memblockq_shorten()\n"); l = bq->total_length - length; l /= bq->base; l *= bq->base; - memblockq_drop(bq, l); + pa_memblockq_drop(bq, l); } -void memblockq_empty(struct memblockq *bq) { +void pa_memblockq_empty(struct pa_memblockq *bq) { assert(bq); - memblockq_shorten(bq, 0); + pa_memblockq_shorten(bq, 0); } -int memblockq_is_readable(struct memblockq *bq) { +int pa_memblockq_is_readable(struct pa_memblockq *bq) { assert(bq); return bq->total_length >= bq->prebuf; } -int memblockq_is_writable(struct memblockq *bq, size_t length) { +int pa_memblockq_is_writable(struct pa_memblockq *bq, size_t length) { assert(bq); assert(length <= bq->maxlength); return bq->total_length + length <= bq->maxlength; } -uint32_t memblockq_get_delay(struct memblockq *bq) { +uint32_t pa_memblockq_get_delay(struct pa_memblockq *bq) { assert(bq); return bq->delay; } -uint32_t memblockq_get_length(struct memblockq *bq) { +uint32_t pa_memblockq_get_length(struct pa_memblockq *bq) { assert(bq); return bq->total_length; } -uint32_t memblockq_missing_to(struct memblockq *bq, size_t qlen) { +uint32_t pa_memblockq_missing_to(struct pa_memblockq *bq, size_t qlen) { assert(bq && qlen); if (bq->total_length >= qlen) @@ -242,25 +242,25 @@ uint32_t memblockq_missing_to(struct memblockq *bq, size_t qlen) { return qlen - bq->total_length; } -void memblockq_push_align(struct memblockq* bq, const struct memchunk *chunk, size_t delta) { - struct memchunk rchunk; +void pa_memblockq_push_align(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta) { + struct pa_memchunk rchunk; assert(bq && chunk && bq->base); if (bq->base == 1) { - memblockq_push(bq, chunk, delta); + pa_memblockq_push(bq, chunk, delta); return; } if (!bq->mcalign) { - bq->mcalign = mcalign_new(bq->base); + bq->mcalign = pa_mcalign_new(bq->base); assert(bq->mcalign); } - mcalign_push(bq->mcalign, chunk); + pa_mcalign_push(bq->mcalign, chunk); - while (mcalign_pop(bq->mcalign, &rchunk) >= 0) { - memblockq_push(bq, &rchunk, delta); - memblock_unref(rchunk.memblock); + while (pa_mcalign_pop(bq->mcalign, &rchunk) >= 0) { + pa_memblockq_push(bq, &rchunk, delta); + pa_memblock_unref(rchunk.memblock); delta = 0; } } diff --git a/src/memblockq.h b/src/memblockq.h index d19aac0e6..d8b9567f8 100644 --- a/src/memblockq.h +++ b/src/memblockq.h @@ -6,46 +6,46 @@ #include "memblock.h" #include "memchunk.h" -struct memblockq; +struct pa_memblockq; /* Parameters: the maximum length of the memblock queue, a base value for all operations (that is, all byte operations shall work on multiples of this base value) and an amount of bytes to prebuffer -before having memblockq_peek() succeed. */ -struct memblockq* memblockq_new(size_t maxlength, size_t base, size_t prebuf); -void memblockq_free(struct memblockq*bq); +before having pa_memblockq_peek() succeed. */ +struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t base, size_t prebuf); +void pa_memblockq_free(struct pa_memblockq*bq); /* Push a new memory chunk into the queue. Optionally specify a value for future cancellation. This is currently not implemented, however! */ -void memblockq_push(struct memblockq* bq, const struct memchunk *chunk, size_t delta); +void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta); -/* Same as memblockq_push(), however chunks are filtered through a mcalign object, and thus aligned to multiples of base */ -void memblockq_push_align(struct memblockq* bq, const struct memchunk *chunk, size_t delta); +/* Same as pa_memblockq_push(), however chunks are filtered through a mcalign object, and thus aligned to multiples of base */ +void pa_memblockq_push_align(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta); /* Return a copy of the next memory chunk in the queue. It is not removed from the queue */ -int memblockq_peek(struct memblockq* bq, struct memchunk *chunk); +int pa_memblockq_peek(struct pa_memblockq* bq, struct pa_memchunk *chunk); /* Drop the specified bytes from the queue */ -void memblockq_drop(struct memblockq *bq, size_t length); +void pa_memblockq_drop(struct pa_memblockq *bq, size_t length); -/* Shorten the memblockq to the specified length by dropping data at the end of the queue */ -void memblockq_shorten(struct memblockq *bq, size_t length); +/* Shorten the pa_memblockq to the specified length by dropping data at the end of the queue */ +void pa_memblockq_shorten(struct pa_memblockq *bq, size_t length); -/* Empty the memblockq */ -void memblockq_empty(struct memblockq *bq); +/* Empty the pa_memblockq */ +void pa_memblockq_empty(struct pa_memblockq *bq); -/* Test if the memblockq is currently readable, that is, more data than base */ -int memblockq_is_readable(struct memblockq *bq); +/* Test if the pa_memblockq is currently readable, that is, more data than base */ +int pa_memblockq_is_readable(struct pa_memblockq *bq); -/* Test if the memblockq is currently writable for the specified amount of bytes */ -int memblockq_is_writable(struct memblockq *bq, size_t length); +/* Test if the pa_memblockq is currently writable for the specified amount of bytes */ +int pa_memblockq_is_writable(struct pa_memblockq *bq, size_t length); /* The time memory chunks stay in the queue until they are removed completely in usecs */ -uint32_t memblockq_get_delay(struct memblockq *bq); +uint32_t pa_memblockq_get_delay(struct pa_memblockq *bq); /* Return the length of the queue in bytes */ -uint32_t memblockq_get_length(struct memblockq *bq); +uint32_t pa_memblockq_get_length(struct pa_memblockq *bq); /* Return how many bytes are missing in queue to the specified fill amount */ -uint32_t memblockq_missing_to(struct memblockq *bq, size_t qlen); +uint32_t pa_memblockq_missing_to(struct pa_memblockq *bq, size_t qlen); #endif diff --git a/src/memchunk.c b/src/memchunk.c index faee45086..c0be8cce0 100644 --- a/src/memchunk.c +++ b/src/memchunk.c @@ -5,34 +5,34 @@ #include "memchunk.h" -void memchunk_make_writable(struct memchunk *c) { - struct memblock *n; +void pa_memchunk_make_writable(struct pa_memchunk *c) { + struct pa_memblock *n; assert(c && c->memblock && c->memblock->ref >= 1); if (c->memblock->ref == 1) return; - n = memblock_new(c->length); + n = pa_memblock_new(c->length); assert(n); memcpy(n->data, c->memblock->data+c->index, c->length); - memblock_unref(c->memblock); + pa_memblock_unref(c->memblock); c->memblock = n; c->index = 0; } -struct mcalign { +struct pa_mcalign { size_t base; - struct memchunk chunk; + struct pa_memchunk chunk; uint8_t *buffer; size_t buffer_fill; }; -struct mcalign *mcalign_new(size_t base) { - struct mcalign *m; +struct pa_mcalign *pa_mcalign_new(size_t base) { + struct pa_mcalign *m; assert(base); - m = malloc(sizeof(struct mcalign)); + m = malloc(sizeof(struct pa_mcalign)); assert(m); m->base = base; m->chunk.memblock = NULL; @@ -42,25 +42,25 @@ struct mcalign *mcalign_new(size_t base) { return m; } -void mcalign_free(struct mcalign *m) { +void pa_mcalign_free(struct pa_mcalign *m) { assert(m); free(m->buffer); if (m->chunk.memblock) - memblock_unref(m->chunk.memblock); + pa_memblock_unref(m->chunk.memblock); free(m); } -void mcalign_push(struct mcalign *m, const struct memchunk *c) { +void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) { assert(m && c && !m->chunk.memblock && c->memblock && c->length); m->chunk = *c; - memblock_ref(m->chunk.memblock); + pa_memblock_ref(m->chunk.memblock); } -int mcalign_pop(struct mcalign *m, struct memchunk *c) { +int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) { assert(m && c && m->base > m->buffer_fill); int ret; @@ -80,13 +80,13 @@ int mcalign_pop(struct mcalign *m, struct memchunk *c) { if (m->chunk.length == 0) { m->chunk.length = m->chunk.index = 0; - memblock_unref(m->chunk.memblock); + pa_memblock_unref(m->chunk.memblock); m->chunk.memblock = NULL; } assert(m->buffer_fill <= m->base); if (m->buffer_fill == m->base) { - c->memblock = memblock_new_dynamic(m->buffer, m->base); + c->memblock = pa_memblock_new_dynamic(m->buffer, m->base); assert(c->memblock); c->index = 0; c->length = m->base; @@ -111,13 +111,13 @@ int mcalign_pop(struct mcalign *m, struct memchunk *c) { if (m->chunk.length) { *c = m->chunk; - memblock_ref(c->memblock); + pa_memblock_ref(c->memblock); ret = 0; } else ret = -1; m->chunk.length = m->chunk.index = 0; - memblock_unref(m->chunk.memblock); + pa_memblock_unref(m->chunk.memblock); m->chunk.memblock = NULL; return ret; diff --git a/src/memchunk.h b/src/memchunk.h index d395cf2c3..24c031a50 100644 --- a/src/memchunk.h +++ b/src/memchunk.h @@ -3,18 +3,18 @@ #include "memblock.h" -struct memchunk { - struct memblock *memblock; +struct pa_memchunk { + struct pa_memblock *memblock; size_t index, length; }; -void memchunk_make_writable(struct memchunk *c); +void pa_memchunk_make_writable(struct pa_memchunk *c); -struct mcalign; +struct pa_mcalign; -struct mcalign *mcalign_new(size_t base); -void mcalign_free(struct mcalign *m); -void mcalign_push(struct mcalign *m, const struct memchunk *c); -int mcalign_pop(struct mcalign *m, struct memchunk *c); +struct pa_mcalign *pa_mcalign_new(size_t base); +void pa_mcalign_free(struct pa_mcalign *m); +void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c); +int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c); #endif diff --git a/src/module-cli.c b/src/module-cli.c index 883f4f53b..4a1692eef 100644 --- a/src/module-cli.c +++ b/src/module-cli.c @@ -7,29 +7,29 @@ #include "iochannel.h" #include "cli.h" -int module_init(struct core *c, struct module*m) { - struct iochannel *io; +int module_init(struct pa_core *c, struct pa_module*m) { + struct pa_iochannel *io; assert(c && m); - if (stdin_inuse || stdout_inuse) { + if (pa_stdin_inuse || pa_stdout_inuse) { fprintf(stderr, "STDIN/STDUSE already used\n"); return -1; } - stdin_inuse = stdout_inuse = 1; - io = iochannel_new(c->mainloop, STDIN_FILENO, STDOUT_FILENO); + pa_stdin_inuse = pa_stdout_inuse = 1; + io = pa_iochannel_new(c->mainloop, STDIN_FILENO, STDOUT_FILENO); assert(io); - iochannel_set_noclose(io, 1); + pa_iochannel_set_noclose(io, 1); - m->userdata = cli_new(c, io); + m->userdata = pa_cli_new(c, io); assert(m->userdata); return 0; } -void module_done(struct core *c, struct module*m) { +void module_done(struct pa_core *c, struct pa_module*m) { assert(c && m); - cli_free(m->userdata); - assert(stdin_inuse && stdout_inuse); - stdin_inuse = stdout_inuse = 0; + pa_cli_free(m->userdata); + assert(pa_stdin_inuse && pa_stdout_inuse); + pa_stdin_inuse = pa_stdout_inuse = 0; } diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index 3f69e05b7..ef2b19d0a 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -19,9 +19,9 @@ #include "sample-util.h" struct userdata { - struct sink *sink; - struct source *source; - struct core *core; + struct pa_sink *sink; + struct pa_source *source; + struct pa_core *core; struct pa_sample_spec sample_spec; size_t in_fragment_size, out_fragment_size, in_fragments, out_fragments, out_fill; @@ -31,13 +31,13 @@ struct userdata { void *in_mmap, *out_mmap; size_t in_mmap_length, out_mmap_length; - struct mainloop_source *mainloop_source; + void *mainloop_source; - struct memblock **in_memblocks, **out_memblocks; + struct pa_memblock **in_memblocks, **out_memblocks; unsigned out_current, in_current; }; -void module_done(struct core *c, struct module*m); +void module_done(struct pa_core *c, struct pa_module*m); static void out_clear_memblocks(struct userdata*u, unsigned n) { unsigned i = u->out_current; @@ -48,7 +48,7 @@ static void out_clear_memblocks(struct userdata*u, unsigned n) { while (n > 0) { if (u->out_memblocks[i]) { - memblock_unref_fixed(u->out_memblocks[i]); + pa_memblock_unref_fixed(u->out_memblocks[i]); u->out_memblocks[i] = NULL; } @@ -64,15 +64,15 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { assert(u && u->out_memblocks); while (n > 0) { - struct memchunk chunk; + struct pa_memchunk chunk; if (!u->out_memblocks[u->out_current]) { - u->out_memblocks[u->out_current] = chunk.memblock = memblock_new_fixed(u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size); + u->out_memblocks[u->out_current] = chunk.memblock = pa_memblock_new_fixed(u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size); chunk.length = chunk.memblock->length; chunk.index = 0; - sink_render_into_full(u->sink, &chunk); + pa_sink_render_into_full(u->sink, &chunk); } u->out_current++; @@ -106,14 +106,14 @@ static void in_post_memblocks(struct userdata *u, unsigned n) { assert(u && u->in_memblocks); while (n > 0) { - struct memchunk chunk; + struct pa_memchunk chunk; if (!u->in_memblocks[u->in_current]) { - u->in_memblocks[u->in_current] = chunk.memblock = memblock_new_fixed(u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size); + u->in_memblocks[u->in_current] = chunk.memblock = pa_memblock_new_fixed(u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size); chunk.length = chunk.memblock->length; chunk.index = 0; - source_post(u->source, &chunk); + pa_source_post(u->source, &chunk); } u->in_current++; @@ -133,7 +133,7 @@ static void in_clear_memblocks(struct userdata*u, unsigned n) { while (n > 0) { if (u->in_memblocks[i]) { - memblock_unref_fixed(u->in_memblocks[i]); + pa_memblock_unref_fixed(u->in_memblocks[i]); u->in_memblocks[i] = NULL; } @@ -172,7 +172,7 @@ static void io_callback(struct pa_mainloop_api *m, void *id, int fd, enum pa_mai do_write(u); } -static uint32_t sink_get_latency_cb(struct sink *s) { +static uint32_t sink_get_latency_cb(struct pa_sink *s) { struct userdata *u = s->userdata; assert(s && u); @@ -180,7 +180,7 @@ static uint32_t sink_get_latency_cb(struct sink *s) { return pa_samples_usec(u->out_fill, &s->sample_spec); } -int module_init(struct core *c, struct module*m) { +int module_init(struct pa_core *c, struct pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; char *p; @@ -240,7 +240,7 @@ int module_init(struct core *c, struct module*m) { goto fail; } - if (oss_auto_format(u->fd, &u->sample_spec) < 0) + if (pa_oss_auto_format(u->fd, &u->sample_spec) < 0) goto fail; if (mode != O_WRONLY) { @@ -262,12 +262,12 @@ int module_init(struct core *c, struct module*m) { } } else { - u->source = source_new(c, "dsp", 0, &u->sample_spec); + u->source = pa_source_new(c, "dsp", 0, &u->sample_spec); assert(u->source); u->source->userdata = u; - u->in_memblocks = malloc(sizeof(struct memblock *)*u->in_fragments); - memset(u->in_memblocks, 0, sizeof(struct memblock *)*u->in_fragments); + u->in_memblocks = malloc(sizeof(struct pa_memblock *)*u->in_fragments); + memset(u->in_memblocks, 0, sizeof(struct pa_memblock *)*u->in_fragments); enable_bits |= PCM_ENABLE_INPUT; } @@ -291,15 +291,15 @@ int module_init(struct core *c, struct module*m) { goto fail; } } else { - silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); + pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); - u->sink = sink_new(c, "dsp", 0, &u->sample_spec); + u->sink = pa_sink_new(c, "dsp", 0, &u->sample_spec); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; u->out_memblocks = malloc(sizeof(struct memblock *)*u->out_fragments); - memset(u->out_memblocks, 0, sizeof(struct memblock *)*u->out_fragments); + memset(u->out_memblocks, 0, sizeof(struct pa_memblock *)*u->out_fragments); enable_bits |= PCM_ENABLE_OUTPUT; } @@ -329,7 +329,7 @@ fail: return -1; } -void module_done(struct core *c, struct module*m) { +void pa_module_done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); @@ -353,10 +353,10 @@ void module_done(struct core *c, struct module*m) { munmap(u->out_mmap, u->out_mmap_length); if (u->sink) - sink_free(u->sink); + pa_sink_free(u->sink); if (u->source) - source_free(u->source); + pa_source_free(u->source); if (u->mainloop_source) u->core->mainloop->cancel_io(u->core->mainloop, u->mainloop_source); diff --git a/src/module-oss.c b/src/module-oss.c index 75082a7fd..3a1afd474 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -18,12 +18,12 @@ #include "sample-util.h" struct userdata { - struct sink *sink; - struct source *source; - struct iochannel *io; - struct core *core; + struct pa_sink *sink; + struct pa_source *source; + struct pa_iochannel *io; + struct pa_core *core; - struct memchunk memchunk, silence; + struct pa_memchunk memchunk, silence; uint32_t in_fragment_size, out_fragment_size, sample_size; @@ -31,15 +31,15 @@ struct userdata { }; static void do_write(struct userdata *u) { - struct memchunk *memchunk; + struct pa_memchunk *memchunk; ssize_t r; assert(u); - if (!u->sink || !iochannel_is_writable(u->io)) + if (!u->sink || !pa_iochannel_is_writable(u->io)) return; if (!u->memchunk.length) { - if (sink_render(u->sink, u->out_fragment_size, &u->memchunk) < 0) + if (pa_sink_render(u->sink, u->out_fragment_size, &u->memchunk) < 0) memchunk = &u->silence; else memchunk = &u->memchunk; @@ -47,7 +47,7 @@ static void do_write(struct userdata *u) { assert(memchunk->memblock && memchunk->length); - if ((r = iochannel_write(u->io, memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { + if ((r = pa_iochannel_write(u->io, memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { fprintf(stderr, "write() failed: %s\n", strerror(errno)); return; } @@ -59,24 +59,24 @@ static void do_write(struct userdata *u) { u->memchunk.length -= r; if (u->memchunk.length <= 0) { - memblock_unref(u->memchunk.memblock); + pa_memblock_unref(u->memchunk.memblock); u->memchunk.memblock = NULL; } } } static void do_read(struct userdata *u) { - struct memchunk memchunk; + struct pa_memchunk memchunk; ssize_t r; assert(u); - if (!u->source || !iochannel_is_readable(u->io)) + if (!u->source || !pa_iochannel_is_readable(u->io)) return; - memchunk.memblock = memblock_new(u->in_fragment_size); + memchunk.memblock = pa_memblock_new(u->in_fragment_size); assert(memchunk.memblock); - if ((r = iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { - memblock_unref(memchunk.memblock); + if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { + pa_memblock_unref(memchunk.memblock); fprintf(stderr, "read() failed: %s\n", strerror(errno)); return; } @@ -85,18 +85,18 @@ static void do_read(struct userdata *u) { memchunk.length = memchunk.memblock->length = r; memchunk.index = 0; - source_post(u->source, &memchunk); - memblock_unref(memchunk.memblock); + pa_source_post(u->source, &memchunk); + pa_memblock_unref(memchunk.memblock); }; -static void io_callback(struct iochannel *io, void*userdata) { +static void io_callback(struct pa_iochannel *io, void*userdata) { struct userdata *u = userdata; assert(u); do_write(u); do_read(u); } -static uint32_t sink_get_latency_cb(struct sink *s) { +static uint32_t sink_get_latency_cb(struct pa_sink *s) { int arg; struct userdata *u = s->userdata; assert(s && u && u->sink); @@ -110,7 +110,7 @@ static uint32_t sink_get_latency_cb(struct sink *s) { return pa_samples_usec(arg, &s->sample_spec); } -int module_init(struct core *c, struct module*m) { +int module_init(struct pa_core *c, struct pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; char *p; @@ -154,7 +154,7 @@ int module_init(struct core *c, struct module*m) { goto fail; } - if (oss_auto_format(fd, &ss) < 0) + if (pa_oss_auto_format(fd, &ss) < 0) goto fail; if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) { @@ -180,7 +180,7 @@ int module_init(struct core *c, struct module*m) { u->core = c; if (mode != O_RDONLY) { - u->sink = sink_new(c, "dsp", 0, &ss); + u->sink = pa_sink_new(c, "dsp", 0, &ss); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; @@ -188,7 +188,7 @@ int module_init(struct core *c, struct module*m) { u->sink = NULL; if (mode != O_WRONLY) { - u->source = source_new(c, "dsp", 0, &ss); + u->source = pa_source_new(c, "dsp", 0, &ss); assert(u->source); u->source->userdata = u; } else @@ -196,9 +196,9 @@ int module_init(struct core *c, struct module*m) { assert(u->source || u->sink); - u->io = iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0); + u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0); assert(u->io); - iochannel_set_callback(u->io, io_callback, u); + pa_iochannel_set_callback(u->io, io_callback, u); u->fd = fd; u->memchunk.memblock = NULL; @@ -207,9 +207,9 @@ int module_init(struct core *c, struct module*m) { u->out_fragment_size = out_frag_size; u->in_fragment_size = in_frag_size; - u->silence.memblock = memblock_new(u->silence.length = u->out_fragment_size); + u->silence.memblock = pa_memblock_new(u->silence.length = u->out_fragment_size); assert(u->silence.memblock); - silence_memblock(u->silence.memblock, &ss); + pa_silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; m->userdata = u; @@ -223,7 +223,7 @@ fail: return -1; } -void module_done(struct core *c, struct module*m) { +void module_done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); @@ -231,14 +231,14 @@ void module_done(struct core *c, struct module*m) { assert(u); if (u->memchunk.memblock) - memblock_unref(u->memchunk.memblock); + pa_memblock_unref(u->memchunk.memblock); if (u->silence.memblock) - memblock_unref(u->silence.memblock); + pa_memblock_unref(u->silence.memblock); if (u->sink) - sink_free(u->sink); + pa_sink_free(u->sink); if (u->source) - source_free(u->source); - iochannel_free(u->io); + pa_source_free(u->source); + pa_iochannel_free(u->io); free(u); } diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index 9747c3307..ea5c15dbf 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -15,13 +15,13 @@ struct userdata { char *filename; - struct sink *sink; - struct iochannel *io; - struct core *core; + struct pa_sink *sink; + struct pa_iochannel *io; + struct pa_core *core; void *mainloop_source; struct pa_mainloop_api *mainloop; - struct memchunk memchunk; + struct pa_memchunk memchunk; }; static void do_write(struct userdata *u) { @@ -30,16 +30,16 @@ static void do_write(struct userdata *u) { u->mainloop->enable_fixed(u->mainloop, u->mainloop_source, 0); - if (!iochannel_is_writable(u->io)) + if (!pa_iochannel_is_writable(u->io)) return; if (!u->memchunk.length) - if (sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) + if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) return; assert(u->memchunk.memblock && u->memchunk.length); - if ((r = iochannel_write(u->io, u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { + if ((r = pa_iochannel_write(u->io, u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { fprintf(stderr, "write() failed: %s\n", strerror(errno)); return; } @@ -48,16 +48,16 @@ static void do_write(struct userdata *u) { u->memchunk.length -= r; if (u->memchunk.length <= 0) { - memblock_unref(u->memchunk.memblock); + pa_memblock_unref(u->memchunk.memblock); u->memchunk.memblock = NULL; } } -static void notify_cb(struct sink*s) { +static void notify_cb(struct pa_sink*s) { struct userdata *u = s->userdata; assert(s && u); - if (iochannel_is_writable(u->io)) + if (pa_iochannel_is_writable(u->io)) u->mainloop->enable_fixed(u->mainloop, u->mainloop_source, 1); } @@ -67,13 +67,13 @@ static void fixed_callback(struct pa_mainloop_api *m, void *id, void *userdata) do_write(u); } -static void io_callback(struct iochannel *io, void*userdata) { +static void io_callback(struct pa_iochannel *io, void*userdata) { struct userdata *u = userdata; assert(u); do_write(u); } -int module_init(struct core *c, struct module*m) { +int module_init(struct pa_core *c, struct pa_module*m) { struct userdata *u = NULL; struct stat st; char *p; @@ -109,14 +109,14 @@ int module_init(struct core *c, struct module*m) { u->filename = strdup(p); assert(u->filename); u->core = c; - u->sink = sink_new(c, "fifo", 0, &ss); + u->sink = pa_sink_new(c, "fifo", 0, &ss); assert(u->sink); u->sink->notify = notify_cb; u->sink->userdata = u; - u->io = iochannel_new(c->mainloop, -1, fd); + u->io = pa_iochannel_new(c->mainloop, -1, fd); assert(u->io); - iochannel_set_callback(u->io, io_callback, u); + pa_iochannel_set_callback(u->io, io_callback, u); u->memchunk.memblock = NULL; u->memchunk.length = 0; @@ -137,7 +137,7 @@ fail: return -1; } -void module_done(struct core *c, struct module*m) { +void module_done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); @@ -145,10 +145,10 @@ void module_done(struct core *c, struct module*m) { assert(u); if (u->memchunk.memblock) - memblock_unref(u->memchunk.memblock); + pa_memblock_unref(u->memchunk.memblock); - sink_free(u->sink); - iochannel_free(u->io); + pa_sink_free(u->sink); + pa_iochannel_free(u->io); u->mainloop->cancel_fixed(u->mainloop, u->mainloop_source); assert(u->filename); diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 29ce6b18c..1a655454b 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -9,23 +9,23 @@ #ifdef USE_PROTOCOL_SIMPLE #include "protocol-simple.h" - #define protocol_free protocol_simple_free + #define protocol_free pa_protocol_simple_free #define IPV4_PORT 4711 #define UNIX_SOCKET_DIR "/tmp/polypaudio" #define UNIX_SOCKET "/tmp/polypaudio/simple" #else #ifdef USE_PROTOCOL_CLI #include "protocol-cli.h" - #define protocol_new protocol_cli_new - #define protocol_free protocol_cli_free + #define protocol_new pa_protocol_cli_new + #define protocol_free pa_protocol_cli_free #define IPV4_PORT 4712 #define UNIX_SOCKET_DIR "/tmp/polypaudio" #define UNIX_SOCKET "/tmp/polypaudio/cli" #else #ifdef USE_PROTOCOL_NATIVE #include "protocol-native.h" - #define protocol_new protocol_native_new - #define protocol_free protocol_native_free + #define protocol_new pa_protocol_native_new + #define protocol_free pa_protocol_native_free #define IPV4_PORT 4713 #define UNIX_SOCKET_DIR "/tmp/polypaudio" #define UNIX_SOCKET "/tmp/polypaudio/native" @@ -33,8 +33,8 @@ #ifdef USE_PROTOCOL_ESOUND #include "protocol-esound.h" #include "esound-spec.h" - #define protocol_new protocol_esound_new - #define protocol_free protocol_esound_free + #define protocol_new pa_protocol_esound_new + #define protocol_free pa_protocol_esound_free #define IPV4_PORT ESD_DEFAULT_PORT #define UNIX_SOCKET_DIR ESD_UNIX_SOCKET_DIR #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME @@ -45,27 +45,27 @@ #endif #endif -int module_init(struct core *c, struct module*m) { - struct socket_server *s; +int module_init(struct pa_core *c, struct pa_module*m) { + struct pa_socket_server *s; assert(c && m); #ifdef USE_TCP_SOCKETS - if (!(s = socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, IPV4_PORT))) + if (!(s = pa_socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, IPV4_PORT))) return -1; #else - if (make_secure_dir(UNIX_SOCKET_DIR) < 0) { + if (pa_make_secure_dir(UNIX_SOCKET_DIR) < 0) { fprintf(stderr, "Failed to create secure socket directory.\n"); return -1; } - if (!(s = socket_server_new_unix(c->mainloop, UNIX_SOCKET))) { + if (!(s = pa_socket_server_new_unix(c->mainloop, UNIX_SOCKET))) { rmdir(UNIX_SOCKET_DIR); return -1; } #endif #ifdef USE_PROTOCOL_SIMPLE - m->userdata = protocol_simple_new(c, s, PROTOCOL_SIMPLE_PLAYBACK); + m->userdata = pa_protocol_simple_new(c, s, PA_PROTOCOL_SIMPLE_PLAYBACK); #else m->userdata = protocol_new(c, s); #endif @@ -74,7 +74,7 @@ int module_init(struct core *c, struct module*m) { return 0; } -void module_done(struct core *c, struct module*m) { +void module_done(struct pa_core *c, struct pa_module*m) { assert(c && m); protocol_free(m->userdata); diff --git a/src/module.c b/src/module.c index 883a22df9..468998ba2 100644 --- a/src/module.c +++ b/src/module.c @@ -8,13 +8,13 @@ #include "module.h" #include "strbuf.h" -struct module* module_load(struct core *c, const char *name, const char *argument) { - struct module *m = NULL; +struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char *argument) { + struct pa_module *m = NULL; int r; assert(c && name); - m = malloc(sizeof(struct module)); + m = malloc(sizeof(struct pa_module)); assert(m); m->name = strdup(name); @@ -37,11 +37,11 @@ struct module* module_load(struct core *c, const char *name, const char *argumen goto fail; if (!c->modules) - c->modules = idxset_new(NULL, NULL); + c->modules = pa_idxset_new(NULL, NULL); assert(c->modules); - r = idxset_put(c->modules, m, &m->index); - assert(r >= 0 && m->index != IDXSET_INVALID); + r = pa_idxset_put(c->modules, m, &m->index); + assert(r >= 0 && m->index != PA_IDXSET_INVALID); fprintf(stderr, "module: loaded %u \"%s\" with argument \"%s\".\n", m->index, m->name, m->argument); @@ -61,7 +61,7 @@ fail: return NULL; } -static void module_free(struct module *m) { +static void pa_module_free(struct pa_module *m) { assert(m && m->done && m->core); m->done(m->core, m); @@ -75,75 +75,75 @@ static void module_free(struct module *m) { } -void module_unload(struct core *c, struct module *m) { +void pa_module_unload(struct pa_core *c, struct pa_module *m) { assert(c && m); assert(c->modules); - if (!(m = idxset_remove_by_data(c->modules, m, NULL))) + if (!(m = pa_idxset_remove_by_data(c->modules, m, NULL))) return; - module_free(m); + pa_module_free(m); } -void module_unload_by_index(struct core *c, uint32_t index) { - struct module *m; - assert(c && index != IDXSET_INVALID); +void pa_module_unload_by_index(struct pa_core *c, uint32_t index) { + struct pa_module *m; + assert(c && index != PA_IDXSET_INVALID); assert(c->modules); - if (!(m = idxset_remove_by_index(c->modules, index))) + if (!(m = pa_idxset_remove_by_index(c->modules, index))) return; - module_free(m); + pa_module_free(m); } -void free_callback(void *p, void *userdata) { - struct module *m = p; +static void free_callback(void *p, void *userdata) { + struct pa_module *m = p; assert(m); - module_free(m); + pa_module_free(m); } -void module_unload_all(struct core *c) { +void pa_module_unload_all(struct pa_core *c) { assert(c); if (!c->modules) return; - idxset_free(c->modules, free_callback, NULL); + pa_idxset_free(c->modules, free_callback, NULL); c->modules = NULL; } -char *module_list_to_string(struct core *c) { - struct strbuf *s; - struct module *m; - uint32_t index = IDXSET_INVALID; +char *pa_module_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_module *m; + uint32_t index = PA_IDXSET_INVALID; assert(c); - s = strbuf_new(); + s = pa_strbuf_new(); assert(s); - strbuf_printf(s, "%u module(s) loaded.\n", idxset_ncontents(c->modules)); + pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_ncontents(c->modules)); - for (m = idxset_first(c->modules, &index); m; m = idxset_next(c->modules, &index)) - strbuf_printf(s, " index: %u, name: <%s>, argument: <%s>\n", m->index, m->name, m->argument); + for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) + pa_strbuf_printf(s, " index: %u, name: <%s>, argument: <%s>\n", m->index, m->name, m->argument); - return strbuf_tostring_free(s); + return pa_strbuf_tostring_free(s); } struct once_info { - struct core *core; + struct pa_core *core; uint32_t index; }; -void module_unload_once_callback(void *userdata) { +static void module_unload_once_callback(void *userdata) { struct once_info *i = userdata; assert(i); - module_unload_by_index(i->core, i->index); + pa_module_unload_by_index(i->core, i->index); free(i); } -void module_unload_request(struct core *c, struct module *m) { +void pa_module_unload_request(struct pa_core *c, struct pa_module *m) { struct once_info *i; assert(c && m); diff --git a/src/module.h b/src/module.h index cdb613476..1cc7d775b 100644 --- a/src/module.h +++ b/src/module.h @@ -6,28 +6,28 @@ #include "core.h" -struct module { - struct core *core; +struct pa_module { + struct pa_core *core; char *name, *argument; uint32_t index; lt_dlhandle dl; - int (*init)(struct core *c, struct module*m); - void (*done)(struct core *c, struct module*m); + int (*init)(struct pa_core *c, struct pa_module*m); + void (*done)(struct pa_core *c, struct pa_module*m); void *userdata; }; -struct module* module_load(struct core *c, const char *name, const char*argument); -void module_unload(struct core *c, struct module *m); -void module_unload_by_index(struct core *c, uint32_t index); +struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char*argument); +void pa_module_unload(struct pa_core *c, struct pa_module *m); +void pa_module_unload_by_index(struct pa_core *c, uint32_t index); -void module_unload_all(struct core *c); +void pa_module_unload_all(struct pa_core *c); -char *module_list_to_string(struct core *c); +char *pa_module_list_to_string(struct pa_core *c); -void module_unload_request(struct core *c, struct module *m); +void pa_module_unload_request(struct pa_core *c, struct pa_module *m); #endif diff --git a/src/namereg.c b/src/namereg.c index 0af461894..9cfb7353c 100644 --- a/src/namereg.c +++ b/src/namereg.c @@ -8,20 +8,20 @@ #include "namereg.h" struct namereg_entry { - enum namereg_type type; + enum pa_namereg_type type; char *name; void *data; }; -void namereg_free(struct core *c) { +void pa_namereg_free(struct pa_core *c) { assert(c); if (!c->namereg) return; - assert(hashset_ncontents(c->namereg) == 0); - hashset_free(c->namereg, NULL, NULL); + assert(pa_hashset_ncontents(c->namereg) == 0); + pa_hashset_free(c->namereg, NULL, NULL); } -const char *namereg_register(struct core *c, const char *name, enum namereg_type type, void *data, int fail) { +const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_namereg_type type, void *data, int fail) { struct namereg_entry *e; char *n = NULL; int r; @@ -29,11 +29,11 @@ const char *namereg_register(struct core *c, const char *name, enum namereg_type assert(c && name && data); if (!c->namereg) { - c->namereg = hashset_new(idxset_string_hash_func, idxset_string_compare_func); + c->namereg = pa_hashset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); assert(c->namereg); } - if ((e = hashset_get(c->namereg, name)) && fail) + if ((e = pa_hashset_get(c->namereg, name)) && fail) return NULL; if (!e) @@ -47,7 +47,7 @@ const char *namereg_register(struct core *c, const char *name, enum namereg_type for (i = 1; i <= 99; i++) { snprintf(n, l+2, "%s%u", name, i); - if (!(e = hashset_get(c->namereg, n))) + if (!(e = pa_hashset_get(c->namereg, n))) break; } @@ -64,36 +64,36 @@ const char *namereg_register(struct core *c, const char *name, enum namereg_type e->name = n; e->data = data; - r = hashset_put(c->namereg, e->name, e); + r = pa_hashset_put(c->namereg, e->name, e); assert (r >= 0); return e->name; } -void namereg_unregister(struct core *c, const char *name) { +void pa_namereg_unregister(struct pa_core *c, const char *name) { struct namereg_entry *e; int r; assert(c && name); - e = hashset_get(c->namereg, name); + e = pa_hashset_get(c->namereg, name); assert(e); - r = hashset_remove(c->namereg, name); + r = pa_hashset_remove(c->namereg, name); assert(r >= 0); free(e->name); free(e); } -void* namereg_get(struct core *c, const char *name, enum namereg_type type) { +void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type) { struct namereg_entry *e; uint32_t index; char *x = NULL; void *d = NULL; assert(c && name); - if ((e = hashset_get(c->namereg, name))) + if ((e = pa_hashset_get(c->namereg, name))) if (e->type == e->type) return e->data; @@ -102,10 +102,10 @@ void* namereg_get(struct core *c, const char *name, enum namereg_type type) { if (!x || *x != 0) return NULL; - if (type == NAMEREG_SINK) - d = idxset_get_by_index(c->sinks, index); - else if (type == NAMEREG_SOURCE) - d = idxset_get_by_index(c->sources, index); + if (type == PA_NAMEREG_SINK) + d = pa_idxset_get_by_index(c->sinks, index); + else if (type == PA_NAMEREG_SOURCE) + d = pa_idxset_get_by_index(c->sources, index); return d; } diff --git a/src/namereg.h b/src/namereg.h index 5632143b7..b53a8566e 100644 --- a/src/namereg.h +++ b/src/namereg.h @@ -3,15 +3,15 @@ #include "core.h" -enum namereg_type { - NAMEREG_SINK, - NAMEREG_SOURCE +enum pa_namereg_type { + PA_NAMEREG_SINK, + PA_NAMEREG_SOURCE }; -void namereg_free(struct core *c); +void pa_namereg_free(struct pa_core *c); -const char *namereg_register(struct core *c, const char *name, enum namereg_type type, void *data, int fail); -void namereg_unregister(struct core *c, const char *name); -void* namereg_get(struct core *c, const char *name, enum namereg_type type); +const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_namereg_type type, void *data, int fail); +void pa_namereg_unregister(struct pa_core *c, const char *name); +void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type); #endif diff --git a/src/oss-util.c b/src/oss-util.c index d3a5fecbb..9c4f55caf 100644 --- a/src/oss-util.c +++ b/src/oss-util.c @@ -7,7 +7,7 @@ #include "oss-util.h" -int oss_auto_format(int fd, struct pa_sample_spec *ss) { +int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { int format, channels, speed; assert(fd >= 0 && ss); diff --git a/src/oss-util.h b/src/oss-util.h index 5fc08b0ba..cf12e8e61 100644 --- a/src/oss-util.h +++ b/src/oss-util.h @@ -3,6 +3,6 @@ #include "sample.h" -int oss_auto_format(int fd, struct pa_sample_spec *ss); +int pa_oss_auto_format(int fd, struct pa_sample_spec *ss); #endif diff --git a/src/pacat.c b/src/pacat.c index ccad01890..32220aeb7 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -75,9 +75,9 @@ static void stream_complete_callback(struct pa_context*c, struct pa_stream *s, v static void context_complete_callback(struct pa_context *c, int success, void *userdata) { static const struct pa_sample_spec ss = { - .format = PA_SAMPLE_S16NE, + .format = PA_SAMPLE_S16LE, .rate = 44100, - .channels = 1 + .channels = 2 }; assert(c && !stream); diff --git a/src/packet.c b/src/packet.c index 0f966d9a7..304545c51 100644 --- a/src/packet.c +++ b/src/packet.c @@ -3,44 +3,44 @@ #include "packet.h" -struct packet* packet_new(size_t length) { - struct packet *p; +struct pa_packet* pa_packet_new(size_t length) { + struct pa_packet *p; assert(length); - p = malloc(sizeof(struct packet)+length); + p = malloc(sizeof(struct pa_packet)+length); assert(p); p->ref = 1; p->length = length; p->data = (uint8_t*) (p+1); - p->type = PACKET_APPENDED; + p->type = PA_PACKET_APPENDED; return p; } -struct packet* packet_new_dynamic(uint8_t* data, size_t length) { - struct packet *p; +struct pa_packet* pa_packet_new_dynamic(uint8_t* data, size_t length) { + struct pa_packet *p; assert(data && length); - p = malloc(sizeof(struct packet)); + p = malloc(sizeof(struct pa_packet)); assert(p); p->ref = 1; p->length = length; p->data = data; - p->type = PACKET_DYNAMIC; + p->type = PA_PACKET_DYNAMIC; return p; } -struct packet* packet_ref(struct packet *p) { +struct pa_packet* pa_packet_ref(struct pa_packet *p) { assert(p && p->ref >= 1); p->ref++; return p; } -void packet_unref(struct packet *p) { +void pa_packet_unref(struct pa_packet *p) { assert(p && p->ref >= 1); p->ref--; if (p->ref == 0) { - if (p->type == PACKET_DYNAMIC) + if (p->type == PA_PACKET_DYNAMIC) free(p->data); free(p); } diff --git a/src/packet.h b/src/packet.h index 7e2e00669..b6024dd0b 100644 --- a/src/packet.h +++ b/src/packet.h @@ -4,17 +4,17 @@ #include #include -struct packet { - enum { PACKET_APPENDED, PACKET_DYNAMIC } type; +struct pa_packet { + enum { PA_PACKET_APPENDED, PA_PACKET_DYNAMIC } type; unsigned ref; size_t length; uint8_t *data; }; -struct packet* packet_new(size_t length); -struct packet* packet_new_dynamic(uint8_t* data, size_t length); +struct pa_packet* pa_packet_new(size_t length); +struct pa_packet* pa_packet_new_dynamic(uint8_t* data, size_t length); -struct packet* packet_ref(struct packet *p); -void packet_unref(struct packet *p); +struct pa_packet* pa_packet_ref(struct pa_packet *p); +void pa_packet_unref(struct pa_packet *p); #endif diff --git a/src/pdispatch.c b/src/pdispatch.c index 65dcd747c..c2db134d9 100644 --- a/src/pdispatch.c +++ b/src/pdispatch.c @@ -5,17 +5,17 @@ #include "protocol-native-spec.h" struct reply_info { - struct pdispatch *pdispatch; + struct pa_pdispatch *pdispatch; struct reply_info *next, *previous; - int (*callback)(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); + int (*callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); void *userdata; uint32_t tag; void *mainloop_timeout; }; -struct pdispatch { +struct pa_pdispatch { struct pa_mainloop_api *mainloop; - const struct pdispatch_command *command_table; + const struct pa_pdispatch_command *command_table; unsigned n_commands; struct reply_info *replies; }; @@ -37,13 +37,13 @@ static void reply_info_free(struct reply_info *r) { free(r); } -struct pdispatch* pdispatch_new(struct pa_mainloop_api *mainloop, const struct pdispatch_command*table, unsigned entries) { - struct pdispatch *pd; +struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *mainloop, const struct pa_pdispatch_command*table, unsigned entries) { + struct pa_pdispatch *pd; assert(mainloop); assert((entries && table) || (!entries && !table)); - pd = malloc(sizeof(struct pdispatch)); + pd = malloc(sizeof(struct pa_pdispatch)); assert(pd); pd->mainloop = mainloop; pd->command_table = table; @@ -52,27 +52,27 @@ struct pdispatch* pdispatch_new(struct pa_mainloop_api *mainloop, const struct p return pd; } -void pdispatch_free(struct pdispatch *pd) { +void pa_pdispatch_free(struct pa_pdispatch *pd) { assert(pd); while (pd->replies) reply_info_free(pd->replies); free(pd); } -int pdispatch_run(struct pdispatch *pd, struct packet*packet, void *userdata) { +int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *userdata) { uint32_t tag, command; assert(pd && packet); - struct tagstruct *ts = NULL; + struct pa_tagstruct *ts = NULL; assert(pd && packet && packet->data); if (packet->length <= 8) goto fail; - ts = tagstruct_new(packet->data, packet->length); + ts = pa_tagstruct_new(packet->data, packet->length); assert(ts); - if (tagstruct_getu32(ts, &command) < 0 || - tagstruct_getu32(ts, &tag) < 0) + if (pa_tagstruct_getu32(ts, &command) < 0 || + pa_tagstruct_getu32(ts, &tag) < 0) goto fail; if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) { @@ -96,7 +96,7 @@ int pdispatch_run(struct pdispatch *pd, struct packet*packet, void *userdata) { goto fail; } else if (pd->command_table && command < pd->n_commands) { - const struct pdispatch_command *c = pd->command_table+command; + const struct pa_pdispatch_command *c = pd->command_table+command; if (!c->proc) goto fail; @@ -106,13 +106,13 @@ int pdispatch_run(struct pdispatch *pd, struct packet*packet, void *userdata) { } else goto fail; - tagstruct_free(ts); + pa_tagstruct_free(ts); return 0; fail: if (ts) - tagstruct_free(ts); + pa_tagstruct_free(ts); return -1; } @@ -125,7 +125,7 @@ static void timeout_callback(struct pa_mainloop_api*m, void *id, const struct ti reply_info_free(r); } -void pdispatch_register_reply(struct pdispatch *pd, uint32_t tag, int timeout, int (*cb)(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata), void *userdata) { +void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int timeout, int (*cb)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void *userdata) { struct reply_info *r; struct timeval tv; assert(pd && cb); diff --git a/src/pdispatch.h b/src/pdispatch.h index 466da9a46..736867005 100644 --- a/src/pdispatch.h +++ b/src/pdispatch.h @@ -6,17 +6,17 @@ #include "packet.h" #include "mainloop-api.h" -struct pdispatch; +struct pa_pdispatch; -struct pdispatch_command { - int (*proc)(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); +struct pa_pdispatch_command { + int (*proc)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); }; -struct pdispatch* pdispatch_new(struct pa_mainloop_api *m, const struct pdispatch_command*table, unsigned entries); -void pdispatch_free(struct pdispatch *pd); +struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *m, const struct pa_pdispatch_command*table, unsigned entries); +void pa_pdispatch_free(struct pa_pdispatch *pd); -int pdispatch_run(struct pdispatch *pd, struct packet*p, void *userdata); +int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*p, void *userdata); -void pdispatch_register_reply(struct pdispatch *pd, uint32_t tag, int timeout, int (*cb)(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata), void *userdata); +void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int timeout, int (*cb)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void *userdata); #endif diff --git a/src/polyp.c b/src/polyp.c index 32974fc44..eb9a3c20a 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -20,10 +20,10 @@ struct pa_context { char *name; struct pa_mainloop_api* mainloop; - struct socket_client *client; - struct pstream *pstream; - struct pdispatch *pdispatch; - struct dynarray *streams; + struct pa_socket_client *client; + struct pa_pstream *pstream; + struct pa_pdispatch *pdispatch; + struct pa_dynarray *streams; struct pa_stream *first_stream; uint32_t ctag; uint32_t errno; @@ -59,9 +59,9 @@ struct pa_stream { void *die_userdata; }; -static int command_request(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); +static int command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static const struct pdispatch_command command_table[PA_COMMAND_MAX] = { +static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, [PA_COMMAND_REPLY] = { NULL }, [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, @@ -82,7 +82,7 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->client = NULL; c->pstream = NULL; c->pdispatch = NULL; - c->streams = dynarray_new(); + c->streams = pa_dynarray_new(); assert(c->streams); c->first_stream = NULL; c->errno = PA_ERROR_OK; @@ -105,13 +105,13 @@ void pa_context_free(struct pa_context *c) { pa_stream_free(c->first_stream); if (c->client) - socket_client_free(c->client); + pa_socket_client_free(c->client); if (c->pdispatch) - pdispatch_free(c->pdispatch); + pa_pdispatch_free(c->pdispatch); if (c->pstream) - pstream_free(c->pstream); + pa_pstream_free(c->pstream); if (c->streams) - dynarray_free(c->streams, NULL, NULL); + pa_dynarray_free(c->streams, NULL, NULL); free(c->name); free(c); @@ -141,7 +141,7 @@ static void context_dead(struct pa_context *c) { c->die_callback(c, c->die_userdata); } -static void pstream_die_callback(struct pstream *p, void *userdata) { +static void pstream_die_callback(struct pa_pstream *p, void *userdata) { struct pa_context *c = userdata; assert(p && c); @@ -152,11 +152,11 @@ static void pstream_die_callback(struct pstream *p, void *userdata) { context_dead(c); } -static int pstream_packet_callback(struct pstream *p, struct packet *packet, void *userdata) { +static int pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { struct pa_context *c = userdata; assert(p && packet && c); - if (pdispatch_run(c->pdispatch, packet, c) < 0) { + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { fprintf(stderr, "polyp.c: invalid packet.\n"); return -1; } @@ -164,12 +164,12 @@ static int pstream_packet_callback(struct pstream *p, struct packet *packet, voi return 0; } -static int pstream_memblock_callback(struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata) { +static int pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata) { struct pa_context *c = userdata; struct pa_stream *s; assert(p && chunk && c && chunk->memblock && chunk->memblock->data); - if (!(s = dynarray_get(c->streams, channel))) + if (!(s = pa_dynarray_get(c->streams, channel))) return -1; if (s->read_callback) @@ -178,11 +178,11 @@ static int pstream_memblock_callback(struct pstream *p, uint32_t channel, int32_ return 0; } -static void on_connection(struct socket_client *client, struct iochannel*io, void *userdata) { +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { struct pa_context *c = userdata; assert(client && io && c && c->state == CONTEXT_CONNECTING); - socket_client_free(client); + pa_socket_client_free(client); c->client = NULL; if (!io) { @@ -195,13 +195,13 @@ static void on_connection(struct socket_client *client, struct iochannel*io, voi return; } - c->pstream = pstream_new(c->mainloop, io); + c->pstream = pa_pstream_new(c->mainloop, io); assert(c->pstream); - pstream_set_die_callback(c->pstream, pstream_die_callback, c); - pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); - pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); - c->pdispatch = pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); + c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); assert(c->pdispatch); c->state = CONTEXT_READY; @@ -214,7 +214,7 @@ int pa_context_connect(struct pa_context *c, const char *server, void (*complete assert(c && c->state == CONTEXT_UNCONNECTED); assert(!c->client); - if (!(c->client = socket_client_new_unix(c->mainloop, server ? server : DEFAULT_SERVER))) { + if (!(c->client = pa_socket_client_new_unix(c->mainloop, server ? server : DEFAULT_SERVER))) { c->errno = PA_ERROR_CONNECTIONREFUSED; return -1; } @@ -222,7 +222,7 @@ int pa_context_connect(struct pa_context *c, const char *server, void (*complete c->connect_complete_callback = complete; c->connect_complete_userdata = userdata; - socket_client_set_callback(c->client, on_connection, c); + pa_socket_client_set_callback(c->client, on_connection, c); c->state = CONTEXT_CONNECTING; return 0; @@ -249,20 +249,20 @@ void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_cont c->die_userdata = userdata; } -static int command_request(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata) { +static int command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_stream *s; struct pa_context *c = userdata; uint32_t bytes, channel; assert(pd && command == PA_COMMAND_REQUEST && t && c); - if (tagstruct_getu32(t, &channel) < 0 || - tagstruct_getu32(t, &bytes) < 0 || - !tagstruct_eof(t)) { + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_getu32(t, &bytes) < 0 || + !pa_tagstruct_eof(t)) { c->errno = PA_ERROR_PROTOCOL; return -1; } - if (!(s = dynarray_get(c->streams, channel))) { + if (!(s = pa_dynarray_get(c->streams, channel))) { c->errno = PA_ERROR_PROTOCOL; return -1; } @@ -277,7 +277,7 @@ static int command_request(struct pdispatch *pd, uint32_t command, uint32_t tag, return 0; } -static int create_playback_callback(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata) { +static int create_playback_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { int ret = 0; struct pa_stream *s = userdata; assert(pd && s && s->state == STREAM_CREATING); @@ -286,7 +286,7 @@ static int create_playback_callback(struct pdispatch *pd, uint32_t command, uint struct pa_context *c = s->context; assert(c); - if (command == PA_COMMAND_ERROR && tagstruct_getu32(t, &s->context->errno) < 0) { + if (command == PA_COMMAND_ERROR && pa_tagstruct_getu32(t, &s->context->errno) < 0) { s->context->errno = PA_ERROR_PROTOCOL; ret = -1; } else if (command == PA_COMMAND_TIMEOUT) { @@ -297,16 +297,16 @@ static int create_playback_callback(struct pdispatch *pd, uint32_t command, uint goto fail; } - if (tagstruct_getu32(t, &s->channel) < 0 || - tagstruct_getu32(t, &s->device_index) < 0 || - !tagstruct_eof(t)) { + if (pa_tagstruct_getu32(t, &s->channel) < 0 || + pa_tagstruct_getu32(t, &s->device_index) < 0 || + !pa_tagstruct_eof(t)) { s->context->errno = PA_ERROR_PROTOCOL; ret = -1; goto fail; } s->channel_valid = 1; - dynarray_put(s->context->streams, s->channel, s); + pa_dynarray_put(s->context->streams, s->channel, s); s->state = STREAM_READY; assert(s->create_complete_callback); @@ -331,7 +331,7 @@ int pa_stream_new( void *userdata) { struct pa_stream *s; - struct tagstruct *t; + struct pa_tagstruct *t; uint32_t tag; assert(c && name && ss && c->state == CONTEXT_READY && complete); @@ -356,21 +356,21 @@ int pa_stream_new( s->device_index = (uint32_t) -1; s->direction = dir; - t = tagstruct_new(NULL, 0); + t = pa_tagstruct_new(NULL, 0); assert(t); - tagstruct_putu32(t, dir == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); - tagstruct_putu32(t, tag = c->ctag++); - tagstruct_puts(t, name); - tagstruct_put_sample_spec(t, ss); - tagstruct_putu32(t, (uint32_t) -1); - tagstruct_putu32(t, attr ? attr->queue_length : DEFAULT_QUEUE_LENGTH); - tagstruct_putu32(t, attr ? attr->max_length : DEFAULT_MAX_LENGTH); - tagstruct_putu32(t, attr ? attr->prebuf : DEFAULT_PREBUF); + pa_tagstruct_putu32(t, dir == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_sample_spec(t, ss); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_putu32(t, attr ? attr->queue_length : DEFAULT_QUEUE_LENGTH); + pa_tagstruct_putu32(t, attr ? attr->max_length : DEFAULT_MAX_LENGTH); + pa_tagstruct_putu32(t, attr ? attr->prebuf : DEFAULT_PREBUF); - pstream_send_tagstruct(c->pstream, t); + pa_pstream_send_tagstruct(c->pstream, t); - pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_playback_callback, s); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_playback_callback, s); s->next = c->first_stream; if (s->next) @@ -385,17 +385,17 @@ void pa_stream_free(struct pa_stream *s) { assert(s && s->context); if (s->channel_valid) { - struct tagstruct *t = tagstruct_new(NULL, 0); + struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); assert(t); - tagstruct_putu32(t, PA_COMMAND_DELETE_PLAYBACK_STREAM); - tagstruct_putu32(t, s->context->ctag++); - tagstruct_putu32(t, s->channel); - pstream_send_tagstruct(s->context->pstream, t); + pa_tagstruct_putu32(t, PA_COMMAND_DELETE_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); } if (s->channel_valid) - dynarray_put(s->context->streams, s->channel, NULL); + pa_dynarray_put(s->context->streams, s->channel, NULL); if (s->next) s->next->previous = s->previous; @@ -414,17 +414,17 @@ void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stre } void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { - struct memchunk chunk; + struct pa_memchunk chunk; assert(s && s->context && data && length); - chunk.memblock = memblock_new(length); + chunk.memblock = pa_memblock_new(length); assert(chunk.memblock && chunk.memblock->data); memcpy(chunk.memblock->data, data, length); chunk.index = 0; chunk.length = length; - pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); - memblock_unref(chunk.memblock); + pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + pa_memblock_unref(chunk.memblock); /*fprintf(stderr, "Sent %u bytes\n", length);*/ diff --git a/src/protocol-cli.c b/src/protocol-cli.c index b6460fecf..0cdf2db1e 100644 --- a/src/protocol-cli.c +++ b/src/protocol-cli.c @@ -4,55 +4,55 @@ #include "protocol-cli.h" #include "cli.h" -struct protocol_cli { - struct core *core; - struct socket_server*server; - struct idxset *connections; +struct pa_protocol_cli { + struct pa_core *core; + struct pa_socket_server*server; + struct pa_idxset *connections; }; -static void cli_eof_cb(struct cli*c, void*userdata) { - struct protocol_cli *p = userdata; +static void cli_eof_cb(struct pa_cli*c, void*userdata) { + struct pa_protocol_cli *p = userdata; assert(p); - idxset_remove_by_data(p->connections, c, NULL); - cli_free(c); + pa_idxset_remove_by_data(p->connections, c, NULL); + pa_cli_free(c); } -static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { - struct protocol_cli *p = userdata; - struct cli *c; +static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { + struct pa_protocol_cli *p = userdata; + struct pa_cli *c; assert(s && io && p); - c = cli_new(p->core, io); + c = pa_cli_new(p->core, io); assert(c); - cli_set_eof_callback(c, cli_eof_cb, p); + pa_cli_set_eof_callback(c, cli_eof_cb, p); - idxset_put(p->connections, c, NULL); + pa_idxset_put(p->connections, c, NULL); } -struct protocol_cli* protocol_cli_new(struct core *core, struct socket_server *server) { - struct protocol_cli* p; +struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server) { + struct pa_protocol_cli* p; assert(core && server); - p = malloc(sizeof(struct protocol_cli)); + p = malloc(sizeof(struct pa_protocol_cli)); assert(p); p->core = core; p->server = server; - p->connections = idxset_new(NULL, NULL); + p->connections = pa_idxset_new(NULL, NULL); - socket_server_set_callback(p->server, on_connection, p); + pa_socket_server_set_callback(p->server, on_connection, p); return p; } static void free_connection(void *p, void *userdata) { assert(p); - cli_free(p); + pa_cli_free(p); } -void protocol_cli_free(struct protocol_cli *p) { +void pa_protocol_cli_free(struct pa_protocol_cli *p) { assert(p); - idxset_free(p->connections, free_connection, NULL); - socket_server_free(p->server); + pa_idxset_free(p->connections, free_connection, NULL); + pa_socket_server_free(p->server); free(p); } diff --git a/src/protocol-cli.h b/src/protocol-cli.h index 8c150ce15..fc6a7d65d 100644 --- a/src/protocol-cli.h +++ b/src/protocol-cli.h @@ -4,9 +4,9 @@ #include "core.h" #include "socket-server.h" -struct protocol_cli; +struct pa_protocol_cli; -struct protocol_cli* protocol_cli_new(struct core *core, struct socket_server *server); -void protocol_cli_free(struct protocol_cli *n); +struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server); +void pa_protocol_cli_free(struct pa_protocol_cli *n); #endif diff --git a/src/protocol-esound.c b/src/protocol-esound.c index 12d6f38c1..8198e72f3 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -17,9 +17,9 @@ struct connection { uint32_t index; - struct protocol_esound *protocol; - struct iochannel *io; - struct client *client; + struct pa_protocol_esound *protocol; + struct pa_iochannel *io; + struct pa_client *client; int authorized, swap_byte_order; void *read_data; size_t read_data_alloc, read_data_length; @@ -27,15 +27,15 @@ struct connection { size_t write_data_alloc, write_data_index, write_data_length; esd_proto_t request; esd_client_state_t state; - struct sink_input *sink_input; - struct memblockq *input_memblockq; + struct pa_sink_input *sink_input; + struct pa_memblockq *input_memblockq; }; -struct protocol_esound { +struct pa_protocol_esound { int public; - struct core *core; - struct socket_server *server; - struct idxset *connections; + struct pa_core *core; + struct pa_socket_server *server; + struct pa_idxset *connections; uint32_t sink_index; unsigned n_player; }; @@ -51,10 +51,10 @@ typedef struct proto_handler { #define BUFSIZE (1024) -static void sink_input_drop_cb(struct sink_input *i, size_t length); -static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk); -static void sink_input_kill_cb(struct sink_input *i); -static uint32_t sink_input_get_latency_cb(struct sink_input *i); +static void sink_input_drop_cb(struct pa_sink_input *i, size_t length); +static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); +static void sink_input_kill_cb(struct pa_sink_input *i); +static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); static int esd_proto_connect(struct connection *c, const void *data, size_t length); static int esd_proto_stream_play(struct connection *c, const void *data, size_t length); @@ -104,36 +104,36 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { static void connection_free(struct connection *c) { assert(c); - idxset_remove_by_data(c->protocol->connections, c, NULL); + pa_idxset_remove_by_data(c->protocol->connections, c, NULL); if (c->state == ESD_STREAMING_DATA) c->protocol->n_player--; - client_free(c->client); + pa_client_free(c->client); if (c->sink_input) - sink_input_free(c->sink_input); + pa_sink_input_free(c->sink_input); if (c->input_memblockq) - memblockq_free(c->input_memblockq); + pa_memblockq_free(c->input_memblockq); free(c->read_data); free(c->write_data); - iochannel_free(c->io); + pa_iochannel_free(c->io); free(c); } -static struct sink* get_output_sink(struct protocol_esound *p) { - struct sink *s; +static struct pa_sink* get_output_sink(struct pa_protocol_esound *p) { + struct pa_sink *s; assert(p); - if (!(s = idxset_get_by_index(p->core->sinks, p->sink_index))) - s = sink_get_default(p->core); + if (!(s = pa_idxset_get_by_index(p->core->sinks, p->sink_index))) + s = pa_sink_get_default(p->core); if (s->index) p->sink_index = s->index; else - p->sink_index = IDXSET_INVALID; + p->sink_index = PA_IDXSET_INVALID; return s; } @@ -183,7 +183,7 @@ static int esd_proto_connect(struct connection *c, const void *data, size_t leng static int esd_proto_stream_play(struct connection *c, const void *data, size_t length) { char name[ESD_NAME_MAX]; int format, rate; - struct sink *sink; + struct pa_sink *sink; struct pa_sample_spec ss; assert(length == (sizeof(int)*2+ESD_NAME_MAX)); @@ -203,14 +203,14 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t strncpy(name, data + sizeof(int)*2, sizeof(name)); name[sizeof(name)-1] = 0; - client_rename(c->client, name); + pa_client_rename(c->client, name); assert(!c->input_memblockq); - c->input_memblockq = memblockq_new(MEMBLOCKQ_LENGTH, pa_sample_size(&ss), MEMBLOCKQ_PREBUF); + c->input_memblockq = pa_memblockq_new(MEMBLOCKQ_LENGTH, pa_sample_size(&ss), MEMBLOCKQ_PREBUF); assert(c->input_memblockq); assert(!c->sink_input); - c->sink_input = sink_input_new(sink, name, &ss); + c->sink_input = pa_sink_input_new(sink, name, &ss); assert(c->sink_input); c->sink_input->peek = sink_input_peek_cb; @@ -233,14 +233,14 @@ static int esd_proto_stream_record(struct connection *c, const void *data, size_ } static int esd_proto_get_latency(struct connection *c, const void *data, size_t length) { - struct sink *sink; + struct pa_sink *sink; int latency, *lag; assert(c && !data && length == 0); if (!(sink = get_output_sink(c->protocol))) latency = 0; else { - float usec = sink_get_latency(sink); + float usec = pa_sink_get_latency(sink); usec += pa_samples_usec(MEMBLOCKQ_LENGTH-BUFSIZE, &sink->sample_spec); latency = (int) ((usec*44100)/1000000); } @@ -254,7 +254,7 @@ static int esd_proto_get_latency(struct connection *c, const void *data, size_t static int esd_proto_server_info(struct connection *c, const void *data, size_t length) { int rate = 44100, format = ESD_STEREO|ESD_BITS16; int *response; - struct sink *sink; + struct pa_sink *sink; assert(c && data && length == sizeof(int)); if ((sink = get_output_sink(c->protocol))) { @@ -275,7 +275,7 @@ static int esd_proto_all_info(struct connection *c, const void *data, size_t len void *response; size_t t, k, s; struct connection *conn; - size_t index = IDXSET_INVALID; + size_t index = PA_IDXSET_INVALID; assert(c && data && length == sizeof(int)); if (esd_proto_server_info(c, data, length) < 0) @@ -286,7 +286,7 @@ static int esd_proto_all_info(struct connection *c, const void *data, size_t len response = connection_write(c, (t = s+k*(c->protocol->n_player+1))); assert(k); - for (conn = idxset_first(c->protocol->connections, &index); conn; conn = idxset_next(c->protocol->connections, &index)) { + for (conn = pa_idxset_first(c->protocol->connections, &index); conn; conn = pa_idxset_next(c->protocol->connections, &index)) { int format = ESD_BITS16 | ESD_STEREO, rate = 44100, volume = 0xFF; if (conn->state != ESD_STREAMING_DATA) @@ -347,7 +347,7 @@ static int esd_proto_stream_pan(struct connection *c, const void *data, size_t l ok = connection_write(c, sizeof(int)); assert(ok); - if ((conn = idxset_get_by_index(c->protocol->connections, index))) { + if ((conn = pa_idxset_get_by_index(c->protocol->connections, index))) { assert(conn->sink_input); conn->sink_input->volume = volume; *ok = 1; @@ -359,24 +359,24 @@ static int esd_proto_stream_pan(struct connection *c, const void *data, size_t l /*** client callbacks ***/ -static void client_kill_cb(struct client *c) { +static void client_kill_cb(struct pa_client *c) { assert(c && c->userdata); connection_free(c->userdata); } -/*** iochannel callbacks ***/ +/*** pa_iochannel callbacks ***/ static int do_read(struct connection *c) { assert(c && c->io); - if (!iochannel_is_readable(c->io)) + if (!pa_iochannel_is_readable(c->io)) return 0; if (c->state == ESD_NEXT_REQUEST) { ssize_t r; assert(c->read_data_length < sizeof(c->request)); - if ((r = iochannel_read(c->io, ((void*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { + if ((r = pa_iochannel_read(c->io, ((void*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -423,7 +423,7 @@ static int do_read(struct connection *c) { assert(c->read_data && c->read_data_length < handler->data_length); - if ((r = iochannel_read(c->io, c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { + if ((r = pa_iochannel_read(c->io, c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -439,20 +439,20 @@ static int do_read(struct connection *c) { return -1; } } else if (c->state == ESD_STREAMING_DATA) { - struct memchunk chunk; + struct pa_memchunk chunk; ssize_t r; assert(c->input_memblockq); - if (!memblockq_is_writable(c->input_memblockq, BUFSIZE)) + if (!pa_memblockq_is_writable(c->input_memblockq, BUFSIZE)) return 0; - chunk.memblock = memblock_new(BUFSIZE); + chunk.memblock = pa_memblock_new(BUFSIZE); assert(chunk.memblock && chunk.memblock->data); - if ((r = iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) { + if ((r = pa_iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) { fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); - memblock_unref(chunk.memblock); + pa_memblock_unref(chunk.memblock); return -1; } @@ -460,10 +460,10 @@ static int do_read(struct connection *c) { chunk.index = 0; assert(c->input_memblockq); - memblockq_push_align(c->input_memblockq, &chunk, 0); - memblock_unref(chunk.memblock); + pa_memblockq_push_align(c->input_memblockq, &chunk, 0); + pa_memblock_unref(chunk.memblock); assert(c->sink_input); - sink_notify(c->sink_input->sink); + pa_sink_notify(c->sink_input->sink); } else assert(0); @@ -475,14 +475,14 @@ static int do_write(struct connection *c) { ssize_t r; assert(c && c->io); - if (!iochannel_is_writable(c->io)) + if (!pa_iochannel_is_writable(c->io)) return 0; if (!c->write_data_length) return 0; assert(c->write_data_index < c->write_data_length); - if ((r = iochannel_write(c->io, c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { + if ((r = pa_iochannel_write(c->io, c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { fprintf(stderr, "protocol-esound.c: write() failed: %s\n", strerror(errno)); return -1; } @@ -493,7 +493,7 @@ static int do_write(struct connection *c) { return 0; } -static void io_callback(struct iochannel*io, void *userdata) { +static void io_callback(struct pa_iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); @@ -503,42 +503,42 @@ static void io_callback(struct iochannel*io, void *userdata) { /*** sink_input callbacks ***/ -static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk) { +static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { struct connection*c; assert(i && i->userdata && chunk); c = i->userdata; - if (memblockq_peek(c->input_memblockq, chunk) < 0) + if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) return -1; return 0; } -static void sink_input_drop_cb(struct sink_input *i, size_t length) { +static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { struct connection*c = i->userdata; assert(i && c && length); - memblockq_drop(c->input_memblockq, length); + pa_memblockq_drop(c->input_memblockq, length); if (do_read(c) < 0) connection_free(c); } -static void sink_input_kill_cb(struct sink_input *i) { +static void sink_input_kill_cb(struct pa_sink_input *i) { assert(i && i->userdata); connection_free((struct connection *) i->userdata); } -static uint32_t sink_input_get_latency_cb(struct sink_input *i) { +static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); - return pa_samples_usec(memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); + return pa_samples_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); } /*** socket server callback ***/ -static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { +static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { struct connection *c; char cname[256]; assert(s && io && userdata); @@ -547,11 +547,11 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us assert(c); c->protocol = userdata; c->io = io; - iochannel_set_callback(c->io, io_callback, c); + pa_iochannel_set_callback(c->io, io_callback, c); - iochannel_peer_to_string(io, cname, sizeof(cname)); + pa_iochannel_peer_to_string(io, cname, sizeof(cname)); assert(c->protocol->core); - c->client = client_new(c->protocol->core, "ESOUND", cname); + c->client = pa_client_new(c->protocol->core, "ESOUND", cname); assert(c->client); c->client->kill = client_kill_cb; c->client->userdata = c; @@ -572,39 +572,39 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->sink_input = NULL; c->input_memblockq = NULL; - idxset_put(c->protocol->connections, c, &c->index); + pa_idxset_put(c->protocol->connections, c, &c->index); } /*** entry points ***/ -struct protocol_esound* protocol_esound_new(struct core*core, struct socket_server *server) { - struct protocol_esound *p; +struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server) { + struct pa_protocol_esound *p; assert(core && server); - p = malloc(sizeof(struct protocol_esound)); + p = malloc(sizeof(struct pa_protocol_esound)); assert(p); p->public = 1; p->server = server; p->core = core; - p->connections = idxset_new(NULL, NULL); + p->connections = pa_idxset_new(NULL, NULL); assert(p->connections); - p->sink_index = IDXSET_INVALID; + p->sink_index = PA_IDXSET_INVALID; p->n_player = 0; - socket_server_set_callback(p->server, on_connection, p); + pa_socket_server_set_callback(p->server, on_connection, p); return p; } -void protocol_esound_free(struct protocol_esound *p) { +void pa_protocol_esound_free(struct pa_protocol_esound *p) { struct connection *c; assert(p); - while ((c = idxset_first(p->connections, NULL))) + while ((c = pa_idxset_first(p->connections, NULL))) connection_free(c); - idxset_free(p->connections, NULL, NULL); - socket_server_free(p->server); + pa_idxset_free(p->connections, NULL, NULL); + pa_socket_server_free(p->server); free(p); } diff --git a/src/protocol-esound.h b/src/protocol-esound.h index 2600cfae4..cd505593a 100644 --- a/src/protocol-esound.h +++ b/src/protocol-esound.h @@ -4,9 +4,9 @@ #include "core.h" #include "socket-server.h" -struct protocol_esound; +struct pa_protocol_esound; -struct protocol_esound* protocol_esound_new(struct core*core, struct socket_server *server); -void protocol_esound_free(struct protocol_esound *p); +struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server); +void pa_protocol_esound_free(struct pa_protocol_esound *p); #endif diff --git a/src/protocol-native.c b/src/protocol-native.c index 425f4ba46..8e4dcae1c 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -14,52 +14,52 @@ #include "pstream-util.h" struct connection; -struct protocol_native; +struct pa_protocol_native; struct record_stream { struct connection *connection; uint32_t index; - struct source_output *source_output; - struct memblockq *memblockq; + struct pa_source_output *source_output; + struct pa_memblockq *memblockq; }; struct playback_stream { struct connection *connection; uint32_t index; size_t qlength; - struct sink_input *sink_input; - struct memblockq *memblockq; + struct pa_sink_input *sink_input; + struct pa_memblockq *memblockq; size_t requested_bytes; }; struct connection { int authorized; - struct protocol_native *protocol; - struct client *client; - struct pstream *pstream; - struct pdispatch *pdispatch; - struct idxset *record_streams, *playback_streams; + struct pa_protocol_native *protocol; + struct pa_client *client; + struct pa_pstream *pstream; + struct pa_pdispatch *pdispatch; + struct pa_idxset *record_streams, *playback_streams; }; -struct protocol_native { +struct pa_protocol_native { int public; - struct core *core; - struct socket_server *server; - struct idxset *connections; + struct pa_core *core; + struct pa_socket_server *server; + struct pa_idxset *connections; }; -static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk); -static void sink_input_drop_cb(struct sink_input *i, size_t length); -static void sink_input_kill_cb(struct sink_input *i); -static uint32_t sink_input_get_latency_cb(struct sink_input *i); +static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); +static void sink_input_drop_cb(struct pa_sink_input *i, size_t length); +static void sink_input_kill_cb(struct pa_sink_input *i); +static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); static void request_bytes(struct playback_stream*s); -static int command_exit(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); -static int command_create_playback_stream(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); -static int command_delete_playback_stream(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata); +static int command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static int command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static int command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static const struct pdispatch_command command_table[PA_COMMAND_MAX] = { +static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, [PA_COMMAND_REPLY] = { NULL }, [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream }, @@ -74,13 +74,13 @@ static const struct pdispatch_command command_table[PA_COMMAND_MAX] = { static void record_stream_free(struct record_stream* r) { assert(r && r->connection); - idxset_remove_by_data(r->connection->record_streams, r, NULL); - source_output_free(r->source_output); - memblockq_free(r->memblockq); + pa_idxset_remove_by_data(r->connection->record_streams, r, NULL); + pa_source_output_free(r->source_output); + pa_memblockq_free(r->memblockq); free(r); } -static struct playback_stream* playback_stream_new(struct connection *c, struct sink *sink, struct pa_sample_spec *ss, const char *name, size_t qlen, size_t maxlength, size_t prebuf) { +static struct playback_stream* playback_stream_new(struct connection *c, struct pa_sink *sink, struct pa_sample_spec *ss, const char *name, size_t qlen, size_t maxlength, size_t prebuf) { struct playback_stream *s; assert(c && sink && ss && name && qlen && maxlength && prebuf); @@ -89,7 +89,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct s->connection = c; s->qlength = qlen; - s->sink_input = sink_input_new(sink, name, ss); + s->sink_input = pa_sink_input_new(sink, name, ss); assert(s->sink_input); s->sink_input->peek = sink_input_peek_cb; s->sink_input->drop = sink_input_drop_cb; @@ -97,21 +97,21 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct s->sink_input->get_latency = sink_input_get_latency_cb; s->sink_input->userdata = s; - s->memblockq = memblockq_new(maxlength, pa_sample_size(ss), prebuf); + s->memblockq = pa_memblockq_new(maxlength, pa_sample_size(ss), prebuf); assert(s->memblockq); s->requested_bytes = 0; - idxset_put(c->playback_streams, s, &s->index); + pa_idxset_put(c->playback_streams, s, &s->index); return s; } static void playback_stream_free(struct playback_stream* p) { assert(p && p->connection); - idxset_remove_by_data(p->connection->playback_streams, p, NULL); - sink_input_free(p->sink_input); - memblockq_free(p->memblockq); + pa_idxset_remove_by_data(p->connection->playback_streams, p, NULL); + pa_sink_input_free(p->sink_input); + pa_memblockq_free(p->memblockq); free(p); } @@ -120,27 +120,27 @@ static void connection_free(struct connection *c) { struct playback_stream *p; assert(c && c->protocol); - idxset_remove_by_data(c->protocol->connections, c, NULL); - while ((r = idxset_first(c->record_streams, NULL))) + pa_idxset_remove_by_data(c->protocol->connections, c, NULL); + while ((r = pa_idxset_first(c->record_streams, NULL))) record_stream_free(r); - idxset_free(c->record_streams, NULL, NULL); + pa_idxset_free(c->record_streams, NULL, NULL); - while ((p = idxset_first(c->playback_streams, NULL))) + while ((p = pa_idxset_first(c->playback_streams, NULL))) playback_stream_free(p); - idxset_free(c->playback_streams, NULL, NULL); + pa_idxset_free(c->playback_streams, NULL, NULL); - pdispatch_free(c->pdispatch); - pstream_free(c->pstream); - client_free(c->client); + pa_pdispatch_free(c->pdispatch); + pa_pstream_free(c->pstream); + pa_client_free(c->client); free(c); } static void request_bytes(struct playback_stream *s) { - struct tagstruct *t; + struct pa_tagstruct *t; size_t l; assert(s); - if (!(l = memblockq_missing_to(s->memblockq, s->qlength))) + if (!(l = pa_memblockq_missing_to(s->memblockq, s->qlength))) return; if (l <= s->requested_bytes) @@ -149,40 +149,40 @@ static void request_bytes(struct playback_stream *s) { l -= s->requested_bytes; s->requested_bytes += l; - t = tagstruct_new(NULL, 0); + t = pa_tagstruct_new(NULL, 0); assert(t); - tagstruct_putu32(t, PA_COMMAND_REQUEST); - tagstruct_putu32(t, (uint32_t) -1); /* tag */ - tagstruct_putu32(t, s->index); - tagstruct_putu32(t, l); - pstream_send_tagstruct(s->connection->pstream, t); + pa_tagstruct_putu32(t, PA_COMMAND_REQUEST); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, s->index); + pa_tagstruct_putu32(t, l); + pa_pstream_send_tagstruct(s->connection->pstream, t); /* fprintf(stderr, "Requesting %u bytes\n", l);*/ } /*** sinkinput callbacks ***/ -static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk) { +static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { struct playback_stream *s; assert(i && i->userdata && chunk); s = i->userdata; - if (memblockq_peek(s->memblockq, chunk) < 0) + if (pa_memblockq_peek(s->memblockq, chunk) < 0) return -1; return 0; } -static void sink_input_drop_cb(struct sink_input *i, size_t length) { +static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { struct playback_stream *s; assert(i && i->userdata && length); s = i->userdata; - memblockq_drop(s->memblockq, length); + pa_memblockq_drop(s->memblockq, length); request_bytes(s); } -static void sink_input_kill_cb(struct sink_input *i) { +static void sink_input_kill_cb(struct pa_sink_input *i) { struct playback_stream *s; assert(i && i->userdata); s = i->userdata; @@ -190,117 +190,117 @@ static void sink_input_kill_cb(struct sink_input *i) { playback_stream_free(s); } -static uint32_t sink_input_get_latency_cb(struct sink_input *i) { +static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct playback_stream *s; assert(i && i->userdata); s = i->userdata; - return pa_samples_usec(memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); + return pa_samples_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); } /*** pdispatch callbacks ***/ -static int command_create_playback_stream(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata) { +static int command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct playback_stream *s; size_t maxlength, prebuf, qlength; uint32_t sink_index; const char *name; struct pa_sample_spec ss; - struct tagstruct *reply; - struct sink *sink; + struct pa_tagstruct *reply; + struct pa_sink *sink; assert(c && t && c->protocol && c->protocol->core); - if (tagstruct_gets(t, &name) < 0 || - tagstruct_get_sample_spec(t, &ss) < 0 || - tagstruct_getu32(t, &sink_index) < 0 || - tagstruct_getu32(t, &qlength) < 0 || - tagstruct_getu32(t, &maxlength) < 0 || - tagstruct_getu32(t, &prebuf) < 0 || - !tagstruct_eof(t)) + if (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_get_sample_spec(t, &ss) < 0 || + pa_tagstruct_getu32(t, &sink_index) < 0 || + pa_tagstruct_getu32(t, &qlength) < 0 || + pa_tagstruct_getu32(t, &maxlength) < 0 || + pa_tagstruct_getu32(t, &prebuf) < 0 || + !pa_tagstruct_eof(t)) return -1; if (!c->authorized) { - pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); return 0; } if (sink_index == (uint32_t) -1) - sink = sink_get_default(c->protocol->core); + sink = pa_sink_get_default(c->protocol->core); else - sink = idxset_get_by_index(c->protocol->core->sinks, sink_index); + sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); if (!sink) { - pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); return 0; } if (!(s = playback_stream_new(c, sink, &ss, name, qlength, maxlength, prebuf))) { - pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); + pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); return 0; } - reply = tagstruct_new(NULL, 0); + reply = pa_tagstruct_new(NULL, 0); assert(reply); - tagstruct_putu32(reply, PA_COMMAND_REPLY); - tagstruct_putu32(reply, tag); - tagstruct_putu32(reply, s->index); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + pa_tagstruct_putu32(reply, s->index); assert(s->sink_input); - tagstruct_putu32(reply, s->sink_input->index); - pstream_send_tagstruct(c->pstream, reply); + pa_tagstruct_putu32(reply, s->sink_input->index); + pa_pstream_send_tagstruct(c->pstream, reply); request_bytes(s); return 0; } -static int command_delete_playback_stream(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata) { +static int command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t channel; struct playback_stream *s; assert(c && t); - if (tagstruct_getu32(t, &channel) < 0 || - !tagstruct_eof(t)) + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) return -1; if (!c->authorized) { - pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); return 0; } - if (!(s = idxset_get_by_index(c->playback_streams, channel))) { - pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + if (!(s = pa_idxset_get_by_index(c->playback_streams, channel))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); return 0; } - pstream_send_simple_ack(c->pstream, tag); + pa_pstream_send_simple_ack(c->pstream, tag); return 0; } -static int command_exit(struct pdispatch *pd, uint32_t command, uint32_t tag, struct tagstruct *t, void *userdata) { +static int command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; assert(c && t); - if (!tagstruct_eof(t)) + if (!pa_tagstruct_eof(t)) return -1; if (!c->authorized) { - pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); return 0; } assert(c->protocol && c->protocol->core && c->protocol->core->mainloop); c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0); - pstream_send_simple_ack(c->pstream, tag); /* nonsense */ + pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */ return 0; } /*** pstream callbacks ***/ -static int packet_callback(struct pstream *p, struct packet *packet, void *userdata) { +static int packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { struct connection *c = userdata; assert(p && packet && packet->data && c); - if (pdispatch_run(c->pdispatch, packet, c) < 0) { + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { fprintf(stderr, "protocol-native: invalid packet.\n"); return -1; } @@ -308,12 +308,12 @@ static int packet_callback(struct pstream *p, struct packet *packet, void *userd return 0; } -static int memblock_callback(struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata) { +static int memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata) { struct connection *c = userdata; struct playback_stream *stream; assert(p && chunk && userdata); - if (!(stream = idxset_get_by_index(c->playback_streams, channel))) { + if (!(stream = pa_idxset_get_by_index(c->playback_streams, channel))) { fprintf(stderr, "protocol-native: client sent block for invalid stream.\n"); return -1; } @@ -323,16 +323,16 @@ static int memblock_callback(struct pstream *p, uint32_t channel, int32_t delta, else stream->requested_bytes -= chunk->length; - memblockq_push_align(stream->memblockq, chunk, delta); + pa_memblockq_push_align(stream->memblockq, chunk, delta); assert(stream->sink_input); - sink_notify(stream->sink_input->sink); + pa_sink_notify(stream->sink_input->sink); /*fprintf(stderr, "Recieved %u bytes.\n", chunk->length);*/ return 0; } -static void die_callback(struct pstream *p, void *userdata) { +static void die_callback(struct pa_pstream *p, void *userdata) { struct connection *c = userdata; assert(p && c); connection_free(c); @@ -342,8 +342,8 @@ static void die_callback(struct pstream *p, void *userdata) { /*** socket server callbacks ***/ -static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { - struct protocol_native *p = userdata; +static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { + struct pa_protocol_native *p = userdata; struct connection *c; assert(s && io && p); @@ -352,52 +352,52 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->authorized = p->public; c->protocol = p; assert(p->core); - c->client = client_new(p->core, "NATIVE", "Client"); + c->client = pa_client_new(p->core, "NATIVE", "Client"); assert(c->client); - c->pstream = pstream_new(p->core->mainloop, io); + c->pstream = pa_pstream_new(p->core->mainloop, io); assert(c->pstream); - pstream_set_recieve_packet_callback(c->pstream, packet_callback, c); - pstream_set_recieve_memblock_callback(c->pstream, memblock_callback, c); - pstream_set_die_callback(c->pstream, die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, memblock_callback, c); + pa_pstream_set_die_callback(c->pstream, die_callback, c); - c->pdispatch = pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX); + c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX); assert(c->pdispatch); - c->record_streams = idxset_new(NULL, NULL); - c->playback_streams = idxset_new(NULL, NULL); + c->record_streams = pa_idxset_new(NULL, NULL); + c->playback_streams = pa_idxset_new(NULL, NULL); assert(c->record_streams && c->playback_streams); - idxset_put(p->connections, c, NULL); + pa_idxset_put(p->connections, c, NULL); } /*** module entry points ***/ -struct protocol_native* protocol_native_new(struct core *core, struct socket_server *server) { - struct protocol_native *p; +struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct pa_socket_server *server) { + struct pa_protocol_native *p; assert(core && server); - p = malloc(sizeof(struct protocol_native)); + p = malloc(sizeof(struct pa_protocol_native)); assert(p); p->public = 1; p->server = server; p->core = core; - p->connections = idxset_new(NULL, NULL); + p->connections = pa_idxset_new(NULL, NULL); assert(p->connections); - socket_server_set_callback(p->server, on_connection, p); + pa_socket_server_set_callback(p->server, on_connection, p); return p; } -void protocol_native_free(struct protocol_native *p) { +void pa_protocol_native_free(struct pa_protocol_native *p) { struct connection *c; assert(p); - while ((c = idxset_first(p->connections, NULL))) + while ((c = pa_idxset_first(p->connections, NULL))) connection_free(c); - idxset_free(p->connections, NULL, NULL); - socket_server_free(p->server); + pa_idxset_free(p->connections, NULL, NULL); + pa_socket_server_free(p->server); free(p); } diff --git a/src/protocol-native.h b/src/protocol-native.h index 88283e1c1..1a260149e 100644 --- a/src/protocol-native.h +++ b/src/protocol-native.h @@ -4,9 +4,9 @@ #include "core.h" #include "socket-server.h" -struct protocol_native; +struct pa_protocol_native; -struct protocol_native* protocol_native_new(struct core*core, struct socket_server *server); -void protocol_native_free(struct protocol_native *n); +struct pa_protocol_native* pa_protocol_native_new(struct pa_core*core, struct pa_socket_server *server); +void pa_protocol_native_free(struct pa_protocol_native *n); #endif diff --git a/src/protocol-simple.c b/src/protocol-simple.c index a7f3eb7e7..380b18029 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -12,19 +12,19 @@ #include "sample-util.h" struct connection { - struct protocol_simple *protocol; - struct iochannel *io; - struct sink_input *sink_input; - struct source_output *source_output; - struct client *client; - struct memblockq *input_memblockq, *output_memblockq; + struct pa_protocol_simple *protocol; + struct pa_iochannel *io; + struct pa_sink_input *sink_input; + struct pa_source_output *source_output; + struct pa_client *client; + struct pa_memblockq *input_memblockq, *output_memblockq; }; -struct protocol_simple { - struct core *core; - struct socket_server*server; - struct idxset *connections; - enum protocol_simple_mode mode; +struct pa_protocol_simple { + struct pa_core *core; + struct pa_socket_server*server; + struct pa_idxset *connections; + enum pa_protocol_simple_mode mode; struct pa_sample_spec sample_spec; }; @@ -33,38 +33,38 @@ struct protocol_simple { static void connection_free(struct connection *c) { assert(c); - idxset_remove_by_data(c->protocol->connections, c, NULL); + pa_idxset_remove_by_data(c->protocol->connections, c, NULL); if (c->sink_input) - sink_input_free(c->sink_input); + pa_sink_input_free(c->sink_input); if (c->source_output) - source_output_free(c->source_output); + pa_source_output_free(c->source_output); if (c->client) - client_free(c->client); + pa_client_free(c->client); if (c->io) - iochannel_free(c->io); + pa_iochannel_free(c->io); if (c->input_memblockq) - memblockq_free(c->input_memblockq); + pa_memblockq_free(c->input_memblockq); if (c->output_memblockq) - memblockq_free(c->output_memblockq); + pa_memblockq_free(c->output_memblockq); free(c); } static int do_read(struct connection *c) { - struct memchunk chunk; + struct pa_memchunk chunk; ssize_t r; - if (!iochannel_is_readable(c->io)) + if (!pa_iochannel_is_readable(c->io)) return 0; - if (!c->sink_input || !memblockq_is_writable(c->input_memblockq, BUFSIZE)) + if (!c->sink_input || !pa_memblockq_is_writable(c->input_memblockq, BUFSIZE)) return 0; - chunk.memblock = memblock_new(BUFSIZE); + chunk.memblock = pa_memblock_new(BUFSIZE); assert(chunk.memblock); - if ((r = iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) { + if ((r = pa_iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) { fprintf(stderr, "read(): %s\n", r == 0 ? "EOF" : strerror(errno)); - memblock_unref(chunk.memblock); + pa_memblock_unref(chunk.memblock); return -1; } @@ -72,103 +72,103 @@ static int do_read(struct connection *c) { chunk.index = 0; assert(c->input_memblockq); - memblockq_push_align(c->input_memblockq, &chunk, 0); - memblock_unref(chunk.memblock); + pa_memblockq_push_align(c->input_memblockq, &chunk, 0); + pa_memblock_unref(chunk.memblock); assert(c->sink_input); - sink_notify(c->sink_input->sink); + pa_sink_notify(c->sink_input->sink); return 0; } static int do_write(struct connection *c) { - struct memchunk chunk; + struct pa_memchunk chunk; ssize_t r; - if (!iochannel_is_writable(c->io)) + if (!pa_iochannel_is_writable(c->io)) return 0; if (!c->source_output) return 0; assert(c->output_memblockq); - if (memblockq_peek(c->output_memblockq, &chunk) < 0) + if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) return 0; assert(chunk.memblock && chunk.length); - if ((r = iochannel_write(c->io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { + if ((r = pa_iochannel_write(c->io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { fprintf(stderr, "write(): %s\n", strerror(errno)); - memblock_unref(chunk.memblock); + pa_memblock_unref(chunk.memblock); return -1; } - memblockq_drop(c->output_memblockq, r); - memblock_unref(chunk.memblock); + pa_memblockq_drop(c->output_memblockq, r); + pa_memblock_unref(chunk.memblock); return 0; } /*** sink_input callbacks ***/ -static int sink_input_peek_cb(struct sink_input *i, struct memchunk *chunk) { +static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { struct connection*c; assert(i && i->userdata && chunk); c = i->userdata; - if (memblockq_peek(c->input_memblockq, chunk) < 0) + if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) return -1; return 0; } -static void sink_input_drop_cb(struct sink_input *i, size_t length) { +static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { struct connection*c = i->userdata; assert(i && c && length); - memblockq_drop(c->input_memblockq, length); + pa_memblockq_drop(c->input_memblockq, length); if (do_read(c) < 0) connection_free(c); } -static void sink_input_kill_cb(struct sink_input *i) { +static void sink_input_kill_cb(struct pa_sink_input *i) { assert(i && i->userdata); connection_free((struct connection *) i->userdata); } -static uint32_t sink_input_get_latency_cb(struct sink_input *i) { +static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); - return pa_samples_usec(memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); + return pa_samples_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); } /*** source_output callbacks ***/ -static void source_output_push_cb(struct source_output *o, const struct memchunk *chunk) { +static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk) { struct connection *c = o->userdata; assert(o && c && chunk); - memblockq_push(c->output_memblockq, chunk, 0); + pa_memblockq_push(c->output_memblockq, chunk, 0); if (do_write(c) < 0) connection_free(c); } -static void source_output_kill_cb(struct source_output *o) { +static void source_output_kill_cb(struct pa_source_output *o) { assert(o && o->userdata); connection_free((struct connection *) o->userdata); } /*** client callbacks ***/ -static void client_kill_cb(struct client *c) { +static void client_kill_cb(struct pa_client *c) { assert(c && c->userdata); connection_free((struct connection *) c->userdata); } -/*** iochannel callbacks ***/ +/*** pa_iochannel callbacks ***/ -static void io_callback(struct iochannel*io, void *userdata) { +static void io_callback(struct pa_iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); @@ -178,8 +178,8 @@ static void io_callback(struct iochannel*io, void *userdata) { /*** socket_server callbacks */ -static void on_connection(struct socket_server*s, struct iochannel *io, void *userdata) { - struct protocol_simple *p = userdata; +static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { + struct pa_protocol_simple *p = userdata; struct connection *c = NULL; char cname[256]; assert(s && io && p); @@ -192,41 +192,41 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->input_memblockq = c->output_memblockq = NULL; c->protocol = p; - iochannel_peer_to_string(io, cname, sizeof(cname)); - c->client = client_new(p->core, "SIMPLE", cname); + pa_iochannel_peer_to_string(io, cname, sizeof(cname)); + c->client = pa_client_new(p->core, "SIMPLE", cname); assert(c->client); c->client->kill = client_kill_cb; c->client->userdata = c; - if (p->mode & PROTOCOL_SIMPLE_RECORD) { - struct source *source; + if (p->mode & PA_PROTOCOL_SIMPLE_RECORD) { + struct pa_source *source; size_t l; - if (!(source = source_get_default(p->core))) { + if (!(source = pa_source_get_default(p->core))) { fprintf(stderr, "Failed to get default source.\n"); goto fail; } - c->source_output = source_output_new(source, c->client->name, &p->sample_spec); + c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec); assert(c->source_output); c->source_output->push = source_output_push_cb; c->source_output->kill = source_output_kill_cb; c->source_output->userdata = c; - l = 5*pa_bytes_per_second(&DEFAULT_SAMPLE_SPEC); /* 5s */ - c->output_memblockq = memblockq_new(l, pa_sample_size(&p->sample_spec), l/2); + l = 5*pa_bytes_per_second(&p->sample_spec); /* 5s */ + c->output_memblockq = pa_memblockq_new(l, pa_sample_size(&p->sample_spec), l/2); } - if (p->mode & PROTOCOL_SIMPLE_PLAYBACK) { - struct sink *sink; + if (p->mode & PA_PROTOCOL_SIMPLE_PLAYBACK) { + struct pa_sink *sink; size_t l; - if (!(sink = sink_get_default(p->core))) { + if (!(sink = pa_sink_get_default(p->core))) { fprintf(stderr, "Failed to get default sink.\n"); goto fail; } - c->sink_input = sink_input_new(sink, c->client->name, &p->sample_spec); + c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec); assert(c->sink_input); c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; @@ -234,13 +234,13 @@ static void on_connection(struct socket_server*s, struct iochannel *io, void *us c->sink_input->get_latency = sink_input_get_latency_cb; c->sink_input->userdata = c; - l = pa_bytes_per_second(&DEFAULT_SAMPLE_SPEC)/2; /* half a second */ - c->input_memblockq = memblockq_new(l, pa_sample_size(&p->sample_spec), l/2); + l = pa_bytes_per_second(&p->sample_spec)/2; /* half a second */ + c->input_memblockq = pa_memblockq_new(l, pa_sample_size(&p->sample_spec), l/2); } - iochannel_set_callback(c->io, io_callback, c); - idxset_put(p->connections, c, NULL); + pa_iochannel_set_callback(c->io, io_callback, c); + pa_idxset_put(p->connections, c, NULL); return; fail: @@ -248,34 +248,34 @@ fail: connection_free(c); } -struct protocol_simple* protocol_simple_new(struct core *core, struct socket_server *server, enum protocol_simple_mode mode) { - struct protocol_simple* p; - assert(core && server && mode <= PROTOCOL_SIMPLE_DUPLEX && mode > 0); +struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, enum pa_protocol_simple_mode mode) { + struct pa_protocol_simple* p; + assert(core && server && mode <= PA_PROTOCOL_SIMPLE_DUPLEX && mode > 0); - p = malloc(sizeof(struct protocol_simple)); + p = malloc(sizeof(struct pa_protocol_simple)); assert(p); p->core = core; p->server = server; - p->connections = idxset_new(NULL, NULL); + p->connections = pa_idxset_new(NULL, NULL); p->mode = mode; - p->sample_spec = DEFAULT_SAMPLE_SPEC; + p->sample_spec = PA_DEFAULT_SAMPLE_SPEC; - socket_server_set_callback(p->server, on_connection, p); + pa_socket_server_set_callback(p->server, on_connection, p); return p; } -void protocol_simple_free(struct protocol_simple *p) { +void pa_protocol_simple_free(struct pa_protocol_simple *p) { struct connection *c; assert(p); - while((c = idxset_first(p->connections, NULL))) + while((c = pa_idxset_first(p->connections, NULL))) connection_free(c); - idxset_free(p->connections, NULL, NULL); + pa_idxset_free(p->connections, NULL, NULL); - socket_server_free(p->server); + pa_socket_server_free(p->server); free(p); } diff --git a/src/protocol-simple.h b/src/protocol-simple.h index f62104361..15ae36a6c 100644 --- a/src/protocol-simple.h +++ b/src/protocol-simple.h @@ -3,15 +3,15 @@ #include "socket-server.h" -struct protocol_simple; +struct pa_protocol_simple; -enum protocol_simple_mode { - PROTOCOL_SIMPLE_RECORD = 1, - PROTOCOL_SIMPLE_PLAYBACK = 2, - PROTOCOL_SIMPLE_DUPLEX = 3 +enum pa_protocol_simple_mode { + PA_PROTOCOL_SIMPLE_RECORD = 1, + PA_PROTOCOL_SIMPLE_PLAYBACK = 2, + PA_PROTOCOL_SIMPLE_DUPLEX = 3 }; -struct protocol_simple* protocol_simple_new(struct core *core, struct socket_server *server, enum protocol_simple_mode mode); -void protocol_simple_free(struct protocol_simple *n); +struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, enum pa_protocol_simple_mode mode); +void pa_protocol_simple_free(struct pa_protocol_simple *n); #endif diff --git a/src/pstream-util.c b/src/pstream-util.c index 2fab2b61c..cdcde5faa 100644 --- a/src/pstream-util.c +++ b/src/pstream-util.c @@ -3,33 +3,33 @@ #include "protocol-native-spec.h" #include "pstream-util.h" -void pstream_send_tagstruct(struct pstream *p, struct tagstruct *t) { +void pa_pstream_send_tagstruct(struct pa_pstream *p, struct pa_tagstruct *t) { size_t length; uint8_t *data; - struct packet *packet; + struct pa_packet *packet; assert(p && t); - data = tagstruct_free_data(t, &length); + data = pa_tagstruct_free_data(t, &length); assert(data && length); - packet = packet_new_dynamic(data, length); + packet = pa_packet_new_dynamic(data, length); assert(packet); - pstream_send_packet(p, packet); - packet_unref(packet); + pa_pstream_send_packet(p, packet); + pa_packet_unref(packet); } -void pstream_send_error(struct pstream *p, uint32_t tag, uint32_t error) { - struct tagstruct *t = tagstruct_new(NULL, 0); +void pa_pstream_send_error(struct pa_pstream *p, uint32_t tag, uint32_t error) { + struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); assert(t); - tagstruct_putu32(t, PA_COMMAND_ERROR); - tagstruct_putu32(t, tag); - tagstruct_putu32(t, error); - pstream_send_tagstruct(p, t); + pa_tagstruct_putu32(t, PA_COMMAND_ERROR); + pa_tagstruct_putu32(t, tag); + pa_tagstruct_putu32(t, error); + pa_pstream_send_tagstruct(p, t); } -void pstream_send_simple_ack(struct pstream *p, uint32_t tag) { - struct tagstruct *t = tagstruct_new(NULL, 0); +void pa_pstream_send_simple_ack(struct pa_pstream *p, uint32_t tag) { + struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); assert(t); - tagstruct_putu32(t, PA_COMMAND_REPLY); - tagstruct_putu32(t, tag); - pstream_send_tagstruct(p, t); + pa_tagstruct_putu32(t, PA_COMMAND_REPLY); + pa_tagstruct_putu32(t, tag); + pa_pstream_send_tagstruct(p, t); } diff --git a/src/pstream-util.h b/src/pstream-util.h index 4e64a95c0..430512603 100644 --- a/src/pstream-util.h +++ b/src/pstream-util.h @@ -6,9 +6,9 @@ #include "tagstruct.h" /* The tagstruct is freed!*/ -void pstream_send_tagstruct(struct pstream *p, struct tagstruct *t); +void pa_pstream_send_tagstruct(struct pa_pstream *p, struct pa_tagstruct *t); -void pstream_send_error(struct pstream *p, uint32_t tag, uint32_t error); -void pstream_send_simple_ack(struct pstream *p, uint32_t tag); +void pa_pstream_send_error(struct pa_pstream *p, uint32_t tag, uint32_t error); +void pa_pstream_send_simple_ack(struct pa_pstream *p, uint32_t tag); #endif diff --git a/src/pstream.c b/src/pstream.c index e3f598161..1739780e5 100644 --- a/src/pstream.c +++ b/src/pstream.c @@ -5,70 +5,70 @@ #include "pstream.h" #include "queue.h" -enum pstream_descriptor_index { - PSTREAM_DESCRIPTOR_LENGTH, - PSTREAM_DESCRIPTOR_CHANNEL, - PSTREAM_DESCRIPTOR_DELTA, - PSTREAM_DESCRIPTOR_MAX +enum pa_pstream_descriptor_index { + PA_PSTREAM_DESCRIPTOR_LENGTH, + PA_PSTREAM_DESCRIPTOR_CHANNEL, + PA_PSTREAM_DESCRIPTOR_DELTA, + PA_PSTREAM_DESCRIPTOR_MAX }; -typedef uint32_t pstream_descriptor[PSTREAM_DESCRIPTOR_MAX]; +typedef uint32_t pa_pstream_descriptor[PA_PSTREAM_DESCRIPTOR_MAX]; -#define PSTREAM_DESCRIPTOR_SIZE (PSTREAM_DESCRIPTOR_MAX*sizeof(uint32_t)) +#define PA_PSTREAM_DESCRIPTOR_SIZE (PA_PSTREAM_DESCRIPTOR_MAX*sizeof(uint32_t)) #define FRAME_SIZE_MAX (1024*64) struct item_info { - enum { PSTREAM_ITEM_PACKET, PSTREAM_ITEM_MEMBLOCK } type; + enum { PA_PSTREAM_ITEM_PACKET, PA_PSTREAM_ITEM_MEMBLOCK } type; /* memblock info */ - struct memchunk chunk; + struct pa_memchunk chunk; uint32_t channel; int32_t delta; /* packet info */ - struct packet *packet; + struct pa_packet *packet; }; -struct pstream { +struct pa_pstream { struct pa_mainloop_api *mainloop; struct mainloop_source *mainloop_source; - struct iochannel *io; - struct queue *send_queue; + struct pa_iochannel *io; + struct pa_queue *send_queue; int dead; - void (*die_callback) (struct pstream *p, void *userdad); + void (*die_callback) (struct pa_pstream *p, void *userdad); void *die_callback_userdata; struct { struct item_info* current; - pstream_descriptor descriptor; + pa_pstream_descriptor descriptor; void *data; size_t index; } write; - void (*send_callback) (struct pstream *p, void *userdata); + void (*send_callback) (struct pa_pstream *p, void *userdata); void *send_callback_userdata; struct { - struct memblock *memblock; - struct packet *packet; - pstream_descriptor descriptor; + struct pa_memblock *memblock; + struct pa_packet *packet; + pa_pstream_descriptor descriptor; void *data; size_t index; } read; - int (*recieve_packet_callback) (struct pstream *p, struct packet *packet, void *userdata); + int (*recieve_packet_callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata); void *recieve_packet_callback_userdata; - int (*recieve_memblock_callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata); + int (*recieve_memblock_callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata); void *recieve_memblock_callback_userdata; }; -static void do_write(struct pstream *p); -static void do_read(struct pstream *p); +static void do_write(struct pa_pstream *p); +static void do_read(struct pa_pstream *p); -static void io_callback(struct iochannel*io, void *userdata) { - struct pstream *p = userdata; +static void io_callback(struct pa_iochannel*io, void *userdata) { + struct pa_pstream *p = userdata; assert(p && p->io == io); p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0); @@ -78,7 +78,7 @@ static void io_callback(struct iochannel*io, void *userdata) { } static void fixed_callback(struct pa_mainloop_api *m, void *id, void*userdata) { - struct pstream *p = userdata; + struct pa_pstream *p = userdata; assert(p && p->mainloop_source == id && p->mainloop == m); p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0); @@ -87,15 +87,15 @@ static void fixed_callback(struct pa_mainloop_api *m, void *id, void*userdata) { do_read(p); } -struct pstream *pstream_new(struct pa_mainloop_api *m, struct iochannel *io) { - struct pstream *p; +struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io) { + struct pa_pstream *p; assert(io); - p = malloc(sizeof(struct pstream)); + p = malloc(sizeof(struct pa_pstream)); assert(p); p->io = io; - iochannel_set_callback(io, io_callback, p); + pa_iochannel_set_callback(io, io_callback, p); p->dead = 0; p->die_callback = NULL; @@ -105,7 +105,7 @@ struct pstream *pstream_new(struct pa_mainloop_api *m, struct iochannel *io) { p->mainloop_source = m->source_fixed(m, fixed_callback, p); m->enable_fixed(m, p->mainloop_source, 0); - p->send_queue = queue_new(); + p->send_queue = pa_queue_new(); assert(p->send_queue); p->write.current = NULL; @@ -131,118 +131,118 @@ static void item_free(void *item, void *p) { struct item_info *i = item; assert(i); - if (i->type == PSTREAM_ITEM_MEMBLOCK) { + if (i->type == PA_PSTREAM_ITEM_MEMBLOCK) { assert(i->chunk.memblock); - memblock_unref(i->chunk.memblock); + pa_memblock_unref(i->chunk.memblock); } else { - assert(i->type == PSTREAM_ITEM_PACKET); + assert(i->type == PA_PSTREAM_ITEM_PACKET); assert(i->packet); - packet_unref(i->packet); + pa_packet_unref(i->packet); } free(i); } -void pstream_free(struct pstream *p) { +void pa_pstream_free(struct pa_pstream *p) { assert(p); - iochannel_free(p->io); - queue_free(p->send_queue, item_free, NULL); + pa_iochannel_free(p->io); + pa_queue_free(p->send_queue, item_free, NULL); if (p->write.current) item_free(p->write.current, NULL); if (p->read.memblock) - memblock_unref(p->read.memblock); + pa_memblock_unref(p->read.memblock); if (p->read.packet) - packet_unref(p->read.packet); + pa_packet_unref(p->read.packet); p->mainloop->cancel_fixed(p->mainloop, p->mainloop_source); free(p); } -void pstream_set_send_callback(struct pstream*p, void (*callback) (struct pstream *p, void *userdata), void *userdata) { +void pa_pstream_set_send_callback(struct pa_pstream*p, void (*callback) (struct pa_pstream *p, void *userdata), void *userdata) { assert(p && callback); p->send_callback = callback; p->send_callback_userdata = userdata; } -void pstream_send_packet(struct pstream*p, struct packet *packet) { +void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { struct item_info *i; assert(p && packet); i = malloc(sizeof(struct item_info)); assert(i); - i->type = PSTREAM_ITEM_PACKET; - i->packet = packet_ref(packet); + i->type = PA_PSTREAM_ITEM_PACKET; + i->packet = pa_packet_ref(packet); - queue_push(p->send_queue, i); + pa_queue_push(p->send_queue, i); p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1); } -void pstream_send_memblock(struct pstream*p, uint32_t channel, int32_t delta, struct memchunk *chunk) { +void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk) { struct item_info *i; assert(p && channel != (uint32_t) -1 && chunk); i = malloc(sizeof(struct item_info)); assert(i); - i->type = PSTREAM_ITEM_MEMBLOCK; + i->type = PA_PSTREAM_ITEM_MEMBLOCK; i->chunk = *chunk; i->channel = channel; i->delta = delta; - memblock_ref(i->chunk.memblock); + pa_memblock_ref(i->chunk.memblock); - queue_push(p->send_queue, i); + pa_queue_push(p->send_queue, i); p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1); } -void pstream_set_recieve_packet_callback(struct pstream *p, int (*callback) (struct pstream *p, struct packet *packet, void *userdata), void *userdata) { +void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, int (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata) { assert(p && callback); p->recieve_packet_callback = callback; p->recieve_packet_callback_userdata = userdata; } -void pstream_set_recieve_memblock_callback(struct pstream *p, int (*callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata), void *userdata) { +void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, int (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata), void *userdata) { assert(p && callback); p->recieve_memblock_callback = callback; p->recieve_memblock_callback_userdata = userdata; } -static void prepare_next_write_item(struct pstream *p) { +static void prepare_next_write_item(struct pa_pstream *p) { assert(p); - if (!(p->write.current = queue_pop(p->send_queue))) + if (!(p->write.current = pa_queue_pop(p->send_queue))) return; p->write.index = 0; - if (p->write.current->type == PSTREAM_ITEM_PACKET) { + if (p->write.current->type == PA_PSTREAM_ITEM_PACKET) { assert(p->write.current->packet); p->write.data = p->write.current->packet->data; - p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length); - p->write.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1); - p->write.descriptor[PSTREAM_DESCRIPTOR_DELTA] = 0; + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA] = 0; } else { - assert(p->write.current->type == PSTREAM_ITEM_MEMBLOCK && p->write.current->chunk.memblock); + assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK && p->write.current->chunk.memblock); p->write.data = p->write.current->chunk.memblock->data + p->write.current->chunk.index; - p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); - p->write.descriptor[PSTREAM_DESCRIPTOR_CHANNEL] = htonl(p->write.current->channel); - p->write.descriptor[PSTREAM_DESCRIPTOR_DELTA] = htonl(p->write.current->delta); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl(p->write.current->channel); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA] = htonl(p->write.current->delta); } } -static void do_write(struct pstream *p) { +static void do_write(struct pa_pstream *p) { void *d; size_t l; ssize_t r; assert(p); - if (p->dead || !iochannel_is_writable(p->io)) + if (p->dead || !pa_iochannel_is_writable(p->io)) return; if (!p->write.current) @@ -253,25 +253,25 @@ static void do_write(struct pstream *p) { assert(p->write.data); - if (p->write.index < PSTREAM_DESCRIPTOR_SIZE) { + if (p->write.index < PA_PSTREAM_DESCRIPTOR_SIZE) { d = (void*) p->write.descriptor + p->write.index; - l = PSTREAM_DESCRIPTOR_SIZE - p->write.index; + l = PA_PSTREAM_DESCRIPTOR_SIZE - p->write.index; } else { - d = (void*) p->write.data + p->write.index - PSTREAM_DESCRIPTOR_SIZE; - l = ntohl(p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PSTREAM_DESCRIPTOR_SIZE); + d = (void*) p->write.data + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; + l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } - if ((r = iochannel_write(p->io, d, l)) < 0) + if ((r = pa_iochannel_write(p->io, d, l)) < 0) goto die; p->write.index += r; - if (p->write.index >= PSTREAM_DESCRIPTOR_SIZE+ntohl(p->write.descriptor[PSTREAM_DESCRIPTOR_LENGTH])) { + if (p->write.index >= PA_PSTREAM_DESCRIPTOR_SIZE+ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])) { assert(p->write.current); item_free(p->write.current, (void *) 1); p->write.current = NULL; - if (p->send_callback && queue_is_empty(p->send_queue)) + if (p->send_callback && pa_queue_is_empty(p->send_queue)) p->send_callback(p, p->send_callback_userdata); } @@ -283,68 +283,68 @@ die: p->die_callback(p, p->die_callback_userdata); } -static void do_read(struct pstream *p) { +static void do_read(struct pa_pstream *p) { void *d; size_t l; ssize_t r; assert(p); - if (p->dead || !iochannel_is_readable(p->io)) + if (p->dead || !pa_iochannel_is_readable(p->io)) return; - if (p->read.index < PSTREAM_DESCRIPTOR_SIZE) { + if (p->read.index < PA_PSTREAM_DESCRIPTOR_SIZE) { d = (void*) p->read.descriptor + p->read.index; - l = PSTREAM_DESCRIPTOR_SIZE - p->read.index; + l = PA_PSTREAM_DESCRIPTOR_SIZE - p->read.index; } else { assert(p->read.data); - d = (void*) p->read.data + p->read.index - PSTREAM_DESCRIPTOR_SIZE; - l = ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PSTREAM_DESCRIPTOR_SIZE); + d = (void*) p->read.data + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE; + l = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE); } - if ((r = iochannel_read(p->io, d, l)) <= 0) + if ((r = pa_iochannel_read(p->io, d, l)) <= 0) goto die; p->read.index += r; - if (p->read.index == PSTREAM_DESCRIPTOR_SIZE) { + if (p->read.index == PA_PSTREAM_DESCRIPTOR_SIZE) { /* Reading of frame descriptor complete */ /* Frame size too large */ - if (ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) > FRAME_SIZE_MAX) + if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) > FRAME_SIZE_MAX) goto die; assert(!p->read.packet && !p->read.memblock); - if (ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_CHANNEL]) == (uint32_t) -1) { + if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]) == (uint32_t) -1) { /* Frame is a packet frame */ - p->read.packet = packet_new(ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH])); + p->read.packet = pa_packet_new(ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])); assert(p->read.packet); p->read.data = p->read.packet->data; } else { /* Frame is a memblock frame */ - p->read.memblock = memblock_new(ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH])); + p->read.memblock = pa_memblock_new(ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])); assert(p->read.memblock); p->read.data = p->read.memblock->data; } - } else if (p->read.index > PSTREAM_DESCRIPTOR_SIZE) { + } else if (p->read.index > PA_PSTREAM_DESCRIPTOR_SIZE) { /* Frame payload available */ if (p->read.memblock && p->recieve_memblock_callback) { /* Is this memblock data? Than pass it to the user */ size_t l; - l = (p->read.index - r) < PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PSTREAM_DESCRIPTOR_SIZE : (size_t) r; + l = (p->read.index - r) < PA_PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE : (size_t) r; if (l > 0) { - struct memchunk chunk; + struct pa_memchunk chunk; chunk.memblock = p->read.memblock; - chunk.index = p->read.index - PSTREAM_DESCRIPTOR_SIZE - l; + chunk.index = p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE - l; chunk.length = l; if (p->recieve_memblock_callback(p, - ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_CHANNEL]), - (int32_t) ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_DELTA]), + ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]), + (int32_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA]), &chunk, p->recieve_memblock_callback_userdata) < 0) goto die; @@ -352,11 +352,11 @@ static void do_read(struct pstream *p) { } /* Frame complete */ - if (p->read.index >= ntohl(p->read.descriptor[PSTREAM_DESCRIPTOR_LENGTH]) + PSTREAM_DESCRIPTOR_SIZE) { + if (p->read.index >= ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) + PA_PSTREAM_DESCRIPTOR_SIZE) { if (p->read.memblock) { assert(!p->read.packet); - memblock_unref(p->read.memblock); + pa_memblock_unref(p->read.memblock); p->read.memblock = NULL; } else { int r = 0; @@ -365,7 +365,7 @@ static void do_read(struct pstream *p) { if (p->recieve_packet_callback) r = p->recieve_packet_callback(p, p->read.packet, p->recieve_packet_callback_userdata); - packet_unref(p->read.packet); + pa_packet_unref(p->read.packet); p->read.packet = NULL; if (r < 0) @@ -385,7 +385,7 @@ die: } -void pstream_set_die_callback(struct pstream *p, void (*callback)(struct pstream *p, void *userdata), void *userdata) { +void pa_pstream_set_die_callback(struct pa_pstream *p, void (*callback)(struct pa_pstream *p, void *userdata), void *userdata) { assert(p && callback); p->die_callback = callback; p->die_callback_userdata = userdata; diff --git a/src/pstream.h b/src/pstream.h index a623156aa..0f5975d26 100644 --- a/src/pstream.h +++ b/src/pstream.h @@ -9,18 +9,18 @@ #include "mainloop-api.h" #include "memchunk.h" -struct pstream; +struct pa_pstream; -struct pstream* pstream_new(struct pa_mainloop_api *m, struct iochannel *io); -void pstream_free(struct pstream*p); +struct pa_pstream* pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io); +void pa_pstream_free(struct pa_pstream*p); -void pstream_set_send_callback(struct pstream*p, void (*callback) (struct pstream *p, void *userdata), void *userdata); -void pstream_send_packet(struct pstream*p, struct packet *packet); -void pstream_send_memblock(struct pstream*p, uint32_t channel, int32_t delta, struct memchunk *chunk); +void pa_pstream_set_send_callback(struct pa_pstream*p, void (*callback) (struct pa_pstream *p, void *userdata), void *userdata); +void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet); +void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk); -void pstream_set_recieve_packet_callback(struct pstream *p, int (*callback) (struct pstream *p, struct packet *packet, void *userdata), void *userdata); -void pstream_set_recieve_memblock_callback(struct pstream *p, int (*callback) (struct pstream *p, uint32_t channel, int32_t delta, struct memchunk *chunk, void *userdata), void *userdata); +void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, int (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata); +void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, int (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata), void *userdata); -void pstream_set_die_callback(struct pstream *p, void (*callback)(struct pstream *p, void *userdata), void *userdata); +void pa_pstream_set_die_callback(struct pa_pstream *p, void (*callback)(struct pa_pstream *p, void *userdata), void *userdata); #endif diff --git a/src/queue.c b/src/queue.c index 5c2e7a67d..9e775f440 100644 --- a/src/queue.c +++ b/src/queue.c @@ -8,20 +8,20 @@ struct queue_entry { void *data; }; -struct queue { +struct pa_queue { struct queue_entry *front, *back; unsigned length; }; -struct queue* queue_new(void) { - struct queue *q = malloc(sizeof(struct queue)); +struct pa_queue* pa_queue_new(void) { + struct pa_queue *q = malloc(sizeof(struct pa_queue)); assert(q); q->front = q->back = NULL; q->length = 0; return q; } -void queue_free(struct queue* q, void (*destroy)(void *p, void *userdata), void *userdata) { +void pa_queue_free(struct pa_queue* q, void (*destroy)(void *p, void *userdata), void *userdata) { struct queue_entry *e; assert(q); @@ -39,7 +39,7 @@ void queue_free(struct queue* q, void (*destroy)(void *p, void *userdata), void free(q); } -void queue_push(struct queue *q, void *p) { +void pa_queue_push(struct pa_queue *q, void *p) { struct queue_entry *e; e = malloc(sizeof(struct queue_entry)); @@ -58,7 +58,7 @@ void queue_push(struct queue *q, void *p) { q->length++; } -void* queue_pop(struct queue *q) { +void* pa_queue_pop(struct pa_queue *q) { void *p; struct queue_entry *e; assert(q); @@ -78,7 +78,7 @@ void* queue_pop(struct queue *q) { return p; } -int queue_is_empty(struct queue *q) { +int pa_queue_is_empty(struct pa_queue *q) { assert(q); return q->length == 0; } diff --git a/src/queue.h b/src/queue.h index 6b371a81c..e06d69cb1 100644 --- a/src/queue.h +++ b/src/queue.h @@ -1,13 +1,13 @@ #ifndef fooqueuehfoo #define fooqueuehfoo -struct queue; +struct pa_queue; -struct queue* queue_new(void); -void queue_free(struct queue* q, void (*destroy)(void *p, void *userdata), void *userdata); -void queue_push(struct queue *q, void *p); -void* queue_pop(struct queue *q); +struct pa_queue* pa_queue_new(void); +void pa_queue_free(struct pa_queue* q, void (*destroy)(void *p, void *userdata), void *userdata); +void pa_queue_push(struct pa_queue *q, void *p); +void* pa_queue_pop(struct pa_queue *q); -int queue_is_empty(struct queue *q); +int pa_queue_is_empty(struct pa_queue *q); #endif diff --git a/src/resampler.c b/src/resampler.c index c2d791741..67823e450 100644 --- a/src/resampler.c +++ b/src/resampler.c @@ -6,7 +6,7 @@ #include "resampler.h" #include "sconv.h" -struct resampler { +struct pa_resampler { struct pa_sample_spec i_ss, o_ss; float* i_buf, *o_buf; unsigned i_alloc, o_alloc; @@ -14,13 +14,13 @@ struct resampler { int channels; - convert_to_float32_func_t to_float32_func; - convert_from_float32_func_t from_float32_func; + pa_convert_to_float32_func_t to_float32_func; + pa_convert_from_float32_func_t from_float32_func; SRC_STATE *src_state; }; -struct resampler* resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b) { - struct resampler *r; +struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b) { + struct pa_resampler *r; int err; assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b)); @@ -30,7 +30,7 @@ struct resampler* resampler_new(const struct pa_sample_spec *a, const struct pa_ if (a->format == PA_SAMPLE_ALAW || a->format == PA_SAMPLE_ULAW || b->format == PA_SAMPLE_ALAW || b->format == PA_SAMPLE_ULAW) goto fail; - r = malloc(sizeof(struct resampler)); + r = malloc(sizeof(struct pa_resampler)); assert(r); r->channels = a->channels; @@ -53,8 +53,8 @@ struct resampler* resampler_new(const struct pa_sample_spec *a, const struct pa_ r->i_sz = pa_sample_size(a); r->o_sz = pa_sample_size(b); - r->to_float32_func = get_convert_to_float32_function(a->format); - r->from_float32_func = get_convert_from_float32_function(b->format); + r->to_float32_func = pa_get_convert_to_float32_function(a->format); + r->from_float32_func = pa_get_convert_from_float32_function(b->format); assert(r->to_float32_func && r->from_float32_func); @@ -67,7 +67,7 @@ fail: return NULL; } -void resampler_free(struct resampler *r) { +void pa_resampler_free(struct pa_resampler *r) { assert(r); if (r->src_state) src_delete(r->src_state); @@ -76,14 +76,14 @@ void resampler_free(struct resampler *r) { free(r); } -size_t resampler_request(struct resampler *r, size_t out_length) { +size_t pa_resampler_request(struct pa_resampler *r, size_t out_length) { assert(r && (out_length % r->o_sz) == 0); return (((out_length / r->o_sz)*r->i_ss.rate)/r->o_ss.rate) * r->i_sz; } -void resampler_run(struct resampler *r, const struct memchunk *in, struct memchunk *out) { +void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out) { unsigned i_nchannels, o_nchannels, ins, ons, eff_ins, eff_ons; float *cbuf; assert(r && in && out && in->length && in->memblock && (in->length % r->i_sz) == 0); @@ -109,7 +109,7 @@ void resampler_run(struct resampler *r, const struct memchunk *in, struct memchu eff_ons = ons; } - out->memblock = memblock_new(out->length = (ons*r->o_sz)); + out->memblock = pa_memblock_new(out->length = (ons*r->o_sz)); out->index = 0; assert(out->memblock); diff --git a/src/resampler.h b/src/resampler.h index 257ba6628..1d42b3658 100644 --- a/src/resampler.h +++ b/src/resampler.h @@ -5,12 +5,12 @@ #include "memblock.h" #include "memchunk.h" -struct resampler; +struct pa_resampler; -struct resampler* resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b); -void resampler_free(struct resampler *r); +struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b); +void pa_resampler_free(struct pa_resampler *r); -size_t resampler_request(struct resampler *r, size_t out_length); -void resampler_run(struct resampler *r, const struct memchunk *in, struct memchunk *out); +size_t pa_resampler_request(struct pa_resampler *r, size_t out_length); +void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out); #endif diff --git a/src/sample-util.c b/src/sample-util.c index 09511a3c1..f37ac78b6 100644 --- a/src/sample-util.c +++ b/src/sample-util.c @@ -4,26 +4,26 @@ #include "sample-util.h" -struct pa_sample_spec default_sample_spec = { +struct pa_sample_spec pa_default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 }; -struct memblock *silence_memblock(struct memblock* b, struct pa_sample_spec *spec) { +struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_sample_spec *spec) { assert(b && b->data && spec); - memblock_assert_exclusive(b); - silence_memory(b->data, b->length, spec); + pa_memblock_assert_exclusive(b); + pa_silence_memory(b->data, b->length, spec); return b; } -void silence_memchunk(struct memchunk *c, struct pa_sample_spec *spec) { +void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spec) { assert(c && c->memblock && c->memblock->data && spec && c->length); - memblock_assert_exclusive(c->memblock); - silence_memory(c->memblock->data+c->index, c->length, spec); + pa_memblock_assert_exclusive(c->memblock); + pa_silence_memory(c->memblock->data+c->index, c->length, spec); } -void silence_memory(void *p, size_t length, struct pa_sample_spec *spec) { +void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec) { char c = 0; assert(p && length && spec); @@ -47,7 +47,7 @@ void silence_memory(void *p, size_t length, struct pa_sample_spec *spec) { memset(p, c, length); } -size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct pa_sample_spec *spec, uint32_t volume) { +size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, uint32_t volume) { unsigned c, d; assert(channels && data && length && spec); assert(spec->format == PA_SAMPLE_S16NE); @@ -65,22 +65,22 @@ size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, si if (d >= channels[c].chunk.length) return d; - if (volume == VOLUME_MUTE) + if (volume == PA_VOLUME_MUTE) v = 0; else { v = *((int16_t*) (channels[c].chunk.memblock->data + channels[c].chunk.index + d)); - if (volume != VOLUME_NORM) - v = (int32_t) ((float)v*volume/VOLUME_NORM); + if (volume != PA_VOLUME_NORM) + v = (int32_t) ((float)v*volume/PA_VOLUME_NORM); } sum += v; } - if (volume == VOLUME_MUTE) + if (volume == PA_VOLUME_MUTE) sum = 0; - else if (volume != VOLUME_NORM) - sum = (int32_t) ((float) sum*volume/VOLUME_NORM); + else if (volume != PA_VOLUME_NORM) + sum = (int32_t) ((float) sum*volume/PA_VOLUME_NORM); if (sum < -0x8000) sum = -0x8000; if (sum > 0x7FFF) sum = 0x7FFF; @@ -91,18 +91,18 @@ size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, si } -void volume_memchunk(struct memchunk*c, struct pa_sample_spec *spec, uint32_t volume) { +void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, uint32_t volume) { int16_t *d; size_t n; assert(c && spec && (c->length % pa_sample_size(spec) == 0)); assert(spec->format == PA_SAMPLE_S16NE); - memblock_assert_exclusive(c->memblock); + pa_memblock_assert_exclusive(c->memblock); - if (volume == VOLUME_NORM) + if (volume == PA_VOLUME_NORM) return; - if (volume == VOLUME_MUTE) { - silence_memchunk(c, spec); + if (volume == PA_VOLUME_MUTE) { + pa_silence_memchunk(c, spec); return; } @@ -110,7 +110,7 @@ void volume_memchunk(struct memchunk*c, struct pa_sample_spec *spec, uint32_t vo int32_t t = (int32_t)(*d); t *= volume; - t /= VOLUME_NORM; + t /= PA_VOLUME_NORM; if (t < -0x8000) t = -0x8000; if (t > 0x7FFF) t = 0x7FFF; @@ -119,10 +119,10 @@ void volume_memchunk(struct memchunk*c, struct pa_sample_spec *spec, uint32_t vo } } -uint32_t volume_multiply(uint32_t a, uint32_t b) { +uint32_t pa_volume_multiply(uint32_t a, uint32_t b) { uint64_t p = a; p *= b; - p /= VOLUME_NORM; + p /= PA_VOLUME_NORM; return (uint32_t) p; } diff --git a/src/sample-util.h b/src/sample-util.h index bc51e5246..6a593b9a4 100644 --- a/src/sample-util.h +++ b/src/sample-util.h @@ -5,27 +5,27 @@ #include "memblock.h" #include "memchunk.h" -#define DEFAULT_SAMPLE_SPEC default_sample_spec +#define PA_DEFAULT_SAMPLE_SPEC pa_default_sample_spec -extern struct pa_sample_spec default_sample_spec; +extern struct pa_sample_spec pa_default_sample_spec; -#define VOLUME_NORM (0x100) -#define VOLUME_MUTE (0) +#define PA_VOLUME_NORM (0x100) +#define PA_VOLUME_MUTE (0) -struct memblock *silence_memblock(struct memblock* b, struct pa_sample_spec *spec); -void silence_memchunk(struct memchunk *c, struct pa_sample_spec *spec); -void silence_memory(void *p, size_t length, struct pa_sample_spec *spec); +struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_sample_spec *spec); +void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spec); +void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec); -struct mix_info { - struct memchunk chunk; +struct pa_mix_info { + struct pa_memchunk chunk; uint32_t volume; void *userdata; }; -size_t mix_chunks(struct mix_info channels[], unsigned nchannels, void *data, size_t length, struct pa_sample_spec *spec, uint32_t volume); +size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, uint32_t volume); -void volume_memchunk(struct memchunk*c, struct pa_sample_spec *spec, uint32_t volume); +void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, uint32_t volume); -uint32_t volume_multiply(uint32_t a, uint32_t b); +uint32_t pa_volume_multiply(uint32_t a, uint32_t b); #endif diff --git a/src/sample.c b/src/sample.c index 706880e46..20142a236 100644 --- a/src/sample.c +++ b/src/sample.c @@ -1,3 +1,4 @@ +#include #include #include "sample.h" @@ -44,7 +45,7 @@ int pa_sample_spec_valid(const struct pa_sample_spec *spec) { if (!spec->rate || !spec->channels) return 0; - if (spec->format <= 0 || spec->format >= PA_SAMPLE_MAX) + if (spec->format >= PA_SAMPLE_MAX) return 0; return 1; @@ -55,3 +56,17 @@ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_s return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels); } + +void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { + static const char* const table[]= { + [PA_SAMPLE_U8] = "U8", + [PA_SAMPLE_ALAW] = "ALAW", + [PA_SAMPLE_ULAW] = "ULAW", + [PA_SAMPLE_S16LE] = "S16LE", + [PA_SAMPLE_S16BE] = "S16BE", + [PA_SAMPLE_FLOAT32] = "FLOAT32", + }; + + assert(pa_sample_spec_valid(spec)); + snprintf(s, l, "%s %uch %uHz", table[spec->format], spec->channels, spec->rate); +} diff --git a/src/sample.h b/src/sample.h index fcb0e6e12..4131992cd 100644 --- a/src/sample.h +++ b/src/sample.h @@ -32,4 +32,6 @@ uint32_t pa_samples_usec(size_t length, const struct pa_sample_spec *spec); int pa_sample_spec_valid(const struct pa_sample_spec *spec); int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b); +void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec); + #endif diff --git a/src/sconv-s16be.c b/src/sconv-s16be.c new file mode 100644 index 000000000..728a4a054 --- /dev/null +++ b/src/sconv-s16be.c @@ -0,0 +1,9 @@ +#include "sconv-s16be.h" + +#define INT16_FROM INT16_FROM_BE +#define INT16_TO INT16_TO_BE + +#define pa_sconv_s16le_to_float32 pa_sconv_s16be_to_float32 +#define pa_sconv_s16le_from_float32 pa_sconv_s16be_from_float32 + +#include "sconv-s16le.c" diff --git a/src/sconv-s16be.h b/src/sconv-s16be.h new file mode 100644 index 000000000..257393c6f --- /dev/null +++ b/src/sconv-s16be.h @@ -0,0 +1,7 @@ +#ifndef foosconv_s16befoo +#define foosconv_s16befoo + +void pa_sconv_s16be_to_float32(unsigned n, const void *a, unsigned an, float *b); +void pa_sconv_s16be_from_float32(unsigned n, const float *a, void *b, unsigned bn); + +#endif diff --git a/src/sconv-s16le.c b/src/sconv-s16le.c new file mode 100644 index 000000000..ca9844633 --- /dev/null +++ b/src/sconv-s16le.c @@ -0,0 +1,57 @@ +#include +#include + +#include "endianmacros.h" +#include "sconv.h" + +#ifndef INT16_FROM +#define INT16_FROM INT16_FROM_LE +#endif + +#ifndef INT16_TO +#define INT16_TO INT16_TO_LE +#endif + +void pa_sconv_s16le_to_float32(unsigned n, const void *a, unsigned an, float *b) { + const int16_t *ca = a; + assert(n && a && an && b); + + for (; n > 0; n--) { + unsigned i; + float sum = 0; + + for (i = 0; i < an; i++) { + int16_t s = *(ca++); + sum += ((float) INT16_FROM(s))/0x7FFF; + } + + if (sum > 1) + sum = 1; + if (sum < -1) + sum = -1; + + *(b++) = sum; + } +} + +void pa_sconv_s16le_from_float32(unsigned n, const float *a, void *b, unsigned bn) { + int16_t *cb = b; + assert(n && a && b && bn); + + for (; n > 0; n--) { + unsigned i; + int16_t s; + float v = *(a++); + + if (v > 1) + v = 1; + if (v < -1) + v = -1; + + s = (int16_t) (v * 0x7FFF); + s = INT16_TO(s); + + for (i = 0; i < bn; i++) + *(cb++) = s; + } +} diff --git a/src/sconv-s16le.h b/src/sconv-s16le.h new file mode 100644 index 000000000..cfbf81fda --- /dev/null +++ b/src/sconv-s16le.h @@ -0,0 +1,7 @@ +#ifndef foosconv_s16lefoo +#define foosconv_s16lefoo + +void pa_sconv_s16le_to_float32(unsigned n, const void *a, unsigned an, float *b); +void pa_sconv_s16le_from_float32(unsigned n, const float *a, void *b, unsigned bn); + +#endif diff --git a/src/sconv.c b/src/sconv.c index 11438b410..6dd165a44 100644 --- a/src/sconv.c +++ b/src/sconv.c @@ -1,48 +1,53 @@ +#include #include #include #include "endianmacros.h" #include "sconv.h" -static void s16le_to_float32(unsigned n, const void *a, unsigned an, float *b) { - const int16_t *ca = a; +#include "sconv-s16le.h" +#include "sconv-s16be.h" + +static void u8_to_float32(unsigned n, const void *a, unsigned an, float *b) { + unsigned i; + const uint8_t *ca = a; assert(n && a && an && b); for (; n > 0; n--) { - unsigned i; float sum = 0; - + for (i = 0; i < an; i++) { - int16_t s = *(ca++); - sum += ((float) INT16_FROM_LE(s))/0x7FFF; + uint8_t v = *(ca++); + sum += (((float) v)-127)/127; } if (sum > 1) sum = 1; if (sum < -1) sum = -1; - + *(b++) = sum; } -} +} + +static void u8_from_float32(unsigned n, const float *a, void *b, unsigned bn) { + unsigned i; + uint8_t *cb = b; -static void s16le_from_float32(unsigned n, const float *a, void *b, unsigned bn) { - int16_t *cb = b; assert(n && a && b && bn); - for (; n > 0; n--) { - unsigned i; - int16_t s; float v = *(a++); + uint8_t u; if (v > 1) v = 1; + if (v < -1) v = -1; - - s = (int16_t) (v * 0x7FFF); + u = (uint8_t) (v*127+127); + for (i = 0; i < bn; i++) - *(cb++) = INT16_TO_LE(v); + *(cb++) = u; } } @@ -76,10 +81,14 @@ static void float32_from_float32(unsigned n, const float *a, void *b, unsigned b } } -convert_to_float32_func_t get_convert_to_float32_function(enum pa_sample_format f) { +pa_convert_to_float32_func_t pa_get_convert_to_float32_function(enum pa_sample_format f) { switch(f) { + case PA_SAMPLE_U8: + return u8_to_float32; case PA_SAMPLE_S16LE: - return s16le_to_float32; + return pa_sconv_s16le_to_float32; + case PA_SAMPLE_S16BE: + return pa_sconv_s16be_to_float32; case PA_SAMPLE_FLOAT32: return float32_to_float32; default: @@ -87,10 +96,14 @@ convert_to_float32_func_t get_convert_to_float32_function(enum pa_sample_format } } -convert_from_float32_func_t get_convert_from_float32_function(enum pa_sample_format f) { +pa_convert_from_float32_func_t pa_get_convert_from_float32_function(enum pa_sample_format f) { switch(f) { + case PA_SAMPLE_U8: + return u8_from_float32; case PA_SAMPLE_S16LE: - return s16le_from_float32; + return pa_sconv_s16le_from_float32; + case PA_SAMPLE_S16BE: + return pa_sconv_s16be_from_float32; case PA_SAMPLE_FLOAT32: return float32_from_float32; default: diff --git a/src/sconv.h b/src/sconv.h index 8667d2ae1..e16f2dcc5 100644 --- a/src/sconv.h +++ b/src/sconv.h @@ -3,12 +3,10 @@ #include "sample.h" -typedef void (*convert_to_float32_func_t)(unsigned n, const void *a, unsigned an, float *b); -typedef void (*convert_from_float32_func_t)(unsigned n, const float *a, void *b, unsigned bn); - -convert_to_float32_func_t get_convert_to_float32_function(enum pa_sample_format f); -convert_from_float32_func_t get_convert_from_float32_function(enum pa_sample_format f); - +typedef void (*pa_convert_to_float32_func_t)(unsigned n, const void *a, unsigned an, float *b); +typedef void (*pa_convert_from_float32_func_t)(unsigned n, const float *a, void *b, unsigned bn); +pa_convert_to_float32_func_t pa_get_convert_to_float32_function(enum pa_sample_format f); +pa_convert_from_float32_func_t pa_get_convert_from_float32_function(enum pa_sample_format f); #endif diff --git a/src/sink.c b/src/sink.c index 2ecb64452..53ebb8bff 100644 --- a/src/sink.c +++ b/src/sink.c @@ -11,16 +11,17 @@ #define MAX_MIX_CHANNELS 32 -struct sink* sink_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec) { - struct sink *s; +struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) { + struct pa_sink *s; char *n = NULL; + char st[256]; int r; assert(core && spec); - s = malloc(sizeof(struct sink)); + s = malloc(sizeof(struct pa_sink)); assert(s); - if (!(name = namereg_register(core, name, NAMEREG_SINK, s, fail))) { + if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) { free(s); return NULL; } @@ -28,46 +29,47 @@ struct sink* sink_new(struct core *core, const char *name, int fail, const struc s->name = strdup(name); s->core = core; s->sample_spec = *spec; - s->inputs = idxset_new(NULL, NULL); + s->inputs = pa_idxset_new(NULL, NULL); if (name) { n = malloc(strlen(name)+9); sprintf(n, "%s_monitor", name); } - s->monitor_source = source_new(core, n, 0, spec); + s->monitor_source = pa_source_new(core, n, 0, spec); assert(s->monitor_source); free(n); - s->volume = VOLUME_NORM; + s->volume = PA_VOLUME_NORM; s->notify = NULL; s->get_latency = NULL; s->userdata = NULL; - r = idxset_put(core->sinks, s, &s->index); - assert(s->index != IDXSET_INVALID && r >= 0); + r = pa_idxset_put(core->sinks, s, &s->index); + assert(s->index != PA_IDXSET_INVALID && r >= 0); - fprintf(stderr, "sink: created %u \"%s\".\n", s->index, s->name); + pa_sample_snprint(st, sizeof(st), spec); + fprintf(stderr, "sink: created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); return s; } -void sink_free(struct sink *s) { - struct sink_input *i, *j = NULL; +void pa_sink_free(struct pa_sink *s) { + struct pa_sink_input *i, *j = NULL; assert(s); - namereg_unregister(s->core, s->name); + pa_namereg_unregister(s->core, s->name); - while ((i = idxset_first(s->inputs, NULL))) { + while ((i = pa_idxset_first(s->inputs, NULL))) { assert(i != j); - sink_input_kill(i); + pa_sink_input_kill(i); j = i; } - idxset_free(s->inputs, NULL, NULL); + pa_idxset_free(s->inputs, NULL, NULL); - source_free(s->monitor_source); - idxset_remove_by_data(s->core->sinks, s, NULL); + pa_source_free(s->monitor_source); + pa_idxset_remove_by_data(s->core->sinks, s, NULL); fprintf(stderr, "sink: freed %u \"%s\"\n", s->index, s->name); @@ -75,22 +77,22 @@ void sink_free(struct sink *s) { free(s); } -void sink_notify(struct sink*s) { +void pa_sink_notify(struct pa_sink*s) { assert(s); if (s->notify) s->notify(s); } -static unsigned fill_mix_info(struct sink *s, struct mix_info *info, unsigned maxinfo) { - uint32_t index = IDXSET_INVALID; - struct sink_input *i; +static unsigned fill_mix_info(struct pa_sink *s, struct pa_mix_info *info, unsigned maxinfo) { + uint32_t index = PA_IDXSET_INVALID; + struct pa_sink_input *i; unsigned n = 0; assert(s && info); - for (i = idxset_first(s->inputs, &index); maxinfo > 0 && i; i = idxset_next(s->inputs, &index)) { - if (sink_input_peek(i, &info->chunk) < 0) + for (i = pa_idxset_first(s->inputs, &index); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &index)) { + if (pa_sink_input_peek(i, &info->chunk) < 0) continue; info->volume = i->volume; @@ -106,20 +108,20 @@ static unsigned fill_mix_info(struct sink *s, struct mix_info *info, unsigned ma return n; } -static void inputs_drop(struct sink *s, struct mix_info *info, unsigned maxinfo, size_t length) { +static void inputs_drop(struct pa_sink *s, struct pa_mix_info *info, unsigned maxinfo, size_t length) { assert(s && info); for (; maxinfo > 0; maxinfo--, info++) { - struct sink_input *i = info->userdata; + struct pa_sink_input *i = info->userdata; assert(i && info->chunk.memblock); - memblock_unref(info->chunk.memblock); - sink_input_drop(i, length); + pa_memblock_unref(info->chunk.memblock); + pa_sink_input_drop(i, length); } } -int sink_render(struct sink*s, size_t length, struct memchunk *result) { - struct mix_info info[MAX_MIX_CHANNELS]; +int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) { + struct pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; size_t l; assert(s && length && result); @@ -130,29 +132,29 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result) { return -1; if (n == 1) { - uint32_t volume = VOLUME_NORM; - struct sink_info *i = info[0].userdata; + uint32_t volume = PA_VOLUME_NORM; + struct pa_sink_input *i = info[0].userdata; assert(i); *result = info[0].chunk; - memblock_ref(result->memblock); + pa_memblock_ref(result->memblock); if (result->length > length) result->length = length; l = result->length; - if (s->volume != VOLUME_NORM || info[0].volume != VOLUME_NORM) - volume = volume_multiply(s->volume, info[0].volume); + if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM) + volume = pa_volume_multiply(s->volume, info[0].volume); - if (volume != VOLUME_NORM) { - memchunk_make_writable(result); - volume_memchunk(result, &s->sample_spec, volume); + if (volume != PA_VOLUME_NORM) { + pa_memchunk_make_writable(result); + pa_volume_memchunk(result, &s->sample_spec, volume); } } else { - result->memblock = memblock_new(length); + result->memblock = pa_memblock_new(length); assert(result->memblock); - result->length = l = mix_chunks(info, n, result->memblock->data, length, &s->sample_spec, s->volume); + result->length = l = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, s->volume); result->index = 0; assert(l); @@ -161,17 +163,17 @@ int sink_render(struct sink*s, size_t length, struct memchunk *result) { inputs_drop(s, info, n, l); assert(s->monitor_source); - source_post(s->monitor_source, result); + pa_source_post(s->monitor_source, result); return 0; } -int sink_render_into(struct sink*s, struct memchunk *target) { - struct mix_info info[MAX_MIX_CHANNELS]; +int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) { + struct pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; size_t l; assert(s && target && target->length && target->memblock && target->memblock->data); - memblock_assert_exclusive(target->memblock); + pa_memblock_assert_exclusive(target->memblock); n = fill_mix_info(s, info, MAX_MIX_CHANNELS); @@ -179,8 +181,8 @@ int sink_render_into(struct sink*s, struct memchunk *target) { return -1; if (n == 1) { - uint32_t volume = VOLUME_NORM; - struct sink_info *i = info[0].userdata; + uint32_t volume = PA_VOLUME_NORM; + struct pa_sink_info *i = info[0].userdata; assert(i); l = target->length; @@ -190,25 +192,25 @@ int sink_render_into(struct sink*s, struct memchunk *target) { memcpy(target->memblock->data+target->index, info[0].chunk.memblock->data + info[0].chunk.index, l); target->length = l; - if (s->volume != VOLUME_NORM || info[0].volume != VOLUME_NORM) - volume = volume_multiply(s->volume, info[0].volume); + if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM) + volume = pa_volume_multiply(s->volume, info[0].volume); - if (volume != VOLUME_NORM) - volume_memchunk(target, &s->sample_spec, volume); + if (volume != PA_VOLUME_NORM) + pa_volume_memchunk(target, &s->sample_spec, volume); } else - target->length = l = mix_chunks(info, n, target->memblock->data+target->index, target->length, &s->sample_spec, s->volume); + target->length = l = pa_mix(info, n, target->memblock->data+target->index, target->length, &s->sample_spec, s->volume); assert(l); inputs_drop(s, info, n, l); assert(s->monitor_source); - source_post(s->monitor_source, target); + pa_source_post(s->monitor_source, target); return 0; } -void sink_render_into_full(struct sink *s, struct memchunk *target) { - struct memchunk chunk; +void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target) { + struct pa_memchunk chunk; size_t l, d; assert(s && target && target->memblock && target->length && target->memblock->data); @@ -219,7 +221,7 @@ void sink_render_into_full(struct sink *s, struct memchunk *target) { chunk.index += d; chunk.length -= d; - if (sink_render_into(s, &chunk) < 0) + if (pa_sink_render_into(s, &chunk) < 0) break; d += chunk.length; @@ -230,11 +232,11 @@ void sink_render_into_full(struct sink *s, struct memchunk *target) { chunk = *target; chunk.index += d; chunk.length -= d; - silence_memchunk(&chunk, &s->sample_spec); + pa_silence_memchunk(&chunk, &s->sample_spec); } } -uint32_t sink_get_latency(struct sink *s) { +uint32_t pa_sink_get_latency(struct pa_sink *s) { assert(s); if (!s->get_latency) @@ -243,38 +245,38 @@ uint32_t sink_get_latency(struct sink *s) { return s->get_latency(s); } -struct sink* sink_get_default(struct core *c) { - struct sink *sink; +struct pa_sink* pa_sink_get_default(struct pa_core *c) { + struct pa_sink *sink; assert(c); - if ((sink = idxset_get_by_index(c->sinks, c->default_sink_index))) + if ((sink = pa_idxset_get_by_index(c->sinks, c->default_sink_index))) return sink; - if (!(sink = idxset_first(c->sinks, &c->default_sink_index))) + if (!(sink = pa_idxset_first(c->sinks, &c->default_sink_index))) return NULL; fprintf(stderr, "core: default sink vanished, setting to %u.\n", sink->index); return sink; } -char *sink_list_to_string(struct core *c) { - struct strbuf *s; - struct sink *sink, *default_sink; - uint32_t index = IDXSET_INVALID; +char *pa_sink_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_sink *sink, *default_sink; + uint32_t index = PA_IDXSET_INVALID; assert(c); - s = strbuf_new(); + s = pa_strbuf_new(); assert(s); - strbuf_printf(s, "%u sink(s) available.\n", idxset_ncontents(c->sinks)); + pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_ncontents(c->sinks)); - default_sink = sink_get_default(c); + default_sink = pa_sink_get_default(c); - for (sink = idxset_first(c->sinks, &index); sink; sink = idxset_next(c->sinks, &index)) { + for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index)) { assert(sink->monitor_source); - strbuf_printf(s, " %c index: %u, name: <%s>, volume: <0x%04x>, latency: <%u usec>, monitor_source: <%u>\n", sink == default_sink ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, sink_get_latency(sink), sink->monitor_source->index); + pa_strbuf_printf(s, " %c index: %u, name: <%s>, volume: <0x%04x>, latency: <%u usec>, monitor_source: <%u>\n", sink == default_sink ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, pa_sink_get_latency(sink), sink->monitor_source->index); } - return strbuf_tostring_free(s); + return pa_strbuf_tostring_free(s); } diff --git a/src/sink.h b/src/sink.h index f251c0b96..7186f5312 100644 --- a/src/sink.h +++ b/src/sink.h @@ -1,7 +1,7 @@ #ifndef foosinkhfoo #define foosinkhfoo -struct sink; +struct pa_sink; #include @@ -10,37 +10,37 @@ struct sink; #include "idxset.h" #include "source.h" -struct sink { +struct pa_sink { uint32_t index; char *name; - struct core *core; + struct pa_core *core; struct pa_sample_spec sample_spec; - struct idxset *inputs; + struct pa_idxset *inputs; - struct source *monitor_source; + struct pa_source *monitor_source; uint32_t volume; - void (*notify)(struct sink*sink); - uint32_t (*get_latency)(struct sink *s); + void (*notify)(struct pa_sink*sink); + uint32_t (*get_latency)(struct pa_sink *s); void *userdata; }; -struct sink* sink_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec); -void sink_free(struct sink* s); +struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec); +void pa_sink_free(struct pa_sink* s); -int sink_render(struct sink*s, size_t length, struct memchunk *result); -int sink_render_into(struct sink*s, struct memchunk *target); -void sink_render_into_full(struct sink *s, struct memchunk *target); +int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result); +int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target); +void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target); -uint32_t sink_get_latency(struct sink *s); +uint32_t pa_sink_get_latency(struct pa_sink *s); -void sink_notify(struct sink*s); +void pa_sink_notify(struct pa_sink*s); -char *sink_list_to_string(struct core *core); +char *pa_sink_list_to_string(struct pa_core *core); -struct sink* sink_get_default(struct core *c); +struct pa_sink* pa_sink_get_default(struct pa_core *c); diff --git a/src/sinkinput.c b/src/sinkinput.c index c9614a5f6..aa6f33292 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -8,17 +9,18 @@ #define CONVERT_BUFFER_LENGTH 4096 -struct sink_input* sink_input_new(struct sink *s, const char *name, const struct pa_sample_spec *spec) { - struct sink_input *i; - struct resampler *resampler = NULL; +struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec) { + struct pa_sink_input *i; + struct pa_resampler *resampler = NULL; int r; + char st[256]; assert(s && spec); if (!pa_sample_spec_equal(spec, &s->sample_spec)) - if (!(resampler = resampler_new(spec, &s->sample_spec))) + if (!(resampler = pa_resampler_new(spec, &s->sample_spec))) return NULL; - i = malloc(sizeof(struct sink_input)); + i = malloc(sizeof(struct pa_sink_input)); assert(i); i->name = name ? strdup(name) : NULL; i->sink = s; @@ -30,69 +32,72 @@ struct sink_input* sink_input_new(struct sink *s, const char *name, const struct i->get_latency = NULL; i->userdata = NULL; - i->volume = VOLUME_NORM; + i->volume = PA_VOLUME_NORM; i->resampled_chunk.memblock = NULL; i->resampled_chunk.index = i->resampled_chunk.length = 0; i->resampler = resampler; assert(s->core); - r = idxset_put(s->core->sink_inputs, i, &i->index); - assert(r == 0 && i->index != IDXSET_INVALID); - r = idxset_put(s->inputs, i, NULL); + r = pa_idxset_put(s->core->sink_inputs, i, &i->index); + assert(r == 0 && i->index != PA_IDXSET_INVALID); + r = pa_idxset_put(s->inputs, i, NULL); assert(r == 0); + pa_sample_snprint(st, sizeof(st), spec); + fprintf(stderr, "sink-input: created %u \"%s\" on %u with sample spec \"%s\"\n", i->index, i->name, s->index, st); + return i; } -void sink_input_free(struct sink_input* i) { +void pa_sink_input_free(struct pa_sink_input* i) { assert(i); assert(i->sink && i->sink->core); - idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL); - idxset_remove_by_data(i->sink->inputs, i, NULL); + pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL); + pa_idxset_remove_by_data(i->sink->inputs, i, NULL); if (i->resampled_chunk.memblock) - memblock_unref(i->resampled_chunk.memblock); + pa_memblock_unref(i->resampled_chunk.memblock); if (i->resampler) - resampler_free(i->resampler); + pa_resampler_free(i->resampler); free(i->name); free(i); } -void sink_input_kill(struct sink_input*i) { +void pa_sink_input_kill(struct pa_sink_input*i) { assert(i); if (i->kill) i->kill(i); } -char *sink_input_list_to_string(struct core *c) { - struct strbuf *s; - struct sink_input *i; - uint32_t index = IDXSET_INVALID; +char *pa_sink_input_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_sink_input *i; + uint32_t index = PA_IDXSET_INVALID; assert(c); - s = strbuf_new(); + s = pa_strbuf_new(); assert(s); - strbuf_printf(s, "%u sink input(s) available.\n", idxset_ncontents(c->sink_inputs)); + pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_ncontents(c->sink_inputs)); - for (i = idxset_first(c->sink_inputs, &index); i; i = idxset_next(c->sink_inputs, &index)) { + for (i = pa_idxset_first(c->sink_inputs, &index); i; i = pa_idxset_next(c->sink_inputs, &index)) { assert(i->sink); - strbuf_printf(s, " index: %u, name: <%s>, sink: <%u>; volume: <0x%04x>, latency: <%u usec>\n", + pa_strbuf_printf(s, " index: %u, name: <%s>, sink: <%u>; volume: <0x%04x>, latency: <%u usec>\n", i->index, i->name, i->sink->index, (unsigned) i->volume, - sink_input_get_latency(i)); + pa_sink_input_get_latency(i)); } - return strbuf_tostring_free(s); + return pa_strbuf_tostring_free(s); } -uint32_t sink_input_get_latency(struct sink_input *i) { +uint32_t pa_sink_input_get_latency(struct pa_sink_input *i) { uint32_t l = 0; assert(i); @@ -100,43 +105,43 @@ uint32_t sink_input_get_latency(struct sink_input *i) { l += i->get_latency(i); assert(i->sink); - l += sink_get_latency(i->sink); + l += pa_sink_get_latency(i->sink); return l; } -int sink_input_peek(struct sink_input *i, struct memchunk *chunk) { +int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { assert(i && chunk && i->peek && i->drop); if (!i->resampler) return i->peek(i, chunk); if (!i->resampled_chunk.memblock) { - struct memchunk tchunk; + struct pa_memchunk tchunk; size_t l; int ret; if ((ret = i->peek(i, &tchunk)) < 0) return ret; - l = resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); + l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); if (tchunk.length > l) tchunk.length = l; i->drop(i, tchunk.length); - resampler_run(i->resampler, &tchunk, &i->resampled_chunk); - memblock_unref(tchunk.memblock); + pa_resampler_run(i->resampler, &tchunk, &i->resampled_chunk); + pa_memblock_unref(tchunk.memblock); } assert(i->resampled_chunk.memblock && i->resampled_chunk.length); *chunk = i->resampled_chunk; - memblock_ref(i->resampled_chunk.memblock); + pa_memblock_ref(i->resampled_chunk.memblock); return 0; } -void sink_input_drop(struct sink_input *i, size_t length) { +void pa_sink_input_drop(struct pa_sink_input *i, size_t length) { assert(i && length); if (!i->resampler) { @@ -150,7 +155,7 @@ void sink_input_drop(struct sink_input *i, size_t length) { i->resampled_chunk.length -= length; if (!i->resampled_chunk.length) { - memblock_unref(i->resampled_chunk.memblock); + pa_memblock_unref(i->resampled_chunk.memblock); i->resampled_chunk.memblock = NULL; i->resampled_chunk.index = i->resampled_chunk.length = 0; } diff --git a/src/sinkinput.h b/src/sinkinput.h index 8899a9edb..b28b51ef9 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -8,36 +8,36 @@ #include "memblockq.h" #include "resampler.h" -struct sink_input { +struct pa_sink_input { uint32_t index; char *name; - struct sink *sink; + struct pa_sink *sink; struct pa_sample_spec sample_spec; uint32_t volume; - int (*peek) (struct sink_input *i, struct memchunk *chunk); - void (*drop) (struct sink_input *i, size_t length); - void (*kill) (struct sink_input *i); - uint32_t (*get_latency) (struct sink_input *i); + int (*peek) (struct pa_sink_input *i, struct pa_memchunk *chunk); + void (*drop) (struct pa_sink_input *i, size_t length); + void (*kill) (struct pa_sink_input *i); + uint32_t (*get_latency) (struct pa_sink_input *i); void *userdata; - struct memchunk resampled_chunk; - struct resampler *resampler; + struct pa_memchunk resampled_chunk; + struct pa_resampler *resampler; }; -struct sink_input* sink_input_new(struct sink *s, const char *name, const struct pa_sample_spec *spec); -void sink_input_free(struct sink_input* i); +struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec); +void pa_sink_input_free(struct pa_sink_input* i); /* Code that didn't create the input stream should call this function to * request destruction of it */ -void sink_input_kill(struct sink_input *i); +void pa_sink_input_kill(struct pa_sink_input *i); -uint32_t sink_input_get_latency(struct sink_input *i); -char *sink_input_list_to_string(struct core *c); +uint32_t pa_sink_input_get_latency(struct pa_sink_input *i); +char *pa_sink_input_list_to_string(struct pa_core *c); -int sink_input_peek(struct sink_input *i, struct memchunk *chunk); -void sink_input_drop(struct sink_input *i, size_t length); +int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk); +void pa_sink_input_drop(struct pa_sink_input *i, size_t length); #endif diff --git a/src/socket-client.c b/src/socket-client.c index 95c76813e..6ff119800 100644 --- a/src/socket-client.c +++ b/src/socket-client.c @@ -11,20 +11,20 @@ #include "socket-client.h" #include "util.h" -struct socket_client { +struct pa_socket_client { struct pa_mainloop_api *mainloop; int fd; void *io_source, *fixed_source; - void (*callback)(struct socket_client*c, struct iochannel *io, void *userdata); + void (*callback)(struct pa_socket_client*c, struct pa_iochannel *io, void *userdata); void *userdata; }; -static struct socket_client*socket_client_new(struct pa_mainloop_api *m) { - struct socket_client *c; +static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { + struct pa_socket_client *c; assert(m); - c = malloc(sizeof(struct socket_client)); + c = malloc(sizeof(struct pa_socket_client)); assert(c); c->mainloop = m; c->fd = -1; @@ -34,8 +34,8 @@ static struct socket_client*socket_client_new(struct pa_mainloop_api *m) { return c; } -static void do_call(struct socket_client *c) { - struct iochannel *io; +static void do_call(struct pa_socket_client *c) { + struct pa_iochannel *io; int error, lerror; assert(c && c->callback); @@ -55,7 +55,7 @@ static void do_call(struct socket_client *c) { goto failed; } - io = iochannel_new(c->mainloop, c->fd, c->fd); + io = pa_iochannel_new(c->mainloop, c->fd, c->fd); assert(io); c->fd = -1; c->callback(c, io, c->userdata); @@ -70,7 +70,7 @@ failed: } static void connect_fixed_cb(struct pa_mainloop_api *m, void *id, void *userdata) { - struct socket_client *c = userdata; + struct pa_socket_client *c = userdata; assert(m && c && c->fixed_source == id); m->cancel_fixed(m, c->fixed_source); c->fixed_source = NULL; @@ -78,18 +78,18 @@ static void connect_fixed_cb(struct pa_mainloop_api *m, void *id, void *userdata } static void connect_io_cb(struct pa_mainloop_api*m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { - struct socket_client *c = userdata; + struct pa_socket_client *c = userdata; assert(m && c && c->io_source == id && fd >= 0 && events == PA_MAINLOOP_API_IO_EVENT_OUTPUT); m->cancel_io(m, c->io_source); c->io_source = NULL; do_call(c); } -static int do_connect(struct socket_client *c, const struct sockaddr *sa, socklen_t len) { +static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, socklen_t len) { int r; assert(c && sa && len); - make_nonblock_fd(c->fd); + pa_make_nonblock_fd(c->fd); if ((r = connect(c->fd, sa, len)) < 0) { if (r != EINPROGRESS) { @@ -107,12 +107,12 @@ static int do_connect(struct socket_client *c, const struct sockaddr *sa, sockle return 0; } -struct socket_client* socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port) { - struct socket_client *c; +struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port) { + struct pa_socket_client *c; struct sockaddr_in sa; assert(m && address && port); - c = socket_client_new(m); + c = pa_socket_client_new(m); assert(c); if ((c->fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { @@ -120,7 +120,7 @@ struct socket_client* socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t goto fail; } - make_tcp_socket_low_delay(c->fd); + pa_make_tcp_socket_low_delay(c->fd); sa.sin_family = AF_INET; sa.sin_port = htons(port); @@ -132,16 +132,16 @@ struct socket_client* socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t return c; fail: - socket_client_free(c); + pa_socket_client_free(c); return NULL; } -struct socket_client* socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) { - struct socket_client *c; +struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) { + struct pa_socket_client *c; struct sockaddr_un sa; assert(m && filename); - c = socket_client_new(m); + c = pa_socket_client_new(m); assert(c); if ((c->fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { @@ -149,7 +149,7 @@ struct socket_client* socket_client_new_unix(struct pa_mainloop_api *m, const ch goto fail; } - make_socket_low_delay(c->fd); + pa_make_socket_low_delay(c->fd); sa.sun_family = AF_LOCAL; strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); @@ -161,11 +161,11 @@ struct socket_client* socket_client_new_unix(struct pa_mainloop_api *m, const ch return c; fail: - socket_client_free(c); + pa_socket_client_free(c); return NULL; } -void socket_client_free(struct socket_client *c) { +void pa_socket_client_free(struct pa_socket_client *c) { assert(c && c->mainloop); if (c->io_source) c->mainloop->cancel_io(c->mainloop, c->io_source); @@ -176,7 +176,7 @@ void socket_client_free(struct socket_client *c) { free(c); } -void socket_client_set_callback(struct socket_client *c, void (*on_connection)(struct socket_client *c, struct iochannel*io, void *userdata), void *userdata) { +void pa_socket_client_set_callback(struct pa_socket_client *c, void (*on_connection)(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata), void *userdata) { assert(c); c->callback = on_connection; c->userdata = userdata; diff --git a/src/socket-client.h b/src/socket-client.h index 4de01e349..76126aee9 100644 --- a/src/socket-client.h +++ b/src/socket-client.h @@ -5,13 +5,13 @@ #include "mainloop-api.h" #include "iochannel.h" -struct socket_client; +struct pa_socket_client; -struct socket_client* socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); -struct socket_client* socket_client_new_unix(struct pa_mainloop_api *m, const char *filename); +struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); +struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename); -void socket_client_free(struct socket_client *c); +void pa_socket_client_free(struct pa_socket_client *c); -void socket_client_set_callback(struct socket_client *c, void (*on_connection)(struct socket_client *c, struct iochannel*io, void *userdata), void *userdata); +void pa_socket_client_set_callback(struct pa_socket_client *c, void (*on_connection)(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata), void *userdata); #endif diff --git a/src/socket-server.c b/src/socket-server.c index bd590f3cb..6a7d94157 100644 --- a/src/socket-server.c +++ b/src/socket-server.c @@ -13,20 +13,21 @@ #include "socket-server.h" #include "util.h" -struct socket_server { +struct pa_socket_server { int fd; char *filename; - void (*on_connection)(struct socket_server*s, struct iochannel *io, void *userdata); + void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata); void *userdata; void *mainloop_source; struct pa_mainloop_api *mainloop; + enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX } type; }; static void callback(struct pa_mainloop_api *mainloop, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { - struct socket_server *s = userdata; - struct iochannel *io; + struct pa_socket_server *s = userdata; + struct pa_iochannel *io; int nfd; assert(s && s->mainloop == mainloop && s->mainloop_source == id && id && fd >= 0 && fd == s->fd && events == PA_MAINLOOP_API_IO_EVENT_INPUT); @@ -41,18 +42,21 @@ static void callback(struct pa_mainloop_api *mainloop, void *id, int fd, enum pa } /* There should be a check for socket type here */ - make_tcp_socket_low_delay(fd); + if (s->type == SOCKET_SERVER_IPV4) + pa_make_tcp_socket_low_delay(fd); + else + pa_make_socket_low_delay(fd); - io = iochannel_new(s->mainloop, nfd, nfd); + io = pa_iochannel_new(s->mainloop, nfd, nfd); assert(io); s->on_connection(s, io, s->userdata); } -struct socket_server* socket_server_new(struct pa_mainloop_api *m, int fd) { - struct socket_server *s; +struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) { + struct pa_socket_server *s; assert(m && fd >= 0); - s = malloc(sizeof(struct socket_server)); + s = malloc(sizeof(struct pa_socket_server)); assert(s); s->fd = fd; s->filename = NULL; @@ -62,14 +66,16 @@ struct socket_server* socket_server_new(struct pa_mainloop_api *m, int fd) { s->mainloop = m; s->mainloop_source = m->source_io(m, fd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, s); assert(s->mainloop_source); + + s->type = SOCKET_SERVER_GENERIC; return s; } -struct socket_server* socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) { +struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) { int fd = -1; struct sockaddr_un sa; - struct socket_server *s; + struct pa_socket_server *s; assert(m && filename); @@ -82,7 +88,7 @@ struct socket_server* socket_server_new_unix(struct pa_mainloop_api *m, const ch strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); sa.sun_path[sizeof(sa.sun_path) - 1] = 0; - make_socket_low_delay(fd); + pa_make_socket_low_delay(fd); if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { fprintf(stderr, "bind(): %s\n", strerror(errno)); @@ -94,12 +100,14 @@ struct socket_server* socket_server_new_unix(struct pa_mainloop_api *m, const ch goto fail; } - s = socket_server_new(m, fd); + s = pa_socket_server_new(m, fd); assert(s); s->filename = strdup(filename); assert(s->filename); + s->type = SOCKET_SERVER_UNIX; + return s; fail: @@ -109,7 +117,8 @@ fail: return NULL; } -struct socket_server* socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port) { +struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port) { + struct pa_socket_server *ss; int fd = -1; struct sockaddr_in sa; int on = 1; @@ -124,7 +133,7 @@ struct socket_server* socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) fprintf(stderr, "setsockopt(): %s\n", strerror(errno)); - make_tcp_socket_low_delay(fd); + pa_make_tcp_socket_low_delay(fd); sa.sin_family = AF_INET; sa.sin_port = htons(port); @@ -140,7 +149,10 @@ struct socket_server* socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t goto fail; } - return socket_server_new(m, fd); + if ((ss = pa_socket_server_new(m, fd))) + ss->type = SOCKET_SERVER_IPV4; + + return ss; fail: if (fd >= 0) @@ -149,7 +161,7 @@ fail: return NULL; } -void socket_server_free(struct socket_server*s) { +void pa_socket_server_free(struct pa_socket_server*s) { assert(s); close(s->fd); @@ -164,7 +176,7 @@ void socket_server_free(struct socket_server*s) { free(s); } -void socket_server_set_callback(struct socket_server*s, void (*on_connection)(struct socket_server*s, struct iochannel *io, void *userdata), void *userdata) { +void pa_socket_server_set_callback(struct pa_socket_server*s, void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata), void *userdata) { assert(s); s->on_connection = on_connection; diff --git a/src/socket-server.h b/src/socket-server.h index 80895f8db..d581fa37d 100644 --- a/src/socket-server.h +++ b/src/socket-server.h @@ -5,14 +5,14 @@ #include "mainloop-api.h" #include "iochannel.h" -struct socket_server; +struct pa_socket_server; -struct socket_server* socket_server_new(struct pa_mainloop_api *m, int fd); -struct socket_server* socket_server_new_unix(struct pa_mainloop_api *m, const char *filename); -struct socket_server* socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); +struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd); +struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename); +struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); -void socket_server_free(struct socket_server*s); +void pa_socket_server_free(struct pa_socket_server*s); -void socket_server_set_callback(struct socket_server*s, void (*on_connection)(struct socket_server*s, struct iochannel *io, void *userdata), void *userdata); +void pa_socket_server_set_callback(struct pa_socket_server*s, void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata), void *userdata); #endif diff --git a/src/source.c b/src/source.c index f3eeb5169..9a4f95a26 100644 --- a/src/source.c +++ b/src/source.c @@ -8,15 +8,16 @@ #include "strbuf.h" #include "namereg.h" -struct source* source_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec) { - struct source *s; +struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) { + struct pa_source *s; + char st[256]; int r; assert(core && spec); - s = malloc(sizeof(struct source)); + s = malloc(sizeof(struct pa_source)); assert(s); - if (!(name = namereg_register(core, name, NAMEREG_SOURCE, s, fail))) { + if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) { free(s); return NULL; } @@ -24,33 +25,34 @@ struct source* source_new(struct core *core, const char *name, int fail, const s s->name = strdup(name); s->core = core; s->sample_spec = *spec; - s->outputs = idxset_new(NULL, NULL); + s->outputs = pa_idxset_new(NULL, NULL); s->notify = NULL; s->userdata = NULL; - r = idxset_put(core->sources, s, &s->index); - assert(s->index != IDXSET_INVALID && r >= 0); + r = pa_idxset_put(core->sources, s, &s->index); + assert(s->index != PA_IDXSET_INVALID && r >= 0); - fprintf(stderr, "source: created %u \"%s\"\n", s->index, s->name); + pa_sample_snprint(st, sizeof(st), spec); + fprintf(stderr, "source: created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); return s; } -void source_free(struct source *s) { - struct source_output *o, *j = NULL; +void pa_source_free(struct pa_source *s) { + struct pa_source_output *o, *j = NULL; assert(s); - namereg_unregister(s->core, s->name); + pa_namereg_unregister(s->core, s->name); - while ((o = idxset_first(s->outputs, NULL))) { + while ((o = pa_idxset_first(s->outputs, NULL))) { assert(o != j); - source_output_kill(o); + pa_source_output_kill(o); j = o; } - idxset_free(s->outputs, NULL, NULL); + pa_idxset_free(s->outputs, NULL, NULL); - idxset_remove_by_data(s->core->sources, s, NULL); + pa_idxset_remove_by_data(s->core->sources, s, NULL); fprintf(stderr, "source: freed %u \"%s\"\n", s->index, s->name); @@ -58,7 +60,7 @@ void source_free(struct source *s) { free(s); } -void source_notify(struct source*s) { +void pa_source_notify(struct pa_source*s) { assert(s); if (s->notify) @@ -66,50 +68,50 @@ void source_notify(struct source*s) { } static int do_post(void *p, uint32_t index, int *del, void*userdata) { - struct memchunk *chunk = userdata; - struct source_output *o = p; + struct pa_memchunk *chunk = userdata; + struct pa_source_output *o = p; assert(o && o->push && del && chunk); - source_output_push(o, chunk); + pa_source_output_push(o, chunk); return 0; } -void source_post(struct source*s, struct memchunk *chunk) { +void pa_source_post(struct pa_source*s, struct pa_memchunk *chunk) { assert(s && chunk); - idxset_foreach(s->outputs, do_post, chunk); + pa_idxset_foreach(s->outputs, do_post, chunk); } -struct source* source_get_default(struct core *c) { - struct source *source; +struct pa_source* pa_source_get_default(struct pa_core *c) { + struct pa_source *source; assert(c); - if ((source = idxset_get_by_index(c->sources, c->default_source_index))) + if ((source = pa_idxset_get_by_index(c->sources, c->default_source_index))) return source; - if (!(source = idxset_first(c->sources, &c->default_source_index))) + if (!(source = pa_idxset_first(c->sources, &c->default_source_index))) return NULL; fprintf(stderr, "core: default source vanished, setting to %u.\n", source->index); return source; } -char *source_list_to_string(struct core *c) { - struct strbuf *s; - struct source *source, *default_source; - uint32_t index = IDXSET_INVALID; +char *pa_source_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_source *source, *default_source; + uint32_t index = PA_IDXSET_INVALID; assert(c); - s = strbuf_new(); + s = pa_strbuf_new(); assert(s); - strbuf_printf(s, "%u source(s) available.\n", idxset_ncontents(c->sources)); + pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_ncontents(c->sources)); - default_source = source_get_default(c); + default_source = pa_source_get_default(c); - for (source = idxset_first(c->sources, &index); source; source = idxset_next(c->sources, &index)) - strbuf_printf(s, " %c index: %u, name: <%s>\n", source == default_source ? '*' : ' ', source->index, source->name); + for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) + pa_strbuf_printf(s, " %c index: %u, name: <%s>\n", source == default_source ? '*' : ' ', source->index, source->name); - return strbuf_tostring_free(s); + return pa_strbuf_tostring_free(s); } diff --git a/src/source.h b/src/source.h index 186271c05..03d540c82 100644 --- a/src/source.h +++ b/src/source.h @@ -1,7 +1,7 @@ #ifndef foosourcehfoo #define foosourcehfoo -struct source; +struct pa_source; #include #include "core.h" @@ -10,28 +10,28 @@ struct source; #include "memblock.h" #include "memchunk.h" -struct source { +struct pa_source { uint32_t index; char *name; - struct core *core; + struct pa_core *core; struct pa_sample_spec sample_spec; - struct idxset *outputs; + struct pa_idxset *outputs; - void (*notify)(struct source*source); + void (*notify)(struct pa_source*source); void *userdata; }; -struct source* source_new(struct core *core, const char *name, int fail, const struct pa_sample_spec *spec); -void source_free(struct source *s); +struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec); +void pa_source_free(struct pa_source *s); /* Pass a new memory block to all output streams */ -void source_post(struct source*s, struct memchunk *b); +void pa_source_post(struct pa_source*s, struct pa_memchunk *b); -void source_notify(struct source *s); +void pa_source_notify(struct pa_source *s); -char *source_list_to_string(struct core *c); +char *pa_source_list_to_string(struct pa_core *c); -struct source* source_get_default(struct core *c); +struct pa_source* pa_source_get_default(struct pa_core *c); #endif diff --git a/src/sourceoutput.c b/src/sourceoutput.c index e0ed07984..4f9f821bb 100644 --- a/src/sourceoutput.c +++ b/src/sourceoutput.c @@ -5,17 +5,17 @@ #include "sourceoutput.h" #include "strbuf.h" -struct source_output* source_output_new(struct source *s, const char *name, const struct pa_sample_spec *spec) { - struct source_output *o; - struct resampler *resampler = NULL; +struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec) { + struct pa_source_output *o; + struct pa_resampler *resampler = NULL; int r; assert(s && spec); if (!pa_sample_spec_equal(&s->sample_spec, spec)) - if (!(resampler = resampler_new(&s->sample_spec, spec))) + if (!(resampler = pa_resampler_new(&s->sample_spec, spec))) return NULL; - o = malloc(sizeof(struct source_output)); + o = malloc(sizeof(struct pa_source_output)); assert(o); o->name = name ? strdup(name) : NULL; o->source = s; @@ -27,59 +27,59 @@ struct source_output* source_output_new(struct source *s, const char *name, cons o->resampler = resampler; assert(s->core); - r = idxset_put(s->core->source_outputs, o, &o->index); - assert(r == 0 && o->index != IDXSET_INVALID); - r = idxset_put(s->outputs, o, NULL); + r = pa_idxset_put(s->core->source_outputs, o, &o->index); + assert(r == 0 && o->index != PA_IDXSET_INVALID); + r = pa_idxset_put(s->outputs, o, NULL); assert(r == 0); return o; } -void source_output_free(struct source_output* o) { +void pa_source_output_free(struct pa_source_output* o) { assert(o); assert(o->source && o->source->core); - idxset_remove_by_data(o->source->core->source_outputs, o, NULL); - idxset_remove_by_data(o->source->outputs, o, NULL); + pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL); + pa_idxset_remove_by_data(o->source->outputs, o, NULL); if (o->resampler) - resampler_free(o->resampler); + pa_resampler_free(o->resampler); free(o->name); free(o); } -void source_output_kill(struct source_output*i) { +void pa_source_output_kill(struct pa_source_output*i) { assert(i); if (i->kill) i->kill(i); } -char *source_output_list_to_string(struct core *c) { - struct strbuf *s; - struct source_output *o; - uint32_t index = IDXSET_INVALID; +char *pa_source_output_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_source_output *o; + uint32_t index = PA_IDXSET_INVALID; assert(c); - s = strbuf_new(); + s = pa_strbuf_new(); assert(s); - strbuf_printf(s, "%u source outputs(s) available.\n", idxset_ncontents(c->source_outputs)); + pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_ncontents(c->source_outputs)); - for (o = idxset_first(c->source_outputs, &index); o; o = idxset_next(c->source_outputs, &index)) { + for (o = pa_idxset_first(c->source_outputs, &index); o; o = pa_idxset_next(c->source_outputs, &index)) { assert(o->source); - strbuf_printf(s, " %c index: %u, name: <%s>, source: <%u>\n", - o->index, - o->name, - o->source->index); + pa_strbuf_printf(s, " %c index: %u, name: <%s>, source: <%u>\n", + o->index, + o->name, + o->source->index); } - return strbuf_tostring_free(s); + return pa_strbuf_tostring_free(s); } -void source_output_push(struct source_output *o, const struct memchunk *chunk) { - struct memchunk rchunk; +void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk *chunk) { + struct pa_memchunk rchunk; assert(o && chunk && chunk->length && o->push); if (!o->resampler) { @@ -87,11 +87,11 @@ void source_output_push(struct source_output *o, const struct memchunk *chunk) { return; } - resampler_run(o->resampler, chunk, &rchunk); + pa_resampler_run(o->resampler, chunk, &rchunk); if (!rchunk.length) return; assert(rchunk.memblock); o->push(o, &rchunk); - memblock_unref(rchunk.memblock); + pa_memblock_unref(rchunk.memblock); } diff --git a/src/sourceoutput.h b/src/sourceoutput.h index 4db2362de..fb60182a5 100644 --- a/src/sourceoutput.h +++ b/src/sourceoutput.h @@ -8,28 +8,28 @@ #include "memblockq.h" #include "resampler.h" -struct source_output { +struct pa_source_output { uint32_t index; char *name; - struct source *source; + struct pa_source *source; struct pa_sample_spec sample_spec; - void (*push)(struct source_output *o, const struct memchunk *chunk); - void (*kill)(struct source_output* o); + void (*push)(struct pa_source_output *o, const struct pa_memchunk *chunk); + void (*kill)(struct pa_source_output* o); - struct resampler* resampler; + struct pa_resampler* resampler; void *userdata; }; -struct source_output* source_output_new(struct source *s, const char *name, const struct pa_sample_spec *spec); -void source_output_free(struct source_output* o); +struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec); +void pa_source_output_free(struct pa_source_output* o); -void source_output_kill(struct source_output*o); +void pa_source_output_kill(struct pa_source_output*o); -char *source_output_list_to_string(struct core *c); +char *pa_source_output_list_to_string(struct pa_core *c); -void source_output_push(struct source_output *o, const struct memchunk *chunk); +void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk *chunk); #endif diff --git a/src/strbuf.c b/src/strbuf.c index 9ce67ec30..c2a6518ea 100644 --- a/src/strbuf.c +++ b/src/strbuf.c @@ -11,20 +11,20 @@ struct chunk { char text[]; }; -struct strbuf { +struct pa_strbuf { size_t length; struct chunk *head, *tail; }; -struct strbuf *strbuf_new(void) { - struct strbuf *sb = malloc(sizeof(struct strbuf)); +struct pa_strbuf *pa_strbuf_new(void) { + struct pa_strbuf *sb = malloc(sizeof(struct pa_strbuf)); assert(sb); sb->length = 0; sb->head = sb->tail = NULL; return sb; } -void strbuf_free(struct strbuf *sb) { +void pa_strbuf_free(struct pa_strbuf *sb) { assert(sb); while (sb->head) { struct chunk *c = sb->head; @@ -35,7 +35,7 @@ void strbuf_free(struct strbuf *sb) { free(sb); } -char *strbuf_tostring(struct strbuf *sb) { +char *pa_strbuf_tostring(struct pa_strbuf *sb) { char *t, *e; struct chunk *c; assert(sb); @@ -54,15 +54,15 @@ char *strbuf_tostring(struct strbuf *sb) { return t; } -char *strbuf_tostring_free(struct strbuf *sb) { +char *pa_strbuf_tostring_free(struct pa_strbuf *sb) { char *t; assert(sb); - t = strbuf_tostring(sb); - strbuf_free(sb); + t = pa_strbuf_tostring(sb); + pa_strbuf_free(sb); return t; } -void strbuf_puts(struct strbuf *sb, const char *t) { +void pa_strbuf_puts(struct pa_strbuf *sb, const char *t) { struct chunk *c; size_t l; assert(sb && t); @@ -87,7 +87,7 @@ void strbuf_puts(struct strbuf *sb, const char *t) { sb->length += l; } -int strbuf_printf(struct strbuf *sb, const char *format, ...) { +int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) { int r, size = 100; struct chunk *c = NULL; diff --git a/src/strbuf.h b/src/strbuf.h index f530a0dcf..bb9720447 100644 --- a/src/strbuf.h +++ b/src/strbuf.h @@ -1,14 +1,14 @@ #ifndef foostrbufhfoo #define foostrbufhfoo -struct strbuf; +struct pa_strbuf; -struct strbuf *strbuf_new(void); -void strbuf_free(struct strbuf *sb); -char *strbuf_tostring(struct strbuf *sb); -char *strbuf_tostring_free(struct strbuf *sb); +struct pa_strbuf *pa_strbuf_new(void); +void pa_strbuf_free(struct pa_strbuf *sb); +char *pa_strbuf_tostring(struct pa_strbuf *sb); +char *pa_strbuf_tostring_free(struct pa_strbuf *sb); -int strbuf_printf(struct strbuf *sb, const char *format, ...); -void strbuf_puts(struct strbuf *sb, const char *t); +int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...); +void pa_strbuf_puts(struct pa_strbuf *sb, const char *t); #endif diff --git a/src/tagstruct.c b/src/tagstruct.c index e6d6b2b25..67f524611 100644 --- a/src/tagstruct.c +++ b/src/tagstruct.c @@ -16,7 +16,7 @@ enum tags { TAG_SAMPLE_SPEC = 'a' }; -struct tagstruct { +struct pa_tagstruct { uint8_t *data; size_t length, allocated; size_t rindex; @@ -24,12 +24,12 @@ struct tagstruct { int dynamic; }; -struct tagstruct *tagstruct_new(const uint8_t* data, size_t length) { - struct tagstruct*t; +struct pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) { + struct pa_tagstruct*t; assert(!data || (data && length)); - t = malloc(sizeof(struct tagstruct)); + t = malloc(sizeof(struct pa_tagstruct)); assert(t); t->data = (uint8_t*) data; t->allocated = t->length = data ? length : 0; @@ -38,14 +38,14 @@ struct tagstruct *tagstruct_new(const uint8_t* data, size_t length) { return t; } -void tagstruct_free(struct tagstruct*t) { +void pa_tagstruct_free(struct pa_tagstruct*t) { assert(t); if (t->dynamic) free(t->data); free(t); } -uint8_t* tagstruct_free_data(struct tagstruct*t, size_t *l) { +uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l) { uint8_t *p; assert(t && t->dynamic && l); p = t->data; @@ -54,7 +54,7 @@ uint8_t* tagstruct_free_data(struct tagstruct*t, size_t *l) { return p; } -static void extend(struct tagstruct*t, size_t l) { +static void extend(struct pa_tagstruct*t, size_t l) { assert(t && t->dynamic); if (l <= t->allocated) @@ -64,7 +64,7 @@ static void extend(struct tagstruct*t, size_t l) { assert(t->data); } -void tagstruct_puts(struct tagstruct*t, const char *s) { +void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s) { size_t l; assert(t && s); l = strlen(s)+2; @@ -74,7 +74,7 @@ void tagstruct_puts(struct tagstruct*t, const char *s) { t->length += l; } -void tagstruct_putu32(struct tagstruct*t, uint32_t i) { +void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) { assert(t); extend(t, 5); t->data[t->length] = TAG_U32; @@ -82,7 +82,7 @@ void tagstruct_putu32(struct tagstruct*t, uint32_t i) { t->length += 5; } -void tagstruct_putu8(struct tagstruct*t, uint8_t c) { +void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c) { assert(t); extend(t, 2); t->data[t->length] = TAG_U8; @@ -90,7 +90,7 @@ void tagstruct_putu8(struct tagstruct*t, uint8_t c) { t->length += 2; } -void tagstruct_put_sample_spec(struct tagstruct *t, const struct pa_sample_spec *ss) { +void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss) { assert(t && ss); extend(t, 7); t->data[t->length] = TAG_SAMPLE_SPEC; @@ -100,7 +100,7 @@ void tagstruct_put_sample_spec(struct tagstruct *t, const struct pa_sample_spec t->length += 7; } -int tagstruct_gets(struct tagstruct*t, const char **s) { +int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) { int error = 0; size_t n; char *c; @@ -128,7 +128,7 @@ int tagstruct_gets(struct tagstruct*t, const char **s) { return 0; } -int tagstruct_getu32(struct tagstruct*t, uint32_t *i) { +int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i) { assert(t && i); if (t->rindex+5 > t->length) @@ -142,7 +142,7 @@ int tagstruct_getu32(struct tagstruct*t, uint32_t *i) { return 0; } -int tagstruct_getu8(struct tagstruct*t, uint8_t *c) { +int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c) { assert(t && c); if (t->rindex+2 > t->length) @@ -156,7 +156,7 @@ int tagstruct_getu8(struct tagstruct*t, uint8_t *c) { return 0; } -int tagstruct_get_sample_spec(struct tagstruct *t, struct pa_sample_spec *ss) { +int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss) { assert(t && ss); if (t->rindex+7 > t->length) @@ -174,12 +174,12 @@ int tagstruct_get_sample_spec(struct tagstruct *t, struct pa_sample_spec *ss) { } -int tagstruct_eof(struct tagstruct*t) { +int pa_tagstruct_eof(struct pa_tagstruct*t) { assert(t); return t->rindex >= t->length; } -const uint8_t* tagstruct_data(struct tagstruct*t, size_t *l) { +const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l) { assert(t && t->dynamic && l); *l = t->length; return t->data; diff --git a/src/tagstruct.h b/src/tagstruct.h index 9f6a0bf4a..be4e01faf 100644 --- a/src/tagstruct.h +++ b/src/tagstruct.h @@ -6,24 +6,24 @@ #include "sample.h" -struct tagstruct; +struct pa_tagstruct; -struct tagstruct *tagstruct_new(const uint8_t* data, size_t length); -void tagstruct_free(struct tagstruct*t); -uint8_t* tagstruct_free_data(struct tagstruct*t, size_t *l); +struct pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length); +void pa_tagstruct_free(struct pa_tagstruct*t); +uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l); -void tagstruct_puts(struct tagstruct*t, const char *s); -void tagstruct_putu32(struct tagstruct*t, uint32_t i); -void tagstruct_putu8(struct tagstruct*t, uint8_t c); -void tagstruct_put_sample_spec(struct tagstruct *t, const struct pa_sample_spec *ss); +void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s); +void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i); +void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c); +void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss); -int tagstruct_gets(struct tagstruct*t, const char **s); -int tagstruct_getu32(struct tagstruct*t, uint32_t *i); -int tagstruct_getu8(struct tagstruct*t, uint8_t *c); -int tagstruct_get_sample_spec(struct tagstruct *t, struct pa_sample_spec *ss); +int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s); +int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i); +int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c); +int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss); -int tagstruct_eof(struct tagstruct*t); -const uint8_t* tagstruct_data(struct tagstruct*t, size_t *l); +int pa_tagstruct_eof(struct pa_tagstruct*t); +const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l); diff --git a/src/todo b/src/todo index 0f88b0437..150438139 100644 --- a/src/todo +++ b/src/todo @@ -1,5 +1,4 @@ - recording (general, simple, esound, native) -- make it embedable (add pa_ prefix too all identifiers) - native library/protocol: sync() function more functions @@ -7,8 +6,10 @@ - kill() routines in all modules - command line protocol: kill client/input/output + default_sink/source - config parser/cmdline - move more stuff from module-oss[-dma] to liboss-util +- stdin_inuse/stdout_inuse - svn-id and license in every file -- post 0.1 diff --git a/src/tokenizer.c b/src/tokenizer.c index 0d266a9a5..de82c8e1f 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -5,15 +5,15 @@ #include "tokenizer.h" #include "dynarray.h" -struct tokenizer { - struct dynarray *dynarray; +struct pa_tokenizer { + struct pa_dynarray *dynarray; }; static void token_free(void *p, void *userdata) { free(p); } -static void parse(struct dynarray*a, const char *s, unsigned args) { +static void parse(struct pa_dynarray*a, const char *s, unsigned args) { int infty = 0; const char delimiter[] = " \t\n\r"; const char *p; @@ -27,7 +27,7 @@ static void parse(struct dynarray*a, const char *s, unsigned args) { size_t l = strcspn(p, delimiter); char *n = strndup(p, l); assert(n); - dynarray_append(a, n); + pa_dynarray_append(a, n); p += l; p += strspn(p, delimiter); args--; @@ -36,29 +36,29 @@ static void parse(struct dynarray*a, const char *s, unsigned args) { if (args && *p) { char *n = strdup(p); assert(n); - dynarray_append(a, n); + pa_dynarray_append(a, n); } } -struct tokenizer* tokenizer_new(const char *s, unsigned args) { - struct tokenizer *t; +struct pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args) { + struct pa_tokenizer *t; - t = malloc(sizeof(struct tokenizer)); + t = malloc(sizeof(struct pa_tokenizer)); assert(t); - t->dynarray = dynarray_new(); + t->dynarray = pa_dynarray_new(); assert(t->dynarray); parse(t->dynarray, s, args); return t; } -void tokenizer_free(struct tokenizer *t) { +void pa_tokenizer_free(struct pa_tokenizer *t) { assert(t); - dynarray_free(t->dynarray, token_free, NULL); + pa_dynarray_free(t->dynarray, token_free, NULL); free(t); } -const char *tokenizer_get(struct tokenizer *t, unsigned i) { +const char *pa_tokenizer_get(struct pa_tokenizer *t, unsigned i) { assert(t); - return dynarray_get(t->dynarray, i); + return pa_dynarray_get(t->dynarray, i); } diff --git a/src/tokenizer.h b/src/tokenizer.h index c71ae7900..160b23e0d 100644 --- a/src/tokenizer.h +++ b/src/tokenizer.h @@ -1,11 +1,11 @@ #ifndef footokenizerhfoo #define footokenizerhfoo -struct tokenizer; +struct pa_tokenizer; -struct tokenizer* tokenizer_new(const char *s, unsigned args); -void tokenizer_free(struct tokenizer *t); +struct pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args); +void pa_tokenizer_free(struct pa_tokenizer *t); -const char *tokenizer_get(struct tokenizer *t, unsigned i); +const char *pa_tokenizer_get(struct pa_tokenizer *t, unsigned i); #endif diff --git a/src/util.c b/src/util.c index 8f4443360..5fff55e3a 100644 --- a/src/util.c +++ b/src/util.c @@ -12,7 +12,7 @@ #include "util.h" -void make_nonblock_fd(int fd) { +void pa_make_nonblock_fd(int fd) { int v; if ((v = fcntl(fd, F_GETFL)) >= 0) @@ -20,7 +20,7 @@ void make_nonblock_fd(int fd) { fcntl(fd, F_SETFL, v|O_NONBLOCK); } -void peer_to_string(char *c, size_t l, int fd) { +void pa_peer_to_string(char *c, size_t l, int fd) { struct stat st; assert(c && l && fd >= 0); @@ -66,7 +66,7 @@ void peer_to_string(char *c, size_t l, int fd) { snprintf(c, l, "Unknown client"); } -int make_secure_dir(const char* dir) { +int pa_make_secure_dir(const char* dir) { struct stat st; if (mkdir(dir, 0700) < 0) @@ -86,7 +86,7 @@ fail: return -1; } -int make_socket_low_delay(int fd) { +int pa_make_socket_low_delay(int fd) { int ret = 0, buf_size, priority; assert(fd >= 0); @@ -106,12 +106,12 @@ int make_socket_low_delay(int fd) { return ret; } -int make_tcp_socket_low_delay(int fd) { +int pa_make_tcp_socket_low_delay(int fd) { int ret, tos, on; assert(fd >= 0); - ret = make_socket_low_delay(fd); + ret = pa_make_socket_low_delay(fd); on = 1; if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) diff --git a/src/util.h b/src/util.h index 8e9a3796f..b8759ad83 100644 --- a/src/util.h +++ b/src/util.h @@ -1,13 +1,15 @@ #ifndef fooutilhfoo #define fooutilhfoo -void make_nonblock_fd(int fd); +#include -void peer_to_string(char *c, size_t l, int fd); +void pa_make_nonblock_fd(int fd); -int make_secure_dir(const char* dir); +void pa_peer_to_string(char *c, size_t l, int fd); -int make_socket_low_delay(int fd); -int make_tcp_socket_low_delay(int fd); +int pa_make_secure_dir(const char* dir); + +int pa_make_socket_low_delay(int fd); +int pa_make_tcp_socket_low_delay(int fd); #endif From 722c2c8c8785d215ec3ec8757168b82c9600f4a3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 4 Jul 2004 17:40:15 +0000 Subject: [PATCH 0049/1514] add kill_* and default_* commands to CLI make module-cli unload itself on EOF clean up stdio usage add sink pointer to monitor sources git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@50 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 +- src/cli.c | 305 ++++++++++++++++++++++++++++++++++++----------- src/client.c | 8 +- src/ioline.c | 10 +- src/main.c | 2 - src/main.h | 6 - src/module-cli.c | 18 ++- src/sink.c | 1 + src/sioman.c | 17 +++ src/sioman.h | 7 ++ src/source.c | 9 +- src/source.h | 2 + src/todo | 5 +- 13 files changed, 300 insertions(+), 96 deletions(-) delete mode 100644 src/main.h create mode 100644 src/sioman.c create mode 100644 src/sioman.h diff --git a/src/Makefile.am b/src/Makefile.am index 167bc91c5..62b1a3a67 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,7 +54,7 @@ pkglib_LTLIBRARIES=libiochannel.la \ polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ strbuf.c strbuf.h \ - main.c main.h \ + main.c \ mainloop.c mainloop.h \ memblock.c memblock.h \ sample.c sample.h \ @@ -77,7 +77,9 @@ polypaudio_SOURCES = idxset.c idxset.h \ endianmacros.h \ memchunk.c memchunk.h \ sconv-s16le.c sconv-s16le.h \ - sconv-s16be.c sconv-s16be.h + sconv-s16be.c sconv-s16be.h \ + sioman.c sioman.h + polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(LIBLTDL) $(LIBSAMPLERATE_LIBS) diff --git a/src/cli.c b/src/cli.c index 659523b1d..ecde57631 100644 --- a/src/cli.c +++ b/src/cli.c @@ -27,48 +27,62 @@ struct pa_cli { struct command { const char *name; - void (*proc) (struct pa_cli *cli, struct pa_tokenizer*t); + int (*proc) (struct pa_cli *cli, struct pa_tokenizer*t); const char *help; unsigned args; }; static void line_callback(struct pa_ioline *line, const char *s, void *userdata); -static void pa_cli_command_exit(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_help(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_modules(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_clients(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_sinks(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_sources(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_sink_inputs(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_source_outputs(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_stat(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_info(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_load(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_unload(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_sink_volume(struct pa_cli *c, struct pa_tokenizer *t); -static void pa_cli_command_sink_input_volume(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_exit(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_help(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_modules(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_clients(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_sinks(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_sources(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_sink_inputs(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_source_outputs(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_stat(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_info(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_load(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_unload(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_sink_volume(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_sink_input_volume(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_sink_default(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_source_default(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_kill_client(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_kill_sink_input(struct pa_cli *c, struct pa_tokenizer *t); +static int pa_cli_command_kill_source_output(struct pa_cli *c, struct pa_tokenizer *t); static const struct command commands[] = { - { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, - { "help", pa_cli_command_help, "Show this help", 1 }, - { "modules", pa_cli_command_modules, "List loaded modules", 1 }, - { "sinks", pa_cli_command_sinks, "List loaded sinks", 1 }, - { "sources", pa_cli_command_sources, "List loaded sources", 1 }, - { "clients", pa_cli_command_clients, "List loaded clients", 1 }, - { "sink_inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 }, - { "source_outputs", pa_cli_command_source_outputs, "List source outputs", 1 }, - { "stat", pa_cli_command_stat, "Show memory block statistics", 1 }, - { "info", pa_cli_command_info, "Show comprehensive status", 1 }, - { "load", pa_cli_command_load, "Load a module (args: name, arguments)", 3}, - { "unload", pa_cli_command_unload, "Unload a module (args: index)", 2}, - { "sink_volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: sink, volume)", 3}, - { "sink_input_volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: sink input, volume)", 3}, + { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, + { "help", pa_cli_command_help, "Show this help", 1 }, + { "modules", pa_cli_command_modules, "List loaded modules", 1 }, + { "sinks", pa_cli_command_sinks, "List loaded sinks", 1 }, + { "sources", pa_cli_command_sources, "List loaded sources", 1 }, + { "clients", pa_cli_command_clients, "List loaded clients", 1 }, + { "sink_inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 }, + { "source_outputs", pa_cli_command_source_outputs, "List source outputs", 1 }, + { "stat", pa_cli_command_stat, "Show memory block statistics", 1 }, + { "info", pa_cli_command_info, "Show comprehensive status", 1 }, + { "ls", pa_cli_command_info, NULL, 1 }, + { "list", pa_cli_command_info, NULL, 1 }, + { "load", pa_cli_command_load, "Load a module (args: name, arguments)", 3}, + { "unload", pa_cli_command_unload, "Unload a module (args: index)", 2}, + { "sink_volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3}, + { "sink_input_volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index|name, volume)", 3}, + { "sink_default", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2}, + { "source_default", pa_cli_command_source_default, "Set the default source (args: index|name)", 2}, + { "kill_client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, + { "kill_sink_input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2}, + { "kill_source_output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2}, { NULL, NULL, NULL, 0 } }; static const char prompt[] = ">>> "; +static void client_kill(struct pa_client *c); + struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io) { char cname[256]; struct pa_cli *c; @@ -86,6 +100,8 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io) { pa_iochannel_peer_to_string(io, cname, sizeof(cname)); c->client = pa_client_new(core, "CLI", cname); assert(c->client); + c->client->kill = client_kill; + c->client->userdata = c; pa_ioline_set_callback(c->line, line_callback, c); pa_ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"); @@ -101,6 +117,16 @@ void pa_cli_free(struct pa_cli *c) { free(c); } +static void client_kill(struct pa_client *client) { + struct pa_cli *c; + assert(client && client->userdata); + c = client->userdata; + fprintf(stderr, "CLI client killed.\n"); + + if (c->eof_callback) + c->eof_callback(c, c->userdata); +} + static void line_callback(struct pa_ioline *line, const char *s, void *userdata) { struct pa_cli *c = userdata; const char *cs; @@ -108,7 +134,7 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) assert(line && c); if (!s) { - fprintf(stderr, "CLI client exited\n"); + fprintf(stderr, "CLI got EOF from user.\n"); if (c->eof_callback) c->eof_callback(c, c->userdata); @@ -125,11 +151,16 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) for (command = commands; command->name; command++) if (strlen(command->name) == l && !strncmp(s, command->name, l)) { + int ret; struct pa_tokenizer *t = pa_tokenizer_new(s, command->args); assert(t); - command->proc(c, t); + ret = command->proc(c, t); pa_tokenizer_free(t); unknown = 0; + + /* A negative return value denotes that the cli object is probably invalid now */ + if (ret < 0) + return; break; } @@ -137,7 +168,7 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) pa_ioline_puts(line, "Unknown command\n"); } - pa_ioline_puts(c->line, prompt); + pa_ioline_puts(line, prompt); } void pa_cli_set_eof_callback(struct pa_cli *c, void (*cb)(struct pa_cli*c, void *userdata), void *userdata) { @@ -146,12 +177,23 @@ void pa_cli_set_eof_callback(struct pa_cli *c, void (*cb)(struct pa_cli*c, void c->userdata = userdata; } -static void pa_cli_command_exit(struct pa_cli *c, struct pa_tokenizer *t) { - assert(c && c->core && c->core->mainloop && t); - c->core->mainloop->quit(c->core->mainloop, 0); +static uint32_t parse_index(const char *n) { + long index; + char *x; + index = strtol(n, &x, 0); + if (!x || *x != 0 || index < 0) + return (uint32_t) PA_IDXSET_INVALID; + + return (uint32_t) index; } -static void pa_cli_command_help(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_exit(struct pa_cli *c, struct pa_tokenizer *t) { + assert(c && c->core && c->core->mainloop && t); + c->core->mainloop->quit(c->core->mainloop, 0); + return 0; +} + +static int pa_cli_command_help(struct pa_cli *c, struct pa_tokenizer *t) { const struct command*command; struct pa_strbuf *pa_strbuf; char *p; @@ -163,85 +205,95 @@ static void pa_cli_command_help(struct pa_cli *c, struct pa_tokenizer *t) { pa_strbuf_puts(pa_strbuf, "Available commands:\n"); for (command = commands; command->name; command++) - pa_strbuf_printf(pa_strbuf, " %-20s %s\n", command->name, command->help); + if (command->help) + pa_strbuf_printf(pa_strbuf, " %-20s %s\n", command->name, command->help); pa_ioline_puts(c->line, p = pa_strbuf_tostring_free(pa_strbuf)); free(p); + return 0; } -static void pa_cli_command_modules(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_modules(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); s = pa_module_list_to_string(c->core); assert(s); pa_ioline_puts(c->line, s); free(s); + return 0; } -static void pa_cli_command_clients(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_clients(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); s = pa_client_list_to_string(c->core); assert(s); pa_ioline_puts(c->line, s); free(s); + return 0; } -static void pa_cli_command_sinks(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_sinks(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); s = pa_sink_list_to_string(c->core); assert(s); pa_ioline_puts(c->line, s); free(s); + return 0; } -static void pa_cli_command_sources(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_sources(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); s = pa_source_list_to_string(c->core); assert(s); pa_ioline_puts(c->line, s); free(s); + return 0; } -static void pa_cli_command_sink_inputs(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_sink_inputs(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); s = pa_sink_input_list_to_string(c->core); assert(s); pa_ioline_puts(c->line, s); free(s); + return 0; } -static void pa_cli_command_source_outputs(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_source_outputs(struct pa_cli *c, struct pa_tokenizer *t) { char *s; assert(c && t); s = pa_source_output_list_to_string(c->core); assert(s); pa_ioline_puts(c->line, s); free(s); + return 0; } -static void pa_cli_command_stat(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_stat(struct pa_cli *c, struct pa_tokenizer *t) { char txt[256]; assert(c && t); snprintf(txt, sizeof(txt), "Memory blocks allocated: %u, total size: %u bytes.\n", pa_memblock_count, pa_memblock_total); pa_ioline_puts(c->line, txt); + return 0; } -static void pa_cli_command_info(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_info(struct pa_cli *c, struct pa_tokenizer *t) { assert(c && t); pa_cli_command_stat(c, t); pa_cli_command_modules(c, t); - pa_cli_command_sources(c, t); pa_cli_command_sinks(c, t); + pa_cli_command_sources(c, t); pa_cli_command_clients(c, t); pa_cli_command_sink_inputs(c, t); pa_cli_command_source_outputs(c, t); + return 0; } -static void pa_cli_command_load(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_load(struct pa_cli *c, struct pa_tokenizer *t) { struct pa_module *m; const char *name; char txt[256]; @@ -249,19 +301,20 @@ static void pa_cli_command_load(struct pa_cli *c, struct pa_tokenizer *t) { if (!(name = pa_tokenizer_get(t, 1))) { pa_ioline_puts(c->line, "You need to specfiy the module name and optionally arguments.\n"); - return; + return 0; } if (!(m = pa_module_load(c->core, name, pa_tokenizer_get(t, 2)))) { pa_ioline_puts(c->line, "Module load failed.\n"); - return; + return 0; } snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index); pa_ioline_puts(c->line, txt); + return 0; } -static void pa_cli_command_unload(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_unload(struct pa_cli *c, struct pa_tokenizer *t) { struct pa_module *m; uint32_t index; const char *i; @@ -270,20 +323,20 @@ static void pa_cli_command_unload(struct pa_cli *c, struct pa_tokenizer *t) { if (!(i = pa_tokenizer_get(t, 1))) { pa_ioline_puts(c->line, "You need to specfiy the module index.\n"); - return; + return 0; } index = (uint32_t) strtoul(i, &e, 10); if (*e || !(m = pa_idxset_get_by_index(c->core->modules, index))) { pa_ioline_puts(c->line, "Invalid module index.\n"); - return; + return 0; } pa_module_unload_request(c->core, m); + return 0; } - -static void pa_cli_command_sink_volume(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_sink_volume(struct pa_cli *c, struct pa_tokenizer *t) { const char *n, *v; char *x = NULL; struct pa_sink *sink; @@ -291,62 +344,178 @@ static void pa_cli_command_sink_volume(struct pa_cli *c, struct pa_tokenizer *t) if (!(n = pa_tokenizer_get(t, 1))) { pa_ioline_puts(c->line, "You need to specify a sink either by its name or its index.\n"); - return; + return 0; } if (!(v = pa_tokenizer_get(t, 2))) { pa_ioline_puts(c->line, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); - return; + return 0; } volume = strtol(v, &x, 0); if (!x || *x != 0 || volume < 0) { pa_ioline_puts(c->line, "Failed to parse volume.\n"); - return; + return 0; } if (!(sink = pa_namereg_get(c->core, n, PA_NAMEREG_SINK))) { pa_ioline_puts(c->line, "No sink found by this name or index.\n"); - return; + return 0; } sink->volume = (uint32_t) volume; + return 0; } -static void pa_cli_command_sink_input_volume(struct pa_cli *c, struct pa_tokenizer *t) { +static int pa_cli_command_sink_input_volume(struct pa_cli *c, struct pa_tokenizer *t) { const char *n, *v; - char *x = NULL; struct pa_sink_input *si; - long index, volume; + long volume; + uint32_t index; + char *x; if (!(n = pa_tokenizer_get(t, 1))) { pa_ioline_puts(c->line, "You need to specify a sink input by its index.\n"); - return; + return 0; } - index = strtol(n, &x, 0); - if (!x || *x != 0 || index < 0) { + if ((index = parse_index(n)) == PA_IDXSET_INVALID) { pa_ioline_puts(c->line, "Failed to parse index.\n"); - return; + return 0; } if (!(v = pa_tokenizer_get(t, 2))) { pa_ioline_puts(c->line, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); - return; + return 0; } x = NULL; volume = strtol(v, &x, 0); if (!x || *x != 0 || volume < 0) { pa_ioline_puts(c->line, "Failed to parse volume.\n"); - return; + return 0; } if (!(si = pa_idxset_get_by_index(c->core->sink_inputs, (uint32_t) index))) { pa_ioline_puts(c->line, "No sink input found with this index.\n"); - return; + return 0; } si->volume = (uint32_t) volume; + return 0; } +static int pa_cli_command_sink_default(struct pa_cli *c, struct pa_tokenizer *t) { + const char *n; + struct pa_sink *sink; + assert(c && t); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_ioline_puts(c->line, "You need to specify a sink either by its name or its index.\n"); + return 0; + } + + if (!(sink = pa_namereg_get(c->core, n, PA_NAMEREG_SINK))) { + pa_ioline_puts(c->line, "No sink found by this name or index.\n"); + return 0; + } + + c->core->default_sink_index = sink->index; + return 0; +} + +static int pa_cli_command_source_default(struct pa_cli *c, struct pa_tokenizer *t) { + const char *n; + struct pa_source *source; + assert(c && t); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_ioline_puts(c->line, "You need to specify a source either by its name or its index.\n"); + return 0; + } + + if (!(source = pa_namereg_get(c->core, n, PA_NAMEREG_SOURCE))) { + pa_ioline_puts(c->line, "No source found by this name or index.\n"); + return 0; + } + + c->core->default_source_index = source->index; + return 0; +} + +static int pa_cli_command_kill_client(struct pa_cli *c, struct pa_tokenizer *t) { + const char *n; + struct pa_client *client; + uint32_t index; + int ret; + assert(c && t); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_ioline_puts(c->line, "You need to specify a client by its index.\n"); + return 0; + } + + if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + pa_ioline_puts(c->line, "Failed to parse index.\n"); + return 0; + } + + if (!(client = pa_idxset_get_by_index(c->core->clients, index))) { + pa_ioline_puts(c->line, "No client found by this index.\n"); + return 0; + } + + ret = (client->userdata == c) ? -1 : 0; + pa_client_kill(client); + return ret; +} + +static int pa_cli_command_kill_sink_input(struct pa_cli *c, struct pa_tokenizer *t) { + const char *n; + struct pa_sink_input *sink_input; + uint32_t index; + assert(c && t); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_ioline_puts(c->line, "You need to specify a sink input by its index.\n"); + return 0; + } + + if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + pa_ioline_puts(c->line, "Failed to parse index.\n"); + return 0; + } + + if (!(sink_input = pa_idxset_get_by_index(c->core->sink_inputs, index))) { + pa_ioline_puts(c->line, "No sink input found by this index.\n"); + return 0; + } + + pa_sink_input_kill(sink_input); + return 0; +} + +static int pa_cli_command_kill_source_output(struct pa_cli *c, struct pa_tokenizer *t) { + const char *n; + struct pa_source_output *source_output; + uint32_t index; + assert(c && t); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_ioline_puts(c->line, "You need to specify a source output by its index.\n"); + return 0; + } + + if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + pa_ioline_puts(c->line, "Failed to parse index.\n"); + return 0; + } + + if (!(source_output = pa_idxset_get_by_index(c->core->source_outputs, index))) { + pa_ioline_puts(c->line, "No source output found by this index.\n"); + return 0; + } + + pa_source_output_kill(source_output); + return 0; +} diff --git a/src/client.c b/src/client.c index eb06c52fb..7f1648a73 100644 --- a/src/client.c +++ b/src/client.c @@ -39,8 +39,12 @@ void pa_client_free(struct pa_client *c) { void pa_client_kill(struct pa_client *c) { assert(c); - if (c->kill) - c->kill(c); + if (!c->kill) { + fprintf(stderr, "kill() operation not implemented for client %u\n", c->index); + return; + } + + c->kill(c); } char *pa_client_list_to_string(struct pa_core *c) { diff --git a/src/ioline.c b/src/ioline.c index ab7cb5176..86ab57202 100644 --- a/src/ioline.c +++ b/src/ioline.c @@ -146,14 +146,14 @@ static int do_read(struct pa_ioline *l) { p = l->rbuf+l->rbuf_index; m = strlen(p); - if (l->callback) - l->callback(l, p, l->userdata); - l->rbuf_index += m+1; l->rbuf_valid_length -= m+1; if (l->rbuf_valid_length == 0) l->rbuf_index = 0; + + if (l->callback) + l->callback(l, p, l->userdata); } return 0; @@ -180,10 +180,10 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { struct pa_ioline *l = userdata; assert(io && l); - if (!l->dead && do_read(l) < 0) + if (!l->dead && do_write(l) < 0) goto fail; - if (!l->dead && do_write(l) < 0) + if (!l->dead && do_read(l) < 0) goto fail; return; diff --git a/src/main.c b/src/main.c index be75b3726..f44a8d479 100644 --- a/src/main.c +++ b/src/main.c @@ -10,8 +10,6 @@ #include "module.h" #include "mainloop-signal.h" -int pa_stdin_inuse = 0, pa_stdout_inuse = 0; - static struct pa_mainloop *mainloop; static void signal_callback(void *id, int sig, void *userdata) { diff --git a/src/main.h b/src/main.h deleted file mode 100644 index 35333bbf9..000000000 --- a/src/main.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef foomainhfoo -#define foomainhfoo - -extern int pa_stdin_inuse, pa_stdout_inuse; - -#endif diff --git a/src/module-cli.c b/src/module-cli.c index 4a1692eef..7306ade55 100644 --- a/src/module-cli.c +++ b/src/module-cli.c @@ -2,27 +2,36 @@ #include #include -#include "main.h" #include "module.h" #include "iochannel.h" #include "cli.h" +#include "sioman.h" + +static void eof_cb(struct pa_cli*c, void *userdata) { + struct pa_module *m = userdata; + assert(c && m); + + pa_module_unload_request(m->core, m); +} int module_init(struct pa_core *c, struct pa_module*m) { struct pa_iochannel *io; assert(c && m); - if (pa_stdin_inuse || pa_stdout_inuse) { + if (pa_stdio_acquire() < 0) { fprintf(stderr, "STDIN/STDUSE already used\n"); return -1; } - pa_stdin_inuse = pa_stdout_inuse = 1; io = pa_iochannel_new(c->mainloop, STDIN_FILENO, STDOUT_FILENO); assert(io); pa_iochannel_set_noclose(io, 1); m->userdata = pa_cli_new(c, io); assert(m->userdata); + + pa_cli_set_eof_callback(m->userdata, eof_cb, m); + return 0; } @@ -30,6 +39,5 @@ void module_done(struct pa_core *c, struct pa_module*m) { assert(c && m); pa_cli_free(m->userdata); - assert(pa_stdin_inuse && pa_stdout_inuse); - pa_stdin_inuse = pa_stdout_inuse = 0; + pa_stdio_release(); } diff --git a/src/sink.c b/src/sink.c index 53ebb8bff..79bf17785 100644 --- a/src/sink.c +++ b/src/sink.c @@ -39,6 +39,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co s->monitor_source = pa_source_new(core, n, 0, spec); assert(s->monitor_source); free(n); + s->monitor_source->monitor_of = s; s->volume = PA_VOLUME_NORM; diff --git a/src/sioman.c b/src/sioman.c new file mode 100644 index 000000000..1a4b08b04 --- /dev/null +++ b/src/sioman.c @@ -0,0 +1,17 @@ +#include +#include "sioman.h" + +static int stdio_inuse = 0; + +int pa_stdio_acquire(void) { + if (stdio_inuse) + return -1; + + stdio_inuse = 1; + return 0; +} + +void pa_stdio_release(void) { + assert(stdio_inuse); + stdio_inuse = 0; +} diff --git a/src/sioman.h b/src/sioman.h new file mode 100644 index 000000000..e675c80ed --- /dev/null +++ b/src/sioman.h @@ -0,0 +1,7 @@ +#ifndef foosiomanhfoo +#define foosiomanhfoo + +int pa_stdio_acquire(void); +void pa_stdio_release(void); + +#endif diff --git a/src/source.c b/src/source.c index 9a4f95a26..1c97604b4 100644 --- a/src/source.c +++ b/src/source.c @@ -26,6 +26,7 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail s->core = core; s->sample_spec = *spec; s->outputs = pa_idxset_new(NULL, NULL); + s->monitor_of = NULL; s->notify = NULL; s->userdata = NULL; @@ -109,8 +110,12 @@ char *pa_source_list_to_string(struct pa_core *c) { default_source = pa_source_get_default(c); - for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) - pa_strbuf_printf(s, " %c index: %u, name: <%s>\n", source == default_source ? '*' : ' ', source->index, source->name); + for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { + char mo[256] = ""; + if (source->monitor_of) + snprintf(mo, sizeof(mo), ", monitor_of: <%u>", source->monitor_of->index); + pa_strbuf_printf(s, " %c index: %u, name: <%s>%s\n", source == default_source ? '*' : ' ', source->index, source->name, mo); + } return pa_strbuf_tostring_free(s); } diff --git a/src/source.h b/src/source.h index 03d540c82..3b66cd368 100644 --- a/src/source.h +++ b/src/source.h @@ -9,6 +9,7 @@ struct pa_source; #include "idxset.h" #include "memblock.h" #include "memchunk.h" +#include "sink.h" struct pa_source { uint32_t index; @@ -17,6 +18,7 @@ struct pa_source { struct pa_core *core; struct pa_sample_spec sample_spec; struct pa_idxset *outputs; + struct pa_sink *monitor_of; void (*notify)(struct pa_source*source); void *userdata; diff --git a/src/todo b/src/todo index 150438139..505eeac2e 100644 --- a/src/todo +++ b/src/todo @@ -4,13 +4,10 @@ more functions - simple library - kill() routines in all modules -- command line protocol: - kill client/input/output - default_sink/source - config parser/cmdline - move more stuff from module-oss[-dma] to liboss-util -- stdin_inuse/stdout_inuse - svn-id and license in every file +- in module-oss: create source first, than sink -- post 0.1 - future cancellation From f8cbde54dab2783e2c6ba699dfaee9ef51b1e098 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 6 Jul 2004 00:08:44 +0000 Subject: [PATCH 0050/1514] auth support in esound and native AUTH and SET_NAME operatins in native simple library git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@51 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 33 +++++++++-- src/authkey.c | 115 +++++++++++++++++++++++++++++++++++++ src/authkey.h | 9 +++ src/main.c | 2 +- src/module-oss.c | 3 +- src/module-protocol-stub.c | 23 +++++++- src/pacat-simple.c | 52 +++++++++++++++++ src/pacat.c | 13 ++--- src/polyp-error.c | 25 ++++++++ src/polyp-error.h | 10 ++++ src/polyp.c | 108 +++++++++++++++++++++++++--------- src/polyp.h | 6 +- src/protocol-esound.c | 35 +++++++---- src/protocol-native-spec.h | 10 +++- src/protocol-native.c | 57 ++++++++++++++++++ src/simple.c | 70 +++++++++++----------- src/simple.h | 7 ++- src/tagstruct.c | 31 +++++++++- src/tagstruct.h | 2 + src/todo | 12 +++- src/util.c | 84 +++++++++++++++++++++++++++ src/util.h | 6 ++ 22 files changed, 615 insertions(+), 98 deletions(-) create mode 100644 src/authkey.c create mode 100644 src/authkey.h create mode 100644 src/pacat-simple.c create mode 100644 src/polyp-error.c create mode 100644 src/polyp-error.h diff --git a/src/Makefile.am b/src/Makefile.am index 62b1a3a67..70e7e09b8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ AM_CFLAGS=-ansi -D_GNU_SOURCE -bin_PROGRAMS = polypaudio pacat +bin_PROGRAMS = polypaudio pacat pacat-simple pkglib_LTLIBRARIES=libiochannel.la \ libsocket-server.la \ @@ -34,6 +34,7 @@ pkglib_LTLIBRARIES=libiochannel.la \ libtagstruct.la \ libpstream-util.la \ libpdispatch.la \ + libauthkey.la \ libprotocol-simple.la \ libprotocol-esound.la \ libprotocol-native.la \ @@ -49,7 +50,9 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-esound-protocol-unix.la \ module-native-protocol-tcp.la \ module-native-protocol-unix.la \ - libpolyp.la + libpolyp.la \ + libpolyp-simple.la \ + libpolyp-error.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -139,14 +142,17 @@ libprotocol_cli_la_LIBADD = libsocket-server.la libiochannel.la libcli.la libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = libsocket-server.la libiochannel.la libpacket.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la +libprotocol_native_la_LIBADD = libsocket-server.la libiochannel.la libpacket.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libtagstruct_la_SOURCES = tagstruct.c tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h protocol-esound-spec.h libprotocol_esound_la_LDFLAGS = -avoid-version -libprotocol_esound_la_LIBADD = libsocket-server.la libiochannel.la +libprotocol_esound_la_LIBADD = libsocket-server.la libiochannel.la libauthkey.la + +libauthkey_la_SOURCES = authkey.c authkey.h +libauthkey_la_LDFLAGS = -avoid-version module_simple_protocol_tcp_la_SOURCES = module-protocol-stub.c module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) @@ -221,7 +227,22 @@ libpolyp_la_SOURCES = polyp.c polyp.h \ packet.c packet.h \ queue.c queue.h \ dynarray.c dynarray.h \ - memchunk.c memchunk.h + memchunk.c memchunk.h \ + authkey.c authkey.h +libpolyp_la_CFLAGS = $(AM_CFLAGS) +#libpolyp_la_LIBADD = libpolyp-error.la -pacat_SOURCES = pacat.c +libpolyp_error_la_SOURCES = polyp-error.c polyp-error.h +libpolyp_error_la_CFLAGS = $(AM_CFLAGS) + +libpolyp_simple_la_SOURCES = simple.c simple.h +libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) +libpolyp_simple_la_LIBADD = libpolyp.la #libpolyp-error.la + +pacat_SOURCES = pacat.c #$(libpolyp_la_SOURCES) pacat_LDADD = libpolyp.la +pacat_CFLAGS = $(AM_CFLAGS) + +pacat_simple_SOURCES = pacat-simple.c +pacat_simple_LDADD = libpolyp-simple.a +pacat_simple_CFLAGS = $(AM_CFLAGS) diff --git a/src/authkey.c b/src/authkey.c new file mode 100644 index 000000000..cd284fb51 --- /dev/null +++ b/src/authkey.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "authkey.h" +#include "util.h" + +#define RANDOM_DEVICE "/dev/urandom" + +static int load(const char *fn, void *data, size_t length) { + int fd = -1, ret = -1; + ssize_t r; + + assert(fn && data && length); + + if ((fd = open(fn, O_RDONLY)) < 0) + goto finish; + + if ((r = pa_loop_read(fd, data, length)) < 0 || (size_t) r != length) { + ret = -2; + goto finish; + } + + ret = 0; + +finish: + if (fd >= 0) + close(fd); + + return ret; +} + +static int generate(const char *fn, void *data, size_t length) { + int fd = -1, random_fd = -1, ret = -1; + ssize_t r; + assert(fn && data && length); + + if ((fd = open(fn, O_WRONLY|O_EXCL|O_CREAT, S_IRUSR | S_IWUSR)) < 0) + goto finish; + + if ((random_fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) { + + if ((r = pa_loop_read(random_fd, data, length)) < 0 || (size_t) r != length) { + ret = -2; + goto finish; + } + + } else { + uint8_t *p; + size_t l; + fprintf(stderr, "WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s, falling back to unsecure pseudo RNG.\n", strerror(errno)); + + srandom(time(NULL)); + + for (p = data, l = length; l > 0; p++, l--) + *p = (uint8_t) random(); + } + + if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) { + ret = -2; + goto finish; + } + + ret = 0; + +finish: + if (fd >= 0) { + if (ret != 0) + unlink(fn); + close(fd); + } + if (random_fd >= 0) + close(random_fd); + + return ret; +} + +int pa_authkey_load(const char *path, void *data, size_t length) { + int ret, i; + + assert(path && data && length); + + for (i = 0; i < 10; i++) { + if ((ret = load(path, data, length)) < 0) + if (ret == -1 && errno == ENOENT) + if ((ret = generate(path, data, length)) < 0) + if (ret == -1 && errno == EEXIST) + continue; + break; + } + + if (ret < 0) + fprintf(stderr, "Failed to load authorization key '%s': %s\n", path, (ret == -1) ? strerror(errno) : "file corrupt"); + + return ret; +} + +int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { + char *home; + char path[PATH_MAX]; + + if (!(home = getenv("HOME"))) + return -2; + + snprintf(path, sizeof(path), "%s/%s", home, fn); + + return pa_authkey_load(path, data, length); +} diff --git a/src/authkey.h b/src/authkey.h new file mode 100644 index 000000000..cc0fcb28b --- /dev/null +++ b/src/authkey.h @@ -0,0 +1,9 @@ +#ifndef fooauthkeyhfoo +#define fooauthkeyhfoo + +#include + +int pa_authkey_load(const char *path, void *data, size_t len); +int pa_authkey_load_from_home(const char *fn, void *data, size_t length); + +#endif diff --git a/src/main.c b/src/main.c index f44a8d479..88552fed4 100644 --- a/src/main.c +++ b/src/main.c @@ -44,7 +44,7 @@ int main(int argc, char *argv[]) { pa_module_load(c, "module-cli-protocol-unix", NULL); pa_module_load(c, "module-native-protocol-tcp", NULL);*/ pa_module_load(c, "module-native-protocol-unix", NULL); -/* pa_module_load(c, "module-esound-protocol-tcp", NULL);*/ + pa_module_load(c, "module-esound-protocol-tcp", NULL); pa_module_load(c, "module-cli", NULL); fprintf(stderr, "main: mainloop entry.\n"); diff --git a/src/module-oss.c b/src/module-oss.c index 3a1afd474..310c89c0a 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -77,7 +77,8 @@ static void do_read(struct userdata *u) { assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); - fprintf(stderr, "read() failed: %s\n", strerror(errno)); + if (errno != EAGAIN) + fprintf(stderr, "read() failed: %s\n", strerror(errno)); return; } diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 1a655454b..713e0ab8f 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -50,13 +52,24 @@ int module_init(struct pa_core *c, struct pa_module*m) { assert(c && m); #ifdef USE_TCP_SOCKETS - if (!(s = pa_socket_server_new_ipv4(c->mainloop, INADDR_LOOPBACK, IPV4_PORT))) + if (!(s = pa_socket_server_new_ipv4(c->mainloop, INADDR_ANY, IPV4_PORT))) return -1; #else if (pa_make_secure_dir(UNIX_SOCKET_DIR) < 0) { fprintf(stderr, "Failed to create secure socket directory.\n"); return -1; } + + { + int r; + if ((r = pa_unix_socket_remove_stale(UNIX_SOCKET)) < 0) { + fprintf(stderr, "Failed to remove stale UNIX socket '%s': %s\n", UNIX_SOCKET, strerror(errno)); + return -1; + } + + if (r) + fprintf(stderr, "Removed stale UNIX socket '%s'.", UNIX_SOCKET); + } if (!(s = pa_socket_server_new_unix(c->mainloop, UNIX_SOCKET))) { rmdir(UNIX_SOCKET_DIR); @@ -69,8 +82,12 @@ int module_init(struct pa_core *c, struct pa_module*m) { #else m->userdata = protocol_new(c, s); #endif - - assert(m->userdata); + + if (!m->userdata) { + pa_socket_server_free(s); + return -1; + } + return 0; } diff --git a/src/pacat-simple.c b/src/pacat-simple.c new file mode 100644 index 000000000..5408221c4 --- /dev/null +++ b/src/pacat-simple.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +#include "simple.h" +#include "polyp-error.h" + +#define BUFSIZE 1024 + +int main(int argc, char*argv[]) { + static const struct pa_sample_spec ss = { + .format = PA_SAMPLE_S16LE, + .rate = 44100, + .channels = 2 + }; + struct pa_simple *s = NULL; + int ret = 1; + int error; + + if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, &error))) { + fprintf(stderr, "Failed to connect to server: %s\n", pa_strerror(error)); + goto finish; + } + + for (;;) { + uint8_t buf[BUFSIZE]; + ssize_t r; + + if ((r = read(STDIN_FILENO, buf, sizeof(buf))) <= 0) { + if (r == 0) /* eof */ + break; + + fprintf(stderr, "read() failed: %s\n", strerror(errno)); + goto finish; + } + + if (pa_simple_write(s, buf, r, &error) < 0) { + fprintf(stderr, "Failed to write data: %s\n", pa_strerror(error)); + goto finish; + } + } + + ret = 0; + +finish: + + if (s) + pa_simple_free(s); + + return ret; +} diff --git a/src/pacat.c b/src/pacat.c index 32220aeb7..c69148e68 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -59,18 +59,17 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user do_write(length); } -static void stream_complete_callback(struct pa_context*c, struct pa_stream *s, void *userdata) { - assert(c); +static void stream_complete_callback(struct pa_stream*s, int success, void *userdata) { + assert(s); - if (!s) { + if (!success) { fprintf(stderr, "Stream creation failed.\n"); mainloop_api->quit(mainloop_api, 1); return; } - stream = s; - pa_stream_set_die_callback(stream, stream_die_callback, NULL); - pa_stream_set_write_callback(stream, stream_write_callback, NULL); + pa_stream_set_die_callback(s, stream_die_callback, NULL); + pa_stream_set_write_callback(s, stream_write_callback, NULL); } static void context_complete_callback(struct pa_context *c, int success, void *userdata) { @@ -87,7 +86,7 @@ static void context_complete_callback(struct pa_context *c, int success, void *u goto fail; } - if (pa_stream_new(c, PA_STREAM_PLAYBACK, NULL, "pacat", &ss, NULL, stream_complete_callback, NULL) < 0) { + if (!(stream = pa_stream_new(c, PA_STREAM_PLAYBACK, NULL, "pacat", &ss, NULL, stream_complete_callback, NULL))) { fprintf(stderr, "pa_stream_new() failed.\n"); goto fail; } diff --git a/src/polyp-error.c b/src/polyp-error.c new file mode 100644 index 000000000..861711a2f --- /dev/null +++ b/src/polyp-error.c @@ -0,0 +1,25 @@ +#include + +#include "polyp-error.h" +#include "protocol-native-spec.h" + +static const char* const errortab[PA_ERROR_MAX] = { + [PA_ERROR_OK] = "OK", + [PA_ERROR_ACCESS] = "Access denied", + [PA_ERROR_COMMAND] = "Unknown command", + [PA_ERROR_INVALID] = "Invalid argument", + [PA_ERROR_EXIST] = "Entity exists", + [PA_ERROR_NOENTITY] = "No such entity", + [PA_ERROR_CONNECTIONREFUSED] = "Connection refused", + [PA_ERROR_PROTOCOL] = "Protocol corrupt", + [PA_ERROR_TIMEOUT] = "Timeout", + [PA_ERROR_AUTHKEY] = "Not authorization key", + [PA_ERROR_INTERNAL] = "Internal error" +}; + +const char*pa_strerror(uint32_t error) { + if (error >= PA_ERROR_MAX) + return NULL; + + return errortab[error]; +} diff --git a/src/polyp-error.h b/src/polyp-error.h new file mode 100644 index 000000000..7407f34cc --- /dev/null +++ b/src/polyp-error.h @@ -0,0 +1,10 @@ +#ifndef foopolyperrhfoo +#define foopolyperrhfoo + +#include + +#include "protocol-native-spec.h" + +const char* pa_strerror(uint32_t error); + +#endif diff --git a/src/polyp.c b/src/polyp.c index eb9a3c20a..c15d5d9f6 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -10,6 +10,7 @@ #include "dynarray.h" #include "socket-client.h" #include "pstream-util.h" +#include "authkey.h" #define DEFAULT_QUEUE_LENGTH 10240 #define DEFAULT_MAX_LENGTH 20480 @@ -26,14 +27,16 @@ struct pa_context { struct pa_dynarray *streams; struct pa_stream *first_stream; uint32_t ctag; - uint32_t errno; - enum { CONTEXT_UNCONNECTED, CONTEXT_CONNECTING, CONTEXT_READY, CONTEXT_DEAD} state; + uint32_t error; + enum { CONTEXT_UNCONNECTED, CONTEXT_CONNECTING, CONTEXT_AUTHORIZING, CONTEXT_SETTING_NAME, CONTEXT_READY, CONTEXT_DEAD} state; void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); void *connect_complete_userdata; void (*die_callback)(struct pa_context*c, void *userdata); void *die_userdata; + + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; }; struct pa_stream { @@ -52,7 +55,7 @@ struct pa_stream { void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); void *write_userdata; - void (*create_complete_callback)(struct pa_context*c, struct pa_stream *s, void *userdata); + void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); void *create_complete_userdata; void (*die_callback)(struct pa_stream*c, void *userdata); @@ -85,7 +88,7 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->streams = pa_dynarray_new(); assert(c->streams); c->first_stream = NULL; - c->errno = PA_ERROR_OK; + c->error = PA_ERROR_OK; c->state = CONTEXT_UNCONNECTED; c->ctag = 0; @@ -158,9 +161,11 @@ static int pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packe if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { fprintf(stderr, "polyp.c: invalid packet.\n"); + context_dead(c); return -1; } + return 0; } @@ -170,7 +175,7 @@ static int pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int assert(p && chunk && c && chunk->memblock && chunk->memblock->data); if (!(s = pa_dynarray_get(c->streams, channel))) - return -1; + return 0; if (s->read_callback) s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); @@ -178,15 +183,57 @@ static int pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int return 0; } +static int auth_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); + + if (command != PA_COMMAND_REPLY) { + if (command == PA_COMMAND_ERROR && pa_tagstruct_getu32(t, &c->error) < 0) + c->error = PA_ERROR_PROTOCOL; + else if (command == PA_COMMAND_TIMEOUT) + c->error = PA_ERROR_TIMEOUT; + + c->state = CONTEXT_DEAD; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return -1; + } + + if (c->state == CONTEXT_AUTHORIZING) { + struct pa_tagstruct *t; + c->state = CONTEXT_SETTING_NAME; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, c->name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, auth_complete_callback, c); + } else { + assert(c->state == CONTEXT_SETTING_NAME); + + c->state = CONTEXT_READY; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 1, c->connect_complete_userdata); + } + + return 0; +} + static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { struct pa_context *c = userdata; + struct pa_tagstruct *t; + uint32_t tag; assert(client && io && c && c->state == CONTEXT_CONNECTING); pa_socket_client_free(client); c->client = NULL; if (!io) { - c->errno = PA_ERROR_CONNECTIONREFUSED; + c->error = PA_ERROR_CONNECTIONREFUSED; c->state = CONTEXT_UNCONNECTED; if (c->connect_complete_callback) @@ -204,18 +251,27 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); assert(c->pdispatch); - c->state = CONTEXT_READY; - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 1, c->connect_complete_userdata); + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_AUTH); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, auth_complete_callback, c); + c->state = CONTEXT_AUTHORIZING; } int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { assert(c && c->state == CONTEXT_UNCONNECTED); + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { + c->error = PA_ERROR_AUTHKEY; + return -1; + } + assert(!c->client); if (!(c->client = pa_socket_client_new_unix(c->mainloop, server ? server : DEFAULT_SERVER))) { - c->errno = PA_ERROR_CONNECTIONREFUSED; + c->error = PA_ERROR_CONNECTIONREFUSED; return -1; } @@ -240,7 +296,7 @@ int pa_context_is_ready(struct pa_context *c) { int pa_context_errno(struct pa_context *c) { assert(c); - return c->errno; + return c->error; } void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { @@ -258,12 +314,12 @@ static int command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t t if (pa_tagstruct_getu32(t, &channel) < 0 || pa_tagstruct_getu32(t, &bytes) < 0 || !pa_tagstruct_eof(t)) { - c->errno = PA_ERROR_PROTOCOL; + c->error = PA_ERROR_PROTOCOL; return -1; } if (!(s = pa_dynarray_get(c->streams, channel))) { - c->errno = PA_ERROR_PROTOCOL; + c->error = PA_ERROR_PROTOCOL; return -1; } @@ -286,21 +342,19 @@ static int create_playback_callback(struct pa_pdispatch *pd, uint32_t command, u struct pa_context *c = s->context; assert(c); - if (command == PA_COMMAND_ERROR && pa_tagstruct_getu32(t, &s->context->errno) < 0) { - s->context->errno = PA_ERROR_PROTOCOL; - ret = -1; - } else if (command == PA_COMMAND_TIMEOUT) { - s->context->errno = PA_ERROR_TIMEOUT; - ret = -1; - } - + if (command == PA_COMMAND_ERROR && pa_tagstruct_getu32(t, &s->context->error) < 0) + s->context->error = PA_ERROR_PROTOCOL; + else if (command == PA_COMMAND_TIMEOUT) + s->context->error = PA_ERROR_TIMEOUT; + + ret = -1; goto fail; } if (pa_tagstruct_getu32(t, &s->channel) < 0 || pa_tagstruct_getu32(t, &s->device_index) < 0 || !pa_tagstruct_eof(t)) { - s->context->errno = PA_ERROR_PROTOCOL; + s->context->error = PA_ERROR_PROTOCOL; ret = -1; goto fail; } @@ -310,24 +364,24 @@ static int create_playback_callback(struct pa_pdispatch *pd, uint32_t command, u s->state = STREAM_READY; assert(s->create_complete_callback); - s->create_complete_callback(s->context, s, s->create_complete_userdata); + s->create_complete_callback(s, 1, s->create_complete_userdata); return 0; fail: assert(s->create_complete_callback); - s->create_complete_callback(s->context, NULL, s->create_complete_userdata); + s->create_complete_callback(s, 0, s->create_complete_userdata); pa_stream_free(s); return ret; } -int pa_stream_new( +struct pa_stream* pa_stream_new( struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, - void (*complete) (struct pa_context*c, struct pa_stream *s, void *userdata), + void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata) { struct pa_stream *s; diff --git a/src/polyp.h b/src/polyp.h index 171e3bdf8..77a6966f7 100644 --- a/src/polyp.h +++ b/src/polyp.h @@ -23,18 +23,18 @@ void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_cont int pa_context_is_dead(struct pa_context *c); int pa_context_is_ready(struct pa_context *c); -int pa_contect_errno(struct pa_context *c); +int pa_context_errno(struct pa_context *c); struct pa_stream; -int pa_stream_new( +struct pa_stream* pa_stream_new( struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, - void (*complete) (struct pa_context*c, struct pa_stream *s, void *userdata), + void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); void pa_stream_free(struct pa_stream *p); diff --git a/src/protocol-esound.c b/src/protocol-esound.c index 8198e72f3..cd6448fc6 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -13,6 +13,14 @@ #include "sink.h" #include "sample.h" +#include "authkey.h" + +#define COOKIE_FILE ".esd_auth" + +#define MEMBLOCKQ_LENGTH (10*1204) +#define MEMBLOCKQ_PREBUF (2*1024) +#define BUFSIZE (1024) + /* This is heavily based on esound's code */ struct connection { @@ -38,6 +46,7 @@ struct pa_protocol_esound { struct pa_idxset *connections; uint32_t sink_index; unsigned n_player; + uint8_t esd_key[ESD_KEY_LEN]; }; typedef struct proto_handler { @@ -46,11 +55,6 @@ typedef struct proto_handler { const char *description; } esd_proto_handler_info_t; -#define MEMBLOCKQ_LENGTH (10*1204) -#define MEMBLOCKQ_PREBUF (2*1024) - -#define BUFSIZE (1024) - static void sink_input_drop_cb(struct pa_sink_input *i, size_t length); static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); static void sink_input_kill_cb(struct pa_sink_input *i); @@ -162,7 +166,14 @@ static int esd_proto_connect(struct connection *c, const void *data, size_t leng int *ok; assert(length == (ESD_KEY_LEN + sizeof(uint32_t))); - c->authorized = 1; + if (!c->authorized) { + if (memcmp(data, c->protocol->esd_key, ESD_KEY_LEN) != 0) { + fprintf(stderr, "protocol-esound.c: Kicked client with invalid authorization key.\n"); + return -1; + } + + c->authorized = 1; + } ekey = *(uint32_t*)(data+ESD_KEY_LEN); if (ekey == ESD_ENDIAN_KEY) @@ -583,17 +594,21 @@ struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa p = malloc(sizeof(struct pa_protocol_esound)); assert(p); - p->public = 1; + + if (pa_authkey_load_from_home(COOKIE_FILE, p->esd_key, sizeof(p->esd_key)) < 0) { + free(p); + return NULL; + } + + p->public = 0; p->server = server; + pa_socket_server_set_callback(p->server, on_connection, p); p->core = core; p->connections = pa_idxset_new(NULL, NULL); assert(p->connections); p->sink_index = PA_IDXSET_INVALID; - p->n_player = 0; - pa_socket_server_set_callback(p->server, on_connection, p); - return p; } diff --git a/src/protocol-native-spec.h b/src/protocol-native-spec.h index df11ae3c6..07fc735b0 100644 --- a/src/protocol-native-spec.h +++ b/src/protocol-native-spec.h @@ -11,6 +11,8 @@ enum { PA_COMMAND_DELETE_RECORD_STREAM, PA_COMMAND_EXIT, PA_COMMAND_REQUEST, + PA_COMMAND_AUTH, + PA_COMMAND_SET_NAME, PA_COMMAND_MAX }; @@ -23,7 +25,13 @@ enum { PA_ERROR_NOENTITY, PA_ERROR_CONNECTIONREFUSED, PA_ERROR_PROTOCOL, - PA_ERROR_TIMEOUT + PA_ERROR_TIMEOUT, + PA_ERROR_AUTHKEY, + PA_ERROR_INTERNAL, + PA_ERROR_MAX }; +#define PA_NATIVE_COOKIE_LENGTH 256 +#define PA_NATIVE_COOKIE_FILE ".polypaudio-cookie" + #endif diff --git a/src/protocol-native.c b/src/protocol-native.c index 8e4dcae1c..9463a469a 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -12,6 +13,7 @@ #include "tagstruct.h" #include "pdispatch.h" #include "pstream-util.h" +#include "authkey.h" struct connection; struct pa_protocol_native; @@ -46,6 +48,7 @@ struct pa_protocol_native { struct pa_core *core; struct pa_socket_server *server; struct pa_idxset *connections; + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; }; static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); @@ -58,15 +61,21 @@ static void request_bytes(struct playback_stream*s); static int command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static int command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static int command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static int command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static int command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, + [PA_COMMAND_TIMEOUT] = { NULL }, [PA_COMMAND_REPLY] = { NULL }, [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream }, [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_playback_stream }, [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_AUTH] = { command_auth }, + [PA_COMMAND_REQUEST] = { NULL }, [PA_COMMAND_EXIT] = { command_exit }, + [PA_COMMAND_SET_NAME] = { command_set_name }, }; /* structure management */ @@ -294,6 +303,40 @@ static int command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, return 0; } +static int command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + const void*cookie; + assert(c && t); + + if (pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 || + !pa_tagstruct_eof(t)) + return -1; + + if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) { + fprintf(stderr, "protocol-native.c: Denied access to client with invalid authorization key.\n"); + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return 0; + } + + c->authorized = 1; + pa_pstream_send_simple_ack(c->pstream, tag); + return 0; +} + +static int command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + const char *name; + assert(c && t); + + if (pa_tagstruct_gets(t, &name) < 0 || + !pa_tagstruct_eof(t)) + return -1; + + pa_client_rename(c->client, name); + pa_pstream_send_simple_ack(c->pstream, tag); + return 0; +} + /*** pstream callbacks ***/ static int packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { @@ -340,6 +383,13 @@ static void die_callback(struct pa_pstream *p, void *userdata) { fprintf(stderr, "protocol-native: connection died.\n"); } +/*** client callbacks ***/ + +static void client_kill_cb(struct pa_client *c) { + assert(c && c->userdata); + connection_free(c->userdata); +} + /*** socket server callbacks ***/ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { @@ -354,6 +404,8 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo assert(p->core); c->client = pa_client_new(p->core, "NATIVE", "Client"); assert(c->client); + c->client->kill = client_kill_cb; + c->client->userdata = c; c->pstream = pa_pstream_new(p->core->mainloop, io); assert(c->pstream); @@ -380,6 +432,11 @@ struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct p p = malloc(sizeof(struct pa_protocol_native)); assert(p); + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, p->auth_cookie, sizeof(p->auth_cookie)) < 0) { + free(p); + return NULL; + } + p->public = 1; p->server = server; p->core = core; diff --git a/src/simple.c b/src/simple.c index a90d22bde..c1d1e96cb 100644 --- a/src/simple.c +++ b/src/simple.c @@ -1,23 +1,19 @@ +#include +#include + #include "simple.h" #include "polyp.h" #include "mainloop.h" +#include "polyp-error.h" struct pa_simple { - struct mainloop *mainloop; + struct pa_mainloop *mainloop; struct pa_context *context; struct pa_stream *stream; - size_t requested; int dead; }; -static void playback_callback(struct pa_stream *p, size_t length, void *userdata) { - struct pa_stream *sp = userdata; - assert(p && length && sp); - - sp->requested = length; -} - struct pa_simple* pa_simple_new( const char *server, const char *name, @@ -25,9 +21,11 @@ struct pa_simple* pa_simple_new( const char *dev, const char *stream_name, const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr) { + const struct pa_buffer_attr *attr, + int *perror) { struct pa_simple *p; + int error = PA_ERROR_INTERNAL; assert(ss); p = malloc(sizeof(struct pa_simple)); @@ -36,39 +34,43 @@ struct pa_simple* pa_simple_new( p->stream = NULL; p->mainloop = pa_mainloop_new(); assert(p->mainloop); - p->requested = 0; p->dead = 0; if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name))) goto fail; - if (pa_context_connect(c, server, NULL, NULL) < 0) + if (pa_context_connect(p->context, server, NULL, NULL) < 0) { + error = pa_context_errno(p->context); goto fail; + } - while (!pa_context_is_ready(c)) { - if (pa_context_is_dead(c)) + while (!pa_context_is_ready(p->context)) { + if (pa_context_is_dead(p->context)) { + error = pa_context_errno(p->context); goto fail; + } - if (mainloop_iterate(p->mainloop) < 0) + if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) goto fail; } - if (!(p->stream = pa_stream_new(p->context, dir, sink, stream_name, ss, attr, NULL, NULL))) + if (!(p->stream = pa_stream_new(p->context, dir, dev, stream_name, ss, attr, NULL, NULL))) goto fail; - while (!pa_stream_is_ready(c)) { - if (pa_stream_is_dead(c)) + while (!pa_stream_is_ready(p->stream)) { + if (pa_stream_is_dead(p->stream)) { + error = pa_context_errno(p->context); goto fail; + } - if (mainloop_iterate(p->mainloop) < 0) + if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) goto fail; } - pa_stream_set_write_callback(p->stream, playback_callback, p); - return p; fail: + *perror = error; pa_simple_free(p); return NULL; } @@ -83,38 +85,40 @@ void pa_simple_free(struct pa_simple *s) { pa_context_free(s->context); if (s->mainloop) - mainloop_free(s->mainloop); + pa_mainloop_free(s->mainloop); free(s); } -int pa_simple_write(struct pa_simple *s, const void*data, size_t length) { - assert(s && data); +int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *perror) { + assert(p && data); while (length > 0) { size_t l; - while (!s->requested) { - if (pa_context_is_dead(c)) + while (!(l = pa_stream_writable_size(p->stream))) { + if (pa_context_is_dead(p->context)) { + *perror = pa_context_errno(p->context); return -1; + } - if (mainloop_iterate(s->mainloop) < 0) + if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) { + *perror = PA_ERROR_INTERNAL; return -1; + } } - l = length; - if (l > s->requested) - l = s->requested; + if (l > length) + l = length; - pa_stream_write(s->stream, data, l); + pa_stream_write(p->stream, data, l); data += l; length -= l; - s->requested = -l; } return 0; } -int pa_simple_read(struct pa_simple *s, const void*data, size_t length) { +int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *perror) { assert(0); } diff --git a/src/simple.h b/src/simple.h index 80693056f..ed181201e 100644 --- a/src/simple.h +++ b/src/simple.h @@ -15,11 +15,12 @@ struct pa_simple* pa_simple_new( const char *dev, const char *stream_name, const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr); + const struct pa_buffer_attr *attr, + int *error); void pa_simple_free(struct pa_simple *s); -int pa_simple_write(struct pa_simple *s, const void*data, size_t length); -int pa_simple_read(struct pa_simple *s, const void*data, size_t length); +int pa_simple_write(struct pa_simple *s, const void*data, size_t length, int *error); +int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *error); #endif diff --git a/src/tagstruct.c b/src/tagstruct.c index 67f524611..e57e755c1 100644 --- a/src/tagstruct.c +++ b/src/tagstruct.c @@ -13,7 +13,8 @@ enum tags { TAG_S16 = 's', TAG_U8 = 'B', TAG_S8 = 'b', - TAG_SAMPLE_SPEC = 'a' + TAG_SAMPLE_SPEC = 'a', + TAG_ARBITRARY = 'x' }; struct pa_tagstruct { @@ -100,6 +101,18 @@ void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample t->length += 7; } + +void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) { + assert(t && p); + + extend(t, 5+length); + t->data[t->length] = TAG_ARBITRARY; + *((uint32_t*) (t->data+t->length+1)) = htonl(length); + if (length) + memcpy(t->data+t->length+5, p, length); + t->length += 5+length; +} + int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) { int error = 0; size_t n; @@ -173,6 +186,22 @@ int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec * return 0; } +int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length) { + assert(t && p); + + if (t->rindex+5+length > t->length) + return -1; + + if (t->data[t->rindex] != TAG_ARBITRARY) + return -1; + + if (ntohl(*((uint32_t*) (t->data+t->rindex+1))) != length) + return -1; + + *p = t->data+t->rindex+5; + t->rindex += 5+length; + return 0; +} int pa_tagstruct_eof(struct pa_tagstruct*t) { assert(t); diff --git a/src/tagstruct.h b/src/tagstruct.h index be4e01faf..2c1ae5874 100644 --- a/src/tagstruct.h +++ b/src/tagstruct.h @@ -16,11 +16,13 @@ void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s); void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i); void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c); void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss); +void pa_tagstruct_put_arbitrary(struct pa_tagstruct*t, const void *p, size_t length); int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s); int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i); int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c); int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss); +int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length); int pa_tagstruct_eof(struct pa_tagstruct*t); const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l); diff --git a/src/todo b/src/todo index 505eeac2e..5b0d893f6 100644 --- a/src/todo +++ b/src/todo @@ -3,17 +3,25 @@ sync() function more functions - simple library -- kill() routines in all modules + - config parser/cmdline + - move more stuff from module-oss[-dma] to liboss-util -- svn-id and license in every file - in module-oss: create source first, than sink +- rename files +- svn-id and license in every file +- documentation + + + -- post 0.1 - future cancellation - client-ui - clip cache - autoloading/autounloading +- ldap/rendezvous +- doxygen drivers: - libao diff --git a/src/util.c b/src/util.c index 5fff55e3a..4ade681a8 100644 --- a/src/util.c +++ b/src/util.c @@ -124,3 +124,87 @@ int pa_make_tcp_socket_low_delay(int fd) { return ret; } + +ssize_t pa_loop_read(int fd, void*data, size_t size) { + ssize_t ret = 0; + assert(fd >= 0 && data && size); + + while (size > 0) { + ssize_t r; + + if ((r = read(fd, data, size)) < 0) + return r; + + if (r == 0) + break; + + ret += r; + data += r; + size -= r; + } + + return ret; +} + +ssize_t pa_loop_write(int fd, const void*data, size_t size) { + ssize_t ret = 0; + assert(fd >= 0 && data && size); + + while (size > 0) { + ssize_t r; + + if ((r = write(fd, data, size)) < 0) + return r; + + if (r == 0) + break; + + ret += r; + data += r; + size -= r; + } + + return ret; +} + +int pa_unix_socket_is_stale(const char *fn) { + struct sockaddr_un sa; + int fd = -1, ret = -1; + + if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "socket(): %s\n", strerror(errno)); + goto finish; + } + + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1); + sa.sun_path[sizeof(sa.sun_path) - 1] = 0; + + if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) { + if (errno == ECONNREFUSED) + ret = 1; + } else + ret = 0; + +finish: + if (fd >= 0) + close(fd); + + return ret; +} + +int pa_unix_socket_remove_stale(const char *fn) { + int r; + + if ((r = pa_unix_socket_is_stale(fn)) < 0) + return errno != ENOENT ? -1 : 0; + + if (!r) + return 0; + + /* Yes, here is a race condition. But who cares? */ + if (unlink(fn) < 0) + return -1; + + return 0; +} diff --git a/src/util.h b/src/util.h index b8759ad83..40095e01b 100644 --- a/src/util.h +++ b/src/util.h @@ -12,4 +12,10 @@ int pa_make_secure_dir(const char* dir); int pa_make_socket_low_delay(int fd); int pa_make_tcp_socket_low_delay(int fd); +ssize_t pa_loop_read(int fd, void*data, size_t size); +ssize_t pa_loop_write(int fd, const void*data, size_t size); + +int pa_unix_socket_is_stale(const char *fn); +int pa_unix_socket_remove_stale(const char *fn); + #endif From e8d1185c4221fef9d712c1f375d8e592721b6943 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 7 Jul 2004 00:22:46 +0000 Subject: [PATCH 0051/1514] draining ind native protocol fixes in callback code on object destruction simple protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@52 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 12 +- src/client.c | 2 +- src/core.c | 3 + src/iochannel.h | 2 + src/main.c | 17 +- src/memblockq.c | 71 +++++--- src/memblockq.h | 22 ++- src/module-cli.c | 4 +- src/module-oss-mmap.c | 2 +- src/module-oss.c | 4 +- src/module-pipe-sink.c | 4 +- src/module-protocol-stub.c | 4 +- src/module.c | 6 +- src/module.h | 4 + src/pacat-simple.c | 8 +- src/pacat.c | 84 ++++++--- src/pdispatch.c | 107 ++++++++--- src/pdispatch.h | 10 +- src/polyp.c | 365 +++++++++++++++++++++++++++---------- src/polyp.h | 9 + src/polypdef.h | 5 +- src/protocol-esound.c | 18 +- src/protocol-native-spec.h | 2 + src/protocol-native.c | 159 ++++++++++------ src/protocol-simple.c | 20 +- src/pstream.c | 118 +++++++----- src/pstream.h | 10 +- src/sample.h | 2 + src/simple.c | 54 +++--- src/sink.c | 12 +- src/sinkinput.c | 17 +- src/socket-client.h | 2 + src/socket-server.h | 2 + src/source.c | 6 +- src/sourceoutput.c | 13 +- src/todo | 10 +- src/util.c | 15 +- src/util.h | 2 + 38 files changed, 843 insertions(+), 364 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 70e7e09b8..d7002caf1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -220,6 +220,7 @@ libpolyp_la_SOURCES = polyp.c polyp.h \ protocol-native-spec.h \ mainloop-api.c mainloop-api.h \ mainloop.c mainloop.h \ + mainloop-signal.c mainloop-signal.h \ idxset.c idxset.h \ util.c util.h \ memblock.c memblock.h \ @@ -237,12 +238,13 @@ libpolyp_error_la_CFLAGS = $(AM_CFLAGS) libpolyp_simple_la_SOURCES = simple.c simple.h libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) -libpolyp_simple_la_LIBADD = libpolyp.la #libpolyp-error.la +libpolyp_simple_la_LIBADD = libpolyp.la +#libpolyp-error.la -pacat_SOURCES = pacat.c #$(libpolyp_la_SOURCES) -pacat_LDADD = libpolyp.la +pacat_SOURCES = pacat.c $(libpolyp_la_SOURCES) $(libpolyp_error_la_SOURCES) +#pacat_LDADD = libpolyp.la pacat_CFLAGS = $(AM_CFLAGS) -pacat_simple_SOURCES = pacat-simple.c -pacat_simple_LDADD = libpolyp-simple.a +pacat_simple_SOURCES = pacat-simple.c $(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) +#pacat_simple_LDADD = libpolyp-simple.la libpolyp-error.la pacat_simple_CFLAGS = $(AM_CFLAGS) diff --git a/src/client.c b/src/client.c index 7f1648a73..d07f188fe 100644 --- a/src/client.c +++ b/src/client.c @@ -59,7 +59,7 @@ char *pa_client_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u client(s).\n", pa_idxset_ncontents(c->clients)); for (client = pa_idxset_first(c->clients, &index); client; client = pa_idxset_next(c->clients, &index)) - pa_strbuf_printf(s, " index: %u, name: <%s>, protocol_name: <%s>\n", client->index, client->name, client->protocol_name); + pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tprotocol_name: <%s>\n", client->index, client->name, client->protocol_name); return pa_strbuf_tostring_free(s); } diff --git a/src/core.c b/src/core.c index 461590377..a1fe7d977 100644 --- a/src/core.c +++ b/src/core.c @@ -7,6 +7,7 @@ #include "sink.h" #include "source.h" #include "namereg.h" +#include "util.h" struct pa_core* pa_core_new(struct pa_mainloop_api *m) { struct pa_core* c; @@ -24,6 +25,8 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->modules = NULL; c->namereg = NULL; + + pa_check_for_sigpipe(); return c; }; diff --git a/src/iochannel.h b/src/iochannel.h index c550af19a..1a5057d66 100644 --- a/src/iochannel.h +++ b/src/iochannel.h @@ -4,6 +4,8 @@ #include #include "mainloop-api.h" +/* It is safe to destroy the calling iochannel object from the callback */ + struct pa_iochannel; struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd); diff --git a/src/main.c b/src/main.c index 88552fed4..c7a83fec3 100644 --- a/src/main.c +++ b/src/main.c @@ -12,10 +12,16 @@ static struct pa_mainloop *mainloop; -static void signal_callback(void *id, int sig, void *userdata) { +static void exit_signal_callback(void *id, int sig, void *userdata) { struct pa_mainloop_api* m = pa_mainloop_get_api(mainloop); m->quit(m, 1); - fprintf(stderr, "main: got signal.\n"); + fprintf(stderr, __FILE__": got signal.\n"); +} + +static void aux_signal_callback(void *id, int sig, void *userdata) { + struct pa_core *c = userdata; + assert(c); + pa_module_load(c, sig == SIGUSR1 ? "module-cli" : "module-cli-protocol-unix", NULL); } int main(int argc, char *argv[]) { @@ -30,12 +36,12 @@ int main(int argc, char *argv[]) { r = pa_signal_init(pa_mainloop_get_api(mainloop)); assert(r == 0); - pa_signal_register(SIGINT, signal_callback, NULL); + pa_signal_register(SIGINT, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); - + pa_module_load(c, "module-oss", "/dev/dsp"); /* pa_module_load(c, "module-pipe-sink", NULL);*/ pa_module_load(c, "module-simple-protocol-tcp", NULL); @@ -46,6 +52,9 @@ int main(int argc, char *argv[]) { pa_module_load(c, "module-native-protocol-unix", NULL); pa_module_load(c, "module-esound-protocol-tcp", NULL); pa_module_load(c, "module-cli", NULL); + + pa_signal_register(SIGUSR1, aux_signal_callback, c); + pa_signal_register(SIGUSR2, aux_signal_callback, c); fprintf(stderr, "main: mainloop entry.\n"); if (pa_mainloop_run(mainloop, &retval) < 0) diff --git a/src/memblockq.c b/src/memblockq.c index b70a67ffe..e5dab6870 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -15,30 +15,45 @@ struct memblock_list { struct pa_memblockq { struct memblock_list *blocks, *blocks_tail; unsigned n_blocks; - size_t total_length, maxlength, base, prebuf; + size_t current_length, maxlength, tlength, base, prebuf, minreq; int measure_delay; uint32_t delay; struct pa_mcalign *mcalign; }; -struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t base, size_t prebuf) { +struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t base, size_t prebuf, size_t minreq) { struct pa_memblockq* bq; - assert(maxlength && base); + assert(maxlength && base && maxlength); bq = malloc(sizeof(struct pa_memblockq)); assert(bq); bq->blocks = bq->blocks_tail = 0; bq->n_blocks = 0; - bq->total_length = 0; - bq->base = base; - bq->maxlength = ((maxlength+base-1)/base)*base; - bq->prebuf = prebuf == (size_t) -1 ? bq->maxlength/2 : prebuf; + + bq->current_length = 0; + + fprintf(stderr, "memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq); + bq->base = base; + + bq->maxlength = ((maxlength+base-1)/base)*base; + assert(bq->maxlength >= base); + + bq->tlength = ((tlength+base-1)/base)*base; + if (bq->tlength == 0 || bq->tlength >= bq->maxlength) + bq->tlength = bq->maxlength; + + bq->prebuf = (prebuf == (size_t) -1) ? bq->maxlength/2 : prebuf; + bq->prebuf = (bq->prebuf/base)*base; if (bq->prebuf > bq->maxlength) bq->prebuf = bq->maxlength; - assert(bq->maxlength >= base); + bq->minreq = (minreq/base)*base; + if (bq->minreq == 0) + bq->minreq = 1; + fprintf(stderr, "memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); + bq->measure_delay = 0; bq->delay = 0; @@ -88,7 +103,7 @@ void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, bq->blocks_tail = q; bq->n_blocks++; - bq->total_length += chunk->length; + bq->current_length += chunk->length; pa_memblockq_shorten(bq, bq->maxlength); } @@ -96,7 +111,7 @@ void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, int pa_memblockq_peek(struct pa_memblockq* bq, struct pa_memchunk *chunk) { assert(bq && chunk); - if (!bq->blocks || bq->total_length < bq->prebuf) + if (!bq->blocks || bq->current_length < bq->prebuf) return -1; bq->prebuf = 0; @@ -116,7 +131,7 @@ int memblockq_pop(struct memblockq* bq, struct pa_memchunk *chunk) { assert(bq && chunk); - if (!bq->blocks || bq->total_length < bq->prebuf) + if (!bq->blocks || bq->current_length < bq->prebuf) return -1; bq->prebuf = 0; @@ -127,7 +142,7 @@ int memblockq_pop(struct memblockq* bq, struct pa_memchunk *chunk) { *chunk = q->chunk; bq->n_blocks--; - bq->total_length -= chunk->length; + bq->current_length -= chunk->length; free(q); return 0; @@ -159,7 +174,7 @@ void pa_memblockq_drop(struct pa_memblockq *bq, size_t length) { while (length > 0) { size_t l = length; - assert(bq->blocks && bq->total_length >= length); + assert(bq->blocks && bq->current_length >= length); if (l > bq->blocks->chunk.length) l = bq->blocks->chunk.length; @@ -169,7 +184,7 @@ void pa_memblockq_drop(struct pa_memblockq *bq, size_t length) { bq->blocks->chunk.index += l; bq->blocks->chunk.length -= l; - bq->total_length -= l; + bq->current_length -= l; if (bq->blocks->chunk.length == 0) { struct memblock_list *q; @@ -192,12 +207,12 @@ void pa_memblockq_shorten(struct pa_memblockq *bq, size_t length) { size_t l; assert(bq); - if (bq->total_length <= length) + if (bq->current_length <= length) return; fprintf(stderr, "Warning! pa_memblockq_shorten()\n"); - l = bq->total_length - length; + l = bq->current_length - length; l /= bq->base; l *= bq->base; @@ -213,14 +228,13 @@ void pa_memblockq_empty(struct pa_memblockq *bq) { int pa_memblockq_is_readable(struct pa_memblockq *bq) { assert(bq); - return bq->total_length >= bq->prebuf; + return bq->current_length >= bq->prebuf; } int pa_memblockq_is_writable(struct pa_memblockq *bq, size_t length) { assert(bq); - assert(length <= bq->maxlength); - return bq->total_length + length <= bq->maxlength; + return bq->current_length + length <= bq->tlength; } uint32_t pa_memblockq_get_delay(struct pa_memblockq *bq) { @@ -230,16 +244,20 @@ uint32_t pa_memblockq_get_delay(struct pa_memblockq *bq) { uint32_t pa_memblockq_get_length(struct pa_memblockq *bq) { assert(bq); - return bq->total_length; + return bq->current_length; } -uint32_t pa_memblockq_missing_to(struct pa_memblockq *bq, size_t qlen) { - assert(bq && qlen); +uint32_t pa_memblockq_missing(struct pa_memblockq *bq) { + size_t l; + assert(bq); - if (bq->total_length >= qlen) + if (bq->current_length >= bq->tlength) return 0; - return qlen - bq->total_length; + l = bq->tlength - bq->current_length; + assert(l); + + return (l >= bq->minreq) ? l : 0; } void pa_memblockq_push_align(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta) { @@ -264,3 +282,8 @@ void pa_memblockq_push_align(struct pa_memblockq* bq, const struct pa_memchunk * delta = 0; } } + +uint32_t pa_memblockq_get_minreq(struct pa_memblockq *bq) { + assert(bq); + return bq->minreq; +} diff --git a/src/memblockq.h b/src/memblockq.h index d8b9567f8..bece4fd76 100644 --- a/src/memblockq.h +++ b/src/memblockq.h @@ -8,11 +8,18 @@ struct pa_memblockq; -/* Parameters: the maximum length of the memblock queue, a base value -for all operations (that is, all byte operations shall work on -multiples of this base value) and an amount of bytes to prebuffer -before having pa_memblockq_peek() succeed. */ -struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t base, size_t prebuf); +/* Parameters: + - maxlength: maximum length of queue. If more data is pushed into the queue, data from the front is dropped + - length: the target length of the queue. + - base: a base value for all metrics. Only multiples of this value are popped from the queue + - prebuf: before passing the first byte out, make sure that enough bytes are in the queue + - minreq: pa_memblockq_missing() will only return values greater than this value +*/ +struct pa_memblockq* pa_memblockq_new(size_t maxlength, + size_t tlength, + size_t base, + size_t prebuf, + size_t minreq); void pa_memblockq_free(struct pa_memblockq*bq); /* Push a new memory chunk into the queue. Optionally specify a value for future cancellation. This is currently not implemented, however! */ @@ -46,6 +53,9 @@ uint32_t pa_memblockq_get_delay(struct pa_memblockq *bq); uint32_t pa_memblockq_get_length(struct pa_memblockq *bq); /* Return how many bytes are missing in queue to the specified fill amount */ -uint32_t pa_memblockq_missing_to(struct pa_memblockq *bq, size_t qlen); +uint32_t pa_memblockq_missing(struct pa_memblockq *bq); + + +uint32_t pa_memblockq_get_minreq(struct pa_memblockq *bq); #endif diff --git a/src/module-cli.c b/src/module-cli.c index 7306ade55..a6e9582d7 100644 --- a/src/module-cli.c +++ b/src/module-cli.c @@ -14,7 +14,7 @@ static void eof_cb(struct pa_cli*c, void *userdata) { pa_module_unload_request(m->core, m); } -int module_init(struct pa_core *c, struct pa_module*m) { +int pa_module_init(struct pa_core *c, struct pa_module*m) { struct pa_iochannel *io; assert(c && m); @@ -35,7 +35,7 @@ int module_init(struct pa_core *c, struct pa_module*m) { return 0; } -void module_done(struct pa_core *c, struct pa_module*m) { +void pa_module_done(struct pa_core *c, struct pa_module*m) { assert(c && m); pa_cli_free(m->userdata); diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index ef2b19d0a..62c2cc2a5 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -180,7 +180,7 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { return pa_samples_usec(u->out_fill, &s->sample_spec); } -int module_init(struct pa_core *c, struct pa_module*m) { +int pa_module_init(struct pa_core *c, struct pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; char *p; diff --git a/src/module-oss.c b/src/module-oss.c index 310c89c0a..5ec9d2d70 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -111,7 +111,7 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { return pa_samples_usec(arg, &s->sample_spec); } -int module_init(struct pa_core *c, struct pa_module*m) { +int pa_module_init(struct pa_core *c, struct pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; char *p; @@ -224,7 +224,7 @@ fail: return -1; } -void module_done(struct pa_core *c, struct pa_module*m) { +void pa_module_done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index ea5c15dbf..efba3b5f2 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -73,7 +73,7 @@ static void io_callback(struct pa_iochannel *io, void*userdata) { do_write(u); } -int module_init(struct pa_core *c, struct pa_module*m) { +int pa_module_init(struct pa_core *c, struct pa_module*m) { struct userdata *u = NULL; struct stat st; char *p; @@ -137,7 +137,7 @@ fail: return -1; } -void module_done(struct pa_core *c, struct pa_module*m) { +void pa_module_done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 713e0ab8f..885ea4c87 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -47,7 +47,7 @@ #endif #endif -int module_init(struct pa_core *c, struct pa_module*m) { +int pa_module_init(struct pa_core *c, struct pa_module*m) { struct pa_socket_server *s; assert(c && m); @@ -91,7 +91,7 @@ int module_init(struct pa_core *c, struct pa_module*m) { return 0; } -void module_done(struct pa_core *c, struct pa_module*m) { +void pa_module_done(struct pa_core *c, struct pa_module*m) { assert(c && m); protocol_free(m->userdata); diff --git a/src/module.c b/src/module.c index 468998ba2..87df3b38d 100644 --- a/src/module.c +++ b/src/module.c @@ -23,10 +23,10 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char if (!(m->dl = lt_dlopenext(name))) goto fail; - if (!(m->init = lt_dlsym(m->dl, "module_init"))) + if (!(m->init = lt_dlsym(m->dl, "pa_module_init"))) goto fail; - if (!(m->done = lt_dlsym(m->dl, "module_done"))) + if (!(m->done = lt_dlsym(m->dl, "pa_module_done"))) goto fail; m->userdata = NULL; @@ -124,7 +124,7 @@ char *pa_module_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_ncontents(c->modules)); for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) - pa_strbuf_printf(s, " index: %u, name: <%s>, argument: <%s>\n", m->index, m->name, m->argument); + pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\targument: <%s>\n", m->index, m->name, m->argument); return pa_strbuf_tostring_free(s); } diff --git a/src/module.h b/src/module.h index 1cc7d775b..2a9cf5583 100644 --- a/src/module.h +++ b/src/module.h @@ -30,4 +30,8 @@ char *pa_module_list_to_string(struct pa_core *c); void pa_module_unload_request(struct pa_core *c, struct pa_module *m); +/* These to following prototypes are for module entrypoints and not implemented by the core */ +int pa_module_init(struct pa_core *c, struct pa_module*m); +void pa_module_done(struct pa_core *c, struct pa_module*m); + #endif diff --git a/src/pacat-simple.c b/src/pacat-simple.c index 5408221c4..8b48bdd33 100644 --- a/src/pacat-simple.c +++ b/src/pacat-simple.c @@ -19,7 +19,7 @@ int main(int argc, char*argv[]) { int error; if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, &error))) { - fprintf(stderr, "Failed to connect to server: %s\n", pa_strerror(error)); + fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); goto finish; } @@ -31,16 +31,16 @@ int main(int argc, char*argv[]) { if (r == 0) /* eof */ break; - fprintf(stderr, "read() failed: %s\n", strerror(errno)); + fprintf(stderr, __FILE__": read() failed: %s\n", strerror(errno)); goto finish; } if (pa_simple_write(s, buf, r, &error) < 0) { - fprintf(stderr, "Failed to write data: %s\n", pa_strerror(error)); + fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(error)); goto finish; } } - + ret = 0; finish: diff --git a/src/pacat.c b/src/pacat.c index c69148e68..75a94fc07 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,7 +7,9 @@ #include #include "polyp.h" +#include "polyp-error.h" #include "mainloop.h" +#include "mainloop-signal.h" static struct pa_context *context = NULL; static struct pa_stream *stream = NULL; @@ -17,21 +20,29 @@ static size_t buffer_length = 0, buffer_index = 0; static void* stdin_source = NULL; +static void quit(int ret) { + assert(mainloop_api); + mainloop_api->quit(mainloop_api, ret); +} + static void context_die_callback(struct pa_context *c, void *userdata) { assert(c); fprintf(stderr, "Connection to server shut down, exiting.\n"); - mainloop_api->quit(mainloop_api, 1); + quit(1); } static void stream_die_callback(struct pa_stream *s, void *userdata) { assert(s); fprintf(stderr, "Stream deleted, exiting.\n"); - mainloop_api->quit(mainloop_api, 1); + quit(1); } static void do_write(size_t length) { size_t l; - assert(buffer && buffer_length); + assert(length); + + if (!buffer || !buffer_length) + return; l = length; if (l > buffer_length) @@ -50,8 +61,9 @@ static void do_write(size_t length) { static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { assert(s && length); - - mainloop_api->enable_io(mainloop_api, stdin_source, PA_MAINLOOP_API_IO_EVENT_INPUT); + + if (stdin_source) + mainloop_api->enable_io(mainloop_api, stdin_source, PA_MAINLOOP_API_IO_EVENT_INPUT); if (!buffer) return; @@ -63,13 +75,12 @@ static void stream_complete_callback(struct pa_stream*s, int success, void *user assert(s); if (!success) { - fprintf(stderr, "Stream creation failed.\n"); - mainloop_api->quit(mainloop_api, 1); + fprintf(stderr, "Stream creation failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + quit(1); return; } - pa_stream_set_die_callback(s, stream_die_callback, NULL); - pa_stream_set_write_callback(s, stream_write_callback, NULL); + fprintf(stderr, "Stream created.\n"); } static void context_complete_callback(struct pa_context *c, int success, void *userdata) { @@ -82,43 +93,59 @@ static void context_complete_callback(struct pa_context *c, int success, void *u assert(c && !stream); if (!success) { - fprintf(stderr, "Connection failed\n"); - goto fail; - } - - if (!(stream = pa_stream_new(c, PA_STREAM_PLAYBACK, NULL, "pacat", &ss, NULL, stream_complete_callback, NULL))) { - fprintf(stderr, "pa_stream_new() failed.\n"); + fprintf(stderr, "Connection failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } + fprintf(stderr, "Connection established.\n"); + + if (!(stream = pa_stream_new(c, PA_STREAM_PLAYBACK, NULL, "pacat", &ss, NULL, stream_complete_callback, NULL))) { + fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(c))); + goto fail; + } + + pa_stream_set_die_callback(stream, stream_die_callback, NULL); + pa_stream_set_write_callback(stream, stream_write_callback, NULL); + return; fail: - mainloop_api->quit(mainloop_api, 1); + quit(1); +} + +static void context_drain_complete(struct pa_context*c, void *userdata) { + quit(0); } static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { size_t l, w = 0; ssize_t r; - assert(a == mainloop_api && id && fd == STDIN_FILENO && events == PA_MAINLOOP_API_IO_EVENT_INPUT); + assert(a == mainloop_api && id && fd == STDIN_FILENO && events == PA_MAINLOOP_API_IO_EVENT_INPUT && stdin_source == id); if (buffer) { mainloop_api->enable_io(mainloop_api, stdin_source, PA_MAINLOOP_API_IO_EVENT_NULL); return; } - if (!stream || !(l = w = pa_stream_writable_size(stream))) + if (!stream || !pa_stream_is_ready(stream) || !(l = w = pa_stream_writable_size(stream))) l = 4096; + buffer = malloc(l); assert(buffer); if ((r = read(fd, buffer, l)) <= 0) { - if (r == 0) - mainloop_api->quit(mainloop_api, 0); - else { + if (r == 0) { + fprintf(stderr, "Got EOF.\n"); + if (pa_context_drain(context, context_drain_complete, NULL) < 0) + quit(0); + else + fprintf(stderr, "Draining connection to server.\n"); + } else { fprintf(stderr, "read() failed: %s\n", strerror(errno)); - mainloop_api->quit(mainloop_api, 1); + quit(1); } + mainloop_api->cancel_io(mainloop_api, stdin_source); + stdin_source = NULL; return; } @@ -129,9 +156,15 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m do_write(w); } + +static void exit_signal_callback(void *id, int sig, void *userdata) { + fprintf(stderr, "Got SIGINT, exiting.\n"); + quit(0); +} + int main(int argc, char *argv[]) { struct pa_mainloop* m; - int ret = 1; + int ret = 1, r; if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); @@ -140,6 +173,11 @@ int main(int argc, char *argv[]) { mainloop_api = pa_mainloop_get_api(m); + r = pa_signal_init(mainloop_api); + assert(r == 0); + pa_signal_register(SIGINT, exit_signal_callback, NULL); + signal(SIGPIPE, SIG_IGN); + if (!(stdin_source = mainloop_api->source_io(mainloop_api, STDIN_FILENO, PA_MAINLOOP_API_IO_EVENT_INPUT, stdin_callback, NULL))) { fprintf(stderr, "source_io() failed.\n"); goto quit; diff --git a/src/pdispatch.c b/src/pdispatch.c index c2db134d9..ec4541909 100644 --- a/src/pdispatch.c +++ b/src/pdispatch.c @@ -4,10 +4,26 @@ #include "pdispatch.h" #include "protocol-native-spec.h" +static const char *command_names[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = "ERROR", + [PA_COMMAND_TIMEOUT] = "TIMEOUT", + [PA_COMMAND_REPLY] = "REPLY", + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = "CREATE_PLAYBACK_STREAM", + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = "DELETE_PLAYBACK_STREAM", + [PA_COMMAND_CREATE_RECORD_STREAM] = "CREATE_RECORD_STREAM", + [PA_COMMAND_DELETE_RECORD_STREAM] = "DELETE_RECORD_STREAM", + [PA_COMMAND_AUTH] = "AUTH", + [PA_COMMAND_REQUEST] = "REQUEST", + [PA_COMMAND_EXIT] = "EXIT", + [PA_COMMAND_SET_NAME] = "SET_NAME", + [PA_COMMAND_LOOKUP_SINK] = "LOOKUP_SINK", + [PA_COMMAND_LOOKUP_SOURCE] = "LOOKUP_SOURCE", +}; + struct reply_info { struct pa_pdispatch *pdispatch; struct reply_info *next, *previous; - int (*callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + void (*callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); void *userdata; uint32_t tag; void *mainloop_timeout; @@ -18,6 +34,9 @@ struct pa_pdispatch { const struct pa_pdispatch_command *command_table; unsigned n_commands; struct reply_info *replies; + void (*drain_callback)(struct pa_pdispatch *pd, void *userdata); + void *drain_userdata; + int in_use, shall_free; }; static void reply_info_free(struct reply_info *r) { @@ -49,11 +68,21 @@ struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *mainloop, const st pd->command_table = table; pd->n_commands = entries; pd->replies = NULL; + pd->drain_callback = NULL; + pd->drain_userdata = NULL; + + pd->in_use = pd->shall_free = 0; return pd; } void pa_pdispatch_free(struct pa_pdispatch *pd) { assert(pd); + + if (pd->in_use) { + pd->shall_free = 1; + return; + } + while (pd->replies) reply_info_free(pd->replies); free(pd); @@ -61,60 +90,61 @@ void pa_pdispatch_free(struct pa_pdispatch *pd) { int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *userdata) { uint32_t tag, command; - assert(pd && packet); struct pa_tagstruct *ts = NULL; - assert(pd && packet && packet->data); + int ret = -1; + assert(pd && packet && packet->data && !pd->in_use); if (packet->length <= 8) - goto fail; + goto finish; ts = pa_tagstruct_new(packet->data, packet->length); assert(ts); if (pa_tagstruct_getu32(ts, &command) < 0 || pa_tagstruct_getu32(ts, &tag) < 0) - goto fail; + goto finish; + + /*fprintf(stderr, __FILE__": Recieved opcode <%s>\n", command_names[command]);*/ if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) { struct reply_info *r; - int done = 0; for (r = pd->replies; r; r = r->next) { - if (r->tag == tag) { - int ret = r->callback(r->pdispatch, command, tag, ts, r->userdata); - reply_info_free(r); - - if (ret < 0) - goto fail; - - done = 1; + if (r->tag != tag) + continue; + + pd->in_use = 1; + assert(r->callback); + r->callback(r->pdispatch, command, tag, ts, r->userdata); + pd->in_use = 0; + reply_info_free(r); + + if (pd->shall_free) { + pa_pdispatch_free(pd); break; } - } - if (!done) - goto fail; + if (pd->drain_callback && !pa_pdispatch_is_pending(r->pdispatch)) + pd->drain_callback(r->pdispatch, r->pdispatch->drain_userdata); + + break; + } } else if (pd->command_table && command < pd->n_commands) { const struct pa_pdispatch_command *c = pd->command_table+command; - if (!c->proc) - goto fail; - - if (c->proc(pd, command, tag, ts, userdata) < 0) - goto fail; + if (c->proc) + c->proc(pd, command, tag, ts, userdata); } else - goto fail; - - pa_tagstruct_free(ts); - - return 0; + goto finish; -fail: + ret = 0; + +finish: if (ts) pa_tagstruct_free(ts); - return -1; + return ret; } static void timeout_callback(struct pa_mainloop_api*m, void *id, const struct timeval *tv, void *userdata) { @@ -123,9 +153,12 @@ static void timeout_callback(struct pa_mainloop_api*m, void *id, const struct ti r->callback(r->pdispatch, PA_COMMAND_TIMEOUT, r->tag, NULL, r->userdata); reply_info_free(r); + + if (r->pdispatch->drain_callback && !pa_pdispatch_is_pending(r->pdispatch)) + r->pdispatch->drain_callback(r->pdispatch, r->pdispatch->drain_userdata); } -void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int timeout, int (*cb)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void *userdata) { +void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int timeout, void (*cb)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void *userdata) { struct reply_info *r; struct timeval tv; assert(pd && cb); @@ -149,3 +182,17 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time r->next->previous = r; pd->replies = r; } + +int pa_pdispatch_is_pending(struct pa_pdispatch *pd) { + assert(pd); + + return !!pd->replies; +} + +void pa_pdispatch_set_drain_callback(struct pa_pdispatch *pd, void (*cb)(struct pa_pdispatch *pd, void *userdata), void *userdata) { + assert(pd); + assert(!cb || pa_pdispatch_is_pending(pd)); + + pd->drain_callback = cb; + pd->drain_userdata = userdata; +} diff --git a/src/pdispatch.h b/src/pdispatch.h index 736867005..35e938299 100644 --- a/src/pdispatch.h +++ b/src/pdispatch.h @@ -8,8 +8,10 @@ struct pa_pdispatch; +/* It is safe to destroy the calling pdispatch object from all callbacks */ + struct pa_pdispatch_command { - int (*proc)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + void (*proc)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); }; struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *m, const struct pa_pdispatch_command*table, unsigned entries); @@ -17,6 +19,10 @@ void pa_pdispatch_free(struct pa_pdispatch *pd); int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*p, void *userdata); -void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int timeout, int (*cb)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void *userdata); +void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int timeout, void (*cb)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void *userdata); + +int pa_pdispatch_is_pending(struct pa_pdispatch *pd); + +void pa_pdispatch_set_drain_callback(struct pa_pdispatch *pd, void (*cb)(struct pa_pdispatch *pd, void *userdata), void *userdata); #endif diff --git a/src/polyp.c b/src/polyp.c index c15d5d9f6..9af8d4688 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -11,10 +11,13 @@ #include "socket-client.h" #include "pstream-util.h" #include "authkey.h" +#include "util.h" -#define DEFAULT_QUEUE_LENGTH 10240 -#define DEFAULT_MAX_LENGTH 20480 +#define DEFAULT_MAXLENGTH 20480 +#define DEFAULT_TLENGTH 10240 #define DEFAULT_PREBUF 4096 +#define DEFAULT_MINREQ 1024 + #define DEFAULT_TIMEOUT (5*60) #define DEFAULT_SERVER "/tmp/polypaudio/native" @@ -28,25 +31,40 @@ struct pa_context { struct pa_stream *first_stream; uint32_t ctag; uint32_t error; - enum { CONTEXT_UNCONNECTED, CONTEXT_CONNECTING, CONTEXT_AUTHORIZING, CONTEXT_SETTING_NAME, CONTEXT_READY, CONTEXT_DEAD} state; + enum { + CONTEXT_UNCONNECTED, + CONTEXT_CONNECTING, + CONTEXT_AUTHORIZING, + CONTEXT_SETTING_NAME, + CONTEXT_READY, + CONTEXT_DEAD + } state; void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); void *connect_complete_userdata; + void (*drain_complete_callback)(struct pa_context*c, void *userdata); + void *drain_complete_userdata; + void (*die_callback)(struct pa_context*c, void *userdata); void *die_userdata; - + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; }; struct pa_stream { struct pa_context *context; struct pa_stream *next, *previous; + + char *name; + struct pa_buffer_attr buffer_attr; + struct pa_sample_spec sample_spec; uint32_t device_index; uint32_t channel; int channel_valid; enum pa_stream_direction direction; - enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; + + enum { STREAM_LOOKING_UP, STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; uint32_t requested_bytes; void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); @@ -62,7 +80,7 @@ struct pa_stream { void *die_userdata; }; -static int command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -76,8 +94,9 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { }; struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { - assert(mainloop && name); struct pa_context *c; + assert(mainloop && name); + c = malloc(sizeof(struct pa_context)); assert(c); c->name = strdup(name); @@ -95,9 +114,13 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->connect_complete_callback = NULL; c->connect_complete_userdata = NULL; + c->drain_complete_callback = NULL; + c->drain_complete_userdata = NULL; + c->die_callback = NULL; c->die_userdata = NULL; - + + pa_check_for_sigpipe(); return c; } @@ -121,84 +144,105 @@ void pa_context_free(struct pa_context *c) { } static void stream_dead(struct pa_stream *s) { + assert(s); + if (s->state == STREAM_DEAD) return; - - s->state = STREAM_DEAD; - if (s->die_callback) - s->die_callback(s, s->die_userdata); + + if (s->state == STREAM_READY) { + s->state = STREAM_DEAD; + if (s->die_callback) + s->die_callback(s, s->die_userdata); + } else + s->state = STREAM_DEAD; } static void context_dead(struct pa_context *c) { struct pa_stream *s; assert(c); + if (c->state == CONTEXT_DEAD) + return; + + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + c->pdispatch = NULL; + + if (c->pstream) + pa_pstream_free(c->pstream); + c->pstream = NULL; + + if (c->client) + pa_socket_client_free(c->client); + c->client = NULL; + for (s = c->first_stream; s; s = s->next) stream_dead(s); - if (c->state == CONTEXT_DEAD) - return; - - c->state = CONTEXT_DEAD; - if (c->die_callback) - c->die_callback(c, c->die_userdata); + if (c->state == CONTEXT_READY) { + c->state = CONTEXT_DEAD; + if (c->die_callback) + c->die_callback(c, c->die_userdata); + } else + s->state = CONTEXT_DEAD; } static void pstream_die_callback(struct pa_pstream *p, void *userdata) { struct pa_context *c = userdata; assert(p && c); - - assert(c->state != CONTEXT_DEAD); - - c->state = CONTEXT_DEAD; - context_dead(c); } -static int pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { +static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { struct pa_context *c = userdata; assert(p && packet && c); if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { fprintf(stderr, "polyp.c: invalid packet.\n"); context_dead(c); - return -1; } - - - return 0; } -static int pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata) { struct pa_context *c = userdata; struct pa_stream *s; assert(p && chunk && c && chunk->memblock && chunk->memblock->data); if (!(s = pa_dynarray_get(c->streams, channel))) - return 0; + return; if (s->read_callback) s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); - - return 0; } -static int auth_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { + assert(c && t); + + if (command == PA_COMMAND_ERROR) { + if (pa_tagstruct_getu32(t, &c->error) < 0) { + c->error = PA_ERROR_PROTOCOL; + return -1; + } + + return 0; + } + + c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; + return -1; +} + +static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_context *c = userdata; assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); if (command != PA_COMMAND_REPLY) { - if (command == PA_COMMAND_ERROR && pa_tagstruct_getu32(t, &c->error) < 0) - c->error = PA_ERROR_PROTOCOL; - else if (command == PA_COMMAND_TIMEOUT) - c->error = PA_ERROR_TIMEOUT; - - c->state = CONTEXT_DEAD; + handle_error(c, command, t); + context_dead(c); if (c->connect_complete_callback) c->connect_complete_callback(c, 0, c->connect_complete_userdata); - return -1; + return; } if (c->state == CONTEXT_AUTHORIZING) { @@ -210,7 +254,7 @@ static int auth_complete_callback(struct pa_pdispatch *pd, uint32_t command, uin pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_puts(t, c->name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, auth_complete_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); } else { assert(c->state == CONTEXT_SETTING_NAME); @@ -220,7 +264,7 @@ static int auth_complete_callback(struct pa_pdispatch *pd, uint32_t command, uin c->connect_complete_callback(c, 1, c->connect_complete_userdata); } - return 0; + return; } static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { @@ -234,7 +278,7 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i if (!io) { c->error = PA_ERROR_CONNECTIONREFUSED; - c->state = CONTEXT_UNCONNECTED; + context_dead(c); if (c->connect_complete_callback) c->connect_complete_callback(c, 0, c->connect_complete_userdata); @@ -257,7 +301,7 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, auth_complete_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); c->state = CONTEXT_AUTHORIZING; } @@ -305,7 +349,7 @@ void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_cont c->die_userdata = userdata; } -static int command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_stream *s; struct pa_context *c = userdata; uint32_t bytes, channel; @@ -315,63 +359,122 @@ static int command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t t pa_tagstruct_getu32(t, &bytes) < 0 || !pa_tagstruct_eof(t)) { c->error = PA_ERROR_PROTOCOL; - return -1; + context_dead(c); + return; } - if (!(s = pa_dynarray_get(c->streams, channel))) { - c->error = PA_ERROR_PROTOCOL; - return -1; - } + if (!(s = pa_dynarray_get(c->streams, channel))) + return; - /*fprintf(stderr, "Requested %u bytes\n", bytes);*/ + if (s->state != STREAM_READY) + return; s->requested_bytes += bytes; if (s->requested_bytes && s->write_callback) s->write_callback(s, s->requested_bytes, s->write_userdata); - - return 0; } -static int create_playback_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - int ret = 0; +static void create_playback_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_stream *s = userdata; assert(pd && s && s->state == STREAM_CREATING); if (command != PA_COMMAND_REPLY) { - struct pa_context *c = s->context; - assert(c); + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } - if (command == PA_COMMAND_ERROR && pa_tagstruct_getu32(t, &s->context->error) < 0) - s->context->error = PA_ERROR_PROTOCOL; - else if (command == PA_COMMAND_TIMEOUT) - s->context->error = PA_ERROR_TIMEOUT; - - ret = -1; - goto fail; + stream_dead(s); + if (s->create_complete_callback) + s->create_complete_callback(s, 0, s->create_complete_userdata); + + return; } if (pa_tagstruct_getu32(t, &s->channel) < 0 || pa_tagstruct_getu32(t, &s->device_index) < 0 || !pa_tagstruct_eof(t)) { s->context->error = PA_ERROR_PROTOCOL; - ret = -1; - goto fail; + context_dead(s->context); + return; } s->channel_valid = 1; pa_dynarray_put(s->context->streams, s->channel, s); s->state = STREAM_READY; - assert(s->create_complete_callback); - s->create_complete_callback(s, 1, s->create_complete_userdata); - return 0; + if (s->create_complete_callback) + s->create_complete_callback(s, 1, s->create_complete_userdata); +} -fail: - assert(s->create_complete_callback); - s->create_complete_callback(s, 0, s->create_complete_userdata); - pa_stream_free(s); - return ret; +static void create_stream(struct pa_stream *s, uint32_t tdev_index) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s); + + s->state = STREAM_CREATING; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_puts(t, s->name); + pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_putu32(t, tdev_index); + pa_tagstruct_putu32(t, s->buffer_attr.maxlength); + pa_tagstruct_putu32(t, s->buffer_attr.tlength); + pa_tagstruct_putu32(t, s->buffer_attr.prebuf); + pa_tagstruct_putu32(t, s->buffer_attr.minreq); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_playback_callback, s); +} + +static void lookup_device_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + uint32_t tdev; + assert(pd && s && s->state == STREAM_LOOKING_UP); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + if (s->create_complete_callback) + s->create_complete_callback(s, 0, s->create_complete_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &tdev) < 0 || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + create_stream(s, tdev); +} + +static void lookup_device(struct pa_stream *s, const char *tdev) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s); + + s->state = STREAM_LOOKING_UP; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_LOOKUP_SINK : PA_COMMAND_LOOKUP_SOURCE); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_puts(t, tdev); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, lookup_device_callback, s); } struct pa_stream* pa_stream_new( @@ -385,10 +488,8 @@ struct pa_stream* pa_stream_new( void *userdata) { struct pa_stream *s; - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name && ss && c->state == CONTEXT_READY && complete); + assert(c && name && ss && c->state == CONTEXT_READY); s = malloc(sizeof(struct pa_stream)); assert(s); @@ -403,42 +504,43 @@ struct pa_stream* pa_stream_new( s->create_complete_callback = complete; s->create_complete_userdata = NULL; + s->name = strdup(name); s->state = STREAM_CREATING; s->requested_bytes = 0; s->channel = 0; s->channel_valid = 0; s->device_index = (uint32_t) -1; s->direction = dir; + s->sample_spec = *ss; + if (attr) + s->buffer_attr = *attr; + else { + s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; + s->buffer_attr.tlength = DEFAULT_TLENGTH; + s->buffer_attr.prebuf = DEFAULT_PREBUF; + s->buffer_attr.minreq = DEFAULT_MINREQ; + } - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, dir == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_tagstruct_put_sample_spec(t, ss); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_putu32(t, attr ? attr->queue_length : DEFAULT_QUEUE_LENGTH); - pa_tagstruct_putu32(t, attr ? attr->max_length : DEFAULT_MAX_LENGTH); - pa_tagstruct_putu32(t, attr ? attr->prebuf : DEFAULT_PREBUF); - - pa_pstream_send_tagstruct(c->pstream, t); - - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_playback_callback, s); - s->next = c->first_stream; if (s->next) s->next->previous = s; s->previous = NULL; c->first_stream = s; - return 0; + if (dev) + lookup_device(s, dev); + else + create_stream(s, (uint32_t) -1); + + return s; } void pa_stream_free(struct pa_stream *s) { assert(s && s->context); + + free(s->name); - if (s->channel_valid) { + if (s->channel_valid && s->context->state == CONTEXT_READY) { struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); assert(t); @@ -469,7 +571,7 @@ void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stre void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { struct pa_memchunk chunk; - assert(s && s->context && data && length); + assert(s && s->context && data && length && s->state == STREAM_READY); chunk.memblock = pa_memblock_new(length); assert(chunk.memblock && chunk.memblock->data); @@ -489,7 +591,7 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { } size_t pa_stream_writable_size(struct pa_stream *s) { - assert(s); + assert(s && s->state == STREAM_READY); return s->requested_bytes; } @@ -512,3 +614,72 @@ void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream s->die_callback = cb; s->die_userdata = userdata; } + +int pa_context_is_pending(struct pa_context *c) { + assert(c); + + if (c->state != CONTEXT_READY) + return 0; + + return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); +} + +struct pa_context* pa_stream_get_context(struct pa_stream *p) { + assert(p); + return p->context; +} + +static void set_dispatch_callbacks(struct pa_context *c); + +static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void set_dispatch_callbacks(struct pa_context *c) { + assert(c && c->state == CONTEXT_READY); + + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + + if (pa_pdispatch_is_pending(c->pdispatch)) { + pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); + return; + } + + if (pa_pstream_is_pending(c->pstream)) { + pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); + return; + } + + assert(c->drain_complete_callback); + c->drain_complete_callback(c, c->drain_complete_userdata); +} + +int pa_context_drain( + struct pa_context *c, + void (*complete) (struct pa_context*c, void *userdata), + void *userdata) { + + assert(c && c->state == CONTEXT_READY); + + if (complete == NULL) { + c->drain_complete_callback = NULL; + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + return 0; + } + + if (!pa_context_is_pending(c)) + return -1; + + c->drain_complete_callback = complete; + c->drain_complete_userdata = userdata; + + set_dispatch_callbacks(c); + + return 0; +} diff --git a/src/polyp.h b/src/polyp.h index 77a6966f7..25ee3bed3 100644 --- a/src/polyp.h +++ b/src/polyp.h @@ -17,6 +17,11 @@ int pa_context_connect( void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); +int pa_context_drain( + struct pa_context *c, + void (*complete) (struct pa_context*c, void *userdata), + void *userdata); + void pa_context_free(struct pa_context *c); void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); @@ -25,6 +30,8 @@ int pa_context_is_dead(struct pa_context *c); int pa_context_is_ready(struct pa_context *c); int pa_context_errno(struct pa_context *c); +int pa_context_is_pending(struct pa_context *c); + struct pa_stream; struct pa_stream* pa_stream_new( @@ -50,4 +57,6 @@ void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_strea int pa_stream_is_dead(struct pa_stream *p); int pa_stream_is_ready(struct pa_stream*p); +struct pa_context* pa_stream_get_context(struct pa_stream *p); + #endif diff --git a/src/polypdef.h b/src/polypdef.h index aa6e6bf64..80b3cc6c1 100644 --- a/src/polypdef.h +++ b/src/polypdef.h @@ -9,9 +9,10 @@ enum pa_stream_direction { }; struct pa_buffer_attr { - uint32_t queue_length; - uint32_t max_length; + uint32_t maxlength; + uint32_t tlength; uint32_t prebuf; + uint32_t minreq; }; diff --git a/src/protocol-esound.c b/src/protocol-esound.c index cd6448fc6..04006d5d4 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -17,9 +17,7 @@ #define COOKIE_FILE ".esd_auth" -#define MEMBLOCKQ_LENGTH (10*1204) -#define MEMBLOCKQ_PREBUF (2*1024) -#define BUFSIZE (1024) +#define BUFFER_SECONDS (0.5) /* This is heavily based on esound's code */ @@ -196,6 +194,7 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t int format, rate; struct pa_sink *sink; struct pa_sample_spec ss; + size_t l; assert(length == (sizeof(int)*2+ESD_NAME_MAX)); format = maybe_swap_endian_32(c->swap_byte_order, *(int*)data); @@ -217,7 +216,9 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t pa_client_rename(c->client, name); assert(!c->input_memblockq); - c->input_memblockq = pa_memblockq_new(MEMBLOCKQ_LENGTH, pa_sample_size(&ss), MEMBLOCKQ_PREBUF); + + l = (size_t) (pa_bytes_per_second(&ss)*BUFFER_SECONDS); + c->input_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&ss), l/2, l/10); assert(c->input_memblockq); assert(!c->sink_input); @@ -252,7 +253,7 @@ static int esd_proto_get_latency(struct connection *c, const void *data, size_t latency = 0; else { float usec = pa_sink_get_latency(sink); - usec += pa_samples_usec(MEMBLOCKQ_LENGTH-BUFSIZE, &sink->sample_spec); + usec += BUFFER_SECONDS*1000000*.9; /* A better estimation would be a good idea! */ latency = (int) ((usec*44100)/1000000); } @@ -452,16 +453,17 @@ static int do_read(struct connection *c) { } else if (c->state == ESD_STREAMING_DATA) { struct pa_memchunk chunk; ssize_t r; + size_t l; assert(c->input_memblockq); - if (!pa_memblockq_is_writable(c->input_memblockq, BUFSIZE)) + if (!(l = pa_memblockq_missing(c->input_memblockq))) return 0; - chunk.memblock = pa_memblock_new(BUFSIZE); + chunk.memblock = pa_memblock_new(l); assert(chunk.memblock && chunk.memblock->data); - if ((r = pa_iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) { + if ((r = pa_iochannel_read(c->io, chunk.memblock->data, l)) <= 0) { fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); pa_memblock_unref(chunk.memblock); return -1; diff --git a/src/protocol-native-spec.h b/src/protocol-native-spec.h index 07fc735b0..7fb9ac4a0 100644 --- a/src/protocol-native-spec.h +++ b/src/protocol-native-spec.h @@ -13,6 +13,8 @@ enum { PA_COMMAND_REQUEST, PA_COMMAND_AUTH, PA_COMMAND_SET_NAME, + PA_COMMAND_LOOKUP_SINK, + PA_COMMAND_LOOKUP_SOURCE, PA_COMMAND_MAX }; diff --git a/src/protocol-native.c b/src/protocol-native.c index 9463a469a..42ff4b520 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -14,6 +14,7 @@ #include "pdispatch.h" #include "pstream-util.h" #include "authkey.h" +#include "namereg.h" struct connection; struct pa_protocol_native; @@ -28,7 +29,6 @@ struct record_stream { struct playback_stream { struct connection *connection; uint32_t index; - size_t qlength; struct pa_sink_input *sink_input; struct pa_memblockq *memblockq; size_t requested_bytes; @@ -58,11 +58,12 @@ static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); static void request_bytes(struct playback_stream*s); -static int command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static int command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static int command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static int command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static int command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -76,6 +77,8 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = { NULL }, [PA_COMMAND_EXIT] = { command_exit }, [PA_COMMAND_SET_NAME] = { command_set_name }, + [PA_COMMAND_LOOKUP_SINK] = { command_lookup }, + [PA_COMMAND_LOOKUP_SOURCE] = { command_lookup }, }; /* structure management */ @@ -89,14 +92,17 @@ static void record_stream_free(struct record_stream* r) { free(r); } -static struct playback_stream* playback_stream_new(struct connection *c, struct pa_sink *sink, struct pa_sample_spec *ss, const char *name, size_t qlen, size_t maxlength, size_t prebuf) { +static struct playback_stream* playback_stream_new(struct connection *c, struct pa_sink *sink, struct pa_sample_spec *ss, const char *name, + size_t maxlength, + size_t tlength, + size_t prebuf, + size_t minreq) { struct playback_stream *s; - assert(c && sink && ss && name && qlen && maxlength && prebuf); + assert(c && sink && ss && name && maxlength); s = malloc(sizeof(struct playback_stream)); assert (s); s->connection = c; - s->qlength = qlen; s->sink_input = pa_sink_input_new(sink, name, ss); assert(s->sink_input); @@ -106,7 +112,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct s->sink_input->get_latency = sink_input_get_latency_cb; s->sink_input->userdata = s; - s->memblockq = pa_memblockq_new(maxlength, pa_sample_size(ss), prebuf); + s->memblockq = pa_memblockq_new(maxlength, tlength, pa_sample_size(ss), prebuf, minreq); assert(s->memblockq); s->requested_bytes = 0; @@ -149,13 +155,17 @@ static void request_bytes(struct playback_stream *s) { size_t l; assert(s); - if (!(l = pa_memblockq_missing_to(s->memblockq, s->qlength))) + if (!(l = pa_memblockq_missing(s->memblockq))) return; if (l <= s->requested_bytes) return; l -= s->requested_bytes; + + if (l < pa_memblockq_get_minreq(s->memblockq)) + return; + s->requested_bytes += l; t = pa_tagstruct_new(NULL, 0); @@ -166,7 +176,7 @@ static void request_bytes(struct playback_stream *s) { pa_tagstruct_putu32(t, l); pa_pstream_send_tagstruct(s->connection->pstream, t); -/* fprintf(stderr, "Requesting %u bytes\n", l);*/ + /*fprintf(stderr, "Requesting %u bytes\n", l);*/ } /*** sinkinput callbacks ***/ @@ -209,10 +219,15 @@ static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { /*** pdispatch callbacks ***/ -static int command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void protocol_error(struct connection *c) { + fprintf(stderr, __FILE__": protocol error, kicking client\n"); + connection_free(c); +} + +static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct playback_stream *s; - size_t maxlength, prebuf, qlength; + size_t maxlength, tlength, prebuf, minreq; uint32_t sink_index; const char *name; struct pa_sample_spec ss; @@ -223,15 +238,18 @@ static int command_create_playback_stream(struct pa_pdispatch *pd, uint32_t comm if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_get_sample_spec(t, &ss) < 0 || pa_tagstruct_getu32(t, &sink_index) < 0 || - pa_tagstruct_getu32(t, &qlength) < 0 || pa_tagstruct_getu32(t, &maxlength) < 0 || + pa_tagstruct_getu32(t, &tlength) < 0 || pa_tagstruct_getu32(t, &prebuf) < 0 || - !pa_tagstruct_eof(t)) - return -1; + pa_tagstruct_getu32(t, &minreq) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } if (!c->authorized) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); - return 0; + return; } if (sink_index == (uint32_t) -1) @@ -241,12 +259,12 @@ static int command_create_playback_stream(struct pa_pdispatch *pd, uint32_t comm if (!sink) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); - return 0; + return; } - if (!(s = playback_stream_new(c, sink, &ss, name, qlength, maxlength, prebuf))) { + if (!(s = playback_stream_new(c, sink, &ss, name, maxlength, tlength, prebuf, minreq))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); - return 0; + return; } reply = pa_tagstruct_new(NULL, 0); @@ -258,107 +276,148 @@ static int command_create_playback_stream(struct pa_pdispatch *pd, uint32_t comm pa_tagstruct_putu32(reply, s->sink_input->index); pa_pstream_send_tagstruct(c->pstream, reply); request_bytes(s); - return 0; } -static int command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t channel; struct playback_stream *s; assert(c && t); if (pa_tagstruct_getu32(t, &channel) < 0 || - !pa_tagstruct_eof(t)) - return -1; + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } if (!c->authorized) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); - return 0; + return; } if (!(s = pa_idxset_get_by_index(c->playback_streams, channel))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); - return 0; + return; } pa_pstream_send_simple_ack(c->pstream, tag); - return 0; } -static int command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; assert(c && t); - if (!pa_tagstruct_eof(t)) - return -1; + if (!pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } if (!c->authorized) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); - return 0; + return; } assert(c->protocol && c->protocol->core && c->protocol->core->mainloop); c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0); pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */ - return 0; + return; } -static int command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const void*cookie; assert(c && t); if (pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 || - !pa_tagstruct_eof(t)) - return -1; - + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) { fprintf(stderr, "protocol-native.c: Denied access to client with invalid authorization key.\n"); pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); - return 0; + return; } c->authorized = 1; pa_pstream_send_simple_ack(c->pstream, tag); - return 0; + return; } -static int command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const char *name; assert(c && t); if (pa_tagstruct_gets(t, &name) < 0 || - !pa_tagstruct_eof(t)) - return -1; + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } pa_client_rename(c->client, name); pa_pstream_send_simple_ack(c->pstream, tag); - return 0; + return; +} + +static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + const char *name; + uint32_t index = PA_IDXSET_INVALID; + assert(c && t); + + if (pa_tagstruct_gets(t, &name) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (command == PA_COMMAND_LOOKUP_SINK) { + struct pa_sink *sink; + if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK))) + index = sink->index; + } else { + struct pa_source *source; + assert(command == PA_COMMAND_LOOKUP_SOURCE); + if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE))) + index = source->index; + } + + if (index == PA_IDXSET_INVALID) + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + else { + struct pa_tagstruct *reply; + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + pa_tagstruct_putu32(reply, index); + pa_pstream_send_tagstruct(c->pstream, reply); + } } /*** pstream callbacks ***/ -static int packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { +static void packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { struct connection *c = userdata; assert(p && packet && packet->data && c); if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { fprintf(stderr, "protocol-native: invalid packet.\n"); - return -1; + connection_free(c); } - - return 0; } -static int memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata) { +static void memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata) { struct connection *c = userdata; struct playback_stream *stream; assert(p && chunk && userdata); if (!(stream = pa_idxset_get_by_index(c->playback_streams, channel))) { fprintf(stderr, "protocol-native: client sent block for invalid stream.\n"); - return -1; + connection_free(c); + return; } if (chunk->length >= stream->requested_bytes) @@ -371,8 +430,6 @@ static int memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t del pa_sink_notify(stream->sink_input->sink); /*fprintf(stderr, "Recieved %u bytes.\n", chunk->length);*/ - - return 0; } static void die_callback(struct pa_pstream *p, void *userdata) { diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 380b18029..91eab59a3 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -28,7 +28,8 @@ struct pa_protocol_simple { struct pa_sample_spec sample_spec; }; -#define BUFSIZE PIPE_BUF +#define PLAYBACK_BUFFER_SECONDS (.5) +#define RECORD_BUFFER_SECONDS (5) static void connection_free(struct connection *c) { assert(c); @@ -52,17 +53,18 @@ static void connection_free(struct connection *c) { static int do_read(struct connection *c) { struct pa_memchunk chunk; ssize_t r; + size_t l; if (!pa_iochannel_is_readable(c->io)) return 0; - if (!c->sink_input || !pa_memblockq_is_writable(c->input_memblockq, BUFSIZE)) + if (!c->sink_input || !(l = pa_memblockq_missing(c->input_memblockq))) return 0; - - chunk.memblock = pa_memblock_new(BUFSIZE); + + chunk.memblock = pa_memblock_new(l); assert(chunk.memblock); - if ((r = pa_iochannel_read(c->io, chunk.memblock->data, BUFSIZE)) <= 0) { + if ((r = pa_iochannel_read(c->io, chunk.memblock->data, l)) <= 0) { fprintf(stderr, "read(): %s\n", r == 0 ? "EOF" : strerror(errno)); pa_memblock_unref(chunk.memblock); return -1; @@ -213,8 +215,8 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->source_output->kill = source_output_kill_cb; c->source_output->userdata = c; - l = 5*pa_bytes_per_second(&p->sample_spec); /* 5s */ - c->output_memblockq = pa_memblockq_new(l, pa_sample_size(&p->sample_spec), l/2); + l = (size_t) (pa_bytes_per_second(&p->sample_spec)*RECORD_BUFFER_SECONDS); + c->output_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&p->sample_spec), l/2, 0); } if (p->mode & PA_PROTOCOL_SIMPLE_PLAYBACK) { @@ -234,8 +236,8 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->sink_input->get_latency = sink_input_get_latency_cb; c->sink_input->userdata = c; - l = pa_bytes_per_second(&p->sample_spec)/2; /* half a second */ - c->input_memblockq = pa_memblockq_new(l, pa_sample_size(&p->sample_spec), l/2); + l = (size_t) (pa_bytes_per_second(&p->sample_spec)*PLAYBACK_BUFFER_SECONDS); + c->input_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&p->sample_spec), l/2, l/10); } diff --git a/src/pstream.c b/src/pstream.c index 1739780e5..19f83e30e 100644 --- a/src/pstream.c +++ b/src/pstream.c @@ -35,6 +35,8 @@ struct pa_pstream { struct pa_iochannel *io; struct pa_queue *send_queue; + int in_use, shall_free; + int dead; void (*die_callback) (struct pa_pstream *p, void *userdad); void *die_callback_userdata; @@ -46,9 +48,6 @@ struct pa_pstream { size_t index; } write; - void (*send_callback) (struct pa_pstream *p, void *userdata); - void *send_callback_userdata; - struct { struct pa_memblock *memblock; struct pa_packet *packet; @@ -57,34 +56,51 @@ struct pa_pstream { size_t index; } read; - int (*recieve_packet_callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata); + void (*recieve_packet_callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata); void *recieve_packet_callback_userdata; - int (*recieve_memblock_callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata); + void (*recieve_memblock_callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata); void *recieve_memblock_callback_userdata; + + void (*drain_callback)(struct pa_pstream *p, void *userdata); + void *drain_userdata; }; static void do_write(struct pa_pstream *p); static void do_read(struct pa_pstream *p); +static void do_something(struct pa_pstream *p) { + assert(p && !p->shall_free); + p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0); + + p->in_use = 1; + do_write(p); + p->in_use = 0; + + if (p->shall_free) { + pa_pstream_free(p); + return; + } + + p->in_use = 1; + do_read(p); + p->in_use = 0; + if (p->shall_free) { + pa_pstream_free(p); + return; + } +} + static void io_callback(struct pa_iochannel*io, void *userdata) { struct pa_pstream *p = userdata; assert(p && p->io == io); - - p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0); - - do_write(p); - do_read(p); + do_something(p); } static void fixed_callback(struct pa_mainloop_api *m, void *id, void*userdata) { struct pa_pstream *p = userdata; assert(p && p->mainloop_source == id && p->mainloop == m); - - p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0); - - do_write(p); - do_read(p); + do_something(p); } struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io) { @@ -115,15 +131,17 @@ struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel p->read.packet = NULL; p->read.index = 0; - p->send_callback = NULL; - p->send_callback_userdata = NULL; - p->recieve_packet_callback = NULL; p->recieve_packet_callback_userdata = NULL; p->recieve_memblock_callback = NULL; p->recieve_memblock_callback_userdata = NULL; + p->drain_callback = NULL; + p->drain_userdata = NULL; + + p->in_use = p->shall_free = 0; + return p; } @@ -146,6 +164,12 @@ static void item_free(void *item, void *p) { void pa_pstream_free(struct pa_pstream *p) { assert(p); + if (p->in_use) { + /* If this pstream object is used by someone else on the call stack, we have to postpone the freeing */ + p->dead = p->shall_free = 1; + return; + } + pa_iochannel_free(p->io); pa_queue_free(p->send_queue, item_free, NULL); @@ -162,13 +186,6 @@ void pa_pstream_free(struct pa_pstream *p) { free(p); } -void pa_pstream_set_send_callback(struct pa_pstream*p, void (*callback) (struct pa_pstream *p, void *userdata), void *userdata) { - assert(p && callback); - - p->send_callback = callback; - p->send_callback_userdata = userdata; -} - void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { struct item_info *i; assert(p && packet); @@ -199,14 +216,14 @@ void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t del p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1); } -void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, int (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata) { +void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata) { assert(p && callback); p->recieve_packet_callback = callback; p->recieve_packet_callback_userdata = userdata; } -void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, int (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata), void *userdata) { +void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata), void *userdata) { assert(p && callback); p->recieve_memblock_callback = callback; @@ -261,7 +278,7 @@ static void do_write(struct pa_pstream *p) { l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } - if ((r = pa_iochannel_write(p->io, d, l)) < 0) + if ((r = pa_iochannel_write(p->io, d, l)) < 0) goto die; p->write.index += r; @@ -271,8 +288,8 @@ static void do_write(struct pa_pstream *p) { item_free(p->write.current, (void *) 1); p->write.current = NULL; - if (p->send_callback && pa_queue_is_empty(p->send_queue)) - p->send_callback(p, p->send_callback_userdata); + if (p->drain_callback && !pa_pstream_is_pending(p)) + p->drain_callback(p, p->drain_userdata); } return; @@ -341,13 +358,14 @@ static void do_read(struct pa_pstream *p) { chunk.memblock = p->read.memblock; chunk.index = p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE - l; chunk.length = l; - - if (p->recieve_memblock_callback(p, - ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]), - (int32_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA]), - &chunk, - p->recieve_memblock_callback_userdata) < 0) - goto die; + + if (p->recieve_memblock_callback) + p->recieve_memblock_callback( + p, + ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]), + (int32_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA]), + &chunk, + p->recieve_memblock_callback_userdata); } } @@ -359,17 +377,13 @@ static void do_read(struct pa_pstream *p) { pa_memblock_unref(p->read.memblock); p->read.memblock = NULL; } else { - int r = 0; assert(p->read.packet); - + if (p->recieve_packet_callback) - r = p->recieve_packet_callback(p, p->read.packet, p->recieve_packet_callback_userdata); + p->recieve_packet_callback(p, p->read.packet, p->recieve_packet_callback_userdata); pa_packet_unref(p->read.packet); p->read.packet = NULL; - - if (r < 0) - goto die; } p->read.index = 0; @@ -390,3 +404,21 @@ void pa_pstream_set_die_callback(struct pa_pstream *p, void (*callback)(struct p p->die_callback = callback; p->die_callback_userdata = userdata; } + +int pa_pstream_is_pending(struct pa_pstream *p) { + assert(p); + + if (p->dead) + return 0; + + return p->write.current || !pa_queue_is_empty(p->send_queue); +} + +void pa_pstream_set_drain_callback(struct pa_pstream *p, void (*cb)(struct pa_pstream *p, void *userdata), void *userdata) { + assert(p); + assert(!cb || pa_pstream_is_pending(p)); + + p->drain_callback = cb; + p->drain_userdata = userdata; +} + diff --git a/src/pstream.h b/src/pstream.h index 0f5975d26..011b8d12e 100644 --- a/src/pstream.h +++ b/src/pstream.h @@ -9,18 +9,22 @@ #include "mainloop-api.h" #include "memchunk.h" +/* It is safe to destroy the calling pstream object from all callbacks */ + struct pa_pstream; struct pa_pstream* pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io); void pa_pstream_free(struct pa_pstream*p); -void pa_pstream_set_send_callback(struct pa_pstream*p, void (*callback) (struct pa_pstream *p, void *userdata), void *userdata); void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet); void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk); -void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, int (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata); -void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, int (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata), void *userdata); +void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata); +void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata), void *userdata); +void pa_pstream_set_drain_callback(struct pa_pstream *p, void (*cb)(struct pa_pstream *p, void *userdata), void *userdata); void pa_pstream_set_die_callback(struct pa_pstream *p, void (*callback)(struct pa_pstream *p, void *userdata), void *userdata); +int pa_pstream_is_pending(struct pa_pstream *p); + #endif diff --git a/src/sample.h b/src/sample.h index 4131992cd..df12924b6 100644 --- a/src/sample.h +++ b/src/sample.h @@ -32,6 +32,8 @@ uint32_t pa_samples_usec(size_t length, const struct pa_sample_spec *spec); int pa_sample_spec_valid(const struct pa_sample_spec *spec); int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b); + +#define PA_SAMPLE_SNPRINT_MAX_LENGTH 32 void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec); #endif diff --git a/src/simple.c b/src/simple.c index c1d1e96cb..cf31ac52d 100644 --- a/src/simple.c +++ b/src/simple.c @@ -14,6 +14,27 @@ struct pa_simple { int dead; }; +static int iterate(struct pa_simple *p, int block, int *perror) { + assert(p && p->context && p->mainloop && perror); + + if (!block && !pa_context_is_pending(p->context)) + return 0; + + do { + if (pa_context_is_dead(p->context) || (p->stream && pa_stream_is_dead(p->stream))) { + *perror = pa_context_errno(p->context); + return -1; + } + + if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) { + *perror = PA_ERROR_INTERNAL; + return -1; + } + } while (pa_context_is_pending(p->context)); + + return 0; +} + struct pa_simple* pa_simple_new( const char *server, const char *name, @@ -44,26 +65,18 @@ struct pa_simple* pa_simple_new( goto fail; } + /* Wait until the context is ready */ while (!pa_context_is_ready(p->context)) { - if (pa_context_is_dead(p->context)) { - error = pa_context_errno(p->context); - goto fail; - } - - if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) + if (iterate(p, 1, &error) < 0) goto fail; } if (!(p->stream = pa_stream_new(p->context, dir, dev, stream_name, ss, attr, NULL, NULL))) goto fail; + /* Wait until the stream is ready */ while (!pa_stream_is_ready(p->stream)) { - if (pa_stream_is_dead(p->stream)) { - error = pa_context_errno(p->context); - goto fail; - } - - if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) + if (iterate(p, 1, &error) < 0) goto fail; } @@ -96,17 +109,9 @@ int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *pe while (length > 0) { size_t l; - while (!(l = pa_stream_writable_size(p->stream))) { - if (pa_context_is_dead(p->context)) { - *perror = pa_context_errno(p->context); + while (!(l = pa_stream_writable_size(p->stream))) + if (iterate(p, 1, perror) < 0) return -1; - } - - if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) { - *perror = PA_ERROR_INTERNAL; - return -1; - } - } if (l > length) l = length; @@ -116,9 +121,14 @@ int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *pe length -= l; } + /* Make sure that no data is pending for write */ + if (iterate(p, 0, perror) < 0) + return -1; + return 0; } int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *perror) { assert(0); } + diff --git a/src/sink.c b/src/sink.c index 79bf17785..4852edcc3 100644 --- a/src/sink.c +++ b/src/sink.c @@ -274,8 +274,18 @@ char *pa_sink_list_to_string(struct pa_core *c) { default_sink = pa_sink_get_default(c); for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index)) { + char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + pa_sample_snprint(ss, sizeof(ss), &sink->sample_spec); assert(sink->monitor_source); - pa_strbuf_printf(s, " %c index: %u, name: <%s>, volume: <0x%04x>, latency: <%u usec>, monitor_source: <%u>\n", sink == default_sink ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, pa_sink_get_latency(sink), sink->monitor_source->index); + pa_strbuf_printf( + s, + " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", + sink == default_sink ? '*' : ' ', + sink->index, sink->name, + (unsigned) sink->volume, + pa_sink_get_latency(sink), + sink->monitor_source->index, + ss); } return pa_strbuf_tostring_free(s); diff --git a/src/sinkinput.c b/src/sinkinput.c index aa6f33292..20ab25ea2 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -85,13 +85,18 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_ncontents(c->sink_inputs)); for (i = pa_idxset_first(c->sink_inputs, &index); i; i = pa_idxset_next(c->sink_inputs, &index)) { + char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + pa_sample_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); - pa_strbuf_printf(s, " index: %u, name: <%s>, sink: <%u>; volume: <0x%04x>, latency: <%u usec>\n", - i->index, - i->name, - i->sink->index, - (unsigned) i->volume, - pa_sink_input_get_latency(i)); + pa_strbuf_printf( + s, + " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tsample_spec: <%s>\n", + i->index, + i->name, + i->sink->index, + (unsigned) i->volume, + pa_sink_input_get_latency(i), + ss); } return pa_strbuf_tostring_free(s); diff --git a/src/socket-client.h b/src/socket-client.h index 76126aee9..046cc3a54 100644 --- a/src/socket-client.h +++ b/src/socket-client.h @@ -5,6 +5,8 @@ #include "mainloop-api.h" #include "iochannel.h" +/* It is safe to destroy the calling socket_client object from the callback */ + struct pa_socket_client; struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); diff --git a/src/socket-server.h b/src/socket-server.h index d581fa37d..dbce172e0 100644 --- a/src/socket-server.h +++ b/src/socket-server.h @@ -5,6 +5,8 @@ #include "mainloop-api.h" #include "iochannel.h" +/* It is safe to destroy the calling socket_server object from the callback */ + struct pa_socket_server; struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd); diff --git a/src/source.c b/src/source.c index 1c97604b4..44d7da01d 100644 --- a/src/source.c +++ b/src/source.c @@ -111,10 +111,12 @@ char *pa_source_list_to_string(struct pa_core *c) { default_source = pa_source_get_default(c); for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { + char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; char mo[256] = ""; if (source->monitor_of) - snprintf(mo, sizeof(mo), ", monitor_of: <%u>", source->monitor_of->index); - pa_strbuf_printf(s, " %c index: %u, name: <%s>%s\n", source == default_source ? '*' : ' ', source->index, source->name, mo); + snprintf(mo, sizeof(mo), "\n\tmonitor_of: <%u>", source->monitor_of->index); + pa_sample_snprint(ss, sizeof(ss), &source->sample_spec); + pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tsample_spec: <%s>%s\n", source == default_source ? '*' : ' ', source->index, source->name, ss, mo); } return pa_strbuf_tostring_free(s); diff --git a/src/sourceoutput.c b/src/sourceoutput.c index 4f9f821bb..388f1225d 100644 --- a/src/sourceoutput.c +++ b/src/sourceoutput.c @@ -68,11 +68,16 @@ char *pa_source_output_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_ncontents(c->source_outputs)); for (o = pa_idxset_first(c->source_outputs, &index); o; o = pa_idxset_next(c->source_outputs, &index)) { + char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + pa_sample_snprint(ss, sizeof(ss), &o->sample_spec); assert(o->source); - pa_strbuf_printf(s, " %c index: %u, name: <%s>, source: <%u>\n", - o->index, - o->name, - o->source->index); + pa_strbuf_printf( + s, " %c index: %u\n\tname: <%s>\n\tsource: <%u>\n\tsample_spec: <%u>\n", + o->index, + o->name, + o->source->index, + ss, + ss); } return pa_strbuf_tostring_free(s); diff --git a/src/todo b/src/todo index 5b0d893f6..57040cd82 100644 --- a/src/todo +++ b/src/todo @@ -1,7 +1,7 @@ - recording (general, simple, esound, native) - native library/protocol: sync() function - more functions + more functions (esp. latency) - simple library - config parser/cmdline @@ -9,18 +9,20 @@ - move more stuff from module-oss[-dma] to liboss-util - in module-oss: create source first, than sink +- client field for sinkinput/sourceoutput + +- xmms+esound latency testing + - rename files - svn-id and license in every file - documentation - - -- post 0.1 - future cancellation - client-ui - clip cache - autoloading/autounloading -- ldap/rendezvous +- slp/rendezvous - doxygen drivers: diff --git a/src/util.c b/src/util.c index 4ade681a8..3111bd5d4 100644 --- a/src/util.c +++ b/src/util.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -51,7 +52,7 @@ void pa_peer_to_string(char *c, size_t l, int fd) { ntohs(sa.in.sin_port)); return; } else if (sa.sa.sa_family == AF_LOCAL) { - snprintf(c, l, "UNIX client for %s", sa.un.sun_path); + snprintf(c, l, "UNIX socket client"); return; } @@ -208,3 +209,15 @@ int pa_unix_socket_remove_stale(const char *fn) { return 0; } + +void pa_check_for_sigpipe(void) { + struct sigaction sa; + + if (sigaction(SIGPIPE, NULL, &sa) < 0) { + fprintf(stderr, __FILE__": sigaction() failed: %s\n", strerror(errno)); + return; + } + + if (sa.sa_handler == SIG_DFL) + fprintf(stderr, "polypaudio: WARNING: SIGPIPE is not trapped. This might cause malfunction!\n"); +} diff --git a/src/util.h b/src/util.h index 40095e01b..ad9916e71 100644 --- a/src/util.h +++ b/src/util.h @@ -18,4 +18,6 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size); int pa_unix_socket_is_stale(const char *fn); int pa_unix_socket_remove_stale(const char *fn); +void pa_check_for_sigpipe(void); + #endif From 863fb90d90c2e57e60a0f5b81e0847319399b8ed Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 7 Jul 2004 22:02:15 +0000 Subject: [PATCH 0052/1514] add output stream draining git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@53 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/memblockq.c | 2 +- src/pacat-simple.c | 6 ++++ src/pacat.c | 17 ++++++++--- src/pdispatch.c | 43 +++++++++++++++++---------- src/pdispatch.h | 3 ++ src/polyp.c | 61 +++++++++++++++++++++++++++++++++++++- src/polyp.h | 6 ++++ src/protocol-native-spec.h | 1 + src/protocol-native.c | 52 +++++++++++++++++++++++++++++++- src/simple.c | 34 +++++++++++++++++---- src/simple.h | 2 ++ src/todo | 1 - 12 files changed, 200 insertions(+), 28 deletions(-) diff --git a/src/memblockq.c b/src/memblockq.c index e5dab6870..fb4cbc7e1 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -228,7 +228,7 @@ void pa_memblockq_empty(struct pa_memblockq *bq) { int pa_memblockq_is_readable(struct pa_memblockq *bq) { assert(bq); - return bq->current_length >= bq->prebuf; + return bq->current_length && (bq->current_length >= bq->prebuf); } int pa_memblockq_is_writable(struct pa_memblockq *bq, size_t length) { diff --git a/src/pacat-simple.c b/src/pacat-simple.c index 8b48bdd33..896df814c 100644 --- a/src/pacat-simple.c +++ b/src/pacat-simple.c @@ -41,6 +41,12 @@ int main(int argc, char*argv[]) { } } + /* Make sure that every single sample way played */ + if (pa_simple_drain(s, &error) < 0) { + fprintf(stderr, __FILE__": pa_simple_drain() failed: %s\n", pa_strerror(error)); + goto finish; + } + ret = 0; finish: diff --git a/src/pacat.c b/src/pacat.c index 75a94fc07..59ccc4629 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -117,6 +117,18 @@ static void context_drain_complete(struct pa_context*c, void *userdata) { quit(0); } +static void stream_drain_complete(struct pa_stream*s, void *userdata) { + fprintf(stderr, "Playback stream drained.\n"); + + pa_stream_free(stream); + stream = NULL; + + if (pa_context_drain(context, context_drain_complete, NULL) < 0) + quit(0); + else + fprintf(stderr, "Draining connection to server.\n"); +} + static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { size_t l, w = 0; ssize_t r; @@ -135,10 +147,7 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m if ((r = read(fd, buffer, l)) <= 0) { if (r == 0) { fprintf(stderr, "Got EOF.\n"); - if (pa_context_drain(context, context_drain_complete, NULL) < 0) - quit(0); - else - fprintf(stderr, "Draining connection to server.\n"); + pa_stream_drain(stream, stream_drain_complete, NULL); } else { fprintf(stderr, "read() failed: %s\n", strerror(errno)); quit(1); diff --git a/src/pdispatch.c b/src/pdispatch.c index ec4541909..b7257dd4e 100644 --- a/src/pdispatch.c +++ b/src/pdispatch.c @@ -18,6 +18,7 @@ static const char *command_names[PA_COMMAND_MAX] = { [PA_COMMAND_SET_NAME] = "SET_NAME", [PA_COMMAND_LOOKUP_SINK] = "LOOKUP_SINK", [PA_COMMAND_LOOKUP_SOURCE] = "LOOKUP_SOURCE", + [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = "DRAIN_PLAYBACK_STREAM", }; struct reply_info { @@ -27,6 +28,7 @@ struct reply_info { void *userdata; uint32_t tag; void *mainloop_timeout; + int callback_is_running; }; struct pa_pdispatch { @@ -77,7 +79,7 @@ struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *mainloop, const st void pa_pdispatch_free(struct pa_pdispatch *pd) { assert(pd); - + if (pd->in_use) { pd->shall_free = 1; return; @@ -109,25 +111,23 @@ int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *use if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) { struct reply_info *r; - for (r = pd->replies; r; r = r->next) { - if (r->tag != tag) - continue; - - pd->in_use = 1; + for (r = pd->replies; r; r = r->next) + if (r->tag == tag) + break; + + if (r) { + pd->in_use = r->callback_is_running = 1; assert(r->callback); r->callback(r->pdispatch, command, tag, ts, r->userdata); - pd->in_use = 0; + pd->in_use = r->callback_is_running = 0; reply_info_free(r); - if (pd->shall_free) { + if (pd->shall_free) pa_pdispatch_free(pd); - break; + else { + if (pd->drain_callback && !pa_pdispatch_is_pending(pd)) + pd->drain_callback(pd, pd->drain_userdata); } - - if (pd->drain_callback && !pa_pdispatch_is_pending(r->pdispatch)) - pd->drain_callback(r->pdispatch, r->pdispatch->drain_userdata); - - break; } } else if (pd->command_table && command < pd->n_commands) { @@ -169,7 +169,8 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time r->callback = cb; r->userdata = userdata; r->tag = tag; - + r->callback_is_running = 0; + gettimeofday(&tv, NULL); tv.tv_sec += timeout; @@ -196,3 +197,15 @@ void pa_pdispatch_set_drain_callback(struct pa_pdispatch *pd, void (*cb)(struct pd->drain_callback = cb; pd->drain_userdata = userdata; } + +void pa_pdispatch_unregister_reply(struct pa_pdispatch *pd, void *userdata) { + struct reply_info *r, *n; + assert(pd); + + for (r = pd->replies; r; r = n) { + n = r->next; + + if (!r->callback_is_running && r->userdata == userdata) /* when this item's callback is currently running it is destroyed anyway in the very near future */ + reply_info_free(r); + } +} diff --git a/src/pdispatch.h b/src/pdispatch.h index 35e938299..ac372477d 100644 --- a/src/pdispatch.h +++ b/src/pdispatch.h @@ -25,4 +25,7 @@ int pa_pdispatch_is_pending(struct pa_pdispatch *pd); void pa_pdispatch_set_drain_callback(struct pa_pdispatch *pd, void (*cb)(struct pa_pdispatch *pd, void *userdata), void *userdata); +/* Remove all reply slots with the give userdata parameter */ +void pa_pdispatch_unregister_reply(struct pa_pdispatch *pd, void *userdata); + #endif diff --git a/src/polyp.c b/src/polyp.c index 9af8d4688..0f2a9181b 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -75,6 +75,9 @@ struct pa_stream { void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); void *create_complete_userdata; + + void (*drain_complete_callback)(struct pa_stream *s, void *userdata); + void *drain_complete_userdata; void (*die_callback)(struct pa_stream*c, void *userdata); void *die_userdata; @@ -538,8 +541,10 @@ struct pa_stream* pa_stream_new( void pa_stream_free(struct pa_stream *s) { assert(s && s->context); - free(s->name); + pa_pdispatch_unregister_reply(s->context->pdispatch, s); + free(s->name); + if (s->channel_valid && s->context->state == CONTEXT_READY) { struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); assert(t); @@ -683,3 +688,57 @@ int pa_context_drain( return 0; } + +static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + return; + } + + if (s->state != STREAM_READY) + return; + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->drain_complete_callback) { + void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; + s->drain_complete_callback = NULL; + temp(s, s->drain_complete_userdata); + } +} + + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->state == STREAM_READY); + + if (!complete) { + s->drain_complete_callback = NULL; + return; + } + + s->drain_complete_callback = complete; + s->drain_complete_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); +} diff --git a/src/polyp.h b/src/polyp.h index 25ee3bed3..c49a72b2c 100644 --- a/src/polyp.h +++ b/src/polyp.h @@ -46,6 +46,12 @@ struct pa_stream* pa_stream_new( void pa_stream_free(struct pa_stream *p); +void pa_stream_drain( + struct pa_stream *s, + void (*complete) (struct pa_stream*s, void *userdata), + void *userdata); + + void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); diff --git a/src/protocol-native-spec.h b/src/protocol-native-spec.h index 7fb9ac4a0..fea14cc09 100644 --- a/src/protocol-native-spec.h +++ b/src/protocol-native-spec.h @@ -15,6 +15,7 @@ enum { PA_COMMAND_SET_NAME, PA_COMMAND_LOOKUP_SINK, PA_COMMAND_LOOKUP_SOURCE, + PA_COMMAND_DRAIN_PLAYBACK_STREAM, PA_COMMAND_MAX }; diff --git a/src/protocol-native.c b/src/protocol-native.c index 42ff4b520..110d0d6b0 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -32,6 +32,8 @@ struct playback_stream { struct pa_sink_input *sink_input; struct pa_memblockq *memblockq; size_t requested_bytes; + int drain_request; + uint32_t drain_tag; }; struct connection { @@ -61,6 +63,7 @@ static void request_bytes(struct playback_stream*s); static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); @@ -71,6 +74,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REPLY] = { NULL }, [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream }, [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_playback_stream }, + [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = { command_drain_playback_stream }, [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, [PA_COMMAND_AUTH] = { command_auth }, @@ -116,6 +120,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct assert(s->memblockq); s->requested_bytes = 0; + s->drain_request = 0; pa_idxset_put(c->playback_streams, s, &s->index); return s; @@ -124,6 +129,9 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct static void playback_stream_free(struct playback_stream* p) { assert(p && p->connection); + if (p->drain_request) + pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERROR_NOENTITY); + pa_idxset_remove_by_data(p->connection->playback_streams, p, NULL); pa_sink_input_free(p->sink_input); pa_memblockq_free(p->memblockq); @@ -199,6 +207,11 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { pa_memblockq_drop(s->memblockq, length); request_bytes(s); + + if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) { + pa_pstream_send_simple_ack(s->connection->pstream, s->drain_tag); + s->drain_request = 0; + } } static void sink_input_kill_cb(struct pa_sink_input *i) { @@ -258,7 +271,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); if (!sink) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -373,6 +386,11 @@ static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t t return; } + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + if (command == PA_COMMAND_LOOKUP_SINK) { struct pa_sink *sink; if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK))) @@ -397,6 +415,38 @@ static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t t } } +static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + struct playback_stream *s; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(s = pa_idxset_get_by_index(c->playback_streams, index))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + s->drain_request = 0; + + if (!pa_memblockq_is_readable(s->memblockq)) + pa_pstream_send_simple_ack(c->pstream, tag); + else { + s->drain_request = 1; + s->drain_tag = tag; + } +} + /*** pstream callbacks ***/ static void packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { diff --git a/src/simple.c b/src/simple.c index cf31ac52d..50bfea431 100644 --- a/src/simple.c +++ b/src/simple.c @@ -11,23 +11,25 @@ struct pa_simple { struct pa_context *context; struct pa_stream *stream; - int dead; + int dead, drained; }; static int iterate(struct pa_simple *p, int block, int *perror) { - assert(p && p->context && p->mainloop && perror); + assert(p && p->context && p->mainloop); if (!block && !pa_context_is_pending(p->context)) return 0; do { if (pa_context_is_dead(p->context) || (p->stream && pa_stream_is_dead(p->stream))) { - *perror = pa_context_errno(p->context); + if (perror) + *perror = pa_context_errno(p->context); return -1; } if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) { - *perror = PA_ERROR_INTERNAL; + if (perror) + *perror = PA_ERROR_INTERNAL; return -1; } } while (pa_context_is_pending(p->context)); @@ -83,7 +85,8 @@ struct pa_simple* pa_simple_new( return p; fail: - *perror = error; + if (perror) + *perror = error; pa_simple_free(p); return NULL; } @@ -132,3 +135,24 @@ int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *perror) { assert(0); } + +static void drain_complete(struct pa_stream *s, void *userdata) { + struct pa_simple *p = userdata; + assert(s && p); + p->drained = 1; +} + +int pa_simple_drain(struct pa_simple *p, int *perror) { + assert(p); + p->drained = 0; + pa_stream_drain(p->stream, drain_complete, p); + + while (!p->drained) { + if (iterate(p, 1, perror) < 0) { + pa_stream_drain(p->stream, NULL, NULL); + return -1; + } + } + + return 0; +} diff --git a/src/simple.h b/src/simple.h index ed181201e..f5f872eee 100644 --- a/src/simple.h +++ b/src/simple.h @@ -21,6 +21,8 @@ struct pa_simple* pa_simple_new( void pa_simple_free(struct pa_simple *s); int pa_simple_write(struct pa_simple *s, const void*data, size_t length, int *error); +int pa_simple_drain(struct pa_simple *s, int *error); + int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *error); #endif diff --git a/src/todo b/src/todo index 57040cd82..93ba2821b 100644 --- a/src/todo +++ b/src/todo @@ -1,6 +1,5 @@ - recording (general, simple, esound, native) - native library/protocol: - sync() function more functions (esp. latency) - simple library From cffc7768bd5b8d16308c15102b4d03d08d287098 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Jul 2004 23:26:10 +0000 Subject: [PATCH 0053/1514] fix recording for simpel and esound protocols git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@54 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/cli.c | 2 +- src/iochannel.c | 24 +++- src/iochannel.h | 5 +- src/main.c | 3 +- src/mainloop-api.h | 3 +- src/mainloop.c | 3 +- src/memblock.h | 2 - src/module-oss-mmap.c | 4 +- src/pacat.c | 3 +- src/polyp.c | 3 +- src/protocol-esound.c | 323 ++++++++++++++++++++++++++++++++---------- src/protocol-simple.c | 162 +++++++++++++++------ src/sample-util.c | 3 - src/simple.c | 27 +++- src/sink.c | 1 - src/sinkinput.c | 3 +- src/socket-client.c | 4 +- src/socket-server.c | 8 +- src/sourceoutput.c | 3 +- src/todo | 14 +- src/util.c | 49 ++++--- src/util.h | 7 +- 22 files changed, 480 insertions(+), 176 deletions(-) diff --git a/src/cli.c b/src/cli.c index ecde57631..429aebf3b 100644 --- a/src/cli.c +++ b/src/cli.c @@ -97,7 +97,7 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io) { c->userdata = NULL; c->eof_callback = NULL; - pa_iochannel_peer_to_string(io, cname, sizeof(cname)); + pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); c->client = pa_client_new(core, "CLI", cname); assert(c->client); c->client->kill = client_kill; diff --git a/src/iochannel.c b/src/iochannel.c index afa94cff1..775c61394 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -15,6 +15,7 @@ struct pa_iochannel { int readable; int writable; + int hungup; int no_close; @@ -47,6 +48,11 @@ static void callback(struct pa_mainloop_api* m, void *id, int fd, enum pa_mainlo int changed = 0; assert(m && fd >= 0 && events && userdata); + if ((events & PA_MAINLOOP_API_IO_EVENT_HUP) && !io->hungup) { + io->hungup = 1; + changed = 1; + } + if ((events & PA_MAINLOOP_API_IO_EVENT_INPUT) && !io->readable) { io->readable = 1; changed = 1; @@ -80,6 +86,7 @@ struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd io->callback = NULL; io->readable = 0; io->writable = 0; + io->hungup = 0; io->no_close = 0; if (ifd == ofd) { @@ -132,6 +139,11 @@ int pa_iochannel_is_writable(struct pa_iochannel*io) { return io->writable; } +int pa_iochannel_is_hungup(struct pa_iochannel*io) { + assert(io); + return io->hungup; +} + ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) { ssize_t r; assert(io && data && l && io->ofd >= 0); @@ -168,7 +180,17 @@ void pa_iochannel_set_noclose(struct pa_iochannel*io, int b) { io->no_close = b; } -void pa_iochannel_peer_to_string(struct pa_iochannel*io, char*s, size_t l) { +void pa_iochannel_socket_peer_to_string(struct pa_iochannel*io, char*s, size_t l) { assert(io && s && l); pa_peer_to_string(s, l, io->ifd); } + +int pa_iochannel_socket_set_rcvbuf(struct pa_iochannel *io, size_t l) { + assert(io); + return pa_socket_set_rcvbuf(io->ifd, l); +} + +int pa_iochannel_socket_set_sndbuf(struct pa_iochannel *io, size_t l) { + assert(io); + return pa_socket_set_sndbuf(io->ofd, l); +} diff --git a/src/iochannel.h b/src/iochannel.h index 1a5057d66..7e31b6cae 100644 --- a/src/iochannel.h +++ b/src/iochannel.h @@ -16,11 +16,14 @@ ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l); int pa_iochannel_is_readable(struct pa_iochannel*io); int pa_iochannel_is_writable(struct pa_iochannel*io); +int pa_iochannel_is_hungup(struct pa_iochannel*io); void pa_iochannel_set_noclose(struct pa_iochannel*io, int b); void pa_iochannel_set_callback(struct pa_iochannel*io, void (*callback)(struct pa_iochannel*io, void *userdata), void *userdata); -void pa_iochannel_peer_to_string(struct pa_iochannel*io, char*s, size_t l); +void pa_iochannel_socket_peer_to_string(struct pa_iochannel*io, char*s, size_t l); +int pa_iochannel_socket_set_rcvbuf(struct pa_iochannel*io, size_t l); +int pa_iochannel_socket_set_sndbuf(struct pa_iochannel*io, size_t l); #endif diff --git a/src/main.c b/src/main.c index c7a83fec3..e2d86b488 100644 --- a/src/main.c +++ b/src/main.c @@ -42,7 +42,8 @@ int main(int argc, char *argv[]) { c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); - pa_module_load(c, "module-oss", "/dev/dsp"); + pa_module_load(c, "module-oss-mmap", "/dev/dsp"); +/* pa_module_load(c, "module-oss-mmap", "/dev/dsp1");*/ /* pa_module_load(c, "module-pipe-sink", NULL);*/ pa_module_load(c, "module-simple-protocol-tcp", NULL); /* pa_module_load(c, "module-simple-protocol-unix", NULL); diff --git a/src/mainloop-api.h b/src/mainloop-api.h index 96dacc22e..961a1a46b 100644 --- a/src/mainloop-api.h +++ b/src/mainloop-api.h @@ -8,7 +8,8 @@ enum pa_mainloop_api_io_events { PA_MAINLOOP_API_IO_EVENT_NULL = 0, PA_MAINLOOP_API_IO_EVENT_INPUT = 1, PA_MAINLOOP_API_IO_EVENT_OUTPUT = 2, - PA_MAINLOOP_API_IO_EVENT_BOTH = 3 + PA_MAINLOOP_API_IO_EVENT_BOTH = 3, + PA_MAINLOOP_API_IO_EVENT_HUP = 4 }; struct pa_mainloop_api { diff --git a/src/mainloop.c b/src/mainloop.c index 4755cc8fb..a485a9635 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -167,7 +167,8 @@ static void dispatch_pollfds(struct pa_mainloop *m) { assert(s->pollfd->fd == s->fd && s->callback); s->callback(&m->api, s, s->fd, - ((s->pollfd->revents & (POLLIN|POLLHUP|POLLERR)) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | + ((s->pollfd->revents & POLLHUP) ? PA_MAINLOOP_API_IO_EVENT_HUP : 0) | + ((s->pollfd->revents & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | ((s->pollfd->revents & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), s->userdata); s->pollfd->revents = 0; } diff --git a/src/memblock.h b/src/memblock.h index acdae0479..2635f023f 100644 --- a/src/memblock.h +++ b/src/memblock.h @@ -22,8 +22,6 @@ struct pa_memblock* pa_memblock_ref(struct pa_memblock*b); void pa_memblock_unref_fixed(struct pa_memblock*b); -#define pa_memblock_assert_exclusive(b) assert((b)->ref == 1) - extern unsigned pa_memblock_count, pa_memblock_total; #endif diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index 62c2cc2a5..a9cf84f3a 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -68,10 +68,10 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { if (!u->out_memblocks[u->out_current]) { - u->out_memblocks[u->out_current] = chunk.memblock = pa_memblock_new_fixed(u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size); + chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed(u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size); chunk.length = chunk.memblock->length; chunk.index = 0; - + pa_sink_render_into_full(u->sink, &chunk); } diff --git a/src/pacat.c b/src/pacat.c index 59ccc4629..4fdf3f699 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -132,7 +132,7 @@ static void stream_drain_complete(struct pa_stream*s, void *userdata) { static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { size_t l, w = 0; ssize_t r; - assert(a == mainloop_api && id && fd == STDIN_FILENO && events == PA_MAINLOOP_API_IO_EVENT_INPUT && stdin_source == id); + assert(a == mainloop_api && id && fd == STDIN_FILENO && stdin_source == id); if (buffer) { mainloop_api->enable_io(mainloop_api, stdin_source, PA_MAINLOOP_API_IO_EVENT_NULL); @@ -169,6 +169,7 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m static void exit_signal_callback(void *id, int sig, void *userdata) { fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); + } int main(int argc, char *argv[]) { diff --git a/src/polyp.c b/src/polyp.c index 0f2a9181b..6bc7ab339 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -541,7 +541,8 @@ struct pa_stream* pa_stream_new( void pa_stream_free(struct pa_stream *s) { assert(s && s->context); - pa_pdispatch_unregister_reply(s->context->pdispatch, s); + if (s->context->pdispatch) + pa_pdispatch_unregister_reply(s->context->pdispatch, s); free(s->name); diff --git a/src/protocol-esound.c b/src/protocol-esound.c index 04006d5d4..3dd9655b8 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -11,13 +11,18 @@ #include "client.h" #include "sinkinput.h" #include "sink.h" +#include "sourceoutput.h" +#include "source.h" #include "sample.h" #include "authkey.h" #define COOKIE_FILE ".esd_auth" -#define BUFFER_SECONDS (0.5) +#define PLAYBACK_BUFFER_SECONDS (.5) +#define PLAYBACK_BUFFER_FRAGMENTS (10) +#define RECORD_BUFFER_SECONDS (5) +#define RECORD_BUFFER_FRAGMENTS (100) /* This is heavily based on esound's code */ @@ -27,14 +32,20 @@ struct connection { struct pa_iochannel *io; struct pa_client *client; int authorized, swap_byte_order; - void *read_data; - size_t read_data_alloc, read_data_length; void *write_data; size_t write_data_alloc, write_data_index, write_data_length; + void *read_data; + size_t read_data_alloc, read_data_length; esd_proto_t request; esd_client_state_t state; struct pa_sink_input *sink_input; - struct pa_memblockq *input_memblockq; + struct pa_source_output *source_output; + struct pa_memblockq *input_memblockq, *output_memblockq; + void *fixed_source; + struct { + struct pa_memblock *current_memblock; + size_t memblock_index, fragment_size; + } playback; }; struct pa_protocol_esound { @@ -42,14 +53,14 @@ struct pa_protocol_esound { struct pa_core *core; struct pa_socket_server *server; struct pa_idxset *connections; - uint32_t sink_index; + uint32_t sink_index, source_index; unsigned n_player; uint8_t esd_key[ESD_KEY_LEN]; }; typedef struct proto_handler { size_t data_length; - int (*proc)(struct connection *c, const void *data, size_t length); + int (*proc)(struct connection *c, esd_proto_t request, const void *data, size_t length); const char *description; } esd_proto_handler_info_t; @@ -58,15 +69,16 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk static void sink_input_kill_cb(struct pa_sink_input *i); static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); -static int esd_proto_connect(struct connection *c, const void *data, size_t length); -static int esd_proto_stream_play(struct connection *c, const void *data, size_t length); -static int esd_proto_stream_record(struct connection *c, const void *data, size_t length); -static int esd_proto_get_latency(struct connection *c, const void *data, size_t length); -static int esd_proto_server_info(struct connection *c, const void *data, size_t length); -static int esd_proto_all_info(struct connection *c, const void *data, size_t length); -static int esd_proto_stream_pan(struct connection *c, const void *data, size_t length); +static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk); +static void source_output_kill_cb(struct pa_source_output *o); -static int do_write(struct connection *c); +static int esd_proto_connect(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_stream_play(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_get_latency(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_server_info(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_all_info(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const void *data, size_t length); /* the big map of protocol handler info */ static struct proto_handler proto_map[ESD_PROTO_MAX] = { @@ -76,7 +88,7 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_play, "stream play" }, { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream rec" }, - { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream mon" }, + { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream mon" }, { ESD_NAME_MAX + 3 * sizeof(int), NULL, "sample cache" }, { sizeof(int), NULL, "sample free" }, @@ -112,16 +124,27 @@ static void connection_free(struct connection *c) { c->protocol->n_player--; pa_client_free(c->client); - + if (c->sink_input) pa_sink_input_free(c->sink_input); + if (c->source_output) + pa_source_output_free(c->source_output); if (c->input_memblockq) pa_memblockq_free(c->input_memblockq); + if (c->output_memblockq) + pa_memblockq_free(c->output_memblockq); + + if (c->playback.current_memblock) + pa_memblock_unref(c->playback.current_memblock); free(c->read_data); free(c->write_data); pa_iochannel_free(c->io); + + if (c->fixed_source) + c->protocol->core->mainloop->cancel_fixed(c->protocol->core->mainloop, c->fixed_source); + free(c); } @@ -132,11 +155,18 @@ static struct pa_sink* get_output_sink(struct pa_protocol_esound *p) { if (!(s = pa_idxset_get_by_index(p->core->sinks, p->sink_index))) s = pa_sink_get_default(p->core); - if (s->index) - p->sink_index = s->index; - else - p->sink_index = PA_IDXSET_INVALID; + p->sink_index = s ? s->index : PA_IDXSET_INVALID; + return s; +} +static struct pa_source* get_input_source(struct pa_protocol_esound *p) { + struct pa_source *s; + assert(p); + + if (!(s = pa_idxset_get_by_index(p->core->sources, p->sink_index))) + s = pa_source_get_default(p->core); + + p->source_index = s ? s->index : PA_IDXSET_INVALID; return s; } @@ -144,6 +174,9 @@ static void* connection_write(struct connection *c, size_t length) { size_t t, i; assert(c); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); + c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + t = c->write_data_length+length; if (c->write_data_alloc < t) @@ -159,14 +192,14 @@ static void* connection_write(struct connection *c, size_t length) { /*** esound commands ***/ -static int esd_proto_connect(struct connection *c, const void *data, size_t length) { +static int esd_proto_connect(struct connection *c, esd_proto_t request, const void *data, size_t length) { uint32_t ekey; int *ok; assert(length == (ESD_KEY_LEN + sizeof(uint32_t))); if (!c->authorized) { if (memcmp(data, c->protocol->esd_key, ESD_KEY_LEN) != 0) { - fprintf(stderr, "protocol-esound.c: Kicked client with invalid authorization key.\n"); + fprintf(stderr, __FILE__": kicked client with invalid authorization key.\n"); return -1; } @@ -179,7 +212,7 @@ static int esd_proto_connect(struct connection *c, const void *data, size_t leng else if (ekey == ESD_SWAP_ENDIAN_KEY) c->swap_byte_order = 1; else { - fprintf(stderr, "protocol-esound.c: client sent invalid endian key\n"); + fprintf(stderr, __FILE__": client sent invalid endian key\n"); return -1; } @@ -189,13 +222,13 @@ static int esd_proto_connect(struct connection *c, const void *data, size_t leng return 0; } -static int esd_proto_stream_play(struct connection *c, const void *data, size_t length) { +static int esd_proto_stream_play(struct connection *c, esd_proto_t request, const void *data, size_t length) { char name[ESD_NAME_MAX]; int format, rate; struct pa_sink *sink; struct pa_sample_spec ss; size_t l; - assert(length == (sizeof(int)*2+ESD_NAME_MAX)); + assert(c && length == (sizeof(int)*2+ESD_NAME_MAX)); format = maybe_swap_endian_32(c->swap_byte_order, *(int*)data); rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); @@ -217,10 +250,12 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t assert(!c->input_memblockq); - l = (size_t) (pa_bytes_per_second(&ss)*BUFFER_SECONDS); - c->input_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&ss), l/2, l/10); + l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); + c->input_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&ss), l/2, l/PLAYBACK_BUFFER_FRAGMENTS); assert(c->input_memblockq); - + pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*5); + c->playback.fragment_size = l/10; + assert(!c->sink_input); c->sink_input = pa_sink_input_new(sink, name, &ss); assert(c->sink_input); @@ -238,13 +273,67 @@ static int esd_proto_stream_play(struct connection *c, const void *data, size_t return 0; } -static int esd_proto_stream_record(struct connection *c, const void *data, size_t length) { - assert(c && data && length == (sizeof(int)*2+ESD_NAME_MAX)); +static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length) { + char name[ESD_NAME_MAX]; + int format, rate; + struct pa_source *source; + struct pa_sample_spec ss; + size_t l; + assert(c && length == (sizeof(int)*2+ESD_NAME_MAX)); + + format = maybe_swap_endian_32(c->swap_byte_order, *(int*)data); + rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); - assert(0); + ss.rate = rate; + ss.channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1; + ss.format = ((format & ESD_MASK_BITS) == ESD_BITS16) ? PA_SAMPLE_S16NE : PA_SAMPLE_U8; + + if (!pa_sample_spec_valid(&ss)) + return -1; + + if (request == ESD_PROTO_STREAM_MON) { + struct pa_sink* sink; + + if (!(sink = get_output_sink(c->protocol))) + return -1; + + if (!(source = sink->monitor_source)) + return -1; + } else { + assert(request == ESD_PROTO_STREAM_REC); + + if (!(source = get_input_source(c->protocol))) + return -1; + } + + strncpy(name, data + sizeof(int)*2, sizeof(name)); + name[sizeof(name)-1] = 0; + + pa_client_rename(c->client, name); + + assert(!c->output_memblockq); + + l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS); + c->output_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&ss), 0, 0); + assert(c->output_memblockq); + pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2); + + assert(!c->source_output); + c->source_output = pa_source_output_new(source, name, &ss); + assert(c->source_output); + + c->source_output->push = source_output_push_cb; + c->source_output->kill = source_output_kill_cb; + c->source_output->userdata = c; + + c->state = ESD_STREAMING_DATA; + + c->protocol->n_player++; + + return 0; } -static int esd_proto_get_latency(struct connection *c, const void *data, size_t length) { +static int esd_proto_get_latency(struct connection *c, esd_proto_t request, const void *data, size_t length) { struct pa_sink *sink; int latency, *lag; assert(c && !data && length == 0); @@ -253,7 +342,7 @@ static int esd_proto_get_latency(struct connection *c, const void *data, size_t latency = 0; else { float usec = pa_sink_get_latency(sink); - usec += BUFFER_SECONDS*1000000*.9; /* A better estimation would be a good idea! */ + usec += PLAYBACK_BUFFER_SECONDS*1000000*.9; /* A better estimation would be a good idea! */ latency = (int) ((usec*44100)/1000000); } @@ -263,7 +352,7 @@ static int esd_proto_get_latency(struct connection *c, const void *data, size_t return 0; } -static int esd_proto_server_info(struct connection *c, const void *data, size_t length) { +static int esd_proto_server_info(struct connection *c, esd_proto_t request, const void *data, size_t length) { int rate = 44100, format = ESD_STEREO|ESD_BITS16; int *response; struct pa_sink *sink; @@ -283,14 +372,14 @@ static int esd_proto_server_info(struct connection *c, const void *data, size_t return 0; } -static int esd_proto_all_info(struct connection *c, const void *data, size_t length) { +static int esd_proto_all_info(struct connection *c, esd_proto_t request, const void *data, size_t length) { void *response; size_t t, k, s; struct connection *conn; size_t index = PA_IDXSET_INVALID; assert(c && data && length == sizeof(int)); - if (esd_proto_server_info(c, data, length) < 0) + if (esd_proto_server_info(c, request, data, length) < 0) return -1; k = sizeof(int)*5+ESD_NAME_MAX; @@ -346,7 +435,7 @@ static int esd_proto_all_info(struct connection *c, const void *data, size_t len return 0; } -static int esd_proto_stream_pan(struct connection *c, const void *data, size_t length) { +static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const void *data, size_t length) { int *ok; uint32_t index, volume; struct connection *conn; @@ -381,9 +470,6 @@ static void client_kill_cb(struct pa_client *c) { static int do_read(struct connection *c) { assert(c && c->io); - if (!pa_iochannel_is_readable(c->io)) - return 0; - if (c->state == ESD_NEXT_REQUEST) { ssize_t r; assert(c->read_data_length < sizeof(c->request)); @@ -414,7 +500,7 @@ static int do_read(struct connection *c) { if (handler->data_length == 0) { c->read_data_length = 0; - if (handler->proc(c, NULL, 0) < 0) + if (handler->proc(c, c->request, NULL, 0) < 0) return -1; } else { @@ -447,10 +533,10 @@ static int do_read(struct connection *c) { c->state = ESD_NEXT_REQUEST; c->read_data_length = 0; - if (handler->proc(c, c->read_data, l) < 0) + if (handler->proc(c, c->request, c->read_data, l) < 0) return -1; } - } else if (c->state == ESD_STREAMING_DATA) { + } else if (c->state == ESD_STREAMING_DATA && c->sink_input) { struct pa_memchunk chunk; ssize_t r; size_t l; @@ -460,21 +546,37 @@ static int do_read(struct connection *c) { if (!(l = pa_memblockq_missing(c->input_memblockq))) return 0; - chunk.memblock = pa_memblock_new(l); - assert(chunk.memblock && chunk.memblock->data); + if (l > c->playback.fragment_size) + l = c->playback.fragment_size; - if ((r = pa_iochannel_read(c->io, chunk.memblock->data, l)) <= 0) { - fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); - pa_memblock_unref(chunk.memblock); - return -1; + if (c->playback.current_memblock) + if (c->playback.current_memblock->length - c->playback.memblock_index < l) { + pa_memblock_unref(c->playback.current_memblock); + c->playback.current_memblock = NULL; + c->playback.memblock_index = 0; + } + + + if (!c->playback.current_memblock) { + c->playback.current_memblock = pa_memblock_new(c->playback.fragment_size*2); + assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); + c->playback.memblock_index = 0; } - chunk.memblock->length = chunk.length = r; - chunk.index = 0; + if ((r = pa_iochannel_read(c->io, c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { + fprintf(stderr, __FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + return -1; + } + + chunk.memblock = c->playback.current_memblock; + chunk.index = c->playback.memblock_index; + chunk.length = r; + assert(chunk.memblock); + c->playback.memblock_index += r; + assert(c->input_memblockq); pa_memblockq_push_align(c->input_memblockq, &chunk, 0); - pa_memblock_unref(chunk.memblock); assert(c->sink_input); pa_sink_notify(c->sink_input->sink); @@ -485,33 +587,80 @@ static int do_read(struct connection *c) { } static int do_write(struct connection *c) { - ssize_t r; assert(c && c->io); - if (!pa_iochannel_is_writable(c->io)) - return 0; + if (c->write_data_length) { + ssize_t r; + + assert(c->write_data_index < c->write_data_length); + if ((r = pa_iochannel_write(c->io, c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { + fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno)); + return -1; + } + + if ((c->write_data_index +=r) >= c->write_data_length) + c->write_data_length = c->write_data_index = 0; + + } else if (c->state == ESD_STREAMING_DATA && c->source_output) { + struct pa_memchunk chunk; + ssize_t r; - if (!c->write_data_length) - return 0; - - assert(c->write_data_index < c->write_data_length); - if ((r = pa_iochannel_write(c->io, c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { - fprintf(stderr, "protocol-esound.c: write() failed: %s\n", strerror(errno)); - return -1; + assert(c->output_memblockq); + if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) + return 0; + + assert(chunk.memblock && chunk.length); + + if ((r = pa_iochannel_write(c->io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { + pa_memblock_unref(chunk.memblock); + fprintf(stderr, __FILE__": write(): %s\n", strerror(errno)); + return -1; + } + + pa_memblockq_drop(c->output_memblockq, r); + pa_memblock_unref(chunk.memblock); } - - if ((c->write_data_index +=r) >= c->write_data_length) - c->write_data_length = c->write_data_index = 0; return 0; } +static void do_work(struct connection *c) { + assert(c); + + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); + c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); + + if (pa_iochannel_is_hungup(c->io)) + goto fail; + + if (pa_iochannel_is_writable(c->io)) + if (do_write(c) < 0) + goto fail; + + if (pa_iochannel_is_readable(c->io)) + if (do_read(c) < 0) + goto fail; + + return; + +fail: + connection_free(c); +} + static void io_callback(struct pa_iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); - if (do_read(c) < 0 || do_write(c) < 0) - connection_free(c); + do_work(c); +} + +/*** fixed callback ***/ + +void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) { + struct connection *c = userdata; + assert(a && c && c->fixed_source == id); + + do_work(c); } /*** sink_input callbacks ***/ @@ -532,9 +681,10 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { assert(i && c && length); pa_memblockq_drop(c->input_memblockq, length); - - if (do_read(c) < 0) - connection_free(c); + + /* do something */ + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); + c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); } static void sink_input_kill_cb(struct pa_sink_input *i) { @@ -549,6 +699,24 @@ static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { return pa_samples_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); } +/*** source_output callbacks ***/ + +static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk) { + struct connection *c = o->userdata; + assert(o && c && chunk); + + pa_memblockq_push(c->output_memblockq, chunk, 0); + + /* do something */ + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); + c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); +} + +static void source_output_kill_cb(struct pa_source_output *o) { + assert(o && o->userdata); + connection_free((struct connection *) o->userdata); +} + /*** socket server callback ***/ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { @@ -562,7 +730,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->io = io; pa_iochannel_set_callback(c->io, io_callback, c); - pa_iochannel_peer_to_string(io, cname, sizeof(cname)); + pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); assert(c->protocol->core); c->client = pa_client_new(c->protocol->core, "ESOUND", cname); assert(c->client); @@ -585,6 +753,17 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->sink_input = NULL; c->input_memblockq = NULL; + c->source_output = NULL; + c->output_memblockq = NULL; + + c->playback.current_memblock = NULL; + c->playback.memblock_index = 0; + c->playback.fragment_size = 0; + + c->fixed_source = c->protocol->core->mainloop->source_fixed(c->protocol->core->mainloop, fixed_callback, c); + assert(c->fixed_source); + c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); + pa_idxset_put(c->protocol->connections, c, &c->index); } @@ -608,7 +787,7 @@ struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa p->core = core; p->connections = pa_idxset_new(NULL, NULL); assert(p->connections); - p->sink_index = PA_IDXSET_INVALID; + p->sink_index = p->source_index = PA_IDXSET_INVALID; p->n_player = 0; return p; diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 91eab59a3..3e2e7fdaa 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -18,6 +18,12 @@ struct connection { struct pa_source_output *source_output; struct pa_client *client; struct pa_memblockq *input_memblockq, *output_memblockq; + void *fixed_source; + + struct { + struct pa_memblock *current_memblock; + size_t memblock_index, fragment_size; + } playback; }; struct pa_protocol_simple { @@ -29,13 +35,17 @@ struct pa_protocol_simple { }; #define PLAYBACK_BUFFER_SECONDS (.5) +#define PLAYBACK_BUFFER_FRAGMENTS (10) #define RECORD_BUFFER_SECONDS (5) +#define RECORD_BUFFER_FRAGMENTS (100) static void connection_free(struct connection *c) { assert(c); pa_idxset_remove_by_data(c->protocol->connections, c, NULL); + if (c->playback.current_memblock) + pa_memblock_unref(c->playback.current_memblock); if (c->sink_input) pa_sink_input_free(c->sink_input); if (c->source_output) @@ -48,34 +58,49 @@ static void connection_free(struct connection *c) { pa_memblockq_free(c->input_memblockq); if (c->output_memblockq) pa_memblockq_free(c->output_memblockq); + if (c->fixed_source) + c->protocol->core->mainloop->cancel_fixed(c->protocol->core->mainloop, c->fixed_source); free(c); } + static int do_read(struct connection *c) { struct pa_memchunk chunk; ssize_t r; size_t l; - if (!pa_iochannel_is_readable(c->io)) - return 0; - if (!c->sink_input || !(l = pa_memblockq_missing(c->input_memblockq))) return 0; - chunk.memblock = pa_memblock_new(l); - assert(chunk.memblock); + if (l > c->playback.fragment_size) + l = c->playback.fragment_size; - if ((r = pa_iochannel_read(c->io, chunk.memblock->data, l)) <= 0) { - fprintf(stderr, "read(): %s\n", r == 0 ? "EOF" : strerror(errno)); - pa_memblock_unref(chunk.memblock); + if (c->playback.current_memblock) + if (c->playback.current_memblock->length - c->playback.memblock_index < l) { + pa_memblock_unref(c->playback.current_memblock); + c->playback.current_memblock = NULL; + c->playback.memblock_index = 0; + } + + if (!c->playback.current_memblock) { + c->playback.current_memblock = pa_memblock_new(c->playback.fragment_size*2); + assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); + c->playback.memblock_index = 0; + } + + if ((r = pa_iochannel_read(c->io, c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { + fprintf(stderr, __FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } - chunk.memblock->length = chunk.length = r; - chunk.index = 0; + chunk.memblock = c->playback.current_memblock; + chunk.index = c->playback.memblock_index; + chunk.length = r; + assert(chunk.memblock); + c->playback.memblock_index += r; + assert(c->input_memblockq); pa_memblockq_push_align(c->input_memblockq, &chunk, 0); - pa_memblock_unref(chunk.memblock); assert(c->sink_input); pa_sink_notify(c->sink_input->sink); @@ -86,29 +111,51 @@ static int do_write(struct connection *c) { struct pa_memchunk chunk; ssize_t r; - if (!pa_iochannel_is_writable(c->io)) - return 0; - if (!c->source_output) return 0; assert(c->output_memblockq); if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) return 0; - + assert(chunk.memblock && chunk.length); if ((r = pa_iochannel_write(c->io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { - fprintf(stderr, "write(): %s\n", strerror(errno)); pa_memblock_unref(chunk.memblock); + fprintf(stderr, "write(): %s\n", strerror(errno)); return -1; } pa_memblockq_drop(c->output_memblockq, r); pa_memblock_unref(chunk.memblock); + return 0; } + +static void do_work(struct connection *c) { + assert(c); + + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); + c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); + + if (pa_iochannel_is_hungup(c->io)) + goto fail; + + if (pa_iochannel_is_writable(c->io)) + if (do_write(c) < 0) + goto fail; + + if (pa_iochannel_is_readable(c->io)) + if (do_read(c) < 0) + goto fail; + + return; + +fail: + connection_free(c); +} + /*** sink_input callbacks ***/ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { @@ -127,9 +174,10 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { assert(i && c && length); pa_memblockq_drop(c->input_memblockq, length); - - if (do_read(c) < 0) - connection_free(c); + + /* do something */ + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); + c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); } static void sink_input_kill_cb(struct pa_sink_input *i) { @@ -152,8 +200,9 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me pa_memblockq_push(c->output_memblockq, chunk, 0); - if (do_write(c) < 0) - connection_free(c); + /* do something */ + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); + c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); } static void source_output_kill_cb(struct pa_source_output *o) { @@ -174,11 +223,19 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); - if (do_read(c) < 0 || do_write(c) < 0) - connection_free(c); + do_work(c); } -/*** socket_server callbacks */ +/*** fixed callback ***/ + +void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) { + struct connection *c = userdata; + assert(a && c && c->fixed_source == id); + + do_work(c); +} + +/*** socket_server callbacks ***/ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { struct pa_protocol_simple *p = userdata; @@ -191,34 +248,19 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->io = io; c->sink_input = NULL; c->source_output = NULL; + c->fixed_source = NULL; c->input_memblockq = c->output_memblockq = NULL; c->protocol = p; - - pa_iochannel_peer_to_string(io, cname, sizeof(cname)); + c->playback.current_memblock = NULL; + c->playback.memblock_index = 0; + c->playback.fragment_size = 0; + + pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); c->client = pa_client_new(p->core, "SIMPLE", cname); assert(c->client); c->client->kill = client_kill_cb; c->client->userdata = c; - if (p->mode & PA_PROTOCOL_SIMPLE_RECORD) { - struct pa_source *source; - size_t l; - - if (!(source = pa_source_get_default(p->core))) { - fprintf(stderr, "Failed to get default source.\n"); - goto fail; - } - - c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec); - assert(c->source_output); - c->source_output->push = source_output_push_cb; - c->source_output->kill = source_output_kill_cb; - c->source_output->userdata = c; - - l = (size_t) (pa_bytes_per_second(&p->sample_spec)*RECORD_BUFFER_SECONDS); - c->output_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&p->sample_spec), l/2, 0); - } - if (p->mode & PA_PROTOCOL_SIMPLE_PLAYBACK) { struct pa_sink *sink; size_t l; @@ -237,12 +279,40 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->sink_input->userdata = c; l = (size_t) (pa_bytes_per_second(&p->sample_spec)*PLAYBACK_BUFFER_SECONDS); - c->input_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&p->sample_spec), l/2, l/10); + c->input_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&p->sample_spec), l/2, l/PLAYBACK_BUFFER_FRAGMENTS); + assert(c->input_memblockq); + pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5); + c->playback.fragment_size = l/10; } + if (p->mode & PA_PROTOCOL_SIMPLE_RECORD) { + struct pa_source *source; + size_t l; + + if (!(source = pa_source_get_default(p->core))) { + fprintf(stderr, "Failed to get default source.\n"); + goto fail; + } + + c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec); + assert(c->source_output); + c->source_output->push = source_output_push_cb; + c->source_output->kill = source_output_kill_cb; + c->source_output->userdata = c; + + l = (size_t) (pa_bytes_per_second(&p->sample_spec)*RECORD_BUFFER_SECONDS); + c->output_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&p->sample_spec), 0, 0); + pa_iochannel_socket_set_sndbuf(io, l/RECORD_BUFFER_FRAGMENTS*2); + } + pa_iochannel_set_callback(c->io, io_callback, c); pa_idxset_put(p->connections, c, NULL); + + c->fixed_source = p->core->mainloop->source_fixed(p->core->mainloop, fixed_callback, c); + assert(c->fixed_source); + p->core->mainloop->enable_fixed(p->core->mainloop, c->fixed_source, 0); + return; fail: diff --git a/src/sample-util.c b/src/sample-util.c index f37ac78b6..5344ecfad 100644 --- a/src/sample-util.c +++ b/src/sample-util.c @@ -12,14 +12,12 @@ struct pa_sample_spec pa_default_sample_spec = { struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_sample_spec *spec) { assert(b && b->data && spec); - pa_memblock_assert_exclusive(b); pa_silence_memory(b->data, b->length, spec); return b; } void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spec) { assert(c && c->memblock && c->memblock->data && spec && c->length); - pa_memblock_assert_exclusive(c->memblock); pa_silence_memory(c->memblock->data+c->index, c->length, spec); } @@ -96,7 +94,6 @@ void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, size_t n; assert(c && spec && (c->length % pa_sample_size(spec) == 0)); assert(spec->format == PA_SAMPLE_S16NE); - pa_memblock_assert_exclusive(c->memblock); if (volume == PA_VOLUME_NORM) return; diff --git a/src/simple.c b/src/simple.c index 50bfea431..ba0a8f0c6 100644 --- a/src/simple.c +++ b/src/simple.c @@ -14,24 +14,37 @@ struct pa_simple { int dead, drained; }; +static int check_error(struct pa_simple *p, int *perror) { + assert(p); + + if (pa_context_is_dead(p->context) || (p->stream && pa_stream_is_dead(p->stream))) { + if (perror) + *perror = pa_context_errno(p->context); + return -1; + } + + return 0; +} + static int iterate(struct pa_simple *p, int block, int *perror) { assert(p && p->context && p->mainloop); + if (check_error(p, perror) < 0) + return -1; + if (!block && !pa_context_is_pending(p->context)) return 0; - + do { - if (pa_context_is_dead(p->context) || (p->stream && pa_stream_is_dead(p->stream))) { - if (perror) - *perror = pa_context_errno(p->context); - return -1; - } - if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) { if (perror) *perror = PA_ERROR_INTERNAL; return -1; } + + if (check_error(p, perror) < 0) + return -1; + } while (pa_context_is_pending(p->context)); return 0; diff --git a/src/sink.c b/src/sink.c index 4852edcc3..80560724c 100644 --- a/src/sink.c +++ b/src/sink.c @@ -174,7 +174,6 @@ int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) { unsigned n; size_t l; assert(s && target && target->length && target->memblock && target->memblock->data); - pa_memblock_assert_exclusive(target->memblock); n = fill_mix_info(s, info, MAX_MIX_CHANNELS); diff --git a/src/sinkinput.c b/src/sinkinput.c index 20ab25ea2..f3e474bcc 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -89,8 +89,7 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { pa_sample_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); pa_strbuf_printf( - s, - " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tsample_spec: <%s>\n", + s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tsample_spec: <%s>\n", i->index, i->name, i->sink->index, diff --git a/src/socket-client.c b/src/socket-client.c index 6ff119800..9a8c56078 100644 --- a/src/socket-client.c +++ b/src/socket-client.c @@ -120,7 +120,7 @@ struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, ui goto fail; } - pa_make_tcp_socket_low_delay(c->fd); + pa_socket_tcp_low_delay(c->fd); sa.sin_family = AF_INET; sa.sin_port = htons(port); @@ -149,7 +149,7 @@ struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, co goto fail; } - pa_make_socket_low_delay(c->fd); + pa_socket_low_delay(c->fd); sa.sun_family = AF_LOCAL; strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); diff --git a/src/socket-server.c b/src/socket-server.c index 6a7d94157..23d8f7e7c 100644 --- a/src/socket-server.c +++ b/src/socket-server.c @@ -43,9 +43,9 @@ static void callback(struct pa_mainloop_api *mainloop, void *id, int fd, enum pa /* There should be a check for socket type here */ if (s->type == SOCKET_SERVER_IPV4) - pa_make_tcp_socket_low_delay(fd); + pa_socket_tcp_low_delay(fd); else - pa_make_socket_low_delay(fd); + pa_socket_low_delay(fd); io = pa_iochannel_new(s->mainloop, nfd, nfd); assert(io); @@ -88,7 +88,7 @@ struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, co strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); sa.sun_path[sizeof(sa.sun_path) - 1] = 0; - pa_make_socket_low_delay(fd); + pa_socket_low_delay(fd); if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { fprintf(stderr, "bind(): %s\n", strerror(errno)); @@ -133,7 +133,7 @@ struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, ui if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) fprintf(stderr, "setsockopt(): %s\n", strerror(errno)); - pa_make_tcp_socket_low_delay(fd); + pa_socket_tcp_low_delay(fd); sa.sin_family = AF_INET; sa.sin_port = htons(port); diff --git a/src/sourceoutput.c b/src/sourceoutput.c index 388f1225d..442dc7f44 100644 --- a/src/sourceoutput.c +++ b/src/sourceoutput.c @@ -72,11 +72,10 @@ char *pa_source_output_list_to_string(struct pa_core *c) { pa_sample_snprint(ss, sizeof(ss), &o->sample_spec); assert(o->source); pa_strbuf_printf( - s, " %c index: %u\n\tname: <%s>\n\tsource: <%u>\n\tsample_spec: <%u>\n", + s, " index: %u\n\tname: <%s>\n\tsource: <%u>\n\tsample_spec: <%s>\n", o->index, o->name, o->source->index, - ss, ss); } diff --git a/src/todo b/src/todo index 93ba2821b..18da09d8d 100644 --- a/src/todo +++ b/src/todo @@ -1,14 +1,20 @@ -- recording (general, simple, esound, native) +- recording (esound, native) - native library/protocol: more functions (esp. latency) -- simple library - config parser/cmdline +- description field for all entities +- client field for sinkinput/sourceoutput +- module field for all entities + - move more stuff from module-oss[-dma] to liboss-util - in module-oss: create source first, than sink -- client field for sinkinput/sourceoutput +- merge memchunks in memblockq + +- create libstatustext, libsocketutil +- prefix modules/libraries with pa_ - xmms+esound latency testing @@ -16,6 +22,8 @@ - svn-id and license in every file - documentation + + -- post 0.1 - future cancellation - client-ui diff --git a/src/util.c b/src/util.c index 3111bd5d4..6fe4bbee3 100644 --- a/src/util.c +++ b/src/util.c @@ -87,36 +87,27 @@ fail: return -1; } -int pa_make_socket_low_delay(int fd) { - int ret = 0, buf_size, priority; - +int pa_socket_low_delay(int fd) { + int priority; assert(fd >= 0); - buf_size = 1024; - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)) < 0) - ret = -1; - - buf_size = 1024; - if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size)) < 0) - ret = -1; - priority = 7; if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0) - ret = -1; + return -1; - return ret; + return 0; } -int pa_make_tcp_socket_low_delay(int fd) { - int ret, tos, on; - +int pa_socket_tcp_low_delay(int fd) { + int ret, tos; + assert(fd >= 0); - ret = pa_make_socket_low_delay(fd); + ret = pa_socket_low_delay(fd); - on = 1; - if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) - ret = -1; +/* on = 1; */ +/* if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) */ +/* ret = -1; */ tos = IPTOS_LOWDELAY; if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0) @@ -126,6 +117,24 @@ int pa_make_tcp_socket_low_delay(int fd) { } +int pa_socket_set_rcvbuf(int fd, size_t l) { + assert(fd >= 0); + + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) + return -1; + + return 0; +} + +int pa_socket_set_sndbuf(int fd, size_t l) { + assert(fd >= 0); + + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) + return -1; + + return 0; +} + ssize_t pa_loop_read(int fd, void*data, size_t size) { ssize_t ret = 0; assert(fd >= 0 && data && size); diff --git a/src/util.h b/src/util.h index ad9916e71..dba89ee89 100644 --- a/src/util.h +++ b/src/util.h @@ -9,8 +9,11 @@ void pa_peer_to_string(char *c, size_t l, int fd); int pa_make_secure_dir(const char* dir); -int pa_make_socket_low_delay(int fd); -int pa_make_tcp_socket_low_delay(int fd); +int pa_socket_low_delay(int fd); +int pa_socket_tcp_low_delay(int fd); + +int pa_socket_set_sndbuf(int fd, size_t l); +int pa_socket_set_rcvbuf(int fd, size_t l); ssize_t pa_loop_read(int fd, void*data, size_t size); ssize_t pa_loop_write(int fd, const void*data, size_t size); From 70bb8165ec0aefef08d524dc72baa29df658b4c0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 10 Jul 2004 16:50:22 +0000 Subject: [PATCH 0054/1514] implement recording in native API fix a memory leak in memblock.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@55 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/memblock.c | 13 +-- src/module-oss-mmap.c | 55 +++++------- src/pacat.c | 89 ++++++++++++++++--- src/polyp.c | 21 +++-- src/polypdef.h | 1 + src/protocol-esound.c | 5 +- src/protocol-native.c | 198 +++++++++++++++++++++++++++++++++++++++--- src/protocol-simple.c | 12 ++- src/pstream.c | 54 +++++++----- src/pstream.h | 4 +- src/todo | 4 +- 11 files changed, 349 insertions(+), 107 deletions(-) diff --git a/src/memblock.c b/src/memblock.c index af57e3a48..2dfa6a9c1 100644 --- a/src/memblock.c +++ b/src/memblock.c @@ -69,12 +69,13 @@ void pa_memblock_unref_fixed(struct pa_memblock *b) { if (b->ref == 1) { pa_memblock_unref(b); return; + } else { + d = malloc(b->length); + assert(d); + memcpy(d, b->data, b->length); + b->data = d; + b->type = PA_MEMBLOCK_DYNAMIC; + b->ref--; } - - d = malloc(b->length); - assert(d); - memcpy(d, b->data, b->length); - b->data = d; - b->type = PA_MEMBLOCK_DYNAMIC; } diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index a9cf84f3a..280484d00 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -39,26 +39,6 @@ struct userdata { void module_done(struct pa_core *c, struct pa_module*m); -static void out_clear_memblocks(struct userdata*u, unsigned n) { - unsigned i = u->out_current; - assert(u && u->out_memblocks); - - if (n > u->out_fragments) - n = u->out_fragments; - - while (n > 0) { - if (u->out_memblocks[i]) { - pa_memblock_unref_fixed(u->out_memblocks[i]); - u->out_memblocks[i] = NULL; - } - - i++; - while (i >= u->out_fragments) - i -= u->out_fragments; - - n--; - } -} static void out_fill_memblocks(struct userdata *u, unsigned n) { assert(u && u->out_memblocks); @@ -66,14 +46,15 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { while (n > 0) { struct pa_memchunk chunk; - if (!u->out_memblocks[u->out_current]) { - - chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed(u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size); - chunk.length = chunk.memblock->length; - chunk.index = 0; - - pa_sink_render_into_full(u->sink, &chunk); - } + if (u->out_memblocks[u->out_current]) + pa_memblock_unref_fixed(u->out_memblocks[u->out_current]); + + chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed(u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size); + assert(chunk.memblock); + chunk.length = chunk.memblock->length; + chunk.index = 0; + + pa_sink_render_into_full(u->sink, &chunk); u->out_current++; while (u->out_current >= u->out_fragments) @@ -97,9 +78,7 @@ static void do_write(struct userdata *u) { if (!info.blocks) return; - out_clear_memblocks(u, info.blocks); out_fill_memblocks(u, info.blocks); - } static void in_post_memblocks(struct userdata *u, unsigned n) { @@ -109,7 +88,7 @@ static void in_post_memblocks(struct userdata *u, unsigned n) { struct pa_memchunk chunk; if (!u->in_memblocks[u->in_current]) { - u->in_memblocks[u->in_current] = chunk.memblock = pa_memblock_new_fixed(u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size); + chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size); chunk.length = chunk.memblock->length; chunk.index = 0; @@ -262,7 +241,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { } } else { - u->source = pa_source_new(c, "dsp", 0, &u->sample_spec); + u->source = pa_source_new(c, "oss_input", 0, &u->sample_spec); assert(u->source); u->source->userdata = u; @@ -293,7 +272,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { } else { pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); - u->sink = pa_sink_new(c, "dsp", 0, &u->sample_spec); + u->sink = pa_sink_new(c, "oss_output", 0, &u->sample_spec); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; @@ -337,12 +316,18 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { assert(u); if (u->out_memblocks) { - out_clear_memblocks(u, u->out_fragments); + unsigned i; + for (i = 0; i < u->out_fragments; i++) + if (u->out_memblocks[i]) + pa_memblock_unref_fixed(u->out_memblocks[i]); free(u->out_memblocks); } if (u->in_memblocks) { - in_clear_memblocks(u, u->in_fragments); + unsigned i; + for (i = 0; i < u->in_fragments; i++) + if (u->in_memblocks[i]) + pa_memblock_unref_fixed(u->in_memblocks[i]); free(u->in_memblocks); } diff --git a/src/pacat.c b/src/pacat.c index 4fdf3f699..80d4835fb 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -11,6 +11,8 @@ #include "mainloop.h" #include "mainloop-signal.h" +static enum { RECORD, PLAYBACK } mode = PLAYBACK; + static struct pa_context *context = NULL; static struct pa_stream *stream = NULL; static struct pa_mainloop_api *mainloop_api = NULL; @@ -18,7 +20,7 @@ static struct pa_mainloop_api *mainloop_api = NULL; static void *buffer = NULL; static size_t buffer_length = 0, buffer_index = 0; -static void* stdin_source = NULL; +static void* stdio_source = NULL; static void quit(int ret) { assert(mainloop_api); @@ -37,7 +39,7 @@ static void stream_die_callback(struct pa_stream *s, void *userdata) { quit(1); } -static void do_write(size_t length) { +static void do_stream_write(size_t length) { size_t l; assert(length); @@ -62,13 +64,30 @@ static void do_write(size_t length) { static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { assert(s && length); - if (stdin_source) - mainloop_api->enable_io(mainloop_api, stdin_source, PA_MAINLOOP_API_IO_EVENT_INPUT); + if (stdio_source) + mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_INPUT); if (!buffer) return; - do_write(length); + do_stream_write(length); +} + +static void stream_read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata) { + assert(s && data && length); + + if (stdio_source) + mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_OUTPUT); + + if (buffer) { + fprintf(stderr, "Buffer overrrun, dropping incoming data\n"); + return; + } + + buffer = malloc(buffer_length = length); + assert(buffer); + memcpy(buffer, data, length); + buffer_index = 0; } static void stream_complete_callback(struct pa_stream*s, int success, void *userdata) { @@ -99,13 +118,14 @@ static void context_complete_callback(struct pa_context *c, int success, void *u fprintf(stderr, "Connection established.\n"); - if (!(stream = pa_stream_new(c, PA_STREAM_PLAYBACK, NULL, "pacat", &ss, NULL, stream_complete_callback, NULL))) { + if (!(stream = pa_stream_new(c, mode == PLAYBACK ? PA_STREAM_PLAYBACK : PA_STREAM_RECORD, NULL, "pacat", &ss, NULL, stream_complete_callback, NULL))) { fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } pa_stream_set_die_callback(stream, stream_die_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); + pa_stream_set_read_callback(stream, stream_read_callback, NULL); return; @@ -132,10 +152,10 @@ static void stream_drain_complete(struct pa_stream*s, void *userdata) { static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { size_t l, w = 0; ssize_t r; - assert(a == mainloop_api && id && fd == STDIN_FILENO && stdin_source == id); + assert(a == mainloop_api && id && stdio_source == id); if (buffer) { - mainloop_api->enable_io(mainloop_api, stdin_source, PA_MAINLOOP_API_IO_EVENT_NULL); + mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_NULL); return; } @@ -153,8 +173,8 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m quit(1); } - mainloop_api->cancel_io(mainloop_api, stdin_source); - stdin_source = NULL; + mainloop_api->cancel_io(mainloop_api, stdio_source); + stdio_source = NULL; return; } @@ -162,9 +182,38 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m buffer_index = 0; if (w) - do_write(w); + do_stream_write(w); } +static void stdout_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { + ssize_t r; + assert(a == mainloop_api && id && stdio_source == id); + + if (!buffer) { + mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_NULL); + return; + } + + assert(buffer_length); + + if ((r = write(fd, buffer+buffer_index, buffer_length)) <= 0) { + fprintf(stderr, "write() failed: %s\n", strerror(errno)); + quit(1); + + mainloop_api->cancel_io(mainloop_api, stdio_source); + stdio_source = NULL; + return; + } + + buffer_length -= r; + buffer_index += r; + + if (!buffer_length) { + free(buffer); + buffer = NULL; + buffer_length = buffer_index = 0; + } +} static void exit_signal_callback(void *id, int sig, void *userdata) { fprintf(stderr, "Got SIGINT, exiting.\n"); @@ -175,7 +224,18 @@ static void exit_signal_callback(void *id, int sig, void *userdata) { int main(int argc, char *argv[]) { struct pa_mainloop* m; int ret = 1, r; + char *bn; + if (!(bn = strrchr(argv[0], '/'))) + bn = argv[0]; + + if (strstr(bn, "rec") || strstr(bn, "mon")) + mode = RECORD; + else if (strstr(bn, "cat") || strstr(bn, "play")) + mode = PLAYBACK; + + fprintf(stderr, "Opening a %s stream.\n", mode == RECORD ? "recording" : "playback"); + if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); goto quit; @@ -188,7 +248,10 @@ int main(int argc, char *argv[]) { pa_signal_register(SIGINT, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - if (!(stdin_source = mainloop_api->source_io(mainloop_api, STDIN_FILENO, PA_MAINLOOP_API_IO_EVENT_INPUT, stdin_callback, NULL))) { + if (!(stdio_source = mainloop_api->source_io(mainloop_api, + mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, + mode == PLAYBACK ? PA_MAINLOOP_API_IO_EVENT_INPUT : PA_MAINLOOP_API_IO_EVENT_OUTPUT, + mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { fprintf(stderr, "source_io() failed.\n"); goto quit; } @@ -215,6 +278,8 @@ quit: pa_stream_free(stream); if (context) pa_context_free(context); + + pa_signal_done(); if (m) pa_mainloop_free(m); if (buffer) diff --git a/src/polyp.c b/src/polyp.c index 6bc7ab339..2c2810fb4 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -13,10 +13,11 @@ #include "authkey.h" #include "util.h" -#define DEFAULT_MAXLENGTH 20480 +#define DEFAULT_MAXLENGTH 204800 #define DEFAULT_TLENGTH 10240 #define DEFAULT_PREBUF 4096 #define DEFAULT_MINREQ 1024 +#define DEFAULT_FRAGSIZE 1024 #define DEFAULT_TIMEOUT (5*60) #define DEFAULT_SERVER "/tmp/polypaudio/native" @@ -187,7 +188,7 @@ static void context_dead(struct pa_context *c) { if (c->die_callback) c->die_callback(c, c->die_userdata); } else - s->state = CONTEXT_DEAD; + c->state = CONTEXT_DEAD; } static void pstream_die_callback(struct pa_pstream *p, void *userdata) { @@ -206,7 +207,7 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack } } -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { struct pa_context *c = userdata; struct pa_stream *s; assert(p && chunk && c && chunk->memblock && chunk->memblock->data); @@ -378,7 +379,7 @@ static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t s->write_callback(s, s->requested_bytes, s->write_userdata); } -static void create_playback_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_stream *s = userdata; assert(pd && s && s->state == STREAM_CREATING); @@ -427,12 +428,15 @@ static void create_stream(struct pa_stream *s, uint32_t tdev_index) { pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_putu32(t, tdev_index); pa_tagstruct_putu32(t, s->buffer_attr.maxlength); - pa_tagstruct_putu32(t, s->buffer_attr.tlength); - pa_tagstruct_putu32(t, s->buffer_attr.prebuf); - pa_tagstruct_putu32(t, s->buffer_attr.minreq); + if (s->direction == PA_STREAM_PLAYBACK) { + pa_tagstruct_putu32(t, s->buffer_attr.tlength); + pa_tagstruct_putu32(t, s->buffer_attr.prebuf); + pa_tagstruct_putu32(t, s->buffer_attr.minreq); + } else + pa_tagstruct_putu32(t, s->buffer_attr.fragsize); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_playback_callback, s); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); } static void lookup_device_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { @@ -522,6 +526,7 @@ struct pa_stream* pa_stream_new( s->buffer_attr.tlength = DEFAULT_TLENGTH; s->buffer_attr.prebuf = DEFAULT_PREBUF; s->buffer_attr.minreq = DEFAULT_MINREQ; + s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; } s->next = c->first_stream; diff --git a/src/polypdef.h b/src/polypdef.h index 80b3cc6c1..6cfafc972 100644 --- a/src/polypdef.h +++ b/src/polypdef.h @@ -13,6 +13,7 @@ struct pa_buffer_attr { uint32_t tlength; uint32_t prebuf; uint32_t minreq; + uint32_t fragsize; }; diff --git a/src/protocol-esound.c b/src/protocol-esound.c index 3dd9655b8..e97ab34d0 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -580,9 +580,8 @@ static int do_read(struct connection *c) { assert(c->sink_input); pa_sink_notify(c->sink_input->sink); - } else - assert(0); - + } + return 0; } diff --git a/src/protocol-native.c b/src/protocol-native.c index 110d0d6b0..fe086066a 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -24,6 +24,7 @@ struct record_stream { uint32_t index; struct pa_source_output *source_output; struct pa_memblockq *memblockq; + size_t fragment_size; }; struct playback_stream { @@ -43,6 +44,7 @@ struct connection { struct pa_pstream *pstream; struct pa_pdispatch *pdispatch; struct pa_idxset *record_streams, *playback_streams; + uint32_t rrobin_index; }; struct pa_protocol_native { @@ -60,10 +62,15 @@ static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); static void request_bytes(struct playback_stream*s); +static void source_output_kill_cb(struct pa_source_output *o); +static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk); + static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_delete_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); @@ -75,8 +82,8 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream }, [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_playback_stream }, [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = { command_drain_playback_stream }, - [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_CREATE_RECORD_STREAM] = { command_create_record_stream }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { command_delete_record_stream }, [PA_COMMAND_AUTH] = { command_auth }, [PA_COMMAND_REQUEST] = { NULL }, [PA_COMMAND_EXIT] = { command_exit }, @@ -87,6 +94,34 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { /* structure management */ +static struct record_stream* record_stream_new(struct connection *c, struct pa_source *source, struct pa_sample_spec *ss, const char *name, size_t maxlength, size_t fragment_size) { + struct record_stream *s; + struct pa_source_output *source_output; + size_t base; + assert(c && source && ss && name && maxlength); + + if (!(source_output = pa_source_output_new(source, name, ss))) + return NULL; + + s = malloc(sizeof(struct record_stream)); + assert(s); + s->connection = c; + s->source_output = source_output; + s->source_output->push = source_output_push_cb; + s->source_output->kill = source_output_kill_cb; + s->source_output->userdata = s; + + s->memblockq = pa_memblockq_new(maxlength, 0, base = pa_sample_size(ss), 0, 0); + assert(s->memblockq); + + s->fragment_size = (fragment_size/base)*base; + if (!s->fragment_size) + s->fragment_size = base; + + pa_idxset_put(c->record_streams, s, &s->index); + return s; +} + static void record_stream_free(struct record_stream* r) { assert(r && r->connection); @@ -102,14 +137,17 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct size_t prebuf, size_t minreq) { struct playback_stream *s; + struct pa_sink_input *sink_input; assert(c && sink && ss && name && maxlength); + if (!(sink_input = pa_sink_input_new(sink, name, ss))) + return NULL; + s = malloc(sizeof(struct playback_stream)); assert (s); s->connection = c; + s->sink_input = sink_input; - s->sink_input = pa_sink_input_new(sink, name, ss); - assert(s->sink_input); s->sink_input->peek = sink_input_peek_cb; s->sink_input->drop = sink_input_drop_cb; s->sink_input->kill = sink_input_kill_cb; @@ -187,6 +225,35 @@ static void request_bytes(struct playback_stream *s) { /*fprintf(stderr, "Requesting %u bytes\n", l);*/ } +static void send_memblock(struct connection *c) { + uint32_t start; + struct record_stream *r; + + start = PA_IDXSET_INVALID; + for (;;) { + struct pa_memchunk chunk; + + if (!(r = pa_idxset_rrobin(c->record_streams, &c->rrobin_index))) + return; + + if (start == PA_IDXSET_INVALID) + start = c->rrobin_index; + else if (start == c->rrobin_index) + return; + + if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) { + if (chunk.length > r->fragment_size) + chunk.length = r->fragment_size; + + pa_pstream_send_memblock(c->pstream, r->index, 0, &chunk); + pa_memblockq_drop(r->memblockq, chunk.length); + pa_memblock_unref(chunk.memblock); + + return; + } + } +} + /*** sinkinput callbacks ***/ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { @@ -215,11 +282,8 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { } static void sink_input_kill_cb(struct pa_sink_input *i) { - struct playback_stream *s; assert(i && i->userdata); - s = i->userdata; - - playback_stream_free(s); + playback_stream_free((struct playback_stream *) i->userdata); } static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { @@ -230,6 +294,23 @@ static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { return pa_samples_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); } +/*** source_output callbacks ***/ + +static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk) { + struct record_stream *s; + assert(o && o->userdata && chunk); + s = o->userdata; + + pa_memblockq_push(s->memblockq, chunk, 0); + if (!pa_pstream_is_pending(s->connection->pstream)) + send_memblock(s->connection); +} + +static void source_output_kill_cb(struct pa_source_output *o) { + assert(o && o->userdata); + record_stream_free((struct record_stream *) o->userdata); +} + /*** pdispatch callbacks ***/ static void protocol_error(struct connection *c) { @@ -313,6 +394,84 @@ static void command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t com return; } + playback_stream_free(s); + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + struct record_stream *s; + size_t maxlength, fragment_size; + uint32_t source_index; + const char *name; + struct pa_sample_spec ss; + struct pa_tagstruct *reply; + struct pa_source *source; + assert(c && t && c->protocol && c->protocol->core); + + if (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_get_sample_spec(t, &ss) < 0 || + pa_tagstruct_getu32(t, &source_index) < 0 || + pa_tagstruct_getu32(t, &maxlength) < 0 || + pa_tagstruct_getu32(t, &fragment_size) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (source_index == (uint32_t) -1) + source = pa_source_get_default(c->protocol->core); + else + source = pa_idxset_get_by_index(c->protocol->core->sources, source_index); + + if (!source) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + if (!(s = record_stream_new(c, source, &ss, name, maxlength, fragment_size))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + pa_tagstruct_putu32(reply, s->index); + assert(s->source_output); + pa_tagstruct_putu32(reply, s->source_output->index); + pa_pstream_send_tagstruct(c->pstream, reply); +} + +static void command_delete_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t channel; + struct record_stream *s; + assert(c && t); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + return; + } + + record_stream_free(s); pa_pstream_send_simple_ack(c->pstream, tag); } @@ -449,7 +608,7 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm /*** pstream callbacks ***/ -static void packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { +static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { struct connection *c = userdata; assert(p && packet && packet->data && c); @@ -459,7 +618,7 @@ static void packet_callback(struct pa_pstream *p, struct pa_packet *packet, void } } -static void memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { struct connection *c = userdata; struct playback_stream *stream; assert(p && chunk && userdata); @@ -482,7 +641,7 @@ static void memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t de /*fprintf(stderr, "Recieved %u bytes.\n", chunk->length);*/ } -static void die_callback(struct pa_pstream *p, void *userdata) { +static void pstream_die_callback(struct pa_pstream *p, void *userdata) { struct connection *c = userdata; assert(p && c); connection_free(c); @@ -490,6 +649,14 @@ static void die_callback(struct pa_pstream *p, void *userdata) { fprintf(stderr, "protocol-native: connection died.\n"); } + +static void pstream_drain_callback(struct pa_pstream *p, void *userdata) { + struct connection *c = userdata; + assert(p && c); + + send_memblock(c); +} + /*** client callbacks ***/ static void client_kill_cb(struct pa_client *c) { @@ -516,9 +683,10 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->pstream = pa_pstream_new(p->core->mainloop, io); assert(c->pstream); - pa_pstream_set_recieve_packet_callback(c->pstream, packet_callback, c); - pa_pstream_set_recieve_memblock_callback(c->pstream, memblock_callback, c); - pa_pstream_set_die_callback(c->pstream, die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX); assert(c->pdispatch); @@ -527,6 +695,8 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->playback_streams = pa_idxset_new(NULL, NULL); assert(c->record_streams && c->playback_streams); + c->rrobin_index = PA_IDXSET_INVALID; + pa_idxset_put(p->connections, c, NULL); } diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 3e2e7fdaa..e7ca0a76c 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -271,7 +271,11 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo } c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec); - assert(c->sink_input); + if (!c->sink_input) { + fprintf(stderr, "Failed to create sink input.\n"); + goto fail; + } + c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; c->sink_input->kill = sink_input_kill_cb; @@ -296,7 +300,11 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo } c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec); - assert(c->source_output); + if (!c->source_output) { + fprintf(stderr, "Failed to create source output.\n"); + goto fail; + } + c->source_output->push = source_output_push_cb; c->source_output->kill = source_output_kill_cb; c->source_output->userdata = c; diff --git a/src/pstream.c b/src/pstream.c index 19f83e30e..18d33b0df 100644 --- a/src/pstream.c +++ b/src/pstream.c @@ -38,7 +38,7 @@ struct pa_pstream { int in_use, shall_free; int dead; - void (*die_callback) (struct pa_pstream *p, void *userdad); + void (*die_callback) (struct pa_pstream *p, void *userdata); void *die_callback_userdata; struct { @@ -59,7 +59,7 @@ struct pa_pstream { void (*recieve_packet_callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata); void *recieve_packet_callback_userdata; - void (*recieve_memblock_callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata); + void (*recieve_memblock_callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata); void *recieve_memblock_callback_userdata; void (*drain_callback)(struct pa_pstream *p, void *userdata); @@ -73,21 +73,36 @@ static void do_something(struct pa_pstream *p) { assert(p && !p->shall_free); p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0); - p->in_use = 1; - do_write(p); - p->in_use = 0; + if (p->dead) + return; + + if (pa_iochannel_is_hungup(p->io)) { + p->dead = 1; + if (p->die_callback) + p->die_callback(p, p->die_callback_userdata); - if (p->shall_free) { - pa_pstream_free(p); return; } - - p->in_use = 1; - do_read(p); - p->in_use = 0; - if (p->shall_free) { - pa_pstream_free(p); - return; + + if (pa_iochannel_is_writable(p->io)) { + p->in_use = 1; + do_write(p); + p->in_use = 0; + + if (p->shall_free) { + pa_pstream_free(p); + return; + } + } + + if (pa_iochannel_is_readable(p->io)) { + p->in_use = 1; + do_read(p); + p->in_use = 0; + if (p->shall_free) { + pa_pstream_free(p); + return; + } } } @@ -199,7 +214,7 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1); } -void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk) { +void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk) { struct item_info *i; assert(p && channel != (uint32_t) -1 && chunk); @@ -223,7 +238,7 @@ void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callbac p->recieve_packet_callback_userdata = userdata; } -void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata), void *userdata) { +void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata), void *userdata) { assert(p && callback); p->recieve_memblock_callback = callback; @@ -259,9 +274,6 @@ static void do_write(struct pa_pstream *p) { ssize_t r; assert(p); - if (p->dead || !pa_iochannel_is_writable(p->io)) - return; - if (!p->write.current) prepare_next_write_item(p); @@ -306,9 +318,6 @@ static void do_read(struct pa_pstream *p) { ssize_t r; assert(p); - if (p->dead || !pa_iochannel_is_readable(p->io)) - return; - if (p->read.index < PA_PSTREAM_DESCRIPTOR_SIZE) { d = (void*) p->read.descriptor + p->read.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->read.index; @@ -416,7 +425,6 @@ int pa_pstream_is_pending(struct pa_pstream *p) { void pa_pstream_set_drain_callback(struct pa_pstream *p, void (*cb)(struct pa_pstream *p, void *userdata), void *userdata) { assert(p); - assert(!cb || pa_pstream_is_pending(p)); p->drain_callback = cb; p->drain_userdata = userdata; diff --git a/src/pstream.h b/src/pstream.h index 011b8d12e..8525cb22b 100644 --- a/src/pstream.h +++ b/src/pstream.h @@ -17,10 +17,10 @@ struct pa_pstream* pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel void pa_pstream_free(struct pa_pstream*p); void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet); -void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk); +void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk); void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata); -void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, struct pa_memchunk *chunk, void *userdata), void *userdata); +void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata), void *userdata); void pa_pstream_set_drain_callback(struct pa_pstream *p, void (*cb)(struct pa_pstream *p, void *userdata), void *userdata); void pa_pstream_set_die_callback(struct pa_pstream *p, void (*callback)(struct pa_pstream *p, void *userdata), void *userdata); diff --git a/src/todo b/src/todo index 18da09d8d..ee971ca0a 100644 --- a/src/todo +++ b/src/todo @@ -1,4 +1,4 @@ -- recording (esound, native) +- implement parec-simple - native library/protocol: more functions (esp. latency) @@ -9,7 +9,6 @@ - module field for all entities - move more stuff from module-oss[-dma] to liboss-util -- in module-oss: create source first, than sink - merge memchunks in memblockq @@ -41,3 +40,4 @@ drivers: modules: - alsa? +- http From 5ea96e312be3aa495e77786283e1edea7592047f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 10 Jul 2004 19:04:21 +0000 Subject: [PATCH 0055/1514] implement parec-simple and matching simple recording API add support for killing source outputs in native protocol fix channel management in client library git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@56 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 +++- src/polyp-error.c | 5 ++- src/polyp.c | 47 ++++++++++++++++++++----- src/protocol-native-spec.h | 4 +++ src/protocol-native.c | 27 +++++++++++++++ src/simple.c | 70 +++++++++++++++++++++++++++++++++++--- src/todo | 3 +- 7 files changed, 145 insertions(+), 17 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index d7002caf1..b02bfba6c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ AM_CFLAGS=-ansi -D_GNU_SOURCE -bin_PROGRAMS = polypaudio pacat pacat-simple +bin_PROGRAMS = polypaudio pacat pacat-simple parec-simple pkglib_LTLIBRARIES=libiochannel.la \ libsocket-server.la \ @@ -248,3 +248,7 @@ pacat_CFLAGS = $(AM_CFLAGS) pacat_simple_SOURCES = pacat-simple.c $(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) #pacat_simple_LDADD = libpolyp-simple.la libpolyp-error.la pacat_simple_CFLAGS = $(AM_CFLAGS) + +parec_simple_SOURCES = parec-simple.c $(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) +#parec_simple_LDADD = libpolyp-simple.la libpolyp-error.la +parec_simple_CFLAGS = $(AM_CFLAGS) diff --git a/src/polyp-error.c b/src/polyp-error.c index 861711a2f..86166b0c8 100644 --- a/src/polyp-error.c +++ b/src/polyp-error.c @@ -1,3 +1,4 @@ +#include #include #include "polyp-error.h" @@ -14,7 +15,9 @@ static const char* const errortab[PA_ERROR_MAX] = { [PA_ERROR_PROTOCOL] = "Protocol corrupt", [PA_ERROR_TIMEOUT] = "Timeout", [PA_ERROR_AUTHKEY] = "Not authorization key", - [PA_ERROR_INTERNAL] = "Internal error" + [PA_ERROR_INTERNAL] = "Internal error", + [PA_ERROR_CONNECTIONTERMINATED] = "Connection terminated", + [PA_ERROR_KILLED] = "Entity killed", }; const char*pa_strerror(uint32_t error) { diff --git a/src/polyp.c b/src/polyp.c index 2c2810fb4..fde0c68b8 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -28,7 +28,7 @@ struct pa_context { struct pa_socket_client *client; struct pa_pstream *pstream; struct pa_pdispatch *pdispatch; - struct pa_dynarray *streams; + struct pa_dynarray *record_streams, *playback_streams; struct pa_stream *first_stream; uint32_t ctag; uint32_t error; @@ -85,6 +85,7 @@ struct pa_stream { }; static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -95,6 +96,8 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, [PA_COMMAND_EXIT] = { NULL }, [PA_COMMAND_REQUEST] = { command_request }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, }; struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { @@ -108,8 +111,10 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->client = NULL; c->pstream = NULL; c->pdispatch = NULL; - c->streams = pa_dynarray_new(); - assert(c->streams); + c->playback_streams = pa_dynarray_new(); + assert(c->playback_streams); + c->record_streams = pa_dynarray_new(); + assert(c->record_streams); c->first_stream = NULL; c->error = PA_ERROR_OK; c->state = CONTEXT_UNCONNECTED; @@ -140,8 +145,10 @@ void pa_context_free(struct pa_context *c) { pa_pdispatch_free(c->pdispatch); if (c->pstream) pa_pstream_free(c->pstream); - if (c->streams) - pa_dynarray_free(c->streams, NULL, NULL); + if (c->record_streams) + pa_dynarray_free(c->record_streams, NULL, NULL); + if (c->playback_streams) + pa_dynarray_free(c->playback_streams, NULL, NULL); free(c->name); free(c); @@ -194,6 +201,7 @@ static void context_dead(struct pa_context *c) { static void pstream_die_callback(struct pa_pstream *p, void *userdata) { struct pa_context *c = userdata; assert(p && c); + c->error = PA_ERROR_CONNECTIONTERMINATED; context_dead(c); } @@ -203,6 +211,7 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { fprintf(stderr, "polyp.c: invalid packet.\n"); + c->error = PA_ERROR_PROTOCOL; context_dead(c); } } @@ -212,7 +221,7 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, in struct pa_stream *s; assert(p && chunk && c && chunk->memblock && chunk->memblock->data); - if (!(s = pa_dynarray_get(c->streams, channel))) + if (!(s = pa_dynarray_get(c->record_streams, channel))) return; if (s->read_callback) @@ -353,6 +362,26 @@ void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_cont c->die_userdata = userdata; } +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + uint32_t channel; + assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) + return; + + c->error = PA_ERROR_KILLED; + stream_dead(s); +} + static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_stream *s; struct pa_context *c = userdata; @@ -367,7 +396,7 @@ static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t return; } - if (!(s = pa_dynarray_get(c->streams, channel))) + if (!(s = pa_dynarray_get(c->playback_streams, channel))) return; if (s->state != STREAM_READY) @@ -405,7 +434,7 @@ static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, ui } s->channel_valid = 1; - pa_dynarray_put(s->context->streams, s->channel, s); + pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, s); s->state = STREAM_READY; if (s->create_complete_callback) @@ -562,7 +591,7 @@ void pa_stream_free(struct pa_stream *s) { } if (s->channel_valid) - pa_dynarray_put(s->context->streams, s->channel, NULL); + pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); if (s->next) s->next->previous = s->previous; diff --git a/src/protocol-native-spec.h b/src/protocol-native-spec.h index fea14cc09..5e67fe74a 100644 --- a/src/protocol-native-spec.h +++ b/src/protocol-native-spec.h @@ -16,6 +16,8 @@ enum { PA_COMMAND_LOOKUP_SINK, PA_COMMAND_LOOKUP_SOURCE, PA_COMMAND_DRAIN_PLAYBACK_STREAM, + PA_COMMAND_PLAYBACK_STREAM_KILLED, + PA_COMMAND_RECORD_STREAM_KILLED, PA_COMMAND_MAX }; @@ -31,6 +33,8 @@ enum { PA_ERROR_TIMEOUT, PA_ERROR_AUTHKEY, PA_ERROR_INTERNAL, + PA_ERROR_CONNECTIONTERMINATED, + PA_ERROR_KILLED, PA_ERROR_MAX }; diff --git a/src/protocol-native.c b/src/protocol-native.c index fe086066a..c7a7cce07 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -254,6 +254,31 @@ static void send_memblock(struct connection *c) { } } +static void send_playback_stream_killed(struct playback_stream *p) { + struct pa_tagstruct *t; + assert(p); + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, p->index); + pa_pstream_send_tagstruct(p->connection->pstream, t); +} + +static void send_record_stream_killed(struct record_stream *r) { + struct pa_tagstruct *t; + assert(r); + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, r->index); + pa_pstream_send_tagstruct(r->connection->pstream, t); +} + + /*** sinkinput callbacks ***/ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { @@ -283,6 +308,7 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { static void sink_input_kill_cb(struct pa_sink_input *i) { assert(i && i->userdata); + send_playback_stream_killed((struct playback_stream *) i->userdata); playback_stream_free((struct playback_stream *) i->userdata); } @@ -308,6 +334,7 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me static void source_output_kill_cb(struct pa_source_output *o) { assert(o && o->userdata); + send_record_stream_killed((struct record_stream *) o->userdata); record_stream_free((struct record_stream *) o->userdata); } diff --git a/src/simple.c b/src/simple.c index ba0a8f0c6..5f86c5bf6 100644 --- a/src/simple.c +++ b/src/simple.c @@ -1,3 +1,5 @@ +#include +#include #include #include @@ -10,10 +12,16 @@ struct pa_simple { struct pa_mainloop *mainloop; struct pa_context *context; struct pa_stream *stream; + enum pa_stream_direction direction; int dead, drained; + + void *read_data; + size_t read_index, read_length; }; +static void read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata); + static int check_error(struct pa_simple *p, int *perror) { assert(p); @@ -71,6 +79,9 @@ struct pa_simple* pa_simple_new( p->mainloop = pa_mainloop_new(); assert(p->mainloop); p->dead = 0; + p->direction = dir; + p->read_data = NULL; + p->read_index = p->read_length = 0; if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name))) goto fail; @@ -95,6 +106,8 @@ struct pa_simple* pa_simple_new( goto fail; } + pa_stream_set_read_callback(p->stream, read_callback, p); + return p; fail: @@ -107,6 +120,8 @@ fail: void pa_simple_free(struct pa_simple *s) { assert(s); + free(s->read_data); + if (s->stream) pa_stream_free(s->stream); @@ -120,7 +135,7 @@ void pa_simple_free(struct pa_simple *s) { } int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *perror) { - assert(p && data); + assert(p && data && p->direction == PA_STREAM_PLAYBACK); while (length > 0) { size_t l; @@ -144,10 +159,57 @@ int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *pe return 0; } -int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *perror) { - assert(0); +static void read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata) { + struct pa_simple *p = userdata; + assert(s && data && length && p); + + if (p->read_data) { + fprintf(stderr, __FILE__": Buffer overflow, dropping incoming memory blocks.\n"); + free(p->read_data); + } + + p->read_data = malloc(p->read_length = length); + assert(p->read_data); + memcpy(p->read_data, data, length); + p->read_index = 0; } +int pa_simple_read(struct pa_simple *p, void*data, size_t length, int *perror) { + assert(p && data && p->direction == PA_STREAM_RECORD); + + while (length > 0) { + if (p->read_data) { + size_t l = length; + + if (p->read_length <= l) + l = p->read_length; + + memcpy(data, p->read_data+p->read_index, l); + + data += l; + length -= l; + + p->read_index += l; + p->read_length -= l; + + if (!p->read_length) { + free(p->read_data); + p->read_data = NULL; + p->read_index = 0; + } + + if (!length) + return 0; + + assert(!p->read_data); + } + + if (iterate(p, 1, perror) < 0) + return -1; + } + + return 0; +} static void drain_complete(struct pa_stream *s, void *userdata) { struct pa_simple *p = userdata; @@ -156,7 +218,7 @@ static void drain_complete(struct pa_stream *s, void *userdata) { } int pa_simple_drain(struct pa_simple *p, int *perror) { - assert(p); + assert(p && p->direction == PA_STREAM_PLAYBACK); p->drained = 0; pa_stream_drain(p->stream, drain_complete, p); diff --git a/src/todo b/src/todo index ee971ca0a..1e1e02c50 100644 --- a/src/todo +++ b/src/todo @@ -1,4 +1,3 @@ -- implement parec-simple - native library/protocol: more functions (esp. latency) @@ -21,7 +20,7 @@ - svn-id and license in every file - documentation - +- dependency checking script -- post 0.1 - future cancellation From 5ee3a59469f9c86659e6de21e70f96f1d7627347 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 10 Jul 2004 19:06:48 +0000 Subject: [PATCH 0056/1514] forgot to add parec-simple git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@57 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/parec-simple.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/parec-simple.c diff --git a/src/parec-simple.c b/src/parec-simple.c new file mode 100644 index 000000000..a2841bebc --- /dev/null +++ b/src/parec-simple.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +#include "simple.h" +#include "polyp-error.h" + +#define BUFSIZE 1024 + +static ssize_t loop_write(int fd, const void*data, size_t size) { + ssize_t ret = 0; + + while (size > 0) { + ssize_t r; + + if ((r = write(fd, data, size)) < 0) + return r; + + if (r == 0) + break; + + ret += r; + data += r; + size -= r; + } + + return ret; +} + +int main(int argc, char*argv[]) { + static const struct pa_sample_spec ss = { + .format = PA_SAMPLE_S16LE, + .rate = 44100, + .channels = 2 + }; + struct pa_simple *s = NULL; + int ret = 1; + int error; + + if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, &error))) { + fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); + goto finish; + } + + for (;;) { + uint8_t buf[BUFSIZE]; + ssize_t r; + + if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) { + fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error)); + goto finish; + } + + if ((r = loop_write(STDOUT_FILENO, buf, sizeof(buf))) <= 0) { + fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno)); + goto finish; + } + } + + ret = 0; + +finish: + + if (s) + pa_simple_free(s); + + return ret; +} From 025389693d292b7a1c5f2c6e0ce96efa14062274 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 10 Jul 2004 19:23:45 +0000 Subject: [PATCH 0057/1514] make memblockq merge chunks git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@58 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/memblockq.c | 12 ++++++++++++ src/protocol-esound.c | 2 +- src/todo | 3 +-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/memblockq.c b/src/memblockq.c index fb4cbc7e1..6d4d712a4 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -82,6 +82,18 @@ void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, struct memblock_list *q; assert(bq && chunk && chunk->memblock && chunk->length && (chunk->length % bq->base) == 0); + if (bq->blocks_tail && bq->blocks_tail->chunk.memblock == chunk->memblock) { + /* Try to merge memory chunks */ + + if (bq->blocks_tail->chunk.index+bq->blocks_tail->chunk.length == chunk->index) { + bq->blocks_tail->chunk.length += chunk->length; + bq->current_length += chunk->length; + + /* fprintf(stderr, __FILE__": merge succeeded: %u\n", chunk->length);*/ + return; + } + } + q = malloc(sizeof(struct memblock_list)); assert(q); diff --git a/src/protocol-esound.c b/src/protocol-esound.c index e97ab34d0..4d9ca546a 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -394,7 +394,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v continue; assert(t >= s+k+k); - + if (conn->sink_input) { rate = conn->sink_input->sample_spec.rate; volume = (conn->sink_input->volume*0xFF)/0x100; diff --git a/src/todo b/src/todo index 1e1e02c50..8c647a8d6 100644 --- a/src/todo +++ b/src/todo @@ -9,8 +9,6 @@ - move more stuff from module-oss[-dma] to liboss-util -- merge memchunks in memblockq - - create libstatustext, libsocketutil - prefix modules/libraries with pa_ @@ -29,6 +27,7 @@ - autoloading/autounloading - slp/rendezvous - doxygen +- make mcalign merge chunks drivers: - libao From c7bd759cdb2b8f16693750f89ed781707a53e5a9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 10 Jul 2004 20:56:38 +0000 Subject: [PATCH 0058/1514] add description field for sinks/sources add owner field to all entities add client file to source outputs and sink inputs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@59 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/cli.c | 3 ++- src/cli.h | 3 ++- src/client.c | 9 +++++++-- src/client.h | 2 ++ src/module-cli.c | 2 +- src/module-oss-mmap.c | 6 ++++++ src/module-oss.c | 21 +++++++++++++-------- src/module-pipe-sink.c | 4 ++++ src/module-protocol-stub.c | 4 ++-- src/protocol-cli.c | 6 ++++-- src/protocol-cli.h | 3 ++- src/protocol-esound.c | 13 ++++++++++--- src/protocol-esound.h | 3 ++- src/protocol-native.c | 12 ++++++++++-- src/protocol-native.h | 3 ++- src/protocol-simple.c | 9 ++++++++- src/protocol-simple.h | 4 +++- src/sink.c | 24 ++++++++++++++++++------ src/sink.h | 5 +++-- src/sinkinput.c | 7 +++++++ src/sinkinput.h | 4 ++++ src/source.c | 22 +++++++++++++++++----- src/source.h | 5 ++++- src/sourceoutput.c | 6 ++++++ src/sourceoutput.h | 4 ++++ src/strbuf.c | 2 ++ src/strbuf.h | 2 +- src/todo | 4 ---- src/util.c | 30 ++++++++++++++++++++++++++++++ src/util.h | 2 ++ 30 files changed, 178 insertions(+), 46 deletions(-) diff --git a/src/cli.c b/src/cli.c index 429aebf3b..b7fc787a2 100644 --- a/src/cli.c +++ b/src/cli.c @@ -83,7 +83,7 @@ static const char prompt[] = ">>> "; static void client_kill(struct pa_client *c); -struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io) { +struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct pa_module *m) { char cname[256]; struct pa_cli *c; assert(io); @@ -102,6 +102,7 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io) { assert(c->client); c->client->kill = client_kill; c->client->userdata = c; + c->client->owner = m; pa_ioline_set_callback(c->line, line_callback, c); pa_ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"); diff --git a/src/cli.h b/src/cli.h index 80d9fec7c..d6250b372 100644 --- a/src/cli.h +++ b/src/cli.h @@ -3,10 +3,11 @@ #include "iochannel.h" #include "core.h" +#include "module.h" struct pa_cli; -struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io); +struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct pa_module *m); void pa_cli_free(struct pa_cli *cli); void pa_cli_set_eof_callback(struct pa_cli *cli, void (*cb)(struct pa_cli*c, void *userdata), void *userdata); diff --git a/src/client.c b/src/client.c index d07f188fe..fa1a28d4a 100644 --- a/src/client.c +++ b/src/client.c @@ -14,6 +14,7 @@ struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, c = malloc(sizeof(struct pa_client)); assert(c); c->name = name ? strdup(name) : NULL; + c->owner = NULL; c->core = core; c->protocol_name = protocol_name; @@ -58,9 +59,13 @@ char *pa_client_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u client(s).\n", pa_idxset_ncontents(c->clients)); - for (client = pa_idxset_first(c->clients, &index); client; client = pa_idxset_next(c->clients, &index)) + for (client = pa_idxset_first(c->clients, &index); client; client = pa_idxset_next(c->clients, &index)) { pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tprotocol_name: <%s>\n", client->index, client->name, client->protocol_name); - + + if (client->owner) + pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index); + } + return pa_strbuf_tostring_free(s); } diff --git a/src/client.h b/src/client.h index 4ca8d96ec..d603411df 100644 --- a/src/client.h +++ b/src/client.h @@ -2,10 +2,12 @@ #define fooclienthfoo #include "core.h" +#include "module.h" struct pa_client { uint32_t index; + struct pa_module *owner; char *name; struct pa_core *core; const char *protocol_name; diff --git a/src/module-cli.c b/src/module-cli.c index a6e9582d7..440c4ba5a 100644 --- a/src/module-cli.c +++ b/src/module-cli.c @@ -27,7 +27,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(io); pa_iochannel_set_noclose(io, 1); - m->userdata = pa_cli_new(c, io); + m->userdata = pa_cli_new(c, io, m); assert(m->userdata); pa_cli_set_eof_callback(m->userdata, eof_cb, m); diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index 280484d00..772abf998 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -17,6 +17,7 @@ #include "module.h" #include "oss-util.h" #include "sample-util.h" +#include "util.h" struct userdata { struct pa_sink *sink; @@ -244,6 +245,9 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->source = pa_source_new(c, "oss_input", 0, &u->sample_spec); assert(u->source); u->source->userdata = u; + pa_source_set_owner(u->source, m); + u->source->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'", p); + u->in_memblocks = malloc(sizeof(struct pa_memblock *)*u->in_fragments); memset(u->in_memblocks, 0, sizeof(struct pa_memblock *)*u->in_fragments); @@ -276,6 +280,8 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'", p); u->out_memblocks = malloc(sizeof(struct memblock *)*u->out_fragments); memset(u->out_memblocks, 0, sizeof(struct pa_memblock *)*u->out_fragments); diff --git a/src/module-oss.c b/src/module-oss.c index 5ec9d2d70..b06775841 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -16,6 +16,7 @@ #include "module.h" #include "oss-util.h" #include "sample-util.h" +#include "util.h" struct userdata { struct pa_sink *sink; @@ -180,21 +181,25 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->core = c; + if (mode != O_WRONLY) { + u->source = pa_source_new(c, "oss_input", 0, &ss); + assert(u->source); + u->source->userdata = u; + pa_source_set_owner(u->source, m); + u->sink->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p); + } else + u->source = NULL; + if (mode != O_RDONLY) { - u->sink = pa_sink_new(c, "dsp", 0, &ss); + u->sink = pa_sink_new(c, "oss_output", 0, &ss); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p); } else u->sink = NULL; - if (mode != O_WRONLY) { - u->source = pa_source_new(c, "dsp", 0, &ss); - assert(u->source); - u->source->userdata = u; - } else - u->source = NULL; - assert(u->source || u->sink); u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0); diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index efba3b5f2..67c024044 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -11,6 +11,7 @@ #include "iochannel.h" #include "sink.h" #include "module.h" +#include "util.h" struct userdata { char *filename; @@ -113,6 +114,9 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(u->sink); u->sink->notify = notify_cb; u->sink->userdata = u; + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("Unix FIFO sink '%s'", p); + assert(u->sink->description); u->io = pa_iochannel_new(c->mainloop, -1, fd); assert(u->io); diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 885ea4c87..3bb0a0729 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -78,9 +78,9 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { #endif #ifdef USE_PROTOCOL_SIMPLE - m->userdata = pa_protocol_simple_new(c, s, PA_PROTOCOL_SIMPLE_PLAYBACK); + m->userdata = pa_protocol_simple_new(c, s, m, PA_PROTOCOL_SIMPLE_PLAYBACK); #else - m->userdata = protocol_new(c, s); + m->userdata = protocol_new(c, s, m); #endif if (!m->userdata) { diff --git a/src/protocol-cli.c b/src/protocol-cli.c index 0cdf2db1e..55b4a8a06 100644 --- a/src/protocol-cli.c +++ b/src/protocol-cli.c @@ -5,6 +5,7 @@ #include "cli.h" struct pa_protocol_cli { + struct pa_module *module; struct pa_core *core; struct pa_socket_server*server; struct pa_idxset *connections; @@ -22,19 +23,20 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo struct pa_cli *c; assert(s && io && p); - c = pa_cli_new(p->core, io); + c = pa_cli_new(p->core, io, p->module); assert(c); pa_cli_set_eof_callback(c, cli_eof_cb, p); pa_idxset_put(p->connections, c, NULL); } -struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server) { +struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m) { struct pa_protocol_cli* p; assert(core && server); p = malloc(sizeof(struct pa_protocol_cli)); assert(p); + p->module = m; p->core = core; p->server = server; p->connections = pa_idxset_new(NULL, NULL); diff --git a/src/protocol-cli.h b/src/protocol-cli.h index fc6a7d65d..c3bb8b4f5 100644 --- a/src/protocol-cli.h +++ b/src/protocol-cli.h @@ -3,10 +3,11 @@ #include "core.h" #include "socket-server.h" +#include "module.h" struct pa_protocol_cli; -struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server); +struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m); void pa_protocol_cli_free(struct pa_protocol_cli *n); #endif diff --git a/src/protocol-esound.c b/src/protocol-esound.c index 4d9ca546a..fc4444c35 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -50,6 +50,7 @@ struct connection { struct pa_protocol_esound { int public; + struct pa_module *module; struct pa_core *core; struct pa_socket_server *server; struct pa_idxset *connections; @@ -260,6 +261,8 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons c->sink_input = pa_sink_input_new(sink, name, &ss); assert(c->sink_input); + c->sink_input->owner = c->protocol->module; + c->sink_input->client = c->client; c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; c->sink_input->kill = sink_input_kill_cb; @@ -321,7 +324,9 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co assert(!c->source_output); c->source_output = pa_source_output_new(source, name, &ss); assert(c->source_output); - + + c->source_output->owner = c->protocol->module; + c->source_output->client = c->client; c->source_output->push = source_output_push_cb; c->source_output->kill = source_output_kill_cb; c->source_output->userdata = c; @@ -733,6 +738,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo assert(c->protocol->core); c->client = pa_client_new(c->protocol->core, "ESOUND", cname); assert(c->client); + c->client->owner = c->protocol->module; c->client->kill = client_kill_cb; c->client->userdata = c; @@ -768,7 +774,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo /*** entry points ***/ -struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server) { +struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m) { struct pa_protocol_esound *p; assert(core && server); @@ -779,7 +785,8 @@ struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa free(p); return NULL; } - + + p->module = m; p->public = 0; p->server = server; pa_socket_server_set_callback(p->server, on_connection, p); diff --git a/src/protocol-esound.h b/src/protocol-esound.h index cd505593a..6071699d3 100644 --- a/src/protocol-esound.h +++ b/src/protocol-esound.h @@ -3,10 +3,11 @@ #include "core.h" #include "socket-server.h" +#include "module.h" struct pa_protocol_esound; -struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server); +struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m); void pa_protocol_esound_free(struct pa_protocol_esound *p); #endif diff --git a/src/protocol-native.c b/src/protocol-native.c index c7a7cce07..d6a5f9b2b 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -48,6 +48,7 @@ struct connection { }; struct pa_protocol_native { + struct pa_module *module; int public; struct pa_core *core; struct pa_socket_server *server; @@ -110,6 +111,8 @@ static struct record_stream* record_stream_new(struct connection *c, struct pa_s s->source_output->push = source_output_push_cb; s->source_output->kill = source_output_kill_cb; s->source_output->userdata = s; + s->source_output->owner = c->protocol->module; + s->source_output->client = c->client; s->memblockq = pa_memblockq_new(maxlength, 0, base = pa_sample_size(ss), 0, 0); assert(s->memblockq); @@ -153,6 +156,8 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct s->sink_input->kill = sink_input_kill_cb; s->sink_input->get_latency = sink_input_get_latency_cb; s->sink_input->userdata = s; + s->sink_input->owner = c->protocol->module; + s->sink_input->client = c->client; s->memblockq = pa_memblockq_new(maxlength, tlength, pa_sample_size(ss), prebuf, minreq); assert(s->memblockq); @@ -707,6 +712,8 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo assert(c->client); c->client->kill = client_kill_cb; c->client->userdata = c; + c->client->owner = p->module; + c->pstream = pa_pstream_new(p->core->mainloop, io); assert(c->pstream); @@ -729,7 +736,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo /*** module entry points ***/ -struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct pa_socket_server *server) { +struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m) { struct pa_protocol_native *p; assert(core && server); @@ -740,7 +747,8 @@ struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct p free(p); return NULL; } - + + p->module = m; p->public = 1; p->server = server; p->core = core; diff --git a/src/protocol-native.h b/src/protocol-native.h index 1a260149e..811b4e4a4 100644 --- a/src/protocol-native.h +++ b/src/protocol-native.h @@ -3,10 +3,11 @@ #include "core.h" #include "socket-server.h" +#include "module.h" struct pa_protocol_native; -struct pa_protocol_native* pa_protocol_native_new(struct pa_core*core, struct pa_socket_server *server); +struct pa_protocol_native* pa_protocol_native_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m); void pa_protocol_native_free(struct pa_protocol_native *n); #endif diff --git a/src/protocol-simple.c b/src/protocol-simple.c index e7ca0a76c..518d5f24b 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -27,6 +27,7 @@ struct connection { }; struct pa_protocol_simple { + struct pa_module *module; struct pa_core *core; struct pa_socket_server*server; struct pa_idxset *connections; @@ -258,6 +259,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); c->client = pa_client_new(p->core, "SIMPLE", cname); assert(c->client); + c->client->owner = p->module; c->client->kill = client_kill_cb; c->client->userdata = c; @@ -275,6 +277,8 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo fprintf(stderr, "Failed to create sink input.\n"); goto fail; } + c->sink_input->owner = p->module; + c->sink_input->client = c->client; c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; @@ -304,6 +308,8 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo fprintf(stderr, "Failed to create source output.\n"); goto fail; } + c->source_output->owner = p->module; + c->source_output->client = c->client; c->source_output->push = source_output_push_cb; c->source_output->kill = source_output_kill_cb; @@ -328,12 +334,13 @@ fail: connection_free(c); } -struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, enum pa_protocol_simple_mode mode) { +struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, enum pa_protocol_simple_mode mode) { struct pa_protocol_simple* p; assert(core && server && mode <= PA_PROTOCOL_SIMPLE_DUPLEX && mode > 0); p = malloc(sizeof(struct pa_protocol_simple)); assert(p); + p->module = m; p->core = core; p->server = server; p->connections = pa_idxset_new(NULL, NULL); diff --git a/src/protocol-simple.h b/src/protocol-simple.h index 15ae36a6c..6b2a2cd13 100644 --- a/src/protocol-simple.h +++ b/src/protocol-simple.h @@ -2,6 +2,8 @@ #define fooprotocolsimplehfoo #include "socket-server.h" +#include "module.h" +#include "core.h" struct pa_protocol_simple; @@ -11,7 +13,7 @@ enum pa_protocol_simple_mode { PA_PROTOCOL_SIMPLE_DUPLEX = 3 }; -struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, enum pa_protocol_simple_mode mode); +struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, enum pa_protocol_simple_mode mode); void pa_protocol_simple_free(struct pa_protocol_simple *n); #endif diff --git a/src/sink.c b/src/sink.c index 80560724c..6a9f35803 100644 --- a/src/sink.c +++ b/src/sink.c @@ -8,6 +8,7 @@ #include "strbuf.h" #include "sample-util.h" #include "namereg.h" +#include "util.h" #define MAX_MIX_CHANNELS 32 @@ -16,7 +17,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co char *n = NULL; char st[256]; int r; - assert(core && spec); + assert(core && name && spec); s = malloc(sizeof(struct pa_sink)); assert(s); @@ -27,15 +28,14 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co } s->name = strdup(name); + s->description = NULL; + + s->owner = NULL; s->core = core; s->sample_spec = *spec; s->inputs = pa_idxset_new(NULL, NULL); - if (name) { - n = malloc(strlen(name)+9); - sprintf(n, "%s_monitor", name); - } - + n = pa_sprintf_malloc("%s_monitor", name); s->monitor_source = pa_source_new(core, n, 0, spec); assert(s->monitor_source); free(n); @@ -75,6 +75,7 @@ void pa_sink_free(struct pa_sink *s) { fprintf(stderr, "sink: freed %u \"%s\"\n", s->index, s->name); free(s->name); + free(s->description); free(s); } @@ -285,8 +286,19 @@ char *pa_sink_list_to_string(struct pa_core *c) { pa_sink_get_latency(sink), sink->monitor_source->index, ss); + + if (sink->owner) + pa_strbuf_printf(s, "\towner module: <%u>\n", sink->owner->index); + if (sink->description) + pa_strbuf_printf(s, "\tdescription: <%s>\n", sink->description); } return pa_strbuf_tostring_free(s); } +void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) { + sink->owner = m; + + if (sink->monitor_source) + pa_source_set_owner(sink->monitor_source, m); +} diff --git a/src/sink.h b/src/sink.h index 7186f5312..071ad0947 100644 --- a/src/sink.h +++ b/src/sink.h @@ -13,7 +13,8 @@ struct pa_sink; struct pa_sink { uint32_t index; - char *name; + char *name, *description; + struct pa_module *owner; struct pa_core *core; struct pa_sample_spec sample_spec; struct pa_idxset *inputs; @@ -42,6 +43,6 @@ char *pa_sink_list_to_string(struct pa_core *core); struct pa_sink* pa_sink_get_default(struct pa_core *c); - +void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m); #endif diff --git a/src/sinkinput.c b/src/sinkinput.c index f3e474bcc..3cfe49b32 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -23,6 +23,8 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con i = malloc(sizeof(struct pa_sink_input)); assert(i); i->name = name ? strdup(name) : NULL; + i->client = NULL; + i->owner = NULL; i->sink = s; i->sample_spec = *spec; @@ -96,6 +98,11 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { (unsigned) i->volume, pa_sink_input_get_latency(i), ss); + + if (i->owner) + pa_strbuf_printf(s, "\towner module: <%u>\n", i->owner->index); + if (i->client) + pa_strbuf_printf(s, "\tclient: <%u>\n", i->client->index); } return pa_strbuf_tostring_free(s); diff --git a/src/sinkinput.h b/src/sinkinput.h index b28b51ef9..8c9813e55 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -7,11 +7,15 @@ #include "sample.h" #include "memblockq.h" #include "resampler.h" +#include "module.h" +#include "client.h" struct pa_sink_input { uint32_t index; char *name; + struct pa_module *owner; + struct pa_client *client; struct pa_sink *sink; struct pa_sample_spec sample_spec; uint32_t volume; diff --git a/src/source.c b/src/source.c index 44d7da01d..45ccfb271 100644 --- a/src/source.c +++ b/src/source.c @@ -12,7 +12,7 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail struct pa_source *s; char st[256]; int r; - assert(core && spec); + assert(core && spec && name); s = malloc(sizeof(struct pa_source)); assert(s); @@ -23,6 +23,9 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail } s->name = strdup(name); + s->description = NULL; + + s->owner = NULL; s->core = core; s->sample_spec = *spec; s->outputs = pa_idxset_new(NULL, NULL); @@ -58,6 +61,7 @@ void pa_source_free(struct pa_source *s) { fprintf(stderr, "source: freed %u \"%s\"\n", s->index, s->name); free(s->name); + free(s->description); free(s); } @@ -112,13 +116,21 @@ char *pa_source_list_to_string(struct pa_core *c) { for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - char mo[256] = ""; - if (source->monitor_of) - snprintf(mo, sizeof(mo), "\n\tmonitor_of: <%u>", source->monitor_of->index); pa_sample_snprint(ss, sizeof(ss), &source->sample_spec); - pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tsample_spec: <%s>%s\n", source == default_source ? '*' : ' ', source->index, source->name, ss, mo); + pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tsample_spec: <%s>\n", source == default_source ? '*' : ' ', source->index, source->name, ss); + + if (source->monitor_of) + pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index); + if (source->owner) + pa_strbuf_printf(s, "\towner module: <%u>\n", source->owner->index); + if (source->description) + pa_strbuf_printf(s, "\tdescription: <%s>\n", source->description); } return pa_strbuf_tostring_free(s); } +void pa_source_set_owner(struct pa_source *s, struct pa_module *m) { + assert(s); + s->owner = m; +} diff --git a/src/source.h b/src/source.h index 3b66cd368..2bc5bea8c 100644 --- a/src/source.h +++ b/src/source.h @@ -14,7 +14,8 @@ struct pa_source; struct pa_source { uint32_t index; - char *name; + char *name, *description; + struct pa_module *owner; struct pa_core *core; struct pa_sample_spec sample_spec; struct pa_idxset *outputs; @@ -36,4 +37,6 @@ char *pa_source_list_to_string(struct pa_core *c); struct pa_source* pa_source_get_default(struct pa_core *c); +void pa_source_set_owner(struct pa_source *s, struct pa_module *m); + #endif diff --git a/src/sourceoutput.c b/src/sourceoutput.c index 442dc7f44..ea7275768 100644 --- a/src/sourceoutput.c +++ b/src/sourceoutput.c @@ -18,6 +18,8 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n o = malloc(sizeof(struct pa_source_output)); assert(o); o->name = name ? strdup(name) : NULL; + o->client = NULL; + o->owner = NULL; o->source = s; o->sample_spec = *spec; @@ -77,6 +79,10 @@ char *pa_source_output_list_to_string(struct pa_core *c) { o->name, o->source->index, ss); + if (o->owner) + pa_strbuf_printf(s, "\towner module: <%u>\n", o->owner->index); + if (o->client) + pa_strbuf_printf(s, "\tclient: <%u>\n", o->client->index); } return pa_strbuf_tostring_free(s); diff --git a/src/sourceoutput.h b/src/sourceoutput.h index fb60182a5..dfd076db3 100644 --- a/src/sourceoutput.h +++ b/src/sourceoutput.h @@ -7,11 +7,15 @@ #include "sample.h" #include "memblockq.h" #include "resampler.h" +#include "module.h" +#include "client.h" struct pa_source_output { uint32_t index; char *name; + struct pa_module *owner; + struct pa_client *client; struct pa_source *source; struct pa_sample_spec sample_spec; diff --git a/src/strbuf.c b/src/strbuf.c index c2a6518ea..2082002a9 100644 --- a/src/strbuf.c +++ b/src/strbuf.c @@ -87,6 +87,8 @@ void pa_strbuf_puts(struct pa_strbuf *sb, const char *t) { sb->length += l; } +/* The following is based on an example from the GNU libc documentation */ + int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) { int r, size = 100; struct chunk *c = NULL; diff --git a/src/strbuf.h b/src/strbuf.h index bb9720447..ab0c6a745 100644 --- a/src/strbuf.h +++ b/src/strbuf.h @@ -8,7 +8,7 @@ void pa_strbuf_free(struct pa_strbuf *sb); char *pa_strbuf_tostring(struct pa_strbuf *sb); char *pa_strbuf_tostring_free(struct pa_strbuf *sb); -int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...); +int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) __attribute__ ((format (printf, 2, 3)));; void pa_strbuf_puts(struct pa_strbuf *sb, const char *t); #endif diff --git a/src/todo b/src/todo index 8c647a8d6..36e69a181 100644 --- a/src/todo +++ b/src/todo @@ -3,10 +3,6 @@ - config parser/cmdline -- description field for all entities -- client field for sinkinput/sourceoutput -- module field for all entities - - move more stuff from module-oss[-dma] to liboss-util - create libstatustext, libsocketutil diff --git a/src/util.c b/src/util.c index 6fe4bbee3..aceb772d2 100644 --- a/src/util.c +++ b/src/util.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -230,3 +232,31 @@ void pa_check_for_sigpipe(void) { if (sa.sa_handler == SIG_DFL) fprintf(stderr, "polypaudio: WARNING: SIGPIPE is not trapped. This might cause malfunction!\n"); } + +/* The following is based on an example from the GNU libc documentation */ +char *pa_sprintf_malloc(const char *format, ...) { + int size = 100; + char *c = NULL; + + assert(format); + + for(;;) { + int r; + va_list ap; + + c = realloc(c, size); + assert(c); + + va_start(ap, format); + r = vsnprintf(c, size, format, ap); + va_end(ap); + + if (r > -1 && r < size) + return c; + + if (r > -1) /* glibc 2.1 */ + size = r+1; + else /* glibc 2.0 */ + size *= 2; + } +} diff --git a/src/util.h b/src/util.h index dba89ee89..c5c6db823 100644 --- a/src/util.h +++ b/src/util.h @@ -23,4 +23,6 @@ int pa_unix_socket_remove_stale(const char *fn); void pa_check_for_sigpipe(void); +char *pa_sprintf_malloc(const char *format, ...) __attribute__ ((format (printf, 1, 2))); + #endif From ccfd55420ebec191d7a3ed842ecb2740ceeb76ba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Jul 2004 01:09:46 +0000 Subject: [PATCH 0059/1514] add dependency script fix some dependencies split off socket-util.c and clitext.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@60 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 52 ++++++----- src/cli.c | 1 + src/client.c | 23 ----- src/client.h | 2 - src/clitext.c | 178 +++++++++++++++++++++++++++++++++++++ src/clitext.h | 14 +++ src/depmod.py | 56 ++++++++++++ src/iochannel.c | 3 +- src/module-protocol-stub.c | 1 + src/module.c | 19 ---- src/module.h | 3 - src/protocol-esound.c | 2 +- src/protocol-simple.c | 2 +- src/sink.c | 39 +------- src/sink.h | 2 - src/sinkinput.c | 35 -------- src/sinkinput.h | 1 - src/socket-client.c | 1 + src/socket-server.c | 2 +- src/socket-util.c | 152 +++++++++++++++++++++++++++++++ src/socket-util.h | 17 ++++ src/source.c | 30 ------- src/source.h | 2 - src/sourceoutput.c | 31 ------- src/sourceoutput.h | 2 - src/todo | 3 - src/util.c | 140 ----------------------------- src/util.h | 11 --- 28 files changed, 456 insertions(+), 368 deletions(-) create mode 100644 src/clitext.c create mode 100644 src/clitext.h create mode 100755 src/depmod.py create mode 100644 src/socket-util.c create mode 100644 src/socket-util.h diff --git a/src/Makefile.am b/src/Makefile.am index b02bfba6c..51129534d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,6 +35,8 @@ pkglib_LTLIBRARIES=libiochannel.la \ libpstream-util.la \ libpdispatch.la \ libauthkey.la \ + libclitext.la \ + libsocket-util.la \ libprotocol-simple.la \ libprotocol-esound.la \ libprotocol-native.la \ @@ -94,26 +96,27 @@ libprotocol_simple_la_LIBADD = libsocket-server.la libiochannel.la libsocket_server_la_SOURCES = socket-server.c socket-server.h libsocket_server_la_LDFLAGS = -avoid-version -libsocket_server_la_LIBADD = libiochannel.la +libsocket_server_la_LIBADD = libiochannel.la libsocket-util.la libsocket_client_la_SOURCES = socket-client.c socket-client.h libsocket_client_la_LDFLAGS = -avoid-version -libsocket_client_la_LIBADD = libiochannel.la +libsocket_client_la_LIBADD = libiochannel.la libsocket-util.la libpstream_la_SOURCES = pstream.c pstream.h libpstream_la_LDFLAGS = -avoid-version -libpstream_la_LIBADD = libpacket.la +libpstream_la_LIBADD = libpacket.la libiochannel.la libpstream_util_la_SOURCES = pstream-util.c pstream-util.h libpstream_util_la_LDFLAGS = -avoid-version -libpstream_util_la_LIBADD = libpstream.la libtagstruct.la +libpstream_util_la_LIBADD = libpacket.la libpstream.la libtagstruct.la libpdispatch_la_SOURCES = pdispatch.c pdispatch.h libpdispatch_la_LDFLAGS = -avoid-version -libpdispatch_la_LIBADD = libpacket.la libtagstruct.la +libpdispatch_la_LIBADD = libtagstruct.la libiochannel_la_SOURCES = iochannel.c iochannel.h libiochannel_la_LDFLAGS = -avoid-version +libiochannel_la_LIBDADD = libsocket-util.la libpacket_la_SOURCES = packet.c packet.h libpacket_la_LDFLAGS = -avoid-version @@ -127,7 +130,7 @@ libioline_la_LIBADD = libiochannel.la libcli_la_SOURCES = cli.c cli.h libcli_la_LDFLAGS = -avoid-version -libcli_la_LIBADD = libiochannel.la libioline.la +libcli_la_LIBADD = libiochannel.la libioline.la libclitext.la libtokenizer.la libdynarray_la_SOURCES = dynarray.c dynarray.h libdynarray_la_LDFLAGS = -avoid-version @@ -142,18 +145,24 @@ libprotocol_cli_la_LIBADD = libsocket-server.la libiochannel.la libcli.la libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = libsocket-server.la libiochannel.la libpacket.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la +libprotocol_native_la_LIBADD = libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libtagstruct_la_SOURCES = tagstruct.c tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version -libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h protocol-esound-spec.h +libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h esound-spec.h libprotocol_esound_la_LDFLAGS = -avoid-version libprotocol_esound_la_LIBADD = libsocket-server.la libiochannel.la libauthkey.la libauthkey_la_SOURCES = authkey.c authkey.h libauthkey_la_LDFLAGS = -avoid-version +libclitext_la_SOURCES = clitext.c clitext.h +libclitext_la_LDFLAGS = -avoid-version + +libsocket_util_la_SOURCES = socket-util.c socket-util.h +libsocket_util_la_LDFLAGS = -avoid-version + module_simple_protocol_tcp_la_SOURCES = module-protocol-stub.c module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version @@ -162,7 +171,7 @@ module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libsocket-server.la module_simple_protocol_unix_la_SOURCES = module-protocol-stub.c module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version -module_simple_protocol_unix_la_LIBADD = libprotocol-simple.la libsocket-server.la +module_simple_protocol_unix_la_LIBADD = libprotocol-simple.la libsocket-server.la libsocket-util.la module_cli_protocol_tcp_la_SOURCES = module-protocol-stub.c module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) @@ -172,7 +181,7 @@ module_cli_protocol_tcp_la_LIBADD = libprotocol-cli.la libsocket-server.la module_cli_protocol_unix_la_SOURCES = module-protocol-stub.c module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version -module_cli_protocol_unix_la_LIBADD = libprotocol-cli.la libsocket-server.la +module_cli_protocol_unix_la_LIBADD = libprotocol-cli.la libsocket-server.la libsocket-util.la module_native_protocol_tcp_la_SOURCES = module-protocol-stub.c module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) @@ -182,7 +191,7 @@ module_native_protocol_tcp_la_LIBADD = libprotocol-native.la libsocket-server.la module_native_protocol_unix_la_SOURCES = module-protocol-stub.c module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_unix_la_LDFLAGS = -module -avoid-version -module_native_protocol_unix_la_LIBADD = libprotocol-native.la libsocket-server.la +module_native_protocol_unix_la_LIBADD = libprotocol-native.la libsocket-server.la libsocket-util.la module_esound_protocol_tcp_la_SOURCES = module-protocol-stub.c module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) @@ -192,7 +201,7 @@ module_esound_protocol_tcp_la_LIBADD = libprotocol-esound.la libsocket-server.la module_esound_protocol_unix_la_SOURCES = module-protocol-stub.c module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version -module_esound_protocol_unix_la_LIBADD = libprotocol-esound.la libsocket-server.la +module_esound_protocol_unix_la_LIBADD = libprotocol-esound.la libsocket-server.la libsocket-util.la module_pipe_sink_la_SOURCES = module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version @@ -204,7 +213,7 @@ module_oss_la_LIBADD = libiochannel.la liboss-util.la module_oss_mmap_la_SOURCES = module-oss-mmap.c module_oss_mmap_la_LDFLAGS = -module -avoid-version -module_oss_mmap_la_LIBADD = libiochannel.la liboss-util.la +module_oss_mmap_la_LIBADD = liboss-util.la module_cli_la_SOURCES = module-cli.c module_cli_la_LDFLAGS = -module -avoid-version @@ -229,9 +238,9 @@ libpolyp_la_SOURCES = polyp.c polyp.h \ queue.c queue.h \ dynarray.c dynarray.h \ memchunk.c memchunk.h \ - authkey.c authkey.h + authkey.c authkey.h \ + socket-util.c socket-util.h libpolyp_la_CFLAGS = $(AM_CFLAGS) -#libpolyp_la_LIBADD = libpolyp-error.la libpolyp_error_la_SOURCES = polyp-error.c polyp-error.h libpolyp_error_la_CFLAGS = $(AM_CFLAGS) @@ -239,16 +248,15 @@ libpolyp_error_la_CFLAGS = $(AM_CFLAGS) libpolyp_simple_la_SOURCES = simple.c simple.h libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) libpolyp_simple_la_LIBADD = libpolyp.la -#libpolyp-error.la -pacat_SOURCES = pacat.c $(libpolyp_la_SOURCES) $(libpolyp_error_la_SOURCES) -#pacat_LDADD = libpolyp.la +pacat_SOURCES = pacat.c #$(libpolyp_la_SOURCES) $(libpolyp_error_la_SOURCES) +pacat_LDADD = libpolyp.la libpolyp-error.la pacat_CFLAGS = $(AM_CFLAGS) -pacat_simple_SOURCES = pacat-simple.c $(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) -#pacat_simple_LDADD = libpolyp-simple.la libpolyp-error.la +pacat_simple_SOURCES = pacat-simple.c #$(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) +pacat_simple_LDADD = libpolyp-simple.la libpolyp-error.la pacat_simple_CFLAGS = $(AM_CFLAGS) -parec_simple_SOURCES = parec-simple.c $(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) -#parec_simple_LDADD = libpolyp-simple.la libpolyp-error.la +parec_simple_SOURCES = parec-simple.c #$(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) +parec_simple_LDADD = libpolyp-simple.la libpolyp-error.la parec_simple_CFLAGS = $(AM_CFLAGS) diff --git a/src/cli.c b/src/cli.c index b7fc787a2..d5b46c461 100644 --- a/src/cli.c +++ b/src/cli.c @@ -14,6 +14,7 @@ #include "tokenizer.h" #include "strbuf.h" #include "namereg.h" +#include "clitext.h" struct pa_cli { struct pa_core *core; diff --git a/src/client.c b/src/client.c index fa1a28d4a..c170e49a1 100644 --- a/src/client.c +++ b/src/client.c @@ -4,7 +4,6 @@ #include #include "client.h" -#include "strbuf.h" struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, char *name) { struct pa_client *c; @@ -48,28 +47,6 @@ void pa_client_kill(struct pa_client *c) { c->kill(c); } -char *pa_client_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_client *client; - uint32_t index = PA_IDXSET_INVALID; - assert(c); - - s = pa_strbuf_new(); - assert(s); - - pa_strbuf_printf(s, "%u client(s).\n", pa_idxset_ncontents(c->clients)); - - for (client = pa_idxset_first(c->clients, &index); client; client = pa_idxset_next(c->clients, &index)) { - pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tprotocol_name: <%s>\n", client->index, client->name, client->protocol_name); - - if (client->owner) - pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index); - } - - return pa_strbuf_tostring_free(s); -} - - void pa_client_rename(struct pa_client *c, const char *name) { assert(c); free(c->name); diff --git a/src/client.h b/src/client.h index d603411df..10ffa8f31 100644 --- a/src/client.h +++ b/src/client.h @@ -25,8 +25,6 @@ void pa_client_free(struct pa_client *c); * request destruction of the client */ void pa_client_kill(struct pa_client *c); -char *pa_client_list_to_string(struct pa_core *c); - void pa_client_rename(struct pa_client *c, const char *name); #endif diff --git a/src/clitext.c b/src/clitext.c new file mode 100644 index 000000000..701cf2c05 --- /dev/null +++ b/src/clitext.c @@ -0,0 +1,178 @@ +#include + +#include "clitext.h" +#include "module.h" +#include "client.h" +#include "sink.h" +#include "source.h" +#include "sinkinput.h" +#include "sourceoutput.h" +#include "strbuf.h" +#include "sample-util.h" + +char *pa_module_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_module *m; + uint32_t index = PA_IDXSET_INVALID; + assert(c); + + s = pa_strbuf_new(); + assert(s); + + pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_ncontents(c->modules)); + + for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) + pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\targument: <%s>\n", m->index, m->name, m->argument); + + return pa_strbuf_tostring_free(s); +} + +char *pa_client_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_client *client; + uint32_t index = PA_IDXSET_INVALID; + assert(c); + + s = pa_strbuf_new(); + assert(s); + + pa_strbuf_printf(s, "%u client(s).\n", pa_idxset_ncontents(c->clients)); + + for (client = pa_idxset_first(c->clients, &index); client; client = pa_idxset_next(c->clients, &index)) { + pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tprotocol_name: <%s>\n", client->index, client->name, client->protocol_name); + + if (client->owner) + pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index); + } + + return pa_strbuf_tostring_free(s); +} + +char *pa_sink_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_sink *sink, *default_sink; + uint32_t index = PA_IDXSET_INVALID; + assert(c); + + s = pa_strbuf_new(); + assert(s); + + pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_ncontents(c->sinks)); + + default_sink = pa_sink_get_default(c); + + for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index)) { + char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + pa_sample_snprint(ss, sizeof(ss), &sink->sample_spec); + assert(sink->monitor_source); + pa_strbuf_printf( + s, + " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", + sink == default_sink ? '*' : ' ', + sink->index, sink->name, + (unsigned) sink->volume, + pa_sink_get_latency(sink), + sink->monitor_source->index, + ss); + + if (sink->owner) + pa_strbuf_printf(s, "\towner module: <%u>\n", sink->owner->index); + if (sink->description) + pa_strbuf_printf(s, "\tdescription: <%s>\n", sink->description); + } + + return pa_strbuf_tostring_free(s); +} + +char *pa_source_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_source *source, *default_source; + uint32_t index = PA_IDXSET_INVALID; + assert(c); + + s = pa_strbuf_new(); + assert(s); + + pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_ncontents(c->sources)); + + default_source = pa_source_get_default(c); + + for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { + char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + pa_sample_snprint(ss, sizeof(ss), &source->sample_spec); + pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tsample_spec: <%s>\n", source == default_source ? '*' : ' ', source->index, source->name, ss); + + if (source->monitor_of) + pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index); + if (source->owner) + pa_strbuf_printf(s, "\towner module: <%u>\n", source->owner->index); + if (source->description) + pa_strbuf_printf(s, "\tdescription: <%s>\n", source->description); + } + + return pa_strbuf_tostring_free(s); +} + + +char *pa_source_output_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_source_output *o; + uint32_t index = PA_IDXSET_INVALID; + assert(c); + + s = pa_strbuf_new(); + assert(s); + + pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_ncontents(c->source_outputs)); + + for (o = pa_idxset_first(c->source_outputs, &index); o; o = pa_idxset_next(c->source_outputs, &index)) { + char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + pa_sample_snprint(ss, sizeof(ss), &o->sample_spec); + assert(o->source); + pa_strbuf_printf( + s, " index: %u\n\tname: <%s>\n\tsource: <%u>\n\tsample_spec: <%s>\n", + o->index, + o->name, + o->source->index, + ss); + if (o->owner) + pa_strbuf_printf(s, "\towner module: <%u>\n", o->owner->index); + if (o->client) + pa_strbuf_printf(s, "\tclient: <%u>\n", o->client->index); + } + + return pa_strbuf_tostring_free(s); +} + +char *pa_sink_input_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + struct pa_sink_input *i; + uint32_t index = PA_IDXSET_INVALID; + assert(c); + + s = pa_strbuf_new(); + assert(s); + + pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_ncontents(c->sink_inputs)); + + for (i = pa_idxset_first(c->sink_inputs, &index); i; i = pa_idxset_next(c->sink_inputs, &index)) { + char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + pa_sample_snprint(ss, sizeof(ss), &i->sample_spec); + assert(i->sink); + pa_strbuf_printf( + s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tsample_spec: <%s>\n", + i->index, + i->name, + i->sink->index, + (unsigned) i->volume, + pa_sink_input_get_latency(i), + ss); + + if (i->owner) + pa_strbuf_printf(s, "\towner module: <%u>\n", i->owner->index); + if (i->client) + pa_strbuf_printf(s, "\tclient: <%u>\n", i->client->index); + } + + return pa_strbuf_tostring_free(s); +} diff --git a/src/clitext.h b/src/clitext.h new file mode 100644 index 000000000..5b17c2d76 --- /dev/null +++ b/src/clitext.h @@ -0,0 +1,14 @@ +#ifndef fooclitexthfoo +#define fooclitexthfoo + +#include "core.h" + +char *pa_sink_input_list_to_string(struct pa_core *c); +char *pa_source_output_list_to_string(struct pa_core *c); +char *pa_sink_list_to_string(struct pa_core *core); +char *pa_source_list_to_string(struct pa_core *c); +char *pa_client_list_to_string(struct pa_core *c); +char *pa_module_list_to_string(struct pa_core *c); + +#endif + diff --git a/src/depmod.py b/src/depmod.py new file mode 100755 index 000000000..d11cceb41 --- /dev/null +++ b/src/depmod.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# $Id$ + +import sys, os, string + +exported_symbols = {} +imported_symbols = {} + +for fn in sys.argv[1:]: + f = os.popen("nm '%s'" % fn, "r") + + imported_symbols[fn] = [] + + for line in f: + sym_address = line[:7].strip() + sym_type = line[9].strip() + sym_name = line[11:].strip() + + if sym_name in ('_fini', '_init'): + continue + + if sym_type in ('T', 'B', 'R', 'D' 'G', 'S', 'D'): + if exported_symbols.has_key(sym_name): + sys.stderr.write("CONFLICT: %s defined in both '%s' and '%s'.\n" % (sym_name, fn, exported_symbols[sym_name])) + else: + exported_symbols[sym_name] = fn + elif sym_type in ('U',): + if sym_name[:3] == 'pa_': + imported_symbols[fn].append(sym_name) + + f.close() + +dependencies = {} +unresolved_symbols = {} + +for fn in imported_symbols: + dependencies[fn] = [] + + for sym in imported_symbols[fn]: + if exported_symbols.has_key(sym): + if exported_symbols[sym] not in dependencies[fn]: + dependencies[fn].append(exported_symbols[sym]) + else: + if unresolved_symbols.has_key(sym): + unresolved_symbols[sym].append(fn) + else: + unresolved_symbols[sym] = [fn] + +for sym, files in unresolved_symbols.iteritems(): + print "WARNING: Unresolved symbol '%s' in %s" % (sym, `files`) + +k = dependencies.keys() +k.sort() +for fn in k: + dependencies[fn].sort() + print "%s: %s" % (fn, string.join(dependencies[fn], " ")) diff --git a/src/iochannel.c b/src/iochannel.c index 775c61394..384300346 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -5,6 +5,7 @@ #include "iochannel.h" #include "util.h" +#include "socket-util.h" struct pa_iochannel { int ifd, ofd; @@ -182,7 +183,7 @@ void pa_iochannel_set_noclose(struct pa_iochannel*io, int b) { void pa_iochannel_socket_peer_to_string(struct pa_iochannel*io, char*s, size_t l) { assert(io && s && l); - pa_peer_to_string(s, l, io->ifd); + pa_socket_peer_to_string(io->ifd, s, l); } int pa_iochannel_socket_set_rcvbuf(struct pa_iochannel *io, size_t l) { diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 3bb0a0729..0547f7e60 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -7,6 +7,7 @@ #include "module.h" #include "socket-server.h" +#include "socket-util.h" #include "util.h" #ifdef USE_PROTOCOL_SIMPLE diff --git a/src/module.c b/src/module.c index 87df3b38d..b6a706c35 100644 --- a/src/module.c +++ b/src/module.c @@ -6,7 +6,6 @@ #include #include "module.h" -#include "strbuf.h" struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char *argument) { struct pa_module *m = NULL; @@ -112,24 +111,6 @@ void pa_module_unload_all(struct pa_core *c) { c->modules = NULL; } -char *pa_module_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_module *m; - uint32_t index = PA_IDXSET_INVALID; - assert(c); - - s = pa_strbuf_new(); - assert(s); - - pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_ncontents(c->modules)); - - for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) - pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\targument: <%s>\n", m->index, m->name, m->argument); - - return pa_strbuf_tostring_free(s); -} - - struct once_info { struct pa_core *core; uint32_t index; diff --git a/src/module.h b/src/module.h index 2a9cf5583..174a8d092 100644 --- a/src/module.h +++ b/src/module.h @@ -25,11 +25,8 @@ void pa_module_unload_by_index(struct pa_core *c, uint32_t index); void pa_module_unload_all(struct pa_core *c); -char *pa_module_list_to_string(struct pa_core *c); - void pa_module_unload_request(struct pa_core *c, struct pa_module *m); - /* These to following prototypes are for module entrypoints and not implemented by the core */ int pa_module_init(struct pa_core *c, struct pa_module*m); void pa_module_done(struct pa_core *c, struct pa_module*m); diff --git a/src/protocol-esound.c b/src/protocol-esound.c index fc4444c35..955ab93cc 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -660,7 +660,7 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { /*** fixed callback ***/ -void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) { +static void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) { struct connection *c = userdata; assert(a && c && c->fixed_source == id); diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 518d5f24b..b57f324ab 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -229,7 +229,7 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { /*** fixed callback ***/ -void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) { +static void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) { struct connection *c = userdata; assert(a && c && c->fixed_source == id); diff --git a/src/sink.c b/src/sink.c index 6a9f35803..9ba79e39e 100644 --- a/src/sink.c +++ b/src/sink.c @@ -5,10 +5,9 @@ #include "sink.h" #include "sinkinput.h" -#include "strbuf.h" -#include "sample-util.h" #include "namereg.h" #include "util.h" +#include "sample-util.h" #define MAX_MIX_CHANNELS 32 @@ -260,42 +259,6 @@ struct pa_sink* pa_sink_get_default(struct pa_core *c) { return sink; } -char *pa_sink_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_sink *sink, *default_sink; - uint32_t index = PA_IDXSET_INVALID; - assert(c); - - s = pa_strbuf_new(); - assert(s); - - pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_ncontents(c->sinks)); - - default_sink = pa_sink_get_default(c); - - for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index)) { - char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - pa_sample_snprint(ss, sizeof(ss), &sink->sample_spec); - assert(sink->monitor_source); - pa_strbuf_printf( - s, - " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", - sink == default_sink ? '*' : ' ', - sink->index, sink->name, - (unsigned) sink->volume, - pa_sink_get_latency(sink), - sink->monitor_source->index, - ss); - - if (sink->owner) - pa_strbuf_printf(s, "\towner module: <%u>\n", sink->owner->index); - if (sink->description) - pa_strbuf_printf(s, "\tdescription: <%s>\n", sink->description); - } - - return pa_strbuf_tostring_free(s); -} - void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) { sink->owner = m; diff --git a/src/sink.h b/src/sink.h index 071ad0947..a25a4377b 100644 --- a/src/sink.h +++ b/src/sink.h @@ -39,8 +39,6 @@ uint32_t pa_sink_get_latency(struct pa_sink *s); void pa_sink_notify(struct pa_sink*s); -char *pa_sink_list_to_string(struct pa_core *core); - struct pa_sink* pa_sink_get_default(struct pa_core *c); void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m); diff --git a/src/sinkinput.c b/src/sinkinput.c index 3cfe49b32..54778a81e 100644 --- a/src/sinkinput.c +++ b/src/sinkinput.c @@ -4,7 +4,6 @@ #include #include "sinkinput.h" -#include "strbuf.h" #include "sample-util.h" #define CONVERT_BUFFER_LENGTH 4096 @@ -75,39 +74,6 @@ void pa_sink_input_kill(struct pa_sink_input*i) { i->kill(i); } -char *pa_sink_input_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_sink_input *i; - uint32_t index = PA_IDXSET_INVALID; - assert(c); - - s = pa_strbuf_new(); - assert(s); - - pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_ncontents(c->sink_inputs)); - - for (i = pa_idxset_first(c->sink_inputs, &index); i; i = pa_idxset_next(c->sink_inputs, &index)) { - char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - pa_sample_snprint(ss, sizeof(ss), &i->sample_spec); - assert(i->sink); - pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tsample_spec: <%s>\n", - i->index, - i->name, - i->sink->index, - (unsigned) i->volume, - pa_sink_input_get_latency(i), - ss); - - if (i->owner) - pa_strbuf_printf(s, "\towner module: <%u>\n", i->owner->index); - if (i->client) - pa_strbuf_printf(s, "\tclient: <%u>\n", i->client->index); - } - - return pa_strbuf_tostring_free(s); -} - uint32_t pa_sink_input_get_latency(struct pa_sink_input *i) { uint32_t l = 0; @@ -121,7 +87,6 @@ uint32_t pa_sink_input_get_latency(struct pa_sink_input *i) { return l; } - int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { assert(i && chunk && i->peek && i->drop); diff --git a/src/sinkinput.h b/src/sinkinput.h index 8c9813e55..02a2a1172 100644 --- a/src/sinkinput.h +++ b/src/sinkinput.h @@ -39,7 +39,6 @@ void pa_sink_input_free(struct pa_sink_input* i); void pa_sink_input_kill(struct pa_sink_input *i); uint32_t pa_sink_input_get_latency(struct pa_sink_input *i); -char *pa_sink_input_list_to_string(struct pa_core *c); int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk); void pa_sink_input_drop(struct pa_sink_input *i, size_t length); diff --git a/src/socket-client.c b/src/socket-client.c index 9a8c56078..8b2bd384c 100644 --- a/src/socket-client.c +++ b/src/socket-client.c @@ -9,6 +9,7 @@ #include #include "socket-client.h" +#include "socket-util.h" #include "util.h" struct pa_socket_client { diff --git a/src/socket-server.c b/src/socket-server.c index 23d8f7e7c..02b4328fc 100644 --- a/src/socket-server.c +++ b/src/socket-server.c @@ -11,7 +11,7 @@ #include #include "socket-server.h" -#include "util.h" +#include "socket-util.h" struct pa_socket_server { int fd; diff --git a/src/socket-util.c b/src/socket-util.c new file mode 100644 index 000000000..f9451af8d --- /dev/null +++ b/src/socket-util.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socket-util.h" + +void pa_socket_peer_to_string(int fd, char *c, size_t l) { + struct stat st; + + assert(c && l && fd >= 0); + + if (fstat(fd, &st) < 0) { + snprintf(c, l, "Invalid client fd"); + return; + } + + if (S_ISSOCK(st.st_mode)) { + union { + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_un un; + } sa; + socklen_t sa_len = sizeof(sa); + + if (getpeername(fd, &sa.sa, &sa_len) >= 0) { + + if (sa.sa.sa_family == AF_INET) { + uint32_t ip = ntohl(sa.in.sin_addr.s_addr); + + snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u", + ip >> 24, + (ip >> 16) & 0xFF, + (ip >> 8) & 0xFF, + ip & 0xFF, + ntohs(sa.in.sin_port)); + return; + } else if (sa.sa.sa_family == AF_LOCAL) { + snprintf(c, l, "UNIX socket client"); + return; + } + + } + snprintf(c, l, "Unknown network client"); + return; + } else if (S_ISCHR(st.st_mode) && (fd == 0 || fd == 1)) { + snprintf(c, l, "STDIN/STDOUT client"); + return; + } + + snprintf(c, l, "Unknown client"); +} + +int pa_socket_low_delay(int fd) { + int priority; + assert(fd >= 0); + + priority = 7; + if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0) + return -1; + + return 0; +} + +int pa_socket_tcp_low_delay(int fd) { + int ret, tos; + + assert(fd >= 0); + + ret = pa_socket_low_delay(fd); + +/* on = 1; */ +/* if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) */ +/* ret = -1; */ + + tos = IPTOS_LOWDELAY; + if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0) + ret = -1; + + return ret; + +} + +int pa_socket_set_rcvbuf(int fd, size_t l) { + assert(fd >= 0); + + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) + return -1; + + return 0; +} + +int pa_socket_set_sndbuf(int fd, size_t l) { + assert(fd >= 0); + + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) + return -1; + + return 0; +} + +int pa_unix_socket_is_stale(const char *fn) { + struct sockaddr_un sa; + int fd = -1, ret = -1; + + if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "socket(): %s\n", strerror(errno)); + goto finish; + } + + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1); + sa.sun_path[sizeof(sa.sun_path) - 1] = 0; + + if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) { + if (errno == ECONNREFUSED) + ret = 1; + } else + ret = 0; + +finish: + if (fd >= 0) + close(fd); + + return ret; +} + +int pa_unix_socket_remove_stale(const char *fn) { + int r; + + if ((r = pa_unix_socket_is_stale(fn)) < 0) + return errno != ENOENT ? -1 : 0; + + if (!r) + return 0; + + /* Yes, here is a race condition. But who cares? */ + if (unlink(fn) < 0) + return -1; + + return 0; +} diff --git a/src/socket-util.h b/src/socket-util.h new file mode 100644 index 000000000..1c4dbe358 --- /dev/null +++ b/src/socket-util.h @@ -0,0 +1,17 @@ +#ifndef foosocketutilhfoo +#define foosocketutilhfoo + +#include + +void pa_socket_peer_to_string(int fd, char *c, size_t l); + +int pa_socket_low_delay(int fd); +int pa_socket_tcp_low_delay(int fd); + +int pa_socket_set_sndbuf(int fd, size_t l); +int pa_socket_set_rcvbuf(int fd, size_t l); + +int pa_unix_socket_is_stale(const char *fn); +int pa_unix_socket_remove_stale(const char *fn); + +#endif diff --git a/src/source.c b/src/source.c index 45ccfb271..c0eec3ead 100644 --- a/src/source.c +++ b/src/source.c @@ -5,7 +5,6 @@ #include "source.h" #include "sourceoutput.h" -#include "strbuf.h" #include "namereg.h" struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) { @@ -101,35 +100,6 @@ struct pa_source* pa_source_get_default(struct pa_core *c) { return source; } -char *pa_source_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_source *source, *default_source; - uint32_t index = PA_IDXSET_INVALID; - assert(c); - - s = pa_strbuf_new(); - assert(s); - - pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_ncontents(c->sources)); - - default_source = pa_source_get_default(c); - - for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { - char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - pa_sample_snprint(ss, sizeof(ss), &source->sample_spec); - pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tsample_spec: <%s>\n", source == default_source ? '*' : ' ', source->index, source->name, ss); - - if (source->monitor_of) - pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index); - if (source->owner) - pa_strbuf_printf(s, "\towner module: <%u>\n", source->owner->index); - if (source->description) - pa_strbuf_printf(s, "\tdescription: <%s>\n", source->description); - } - - return pa_strbuf_tostring_free(s); -} - void pa_source_set_owner(struct pa_source *s, struct pa_module *m) { assert(s); s->owner = m; diff --git a/src/source.h b/src/source.h index 2bc5bea8c..9e57bc0fb 100644 --- a/src/source.h +++ b/src/source.h @@ -33,8 +33,6 @@ void pa_source_post(struct pa_source*s, struct pa_memchunk *b); void pa_source_notify(struct pa_source *s); -char *pa_source_list_to_string(struct pa_core *c); - struct pa_source* pa_source_get_default(struct pa_core *c); void pa_source_set_owner(struct pa_source *s, struct pa_module *m); diff --git a/src/sourceoutput.c b/src/sourceoutput.c index ea7275768..25c661a98 100644 --- a/src/sourceoutput.c +++ b/src/sourceoutput.c @@ -3,7 +3,6 @@ #include #include "sourceoutput.h" -#include "strbuf.h" struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec) { struct pa_source_output *o; @@ -58,36 +57,6 @@ void pa_source_output_kill(struct pa_source_output*i) { i->kill(i); } -char *pa_source_output_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_source_output *o; - uint32_t index = PA_IDXSET_INVALID; - assert(c); - - s = pa_strbuf_new(); - assert(s); - - pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_ncontents(c->source_outputs)); - - for (o = pa_idxset_first(c->source_outputs, &index); o; o = pa_idxset_next(c->source_outputs, &index)) { - char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - pa_sample_snprint(ss, sizeof(ss), &o->sample_spec); - assert(o->source); - pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\tsource: <%u>\n\tsample_spec: <%s>\n", - o->index, - o->name, - o->source->index, - ss); - if (o->owner) - pa_strbuf_printf(s, "\towner module: <%u>\n", o->owner->index); - if (o->client) - pa_strbuf_printf(s, "\tclient: <%u>\n", o->client->index); - } - - return pa_strbuf_tostring_free(s); -} - void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk *chunk) { struct pa_memchunk rchunk; assert(o && chunk && chunk->length && o->push); diff --git a/src/sourceoutput.h b/src/sourceoutput.h index dfd076db3..a8ea5a9f6 100644 --- a/src/sourceoutput.h +++ b/src/sourceoutput.h @@ -32,8 +32,6 @@ void pa_source_output_free(struct pa_source_output* o); void pa_source_output_kill(struct pa_source_output*o); -char *pa_source_output_list_to_string(struct pa_core *c); - void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk *chunk); #endif diff --git a/src/todo b/src/todo index 36e69a181..bf01a4c4b 100644 --- a/src/todo +++ b/src/todo @@ -5,7 +5,6 @@ - move more stuff from module-oss[-dma] to liboss-util -- create libstatustext, libsocketutil - prefix modules/libraries with pa_ - xmms+esound latency testing @@ -14,8 +13,6 @@ - svn-id and license in every file - documentation -- dependency checking script - -- post 0.1 - future cancellation - client-ui diff --git a/src/util.c b/src/util.c index aceb772d2..773922b55 100644 --- a/src/util.c +++ b/src/util.c @@ -5,13 +5,9 @@ #include #include #include -#include -#include #include #include #include -#include -#include #include "util.h" @@ -23,52 +19,6 @@ void pa_make_nonblock_fd(int fd) { fcntl(fd, F_SETFL, v|O_NONBLOCK); } -void pa_peer_to_string(char *c, size_t l, int fd) { - struct stat st; - - assert(c && l && fd >= 0); - - if (fstat(fd, &st) < 0) { - snprintf(c, l, "Invalid client fd"); - return; - } - - if (S_ISSOCK(st.st_mode)) { - union { - struct sockaddr sa; - struct sockaddr_in in; - struct sockaddr_un un; - } sa; - socklen_t sa_len = sizeof(sa); - - if (getpeername(fd, &sa.sa, &sa_len) >= 0) { - - if (sa.sa.sa_family == AF_INET) { - uint32_t ip = ntohl(sa.in.sin_addr.s_addr); - - snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u", - ip >> 24, - (ip >> 16) & 0xFF, - (ip >> 8) & 0xFF, - ip & 0xFF, - ntohs(sa.in.sin_port)); - return; - } else if (sa.sa.sa_family == AF_LOCAL) { - snprintf(c, l, "UNIX socket client"); - return; - } - - } - snprintf(c, l, "Unknown network client"); - return; - } else if (S_ISCHR(st.st_mode) && (fd == 0 || fd == 1)) { - snprintf(c, l, "STDIN/STDOUT client"); - return; - } - - snprintf(c, l, "Unknown client"); -} - int pa_make_secure_dir(const char* dir) { struct stat st; @@ -89,54 +39,6 @@ fail: return -1; } -int pa_socket_low_delay(int fd) { - int priority; - assert(fd >= 0); - - priority = 7; - if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0) - return -1; - - return 0; -} - -int pa_socket_tcp_low_delay(int fd) { - int ret, tos; - - assert(fd >= 0); - - ret = pa_socket_low_delay(fd); - -/* on = 1; */ -/* if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) */ -/* ret = -1; */ - - tos = IPTOS_LOWDELAY; - if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0) - ret = -1; - - return ret; - -} - -int pa_socket_set_rcvbuf(int fd, size_t l) { - assert(fd >= 0); - - if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) - return -1; - - return 0; -} - -int pa_socket_set_sndbuf(int fd, size_t l) { - assert(fd >= 0); - - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) - return -1; - - return 0; -} - ssize_t pa_loop_read(int fd, void*data, size_t size) { ssize_t ret = 0; assert(fd >= 0 && data && size); @@ -179,48 +81,6 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) { return ret; } -int pa_unix_socket_is_stale(const char *fn) { - struct sockaddr_un sa; - int fd = -1, ret = -1; - - if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "socket(): %s\n", strerror(errno)); - goto finish; - } - - sa.sun_family = AF_LOCAL; - strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1); - sa.sun_path[sizeof(sa.sun_path) - 1] = 0; - - if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) { - if (errno == ECONNREFUSED) - ret = 1; - } else - ret = 0; - -finish: - if (fd >= 0) - close(fd); - - return ret; -} - -int pa_unix_socket_remove_stale(const char *fn) { - int r; - - if ((r = pa_unix_socket_is_stale(fn)) < 0) - return errno != ENOENT ? -1 : 0; - - if (!r) - return 0; - - /* Yes, here is a race condition. But who cares? */ - if (unlink(fn) < 0) - return -1; - - return 0; -} - void pa_check_for_sigpipe(void) { struct sigaction sa; diff --git a/src/util.h b/src/util.h index c5c6db823..3e4944347 100644 --- a/src/util.h +++ b/src/util.h @@ -5,22 +5,11 @@ void pa_make_nonblock_fd(int fd); -void pa_peer_to_string(char *c, size_t l, int fd); - int pa_make_secure_dir(const char* dir); -int pa_socket_low_delay(int fd); -int pa_socket_tcp_low_delay(int fd); - -int pa_socket_set_sndbuf(int fd, size_t l); -int pa_socket_set_rcvbuf(int fd, size_t l); - ssize_t pa_loop_read(int fd, void*data, size_t size); ssize_t pa_loop_write(int fd, const void*data, size_t size); -int pa_unix_socket_is_stale(const char *fn); -int pa_unix_socket_remove_stale(const char *fn); - void pa_check_for_sigpipe(void); char *pa_sprintf_malloc(const char *format, ...) __attribute__ ((format (printf, 1, 2))); From a96ed347a30fdc7494b96542c0ad8a19ef178b25 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Jul 2004 16:59:22 +0000 Subject: [PATCH 0060/1514] rename hashset to hashmap add module arguments parse in modargs.c make module-pipe-sink use it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@61 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 5 +- src/core.h | 4 +- src/{hashset.c => hashmap.c} | 46 ++++---- src/hashmap.h | 16 +++ src/hashset.h | 16 --- src/modargs.c | 222 +++++++++++++++++++++++++++++++++++ src/modargs.h | 18 +++ src/module-pipe-sink.c | 75 ++++++++---- src/namereg.c | 18 +-- src/todo | 6 +- 10 files changed, 350 insertions(+), 76 deletions(-) rename src/{hashset.c => hashmap.c} (69%) create mode 100644 src/hashmap.h delete mode 100644 src/hashset.h create mode 100644 src/modargs.c create mode 100644 src/modargs.h diff --git a/src/Makefile.am b/src/Makefile.am index 51129534d..e8704f786 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,7 +75,7 @@ polypaudio_SOURCES = idxset.c idxset.h \ mainloop-signal.c mainloop-signal.h \ mainloop-api.c mainloop-api.h \ util.c util.h \ - hashset.c hashset.h \ + hashmap.c hashmap.h \ namereg.c namereg.h \ sconv.c sconv.h \ resampler.c resampler.h \ @@ -83,7 +83,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ memchunk.c memchunk.h \ sconv-s16le.c sconv-s16le.h \ sconv-s16be.c sconv-s16be.h \ - sioman.c sioman.h + sioman.c sioman.h \ + modargs.c modargs.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) diff --git a/src/core.h b/src/core.h index 8eb638d94..13374e400 100644 --- a/src/core.h +++ b/src/core.h @@ -2,7 +2,7 @@ #define foocorehfoo #include "idxset.h" -#include "hashset.h" +#include "hashmap.h" #include "mainloop-api.h" struct pa_core { @@ -10,7 +10,7 @@ struct pa_core { struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules; - struct pa_hashset *namereg; + struct pa_hashmap *namereg; uint32_t default_source_index, default_sink_index; }; diff --git a/src/hashset.c b/src/hashmap.c similarity index 69% rename from src/hashset.c rename to src/hashmap.c index 4815a13a4..0c963f126 100644 --- a/src/hashset.c +++ b/src/hashmap.c @@ -2,33 +2,33 @@ #include #include -#include "hashset.h" +#include "hashmap.h" #include "idxset.h" -struct hashset_entry { - struct hashset_entry *next, *previous, *bucket_next, *bucket_previous; +struct hashmap_entry { + struct hashmap_entry *next, *previous, *bucket_next, *bucket_previous; unsigned hash; const void *key; void *value; }; -struct pa_hashset { +struct pa_hashmap { unsigned size; - struct hashset_entry **data; - struct hashset_entry *first_entry; + struct hashmap_entry **data; + struct hashmap_entry *first_entry; unsigned n_entries; unsigned (*hash_func) (const void *p); int (*compare_func) (const void*a, const void*b); }; -struct pa_hashset *pa_hashset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { - struct pa_hashset *h; - h = malloc(sizeof(struct pa_hashset)); +struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { + struct pa_hashmap *h; + h = malloc(sizeof(struct pa_hashmap)); assert(h); - h->data = malloc(sizeof(struct hashset_entry*)*(h->size = 1023)); + h->data = malloc(sizeof(struct hashmap_entry*)*(h->size = 1023)); assert(h->data); - memset(h->data, 0, sizeof(struct hashset_entry*)*(h->size = 1023)); + memset(h->data, 0, sizeof(struct hashmap_entry*)*(h->size = 1023)); h->first_entry = NULL; h->n_entries = 0; h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; @@ -36,7 +36,7 @@ struct pa_hashset *pa_hashset_new(unsigned (*hash_func) (const void *p), int (*c return h; } -static void remove(struct pa_hashset *h, struct hashset_entry *e) { +static void remove(struct pa_hashmap *h, struct hashmap_entry *e) { assert(e); if (e->next) @@ -57,7 +57,7 @@ static void remove(struct pa_hashset *h, struct hashset_entry *e) { h->n_entries--; } -void pa_hashset_free(struct pa_hashset*h, void (*free_func)(void *p, void *userdata), void *userdata) { +void pa_hashmap_free(struct pa_hashmap*h, void (*free_func)(void *p, void *userdata), void *userdata) { assert(h); while (h->first_entry) { @@ -70,8 +70,8 @@ void pa_hashset_free(struct pa_hashset*h, void (*free_func)(void *p, void *userd free(h); } -static struct hashset_entry *get(struct pa_hashset *h, unsigned hash, const void *key) { - struct hashset_entry *e; +static struct hashmap_entry *get(struct pa_hashmap *h, unsigned hash, const void *key) { + struct hashmap_entry *e; for (e = h->data[hash]; e; e = e->bucket_next) if (h->compare_func(e->key, key) == 0) @@ -80,8 +80,8 @@ static struct hashset_entry *get(struct pa_hashset *h, unsigned hash, const void return NULL; } -int pa_hashset_put(struct pa_hashset *h, const void *key, void *value) { - struct hashset_entry *e; +int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value) { + struct hashmap_entry *e; unsigned hash; assert(h && key); @@ -90,7 +90,7 @@ int pa_hashset_put(struct pa_hashset *h, const void *key, void *value) { if ((e = get(h, hash, key))) return -1; - e = malloc(sizeof(struct hashset_entry)); + e = malloc(sizeof(struct hashmap_entry)); assert(e); e->hash = hash; @@ -113,9 +113,9 @@ int pa_hashset_put(struct pa_hashset *h, const void *key, void *value) { return 0; } -void* pa_hashset_get(struct pa_hashset *h, const void *key) { +void* pa_hashmap_get(struct pa_hashmap *h, const void *key) { unsigned hash; - struct hashset_entry *e; + struct hashmap_entry *e; assert(h && key); hash = h->hash_func(key) % h->size; @@ -126,8 +126,8 @@ void* pa_hashset_get(struct pa_hashset *h, const void *key) { return e->value; } -int pa_hashset_remove(struct pa_hashset *h, const void *key) { - struct hashset_entry *e; +int pa_hashmap_remove(struct pa_hashmap *h, const void *key) { + struct hashmap_entry *e; unsigned hash; assert(h && key); @@ -140,6 +140,6 @@ int pa_hashset_remove(struct pa_hashset *h, const void *key) { return 0; } -unsigned pa_hashset_ncontents(struct pa_hashset *h) { +unsigned pa_hashmap_ncontents(struct pa_hashmap *h) { return h->n_entries; } diff --git a/src/hashmap.h b/src/hashmap.h new file mode 100644 index 000000000..4a0ad77ec --- /dev/null +++ b/src/hashmap.h @@ -0,0 +1,16 @@ +#ifndef foohashmaphfoo +#define foohashmaphfoo + +struct pa_hashmap; + +struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); +void pa_hashmap_free(struct pa_hashmap*, void (*free_func)(void *p, void *userdata), void *userdata); + +int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value); +void* pa_hashmap_get(struct pa_hashmap *h, const void *key); + +int pa_hashmap_remove(struct pa_hashmap *h, const void *key); + +unsigned pa_hashmap_ncontents(struct pa_hashmap *h); + +#endif diff --git a/src/hashset.h b/src/hashset.h deleted file mode 100644 index a6ece8bf7..000000000 --- a/src/hashset.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef foohashsethfoo -#define foohashsethfoo - -struct pa_hashset; - -struct pa_hashset *pa_hashset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); -void pa_hashset_free(struct pa_hashset*, void (*free_func)(void *p, void *userdata), void *userdata); - -int pa_hashset_put(struct pa_hashset *h, const void *key, void *value); -void* pa_hashset_get(struct pa_hashset *h, const void *key); - -int pa_hashset_remove(struct pa_hashset *h, const void *key); - -unsigned pa_hashset_ncontents(struct pa_hashset *h); - -#endif diff --git a/src/modargs.c b/src/modargs.c new file mode 100644 index 000000000..a7b48808e --- /dev/null +++ b/src/modargs.c @@ -0,0 +1,222 @@ +#include +#include +#include +#include + +#include "hashmap.h" +#include "modargs.h" +#include "idxset.h" +#include "sample-util.h" + +struct pa_modargs; + +struct entry { + char *key, *value; +}; + +static int add_key_value(struct pa_hashmap *map, char *key, char *value, const char* const* valid_keys) { + struct entry *e; + assert(map && key && value); + + if (valid_keys) { + const char*const* v; + for (v = valid_keys; *v; v++) + if (strcmp(*v, key) == 0) + break; + + if (!*v) { + free(key); + free(value); + return -1; + } + } + + e = malloc(sizeof(struct entry)); + assert(e); + e->key = key; + e->value = value; + pa_hashmap_put(map, key, e); + return 0; +} + +struct pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) { + struct pa_hashmap *map = NULL; + + map = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + assert(map); + + if (args) { + enum { WHITESPACE, KEY, VALUE_START, VALUE_SIMPLE, VALUE_DOUBLE_QUOTES, VALUE_TICKS } state; + const char *p, *key, *value; + size_t key_len, value_len; + + key = value = NULL; + state = WHITESPACE; + for (p = args; *p; p++) { + switch (state) { + case WHITESPACE: + if (*p == '=') + goto fail; + else if (!isspace(*p)) { + key = p; + state = KEY; + key_len = 1; + } + break; + case KEY: + if (*p == '=') + state = VALUE_START; + else + key_len++; + break; + case VALUE_START: + if (*p == '\'') { + state = VALUE_TICKS; + value = p+1; + value_len = 0; + } else if (*p == '"') { + state = VALUE_DOUBLE_QUOTES; + value = p+1; + value_len = 0; + } else if (isspace(*p)) { + if (add_key_value(map, strndup(key, key_len), strdup(""), valid_keys) < 0) + goto fail; + state = WHITESPACE; + } else { + state = VALUE_SIMPLE; + value = p; + value_len = 1; + } + break; + case VALUE_SIMPLE: + if (isspace(*p)) { + if (add_key_value(map, strndup(key, key_len), strndup(value, value_len), valid_keys) < 0) + goto fail; + state = WHITESPACE; + } else + value_len++; + break; + case VALUE_DOUBLE_QUOTES: + if (*p == '"') { + if (add_key_value(map, strndup(key, key_len), strndup(value, value_len), valid_keys) < 0) + goto fail; + state = WHITESPACE; + } else + value_len++; + break; + case VALUE_TICKS: + if (*p == '\'') { + if (add_key_value(map, strndup(key, key_len), strndup(value, value_len), valid_keys) < 0) + goto fail; + state = WHITESPACE; + } else + value_len++; + break; + } + } + + if (state == VALUE_START) { + if (add_key_value(map, strndup(key, key_len), strdup(""), valid_keys) < 0) + goto fail; + } else if (state == VALUE_SIMPLE) { + if (add_key_value(map, strndup(key, key_len), strdup(value), valid_keys) < 0) + goto fail; + } else if (state != WHITESPACE) + goto fail; + } + + return (struct pa_modargs*) map; + +fail: + + if (map) + pa_modargs_free((struct pa_modargs*) map); + + return NULL; +} + + +static void free_func(void *p, void*userdata) { + struct entry *e = p; + assert(e); + free(e->key); + free(e->value); + free(e); +} + +void pa_modargs_free(struct pa_modargs*ma) { + struct pa_hashmap *map = (struct pa_hashmap*) ma; + pa_hashmap_free(map, free_func, NULL); +} + +const char *pa_modargs_get_value(struct pa_modargs *ma, const char *key, const char *def) { + struct pa_hashmap *map = (struct pa_hashmap*) ma; + struct entry*e; + + if (!(e = pa_hashmap_get(map, key))) + return def; + + return e->value; +} + +int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *value) { + const char *v; + char *e; + unsigned long l; + assert(ma && key && value); + + if (!(v = pa_modargs_get_value(ma, key, NULL))) + return 0; + + if (!*v) + return -1; + + l = strtoul(v, &e, 0); + if (*e) + return -1; + + *value = (uint32_t) l; + return 0; +} + +int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss) { + const char *format; + uint32_t channels; + struct pa_sample_spec ss; + assert(ma && rss); + + ss = pa_default_sample_spec; + if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0) + return -1; + + channels = ss.channels; + if ((pa_modargs_get_value_u32(ma, "channels", &channels)) < 0) + return -1; + ss.channels = (uint8_t) channels; + + if ((format = pa_modargs_get_value(ma, "format", NULL))) { + if (strcmp(format, "s16le") == 0) + ss.format = PA_SAMPLE_S16LE; + else if (strcmp(format, "s16be") == 0) + ss.format = PA_SAMPLE_S16BE; + else if (strcmp(format, "s16ne") == 0 || strcmp(format, "s16") == 0 || strcmp(format, "16") == 0) + ss.format = PA_SAMPLE_S16NE; + else if (strcmp(format, "u8") == 0 || strcmp(format, "8") == 0) + ss.format = PA_SAMPLE_U8; + else if (strcmp(format, "float32") == 0) + ss.format = PA_SAMPLE_FLOAT32; + else if (strcmp(format, "ulaw") == 0) + ss.format = PA_SAMPLE_ULAW; + else if (strcmp(format, "alaw") == 0) + ss.format = PA_SAMPLE_ALAW; + else + return -1; + } + + if (!pa_sample_spec_valid(&ss)) + return -1; + + *rss = ss; + + return 0; +} diff --git a/src/modargs.h b/src/modargs.h new file mode 100644 index 000000000..437dd4321 --- /dev/null +++ b/src/modargs.h @@ -0,0 +1,18 @@ +#ifndef foomodargshfoo +#define foomodargshfoo + +#include +#include "sample.h" + +struct pa_modargs; + +struct pa_modargs *pa_modargs_new(const char *args, const char* const* keys); +void pa_modargs_free(struct pa_modargs*ma); + +const char *pa_modargs_get_value(struct pa_modargs *ma, const char *key, const char *def); +int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *value); + +int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *ss); + + +#endif diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index 67c024044..e5e97b517 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -12,24 +12,37 @@ #include "sink.h" #include "module.h" #include "util.h" +#include "modargs.h" + +#define DEFAULT_FIFO_NAME "/tmp/musicfifo" +#define DEFAULT_SINK_NAME "fifo_output" struct userdata { + struct pa_core *core; + char *filename; struct pa_sink *sink; struct pa_iochannel *io; - struct pa_core *core; void *mainloop_source; - struct pa_mainloop_api *mainloop; struct pa_memchunk memchunk; }; +static const char* const valid_modargs[] = { + "file", + "rate", + "channels", + "format", + "sink", + NULL +}; + static void do_write(struct userdata *u) { ssize_t r; assert(u); - u->mainloop->enable_fixed(u->mainloop, u->mainloop_source, 0); + u->core->mainloop->enable_fixed(u->core->mainloop, u->mainloop_source, 0); if (!pa_iochannel_is_writable(u->io)) return; @@ -59,7 +72,7 @@ static void notify_cb(struct pa_sink*s) { assert(s && u); if (pa_iochannel_is_writable(u->io)) - u->mainloop->enable_fixed(u->mainloop, u->mainloop_source, 1); + u->core->mainloop->enable_fixed(u->core->mainloop, u->mainloop_source, 1); } static void fixed_callback(struct pa_mainloop_api *m, void *id, void *userdata) { @@ -77,41 +90,51 @@ static void io_callback(struct pa_iochannel *io, void*userdata) { int pa_module_init(struct pa_core *c, struct pa_module*m) { struct userdata *u = NULL; struct stat st; - char *p; + const char *p; int fd = -1; - static const struct pa_sample_spec ss = { - .format = PA_SAMPLE_S16NE, - .rate = 44100, - .channels = 2, - }; + struct pa_sample_spec ss; + struct pa_modargs *ma = NULL; assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + fprintf(stderr, __FILE__": failed to parse module arguments\n"); + goto fail; + } - mkfifo((p = m->argument ? m->argument : "/tmp/musicfifo"), 0777); + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + fprintf(stderr, __FILE__": invalid sample format specification\n"); + goto fail; + } + + mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); if ((fd = open(p, O_RDWR)) < 0) { - fprintf(stderr, "open('%s'): %s\n", p, strerror(errno)); + fprintf(stderr, __FILE__": open('%s'): %s\n", p, strerror(errno)); goto fail; } if (fstat(fd, &st) < 0) { - fprintf(stderr, "fstat('%s'): %s\n", p, strerror(errno)); + fprintf(stderr, __FILE__": fstat('%s'): %s\n", p, strerror(errno)); goto fail; } if (!S_ISFIFO(st.st_mode)) { - fprintf(stderr, "'%s' is not a FIFO\n", p); + fprintf(stderr, __FILE__": '%s' is not a FIFO.\n", p); goto fail; } - u = malloc(sizeof(struct userdata)); assert(u); + memset(u, 0, sizeof(struct userdata)); u->filename = strdup(p); assert(u->filename); u->core = c; - u->sink = pa_sink_new(c, "fifo", 0, &ss); - assert(u->sink); + + if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink", DEFAULT_SINK_NAME), 0, &ss))) { + fprintf(stderr, __FILE__": failed to create sink.\n"); + goto fail; + } u->sink->notify = notify_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); @@ -125,19 +148,25 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; - u->mainloop = c->mainloop; - u->mainloop_source = u->mainloop->source_fixed(u->mainloop, fixed_callback, u); + u->mainloop_source = c->mainloop->source_fixed(c->mainloop, fixed_callback, u); assert(u->mainloop_source); - u->mainloop->enable_fixed(u->mainloop, u->mainloop_source, 0); + c->mainloop->enable_fixed(c->mainloop, u->mainloop_source, 0); m->userdata = u; + pa_modargs_free(ma); + return 0; fail: + if (ma) + pa_modargs_free(ma); + if (fd >= 0) close(fd); + pa_module_done(c, m); + return -1; } @@ -145,15 +174,15 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); - u = m->userdata; - assert(u); + if (!(u = m->userdata)) + return; if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); pa_sink_free(u->sink); pa_iochannel_free(u->io); - u->mainloop->cancel_fixed(u->mainloop, u->mainloop_source); + u->core->mainloop->cancel_fixed(u->core->mainloop, u->mainloop_source); assert(u->filename); unlink(u->filename); diff --git a/src/namereg.c b/src/namereg.c index 9cfb7353c..bf381ae4a 100644 --- a/src/namereg.c +++ b/src/namereg.c @@ -17,8 +17,8 @@ void pa_namereg_free(struct pa_core *c) { assert(c); if (!c->namereg) return; - assert(pa_hashset_ncontents(c->namereg) == 0); - pa_hashset_free(c->namereg, NULL, NULL); + assert(pa_hashmap_ncontents(c->namereg) == 0); + pa_hashmap_free(c->namereg, NULL, NULL); } const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_namereg_type type, void *data, int fail) { @@ -29,11 +29,11 @@ const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_nam assert(c && name && data); if (!c->namereg) { - c->namereg = pa_hashset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + c->namereg = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); assert(c->namereg); } - if ((e = pa_hashset_get(c->namereg, name)) && fail) + if ((e = pa_hashmap_get(c->namereg, name)) && fail) return NULL; if (!e) @@ -47,7 +47,7 @@ const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_nam for (i = 1; i <= 99; i++) { snprintf(n, l+2, "%s%u", name, i); - if (!(e = pa_hashset_get(c->namereg, n))) + if (!(e = pa_hashmap_get(c->namereg, n))) break; } @@ -64,7 +64,7 @@ const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_nam e->name = n; e->data = data; - r = pa_hashset_put(c->namereg, e->name, e); + r = pa_hashmap_put(c->namereg, e->name, e); assert (r >= 0); return e->name; @@ -76,10 +76,10 @@ void pa_namereg_unregister(struct pa_core *c, const char *name) { int r; assert(c && name); - e = pa_hashset_get(c->namereg, name); + e = pa_hashmap_get(c->namereg, name); assert(e); - r = pa_hashset_remove(c->namereg, name); + r = pa_hashmap_remove(c->namereg, name); assert(r >= 0); free(e->name); @@ -93,7 +93,7 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t void *d = NULL; assert(c && name); - if ((e = pa_hashset_get(c->namereg, name))) + if ((e = pa_hashmap_get(c->namereg, name))) if (e->type == e->type) return e->data; diff --git a/src/todo b/src/todo index bf01a4c4b..deab2163e 100644 --- a/src/todo +++ b/src/todo @@ -1,7 +1,9 @@ - native library/protocol: more functions (esp. latency) -- config parser/cmdline +- make all modules use modargs.c +- cmdline +- daemonizing - move more stuff from module-oss[-dma] to liboss-util @@ -13,6 +15,8 @@ - svn-id and license in every file - documentation +- eliminate global variables + -- post 0.1 - future cancellation - client-ui From 216591d95e00a0cb771088dad9a752efead55e10 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Jul 2004 22:20:08 +0000 Subject: [PATCH 0061/1514] make the protocol plugins make use of modargs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@62 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/authkey.c | 11 ++++ src/authkey.h | 1 + src/modargs.c | 37 ++++++++++++++ src/modargs.h | 3 ++ src/module-cli.c | 7 ++- src/module-protocol-stub.c | 100 ++++++++++++++++++++++++------------- src/protocol-cli.c | 2 +- src/protocol-cli.h | 3 +- src/protocol-esound.c | 21 ++++++-- src/protocol-esound.h | 3 +- src/protocol-native.c | 14 ++++-- src/protocol-native.h | 3 +- src/protocol-simple.c | 94 ++++++++++++++++++++++++++-------- src/protocol-simple.h | 9 +--- src/socket-util.c | 39 +++++++++++++++ src/socket-util.h | 3 ++ src/todo | 4 +- 17 files changed, 275 insertions(+), 79 deletions(-) diff --git a/src/authkey.c b/src/authkey.c index cd284fb51..7bf451658 100644 --- a/src/authkey.c +++ b/src/authkey.c @@ -106,6 +106,8 @@ int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { char *home; char path[PATH_MAX]; + assert(fn && data && length); + if (!(home = getenv("HOME"))) return -2; @@ -113,3 +115,12 @@ int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { return pa_authkey_load(path, data, length); } + +int pa_authkey_load_auto(const char *fn, void *data, size_t length) { + assert(fn && data && length); + + if (*fn == '/') + return pa_authkey_load(fn, data, length); + else + return pa_authkey_load_from_home(fn, data, length); +} diff --git a/src/authkey.h b/src/authkey.h index cc0fcb28b..a0d695a9e 100644 --- a/src/authkey.h +++ b/src/authkey.h @@ -5,5 +5,6 @@ int pa_authkey_load(const char *path, void *data, size_t len); int pa_authkey_load_from_home(const char *fn, void *data, size_t length); +int pa_authkey_load_auto(const char *fn, void *data, size_t length); #endif diff --git a/src/modargs.c b/src/modargs.c index a7b48808e..a716a80e1 100644 --- a/src/modargs.c +++ b/src/modargs.c @@ -7,6 +7,9 @@ #include "modargs.h" #include "idxset.h" #include "sample-util.h" +#include "namereg.h" +#include "sink.h" +#include "source.h" struct pa_modargs; @@ -220,3 +223,37 @@ int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss return 0; } + +int pa_modargs_get_source_index(struct pa_modargs *ma, struct pa_core *c, uint32_t *index) { + const char *t; + assert(ma && index); + + if (!(t = pa_modargs_get_value(ma, "source", NULL))) + *index = PA_IDXSET_INVALID; + else { + struct pa_source *source; + if (!(source = pa_namereg_get(c, t, PA_NAMEREG_SOURCE))) + return -1; + + *index = source->index; + } + + return 0; +} + +int pa_modargs_get_sink_index(struct pa_modargs *ma, struct pa_core *c, uint32_t *index) { + const char *t; + assert(ma && index); + + if (!(t = pa_modargs_get_value(ma, "sink", NULL))) + *index = PA_IDXSET_INVALID; + else { + struct pa_sink *sink; + if (!(sink = pa_namereg_get(c, t, PA_NAMEREG_SINK))) + return -1; + + *index = sink->index; + } + + return 0; +} diff --git a/src/modargs.h b/src/modargs.h index 437dd4321..07792ef3c 100644 --- a/src/modargs.h +++ b/src/modargs.h @@ -3,6 +3,7 @@ #include #include "sample.h" +#include "core.h" struct pa_modargs; @@ -14,5 +15,7 @@ int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *v int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *ss); +int pa_modargs_get_source_index(struct pa_modargs *ma, struct pa_core *c, uint32_t *index); +int pa_modargs_get_sink_index(struct pa_modargs *ma, struct pa_core *c, uint32_t *index); #endif diff --git a/src/module-cli.c b/src/module-cli.c index 440c4ba5a..135d35881 100644 --- a/src/module-cli.c +++ b/src/module-cli.c @@ -18,8 +18,13 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { struct pa_iochannel *io; assert(c && m); + if (m->argument) { + fprintf(stderr, __FILE__": module doesn't accept arguments.\n"); + return -1; + } + if (pa_stdio_acquire() < 0) { - fprintf(stderr, "STDIN/STDUSE already used\n"); + fprintf(stderr, __FILE__": STDIN/STDUSE already in use.\n"); return -1; } diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 0547f7e60..4f82d4e02 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -9,29 +9,31 @@ #include "socket-server.h" #include "socket-util.h" #include "util.h" +#include "modargs.h" #ifdef USE_PROTOCOL_SIMPLE #include "protocol-simple.h" + #define protocol_new pa_protocol_simple_new #define protocol_free pa_protocol_simple_free #define IPV4_PORT 4711 - #define UNIX_SOCKET_DIR "/tmp/polypaudio" #define UNIX_SOCKET "/tmp/polypaudio/simple" + #define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record", #else #ifdef USE_PROTOCOL_CLI #include "protocol-cli.h" #define protocol_new pa_protocol_cli_new #define protocol_free pa_protocol_cli_free #define IPV4_PORT 4712 - #define UNIX_SOCKET_DIR "/tmp/polypaudio" #define UNIX_SOCKET "/tmp/polypaudio/cli" + #define MODULE_ARGUMENTS #else #ifdef USE_PROTOCOL_NATIVE #include "protocol-native.h" #define protocol_new pa_protocol_native_new #define protocol_free pa_protocol_native_free #define IPV4_PORT 4713 - #define UNIX_SOCKET_DIR "/tmp/polypaudio" #define UNIX_SOCKET "/tmp/polypaudio/native" + #define MODULE_ARGUMENTS "public", "cookie", #else #ifdef USE_PROTOCOL_ESOUND #include "protocol-esound.h" @@ -39,8 +41,8 @@ #define protocol_new pa_protocol_esound_new #define protocol_free pa_protocol_esound_free #define IPV4_PORT ESD_DEFAULT_PORT - #define UNIX_SOCKET_DIR ESD_UNIX_SOCKET_DIR #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME + #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", #else #error "Broken build system" #endif @@ -48,43 +50,75 @@ #endif #endif -int pa_module_init(struct pa_core *c, struct pa_module*m) { - struct pa_socket_server *s; - assert(c && m); - +static const char* const valid_modargs[] = { + MODULE_ARGUMENTS #ifdef USE_TCP_SOCKETS - if (!(s = pa_socket_server_new_ipv4(c->mainloop, INADDR_ANY, IPV4_PORT))) - return -1; + "port", + "loopback", #else - if (pa_make_secure_dir(UNIX_SOCKET_DIR) < 0) { - fprintf(stderr, "Failed to create secure socket directory.\n"); - return -1; + "socket", +#endif + NULL +}; + +struct pa_socket_server *create_socket_server(struct pa_core *c, struct pa_modargs *ma) { + struct pa_socket_server *s; +#ifdef USE_TCP_SOCKETS + uint32_t loopback = 0, port = IPV4_PORT; + + if (pa_modargs_get_value_u32(ma, "loopback", &loopback) < 0) { + fprintf(stderr, "loopback= expects a numerical argument.\n"); + return NULL; } - { - int r; - if ((r = pa_unix_socket_remove_stale(UNIX_SOCKET)) < 0) { - fprintf(stderr, "Failed to remove stale UNIX socket '%s': %s\n", UNIX_SOCKET, strerror(errno)); - return -1; - } - - if (r) - fprintf(stderr, "Removed stale UNIX socket '%s'.", UNIX_SOCKET); + if (pa_modargs_get_value_u32(ma, "port", &port) < 0) { + fprintf(stderr, "port= expects a numerical argument.\n"); + return NULL; } - if (!(s = pa_socket_server_new_unix(c->mainloop, UNIX_SOCKET))) { - rmdir(UNIX_SOCKET_DIR); + if (!(s = pa_socket_server_new_ipv4(c->mainloop, loopback ? INADDR_LOOPBACK : INADDR_ANY, port))) + return NULL; +#else + int r; + const char *p; + + p = pa_modargs_get_value(ma, "socket", UNIX_SOCKET); + assert(p); + + if (pa_unix_socket_make_secure_dir(p) < 0) { + fprintf(stderr, "Failed to create secure socket directory.\n"); + return NULL; + } + + if ((r = pa_unix_socket_remove_stale(p)) < 0) { + fprintf(stderr, "Failed to remove stale UNIX socket '%s': %s\n", p, strerror(errno)); + return NULL; + } + + if (r) + fprintf(stderr, "Removed stale UNIX socket '%s'.", p); + + if (!(s = pa_socket_server_new_unix(c->mainloop, p))) + return NULL; + +#endif + return s; +} + +int pa_module_init(struct pa_core *c, struct pa_module*m) { + struct pa_socket_server *s; + struct pa_modargs *ma; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + fprintf(stderr, "Failed to parse module arguments\n"); return -1; } -#endif -#ifdef USE_PROTOCOL_SIMPLE - m->userdata = pa_protocol_simple_new(c, s, m, PA_PROTOCOL_SIMPLE_PLAYBACK); -#else - m->userdata = protocol_new(c, s, m); -#endif + if (!(s = create_socket_server(c, ma))) + return -1; - if (!m->userdata) { + if (!(m->userdata = protocol_new(c, s, m, ma))) { pa_socket_server_free(s); return -1; } @@ -96,8 +130,4 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { assert(c && m); protocol_free(m->userdata); - -#ifndef USE_TCP_SOCKETS - rmdir(UNIX_SOCKET_DIR); -#endif } diff --git a/src/protocol-cli.c b/src/protocol-cli.c index 55b4a8a06..0e7383210 100644 --- a/src/protocol-cli.c +++ b/src/protocol-cli.c @@ -30,7 +30,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo pa_idxset_put(p->connections, c, NULL); } -struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m) { +struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { struct pa_protocol_cli* p; assert(core && server); diff --git a/src/protocol-cli.h b/src/protocol-cli.h index c3bb8b4f5..f970bb8dc 100644 --- a/src/protocol-cli.h +++ b/src/protocol-cli.h @@ -4,10 +4,11 @@ #include "core.h" #include "socket-server.h" #include "module.h" +#include "modargs.h" struct pa_protocol_cli; -struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m); +struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); void pa_protocol_cli_free(struct pa_protocol_cli *n); #endif diff --git a/src/protocol-esound.c b/src/protocol-esound.c index 955ab93cc..cba724381 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -17,7 +17,7 @@ #include "authkey.h" -#define COOKIE_FILE ".esd_auth" +#define DEFAULT_COOKIE_FILE ".esd_auth" #define PLAYBACK_BUFFER_SECONDS (.5) #define PLAYBACK_BUFFER_FRAGMENTS (10) @@ -774,14 +774,24 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo /*** entry points ***/ -struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m) { +struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { + uint32_t source_index, sink_index; struct pa_protocol_esound *p; - assert(core && server); + assert(core && server && ma); + if (pa_modargs_get_source_index(ma, core, &source_index) < 0) { + fprintf(stderr, __FILE__": source does not exist.\n"); + return NULL; + } + + if (pa_modargs_get_sink_index(ma, core, &sink_index) < 0) { + fprintf(stderr, __FILE__": sink does not exist.\n"); + return NULL; + } p = malloc(sizeof(struct pa_protocol_esound)); assert(p); - if (pa_authkey_load_from_home(COOKIE_FILE, p->esd_key, sizeof(p->esd_key)) < 0) { + if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", DEFAULT_COOKIE_FILE), p->esd_key, sizeof(p->esd_key)) < 0) { free(p); return NULL; } @@ -793,7 +803,8 @@ struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa p->core = core; p->connections = pa_idxset_new(NULL, NULL); assert(p->connections); - p->sink_index = p->source_index = PA_IDXSET_INVALID; + p->sink_index = sink_index; + p->source_index = source_index; p->n_player = 0; return p; diff --git a/src/protocol-esound.h b/src/protocol-esound.h index 6071699d3..8653949da 100644 --- a/src/protocol-esound.h +++ b/src/protocol-esound.h @@ -4,10 +4,11 @@ #include "core.h" #include "socket-server.h" #include "module.h" +#include "modargs.h" struct pa_protocol_esound; -struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m); +struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); void pa_protocol_esound_free(struct pa_protocol_esound *p); #endif diff --git a/src/protocol-native.c b/src/protocol-native.c index d6a5f9b2b..abd170263 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -736,20 +736,26 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo /*** module entry points ***/ -struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m) { +struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { struct pa_protocol_native *p; - assert(core && server); + uint32_t public; + assert(core && server && ma); + if (pa_modargs_get_value_u32(ma, "public", &public) < 0) { + fprintf(stderr, __FILE__": public= expects numeric argument.\n"); + return NULL; + } + p = malloc(sizeof(struct pa_protocol_native)); assert(p); - if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, p->auth_cookie, sizeof(p->auth_cookie)) < 0) { + if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), p->auth_cookie, sizeof(p->auth_cookie)) < 0) { free(p); return NULL; } p->module = m; - p->public = 1; + p->public = public; p->server = server; p->core = core; p->connections = pa_idxset_new(NULL, NULL); diff --git a/src/protocol-native.h b/src/protocol-native.h index 811b4e4a4..89cb1634c 100644 --- a/src/protocol-native.h +++ b/src/protocol-native.h @@ -4,10 +4,11 @@ #include "core.h" #include "socket-server.h" #include "module.h" +#include "modargs.h" struct pa_protocol_native; -struct pa_protocol_native* pa_protocol_native_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m); +struct pa_protocol_native* pa_protocol_native_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); void pa_protocol_native_free(struct pa_protocol_native *n); #endif diff --git a/src/protocol-simple.c b/src/protocol-simple.c index b57f324ab..89207133c 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -10,6 +10,7 @@ #include "protocol-simple.h" #include "client.h" #include "sample-util.h" +#include "namereg.h" struct connection { struct pa_protocol_simple *protocol; @@ -31,8 +32,13 @@ struct pa_protocol_simple { struct pa_core *core; struct pa_socket_server*server; struct pa_idxset *connections; - enum pa_protocol_simple_mode mode; + enum { + RECORD = 1, + PLAYBACK = 2, + DUPLEX = 3 + } mode; struct pa_sample_spec sample_spec; + uint32_t sink_index, source_index; }; #define PLAYBACK_BUFFER_SECONDS (.5) @@ -263,14 +269,15 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->client->kill = client_kill_cb; c->client->userdata = c; - if (p->mode & PA_PROTOCOL_SIMPLE_PLAYBACK) { + if (p->mode & PLAYBACK) { struct pa_sink *sink; size_t l; - if (!(sink = pa_sink_get_default(p->core))) { - fprintf(stderr, "Failed to get default sink.\n"); - goto fail; - } + if (!(sink = pa_idxset_get_by_index(p->core->sinks, p->sink_index))) + if (!(sink = pa_sink_get_default(p->core))) { + fprintf(stderr, "Failed to get sink.\n"); + goto fail; + } c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec); if (!c->sink_input) { @@ -293,15 +300,15 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->playback.fragment_size = l/10; } - - if (p->mode & PA_PROTOCOL_SIMPLE_RECORD) { + if (p->mode & RECORD) { struct pa_source *source; size_t l; - if (!(source = pa_source_get_default(p->core))) { - fprintf(stderr, "Failed to get default source.\n"); - goto fail; - } + if (!(source = pa_idxset_get_by_index(p->core->sources, p->source_index))) + if (!(source = pa_source_get_default(p->core))) { + fprintf(stderr, "Failed to get source.\n"); + goto fail; + } c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec); if (!c->source_output) { @@ -334,22 +341,62 @@ fail: connection_free(c); } -struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, enum pa_protocol_simple_mode mode) { - struct pa_protocol_simple* p; - assert(core && server && mode <= PA_PROTOCOL_SIMPLE_DUPLEX && mode > 0); +struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { + struct pa_protocol_simple* p = NULL; + uint32_t enable; + assert(core && server && ma); p = malloc(sizeof(struct pa_protocol_simple)); assert(p); + memset(p, 0, sizeof(struct pa_protocol_simple)); + p->module = m; p->core = core; p->server = server; p->connections = pa_idxset_new(NULL, NULL); - p->mode = mode; - p->sample_spec = PA_DEFAULT_SAMPLE_SPEC; + if (pa_modargs_get_sample_spec(ma, &p->sample_spec) < 0) { + fprintf(stderr, "Failed to parse sample type specification.\n"); + goto fail; + } + + if (pa_modargs_get_source_index(ma, core, &p->source_index) < 0) { + fprintf(stderr, __FILE__": source does not exist.\n"); + goto fail; + } + + if (pa_modargs_get_sink_index(ma, core, &p->sink_index) < 0) { + fprintf(stderr, __FILE__": sink does not exist.\n"); + goto fail; + } + + enable = 0; + if (pa_modargs_get_value_u32(ma, "record", &enable) < 0) { + fprintf(stderr, __FILE__": record= expects a numeric argument.\n"); + goto fail; + } + p->mode = enable ? RECORD : 0; + + enable = 1; + if (pa_modargs_get_value_u32(ma, "playback", &enable) < 0) { + fprintf(stderr, __FILE__": playback= expects a numeric argument.\n"); + goto fail; + } + p->mode |= enable ? PLAYBACK : 0; + + if ((p->mode & (RECORD|PLAYBACK)) == 0) { + fprintf(stderr, __FILE__": neither playback nor recording enabled for protocol.\n"); + goto fail; + } + pa_socket_server_set_callback(p->server, on_connection, p); return p; + +fail: + if (p) + pa_protocol_simple_free(p); + return NULL; } @@ -357,12 +404,15 @@ void pa_protocol_simple_free(struct pa_protocol_simple *p) { struct connection *c; assert(p); - while((c = pa_idxset_first(p->connections, NULL))) - connection_free(c); + if (p->connections) { + while((c = pa_idxset_first(p->connections, NULL))) + connection_free(c); + + pa_idxset_free(p->connections, NULL, NULL); + } - pa_idxset_free(p->connections, NULL, NULL); - - pa_socket_server_free(p->server); + if (p->server) + pa_socket_server_free(p->server); free(p); } diff --git a/src/protocol-simple.h b/src/protocol-simple.h index 6b2a2cd13..62682915a 100644 --- a/src/protocol-simple.h +++ b/src/protocol-simple.h @@ -4,16 +4,11 @@ #include "socket-server.h" #include "module.h" #include "core.h" +#include "modargs.h" struct pa_protocol_simple; -enum pa_protocol_simple_mode { - PA_PROTOCOL_SIMPLE_RECORD = 1, - PA_PROTOCOL_SIMPLE_PLAYBACK = 2, - PA_PROTOCOL_SIMPLE_DUPLEX = 3 -}; - -struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, enum pa_protocol_simple_mode mode); +struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); void pa_protocol_simple_free(struct pa_protocol_simple *n); #endif diff --git a/src/socket-util.c b/src/socket-util.c index f9451af8d..f4648da5a 100644 --- a/src/socket-util.c +++ b/src/socket-util.c @@ -14,6 +14,7 @@ #include #include "socket-util.h" +#include "util.h" void pa_socket_peer_to_string(int fd, char *c, size_t l) { struct stat st; @@ -150,3 +151,41 @@ int pa_unix_socket_remove_stale(const char *fn) { return 0; } + +int pa_unix_socket_make_secure_dir(const char *fn) { + int ret = -1; + char *slash, *dir = strdup(fn); + assert(dir); + + if (!(slash = strrchr(dir, '/'))) + goto finish; + *slash = 0; + + if (pa_make_secure_dir(dir) < 0) + goto finish; + + ret = 0; + +finish: + free(dir); + return ret; +} + +int pa_unix_socket_remove_secure_dir(const char *fn) { + int ret = -1; + char *slash, *dir = strdup(fn); + assert(dir); + + if (!(slash = strrchr(dir, '/'))) + goto finish; + *slash = 0; + + if (rmdir(dir) < 0) + goto finish; + + ret = 0; + +finish: + free(dir); + return ret; +} diff --git a/src/socket-util.h b/src/socket-util.h index 1c4dbe358..0133bfc3b 100644 --- a/src/socket-util.h +++ b/src/socket-util.h @@ -14,4 +14,7 @@ int pa_socket_set_rcvbuf(int fd, size_t l); int pa_unix_socket_is_stale(const char *fn); int pa_unix_socket_remove_stale(const char *fn); +int pa_unix_socket_make_secure_dir(const char *fn); +int pa_unix_socket_remove_secure_dir(const char *fn); + #endif diff --git a/src/todo b/src/todo index deab2163e..b131ac737 100644 --- a/src/todo +++ b/src/todo @@ -1,7 +1,9 @@ - native library/protocol: more functions (esp. latency) -- make all modules use modargs.c +- make all modules use modargs.c: + module-oss.c + module-oss-mmap.c - cmdline - daemonizing From d4e0d51c157dea740d35089f077451b6ec7b11a5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Jul 2004 23:21:32 +0000 Subject: [PATCH 0062/1514] make module-oss-* use modargs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@63 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/main.c | 2 +- src/module-oss-mmap.c | 68 +++++++++++++++++++++--------------------- src/module-oss.c | 62 ++++++++++++++++++++++---------------- src/module-pipe-sink.c | 4 +-- src/oss-util.c | 54 +++++++++++++++++++++++++++++++++ src/oss-util.h | 1 + src/todo | 14 ++++----- 7 files changed, 135 insertions(+), 70 deletions(-) diff --git a/src/main.c b/src/main.c index e2d86b488..8ba554c80 100644 --- a/src/main.c +++ b/src/main.c @@ -42,7 +42,7 @@ int main(int argc, char *argv[]) { c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); - pa_module_load(c, "module-oss-mmap", "/dev/dsp"); + pa_module_load(c, "module-oss-mmap", "device=/dev/dsp playback=1 record=1"); /* pa_module_load(c, "module-oss-mmap", "/dev/dsp1");*/ /* pa_module_load(c, "module-pipe-sink", NULL);*/ pa_module_load(c, "module-simple-protocol-tcp", NULL); diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index 772abf998..a9e130866 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -18,6 +18,7 @@ #include "oss-util.h" #include "sample-util.h" #include "util.h" +#include "modargs.h" struct userdata { struct pa_sink *sink; @@ -38,8 +39,18 @@ struct userdata { unsigned out_current, in_current; }; -void module_done(struct pa_core *c, struct pa_module*m); +static const char* const valid_modargs[] = { + "sink_name", + "source_name", + "device", + "record", + "playback", + NULL +}; +#define DEFAULT_SINK_NAME "oss_output" +#define DEFAULT_SOURCE_NAME "oss_input" +#define DEFAULT_DEVICE "/dev/dsp" static void out_fill_memblocks(struct userdata *u, unsigned n) { assert(u && u->out_memblocks); @@ -163,10 +174,12 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { int pa_module_init(struct pa_core *c, struct pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; - char *p; + const char *p; int frag_size; - int mode, caps, caps_read = 0; + int mode, caps; int enable_bits = 0, zero = 0; + int playback = 1, record = 1; + struct pa_modargs *ma = NULL; assert(c && m); m->userdata = u = malloc(sizeof(struct userdata)); @@ -174,39 +187,26 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { memset(u, 0, sizeof(struct userdata)); u->fd = -1; u->core = c; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + fprintf(stderr, __FILE__": failed to parse module arguments.\n"); + goto fail; + } - p = m->argument ? m->argument : "/dev/dsp"; - if ((u->fd = open(p, (mode = O_RDWR)|O_NDELAY)) >= 0) { - ioctl(u->fd, SNDCTL_DSP_SETDUPLEX, 0); - - if (ioctl(u->fd, SNDCTL_DSP_GETCAPS, &caps) < 0) { - fprintf(stderr, "SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); - goto fail; - } - - if (!(caps & DSP_CAP_DUPLEX)) { - close(u->fd); - u->fd = -1; - } else - caps_read = 1; + if (pa_modargs_get_value_u32(ma, "record", &record) < 0 || pa_modargs_get_value_u32(ma, "playback", &playback) < 0) { + fprintf(stderr, __FILE__": record= and playback= expect numeric arguments.\n"); + goto fail; } - if (u->fd < 0) { - if ((u->fd = open(p, (mode = O_WRONLY)|O_NDELAY)) < 0) { - if ((u->fd = open(p, (mode = O_RDONLY)|O_NDELAY)) < 0) { - fprintf(stderr, "open('%s'): %s\n", p, strerror(errno)); - goto fail; - } - } + mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); + if (mode == 0) { + fprintf(stderr, __FILE__": neither playback nor record enabled for device.\n"); + goto fail; } - if (!caps_read) { - if (ioctl(u->fd, SNDCTL_DSP_GETCAPS, &caps) < 0) { - fprintf(stderr, "SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); - goto fail; - } - } - + if ((u->fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0) + goto fail; + if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_REALTIME) || !(caps & DSP_CAP_TRIGGER)) { fprintf(stderr, "OSS device not mmap capable.\n"); goto fail; @@ -242,7 +242,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { } } else { - u->source = pa_source_new(c, "oss_input", 0, &u->sample_spec); + u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec); assert(u->source); u->source->userdata = u; pa_source_set_owner(u->source, m); @@ -276,7 +276,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { } else { pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); - u->sink = pa_sink_new(c, "oss_output", 0, &u->sample_spec); + u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; @@ -309,7 +309,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { return 0; fail: - module_done(c, m); + pa_module_done(c, m); return -1; } diff --git a/src/module-oss.c b/src/module-oss.c index b06775841..31ca2dba7 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -17,6 +17,7 @@ #include "oss-util.h" #include "sample-util.h" #include "util.h" +#include "modargs.h" struct userdata { struct pa_sink *sink; @@ -31,6 +32,19 @@ struct userdata { int fd; }; +static const char* const valid_modargs[] = { + "sink_name", + "source_name", + "device", + "record", + "playback", + NULL +}; + +#define DEFAULT_SINK_NAME "oss_output" +#define DEFAULT_SOURCE_NAME "oss_input" +#define DEFAULT_DEVICE "/dev/dsp" + static void do_write(struct userdata *u) { struct pa_memchunk *memchunk; ssize_t r; @@ -115,39 +129,34 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { int pa_module_init(struct pa_core *c, struct pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; - char *p; + const char *p; int fd = -1; int frag_size, in_frag_size, out_frag_size; int mode; + uint32_t record = 1, playback = 1; struct pa_sample_spec ss; + struct pa_modargs *ma = NULL; assert(c && m); - p = m->argument ? m->argument : "/dev/dsp"; - if ((fd = open(p, (mode = O_RDWR)|O_NDELAY)) >= 0) { - int caps; - - ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); - - if (ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) < 0) { - fprintf(stderr, "SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); - goto fail; - } - - if (!(caps & DSP_CAP_DUPLEX)) { - close(fd); - fd = -1; - } + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + fprintf(stderr, __FILE__": failed to parse module arguments.\n"); + goto fail; + } + + if (pa_modargs_get_value_u32(ma, "record", &record) < 0 || pa_modargs_get_value_u32(ma, "playback", &playback) < 0) { + fprintf(stderr, __FILE__": record= and playback= expect numeric argument.\n"); + goto fail; } - if (fd < 0) { - if ((fd = open(p, (mode = O_WRONLY)|O_NDELAY)) < 0) { - if ((fd = open(p, (mode = O_RDONLY)|O_NDELAY)) < 0) { - fprintf(stderr, "open('%s'): %s\n", p, strerror(errno)); - goto fail; - } - } + mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); + if (mode == 0) { + fprintf(stderr, __FILE__": neither playback nor record enabled for device.\n"); + goto fail; } + if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, NULL)) < 0) + goto fail; + fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); frag_size = ((int) 12 << 16) | 10; /* nfrags = 12; frag_size = 2^10 */ @@ -182,7 +191,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->core = c; if (mode != O_WRONLY) { - u->source = pa_source_new(c, "oss_input", 0, &ss); + u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); assert(u->source); u->source->userdata = u; pa_source_set_owner(u->source, m); @@ -191,7 +200,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->source = NULL; if (mode != O_RDONLY) { - u->sink = pa_sink_new(c, "oss_output", 0, &ss); + u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; @@ -226,6 +235,9 @@ fail: if (fd >= 0) close(fd); + if (ma) + pa_modargs_free(ma); + return -1; } diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index e5e97b517..29767ea80 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -34,7 +34,7 @@ static const char* const valid_modargs[] = { "rate", "channels", "format", - "sink", + "sink_name", NULL }; @@ -131,7 +131,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(u->filename); u->core = c; - if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink", DEFAULT_SINK_NAME), 0, &ss))) { + if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { fprintf(stderr, __FILE__": failed to create sink.\n"); goto fail; } diff --git a/src/oss-util.c b/src/oss-util.c index 9c4f55caf..f1e07017e 100644 --- a/src/oss-util.c +++ b/src/oss-util.c @@ -4,9 +4,63 @@ #include #include #include +#include +#include +#include +#include #include "oss-util.h" +int pa_oss_open(const char *device, int *mode, int* pcaps) { + int fd = -1; + assert(device && mode && (*mode == O_RDWR || *mode == O_RDONLY || *mode == O_WRONLY)); + + if (*mode == O_RDWR) { + if ((fd = open(device, O_RDWR|O_NDELAY)) >= 0) { + int dcaps, *tcaps; + ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); + + tcaps = pcaps ? pcaps : &dcaps; + + if (ioctl(fd, SNDCTL_DSP_GETCAPS, tcaps) < 0) { + fprintf(stderr, __FILE__": SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); + goto fail; + } + + if (*tcaps & DSP_CAP_DUPLEX) + return fd; + + close(fd); + } + + if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) { + if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY)) < 0) { + fprintf(stderr, __FILE__": open('%s'): %s\n", device, strerror(errno)); + goto fail; + } + } + } else { + if ((fd = open(device, *mode|O_NDELAY)) < 0) { + fprintf(stderr, __FILE__": open('%s'): %s\n", device, strerror(errno)); + goto fail; + } + } + + if (pcaps) { + if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { + fprintf(stderr, "SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); + goto fail; + } + } + + return fd; + +fail: + if (fd >= 0) + close(fd); + return fd; +} + int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { int format, channels, speed; diff --git a/src/oss-util.h b/src/oss-util.h index cf12e8e61..030afba46 100644 --- a/src/oss-util.h +++ b/src/oss-util.h @@ -3,6 +3,7 @@ #include "sample.h" +int pa_oss_open(const char *device, int *mode, int* pcaps); int pa_oss_auto_format(int fd, struct pa_sample_spec *ss); #endif diff --git a/src/todo b/src/todo index b131ac737..febdca7cc 100644 --- a/src/todo +++ b/src/todo @@ -1,13 +1,7 @@ - native library/protocol: more functions (esp. latency) -- make all modules use modargs.c: - module-oss.c - module-oss-mmap.c -- cmdline -- daemonizing - -- move more stuff from module-oss[-dma] to liboss-util +- cmdline & daemonizing - prefix modules/libraries with pa_ @@ -17,7 +11,10 @@ - svn-id and license in every file - documentation -- eliminate global variables +- eliminate global variables: + pa_default_sample_spec + pa_memblock_count + pa_memblock_total -- post 0.1 - future cancellation @@ -27,6 +24,7 @@ - slp/rendezvous - doxygen - make mcalign merge chunks +- modinfo drivers: - libao From b69178b067d4151de08bdcdaa9922d2838134c3c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 12 Jul 2004 21:28:11 +0000 Subject: [PATCH 0063/1514] add preliminary command line parsing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@64 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 3 +- src/cmdline.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cmdline.h | 19 +++++++++ src/main.c | 15 +++++++ 4 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/cmdline.c create mode 100644 src/cmdline.h diff --git a/src/Makefile.am b/src/Makefile.am index e8704f786..bdd621ab4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -84,7 +84,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ sconv-s16le.c sconv-s16le.h \ sconv-s16be.c sconv-s16be.h \ sioman.c sioman.h \ - modargs.c modargs.h + modargs.c modargs.h \ + cmdline.c cmdline.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) diff --git a/src/cmdline.c b/src/cmdline.c new file mode 100644 index 000000000..36fe3e613 --- /dev/null +++ b/src/cmdline.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include + +#include "cmdline.h" +#include "util.h" + +void pa_cmdline_help(const char *argv0) { + const char *e; + + if ((e = strrchr(argv0, '/'))) + e++; + else + e = argv0; + + printf("%s [options]\n" + " -L MODULE Load the specified plugin module with the specified argument\n" + " -F FILE A shortcut for '-L module-cli file=FILE', i.e. run the specified script after startup\n" + " -C A shortcut for '-L module-cli', i.e. open a command line on the running TTY\n" + " -D Daemonize after loading the modules\n" + " -h Show this help\n", e); +} + +static void add_module(struct pa_cmdline *cmdline, char *name, char *arguments) { + struct pa_cmdline_module *m; + assert(cmdline && name); + + m = malloc(sizeof(struct pa_cmdline_module)); + assert(m); + m->name = name; + m->arguments = name; + m->next = NULL; + + if (cmdline->last_module) + cmdline->last_module->next = m; + else { + assert(!cmdline->first_module); + cmdline->first_module = m; + } + cmdline->last_module = m; +} + +struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { + char c; + struct pa_cmdline *cmdline = NULL; + assert(argc && argv); + + cmdline = malloc(sizeof(struct pa_cmdline)); + assert(cmdline); + cmdline->daemonize = cmdline->help = 0; + cmdline->first_module = cmdline->last_module = NULL; + + while ((c = getopt(argc, argv, "L:F:CDh")) != -1) { + switch (c) { + case 'L': { + char *space; + if ((space = strchr(optarg, ' '))) + add_module(cmdline, strndup(optarg, space-optarg), space+1); + else + add_module(cmdline, strdup(optarg), NULL); + break; + } + case 'F': + add_module(cmdline, strdup("module-cli"), pa_sprintf_malloc("file='%s'", optarg)); + break; + case 'C': + add_module(cmdline, strdup("module-cli"), NULL); + break; + case 'D': + cmdline->daemonize = 1; + break; + case 'h': + cmdline->help = 1; + break; + default: + goto fail; + } + } + + return cmdline; + +fail: + if (cmdline) + pa_cmdline_free(cmdline); + return NULL; +} + +void pa_cmdline_free(struct pa_cmdline *cmd) { + struct pa_cmdline_module *m; + assert(cmd); + + while ((m = cmd->first_module)) { + cmd->first_module = m->next; + free(m->name); + free(m->arguments); + free(m); + } + + free(cmd); +} diff --git a/src/cmdline.h b/src/cmdline.h new file mode 100644 index 000000000..9a647706b --- /dev/null +++ b/src/cmdline.h @@ -0,0 +1,19 @@ +#ifndef foocmdlinehfoo +#define foocmdlinehfoo + +struct pa_cmdline_module { + char *name, *arguments; + struct pa_cmdline_module *next; +}; + +struct pa_cmdline { + int daemonize, help; + struct pa_cmdline_module *first_module, *last_module; +}; + +struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []); +void pa_cmdline_free(struct pa_cmdline *cmd); + +void pa_cmdline_help(const char *argv0); + +#endif diff --git a/src/main.c b/src/main.c index 8ba554c80..e2c8eb63f 100644 --- a/src/main.c +++ b/src/main.c @@ -9,6 +9,7 @@ #include "mainloop.h" #include "module.h" #include "mainloop-signal.h" +#include "cmdline.h" static struct pa_mainloop *mainloop; @@ -26,8 +27,20 @@ static void aux_signal_callback(void *id, int sig, void *userdata) { int main(int argc, char *argv[]) { struct pa_core *c; + struct pa_cmdline *cmdline = NULL; int r, retval = 0; + if (!(cmdline = pa_cmdline_parse(argc, argv))) { + fprintf(stderr, "Failed to parse command line.\n"); + return 1; + } + + if (cmdline->help) { + pa_cmdline_help(argv[0]); + pa_cmdline_free(cmdline); + return 0; + } + r = lt_dlinit(); assert(r == 0); @@ -67,6 +80,8 @@ int main(int argc, char *argv[]) { pa_signal_done(); pa_mainloop_free(mainloop); + + lt_dlexit(); return retval; From e61e9244aa082c07df4f21213cd3d223033fd03f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 14 Jul 2004 21:52:41 +0000 Subject: [PATCH 0064/1514] complete implementation of the command line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@65 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 25 +- src/cli-command.c | 531 ++++++++++++++++++++++++++++++++++++++++++ src/cli-command.h | 11 + src/cli.c | 452 +++-------------------------------- src/cmdline.c | 68 +++--- src/cmdline.h | 8 +- src/main.c | 45 ++-- src/module-oss-mmap.c | 2 +- src/module-oss.c | 2 +- src/polypaudio.run | 13 ++ src/strbuf.c | 14 +- src/strbuf.h | 1 + 12 files changed, 663 insertions(+), 509 deletions(-) create mode 100644 src/cli-command.c create mode 100644 src/cli-command.h create mode 100755 src/polypaudio.run diff --git a/src/Makefile.am b/src/Makefile.am index bdd621ab4..c973af52f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,14 +28,11 @@ pkglib_LTLIBRARIES=libiochannel.la \ liboss-util.la \ libioline.la \ libcli.la \ - libtokenizer.la \ - libdynarray.la \ libprotocol-cli.la \ libtagstruct.la \ libpstream-util.la \ libpdispatch.la \ libauthkey.la \ - libclitext.la \ libsocket-util.la \ libprotocol-simple.la \ libprotocol-esound.la \ @@ -85,7 +82,11 @@ polypaudio_SOURCES = idxset.c idxset.h \ sconv-s16be.c sconv-s16be.h \ sioman.c sioman.h \ modargs.c modargs.h \ - cmdline.c cmdline.h + cmdline.c cmdline.h \ + cli-command.c cli-command.h \ + clitext.c clitext.h \ + tokenizer.c tokenizer.h \ + dynarray.c dynarray.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) @@ -118,7 +119,7 @@ libpdispatch_la_LIBADD = libtagstruct.la libiochannel_la_SOURCES = iochannel.c iochannel.h libiochannel_la_LDFLAGS = -avoid-version -libiochannel_la_LIBDADD = libsocket-util.la +libiochannel_la_LIBADD = libsocket-util.la libpacket_la_SOURCES = packet.c packet.h libpacket_la_LDFLAGS = -avoid-version @@ -132,14 +133,7 @@ libioline_la_LIBADD = libiochannel.la libcli_la_SOURCES = cli.c cli.h libcli_la_LDFLAGS = -avoid-version -libcli_la_LIBADD = libiochannel.la libioline.la libclitext.la libtokenizer.la - -libdynarray_la_SOURCES = dynarray.c dynarray.h -libdynarray_la_LDFLAGS = -avoid-version - -libtokenizer_la_SOURCES = tokenizer.c tokenizer.h -libtokenizer_la_LDFLAGS = -avoid-version -libtokenizer_la_LIBADD = libdynarray.la +libcli_la_LIBADD = libiochannel.la libioline.la libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h libprotocol_cli_la_LDFLAGS = -avoid-version @@ -159,9 +153,6 @@ libprotocol_esound_la_LIBADD = libsocket-server.la libiochannel.la libauthkey.la libauthkey_la_SOURCES = authkey.c authkey.h libauthkey_la_LDFLAGS = -avoid-version -libclitext_la_SOURCES = clitext.c clitext.h -libclitext_la_LDFLAGS = -avoid-version - libsocket_util_la_SOURCES = socket-util.c socket-util.h libsocket_util_la_LDFLAGS = -avoid-version @@ -219,7 +210,7 @@ module_oss_mmap_la_LIBADD = liboss-util.la module_cli_la_SOURCES = module-cli.c module_cli_la_LDFLAGS = -module -avoid-version -module_cli_la_LIBADD = libcli.la libiochannel.la libtokenizer.la +module_cli_la_LIBADD = libcli.la libiochannel.la libpolyp_la_SOURCES = polyp.c polyp.h \ polypdef.h \ diff --git a/src/cli-command.c b/src/cli-command.c new file mode 100644 index 000000000..06e0eb300 --- /dev/null +++ b/src/cli-command.c @@ -0,0 +1,531 @@ +#include +#include +#include +#include +#include + +#include "cli-command.h" +#include "module.h" +#include "sink.h" +#include "source.h" +#include "client.h" +#include "sinkinput.h" +#include "sourceoutput.h" +#include "tokenizer.h" +#include "strbuf.h" +#include "namereg.h" +#include "clitext.h" + +struct command { + const char *name; + int (*proc) (struct pa_core *c, struct pa_tokenizer*t, struct pa_strbuf *buf, int *fail, int *verbose); + const char *help; + unsigned args; +}; + +static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); + +static const struct command commands[] = { + { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, + { "help", pa_cli_command_help, "Show this help", 1 }, + { "modules", pa_cli_command_modules, "List loaded modules", 1 }, + { "sinks", pa_cli_command_sinks, "List loaded sinks", 1 }, + { "sources", pa_cli_command_sources, "List loaded sources", 1 }, + { "clients", pa_cli_command_clients, "List loaded clients", 1 }, + { "sink_inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 }, + { "source_outputs", pa_cli_command_source_outputs, "List source outputs", 1 }, + { "stat", pa_cli_command_stat, "Show memory block statistics", 1 }, + { "info", pa_cli_command_info, "Show comprehensive status", 1 }, + { "ls", pa_cli_command_info, NULL, 1 }, + { "list", pa_cli_command_info, NULL, 1 }, + { "load", pa_cli_command_load, "Load a module (args: name, arguments)", 3}, + { "unload", pa_cli_command_unload, "Unload a module (args: index)", 2}, + { "sink_volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3}, + { "sink_input_volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index|name, volume)", 3}, + { "sink_default", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2}, + { "source_default", pa_cli_command_source_default, "Set the default source (args: index|name)", 2}, + { "kill_client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, + { "kill_sink_input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2}, + { "kill_source_output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2}, + { NULL, NULL, NULL, 0 } +}; + +static const char whitespace[] = " \t\n\r"; +static const char linebreak[] = "\n\r"; + +static uint32_t parse_index(const char *n) { + long index; + char *x; + index = strtol(n, &x, 0); + if (!x || *x != 0 || index < 0) + return (uint32_t) PA_IDXSET_INVALID; + + return (uint32_t) index; +} + +static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + assert(c && c->mainloop && t); + c->mainloop->quit(c->mainloop, 0); + return 0; +} + +static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const struct command*command; + assert(c && t && buf); + + pa_strbuf_puts(buf, "Available commands:\n"); + + for (command = commands; command->name; command++) + if (command->help) + pa_strbuf_printf(buf, " %-20s %s\n", command->name, command->help); + return 0; +} + +static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + char *s; + assert(c && t); + s = pa_module_list_to_string(c); + assert(s); + pa_strbuf_puts(buf, s); + free(s); + return 0; +} + +static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + char *s; + assert(c && t); + s = pa_client_list_to_string(c); + assert(s); + pa_strbuf_puts(buf, s); + free(s); + return 0; +} + +static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + char *s; + assert(c && t); + s = pa_sink_list_to_string(c); + assert(s); + pa_strbuf_puts(buf, s); + free(s); + return 0; +} + +static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + char *s; + assert(c && t); + s = pa_source_list_to_string(c); + assert(s); + pa_strbuf_puts(buf, s); + free(s); + return 0; +} + +static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + char *s; + assert(c && t); + s = pa_sink_input_list_to_string(c); + assert(s); + pa_strbuf_puts(buf, s); + free(s); + return 0; +} + +static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + char *s; + assert(c && t); + s = pa_source_output_list_to_string(c); + assert(s); + pa_strbuf_puts(buf, s); + free(s); + return 0; +} + +static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + assert(c && t); + pa_strbuf_printf(buf, "Memory blocks allocated: %u, total size: %u bytes.\n", pa_memblock_count, pa_memblock_total); + return 0; +} + +static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + assert(c && t); + pa_cli_command_stat(c, t, buf, fail, verbose); + pa_cli_command_modules(c, t, buf, fail, verbose); + pa_cli_command_sinks(c, t, buf, fail, verbose); + pa_cli_command_sources(c, t, buf, fail, verbose); + pa_cli_command_clients(c, t, buf, fail, verbose); + pa_cli_command_sink_inputs(c, t, buf, fail, verbose); + pa_cli_command_source_outputs(c, t, buf, fail, verbose); + return 0; +} + +static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + struct pa_module *m; + const char *name; + char txt[256]; + assert(c && t); + + if (!(name = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n"); + return -1; + } + + if (!(m = pa_module_load(c, name, pa_tokenizer_get(t, 2)))) { + pa_strbuf_puts(buf, "Module load failed.\n"); + return -1; + } + + if (*verbose) + snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index); + pa_strbuf_puts(buf, txt); + return 0; +} + +static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + struct pa_module *m; + uint32_t index; + const char *i; + char *e; + assert(c && t); + + if (!(i = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify the module index.\n"); + return -1; + } + + index = (uint32_t) strtoul(i, &e, 10); + if (*e || !(m = pa_idxset_get_by_index(c->modules, index))) { + pa_strbuf_puts(buf, "Invalid module index.\n"); + return -1; + } + + pa_module_unload_request(c, m); + return 0; +} + +static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *n, *v; + char *x = NULL; + struct pa_sink *sink; + long volume; + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n"); + return -1; + } + + if (!(v = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); + return -1; + } + + volume = strtol(v, &x, 0); + if (!x || *x != 0 || volume < 0) { + pa_strbuf_puts(buf, "Failed to parse volume.\n"); + return -1; + } + + if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) { + pa_strbuf_puts(buf, "No sink found by this name or index.\n"); + return -1; + } + + sink->volume = (uint32_t) volume; + return 0; +} + +static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *n, *v; + struct pa_sink_input *si; + long volume; + uint32_t index; + char *x; + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n"); + return -1; + } + + if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + pa_strbuf_puts(buf, "Failed to parse index.\n"); + return -1; + } + + if (!(v = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); + return -1; + } + + x = NULL; + volume = strtol(v, &x, 0); + if (!x || *x != 0 || volume < 0) { + pa_strbuf_puts(buf, "Failed to parse volume.\n"); + return -1; + } + + if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) index))) { + pa_strbuf_puts(buf, "No sink input found with this index.\n"); + return -1; + } + + si->volume = (uint32_t) volume; + return 0; +} + +static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *n; + struct pa_sink *sink; + assert(c && t); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n"); + return -1; + } + + if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) { + pa_strbuf_puts(buf, "No sink found by this name or index.\n"); + return -1; + } + + c->default_sink_index = sink->index; + return 0; +} + +static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *n; + struct pa_source *source; + assert(c && t); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n"); + return -1; + } + + if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) { + pa_strbuf_puts(buf, "No source found by this name or index.\n"); + return -1; + } + + c->default_source_index = source->index; + return 0; +} + +static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *n; + struct pa_client *client; + uint32_t index; + assert(c && t); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a client by its index.\n"); + return -1; + } + + if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + pa_strbuf_puts(buf, "Failed to parse index.\n"); + return -1; + } + + if (!(client = pa_idxset_get_by_index(c->clients, index))) { + pa_strbuf_puts(buf, "No client found by this index.\n"); + return -1; + } + + pa_client_kill(client); + return 0; +} + +static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *n; + struct pa_sink_input *sink_input; + uint32_t index; + assert(c && t); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n"); + return -1; + } + + if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + pa_strbuf_puts(buf, "Failed to parse index.\n"); + return -1; + } + + if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, index))) { + pa_strbuf_puts(buf, "No sink input found by this index.\n"); + return -1; + } + + pa_sink_input_kill(sink_input); + return 0; +} + +static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *n; + struct pa_source_output *source_output; + uint32_t index; + assert(c && t); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a source output by its index.\n"); + return -1; + } + + if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + pa_strbuf_puts(buf, "Failed to parse index.\n"); + return -1; + } + + if (!(source_output = pa_idxset_get_by_index(c->source_outputs, index))) { + pa_strbuf_puts(buf, "No source output found by this index.\n"); + return -1; + } + + pa_source_output_kill(source_output); + return 0; +} + +int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *cs; + + cs = s+strspn(s, whitespace); + + if (*cs == '#' || !*cs) + return 0; + else if (*cs == '.') { + static const char fail_meta[] = ".fail"; + static const char nofail_meta[] = ".nofail"; + static const char verbose_meta[] = ".verbose"; + static const char noverbose_meta[] = ".noverbose"; + + if (!strcmp(cs, verbose_meta)) + *verbose = 1; + else if (!strcmp(cs, noverbose_meta)) + *verbose = 0; + else if (!strcmp(cs, fail_meta)) + *fail = 1; + else if (!strcmp(cs, nofail_meta)) + *fail = 0; + else { + size_t l; + static const char include_meta[] = ".include"; + l = strcspn(cs, whitespace); + + if (l == sizeof(include_meta)-1 && !strncmp(cs, include_meta, l)) { + const char *filename = cs+l+strspn(cs+l, whitespace); + + if (pa_cli_command_execute_file(c, filename, buf, fail, verbose) < 0) + if (*fail) return -1; + } else { + pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs); + if (*fail) return -1; + } + } + } else { + const struct command*command; + int unknown = 1; + size_t l; + + l = strcspn(cs, whitespace); + + for (command = commands; command->name; command++) + if (strlen(command->name) == l && !strncmp(cs, command->name, l)) { + int ret; + struct pa_tokenizer *t = pa_tokenizer_new(cs, command->args); + assert(t); + ret = command->proc(c, t, buf, fail, verbose); + pa_tokenizer_free(t); + unknown = 0; + + if (ret < 0 && *fail) + return -1; + + break; + } + + if (unknown) { + pa_strbuf_printf(buf, "Unknown command: %s\n", cs); + if (*fail) + return -1; + } + } + + return 0; +} + +int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_strbuf *buf, int *fail, int *verbose) { + char line[256]; + FILE *f = NULL; + int ret = -1; + assert(c && fn && buf); + + if (!(f = fopen(fn, "r"))) { + pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, strerror(errno)); + if (!*fail) + ret = 0; + goto fail; + } + + if (*verbose) + pa_strbuf_printf(buf, "Executing file: '%s'\n", fn); + + while (fgets(line, sizeof(line), f)) { + char *e = line + strcspn(line, linebreak); + *e = 0; + + if (pa_cli_command_execute_line(c, line, buf, fail, verbose) < 0 && *fail) + goto fail; + } + + if (*verbose) + pa_strbuf_printf(buf, "Executed file: '%s'\n", fn); + + ret = 0; + +fail: + if (f) + fclose(f); + + return ret; +} + +int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *p; + assert(c && s && buf && fail && verbose); + + p = s; + while (*p) { + size_t l = strcspn(p, linebreak); + char *line = strndup(p, l); + assert(line); + + if (pa_cli_command_execute_line(c, line, buf, fail, verbose) < 0&& *fail) { + free(line); + return -1; + } + free(line); + + p += l; + p += strspn(p, linebreak); + } + + return 0; +} diff --git a/src/cli-command.h b/src/cli-command.h new file mode 100644 index 000000000..f95261b73 --- /dev/null +++ b/src/cli-command.h @@ -0,0 +1,11 @@ +#ifndef fooclicommandhfoo +#define fooclicommandhfoo + +#include "strbuf.h" +#include "core.h" + +int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose); +int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_strbuf *buf, int *fail, int *verbose); +int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose); + +#endif diff --git a/src/cli.c b/src/cli.c index d5b46c461..b4d6625db 100644 --- a/src/cli.c +++ b/src/cli.c @@ -15,6 +15,7 @@ #include "strbuf.h" #include "namereg.h" #include "clitext.h" +#include "cli-command.h" struct pa_cli { struct pa_core *core; @@ -24,62 +25,12 @@ struct pa_cli { void *userdata; struct pa_client *client; -}; -struct command { - const char *name; - int (*proc) (struct pa_cli *cli, struct pa_tokenizer*t); - const char *help; - unsigned args; + int fail, verbose, kill_requested, defer_kill; }; static void line_callback(struct pa_ioline *line, const char *s, void *userdata); -static int pa_cli_command_exit(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_help(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_modules(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_clients(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_sinks(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_sources(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_sink_inputs(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_source_outputs(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_stat(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_info(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_load(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_unload(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_sink_volume(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_sink_input_volume(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_sink_default(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_source_default(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_kill_client(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_kill_sink_input(struct pa_cli *c, struct pa_tokenizer *t); -static int pa_cli_command_kill_source_output(struct pa_cli *c, struct pa_tokenizer *t); - -static const struct command commands[] = { - { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, - { "help", pa_cli_command_help, "Show this help", 1 }, - { "modules", pa_cli_command_modules, "List loaded modules", 1 }, - { "sinks", pa_cli_command_sinks, "List loaded sinks", 1 }, - { "sources", pa_cli_command_sources, "List loaded sources", 1 }, - { "clients", pa_cli_command_clients, "List loaded clients", 1 }, - { "sink_inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 }, - { "source_outputs", pa_cli_command_source_outputs, "List source outputs", 1 }, - { "stat", pa_cli_command_stat, "Show memory block statistics", 1 }, - { "info", pa_cli_command_info, "Show comprehensive status", 1 }, - { "ls", pa_cli_command_info, NULL, 1 }, - { "list", pa_cli_command_info, NULL, 1 }, - { "load", pa_cli_command_load, "Load a module (args: name, arguments)", 3}, - { "unload", pa_cli_command_unload, "Unload a module (args: index)", 2}, - { "sink_volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3}, - { "sink_input_volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index|name, volume)", 3}, - { "sink_default", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2}, - { "source_default", pa_cli_command_source_default, "Set the default source (args: index|name)", 2}, - { "kill_client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, - { "kill_sink_input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2}, - { "kill_source_output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2}, - { NULL, NULL, NULL, 0 } -}; - static const char prompt[] = ">>> "; static void client_kill(struct pa_client *c); @@ -108,6 +59,9 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct pa_ioline_set_callback(c->line, line_callback, c); pa_ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"); pa_ioline_puts(c->line, prompt); + + c->fail = c->kill_requested = c->defer_kill = 0; + c->verbose = 1; return c; } @@ -123,16 +77,20 @@ static void client_kill(struct pa_client *client) { struct pa_cli *c; assert(client && client->userdata); c = client->userdata; + fprintf(stderr, "CLI client killed.\n"); - - if (c->eof_callback) - c->eof_callback(c, c->userdata); + if (c->defer_kill) + c->kill_requested = 1; + else { + if (c->eof_callback) + c->eof_callback(c, c->userdata); + } } static void line_callback(struct pa_ioline *line, const char *s, void *userdata) { + struct pa_strbuf *buf; struct pa_cli *c = userdata; - const char *cs; - const char delimiter[] = " \t\n\r"; + char *p; assert(line && c); if (!s) { @@ -143,34 +101,19 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) return; } - cs = s+strspn(s, delimiter); - if (*cs && *cs != '#') { - const struct command*command; - int unknown = 1; - size_t l; - - l = strcspn(s, delimiter); + buf = pa_strbuf_new(); + assert(buf); + c->defer_kill++; + pa_cli_command_execute_line(c->core, s, buf, &c->fail, &c->verbose); + c->defer_kill--; + pa_ioline_puts(line, p = pa_strbuf_tostring_free(buf)); + free(p); - for (command = commands; command->name; command++) - if (strlen(command->name) == l && !strncmp(s, command->name, l)) { - int ret; - struct pa_tokenizer *t = pa_tokenizer_new(s, command->args); - assert(t); - ret = command->proc(c, t); - pa_tokenizer_free(t); - unknown = 0; - - /* A negative return value denotes that the cli object is probably invalid now */ - if (ret < 0) - return; - break; - } - - if (unknown) - pa_ioline_puts(line, "Unknown command\n"); - } - - pa_ioline_puts(line, prompt); + if (c->kill_requested) { + if (c->eof_callback) + c->eof_callback(c, c->userdata); + } else + pa_ioline_puts(line, prompt); } void pa_cli_set_eof_callback(struct pa_cli *c, void (*cb)(struct pa_cli*c, void *userdata), void *userdata) { @@ -178,346 +121,3 @@ void pa_cli_set_eof_callback(struct pa_cli *c, void (*cb)(struct pa_cli*c, void c->eof_callback = cb; c->userdata = userdata; } - -static uint32_t parse_index(const char *n) { - long index; - char *x; - index = strtol(n, &x, 0); - if (!x || *x != 0 || index < 0) - return (uint32_t) PA_IDXSET_INVALID; - - return (uint32_t) index; -} - -static int pa_cli_command_exit(struct pa_cli *c, struct pa_tokenizer *t) { - assert(c && c->core && c->core->mainloop && t); - c->core->mainloop->quit(c->core->mainloop, 0); - return 0; -} - -static int pa_cli_command_help(struct pa_cli *c, struct pa_tokenizer *t) { - const struct command*command; - struct pa_strbuf *pa_strbuf; - char *p; - assert(c && t); - - pa_strbuf = pa_strbuf_new(); - assert(pa_strbuf); - - pa_strbuf_puts(pa_strbuf, "Available commands:\n"); - - for (command = commands; command->name; command++) - if (command->help) - pa_strbuf_printf(pa_strbuf, " %-20s %s\n", command->name, command->help); - - pa_ioline_puts(c->line, p = pa_strbuf_tostring_free(pa_strbuf)); - free(p); - return 0; -} - -static int pa_cli_command_modules(struct pa_cli *c, struct pa_tokenizer *t) { - char *s; - assert(c && t); - s = pa_module_list_to_string(c->core); - assert(s); - pa_ioline_puts(c->line, s); - free(s); - return 0; -} - -static int pa_cli_command_clients(struct pa_cli *c, struct pa_tokenizer *t) { - char *s; - assert(c && t); - s = pa_client_list_to_string(c->core); - assert(s); - pa_ioline_puts(c->line, s); - free(s); - return 0; -} - -static int pa_cli_command_sinks(struct pa_cli *c, struct pa_tokenizer *t) { - char *s; - assert(c && t); - s = pa_sink_list_to_string(c->core); - assert(s); - pa_ioline_puts(c->line, s); - free(s); - return 0; -} - -static int pa_cli_command_sources(struct pa_cli *c, struct pa_tokenizer *t) { - char *s; - assert(c && t); - s = pa_source_list_to_string(c->core); - assert(s); - pa_ioline_puts(c->line, s); - free(s); - return 0; -} - -static int pa_cli_command_sink_inputs(struct pa_cli *c, struct pa_tokenizer *t) { - char *s; - assert(c && t); - s = pa_sink_input_list_to_string(c->core); - assert(s); - pa_ioline_puts(c->line, s); - free(s); - return 0; -} - -static int pa_cli_command_source_outputs(struct pa_cli *c, struct pa_tokenizer *t) { - char *s; - assert(c && t); - s = pa_source_output_list_to_string(c->core); - assert(s); - pa_ioline_puts(c->line, s); - free(s); - return 0; -} - -static int pa_cli_command_stat(struct pa_cli *c, struct pa_tokenizer *t) { - char txt[256]; - assert(c && t); - snprintf(txt, sizeof(txt), "Memory blocks allocated: %u, total size: %u bytes.\n", pa_memblock_count, pa_memblock_total); - pa_ioline_puts(c->line, txt); - return 0; -} - -static int pa_cli_command_info(struct pa_cli *c, struct pa_tokenizer *t) { - assert(c && t); - pa_cli_command_stat(c, t); - pa_cli_command_modules(c, t); - pa_cli_command_sinks(c, t); - pa_cli_command_sources(c, t); - pa_cli_command_clients(c, t); - pa_cli_command_sink_inputs(c, t); - pa_cli_command_source_outputs(c, t); - return 0; -} - -static int pa_cli_command_load(struct pa_cli *c, struct pa_tokenizer *t) { - struct pa_module *m; - const char *name; - char txt[256]; - assert(c && t); - - if (!(name = pa_tokenizer_get(t, 1))) { - pa_ioline_puts(c->line, "You need to specfiy the module name and optionally arguments.\n"); - return 0; - } - - if (!(m = pa_module_load(c->core, name, pa_tokenizer_get(t, 2)))) { - pa_ioline_puts(c->line, "Module load failed.\n"); - return 0; - } - - snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index); - pa_ioline_puts(c->line, txt); - return 0; -} - -static int pa_cli_command_unload(struct pa_cli *c, struct pa_tokenizer *t) { - struct pa_module *m; - uint32_t index; - const char *i; - char *e; - assert(c && t); - - if (!(i = pa_tokenizer_get(t, 1))) { - pa_ioline_puts(c->line, "You need to specfiy the module index.\n"); - return 0; - } - - index = (uint32_t) strtoul(i, &e, 10); - if (*e || !(m = pa_idxset_get_by_index(c->core->modules, index))) { - pa_ioline_puts(c->line, "Invalid module index.\n"); - return 0; - } - - pa_module_unload_request(c->core, m); - return 0; -} - -static int pa_cli_command_sink_volume(struct pa_cli *c, struct pa_tokenizer *t) { - const char *n, *v; - char *x = NULL; - struct pa_sink *sink; - long volume; - - if (!(n = pa_tokenizer_get(t, 1))) { - pa_ioline_puts(c->line, "You need to specify a sink either by its name or its index.\n"); - return 0; - } - - if (!(v = pa_tokenizer_get(t, 2))) { - pa_ioline_puts(c->line, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); - return 0; - } - - volume = strtol(v, &x, 0); - if (!x || *x != 0 || volume < 0) { - pa_ioline_puts(c->line, "Failed to parse volume.\n"); - return 0; - } - - if (!(sink = pa_namereg_get(c->core, n, PA_NAMEREG_SINK))) { - pa_ioline_puts(c->line, "No sink found by this name or index.\n"); - return 0; - } - - sink->volume = (uint32_t) volume; - return 0; -} - -static int pa_cli_command_sink_input_volume(struct pa_cli *c, struct pa_tokenizer *t) { - const char *n, *v; - struct pa_sink_input *si; - long volume; - uint32_t index; - char *x; - - if (!(n = pa_tokenizer_get(t, 1))) { - pa_ioline_puts(c->line, "You need to specify a sink input by its index.\n"); - return 0; - } - - if ((index = parse_index(n)) == PA_IDXSET_INVALID) { - pa_ioline_puts(c->line, "Failed to parse index.\n"); - return 0; - } - - if (!(v = pa_tokenizer_get(t, 2))) { - pa_ioline_puts(c->line, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); - return 0; - } - - x = NULL; - volume = strtol(v, &x, 0); - if (!x || *x != 0 || volume < 0) { - pa_ioline_puts(c->line, "Failed to parse volume.\n"); - return 0; - } - - if (!(si = pa_idxset_get_by_index(c->core->sink_inputs, (uint32_t) index))) { - pa_ioline_puts(c->line, "No sink input found with this index.\n"); - return 0; - } - - si->volume = (uint32_t) volume; - return 0; -} - -static int pa_cli_command_sink_default(struct pa_cli *c, struct pa_tokenizer *t) { - const char *n; - struct pa_sink *sink; - assert(c && t); - - if (!(n = pa_tokenizer_get(t, 1))) { - pa_ioline_puts(c->line, "You need to specify a sink either by its name or its index.\n"); - return 0; - } - - if (!(sink = pa_namereg_get(c->core, n, PA_NAMEREG_SINK))) { - pa_ioline_puts(c->line, "No sink found by this name or index.\n"); - return 0; - } - - c->core->default_sink_index = sink->index; - return 0; -} - -static int pa_cli_command_source_default(struct pa_cli *c, struct pa_tokenizer *t) { - const char *n; - struct pa_source *source; - assert(c && t); - - if (!(n = pa_tokenizer_get(t, 1))) { - pa_ioline_puts(c->line, "You need to specify a source either by its name or its index.\n"); - return 0; - } - - if (!(source = pa_namereg_get(c->core, n, PA_NAMEREG_SOURCE))) { - pa_ioline_puts(c->line, "No source found by this name or index.\n"); - return 0; - } - - c->core->default_source_index = source->index; - return 0; -} - -static int pa_cli_command_kill_client(struct pa_cli *c, struct pa_tokenizer *t) { - const char *n; - struct pa_client *client; - uint32_t index; - int ret; - assert(c && t); - - if (!(n = pa_tokenizer_get(t, 1))) { - pa_ioline_puts(c->line, "You need to specify a client by its index.\n"); - return 0; - } - - if ((index = parse_index(n)) == PA_IDXSET_INVALID) { - pa_ioline_puts(c->line, "Failed to parse index.\n"); - return 0; - } - - if (!(client = pa_idxset_get_by_index(c->core->clients, index))) { - pa_ioline_puts(c->line, "No client found by this index.\n"); - return 0; - } - - ret = (client->userdata == c) ? -1 : 0; - pa_client_kill(client); - return ret; -} - -static int pa_cli_command_kill_sink_input(struct pa_cli *c, struct pa_tokenizer *t) { - const char *n; - struct pa_sink_input *sink_input; - uint32_t index; - assert(c && t); - - if (!(n = pa_tokenizer_get(t, 1))) { - pa_ioline_puts(c->line, "You need to specify a sink input by its index.\n"); - return 0; - } - - if ((index = parse_index(n)) == PA_IDXSET_INVALID) { - pa_ioline_puts(c->line, "Failed to parse index.\n"); - return 0; - } - - if (!(sink_input = pa_idxset_get_by_index(c->core->sink_inputs, index))) { - pa_ioline_puts(c->line, "No sink input found by this index.\n"); - return 0; - } - - pa_sink_input_kill(sink_input); - return 0; -} - -static int pa_cli_command_kill_source_output(struct pa_cli *c, struct pa_tokenizer *t) { - const char *n; - struct pa_source_output *source_output; - uint32_t index; - assert(c && t); - - if (!(n = pa_tokenizer_get(t, 1))) { - pa_ioline_puts(c->line, "You need to specify a source output by its index.\n"); - return 0; - } - - if ((index = parse_index(n)) == PA_IDXSET_INVALID) { - pa_ioline_puts(c->line, "Failed to parse index.\n"); - return 0; - } - - if (!(source_output = pa_idxset_get_by_index(c->core->source_outputs, index))) { - pa_ioline_puts(c->line, "No source output found by this index.\n"); - return 0; - } - - pa_source_output_kill(source_output); - return 0; -} diff --git a/src/cmdline.c b/src/cmdline.c index 36fe3e613..d53d028b0 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -6,6 +6,7 @@ #include "cmdline.h" #include "util.h" +#include "strbuf.h" void pa_cmdline_help(const char *argv0) { const char *e; @@ -17,56 +18,38 @@ void pa_cmdline_help(const char *argv0) { printf("%s [options]\n" " -L MODULE Load the specified plugin module with the specified argument\n" - " -F FILE A shortcut for '-L module-cli file=FILE', i.e. run the specified script after startup\n" - " -C A shortcut for '-L module-cli', i.e. open a command line on the running TTY\n" + " -F FILE Run the specified script\n" + " -C Open a command line on the running TTY\n" " -D Daemonize after loading the modules\n" + " -f Dont quit when the startup fails\n" + " -v Verbose startup\n" " -h Show this help\n", e); } -static void add_module(struct pa_cmdline *cmdline, char *name, char *arguments) { - struct pa_cmdline_module *m; - assert(cmdline && name); - - m = malloc(sizeof(struct pa_cmdline_module)); - assert(m); - m->name = name; - m->arguments = name; - m->next = NULL; - - if (cmdline->last_module) - cmdline->last_module->next = m; - else { - assert(!cmdline->first_module); - cmdline->first_module = m; - } - cmdline->last_module = m; -} - struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { char c; struct pa_cmdline *cmdline = NULL; + struct pa_strbuf *buf = NULL; assert(argc && argv); cmdline = malloc(sizeof(struct pa_cmdline)); assert(cmdline); - cmdline->daemonize = cmdline->help = 0; - cmdline->first_module = cmdline->last_module = NULL; + cmdline->daemonize = cmdline->help = cmdline->verbose = 0; + cmdline->fail = 1; + + buf = pa_strbuf_new(); + assert(buf); - while ((c = getopt(argc, argv, "L:F:CDh")) != -1) { + while ((c = getopt(argc, argv, "L:F:CDhfv")) != -1) { switch (c) { - case 'L': { - char *space; - if ((space = strchr(optarg, ' '))) - add_module(cmdline, strndup(optarg, space-optarg), space+1); - else - add_module(cmdline, strdup(optarg), NULL); + case 'L': + pa_strbuf_printf(buf, "load %s\n", optarg); break; - } case 'F': - add_module(cmdline, strdup("module-cli"), pa_sprintf_malloc("file='%s'", optarg)); + pa_strbuf_printf(buf, ".include %s\n", optarg); break; case 'C': - add_module(cmdline, strdup("module-cli"), NULL); + pa_strbuf_puts(buf, "load module-cli\n"); break; case 'D': cmdline->daemonize = 1; @@ -74,29 +57,30 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { case 'h': cmdline->help = 1; break; + case 'f': + cmdline->fail = 0; + break; + case 'v': + cmdline->verbose = 0; + break; default: goto fail; } } + cmdline->cli_commands = pa_strbuf_tostring_free(buf); return cmdline; fail: if (cmdline) pa_cmdline_free(cmdline); + if (buf) + pa_strbuf_free(buf); return NULL; } void pa_cmdline_free(struct pa_cmdline *cmd) { - struct pa_cmdline_module *m; assert(cmd); - - while ((m = cmd->first_module)) { - cmd->first_module = m->next; - free(m->name); - free(m->arguments); - free(m); - } - + free(cmd->cli_commands); free(cmd); } diff --git a/src/cmdline.h b/src/cmdline.h index 9a647706b..ec2dd0c26 100644 --- a/src/cmdline.h +++ b/src/cmdline.h @@ -1,14 +1,10 @@ #ifndef foocmdlinehfoo #define foocmdlinehfoo -struct pa_cmdline_module { - char *name, *arguments; - struct pa_cmdline_module *next; -}; struct pa_cmdline { - int daemonize, help; - struct pa_cmdline_module *first_module, *last_module; + int daemonize, help, fail, verbose; + char *cli_commands; }; struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []); diff --git a/src/main.c b/src/main.c index e2c8eb63f..d2ae61c90 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -10,6 +11,7 @@ #include "module.h" #include "mainloop-signal.h" #include "cmdline.h" +#include "cli-command.h" static struct pa_mainloop *mainloop; @@ -28,10 +30,12 @@ static void aux_signal_callback(void *id, int sig, void *userdata) { int main(int argc, char *argv[]) { struct pa_core *c; struct pa_cmdline *cmdline = NULL; + struct pa_strbuf *buf = NULL; + char *s; int r, retval = 0; if (!(cmdline = pa_cmdline_parse(argc, argv))) { - fprintf(stderr, "Failed to parse command line.\n"); + fprintf(stderr, __FILE__": failed to parse command line.\n"); return 1; } @@ -55,33 +59,48 @@ int main(int argc, char *argv[]) { c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); - pa_module_load(c, "module-oss-mmap", "device=/dev/dsp playback=1 record=1"); -/* pa_module_load(c, "module-oss-mmap", "/dev/dsp1");*/ -/* pa_module_load(c, "module-pipe-sink", NULL);*/ +/* pa_module_load(c, "module-oss-mmap", "device=/dev/dsp playback=1 record=1"); + pa_module_load(c, "module-oss-mmap", "/dev/dsp1"); + pa_module_load(c, "module-pipe-sink", NULL); pa_module_load(c, "module-simple-protocol-tcp", NULL); -/* pa_module_load(c, "module-simple-protocol-unix", NULL); + pa_module_load(c, "module-simple-protocol-unix", NULL); pa_module_load(c, "module-cli-protocol-tcp", NULL); pa_module_load(c, "module-cli-protocol-unix", NULL); - pa_module_load(c, "module-native-protocol-tcp", NULL);*/ + pa_module_load(c, "module-native-protocol-tcp", NULL); pa_module_load(c, "module-native-protocol-unix", NULL); pa_module_load(c, "module-esound-protocol-tcp", NULL); - pa_module_load(c, "module-cli", NULL); + pa_module_load(c, "module-cli", NULL);*/ pa_signal_register(SIGUSR1, aux_signal_callback, c); pa_signal_register(SIGUSR2, aux_signal_callback, c); + + buf = pa_strbuf_new(); + assert(buf); + r = pa_cli_command_execute(c, cmdline->cli_commands, buf, &cmdline->fail, &cmdline->verbose); + fprintf(stderr, s = pa_strbuf_tostring_free(buf)); + free(s); - fprintf(stderr, "main: mainloop entry.\n"); - if (pa_mainloop_run(mainloop, &retval) < 0) + if (r < 0 && cmdline->fail) { + fprintf(stderr, __FILE__": failed to initialize daemon.\n"); retval = 1; - fprintf(stderr, "main: mainloop exit.\n"); - + } else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) { + fprintf(stderr, __FILE__": daemon startup without any loaded modules, refusing to work.\n"); + retval = 1; + } else { + fprintf(stderr, __FILE__": mainloop entry.\n"); + if (pa_mainloop_run(mainloop, &retval) < 0) + retval = 1; + fprintf(stderr, __FILE__": mainloop exit.\n"); + } + + pa_core_free(c); pa_signal_done(); pa_mainloop_free(mainloop); + + pa_cmdline_free(cmdline); - - lt_dlexit(); return retval; diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index a9e130866..020daa2c2 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -270,7 +270,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { fprintf(stderr, "module-oss-mmap: mmap filed for output. Changing to O_RDONLY mode.\n"); mode = O_RDONLY; } else { - fprintf(stderr, "modeule-oss-mmap: mmap(): %s\n", strerror(errno)); + fprintf(stderr, "module-oss-mmap: mmap(): %s\n", strerror(errno)); goto fail; } } else { diff --git a/src/module-oss.c b/src/module-oss.c index 31ca2dba7..5a6513c39 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -195,7 +195,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(u->source); u->source->userdata = u; pa_source_set_owner(u->source, m); - u->sink->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p); + u->source->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p); } else u->source = NULL; diff --git a/src/polypaudio.run b/src/polypaudio.run new file mode 100755 index 000000000..f82ad40e1 --- /dev/null +++ b/src/polypaudio.run @@ -0,0 +1,13 @@ +#!./polypaudio -F + +# Load the CLI module +load module-cli + +load module-esound-protocol-tcp +load module-simple-protocol-tcp +load module-native-protocol-unix +load module-cli-protocol-unix + +load module-oss-mmap device="/dev/dsp" + +load module-cli diff --git a/src/strbuf.c b/src/strbuf.c index 2082002a9..41c139bd4 100644 --- a/src/strbuf.c +++ b/src/strbuf.c @@ -5,6 +5,8 @@ #include #include +#include "strbuf.h" + struct chunk { struct chunk *next; size_t length; @@ -63,11 +65,17 @@ char *pa_strbuf_tostring_free(struct pa_strbuf *sb) { } void pa_strbuf_puts(struct pa_strbuf *sb, const char *t) { - struct chunk *c; - size_t l; assert(sb && t); + pa_strbuf_putsn(sb, t, strlen(t)); +} - l = strlen(t); +void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t l) { + struct chunk *c; + assert(sb && t); + + if (!l) + return; + c = malloc(sizeof(struct chunk)+l); assert(c); diff --git a/src/strbuf.h b/src/strbuf.h index ab0c6a745..0e9bb5e36 100644 --- a/src/strbuf.h +++ b/src/strbuf.h @@ -10,5 +10,6 @@ char *pa_strbuf_tostring_free(struct pa_strbuf *sb); int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) __attribute__ ((format (printf, 2, 3)));; void pa_strbuf_puts(struct pa_strbuf *sb, const char *t); +void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t m); #endif From e83b7106ac1c008d1fa077c4bbb68423a46e604c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 14 Jul 2004 22:48:49 +0000 Subject: [PATCH 0065/1514] update todo fix polypaudio.run git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@66 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypaudio.run | 2 -- src/todo | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/polypaudio.run b/src/polypaudio.run index f82ad40e1..5d2588521 100755 --- a/src/polypaudio.run +++ b/src/polypaudio.run @@ -9,5 +9,3 @@ load module-native-protocol-unix load module-cli-protocol-unix load module-oss-mmap device="/dev/dsp" - -load module-cli diff --git a/src/todo b/src/todo index febdca7cc..db007d97e 100644 --- a/src/todo +++ b/src/todo @@ -1,7 +1,7 @@ - native library/protocol: more functions (esp. latency) -- cmdline & daemonizing +- daemonizing - prefix modules/libraries with pa_ From 1416fef19796fa5372e6ed02cfd18574a040255f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Jul 2004 00:16:27 +0000 Subject: [PATCH 0066/1514] implement client side TCP support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@67 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/cli-command.c | 5 +-- src/polyp.c | 65 +++++++++++++++++++++++++++++++++++--- src/protocol-native-spec.h | 1 + src/socket-client.c | 31 ++++++++++++++++-- src/socket-client.h | 1 + src/todo | 7 ++-- 6 files changed, 100 insertions(+), 10 deletions(-) diff --git a/src/cli-command.c b/src/cli-command.c index 06e0eb300..bf3ab0c4e 100644 --- a/src/cli-command.c +++ b/src/cli-command.c @@ -193,9 +193,10 @@ static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct return -1; } - if (*verbose) + if (*verbose) { snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index); - pa_strbuf_puts(buf, txt); + pa_strbuf_puts(buf, txt); + } return 0; } diff --git a/src/polyp.c b/src/polyp.c index fde0c68b8..75187d793 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include #include "polyp.h" #include "protocol-native-spec.h" @@ -21,6 +24,7 @@ #define DEFAULT_TIMEOUT (5*60) #define DEFAULT_SERVER "/tmp/polypaudio/native" +#define DEFAULT_PORT "4713" struct pa_context { char *name; @@ -284,7 +288,7 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i struct pa_context *c = userdata; struct pa_tagstruct *t; uint32_t tag; - assert(client && io && c && c->state == CONTEXT_CONNECTING); + assert(client && c && c->state == CONTEXT_CONNECTING); pa_socket_client_free(client); c->client = NULL; @@ -318,6 +322,36 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i c->state = CONTEXT_AUTHORIZING; } +static struct sockaddr *resolve_server(const char *server, size_t *len) { + struct sockaddr *sa; + struct addrinfo hints, *result = NULL; + char *port; + assert(server && len); + + if ((port = strrchr(server, ':'))) + port++; + if (!port) + port = DEFAULT_PORT; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + if (getaddrinfo(server, port, &hints, &result) != 0) + return NULL; + assert(result); + + sa = malloc(*len = result->ai_addrlen); + assert(sa); + memcpy(sa, result->ai_addr, *len); + + freeaddrinfo(result); + + return sa; + +} + int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { assert(c && c->state == CONTEXT_UNCONNECTED); @@ -326,10 +360,33 @@ int pa_context_connect(struct pa_context *c, const char *server, void (*complete return -1; } + if (!server) + if (!(server = getenv("POLYP_SERVER"))) + server = DEFAULT_SERVER; + assert(!c->client); - if (!(c->client = pa_socket_client_new_unix(c->mainloop, server ? server : DEFAULT_SERVER))) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; + + if (*server == '/') { + if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } else { + struct sockaddr* sa; + size_t sa_len; + + if (!(sa = resolve_server(server, &sa_len))) { + c->error = PA_ERROR_INVALIDSERVER; + return -1; + } + + c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); + free(sa); + + if (!c->client) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } } c->connect_complete_callback = complete; diff --git a/src/protocol-native-spec.h b/src/protocol-native-spec.h index 5e67fe74a..78dc06c24 100644 --- a/src/protocol-native-spec.h +++ b/src/protocol-native-spec.h @@ -35,6 +35,7 @@ enum { PA_ERROR_INTERNAL, PA_ERROR_CONNECTIONTERMINATED, PA_ERROR_KILLED, + PA_ERROR_INVALIDSERVER, PA_ERROR_MAX }; diff --git a/src/socket-client.c b/src/socket-client.c index 8b2bd384c..b1e609abd 100644 --- a/src/socket-client.c +++ b/src/socket-client.c @@ -80,7 +80,7 @@ static void connect_fixed_cb(struct pa_mainloop_api *m, void *id, void *userdata static void connect_io_cb(struct pa_mainloop_api*m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { struct pa_socket_client *c = userdata; - assert(m && c && c->io_source == id && fd >= 0 && events == PA_MAINLOOP_API_IO_EVENT_OUTPUT); + assert(m && c && c->io_source == id && fd >= 0); m->cancel_io(m, c->io_source); c->io_source = NULL; do_call(c); @@ -93,7 +93,7 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc pa_make_nonblock_fd(c->fd); if ((r = connect(c->fd, sa, len)) < 0) { - if (r != EINPROGRESS) { + if (errno != EINPROGRESS) { fprintf(stderr, "connect(): %s\n", strerror(errno)); return -1; } @@ -165,7 +165,34 @@ fail: pa_socket_client_free(c); return NULL; } + +struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) { + struct pa_socket_client *c; + assert(m && sa); + c = pa_socket_client_new(m); + assert(c); + + if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) { + fprintf(stderr, "socket(): %s\n", strerror(errno)); + goto fail; + } + + if (sa->sa_family == AF_INET) + pa_socket_tcp_low_delay(c->fd); + else + pa_socket_low_delay(c->fd); + + if (do_connect(c, sa, salen) < 0) + goto fail; + return c; + +fail: + pa_socket_client_free(c); + return NULL; + +} + void pa_socket_client_free(struct pa_socket_client *c) { assert(c && c->mainloop); if (c->io_source) diff --git a/src/socket-client.h b/src/socket-client.h index 046cc3a54..857537888 100644 --- a/src/socket-client.h +++ b/src/socket-client.h @@ -11,6 +11,7 @@ struct pa_socket_client; struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename); +struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen); void pa_socket_client_free(struct pa_socket_client *c); diff --git a/src/todo b/src/todo index db007d97e..2bec6f183 100644 --- a/src/todo +++ b/src/todo @@ -1,8 +1,10 @@ +- modargs memory leak + +- clean secure directory handling (with username) + - native library/protocol: more functions (esp. latency) -- daemonizing - - prefix modules/libraries with pa_ - xmms+esound latency testing @@ -25,6 +27,7 @@ - doxygen - make mcalign merge chunks - modinfo +- daemonizing drivers: - libao From ed9bd5f01fca5e8d610b4884358e3dda47c9ab00 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Jul 2004 17:33:56 +0000 Subject: [PATCH 0067/1514] fix modargs memory leak git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@68 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/module-oss-mmap.c | 5 +++++ src/module-oss.c | 2 ++ src/module-protocol-stub.c | 17 ++++++++++++----- src/todo | 2 -- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index 020daa2c2..ceaae4931 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -306,11 +306,16 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->mainloop_source = c->mainloop->source_io(c->mainloop, u->fd, (u->source ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | (u->sink ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), io_callback, u); assert(u->mainloop_source); + pa_modargs_free(ma); + return 0; fail: pa_module_done(c, m); + if (ma) + pa_modargs_free(ma); + return -1; } diff --git a/src/module-oss.c b/src/module-oss.c index 5a6513c39..48d104865 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -229,6 +229,8 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { m->userdata = u; + pa_modargs_free(ma); + return 0; fail: diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 4f82d4e02..7338abc94 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -107,23 +107,30 @@ struct pa_socket_server *create_socket_server(struct pa_core *c, struct pa_modar int pa_module_init(struct pa_core *c, struct pa_module*m) { struct pa_socket_server *s; - struct pa_modargs *ma; + struct pa_modargs *ma = NULL; + int ret = -1; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { fprintf(stderr, "Failed to parse module arguments\n"); - return -1; + goto finish; } if (!(s = create_socket_server(c, ma))) - return -1; + goto finish; if (!(m->userdata = protocol_new(c, s, m, ma))) { pa_socket_server_free(s); - return -1; + goto finish; } - return 0; + ret = 0; + +finish: + if (ma) + pa_modargs_free(ma); + + return ret; } void pa_module_done(struct pa_core *c, struct pa_module*m) { diff --git a/src/todo b/src/todo index 2bec6f183..5e90dfdae 100644 --- a/src/todo +++ b/src/todo @@ -1,5 +1,3 @@ -- modargs memory leak - - clean secure directory handling (with username) - native library/protocol: From 1a6fea24f51dc7e1dc5c0683de6eb9dc9aa8d88b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Jul 2004 19:00:42 +0000 Subject: [PATCH 0068/1514] implement daemonizing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@69 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/main.c | 92 +++++++++++++++++++++++++++++++++++++++++------------- src/todo | 1 - 2 files changed, 71 insertions(+), 22 deletions(-) diff --git a/src/main.c b/src/main.c index d2ae61c90..9e2e00664 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,6 @@ +#include +#include +#include #include #include #include @@ -12,6 +15,8 @@ #include "mainloop-signal.h" #include "cmdline.h" #include "cli-command.h" +#include "util.h" +#include "sioman.h" static struct pa_mainloop *mainloop; @@ -27,22 +32,70 @@ static void aux_signal_callback(void *id, int sig, void *userdata) { pa_module_load(c, sig == SIGUSR1 ? "module-cli" : "module-cli-protocol-unix", NULL); } +static void close_pipe(int p[2]) { + if (p[0] != -1) + close(p[0]); + if (p[1] != -1) + close(p[1]); + p[0] = p[1] = -1; +} + int main(int argc, char *argv[]) { struct pa_core *c; struct pa_cmdline *cmdline = NULL; struct pa_strbuf *buf = NULL; char *s; - int r, retval = 0; + int r, retval = 1; + int daemon_pipe[2] = { -1, -1 }; if (!(cmdline = pa_cmdline_parse(argc, argv))) { fprintf(stderr, __FILE__": failed to parse command line.\n"); - return 1; + goto finish; } if (cmdline->help) { pa_cmdline_help(argv[0]); - pa_cmdline_free(cmdline); - return 0; + retval = 0; + goto finish; + } + + if (cmdline->daemonize) { + pid_t child; + + if (pa_stdio_acquire() < 0) { + fprintf(stderr, __FILE__": failed to acquire stdio.\n"); + goto finish; + } + + if (pipe(daemon_pipe) < 0) { + fprintf(stderr, __FILE__": failed to create pipe.\n"); + goto finish; + } + + if ((child = fork()) < 0) { + fprintf(stderr, __FILE__": fork() failed: %s\n", strerror(errno)); + goto finish; + } + + if (child != 0) { + /* Father */ + + close(daemon_pipe[1]); + daemon_pipe[1] = -1; + + if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval)) != sizeof(retval)) { + fprintf(stderr, __FILE__": read() failed: %s\n", strerror(errno)); + retval = 1; + } + + goto finish; + } + + close(daemon_pipe[0]); + daemon_pipe[0] = -1; + + setsid(); + setpgrp(); } r = lt_dlinit(); @@ -59,18 +112,6 @@ int main(int argc, char *argv[]) { c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); -/* pa_module_load(c, "module-oss-mmap", "device=/dev/dsp playback=1 record=1"); - pa_module_load(c, "module-oss-mmap", "/dev/dsp1"); - pa_module_load(c, "module-pipe-sink", NULL); - pa_module_load(c, "module-simple-protocol-tcp", NULL); - pa_module_load(c, "module-simple-protocol-unix", NULL); - pa_module_load(c, "module-cli-protocol-tcp", NULL); - pa_module_load(c, "module-cli-protocol-unix", NULL); - pa_module_load(c, "module-native-protocol-tcp", NULL); - pa_module_load(c, "module-native-protocol-unix", NULL); - pa_module_load(c, "module-esound-protocol-tcp", NULL); - pa_module_load(c, "module-cli", NULL);*/ - pa_signal_register(SIGUSR1, aux_signal_callback, c); pa_signal_register(SIGUSR2, aux_signal_callback, c); @@ -82,26 +123,35 @@ int main(int argc, char *argv[]) { if (r < 0 && cmdline->fail) { fprintf(stderr, __FILE__": failed to initialize daemon.\n"); - retval = 1; + if (cmdline->daemonize) + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); } else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) { fprintf(stderr, __FILE__": daemon startup without any loaded modules, refusing to work.\n"); - retval = 1; + if (cmdline->daemonize) + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); } else { + retval = 0; + if (cmdline->daemonize) + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); fprintf(stderr, __FILE__": mainloop entry.\n"); if (pa_mainloop_run(mainloop, &retval) < 0) retval = 1; fprintf(stderr, __FILE__": mainloop exit.\n"); } - pa_core_free(c); pa_signal_done(); pa_mainloop_free(mainloop); - pa_cmdline_free(cmdline); - lt_dlexit(); + +finish: + + if (cmdline) + pa_cmdline_free(cmdline); + + close_pipe(daemon_pipe); return retval; } diff --git a/src/todo b/src/todo index 5e90dfdae..963b57fda 100644 --- a/src/todo +++ b/src/todo @@ -25,7 +25,6 @@ - doxygen - make mcalign merge chunks - modinfo -- daemonizing drivers: - libao From c36dadd2bdf01b26a3e5598def477b22a0b31e77 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Jul 2004 20:12:21 +0000 Subject: [PATCH 0069/1514] remove global exported variables: pa_memblock statistics pa_default_sample_spec git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@70 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/cli-command.c | 2 +- src/core.c | 4 ++++ src/core.h | 3 +++ src/memblock.c | 25 ++++++++++++++++--------- src/memblock.h | 3 ++- src/modargs.c | 2 +- src/module-pipe-sink.c | 1 + src/protocol-simple.c | 1 + src/sample-util.c | 6 ------ src/sample-util.h | 4 ---- src/todo | 6 +----- 11 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/cli-command.c b/src/cli-command.c index bf3ab0c4e..0c754c7e6 100644 --- a/src/cli-command.c +++ b/src/cli-command.c @@ -161,7 +161,7 @@ static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { assert(c && t); - pa_strbuf_printf(buf, "Memory blocks allocated: %u, total size: %u bytes.\n", pa_memblock_count, pa_memblock_total); + pa_strbuf_printf(buf, "Memory blocks allocated: %u, total size: %u bytes.\n", pa_memblock_get_count(), pa_memblock_get_total()); return 0; } diff --git a/src/core.c b/src/core.c index a1fe7d977..987bcc18c 100644 --- a/src/core.c +++ b/src/core.c @@ -26,6 +26,10 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->modules = NULL; c->namereg = NULL; + c->default_sample_spec.format = PA_SAMPLE_S16NE; + c->default_sample_spec.rate = 44100; + c->default_sample_spec.channels = 2; + pa_check_for_sigpipe(); return c; diff --git a/src/core.h b/src/core.h index 13374e400..ee5bfc413 100644 --- a/src/core.h +++ b/src/core.h @@ -4,6 +4,7 @@ #include "idxset.h" #include "hashmap.h" #include "mainloop-api.h" +#include "sample.h" struct pa_core { struct pa_mainloop_api *mainloop; @@ -13,6 +14,8 @@ struct pa_core { struct pa_hashmap *namereg; uint32_t default_source_index, default_sink_index; + + struct pa_sample_spec default_sample_spec; }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/src/memblock.c b/src/memblock.c index 2dfa6a9c1..17038861f 100644 --- a/src/memblock.c +++ b/src/memblock.c @@ -5,7 +5,7 @@ #include "memblock.h" -unsigned pa_memblock_count = 0, pa_memblock_total = 0; +static unsigned memblock_count = 0, memblock_total = 0; struct pa_memblock *pa_memblock_new(size_t length) { struct pa_memblock *b = malloc(sizeof(struct pa_memblock)+length); @@ -13,8 +13,8 @@ struct pa_memblock *pa_memblock_new(size_t length) { b->ref = 1; b->length = length; b->data = b+1; - pa_memblock_count++; - pa_memblock_total += length; + memblock_count++; + memblock_total += length; return b; } @@ -24,8 +24,8 @@ struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length) { b->ref = 1; b->length = length; b->data = d; - pa_memblock_count++; - pa_memblock_total += length; + memblock_count++; + memblock_total += length; return b; } @@ -35,8 +35,8 @@ struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length) { b->ref = 1; b->length = length; b->data = d; - pa_memblock_count++; - pa_memblock_total += length; + memblock_count++; + memblock_total += length; return b; } @@ -54,8 +54,8 @@ void pa_memblock_unref(struct pa_memblock*b) { if (b->type == PA_MEMBLOCK_DYNAMIC) free(b->data); - pa_memblock_count--; - pa_memblock_total -= b->length; + memblock_count--; + memblock_total -= b->length; free(b); } @@ -79,3 +79,10 @@ void pa_memblock_unref_fixed(struct pa_memblock *b) { } } +unsigned pa_memblock_get_count(void) { + return memblock_count; +} + +unsigned pa_memblock_get_total(void) { + return memblock_total; +} diff --git a/src/memblock.h b/src/memblock.h index 2635f023f..647a1c8c5 100644 --- a/src/memblock.h +++ b/src/memblock.h @@ -22,6 +22,7 @@ struct pa_memblock* pa_memblock_ref(struct pa_memblock*b); void pa_memblock_unref_fixed(struct pa_memblock*b); -extern unsigned pa_memblock_count, pa_memblock_total; +unsigned pa_memblock_get_count(void); +unsigned pa_memblock_get_total(void); #endif diff --git a/src/modargs.c b/src/modargs.c index a716a80e1..a4ef9af79 100644 --- a/src/modargs.c +++ b/src/modargs.c @@ -188,7 +188,7 @@ int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss struct pa_sample_spec ss; assert(ma && rss); - ss = pa_default_sample_spec; + ss = *rss; if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0) return -1; diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index 29767ea80..0a24f7599 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -101,6 +101,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto fail; } + ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { fprintf(stderr, __FILE__": invalid sample format specification\n"); goto fail; diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 89207133c..4b52a2463 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -355,6 +355,7 @@ struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct p p->server = server; p->connections = pa_idxset_new(NULL, NULL); + p->sample_spec = core->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &p->sample_spec) < 0) { fprintf(stderr, "Failed to parse sample type specification.\n"); goto fail; diff --git a/src/sample-util.c b/src/sample-util.c index 5344ecfad..c7a7b679b 100644 --- a/src/sample-util.c +++ b/src/sample-util.c @@ -4,12 +4,6 @@ #include "sample-util.h" -struct pa_sample_spec pa_default_sample_spec = { - .format = PA_SAMPLE_S16NE, - .rate = 44100, - .channels = 2 -}; - struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_sample_spec *spec) { assert(b && b->data && spec); pa_silence_memory(b->data, b->length, spec); diff --git a/src/sample-util.h b/src/sample-util.h index 6a593b9a4..4efa59a47 100644 --- a/src/sample-util.h +++ b/src/sample-util.h @@ -5,10 +5,6 @@ #include "memblock.h" #include "memchunk.h" -#define PA_DEFAULT_SAMPLE_SPEC pa_default_sample_spec - -extern struct pa_sample_spec pa_default_sample_spec; - #define PA_VOLUME_NORM (0x100) #define PA_VOLUME_MUTE (0) diff --git a/src/todo b/src/todo index 963b57fda..5eb4329d2 100644 --- a/src/todo +++ b/src/todo @@ -11,11 +11,6 @@ - svn-id and license in every file - documentation -- eliminate global variables: - pa_default_sample_spec - pa_memblock_count - pa_memblock_total - -- post 0.1 - future cancellation - client-ui @@ -25,6 +20,7 @@ - doxygen - make mcalign merge chunks - modinfo +- move the global memblock statistics variables to the core drivers: - libao From d8f13006614dca80de8903f5380b7cb718f26fcc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Jul 2004 20:51:55 +0000 Subject: [PATCH 0070/1514] add pactl tool git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@71 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 +- src/pacat.c | 8 ++- src/pactl.c | 141 +++++++++++++++++++++++++++++++++++++ src/polyp.c | 61 ++++++++++++++++ src/polyp.h | 3 + src/protocol-native-spec.h | 1 + src/protocol-native.c | 26 +++++++ src/todo | 7 +- 8 files changed, 246 insertions(+), 7 deletions(-) create mode 100644 src/pactl.c diff --git a/src/Makefile.am b/src/Makefile.am index c973af52f..7aa072152 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ AM_CFLAGS=-ansi -D_GNU_SOURCE -bin_PROGRAMS = polypaudio pacat pacat-simple parec-simple +bin_PROGRAMS = polypaudio pacat pactl pacat-simple parec-simple pkglib_LTLIBRARIES=libiochannel.la \ libsocket-server.la \ @@ -246,6 +246,10 @@ pacat_SOURCES = pacat.c #$(libpolyp_la_SOURCES) $(libpolyp_error_la_SOURCES) pacat_LDADD = libpolyp.la libpolyp-error.la pacat_CFLAGS = $(AM_CFLAGS) +pactl_SOURCES = pactl.c #$(libpolyp_la_SOURCES) $(libpolyp_error_la_SOURCES) +pactl_LDADD = libpolyp.la libpolyp-error.la +pactl_CFLAGS = $(AM_CFLAGS) + pacat_simple_SOURCES = pacat-simple.c #$(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) pacat_simple_LDADD = libpolyp-simple.la libpolyp-error.la pacat_simple_CFLAGS = $(AM_CFLAGS) diff --git a/src/pacat.c b/src/pacat.c index 80d4835fb..c9257d030 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -222,7 +222,7 @@ static void exit_signal_callback(void *id, int sig, void *userdata) { } int main(int argc, char *argv[]) { - struct pa_mainloop* m; + struct pa_mainloop* m = NULL; int ret = 1, r; char *bn; @@ -279,9 +279,11 @@ quit: if (context) pa_context_free(context); - pa_signal_done(); - if (m) + if (m) { + pa_signal_done(); pa_mainloop_free(m); + } + if (buffer) free(buffer); diff --git a/src/pactl.c b/src/pactl.c new file mode 100644 index 000000000..688e1104b --- /dev/null +++ b/src/pactl.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "polyp.h" +#include "polyp-error.h" +#include "mainloop.h" +#include "mainloop-signal.h" + +static struct pa_context *context = NULL; +static struct pa_mainloop_api *mainloop_api = NULL; + +static enum { + NONE, + EXIT, + STAT +} action = NONE; + +static void quit(int ret) { + assert(mainloop_api); + mainloop_api->quit(mainloop_api, ret); +} + +static void context_die_callback(struct pa_context *c, void *userdata) { + assert(c); + fprintf(stderr, "Connection to server shut down, exiting.\n"); + quit(1); +} + +static void context_drain_complete(struct pa_context *c, void *userdata) { + assert(c); + fprintf(stderr, "Connection to server shut down, exiting.\n"); + quit(0); +} + +static void drain(void) { + if (pa_context_drain(context, context_drain_complete, NULL) < 0) + quit(0); +} + +static void stat_callback(struct pa_context *c, uint32_t blocks, uint32_t total, void *userdata) { + if (blocks == (uint32_t) -1) { + fprintf(stderr, "Failed to get statistics: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + fprintf(stderr, "Currently in use: %u blocks containing %u bytes total.\n", blocks, total); + drain(); +} + +static void context_complete_callback(struct pa_context *c, int success, void *userdata) { + assert(c); + + if (!success) { + fprintf(stderr, "Connection failed: %s\n", pa_strerror(pa_context_errno(c))); + goto fail; + } + + fprintf(stderr, "Connection established.\n"); + + if (action == STAT) + pa_context_stat(c, stat_callback, NULL); + else { + assert(action == EXIT); + pa_context_exit(c); + drain(); + } + + return; + +fail: + quit(1); +} + +static void exit_signal_callback(void *id, int sig, void *userdata) { + fprintf(stderr, "Got SIGINT, exiting.\n"); + quit(0); + +} + +int main(int argc, char *argv[]) { + struct pa_mainloop* m = NULL; + int ret = 1, r; + + if (argc >= 2) { + if (!strcmp(argv[1], "stat")) + action = STAT; + else if (!strcmp(argv[1], "exit")) + action = EXIT; + } + + if (action == NONE) { + fprintf(stderr, "No valid action specified. Use one of: stat, exit\n"); + goto quit; + } + + if (!(m = pa_mainloop_new())) { + fprintf(stderr, "pa_mainloop_new() failed.\n"); + goto quit; + } + + mainloop_api = pa_mainloop_get_api(m); + + r = pa_signal_init(mainloop_api); + assert(r == 0); + pa_signal_register(SIGINT, exit_signal_callback, NULL); + signal(SIGPIPE, SIG_IGN); + + if (!(context = pa_context_new(mainloop_api, argv[0]))) { + fprintf(stderr, "pa_context_new() failed.\n"); + goto quit; + } + + if (pa_context_connect(context, NULL, context_complete_callback, NULL) < 0) { + fprintf(stderr, "pa_context_connext() failed.\n"); + goto quit; + } + + pa_context_set_die_callback(context, context_die_callback, NULL); + + if (pa_mainloop_run(m, &ret) < 0) { + fprintf(stderr, "pa_mainloop_run() failed.\n"); + goto quit; + } + +quit: + if (context) + pa_context_free(context); + + if (m) { + pa_signal_done(); + pa_mainloop_free(m); + } + + return ret; +} diff --git a/src/polyp.c b/src/polyp.c index 75187d793..bc6bff5ae 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -53,6 +53,9 @@ struct pa_context { void (*die_callback)(struct pa_context*c, void *userdata); void *die_userdata; + + void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); + void *stat_userdata; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; }; @@ -133,6 +136,9 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->die_callback = NULL; c->die_userdata = NULL; + c->stat_callback = NULL; + c->stat_userdata = NULL; + pa_check_for_sigpipe(); return c; } @@ -834,3 +840,58 @@ void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); } + +void pa_context_exit(struct pa_context *c) { + struct pa_tagstruct *t; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_EXIT); + pa_tagstruct_putu32(t, c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + uint32_t total, count; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &count) < 0 || + pa_tagstruct_getu32(t, &total) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, count, total, c->stat_userdata); +} + +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + c->stat_callback = cb; + c->stat_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_STAT); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); +} diff --git a/src/polyp.h b/src/polyp.h index c49a72b2c..5b7303022 100644 --- a/src/polyp.h +++ b/src/polyp.h @@ -32,6 +32,9 @@ int pa_context_errno(struct pa_context *c); int pa_context_is_pending(struct pa_context *c); +void pa_context_exit(struct pa_context *c); +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); + struct pa_stream; struct pa_stream* pa_stream_new( diff --git a/src/protocol-native-spec.h b/src/protocol-native-spec.h index 78dc06c24..0a60fd80f 100644 --- a/src/protocol-native-spec.h +++ b/src/protocol-native-spec.h @@ -18,6 +18,7 @@ enum { PA_COMMAND_DRAIN_PLAYBACK_STREAM, PA_COMMAND_PLAYBACK_STREAM_KILLED, PA_COMMAND_RECORD_STREAM_KILLED, + PA_COMMAND_STAT, PA_COMMAND_MAX }; diff --git a/src/protocol-native.c b/src/protocol-native.c index abd170263..56395e980 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -75,6 +75,7 @@ static void command_delete_record_stream(struct pa_pdispatch *pd, uint32_t comma static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -91,6 +92,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SET_NAME] = { command_set_name }, [PA_COMMAND_LOOKUP_SINK] = { command_lookup }, [PA_COMMAND_LOOKUP_SOURCE] = { command_lookup }, + [PA_COMMAND_STAT] = { command_stat }, }; /* structure management */ @@ -638,6 +640,30 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm } } +static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + assert(c && t); + struct pa_tagstruct *reply; + + if (!pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + pa_tagstruct_putu32(reply, pa_memblock_get_count()); + pa_tagstruct_putu32(reply, pa_memblock_get_total()); + pa_pstream_send_tagstruct(c->pstream, reply); +} + /*** pstream callbacks ***/ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { diff --git a/src/todo b/src/todo index 5eb4329d2..107fa787e 100644 --- a/src/todo +++ b/src/todo @@ -1,12 +1,11 @@ -- clean secure directory handling (with username) +- pactl - native library/protocol: more functions (esp. latency) -- prefix modules/libraries with pa_ - - xmms+esound latency testing +- prefix modules/libraries with pa_ - rename files - svn-id and license in every file - documentation @@ -21,6 +20,8 @@ - make mcalign merge chunks - modinfo - move the global memblock statistics variables to the core +- unix socket directories include user name + drivers: - libao From 710233bbf68c845ec5f1713679f4ff0b74c517de Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Jul 2004 21:18:18 +0000 Subject: [PATCH 0071/1514] implement get_latency native command git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@72 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pacat.c | 20 +++++++++++++++ src/pdispatch.c | 12 ++++++++- src/polyp.c | 51 ++++++++++++++++++++++++++++++++++++++ src/polyp.h | 2 ++ src/protocol-native-spec.h | 1 + src/protocol-native.c | 34 +++++++++++++++++++++++++ src/todo | 12 ++++----- 7 files changed, 125 insertions(+), 7 deletions(-) diff --git a/src/pacat.c b/src/pacat.c index c9257d030..2c5198fb1 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -221,6 +221,25 @@ static void exit_signal_callback(void *id, int sig, void *userdata) { } +static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, void *userdata) { + assert(s); + + if (latency == (uint32_t) -1) { + fprintf(stderr, "Failed to get latency: %s\n", strerror(errno)); + quit(1); + return; + } + + fprintf(stderr, "Current latency is %u usecs.\n", latency); +} + +static void sigusr1_signal_callback(void *id, int sig, void *userdata) { + if (mode == PLAYBACK) { + fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); + pa_stream_get_latency(stream, stream_get_latency_callback, NULL); + } +} + int main(int argc, char *argv[]) { struct pa_mainloop* m = NULL; int ret = 1, r; @@ -246,6 +265,7 @@ int main(int argc, char *argv[]) { r = pa_signal_init(mainloop_api); assert(r == 0); pa_signal_register(SIGINT, exit_signal_callback, NULL); + pa_signal_register(SIGUSR1, sigusr1_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); if (!(stdio_source = mainloop_api->source_io(mainloop_api, diff --git a/src/pdispatch.c b/src/pdispatch.c index b7257dd4e..32753963e 100644 --- a/src/pdispatch.c +++ b/src/pdispatch.c @@ -4,6 +4,8 @@ #include "pdispatch.h" #include "protocol-native-spec.h" +#ifdef DEBUG_OPCODES + static const char *command_names[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = "ERROR", [PA_COMMAND_TIMEOUT] = "TIMEOUT", @@ -19,8 +21,14 @@ static const char *command_names[PA_COMMAND_MAX] = { [PA_COMMAND_LOOKUP_SINK] = "LOOKUP_SINK", [PA_COMMAND_LOOKUP_SOURCE] = "LOOKUP_SOURCE", [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = "DRAIN_PLAYBACK_STREAM", + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = "PLAYBACK_STREAM_KILLED", + [PA_COMMAND_RECORD_STREAM_KILLED] = "RECORD_STREAM_KILLED", + [PA_COMMAND_STAT] = "STAT", + [PA_COMMAND_GET_PLAYBACK_LATENCY] = "PLAYBACK_LATENCY", }; +#endif + struct reply_info { struct pa_pdispatch *pdispatch; struct reply_info *next, *previous; @@ -106,7 +114,9 @@ int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *use pa_tagstruct_getu32(ts, &tag) < 0) goto finish; - /*fprintf(stderr, __FILE__": Recieved opcode <%s>\n", command_names[command]);*/ +#ifdef DEBUG_OPCODES + fprintf(stderr, __FILE__": Recieved opcode <%s>\n", command_names[command]); +#endif if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) { struct reply_info *r; diff --git a/src/polyp.c b/src/polyp.c index bc6bff5ae..d6d0f9089 100644 --- a/src/polyp.c +++ b/src/polyp.c @@ -89,6 +89,9 @@ struct pa_stream { void (*die_callback)(struct pa_stream*c, void *userdata); void *die_userdata; + + void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); + void *get_latency_userdata; }; static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); @@ -602,6 +605,8 @@ struct pa_stream* pa_stream_new( s->die_userdata = NULL; s->create_complete_callback = complete; s->create_complete_userdata = NULL; + s->get_latency_callback = NULL; + s->get_latency_userdata = NULL; s->name = strdup(name); s->state = STREAM_CREATING; @@ -895,3 +900,49 @@ void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); } + +static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + uint32_t latency; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &latency) < 0 || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, latency, s->get_latency_userdata); +} + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + p->get_latency_callback = cb; + p->get_latency_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); +} diff --git a/src/polyp.h b/src/polyp.h index 5b7303022..008494459 100644 --- a/src/polyp.h +++ b/src/polyp.h @@ -66,6 +66,8 @@ void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_strea int pa_stream_is_dead(struct pa_stream *p); int pa_stream_is_ready(struct pa_stream*p); +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); + struct pa_context* pa_stream_get_context(struct pa_stream *p); #endif diff --git a/src/protocol-native-spec.h b/src/protocol-native-spec.h index 0a60fd80f..e1db6f642 100644 --- a/src/protocol-native-spec.h +++ b/src/protocol-native-spec.h @@ -19,6 +19,7 @@ enum { PA_COMMAND_PLAYBACK_STREAM_KILLED, PA_COMMAND_RECORD_STREAM_KILLED, PA_COMMAND_STAT, + PA_COMMAND_GET_PLAYBACK_LATENCY, PA_COMMAND_MAX }; diff --git a/src/protocol-native.c b/src/protocol-native.c index 56395e980..094c66306 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -76,6 +76,7 @@ static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -93,6 +94,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_LOOKUP_SINK] = { command_lookup }, [PA_COMMAND_LOOKUP_SOURCE] = { command_lookup }, [PA_COMMAND_STAT] = { command_stat }, + [PA_COMMAND_GET_PLAYBACK_LATENCY] = { command_get_playback_latency }, }; /* structure management */ @@ -664,6 +666,38 @@ static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag pa_pstream_send_tagstruct(c->pstream, reply); } +static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + assert(c && t); + struct pa_tagstruct *reply; + struct playback_stream *s; + uint32_t index, latency; + + if (pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(s = pa_idxset_get_by_index(c->playback_streams, index))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + latency = pa_sink_input_get_latency(s->sink_input); + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + pa_tagstruct_putu32(reply, latency); + pa_pstream_send_tagstruct(c->pstream, reply); +} + /*** pstream callbacks ***/ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { diff --git a/src/todo b/src/todo index 107fa787e..09a7a5c13 100644 --- a/src/todo +++ b/src/todo @@ -1,8 +1,3 @@ -- pactl - -- native library/protocol: - more functions (esp. latency) - - xmms+esound latency testing - prefix modules/libraries with pa_ @@ -21,7 +16,12 @@ - modinfo - move the global memblock statistics variables to the core - unix socket directories include user name - +- more complete pactl +- native library/protocol: + get server layout + subscription + module load/unload + kill client/... drivers: - libao From b2405646d8216ceb058529348d87dab8c6a6954e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Jul 2004 21:51:54 +0000 Subject: [PATCH 0072/1514] optimize esound latency for xmms git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@73 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/protocol-esound.c | 5 ++--- src/todo | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/protocol-esound.c b/src/protocol-esound.c index cba724381..d6d7e177a 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -254,7 +254,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); c->input_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&ss), l/2, l/PLAYBACK_BUFFER_FRAGMENTS); assert(c->input_memblockq); - pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*5); + pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2); c->playback.fragment_size = l/10; assert(!c->sink_input); @@ -347,7 +347,7 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons latency = 0; else { float usec = pa_sink_get_latency(sink); - usec += PLAYBACK_BUFFER_SECONDS*1000000*.9; /* A better estimation would be a good idea! */ + usec += PLAYBACK_BUFFER_SECONDS*1000000; /* A better estimation would be a good idea! */ latency = (int) ((usec*44100)/1000000); } @@ -560,7 +560,6 @@ static int do_read(struct connection *c) { c->playback.current_memblock = NULL; c->playback.memblock_index = 0; } - if (!c->playback.current_memblock) { c->playback.current_memblock = pa_memblock_new(c->playback.fragment_size*2); diff --git a/src/todo b/src/todo index 09a7a5c13..1a4e99568 100644 --- a/src/todo +++ b/src/todo @@ -1,5 +1,3 @@ -- xmms+esound latency testing - - prefix modules/libraries with pa_ - rename files - svn-id and license in every file From b8eb0c088df2c5a0495cf43f8991977693258d5b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 00:27:02 +0000 Subject: [PATCH 0073/1514] add alsa sink git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@74 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 + src/Makefile.am | 6 + src/module-alsa-sink.c | 252 +++++++++++++++++++++++++++++++++++++++++ src/polypaudio.run | 3 +- src/todo | 5 +- 5 files changed, 268 insertions(+), 2 deletions(-) create mode 100644 src/module-alsa-sink.c diff --git a/configure.ac b/configure.ac index 647bfab7c..672e6e3d0 100644 --- a/configure.ac +++ b/configure.ac @@ -46,6 +46,10 @@ PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) AC_SUBST(LIBSAMPLERATE_CFLAGS) AC_SUBST(LIBSAMPLERATE_LIBS) +PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ]) +AC_SUBST(ASOUNDLIB_CFLAGS) +AC_SUBST(ASOUNDLIB_LIBS) + # If using GCC specifiy some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -Wall -W -Wno-unused-parameter" diff --git a/src/Makefile.am b/src/Makefile.am index 7aa072152..531347920 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,6 +41,7 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-cli-protocol-tcp.la \ module-cli-protocol-unix.la \ module-pipe-sink.la \ + module-alsa-sink.la \ module-oss.la \ module-oss-mmap.la \ module-simple-protocol-tcp.la \ @@ -200,6 +201,11 @@ module_pipe_sink_la_SOURCES = module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version module_pipe_sink_la_LIBADD = libiochannel.la +module_alsa_sink_la_SOURCES = module-alsa-sink.c +module_alsa_sink_la_LDFLAGS = -module -avoid-version +module_alsa_sink_la_LIBADD = $(ASOUNDLIB_LIBS) +module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) + module_oss_la_SOURCES = module-oss.c module_oss_la_LDFLAGS = -module -avoid-version module_oss_la_LIBADD = libiochannel.la liboss-util.la diff --git a/src/module-alsa-sink.c b/src/module-alsa-sink.c new file mode 100644 index 000000000..7afd24fd5 --- /dev/null +++ b/src/module-alsa-sink.c @@ -0,0 +1,252 @@ +#include +#include +#include + +#include + +#include "module.h" +#include "core.h" +#include "memchunk.h" +#include "sink.h" +#include "modargs.h" +#include "util.h" +#include "sample-util.h" + +struct userdata { + snd_pcm_t *pcm_handle; + struct pa_sink *sink; + void **io_sources; + unsigned n_io_sources; + + size_t frame_size, fragment_size; + struct pa_memchunk memchunk, silence; +}; + +static const char* const valid_modargs[] = { + "device", + "sink_name", + NULL +}; + +#define DEFAULT_SINK_NAME "alsa_output" +#define DEFAULT_DEVICE "plughw:0,0" + +static void xrun_recovery(struct userdata *u) { + assert(u); + + fprintf(stderr, "*** XRUN ***\n"); + + if (snd_pcm_prepare(u->pcm_handle) < 0) + fprintf(stderr, "snd_pcm_prepare() failed\n"); +} + +static void do_write(struct userdata *u) { + assert(u); + + for (;;) { + struct pa_memchunk *memchunk = NULL; + snd_pcm_sframes_t frames; + + if (u->memchunk.memblock) + memchunk = &u->memchunk; + else { + if (pa_sink_render(u->sink, u->fragment_size, &u->memchunk) < 0) + memchunk = &u->silence; + else + memchunk = &u->memchunk; + } + + assert(memchunk->memblock && memchunk->memblock->data && memchunk->length && memchunk->memblock->length && (memchunk->length % u->frame_size) == 0); + + assert(u->pcm_handle); + assert(memchunk->memblock); + assert(memchunk->memblock->data); + assert(memchunk->length); + assert(u->frame_size); + + if ((frames = snd_pcm_writei(u->pcm_handle, memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) { + if (frames == -EPIPE) { + xrun_recovery(u); + continue; + } + + fprintf(stderr, "snd_pcm_writei() failed\n"); + return; + } + + if (memchunk == &u->memchunk) { + memchunk->index += frames * u->frame_size; + memchunk->length -= frames * u->frame_size; + + if (memchunk->length == 0) { + pa_memblock_unref(memchunk->memblock); + memchunk->memblock = NULL; + memchunk->index = memchunk->length = 0; + } + } + + break; + } +} + +static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { + struct userdata *u = userdata; + assert(u && a && id); + + if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) + xrun_recovery(u); + + do_write(u); +} + +static uint32_t sink_get_latency_cb(struct pa_sink *s) { + struct userdata *u = s->userdata; + snd_pcm_sframes_t frames; + assert(s && u && u->sink); + + if (snd_pcm_delay(u->pcm_handle, &frames) < 0) { + fprintf(stderr, __FILE__": failed to get delay\n"); + s->get_latency = NULL; + return 0; + } + + if (frames < 0) + frames = 0; + + return pa_samples_usec(frames * u->frame_size, &s->sample_spec); +} + +int pa_module_init(struct pa_core *c, struct pa_module*m) { + struct pa_modargs *ma = NULL; + int ret = -1; + struct userdata *u = NULL; + snd_pcm_hw_params_t *hwparams; + const char *dev; + struct pollfd *pfds, *ppfd; + struct pa_sample_spec ss; + unsigned i, periods; + snd_pcm_uframes_t buffer_size; + void ** ios; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + fprintf(stderr, __FILE__": failed to parse module arguments\n"); + goto fail; + } + + u = malloc(sizeof(struct userdata)); + assert(u); + memset(u, 0, sizeof(struct userdata)); + m->userdata = u; + + if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) { + fprintf(stderr, "Error opening PCM device %s\n", dev); + goto fail; + } + + ss.format = PA_SAMPLE_S16LE; + ss.rate = 44100; + ss.channels = 2; + + periods = 12; + buffer_size = periods*256; + + snd_pcm_hw_params_alloca(&hwparams); + if (snd_pcm_hw_params_any(u->pcm_handle, hwparams) < 0 || + snd_pcm_hw_params_set_access(u->pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 || + snd_pcm_hw_params_set_format(u->pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0 || + snd_pcm_hw_params_set_rate_near(u->pcm_handle, hwparams, &ss.rate, NULL) < 0 || + snd_pcm_hw_params_set_channels(u->pcm_handle, hwparams, ss.channels) < 0 || + snd_pcm_hw_params_set_periods_near(u->pcm_handle, hwparams, &periods, NULL) < 0 || + snd_pcm_hw_params_set_buffer_size_near(u->pcm_handle, hwparams, &buffer_size) < 0 || + snd_pcm_hw_params(u->pcm_handle, hwparams) < 0) { + fprintf(stderr, "Error setting HW params.\n"); + goto fail; + } + + u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); + assert(u->sink); + + u->sink->get_latency = sink_get_latency_cb; + u->sink->userdata = u; + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); + + u->n_io_sources = snd_pcm_poll_descriptors_count(u->pcm_handle); + + pfds = malloc(sizeof(struct pollfd) * u->n_io_sources); + assert(pfds); + if (snd_pcm_poll_descriptors(u->pcm_handle, pfds, u->n_io_sources) < 0) { + printf("Unable to obtain poll descriptors for playback.\n"); + free(pfds); + goto fail; + } + + u->io_sources = malloc(sizeof(void*) * u->n_io_sources); + assert(u->io_sources); + + for (i = 0, ios = u->io_sources, ppfd = pfds; i < u->n_io_sources; i++, ios++, ppfd++) { + *ios = c->mainloop->source_io(c->mainloop, ppfd->fd, + ((ppfd->events & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | + ((ppfd->events & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), io_callback, u); + assert(*ios); + } + + free(pfds); + + u->frame_size = pa_sample_size(&ss); + u->fragment_size = buffer_size*u->frame_size/periods; + + fprintf(stderr, __FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); + + u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size); + assert(u->silence.memblock); + pa_silence_memblock(u->silence.memblock, &ss); + u->silence.index = 0; + + u->memchunk.memblock = NULL; + u->memchunk.index = u->memchunk.length = 0; + + ret = 0; + +finish: + if (ma) + pa_modargs_free(ma); + + return ret; + +fail: + + if (u) + pa_module_done(c, m); + + goto finish; +} + +void pa_module_done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + assert(c && m); + + if ((u = m->userdata)) { + unsigned i; + void **ios; + + pa_sink_free(u->sink); + + for (ios = u->io_sources, i = 0; i < u->n_io_sources; i++, ios++) + c->mainloop->cancel_io(c->mainloop, *ios); + free(u->io_sources); + + if (u->pcm_handle) { + snd_pcm_drop(u->pcm_handle); + snd_pcm_close(u->pcm_handle); + } + + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + if (u->silence.memblock) + pa_memblock_unref(u->silence.memblock); + + free(u); + } +} + diff --git a/src/polypaudio.run b/src/polypaudio.run index 5d2588521..48c3f7eaf 100755 --- a/src/polypaudio.run +++ b/src/polypaudio.run @@ -8,4 +8,5 @@ load module-simple-protocol-tcp load module-native-protocol-unix load module-cli-protocol-unix -load module-oss-mmap device="/dev/dsp" +load module-alsa-sink +#load module-oss-mmap device="/dev/dsp" diff --git a/src/todo b/src/todo index 1a4e99568..e6685b2e2 100644 --- a/src/todo +++ b/src/todo @@ -1,7 +1,10 @@ +- alsa source + - prefix modules/libraries with pa_ - rename files - svn-id and license in every file - documentation +- pkgconfig -- post 0.1 - future cancellation @@ -20,6 +23,7 @@ subscription module load/unload kill client/... +- make alsa modules use mmap drivers: - libao @@ -29,5 +33,4 @@ drivers: - python modules: -- alsa? - http From f2e08d53d03303376da4491559a5af6296bbfea8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 14:43:25 +0000 Subject: [PATCH 0074/1514] split PA_SAMPLE_FLOAT32 into PA_SAMPLE_FLOAT{LE,BE} add more configuration arguments to alsa sink git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@75 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/module-alsa-sink.c | 43 ++++++++++++++++++++++++++++++++---------- src/sample.c | 6 ++++-- src/sample.h | 6 +++++- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/module-alsa-sink.c b/src/module-alsa-sink.c index 7afd24fd5..16571a2c5 100644 --- a/src/module-alsa-sink.c +++ b/src/module-alsa-sink.c @@ -25,6 +25,11 @@ struct userdata { static const char* const valid_modargs[] = { "device", "sink_name", + "format", + "channels", + "rate", + "fragments", + "fragment_size", NULL }; @@ -124,14 +129,39 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { const char *dev; struct pollfd *pfds, *ppfd; struct pa_sample_spec ss; - unsigned i, periods; + unsigned i, periods, fragsize; snd_pcm_uframes_t buffer_size; void ** ios; + size_t frame_size; + static const snd_pcm_format_t format_trans[] = { + [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8, + [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW, + [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW, + [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE, + [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE, + [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE, + [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE, + }; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { fprintf(stderr, __FILE__": failed to parse module arguments\n"); goto fail; } + + ss = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + fprintf(stderr, __FILE__": failed to parse sample specification\n"); + goto fail; + } + frame_size = pa_sample_size(&ss); + + periods = 12; + fragsize = 1024; + if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { + fprintf(stderr, __FILE__": failed to parse buffer metrics\n"); + goto fail; + } + buffer_size = fragsize/frame_size*periods; u = malloc(sizeof(struct userdata)); assert(u); @@ -142,18 +172,11 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { fprintf(stderr, "Error opening PCM device %s\n", dev); goto fail; } - - ss.format = PA_SAMPLE_S16LE; - ss.rate = 44100; - ss.channels = 2; - - periods = 12; - buffer_size = periods*256; snd_pcm_hw_params_alloca(&hwparams); if (snd_pcm_hw_params_any(u->pcm_handle, hwparams) < 0 || snd_pcm_hw_params_set_access(u->pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 || - snd_pcm_hw_params_set_format(u->pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0 || + snd_pcm_hw_params_set_format(u->pcm_handle, hwparams, format_trans[ss.format]) < 0 || snd_pcm_hw_params_set_rate_near(u->pcm_handle, hwparams, &ss.rate, NULL) < 0 || snd_pcm_hw_params_set_channels(u->pcm_handle, hwparams, ss.channels) < 0 || snd_pcm_hw_params_set_periods_near(u->pcm_handle, hwparams, &periods, NULL) < 0 || @@ -193,7 +216,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { free(pfds); - u->frame_size = pa_sample_size(&ss); + u->frame_size = frame_size; u->fragment_size = buffer_size*u->frame_size/periods; fprintf(stderr, __FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); diff --git a/src/sample.c b/src/sample.c index 20142a236..2cdc9e72a 100644 --- a/src/sample.c +++ b/src/sample.c @@ -17,7 +17,8 @@ size_t pa_sample_size(const struct pa_sample_spec *spec) { case PA_SAMPLE_S16BE: b = 2; break; - case PA_SAMPLE_FLOAT32: + case PA_SAMPLE_FLOAT32LE: + case PA_SAMPLE_FLOAT32BE: b = 4; break; default: @@ -64,7 +65,8 @@ void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { [PA_SAMPLE_ULAW] = "ULAW", [PA_SAMPLE_S16LE] = "S16LE", [PA_SAMPLE_S16BE] = "S16BE", - [PA_SAMPLE_FLOAT32] = "FLOAT32", + [PA_SAMPLE_FLOAT32LE] = "FLOAT32LE", + [PA_SAMPLE_FLOAT32BE] = "FLOAT32BE", }; assert(pa_sample_spec_valid(spec)); diff --git a/src/sample.h b/src/sample.h index df12924b6..a755b76df 100644 --- a/src/sample.h +++ b/src/sample.h @@ -10,15 +10,19 @@ enum pa_sample_format { PA_SAMPLE_ULAW, PA_SAMPLE_S16LE, PA_SAMPLE_S16BE, - PA_SAMPLE_FLOAT32, + PA_SAMPLE_FLOAT32LE, + PA_SAMPLE_FLOAT32BE, PA_SAMPLE_MAX }; #ifdef WORDS_BIGENDIAN #define PA_SAMPLE_S16NE PA_SAMPLE_S16BE +#define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32BE #else #define PA_SAMPLE_S16NE PA_SAMPLE_S16LE +#define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32LE #endif +#define PA_SAMPLE_FLOAT32 PA_SAMPLE_FLOAT32NE struct pa_sample_spec { enum pa_sample_format format; From 74bbf31c37b327be3c52c8043be72b96b8fee8f4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 17:03:11 +0000 Subject: [PATCH 0075/1514] implement alsa source split off alsa-util.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@76 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 14 ++- src/alsa-util.c | 73 ++++++++++++++ src/alsa-util.h | 14 +++ src/module-alsa-sink.c | 77 ++++---------- src/module-alsa-source.c | 212 +++++++++++++++++++++++++++++++++++++++ src/polypaudio.run | 16 ++- src/todo | 5 +- 7 files changed, 344 insertions(+), 67 deletions(-) create mode 100644 src/alsa-util.c create mode 100644 src/alsa-util.h create mode 100644 src/module-alsa-source.c diff --git a/src/Makefile.am b/src/Makefile.am index 531347920..09df6284e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,6 +26,7 @@ pkglib_LTLIBRARIES=libiochannel.la \ libpstream.la \ libpacket.la \ liboss-util.la \ + libalsa-util.la \ libioline.la \ libcli.la \ libprotocol-cli.la \ @@ -42,6 +43,7 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-cli-protocol-unix.la \ module-pipe-sink.la \ module-alsa-sink.la \ + module-alsa-source.la \ module-oss.la \ module-oss-mmap.la \ module-simple-protocol-tcp.la \ @@ -128,6 +130,11 @@ libpacket_la_LDFLAGS = -avoid-version liboss_util_la_SOURCES = oss-util.c oss-util.h liboss_util_la_LDFLAGS = -avoid-version +libalsa_util_la_SOURCES = alsa-util.c alsa-util.h +libalsa_util_la_LDFLAGS = -avoid-version +libalsa_util_la_LIBADD = $(ASOUNDLIB_LIBS) +libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) + libioline_la_SOURCES = ioline.c ioline.h libioline_la_LDFLAGS = -avoid-version libioline_la_LIBADD = libiochannel.la @@ -203,9 +210,14 @@ module_pipe_sink_la_LIBADD = libiochannel.la module_alsa_sink_la_SOURCES = module-alsa-sink.c module_alsa_sink_la_LDFLAGS = -module -avoid-version -module_alsa_sink_la_LIBADD = $(ASOUNDLIB_LIBS) +module_alsa_sink_la_LIBADD = $(ASOUNDLIB_LIBS) libalsa-util.la module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) +module_alsa_source_la_SOURCES = module-alsa-source.c +module_alsa_source_la_LDFLAGS = -module -avoid-version +module_alsa_source_la_LIBADD = $(ASOUNDLIB_LIBS) libalsa-util.la +module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) + module_oss_la_SOURCES = module-oss.c module_oss_la_LDFLAGS = -module -avoid-version module_oss_la_LIBADD = libiochannel.la liboss-util.la diff --git a/src/alsa-util.c b/src/alsa-util.c new file mode 100644 index 000000000..edfd1613e --- /dev/null +++ b/src/alsa-util.c @@ -0,0 +1,73 @@ +#include + +#include "alsa-util.h" +#include "sample.h" + +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *buffer_size) { + int ret = 0; + snd_pcm_hw_params_t *hwparams = NULL; + static const snd_pcm_format_t format_trans[] = { + [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8, + [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW, + [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW, + [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE, + [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE, + [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE, + [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE, + }; + + if (snd_pcm_hw_params_malloc(&hwparams) < 0 || + snd_pcm_hw_params_any(pcm_handle, hwparams) < 0 || + snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 || + snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[ss->format]) < 0 || + snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &ss->rate, NULL) < 0 || + snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss->channels) < 0 || + snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, periods, NULL) < 0 || + snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, buffer_size) < 0 || + snd_pcm_hw_params(pcm_handle, hwparams) < 0) { + ret = -1; + } + + if (hwparams) + snd_pcm_hw_params_free(hwparams); + return ret; +} + +int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, void ***io_sources, unsigned *n_io_sources, void (*cb)(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata) { + unsigned i; + struct pollfd *pfds, *ppfd; + void **ios; + assert(pcm_handle && m && io_sources && n_io_sources && cb); + + *n_io_sources = snd_pcm_poll_descriptors_count(pcm_handle); + + pfds = malloc(sizeof(struct pollfd) * *n_io_sources); + assert(pfds); + if (snd_pcm_poll_descriptors(pcm_handle, pfds, *n_io_sources) < 0) { + free(pfds); + return -1; + } + + *io_sources = malloc(sizeof(void*) * *n_io_sources); + assert(io_sources); + + for (i = 0, ios = *io_sources, ppfd = pfds; i < *n_io_sources; i++, ios++, ppfd++) { + *ios = m->source_io(m, ppfd->fd, + ((ppfd->events & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | + ((ppfd->events & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), cb, userdata); + assert(*ios); + } + + free(pfds); + return 0; +} + +void pa_free_io_sources(struct pa_mainloop_api* m, void **io_sources, unsigned n_io_sources) { + unsigned i; + void **ios; + assert(m && io_sources); + + for (ios = io_sources, i = 0; i < n_io_sources; i++, ios++) + m->cancel_io(m, *ios); + free(io_sources); +} diff --git a/src/alsa-util.h b/src/alsa-util.h new file mode 100644 index 000000000..4468c9d85 --- /dev/null +++ b/src/alsa-util.h @@ -0,0 +1,14 @@ +#ifndef fooalsautilhfoo +#define fooalsautilhfoo + +#include + +#include "sample.h" +#include "mainloop-api.h" + +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *buffer_size); + +int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api *m, void ***io_sources, unsigned *n_io_sources, void (*cb)(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata); +void pa_free_io_sources(struct pa_mainloop_api* m, void **io_sources, unsigned n_io_sources); + +#endif diff --git a/src/module-alsa-sink.c b/src/module-alsa-sink.c index 16571a2c5..a0b1e548e 100644 --- a/src/module-alsa-sink.c +++ b/src/module-alsa-sink.c @@ -11,6 +11,7 @@ #include "modargs.h" #include "util.h" #include "sample-util.h" +#include "alsa-util.h" struct userdata { snd_pcm_t *pcm_handle; @@ -39,7 +40,7 @@ static const char* const valid_modargs[] = { static void xrun_recovery(struct userdata *u) { assert(u); - fprintf(stderr, "*** XRUN ***\n"); + fprintf(stderr, "*** ALSA-XRUN (playback) ***\n"); if (snd_pcm_prepare(u->pcm_handle) < 0) fprintf(stderr, "snd_pcm_prepare() failed\n"); @@ -63,13 +64,10 @@ static void do_write(struct userdata *u) { assert(memchunk->memblock && memchunk->memblock->data && memchunk->length && memchunk->memblock->length && (memchunk->length % u->frame_size) == 0); - assert(u->pcm_handle); - assert(memchunk->memblock); - assert(memchunk->memblock->data); - assert(memchunk->length); - assert(u->frame_size); - if ((frames = snd_pcm_writei(u->pcm_handle, memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) { + if (frames == -EAGAIN) + return; + if (frames == -EPIPE) { xrun_recovery(u); continue; @@ -80,8 +78,9 @@ static void do_write(struct userdata *u) { } if (memchunk == &u->memchunk) { - memchunk->index += frames * u->frame_size; - memchunk->length -= frames * u->frame_size; + size_t l = frames * u->frame_size; + memchunk->index += l; + memchunk->length -= l; if (memchunk->length == 0) { pa_memblock_unref(memchunk->memblock); @@ -125,23 +124,11 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; int ret = -1; struct userdata *u = NULL; - snd_pcm_hw_params_t *hwparams; const char *dev; - struct pollfd *pfds, *ppfd; struct pa_sample_spec ss; - unsigned i, periods, fragsize; + unsigned periods, fragsize; snd_pcm_uframes_t buffer_size; - void ** ios; size_t frame_size; - static const snd_pcm_format_t format_trans[] = { - [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8, - [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW, - [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW, - [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE, - [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE, - [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE, - [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE, - }; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { fprintf(stderr, __FILE__": failed to parse module arguments\n"); @@ -169,20 +156,12 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { m->userdata = u; if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) { - fprintf(stderr, "Error opening PCM device %s\n", dev); + fprintf(stderr, __FILE__": Error opening PCM device %s\n", dev); goto fail; } - snd_pcm_hw_params_alloca(&hwparams); - if (snd_pcm_hw_params_any(u->pcm_handle, hwparams) < 0 || - snd_pcm_hw_params_set_access(u->pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 || - snd_pcm_hw_params_set_format(u->pcm_handle, hwparams, format_trans[ss.format]) < 0 || - snd_pcm_hw_params_set_rate_near(u->pcm_handle, hwparams, &ss.rate, NULL) < 0 || - snd_pcm_hw_params_set_channels(u->pcm_handle, hwparams, ss.channels) < 0 || - snd_pcm_hw_params_set_periods_near(u->pcm_handle, hwparams, &periods, NULL) < 0 || - snd_pcm_hw_params_set_buffer_size_near(u->pcm_handle, hwparams, &buffer_size) < 0 || - snd_pcm_hw_params(u->pcm_handle, hwparams) < 0) { - fprintf(stderr, "Error setting HW params.\n"); + if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &buffer_size) < 0) { + fprintf(stderr, __FILE__": Failed to set hardware parameters\n"); goto fail; } @@ -194,28 +173,11 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); - u->n_io_sources = snd_pcm_poll_descriptors_count(u->pcm_handle); - - pfds = malloc(sizeof(struct pollfd) * u->n_io_sources); - assert(pfds); - if (snd_pcm_poll_descriptors(u->pcm_handle, pfds, u->n_io_sources) < 0) { - printf("Unable to obtain poll descriptors for playback.\n"); - free(pfds); + if (pa_create_io_sources(u->pcm_handle, c->mainloop, &u->io_sources, &u->n_io_sources, io_callback, u) < 0) { + fprintf(stderr, __FILE__": failed to obtain file descriptors\n"); goto fail; } - u->io_sources = malloc(sizeof(void*) * u->n_io_sources); - assert(u->io_sources); - - for (i = 0, ios = u->io_sources, ppfd = pfds; i < u->n_io_sources; i++, ios++, ppfd++) { - *ios = c->mainloop->source_io(c->mainloop, ppfd->fd, - ((ppfd->events & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | - ((ppfd->events & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), io_callback, u); - assert(*ios); - } - - free(pfds); - u->frame_size = frame_size; u->fragment_size = buffer_size*u->frame_size/periods; @@ -250,14 +212,11 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { assert(c && m); if ((u = m->userdata)) { - unsigned i; - void **ios; - - pa_sink_free(u->sink); + if (u->sink) + pa_sink_free(u->sink); - for (ios = u->io_sources, i = 0; i < u->n_io_sources; i++, ios++) - c->mainloop->cancel_io(c->mainloop, *ios); - free(u->io_sources); + if (u->io_sources) + pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources); if (u->pcm_handle) { snd_pcm_drop(u->pcm_handle); diff --git a/src/module-alsa-source.c b/src/module-alsa-source.c new file mode 100644 index 000000000..cc45254cf --- /dev/null +++ b/src/module-alsa-source.c @@ -0,0 +1,212 @@ +#include +#include +#include + +#include + +#include "module.h" +#include "core.h" +#include "memchunk.h" +#include "sink.h" +#include "modargs.h" +#include "util.h" +#include "sample-util.h" +#include "alsa-util.h" + +struct userdata { + snd_pcm_t *pcm_handle; + struct pa_source *source; + void **io_sources; + unsigned n_io_sources; + + size_t frame_size, fragment_size; + struct pa_memchunk memchunk; +}; + +static const char* const valid_modargs[] = { + "device", + "source_name", + "format", + "channels", + "rate", + "fragments", + "fragment_size", + NULL +}; + +#define DEFAULT_SOURCE_NAME "alsa_input" +#define DEFAULT_DEVICE "hw:0,0" + +static void xrun_recovery(struct userdata *u) { + assert(u); + + fprintf(stderr, "*** ALSA-XRUN (capture) ***\n"); + + if (snd_pcm_prepare(u->pcm_handle) < 0) + fprintf(stderr, "snd_pcm_prepare() failed\n"); +} + +static void do_read(struct userdata *u) { + assert(u); + + for (;;) { + struct pa_memchunk post_memchunk; + snd_pcm_sframes_t frames; + size_t l; + + if (!u->memchunk.memblock) { + u->memchunk.memblock = pa_memblock_new(u->memchunk.length = u->fragment_size); + u->memchunk.index = 0; + } + + assert(u->memchunk.memblock && u->memchunk.memblock->data && u->memchunk.length && u->memchunk.memblock->length && (u->memchunk.length % u->frame_size) == 0); + + if ((frames = snd_pcm_readi(u->pcm_handle, u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) { + if (frames == -EAGAIN) + return; + + if (frames == -EPIPE) { + xrun_recovery(u); + continue; + } + + fprintf(stderr, "snd_pcm_readi() failed: %s\n", strerror(-frames)); + return; + } + + l = frames * u->frame_size; + + post_memchunk = u->memchunk; + post_memchunk.length = l; + + pa_source_post(u->source, &post_memchunk); + + u->memchunk.index += l; + u->memchunk.length -= l; + + if (u->memchunk.length == 0) { + pa_memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; + u->memchunk.index = u->memchunk.length = 0; + } + + break; + } +} + +static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { + struct userdata *u = userdata; + assert(u && a && id); + + if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) + xrun_recovery(u); + + do_read(u); +} + +int pa_module_init(struct pa_core *c, struct pa_module*m) { + struct pa_modargs *ma = NULL; + int ret = -1; + struct userdata *u = NULL; + const char *dev; + struct pa_sample_spec ss; + unsigned periods, fragsize; + snd_pcm_uframes_t buffer_size; + size_t frame_size; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + fprintf(stderr, __FILE__": failed to parse module arguments\n"); + goto fail; + } + + ss = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + fprintf(stderr, __FILE__": failed to parse sample specification\n"); + goto fail; + } + frame_size = pa_sample_size(&ss); + + periods = 12; + fragsize = 1024; + if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { + fprintf(stderr, __FILE__": failed to parse buffer metrics\n"); + goto fail; + } + buffer_size = fragsize/frame_size*periods; + + u = malloc(sizeof(struct userdata)); + assert(u); + memset(u, 0, sizeof(struct userdata)); + m->userdata = u; + + if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) < 0) { + fprintf(stderr, __FILE__": Error opening PCM device %s\n", dev); + goto fail; + } + + if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &buffer_size) < 0) { + fprintf(stderr, __FILE__": Failed to set hardware parameters\n"); + goto fail; + } + + u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); + assert(u->source); + + u->source->userdata = u; + pa_source_set_owner(u->source, m); + u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); + + if (pa_create_io_sources(u->pcm_handle, c->mainloop, &u->io_sources, &u->n_io_sources, io_callback, u) < 0) { + fprintf(stderr, __FILE__": failed to obtain file descriptors\n"); + goto fail; + } + + u->frame_size = frame_size; + u->fragment_size = buffer_size*u->frame_size/periods; + + fprintf(stderr, __FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); + + u->memchunk.memblock = NULL; + u->memchunk.index = u->memchunk.length = 0; + + snd_pcm_start(u->pcm_handle); + + ret = 0; + +finish: + if (ma) + pa_modargs_free(ma); + + return ret; + +fail: + + if (u) + pa_module_done(c, m); + + goto finish; +} + +void pa_module_done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + assert(c && m); + + if ((u = m->userdata)) { + if (u->source) + pa_source_free(u->source); + + if (u->io_sources) + pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources); + + if (u->pcm_handle) { + snd_pcm_drop(u->pcm_handle); + snd_pcm_close(u->pcm_handle); + } + + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + + free(u); + } +} + diff --git a/src/polypaudio.run b/src/polypaudio.run index 48c3f7eaf..2698c5386 100755 --- a/src/polypaudio.run +++ b/src/polypaudio.run @@ -1,12 +1,20 @@ #!./polypaudio -F -# Load the CLI module -load module-cli +# Load audio drivers +load module-alsa-sink +load module-alsa-source device=plughw:1,0 +#load module-oss-mmap device="/dev/dsp" +# Make some devices default +sink_default alsa_output +source_default alsa_input + +# Load several protocols load module-esound-protocol-tcp load module-simple-protocol-tcp load module-native-protocol-unix load module-cli-protocol-unix -load module-alsa-sink -#load module-oss-mmap device="/dev/dsp" +# Load the CLI module +load module-cli + diff --git a/src/todo b/src/todo index e6685b2e2..8a97ca6a0 100644 --- a/src/todo +++ b/src/todo @@ -1,5 +1,4 @@ -- alsa source - +- make the sample spec configurable for oss devices - prefix modules/libraries with pa_ - rename files - svn-id and license in every file @@ -33,4 +32,4 @@ drivers: - python modules: -- http +- http? From 554b01b6b3a82d201da9a10c54187a66b4804501 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 17:51:53 +0000 Subject: [PATCH 0076/1514] make oss sample spec configurable git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@77 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/module-oss-mmap.c | 27 +++++++++++++---- src/module-oss.c | 27 +++++++++++++---- src/oss-util.c | 70 ++++++++++++++++++++++++++++++++----------- src/oss-util.h | 2 ++ src/polypaudio.run | 17 ++++++----- src/todo | 2 +- 6 files changed, 108 insertions(+), 37 deletions(-) diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index ceaae4931..2b43cbade 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -45,6 +45,11 @@ static const char* const valid_modargs[] = { "device", "record", "playback", + "fragments", + "fragment_size", + "format", + "rate", + "channels", NULL }; @@ -175,7 +180,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; const char *p; - int frag_size; + int nfrags, frag_size; int mode, caps; int enable_bits = 0, zero = 0; int playback = 1, record = 1; @@ -204,6 +209,19 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto fail; } + nfrags = 12; + frag_size = 1024; + if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) { + fprintf(stderr, __FILE__": failed to parse fragments arguments\n"); + goto fail; + } + + u->sample_spec = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &u->sample_spec) < 0) { + fprintf(stderr, __FILE__": failed to parse sample specification\n"); + goto fail; + } + if ((u->fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0) goto fail; @@ -214,12 +232,9 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); - frag_size = ((int) 12 << 16) | 10; /* nfrags = 12; frag_size = 2^10 */ - if (ioctl(u->fd, SNDCTL_DSP_SETFRAGMENT, &frag_size) < 0) { - fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); + if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0) goto fail; - } - + if (pa_oss_auto_format(u->fd, &u->sample_spec) < 0) goto fail; diff --git a/src/module-oss.c b/src/module-oss.c index 48d104865..324bab3be 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -38,6 +38,11 @@ static const char* const valid_modargs[] = { "device", "record", "playback", + "fragments", + "fragment_size", + "format", + "rate", + "channels", NULL }; @@ -131,7 +136,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { struct userdata *u = NULL; const char *p; int fd = -1; - int frag_size, in_frag_size, out_frag_size; + int nfrags, frag_size, in_frag_size, out_frag_size; int mode; uint32_t record = 1, playback = 1; struct pa_sample_spec ss; @@ -154,16 +159,26 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto fail; } + nfrags = 12; + frag_size = 1024; + if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) { + fprintf(stderr, __FILE__": failed to parse fragments arguments\n"); + goto fail; + } + + ss = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + fprintf(stderr, __FILE__": failed to parse sample specification\n"); + goto fail; + } + if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, NULL)) < 0) goto fail; fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); - - frag_size = ((int) 12 << 16) | 10; /* nfrags = 12; frag_size = 2^10 */ - if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag_size) < 0) { - fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); + + if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) goto fail; - } if (pa_oss_auto_format(fd, &ss) < 0) goto fail; diff --git a/src/oss-util.c b/src/oss-util.c index f1e07017e..7be91dcb0 100644 --- a/src/oss-util.c +++ b/src/oss-util.c @@ -62,27 +62,39 @@ fail: } int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { - int format, channels, speed; + int format, channels, speed, reqformat; + static const int format_trans[] = { + [PA_SAMPLE_U8] = AFMT_U8, + [PA_SAMPLE_ALAW] = AFMT_A_LAW, + [PA_SAMPLE_ULAW] = AFMT_MU_LAW, + [PA_SAMPLE_S16LE] = AFMT_S16_LE, + [PA_SAMPLE_S16BE] = AFMT_S16_BE, + [PA_SAMPLE_FLOAT32LE] = AFMT_QUERY, /* not supported */ + [PA_SAMPLE_FLOAT32BE] = AFMT_QUERY, /* not supported */ + }; assert(fd >= 0 && ss); - - format = AFMT_S16_NE; - if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_S16_NE) { - int f = AFMT_S16_NE == AFMT_S16_LE ? AFMT_S16_BE : AFMT_S16_LE; - format = f; - if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != f) { - format = AFMT_U8; - if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_U8) { - fprintf(stderr, "SNDCTL_DSP_SETFMT: %s\n", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); - return -1; + + reqformat = format = format_trans[ss->format]; + if (reqformat == AFMT_QUERY || ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != reqformat) { + format = AFMT_S16_NE; + if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_S16_NE) { + int f = AFMT_S16_NE == AFMT_S16_LE ? AFMT_S16_BE : AFMT_S16_LE; + format = f; + if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != f) { + format = AFMT_U8; + if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_U8) { + fprintf(stderr, "SNDCTL_DSP_SETFMT: %s\n", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); + return -1; + } else + ss->format = PA_SAMPLE_U8; } else - ss->format = PA_SAMPLE_U8; + ss->format = f == AFMT_S16_LE ? PA_SAMPLE_S16LE : PA_SAMPLE_S16BE; } else - ss->format = f == AFMT_S16_LE ? PA_SAMPLE_S16LE : PA_SAMPLE_S16BE; - } else - ss->format = PA_SAMPLE_S16NE; + ss->format = PA_SAMPLE_S16NE; + } - channels = 2; + channels = ss->channels; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { fprintf(stderr, "SNDCTL_DSP_CHANNELS: %s\n", strerror(errno)); return -1; @@ -90,7 +102,7 @@ int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { assert(channels); ss->channels = channels; - speed = 44100; + speed = ss->rate; if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { fprintf(stderr, "SNDCTL_DSP_SPEED: %s\n", strerror(errno)); return -1; @@ -100,3 +112,27 @@ int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { return 0; } + +static int log2(int v) { + int k = 0; + + for (;;) { + v >>= 1; + if (!v) break; + k++; + } + + return k; +} + +int pa_oss_set_fragments(int fd, int nfrags, int frag_size) { + int arg; + arg = ((int) nfrags << 16) | log2(frag_size); + + if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &arg) < 0) { + fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); + return -1; + } + + return 0; +} diff --git a/src/oss-util.h b/src/oss-util.h index 030afba46..a62eee1d4 100644 --- a/src/oss-util.h +++ b/src/oss-util.h @@ -6,4 +6,6 @@ int pa_oss_open(const char *device, int *mode, int* pcaps); int pa_oss_auto_format(int fd, struct pa_sample_spec *ss); +int pa_oss_set_fragments(int fd, int frags, int frag_size); + #endif diff --git a/src/polypaudio.run b/src/polypaudio.run index 2698c5386..25af2df6f 100755 --- a/src/polypaudio.run +++ b/src/polypaudio.run @@ -1,13 +1,10 @@ #!./polypaudio -F # Load audio drivers -load module-alsa-sink -load module-alsa-source device=plughw:1,0 -#load module-oss-mmap device="/dev/dsp" - -# Make some devices default -sink_default alsa_output -source_default alsa_input +#load module-alsa-sink +#load module-alsa-source device=plughw:1,0 +#load module-oss device="/dev/dsp" +load module-oss-mmap device="/dev/dsp" # Load several protocols load module-esound-protocol-tcp @@ -18,3 +15,9 @@ load module-cli-protocol-unix # Load the CLI module load module-cli +.nofail + +# Make some devices default +sink_default alsa_output +source_default alsa_input + diff --git a/src/todo b/src/todo index 8a97ca6a0..225fb2276 100644 --- a/src/todo +++ b/src/todo @@ -1,4 +1,4 @@ -- make the sample spec configurable for oss devices +- run depmod once again - prefix modules/libraries with pa_ - rename files - svn-id and license in every file From 00b53f3f4b27af2572656c975b1fd225e272e012 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 17:56:35 +0000 Subject: [PATCH 0077/1514] make a symbol in module-ptorocol-stub static git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@78 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/module-protocol-stub.c | 2 +- src/todo | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 7338abc94..f9ed62b8e 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -61,7 +61,7 @@ static const char* const valid_modargs[] = { NULL }; -struct pa_socket_server *create_socket_server(struct pa_core *c, struct pa_modargs *ma) { +static struct pa_socket_server *create_socket_server(struct pa_core *c, struct pa_modargs *ma) { struct pa_socket_server *s; #ifdef USE_TCP_SOCKETS uint32_t loopback = 0, port = IPV4_PORT; diff --git a/src/todo b/src/todo index 225fb2276..1e1ff873d 100644 --- a/src/todo +++ b/src/todo @@ -1,4 +1,3 @@ -- run depmod once again - prefix modules/libraries with pa_ - rename files - svn-id and license in every file From 2a6ee7731f6654b2efbc5dbf861f82c2823d1a54 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 18:40:20 +0000 Subject: [PATCH 0078/1514] rename a bunch of files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@79 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/{esound-spec.h => esound.h} | 0 src/{protocol-native-spec.h => native-common.h} | 0 src/{polypdef.h => polyplib-def.h} | 0 src/{polyp-error.c => polyplib-error.c} | 0 src/{polyp-error.h => polyplib-error.h} | 0 src/{simple.c => polyplib-simple.c} | 0 src/{simple.h => polyplib-simple.h} | 0 src/{polyp.c => polyplib.c} | 0 src/{polyp.h => polyplib.h} | 0 src/{sinkinput.c => sink-input.c} | 0 src/{sinkinput.h => sink-input.h} | 0 src/{sourceoutput.c => source-output.c} | 0 src/{sourceoutput.h => source-output.h} | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename src/{esound-spec.h => esound.h} (100%) rename src/{protocol-native-spec.h => native-common.h} (100%) rename src/{polypdef.h => polyplib-def.h} (100%) rename src/{polyp-error.c => polyplib-error.c} (100%) rename src/{polyp-error.h => polyplib-error.h} (100%) rename src/{simple.c => polyplib-simple.c} (100%) rename src/{simple.h => polyplib-simple.h} (100%) rename src/{polyp.c => polyplib.c} (100%) rename src/{polyp.h => polyplib.h} (100%) rename src/{sinkinput.c => sink-input.c} (100%) rename src/{sinkinput.h => sink-input.h} (100%) rename src/{sourceoutput.c => source-output.c} (100%) rename src/{sourceoutput.h => source-output.h} (100%) diff --git a/src/esound-spec.h b/src/esound.h similarity index 100% rename from src/esound-spec.h rename to src/esound.h diff --git a/src/protocol-native-spec.h b/src/native-common.h similarity index 100% rename from src/protocol-native-spec.h rename to src/native-common.h diff --git a/src/polypdef.h b/src/polyplib-def.h similarity index 100% rename from src/polypdef.h rename to src/polyplib-def.h diff --git a/src/polyp-error.c b/src/polyplib-error.c similarity index 100% rename from src/polyp-error.c rename to src/polyplib-error.c diff --git a/src/polyp-error.h b/src/polyplib-error.h similarity index 100% rename from src/polyp-error.h rename to src/polyplib-error.h diff --git a/src/simple.c b/src/polyplib-simple.c similarity index 100% rename from src/simple.c rename to src/polyplib-simple.c diff --git a/src/simple.h b/src/polyplib-simple.h similarity index 100% rename from src/simple.h rename to src/polyplib-simple.h diff --git a/src/polyp.c b/src/polyplib.c similarity index 100% rename from src/polyp.c rename to src/polyplib.c diff --git a/src/polyp.h b/src/polyplib.h similarity index 100% rename from src/polyp.h rename to src/polyplib.h diff --git a/src/sinkinput.c b/src/sink-input.c similarity index 100% rename from src/sinkinput.c rename to src/sink-input.c diff --git a/src/sinkinput.h b/src/sink-input.h similarity index 100% rename from src/sinkinput.h rename to src/sink-input.h diff --git a/src/sourceoutput.c b/src/source-output.c similarity index 100% rename from src/sourceoutput.c rename to src/source-output.c diff --git a/src/sourceoutput.h b/src/source-output.h similarity index 100% rename from src/sourceoutput.h rename to src/source-output.h From 005cb3e013047e29b5c6e089fcb278e4ff225a1a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 18:58:23 +0000 Subject: [PATCH 0079/1514] adjust file references due to renaming git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@80 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 40 +++++++++++++++++++++++--------------- src/cli-command.c | 4 ++-- src/cli.c | 4 ++-- src/clitext.c | 4 ++-- src/module-protocol-stub.c | 2 +- src/native-common.h | 4 ++-- src/pacat-simple.c | 4 ++-- src/pacat.c | 4 ++-- src/pactl.c | 4 ++-- src/parec-simple.c | 4 ++-- src/pdispatch.c | 3 ++- src/polyplib-def.h | 5 ++--- src/polyplib-error.c | 4 ++-- src/polyplib-error.h | 6 ++---- src/polyplib-simple.c | 7 ++++--- src/polyplib-simple.h | 6 +++--- src/polyplib.c | 4 ++-- src/polyplib.h | 6 +++--- src/protocol-esound.c | 6 +++--- src/protocol-native.c | 6 +++--- src/protocol-simple.c | 4 ++-- src/pstream-util.c | 2 +- src/sink-input.c | 2 +- src/sink.c | 2 +- src/source-output.c | 2 +- src/source.c | 2 +- 26 files changed, 74 insertions(+), 67 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 09df6284e..8ca2bfeda 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,10 @@ AM_CFLAGS=-ansi -D_GNU_SOURCE -bin_PROGRAMS = polypaudio pacat pactl pacat-simple parec-simple +EXTRA_DIST = polypaudio.run +bin_PROGRAMS = polypaudio pacat pactl +noinst_PROGRAMS = pacat-simple parec-simple +noinst_SCRIPTS = depmod.py pkglib_LTLIBRARIES=libiochannel.la \ libsocket-server.la \ @@ -54,7 +57,8 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-native-protocol-unix.la \ libpolyp.la \ libpolyp-simple.la \ - libpolyp-error.la + libpolyp-error.la \ + libpolyp-mainloop.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -67,8 +71,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ memblockq.c memblockq.h \ client.c client.h \ core.c core.h \ - sourceoutput.c sourceoutput.h \ - sinkinput.c sinkinput.h \ + source-output.c source-output.h \ + sink-input.c sink-input.h \ source.c source.h \ sink.c sink.h \ module.c module.h \ @@ -147,14 +151,14 @@ libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h libprotocol_cli_la_LDFLAGS = -avoid-version libprotocol_cli_la_LIBADD = libsocket-server.la libiochannel.la libcli.la -libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h +libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h native-common.h libprotocol_native_la_LDFLAGS = -avoid-version libprotocol_native_la_LIBADD = libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libtagstruct_la_SOURCES = tagstruct.c tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version -libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h esound-spec.h +libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h esound.h libprotocol_esound_la_LDFLAGS = -avoid-version libprotocol_esound_la_LIBADD = libsocket-server.la libiochannel.la libauthkey.la @@ -230,8 +234,8 @@ module_cli_la_SOURCES = module-cli.c module_cli_la_LDFLAGS = -module -avoid-version module_cli_la_LIBADD = libcli.la libiochannel.la -libpolyp_la_SOURCES = polyp.c polyp.h \ - polypdef.h \ +libpolyp_la_SOURCES = polyplib.c polyplib.h \ + polyplib-def.h \ tagstruct.c tagstruct.h \ iochannel.c iochannel.h \ pstream.c pstream.h \ @@ -239,8 +243,6 @@ libpolyp_la_SOURCES = polyp.c polyp.h \ pdispatch.c pdispatch.h \ protocol-native-spec.h \ mainloop-api.c mainloop-api.h \ - mainloop.c mainloop.h \ - mainloop-signal.c mainloop-signal.h \ idxset.c idxset.h \ util.c util.h \ memblock.c memblock.h \ @@ -250,22 +252,28 @@ libpolyp_la_SOURCES = polyp.c polyp.h \ dynarray.c dynarray.h \ memchunk.c memchunk.h \ authkey.c authkey.h \ - socket-util.c socket-util.h + socket-util.c socket-util.h \ + native-common.h libpolyp_la_CFLAGS = $(AM_CFLAGS) -libpolyp_error_la_SOURCES = polyp-error.c polyp-error.h +libpolyp_mainloop_la_SOURCES = mainloop-api.h mainloop-api.c \ + mainloop.c mainloop.h \ + mainloop-signal.c mainloop-signal.h +libpolyp_mainloop_la_CFLAGS = $(AM_CFLAGS) + +libpolyp_error_la_SOURCES = polyplib-error.c polyplib-error.h libpolyp_error_la_CFLAGS = $(AM_CFLAGS) -libpolyp_simple_la_SOURCES = simple.c simple.h +libpolyp_simple_la_SOURCES = polyplib-simple.c polyplib-simple.h libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) -libpolyp_simple_la_LIBADD = libpolyp.la +libpolyp_simple_la_LIBADD = libpolyp.la libpolyp-mainloop.la pacat_SOURCES = pacat.c #$(libpolyp_la_SOURCES) $(libpolyp_error_la_SOURCES) -pacat_LDADD = libpolyp.la libpolyp-error.la +pacat_LDADD = libpolyp.la libpolyp-error.la libpolyp-mainloop.la pacat_CFLAGS = $(AM_CFLAGS) pactl_SOURCES = pactl.c #$(libpolyp_la_SOURCES) $(libpolyp_error_la_SOURCES) -pactl_LDADD = libpolyp.la libpolyp-error.la +pactl_LDADD = libpolyp.la libpolyp-error.la libpolyp-mainloop.la pactl_CFLAGS = $(AM_CFLAGS) pacat_simple_SOURCES = pacat-simple.c #$(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) diff --git a/src/cli-command.c b/src/cli-command.c index 0c754c7e6..469e405e7 100644 --- a/src/cli-command.c +++ b/src/cli-command.c @@ -9,8 +9,8 @@ #include "sink.h" #include "source.h" #include "client.h" -#include "sinkinput.h" -#include "sourceoutput.h" +#include "sink-input.h" +#include "source-output.h" #include "tokenizer.h" #include "strbuf.h" #include "namereg.h" diff --git a/src/cli.c b/src/cli.c index b4d6625db..578852d88 100644 --- a/src/cli.c +++ b/src/cli.c @@ -9,8 +9,8 @@ #include "sink.h" #include "source.h" #include "client.h" -#include "sinkinput.h" -#include "sourceoutput.h" +#include "sink-input.h" +#include "source-output.h" #include "tokenizer.h" #include "strbuf.h" #include "namereg.h" diff --git a/src/clitext.c b/src/clitext.c index 701cf2c05..6c3a0b2e6 100644 --- a/src/clitext.c +++ b/src/clitext.c @@ -5,8 +5,8 @@ #include "client.h" #include "sink.h" #include "source.h" -#include "sinkinput.h" -#include "sourceoutput.h" +#include "sink-input.h" +#include "source-output.h" #include "strbuf.h" #include "sample-util.h" diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index f9ed62b8e..4fbb2258f 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -37,7 +37,7 @@ #else #ifdef USE_PROTOCOL_ESOUND #include "protocol-esound.h" - #include "esound-spec.h" + #include "esound.h" #define protocol_new pa_protocol_esound_new #define protocol_free pa_protocol_esound_free #define IPV4_PORT ESD_DEFAULT_PORT diff --git a/src/native-common.h b/src/native-common.h index e1db6f642..75fe483e2 100644 --- a/src/native-common.h +++ b/src/native-common.h @@ -1,5 +1,5 @@ -#ifndef fooprotocolnativespech -#define fooprotocolnativespech +#ifndef foonativecommonhfoo +#define foonativecommonhfoo enum { PA_COMMAND_ERROR, diff --git a/src/pacat-simple.c b/src/pacat-simple.c index 896df814c..be24c4fc3 100644 --- a/src/pacat-simple.c +++ b/src/pacat-simple.c @@ -3,8 +3,8 @@ #include #include -#include "simple.h" -#include "polyp-error.h" +#include "polyplib-simple.h" +#include "polyplib-error.h" #define BUFSIZE 1024 diff --git a/src/pacat.c b/src/pacat.c index 2c5198fb1..ca11b3e9e 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -6,8 +6,8 @@ #include #include -#include "polyp.h" -#include "polyp-error.h" +#include "polyplib.h" +#include "polyplib-error.h" #include "mainloop.h" #include "mainloop-signal.h" diff --git a/src/pactl.c b/src/pactl.c index 688e1104b..2f1959070 100644 --- a/src/pactl.c +++ b/src/pactl.c @@ -6,8 +6,8 @@ #include #include -#include "polyp.h" -#include "polyp-error.h" +#include "polyplib.h" +#include "polyplib-error.h" #include "mainloop.h" #include "mainloop-signal.h" diff --git a/src/parec-simple.c b/src/parec-simple.c index a2841bebc..83c4ea2f0 100644 --- a/src/parec-simple.c +++ b/src/parec-simple.c @@ -3,8 +3,8 @@ #include #include -#include "simple.h" -#include "polyp-error.h" +#include "polyplib-simple.h" +#include "polyplib-error.h" #define BUFSIZE 1024 diff --git a/src/pdispatch.c b/src/pdispatch.c index 32753963e..51f317255 100644 --- a/src/pdispatch.c +++ b/src/pdispatch.c @@ -1,8 +1,9 @@ #include #include #include + #include "pdispatch.h" -#include "protocol-native-spec.h" +#include "native-common.h" #ifdef DEBUG_OPCODES diff --git a/src/polyplib-def.h b/src/polyplib-def.h index 6cfafc972..85920d2bd 100644 --- a/src/polyplib-def.h +++ b/src/polyplib-def.h @@ -1,5 +1,5 @@ -#ifndef foopolypdefhfoo -#define foopolypdefhfoo +#ifndef foopolyplibdefhfoo +#define foopolyplibdefhfoo #include @@ -16,5 +16,4 @@ struct pa_buffer_attr { uint32_t fragsize; }; - #endif diff --git a/src/polyplib-error.c b/src/polyplib-error.c index 86166b0c8..87c9d8fa3 100644 --- a/src/polyplib-error.c +++ b/src/polyplib-error.c @@ -1,8 +1,8 @@ #include #include -#include "polyp-error.h" -#include "protocol-native-spec.h" +#include "polyplib-error.h" +#include "native-common.h" static const char* const errortab[PA_ERROR_MAX] = { [PA_ERROR_OK] = "OK", diff --git a/src/polyplib-error.h b/src/polyplib-error.h index 7407f34cc..7d31ec5a8 100644 --- a/src/polyplib-error.h +++ b/src/polyplib-error.h @@ -1,10 +1,8 @@ -#ifndef foopolyperrhfoo -#define foopolyperrhfoo +#ifndef foopolypliberrorhfoo +#define foopolypliberrorhfoo #include -#include "protocol-native-spec.h" - const char* pa_strerror(uint32_t error); #endif diff --git a/src/polyplib-simple.c b/src/polyplib-simple.c index 5f86c5bf6..6015b77d3 100644 --- a/src/polyplib-simple.c +++ b/src/polyplib-simple.c @@ -3,10 +3,11 @@ #include #include -#include "simple.h" -#include "polyp.h" +#include "polyplib-simple.h" +#include "polyplib.h" #include "mainloop.h" -#include "polyp-error.h" +#include "native-common.h" +/*#include "polyp-error.h"*/ struct pa_simple { struct pa_mainloop *mainloop; diff --git a/src/polyplib-simple.h b/src/polyplib-simple.h index f5f872eee..8286811dc 100644 --- a/src/polyplib-simple.h +++ b/src/polyplib-simple.h @@ -1,10 +1,10 @@ -#ifndef foosimplehfoo -#define foosimplehfoo +#ifndef foopolyplibsimplehfoo +#define foopolyplibsimplehfoo #include #include "sample.h" -#include "polypdef.h" +#include "polyplib-def.h" struct pa_simple; diff --git a/src/polyplib.c b/src/polyplib.c index d6d0f9089..f60d9a2a1 100644 --- a/src/polyplib.c +++ b/src/polyplib.c @@ -6,8 +6,8 @@ #include #include -#include "polyp.h" -#include "protocol-native-spec.h" +#include "polyplib.h" +#include "native-common.h" #include "pdispatch.h" #include "pstream.h" #include "dynarray.h" diff --git a/src/polyplib.h b/src/polyplib.h index 008494459..56d1ba66a 100644 --- a/src/polyplib.h +++ b/src/polyplib.h @@ -1,10 +1,10 @@ -#ifndef foopolyphfoo -#define foopolyphfoo +#ifndef foopolyplibhfoo +#define foopolyplibhfoo #include #include "sample.h" -#include "polypdef.h" +#include "polyplib-def.h" #include "mainloop-api.h" struct pa_context; diff --git a/src/protocol-esound.c b/src/protocol-esound.c index d6d7e177a..db57dfc79 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -6,12 +6,12 @@ #include #include "protocol-esound.h" -#include "esound-spec.h" +#include "esound.h" #include "memblock.h" #include "client.h" -#include "sinkinput.h" +#include "sink-input.h" #include "sink.h" -#include "sourceoutput.h" +#include "source-output.h" #include "source.h" #include "sample.h" diff --git a/src/protocol-native.c b/src/protocol-native.c index 094c66306..5165d671d 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -4,11 +4,11 @@ #include #include "protocol-native.h" -#include "protocol-native-spec.h" +#include "native-common.h" #include "packet.h" #include "client.h" -#include "sourceoutput.h" -#include "sinkinput.h" +#include "source-output.h" +#include "sink-input.h" #include "pstream.h" #include "tagstruct.h" #include "pdispatch.h" diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 4b52a2463..6d27a284a 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -5,8 +5,8 @@ #include #include -#include "sinkinput.h" -#include "sourceoutput.h" +#include "sink-input.h" +#include "source-output.h" #include "protocol-simple.h" #include "client.h" #include "sample-util.h" diff --git a/src/pstream-util.c b/src/pstream-util.c index cdcde5faa..4f545ab42 100644 --- a/src/pstream-util.c +++ b/src/pstream-util.c @@ -1,6 +1,6 @@ #include -#include "protocol-native-spec.h" +#include "native-common.h" #include "pstream-util.h" void pa_pstream_send_tagstruct(struct pa_pstream *p, struct pa_tagstruct *t) { diff --git a/src/sink-input.c b/src/sink-input.c index 54778a81e..b31455ddf 100644 --- a/src/sink-input.c +++ b/src/sink-input.c @@ -3,7 +3,7 @@ #include #include -#include "sinkinput.h" +#include "sink-input.h" #include "sample-util.h" #define CONVERT_BUFFER_LENGTH 4096 diff --git a/src/sink.c b/src/sink.c index 9ba79e39e..4677e9fd5 100644 --- a/src/sink.c +++ b/src/sink.c @@ -4,7 +4,7 @@ #include #include "sink.h" -#include "sinkinput.h" +#include "sink-input.h" #include "namereg.h" #include "util.h" #include "sample-util.h" diff --git a/src/source-output.c b/src/source-output.c index 25c661a98..eefc4f997 100644 --- a/src/source-output.c +++ b/src/source-output.c @@ -2,7 +2,7 @@ #include #include -#include "sourceoutput.h" +#include "source-output.h" struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec) { struct pa_source_output *o; diff --git a/src/source.c b/src/source.c index c0eec3ead..08ce46b7e 100644 --- a/src/source.c +++ b/src/source.c @@ -4,7 +4,7 @@ #include #include "source.h" -#include "sourceoutput.h" +#include "source-output.h" #include "namereg.h" struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) { From dc812dada4a8a51429d28d6d297150dfb8b61aae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 19:08:28 +0000 Subject: [PATCH 0080/1514] fix distcheck git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@81 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- src/Makefile.am | 4 +--- src/todo | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 672e6e3d0..19e813d9a 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.0],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.1],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) diff --git a/src/Makefile.am b/src/Makefile.am index 8ca2bfeda..8b5e80f03 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,10 +18,9 @@ AM_CFLAGS=-ansi -D_GNU_SOURCE -EXTRA_DIST = polypaudio.run +EXTRA_DIST = polypaudio.run depmod.py bin_PROGRAMS = polypaudio pacat pactl noinst_PROGRAMS = pacat-simple parec-simple -noinst_SCRIPTS = depmod.py pkglib_LTLIBRARIES=libiochannel.la \ libsocket-server.la \ @@ -241,7 +240,6 @@ libpolyp_la_SOURCES = polyplib.c polyplib.h \ pstream.c pstream.h \ pstream-util.c pstream-util.h \ pdispatch.c pdispatch.h \ - protocol-native-spec.h \ mainloop-api.c mainloop-api.h \ idxset.c idxset.h \ util.c util.h \ diff --git a/src/todo b/src/todo index 1e1ff873d..a6b2b3c84 100644 --- a/src/todo +++ b/src/todo @@ -1,5 +1,3 @@ -- prefix modules/libraries with pa_ -- rename files - svn-id and license in every file - documentation - pkgconfig From b5384e09fa718c0a1c49ef2e296a8953d883fa73 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 19:16:42 +0000 Subject: [PATCH 0081/1514] include config.h in every file git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@82 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/alsa-util.c | 4 ++++ src/authkey.c | 4 ++++ src/cli-command.c | 4 ++++ src/cli.c | 4 ++++ src/client.c | 4 ++++ src/clitext.c | 4 ++++ src/cmdline.c | 4 ++++ src/core.c | 4 ++++ src/dynarray.c | 4 ++++ src/hashmap.c | 4 ++++ src/idxset.c | 4 ++++ src/iochannel.c | 4 ++++ src/ioline.c | 4 ++++ src/main.c | 4 ++++ src/mainloop-api.c | 4 ++++ src/mainloop-signal.c | 4 ++++ src/mainloop.c | 4 ++++ src/memblock.c | 4 ++++ src/memblockq.c | 4 ++++ src/memchunk.c | 4 ++++ src/modargs.c | 4 ++++ src/module-alsa-sink.c | 4 ++++ src/module-alsa-source.c | 4 ++++ src/module-cli.c | 4 ++++ src/module-oss-mmap.c | 4 ++++ src/module-oss.c | 4 ++++ src/module-pipe-sink.c | 4 ++++ src/module-protocol-stub.c | 4 ++++ src/module.c | 4 ++++ src/namereg.c | 4 ++++ src/oss-util.c | 4 ++++ src/pacat-simple.c | 4 ++++ src/pacat.c | 4 ++++ src/packet.c | 4 ++++ src/pactl.c | 4 ++++ src/parec-simple.c | 4 ++++ src/pdispatch.c | 4 ++++ src/polyplib-error.c | 4 ++++ src/polyplib-simple.c | 4 ++++ src/polyplib.c | 4 ++++ src/protocol-cli.c | 4 ++++ src/protocol-esound.c | 4 ++++ src/protocol-native.c | 4 ++++ src/protocol-simple.c | 4 ++++ src/pstream-util.c | 4 ++++ src/pstream.c | 4 ++++ src/queue.c | 4 ++++ src/resampler.c | 4 ++++ src/sample-util.c | 4 ++++ src/sample.c | 4 ++++ src/sconv-s16be.c | 4 ++++ src/sconv-s16le.c | 4 ++++ src/sconv.c | 4 ++++ src/sink-input.c | 4 ++++ src/sink.c | 4 ++++ src/sioman.c | 4 ++++ src/socket-client.c | 4 ++++ src/socket-server.c | 4 ++++ src/socket-util.c | 4 ++++ src/source-output.c | 4 ++++ src/source.c | 4 ++++ src/strbuf.c | 4 ++++ src/tagstruct.c | 4 ++++ src/todo | 1 + src/tokenizer.c | 4 ++++ src/util.c | 4 ++++ 66 files changed, 261 insertions(+) diff --git a/src/alsa-util.c b/src/alsa-util.c index edfd1613e..be5b0437e 100644 --- a/src/alsa-util.c +++ b/src/alsa-util.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include "alsa-util.h" diff --git a/src/authkey.c b/src/authkey.c index 7bf451658..bdccc8f3c 100644 --- a/src/authkey.c +++ b/src/authkey.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/cli-command.c b/src/cli-command.c index 469e405e7..57dff7ca6 100644 --- a/src/cli-command.c +++ b/src/cli-command.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/cli.c b/src/cli.c index 578852d88..656ba0494 100644 --- a/src/cli.c +++ b/src/cli.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/client.c b/src/client.c index c170e49a1..c6b958afe 100644 --- a/src/client.c +++ b/src/client.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/clitext.c b/src/clitext.c index 6c3a0b2e6..47f0f8ecd 100644 --- a/src/clitext.c +++ b/src/clitext.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include "clitext.h" diff --git a/src/cmdline.c b/src/cmdline.c index d53d028b0..e97a7a0a1 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/core.c b/src/core.c index 987bcc18c..1782559e4 100644 --- a/src/core.c +++ b/src/core.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/dynarray.c b/src/dynarray.c index 7f34eef82..c7af5b273 100644 --- a/src/dynarray.c +++ b/src/dynarray.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/hashmap.c b/src/hashmap.c index 0c963f126..db610c377 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/idxset.c b/src/idxset.c index ba740250a..aceb566a2 100644 --- a/src/idxset.c +++ b/src/idxset.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/iochannel.c b/src/iochannel.c index 384300346..6d8ab3229 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/ioline.c b/src/ioline.c index 86ab57202..e6b35a2d4 100644 --- a/src/ioline.c +++ b/src/ioline.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/main.c b/src/main.c index 9e2e00664..43e9e184d 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/mainloop-api.c b/src/mainloop-api.c index 6caa0c25e..f68852062 100644 --- a/src/mainloop-api.c +++ b/src/mainloop-api.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include "mainloop-api.h" diff --git a/src/mainloop-signal.c b/src/mainloop-signal.c index 3c55f8000..e8b592ea0 100644 --- a/src/mainloop-signal.c +++ b/src/mainloop-signal.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/mainloop.c b/src/mainloop.c index a485a9635..8fd16ef07 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/memblock.c b/src/memblock.c index 17038861f..199b64fac 100644 --- a/src/memblock.c +++ b/src/memblock.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/memblockq.c b/src/memblockq.c index 6d4d712a4..b46070239 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/memchunk.c b/src/memchunk.c index c0be8cce0..d594d2455 100644 --- a/src/memchunk.c +++ b/src/memchunk.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/modargs.c b/src/modargs.c index a4ef9af79..9419129b8 100644 --- a/src/modargs.c +++ b/src/modargs.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/module-alsa-sink.c b/src/module-alsa-sink.c index a0b1e548e..25533361f 100644 --- a/src/module-alsa-sink.c +++ b/src/module-alsa-sink.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/module-alsa-source.c b/src/module-alsa-source.c index cc45254cf..572d28b08 100644 --- a/src/module-alsa-source.c +++ b/src/module-alsa-source.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/module-cli.c b/src/module-cli.c index 135d35881..4c3d71c20 100644 --- a/src/module-cli.c +++ b/src/module-cli.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index 2b43cbade..058bfa16e 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/module-oss.c b/src/module-oss.c index 324bab3be..7acdae932 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index 0a24f7599..66658fd4b 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 4fbb2258f..cb980b166 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/module.c b/src/module.c index b6a706c35..fe27d617f 100644 --- a/src/module.c +++ b/src/module.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/namereg.c b/src/namereg.c index bf381ae4a..2406b50cd 100644 --- a/src/namereg.c +++ b/src/namereg.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/oss-util.c b/src/oss-util.c index 7be91dcb0..de8fa6632 100644 --- a/src/oss-util.c +++ b/src/oss-util.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/pacat-simple.c b/src/pacat-simple.c index be24c4fc3..c0e07146b 100644 --- a/src/pacat-simple.c +++ b/src/pacat-simple.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/pacat.c b/src/pacat.c index ca11b3e9e..b614af732 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/packet.c b/src/packet.c index 304545c51..48685b1e4 100644 --- a/src/packet.c +++ b/src/packet.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/src/pactl.c b/src/pactl.c index 2f1959070..5208321f3 100644 --- a/src/pactl.c +++ b/src/pactl.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/parec-simple.c b/src/parec-simple.c index 83c4ea2f0..f26a13357 100644 --- a/src/parec-simple.c +++ b/src/parec-simple.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/pdispatch.c b/src/pdispatch.c index 51f317255..126c26ef8 100644 --- a/src/pdispatch.c +++ b/src/pdispatch.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/polyplib-error.c b/src/polyplib-error.c index 87c9d8fa3..1a9fe12da 100644 --- a/src/polyplib-error.c +++ b/src/polyplib-error.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/src/polyplib-simple.c b/src/polyplib-simple.c index 6015b77d3..846c2f804 100644 --- a/src/polyplib-simple.c +++ b/src/polyplib-simple.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/polyplib.c b/src/polyplib.c index f60d9a2a1..dd66c5d28 100644 --- a/src/polyplib.c +++ b/src/polyplib.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/protocol-cli.c b/src/protocol-cli.c index 0e7383210..6f052ac44 100644 --- a/src/protocol-cli.c +++ b/src/protocol-cli.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/src/protocol-esound.c b/src/protocol-esound.c index db57dfc79..c28dfa3dd 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/protocol-native.c b/src/protocol-native.c index 5165d671d..223a0972d 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 6d27a284a..563fee94a 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/pstream-util.c b/src/pstream-util.c index 4f545ab42..82bdaa550 100644 --- a/src/pstream-util.c +++ b/src/pstream-util.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include "native-common.h" diff --git a/src/pstream.c b/src/pstream.c index 18d33b0df..4a0848f37 100644 --- a/src/pstream.c +++ b/src/pstream.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/queue.c b/src/queue.c index 9e775f440..f28b26075 100644 --- a/src/queue.c +++ b/src/queue.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/src/resampler.c b/src/resampler.c index 67823e450..42555eca5 100644 --- a/src/resampler.c +++ b/src/resampler.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/src/sample-util.c b/src/sample-util.c index c7a7b679b..df0b58c81 100644 --- a/src/sample-util.c +++ b/src/sample-util.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/sample.c b/src/sample.c index 2cdc9e72a..3c93b3764 100644 --- a/src/sample.c +++ b/src/sample.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/src/sconv-s16be.c b/src/sconv-s16be.c index 728a4a054..3640b9f70 100644 --- a/src/sconv-s16be.c +++ b/src/sconv-s16be.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include "sconv-s16be.h" #define INT16_FROM INT16_FROM_BE diff --git a/src/sconv-s16le.c b/src/sconv-s16le.c index ca9844633..b61ca2bf9 100644 --- a/src/sconv-s16le.c +++ b/src/sconv-s16le.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/src/sconv.c b/src/sconv.c index 6dd165a44..b0a57b770 100644 --- a/src/sconv.c +++ b/src/sconv.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/sink-input.c b/src/sink-input.c index b31455ddf..7b5801268 100644 --- a/src/sink-input.c +++ b/src/sink-input.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/sink.c b/src/sink.c index 4677e9fd5..8c48c033d 100644 --- a/src/sink.c +++ b/src/sink.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/sioman.c b/src/sioman.c index 1a4b08b04..a93e8f458 100644 --- a/src/sioman.c +++ b/src/sioman.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include "sioman.h" diff --git a/src/socket-client.c b/src/socket-client.c index b1e609abd..e7ffa33da 100644 --- a/src/socket-client.c +++ b/src/socket-client.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/socket-server.c b/src/socket-server.c index 02b4328fc..193b3c483 100644 --- a/src/socket-server.c +++ b/src/socket-server.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/socket-util.c b/src/socket-util.c index f4648da5a..c2bb277ea 100644 --- a/src/socket-util.c +++ b/src/socket-util.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/source-output.c b/src/source-output.c index eefc4f997..7b93bcb35 100644 --- a/src/source-output.c +++ b/src/source-output.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/source.c b/src/source.c index 08ce46b7e..fe7cf16e2 100644 --- a/src/source.c +++ b/src/source.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/strbuf.c b/src/strbuf.c index 41c139bd4..44fa5b405 100644 --- a/src/strbuf.c +++ b/src/strbuf.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/tagstruct.c b/src/tagstruct.c index e57e755c1..50854c28c 100644 --- a/src/tagstruct.c +++ b/src/tagstruct.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/todo b/src/todo index a6b2b3c84..c3414fe5a 100644 --- a/src/todo +++ b/src/todo @@ -1,3 +1,4 @@ +- config.h - svn-id and license in every file - documentation - pkgconfig diff --git a/src/tokenizer.c b/src/tokenizer.c index de82c8e1f..bdd05e447 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/src/util.c b/src/util.c index 773922b55..a13679a2c 100644 --- a/src/util.c +++ b/src/util.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include From e0d510df922d4c3440944a3c9670e52ad668056d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 19:56:36 +0000 Subject: [PATCH 0082/1514] include copyright and svn tag in *.[ch] git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@83 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/alsa-util.c | 21 +++++++++++++++++++++ src/alsa-util.h | 21 +++++++++++++++++++++ src/authkey.c | 21 +++++++++++++++++++++ src/authkey.h | 21 +++++++++++++++++++++ src/cli-command.c | 21 +++++++++++++++++++++ src/cli-command.h | 21 +++++++++++++++++++++ src/cli.c | 21 +++++++++++++++++++++ src/cli.h | 21 +++++++++++++++++++++ src/client.c | 21 +++++++++++++++++++++ src/client.h | 21 +++++++++++++++++++++ src/clitext.c | 21 +++++++++++++++++++++ src/clitext.h | 21 +++++++++++++++++++++ src/cmdline.c | 21 +++++++++++++++++++++ src/cmdline.h | 21 +++++++++++++++++++++ src/core.c | 21 +++++++++++++++++++++ src/core.h | 21 +++++++++++++++++++++ src/dynarray.c | 21 +++++++++++++++++++++ src/dynarray.h | 21 +++++++++++++++++++++ src/endianmacros.h | 21 +++++++++++++++++++++ src/esound.h | 21 +++++++++++++++++++++ src/hashmap.c | 21 +++++++++++++++++++++ src/hashmap.h | 21 +++++++++++++++++++++ src/idxset.c | 21 +++++++++++++++++++++ src/idxset.h | 21 +++++++++++++++++++++ src/iochannel.c | 21 +++++++++++++++++++++ src/iochannel.h | 21 +++++++++++++++++++++ src/ioline.c | 21 +++++++++++++++++++++ src/ioline.h | 21 +++++++++++++++++++++ src/main.c | 21 +++++++++++++++++++++ src/mainloop-api.c | 21 +++++++++++++++++++++ src/mainloop-api.h | 21 +++++++++++++++++++++ src/mainloop-signal.c | 21 +++++++++++++++++++++ src/mainloop-signal.h | 21 +++++++++++++++++++++ src/mainloop.c | 21 +++++++++++++++++++++ src/mainloop.h | 21 +++++++++++++++++++++ src/memblock.c | 21 +++++++++++++++++++++ src/memblock.h | 21 +++++++++++++++++++++ src/memblockq.c | 21 +++++++++++++++++++++ src/memblockq.h | 21 +++++++++++++++++++++ src/memchunk.c | 21 +++++++++++++++++++++ src/memchunk.h | 21 +++++++++++++++++++++ src/modargs.c | 21 +++++++++++++++++++++ src/modargs.h | 21 +++++++++++++++++++++ src/module-alsa-sink.c | 21 +++++++++++++++++++++ src/module-alsa-source.c | 21 +++++++++++++++++++++ src/module-cli.c | 21 +++++++++++++++++++++ src/module-oss-mmap.c | 21 +++++++++++++++++++++ src/module-oss.c | 21 +++++++++++++++++++++ src/module-pipe-sink.c | 21 +++++++++++++++++++++ src/module-protocol-stub.c | 21 +++++++++++++++++++++ src/module.c | 21 +++++++++++++++++++++ src/module.h | 21 +++++++++++++++++++++ src/namereg.c | 21 +++++++++++++++++++++ src/namereg.h | 21 +++++++++++++++++++++ src/native-common.h | 21 +++++++++++++++++++++ src/oss-util.c | 21 +++++++++++++++++++++ src/oss-util.h | 21 +++++++++++++++++++++ src/pacat-simple.c | 21 +++++++++++++++++++++ src/pacat.c | 21 +++++++++++++++++++++ src/packet.c | 21 +++++++++++++++++++++ src/packet.h | 21 +++++++++++++++++++++ src/pactl.c | 21 +++++++++++++++++++++ src/parec-simple.c | 21 +++++++++++++++++++++ src/pdispatch.c | 21 +++++++++++++++++++++ src/pdispatch.h | 21 +++++++++++++++++++++ src/polyplib-def.h | 21 +++++++++++++++++++++ src/polyplib-error.c | 21 +++++++++++++++++++++ src/polyplib-error.h | 21 +++++++++++++++++++++ src/polyplib-simple.c | 21 +++++++++++++++++++++ src/polyplib-simple.h | 21 +++++++++++++++++++++ src/polyplib.c | 21 +++++++++++++++++++++ src/polyplib.h | 21 +++++++++++++++++++++ src/protocol-cli.c | 21 +++++++++++++++++++++ src/protocol-cli.h | 21 +++++++++++++++++++++ src/protocol-esound.c | 21 +++++++++++++++++++++ src/protocol-esound.h | 21 +++++++++++++++++++++ src/protocol-native.c | 21 +++++++++++++++++++++ src/protocol-native.h | 21 +++++++++++++++++++++ src/protocol-simple.c | 21 +++++++++++++++++++++ src/protocol-simple.h | 21 +++++++++++++++++++++ src/pstream-util.c | 21 +++++++++++++++++++++ src/pstream-util.h | 21 +++++++++++++++++++++ src/pstream.c | 21 +++++++++++++++++++++ src/pstream.h | 21 +++++++++++++++++++++ src/queue.c | 21 +++++++++++++++++++++ src/queue.h | 21 +++++++++++++++++++++ src/resampler.c | 21 +++++++++++++++++++++ src/resampler.h | 21 +++++++++++++++++++++ src/sample-util.c | 21 +++++++++++++++++++++ src/sample-util.h | 21 +++++++++++++++++++++ src/sample.c | 21 +++++++++++++++++++++ src/sample.h | 21 +++++++++++++++++++++ src/sconv-s16be.c | 21 +++++++++++++++++++++ src/sconv-s16be.h | 21 +++++++++++++++++++++ src/sconv-s16le.c | 21 +++++++++++++++++++++ src/sconv-s16le.h | 21 +++++++++++++++++++++ src/sconv.c | 21 +++++++++++++++++++++ src/sconv.h | 21 +++++++++++++++++++++ src/sink-input.c | 21 +++++++++++++++++++++ src/sink-input.h | 21 +++++++++++++++++++++ src/sink.c | 21 +++++++++++++++++++++ src/sink.h | 21 +++++++++++++++++++++ src/sioman.c | 21 +++++++++++++++++++++ src/sioman.h | 21 +++++++++++++++++++++ src/socket-client.c | 21 +++++++++++++++++++++ src/socket-client.h | 21 +++++++++++++++++++++ src/socket-server.c | 21 +++++++++++++++++++++ src/socket-server.h | 21 +++++++++++++++++++++ src/socket-util.c | 21 +++++++++++++++++++++ src/socket-util.h | 21 +++++++++++++++++++++ src/source-output.c | 21 +++++++++++++++++++++ src/source-output.h | 21 +++++++++++++++++++++ src/source.c | 21 +++++++++++++++++++++ src/source.h | 21 +++++++++++++++++++++ src/strbuf.c | 21 +++++++++++++++++++++ src/strbuf.h | 21 +++++++++++++++++++++ src/tagstruct.c | 21 +++++++++++++++++++++ src/tagstruct.h | 21 +++++++++++++++++++++ src/tokenizer.c | 21 +++++++++++++++++++++ src/tokenizer.h | 21 +++++++++++++++++++++ src/util.c | 21 +++++++++++++++++++++ src/util.h | 21 +++++++++++++++++++++ 122 files changed, 2562 insertions(+) diff --git a/src/alsa-util.c b/src/alsa-util.c index be5b0437e..7f266df56 100644 --- a/src/alsa-util.c +++ b/src/alsa-util.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/alsa-util.h b/src/alsa-util.h index 4468c9d85..03e427d90 100644 --- a/src/alsa-util.h +++ b/src/alsa-util.h @@ -1,6 +1,27 @@ #ifndef fooalsautilhfoo #define fooalsautilhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "sample.h" diff --git a/src/authkey.c b/src/authkey.c index bdccc8f3c..3180b8fd2 100644 --- a/src/authkey.c +++ b/src/authkey.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/authkey.h b/src/authkey.h index a0d695a9e..acdcc24d3 100644 --- a/src/authkey.h +++ b/src/authkey.h @@ -1,6 +1,27 @@ #ifndef fooauthkeyhfoo #define fooauthkeyhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include int pa_authkey_load(const char *path, void *data, size_t len); diff --git a/src/cli-command.c b/src/cli-command.c index 57dff7ca6..f3a2f8a0d 100644 --- a/src/cli-command.c +++ b/src/cli-command.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/cli-command.h b/src/cli-command.h index f95261b73..b3c601ada 100644 --- a/src/cli-command.h +++ b/src/cli-command.h @@ -1,6 +1,27 @@ #ifndef fooclicommandhfoo #define fooclicommandhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "strbuf.h" #include "core.h" diff --git a/src/cli.c b/src/cli.c index 656ba0494..f2aa5a659 100644 --- a/src/cli.c +++ b/src/cli.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/cli.h b/src/cli.h index d6250b372..9cfee0d8c 100644 --- a/src/cli.h +++ b/src/cli.h @@ -1,6 +1,27 @@ #ifndef fooclihfoo #define fooclihfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "iochannel.h" #include "core.h" #include "module.h" diff --git a/src/client.c b/src/client.c index c6b958afe..0294c9e2c 100644 --- a/src/client.c +++ b/src/client.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/client.h b/src/client.h index 10ffa8f31..c926208e8 100644 --- a/src/client.h +++ b/src/client.h @@ -1,6 +1,27 @@ #ifndef fooclienthfoo #define fooclienthfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "core.h" #include "module.h" diff --git a/src/clitext.c b/src/clitext.c index 47f0f8ecd..c1b9953b2 100644 --- a/src/clitext.c +++ b/src/clitext.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/clitext.h b/src/clitext.h index 5b17c2d76..b1718cb5a 100644 --- a/src/clitext.h +++ b/src/clitext.h @@ -1,6 +1,27 @@ #ifndef fooclitexthfoo #define fooclitexthfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "core.h" char *pa_sink_input_list_to_string(struct pa_core *c); diff --git a/src/cmdline.c b/src/cmdline.c index e97a7a0a1..a3330145a 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/cmdline.h b/src/cmdline.h index ec2dd0c26..95ce91dec 100644 --- a/src/cmdline.h +++ b/src/cmdline.h @@ -1,6 +1,27 @@ #ifndef foocmdlinehfoo #define foocmdlinehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + struct pa_cmdline { int daemonize, help, fail, verbose; diff --git a/src/core.c b/src/core.c index 1782559e4..dc9525a8f 100644 --- a/src/core.c +++ b/src/core.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/core.h b/src/core.h index ee5bfc413..99d7d76a7 100644 --- a/src/core.h +++ b/src/core.h @@ -1,6 +1,27 @@ #ifndef foocorehfoo #define foocorehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "idxset.h" #include "hashmap.h" #include "mainloop-api.h" diff --git a/src/dynarray.c b/src/dynarray.c index c7af5b273..243069649 100644 --- a/src/dynarray.c +++ b/src/dynarray.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/dynarray.h b/src/dynarray.h index fab3841df..56ec5386b 100644 --- a/src/dynarray.h +++ b/src/dynarray.h @@ -1,6 +1,27 @@ #ifndef foodynarrayhfoo #define foodynarrayhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + struct pa_dynarray; struct pa_dynarray* pa_dynarray_new(void); diff --git a/src/endianmacros.h b/src/endianmacros.h index 2394b3e89..cd7b7d833 100644 --- a/src/endianmacros.h +++ b/src/endianmacros.h @@ -1,6 +1,27 @@ #ifndef fooendianmacroshfoo #define fooendianmacroshfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #ifdef HAVE_CONFIG_H diff --git a/src/esound.h b/src/esound.h index f7a4d3db5..01a2962fb 100644 --- a/src/esound.h +++ b/src/esound.h @@ -1,6 +1,27 @@ #ifndef fooesoundhfoo #define fooesoundhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + /* Most of the following is blatantly stolen from esound. */ diff --git a/src/hashmap.c b/src/hashmap.c index db610c377..2c7c92b5d 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/hashmap.h b/src/hashmap.h index 4a0ad77ec..b24e74a52 100644 --- a/src/hashmap.h +++ b/src/hashmap.h @@ -1,6 +1,27 @@ #ifndef foohashmaphfoo #define foohashmaphfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + struct pa_hashmap; struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); diff --git a/src/idxset.c b/src/idxset.c index aceb566a2..cecda6b7c 100644 --- a/src/idxset.c +++ b/src/idxset.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/idxset.h b/src/idxset.h index be5bb2948..f26b03fbe 100644 --- a/src/idxset.h +++ b/src/idxset.h @@ -1,6 +1,27 @@ #ifndef fooidxsethfoo #define fooidxsethfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #define PA_IDXSET_INVALID ((uint32_t) -1) diff --git a/src/iochannel.c b/src/iochannel.c index 6d8ab3229..69d381f4e 100644 --- a/src/iochannel.c +++ b/src/iochannel.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/iochannel.h b/src/iochannel.h index 7e31b6cae..6f5f351c2 100644 --- a/src/iochannel.h +++ b/src/iochannel.h @@ -1,6 +1,27 @@ #ifndef fooiochannelhfoo #define fooiochannelhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "mainloop-api.h" diff --git a/src/ioline.c b/src/ioline.c index e6b35a2d4..ff9a03c25 100644 --- a/src/ioline.c +++ b/src/ioline.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/ioline.h b/src/ioline.h index ba7cf5406..5f29a16bc 100644 --- a/src/ioline.h +++ b/src/ioline.h @@ -1,6 +1,27 @@ #ifndef fooiolinehfoo #define fooiolinehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "iochannel.h" struct pa_ioline; diff --git a/src/main.c b/src/main.c index 43e9e184d..d9967cef2 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/mainloop-api.c b/src/mainloop-api.c index f68852062..cce49c067 100644 --- a/src/mainloop-api.c +++ b/src/mainloop-api.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/mainloop-api.h b/src/mainloop-api.h index 961a1a46b..0228f580c 100644 --- a/src/mainloop-api.h +++ b/src/mainloop-api.h @@ -1,6 +1,27 @@ #ifndef foomainloopapihfoo #define foomainloopapihfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include diff --git a/src/mainloop-signal.c b/src/mainloop-signal.c index e8b592ea0..642ca5e05 100644 --- a/src/mainloop-signal.c +++ b/src/mainloop-signal.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/mainloop-signal.h b/src/mainloop-signal.h index e3e2364d5..8afe9c8d1 100644 --- a/src/mainloop-signal.h +++ b/src/mainloop-signal.h @@ -1,6 +1,27 @@ #ifndef foomainloopsignalhfoo #define foomainloopsignalhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "mainloop-api.h" int pa_signal_init(struct pa_mainloop_api *api); diff --git a/src/mainloop.c b/src/mainloop.c index 8fd16ef07..b9eee86d4 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/mainloop.h b/src/mainloop.h index 7837636f9..58448c3ee 100644 --- a/src/mainloop.h +++ b/src/mainloop.h @@ -1,6 +1,27 @@ #ifndef foomainloophfoo #define foomainloophfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "mainloop-api.h" struct pa_mainloop; diff --git a/src/memblock.c b/src/memblock.c index 199b64fac..8f24ff221 100644 --- a/src/memblock.c +++ b/src/memblock.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/memblock.h b/src/memblock.h index 647a1c8c5..4bb029774 100644 --- a/src/memblock.h +++ b/src/memblock.h @@ -1,6 +1,27 @@ #ifndef foomemblockhfoo #define foomemblockhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include diff --git a/src/memblockq.c b/src/memblockq.c index b46070239..eff923b90 100644 --- a/src/memblockq.c +++ b/src/memblockq.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/memblockq.h b/src/memblockq.h index bece4fd76..e6ad01db8 100644 --- a/src/memblockq.h +++ b/src/memblockq.h @@ -1,6 +1,27 @@ #ifndef foomemblockqhfoo #define foomemblockqhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "memblock.h" diff --git a/src/memchunk.c b/src/memchunk.c index d594d2455..d27ca61aa 100644 --- a/src/memchunk.c +++ b/src/memchunk.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/memchunk.h b/src/memchunk.h index 24c031a50..341c145cd 100644 --- a/src/memchunk.h +++ b/src/memchunk.h @@ -1,6 +1,27 @@ #ifndef foomemchunkhfoo #define foomemchunkhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "memblock.h" struct pa_memchunk { diff --git a/src/modargs.c b/src/modargs.c index 9419129b8..da2bab878 100644 --- a/src/modargs.c +++ b/src/modargs.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/modargs.h b/src/modargs.h index 07792ef3c..301dc2971 100644 --- a/src/modargs.h +++ b/src/modargs.h @@ -1,6 +1,27 @@ #ifndef foomodargshfoo #define foomodargshfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "sample.h" #include "core.h" diff --git a/src/module-alsa-sink.c b/src/module-alsa-sink.c index 25533361f..8a3388af9 100644 --- a/src/module-alsa-sink.c +++ b/src/module-alsa-sink.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/module-alsa-source.c b/src/module-alsa-source.c index 572d28b08..287a03502 100644 --- a/src/module-alsa-source.c +++ b/src/module-alsa-source.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/module-cli.c b/src/module-cli.c index 4c3d71c20..8897c9c63 100644 --- a/src/module-cli.c +++ b/src/module-cli.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/module-oss-mmap.c b/src/module-oss-mmap.c index 058bfa16e..800eaf252 100644 --- a/src/module-oss-mmap.c +++ b/src/module-oss-mmap.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/module-oss.c b/src/module-oss.c index 7acdae932..d727534ac 100644 --- a/src/module-oss.c +++ b/src/module-oss.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/module-pipe-sink.c b/src/module-pipe-sink.c index 66658fd4b..df34f73a2 100644 --- a/src/module-pipe-sink.c +++ b/src/module-pipe-sink.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index cb980b166..545de3e85 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/module.c b/src/module.c index fe27d617f..5c6f0fb61 100644 --- a/src/module.c +++ b/src/module.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/module.h b/src/module.h index 174a8d092..af2d85523 100644 --- a/src/module.h +++ b/src/module.h @@ -1,6 +1,27 @@ #ifndef foomodulehfoo #define foomodulehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include diff --git a/src/namereg.c b/src/namereg.c index 2406b50cd..2349436f3 100644 --- a/src/namereg.c +++ b/src/namereg.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/namereg.h b/src/namereg.h index b53a8566e..0af83cd84 100644 --- a/src/namereg.h +++ b/src/namereg.h @@ -1,6 +1,27 @@ #ifndef foonamereghfoo #define foonamereghfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "core.h" enum pa_namereg_type { diff --git a/src/native-common.h b/src/native-common.h index 75fe483e2..2acbae8e8 100644 --- a/src/native-common.h +++ b/src/native-common.h @@ -1,6 +1,27 @@ #ifndef foonativecommonhfoo #define foonativecommonhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + enum { PA_COMMAND_ERROR, PA_COMMAND_TIMEOUT, /* pseudo command */ diff --git a/src/oss-util.c b/src/oss-util.c index de8fa6632..cf55a6ee6 100644 --- a/src/oss-util.c +++ b/src/oss-util.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/oss-util.h b/src/oss-util.h index a62eee1d4..cb2ce33c4 100644 --- a/src/oss-util.h +++ b/src/oss-util.h @@ -1,6 +1,27 @@ #ifndef fooossutilhfoo #define fooossutilhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "sample.h" int pa_oss_open(const char *device, int *mode, int* pcaps); diff --git a/src/pacat-simple.c b/src/pacat-simple.c index c0e07146b..5018aa5f6 100644 --- a/src/pacat-simple.c +++ b/src/pacat-simple.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/pacat.c b/src/pacat.c index b614af732..1d1cc3d57 100644 --- a/src/pacat.c +++ b/src/pacat.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/packet.c b/src/packet.c index 48685b1e4..e94df057c 100644 --- a/src/packet.c +++ b/src/packet.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/packet.h b/src/packet.h index b6024dd0b..8bea07e19 100644 --- a/src/packet.h +++ b/src/packet.h @@ -1,6 +1,27 @@ #ifndef foopackethfoo #define foopackethfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include diff --git a/src/pactl.c b/src/pactl.c index 5208321f3..2b1ed2c18 100644 --- a/src/pactl.c +++ b/src/pactl.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/parec-simple.c b/src/parec-simple.c index f26a13357..c4196a145 100644 --- a/src/parec-simple.c +++ b/src/parec-simple.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/pdispatch.c b/src/pdispatch.c index 126c26ef8..a28458a40 100644 --- a/src/pdispatch.c +++ b/src/pdispatch.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/pdispatch.h b/src/pdispatch.h index ac372477d..796c1e031 100644 --- a/src/pdispatch.h +++ b/src/pdispatch.h @@ -1,6 +1,27 @@ #ifndef foopdispatchhfoo #define foopdispatchhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "tagstruct.h" #include "packet.h" diff --git a/src/polyplib-def.h b/src/polyplib-def.h index 85920d2bd..e43f4b359 100644 --- a/src/polyplib-def.h +++ b/src/polyplib-def.h @@ -1,6 +1,27 @@ #ifndef foopolyplibdefhfoo #define foopolyplibdefhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include enum pa_stream_direction { diff --git a/src/polyplib-error.c b/src/polyplib-error.c index 1a9fe12da..10b637c4d 100644 --- a/src/polyplib-error.c +++ b/src/polyplib-error.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/polyplib-error.h b/src/polyplib-error.h index 7d31ec5a8..cb86864ad 100644 --- a/src/polyplib-error.h +++ b/src/polyplib-error.h @@ -1,6 +1,27 @@ #ifndef foopolypliberrorhfoo #define foopolypliberrorhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include const char* pa_strerror(uint32_t error); diff --git a/src/polyplib-simple.c b/src/polyplib-simple.c index 846c2f804..024cb18ab 100644 --- a/src/polyplib-simple.c +++ b/src/polyplib-simple.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/polyplib-simple.h b/src/polyplib-simple.h index 8286811dc..0544410c0 100644 --- a/src/polyplib-simple.h +++ b/src/polyplib-simple.h @@ -1,6 +1,27 @@ #ifndef foopolyplibsimplehfoo #define foopolyplibsimplehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "sample.h" diff --git a/src/polyplib.c b/src/polyplib.c index dd66c5d28..ea5003b40 100644 --- a/src/polyplib.c +++ b/src/polyplib.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/polyplib.h b/src/polyplib.h index 56d1ba66a..440b9658e 100644 --- a/src/polyplib.h +++ b/src/polyplib.h @@ -1,6 +1,27 @@ #ifndef foopolyplibhfoo #define foopolyplibhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "sample.h" diff --git a/src/protocol-cli.c b/src/protocol-cli.c index 6f052ac44..d6e69b54f 100644 --- a/src/protocol-cli.c +++ b/src/protocol-cli.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/protocol-cli.h b/src/protocol-cli.h index f970bb8dc..7ad2db754 100644 --- a/src/protocol-cli.h +++ b/src/protocol-cli.h @@ -1,6 +1,27 @@ #ifndef fooprotocolclihfoo #define fooprotocolclihfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "core.h" #include "socket-server.h" #include "module.h" diff --git a/src/protocol-esound.c b/src/protocol-esound.c index c28dfa3dd..8a7c4bcbf 100644 --- a/src/protocol-esound.c +++ b/src/protocol-esound.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/protocol-esound.h b/src/protocol-esound.h index 8653949da..b2bdd31b4 100644 --- a/src/protocol-esound.h +++ b/src/protocol-esound.h @@ -1,6 +1,27 @@ #ifndef fooprotocolesoundhfoo #define fooprotocolesoundhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "core.h" #include "socket-server.h" #include "module.h" diff --git a/src/protocol-native.c b/src/protocol-native.c index 223a0972d..83c910d1d 100644 --- a/src/protocol-native.c +++ b/src/protocol-native.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/protocol-native.h b/src/protocol-native.h index 89cb1634c..3d9fdde11 100644 --- a/src/protocol-native.h +++ b/src/protocol-native.h @@ -1,6 +1,27 @@ #ifndef fooprotocolnativehfoo #define fooprotocolnativehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "core.h" #include "socket-server.h" #include "module.h" diff --git a/src/protocol-simple.c b/src/protocol-simple.c index 563fee94a..3a52e311f 100644 --- a/src/protocol-simple.c +++ b/src/protocol-simple.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/protocol-simple.h b/src/protocol-simple.h index 62682915a..0fc1e19df 100644 --- a/src/protocol-simple.h +++ b/src/protocol-simple.h @@ -1,6 +1,27 @@ #ifndef fooprotocolsimplehfoo #define fooprotocolsimplehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "socket-server.h" #include "module.h" #include "core.h" diff --git a/src/pstream-util.c b/src/pstream-util.c index 82bdaa550..3957e6435 100644 --- a/src/pstream-util.c +++ b/src/pstream-util.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/pstream-util.h b/src/pstream-util.h index 430512603..b3c89eb04 100644 --- a/src/pstream-util.h +++ b/src/pstream-util.h @@ -1,6 +1,27 @@ #ifndef foopstreamutilhfoo #define foopstreamutilhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "pstream.h" #include "tagstruct.h" diff --git a/src/pstream.c b/src/pstream.c index 4a0848f37..3076b776f 100644 --- a/src/pstream.c +++ b/src/pstream.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/pstream.h b/src/pstream.h index 8525cb22b..6b91aeb0b 100644 --- a/src/pstream.h +++ b/src/pstream.h @@ -1,6 +1,27 @@ #ifndef foopstreamhfoo #define foopstreamhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "packet.h" diff --git a/src/queue.c b/src/queue.c index f28b26075..9befd4753 100644 --- a/src/queue.c +++ b/src/queue.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/queue.h b/src/queue.h index e06d69cb1..3ec137345 100644 --- a/src/queue.h +++ b/src/queue.h @@ -1,6 +1,27 @@ #ifndef fooqueuehfoo #define fooqueuehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + struct pa_queue; struct pa_queue* pa_queue_new(void); diff --git a/src/resampler.c b/src/resampler.c index 42555eca5..4f5f6be3b 100644 --- a/src/resampler.c +++ b/src/resampler.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/resampler.h b/src/resampler.h index 1d42b3658..8e979478f 100644 --- a/src/resampler.h +++ b/src/resampler.h @@ -1,6 +1,27 @@ #ifndef fooresamplerhfoo #define fooresamplerhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "sample.h" #include "memblock.h" #include "memchunk.h" diff --git a/src/sample-util.c b/src/sample-util.c index df0b58c81..d608ce1bc 100644 --- a/src/sample-util.c +++ b/src/sample-util.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/sample-util.h b/src/sample-util.h index 4efa59a47..73101ab4b 100644 --- a/src/sample-util.h +++ b/src/sample-util.h @@ -1,6 +1,27 @@ #ifndef foosampleutilhfoo #define foosampleutilhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "sample.h" #include "memblock.h" #include "memchunk.h" diff --git a/src/sample.c b/src/sample.c index 3c93b3764..8179475dd 100644 --- a/src/sample.c +++ b/src/sample.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/sample.h b/src/sample.h index a755b76df..825441f28 100644 --- a/src/sample.h +++ b/src/sample.h @@ -1,6 +1,27 @@ #ifndef foosamplehfoo #define foosamplehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include diff --git a/src/sconv-s16be.c b/src/sconv-s16be.c index 3640b9f70..a4c25cde9 100644 --- a/src/sconv-s16be.c +++ b/src/sconv-s16be.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/sconv-s16be.h b/src/sconv-s16be.h index 257393c6f..d112d9f29 100644 --- a/src/sconv-s16be.h +++ b/src/sconv-s16be.h @@ -1,6 +1,27 @@ #ifndef foosconv_s16befoo #define foosconv_s16befoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + void pa_sconv_s16be_to_float32(unsigned n, const void *a, unsigned an, float *b); void pa_sconv_s16be_from_float32(unsigned n, const float *a, void *b, unsigned bn); diff --git a/src/sconv-s16le.c b/src/sconv-s16le.c index b61ca2bf9..45b28bdb5 100644 --- a/src/sconv-s16le.c +++ b/src/sconv-s16le.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/sconv-s16le.h b/src/sconv-s16le.h index cfbf81fda..0f206ec33 100644 --- a/src/sconv-s16le.h +++ b/src/sconv-s16le.h @@ -1,6 +1,27 @@ #ifndef foosconv_s16lefoo #define foosconv_s16lefoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + void pa_sconv_s16le_to_float32(unsigned n, const void *a, unsigned an, float *b); void pa_sconv_s16le_from_float32(unsigned n, const float *a, void *b, unsigned bn); diff --git a/src/sconv.c b/src/sconv.c index b0a57b770..dd9dd2412 100644 --- a/src/sconv.c +++ b/src/sconv.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/sconv.h b/src/sconv.h index e16f2dcc5..1a62ed20c 100644 --- a/src/sconv.h +++ b/src/sconv.h @@ -1,6 +1,27 @@ #ifndef foosconvhfoo #define foosconvhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "sample.h" typedef void (*pa_convert_to_float32_func_t)(unsigned n, const void *a, unsigned an, float *b); diff --git a/src/sink-input.c b/src/sink-input.c index 7b5801268..5c2d3a139 100644 --- a/src/sink-input.c +++ b/src/sink-input.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/sink-input.h b/src/sink-input.h index 02a2a1172..63dce71d5 100644 --- a/src/sink-input.h +++ b/src/sink-input.h @@ -1,6 +1,27 @@ #ifndef foosinkinputhfoo #define foosinkinputhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "sink.h" diff --git a/src/sink.c b/src/sink.c index 8c48c033d..20fa76a68 100644 --- a/src/sink.c +++ b/src/sink.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/sink.h b/src/sink.h index a25a4377b..2b5d94958 100644 --- a/src/sink.h +++ b/src/sink.h @@ -1,6 +1,27 @@ #ifndef foosinkhfoo #define foosinkhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + struct pa_sink; #include diff --git a/src/sioman.c b/src/sioman.c index a93e8f458..999b8a5c1 100644 --- a/src/sioman.c +++ b/src/sioman.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/sioman.h b/src/sioman.h index e675c80ed..1b60d4a9d 100644 --- a/src/sioman.h +++ b/src/sioman.h @@ -1,6 +1,27 @@ #ifndef foosiomanhfoo #define foosiomanhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + int pa_stdio_acquire(void); void pa_stdio_release(void); diff --git a/src/socket-client.c b/src/socket-client.c index e7ffa33da..a2187e6ae 100644 --- a/src/socket-client.c +++ b/src/socket-client.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/socket-client.h b/src/socket-client.h index 857537888..2a89210e6 100644 --- a/src/socket-client.h +++ b/src/socket-client.h @@ -1,6 +1,27 @@ #ifndef foosocketclienthfoo #define foosocketclienthfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "mainloop-api.h" #include "iochannel.h" diff --git a/src/socket-server.c b/src/socket-server.c index 193b3c483..0f497377d 100644 --- a/src/socket-server.c +++ b/src/socket-server.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/socket-server.h b/src/socket-server.h index dbce172e0..6661a66ed 100644 --- a/src/socket-server.h +++ b/src/socket-server.h @@ -1,6 +1,27 @@ #ifndef foosocketserverhfoo #define foosocketserverhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "mainloop-api.h" #include "iochannel.h" diff --git a/src/socket-util.c b/src/socket-util.c index c2bb277ea..e0a3c28d2 100644 --- a/src/socket-util.c +++ b/src/socket-util.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/socket-util.h b/src/socket-util.h index 0133bfc3b..85133febd 100644 --- a/src/socket-util.h +++ b/src/socket-util.h @@ -1,6 +1,27 @@ #ifndef foosocketutilhfoo #define foosocketutilhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include void pa_socket_peer_to_string(int fd, char *c, size_t l); diff --git a/src/source-output.c b/src/source-output.c index 7b93bcb35..2705fdb3c 100644 --- a/src/source-output.c +++ b/src/source-output.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/source-output.h b/src/source-output.h index a8ea5a9f6..0e6e2cfdf 100644 --- a/src/source-output.h +++ b/src/source-output.h @@ -1,6 +1,27 @@ #ifndef foosourceoutputhfoo #define foosourceoutputhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "source.h" diff --git a/src/source.c b/src/source.c index fe7cf16e2..ccde0e2f9 100644 --- a/src/source.c +++ b/src/source.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/source.h b/src/source.h index 9e57bc0fb..9c584a6de 100644 --- a/src/source.h +++ b/src/source.h @@ -1,6 +1,27 @@ #ifndef foosourcehfoo #define foosourcehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + struct pa_source; #include diff --git a/src/strbuf.c b/src/strbuf.c index 44fa5b405..c6a3772db 100644 --- a/src/strbuf.c +++ b/src/strbuf.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/strbuf.h b/src/strbuf.h index 0e9bb5e36..d672c42a4 100644 --- a/src/strbuf.h +++ b/src/strbuf.h @@ -1,6 +1,27 @@ #ifndef foostrbufhfoo #define foostrbufhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + struct pa_strbuf; struct pa_strbuf *pa_strbuf_new(void); diff --git a/src/tagstruct.c b/src/tagstruct.c index 50854c28c..0d93c1e90 100644 --- a/src/tagstruct.c +++ b/src/tagstruct.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/tagstruct.h b/src/tagstruct.h index 2c1ae5874..aefd03c4a 100644 --- a/src/tagstruct.h +++ b/src/tagstruct.h @@ -1,6 +1,27 @@ #ifndef footagstructhfoo #define footagstructhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include diff --git a/src/tokenizer.c b/src/tokenizer.c index bdd05e447..c7f18d267 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/tokenizer.h b/src/tokenizer.h index 160b23e0d..7d1cf9b5e 100644 --- a/src/tokenizer.h +++ b/src/tokenizer.h @@ -1,6 +1,27 @@ #ifndef footokenizerhfoo #define footokenizerhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + struct pa_tokenizer; struct pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args); diff --git a/src/util.c b/src/util.c index a13679a2c..6e75c240c 100644 --- a/src/util.c +++ b/src/util.c @@ -1,3 +1,24 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #ifdef HAVE_CONFIG_H #include #endif diff --git a/src/util.h b/src/util.h index 3e4944347..96fde11c2 100644 --- a/src/util.h +++ b/src/util.h @@ -1,6 +1,27 @@ #ifndef fooutilhfoo #define fooutilhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include void pa_make_nonblock_fd(int fd); From cf965cbda8a9330baf7a45dbea8ea9499a0e4e96 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 20:02:44 +0000 Subject: [PATCH 0083/1514] add missing liecenses git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@84 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 9 +++++---- src/Makefile.am | 9 +++++---- src/depmod.py | 17 +++++++++++++++++ src/polypaudio.run | 24 +++++++++++++++++++++--- src/todo | 6 +++--- 5 files changed, 51 insertions(+), 14 deletions(-) diff --git a/Makefile.am b/Makefile.am index 7266cba57..c03548b21 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,8 +2,8 @@ # # This file is part of polypaudio. # -# polypaudio is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by +# polypaudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -13,8 +13,9 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with polypaudio; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# along with polypaudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. EXTRA_DIST = bootstrap.sh SUBDIRS=src diff --git a/src/Makefile.am b/src/Makefile.am index 8b5e80f03..c2ede9f38 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,8 +2,8 @@ # # This file is part of polypaudio. # -# polypaudio is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by +# polypaudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -13,8 +13,9 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with polypaudio; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# along with polypaudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. AM_CFLAGS=-ansi -D_GNU_SOURCE diff --git a/src/depmod.py b/src/depmod.py index d11cceb41..85dc66a8f 100755 --- a/src/depmod.py +++ b/src/depmod.py @@ -1,5 +1,22 @@ #!/usr/bin/python # $Id$ +# +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. import sys, os, string diff --git a/src/polypaudio.run b/src/polypaudio.run index 25af2df6f..177707ba7 100755 --- a/src/polypaudio.run +++ b/src/polypaudio.run @@ -1,10 +1,28 @@ #!./polypaudio -F +# +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + # Load audio drivers -#load module-alsa-sink -#load module-alsa-source device=plughw:1,0 +load module-alsa-sink +load module-alsa-source device=plughw:1,0 #load module-oss device="/dev/dsp" -load module-oss-mmap device="/dev/dsp" +#load module-oss-mmap device="/dev/dsp" # Load several protocols load module-esound-protocol-tcp diff --git a/src/todo b/src/todo index c3414fe5a..685173383 100644 --- a/src/todo +++ b/src/todo @@ -1,9 +1,9 @@ -- config.h -- svn-id and license in every file +*** $Id$ *** + - documentation - pkgconfig --- post 0.1 +*** post 0.1 *** - future cancellation - client-ui - clip cache From 3e379ca99d44c84b2117ac048ee6e84fc2837280 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jul 2004 20:58:18 +0000 Subject: [PATCH 0084/1514] add pkgconfig stuff git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@85 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 3 ++ configure.ac | 4 +- polyplib-error.pc.in | 10 +++++ polyplib-mainloop.pc.in | 10 +++++ polyplib-simple.pc.in | 10 +++++ polyplib.pc.in | 10 +++++ src/Makefile.am | 92 ++++++++++++++++++++++++++++++++++++++--- 7 files changed, 132 insertions(+), 7 deletions(-) create mode 100644 polyplib-error.pc.in create mode 100644 polyplib-mainloop.pc.in create mode 100644 polyplib-simple.pc.in create mode 100644 polyplib.pc.in diff --git a/Makefile.am b/Makefile.am index c03548b21..dc7024a4a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,5 +20,8 @@ EXTRA_DIST = bootstrap.sh SUBDIRS=src +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc + distcleancheck: @: diff --git a/configure.ac b/configure.ac index 19e813d9a..e73cb0333 100644 --- a/configure.ac +++ b/configure.ac @@ -55,5 +55,7 @@ if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -Wall -W -Wno-unused-parameter" fi -AC_CONFIG_FILES([Makefile src/Makefile]) +AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) + +AC_CONFIG_FILES([Makefile src/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc]) AC_OUTPUT diff --git a/polyplib-error.pc.in b/polyplib-error.pc.in new file mode 100644 index 000000000..b5289959e --- /dev/null +++ b/polyplib-error.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: polyplib-error +Description: Error library for the polypaudio sound daemon +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lpolyp-error +Cflags: -D_REENTRANT -I${includedir} diff --git a/polyplib-mainloop.pc.in b/polyplib-mainloop.pc.in new file mode 100644 index 000000000..f4bdba5bd --- /dev/null +++ b/polyplib-mainloop.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: polyplib-mainloop +Description: Mainloop API of the polypaudio sound daemon +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lpolyp-mainloop +Cflags: -D_REENTRANT -I${includedir} diff --git a/polyplib-simple.pc.in b/polyplib-simple.pc.in new file mode 100644 index 000000000..efae94103 --- /dev/null +++ b/polyplib-simple.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: polyplib-simple +Description: Simplistic client interface to polypaudio sound daemon +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lpolyp-simple +Cflags: -D_REENTRANT -I${includedir} diff --git a/polyplib.pc.in b/polyplib.pc.in new file mode 100644 index 000000000..8a554cb14 --- /dev/null +++ b/polyplib.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: polyplib +Description: Client interface to polypaudio sound daemon +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lpolyp +Cflags: -D_REENTRANT -I${includedir} diff --git a/src/Makefile.am b/src/Makefile.am index c2ede9f38..86f86a5de 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,6 +23,15 @@ EXTRA_DIST = polypaudio.run depmod.py bin_PROGRAMS = polypaudio pacat pactl noinst_PROGRAMS = pacat-simple parec-simple +pkginclude_HEADERS=polyplib.h \ + polyplib-def.h \ + polyplib-simple.h \ + polyplib-error.h \ + mainloop-api.h \ + mainloop.h \ + mainloop-signal.h \ + sample.h + pkglib_LTLIBRARIES=libiochannel.la \ libsocket-server.la \ libsocket-client.la \ @@ -54,8 +63,9 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-esound-protocol-tcp.la \ module-esound-protocol-unix.la \ module-native-protocol-tcp.la \ - module-native-protocol-unix.la \ - libpolyp.la \ + module-native-protocol-unix.la + +lib_LTLIBRARIES=libpolyp.la \ libpolyp-simple.la \ libpolyp-error.la \ libpolyp-mainloop.la @@ -267,18 +277,88 @@ libpolyp_simple_la_SOURCES = polyplib-simple.c polyplib-simple.h libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) libpolyp_simple_la_LIBADD = libpolyp.la libpolyp-mainloop.la -pacat_SOURCES = pacat.c #$(libpolyp_la_SOURCES) $(libpolyp_error_la_SOURCES) +pacat_SOURCES = pacat.c pacat_LDADD = libpolyp.la libpolyp-error.la libpolyp-mainloop.la pacat_CFLAGS = $(AM_CFLAGS) -pactl_SOURCES = pactl.c #$(libpolyp_la_SOURCES) $(libpolyp_error_la_SOURCES) +pactl_SOURCES = pactl.c pactl_LDADD = libpolyp.la libpolyp-error.la libpolyp-mainloop.la pactl_CFLAGS = $(AM_CFLAGS) -pacat_simple_SOURCES = pacat-simple.c #$(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) +pacat_simple_SOURCES = pacat-simple.c pacat_simple_LDADD = libpolyp-simple.la libpolyp-error.la pacat_simple_CFLAGS = $(AM_CFLAGS) -parec_simple_SOURCES = parec-simple.c #$(libpolyp_la_SOURCES) $(libpolyp_simple_la_SOURCES) $(libpolyp_error_la_SOURCES) +parec_simple_SOURCES = parec-simple.c parec_simple_LDADD = libpolyp-simple.la libpolyp-error.la parec_simple_CFLAGS = $(AM_CFLAGS) + +if BUILD_LIBPOLYPCORE + +pkginclude_HEADERS+=cli-command.h\ + client.h \ + core.h \ + dynarray.h \ + endianmacros.h \ + hashmap.h \ + idxset.h \ + iochannel.h \ + memblock.h \ + memblockq.h \ + memchunk.h \ + modargs.h \ + module.h \ + namereg.h \ + queue.h \ + resampler.h \ + sample-util.h \ + sink.h \ + sink-input.h \ + sioman.h \ + socket-server.h \ + socket-client.h \ + socket-util.h \ + source.h \ + source-output.h \ + strbuf.h \ + tokenizer.h \ + tagstruct.h \ + util.h + +lib_LTLIBRARIES+= libpolypcore.la + +libpolypcore_la_SOURCES = idxset.c idxset.h \ + queue.c queue.h \ + strbuf.c strbuf.h \ + mainloop.c mainloop.h \ + memblock.c memblock.h \ + sample.c sample.h \ + sample-util.c sample-util.h \ + memblockq.c memblockq.h \ + client.c client.h \ + core.c core.h \ + source-output.c source-output.h \ + sink-input.c sink-input.h \ + source.c source.h \ + sink.c sink.h \ + module.c module.h \ + mainloop-signal.c mainloop-signal.h \ + mainloop-api.c mainloop-api.h \ + util.c util.h \ + hashmap.c hashmap.h \ + namereg.c namereg.h \ + sconv.c sconv.h \ + resampler.c resampler.h \ + endianmacros.h \ + memchunk.c memchunk.h \ + sconv-s16le.c sconv-s16le.h \ + sconv-s16be.c sconv-s16be.h \ + sioman.c sioman.h \ + modargs.c modargs.h \ + cmdline.c cmdline.h \ + cli-command.c cli-command.h \ + clitext.c clitext.h \ + tokenizer.c tokenizer.h \ + dynarray.c dynarray.h + +endif From 7b8c329578d642d31618d487b97864306c43073c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 14:06:13 +0000 Subject: [PATCH 0085/1514] add documentation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@86 fefdeb5f-60dc-0310-8127-8f9354f1896f --- LICENSE | 340 +++++++++++++++++++++++++++++++++++++ Makefile.am | 21 ++- configure.ac | 21 ++- doc/Makefile.am | 39 +++++ doc/README.html.in | 133 +++++++++++++++ doc/cli.html.in | 152 +++++++++++++++++ doc/daemon.html.in | 51 ++++++ doc/modules.html.in | 191 +++++++++++++++++++++ doc/style.css | 34 ++++ src/Makefile.am | 1 - src/modargs.c | 6 +- src/module-protocol-stub.c | 2 +- src/todo | 1 - 13 files changed, 985 insertions(+), 7 deletions(-) create mode 100644 LICENSE create mode 100644 doc/Makefile.am create mode 100644 doc/README.html.in create mode 100644 doc/cli.html.in create mode 100644 doc/daemon.html.in create mode 100644 doc/modules.html.in create mode 100644 doc/style.css diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..d60c31a97 --- /dev/null +++ b/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Makefile.am b/Makefile.am index dc7024a4a..43009b443 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,11 +17,28 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh -SUBDIRS=src +EXTRA_DIST = bootstrap.sh README LICENSE +SUBDIRS=src doc + +MAINTAINERCLEANFILES=README +noinst_DATA = README pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc +README: + rm -f README + $(MAKE) -C doc README + cd $(srcdir) && ln -s doc/README README + +homepage: all dist + test -d $$HOME/homepage/private + mkdir -p $$HOME/homepage/private/projects/polypaudio + cp *.tar.gz $$HOME/homepage/private/projects/polypaudio + cp doc/README.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css doc/NEWS $$HOME/homepage/private/projects/polypaudio + cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html + distcleancheck: @: + +.PHONY: homepage distcleancheck diff --git a/configure.ac b/configure.ac index e73cb0333..86398f4dd 100644 --- a/configure.ac +++ b/configure.ac @@ -55,7 +55,26 @@ if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -Wall -W -Wno-unused-parameter" fi +# LYNX documentation generation +AC_ARG_ENABLE(lynx, + AS_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation), +[case "${enableval}" in + yes) lynx=yes ;; + no) lynx=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-lynx) ;; +esac],[lynx=yes]) + +if test x$lynx = xyes ; then + AC_CHECK_PROG(have_lynx, lynx, yes, no) + + if test x$have_lynx = xno ; then + AC_MSG_ERROR([*** Sorry, you have to install lynx or use --disable-lynx ***]) + fi +fi + +AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) + AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) -AC_CONFIG_FILES([Makefile src/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc]) +AC_CONFIG_FILES([Makefile src/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html]) AC_OUTPUT diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 000000000..015d503dd --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,39 @@ +# $Id$ + +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +noinst_DATA = README.html cli.html modules.html daemon.html README +EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in + +MAINTAINERCLEANFILES = README README.html cli.html modules.html daemon.html +CLEANFILES = + +if USE_LYNX +README: README.html + lynx --dump $^ | sed 's,file://localhost/.*/doc/README.html,README,' > $@ + +CLEANFILES += README +endif + +tidy: README.html cli.html modules.html daemon.html + tidy -e < README.html + tidy -e < cli.html + tidy -e < modules.html + tidy -e < daemon.html + +.PHONY: tidy + diff --git a/doc/README.html.in b/doc/README.html.in new file mode 100644 index 000000000..a9b07d60c --- /dev/null +++ b/doc/README.html.in @@ -0,0 +1,133 @@ + + + + + +polypaudio @PACKAGE_VERSION@ + + + + +

polypaudio @PACKAGE_VERSION@

+ +

Copyright 2002-2004 Lennart Poettering <@PACKAGE_BUGREPORT@>

+ + + +

License

+ +

This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version.

+ +

This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details.

+ +

You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

+ +

News

+ + +
Sat Jul 17 2004:

Version 0.1 released

+ +

Overview

+ +

polypaudio is a sound server for Linux and other Unix like +operating systems. It is intended to be an improved drop-in +replacement for the Enlightened Sound +Daemon (ESOUND). In addition to the features ESOUND provides +polypaudio has:

+ +
    +
  • Extensible plugin architecture (dlopen())
  • +
  • Support for more than one sink/source
  • +
  • Better low latency behaviour
  • +
  • Embedabble into other software (the core is available as C library)
  • +
  • Completely asynchronous C API
  • +
  • Simple command line interface for reconfiguring the daemon while running
  • +
  • Flexible, implicit sample type conversion and resampling
  • +
  • "Zero-Copy" architecture
  • +
+ +

Both the core and the client API are completely asynchronous making +use of a simple main loop abstraction layer. This allows easy +integration with asynchronous applications using the +glib/gtk mainloop. Since the asynchronous API +available through polyplib is quite difficult to use there is +a simplified synchronous API wrapper polyplib-simple +available.

+ +

Status

+ +

Version @PACKAGE_VERSION@ is quite usable. polypaudio does +not yet match all ESOUND features: currently a sample cache and +automatic releasing of unused sound drivers are missing. Have a look on the more extensive TODO list.

+ +

Documentation

+ +

There is some prelimenary documentation available: modules.html, cli.html, daemeon.html.

+ +

Documentation for developing with polypaudio is not yet +available. Read the source, Luke!

+ +

Requirements

+ +

Currently, polypaudio is tested on Linux only. It requires an OSS or ALSA compatible soundcard.

+ +

polypaudio was developed and tested on Debian GNU/Linux +"testing" from July 2004, it should work on most other Linux +distributions (and maybe Unix versions) since it uses GNU autoconf and +GNU libtool for source code configuration and shared library +management.

+ +

polypaudio needs Secret Rabbit Code (aka libsamplerate) and alsa-lib.

+ +

Installation

+ +

As this package is made with the GNU autotools you should run +./configure inside the distribution directory for configuring +the source tree. After that you should run make for +compilation and make install (as root) for installation of +polypaudio.

+ +

Acknowledgements

+ +

Eric B. Mitchell for writing ESOUND

+ +

Download

+ +

The newest release is always available from @PACKAGE_URL@

+ +

The current release is @PACKAGE_VERSION@

+ +

Get polypaudio's development sources from the Subversion repository. (viewcvs)

+ +

If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

+ +
+
Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2004
+
$Id$
+ + + diff --git a/doc/cli.html.in b/doc/cli.html.in new file mode 100644 index 000000000..c67d78db7 --- /dev/null +++ b/doc/cli.html.in @@ -0,0 +1,152 @@ + + + + +polypaudio: Simple Command Line Language + + + + +

Simple Command Line Language

+ +

polypaudio provides a simple command line language used by +configuration scripts as well as the modules module-cli +and module-cli-protocol-{unix,tcp}. Empty lines and lines +beginning with a hashmark (#) are silently ignored. Several +commands are supported:

+ +

Miscellaneous Commands

+ +

help

+ +

Show a quick help on the commands available.

+ +

exit

+ +

Terminate the daemon. If you want to terminate a CLI connection +("log out") you might want to use C-d.

+ +

Status Commands

+ +

modules

+ +

Show all currently loaded modules with their arguments.

+ +

sinks/sources

+ +

Show all currently registered sinks (resp. sources).

+ +

clients

+ +

Show all currently active clients.

+ +

sink_inputs/sink_outputs

+ +

Show all currently active inputs to sinks (resp. outputs of sources).

+ +

stat

+ +

Show some simple statistics about the allocated memory blocks and +the space used by them.

+ +

info

+ +

A combination of all status commands described above. ls +and list are synonyms for info.

+ +

Module Management

+ +

load

+ +

Load a module specified by its name and arguments. For most modules +it is OK to be loaded more than once.

+ +

unload

+ +

Unload a module specified by its index in the module list as +returned by modules.

+ +

Configuration Commands

+ +

sink_volume

+ +

Set the volume of the specified sink. You may specify the sink either +by its index in the sink list or by its name. The volume should be an +integer value greater or equal than 0 (= muted). Volume 256 +(0x100) is normal volume, values greater than this amplify +the audio signal with clipping.

+ +

sink_input_volume

+ +

Set the volume of a sink input specified by its index the the sink +input list. The same volume rules apply as with sink_volume.

+ +

sink_default/source_default

+ +

Make a sink (resp. source) the default. You may specify the sink +(resp. ssource) by its index in the sink (resp. source) list or by its +name.

+ +

Killing clients/streams

+ +

kill_client

+ +

Remove a client forcibly from the server. There is no protection that +the client reconnects immediately.

+ +

kill_sink_input/kill_source_output

+ +

Remove a sink input (resp. source output) forcibly from the +server. This will not remove the owning client or any other streams +opened by the client from the server.

+ +

Meta Commands

+ +

In addition the the commands described above there a few meta +directives supported by the command line interpreter:

+ +

.include

+ +

Executes the commands from the specified script file.

+ +

.fail/.nofail

+ +

Enable (resp. disable) that following failing commands will cancel +the execution of the current script file. This is a ignored when used +on the interactive command line.

+ +

.verbose/.noverbose

+

Enable (resp. disable) extra verbosity.

+ +

Example Configuration Script

+ +
+#!/usr/bin/polaudio -F
+
+# Load audio drivers
+load module-alsa-sink device=plughw:0,0 rate=48000
+load module-alsa-source device=hw:1,0
+
+# Load several protocols
+load module-esound-protocol-tcp
+load module-simple-protocol-tcp
+load module-native-protocol-unix
+load module-cli-protocol-unix
+
+# Load the CLI module (This is similar to passing "-C" on the command line of polypaudio)
+load module-cli
+
+.nofail
+
+# Make some devices default
+sink_default alsa_output
+source_default alsa_input
+
+# Use digital amplification
+sink_volume alsa_output 0x200
+
+ +
+
Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2004
+
$Id$
+ diff --git a/doc/daemon.html.in b/doc/daemon.html.in new file mode 100644 index 000000000..a5d933dbc --- /dev/null +++ b/doc/daemon.html.in @@ -0,0 +1,51 @@ + + + + +polypaudio: Daemon + + + + +

Daemon

+ +

Command Line Arguments

+ +The polypaudio daemon accepts several command line arguments: + +

-L MODULE: Load the specified module. This option may be specified more than once.

+

-F FILE: Run the specified script. This option may be specified more than once.

+

-C: Load the module module-cli after startup.

+

-D: Daemonize after successfully executing all scripts and loading all modules.

+

-f: Unless this option is given the daemon will terminate if any of the specified modules failed to load or the script didn't execute successfully.

+

-v: Increase the verbosity of the daemon.

+

-h: Show a quick help.

+ +

Example

+ +

It is a good idea to run the daemon like this:

+ +
polypaudio -D -F /etc/polypaudio/polypaudio.pa
+ +

/etc/polypaudio/polypaudio.pa should be a script written in the CLI language described in cli.html + +

Signals

+ +

The following signals are trapped specially:

+ +

SIGINT

+ +

The daemon is shut down cleanly.

+ +

SIGUSR1

+ +

The daemon tries to load the module module-cli, effectively providing a command line interface on the calling TTY.

+ +

SIGUSR2

+ +

The daemon tries to load the module module-cli-protocol-unix, effectively providing a command line interface on a special UNIX domain socket.

+ +
+
Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2004
+
$Id$
+ diff --git a/doc/modules.html.in b/doc/modules.html.in new file mode 100644 index 000000000..6954418fb --- /dev/null +++ b/doc/modules.html.in @@ -0,0 +1,191 @@ + + + + +polypaudio: Loadable Modules + + + + + +

Loadable Modules

+ +

The following loadable modules are provided with the polypaudio distribution:

+ +

Device Drivers

+ +

All device driver modules support the following parameters:

+ + + + + +
format=The sample format (one of u8, s16, s16le, s16le, float32, float32be, float32le, alaw, ulaw) (defaults to s16)
rate=The sample rate (defaults to 44100)
channels=Audio channels (defaults to 2)
sink_name=, source_name=Name for the sink (resp. source)
+ +

module-pipe-sink

+ +

Provides a simple test sink that writes the audio data to a FIFO +special file in the file system. The sink name defaults to pipe_output.

+ +

The following option is supported:

+ + + +
file=The name of the FIFO special file to use
+ + + +

module-alsa-sink

+ +

Provides a playback sink for devices supported by the Advanced Linux +Sound Architecture (ALSA). The sink name defaults to alsa_output.

+ +

In addition to the general device driver options described above this module supports:

+ + + + + +
device=The ALSA device to use. (defaults to "plughw:0,0")
fragments=The desired fragments when opening the device. (defaults to 12)
fragment_size=The desired fragment size in bytes when opening the device (defaults to 1024)
+ +

module-alsa-source

+ +

Provides a recording source for devices supported by the Advanced +Linux Sound Architecture (ALSA). The source name defaults to alsa_input.

+ +

This module supports device=, fragments= and fragment_size= arguments the same way as module-alsa-sink.

+ + + +

module-oss

+ +

Provides both a sink and a source for playback, resp. recording on +Open Sound System (OSS) compatible devices.

+ +

This module supports device= (which defaults to /dev/dsp), fragments= and fragment_size= arguments the same way as module-alsa-sink.

+ +

In addition this module supports the following options:

+ + + + +
record=Accepts a binary numerical value for enabling (resp. disabling) the recording on this device. (defaults: to 1)
playback=Accepts a binary numerical value for enabling (resp. disabling) the playback on this device. (defaults: to 1)
+ +

The sink name (resp. source name) defaults to oss_output (resp. oss_input).

+ +

module-oss-mmap

+ +

Similar to module-oss but uses memory mapped +(mmap()) access to the input/output buffers of the audio +device. This provides better latency behaviour but is not as +compatible as module-oss.

+ +

This module accepts exactly the same arguments as module-oss.

+ +

Protocols

+ + + +

module-cli

+ +

Provides the user with a simple command line interface on the +controlling TTY of the daemon. This module may not be loaded more than +once.

+ +

For an explanation of the simple command line language used by this +module see cli.html. + +

This module doesn't accept any arguments.

+ + + + + +

module-cli-protocol-{unix,tcp}

+ +

An implemenation of a simple command line based protocol for +controlling the polypaudio daemon. If loaded, the user may +connect with tools like netcat, telnet or +bidilink to the listening sockets and execute commands the +same way as with module-cli.

+ +

Beware! Users are not authenticated when connecting to this +service.

+ +

This module exists in two versions: with the suffix -unix +the service will listen on an UNIX domain socket in the local file +system. With the suffix -tcp it will listen on a network +transparent TCP/IP socket.

+ +

This module supports the following options:

+ + + + + +
port=(only for -tcp) The port number to listen on (defaults to 4712)
loopback=(only for -tcp) Accepts +a numerical binary value. If 1 the socket is bound to the loopback +device, i.e. not publicly accessible. (defaults to 1)
socket=(only for -unix) The UNIX socket name (defaults to /tmp/polypaudio/cli)
+ +

module-simple-protocol-{unix,tcp}

+ +

An implementation of a simple protocol which allows playback by using +simple tools like netcat. Just connect to the listening +socket of this module and write the audio data to it, or read it from +it for playback, resp. recording.

+ +

Beware! Users are not authenticated when connecting to this +service.

+ +

See module-cli-protocol-{unix,tcp} for more information +about the two possible suffixes of this module.

+ +

In addition to the options supported by module-cli-protocol-*, this module supports:

+ + + + + +
rate=, format=, channels=Sample format for streams connecting to this service.
playback=, record=Enable/disable playback/recording
sink=, source=Specify the sink/source this service connects to
+ +

module-esound-protocol-{unix,tcp}

+ +

An implemenation of a protocol compatible with the Enlightened Sound +Daemon (ESOUND, esd). When you load this module you may +access the polypaudio daemon with tools like esdcat, +esdrec or even esdctl. Many applications, such as +XMMS, include support for this protocol.

+ +

See module-cli-protocol-{unix,tcp} for more information +about the two possible suffixes of this module.

+ +

In addition to the options supported by module-cli-protocol-*, this module supports:

+ + + + + +
sink=, source=Specify the sink/source this service connects to
public=If set to 0 not authentication is required to connect to the service
cookie=Name of the cookie file for authentication purposes
+ +

This implementation misses some features the original ESOUND has: e.g. there is no sample cache yet. However: XMMS works fine.

+ +

module-native-protocol-{unix,tcp}

+ +

The native protocol of polypaudio.

+ +

See module-cli-protocol-{unix,tcp} for more information +about the two possible suffixes of this module.

+ +

In addition to the options supported by module-cli-protocol-*, this module supports:

+ + + + +
public=If set to 0 not authentication is required to connect to the service
cookie=Name of the cookie file for authentication purposes
+ + +
+
Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2004
+
$Id$
+ diff --git a/doc/style.css b/doc/style.css new file mode 100644 index 000000000..e54a15a35 --- /dev/null +++ b/doc/style.css @@ -0,0 +1,34 @@ +/* $Id$ */ + +/*** + * This file is part of polypaudio. + * + * polypaudio is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * polypaudio is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with polypaudio; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + ***/ + +body { color: black; background-color: white; margin: 0.5cm; } +a:link, a:visited { color: #900000; } +p { margin-left: 0.5cm; margin-right: 0.5cm; } +div.news-date { margin-left: 0.5cm; font-size: 80%; color: #4f0000; } +p.news-text { margin-left: 1cm; } +h1 { color: #00009F; } +h2 { color: #00009F; } +h3 { color: #00004F; margin-left: 0.5cm; } +ul { margin-left: .5cm; } +ol { margin-left: .5cm; } +pre { margin-left: .5cm; background-color: #f0f0f0; padding: 0.4cm;} +.grey { color: #afafaf; } +table { margin-left: 1cm; border:1px solid lightgrey; padding: 0.2cm; } +td { padding-left:10px; padding-right:10px; } diff --git a/src/Makefile.am b/src/Makefile.am index 86f86a5de..c4da73427 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -355,7 +355,6 @@ libpolypcore_la_SOURCES = idxset.c idxset.h \ sconv-s16be.c sconv-s16be.h \ sioman.c sioman.h \ modargs.c modargs.h \ - cmdline.c cmdline.h \ cli-command.c cli-command.h \ clitext.c clitext.h \ tokenizer.c tokenizer.h \ diff --git a/src/modargs.c b/src/modargs.c index da2bab878..280a546d2 100644 --- a/src/modargs.c +++ b/src/modargs.c @@ -231,8 +231,12 @@ int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss ss.format = PA_SAMPLE_S16NE; else if (strcmp(format, "u8") == 0 || strcmp(format, "8") == 0) ss.format = PA_SAMPLE_U8; - else if (strcmp(format, "float32") == 0) + else if (strcmp(format, "float32") == 0 || strcmp(format, "float32ne") == 0) ss.format = PA_SAMPLE_FLOAT32; + else if (strcmp(format, "float32le") == 0) + ss.format = PA_SAMPLE_FLOAT32LE; + else if (strcmp(format, "float32be") == 0) + ss.format = PA_SAMPLE_FLOAT32BE; else if (strcmp(format, "ulaw") == 0) ss.format = PA_SAMPLE_ULAW; else if (strcmp(format, "alaw") == 0) diff --git a/src/module-protocol-stub.c b/src/module-protocol-stub.c index 545de3e85..3ce18c315 100644 --- a/src/module-protocol-stub.c +++ b/src/module-protocol-stub.c @@ -89,7 +89,7 @@ static const char* const valid_modargs[] = { static struct pa_socket_server *create_socket_server(struct pa_core *c, struct pa_modargs *ma) { struct pa_socket_server *s; #ifdef USE_TCP_SOCKETS - uint32_t loopback = 0, port = IPV4_PORT; + uint32_t loopback = 1, port = IPV4_PORT; if (pa_modargs_get_value_u32(ma, "loopback", &loopback) < 0) { fprintf(stderr, "loopback= expects a numerical argument.\n"); diff --git a/src/todo b/src/todo index 685173383..5b944a360 100644 --- a/src/todo +++ b/src/todo @@ -1,7 +1,6 @@ *** $Id$ *** - documentation -- pkgconfig *** post 0.1 *** - future cancellation From 539eb0202cc01d2b8e0d8ea53a754a007fa0e177 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 14:08:07 +0000 Subject: [PATCH 0086/1514] ignore README git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@87 fefdeb5f-60dc-0310-8127-8f9354f1896f From 86f5b30e10773c3421486bf06062b416e2bfd5c1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 14:08:26 +0000 Subject: [PATCH 0087/1514] move todo file git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@88 fefdeb5f-60dc-0310-8127-8f9354f1896f --- {src => doc}/todo | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {src => doc}/todo (100%) diff --git a/src/todo b/doc/todo similarity index 100% rename from src/todo rename to doc/todo From 563201e128d600ec1ae4a33ca81d03b776501f82 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 14:09:41 +0000 Subject: [PATCH 0088/1514] rename configuration file make sure the todo file is packaged git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@89 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/Makefile.am | 2 +- src/{polypaudio.run => polypaudio.pa} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{polypaudio.run => polypaudio.pa} (100%) diff --git a/doc/Makefile.am b/doc/Makefile.am index 015d503dd..d88451f5e 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -17,7 +17,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. noinst_DATA = README.html cli.html modules.html daemon.html README -EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in +EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in todo MAINTAINERCLEANFILES = README README.html cli.html modules.html daemon.html CLEANFILES = diff --git a/src/polypaudio.run b/src/polypaudio.pa similarity index 100% rename from src/polypaudio.run rename to src/polypaudio.pa From 41f6aea8fdbc744c13bc461056a2d694a5c4d06f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 14:12:30 +0000 Subject: [PATCH 0089/1514] rename src to polyp git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@90 fefdeb5f-60dc-0310-8127-8f9354f1896f --- {src => polyp}/Makefile.am | 0 {src => polyp}/alsa-util.c | 0 {src => polyp}/alsa-util.h | 0 {src => polyp}/authkey.c | 0 {src => polyp}/authkey.h | 0 {src => polyp}/cli-command.c | 0 {src => polyp}/cli-command.h | 0 {src => polyp}/cli.c | 0 {src => polyp}/cli.h | 0 {src => polyp}/client.c | 0 {src => polyp}/client.h | 0 {src => polyp}/clitext.c | 0 {src => polyp}/clitext.h | 0 {src => polyp}/cmdline.c | 0 {src => polyp}/cmdline.h | 0 {src => polyp}/core.c | 0 {src => polyp}/core.h | 0 {src => polyp}/depmod.py | 0 {src => polyp}/dynarray.c | 0 {src => polyp}/dynarray.h | 0 {src => polyp}/endianmacros.h | 0 {src => polyp}/esound.h | 0 {src => polyp}/hashmap.c | 0 {src => polyp}/hashmap.h | 0 {src => polyp}/idxset.c | 0 {src => polyp}/idxset.h | 0 {src => polyp}/iochannel.c | 0 {src => polyp}/iochannel.h | 0 {src => polyp}/ioline.c | 0 {src => polyp}/ioline.h | 0 {src => polyp}/main.c | 0 {src => polyp}/mainloop-api.c | 0 {src => polyp}/mainloop-api.h | 0 {src => polyp}/mainloop-signal.c | 0 {src => polyp}/mainloop-signal.h | 0 {src => polyp}/mainloop.c | 0 {src => polyp}/mainloop.h | 0 {src => polyp}/memblock.c | 0 {src => polyp}/memblock.h | 0 {src => polyp}/memblockq.c | 0 {src => polyp}/memblockq.h | 0 {src => polyp}/memchunk.c | 0 {src => polyp}/memchunk.h | 0 {src => polyp}/modargs.c | 0 {src => polyp}/modargs.h | 0 {src => polyp}/module-alsa-sink.c | 0 {src => polyp}/module-alsa-source.c | 0 {src => polyp}/module-cli.c | 0 {src => polyp}/module-oss-mmap.c | 0 {src => polyp}/module-oss.c | 0 {src => polyp}/module-pipe-sink.c | 0 {src => polyp}/module-protocol-stub.c | 0 {src => polyp}/module.c | 0 {src => polyp}/module.h | 0 {src => polyp}/namereg.c | 0 {src => polyp}/namereg.h | 0 {src => polyp}/native-common.h | 0 {src => polyp}/oss-util.c | 0 {src => polyp}/oss-util.h | 0 {src => polyp}/pacat-simple.c | 0 {src => polyp}/pacat.c | 0 {src => polyp}/packet.c | 0 {src => polyp}/packet.h | 0 {src => polyp}/pactl.c | 0 {src => polyp}/parec-simple.c | 0 {src => polyp}/pdispatch.c | 0 {src => polyp}/pdispatch.h | 0 {src => polyp}/polypaudio.pa | 0 {src => polyp}/polyplib-def.h | 0 {src => polyp}/polyplib-error.c | 0 {src => polyp}/polyplib-error.h | 0 {src => polyp}/polyplib-simple.c | 0 {src => polyp}/polyplib-simple.h | 0 {src => polyp}/polyplib.c | 0 {src => polyp}/polyplib.h | 0 {src => polyp}/protocol-cli.c | 0 {src => polyp}/protocol-cli.h | 0 {src => polyp}/protocol-esound.c | 0 {src => polyp}/protocol-esound.h | 0 {src => polyp}/protocol-native.c | 0 {src => polyp}/protocol-native.h | 0 {src => polyp}/protocol-simple.c | 0 {src => polyp}/protocol-simple.h | 0 {src => polyp}/pstream-util.c | 0 {src => polyp}/pstream-util.h | 0 {src => polyp}/pstream.c | 0 {src => polyp}/pstream.h | 0 {src => polyp}/queue.c | 0 {src => polyp}/queue.h | 0 {src => polyp}/resampler.c | 0 {src => polyp}/resampler.h | 0 {src => polyp}/sample-util.c | 0 {src => polyp}/sample-util.h | 0 {src => polyp}/sample.c | 0 {src => polyp}/sample.h | 0 {src => polyp}/sconv-s16be.c | 0 {src => polyp}/sconv-s16be.h | 0 {src => polyp}/sconv-s16le.c | 0 {src => polyp}/sconv-s16le.h | 0 {src => polyp}/sconv.c | 0 {src => polyp}/sconv.h | 0 {src => polyp}/sink-input.c | 0 {src => polyp}/sink-input.h | 0 {src => polyp}/sink.c | 0 {src => polyp}/sink.h | 0 {src => polyp}/sioman.c | 0 {src => polyp}/sioman.h | 0 {src => polyp}/socket-client.c | 0 {src => polyp}/socket-client.h | 0 {src => polyp}/socket-server.c | 0 {src => polyp}/socket-server.h | 0 {src => polyp}/socket-util.c | 0 {src => polyp}/socket-util.h | 0 {src => polyp}/source-output.c | 0 {src => polyp}/source-output.h | 0 {src => polyp}/source.c | 0 {src => polyp}/source.h | 0 {src => polyp}/strbuf.c | 0 {src => polyp}/strbuf.h | 0 {src => polyp}/tagstruct.c | 0 {src => polyp}/tagstruct.h | 0 {src => polyp}/tokenizer.c | 0 {src => polyp}/tokenizer.h | 0 {src => polyp}/util.c | 0 {src => polyp}/util.h | 0 125 files changed, 0 insertions(+), 0 deletions(-) rename {src => polyp}/Makefile.am (100%) rename {src => polyp}/alsa-util.c (100%) rename {src => polyp}/alsa-util.h (100%) rename {src => polyp}/authkey.c (100%) rename {src => polyp}/authkey.h (100%) rename {src => polyp}/cli-command.c (100%) rename {src => polyp}/cli-command.h (100%) rename {src => polyp}/cli.c (100%) rename {src => polyp}/cli.h (100%) rename {src => polyp}/client.c (100%) rename {src => polyp}/client.h (100%) rename {src => polyp}/clitext.c (100%) rename {src => polyp}/clitext.h (100%) rename {src => polyp}/cmdline.c (100%) rename {src => polyp}/cmdline.h (100%) rename {src => polyp}/core.c (100%) rename {src => polyp}/core.h (100%) rename {src => polyp}/depmod.py (100%) rename {src => polyp}/dynarray.c (100%) rename {src => polyp}/dynarray.h (100%) rename {src => polyp}/endianmacros.h (100%) rename {src => polyp}/esound.h (100%) rename {src => polyp}/hashmap.c (100%) rename {src => polyp}/hashmap.h (100%) rename {src => polyp}/idxset.c (100%) rename {src => polyp}/idxset.h (100%) rename {src => polyp}/iochannel.c (100%) rename {src => polyp}/iochannel.h (100%) rename {src => polyp}/ioline.c (100%) rename {src => polyp}/ioline.h (100%) rename {src => polyp}/main.c (100%) rename {src => polyp}/mainloop-api.c (100%) rename {src => polyp}/mainloop-api.h (100%) rename {src => polyp}/mainloop-signal.c (100%) rename {src => polyp}/mainloop-signal.h (100%) rename {src => polyp}/mainloop.c (100%) rename {src => polyp}/mainloop.h (100%) rename {src => polyp}/memblock.c (100%) rename {src => polyp}/memblock.h (100%) rename {src => polyp}/memblockq.c (100%) rename {src => polyp}/memblockq.h (100%) rename {src => polyp}/memchunk.c (100%) rename {src => polyp}/memchunk.h (100%) rename {src => polyp}/modargs.c (100%) rename {src => polyp}/modargs.h (100%) rename {src => polyp}/module-alsa-sink.c (100%) rename {src => polyp}/module-alsa-source.c (100%) rename {src => polyp}/module-cli.c (100%) rename {src => polyp}/module-oss-mmap.c (100%) rename {src => polyp}/module-oss.c (100%) rename {src => polyp}/module-pipe-sink.c (100%) rename {src => polyp}/module-protocol-stub.c (100%) rename {src => polyp}/module.c (100%) rename {src => polyp}/module.h (100%) rename {src => polyp}/namereg.c (100%) rename {src => polyp}/namereg.h (100%) rename {src => polyp}/native-common.h (100%) rename {src => polyp}/oss-util.c (100%) rename {src => polyp}/oss-util.h (100%) rename {src => polyp}/pacat-simple.c (100%) rename {src => polyp}/pacat.c (100%) rename {src => polyp}/packet.c (100%) rename {src => polyp}/packet.h (100%) rename {src => polyp}/pactl.c (100%) rename {src => polyp}/parec-simple.c (100%) rename {src => polyp}/pdispatch.c (100%) rename {src => polyp}/pdispatch.h (100%) rename {src => polyp}/polypaudio.pa (100%) rename {src => polyp}/polyplib-def.h (100%) rename {src => polyp}/polyplib-error.c (100%) rename {src => polyp}/polyplib-error.h (100%) rename {src => polyp}/polyplib-simple.c (100%) rename {src => polyp}/polyplib-simple.h (100%) rename {src => polyp}/polyplib.c (100%) rename {src => polyp}/polyplib.h (100%) rename {src => polyp}/protocol-cli.c (100%) rename {src => polyp}/protocol-cli.h (100%) rename {src => polyp}/protocol-esound.c (100%) rename {src => polyp}/protocol-esound.h (100%) rename {src => polyp}/protocol-native.c (100%) rename {src => polyp}/protocol-native.h (100%) rename {src => polyp}/protocol-simple.c (100%) rename {src => polyp}/protocol-simple.h (100%) rename {src => polyp}/pstream-util.c (100%) rename {src => polyp}/pstream-util.h (100%) rename {src => polyp}/pstream.c (100%) rename {src => polyp}/pstream.h (100%) rename {src => polyp}/queue.c (100%) rename {src => polyp}/queue.h (100%) rename {src => polyp}/resampler.c (100%) rename {src => polyp}/resampler.h (100%) rename {src => polyp}/sample-util.c (100%) rename {src => polyp}/sample-util.h (100%) rename {src => polyp}/sample.c (100%) rename {src => polyp}/sample.h (100%) rename {src => polyp}/sconv-s16be.c (100%) rename {src => polyp}/sconv-s16be.h (100%) rename {src => polyp}/sconv-s16le.c (100%) rename {src => polyp}/sconv-s16le.h (100%) rename {src => polyp}/sconv.c (100%) rename {src => polyp}/sconv.h (100%) rename {src => polyp}/sink-input.c (100%) rename {src => polyp}/sink-input.h (100%) rename {src => polyp}/sink.c (100%) rename {src => polyp}/sink.h (100%) rename {src => polyp}/sioman.c (100%) rename {src => polyp}/sioman.h (100%) rename {src => polyp}/socket-client.c (100%) rename {src => polyp}/socket-client.h (100%) rename {src => polyp}/socket-server.c (100%) rename {src => polyp}/socket-server.h (100%) rename {src => polyp}/socket-util.c (100%) rename {src => polyp}/socket-util.h (100%) rename {src => polyp}/source-output.c (100%) rename {src => polyp}/source-output.h (100%) rename {src => polyp}/source.c (100%) rename {src => polyp}/source.h (100%) rename {src => polyp}/strbuf.c (100%) rename {src => polyp}/strbuf.h (100%) rename {src => polyp}/tagstruct.c (100%) rename {src => polyp}/tagstruct.h (100%) rename {src => polyp}/tokenizer.c (100%) rename {src => polyp}/tokenizer.h (100%) rename {src => polyp}/util.c (100%) rename {src => polyp}/util.h (100%) diff --git a/src/Makefile.am b/polyp/Makefile.am similarity index 100% rename from src/Makefile.am rename to polyp/Makefile.am diff --git a/src/alsa-util.c b/polyp/alsa-util.c similarity index 100% rename from src/alsa-util.c rename to polyp/alsa-util.c diff --git a/src/alsa-util.h b/polyp/alsa-util.h similarity index 100% rename from src/alsa-util.h rename to polyp/alsa-util.h diff --git a/src/authkey.c b/polyp/authkey.c similarity index 100% rename from src/authkey.c rename to polyp/authkey.c diff --git a/src/authkey.h b/polyp/authkey.h similarity index 100% rename from src/authkey.h rename to polyp/authkey.h diff --git a/src/cli-command.c b/polyp/cli-command.c similarity index 100% rename from src/cli-command.c rename to polyp/cli-command.c diff --git a/src/cli-command.h b/polyp/cli-command.h similarity index 100% rename from src/cli-command.h rename to polyp/cli-command.h diff --git a/src/cli.c b/polyp/cli.c similarity index 100% rename from src/cli.c rename to polyp/cli.c diff --git a/src/cli.h b/polyp/cli.h similarity index 100% rename from src/cli.h rename to polyp/cli.h diff --git a/src/client.c b/polyp/client.c similarity index 100% rename from src/client.c rename to polyp/client.c diff --git a/src/client.h b/polyp/client.h similarity index 100% rename from src/client.h rename to polyp/client.h diff --git a/src/clitext.c b/polyp/clitext.c similarity index 100% rename from src/clitext.c rename to polyp/clitext.c diff --git a/src/clitext.h b/polyp/clitext.h similarity index 100% rename from src/clitext.h rename to polyp/clitext.h diff --git a/src/cmdline.c b/polyp/cmdline.c similarity index 100% rename from src/cmdline.c rename to polyp/cmdline.c diff --git a/src/cmdline.h b/polyp/cmdline.h similarity index 100% rename from src/cmdline.h rename to polyp/cmdline.h diff --git a/src/core.c b/polyp/core.c similarity index 100% rename from src/core.c rename to polyp/core.c diff --git a/src/core.h b/polyp/core.h similarity index 100% rename from src/core.h rename to polyp/core.h diff --git a/src/depmod.py b/polyp/depmod.py similarity index 100% rename from src/depmod.py rename to polyp/depmod.py diff --git a/src/dynarray.c b/polyp/dynarray.c similarity index 100% rename from src/dynarray.c rename to polyp/dynarray.c diff --git a/src/dynarray.h b/polyp/dynarray.h similarity index 100% rename from src/dynarray.h rename to polyp/dynarray.h diff --git a/src/endianmacros.h b/polyp/endianmacros.h similarity index 100% rename from src/endianmacros.h rename to polyp/endianmacros.h diff --git a/src/esound.h b/polyp/esound.h similarity index 100% rename from src/esound.h rename to polyp/esound.h diff --git a/src/hashmap.c b/polyp/hashmap.c similarity index 100% rename from src/hashmap.c rename to polyp/hashmap.c diff --git a/src/hashmap.h b/polyp/hashmap.h similarity index 100% rename from src/hashmap.h rename to polyp/hashmap.h diff --git a/src/idxset.c b/polyp/idxset.c similarity index 100% rename from src/idxset.c rename to polyp/idxset.c diff --git a/src/idxset.h b/polyp/idxset.h similarity index 100% rename from src/idxset.h rename to polyp/idxset.h diff --git a/src/iochannel.c b/polyp/iochannel.c similarity index 100% rename from src/iochannel.c rename to polyp/iochannel.c diff --git a/src/iochannel.h b/polyp/iochannel.h similarity index 100% rename from src/iochannel.h rename to polyp/iochannel.h diff --git a/src/ioline.c b/polyp/ioline.c similarity index 100% rename from src/ioline.c rename to polyp/ioline.c diff --git a/src/ioline.h b/polyp/ioline.h similarity index 100% rename from src/ioline.h rename to polyp/ioline.h diff --git a/src/main.c b/polyp/main.c similarity index 100% rename from src/main.c rename to polyp/main.c diff --git a/src/mainloop-api.c b/polyp/mainloop-api.c similarity index 100% rename from src/mainloop-api.c rename to polyp/mainloop-api.c diff --git a/src/mainloop-api.h b/polyp/mainloop-api.h similarity index 100% rename from src/mainloop-api.h rename to polyp/mainloop-api.h diff --git a/src/mainloop-signal.c b/polyp/mainloop-signal.c similarity index 100% rename from src/mainloop-signal.c rename to polyp/mainloop-signal.c diff --git a/src/mainloop-signal.h b/polyp/mainloop-signal.h similarity index 100% rename from src/mainloop-signal.h rename to polyp/mainloop-signal.h diff --git a/src/mainloop.c b/polyp/mainloop.c similarity index 100% rename from src/mainloop.c rename to polyp/mainloop.c diff --git a/src/mainloop.h b/polyp/mainloop.h similarity index 100% rename from src/mainloop.h rename to polyp/mainloop.h diff --git a/src/memblock.c b/polyp/memblock.c similarity index 100% rename from src/memblock.c rename to polyp/memblock.c diff --git a/src/memblock.h b/polyp/memblock.h similarity index 100% rename from src/memblock.h rename to polyp/memblock.h diff --git a/src/memblockq.c b/polyp/memblockq.c similarity index 100% rename from src/memblockq.c rename to polyp/memblockq.c diff --git a/src/memblockq.h b/polyp/memblockq.h similarity index 100% rename from src/memblockq.h rename to polyp/memblockq.h diff --git a/src/memchunk.c b/polyp/memchunk.c similarity index 100% rename from src/memchunk.c rename to polyp/memchunk.c diff --git a/src/memchunk.h b/polyp/memchunk.h similarity index 100% rename from src/memchunk.h rename to polyp/memchunk.h diff --git a/src/modargs.c b/polyp/modargs.c similarity index 100% rename from src/modargs.c rename to polyp/modargs.c diff --git a/src/modargs.h b/polyp/modargs.h similarity index 100% rename from src/modargs.h rename to polyp/modargs.h diff --git a/src/module-alsa-sink.c b/polyp/module-alsa-sink.c similarity index 100% rename from src/module-alsa-sink.c rename to polyp/module-alsa-sink.c diff --git a/src/module-alsa-source.c b/polyp/module-alsa-source.c similarity index 100% rename from src/module-alsa-source.c rename to polyp/module-alsa-source.c diff --git a/src/module-cli.c b/polyp/module-cli.c similarity index 100% rename from src/module-cli.c rename to polyp/module-cli.c diff --git a/src/module-oss-mmap.c b/polyp/module-oss-mmap.c similarity index 100% rename from src/module-oss-mmap.c rename to polyp/module-oss-mmap.c diff --git a/src/module-oss.c b/polyp/module-oss.c similarity index 100% rename from src/module-oss.c rename to polyp/module-oss.c diff --git a/src/module-pipe-sink.c b/polyp/module-pipe-sink.c similarity index 100% rename from src/module-pipe-sink.c rename to polyp/module-pipe-sink.c diff --git a/src/module-protocol-stub.c b/polyp/module-protocol-stub.c similarity index 100% rename from src/module-protocol-stub.c rename to polyp/module-protocol-stub.c diff --git a/src/module.c b/polyp/module.c similarity index 100% rename from src/module.c rename to polyp/module.c diff --git a/src/module.h b/polyp/module.h similarity index 100% rename from src/module.h rename to polyp/module.h diff --git a/src/namereg.c b/polyp/namereg.c similarity index 100% rename from src/namereg.c rename to polyp/namereg.c diff --git a/src/namereg.h b/polyp/namereg.h similarity index 100% rename from src/namereg.h rename to polyp/namereg.h diff --git a/src/native-common.h b/polyp/native-common.h similarity index 100% rename from src/native-common.h rename to polyp/native-common.h diff --git a/src/oss-util.c b/polyp/oss-util.c similarity index 100% rename from src/oss-util.c rename to polyp/oss-util.c diff --git a/src/oss-util.h b/polyp/oss-util.h similarity index 100% rename from src/oss-util.h rename to polyp/oss-util.h diff --git a/src/pacat-simple.c b/polyp/pacat-simple.c similarity index 100% rename from src/pacat-simple.c rename to polyp/pacat-simple.c diff --git a/src/pacat.c b/polyp/pacat.c similarity index 100% rename from src/pacat.c rename to polyp/pacat.c diff --git a/src/packet.c b/polyp/packet.c similarity index 100% rename from src/packet.c rename to polyp/packet.c diff --git a/src/packet.h b/polyp/packet.h similarity index 100% rename from src/packet.h rename to polyp/packet.h diff --git a/src/pactl.c b/polyp/pactl.c similarity index 100% rename from src/pactl.c rename to polyp/pactl.c diff --git a/src/parec-simple.c b/polyp/parec-simple.c similarity index 100% rename from src/parec-simple.c rename to polyp/parec-simple.c diff --git a/src/pdispatch.c b/polyp/pdispatch.c similarity index 100% rename from src/pdispatch.c rename to polyp/pdispatch.c diff --git a/src/pdispatch.h b/polyp/pdispatch.h similarity index 100% rename from src/pdispatch.h rename to polyp/pdispatch.h diff --git a/src/polypaudio.pa b/polyp/polypaudio.pa similarity index 100% rename from src/polypaudio.pa rename to polyp/polypaudio.pa diff --git a/src/polyplib-def.h b/polyp/polyplib-def.h similarity index 100% rename from src/polyplib-def.h rename to polyp/polyplib-def.h diff --git a/src/polyplib-error.c b/polyp/polyplib-error.c similarity index 100% rename from src/polyplib-error.c rename to polyp/polyplib-error.c diff --git a/src/polyplib-error.h b/polyp/polyplib-error.h similarity index 100% rename from src/polyplib-error.h rename to polyp/polyplib-error.h diff --git a/src/polyplib-simple.c b/polyp/polyplib-simple.c similarity index 100% rename from src/polyplib-simple.c rename to polyp/polyplib-simple.c diff --git a/src/polyplib-simple.h b/polyp/polyplib-simple.h similarity index 100% rename from src/polyplib-simple.h rename to polyp/polyplib-simple.h diff --git a/src/polyplib.c b/polyp/polyplib.c similarity index 100% rename from src/polyplib.c rename to polyp/polyplib.c diff --git a/src/polyplib.h b/polyp/polyplib.h similarity index 100% rename from src/polyplib.h rename to polyp/polyplib.h diff --git a/src/protocol-cli.c b/polyp/protocol-cli.c similarity index 100% rename from src/protocol-cli.c rename to polyp/protocol-cli.c diff --git a/src/protocol-cli.h b/polyp/protocol-cli.h similarity index 100% rename from src/protocol-cli.h rename to polyp/protocol-cli.h diff --git a/src/protocol-esound.c b/polyp/protocol-esound.c similarity index 100% rename from src/protocol-esound.c rename to polyp/protocol-esound.c diff --git a/src/protocol-esound.h b/polyp/protocol-esound.h similarity index 100% rename from src/protocol-esound.h rename to polyp/protocol-esound.h diff --git a/src/protocol-native.c b/polyp/protocol-native.c similarity index 100% rename from src/protocol-native.c rename to polyp/protocol-native.c diff --git a/src/protocol-native.h b/polyp/protocol-native.h similarity index 100% rename from src/protocol-native.h rename to polyp/protocol-native.h diff --git a/src/protocol-simple.c b/polyp/protocol-simple.c similarity index 100% rename from src/protocol-simple.c rename to polyp/protocol-simple.c diff --git a/src/protocol-simple.h b/polyp/protocol-simple.h similarity index 100% rename from src/protocol-simple.h rename to polyp/protocol-simple.h diff --git a/src/pstream-util.c b/polyp/pstream-util.c similarity index 100% rename from src/pstream-util.c rename to polyp/pstream-util.c diff --git a/src/pstream-util.h b/polyp/pstream-util.h similarity index 100% rename from src/pstream-util.h rename to polyp/pstream-util.h diff --git a/src/pstream.c b/polyp/pstream.c similarity index 100% rename from src/pstream.c rename to polyp/pstream.c diff --git a/src/pstream.h b/polyp/pstream.h similarity index 100% rename from src/pstream.h rename to polyp/pstream.h diff --git a/src/queue.c b/polyp/queue.c similarity index 100% rename from src/queue.c rename to polyp/queue.c diff --git a/src/queue.h b/polyp/queue.h similarity index 100% rename from src/queue.h rename to polyp/queue.h diff --git a/src/resampler.c b/polyp/resampler.c similarity index 100% rename from src/resampler.c rename to polyp/resampler.c diff --git a/src/resampler.h b/polyp/resampler.h similarity index 100% rename from src/resampler.h rename to polyp/resampler.h diff --git a/src/sample-util.c b/polyp/sample-util.c similarity index 100% rename from src/sample-util.c rename to polyp/sample-util.c diff --git a/src/sample-util.h b/polyp/sample-util.h similarity index 100% rename from src/sample-util.h rename to polyp/sample-util.h diff --git a/src/sample.c b/polyp/sample.c similarity index 100% rename from src/sample.c rename to polyp/sample.c diff --git a/src/sample.h b/polyp/sample.h similarity index 100% rename from src/sample.h rename to polyp/sample.h diff --git a/src/sconv-s16be.c b/polyp/sconv-s16be.c similarity index 100% rename from src/sconv-s16be.c rename to polyp/sconv-s16be.c diff --git a/src/sconv-s16be.h b/polyp/sconv-s16be.h similarity index 100% rename from src/sconv-s16be.h rename to polyp/sconv-s16be.h diff --git a/src/sconv-s16le.c b/polyp/sconv-s16le.c similarity index 100% rename from src/sconv-s16le.c rename to polyp/sconv-s16le.c diff --git a/src/sconv-s16le.h b/polyp/sconv-s16le.h similarity index 100% rename from src/sconv-s16le.h rename to polyp/sconv-s16le.h diff --git a/src/sconv.c b/polyp/sconv.c similarity index 100% rename from src/sconv.c rename to polyp/sconv.c diff --git a/src/sconv.h b/polyp/sconv.h similarity index 100% rename from src/sconv.h rename to polyp/sconv.h diff --git a/src/sink-input.c b/polyp/sink-input.c similarity index 100% rename from src/sink-input.c rename to polyp/sink-input.c diff --git a/src/sink-input.h b/polyp/sink-input.h similarity index 100% rename from src/sink-input.h rename to polyp/sink-input.h diff --git a/src/sink.c b/polyp/sink.c similarity index 100% rename from src/sink.c rename to polyp/sink.c diff --git a/src/sink.h b/polyp/sink.h similarity index 100% rename from src/sink.h rename to polyp/sink.h diff --git a/src/sioman.c b/polyp/sioman.c similarity index 100% rename from src/sioman.c rename to polyp/sioman.c diff --git a/src/sioman.h b/polyp/sioman.h similarity index 100% rename from src/sioman.h rename to polyp/sioman.h diff --git a/src/socket-client.c b/polyp/socket-client.c similarity index 100% rename from src/socket-client.c rename to polyp/socket-client.c diff --git a/src/socket-client.h b/polyp/socket-client.h similarity index 100% rename from src/socket-client.h rename to polyp/socket-client.h diff --git a/src/socket-server.c b/polyp/socket-server.c similarity index 100% rename from src/socket-server.c rename to polyp/socket-server.c diff --git a/src/socket-server.h b/polyp/socket-server.h similarity index 100% rename from src/socket-server.h rename to polyp/socket-server.h diff --git a/src/socket-util.c b/polyp/socket-util.c similarity index 100% rename from src/socket-util.c rename to polyp/socket-util.c diff --git a/src/socket-util.h b/polyp/socket-util.h similarity index 100% rename from src/socket-util.h rename to polyp/socket-util.h diff --git a/src/source-output.c b/polyp/source-output.c similarity index 100% rename from src/source-output.c rename to polyp/source-output.c diff --git a/src/source-output.h b/polyp/source-output.h similarity index 100% rename from src/source-output.h rename to polyp/source-output.h diff --git a/src/source.c b/polyp/source.c similarity index 100% rename from src/source.c rename to polyp/source.c diff --git a/src/source.h b/polyp/source.h similarity index 100% rename from src/source.h rename to polyp/source.h diff --git a/src/strbuf.c b/polyp/strbuf.c similarity index 100% rename from src/strbuf.c rename to polyp/strbuf.c diff --git a/src/strbuf.h b/polyp/strbuf.h similarity index 100% rename from src/strbuf.h rename to polyp/strbuf.h diff --git a/src/tagstruct.c b/polyp/tagstruct.c similarity index 100% rename from src/tagstruct.c rename to polyp/tagstruct.c diff --git a/src/tagstruct.h b/polyp/tagstruct.h similarity index 100% rename from src/tagstruct.h rename to polyp/tagstruct.h diff --git a/src/tokenizer.c b/polyp/tokenizer.c similarity index 100% rename from src/tokenizer.c rename to polyp/tokenizer.c diff --git a/src/tokenizer.h b/polyp/tokenizer.h similarity index 100% rename from src/tokenizer.h rename to polyp/tokenizer.h diff --git a/src/util.c b/polyp/util.c similarity index 100% rename from src/util.c rename to polyp/util.c diff --git a/src/util.h b/polyp/util.h similarity index 100% rename from src/util.h rename to polyp/util.h From 6601d958bfa16acef7da5eafde23161a3b2cca41 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 14:14:41 +0000 Subject: [PATCH 0090/1514] fix Makefile.am and configure.ac to match directory renaming git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@91 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- configure.ac | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 43009b443..1fec1ced5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # USA. EXTRA_DIST = bootstrap.sh README LICENSE -SUBDIRS=src doc +SUBDIRS=polyp doc MAINTAINERCLEANFILES=README noinst_DATA = README diff --git a/configure.ac b/configure.ac index 86398f4dd..3028228a4 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ AC_PREREQ(2.57) AC_INIT([polypaudio],[0.1],[mzcbylcnhqvb (at) 0pointer (dot) de]) -AC_CONFIG_SRCDIR([src/main.c]) +AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) @@ -76,5 +76,5 @@ AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) -AC_CONFIG_FILES([Makefile src/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html]) +AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html]) AC_OUTPUT From 141ab85bb76c3d2a8f6f2eee91801597c98e4154 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 15:00:31 +0000 Subject: [PATCH 0091/1514] make polypaudio run when installed update docs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@92 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 25 ++++++++++++++++++++++++- polyp/Makefile.am | 2 +- polyp/main.c | 5 ++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index a9b07d60c..b523e3dcb 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -78,7 +78,10 @@ available.

Version @PACKAGE_VERSION@ is quite usable. polypaudio does not yet match all ESOUND features: currently a sample cache and -automatic releasing of unused sound drivers are missing. Have a look on the more extensive TODO list.

+automatic releasing of unused sound drivers are missing. Have a look +on the more extensive TODO +list.

Documentation

@@ -90,6 +93,26 @@ href="daemon.html">daemeon.html.

Documentation for developing with polypaudio is not yet available. Read the source, Luke!

+

First Steps

+ +

Simply start the polypaudio daemon with the argument -C

+ +
polypaudio -C
+ +

This will present you a screen like this:

+ +
Welcome to polypaudio! Use "help" for usage information.
+>>> 
+ +

Now you can issue CLI commands as described in cli.html. Another way to start +polypaudio is by specifying a configuration script on the +command line like that one included in the distribution:

+ +
polypaudio -F polypaudio.pa
+ +

This will load some drivers and protocols automatically.

+

Requirements

Currently, polypaudio is tested on Linux only. It requires an OSS or ALSA compatible soundcard.

diff --git a/polyp/Makefile.am b/polyp/Makefile.am index c4da73427..4edeeeba3 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -17,7 +17,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -AM_CFLAGS=-ansi -D_GNU_SOURCE +AM_CFLAGS=-ansi -D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" EXTRA_DIST = polypaudio.run depmod.py bin_PROGRAMS = polypaudio pacat pactl diff --git a/polyp/main.c b/polyp/main.c index d9967cef2..bcc1fadae 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -125,7 +125,10 @@ int main(int argc, char *argv[]) { r = lt_dlinit(); assert(r == 0); - +#ifdef DLSEARCHDIR + lt_dladdsearchdir(DLSEARCHDIR); +#endif + mainloop = pa_mainloop_new(); assert(mainloop); From 78a799e649b644f4c2f43bf1a1bd71cfd0f5ef45 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 15:22:12 +0000 Subject: [PATCH 0092/1514] make distcheck clean git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@93 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 11 ++++++++--- doc/todo | 20 ++++++++++++-------- polyp/Makefile.am | 4 ++-- polyp/pacat-simple.c | 4 ++-- polyp/pacat.c | 8 ++++---- polyp/pactl.c | 8 ++++---- polyp/parec-simple.c | 4 ++-- 7 files changed, 34 insertions(+), 25 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index b523e3dcb..ad8832c6e 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -10,7 +10,7 @@

polypaudio @PACKAGE_VERSION@

-

Copyright 2002-2004 Lennart Poettering <@PACKAGE_BUGREPORT@>

+

Copyright 2004 Lennart Poettering <@PACKAGE_BUGREPORT@>

  • License
  • @@ -72,7 +72,7 @@ integration with asynchronous applications using the glib/gtk mainloop. Since the asynchronous API available through polyplib is quite difficult to use there is a simplified synchronous API wrapper polyplib-simple -available.

    +available. A simple main loop implementation is available as well.

    Status

    @@ -91,7 +91,12 @@ href="cli.html">cli.html, daemeon.html.

    Documentation for developing with polypaudio is not yet -available. Read the source, Luke!

    +available. Read the source, Luke! There are some example application +available: for the asynchronous +API and for the simple, +synchronous API.

    First Steps

    diff --git a/doc/todo b/doc/todo index 5b944a360..5142c0138 100644 --- a/doc/todo +++ b/doc/todo @@ -1,27 +1,31 @@ *** $Id$ *** -- documentation - -*** post 0.1 *** +*** 0.2 *** - future cancellation -- client-ui - clip cache - autoloading/autounloading -- slp/rendezvous - doxygen - make mcalign merge chunks -- modinfo + +*** 0.3 *** +- client-ui - move the global memblock statistics variables to the core - unix socket directories include user name -- more complete pactl - native library/protocol: get server layout subscription module load/unload kill client/... +- more complete pactl + +** later *** +- slp/rendezvous +- modinfo - make alsa modules use mmap -drivers: +*********** + +backends for: - libao - xmms - portaudio diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 4edeeeba3..02227476c 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -17,9 +17,9 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -AM_CFLAGS=-ansi -D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" +AM_CFLAGS=-ansi -D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" -I$(srcdir)/.. -EXTRA_DIST = polypaudio.run depmod.py +EXTRA_DIST = polypaudio.pa depmod.py bin_PROGRAMS = polypaudio pacat pactl noinst_PROGRAMS = pacat-simple parec-simple diff --git a/polyp/pacat-simple.c b/polyp/pacat-simple.c index 5018aa5f6..f2aae2e4b 100644 --- a/polyp/pacat-simple.c +++ b/polyp/pacat-simple.c @@ -28,8 +28,8 @@ #include #include -#include "polyplib-simple.h" -#include "polyplib-error.h" +#include +#include #define BUFSIZE 1024 diff --git a/polyp/pacat.c b/polyp/pacat.c index 1d1cc3d57..55a0f6b94 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -31,10 +31,10 @@ #include #include -#include "polyplib.h" -#include "polyplib-error.h" -#include "mainloop.h" -#include "mainloop-signal.h" +#include +#include +#include +#include static enum { RECORD, PLAYBACK } mode = PLAYBACK; diff --git a/polyp/pactl.c b/polyp/pactl.c index 2b1ed2c18..61060c469 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -31,10 +31,10 @@ #include #include -#include "polyplib.h" -#include "polyplib-error.h" -#include "mainloop.h" -#include "mainloop-signal.h" +#include +#include +#include +#include static struct pa_context *context = NULL; static struct pa_mainloop_api *mainloop_api = NULL; diff --git a/polyp/parec-simple.c b/polyp/parec-simple.c index c4196a145..e12b8e004 100644 --- a/polyp/parec-simple.c +++ b/polyp/parec-simple.c @@ -28,8 +28,8 @@ #include #include -#include "polyplib-simple.h" -#include "polyplib-error.h" +#include +#include #define BUFSIZE 1024 From d6d50b0eab254d664c7998b08b84b7bce0a82b32 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 15:44:49 +0000 Subject: [PATCH 0093/1514] some makefile fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@94 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 68 ++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 02227476c..94edf6165 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -18,6 +18,8 @@ # USA. AM_CFLAGS=-ansi -D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" -I$(srcdir)/.. +AM_LDADD=-L. +AM_LIBADD=-L. EXTRA_DIST = polypaudio.pa depmod.py bin_PROGRAMS = polypaudio pacat pactl @@ -107,36 +109,36 @@ polypaudio_SOURCES = idxset.c idxset.h \ polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) -polypaudio_LDADD = $(LIBLTDL) $(LIBSAMPLERATE_LIBS) +polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) polypaudio_LDFLAGS=-export-dynamic libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version -libprotocol_simple_la_LIBADD = libsocket-server.la libiochannel.la +libprotocol_simple_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libsocket_server_la_SOURCES = socket-server.c socket-server.h libsocket_server_la_LDFLAGS = -avoid-version -libsocket_server_la_LIBADD = libiochannel.la libsocket-util.la +libsocket_server_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la libsocket_client_la_SOURCES = socket-client.c socket-client.h libsocket_client_la_LDFLAGS = -avoid-version -libsocket_client_la_LIBADD = libiochannel.la libsocket-util.la +libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la libpstream_la_SOURCES = pstream.c pstream.h libpstream_la_LDFLAGS = -avoid-version -libpstream_la_LIBADD = libpacket.la libiochannel.la +libpstream_la_LIBADD = $(AM_LIBADD) libpacket.la libiochannel.la libpstream_util_la_SOURCES = pstream-util.c pstream-util.h libpstream_util_la_LDFLAGS = -avoid-version -libpstream_util_la_LIBADD = libpacket.la libpstream.la libtagstruct.la +libpstream_util_la_LIBADD = $(AM_LIBADD) libpacket.la libpstream.la libtagstruct.la libpdispatch_la_SOURCES = pdispatch.c pdispatch.h libpdispatch_la_LDFLAGS = -avoid-version -libpdispatch_la_LIBADD = libtagstruct.la +libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la libiochannel_la_SOURCES = iochannel.c iochannel.h libiochannel_la_LDFLAGS = -avoid-version -libiochannel_la_LIBADD = libsocket-util.la +libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpacket_la_SOURCES = packet.c packet.h libpacket_la_LDFLAGS = -avoid-version @@ -146,31 +148,31 @@ liboss_util_la_LDFLAGS = -avoid-version libalsa_util_la_SOURCES = alsa-util.c alsa-util.h libalsa_util_la_LDFLAGS = -avoid-version -libalsa_util_la_LIBADD = $(ASOUNDLIB_LIBS) +libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) libioline_la_SOURCES = ioline.c ioline.h libioline_la_LDFLAGS = -avoid-version -libioline_la_LIBADD = libiochannel.la +libioline_la_LIBADD = $(AM_LIBADD) libiochannel.la libcli_la_SOURCES = cli.c cli.h libcli_la_LDFLAGS = -avoid-version -libcli_la_LIBADD = libiochannel.la libioline.la +libcli_la_LIBADD = $(AM_LIBADD) libiochannel.la libioline.la libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h libprotocol_cli_la_LDFLAGS = -avoid-version -libprotocol_cli_la_LIBADD = libsocket-server.la libiochannel.la libcli.la +libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h native-common.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la +libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libtagstruct_la_SOURCES = tagstruct.c tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h esound.h libprotocol_esound_la_LDFLAGS = -avoid-version -libprotocol_esound_la_LIBADD = libsocket-server.la libiochannel.la libauthkey.la +libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la libauthkey_la_SOURCES = authkey.c authkey.h libauthkey_la_LDFLAGS = -avoid-version @@ -181,68 +183,68 @@ libsocket_util_la_LDFLAGS = -avoid-version module_simple_protocol_tcp_la_SOURCES = module-protocol-stub.c module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_simple_protocol_tcp_la_LIBADD = libprotocol-simple.la libsocket-server.la +module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-simple.la libsocket-server.la module_simple_protocol_unix_la_SOURCES = module-protocol-stub.c module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version -module_simple_protocol_unix_la_LIBADD = libprotocol-simple.la libsocket-server.la libsocket-util.la +module_simple_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-simple.la libsocket-server.la libsocket-util.la module_cli_protocol_tcp_la_SOURCES = module-protocol-stub.c module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_cli_protocol_tcp_la_LIBADD = libprotocol-cli.la libsocket-server.la +module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la module_cli_protocol_unix_la_SOURCES = module-protocol-stub.c module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version -module_cli_protocol_unix_la_LIBADD = libprotocol-cli.la libsocket-server.la libsocket-util.la +module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la libsocket-util.la module_native_protocol_tcp_la_SOURCES = module-protocol-stub.c module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_native_protocol_tcp_la_LIBADD = libprotocol-native.la libsocket-server.la +module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la module_native_protocol_unix_la_SOURCES = module-protocol-stub.c module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_unix_la_LDFLAGS = -module -avoid-version -module_native_protocol_unix_la_LIBADD = libprotocol-native.la libsocket-server.la libsocket-util.la +module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la libsocket-util.la module_esound_protocol_tcp_la_SOURCES = module-protocol-stub.c module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_esound_protocol_tcp_la_LIBADD = libprotocol-esound.la libsocket-server.la +module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-esound.la libsocket-server.la module_esound_protocol_unix_la_SOURCES = module-protocol-stub.c module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version -module_esound_protocol_unix_la_LIBADD = libprotocol-esound.la libsocket-server.la libsocket-util.la +module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-esound.la libsocket-server.la libsocket-util.la module_pipe_sink_la_SOURCES = module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version -module_pipe_sink_la_LIBADD = libiochannel.la +module_pipe_sink_la_LIBADD = $(AM_LIBADD) libiochannel.la module_alsa_sink_la_SOURCES = module-alsa-sink.c module_alsa_sink_la_LDFLAGS = -module -avoid-version -module_alsa_sink_la_LIBADD = $(ASOUNDLIB_LIBS) libalsa-util.la +module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) module_alsa_source_la_SOURCES = module-alsa-source.c module_alsa_source_la_LDFLAGS = -module -avoid-version -module_alsa_source_la_LIBADD = $(ASOUNDLIB_LIBS) libalsa-util.la +module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) module_oss_la_SOURCES = module-oss.c module_oss_la_LDFLAGS = -module -avoid-version -module_oss_la_LIBADD = libiochannel.la liboss-util.la +module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la module_oss_mmap_la_SOURCES = module-oss-mmap.c module_oss_mmap_la_LDFLAGS = -module -avoid-version -module_oss_mmap_la_LIBADD = liboss-util.la +module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la module_cli_la_SOURCES = module-cli.c module_cli_la_LDFLAGS = -module -avoid-version -module_cli_la_LIBADD = libcli.la libiochannel.la +module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la libpolyp_la_SOURCES = polyplib.c polyplib.h \ polyplib-def.h \ @@ -275,22 +277,22 @@ libpolyp_error_la_CFLAGS = $(AM_CFLAGS) libpolyp_simple_la_SOURCES = polyplib-simple.c polyplib-simple.h libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) -libpolyp_simple_la_LIBADD = libpolyp.la libpolyp-mainloop.la +libpolyp_simple_la_LIBADD = $(AM_LIBADD) libpolyp.la libpolyp-mainloop.la pacat_SOURCES = pacat.c -pacat_LDADD = libpolyp.la libpolyp-error.la libpolyp-mainloop.la +pacat_LDADD = $(AM_LDADD) libpolyp.la libpolyp-error.la libpolyp-mainloop.la pacat_CFLAGS = $(AM_CFLAGS) pactl_SOURCES = pactl.c -pactl_LDADD = libpolyp.la libpolyp-error.la libpolyp-mainloop.la +pactl_LDADD = $(AM_LDADD) libpolyp.la libpolyp-error.la libpolyp-mainloop.la pactl_CFLAGS = $(AM_CFLAGS) pacat_simple_SOURCES = pacat-simple.c -pacat_simple_LDADD = libpolyp-simple.la libpolyp-error.la +pacat_simple_LDADD = $(AM_LDADD) libpolyp-simple.la libpolyp-error.la pacat_simple_CFLAGS = $(AM_CFLAGS) parec_simple_SOURCES = parec-simple.c -parec_simple_LDADD = libpolyp-simple.la libpolyp-error.la +parec_simple_LDADD = $(AM_LDADD) libpolyp-simple.la libpolyp-error.la parec_simple_CFLAGS = $(AM_CFLAGS) if BUILD_LIBPOLYPCORE From 765d2f70c798a4781b497fce4b4db5e5e9ab007c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 15:48:28 +0000 Subject: [PATCH 0094/1514] two simple fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@95 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/modargs.c | 2 +- polyp/resampler.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/polyp/modargs.c b/polyp/modargs.c index 280a546d2..ea104761a 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -76,7 +76,7 @@ struct pa_modargs *pa_modargs_new(const char *args, const char* const* valid_key if (args) { enum { WHITESPACE, KEY, VALUE_START, VALUE_SIMPLE, VALUE_DOUBLE_QUOTES, VALUE_TICKS } state; const char *p, *key, *value; - size_t key_len, value_len; + size_t key_len = 0, value_len = 0; key = value = NULL; state = WHITESPACE; diff --git a/polyp/resampler.c b/polyp/resampler.c index 4f5f6be3b..320d71195 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -45,7 +45,7 @@ struct pa_resampler { }; struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b) { - struct pa_resampler *r; + struct pa_resampler *r = NULL; int err; assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b)); From 854071844fbaa5ea8d17e9e82d818c3c7cab6667 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jul 2004 16:00:46 +0000 Subject: [PATCH 0095/1514] readme update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@96 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/Makefile.am | 2 +- doc/README.html.in | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/Makefile.am b/doc/Makefile.am index d88451f5e..6101521cf 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -32,8 +32,8 @@ endif tidy: README.html cli.html modules.html daemon.html tidy -e < README.html tidy -e < cli.html - tidy -e < modules.html tidy -e < daemon.html + tidy -e < modules.html .PHONY: tidy diff --git a/doc/README.html.in b/doc/README.html.in index ad8832c6e..296d4506c 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -73,7 +73,9 @@ integration with asynchronous applications using the available through polyplib is quite difficult to use there is a simplified synchronous API wrapper polyplib-simple available. A simple main loop implementation is available as well.

    - + +

    polypaudio is the successor of my previous, ill-fated attempt to write a sound server asd.

    +

    Status

    Version @PACKAGE_VERSION@ is quite usable. polypaudio does @@ -98,7 +100,7 @@ API and for the simple, synchronous API.

    -

    First Steps

    +

    First Steps

    Simply start the polypaudio daemon with the argument -C

    From 527faf01d0605a6ced9a73017cc8155adba59d24 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 18 Jul 2004 14:19:28 +0000 Subject: [PATCH 0096/1514] minor fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@97 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 1fec1ced5..a54fd606a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,7 +35,7 @@ homepage: all dist test -d $$HOME/homepage/private mkdir -p $$HOME/homepage/private/projects/polypaudio cp *.tar.gz $$HOME/homepage/private/projects/polypaudio - cp doc/README.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css doc/NEWS $$HOME/homepage/private/projects/polypaudio + cp doc/README.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/polypaudio cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html distcleancheck: From bb0b105b83c0f4ee56b4c7e9a179606aee296aa9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 20 Jul 2004 01:07:06 +0000 Subject: [PATCH 0097/1514] sample cache work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@98 fefdeb5f-60dc-0310-8127-8f9354f1896f --- bootstrap.sh | 14 ++- doc/todo | 9 +- polyp/Makefile.am | 3 +- polyp/cli-command.c | 59 ++++++++++++ polyp/clitext.c | 35 +++++++ polyp/clitext.h | 1 + polyp/core.c | 4 + polyp/core.h | 4 +- polyp/debug.h | 8 ++ polyp/hashmap.c | 14 +++ polyp/hashmap.h | 5 + polyp/main.c | 2 +- polyp/modargs.c | 4 + polyp/module-alsa-sink.c | 2 +- polyp/protocol-esound.c | 194 ++++++++++++++++++++++++++++++++++++--- polyp/scache.c | 181 ++++++++++++++++++++++++++++++++++++ polyp/scache.h | 24 +++++ 17 files changed, 539 insertions(+), 24 deletions(-) create mode 100644 polyp/debug.h create mode 100644 polyp/scache.c create mode 100644 polyp/scache.h diff --git a/bootstrap.sh b/bootstrap.sh index c9880d85e..3592ce75c 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -17,9 +17,17 @@ # along with polypaudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +run_versioned() { + local P + type -p "$1-$2" &> /dev/null && P="$1-$2" || local P="$1" + + shift 2 + "$P" "$@" +} + if [ "x$1" = "xam" ] ; then set -ex - automake -a -c --foreign + run_versioned automake 1.7 -a -c --foreign ./config.status else set -ex @@ -27,10 +35,10 @@ else rm -rf autom4te.cache rm -f config.cache - aclocal + run_versioned aclocal 1.7 libtoolize -c --force autoheader - automake -a -c + run_versioned automake 1.7 -a -c --foreign autoconf -Wall CFLAGS="-g -O0" ./configure --sysconfdir=/etc "$@" diff --git a/doc/todo b/doc/todo index 5142c0138..76b0d312f 100644 --- a/doc/todo +++ b/doc/todo @@ -1,11 +1,18 @@ *** $Id$ *** *** 0.2 *** + +- scache memory leak +- scache remove() +- scache in native protocol +- scache/debug.h copyright + - future cancellation -- clip cache - autoloading/autounloading - doxygen - make mcalign merge chunks +- autoscan +- rename clitext.[ch] to cli-text.[ch] *** 0.3 *** - client-ui diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 94edf6165..d16155857 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -105,7 +105,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ cli-command.c cli-command.h \ clitext.c clitext.h \ tokenizer.c tokenizer.h \ - dynarray.c dynarray.h + dynarray.c dynarray.h \ + scache.c scache.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) diff --git a/polyp/cli-command.c b/polyp/cli-command.c index f3a2f8a0d..03bd125b3 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -40,6 +40,8 @@ #include "strbuf.h" #include "namereg.h" #include "clitext.h" +#include "scache.h" +#include "sample-util.h" struct command { const char *name; @@ -67,6 +69,9 @@ static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static const struct command commands[] = { { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, @@ -90,6 +95,9 @@ static const struct command commands[] = { { "kill_client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, { "kill_sink_input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2}, { "kill_source_output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2}, + { "scache_list", pa_cli_command_scache_list, "List all entries in the sample cache", 2}, + { "scache_play", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3}, + { "scache_remove", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2}, { NULL, NULL, NULL, 0 } }; @@ -199,6 +207,7 @@ static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_cli_command_clients(c, t, buf, fail, verbose); pa_cli_command_sink_inputs(c, t, buf, fail, verbose); pa_cli_command_source_outputs(c, t, buf, fail, verbose); + pa_cli_command_scache_list(c, t, buf, fail, verbose); return 0; } @@ -429,6 +438,56 @@ static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokeni return 0; } +static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + char *s; + assert(c && t); + s = pa_scache_list_to_string(c); + assert(s); + pa_strbuf_puts(buf, s); + free(s); + return 0; +} + +static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *n, *sink_name; + struct pa_sink *sink; + assert(c && t && buf && fail && verbose); + + if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n"); + return -1; + } + + if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) { + pa_strbuf_puts(buf, "No sink by that name.\n"); + return -1; + } + + if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM) < 0) { + pa_strbuf_puts(buf, "Failed to play sample.\n"); + return -1; + } + + return 0; +} + +static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *n; + assert(c && t && buf && fail && verbose); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a sample name.\n"); + return -1; + } + + if (pa_scache_remove_item(c, n) < 0) { + pa_strbuf_puts(buf, "Failed to remove sample.\n"); + return -1; + } + + return 0; +} + int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) { const char *cs; diff --git a/polyp/clitext.c b/polyp/clitext.c index c1b9953b2..d0c3f9a74 100644 --- a/polyp/clitext.c +++ b/polyp/clitext.c @@ -24,6 +24,7 @@ #endif #include +#include #include "clitext.h" #include "module.h" @@ -34,6 +35,7 @@ #include "source-output.h" #include "strbuf.h" #include "sample-util.h" +#include "scache.h" char *pa_module_list_to_string(struct pa_core *c) { struct pa_strbuf *s; @@ -201,3 +203,36 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { return pa_strbuf_tostring_free(s); } + +char *pa_scache_list_to_string(struct pa_core *c) { + struct pa_scache_entry *e; + void *state = NULL; + struct pa_strbuf *s; + assert(c); + + s = pa_strbuf_new(); + assert(s); + + pa_strbuf_printf(s, "%u cache entries available.\n", c->scache_hashmap ? pa_hashmap_ncontents(c->scache_hashmap) : 0); + + if (c->scache_hashmap) { + + while ((e = pa_hashmap_iterate(c->scache_hashmap, &state))) { + double l; + char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + pa_sample_snprint(ss, sizeof(ss), &e->sample_spec); + + l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec); + + pa_strbuf_printf( + s, " name: <%s>\n\tindex: <%i>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n", + e->name, + e->index, + ss, + e->memchunk.length, + l); + } + } + + return pa_strbuf_tostring_free(s); +} diff --git a/polyp/clitext.h b/polyp/clitext.h index b1718cb5a..4e5252fe3 100644 --- a/polyp/clitext.h +++ b/polyp/clitext.h @@ -30,6 +30,7 @@ char *pa_sink_list_to_string(struct pa_core *core); char *pa_source_list_to_string(struct pa_core *c); char *pa_client_list_to_string(struct pa_core *c); char *pa_module_list_to_string(struct pa_core *c); +char *pa_scache_list_to_string(struct pa_core *c); #endif diff --git a/polyp/core.c b/polyp/core.c index dc9525a8f..1c69f9147 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -33,6 +33,7 @@ #include "source.h" #include "namereg.h" #include "util.h" +#include "scache.h" struct pa_core* pa_core_new(struct pa_mainloop_api *m) { struct pa_core* c; @@ -50,6 +51,8 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->modules = NULL; c->namereg = NULL; + c->scache_idxset = NULL; + c->scache_hashmap = NULL; c->default_sample_spec.format = PA_SAMPLE_S16NE; c->default_sample_spec.rate = 44100; @@ -82,6 +85,7 @@ void pa_core_free(struct pa_core *c) { pa_idxset_free(c->sink_inputs, NULL, NULL); pa_namereg_free(c); + pa_scache_free(c); free(c); }; diff --git a/polyp/core.h b/polyp/core.h index 99d7d76a7..03b8671ab 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -30,9 +30,9 @@ struct pa_core { struct pa_mainloop_api *mainloop; - struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules; + struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache_idxset; - struct pa_hashmap *namereg; + struct pa_hashmap *namereg, *scache_hashmap; uint32_t default_source_index, default_sink_index; diff --git a/polyp/debug.h b/polyp/debug.h new file mode 100644 index 000000000..fb2b889e6 --- /dev/null +++ b/polyp/debug.h @@ -0,0 +1,8 @@ +#ifndef foodebughfoo +#define foodebughfoo + +/* A nice trick for debuggers, working on x86 only */ + +#define DEBUG_TRAP __asm__("int $3") + +#endif diff --git a/polyp/hashmap.c b/polyp/hashmap.c index 2c7c92b5d..51e3879b5 100644 --- a/polyp/hashmap.c +++ b/polyp/hashmap.c @@ -168,3 +168,17 @@ int pa_hashmap_remove(struct pa_hashmap *h, const void *key) { unsigned pa_hashmap_ncontents(struct pa_hashmap *h) { return h->n_entries; } + +void *pa_hashmap_iterate(struct pa_hashmap *h, void **state) { + assert(h && state); + + if (!*state) { + *state = h->first_entry; + } else + *state = ((struct hashmap_entry*) *state)->next; + + if (!*state) + return NULL; + + return ((struct hashmap_entry*) *state)->value; +} diff --git a/polyp/hashmap.h b/polyp/hashmap.h index b24e74a52..3b79d7ae8 100644 --- a/polyp/hashmap.h +++ b/polyp/hashmap.h @@ -34,4 +34,9 @@ int pa_hashmap_remove(struct pa_hashmap *h, const void *key); unsigned pa_hashmap_ncontents(struct pa_hashmap *h); +/* Maybe used to iterate through the hashmap. Initial state should + point to a NULL pointer. The hashmap may not be modified during + iteration */ +void *pa_hashmap_iterate(struct pa_hashmap *h, void **state); + #endif diff --git a/polyp/main.c b/polyp/main.c index bcc1fadae..0c6104a44 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -126,7 +126,7 @@ int main(int argc, char *argv[]) { r = lt_dlinit(); assert(r == 0); #ifdef DLSEARCHDIR - lt_dladdsearchdir(DLSEARCHDIR); +/* lt_dladdsearchdir(DLSEARCHDIR);*/ #endif mainloop = pa_mainloop_new(); diff --git a/polyp/modargs.c b/polyp/modargs.c index ea104761a..3841a9ec2 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -36,6 +36,8 @@ #include "sink.h" #include "source.h" +#include "debug.h" + struct pa_modargs; struct entry { @@ -213,6 +215,8 @@ int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss struct pa_sample_spec ss; assert(ma && rss); +/* DEBUG_TRAP;*/ + ss = *rss; if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0) return -1; diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 8a3388af9..c250d1cf2 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -154,7 +154,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { unsigned periods, fragsize; snd_pcm_uframes_t buffer_size; size_t frame_size; - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { fprintf(stderr, __FILE__": failed to parse module arguments\n"); goto fail; diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 8a7c4bcbf..91e6b7d68 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -39,8 +39,10 @@ #include "source-output.h" #include "source.h" #include "sample.h" - +#include "scache.h" +#include "sample-util.h" #include "authkey.h" +#include "debug.h" #define DEFAULT_COOKIE_FILE ".esd_auth" @@ -49,6 +51,10 @@ #define RECORD_BUFFER_SECONDS (5) #define RECORD_BUFFER_FRAGMENTS (100) +#define MAX_CACHE_SAMPLE_SIZE (1024000) + +#define SCACHE_PREFIX "esound~" + /* This is heavily based on esound's code */ struct connection { @@ -71,6 +77,11 @@ struct connection { struct pa_memblock *current_memblock; size_t memblock_index, fragment_size; } playback; + + + struct pa_memchunk scache_memchunk; + char *scache_name; + struct pa_sample_spec scache_sample_spec; }; struct pa_protocol_esound { @@ -105,6 +116,9 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons static int esd_proto_server_info(struct connection *c, esd_proto_t request, const void *data, size_t length); static int esd_proto_all_info(struct connection *c, esd_proto_t request, const void *data, size_t length); static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_sample_get_id(struct connection *c, esd_proto_t request, const void *data, size_t length); /* the big map of protocol handler info */ static struct proto_handler proto_map[ESD_PROTO_MAX] = { @@ -116,9 +130,9 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream rec" }, { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream mon" }, - { ESD_NAME_MAX + 3 * sizeof(int), NULL, "sample cache" }, - { sizeof(int), NULL, "sample free" }, - { sizeof(int), NULL, "sample play" }, + { ESD_NAME_MAX + 3 * sizeof(int), esd_proto_sample_cache, "sample cache" }, + { sizeof(int), esd_proto_sample_free_or_play, "sample free" }, + { sizeof(int), esd_proto_sample_free_or_play, "sample play" }, { sizeof(int), NULL, "sample loop" }, { sizeof(int), NULL, "sample stop" }, { -1, NULL, "TODO: sample kill" }, @@ -126,7 +140,7 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { ESD_KEY_LEN + sizeof(int), NULL, "standby" }, { ESD_KEY_LEN + sizeof(int), NULL, "resume" }, - { ESD_NAME_MAX, NULL, "sample getid" }, + { ESD_NAME_MAX, esd_proto_sample_get_id, "sample getid" }, { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream filter" }, { sizeof(int), esd_proto_server_info, "server info" }, @@ -170,6 +184,10 @@ static void connection_free(struct connection *c) { if (c->fixed_source) c->protocol->core->mainloop->cancel_fixed(c->protocol->core->mainloop, c->fixed_source); + + if (c->scache_memchunk.memblock) + pa_memblock_unref(c->scache_memchunk.memblock); + free(c->scache_name); free(c); } @@ -216,6 +234,22 @@ static void* connection_write(struct connection *c, size_t length) { return c->write_data+i; } +static void format_esd2native(int format, struct pa_sample_spec *ss) { + assert(ss); + + ss->channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1; + ss->format = ((format & ESD_MASK_BITS) == ESD_BITS16) ? PA_SAMPLE_S16NE : PA_SAMPLE_U8; +} + +static int format_native2esd(struct pa_sample_spec *ss) { + int format = 0; + + format = (ss->format == PA_SAMPLE_U8) ? ESD_BITS8 : ESD_BITS16; + format |= (ss->channels >= 2) ? ESD_STEREO : ESD_MONO; + + return format; +} + /*** esound commands ***/ static int esd_proto_connect(struct connection *c, esd_proto_t request, const void *data, size_t length) { @@ -260,8 +294,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); ss.rate = rate; - ss.channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1; - ss.format = ((format & ESD_MASK_BITS) == ESD_BITS16) ? PA_SAMPLE_S16NE : PA_SAMPLE_U8; + format_esd2native(format, &ss); if (!pa_sample_spec_valid(&ss)) return -1; @@ -313,8 +346,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); ss.rate = rate; - ss.channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1; - ss.format = ((format & ESD_MASK_BITS) == ESD_BITS16) ? PA_SAMPLE_S16NE : PA_SAMPLE_U8; + format_esd2native(format, &ss); if (!pa_sample_spec_valid(&ss)) return -1; @@ -390,8 +422,7 @@ static int esd_proto_server_info(struct connection *c, esd_proto_t request, cons if ((sink = get_output_sink(c->protocol))) { rate = sink->sample_spec.rate; - format = (sink->sample_spec.format == PA_SAMPLE_U8) ? ESD_BITS8 : ESD_BITS16; - format |= (sink->sample_spec.channels >= 2) ? ESD_STEREO : ESD_MONO; + format = format_native2esd(&sink->sample_spec); } response = connection_write(c, sizeof(int)*3); @@ -428,8 +459,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v if (conn->sink_input) { rate = conn->sink_input->sample_spec.rate; volume = (conn->sink_input->volume*0xFF)/0x100; - format = (conn->sink_input->sample_spec.format == PA_SAMPLE_U8) ? ESD_BITS8 : ESD_BITS16; - format |= (conn->sink_input->sample_spec.channels >= 2) ? ESD_STEREO : ESD_MONO; + format = format_native2esd(&conn->sink_input->sample_spec); } /* id */ @@ -488,6 +518,103 @@ static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const return 0; } +static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, const void *data, size_t length) { + struct pa_sample_spec ss; + int format, rate; + size_t sc_length; + uint32_t index; + int *ok; + char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1]; + assert(c && data && length == (ESD_NAME_MAX+3*sizeof(int))); + + format = maybe_swap_endian_32(c->swap_byte_order, *(int*)data); + rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); + + ss.rate = rate; + format_esd2native(format, &ss); + + sc_length = (size_t) maybe_swap_endian_32(c->swap_byte_order, (*((int*)data + 2))); + + if (sc_length >= MAX_CACHE_SAMPLE_SIZE) + return -1; + + strcpy(name, SCACHE_PREFIX); + strncpy(name+sizeof(SCACHE_PREFIX)-1, data+3*sizeof(int), ESD_NAME_MAX); + name[sizeof(name)-1] = 0; + + assert(!c->scache_memchunk.memblock); + c->scache_memchunk.memblock = pa_memblock_new(sc_length); + c->scache_memchunk.index = 0; + c->scache_memchunk.length = sc_length; + c->scache_sample_spec = ss; + assert(!c->scache_name); + c->scache_name = strdup(name); + assert(c->scache_name); + + c->state = ESD_CACHING_SAMPLE; + + pa_scache_add_item(c->protocol->core, c->scache_name, NULL, NULL, &index); + + ok = connection_write(c, sizeof(int)); + assert(ok); + + *ok = index+1; + + return 0; +} + +static int esd_proto_sample_get_id(struct connection *c, esd_proto_t request, const void *data, size_t length) { + int *ok; + uint32_t index; + char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1]; + assert(c && data && length == ESD_NAME_MAX); + + ok = connection_write(c, sizeof(int)); + assert(ok); + + *ok = -1; + + strcpy(name, SCACHE_PREFIX); + strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX); + name[sizeof(name)-1] = 0; + + if ((index = pa_scache_get_id_by_name(c->protocol->core, name)) != PA_IDXSET_INVALID) + *ok = (int) index +1; + + return 0; +} + +static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t request, const void *data, size_t length) { + int *ok; + const char *name; + uint32_t index; + assert(c && data && length == sizeof(int)); + + index = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(int*)data)-1; + + ok = connection_write(c, sizeof(int)); + assert(ok); + + *ok = 0; + + if ((name = pa_scache_get_name_by_id(c->protocol->core, index))) { + if (request == ESD_PROTO_SAMPLE_PLAY) { + struct pa_sink *sink; + + if ((sink = get_output_sink(c->protocol))) + if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0) + *ok = (int) index+1; + } else { + assert(request == ESD_PROTO_SAMPLE_FREE); + + if (pa_scache_remove_item(c->protocol->core, name) >= 0) + *ok = (int) index+1; + } + } + + return 0; +} + /*** client callbacks ***/ static void client_kill_cb(struct pa_client *c) { @@ -566,6 +693,40 @@ static int do_read(struct connection *c) { if (handler->proc(c, c->request, c->read_data, l) < 0) return -1; } + } else if (c->state == ESD_CACHING_SAMPLE) { + ssize_t r; + + assert(c->scache_memchunk.memblock && c->scache_name && c->scache_memchunk.index < c->scache_memchunk.length); + + if ((r = pa_iochannel_read(c->io, c->scache_memchunk.memblock->data+c->scache_memchunk.index, c->scache_memchunk.length-c->scache_memchunk.index)) <= 0) { + fprintf(stderr, __FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + return -1; + } + + c->scache_memchunk.index += r; + assert(c->scache_memchunk.index <= c->scache_memchunk.length); + + if (c->scache_memchunk.index == c->scache_memchunk.length) { + uint32_t index; + int *ok; + + c->scache_memchunk.index = 0; + pa_scache_add_item(c->protocol->core, c->scache_name, &c->scache_sample_spec, &c->scache_memchunk, &index); + + pa_memblock_unref(c->scache_memchunk.memblock); + c->scache_memchunk.memblock = NULL; + c->scache_memchunk.index = c->scache_memchunk.length = 0; + + free(c->scache_name); + c->scache_name = NULL; + + c->state = ESD_NEXT_REQUEST; + + ok = connection_write(c, sizeof(int)); + assert(ok); + *ok = index+1; + } + } else if (c->state == ESD_STREAMING_DATA && c->sink_input) { struct pa_memchunk chunk; ssize_t r; @@ -608,7 +769,6 @@ static int do_read(struct connection *c) { pa_memblockq_push_align(c->input_memblockq, &chunk, 0); assert(c->sink_input); pa_sink_notify(c->sink_input->sink); - } return 0; @@ -789,10 +949,14 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->playback.memblock_index = 0; c->playback.fragment_size = 0; + c->scache_memchunk.length = c->scache_memchunk.index = 0; + c->scache_memchunk.memblock = NULL; + c->scache_name = NULL; + c->fixed_source = c->protocol->core->mainloop->source_fixed(c->protocol->core->mainloop, fixed_callback, c); assert(c->fixed_source); c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); - + pa_idxset_put(c->protocol->connections, c, &c->index); } diff --git a/polyp/scache.c b/polyp/scache.c new file mode 100644 index 000000000..d2a84827c --- /dev/null +++ b/polyp/scache.c @@ -0,0 +1,181 @@ +#include +#include +#include + +#include "scache.h" +#include "sink-input.h" + +static void free_entry(struct pa_scache_entry *e) { + assert(e); + free(e->name); + if (e->memchunk.memblock) + pa_memblock_unref(e->memchunk.memblock); + free(e); +} + +void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index) { + struct pa_scache_entry *e; + int put; + assert(c && name); + + if (c->scache_hashmap && (e = pa_hashmap_get(c->scache_hashmap, name))) { + put = 0; + if (e->memchunk.memblock) + pa_memblock_unref(e->memchunk.memblock); + } else { + put = 1; + e = malloc(sizeof(struct pa_scache_entry)); + assert(e); + e->name = strdup(name); + assert(e->name); + } + + if (ss) + e->sample_spec = *ss; + else + memset(&e->sample_spec, 0, sizeof(struct pa_sample_spec)); + + if (chunk) { + e->memchunk = *chunk; + pa_memblock_ref(e->memchunk.memblock); + } else { + e->memchunk.memblock = NULL; + e->memchunk.index = e->memchunk.length = 0; + } + + if (put) { + if (!c->scache_hashmap) { + c->scache_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + assert(c->scache_hashmap); + } + + if (!c->scache_idxset) { + c->scache_idxset = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + assert(c->scache_idxset); + } + + pa_idxset_put(c->scache_idxset, e, &e->index); + pa_hashmap_put(c->scache_hashmap, e->name, e); + } + + if (index) + *index = e->index; +} + +int pa_scache_remove_item(struct pa_core *c, const char *name) { + struct pa_scache_entry *e; + assert(c && name); + + if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name))) + return -1; + + pa_hashmap_remove(c->scache_hashmap, name); + pa_idxset_remove_by_index(c->scache_idxset, e->index); + free_entry(e); + return 0; +} + +static void free_cb(void *p, void *userdata) { + struct pa_scache_entry *e = p; + assert(e); + free_entry(e); +} + +void pa_scache_free(struct pa_core *c) { + assert(c); + + if (c->scache_hashmap) { + pa_hashmap_free(c->scache_hashmap, free_cb, NULL); + c->scache_hashmap = NULL; + } + + if (c->scache_idxset) { + pa_idxset_free(c->scache_idxset, NULL, NULL); + c->scache_idxset = NULL; + } +} + +static void sink_input_kill(struct pa_sink_input *i) { + struct pa_memchunk *c; + assert(i && i->userdata); + c = i->userdata; + + pa_memblock_unref(c->memblock); + free(c); + pa_sink_input_free(i); +} + +static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { + struct pa_memchunk *c; + assert(i && chunk && i->userdata); + c = i->userdata; + + assert(c->length && c->memblock && c->memblock->length); + *chunk = *c; + pa_memblock_ref(c->memblock); + + return 0; +} + +static void sink_input_drop(struct pa_sink_input *i, size_t length) { + struct pa_memchunk *c; + assert(i && length && i->userdata); + c = i->userdata; + + assert(length <= c->length); + + c->length -= length; + c->index += length; + + if (c->length <= 0) + sink_input_kill(i); +} + +int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume) { + struct pa_sink_input *si; + struct pa_scache_entry *e; + struct pa_memchunk *chunk; + assert(c && name && sink); + + if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name))) + return -1; + + if (!e->memchunk.memblock) + return -1; + + if (!(si = pa_sink_input_new(sink, name, &e->sample_spec))) + return -1; + + si->volume = volume; + + si->peek = sink_input_peek; + si->drop = sink_input_drop; + si->kill = sink_input_kill; + si->userdata = chunk = malloc(sizeof(struct pa_memchunk)); + assert(chunk); + *chunk = e->memchunk; + pa_memblock_ref(chunk->memblock); + + return 0; +} + +const char * pa_scache_get_name_by_id(struct pa_core *c, uint32_t id) { + struct pa_scache_entry *e; + assert(c && id != PA_IDXSET_INVALID); + + if (!c->scache_idxset || !(e = pa_idxset_get_by_index(c->scache_idxset, id))) + return NULL; + + return e->name; + +} + +uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { + struct pa_scache_entry *e; + assert(c && name); + + if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name))) + return PA_IDXSET_INVALID; + + return e->index; +} diff --git a/polyp/scache.h b/polyp/scache.h new file mode 100644 index 000000000..73759b81e --- /dev/null +++ b/polyp/scache.h @@ -0,0 +1,24 @@ +#ifndef fooscachehfoo +#define fooscachehfoo + +#include "core.h" +#include "memchunk.h" +#include "sink.h" + +struct pa_scache_entry { + uint32_t index; + char *name; + struct pa_sample_spec sample_spec; + struct pa_memchunk memchunk; +}; + +void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index); + +int pa_scache_remove_item(struct pa_core *c, const char *name); +int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume); +void pa_scache_free(struct pa_core *c); + +const char *pa_scache_get_name_by_id(struct pa_core *c, uint32_t id); +uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name); + +#endif From 5a694fd508d3b5d9b2433f041aa24feb5a9ebc40 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 20 Jul 2004 01:08:07 +0000 Subject: [PATCH 0098/1514] add a todo item git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@99 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/todo b/doc/todo index 76b0d312f..326a64b01 100644 --- a/doc/todo +++ b/doc/todo @@ -2,6 +2,8 @@ *** 0.2 *** +- enable searchdir + - scache memory leak - scache remove() - scache in native protocol From 8705af792b0c95ec94822b1727addb54389db674 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 2 Aug 2004 16:24:14 +0000 Subject: [PATCH 0099/1514] add new module "module-x11-bell" fix scache memory leak git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@100 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 7 +- polyp/idxset.c | 16 ++-- polyp/module-x11-bell.c | 177 ++++++++++++++++++++++++++++++++++++++++ polyp/protocol-esound.c | 2 +- polyp/scache.c | 13 ++- polyp/sink-input.c | 4 +- 6 files changed, 204 insertions(+), 15 deletions(-) create mode 100644 polyp/module-x11-bell.c diff --git a/polyp/Makefile.am b/polyp/Makefile.am index d16155857..abe1d0747 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -65,7 +65,8 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-esound-protocol-tcp.la \ module-esound-protocol-unix.la \ module-native-protocol-tcp.la \ - module-native-protocol-unix.la + module-native-protocol-unix.la \ + module-x11-bell.la lib_LTLIBRARIES=libpolyp.la \ libpolyp-simple.la \ @@ -247,6 +248,10 @@ module_cli_la_SOURCES = module-cli.c module_cli_la_LDFLAGS = -module -avoid-version module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la +module_x11_bell_la_SOURCES = module-x11-bell.c +module_x11_bell_la_LDFLAGS = -module -avoid-version +module_x11_bell_la_LIBADD = $(AM_LIBADD) -lX11 -L/usr/X11R6/lib + libpolyp_la_SOURCES = polyplib.c polyplib.h \ polyplib-def.h \ tagstruct.c tagstruct.h \ diff --git a/polyp/idxset.c b/polyp/idxset.c index cecda6b7c..0072e3cd3 100644 --- a/polyp/idxset.c +++ b/polyp/idxset.c @@ -95,15 +95,13 @@ struct pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*com void pa_idxset_free(struct pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata) { assert(s); - if (free_func) { - while (s->iterate_list_head) { - struct idxset_entry *e = s->iterate_list_head; - s->iterate_list_head = s->iterate_list_head->iterate_next; - - if (free_func) - free_func(e->data, userdata); - free(e); - } + while (s->iterate_list_head) { + struct idxset_entry *e = s->iterate_list_head; + s->iterate_list_head = s->iterate_list_head->iterate_next; + + if (free_func) + free_func(e->data, userdata); + free(e); } free(s->hash_table); diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c new file mode 100644 index 000000000..296631347 --- /dev/null +++ b/polyp/module-x11-bell.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include + +#include +#include + +#include "module.h" +#include "sink.h" +#include "scache.h" +#include "modargs.h" + +struct x11_source { + void *io_source; + struct x11_source *next; +}; + +struct userdata { + struct pa_core *core; + Display *display; + struct x11_source *x11_sources; + int xkb_event_base; + + int sink_index; + char *scache_item; +}; + +static const char* const valid_modargs[] = { + "sink", + "sample", + "display", + NULL +}; + +static struct pa_sink* get_output_sink(struct userdata *u) { + struct pa_sink *s; + assert(u); + + if (!(s = pa_idxset_get_by_index(u->core->sinks, u->sink_index))) + s = pa_sink_get_default(u->core); + + u->sink_index = s ? s->index : PA_IDXSET_INVALID; + return s; +} + +static int ring_bell(struct userdata *u, int percent) { + struct pa_sink *s; + assert(u); + + if (!(s = get_output_sink(u))) { + fprintf(stderr, __FILE__": Invalid sink\n"); + return -1; + } + + if (pa_scache_play_item(u->core, u->scache_item, s, percent*2) < 0) { + fprintf(stderr, __FILE__": Failed to play sample\n"); + return -1; + } + + return 0; +} + +static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { + struct userdata *u = userdata; + assert(u); + + while (XPending(u->display)) { + XEvent e; + XkbBellNotifyEvent *bne; + XNextEvent(u->display, &e); + + if (((XkbEvent*) &e)->any.xkb_type != XkbBellNotify) + continue; + + bne = ((XkbBellNotifyEvent*) &e); + + if (ring_bell(u, bne->percent) < 0) { + fprintf(stderr, __FILE__": Ringing bell failed, reverting to X11 device bell.\n"); + XkbForceDeviceBell(u->display, bne->device, bne->bell_class, bne->bell_id, bne->percent); + } + } +} + +static void new_io_source(struct userdata *u, int fd) { + struct x11_source *s; + + s = malloc(sizeof(struct x11_source)); + assert(s); + s->io_source = u->core->mainloop->source_io(u->core->mainloop, fd, PA_MAINLOOP_API_IO_EVENT_INPUT, io_callback, u); + assert(s->io_source); + s->next = u->x11_sources; + u->x11_sources = s; +} + +int pa_module_init(struct pa_core *c, struct pa_module*m) { + struct userdata *u = NULL; + struct pa_modargs *ma = NULL; + int major, minor; + unsigned int auto_ctrls, auto_values; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + fprintf(stderr, __FILE__": failed to parse module arguments\n"); + goto fail; + } + + m->userdata = u = malloc(sizeof(struct userdata)); + assert(u); + u->core = c; + u->display = NULL; + u->x11_sources = NULL; + u->scache_item = strdup(pa_modargs_get_value(ma, "sample", "bell")); + assert(u->scache_item); + + if (pa_modargs_get_sink_index(ma, c, &u->sink_index) < 0) { + fprintf(stderr, __FILE__": Invalid sink specified\n"); + goto fail; + } + + if (!(u->display = XOpenDisplay(pa_modargs_get_value(ma, "display", NULL)))) { + fprintf(stderr, __FILE__": XOpenDisplay() failed\n"); + goto fail; + } + + new_io_source(u, ConnectionNumber(u->display)); + + major = XkbMajorVersion; + minor = XkbMinorVersion; + + if (!XkbLibraryVersion(&major, &minor)) { + fprintf(stderr, __FILE__": XkbLibraryVersion() failed\n"); + goto fail; + } + + major = XkbMajorVersion; + minor = XkbMinorVersion; + + if (!XkbQueryExtension(u->display, NULL, &u->xkb_event_base, NULL, &major, &minor)) { + fprintf(stderr, __FILE__": XkbQueryExtension() failed\n"); + goto fail; + } + + XkbSelectEvents(u->display, XkbUseCoreKbd, XkbBellNotifyMask, XkbBellNotifyMask); + auto_ctrls = auto_values = XkbAudibleBellMask; + XkbSetAutoResetControls(u->display, XkbAudibleBellMask, &auto_ctrls, &auto_values); + XkbChangeEnabledControls(u->display, XkbUseCoreKbd, XkbAudibleBellMask, 0); + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + if (m->userdata) + pa_module_done(c, m); + return -1; +} + +void pa_module_done(struct pa_core *c, struct pa_module*m) { + struct userdata *u = m->userdata; + assert(c && m && u); + + while (u->x11_sources) { + struct x11_source *s = u->x11_sources; + u->x11_sources = u->x11_sources->next; + c->mainloop->cancel_io(c->mainloop, s->io_source); + free(s); + } + + free(u->scache_item); + + if (u->display) + XCloseDisplay(u->display); + free(u); +} diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 91e6b7d68..7a141d3a1 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -202,7 +202,7 @@ static struct pa_sink* get_output_sink(struct pa_protocol_esound *p) { p->sink_index = s ? s->index : PA_IDXSET_INVALID; return s; } - + static struct pa_source* get_input_source(struct pa_protocol_esound *p) { struct pa_source *s; assert(p); diff --git a/polyp/scache.c b/polyp/scache.c index d2a84827c..c1505046d 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -1,9 +1,11 @@ #include #include #include +#include #include "scache.h" #include "sink-input.h" +#include "mainloop.h" static void free_entry(struct pa_scache_entry *e) { assert(e); @@ -70,7 +72,8 @@ int pa_scache_remove_item(struct pa_core *c, const char *name) { return -1; pa_hashmap_remove(c->scache_hashmap, name); - pa_idxset_remove_by_index(c->scache_idxset, e->index); + if (pa_idxset_remove_by_data(c->scache_idxset, e, NULL) != e) + assert(0); free_entry(e); return 0; } @@ -113,10 +116,14 @@ static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { assert(c->length && c->memblock && c->memblock->length); *chunk = *c; pa_memblock_ref(c->memblock); - + return 0; } +static void si_kill(void *i) { + sink_input_kill(i); +} + static void sink_input_drop(struct pa_sink_input *i, size_t length) { struct pa_memchunk *c; assert(i && length && i->userdata); @@ -128,7 +135,7 @@ static void sink_input_drop(struct pa_sink_input *i, size_t length) { c->index += length; if (c->length <= 0) - sink_input_kill(i); + pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); } int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume) { diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 5c2d3a139..25d8022f3 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -126,12 +126,14 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { if ((ret = i->peek(i, &tchunk)) < 0) return ret; + assert(tchunk.length); + l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); if (tchunk.length > l) tchunk.length = l; i->drop(i, tchunk.length); - + pa_resampler_run(i->resampler, &tchunk, &i->resampled_chunk); pa_memblock_unref(tchunk.memblock); } From e10b918009446186c80584273d2e3f5e84a6670b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 2 Aug 2004 19:45:02 +0000 Subject: [PATCH 0100/1514] add support for querying sample ist with esound protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@101 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - polyp/polypaudio.pa | 13 +++++--- polyp/protocol-esound.c | 68 ++++++++++++++++++++++++++++++++++++----- polyp/scache.c | 2 ++ polyp/scache.h | 1 + 5 files changed, 71 insertions(+), 14 deletions(-) diff --git a/doc/todo b/doc/todo index 326a64b01..73401e7a4 100644 --- a/doc/todo +++ b/doc/todo @@ -4,7 +4,6 @@ - enable searchdir -- scache memory leak - scache remove() - scache in native protocol - scache/debug.h copyright diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 177707ba7..79ca83ea5 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -19,9 +19,9 @@ # Load audio drivers -load module-alsa-sink -load module-alsa-source device=plughw:1,0 -#load module-oss device="/dev/dsp" +#load module-alsa-sink +#load module-alsa-source device=plughw:1,0 +load module-oss device="/dev/dsp" #load module-oss-mmap device="/dev/dsp" # Load several protocols @@ -30,12 +30,15 @@ load module-simple-protocol-tcp load module-native-protocol-unix load module-cli-protocol-unix +# Load X11 bell module +load module-x11-bell + # Load the CLI module load module-cli .nofail # Make some devices default -sink_default alsa_output -source_default alsa_input +sink_default oss_output +source_default oss_input diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 7a141d3a1..5db0442f9 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -53,7 +53,7 @@ #define MAX_CACHE_SAMPLE_SIZE (1024000) -#define SCACHE_PREFIX "esound~" +#define SCACHE_PREFIX "esound." /* This is heavily based on esound's code */ @@ -299,8 +299,10 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons if (!pa_sample_spec_valid(&ss)) return -1; - if (!(sink = get_output_sink(c->protocol))) + if (!(sink = get_output_sink(c->protocol))) { + fprintf(stderr, __FILE__": No output sink\n"); return -1; + } strncpy(name, data + sizeof(int)*2, sizeof(name)); name[sizeof(name)-1] = 0; @@ -438,6 +440,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v size_t t, k, s; struct connection *conn; size_t index = PA_IDXSET_INVALID; + unsigned nsamples; assert(c && data && length == sizeof(int)); if (esd_proto_server_info(c, request, data, length) < 0) @@ -445,7 +448,8 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v k = sizeof(int)*5+ESD_NAME_MAX; s = sizeof(int)*6+ESD_NAME_MAX; - response = connection_write(c, (t = s+k*(c->protocol->n_player+1))); + nsamples = c->protocol->core->scache_idxset ? pa_idxset_ncontents(c->protocol->core->scache_idxset) : 0; + response = connection_write(c, (t = s*(nsamples+1) + k*(c->protocol->n_player+1))); assert(k); for (conn = pa_idxset_first(c->protocol->connections, &index); conn; conn = pa_idxset_next(c->protocol->connections, &index)) { @@ -455,7 +459,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v continue; assert(t >= s+k+k); - + if (conn->sink_input) { rate = conn->sink_input->sample_spec.rate; volume = (conn->sink_input->volume*0xFF)/0x100; @@ -463,7 +467,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v } /* id */ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (int) conn->index); + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (int) (conn->index+1)); response += sizeof(int); /* name */ @@ -490,8 +494,56 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v t-= k; } - assert(t == s+k); - memset(response, 0, t); + assert(t == s*(nsamples+1)+k); + memset(response, 0, k); + response += k; + t -= k; + + if (nsamples) { + struct pa_scache_entry *ce; + + index = PA_IDXSET_INVALID; + for (ce = pa_idxset_first(c->protocol->core->scache_idxset, &index); ce; ce = pa_idxset_next(c->protocol->core->scache_idxset, &index)) { + assert(t >= s*2); + + /* id */ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (int) (ce->index+1)); + response += sizeof(int); + + /* name */ + if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0) + strncpy(response, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX); + else + snprintf(response, ESD_NAME_MAX, "native.%s", ce->name); + response += ESD_NAME_MAX; + + /* rate */ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, ce->sample_spec.rate); + response += sizeof(int); + + /* left */ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume*0xFF)/0x100); + response += sizeof(int); + + /*right*/ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume*0xFF)/0x100); + response += sizeof(int); + + /*format*/ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, format_native2esd(&ce->sample_spec)); + response += sizeof(int); + + /*length*/ + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (int) ce->memchunk.length); + response += sizeof(int); + + t -= s; + } + } + + assert(t == s); + memset(response, 0, s); + return 0; } @@ -501,7 +553,7 @@ static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const struct connection *conn; assert(c && data && length == sizeof(int)*3); - index = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(int*)data); + index = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(int*)data)-1; volume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); volume = (volume*0x100)/0xFF; diff --git a/polyp/scache.c b/polyp/scache.c index c1505046d..f1f7ec5af 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -32,6 +32,8 @@ void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_sp assert(e->name); } + e->volume = 0x100; + if (ss) e->sample_spec = *ss; else diff --git a/polyp/scache.h b/polyp/scache.h index 73759b81e..a1454ceac 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -8,6 +8,7 @@ struct pa_scache_entry { uint32_t index; char *name; + uint32_t volume; struct pa_sample_spec sample_spec; struct pa_memchunk memchunk; }; From 24291aff27c671c11619684cb10d3b36fdf87c0d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 3 Aug 2004 19:26:56 +0000 Subject: [PATCH 0101/1514] sample cache work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@102 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 + doc/todo | 12 +- polyp/Makefile.am | 15 +- polyp/cli-command.c | 55 ++++++ polyp/clitext.c | 5 +- polyp/module-alsa-sink.c | 4 +- polyp/module-alsa-source.c | 2 +- polyp/module-oss-mmap.c | 2 +- polyp/module-oss.c | 4 +- polyp/module-x11-bell.c | 2 +- polyp/native-common.h | 18 ++ polyp/pactl.c | 162 +++++++++++++++- polyp/pdispatch.c | 10 +- polyp/polyplib-def.h | 3 +- polyp/polyplib.c | 298 +++++++++++++++++++++-------- polyp/polyplib.h | 6 + polyp/protocol-esound.c | 6 +- polyp/protocol-native.c | 381 ++++++++++++++++++++++++++++++------- polyp/protocol-simple.c | 6 +- polyp/pstream.c | 7 +- polyp/resampler.c | 4 +- polyp/sample-util.c | 2 +- polyp/sample.c | 9 +- polyp/sample.h | 5 +- polyp/scache.c | 60 +----- polyp/sink.c | 2 +- polyp/source.c | 2 +- 27 files changed, 835 insertions(+), 251 deletions(-) diff --git a/configure.ac b/configure.ac index 3028228a4..9e5352a5e 100644 --- a/configure.ac +++ b/configure.ac @@ -46,6 +46,10 @@ PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) AC_SUBST(LIBSAMPLERATE_CFLAGS) AC_SUBST(LIBSAMPLERATE_LIBS) +PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.0 ]) +AC_SUBST(LIBSNDFILE_CFLAGS) +AC_SUBST(LIBSNDFILE_LIBS) + PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ]) AC_SUBST(ASOUNDLIB_CFLAGS) AC_SUBST(ASOUNDLIB_LIBS) diff --git a/doc/todo b/doc/todo index 73401e7a4..3f04bfca3 100644 --- a/doc/todo +++ b/doc/todo @@ -2,16 +2,14 @@ *** 0.2 *** -- enable searchdir - -- scache remove() -- scache in native protocol -- scache/debug.h copyright - - future cancellation - autoloading/autounloading -- doxygen - make mcalign merge chunks + +- doxygen + +- scache.[ch]/module-x11-bell.c/debug.h copyright +- enable searchdir - autoscan - rename clitext.[ch] to cli-text.[ch] diff --git a/polyp/Makefile.am b/polyp/Makefile.am index abe1d0747..48b984f80 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -107,11 +107,13 @@ polypaudio_SOURCES = idxset.c idxset.h \ clitext.c clitext.h \ tokenizer.c tokenizer.h \ dynarray.c dynarray.h \ - scache.c scache.h + scache.c scache.h \ + sound-file.c sound-file.h \ + play-memchunk.c play-memchunk.h -polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) +polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) -polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) +polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) polypaudio_LDFLAGS=-export-dynamic libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h @@ -270,7 +272,8 @@ libpolyp_la_SOURCES = polyplib.c polyplib.h \ memchunk.c memchunk.h \ authkey.c authkey.h \ socket-util.c socket-util.h \ - native-common.h + native-common.h \ + sample.c sample.h libpolyp_la_CFLAGS = $(AM_CFLAGS) libpolyp_mainloop_la_SOURCES = mainloop-api.h mainloop-api.c \ @@ -290,8 +293,8 @@ pacat_LDADD = $(AM_LDADD) libpolyp.la libpolyp-error.la libpolyp-mainloop.la pacat_CFLAGS = $(AM_CFLAGS) pactl_SOURCES = pactl.c -pactl_LDADD = $(AM_LDADD) libpolyp.la libpolyp-error.la libpolyp-mainloop.la -pactl_CFLAGS = $(AM_CFLAGS) +pactl_LDADD = $(AM_LDADD) libpolyp.la libpolyp-error.la libpolyp-mainloop.la $(LIBSNDFILE_LIBS) +pactl_CFLAGS = $(AM_CFLAGS) $(LIBSDNFILE_CFLAGS) pacat_simple_SOURCES = pacat-simple.c pacat_simple_LDADD = $(AM_LDADD) libpolyp-simple.la libpolyp-error.la diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 03bd125b3..826789ce2 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -42,6 +42,8 @@ #include "clitext.h" #include "scache.h" #include "sample-util.h" +#include "sound-file.h" +#include "play-memchunk.h" struct command { const char *name; @@ -72,6 +74,8 @@ static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokeni static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static const struct command commands[] = { { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, @@ -98,6 +102,8 @@ static const struct command commands[] = { { "scache_list", pa_cli_command_scache_list, "List all entries in the sample cache", 2}, { "scache_play", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3}, { "scache_remove", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2}, + { "scache_load", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: filename,name)", 3}, + { "play_file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3}, { NULL, NULL, NULL, 0 } }; @@ -488,6 +494,55 @@ static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer * return 0; } +static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *fname, *n; + struct pa_memchunk chunk; + struct pa_sample_spec ss; + assert(c && t && buf && fail && verbose); + + if (!(fname = pa_tokenizer_get(t, 1)) || !(n = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n"); + return -1; + } + + if (pa_sound_file_load(fname, &ss, &chunk) < 0) { + pa_strbuf_puts(buf, "Failed to load sound file.\n"); + return -1; + } + + pa_scache_add_item(c, n, &ss, &chunk, NULL); + pa_memblock_unref(chunk.memblock); + return 0; +} + +static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *fname, *sink_name; + struct pa_memchunk chunk; + struct pa_sample_spec ss; + struct pa_sink *sink; + int ret; + assert(c && t && buf && fail && verbose); + + if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n"); + return -1; + } + + if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) { + pa_strbuf_puts(buf, "No sink by that name.\n"); + return -1; + } + + if (pa_sound_file_load(fname, &ss, &chunk) < 0) { + pa_strbuf_puts(buf, "Failed to load sound file.\n"); + return -1; + } + + ret = pa_play_memchunk(sink, fname, &ss, &chunk, PA_VOLUME_NORM); + pa_memblock_unref(chunk.memblock); + return ret; +} + int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) { const char *cs; diff --git a/polyp/clitext.c b/polyp/clitext.c index d0c3f9a74..fbce22237 100644 --- a/polyp/clitext.c +++ b/polyp/clitext.c @@ -225,12 +225,13 @@ char *pa_scache_list_to_string(struct pa_core *c) { l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec); pa_strbuf_printf( - s, " name: <%s>\n\tindex: <%i>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n", + s, " name: <%s>\n\tindex: <%i>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n", e->name, e->index, ss, e->memchunk.length, - l); + l, + e->volume); } } diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index c250d1cf2..c19582272 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -142,7 +142,7 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { if (frames < 0) frames = 0; - return pa_samples_usec(frames * u->frame_size, &s->sample_spec); + return pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); } int pa_module_init(struct pa_core *c, struct pa_module*m) { @@ -165,7 +165,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { fprintf(stderr, __FILE__": failed to parse sample specification\n"); goto fail; } - frame_size = pa_sample_size(&ss); + frame_size = pa_frame_size(&ss); periods = 12; fragsize = 1024; diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 287a03502..a453944e9 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -149,7 +149,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { fprintf(stderr, __FILE__": failed to parse sample specification\n"); goto fail; } - frame_size = pa_sample_size(&ss); + frame_size = pa_frame_size(&ss); periods = 12; fragsize = 1024; diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 800eaf252..30ff3ce6b 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -198,7 +198,7 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { assert(s && u); do_write(u); - return pa_samples_usec(u->out_fill, &s->sample_spec); + return pa_bytes_to_usec(u->out_fill, &s->sample_spec); } int pa_module_init(struct pa_core *c, struct pa_module*m) { diff --git a/polyp/module-oss.c b/polyp/module-oss.c index d727534ac..51585ca9d 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -153,7 +153,7 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { return 0; } - return pa_samples_usec(arg, &s->sample_spec); + return pa_bytes_to_usec(arg, &s->sample_spec); } int pa_module_init(struct pa_core *c, struct pa_module*m) { @@ -258,7 +258,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; - u->sample_size = pa_sample_size(&ss); + u->sample_size = pa_frame_size(&ss); u->out_fragment_size = out_frag_size; u->in_fragment_size = in_frag_size; diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index 296631347..4da3c880e 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -110,7 +110,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->core = c; u->display = NULL; u->x11_sources = NULL; - u->scache_item = strdup(pa_modargs_get_value(ma, "sample", "bell")); + u->scache_item = strdup(pa_modargs_get_value(ma, "sample", "x11-bell")); assert(u->scache_item); if (pa_modargs_get_sink_index(ma, c, &u->sink_index) < 0) { diff --git a/polyp/native-common.h b/polyp/native-common.h index 2acbae8e8..dc730e4b0 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -41,6 +41,24 @@ enum { PA_COMMAND_RECORD_STREAM_KILLED, PA_COMMAND_STAT, PA_COMMAND_GET_PLAYBACK_LATENCY, + + PA_COMMAND_CREATE_UPLOAD_STREAM, + PA_COMMAND_DELETE_UPLOAD_STREAM, + PA_COMMAND_FINISH_UPLOAD_STREAM, + PA_COMMAND_PLAY_SAMPLE, + PA_COMMAND_REMOVE_SAMPLE, + + PA_COMMAND_GET_SINK, + PA_COMMAND_GET_SOURCE, + PA_COMMAND_GET_MODULE, + PA_COMMAND_GET_CLIENT, + PA_COMMAND_GET_SINK_INPUT, + PA_COMMAND_GET_SOURCE_OUTPUT, + PA_COMMAND_GET_SAMPLE, + + PA_COMMAND_SUBSCRIBE, + PA_COMMAND_SUBSCRIBE_EVENT, + PA_COMMAND_MAX }; diff --git a/polyp/pactl.c b/polyp/pactl.c index 61060c469..28b187b04 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -30,19 +30,37 @@ #include #include #include +#include + +#include #include #include #include #include +#include + +#define BUFSIZE 1024 static struct pa_context *context = NULL; static struct pa_mainloop_api *mainloop_api = NULL; +static char **process_argv = NULL; + +static SNDFILE *sndfile = NULL; +static struct pa_stream *sample_stream = NULL; +static struct pa_sample_spec sample_spec; +static size_t sample_length = 0; + +static char *sample_name = NULL; + static enum { NONE, EXIT, - STAT + STAT, + UPLOAD_SAMPLE, + PLAY_SAMPLE, + REMOVE_SAMPLE } action = NONE; static void quit(int ret) { @@ -78,6 +96,79 @@ static void stat_callback(struct pa_context *c, uint32_t blocks, uint32_t total, drain(); } +static void play_sample_callback(struct pa_context *c, int success, void *userdata) { + if (!success) { + fprintf(stderr, "Failed to play sample: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + drain(); +} + +static void remove_sample_callback(struct pa_context *c, int success, void *userdata) { + if (!success) { + fprintf(stderr, "Failed to remove sample: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + drain(); +} + +static void stream_die_callback(struct pa_stream *s, void *userdata) { + assert(s); + fprintf(stderr, "Stream deleted, exiting.\n"); + quit(1); +} + +static void finish_sample_callback(struct pa_stream *s, int success, void *userdata) { + assert(s); + + if (!success) { + fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + return; + } + + drain(); +} + +static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { + sf_count_t l; + float *d; + assert(s && length && sndfile); + + d = malloc(length); + assert(d); + + assert(sample_length >= length); + l = length/pa_frame_size(&sample_spec); + + if ((sf_readf_float(sndfile, d, l)) != l) { + free(d); + fprintf(stderr, "Premature end of file\n"); + quit(1); + } + + pa_stream_write(s, d, length); + free(d); + + sample_length -= length; + + if (sample_length <= 0) { + pa_stream_set_write_callback(sample_stream, NULL, NULL); + pa_stream_finish_sample(sample_stream, finish_sample_callback, NULL); + } +} + +static void upload_callback(struct pa_stream *s, int success, void *userdata) { + if (!success) { + fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + } +} + static void context_complete_callback(struct pa_context *c, int success, void *userdata) { assert(c); @@ -90,7 +181,19 @@ static void context_complete_callback(struct pa_context *c, int success, void *u if (action == STAT) pa_context_stat(c, stat_callback, NULL); - else { + else if (action == PLAY_SAMPLE) + pa_context_play_sample(c, process_argv[2], NULL, 0x100, play_sample_callback, NULL); + else if (action == REMOVE_SAMPLE) + pa_context_remove_sample(c, process_argv[2], remove_sample_callback, NULL); + else if (action == UPLOAD_SAMPLE) { + if (!(sample_stream = pa_context_upload_sample(c, sample_name, &sample_spec, sample_length, upload_callback, NULL))) { + fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(c))); + goto fail; + } + + pa_stream_set_die_callback(sample_stream, stream_die_callback, NULL); + pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL); + } else { assert(action == EXIT); pa_context_exit(c); drain(); @@ -105,11 +208,12 @@ fail: static void exit_signal_callback(void *id, int sig, void *userdata) { fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); - } int main(int argc, char *argv[]) { struct pa_mainloop* m = NULL; + char tmp[PATH_MAX]; + int ret = 1, r; if (argc >= 2) { @@ -117,13 +221,60 @@ int main(int argc, char *argv[]) { action = STAT; else if (!strcmp(argv[1], "exit")) action = EXIT; + else if (!strcmp(argv[1], "scache_upload")) { + struct SF_INFO sfinfo; + action = UPLOAD_SAMPLE; + + if (argc < 3) { + fprintf(stderr, "Please specify a sample file to load\n"); + goto quit; + } + + if (argc >= 4) + sample_name = argv[3]; + else { + char *f = strrchr(argv[2], '/'); + if (f) + f++; + else + f = argv[2]; + + strncpy(sample_name = tmp, f, strcspn(f, ".")); + } + + memset(&sfinfo, 0, sizeof(sfinfo)); + if (!(sndfile = sf_open(argv[2], SFM_READ, &sfinfo))) { + fprintf(stderr, "Failed to open sound file.\n"); + goto quit; + } + + sample_spec.format = PA_SAMPLE_FLOAT32; + sample_spec.rate = sfinfo.samplerate; + sample_spec.channels = sfinfo.channels; + + sample_length = sfinfo.frames*pa_frame_size(&sample_spec); + } else if (!strcmp(argv[1], "scache_play")) { + action = PLAY_SAMPLE; + if (argc < 3) { + fprintf(stderr, "You have to specify a sample name to play\n"); + goto quit; + } + } else if (!strcmp(argv[1], "scache_remove")) { + action = REMOVE_SAMPLE; + if (argc < 3) { + fprintf(stderr, "You have to specify a sample name to remove\n"); + goto quit; + } + } } if (action == NONE) { - fprintf(stderr, "No valid action specified. Use one of: stat, exit\n"); + fprintf(stderr, "No valid action specified. Use one of: stat, exit, scache_upload, scache_play, scache_remove\n"); goto quit; } + process_argv = argv; + if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); goto quit; @@ -162,5 +313,8 @@ quit: pa_mainloop_free(m); } + if (sndfile) + sf_close(sndfile); + return ret; } diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index a28458a40..2ab98b52a 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -30,6 +30,8 @@ #include "pdispatch.h" #include "native-common.h" +/*#define DEBUG_OPCODES*/ + #ifdef DEBUG_OPCODES static const char *command_names[PA_COMMAND_MAX] = { @@ -51,6 +53,11 @@ static const char *command_names[PA_COMMAND_MAX] = { [PA_COMMAND_RECORD_STREAM_KILLED] = "RECORD_STREAM_KILLED", [PA_COMMAND_STAT] = "STAT", [PA_COMMAND_GET_PLAYBACK_LATENCY] = "PLAYBACK_LATENCY", + [PA_COMMAND_CREATE_UPLOAD_STREAM] = "CREATE_UPLOAD_STREAM", + [PA_COMMAND_DELETE_UPLOAD_STREAM] = "DELETE_UPLOAD_STREAM", + [PA_COMMAND_FINISH_UPLOAD_STREAM] = "FINISH_UPLOAD_STREAM", + [PA_COMMAND_PLAY_SAMPLE] = "PLAY_SAMPLE", + [PA_COMMAND_REMOVE_SAMPLE] = "REMOVE_SAMPLE", }; #endif @@ -108,12 +115,13 @@ struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *mainloop, const st pd->drain_userdata = NULL; pd->in_use = pd->shall_free = 0; + return pd; } void pa_pdispatch_free(struct pa_pdispatch *pd) { assert(pd); - + if (pd->in_use) { pd->shall_free = 1; return; diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index e43f4b359..ec2d528b0 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -26,7 +26,8 @@ enum pa_stream_direction { PA_STREAM_PLAYBACK, - PA_STREAM_RECORD + PA_STREAM_RECORD, + PA_STREAM_UPLOAD }; struct pa_buffer_attr { diff --git a/polyp/polyplib.c b/polyp/polyplib.c index ea5003b40..b1052a8d3 100644 --- a/polyp/polyplib.c +++ b/polyp/polyplib.c @@ -81,6 +81,12 @@ struct pa_context { void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); void *stat_userdata; + + void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); + void *play_sample_userdata; + + void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); + void *remove_sample_userdata; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; }; @@ -92,12 +98,12 @@ struct pa_stream { char *name; struct pa_buffer_attr buffer_attr; struct pa_sample_spec sample_spec; - uint32_t device_index; uint32_t channel; int channel_valid; + uint32_t device_index; enum pa_stream_direction direction; - enum { STREAM_LOOKING_UP, STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; + enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; uint32_t requested_bytes; void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); @@ -117,6 +123,9 @@ struct pa_stream { void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); void *get_latency_userdata; + + void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); + void *finish_sample_userdata; }; static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); @@ -167,6 +176,12 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->stat_callback = NULL; c->stat_userdata = NULL; + c->play_sample_callback = NULL; + c->play_sample_userdata = NULL; + + c->remove_sample_callback = NULL; + c->remove_sample_userdata = NULL; + pa_check_for_sigpipe(); return c; } @@ -494,7 +509,7 @@ static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t return; s->requested_bytes += bytes; - + if (s->requested_bytes && s->write_callback) s->write_callback(s, s->requested_bytes, s->write_userdata); } @@ -517,7 +532,7 @@ static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, ui } if (pa_tagstruct_getu32(t, &s->channel) < 0 || - pa_tagstruct_getu32(t, &s->device_index) < 0 || + ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || !pa_tagstruct_eof(t)) { s->context->error = PA_ERROR_PROTOCOL; context_dead(s->context); @@ -525,14 +540,14 @@ static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, ui } s->channel_valid = 1; - pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, s); + pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); s->state = STREAM_READY; if (s->create_complete_callback) s->create_complete_callback(s, 1, s->create_complete_userdata); } -static void create_stream(struct pa_stream *s, uint32_t tdev_index) { +static void create_stream(struct pa_stream *s, const char *dev) { struct pa_tagstruct *t; uint32_t tag; assert(s); @@ -546,7 +561,8 @@ static void create_stream(struct pa_stream *s, uint32_t tdev_index) { pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_puts(t, s->name); pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_putu32(t, tdev_index); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); pa_tagstruct_putu32(t, s->buffer_attr.maxlength); if (s->direction == PA_STREAM_PLAYBACK) { pa_tagstruct_putu32(t, s->buffer_attr.tlength); @@ -559,49 +575,42 @@ static void create_stream(struct pa_stream *s, uint32_t tdev_index) { pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); } -static void lookup_device_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - uint32_t tdev; - assert(pd && s && s->state == STREAM_LOOKING_UP); +static struct pa_stream *internal_stream_new(struct pa_context *c) { + struct pa_stream *s; - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - if (s->create_complete_callback) - s->create_complete_callback(s, 0, s->create_complete_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &tdev) < 0 || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - create_stream(s, tdev); -} - -static void lookup_device(struct pa_stream *s, const char *tdev) { - struct pa_tagstruct *t; - uint32_t tag; + s = malloc(sizeof(struct pa_stream)); assert(s); + s->context = c; + + s->read_callback = NULL; + s->read_userdata = NULL; + s->write_callback = NULL; + s->write_userdata = NULL; + s->die_callback = NULL; + s->die_userdata = NULL; + s->create_complete_callback = NULL; + s->create_complete_userdata = NULL; + s->get_latency_callback = NULL; + s->get_latency_userdata = NULL; + s->finish_sample_callback = NULL; + s->finish_sample_userdata = NULL; + + s->name = NULL; + s->state = STREAM_CREATING; + s->requested_bytes = 0; + s->channel = 0; + s->channel_valid = 0; + s->device_index = (uint32_t) -1; + + memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - s->state = STREAM_LOOKING_UP; + s->next = c->first_stream; + if (s->next) + s->next->previous = s; + s->previous = NULL; + c->first_stream = s; - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_LOOKUP_SINK : PA_COMMAND_LOOKUP_SOURCE); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_puts(t, tdev); - - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, lookup_device_callback, s); + return s; } struct pa_stream* pa_stream_new( @@ -616,29 +625,15 @@ struct pa_stream* pa_stream_new( struct pa_stream *s; - assert(c && name && ss && c->state == CONTEXT_READY); - - s = malloc(sizeof(struct pa_stream)); + assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); + + s = internal_stream_new(c); assert(s); - s->context = c; - s->read_callback = NULL; - s->read_userdata = NULL; - s->write_callback = NULL; - s->write_userdata = NULL; - s->die_callback = NULL; - s->die_userdata = NULL; s->create_complete_callback = complete; - s->create_complete_userdata = NULL; - s->get_latency_callback = NULL; - s->get_latency_userdata = NULL; - + s->create_complete_userdata = userdata; s->name = strdup(name); s->state = STREAM_CREATING; - s->requested_bytes = 0; - s->channel = 0; - s->channel_valid = 0; - s->device_index = (uint32_t) -1; s->direction = dir; s->sample_spec = *ss; if (attr) @@ -651,16 +646,7 @@ struct pa_stream* pa_stream_new( s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; } - s->next = c->first_stream; - if (s->next) - s->next->previous = s; - s->previous = NULL; - c->first_stream = s; - - if (dev) - lookup_device(s, dev); - else - create_stream(s, (uint32_t) -1); + create_stream(s, dev); return s; } @@ -677,7 +663,8 @@ void pa_stream_free(struct pa_stream *s) { struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_DELETE_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); pa_tagstruct_putu32(t, s->context->ctag++); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); @@ -697,7 +684,6 @@ void pa_stream_free(struct pa_stream *s) { } void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { - assert(s && cb); s->write_callback = cb; s->write_userdata = userdata; } @@ -971,3 +957,163 @@ void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, pa_pstream_send_tagstruct(p->context->pstream, t); pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); } + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_stream *s; + struct pa_tagstruct *t; + uint32_t tag; + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = cb; + s->create_complete_userdata = userdata; + s->name = strdup(name); + s->state = STREAM_CREATING; + s->direction = PA_STREAM_UPLOAD; + s->sample_spec = *ss; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_sample_spec(t, ss); + pa_tagstruct_putu32(t, length); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); + + return s; +} + +static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 0, s->finish_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 1, s->finish_sample_userdata); +} + +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(p); + + p->finish_sample_callback = cb; + p->finish_sample_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); +} + +static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 0, c->play_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 1, c->play_sample_userdata); +} + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name && *name && (!dev || *dev)); + + if (!volume) + return; + + c->play_sample_callback = cb; + c->play_sample_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, volume); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); +} + +static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 0, c->remove_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 1, c->remove_sample_userdata); +} + +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name); + + c->remove_sample_callback = cb; + c->remove_sample_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); +} diff --git a/polyp/polyplib.h b/polyp/polyplib.h index 440b9658e..391cb0c86 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -91,4 +91,10 @@ void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, struct pa_context* pa_stream_get_context(struct pa_stream *p); +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + #endif diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 5db0442f9..d80445dee 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -312,7 +312,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons assert(!c->input_memblockq); l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); - c->input_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&ss), l/2, l/PLAYBACK_BUFFER_FRAGMENTS); + c->input_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&ss), l/2, l/PLAYBACK_BUFFER_FRAGMENTS); assert(c->input_memblockq); pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2); c->playback.fragment_size = l/10; @@ -376,7 +376,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co assert(!c->output_memblockq); l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS); - c->output_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&ss), 0, 0); + c->output_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&ss), 0, 0); assert(c->output_memblockq); pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2); @@ -936,7 +936,7 @@ static void sink_input_kill_cb(struct pa_sink_input *i) { static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); - return pa_samples_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); + return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); } /*** source_output callbacks ***/ diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 83c910d1d..a2332a127 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -40,6 +40,7 @@ #include "pstream-util.h" #include "authkey.h" #include "namereg.h" +#include "scache.h" struct connection; struct pa_protocol_native; @@ -53,6 +54,7 @@ struct record_stream { }; struct playback_stream { + int type; struct connection *connection; uint32_t index; struct pa_sink_input *sink_input; @@ -62,13 +64,32 @@ struct playback_stream { uint32_t drain_tag; }; +struct upload_stream { + int type; + struct connection *connection; + uint32_t index; + struct pa_memchunk memchunk; + size_t length; + char *name; + struct pa_sample_spec sample_spec; +}; + +struct output_stream { + int type; +}; + +enum { + UPLOAD_STREAM, + PLAYBACK_STREAM +}; + struct connection { int authorized; struct pa_protocol_native *protocol; struct pa_client *client; struct pa_pstream *pstream; struct pa_pdispatch *pdispatch; - struct pa_idxset *record_streams, *playback_streams; + struct pa_idxset *record_streams, *output_streams; uint32_t rrobin_index; }; @@ -93,25 +114,28 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_delete_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_delete_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, [PA_COMMAND_TIMEOUT] = { NULL }, [PA_COMMAND_REPLY] = { NULL }, [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream }, - [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_playback_stream }, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_stream }, [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = { command_drain_playback_stream }, [PA_COMMAND_CREATE_RECORD_STREAM] = { command_create_record_stream }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { command_delete_record_stream }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { command_delete_stream }, [PA_COMMAND_AUTH] = { command_auth }, [PA_COMMAND_REQUEST] = { NULL }, [PA_COMMAND_EXIT] = { command_exit }, @@ -120,11 +144,51 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_LOOKUP_SOURCE] = { command_lookup }, [PA_COMMAND_STAT] = { command_stat }, [PA_COMMAND_GET_PLAYBACK_LATENCY] = { command_get_playback_latency }, + [PA_COMMAND_CREATE_UPLOAD_STREAM] = { command_create_upload_stream }, + [PA_COMMAND_DELETE_UPLOAD_STREAM] = { command_delete_stream }, + [PA_COMMAND_FINISH_UPLOAD_STREAM] = { command_finish_upload_stream }, + [PA_COMMAND_PLAY_SAMPLE] = { command_play_sample }, + [PA_COMMAND_REMOVE_SAMPLE] = { command_remove_sample }, }; /* structure management */ -static struct record_stream* record_stream_new(struct connection *c, struct pa_source *source, struct pa_sample_spec *ss, const char *name, size_t maxlength, size_t fragment_size) { +static struct upload_stream* upload_stream_new(struct connection *c, const struct pa_sample_spec *ss, const char *name, size_t length) { + struct upload_stream *s; + assert(c && ss && name && length); + + s = malloc(sizeof(struct upload_stream)); + assert (s); + s->type = UPLOAD_STREAM; + s->connection = c; + s->sample_spec = *ss; + s->name = strdup(name); + assert(s->name); + + s->memchunk.memblock = NULL; + s->memchunk.index = 0; + s->memchunk.length = 0; + + s->length = length; + + pa_idxset_put(c->output_streams, s, &s->index); + return s; +} + +static void upload_stream_free(struct upload_stream *o) { + assert(o && o->connection); + + pa_idxset_remove_by_data(o->connection->output_streams, o, NULL); + + free(o->name); + + if (o->memchunk.memblock) + pa_memblock_unref(o->memchunk.memblock); + + free(o); +} + +static struct record_stream* record_stream_new(struct connection *c, struct pa_source *source, const struct pa_sample_spec *ss, const char *name, size_t maxlength, size_t fragment_size) { struct record_stream *s; struct pa_source_output *source_output; size_t base; @@ -143,7 +207,7 @@ static struct record_stream* record_stream_new(struct connection *c, struct pa_s s->source_output->owner = c->protocol->module; s->source_output->client = c->client; - s->memblockq = pa_memblockq_new(maxlength, 0, base = pa_sample_size(ss), 0, 0); + s->memblockq = pa_memblockq_new(maxlength, 0, base = pa_frame_size(ss), 0, 0); assert(s->memblockq); s->fragment_size = (fragment_size/base)*base; @@ -163,7 +227,7 @@ static void record_stream_free(struct record_stream* r) { free(r); } -static struct playback_stream* playback_stream_new(struct connection *c, struct pa_sink *sink, struct pa_sample_spec *ss, const char *name, +static struct playback_stream* playback_stream_new(struct connection *c, struct pa_sink *sink, const struct pa_sample_spec *ss, const char *name, size_t maxlength, size_t tlength, size_t prebuf, @@ -177,6 +241,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct s = malloc(sizeof(struct playback_stream)); assert (s); + s->type = PLAYBACK_STREAM; s->connection = c; s->sink_input = sink_input; @@ -188,13 +253,13 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct s->sink_input->owner = c->protocol->module; s->sink_input->client = c->client; - s->memblockq = pa_memblockq_new(maxlength, tlength, pa_sample_size(ss), prebuf, minreq); + s->memblockq = pa_memblockq_new(maxlength, tlength, pa_frame_size(ss), prebuf, minreq); assert(s->memblockq); s->requested_bytes = 0; s->drain_request = 0; - pa_idxset_put(c->playback_streams, s, &s->index); + pa_idxset_put(c->output_streams, s, &s->index); return s; } @@ -204,7 +269,7 @@ static void playback_stream_free(struct playback_stream* p) { if (p->drain_request) pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERROR_NOENTITY); - pa_idxset_remove_by_data(p->connection->playback_streams, p, NULL); + pa_idxset_remove_by_data(p->connection->output_streams, p, NULL); pa_sink_input_free(p->sink_input); pa_memblockq_free(p->memblockq); free(p); @@ -212,7 +277,7 @@ static void playback_stream_free(struct playback_stream* p) { static void connection_free(struct connection *c) { struct record_stream *r; - struct playback_stream *p; + struct output_stream *o; assert(c && c->protocol); pa_idxset_remove_by_data(c->protocol->connections, c, NULL); @@ -220,9 +285,12 @@ static void connection_free(struct connection *c) { record_stream_free(r); pa_idxset_free(c->record_streams, NULL, NULL); - while ((p = pa_idxset_first(c->playback_streams, NULL))) - playback_stream_free(p); - pa_idxset_free(c->playback_streams, NULL, NULL); + while ((o = pa_idxset_first(c->output_streams, NULL))) + if (o->type == PLAYBACK_STREAM) + playback_stream_free((struct playback_stream*) o); + else + upload_stream_free((struct upload_stream*) o); + pa_idxset_free(c->output_streams, NULL, NULL); pa_pdispatch_free(c->pdispatch); pa_pstream_free(c->pstream); @@ -351,7 +419,7 @@ static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { assert(i && i->userdata); s = i->userdata; - return pa_samples_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); + return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); } /*** source_output callbacks ***/ @@ -384,7 +452,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com struct playback_stream *s; size_t maxlength, tlength, prebuf, minreq; uint32_t sink_index; - const char *name; + const char *name, *sink_name; struct pa_sample_spec ss; struct pa_tagstruct *reply; struct pa_sink *sink; @@ -393,6 +461,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_get_sample_spec(t, &ss) < 0 || pa_tagstruct_getu32(t, &sink_index) < 0 || + pa_tagstruct_gets(t, &sink_name) < 0 || pa_tagstruct_getu32(t, &maxlength) < 0 || pa_tagstruct_getu32(t, &tlength) < 0 || pa_tagstruct_getu32(t, &prebuf) < 0 || @@ -407,10 +476,12 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com return; } - if (sink_index == (uint32_t) -1) + if (!*sink_name || sink_index == (uint32_t) -1) sink = pa_sink_get_default(c->protocol->core); - else + else if (sink_index != (uint32_t) -1) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); + else + sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK); if (!sink) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); @@ -433,10 +504,9 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com request_bytes(s); } -static void command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_delete_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t channel; - struct playback_stream *s; assert(c && t); if (pa_tagstruct_getu32(t, &channel) < 0 || @@ -449,13 +519,34 @@ static void command_delete_playback_stream(struct pa_pdispatch *pd, uint32_t com pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); return; } - - if (!(s = pa_idxset_get_by_index(c->playback_streams, channel))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); - return; - } - playback_stream_free(s); + if (command == PA_COMMAND_DELETE_PLAYBACK_STREAM) { + struct playback_stream *s; + if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != PLAYBACK_STREAM)) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + return; + } + + playback_stream_free(s); + } else if (command == PA_COMMAND_DELETE_RECORD_STREAM) { + struct record_stream *s; + if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + return; + } + + record_stream_free(s); + } else { + struct upload_stream *s; + assert(command == PA_COMMAND_DELETE_UPLOAD_STREAM); + if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + return; + } + + upload_stream_free(s); + } + pa_pstream_send_simple_ack(c->pstream, tag); } @@ -464,7 +555,7 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma struct record_stream *s; size_t maxlength, fragment_size; uint32_t source_index; - const char *name; + const char *name, *source_name; struct pa_sample_spec ss; struct pa_tagstruct *reply; struct pa_source *source; @@ -473,6 +564,7 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_get_sample_spec(t, &ss) < 0 || pa_tagstruct_getu32(t, &source_index) < 0 || + pa_tagstruct_gets(t, &source_name) < 0 || pa_tagstruct_getu32(t, &maxlength) < 0 || pa_tagstruct_getu32(t, &fragment_size) < 0 || !pa_tagstruct_eof(t)) { @@ -485,10 +577,12 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma return; } - if (source_index == (uint32_t) -1) + if (!*source_name || source_index == (uint32_t) -1) source = pa_source_get_default(c->protocol->core); - else + else if (source_index != (uint32_t) -1) source = pa_idxset_get_by_index(c->protocol->core->sources, source_index); + else + source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE); if (!source) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); @@ -510,32 +604,6 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_delete_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; - uint32_t channel; - struct record_stream *s; - assert(c && t); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - !pa_tagstruct_eof(t)) { - protocol_error(c); - return; - } - - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); - return; - } - - if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); - return; - } - - record_stream_free(s); - pa_pstream_send_simple_ack(c->pstream, tag); -} - static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; assert(c && t); @@ -652,7 +720,7 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm return; } - if (!(s = pa_idxset_get_by_index(c->playback_streams, index))) { + if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -709,7 +777,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma return; } - if (!(s = pa_idxset_get_by_index(c->playback_streams, index))) { + if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -723,6 +791,147 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma pa_pstream_send_tagstruct(c->pstream, reply); } +static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + struct upload_stream *s; + size_t length; + const char *name; + struct pa_sample_spec ss; + struct pa_tagstruct *reply; + assert(c && t && c->protocol && c->protocol->core); + + if (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_get_sample_spec(t, &ss) < 0 || + pa_tagstruct_getu32(t, &length) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if ((length % pa_frame_size(&ss)) != 0 || length <= 0 || !*name) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); + return; + } + + if (!(s = upload_stream_new(c, &ss, name, length))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + pa_tagstruct_putu32(reply, s->index); + pa_pstream_send_tagstruct(c->pstream, reply); + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REQUEST); + pa_tagstruct_putu32(reply, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(reply, s->index); + pa_tagstruct_putu32(reply, length); + pa_pstream_send_tagstruct(c->pstream, reply); +} + +static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t channel; + struct upload_stream *s; + uint32_t index; + assert(c && t); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + return; + } + + pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &index); + pa_pstream_send_simple_ack(c->pstream, tag); + upload_stream_free(s); +} + +static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t sink_index, volume; + struct pa_sink *sink; + const char *name, *sink_name; + assert(c && t); + + if (pa_tagstruct_getu32(t, &sink_index) < 0 || + pa_tagstruct_gets(t, &sink_name) < 0 || + pa_tagstruct_getu32(t, &volume) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!*sink_name && sink_index == (uint32_t) -1) + sink = pa_sink_get_default(c->protocol->core); + else if (sink_index != (uint32_t) -1) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); + else + sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK); + + if (!sink) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + if (pa_scache_play_item(c->protocol->core, name, sink, volume) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + const char *name; + assert(c && t); + + if (pa_tagstruct_gets(t, &name) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (pa_scache_remove_item(c->protocol->core, name) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_pstream_send_simple_ack(c->pstream, tag); +} + /*** pstream callbacks ***/ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { @@ -737,25 +946,55 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { struct connection *c = userdata; - struct playback_stream *stream; + struct output_stream *stream; assert(p && chunk && userdata); - if (!(stream = pa_idxset_get_by_index(c->playback_streams, channel))) { + if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) { fprintf(stderr, "protocol-native: client sent block for invalid stream.\n"); connection_free(c); return; } - if (chunk->length >= stream->requested_bytes) - stream->requested_bytes = 0; - else - stream->requested_bytes -= chunk->length; - - pa_memblockq_push_align(stream->memblockq, chunk, delta); - assert(stream->sink_input); - pa_sink_notify(stream->sink_input->sink); + if (stream->type == PLAYBACK_STREAM) { + struct playback_stream *p = (struct playback_stream*) stream; + if (chunk->length >= p->requested_bytes) + p->requested_bytes = 0; + else + p->requested_bytes -= chunk->length; + + pa_memblockq_push_align(p->memblockq, chunk, delta); + assert(p->sink_input); + pa_sink_notify(p->sink_input->sink); + /*fprintf(stderr, "Recieved %u bytes.\n", chunk->length);*/ + } else { + struct upload_stream *u = (struct upload_stream*) stream; + size_t l; + assert(u->type == UPLOAD_STREAM); - /*fprintf(stderr, "Recieved %u bytes.\n", chunk->length);*/ + if (!u->memchunk.memblock) { + if (u->length == chunk->length) { + u->memchunk = *chunk; + pa_memblock_ref(u->memchunk.memblock); + u->length = 0; + fprintf(stderr, "COPY\n"); + } else { + u->memchunk.memblock = pa_memblock_new(u->length); + u->memchunk.index = u->memchunk.length = 0; + } + } + + assert(u->memchunk.memblock); + + l = u->length; + if (l > chunk->length) + l = chunk->length; + + if (l > 0) { + memcpy(u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length, chunk->memblock->data+chunk->index, l); + u->memchunk.length += l; + u->length -= l; + } + } } static void pstream_die_callback(struct pa_pstream *p, void *userdata) { @@ -811,8 +1050,8 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo assert(c->pdispatch); c->record_streams = pa_idxset_new(NULL, NULL); - c->playback_streams = pa_idxset_new(NULL, NULL); - assert(c->record_streams && c->playback_streams); + c->output_streams = pa_idxset_new(NULL, NULL); + assert(c->record_streams && c->output_streams); c->rrobin_index = PA_IDXSET_INVALID; diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 3a52e311f..037d4f9ae 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -221,7 +221,7 @@ static void sink_input_kill_cb(struct pa_sink_input *i) { static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); - return pa_samples_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); + return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); } /*** source_output callbacks ***/ @@ -319,7 +319,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->sink_input->userdata = c; l = (size_t) (pa_bytes_per_second(&p->sample_spec)*PLAYBACK_BUFFER_SECONDS); - c->input_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&p->sample_spec), l/2, l/PLAYBACK_BUFFER_FRAGMENTS); + c->input_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&p->sample_spec), l/2, l/PLAYBACK_BUFFER_FRAGMENTS); assert(c->input_memblockq); pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5); c->playback.fragment_size = l/10; @@ -348,7 +348,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->source_output->userdata = c; l = (size_t) (pa_bytes_per_second(&p->sample_spec)*RECORD_BUFFER_SECONDS); - c->output_memblockq = pa_memblockq_new(l, 0, pa_sample_size(&p->sample_spec), 0, 0); + c->output_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&p->sample_spec), 0, 0); pa_iochannel_socket_set_sndbuf(io, l/RECORD_BUFFER_FRAGMENTS*2); } diff --git a/polyp/pstream.c b/polyp/pstream.c index 3076b776f..7d576a16e 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -23,6 +23,7 @@ #include #endif +#include #include #include #include @@ -40,7 +41,7 @@ enum pa_pstream_descriptor_index { typedef uint32_t pa_pstream_descriptor[PA_PSTREAM_DESCRIPTOR_MAX]; #define PA_PSTREAM_DESCRIPTOR_SIZE (PA_PSTREAM_DESCRIPTOR_MAX*sizeof(uint32_t)) -#define FRAME_SIZE_MAX (1024*64) +#define FRAME_SIZE_MAX (1024*500) /* half a megabyte */ struct item_info { enum { PA_PSTREAM_ITEM_PACKET, PA_PSTREAM_ITEM_MEMBLOCK } type; @@ -361,8 +362,10 @@ static void do_read(struct pa_pstream *p) { /* Reading of frame descriptor complete */ /* Frame size too large */ - if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) > FRAME_SIZE_MAX) + if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) > FRAME_SIZE_MAX) { + fprintf(stderr, "frame size too large\n"); goto die; + } assert(!p->read.packet && !p->read.memblock); diff --git a/polyp/resampler.c b/polyp/resampler.c index 320d71195..adf08e80c 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -75,8 +75,8 @@ struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const stru r->i_ss = *a; r->o_ss = *b; - r->i_sz = pa_sample_size(a); - r->o_sz = pa_sample_size(b); + r->i_sz = pa_frame_size(a); + r->o_sz = pa_frame_size(b); r->to_float32_func = pa_get_convert_to_float32_function(a->format); r->from_float32_func = pa_get_convert_from_float32_function(b->format); diff --git a/polyp/sample-util.c b/polyp/sample-util.c index d608ce1bc..5b1cd6264 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -111,7 +111,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, uint32_t volume) { int16_t *d; size_t n; - assert(c && spec && (c->length % pa_sample_size(spec) == 0)); + assert(c && spec && (c->length % pa_frame_size(spec) == 0)); assert(spec->format == PA_SAMPLE_S16NE); if (volume == PA_VOLUME_NORM) diff --git a/polyp/sample.c b/polyp/sample.c index 8179475dd..e4c4bd526 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -28,7 +28,7 @@ #include "sample.h" -size_t pa_sample_size(const struct pa_sample_spec *spec) { +size_t pa_frame_size(const struct pa_sample_spec *spec) { assert(spec); size_t b = 1; @@ -55,14 +55,13 @@ size_t pa_sample_size(const struct pa_sample_spec *spec) { size_t pa_bytes_per_second(const struct pa_sample_spec *spec) { assert(spec); - return spec->rate*pa_sample_size(spec); + return spec->rate*pa_frame_size(spec); } - -uint32_t pa_samples_usec(size_t length, const struct pa_sample_spec *spec) { +uint32_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec) { assert(spec); - return (uint32_t) (((double) length /pa_sample_size(spec))/spec->rate*1000000); + return (uint32_t) (((double) length /pa_frame_size(spec))/spec->rate*1000000); } int pa_sample_spec_valid(const struct pa_sample_spec *spec) { diff --git a/polyp/sample.h b/polyp/sample.h index 825441f28..01a4efcf2 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -52,12 +52,11 @@ struct pa_sample_spec { }; size_t pa_bytes_per_second(const struct pa_sample_spec *spec); -size_t pa_sample_size(const struct pa_sample_spec *spec); -uint32_t pa_samples_usec(size_t length, const struct pa_sample_spec *spec); +size_t pa_frame_size(const struct pa_sample_spec *spec); +uint32_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec); int pa_sample_spec_valid(const struct pa_sample_spec *spec); int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b); - #define PA_SAMPLE_SNPRINT_MAX_LENGTH 32 void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec); diff --git a/polyp/scache.c b/polyp/scache.c index f1f7ec5af..21af0e221 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -6,6 +6,8 @@ #include "scache.h" #include "sink-input.h" #include "mainloop.h" +#include "sample-util.h" +#include "play-memchunk.h" static void free_entry(struct pa_scache_entry *e) { assert(e); @@ -100,50 +102,8 @@ void pa_scache_free(struct pa_core *c) { } } -static void sink_input_kill(struct pa_sink_input *i) { - struct pa_memchunk *c; - assert(i && i->userdata); - c = i->userdata; - - pa_memblock_unref(c->memblock); - free(c); - pa_sink_input_free(i); -} - -static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { - struct pa_memchunk *c; - assert(i && chunk && i->userdata); - c = i->userdata; - - assert(c->length && c->memblock && c->memblock->length); - *chunk = *c; - pa_memblock_ref(c->memblock); - - return 0; -} - -static void si_kill(void *i) { - sink_input_kill(i); -} - -static void sink_input_drop(struct pa_sink_input *i, size_t length) { - struct pa_memchunk *c; - assert(i && length && i->userdata); - c = i->userdata; - - assert(length <= c->length); - - c->length -= length; - c->index += length; - - if (c->length <= 0) - pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); -} - int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume) { - struct pa_sink_input *si; struct pa_scache_entry *e; - struct pa_memchunk *chunk; assert(c && name && sink); if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name))) @@ -151,20 +111,10 @@ int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sin if (!e->memchunk.memblock) return -1; - - if (!(si = pa_sink_input_new(sink, name, &e->sample_spec))) + + if (pa_play_memchunk(sink, name, &e->sample_spec, &e->memchunk, pa_volume_multiply(volume, e->volume)) < 0) return -1; - - si->volume = volume; - - si->peek = sink_input_peek; - si->drop = sink_input_drop; - si->kill = sink_input_kill; - si->userdata = chunk = malloc(sizeof(struct pa_memchunk)); - assert(chunk); - *chunk = e->memchunk; - pa_memblock_ref(chunk->memblock); - + return 0; } diff --git a/polyp/sink.c b/polyp/sink.c index 20fa76a68..c2c873c6d 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -41,7 +41,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co char *n = NULL; char st[256]; int r; - assert(core && name && spec); + assert(core && name && *name && spec); s = malloc(sizeof(struct pa_sink)); assert(s); diff --git a/polyp/source.c b/polyp/source.c index ccde0e2f9..136354145 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -36,7 +36,7 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail struct pa_source *s; char st[256]; int r; - assert(core && spec && name); + assert(core && spec && name && *name); s = malloc(sizeof(struct pa_source)); assert(s); From 46091a9237f17f4295dca7140d8d70b4fce8b357 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 4 Aug 2004 16:39:30 +0000 Subject: [PATCH 0102/1514] introduce pa_xmalloc() and friends implement module auto loading git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@103 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +- polyp/Makefile.am | 7 ++- polyp/alsa-util.c | 13 +++--- polyp/cli-command.c | 96 ++++++++++++++++++++++++++------------ polyp/cli.c | 8 ++-- polyp/client.c | 14 +++--- polyp/clitext.c | 49 ++++++++++++++----- polyp/clitext.h | 1 + polyp/cmdline.c | 8 ++-- polyp/core.c | 19 ++++++-- polyp/core.h | 8 ++-- polyp/dynarray.c | 10 ++-- polyp/hashmap.c | 18 +++---- polyp/idxset.c | 28 +++++------ polyp/iochannel.c | 5 +- polyp/ioline.c | 18 +++---- polyp/main.c | 3 +- polyp/mainloop-api.c | 7 +-- polyp/mainloop-signal.c | 8 ++-- polyp/mainloop.c | 24 ++++------ polyp/memblock.c | 14 +++--- polyp/memblockq.c | 15 +++--- polyp/memchunk.c | 11 ++--- polyp/modargs.c | 62 ++++++------------------ polyp/modargs.h | 3 -- polyp/module-alsa-sink.c | 52 ++++++++++++--------- polyp/module-alsa-source.c | 47 +++++++++++-------- polyp/module-oss-mmap.c | 35 ++++++++------ polyp/module-oss.c | 27 ++++++++--- polyp/module-pipe-sink.c | 18 +++---- polyp/module-x11-bell.c | 38 +++++---------- polyp/module.c | 88 ++++++++++++++++++++++++++++------ polyp/module.h | 8 ++++ polyp/namereg.c | 78 ++++++++++++++++++++++++++----- polyp/namereg.h | 3 +- polyp/packet.c | 13 ++---- polyp/pdispatch.c | 11 ++--- polyp/polypaudio.pa | 10 +++- polyp/polyplib-simple.c | 16 +++---- polyp/polyplib.c | 27 +++++------ polyp/protocol-cli.c | 6 +-- polyp/protocol-esound.c | 85 ++++++++++----------------------- polyp/protocol-native.c | 55 +++++++++------------- polyp/protocol-simple.c | 48 +++++++------------ polyp/pstream.c | 14 +++--- polyp/queue.c | 13 +++--- polyp/resampler.c | 16 +++---- polyp/scache.c | 11 ++--- polyp/sink-input.c | 10 ++-- polyp/sink.c | 29 ++++-------- polyp/sink.h | 2 - polyp/socket-client.c | 6 +-- polyp/socket-server.c | 14 ++---- polyp/socket-util.c | 11 ++--- polyp/source-output.c | 10 ++-- polyp/source.c | 28 +++-------- polyp/source.h | 2 - polyp/strbuf.c | 17 +++---- polyp/tagstruct.c | 13 +++--- polyp/tokenizer.c | 14 +++--- polyp/util.c | 4 +- 61 files changed, 700 insertions(+), 631 deletions(-) diff --git a/doc/todo b/doc/todo index 3f04bfca3..7cf36b086 100644 --- a/doc/todo +++ b/doc/todo @@ -3,12 +3,11 @@ *** 0.2 *** - future cancellation -- autoloading/autounloading - make mcalign merge chunks - doxygen -- scache.[ch]/module-x11-bell.c/debug.h copyright +- several files: copyright and config.h - enable searchdir - autoscan - rename clitext.[ch] to cli-text.[ch] diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 48b984f80..0af99110f 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -109,7 +109,9 @@ polypaudio_SOURCES = idxset.c idxset.h \ dynarray.c dynarray.h \ scache.c scache.h \ sound-file.c sound-file.h \ - play-memchunk.c play-memchunk.h + play-memchunk.c play-memchunk.h \ + autoload.c autoload.h \ + xmalloc.c xmalloc.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) @@ -273,7 +275,8 @@ libpolyp_la_SOURCES = polyplib.c polyplib.h \ authkey.c authkey.h \ socket-util.c socket-util.h \ native-common.h \ - sample.c sample.h + sample.c sample.h \ + xmalloc.c xmalloc.h libpolyp_la_CFLAGS = $(AM_CFLAGS) libpolyp_mainloop_la_SOURCES = mainloop-api.h mainloop-api.c \ diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index 7f266df56..43562378d 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -27,6 +27,7 @@ #include "alsa-util.h" #include "sample.h" +#include "xmalloc.h" int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *buffer_size) { int ret = 0; @@ -66,15 +67,13 @@ int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, void *n_io_sources = snd_pcm_poll_descriptors_count(pcm_handle); - pfds = malloc(sizeof(struct pollfd) * *n_io_sources); - assert(pfds); + pfds = pa_xmalloc(sizeof(struct pollfd) * *n_io_sources); if (snd_pcm_poll_descriptors(pcm_handle, pfds, *n_io_sources) < 0) { - free(pfds); + pa_xfree(pfds); return -1; } - *io_sources = malloc(sizeof(void*) * *n_io_sources); - assert(io_sources); + *io_sources = pa_xmalloc(sizeof(void*) * *n_io_sources); for (i = 0, ios = *io_sources, ppfd = pfds; i < *n_io_sources; i++, ios++, ppfd++) { *ios = m->source_io(m, ppfd->fd, @@ -83,7 +82,7 @@ int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, void assert(*ios); } - free(pfds); + pa_xfree(pfds); return 0; } @@ -94,5 +93,5 @@ void pa_free_io_sources(struct pa_mainloop_api* m, void **io_sources, unsigned n for (ios = io_sources, i = 0; i < n_io_sources; i++, ios++) m->cancel_io(m, *ios); - free(io_sources); + pa_xfree(io_sources); } diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 826789ce2..6386d4e45 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -44,6 +44,8 @@ #include "sample-util.h" #include "sound-file.h" #include "play-memchunk.h" +#include "autoload.h" +#include "xmalloc.h" struct command { const char *name; @@ -76,6 +78,9 @@ static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer * static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static const struct command commands[] = { { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, @@ -99,11 +104,16 @@ static const struct command commands[] = { { "kill_client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, { "kill_sink_input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2}, { "kill_source_output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2}, - { "scache_list", pa_cli_command_scache_list, "List all entries in the sample cache", 2}, + { "scache_list", pa_cli_command_scache_list, "List all entries in the sample cache", 1}, { "scache_play", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3}, { "scache_remove", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2}, { "scache_load", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: filename,name)", 3}, { "play_file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3}, + { "autoload_list", pa_cli_command_autoload_list, "List autoload entries", 1}, + { "autoload_sink_add", pa_cli_command_autoload_add, "Add autoload entry for a sink (args: sink, name, arguments)", 4}, + { "autoload_source_add", pa_cli_command_autoload_add, "Add autoload entry for a source (args: source, name, arguments)", 4}, + { "autoload_sink_remove", pa_cli_command_autoload_remove, "Remove autoload entry for a sink (args: sink)", 2}, + { "autoload_source_remove", pa_cli_command_autoload_remove, "Remove autoload entry for a source (args: source)", 2}, { NULL, NULL, NULL, 0 } }; @@ -144,7 +154,7 @@ static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, str s = pa_module_list_to_string(c); assert(s); pa_strbuf_puts(buf, s); - free(s); + pa_xfree(s); return 0; } @@ -154,7 +164,7 @@ static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, str s = pa_client_list_to_string(c); assert(s); pa_strbuf_puts(buf, s); - free(s); + pa_xfree(s); return 0; } @@ -164,7 +174,7 @@ static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struc s = pa_sink_list_to_string(c); assert(s); pa_strbuf_puts(buf, s); - free(s); + pa_xfree(s); return 0; } @@ -174,7 +184,7 @@ static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, str s = pa_source_list_to_string(c); assert(s); pa_strbuf_puts(buf, s); - free(s); + pa_xfree(s); return 0; } @@ -184,7 +194,7 @@ static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, s = pa_sink_input_list_to_string(c); assert(s); pa_strbuf_puts(buf, s); - free(s); + pa_xfree(s); return 0; } @@ -194,7 +204,7 @@ static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer s = pa_source_output_list_to_string(c); assert(s); pa_strbuf_puts(buf, s); - free(s); + pa_xfree(s); return 0; } @@ -214,6 +224,7 @@ static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_cli_command_sink_inputs(c, t, buf, fail, verbose); pa_cli_command_source_outputs(c, t, buf, fail, verbose); pa_cli_command_scache_list(c, t, buf, fail, verbose); + pa_cli_command_autoload_list(c, t, buf, fail, verbose); return 0; } @@ -284,7 +295,7 @@ static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, return -1; } - if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) { + if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) { pa_strbuf_puts(buf, "No sink found by this name or index.\n"); return -1; } @@ -333,7 +344,6 @@ static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokeniz static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { const char *n; - struct pa_sink *sink; assert(c && t); if (!(n = pa_tokenizer_get(t, 1))) { @@ -341,18 +351,12 @@ static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t return -1; } - if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) { - pa_strbuf_puts(buf, "No sink found by this name or index.\n"); - return -1; - } - - c->default_sink_index = sink->index; + pa_namereg_set_default(c, n, PA_NAMEREG_SINK); return 0; } static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { const char *n; - struct pa_source *source; assert(c && t); if (!(n = pa_tokenizer_get(t, 1))) { @@ -360,12 +364,7 @@ static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer return -1; } - if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) { - pa_strbuf_puts(buf, "No source found by this name or index.\n"); - return -1; - } - - c->default_source_index = source->index; + pa_namereg_set_default(c, n, PA_NAMEREG_SOURCE); return 0; } @@ -450,7 +449,7 @@ static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, s = pa_scache_list_to_string(c); assert(s); pa_strbuf_puts(buf, s); - free(s); + pa_xfree(s); return 0; } @@ -464,7 +463,7 @@ static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, return -1; } - if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) { + if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, 1))) { pa_strbuf_puts(buf, "No sink by that name.\n"); return -1; } @@ -528,7 +527,7 @@ static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, s return -1; } - if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) { + if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, 1))) { pa_strbuf_puts(buf, "No sink by that name.\n"); return -1; } @@ -543,6 +542,46 @@ static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, s return ret; } +static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *devname, *module; + assert(c && t && buf && fail && verbose); + + if (!(devname = pa_tokenizer_get(t, 1)) || !(module = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a device name, a module name and optionally module arguments\n"); + return -1; + } + + pa_autoload_add(c, devname, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, pa_tokenizer_get(t, 3)); + return 0; +} + +static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *devname; + assert(c && t && buf && fail && verbose); + + if (!(devname = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a device name\n"); + return -1; + } + + if (pa_autoload_remove(c, devname, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) < 0) { + pa_strbuf_puts(buf, "Failed to remove autload entry\n"); + return -1; + } + + return 0; +} + +static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + char *s; + assert(c && t); + s = pa_autoload_list_to_string(c); + assert(s); + pa_strbuf_puts(buf, s); + pa_xfree(s); + return 0; +} + int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) { const char *cs; @@ -654,14 +693,13 @@ int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *b p = s; while (*p) { size_t l = strcspn(p, linebreak); - char *line = strndup(p, l); - assert(line); + char *line = pa_xstrndup(p, l); if (pa_cli_command_execute_line(c, line, buf, fail, verbose) < 0&& *fail) { - free(line); + pa_xfree(line); return -1; } - free(line); + pa_xfree(line); p += l; p += strspn(p, linebreak); diff --git a/polyp/cli.c b/polyp/cli.c index f2aa5a659..f0ad48309 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -41,6 +41,7 @@ #include "namereg.h" #include "clitext.h" #include "cli-command.h" +#include "xmalloc.h" struct pa_cli { struct pa_core *core; @@ -65,8 +66,7 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct struct pa_cli *c; assert(io); - c = malloc(sizeof(struct pa_cli)); - assert(c); + c = pa_xmalloc(sizeof(struct pa_cli)); c->core = core; c->line = pa_ioline_new(io); assert(c->line); @@ -95,7 +95,7 @@ void pa_cli_free(struct pa_cli *c) { assert(c); pa_ioline_free(c->line); pa_client_free(c->client); - free(c); + pa_xfree(c); } static void client_kill(struct pa_client *client) { @@ -132,7 +132,7 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) pa_cli_command_execute_line(c->core, s, buf, &c->fail, &c->verbose); c->defer_kill--; pa_ioline_puts(line, p = pa_strbuf_tostring_free(buf)); - free(p); + pa_xfree(p); if (c->kill_requested) { if (c->eof_callback) diff --git a/polyp/client.c b/polyp/client.c index 0294c9e2c..83a6264de 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -29,15 +29,15 @@ #include #include "client.h" +#include "xmalloc.h" struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, char *name) { struct pa_client *c; int r; assert(core); - c = malloc(sizeof(struct pa_client)); - assert(c); - c->name = name ? strdup(name) : NULL; + c = pa_xmalloc(sizeof(struct pa_client)); + c->name = pa_xstrdup(name); c->owner = NULL; c->core = core; c->protocol_name = protocol_name; @@ -58,8 +58,8 @@ void pa_client_free(struct pa_client *c) { pa_idxset_remove_by_data(c->core->clients, c, NULL); fprintf(stderr, "client: freed %u \"%s\"\n", c->index, c->name); - free(c->name); - free(c); + pa_xfree(c->name); + pa_xfree(c); } void pa_client_kill(struct pa_client *c) { @@ -74,6 +74,6 @@ void pa_client_kill(struct pa_client *c) { void pa_client_rename(struct pa_client *c, const char *name) { assert(c); - free(c->name); - c->name = name ? strdup(name) : NULL; + pa_xfree(c->name); + c->name = pa_xstrdup(name); } diff --git a/polyp/clitext.c b/polyp/clitext.c index fbce22237..6d2d62539 100644 --- a/polyp/clitext.c +++ b/polyp/clitext.c @@ -36,6 +36,7 @@ #include "strbuf.h" #include "sample-util.h" #include "scache.h" +#include "autoload.h" char *pa_module_list_to_string(struct pa_core *c) { struct pa_strbuf *s; @@ -49,7 +50,7 @@ char *pa_module_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_ncontents(c->modules)); for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) - pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\targument: <%s>\n", m->index, m->name, m->argument); + pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\targument: <%s>\n\tused: %i\n\tauto unload: %s\n", m->index, m->name, m->argument, m->n_used, m->auto_unload ? "yes" : "no"); return pa_strbuf_tostring_free(s); } @@ -77,7 +78,7 @@ char *pa_client_list_to_string(struct pa_core *c) { char *pa_sink_list_to_string(struct pa_core *c) { struct pa_strbuf *s; - struct pa_sink *sink, *default_sink; + struct pa_sink *sink; uint32_t index = PA_IDXSET_INVALID; assert(c); @@ -86,8 +87,6 @@ char *pa_sink_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_ncontents(c->sinks)); - default_sink = pa_sink_get_default(c); - for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index)) { char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; pa_sample_snprint(ss, sizeof(ss), &sink->sample_spec); @@ -95,7 +94,7 @@ char *pa_sink_list_to_string(struct pa_core *c) { pa_strbuf_printf( s, " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", - sink == default_sink ? '*' : ' ', + !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, pa_sink_get_latency(sink), @@ -113,7 +112,7 @@ char *pa_sink_list_to_string(struct pa_core *c) { char *pa_source_list_to_string(struct pa_core *c) { struct pa_strbuf *s; - struct pa_source *source, *default_source; + struct pa_source *source; uint32_t index = PA_IDXSET_INVALID; assert(c); @@ -122,12 +121,14 @@ char *pa_source_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_ncontents(c->sources)); - default_source = pa_source_get_default(c); - for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; pa_sample_snprint(ss, sizeof(ss), &source->sample_spec); - pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tsample_spec: <%s>\n", source == default_source ? '*' : ' ', source->index, source->name, ss); + pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tsample_spec: <%s>\n", + !strcmp(source->name, c->default_source_name) ? '*' : ' ', + source->index, + source->name, + ss); if (source->monitor_of) pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index); @@ -205,8 +206,6 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { } char *pa_scache_list_to_string(struct pa_core *c) { - struct pa_scache_entry *e; - void *state = NULL; struct pa_strbuf *s; assert(c); @@ -216,6 +215,8 @@ char *pa_scache_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u cache entries available.\n", c->scache_hashmap ? pa_hashmap_ncontents(c->scache_hashmap) : 0); if (c->scache_hashmap) { + struct pa_scache_entry *e; + void *state = NULL; while ((e = pa_hashmap_iterate(c->scache_hashmap, &state))) { double l; @@ -237,3 +238,29 @@ char *pa_scache_list_to_string(struct pa_core *c) { return pa_strbuf_tostring_free(s); } + +char *pa_autoload_list_to_string(struct pa_core *c) { + struct pa_strbuf *s; + assert(c); + + s = pa_strbuf_new(); + assert(s); + + pa_strbuf_printf(s, "%u autoload entries available.\n", c->autoload_hashmap ? pa_hashmap_ncontents(c->autoload_hashmap) : 0); + + if (c->autoload_hashmap) { + struct pa_autoload_entry *e; + void *state = NULL; + + while ((e = pa_hashmap_iterate(c->autoload_hashmap, &state))) { + pa_strbuf_printf( + s, " name: <%s>\n\ttype: <%s>\n\tmodule_name: <%s>\n\targuments: <%s>\n", + e->name, + e->type == PA_NAMEREG_SOURCE ? "source" : "sink", + e->module, + e->argument); + } + } + + return pa_strbuf_tostring_free(s); +} diff --git a/polyp/clitext.h b/polyp/clitext.h index 4e5252fe3..121f2a5d2 100644 --- a/polyp/clitext.h +++ b/polyp/clitext.h @@ -31,6 +31,7 @@ char *pa_source_list_to_string(struct pa_core *c); char *pa_client_list_to_string(struct pa_core *c); char *pa_module_list_to_string(struct pa_core *c); char *pa_scache_list_to_string(struct pa_core *c); +char *pa_autoload_list_to_string(struct pa_core *c); #endif diff --git a/polyp/cmdline.c b/polyp/cmdline.c index a3330145a..8acdde6fb 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -32,6 +32,7 @@ #include "cmdline.h" #include "util.h" #include "strbuf.h" +#include "xmalloc.h" void pa_cmdline_help(const char *argv0) { const char *e; @@ -57,8 +58,7 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { struct pa_strbuf *buf = NULL; assert(argc && argv); - cmdline = malloc(sizeof(struct pa_cmdline)); - assert(cmdline); + cmdline = pa_xmalloc(sizeof(struct pa_cmdline)); cmdline->daemonize = cmdline->help = cmdline->verbose = 0; cmdline->fail = 1; @@ -106,6 +106,6 @@ fail: void pa_cmdline_free(struct pa_cmdline *cmd) { assert(cmd); - free(cmd->cli_commands); - free(cmd); + pa_xfree(cmd->cli_commands); + pa_xfree(cmd); } diff --git a/polyp/core.c b/polyp/core.c index 1c69f9147..ffc11cec9 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -34,11 +34,12 @@ #include "namereg.h" #include "util.h" #include "scache.h" +#include "autoload.h" +#include "xmalloc.h" struct pa_core* pa_core_new(struct pa_mainloop_api *m) { struct pa_core* c; - c = malloc(sizeof(struct pa_core)); - assert(c); + c = pa_xmalloc(sizeof(struct pa_core)); c->mainloop = m; c->clients = pa_idxset_new(NULL, NULL); @@ -47,16 +48,20 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->source_outputs = pa_idxset_new(NULL, NULL); c->sink_inputs = pa_idxset_new(NULL, NULL); - c->default_source_index = c->default_sink_index = PA_IDXSET_INVALID; + c->default_source_name = c->default_sink_name = NULL; c->modules = NULL; c->namereg = NULL; c->scache_idxset = NULL; c->scache_hashmap = NULL; + c->autoload_hashmap = NULL; + c->default_sample_spec.format = PA_SAMPLE_S16NE; c->default_sample_spec.rate = 44100; c->default_sample_spec.channels = 2; + + c->auto_unload_time = 20; pa_check_for_sigpipe(); @@ -68,7 +73,7 @@ void pa_core_free(struct pa_core *c) { pa_module_unload_all(c); assert(!c->modules); - + assert(pa_idxset_isempty(c->clients)); pa_idxset_free(c->clients, NULL, NULL); @@ -86,7 +91,11 @@ void pa_core_free(struct pa_core *c) { pa_namereg_free(c); pa_scache_free(c); + pa_autoload_free(c); + + pa_xfree(c->default_source_name); + pa_xfree(c->default_sink_name); - free(c); + pa_xfree(c); }; diff --git a/polyp/core.h b/polyp/core.h index 03b8671ab..b125083d7 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -32,11 +32,13 @@ struct pa_core { struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache_idxset; - struct pa_hashmap *namereg, *scache_hashmap; - - uint32_t default_source_index, default_sink_index; + struct pa_hashmap *namereg, *scache_hashmap, *autoload_hashmap; + + char *default_source_name, *default_sink_name; struct pa_sample_spec default_sample_spec; + int auto_unload_time; + void *auto_unload_mainloop_source; }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/polyp/dynarray.c b/polyp/dynarray.c index 243069649..23adb5819 100644 --- a/polyp/dynarray.c +++ b/polyp/dynarray.c @@ -28,6 +28,7 @@ #include #include "dynarray.h" +#include "xmalloc.h" struct pa_dynarray { void **data; @@ -36,8 +37,7 @@ struct pa_dynarray { struct pa_dynarray* pa_dynarray_new(void) { struct pa_dynarray *a; - a = malloc(sizeof(struct pa_dynarray)); - assert(a); + a = pa_xmalloc(sizeof(struct pa_dynarray)); a->data = NULL; a->n_entries = 0; a->n_allocated = 0; @@ -53,8 +53,8 @@ void pa_dynarray_free(struct pa_dynarray* a, void (*func)(void *p, void *userdat if (a->data[i]) func(a->data[i], userdata); - free(a->data); - free(a); + pa_xfree(a->data); + pa_xfree(a); } void pa_dynarray_put(struct pa_dynarray*a, unsigned i, void *p) { @@ -67,7 +67,7 @@ void pa_dynarray_put(struct pa_dynarray*a, unsigned i, void *p) { return; n = i+100; - a->data = realloc(a->data, sizeof(void*)*n); + a->data = pa_xrealloc(a->data, sizeof(void*)*n); memset(a->data+a->n_allocated, 0, sizeof(void*)*(n-a->n_allocated)); a->n_allocated = n; } diff --git a/polyp/hashmap.c b/polyp/hashmap.c index 51e3879b5..2b9550fda 100644 --- a/polyp/hashmap.c +++ b/polyp/hashmap.c @@ -29,6 +29,7 @@ #include "hashmap.h" #include "idxset.h" +#include "xmalloc.h" struct hashmap_entry { struct hashmap_entry *next, *previous, *bucket_next, *bucket_previous; @@ -49,11 +50,8 @@ struct pa_hashmap { struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { struct pa_hashmap *h; - h = malloc(sizeof(struct pa_hashmap)); - assert(h); - h->data = malloc(sizeof(struct hashmap_entry*)*(h->size = 1023)); - assert(h->data); - memset(h->data, 0, sizeof(struct hashmap_entry*)*(h->size = 1023)); + h = pa_xmalloc(sizeof(struct pa_hashmap)); + h->data = pa_xmalloc0(sizeof(struct hashmap_entry*)*(h->size = 1023)); h->first_entry = NULL; h->n_entries = 0; h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; @@ -78,7 +76,7 @@ static void remove(struct pa_hashmap *h, struct hashmap_entry *e) { else h->data[e->hash] = e->bucket_next; - free(e); + pa_xfree(e); h->n_entries--; } @@ -91,8 +89,8 @@ void pa_hashmap_free(struct pa_hashmap*h, void (*free_func)(void *p, void *userd remove(h, h->first_entry); } - free(h->data); - free(h); + pa_xfree(h->data); + pa_xfree(h); } static struct hashmap_entry *get(struct pa_hashmap *h, unsigned hash, const void *key) { @@ -115,9 +113,7 @@ int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value) { if ((e = get(h, hash, key))) return -1; - e = malloc(sizeof(struct hashmap_entry)); - assert(e); - + e = pa_xmalloc(sizeof(struct hashmap_entry)); e->hash = hash; e->key = key; e->value = value; diff --git a/polyp/idxset.c b/polyp/idxset.c index 0072e3cd3..83565193c 100644 --- a/polyp/idxset.c +++ b/polyp/idxset.c @@ -29,6 +29,7 @@ #include #include "idxset.h" +#include "xmalloc.h" struct idxset_entry { void *data; @@ -73,14 +74,11 @@ int pa_idxset_trivial_compare_func(const void *a, const void *b) { struct pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { struct pa_idxset *s; - s = malloc(sizeof(struct pa_idxset)); - assert(s); + s = pa_xmalloc(sizeof(struct pa_idxset)); s->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; s->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; s->hash_table_size = 1023; - s->hash_table = malloc(sizeof(struct idxset_entry*)*s->hash_table_size); - assert(s->hash_table); - memset(s->hash_table, 0, sizeof(struct idxset_entry*)*s->hash_table_size); + s->hash_table = pa_xmalloc0(sizeof(struct idxset_entry*)*s->hash_table_size); s->array = NULL; s->array_size = 0; s->index = 0; @@ -101,12 +99,12 @@ void pa_idxset_free(struct pa_idxset *s, void (*free_func) (void *p, void *userd if (free_func) free_func(e->data, userdata); - free(e); + pa_xfree(e); } - free(s->hash_table); - free(s->array); - free(s); + pa_xfree(s->hash_table); + pa_xfree(s->array); + pa_xfree(s); } static struct idxset_entry* hash_scan(struct pa_idxset *s, struct idxset_entry* e, void *p) { @@ -133,14 +131,12 @@ static void extend_array(struct pa_idxset *s, uint32_t index) { break; l = index - s->start_index - i + 100; - n = malloc(sizeof(struct hash_table_entry*)*l); - assert(n); - memset(n, 0, sizeof(struct hash_table_entry*)*l); + n = pa_xmalloc0(sizeof(struct hash_table_entry*)*l); for (j = 0; j < s->array_size-i; j++) n[j] = s->array[i+j]; - free(s->array); + pa_xfree(s->array); s->array = n; s->array_size = l; @@ -173,9 +169,7 @@ int pa_idxset_put(struct pa_idxset*s, void *p, uint32_t *index) { return -1; } - e = malloc(sizeof(struct idxset_entry)); - assert(e); - + e = pa_xmalloc(sizeof(struct idxset_entry)); e->data = p; e->index = s->index++; e->hash_value = h; @@ -274,7 +268,7 @@ static void remove_entry(struct pa_idxset *s, struct idxset_entry *e) { else s->hash_table[e->hash_value] = e->hash_next; - free(e); + pa_xfree(e); assert(s->n_entries >= 1); s->n_entries--; diff --git a/polyp/iochannel.c b/polyp/iochannel.c index 69d381f4e..77f8fb086 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -31,6 +31,7 @@ #include "iochannel.h" #include "util.h" #include "socket-util.h" +#include "xmalloc.h" struct pa_iochannel { int ifd, ofd; @@ -103,7 +104,7 @@ struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd struct pa_iochannel *io; assert(m && (ifd >= 0 || ofd >= 0)); - io = malloc(sizeof(struct pa_iochannel)); + io = pa_xmalloc(sizeof(struct pa_iochannel)); io->ifd = ifd; io->ofd = ofd; io->mainloop = m; @@ -152,7 +153,7 @@ void pa_iochannel_free(struct pa_iochannel*io) { if (io->output_source && (io->output_source != io->input_source)) io->mainloop->cancel_io(io->mainloop, io->output_source); - free(io); + pa_xfree(io); } int pa_iochannel_is_readable(struct pa_iochannel*io) { diff --git a/polyp/ioline.c b/polyp/ioline.c index ff9a03c25..dfa92ab73 100644 --- a/polyp/ioline.c +++ b/polyp/ioline.c @@ -30,6 +30,7 @@ #include #include "ioline.h" +#include "xmalloc.h" #define BUFFER_LIMIT (64*1024) #define READ_SIZE (1024) @@ -55,8 +56,7 @@ struct pa_ioline* pa_ioline_new(struct pa_iochannel *io) { struct pa_ioline *l; assert(io); - l = malloc(sizeof(struct pa_ioline)); - assert(l); + l = pa_xmalloc(sizeof(struct pa_ioline)); l->io = io; l->dead = 0; @@ -77,9 +77,9 @@ struct pa_ioline* pa_ioline_new(struct pa_iochannel *io) { void pa_ioline_free(struct pa_ioline *l) { assert(l); pa_iochannel_free(l->io); - free(l->wbuf); - free(l->rbuf); - free(l); + pa_xfree(l->wbuf); + pa_xfree(l->rbuf); + pa_xfree(l); } void pa_ioline_puts(struct pa_ioline *l, const char *c) { @@ -95,10 +95,10 @@ void pa_ioline_puts(struct pa_ioline *l, const char *c) { if (len > l->wbuf_length - l->wbuf_valid_length) { size_t n = l->wbuf_valid_length+len; - char *new = malloc(n); + char *new = pa_xmalloc(n); if (l->wbuf) { memcpy(new, l->wbuf+l->wbuf_index, l->wbuf_valid_length); - free(l->wbuf); + pa_xfree(l->wbuf); } l->wbuf = new; l->wbuf_length = n; @@ -141,10 +141,10 @@ static int do_read(struct pa_ioline *l) { if (l->rbuf_valid_length) memmove(l->rbuf, l->rbuf+l->rbuf_index, l->rbuf_valid_length); } else { - char *new = malloc(n); + char *new = pa_xmalloc(n); if (l->rbuf_valid_length) memcpy(new, l->rbuf+l->rbuf_index, l->rbuf_valid_length); - free(l->rbuf); + pa_xfree(l->rbuf); l->rbuf = new; l->rbuf_length = n; } diff --git a/polyp/main.c b/polyp/main.c index 0c6104a44..de66f1c88 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -42,6 +42,7 @@ #include "cli-command.h" #include "util.h" #include "sioman.h" +#include "xmalloc.h" static struct pa_mainloop *mainloop; @@ -147,7 +148,7 @@ int main(int argc, char *argv[]) { assert(buf); r = pa_cli_command_execute(c, cmdline->cli_commands, buf, &cmdline->fail, &cmdline->verbose); fprintf(stderr, s = pa_strbuf_tostring_free(buf)); - free(s); + pa_xfree(s); if (r < 0 && cmdline->fail) { fprintf(stderr, __FILE__": failed to initialize daemon.\n"); diff --git a/polyp/mainloop-api.c b/polyp/mainloop-api.c index cce49c067..8b4e09ac5 100644 --- a/polyp/mainloop-api.c +++ b/polyp/mainloop-api.c @@ -25,7 +25,9 @@ #include #include + #include "mainloop-api.h" +#include "xmalloc.h" struct once_info { void (*callback)(void *userdata); @@ -38,7 +40,7 @@ static void once_callback(struct pa_mainloop_api *api, void *id, void *userdata) i->callback(i->userdata); assert(api->cancel_fixed); api->cancel_fixed(api, id); - free(i); + pa_xfree(i); } void pa_mainloop_api_once(struct pa_mainloop_api* api, void (*callback)(void *userdata), void *userdata) { @@ -46,8 +48,7 @@ void pa_mainloop_api_once(struct pa_mainloop_api* api, void (*callback)(void *us void *id; assert(api && callback); - i = malloc(sizeof(struct once_info)); - assert(i); + i = pa_xmalloc(sizeof(struct once_info)); i->callback = callback; i->userdata = userdata; diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c index 642ca5e05..6e79767a9 100644 --- a/polyp/mainloop-signal.c +++ b/polyp/mainloop-signal.c @@ -33,6 +33,7 @@ #include "mainloop-signal.h" #include "util.h" +#include "xmalloc.h" struct signal_info { int sig; @@ -122,8 +123,7 @@ void* pa_signal_register(int sig, void (*callback) (void *id, int signal, void * if (s->sig == sig) goto fail; - s = malloc(sizeof(struct signal_info)); - assert(s); + s = pa_xmalloc(sizeof(struct signal_info)); s->sig = sig; s->callback = callback; s->userdata = userdata; @@ -143,7 +143,7 @@ void* pa_signal_register(int sig, void (*callback) (void *id, int signal, void * return s; fail: if (s) - free(s); + pa_xfree(s); return NULL; } @@ -159,5 +159,5 @@ void pa_signal_unregister(void *id) { signals = s->next; sigaction(s->sig, &s->saved_sigaction, NULL); - free(s); + pa_xfree(s); } diff --git a/polyp/mainloop.c b/polyp/mainloop.c index b9eee86d4..f3d8e781b 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -36,6 +36,7 @@ #include "mainloop.h" #include "util.h" #include "idxset.h" +#include "xmalloc.h" struct mainloop_source_header { struct pa_mainloop *mainloop; @@ -87,8 +88,7 @@ static void setup_api(struct pa_mainloop *m); struct pa_mainloop *pa_mainloop_new(void) { struct pa_mainloop *m; - m = malloc(sizeof(struct pa_mainloop)); - assert(m); + m = pa_xmalloc(sizeof(struct pa_mainloop)); m->io_sources = pa_idxset_new(NULL, NULL); m->fixed_sources = pa_idxset_new(NULL, NULL); @@ -115,7 +115,7 @@ static int foreach(void *p, uint32_t index, int *del, void*userdata) { assert(p && del && all); if (*all || h->dead) { - free(h); + pa_xfree(h); *del = 1; } @@ -135,8 +135,8 @@ void pa_mainloop_free(struct pa_mainloop* m) { pa_idxset_free(m->idle_sources, NULL, NULL); pa_idxset_free(m->time_sources, NULL, NULL); - free(m->pollfds); - free(m); + pa_xfree(m->pollfds); + pa_xfree(m); } static void scan_dead(struct pa_mainloop *m) { @@ -160,7 +160,7 @@ static void rebuild_pollfds(struct pa_mainloop *m) { l = pa_idxset_ncontents(m->io_sources); if (m->max_pollfds < l) { - m->pollfds = realloc(m->pollfds, sizeof(struct pollfd)*l); + m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l); m->max_pollfds = l; } @@ -349,8 +349,7 @@ static void* mainloop_source_io(struct pa_mainloop_api*a, int fd, enum pa_mainlo m = a->userdata; assert(a == &m->api); - s = malloc(sizeof(struct mainloop_source_io)); - assert(s); + s = pa_xmalloc(sizeof(struct mainloop_source_io)); s->header.mainloop = m; s->header.dead = 0; @@ -397,8 +396,7 @@ static void* mainloop_source_fixed(struct pa_mainloop_api*a, void (*callback) (s m = a->userdata; assert(a == &m->api); - s = malloc(sizeof(struct mainloop_source_fixed_or_idle)); - assert(s); + s = pa_xmalloc(sizeof(struct mainloop_source_fixed_or_idle)); s->header.mainloop = m; s->header.dead = 0; @@ -439,8 +437,7 @@ static void* mainloop_source_idle(struct pa_mainloop_api*a, void (*callback) (st m = a->userdata; assert(a == &m->api); - s = malloc(sizeof(struct mainloop_source_fixed_or_idle)); - assert(s); + s = pa_xmalloc(sizeof(struct mainloop_source_fixed_or_idle)); s->header.mainloop = m; s->header.dead = 0; @@ -471,8 +468,7 @@ static void* mainloop_source_time(struct pa_mainloop_api*a, const struct timeval m = a->userdata; assert(a == &m->api); - s = malloc(sizeof(struct mainloop_source_time)); - assert(s); + s = pa_xmalloc(sizeof(struct mainloop_source_time)); s->header.mainloop = m; s->header.dead = 0; diff --git a/polyp/memblock.c b/polyp/memblock.c index 8f24ff221..0571f5dae 100644 --- a/polyp/memblock.c +++ b/polyp/memblock.c @@ -29,11 +29,12 @@ #include #include "memblock.h" +#include "xmalloc.h" static unsigned memblock_count = 0, memblock_total = 0; struct pa_memblock *pa_memblock_new(size_t length) { - struct pa_memblock *b = malloc(sizeof(struct pa_memblock)+length); + struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)+length); b->type = PA_MEMBLOCK_APPENDED; b->ref = 1; b->length = length; @@ -44,7 +45,7 @@ struct pa_memblock *pa_memblock_new(size_t length) { } struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length) { - struct pa_memblock *b = malloc(sizeof(struct pa_memblock)); + struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)); b->type = PA_MEMBLOCK_FIXED; b->ref = 1; b->length = length; @@ -55,7 +56,7 @@ struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length) { } struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length) { - struct pa_memblock *b = malloc(sizeof(struct pa_memblock)); + struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)); b->type = PA_MEMBLOCK_DYNAMIC; b->ref = 1; b->length = length; @@ -77,12 +78,12 @@ void pa_memblock_unref(struct pa_memblock*b) { if (b->ref == 0) { if (b->type == PA_MEMBLOCK_DYNAMIC) - free(b->data); + pa_xfree(b->data); memblock_count--; memblock_total -= b->length; - free(b); + pa_xfree(b); } } @@ -95,8 +96,7 @@ void pa_memblock_unref_fixed(struct pa_memblock *b) { pa_memblock_unref(b); return; } else { - d = malloc(b->length); - assert(d); + d = pa_xmalloc(b->length); memcpy(d, b->data, b->length); b->data = d; b->type = PA_MEMBLOCK_DYNAMIC; diff --git a/polyp/memblockq.c b/polyp/memblockq.c index eff923b90..4019c893b 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -30,6 +30,7 @@ #include #include "memblockq.h" +#include "xmalloc.h" struct memblock_list { struct memblock_list *next; @@ -50,8 +51,7 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b struct pa_memblockq* bq; assert(maxlength && base && maxlength); - bq = malloc(sizeof(struct pa_memblockq)); - assert(bq); + bq = pa_xmalloc(sizeof(struct pa_memblockq)); bq->blocks = bq->blocks_tail = 0; bq->n_blocks = 0; @@ -97,10 +97,10 @@ void pa_memblockq_free(struct pa_memblockq* bq) { while ((l = bq->blocks)) { bq->blocks = l->next; pa_memblock_unref(l->chunk.memblock); - free(l); + pa_xfree(l); } - free(bq); + pa_xfree(bq); } void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta) { @@ -119,8 +119,7 @@ void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, } } - q = malloc(sizeof(struct memblock_list)); - assert(q); + q = pa_xmalloc(sizeof(struct memblock_list)); if (bq->measure_delay) gettimeofday(&q->stamp, NULL); @@ -181,7 +180,7 @@ int memblockq_pop(struct memblockq* bq, struct pa_memchunk *chunk) { bq->n_blocks--; bq->current_length -= chunk->length; - free(q); + pa_xfree(q); return 0; } */ @@ -231,7 +230,7 @@ void pa_memblockq_drop(struct pa_memblockq *bq, size_t length) { if (bq->blocks == NULL) bq->blocks_tail = NULL; pa_memblock_unref(q->chunk.memblock); - free(q); + pa_xfree(q); bq->n_blocks--; } diff --git a/polyp/memchunk.c b/polyp/memchunk.c index d27ca61aa..77e1b7dda 100644 --- a/polyp/memchunk.c +++ b/polyp/memchunk.c @@ -29,6 +29,7 @@ #include #include "memchunk.h" +#include "xmalloc.h" void pa_memchunk_make_writable(struct pa_memchunk *c) { struct pa_memblock *n; @@ -57,8 +58,7 @@ struct pa_mcalign *pa_mcalign_new(size_t base) { struct pa_mcalign *m; assert(base); - m = malloc(sizeof(struct pa_mcalign)); - assert(m); + m = pa_xmalloc(sizeof(struct pa_mcalign)); m->base = base; m->chunk.memblock = NULL; m->chunk.length = m->chunk.index = 0; @@ -70,12 +70,12 @@ struct pa_mcalign *pa_mcalign_new(size_t base) { void pa_mcalign_free(struct pa_mcalign *m) { assert(m); - free(m->buffer); + pa_xfree(m->buffer); if (m->chunk.memblock) pa_memblock_unref(m->chunk.memblock); - free(m); + pa_xfree(m); } void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) { @@ -128,8 +128,7 @@ int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) { if (m->buffer_fill) { assert(!m->buffer); - m->buffer = malloc(m->base); - assert(m->buffer); + m->buffer = pa_xmalloc(m->base); m->chunk.length -= m->buffer_fill; memcpy(m->buffer, m->chunk.memblock->data + m->chunk.index + m->chunk.length, m->buffer_fill); } diff --git a/polyp/modargs.c b/polyp/modargs.c index 3841a9ec2..87d99ad28 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -35,8 +35,7 @@ #include "namereg.h" #include "sink.h" #include "source.h" - -#include "debug.h" +#include "xmalloc.h" struct pa_modargs; @@ -55,14 +54,13 @@ static int add_key_value(struct pa_hashmap *map, char *key, char *value, const c break; if (!*v) { - free(key); - free(value); + pa_xfree(key); + pa_xfree(value); return -1; } } - e = malloc(sizeof(struct entry)); - assert(e); + e = pa_xmalloc(sizeof(struct entry)); e->key = key; e->value = value; pa_hashmap_put(map, key, e); @@ -109,7 +107,7 @@ struct pa_modargs *pa_modargs_new(const char *args, const char* const* valid_key value = p+1; value_len = 0; } else if (isspace(*p)) { - if (add_key_value(map, strndup(key, key_len), strdup(""), valid_keys) < 0) + if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(""), valid_keys) < 0) goto fail; state = WHITESPACE; } else { @@ -120,7 +118,7 @@ struct pa_modargs *pa_modargs_new(const char *args, const char* const* valid_key break; case VALUE_SIMPLE: if (isspace(*p)) { - if (add_key_value(map, strndup(key, key_len), strndup(value, value_len), valid_keys) < 0) + if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0) goto fail; state = WHITESPACE; } else @@ -128,7 +126,7 @@ struct pa_modargs *pa_modargs_new(const char *args, const char* const* valid_key break; case VALUE_DOUBLE_QUOTES: if (*p == '"') { - if (add_key_value(map, strndup(key, key_len), strndup(value, value_len), valid_keys) < 0) + if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0) goto fail; state = WHITESPACE; } else @@ -136,7 +134,7 @@ struct pa_modargs *pa_modargs_new(const char *args, const char* const* valid_key break; case VALUE_TICKS: if (*p == '\'') { - if (add_key_value(map, strndup(key, key_len), strndup(value, value_len), valid_keys) < 0) + if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0) goto fail; state = WHITESPACE; } else @@ -146,10 +144,10 @@ struct pa_modargs *pa_modargs_new(const char *args, const char* const* valid_key } if (state == VALUE_START) { - if (add_key_value(map, strndup(key, key_len), strdup(""), valid_keys) < 0) + if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(""), valid_keys) < 0) goto fail; } else if (state == VALUE_SIMPLE) { - if (add_key_value(map, strndup(key, key_len), strdup(value), valid_keys) < 0) + if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(value), valid_keys) < 0) goto fail; } else if (state != WHITESPACE) goto fail; @@ -169,9 +167,9 @@ fail: static void free_func(void *p, void*userdata) { struct entry *e = p; assert(e); - free(e->key); - free(e->value); - free(e); + pa_xfree(e->key); + pa_xfree(e->value); + pa_xfree(e); } void pa_modargs_free(struct pa_modargs*ma) { @@ -256,37 +254,3 @@ int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss return 0; } - -int pa_modargs_get_source_index(struct pa_modargs *ma, struct pa_core *c, uint32_t *index) { - const char *t; - assert(ma && index); - - if (!(t = pa_modargs_get_value(ma, "source", NULL))) - *index = PA_IDXSET_INVALID; - else { - struct pa_source *source; - if (!(source = pa_namereg_get(c, t, PA_NAMEREG_SOURCE))) - return -1; - - *index = source->index; - } - - return 0; -} - -int pa_modargs_get_sink_index(struct pa_modargs *ma, struct pa_core *c, uint32_t *index) { - const char *t; - assert(ma && index); - - if (!(t = pa_modargs_get_value(ma, "sink", NULL))) - *index = PA_IDXSET_INVALID; - else { - struct pa_sink *sink; - if (!(sink = pa_namereg_get(c, t, PA_NAMEREG_SINK))) - return -1; - - *index = sink->index; - } - - return 0; -} diff --git a/polyp/modargs.h b/polyp/modargs.h index 301dc2971..872fb14f1 100644 --- a/polyp/modargs.h +++ b/polyp/modargs.h @@ -36,7 +36,4 @@ int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *v int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *ss); -int pa_modargs_get_source_index(struct pa_modargs *ma, struct pa_core *c, uint32_t *index); -int pa_modargs_get_sink_index(struct pa_modargs *ma, struct pa_core *c, uint32_t *index); - #endif diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index c19582272..a0fa52db1 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -37,6 +37,7 @@ #include "util.h" #include "sample-util.h" #include "alsa-util.h" +#include "xmalloc.h" struct userdata { snd_pcm_t *pcm_handle; @@ -46,6 +47,7 @@ struct userdata { size_t frame_size, fragment_size; struct pa_memchunk memchunk, silence; + struct pa_module *module; }; static const char* const valid_modargs[] = { @@ -62,6 +64,12 @@ static const char* const valid_modargs[] = { #define DEFAULT_SINK_NAME "alsa_output" #define DEFAULT_DEVICE "plughw:0,0" +static void update_usage(struct userdata *u) { + pa_module_set_used(u->module, + (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0)); +} + static void xrun_recovery(struct userdata *u) { assert(u); @@ -74,6 +82,8 @@ static void xrun_recovery(struct userdata *u) { static void do_write(struct userdata *u) { assert(u); + update_usage(u); + for (;;) { struct pa_memchunk *memchunk = NULL; snd_pcm_sframes_t frames; @@ -175,10 +185,9 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { } buffer_size = fragsize/frame_size*periods; - u = malloc(sizeof(struct userdata)); - assert(u); - memset(u, 0, sizeof(struct userdata)); + u = pa_xmalloc0(sizeof(struct userdata)); m->userdata = u; + u->module = m; if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) { fprintf(stderr, __FILE__": Error opening PCM device %s\n", dev); @@ -236,24 +245,25 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); - if ((u = m->userdata)) { - if (u->sink) - pa_sink_free(u->sink); - - if (u->io_sources) - pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources); - - if (u->pcm_handle) { - snd_pcm_drop(u->pcm_handle); - snd_pcm_close(u->pcm_handle); - } - - if (u->memchunk.memblock) - pa_memblock_unref(u->memchunk.memblock); - if (u->silence.memblock) - pa_memblock_unref(u->silence.memblock); - - free(u); + if (!(u = m->userdata)) + return; + + if (u->sink) + pa_sink_free(u->sink); + + if (u->io_sources) + pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources); + + if (u->pcm_handle) { + snd_pcm_drop(u->pcm_handle); + snd_pcm_close(u->pcm_handle); } + + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + if (u->silence.memblock) + pa_memblock_unref(u->silence.memblock); + + pa_xfree(u); } diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index a453944e9..8207d462a 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -37,6 +37,7 @@ #include "util.h" #include "sample-util.h" #include "alsa-util.h" +#include "xmalloc.h" struct userdata { snd_pcm_t *pcm_handle; @@ -46,6 +47,7 @@ struct userdata { size_t frame_size, fragment_size; struct pa_memchunk memchunk; + struct pa_module *module; }; static const char* const valid_modargs[] = { @@ -62,6 +64,11 @@ static const char* const valid_modargs[] = { #define DEFAULT_SOURCE_NAME "alsa_input" #define DEFAULT_DEVICE "hw:0,0" +static void update_usage(struct userdata *u) { + pa_module_set_used(u->module, + (u->source ? pa_idxset_ncontents(u->source->outputs) : 0)); +} + static void xrun_recovery(struct userdata *u) { assert(u); @@ -74,6 +81,8 @@ static void xrun_recovery(struct userdata *u) { static void do_read(struct userdata *u) { assert(u); + update_usage(u); + for (;;) { struct pa_memchunk post_memchunk; snd_pcm_sframes_t frames; @@ -159,10 +168,9 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { } buffer_size = fragsize/frame_size*periods; - u = malloc(sizeof(struct userdata)); - assert(u); - memset(u, 0, sizeof(struct userdata)); + u = pa_xmalloc0(sizeof(struct userdata)); m->userdata = u; + u->module = m; if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) < 0) { fprintf(stderr, __FILE__": Error opening PCM device %s\n", dev); @@ -216,22 +224,23 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); - if ((u = m->userdata)) { - if (u->source) - pa_source_free(u->source); - - if (u->io_sources) - pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources); - - if (u->pcm_handle) { - snd_pcm_drop(u->pcm_handle); - snd_pcm_close(u->pcm_handle); - } - - if (u->memchunk.memblock) - pa_memblock_unref(u->memchunk.memblock); - - free(u); + if (!(u = m->userdata)) + return; + + if (u->source) + pa_source_free(u->source); + + if (u->io_sources) + pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources); + + if (u->pcm_handle) { + snd_pcm_drop(u->pcm_handle); + snd_pcm_close(u->pcm_handle); } + + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + + pa_xfree(u); } diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 30ff3ce6b..37710fc56 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -44,6 +44,7 @@ #include "sample-util.h" #include "util.h" #include "modargs.h" +#include "xmalloc.h" struct userdata { struct pa_sink *sink; @@ -62,6 +63,7 @@ struct userdata { struct pa_memblock **in_memblocks, **out_memblocks; unsigned out_current, in_current; + struct pa_module *module; }; static const char* const valid_modargs[] = { @@ -82,6 +84,13 @@ static const char* const valid_modargs[] = { #define DEFAULT_SOURCE_NAME "oss_input" #define DEFAULT_DEVICE "/dev/dsp" +static void update_usage(struct userdata *u) { + pa_module_set_used(u->module, + (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) + + (u->source ? pa_idxset_ncontents(u->source->outputs) : 0)); +} + static void out_fill_memblocks(struct userdata *u, unsigned n) { assert(u && u->out_memblocks); @@ -110,6 +119,8 @@ static void do_write(struct userdata *u) { struct count_info info; assert(u && u->sink); + update_usage(u); + if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { fprintf(stderr, "SNDCTL_DSP_GETOPTR: %s\n", strerror(errno)); return; @@ -170,6 +181,8 @@ static void do_read(struct userdata *u) { struct count_info info; assert(u && u->source); + update_usage(u); + if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { fprintf(stderr, "SNDCTL_DSP_GETIPTR: %s\n", strerror(errno)); return; @@ -212,9 +225,8 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; assert(c && m); - m->userdata = u = malloc(sizeof(struct userdata)); - assert(u); - memset(u, 0, sizeof(struct userdata)); + m->userdata = u = pa_xmalloc0(sizeof(struct userdata)); + u->module = m; u->fd = -1; u->core = c; @@ -288,9 +300,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'", p); - - u->in_memblocks = malloc(sizeof(struct pa_memblock *)*u->in_fragments); - memset(u->in_memblocks, 0, sizeof(struct pa_memblock *)*u->in_fragments); + u->in_memblocks = pa_xmalloc0(sizeof(struct pa_memblock *)*u->in_fragments); enable_bits |= PCM_ENABLE_INPUT; } @@ -323,8 +333,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'", p); - u->out_memblocks = malloc(sizeof(struct memblock *)*u->out_fragments); - memset(u->out_memblocks, 0, sizeof(struct pa_memblock *)*u->out_fragments); + u->out_memblocks = pa_xmalloc0(sizeof(struct memblock *)*u->out_fragments); enable_bits |= PCM_ENABLE_OUTPUT; } @@ -363,15 +372,15 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); - u = m->userdata; - assert(u); + if (!(u = m->userdata)) + return; if (u->out_memblocks) { unsigned i; for (i = 0; i < u->out_fragments; i++) if (u->out_memblocks[i]) pa_memblock_unref_fixed(u->out_memblocks[i]); - free(u->out_memblocks); + pa_xfree(u->out_memblocks); } if (u->in_memblocks) { @@ -379,7 +388,7 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { for (i = 0; i < u->in_fragments; i++) if (u->in_memblocks[i]) pa_memblock_unref_fixed(u->in_memblocks[i]); - free(u->in_memblocks); + pa_xfree(u->in_memblocks); } if (u->in_mmap && u->in_mmap != MAP_FAILED) @@ -400,5 +409,5 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { if (u->fd >= 0) close(u->fd); - free(u); + pa_xfree(u); } diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 51585ca9d..a8db4a337 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -43,6 +43,7 @@ #include "sample-util.h" #include "util.h" #include "modargs.h" +#include "xmalloc.h" struct userdata { struct pa_sink *sink; @@ -55,6 +56,7 @@ struct userdata { uint32_t in_fragment_size, out_fragment_size, sample_size; int fd; + struct pa_module *module; }; static const char* const valid_modargs[] = { @@ -75,6 +77,13 @@ static const char* const valid_modargs[] = { #define DEFAULT_SOURCE_NAME "oss_input" #define DEFAULT_DEVICE "/dev/dsp" +static void update_usage(struct userdata *u) { + pa_module_set_used(u->module, + (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) + + (u->source ? pa_idxset_ncontents(u->source->outputs) : 0)); +} + static void do_write(struct userdata *u) { struct pa_memchunk *memchunk; ssize_t r; @@ -83,6 +92,8 @@ static void do_write(struct userdata *u) { if (!u->sink || !pa_iochannel_is_writable(u->io)) return; + update_usage(u); + if (!u->memchunk.length) { if (pa_sink_render(u->sink, u->out_fragment_size, &u->memchunk) < 0) memchunk = &u->silence; @@ -118,6 +129,8 @@ static void do_read(struct userdata *u) { if (!u->source || !pa_iochannel_is_readable(u->io)) return; + update_usage(u); + memchunk.memblock = pa_memblock_new(u->in_fragment_size); assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { @@ -225,9 +238,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { out_frag_size = info.fragsize; } - u = malloc(sizeof(struct userdata)); - assert(u); - + u = pa_xmalloc(sizeof(struct userdata)); u->core = c; if (mode != O_WRONLY) { @@ -266,7 +277,8 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(u->silence.memblock); pa_silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; - + + u->module = m; m->userdata = u; pa_modargs_free(ma); @@ -287,8 +299,8 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); - u = m->userdata; - assert(u); + if (!(u = m->userdata)) + return; if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); @@ -299,6 +311,7 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { pa_sink_free(u->sink); if (u->source) pa_source_free(u->source); + pa_iochannel_free(u->io); - free(u); + pa_xfree(u); } diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index df34f73a2..dc2bc633d 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -38,6 +38,7 @@ #include "module.h" #include "util.h" #include "modargs.h" +#include "xmalloc.h" #define DEFAULT_FIFO_NAME "/tmp/musicfifo" #define DEFAULT_SINK_NAME "fifo_output" @@ -52,6 +53,7 @@ struct userdata { void *mainloop_source; struct pa_memchunk memchunk; + struct pa_module *module; }; static const char* const valid_modargs[] = { @@ -72,6 +74,8 @@ static void do_write(struct userdata *u) { if (!pa_iochannel_is_writable(u->io)) return; + pa_module_set_used(u->module, pa_idxset_ncontents(u->sink->inputs) + pa_idxset_ncontents(u->sink->monitor_source->outputs)); + if (!u->memchunk.length) if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) return; @@ -149,12 +153,9 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto fail; } - u = malloc(sizeof(struct userdata)); - assert(u); - memset(u, 0, sizeof(struct userdata)); + u = pa_xmalloc0(sizeof(struct userdata)); - u->filename = strdup(p); - assert(u->filename); + u->filename = pa_xstrdup(p); u->core = c; if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { @@ -177,7 +178,8 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->mainloop_source = c->mainloop->source_fixed(c->mainloop, fixed_callback, u); assert(u->mainloop_source); c->mainloop->enable_fixed(c->mainloop, u->mainloop_source, 0); - + + u->module = m; m->userdata = u; pa_modargs_free(ma); @@ -212,7 +214,7 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { assert(u->filename); unlink(u->filename); - free(u->filename); + pa_xfree(u->filename); - free(u); + pa_xfree(u); } diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index 4da3c880e..2cf760998 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -10,6 +10,8 @@ #include "sink.h" #include "scache.h" #include "modargs.h" +#include "xmalloc.h" +#include "namereg.h" struct x11_source { void *io_source; @@ -22,7 +24,7 @@ struct userdata { struct x11_source *x11_sources; int xkb_event_base; - int sink_index; + char *sink_name; char *scache_item; }; @@ -33,22 +35,11 @@ static const char* const valid_modargs[] = { NULL }; -static struct pa_sink* get_output_sink(struct userdata *u) { - struct pa_sink *s; - assert(u); - - if (!(s = pa_idxset_get_by_index(u->core->sinks, u->sink_index))) - s = pa_sink_get_default(u->core); - - u->sink_index = s ? s->index : PA_IDXSET_INVALID; - return s; -} - static int ring_bell(struct userdata *u, int percent) { struct pa_sink *s; assert(u); - if (!(s = get_output_sink(u))) { + if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { fprintf(stderr, __FILE__": Invalid sink\n"); return -1; } @@ -85,8 +76,7 @@ static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_main static void new_io_source(struct userdata *u, int fd) { struct x11_source *s; - s = malloc(sizeof(struct x11_source)); - assert(s); + s = pa_xmalloc(sizeof(struct x11_source)); s->io_source = u->core->mainloop->source_io(u->core->mainloop, fd, PA_MAINLOOP_API_IO_EVENT_INPUT, io_callback, u); assert(s->io_source); s->next = u->x11_sources; @@ -105,18 +95,12 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto fail; } - m->userdata = u = malloc(sizeof(struct userdata)); - assert(u); + m->userdata = u = pa_xmalloc(sizeof(struct userdata)); u->core = c; u->display = NULL; u->x11_sources = NULL; - u->scache_item = strdup(pa_modargs_get_value(ma, "sample", "x11-bell")); - assert(u->scache_item); - - if (pa_modargs_get_sink_index(ma, c, &u->sink_index) < 0) { - fprintf(stderr, __FILE__": Invalid sink specified\n"); - goto fail; - } + u->scache_item = pa_xstrdup(pa_modargs_get_value(ma, "sample", "x11-bell")); + u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); if (!(u->display = XOpenDisplay(pa_modargs_get_value(ma, "display", NULL)))) { fprintf(stderr, __FILE__": XOpenDisplay() failed\n"); @@ -166,12 +150,12 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { struct x11_source *s = u->x11_sources; u->x11_sources = u->x11_sources->next; c->mainloop->cancel_io(c->mainloop, s->io_source); - free(s); + pa_xfree(s); } - free(u->scache_item); + pa_xfree(u->scache_item); if (u->display) XCloseDisplay(u->display); - free(u); + pa_xfree(u); } diff --git a/polyp/module.c b/polyp/module.c index 5c6f0fb61..8c5e318f1 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -31,6 +31,21 @@ #include #include "module.h" +#include "xmalloc.h" + +#define UNLOAD_POLL_TIME 10 + +static void timeout_callback(struct pa_mainloop_api *m, void *id, const struct timeval *tv, void *userdata) { + struct pa_core *c = userdata; + struct timeval ntv; + assert(c && c->mainloop == m && c->auto_unload_mainloop_source == id); + + pa_module_unload_unused(c); + + gettimeofday(&ntv, NULL); + ntv.tv_sec += UNLOAD_POLL_TIME; + m->enable_time(m, id, &ntv); +} struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char *argument) { struct pa_module *m = NULL; @@ -38,11 +53,10 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char assert(c && name); - m = malloc(sizeof(struct pa_module)); - assert(m); + m = pa_xmalloc(sizeof(struct pa_module)); - m->name = strdup(name); - m->argument = argument ? strdup(argument) : NULL; + m->name = pa_xstrdup(name); + m->argument = pa_xstrdup(argument); if (!(m->dl = lt_dlopenext(name))) goto fail; @@ -55,6 +69,8 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char m->userdata = NULL; m->core = c; + m->n_used = -1; + m->auto_unload = 0; assert(m->init); if (m->init(c, m) < 0) @@ -62,6 +78,14 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char if (!c->modules) c->modules = pa_idxset_new(NULL, NULL); + + if (!c->auto_unload_mainloop_source) { + struct timeval ntv; + gettimeofday(&ntv, NULL); + ntv.tv_sec += UNLOAD_POLL_TIME; + c->auto_unload_mainloop_source = c->mainloop->source_time(c->mainloop, &ntv, timeout_callback, c); + } + assert(c->auto_unload_mainloop_source); assert(c->modules); r = pa_idxset_put(c->modules, m, &m->index); @@ -73,13 +97,13 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char fail: if (m) { - free(m->argument); - free(m->name); + pa_xfree(m->argument); + pa_xfree(m->name); if (m->dl) lt_dlclose(m->dl); - free(m); + pa_xfree(m); } return NULL; @@ -93,9 +117,9 @@ static void pa_module_free(struct pa_module *m) { fprintf(stderr, "module: unloaded %u \"%s\".\n", m->index, m->name); - free(m->name); - free(m->argument); - free(m); + pa_xfree(m->name); + pa_xfree(m->argument); + pa_xfree(m); } @@ -134,6 +158,34 @@ void pa_module_unload_all(struct pa_core *c) { pa_idxset_free(c->modules, free_callback, NULL); c->modules = NULL; + + if (c->auto_unload_mainloop_source) + c->mainloop->cancel_time(c->mainloop, c->auto_unload_mainloop_source); + c->auto_unload_mainloop_source = NULL; +} + +static int unused_callback(void *p, uint32_t index, int *del, void *userdata) { + struct pa_module *m = p; + time_t *now = userdata; + assert(p && del && now); + + if (m->n_used == 0 && m->auto_unload && m->last_used_time+m->core->auto_unload_time <= *now) { + pa_module_free(m); + *del = 1; + } + + return 0; +} + +void pa_module_unload_unused(struct pa_core *c) { + time_t now; + assert(c); + + if (!c->modules) + return; + + time(&now); + pa_idxset_foreach(c->modules, unused_callback, &now); } struct once_info { @@ -141,21 +193,29 @@ struct once_info { uint32_t index; }; - static void module_unload_once_callback(void *userdata) { struct once_info *i = userdata; assert(i); pa_module_unload_by_index(i->core, i->index); - free(i); + pa_xfree(i); } void pa_module_unload_request(struct pa_core *c, struct pa_module *m) { struct once_info *i; assert(c && m); - i = malloc(sizeof(struct once_info)); - assert(i); + i = pa_xmalloc(sizeof(struct once_info)); i->core = c; i->index = m->index; pa_mainloop_api_once(c->mainloop, module_unload_once_callback, i); } + +void pa_module_set_used(struct pa_module*m, int used) { + assert(m); + + if (m->n_used != used && used == 0) + time(&m->last_used_time); + + m->n_used = used; +} + diff --git a/polyp/module.h b/polyp/module.h index af2d85523..de195a4b2 100644 --- a/polyp/module.h +++ b/polyp/module.h @@ -38,6 +38,10 @@ struct pa_module { void (*done)(struct pa_core *c, struct pa_module*m); void *userdata; + + int n_used; + int auto_unload; + time_t last_used_time; }; struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char*argument); @@ -45,6 +49,7 @@ void pa_module_unload(struct pa_core *c, struct pa_module *m); void pa_module_unload_by_index(struct pa_core *c, uint32_t index); void pa_module_unload_all(struct pa_core *c); +void pa_module_unload_unused(struct pa_core *c); void pa_module_unload_request(struct pa_core *c, struct pa_module *m); @@ -52,4 +57,7 @@ void pa_module_unload_request(struct pa_core *c, struct pa_module *m); int pa_module_init(struct pa_core *c, struct pa_module*m); void pa_module_done(struct pa_core *c, struct pa_module*m); +void pa_module_set_used(struct pa_module*m, int used); + + #endif diff --git a/polyp/namereg.c b/polyp/namereg.c index 2349436f3..b6a8c23f7 100644 --- a/polyp/namereg.c +++ b/polyp/namereg.c @@ -31,6 +31,10 @@ #include #include "namereg.h" +#include "autoload.h" +#include "source.h" +#include "sink.h" +#include "xmalloc.h" struct namereg_entry { enum pa_namereg_type type; @@ -62,12 +66,11 @@ const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_nam return NULL; if (!e) - n = strdup(name); + n = pa_xstrdup(name); else { unsigned i; size_t l = strlen(name); - n = malloc(l+3); - assert(n); + n = pa_xmalloc(l+3); for (i = 1; i <= 99; i++) { snprintf(n, l+2, "%s%u", name, i); @@ -77,14 +80,13 @@ const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_nam } if (e) { - free(n); + pa_xfree(n); return NULL; } } assert(n); - e = malloc(sizeof(struct namereg_entry)); - assert(e); + e = pa_xmalloc(sizeof(struct namereg_entry)); e->type = type; e->name = n; e->data = data; @@ -107,25 +109,66 @@ void pa_namereg_unregister(struct pa_core *c, const char *name) { r = pa_hashmap_remove(c->namereg, name); assert(r >= 0); - free(e->name); - free(e); + pa_xfree(e->name); + pa_xfree(e); } -void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type) { +void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type, int autoload) { struct namereg_entry *e; uint32_t index; char *x = NULL; void *d = NULL; - assert(c && name); + assert(c); + + if (!name) { + if (type == PA_NAMEREG_SOURCE) { + if (!c->default_source_name) { + struct pa_source *s; - if ((e = pa_hashmap_get(c->namereg, name))) + for (s = pa_idxset_first(c->sources, &index); s; s = pa_idxset_next(c->sources, &index)) + if (!s->monitor_of) { + pa_namereg_set_default(c, s->name, PA_NAMEREG_SOURCE); + break; + } + } + + name = c->default_source_name; + + } else { + assert(type == PA_NAMEREG_SINK); + + if (!c->default_sink_name) { + struct pa_sink *s; + + if ((s = pa_idxset_first(c->sinks, NULL))) + pa_namereg_set_default(c, s->name, PA_NAMEREG_SINK); + } + + name = c->default_sink_name; + } + } + + if (!name) + return NULL; + + if (c->namereg && (e = pa_hashmap_get(c->namereg, name))) if (e->type == e->type) return e->data; index = (uint32_t) strtol(name, &x, 0); - if (!x || *x != 0) + if (!x || *x != 0) { + + if (autoload) { + pa_autoload_request(c, name, type); + + if (c->namereg && (e = pa_hashmap_get(c->namereg, name))) + if (e->type == e->type) + return e->data; + } + return NULL; + } if (type == PA_NAMEREG_SINK) d = pa_idxset_get_by_index(c->sinks, index); @@ -134,3 +177,14 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t return d; } + +void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_type type) { + char **s; + assert(c); + + s = type == PA_NAMEREG_SINK ? &c->default_sink_name : &c->default_source_name; + assert(s); + + pa_xfree(*s); + *s = pa_xstrdup(name); +} diff --git a/polyp/namereg.h b/polyp/namereg.h index 0af83cd84..5bc92693d 100644 --- a/polyp/namereg.h +++ b/polyp/namereg.h @@ -33,6 +33,7 @@ void pa_namereg_free(struct pa_core *c); const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_namereg_type type, void *data, int fail); void pa_namereg_unregister(struct pa_core *c, const char *name); -void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type); +void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type, int autoload); +void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_type type); #endif diff --git a/polyp/packet.c b/polyp/packet.c index e94df057c..955feeb12 100644 --- a/polyp/packet.c +++ b/polyp/packet.c @@ -27,13 +27,12 @@ #include #include "packet.h" +#include "xmalloc.h" struct pa_packet* pa_packet_new(size_t length) { struct pa_packet *p; assert(length); - p = malloc(sizeof(struct pa_packet)+length); - assert(p); - + p = pa_xmalloc(sizeof(struct pa_packet)+length); p->ref = 1; p->length = length; p->data = (uint8_t*) (p+1); @@ -44,9 +43,7 @@ struct pa_packet* pa_packet_new(size_t length) { struct pa_packet* pa_packet_new_dynamic(uint8_t* data, size_t length) { struct pa_packet *p; assert(data && length); - p = malloc(sizeof(struct pa_packet)); - assert(p); - + p = pa_xmalloc(sizeof(struct pa_packet)); p->ref = 1; p->length = length; p->data = data; @@ -66,7 +63,7 @@ void pa_packet_unref(struct pa_packet *p) { if (p->ref == 0) { if (p->type == PA_PACKET_DYNAMIC) - free(p->data); - free(p); + pa_xfree(p->data); + pa_xfree(p); } } diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index 2ab98b52a..c34c6e0ad 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -29,6 +29,7 @@ #include "pdispatch.h" #include "native-common.h" +#include "xmalloc.h" /*#define DEBUG_OPCODES*/ @@ -96,7 +97,7 @@ static void reply_info_free(struct reply_info *r) { if (r->next) r->next->previous = r->previous; - free(r); + pa_xfree(r); } struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *mainloop, const struct pa_pdispatch_command*table, unsigned entries) { @@ -105,8 +106,7 @@ struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *mainloop, const st assert((entries && table) || (!entries && !table)); - pd = malloc(sizeof(struct pa_pdispatch)); - assert(pd); + pd = pa_xmalloc(sizeof(struct pa_pdispatch)); pd->mainloop = mainloop; pd->command_table = table; pd->n_commands = entries; @@ -129,7 +129,7 @@ void pa_pdispatch_free(struct pa_pdispatch *pd) { while (pd->replies) reply_info_free(pd->replies); - free(pd); + pa_xfree(pd); } int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *userdata) { @@ -207,8 +207,7 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time struct timeval tv; assert(pd && cb); - r = malloc(sizeof(struct reply_info)); - assert(r); + r = pa_xmalloc(sizeof(struct reply_info)); r->pdispatch = pd; r->callback = cb; r->userdata = userdata; diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 79ca83ea5..0989a78d2 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -21,7 +21,7 @@ # Load audio drivers #load module-alsa-sink #load module-alsa-source device=plughw:1,0 -load module-oss device="/dev/dsp" +#load module-oss device="/dev/dsp" #load module-oss-mmap device="/dev/dsp" # Load several protocols @@ -36,9 +36,15 @@ load module-x11-bell # Load the CLI module load module-cli -.nofail +autoload_sink_add oss_output module-oss device="/dev/dsp" sink_name=oss_output source_name=oss_input +autoload_source_add oss_input module-oss device="/dev/dsp" sink_name=oss_output source_name=oss_input # Make some devices default sink_default oss_output source_default oss_input +.nofail + +# Load something to the sample cache +scache_load /usr/share/sounds/KDE_Notify.wav x11-bell +scache_play x11-bell oss_output diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index 024cb18ab..1f5ea5535 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -32,7 +32,7 @@ #include "polyplib.h" #include "mainloop.h" #include "native-common.h" -/*#include "polyp-error.h"*/ +#include "xmalloc.h" struct pa_simple { struct pa_mainloop *mainloop; @@ -98,8 +98,7 @@ struct pa_simple* pa_simple_new( int error = PA_ERROR_INTERNAL; assert(ss); - p = malloc(sizeof(struct pa_simple)); - assert(p); + p = pa_xmalloc(sizeof(struct pa_simple)); p->context = NULL; p->stream = NULL; p->mainloop = pa_mainloop_new(); @@ -146,7 +145,7 @@ fail: void pa_simple_free(struct pa_simple *s) { assert(s); - free(s->read_data); + pa_xfree(s->read_data); if (s->stream) pa_stream_free(s->stream); @@ -157,7 +156,7 @@ void pa_simple_free(struct pa_simple *s) { if (s->mainloop) pa_mainloop_free(s->mainloop); - free(s); + pa_xfree(s); } int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *perror) { @@ -191,11 +190,10 @@ static void read_callback(struct pa_stream *s, const void*data, size_t length, v if (p->read_data) { fprintf(stderr, __FILE__": Buffer overflow, dropping incoming memory blocks.\n"); - free(p->read_data); + pa_xfree(p->read_data); } - p->read_data = malloc(p->read_length = length); - assert(p->read_data); + p->read_data = pa_xmalloc(p->read_length = length); memcpy(p->read_data, data, length); p->read_index = 0; } @@ -219,7 +217,7 @@ int pa_simple_read(struct pa_simple *p, void*data, size_t length, int *perror) { p->read_length -= l; if (!p->read_length) { - free(p->read_data); + pa_xfree(p->read_data); p->read_data = NULL; p->read_index = 0; } diff --git a/polyp/polyplib.c b/polyp/polyplib.c index b1052a8d3..4d87fdb5b 100644 --- a/polyp/polyplib.c +++ b/polyp/polyplib.c @@ -40,6 +40,7 @@ #include "pstream-util.h" #include "authkey.h" #include "util.h" +#include "xmalloc.h" #define DEFAULT_MAXLENGTH 204800 #define DEFAULT_TLENGTH 10240 @@ -148,9 +149,8 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * struct pa_context *c; assert(mainloop && name); - c = malloc(sizeof(struct pa_context)); - assert(c); - c->name = strdup(name); + c = pa_xmalloc(sizeof(struct pa_context)); + c->name = pa_xstrdup(name); c->mainloop = mainloop; c->client = NULL; c->pstream = NULL; @@ -203,8 +203,8 @@ void pa_context_free(struct pa_context *c) { if (c->playback_streams) pa_dynarray_free(c->playback_streams, NULL, NULL); - free(c->name); - free(c); + pa_xfree(c->name); + pa_xfree(c); } static void stream_dead(struct pa_stream *s) { @@ -391,14 +391,12 @@ static struct sockaddr *resolve_server(const char *server, size_t *len) { return NULL; assert(result); - sa = malloc(*len = result->ai_addrlen); - assert(sa); + sa = pa_xmalloc(*len = result->ai_addrlen); memcpy(sa, result->ai_addr, *len); freeaddrinfo(result); return sa; - } int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { @@ -430,7 +428,7 @@ int pa_context_connect(struct pa_context *c, const char *server, void (*complete } c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); - free(sa); + pa_xfree(sa); if (!c->client) { c->error = PA_ERROR_CONNECTIONREFUSED; @@ -578,8 +576,7 @@ static void create_stream(struct pa_stream *s, const char *dev) { static struct pa_stream *internal_stream_new(struct pa_context *c) { struct pa_stream *s; - s = malloc(sizeof(struct pa_stream)); - assert(s); + s = pa_xmalloc(sizeof(struct pa_stream)); s->context = c; s->read_callback = NULL; @@ -632,7 +629,7 @@ struct pa_stream* pa_stream_new( s->create_complete_callback = complete; s->create_complete_userdata = userdata; - s->name = strdup(name); + s->name = pa_xstrdup(name); s->state = STREAM_CREATING; s->direction = dir; s->sample_spec = *ss; @@ -657,7 +654,7 @@ void pa_stream_free(struct pa_stream *s) { if (s->context->pdispatch) pa_pdispatch_unregister_reply(s->context->pdispatch, s); - free(s->name); + pa_xfree(s->name); if (s->channel_valid && s->context->state == CONTEXT_READY) { struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); @@ -680,7 +677,7 @@ void pa_stream_free(struct pa_stream *s) { else s->context->first_stream = s->next; - free(s); + pa_xfree(s); } void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { @@ -968,7 +965,7 @@ struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *nam s->create_complete_callback = cb; s->create_complete_userdata = userdata; - s->name = strdup(name); + s->name = pa_xstrdup(name); s->state = STREAM_CREATING; s->direction = PA_STREAM_UPLOAD; s->sample_spec = *ss; diff --git a/polyp/protocol-cli.c b/polyp/protocol-cli.c index d6e69b54f..11aeabe0c 100644 --- a/polyp/protocol-cli.c +++ b/polyp/protocol-cli.c @@ -28,6 +28,7 @@ #include "protocol-cli.h" #include "cli.h" +#include "xmalloc.h" struct pa_protocol_cli { struct pa_module *module; @@ -59,8 +60,7 @@ struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_sock struct pa_protocol_cli* p; assert(core && server); - p = malloc(sizeof(struct pa_protocol_cli)); - assert(p); + p = pa_xmalloc(sizeof(struct pa_protocol_cli)); p->module = m; p->core = core; p->server = server; @@ -81,5 +81,5 @@ void pa_protocol_cli_free(struct pa_protocol_cli *p) { pa_idxset_free(p->connections, free_connection, NULL); pa_socket_server_free(p->server); - free(p); + pa_xfree(p); } diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index d80445dee..5f6f02fa8 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -43,6 +43,8 @@ #include "sample-util.h" #include "authkey.h" #include "debug.h" +#include "namereg.h" +#include "xmalloc.h" #define DEFAULT_COOKIE_FILE ".esd_auth" @@ -78,7 +80,6 @@ struct connection { size_t memblock_index, fragment_size; } playback; - struct pa_memchunk scache_memchunk; char *scache_name; struct pa_sample_spec scache_sample_spec; @@ -90,7 +91,7 @@ struct pa_protocol_esound { struct pa_core *core; struct pa_socket_server *server; struct pa_idxset *connections; - uint32_t sink_index, source_index; + char *sink_name, *source_name; unsigned n_player; uint8_t esd_key[ESD_KEY_LEN]; }; @@ -177,8 +178,8 @@ static void connection_free(struct connection *c) { if (c->playback.current_memblock) pa_memblock_unref(c->playback.current_memblock); - free(c->read_data); - free(c->write_data); + pa_xfree(c->read_data); + pa_xfree(c->write_data); pa_iochannel_free(c->io); @@ -187,31 +188,9 @@ static void connection_free(struct connection *c) { if (c->scache_memchunk.memblock) pa_memblock_unref(c->scache_memchunk.memblock); - free(c->scache_name); + pa_xfree(c->scache_name); - free(c); -} - -static struct pa_sink* get_output_sink(struct pa_protocol_esound *p) { - struct pa_sink *s; - assert(p); - - if (!(s = pa_idxset_get_by_index(p->core->sinks, p->sink_index))) - s = pa_sink_get_default(p->core); - - p->sink_index = s ? s->index : PA_IDXSET_INVALID; - return s; -} - -static struct pa_source* get_input_source(struct pa_protocol_esound *p) { - struct pa_source *s; - assert(p); - - if (!(s = pa_idxset_get_by_index(p->core->sources, p->sink_index))) - s = pa_source_get_default(p->core); - - p->source_index = s ? s->index : PA_IDXSET_INVALID; - return s; + pa_xfree(c); } static void* connection_write(struct connection *c, size_t length) { @@ -224,7 +203,7 @@ static void* connection_write(struct connection *c, size_t length) { t = c->write_data_length+length; if (c->write_data_alloc < t) - c->write_data = realloc(c->write_data, c->write_data_alloc = t); + c->write_data = pa_xrealloc(c->write_data, c->write_data_alloc = t); assert(c->write_data); @@ -299,7 +278,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons if (!pa_sample_spec_valid(&ss)) return -1; - if (!(sink = get_output_sink(c->protocol))) { + if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { fprintf(stderr, __FILE__": No output sink\n"); return -1; } @@ -356,7 +335,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co if (request == ESD_PROTO_STREAM_MON) { struct pa_sink* sink; - if (!(sink = get_output_sink(c->protocol))) + if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) return -1; if (!(source = sink->monitor_source)) @@ -364,7 +343,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co } else { assert(request == ESD_PROTO_STREAM_REC); - if (!(source = get_input_source(c->protocol))) + if (!(source = pa_namereg_get(c->protocol->core, c->protocol->source_name, PA_NAMEREG_SOURCE, 1))) return -1; } @@ -402,7 +381,7 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons int latency, *lag; assert(c && !data && length == 0); - if (!(sink = get_output_sink(c->protocol))) + if (!(sink = pa_namereg(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) latency = 0; else { float usec = pa_sink_get_latency(sink); @@ -422,7 +401,7 @@ static int esd_proto_server_info(struct connection *c, esd_proto_t request, cons struct pa_sink *sink; assert(c && data && length == sizeof(int)); - if ((sink = get_output_sink(c->protocol))) { + if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { rate = sink->sample_spec.rate; format = format_native2esd(&sink->sample_spec); } @@ -600,8 +579,7 @@ static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, con c->scache_memchunk.length = sc_length; c->scache_sample_spec = ss; assert(!c->scache_name); - c->scache_name = strdup(name); - assert(c->scache_name); + c->scache_name = pa_xstrdup(name); c->state = ESD_CACHING_SAMPLE; @@ -653,7 +631,7 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque if (request == ESD_PROTO_SAMPLE_PLAY) { struct pa_sink *sink; - if ((sink = get_output_sink(c->protocol))) + if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0) *ok = (int) index+1; } else { @@ -714,7 +692,7 @@ static int do_read(struct connection *c) { } else { if (c->read_data_alloc < handler->data_length) - c->read_data = realloc(c->read_data, c->read_data_alloc = handler->data_length); + c->read_data = pa_xrealloc(c->read_data, c->read_data_alloc = handler->data_length); assert(c->read_data); c->state = ESD_NEEDS_REQDATA; @@ -769,7 +747,7 @@ static int do_read(struct connection *c) { c->scache_memchunk.memblock = NULL; c->scache_memchunk.index = c->scache_memchunk.length = 0; - free(c->scache_name); + pa_xfree(c->scache_name); c->scache_name = NULL; c->state = ESD_NEXT_REQUEST; @@ -964,8 +942,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo char cname[256]; assert(s && io && userdata); - c = malloc(sizeof(struct connection)); - assert(c); + c = pa_xmalloc(sizeof(struct connection)); c->protocol = userdata; c->io = io; pa_iochannel_set_callback(c->io, io_callback, c); @@ -982,8 +959,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->swap_byte_order = 0; c->read_data_length = 0; - c->read_data = malloc(c->read_data_alloc = proto_map[ESD_PROTO_CONNECT].data_length); - assert(c->read_data); + c->read_data = pa_xmalloc(c->read_data_alloc = proto_map[ESD_PROTO_CONNECT].data_length); c->write_data_length = c->write_data_index = c->write_data_alloc = 0; c->write_data = NULL; @@ -1006,7 +982,6 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->scache_name = NULL; c->fixed_source = c->protocol->core->mainloop->source_fixed(c->protocol->core->mainloop, fixed_callback, c); - assert(c->fixed_source); c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); pa_idxset_put(c->protocol->connections, c, &c->index); @@ -1015,24 +990,13 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo /*** entry points ***/ struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { - uint32_t source_index, sink_index; struct pa_protocol_esound *p; assert(core && server && ma); - if (pa_modargs_get_source_index(ma, core, &source_index) < 0) { - fprintf(stderr, __FILE__": source does not exist.\n"); - return NULL; - } - - if (pa_modargs_get_sink_index(ma, core, &sink_index) < 0) { - fprintf(stderr, __FILE__": sink does not exist.\n"); - return NULL; - } - p = malloc(sizeof(struct pa_protocol_esound)); - assert(p); + p = pa_xmalloc(sizeof(struct pa_protocol_esound)); if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", DEFAULT_COOKIE_FILE), p->esd_key, sizeof(p->esd_key)) < 0) { - free(p); + pa_xfree(p); return NULL; } @@ -1043,8 +1007,9 @@ struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa p->core = core; p->connections = pa_idxset_new(NULL, NULL); assert(p->connections); - p->sink_index = sink_index; - p->source_index = source_index; + + p->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + p->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL)); p->n_player = 0; return p; @@ -1059,5 +1024,5 @@ void pa_protocol_esound_free(struct pa_protocol_esound *p) { pa_idxset_free(p->connections, NULL, NULL); pa_socket_server_free(p->server); - free(p); + pa_xfree(p); } diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index a2332a127..c0aef180e 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -41,6 +41,7 @@ #include "authkey.h" #include "namereg.h" #include "scache.h" +#include "xmalloc.h" struct connection; struct pa_protocol_native; @@ -157,13 +158,11 @@ static struct upload_stream* upload_stream_new(struct connection *c, const struc struct upload_stream *s; assert(c && ss && name && length); - s = malloc(sizeof(struct upload_stream)); - assert (s); + s = pa_xmalloc(sizeof(struct upload_stream)); s->type = UPLOAD_STREAM; s->connection = c; s->sample_spec = *ss; - s->name = strdup(name); - assert(s->name); + s->name = pa_xstrdup(name); s->memchunk.memblock = NULL; s->memchunk.index = 0; @@ -180,12 +179,12 @@ static void upload_stream_free(struct upload_stream *o) { pa_idxset_remove_by_data(o->connection->output_streams, o, NULL); - free(o->name); + pa_xfree(o->name); if (o->memchunk.memblock) pa_memblock_unref(o->memchunk.memblock); - free(o); + pa_xfree(o); } static struct record_stream* record_stream_new(struct connection *c, struct pa_source *source, const struct pa_sample_spec *ss, const char *name, size_t maxlength, size_t fragment_size) { @@ -197,8 +196,7 @@ static struct record_stream* record_stream_new(struct connection *c, struct pa_s if (!(source_output = pa_source_output_new(source, name, ss))) return NULL; - s = malloc(sizeof(struct record_stream)); - assert(s); + s = pa_xmalloc(sizeof(struct record_stream)); s->connection = c; s->source_output = source_output; s->source_output->push = source_output_push_cb; @@ -224,7 +222,7 @@ static void record_stream_free(struct record_stream* r) { pa_idxset_remove_by_data(r->connection->record_streams, r, NULL); pa_source_output_free(r->source_output); pa_memblockq_free(r->memblockq); - free(r); + pa_xfree(r); } static struct playback_stream* playback_stream_new(struct connection *c, struct pa_sink *sink, const struct pa_sample_spec *ss, const char *name, @@ -239,8 +237,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct if (!(sink_input = pa_sink_input_new(sink, name, ss))) return NULL; - s = malloc(sizeof(struct playback_stream)); - assert (s); + s = pa_xmalloc(sizeof(struct playback_stream)); s->type = PLAYBACK_STREAM; s->connection = c; s->sink_input = sink_input; @@ -272,7 +269,7 @@ static void playback_stream_free(struct playback_stream* p) { pa_idxset_remove_by_data(p->connection->output_streams, p, NULL); pa_sink_input_free(p->sink_input); pa_memblockq_free(p->memblockq); - free(p); + pa_xfree(p); } static void connection_free(struct connection *c) { @@ -295,7 +292,7 @@ static void connection_free(struct connection *c) { pa_pdispatch_free(c->pdispatch); pa_pstream_free(c->pstream); pa_client_free(c->client); - free(c); + pa_xfree(c); } static void request_bytes(struct playback_stream *s) { @@ -476,12 +473,10 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com return; } - if (!*sink_name || sink_index == (uint32_t) -1) - sink = pa_sink_get_default(c->protocol->core); - else if (sink_index != (uint32_t) -1) + if (sink_index != (uint32_t) -1) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); else - sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK); + sink = pa_namereg_get(c->protocol->core, *sink_name ? sink_name : NULL, PA_NAMEREG_SINK, 1); if (!sink) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); @@ -577,12 +572,10 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma return; } - if (!*source_name || source_index == (uint32_t) -1) - source = pa_source_get_default(c->protocol->core); - else if (source_index != (uint32_t) -1) + if (source_index != (uint32_t) -1) source = pa_idxset_get_by_index(c->protocol->core->sources, source_index); else - source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE); + source = pa_namereg_get(c->protocol->core, *source_name ? source_name : NULL, PA_NAMEREG_SOURCE, 1); if (!source) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); @@ -681,12 +674,12 @@ static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t t if (command == PA_COMMAND_LOOKUP_SINK) { struct pa_sink *sink; - if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK))) + if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1))) index = sink->index; } else { struct pa_source *source; assert(command == PA_COMMAND_LOOKUP_SOURCE); - if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE))) + if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1))) index = source->index; } @@ -888,12 +881,10 @@ static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint3 return; } - if (!*sink_name && sink_index == (uint32_t) -1) - sink = pa_sink_get_default(c->protocol->core); - else if (sink_index != (uint32_t) -1) + if (sink_index != (uint32_t) -1) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); else - sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK); + sink = pa_namereg_get(c->protocol->core, *sink_name ? sink_name : NULL, PA_NAMEREG_SINK, 1); if (!sink) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); @@ -1027,8 +1018,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo struct connection *c; assert(s && io && p); - c = malloc(sizeof(struct connection)); - assert(c); + c = pa_xmalloc(sizeof(struct connection)); c->authorized = p->public; c->protocol = p; assert(p->core); @@ -1070,11 +1060,10 @@ struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct p return NULL; } - p = malloc(sizeof(struct pa_protocol_native)); - assert(p); + p = pa_xmalloc(sizeof(struct pa_protocol_native)); if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), p->auth_cookie, sizeof(p->auth_cookie)) < 0) { - free(p); + pa_xfree(p); return NULL; } @@ -1098,5 +1087,5 @@ void pa_protocol_native_free(struct pa_protocol_native *p) { connection_free(c); pa_idxset_free(p->connections, NULL, NULL); pa_socket_server_free(p->server); - free(p); + pa_xfree(p); } diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 037d4f9ae..4b3b1513c 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -36,6 +36,7 @@ #include "client.h" #include "sample-util.h" #include "namereg.h" +#include "xmalloc.h" struct connection { struct pa_protocol_simple *protocol; @@ -63,7 +64,7 @@ struct pa_protocol_simple { DUPLEX = 3 } mode; struct pa_sample_spec sample_spec; - uint32_t sink_index, source_index; + char *source_name, *sink_name; }; #define PLAYBACK_BUFFER_SECONDS (.5) @@ -92,7 +93,7 @@ static void connection_free(struct connection *c) { pa_memblockq_free(c->output_memblockq); if (c->fixed_source) c->protocol->core->mainloop->cancel_fixed(c->protocol->core->mainloop, c->fixed_source); - free(c); + pa_xfree(c); } static int do_read(struct connection *c) { @@ -275,8 +276,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo char cname[256]; assert(s && io && p); - c = malloc(sizeof(struct connection)); - assert(c); + c = pa_xmalloc(sizeof(struct connection)); c->io = io; c->sink_input = NULL; c->source_output = NULL; @@ -298,17 +298,16 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo struct pa_sink *sink; size_t l; - if (!(sink = pa_idxset_get_by_index(p->core->sinks, p->sink_index))) - if (!(sink = pa_sink_get_default(p->core))) { - fprintf(stderr, "Failed to get sink.\n"); - goto fail; - } + if (!(sink = pa_namereg_get(p->core, p->sink_name, PA_NAMEREG_SINK, 1))) { + fprintf(stderr, "Failed to get sink.\n"); + goto fail; + } - c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec); - if (!c->sink_input) { + if (!(c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec))) { fprintf(stderr, "Failed to create sink input.\n"); goto fail; } + c->sink_input->owner = p->module; c->sink_input->client = c->client; @@ -329,11 +328,10 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo struct pa_source *source; size_t l; - if (!(source = pa_idxset_get_by_index(p->core->sources, p->source_index))) - if (!(source = pa_source_get_default(p->core))) { - fprintf(stderr, "Failed to get source.\n"); - goto fail; - } + if (!(source = pa_namereg_get(p->core, p->source_name, PA_NAMEREG_SOURCE, 1))) { + fprintf(stderr, "Failed to get source.\n"); + goto fail; + } c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec); if (!c->source_output) { @@ -371,10 +369,7 @@ struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct p uint32_t enable; assert(core && server && ma); - p = malloc(sizeof(struct pa_protocol_simple)); - assert(p); - memset(p, 0, sizeof(struct pa_protocol_simple)); - + p = pa_xmalloc0(sizeof(struct pa_protocol_simple)); p->module = m; p->core = core; p->server = server; @@ -386,15 +381,8 @@ struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct p goto fail; } - if (pa_modargs_get_source_index(ma, core, &p->source_index) < 0) { - fprintf(stderr, __FILE__": source does not exist.\n"); - goto fail; - } - - if (pa_modargs_get_sink_index(ma, core, &p->sink_index) < 0) { - fprintf(stderr, __FILE__": sink does not exist.\n"); - goto fail; - } + p->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL)); + p->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); enable = 0; if (pa_modargs_get_value_u32(ma, "record", &enable) < 0) { @@ -439,6 +427,6 @@ void pa_protocol_simple_free(struct pa_protocol_simple *p) { if (p->server) pa_socket_server_free(p->server); - free(p); + pa_xfree(p); } diff --git a/polyp/pstream.c b/polyp/pstream.c index 7d576a16e..e7441b24b 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -30,6 +30,7 @@ #include "pstream.h" #include "queue.h" +#include "xmalloc.h" enum pa_pstream_descriptor_index { PA_PSTREAM_DESCRIPTOR_LENGTH, @@ -148,8 +149,7 @@ struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel struct pa_pstream *p; assert(io); - p = malloc(sizeof(struct pa_pstream)); - assert(p); + p = pa_xmalloc(sizeof(struct pa_pstream)); p->io = io; pa_iochannel_set_callback(io, io_callback, p); @@ -199,7 +199,7 @@ static void item_free(void *item, void *p) { pa_packet_unref(i->packet); } - free(i); + pa_xfree(i); } void pa_pstream_free(struct pa_pstream *p) { @@ -224,15 +224,14 @@ void pa_pstream_free(struct pa_pstream *p) { pa_packet_unref(p->read.packet); p->mainloop->cancel_fixed(p->mainloop, p->mainloop_source); - free(p); + pa_xfree(p); } void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { struct item_info *i; assert(p && packet); - i = malloc(sizeof(struct item_info)); - assert(i); + i = pa_xmalloc(sizeof(struct item_info)); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); @@ -244,8 +243,7 @@ void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t del struct item_info *i; assert(p && channel != (uint32_t) -1 && chunk); - i = malloc(sizeof(struct item_info)); - assert(i); + i = pa_xmalloc(sizeof(struct item_info)); i->type = PA_PSTREAM_ITEM_MEMBLOCK; i->chunk = *chunk; i->channel = channel; diff --git a/polyp/queue.c b/polyp/queue.c index 9befd4753..9488f4333 100644 --- a/polyp/queue.c +++ b/polyp/queue.c @@ -27,6 +27,7 @@ #include #include "queue.h" +#include "xmalloc.h" struct queue_entry { struct queue_entry *next; @@ -39,8 +40,7 @@ struct pa_queue { }; struct pa_queue* pa_queue_new(void) { - struct pa_queue *q = malloc(sizeof(struct pa_queue)); - assert(q); + struct pa_queue *q = pa_xmalloc(sizeof(struct pa_queue)); q->front = q->back = NULL; q->length = 0; return q; @@ -57,18 +57,17 @@ void pa_queue_free(struct pa_queue* q, void (*destroy)(void *p, void *userdata), if (destroy) destroy(e->data, userdata); - free(e); + pa_xfree(e); e = n; } - free(q); + pa_xfree(q); } void pa_queue_push(struct pa_queue *q, void *p) { struct queue_entry *e; - e = malloc(sizeof(struct queue_entry)); - + e = pa_xmalloc(sizeof(struct queue_entry)); e->data = p; e->next = NULL; @@ -96,7 +95,7 @@ void* pa_queue_pop(struct pa_queue *q) { q->back = NULL; p = e->data; - free(e); + pa_xfree(e); q->length--; diff --git a/polyp/resampler.c b/polyp/resampler.c index adf08e80c..241f97c49 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -30,6 +30,7 @@ #include "resampler.h" #include "sconv.h" +#include "xmalloc.h" struct pa_resampler { struct pa_sample_spec i_ss, o_ss; @@ -55,8 +56,7 @@ struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const stru if (a->format == PA_SAMPLE_ALAW || a->format == PA_SAMPLE_ULAW || b->format == PA_SAMPLE_ALAW || b->format == PA_SAMPLE_ULAW) goto fail; - r = malloc(sizeof(struct pa_resampler)); - assert(r); + r = pa_xmalloc(sizeof(struct pa_resampler)); r->channels = a->channels; if (b->channels < r->channels) @@ -87,7 +87,7 @@ struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const stru fail: if (r) - free(r); + pa_xfree(r); return NULL; } @@ -96,9 +96,9 @@ void pa_resampler_free(struct pa_resampler *r) { assert(r); if (r->src_state) src_delete(r->src_state); - free(r->i_buf); - free(r->o_buf); - free(r); + pa_xfree(r->i_buf); + pa_xfree(r->o_buf); + pa_xfree(r); } size_t pa_resampler_request(struct pa_resampler *r, size_t out_length) { @@ -139,7 +139,7 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru assert(out->memblock); if (r->i_alloc < eff_ins) - r->i_buf = realloc(r->i_buf, sizeof(float) * (r->i_alloc = eff_ins)); + r->i_buf = pa_xrealloc(r->i_buf, sizeof(float) * (r->i_alloc = eff_ins)); assert(r->i_buf); r->to_float32_func(eff_ins, in->memblock->data+in->index, i_nchannels, r->i_buf); @@ -149,7 +149,7 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru SRC_DATA data; if (r->o_alloc < eff_ons) - r->o_buf = realloc(r->o_buf, sizeof(float) * (r->o_alloc = eff_ons)); + r->o_buf = pa_xrealloc(r->o_buf, sizeof(float) * (r->o_alloc = eff_ons)); assert(r->o_buf); data.data_in = r->i_buf; diff --git a/polyp/scache.c b/polyp/scache.c index 21af0e221..fd7b74e54 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -8,13 +8,14 @@ #include "mainloop.h" #include "sample-util.h" #include "play-memchunk.h" +#include "xmalloc.h" static void free_entry(struct pa_scache_entry *e) { assert(e); - free(e->name); + pa_xfree(e->name); if (e->memchunk.memblock) pa_memblock_unref(e->memchunk.memblock); - free(e); + pa_xfree(e); } void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index) { @@ -28,10 +29,8 @@ void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_sp pa_memblock_unref(e->memchunk.memblock); } else { put = 1; - e = malloc(sizeof(struct pa_scache_entry)); - assert(e); - e->name = strdup(name); - assert(e->name); + e = pa_xmalloc(sizeof(struct pa_scache_entry)); + e->name = pa_xstrdup(name); } e->volume = 0x100; diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 25d8022f3..04a2f0200 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -30,6 +30,7 @@ #include "sink-input.h" #include "sample-util.h" +#include "xmalloc.h" #define CONVERT_BUFFER_LENGTH 4096 @@ -44,9 +45,8 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con if (!(resampler = pa_resampler_new(spec, &s->sample_spec))) return NULL; - i = malloc(sizeof(struct pa_sink_input)); - assert(i); - i->name = name ? strdup(name) : NULL; + i = pa_xmalloc(sizeof(struct pa_sink_input)); + i->name = pa_xstrdup(name); i->client = NULL; i->owner = NULL; i->sink = s; @@ -88,8 +88,8 @@ void pa_sink_input_free(struct pa_sink_input* i) { if (i->resampler) pa_resampler_free(i->resampler); - free(i->name); - free(i); + pa_xfree(i->name); + pa_xfree(i); } void pa_sink_input_kill(struct pa_sink_input*i) { diff --git a/polyp/sink.c b/polyp/sink.c index c2c873c6d..6df92e76c 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -33,6 +33,7 @@ #include "namereg.h" #include "util.h" #include "sample-util.h" +#include "xmalloc.h" #define MAX_MIX_CHANNELS 32 @@ -43,15 +44,14 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co int r; assert(core && name && *name && spec); - s = malloc(sizeof(struct pa_sink)); - assert(s); + s = pa_xmalloc(sizeof(struct pa_sink)); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) { - free(s); + pa_xfree(s); return NULL; } - s->name = strdup(name); + s->name = pa_xstrdup(name); s->description = NULL; s->owner = NULL; @@ -62,7 +62,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co n = pa_sprintf_malloc("%s_monitor", name); s->monitor_source = pa_source_new(core, n, 0, spec); assert(s->monitor_source); - free(n); + pa_xfree(n); s->monitor_source->monitor_of = s; s->volume = PA_VOLUME_NORM; @@ -98,9 +98,9 @@ void pa_sink_free(struct pa_sink *s) { fprintf(stderr, "sink: freed %u \"%s\"\n", s->index, s->name); - free(s->name); - free(s->description); - free(s); + pa_xfree(s->name); + pa_xfree(s->description); + pa_xfree(s); } void pa_sink_notify(struct pa_sink*s) { @@ -270,19 +270,6 @@ uint32_t pa_sink_get_latency(struct pa_sink *s) { return s->get_latency(s); } -struct pa_sink* pa_sink_get_default(struct pa_core *c) { - struct pa_sink *sink; - assert(c); - - if ((sink = pa_idxset_get_by_index(c->sinks, c->default_sink_index))) - return sink; - - if (!(sink = pa_idxset_first(c->sinks, &c->default_sink_index))) - return NULL; - - fprintf(stderr, "core: default sink vanished, setting to %u.\n", sink->index); - return sink; -} void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) { sink->owner = m; diff --git a/polyp/sink.h b/polyp/sink.h index 2b5d94958..400d5d04f 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -60,8 +60,6 @@ uint32_t pa_sink_get_latency(struct pa_sink *s); void pa_sink_notify(struct pa_sink*s); -struct pa_sink* pa_sink_get_default(struct pa_core *c); - void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m); #endif diff --git a/polyp/socket-client.c b/polyp/socket-client.c index a2187e6ae..c0c355de0 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -36,6 +36,7 @@ #include "socket-client.h" #include "socket-util.h" #include "util.h" +#include "xmalloc.h" struct pa_socket_client { struct pa_mainloop_api *mainloop; @@ -50,8 +51,7 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { struct pa_socket_client *c; assert(m); - c = malloc(sizeof(struct pa_socket_client)); - assert(c); + c = pa_xmalloc(sizeof(struct pa_socket_client)); c->mainloop = m; c->fd = -1; c->io_source = c->fixed_source = NULL; @@ -226,7 +226,7 @@ void pa_socket_client_free(struct pa_socket_client *c) { c->mainloop->cancel_fixed(c->mainloop, c->fixed_source); if (c->fd >= 0) close(c->fd); - free(c); + pa_xfree(c); } void pa_socket_client_set_callback(struct pa_socket_client *c, void (*on_connection)(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata), void *userdata) { diff --git a/polyp/socket-server.c b/polyp/socket-server.c index 0f497377d..5f332f0c1 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -37,6 +37,7 @@ #include "socket-server.h" #include "socket-util.h" +#include "xmalloc.h" struct pa_socket_server { int fd; @@ -81,8 +82,7 @@ struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) struct pa_socket_server *s; assert(m && fd >= 0); - s = malloc(sizeof(struct pa_socket_server)); - assert(s); + s = pa_xmalloc(sizeof(struct pa_socket_server)); s->fd = fd; s->filename = NULL; s->on_connection = NULL; @@ -128,9 +128,7 @@ struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, co s = pa_socket_server_new(m, fd); assert(s); - s->filename = strdup(filename); - assert(s->filename); - + s->filename = pa_xstrdup(filename); s->type = SOCKET_SERVER_UNIX; return s; @@ -192,13 +190,11 @@ void pa_socket_server_free(struct pa_socket_server*s) { if (s->filename) { unlink(s->filename); - free(s->filename); + pa_xfree(s->filename); } - s->mainloop->cancel_io(s->mainloop, s->mainloop_source); - - free(s); + pa_xfree(s); } void pa_socket_server_set_callback(struct pa_socket_server*s, void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata), void *userdata) { diff --git a/polyp/socket-util.c b/polyp/socket-util.c index e0a3c28d2..904381b7e 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -40,6 +40,7 @@ #include "socket-util.h" #include "util.h" +#include "xmalloc.h" void pa_socket_peer_to_string(int fd, char *c, size_t l) { struct stat st; @@ -179,8 +180,7 @@ int pa_unix_socket_remove_stale(const char *fn) { int pa_unix_socket_make_secure_dir(const char *fn) { int ret = -1; - char *slash, *dir = strdup(fn); - assert(dir); + char *slash, *dir = pa_xstrdup(fn); if (!(slash = strrchr(dir, '/'))) goto finish; @@ -192,14 +192,13 @@ int pa_unix_socket_make_secure_dir(const char *fn) { ret = 0; finish: - free(dir); + pa_xfree(dir); return ret; } int pa_unix_socket_remove_secure_dir(const char *fn) { int ret = -1; - char *slash, *dir = strdup(fn); - assert(dir); + char *slash, *dir = pa_xstrdup(fn); if (!(slash = strrchr(dir, '/'))) goto finish; @@ -211,6 +210,6 @@ int pa_unix_socket_remove_secure_dir(const char *fn) { ret = 0; finish: - free(dir); + pa_xfree(dir); return ret; } diff --git a/polyp/source-output.c b/polyp/source-output.c index 2705fdb3c..07901fa86 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -28,6 +28,7 @@ #include #include "source-output.h" +#include "xmalloc.h" struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec) { struct pa_source_output *o; @@ -39,9 +40,8 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n if (!(resampler = pa_resampler_new(&s->sample_spec, spec))) return NULL; - o = malloc(sizeof(struct pa_source_output)); - assert(o); - o->name = name ? strdup(name) : NULL; + o = pa_xmalloc(sizeof(struct pa_source_output)); + o->name = pa_xstrdup(name); o->client = NULL; o->owner = NULL; o->source = s; @@ -71,8 +71,8 @@ void pa_source_output_free(struct pa_source_output* o) { if (o->resampler) pa_resampler_free(o->resampler); - free(o->name); - free(o); + pa_xfree(o->name); + pa_xfree(o); } void pa_source_output_kill(struct pa_source_output*i) { diff --git a/polyp/source.c b/polyp/source.c index 136354145..65c90e9a5 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -31,6 +31,7 @@ #include "source.h" #include "source-output.h" #include "namereg.h" +#include "xmalloc.h" struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) { struct pa_source *s; @@ -38,15 +39,14 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail int r; assert(core && spec && name && *name); - s = malloc(sizeof(struct pa_source)); - assert(s); + s = pa_xmalloc(sizeof(struct pa_source)); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) { - free(s); + pa_xfree(s); return NULL; } - s->name = strdup(name); + s->name = pa_xstrdup(name); s->description = NULL; s->owner = NULL; @@ -84,9 +84,9 @@ void pa_source_free(struct pa_source *s) { fprintf(stderr, "source: freed %u \"%s\"\n", s->index, s->name); - free(s->name); - free(s->description); - free(s); + pa_xfree(s->name); + pa_xfree(s->description); + pa_xfree(s); } void pa_source_notify(struct pa_source*s) { @@ -111,20 +111,6 @@ void pa_source_post(struct pa_source*s, struct pa_memchunk *chunk) { pa_idxset_foreach(s->outputs, do_post, chunk); } -struct pa_source* pa_source_get_default(struct pa_core *c) { - struct pa_source *source; - assert(c); - - if ((source = pa_idxset_get_by_index(c->sources, c->default_source_index))) - return source; - - if (!(source = pa_idxset_first(c->sources, &c->default_source_index))) - return NULL; - - fprintf(stderr, "core: default source vanished, setting to %u.\n", source->index); - return source; -} - void pa_source_set_owner(struct pa_source *s, struct pa_module *m) { assert(s); s->owner = m; diff --git a/polyp/source.h b/polyp/source.h index 9c584a6de..32ef14e60 100644 --- a/polyp/source.h +++ b/polyp/source.h @@ -54,8 +54,6 @@ void pa_source_post(struct pa_source*s, struct pa_memchunk *b); void pa_source_notify(struct pa_source *s); -struct pa_source* pa_source_get_default(struct pa_core *c); - void pa_source_set_owner(struct pa_source *s, struct pa_module *m); #endif diff --git a/polyp/strbuf.c b/polyp/strbuf.c index c6a3772db..169604e82 100644 --- a/polyp/strbuf.c +++ b/polyp/strbuf.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "strbuf.h" @@ -44,8 +45,7 @@ struct pa_strbuf { }; struct pa_strbuf *pa_strbuf_new(void) { - struct pa_strbuf *sb = malloc(sizeof(struct pa_strbuf)); - assert(sb); + struct pa_strbuf *sb = pa_xmalloc(sizeof(struct pa_strbuf)); sb->length = 0; sb->head = sb->tail = NULL; return sb; @@ -56,10 +56,10 @@ void pa_strbuf_free(struct pa_strbuf *sb) { while (sb->head) { struct chunk *c = sb->head; sb->head = sb->head->next; - free(c); + pa_xfree(c); } - free(sb); + pa_xfree(sb); } char *pa_strbuf_tostring(struct pa_strbuf *sb) { @@ -67,8 +67,7 @@ char *pa_strbuf_tostring(struct pa_strbuf *sb) { struct chunk *c; assert(sb); - t = malloc(sb->length+1); - assert(t); + t = pa_xmalloc(sb->length+1); e = t; for (c = sb->head; c; c = c->next) { @@ -101,8 +100,7 @@ void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t l) { if (!l) return; - c = malloc(sizeof(struct chunk)+l); - assert(c); + c = pa_xmalloc(sizeof(struct chunk)+l); c->next = NULL; c->length = l; @@ -131,8 +129,7 @@ int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) { for(;;) { va_list ap; - c = realloc(c, sizeof(struct chunk)+size); - assert(c); + c = pa_xrealloc(c, sizeof(struct chunk)+size); va_start(ap, format); r = vsnprintf(c->text, size, format, ap); diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 0d93c1e90..cb93a9c4d 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -29,6 +29,7 @@ #include #include "tagstruct.h" +#include "xmalloc.h" enum tags { TAG_STRING = 't', @@ -55,8 +56,7 @@ struct pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) { assert(!data || (data && length)); - t = malloc(sizeof(struct pa_tagstruct)); - assert(t); + t = pa_xmalloc(sizeof(struct pa_tagstruct)); t->data = (uint8_t*) data; t->allocated = t->length = data ? length : 0; t->rindex = 0; @@ -67,8 +67,8 @@ struct pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) { void pa_tagstruct_free(struct pa_tagstruct*t) { assert(t); if (t->dynamic) - free(t->data); - free(t); + pa_xfree(t->data); + pa_xfree(t); } uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l) { @@ -76,7 +76,7 @@ uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l) { assert(t && t->dynamic && l); p = t->data; *l = t->length; - free(t); + pa_xfree(t); return p; } @@ -86,8 +86,7 @@ static void extend(struct pa_tagstruct*t, size_t l) { if (l <= t->allocated) return; - t->data = realloc(t->data, t->allocated = l+100); - assert(t->data); + t->data = pa_xrealloc(t->data, t->allocated = l+100); } void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s) { diff --git a/polyp/tokenizer.c b/polyp/tokenizer.c index c7f18d267..43d695bd6 100644 --- a/polyp/tokenizer.c +++ b/polyp/tokenizer.c @@ -29,13 +29,14 @@ #include "tokenizer.h" #include "dynarray.h" +#include "xmalloc.h" struct pa_tokenizer { struct pa_dynarray *dynarray; }; static void token_free(void *p, void *userdata) { - free(p); + pa_xfree(p); } static void parse(struct pa_dynarray*a, const char *s, unsigned args) { @@ -50,8 +51,7 @@ static void parse(struct pa_dynarray*a, const char *s, unsigned args) { p = s+strspn(s, delimiter); while (*p && (infty || args >= 2)) { size_t l = strcspn(p, delimiter); - char *n = strndup(p, l); - assert(n); + char *n = pa_xstrndup(p, l); pa_dynarray_append(a, n); p += l; p += strspn(p, delimiter); @@ -59,8 +59,7 @@ static void parse(struct pa_dynarray*a, const char *s, unsigned args) { } if (args && *p) { - char *n = strdup(p); - assert(n); + char *n = pa_xstrdup(p); pa_dynarray_append(a, n); } } @@ -68,8 +67,7 @@ static void parse(struct pa_dynarray*a, const char *s, unsigned args) { struct pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args) { struct pa_tokenizer *t; - t = malloc(sizeof(struct pa_tokenizer)); - assert(t); + t = pa_xmalloc(sizeof(struct pa_tokenizer)); t->dynarray = pa_dynarray_new(); assert(t->dynarray); @@ -80,7 +78,7 @@ struct pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args) { void pa_tokenizer_free(struct pa_tokenizer *t) { assert(t); pa_dynarray_free(t->dynarray, token_free, NULL); - free(t); + pa_xfree(t); } const char *pa_tokenizer_get(struct pa_tokenizer *t, unsigned i) { diff --git a/polyp/util.c b/polyp/util.c index 6e75c240c..98d910759 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -35,6 +35,7 @@ #include #include "util.h" +#include "xmalloc.h" void pa_make_nonblock_fd(int fd) { int v; @@ -129,8 +130,7 @@ char *pa_sprintf_malloc(const char *format, ...) { int r; va_list ap; - c = realloc(c, size); - assert(c); + c = pa_xrealloc(c, size); va_start(ap, format); r = vsnprintf(c, size, format, ap); From 839f99ffbf5b01e585845a061830a6fa5f0743dc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 4 Aug 2004 16:42:37 +0000 Subject: [PATCH 0103/1514] forgot some files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@104 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/autoload.c | 74 +++++++++++++++++++++++++++++++++++++++++ polyp/autoload.h | 17 ++++++++++ polyp/play-memchunk.c | 76 +++++++++++++++++++++++++++++++++++++++++++ polyp/play-memchunk.h | 8 +++++ polyp/sound-file.c | 64 ++++++++++++++++++++++++++++++++++++ polyp/sound-file.h | 9 +++++ polyp/xmalloc.c | 76 +++++++++++++++++++++++++++++++++++++++++++ polyp/xmalloc.h | 14 ++++++++ 8 files changed, 338 insertions(+) create mode 100644 polyp/autoload.c create mode 100644 polyp/autoload.h create mode 100644 polyp/play-memchunk.c create mode 100644 polyp/play-memchunk.h create mode 100644 polyp/sound-file.c create mode 100644 polyp/sound-file.h create mode 100644 polyp/xmalloc.c create mode 100644 polyp/xmalloc.h diff --git a/polyp/autoload.c b/polyp/autoload.c new file mode 100644 index 000000000..f0d70d2dc --- /dev/null +++ b/polyp/autoload.c @@ -0,0 +1,74 @@ +#include +#include +#include + +#include "autoload.h" +#include "module.h" +#include "xmalloc.h" + +static void entry_free(struct pa_autoload_entry *e) { + assert(e); + pa_xfree(e->name); + pa_xfree(e->module); + pa_xfree(e->argument); + pa_xfree(e); +} + +void pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument) { + struct pa_autoload_entry *e = NULL; + assert(c && name && module); + + if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name))) { + pa_xfree(e->module); + pa_xfree(e->argument); + } else { + e = pa_xmalloc(sizeof(struct pa_autoload_entry)); + e->name = pa_xstrdup(name); + + if (!c->autoload_hashmap) + c->autoload_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + assert(c->autoload_hashmap); + + pa_hashmap_put(c->autoload_hashmap, e->name, e); + } + + e->module = pa_xstrdup(module); + e->argument = pa_xstrdup(argument); + e->type = type; +} + +int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type) { + struct pa_autoload_entry *e; + assert(c && name && type); + + if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name))) + return -1; + + pa_hashmap_remove(c->autoload_hashmap, e->name); + entry_free(e); + return 0; +} + +void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type) { + struct pa_autoload_entry *e; + struct pa_module *m; + assert(c && name); + + if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || (e->type != type)) + return; + + if ((m = pa_module_load(c, e->module, e->argument))) + m->auto_unload = 1; +} + +static void free_func(void *p, void *userdata) { + struct pa_autoload_entry *e = p; + entry_free(e); +} + +void pa_autoload_free(struct pa_core *c) { + if (!c->autoload_hashmap) + return; + + pa_hashmap_free(c->autoload_hashmap, free_func, NULL); +} diff --git a/polyp/autoload.h b/polyp/autoload.h new file mode 100644 index 000000000..f1862e77d --- /dev/null +++ b/polyp/autoload.h @@ -0,0 +1,17 @@ +#ifndef fooautoloadhfoo +#define fooautoloadhfoo + +#include "namereg.h" + +struct pa_autoload_entry { + char *name; + enum pa_namereg_type type; + char *module, *argument; +}; + +void pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument); +void pa_autoload_free(struct pa_core *c); +int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type); +void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type); + +#endif diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c new file mode 100644 index 000000000..5c448a754 --- /dev/null +++ b/polyp/play-memchunk.c @@ -0,0 +1,76 @@ +#include +#include + +#include "play-memchunk.h" +#include "sink-input.h" +#include "xmalloc.h" + +static void sink_input_kill(struct pa_sink_input *i) { + struct pa_memchunk *c; + assert(i && i->userdata); + c = i->userdata; + + pa_memblock_unref(c->memblock); + pa_xfree(c); + pa_sink_input_free(i); +} + +static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { + struct pa_memchunk *c; + assert(i && chunk && i->userdata); + c = i->userdata; + + if (c->length <= 0) + return -1; + + assert(c->memblock && c->memblock->length); + *chunk = *c; + pa_memblock_ref(c->memblock); + + return 0; +} + +static void si_kill(void *i) { + sink_input_kill(i); +} + +static void sink_input_drop(struct pa_sink_input *i, size_t length) { + struct pa_memchunk *c; + assert(i && length && i->userdata); + c = i->userdata; + + assert(length <= c->length); + + c->length -= length; + c->index += length; + + if (c->length <= 0) + pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); +} + +int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, uint32_t volume) { + struct pa_sink_input *si; + struct pa_memchunk *nchunk; + + assert(sink && chunk); + + if (volume <= 0) + return 0; + + if (!(si = pa_sink_input_new(sink, name, ss))) + return -1; + + si->volume = volume; + si->peek = sink_input_peek; + si->drop = sink_input_drop; + si->kill = sink_input_kill; + + si->userdata = nchunk = pa_xmalloc(sizeof(struct pa_memchunk)); + *nchunk = *chunk; + + pa_memblock_ref(chunk->memblock); + + pa_sink_notify(sink); + + return 0; +} diff --git a/polyp/play-memchunk.h b/polyp/play-memchunk.h new file mode 100644 index 000000000..76f9dbd0f --- /dev/null +++ b/polyp/play-memchunk.h @@ -0,0 +1,8 @@ +#ifndef fooplaychunkhfoo +#define fooplaychunkhfoo + +#include "sink.h" + +int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, uint32_t volume); + +#endif diff --git a/polyp/sound-file.c b/polyp/sound-file.c new file mode 100644 index 000000000..b0df7185e --- /dev/null +++ b/polyp/sound-file.c @@ -0,0 +1,64 @@ +#include +#include + +#include + +#include "sound-file.h" +#include "sample.h" + +#define MAX_FILE_SIZE (1024*1024) + +int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk) { + SNDFILE*sf = NULL; + SF_INFO sfinfo; + int ret = -1; + size_t l; + assert(fname && ss && chunk); + + memset(&sfinfo, 0, sizeof(sfinfo)); + + chunk->memblock = NULL; + chunk->index = chunk->length = 0; + + if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { + fprintf(stderr, __FILE__": Failed to open file %s\n", fname); + goto finish; + } + + ss->format = PA_SAMPLE_FLOAT32; + ss->rate = sfinfo.samplerate; + ss->channels = sfinfo.channels; + + if (!pa_sample_spec_valid(ss)) { + fprintf(stderr, __FILE__": Unsupported sample format in file %s\n", fname); + goto finish; + } + + if ((l = pa_frame_size(ss)*sfinfo.frames) > MAX_FILE_SIZE) { + fprintf(stderr, __FILE__": File to large\n"); + goto finish; + } + + chunk->memblock = pa_memblock_new(l); + assert(chunk->memblock); + chunk->index = 0; + chunk->length = l; + + if (sf_readf_float(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) { + fprintf(stderr, __FILE__": Premature file end\n"); + goto finish; + } + + ret = 0; + +finish: + + if (sf) + sf_close(sf); + + if (ret != 0 && chunk->memblock) + pa_memblock_unref(chunk->memblock); + + return ret; + +} diff --git a/polyp/sound-file.h b/polyp/sound-file.h new file mode 100644 index 000000000..3a6fa4151 --- /dev/null +++ b/polyp/sound-file.h @@ -0,0 +1,9 @@ +#ifndef soundfilehfoo +#define soundfilehfoo + +#include "memchunk.h" +#include "sample.h" + +int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk); + +#endif diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c new file mode 100644 index 000000000..8ff3054da --- /dev/null +++ b/polyp/xmalloc.c @@ -0,0 +1,76 @@ +#include +#include +#include + +#include "memory.h" +#include "util.h" + +#define MAX_ALLOC_SIZE (1024*1024*20) + +#undef malloc +#undef free +#undef realloc +#undef strndup +#undef strdup + +static void oom(void) { + static const char e[] = "Not enough memory\n"; + pa_loop_write(2, e, sizeof(e)-1); + raise(SIGQUIT); + exit(1); +} + +void* pa_xmalloc(size_t size) { + void *p; + assert(size > 0); + assert(size < MAX_ALLOC_SIZE); + + if (!(p = malloc(size))) + oom(); + + return p; +} + +void* pa_xmalloc0(size_t size) { + void *p; + assert(size > 0); + assert(size < MAX_ALLOC_SIZE); + + if (!(p = calloc(1, size))) + oom(); + + return p; +} + +void *pa_xrealloc(void *ptr, size_t size) { + void *p; + assert(size > 0); + assert(size < MAX_ALLOC_SIZE); + + if (!(p = realloc(ptr, size))) + oom(); + return p; +} + +char *pa_xstrdup(const char *s) { + if (!s) + return NULL; + else { + char *r = strdup(s); + if (!r) + oom(); + + return r; + } +} + +char *pa_xstrndup(const char *s, size_t l) { + if (!s) + return NULL; + else { + char *r = strndup(s, l); + if (!r) + oom(); + return r; + } +} diff --git a/polyp/xmalloc.h b/polyp/xmalloc.h new file mode 100644 index 000000000..5f58a8adf --- /dev/null +++ b/polyp/xmalloc.h @@ -0,0 +1,14 @@ +#ifndef foomemoryhfoo +#define foomemoryhfoo + +#include + +void* pa_xmalloc(size_t l); +void *pa_xmalloc0(size_t l); +void *pa_xrealloc(void *ptr, size_t size); +#define pa_xfree free + +char *pa_xstrdup(const char *s); +char *pa_xstrndup(const char *s, size_t l); + +#endif From 964bdfd1e8255b57e9d22cd22b3784e2fc79b905 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Aug 2004 19:53:57 +0000 Subject: [PATCH 0104/1514] add initial glib mainloop adapter clean up mainloop API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@105 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 + polyp/Makefile.am | 7 +- polyp/alsa-util.c | 34 +- polyp/alsa-util.h | 4 +- polyp/core.c | 1 + polyp/core.h | 2 +- polyp/glib-mainloop.c | 503 ++++++++++++++++++++++++++++++ polyp/glib-mainloop.h | 14 + polyp/iochannel.c | 60 ++-- polyp/main.c | 11 +- polyp/mainloop-api.c | 34 +- polyp/mainloop-api.h | 48 +-- polyp/mainloop-signal.c | 99 +++--- polyp/mainloop-signal.h | 8 +- polyp/mainloop.c | 620 ++++++++++++++++++------------------- polyp/module-alsa-sink.c | 14 +- polyp/module-alsa-source.c | 14 +- polyp/module-oss-mmap.c | 19 +- polyp/module-pipe-sink.c | 16 +- polyp/module-x11-bell.c | 10 +- polyp/module.c | 20 +- polyp/module.h | 1 - polyp/native-common.h | 16 +- polyp/pacat.c | 46 +-- polyp/pactl.c | 4 +- polyp/pdispatch.c | 12 +- polyp/play-memchunk.c | 2 +- polyp/polypaudio.pa | 30 +- polyp/polyplib.h | 30 ++ polyp/protocol-esound.c | 35 ++- polyp/protocol-native.c | 122 ++++++++ polyp/protocol-simple.c | 30 +- polyp/pstream.c | 18 +- polyp/socket-client.c | 39 +-- polyp/socket-server.c | 12 +- polyp/xmalloc.h | 1 + 36 files changed, 1312 insertions(+), 628 deletions(-) create mode 100644 polyp/glib-mainloop.c create mode 100644 polyp/glib-mainloop.h diff --git a/configure.ac b/configure.ac index 9e5352a5e..3183d1743 100644 --- a/configure.ac +++ b/configure.ac @@ -54,6 +54,10 @@ PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ]) AC_SUBST(ASOUNDLIB_CFLAGS) AC_SUBST(ASOUNDLIB_LIBS) +PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ]) +AC_SUBST(GLIB20_CFLAGS) +AC_SUBST(GLIB20_LIBS) + # If using GCC specifiy some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -Wall -W -Wno-unused-parameter" diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 0af99110f..c0be8ce08 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -71,7 +71,8 @@ pkglib_LTLIBRARIES=libiochannel.la \ lib_LTLIBRARIES=libpolyp.la \ libpolyp-simple.la \ libpolyp-error.la \ - libpolyp-mainloop.la + libpolyp-mainloop.la \ + libpolyp-mainloop-glib.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -307,6 +308,10 @@ parec_simple_SOURCES = parec-simple.c parec_simple_LDADD = $(AM_LDADD) libpolyp-simple.la libpolyp-error.la parec_simple_CFLAGS = $(AM_CFLAGS) +libpolyp_mainloop_glib_la_SOURCES = glib-mainloop.h glib-mainloop.c +libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) +libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB20_LIBS) + if BUILD_LIBPOLYPCORE pkginclude_HEADERS+=cli-command.h\ diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index 43562378d..70e2e0725 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -59,26 +59,26 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint return ret; } -int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, void ***io_sources, unsigned *n_io_sources, void (*cb)(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata) { +int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) { unsigned i; struct pollfd *pfds, *ppfd; - void **ios; - assert(pcm_handle && m && io_sources && n_io_sources && cb); + struct pa_io_event **ios; + assert(pcm_handle && m && io_events && n_io_events && cb); - *n_io_sources = snd_pcm_poll_descriptors_count(pcm_handle); + *n_io_events = snd_pcm_poll_descriptors_count(pcm_handle); - pfds = pa_xmalloc(sizeof(struct pollfd) * *n_io_sources); - if (snd_pcm_poll_descriptors(pcm_handle, pfds, *n_io_sources) < 0) { + pfds = pa_xmalloc(sizeof(struct pollfd) * *n_io_events); + if (snd_pcm_poll_descriptors(pcm_handle, pfds, *n_io_events) < 0) { pa_xfree(pfds); return -1; } - *io_sources = pa_xmalloc(sizeof(void*) * *n_io_sources); + *io_events = pa_xmalloc(sizeof(void*) * *n_io_events); - for (i = 0, ios = *io_sources, ppfd = pfds; i < *n_io_sources; i++, ios++, ppfd++) { - *ios = m->source_io(m, ppfd->fd, - ((ppfd->events & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | - ((ppfd->events & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), cb, userdata); + for (i = 0, ios = *io_events, ppfd = pfds; i < *n_io_events; i++, ios++, ppfd++) { + *ios = m->io_new(m, ppfd->fd, + ((ppfd->events & POLLIN) ? PA_IO_EVENT_INPUT : 0) | + ((ppfd->events & POLLOUT) ? PA_IO_EVENT_OUTPUT : 0), cb, userdata); assert(*ios); } @@ -86,12 +86,12 @@ int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, void return 0; } -void pa_free_io_sources(struct pa_mainloop_api* m, void **io_sources, unsigned n_io_sources) { +void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_events, unsigned n_io_events) { unsigned i; - void **ios; - assert(m && io_sources); + struct pa_io_event **ios; + assert(m && io_events); - for (ios = io_sources, i = 0; i < n_io_sources; i++, ios++) - m->cancel_io(m, *ios); - pa_xfree(io_sources); + for (ios = io_events, i = 0; i < n_io_events; i++, ios++) + m->io_free(*ios); + pa_xfree(io_events); } diff --git a/polyp/alsa-util.h b/polyp/alsa-util.h index 03e427d90..2627a75c9 100644 --- a/polyp/alsa-util.h +++ b/polyp/alsa-util.h @@ -29,7 +29,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *buffer_size); -int pa_create_io_sources(snd_pcm_t *pcm_handle, struct pa_mainloop_api *m, void ***io_sources, unsigned *n_io_sources, void (*cb)(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata); -void pa_free_io_sources(struct pa_mainloop_api* m, void **io_sources, unsigned n_io_sources); +int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api *m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata); +void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_sources, unsigned n_io_sources); #endif diff --git a/polyp/core.c b/polyp/core.c index ffc11cec9..0444fa967 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -62,6 +62,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->default_sample_spec.channels = 2; c->auto_unload_time = 20; + c->auto_unload_event = NULL; pa_check_for_sigpipe(); diff --git a/polyp/core.h b/polyp/core.h index b125083d7..e1e48cbcb 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -38,7 +38,7 @@ struct pa_core { struct pa_sample_spec default_sample_spec; int auto_unload_time; - void *auto_unload_mainloop_source; + struct pa_time_event *auto_unload_event; }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c new file mode 100644 index 000000000..978cad076 --- /dev/null +++ b/polyp/glib-mainloop.c @@ -0,0 +1,503 @@ +#include + +#include "glib-mainloop.h" +#include "idxset.h" +#include "xmalloc.h" + +struct pa_io_event { + GSource source; + int dead; + struct pa_glib_mainloop *mainloop; + int fd; + GPollFD pollfd; + void (*callback) (struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata); + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_io_event*e, void *userdata); + struct pa_io_event *next, *prev; +}; + +struct pa_time_event { + struct pa_glib_mainloop *mainloop; + int dead; + GSource *source; + struct timeval timeval; + void (*callback) (struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata); + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_time_event*e, void *userdata); + struct pa_time_event *next, *prev; +}; + +struct pa_defer_event { + struct pa_glib_mainloop *mainloop; + int dead; + GSource *source; + void (*callback) (struct pa_mainloop_api*m, struct pa_defer_event *e, void *userdata); + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata); + struct pa_defer_event *next, *prev; +}; + +struct pa_glib_mainloop { + GMainLoop *glib_mainloop; + struct pa_mainloop_api api; + GSource *cleanup_source; + struct pa_io_event *io_events, *dead_io_events; + struct pa_time_event *time_events, *dead_time_events; + struct pa_defer_event *defer_events, *dead_defer_events; +}; + +static void schedule_free_dead_events(struct pa_glib_mainloop *g); + +static gboolean glib_source_prepare(GSource *source, gint *timeout) { + return FALSE; +} + +static gboolean glib_source_check(GSource *source) { + struct pa_io_event *e = (struct pa_io_event*) source; + assert(e); + return !!e->pollfd.revents; +} + +static gboolean glib_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { + struct pa_io_event *e = (struct pa_io_event*) source; + assert(e); + + if (e->pollfd.revents) { + int f = + (e->pollfd.revents ? G_IO_IN : PA_IO_EVENT_INPUT) | + (e->pollfd.revents ? G_IO_OUT : PA_IO_EVENT_OUTPUT) | + (e->pollfd.revents ? G_IO_HUP : PA_IO_EVENT_HANGUP) | + (e->pollfd.revents ? G_IO_ERR : PA_IO_EVENT_ERROR); + e->pollfd.revents = 0; + + assert(e->callback); + e->callback(&e->mainloop->api, e, e->fd, f, e->userdata); + } + + return TRUE; +} + +static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f); + +static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa_io_event_flags f, void (*callback) (struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata), void *userdata) { + struct pa_io_event *e; + struct pa_glib_mainloop *g; + + GSourceFuncs io_source_funcs = { + prepare: glib_source_prepare, + check: glib_source_check, + dispatch: glib_source_dispatch, + finalize: NULL, + closure_callback: NULL, + closure_marshal : NULL, + }; + + assert(m && m->userdata && fd >= 0 && callback); + g = m->userdata; + + e = (struct pa_io_event*) g_source_new(&io_source_funcs, sizeof(struct pa_io_event)); + assert(e); + e->mainloop = m->userdata; + e->dead = 0; + e->fd = fd; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + + e->pollfd.fd = fd; + e->pollfd.events = e->pollfd.revents = 0; + + g_source_attach(&e->source, g_main_loop_get_context(g->glib_mainloop)); + + glib_io_enable(e, f); + + e->next = g->io_events; + if (e->next) e->next->prev = e; + g->io_events = e; + e->prev = NULL; + + return e; +} + +static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f) { + int o; + assert(e && !e->dead); + + o = e->pollfd.events; + e->pollfd.events = (f & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | (f & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) | G_IO_HUP | G_IO_ERR; + + if (!o && e->pollfd.events) + g_source_add_poll(&e->source, &e->pollfd); + else if (o && !e->pollfd.events) + g_source_remove_poll(&e->source, &e->pollfd); +} + +static void glib_io_free(struct pa_io_event*e) { + assert(e && !e->dead); + + g_source_destroy(&e->source); + + if (e->prev) + e->prev->next = e->next; + else + e->mainloop->io_events = e->next; + + if (e->next) + e->next->prev = e->prev; + + if ((e->next = e->mainloop->dead_io_events)) + e->next->prev = e; + + e->mainloop->dead_io_events = e; + e->prev = NULL; + + e->dead = 1; + schedule_free_dead_events(e->mainloop); +} + +static void glib_io_set_destroy(struct pa_io_event*e, void (*callback)(struct pa_mainloop_api*m, struct pa_io_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* Time sources */ + +static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv); + +static struct pa_time_event* glib_time_new(struct pa_mainloop_api*m, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*m, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { + struct pa_glib_mainloop *g; + struct pa_time_event *e; + + assert(m && m->userdata && tv && callback); + g = m->userdata; + + e = pa_xmalloc(sizeof(struct pa_time_event)); + e->mainloop = g; + e->dead = 0; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + e->source = NULL; + + glib_time_restart(e, tv); + + e->next = g->time_events; + if (e->next) e->next->prev = e; + g->time_events = e; + e->prev = NULL; + + return e; +} + +static guint msec_diff(const struct timeval *a, const struct timeval *b) { + guint r; + assert(a && b); + + if (a->tv_sec < b->tv_sec) + return 0; + + if (a->tv_sec == b->tv_sec && a->tv_sec <= b->tv_sec) + return 0; + + r = (a->tv_sec-b->tv_sec)*1000; + + if (a->tv_usec >= b->tv_usec) + r += (a->tv_usec - b->tv_usec) / 1000; + else + r -= (b->tv_usec - a->tv_usec) / 1000; + + return r; +} + +static gboolean time_cb(gpointer data) { + struct pa_time_event* e = data; + assert(e && e->mainloop && e->source); + + g_source_unref(e->source); + e->source = NULL; + + e->callback(&e->mainloop->api, e, &e->timeval, e->userdata); + return FALSE; +} + +static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) { + struct timeval now; + assert(e && e->mainloop); + + gettimeofday(&now, NULL); + if (e->source) { + g_source_destroy(e->source); + g_source_unref(e->source); + } + + if (tv) { + e->timeval = *tv; + e->source = g_timeout_source_new(msec_diff(tv, &now)); + assert(e->source); + g_source_set_callback(e->source, time_cb, e, NULL); + g_source_attach(e->source, g_main_loop_get_context(e->mainloop->glib_mainloop)); + } else + e->source = NULL; + } + +static void glib_time_free(struct pa_time_event *e) { + assert(e && e->mainloop); + + if (e->source) { + g_source_destroy(e->source); + g_source_unref(e->source); + e->source = NULL; + } + + if (e->prev) + e->prev->next = e->next; + else + e->mainloop->time_events = e->next; + + if (e->next) + e->next->prev = e->prev; + + if ((e->next = e->mainloop->dead_time_events)) + e->next->prev = e; + + e->mainloop->dead_time_events = e; + e->prev = NULL; + + e->dead = 1; + schedule_free_dead_events(e->mainloop); +} + +static void glib_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*m, struct pa_time_event*e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* Deferred sources */ + +static void glib_defer_enable(struct pa_defer_event *e, int b); + +static struct pa_defer_event* glib_defer_new(struct pa_mainloop_api*m, void (*callback) (struct pa_mainloop_api*m, struct pa_defer_event *e, void *userdata), void *userdata) { + struct pa_defer_event *e; + struct pa_glib_mainloop *g; + + assert(m && m->userdata && callback); + g = m->userdata; + + e = pa_xmalloc(sizeof(struct pa_defer_event)); + e->mainloop = g; + e->dead = 0; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + e->source = NULL; + + glib_defer_enable(e, 1); + + e->next = g->defer_events; + if (e->next) e->next->prev = e; + g->defer_events = e; + e->prev = NULL; + return e; +} + +static gboolean idle_cb(gpointer data) { + struct pa_defer_event* e = data; + assert(e && e->mainloop && e->source); + + e->callback(&e->mainloop->api, e, e->userdata); + return TRUE; +} + +static void glib_defer_enable(struct pa_defer_event *e, int b) { + assert(e && e->mainloop); + + if (e->source && !b) { + g_source_destroy(e->source); + g_source_unref(e->source); + e->source = NULL; + } else if (!e->source && b) { + e->source = g_idle_source_new(); + assert(e->source); + g_source_set_callback(e->source, idle_cb, e, NULL); + g_source_attach(e->source, g_main_loop_get_context(e->mainloop->glib_mainloop)); + g_source_set_priority(e->source, G_PRIORITY_HIGH_IDLE); + } +} + +static void glib_defer_free(struct pa_defer_event *e) { + assert(e && e->mainloop); + + if (e->source) { + g_source_destroy(e->source); + g_source_unref(e->source); + e->source = NULL; + } + + if (e->prev) + e->prev->next = e->next; + else + e->mainloop->defer_events = e->next; + + if (e->next) + e->next->prev = e->prev; + + if ((e->next = e->mainloop->dead_defer_events)) + e->next->prev = e; + + e->mainloop->dead_defer_events = e; + e->prev = NULL; + + e->dead = 1; + schedule_free_dead_events(e->mainloop); +} + +static void glib_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* quit() */ + +static void glib_quit(struct pa_mainloop_api*a, int retval) { + struct pa_glib_mainloop *g; + assert(a && a->userdata); + g = a->userdata; + + g_main_loop_quit(g->glib_mainloop); +} + +static const struct pa_mainloop_api vtable = { + userdata: NULL, + + io_new: glib_io_new, + io_enable: glib_io_enable, + io_free: glib_io_free, + io_set_destroy: glib_io_set_destroy, + + time_new : glib_time_new, + time_restart : glib_time_restart, + time_free : glib_time_free, + time_set_destroy : glib_time_set_destroy, + + defer_new : glib_defer_new, + defer_enable : glib_defer_enable, + defer_free : glib_defer_free, + defer_set_destroy : glib_defer_set_destroy, + + quit : glib_quit, +}; + +struct pa_glib_mainloop *pa_glib_mainloop_new(GMainLoop *ml) { + struct pa_glib_mainloop *g; + assert(ml); + + g = pa_xmalloc(sizeof(struct pa_glib_mainloop)); + g->glib_mainloop = g_main_loop_ref(ml); + g->api = vtable; + g->api.userdata = g; + + g->io_events = g->dead_io_events = NULL; + g->time_events = g->dead_time_events = NULL; + g->defer_events = g->dead_defer_events = NULL; + + g->cleanup_source = NULL; + return g; +} + +static void free_io_events(struct pa_io_event *e) { + while (e) { + struct pa_io_event *r = e; + e = r->next; + + if (r->pollfd.events) + g_source_remove_poll(&r->source, &r->pollfd); + + if (!r->dead) + g_source_destroy(&r->source); + + if (r->destroy_callback) + r->destroy_callback(&r->mainloop->api, r, r->userdata); + + g_source_unref(&r->source); + } +} + +static void free_time_events(struct pa_time_event *e) { + while (e) { + struct pa_time_event *r = e; + e = r->next; + + if (r->source) { + g_source_destroy(r->source); + g_source_unref(r->source); + } + + if (r->destroy_callback) + r->destroy_callback(&r->mainloop->api, r, r->userdata); + + pa_xfree(r); + } +} + +static void free_defer_events(struct pa_defer_event *e) { + while (e) { + struct pa_defer_event *r = e; + e = r->next; + + if (r->source) { + g_source_destroy(r->source); + g_source_unref(r->source); + } + + if (r->destroy_callback) + r->destroy_callback(&r->mainloop->api, r, r->userdata); + + pa_xfree(r); + } +} + +void pa_glib_mainloop_free(struct pa_glib_mainloop* g) { + assert(g); + + free_io_events(g->io_events); + free_io_events(g->dead_io_events); + free_defer_events(g->defer_events); + free_defer_events(g->dead_defer_events); + free_time_events(g->time_events); + free_time_events(g->dead_time_events); + + g_main_loop_unref(g->glib_mainloop); + pa_xfree(g); +} + +struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g) { + assert(g); + return &g->api; +} + +static gboolean free_dead_events(gpointer p) { + struct pa_glib_mainloop *g = p; + assert(g); + + free_io_events(g->dead_io_events); + free_defer_events(g->dead_defer_events); + free_time_events(g->dead_time_events); + + g_source_destroy(g->cleanup_source); + g_source_unref(g->cleanup_source); + g->cleanup_source = NULL; + + return FALSE; +} + +static void schedule_free_dead_events(struct pa_glib_mainloop *g) { + assert(g && g->glib_mainloop); + + if (g->cleanup_source) + return; + + g->cleanup_source = g_idle_source_new(); + assert(g->cleanup_source); + g_source_set_callback(g->cleanup_source, free_dead_events, g, NULL); + g_source_attach(g->cleanup_source, g_main_loop_get_context(g->glib_mainloop)); +} diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h new file mode 100644 index 000000000..50fe8b9c9 --- /dev/null +++ b/polyp/glib-mainloop.h @@ -0,0 +1,14 @@ +#ifndef fooglibmainloophfoo +#define fooglibmainloophfoo + +#include + +#include "mainloop-api.h" + +struct pa_glib_mainloop; + +struct pa_glib_mainloop *pa_glib_mainloop_new(GMainLoop *ml); +void pa_glib_mainloop_free(struct pa_glib_mainloop* g); +struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g); + +#endif diff --git a/polyp/iochannel.c b/polyp/iochannel.c index 77f8fb086..813347d42 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -46,50 +46,50 @@ struct pa_iochannel { int no_close; - void* input_source, *output_source; + struct pa_io_event* input_event, *output_event; }; static void enable_mainloop_sources(struct pa_iochannel *io) { assert(io); - if (io->input_source == io->output_source) { - enum pa_mainloop_api_io_events e = PA_MAINLOOP_API_IO_EVENT_NULL; - assert(io->input_source); + if (io->input_event == io->output_event) { + enum pa_io_event_flags f = PA_IO_EVENT_NULL; + assert(io->input_event); if (!io->readable) - e |= PA_MAINLOOP_API_IO_EVENT_INPUT; + f |= PA_IO_EVENT_INPUT; if (!io->writable) - e |= PA_MAINLOOP_API_IO_EVENT_OUTPUT; + f |= PA_IO_EVENT_OUTPUT; - io->mainloop->enable_io(io->mainloop, io->input_source, e); + io->mainloop->io_enable(io->input_event, f); } else { - if (io->input_source) - io->mainloop->enable_io(io->mainloop, io->input_source, io->readable ? PA_MAINLOOP_API_IO_EVENT_NULL : PA_MAINLOOP_API_IO_EVENT_INPUT); - if (io->output_source) - io->mainloop->enable_io(io->mainloop, io->output_source, io->writable ? PA_MAINLOOP_API_IO_EVENT_NULL : PA_MAINLOOP_API_IO_EVENT_OUTPUT); + if (io->input_event) + io->mainloop->io_enable(io->input_event, io->readable ? PA_IO_EVENT_NULL : PA_IO_EVENT_INPUT); + if (io->output_event) + io->mainloop->io_enable(io->output_event, io->writable ? PA_IO_EVENT_NULL : PA_IO_EVENT_OUTPUT); } } -static void callback(struct pa_mainloop_api* m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void callback(struct pa_mainloop_api* m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct pa_iochannel *io = userdata; int changed = 0; - assert(m && fd >= 0 && events && userdata); + assert(m && e && fd >= 0 && userdata); - if ((events & PA_MAINLOOP_API_IO_EVENT_HUP) && !io->hungup) { + if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) { io->hungup = 1; changed = 1; } - if ((events & PA_MAINLOOP_API_IO_EVENT_INPUT) && !io->readable) { + if ((f & PA_IO_EVENT_INPUT) && !io->readable) { io->readable = 1; changed = 1; - assert(id == io->input_source); + assert(e == io->input_event); } - if ((events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) && !io->writable) { + if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) { io->writable = 1; changed = 1; - assert(id == io->output_source); + assert(e == io->output_event); } if (changed) { @@ -116,23 +116,23 @@ struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd io->hungup = 0; io->no_close = 0; + io->input_event = io->output_event = NULL; + if (ifd == ofd) { assert(ifd >= 0); pa_make_nonblock_fd(io->ifd); - io->input_source = io->output_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_BOTH, callback, io); + io->input_event = io->output_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT|PA_IO_EVENT_OUTPUT, callback, io); } else { if (ifd >= 0) { pa_make_nonblock_fd(io->ifd); - io->input_source = m->source_io(m, ifd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, io); - } else - io->input_source = NULL; + io->input_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT, callback, io); + } if (ofd >= 0) { pa_make_nonblock_fd(io->ofd); - io->output_source = m->source_io(m, ofd, PA_MAINLOOP_API_IO_EVENT_OUTPUT, callback, io); - } else - io->output_source = NULL; + io->output_event = m->io_new(m, ofd, PA_IO_EVENT_OUTPUT, callback, io); + } } return io; @@ -141,17 +141,17 @@ struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd void pa_iochannel_free(struct pa_iochannel*io) { assert(io); + if (io->input_event) + io->mainloop->io_free(io->input_event); + if (io->output_event && (io->output_event != io->input_event)) + io->mainloop->io_free(io->output_event); + if (!io->no_close) { if (io->ifd >= 0) close(io->ifd); if (io->ofd >= 0 && io->ofd != io->ifd) close(io->ofd); } - - if (io->input_source) - io->mainloop->cancel_io(io->mainloop, io->input_source); - if (io->output_source && (io->output_source != io->input_source)) - io->mainloop->cancel_io(io->mainloop, io->output_source); pa_xfree(io); } diff --git a/polyp/main.c b/polyp/main.c index de66f1c88..9f3d34063 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -46,13 +46,12 @@ static struct pa_mainloop *mainloop; -static void exit_signal_callback(void *id, int sig, void *userdata) { - struct pa_mainloop_api* m = pa_mainloop_get_api(mainloop); +static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { m->quit(m, 1); fprintf(stderr, __FILE__": got signal.\n"); } -static void aux_signal_callback(void *id, int sig, void *userdata) { +static void aux_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { struct pa_core *c = userdata; assert(c); pa_module_load(c, sig == SIGUSR1 ? "module-cli" : "module-cli-protocol-unix", NULL); @@ -135,14 +134,14 @@ int main(int argc, char *argv[]) { r = pa_signal_init(pa_mainloop_get_api(mainloop)); assert(r == 0); - pa_signal_register(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGINT, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); - pa_signal_register(SIGUSR1, aux_signal_callback, c); - pa_signal_register(SIGUSR2, aux_signal_callback, c); + pa_signal_new(SIGUSR1, aux_signal_callback, c); + pa_signal_new(SIGUSR2, aux_signal_callback, c); buf = pa_strbuf_new(); assert(buf); diff --git a/polyp/mainloop-api.c b/polyp/mainloop-api.c index 8b4e09ac5..952fce0a1 100644 --- a/polyp/mainloop-api.c +++ b/polyp/mainloop-api.c @@ -30,32 +30,38 @@ #include "xmalloc.h" struct once_info { - void (*callback)(void *userdata); + void (*callback)(struct pa_mainloop_api*m, void *userdata); void *userdata; }; -static void once_callback(struct pa_mainloop_api *api, void *id, void *userdata) { +static void once_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { struct once_info *i = userdata; - assert(api && i && i->callback); - i->callback(i->userdata); - assert(api->cancel_fixed); - api->cancel_fixed(api, id); + assert(m && i && i->callback); + + i->callback(m, i->userdata); + + assert(m->defer_free); + m->defer_free(e); +} + +static void free_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { + struct once_info *i = userdata; + assert(m && i); pa_xfree(i); } -void pa_mainloop_api_once(struct pa_mainloop_api* api, void (*callback)(void *userdata), void *userdata) { +void pa_mainloop_api_once(struct pa_mainloop_api* m, void (*callback)(struct pa_mainloop_api *m, void *userdata), void *userdata) { struct once_info *i; - void *id; - assert(api && callback); + struct pa_defer_event *e; + assert(m && callback); i = pa_xmalloc(sizeof(struct once_info)); i->callback = callback; i->userdata = userdata; - assert(api->source_fixed); - id = api->source_fixed(api, once_callback, i); - assert(id); - - /* Note: if the mainloop is destroyed before once_callback() was called, some memory is leaked. */ + assert(m->defer_new); + e = m->defer_new(m, once_callback, i); + assert(e); + m->defer_set_destroy(e, free_callback); } diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index 0228f580c..4c8e379ba 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -25,41 +25,43 @@ #include #include -enum pa_mainloop_api_io_events { - PA_MAINLOOP_API_IO_EVENT_NULL = 0, - PA_MAINLOOP_API_IO_EVENT_INPUT = 1, - PA_MAINLOOP_API_IO_EVENT_OUTPUT = 2, - PA_MAINLOOP_API_IO_EVENT_BOTH = 3, - PA_MAINLOOP_API_IO_EVENT_HUP = 4 +enum pa_io_event_flags { + PA_IO_EVENT_NULL = 0, + PA_IO_EVENT_INPUT = 1, + PA_IO_EVENT_OUTPUT = 2, + PA_IO_EVENT_HANGUP = 4, + PA_IO_EVENT_ERROR = 8, }; +struct pa_io_event; +struct pa_defer_event; +struct pa_time_event; + struct pa_mainloop_api { void *userdata; /* IO sources */ - void* (*source_io)(struct pa_mainloop_api*a, int fd, enum pa_mainloop_api_io_events events, void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata); - void (*enable_io)(struct pa_mainloop_api*a, void* id, enum pa_mainloop_api_io_events events); - void (*cancel_io)(struct pa_mainloop_api*a, void* id); + struct pa_io_event* (*io_new)(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event* e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata); + void (*io_enable)(struct pa_io_event* e, enum pa_io_event_flags events); + void (*io_free)(struct pa_io_event* e); + void (*io_set_destroy)(struct pa_io_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata)); - /* Fixed sources */ - void* (*source_fixed)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata); - void (*enable_fixed)(struct pa_mainloop_api*a, void* id, int b); - void (*cancel_fixed)(struct pa_mainloop_api*a, void* id); - - /* Idle sources */ - void* (*source_idle)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata); - void (*enable_idle)(struct pa_mainloop_api*a, void* id, int b); - void (*cancel_idle)(struct pa_mainloop_api*a, void* id); - /* Time sources */ - void* (*source_time)(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, void *id, const struct timeval *tv, void *userdata), void *userdata); - void (*enable_time)(struct pa_mainloop_api*a, void *id, const struct timeval *tv); - void (*cancel_time)(struct pa_mainloop_api*a, void* id); + struct pa_time_event* (*time_new)(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event* e, const struct timeval *tv, void *userdata), void *userdata); + void (*time_restart)(struct pa_time_event* e, const struct timeval *tv); + void (*time_free)(struct pa_time_event* e); + void (*time_set_destroy)(struct pa_time_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)); + + /* Deferred sources */ + struct pa_defer_event* (*defer_new)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event* e, void *userdata), void *userdata); + void (*defer_enable)(struct pa_defer_event* e, int b); + void (*defer_free)(struct pa_defer_event* e); + void (*defer_set_destroy)(struct pa_defer_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)); /* Exit mainloop */ void (*quit)(struct pa_mainloop_api*a, int retval); }; -void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(void *userdata), void *userdata); +void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(struct pa_mainloop_api*m, void *userdata), void *userdata); #endif diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c index 6e79767a9..f7ff7e93b 100644 --- a/polyp/mainloop-signal.c +++ b/polyp/mainloop-signal.c @@ -35,30 +35,31 @@ #include "util.h" #include "xmalloc.h" -struct signal_info { +struct pa_signal_event { int sig; struct sigaction saved_sigaction; - void (*callback) (void *id, int signal, void *userdata); + void (*callback) (struct pa_mainloop_api*a, struct pa_signal_event *e, int signal, void *userdata); void *userdata; - struct signal_info *previous, *next; + void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_signal_event*e, void *userdata); + struct pa_signal_event *previous, *next; }; static struct pa_mainloop_api *api = NULL; static int signal_pipe[2] = { -1, -1 }; -static void* mainloop_source = NULL; -static struct signal_info *signals = NULL; +static struct pa_io_event* io_event = NULL; +static struct pa_signal_event *signals = NULL; static void signal_handler(int sig) { write(signal_pipe[1], &sig, sizeof(sig)); } -static void callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { - assert(a && id && events == PA_MAINLOOP_API_IO_EVENT_INPUT && id == mainloop_source && fd == signal_pipe[0]); +static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) { + assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); for (;;) { ssize_t r; int sig; - struct signal_info*s; + struct pa_signal_event*s; if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { if (errno == EAGAIN) @@ -76,14 +77,15 @@ static void callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloo for (s = signals; s; s = s->next) if (s->sig == sig) { assert(s->callback); - s->callback(s, sig, s->userdata); + s->callback(a, s, sig, s->userdata); break; } } } int pa_signal_init(struct pa_mainloop_api *a) { - assert(a); + assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event); + if (pipe(signal_pipe) < 0) { fprintf(stderr, "pipe() failed: %s\n", strerror(errno)); return -1; @@ -93,71 +95,80 @@ int pa_signal_init(struct pa_mainloop_api *a) { pa_make_nonblock_fd(signal_pipe[1]); api = a; - mainloop_source = api->source_io(api, signal_pipe[0], PA_MAINLOOP_API_IO_EVENT_INPUT, callback, NULL); - assert(mainloop_source); + io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL); + assert(io_event); return 0; } void pa_signal_done(void) { - assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && mainloop_source); + assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && io_event); - api->cancel_io(api, mainloop_source); - mainloop_source = NULL; + while (signals) + pa_signal_free(signals); + + api->io_free(io_event); + io_event = NULL; close(signal_pipe[0]); close(signal_pipe[1]); signal_pipe[0] = signal_pipe[1] = -1; - while (signals) - pa_signal_unregister(signals); - api = NULL; } -void* pa_signal_register(int sig, void (*callback) (void *id, int signal, void *userdata), void *userdata) { - struct signal_info *s = NULL; +struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int sig, void *userdata), void *userdata) { + struct pa_signal_event *e = NULL; struct sigaction sa; assert(sig > 0 && callback); - - for (s = signals; s; s = s->next) - if (s->sig == sig) + + for (e = signals; e; e = e->next) + if (e->sig == sig) goto fail; - s = pa_xmalloc(sizeof(struct signal_info)); - s->sig = sig; - s->callback = callback; - s->userdata = userdata; + e = pa_xmalloc(sizeof(struct pa_signal_event)); + e->sig = sig; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - if (sigaction(sig, &sa, &s->saved_sigaction) < 0) + if (sigaction(sig, &sa, &e->saved_sigaction) < 0) goto fail; - s->previous = NULL; - s->next = signals; - signals = s; + e->previous = NULL; + e->next = signals; + signals = e; - return s; + return e; fail: - if (s) - pa_xfree(s); + if (e) + pa_xfree(e); return NULL; } -void pa_signal_unregister(void *id) { - struct signal_info *s = id; - assert(s); +void pa_signal_free(struct pa_signal_event *e) { + assert(e); - if (s->next) - s->next->previous = s->previous; - if (s->previous) - s->previous->next = s->next; + if (e->next) + e->next->previous = e->previous; + if (e->previous) + e->previous->next = e->next; else - signals = s->next; + signals = e->next; - sigaction(s->sig, &s->saved_sigaction, NULL); - pa_xfree(s); + sigaction(e->sig, &e->saved_sigaction, NULL); + + if (e->destroy_callback) + e->destroy_callback(api, e, e->userdata); + + pa_xfree(e); +} + +void pa_signal_set_destroy(struct pa_signal_event *e, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, void *userdata)) { + assert(e); + e->destroy_callback = callback; } diff --git a/polyp/mainloop-signal.h b/polyp/mainloop-signal.h index 8afe9c8d1..dacbc1534 100644 --- a/polyp/mainloop-signal.h +++ b/polyp/mainloop-signal.h @@ -27,7 +27,11 @@ int pa_signal_init(struct pa_mainloop_api *api); void pa_signal_done(void); -void* pa_signal_register(int signal, void (*callback) (void *id, int signal, void *userdata), void *userdata); -void pa_signal_unregister(void *id); +struct pa_signal_event; + +struct pa_signal_event* pa_signal_new(int signal, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int signal, void *userdata), void *userdata); +void pa_signal_free(struct pa_signal_event *e); + +void pa_signal_set_destroy(struct pa_signal_event *e, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, void *userdata)); #endif diff --git a/polyp/mainloop.c b/polyp/mainloop.c index f3d8e781b..c678537eb 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -38,42 +38,42 @@ #include "idxset.h" #include "xmalloc.h" -struct mainloop_source_header { +struct pa_base_event { +}; + +struct pa_io_event { struct pa_mainloop *mainloop; int dead; -}; - -struct mainloop_source_io { - struct mainloop_source_header header; - int fd; - enum pa_mainloop_api_io_events events; - void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata); - void *userdata; - + enum pa_io_event_flags events; + void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata); struct pollfd *pollfd; -}; - -struct mainloop_source_fixed_or_idle { - struct mainloop_source_header header; - int enabled; - - void (*callback)(struct pa_mainloop_api*a, void *id, void *userdata); void *userdata; + void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata); }; -struct mainloop_source_time { - struct mainloop_source_header header; +struct pa_time_event { + struct pa_mainloop *mainloop; + int dead; int enabled; - struct timeval timeval; - void (*callback)(struct pa_mainloop_api*a, void *id, const struct timeval*tv, void *userdata); + void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval*tv, void *userdata); void *userdata; + void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata); +}; + +struct pa_defer_event { + struct pa_mainloop *mainloop; + int dead; + int enabled; + void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata); + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata); }; struct pa_mainloop { - struct pa_idxset *io_sources, *fixed_sources, *idle_sources, *time_sources; - int io_sources_scan_dead, fixed_sources_scan_dead, idle_sources_scan_dead, time_sources_scan_dead; + struct pa_idxset *io_events, *time_events, *defer_events; + int io_events_scan_dead, defer_events_scan_dead, time_events_scan_dead; struct pollfd *pollfds; unsigned max_pollfds, n_pollfds; @@ -83,57 +83,248 @@ struct pa_mainloop { struct pa_mainloop_api api; }; -static void setup_api(struct pa_mainloop *m); +/* IO events */ +static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) { + struct pa_mainloop *m; + struct pa_io_event *e; + + assert(a && a->userdata && fd >= 0 && callback); + m = a->userdata; + assert(a == &m->api); + + e = pa_xmalloc(sizeof(struct pa_io_event)); + e->mainloop = m; + e->dead = 0; + + e->fd = fd; + e->events = events; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + e->pollfd = NULL; + + pa_idxset_put(m->io_events, e, NULL); + m->rebuild_pollfds = 1; + return e; +} + +static void mainloop_io_enable(struct pa_io_event *e, enum pa_io_event_flags events) { + assert(e && e->mainloop); + + e->events = events; + if (e->pollfd) + e->pollfd->events = + (events & PA_IO_EVENT_INPUT ? POLLIN : 0) | + (events & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | + POLLHUP | + POLLERR; +} + +static void mainloop_io_free(struct pa_io_event *e) { + assert(e && e->mainloop); + e->dead = e->mainloop->io_events_scan_dead = e->mainloop->rebuild_pollfds = 1; +} + +static void mainloop_io_set_destroy(struct pa_io_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* Defer events */ +struct pa_defer_event* mainloop_defer_new(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata), void *userdata) { + struct pa_mainloop *m; + struct pa_defer_event *e; + + assert(a && a->userdata && callback); + m = a->userdata; + assert(a == &m->api); + + e = pa_xmalloc(sizeof(struct pa_defer_event)); + e->mainloop = m; + e->dead = 0; + + e->enabled = 1; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + + pa_idxset_put(m->defer_events, e, NULL); + return e; +} + +static void mainloop_defer_enable(struct pa_defer_event *e, int b) { + assert(e); + e->enabled = b; +} + +static void mainloop_defer_free(struct pa_defer_event *e) { + assert(e); + e->dead = e->mainloop->defer_events_scan_dead = 1; +} + +static void mainloop_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* Time events */ +static struct pa_time_event* mainloop_time_new(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { + struct pa_mainloop *m; + struct pa_time_event *e; + + assert(a && a->userdata && callback); + m = a->userdata; + assert(a == &m->api); + + e = pa_xmalloc(sizeof(struct pa_time_event)); + e->mainloop = m; + e->dead = 0; + + e->enabled = !!tv; + if (tv) + e->timeval = *tv; + + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + + pa_idxset_put(m->time_events, e, NULL); + return e; +} + +static void mainloop_time_restart(struct pa_time_event *e, const struct timeval *tv) { + assert(e); + + if (tv) { + e->enabled = 1; + e->timeval = *tv; + } else + e->enabled = 0; +} + +static void mainloop_time_free(struct pa_time_event *e) { + assert(e); + e->dead = e->mainloop->time_events_scan_dead = 1; +} + +static void mainloop_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* quit() */ + +static void mainloop_quit(struct pa_mainloop_api*a, int retval) { + struct pa_mainloop *m; + assert(a && a->userdata); + m = a->userdata; + assert(a == &m->api); + + m->quit = 1; + m->retval = retval; +} + +static const struct pa_mainloop_api vtable = { + userdata: NULL, + + io_new: mainloop_io_new, + io_enable: mainloop_io_enable, + io_free: mainloop_io_free, + io_set_destroy: mainloop_io_set_destroy, + + time_new : mainloop_time_new, + time_restart : mainloop_time_restart, + time_free : mainloop_time_free, + time_set_destroy : mainloop_time_set_destroy, + + defer_new : mainloop_defer_new, + defer_enable : mainloop_defer_enable, + defer_free : mainloop_defer_free, + defer_set_destroy : mainloop_defer_set_destroy, + + quit : mainloop_quit, +}; struct pa_mainloop *pa_mainloop_new(void) { struct pa_mainloop *m; m = pa_xmalloc(sizeof(struct pa_mainloop)); - m->io_sources = pa_idxset_new(NULL, NULL); - m->fixed_sources = pa_idxset_new(NULL, NULL); - m->idle_sources = pa_idxset_new(NULL, NULL); - m->time_sources = pa_idxset_new(NULL, NULL); + m->io_events = pa_idxset_new(NULL, NULL); + m->defer_events = pa_idxset_new(NULL, NULL); + m->time_events = pa_idxset_new(NULL, NULL); - assert(m->io_sources && m->fixed_sources && m->idle_sources && m->time_sources); + assert(m->io_events && m->defer_events && m->time_events); - m->io_sources_scan_dead = m->fixed_sources_scan_dead = m->idle_sources_scan_dead = m->time_sources_scan_dead = 0; + m->io_events_scan_dead = m->defer_events_scan_dead = m->time_events_scan_dead = 0; m->pollfds = NULL; m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0; m->quit = m->running = m->retval = 0; - setup_api(m); + m->api = vtable; + m->api.userdata = m; return m; } -static int foreach(void *p, uint32_t index, int *del, void*userdata) { - struct mainloop_source_header *h = p; +static int io_foreach(void *p, uint32_t index, int *del, void*userdata) { + struct pa_io_event *e = p; int *all = userdata; - assert(p && del && all); + assert(e && del && all); - if (*all || h->dead) { - pa_xfree(h); - *del = 1; - } + if (!*all || !e->dead) + return 0; + + if (e->destroy_callback) + e->destroy_callback(&e->mainloop->api, e, e->userdata); + pa_xfree(e); + *del = 1; + return 0; +}; +static int time_foreach(void *p, uint32_t index, int *del, void*userdata) { + struct pa_time_event *e = p; + int *all = userdata; + assert(e && del && all); + + if (!*all || !e->dead) + return 0; + + if (e->destroy_callback) + e->destroy_callback(&e->mainloop->api, e, e->userdata); + pa_xfree(e); + *del = 1; + return 0; +}; + +static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) { + struct pa_defer_event *e = p; + int *all = userdata; + assert(e && del && all); + + if (!*all || !e->dead) + return 0; + + if (e->destroy_callback) + e->destroy_callback(&e->mainloop->api, e, e->userdata); + pa_xfree(e); + *del = 1; return 0; }; void pa_mainloop_free(struct pa_mainloop* m) { int all = 1; assert(m); - pa_idxset_foreach(m->io_sources, foreach, &all); - pa_idxset_foreach(m->fixed_sources, foreach, &all); - pa_idxset_foreach(m->idle_sources, foreach, &all); - pa_idxset_foreach(m->time_sources, foreach, &all); - pa_idxset_free(m->io_sources, NULL, NULL); - pa_idxset_free(m->fixed_sources, NULL, NULL); - pa_idxset_free(m->idle_sources, NULL, NULL); - pa_idxset_free(m->time_sources, NULL, NULL); + pa_idxset_foreach(m->io_events, io_foreach, &all); + pa_idxset_foreach(m->time_events, time_foreach, &all); + pa_idxset_foreach(m->defer_events, defer_foreach, &all); + + pa_idxset_free(m->io_events, NULL, NULL); + pa_idxset_free(m->time_events, NULL, NULL); + pa_idxset_free(m->defer_events, NULL, NULL); pa_xfree(m->pollfds); pa_xfree(m); @@ -142,23 +333,21 @@ void pa_mainloop_free(struct pa_mainloop* m) { static void scan_dead(struct pa_mainloop *m) { int all = 0; assert(m); - if (m->io_sources_scan_dead) - pa_idxset_foreach(m->io_sources, foreach, &all); - if (m->fixed_sources_scan_dead) - pa_idxset_foreach(m->fixed_sources, foreach, &all); - if (m->idle_sources_scan_dead) - pa_idxset_foreach(m->idle_sources, foreach, &all); - if (m->time_sources_scan_dead) - pa_idxset_foreach(m->time_sources, foreach, &all); + if (m->io_events_scan_dead) + pa_idxset_foreach(m->io_events, io_foreach, &all); + if (m->time_events_scan_dead) + pa_idxset_foreach(m->time_events, time_foreach, &all); + if (m->defer_events_scan_dead) + pa_idxset_foreach(m->defer_events, defer_foreach, &all); } static void rebuild_pollfds(struct pa_mainloop *m) { - struct mainloop_source_io*s; + struct pa_io_event*e; struct pollfd *p; uint32_t index = PA_IDXSET_INVALID; unsigned l; - l = pa_idxset_ncontents(m->io_sources); + l = pa_idxset_ncontents(m->io_events); if (m->max_pollfds < l) { m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l); m->max_pollfds = l; @@ -166,15 +355,19 @@ static void rebuild_pollfds(struct pa_mainloop *m) { m->n_pollfds = 0; p = m->pollfds; - for (s = pa_idxset_first(m->io_sources, &index); s; s = pa_idxset_next(m->io_sources, &index)) { - if (s->header.dead) { - s->pollfd = NULL; + for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) { + if (e->dead) { + e->pollfd = NULL; continue; } - s->pollfd = p; - p->fd = s->fd; - p->events = ((s->events & PA_MAINLOOP_API_IO_EVENT_INPUT) ? POLLIN : 0) | ((s->events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) ? POLLOUT : 0); + e->pollfd = p; + p->fd = e->fd; + p->events = + ((e->events & PA_IO_EVENT_INPUT) ? POLLIN : 0) | + ((e->events & PA_IO_EVENT_OUTPUT) ? POLLOUT : 0) | + POLLHUP | + POLLERR; p->revents = 0; p++; @@ -184,60 +377,62 @@ static void rebuild_pollfds(struct pa_mainloop *m) { static void dispatch_pollfds(struct pa_mainloop *m) { uint32_t index = PA_IDXSET_INVALID; - struct mainloop_source_io *s; + struct pa_io_event *e; - for (s = pa_idxset_first(m->io_sources, &index); s; s = pa_idxset_next(m->io_sources, &index)) { - if (s->header.dead || !s->pollfd || !s->pollfd->revents) + for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) { + if (e->dead || !e->pollfd || !e->pollfd->revents) continue; - assert(s->pollfd->fd == s->fd && s->callback); - s->callback(&m->api, s, s->fd, - ((s->pollfd->revents & POLLHUP) ? PA_MAINLOOP_API_IO_EVENT_HUP : 0) | - ((s->pollfd->revents & POLLIN) ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | - ((s->pollfd->revents & POLLOUT) ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), s->userdata); - s->pollfd->revents = 0; + assert(e->pollfd->fd == e->fd && e->callback); + e->callback(&m->api, e, e->fd, + (e->pollfd->revents & POLLHUP ? PA_IO_EVENT_HANGUP : 0) | + (e->pollfd->revents & POLLIN ? PA_IO_EVENT_INPUT : 0) | + (e->pollfd->revents & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) | + (e->pollfd->revents & POLLERR ? PA_IO_EVENT_ERROR : 0), + e->userdata); + e->pollfd->revents = 0; } } -static void run_fixed_or_idle(struct pa_mainloop *m, struct pa_idxset *i) { - uint32_t index = PA_IDXSET_INVALID; - struct mainloop_source_fixed_or_idle *s; +static void dispatch_defer(struct pa_mainloop *m) { + uint32_t index; + struct pa_defer_event *e; - for (s = pa_idxset_first(i, &index); s; s = pa_idxset_next(i, &index)) { - if (s->header.dead || !s->enabled) + for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) { + if (e->dead || !e->enabled) continue; - assert(s->callback); - s->callback(&m->api, s, s->userdata); + assert(e->callback); + e->callback(&m->api, e, e->userdata); } } static int calc_next_timeout(struct pa_mainloop *m) { - uint32_t index = PA_IDXSET_INVALID; - struct mainloop_source_time *s; + uint32_t index; + struct pa_time_event *e; struct timeval now; int t = -1; - if (pa_idxset_isempty(m->time_sources)) + if (pa_idxset_isempty(m->time_events)) return -1; gettimeofday(&now, NULL); - for (s = pa_idxset_first(m->time_sources, &index); s; s = pa_idxset_next(m->time_sources, &index)) { + for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { int tmp; - if (s->header.dead || !s->enabled) + if (e->dead || !e->enabled) continue; - if (s->timeval.tv_sec < now.tv_sec || (s->timeval.tv_sec == now.tv_sec && s->timeval.tv_usec <= now.tv_usec)) + if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) return 0; - tmp = (s->timeval.tv_sec - now.tv_sec)*1000; + tmp = (e->timeval.tv_sec - now.tv_sec)*1000; - if (s->timeval.tv_usec > now.tv_usec) - tmp += (s->timeval.tv_usec - now.tv_usec)/1000; + if (e->timeval.tv_usec > now.tv_usec) + tmp += (e->timeval.tv_usec - now.tv_usec)/1000; else - tmp -= (now.tv_usec - s->timeval.tv_usec)/1000; + tmp -= (now.tv_usec - e->timeval.tv_usec)/1000; if (tmp == 0) return 0; @@ -249,43 +444,31 @@ static int calc_next_timeout(struct pa_mainloop *m) { } static void dispatch_timeout(struct pa_mainloop *m) { - uint32_t index = PA_IDXSET_INVALID; - struct mainloop_source_time *s; + uint32_t index; + struct pa_time_event *e; struct timeval now; assert(m); - if (pa_idxset_isempty(m->time_sources)) + if (pa_idxset_isempty(m->time_events)) return; gettimeofday(&now, NULL); - for (s = pa_idxset_first(m->time_sources, &index); s; s = pa_idxset_next(m->time_sources, &index)) { + for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { - if (s->header.dead || !s->enabled) + if (e->dead || !e->enabled) continue; - if (s->timeval.tv_sec < now.tv_sec || (s->timeval.tv_sec == now.tv_sec && s->timeval.tv_usec <= now.tv_usec)) { - assert(s->callback); + if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) { + assert(e->callback); - s->enabled = 0; - s->callback(&m->api, s, &s->timeval, s->userdata); + e->enabled = 0; + e->callback(&m->api, e, &e->timeval, e->userdata); } } } -static int any_idle_sources(struct pa_mainloop *m) { - struct mainloop_source_fixed_or_idle *s; - uint32_t index; - assert(m); - - for (s = pa_idxset_first(m->idle_sources, &index); s; s = pa_idxset_next(m->idle_sources, &index)) - if (!s->header.dead && s->enabled) - return 1; - - return 0; -} - int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { - int r, idle; + int r; assert(m && !m->running); if(m->quit) { @@ -297,23 +480,16 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { m->running = 1; scan_dead(m); - run_fixed_or_idle(m, m->fixed_sources); + dispatch_defer(m); if (m->rebuild_pollfds) { rebuild_pollfds(m); m->rebuild_pollfds = 0; } - idle = any_idle_sources(m); - do { - int t; - - if (!block || idle) - t = 0; - else - t = calc_next_timeout(m); - + int t = block ? calc_next_timeout(m) : 0; + /*fprintf(stderr, "%u\n", t);*/ r = poll(m->pollfds, m->n_pollfds, t); } while (r < 0 && errno == EINTR); @@ -321,8 +497,6 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { if (r > 0) dispatch_pollfds(m); - else if (r == 0 && idle) - run_fixed_or_idle(m, m->idle_sources); else if (r < 0) fprintf(stderr, "select(): %s\n", strerror(errno)); @@ -341,209 +515,7 @@ void pa_mainloop_quit(struct pa_mainloop *m, int r) { m->quit = r; } -/* IO sources */ -static void* mainloop_source_io(struct pa_mainloop_api*a, int fd, enum pa_mainloop_api_io_events events, void (*callback) (struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct mainloop_source_io *s; - assert(a && a->userdata && fd >= 0 && callback); - m = a->userdata; - assert(a == &m->api); - - s = pa_xmalloc(sizeof(struct mainloop_source_io)); - s->header.mainloop = m; - s->header.dead = 0; - - s->fd = fd; - s->events = events; - s->callback = callback; - s->userdata = userdata; - s->pollfd = NULL; - - pa_idxset_put(m->io_sources, s, NULL); - m->rebuild_pollfds = 1; - return s; -} - -static void mainloop_enable_io(struct pa_mainloop_api*a, void* id, enum pa_mainloop_api_io_events events) { - struct pa_mainloop *m; - struct mainloop_source_io *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api && s->header.mainloop == m); - - s->events = events; - if (s->pollfd) - s->pollfd->events = ((s->events & PA_MAINLOOP_API_IO_EVENT_INPUT) ? POLLIN : 0) | ((s->events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) ? POLLOUT : 0); -} - -static void mainloop_cancel_io(struct pa_mainloop_api*a, void* id) { - struct pa_mainloop *m; - struct mainloop_source_io *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api && s->header.mainloop == m); - - s->header.dead = 1; - m->io_sources_scan_dead = 1; - m->rebuild_pollfds = 1; -} - -/* Fixed sources */ -static void* mainloop_source_fixed(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct mainloop_source_fixed_or_idle *s; - assert(a && a->userdata && callback); - m = a->userdata; - assert(a == &m->api); - - s = pa_xmalloc(sizeof(struct mainloop_source_fixed_or_idle)); - s->header.mainloop = m; - s->header.dead = 0; - - s->enabled = 1; - s->callback = callback; - s->userdata = userdata; - - pa_idxset_put(m->fixed_sources, s, NULL); - return s; -} - -static void mainloop_enable_fixed(struct pa_mainloop_api*a, void* id, int b) { - struct pa_mainloop *m; - struct mainloop_source_fixed_or_idle *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api); - - s->enabled = b; -} - -static void mainloop_cancel_fixed(struct pa_mainloop_api*a, void* id) { - struct pa_mainloop *m; - struct mainloop_source_fixed_or_idle *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api); - - s->header.dead = 1; - m->fixed_sources_scan_dead = 1; -} - -/* Idle sources */ -static void* mainloop_source_idle(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, void *id, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct mainloop_source_fixed_or_idle *s; - assert(a && a->userdata && callback); - m = a->userdata; - assert(a == &m->api); - - s = pa_xmalloc(sizeof(struct mainloop_source_fixed_or_idle)); - s->header.mainloop = m; - s->header.dead = 0; - - s->enabled = 1; - s->callback = callback; - s->userdata = userdata; - - pa_idxset_put(m->idle_sources, s, NULL); - return s; -} - -static void mainloop_cancel_idle(struct pa_mainloop_api*a, void* id) { - struct pa_mainloop *m; - struct mainloop_source_fixed_or_idle *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api); - - s->header.dead = 1; - m->idle_sources_scan_dead = 1; -} - -/* Time sources */ -static void* mainloop_source_time(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, void *id, const struct timeval *tv, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct mainloop_source_time *s; - assert(a && a->userdata && callback); - m = a->userdata; - assert(a == &m->api); - - s = pa_xmalloc(sizeof(struct mainloop_source_time)); - s->header.mainloop = m; - s->header.dead = 0; - - s->enabled = !!tv; - if (tv) - s->timeval = *tv; - - s->callback = callback; - s->userdata = userdata; - - pa_idxset_put(m->time_sources, s, NULL); - return s; -} - -static void mainloop_enable_time(struct pa_mainloop_api*a, void *id, const struct timeval *tv) { - struct pa_mainloop *m; - struct mainloop_source_time *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api); - - if (tv) { - s->enabled = 1; - s->timeval = *tv; - } else - s->enabled = 0; -} - -static void mainloop_cancel_time(struct pa_mainloop_api*a, void* id) { - struct pa_mainloop *m; - struct mainloop_source_time *s = id; - assert(a && a->userdata && s && !s->header.dead); - m = a->userdata; - assert(a == &m->api); - - s->header.dead = 1; - m->time_sources_scan_dead = 1; - -} - -static void mainloop_quit(struct pa_mainloop_api*a, int retval) { - struct pa_mainloop *m; - assert(a && a->userdata); - m = a->userdata; - assert(a == &m->api); - - m->quit = 1; - m->retval = retval; -} - -static void setup_api(struct pa_mainloop *m) { - assert(m); - - m->api.userdata = m; - m->api.source_io = mainloop_source_io; - m->api.enable_io = mainloop_enable_io; - m->api.cancel_io = mainloop_cancel_io; - - m->api.source_fixed = mainloop_source_fixed; - m->api.enable_fixed = mainloop_enable_fixed; - m->api.cancel_fixed = mainloop_cancel_fixed; - - m->api.source_idle = mainloop_source_idle; - m->api.enable_idle = mainloop_enable_fixed; /* (!) */ - m->api.cancel_idle = mainloop_cancel_idle; - - m->api.source_time = mainloop_source_time; - m->api.enable_time = mainloop_enable_time; - m->api.cancel_time = mainloop_cancel_time; - - m->api.quit = mainloop_quit; -} - struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m) { assert(m); return &m->api; } - diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index a0fa52db1..5b4a7b732 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -42,8 +42,8 @@ struct userdata { snd_pcm_t *pcm_handle; struct pa_sink *sink; - void **io_sources; - unsigned n_io_sources; + struct pa_io_event **io_events; + unsigned n_io_events; size_t frame_size, fragment_size; struct pa_memchunk memchunk, silence; @@ -128,9 +128,9 @@ static void do_write(struct userdata *u) { } } -static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; - assert(u && a && id); + assert(u && a && e); if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) xrun_recovery(u); @@ -207,7 +207,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); - if (pa_create_io_sources(u->pcm_handle, c->mainloop, &u->io_sources, &u->n_io_sources, io_callback, u) < 0) { + if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { fprintf(stderr, __FILE__": failed to obtain file descriptors\n"); goto fail; } @@ -251,8 +251,8 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { if (u->sink) pa_sink_free(u->sink); - if (u->io_sources) - pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources); + if (u->io_events) + pa_free_io_events(c->mainloop, u->io_events, u->n_io_events); if (u->pcm_handle) { snd_pcm_drop(u->pcm_handle); diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 8207d462a..df716f737 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -42,8 +42,8 @@ struct userdata { snd_pcm_t *pcm_handle; struct pa_source *source; - void **io_sources; - unsigned n_io_sources; + struct pa_io_event **io_events; + unsigned n_io_events; size_t frame_size, fragment_size; struct pa_memchunk memchunk; @@ -128,9 +128,9 @@ static void do_read(struct userdata *u) { } } -static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; - assert(u && a && id); + assert(u && a && e); if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) xrun_recovery(u); @@ -189,7 +189,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); - if (pa_create_io_sources(u->pcm_handle, c->mainloop, &u->io_sources, &u->n_io_sources, io_callback, u) < 0) { + if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { fprintf(stderr, __FILE__": failed to obtain file descriptors\n"); goto fail; } @@ -230,8 +230,8 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { if (u->source) pa_source_free(u->source); - if (u->io_sources) - pa_free_io_sources(c->mainloop, u->io_sources, u->n_io_sources); + if (u->io_events) + pa_free_io_events(c->mainloop, u->io_events, u->n_io_events); if (u->pcm_handle) { snd_pcm_drop(u->pcm_handle); diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 37710fc56..ea768a987 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -59,7 +59,7 @@ struct userdata { void *in_mmap, *out_mmap; size_t in_mmap_length, out_mmap_length; - void *mainloop_source; + struct pa_io_event *io_event; struct pa_memblock **in_memblocks, **out_memblocks; unsigned out_current, in_current; @@ -195,14 +195,13 @@ static void do_read(struct userdata *u) { in_clear_memblocks(u, u->in_fragments/2); }; -static void io_callback(struct pa_mainloop_api *m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void io_callback(struct pa_mainloop_api *m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; + assert (u && u->core->mainloop == m && u->io_event == e); - assert (u && u->core->mainloop == m && u->mainloop_source == id); - - if (events & PA_MAINLOOP_API_IO_EVENT_INPUT) + if (f & PA_IO_EVENT_INPUT) do_read(u); - if (events & PA_MAINLOOP_API_IO_EVENT_OUTPUT) + if (f & PA_IO_EVENT_OUTPUT) do_write(u); } @@ -352,8 +351,8 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(u->source || u->sink); - u->mainloop_source = c->mainloop->source_io(c->mainloop, u->fd, (u->source ? PA_MAINLOOP_API_IO_EVENT_INPUT : 0) | (u->sink ? PA_MAINLOOP_API_IO_EVENT_OUTPUT : 0), io_callback, u); - assert(u->mainloop_source); + u->io_event = c->mainloop->io_new(c->mainloop, u->fd, (u->source ? PA_IO_EVENT_INPUT : 0) | (u->sink ? PA_IO_EVENT_OUTPUT : 0), io_callback, u); + assert(u->io_event); pa_modargs_free(ma); @@ -403,8 +402,8 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { if (u->source) pa_source_free(u->source); - if (u->mainloop_source) - u->core->mainloop->cancel_io(u->core->mainloop, u->mainloop_source); + if (u->io_event) + u->core->mainloop->io_free(u->io_event); if (u->fd >= 0) close(u->fd); diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index dc2bc633d..22d9f6768 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -50,7 +50,7 @@ struct userdata { struct pa_sink *sink; struct pa_iochannel *io; - void *mainloop_source; + struct pa_defer_event *defer_event; struct pa_memchunk memchunk; struct pa_module *module; @@ -69,7 +69,7 @@ static void do_write(struct userdata *u) { ssize_t r; assert(u); - u->core->mainloop->enable_fixed(u->core->mainloop, u->mainloop_source, 0); + u->core->mainloop->defer_enable(u->defer_event, 0); if (!pa_iochannel_is_writable(u->io)) return; @@ -101,10 +101,10 @@ static void notify_cb(struct pa_sink*s) { assert(s && u); if (pa_iochannel_is_writable(u->io)) - u->core->mainloop->enable_fixed(u->core->mainloop, u->mainloop_source, 1); + u->core->mainloop->defer_enable(u->defer_event, 1); } -static void fixed_callback(struct pa_mainloop_api *m, void *id, void *userdata) { +static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata) { struct userdata *u = userdata; assert(u); do_write(u); @@ -175,9 +175,9 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; - u->mainloop_source = c->mainloop->source_fixed(c->mainloop, fixed_callback, u); - assert(u->mainloop_source); - c->mainloop->enable_fixed(c->mainloop, u->mainloop_source, 0); + u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u); + assert(u->defer_event); + c->mainloop->defer_enable(u->defer_event, 0); u->module = m; m->userdata = u; @@ -210,7 +210,7 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { pa_sink_free(u->sink); pa_iochannel_free(u->io); - u->core->mainloop->cancel_fixed(u->core->mainloop, u->mainloop_source); + u->core->mainloop->defer_free(u->defer_event); assert(u->filename); unlink(u->filename); diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index 2cf760998..5449e944d 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -14,7 +14,7 @@ #include "namereg.h" struct x11_source { - void *io_source; + struct pa_io_event *io_event; struct x11_source *next; }; @@ -52,7 +52,7 @@ static int ring_bell(struct userdata *u, int percent) { return 0; } -static void io_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; assert(u); @@ -77,8 +77,8 @@ static void new_io_source(struct userdata *u, int fd) { struct x11_source *s; s = pa_xmalloc(sizeof(struct x11_source)); - s->io_source = u->core->mainloop->source_io(u->core->mainloop, fd, PA_MAINLOOP_API_IO_EVENT_INPUT, io_callback, u); - assert(s->io_source); + s->io_event = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, io_callback, u); + assert(s->io_event); s->next = u->x11_sources; u->x11_sources = s; } @@ -149,7 +149,7 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { while (u->x11_sources) { struct x11_source *s = u->x11_sources; u->x11_sources = u->x11_sources->next; - c->mainloop->cancel_io(c->mainloop, s->io_source); + c->mainloop->io_free(s->io_event); pa_xfree(s); } diff --git a/polyp/module.c b/polyp/module.c index 8c5e318f1..83bfa8007 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -35,16 +35,16 @@ #define UNLOAD_POLL_TIME 10 -static void timeout_callback(struct pa_mainloop_api *m, void *id, const struct timeval *tv, void *userdata) { +static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { struct pa_core *c = userdata; struct timeval ntv; - assert(c && c->mainloop == m && c->auto_unload_mainloop_source == id); + assert(c && c->mainloop == m && c->auto_unload_event == e); pa_module_unload_unused(c); gettimeofday(&ntv, NULL); ntv.tv_sec += UNLOAD_POLL_TIME; - m->enable_time(m, id, &ntv); + m->time_restart(e, &ntv); } struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char *argument) { @@ -79,13 +79,13 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char if (!c->modules) c->modules = pa_idxset_new(NULL, NULL); - if (!c->auto_unload_mainloop_source) { + if (!c->auto_unload_event) { struct timeval ntv; gettimeofday(&ntv, NULL); ntv.tv_sec += UNLOAD_POLL_TIME; - c->auto_unload_mainloop_source = c->mainloop->source_time(c->mainloop, &ntv, timeout_callback, c); + c->auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } - assert(c->auto_unload_mainloop_source); + assert(c->auto_unload_event); assert(c->modules); r = pa_idxset_put(c->modules, m, &m->index); @@ -159,9 +159,9 @@ void pa_module_unload_all(struct pa_core *c) { pa_idxset_free(c->modules, free_callback, NULL); c->modules = NULL; - if (c->auto_unload_mainloop_source) - c->mainloop->cancel_time(c->mainloop, c->auto_unload_mainloop_source); - c->auto_unload_mainloop_source = NULL; + if (c->auto_unload_event) + c->mainloop->time_free(c->auto_unload_event); + c->auto_unload_event = NULL; } static int unused_callback(void *p, uint32_t index, int *del, void *userdata) { @@ -193,7 +193,7 @@ struct once_info { uint32_t index; }; -static void module_unload_once_callback(void *userdata) { +static void module_unload_once_callback(struct pa_mainloop_api *m, void *userdata) { struct once_info *i = userdata; assert(i); pa_module_unload_by_index(i->core, i->index); diff --git a/polyp/module.h b/polyp/module.h index de195a4b2..acc08c3e0 100644 --- a/polyp/module.h +++ b/polyp/module.h @@ -59,5 +59,4 @@ void pa_module_done(struct pa_core *c, struct pa_module*m); void pa_module_set_used(struct pa_module*m, int used); - #endif diff --git a/polyp/native-common.h b/polyp/native-common.h index dc730e4b0..d8a2a5ab1 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -48,13 +48,15 @@ enum { PA_COMMAND_PLAY_SAMPLE, PA_COMMAND_REMOVE_SAMPLE, - PA_COMMAND_GET_SINK, - PA_COMMAND_GET_SOURCE, - PA_COMMAND_GET_MODULE, - PA_COMMAND_GET_CLIENT, - PA_COMMAND_GET_SINK_INPUT, - PA_COMMAND_GET_SOURCE_OUTPUT, - PA_COMMAND_GET_SAMPLE, + PA_COMMAND_GET_SINK_INFO, + PA_COMMAND_GET_SINK_INFO_LIST, + PA_COMMAND_GET_SOURCE_INFO, + PA_COMMAND_GET_SOURCE_INFO_LIST, + PA_COMMAND_GET_MODULE_INFO, + PA_COMMAND_GET_CLIENT_INFO, + PA_COMMAND_GET_SINK_INPUT_INFO, + PA_COMMAND_GET_SOURCE_OUTPUT_INFO, + PA_COMMAND_GET_SAMPLE_INFO, PA_COMMAND_SUBSCRIBE, PA_COMMAND_SUBSCRIBE_EVENT, diff --git a/polyp/pacat.c b/polyp/pacat.c index 55a0f6b94..4d8605c7a 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -45,7 +45,7 @@ static struct pa_mainloop_api *mainloop_api = NULL; static void *buffer = NULL; static size_t buffer_length = 0, buffer_index = 0; -static void* stdio_source = NULL; +static struct pa_io_event* stdio_event = NULL; static void quit(int ret) { assert(mainloop_api); @@ -89,8 +89,8 @@ static void do_stream_write(size_t length) { static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { assert(s && length); - if (stdio_source) - mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_INPUT); + if (stdio_event) + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT); if (!buffer) return; @@ -101,8 +101,8 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user static void stream_read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata) { assert(s && data && length); - if (stdio_source) - mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_OUTPUT); + if (stdio_event) + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); if (buffer) { fprintf(stderr, "Buffer overrrun, dropping incoming data\n"); @@ -174,13 +174,13 @@ static void stream_drain_complete(struct pa_stream*s, void *userdata) { fprintf(stderr, "Draining connection to server.\n"); } -static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { size_t l, w = 0; ssize_t r; - assert(a == mainloop_api && id && stdio_source == id); + assert(a == mainloop_api && e && stdio_event == e); if (buffer) { - mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_NULL); + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); return; } @@ -198,8 +198,8 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m quit(1); } - mainloop_api->cancel_io(mainloop_api, stdio_source); - stdio_source = NULL; + mainloop_api->io_free(stdio_event); + stdio_event = NULL; return; } @@ -210,12 +210,12 @@ static void stdin_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_m do_stream_write(w); } -static void stdout_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { ssize_t r; - assert(a == mainloop_api && id && stdio_source == id); + assert(a == mainloop_api && e && stdio_event == e); if (!buffer) { - mainloop_api->enable_io(mainloop_api, stdio_source, PA_MAINLOOP_API_IO_EVENT_NULL); + mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); return; } @@ -225,8 +225,8 @@ static void stdout_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_ fprintf(stderr, "write() failed: %s\n", strerror(errno)); quit(1); - mainloop_api->cancel_io(mainloop_api, stdio_source); - stdio_source = NULL; + mainloop_api->io_free(stdio_event); + stdio_event = NULL; return; } @@ -240,7 +240,7 @@ static void stdout_callback(struct pa_mainloop_api*a, void *id, int fd, enum pa_ } } -static void exit_signal_callback(void *id, int sig, void *userdata) { +static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); @@ -258,7 +258,7 @@ static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, v fprintf(stderr, "Current latency is %u usecs.\n", latency); } -static void sigusr1_signal_callback(void *id, int sig, void *userdata) { +static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { if (mode == PLAYBACK) { fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); pa_stream_get_latency(stream, stream_get_latency_callback, NULL); @@ -289,14 +289,14 @@ int main(int argc, char *argv[]) { r = pa_signal_init(mainloop_api); assert(r == 0); - pa_signal_register(SIGINT, exit_signal_callback, NULL); - pa_signal_register(SIGUSR1, sigusr1_signal_callback, NULL); + pa_signal_new(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - if (!(stdio_source = mainloop_api->source_io(mainloop_api, - mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, - mode == PLAYBACK ? PA_MAINLOOP_API_IO_EVENT_INPUT : PA_MAINLOOP_API_IO_EVENT_OUTPUT, - mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { + if (!(stdio_event = mainloop_api->io_new(mainloop_api, + mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, + mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, + mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { fprintf(stderr, "source_io() failed.\n"); goto quit; } diff --git a/polyp/pactl.c b/polyp/pactl.c index 28b187b04..2f3a48331 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -205,7 +205,7 @@ fail: quit(1); } -static void exit_signal_callback(void *id, int sig, void *userdata) { +static void exit_signal_callback(struct pa_mainloop_api *m, struct pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); } @@ -284,7 +284,7 @@ int main(int argc, char *argv[]) { r = pa_signal_init(mainloop_api); assert(r == 0); - pa_signal_register(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGINT, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); if (!(context = pa_context_new(mainloop_api, argv[0]))) { diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index c34c6e0ad..2d4c4d641 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -69,7 +69,7 @@ struct reply_info { void (*callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); void *userdata; uint32_t tag; - void *mainloop_timeout; + struct pa_time_event *time_event; int callback_is_running; }; @@ -87,7 +87,7 @@ static void reply_info_free(struct reply_info *r) { assert(r && r->pdispatch && r->pdispatch->mainloop); if (r->pdispatch) - r->pdispatch->mainloop->cancel_time(r->pdispatch->mainloop, r->mainloop_timeout); + r->pdispatch->mainloop->time_free(r->time_event); if (r->previous) r->previous->next = r->next; @@ -191,9 +191,9 @@ finish: return ret; } -static void timeout_callback(struct pa_mainloop_api*m, void *id, const struct timeval *tv, void *userdata) { +static void timeout_callback(struct pa_mainloop_api*m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { struct reply_info*r = userdata; - assert (r && r->mainloop_timeout == id && r->pdispatch && r->pdispatch->mainloop == m && r->callback); + assert (r && r->time_event == e && r->pdispatch && r->pdispatch->mainloop == m && r->callback); r->callback(r->pdispatch, PA_COMMAND_TIMEOUT, r->tag, NULL, r->userdata); reply_info_free(r); @@ -217,8 +217,8 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time gettimeofday(&tv, NULL); tv.tv_sec += timeout; - r->mainloop_timeout = pd->mainloop->source_time(pd->mainloop, &tv, timeout_callback, r); - assert(r->mainloop_timeout); + r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r); + assert(r->time_event); r->previous = NULL; r->next = pd->replies; diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index 5c448a754..866344070 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -30,7 +30,7 @@ static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { return 0; } -static void si_kill(void *i) { +static void si_kill(struct pa_mainloop_api *m, void *i) { sink_input_kill(i); } diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 0989a78d2..715135657 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -18,33 +18,41 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -# Load audio drivers +# Load audio drivers statically + #load module-alsa-sink #load module-alsa-source device=plughw:1,0 -#load module-oss device="/dev/dsp" +#load module-oss device="/dev/dsp" sink_name=output source_name=input #load module-oss-mmap device="/dev/dsp" +# Load audio drivers automatically on access + +#autoload_sink_add output module-oss device="/dev/dsp" sink_name=output source_name=input +#autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input +autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#autoload_sink_add output module-alsa-sink sink_name=output +#autoload_source_add input module-alsa-source source_name=input + # Load several protocols load module-esound-protocol-tcp load module-simple-protocol-tcp load module-native-protocol-unix load module-cli-protocol-unix -# Load X11 bell module -load module-x11-bell - # Load the CLI module load module-cli -autoload_sink_add oss_output module-oss device="/dev/dsp" sink_name=oss_output source_name=oss_input -autoload_source_add oss_input module-oss device="/dev/dsp" sink_name=oss_output source_name=oss_input - # Make some devices default -sink_default oss_output -source_default oss_input +sink_default output +source_default input .nofail # Load something to the sample cache scache_load /usr/share/sounds/KDE_Notify.wav x11-bell -scache_play x11-bell oss_output +scache_play x11-bell output + +# Load X11 bell module +load module-x11-bell sample=x11-bell sink=output + diff --git a/polyp/polyplib.h b/polyp/polyplib.h index 391cb0c86..08e6a5a5a 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -97,4 +97,34 @@ void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +struct pa_sink_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec *sample_spec; + uint32_t owner_module; + uint32_t volume; + uint32_t monitor_source; + const char *monitor_source_name; + uint32_t latency; +}; + +void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata); +void pa_context_get_sink_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata); +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata); + +struct pa_source_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec *sample_spec; + uint32_t owner_module; + uint32_t monitor_of_sink; + const char *monitor_of_sink_name; +}; + +void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); +void pa_context_get_source_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); + #endif diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 5f6f02fa8..b11e19923 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -74,7 +74,7 @@ struct connection { struct pa_sink_input *sink_input; struct pa_source_output *source_output; struct pa_memblockq *input_memblockq, *output_memblockq; - void *fixed_source; + struct pa_defer_event *defer_event; struct { struct pa_memblock *current_memblock; size_t memblock_index, fragment_size; @@ -183,8 +183,8 @@ static void connection_free(struct connection *c) { pa_iochannel_free(c->io); - if (c->fixed_source) - c->protocol->core->mainloop->cancel_fixed(c->protocol->core->mainloop, c->fixed_source); + if (c->defer_event) + c->protocol->core->mainloop->defer_free(c->defer_event); if (c->scache_memchunk.memblock) pa_memblock_unref(c->scache_memchunk.memblock); @@ -197,8 +197,8 @@ static void* connection_write(struct connection *c, size_t length) { size_t t, i; assert(c); - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); t = c->write_data_length+length; @@ -381,7 +381,7 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons int latency, *lag; assert(c && !data && length == 0); - if (!(sink = pa_namereg(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) + if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) latency = 0; else { float usec = pa_sink_get_latency(sink); @@ -845,8 +845,8 @@ static int do_write(struct connection *c) { static void do_work(struct connection *c) { assert(c); - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 0); if (pa_iochannel_is_hungup(c->io)) goto fail; @@ -872,11 +872,11 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { do_work(c); } -/*** fixed callback ***/ +/*** defer callback ***/ -static void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) { +static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { struct connection *c = userdata; - assert(a && c && c->fixed_source == id); + assert(a && c && c->defer_event == e); do_work(c); } @@ -901,8 +901,8 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { pa_memblockq_drop(c->input_memblockq, length); /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } static void sink_input_kill_cb(struct pa_sink_input *i) { @@ -926,8 +926,8 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me pa_memblockq_push(c->output_memblockq, chunk, 0); /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } static void source_output_kill_cb(struct pa_source_output *o) { @@ -981,8 +981,9 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->scache_memchunk.memblock = NULL; c->scache_name = NULL; - c->fixed_source = c->protocol->core->mainloop->source_fixed(c->protocol->core->mainloop, fixed_callback, c); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); + c->defer_event = c->protocol->core->mainloop->defer_new(c->protocol->core->mainloop, defer_callback, c); + assert(c->defer_event); + c->protocol->core->mainloop->defer_enable(c->defer_event, 0); pa_idxset_put(c->protocol->connections, c, &c->index); } diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index c0aef180e..778677b31 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -127,6 +127,8 @@ static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t comma static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -150,6 +152,10 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_FINISH_UPLOAD_STREAM] = { command_finish_upload_stream }, [PA_COMMAND_PLAY_SAMPLE] = { command_play_sample }, [PA_COMMAND_REMOVE_SAMPLE] = { command_remove_sample }, + [PA_COMMAND_GET_SINK_INFO] = { command_get_info }, + [PA_COMMAND_GET_SOURCE_INFO] = { command_get_info }, + [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list }, + [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list }, }; /* structure management */ @@ -923,6 +929,122 @@ static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uin pa_pstream_send_simple_ack(c->pstream, tag); } +static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) { + assert(t && sink); + pa_tagstruct_putu32(t, sink->index); + pa_tagstruct_puts(t, sink->name); + pa_tagstruct_puts(t, sink->description); + pa_tagstruct_put_sample_spec(t, &sink->sample_spec); + pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1); + pa_tagstruct_putu32(t, sink->volume); + pa_tagstruct_putu32(t, sink->monitor_source->index); + pa_tagstruct_puts(t, sink->monitor_source->name); + pa_tagstruct_putu32(t, pa_sink_get_latency(sink)); +} + +static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *source) { + assert(t && source); + pa_tagstruct_putu32(t, source->index); + pa_tagstruct_puts(t, source->name); + pa_tagstruct_puts(t, source->description); + pa_tagstruct_put_sample_spec(t, &source->sample_spec); + pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1); + pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1); + pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : ""); +} + +static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + struct pa_sink *sink = NULL; + struct pa_source *source = NULL; + const char *name; + struct pa_tagstruct *reply; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (command == PA_COMMAND_GET_SINK_INFO) { + if (index != (uint32_t) -1) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, index); + else + sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1); + } else { + assert(command == PA_COMMAND_GET_SOURCE_INFO); + if (index != (uint32_t) -1) + source = pa_idxset_get_by_index(c->protocol->core->sources, index); + else + source = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SOURCE, 1); + } + + if (!sink && !source) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + if (sink) + sink_fill_tagstruct(reply, sink); + else + source_fill_tagstruct(reply, source); + pa_pstream_send_tagstruct(c->pstream, reply); +} + +static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + struct pa_idxset *i; + uint32_t index; + void *p; + struct pa_tagstruct *reply; + assert(c && t); + + if (!pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + + if (command == PA_COMMAND_GET_SINK_INFO_LIST) + i = c->protocol->core->sinks; + else { + assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST); + i = c->protocol->core->sources; + } + + for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) { + if (command == PA_COMMAND_GET_SINK_INFO_LIST) + sink_fill_tagstruct(reply, p); + else { + assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST); + source_fill_tagstruct(reply, p); + } + } + + pa_pstream_send_tagstruct(c->pstream, reply); +} + /*** pstream callbacks ***/ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 4b3b1513c..a95b356c1 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -45,7 +45,7 @@ struct connection { struct pa_source_output *source_output; struct pa_client *client; struct pa_memblockq *input_memblockq, *output_memblockq; - void *fixed_source; + struct pa_defer_event *defer_event; struct { struct pa_memblock *current_memblock; @@ -91,8 +91,8 @@ static void connection_free(struct connection *c) { pa_memblockq_free(c->input_memblockq); if (c->output_memblockq) pa_memblockq_free(c->output_memblockq); - if (c->fixed_source) - c->protocol->core->mainloop->cancel_fixed(c->protocol->core->mainloop, c->fixed_source); + if (c->defer_event) + c->protocol->core->mainloop->defer_free(c->defer_event); pa_xfree(c); } @@ -169,8 +169,8 @@ static int do_write(struct connection *c) { static void do_work(struct connection *c) { assert(c); - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 0); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 0); if (pa_iochannel_is_hungup(c->io)) goto fail; @@ -209,8 +209,8 @@ static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { pa_memblockq_drop(c->input_memblockq, length); /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } static void sink_input_kill_cb(struct pa_sink_input *i) { @@ -234,8 +234,8 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me pa_memblockq_push(c->output_memblockq, chunk, 0); /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->enable_fixed); - c->protocol->core->mainloop->enable_fixed(c->protocol->core->mainloop, c->fixed_source, 1); + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } static void source_output_kill_cb(struct pa_source_output *o) { @@ -261,9 +261,9 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { /*** fixed callback ***/ -static void fixed_callback(struct pa_mainloop_api*a, void *id, void *userdata) { +static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { struct connection *c = userdata; - assert(a && c && c->fixed_source == id); + assert(a && c && c->defer_event == e); do_work(c); } @@ -280,7 +280,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->io = io; c->sink_input = NULL; c->source_output = NULL; - c->fixed_source = NULL; + c->defer_event = NULL; c->input_memblockq = c->output_memblockq = NULL; c->protocol = p; c->playback.current_memblock = NULL; @@ -353,9 +353,9 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo pa_iochannel_set_callback(c->io, io_callback, c); pa_idxset_put(p->connections, c, NULL); - c->fixed_source = p->core->mainloop->source_fixed(p->core->mainloop, fixed_callback, c); - assert(c->fixed_source); - p->core->mainloop->enable_fixed(p->core->mainloop, c->fixed_source, 0); + c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c); + assert(c->defer_event); + p->core->mainloop->defer_enable(c->defer_event, 0); return; diff --git a/polyp/pstream.c b/polyp/pstream.c index e7441b24b..4f071e4ae 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -58,7 +58,7 @@ struct item_info { struct pa_pstream { struct pa_mainloop_api *mainloop; - struct mainloop_source *mainloop_source; + struct pa_defer_event *defer_event; struct pa_iochannel *io; struct pa_queue *send_queue; @@ -98,7 +98,7 @@ static void do_read(struct pa_pstream *p); static void do_something(struct pa_pstream *p) { assert(p && !p->shall_free); - p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 0); + p->mainloop->defer_enable(p->defer_event, 0); if (p->dead) return; @@ -139,9 +139,9 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { do_something(p); } -static void fixed_callback(struct pa_mainloop_api *m, void *id, void*userdata) { +static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, void*userdata) { struct pa_pstream *p = userdata; - assert(p && p->mainloop_source == id && p->mainloop == m); + assert(p && p->defer_event == e && p->mainloop == m); do_something(p); } @@ -159,8 +159,8 @@ struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel p->die_callback_userdata = NULL; p->mainloop = m; - p->mainloop_source = m->source_fixed(m, fixed_callback, p); - m->enable_fixed(m, p->mainloop_source, 0); + p->defer_event = m->defer_new(m, defer_callback, p); + m->defer_enable(p->defer_event, 0); p->send_queue = pa_queue_new(); assert(p->send_queue); @@ -223,7 +223,7 @@ void pa_pstream_free(struct pa_pstream *p) { if (p->read.packet) pa_packet_unref(p->read.packet); - p->mainloop->cancel_fixed(p->mainloop, p->mainloop_source); + p->mainloop->defer_free(p->defer_event); pa_xfree(p); } @@ -236,7 +236,7 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { i->packet = pa_packet_ref(packet); pa_queue_push(p->send_queue, i); - p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1); + p->mainloop->defer_enable(p->defer_event, 1); } void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk) { @@ -252,7 +252,7 @@ void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t del pa_memblock_ref(i->chunk.memblock); pa_queue_push(p->send_queue, i); - p->mainloop->enable_fixed(p->mainloop, p->mainloop_source, 1); + p->mainloop->defer_enable(p->defer_event, 1); } void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata) { diff --git a/polyp/socket-client.c b/polyp/socket-client.c index c0c355de0..e8cb2f92a 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -41,8 +41,8 @@ struct pa_socket_client { struct pa_mainloop_api *mainloop; int fd; - - void *io_source, *fixed_source; + struct pa_io_event *io_event; + struct pa_defer_event *defer_event; void (*callback)(struct pa_socket_client*c, struct pa_iochannel *io, void *userdata); void *userdata; }; @@ -54,7 +54,8 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { c = pa_xmalloc(sizeof(struct pa_socket_client)); c->mainloop = m; c->fd = -1; - c->io_source = c->fixed_source = NULL; + c->io_event = NULL; + c->defer_event = NULL; c->callback = NULL; c->userdata = NULL; return c; @@ -95,19 +96,19 @@ failed: return; } -static void connect_fixed_cb(struct pa_mainloop_api *m, void *id, void *userdata) { +static void connect_fixed_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { struct pa_socket_client *c = userdata; - assert(m && c && c->fixed_source == id); - m->cancel_fixed(m, c->fixed_source); - c->fixed_source = NULL; + assert(m && c && c->defer_event == e); + m->defer_free(c->defer_event); + c->defer_event = NULL; do_call(c); } -static void connect_io_cb(struct pa_mainloop_api*m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void connect_io_cb(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct pa_socket_client *c = userdata; - assert(m && c && c->io_source == id && fd >= 0); - m->cancel_io(m, c->io_source); - c->io_source = NULL; + assert(m && c && c->io_event == e && fd >= 0); + m->io_free(c->io_event); + c->io_event = NULL; do_call(c); } @@ -123,11 +124,11 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc return -1; } - c->io_source = c->mainloop->source_io(c->mainloop, c->fd, PA_MAINLOOP_API_IO_EVENT_OUTPUT, connect_io_cb, c); - assert(c->io_source); + c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c); + assert(c->io_event); } else { - c->fixed_source = c->mainloop->source_fixed(c->mainloop, connect_fixed_cb, c); - assert(c->fixed_source); + c->defer_event = c->mainloop->defer_new(c->mainloop, connect_fixed_cb, c); + assert(c->defer_event); } return 0; @@ -220,10 +221,10 @@ fail: void pa_socket_client_free(struct pa_socket_client *c) { assert(c && c->mainloop); - if (c->io_source) - c->mainloop->cancel_io(c->mainloop, c->io_source); - if (c->fixed_source) - c->mainloop->cancel_fixed(c->mainloop, c->fixed_source); + if (c->io_event) + c->mainloop->io_free(c->io_event); + if (c->defer_event) + c->mainloop->defer_free(c->defer_event); if (c->fd >= 0) close(c->fd); pa_xfree(c); diff --git a/polyp/socket-server.c b/polyp/socket-server.c index 5f332f0c1..6af2c2865 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -46,16 +46,16 @@ struct pa_socket_server { void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata); void *userdata; - void *mainloop_source; + struct pa_io_event *io_event; struct pa_mainloop_api *mainloop; enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX } type; }; -static void callback(struct pa_mainloop_api *mainloop, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) { +static void callback(struct pa_mainloop_api *mainloop, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct pa_socket_server *s = userdata; struct pa_iochannel *io; int nfd; - assert(s && s->mainloop == mainloop && s->mainloop_source == id && id && fd >= 0 && fd == s->fd && events == PA_MAINLOOP_API_IO_EVENT_INPUT); + assert(s && s->mainloop == mainloop && s->io_event == e && e && fd >= 0 && fd == s->fd); if ((nfd = accept(fd, NULL, NULL)) < 0) { fprintf(stderr, "accept(): %s\n", strerror(errno)); @@ -89,8 +89,8 @@ struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) s->userdata = NULL; s->mainloop = m; - s->mainloop_source = m->source_io(m, fd, PA_MAINLOOP_API_IO_EVENT_INPUT, callback, s); - assert(s->mainloop_source); + s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s); + assert(s->io_event); s->type = SOCKET_SERVER_GENERIC; @@ -193,7 +193,7 @@ void pa_socket_server_free(struct pa_socket_server*s) { pa_xfree(s->filename); } - s->mainloop->cancel_io(s->mainloop, s->mainloop_source); + s->mainloop->io_free(s->io_event); pa_xfree(s); } diff --git a/polyp/xmalloc.h b/polyp/xmalloc.h index 5f58a8adf..45209b05e 100644 --- a/polyp/xmalloc.h +++ b/polyp/xmalloc.h @@ -2,6 +2,7 @@ #define foomemoryhfoo #include +#include void* pa_xmalloc(size_t l); void *pa_xmalloc0(size_t l); From 68eb5dd2486611d08d1d14e02ff1624ec27997c7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 6 Aug 2004 23:07:48 +0000 Subject: [PATCH 0105/1514] add mainloop test utility fix glib mainloop support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@106 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 16 +++-- polyp/glib-mainloop.c | 147 +++++++++++++++++++++--------------------- polyp/glib-mainloop.h | 11 +++- polyp/glib-test.c | 92 ++++++++++++++++++++++++++ polyp/mainloop-api.h | 8 +++ polyp/polyplib-def.h | 8 +++ polyp/polyplib.h | 8 +++ polyp/sample.h | 8 +++ 8 files changed, 221 insertions(+), 77 deletions(-) create mode 100644 polyp/glib-test.c diff --git a/polyp/Makefile.am b/polyp/Makefile.am index c0be8ce08..1be04f410 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -21,18 +21,21 @@ AM_CFLAGS=-ansi -D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" -I$(srcdir)/.. AM_LDADD=-L. AM_LIBADD=-L. +polypincludedir=$(includedir)/polyp + EXTRA_DIST = polypaudio.pa depmod.py bin_PROGRAMS = polypaudio pacat pactl -noinst_PROGRAMS = pacat-simple parec-simple +noinst_PROGRAMS = pacat-simple parec-simple glib-test -pkginclude_HEADERS=polyplib.h \ +polypinclude_HEADERS=polyplib.h \ polyplib-def.h \ polyplib-simple.h \ polyplib-error.h \ mainloop-api.h \ mainloop.h \ mainloop-signal.h \ - sample.h + sample.h \ + glib-mainloop.h pkglib_LTLIBRARIES=libiochannel.la \ libsocket-server.la \ @@ -312,9 +315,13 @@ libpolyp_mainloop_glib_la_SOURCES = glib-mainloop.h glib-mainloop.c libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB20_LIBS) +glib_test_SOURCES = glib-test.c +glib_test_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) +glib_test_LDADD = $(AM_LDADD) $(GLIB20_LIBS) libpolyp.la libpolyp-mainloop-glib.la + if BUILD_LIBPOLYPCORE -pkginclude_HEADERS+=cli-command.h\ +polypinclude_HEADERS+=cli-command.h\ client.h \ core.h \ dynarray.h \ @@ -380,3 +387,4 @@ libpolypcore_la_SOURCES = idxset.c idxset.h \ dynarray.c dynarray.h endif + diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c index 978cad076..3b9feaad2 100644 --- a/polyp/glib-mainloop.c +++ b/polyp/glib-mainloop.c @@ -5,11 +5,12 @@ #include "xmalloc.h" struct pa_io_event { - GSource source; - int dead; struct pa_glib_mainloop *mainloop; + int dead; + GIOChannel *io_channel; + GSource *source; + GIOCondition io_condition; int fd; - GPollFD pollfd; void (*callback) (struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata); void *userdata; void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_io_event*e, void *userdata); @@ -38,7 +39,7 @@ struct pa_defer_event { }; struct pa_glib_mainloop { - GMainLoop *glib_mainloop; + GMainContext *glib_main_context; struct pa_mainloop_api api; GSource *cleanup_source; struct pa_io_event *io_events, *dead_io_events; @@ -48,55 +49,16 @@ struct pa_glib_mainloop { static void schedule_free_dead_events(struct pa_glib_mainloop *g); -static gboolean glib_source_prepare(GSource *source, gint *timeout) { - return FALSE; -} - -static gboolean glib_source_check(GSource *source) { - struct pa_io_event *e = (struct pa_io_event*) source; - assert(e); - return !!e->pollfd.revents; -} - -static gboolean glib_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { - struct pa_io_event *e = (struct pa_io_event*) source; - assert(e); - - if (e->pollfd.revents) { - int f = - (e->pollfd.revents ? G_IO_IN : PA_IO_EVENT_INPUT) | - (e->pollfd.revents ? G_IO_OUT : PA_IO_EVENT_OUTPUT) | - (e->pollfd.revents ? G_IO_HUP : PA_IO_EVENT_HANGUP) | - (e->pollfd.revents ? G_IO_ERR : PA_IO_EVENT_ERROR); - e->pollfd.revents = 0; - - assert(e->callback); - e->callback(&e->mainloop->api, e, e->fd, f, e->userdata); - } - - return TRUE; -} - static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f); static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa_io_event_flags f, void (*callback) (struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata), void *userdata) { struct pa_io_event *e; struct pa_glib_mainloop *g; - GSourceFuncs io_source_funcs = { - prepare: glib_source_prepare, - check: glib_source_check, - dispatch: glib_source_dispatch, - finalize: NULL, - closure_callback: NULL, - closure_marshal : NULL, - }; - assert(m && m->userdata && fd >= 0 && callback); g = m->userdata; - e = (struct pa_io_event*) g_source_new(&io_source_funcs, sizeof(struct pa_io_event)); - assert(e); + e = pa_xmalloc(sizeof(struct pa_io_event)); e->mainloop = m->userdata; e->dead = 0; e->fd = fd; @@ -104,10 +66,10 @@ static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa e->userdata = userdata; e->destroy_callback = NULL; - e->pollfd.fd = fd; - e->pollfd.events = e->pollfd.revents = 0; - - g_source_attach(&e->source, g_main_loop_get_context(g->glib_mainloop)); + e->io_channel = g_io_channel_unix_new(e->fd); + assert(e->io_channel); + e->source = NULL; + e->io_condition = 0; glib_io_enable(e, f); @@ -119,23 +81,52 @@ static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa return e; } +static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) { + struct pa_io_event *e = data; + enum pa_io_event_flags f; + assert(source && e && e->io_channel == source); + + f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) | + (condition & G_IO_OUT ? PA_IO_EVENT_OUTPUT : 0) | + (condition & G_IO_ERR ? PA_IO_EVENT_ERROR : 0) | + (condition & G_IO_HUP ? PA_IO_EVENT_HANGUP : 0); + + e->callback(&e->mainloop->api, e, e->fd, f, e->userdata); + return TRUE; +} + static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f) { - int o; + GIOCondition c; assert(e && !e->dead); - o = e->pollfd.events; - e->pollfd.events = (f & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | (f & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) | G_IO_HUP | G_IO_ERR; - - if (!o && e->pollfd.events) - g_source_add_poll(&e->source, &e->pollfd); - else if (o && !e->pollfd.events) - g_source_remove_poll(&e->source, &e->pollfd); + c = (f & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | (f & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0); + + if (c == e->io_condition) + return; + + if (e->source) { + g_source_destroy(e->source); + g_source_unref(e->source); + } + + e->source = g_io_create_watch(e->io_channel, c | G_IO_ERR | G_IO_HUP); + assert(e->source); + + g_source_set_callback(e->source, (GSourceFunc) io_cb, e, NULL); + g_source_attach(e->source, e->mainloop->glib_main_context); + g_source_set_priority(e->source, G_PRIORITY_DEFAULT); + + e->io_condition = c; } static void glib_io_free(struct pa_io_event*e) { assert(e && !e->dead); - g_source_destroy(&e->source); + if (e->source) { + g_source_destroy(e->source); + g_source_unref(e->source); + e->source = NULL; + } if (e->prev) e->prev->next = e->next; @@ -235,7 +226,8 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) e->source = g_timeout_source_new(msec_diff(tv, &now)); assert(e->source); g_source_set_callback(e->source, time_cb, e, NULL); - g_source_attach(e->source, g_main_loop_get_context(e->mainloop->glib_mainloop)); + g_source_set_priority(e->source, G_PRIORITY_HIGH); + g_source_attach(e->source, e->mainloop->glib_main_context); } else e->source = NULL; } @@ -319,7 +311,7 @@ static void glib_defer_enable(struct pa_defer_event *e, int b) { e->source = g_idle_source_new(); assert(e->source); g_source_set_callback(e->source, idle_cb, e, NULL); - g_source_attach(e->source, g_main_loop_get_context(e->mainloop->glib_mainloop)); + g_source_attach(e->source, e->mainloop->glib_main_context); g_source_set_priority(e->source, G_PRIORITY_HIGH_IDLE); } } @@ -362,8 +354,8 @@ static void glib_quit(struct pa_mainloop_api*a, int retval) { struct pa_glib_mainloop *g; assert(a && a->userdata); g = a->userdata; - - g_main_loop_quit(g->glib_mainloop); + + /* NOOP */ } static const struct pa_mainloop_api vtable = { @@ -387,12 +379,16 @@ static const struct pa_mainloop_api vtable = { quit : glib_quit, }; -struct pa_glib_mainloop *pa_glib_mainloop_new(GMainLoop *ml) { +struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { struct pa_glib_mainloop *g; - assert(ml); g = pa_xmalloc(sizeof(struct pa_glib_mainloop)); - g->glib_mainloop = g_main_loop_ref(ml); + if (c) { + g->glib_main_context = c; + g_main_context_ref(c); + } else + g->glib_main_context = g_main_context_default(); + g->api = vtable; g->api.userdata = g; @@ -409,16 +405,18 @@ static void free_io_events(struct pa_io_event *e) { struct pa_io_event *r = e; e = r->next; - if (r->pollfd.events) - g_source_remove_poll(&r->source, &r->pollfd); + if (r->source) { + g_source_destroy(r->source); + g_source_unref(r->source); + } - if (!r->dead) - g_source_destroy(&r->source); + if (r->io_channel) + g_io_channel_unref(r->io_channel); if (r->destroy_callback) r->destroy_callback(&r->mainloop->api, r, r->userdata); - g_source_unref(&r->source); + pa_xfree(r); } } @@ -466,7 +464,12 @@ void pa_glib_mainloop_free(struct pa_glib_mainloop* g) { free_time_events(g->time_events); free_time_events(g->dead_time_events); - g_main_loop_unref(g->glib_mainloop); + if (g->cleanup_source) { + g_source_destroy(g->cleanup_source); + g_source_unref(g->cleanup_source); + } + + g_main_context_unref(g->glib_main_context); pa_xfree(g); } @@ -491,7 +494,7 @@ static gboolean free_dead_events(gpointer p) { } static void schedule_free_dead_events(struct pa_glib_mainloop *g) { - assert(g && g->glib_mainloop); + assert(g && g->glib_main_context); if (g->cleanup_source) return; @@ -499,5 +502,5 @@ static void schedule_free_dead_events(struct pa_glib_mainloop *g) { g->cleanup_source = g_idle_source_new(); assert(g->cleanup_source); g_source_set_callback(g->cleanup_source, free_dead_events, g, NULL); - g_source_attach(g->cleanup_source, g_main_loop_get_context(g->glib_mainloop)); + g_source_attach(g->cleanup_source, g->glib_main_context); } diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h index 50fe8b9c9..7655108af 100644 --- a/polyp/glib-mainloop.h +++ b/polyp/glib-mainloop.h @@ -5,10 +5,19 @@ #include "mainloop-api.h" +#ifdef __cplusplus +extern "C" { +#endif + struct pa_glib_mainloop; -struct pa_glib_mainloop *pa_glib_mainloop_new(GMainLoop *ml); +struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c); void pa_glib_mainloop_free(struct pa_glib_mainloop* g); struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/polyp/glib-test.c b/polyp/glib-test.c new file mode 100644 index 000000000..99196c4a6 --- /dev/null +++ b/polyp/glib-test.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include + +/*#define GLIB_MAIN_LOOP*/ + +#ifdef GLIB_MAIN_LOOP +#include +#include "glib-mainloop.h" +static GMainLoop* glib_main_loop = NULL; +#else +#include "mainloop.h" +#endif + +static void iocb(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { + unsigned char c; + read(fd, &c, sizeof(c)); + fprintf(stderr, "IO EVENT: %c\n", c < 32 ? '.' : c); +} + +static void dcb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { + fprintf(stderr, "DEFER EVENT\n"); + a->defer_enable(e, 0); +} + +static void tcb(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval *tv, void *userdata) { + fprintf(stderr, "TIME EVENT\n"); + +#ifdef GLIB_MAIN_LOOP + g_main_loop_quit(glib_main_loop); +#else + a->quit(a, 0); +#endif +} + +int main(int argc, char *argv[]) { + struct pa_mainloop_api *a; + struct pa_io_event *ioe; + struct pa_defer_event *de; + struct pa_time_event *te; + struct timeval tv; + +#ifdef GLIB_MAIN_LOOP + struct pa_glib_mainloop *g; + glib_main_loop = g_main_loop_new(NULL, FALSE); + assert(glib_main_loop); + + g = pa_glib_mainloop_new(NULL); + assert(g); + + a = pa_glib_mainloop_get_api(g); + assert(a); +#else + struct pa_mainloop *m; + + m = pa_mainloop_new(); + assert(m); + + a = pa_mainloop_get_api(m); + assert(a); +#endif + + ioe = a->io_new(a, 0, PA_IO_EVENT_INPUT, iocb, NULL); + assert(ioe); + + de = a->defer_new(a, dcb, NULL); + assert(de); + + gettimeofday(&tv, NULL); + tv.tv_sec += 10; + te = a->time_new(a, &tv, tcb, NULL); + +#ifdef GLIB_MAIN_LOOP + g_main_loop_run(glib_main_loop); +#else + pa_mainloop_run(m, NULL); +#endif + + a->time_free(te); + a->defer_free(de); + a->io_free(ioe); + +#ifdef GLIB_MAIN_LOOP + pa_glib_mainloop_free(g); + g_main_loop_unref(glib_main_loop); +#else + pa_mainloop_free(m); +#endif + + return 0; +} diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index 4c8e379ba..1b9e27836 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -25,6 +25,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + enum pa_io_event_flags { PA_IO_EVENT_NULL = 0, PA_IO_EVENT_INPUT = 1, @@ -64,4 +68,8 @@ struct pa_mainloop_api { void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(struct pa_mainloop_api*m, void *userdata), void *userdata); +#ifdef __cplusplus +} +#endif + #endif diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index ec2d528b0..e5c786f2b 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -24,6 +24,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + enum pa_stream_direction { PA_STREAM_PLAYBACK, PA_STREAM_RECORD, @@ -38,4 +42,8 @@ struct pa_buffer_attr { uint32_t fragsize; }; +#ifdef __cplusplus +} +#endif + #endif diff --git a/polyp/polyplib.h b/polyp/polyplib.h index 08e6a5a5a..9741fc937 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -28,6 +28,10 @@ #include "polyplib-def.h" #include "mainloop-api.h" +#ifdef __cplusplus +extern "C" { +#endif + struct pa_context; struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); @@ -127,4 +131,8 @@ void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void pa_context_get_source_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); +#ifdef __cplusplus +} +#endif + #endif diff --git a/polyp/sample.h b/polyp/sample.h index 01a4efcf2..250278798 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -25,6 +25,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + enum pa_sample_format { PA_SAMPLE_U8, PA_SAMPLE_ALAW, @@ -60,4 +64,8 @@ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_s #define PA_SAMPLE_SNPRINT_MAX_LENGTH 32 void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec); +#ifdef __cplusplus +} +#endif + #endif From 6f0936f6d0b4d415653c50760caaa65fa9bf78a3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 7 Aug 2004 10:42:39 +0000 Subject: [PATCH 0106/1514] cleanup priority management in main loop git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@107 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/glib-mainloop.c | 4 ++-- polyp/glib-test.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c index 3b9feaad2..0c46ab0c0 100644 --- a/polyp/glib-mainloop.c +++ b/polyp/glib-mainloop.c @@ -226,7 +226,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) e->source = g_timeout_source_new(msec_diff(tv, &now)); assert(e->source); g_source_set_callback(e->source, time_cb, e, NULL); - g_source_set_priority(e->source, G_PRIORITY_HIGH); + g_source_set_priority(e->source, G_PRIORITY_DEFAULT); g_source_attach(e->source, e->mainloop->glib_main_context); } else e->source = NULL; @@ -312,7 +312,7 @@ static void glib_defer_enable(struct pa_defer_event *e, int b) { assert(e->source); g_source_set_callback(e->source, idle_cb, e, NULL); g_source_attach(e->source, e->mainloop->glib_main_context); - g_source_set_priority(e->source, G_PRIORITY_HIGH_IDLE); + g_source_set_priority(e->source, G_PRIORITY_HIGH); } } diff --git a/polyp/glib-test.c b/polyp/glib-test.c index 99196c4a6..a03387e74 100644 --- a/polyp/glib-test.c +++ b/polyp/glib-test.c @@ -3,7 +3,7 @@ #include #include -/*#define GLIB_MAIN_LOOP*/ +#define GLIB_MAIN_LOOP #ifdef GLIB_MAIN_LOOP #include @@ -13,10 +13,13 @@ static GMainLoop* glib_main_loop = NULL; #include "mainloop.h" #endif +static struct pa_defer_event *de; + static void iocb(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { unsigned char c; read(fd, &c, sizeof(c)); fprintf(stderr, "IO EVENT: %c\n", c < 32 ? '.' : c); + a->defer_enable(de, 1); } static void dcb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { @@ -37,7 +40,6 @@ static void tcb(struct pa_mainloop_api*a, struct pa_time_event *e, const struct int main(int argc, char *argv[]) { struct pa_mainloop_api *a; struct pa_io_event *ioe; - struct pa_defer_event *de; struct pa_time_event *te; struct timeval tv; From 209c9dd88294be7aa9e7b552e69f98a5b0263aa8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 7 Aug 2004 10:43:33 +0000 Subject: [PATCH 0107/1514] rename mainloop testing tool git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@108 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/{glib-test.c => mainloop-test.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename polyp/{glib-test.c => mainloop-test.c} (100%) diff --git a/polyp/glib-test.c b/polyp/mainloop-test.c similarity index 100% rename from polyp/glib-test.c rename to polyp/mainloop-test.c From e9bed206d22c6985bce66d09867dc1256b9fc2e6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 7 Aug 2004 10:52:43 +0000 Subject: [PATCH 0108/1514] better mainloop test build system git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@109 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 13 +++++++++---- polyp/mainloop-test.c | 2 -- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 1be04f410..b1c911a4a 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -25,7 +25,7 @@ polypincludedir=$(includedir)/polyp EXTRA_DIST = polypaudio.pa depmod.py bin_PROGRAMS = polypaudio pacat pactl -noinst_PROGRAMS = pacat-simple parec-simple glib-test +noinst_PROGRAMS = pacat-simple parec-simple mainloop-test mainloop-test-glib polypinclude_HEADERS=polyplib.h \ polyplib-def.h \ @@ -287,6 +287,7 @@ libpolyp_mainloop_la_SOURCES = mainloop-api.h mainloop-api.c \ mainloop.c mainloop.h \ mainloop-signal.c mainloop-signal.h libpolyp_mainloop_la_CFLAGS = $(AM_CFLAGS) +libpolyp_mainloop_la_LIBADD = $(AM_LIBADD) libpolyp.la libpolyp_error_la_SOURCES = polyplib-error.c polyplib-error.h libpolyp_error_la_CFLAGS = $(AM_CFLAGS) @@ -315,9 +316,13 @@ libpolyp_mainloop_glib_la_SOURCES = glib-mainloop.h glib-mainloop.c libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB20_LIBS) -glib_test_SOURCES = glib-test.c -glib_test_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) -glib_test_LDADD = $(AM_LDADD) $(GLIB20_LIBS) libpolyp.la libpolyp-mainloop-glib.la +mainloop_test_SOURCES = mainloop-test.c +mainloop_test_CFLAGS = $(AM_CFLAGS) +mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop.la + +mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) +mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP +mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib.la if BUILD_LIBPOLYPCORE diff --git a/polyp/mainloop-test.c b/polyp/mainloop-test.c index a03387e74..31caaa033 100644 --- a/polyp/mainloop-test.c +++ b/polyp/mainloop-test.c @@ -3,8 +3,6 @@ #include #include -#define GLIB_MAIN_LOOP - #ifdef GLIB_MAIN_LOOP #include #include "glib-mainloop.h" From 37d930ac4afa9642b7b918b60ca0e0cb42b50682 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 10 Aug 2004 13:00:12 +0000 Subject: [PATCH 0109/1514] glib mainloop fix implement server status command support for sink_list/source_list in polyplib git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@110 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 4 +- polyp/clitext.c | 4 +- polyp/glib-mainloop.c | 12 ++- polyp/native-common.h | 2 + polyp/polypaudio.pa | 7 +- polyp/polyplib-error.h | 8 ++ polyp/polyplib.c | 195 +++++++++++++++++++++++++++++++++++++++- polyp/polyplib.h | 26 ++++-- polyp/protocol-native.c | 35 +++++++- polyp/sink.c | 1 + polyp/tagstruct.c | 4 +- polyp/util.c | 47 +++++++++- polyp/util.h | 3 + 13 files changed, 319 insertions(+), 29 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index b1c911a4a..8206bcf69 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -18,8 +18,8 @@ # USA. AM_CFLAGS=-ansi -D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" -I$(srcdir)/.. -AM_LDADD=-L. -AM_LIBADD=-L. +AM_LDADD=-L. -lpthread +AM_LIBADD=-L. -lpthread polypincludedir=$(includedir)/polyp diff --git a/polyp/clitext.c b/polyp/clitext.c index 6d2d62539..a530238fb 100644 --- a/polyp/clitext.c +++ b/polyp/clitext.c @@ -94,7 +94,7 @@ char *pa_sink_list_to_string(struct pa_core *c) { pa_strbuf_printf( s, " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", - !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', + c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, pa_sink_get_latency(sink), @@ -125,7 +125,7 @@ char *pa_source_list_to_string(struct pa_core *c) { char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; pa_sample_snprint(ss, sizeof(ss), &source->sample_spec); pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tsample_spec: <%s>\n", - !strcmp(source->name, c->default_source_name) ? '*' : ' ', + c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ', source->index, source->name, ss); diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c index 0c46ab0c0..9abb1e472 100644 --- a/polyp/glib-mainloop.c +++ b/polyp/glib-mainloop.c @@ -213,7 +213,7 @@ static gboolean time_cb(gpointer data) { static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) { struct timeval now; - assert(e && e->mainloop); + assert(e && e->mainloop && !e->dead); gettimeofday(&now, NULL); if (e->source) { @@ -233,7 +233,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) } static void glib_time_free(struct pa_time_event *e) { - assert(e && e->mainloop); + assert(e && e->mainloop && !e->dead); if (e->source) { g_source_destroy(e->source); @@ -317,8 +317,8 @@ static void glib_defer_enable(struct pa_defer_event *e, int b) { } static void glib_defer_free(struct pa_defer_event *e) { - assert(e && e->mainloop); - + assert(e && e->mainloop && !e->dead); + if (e->source) { g_source_destroy(e->source); g_source_unref(e->source); @@ -486,6 +486,10 @@ static gboolean free_dead_events(gpointer p) { free_defer_events(g->dead_defer_events); free_time_events(g->dead_time_events); + g->dead_io_events = NULL; + g->dead_defer_events = NULL; + g->dead_time_events = NULL; + g_source_destroy(g->cleanup_source); g_source_unref(g->cleanup_source); g->cleanup_source = NULL; diff --git a/polyp/native-common.h b/polyp/native-common.h index d8a2a5ab1..4a74ac449 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -47,6 +47,8 @@ enum { PA_COMMAND_FINISH_UPLOAD_STREAM, PA_COMMAND_PLAY_SAMPLE, PA_COMMAND_REMOVE_SAMPLE, + + PA_COMMAND_GET_SERVER_INFO, PA_COMMAND_GET_SINK_INFO, PA_COMMAND_GET_SINK_INFO_LIST, diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 715135657..8da20c62b 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -23,14 +23,15 @@ #load module-alsa-sink #load module-alsa-source device=plughw:1,0 #load module-oss device="/dev/dsp" sink_name=output source_name=input -#load module-oss-mmap device="/dev/dsp" +load module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +load module-pipe-sink # Load audio drivers automatically on access #autoload_sink_add output module-oss device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input -autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_sink_add output module-alsa-sink sink_name=output #autoload_source_add input module-alsa-source source_name=input diff --git a/polyp/polyplib-error.h b/polyp/polyplib-error.h index cb86864ad..d76ce6ffa 100644 --- a/polyp/polyplib-error.h +++ b/polyp/polyplib-error.h @@ -24,6 +24,14 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + const char* pa_strerror(uint32_t error); +#ifdef __cplusplus +} +#endif + #endif diff --git a/polyp/polyplib.c b/polyp/polyplib.c index 4d87fdb5b..e14f8cf96 100644 --- a/polyp/polyplib.c +++ b/polyp/polyplib.c @@ -88,7 +88,16 @@ struct pa_context { void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); void *remove_sample_userdata; - + + void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); + void *get_server_info_userdata; + + void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); + void *get_sink_info_userdata; + + void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); + void *get_source_info_userdata; + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; }; @@ -182,6 +191,15 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->remove_sample_callback = NULL; c->remove_sample_userdata = NULL; + c->get_server_info_callback = NULL; + c->get_server_info_userdata = NULL; + + c->get_sink_info_callback = NULL; + c->get_sink_info_userdata = NULL; + + c->get_source_info_callback = NULL; + c->get_source_info_userdata = NULL; + pa_check_for_sigpipe(); return c; } @@ -1055,12 +1073,12 @@ void pa_context_play_sample(struct pa_context *c, const char *name, const char * uint32_t tag; assert(c && name && *name && (!dev || *dev)); - if (!volume) - return; - c->play_sample_callback = cb; c->play_sample_userdata = userdata; + if (!cb) + return; + t = pa_tagstruct_new(NULL, 0); assert(t); pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); @@ -1106,6 +1124,9 @@ void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb) c->remove_sample_callback = cb; c->remove_sample_userdata = userdata; + if (!cb) + return; + t = pa_tagstruct_new(NULL, 0); assert(t); pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); @@ -1114,3 +1135,169 @@ void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb) pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); } + +static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_server_info i; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, NULL, c->get_server_info_userdata); + return; + } + + if (pa_tagstruct_gets(t, &i.server_name) < 0 || + pa_tagstruct_gets(t, &i.server_version) < 0 || + pa_tagstruct_gets(t, &i.user_name) < 0 || + pa_tagstruct_gets(t, &i.host_name) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, &i, c->get_server_info_userdata); +} + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_server_info_callback = cb; + c->get_server_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); +} + +static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_sink_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.monitor_source) < 0 || + pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || + pa_tagstruct_getu32(t, &i.latency) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); +} + +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_source_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || + pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); +} + +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} diff --git a/polyp/polyplib.h b/polyp/polyplib.h index 9741fc937..cc1251e2b 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -105,7 +105,7 @@ struct pa_sink_info { const char *name; uint32_t index; const char *description; - struct pa_sample_spec *sample_spec; + struct pa_sample_spec sample_spec; uint32_t owner_module; uint32_t volume; uint32_t monitor_source; @@ -113,24 +113,34 @@ struct pa_sink_info { uint32_t latency; }; -void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata); -void pa_context_get_sink_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata); -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, void *userdata), void *userdata); +void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); struct pa_source_info { const char *name; uint32_t index; const char *description; - struct pa_sample_spec *sample_spec; + struct pa_sample_spec sample_spec; uint32_t owner_module; uint32_t monitor_of_sink; const char *monitor_of_sink_name; }; -void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); -void pa_context_get_source_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, void *userdata), void *userdata); +void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +struct pa_server_info { + const char *user_name; + const char *host_name; + const char *server_version; + const char *server_name; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); + #ifdef __cplusplus } #endif diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 778677b31..abe6c8b75 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -42,6 +42,7 @@ #include "namereg.h" #include "scache.h" #include "xmalloc.h" +#include "util.h" struct connection; struct pa_protocol_native; @@ -129,6 +130,7 @@ static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint3 static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -156,6 +158,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_GET_SOURCE_INFO] = { command_get_info }, [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list }, + [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info }, }; /* structure management */ @@ -933,7 +936,7 @@ static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) { assert(t && sink); pa_tagstruct_putu32(t, sink->index); pa_tagstruct_puts(t, sink->name); - pa_tagstruct_puts(t, sink->description); + pa_tagstruct_puts(t, sink->description ? sink->description : ""); pa_tagstruct_put_sample_spec(t, &sink->sample_spec); pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1); pa_tagstruct_putu32(t, sink->volume); @@ -946,7 +949,7 @@ static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *sour assert(t && source); pa_tagstruct_putu32(t, source->index); pa_tagstruct_puts(t, source->name); - pa_tagstruct_puts(t, source->description); + pa_tagstruct_puts(t, source->description ? source->description : ""); pa_tagstruct_put_sample_spec(t, &source->sample_spec); pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1); pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1); @@ -1045,6 +1048,34 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin pa_pstream_send_tagstruct(c->pstream, reply); } +static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + struct pa_tagstruct *reply; + char txt[256]; + assert(c && t); + + if (!pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + pa_tagstruct_puts(reply, PACKAGE_NAME); + pa_tagstruct_puts(reply, PACKAGE_VERSION); + pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt))); + pa_tagstruct_puts(reply, pa_get_host_name(txt, sizeof(txt))); + pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec); + pa_pstream_send_tagstruct(c->pstream, reply); +} + /*** pstream callbacks ***/ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { diff --git a/polyp/sink.c b/polyp/sink.c index 6df92e76c..9628d8bd7 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -64,6 +64,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co assert(s->monitor_source); pa_xfree(n); s->monitor_source->monitor_of = s; + s->monitor_source->description = pa_sprintf_malloc("Monitor source of sink '%s'", s->name); s->volume = PA_VOLUME_NORM; diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index cb93a9c4d..9578a9eb6 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -83,10 +83,10 @@ uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l) { static void extend(struct pa_tagstruct*t, size_t l) { assert(t && t->dynamic); - if (l <= t->allocated) + if (t->length+l <= t->allocated) return; - t->data = pa_xrealloc(t->data, t->allocated = l+100); + t->data = pa_xrealloc(t->data, t->allocated = t->length+l+100); } void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s) { diff --git a/polyp/util.c b/polyp/util.c index 98d910759..70766a068 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -33,6 +33,9 @@ #include #include #include +#include +#include +#include #include "util.h" #include "xmalloc.h" @@ -109,14 +112,27 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) { void pa_check_for_sigpipe(void) { struct sigaction sa; + sigset_t set; + if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) { + if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) { + fprintf(stderr, __FILE__": sigprocmask() failed: %s\n", strerror(errno)); + return; + } + } + + if (sigismember(&set, SIGPIPE)) + return; + if (sigaction(SIGPIPE, NULL, &sa) < 0) { fprintf(stderr, __FILE__": sigaction() failed: %s\n", strerror(errno)); return; } - if (sa.sa_handler == SIG_DFL) - fprintf(stderr, "polypaudio: WARNING: SIGPIPE is not trapped. This might cause malfunction!\n"); + if (sa.sa_handler != SIG_DFL) + return; + + fprintf(stderr, "polypaudio: WARNING: SIGPIPE is not trapped. This might cause malfunction!\n"); } /* The following is based on an example from the GNU libc documentation */ @@ -145,3 +161,30 @@ char *pa_sprintf_malloc(const char *format, ...) { size *= 2; } } + +char *pa_get_user_name(char *s, size_t l) { + struct passwd pw, *r; + char buf[1024]; + char *p; + + if (!(p = getenv("USER"))) + if (!(p = getenv("LOGNAME"))) + if (!(p = getenv("USERNAME"))) { + + if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { + snprintf(s, l, "%lu", (unsigned long) getuid()); + return s; + } + + p = r->pw_name; + } + + snprintf(s, l, "%s", p); + return s; +} + +char *pa_get_host_name(char *s, size_t l) { + gethostname(s, l); + s[l-1] = 0; + return s; +} diff --git a/polyp/util.h b/polyp/util.h index 96fde11c2..7dd7b7de4 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -35,4 +35,7 @@ void pa_check_for_sigpipe(void); char *pa_sprintf_malloc(const char *format, ...) __attribute__ ((format (printf, 1, 2))); +char *pa_get_user_name(char *s, size_t l); +char *pa_get_host_name(char *s, size_t l); + #endif From fc618e9f316a1ec2b48a7981db41a121c79f0c27 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 10 Aug 2004 15:11:37 +0000 Subject: [PATCH 0110/1514] compile fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@111 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 8206bcf69..254af28a0 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -291,6 +291,7 @@ libpolyp_mainloop_la_LIBADD = $(AM_LIBADD) libpolyp.la libpolyp_error_la_SOURCES = polyplib-error.c polyplib-error.h libpolyp_error_la_CFLAGS = $(AM_CFLAGS) +libpolyp_error_la_LIBADD = $(AM_LIBADD) libpolyp.la libpolyp_simple_la_SOURCES = polyplib-simple.c polyplib-simple.h libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) @@ -305,11 +306,11 @@ pactl_LDADD = $(AM_LDADD) libpolyp.la libpolyp-error.la libpolyp-mainloop.la $(L pactl_CFLAGS = $(AM_CFLAGS) $(LIBSDNFILE_CFLAGS) pacat_simple_SOURCES = pacat-simple.c -pacat_simple_LDADD = $(AM_LDADD) libpolyp-simple.la libpolyp-error.la +pacat_simple_LDADD = $(AM_LDADD) libpolyp.la libpolyp-simple.la libpolyp-error.la pacat_simple_CFLAGS = $(AM_CFLAGS) parec_simple_SOURCES = parec-simple.c -parec_simple_LDADD = $(AM_LDADD) libpolyp-simple.la libpolyp-error.la +parec_simple_LDADD = $(AM_LDADD) libpolyp.la libpolyp-simple.la libpolyp-error.la parec_simple_CFLAGS = $(AM_CFLAGS) libpolyp_mainloop_glib_la_SOURCES = glib-mainloop.h glib-mainloop.c @@ -318,7 +319,7 @@ libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB20_LI mainloop_test_SOURCES = mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) -mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop.la +mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop.la libpolyp.la mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP From 3d374e9f678133638e661cadf73d4ef7ddcfe6eb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 11 Aug 2004 00:11:12 +0000 Subject: [PATCH 0111/1514] add subscription subsystem git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@112 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 3 +- polyp/client.c | 3 + polyp/core.c | 8 ++- polyp/core.h | 4 ++ polyp/module.c | 5 ++ polyp/sink-input.c | 5 ++ polyp/sink.c | 5 ++ polyp/source-output.c | 5 ++ polyp/source.c | 5 ++ polyp/subscribe.c | 152 ++++++++++++++++++++++++++++++++++++++++++ polyp/subscribe.h | 43 ++++++++++++ 11 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 polyp/subscribe.c create mode 100644 polyp/subscribe.h diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 254af28a0..ce753da47 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -115,7 +115,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ sound-file.c sound-file.h \ play-memchunk.c play-memchunk.h \ autoload.c autoload.h \ - xmalloc.c xmalloc.h + xmalloc.c xmalloc.h \ + subscribe.h subscribe.c polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) diff --git a/polyp/client.c b/polyp/client.c index 83a6264de..809f97615 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -30,6 +30,7 @@ #include "client.h" #include "xmalloc.h" +#include "subscribe.h" struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, char *name) { struct pa_client *c; @@ -49,6 +50,7 @@ struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, assert(c->index != PA_IDXSET_INVALID && r >= 0); fprintf(stderr, "client: created %u \"%s\"\n", c->index, c->name); + pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); return c; } @@ -58,6 +60,7 @@ void pa_client_free(struct pa_client *c) { pa_idxset_remove_by_data(c->core->clients, c, NULL); fprintf(stderr, "client: freed %u \"%s\"\n", c->index, c->name); + pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_xfree(c->name); pa_xfree(c); } diff --git a/polyp/core.c b/polyp/core.c index 0444fa967..55944aad8 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -36,6 +36,7 @@ #include "scache.h" #include "autoload.h" #include "xmalloc.h" +#include "subscribe.h" struct pa_core* pa_core_new(struct pa_mainloop_api *m) { struct pa_core* c; @@ -63,6 +64,10 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->auto_unload_time = 20; c->auto_unload_event = NULL; + + c->subscription_defer_event = NULL; + c->subscription_event_queue = NULL; + c->subscriptions = NULL; pa_check_for_sigpipe(); @@ -93,7 +98,8 @@ void pa_core_free(struct pa_core *c) { pa_namereg_free(c); pa_scache_free(c); pa_autoload_free(c); - + pa_subscription_free_all(c); + pa_xfree(c->default_source_name); pa_xfree(c->default_sink_name); diff --git a/polyp/core.h b/polyp/core.h index e1e48cbcb..436917714 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -39,6 +39,10 @@ struct pa_core { struct pa_sample_spec default_sample_spec; int auto_unload_time; struct pa_time_event *auto_unload_event; + + struct pa_defer_event *subscription_defer_event; + struct pa_queue *subscription_event_queue; + struct pa_subscription *subscriptions; }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/polyp/module.c b/polyp/module.c index 83bfa8007..849afca4d 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -32,6 +32,7 @@ #include "module.h" #include "xmalloc.h" +#include "subscribe.h" #define UNLOAD_POLL_TIME 10 @@ -92,6 +93,8 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char assert(r >= 0 && m->index != PA_IDXSET_INVALID); fprintf(stderr, "module: loaded %u \"%s\" with argument \"%s\".\n", m->index, m->name, m->argument); + + pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_NEW, m->index); return m; @@ -117,6 +120,8 @@ static void pa_module_free(struct pa_module *m) { fprintf(stderr, "module: unloaded %u \"%s\".\n", m->index, m->name); + pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE, m->index); + pa_xfree(m->name); pa_xfree(m->argument); pa_xfree(m); diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 04a2f0200..dd7469e02 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -31,6 +31,7 @@ #include "sink-input.h" #include "sample-util.h" #include "xmalloc.h" +#include "subscribe.h" #define CONVERT_BUFFER_LENGTH 4096 @@ -72,6 +73,8 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con pa_sample_snprint(st, sizeof(st), spec); fprintf(stderr, "sink-input: created %u \"%s\" on %u with sample spec \"%s\"\n", i->index, i->name, s->index, st); + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); return i; } @@ -87,6 +90,8 @@ void pa_sink_input_free(struct pa_sink_input* i) { pa_memblock_unref(i->resampled_chunk.memblock); if (i->resampler) pa_resampler_free(i->resampler); + + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index); pa_xfree(i->name); pa_xfree(i); diff --git a/polyp/sink.c b/polyp/sink.c index 9628d8bd7..7e0e15cdd 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -34,6 +34,7 @@ #include "util.h" #include "sample-util.h" #include "xmalloc.h" +#include "subscribe.h" #define MAX_MIX_CHANNELS 32 @@ -77,6 +78,8 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co pa_sample_snprint(st, sizeof(st), spec); fprintf(stderr, "sink: created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); + + pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); return s; } @@ -98,6 +101,8 @@ void pa_sink_free(struct pa_sink *s) { pa_idxset_remove_by_data(s->core->sinks, s, NULL); fprintf(stderr, "sink: freed %u \"%s\"\n", s->index, s->name); + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); pa_xfree(s->name); pa_xfree(s->description); diff --git a/polyp/source-output.c b/polyp/source-output.c index 07901fa86..c53831c7b 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -29,6 +29,7 @@ #include "source-output.h" #include "xmalloc.h" +#include "subscribe.h" struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec) { struct pa_source_output *o; @@ -57,6 +58,8 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n assert(r == 0 && o->index != PA_IDXSET_INVALID); r = pa_idxset_put(s->outputs, o, NULL); assert(r == 0); + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index); return o; } @@ -70,6 +73,8 @@ void pa_source_output_free(struct pa_source_output* o) { if (o->resampler) pa_resampler_free(o->resampler); + + pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index); pa_xfree(o->name); pa_xfree(o); diff --git a/polyp/source.c b/polyp/source.c index 65c90e9a5..2c6116513 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -32,6 +32,7 @@ #include "source-output.h" #include "namereg.h" #include "xmalloc.h" +#include "subscribe.h" struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) { struct pa_source *s; @@ -63,6 +64,8 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail pa_sample_snprint(st, sizeof(st), spec); fprintf(stderr, "source: created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); + + pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); return s; } @@ -84,6 +87,8 @@ void pa_source_free(struct pa_source *s) { fprintf(stderr, "source: freed %u \"%s\"\n", s->index, s->name); + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + pa_xfree(s->name); pa_xfree(s->description); pa_xfree(s); diff --git a/polyp/subscribe.c b/polyp/subscribe.c new file mode 100644 index 000000000..541657ae0 --- /dev/null +++ b/polyp/subscribe.c @@ -0,0 +1,152 @@ +#include +#include + +#include "queue.h" +#include "subscribe.h" +#include "xmalloc.h" + +struct pa_subscription { + struct pa_core *core; + int dead; + void (*callback)(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void *userdata; + enum pa_subscription_mask mask; + + struct pa_subscription *prev, *next; +}; + +struct pa_subscription_event { + enum pa_subscription_event_type type; + uint32_t index; +}; + +static void sched_event(struct pa_core *c); + +struct pa_subscription* pa_subscription_new(struct pa_core *c, enum pa_subscription_mask m, void (*callback)(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + struct pa_subscription *s; + assert(c); + + s = pa_xmalloc(sizeof(struct pa_subscription)); + s->core = c; + s->dead = 0; + s->callback = callback; + s->userdata = userdata; + s->mask = m; + + if ((s->next = c->subscriptions)) + s->next->prev = s; + s->prev = NULL; + c->subscriptions = s; + return NULL; +} + +void pa_subscription_free(struct pa_subscription*s) { + assert(s && !s->dead); + s->dead = 1; + sched_event(s->core); +} + +static void free_item(struct pa_subscription *s) { + assert(s && s->core); + + if (s->prev) + s->prev->next = s->next; + else + s->core->subscriptions = s->next; + + if (s->next) + s->next->prev = s->prev; + + pa_xfree(s); +} + +void pa_subscription_free_all(struct pa_core *c) { + struct pa_subscription_event *e; + assert(c); + + while (c->subscriptions) + free_item(c->subscriptions); + + if (c->subscription_event_queue) { + while ((e = pa_queue_pop(c->subscription_event_queue))) + pa_xfree(e); + + pa_queue_free(c->subscription_event_queue, NULL, NULL); + c->subscription_event_queue = NULL; + } + + if (c->subscription_defer_event) { + c->mainloop->defer_free(c->subscription_defer_event); + c->subscription_defer_event = NULL; + } +} + +static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { + struct pa_core *c = userdata; + struct pa_subscription *s; + assert(c && c->subscription_defer_event == e && c->mainloop == m); + + c->mainloop->defer_enable(c->subscription_defer_event, 0); + + + /* Dispatch queued events */ + + if (c->subscription_event_queue) { + struct pa_subscription_event *e; + + while ((e = pa_queue_pop(c->subscription_event_queue))) { + struct pa_subscription *s; + + for (s = c->subscriptions; s; s = s->next) { + if (!s->dead && pa_subscription_match_flags(s->mask, e->type)) + s->callback(c, e->type, e->index, s->userdata); + } + + pa_xfree(e); + } + } + + /* Remove dead subscriptions */ + + s = c->subscriptions; + while (s) { + struct pa_subscription *n = s->next; + if (s->dead) + free_item(s); + s = n; + } +} + +static void sched_event(struct pa_core *c) { + assert(c); + + if (!c->subscription_defer_event) { + c->subscription_defer_event = c->mainloop->defer_new(c->mainloop, defer_cb, c); + assert(c->subscription_defer_event); + } + + c->mainloop->defer_enable(c->subscription_defer_event, 1); +} + + +void pa_subscription_post(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index) { + struct pa_subscription_event *e; + assert(c); + + e = pa_xmalloc(sizeof(struct pa_subscription_event)); + e->type = t; + e->index = index; + + if (!c->subscription_event_queue) { + c->subscription_event_queue = pa_queue_new(); + assert(c->subscription_event_queue); + } + + pa_queue_push(c->subscription_event_queue, e); + sched_event(c); +} + + +int pa_subscription_match_flags(enum pa_subscription_mask m, enum pa_subscription_event_type t) { + return !!(m & (1 >> (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK))); +} diff --git a/polyp/subscribe.h b/polyp/subscribe.h new file mode 100644 index 000000000..1561249fb --- /dev/null +++ b/polyp/subscribe.h @@ -0,0 +1,43 @@ +#ifndef foosubscribehfoo +#define foosubscribehfoo + +#include "core.h" + +enum pa_subscription_mask { + PA_SUBSCRIPTION_FACILITY_SINK = 1, + PA_SUBSCRIPTION_FACILITY_SOURCE = 2, + PA_SUBSCRIPTION_FACILITY_SINK_INPUT = 4, + PA_SUBSCRIPTION_FACILITY_SOURCE_OUTPUT = 8, + PA_SUBSCRIPTION_FACILITY_MODULE = 16, + PA_SUBSCRIPTION_FACILITY_CLIENT = 32, + PA_SUBSCRIPTION_FACILITY_SAMPLE_CACHE = 64, +}; + +enum pa_subscription_event_type { + PA_SUBSCRIPTION_EVENT_SINK = 0, + PA_SUBSCRIPTION_EVENT_SOURCE = 1, + PA_SUBSCRIPTION_EVENT_SINK_INPUT = 2, + PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 3, + PA_SUBSCRIPTION_EVENT_MODULE = 4, + PA_SUBSCRIPTION_EVENT_CLIENT = 5, + PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6, + PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 7, + + PA_SUBSCRIPTION_EVENT_NEW = 0, + PA_SUBSCRIPTION_EVENT_CHANGE = 16, + PA_SUBSCRIPTION_EVENT_REMOVE = 32, + PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32, +}; + +struct pa_subscription; +struct pa_subscription_event; + +struct pa_subscription* pa_subscription_new(struct pa_core *c, enum pa_subscription_mask m, void (*callback)(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); +void pa_subscription_free(struct pa_subscription*s); +void pa_subscription_free_all(struct pa_core *c); + +void pa_subscription_post(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index); + +int pa_subscription_match_flags(enum pa_subscription_mask m, enum pa_subscription_event_type e); + +#endif From b297d0b59a7d44f14073daf96a6206763a0c307b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 11 Aug 2004 00:12:04 +0000 Subject: [PATCH 0112/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@113 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 7cf36b086..276cccfc7 100644 --- a/doc/todo +++ b/doc/todo @@ -4,6 +4,7 @@ - future cancellation - make mcalign merge chunks +- ref counting foo - doxygen From cbfaf40b45f712c1cdcc6b7cb694f907ce0e7f8f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 11 Aug 2004 15:11:26 +0000 Subject: [PATCH 0113/1514] info and subscription work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@114 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/native-common.h | 28 ++++++++++++++ polyp/polypaudio.pa | 8 ++-- polyp/polyplib-def.h | 4 +- polyp/polyplib.c | 85 +++++++++++++++++++++++++++++++++++++++++ polyp/polyplib.h | 8 ++-- polyp/protocol-native.c | 52 +++++++++++++++++++++++++ polyp/scache.c | 7 ++++ polyp/scache.h | 1 + polyp/subscribe.c | 51 ++++++++++++++++++++++--- polyp/subscribe.h | 29 +------------- 10 files changed, 232 insertions(+), 41 deletions(-) diff --git a/polyp/native-common.h b/polyp/native-common.h index 4a74ac449..5e69c805c 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -87,4 +87,32 @@ enum { #define PA_NATIVE_COOKIE_LENGTH 256 #define PA_NATIVE_COOKIE_FILE ".polypaudio-cookie" +enum pa_subscription_mask { + PA_SUBSCRIPTION_FACILITY_SINK = 1, + PA_SUBSCRIPTION_FACILITY_SOURCE = 2, + PA_SUBSCRIPTION_FACILITY_SINK_INPUT = 4, + PA_SUBSCRIPTION_FACILITY_SOURCE_OUTPUT = 8, + PA_SUBSCRIPTION_FACILITY_MODULE = 16, + PA_SUBSCRIPTION_FACILITY_CLIENT = 32, + PA_SUBSCRIPTION_FACILITY_SAMPLE_CACHE = 64, +}; + +enum pa_subscription_event_type { + PA_SUBSCRIPTION_EVENT_SINK = 0, + PA_SUBSCRIPTION_EVENT_SOURCE = 1, + PA_SUBSCRIPTION_EVENT_SINK_INPUT = 2, + PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 3, + PA_SUBSCRIPTION_EVENT_MODULE = 4, + PA_SUBSCRIPTION_EVENT_CLIENT = 5, + PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6, + PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 7, + + PA_SUBSCRIPTION_EVENT_NEW = 0, + PA_SUBSCRIPTION_EVENT_CHANGE = 16, + PA_SUBSCRIPTION_EVENT_REMOVE = 32, + PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32, +}; + +#define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) + #endif diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 8da20c62b..d57f81275 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -23,8 +23,8 @@ #load module-alsa-sink #load module-alsa-source device=plughw:1,0 #load module-oss device="/dev/dsp" sink_name=output source_name=input -load module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -load module-pipe-sink +#load module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#load module-pipe-sink # Load audio drivers automatically on access @@ -32,8 +32,8 @@ load module-pipe-sink #autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input #autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#autoload_sink_add output module-alsa-sink sink_name=output -#autoload_source_add input module-alsa-source source_name=input +autoload_sink_add output module-alsa-sink sink_name=output +autoload_source_add input module-alsa-source source_name=input # Load several protocols load module-esound-protocol-tcp diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index e5c786f2b..d96c68995 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -28,6 +28,8 @@ extern "C" { #endif +#include "native-common.h" + enum pa_stream_direction { PA_STREAM_PLAYBACK, PA_STREAM_RECORD, @@ -41,7 +43,7 @@ struct pa_buffer_attr { uint32_t minreq; uint32_t fragsize; }; - + #ifdef __cplusplus } #endif diff --git a/polyp/polyplib.c b/polyp/polyplib.c index e14f8cf96..b77d24ea5 100644 --- a/polyp/polyplib.c +++ b/polyp/polyplib.c @@ -98,6 +98,10 @@ struct pa_context { void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); void *get_source_info_userdata; + void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void *subscribe_userdata; + enum pa_subscription_mask subscribe_mask; + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; }; @@ -140,6 +144,7 @@ struct pa_stream { static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -152,6 +157,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = { command_request }, [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, }; struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { @@ -200,6 +206,9 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->get_source_info_callback = NULL; c->get_source_info_userdata = NULL; + c->subscribe_callback = NULL; + c->subscribe_userdata = NULL; + pa_check_for_sigpipe(); return c; } @@ -1301,3 +1310,79 @@ void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_ pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); } + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + struct pa_tagstruct *t; + assert(c); + + c->subscribe_callback = cb; + c->subscribe_userdata = userdata; + c->subscribe_mask = m; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); + pa_tagstruct_putu32(t, c->ctag++); + pa_tagstruct_putu32(t, cb ? m : 0); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + enum pa_subscription_event_type e; + uint32_t index; + assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); + + if (pa_tagstruct_getu32(t, &e) < 0 || + pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) + c->subscribe_callback(c, e, index, c->subscribe_userdata); +} + +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} diff --git a/polyp/polyplib.h b/polyp/polyplib.h index cc1251e2b..8708cd723 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -114,7 +114,7 @@ struct pa_sink_info { }; void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); struct pa_source_info { @@ -128,7 +128,7 @@ struct pa_source_info { }; void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_by_id(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); struct pa_server_info { @@ -140,7 +140,9 @@ struct pa_server_info { }; void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); - + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); + #ifdef __cplusplus } #endif diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index abe6c8b75..caaa13962 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -43,6 +43,7 @@ #include "scache.h" #include "xmalloc.h" #include "util.h" +#include "subscribe.h" struct connection; struct pa_protocol_native; @@ -93,6 +94,7 @@ struct connection { struct pa_pdispatch *pdispatch; struct pa_idxset *record_streams, *output_streams; uint32_t rrobin_index; + struct pa_subscription *subscription; }; struct pa_protocol_native { @@ -131,6 +133,7 @@ static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uin static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -159,6 +162,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info }, + [PA_COMMAND_SUBSCRIBE] = { command_subscribe }, }; /* structure management */ @@ -301,6 +305,10 @@ static void connection_free(struct connection *c) { pa_pdispatch_free(c->pdispatch); pa_pstream_free(c->pstream); pa_client_free(c->client); + + if (c->subscription) + pa_subscription_free(c->subscription); + pa_xfree(c); } @@ -1076,6 +1084,49 @@ static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, u pa_pstream_send_tagstruct(c->pstream, reply); } +static void subscription_cb(struct pa_core *core, enum pa_subscription_event_type e, uint32_t index, void *userdata) { + struct pa_tagstruct *t; + struct connection *c = userdata; + assert(c && core); + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_putu32(t, e); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + enum pa_subscription_mask m; + assert(c && t); + + if (pa_tagstruct_getu32(t, &m) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (c->subscription) + pa_subscription_free(c->subscription); + + if (m != 0) { + c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c); + assert(c->subscription); + } else + c->subscription = NULL; + + pa_pstream_send_simple_ack(c->pstream, tag); + +} + /*** pstream callbacks ***/ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { @@ -1197,6 +1248,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo assert(c->record_streams && c->output_streams); c->rrobin_index = PA_IDXSET_INVALID; + c->subscription = NULL; pa_idxset_put(p->connections, c, NULL); } diff --git a/polyp/scache.c b/polyp/scache.c index fd7b74e54..9485a2b6e 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -9,9 +9,11 @@ #include "sample-util.h" #include "play-memchunk.h" #include "xmalloc.h" +#include "subscribe.h" static void free_entry(struct pa_scache_entry *e) { assert(e); + pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_REMOVE, e->index); pa_xfree(e->name); if (e->memchunk.memblock) pa_memblock_unref(e->memchunk.memblock); @@ -27,10 +29,12 @@ void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_sp put = 0; if (e->memchunk.memblock) pa_memblock_unref(e->memchunk.memblock); + assert(e->core == c); } else { put = 1; e = pa_xmalloc(sizeof(struct pa_scache_entry)); e->name = pa_xstrdup(name); + e->core = c; } e->volume = 0x100; @@ -61,6 +65,8 @@ void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_sp pa_idxset_put(c->scache_idxset, e, &e->index); pa_hashmap_put(c->scache_hashmap, e->name, e); + + pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index); } if (index) @@ -77,6 +83,7 @@ int pa_scache_remove_item(struct pa_core *c, const char *name) { pa_hashmap_remove(c->scache_hashmap, name); if (pa_idxset_remove_by_data(c->scache_idxset, e, NULL) != e) assert(0); + free_entry(e); return 0; } diff --git a/polyp/scache.h b/polyp/scache.h index a1454ceac..15cd5d488 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -6,6 +6,7 @@ #include "sink.h" struct pa_scache_entry { + struct pa_core *core; uint32_t index; char *name; uint32_t volume; diff --git a/polyp/subscribe.c b/polyp/subscribe.c index 541657ae0..104566d1b 100644 --- a/polyp/subscribe.c +++ b/polyp/subscribe.c @@ -37,7 +37,7 @@ struct pa_subscription* pa_subscription_new(struct pa_core *c, enum pa_subscript s->next->prev = s; s->prev = NULL; c->subscriptions = s; - return NULL; + return s; } void pa_subscription_free(struct pa_subscription*s) { @@ -81,6 +81,49 @@ void pa_subscription_free_all(struct pa_core *c) { } } +/*static void dump_event(struct pa_subscription_event*e) { + switch (e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { + case PA_SUBSCRIPTION_EVENT_SINK: + fprintf(stderr, "SINK_EVENT"); + break; + case PA_SUBSCRIPTION_EVENT_SOURCE: + fprintf(stderr, "SOURCE_EVENT"); + break; + case PA_SUBSCRIPTION_EVENT_SINK_INPUT: + fprintf(stderr, "SINK_INPUT_EVENT"); + break; + case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: + fprintf(stderr, "SOURCE_OUTPUT_EVENT"); + break; + case PA_SUBSCRIPTION_EVENT_MODULE: + fprintf(stderr, "MODULE_EVENT"); + break; + case PA_SUBSCRIPTION_EVENT_CLIENT: + fprintf(stderr, "CLIENT_EVENT"); + break; + default: + fprintf(stderr, "OTHER"); + break; + } + + switch (e->type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) { + case PA_SUBSCRIPTION_EVENT_NEW: + fprintf(stderr, " NEW"); + break; + case PA_SUBSCRIPTION_EVENT_CHANGE: + fprintf(stderr, " CHANGE"); + break; + case PA_SUBSCRIPTION_EVENT_REMOVE: + fprintf(stderr, " REMOVE"); + break; + default: + fprintf(stderr, " OTHER"); + break; + } + + fprintf(stderr, " %u\n", e->index); +}*/ + static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { struct pa_core *c = userdata; struct pa_subscription *s; @@ -98,6 +141,7 @@ static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void * struct pa_subscription *s; for (s = c->subscriptions; s; s = s->next) { + if (!s->dead && pa_subscription_match_flags(s->mask, e->type)) s->callback(c, e->type, e->index, s->userdata); } @@ -119,7 +163,7 @@ static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void * static void sched_event(struct pa_core *c) { assert(c); - + if (!c->subscription_defer_event) { c->subscription_defer_event = c->mainloop->defer_new(c->mainloop, defer_cb, c); assert(c->subscription_defer_event); @@ -147,6 +191,3 @@ void pa_subscription_post(struct pa_core *c, enum pa_subscription_event_type t, } -int pa_subscription_match_flags(enum pa_subscription_mask m, enum pa_subscription_event_type t) { - return !!(m & (1 >> (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK))); -} diff --git a/polyp/subscribe.h b/polyp/subscribe.h index 1561249fb..a88677d2d 100644 --- a/polyp/subscribe.h +++ b/polyp/subscribe.h @@ -2,33 +2,8 @@ #define foosubscribehfoo #include "core.h" +#include "native-common.h" -enum pa_subscription_mask { - PA_SUBSCRIPTION_FACILITY_SINK = 1, - PA_SUBSCRIPTION_FACILITY_SOURCE = 2, - PA_SUBSCRIPTION_FACILITY_SINK_INPUT = 4, - PA_SUBSCRIPTION_FACILITY_SOURCE_OUTPUT = 8, - PA_SUBSCRIPTION_FACILITY_MODULE = 16, - PA_SUBSCRIPTION_FACILITY_CLIENT = 32, - PA_SUBSCRIPTION_FACILITY_SAMPLE_CACHE = 64, -}; - -enum pa_subscription_event_type { - PA_SUBSCRIPTION_EVENT_SINK = 0, - PA_SUBSCRIPTION_EVENT_SOURCE = 1, - PA_SUBSCRIPTION_EVENT_SINK_INPUT = 2, - PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 3, - PA_SUBSCRIPTION_EVENT_MODULE = 4, - PA_SUBSCRIPTION_EVENT_CLIENT = 5, - PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6, - PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 7, - - PA_SUBSCRIPTION_EVENT_NEW = 0, - PA_SUBSCRIPTION_EVENT_CHANGE = 16, - PA_SUBSCRIPTION_EVENT_REMOVE = 32, - PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32, -}; - struct pa_subscription; struct pa_subscription_event; @@ -38,6 +13,4 @@ void pa_subscription_free_all(struct pa_core *c); void pa_subscription_post(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index); -int pa_subscription_match_flags(enum pa_subscription_mask m, enum pa_subscription_event_type e); - #endif From 886041aab88930108953af0e9e14b39ec9d03809 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 12 Aug 2004 23:25:28 +0000 Subject: [PATCH 0114/1514] add more subscription events add support for clients/modules in native protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@115 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/cli-command.c | 2 +- polyp/module.c | 3 + polyp/native-common.h | 2 + polyp/polypaudio.pa | 6 +- polyp/polyplib.c | 162 ++++++++++++++++++++++++++++++++++++++++ polyp/polyplib.h | 19 +++++ polyp/protocol-native.c | 57 +++++++++++--- polyp/sink.c | 9 ++- polyp/sink.h | 2 + 9 files changed, 248 insertions(+), 14 deletions(-) diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 6386d4e45..1d454f2a5 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -300,7 +300,7 @@ static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, return -1; } - sink->volume = (uint32_t) volume; + pa_sink_set_volume(sink, (uint32_t) volume); return 0; } diff --git a/polyp/module.c b/polyp/module.c index 849afca4d..1deb7cde8 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -218,6 +218,9 @@ void pa_module_unload_request(struct pa_core *c, struct pa_module *m) { void pa_module_set_used(struct pa_module*m, int used) { assert(m); + if (m->n_used != used) + pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_CHANGE, m->index); + if (m->n_used != used && used == 0) time(&m->last_used_time); diff --git a/polyp/native-common.h b/polyp/native-common.h index 5e69c805c..4d5ab53d7 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -55,7 +55,9 @@ enum { PA_COMMAND_GET_SOURCE_INFO, PA_COMMAND_GET_SOURCE_INFO_LIST, PA_COMMAND_GET_MODULE_INFO, + PA_COMMAND_GET_MODULE_INFO_LIST, PA_COMMAND_GET_CLIENT_INFO, + PA_COMMAND_GET_CLIENT_INFO_LIST, PA_COMMAND_GET_SINK_INPUT_INFO, PA_COMMAND_GET_SOURCE_OUTPUT_INFO, PA_COMMAND_GET_SAMPLE_INFO, diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index d57f81275..9f8cf8602 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -24,7 +24,7 @@ #load module-alsa-source device=plughw:1,0 #load module-oss device="/dev/dsp" sink_name=output source_name=input #load module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#load module-pipe-sink +load module-pipe-sink # Load audio drivers automatically on access @@ -32,8 +32,8 @@ #autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input #autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -autoload_sink_add output module-alsa-sink sink_name=output -autoload_source_add input module-alsa-source source_name=input +#autoload_sink_add output module-alsa-sink sink_name=output +#autoload_source_add input module-alsa-source source_name=input # Load several protocols load module-esound-protocol-tcp diff --git a/polyp/polyplib.c b/polyp/polyplib.c index b77d24ea5..35001d3d3 100644 --- a/polyp/polyplib.c +++ b/polyp/polyplib.c @@ -102,6 +102,12 @@ struct pa_context { void *subscribe_userdata; enum pa_subscription_mask subscribe_mask; + void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); + void *get_client_info_userdata; + + void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); + void *get_module_info_userdata; + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; }; @@ -209,6 +215,12 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->subscribe_callback = NULL; c->subscribe_userdata = NULL; + c->get_client_info_callback = NULL; + c->get_client_info_userdata = NULL; + + c->get_module_info_callback = NULL; + c->get_module_info_userdata = NULL; + pa_check_for_sigpipe(); return c; } @@ -1386,3 +1398,153 @@ void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, v pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); } + +static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_client_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.protocol_name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); +} + + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_module_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0 || + pa_tagstruct_getu32(t, &i.n_used) < 0 || + pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); +} + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} + +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} diff --git a/polyp/polyplib.h b/polyp/polyplib.h index 8708cd723..590b978f8 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -141,6 +141,25 @@ struct pa_server_info { void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); +struct pa_module_info { + uint32_t index; + const char*name, *argument; + uint32_t n_used, auto_unload; +}; + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); + +struct pa_client_info { + uint32_t index; + const char *name; + uint32_t owner_module; + const char *protocol_name; +}; + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); + void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); #ifdef __cplusplus diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index caaa13962..247851fc1 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -159,8 +159,12 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REMOVE_SAMPLE] = { command_remove_sample }, [PA_COMMAND_GET_SINK_INFO] = { command_get_info }, [PA_COMMAND_GET_SOURCE_INFO] = { command_get_info }, + [PA_COMMAND_GET_CLIENT_INFO] = { command_get_info }, + [PA_COMMAND_GET_MODULE_INFO] = { command_get_info }, [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list }, + [PA_COMMAND_GET_MODULE_INFO_LIST] = { command_get_info_list }, + [PA_COMMAND_GET_CLIENT_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info }, [PA_COMMAND_SUBSCRIBE] = { command_subscribe }, }; @@ -964,11 +968,30 @@ static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *sour pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : ""); } +static void client_fill_tagstruct(struct pa_tagstruct *t, struct pa_client *client) { + assert(t && client); + pa_tagstruct_putu32(t, client->index); + pa_tagstruct_puts(t, client->name); + pa_tagstruct_puts(t, client->protocol_name); + pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1); +} + +static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *module) { + assert(t && module); + pa_tagstruct_putu32(t, module->index); + pa_tagstruct_puts(t, module->name); + pa_tagstruct_puts(t, module->argument ? module->argument : ""); + pa_tagstruct_putu32(t, module->n_used); + pa_tagstruct_putu32(t, module->auto_unload); +} + static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t index; struct pa_sink *sink = NULL; struct pa_source *source = NULL; + struct pa_client *client = NULL; + struct pa_module *module = NULL; const char *name; struct pa_tagstruct *reply; assert(c && t); @@ -990,15 +1013,19 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t sink = pa_idxset_get_by_index(c->protocol->core->sinks, index); else sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1); - } else { - assert(command == PA_COMMAND_GET_SOURCE_INFO); + } else if (command == PA_COMMAND_GET_SOURCE_INFO) { if (index != (uint32_t) -1) source = pa_idxset_get_by_index(c->protocol->core->sources, index); else source = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SOURCE, 1); + } else if (command == PA_COMMAND_GET_CLIENT_INFO) + client = pa_idxset_get_by_index(c->protocol->core->clients, index); + else { + assert(command == PA_COMMAND_GET_MODULE_INFO); + module = pa_idxset_get_by_index(c->protocol->core->modules, index); } - - if (!sink && !source) { + + if (!sink && !source && !client && !module) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1009,8 +1036,12 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct_putu32(reply, tag); if (sink) sink_fill_tagstruct(reply, sink); - else + else if (source) source_fill_tagstruct(reply, source); + else if (client) + client_fill_tagstruct(reply, client); + else + module_fill_tagstruct(reply, module); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1039,17 +1070,25 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin if (command == PA_COMMAND_GET_SINK_INFO_LIST) i = c->protocol->core->sinks; - else { - assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST); + else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST) i = c->protocol->core->sources; + else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST) + i = c->protocol->core->clients; + else { + assert(command == PA_COMMAND_GET_MODULE_INFO_LIST); + i = c->protocol->core->modules; } for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) { if (command == PA_COMMAND_GET_SINK_INFO_LIST) sink_fill_tagstruct(reply, p); - else { - assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST); + else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST) source_fill_tagstruct(reply, p); + else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST) + client_fill_tagstruct(reply, p); + else { + assert(command == PA_COMMAND_GET_MODULE_INFO_LIST); + module_fill_tagstruct(reply, p); } } diff --git a/polyp/sink.c b/polyp/sink.c index 7e0e15cdd..d9a3ae861 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -276,10 +276,17 @@ uint32_t pa_sink_get_latency(struct pa_sink *s) { return s->get_latency(s); } - void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) { sink->owner = m; if (sink->monitor_source) pa_source_set_owner(sink->monitor_source, m); } + +void pa_sink_set_volume(struct pa_sink *sink, uint32_t volume) { + assert(sink); + if (sink->volume != volume) { + pa_subscription_post(sink->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, sink->index); + sink->volume = volume; + } +} diff --git a/polyp/sink.h b/polyp/sink.h index 400d5d04f..2aa5d6112 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -62,4 +62,6 @@ void pa_sink_notify(struct pa_sink*s); void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m); +void pa_sink_set_volume(struct pa_sink *sink, uint32_t volume); + #endif From cd5809ca97e40fa1603474f034f034c705cb4d23 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 12 Aug 2004 23:27:57 +0000 Subject: [PATCH 0115/1514] todo fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@116 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 276cccfc7..943fab0d4 100644 --- a/doc/todo +++ b/doc/todo @@ -22,6 +22,7 @@ subscription module load/unload kill client/... + set volume - more complete pactl ** later *** From 7b52d5d02bf107491388fbcfe6ffbd354596cfdd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Aug 2004 13:14:22 +0000 Subject: [PATCH 0116/1514] some preliminary cleanup git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@117 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib.h | 79 +++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/polyp/polyplib.h b/polyp/polyplib.h index 590b978f8..a0dd9f9cb 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -29,26 +29,18 @@ #include "mainloop-api.h" #ifdef __cplusplus -extern "C" { +//extern "C" { #endif struct pa_context; +struct pa_stream; struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); +void pa_context_unref(struct pa_context *c); +struct pa_context* pa_context_ref(struct pa_context *c); -int pa_context_connect( - struct pa_context *c, - const char *server, - void (*complete) (struct pa_context*c, int success, void *userdata), - void *userdata); - -int pa_context_drain( - struct pa_context *c, - void (*complete) (struct pa_context*c, void *userdata), - void *userdata); - -void pa_context_free(struct pa_context *c); - +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); +int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); int pa_context_is_dead(struct pa_context *c); @@ -57,28 +49,11 @@ int pa_context_errno(struct pa_context *c); int pa_context_is_pending(struct pa_context *c); -void pa_context_exit(struct pa_context *c); -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); - -struct pa_stream; - -struct pa_stream* pa_stream_new( - struct pa_context *c, - enum pa_stream_direction dir, - const char *dev, - const char *name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, - void (*complete) (struct pa_stream*s, int success, void *userdata), - void *userdata); - -void pa_stream_free(struct pa_stream *p); - -void pa_stream_drain( - struct pa_stream *s, - void (*complete) (struct pa_stream*s, void *userdata), - void *userdata); +struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_unref(struct pa_stream *s); +struct pa_stream *pa_stream_ref(struct pa_stream *s); +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); @@ -95,6 +70,8 @@ void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, struct pa_context* pa_stream_get_context(struct pa_stream *p); +uint32_t pa_stream_get_index(struct pa_stream *s); + struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); @@ -160,6 +137,38 @@ struct pa_client_info { void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +struct pa_sink_input_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t sink; + struct pa_sample_spec sample_spec; + uint32_t volume; + uint32_t latency; +}; + +void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); + +struct pa_source_output_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t source; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); + +void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +void pa_context_exit(struct pa_context *c); +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); + void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); #ifdef __cplusplus From 79a4e75e3ac61c3412d5c785215283e99d8b52bf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Aug 2004 13:22:44 +0000 Subject: [PATCH 0117/1514] split polyplib.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@118 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-context.c | 1550 +++++++++++++++++++++++++++++++++++ polyp/polyplib-context.h | 178 ++++ polyp/polyplib-introspect.c | 1550 +++++++++++++++++++++++++++++++++++ polyp/polyplib-introspect.h | 178 ++++ polyp/polyplib-stream.c | 1550 +++++++++++++++++++++++++++++++++++ polyp/polyplib-stream.h | 178 ++++ polyp/polyplib-subscribe.c | 1550 +++++++++++++++++++++++++++++++++++ polyp/polyplib-subscribe.h | 178 ++++ 8 files changed, 6912 insertions(+) create mode 100644 polyp/polyplib-context.c create mode 100644 polyp/polyplib-context.h create mode 100644 polyp/polyplib-introspect.c create mode 100644 polyp/polyplib-introspect.h create mode 100644 polyp/polyplib-stream.c create mode 100644 polyp/polyplib-stream.h create mode 100644 polyp/polyplib-subscribe.c create mode 100644 polyp/polyplib-subscribe.h diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c new file mode 100644 index 000000000..35001d3d3 --- /dev/null +++ b/polyp/polyplib-context.c @@ -0,0 +1,1550 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "polyplib.h" +#include "native-common.h" +#include "pdispatch.h" +#include "pstream.h" +#include "dynarray.h" +#include "socket-client.h" +#include "pstream-util.h" +#include "authkey.h" +#include "util.h" +#include "xmalloc.h" + +#define DEFAULT_MAXLENGTH 204800 +#define DEFAULT_TLENGTH 10240 +#define DEFAULT_PREBUF 4096 +#define DEFAULT_MINREQ 1024 +#define DEFAULT_FRAGSIZE 1024 + +#define DEFAULT_TIMEOUT (5*60) +#define DEFAULT_SERVER "/tmp/polypaudio/native" +#define DEFAULT_PORT "4713" + +struct pa_context { + char *name; + struct pa_mainloop_api* mainloop; + struct pa_socket_client *client; + struct pa_pstream *pstream; + struct pa_pdispatch *pdispatch; + struct pa_dynarray *record_streams, *playback_streams; + struct pa_stream *first_stream; + uint32_t ctag; + uint32_t error; + enum { + CONTEXT_UNCONNECTED, + CONTEXT_CONNECTING, + CONTEXT_AUTHORIZING, + CONTEXT_SETTING_NAME, + CONTEXT_READY, + CONTEXT_DEAD + } state; + + void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); + void *connect_complete_userdata; + + void (*drain_complete_callback)(struct pa_context*c, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_context*c, void *userdata); + void *die_userdata; + + void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); + void *stat_userdata; + + void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); + void *play_sample_userdata; + + void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); + void *remove_sample_userdata; + + void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); + void *get_server_info_userdata; + + void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); + void *get_sink_info_userdata; + + void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); + void *get_source_info_userdata; + + void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void *subscribe_userdata; + enum pa_subscription_mask subscribe_mask; + + void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); + void *get_client_info_userdata; + + void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); + void *get_module_info_userdata; + + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; +}; + +struct pa_stream { + struct pa_context *context; + struct pa_stream *next, *previous; + + char *name; + struct pa_buffer_attr buffer_attr; + struct pa_sample_spec sample_spec; + uint32_t channel; + int channel_valid; + uint32_t device_index; + enum pa_stream_direction direction; + + enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; + uint32_t requested_bytes; + + void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); + void *read_userdata; + + void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); + void *write_userdata; + + void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); + void *create_complete_userdata; + + void (*drain_complete_callback)(struct pa_stream *s, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_stream*c, void *userdata); + void *die_userdata; + + void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); + void *get_latency_userdata; + + void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); + void *finish_sample_userdata; +}; + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + +static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = { NULL }, + [PA_COMMAND_REPLY] = { NULL }, + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_EXIT] = { NULL }, + [PA_COMMAND_REQUEST] = { command_request }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, +}; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { + struct pa_context *c; + assert(mainloop && name); + + c = pa_xmalloc(sizeof(struct pa_context)); + c->name = pa_xstrdup(name); + c->mainloop = mainloop; + c->client = NULL; + c->pstream = NULL; + c->pdispatch = NULL; + c->playback_streams = pa_dynarray_new(); + assert(c->playback_streams); + c->record_streams = pa_dynarray_new(); + assert(c->record_streams); + c->first_stream = NULL; + c->error = PA_ERROR_OK; + c->state = CONTEXT_UNCONNECTED; + c->ctag = 0; + + c->connect_complete_callback = NULL; + c->connect_complete_userdata = NULL; + + c->drain_complete_callback = NULL; + c->drain_complete_userdata = NULL; + + c->die_callback = NULL; + c->die_userdata = NULL; + + c->stat_callback = NULL; + c->stat_userdata = NULL; + + c->play_sample_callback = NULL; + c->play_sample_userdata = NULL; + + c->remove_sample_callback = NULL; + c->remove_sample_userdata = NULL; + + c->get_server_info_callback = NULL; + c->get_server_info_userdata = NULL; + + c->get_sink_info_callback = NULL; + c->get_sink_info_userdata = NULL; + + c->get_source_info_callback = NULL; + c->get_source_info_userdata = NULL; + + c->subscribe_callback = NULL; + c->subscribe_userdata = NULL; + + c->get_client_info_callback = NULL; + c->get_client_info_userdata = NULL; + + c->get_module_info_callback = NULL; + c->get_module_info_userdata = NULL; + + pa_check_for_sigpipe(); + return c; +} + +void pa_context_free(struct pa_context *c) { + assert(c); + + while (c->first_stream) + pa_stream_free(c->first_stream); + + if (c->client) + pa_socket_client_free(c->client); + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + if (c->pstream) + pa_pstream_free(c->pstream); + if (c->record_streams) + pa_dynarray_free(c->record_streams, NULL, NULL); + if (c->playback_streams) + pa_dynarray_free(c->playback_streams, NULL, NULL); + + pa_xfree(c->name); + pa_xfree(c); +} + +static void stream_dead(struct pa_stream *s) { + assert(s); + + if (s->state == STREAM_DEAD) + return; + + if (s->state == STREAM_READY) { + s->state = STREAM_DEAD; + if (s->die_callback) + s->die_callback(s, s->die_userdata); + } else + s->state = STREAM_DEAD; +} + +static void context_dead(struct pa_context *c) { + struct pa_stream *s; + assert(c); + + if (c->state == CONTEXT_DEAD) + return; + + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + c->pdispatch = NULL; + + if (c->pstream) + pa_pstream_free(c->pstream); + c->pstream = NULL; + + if (c->client) + pa_socket_client_free(c->client); + c->client = NULL; + + for (s = c->first_stream; s; s = s->next) + stream_dead(s); + + if (c->state == CONTEXT_READY) { + c->state = CONTEXT_DEAD; + if (c->die_callback) + c->die_callback(c, c->die_userdata); + } else + c->state = CONTEXT_DEAD; +} + +static void pstream_die_callback(struct pa_pstream *p, void *userdata) { + struct pa_context *c = userdata; + assert(p && c); + c->error = PA_ERROR_CONNECTIONTERMINATED; + context_dead(c); +} + +static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { + struct pa_context *c = userdata; + assert(p && packet && c); + + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { + fprintf(stderr, "polyp.c: invalid packet.\n"); + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + } +} + +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + assert(p && chunk && c && chunk->memblock && chunk->memblock->data); + + if (!(s = pa_dynarray_get(c->record_streams, channel))) + return; + + if (s->read_callback) + s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); +} + +static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { + assert(c && t); + + if (command == PA_COMMAND_ERROR) { + if (pa_tagstruct_getu32(t, &c->error) < 0) { + c->error = PA_ERROR_PROTOCOL; + return -1; + } + + return 0; + } + + c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; + return -1; +} + +static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); + + if (command != PA_COMMAND_REPLY) { + handle_error(c, command, t); + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + if (c->state == CONTEXT_AUTHORIZING) { + struct pa_tagstruct *t; + c->state = CONTEXT_SETTING_NAME; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, c->name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + } else { + assert(c->state == CONTEXT_SETTING_NAME); + + c->state = CONTEXT_READY; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 1, c->connect_complete_userdata); + } + + return; +} + +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { + struct pa_context *c = userdata; + struct pa_tagstruct *t; + uint32_t tag; + assert(client && c && c->state == CONTEXT_CONNECTING); + + pa_socket_client_free(client); + c->client = NULL; + + if (!io) { + c->error = PA_ERROR_CONNECTIONREFUSED; + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + c->pstream = pa_pstream_new(c->mainloop, io); + assert(c->pstream); + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + + c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); + assert(c->pdispatch); + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_AUTH); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + c->state = CONTEXT_AUTHORIZING; +} + +static struct sockaddr *resolve_server(const char *server, size_t *len) { + struct sockaddr *sa; + struct addrinfo hints, *result = NULL; + char *port; + assert(server && len); + + if ((port = strrchr(server, ':'))) + port++; + if (!port) + port = DEFAULT_PORT; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + if (getaddrinfo(server, port, &hints, &result) != 0) + return NULL; + assert(result); + + sa = pa_xmalloc(*len = result->ai_addrlen); + memcpy(sa, result->ai_addr, *len); + + freeaddrinfo(result); + + return sa; +} + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { + assert(c && c->state == CONTEXT_UNCONNECTED); + + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { + c->error = PA_ERROR_AUTHKEY; + return -1; + } + + if (!server) + if (!(server = getenv("POLYP_SERVER"))) + server = DEFAULT_SERVER; + + assert(!c->client); + + if (*server == '/') { + if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } else { + struct sockaddr* sa; + size_t sa_len; + + if (!(sa = resolve_server(server, &sa_len))) { + c->error = PA_ERROR_INVALIDSERVER; + return -1; + } + + c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); + pa_xfree(sa); + + if (!c->client) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } + + c->connect_complete_callback = complete; + c->connect_complete_userdata = userdata; + + pa_socket_client_set_callback(c->client, on_connection, c); + c->state = CONTEXT_CONNECTING; + + return 0; +} + +int pa_context_is_dead(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_DEAD; +} + +int pa_context_is_ready(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_READY; +} + +int pa_context_errno(struct pa_context *c) { + assert(c); + return c->error; +} + +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { + assert(c); + c->die_callback = cb; + c->die_userdata = userdata; +} + +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + uint32_t channel; + assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) + return; + + c->error = PA_ERROR_KILLED; + stream_dead(s); +} + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s; + struct pa_context *c = userdata; + uint32_t bytes, channel; + assert(pd && command == PA_COMMAND_REQUEST && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_getu32(t, &bytes) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(c->playback_streams, channel))) + return; + + if (s->state != STREAM_READY) + return; + + s->requested_bytes += bytes; + + if (s->requested_bytes && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); +} + +static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s && s->state == STREAM_CREATING); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + if (s->create_complete_callback) + s->create_complete_callback(s, 0, s->create_complete_userdata); + + return; + } + + if (pa_tagstruct_getu32(t, &s->channel) < 0 || + ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + s->channel_valid = 1; + pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); + + s->state = STREAM_READY; + if (s->create_complete_callback) + s->create_complete_callback(s, 1, s->create_complete_userdata); +} + +static void create_stream(struct pa_stream *s, const char *dev) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s); + + s->state = STREAM_CREATING; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_puts(t, s->name); + pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, s->buffer_attr.maxlength); + if (s->direction == PA_STREAM_PLAYBACK) { + pa_tagstruct_putu32(t, s->buffer_attr.tlength); + pa_tagstruct_putu32(t, s->buffer_attr.prebuf); + pa_tagstruct_putu32(t, s->buffer_attr.minreq); + } else + pa_tagstruct_putu32(t, s->buffer_attr.fragsize); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); +} + +static struct pa_stream *internal_stream_new(struct pa_context *c) { + struct pa_stream *s; + + s = pa_xmalloc(sizeof(struct pa_stream)); + s->context = c; + + s->read_callback = NULL; + s->read_userdata = NULL; + s->write_callback = NULL; + s->write_userdata = NULL; + s->die_callback = NULL; + s->die_userdata = NULL; + s->create_complete_callback = NULL; + s->create_complete_userdata = NULL; + s->get_latency_callback = NULL; + s->get_latency_userdata = NULL; + s->finish_sample_callback = NULL; + s->finish_sample_userdata = NULL; + + s->name = NULL; + s->state = STREAM_CREATING; + s->requested_bytes = 0; + s->channel = 0; + s->channel_valid = 0; + s->device_index = (uint32_t) -1; + + memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + + s->next = c->first_stream; + if (s->next) + s->next->previous = s; + s->previous = NULL; + c->first_stream = s; + + return s; +} + +struct pa_stream* pa_stream_new( + struct pa_context *c, + enum pa_stream_direction dir, + const char *dev, + const char *name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr, + void (*complete) (struct pa_stream*s, int success, void *userdata), + void *userdata) { + + struct pa_stream *s; + + assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = complete; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = dir; + s->sample_spec = *ss; + if (attr) + s->buffer_attr = *attr; + else { + s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; + s->buffer_attr.tlength = DEFAULT_TLENGTH; + s->buffer_attr.prebuf = DEFAULT_PREBUF; + s->buffer_attr.minreq = DEFAULT_MINREQ; + s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; + } + + create_stream(s, dev); + + return s; +} + +void pa_stream_free(struct pa_stream *s) { + assert(s && s->context); + + if (s->context->pdispatch) + pa_pdispatch_unregister_reply(s->context->pdispatch, s); + + pa_xfree(s->name); + + if (s->channel_valid && s->context->state == CONTEXT_READY) { + struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); + pa_tagstruct_putu32(t, s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + } + + if (s->channel_valid) + pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); + + if (s->next) + s->next->previous = s->previous; + if (s->previous) + s->previous->next = s->next; + else + s->context->first_stream = s->next; + + pa_xfree(s); +} + +void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { + s->write_callback = cb; + s->write_userdata = userdata; +} + +void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { + struct pa_memchunk chunk; + assert(s && s->context && data && length && s->state == STREAM_READY); + + chunk.memblock = pa_memblock_new(length); + assert(chunk.memblock && chunk.memblock->data); + memcpy(chunk.memblock->data, data, length); + chunk.index = 0; + chunk.length = length; + + pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + pa_memblock_unref(chunk.memblock); + + /*fprintf(stderr, "Sent %u bytes\n", length);*/ + + if (length < s->requested_bytes) + s->requested_bytes -= length; + else + s->requested_bytes = 0; +} + +size_t pa_stream_writable_size(struct pa_stream *s) { + assert(s && s->state == STREAM_READY); + return s->requested_bytes; +} + +void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { + assert(s && cb); + s->read_callback = cb; + s->read_userdata = userdata; +} + +int pa_stream_is_dead(struct pa_stream *s) { + return s->state == STREAM_DEAD; +} + +int pa_stream_is_ready(struct pa_stream*s) { + return s->state == STREAM_READY; +} + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { + assert(s); + s->die_callback = cb; + s->die_userdata = userdata; +} + +int pa_context_is_pending(struct pa_context *c) { + assert(c); + + if (c->state != CONTEXT_READY) + return 0; + + return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); +} + +struct pa_context* pa_stream_get_context(struct pa_stream *p) { + assert(p); + return p->context; +} + +static void set_dispatch_callbacks(struct pa_context *c); + +static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void set_dispatch_callbacks(struct pa_context *c) { + assert(c && c->state == CONTEXT_READY); + + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + + if (pa_pdispatch_is_pending(c->pdispatch)) { + pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); + return; + } + + if (pa_pstream_is_pending(c->pstream)) { + pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); + return; + } + + assert(c->drain_complete_callback); + c->drain_complete_callback(c, c->drain_complete_userdata); +} + +int pa_context_drain( + struct pa_context *c, + void (*complete) (struct pa_context*c, void *userdata), + void *userdata) { + + assert(c && c->state == CONTEXT_READY); + + if (complete == NULL) { + c->drain_complete_callback = NULL; + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + return 0; + } + + if (!pa_context_is_pending(c)) + return -1; + + c->drain_complete_callback = complete; + c->drain_complete_userdata = userdata; + + set_dispatch_callbacks(c); + + return 0; +} + +static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + return; + } + + if (s->state != STREAM_READY) + return; + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->drain_complete_callback) { + void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; + s->drain_complete_callback = NULL; + temp(s, s->drain_complete_userdata); + } +} + + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->state == STREAM_READY); + + if (!complete) { + s->drain_complete_callback = NULL; + return; + } + + s->drain_complete_callback = complete; + s->drain_complete_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); +} + +void pa_context_exit(struct pa_context *c) { + struct pa_tagstruct *t; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_EXIT); + pa_tagstruct_putu32(t, c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + uint32_t total, count; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &count) < 0 || + pa_tagstruct_getu32(t, &total) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, count, total, c->stat_userdata); +} + +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + c->stat_callback = cb; + c->stat_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_STAT); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); +} + +static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + uint32_t latency; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &latency) < 0 || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, latency, s->get_latency_userdata); +} + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + p->get_latency_callback = cb; + p->get_latency_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); +} + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_stream *s; + struct pa_tagstruct *t; + uint32_t tag; + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = cb; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = PA_STREAM_UPLOAD; + s->sample_spec = *ss; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_sample_spec(t, ss); + pa_tagstruct_putu32(t, length); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); + + return s; +} + +static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 0, s->finish_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 1, s->finish_sample_userdata); +} + +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(p); + + p->finish_sample_callback = cb; + p->finish_sample_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); +} + +static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 0, c->play_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 1, c->play_sample_userdata); +} + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name && *name && (!dev || *dev)); + + c->play_sample_callback = cb; + c->play_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, volume); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); +} + +static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 0, c->remove_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 1, c->remove_sample_userdata); +} + +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name); + + c->remove_sample_callback = cb; + c->remove_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); +} + +static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_server_info i; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, NULL, c->get_server_info_userdata); + return; + } + + if (pa_tagstruct_gets(t, &i.server_name) < 0 || + pa_tagstruct_gets(t, &i.server_version) < 0 || + pa_tagstruct_gets(t, &i.user_name) < 0 || + pa_tagstruct_gets(t, &i.host_name) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, &i, c->get_server_info_userdata); +} + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_server_info_callback = cb; + c->get_server_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); +} + +static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_sink_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.monitor_source) < 0 || + pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || + pa_tagstruct_getu32(t, &i.latency) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); +} + +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_source_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || + pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); +} + +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + struct pa_tagstruct *t; + assert(c); + + c->subscribe_callback = cb; + c->subscribe_userdata = userdata; + c->subscribe_mask = m; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); + pa_tagstruct_putu32(t, c->ctag++); + pa_tagstruct_putu32(t, cb ? m : 0); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + enum pa_subscription_event_type e; + uint32_t index; + assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); + + if (pa_tagstruct_getu32(t, &e) < 0 || + pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) + c->subscribe_callback(c, e, index, c->subscribe_userdata); +} + +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_client_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.protocol_name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); +} + + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_module_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0 || + pa_tagstruct_getu32(t, &i.n_used) < 0 || + pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); +} + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} + +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h new file mode 100644 index 000000000..a0dd9f9cb --- /dev/null +++ b/polyp/polyplib-context.h @@ -0,0 +1,178 @@ +#ifndef foopolyplibhfoo +#define foopolyplibhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "sample.h" +#include "polyplib-def.h" +#include "mainloop-api.h" + +#ifdef __cplusplus +//extern "C" { +#endif + +struct pa_context; +struct pa_stream; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); +void pa_context_unref(struct pa_context *c); +struct pa_context* pa_context_ref(struct pa_context *c); + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); +int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); + +int pa_context_is_dead(struct pa_context *c); +int pa_context_is_ready(struct pa_context *c); +int pa_context_errno(struct pa_context *c); + +int pa_context_is_pending(struct pa_context *c); + +struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_unref(struct pa_stream *s); +struct pa_stream *pa_stream_ref(struct pa_stream *s); + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); + +void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); +void pa_stream_write(struct pa_stream *p, const void *data, size_t length); +size_t pa_stream_writable_size(struct pa_stream *p); + +void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); + +int pa_stream_is_dead(struct pa_stream *p); +int pa_stream_is_ready(struct pa_stream*p); + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); + +struct pa_context* pa_stream_get_context(struct pa_stream *p); + +uint32_t pa_stream_get_index(struct pa_stream *s); + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +struct pa_sink_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t volume; + uint32_t monitor_source; + const char *monitor_source_name; + uint32_t latency; +}; + +void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); + +struct pa_source_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t monitor_of_sink; + const char *monitor_of_sink_name; +}; + +void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); + +struct pa_server_info { + const char *user_name; + const char *host_name; + const char *server_version; + const char *server_name; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); + +struct pa_module_info { + uint32_t index; + const char*name, *argument; + uint32_t n_used, auto_unload; +}; + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); + +struct pa_client_info { + uint32_t index; + const char *name; + uint32_t owner_module; + const char *protocol_name; +}; + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); + +struct pa_sink_input_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t sink; + struct pa_sample_spec sample_spec; + uint32_t volume; + uint32_t latency; +}; + +void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); + +struct pa_source_output_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t source; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); + +void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +void pa_context_exit(struct pa_context *c); +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c new file mode 100644 index 000000000..35001d3d3 --- /dev/null +++ b/polyp/polyplib-introspect.c @@ -0,0 +1,1550 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "polyplib.h" +#include "native-common.h" +#include "pdispatch.h" +#include "pstream.h" +#include "dynarray.h" +#include "socket-client.h" +#include "pstream-util.h" +#include "authkey.h" +#include "util.h" +#include "xmalloc.h" + +#define DEFAULT_MAXLENGTH 204800 +#define DEFAULT_TLENGTH 10240 +#define DEFAULT_PREBUF 4096 +#define DEFAULT_MINREQ 1024 +#define DEFAULT_FRAGSIZE 1024 + +#define DEFAULT_TIMEOUT (5*60) +#define DEFAULT_SERVER "/tmp/polypaudio/native" +#define DEFAULT_PORT "4713" + +struct pa_context { + char *name; + struct pa_mainloop_api* mainloop; + struct pa_socket_client *client; + struct pa_pstream *pstream; + struct pa_pdispatch *pdispatch; + struct pa_dynarray *record_streams, *playback_streams; + struct pa_stream *first_stream; + uint32_t ctag; + uint32_t error; + enum { + CONTEXT_UNCONNECTED, + CONTEXT_CONNECTING, + CONTEXT_AUTHORIZING, + CONTEXT_SETTING_NAME, + CONTEXT_READY, + CONTEXT_DEAD + } state; + + void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); + void *connect_complete_userdata; + + void (*drain_complete_callback)(struct pa_context*c, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_context*c, void *userdata); + void *die_userdata; + + void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); + void *stat_userdata; + + void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); + void *play_sample_userdata; + + void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); + void *remove_sample_userdata; + + void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); + void *get_server_info_userdata; + + void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); + void *get_sink_info_userdata; + + void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); + void *get_source_info_userdata; + + void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void *subscribe_userdata; + enum pa_subscription_mask subscribe_mask; + + void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); + void *get_client_info_userdata; + + void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); + void *get_module_info_userdata; + + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; +}; + +struct pa_stream { + struct pa_context *context; + struct pa_stream *next, *previous; + + char *name; + struct pa_buffer_attr buffer_attr; + struct pa_sample_spec sample_spec; + uint32_t channel; + int channel_valid; + uint32_t device_index; + enum pa_stream_direction direction; + + enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; + uint32_t requested_bytes; + + void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); + void *read_userdata; + + void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); + void *write_userdata; + + void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); + void *create_complete_userdata; + + void (*drain_complete_callback)(struct pa_stream *s, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_stream*c, void *userdata); + void *die_userdata; + + void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); + void *get_latency_userdata; + + void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); + void *finish_sample_userdata; +}; + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + +static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = { NULL }, + [PA_COMMAND_REPLY] = { NULL }, + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_EXIT] = { NULL }, + [PA_COMMAND_REQUEST] = { command_request }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, +}; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { + struct pa_context *c; + assert(mainloop && name); + + c = pa_xmalloc(sizeof(struct pa_context)); + c->name = pa_xstrdup(name); + c->mainloop = mainloop; + c->client = NULL; + c->pstream = NULL; + c->pdispatch = NULL; + c->playback_streams = pa_dynarray_new(); + assert(c->playback_streams); + c->record_streams = pa_dynarray_new(); + assert(c->record_streams); + c->first_stream = NULL; + c->error = PA_ERROR_OK; + c->state = CONTEXT_UNCONNECTED; + c->ctag = 0; + + c->connect_complete_callback = NULL; + c->connect_complete_userdata = NULL; + + c->drain_complete_callback = NULL; + c->drain_complete_userdata = NULL; + + c->die_callback = NULL; + c->die_userdata = NULL; + + c->stat_callback = NULL; + c->stat_userdata = NULL; + + c->play_sample_callback = NULL; + c->play_sample_userdata = NULL; + + c->remove_sample_callback = NULL; + c->remove_sample_userdata = NULL; + + c->get_server_info_callback = NULL; + c->get_server_info_userdata = NULL; + + c->get_sink_info_callback = NULL; + c->get_sink_info_userdata = NULL; + + c->get_source_info_callback = NULL; + c->get_source_info_userdata = NULL; + + c->subscribe_callback = NULL; + c->subscribe_userdata = NULL; + + c->get_client_info_callback = NULL; + c->get_client_info_userdata = NULL; + + c->get_module_info_callback = NULL; + c->get_module_info_userdata = NULL; + + pa_check_for_sigpipe(); + return c; +} + +void pa_context_free(struct pa_context *c) { + assert(c); + + while (c->first_stream) + pa_stream_free(c->first_stream); + + if (c->client) + pa_socket_client_free(c->client); + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + if (c->pstream) + pa_pstream_free(c->pstream); + if (c->record_streams) + pa_dynarray_free(c->record_streams, NULL, NULL); + if (c->playback_streams) + pa_dynarray_free(c->playback_streams, NULL, NULL); + + pa_xfree(c->name); + pa_xfree(c); +} + +static void stream_dead(struct pa_stream *s) { + assert(s); + + if (s->state == STREAM_DEAD) + return; + + if (s->state == STREAM_READY) { + s->state = STREAM_DEAD; + if (s->die_callback) + s->die_callback(s, s->die_userdata); + } else + s->state = STREAM_DEAD; +} + +static void context_dead(struct pa_context *c) { + struct pa_stream *s; + assert(c); + + if (c->state == CONTEXT_DEAD) + return; + + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + c->pdispatch = NULL; + + if (c->pstream) + pa_pstream_free(c->pstream); + c->pstream = NULL; + + if (c->client) + pa_socket_client_free(c->client); + c->client = NULL; + + for (s = c->first_stream; s; s = s->next) + stream_dead(s); + + if (c->state == CONTEXT_READY) { + c->state = CONTEXT_DEAD; + if (c->die_callback) + c->die_callback(c, c->die_userdata); + } else + c->state = CONTEXT_DEAD; +} + +static void pstream_die_callback(struct pa_pstream *p, void *userdata) { + struct pa_context *c = userdata; + assert(p && c); + c->error = PA_ERROR_CONNECTIONTERMINATED; + context_dead(c); +} + +static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { + struct pa_context *c = userdata; + assert(p && packet && c); + + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { + fprintf(stderr, "polyp.c: invalid packet.\n"); + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + } +} + +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + assert(p && chunk && c && chunk->memblock && chunk->memblock->data); + + if (!(s = pa_dynarray_get(c->record_streams, channel))) + return; + + if (s->read_callback) + s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); +} + +static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { + assert(c && t); + + if (command == PA_COMMAND_ERROR) { + if (pa_tagstruct_getu32(t, &c->error) < 0) { + c->error = PA_ERROR_PROTOCOL; + return -1; + } + + return 0; + } + + c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; + return -1; +} + +static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); + + if (command != PA_COMMAND_REPLY) { + handle_error(c, command, t); + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + if (c->state == CONTEXT_AUTHORIZING) { + struct pa_tagstruct *t; + c->state = CONTEXT_SETTING_NAME; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, c->name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + } else { + assert(c->state == CONTEXT_SETTING_NAME); + + c->state = CONTEXT_READY; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 1, c->connect_complete_userdata); + } + + return; +} + +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { + struct pa_context *c = userdata; + struct pa_tagstruct *t; + uint32_t tag; + assert(client && c && c->state == CONTEXT_CONNECTING); + + pa_socket_client_free(client); + c->client = NULL; + + if (!io) { + c->error = PA_ERROR_CONNECTIONREFUSED; + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + c->pstream = pa_pstream_new(c->mainloop, io); + assert(c->pstream); + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + + c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); + assert(c->pdispatch); + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_AUTH); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + c->state = CONTEXT_AUTHORIZING; +} + +static struct sockaddr *resolve_server(const char *server, size_t *len) { + struct sockaddr *sa; + struct addrinfo hints, *result = NULL; + char *port; + assert(server && len); + + if ((port = strrchr(server, ':'))) + port++; + if (!port) + port = DEFAULT_PORT; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + if (getaddrinfo(server, port, &hints, &result) != 0) + return NULL; + assert(result); + + sa = pa_xmalloc(*len = result->ai_addrlen); + memcpy(sa, result->ai_addr, *len); + + freeaddrinfo(result); + + return sa; +} + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { + assert(c && c->state == CONTEXT_UNCONNECTED); + + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { + c->error = PA_ERROR_AUTHKEY; + return -1; + } + + if (!server) + if (!(server = getenv("POLYP_SERVER"))) + server = DEFAULT_SERVER; + + assert(!c->client); + + if (*server == '/') { + if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } else { + struct sockaddr* sa; + size_t sa_len; + + if (!(sa = resolve_server(server, &sa_len))) { + c->error = PA_ERROR_INVALIDSERVER; + return -1; + } + + c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); + pa_xfree(sa); + + if (!c->client) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } + + c->connect_complete_callback = complete; + c->connect_complete_userdata = userdata; + + pa_socket_client_set_callback(c->client, on_connection, c); + c->state = CONTEXT_CONNECTING; + + return 0; +} + +int pa_context_is_dead(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_DEAD; +} + +int pa_context_is_ready(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_READY; +} + +int pa_context_errno(struct pa_context *c) { + assert(c); + return c->error; +} + +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { + assert(c); + c->die_callback = cb; + c->die_userdata = userdata; +} + +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + uint32_t channel; + assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) + return; + + c->error = PA_ERROR_KILLED; + stream_dead(s); +} + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s; + struct pa_context *c = userdata; + uint32_t bytes, channel; + assert(pd && command == PA_COMMAND_REQUEST && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_getu32(t, &bytes) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(c->playback_streams, channel))) + return; + + if (s->state != STREAM_READY) + return; + + s->requested_bytes += bytes; + + if (s->requested_bytes && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); +} + +static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s && s->state == STREAM_CREATING); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + if (s->create_complete_callback) + s->create_complete_callback(s, 0, s->create_complete_userdata); + + return; + } + + if (pa_tagstruct_getu32(t, &s->channel) < 0 || + ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + s->channel_valid = 1; + pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); + + s->state = STREAM_READY; + if (s->create_complete_callback) + s->create_complete_callback(s, 1, s->create_complete_userdata); +} + +static void create_stream(struct pa_stream *s, const char *dev) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s); + + s->state = STREAM_CREATING; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_puts(t, s->name); + pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, s->buffer_attr.maxlength); + if (s->direction == PA_STREAM_PLAYBACK) { + pa_tagstruct_putu32(t, s->buffer_attr.tlength); + pa_tagstruct_putu32(t, s->buffer_attr.prebuf); + pa_tagstruct_putu32(t, s->buffer_attr.minreq); + } else + pa_tagstruct_putu32(t, s->buffer_attr.fragsize); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); +} + +static struct pa_stream *internal_stream_new(struct pa_context *c) { + struct pa_stream *s; + + s = pa_xmalloc(sizeof(struct pa_stream)); + s->context = c; + + s->read_callback = NULL; + s->read_userdata = NULL; + s->write_callback = NULL; + s->write_userdata = NULL; + s->die_callback = NULL; + s->die_userdata = NULL; + s->create_complete_callback = NULL; + s->create_complete_userdata = NULL; + s->get_latency_callback = NULL; + s->get_latency_userdata = NULL; + s->finish_sample_callback = NULL; + s->finish_sample_userdata = NULL; + + s->name = NULL; + s->state = STREAM_CREATING; + s->requested_bytes = 0; + s->channel = 0; + s->channel_valid = 0; + s->device_index = (uint32_t) -1; + + memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + + s->next = c->first_stream; + if (s->next) + s->next->previous = s; + s->previous = NULL; + c->first_stream = s; + + return s; +} + +struct pa_stream* pa_stream_new( + struct pa_context *c, + enum pa_stream_direction dir, + const char *dev, + const char *name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr, + void (*complete) (struct pa_stream*s, int success, void *userdata), + void *userdata) { + + struct pa_stream *s; + + assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = complete; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = dir; + s->sample_spec = *ss; + if (attr) + s->buffer_attr = *attr; + else { + s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; + s->buffer_attr.tlength = DEFAULT_TLENGTH; + s->buffer_attr.prebuf = DEFAULT_PREBUF; + s->buffer_attr.minreq = DEFAULT_MINREQ; + s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; + } + + create_stream(s, dev); + + return s; +} + +void pa_stream_free(struct pa_stream *s) { + assert(s && s->context); + + if (s->context->pdispatch) + pa_pdispatch_unregister_reply(s->context->pdispatch, s); + + pa_xfree(s->name); + + if (s->channel_valid && s->context->state == CONTEXT_READY) { + struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); + pa_tagstruct_putu32(t, s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + } + + if (s->channel_valid) + pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); + + if (s->next) + s->next->previous = s->previous; + if (s->previous) + s->previous->next = s->next; + else + s->context->first_stream = s->next; + + pa_xfree(s); +} + +void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { + s->write_callback = cb; + s->write_userdata = userdata; +} + +void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { + struct pa_memchunk chunk; + assert(s && s->context && data && length && s->state == STREAM_READY); + + chunk.memblock = pa_memblock_new(length); + assert(chunk.memblock && chunk.memblock->data); + memcpy(chunk.memblock->data, data, length); + chunk.index = 0; + chunk.length = length; + + pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + pa_memblock_unref(chunk.memblock); + + /*fprintf(stderr, "Sent %u bytes\n", length);*/ + + if (length < s->requested_bytes) + s->requested_bytes -= length; + else + s->requested_bytes = 0; +} + +size_t pa_stream_writable_size(struct pa_stream *s) { + assert(s && s->state == STREAM_READY); + return s->requested_bytes; +} + +void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { + assert(s && cb); + s->read_callback = cb; + s->read_userdata = userdata; +} + +int pa_stream_is_dead(struct pa_stream *s) { + return s->state == STREAM_DEAD; +} + +int pa_stream_is_ready(struct pa_stream*s) { + return s->state == STREAM_READY; +} + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { + assert(s); + s->die_callback = cb; + s->die_userdata = userdata; +} + +int pa_context_is_pending(struct pa_context *c) { + assert(c); + + if (c->state != CONTEXT_READY) + return 0; + + return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); +} + +struct pa_context* pa_stream_get_context(struct pa_stream *p) { + assert(p); + return p->context; +} + +static void set_dispatch_callbacks(struct pa_context *c); + +static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void set_dispatch_callbacks(struct pa_context *c) { + assert(c && c->state == CONTEXT_READY); + + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + + if (pa_pdispatch_is_pending(c->pdispatch)) { + pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); + return; + } + + if (pa_pstream_is_pending(c->pstream)) { + pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); + return; + } + + assert(c->drain_complete_callback); + c->drain_complete_callback(c, c->drain_complete_userdata); +} + +int pa_context_drain( + struct pa_context *c, + void (*complete) (struct pa_context*c, void *userdata), + void *userdata) { + + assert(c && c->state == CONTEXT_READY); + + if (complete == NULL) { + c->drain_complete_callback = NULL; + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + return 0; + } + + if (!pa_context_is_pending(c)) + return -1; + + c->drain_complete_callback = complete; + c->drain_complete_userdata = userdata; + + set_dispatch_callbacks(c); + + return 0; +} + +static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + return; + } + + if (s->state != STREAM_READY) + return; + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->drain_complete_callback) { + void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; + s->drain_complete_callback = NULL; + temp(s, s->drain_complete_userdata); + } +} + + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->state == STREAM_READY); + + if (!complete) { + s->drain_complete_callback = NULL; + return; + } + + s->drain_complete_callback = complete; + s->drain_complete_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); +} + +void pa_context_exit(struct pa_context *c) { + struct pa_tagstruct *t; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_EXIT); + pa_tagstruct_putu32(t, c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + uint32_t total, count; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &count) < 0 || + pa_tagstruct_getu32(t, &total) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, count, total, c->stat_userdata); +} + +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + c->stat_callback = cb; + c->stat_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_STAT); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); +} + +static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + uint32_t latency; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &latency) < 0 || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, latency, s->get_latency_userdata); +} + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + p->get_latency_callback = cb; + p->get_latency_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); +} + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_stream *s; + struct pa_tagstruct *t; + uint32_t tag; + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = cb; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = PA_STREAM_UPLOAD; + s->sample_spec = *ss; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_sample_spec(t, ss); + pa_tagstruct_putu32(t, length); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); + + return s; +} + +static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 0, s->finish_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 1, s->finish_sample_userdata); +} + +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(p); + + p->finish_sample_callback = cb; + p->finish_sample_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); +} + +static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 0, c->play_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 1, c->play_sample_userdata); +} + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name && *name && (!dev || *dev)); + + c->play_sample_callback = cb; + c->play_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, volume); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); +} + +static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 0, c->remove_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 1, c->remove_sample_userdata); +} + +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name); + + c->remove_sample_callback = cb; + c->remove_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); +} + +static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_server_info i; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, NULL, c->get_server_info_userdata); + return; + } + + if (pa_tagstruct_gets(t, &i.server_name) < 0 || + pa_tagstruct_gets(t, &i.server_version) < 0 || + pa_tagstruct_gets(t, &i.user_name) < 0 || + pa_tagstruct_gets(t, &i.host_name) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, &i, c->get_server_info_userdata); +} + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_server_info_callback = cb; + c->get_server_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); +} + +static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_sink_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.monitor_source) < 0 || + pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || + pa_tagstruct_getu32(t, &i.latency) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); +} + +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_source_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || + pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); +} + +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + struct pa_tagstruct *t; + assert(c); + + c->subscribe_callback = cb; + c->subscribe_userdata = userdata; + c->subscribe_mask = m; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); + pa_tagstruct_putu32(t, c->ctag++); + pa_tagstruct_putu32(t, cb ? m : 0); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + enum pa_subscription_event_type e; + uint32_t index; + assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); + + if (pa_tagstruct_getu32(t, &e) < 0 || + pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) + c->subscribe_callback(c, e, index, c->subscribe_userdata); +} + +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_client_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.protocol_name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); +} + + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_module_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0 || + pa_tagstruct_getu32(t, &i.n_used) < 0 || + pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); +} + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} + +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h new file mode 100644 index 000000000..a0dd9f9cb --- /dev/null +++ b/polyp/polyplib-introspect.h @@ -0,0 +1,178 @@ +#ifndef foopolyplibhfoo +#define foopolyplibhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "sample.h" +#include "polyplib-def.h" +#include "mainloop-api.h" + +#ifdef __cplusplus +//extern "C" { +#endif + +struct pa_context; +struct pa_stream; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); +void pa_context_unref(struct pa_context *c); +struct pa_context* pa_context_ref(struct pa_context *c); + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); +int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); + +int pa_context_is_dead(struct pa_context *c); +int pa_context_is_ready(struct pa_context *c); +int pa_context_errno(struct pa_context *c); + +int pa_context_is_pending(struct pa_context *c); + +struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_unref(struct pa_stream *s); +struct pa_stream *pa_stream_ref(struct pa_stream *s); + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); + +void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); +void pa_stream_write(struct pa_stream *p, const void *data, size_t length); +size_t pa_stream_writable_size(struct pa_stream *p); + +void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); + +int pa_stream_is_dead(struct pa_stream *p); +int pa_stream_is_ready(struct pa_stream*p); + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); + +struct pa_context* pa_stream_get_context(struct pa_stream *p); + +uint32_t pa_stream_get_index(struct pa_stream *s); + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +struct pa_sink_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t volume; + uint32_t monitor_source; + const char *monitor_source_name; + uint32_t latency; +}; + +void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); + +struct pa_source_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t monitor_of_sink; + const char *monitor_of_sink_name; +}; + +void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); + +struct pa_server_info { + const char *user_name; + const char *host_name; + const char *server_version; + const char *server_name; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); + +struct pa_module_info { + uint32_t index; + const char*name, *argument; + uint32_t n_used, auto_unload; +}; + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); + +struct pa_client_info { + uint32_t index; + const char *name; + uint32_t owner_module; + const char *protocol_name; +}; + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); + +struct pa_sink_input_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t sink; + struct pa_sample_spec sample_spec; + uint32_t volume; + uint32_t latency; +}; + +void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); + +struct pa_source_output_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t source; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); + +void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +void pa_context_exit(struct pa_context *c); +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c new file mode 100644 index 000000000..35001d3d3 --- /dev/null +++ b/polyp/polyplib-stream.c @@ -0,0 +1,1550 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "polyplib.h" +#include "native-common.h" +#include "pdispatch.h" +#include "pstream.h" +#include "dynarray.h" +#include "socket-client.h" +#include "pstream-util.h" +#include "authkey.h" +#include "util.h" +#include "xmalloc.h" + +#define DEFAULT_MAXLENGTH 204800 +#define DEFAULT_TLENGTH 10240 +#define DEFAULT_PREBUF 4096 +#define DEFAULT_MINREQ 1024 +#define DEFAULT_FRAGSIZE 1024 + +#define DEFAULT_TIMEOUT (5*60) +#define DEFAULT_SERVER "/tmp/polypaudio/native" +#define DEFAULT_PORT "4713" + +struct pa_context { + char *name; + struct pa_mainloop_api* mainloop; + struct pa_socket_client *client; + struct pa_pstream *pstream; + struct pa_pdispatch *pdispatch; + struct pa_dynarray *record_streams, *playback_streams; + struct pa_stream *first_stream; + uint32_t ctag; + uint32_t error; + enum { + CONTEXT_UNCONNECTED, + CONTEXT_CONNECTING, + CONTEXT_AUTHORIZING, + CONTEXT_SETTING_NAME, + CONTEXT_READY, + CONTEXT_DEAD + } state; + + void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); + void *connect_complete_userdata; + + void (*drain_complete_callback)(struct pa_context*c, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_context*c, void *userdata); + void *die_userdata; + + void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); + void *stat_userdata; + + void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); + void *play_sample_userdata; + + void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); + void *remove_sample_userdata; + + void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); + void *get_server_info_userdata; + + void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); + void *get_sink_info_userdata; + + void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); + void *get_source_info_userdata; + + void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void *subscribe_userdata; + enum pa_subscription_mask subscribe_mask; + + void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); + void *get_client_info_userdata; + + void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); + void *get_module_info_userdata; + + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; +}; + +struct pa_stream { + struct pa_context *context; + struct pa_stream *next, *previous; + + char *name; + struct pa_buffer_attr buffer_attr; + struct pa_sample_spec sample_spec; + uint32_t channel; + int channel_valid; + uint32_t device_index; + enum pa_stream_direction direction; + + enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; + uint32_t requested_bytes; + + void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); + void *read_userdata; + + void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); + void *write_userdata; + + void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); + void *create_complete_userdata; + + void (*drain_complete_callback)(struct pa_stream *s, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_stream*c, void *userdata); + void *die_userdata; + + void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); + void *get_latency_userdata; + + void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); + void *finish_sample_userdata; +}; + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + +static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = { NULL }, + [PA_COMMAND_REPLY] = { NULL }, + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_EXIT] = { NULL }, + [PA_COMMAND_REQUEST] = { command_request }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, +}; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { + struct pa_context *c; + assert(mainloop && name); + + c = pa_xmalloc(sizeof(struct pa_context)); + c->name = pa_xstrdup(name); + c->mainloop = mainloop; + c->client = NULL; + c->pstream = NULL; + c->pdispatch = NULL; + c->playback_streams = pa_dynarray_new(); + assert(c->playback_streams); + c->record_streams = pa_dynarray_new(); + assert(c->record_streams); + c->first_stream = NULL; + c->error = PA_ERROR_OK; + c->state = CONTEXT_UNCONNECTED; + c->ctag = 0; + + c->connect_complete_callback = NULL; + c->connect_complete_userdata = NULL; + + c->drain_complete_callback = NULL; + c->drain_complete_userdata = NULL; + + c->die_callback = NULL; + c->die_userdata = NULL; + + c->stat_callback = NULL; + c->stat_userdata = NULL; + + c->play_sample_callback = NULL; + c->play_sample_userdata = NULL; + + c->remove_sample_callback = NULL; + c->remove_sample_userdata = NULL; + + c->get_server_info_callback = NULL; + c->get_server_info_userdata = NULL; + + c->get_sink_info_callback = NULL; + c->get_sink_info_userdata = NULL; + + c->get_source_info_callback = NULL; + c->get_source_info_userdata = NULL; + + c->subscribe_callback = NULL; + c->subscribe_userdata = NULL; + + c->get_client_info_callback = NULL; + c->get_client_info_userdata = NULL; + + c->get_module_info_callback = NULL; + c->get_module_info_userdata = NULL; + + pa_check_for_sigpipe(); + return c; +} + +void pa_context_free(struct pa_context *c) { + assert(c); + + while (c->first_stream) + pa_stream_free(c->first_stream); + + if (c->client) + pa_socket_client_free(c->client); + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + if (c->pstream) + pa_pstream_free(c->pstream); + if (c->record_streams) + pa_dynarray_free(c->record_streams, NULL, NULL); + if (c->playback_streams) + pa_dynarray_free(c->playback_streams, NULL, NULL); + + pa_xfree(c->name); + pa_xfree(c); +} + +static void stream_dead(struct pa_stream *s) { + assert(s); + + if (s->state == STREAM_DEAD) + return; + + if (s->state == STREAM_READY) { + s->state = STREAM_DEAD; + if (s->die_callback) + s->die_callback(s, s->die_userdata); + } else + s->state = STREAM_DEAD; +} + +static void context_dead(struct pa_context *c) { + struct pa_stream *s; + assert(c); + + if (c->state == CONTEXT_DEAD) + return; + + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + c->pdispatch = NULL; + + if (c->pstream) + pa_pstream_free(c->pstream); + c->pstream = NULL; + + if (c->client) + pa_socket_client_free(c->client); + c->client = NULL; + + for (s = c->first_stream; s; s = s->next) + stream_dead(s); + + if (c->state == CONTEXT_READY) { + c->state = CONTEXT_DEAD; + if (c->die_callback) + c->die_callback(c, c->die_userdata); + } else + c->state = CONTEXT_DEAD; +} + +static void pstream_die_callback(struct pa_pstream *p, void *userdata) { + struct pa_context *c = userdata; + assert(p && c); + c->error = PA_ERROR_CONNECTIONTERMINATED; + context_dead(c); +} + +static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { + struct pa_context *c = userdata; + assert(p && packet && c); + + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { + fprintf(stderr, "polyp.c: invalid packet.\n"); + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + } +} + +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + assert(p && chunk && c && chunk->memblock && chunk->memblock->data); + + if (!(s = pa_dynarray_get(c->record_streams, channel))) + return; + + if (s->read_callback) + s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); +} + +static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { + assert(c && t); + + if (command == PA_COMMAND_ERROR) { + if (pa_tagstruct_getu32(t, &c->error) < 0) { + c->error = PA_ERROR_PROTOCOL; + return -1; + } + + return 0; + } + + c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; + return -1; +} + +static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); + + if (command != PA_COMMAND_REPLY) { + handle_error(c, command, t); + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + if (c->state == CONTEXT_AUTHORIZING) { + struct pa_tagstruct *t; + c->state = CONTEXT_SETTING_NAME; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, c->name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + } else { + assert(c->state == CONTEXT_SETTING_NAME); + + c->state = CONTEXT_READY; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 1, c->connect_complete_userdata); + } + + return; +} + +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { + struct pa_context *c = userdata; + struct pa_tagstruct *t; + uint32_t tag; + assert(client && c && c->state == CONTEXT_CONNECTING); + + pa_socket_client_free(client); + c->client = NULL; + + if (!io) { + c->error = PA_ERROR_CONNECTIONREFUSED; + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + c->pstream = pa_pstream_new(c->mainloop, io); + assert(c->pstream); + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + + c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); + assert(c->pdispatch); + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_AUTH); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + c->state = CONTEXT_AUTHORIZING; +} + +static struct sockaddr *resolve_server(const char *server, size_t *len) { + struct sockaddr *sa; + struct addrinfo hints, *result = NULL; + char *port; + assert(server && len); + + if ((port = strrchr(server, ':'))) + port++; + if (!port) + port = DEFAULT_PORT; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + if (getaddrinfo(server, port, &hints, &result) != 0) + return NULL; + assert(result); + + sa = pa_xmalloc(*len = result->ai_addrlen); + memcpy(sa, result->ai_addr, *len); + + freeaddrinfo(result); + + return sa; +} + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { + assert(c && c->state == CONTEXT_UNCONNECTED); + + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { + c->error = PA_ERROR_AUTHKEY; + return -1; + } + + if (!server) + if (!(server = getenv("POLYP_SERVER"))) + server = DEFAULT_SERVER; + + assert(!c->client); + + if (*server == '/') { + if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } else { + struct sockaddr* sa; + size_t sa_len; + + if (!(sa = resolve_server(server, &sa_len))) { + c->error = PA_ERROR_INVALIDSERVER; + return -1; + } + + c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); + pa_xfree(sa); + + if (!c->client) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } + + c->connect_complete_callback = complete; + c->connect_complete_userdata = userdata; + + pa_socket_client_set_callback(c->client, on_connection, c); + c->state = CONTEXT_CONNECTING; + + return 0; +} + +int pa_context_is_dead(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_DEAD; +} + +int pa_context_is_ready(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_READY; +} + +int pa_context_errno(struct pa_context *c) { + assert(c); + return c->error; +} + +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { + assert(c); + c->die_callback = cb; + c->die_userdata = userdata; +} + +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + uint32_t channel; + assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) + return; + + c->error = PA_ERROR_KILLED; + stream_dead(s); +} + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s; + struct pa_context *c = userdata; + uint32_t bytes, channel; + assert(pd && command == PA_COMMAND_REQUEST && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_getu32(t, &bytes) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(c->playback_streams, channel))) + return; + + if (s->state != STREAM_READY) + return; + + s->requested_bytes += bytes; + + if (s->requested_bytes && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); +} + +static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s && s->state == STREAM_CREATING); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + if (s->create_complete_callback) + s->create_complete_callback(s, 0, s->create_complete_userdata); + + return; + } + + if (pa_tagstruct_getu32(t, &s->channel) < 0 || + ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + s->channel_valid = 1; + pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); + + s->state = STREAM_READY; + if (s->create_complete_callback) + s->create_complete_callback(s, 1, s->create_complete_userdata); +} + +static void create_stream(struct pa_stream *s, const char *dev) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s); + + s->state = STREAM_CREATING; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_puts(t, s->name); + pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, s->buffer_attr.maxlength); + if (s->direction == PA_STREAM_PLAYBACK) { + pa_tagstruct_putu32(t, s->buffer_attr.tlength); + pa_tagstruct_putu32(t, s->buffer_attr.prebuf); + pa_tagstruct_putu32(t, s->buffer_attr.minreq); + } else + pa_tagstruct_putu32(t, s->buffer_attr.fragsize); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); +} + +static struct pa_stream *internal_stream_new(struct pa_context *c) { + struct pa_stream *s; + + s = pa_xmalloc(sizeof(struct pa_stream)); + s->context = c; + + s->read_callback = NULL; + s->read_userdata = NULL; + s->write_callback = NULL; + s->write_userdata = NULL; + s->die_callback = NULL; + s->die_userdata = NULL; + s->create_complete_callback = NULL; + s->create_complete_userdata = NULL; + s->get_latency_callback = NULL; + s->get_latency_userdata = NULL; + s->finish_sample_callback = NULL; + s->finish_sample_userdata = NULL; + + s->name = NULL; + s->state = STREAM_CREATING; + s->requested_bytes = 0; + s->channel = 0; + s->channel_valid = 0; + s->device_index = (uint32_t) -1; + + memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + + s->next = c->first_stream; + if (s->next) + s->next->previous = s; + s->previous = NULL; + c->first_stream = s; + + return s; +} + +struct pa_stream* pa_stream_new( + struct pa_context *c, + enum pa_stream_direction dir, + const char *dev, + const char *name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr, + void (*complete) (struct pa_stream*s, int success, void *userdata), + void *userdata) { + + struct pa_stream *s; + + assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = complete; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = dir; + s->sample_spec = *ss; + if (attr) + s->buffer_attr = *attr; + else { + s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; + s->buffer_attr.tlength = DEFAULT_TLENGTH; + s->buffer_attr.prebuf = DEFAULT_PREBUF; + s->buffer_attr.minreq = DEFAULT_MINREQ; + s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; + } + + create_stream(s, dev); + + return s; +} + +void pa_stream_free(struct pa_stream *s) { + assert(s && s->context); + + if (s->context->pdispatch) + pa_pdispatch_unregister_reply(s->context->pdispatch, s); + + pa_xfree(s->name); + + if (s->channel_valid && s->context->state == CONTEXT_READY) { + struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); + pa_tagstruct_putu32(t, s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + } + + if (s->channel_valid) + pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); + + if (s->next) + s->next->previous = s->previous; + if (s->previous) + s->previous->next = s->next; + else + s->context->first_stream = s->next; + + pa_xfree(s); +} + +void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { + s->write_callback = cb; + s->write_userdata = userdata; +} + +void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { + struct pa_memchunk chunk; + assert(s && s->context && data && length && s->state == STREAM_READY); + + chunk.memblock = pa_memblock_new(length); + assert(chunk.memblock && chunk.memblock->data); + memcpy(chunk.memblock->data, data, length); + chunk.index = 0; + chunk.length = length; + + pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + pa_memblock_unref(chunk.memblock); + + /*fprintf(stderr, "Sent %u bytes\n", length);*/ + + if (length < s->requested_bytes) + s->requested_bytes -= length; + else + s->requested_bytes = 0; +} + +size_t pa_stream_writable_size(struct pa_stream *s) { + assert(s && s->state == STREAM_READY); + return s->requested_bytes; +} + +void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { + assert(s && cb); + s->read_callback = cb; + s->read_userdata = userdata; +} + +int pa_stream_is_dead(struct pa_stream *s) { + return s->state == STREAM_DEAD; +} + +int pa_stream_is_ready(struct pa_stream*s) { + return s->state == STREAM_READY; +} + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { + assert(s); + s->die_callback = cb; + s->die_userdata = userdata; +} + +int pa_context_is_pending(struct pa_context *c) { + assert(c); + + if (c->state != CONTEXT_READY) + return 0; + + return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); +} + +struct pa_context* pa_stream_get_context(struct pa_stream *p) { + assert(p); + return p->context; +} + +static void set_dispatch_callbacks(struct pa_context *c); + +static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void set_dispatch_callbacks(struct pa_context *c) { + assert(c && c->state == CONTEXT_READY); + + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + + if (pa_pdispatch_is_pending(c->pdispatch)) { + pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); + return; + } + + if (pa_pstream_is_pending(c->pstream)) { + pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); + return; + } + + assert(c->drain_complete_callback); + c->drain_complete_callback(c, c->drain_complete_userdata); +} + +int pa_context_drain( + struct pa_context *c, + void (*complete) (struct pa_context*c, void *userdata), + void *userdata) { + + assert(c && c->state == CONTEXT_READY); + + if (complete == NULL) { + c->drain_complete_callback = NULL; + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + return 0; + } + + if (!pa_context_is_pending(c)) + return -1; + + c->drain_complete_callback = complete; + c->drain_complete_userdata = userdata; + + set_dispatch_callbacks(c); + + return 0; +} + +static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + return; + } + + if (s->state != STREAM_READY) + return; + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->drain_complete_callback) { + void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; + s->drain_complete_callback = NULL; + temp(s, s->drain_complete_userdata); + } +} + + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->state == STREAM_READY); + + if (!complete) { + s->drain_complete_callback = NULL; + return; + } + + s->drain_complete_callback = complete; + s->drain_complete_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); +} + +void pa_context_exit(struct pa_context *c) { + struct pa_tagstruct *t; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_EXIT); + pa_tagstruct_putu32(t, c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + uint32_t total, count; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &count) < 0 || + pa_tagstruct_getu32(t, &total) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, count, total, c->stat_userdata); +} + +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + c->stat_callback = cb; + c->stat_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_STAT); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); +} + +static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + uint32_t latency; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &latency) < 0 || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, latency, s->get_latency_userdata); +} + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + p->get_latency_callback = cb; + p->get_latency_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); +} + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_stream *s; + struct pa_tagstruct *t; + uint32_t tag; + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = cb; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = PA_STREAM_UPLOAD; + s->sample_spec = *ss; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_sample_spec(t, ss); + pa_tagstruct_putu32(t, length); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); + + return s; +} + +static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 0, s->finish_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 1, s->finish_sample_userdata); +} + +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(p); + + p->finish_sample_callback = cb; + p->finish_sample_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); +} + +static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 0, c->play_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 1, c->play_sample_userdata); +} + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name && *name && (!dev || *dev)); + + c->play_sample_callback = cb; + c->play_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, volume); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); +} + +static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 0, c->remove_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 1, c->remove_sample_userdata); +} + +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name); + + c->remove_sample_callback = cb; + c->remove_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); +} + +static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_server_info i; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, NULL, c->get_server_info_userdata); + return; + } + + if (pa_tagstruct_gets(t, &i.server_name) < 0 || + pa_tagstruct_gets(t, &i.server_version) < 0 || + pa_tagstruct_gets(t, &i.user_name) < 0 || + pa_tagstruct_gets(t, &i.host_name) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, &i, c->get_server_info_userdata); +} + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_server_info_callback = cb; + c->get_server_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); +} + +static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_sink_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.monitor_source) < 0 || + pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || + pa_tagstruct_getu32(t, &i.latency) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); +} + +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_source_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || + pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); +} + +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + struct pa_tagstruct *t; + assert(c); + + c->subscribe_callback = cb; + c->subscribe_userdata = userdata; + c->subscribe_mask = m; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); + pa_tagstruct_putu32(t, c->ctag++); + pa_tagstruct_putu32(t, cb ? m : 0); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + enum pa_subscription_event_type e; + uint32_t index; + assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); + + if (pa_tagstruct_getu32(t, &e) < 0 || + pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) + c->subscribe_callback(c, e, index, c->subscribe_userdata); +} + +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_client_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.protocol_name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); +} + + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_module_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0 || + pa_tagstruct_getu32(t, &i.n_used) < 0 || + pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); +} + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} + +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h new file mode 100644 index 000000000..a0dd9f9cb --- /dev/null +++ b/polyp/polyplib-stream.h @@ -0,0 +1,178 @@ +#ifndef foopolyplibhfoo +#define foopolyplibhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "sample.h" +#include "polyplib-def.h" +#include "mainloop-api.h" + +#ifdef __cplusplus +//extern "C" { +#endif + +struct pa_context; +struct pa_stream; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); +void pa_context_unref(struct pa_context *c); +struct pa_context* pa_context_ref(struct pa_context *c); + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); +int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); + +int pa_context_is_dead(struct pa_context *c); +int pa_context_is_ready(struct pa_context *c); +int pa_context_errno(struct pa_context *c); + +int pa_context_is_pending(struct pa_context *c); + +struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_unref(struct pa_stream *s); +struct pa_stream *pa_stream_ref(struct pa_stream *s); + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); + +void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); +void pa_stream_write(struct pa_stream *p, const void *data, size_t length); +size_t pa_stream_writable_size(struct pa_stream *p); + +void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); + +int pa_stream_is_dead(struct pa_stream *p); +int pa_stream_is_ready(struct pa_stream*p); + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); + +struct pa_context* pa_stream_get_context(struct pa_stream *p); + +uint32_t pa_stream_get_index(struct pa_stream *s); + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +struct pa_sink_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t volume; + uint32_t monitor_source; + const char *monitor_source_name; + uint32_t latency; +}; + +void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); + +struct pa_source_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t monitor_of_sink; + const char *monitor_of_sink_name; +}; + +void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); + +struct pa_server_info { + const char *user_name; + const char *host_name; + const char *server_version; + const char *server_name; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); + +struct pa_module_info { + uint32_t index; + const char*name, *argument; + uint32_t n_used, auto_unload; +}; + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); + +struct pa_client_info { + uint32_t index; + const char *name; + uint32_t owner_module; + const char *protocol_name; +}; + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); + +struct pa_sink_input_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t sink; + struct pa_sample_spec sample_spec; + uint32_t volume; + uint32_t latency; +}; + +void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); + +struct pa_source_output_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t source; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); + +void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +void pa_context_exit(struct pa_context *c); +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/polyp/polyplib-subscribe.c b/polyp/polyplib-subscribe.c new file mode 100644 index 000000000..35001d3d3 --- /dev/null +++ b/polyp/polyplib-subscribe.c @@ -0,0 +1,1550 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "polyplib.h" +#include "native-common.h" +#include "pdispatch.h" +#include "pstream.h" +#include "dynarray.h" +#include "socket-client.h" +#include "pstream-util.h" +#include "authkey.h" +#include "util.h" +#include "xmalloc.h" + +#define DEFAULT_MAXLENGTH 204800 +#define DEFAULT_TLENGTH 10240 +#define DEFAULT_PREBUF 4096 +#define DEFAULT_MINREQ 1024 +#define DEFAULT_FRAGSIZE 1024 + +#define DEFAULT_TIMEOUT (5*60) +#define DEFAULT_SERVER "/tmp/polypaudio/native" +#define DEFAULT_PORT "4713" + +struct pa_context { + char *name; + struct pa_mainloop_api* mainloop; + struct pa_socket_client *client; + struct pa_pstream *pstream; + struct pa_pdispatch *pdispatch; + struct pa_dynarray *record_streams, *playback_streams; + struct pa_stream *first_stream; + uint32_t ctag; + uint32_t error; + enum { + CONTEXT_UNCONNECTED, + CONTEXT_CONNECTING, + CONTEXT_AUTHORIZING, + CONTEXT_SETTING_NAME, + CONTEXT_READY, + CONTEXT_DEAD + } state; + + void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); + void *connect_complete_userdata; + + void (*drain_complete_callback)(struct pa_context*c, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_context*c, void *userdata); + void *die_userdata; + + void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); + void *stat_userdata; + + void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); + void *play_sample_userdata; + + void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); + void *remove_sample_userdata; + + void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); + void *get_server_info_userdata; + + void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); + void *get_sink_info_userdata; + + void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); + void *get_source_info_userdata; + + void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void *subscribe_userdata; + enum pa_subscription_mask subscribe_mask; + + void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); + void *get_client_info_userdata; + + void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); + void *get_module_info_userdata; + + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; +}; + +struct pa_stream { + struct pa_context *context; + struct pa_stream *next, *previous; + + char *name; + struct pa_buffer_attr buffer_attr; + struct pa_sample_spec sample_spec; + uint32_t channel; + int channel_valid; + uint32_t device_index; + enum pa_stream_direction direction; + + enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; + uint32_t requested_bytes; + + void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); + void *read_userdata; + + void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); + void *write_userdata; + + void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); + void *create_complete_userdata; + + void (*drain_complete_callback)(struct pa_stream *s, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_stream*c, void *userdata); + void *die_userdata; + + void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); + void *get_latency_userdata; + + void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); + void *finish_sample_userdata; +}; + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + +static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = { NULL }, + [PA_COMMAND_REPLY] = { NULL }, + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_EXIT] = { NULL }, + [PA_COMMAND_REQUEST] = { command_request }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, +}; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { + struct pa_context *c; + assert(mainloop && name); + + c = pa_xmalloc(sizeof(struct pa_context)); + c->name = pa_xstrdup(name); + c->mainloop = mainloop; + c->client = NULL; + c->pstream = NULL; + c->pdispatch = NULL; + c->playback_streams = pa_dynarray_new(); + assert(c->playback_streams); + c->record_streams = pa_dynarray_new(); + assert(c->record_streams); + c->first_stream = NULL; + c->error = PA_ERROR_OK; + c->state = CONTEXT_UNCONNECTED; + c->ctag = 0; + + c->connect_complete_callback = NULL; + c->connect_complete_userdata = NULL; + + c->drain_complete_callback = NULL; + c->drain_complete_userdata = NULL; + + c->die_callback = NULL; + c->die_userdata = NULL; + + c->stat_callback = NULL; + c->stat_userdata = NULL; + + c->play_sample_callback = NULL; + c->play_sample_userdata = NULL; + + c->remove_sample_callback = NULL; + c->remove_sample_userdata = NULL; + + c->get_server_info_callback = NULL; + c->get_server_info_userdata = NULL; + + c->get_sink_info_callback = NULL; + c->get_sink_info_userdata = NULL; + + c->get_source_info_callback = NULL; + c->get_source_info_userdata = NULL; + + c->subscribe_callback = NULL; + c->subscribe_userdata = NULL; + + c->get_client_info_callback = NULL; + c->get_client_info_userdata = NULL; + + c->get_module_info_callback = NULL; + c->get_module_info_userdata = NULL; + + pa_check_for_sigpipe(); + return c; +} + +void pa_context_free(struct pa_context *c) { + assert(c); + + while (c->first_stream) + pa_stream_free(c->first_stream); + + if (c->client) + pa_socket_client_free(c->client); + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + if (c->pstream) + pa_pstream_free(c->pstream); + if (c->record_streams) + pa_dynarray_free(c->record_streams, NULL, NULL); + if (c->playback_streams) + pa_dynarray_free(c->playback_streams, NULL, NULL); + + pa_xfree(c->name); + pa_xfree(c); +} + +static void stream_dead(struct pa_stream *s) { + assert(s); + + if (s->state == STREAM_DEAD) + return; + + if (s->state == STREAM_READY) { + s->state = STREAM_DEAD; + if (s->die_callback) + s->die_callback(s, s->die_userdata); + } else + s->state = STREAM_DEAD; +} + +static void context_dead(struct pa_context *c) { + struct pa_stream *s; + assert(c); + + if (c->state == CONTEXT_DEAD) + return; + + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + c->pdispatch = NULL; + + if (c->pstream) + pa_pstream_free(c->pstream); + c->pstream = NULL; + + if (c->client) + pa_socket_client_free(c->client); + c->client = NULL; + + for (s = c->first_stream; s; s = s->next) + stream_dead(s); + + if (c->state == CONTEXT_READY) { + c->state = CONTEXT_DEAD; + if (c->die_callback) + c->die_callback(c, c->die_userdata); + } else + c->state = CONTEXT_DEAD; +} + +static void pstream_die_callback(struct pa_pstream *p, void *userdata) { + struct pa_context *c = userdata; + assert(p && c); + c->error = PA_ERROR_CONNECTIONTERMINATED; + context_dead(c); +} + +static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { + struct pa_context *c = userdata; + assert(p && packet && c); + + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { + fprintf(stderr, "polyp.c: invalid packet.\n"); + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + } +} + +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + assert(p && chunk && c && chunk->memblock && chunk->memblock->data); + + if (!(s = pa_dynarray_get(c->record_streams, channel))) + return; + + if (s->read_callback) + s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); +} + +static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { + assert(c && t); + + if (command == PA_COMMAND_ERROR) { + if (pa_tagstruct_getu32(t, &c->error) < 0) { + c->error = PA_ERROR_PROTOCOL; + return -1; + } + + return 0; + } + + c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; + return -1; +} + +static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); + + if (command != PA_COMMAND_REPLY) { + handle_error(c, command, t); + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + if (c->state == CONTEXT_AUTHORIZING) { + struct pa_tagstruct *t; + c->state = CONTEXT_SETTING_NAME; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, c->name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + } else { + assert(c->state == CONTEXT_SETTING_NAME); + + c->state = CONTEXT_READY; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 1, c->connect_complete_userdata); + } + + return; +} + +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { + struct pa_context *c = userdata; + struct pa_tagstruct *t; + uint32_t tag; + assert(client && c && c->state == CONTEXT_CONNECTING); + + pa_socket_client_free(client); + c->client = NULL; + + if (!io) { + c->error = PA_ERROR_CONNECTIONREFUSED; + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + c->pstream = pa_pstream_new(c->mainloop, io); + assert(c->pstream); + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + + c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); + assert(c->pdispatch); + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_AUTH); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + c->state = CONTEXT_AUTHORIZING; +} + +static struct sockaddr *resolve_server(const char *server, size_t *len) { + struct sockaddr *sa; + struct addrinfo hints, *result = NULL; + char *port; + assert(server && len); + + if ((port = strrchr(server, ':'))) + port++; + if (!port) + port = DEFAULT_PORT; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + if (getaddrinfo(server, port, &hints, &result) != 0) + return NULL; + assert(result); + + sa = pa_xmalloc(*len = result->ai_addrlen); + memcpy(sa, result->ai_addr, *len); + + freeaddrinfo(result); + + return sa; +} + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { + assert(c && c->state == CONTEXT_UNCONNECTED); + + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { + c->error = PA_ERROR_AUTHKEY; + return -1; + } + + if (!server) + if (!(server = getenv("POLYP_SERVER"))) + server = DEFAULT_SERVER; + + assert(!c->client); + + if (*server == '/') { + if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } else { + struct sockaddr* sa; + size_t sa_len; + + if (!(sa = resolve_server(server, &sa_len))) { + c->error = PA_ERROR_INVALIDSERVER; + return -1; + } + + c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); + pa_xfree(sa); + + if (!c->client) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } + + c->connect_complete_callback = complete; + c->connect_complete_userdata = userdata; + + pa_socket_client_set_callback(c->client, on_connection, c); + c->state = CONTEXT_CONNECTING; + + return 0; +} + +int pa_context_is_dead(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_DEAD; +} + +int pa_context_is_ready(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_READY; +} + +int pa_context_errno(struct pa_context *c) { + assert(c); + return c->error; +} + +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { + assert(c); + c->die_callback = cb; + c->die_userdata = userdata; +} + +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + uint32_t channel; + assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) + return; + + c->error = PA_ERROR_KILLED; + stream_dead(s); +} + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s; + struct pa_context *c = userdata; + uint32_t bytes, channel; + assert(pd && command == PA_COMMAND_REQUEST && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_getu32(t, &bytes) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(c->playback_streams, channel))) + return; + + if (s->state != STREAM_READY) + return; + + s->requested_bytes += bytes; + + if (s->requested_bytes && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); +} + +static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s && s->state == STREAM_CREATING); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + if (s->create_complete_callback) + s->create_complete_callback(s, 0, s->create_complete_userdata); + + return; + } + + if (pa_tagstruct_getu32(t, &s->channel) < 0 || + ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + s->channel_valid = 1; + pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); + + s->state = STREAM_READY; + if (s->create_complete_callback) + s->create_complete_callback(s, 1, s->create_complete_userdata); +} + +static void create_stream(struct pa_stream *s, const char *dev) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s); + + s->state = STREAM_CREATING; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_puts(t, s->name); + pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, s->buffer_attr.maxlength); + if (s->direction == PA_STREAM_PLAYBACK) { + pa_tagstruct_putu32(t, s->buffer_attr.tlength); + pa_tagstruct_putu32(t, s->buffer_attr.prebuf); + pa_tagstruct_putu32(t, s->buffer_attr.minreq); + } else + pa_tagstruct_putu32(t, s->buffer_attr.fragsize); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); +} + +static struct pa_stream *internal_stream_new(struct pa_context *c) { + struct pa_stream *s; + + s = pa_xmalloc(sizeof(struct pa_stream)); + s->context = c; + + s->read_callback = NULL; + s->read_userdata = NULL; + s->write_callback = NULL; + s->write_userdata = NULL; + s->die_callback = NULL; + s->die_userdata = NULL; + s->create_complete_callback = NULL; + s->create_complete_userdata = NULL; + s->get_latency_callback = NULL; + s->get_latency_userdata = NULL; + s->finish_sample_callback = NULL; + s->finish_sample_userdata = NULL; + + s->name = NULL; + s->state = STREAM_CREATING; + s->requested_bytes = 0; + s->channel = 0; + s->channel_valid = 0; + s->device_index = (uint32_t) -1; + + memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + + s->next = c->first_stream; + if (s->next) + s->next->previous = s; + s->previous = NULL; + c->first_stream = s; + + return s; +} + +struct pa_stream* pa_stream_new( + struct pa_context *c, + enum pa_stream_direction dir, + const char *dev, + const char *name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr, + void (*complete) (struct pa_stream*s, int success, void *userdata), + void *userdata) { + + struct pa_stream *s; + + assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = complete; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = dir; + s->sample_spec = *ss; + if (attr) + s->buffer_attr = *attr; + else { + s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; + s->buffer_attr.tlength = DEFAULT_TLENGTH; + s->buffer_attr.prebuf = DEFAULT_PREBUF; + s->buffer_attr.minreq = DEFAULT_MINREQ; + s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; + } + + create_stream(s, dev); + + return s; +} + +void pa_stream_free(struct pa_stream *s) { + assert(s && s->context); + + if (s->context->pdispatch) + pa_pdispatch_unregister_reply(s->context->pdispatch, s); + + pa_xfree(s->name); + + if (s->channel_valid && s->context->state == CONTEXT_READY) { + struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); + pa_tagstruct_putu32(t, s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + } + + if (s->channel_valid) + pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); + + if (s->next) + s->next->previous = s->previous; + if (s->previous) + s->previous->next = s->next; + else + s->context->first_stream = s->next; + + pa_xfree(s); +} + +void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { + s->write_callback = cb; + s->write_userdata = userdata; +} + +void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { + struct pa_memchunk chunk; + assert(s && s->context && data && length && s->state == STREAM_READY); + + chunk.memblock = pa_memblock_new(length); + assert(chunk.memblock && chunk.memblock->data); + memcpy(chunk.memblock->data, data, length); + chunk.index = 0; + chunk.length = length; + + pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + pa_memblock_unref(chunk.memblock); + + /*fprintf(stderr, "Sent %u bytes\n", length);*/ + + if (length < s->requested_bytes) + s->requested_bytes -= length; + else + s->requested_bytes = 0; +} + +size_t pa_stream_writable_size(struct pa_stream *s) { + assert(s && s->state == STREAM_READY); + return s->requested_bytes; +} + +void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { + assert(s && cb); + s->read_callback = cb; + s->read_userdata = userdata; +} + +int pa_stream_is_dead(struct pa_stream *s) { + return s->state == STREAM_DEAD; +} + +int pa_stream_is_ready(struct pa_stream*s) { + return s->state == STREAM_READY; +} + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { + assert(s); + s->die_callback = cb; + s->die_userdata = userdata; +} + +int pa_context_is_pending(struct pa_context *c) { + assert(c); + + if (c->state != CONTEXT_READY) + return 0; + + return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); +} + +struct pa_context* pa_stream_get_context(struct pa_stream *p) { + assert(p); + return p->context; +} + +static void set_dispatch_callbacks(struct pa_context *c); + +static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void set_dispatch_callbacks(struct pa_context *c) { + assert(c && c->state == CONTEXT_READY); + + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + + if (pa_pdispatch_is_pending(c->pdispatch)) { + pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); + return; + } + + if (pa_pstream_is_pending(c->pstream)) { + pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); + return; + } + + assert(c->drain_complete_callback); + c->drain_complete_callback(c, c->drain_complete_userdata); +} + +int pa_context_drain( + struct pa_context *c, + void (*complete) (struct pa_context*c, void *userdata), + void *userdata) { + + assert(c && c->state == CONTEXT_READY); + + if (complete == NULL) { + c->drain_complete_callback = NULL; + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + return 0; + } + + if (!pa_context_is_pending(c)) + return -1; + + c->drain_complete_callback = complete; + c->drain_complete_userdata = userdata; + + set_dispatch_callbacks(c); + + return 0; +} + +static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + return; + } + + if (s->state != STREAM_READY) + return; + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->drain_complete_callback) { + void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; + s->drain_complete_callback = NULL; + temp(s, s->drain_complete_userdata); + } +} + + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->state == STREAM_READY); + + if (!complete) { + s->drain_complete_callback = NULL; + return; + } + + s->drain_complete_callback = complete; + s->drain_complete_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); +} + +void pa_context_exit(struct pa_context *c) { + struct pa_tagstruct *t; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_EXIT); + pa_tagstruct_putu32(t, c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + uint32_t total, count; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &count) < 0 || + pa_tagstruct_getu32(t, &total) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, count, total, c->stat_userdata); +} + +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + c->stat_callback = cb; + c->stat_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_STAT); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); +} + +static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + uint32_t latency; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &latency) < 0 || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, latency, s->get_latency_userdata); +} + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + p->get_latency_callback = cb; + p->get_latency_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); +} + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_stream *s; + struct pa_tagstruct *t; + uint32_t tag; + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = cb; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = PA_STREAM_UPLOAD; + s->sample_spec = *ss; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_sample_spec(t, ss); + pa_tagstruct_putu32(t, length); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); + + return s; +} + +static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 0, s->finish_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 1, s->finish_sample_userdata); +} + +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(p); + + p->finish_sample_callback = cb; + p->finish_sample_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); +} + +static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 0, c->play_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 1, c->play_sample_userdata); +} + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name && *name && (!dev || *dev)); + + c->play_sample_callback = cb; + c->play_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, volume); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); +} + +static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 0, c->remove_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 1, c->remove_sample_userdata); +} + +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name); + + c->remove_sample_callback = cb; + c->remove_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); +} + +static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_server_info i; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, NULL, c->get_server_info_userdata); + return; + } + + if (pa_tagstruct_gets(t, &i.server_name) < 0 || + pa_tagstruct_gets(t, &i.server_version) < 0 || + pa_tagstruct_gets(t, &i.user_name) < 0 || + pa_tagstruct_gets(t, &i.host_name) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, &i, c->get_server_info_userdata); +} + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_server_info_callback = cb; + c->get_server_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); +} + +static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_sink_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.monitor_source) < 0 || + pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || + pa_tagstruct_getu32(t, &i.latency) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); +} + +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_source_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || + pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); +} + +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + struct pa_tagstruct *t; + assert(c); + + c->subscribe_callback = cb; + c->subscribe_userdata = userdata; + c->subscribe_mask = m; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); + pa_tagstruct_putu32(t, c->ctag++); + pa_tagstruct_putu32(t, cb ? m : 0); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + enum pa_subscription_event_type e; + uint32_t index; + assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); + + if (pa_tagstruct_getu32(t, &e) < 0 || + pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) + c->subscribe_callback(c, e, index, c->subscribe_userdata); +} + +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_client_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.protocol_name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); +} + + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_module_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0 || + pa_tagstruct_getu32(t, &i.n_used) < 0 || + pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); +} + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} + +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} diff --git a/polyp/polyplib-subscribe.h b/polyp/polyplib-subscribe.h new file mode 100644 index 000000000..a0dd9f9cb --- /dev/null +++ b/polyp/polyplib-subscribe.h @@ -0,0 +1,178 @@ +#ifndef foopolyplibhfoo +#define foopolyplibhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "sample.h" +#include "polyplib-def.h" +#include "mainloop-api.h" + +#ifdef __cplusplus +//extern "C" { +#endif + +struct pa_context; +struct pa_stream; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); +void pa_context_unref(struct pa_context *c); +struct pa_context* pa_context_ref(struct pa_context *c); + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); +int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); + +int pa_context_is_dead(struct pa_context *c); +int pa_context_is_ready(struct pa_context *c); +int pa_context_errno(struct pa_context *c); + +int pa_context_is_pending(struct pa_context *c); + +struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_unref(struct pa_stream *s); +struct pa_stream *pa_stream_ref(struct pa_stream *s); + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); + +void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); +void pa_stream_write(struct pa_stream *p, const void *data, size_t length); +size_t pa_stream_writable_size(struct pa_stream *p); + +void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); + +int pa_stream_is_dead(struct pa_stream *p); +int pa_stream_is_ready(struct pa_stream*p); + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); + +struct pa_context* pa_stream_get_context(struct pa_stream *p); + +uint32_t pa_stream_get_index(struct pa_stream *s); + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +struct pa_sink_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t volume; + uint32_t monitor_source; + const char *monitor_source_name; + uint32_t latency; +}; + +void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); + +struct pa_source_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t monitor_of_sink; + const char *monitor_of_sink_name; +}; + +void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); + +struct pa_server_info { + const char *user_name; + const char *host_name; + const char *server_version; + const char *server_name; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); + +struct pa_module_info { + uint32_t index; + const char*name, *argument; + uint32_t n_used, auto_unload; +}; + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); + +struct pa_client_info { + uint32_t index; + const char *name; + uint32_t owner_module; + const char *protocol_name; +}; + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); + +struct pa_sink_input_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t sink; + struct pa_sample_spec sample_spec; + uint32_t volume; + uint32_t latency; +}; + +void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); + +struct pa_source_output_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t source; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); + +void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +void pa_context_exit(struct pa_context *c); +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); + +#ifdef __cplusplus +} +#endif + +#endif From 821afd66b0598aaa6851796ee27ca506302a21cd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Aug 2004 13:24:48 +0000 Subject: [PATCH 0118/1514] add internal header file for polyplib git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@119 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-internal.h | 1550 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1550 insertions(+) create mode 100644 polyp/polyplib-internal.h diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h new file mode 100644 index 000000000..35001d3d3 --- /dev/null +++ b/polyp/polyplib-internal.h @@ -0,0 +1,1550 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "polyplib.h" +#include "native-common.h" +#include "pdispatch.h" +#include "pstream.h" +#include "dynarray.h" +#include "socket-client.h" +#include "pstream-util.h" +#include "authkey.h" +#include "util.h" +#include "xmalloc.h" + +#define DEFAULT_MAXLENGTH 204800 +#define DEFAULT_TLENGTH 10240 +#define DEFAULT_PREBUF 4096 +#define DEFAULT_MINREQ 1024 +#define DEFAULT_FRAGSIZE 1024 + +#define DEFAULT_TIMEOUT (5*60) +#define DEFAULT_SERVER "/tmp/polypaudio/native" +#define DEFAULT_PORT "4713" + +struct pa_context { + char *name; + struct pa_mainloop_api* mainloop; + struct pa_socket_client *client; + struct pa_pstream *pstream; + struct pa_pdispatch *pdispatch; + struct pa_dynarray *record_streams, *playback_streams; + struct pa_stream *first_stream; + uint32_t ctag; + uint32_t error; + enum { + CONTEXT_UNCONNECTED, + CONTEXT_CONNECTING, + CONTEXT_AUTHORIZING, + CONTEXT_SETTING_NAME, + CONTEXT_READY, + CONTEXT_DEAD + } state; + + void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); + void *connect_complete_userdata; + + void (*drain_complete_callback)(struct pa_context*c, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_context*c, void *userdata); + void *die_userdata; + + void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); + void *stat_userdata; + + void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); + void *play_sample_userdata; + + void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); + void *remove_sample_userdata; + + void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); + void *get_server_info_userdata; + + void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); + void *get_sink_info_userdata; + + void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); + void *get_source_info_userdata; + + void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void *subscribe_userdata; + enum pa_subscription_mask subscribe_mask; + + void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); + void *get_client_info_userdata; + + void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); + void *get_module_info_userdata; + + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; +}; + +struct pa_stream { + struct pa_context *context; + struct pa_stream *next, *previous; + + char *name; + struct pa_buffer_attr buffer_attr; + struct pa_sample_spec sample_spec; + uint32_t channel; + int channel_valid; + uint32_t device_index; + enum pa_stream_direction direction; + + enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; + uint32_t requested_bytes; + + void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); + void *read_userdata; + + void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); + void *write_userdata; + + void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); + void *create_complete_userdata; + + void (*drain_complete_callback)(struct pa_stream *s, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_stream*c, void *userdata); + void *die_userdata; + + void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); + void *get_latency_userdata; + + void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); + void *finish_sample_userdata; +}; + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + +static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = { NULL }, + [PA_COMMAND_REPLY] = { NULL }, + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_EXIT] = { NULL }, + [PA_COMMAND_REQUEST] = { command_request }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, +}; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { + struct pa_context *c; + assert(mainloop && name); + + c = pa_xmalloc(sizeof(struct pa_context)); + c->name = pa_xstrdup(name); + c->mainloop = mainloop; + c->client = NULL; + c->pstream = NULL; + c->pdispatch = NULL; + c->playback_streams = pa_dynarray_new(); + assert(c->playback_streams); + c->record_streams = pa_dynarray_new(); + assert(c->record_streams); + c->first_stream = NULL; + c->error = PA_ERROR_OK; + c->state = CONTEXT_UNCONNECTED; + c->ctag = 0; + + c->connect_complete_callback = NULL; + c->connect_complete_userdata = NULL; + + c->drain_complete_callback = NULL; + c->drain_complete_userdata = NULL; + + c->die_callback = NULL; + c->die_userdata = NULL; + + c->stat_callback = NULL; + c->stat_userdata = NULL; + + c->play_sample_callback = NULL; + c->play_sample_userdata = NULL; + + c->remove_sample_callback = NULL; + c->remove_sample_userdata = NULL; + + c->get_server_info_callback = NULL; + c->get_server_info_userdata = NULL; + + c->get_sink_info_callback = NULL; + c->get_sink_info_userdata = NULL; + + c->get_source_info_callback = NULL; + c->get_source_info_userdata = NULL; + + c->subscribe_callback = NULL; + c->subscribe_userdata = NULL; + + c->get_client_info_callback = NULL; + c->get_client_info_userdata = NULL; + + c->get_module_info_callback = NULL; + c->get_module_info_userdata = NULL; + + pa_check_for_sigpipe(); + return c; +} + +void pa_context_free(struct pa_context *c) { + assert(c); + + while (c->first_stream) + pa_stream_free(c->first_stream); + + if (c->client) + pa_socket_client_free(c->client); + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + if (c->pstream) + pa_pstream_free(c->pstream); + if (c->record_streams) + pa_dynarray_free(c->record_streams, NULL, NULL); + if (c->playback_streams) + pa_dynarray_free(c->playback_streams, NULL, NULL); + + pa_xfree(c->name); + pa_xfree(c); +} + +static void stream_dead(struct pa_stream *s) { + assert(s); + + if (s->state == STREAM_DEAD) + return; + + if (s->state == STREAM_READY) { + s->state = STREAM_DEAD; + if (s->die_callback) + s->die_callback(s, s->die_userdata); + } else + s->state = STREAM_DEAD; +} + +static void context_dead(struct pa_context *c) { + struct pa_stream *s; + assert(c); + + if (c->state == CONTEXT_DEAD) + return; + + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + c->pdispatch = NULL; + + if (c->pstream) + pa_pstream_free(c->pstream); + c->pstream = NULL; + + if (c->client) + pa_socket_client_free(c->client); + c->client = NULL; + + for (s = c->first_stream; s; s = s->next) + stream_dead(s); + + if (c->state == CONTEXT_READY) { + c->state = CONTEXT_DEAD; + if (c->die_callback) + c->die_callback(c, c->die_userdata); + } else + c->state = CONTEXT_DEAD; +} + +static void pstream_die_callback(struct pa_pstream *p, void *userdata) { + struct pa_context *c = userdata; + assert(p && c); + c->error = PA_ERROR_CONNECTIONTERMINATED; + context_dead(c); +} + +static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { + struct pa_context *c = userdata; + assert(p && packet && c); + + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { + fprintf(stderr, "polyp.c: invalid packet.\n"); + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + } +} + +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + assert(p && chunk && c && chunk->memblock && chunk->memblock->data); + + if (!(s = pa_dynarray_get(c->record_streams, channel))) + return; + + if (s->read_callback) + s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); +} + +static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { + assert(c && t); + + if (command == PA_COMMAND_ERROR) { + if (pa_tagstruct_getu32(t, &c->error) < 0) { + c->error = PA_ERROR_PROTOCOL; + return -1; + } + + return 0; + } + + c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; + return -1; +} + +static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); + + if (command != PA_COMMAND_REPLY) { + handle_error(c, command, t); + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + if (c->state == CONTEXT_AUTHORIZING) { + struct pa_tagstruct *t; + c->state = CONTEXT_SETTING_NAME; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, c->name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + } else { + assert(c->state == CONTEXT_SETTING_NAME); + + c->state = CONTEXT_READY; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 1, c->connect_complete_userdata); + } + + return; +} + +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { + struct pa_context *c = userdata; + struct pa_tagstruct *t; + uint32_t tag; + assert(client && c && c->state == CONTEXT_CONNECTING); + + pa_socket_client_free(client); + c->client = NULL; + + if (!io) { + c->error = PA_ERROR_CONNECTIONREFUSED; + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + c->pstream = pa_pstream_new(c->mainloop, io); + assert(c->pstream); + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + + c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); + assert(c->pdispatch); + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_AUTH); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + c->state = CONTEXT_AUTHORIZING; +} + +static struct sockaddr *resolve_server(const char *server, size_t *len) { + struct sockaddr *sa; + struct addrinfo hints, *result = NULL; + char *port; + assert(server && len); + + if ((port = strrchr(server, ':'))) + port++; + if (!port) + port = DEFAULT_PORT; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + if (getaddrinfo(server, port, &hints, &result) != 0) + return NULL; + assert(result); + + sa = pa_xmalloc(*len = result->ai_addrlen); + memcpy(sa, result->ai_addr, *len); + + freeaddrinfo(result); + + return sa; +} + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { + assert(c && c->state == CONTEXT_UNCONNECTED); + + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { + c->error = PA_ERROR_AUTHKEY; + return -1; + } + + if (!server) + if (!(server = getenv("POLYP_SERVER"))) + server = DEFAULT_SERVER; + + assert(!c->client); + + if (*server == '/') { + if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } else { + struct sockaddr* sa; + size_t sa_len; + + if (!(sa = resolve_server(server, &sa_len))) { + c->error = PA_ERROR_INVALIDSERVER; + return -1; + } + + c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); + pa_xfree(sa); + + if (!c->client) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } + + c->connect_complete_callback = complete; + c->connect_complete_userdata = userdata; + + pa_socket_client_set_callback(c->client, on_connection, c); + c->state = CONTEXT_CONNECTING; + + return 0; +} + +int pa_context_is_dead(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_DEAD; +} + +int pa_context_is_ready(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_READY; +} + +int pa_context_errno(struct pa_context *c) { + assert(c); + return c->error; +} + +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { + assert(c); + c->die_callback = cb; + c->die_userdata = userdata; +} + +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + uint32_t channel; + assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) + return; + + c->error = PA_ERROR_KILLED; + stream_dead(s); +} + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s; + struct pa_context *c = userdata; + uint32_t bytes, channel; + assert(pd && command == PA_COMMAND_REQUEST && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_getu32(t, &bytes) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(c->playback_streams, channel))) + return; + + if (s->state != STREAM_READY) + return; + + s->requested_bytes += bytes; + + if (s->requested_bytes && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); +} + +static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s && s->state == STREAM_CREATING); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + if (s->create_complete_callback) + s->create_complete_callback(s, 0, s->create_complete_userdata); + + return; + } + + if (pa_tagstruct_getu32(t, &s->channel) < 0 || + ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + s->channel_valid = 1; + pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); + + s->state = STREAM_READY; + if (s->create_complete_callback) + s->create_complete_callback(s, 1, s->create_complete_userdata); +} + +static void create_stream(struct pa_stream *s, const char *dev) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s); + + s->state = STREAM_CREATING; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_puts(t, s->name); + pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, s->buffer_attr.maxlength); + if (s->direction == PA_STREAM_PLAYBACK) { + pa_tagstruct_putu32(t, s->buffer_attr.tlength); + pa_tagstruct_putu32(t, s->buffer_attr.prebuf); + pa_tagstruct_putu32(t, s->buffer_attr.minreq); + } else + pa_tagstruct_putu32(t, s->buffer_attr.fragsize); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); +} + +static struct pa_stream *internal_stream_new(struct pa_context *c) { + struct pa_stream *s; + + s = pa_xmalloc(sizeof(struct pa_stream)); + s->context = c; + + s->read_callback = NULL; + s->read_userdata = NULL; + s->write_callback = NULL; + s->write_userdata = NULL; + s->die_callback = NULL; + s->die_userdata = NULL; + s->create_complete_callback = NULL; + s->create_complete_userdata = NULL; + s->get_latency_callback = NULL; + s->get_latency_userdata = NULL; + s->finish_sample_callback = NULL; + s->finish_sample_userdata = NULL; + + s->name = NULL; + s->state = STREAM_CREATING; + s->requested_bytes = 0; + s->channel = 0; + s->channel_valid = 0; + s->device_index = (uint32_t) -1; + + memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + + s->next = c->first_stream; + if (s->next) + s->next->previous = s; + s->previous = NULL; + c->first_stream = s; + + return s; +} + +struct pa_stream* pa_stream_new( + struct pa_context *c, + enum pa_stream_direction dir, + const char *dev, + const char *name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr, + void (*complete) (struct pa_stream*s, int success, void *userdata), + void *userdata) { + + struct pa_stream *s; + + assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = complete; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = dir; + s->sample_spec = *ss; + if (attr) + s->buffer_attr = *attr; + else { + s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; + s->buffer_attr.tlength = DEFAULT_TLENGTH; + s->buffer_attr.prebuf = DEFAULT_PREBUF; + s->buffer_attr.minreq = DEFAULT_MINREQ; + s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; + } + + create_stream(s, dev); + + return s; +} + +void pa_stream_free(struct pa_stream *s) { + assert(s && s->context); + + if (s->context->pdispatch) + pa_pdispatch_unregister_reply(s->context->pdispatch, s); + + pa_xfree(s->name); + + if (s->channel_valid && s->context->state == CONTEXT_READY) { + struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); + pa_tagstruct_putu32(t, s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + } + + if (s->channel_valid) + pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); + + if (s->next) + s->next->previous = s->previous; + if (s->previous) + s->previous->next = s->next; + else + s->context->first_stream = s->next; + + pa_xfree(s); +} + +void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { + s->write_callback = cb; + s->write_userdata = userdata; +} + +void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { + struct pa_memchunk chunk; + assert(s && s->context && data && length && s->state == STREAM_READY); + + chunk.memblock = pa_memblock_new(length); + assert(chunk.memblock && chunk.memblock->data); + memcpy(chunk.memblock->data, data, length); + chunk.index = 0; + chunk.length = length; + + pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + pa_memblock_unref(chunk.memblock); + + /*fprintf(stderr, "Sent %u bytes\n", length);*/ + + if (length < s->requested_bytes) + s->requested_bytes -= length; + else + s->requested_bytes = 0; +} + +size_t pa_stream_writable_size(struct pa_stream *s) { + assert(s && s->state == STREAM_READY); + return s->requested_bytes; +} + +void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { + assert(s && cb); + s->read_callback = cb; + s->read_userdata = userdata; +} + +int pa_stream_is_dead(struct pa_stream *s) { + return s->state == STREAM_DEAD; +} + +int pa_stream_is_ready(struct pa_stream*s) { + return s->state == STREAM_READY; +} + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { + assert(s); + s->die_callback = cb; + s->die_userdata = userdata; +} + +int pa_context_is_pending(struct pa_context *c) { + assert(c); + + if (c->state != CONTEXT_READY) + return 0; + + return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); +} + +struct pa_context* pa_stream_get_context(struct pa_stream *p) { + assert(p); + return p->context; +} + +static void set_dispatch_callbacks(struct pa_context *c); + +static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void set_dispatch_callbacks(struct pa_context *c) { + assert(c && c->state == CONTEXT_READY); + + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + + if (pa_pdispatch_is_pending(c->pdispatch)) { + pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); + return; + } + + if (pa_pstream_is_pending(c->pstream)) { + pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); + return; + } + + assert(c->drain_complete_callback); + c->drain_complete_callback(c, c->drain_complete_userdata); +} + +int pa_context_drain( + struct pa_context *c, + void (*complete) (struct pa_context*c, void *userdata), + void *userdata) { + + assert(c && c->state == CONTEXT_READY); + + if (complete == NULL) { + c->drain_complete_callback = NULL; + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + return 0; + } + + if (!pa_context_is_pending(c)) + return -1; + + c->drain_complete_callback = complete; + c->drain_complete_userdata = userdata; + + set_dispatch_callbacks(c); + + return 0; +} + +static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + return; + } + + if (s->state != STREAM_READY) + return; + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->drain_complete_callback) { + void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; + s->drain_complete_callback = NULL; + temp(s, s->drain_complete_userdata); + } +} + + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->state == STREAM_READY); + + if (!complete) { + s->drain_complete_callback = NULL; + return; + } + + s->drain_complete_callback = complete; + s->drain_complete_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); +} + +void pa_context_exit(struct pa_context *c) { + struct pa_tagstruct *t; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_EXIT); + pa_tagstruct_putu32(t, c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + uint32_t total, count; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &count) < 0 || + pa_tagstruct_getu32(t, &total) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, count, total, c->stat_userdata); +} + +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + c->stat_callback = cb; + c->stat_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_STAT); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); +} + +static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + uint32_t latency; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &latency) < 0 || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, latency, s->get_latency_userdata); +} + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + p->get_latency_callback = cb; + p->get_latency_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); +} + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_stream *s; + struct pa_tagstruct *t; + uint32_t tag; + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = cb; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = PA_STREAM_UPLOAD; + s->sample_spec = *ss; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_sample_spec(t, ss); + pa_tagstruct_putu32(t, length); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); + + return s; +} + +static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 0, s->finish_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 1, s->finish_sample_userdata); +} + +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(p); + + p->finish_sample_callback = cb; + p->finish_sample_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); +} + +static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 0, c->play_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 1, c->play_sample_userdata); +} + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name && *name && (!dev || *dev)); + + c->play_sample_callback = cb; + c->play_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, volume); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); +} + +static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 0, c->remove_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 1, c->remove_sample_userdata); +} + +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name); + + c->remove_sample_callback = cb; + c->remove_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); +} + +static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_server_info i; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, NULL, c->get_server_info_userdata); + return; + } + + if (pa_tagstruct_gets(t, &i.server_name) < 0 || + pa_tagstruct_gets(t, &i.server_version) < 0 || + pa_tagstruct_gets(t, &i.user_name) < 0 || + pa_tagstruct_gets(t, &i.host_name) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, &i, c->get_server_info_userdata); +} + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_server_info_callback = cb; + c->get_server_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); +} + +static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_sink_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.monitor_source) < 0 || + pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || + pa_tagstruct_getu32(t, &i.latency) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); +} + +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_source_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || + pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); +} + +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + struct pa_tagstruct *t; + assert(c); + + c->subscribe_callback = cb; + c->subscribe_userdata = userdata; + c->subscribe_mask = m; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); + pa_tagstruct_putu32(t, c->ctag++); + pa_tagstruct_putu32(t, cb ? m : 0); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + enum pa_subscription_event_type e; + uint32_t index; + assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); + + if (pa_tagstruct_getu32(t, &e) < 0 || + pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) + c->subscribe_callback(c, e, index, c->subscribe_userdata); +} + +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_client_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.protocol_name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); +} + + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_module_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0 || + pa_tagstruct_getu32(t, &i.n_used) < 0 || + pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); +} + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} + +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} From 56bcba9559279701eaa8860642c835484651ebdb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Aug 2004 13:26:34 +0000 Subject: [PATCH 0119/1514] add polyplib-sample git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@120 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-sample.h | 178 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 polyp/polyplib-sample.h diff --git a/polyp/polyplib-sample.h b/polyp/polyplib-sample.h new file mode 100644 index 000000000..a0dd9f9cb --- /dev/null +++ b/polyp/polyplib-sample.h @@ -0,0 +1,178 @@ +#ifndef foopolyplibhfoo +#define foopolyplibhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "sample.h" +#include "polyplib-def.h" +#include "mainloop-api.h" + +#ifdef __cplusplus +//extern "C" { +#endif + +struct pa_context; +struct pa_stream; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); +void pa_context_unref(struct pa_context *c); +struct pa_context* pa_context_ref(struct pa_context *c); + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); +int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); + +int pa_context_is_dead(struct pa_context *c); +int pa_context_is_ready(struct pa_context *c); +int pa_context_errno(struct pa_context *c); + +int pa_context_is_pending(struct pa_context *c); + +struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_unref(struct pa_stream *s); +struct pa_stream *pa_stream_ref(struct pa_stream *s); + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); + +void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); +void pa_stream_write(struct pa_stream *p, const void *data, size_t length); +size_t pa_stream_writable_size(struct pa_stream *p); + +void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); + +int pa_stream_is_dead(struct pa_stream *p); +int pa_stream_is_ready(struct pa_stream*p); + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); + +struct pa_context* pa_stream_get_context(struct pa_stream *p); + +uint32_t pa_stream_get_index(struct pa_stream *s); + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +struct pa_sink_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t volume; + uint32_t monitor_source; + const char *monitor_source_name; + uint32_t latency; +}; + +void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); + +struct pa_source_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t monitor_of_sink; + const char *monitor_of_sink_name; +}; + +void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); + +struct pa_server_info { + const char *user_name; + const char *host_name; + const char *server_version; + const char *server_name; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); + +struct pa_module_info { + uint32_t index; + const char*name, *argument; + uint32_t n_used, auto_unload; +}; + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); + +struct pa_client_info { + uint32_t index; + const char *name; + uint32_t owner_module; + const char *protocol_name; +}; + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); + +struct pa_sink_input_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t sink; + struct pa_sample_spec sample_spec; + uint32_t volume; + uint32_t latency; +}; + +void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); + +struct pa_source_output_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t source; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); + +void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +void pa_context_exit(struct pa_context *c); +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); + +#ifdef __cplusplus +} +#endif + +#endif From 50b9fc2031cacf597813bb84d56f20e29fe0c93d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Aug 2004 13:27:23 +0000 Subject: [PATCH 0120/1514] add polyplib-sample.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@121 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-sample.c | 1550 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1550 insertions(+) create mode 100644 polyp/polyplib-sample.c diff --git a/polyp/polyplib-sample.c b/polyp/polyplib-sample.c new file mode 100644 index 000000000..35001d3d3 --- /dev/null +++ b/polyp/polyplib-sample.c @@ -0,0 +1,1550 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "polyplib.h" +#include "native-common.h" +#include "pdispatch.h" +#include "pstream.h" +#include "dynarray.h" +#include "socket-client.h" +#include "pstream-util.h" +#include "authkey.h" +#include "util.h" +#include "xmalloc.h" + +#define DEFAULT_MAXLENGTH 204800 +#define DEFAULT_TLENGTH 10240 +#define DEFAULT_PREBUF 4096 +#define DEFAULT_MINREQ 1024 +#define DEFAULT_FRAGSIZE 1024 + +#define DEFAULT_TIMEOUT (5*60) +#define DEFAULT_SERVER "/tmp/polypaudio/native" +#define DEFAULT_PORT "4713" + +struct pa_context { + char *name; + struct pa_mainloop_api* mainloop; + struct pa_socket_client *client; + struct pa_pstream *pstream; + struct pa_pdispatch *pdispatch; + struct pa_dynarray *record_streams, *playback_streams; + struct pa_stream *first_stream; + uint32_t ctag; + uint32_t error; + enum { + CONTEXT_UNCONNECTED, + CONTEXT_CONNECTING, + CONTEXT_AUTHORIZING, + CONTEXT_SETTING_NAME, + CONTEXT_READY, + CONTEXT_DEAD + } state; + + void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); + void *connect_complete_userdata; + + void (*drain_complete_callback)(struct pa_context*c, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_context*c, void *userdata); + void *die_userdata; + + void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); + void *stat_userdata; + + void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); + void *play_sample_userdata; + + void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); + void *remove_sample_userdata; + + void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); + void *get_server_info_userdata; + + void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); + void *get_sink_info_userdata; + + void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); + void *get_source_info_userdata; + + void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void *subscribe_userdata; + enum pa_subscription_mask subscribe_mask; + + void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); + void *get_client_info_userdata; + + void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); + void *get_module_info_userdata; + + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; +}; + +struct pa_stream { + struct pa_context *context; + struct pa_stream *next, *previous; + + char *name; + struct pa_buffer_attr buffer_attr; + struct pa_sample_spec sample_spec; + uint32_t channel; + int channel_valid; + uint32_t device_index; + enum pa_stream_direction direction; + + enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; + uint32_t requested_bytes; + + void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); + void *read_userdata; + + void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); + void *write_userdata; + + void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); + void *create_complete_userdata; + + void (*drain_complete_callback)(struct pa_stream *s, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_stream*c, void *userdata); + void *die_userdata; + + void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); + void *get_latency_userdata; + + void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); + void *finish_sample_userdata; +}; + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + +static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = { NULL }, + [PA_COMMAND_REPLY] = { NULL }, + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_EXIT] = { NULL }, + [PA_COMMAND_REQUEST] = { command_request }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, +}; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { + struct pa_context *c; + assert(mainloop && name); + + c = pa_xmalloc(sizeof(struct pa_context)); + c->name = pa_xstrdup(name); + c->mainloop = mainloop; + c->client = NULL; + c->pstream = NULL; + c->pdispatch = NULL; + c->playback_streams = pa_dynarray_new(); + assert(c->playback_streams); + c->record_streams = pa_dynarray_new(); + assert(c->record_streams); + c->first_stream = NULL; + c->error = PA_ERROR_OK; + c->state = CONTEXT_UNCONNECTED; + c->ctag = 0; + + c->connect_complete_callback = NULL; + c->connect_complete_userdata = NULL; + + c->drain_complete_callback = NULL; + c->drain_complete_userdata = NULL; + + c->die_callback = NULL; + c->die_userdata = NULL; + + c->stat_callback = NULL; + c->stat_userdata = NULL; + + c->play_sample_callback = NULL; + c->play_sample_userdata = NULL; + + c->remove_sample_callback = NULL; + c->remove_sample_userdata = NULL; + + c->get_server_info_callback = NULL; + c->get_server_info_userdata = NULL; + + c->get_sink_info_callback = NULL; + c->get_sink_info_userdata = NULL; + + c->get_source_info_callback = NULL; + c->get_source_info_userdata = NULL; + + c->subscribe_callback = NULL; + c->subscribe_userdata = NULL; + + c->get_client_info_callback = NULL; + c->get_client_info_userdata = NULL; + + c->get_module_info_callback = NULL; + c->get_module_info_userdata = NULL; + + pa_check_for_sigpipe(); + return c; +} + +void pa_context_free(struct pa_context *c) { + assert(c); + + while (c->first_stream) + pa_stream_free(c->first_stream); + + if (c->client) + pa_socket_client_free(c->client); + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + if (c->pstream) + pa_pstream_free(c->pstream); + if (c->record_streams) + pa_dynarray_free(c->record_streams, NULL, NULL); + if (c->playback_streams) + pa_dynarray_free(c->playback_streams, NULL, NULL); + + pa_xfree(c->name); + pa_xfree(c); +} + +static void stream_dead(struct pa_stream *s) { + assert(s); + + if (s->state == STREAM_DEAD) + return; + + if (s->state == STREAM_READY) { + s->state = STREAM_DEAD; + if (s->die_callback) + s->die_callback(s, s->die_userdata); + } else + s->state = STREAM_DEAD; +} + +static void context_dead(struct pa_context *c) { + struct pa_stream *s; + assert(c); + + if (c->state == CONTEXT_DEAD) + return; + + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + c->pdispatch = NULL; + + if (c->pstream) + pa_pstream_free(c->pstream); + c->pstream = NULL; + + if (c->client) + pa_socket_client_free(c->client); + c->client = NULL; + + for (s = c->first_stream; s; s = s->next) + stream_dead(s); + + if (c->state == CONTEXT_READY) { + c->state = CONTEXT_DEAD; + if (c->die_callback) + c->die_callback(c, c->die_userdata); + } else + c->state = CONTEXT_DEAD; +} + +static void pstream_die_callback(struct pa_pstream *p, void *userdata) { + struct pa_context *c = userdata; + assert(p && c); + c->error = PA_ERROR_CONNECTIONTERMINATED; + context_dead(c); +} + +static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { + struct pa_context *c = userdata; + assert(p && packet && c); + + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { + fprintf(stderr, "polyp.c: invalid packet.\n"); + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + } +} + +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + assert(p && chunk && c && chunk->memblock && chunk->memblock->data); + + if (!(s = pa_dynarray_get(c->record_streams, channel))) + return; + + if (s->read_callback) + s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); +} + +static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { + assert(c && t); + + if (command == PA_COMMAND_ERROR) { + if (pa_tagstruct_getu32(t, &c->error) < 0) { + c->error = PA_ERROR_PROTOCOL; + return -1; + } + + return 0; + } + + c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; + return -1; +} + +static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); + + if (command != PA_COMMAND_REPLY) { + handle_error(c, command, t); + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + if (c->state == CONTEXT_AUTHORIZING) { + struct pa_tagstruct *t; + c->state = CONTEXT_SETTING_NAME; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, c->name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + } else { + assert(c->state == CONTEXT_SETTING_NAME); + + c->state = CONTEXT_READY; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 1, c->connect_complete_userdata); + } + + return; +} + +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { + struct pa_context *c = userdata; + struct pa_tagstruct *t; + uint32_t tag; + assert(client && c && c->state == CONTEXT_CONNECTING); + + pa_socket_client_free(client); + c->client = NULL; + + if (!io) { + c->error = PA_ERROR_CONNECTIONREFUSED; + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + c->pstream = pa_pstream_new(c->mainloop, io); + assert(c->pstream); + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + + c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); + assert(c->pdispatch); + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_AUTH); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + c->state = CONTEXT_AUTHORIZING; +} + +static struct sockaddr *resolve_server(const char *server, size_t *len) { + struct sockaddr *sa; + struct addrinfo hints, *result = NULL; + char *port; + assert(server && len); + + if ((port = strrchr(server, ':'))) + port++; + if (!port) + port = DEFAULT_PORT; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + if (getaddrinfo(server, port, &hints, &result) != 0) + return NULL; + assert(result); + + sa = pa_xmalloc(*len = result->ai_addrlen); + memcpy(sa, result->ai_addr, *len); + + freeaddrinfo(result); + + return sa; +} + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { + assert(c && c->state == CONTEXT_UNCONNECTED); + + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { + c->error = PA_ERROR_AUTHKEY; + return -1; + } + + if (!server) + if (!(server = getenv("POLYP_SERVER"))) + server = DEFAULT_SERVER; + + assert(!c->client); + + if (*server == '/') { + if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } else { + struct sockaddr* sa; + size_t sa_len; + + if (!(sa = resolve_server(server, &sa_len))) { + c->error = PA_ERROR_INVALIDSERVER; + return -1; + } + + c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); + pa_xfree(sa); + + if (!c->client) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } + + c->connect_complete_callback = complete; + c->connect_complete_userdata = userdata; + + pa_socket_client_set_callback(c->client, on_connection, c); + c->state = CONTEXT_CONNECTING; + + return 0; +} + +int pa_context_is_dead(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_DEAD; +} + +int pa_context_is_ready(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_READY; +} + +int pa_context_errno(struct pa_context *c) { + assert(c); + return c->error; +} + +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { + assert(c); + c->die_callback = cb; + c->die_userdata = userdata; +} + +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + uint32_t channel; + assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) + return; + + c->error = PA_ERROR_KILLED; + stream_dead(s); +} + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s; + struct pa_context *c = userdata; + uint32_t bytes, channel; + assert(pd && command == PA_COMMAND_REQUEST && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_getu32(t, &bytes) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(c->playback_streams, channel))) + return; + + if (s->state != STREAM_READY) + return; + + s->requested_bytes += bytes; + + if (s->requested_bytes && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); +} + +static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s && s->state == STREAM_CREATING); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + if (s->create_complete_callback) + s->create_complete_callback(s, 0, s->create_complete_userdata); + + return; + } + + if (pa_tagstruct_getu32(t, &s->channel) < 0 || + ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + s->channel_valid = 1; + pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); + + s->state = STREAM_READY; + if (s->create_complete_callback) + s->create_complete_callback(s, 1, s->create_complete_userdata); +} + +static void create_stream(struct pa_stream *s, const char *dev) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s); + + s->state = STREAM_CREATING; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_puts(t, s->name); + pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, s->buffer_attr.maxlength); + if (s->direction == PA_STREAM_PLAYBACK) { + pa_tagstruct_putu32(t, s->buffer_attr.tlength); + pa_tagstruct_putu32(t, s->buffer_attr.prebuf); + pa_tagstruct_putu32(t, s->buffer_attr.minreq); + } else + pa_tagstruct_putu32(t, s->buffer_attr.fragsize); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); +} + +static struct pa_stream *internal_stream_new(struct pa_context *c) { + struct pa_stream *s; + + s = pa_xmalloc(sizeof(struct pa_stream)); + s->context = c; + + s->read_callback = NULL; + s->read_userdata = NULL; + s->write_callback = NULL; + s->write_userdata = NULL; + s->die_callback = NULL; + s->die_userdata = NULL; + s->create_complete_callback = NULL; + s->create_complete_userdata = NULL; + s->get_latency_callback = NULL; + s->get_latency_userdata = NULL; + s->finish_sample_callback = NULL; + s->finish_sample_userdata = NULL; + + s->name = NULL; + s->state = STREAM_CREATING; + s->requested_bytes = 0; + s->channel = 0; + s->channel_valid = 0; + s->device_index = (uint32_t) -1; + + memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + + s->next = c->first_stream; + if (s->next) + s->next->previous = s; + s->previous = NULL; + c->first_stream = s; + + return s; +} + +struct pa_stream* pa_stream_new( + struct pa_context *c, + enum pa_stream_direction dir, + const char *dev, + const char *name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr, + void (*complete) (struct pa_stream*s, int success, void *userdata), + void *userdata) { + + struct pa_stream *s; + + assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = complete; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = dir; + s->sample_spec = *ss; + if (attr) + s->buffer_attr = *attr; + else { + s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; + s->buffer_attr.tlength = DEFAULT_TLENGTH; + s->buffer_attr.prebuf = DEFAULT_PREBUF; + s->buffer_attr.minreq = DEFAULT_MINREQ; + s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; + } + + create_stream(s, dev); + + return s; +} + +void pa_stream_free(struct pa_stream *s) { + assert(s && s->context); + + if (s->context->pdispatch) + pa_pdispatch_unregister_reply(s->context->pdispatch, s); + + pa_xfree(s->name); + + if (s->channel_valid && s->context->state == CONTEXT_READY) { + struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); + pa_tagstruct_putu32(t, s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + } + + if (s->channel_valid) + pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); + + if (s->next) + s->next->previous = s->previous; + if (s->previous) + s->previous->next = s->next; + else + s->context->first_stream = s->next; + + pa_xfree(s); +} + +void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { + s->write_callback = cb; + s->write_userdata = userdata; +} + +void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { + struct pa_memchunk chunk; + assert(s && s->context && data && length && s->state == STREAM_READY); + + chunk.memblock = pa_memblock_new(length); + assert(chunk.memblock && chunk.memblock->data); + memcpy(chunk.memblock->data, data, length); + chunk.index = 0; + chunk.length = length; + + pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + pa_memblock_unref(chunk.memblock); + + /*fprintf(stderr, "Sent %u bytes\n", length);*/ + + if (length < s->requested_bytes) + s->requested_bytes -= length; + else + s->requested_bytes = 0; +} + +size_t pa_stream_writable_size(struct pa_stream *s) { + assert(s && s->state == STREAM_READY); + return s->requested_bytes; +} + +void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { + assert(s && cb); + s->read_callback = cb; + s->read_userdata = userdata; +} + +int pa_stream_is_dead(struct pa_stream *s) { + return s->state == STREAM_DEAD; +} + +int pa_stream_is_ready(struct pa_stream*s) { + return s->state == STREAM_READY; +} + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { + assert(s); + s->die_callback = cb; + s->die_userdata = userdata; +} + +int pa_context_is_pending(struct pa_context *c) { + assert(c); + + if (c->state != CONTEXT_READY) + return 0; + + return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); +} + +struct pa_context* pa_stream_get_context(struct pa_stream *p) { + assert(p); + return p->context; +} + +static void set_dispatch_callbacks(struct pa_context *c); + +static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void set_dispatch_callbacks(struct pa_context *c) { + assert(c && c->state == CONTEXT_READY); + + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + + if (pa_pdispatch_is_pending(c->pdispatch)) { + pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); + return; + } + + if (pa_pstream_is_pending(c->pstream)) { + pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); + return; + } + + assert(c->drain_complete_callback); + c->drain_complete_callback(c, c->drain_complete_userdata); +} + +int pa_context_drain( + struct pa_context *c, + void (*complete) (struct pa_context*c, void *userdata), + void *userdata) { + + assert(c && c->state == CONTEXT_READY); + + if (complete == NULL) { + c->drain_complete_callback = NULL; + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + return 0; + } + + if (!pa_context_is_pending(c)) + return -1; + + c->drain_complete_callback = complete; + c->drain_complete_userdata = userdata; + + set_dispatch_callbacks(c); + + return 0; +} + +static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + return; + } + + if (s->state != STREAM_READY) + return; + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->drain_complete_callback) { + void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; + s->drain_complete_callback = NULL; + temp(s, s->drain_complete_userdata); + } +} + + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->state == STREAM_READY); + + if (!complete) { + s->drain_complete_callback = NULL; + return; + } + + s->drain_complete_callback = complete; + s->drain_complete_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); +} + +void pa_context_exit(struct pa_context *c) { + struct pa_tagstruct *t; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_EXIT); + pa_tagstruct_putu32(t, c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + uint32_t total, count; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &count) < 0 || + pa_tagstruct_getu32(t, &total) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, count, total, c->stat_userdata); +} + +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + c->stat_callback = cb; + c->stat_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_STAT); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); +} + +static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + uint32_t latency; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &latency) < 0 || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, latency, s->get_latency_userdata); +} + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + p->get_latency_callback = cb; + p->get_latency_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); +} + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_stream *s; + struct pa_tagstruct *t; + uint32_t tag; + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = cb; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = PA_STREAM_UPLOAD; + s->sample_spec = *ss; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_sample_spec(t, ss); + pa_tagstruct_putu32(t, length); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); + + return s; +} + +static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 0, s->finish_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 1, s->finish_sample_userdata); +} + +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(p); + + p->finish_sample_callback = cb; + p->finish_sample_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); +} + +static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 0, c->play_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 1, c->play_sample_userdata); +} + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name && *name && (!dev || *dev)); + + c->play_sample_callback = cb; + c->play_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, volume); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); +} + +static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 0, c->remove_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 1, c->remove_sample_userdata); +} + +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name); + + c->remove_sample_callback = cb; + c->remove_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); +} + +static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_server_info i; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, NULL, c->get_server_info_userdata); + return; + } + + if (pa_tagstruct_gets(t, &i.server_name) < 0 || + pa_tagstruct_gets(t, &i.server_version) < 0 || + pa_tagstruct_gets(t, &i.user_name) < 0 || + pa_tagstruct_gets(t, &i.host_name) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, &i, c->get_server_info_userdata); +} + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_server_info_callback = cb; + c->get_server_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); +} + +static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_sink_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.monitor_source) < 0 || + pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || + pa_tagstruct_getu32(t, &i.latency) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); +} + +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_source_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || + pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); +} + +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + struct pa_tagstruct *t; + assert(c); + + c->subscribe_callback = cb; + c->subscribe_userdata = userdata; + c->subscribe_mask = m; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); + pa_tagstruct_putu32(t, c->ctag++); + pa_tagstruct_putu32(t, cb ? m : 0); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + enum pa_subscription_event_type e; + uint32_t index; + assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); + + if (pa_tagstruct_getu32(t, &e) < 0 || + pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) + c->subscribe_callback(c, e, index, c->subscribe_userdata); +} + +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_client_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.protocol_name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); +} + + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_module_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0 || + pa_tagstruct_getu32(t, &i.n_used) < 0 || + pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); +} + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} + +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} From 1c2ec47cf1506ad1c75c088d476ae382170df62c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Aug 2004 16:05:03 +0000 Subject: [PATCH 0121/1514] rename polyplib-sample to polyplib-scache git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@122 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-scache.c | 1550 +++++++++++++++++++++++++++++++++++++++ polyp/polyplib-scache.h | 178 +++++ 2 files changed, 1728 insertions(+) create mode 100644 polyp/polyplib-scache.c create mode 100644 polyp/polyplib-scache.h diff --git a/polyp/polyplib-scache.c b/polyp/polyplib-scache.c new file mode 100644 index 000000000..35001d3d3 --- /dev/null +++ b/polyp/polyplib-scache.c @@ -0,0 +1,1550 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "polyplib.h" +#include "native-common.h" +#include "pdispatch.h" +#include "pstream.h" +#include "dynarray.h" +#include "socket-client.h" +#include "pstream-util.h" +#include "authkey.h" +#include "util.h" +#include "xmalloc.h" + +#define DEFAULT_MAXLENGTH 204800 +#define DEFAULT_TLENGTH 10240 +#define DEFAULT_PREBUF 4096 +#define DEFAULT_MINREQ 1024 +#define DEFAULT_FRAGSIZE 1024 + +#define DEFAULT_TIMEOUT (5*60) +#define DEFAULT_SERVER "/tmp/polypaudio/native" +#define DEFAULT_PORT "4713" + +struct pa_context { + char *name; + struct pa_mainloop_api* mainloop; + struct pa_socket_client *client; + struct pa_pstream *pstream; + struct pa_pdispatch *pdispatch; + struct pa_dynarray *record_streams, *playback_streams; + struct pa_stream *first_stream; + uint32_t ctag; + uint32_t error; + enum { + CONTEXT_UNCONNECTED, + CONTEXT_CONNECTING, + CONTEXT_AUTHORIZING, + CONTEXT_SETTING_NAME, + CONTEXT_READY, + CONTEXT_DEAD + } state; + + void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); + void *connect_complete_userdata; + + void (*drain_complete_callback)(struct pa_context*c, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_context*c, void *userdata); + void *die_userdata; + + void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); + void *stat_userdata; + + void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); + void *play_sample_userdata; + + void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); + void *remove_sample_userdata; + + void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); + void *get_server_info_userdata; + + void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); + void *get_sink_info_userdata; + + void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); + void *get_source_info_userdata; + + void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void *subscribe_userdata; + enum pa_subscription_mask subscribe_mask; + + void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); + void *get_client_info_userdata; + + void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); + void *get_module_info_userdata; + + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; +}; + +struct pa_stream { + struct pa_context *context; + struct pa_stream *next, *previous; + + char *name; + struct pa_buffer_attr buffer_attr; + struct pa_sample_spec sample_spec; + uint32_t channel; + int channel_valid; + uint32_t device_index; + enum pa_stream_direction direction; + + enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; + uint32_t requested_bytes; + + void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); + void *read_userdata; + + void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); + void *write_userdata; + + void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); + void *create_complete_userdata; + + void (*drain_complete_callback)(struct pa_stream *s, void *userdata); + void *drain_complete_userdata; + + void (*die_callback)(struct pa_stream*c, void *userdata); + void *die_userdata; + + void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); + void *get_latency_userdata; + + void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); + void *finish_sample_userdata; +}; + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + +static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = { NULL }, + [PA_COMMAND_REPLY] = { NULL }, + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, + [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, + [PA_COMMAND_EXIT] = { NULL }, + [PA_COMMAND_REQUEST] = { command_request }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, + [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, +}; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { + struct pa_context *c; + assert(mainloop && name); + + c = pa_xmalloc(sizeof(struct pa_context)); + c->name = pa_xstrdup(name); + c->mainloop = mainloop; + c->client = NULL; + c->pstream = NULL; + c->pdispatch = NULL; + c->playback_streams = pa_dynarray_new(); + assert(c->playback_streams); + c->record_streams = pa_dynarray_new(); + assert(c->record_streams); + c->first_stream = NULL; + c->error = PA_ERROR_OK; + c->state = CONTEXT_UNCONNECTED; + c->ctag = 0; + + c->connect_complete_callback = NULL; + c->connect_complete_userdata = NULL; + + c->drain_complete_callback = NULL; + c->drain_complete_userdata = NULL; + + c->die_callback = NULL; + c->die_userdata = NULL; + + c->stat_callback = NULL; + c->stat_userdata = NULL; + + c->play_sample_callback = NULL; + c->play_sample_userdata = NULL; + + c->remove_sample_callback = NULL; + c->remove_sample_userdata = NULL; + + c->get_server_info_callback = NULL; + c->get_server_info_userdata = NULL; + + c->get_sink_info_callback = NULL; + c->get_sink_info_userdata = NULL; + + c->get_source_info_callback = NULL; + c->get_source_info_userdata = NULL; + + c->subscribe_callback = NULL; + c->subscribe_userdata = NULL; + + c->get_client_info_callback = NULL; + c->get_client_info_userdata = NULL; + + c->get_module_info_callback = NULL; + c->get_module_info_userdata = NULL; + + pa_check_for_sigpipe(); + return c; +} + +void pa_context_free(struct pa_context *c) { + assert(c); + + while (c->first_stream) + pa_stream_free(c->first_stream); + + if (c->client) + pa_socket_client_free(c->client); + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + if (c->pstream) + pa_pstream_free(c->pstream); + if (c->record_streams) + pa_dynarray_free(c->record_streams, NULL, NULL); + if (c->playback_streams) + pa_dynarray_free(c->playback_streams, NULL, NULL); + + pa_xfree(c->name); + pa_xfree(c); +} + +static void stream_dead(struct pa_stream *s) { + assert(s); + + if (s->state == STREAM_DEAD) + return; + + if (s->state == STREAM_READY) { + s->state = STREAM_DEAD; + if (s->die_callback) + s->die_callback(s, s->die_userdata); + } else + s->state = STREAM_DEAD; +} + +static void context_dead(struct pa_context *c) { + struct pa_stream *s; + assert(c); + + if (c->state == CONTEXT_DEAD) + return; + + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + c->pdispatch = NULL; + + if (c->pstream) + pa_pstream_free(c->pstream); + c->pstream = NULL; + + if (c->client) + pa_socket_client_free(c->client); + c->client = NULL; + + for (s = c->first_stream; s; s = s->next) + stream_dead(s); + + if (c->state == CONTEXT_READY) { + c->state = CONTEXT_DEAD; + if (c->die_callback) + c->die_callback(c, c->die_userdata); + } else + c->state = CONTEXT_DEAD; +} + +static void pstream_die_callback(struct pa_pstream *p, void *userdata) { + struct pa_context *c = userdata; + assert(p && c); + c->error = PA_ERROR_CONNECTIONTERMINATED; + context_dead(c); +} + +static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { + struct pa_context *c = userdata; + assert(p && packet && c); + + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { + fprintf(stderr, "polyp.c: invalid packet.\n"); + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + } +} + +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + assert(p && chunk && c && chunk->memblock && chunk->memblock->data); + + if (!(s = pa_dynarray_get(c->record_streams, channel))) + return; + + if (s->read_callback) + s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); +} + +static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { + assert(c && t); + + if (command == PA_COMMAND_ERROR) { + if (pa_tagstruct_getu32(t, &c->error) < 0) { + c->error = PA_ERROR_PROTOCOL; + return -1; + } + + return 0; + } + + c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; + return -1; +} + +static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); + + if (command != PA_COMMAND_REPLY) { + handle_error(c, command, t); + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + if (c->state == CONTEXT_AUTHORIZING) { + struct pa_tagstruct *t; + c->state = CONTEXT_SETTING_NAME; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, c->name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + } else { + assert(c->state == CONTEXT_SETTING_NAME); + + c->state = CONTEXT_READY; + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 1, c->connect_complete_userdata); + } + + return; +} + +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { + struct pa_context *c = userdata; + struct pa_tagstruct *t; + uint32_t tag; + assert(client && c && c->state == CONTEXT_CONNECTING); + + pa_socket_client_free(client); + c->client = NULL; + + if (!io) { + c->error = PA_ERROR_CONNECTIONREFUSED; + context_dead(c); + + if (c->connect_complete_callback) + c->connect_complete_callback(c, 0, c->connect_complete_userdata); + + return; + } + + c->pstream = pa_pstream_new(c->mainloop, io); + assert(c->pstream); + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + + c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); + assert(c->pdispatch); + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_AUTH); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + c->state = CONTEXT_AUTHORIZING; +} + +static struct sockaddr *resolve_server(const char *server, size_t *len) { + struct sockaddr *sa; + struct addrinfo hints, *result = NULL; + char *port; + assert(server && len); + + if ((port = strrchr(server, ':'))) + port++; + if (!port) + port = DEFAULT_PORT; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + if (getaddrinfo(server, port, &hints, &result) != 0) + return NULL; + assert(result); + + sa = pa_xmalloc(*len = result->ai_addrlen); + memcpy(sa, result->ai_addr, *len); + + freeaddrinfo(result); + + return sa; +} + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { + assert(c && c->state == CONTEXT_UNCONNECTED); + + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { + c->error = PA_ERROR_AUTHKEY; + return -1; + } + + if (!server) + if (!(server = getenv("POLYP_SERVER"))) + server = DEFAULT_SERVER; + + assert(!c->client); + + if (*server == '/') { + if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } else { + struct sockaddr* sa; + size_t sa_len; + + if (!(sa = resolve_server(server, &sa_len))) { + c->error = PA_ERROR_INVALIDSERVER; + return -1; + } + + c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); + pa_xfree(sa); + + if (!c->client) { + c->error = PA_ERROR_CONNECTIONREFUSED; + return -1; + } + } + + c->connect_complete_callback = complete; + c->connect_complete_userdata = userdata; + + pa_socket_client_set_callback(c->client, on_connection, c); + c->state = CONTEXT_CONNECTING; + + return 0; +} + +int pa_context_is_dead(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_DEAD; +} + +int pa_context_is_ready(struct pa_context *c) { + assert(c); + return c->state == CONTEXT_READY; +} + +int pa_context_errno(struct pa_context *c) { + assert(c); + return c->error; +} + +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { + assert(c); + c->die_callback = cb; + c->die_userdata = userdata; +} + +static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_stream *s; + uint32_t channel; + assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) + return; + + c->error = PA_ERROR_KILLED; + stream_dead(s); +} + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s; + struct pa_context *c = userdata; + uint32_t bytes, channel; + assert(pd && command == PA_COMMAND_REQUEST && t && c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_getu32(t, &bytes) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (!(s = pa_dynarray_get(c->playback_streams, channel))) + return; + + if (s->state != STREAM_READY) + return; + + s->requested_bytes += bytes; + + if (s->requested_bytes && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); +} + +static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s && s->state == STREAM_CREATING); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + if (s->create_complete_callback) + s->create_complete_callback(s, 0, s->create_complete_userdata); + + return; + } + + if (pa_tagstruct_getu32(t, &s->channel) < 0 || + ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + s->channel_valid = 1; + pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); + + s->state = STREAM_READY; + if (s->create_complete_callback) + s->create_complete_callback(s, 1, s->create_complete_userdata); +} + +static void create_stream(struct pa_stream *s, const char *dev) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s); + + s->state = STREAM_CREATING; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_puts(t, s->name); + pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, s->buffer_attr.maxlength); + if (s->direction == PA_STREAM_PLAYBACK) { + pa_tagstruct_putu32(t, s->buffer_attr.tlength); + pa_tagstruct_putu32(t, s->buffer_attr.prebuf); + pa_tagstruct_putu32(t, s->buffer_attr.minreq); + } else + pa_tagstruct_putu32(t, s->buffer_attr.fragsize); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); +} + +static struct pa_stream *internal_stream_new(struct pa_context *c) { + struct pa_stream *s; + + s = pa_xmalloc(sizeof(struct pa_stream)); + s->context = c; + + s->read_callback = NULL; + s->read_userdata = NULL; + s->write_callback = NULL; + s->write_userdata = NULL; + s->die_callback = NULL; + s->die_userdata = NULL; + s->create_complete_callback = NULL; + s->create_complete_userdata = NULL; + s->get_latency_callback = NULL; + s->get_latency_userdata = NULL; + s->finish_sample_callback = NULL; + s->finish_sample_userdata = NULL; + + s->name = NULL; + s->state = STREAM_CREATING; + s->requested_bytes = 0; + s->channel = 0; + s->channel_valid = 0; + s->device_index = (uint32_t) -1; + + memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + + s->next = c->first_stream; + if (s->next) + s->next->previous = s; + s->previous = NULL; + c->first_stream = s; + + return s; +} + +struct pa_stream* pa_stream_new( + struct pa_context *c, + enum pa_stream_direction dir, + const char *dev, + const char *name, + const struct pa_sample_spec *ss, + const struct pa_buffer_attr *attr, + void (*complete) (struct pa_stream*s, int success, void *userdata), + void *userdata) { + + struct pa_stream *s; + + assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = complete; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = dir; + s->sample_spec = *ss; + if (attr) + s->buffer_attr = *attr; + else { + s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; + s->buffer_attr.tlength = DEFAULT_TLENGTH; + s->buffer_attr.prebuf = DEFAULT_PREBUF; + s->buffer_attr.minreq = DEFAULT_MINREQ; + s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; + } + + create_stream(s, dev); + + return s; +} + +void pa_stream_free(struct pa_stream *s) { + assert(s && s->context); + + if (s->context->pdispatch) + pa_pdispatch_unregister_reply(s->context->pdispatch, s); + + pa_xfree(s->name); + + if (s->channel_valid && s->context->state == CONTEXT_READY) { + struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); + pa_tagstruct_putu32(t, s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + } + + if (s->channel_valid) + pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); + + if (s->next) + s->next->previous = s->previous; + if (s->previous) + s->previous->next = s->next; + else + s->context->first_stream = s->next; + + pa_xfree(s); +} + +void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { + s->write_callback = cb; + s->write_userdata = userdata; +} + +void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { + struct pa_memchunk chunk; + assert(s && s->context && data && length && s->state == STREAM_READY); + + chunk.memblock = pa_memblock_new(length); + assert(chunk.memblock && chunk.memblock->data); + memcpy(chunk.memblock->data, data, length); + chunk.index = 0; + chunk.length = length; + + pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + pa_memblock_unref(chunk.memblock); + + /*fprintf(stderr, "Sent %u bytes\n", length);*/ + + if (length < s->requested_bytes) + s->requested_bytes -= length; + else + s->requested_bytes = 0; +} + +size_t pa_stream_writable_size(struct pa_stream *s) { + assert(s && s->state == STREAM_READY); + return s->requested_bytes; +} + +void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { + assert(s && cb); + s->read_callback = cb; + s->read_userdata = userdata; +} + +int pa_stream_is_dead(struct pa_stream *s) { + return s->state == STREAM_DEAD; +} + +int pa_stream_is_ready(struct pa_stream*s) { + return s->state == STREAM_READY; +} + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { + assert(s); + s->die_callback = cb; + s->die_userdata = userdata; +} + +int pa_context_is_pending(struct pa_context *c) { + assert(c); + + if (c->state != CONTEXT_READY) + return 0; + + return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); +} + +struct pa_context* pa_stream_get_context(struct pa_stream *p) { + assert(p); + return p->context; +} + +static void set_dispatch_callbacks(struct pa_context *c); + +static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void set_dispatch_callbacks(struct pa_context *c) { + assert(c && c->state == CONTEXT_READY); + + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + + if (pa_pdispatch_is_pending(c->pdispatch)) { + pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); + return; + } + + if (pa_pstream_is_pending(c->pstream)) { + pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); + return; + } + + assert(c->drain_complete_callback); + c->drain_complete_callback(c, c->drain_complete_userdata); +} + +int pa_context_drain( + struct pa_context *c, + void (*complete) (struct pa_context*c, void *userdata), + void *userdata) { + + assert(c && c->state == CONTEXT_READY); + + if (complete == NULL) { + c->drain_complete_callback = NULL; + pa_pstream_set_drain_callback(c->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + return 0; + } + + if (!pa_context_is_pending(c)) + return -1; + + c->drain_complete_callback = complete; + c->drain_complete_userdata = userdata; + + set_dispatch_callbacks(c); + + return 0; +} + +static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + stream_dead(s); + return; + } + + if (s->state != STREAM_READY) + return; + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->drain_complete_callback) { + void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; + s->drain_complete_callback = NULL; + temp(s, s->drain_complete_userdata); + } +} + + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->state == STREAM_READY); + + if (!complete) { + s->drain_complete_callback = NULL; + return; + } + + s->drain_complete_callback = complete; + s->drain_complete_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + + pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); +} + +void pa_context_exit(struct pa_context *c) { + struct pa_tagstruct *t; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_EXIT); + pa_tagstruct_putu32(t, c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + uint32_t total, count; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &count) < 0 || + pa_tagstruct_getu32(t, &total) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->stat_callback) + c->stat_callback(c, count, total, c->stat_userdata); +} + +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + c->stat_callback = cb; + c->stat_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_STAT); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); +} + +static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + uint32_t latency; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); + return; + } + + if (pa_tagstruct_getu32(t, &latency) < 0 || + !pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->get_latency_callback) + s->get_latency_callback(s, latency, s->get_latency_userdata); +} + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { + uint32_t tag; + struct pa_tagstruct *t; + + p->get_latency_callback = cb; + p->get_latency_userdata = userdata; + + if (cb == NULL) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); +} + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_stream *s; + struct pa_tagstruct *t; + uint32_t tag; + + s = internal_stream_new(c); + assert(s); + + s->create_complete_callback = cb; + s->create_complete_userdata = userdata; + s->name = pa_xstrdup(name); + s->state = STREAM_CREATING; + s->direction = PA_STREAM_UPLOAD; + s->sample_spec = *ss; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_sample_spec(t, ss); + pa_tagstruct_putu32(t, length); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); + + return s; +} + +static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_stream *s = userdata; + assert(pd && s); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(s->context, command, t) < 0) { + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 0, s->finish_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + s->context->error = PA_ERROR_PROTOCOL; + context_dead(s->context); + return; + } + + if (s->finish_sample_callback) + s->finish_sample_callback(s, 1, s->finish_sample_userdata); +} + +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(p); + + p->finish_sample_callback = cb; + p->finish_sample_userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); + pa_tagstruct_putu32(t, tag = p->context->ctag++); + pa_tagstruct_putu32(t, p->channel); + pa_pstream_send_tagstruct(p->context->pstream, t); + pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); +} + +static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 0, c->play_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->play_sample_callback) + c->play_sample_callback(c, 1, c->play_sample_userdata); +} + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name && *name && (!dev || *dev)); + + c->play_sample_callback = cb; + c->play_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_putu32(t, volume); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); +} + +static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 0, c->remove_sample_userdata); + return; + } + + if (!pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->remove_sample_callback) + c->remove_sample_callback(c, 1, c->remove_sample_userdata); +} + +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name); + + c->remove_sample_callback = cb; + c->remove_sample_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); +} + +static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + struct pa_server_info i; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, NULL, c->get_server_info_userdata); + return; + } + + if (pa_tagstruct_gets(t, &i.server_name) < 0 || + pa_tagstruct_gets(t, &i.server_version) < 0 || + pa_tagstruct_gets(t, &i.user_name) < 0 || + pa_tagstruct_gets(t, &i.host_name) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_server_info_callback) + c->get_server_info_callback(c, &i, c->get_server_info_userdata); +} + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_server_info_callback = cb; + c->get_server_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); +} + +static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_sink_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.monitor_source) < 0 || + pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || + pa_tagstruct_getu32(t, &i.latency) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); + } + + if (c->get_sink_info_callback) + c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); +} + +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_source_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || + pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); + } + + if (c->get_source_info_callback) + c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); +} + +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + struct pa_tagstruct *t; + assert(c); + + c->subscribe_callback = cb; + c->subscribe_userdata = userdata; + c->subscribe_mask = m; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); + pa_tagstruct_putu32(t, c->ctag++); + pa_tagstruct_putu32(t, cb ? m : 0); + pa_pstream_send_tagstruct(c->pstream, t); +} + +static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + enum pa_subscription_event_type e; + uint32_t index; + assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); + + if (pa_tagstruct_getu32(t, &e) < 0 || + pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) + c->subscribe_callback(c, e, index, c->subscribe_userdata); +} + +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_sink_info_callback = cb; + c->get_sink_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); +} + +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_source_info_callback = cb; + c->get_source_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); +} + +static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_client_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.protocol_name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); +} + + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_module_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0 || + pa_tagstruct_getu32(t, &i.n_used) < 0 || + pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); +} + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} + +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} diff --git a/polyp/polyplib-scache.h b/polyp/polyplib-scache.h new file mode 100644 index 000000000..a0dd9f9cb --- /dev/null +++ b/polyp/polyplib-scache.h @@ -0,0 +1,178 @@ +#ifndef foopolyplibhfoo +#define foopolyplibhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "sample.h" +#include "polyplib-def.h" +#include "mainloop-api.h" + +#ifdef __cplusplus +//extern "C" { +#endif + +struct pa_context; +struct pa_stream; + +struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); +void pa_context_unref(struct pa_context *c); +struct pa_context* pa_context_ref(struct pa_context *c); + +int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); +int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); +void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); + +int pa_context_is_dead(struct pa_context *c); +int pa_context_is_ready(struct pa_context *c); +int pa_context_errno(struct pa_context *c); + +int pa_context_is_pending(struct pa_context *c); + +struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_unref(struct pa_stream *s); +struct pa_stream *pa_stream_ref(struct pa_stream *s); + +void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); + +void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); + +void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); +void pa_stream_write(struct pa_stream *p, const void *data, size_t length); +size_t pa_stream_writable_size(struct pa_stream *p); + +void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); + +int pa_stream_is_dead(struct pa_stream *p); +int pa_stream_is_ready(struct pa_stream*p); + +void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); + +struct pa_context* pa_stream_get_context(struct pa_stream *p); + +uint32_t pa_stream_get_index(struct pa_stream *s); + +struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); +void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); + +void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +struct pa_sink_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t volume; + uint32_t monitor_source; + const char *monitor_source_name; + uint32_t latency; +}; + +void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); + +struct pa_source_info { + const char *name; + uint32_t index; + const char *description; + struct pa_sample_spec sample_spec; + uint32_t owner_module; + uint32_t monitor_of_sink; + const char *monitor_of_sink_name; +}; + +void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); + +struct pa_server_info { + const char *user_name; + const char *host_name; + const char *server_version; + const char *server_name; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); + +struct pa_module_info { + uint32_t index; + const char*name, *argument; + uint32_t n_used, auto_unload; +}; + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); + +struct pa_client_info { + uint32_t index; + const char *name; + uint32_t owner_module; + const char *protocol_name; +}; + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); + +struct pa_sink_input_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t sink; + struct pa_sample_spec sample_spec; + uint32_t volume; + uint32_t latency; +}; + +void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); + +struct pa_source_output_info { + uint32_t index; + const char *name; + uint32_t owner_module; + uint32_t owner_client; + uint32_t source; + struct pa_sample_spec sample_spec; +}; + +void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); + +void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +void pa_context_exit(struct pa_context *c); +void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); + +void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); + +#ifdef __cplusplus +} +#endif + +#endif From 22cb23eedb2eae7c79dc8fcf395be08bfc666256 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 14 Aug 2004 20:25:32 +0000 Subject: [PATCH 0122/1514] implement proper refcounting in polyplib split polyplib to multiple modules add some prelimenary documentation add doxygen support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@123 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 5 +- configure.ac | 2 +- doxygen/Makefile.am | 11 + doxygen/doxygen.conf.in | 1153 +++++++++++++++++++++++ polyp/Makefile.am | 25 +- polyp/cdecl.h | 21 + polyp/glib-mainloop.h | 20 +- polyp/llist.h | 39 + polyp/mainloop-api.h | 44 +- polyp/mainloop.h | 5 + polyp/memblock.c | 42 +- polyp/memblock.h | 4 +- polyp/native-common.h | 18 +- polyp/pacat.c | 152 ++-- polyp/pactl.c | 148 ++- polyp/polyplib-context.c | 1516 +++++------------------------- polyp/polyplib-context.h | 180 +--- polyp/polyplib-def.h | 17 +- polyp/polyplib-error.h | 12 +- polyp/polyplib-internal.h | 1530 ++----------------------------- polyp/polyplib-introspect.c | 1721 +++++++---------------------------- polyp/polyplib-introspect.h | 109 +-- polyp/polyplib-operation.c | 78 ++ polyp/polyplib-operation.h | 56 ++ polyp/polyplib-sample.c | 1550 ------------------------------- polyp/polyplib-sample.h | 178 ---- polyp/polyplib-scache.c | 1505 +----------------------------- polyp/polyplib-scache.h | 162 +--- polyp/polyplib-simple.c | 68 +- polyp/polyplib-simple.h | 33 +- polyp/polyplib-stream.c | 1608 ++++++-------------------------- polyp/polyplib-stream.h | 180 ++-- polyp/polyplib-subscribe.c | 1520 +------------------------------ polyp/polyplib-subscribe.h | 158 +--- polyp/polyplib.c | 1550 ------------------------------- polyp/polyplib.h | 156 +--- polyp/sample-util.c | 7 - polyp/sample-util.h | 4 - polyp/sample.c | 8 + polyp/sample.h | 21 +- polyp/socket-client.c | 2 +- polyp/socket-client.h | 2 + polyp/tagstruct.h | 2 - polyp/xmalloc.c | 29 +- polyp/xmalloc.h | 2 + 45 files changed, 2853 insertions(+), 12800 deletions(-) create mode 100644 doxygen/Makefile.am create mode 100644 doxygen/doxygen.conf.in create mode 100644 polyp/cdecl.h create mode 100644 polyp/llist.h create mode 100644 polyp/polyplib-operation.c create mode 100644 polyp/polyplib-operation.h delete mode 100644 polyp/polyplib-sample.c delete mode 100644 polyp/polyplib-sample.h delete mode 100644 polyp/polyplib.c diff --git a/Makefile.am b/Makefile.am index a54fd606a..3fc81b40e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,4 +41,7 @@ homepage: all dist distcleancheck: @: -.PHONY: homepage distcleancheck +doxygen: + $(MAKE) -C doxygen + +.PHONY: homepage distcleancheck doxygen diff --git a/configure.ac b/configure.ac index 3183d1743..b7766e4a6 100644 --- a/configure.ac +++ b/configure.ac @@ -84,5 +84,5 @@ AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) -AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html]) +AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf]) AC_OUTPUT diff --git a/doxygen/Makefile.am b/doxygen/Makefile.am new file mode 100644 index 000000000..d2f508c72 --- /dev/null +++ b/doxygen/Makefile.am @@ -0,0 +1,11 @@ +# $Id$ + +noinst_DATA=html + +html: doxygen.conf + doxygen $< + +clean-local: + rm -rf html + +.PHONY: all html diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in new file mode 100644 index 000000000..78a43685d --- /dev/null +++ b/doxygen/doxygen.conf.in @@ -0,0 +1,1153 @@ +# Doxyfile 1.3.8 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = @PACKAGE_NAME@ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of source +# files, where putting all generated files in the same directory would otherwise +# cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= NO + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../polyp/polyplib-context.h ../polyp/polyplib-stream.h ../polyp/polyplib.h ../polyp/sample.h ../polyp/polyplib-def.h ../polyp/polyplib-subscribe.h ../polyp/polyplib-introspect.h ../polyp/polyplib-scache.h ../polyp/mainloop-api.h ../polyp/cdecl.h ../polyp/glib-mainloop.h ../polyp/mainloop.h ../polyp/mainloop-signal.h ../polyp/native-common.h ../polyp/polyplib-error.h ../polyp/polyplib-operation.h ../polyp/polyplib-simple.h + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = PA_C_DECL_BEGIN=,PA_C_DECL_END + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = PA_C_DECL_BEGIN, PA_C_DECL_END + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# If 0 is used for the depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/polyp/Makefile.am b/polyp/Makefile.am index ce753da47..7f70ec9d4 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -25,12 +25,19 @@ polypincludedir=$(includedir)/polyp EXTRA_DIST = polypaudio.pa depmod.py bin_PROGRAMS = polypaudio pacat pactl -noinst_PROGRAMS = pacat-simple parec-simple mainloop-test mainloop-test-glib +noinst_PROGRAMS = mainloop-test mainloop-test-glib pacat-simple parec-simple polypinclude_HEADERS=polyplib.h \ polyplib-def.h \ polyplib-simple.h \ polyplib-error.h \ + polyplib-stream.h \ + polyplib-context.h \ + polyplib-introspect.h \ + polyplib-subscribe.h \ + polyplib-operation.h \ + polyplib-scache.h \ + cdecl.h \ mainloop-api.h \ mainloop.h \ mainloop-signal.h \ @@ -72,10 +79,11 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-x11-bell.la lib_LTLIBRARIES=libpolyp.la \ - libpolyp-simple.la \ libpolyp-error.la \ libpolyp-mainloop.la \ - libpolyp-mainloop-glib.la + libpolyp-mainloop-glib.la \ + libpolyp-simple.la + polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -261,7 +269,7 @@ module_x11_bell_la_SOURCES = module-x11-bell.c module_x11_bell_la_LDFLAGS = -module -avoid-version module_x11_bell_la_LIBADD = $(AM_LIBADD) -lX11 -L/usr/X11R6/lib -libpolyp_la_SOURCES = polyplib.c polyplib.h \ +libpolyp_la_SOURCES = polyplib.h \ polyplib-def.h \ tagstruct.c tagstruct.h \ iochannel.c iochannel.h \ @@ -281,7 +289,14 @@ libpolyp_la_SOURCES = polyplib.c polyplib.h \ socket-util.c socket-util.h \ native-common.h \ sample.c sample.h \ - xmalloc.c xmalloc.h + xmalloc.c xmalloc.h \ + polyplib-operation.c polyplib-operation.h \ + polyplib-context.c polyplib-context.h \ + polyplib-stream.c polyplib-stream.h \ + polyplib-introspect.c polyplib-introspect.h \ + polyplib-scache.c polyplib-scache.h \ + polyplib-subscribe.c polyplib-subscribe.h \ + cdecl.h libpolyp_la_CFLAGS = $(AM_CFLAGS) libpolyp_mainloop_la_SOURCES = mainloop-api.h mainloop-api.c \ diff --git a/polyp/cdecl.h b/polyp/cdecl.h new file mode 100644 index 000000000..39880a474 --- /dev/null +++ b/polyp/cdecl.h @@ -0,0 +1,21 @@ +#ifndef foocdeclhfoo +#define foocdeclhfoo + +/** \file + * C++ compatibility support */ + +#ifdef __cplusplus +/** If using C++ this macro enables C mode, otherwise does nothing */ +#define PA_C_DECL_BEGIN extern "C" { +/** If using C++ this macros switches back to C++ mode, otherwise does nothing */ +#define PA_C_DECL_END } + +#else +/** If using C++ this macro enables C mode, otherwise does nothing */ +#define PA_C_DECL_BEGIN +/** If using C++ this macros switches back to C++ mode, otherwise does nothing */ +#define PA_C_DECL_END + +#endif + +#endif diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h index 7655108af..c67e72bd1 100644 --- a/polyp/glib-mainloop.h +++ b/polyp/glib-mainloop.h @@ -4,20 +4,26 @@ #include #include "mainloop-api.h" +#include "cdecl.h" -#ifdef __cplusplus -extern "C" { -#endif +/** \file + * GLIB main loop support */ +PA_C_DECL_BEGIN + +/** \struct pa_glib_mainloop + * A GLIB main loop object */ struct pa_glib_mainloop; +/** Create a new GLIB main loop object for the specified GLIB main loop context. If c is NULL the default context is used. */ struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c); + +/** Free the GLIB main loop object */ void pa_glib_mainloop_free(struct pa_glib_mainloop* g); + +/** Return the abstract main loop API vtable for the GLIB main loop object */ struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g); - -#ifdef __cplusplus -} -#endif +PA_C_DECL_BEGIN #endif diff --git a/polyp/llist.h b/polyp/llist.h new file mode 100644 index 000000000..1f145de21 --- /dev/null +++ b/polyp/llist.h @@ -0,0 +1,39 @@ +#ifndef foollistfoo +#define foollistfoo + +#define PA_LLIST_HEAD(t,name) t *name + +#define PA_LLIST_FIELDS(t) t *next, *prev; + +#define PA_LLIST_HEAD_INIT(t,item) do { (item) = NULL; } while(0) + +#define PA_LLIST_INIT(t,item) do { \ + t *_item = (item); \ + assert(_item); \ + _item->prev = _item->next = NULL; \ + } while(0) + +#define PA_LLIST_PREPEND(t,head,item) do { \ + t **_head = &(head), *_item = (item); \ + assert(_item); \ + if ((_item->next = *_head)) \ + _item->next->prev = _item; \ + _item->prev = NULL; \ + *_head = _item; \ + } while (0) + +#define PA_LLIST_REMOVE(t,head,item) do { \ + t **_head = &(head), *_item = (item); \ + assert(_item); \ + if (_item->next) \ + _item->next->prev = _item->prev; \ + if (_item->prev) \ + _item->prev->next = _item->next; \ + else {\ + assert(*_head == _item); \ + *_head = _item->next; \ + } \ + _item->next = _item->prev = NULL; \ + } while(0) + +#endif diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index 1b9e27836..97ab6a684 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -22,26 +22,37 @@ USA. ***/ -#include #include +#include -#ifdef __cplusplus -extern "C" { -#endif +#include "cdecl.h" +PA_C_DECL_BEGIN + +/** A bitmask for IO events */ enum pa_io_event_flags { - PA_IO_EVENT_NULL = 0, - PA_IO_EVENT_INPUT = 1, - PA_IO_EVENT_OUTPUT = 2, - PA_IO_EVENT_HANGUP = 4, - PA_IO_EVENT_ERROR = 8, + PA_IO_EVENT_NULL = 0, /**< No event */ + PA_IO_EVENT_INPUT = 1, /**< Input event */ + PA_IO_EVENT_OUTPUT = 2, /**< Output event */ + PA_IO_EVENT_HANGUP = 4, /**< Hangup event */ + PA_IO_EVENT_ERROR = 8, /**< Error event */ }; +/** \struct pa_io_event + * An IO event source object */ struct pa_io_event; + +/** \struct pa_defer_event + * A deferred event source object. Events of this type are triggered once in every main loop iteration */ struct pa_defer_event; + +/** \struct pa_time_event + * A timer event source object */ struct pa_time_event; +/** An abstract mainloop API vtable */ struct pa_mainloop_api { + /** A pointer to some private, arbitrary data of the main loop implementation */ void *userdata; /* IO sources */ @@ -56,20 +67,25 @@ struct pa_mainloop_api { void (*time_free)(struct pa_time_event* e); void (*time_set_destroy)(struct pa_time_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)); - /* Deferred sources */ + /** Create a new deferred event source object */ struct pa_defer_event* (*defer_new)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event* e, void *userdata), void *userdata); + + /** Enable or disable a deferred event source temporarily */ void (*defer_enable)(struct pa_defer_event* e, int b); + + /** Free a deferred event source object */ void (*defer_free)(struct pa_defer_event* e); + + /** Set a function that is called when the deferred event source is destroyed. Use this to free the userdata argument if required */ void (*defer_set_destroy)(struct pa_defer_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)); - /* Exit mainloop */ + /** Exit the main loop and return the specfied retval*/ void (*quit)(struct pa_mainloop_api*a, int retval); }; +/** Run the specified callback function once from the main loop using an anonymous defer event. */ void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(struct pa_mainloop_api*m, void *userdata), void *userdata); -#ifdef __cplusplus -} -#endif +PA_C_DECL_END #endif diff --git a/polyp/mainloop.h b/polyp/mainloop.h index 58448c3ee..4a4c85dfa 100644 --- a/polyp/mainloop.h +++ b/polyp/mainloop.h @@ -23,6 +23,9 @@ ***/ #include "mainloop-api.h" +#include "cdecl.h" + +PA_C_DECL_BEGIN struct pa_mainloop; @@ -34,4 +37,6 @@ int pa_mainloop_run(struct pa_mainloop *m, int *retval); struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m); +PA_C_DECL_END + #endif diff --git a/polyp/memblock.c b/polyp/memblock.c index 0571f5dae..a4452efa4 100644 --- a/polyp/memblock.c +++ b/polyp/memblock.c @@ -39,6 +39,7 @@ struct pa_memblock *pa_memblock_new(size_t length) { b->ref = 1; b->length = length; b->data = b+1; + b->free_cb = NULL; memblock_count++; memblock_total += length; return b; @@ -50,6 +51,7 @@ struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length) { b->ref = 1; b->length = length; b->data = d; + b->free_cb = NULL; memblock_count++; memblock_total += length; return b; @@ -61,6 +63,21 @@ struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length) { b->ref = 1; b->length = length; b->data = d; + b->free_cb = NULL; + memblock_count++; + memblock_total += length; + return b; +} + +struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p)) { + struct pa_memblock *b; + assert(d && length && free_cb); + b = pa_xmalloc(sizeof(struct pa_memblock)); + b->type = PA_MEMBLOCK_USER; + b->ref = 1; + b->length = length; + b->data = d; + b->free_cb = free_cb; memblock_count++; memblock_total += length; return b; @@ -74,31 +91,28 @@ struct pa_memblock* pa_memblock_ref(struct pa_memblock*b) { void pa_memblock_unref(struct pa_memblock*b) { assert(b && b->ref >= 1); - b->ref--; - - if (b->ref == 0) { - if (b->type == PA_MEMBLOCK_DYNAMIC) - pa_xfree(b->data); + if ((--(b->ref)) == 0) { memblock_count--; memblock_total -= b->length; + if (b->type == PA_MEMBLOCK_USER) { + assert(b->free_cb); + b->free_cb(b->data); + } else if (b->type == PA_MEMBLOCK_DYNAMIC) + pa_xfree(b->data); + pa_xfree(b); } } void pa_memblock_unref_fixed(struct pa_memblock *b) { - void *d; - - assert(b && b->ref >= 1); + assert(b && b->ref >= 1 && b->type == PA_MEMBLOCK_FIXED); - if (b->ref == 1) { + if (b->ref == 1) pa_memblock_unref(b); - return; - } else { - d = pa_xmalloc(b->length); - memcpy(d, b->data, b->length); - b->data = d; + else { + b->data = pa_xmemdup(b->data, b->length); b->type = PA_MEMBLOCK_DYNAMIC; b->ref--; } diff --git a/polyp/memblock.h b/polyp/memblock.h index 4bb029774..6e79aa3ef 100644 --- a/polyp/memblock.h +++ b/polyp/memblock.h @@ -25,18 +25,20 @@ #include #include -enum pa_memblock_type { PA_MEMBLOCK_FIXED, PA_MEMBLOCK_APPENDED, PA_MEMBLOCK_DYNAMIC }; +enum pa_memblock_type { PA_MEMBLOCK_FIXED, PA_MEMBLOCK_APPENDED, PA_MEMBLOCK_DYNAMIC, PA_MEMBLOCK_USER }; struct pa_memblock { enum pa_memblock_type type; unsigned ref; size_t length; void *data; + void (*free_cb)(void *p); }; struct pa_memblock *pa_memblock_new(size_t length); struct pa_memblock *pa_memblock_new_fixed(void *data, size_t length); struct pa_memblock *pa_memblock_new_dynamic(void *data, size_t length); +struct pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p)); void pa_memblock_unref(struct pa_memblock*b); struct pa_memblock* pa_memblock_ref(struct pa_memblock*b); diff --git a/polyp/native-common.h b/polyp/native-common.h index 4d5ab53d7..fa3213d01 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -64,6 +64,9 @@ enum { PA_COMMAND_SUBSCRIBE, PA_COMMAND_SUBSCRIBE_EVENT, + + PA_COMMAND_SET_SINK_VOLUME, + PA_COMMAND_SET_SINK_INPUT_VOLUME, PA_COMMAND_MAX }; @@ -90,13 +93,14 @@ enum { #define PA_NATIVE_COOKIE_FILE ".polypaudio-cookie" enum pa_subscription_mask { - PA_SUBSCRIPTION_FACILITY_SINK = 1, - PA_SUBSCRIPTION_FACILITY_SOURCE = 2, - PA_SUBSCRIPTION_FACILITY_SINK_INPUT = 4, - PA_SUBSCRIPTION_FACILITY_SOURCE_OUTPUT = 8, - PA_SUBSCRIPTION_FACILITY_MODULE = 16, - PA_SUBSCRIPTION_FACILITY_CLIENT = 32, - PA_SUBSCRIPTION_FACILITY_SAMPLE_CACHE = 64, + PA_SUBSCRIPTION_MASK_NULL = 0, + PA_SUBSCRIPTION_MASK_SINK = 1, + PA_SUBSCRIPTION_MASK_SOURCE = 2, + PA_SUBSCRIPTION_MASK_SINK_INPUT = 4, + PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8, + PA_SUBSCRIPTION_MASK_MODULE = 16, + PA_SUBSCRIPTION_MASK_CLIENT = 32, + PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, }; enum pa_subscription_event_type { diff --git a/polyp/pacat.c b/polyp/pacat.c index 4d8605c7a..5d29451ae 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -52,18 +52,6 @@ static void quit(int ret) { mainloop_api->quit(mainloop_api, ret); } -static void context_die_callback(struct pa_context *c, void *userdata) { - assert(c); - fprintf(stderr, "Connection to server shut down, exiting.\n"); - quit(1); -} - -static void stream_die_callback(struct pa_stream *s, void *userdata) { - assert(s); - fprintf(stderr, "Stream deleted, exiting.\n"); - quit(1); -} - static void do_stream_write(size_t length) { size_t l; assert(length); @@ -75,7 +63,7 @@ static void do_stream_write(size_t length) { if (l > buffer_length) l = buffer_length; - pa_stream_write(stream, buffer+buffer_index, l); + pa_stream_write(stream, buffer+buffer_index, l, NULL); buffer_length -= l; buffer_index += l; @@ -115,63 +103,97 @@ static void stream_read_callback(struct pa_stream *s, const void*data, size_t le buffer_index = 0; } -static void stream_complete_callback(struct pa_stream*s, int success, void *userdata) { +static void stream_state_callback(struct pa_stream *s, void *userdata) { assert(s); - if (!success) { - fprintf(stderr, "Stream creation failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); - quit(1); - return; - } + switch (pa_stream_get_state(s)) { + case PA_STREAM_CREATING: + break; - fprintf(stderr, "Stream created.\n"); + case PA_STREAM_READY: + fprintf(stderr, "Stream successfully created\n"); + break; + + case PA_STREAM_TERMINATED: + quit(0); + break; + + case PA_STREAM_FAILED: + default: + fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + quit(1); + } } -static void context_complete_callback(struct pa_context *c, int success, void *userdata) { +static void context_state_callback(struct pa_context *c, void *userdata) { static const struct pa_sample_spec ss = { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 }; + + assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; - assert(c && !stream); + case PA_CONTEXT_READY: + + assert(c && !stream); + fprintf(stderr, "Connection established.\n"); - if (!success) { - fprintf(stderr, "Connection failed: %s\n", pa_strerror(pa_context_errno(c))); - goto fail; + stream = pa_stream_new(c, "pacat", &ss); + assert(stream); + + pa_stream_set_state_callback(stream, stream_state_callback, NULL); + pa_stream_set_write_callback(stream, stream_write_callback, NULL); + pa_stream_set_read_callback(stream, stream_read_callback, NULL); + + if (mode == PLAYBACK) + pa_stream_connect_playback(stream, NULL, NULL); + else + pa_stream_connect_record(stream, NULL, NULL); + + break; + + case PA_CONTEXT_TERMINATED: + quit(0); + break; + + case PA_CONTEXT_FAILED: + default: + fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); } - - fprintf(stderr, "Connection established.\n"); - - if (!(stream = pa_stream_new(c, mode == PLAYBACK ? PA_STREAM_PLAYBACK : PA_STREAM_RECORD, NULL, "pacat", &ss, NULL, stream_complete_callback, NULL))) { - fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(c))); - goto fail; - } - - pa_stream_set_die_callback(stream, stream_die_callback, NULL); - pa_stream_set_write_callback(stream, stream_write_callback, NULL); - pa_stream_set_read_callback(stream, stream_read_callback, NULL); - - return; - -fail: - quit(1); } static void context_drain_complete(struct pa_context*c, void *userdata) { - quit(0); + pa_context_disconnect(c); } -static void stream_drain_complete(struct pa_stream*s, void *userdata) { +static void stream_drain_complete(struct pa_stream*s, int success, void *userdata) { + struct pa_operation *o; + + if (!success) { + fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + } + fprintf(stderr, "Playback stream drained.\n"); - pa_stream_free(stream); + pa_stream_disconnect(stream); + pa_stream_unref(stream); stream = NULL; - if (pa_context_drain(context, context_drain_complete, NULL) < 0) - quit(0); - else + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) + pa_context_disconnect(context); + else { + pa_operation_unref(o); fprintf(stderr, "Draining connection to server.\n"); + } } static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { @@ -184,7 +206,7 @@ static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int return; } - if (!stream || !pa_stream_is_ready(stream) || !(l = w = pa_stream_writable_size(stream))) + if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream))) l = 4096; buffer = malloc(l); @@ -192,7 +214,7 @@ static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int if ((r = read(fd, buffer, l)) <= 0) { if (r == 0) { fprintf(stderr, "Got EOF.\n"); - pa_stream_drain(stream, stream_drain_complete, NULL); + pa_operation_unref(pa_stream_drain(stream, stream_drain_complete, NULL)); } else { fprintf(stderr, "read() failed: %s\n", strerror(errno)); quit(1); @@ -259,10 +281,11 @@ static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, v } static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { - if (mode == PLAYBACK) { - fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); - pa_stream_get_latency(stream, stream_get_latency_callback, NULL); - } + if (mode != PLAYBACK) + return; + + fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); + pa_operation_unref(pa_stream_get_latency(stream, stream_get_latency_callback, NULL)); } int main(int argc, char *argv[]) { @@ -306,12 +329,9 @@ int main(int argc, char *argv[]) { goto quit; } - if (pa_context_connect(context, NULL, context_complete_callback, NULL) < 0) { - fprintf(stderr, "pa_context_connext() failed.\n"); - goto quit; - } - - pa_context_set_die_callback(context, context_die_callback, NULL); + pa_context_set_state_callback(context, context_state_callback, NULL); + + pa_context_connect(context, NULL); if (pa_mainloop_run(m, &ret) < 0) { fprintf(stderr, "pa_mainloop_run() failed.\n"); @@ -320,15 +340,21 @@ int main(int argc, char *argv[]) { quit: if (stream) - pa_stream_free(stream); - if (context) - pa_context_free(context); + pa_stream_unref(stream); + if (context) + pa_context_unref(context); + + if (stdio_event) { + assert(mainloop_api); + mainloop_api->io_free(stdio_event); + } + if (m) { pa_signal_done(); pa_mainloop_free(m); } - + if (buffer) free(buffer); diff --git a/polyp/pactl.c b/polyp/pactl.c index 2f3a48331..0ff2aa909 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -68,31 +68,27 @@ static void quit(int ret) { mainloop_api->quit(mainloop_api, ret); } -static void context_die_callback(struct pa_context *c, void *userdata) { - assert(c); - fprintf(stderr, "Connection to server shut down, exiting.\n"); - quit(1); -} static void context_drain_complete(struct pa_context *c, void *userdata) { - assert(c); - fprintf(stderr, "Connection to server shut down, exiting.\n"); - quit(0); + pa_context_disconnect(c); } static void drain(void) { - if (pa_context_drain(context, context_drain_complete, NULL) < 0) - quit(0); + struct pa_operation *o; + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) + pa_context_disconnect(context); + else + pa_operation_unref(o); } -static void stat_callback(struct pa_context *c, uint32_t blocks, uint32_t total, void *userdata) { - if (blocks == (uint32_t) -1) { +static void stat_callback(struct pa_context *c, const struct pa_stat_info *i, void *userdata) { + if (!i) { fprintf(stderr, "Failed to get statistics: %s\n", pa_strerror(pa_context_errno(c))); quit(1); return; } - fprintf(stderr, "Currently in use: %u blocks containing %u bytes total.\n", blocks, total); + fprintf(stderr, "Currently in use: %u blocks containing %u bytes total.\n", i->memblock_count, i->memblock_total); drain(); } @@ -116,22 +112,23 @@ static void remove_sample_callback(struct pa_context *c, int success, void *user drain(); } -static void stream_die_callback(struct pa_stream *s, void *userdata) { - assert(s); - fprintf(stderr, "Stream deleted, exiting.\n"); - quit(1); -} - -static void finish_sample_callback(struct pa_stream *s, int success, void *userdata) { +static void stream_state_callback(struct pa_stream *s, void *userdata) { assert(s); - if (!success) { - fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(context))); - quit(1); - return; + switch (pa_stream_get_state(s)) { + case PA_STREAM_CREATING: + case PA_STREAM_READY: + break; + + case PA_STREAM_TERMINATED: + drain(); + break; + + case PA_STREAM_FAILED: + default: + fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + quit(1); } - - drain(); } static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { @@ -151,58 +148,55 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user quit(1); } - pa_stream_write(s, d, length); - free(d); + pa_stream_write(s, d, length, free); sample_length -= length; if (sample_length <= 0) { pa_stream_set_write_callback(sample_stream, NULL, NULL); - pa_stream_finish_sample(sample_stream, finish_sample_callback, NULL); + pa_stream_finish_upload(sample_stream); } } -static void upload_callback(struct pa_stream *s, int success, void *userdata) { - if (!success) { - fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(context))); - quit(1); - } -} - -static void context_complete_callback(struct pa_context *c, int success, void *userdata) { +static void context_state_callback(struct pa_context *c, void *userdata) { assert(c); + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; - if (!success) { - fprintf(stderr, "Connection failed: %s\n", pa_strerror(pa_context_errno(c))); - goto fail; + case PA_CONTEXT_READY: + if (action == STAT) + pa_operation_unref(pa_context_stat(c, stat_callback, NULL)); + else if (action == PLAY_SAMPLE) + pa_operation_unref(pa_context_play_sample(c, process_argv[2], NULL, 0x100, play_sample_callback, NULL)); + else if (action == REMOVE_SAMPLE) + pa_operation_unref(pa_context_remove_sample(c, process_argv[2], remove_sample_callback, NULL)); + else if (action == UPLOAD_SAMPLE) { + + sample_stream = pa_stream_new(c, sample_name, &sample_spec); + assert(sample_stream); + + pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL); + pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL); + pa_stream_connect_upload(sample_stream, sample_length); + } else { + assert(action == EXIT); + pa_context_exit_daemon(c); + drain(); + } + break; + + case PA_CONTEXT_TERMINATED: + quit(0); + break; + + case PA_CONTEXT_FAILED: + default: + fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); } - - fprintf(stderr, "Connection established.\n"); - - if (action == STAT) - pa_context_stat(c, stat_callback, NULL); - else if (action == PLAY_SAMPLE) - pa_context_play_sample(c, process_argv[2], NULL, 0x100, play_sample_callback, NULL); - else if (action == REMOVE_SAMPLE) - pa_context_remove_sample(c, process_argv[2], remove_sample_callback, NULL); - else if (action == UPLOAD_SAMPLE) { - if (!(sample_stream = pa_context_upload_sample(c, sample_name, &sample_spec, sample_length, upload_callback, NULL))) { - fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(c))); - goto fail; - } - - pa_stream_set_die_callback(sample_stream, stream_die_callback, NULL); - pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL); - } else { - assert(action == EXIT); - pa_context_exit(c); - drain(); - } - - return; - -fail: - quit(1); } static void exit_signal_callback(struct pa_mainloop_api *m, struct pa_signal_event *e, int sig, void *userdata) { @@ -234,12 +228,15 @@ int main(int argc, char *argv[]) { sample_name = argv[3]; else { char *f = strrchr(argv[2], '/'); + size_t n; if (f) f++; else f = argv[2]; - strncpy(sample_name = tmp, f, strcspn(f, ".")); + n = strcspn(f, "."); + strncpy(sample_name = tmp, f, n); + tmp[n] = 0; } memset(&sfinfo, 0, sizeof(sfinfo)); @@ -292,12 +289,8 @@ int main(int argc, char *argv[]) { goto quit; } - if (pa_context_connect(context, NULL, context_complete_callback, NULL) < 0) { - fprintf(stderr, "pa_context_connext() failed.\n"); - goto quit; - } - - pa_context_set_die_callback(context, context_die_callback, NULL); + pa_context_set_state_callback(context, context_state_callback, NULL); + pa_context_connect(context, NULL); if (pa_mainloop_run(m, &ret) < 0) { fprintf(stderr, "pa_mainloop_run() failed.\n"); @@ -305,8 +298,11 @@ int main(int argc, char *argv[]) { } quit: + if (sample_stream) + pa_stream_unref(sample_stream); + if (context) - pa_context_free(context); + pa_context_unref(context); if (m) { pa_signal_done(); @@ -315,6 +311,6 @@ quit: if (sndfile) sf_close(sndfile); - + return ret; } diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 35001d3d3..5f849e242 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -31,7 +31,8 @@ #include #include -#include "polyplib.h" +#include "polyplib-internal.h" +#include "polyplib-context.h" #include "native-common.h" #include "pdispatch.h" #include "pstream.h" @@ -42,128 +43,11 @@ #include "util.h" #include "xmalloc.h" -#define DEFAULT_MAXLENGTH 204800 -#define DEFAULT_TLENGTH 10240 -#define DEFAULT_PREBUF 4096 -#define DEFAULT_MINREQ 1024 -#define DEFAULT_FRAGSIZE 1024 - -#define DEFAULT_TIMEOUT (5*60) -#define DEFAULT_SERVER "/tmp/polypaudio/native" -#define DEFAULT_PORT "4713" - -struct pa_context { - char *name; - struct pa_mainloop_api* mainloop; - struct pa_socket_client *client; - struct pa_pstream *pstream; - struct pa_pdispatch *pdispatch; - struct pa_dynarray *record_streams, *playback_streams; - struct pa_stream *first_stream; - uint32_t ctag; - uint32_t error; - enum { - CONTEXT_UNCONNECTED, - CONTEXT_CONNECTING, - CONTEXT_AUTHORIZING, - CONTEXT_SETTING_NAME, - CONTEXT_READY, - CONTEXT_DEAD - } state; - - void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); - void *connect_complete_userdata; - - void (*drain_complete_callback)(struct pa_context*c, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_context*c, void *userdata); - void *die_userdata; - - void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); - void *stat_userdata; - - void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); - void *play_sample_userdata; - - void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); - void *remove_sample_userdata; - - void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); - void *get_server_info_userdata; - - void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); - void *get_sink_info_userdata; - - void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); - void *get_source_info_userdata; - - void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); - void *subscribe_userdata; - enum pa_subscription_mask subscribe_mask; - - void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); - void *get_client_info_userdata; - - void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); - void *get_module_info_userdata; - - uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; -}; - -struct pa_stream { - struct pa_context *context; - struct pa_stream *next, *previous; - - char *name; - struct pa_buffer_attr buffer_attr; - struct pa_sample_spec sample_spec; - uint32_t channel; - int channel_valid; - uint32_t device_index; - enum pa_stream_direction direction; - - enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; - uint32_t requested_bytes; - - void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); - void *read_userdata; - - void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); - void *write_userdata; - - void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); - void *create_complete_userdata; - - void (*drain_complete_callback)(struct pa_stream *s, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_stream*c, void *userdata); - void *die_userdata; - - void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); - void *get_latency_userdata; - - void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); - void *finish_sample_userdata; -}; - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); - static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { - [PA_COMMAND_ERROR] = { NULL }, - [PA_COMMAND_REPLY] = { NULL }, - [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_EXIT] = { NULL }, - [PA_COMMAND_REQUEST] = { command_request }, - [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, + [PA_COMMAND_REQUEST] = { pa_command_request }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { pa_command_stream_killed }, + [PA_COMMAND_RECORD_STREAM_KILLED] = { pa_command_stream_killed }, + [PA_COMMAND_SUBSCRIBE_EVENT] = { pa_command_subscribe_event }, }; struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { @@ -171,65 +55,41 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * assert(mainloop && name); c = pa_xmalloc(sizeof(struct pa_context)); + c->ref = 1; c->name = pa_xstrdup(name); c->mainloop = mainloop; c->client = NULL; c->pstream = NULL; c->pdispatch = NULL; c->playback_streams = pa_dynarray_new(); - assert(c->playback_streams); c->record_streams = pa_dynarray_new(); - assert(c->record_streams); - c->first_stream = NULL; + assert(c->playback_streams && c->record_streams); + + PA_LLIST_HEAD_INIT(struct pa_stream, c->streams); + PA_LLIST_HEAD_INIT(struct pa_operation, c->operations); + c->error = PA_ERROR_OK; - c->state = CONTEXT_UNCONNECTED; + c->state = PA_CONTEXT_UNCONNECTED; c->ctag = 0; - c->connect_complete_callback = NULL; - c->connect_complete_userdata = NULL; - - c->drain_complete_callback = NULL; - c->drain_complete_userdata = NULL; - - c->die_callback = NULL; - c->die_userdata = NULL; - - c->stat_callback = NULL; - c->stat_userdata = NULL; - - c->play_sample_callback = NULL; - c->play_sample_userdata = NULL; - - c->remove_sample_callback = NULL; - c->remove_sample_userdata = NULL; - - c->get_server_info_callback = NULL; - c->get_server_info_userdata = NULL; - - c->get_sink_info_callback = NULL; - c->get_sink_info_userdata = NULL; - - c->get_source_info_callback = NULL; - c->get_source_info_userdata = NULL; + c->state_callback = NULL; + c->state_userdata = NULL; c->subscribe_callback = NULL; c->subscribe_userdata = NULL; - c->get_client_info_callback = NULL; - c->get_client_info_userdata = NULL; - - c->get_module_info_callback = NULL; - c->get_module_info_userdata = NULL; - pa_check_for_sigpipe(); return c; } -void pa_context_free(struct pa_context *c) { +static void context_free(struct pa_context *c) { assert(c); - while (c->first_stream) - pa_stream_free(c->first_stream); + while (c->operations) + pa_operation_cancel(c->operations); + + while (c->streams) + pa_stream_set_state(c->streams, PA_STREAM_TERMINATED); if (c->client) pa_socket_client_free(c->client); @@ -237,6 +97,7 @@ void pa_context_free(struct pa_context *c) { pa_pdispatch_free(c->pdispatch); if (c->pstream) pa_pstream_free(c->pstream); + if (c->record_streams) pa_dynarray_free(c->record_streams, NULL, NULL); if (c->playback_streams) @@ -246,66 +107,82 @@ void pa_context_free(struct pa_context *c) { pa_xfree(c); } -static void stream_dead(struct pa_stream *s) { - assert(s); - - if (s->state == STREAM_DEAD) - return; - - if (s->state == STREAM_READY) { - s->state = STREAM_DEAD; - if (s->die_callback) - s->die_callback(s, s->die_userdata); - } else - s->state = STREAM_DEAD; +struct pa_context* pa_context_ref(struct pa_context *c) { + assert(c && c->ref >= 1); + c->ref++; + return c; } -static void context_dead(struct pa_context *c) { - struct pa_stream *s; +void pa_context_unref(struct pa_context *c) { + assert(c && c->ref >= 1); + + if ((--(c->ref)) == 0) + context_free(c); +} + +void pa_context_set_state(struct pa_context *c, enum pa_context_state st) { assert(c); - if (c->state == CONTEXT_DEAD) + if (c->state == st) return; - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - c->pdispatch = NULL; - - if (c->pstream) - pa_pstream_free(c->pstream); - c->pstream = NULL; - - if (c->client) - pa_socket_client_free(c->client); - c->client = NULL; - - for (s = c->first_stream; s; s = s->next) - stream_dead(s); + pa_context_ref(c); - if (c->state == CONTEXT_READY) { - c->state = CONTEXT_DEAD; - if (c->die_callback) - c->die_callback(c, c->die_userdata); - } else - c->state = CONTEXT_DEAD; + if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) { + struct pa_stream *s; + + s = c->streams ? pa_stream_ref(c->streams) : NULL; + while (s) { + struct pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL; + pa_stream_set_state(s, st == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED); + pa_stream_unref(s); + s = n; + } + + if (c->pdispatch) + pa_pdispatch_free(c->pdispatch); + c->pdispatch = NULL; + + if (c->pstream) + pa_pstream_free(c->pstream); + c->pstream = NULL; + + if (c->client) + pa_socket_client_free(c->client); + c->client = NULL; + } + + c->state = st; + if (c->state_callback) + c->state_callback(c, c->state_userdata); + + pa_context_unref(c); +} + +void pa_context_fail(struct pa_context *c, int error) { + assert(c); + c->error = error; + pa_context_set_state(c, PA_CONTEXT_FAILED); } static void pstream_die_callback(struct pa_pstream *p, void *userdata) { struct pa_context *c = userdata; assert(p && c); - c->error = PA_ERROR_CONNECTIONTERMINATED; - context_dead(c); + pa_context_fail(c, PA_ERROR_CONNECTIONTERMINATED); } static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { struct pa_context *c = userdata; assert(p && packet && c); + pa_context_ref(c); + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { fprintf(stderr, "polyp.c: invalid packet.\n"); - c->error = PA_ERROR_PROTOCOL; - context_dead(c); + pa_context_fail(c, PA_ERROR_PROTOCOL); } + + pa_context_unref(c); } static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { @@ -313,90 +190,100 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, in struct pa_stream *s; assert(p && chunk && c && chunk->memblock && chunk->memblock->data); - if (!(s = pa_dynarray_get(c->record_streams, channel))) - return; - - if (s->read_callback) - s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); -} - -static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { - assert(c && t); + pa_context_ref(c); - if (command == PA_COMMAND_ERROR) { - if (pa_tagstruct_getu32(t, &c->error) < 0) { - c->error = PA_ERROR_PROTOCOL; - return -1; - } - - return 0; + if ((s = pa_dynarray_get(c->record_streams, channel))) { + if (s->read_callback) + s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); } - c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; - return -1; + pa_context_unref(c); +} + +int pa_context_handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { + assert(c && t); + + if (command == PA_COMMAND_ERROR) { + if (pa_tagstruct_getu32(t, &c->error) < 0) { + pa_context_fail(c, PA_ERROR_PROTOCOL); + return -1; + + } + } else if (command == PA_COMMAND_TIMEOUT) + c->error = PA_ERROR_TIMEOUT; + else { + pa_context_fail(c, PA_ERROR_PROTOCOL); + return -1; + } + + return 0; } static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_context *c = userdata; - assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); + assert(pd && c && (c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME)); + pa_context_ref(c); + if (command != PA_COMMAND_REPLY) { - handle_error(c, command, t); - context_dead(c); + if (pa_context_handle_error(c, command, t) < 0) + pa_context_fail(c, PA_ERROR_PROTOCOL); - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; + goto finish; } - if (c->state == CONTEXT_AUTHORIZING) { - struct pa_tagstruct *t; - c->state = CONTEXT_SETTING_NAME; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, c->name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - } else { - assert(c->state == CONTEXT_SETTING_NAME); - - c->state = CONTEXT_READY; + switch(c->state) { + case PA_CONTEXT_AUTHORIZING: { + struct pa_tagstruct *t; + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, c->name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - if (c->connect_complete_callback) - c->connect_complete_callback(c, 1, c->connect_complete_userdata); + pa_context_set_state(c, PA_CONTEXT_SETTING_NAME); + break; + } + + case PA_CONTEXT_SETTING_NAME : + pa_context_set_state(c, PA_CONTEXT_READY); + break; + + default: + assert(0); } - return; +finish: + pa_context_unref(c); } static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { struct pa_context *c = userdata; struct pa_tagstruct *t; uint32_t tag; - assert(client && c && c->state == CONTEXT_CONNECTING); + assert(client && c && c->state == PA_CONTEXT_CONNECTING); + pa_context_ref(c); + pa_socket_client_free(client); c->client = NULL; if (!io) { - c->error = PA_ERROR_CONNECTIONREFUSED; - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; + pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + goto finish; } - + + assert(!c->pstream); c->pstream = pa_pstream_new(c->mainloop, io); assert(c->pstream); + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); - + + assert(!c->pdispatch); c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); assert(c->pdispatch); @@ -407,7 +294,11 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - c->state = CONTEXT_AUTHORIZING; + + pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); + +finish: + pa_context_unref(c); } static struct sockaddr *resolve_server(const char *server, size_t *len) { @@ -438,353 +329,89 @@ static struct sockaddr *resolve_server(const char *server, size_t *len) { return sa; } -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { - assert(c && c->state == CONTEXT_UNCONNECTED); +int pa_context_connect(struct pa_context *c, const char *server) { + int r = -1; + assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED); + pa_context_ref(c); + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { - c->error = PA_ERROR_AUTHKEY; - return -1; + pa_context_fail(c, PA_ERROR_AUTHKEY); + goto finish; } if (!server) - if (!(server = getenv("POLYP_SERVER"))) + if (!(server = getenv(ENV_DEFAULT_SERVER))) server = DEFAULT_SERVER; assert(!c->client); if (*server == '/') { if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; + pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + goto finish; } } else { struct sockaddr* sa; size_t sa_len; if (!(sa = resolve_server(server, &sa_len))) { - c->error = PA_ERROR_INVALIDSERVER; - return -1; + pa_context_fail(c, PA_ERROR_INVALIDSERVER); + goto finish; } c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); pa_xfree(sa); if (!c->client) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; + pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + goto finish; } } - c->connect_complete_callback = complete; - c->connect_complete_userdata = userdata; - pa_socket_client_set_callback(c->client, on_connection, c); - c->state = CONTEXT_CONNECTING; + pa_context_set_state(c, PA_CONTEXT_CONNECTING); - return 0; + r = 0; + +finish: + pa_context_unref(c); + + return r; } -int pa_context_is_dead(struct pa_context *c) { +void pa_context_disconnect(struct pa_context *c) { assert(c); - return c->state == CONTEXT_DEAD; + pa_context_set_state(c, PA_CONTEXT_TERMINATED); } -int pa_context_is_ready(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_READY; +enum pa_context_state pa_context_get_state(struct pa_context *c) { + assert(c && c->ref >= 1); + return c->state; } int pa_context_errno(struct pa_context *c) { - assert(c); + assert(c && c->ref >= 1); return c->error; } -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { - assert(c); - c->die_callback = cb; - c->die_userdata = userdata; -} - -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - uint32_t channel; - assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) - return; - - c->error = PA_ERROR_KILLED; - stream_dead(s); -} - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s; - struct pa_context *c = userdata; - uint32_t bytes, channel; - assert(pd && command == PA_COMMAND_REQUEST && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - pa_tagstruct_getu32(t, &bytes) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(c->playback_streams, channel))) - return; - - if (s->state != STREAM_READY) - return; - - s->requested_bytes += bytes; - - if (s->requested_bytes && s->write_callback) - s->write_callback(s, s->requested_bytes, s->write_userdata); -} - -static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s && s->state == STREAM_CREATING); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - if (s->create_complete_callback) - s->create_complete_callback(s, 0, s->create_complete_userdata); - - return; - } - - if (pa_tagstruct_getu32(t, &s->channel) < 0 || - ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - s->channel_valid = 1; - pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - - s->state = STREAM_READY; - if (s->create_complete_callback) - s->create_complete_callback(s, 1, s->create_complete_userdata); -} - -static void create_stream(struct pa_stream *s, const char *dev) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s); - - s->state = STREAM_CREATING; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_puts(t, s->name); - pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, s->buffer_attr.maxlength); - if (s->direction == PA_STREAM_PLAYBACK) { - pa_tagstruct_putu32(t, s->buffer_attr.tlength); - pa_tagstruct_putu32(t, s->buffer_attr.prebuf); - pa_tagstruct_putu32(t, s->buffer_attr.minreq); - } else - pa_tagstruct_putu32(t, s->buffer_attr.fragsize); - - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); -} - -static struct pa_stream *internal_stream_new(struct pa_context *c) { - struct pa_stream *s; - - s = pa_xmalloc(sizeof(struct pa_stream)); - s->context = c; - - s->read_callback = NULL; - s->read_userdata = NULL; - s->write_callback = NULL; - s->write_userdata = NULL; - s->die_callback = NULL; - s->die_userdata = NULL; - s->create_complete_callback = NULL; - s->create_complete_userdata = NULL; - s->get_latency_callback = NULL; - s->get_latency_userdata = NULL; - s->finish_sample_callback = NULL; - s->finish_sample_userdata = NULL; - - s->name = NULL; - s->state = STREAM_CREATING; - s->requested_bytes = 0; - s->channel = 0; - s->channel_valid = 0; - s->device_index = (uint32_t) -1; - - memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - - s->next = c->first_stream; - if (s->next) - s->next->previous = s; - s->previous = NULL; - c->first_stream = s; - - return s; -} - -struct pa_stream* pa_stream_new( - struct pa_context *c, - enum pa_stream_direction dir, - const char *dev, - const char *name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, - void (*complete) (struct pa_stream*s, int success, void *userdata), - void *userdata) { - - struct pa_stream *s; - - assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = complete; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = dir; - s->sample_spec = *ss; - if (attr) - s->buffer_attr = *attr; - else { - s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; - s->buffer_attr.tlength = DEFAULT_TLENGTH; - s->buffer_attr.prebuf = DEFAULT_PREBUF; - s->buffer_attr.minreq = DEFAULT_MINREQ; - s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; - } - - create_stream(s, dev); - - return s; -} - -void pa_stream_free(struct pa_stream *s) { - assert(s && s->context); - - if (s->context->pdispatch) - pa_pdispatch_unregister_reply(s->context->pdispatch, s); - - pa_xfree(s->name); - - if (s->channel_valid && s->context->state == CONTEXT_READY) { - struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : - (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); - pa_tagstruct_putu32(t, s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - } - - if (s->channel_valid) - pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - - if (s->next) - s->next->previous = s->previous; - if (s->previous) - s->previous->next = s->next; - else - s->context->first_stream = s->next; - - pa_xfree(s); -} - -void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { - s->write_callback = cb; - s->write_userdata = userdata; -} - -void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { - struct pa_memchunk chunk; - assert(s && s->context && data && length && s->state == STREAM_READY); - - chunk.memblock = pa_memblock_new(length); - assert(chunk.memblock && chunk.memblock->data); - memcpy(chunk.memblock->data, data, length); - chunk.index = 0; - chunk.length = length; - - pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); - pa_memblock_unref(chunk.memblock); - - /*fprintf(stderr, "Sent %u bytes\n", length);*/ - - if (length < s->requested_bytes) - s->requested_bytes -= length; - else - s->requested_bytes = 0; -} - -size_t pa_stream_writable_size(struct pa_stream *s) { - assert(s && s->state == STREAM_READY); - return s->requested_bytes; -} - -void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { - assert(s && cb); - s->read_callback = cb; - s->read_userdata = userdata; -} - -int pa_stream_is_dead(struct pa_stream *s) { - return s->state == STREAM_DEAD; -} - -int pa_stream_is_ready(struct pa_stream*s) { - return s->state == STREAM_READY; -} - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { - assert(s); - s->die_callback = cb; - s->die_userdata = userdata; +void pa_context_set_state_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { + assert(c && c->ref >= 1); + c->state_callback = cb; + c->state_userdata = userdata; } int pa_context_is_pending(struct pa_context *c) { - assert(c); + assert(c && c->ref >= 1); - if (c->state != CONTEXT_READY) + if (c->state != PA_CONTEXT_READY) return 0; + assert(c->pstream && c->pdispatch); return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); } -struct pa_context* pa_stream_get_context(struct pa_stream *p) { - assert(p); - return p->context; -} - -static void set_dispatch_callbacks(struct pa_context *c); +static void set_dispatch_callbacks(struct pa_operation *o); static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { set_dispatch_callbacks(userdata); @@ -794,107 +421,59 @@ static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { set_dispatch_callbacks(userdata); } -static void set_dispatch_callbacks(struct pa_context *c) { - assert(c && c->state == CONTEXT_READY); +static void set_dispatch_callbacks(struct pa_operation *o) { + int done = 1; + assert(o && o->context && o->context->ref >= 1 && o->ref >= 1 && o->context->state == PA_CONTEXT_READY); - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); + pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL); - if (pa_pdispatch_is_pending(c->pdispatch)) { - pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); - return; + if (pa_pdispatch_is_pending(o->context->pdispatch)) { + pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o); + done = 0; } - if (pa_pstream_is_pending(c->pstream)) { - pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); - return; + if (pa_pstream_is_pending(o->context->pstream)) { + pa_pstream_set_drain_callback(o->context->pstream, pstream_drain_callback, o); + done = 0; } - assert(c->drain_complete_callback); - c->drain_complete_callback(c, c->drain_complete_userdata); -} - -int pa_context_drain( - struct pa_context *c, - void (*complete) (struct pa_context*c, void *userdata), - void *userdata) { - - assert(c && c->state == CONTEXT_READY); - - if (complete == NULL) { - c->drain_complete_callback = NULL; - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - return 0; - } - - if (!pa_context_is_pending(c)) - return -1; - - c->drain_complete_callback = complete; - c->drain_complete_userdata = userdata; - - set_dispatch_callbacks(c); - - return 0; -} - -static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; + if (!done) + pa_operation_ref(o); + else { + if (o->callback) { + void (*cb)(struct pa_context *c, void *userdata); + cb = (void*) o->callback; + cb(o->context, o->userdata); } + + pa_operation_done(o); + } - stream_dead(s); - return; - } - - if (s->state != STREAM_READY) - return; - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->drain_complete_callback) { - void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; - s->drain_complete_callback = NULL; - temp(s, s->drain_complete_userdata); - } + pa_operation_unref(o); } +struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct pa_context*c, void *userdata), void *userdata) { + struct pa_operation *o; + assert(c && c->ref >= 1 && c->state == PA_CONTEXT_READY); -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { + if (!pa_context_is_pending(c)) + return NULL; + + o = pa_operation_new(c, NULL); + assert(o); + o->callback = cb; + o->userdata = userdata; + + set_dispatch_callbacks(pa_operation_ref(o)); + + return o; +} + +void pa_context_exit_daemon(struct pa_context *c) { struct pa_tagstruct *t; - uint32_t tag; - assert(s && s->state == STREAM_READY); - - if (!complete) { - s->drain_complete_callback = NULL; - return; - } - - s->drain_complete_callback = complete; - s->drain_complete_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); + assert(c && c->ref >= 1); - pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); -} - -void pa_context_exit(struct pa_context *c) { - struct pa_tagstruct *t; t = pa_tagstruct_new(NULL, 0); assert(t); pa_tagstruct_putu32(t, PA_COMMAND_EXIT); @@ -902,649 +481,46 @@ void pa_context_exit(struct pa_context *c) { pa_pstream_send_tagstruct(c->pstream, t); } -static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - uint32_t total, count; - assert(pd && c); +void pa_context_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_operation *o = userdata; + int success = 1; + assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; - if (c->stat_callback) - c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); - return; + success = 0; + } else if (!pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; } - if (pa_tagstruct_getu32(t, &count) < 0 || - pa_tagstruct_getu32(t, &total) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; + if (o->callback) { + void (*cb)(struct pa_context *c, int success, void *userdata) = o->callback; + cb(o->context, success, o->userdata); } - if (c->stat_callback) - c->stat_callback(c, count, total, c->stat_userdata); +finish: + pa_operation_done(o); + pa_operation_unref(o); } -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { - uint32_t tag; +struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32_t command, void (*internal_callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void (*cb)(), void *userdata) { struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb); - c->stat_callback = cb; - c->stat_userdata = userdata; + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; - if (cb == NULL) - return; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_STAT); + pa_tagstruct_putu32(t, command); pa_tagstruct_putu32(t, tag = c->ctag++); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); -} - -static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - uint32_t latency; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &latency) < 0 || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, latency, s->get_latency_userdata); -} - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - p->get_latency_callback = cb; - p->get_latency_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); -} - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_stream *s; - struct pa_tagstruct *t; - uint32_t tag; - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = cb; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = PA_STREAM_UPLOAD; - s->sample_spec = *ss; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_tagstruct_put_sample_spec(t, ss); - pa_tagstruct_putu32(t, length); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); - - return s; -} - -static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 0, s->finish_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 1, s->finish_sample_userdata); -} - -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(p); - - p->finish_sample_callback = cb; - p->finish_sample_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); -} - -static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 0, c->play_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 1, c->play_sample_userdata); -} - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name && *name && (!dev || *dev)); - - c->play_sample_callback = cb; - c->play_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, volume); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); -} - -static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 0, c->remove_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 1, c->remove_sample_userdata); -} - -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name); - - c->remove_sample_callback = cb; - c->remove_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); -} - -static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_server_info i; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, NULL, c->get_server_info_userdata); - return; - } - - if (pa_tagstruct_gets(t, &i.server_name) < 0 || - pa_tagstruct_gets(t, &i.server_version) < 0 || - pa_tagstruct_gets(t, &i.user_name) < 0 || - pa_tagstruct_gets(t, &i.host_name) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, &i, c->get_server_info_userdata); -} - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_server_info_callback = cb; - c->get_server_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); -} - -static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_sink_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.monitor_source) < 0 || - pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); -} - -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_source_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || - pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); -} - -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { - struct pa_tagstruct *t; - assert(c); - - c->subscribe_callback = cb; - c->subscribe_userdata = userdata; - c->subscribe_mask = m; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); - pa_tagstruct_putu32(t, c->ctag++); - pa_tagstruct_putu32(t, cb ? m : 0); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - enum pa_subscription_event_type e; - uint32_t index; - assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); - - if (pa_tagstruct_getu32(t, &e) < 0 || - pa_tagstruct_getu32(t, &index) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) - c->subscribe_callback(c, e, index, c->subscribe_userdata); -} - -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_client_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.protocol_name) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); -} - - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_module_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.argument) < 0 || - pa_tagstruct_getu32(t, &i.n_used) < 0 || - pa_tagstruct_getu32(t, &i.auto_unload) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); -} - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} - -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_callback, o); + + return pa_operation_ref(o); } diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index a0dd9f9cb..6a1cc8bd8 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibhfoo -#define foopolyplibhfoo +#ifndef foopolyplibcontexthfoo +#define foopolyplibcontexthfoo /* $Id$ */ @@ -22,157 +22,71 @@ USA. ***/ -#include - #include "sample.h" #include "polyplib-def.h" #include "mainloop-api.h" +#include "cdecl.h" +#include "polyplib-operation.h" -#ifdef __cplusplus -//extern "C" { -#endif +/** \file + * Connection contexts */ +PA_C_DECL_BEGIN + +/** The state of a connection context */ +enum pa_context_state { + PA_CONTEXT_UNCONNECTED, /**< The context hasn't been connected yet */ + PA_CONTEXT_CONNECTING, /**< A connection is being established */ + PA_CONTEXT_AUTHORIZING, /**< The client is authorizing itself to the daemon */ + PA_CONTEXT_SETTING_NAME, /**< The client is passing its application name to the daemon */ + PA_CONTEXT_READY, /**< The connection is established, the context is ready to execute operations */ + PA_CONTEXT_FAILED, /**< The connection failed or was disconnected */ + PA_CONTEXT_TERMINATED /**< The connect was terminated cleanly */ +}; + +/** \struct pa_context + * A connection context to a daemon */ struct pa_context; -struct pa_stream; +/** Instantiate a new connection context with an abstract mainloop API + * and an application name */ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); + +/** Decrease the reference counter of the context by one */ void pa_context_unref(struct pa_context *c); + +/** Increase the reference counter of the context by one */ struct pa_context* pa_context_ref(struct pa_context *c); -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); -int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); +/** Set a callback function that is called whenever the context status changes */ +void pa_context_set_state_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); -int pa_context_is_dead(struct pa_context *c); -int pa_context_is_ready(struct pa_context *c); +/** Return the error number of the last failed operation */ int pa_context_errno(struct pa_context *c); +/** Return non-zero if some data is pending to be written to the connection */ int pa_context_is_pending(struct pa_context *c); -struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_unref(struct pa_stream *s); -struct pa_stream *pa_stream_ref(struct pa_stream *s); +/** Return the current context status */ +enum pa_context_state pa_context_get_state(struct pa_context *c); -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); +/** Connect the context to the specified server. If server is NULL, +connect to the default server. This routine may but will not always +return synchronously on error. Use pa_context_set_state_callback() to +be notified when the connection is established */ +int pa_context_connect(struct pa_context *c, const char *server); -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); +/** Terminate the context connection immediately */ +void pa_context_disconnect(struct pa_context *c); -void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); -void pa_stream_write(struct pa_stream *p, const void *data, size_t length); -size_t pa_stream_writable_size(struct pa_stream *p); +/** Drain the context. If there is nothing to drain, the function returns NULL */ +struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct pa_context*c, void *userdata), void *userdata); -void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); +/** Tell the daemon to exit. No operation object is returned as the + * connection is terminated when the daemon quits, thus this operation + * would never complete. */ +void pa_context_exit_daemon(struct pa_context *c); -int pa_stream_is_dead(struct pa_stream *p); -int pa_stream_is_ready(struct pa_stream*p); - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); - -struct pa_context* pa_stream_get_context(struct pa_stream *p); - -uint32_t pa_stream_get_index(struct pa_stream *s); - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -struct pa_sink_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t volume; - uint32_t monitor_source; - const char *monitor_source_name; - uint32_t latency; -}; - -void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); - -struct pa_source_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t monitor_of_sink; - const char *monitor_of_sink_name; -}; - -void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); - -struct pa_server_info { - const char *user_name; - const char *host_name; - const char *server_version; - const char *server_name; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); - -struct pa_module_info { - uint32_t index; - const char*name, *argument; - uint32_t n_used, auto_unload; -}; - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); - -struct pa_client_info { - uint32_t index; - const char *name; - uint32_t owner_module; - const char *protocol_name; -}; - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); - -struct pa_sink_input_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t sink; - struct pa_sample_spec sample_spec; - uint32_t volume; - uint32_t latency; -}; - -void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); - -struct pa_source_output_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t source; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); - -void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -void pa_context_exit(struct pa_context *c); -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); - -#ifdef __cplusplus -} -#endif +PA_C_DECL_END #endif diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index d96c68995..fc19be697 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -23,14 +23,13 @@ ***/ #include - -#ifdef __cplusplus -extern "C" { -#endif - #include "native-common.h" +#include "cdecl.h" + +PA_C_DECL_BEGIN enum pa_stream_direction { + PA_STREAM_NODIRECTION, PA_STREAM_PLAYBACK, PA_STREAM_RECORD, PA_STREAM_UPLOAD @@ -43,9 +42,9 @@ struct pa_buffer_attr { uint32_t minreq; uint32_t fragsize; }; - -#ifdef __cplusplus -} -#endif + +#define PA_INVALID_INDEX ((uint32_t) -1) + +PA_C_DECL_END #endif diff --git a/polyp/polyplib-error.h b/polyp/polyplib-error.h index d76ce6ffa..d7519af4a 100644 --- a/polyp/polyplib-error.h +++ b/polyp/polyplib-error.h @@ -23,15 +23,13 @@ ***/ #include +#include "cdecl.h" -#ifdef __cplusplus -extern "C" { -#endif +PA_C_DECL_BEGIN; +/** Return a human readable error message for the specified numeric error code */ const char* pa_strerror(uint32_t error); -#ifdef __cplusplus -} -#endif - +PA_C_DECL_END; + #endif diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 35001d3d3..0b6b3887c 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -1,3 +1,6 @@ +#ifndef foopolyplibinternalhfoo +#define foopolyplibinternalhfoo + /* $Id$ */ /*** @@ -19,28 +22,16 @@ USA. ***/ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "polyplib.h" -#include "native-common.h" -#include "pdispatch.h" -#include "pstream.h" -#include "dynarray.h" +#include "mainloop-api.h" #include "socket-client.h" -#include "pstream-util.h" -#include "authkey.h" -#include "util.h" -#include "xmalloc.h" +#include "pstream.h" +#include "pdispatch.h" +#include "dynarray.h" + +#include "polyplib-context.h" +#include "polyplib-stream.h" +#include "polyplib-operation.h" +#include "llist.h" #define DEFAULT_MAXLENGTH 204800 #define DEFAULT_TLENGTH 10240 @@ -52,68 +43,41 @@ #define DEFAULT_SERVER "/tmp/polypaudio/native" #define DEFAULT_PORT "4713" +#define ENV_DEFAULT_SINK "POLYP_SINK" +#define ENV_DEFAULT_SOURCE "POLYP_SOURCE" +#define ENV_DEFAULT_SERVER "POLYP_SERVER" + struct pa_context { + int ref; + char *name; struct pa_mainloop_api* mainloop; + struct pa_socket_client *client; struct pa_pstream *pstream; struct pa_pdispatch *pdispatch; + struct pa_dynarray *record_streams, *playback_streams; - struct pa_stream *first_stream; + PA_LLIST_HEAD(struct pa_stream, streams); + PA_LLIST_HEAD(struct pa_operation, operations); + uint32_t ctag; uint32_t error; - enum { - CONTEXT_UNCONNECTED, - CONTEXT_CONNECTING, - CONTEXT_AUTHORIZING, - CONTEXT_SETTING_NAME, - CONTEXT_READY, - CONTEXT_DEAD - } state; - - void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); - void *connect_complete_userdata; - - void (*drain_complete_callback)(struct pa_context*c, void *userdata); - void *drain_complete_userdata; + enum pa_context_state state; - void (*die_callback)(struct pa_context*c, void *userdata); - void *die_userdata; - - void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); - void *stat_userdata; - - void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); - void *play_sample_userdata; + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; - void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); - void *remove_sample_userdata; - - void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); - void *get_server_info_userdata; - - void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); - void *get_sink_info_userdata; - - void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); - void *get_source_info_userdata; + void (*state_callback)(struct pa_context*c, void *userdata); + void *state_userdata; void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); void *subscribe_userdata; - enum pa_subscription_mask subscribe_mask; - - void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); - void *get_client_info_userdata; - - void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); - void *get_module_info_userdata; - - uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; }; struct pa_stream { + int ref; struct pa_context *context; - struct pa_stream *next, *previous; + PA_LLIST_FIELDS(struct pa_stream); char *name; struct pa_buffer_attr buffer_attr; @@ -122,1429 +86,47 @@ struct pa_stream { int channel_valid; uint32_t device_index; enum pa_stream_direction direction; - - enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; uint32_t requested_bytes; + enum pa_stream_state state; + + void (*state_callback)(struct pa_stream*c, void *userdata); + void *state_userdata; void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); void *read_userdata; void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); void *write_userdata; - - void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); - void *create_complete_userdata; - - void (*drain_complete_callback)(struct pa_stream *s, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_stream*c, void *userdata); - void *die_userdata; - - void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); - void *get_latency_userdata; - - void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); - void *finish_sample_userdata; }; -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +struct pa_operation { + int ref; + struct pa_context *context; + struct pa_stream *stream; + PA_LLIST_FIELDS(struct pa_operation); -static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { - [PA_COMMAND_ERROR] = { NULL }, - [PA_COMMAND_REPLY] = { NULL }, - [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_EXIT] = { NULL }, - [PA_COMMAND_REQUEST] = { command_request }, - [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, + enum pa_operation_state state; + void *userdata; + void (*callback)(); }; -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { - struct pa_context *c; - assert(mainloop && name); - - c = pa_xmalloc(sizeof(struct pa_context)); - c->name = pa_xstrdup(name); - c->mainloop = mainloop; - c->client = NULL; - c->pstream = NULL; - c->pdispatch = NULL; - c->playback_streams = pa_dynarray_new(); - assert(c->playback_streams); - c->record_streams = pa_dynarray_new(); - assert(c->record_streams); - c->first_stream = NULL; - c->error = PA_ERROR_OK; - c->state = CONTEXT_UNCONNECTED; - c->ctag = 0; +void pa_command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +void pa_command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +void pa_command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); - c->connect_complete_callback = NULL; - c->connect_complete_userdata = NULL; +struct pa_operation *pa_operation_new(struct pa_context *c, struct pa_stream *s); +void pa_operation_done(struct pa_operation *o); - c->drain_complete_callback = NULL; - c->drain_complete_userdata = NULL; +void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +void pa_stream_disconnect_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +void pa_context_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +void pa_stream_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); - c->die_callback = NULL; - c->die_userdata = NULL; +void pa_context_fail(struct pa_context *c, int error); +void pa_context_set_state(struct pa_context *c, enum pa_context_state st); +int pa_context_handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t); +struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32_t command, void (*internal_callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void (*cb)(), void *userdata); - c->stat_callback = NULL; - c->stat_userdata = NULL; +void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st); - c->play_sample_callback = NULL; - c->play_sample_userdata = NULL; - - c->remove_sample_callback = NULL; - c->remove_sample_userdata = NULL; - - c->get_server_info_callback = NULL; - c->get_server_info_userdata = NULL; - - c->get_sink_info_callback = NULL; - c->get_sink_info_userdata = NULL; - - c->get_source_info_callback = NULL; - c->get_source_info_userdata = NULL; - - c->subscribe_callback = NULL; - c->subscribe_userdata = NULL; - - c->get_client_info_callback = NULL; - c->get_client_info_userdata = NULL; - - c->get_module_info_callback = NULL; - c->get_module_info_userdata = NULL; - - pa_check_for_sigpipe(); - return c; -} - -void pa_context_free(struct pa_context *c) { - assert(c); - - while (c->first_stream) - pa_stream_free(c->first_stream); - - if (c->client) - pa_socket_client_free(c->client); - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - if (c->pstream) - pa_pstream_free(c->pstream); - if (c->record_streams) - pa_dynarray_free(c->record_streams, NULL, NULL); - if (c->playback_streams) - pa_dynarray_free(c->playback_streams, NULL, NULL); - - pa_xfree(c->name); - pa_xfree(c); -} - -static void stream_dead(struct pa_stream *s) { - assert(s); - - if (s->state == STREAM_DEAD) - return; - - if (s->state == STREAM_READY) { - s->state = STREAM_DEAD; - if (s->die_callback) - s->die_callback(s, s->die_userdata); - } else - s->state = STREAM_DEAD; -} - -static void context_dead(struct pa_context *c) { - struct pa_stream *s; - assert(c); - - if (c->state == CONTEXT_DEAD) - return; - - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - c->pdispatch = NULL; - - if (c->pstream) - pa_pstream_free(c->pstream); - c->pstream = NULL; - - if (c->client) - pa_socket_client_free(c->client); - c->client = NULL; - - for (s = c->first_stream; s; s = s->next) - stream_dead(s); - - if (c->state == CONTEXT_READY) { - c->state = CONTEXT_DEAD; - if (c->die_callback) - c->die_callback(c, c->die_userdata); - } else - c->state = CONTEXT_DEAD; -} - -static void pstream_die_callback(struct pa_pstream *p, void *userdata) { - struct pa_context *c = userdata; - assert(p && c); - c->error = PA_ERROR_CONNECTIONTERMINATED; - context_dead(c); -} - -static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { - struct pa_context *c = userdata; - assert(p && packet && c); - - if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - fprintf(stderr, "polyp.c: invalid packet.\n"); - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - } -} - -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - assert(p && chunk && c && chunk->memblock && chunk->memblock->data); - - if (!(s = pa_dynarray_get(c->record_streams, channel))) - return; - - if (s->read_callback) - s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); -} - -static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { - assert(c && t); - - if (command == PA_COMMAND_ERROR) { - if (pa_tagstruct_getu32(t, &c->error) < 0) { - c->error = PA_ERROR_PROTOCOL; - return -1; - } - - return 0; - } - - c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; - return -1; -} - -static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); - - if (command != PA_COMMAND_REPLY) { - handle_error(c, command, t); - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - if (c->state == CONTEXT_AUTHORIZING) { - struct pa_tagstruct *t; - c->state = CONTEXT_SETTING_NAME; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, c->name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - } else { - assert(c->state == CONTEXT_SETTING_NAME); - - c->state = CONTEXT_READY; - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 1, c->connect_complete_userdata); - } - - return; -} - -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { - struct pa_context *c = userdata; - struct pa_tagstruct *t; - uint32_t tag; - assert(client && c && c->state == CONTEXT_CONNECTING); - - pa_socket_client_free(client); - c->client = NULL; - - if (!io) { - c->error = PA_ERROR_CONNECTIONREFUSED; - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - c->pstream = pa_pstream_new(c->mainloop, io); - assert(c->pstream); - pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); - pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); - pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); - - c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); - assert(c->pdispatch); - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_AUTH); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - c->state = CONTEXT_AUTHORIZING; -} - -static struct sockaddr *resolve_server(const char *server, size_t *len) { - struct sockaddr *sa; - struct addrinfo hints, *result = NULL; - char *port; - assert(server && len); - - if ((port = strrchr(server, ':'))) - port++; - if (!port) - port = DEFAULT_PORT; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(server, port, &hints, &result) != 0) - return NULL; - assert(result); - - sa = pa_xmalloc(*len = result->ai_addrlen); - memcpy(sa, result->ai_addr, *len); - - freeaddrinfo(result); - - return sa; -} - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { - assert(c && c->state == CONTEXT_UNCONNECTED); - - if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { - c->error = PA_ERROR_AUTHKEY; - return -1; - } - - if (!server) - if (!(server = getenv("POLYP_SERVER"))) - server = DEFAULT_SERVER; - - assert(!c->client); - - if (*server == '/') { - if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } else { - struct sockaddr* sa; - size_t sa_len; - - if (!(sa = resolve_server(server, &sa_len))) { - c->error = PA_ERROR_INVALIDSERVER; - return -1; - } - - c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); - pa_xfree(sa); - - if (!c->client) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } - - c->connect_complete_callback = complete; - c->connect_complete_userdata = userdata; - - pa_socket_client_set_callback(c->client, on_connection, c); - c->state = CONTEXT_CONNECTING; - - return 0; -} - -int pa_context_is_dead(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_DEAD; -} - -int pa_context_is_ready(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_READY; -} - -int pa_context_errno(struct pa_context *c) { - assert(c); - return c->error; -} - -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { - assert(c); - c->die_callback = cb; - c->die_userdata = userdata; -} - -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - uint32_t channel; - assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) - return; - - c->error = PA_ERROR_KILLED; - stream_dead(s); -} - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s; - struct pa_context *c = userdata; - uint32_t bytes, channel; - assert(pd && command == PA_COMMAND_REQUEST && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - pa_tagstruct_getu32(t, &bytes) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(c->playback_streams, channel))) - return; - - if (s->state != STREAM_READY) - return; - - s->requested_bytes += bytes; - - if (s->requested_bytes && s->write_callback) - s->write_callback(s, s->requested_bytes, s->write_userdata); -} - -static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s && s->state == STREAM_CREATING); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - if (s->create_complete_callback) - s->create_complete_callback(s, 0, s->create_complete_userdata); - - return; - } - - if (pa_tagstruct_getu32(t, &s->channel) < 0 || - ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - s->channel_valid = 1; - pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - - s->state = STREAM_READY; - if (s->create_complete_callback) - s->create_complete_callback(s, 1, s->create_complete_userdata); -} - -static void create_stream(struct pa_stream *s, const char *dev) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s); - - s->state = STREAM_CREATING; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_puts(t, s->name); - pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, s->buffer_attr.maxlength); - if (s->direction == PA_STREAM_PLAYBACK) { - pa_tagstruct_putu32(t, s->buffer_attr.tlength); - pa_tagstruct_putu32(t, s->buffer_attr.prebuf); - pa_tagstruct_putu32(t, s->buffer_attr.minreq); - } else - pa_tagstruct_putu32(t, s->buffer_attr.fragsize); - - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); -} - -static struct pa_stream *internal_stream_new(struct pa_context *c) { - struct pa_stream *s; - - s = pa_xmalloc(sizeof(struct pa_stream)); - s->context = c; - - s->read_callback = NULL; - s->read_userdata = NULL; - s->write_callback = NULL; - s->write_userdata = NULL; - s->die_callback = NULL; - s->die_userdata = NULL; - s->create_complete_callback = NULL; - s->create_complete_userdata = NULL; - s->get_latency_callback = NULL; - s->get_latency_userdata = NULL; - s->finish_sample_callback = NULL; - s->finish_sample_userdata = NULL; - - s->name = NULL; - s->state = STREAM_CREATING; - s->requested_bytes = 0; - s->channel = 0; - s->channel_valid = 0; - s->device_index = (uint32_t) -1; - - memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - - s->next = c->first_stream; - if (s->next) - s->next->previous = s; - s->previous = NULL; - c->first_stream = s; - - return s; -} - -struct pa_stream* pa_stream_new( - struct pa_context *c, - enum pa_stream_direction dir, - const char *dev, - const char *name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, - void (*complete) (struct pa_stream*s, int success, void *userdata), - void *userdata) { - - struct pa_stream *s; - - assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = complete; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = dir; - s->sample_spec = *ss; - if (attr) - s->buffer_attr = *attr; - else { - s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; - s->buffer_attr.tlength = DEFAULT_TLENGTH; - s->buffer_attr.prebuf = DEFAULT_PREBUF; - s->buffer_attr.minreq = DEFAULT_MINREQ; - s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; - } - - create_stream(s, dev); - - return s; -} - -void pa_stream_free(struct pa_stream *s) { - assert(s && s->context); - - if (s->context->pdispatch) - pa_pdispatch_unregister_reply(s->context->pdispatch, s); - - pa_xfree(s->name); - - if (s->channel_valid && s->context->state == CONTEXT_READY) { - struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : - (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); - pa_tagstruct_putu32(t, s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - } - - if (s->channel_valid) - pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - - if (s->next) - s->next->previous = s->previous; - if (s->previous) - s->previous->next = s->next; - else - s->context->first_stream = s->next; - - pa_xfree(s); -} - -void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { - s->write_callback = cb; - s->write_userdata = userdata; -} - -void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { - struct pa_memchunk chunk; - assert(s && s->context && data && length && s->state == STREAM_READY); - - chunk.memblock = pa_memblock_new(length); - assert(chunk.memblock && chunk.memblock->data); - memcpy(chunk.memblock->data, data, length); - chunk.index = 0; - chunk.length = length; - - pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); - pa_memblock_unref(chunk.memblock); - - /*fprintf(stderr, "Sent %u bytes\n", length);*/ - - if (length < s->requested_bytes) - s->requested_bytes -= length; - else - s->requested_bytes = 0; -} - -size_t pa_stream_writable_size(struct pa_stream *s) { - assert(s && s->state == STREAM_READY); - return s->requested_bytes; -} - -void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { - assert(s && cb); - s->read_callback = cb; - s->read_userdata = userdata; -} - -int pa_stream_is_dead(struct pa_stream *s) { - return s->state == STREAM_DEAD; -} - -int pa_stream_is_ready(struct pa_stream*s) { - return s->state == STREAM_READY; -} - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { - assert(s); - s->die_callback = cb; - s->die_userdata = userdata; -} - -int pa_context_is_pending(struct pa_context *c) { - assert(c); - - if (c->state != CONTEXT_READY) - return 0; - - return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); -} - -struct pa_context* pa_stream_get_context(struct pa_stream *p) { - assert(p); - return p->context; -} - -static void set_dispatch_callbacks(struct pa_context *c); - -static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void set_dispatch_callbacks(struct pa_context *c) { - assert(c && c->state == CONTEXT_READY); - - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - - if (pa_pdispatch_is_pending(c->pdispatch)) { - pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); - return; - } - - if (pa_pstream_is_pending(c->pstream)) { - pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); - return; - } - - assert(c->drain_complete_callback); - c->drain_complete_callback(c, c->drain_complete_userdata); -} - -int pa_context_drain( - struct pa_context *c, - void (*complete) (struct pa_context*c, void *userdata), - void *userdata) { - - assert(c && c->state == CONTEXT_READY); - - if (complete == NULL) { - c->drain_complete_callback = NULL; - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - return 0; - } - - if (!pa_context_is_pending(c)) - return -1; - - c->drain_complete_callback = complete; - c->drain_complete_userdata = userdata; - - set_dispatch_callbacks(c); - - return 0; -} - -static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - return; - } - - if (s->state != STREAM_READY) - return; - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->drain_complete_callback) { - void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; - s->drain_complete_callback = NULL; - temp(s, s->drain_complete_userdata); - } -} - - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s && s->state == STREAM_READY); - - if (!complete) { - s->drain_complete_callback = NULL; - return; - } - - s->drain_complete_callback = complete; - s->drain_complete_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); -} - -void pa_context_exit(struct pa_context *c) { - struct pa_tagstruct *t; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_EXIT); - pa_tagstruct_putu32(t, c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - uint32_t total, count; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &count) < 0 || - pa_tagstruct_getu32(t, &total) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, count, total, c->stat_userdata); -} - -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - c->stat_callback = cb; - c->stat_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_STAT); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); -} - -static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - uint32_t latency; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &latency) < 0 || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, latency, s->get_latency_userdata); -} - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - p->get_latency_callback = cb; - p->get_latency_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); -} - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_stream *s; - struct pa_tagstruct *t; - uint32_t tag; - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = cb; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = PA_STREAM_UPLOAD; - s->sample_spec = *ss; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_tagstruct_put_sample_spec(t, ss); - pa_tagstruct_putu32(t, length); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); - - return s; -} - -static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 0, s->finish_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 1, s->finish_sample_userdata); -} - -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(p); - - p->finish_sample_callback = cb; - p->finish_sample_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); -} - -static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 0, c->play_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 1, c->play_sample_userdata); -} - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name && *name && (!dev || *dev)); - - c->play_sample_callback = cb; - c->play_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, volume); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); -} - -static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 0, c->remove_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 1, c->remove_sample_userdata); -} - -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name); - - c->remove_sample_callback = cb; - c->remove_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); -} - -static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_server_info i; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, NULL, c->get_server_info_userdata); - return; - } - - if (pa_tagstruct_gets(t, &i.server_name) < 0 || - pa_tagstruct_gets(t, &i.server_version) < 0 || - pa_tagstruct_gets(t, &i.user_name) < 0 || - pa_tagstruct_gets(t, &i.host_name) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, &i, c->get_server_info_userdata); -} - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_server_info_callback = cb; - c->get_server_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); -} - -static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_sink_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.monitor_source) < 0 || - pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); -} - -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_source_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || - pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); -} - -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { - struct pa_tagstruct *t; - assert(c); - - c->subscribe_callback = cb; - c->subscribe_userdata = userdata; - c->subscribe_mask = m; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); - pa_tagstruct_putu32(t, c->ctag++); - pa_tagstruct_putu32(t, cb ? m : 0); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - enum pa_subscription_event_type e; - uint32_t index; - assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); - - if (pa_tagstruct_getu32(t, &e) < 0 || - pa_tagstruct_getu32(t, &index) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) - c->subscribe_callback(c, e, index, c->subscribe_userdata); -} - -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_client_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.protocol_name) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); -} - - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_module_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.argument) < 0 || - pa_tagstruct_getu32(t, &i.n_used) < 0 || - pa_tagstruct_getu32(t, &i.auto_unload) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); -} - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} - -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} +#endif diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 35001d3d3..345a9cd5f 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -23,1528 +23,421 @@ #include #endif -#include #include -#include -#include -#include -#include -#include -#include "polyplib.h" -#include "native-common.h" -#include "pdispatch.h" -#include "pstream.h" -#include "dynarray.h" -#include "socket-client.h" +#include "polyplib-introspect.h" +#include "polyplib-context.h" +#include "polyplib-internal.h" #include "pstream-util.h" -#include "authkey.h" -#include "util.h" -#include "xmalloc.h" -#define DEFAULT_MAXLENGTH 204800 -#define DEFAULT_TLENGTH 10240 -#define DEFAULT_PREBUF 4096 -#define DEFAULT_MINREQ 1024 -#define DEFAULT_FRAGSIZE 1024 - -#define DEFAULT_TIMEOUT (5*60) -#define DEFAULT_SERVER "/tmp/polypaudio/native" -#define DEFAULT_PORT "4713" - -struct pa_context { - char *name; - struct pa_mainloop_api* mainloop; - struct pa_socket_client *client; - struct pa_pstream *pstream; - struct pa_pdispatch *pdispatch; - struct pa_dynarray *record_streams, *playback_streams; - struct pa_stream *first_stream; - uint32_t ctag; - uint32_t error; - enum { - CONTEXT_UNCONNECTED, - CONTEXT_CONNECTING, - CONTEXT_AUTHORIZING, - CONTEXT_SETTING_NAME, - CONTEXT_READY, - CONTEXT_DEAD - } state; - - void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); - void *connect_complete_userdata; - - void (*drain_complete_callback)(struct pa_context*c, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_context*c, void *userdata); - void *die_userdata; - - void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); - void *stat_userdata; - - void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); - void *play_sample_userdata; - - void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); - void *remove_sample_userdata; - - void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); - void *get_server_info_userdata; - - void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); - void *get_sink_info_userdata; - - void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); - void *get_source_info_userdata; - - void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); - void *subscribe_userdata; - enum pa_subscription_mask subscribe_mask; - - void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); - void *get_client_info_userdata; - - void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); - void *get_module_info_userdata; - - uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; -}; - -struct pa_stream { - struct pa_context *context; - struct pa_stream *next, *previous; - - char *name; - struct pa_buffer_attr buffer_attr; - struct pa_sample_spec sample_spec; - uint32_t channel; - int channel_valid; - uint32_t device_index; - enum pa_stream_direction direction; - - enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; - uint32_t requested_bytes; - - void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); - void *read_userdata; - - void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); - void *write_userdata; - - void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); - void *create_complete_userdata; - - void (*drain_complete_callback)(struct pa_stream *s, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_stream*c, void *userdata); - void *die_userdata; - - void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); - void *get_latency_userdata; - - void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); - void *finish_sample_userdata; -}; - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); - -static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { - [PA_COMMAND_ERROR] = { NULL }, - [PA_COMMAND_REPLY] = { NULL }, - [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_EXIT] = { NULL }, - [PA_COMMAND_REQUEST] = { command_request }, - [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, -}; - -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { - struct pa_context *c; - assert(mainloop && name); - - c = pa_xmalloc(sizeof(struct pa_context)); - c->name = pa_xstrdup(name); - c->mainloop = mainloop; - c->client = NULL; - c->pstream = NULL; - c->pdispatch = NULL; - c->playback_streams = pa_dynarray_new(); - assert(c->playback_streams); - c->record_streams = pa_dynarray_new(); - assert(c->record_streams); - c->first_stream = NULL; - c->error = PA_ERROR_OK; - c->state = CONTEXT_UNCONNECTED; - c->ctag = 0; - - c->connect_complete_callback = NULL; - c->connect_complete_userdata = NULL; - - c->drain_complete_callback = NULL; - c->drain_complete_userdata = NULL; - - c->die_callback = NULL; - c->die_userdata = NULL; - - c->stat_callback = NULL; - c->stat_userdata = NULL; - - c->play_sample_callback = NULL; - c->play_sample_userdata = NULL; - - c->remove_sample_callback = NULL; - c->remove_sample_userdata = NULL; - - c->get_server_info_callback = NULL; - c->get_server_info_userdata = NULL; - - c->get_sink_info_callback = NULL; - c->get_sink_info_userdata = NULL; - - c->get_source_info_callback = NULL; - c->get_source_info_userdata = NULL; - - c->subscribe_callback = NULL; - c->subscribe_userdata = NULL; - - c->get_client_info_callback = NULL; - c->get_client_info_userdata = NULL; - - c->get_module_info_callback = NULL; - c->get_module_info_userdata = NULL; - - pa_check_for_sigpipe(); - return c; -} - -void pa_context_free(struct pa_context *c) { - assert(c); - - while (c->first_stream) - pa_stream_free(c->first_stream); - - if (c->client) - pa_socket_client_free(c->client); - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - if (c->pstream) - pa_pstream_free(c->pstream); - if (c->record_streams) - pa_dynarray_free(c->record_streams, NULL, NULL); - if (c->playback_streams) - pa_dynarray_free(c->playback_streams, NULL, NULL); - - pa_xfree(c->name); - pa_xfree(c); -} - -static void stream_dead(struct pa_stream *s) { - assert(s); - - if (s->state == STREAM_DEAD) - return; - - if (s->state == STREAM_READY) { - s->state = STREAM_DEAD; - if (s->die_callback) - s->die_callback(s, s->die_userdata); - } else - s->state = STREAM_DEAD; -} - -static void context_dead(struct pa_context *c) { - struct pa_stream *s; - assert(c); - - if (c->state == CONTEXT_DEAD) - return; - - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - c->pdispatch = NULL; - - if (c->pstream) - pa_pstream_free(c->pstream); - c->pstream = NULL; - - if (c->client) - pa_socket_client_free(c->client); - c->client = NULL; - - for (s = c->first_stream; s; s = s->next) - stream_dead(s); - - if (c->state == CONTEXT_READY) { - c->state = CONTEXT_DEAD; - if (c->die_callback) - c->die_callback(c, c->die_userdata); - } else - c->state = CONTEXT_DEAD; -} - -static void pstream_die_callback(struct pa_pstream *p, void *userdata) { - struct pa_context *c = userdata; - assert(p && c); - c->error = PA_ERROR_CONNECTIONTERMINATED; - context_dead(c); -} - -static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { - struct pa_context *c = userdata; - assert(p && packet && c); - - if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - fprintf(stderr, "polyp.c: invalid packet.\n"); - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - } -} - -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - assert(p && chunk && c && chunk->memblock && chunk->memblock->data); - - if (!(s = pa_dynarray_get(c->record_streams, channel))) - return; - - if (s->read_callback) - s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); -} - -static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { - assert(c && t); - - if (command == PA_COMMAND_ERROR) { - if (pa_tagstruct_getu32(t, &c->error) < 0) { - c->error = PA_ERROR_PROTOCOL; - return -1; - } - - return 0; - } - - c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; - return -1; -} - -static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); - - if (command != PA_COMMAND_REPLY) { - handle_error(c, command, t); - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - if (c->state == CONTEXT_AUTHORIZING) { - struct pa_tagstruct *t; - c->state = CONTEXT_SETTING_NAME; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, c->name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - } else { - assert(c->state == CONTEXT_SETTING_NAME); - - c->state = CONTEXT_READY; - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 1, c->connect_complete_userdata); - } - - return; -} - -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { - struct pa_context *c = userdata; - struct pa_tagstruct *t; - uint32_t tag; - assert(client && c && c->state == CONTEXT_CONNECTING); - - pa_socket_client_free(client); - c->client = NULL; - - if (!io) { - c->error = PA_ERROR_CONNECTIONREFUSED; - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - c->pstream = pa_pstream_new(c->mainloop, io); - assert(c->pstream); - pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); - pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); - pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); - - c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); - assert(c->pdispatch); - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_AUTH); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - c->state = CONTEXT_AUTHORIZING; -} - -static struct sockaddr *resolve_server(const char *server, size_t *len) { - struct sockaddr *sa; - struct addrinfo hints, *result = NULL; - char *port; - assert(server && len); - - if ((port = strrchr(server, ':'))) - port++; - if (!port) - port = DEFAULT_PORT; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(server, port, &hints, &result) != 0) - return NULL; - assert(result); - - sa = pa_xmalloc(*len = result->ai_addrlen); - memcpy(sa, result->ai_addr, *len); - - freeaddrinfo(result); - - return sa; -} - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { - assert(c && c->state == CONTEXT_UNCONNECTED); - - if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { - c->error = PA_ERROR_AUTHKEY; - return -1; - } - - if (!server) - if (!(server = getenv("POLYP_SERVER"))) - server = DEFAULT_SERVER; - - assert(!c->client); - - if (*server == '/') { - if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } else { - struct sockaddr* sa; - size_t sa_len; - - if (!(sa = resolve_server(server, &sa_len))) { - c->error = PA_ERROR_INVALIDSERVER; - return -1; - } - - c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); - pa_xfree(sa); - - if (!c->client) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } - - c->connect_complete_callback = complete; - c->connect_complete_userdata = userdata; - - pa_socket_client_set_callback(c->client, on_connection, c); - c->state = CONTEXT_CONNECTING; - - return 0; -} - -int pa_context_is_dead(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_DEAD; -} - -int pa_context_is_ready(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_READY; -} - -int pa_context_errno(struct pa_context *c) { - assert(c); - return c->error; -} - -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { - assert(c); - c->die_callback = cb; - c->die_userdata = userdata; -} - -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - uint32_t channel; - assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) - return; - - c->error = PA_ERROR_KILLED; - stream_dead(s); -} - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s; - struct pa_context *c = userdata; - uint32_t bytes, channel; - assert(pd && command == PA_COMMAND_REQUEST && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - pa_tagstruct_getu32(t, &bytes) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(c->playback_streams, channel))) - return; - - if (s->state != STREAM_READY) - return; - - s->requested_bytes += bytes; - - if (s->requested_bytes && s->write_callback) - s->write_callback(s, s->requested_bytes, s->write_userdata); -} - -static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s && s->state == STREAM_CREATING); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - if (s->create_complete_callback) - s->create_complete_callback(s, 0, s->create_complete_userdata); - - return; - } - - if (pa_tagstruct_getu32(t, &s->channel) < 0 || - ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - s->channel_valid = 1; - pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - - s->state = STREAM_READY; - if (s->create_complete_callback) - s->create_complete_callback(s, 1, s->create_complete_userdata); -} - -static void create_stream(struct pa_stream *s, const char *dev) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s); - - s->state = STREAM_CREATING; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_puts(t, s->name); - pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, s->buffer_attr.maxlength); - if (s->direction == PA_STREAM_PLAYBACK) { - pa_tagstruct_putu32(t, s->buffer_attr.tlength); - pa_tagstruct_putu32(t, s->buffer_attr.prebuf); - pa_tagstruct_putu32(t, s->buffer_attr.minreq); - } else - pa_tagstruct_putu32(t, s->buffer_attr.fragsize); - - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); -} - -static struct pa_stream *internal_stream_new(struct pa_context *c) { - struct pa_stream *s; - - s = pa_xmalloc(sizeof(struct pa_stream)); - s->context = c; - - s->read_callback = NULL; - s->read_userdata = NULL; - s->write_callback = NULL; - s->write_userdata = NULL; - s->die_callback = NULL; - s->die_userdata = NULL; - s->create_complete_callback = NULL; - s->create_complete_userdata = NULL; - s->get_latency_callback = NULL; - s->get_latency_userdata = NULL; - s->finish_sample_callback = NULL; - s->finish_sample_userdata = NULL; - - s->name = NULL; - s->state = STREAM_CREATING; - s->requested_bytes = 0; - s->channel = 0; - s->channel_valid = 0; - s->device_index = (uint32_t) -1; - - memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - - s->next = c->first_stream; - if (s->next) - s->next->previous = s; - s->previous = NULL; - c->first_stream = s; - - return s; -} - -struct pa_stream* pa_stream_new( - struct pa_context *c, - enum pa_stream_direction dir, - const char *dev, - const char *name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, - void (*complete) (struct pa_stream*s, int success, void *userdata), - void *userdata) { - - struct pa_stream *s; - - assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = complete; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = dir; - s->sample_spec = *ss; - if (attr) - s->buffer_attr = *attr; - else { - s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; - s->buffer_attr.tlength = DEFAULT_TLENGTH; - s->buffer_attr.prebuf = DEFAULT_PREBUF; - s->buffer_attr.minreq = DEFAULT_MINREQ; - s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; - } - - create_stream(s, dev); - - return s; -} - -void pa_stream_free(struct pa_stream *s) { - assert(s && s->context); - - if (s->context->pdispatch) - pa_pdispatch_unregister_reply(s->context->pdispatch, s); - - pa_xfree(s->name); - - if (s->channel_valid && s->context->state == CONTEXT_READY) { - struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : - (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); - pa_tagstruct_putu32(t, s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - } - - if (s->channel_valid) - pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - - if (s->next) - s->next->previous = s->previous; - if (s->previous) - s->previous->next = s->next; - else - s->context->first_stream = s->next; - - pa_xfree(s); -} - -void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { - s->write_callback = cb; - s->write_userdata = userdata; -} - -void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { - struct pa_memchunk chunk; - assert(s && s->context && data && length && s->state == STREAM_READY); - - chunk.memblock = pa_memblock_new(length); - assert(chunk.memblock && chunk.memblock->data); - memcpy(chunk.memblock->data, data, length); - chunk.index = 0; - chunk.length = length; - - pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); - pa_memblock_unref(chunk.memblock); - - /*fprintf(stderr, "Sent %u bytes\n", length);*/ - - if (length < s->requested_bytes) - s->requested_bytes -= length; - else - s->requested_bytes = 0; -} - -size_t pa_stream_writable_size(struct pa_stream *s) { - assert(s && s->state == STREAM_READY); - return s->requested_bytes; -} - -void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { - assert(s && cb); - s->read_callback = cb; - s->read_userdata = userdata; -} - -int pa_stream_is_dead(struct pa_stream *s) { - return s->state == STREAM_DEAD; -} - -int pa_stream_is_ready(struct pa_stream*s) { - return s->state == STREAM_READY; -} - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { - assert(s); - s->die_callback = cb; - s->die_userdata = userdata; -} - -int pa_context_is_pending(struct pa_context *c) { - assert(c); - - if (c->state != CONTEXT_READY) - return 0; - - return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); -} - -struct pa_context* pa_stream_get_context(struct pa_stream *p) { - assert(p); - return p->context; -} - -static void set_dispatch_callbacks(struct pa_context *c); - -static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void set_dispatch_callbacks(struct pa_context *c) { - assert(c && c->state == CONTEXT_READY); - - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - - if (pa_pdispatch_is_pending(c->pdispatch)) { - pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); - return; - } - - if (pa_pstream_is_pending(c->pstream)) { - pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); - return; - } - - assert(c->drain_complete_callback); - c->drain_complete_callback(c, c->drain_complete_userdata); -} - -int pa_context_drain( - struct pa_context *c, - void (*complete) (struct pa_context*c, void *userdata), - void *userdata) { - - assert(c && c->state == CONTEXT_READY); - - if (complete == NULL) { - c->drain_complete_callback = NULL; - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - return 0; - } - - if (!pa_context_is_pending(c)) - return -1; - - c->drain_complete_callback = complete; - c->drain_complete_userdata = userdata; - - set_dispatch_callbacks(c); - - return 0; -} - -static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - return; - } - - if (s->state != STREAM_READY) - return; - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->drain_complete_callback) { - void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; - s->drain_complete_callback = NULL; - temp(s, s->drain_complete_userdata); - } -} - - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s && s->state == STREAM_READY); - - if (!complete) { - s->drain_complete_callback = NULL; - return; - } - - s->drain_complete_callback = complete; - s->drain_complete_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); -} - -void pa_context_exit(struct pa_context *c) { - struct pa_tagstruct *t; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_EXIT); - pa_tagstruct_putu32(t, c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); -} +/*** Statistics ***/ static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - uint32_t total, count; - assert(pd && c); + struct pa_operation *o = userdata; + struct pa_stat_info i, *p = &i; + assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; - if (c->stat_callback) - c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); - return; + p = NULL; + } else if (pa_tagstruct_getu32(t, &i.memblock_count) < 0 || + pa_tagstruct_getu32(t, &i.memblock_total) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; } - if (pa_tagstruct_getu32(t, &count) < 0 || - pa_tagstruct_getu32(t, &total) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_stat_info*i, void *userdata) = o->callback; + cb(o->context, p, o->userdata); } - if (c->stat_callback) - c->stat_callback(c, count, total, c->stat_userdata); +finish: + pa_operation_done(o); + pa_operation_unref(o); } -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - c->stat_callback = cb; - c->stat_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_STAT); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); +struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info*i, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, cb, userdata); } -static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - uint32_t latency; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &latency) < 0 || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, latency, s->get_latency_userdata); -} - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - p->get_latency_callback = cb; - p->get_latency_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); -} - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_stream *s; - struct pa_tagstruct *t; - uint32_t tag; - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = cb; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = PA_STREAM_UPLOAD; - s->sample_spec = *ss; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_tagstruct_put_sample_spec(t, ss); - pa_tagstruct_putu32(t, length); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); - - return s; -} - -static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 0, s->finish_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 1, s->finish_sample_userdata); -} - -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(p); - - p->finish_sample_callback = cb; - p->finish_sample_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); -} - -static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 0, c->play_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 1, c->play_sample_userdata); -} - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name && *name && (!dev || *dev)); - - c->play_sample_callback = cb; - c->play_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, volume); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); -} - -static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 0, c->remove_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 1, c->remove_sample_userdata); -} - -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name); - - c->remove_sample_callback = cb; - c->remove_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); -} +/*** Server Info ***/ static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_server_info i; - assert(pd && c); + struct pa_operation *o = userdata; + struct pa_server_info i, *p = &i; + assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; - if (c->get_server_info_callback) - c->get_server_info_callback(c, NULL, c->get_server_info_userdata); - return; + p = NULL; + } else if (pa_tagstruct_gets(t, &i.server_name) < 0 || + pa_tagstruct_gets(t, &i.server_version) < 0 || + pa_tagstruct_gets(t, &i.user_name) < 0 || + pa_tagstruct_gets(t, &i.host_name) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; } - - if (pa_tagstruct_gets(t, &i.server_name) < 0 || - pa_tagstruct_gets(t, &i.server_version) < 0 || - pa_tagstruct_gets(t, &i.user_name) < 0 || - pa_tagstruct_gets(t, &i.host_name) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, &i, c->get_server_info_userdata); -} - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_server_info_callback = cb; - c->get_server_info_userdata = userdata; - - if (!cb) - return; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_server_info*i, void *userdata) = o->callback; + cb(o->context, p, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); } +struct pa_operation* pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, cb, userdata); +} + +/*** Sink Info ***/ + static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); + struct pa_operation *o = userdata; + int eof = 1; + assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_sink_info i; + eof = -1; + } else { - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.monitor_source) < 0 || - pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; + while (!pa_tagstruct_eof(t)) { + struct pa_sink_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.monitor_source) < 0 || + pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || + pa_tagstruct_getu32(t, &i.latency) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback; + cb(o->context, &i, 0, o->userdata); + } } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); -} - -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); - return; + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback; + cb(o->context, NULL, eof, o->userdata); } - while (!pa_tagstruct_eof(t)) { - struct pa_source_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || - pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); +finish: + pa_operation_done(o); + pa_operation_unref(o); } -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { +struct pa_operation* pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, cb, userdata); +} + +struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { struct pa_tagstruct *t; + struct pa_operation *o; uint32_t tag; - assert(c); + assert(c && cb); - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { - struct pa_tagstruct *t; - assert(c); - - c->subscribe_callback = cb; - c->subscribe_userdata = userdata; - c->subscribe_mask = m; + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); - pa_tagstruct_putu32(t, c->ctag++); - pa_tagstruct_putu32(t, cb ? m : 0); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - enum pa_subscription_event_type e; - uint32_t index; - assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); - - if (pa_tagstruct_getu32(t, &e) < 0 || - pa_tagstruct_getu32(t, &index) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) - c->subscribe_callback(c, e, index, c->subscribe_userdata); -} - -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, index); pa_tagstruct_puts(t, ""); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o); + + return pa_operation_ref(o); } -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); +/*** Source info ***/ - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; +static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_operation *o = userdata; + int eof = 1; + assert(pd && o && o->context && o->ref >= 1); - if (!cb) - return; + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; + + eof = -1; + } else { + + while (!pa_tagstruct_eof(t)) { + struct pa_source_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || + pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback; + cb(o->context, &i, 0, o->userdata); + } + } + } + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback; + cb(o->context, NULL, eof, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +struct pa_operation* pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, cb, userdata); +} + +struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, index); pa_tagstruct_puts(t, ""); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o); + + return pa_operation_ref(o); } +/*** Client info ***/ + static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); + struct pa_operation *o = userdata; + int eof = 1; + assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_client_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.protocol_name) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } + eof = -1; + } else { - if (c->get_client_info_callback) - c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); + while (!pa_tagstruct_eof(t)) { + struct pa_client_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.protocol_name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback; + cb(o->context, &i, 0, o->userdata); + } + } + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback; + cb(o->context, NULL, eof, o->userdata); } - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); +finish: + pa_operation_done(o); + pa_operation_unref(o); } - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { +struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { struct pa_tagstruct *t; + struct pa_operation *o; uint32_t tag; - assert(c); + assert(c && cb); - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; - if (!cb) - return; - t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, o); + + return pa_operation_ref(o); } -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +struct pa_operation* pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, cb, userdata); } +/*** Module info ***/ + static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); + struct pa_operation *o = userdata; + int eof = 1; + assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_module_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.argument) < 0 || - pa_tagstruct_getu32(t, &i.n_used) < 0 || - pa_tagstruct_getu32(t, &i.auto_unload) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } + eof = -1; + } else { - if (c->get_module_info_callback) - c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); + while (!pa_tagstruct_eof(t)) { + struct pa_module_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0 || + pa_tagstruct_getu32(t, &i.n_used) < 0 || + pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback; + cb(o->context, &i, 0, o->userdata); + } + } + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback; + cb(o->context, NULL, eof, o->userdata); } - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); +finish: + pa_operation_done(o); + pa_operation_unref(o); } -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { +struct pa_operation* pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { struct pa_tagstruct *t; + struct pa_operation *o; uint32_t tag; - assert(c); + assert(c && cb); - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; - if (!cb) - return; - t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, index); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, o); + + return pa_operation_ref(o); } -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { +struct pa_operation* pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, cb, userdata); +} + +/*** Volume manipulation ***/ + +struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_operation *o; struct pa_tagstruct *t; uint32_t tag; - assert(c); + assert(c && index != PA_INVALID_INDEX); - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; - if (!cb) - return; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME); pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_tagstruct_putu32(t, volume); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_operation *o; + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, name); + pa_tagstruct_putu32(t, volume); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_operation *o; + struct pa_tagstruct *t; + uint32_t tag; + assert(c && index != PA_INVALID_INDEX); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, volume); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); } diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index a0dd9f9cb..bca752e2b 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibhfoo -#define foopolyplibhfoo +#ifndef foopolyplibintrospecthfoo +#define foopolyplibintrospecthfoo /* $Id$ */ @@ -22,61 +22,13 @@ USA. ***/ -#include +#include -#include "sample.h" -#include "polyplib-def.h" -#include "mainloop-api.h" +#include "polyplib-operation.h" +#include "polyplib-context.h" +#include "cdecl.h" -#ifdef __cplusplus -//extern "C" { -#endif - -struct pa_context; -struct pa_stream; - -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); -void pa_context_unref(struct pa_context *c); -struct pa_context* pa_context_ref(struct pa_context *c); - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); -int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); - -int pa_context_is_dead(struct pa_context *c); -int pa_context_is_ready(struct pa_context *c); -int pa_context_errno(struct pa_context *c); - -int pa_context_is_pending(struct pa_context *c); - -struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_unref(struct pa_stream *s); -struct pa_stream *pa_stream_ref(struct pa_stream *s); - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); - -void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); -void pa_stream_write(struct pa_stream *p, const void *data, size_t length); -size_t pa_stream_writable_size(struct pa_stream *p); - -void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); - -int pa_stream_is_dead(struct pa_stream *p); -int pa_stream_is_ready(struct pa_stream*p); - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); - -struct pa_context* pa_stream_get_context(struct pa_stream *p); - -uint32_t pa_stream_get_index(struct pa_stream *s); - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +PA_C_DECL_BEGIN struct pa_sink_info { const char *name; @@ -90,9 +42,9 @@ struct pa_sink_info { uint32_t latency; }; -void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); struct pa_source_info { const char *name; @@ -104,9 +56,9 @@ struct pa_source_info { const char *monitor_of_sink_name; }; -void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); struct pa_server_info { const char *user_name; @@ -116,7 +68,7 @@ struct pa_server_info { struct pa_sample_spec sample_spec; }; -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); +struct pa_operation* pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); struct pa_module_info { uint32_t index; @@ -124,8 +76,8 @@ struct pa_module_info { uint32_t n_used, auto_unload; }; -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); struct pa_client_info { uint32_t index; @@ -134,8 +86,8 @@ struct pa_client_info { const char *protocol_name; }; -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); struct pa_sink_input_info { uint32_t index; @@ -148,8 +100,8 @@ struct pa_sink_input_info { uint32_t latency; }; -void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); struct pa_source_output_info { uint32_t index; @@ -160,19 +112,20 @@ struct pa_source_output_info { struct pa_sample_spec sample_spec; }; -void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); -void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_exit(struct pa_context *c); -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); +struct pa_stat_info { + uint32_t memblock_count; + uint32_t memblock_total; +}; -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); +struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info *i, void *userdata), void *userdata); -#ifdef __cplusplus -} -#endif +PA_C_DECL_END #endif diff --git a/polyp/polyplib-operation.c b/polyp/polyplib-operation.c new file mode 100644 index 000000000..994ac016a --- /dev/null +++ b/polyp/polyplib-operation.c @@ -0,0 +1,78 @@ +#include + +#include "xmalloc.h" +#include "polyplib-internal.h" +#include "polyplib-operation.h" + +struct pa_operation *pa_operation_new(struct pa_context *c, struct pa_stream *s) { + struct pa_operation *o; + assert(c); + + o = pa_xmalloc(sizeof(struct pa_operation)); + o->ref = 1; + o->context = pa_context_ref(c); + o->stream = s ? pa_stream_ref(s) : NULL; + + o->state = PA_OPERATION_RUNNING; + o->userdata = NULL; + o->callback = NULL; + + PA_LLIST_PREPEND(struct pa_operation, o->context->operations, o); + return pa_operation_ref(o); +} + +struct pa_operation *pa_operation_ref(struct pa_operation *o) { + assert(o && o->ref >= 1); + o->ref++; + return o; +} + +void pa_operation_unref(struct pa_operation *o) { + assert(o && o->ref >= 1); + + if ((--(o->ref)) == 0) { + assert(!o->context); + assert(!o->stream); + free(o); + } +} + +static void operation_set_state(struct pa_operation *o, enum pa_operation_state st) { + assert(o && o->ref >= 1); + + if (st == o->state) + return; + + if (!o->context) + return; + + o->state = st; + + if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) { + PA_LLIST_REMOVE(struct pa_operation, o->context->operations, o); + pa_context_unref(o->context); + if (o->stream) + pa_stream_unref(o->stream); + o->context = NULL; + o->stream = NULL; + o->callback = NULL; + o->userdata = NULL; + + pa_operation_unref(o); + } +} + +void pa_operation_cancel(struct pa_operation *o) { + assert(o && o->ref >= 1); + operation_set_state(o, PA_OPERATION_CANCELED); +} + +void pa_operation_done(struct pa_operation *o) { + assert(o && o->ref >= 1); + operation_set_state(o, PA_OPERATION_DONE); +} + +enum pa_operation_state pa_operation_get_state(struct pa_operation *o) { + assert(o && o->ref >= 1); + return o->state; +} diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h new file mode 100644 index 000000000..7d0adc260 --- /dev/null +++ b/polyp/polyplib-operation.h @@ -0,0 +1,56 @@ +#ifndef foopolypliboperationhfoo +#define foopolypliboperationhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "cdecl.h" + +/** \file + * Asynchronous operations */ + +PA_C_DECL_BEGIN + +enum pa_operation_state { + PA_OPERATION_RUNNING, /**< The operation is still running */ + PA_OPERATION_DONE, /**< The operation has been completed */ + PA_OPERATION_CANCELED, /**< The operation has been canceled */ +}; + +/** \struct pa_operation + * An asynchronous operation object */ +struct pa_operation; + +/** Increase the reference count by one */ +struct pa_operation *pa_operation_ref(struct pa_operation *o); + +/** Decrease the reference count by one */ +void pa_operation_unref(struct pa_operation *o); + +/** Cancel the operation. Beware! This will not necessarily cancel the execution of the operation on the server side. */ +void pa_operation_cancel(struct pa_operation *o); + +/** Return the current status of the operation */ +enum pa_operation_state pa_operation_get_state(struct pa_operation *o); + +PA_C_DECL_END + +#endif diff --git a/polyp/polyplib-sample.c b/polyp/polyplib-sample.c deleted file mode 100644 index 35001d3d3..000000000 --- a/polyp/polyplib-sample.c +++ /dev/null @@ -1,1550 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of polypaudio. - - polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - polypaudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "polyplib.h" -#include "native-common.h" -#include "pdispatch.h" -#include "pstream.h" -#include "dynarray.h" -#include "socket-client.h" -#include "pstream-util.h" -#include "authkey.h" -#include "util.h" -#include "xmalloc.h" - -#define DEFAULT_MAXLENGTH 204800 -#define DEFAULT_TLENGTH 10240 -#define DEFAULT_PREBUF 4096 -#define DEFAULT_MINREQ 1024 -#define DEFAULT_FRAGSIZE 1024 - -#define DEFAULT_TIMEOUT (5*60) -#define DEFAULT_SERVER "/tmp/polypaudio/native" -#define DEFAULT_PORT "4713" - -struct pa_context { - char *name; - struct pa_mainloop_api* mainloop; - struct pa_socket_client *client; - struct pa_pstream *pstream; - struct pa_pdispatch *pdispatch; - struct pa_dynarray *record_streams, *playback_streams; - struct pa_stream *first_stream; - uint32_t ctag; - uint32_t error; - enum { - CONTEXT_UNCONNECTED, - CONTEXT_CONNECTING, - CONTEXT_AUTHORIZING, - CONTEXT_SETTING_NAME, - CONTEXT_READY, - CONTEXT_DEAD - } state; - - void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); - void *connect_complete_userdata; - - void (*drain_complete_callback)(struct pa_context*c, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_context*c, void *userdata); - void *die_userdata; - - void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); - void *stat_userdata; - - void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); - void *play_sample_userdata; - - void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); - void *remove_sample_userdata; - - void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); - void *get_server_info_userdata; - - void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); - void *get_sink_info_userdata; - - void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); - void *get_source_info_userdata; - - void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); - void *subscribe_userdata; - enum pa_subscription_mask subscribe_mask; - - void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); - void *get_client_info_userdata; - - void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); - void *get_module_info_userdata; - - uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; -}; - -struct pa_stream { - struct pa_context *context; - struct pa_stream *next, *previous; - - char *name; - struct pa_buffer_attr buffer_attr; - struct pa_sample_spec sample_spec; - uint32_t channel; - int channel_valid; - uint32_t device_index; - enum pa_stream_direction direction; - - enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; - uint32_t requested_bytes; - - void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); - void *read_userdata; - - void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); - void *write_userdata; - - void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); - void *create_complete_userdata; - - void (*drain_complete_callback)(struct pa_stream *s, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_stream*c, void *userdata); - void *die_userdata; - - void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); - void *get_latency_userdata; - - void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); - void *finish_sample_userdata; -}; - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); - -static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { - [PA_COMMAND_ERROR] = { NULL }, - [PA_COMMAND_REPLY] = { NULL }, - [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_EXIT] = { NULL }, - [PA_COMMAND_REQUEST] = { command_request }, - [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, -}; - -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { - struct pa_context *c; - assert(mainloop && name); - - c = pa_xmalloc(sizeof(struct pa_context)); - c->name = pa_xstrdup(name); - c->mainloop = mainloop; - c->client = NULL; - c->pstream = NULL; - c->pdispatch = NULL; - c->playback_streams = pa_dynarray_new(); - assert(c->playback_streams); - c->record_streams = pa_dynarray_new(); - assert(c->record_streams); - c->first_stream = NULL; - c->error = PA_ERROR_OK; - c->state = CONTEXT_UNCONNECTED; - c->ctag = 0; - - c->connect_complete_callback = NULL; - c->connect_complete_userdata = NULL; - - c->drain_complete_callback = NULL; - c->drain_complete_userdata = NULL; - - c->die_callback = NULL; - c->die_userdata = NULL; - - c->stat_callback = NULL; - c->stat_userdata = NULL; - - c->play_sample_callback = NULL; - c->play_sample_userdata = NULL; - - c->remove_sample_callback = NULL; - c->remove_sample_userdata = NULL; - - c->get_server_info_callback = NULL; - c->get_server_info_userdata = NULL; - - c->get_sink_info_callback = NULL; - c->get_sink_info_userdata = NULL; - - c->get_source_info_callback = NULL; - c->get_source_info_userdata = NULL; - - c->subscribe_callback = NULL; - c->subscribe_userdata = NULL; - - c->get_client_info_callback = NULL; - c->get_client_info_userdata = NULL; - - c->get_module_info_callback = NULL; - c->get_module_info_userdata = NULL; - - pa_check_for_sigpipe(); - return c; -} - -void pa_context_free(struct pa_context *c) { - assert(c); - - while (c->first_stream) - pa_stream_free(c->first_stream); - - if (c->client) - pa_socket_client_free(c->client); - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - if (c->pstream) - pa_pstream_free(c->pstream); - if (c->record_streams) - pa_dynarray_free(c->record_streams, NULL, NULL); - if (c->playback_streams) - pa_dynarray_free(c->playback_streams, NULL, NULL); - - pa_xfree(c->name); - pa_xfree(c); -} - -static void stream_dead(struct pa_stream *s) { - assert(s); - - if (s->state == STREAM_DEAD) - return; - - if (s->state == STREAM_READY) { - s->state = STREAM_DEAD; - if (s->die_callback) - s->die_callback(s, s->die_userdata); - } else - s->state = STREAM_DEAD; -} - -static void context_dead(struct pa_context *c) { - struct pa_stream *s; - assert(c); - - if (c->state == CONTEXT_DEAD) - return; - - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - c->pdispatch = NULL; - - if (c->pstream) - pa_pstream_free(c->pstream); - c->pstream = NULL; - - if (c->client) - pa_socket_client_free(c->client); - c->client = NULL; - - for (s = c->first_stream; s; s = s->next) - stream_dead(s); - - if (c->state == CONTEXT_READY) { - c->state = CONTEXT_DEAD; - if (c->die_callback) - c->die_callback(c, c->die_userdata); - } else - c->state = CONTEXT_DEAD; -} - -static void pstream_die_callback(struct pa_pstream *p, void *userdata) { - struct pa_context *c = userdata; - assert(p && c); - c->error = PA_ERROR_CONNECTIONTERMINATED; - context_dead(c); -} - -static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { - struct pa_context *c = userdata; - assert(p && packet && c); - - if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - fprintf(stderr, "polyp.c: invalid packet.\n"); - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - } -} - -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - assert(p && chunk && c && chunk->memblock && chunk->memblock->data); - - if (!(s = pa_dynarray_get(c->record_streams, channel))) - return; - - if (s->read_callback) - s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); -} - -static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { - assert(c && t); - - if (command == PA_COMMAND_ERROR) { - if (pa_tagstruct_getu32(t, &c->error) < 0) { - c->error = PA_ERROR_PROTOCOL; - return -1; - } - - return 0; - } - - c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; - return -1; -} - -static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); - - if (command != PA_COMMAND_REPLY) { - handle_error(c, command, t); - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - if (c->state == CONTEXT_AUTHORIZING) { - struct pa_tagstruct *t; - c->state = CONTEXT_SETTING_NAME; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, c->name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - } else { - assert(c->state == CONTEXT_SETTING_NAME); - - c->state = CONTEXT_READY; - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 1, c->connect_complete_userdata); - } - - return; -} - -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { - struct pa_context *c = userdata; - struct pa_tagstruct *t; - uint32_t tag; - assert(client && c && c->state == CONTEXT_CONNECTING); - - pa_socket_client_free(client); - c->client = NULL; - - if (!io) { - c->error = PA_ERROR_CONNECTIONREFUSED; - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - c->pstream = pa_pstream_new(c->mainloop, io); - assert(c->pstream); - pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); - pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); - pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); - - c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); - assert(c->pdispatch); - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_AUTH); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - c->state = CONTEXT_AUTHORIZING; -} - -static struct sockaddr *resolve_server(const char *server, size_t *len) { - struct sockaddr *sa; - struct addrinfo hints, *result = NULL; - char *port; - assert(server && len); - - if ((port = strrchr(server, ':'))) - port++; - if (!port) - port = DEFAULT_PORT; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(server, port, &hints, &result) != 0) - return NULL; - assert(result); - - sa = pa_xmalloc(*len = result->ai_addrlen); - memcpy(sa, result->ai_addr, *len); - - freeaddrinfo(result); - - return sa; -} - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { - assert(c && c->state == CONTEXT_UNCONNECTED); - - if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { - c->error = PA_ERROR_AUTHKEY; - return -1; - } - - if (!server) - if (!(server = getenv("POLYP_SERVER"))) - server = DEFAULT_SERVER; - - assert(!c->client); - - if (*server == '/') { - if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } else { - struct sockaddr* sa; - size_t sa_len; - - if (!(sa = resolve_server(server, &sa_len))) { - c->error = PA_ERROR_INVALIDSERVER; - return -1; - } - - c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); - pa_xfree(sa); - - if (!c->client) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } - - c->connect_complete_callback = complete; - c->connect_complete_userdata = userdata; - - pa_socket_client_set_callback(c->client, on_connection, c); - c->state = CONTEXT_CONNECTING; - - return 0; -} - -int pa_context_is_dead(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_DEAD; -} - -int pa_context_is_ready(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_READY; -} - -int pa_context_errno(struct pa_context *c) { - assert(c); - return c->error; -} - -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { - assert(c); - c->die_callback = cb; - c->die_userdata = userdata; -} - -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - uint32_t channel; - assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) - return; - - c->error = PA_ERROR_KILLED; - stream_dead(s); -} - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s; - struct pa_context *c = userdata; - uint32_t bytes, channel; - assert(pd && command == PA_COMMAND_REQUEST && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - pa_tagstruct_getu32(t, &bytes) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(c->playback_streams, channel))) - return; - - if (s->state != STREAM_READY) - return; - - s->requested_bytes += bytes; - - if (s->requested_bytes && s->write_callback) - s->write_callback(s, s->requested_bytes, s->write_userdata); -} - -static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s && s->state == STREAM_CREATING); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - if (s->create_complete_callback) - s->create_complete_callback(s, 0, s->create_complete_userdata); - - return; - } - - if (pa_tagstruct_getu32(t, &s->channel) < 0 || - ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - s->channel_valid = 1; - pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - - s->state = STREAM_READY; - if (s->create_complete_callback) - s->create_complete_callback(s, 1, s->create_complete_userdata); -} - -static void create_stream(struct pa_stream *s, const char *dev) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s); - - s->state = STREAM_CREATING; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_puts(t, s->name); - pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, s->buffer_attr.maxlength); - if (s->direction == PA_STREAM_PLAYBACK) { - pa_tagstruct_putu32(t, s->buffer_attr.tlength); - pa_tagstruct_putu32(t, s->buffer_attr.prebuf); - pa_tagstruct_putu32(t, s->buffer_attr.minreq); - } else - pa_tagstruct_putu32(t, s->buffer_attr.fragsize); - - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); -} - -static struct pa_stream *internal_stream_new(struct pa_context *c) { - struct pa_stream *s; - - s = pa_xmalloc(sizeof(struct pa_stream)); - s->context = c; - - s->read_callback = NULL; - s->read_userdata = NULL; - s->write_callback = NULL; - s->write_userdata = NULL; - s->die_callback = NULL; - s->die_userdata = NULL; - s->create_complete_callback = NULL; - s->create_complete_userdata = NULL; - s->get_latency_callback = NULL; - s->get_latency_userdata = NULL; - s->finish_sample_callback = NULL; - s->finish_sample_userdata = NULL; - - s->name = NULL; - s->state = STREAM_CREATING; - s->requested_bytes = 0; - s->channel = 0; - s->channel_valid = 0; - s->device_index = (uint32_t) -1; - - memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - - s->next = c->first_stream; - if (s->next) - s->next->previous = s; - s->previous = NULL; - c->first_stream = s; - - return s; -} - -struct pa_stream* pa_stream_new( - struct pa_context *c, - enum pa_stream_direction dir, - const char *dev, - const char *name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, - void (*complete) (struct pa_stream*s, int success, void *userdata), - void *userdata) { - - struct pa_stream *s; - - assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = complete; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = dir; - s->sample_spec = *ss; - if (attr) - s->buffer_attr = *attr; - else { - s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; - s->buffer_attr.tlength = DEFAULT_TLENGTH; - s->buffer_attr.prebuf = DEFAULT_PREBUF; - s->buffer_attr.minreq = DEFAULT_MINREQ; - s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; - } - - create_stream(s, dev); - - return s; -} - -void pa_stream_free(struct pa_stream *s) { - assert(s && s->context); - - if (s->context->pdispatch) - pa_pdispatch_unregister_reply(s->context->pdispatch, s); - - pa_xfree(s->name); - - if (s->channel_valid && s->context->state == CONTEXT_READY) { - struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : - (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); - pa_tagstruct_putu32(t, s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - } - - if (s->channel_valid) - pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - - if (s->next) - s->next->previous = s->previous; - if (s->previous) - s->previous->next = s->next; - else - s->context->first_stream = s->next; - - pa_xfree(s); -} - -void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { - s->write_callback = cb; - s->write_userdata = userdata; -} - -void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { - struct pa_memchunk chunk; - assert(s && s->context && data && length && s->state == STREAM_READY); - - chunk.memblock = pa_memblock_new(length); - assert(chunk.memblock && chunk.memblock->data); - memcpy(chunk.memblock->data, data, length); - chunk.index = 0; - chunk.length = length; - - pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); - pa_memblock_unref(chunk.memblock); - - /*fprintf(stderr, "Sent %u bytes\n", length);*/ - - if (length < s->requested_bytes) - s->requested_bytes -= length; - else - s->requested_bytes = 0; -} - -size_t pa_stream_writable_size(struct pa_stream *s) { - assert(s && s->state == STREAM_READY); - return s->requested_bytes; -} - -void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { - assert(s && cb); - s->read_callback = cb; - s->read_userdata = userdata; -} - -int pa_stream_is_dead(struct pa_stream *s) { - return s->state == STREAM_DEAD; -} - -int pa_stream_is_ready(struct pa_stream*s) { - return s->state == STREAM_READY; -} - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { - assert(s); - s->die_callback = cb; - s->die_userdata = userdata; -} - -int pa_context_is_pending(struct pa_context *c) { - assert(c); - - if (c->state != CONTEXT_READY) - return 0; - - return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); -} - -struct pa_context* pa_stream_get_context(struct pa_stream *p) { - assert(p); - return p->context; -} - -static void set_dispatch_callbacks(struct pa_context *c); - -static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void set_dispatch_callbacks(struct pa_context *c) { - assert(c && c->state == CONTEXT_READY); - - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - - if (pa_pdispatch_is_pending(c->pdispatch)) { - pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); - return; - } - - if (pa_pstream_is_pending(c->pstream)) { - pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); - return; - } - - assert(c->drain_complete_callback); - c->drain_complete_callback(c, c->drain_complete_userdata); -} - -int pa_context_drain( - struct pa_context *c, - void (*complete) (struct pa_context*c, void *userdata), - void *userdata) { - - assert(c && c->state == CONTEXT_READY); - - if (complete == NULL) { - c->drain_complete_callback = NULL; - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - return 0; - } - - if (!pa_context_is_pending(c)) - return -1; - - c->drain_complete_callback = complete; - c->drain_complete_userdata = userdata; - - set_dispatch_callbacks(c); - - return 0; -} - -static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - return; - } - - if (s->state != STREAM_READY) - return; - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->drain_complete_callback) { - void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; - s->drain_complete_callback = NULL; - temp(s, s->drain_complete_userdata); - } -} - - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s && s->state == STREAM_READY); - - if (!complete) { - s->drain_complete_callback = NULL; - return; - } - - s->drain_complete_callback = complete; - s->drain_complete_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); -} - -void pa_context_exit(struct pa_context *c) { - struct pa_tagstruct *t; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_EXIT); - pa_tagstruct_putu32(t, c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - uint32_t total, count; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &count) < 0 || - pa_tagstruct_getu32(t, &total) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, count, total, c->stat_userdata); -} - -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - c->stat_callback = cb; - c->stat_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_STAT); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); -} - -static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - uint32_t latency; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &latency) < 0 || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, latency, s->get_latency_userdata); -} - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - p->get_latency_callback = cb; - p->get_latency_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); -} - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_stream *s; - struct pa_tagstruct *t; - uint32_t tag; - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = cb; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = PA_STREAM_UPLOAD; - s->sample_spec = *ss; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_tagstruct_put_sample_spec(t, ss); - pa_tagstruct_putu32(t, length); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); - - return s; -} - -static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 0, s->finish_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 1, s->finish_sample_userdata); -} - -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(p); - - p->finish_sample_callback = cb; - p->finish_sample_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); -} - -static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 0, c->play_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 1, c->play_sample_userdata); -} - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name && *name && (!dev || *dev)); - - c->play_sample_callback = cb; - c->play_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, volume); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); -} - -static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 0, c->remove_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 1, c->remove_sample_userdata); -} - -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name); - - c->remove_sample_callback = cb; - c->remove_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); -} - -static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_server_info i; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, NULL, c->get_server_info_userdata); - return; - } - - if (pa_tagstruct_gets(t, &i.server_name) < 0 || - pa_tagstruct_gets(t, &i.server_version) < 0 || - pa_tagstruct_gets(t, &i.user_name) < 0 || - pa_tagstruct_gets(t, &i.host_name) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, &i, c->get_server_info_userdata); -} - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_server_info_callback = cb; - c->get_server_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); -} - -static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_sink_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.monitor_source) < 0 || - pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); -} - -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_source_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || - pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); -} - -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { - struct pa_tagstruct *t; - assert(c); - - c->subscribe_callback = cb; - c->subscribe_userdata = userdata; - c->subscribe_mask = m; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); - pa_tagstruct_putu32(t, c->ctag++); - pa_tagstruct_putu32(t, cb ? m : 0); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - enum pa_subscription_event_type e; - uint32_t index; - assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); - - if (pa_tagstruct_getu32(t, &e) < 0 || - pa_tagstruct_getu32(t, &index) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) - c->subscribe_callback(c, e, index, c->subscribe_userdata); -} - -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_client_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.protocol_name) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); -} - - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_module_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.argument) < 0 || - pa_tagstruct_getu32(t, &i.n_used) < 0 || - pa_tagstruct_getu32(t, &i.auto_unload) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); -} - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} - -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} diff --git a/polyp/polyplib-sample.h b/polyp/polyplib-sample.h deleted file mode 100644 index a0dd9f9cb..000000000 --- a/polyp/polyplib-sample.h +++ /dev/null @@ -1,178 +0,0 @@ -#ifndef foopolyplibhfoo -#define foopolyplibhfoo - -/* $Id$ */ - -/*** - This file is part of polypaudio. - - polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - polypaudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -#include "sample.h" -#include "polyplib-def.h" -#include "mainloop-api.h" - -#ifdef __cplusplus -//extern "C" { -#endif - -struct pa_context; -struct pa_stream; - -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); -void pa_context_unref(struct pa_context *c); -struct pa_context* pa_context_ref(struct pa_context *c); - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); -int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); - -int pa_context_is_dead(struct pa_context *c); -int pa_context_is_ready(struct pa_context *c); -int pa_context_errno(struct pa_context *c); - -int pa_context_is_pending(struct pa_context *c); - -struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_unref(struct pa_stream *s); -struct pa_stream *pa_stream_ref(struct pa_stream *s); - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); - -void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); -void pa_stream_write(struct pa_stream *p, const void *data, size_t length); -size_t pa_stream_writable_size(struct pa_stream *p); - -void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); - -int pa_stream_is_dead(struct pa_stream *p); -int pa_stream_is_ready(struct pa_stream*p); - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); - -struct pa_context* pa_stream_get_context(struct pa_stream *p); - -uint32_t pa_stream_get_index(struct pa_stream *s); - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -struct pa_sink_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t volume; - uint32_t monitor_source; - const char *monitor_source_name; - uint32_t latency; -}; - -void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); - -struct pa_source_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t monitor_of_sink; - const char *monitor_of_sink_name; -}; - -void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); - -struct pa_server_info { - const char *user_name; - const char *host_name; - const char *server_version; - const char *server_name; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); - -struct pa_module_info { - uint32_t index; - const char*name, *argument; - uint32_t n_used, auto_unload; -}; - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); - -struct pa_client_info { - uint32_t index; - const char *name; - uint32_t owner_module; - const char *protocol_name; -}; - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); - -struct pa_sink_input_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t sink; - struct pa_sample_spec sample_spec; - uint32_t volume; - uint32_t latency; -}; - -void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); - -struct pa_source_output_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t source; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); - -void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -void pa_context_exit(struct pa_context *c); -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/polyp/polyplib-scache.c b/polyp/polyplib-scache.c index 35001d3d3..8215eaec1 100644 --- a/polyp/polyplib-scache.c +++ b/polyp/polyplib-scache.c @@ -23,1083 +23,73 @@ #include #endif -#include #include #include +#include #include -#include -#include -#include -#include "polyplib.h" -#include "native-common.h" -#include "pdispatch.h" -#include "pstream.h" -#include "dynarray.h" -#include "socket-client.h" +#include "polyplib-scache.h" +#include "polyplib-internal.h" #include "pstream-util.h" -#include "authkey.h" -#include "util.h" -#include "xmalloc.h" -#define DEFAULT_MAXLENGTH 204800 -#define DEFAULT_TLENGTH 10240 -#define DEFAULT_PREBUF 4096 -#define DEFAULT_MINREQ 1024 -#define DEFAULT_FRAGSIZE 1024 - -#define DEFAULT_TIMEOUT (5*60) -#define DEFAULT_SERVER "/tmp/polypaudio/native" -#define DEFAULT_PORT "4713" - -struct pa_context { - char *name; - struct pa_mainloop_api* mainloop; - struct pa_socket_client *client; - struct pa_pstream *pstream; - struct pa_pdispatch *pdispatch; - struct pa_dynarray *record_streams, *playback_streams; - struct pa_stream *first_stream; - uint32_t ctag; - uint32_t error; - enum { - CONTEXT_UNCONNECTED, - CONTEXT_CONNECTING, - CONTEXT_AUTHORIZING, - CONTEXT_SETTING_NAME, - CONTEXT_READY, - CONTEXT_DEAD - } state; - - void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); - void *connect_complete_userdata; - - void (*drain_complete_callback)(struct pa_context*c, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_context*c, void *userdata); - void *die_userdata; - - void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); - void *stat_userdata; - - void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); - void *play_sample_userdata; - - void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); - void *remove_sample_userdata; - - void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); - void *get_server_info_userdata; - - void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); - void *get_sink_info_userdata; - - void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); - void *get_source_info_userdata; - - void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); - void *subscribe_userdata; - enum pa_subscription_mask subscribe_mask; - - void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); - void *get_client_info_userdata; - - void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); - void *get_module_info_userdata; - - uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; -}; - -struct pa_stream { - struct pa_context *context; - struct pa_stream *next, *previous; - - char *name; - struct pa_buffer_attr buffer_attr; - struct pa_sample_spec sample_spec; - uint32_t channel; - int channel_valid; - uint32_t device_index; - enum pa_stream_direction direction; - - enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; - uint32_t requested_bytes; - - void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); - void *read_userdata; - - void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); - void *write_userdata; - - void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); - void *create_complete_userdata; - - void (*drain_complete_callback)(struct pa_stream *s, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_stream*c, void *userdata); - void *die_userdata; - - void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); - void *get_latency_userdata; - - void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); - void *finish_sample_userdata; -}; - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); - -static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { - [PA_COMMAND_ERROR] = { NULL }, - [PA_COMMAND_REPLY] = { NULL }, - [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_EXIT] = { NULL }, - [PA_COMMAND_REQUEST] = { command_request }, - [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, -}; - -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { - struct pa_context *c; - assert(mainloop && name); - - c = pa_xmalloc(sizeof(struct pa_context)); - c->name = pa_xstrdup(name); - c->mainloop = mainloop; - c->client = NULL; - c->pstream = NULL; - c->pdispatch = NULL; - c->playback_streams = pa_dynarray_new(); - assert(c->playback_streams); - c->record_streams = pa_dynarray_new(); - assert(c->record_streams); - c->first_stream = NULL; - c->error = PA_ERROR_OK; - c->state = CONTEXT_UNCONNECTED; - c->ctag = 0; - - c->connect_complete_callback = NULL; - c->connect_complete_userdata = NULL; - - c->drain_complete_callback = NULL; - c->drain_complete_userdata = NULL; - - c->die_callback = NULL; - c->die_userdata = NULL; - - c->stat_callback = NULL; - c->stat_userdata = NULL; - - c->play_sample_callback = NULL; - c->play_sample_userdata = NULL; - - c->remove_sample_callback = NULL; - c->remove_sample_userdata = NULL; - - c->get_server_info_callback = NULL; - c->get_server_info_userdata = NULL; - - c->get_sink_info_callback = NULL; - c->get_sink_info_userdata = NULL; - - c->get_source_info_callback = NULL; - c->get_source_info_userdata = NULL; - - c->subscribe_callback = NULL; - c->subscribe_userdata = NULL; - - c->get_client_info_callback = NULL; - c->get_client_info_userdata = NULL; - - c->get_module_info_callback = NULL; - c->get_module_info_userdata = NULL; - - pa_check_for_sigpipe(); - return c; -} - -void pa_context_free(struct pa_context *c) { - assert(c); - - while (c->first_stream) - pa_stream_free(c->first_stream); - - if (c->client) - pa_socket_client_free(c->client); - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - if (c->pstream) - pa_pstream_free(c->pstream); - if (c->record_streams) - pa_dynarray_free(c->record_streams, NULL, NULL); - if (c->playback_streams) - pa_dynarray_free(c->playback_streams, NULL, NULL); - - pa_xfree(c->name); - pa_xfree(c); -} - -static void stream_dead(struct pa_stream *s) { - assert(s); - - if (s->state == STREAM_DEAD) - return; - - if (s->state == STREAM_READY) { - s->state = STREAM_DEAD; - if (s->die_callback) - s->die_callback(s, s->die_userdata); - } else - s->state = STREAM_DEAD; -} - -static void context_dead(struct pa_context *c) { - struct pa_stream *s; - assert(c); - - if (c->state == CONTEXT_DEAD) - return; - - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - c->pdispatch = NULL; - - if (c->pstream) - pa_pstream_free(c->pstream); - c->pstream = NULL; - - if (c->client) - pa_socket_client_free(c->client); - c->client = NULL; - - for (s = c->first_stream; s; s = s->next) - stream_dead(s); - - if (c->state == CONTEXT_READY) { - c->state = CONTEXT_DEAD; - if (c->die_callback) - c->die_callback(c, c->die_userdata); - } else - c->state = CONTEXT_DEAD; -} - -static void pstream_die_callback(struct pa_pstream *p, void *userdata) { - struct pa_context *c = userdata; - assert(p && c); - c->error = PA_ERROR_CONNECTIONTERMINATED; - context_dead(c); -} - -static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { - struct pa_context *c = userdata; - assert(p && packet && c); - - if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - fprintf(stderr, "polyp.c: invalid packet.\n"); - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - } -} - -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - assert(p && chunk && c && chunk->memblock && chunk->memblock->data); - - if (!(s = pa_dynarray_get(c->record_streams, channel))) - return; - - if (s->read_callback) - s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); -} - -static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { - assert(c && t); - - if (command == PA_COMMAND_ERROR) { - if (pa_tagstruct_getu32(t, &c->error) < 0) { - c->error = PA_ERROR_PROTOCOL; - return -1; - } - - return 0; - } - - c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; - return -1; -} - -static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); - - if (command != PA_COMMAND_REPLY) { - handle_error(c, command, t); - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - if (c->state == CONTEXT_AUTHORIZING) { - struct pa_tagstruct *t; - c->state = CONTEXT_SETTING_NAME; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, c->name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - } else { - assert(c->state == CONTEXT_SETTING_NAME); - - c->state = CONTEXT_READY; - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 1, c->connect_complete_userdata); - } - - return; -} - -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { - struct pa_context *c = userdata; +void pa_stream_connect_upload(struct pa_stream *s, size_t length) { struct pa_tagstruct *t; uint32_t tag; - assert(client && c && c->state == CONTEXT_CONNECTING); - - pa_socket_client_free(client); - c->client = NULL; - - if (!io) { - c->error = PA_ERROR_CONNECTIONREFUSED; - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - c->pstream = pa_pstream_new(c->mainloop, io); - assert(c->pstream); - pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); - pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); - pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + assert(s && length); + + pa_stream_ref(s); - c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); - assert(c->pdispatch); + s->state = PA_STREAM_CREATING; + s->direction = PA_STREAM_UPLOAD; t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_AUTH); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - c->state = CONTEXT_AUTHORIZING; -} - -static struct sockaddr *resolve_server(const char *server, size_t *len) { - struct sockaddr *sa; - struct addrinfo hints, *result = NULL; - char *port; - assert(server && len); - - if ((port = strrchr(server, ':'))) - port++; - if (!port) - port = DEFAULT_PORT; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(server, port, &hints, &result) != 0) - return NULL; - assert(result); - - sa = pa_xmalloc(*len = result->ai_addrlen); - memcpy(sa, result->ai_addr, *len); - - freeaddrinfo(result); - - return sa; -} - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { - assert(c && c->state == CONTEXT_UNCONNECTED); - - if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { - c->error = PA_ERROR_AUTHKEY; - return -1; - } - - if (!server) - if (!(server = getenv("POLYP_SERVER"))) - server = DEFAULT_SERVER; - - assert(!c->client); - - if (*server == '/') { - if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } else { - struct sockaddr* sa; - size_t sa_len; - - if (!(sa = resolve_server(server, &sa_len))) { - c->error = PA_ERROR_INVALIDSERVER; - return -1; - } - - c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); - pa_xfree(sa); - - if (!c->client) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } - - c->connect_complete_callback = complete; - c->connect_complete_userdata = userdata; - - pa_socket_client_set_callback(c->client, on_connection, c); - c->state = CONTEXT_CONNECTING; - - return 0; -} - -int pa_context_is_dead(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_DEAD; -} - -int pa_context_is_ready(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_READY; -} - -int pa_context_errno(struct pa_context *c) { - assert(c); - return c->error; -} - -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { - assert(c); - c->die_callback = cb; - c->die_userdata = userdata; -} - -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - uint32_t channel; - assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) - return; - - c->error = PA_ERROR_KILLED; - stream_dead(s); -} - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s; - struct pa_context *c = userdata; - uint32_t bytes, channel; - assert(pd && command == PA_COMMAND_REQUEST && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - pa_tagstruct_getu32(t, &bytes) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(c->playback_streams, channel))) - return; - - if (s->state != STREAM_READY) - return; - - s->requested_bytes += bytes; - - if (s->requested_bytes && s->write_callback) - s->write_callback(s, s->requested_bytes, s->write_userdata); -} - -static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s && s->state == STREAM_CREATING); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - if (s->create_complete_callback) - s->create_complete_callback(s, 0, s->create_complete_userdata); - - return; - } - - if (pa_tagstruct_getu32(t, &s->channel) < 0 || - ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - s->channel_valid = 1; - pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - - s->state = STREAM_READY; - if (s->create_complete_callback) - s->create_complete_callback(s, 1, s->create_complete_userdata); -} - -static void create_stream(struct pa_stream *s, const char *dev) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s); - - s->state = STREAM_CREATING; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_puts(t, s->name); pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, s->buffer_attr.maxlength); - if (s->direction == PA_STREAM_PLAYBACK) { - pa_tagstruct_putu32(t, s->buffer_attr.tlength); - pa_tagstruct_putu32(t, s->buffer_attr.prebuf); - pa_tagstruct_putu32(t, s->buffer_attr.minreq); - } else - pa_tagstruct_putu32(t, s->buffer_attr.fragsize); - + pa_tagstruct_putu32(t, length); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s); + + pa_stream_unref(s); } -static struct pa_stream *internal_stream_new(struct pa_context *c) { - struct pa_stream *s; - - s = pa_xmalloc(sizeof(struct pa_stream)); - s->context = c; - - s->read_callback = NULL; - s->read_userdata = NULL; - s->write_callback = NULL; - s->write_userdata = NULL; - s->die_callback = NULL; - s->die_userdata = NULL; - s->create_complete_callback = NULL; - s->create_complete_userdata = NULL; - s->get_latency_callback = NULL; - s->get_latency_userdata = NULL; - s->finish_sample_callback = NULL; - s->finish_sample_userdata = NULL; - - s->name = NULL; - s->state = STREAM_CREATING; - s->requested_bytes = 0; - s->channel = 0; - s->channel_valid = 0; - s->device_index = (uint32_t) -1; - - memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - - s->next = c->first_stream; - if (s->next) - s->next->previous = s; - s->previous = NULL; - c->first_stream = s; - - return s; -} - -struct pa_stream* pa_stream_new( - struct pa_context *c, - enum pa_stream_direction dir, - const char *dev, - const char *name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, - void (*complete) (struct pa_stream*s, int success, void *userdata), - void *userdata) { - - struct pa_stream *s; - - assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = complete; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = dir; - s->sample_spec = *ss; - if (attr) - s->buffer_attr = *attr; - else { - s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; - s->buffer_attr.tlength = DEFAULT_TLENGTH; - s->buffer_attr.prebuf = DEFAULT_PREBUF; - s->buffer_attr.minreq = DEFAULT_MINREQ; - s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; - } - - create_stream(s, dev); - - return s; -} - -void pa_stream_free(struct pa_stream *s) { - assert(s && s->context); - - if (s->context->pdispatch) - pa_pdispatch_unregister_reply(s->context->pdispatch, s); - - pa_xfree(s->name); - - if (s->channel_valid && s->context->state == CONTEXT_READY) { - struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : - (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); - pa_tagstruct_putu32(t, s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - } - - if (s->channel_valid) - pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - - if (s->next) - s->next->previous = s->previous; - if (s->previous) - s->previous->next = s->next; - else - s->context->first_stream = s->next; - - pa_xfree(s); -} - -void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { - s->write_callback = cb; - s->write_userdata = userdata; -} - -void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { - struct pa_memchunk chunk; - assert(s && s->context && data && length && s->state == STREAM_READY); - - chunk.memblock = pa_memblock_new(length); - assert(chunk.memblock && chunk.memblock->data); - memcpy(chunk.memblock->data, data, length); - chunk.index = 0; - chunk.length = length; - - pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); - pa_memblock_unref(chunk.memblock); - - /*fprintf(stderr, "Sent %u bytes\n", length);*/ - - if (length < s->requested_bytes) - s->requested_bytes -= length; - else - s->requested_bytes = 0; -} - -size_t pa_stream_writable_size(struct pa_stream *s) { - assert(s && s->state == STREAM_READY); - return s->requested_bytes; -} - -void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { - assert(s && cb); - s->read_callback = cb; - s->read_userdata = userdata; -} - -int pa_stream_is_dead(struct pa_stream *s) { - return s->state == STREAM_DEAD; -} - -int pa_stream_is_ready(struct pa_stream*s) { - return s->state == STREAM_READY; -} - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { - assert(s); - s->die_callback = cb; - s->die_userdata = userdata; -} - -int pa_context_is_pending(struct pa_context *c) { - assert(c); - - if (c->state != CONTEXT_READY) - return 0; - - return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); -} - -struct pa_context* pa_stream_get_context(struct pa_stream *p) { - assert(p); - return p->context; -} - -static void set_dispatch_callbacks(struct pa_context *c); - -static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void set_dispatch_callbacks(struct pa_context *c) { - assert(c && c->state == CONTEXT_READY); - - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - - if (pa_pdispatch_is_pending(c->pdispatch)) { - pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); - return; - } - - if (pa_pstream_is_pending(c->pstream)) { - pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); - return; - } - - assert(c->drain_complete_callback); - c->drain_complete_callback(c, c->drain_complete_userdata); -} - -int pa_context_drain( - struct pa_context *c, - void (*complete) (struct pa_context*c, void *userdata), - void *userdata) { - - assert(c && c->state == CONTEXT_READY); - - if (complete == NULL) { - c->drain_complete_callback = NULL; - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - return 0; - } - - if (!pa_context_is_pending(c)) - return -1; - - c->drain_complete_callback = complete; - c->drain_complete_userdata = userdata; - - set_dispatch_callbacks(c); - - return 0; -} - -static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - return; - } - - if (s->state != STREAM_READY) - return; - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->drain_complete_callback) { - void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; - s->drain_complete_callback = NULL; - temp(s, s->drain_complete_userdata); - } -} - - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { +void pa_stream_finish_upload(struct pa_stream *s) { struct pa_tagstruct *t; uint32_t tag; - assert(s && s->state == STREAM_READY); + assert(s); - if (!complete) { - s->drain_complete_callback = NULL; + if (!s->channel_valid || !s->context->state == PA_CONTEXT_READY) return; - } - s->drain_complete_callback = complete; - s->drain_complete_userdata = userdata; + pa_stream_ref(s); t = pa_tagstruct_new(NULL, 0); assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s); + + pa_stream_unref(s); } -void pa_context_exit(struct pa_context *c) { - struct pa_tagstruct *t; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_EXIT); - pa_tagstruct_putu32(t, c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - uint32_t total, count; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &count) < 0 || - pa_tagstruct_getu32(t, &total) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, count, total, c->stat_userdata); -} - -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - c->stat_callback = cb; - c->stat_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_STAT); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); -} - -static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - uint32_t latency; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &latency) < 0 || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, latency, s->get_latency_userdata); -} - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - p->get_latency_callback = cb; - p->get_latency_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); -} - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_stream *s; - struct pa_tagstruct *t; - uint32_t tag; - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = cb; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = PA_STREAM_UPLOAD; - s->sample_spec = *ss; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_tagstruct_put_sample_spec(t, ss); - pa_tagstruct_putu32(t, length); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); - - return s; -} - -static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 0, s->finish_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 1, s->finish_sample_userdata); -} - -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(p); - - p->finish_sample_callback = cb; - p->finish_sample_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); -} - -static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 0, c->play_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 1, c->play_sample_userdata); -} - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { +struct pa_operation * pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_operation *o; struct pa_tagstruct *t; uint32_t tag; assert(c && name && *name && (!dev || *dev)); - c->play_sample_callback = cb; - c->play_sample_userdata = userdata; - - if (!cb) - return; + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + if (!dev) + dev = getenv(ENV_DEFAULT_SINK); + t = pa_tagstruct_new(NULL, 0); assert(t); pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); @@ -1109,44 +99,20 @@ void pa_context_play_sample(struct pa_context *c, const char *name, const char * pa_tagstruct_putu32(t, volume); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); } -static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 0, c->remove_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 1, c->remove_sample_userdata); -} - -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { +struct pa_operation* pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_operation *o; struct pa_tagstruct *t; uint32_t tag; assert(c && name); - c->remove_sample_callback = cb; - c->remove_sample_userdata = userdata; - - if (!cb) - return; + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); assert(t); @@ -1154,397 +120,8 @@ void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb) pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); } -static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_server_info i; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, NULL, c->get_server_info_userdata); - return; - } - - if (pa_tagstruct_gets(t, &i.server_name) < 0 || - pa_tagstruct_gets(t, &i.server_version) < 0 || - pa_tagstruct_gets(t, &i.user_name) < 0 || - pa_tagstruct_gets(t, &i.host_name) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, &i, c->get_server_info_userdata); -} - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_server_info_callback = cb; - c->get_server_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); -} - -static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_sink_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.monitor_source) < 0 || - pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); -} - -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_source_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || - pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); -} - -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { - struct pa_tagstruct *t; - assert(c); - - c->subscribe_callback = cb; - c->subscribe_userdata = userdata; - c->subscribe_mask = m; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); - pa_tagstruct_putu32(t, c->ctag++); - pa_tagstruct_putu32(t, cb ? m : 0); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - enum pa_subscription_event_type e; - uint32_t index; - assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); - - if (pa_tagstruct_getu32(t, &e) < 0 || - pa_tagstruct_getu32(t, &index) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) - c->subscribe_callback(c, e, index, c->subscribe_userdata); -} - -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_client_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.protocol_name) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); -} - - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_module_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.argument) < 0 || - pa_tagstruct_getu32(t, &i.n_used) < 0 || - pa_tagstruct_getu32(t, &i.auto_unload) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); -} - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} - -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} diff --git a/polyp/polyplib-scache.h b/polyp/polyplib-scache.h index a0dd9f9cb..ce74bef09 100644 --- a/polyp/polyplib-scache.h +++ b/polyp/polyplib-scache.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibhfoo -#define foopolyplibhfoo +#ifndef foopolyplibscachehfoo +#define foopolyplibscachehfoo /* $Id$ */ @@ -24,155 +24,27 @@ #include -#include "sample.h" -#include "polyplib-def.h" -#include "mainloop-api.h" +#include "polyplib-context.h" +#include "polyplib-stream.h" +#include "cdecl.h" -#ifdef __cplusplus -//extern "C" { -#endif +/** \file + * All sample cache related routines */ -struct pa_context; -struct pa_stream; +PA_C_DECL_BEGIN -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); -void pa_context_unref(struct pa_context *c); -struct pa_context* pa_context_ref(struct pa_context *c); +/** Make this stream a sample upload stream */ +void pa_stream_connect_upload(struct pa_stream *s, size_t length); -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); -int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); +/** Finish the sample upload, the stream name will become the sample name. You cancel a sample upload by issuing pa_stream_disconnect() */ +void pa_stream_finish_upload(struct pa_stream *s); -int pa_context_is_dead(struct pa_context *c); -int pa_context_is_ready(struct pa_context *c); -int pa_context_errno(struct pa_context *c); +/** Play a sample from the sample cache to the specified device. If the latter is NULL use the default sink. Returns an operation object */ +struct pa_operation* pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -int pa_context_is_pending(struct pa_context *c); +/** Remove a sample from the sample cache. Returns an operation object which may be used to cancel the operation while it is running */ +struct pa_operation* pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_unref(struct pa_stream *s); -struct pa_stream *pa_stream_ref(struct pa_stream *s); - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); - -void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); -void pa_stream_write(struct pa_stream *p, const void *data, size_t length); -size_t pa_stream_writable_size(struct pa_stream *p); - -void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); - -int pa_stream_is_dead(struct pa_stream *p); -int pa_stream_is_ready(struct pa_stream*p); - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); - -struct pa_context* pa_stream_get_context(struct pa_stream *p); - -uint32_t pa_stream_get_index(struct pa_stream *s); - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -struct pa_sink_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t volume; - uint32_t monitor_source; - const char *monitor_source_name; - uint32_t latency; -}; - -void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); - -struct pa_source_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t monitor_of_sink; - const char *monitor_of_sink_name; -}; - -void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); - -struct pa_server_info { - const char *user_name; - const char *host_name; - const char *server_version; - const char *server_name; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); - -struct pa_module_info { - uint32_t index; - const char*name, *argument; - uint32_t n_used, auto_unload; -}; - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); - -struct pa_client_info { - uint32_t index; - const char *name; - uint32_t owner_module; - const char *protocol_name; -}; - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); - -struct pa_sink_input_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t sink; - struct pa_sample_spec sample_spec; - uint32_t volume; - uint32_t latency; -}; - -void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); - -struct pa_source_output_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t source; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); - -void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -void pa_context_exit(struct pa_context *c); -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); - -#ifdef __cplusplus -} -#endif +PA_C_DECL_END #endif diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index 1f5ea5535..66ee5995f 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -49,15 +49,28 @@ struct pa_simple { static void read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata); static int check_error(struct pa_simple *p, int *perror) { + enum pa_context_state cst; + enum pa_stream_state sst; assert(p); - if (pa_context_is_dead(p->context) || (p->stream && pa_stream_is_dead(p->stream))) { - if (perror) - *perror = pa_context_errno(p->context); - return -1; - } + if ((cst = pa_context_get_state(p->context)) == PA_CONTEXT_FAILED) + goto fail; + assert(cst != PA_CONTEXT_TERMINATED); + + if (p->stream) { + if ((sst = pa_stream_get_state(p->stream)) == PA_STREAM_FAILED) + goto fail; + + assert(sst != PA_STREAM_TERMINATED); + } + return 0; + +fail: + if (perror) + *perror = pa_context_errno(p->context); + return -1; } static int iterate(struct pa_simple *p, int block, int *perror) { @@ -96,7 +109,7 @@ struct pa_simple* pa_simple_new( struct pa_simple *p; int error = PA_ERROR_INTERNAL; - assert(ss); + assert(ss && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); p = pa_xmalloc(sizeof(struct pa_simple)); p->context = NULL; @@ -110,23 +123,25 @@ struct pa_simple* pa_simple_new( if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name))) goto fail; - - if (pa_context_connect(p->context, server, NULL, NULL) < 0) { - error = pa_context_errno(p->context); - goto fail; - } + + pa_context_connect(p->context, server); /* Wait until the context is ready */ - while (!pa_context_is_ready(p->context)) { + while (pa_context_get_state(p->context) != PA_CONTEXT_READY) { if (iterate(p, 1, &error) < 0) goto fail; } - if (!(p->stream = pa_stream_new(p->context, dir, dev, stream_name, ss, attr, NULL, NULL))) + if (!(p->stream = pa_stream_new(p->context, stream_name, ss))) goto fail; + if (dir == PA_STREAM_PLAYBACK) + pa_stream_connect_playback(p->stream, dev, attr); + else + pa_stream_connect_record(p->stream, dev, attr); + /* Wait until the stream is ready */ - while (!pa_stream_is_ready(p->stream)) { + while (pa_stream_get_state(p->stream) != PA_STREAM_READY) { if (iterate(p, 1, &error) < 0) goto fail; } @@ -148,10 +163,10 @@ void pa_simple_free(struct pa_simple *s) { pa_xfree(s->read_data); if (s->stream) - pa_stream_free(s->stream); + pa_stream_unref(s->stream); if (s->context) - pa_context_free(s->context); + pa_context_unref(s->context); if (s->mainloop) pa_mainloop_free(s->mainloop); @@ -172,7 +187,7 @@ int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *pe if (l > length) l = length; - pa_stream_write(p->stream, data, l); + pa_stream_write(p->stream, data, l, NULL); data += l; length -= l; } @@ -193,8 +208,7 @@ static void read_callback(struct pa_stream *s, const void*data, size_t length, v pa_xfree(p->read_data); } - p->read_data = pa_xmalloc(p->read_length = length); - memcpy(p->read_data, data, length); + p->read_data = pa_xmemdup(data, p->read_length = length); p->read_index = 0; } @@ -235,23 +249,31 @@ int pa_simple_read(struct pa_simple *p, void*data, size_t length, int *perror) { return 0; } -static void drain_complete(struct pa_stream *s, void *userdata) { +static void drain_complete(struct pa_stream *s, int success, void *userdata) { struct pa_simple *p = userdata; assert(s && p); - p->drained = 1; + p->drained = success ? 1 : -1; } int pa_simple_drain(struct pa_simple *p, int *perror) { + struct pa_operation *o; + assert(p && p->direction == PA_STREAM_PLAYBACK); p->drained = 0; - pa_stream_drain(p->stream, drain_complete, p); + o = pa_stream_drain(p->stream, drain_complete, p); while (!p->drained) { if (iterate(p, 1, perror) < 0) { - pa_stream_drain(p->stream, NULL, NULL); + pa_operation_cancel(o); + pa_operation_unref(o); return -1; } } + pa_operation_unref(o); + + if (p->drained < 0 && perror) + *perror = pa_context_errno(p->context); + return 0; } diff --git a/polyp/polyplib-simple.h b/polyp/polyplib-simple.h index 0544410c0..ee2e27e3f 100644 --- a/polyp/polyplib-simple.h +++ b/polyp/polyplib-simple.h @@ -26,24 +26,41 @@ #include "sample.h" #include "polyplib-def.h" +#include "cdecl.h" +/** \file + * A simple but limited synchronous playback and recording API. */ + +PA_C_DECL_BEGIN + +/** \struct pa_simple + * A simple connection object */ struct pa_simple; +/** Create a new connection to the server */ struct pa_simple* pa_simple_new( - const char *server, - const char *name, - enum pa_stream_direction dir, - const char *dev, - const char *stream_name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, - int *error); + const char *server, /**< Server name, or NULL for default */ + const char *name, /**< A descriptive name for this client (application name, ...) */ + enum pa_stream_direction dir, /**< Open this stream for recording or playback? */ + const char *dev, /**< Sink (resp. source) name, or NULL for default */ + const char *stream_name, /**< A descriptive name for this client (application name, song title, ...) */ + const struct pa_sample_spec *ss, /**< The sample type to use */ + const struct pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */ + int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */ + ); +/** Close and free the connection to the server. The connection objects becomes invalid when this is called. */ void pa_simple_free(struct pa_simple *s); +/** Write some data to the server */ int pa_simple_write(struct pa_simple *s, const void*data, size_t length, int *error); + +/** Wait until all data already written is played by the daemon */ int pa_simple_drain(struct pa_simple *s, int *error); +/** Read some data from the server */ int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *error); +PA_C_DECL_END + #endif diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 35001d3d3..362dbad14 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -23,576 +23,217 @@ #include #endif -#include #include -#include #include -#include -#include -#include +#include -#include "polyplib.h" -#include "native-common.h" -#include "pdispatch.h" -#include "pstream.h" -#include "dynarray.h" -#include "socket-client.h" -#include "pstream-util.h" -#include "authkey.h" -#include "util.h" +#include "polyplib-internal.h" #include "xmalloc.h" +#include "pstream-util.h" -#define DEFAULT_MAXLENGTH 204800 -#define DEFAULT_TLENGTH 10240 -#define DEFAULT_PREBUF 4096 -#define DEFAULT_MINREQ 1024 -#define DEFAULT_FRAGSIZE 1024 +struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss) { + assert(c && ss); + struct pa_stream *s; -#define DEFAULT_TIMEOUT (5*60) -#define DEFAULT_SERVER "/tmp/polypaudio/native" -#define DEFAULT_PORT "4713" + s = pa_xmalloc(sizeof(struct pa_stream)); + s->ref = 1; + s->context = c; -struct pa_context { - char *name; - struct pa_mainloop_api* mainloop; - struct pa_socket_client *client; - struct pa_pstream *pstream; - struct pa_pdispatch *pdispatch; - struct pa_dynarray *record_streams, *playback_streams; - struct pa_stream *first_stream; - uint32_t ctag; - uint32_t error; - enum { - CONTEXT_UNCONNECTED, - CONTEXT_CONNECTING, - CONTEXT_AUTHORIZING, - CONTEXT_SETTING_NAME, - CONTEXT_READY, - CONTEXT_DEAD - } state; + s->read_callback = NULL; + s->read_userdata = NULL; + s->write_callback = NULL; + s->write_userdata = NULL; + s->state_callback = NULL; + s->state_userdata = NULL; - void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); - void *connect_complete_userdata; + s->state = PA_STREAM_NODIRECTION; + s->name = pa_xstrdup(name); + s->sample_spec = *ss; + s->channel = 0; + s->channel_valid = 0; + s->device_index = PA_INVALID_INDEX; + s->requested_bytes = 0; + s->state = PA_STREAM_DISCONNECTED; + memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - void (*drain_complete_callback)(struct pa_context*c, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_context*c, void *userdata); - void *die_userdata; + PA_LLIST_PREPEND(struct pa_stream, c->streams, s); - void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); - void *stat_userdata; - - void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); - void *play_sample_userdata; - - void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); - void *remove_sample_userdata; - - void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); - void *get_server_info_userdata; - - void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); - void *get_sink_info_userdata; - - void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); - void *get_source_info_userdata; - - void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); - void *subscribe_userdata; - enum pa_subscription_mask subscribe_mask; - - void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); - void *get_client_info_userdata; - - void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); - void *get_module_info_userdata; - - uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; -}; - -struct pa_stream { - struct pa_context *context; - struct pa_stream *next, *previous; - - char *name; - struct pa_buffer_attr buffer_attr; - struct pa_sample_spec sample_spec; - uint32_t channel; - int channel_valid; - uint32_t device_index; - enum pa_stream_direction direction; - - enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; - uint32_t requested_bytes; - - void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); - void *read_userdata; - - void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); - void *write_userdata; - - void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); - void *create_complete_userdata; - - void (*drain_complete_callback)(struct pa_stream *s, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_stream*c, void *userdata); - void *die_userdata; - - void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); - void *get_latency_userdata; - - void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); - void *finish_sample_userdata; -}; - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); - -static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { - [PA_COMMAND_ERROR] = { NULL }, - [PA_COMMAND_REPLY] = { NULL }, - [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_EXIT] = { NULL }, - [PA_COMMAND_REQUEST] = { command_request }, - [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, -}; - -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { - struct pa_context *c; - assert(mainloop && name); - - c = pa_xmalloc(sizeof(struct pa_context)); - c->name = pa_xstrdup(name); - c->mainloop = mainloop; - c->client = NULL; - c->pstream = NULL; - c->pdispatch = NULL; - c->playback_streams = pa_dynarray_new(); - assert(c->playback_streams); - c->record_streams = pa_dynarray_new(); - assert(c->record_streams); - c->first_stream = NULL; - c->error = PA_ERROR_OK; - c->state = CONTEXT_UNCONNECTED; - c->ctag = 0; - - c->connect_complete_callback = NULL; - c->connect_complete_userdata = NULL; - - c->drain_complete_callback = NULL; - c->drain_complete_userdata = NULL; - - c->die_callback = NULL; - c->die_userdata = NULL; - - c->stat_callback = NULL; - c->stat_userdata = NULL; - - c->play_sample_callback = NULL; - c->play_sample_userdata = NULL; - - c->remove_sample_callback = NULL; - c->remove_sample_userdata = NULL; - - c->get_server_info_callback = NULL; - c->get_server_info_userdata = NULL; - - c->get_sink_info_callback = NULL; - c->get_sink_info_userdata = NULL; - - c->get_source_info_callback = NULL; - c->get_source_info_userdata = NULL; - - c->subscribe_callback = NULL; - c->subscribe_userdata = NULL; - - c->get_client_info_callback = NULL; - c->get_client_info_userdata = NULL; - - c->get_module_info_callback = NULL; - c->get_module_info_userdata = NULL; - - pa_check_for_sigpipe(); - return c; + return pa_stream_ref(s); } -void pa_context_free(struct pa_context *c) { - assert(c); - - while (c->first_stream) - pa_stream_free(c->first_stream); - - if (c->client) - pa_socket_client_free(c->client); - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - if (c->pstream) - pa_pstream_free(c->pstream); - if (c->record_streams) - pa_dynarray_free(c->record_streams, NULL, NULL); - if (c->playback_streams) - pa_dynarray_free(c->playback_streams, NULL, NULL); - - pa_xfree(c->name); - pa_xfree(c); -} - -static void stream_dead(struct pa_stream *s) { +static void stream_free(struct pa_stream *s) { assert(s); + pa_xfree(s->name); + pa_xfree(s); +} + +void pa_stream_unref(struct pa_stream *s) { + assert(s && s->ref >= 1); + + if (--(s->ref) == 0) + stream_free(s); +} + +struct pa_stream* pa_stream_ref(struct pa_stream *s) { + assert(s && s->ref >= 1); + s->ref++; + return s; +} + +enum pa_stream_state pa_stream_get_state(struct pa_stream *s) { + assert(s && s->ref >= 1); + return s->state; +} + +struct pa_context* pa_stream_get_context(struct pa_stream *s) { + assert(s && s->ref >= 1); + return s->context; +} + +uint32_t pa_stream_get_index(struct pa_stream *s) { + assert(s && s->ref >= 1); + return s->device_index; +} - if (s->state == STREAM_DEAD) +void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st) { + assert(s && s->ref >= 1); + + if (s->state == st) return; - if (s->state == STREAM_READY) { - s->state = STREAM_DEAD; - if (s->die_callback) - s->die_callback(s, s->die_userdata); - } else - s->state = STREAM_DEAD; -} + pa_stream_ref(s); -static void context_dead(struct pa_context *c) { - struct pa_stream *s; - assert(c); + s->state = st; - if (c->state == CONTEXT_DEAD) - return; + if ((st == PA_STREAM_FAILED || st == PA_STREAM_TERMINATED) && s->context) { + if (s->channel_valid) + pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - c->pdispatch = NULL; - - if (c->pstream) - pa_pstream_free(c->pstream); - c->pstream = NULL; - - if (c->client) - pa_socket_client_free(c->client); - c->client = NULL; - - for (s = c->first_stream; s; s = s->next) - stream_dead(s); - - if (c->state == CONTEXT_READY) { - c->state = CONTEXT_DEAD; - if (c->die_callback) - c->die_callback(c, c->die_userdata); - } else - c->state = CONTEXT_DEAD; -} - -static void pstream_die_callback(struct pa_pstream *p, void *userdata) { - struct pa_context *c = userdata; - assert(p && c); - c->error = PA_ERROR_CONNECTIONTERMINATED; - context_dead(c); -} - -static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { - struct pa_context *c = userdata; - assert(p && packet && c); - - if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - fprintf(stderr, "polyp.c: invalid packet.\n"); - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - } -} - -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - assert(p && chunk && c && chunk->memblock && chunk->memblock->data); - - if (!(s = pa_dynarray_get(c->record_streams, channel))) - return; - - if (s->read_callback) - s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); -} - -static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { - assert(c && t); - - if (command == PA_COMMAND_ERROR) { - if (pa_tagstruct_getu32(t, &c->error) < 0) { - c->error = PA_ERROR_PROTOCOL; - return -1; - } - - return 0; + PA_LLIST_REMOVE(struct pa_stream, s->context->streams, s); + pa_stream_unref(s); } - c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; - return -1; + if (s->state_callback) + s->state_callback(s, s->state_userdata); + + pa_stream_unref(s); } -static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); - - if (command != PA_COMMAND_REPLY) { - handle_error(c, command, t); - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - if (c->state == CONTEXT_AUTHORIZING) { - struct pa_tagstruct *t; - c->state = CONTEXT_SETTING_NAME; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, c->name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - } else { - assert(c->state == CONTEXT_SETTING_NAME); - - c->state = CONTEXT_READY; - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 1, c->connect_complete_userdata); - } - - return; -} - -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { - struct pa_context *c = userdata; - struct pa_tagstruct *t; - uint32_t tag; - assert(client && c && c->state == CONTEXT_CONNECTING); - - pa_socket_client_free(client); - c->client = NULL; - - if (!io) { - c->error = PA_ERROR_CONNECTIONREFUSED; - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - c->pstream = pa_pstream_new(c->mainloop, io); - assert(c->pstream); - pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); - pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); - pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); - - c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); - assert(c->pdispatch); - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_AUTH); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - c->state = CONTEXT_AUTHORIZING; -} - -static struct sockaddr *resolve_server(const char *server, size_t *len) { - struct sockaddr *sa; - struct addrinfo hints, *result = NULL; - char *port; - assert(server && len); - - if ((port = strrchr(server, ':'))) - port++; - if (!port) - port = DEFAULT_PORT; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(server, port, &hints, &result) != 0) - return NULL; - assert(result); - - sa = pa_xmalloc(*len = result->ai_addrlen); - memcpy(sa, result->ai_addr, *len); - - freeaddrinfo(result); - - return sa; -} - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { - assert(c && c->state == CONTEXT_UNCONNECTED); - - if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { - c->error = PA_ERROR_AUTHKEY; - return -1; - } - - if (!server) - if (!(server = getenv("POLYP_SERVER"))) - server = DEFAULT_SERVER; - - assert(!c->client); - - if (*server == '/') { - if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } else { - struct sockaddr* sa; - size_t sa_len; - - if (!(sa = resolve_server(server, &sa_len))) { - c->error = PA_ERROR_INVALIDSERVER; - return -1; - } - - c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); - pa_xfree(sa); - - if (!c->client) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } - - c->connect_complete_callback = complete; - c->connect_complete_userdata = userdata; - - pa_socket_client_set_callback(c->client, on_connection, c); - c->state = CONTEXT_CONNECTING; - - return 0; -} - -int pa_context_is_dead(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_DEAD; -} - -int pa_context_is_ready(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_READY; -} - -int pa_context_errno(struct pa_context *c) { - assert(c); - return c->error; -} - -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { - assert(c); - c->die_callback = cb; - c->die_userdata = userdata; -} - -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +void pa_command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_context *c = userdata; struct pa_stream *s; uint32_t channel; assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); + pa_context_ref(c); + if (pa_tagstruct_getu32(t, &channel) < 0 || !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; + pa_context_fail(c, PA_ERROR_PROTOCOL); + goto finish; } if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) - return; + goto finish; c->error = PA_ERROR_KILLED; - stream_dead(s); + pa_stream_set_state(s, PA_STREAM_FAILED); + +finish: + pa_context_unref(c); } -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +void pa_command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_stream *s; struct pa_context *c = userdata; uint32_t bytes, channel; assert(pd && command == PA_COMMAND_REQUEST && t && c); + pa_context_ref(c); + if (pa_tagstruct_getu32(t, &channel) < 0 || pa_tagstruct_getu32(t, &bytes) < 0 || !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; + pa_context_fail(c, PA_ERROR_PROTOCOL); + goto finish; } if (!(s = pa_dynarray_get(c->playback_streams, channel))) - return; + goto finish; - if (s->state != STREAM_READY) - return; + if (s->state != PA_STREAM_READY) + goto finish; + + pa_stream_ref(s); s->requested_bytes += bytes; if (s->requested_bytes && s->write_callback) s->write_callback(s, s->requested_bytes, s->write_userdata); + + pa_stream_unref(s); + +finish: + pa_context_unref(c); } -static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_stream *s = userdata; - assert(pd && s && s->state == STREAM_CREATING); + assert(pd && s && s->state == PA_STREAM_CREATING); + pa_stream_ref(s); + if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - if (s->create_complete_callback) - s->create_complete_callback(s, 0, s->create_complete_userdata); - - return; + if (pa_context_handle_error(s->context, command, t) < 0) + goto finish; + + pa_stream_set_state(s, PA_STREAM_FAILED); + goto finish; } if (pa_tagstruct_getu32(t, &s->channel) < 0 || ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; + pa_context_fail(s->context, PA_ERROR_PROTOCOL); + goto finish; } s->channel_valid = 1; pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - - s->state = STREAM_READY; - if (s->create_complete_callback) - s->create_complete_callback(s, 1, s->create_complete_userdata); + pa_stream_set_state(s, PA_STREAM_READY); + +finish: + pa_stream_unref(s); } -static void create_stream(struct pa_stream *s, const char *dev) { +static void create_stream(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) { struct pa_tagstruct *t; uint32_t tag; - assert(s); + assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED); - s->state = STREAM_CREATING; + pa_stream_ref(s); + + if (attr) + s->buffer_attr = *attr; + else { + s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; + s->buffer_attr.tlength = DEFAULT_TLENGTH; + s->buffer_attr.prebuf = DEFAULT_PREBUF; + s->buffer_attr.minreq = DEFAULT_MINREQ; + s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; + } + + pa_stream_set_state(s, PA_STREAM_CREATING); t = pa_tagstruct_new(NULL, 0); assert(t); + + if (!dev) { + if (s->direction == PA_STREAM_PLAYBACK) + dev = getenv(ENV_DEFAULT_SINK); + else + dev = getenv(ENV_DEFAULT_SOURCE); + } pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); pa_tagstruct_putu32(t, tag = s->context->ctag++); @@ -609,135 +250,40 @@ static void create_stream(struct pa_stream *s, const char *dev) { pa_tagstruct_putu32(t, s->buffer_attr.fragsize); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s); + + pa_stream_unref(s); } -static struct pa_stream *internal_stream_new(struct pa_context *c) { - struct pa_stream *s; - - s = pa_xmalloc(sizeof(struct pa_stream)); - s->context = c; - - s->read_callback = NULL; - s->read_userdata = NULL; - s->write_callback = NULL; - s->write_userdata = NULL; - s->die_callback = NULL; - s->die_userdata = NULL; - s->create_complete_callback = NULL; - s->create_complete_userdata = NULL; - s->get_latency_callback = NULL; - s->get_latency_userdata = NULL; - s->finish_sample_callback = NULL; - s->finish_sample_userdata = NULL; - - s->name = NULL; - s->state = STREAM_CREATING; - s->requested_bytes = 0; - s->channel = 0; - s->channel_valid = 0; - s->device_index = (uint32_t) -1; - - memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - - s->next = c->first_stream; - if (s->next) - s->next->previous = s; - s->previous = NULL; - c->first_stream = s; - - return s; +void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) { + assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); + s->direction = PA_STREAM_PLAYBACK; + create_stream(s, dev, attr); } -struct pa_stream* pa_stream_new( - struct pa_context *c, - enum pa_stream_direction dir, - const char *dev, - const char *name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, - void (*complete) (struct pa_stream*s, int success, void *userdata), - void *userdata) { - - struct pa_stream *s; - - assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = complete; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = dir; - s->sample_spec = *ss; - if (attr) - s->buffer_attr = *attr; - else { - s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; - s->buffer_attr.tlength = DEFAULT_TLENGTH; - s->buffer_attr.prebuf = DEFAULT_PREBUF; - s->buffer_attr.minreq = DEFAULT_MINREQ; - s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; - } - - create_stream(s, dev); - - return s; +void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) { + assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); + s->direction = PA_STREAM_RECORD; + create_stream(s, dev, attr); } -void pa_stream_free(struct pa_stream *s) { - assert(s && s->context); - - if (s->context->pdispatch) - pa_pdispatch_unregister_reply(s->context->pdispatch, s); - - pa_xfree(s->name); - - if (s->channel_valid && s->context->state == CONTEXT_READY) { - struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : - (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); - pa_tagstruct_putu32(t, s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - } - - if (s->channel_valid) - pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - - if (s->next) - s->next->previous = s->previous; - if (s->previous) - s->previous->next = s->next; - else - s->context->first_stream = s->next; - - pa_xfree(s); -} - -void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { - s->write_callback = cb; - s->write_userdata = userdata; -} - -void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { +void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void (*free_cb)(void *p)) { struct pa_memchunk chunk; - assert(s && s->context && data && length && s->state == STREAM_READY); + assert(s && s->context && data && length && s->state == PA_STREAM_READY && s->ref >= 1); - chunk.memblock = pa_memblock_new(length); - assert(chunk.memblock && chunk.memblock->data); - memcpy(chunk.memblock->data, data, length); + if (free_cb) { + chunk.memblock = pa_memblock_new_user((void*) data, length, free_cb); + assert(chunk.memblock && chunk.memblock->data); + } else { + chunk.memblock = pa_memblock_new(length); + assert(chunk.memblock && chunk.memblock->data); + memcpy(chunk.memblock->data, data, length); + } chunk.index = 0; chunk.length = length; pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); pa_memblock_unref(chunk.memblock); - - /*fprintf(stderr, "Sent %u bytes\n", length);*/ if (length < s->requested_bytes) s->requested_bytes -= length; @@ -746,805 +292,163 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { } size_t pa_stream_writable_size(struct pa_stream *s) { - assert(s && s->state == STREAM_READY); + assert(s && s->state == PA_STREAM_READY && s->ref >= 1); return s->requested_bytes; } -void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { - assert(s && cb); - s->read_callback = cb; - s->read_userdata = userdata; -} - -int pa_stream_is_dead(struct pa_stream *s) { - return s->state == STREAM_DEAD; -} - -int pa_stream_is_ready(struct pa_stream*s) { - return s->state == STREAM_READY; -} - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { - assert(s); - s->die_callback = cb; - s->die_userdata = userdata; -} - -int pa_context_is_pending(struct pa_context *c) { - assert(c); - - if (c->state != CONTEXT_READY) - return 0; - - return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); -} - -struct pa_context* pa_stream_get_context(struct pa_stream *p) { - assert(p); - return p->context; -} - -static void set_dispatch_callbacks(struct pa_context *c); - -static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void set_dispatch_callbacks(struct pa_context *c) { - assert(c && c->state == CONTEXT_READY); - - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - - if (pa_pdispatch_is_pending(c->pdispatch)) { - pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); - return; - } - - if (pa_pstream_is_pending(c->pstream)) { - pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); - return; - } - - assert(c->drain_complete_callback); - c->drain_complete_callback(c, c->drain_complete_userdata); -} - -int pa_context_drain( - struct pa_context *c, - void (*complete) (struct pa_context*c, void *userdata), - void *userdata) { - - assert(c && c->state == CONTEXT_READY); - - if (complete == NULL) { - c->drain_complete_callback = NULL; - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - return 0; - } - - if (!pa_context_is_pending(c)) - return -1; - - c->drain_complete_callback = complete; - c->drain_complete_userdata = userdata; - - set_dispatch_callbacks(c); - - return 0; -} - -static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - return; - } - - if (s->state != STREAM_READY) - return; - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->drain_complete_callback) { - void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; - s->drain_complete_callback = NULL; - temp(s, s->drain_complete_userdata); - } -} - - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { +struct pa_operation * pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_operation *o; struct pa_tagstruct *t; uint32_t tag; - assert(s && s->state == STREAM_READY); + assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); - if (!complete) { - s->drain_complete_callback = NULL; - return; - } - - s->drain_complete_callback = complete; - s->drain_complete_userdata = userdata; + o = pa_operation_new(s->context, s); + assert(o); + o->callback = cb; + o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); -} + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); -void pa_context_exit(struct pa_context *c) { - struct pa_tagstruct *t; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_EXIT); - pa_tagstruct_putu32(t, c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - uint32_t total, count; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &count) < 0 || - pa_tagstruct_getu32(t, &total) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, count, total, c->stat_userdata); -} - -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - c->stat_callback = cb; - c->stat_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_STAT); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); + return pa_operation_ref(o); } static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; + struct pa_operation *o = userdata; uint32_t latency; - assert(pd && s); + assert(pd && o && o->stream && o->context); if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; - if (s->get_latency_callback) - s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); - return; + latency = (uint32_t) -1; + } else if (pa_tagstruct_getu32(t, &latency) < 0 || !pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; } - if (pa_tagstruct_getu32(t, &latency) < 0 || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; + if (o->callback) { + void (*cb)(struct pa_stream *s, uint32_t latency, void *userdata) = o->callback; + cb(o->stream, latency, o->userdata); } - if (s->get_latency_callback) - s->get_latency_callback(s, latency, s->get_latency_userdata); +finish: + pa_operation_done(o); + pa_operation_unref(o); } -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { +struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { uint32_t tag; + struct pa_operation *o; struct pa_tagstruct *t; - p->get_latency_callback = cb; - p->get_latency_userdata = userdata; + o = pa_operation_new(s->context, s); + assert(o); + o->callback = cb; + o->userdata = userdata; - if (cb == NULL) - return; - t = pa_tagstruct_new(NULL, 0); assert(t); pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, o); + + return pa_operation_ref(o); } -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_stream *s; - struct pa_tagstruct *t; - uint32_t tag; - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = cb; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = PA_STREAM_UPLOAD; - s->sample_spec = *ss; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_tagstruct_put_sample_spec(t, ss); - pa_tagstruct_putu32(t, length); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); - - return s; -} - -static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +void pa_stream_disconnect_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_stream *s = userdata; - assert(pd && s); + assert(pd && s && s->ref >= 1); + + pa_stream_ref(s); if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } + if (pa_context_handle_error(s->context, command, t) < 0) + goto finish; - if (s->finish_sample_callback) - s->finish_sample_callback(s, 0, s->finish_sample_userdata); - return; + pa_stream_set_state(s, PA_STREAM_FAILED); + goto finish; + } else if (!pa_tagstruct_eof(t)) { + pa_context_fail(s->context, PA_ERROR_PROTOCOL); + goto finish; } - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } + pa_stream_set_state(s, PA_STREAM_TERMINATED); - if (s->finish_sample_callback) - s->finish_sample_callback(s, 1, s->finish_sample_userdata); +finish: + pa_stream_unref(s); } -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { +void pa_stream_disconnect(struct pa_stream *s) { struct pa_tagstruct *t; uint32_t tag; - assert(p); - - p->finish_sample_callback = cb; - p->finish_sample_userdata = userdata; + assert(s && s->ref >= 1); + if (!s->channel_valid || !s->context->state == PA_CONTEXT_READY) + return; + + pa_stream_ref(s); + t = pa_tagstruct_new(NULL, 0); assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); + + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s); + + pa_stream_unref(s); } -static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); +void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { + assert(s && s->ref >= 1); + s->read_callback = cb; + s->read_userdata = userdata; +} + +void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { + assert(s && s->ref >= 1); + s->write_callback = cb; + s->write_userdata = userdata; +} + +void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { + assert(s && s->ref >= 1); + s->state_callback = cb; + s->state_userdata = userdata; +} + +void pa_stream_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_operation *o = userdata; + int success = 1; + assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; - if (c->play_sample_callback) - c->play_sample_callback(c, 0, c->play_sample_userdata); - return; + success = 0; + } else if (!pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; } - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; + if (o->callback) { + void (*cb)(struct pa_stream *s, int success, void *userdata) = o->callback; + cb(o->stream, success, o->userdata); } - if (c->play_sample_callback) - c->play_sample_callback(c, 1, c->play_sample_userdata); -} - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name && *name && (!dev || *dev)); - - c->play_sample_callback = cb; - c->play_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, volume); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); -} - -static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 0, c->remove_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 1, c->remove_sample_userdata); -} - -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name); - - c->remove_sample_callback = cb; - c->remove_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); -} - -static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_server_info i; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, NULL, c->get_server_info_userdata); - return; - } - - if (pa_tagstruct_gets(t, &i.server_name) < 0 || - pa_tagstruct_gets(t, &i.server_version) < 0 || - pa_tagstruct_gets(t, &i.user_name) < 0 || - pa_tagstruct_gets(t, &i.host_name) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, &i, c->get_server_info_userdata); -} - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_server_info_callback = cb; - c->get_server_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); -} - -static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_sink_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.monitor_source) < 0 || - pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); -} - -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_source_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || - pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); -} - -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { - struct pa_tagstruct *t; - assert(c); - - c->subscribe_callback = cb; - c->subscribe_userdata = userdata; - c->subscribe_mask = m; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); - pa_tagstruct_putu32(t, c->ctag++); - pa_tagstruct_putu32(t, cb ? m : 0); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - enum pa_subscription_event_type e; - uint32_t index; - assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); - - if (pa_tagstruct_getu32(t, &e) < 0 || - pa_tagstruct_getu32(t, &index) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) - c->subscribe_callback(c, e, index, c->subscribe_userdata); -} - -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_client_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.protocol_name) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); -} - - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_module_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.argument) < 0 || - pa_tagstruct_getu32(t, &i.n_used) < 0 || - pa_tagstruct_getu32(t, &i.auto_unload) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); -} - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} - -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +finish: + pa_operation_done(o); + pa_operation_unref(o); } diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index a0dd9f9cb..41801c6c4 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibhfoo -#define foopolyplibhfoo +#ifndef foopolyplibstreamhfoo +#define foopolyplibstreamhfoo /* $Id$ */ @@ -26,153 +26,79 @@ #include "sample.h" #include "polyplib-def.h" -#include "mainloop-api.h" +#include "cdecl.h" +#include "polyplib-operation.h" -#ifdef __cplusplus -//extern "C" { -#endif +/** \file + * Audio streams for input, output and sample upload */ -struct pa_context; +PA_C_DECL_BEGIN + +/** The state of a stream */ +enum pa_stream_state { + PA_STREAM_DISCONNECTED, /**< The stream is not yet connected to any sink or source */ + PA_STREAM_CREATING, /**< The stream is being created */ + PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */ + PA_STREAM_FAILED, /**< An error occured that made the stream invalid */ + PA_STREAM_TERMINATED, /**< The stream has been terminated cleanly */ +}; + +/** \struct pa_stream + * A stream for playback or recording */ struct pa_stream; -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); -void pa_context_unref(struct pa_context *c); -struct pa_context* pa_context_ref(struct pa_context *c); +/** Create a new, unconnected stream with the specified name and sample type */ +struct pa_stream* pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss); -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); -int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); - -int pa_context_is_dead(struct pa_context *c); -int pa_context_is_ready(struct pa_context *c); -int pa_context_errno(struct pa_context *c); - -int pa_context_is_pending(struct pa_context *c); - -struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); +/** Decrease the reference counter by one */ void pa_stream_unref(struct pa_stream *s); + +/** Increase the reference counter by one */ struct pa_stream *pa_stream_ref(struct pa_stream *s); -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); - -void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); -void pa_stream_write(struct pa_stream *p, const void *data, size_t length); -size_t pa_stream_writable_size(struct pa_stream *p); - -void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); - -int pa_stream_is_dead(struct pa_stream *p); -int pa_stream_is_ready(struct pa_stream*p); - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); +/** Return the current state of the stream */ +enum pa_stream_state pa_stream_get_state(struct pa_stream *p); +/** Return the context this stream is attached to */ struct pa_context* pa_stream_get_context(struct pa_stream *p); +/** Return the device (sink input or source output) index this stream is connected to */ uint32_t pa_stream_get_index(struct pa_stream *s); -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); +/** Connect the stream to a sink */ +void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr); -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +/** Connect the stream to a source */ +void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr); -struct pa_sink_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t volume; - uint32_t monitor_source; - const char *monitor_source_name; - uint32_t latency; -}; +/** Disconnect a stream from a source/sink */ +void pa_stream_disconnect(struct pa_stream *s); -void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +/** Write some data to the server (for playback sinks), if free_cb is + * non-NULL this routine is called when all data has been written out + * and an internal reference to the specified data is kept, the data + * is not copied. If NULL, the data is copied into an internal + * buffer. */ +void pa_stream_write(struct pa_stream *p, const void *data, size_t length, void (*free_cb)(void *p)); -struct pa_source_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t monitor_of_sink; - const char *monitor_of_sink_name; -}; +/** Return the amount of bytes that may be written using pa_stream_write() */ +size_t pa_stream_writable_size(struct pa_stream *p); -void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +/** Drain a playback stream */ +struct pa_operation* pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); -struct pa_server_info { - const char *user_name; - const char *host_name; - const char *server_version; - const char *server_name; - struct pa_sample_spec sample_spec; -}; +/** Get the playback latency of a stream */ +struct pa_operation* pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); +/** Set the callback function that is called whenever the state of the stream changes */ +void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); -struct pa_module_info { - uint32_t index; - const char*name, *argument; - uint32_t n_used, auto_unload; -}; +/** Set the callback function that is called when new data may be written to the stream */ +void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +/** Set the callback function that is called when new data is available from the stream */ +void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); -struct pa_client_info { - uint32_t index; - const char *name; - uint32_t owner_module; - const char *protocol_name; -}; - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); - -struct pa_sink_input_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t sink; - struct pa_sample_spec sample_spec; - uint32_t volume; - uint32_t latency; -}; - -void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); - -struct pa_source_output_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t source; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); - -void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -void pa_context_exit(struct pa_context *c); -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); - -#ifdef __cplusplus -} -#endif +PA_C_DECL_END #endif diff --git a/polyp/polyplib-subscribe.c b/polyp/polyplib-subscribe.c index 35001d3d3..a14d0b064 100644 --- a/polyp/polyplib-subscribe.c +++ b/polyp/polyplib-subscribe.c @@ -23,1528 +23,52 @@ #include #endif -#include #include -#include -#include -#include -#include -#include -#include "polyplib.h" -#include "native-common.h" -#include "pdispatch.h" -#include "pstream.h" -#include "dynarray.h" -#include "socket-client.h" +#include "polyplib-subscribe.h" +#include "polyplib-internal.h" #include "pstream-util.h" -#include "authkey.h" -#include "util.h" -#include "xmalloc.h" -#define DEFAULT_MAXLENGTH 204800 -#define DEFAULT_TLENGTH 10240 -#define DEFAULT_PREBUF 4096 -#define DEFAULT_MINREQ 1024 -#define DEFAULT_FRAGSIZE 1024 - -#define DEFAULT_TIMEOUT (5*60) -#define DEFAULT_SERVER "/tmp/polypaudio/native" -#define DEFAULT_PORT "4713" - -struct pa_context { - char *name; - struct pa_mainloop_api* mainloop; - struct pa_socket_client *client; - struct pa_pstream *pstream; - struct pa_pdispatch *pdispatch; - struct pa_dynarray *record_streams, *playback_streams; - struct pa_stream *first_stream; - uint32_t ctag; - uint32_t error; - enum { - CONTEXT_UNCONNECTED, - CONTEXT_CONNECTING, - CONTEXT_AUTHORIZING, - CONTEXT_SETTING_NAME, - CONTEXT_READY, - CONTEXT_DEAD - } state; - - void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); - void *connect_complete_userdata; - - void (*drain_complete_callback)(struct pa_context*c, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_context*c, void *userdata); - void *die_userdata; - - void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); - void *stat_userdata; - - void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); - void *play_sample_userdata; - - void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); - void *remove_sample_userdata; - - void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); - void *get_server_info_userdata; - - void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); - void *get_sink_info_userdata; - - void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); - void *get_source_info_userdata; - - void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); - void *subscribe_userdata; - enum pa_subscription_mask subscribe_mask; - - void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); - void *get_client_info_userdata; - - void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); - void *get_module_info_userdata; - - uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; -}; - -struct pa_stream { - struct pa_context *context; - struct pa_stream *next, *previous; - - char *name; - struct pa_buffer_attr buffer_attr; - struct pa_sample_spec sample_spec; - uint32_t channel; - int channel_valid; - uint32_t device_index; - enum pa_stream_direction direction; - - enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; - uint32_t requested_bytes; - - void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); - void *read_userdata; - - void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); - void *write_userdata; - - void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); - void *create_complete_userdata; - - void (*drain_complete_callback)(struct pa_stream *s, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_stream*c, void *userdata); - void *die_userdata; - - void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); - void *get_latency_userdata; - - void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); - void *finish_sample_userdata; -}; - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); - -static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { - [PA_COMMAND_ERROR] = { NULL }, - [PA_COMMAND_REPLY] = { NULL }, - [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_EXIT] = { NULL }, - [PA_COMMAND_REQUEST] = { command_request }, - [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, -}; - -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { - struct pa_context *c; - assert(mainloop && name); - - c = pa_xmalloc(sizeof(struct pa_context)); - c->name = pa_xstrdup(name); - c->mainloop = mainloop; - c->client = NULL; - c->pstream = NULL; - c->pdispatch = NULL; - c->playback_streams = pa_dynarray_new(); - assert(c->playback_streams); - c->record_streams = pa_dynarray_new(); - assert(c->record_streams); - c->first_stream = NULL; - c->error = PA_ERROR_OK; - c->state = CONTEXT_UNCONNECTED; - c->ctag = 0; - - c->connect_complete_callback = NULL; - c->connect_complete_userdata = NULL; - - c->drain_complete_callback = NULL; - c->drain_complete_userdata = NULL; - - c->die_callback = NULL; - c->die_userdata = NULL; - - c->stat_callback = NULL; - c->stat_userdata = NULL; - - c->play_sample_callback = NULL; - c->play_sample_userdata = NULL; - - c->remove_sample_callback = NULL; - c->remove_sample_userdata = NULL; - - c->get_server_info_callback = NULL; - c->get_server_info_userdata = NULL; - - c->get_sink_info_callback = NULL; - c->get_sink_info_userdata = NULL; - - c->get_source_info_callback = NULL; - c->get_source_info_userdata = NULL; - - c->subscribe_callback = NULL; - c->subscribe_userdata = NULL; - - c->get_client_info_callback = NULL; - c->get_client_info_userdata = NULL; - - c->get_module_info_callback = NULL; - c->get_module_info_userdata = NULL; - - pa_check_for_sigpipe(); - return c; -} - -void pa_context_free(struct pa_context *c) { - assert(c); - - while (c->first_stream) - pa_stream_free(c->first_stream); - - if (c->client) - pa_socket_client_free(c->client); - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - if (c->pstream) - pa_pstream_free(c->pstream); - if (c->record_streams) - pa_dynarray_free(c->record_streams, NULL, NULL); - if (c->playback_streams) - pa_dynarray_free(c->playback_streams, NULL, NULL); - - pa_xfree(c->name); - pa_xfree(c); -} - -static void stream_dead(struct pa_stream *s) { - assert(s); - - if (s->state == STREAM_DEAD) - return; - - if (s->state == STREAM_READY) { - s->state = STREAM_DEAD; - if (s->die_callback) - s->die_callback(s, s->die_userdata); - } else - s->state = STREAM_DEAD; -} - -static void context_dead(struct pa_context *c) { - struct pa_stream *s; - assert(c); - - if (c->state == CONTEXT_DEAD) - return; - - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - c->pdispatch = NULL; - - if (c->pstream) - pa_pstream_free(c->pstream); - c->pstream = NULL; - - if (c->client) - pa_socket_client_free(c->client); - c->client = NULL; - - for (s = c->first_stream; s; s = s->next) - stream_dead(s); - - if (c->state == CONTEXT_READY) { - c->state = CONTEXT_DEAD; - if (c->die_callback) - c->die_callback(c, c->die_userdata); - } else - c->state = CONTEXT_DEAD; -} - -static void pstream_die_callback(struct pa_pstream *p, void *userdata) { - struct pa_context *c = userdata; - assert(p && c); - c->error = PA_ERROR_CONNECTIONTERMINATED; - context_dead(c); -} - -static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { - struct pa_context *c = userdata; - assert(p && packet && c); - - if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - fprintf(stderr, "polyp.c: invalid packet.\n"); - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - } -} - -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - assert(p && chunk && c && chunk->memblock && chunk->memblock->data); - - if (!(s = pa_dynarray_get(c->record_streams, channel))) - return; - - if (s->read_callback) - s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); -} - -static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { - assert(c && t); - - if (command == PA_COMMAND_ERROR) { - if (pa_tagstruct_getu32(t, &c->error) < 0) { - c->error = PA_ERROR_PROTOCOL; - return -1; - } - - return 0; - } - - c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; - return -1; -} - -static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); - - if (command != PA_COMMAND_REPLY) { - handle_error(c, command, t); - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - if (c->state == CONTEXT_AUTHORIZING) { - struct pa_tagstruct *t; - c->state = CONTEXT_SETTING_NAME; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, c->name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - } else { - assert(c->state == CONTEXT_SETTING_NAME); - - c->state = CONTEXT_READY; - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 1, c->connect_complete_userdata); - } - - return; -} - -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { - struct pa_context *c = userdata; - struct pa_tagstruct *t; - uint32_t tag; - assert(client && c && c->state == CONTEXT_CONNECTING); - - pa_socket_client_free(client); - c->client = NULL; - - if (!io) { - c->error = PA_ERROR_CONNECTIONREFUSED; - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - c->pstream = pa_pstream_new(c->mainloop, io); - assert(c->pstream); - pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); - pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); - pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); - - c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); - assert(c->pdispatch); - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_AUTH); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - c->state = CONTEXT_AUTHORIZING; -} - -static struct sockaddr *resolve_server(const char *server, size_t *len) { - struct sockaddr *sa; - struct addrinfo hints, *result = NULL; - char *port; - assert(server && len); - - if ((port = strrchr(server, ':'))) - port++; - if (!port) - port = DEFAULT_PORT; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(server, port, &hints, &result) != 0) - return NULL; - assert(result); - - sa = pa_xmalloc(*len = result->ai_addrlen); - memcpy(sa, result->ai_addr, *len); - - freeaddrinfo(result); - - return sa; -} - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { - assert(c && c->state == CONTEXT_UNCONNECTED); - - if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { - c->error = PA_ERROR_AUTHKEY; - return -1; - } - - if (!server) - if (!(server = getenv("POLYP_SERVER"))) - server = DEFAULT_SERVER; - - assert(!c->client); - - if (*server == '/') { - if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } else { - struct sockaddr* sa; - size_t sa_len; - - if (!(sa = resolve_server(server, &sa_len))) { - c->error = PA_ERROR_INVALIDSERVER; - return -1; - } - - c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); - pa_xfree(sa); - - if (!c->client) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } - - c->connect_complete_callback = complete; - c->connect_complete_userdata = userdata; - - pa_socket_client_set_callback(c->client, on_connection, c); - c->state = CONTEXT_CONNECTING; - - return 0; -} - -int pa_context_is_dead(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_DEAD; -} - -int pa_context_is_ready(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_READY; -} - -int pa_context_errno(struct pa_context *c) { - assert(c); - return c->error; -} - -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { - assert(c); - c->die_callback = cb; - c->die_userdata = userdata; -} - -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - uint32_t channel; - assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) - return; - - c->error = PA_ERROR_KILLED; - stream_dead(s); -} - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s; - struct pa_context *c = userdata; - uint32_t bytes, channel; - assert(pd && command == PA_COMMAND_REQUEST && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - pa_tagstruct_getu32(t, &bytes) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(c->playback_streams, channel))) - return; - - if (s->state != STREAM_READY) - return; - - s->requested_bytes += bytes; - - if (s->requested_bytes && s->write_callback) - s->write_callback(s, s->requested_bytes, s->write_userdata); -} - -static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s && s->state == STREAM_CREATING); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - if (s->create_complete_callback) - s->create_complete_callback(s, 0, s->create_complete_userdata); - - return; - } - - if (pa_tagstruct_getu32(t, &s->channel) < 0 || - ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - s->channel_valid = 1; - pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - - s->state = STREAM_READY; - if (s->create_complete_callback) - s->create_complete_callback(s, 1, s->create_complete_userdata); -} - -static void create_stream(struct pa_stream *s, const char *dev) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s); - - s->state = STREAM_CREATING; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_puts(t, s->name); - pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, s->buffer_attr.maxlength); - if (s->direction == PA_STREAM_PLAYBACK) { - pa_tagstruct_putu32(t, s->buffer_attr.tlength); - pa_tagstruct_putu32(t, s->buffer_attr.prebuf); - pa_tagstruct_putu32(t, s->buffer_attr.minreq); - } else - pa_tagstruct_putu32(t, s->buffer_attr.fragsize); - - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); -} - -static struct pa_stream *internal_stream_new(struct pa_context *c) { - struct pa_stream *s; - - s = pa_xmalloc(sizeof(struct pa_stream)); - s->context = c; - - s->read_callback = NULL; - s->read_userdata = NULL; - s->write_callback = NULL; - s->write_userdata = NULL; - s->die_callback = NULL; - s->die_userdata = NULL; - s->create_complete_callback = NULL; - s->create_complete_userdata = NULL; - s->get_latency_callback = NULL; - s->get_latency_userdata = NULL; - s->finish_sample_callback = NULL; - s->finish_sample_userdata = NULL; - - s->name = NULL; - s->state = STREAM_CREATING; - s->requested_bytes = 0; - s->channel = 0; - s->channel_valid = 0; - s->device_index = (uint32_t) -1; - - memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - - s->next = c->first_stream; - if (s->next) - s->next->previous = s; - s->previous = NULL; - c->first_stream = s; - - return s; -} - -struct pa_stream* pa_stream_new( - struct pa_context *c, - enum pa_stream_direction dir, - const char *dev, - const char *name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, - void (*complete) (struct pa_stream*s, int success, void *userdata), - void *userdata) { - - struct pa_stream *s; - - assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = complete; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = dir; - s->sample_spec = *ss; - if (attr) - s->buffer_attr = *attr; - else { - s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; - s->buffer_attr.tlength = DEFAULT_TLENGTH; - s->buffer_attr.prebuf = DEFAULT_PREBUF; - s->buffer_attr.minreq = DEFAULT_MINREQ; - s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; - } - - create_stream(s, dev); - - return s; -} - -void pa_stream_free(struct pa_stream *s) { - assert(s && s->context); - - if (s->context->pdispatch) - pa_pdispatch_unregister_reply(s->context->pdispatch, s); - - pa_xfree(s->name); - - if (s->channel_valid && s->context->state == CONTEXT_READY) { - struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : - (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); - pa_tagstruct_putu32(t, s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - } - - if (s->channel_valid) - pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - - if (s->next) - s->next->previous = s->previous; - if (s->previous) - s->previous->next = s->next; - else - s->context->first_stream = s->next; - - pa_xfree(s); -} - -void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { - s->write_callback = cb; - s->write_userdata = userdata; -} - -void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { - struct pa_memchunk chunk; - assert(s && s->context && data && length && s->state == STREAM_READY); - - chunk.memblock = pa_memblock_new(length); - assert(chunk.memblock && chunk.memblock->data); - memcpy(chunk.memblock->data, data, length); - chunk.index = 0; - chunk.length = length; - - pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); - pa_memblock_unref(chunk.memblock); - - /*fprintf(stderr, "Sent %u bytes\n", length);*/ - - if (length < s->requested_bytes) - s->requested_bytes -= length; - else - s->requested_bytes = 0; -} - -size_t pa_stream_writable_size(struct pa_stream *s) { - assert(s && s->state == STREAM_READY); - return s->requested_bytes; -} - -void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { - assert(s && cb); - s->read_callback = cb; - s->read_userdata = userdata; -} - -int pa_stream_is_dead(struct pa_stream *s) { - return s->state == STREAM_DEAD; -} - -int pa_stream_is_ready(struct pa_stream*s) { - return s->state == STREAM_READY; -} - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { - assert(s); - s->die_callback = cb; - s->die_userdata = userdata; -} - -int pa_context_is_pending(struct pa_context *c) { - assert(c); - - if (c->state != CONTEXT_READY) - return 0; - - return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); -} - -struct pa_context* pa_stream_get_context(struct pa_stream *p) { - assert(p); - return p->context; -} - -static void set_dispatch_callbacks(struct pa_context *c); - -static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void set_dispatch_callbacks(struct pa_context *c) { - assert(c && c->state == CONTEXT_READY); - - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - - if (pa_pdispatch_is_pending(c->pdispatch)) { - pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); - return; - } - - if (pa_pstream_is_pending(c->pstream)) { - pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); - return; - } - - assert(c->drain_complete_callback); - c->drain_complete_callback(c, c->drain_complete_userdata); -} - -int pa_context_drain( - struct pa_context *c, - void (*complete) (struct pa_context*c, void *userdata), - void *userdata) { - - assert(c && c->state == CONTEXT_READY); - - if (complete == NULL) { - c->drain_complete_callback = NULL; - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - return 0; - } - - if (!pa_context_is_pending(c)) - return -1; - - c->drain_complete_callback = complete; - c->drain_complete_userdata = userdata; - - set_dispatch_callbacks(c); - - return 0; -} - -static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - return; - } - - if (s->state != STREAM_READY) - return; - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->drain_complete_callback) { - void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; - s->drain_complete_callback = NULL; - temp(s, s->drain_complete_userdata); - } -} - - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s && s->state == STREAM_READY); - - if (!complete) { - s->drain_complete_callback = NULL; - return; - } - - s->drain_complete_callback = complete; - s->drain_complete_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); -} - -void pa_context_exit(struct pa_context *c) { - struct pa_tagstruct *t; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_EXIT); - pa_tagstruct_putu32(t, c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - uint32_t total, count; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &count) < 0 || - pa_tagstruct_getu32(t, &total) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, count, total, c->stat_userdata); -} - -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - c->stat_callback = cb; - c->stat_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_STAT); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); -} - -static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - uint32_t latency; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &latency) < 0 || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, latency, s->get_latency_userdata); -} - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - p->get_latency_callback = cb; - p->get_latency_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); -} - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_stream *s; - struct pa_tagstruct *t; - uint32_t tag; - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = cb; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = PA_STREAM_UPLOAD; - s->sample_spec = *ss; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_tagstruct_put_sample_spec(t, ss); - pa_tagstruct_putu32(t, length); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); - - return s; -} - -static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 0, s->finish_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 1, s->finish_sample_userdata); -} - -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(p); - - p->finish_sample_callback = cb; - p->finish_sample_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); -} - -static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 0, c->play_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 1, c->play_sample_userdata); -} - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name && *name && (!dev || *dev)); - - c->play_sample_callback = cb; - c->play_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, volume); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); -} - -static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 0, c->remove_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 1, c->remove_sample_userdata); -} - -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name); - - c->remove_sample_callback = cb; - c->remove_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); -} - -static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_server_info i; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, NULL, c->get_server_info_userdata); - return; - } - - if (pa_tagstruct_gets(t, &i.server_name) < 0 || - pa_tagstruct_gets(t, &i.server_version) < 0 || - pa_tagstruct_gets(t, &i.user_name) < 0 || - pa_tagstruct_gets(t, &i.host_name) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, &i, c->get_server_info_userdata); -} - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_server_info_callback = cb; - c->get_server_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); -} - -static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_sink_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.monitor_source) < 0 || - pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); -} - -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_source_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || - pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); -} - -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { - struct pa_tagstruct *t; - assert(c); - - c->subscribe_callback = cb; - c->subscribe_userdata = userdata; - c->subscribe_mask = m; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); - pa_tagstruct_putu32(t, c->ctag++); - pa_tagstruct_putu32(t, cb ? m : 0); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +void pa_command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_context *c = userdata; enum pa_subscription_event_type e; uint32_t index; assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); + pa_context_ref(c); + if (pa_tagstruct_getu32(t, &e) < 0 || pa_tagstruct_getu32(t, &index) < 0 || !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; + pa_context_fail(c, PA_ERROR_PROTOCOL); + goto finish; } - if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) + if (c->subscribe_callback) c->subscribe_callback(c, e, index, c->subscribe_userdata); + +finish: + pa_context_unref(c); } -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + +struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_operation *o; struct pa_tagstruct *t; uint32_t tag; assert(c); - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; - if (!cb) - return; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); + pa_tagstruct_putu32(t, cb ? m : 0); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); } -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_client_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.protocol_name) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); -} - - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_module_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.argument) < 0 || - pa_tagstruct_getu32(t, &i.n_used) < 0 || - pa_tagstruct_getu32(t, &i.auto_unload) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); -} - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} - -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} diff --git a/polyp/polyplib-subscribe.h b/polyp/polyplib-subscribe.h index a0dd9f9cb..563849151 100644 --- a/polyp/polyplib-subscribe.h +++ b/polyp/polyplib-subscribe.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibhfoo -#define foopolyplibhfoo +#ifndef foopolyplibsubscribehfoo +#define foopolyplibsubscribehfoo /* $Id$ */ @@ -22,157 +22,17 @@ USA. ***/ -#include +#include -#include "sample.h" #include "polyplib-def.h" -#include "mainloop-api.h" +#include "polyplib-context.h" +#include "cdecl.h" -#ifdef __cplusplus -//extern "C" { -#endif +PA_C_DECL_BEGIN -struct pa_context; -struct pa_stream; +struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +void pa_context_set_subscribe_callback(struct pa_context *c, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); -void pa_context_unref(struct pa_context *c); -struct pa_context* pa_context_ref(struct pa_context *c); - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); -int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); - -int pa_context_is_dead(struct pa_context *c); -int pa_context_is_ready(struct pa_context *c); -int pa_context_errno(struct pa_context *c); - -int pa_context_is_pending(struct pa_context *c); - -struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_unref(struct pa_stream *s); -struct pa_stream *pa_stream_ref(struct pa_stream *s); - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); - -void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); -void pa_stream_write(struct pa_stream *p, const void *data, size_t length); -size_t pa_stream_writable_size(struct pa_stream *p); - -void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); - -int pa_stream_is_dead(struct pa_stream *p); -int pa_stream_is_ready(struct pa_stream*p); - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); - -struct pa_context* pa_stream_get_context(struct pa_stream *p); - -uint32_t pa_stream_get_index(struct pa_stream *s); - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -struct pa_sink_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t volume; - uint32_t monitor_source; - const char *monitor_source_name; - uint32_t latency; -}; - -void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); - -struct pa_source_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t monitor_of_sink; - const char *monitor_of_sink_name; -}; - -void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); - -struct pa_server_info { - const char *user_name; - const char *host_name; - const char *server_version; - const char *server_name; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); - -struct pa_module_info { - uint32_t index; - const char*name, *argument; - uint32_t n_used, auto_unload; -}; - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); - -struct pa_client_info { - uint32_t index; - const char *name; - uint32_t owner_module; - const char *protocol_name; -}; - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); - -struct pa_sink_input_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t sink; - struct pa_sample_spec sample_spec; - uint32_t volume; - uint32_t latency; -}; - -void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); - -struct pa_source_output_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t source; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); - -void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -void pa_context_exit(struct pa_context *c); -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); - -#ifdef __cplusplus -} -#endif +PA_C_DECL_END #endif diff --git a/polyp/polyplib.c b/polyp/polyplib.c deleted file mode 100644 index 35001d3d3..000000000 --- a/polyp/polyplib.c +++ /dev/null @@ -1,1550 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of polypaudio. - - polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - polypaudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "polyplib.h" -#include "native-common.h" -#include "pdispatch.h" -#include "pstream.h" -#include "dynarray.h" -#include "socket-client.h" -#include "pstream-util.h" -#include "authkey.h" -#include "util.h" -#include "xmalloc.h" - -#define DEFAULT_MAXLENGTH 204800 -#define DEFAULT_TLENGTH 10240 -#define DEFAULT_PREBUF 4096 -#define DEFAULT_MINREQ 1024 -#define DEFAULT_FRAGSIZE 1024 - -#define DEFAULT_TIMEOUT (5*60) -#define DEFAULT_SERVER "/tmp/polypaudio/native" -#define DEFAULT_PORT "4713" - -struct pa_context { - char *name; - struct pa_mainloop_api* mainloop; - struct pa_socket_client *client; - struct pa_pstream *pstream; - struct pa_pdispatch *pdispatch; - struct pa_dynarray *record_streams, *playback_streams; - struct pa_stream *first_stream; - uint32_t ctag; - uint32_t error; - enum { - CONTEXT_UNCONNECTED, - CONTEXT_CONNECTING, - CONTEXT_AUTHORIZING, - CONTEXT_SETTING_NAME, - CONTEXT_READY, - CONTEXT_DEAD - } state; - - void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata); - void *connect_complete_userdata; - - void (*drain_complete_callback)(struct pa_context*c, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_context*c, void *userdata); - void *die_userdata; - - void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata); - void *stat_userdata; - - void (*play_sample_callback)(struct pa_context*c, int success, void *userdata); - void *play_sample_userdata; - - void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata); - void *remove_sample_userdata; - - void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata); - void *get_server_info_userdata; - - void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata); - void *get_sink_info_userdata; - - void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata); - void *get_source_info_userdata; - - void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); - void *subscribe_userdata; - enum pa_subscription_mask subscribe_mask; - - void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); - void *get_client_info_userdata; - - void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); - void *get_module_info_userdata; - - uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; -}; - -struct pa_stream { - struct pa_context *context; - struct pa_stream *next, *previous; - - char *name; - struct pa_buffer_attr buffer_attr; - struct pa_sample_spec sample_spec; - uint32_t channel; - int channel_valid; - uint32_t device_index; - enum pa_stream_direction direction; - - enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state; - uint32_t requested_bytes; - - void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); - void *read_userdata; - - void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); - void *write_userdata; - - void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata); - void *create_complete_userdata; - - void (*drain_complete_callback)(struct pa_stream *s, void *userdata); - void *drain_complete_userdata; - - void (*die_callback)(struct pa_stream*c, void *userdata); - void *die_userdata; - - void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); - void *get_latency_userdata; - - void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata); - void *finish_sample_userdata; -}; - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); - -static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { - [PA_COMMAND_ERROR] = { NULL }, - [PA_COMMAND_REPLY] = { NULL }, - [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL }, - [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL }, - [PA_COMMAND_EXIT] = { NULL }, - [PA_COMMAND_REQUEST] = { command_request }, - [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed }, - [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event }, -}; - -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { - struct pa_context *c; - assert(mainloop && name); - - c = pa_xmalloc(sizeof(struct pa_context)); - c->name = pa_xstrdup(name); - c->mainloop = mainloop; - c->client = NULL; - c->pstream = NULL; - c->pdispatch = NULL; - c->playback_streams = pa_dynarray_new(); - assert(c->playback_streams); - c->record_streams = pa_dynarray_new(); - assert(c->record_streams); - c->first_stream = NULL; - c->error = PA_ERROR_OK; - c->state = CONTEXT_UNCONNECTED; - c->ctag = 0; - - c->connect_complete_callback = NULL; - c->connect_complete_userdata = NULL; - - c->drain_complete_callback = NULL; - c->drain_complete_userdata = NULL; - - c->die_callback = NULL; - c->die_userdata = NULL; - - c->stat_callback = NULL; - c->stat_userdata = NULL; - - c->play_sample_callback = NULL; - c->play_sample_userdata = NULL; - - c->remove_sample_callback = NULL; - c->remove_sample_userdata = NULL; - - c->get_server_info_callback = NULL; - c->get_server_info_userdata = NULL; - - c->get_sink_info_callback = NULL; - c->get_sink_info_userdata = NULL; - - c->get_source_info_callback = NULL; - c->get_source_info_userdata = NULL; - - c->subscribe_callback = NULL; - c->subscribe_userdata = NULL; - - c->get_client_info_callback = NULL; - c->get_client_info_userdata = NULL; - - c->get_module_info_callback = NULL; - c->get_module_info_userdata = NULL; - - pa_check_for_sigpipe(); - return c; -} - -void pa_context_free(struct pa_context *c) { - assert(c); - - while (c->first_stream) - pa_stream_free(c->first_stream); - - if (c->client) - pa_socket_client_free(c->client); - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - if (c->pstream) - pa_pstream_free(c->pstream); - if (c->record_streams) - pa_dynarray_free(c->record_streams, NULL, NULL); - if (c->playback_streams) - pa_dynarray_free(c->playback_streams, NULL, NULL); - - pa_xfree(c->name); - pa_xfree(c); -} - -static void stream_dead(struct pa_stream *s) { - assert(s); - - if (s->state == STREAM_DEAD) - return; - - if (s->state == STREAM_READY) { - s->state = STREAM_DEAD; - if (s->die_callback) - s->die_callback(s, s->die_userdata); - } else - s->state = STREAM_DEAD; -} - -static void context_dead(struct pa_context *c) { - struct pa_stream *s; - assert(c); - - if (c->state == CONTEXT_DEAD) - return; - - if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - c->pdispatch = NULL; - - if (c->pstream) - pa_pstream_free(c->pstream); - c->pstream = NULL; - - if (c->client) - pa_socket_client_free(c->client); - c->client = NULL; - - for (s = c->first_stream; s; s = s->next) - stream_dead(s); - - if (c->state == CONTEXT_READY) { - c->state = CONTEXT_DEAD; - if (c->die_callback) - c->die_callback(c, c->die_userdata); - } else - c->state = CONTEXT_DEAD; -} - -static void pstream_die_callback(struct pa_pstream *p, void *userdata) { - struct pa_context *c = userdata; - assert(p && c); - c->error = PA_ERROR_CONNECTIONTERMINATED; - context_dead(c); -} - -static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { - struct pa_context *c = userdata; - assert(p && packet && c); - - if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - fprintf(stderr, "polyp.c: invalid packet.\n"); - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - } -} - -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - assert(p && chunk && c && chunk->memblock && chunk->memblock->data); - - if (!(s = pa_dynarray_get(c->record_streams, channel))) - return; - - if (s->read_callback) - s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); -} - -static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { - assert(c && t); - - if (command == PA_COMMAND_ERROR) { - if (pa_tagstruct_getu32(t, &c->error) < 0) { - c->error = PA_ERROR_PROTOCOL; - return -1; - } - - return 0; - } - - c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL; - return -1; -} - -static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME)); - - if (command != PA_COMMAND_REPLY) { - handle_error(c, command, t); - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - if (c->state == CONTEXT_AUTHORIZING) { - struct pa_tagstruct *t; - c->state = CONTEXT_SETTING_NAME; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, c->name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - } else { - assert(c->state == CONTEXT_SETTING_NAME); - - c->state = CONTEXT_READY; - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 1, c->connect_complete_userdata); - } - - return; -} - -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { - struct pa_context *c = userdata; - struct pa_tagstruct *t; - uint32_t tag; - assert(client && c && c->state == CONTEXT_CONNECTING); - - pa_socket_client_free(client); - c->client = NULL; - - if (!io) { - c->error = PA_ERROR_CONNECTIONREFUSED; - context_dead(c); - - if (c->connect_complete_callback) - c->connect_complete_callback(c, 0, c->connect_complete_userdata); - - return; - } - - c->pstream = pa_pstream_new(c->mainloop, io); - assert(c->pstream); - pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); - pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); - pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); - - c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); - assert(c->pdispatch); - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_AUTH); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); - c->state = CONTEXT_AUTHORIZING; -} - -static struct sockaddr *resolve_server(const char *server, size_t *len) { - struct sockaddr *sa; - struct addrinfo hints, *result = NULL; - char *port; - assert(server && len); - - if ((port = strrchr(server, ':'))) - port++; - if (!port) - port = DEFAULT_PORT; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(server, port, &hints, &result) != 0) - return NULL; - assert(result); - - sa = pa_xmalloc(*len = result->ai_addrlen); - memcpy(sa, result->ai_addr, *len); - - freeaddrinfo(result); - - return sa; -} - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) { - assert(c && c->state == CONTEXT_UNCONNECTED); - - if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { - c->error = PA_ERROR_AUTHKEY; - return -1; - } - - if (!server) - if (!(server = getenv("POLYP_SERVER"))) - server = DEFAULT_SERVER; - - assert(!c->client); - - if (*server == '/') { - if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } else { - struct sockaddr* sa; - size_t sa_len; - - if (!(sa = resolve_server(server, &sa_len))) { - c->error = PA_ERROR_INVALIDSERVER; - return -1; - } - - c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); - pa_xfree(sa); - - if (!c->client) { - c->error = PA_ERROR_CONNECTIONREFUSED; - return -1; - } - } - - c->connect_complete_callback = complete; - c->connect_complete_userdata = userdata; - - pa_socket_client_set_callback(c->client, on_connection, c); - c->state = CONTEXT_CONNECTING; - - return 0; -} - -int pa_context_is_dead(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_DEAD; -} - -int pa_context_is_ready(struct pa_context *c) { - assert(c); - return c->state == CONTEXT_READY; -} - -int pa_context_errno(struct pa_context *c) { - assert(c); - return c->error; -} - -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { - assert(c); - c->die_callback = cb; - c->die_userdata = userdata; -} - -static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; - uint32_t channel; - assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) - return; - - c->error = PA_ERROR_KILLED; - stream_dead(s); -} - -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s; - struct pa_context *c = userdata; - uint32_t bytes, channel; - assert(pd && command == PA_COMMAND_REQUEST && t && c); - - if (pa_tagstruct_getu32(t, &channel) < 0 || - pa_tagstruct_getu32(t, &bytes) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (!(s = pa_dynarray_get(c->playback_streams, channel))) - return; - - if (s->state != STREAM_READY) - return; - - s->requested_bytes += bytes; - - if (s->requested_bytes && s->write_callback) - s->write_callback(s, s->requested_bytes, s->write_userdata); -} - -static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s && s->state == STREAM_CREATING); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - if (s->create_complete_callback) - s->create_complete_callback(s, 0, s->create_complete_userdata); - - return; - } - - if (pa_tagstruct_getu32(t, &s->channel) < 0 || - ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - s->channel_valid = 1; - pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - - s->state = STREAM_READY; - if (s->create_complete_callback) - s->create_complete_callback(s, 1, s->create_complete_userdata); -} - -static void create_stream(struct pa_stream *s, const char *dev) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s); - - s->state = STREAM_CREATING; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_puts(t, s->name); - pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, s->buffer_attr.maxlength); - if (s->direction == PA_STREAM_PLAYBACK) { - pa_tagstruct_putu32(t, s->buffer_attr.tlength); - pa_tagstruct_putu32(t, s->buffer_attr.prebuf); - pa_tagstruct_putu32(t, s->buffer_attr.minreq); - } else - pa_tagstruct_putu32(t, s->buffer_attr.fragsize); - - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); -} - -static struct pa_stream *internal_stream_new(struct pa_context *c) { - struct pa_stream *s; - - s = pa_xmalloc(sizeof(struct pa_stream)); - s->context = c; - - s->read_callback = NULL; - s->read_userdata = NULL; - s->write_callback = NULL; - s->write_userdata = NULL; - s->die_callback = NULL; - s->die_userdata = NULL; - s->create_complete_callback = NULL; - s->create_complete_userdata = NULL; - s->get_latency_callback = NULL; - s->get_latency_userdata = NULL; - s->finish_sample_callback = NULL; - s->finish_sample_userdata = NULL; - - s->name = NULL; - s->state = STREAM_CREATING; - s->requested_bytes = 0; - s->channel = 0; - s->channel_valid = 0; - s->device_index = (uint32_t) -1; - - memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - - s->next = c->first_stream; - if (s->next) - s->next->previous = s; - s->previous = NULL; - c->first_stream = s; - - return s; -} - -struct pa_stream* pa_stream_new( - struct pa_context *c, - enum pa_stream_direction dir, - const char *dev, - const char *name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, - void (*complete) (struct pa_stream*s, int success, void *userdata), - void *userdata) { - - struct pa_stream *s; - - assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = complete; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = dir; - s->sample_spec = *ss; - if (attr) - s->buffer_attr = *attr; - else { - s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; - s->buffer_attr.tlength = DEFAULT_TLENGTH; - s->buffer_attr.prebuf = DEFAULT_PREBUF; - s->buffer_attr.minreq = DEFAULT_MINREQ; - s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; - } - - create_stream(s, dev); - - return s; -} - -void pa_stream_free(struct pa_stream *s) { - assert(s && s->context); - - if (s->context->pdispatch) - pa_pdispatch_unregister_reply(s->context->pdispatch, s); - - pa_xfree(s->name); - - if (s->channel_valid && s->context->state == CONTEXT_READY) { - struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : - (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); - pa_tagstruct_putu32(t, s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - } - - if (s->channel_valid) - pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - - if (s->next) - s->next->previous = s->previous; - if (s->previous) - s->previous->next = s->next; - else - s->context->first_stream = s->next; - - pa_xfree(s); -} - -void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { - s->write_callback = cb; - s->write_userdata = userdata; -} - -void pa_stream_write(struct pa_stream *s, const void *data, size_t length) { - struct pa_memchunk chunk; - assert(s && s->context && data && length && s->state == STREAM_READY); - - chunk.memblock = pa_memblock_new(length); - assert(chunk.memblock && chunk.memblock->data); - memcpy(chunk.memblock->data, data, length); - chunk.index = 0; - chunk.length = length; - - pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); - pa_memblock_unref(chunk.memblock); - - /*fprintf(stderr, "Sent %u bytes\n", length);*/ - - if (length < s->requested_bytes) - s->requested_bytes -= length; - else - s->requested_bytes = 0; -} - -size_t pa_stream_writable_size(struct pa_stream *s) { - assert(s && s->state == STREAM_READY); - return s->requested_bytes; -} - -void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { - assert(s && cb); - s->read_callback = cb; - s->read_userdata = userdata; -} - -int pa_stream_is_dead(struct pa_stream *s) { - return s->state == STREAM_DEAD; -} - -int pa_stream_is_ready(struct pa_stream*s) { - return s->state == STREAM_READY; -} - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { - assert(s); - s->die_callback = cb; - s->die_userdata = userdata; -} - -int pa_context_is_pending(struct pa_context *c) { - assert(c); - - if (c->state != CONTEXT_READY) - return 0; - - return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); -} - -struct pa_context* pa_stream_get_context(struct pa_stream *p) { - assert(p); - return p->context; -} - -static void set_dispatch_callbacks(struct pa_context *c); - -static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { - set_dispatch_callbacks(userdata); -} - -static void set_dispatch_callbacks(struct pa_context *c) { - assert(c && c->state == CONTEXT_READY); - - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - - if (pa_pdispatch_is_pending(c->pdispatch)) { - pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c); - return; - } - - if (pa_pstream_is_pending(c->pstream)) { - pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); - return; - } - - assert(c->drain_complete_callback); - c->drain_complete_callback(c, c->drain_complete_userdata); -} - -int pa_context_drain( - struct pa_context *c, - void (*complete) (struct pa_context*c, void *userdata), - void *userdata) { - - assert(c && c->state == CONTEXT_READY); - - if (complete == NULL) { - c->drain_complete_callback = NULL; - pa_pstream_set_drain_callback(c->pstream, NULL, NULL); - pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL); - return 0; - } - - if (!pa_context_is_pending(c)) - return -1; - - c->drain_complete_callback = complete; - c->drain_complete_userdata = userdata; - - set_dispatch_callbacks(c); - - return 0; -} - -static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - stream_dead(s); - return; - } - - if (s->state != STREAM_READY) - return; - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->drain_complete_callback) { - void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback; - s->drain_complete_callback = NULL; - temp(s, s->drain_complete_userdata); - } -} - - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(s && s->state == STREAM_READY); - - if (!complete) { - s->drain_complete_callback = NULL; - return; - } - - s->drain_complete_callback = complete; - s->drain_complete_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - - pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_putu32(t, s->channel); - pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s); -} - -void pa_context_exit(struct pa_context *c) { - struct pa_tagstruct *t; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_EXIT); - pa_tagstruct_putu32(t, c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - uint32_t total, count; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &count) < 0 || - pa_tagstruct_getu32(t, &total) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->stat_callback) - c->stat_callback(c, count, total, c->stat_userdata); -} - -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - c->stat_callback = cb; - c->stat_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_STAT); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); -} - -static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - uint32_t latency; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); - return; - } - - if (pa_tagstruct_getu32(t, &latency) < 0 || - !pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->get_latency_callback) - s->get_latency_callback(s, latency, s->get_latency_userdata); -} - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { - uint32_t tag; - struct pa_tagstruct *t; - - p->get_latency_callback = cb; - p->get_latency_userdata = userdata; - - if (cb == NULL) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); -} - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_stream *s; - struct pa_tagstruct *t; - uint32_t tag; - - s = internal_stream_new(c); - assert(s); - - s->create_complete_callback = cb; - s->create_complete_userdata = userdata; - s->name = pa_xstrdup(name); - s->state = STREAM_CREATING; - s->direction = PA_STREAM_UPLOAD; - s->sample_spec = *ss; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_tagstruct_put_sample_spec(t, ss); - pa_tagstruct_putu32(t, length); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s); - - return s; -} - -static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; - assert(pd && s); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(s->context, command, t) < 0) { - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 0, s->finish_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - s->context->error = PA_ERROR_PROTOCOL; - context_dead(s->context); - return; - } - - if (s->finish_sample_callback) - s->finish_sample_callback(s, 1, s->finish_sample_userdata); -} - -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(p); - - p->finish_sample_callback = cb; - p->finish_sample_userdata = userdata; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = p->context->ctag++); - pa_tagstruct_putu32(t, p->channel); - pa_pstream_send_tagstruct(p->context->pstream, t); - pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p); -} - -static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 0, c->play_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->play_sample_callback) - c->play_sample_callback(c, 1, c->play_sample_userdata); -} - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name && *name && (!dev || *dev)); - - c->play_sample_callback = cb; - c->play_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); - pa_tagstruct_putu32(t, volume); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c); -} - -static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 0, c->remove_sample_userdata); - return; - } - - if (!pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->remove_sample_callback) - c->remove_sample_callback(c, 1, c->remove_sample_userdata); -} - -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c && name); - - c->remove_sample_callback = cb; - c->remove_sample_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, name); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c); -} - -static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_server_info i; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, NULL, c->get_server_info_userdata); - return; - } - - if (pa_tagstruct_gets(t, &i.server_name) < 0 || - pa_tagstruct_gets(t, &i.server_version) < 0 || - pa_tagstruct_gets(t, &i.user_name) < 0 || - pa_tagstruct_gets(t, &i.host_name) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_server_info_callback) - c->get_server_info_callback(c, &i, c->get_server_info_userdata); -} - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_server_info_callback = cb; - c->get_server_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c); -} - -static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_sink_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.monitor_source) < 0 || - pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata); - } - - if (c->get_sink_info_callback) - c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata); -} - -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_source_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || - pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata); - } - - if (c->get_source_info_callback) - c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata); -} - -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { - struct pa_tagstruct *t; - assert(c); - - c->subscribe_callback = cb; - c->subscribe_userdata = userdata; - c->subscribe_mask = m; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); - pa_tagstruct_putu32(t, c->ctag++); - pa_tagstruct_putu32(t, cb ? m : 0); - pa_pstream_send_tagstruct(c->pstream, t); -} - -static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - enum pa_subscription_event_type e; - uint32_t index; - assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); - - if (pa_tagstruct_getu32(t, &e) < 0 || - pa_tagstruct_getu32(t, &index) < 0 || - !pa_tagstruct_eof(t)) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback) - c->subscribe_callback(c, e, index, c->subscribe_userdata); -} - -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_sink_info_callback = cb; - c->get_sink_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c); -} - -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_source_info_callback = cb; - c->get_source_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); -} - -static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_client_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.protocol_name) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); - } - - if (c->get_client_info_callback) - c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); -} - - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_client_info_callback = cb; - c->get_client_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); -} - -static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - assert(pd && c); - - if (command != PA_COMMAND_REPLY) { - if (handle_error(c, command, t) < 0) { - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); - return; - } - - while (!pa_tagstruct_eof(t)) { - struct pa_module_info i; - - if (pa_tagstruct_getu32(t, &i.index) < 0 || - pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.argument) < 0 || - pa_tagstruct_getu32(t, &i.n_used) < 0 || - pa_tagstruct_getu32(t, &i.auto_unload) < 0) { - c->error = PA_ERROR_PROTOCOL; - context_dead(c); - return; - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); - } - - if (c->get_module_info_callback) - c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); -} - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} - -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - uint32_t tag; - assert(c); - - c->get_module_info_callback = cb; - c->get_module_info_userdata = userdata; - - if (!cb) - return; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); -} diff --git a/polyp/polyplib.h b/polyp/polyplib.h index a0dd9f9cb..b9e5637ce 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -22,157 +22,13 @@ USA. ***/ -#include - +#include "mainloop-api.h" #include "sample.h" #include "polyplib-def.h" -#include "mainloop-api.h" - -#ifdef __cplusplus -//extern "C" { -#endif - -struct pa_context; -struct pa_stream; - -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); -void pa_context_unref(struct pa_context *c); -struct pa_context* pa_context_ref(struct pa_context *c); - -int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata); -int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata); -void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); - -int pa_context_is_dead(struct pa_context *c); -int pa_context_is_ready(struct pa_context *c); -int pa_context_errno(struct pa_context *c); - -int pa_context_is_pending(struct pa_context *c); - -struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_unref(struct pa_stream *s); -struct pa_stream *pa_stream_ref(struct pa_stream *s); - -void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata); - -void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); - -void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); -void pa_stream_write(struct pa_stream *p, const void *data, size_t length); -size_t pa_stream_writable_size(struct pa_stream *p); - -void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); - -int pa_stream_is_dead(struct pa_stream *p); -int pa_stream_is_ready(struct pa_stream*p); - -void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); - -struct pa_context* pa_stream_get_context(struct pa_stream *p); - -uint32_t pa_stream_get_index(struct pa_stream *s); - -struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); -void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata); - -void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -struct pa_sink_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t volume; - uint32_t monitor_source; - const char *monitor_source_name; - uint32_t latency; -}; - -void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); - -struct pa_source_info { - const char *name; - uint32_t index; - const char *description; - struct pa_sample_spec sample_spec; - uint32_t owner_module; - uint32_t monitor_of_sink; - const char *monitor_of_sink_name; -}; - -void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); - -struct pa_server_info { - const char *user_name; - const char *host_name; - const char *server_version; - const char *server_name; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); - -struct pa_module_info { - uint32_t index; - const char*name, *argument; - uint32_t n_used, auto_unload; -}; - -void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); - -struct pa_client_info { - uint32_t index; - const char *name; - uint32_t owner_module; - const char *protocol_name; -}; - -void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); - -struct pa_sink_input_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t sink; - struct pa_sample_spec sample_spec; - uint32_t volume; - uint32_t latency; -}; - -void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); - -struct pa_source_output_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t owner_client; - uint32_t source; - struct pa_sample_spec sample_spec; -}; - -void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); -void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); - -void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); - -void pa_context_exit(struct pa_context *c); -void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata); - -void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); - -#ifdef __cplusplus -} -#endif +#include "polyplib-context.h" +#include "polyplib-stream.h" +#include "polyplib-introspect.h" +#include "polyplib-subscribe.h" +#include "polyplib-scache.h" #endif diff --git a/polyp/sample-util.c b/polyp/sample-util.c index 5b1cd6264..8f5558a4a 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -135,10 +135,3 @@ void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, } } -uint32_t pa_volume_multiply(uint32_t a, uint32_t b) { - uint64_t p = a; - p *= b; - p /= PA_VOLUME_NORM; - - return (uint32_t) p; -} diff --git a/polyp/sample-util.h b/polyp/sample-util.h index 73101ab4b..66f40a16a 100644 --- a/polyp/sample-util.h +++ b/polyp/sample-util.h @@ -26,8 +26,6 @@ #include "memblock.h" #include "memchunk.h" -#define PA_VOLUME_NORM (0x100) -#define PA_VOLUME_MUTE (0) struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_sample_spec *spec); void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spec); @@ -43,6 +41,4 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, uint32_t volume); -uint32_t pa_volume_multiply(uint32_t a, uint32_t b); - #endif diff --git a/polyp/sample.c b/polyp/sample.c index e4c4bd526..4f93f2b7e 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -96,3 +96,11 @@ void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { assert(pa_sample_spec_valid(spec)); snprintf(s, l, "%s %uch %uHz", table[spec->format], spec->channels, spec->rate); } + +uint32_t pa_volume_multiply(uint32_t a, uint32_t b) { + uint64_t p = a; + p *= b; + p /= PA_VOLUME_NORM; + + return (uint32_t) p; +} diff --git a/polyp/sample.h b/polyp/sample.h index 250278798..a7cde093a 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -25,9 +25,9 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +#include "cdecl.h" + +PA_C_DECL_BEGIN enum pa_sample_format { PA_SAMPLE_U8, @@ -49,10 +49,11 @@ enum pa_sample_format { #endif #define PA_SAMPLE_FLOAT32 PA_SAMPLE_FLOAT32NE +/** A sample format and attribute specification */ struct pa_sample_spec { - enum pa_sample_format format; - uint32_t rate; - uint8_t channels; + enum pa_sample_format format; /**< The sample format */ + uint32_t rate; /**< The sample rate. (e.g. 44100) */ + uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */ }; size_t pa_bytes_per_second(const struct pa_sample_spec *spec); @@ -64,8 +65,10 @@ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_s #define PA_SAMPLE_SNPRINT_MAX_LENGTH 32 void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec); -#ifdef __cplusplus -} -#endif +#define PA_VOLUME_NORM (0x100) +#define PA_VOLUME_MUTE (0) +uint32_t pa_volume_multiply(uint32_t a, uint32_t b); + +PA_C_DECL_END #endif diff --git a/polyp/socket-client.c b/polyp/socket-client.c index e8cb2f92a..dffbfe7d9 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -120,7 +120,7 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc if ((r = connect(c->fd, sa, len)) < 0) { if (errno != EINPROGRESS) { - fprintf(stderr, "connect(): %s\n", strerror(errno)); + /*fprintf(stderr, "connect(): %s\n", strerror(errno));*/ return -1; } diff --git a/polyp/socket-client.h b/polyp/socket-client.h index 2a89210e6..7b9e2a720 100644 --- a/polyp/socket-client.h +++ b/polyp/socket-client.h @@ -23,6 +23,8 @@ ***/ #include +#include + #include "mainloop-api.h" #include "iochannel.h" diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index aefd03c4a..bcd7f456a 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -48,6 +48,4 @@ int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t le int pa_tagstruct_eof(struct pa_tagstruct*t); const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l); - - #endif diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c index 8ff3054da..7d8b4821e 100644 --- a/polyp/xmalloc.c +++ b/polyp/xmalloc.c @@ -52,25 +52,36 @@ void *pa_xrealloc(void *ptr, size_t size) { return p; } +void* pa_xmemdup(const void *p, size_t l) { + if (!p) + return NULL; + else { + char *r = pa_xmalloc(l); + memcpy(r, p, l); + return r; + } +} + char *pa_xstrdup(const char *s) { if (!s) return NULL; - else { - char *r = strdup(s); - if (!r) - oom(); - return r; - } + return pa_xmemdup(s, strlen(s)+1); } char *pa_xstrndup(const char *s, size_t l) { if (!s) return NULL; else { - char *r = strndup(s, l); - if (!r) - oom(); + char *r; + size_t t = strlen(s); + + if (t > l) + t = l; + + r = pa_xmemdup(s, t+1); + r[t] = 0; return r; } } + diff --git a/polyp/xmalloc.h b/polyp/xmalloc.h index 45209b05e..eaf8f708b 100644 --- a/polyp/xmalloc.h +++ b/polyp/xmalloc.h @@ -12,4 +12,6 @@ void *pa_xrealloc(void *ptr, size_t size); char *pa_xstrdup(const char *s); char *pa_xstrndup(const char *s, size_t l); +void* pa_xmemdup(const void *p, size_t l); + #endif From c17545108b33162fb186f797b8a408511e9252f4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 15 Aug 2004 00:02:26 +0000 Subject: [PATCH 0123/1514] proper ref counting for more objects some documentation update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@124 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doxygen/doxygen.conf.in | 2 +- polyp/Makefile.am | 6 +- polyp/client.c | 2 + polyp/glib-mainloop.h | 2 +- polyp/mainloop-api.h | 30 +++++++++- polyp/mainloop-signal.h | 5 ++ polyp/module-protocol-stub.c | 2 +- polyp/module-x11-bell.c | 1 + polyp/native-common.h | 6 ++ polyp/pdispatch.c | 111 +++++++++++++++++++---------------- polyp/pdispatch.h | 5 +- polyp/polyplib-context.c | 22 ++++--- polyp/polyplib-error.h | 4 +- polyp/polyplib-subscribe.c | 8 ++- polyp/protocol-cli.c | 2 +- polyp/protocol-esound.c | 2 +- polyp/protocol-native.c | 7 ++- polyp/protocol-simple.c | 2 +- polyp/pstream.c | 85 +++++++++++++++------------ polyp/pstream.h | 7 ++- polyp/socket-client.c | 49 +++++++++++----- polyp/socket-client.h | 3 +- polyp/socket-server.c | 28 +++++++-- polyp/socket-server.h | 3 +- 24 files changed, 251 insertions(+), 143 deletions(-) diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 78a43685d..7fd00c609 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -291,7 +291,7 @@ HIDE_SCOPE_NAMES = NO # will put a list of the files that are included by a file in the documentation # of that file. -SHOW_INCLUDE_FILES = YES +SHOW_INCLUDE_FILES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 7f70ec9d4..f2d61f7cd 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -124,7 +124,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ play-memchunk.c play-memchunk.h \ autoload.c autoload.h \ xmalloc.c xmalloc.h \ - subscribe.h subscribe.c + subscribe.h subscribe.c \ + debug.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) @@ -296,7 +297,8 @@ libpolyp_la_SOURCES = polyplib.h \ polyplib-introspect.c polyplib-introspect.h \ polyplib-scache.c polyplib-scache.h \ polyplib-subscribe.c polyplib-subscribe.h \ - cdecl.h + cdecl.h \ + llist.h libpolyp_la_CFLAGS = $(AM_CFLAGS) libpolyp_mainloop_la_SOURCES = mainloop-api.h mainloop-api.c \ diff --git a/polyp/client.c b/polyp/client.c index 809f97615..0cb42466a 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -79,4 +79,6 @@ void pa_client_rename(struct pa_client *c, const char *name) { assert(c); pa_xfree(c->name); c->name = pa_xstrdup(name); + + pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->index); } diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h index c67e72bd1..1ba663fd6 100644 --- a/polyp/glib-mainloop.h +++ b/polyp/glib-mainloop.h @@ -24,6 +24,6 @@ void pa_glib_mainloop_free(struct pa_glib_mainloop* g); /** Return the abstract main loop API vtable for the GLIB main loop object */ struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g); -PA_C_DECL_BEGIN +PA_C_DECL_END #endif diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index 97ab6a684..c1f40eaea 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -27,6 +27,20 @@ #include "cdecl.h" +/** \file + * + * Main loop abstraction layer. Both the polypaudio core and the + * polypaudio client library use a main loop abstraction layer. Due to + * this it is possible to embed polypaudio into other + * applications easily. Two main loop implemenations are + * currently available: + * \li A minimal implementation based on the C library's poll() function (See \ref mainloop.h) + * \li A wrapper around the GLIB main loop. Use this to embed polypaudio into your GLIB/GTK+/GNOME programs (See \ref glib-mainloop.h) + * + * The structure pa_mainloop_api is used as vtable for the main loop abstraction. + * */ + + PA_C_DECL_BEGIN /** A bitmask for IO events */ @@ -55,16 +69,28 @@ struct pa_mainloop_api { /** A pointer to some private, arbitrary data of the main loop implementation */ void *userdata; - /* IO sources */ + /** Create a new IO event source object */ struct pa_io_event* (*io_new)(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event* e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata); + + /** Enable or disable IO events on this object */ void (*io_enable)(struct pa_io_event* e, enum pa_io_event_flags events); + + /** Free a IO event source object */ void (*io_free)(struct pa_io_event* e); + + /** Set a function that is called when the IO event source is destroyed. Use this to free the userdata argument if required */ void (*io_set_destroy)(struct pa_io_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata)); - /* Time sources */ + /** Create a new timer event source object for the specified Unix time */ struct pa_time_event* (*time_new)(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event* e, const struct timeval *tv, void *userdata), void *userdata); + + /** Restart a running or expired timer event source with a new Unix time */ void (*time_restart)(struct pa_time_event* e, const struct timeval *tv); + + /** Free a deferred timer event source object */ void (*time_free)(struct pa_time_event* e); + + /** Set a function that is called when the timer event source is destroyed. Use this to free the userdata argument if required */ void (*time_set_destroy)(struct pa_time_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)); /** Create a new deferred event source object */ diff --git a/polyp/mainloop-signal.h b/polyp/mainloop-signal.h index dacbc1534..4dd6c5524 100644 --- a/polyp/mainloop-signal.h +++ b/polyp/mainloop-signal.h @@ -23,6 +23,9 @@ ***/ #include "mainloop-api.h" +#include "cdecl.h" + +PA_C_DECL_BEGIN int pa_signal_init(struct pa_mainloop_api *api); void pa_signal_done(void); @@ -34,4 +37,6 @@ void pa_signal_free(struct pa_signal_event *e); void pa_signal_set_destroy(struct pa_signal_event *e, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, void *userdata)); +PA_C_DECL_END + #endif diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 3ce18c315..3b1a02706 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -145,7 +145,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto finish; if (!(m->userdata = protocol_new(c, s, m, ma))) { - pa_socket_server_free(s); + pa_socket_server_unref(s); goto finish; } diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index 5449e944d..2414e36be 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -154,6 +154,7 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { } pa_xfree(u->scache_item); + pa_xfree(u->sink_name); if (u->display) XCloseDisplay(u->display); diff --git a/polyp/native-common.h b/polyp/native-common.h index fa3213d01..0fc441658 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -22,6 +22,10 @@ USA. ***/ +#include "cdecl.h" + +PA_C_DECL_BEGIN + enum { PA_COMMAND_ERROR, PA_COMMAND_TIMEOUT, /* pseudo command */ @@ -121,4 +125,6 @@ enum pa_subscription_event_type { #define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) +PA_C_DECL_END + #endif diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index 2d4c4d641..9ed91fc59 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -30,6 +30,7 @@ #include "pdispatch.h" #include "native-common.h" #include "xmalloc.h" +#include "llist.h" /*#define DEBUG_OPCODES*/ @@ -65,37 +66,30 @@ static const char *command_names[PA_COMMAND_MAX] = { struct reply_info { struct pa_pdispatch *pdispatch; - struct reply_info *next, *previous; + PA_LLIST_FIELDS(struct reply_info); void (*callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); void *userdata; uint32_t tag; struct pa_time_event *time_event; - int callback_is_running; }; struct pa_pdispatch { + int ref; struct pa_mainloop_api *mainloop; const struct pa_pdispatch_command *command_table; unsigned n_commands; - struct reply_info *replies; + PA_LLIST_HEAD(struct reply_info, replies); void (*drain_callback)(struct pa_pdispatch *pd, void *userdata); void *drain_userdata; - int in_use, shall_free; }; static void reply_info_free(struct reply_info *r) { assert(r && r->pdispatch && r->pdispatch->mainloop); - if (r->pdispatch) + if (r->time_event) r->pdispatch->mainloop->time_free(r->time_event); - - if (r->previous) - r->previous->next = r->next; - else - r->pdispatch->replies = r->next; - - if (r->next) - r->next->previous = r->previous; + + PA_LLIST_REMOVE(struct reply_info, r->pdispatch->replies, r); pa_xfree(r); } @@ -107,37 +101,56 @@ struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *mainloop, const st assert((entries && table) || (!entries && !table)); pd = pa_xmalloc(sizeof(struct pa_pdispatch)); + pd->ref = 1; pd->mainloop = mainloop; pd->command_table = table; pd->n_commands = entries; - pd->replies = NULL; + PA_LLIST_HEAD_INIT(struct pa_reply_info, pd->replies); pd->drain_callback = NULL; pd->drain_userdata = NULL; - pd->in_use = pd->shall_free = 0; - return pd; } -void pa_pdispatch_free(struct pa_pdispatch *pd) { +void pdispatch_free(struct pa_pdispatch *pd) { assert(pd); - if (pd->in_use) { - pd->shall_free = 1; - return; - } - while (pd->replies) reply_info_free(pd->replies); + pa_xfree(pd); } +static void run_action(struct pa_pdispatch *pd, struct reply_info *r, uint32_t command, struct pa_tagstruct *ts) { + void (*callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + void *userdata; + uint32_t tag; + assert(r); + + pa_pdispatch_ref(pd); + + callback = r->callback; + userdata = r->userdata; + tag = r->tag; + + reply_info_free(r); + + callback(pd, command, tag, ts, userdata); + + if (pd->drain_callback && !pa_pdispatch_is_pending(pd)) + pd->drain_callback(pd, pd->drain_userdata); + + pa_pdispatch_unref(pd); +} + int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *userdata) { uint32_t tag, command; struct pa_tagstruct *ts = NULL; int ret = -1; - assert(pd && packet && packet->data && !pd->in_use); + assert(pd && packet && packet->data); + pa_pdispatch_ref(pd); + if (packet->length <= 8) goto finish; @@ -159,20 +172,8 @@ int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *use if (r->tag == tag) break; - if (r) { - pd->in_use = r->callback_is_running = 1; - assert(r->callback); - r->callback(r->pdispatch, command, tag, ts, r->userdata); - pd->in_use = r->callback_is_running = 0; - reply_info_free(r); - - if (pd->shall_free) - pa_pdispatch_free(pd); - else { - if (pd->drain_callback && !pa_pdispatch_is_pending(pd)) - pd->drain_callback(pd, pd->drain_userdata); - } - } + if (r) + run_action(pd, r, command, ts); } else if (pd->command_table && command < pd->n_commands) { const struct pa_pdispatch_command *c = pd->command_table+command; @@ -186,33 +187,30 @@ int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *use finish: if (ts) - pa_tagstruct_free(ts); + pa_tagstruct_free(ts); + + pa_pdispatch_unref(pd); return ret; } static void timeout_callback(struct pa_mainloop_api*m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { struct reply_info*r = userdata; - assert (r && r->time_event == e && r->pdispatch && r->pdispatch->mainloop == m && r->callback); + assert(r && r->time_event == e && r->pdispatch && r->pdispatch->mainloop == m && r->callback); - r->callback(r->pdispatch, PA_COMMAND_TIMEOUT, r->tag, NULL, r->userdata); - reply_info_free(r); - - if (r->pdispatch->drain_callback && !pa_pdispatch_is_pending(r->pdispatch)) - r->pdispatch->drain_callback(r->pdispatch, r->pdispatch->drain_userdata); + run_action(r->pdispatch, r, PA_COMMAND_TIMEOUT, NULL); } void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int timeout, void (*cb)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void *userdata) { struct reply_info *r; struct timeval tv; - assert(pd && cb); + assert(pd && pd->ref >= 1 && cb); r = pa_xmalloc(sizeof(struct reply_info)); r->pdispatch = pd; r->callback = cb; r->userdata = userdata; r->tag = tag; - r->callback_is_running = 0; gettimeofday(&tv, NULL); tv.tv_sec += timeout; @@ -220,11 +218,7 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r); assert(r->time_event); - r->previous = NULL; - r->next = pd->replies; - if (r->next) - r->next->previous = r; - pd->replies = r; + PA_LLIST_PREPEND(struct reply_info, pd->replies, r); } int pa_pdispatch_is_pending(struct pa_pdispatch *pd) { @@ -248,7 +242,20 @@ void pa_pdispatch_unregister_reply(struct pa_pdispatch *pd, void *userdata) { for (r = pd->replies; r; r = n) { n = r->next; - if (!r->callback_is_running && r->userdata == userdata) /* when this item's callback is currently running it is destroyed anyway in the very near future */ + if (r->userdata == userdata) reply_info_free(r); } } + +void pa_pdispatch_unref(struct pa_pdispatch *pd) { + assert(pd && pd->ref >= 1); + + if (!(--(pd->ref))) + pdispatch_free(pd); +} + +struct pa_pdispatch* pa_pdispatch_ref(struct pa_pdispatch *pd) { + assert(pd && pd->ref >= 1); + pd->ref++; + return pd; +} diff --git a/polyp/pdispatch.h b/polyp/pdispatch.h index 796c1e031..ff99b1844 100644 --- a/polyp/pdispatch.h +++ b/polyp/pdispatch.h @@ -29,14 +29,13 @@ struct pa_pdispatch; -/* It is safe to destroy the calling pdispatch object from all callbacks */ - struct pa_pdispatch_command { void (*proc)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); }; struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *m, const struct pa_pdispatch_command*table, unsigned entries); -void pa_pdispatch_free(struct pa_pdispatch *pd); +void pa_pdispatch_unref(struct pa_pdispatch *pd); +struct pa_pdispatch* pa_pdispatch_ref(struct pa_pdispatch *pd); int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*p, void *userdata); diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 5f849e242..2a0c24a52 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -92,11 +92,13 @@ static void context_free(struct pa_context *c) { pa_stream_set_state(c->streams, PA_STREAM_TERMINATED); if (c->client) - pa_socket_client_free(c->client); + pa_socket_client_unref(c->client); if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); - if (c->pstream) - pa_pstream_free(c->pstream); + pa_pdispatch_unref(c->pdispatch); + if (c->pstream) { + pa_pstream_close(c->pstream); + pa_pstream_unref(c->pstream); + } if (c->record_streams) pa_dynarray_free(c->record_streams, NULL, NULL); @@ -140,15 +142,17 @@ void pa_context_set_state(struct pa_context *c, enum pa_context_state st) { } if (c->pdispatch) - pa_pdispatch_free(c->pdispatch); + pa_pdispatch_unref(c->pdispatch); c->pdispatch = NULL; - if (c->pstream) - pa_pstream_free(c->pstream); + if (c->pstream) { + pa_pstream_close(c->pstream); + pa_pstream_unref(c->pstream); + } c->pstream = NULL; if (c->client) - pa_socket_client_free(c->client); + pa_socket_client_unref(c->client); c->client = NULL; } @@ -267,7 +271,7 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i pa_context_ref(c); - pa_socket_client_free(client); + pa_socket_client_unref(client); c->client = NULL; if (!io) { diff --git a/polyp/polyplib-error.h b/polyp/polyplib-error.h index d7519af4a..437d618e1 100644 --- a/polyp/polyplib-error.h +++ b/polyp/polyplib-error.h @@ -25,11 +25,11 @@ #include #include "cdecl.h" -PA_C_DECL_BEGIN; +PA_C_DECL_BEGIN /** Return a human readable error message for the specified numeric error code */ const char* pa_strerror(uint32_t error); -PA_C_DECL_END; +PA_C_DECL_END #endif diff --git a/polyp/polyplib-subscribe.c b/polyp/polyplib-subscribe.c index a14d0b064..9536bbc65 100644 --- a/polyp/polyplib-subscribe.c +++ b/polyp/polyplib-subscribe.c @@ -24,6 +24,7 @@ #endif #include +#include #include "polyplib-subscribe.h" #include "polyplib-internal.h" @@ -65,10 +66,15 @@ struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscrip t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, cb ? m : 0); + pa_tagstruct_putu32(t, m); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); return pa_operation_ref(o); } +void pa_context_set_subscribe_callback(struct pa_context *c, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + assert(c); + c->subscribe_callback = cb; + c->subscribe_userdata = userdata; +} diff --git a/polyp/protocol-cli.c b/polyp/protocol-cli.c index 11aeabe0c..266d49697 100644 --- a/polyp/protocol-cli.c +++ b/polyp/protocol-cli.c @@ -80,6 +80,6 @@ void pa_protocol_cli_free(struct pa_protocol_cli *p) { assert(p); pa_idxset_free(p->connections, free_connection, NULL); - pa_socket_server_free(p->server); + pa_socket_server_unref(p->server); pa_xfree(p); } diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index b11e19923..fb639b7fb 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -1024,6 +1024,6 @@ void pa_protocol_esound_free(struct pa_protocol_esound *p) { connection_free(c); pa_idxset_free(p->connections, NULL, NULL); - pa_socket_server_free(p->server); + pa_socket_server_unref(p->server); pa_xfree(p); } diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 247851fc1..0d265e332 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -306,8 +306,9 @@ static void connection_free(struct connection *c) { upload_stream_free((struct upload_stream*) o); pa_idxset_free(c->output_streams, NULL, NULL); - pa_pdispatch_free(c->pdispatch); - pa_pstream_free(c->pstream); + pa_pdispatch_unref(c->pdispatch); + pa_pstream_close(c->pstream); + pa_pstream_unref(c->pstream); pa_client_free(c->client); if (c->subscription) @@ -1330,6 +1331,6 @@ void pa_protocol_native_free(struct pa_protocol_native *p) { while ((c = pa_idxset_first(p->connections, NULL))) connection_free(c); pa_idxset_free(p->connections, NULL, NULL); - pa_socket_server_free(p->server); + pa_socket_server_unref(p->server); pa_xfree(p); } diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index a95b356c1..bd0e14889 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -426,7 +426,7 @@ void pa_protocol_simple_free(struct pa_protocol_simple *p) { } if (p->server) - pa_socket_server_free(p->server); + pa_socket_server_unref(p->server); pa_xfree(p); } diff --git a/polyp/pstream.c b/polyp/pstream.c index 4f071e4ae..2d147e03a 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -57,13 +57,13 @@ struct item_info { }; struct pa_pstream { + int ref; + struct pa_mainloop_api *mainloop; struct pa_defer_event *defer_event; struct pa_iochannel *io; struct pa_queue *send_queue; - int in_use, shall_free; - int dead; void (*die_callback) (struct pa_pstream *p, void *userdata); void *die_callback_userdata; @@ -97,40 +97,24 @@ static void do_write(struct pa_pstream *p); static void do_read(struct pa_pstream *p); static void do_something(struct pa_pstream *p) { - assert(p && !p->shall_free); + assert(p); p->mainloop->defer_enable(p->defer_event, 0); - if (p->dead) - return; - - if (pa_iochannel_is_hungup(p->io)) { + pa_pstream_ref(p); + + if (!p->dead && pa_iochannel_is_hungup(p->io)) { p->dead = 1; if (p->die_callback) p->die_callback(p, p->die_callback_userdata); - - return; } - if (pa_iochannel_is_writable(p->io)) { - p->in_use = 1; + if (!p->dead && pa_iochannel_is_writable(p->io)) do_write(p); - p->in_use = 0; - if (p->shall_free) { - pa_pstream_free(p); - return; - } - } - - if (pa_iochannel_is_readable(p->io)) { - p->in_use = 1; + if (!p->dead && pa_iochannel_is_readable(p->io)) do_read(p); - p->in_use = 0; - if (p->shall_free) { - pa_pstream_free(p); - return; - } - } + + pa_pstream_unref(p); } static void io_callback(struct pa_iochannel*io, void *userdata) { @@ -150,7 +134,7 @@ struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel assert(io); p = pa_xmalloc(sizeof(struct pa_pstream)); - + p->ref = 1; p->io = io; pa_iochannel_set_callback(io, io_callback, p); @@ -181,8 +165,6 @@ struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel p->drain_callback = NULL; p->drain_userdata = NULL; - p->in_use = p->shall_free = 0; - return p; } @@ -202,16 +184,11 @@ static void item_free(void *item, void *p) { pa_xfree(i); } -void pa_pstream_free(struct pa_pstream *p) { +static void pstream_free(struct pa_pstream *p) { assert(p); - if (p->in_use) { - /* If this pstream object is used by someone else on the call stack, we have to postpone the freeing */ - p->dead = p->shall_free = 1; - return; - } - - pa_iochannel_free(p->io); + pa_pstream_close(p); + pa_queue_free(p->send_queue, item_free, NULL); if (p->write.current) @@ -223,7 +200,6 @@ void pa_pstream_free(struct pa_pstream *p) { if (p->read.packet) pa_packet_unref(p->read.packet); - p->mainloop->defer_free(p->defer_event); pa_xfree(p); } @@ -456,3 +432,36 @@ void pa_pstream_set_drain_callback(struct pa_pstream *p, void (*cb)(struct pa_ps p->drain_userdata = userdata; } +void pa_pstream_unref(struct pa_pstream*p) { + assert(p && p->ref >= 1); + + if (!(--(p->ref))) + pstream_free(p); +} + +struct pa_pstream* pa_pstream_ref(struct pa_pstream*p) { + assert(p && p->ref >= 1); + p->ref++; + return p; +} + +void pa_pstream_close(struct pa_pstream *p) { + assert(p); + + p->dead = 1; + + if (p->io) { + pa_iochannel_free(p->io); + p->io = NULL; + } + + if (p->defer_event) { + p->mainloop->defer_free(p->defer_event); + p->defer_event = NULL; + } + + p->die_callback = NULL; + p->drain_callback = NULL; + p->recieve_packet_callback = NULL; + p->recieve_memblock_callback = NULL; +} diff --git a/polyp/pstream.h b/polyp/pstream.h index 6b91aeb0b..ff70a8559 100644 --- a/polyp/pstream.h +++ b/polyp/pstream.h @@ -30,12 +30,11 @@ #include "mainloop-api.h" #include "memchunk.h" -/* It is safe to destroy the calling pstream object from all callbacks */ - struct pa_pstream; struct pa_pstream* pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io); -void pa_pstream_free(struct pa_pstream*p); +void pa_pstream_unref(struct pa_pstream*p); +struct pa_pstream* pa_pstream_ref(struct pa_pstream*p); void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet); void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk); @@ -48,4 +47,6 @@ void pa_pstream_set_die_callback(struct pa_pstream *p, void (*callback)(struct p int pa_pstream_is_pending(struct pa_pstream *p); +void pa_pstream_close(struct pa_pstream *p); + #endif diff --git a/polyp/socket-client.c b/polyp/socket-client.c index dffbfe7d9..3852c1adf 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -39,6 +39,7 @@ #include "xmalloc.h" struct pa_socket_client { + int ref; struct pa_mainloop_api *mainloop; int fd; struct pa_io_event *io_event; @@ -52,6 +53,7 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { assert(m); c = pa_xmalloc(sizeof(struct pa_socket_client)); + c->ref = 1; c->mainloop = m; c->fd = -1; c->io_event = NULL; @@ -62,38 +64,40 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { } static void do_call(struct pa_socket_client *c) { - struct pa_iochannel *io; + struct pa_iochannel *io = NULL; int error, lerror; assert(c && c->callback); + pa_socket_client_ref(c); + lerror = sizeof(error); if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &error, &lerror) < 0) { fprintf(stderr, "getsockopt(): %s\n", strerror(errno)); - goto failed; + goto finish; } if (lerror != sizeof(error)) { fprintf(stderr, "getsocktop() returned invalid size.\n"); - goto failed; + goto finish; } if (error != 0) { fprintf(stderr, "connect(): %s\n", strerror(error)); - goto failed; + goto finish; } io = pa_iochannel_new(c->mainloop, c->fd, c->fd); assert(io); - c->fd = -1; - c->callback(c, io, c->userdata); - - return; -failed: - close(c->fd); +finish: + if (!io) + close(c->fd); c->fd = -1; - c->callback(c, NULL, c->userdata); - return; + + assert(c->callback); + c->callback(c, io, c->userdata); + + pa_socket_client_unref(c); } static void connect_fixed_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { @@ -159,7 +163,7 @@ struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, ui return c; fail: - pa_socket_client_free(c); + pa_socket_client_unref(c); return NULL; } @@ -188,7 +192,7 @@ struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, co return c; fail: - pa_socket_client_free(c); + pa_socket_client_unref(c); return NULL; } @@ -214,12 +218,12 @@ struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m return c; fail: - pa_socket_client_free(c); + pa_socket_client_unref(c); return NULL; } -void pa_socket_client_free(struct pa_socket_client *c) { +void socket_client_free(struct pa_socket_client *c) { assert(c && c->mainloop); if (c->io_event) c->mainloop->io_free(c->io_event); @@ -230,6 +234,19 @@ void pa_socket_client_free(struct pa_socket_client *c) { pa_xfree(c); } +void pa_socket_client_unref(struct pa_socket_client *c) { + assert(c && c->ref >= 1); + + if (!(--(c->ref))) + socket_client_free(c); +} + +struct pa_socket_client* pa_socket_client_ref(struct pa_socket_client *c) { + assert(c && c->ref >= 1); + c->ref++; + return c; +} + void pa_socket_client_set_callback(struct pa_socket_client *c, void (*on_connection)(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata), void *userdata) { assert(c); c->callback = on_connection; diff --git a/polyp/socket-client.h b/polyp/socket-client.h index 7b9e2a720..1957355c6 100644 --- a/polyp/socket-client.h +++ b/polyp/socket-client.h @@ -36,7 +36,8 @@ struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, ui struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename); struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen); -void pa_socket_client_free(struct pa_socket_client *c); +void pa_socket_client_unref(struct pa_socket_client *c); +struct pa_socket_client* pa_socket_client_ref(struct pa_socket_client *c); void pa_socket_client_set_callback(struct pa_socket_client *c, void (*on_connection)(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata), void *userdata); diff --git a/polyp/socket-server.c b/polyp/socket-server.c index 6af2c2865..f01e417c4 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -40,6 +40,7 @@ #include "xmalloc.h" struct pa_socket_server { + int ref; int fd; char *filename; @@ -57,14 +58,16 @@ static void callback(struct pa_mainloop_api *mainloop, struct pa_io_event *e, in int nfd; assert(s && s->mainloop == mainloop && s->io_event == e && e && fd >= 0 && fd == s->fd); + pa_socket_server_ref(s); + if ((nfd = accept(fd, NULL, NULL)) < 0) { fprintf(stderr, "accept(): %s\n", strerror(errno)); - return; + goto finish; } if (!s->on_connection) { close(nfd); - return; + goto finish; } /* There should be a check for socket type here */ @@ -76,6 +79,9 @@ static void callback(struct pa_mainloop_api *mainloop, struct pa_io_event *e, in io = pa_iochannel_new(s->mainloop, nfd, nfd); assert(io); s->on_connection(s, io, s->userdata); + +finish: + pa_socket_server_unref(s); } struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) { @@ -83,6 +89,7 @@ struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) assert(m && fd >= 0); s = pa_xmalloc(sizeof(struct pa_socket_server)); + s->ref = 1; s->fd = fd; s->filename = NULL; s->on_connection = NULL; @@ -97,6 +104,12 @@ struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) return s; } +struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *s) { + assert(s && s->ref >= 1); + s->ref++; + return s; +} + struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) { int fd = -1; struct sockaddr_un sa; @@ -184,7 +197,7 @@ fail: return NULL; } -void pa_socket_server_free(struct pa_socket_server*s) { +static void socket_server_free(struct pa_socket_server*s) { assert(s); close(s->fd); @@ -197,8 +210,15 @@ void pa_socket_server_free(struct pa_socket_server*s) { pa_xfree(s); } +void pa_socket_server_unref(struct pa_socket_server *s) { + assert(s && s->ref >= 1); + + if (!(--(s->ref))) + socket_server_free(s); +} + void pa_socket_server_set_callback(struct pa_socket_server*s, void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata), void *userdata) { - assert(s); + assert(s && s->ref >= 1); s->on_connection = on_connection; s->userdata = userdata; diff --git a/polyp/socket-server.h b/polyp/socket-server.h index 6661a66ed..c9d9193d3 100644 --- a/polyp/socket-server.h +++ b/polyp/socket-server.h @@ -34,7 +34,8 @@ struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename); struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); -void pa_socket_server_free(struct pa_socket_server*s); +void pa_socket_server_unref(struct pa_socket_server*s); +struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *s); void pa_socket_server_set_callback(struct pa_socket_server*s, void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata), void *userdata); From efc3491f1f1ca42cd776f96ccfb006c53717d2e8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 15 Aug 2004 13:15:51 +0000 Subject: [PATCH 0124/1514] add support for volume manipulation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@125 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/cli-command.c | 2 +- polyp/pdispatch.c | 9 ++++---- polyp/protocol-native.c | 48 ++++++++++++++++++++++++++++++++++++++++- polyp/sample.h | 5 +++++ polyp/sink-input.c | 9 ++++++++ polyp/sink-input.h | 2 ++ polyp/sink.c | 3 ++- 7 files changed, 71 insertions(+), 7 deletions(-) diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 1d454f2a5..aa61b10ef 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -338,7 +338,7 @@ static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokeniz return -1; } - si->volume = (uint32_t) volume; + pa_sink_input_set_volume(si, (uint32_t) volume); return 0; } diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index 9ed91fc59..c46d4f770 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -175,13 +175,14 @@ int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *use if (r) run_action(pd, r, command, ts); - } else if (pd->command_table && command < pd->n_commands) { + } else if (pd->command_table && (command < pd->n_commands) && pd->command_table[command].proc) { const struct pa_pdispatch_command *c = pd->command_table+command; - if (c->proc) - c->proc(pd, command, tag, ts, userdata); - } else + c->proc(pd, command, tag, ts, userdata); + } else { + fprintf(stderr, "Recieved unsupported command %u\n", command); goto finish; + } ret = 0; diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 0d265e332..7df39fe3f 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -134,6 +134,7 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -167,6 +168,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_GET_CLIENT_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info }, [PA_COMMAND_SUBSCRIBE] = { command_subscribe }, + [PA_COMMAND_SET_SINK_VOLUME] = { command_set_volume }, }; /* structure management */ @@ -1164,9 +1166,53 @@ static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_ c->subscription = NULL; pa_pstream_send_simple_ack(c->pstream, tag); - } +static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index, volume; + struct pa_sink *sink = NULL; + struct pa_sink_input *si = NULL; + const char *name = NULL; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) || + pa_tagstruct_getu32(t, &volume) || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (command == PA_COMMAND_SET_SINK_VOLUME) { + if (index != (uint32_t) -1) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, index); + else + sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1); + } else { + assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME); + si = pa_idxset_get_by_index(c->protocol->core->sinks, index); + } + + if (!si && !sink) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + if (sink) + pa_sink_set_volume(sink, volume); + else if (si) + pa_sink_input_set_volume(si, volume); + + pa_pstream_send_simple_ack(c->pstream, tag); +} + + /*** pstream callbacks ***/ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { diff --git a/polyp/sample.h b/polyp/sample.h index a7cde093a..e397a1dfe 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -65,8 +65,13 @@ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_s #define PA_SAMPLE_SNPRINT_MAX_LENGTH 32 void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec); +/** Normal volume (100%) */ #define PA_VOLUME_NORM (0x100) + +/** Muted volume (0%) */ #define PA_VOLUME_MUTE (0) + +/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */ uint32_t pa_volume_multiply(uint32_t a, uint32_t b); PA_C_DECL_END diff --git a/polyp/sink-input.c b/polyp/sink-input.c index dd7469e02..cf255a078 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -168,3 +168,12 @@ void pa_sink_input_drop(struct pa_sink_input *i, size_t length) { i->resampled_chunk.index = i->resampled_chunk.length = 0; } } + +void pa_sink_input_set_volume(struct pa_sink_input *i, uint32_t volume) { + assert(i); + + if (i->volume != volume) { + i->volume = volume; + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); + } +} diff --git a/polyp/sink-input.h b/polyp/sink-input.h index 63dce71d5..b21dbf4d0 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -64,4 +64,6 @@ uint32_t pa_sink_input_get_latency(struct pa_sink_input *i); int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk); void pa_sink_input_drop(struct pa_sink_input *i, size_t length); +void pa_sink_input_set_volume(struct pa_sink_input *i, uint32_t volume); + #endif diff --git a/polyp/sink.c b/polyp/sink.c index d9a3ae861..b8617ae1e 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -285,8 +285,9 @@ void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) { void pa_sink_set_volume(struct pa_sink *sink, uint32_t volume) { assert(sink); + if (sink->volume != volume) { - pa_subscription_post(sink->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, sink->index); sink->volume = volume; + pa_subscription_post(sink->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, sink->index); } } From 369a908db761e7f59481000a68bffb476aa6e056 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 16 Aug 2004 19:55:02 +0000 Subject: [PATCH 0125/1514] add sink input/source output support to the native protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@126 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/native-common.h | 3 + polyp/polyplib-introspect.c | 139 +++++++++++++++++++++++++++++++++++- polyp/polyplib-introspect.h | 4 +- polyp/protocol-native.c | 70 +++++++++++++++--- 4 files changed, 203 insertions(+), 13 deletions(-) diff --git a/polyp/native-common.h b/polyp/native-common.h index 0fc441658..debb9bba6 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -63,8 +63,11 @@ enum { PA_COMMAND_GET_CLIENT_INFO, PA_COMMAND_GET_CLIENT_INFO_LIST, PA_COMMAND_GET_SINK_INPUT_INFO, + PA_COMMAND_GET_SINK_INPUT_INFO_LIST, PA_COMMAND_GET_SOURCE_OUTPUT_INFO, + PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, PA_COMMAND_GET_SAMPLE_INFO, + PA_COMMAND_GET_SAMPLE_INFO_LIST, PA_COMMAND_SUBSCRIBE, PA_COMMAND_SUBSCRIBE_EVENT, diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 345a9cd5f..aa70a111f 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -297,7 +297,6 @@ struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t i pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, o); @@ -375,6 +374,144 @@ struct pa_operation* pa_context_get_module_info_list(struct pa_context *c, void return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, cb, userdata); } +/*** Sink input info ***/ + +static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_operation *o = userdata; + int eof = 1; + assert(pd && o && o->context && o->ref >= 1); + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; + + eof = -1; + } else { + + while (!pa_tagstruct_eof(t)) { + struct pa_sink_input_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.client) < 0 || + pa_tagstruct_getu32(t, &i.sink) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.latency) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_sink_input_info*i, int eof, void *userdata) = o->callback; + cb(o->context, &i, 0, o->userdata); + } + } + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_sink_input_info*i, int eof, void *userdata) = o->callback; + cb(o->context, NULL, eof, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +struct pa_operation* pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INPUT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, cb, userdata); +} + +/*** Source output info ***/ + +static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_operation *o = userdata; + int eof = 1; + assert(pd && o && o->context && o->ref >= 1); + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; + + eof = -1; + } else { + + while (!pa_tagstruct_eof(t)) { + struct pa_source_output_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.client) < 0 || + pa_tagstruct_getu32(t, &i.source) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_source_output_info*i, int eof, void *userdata) = o->callback; + cb(o->context, &i, 0, o->userdata); + } + } + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_source_output_info*i, int eof, void *userdata) = o->callback; + cb(o->context, NULL, eof, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +struct pa_operation* pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_OUTPUT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, cb, userdata); +} + /*** Volume manipulation ***/ struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index bca752e2b..e83ba73b7 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -93,7 +93,7 @@ struct pa_sink_input_info { uint32_t index; const char *name; uint32_t owner_module; - uint32_t owner_client; + uint32_t client; uint32_t sink; struct pa_sample_spec sample_spec; uint32_t volume; @@ -107,7 +107,7 @@ struct pa_source_output_info { uint32_t index; const char *name; uint32_t owner_module; - uint32_t owner_client; + uint32_t client; uint32_t source; struct pa_sample_spec sample_spec; }; diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 7df39fe3f..35c78f61b 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -162,13 +162,18 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_GET_SOURCE_INFO] = { command_get_info }, [PA_COMMAND_GET_CLIENT_INFO] = { command_get_info }, [PA_COMMAND_GET_MODULE_INFO] = { command_get_info }, + [PA_COMMAND_GET_SINK_INPUT_INFO] = { command_get_info }, + [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = { command_get_info }, [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_MODULE_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_CLIENT_INFO_LIST] = { command_get_info_list }, + [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = { command_get_info_list }, + [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info }, [PA_COMMAND_SUBSCRIBE] = { command_subscribe }, [PA_COMMAND_SET_SINK_VOLUME] = { command_set_volume }, + [PA_COMMAND_SET_SINK_INPUT_VOLUME] = { command_set_volume }, }; /* structure management */ @@ -988,6 +993,28 @@ static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *modu pa_tagstruct_putu32(t, module->auto_unload); } +static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_input *s) { + assert(t && s); + pa_tagstruct_putu32(t, s->index); + pa_tagstruct_puts(t, s->name ? s->name : ""); + pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1); + pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1); + pa_tagstruct_putu32(t, s->sink->index); + pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_putu32(t, s->volume); + pa_tagstruct_putu32(t, pa_sink_input_get_latency(s)); +} + +static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) { + assert(t && s); + pa_tagstruct_putu32(t, s->index); + pa_tagstruct_puts(t, s->name ? s->name : ""); + pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1); + pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1); + pa_tagstruct_putu32(t, s->source->index); + pa_tagstruct_put_sample_spec(t, &s->sample_spec); +} + static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t index; @@ -995,12 +1022,19 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t struct pa_source *source = NULL; struct pa_client *client = NULL; struct pa_module *module = NULL; + struct pa_sink_input *si = NULL; + struct pa_source_output *so = NULL; const char *name; struct pa_tagstruct *reply; assert(c && t); + if (pa_tagstruct_getu32(t, &index) < 0 || - pa_tagstruct_gets(t, &name) < 0 || + (command != PA_COMMAND_GET_CLIENT_INFO && + command != PA_COMMAND_GET_MODULE_INFO && + command != PA_COMMAND_GET_SINK_INPUT_INFO && + command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO && + pa_tagstruct_gets(t, &name) < 0) || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1023,12 +1057,16 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t source = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SOURCE, 1); } else if (command == PA_COMMAND_GET_CLIENT_INFO) client = pa_idxset_get_by_index(c->protocol->core->clients, index); - else { - assert(command == PA_COMMAND_GET_MODULE_INFO); + else if (command == PA_COMMAND_GET_MODULE_INFO) module = pa_idxset_get_by_index(c->protocol->core->modules, index); + else if (command == PA_COMMAND_GET_SINK_INPUT_INFO) + si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index); + else { + assert(command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO); + so = pa_idxset_get_by_index(c->protocol->core->source_outputs, index); } - - if (!sink && !source && !client && !module) { + + if (!sink && !source && !client && !module && !si && !so) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1043,8 +1081,12 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t source_fill_tagstruct(reply, source); else if (client) client_fill_tagstruct(reply, client); - else + else if (module) module_fill_tagstruct(reply, module); + else if (si) + sink_input_fill_tagstruct(reply, si); + else + source_output_fill_tagstruct(reply, so); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1077,9 +1119,13 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin i = c->protocol->core->sources; else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST) i = c->protocol->core->clients; - else { - assert(command == PA_COMMAND_GET_MODULE_INFO_LIST); + else if (command == PA_COMMAND_GET_MODULE_INFO_LIST) i = c->protocol->core->modules; + else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST) + i = c->protocol->core->sink_inputs; + else { + assert(command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST); + i = c->protocol->core->source_outputs; } for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) { @@ -1089,9 +1135,13 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin source_fill_tagstruct(reply, p); else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST) client_fill_tagstruct(reply, p); - else { - assert(command == PA_COMMAND_GET_MODULE_INFO_LIST); + else if (command == PA_COMMAND_GET_MODULE_INFO_LIST) module_fill_tagstruct(reply, p); + else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST) + sink_input_fill_tagstruct(reply, p); + else { + assert(command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST); + source_output_fill_tagstruct(reply, p); } } From 126fedea31b346c0c16ce2e3211768036675e46f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 16 Aug 2004 20:16:37 +0000 Subject: [PATCH 0126/1514] fix sink iunput and source output stuff git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@127 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/protocol-native.c | 2 +- polyp/sink-input.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 35c78f61b..1fafc9844 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -1246,7 +1246,7 @@ static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32 sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1); } else { assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME); - si = pa_idxset_get_by_index(c->protocol->core->sinks, index); + si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index); } if (!si && !sink) { diff --git a/polyp/sink-input.c b/polyp/sink-input.c index cf255a078..99ff8fe6a 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -170,7 +170,7 @@ void pa_sink_input_drop(struct pa_sink_input *i, size_t length) { } void pa_sink_input_set_volume(struct pa_sink_input *i, uint32_t volume) { - assert(i); + assert(i && i->sink && i->sink->core); if (i->volume != volume) { i->volume = volume; From e4be61675ea192391d2e9d586275b618544fa664 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 12:49:23 +0000 Subject: [PATCH 0127/1514] rename clitext to cli-text git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@128 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/{clitext.c => cli-text.c} | 0 polyp/{clitext.h => cli-text.h} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename polyp/{clitext.c => cli-text.c} (100%) rename polyp/{clitext.h => cli-text.h} (100%) diff --git a/polyp/clitext.c b/polyp/cli-text.c similarity index 100% rename from polyp/clitext.c rename to polyp/cli-text.c diff --git a/polyp/clitext.h b/polyp/cli-text.h similarity index 100% rename from polyp/clitext.h rename to polyp/cli-text.h From a0d54ddb8bf9c03d1916140730260abb6e3f053b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 13:00:01 +0000 Subject: [PATCH 0128/1514] make clitext to cli-text renaming complete git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@129 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 4 ++-- polyp/cli-command.c | 2 +- polyp/cli-text.c | 2 +- polyp/cli.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index f2d61f7cd..100cd4ffb 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -116,7 +116,7 @@ polypaudio_SOURCES = idxset.c idxset.h \ modargs.c modargs.h \ cmdline.c cmdline.h \ cli-command.c cli-command.h \ - clitext.c clitext.h \ + cli-text.c cli-text.h \ tokenizer.c tokenizer.h \ dynarray.c dynarray.h \ scache.c scache.h \ @@ -406,7 +406,7 @@ libpolypcore_la_SOURCES = idxset.c idxset.h \ sioman.c sioman.h \ modargs.c modargs.h \ cli-command.c cli-command.h \ - clitext.c clitext.h \ + cli-text.c cli-text.h \ tokenizer.c tokenizer.h \ dynarray.c dynarray.h diff --git a/polyp/cli-command.c b/polyp/cli-command.c index aa61b10ef..8459d71b6 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -39,7 +39,7 @@ #include "tokenizer.h" #include "strbuf.h" #include "namereg.h" -#include "clitext.h" +#include "cli-text.h" #include "scache.h" #include "sample-util.h" #include "sound-file.h" diff --git a/polyp/cli-text.c b/polyp/cli-text.c index a530238fb..558b53ca9 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -26,7 +26,7 @@ #include #include -#include "clitext.h" +#include "cli-text.h" #include "module.h" #include "client.h" #include "sink.h" diff --git a/polyp/cli.c b/polyp/cli.c index f0ad48309..6fd2c2387 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -39,7 +39,7 @@ #include "tokenizer.h" #include "strbuf.h" #include "namereg.h" -#include "clitext.h" +#include "cli-text.h" #include "cli-command.h" #include "xmalloc.h" From aff43ddabb87903823805ec49533cb99fb1aa771 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 13:00:45 +0000 Subject: [PATCH 0129/1514] update todo file git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@130 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 5 ----- 1 file changed, 5 deletions(-) diff --git a/doc/todo b/doc/todo index 943fab0d4..db89e6129 100644 --- a/doc/todo +++ b/doc/todo @@ -11,18 +11,13 @@ - several files: copyright and config.h - enable searchdir - autoscan -- rename clitext.[ch] to cli-text.[ch] *** 0.3 *** -- client-ui - move the global memblock statistics variables to the core - unix socket directories include user name - native library/protocol: - get server layout - subscription module load/unload kill client/... - set volume - more complete pactl ** later *** From bee750bbb3d9d7a64fa7f344ab42cdcfcb280a7e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 13:28:52 +0000 Subject: [PATCH 0130/1514] create native-common-internal.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@131 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/mainloop-api.h | 3 +- polyp/mainloop-signal.h | 18 +++++ polyp/mainloop.h | 22 ++++++ polyp/native-common-internal.h | 133 +++++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 polyp/native-common-internal.h diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index c1f40eaea..3d5ad24a7 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -38,9 +38,10 @@ * \li A wrapper around the GLIB main loop. Use this to embed polypaudio into your GLIB/GTK+/GNOME programs (See \ref glib-mainloop.h) * * The structure pa_mainloop_api is used as vtable for the main loop abstraction. + * + * This mainloop abstraction layer has no direct support for UNIX signals. Generic, mainloop implementation agnostic support is available throught \ref mainloop-signal.h. * */ - PA_C_DECL_BEGIN /** A bitmask for IO events */ diff --git a/polyp/mainloop-signal.h b/polyp/mainloop-signal.h index 4dd6c5524..0ff208273 100644 --- a/polyp/mainloop-signal.h +++ b/polyp/mainloop-signal.h @@ -27,14 +27,32 @@ PA_C_DECL_BEGIN +/** \file + * UNIX signal support for main loops. In contrast to other + * main loop event sources such as timer and IO events, UNIX signal + * support requires modification of the global process + * environment. Due to this the generic main loop abstraction layer as + * defined in \ref mainloop-api.h doesn't have direct support for UNIX + * signals. However, you may hook signal support into an abstract main loop via the routines defined herein. + */ + +/** Initialize the UNIX signal subsystem and bind it to the specified main loop */ int pa_signal_init(struct pa_mainloop_api *api); + +/** Cleanup the signal subsystem */ void pa_signal_done(void); +/** \struct pa_signal_event + * A UNIX signal event source object */ struct pa_signal_event; +/** Create a new UNIX signal event source object */ struct pa_signal_event* pa_signal_new(int signal, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int signal, void *userdata), void *userdata); + +/** Free a UNIX signal event source object */ void pa_signal_free(struct pa_signal_event *e); +/** Set a function that is called when the signal event source is destroyed. Use this to free the userdata argument if required */ void pa_signal_set_destroy(struct pa_signal_event *e, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, void *userdata)); PA_C_DECL_END diff --git a/polyp/mainloop.h b/polyp/mainloop.h index 4a4c85dfa..b51f42269 100644 --- a/polyp/mainloop.h +++ b/polyp/mainloop.h @@ -27,14 +27,36 @@ PA_C_DECL_BEGIN +/** \file + * + * A minimal main loop implementation based on the C library's poll() + * function. Using the routines defined herein you may create a simple + * main loop supporting the generic main loop abstraction layer as + * defined in \ref mainloop-api.h. This implementation is thread safe + * as long as you access the main loop object from a single thread only.*/ + +/** \struct pa_mainloop + * A main loop object + */ struct pa_mainloop; +/** Allocate a new main loop object */ struct pa_mainloop *pa_mainloop_new(void); + +/** Free a main loop object */ void pa_mainloop_free(struct pa_mainloop* m); +/** Run a single iteration of the main loop. Returns a negative value +on error or exit request. If block is nonzero, block for events if +none are queued. Optionally return the return value as specified with +the main loop's quit() routine in the integer variable retval points +to */ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval); + +/** Run unlimited iterations of the main loop object until the main loop's quit() routine is called. */ int pa_mainloop_run(struct pa_mainloop *m, int *retval); +/** Return the abstract main loop abstraction layer vtable for this main loop. This calls pa_mainloop_iterate() iteratively.*/ struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m); PA_C_DECL_END diff --git a/polyp/native-common-internal.h b/polyp/native-common-internal.h new file mode 100644 index 000000000..debb9bba6 --- /dev/null +++ b/polyp/native-common-internal.h @@ -0,0 +1,133 @@ +#ifndef foonativecommonhfoo +#define foonativecommonhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "cdecl.h" + +PA_C_DECL_BEGIN + +enum { + PA_COMMAND_ERROR, + PA_COMMAND_TIMEOUT, /* pseudo command */ + PA_COMMAND_REPLY, + PA_COMMAND_CREATE_PLAYBACK_STREAM, + PA_COMMAND_DELETE_PLAYBACK_STREAM, + PA_COMMAND_CREATE_RECORD_STREAM, + PA_COMMAND_DELETE_RECORD_STREAM, + PA_COMMAND_EXIT, + PA_COMMAND_REQUEST, + PA_COMMAND_AUTH, + PA_COMMAND_SET_NAME, + PA_COMMAND_LOOKUP_SINK, + PA_COMMAND_LOOKUP_SOURCE, + PA_COMMAND_DRAIN_PLAYBACK_STREAM, + PA_COMMAND_PLAYBACK_STREAM_KILLED, + PA_COMMAND_RECORD_STREAM_KILLED, + PA_COMMAND_STAT, + PA_COMMAND_GET_PLAYBACK_LATENCY, + + PA_COMMAND_CREATE_UPLOAD_STREAM, + PA_COMMAND_DELETE_UPLOAD_STREAM, + PA_COMMAND_FINISH_UPLOAD_STREAM, + PA_COMMAND_PLAY_SAMPLE, + PA_COMMAND_REMOVE_SAMPLE, + + PA_COMMAND_GET_SERVER_INFO, + + PA_COMMAND_GET_SINK_INFO, + PA_COMMAND_GET_SINK_INFO_LIST, + PA_COMMAND_GET_SOURCE_INFO, + PA_COMMAND_GET_SOURCE_INFO_LIST, + PA_COMMAND_GET_MODULE_INFO, + PA_COMMAND_GET_MODULE_INFO_LIST, + PA_COMMAND_GET_CLIENT_INFO, + PA_COMMAND_GET_CLIENT_INFO_LIST, + PA_COMMAND_GET_SINK_INPUT_INFO, + PA_COMMAND_GET_SINK_INPUT_INFO_LIST, + PA_COMMAND_GET_SOURCE_OUTPUT_INFO, + PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, + PA_COMMAND_GET_SAMPLE_INFO, + PA_COMMAND_GET_SAMPLE_INFO_LIST, + + PA_COMMAND_SUBSCRIBE, + PA_COMMAND_SUBSCRIBE_EVENT, + + PA_COMMAND_SET_SINK_VOLUME, + PA_COMMAND_SET_SINK_INPUT_VOLUME, + + PA_COMMAND_MAX +}; + +enum { + PA_ERROR_OK, + PA_ERROR_ACCESS, + PA_ERROR_COMMAND, + PA_ERROR_INVALID, + PA_ERROR_EXIST, + PA_ERROR_NOENTITY, + PA_ERROR_CONNECTIONREFUSED, + PA_ERROR_PROTOCOL, + PA_ERROR_TIMEOUT, + PA_ERROR_AUTHKEY, + PA_ERROR_INTERNAL, + PA_ERROR_CONNECTIONTERMINATED, + PA_ERROR_KILLED, + PA_ERROR_INVALIDSERVER, + PA_ERROR_MAX +}; + +#define PA_NATIVE_COOKIE_LENGTH 256 +#define PA_NATIVE_COOKIE_FILE ".polypaudio-cookie" + +enum pa_subscription_mask { + PA_SUBSCRIPTION_MASK_NULL = 0, + PA_SUBSCRIPTION_MASK_SINK = 1, + PA_SUBSCRIPTION_MASK_SOURCE = 2, + PA_SUBSCRIPTION_MASK_SINK_INPUT = 4, + PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8, + PA_SUBSCRIPTION_MASK_MODULE = 16, + PA_SUBSCRIPTION_MASK_CLIENT = 32, + PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, +}; + +enum pa_subscription_event_type { + PA_SUBSCRIPTION_EVENT_SINK = 0, + PA_SUBSCRIPTION_EVENT_SOURCE = 1, + PA_SUBSCRIPTION_EVENT_SINK_INPUT = 2, + PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 3, + PA_SUBSCRIPTION_EVENT_MODULE = 4, + PA_SUBSCRIPTION_EVENT_CLIENT = 5, + PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6, + PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 7, + + PA_SUBSCRIPTION_EVENT_NEW = 0, + PA_SUBSCRIPTION_EVENT_CHANGE = 16, + PA_SUBSCRIPTION_EVENT_REMOVE = 32, + PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32, +}; + +#define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) + +PA_C_DECL_END + +#endif From f693aa4c8811b67377a4fcc55887d03876fb48be Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 13:30:26 +0000 Subject: [PATCH 0131/1514] remove native-common-internal git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@132 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/native-common-internal.h | 133 --------------------------------- 1 file changed, 133 deletions(-) delete mode 100644 polyp/native-common-internal.h diff --git a/polyp/native-common-internal.h b/polyp/native-common-internal.h deleted file mode 100644 index debb9bba6..000000000 --- a/polyp/native-common-internal.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef foonativecommonhfoo -#define foonativecommonhfoo - -/* $Id$ */ - -/*** - This file is part of polypaudio. - - polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - polypaudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include "cdecl.h" - -PA_C_DECL_BEGIN - -enum { - PA_COMMAND_ERROR, - PA_COMMAND_TIMEOUT, /* pseudo command */ - PA_COMMAND_REPLY, - PA_COMMAND_CREATE_PLAYBACK_STREAM, - PA_COMMAND_DELETE_PLAYBACK_STREAM, - PA_COMMAND_CREATE_RECORD_STREAM, - PA_COMMAND_DELETE_RECORD_STREAM, - PA_COMMAND_EXIT, - PA_COMMAND_REQUEST, - PA_COMMAND_AUTH, - PA_COMMAND_SET_NAME, - PA_COMMAND_LOOKUP_SINK, - PA_COMMAND_LOOKUP_SOURCE, - PA_COMMAND_DRAIN_PLAYBACK_STREAM, - PA_COMMAND_PLAYBACK_STREAM_KILLED, - PA_COMMAND_RECORD_STREAM_KILLED, - PA_COMMAND_STAT, - PA_COMMAND_GET_PLAYBACK_LATENCY, - - PA_COMMAND_CREATE_UPLOAD_STREAM, - PA_COMMAND_DELETE_UPLOAD_STREAM, - PA_COMMAND_FINISH_UPLOAD_STREAM, - PA_COMMAND_PLAY_SAMPLE, - PA_COMMAND_REMOVE_SAMPLE, - - PA_COMMAND_GET_SERVER_INFO, - - PA_COMMAND_GET_SINK_INFO, - PA_COMMAND_GET_SINK_INFO_LIST, - PA_COMMAND_GET_SOURCE_INFO, - PA_COMMAND_GET_SOURCE_INFO_LIST, - PA_COMMAND_GET_MODULE_INFO, - PA_COMMAND_GET_MODULE_INFO_LIST, - PA_COMMAND_GET_CLIENT_INFO, - PA_COMMAND_GET_CLIENT_INFO_LIST, - PA_COMMAND_GET_SINK_INPUT_INFO, - PA_COMMAND_GET_SINK_INPUT_INFO_LIST, - PA_COMMAND_GET_SOURCE_OUTPUT_INFO, - PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, - PA_COMMAND_GET_SAMPLE_INFO, - PA_COMMAND_GET_SAMPLE_INFO_LIST, - - PA_COMMAND_SUBSCRIBE, - PA_COMMAND_SUBSCRIBE_EVENT, - - PA_COMMAND_SET_SINK_VOLUME, - PA_COMMAND_SET_SINK_INPUT_VOLUME, - - PA_COMMAND_MAX -}; - -enum { - PA_ERROR_OK, - PA_ERROR_ACCESS, - PA_ERROR_COMMAND, - PA_ERROR_INVALID, - PA_ERROR_EXIST, - PA_ERROR_NOENTITY, - PA_ERROR_CONNECTIONREFUSED, - PA_ERROR_PROTOCOL, - PA_ERROR_TIMEOUT, - PA_ERROR_AUTHKEY, - PA_ERROR_INTERNAL, - PA_ERROR_CONNECTIONTERMINATED, - PA_ERROR_KILLED, - PA_ERROR_INVALIDSERVER, - PA_ERROR_MAX -}; - -#define PA_NATIVE_COOKIE_LENGTH 256 -#define PA_NATIVE_COOKIE_FILE ".polypaudio-cookie" - -enum pa_subscription_mask { - PA_SUBSCRIPTION_MASK_NULL = 0, - PA_SUBSCRIPTION_MASK_SINK = 1, - PA_SUBSCRIPTION_MASK_SOURCE = 2, - PA_SUBSCRIPTION_MASK_SINK_INPUT = 4, - PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8, - PA_SUBSCRIPTION_MASK_MODULE = 16, - PA_SUBSCRIPTION_MASK_CLIENT = 32, - PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, -}; - -enum pa_subscription_event_type { - PA_SUBSCRIPTION_EVENT_SINK = 0, - PA_SUBSCRIPTION_EVENT_SOURCE = 1, - PA_SUBSCRIPTION_EVENT_SINK_INPUT = 2, - PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 3, - PA_SUBSCRIPTION_EVENT_MODULE = 4, - PA_SUBSCRIPTION_EVENT_CLIENT = 5, - PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6, - PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 7, - - PA_SUBSCRIPTION_EVENT_NEW = 0, - PA_SUBSCRIPTION_EVENT_CHANGE = 16, - PA_SUBSCRIPTION_EVENT_REMOVE = 32, - PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32, -}; - -#define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) - -PA_C_DECL_END - -#endif From ca2265f37277081b4fe82e375923483c2e03931d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 17:17:22 +0000 Subject: [PATCH 0132/1514] Documentation work add pkg-config support for GLIB main loop git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@133 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- configure.ac | 4 +- doc/todo | 1 + doxygen/doxygen.conf.in | 4 +- polyp/Makefile.am | 1 - polyp/glib-mainloop.h | 2 +- polyp/mainloop-api.h | 6 +- polyp/mainloop-signal.h | 2 +- polyp/mainloop.h | 2 +- polyp/native-common.h | 48 +--------------- polyp/pacat-simple.c | 12 +++- polyp/pacat.c | 25 +++++++- polyp/parec-simple.c | 7 ++- polyp/polyplib-context.h | 28 ++++----- polyp/polyplib-def.h | 107 +++++++++++++++++++++++++++++++---- polyp/polyplib-error.c | 5 +- polyp/polyplib-error.h | 3 + polyp/polyplib-internal.h | 1 + polyp/polyplib-introspect.c | 6 +- polyp/polyplib-introspect.h | 35 ++++++++---- polyp/polyplib-operation.h | 6 -- polyp/polyplib-simple.h | 12 +++- polyp/polyplib-stream.h | 11 +--- polyp/polyplib-subscribe.h | 9 +++ polyp/polyplib.h | 50 ++++++++++++++++ polyp/sample-util.h | 6 +- polyp/sample.c | 6 +- polyp/sample.h | 47 +++++++++++---- polyp/sink-input.c | 2 +- polyp/sink-input.h | 2 +- polyp/sink.c | 2 +- polyp/sink.h | 4 +- polyplib-glib-mainloop.pc.in | 11 ++++ polyplib-mainloop.pc.in | 2 +- polyplib-simple.pc.in | 3 +- polyplib.pc.in | 3 +- 36 files changed, 326 insertions(+), 151 deletions(-) create mode 100644 polyplib-glib-mainloop.pc.in diff --git a/Makefile.am b/Makefile.am index 3fc81b40e..13a063627 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ MAINTAINERCLEANFILES=README noinst_DATA = README pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc +pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-glib-mainloop.pc README: rm -f README diff --git a/configure.ac b/configure.ac index b7766e4a6..e6194d9f9 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.1],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.2],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) @@ -84,5 +84,5 @@ AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) -AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf]) +AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf]) AC_OUTPUT diff --git a/doc/todo b/doc/todo index db89e6129..aa65d3396 100644 --- a/doc/todo +++ b/doc/todo @@ -5,6 +5,7 @@ - future cancellation - make mcalign merge chunks - ref counting foo +- pacat quit() ? - doxygen diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 7fd00c609..7d4c44c95 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../polyp/polyplib-context.h ../polyp/polyplib-stream.h ../polyp/polyplib.h ../polyp/sample.h ../polyp/polyplib-def.h ../polyp/polyplib-subscribe.h ../polyp/polyplib-introspect.h ../polyp/polyplib-scache.h ../polyp/mainloop-api.h ../polyp/cdecl.h ../polyp/glib-mainloop.h ../polyp/mainloop.h ../polyp/mainloop-signal.h ../polyp/native-common.h ../polyp/polyplib-error.h ../polyp/polyplib-operation.h ../polyp/polyplib-simple.h +INPUT = ../polyp/polyplib-context.h ../polyp/polyplib-stream.h ../polyp/polyplib.h ../polyp/sample.h ../polyp/polyplib-def.h ../polyp/polyplib-subscribe.h ../polyp/polyplib-introspect.h ../polyp/polyplib-scache.h ../polyp/mainloop-api.h ../polyp/cdecl.h ../polyp/glib-mainloop.h ../polyp/mainloop.h ../polyp/mainloop-signal.h ../polyp/polyplib-error.h ../polyp/polyplib-operation.h ../polyp/polyplib-simple.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -455,7 +455,7 @@ EXCLUDE_PATTERNS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = ../polyp/ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 100cd4ffb..791abf0ec 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -84,7 +84,6 @@ lib_LTLIBRARIES=libpolyp.la \ libpolyp-mainloop-glib.la \ libpolyp-simple.la - polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ strbuf.c strbuf.h \ diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h index 1ba663fd6..dbbf2a62a 100644 --- a/polyp/glib-mainloop.h +++ b/polyp/glib-mainloop.h @@ -12,7 +12,7 @@ PA_C_DECL_BEGIN /** \struct pa_glib_mainloop - * A GLIB main loop object */ + * An opaque GLIB main loop object */ struct pa_glib_mainloop; /** Create a new GLIB main loop object for the specified GLIB main loop context. If c is NULL the default context is used. */ diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index 3d5ad24a7..e631c7acf 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -54,15 +54,15 @@ enum pa_io_event_flags { }; /** \struct pa_io_event - * An IO event source object */ + * An opaque IO event source object */ struct pa_io_event; /** \struct pa_defer_event - * A deferred event source object. Events of this type are triggered once in every main loop iteration */ + * An opaque deferred event source object. Events of this type are triggered once in every main loop iteration */ struct pa_defer_event; /** \struct pa_time_event - * A timer event source object */ + * An opaque timer event source object */ struct pa_time_event; /** An abstract mainloop API vtable */ diff --git a/polyp/mainloop-signal.h b/polyp/mainloop-signal.h index 0ff208273..fa5ce7184 100644 --- a/polyp/mainloop-signal.h +++ b/polyp/mainloop-signal.h @@ -43,7 +43,7 @@ int pa_signal_init(struct pa_mainloop_api *api); void pa_signal_done(void); /** \struct pa_signal_event - * A UNIX signal event source object */ + * An opaque UNIX signal event source object */ struct pa_signal_event; /** Create a new UNIX signal event source object */ diff --git a/polyp/mainloop.h b/polyp/mainloop.h index b51f42269..5d4fd9904 100644 --- a/polyp/mainloop.h +++ b/polyp/mainloop.h @@ -36,7 +36,7 @@ PA_C_DECL_BEGIN * as long as you access the main loop object from a single thread only.*/ /** \struct pa_mainloop - * A main loop object + * An opaque main loop object */ struct pa_mainloop; diff --git a/polyp/native-common.h b/polyp/native-common.h index debb9bba6..b921ccc2c 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -23,6 +23,7 @@ ***/ #include "cdecl.h" +#include "polyplib-def.h" PA_C_DECL_BEGIN @@ -78,56 +79,9 @@ enum { PA_COMMAND_MAX }; -enum { - PA_ERROR_OK, - PA_ERROR_ACCESS, - PA_ERROR_COMMAND, - PA_ERROR_INVALID, - PA_ERROR_EXIST, - PA_ERROR_NOENTITY, - PA_ERROR_CONNECTIONREFUSED, - PA_ERROR_PROTOCOL, - PA_ERROR_TIMEOUT, - PA_ERROR_AUTHKEY, - PA_ERROR_INTERNAL, - PA_ERROR_CONNECTIONTERMINATED, - PA_ERROR_KILLED, - PA_ERROR_INVALIDSERVER, - PA_ERROR_MAX -}; - #define PA_NATIVE_COOKIE_LENGTH 256 #define PA_NATIVE_COOKIE_FILE ".polypaudio-cookie" -enum pa_subscription_mask { - PA_SUBSCRIPTION_MASK_NULL = 0, - PA_SUBSCRIPTION_MASK_SINK = 1, - PA_SUBSCRIPTION_MASK_SOURCE = 2, - PA_SUBSCRIPTION_MASK_SINK_INPUT = 4, - PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8, - PA_SUBSCRIPTION_MASK_MODULE = 16, - PA_SUBSCRIPTION_MASK_CLIENT = 32, - PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, -}; - -enum pa_subscription_event_type { - PA_SUBSCRIPTION_EVENT_SINK = 0, - PA_SUBSCRIPTION_EVENT_SOURCE = 1, - PA_SUBSCRIPTION_EVENT_SINK_INPUT = 2, - PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 3, - PA_SUBSCRIPTION_EVENT_MODULE = 4, - PA_SUBSCRIPTION_EVENT_CLIENT = 5, - PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6, - PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 7, - - PA_SUBSCRIPTION_EVENT_NEW = 0, - PA_SUBSCRIPTION_EVENT_CHANGE = 16, - PA_SUBSCRIPTION_EVENT_REMOVE = 32, - PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32, -}; - -#define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) - PA_C_DECL_END #endif diff --git a/polyp/pacat-simple.c b/polyp/pacat-simple.c index f2aae2e4b..f5b696a89 100644 --- a/polyp/pacat-simple.c +++ b/polyp/pacat-simple.c @@ -34,15 +34,19 @@ #define BUFSIZE 1024 int main(int argc, char*argv[]) { + + /* The Sample format to use */ static const struct pa_sample_spec ss = { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 }; + struct pa_simple *s = NULL; int ret = 1; int error; + /* Create a new playback stream */ if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, &error))) { fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); goto finish; @@ -51,22 +55,24 @@ int main(int argc, char*argv[]) { for (;;) { uint8_t buf[BUFSIZE]; ssize_t r; - + + /* Read some data ... */ if ((r = read(STDIN_FILENO, buf, sizeof(buf))) <= 0) { - if (r == 0) /* eof */ + if (r == 0) /* EOF */ break; fprintf(stderr, __FILE__": read() failed: %s\n", strerror(errno)); goto finish; } + /* ... and play it */ if (pa_simple_write(s, buf, r, &error) < 0) { fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(error)); goto finish; } } - /* Make sure that every single sample way played */ + /* Make sure that every single sample was played */ if (pa_simple_drain(s, &error) < 0) { fprintf(stderr, __FILE__": pa_simple_drain() failed: %s\n", pa_strerror(error)); goto finish; diff --git a/polyp/pacat.c b/polyp/pacat.c index 5d29451ae..4f3bf0016 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -47,11 +47,13 @@ static size_t buffer_length = 0, buffer_index = 0; static struct pa_io_event* stdio_event = NULL; +/* A shortcut for terminating the application */ static void quit(int ret) { assert(mainloop_api); mainloop_api->quit(mainloop_api, ret); } +/* Write some data to the stream */ static void do_stream_write(size_t length) { size_t l; assert(length); @@ -74,6 +76,7 @@ static void do_stream_write(size_t length) { } } +/* This is called whenever new data may be written to the stream */ static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { assert(s && length); @@ -86,6 +89,7 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user do_stream_write(length); } +/* This is called whenever new data may is available */ static void stream_read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata) { assert(s && data && length); @@ -103,6 +107,7 @@ static void stream_read_callback(struct pa_stream *s, const void*data, size_t le buffer_index = 0; } +/* This routine is called whenever the stream state changes */ static void stream_state_callback(struct pa_stream *s, void *userdata) { assert(s); @@ -125,6 +130,7 @@ static void stream_state_callback(struct pa_stream *s, void *userdata) { } } +/* This is called whenever the context status changes */ static void context_state_callback(struct pa_context *c, void *userdata) { static const struct pa_sample_spec ss = { .format = PA_SAMPLE_S16LE, @@ -170,10 +176,12 @@ static void context_state_callback(struct pa_context *c, void *userdata) { } } +/* Connection draining complete */ static void context_drain_complete(struct pa_context*c, void *userdata) { pa_context_disconnect(c); } +/* Stream draining complete */ static void stream_drain_complete(struct pa_stream*s, int success, void *userdata) { struct pa_operation *o; @@ -196,6 +204,7 @@ static void stream_drain_complete(struct pa_stream*s, int success, void *userdat } } +/* New data on STDIN **/ static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { size_t l, w = 0; ssize_t r; @@ -232,6 +241,7 @@ static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int do_stream_write(w); } +/* Some data may be written to STDOUT */ static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { ssize_t r; assert(a == mainloop_api && e && stdio_event == e); @@ -262,12 +272,14 @@ static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int } } +/* UNIX signal to quit recieved */ static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); } +/* Show the current playback latency */ static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, void *userdata) { assert(s); @@ -280,6 +292,7 @@ static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, v fprintf(stderr, "Current latency is %u usecs.\n", latency); } +/* Someone requested that the latency is shown */ static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { if (mode != PLAYBACK) return; @@ -295,6 +308,8 @@ int main(int argc, char *argv[]) { if (!(bn = strrchr(argv[0], '/'))) bn = argv[0]; + else + bn++; if (strstr(bn, "rec") || strstr(bn, "mon")) mode = RECORD; @@ -302,7 +317,8 @@ int main(int argc, char *argv[]) { mode = PLAYBACK; fprintf(stderr, "Opening a %s stream.\n", mode == RECORD ? "recording" : "playback"); - + + /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); goto quit; @@ -323,16 +339,19 @@ int main(int argc, char *argv[]) { fprintf(stderr, "source_io() failed.\n"); goto quit; } - - if (!(context = pa_context_new(mainloop_api, argv[0]))) { + + /* Create a new connection context */ + if (!(context = pa_context_new(mainloop_api, bn))) { fprintf(stderr, "pa_context_new() failed.\n"); goto quit; } pa_context_set_state_callback(context, context_state_callback, NULL); + /* Connect the context */ pa_context_connect(context, NULL); + /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { fprintf(stderr, "pa_mainloop_run() failed.\n"); goto quit; diff --git a/polyp/parec-simple.c b/polyp/parec-simple.c index e12b8e004..74f0a0f7a 100644 --- a/polyp/parec-simple.c +++ b/polyp/parec-simple.c @@ -33,6 +33,7 @@ #define BUFSIZE 1024 +/* A simple routine calling UNIX write() in a loop */ static ssize_t loop_write(int fd, const void*data, size_t size) { ssize_t ret = 0; @@ -54,6 +55,7 @@ static ssize_t loop_write(int fd, const void*data, size_t size) { } int main(int argc, char*argv[]) { + /* The sample type to use */ static const struct pa_sample_spec ss = { .format = PA_SAMPLE_S16LE, .rate = 44100, @@ -63,6 +65,7 @@ int main(int argc, char*argv[]) { int ret = 1; int error; + /* Create the recording stream */ if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, &error))) { fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); goto finish; @@ -72,11 +75,13 @@ int main(int argc, char*argv[]) { uint8_t buf[BUFSIZE]; ssize_t r; + /* Record some data ... */ if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) { fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error)); goto finish; } - + + /* And write it to STDOUT */ if ((r = loop_write(STDOUT_FILENO, buf, sizeof(buf))) <= 0) { fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno)); goto finish; diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 6a1cc8bd8..9614ce698 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -29,23 +29,25 @@ #include "polyplib-operation.h" /** \file - * Connection contexts */ + * Connection contexts for asynchrononous communication with a + * server. A pa_context object wraps a connection to a polypaudio + * server using its native protocol. A context may be used to issue + * commands on the server or to create playback or recording + * streams. Multiple playback streams may be piped through a single + * connection context. Operations on the contect involving + * communication with the server are executed asynchronously: i.e. the + * client function do not implicitely wait for completion of the + * operation on the server. Instead the caller specifies a call back + * function that is called when the operation is completed. Currently + * running operations may be canceled using pa_operation_cancel(). */ + +/** \example pacat.c + * A playback and recording tool using the asynchronous API */ PA_C_DECL_BEGIN -/** The state of a connection context */ -enum pa_context_state { - PA_CONTEXT_UNCONNECTED, /**< The context hasn't been connected yet */ - PA_CONTEXT_CONNECTING, /**< A connection is being established */ - PA_CONTEXT_AUTHORIZING, /**< The client is authorizing itself to the daemon */ - PA_CONTEXT_SETTING_NAME, /**< The client is passing its application name to the daemon */ - PA_CONTEXT_READY, /**< The connection is established, the context is ready to execute operations */ - PA_CONTEXT_FAILED, /**< The connection failed or was disconnected */ - PA_CONTEXT_TERMINATED /**< The connect was terminated cleanly */ -}; - /** \struct pa_context - * A connection context to a daemon */ + * An opaque connection context to a daemon */ struct pa_context; /** Instantiate a new connection context with an abstract mainloop API diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index fc19be697..8a506c8d8 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -23,28 +23,111 @@ ***/ #include -#include "native-common.h" #include "cdecl.h" +/** \file + * Global definitions */ + PA_C_DECL_BEGIN -enum pa_stream_direction { - PA_STREAM_NODIRECTION, - PA_STREAM_PLAYBACK, - PA_STREAM_RECORD, - PA_STREAM_UPLOAD +/** The state of a connection context */ +enum pa_context_state { + PA_CONTEXT_UNCONNECTED, /**< The context hasn't been connected yet */ + PA_CONTEXT_CONNECTING, /**< A connection is being established */ + PA_CONTEXT_AUTHORIZING, /**< The client is authorizing itself to the daemon */ + PA_CONTEXT_SETTING_NAME, /**< The client is passing its application name to the daemon */ + PA_CONTEXT_READY, /**< The connection is established, the context is ready to execute operations */ + PA_CONTEXT_FAILED, /**< The connection failed or was disconnected */ + PA_CONTEXT_TERMINATED /**< The connection was terminated cleanly */ }; -struct pa_buffer_attr { - uint32_t maxlength; - uint32_t tlength; - uint32_t prebuf; - uint32_t minreq; - uint32_t fragsize; +/** The state of a stream */ +enum pa_stream_state { + PA_STREAM_DISCONNECTED, /**< The stream is not yet connected to any sink or source */ + PA_STREAM_CREATING, /**< The stream is being created */ + PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */ + PA_STREAM_FAILED, /**< An error occured that made the stream invalid */ + PA_STREAM_TERMINATED, /**< The stream has been terminated cleanly */ }; +/** The state of an operation */ +enum pa_operation_state { + PA_OPERATION_RUNNING, /**< The operation is still running */ + PA_OPERATION_DONE, /**< The operation has been completed */ + PA_OPERATION_CANCELED, /**< The operation has been canceled */ +}; + +/** An invalid index */ #define PA_INVALID_INDEX ((uint32_t) -1) +/** The direction of a pa_stream object */ +enum pa_stream_direction { + PA_STREAM_NODIRECTION, /**< Invalid direction */ + PA_STREAM_PLAYBACK, /**< Playback stream */ + PA_STREAM_RECORD, /**< Record stream */ + PA_STREAM_UPLOAD /**< Sample upload stream */ +}; + +/** Playback and record buffer metrics */ +struct pa_buffer_attr{ + uint32_t maxlength; /**< Maximum length of the buffer */ + uint32_t tlength; /**< Playback only: target length of the buffer. The server tries to assure that at least tlength bytes are always available in the buffer */ + uint32_t prebuf; /**< Playback only: pre-buffering. The server does not start with playback before at least prebug bytes are available in the buffer */ + uint32_t minreq; /**< Playback only: minimum request. The server does not request less than minreq bytes from the client, instead waints until the buffer is free enough to request more bytes at once */ + uint32_t fragsize; /**< Recording only: fragment size. The server sends data in blocks of fragsize bytes size. Large values deminish interactivity with other operations on the connection context but decrease control overhead. */ +}; + +/** Error values as used by pa_context_errno(). Use pa_strerror() to convert these values to human readable strings */ +enum { + PA_ERROR_OK, /**< No error */ + PA_ERROR_ACCESS, /**< Access failure */ + PA_ERROR_COMMAND, /**< Unknown command */ + PA_ERROR_INVALID, /**< Invalid argument */ + PA_ERROR_EXIST, /**< Entity exists */ + PA_ERROR_NOENTITY, /**< No such entity */ + PA_ERROR_CONNECTIONREFUSED, /**< Connection refused */ + PA_ERROR_PROTOCOL, /**< Protocol error */ + PA_ERROR_TIMEOUT, /**< Timeout */ + PA_ERROR_AUTHKEY, /**< No authorization key */ + PA_ERROR_INTERNAL, /**< Internal error */ + PA_ERROR_CONNECTIONTERMINATED, /**< Connection terminated */ + PA_ERROR_KILLED, /**< Entity killed */ + PA_ERROR_INVALIDSERVER, /**< Invalid server */ + PA_ERROR_MAX /**< Not really an error but the first invalid error code */ +}; + +/** Subscription event mask, as used by pa_context_subscribe() */ +enum pa_subscription_mask { + PA_SUBSCRIPTION_MASK_NULL = 0, /**< No events */ + PA_SUBSCRIPTION_MASK_SINK = 1, /**< Sink events */ + PA_SUBSCRIPTION_MASK_SOURCE = 2, /**< Source events */ + PA_SUBSCRIPTION_MASK_SINK_INPUT = 4, /**< Sink input events */ + PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8, /**< Source output events */ + PA_SUBSCRIPTION_MASK_MODULE = 16, /**< Module events */ + PA_SUBSCRIPTION_MASK_CLIENT = 32, /**< Client events */ + PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */ +}; + +/** Subscription event types, as used by pa_context_subscribe() */ +enum pa_subscription_event_type { + PA_SUBSCRIPTION_EVENT_SINK = 0, /**< Event type: Sink */ + PA_SUBSCRIPTION_EVENT_SOURCE = 1, /**< Event type: Source */ + PA_SUBSCRIPTION_EVENT_SINK_INPUT = 2, /**< Event type: Sink input */ + PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 3, /**< Event type: Source output */ + PA_SUBSCRIPTION_EVENT_MODULE = 4, /**< Event type: Module */ + PA_SUBSCRIPTION_EVENT_CLIENT = 5, /**< Event type: Client */ + PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6, /**< Event type: Sample cache item */ + PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 7, /**< A mask to extract the event type from an event value */ + + PA_SUBSCRIPTION_EVENT_NEW = 0, /**< A new object was created */ + PA_SUBSCRIPTION_EVENT_CHANGE = 16, /**< A property of the object was modified */ + PA_SUBSCRIPTION_EVENT_REMOVE = 32, /**< An object was removed */ + PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32, /**< A mask to extract the event operation from an event value */ +}; + +/** Return one if an event type t matches an event mask bitfield */ +#define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) + PA_C_DECL_END #endif diff --git a/polyp/polyplib-error.c b/polyp/polyplib-error.c index 10b637c4d..24054f2ef 100644 --- a/polyp/polyplib-error.c +++ b/polyp/polyplib-error.c @@ -37,12 +37,13 @@ static const char* const errortab[PA_ERROR_MAX] = { [PA_ERROR_EXIST] = "Entity exists", [PA_ERROR_NOENTITY] = "No such entity", [PA_ERROR_CONNECTIONREFUSED] = "Connection refused", - [PA_ERROR_PROTOCOL] = "Protocol corrupt", + [PA_ERROR_PROTOCOL] = "Protocol error", [PA_ERROR_TIMEOUT] = "Timeout", - [PA_ERROR_AUTHKEY] = "Not authorization key", + [PA_ERROR_AUTHKEY] = "No authorization key", [PA_ERROR_INTERNAL] = "Internal error", [PA_ERROR_CONNECTIONTERMINATED] = "Connection terminated", [PA_ERROR_KILLED] = "Entity killed", + [PA_ERROR_INVALIDSERVER] = "Invalid server", }; const char*pa_strerror(uint32_t error) { diff --git a/polyp/polyplib-error.h b/polyp/polyplib-error.h index 437d618e1..8b5cd9104 100644 --- a/polyp/polyplib-error.h +++ b/polyp/polyplib-error.h @@ -25,6 +25,9 @@ #include #include "cdecl.h" +/** \file + * Error management */ + PA_C_DECL_BEGIN /** Return a human readable error message for the specified numeric error code */ diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 0b6b3887c..c8228a862 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -32,6 +32,7 @@ #include "polyplib-stream.h" #include "polyplib-operation.h" #include "llist.h" +#include "native-common.h" #define DEFAULT_MAXLENGTH 204800 #define DEFAULT_TLENGTH 10240 diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index aa70a111f..9a7ec1579 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -514,7 +514,7 @@ struct pa_operation* pa_context_get_source_output_info_list(struct pa_context *c /*** Volume manipulation ***/ -struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { +struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { struct pa_operation *o; struct pa_tagstruct *t; uint32_t tag; @@ -536,7 +536,7 @@ struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, u return pa_operation_ref(o); } -struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { +struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { struct pa_operation *o; struct pa_tagstruct *t; uint32_t tag; @@ -558,7 +558,7 @@ struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, co return pa_operation_ref(o); } -struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { +struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { struct pa_operation *o; struct pa_tagstruct *t; uint32_t tag; diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index e83ba73b7..dfa24ed55 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -28,6 +28,9 @@ #include "polyplib-context.h" #include "cdecl.h" +/** \file + * Routines for daemon introspection. */ + PA_C_DECL_BEGIN struct pa_sink_info { @@ -36,7 +39,7 @@ struct pa_sink_info { const char *description; struct pa_sample_spec sample_spec; uint32_t owner_module; - uint32_t volume; + pa_volume_t volume; uint32_t monitor_source; const char *monitor_source_name; uint32_t latency; @@ -60,12 +63,13 @@ struct pa_operation* pa_context_get_source_info_by_name(struct pa_context *c, co struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); struct pa_operation* pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +/** Server information */ struct pa_server_info { - const char *user_name; - const char *host_name; - const char *server_version; - const char *server_name; - struct pa_sample_spec sample_spec; + const char *user_name; /**< User name of the daemon process */ + const char *host_name; /**< Host name the daemon is running on */ + const char *server_version; /**< Version string of the daemon */ + const char *server_name; /**< Server package name (usually "polypaudio") */ + struct pa_sample_spec sample_spec; /**< Default sample specification */ }; struct pa_operation* pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); @@ -96,7 +100,7 @@ struct pa_sink_input_info { uint32_t client; uint32_t sink; struct pa_sample_spec sample_spec; - uint32_t volume; + pa_volume_t volume; uint32_t latency; }; @@ -115,15 +119,22 @@ struct pa_source_output_info { struct pa_operation* pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); struct pa_operation* pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); -struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); -struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +/** Set the volume of a sink device specified by its index */ +struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +/** Set the volume of a sink device specified by its name */ +struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +/** Set the volume of a sink input stream */ +struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +/** Memory block statistics */ struct pa_stat_info { - uint32_t memblock_count; - uint32_t memblock_total; + uint32_t memblock_count; /**< Allocated memory blocks */ + uint32_t memblock_total; /**< Total size of allocated memory blocks */ }; +/** Get daemon memory block statistics */ struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info *i, void *userdata), void *userdata); PA_C_DECL_END diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h index 7d0adc260..ce2756efb 100644 --- a/polyp/polyplib-operation.h +++ b/polyp/polyplib-operation.h @@ -29,12 +29,6 @@ PA_C_DECL_BEGIN -enum pa_operation_state { - PA_OPERATION_RUNNING, /**< The operation is still running */ - PA_OPERATION_DONE, /**< The operation has been completed */ - PA_OPERATION_CANCELED, /**< The operation has been canceled */ -}; - /** \struct pa_operation * An asynchronous operation object */ struct pa_operation; diff --git a/polyp/polyplib-simple.h b/polyp/polyplib-simple.h index ee2e27e3f..ed552cb46 100644 --- a/polyp/polyplib-simple.h +++ b/polyp/polyplib-simple.h @@ -29,12 +29,20 @@ #include "cdecl.h" /** \file - * A simple but limited synchronous playback and recording API. */ + * A simple but limited synchronous playback and recording + * API. This is synchronouse, simplified wrapper around the standard + * asynchronous API. */ + +/** \example pacat-simple.c + * A simple playback tool using the simple API */ + +/** \example parec-simple.c + * A simple recording tool using the simple API */ PA_C_DECL_BEGIN /** \struct pa_simple - * A simple connection object */ + * An opaque simple connection object */ struct pa_simple; /** Create a new connection to the server */ diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index 41801c6c4..1a9d58dd2 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -34,17 +34,8 @@ PA_C_DECL_BEGIN -/** The state of a stream */ -enum pa_stream_state { - PA_STREAM_DISCONNECTED, /**< The stream is not yet connected to any sink or source */ - PA_STREAM_CREATING, /**< The stream is being created */ - PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */ - PA_STREAM_FAILED, /**< An error occured that made the stream invalid */ - PA_STREAM_TERMINATED, /**< The stream has been terminated cleanly */ -}; - /** \struct pa_stream - * A stream for playback or recording */ + * An opaque stream for playback or recording */ struct pa_stream; /** Create a new, unconnected stream with the specified name and sample type */ diff --git a/polyp/polyplib-subscribe.h b/polyp/polyplib-subscribe.h index 563849151..bd0e03991 100644 --- a/polyp/polyplib-subscribe.h +++ b/polyp/polyplib-subscribe.h @@ -28,9 +28,18 @@ #include "polyplib-context.h" #include "cdecl.h" +/** \file + * Daemon introspection event subscription subsystem. Use this + * to be notified whenever the internal layout of daemon changes: + * i.e. entities such as sinks or sources are create, removed or + * modified. */ + PA_C_DECL_BEGIN +/** Enable event notification */ struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +/** Set the context specific call back function that is called whenever the state of the daemon changes */ void pa_context_set_subscribe_callback(struct pa_context *c, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); PA_C_DECL_END diff --git a/polyp/polyplib.h b/polyp/polyplib.h index b9e5637ce..daaed6494 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -31,4 +31,54 @@ #include "polyplib-subscribe.h" #include "polyplib-scache.h" +/** \file + * Include all polyplib header file at once. The following files are included: \ref mainloop-api.h, \ref sample.h, + * \ref polyplib-def.h, \ref polyplib-context.h, \ref polyplib-stream.h, + * \ref polyplib-introspect.h, \ref polyplib-subscribe.h and \ref polyplib-scache.h + * at once */ + +/** \mainpage + * + * \section intro_sec Introduction + * + * This document describes the client API for the polypaudio sound + * server. The API comes in two flavours: + * + * \li The complete but somewhat complicated to use asynchronous API + * \li And the simplified, easy to use, but limited synchronous API + * + * The polypaudio client libraries are thread safe as long as all + * objects created by any library function are accessed from the thread + * that created them only. + * + * \section simple_sec Simple API + * + * Use this if you develop your program in synchronous style and just + * need a way to play or record data on the sound server. See + * \ref polyplib-simple.h for more details. + * + * \section async_api Asynchronous API + * + * Use this if you develop your programs in asynchronous, main loop + * based style or want to use advanced features of the polypaudio + * API. A good starting point is \ref polyplib-context.h + * + * The asynchronous API relies on an abstract main loop API that is + * described in \ref mainloop-api.h. Two distinct implementations are + * available: + * + * \li \ref mainloop.h: a minimal but fast implementation based on poll() + * \li \ref glib-mainloop.h: a wrapper around GLIB's main loop + * + * UNIX signals may be hooked to a main loop using the functions from + * \ref mainloop-signal.h + * + * \section pkgconfig pkg-config + * + * The polypaudio libraries provide pkg-config snippets for the different modules. To use the + * asynchronous API use "polyplib" as pkg-config file. GLIB main loop + * support is available as "polyplib-glib-mainloop". The simple + * synchronous API is available as "polyplib-simple". + */ + #endif diff --git a/polyp/sample-util.h b/polyp/sample-util.h index 66f40a16a..9f3fced16 100644 --- a/polyp/sample-util.h +++ b/polyp/sample-util.h @@ -33,12 +33,12 @@ void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec struct pa_mix_info { struct pa_memchunk chunk; - uint32_t volume; + pa_volume_t volume; void *userdata; }; -size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, uint32_t volume); +size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, pa_volume_t volume); -void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, uint32_t volume); +void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, pa_volume_t volume); #endif diff --git a/polyp/sample.c b/polyp/sample.c index 4f93f2b7e..173de9c1c 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -82,7 +82,7 @@ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_s return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels); } -void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { +void pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { static const char* const table[]= { [PA_SAMPLE_U8] = "U8", [PA_SAMPLE_ALAW] = "ALAW", @@ -97,10 +97,10 @@ void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { snprintf(s, l, "%s %uch %uHz", table[spec->format], spec->channels, spec->rate); } -uint32_t pa_volume_multiply(uint32_t a, uint32_t b) { +pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b) { uint64_t p = a; p *= b; p /= PA_VOLUME_NORM; - return (uint32_t) p; + return (pa_volume_t) p; } diff --git a/polyp/sample.h b/polyp/sample.h index e397a1dfe..459f8a302 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -27,26 +27,36 @@ #include "cdecl.h" +/** \file + * Constants and routines for sample type handling */ + PA_C_DECL_BEGIN +/** Sample format */ enum pa_sample_format { - PA_SAMPLE_U8, - PA_SAMPLE_ALAW, - PA_SAMPLE_ULAW, - PA_SAMPLE_S16LE, - PA_SAMPLE_S16BE, - PA_SAMPLE_FLOAT32LE, - PA_SAMPLE_FLOAT32BE, - PA_SAMPLE_MAX + PA_SAMPLE_U8, /**< Unsigned 8 Bit PCM */ + PA_SAMPLE_ALAW, /**< 8 Bit a-Law */ + PA_SAMPLE_ULAW, /**< 8 Bit mu-Law */ + PA_SAMPLE_S16LE, /**< Signed 16 Bit PCM, little endian (PC) */ + PA_SAMPLE_S16BE, /**< Signed 16 Bit PCM, big endian */ + PA_SAMPLE_FLOAT32LE, /**< 32 Bit IEEE floating point, little endian, range -1..1 */ + PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1..1 */ + PA_SAMPLE_MAX /**< Upper limit of valid sample types */ }; #ifdef WORDS_BIGENDIAN +/** Signed 16 Bit PCM, native endian */ #define PA_SAMPLE_S16NE PA_SAMPLE_S16BE +/** 32 Bit IEEE floating point, native endian */ #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32BE #else +/** Signed 16 Bit PCM, native endian */ #define PA_SAMPLE_S16NE PA_SAMPLE_S16LE +/** 32 Bit IEEE floating point, native endian */ #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32LE #endif + +/** A Shortcut for PA_SAMPLE_FLOAT32NE */ #define PA_SAMPLE_FLOAT32 PA_SAMPLE_FLOAT32NE /** A sample format and attribute specification */ @@ -56,23 +66,38 @@ struct pa_sample_spec { uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */ }; +/** Return the amount of bytes playback of a second of audio with the speicified sample type takes */ size_t pa_bytes_per_second(const struct pa_sample_spec *spec); + +/** Return the size of a frame with the specific sample type */ size_t pa_frame_size(const struct pa_sample_spec *spec); + +/** Calculate the time the specified bytes take to play with the specified sample type */ uint32_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec); + +/** Return non-zero when the sample type specification is valid */ int pa_sample_spec_valid(const struct pa_sample_spec *spec); + +/** Return non-zero when the two sample type specifications match */ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b); +/** Maximum required string length for pa_sample_spec_snprint() */ #define PA_SAMPLE_SNPRINT_MAX_LENGTH 32 -void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec); + +/** Pretty print a sample type specification to a string */ +void pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec); + +/** Volume specification: 0: silence; < 256: diminished volume; 256: normal volume; > 256 amplified volume */ +typedef uint32_t pa_volume_t; /** Normal volume (100%) */ #define PA_VOLUME_NORM (0x100) /** Muted volume (0%) */ -#define PA_VOLUME_MUTE (0) +#define PA_VOLUME_MUTED (0) /** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */ -uint32_t pa_volume_multiply(uint32_t a, uint32_t b); +pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b); PA_C_DECL_END diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 99ff8fe6a..7629bfb96 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -169,7 +169,7 @@ void pa_sink_input_drop(struct pa_sink_input *i, size_t length) { } } -void pa_sink_input_set_volume(struct pa_sink_input *i, uint32_t volume) { +void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume) { assert(i && i->sink && i->sink->core); if (i->volume != volume) { diff --git a/polyp/sink-input.h b/polyp/sink-input.h index b21dbf4d0..8d7788d8e 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -64,6 +64,6 @@ uint32_t pa_sink_input_get_latency(struct pa_sink_input *i); int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk); void pa_sink_input_drop(struct pa_sink_input *i, size_t length); -void pa_sink_input_set_volume(struct pa_sink_input *i, uint32_t volume); +void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume); #endif diff --git a/polyp/sink.c b/polyp/sink.c index b8617ae1e..eb3133ac1 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -283,7 +283,7 @@ void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) { pa_source_set_owner(sink->monitor_source, m); } -void pa_sink_set_volume(struct pa_sink *sink, uint32_t volume) { +void pa_sink_set_volume(struct pa_sink *sink, pa_volume_t volume) { assert(sink); if (sink->volume != volume) { diff --git a/polyp/sink.h b/polyp/sink.h index 2aa5d6112..8248d00cc 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -42,7 +42,7 @@ struct pa_sink { struct pa_source *monitor_source; - uint32_t volume; + pa_volume_t volume; void (*notify)(struct pa_sink*sink); uint32_t (*get_latency)(struct pa_sink *s); @@ -62,6 +62,6 @@ void pa_sink_notify(struct pa_sink*s); void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m); -void pa_sink_set_volume(struct pa_sink *sink, uint32_t volume); +void pa_sink_set_volume(struct pa_sink *sink, pa_volume_t volume); #endif diff --git a/polyplib-glib-mainloop.pc.in b/polyplib-glib-mainloop.pc.in new file mode 100644 index 000000000..f4c093307 --- /dev/null +++ b/polyplib-glib-mainloop.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: polyplib-glib-mainloop +Description: GLIB main loop wrapper for polypaudio +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lpolyp-mainloop-glib +Cflags: -D_REENTRANT -I${includedir} +Requires: polyplib-mainloop diff --git a/polyplib-mainloop.pc.in b/polyplib-mainloop.pc.in index f4bdba5bd..73e579a3a 100644 --- a/polyplib-mainloop.pc.in +++ b/polyplib-mainloop.pc.in @@ -4,7 +4,7 @@ libdir=${exec_prefix}/lib includedir=${prefix}/include Name: polyplib-mainloop -Description: Mainloop API of the polypaudio sound daemon +Description: Main loop support for polypaudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpolyp-mainloop Cflags: -D_REENTRANT -I${includedir} diff --git a/polyplib-simple.pc.in b/polyplib-simple.pc.in index efae94103..e5dcaa9e0 100644 --- a/polyplib-simple.pc.in +++ b/polyplib-simple.pc.in @@ -4,7 +4,8 @@ libdir=${exec_prefix}/lib includedir=${prefix}/include Name: polyplib-simple -Description: Simplistic client interface to polypaudio sound daemon +Description: Simplified synchronous client interface to polypaudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpolyp-simple Cflags: -D_REENTRANT -I${includedir} +Requires: polyplib polyplib-mainloop polyplib-error diff --git a/polyplib.pc.in b/polyplib.pc.in index 8a554cb14..b06c6e514 100644 --- a/polyplib.pc.in +++ b/polyplib.pc.in @@ -4,7 +4,8 @@ libdir=${exec_prefix}/lib includedir=${prefix}/include Name: polyplib -Description: Client interface to polypaudio sound daemon +Description: Client interface to polypaudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpolyp Cflags: -D_REENTRANT -I${includedir} +Requires: polyplib-error polyplib-mainloop From 711de8df9b78a46d4e12b810c26d26e9ead294e6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 17:56:09 +0000 Subject: [PATCH 0133/1514] autoconf beefup build fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@134 fefdeb5f-60dc-0310-8127-8f9354f1896f --- acinclude.m4 | 199 ++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 27 ++++++ polyp/Makefile.am | 31 ++++--- polyp/cli-text.c | 10 +-- polyp/sample-util.c | 10 +-- polyp/sink-input.c | 2 +- polyp/sink.c | 2 +- polyp/source.c | 2 +- polyp/util.c | 4 + 9 files changed, 264 insertions(+), 23 deletions(-) create mode 100644 acinclude.m4 diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 000000000..bedf51c32 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,199 @@ +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html +dnl +AC_DEFUN([ACX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthread or + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) + if test x"$acx_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: threads are created detached by default + # and the JOINABLE attribute has a nonstandard name (UNDETACHED). + AC_MSG_CHECKING([for joinable pthread attribute]) + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_JOINABLE;], + ok=PTHREAD_CREATE_JOINABLE, ok=unknown) + if test x"$ok" = xunknown; then + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_UNDETACHED;], + ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) + fi + if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then + AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, + [Define to the necessary symbol if this constant + uses a non-standard name on your system.]) + fi + AC_MSG_RESULT(${ok}) + if test x"$ok" = xunknown; then + AC_MSG_WARN([we do not know how to create joinable pthreads]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with cc_r + AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD diff --git a/configure.ac b/configure.ac index e6194d9f9..4e4bf3aa3 100644 --- a/configure.ac +++ b/configure.ac @@ -40,6 +40,33 @@ AC_SUBST(LIBLTDL) AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h]) + +ACX_PTHREAD +AC_PATH_XTRA +AM_CONDITIONAL(X_DISPLAY_MISSING, test "x$X_DISPLAY_MISSING" != "x") + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_HEADER_TIME + +# Checks for library functions. +AC_FUNC_FORK +AC_PROG_GCC_TRADITIONAL +AC_FUNC_LSTAT +AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK +AC_FUNC_MALLOC +AC_FUNC_MEMCMP +AC_FUNC_MMAP +AC_FUNC_REALLOC +AC_FUNC_SETPGRP +AC_TYPE_SIGNAL +AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul]) + AC_C_BIGENDIAN PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 791abf0ec..1f982515c 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -17,9 +17,9 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -AM_CFLAGS=-ansi -D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" -I$(srcdir)/.. -AM_LDADD=-L. -lpthread -AM_LIBADD=-L. -lpthread +AM_CFLAGS=-ansi -D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" -I$(srcdir)/.. $(PTHREAD_CFLAGS) +AM_LDADD=$(PTHREAD_LIBS) +AM_LIBADD=$(PTHREAD_LIBS) polypincludedir=$(includedir)/polyp @@ -75,8 +75,11 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-esound-protocol-tcp.la \ module-esound-protocol-unix.la \ module-native-protocol-tcp.la \ - module-native-protocol-unix.la \ - module-x11-bell.la + module-native-protocol-unix.la + +if !X_DISPLAY_MISSING +pkglib_LTLIBRARIES+=module-x11-bell.la +endif lib_LTLIBRARIES=libpolyp.la \ libpolyp-error.la \ @@ -265,9 +268,12 @@ module_cli_la_SOURCES = module-cli.c module_cli_la_LDFLAGS = -module -avoid-version module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la +if !X_DISPLAY_MISSING module_x11_bell_la_SOURCES = module-x11-bell.c +module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_bell_la_LDFLAGS = -module -avoid-version -module_x11_bell_la_LIBADD = $(AM_LIBADD) -lX11 -L/usr/X11R6/lib +module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) $(X_LIBS) $(X_EXTRA_LIB) +endif libpolyp_la_SOURCES = polyplib.h \ polyplib-def.h \ @@ -299,20 +305,29 @@ libpolyp_la_SOURCES = polyplib.h \ cdecl.h \ llist.h libpolyp_la_CFLAGS = $(AM_CFLAGS) +libpolyp_la_LDFLAGS = -version-info 0:0:0 libpolyp_mainloop_la_SOURCES = mainloop-api.h mainloop-api.c \ mainloop.c mainloop.h \ mainloop-signal.c mainloop-signal.h libpolyp_mainloop_la_CFLAGS = $(AM_CFLAGS) libpolyp_mainloop_la_LIBADD = $(AM_LIBADD) libpolyp.la +libpolyp_mainloop_la_LDFLAGS = -version-info 0:0:0 libpolyp_error_la_SOURCES = polyplib-error.c polyplib-error.h libpolyp_error_la_CFLAGS = $(AM_CFLAGS) libpolyp_error_la_LIBADD = $(AM_LIBADD) libpolyp.la +libpolyp_error_la_LDFLAGS = -version-info 0:0:0 libpolyp_simple_la_SOURCES = polyplib-simple.c polyplib-simple.h libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) libpolyp_simple_la_LIBADD = $(AM_LIBADD) libpolyp.la libpolyp-mainloop.la +libpolyp_simple_la_LDFLAGS = -version-info 0:0:0 + +libpolyp_mainloop_glib_la_SOURCES = glib-mainloop.h glib-mainloop.c +libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) +libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB20_LIBS) +libpolyp_mainloop_glib_la_LDFLAGS = -version-info 0:0:0 pacat_SOURCES = pacat.c pacat_LDADD = $(AM_LDADD) libpolyp.la libpolyp-error.la libpolyp-mainloop.la @@ -330,10 +345,6 @@ parec_simple_SOURCES = parec-simple.c parec_simple_LDADD = $(AM_LDADD) libpolyp.la libpolyp-simple.la libpolyp-error.la parec_simple_CFLAGS = $(AM_CFLAGS) -libpolyp_mainloop_glib_la_SOURCES = glib-mainloop.h glib-mainloop.c -libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) -libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB20_LIBS) - mainloop_test_SOURCES = mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop.la libpolyp.la diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 558b53ca9..000d6d344 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -89,7 +89,7 @@ char *pa_sink_list_to_string(struct pa_core *c) { for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index)) { char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - pa_sample_snprint(ss, sizeof(ss), &sink->sample_spec); + pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec); assert(sink->monitor_source); pa_strbuf_printf( s, @@ -123,7 +123,7 @@ char *pa_source_list_to_string(struct pa_core *c) { for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - pa_sample_snprint(ss, sizeof(ss), &source->sample_spec); + pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec); pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tsample_spec: <%s>\n", c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ', source->index, @@ -155,7 +155,7 @@ char *pa_source_output_list_to_string(struct pa_core *c) { for (o = pa_idxset_first(c->source_outputs, &index); o; o = pa_idxset_next(c->source_outputs, &index)) { char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - pa_sample_snprint(ss, sizeof(ss), &o->sample_spec); + pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec); assert(o->source); pa_strbuf_printf( s, " index: %u\n\tname: <%s>\n\tsource: <%u>\n\tsample_spec: <%s>\n", @@ -185,7 +185,7 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { for (i = pa_idxset_first(c->sink_inputs, &index); i; i = pa_idxset_next(c->sink_inputs, &index)) { char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - pa_sample_snprint(ss, sizeof(ss), &i->sample_spec); + pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); pa_strbuf_printf( s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tsample_spec: <%s>\n", @@ -221,7 +221,7 @@ char *pa_scache_list_to_string(struct pa_core *c) { while ((e = pa_hashmap_iterate(c->scache_hashmap, &state))) { double l; char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - pa_sample_snprint(ss, sizeof(ss), &e->sample_spec); + pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec); l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec); diff --git a/polyp/sample-util.c b/polyp/sample-util.c index 8f5558a4a..6a09478f6 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -64,7 +64,7 @@ void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec memset(p, c, length); } -size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, uint32_t volume) { +size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, pa_volume_t volume) { unsigned c, d; assert(channels && data && length && spec); assert(spec->format == PA_SAMPLE_S16NE); @@ -82,7 +82,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz if (d >= channels[c].chunk.length) return d; - if (volume == PA_VOLUME_MUTE) + if (volume == PA_VOLUME_MUTED) v = 0; else { v = *((int16_t*) (channels[c].chunk.memblock->data + channels[c].chunk.index + d)); @@ -94,7 +94,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz sum += v; } - if (volume == PA_VOLUME_MUTE) + if (volume == PA_VOLUME_MUTED) sum = 0; else if (volume != PA_VOLUME_NORM) sum = (int32_t) ((float) sum*volume/PA_VOLUME_NORM); @@ -108,7 +108,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz } -void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, uint32_t volume) { +void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, pa_volume_t volume) { int16_t *d; size_t n; assert(c && spec && (c->length % pa_frame_size(spec) == 0)); @@ -117,7 +117,7 @@ void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, if (volume == PA_VOLUME_NORM) return; - if (volume == PA_VOLUME_MUTE) { + if (volume == PA_VOLUME_MUTED) { pa_silence_memchunk(c, spec); return; } diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 7629bfb96..efa8c551c 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -71,7 +71,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con r = pa_idxset_put(s->inputs, i, NULL); assert(r == 0); - pa_sample_snprint(st, sizeof(st), spec); + pa_sample_spec_snprint(st, sizeof(st), spec); fprintf(stderr, "sink-input: created %u \"%s\" on %u with sample spec \"%s\"\n", i->index, i->name, s->index, st); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); diff --git a/polyp/sink.c b/polyp/sink.c index eb3133ac1..becaef9e5 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -76,7 +76,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co r = pa_idxset_put(core->sinks, s, &s->index); assert(s->index != PA_IDXSET_INVALID && r >= 0); - pa_sample_snprint(st, sizeof(st), spec); + pa_sample_spec_snprint(st, sizeof(st), spec); fprintf(stderr, "sink: created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); diff --git a/polyp/source.c b/polyp/source.c index 2c6116513..6ab439d66 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -62,7 +62,7 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail r = pa_idxset_put(core->sources, s, &s->index); assert(s->index != PA_IDXSET_INVALID && r >= 0); - pa_sample_snprint(st, sizeof(st), spec); + pa_sample_spec_snprint(st, sizeof(st), spec); fprintf(stderr, "source: created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); diff --git a/polyp/util.c b/polyp/util.c index 70766a068..2878c546b 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -114,12 +114,16 @@ void pa_check_for_sigpipe(void) { struct sigaction sa; sigset_t set; +#ifdef HAVE_PTHREAD if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) { +#endif if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) { fprintf(stderr, __FILE__": sigprocmask() failed: %s\n", strerror(errno)); return; } +#ifdef HAVE_PTHREAD } +#endif if (sigismember(&set, SIGPIPE)) return; From 2d6d3e5c474544fd8dc4e59695a20f8cbab976fe Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 17:57:09 +0000 Subject: [PATCH 0134/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@135 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/doc/todo b/doc/todo index aa65d3396..887b8043f 100644 --- a/doc/todo +++ b/doc/todo @@ -2,18 +2,14 @@ *** 0.2 *** -- future cancellation -- make mcalign merge chunks -- ref counting foo - pacat quit() ? - -- doxygen - - several files: copyright and config.h - enable searchdir -- autoscan *** 0.3 *** +- future cancellation +- make mcalign merge chunks +- use ref counting in more objects - move the global memblock statistics variables to the core - unix socket directories include user name - native library/protocol: From 81822a751929fbc153282de3af447b9430d5c474 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 18:53:42 +0000 Subject: [PATCH 0135/1514] fix x11 build disable prebuf on drain git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@136 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 2 +- polyp/memblockq.c | 5 +++++ polyp/memblockq.h | 5 ++++- polyp/pacat.c | 5 +---- polyp/protocol-native.c | 4 ++++ 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 1f982515c..5a49201ab 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -272,7 +272,7 @@ if !X_DISPLAY_MISSING module_x11_bell_la_SOURCES = module-x11-bell.c module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_bell_la_LDFLAGS = -module -avoid-version -module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) $(X_LIBS) $(X_EXTRA_LIB) +module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) endif libpolyp_la_SOURCES = polyplib.h \ diff --git a/polyp/memblockq.c b/polyp/memblockq.c index 4019c893b..8f499df0b 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -323,3 +323,8 @@ uint32_t pa_memblockq_get_minreq(struct pa_memblockq *bq) { assert(bq); return bq->minreq; } + +void pa_memblockq_prebuf_disable(struct pa_memblockq *bq) { + assert(bq); + bq->prebuf = 0; +} diff --git a/polyp/memblockq.h b/polyp/memblockq.h index e6ad01db8..40184703e 100644 --- a/polyp/memblockq.h +++ b/polyp/memblockq.h @@ -76,7 +76,10 @@ uint32_t pa_memblockq_get_length(struct pa_memblockq *bq); /* Return how many bytes are missing in queue to the specified fill amount */ uint32_t pa_memblockq_missing(struct pa_memblockq *bq); - +/* Returns the minimal request value */ uint32_t pa_memblockq_get_minreq(struct pa_memblockq *bq); +/* Force disabling of pre-buf even when the pre-buffer is not yet filled */ +void pa_memblockq_prebuf_disable(struct pa_memblockq *bq); + #endif diff --git a/polyp/pacat.c b/polyp/pacat.c index 4f3bf0016..2c7044b8c 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -113,16 +113,13 @@ static void stream_state_callback(struct pa_stream *s, void *userdata) { switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: + case PA_STREAM_TERMINATED: break; case PA_STREAM_READY: fprintf(stderr, "Stream successfully created\n"); break; - case PA_STREAM_TERMINATED: - quit(0); - break; - case PA_STREAM_FAILED: default: fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 1fafc9844..e86c78f00 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -748,12 +748,16 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm } s->drain_request = 0; + + pa_memblockq_prebuf_disable(s->memblockq); if (!pa_memblockq_is_readable(s->memblockq)) pa_pstream_send_simple_ack(c->pstream, tag); else { s->drain_request = 1; s->drain_tag = tag; + + pa_sink_notify(s->sink_input->sink); } } From e75b65715b2fc9a3363bd4ac598fe02888b7ed21 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 19:37:29 +0000 Subject: [PATCH 0136/1514] remove global memblock statistic variables in favor of memblock_stat objects git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@137 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 -- polyp/cli-command.c | 6 ++-- polyp/core.c | 4 +++ polyp/core.h | 3 ++ polyp/memblock.c | 71 +++++++++++++++++++++++++++---------- polyp/memblock.h | 24 +++++++++---- polyp/memblockq.c | 7 ++-- polyp/memblockq.h | 3 +- polyp/memchunk.c | 10 +++--- polyp/memchunk.h | 4 +-- polyp/module-alsa-sink.c | 2 +- polyp/module-alsa-source.c | 2 +- polyp/module-oss-mmap.c | 4 +-- polyp/module-oss.c | 4 +-- polyp/pactl.c | 4 ++- polyp/polyplib-context.c | 8 +++-- polyp/polyplib-internal.h | 2 ++ polyp/polyplib-introspect.c | 6 ++-- polyp/polyplib-introspect.h | 6 ++-- polyp/polyplib-stream.c | 4 +-- polyp/protocol-esound.c | 8 ++--- polyp/protocol-native.c | 14 ++++---- polyp/protocol-simple.c | 6 ++-- polyp/pstream.c | 8 +++-- polyp/pstream.h | 2 +- polyp/resampler.c | 8 +++-- polyp/resampler.h | 2 +- polyp/sink-input.c | 2 +- polyp/sink.c | 4 +-- polyp/sound-file.c | 4 +-- polyp/sound-file.h | 2 +- polyp/source-output.c | 2 +- 32 files changed, 158 insertions(+), 80 deletions(-) diff --git a/doc/todo b/doc/todo index 887b8043f..7814321d0 100644 --- a/doc/todo +++ b/doc/todo @@ -2,7 +2,6 @@ *** 0.2 *** -- pacat quit() ? - several files: copyright and config.h - enable searchdir @@ -10,7 +9,6 @@ - future cancellation - make mcalign merge chunks - use ref counting in more objects -- move the global memblock statistics variables to the core - unix socket directories include user name - native library/protocol: module load/unload diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 8459d71b6..5a8ff1770 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -210,7 +210,7 @@ static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { assert(c && t); - pa_strbuf_printf(buf, "Memory blocks allocated: %u, total size: %u bytes.\n", pa_memblock_get_count(), pa_memblock_get_total()); + pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %u bytes.\nMemory blocks allocated during the whole lifetime: %u, size: %u bytes.\n", c->memblock_stat->total, c->memblock_stat->total_size, c->memblock_stat->allocated, c->memblock_stat->allocated_size); return 0; } @@ -504,7 +504,7 @@ static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, return -1; } - if (pa_sound_file_load(fname, &ss, &chunk) < 0) { + if (pa_sound_file_load(fname, &ss, &chunk, c->memblock_stat) < 0) { pa_strbuf_puts(buf, "Failed to load sound file.\n"); return -1; } @@ -532,7 +532,7 @@ static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, s return -1; } - if (pa_sound_file_load(fname, &ss, &chunk) < 0) { + if (pa_sound_file_load(fname, &ss, &chunk, c->memblock_stat) < 0) { pa_strbuf_puts(buf, "Failed to load sound file.\n"); return -1; } diff --git a/polyp/core.c b/polyp/core.c index 55944aad8..b43eb639d 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -68,6 +68,8 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->subscription_defer_event = NULL; c->subscription_event_queue = NULL; c->subscriptions = NULL; + + c->memblock_stat = pa_memblock_stat_new(); pa_check_for_sigpipe(); @@ -102,6 +104,8 @@ void pa_core_free(struct pa_core *c) { pa_xfree(c->default_source_name); pa_xfree(c->default_sink_name); + + pa_memblock_stat_unref(c->memblock_stat); pa_xfree(c); }; diff --git a/polyp/core.h b/polyp/core.h index 436917714..c0a2d6d8c 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -26,6 +26,7 @@ #include "hashmap.h" #include "mainloop-api.h" #include "sample.h" +#include "memblock.h" struct pa_core { struct pa_mainloop_api *mainloop; @@ -43,6 +44,8 @@ struct pa_core { struct pa_defer_event *subscription_defer_event; struct pa_queue *subscription_event_queue; struct pa_subscription *subscriptions; + + struct pa_memblock_stat *memblock_stat; }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/polyp/memblock.c b/polyp/memblock.c index a4452efa4..500d8b206 100644 --- a/polyp/memblock.c +++ b/polyp/memblock.c @@ -31,45 +31,63 @@ #include "memblock.h" #include "xmalloc.h" -static unsigned memblock_count = 0, memblock_total = 0; +static void stat_add(struct pa_memblock*m, struct pa_memblock_stat *s) { + assert(m); -struct pa_memblock *pa_memblock_new(size_t length) { + m->stat = pa_memblock_stat_ref(s); + s->total++; + s->allocated++; + s->total_size += m->length; + s->allocated_size += m->length; +} + +static void stat_remove(struct pa_memblock *m) { + assert(m); + + if (!m->stat) + return; + + m->stat->total--; + m->stat->total_size -= m->length; + + pa_memblock_stat_unref(m->stat); + m->stat = NULL; +} + +struct pa_memblock *pa_memblock_new(size_t length, struct pa_memblock_stat*s) { struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)+length); b->type = PA_MEMBLOCK_APPENDED; b->ref = 1; b->length = length; b->data = b+1; b->free_cb = NULL; - memblock_count++; - memblock_total += length; + stat_add(b, s); return b; } -struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length) { +struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length, struct pa_memblock_stat*s) { struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)); b->type = PA_MEMBLOCK_FIXED; b->ref = 1; b->length = length; b->data = d; b->free_cb = NULL; - memblock_count++; - memblock_total += length; + stat_add(b, s); return b; } -struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length) { +struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length, struct pa_memblock_stat*s) { struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)); b->type = PA_MEMBLOCK_DYNAMIC; b->ref = 1; b->length = length; b->data = d; b->free_cb = NULL; - memblock_count++; - memblock_total += length; + stat_add(b, s); return b; } -struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p)) { +struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p), struct pa_memblock_stat*s) { struct pa_memblock *b; assert(d && length && free_cb); b = pa_xmalloc(sizeof(struct pa_memblock)); @@ -78,8 +96,7 @@ struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb) b->length = length; b->data = d; b->free_cb = free_cb; - memblock_count++; - memblock_total += length; + stat_add(b, s); return b; } @@ -93,8 +110,7 @@ void pa_memblock_unref(struct pa_memblock*b) { assert(b && b->ref >= 1); if ((--(b->ref)) == 0) { - memblock_count--; - memblock_total -= b->length; + stat_remove(b); if (b->type == PA_MEMBLOCK_USER) { assert(b->free_cb); @@ -118,10 +134,27 @@ void pa_memblock_unref_fixed(struct pa_memblock *b) { } } -unsigned pa_memblock_get_count(void) { - return memblock_count; +struct pa_memblock_stat* pa_memblock_stat_new(void) { + struct pa_memblock_stat *s; + + s = pa_xmalloc(sizeof(struct pa_memblock_stat)); + s->ref = 1; + s->total = s->total_size = s->allocated = s->allocated_size = 0; + + return s; } -unsigned pa_memblock_get_total(void) { - return memblock_total; +void pa_memblock_stat_unref(struct pa_memblock_stat *s) { + assert(s && s->ref >= 1); + + if (!(--(s->ref))) { + assert(!s->total); + pa_xfree(s); + } +} + +struct pa_memblock_stat * pa_memblock_stat_ref(struct pa_memblock_stat *s) { + assert(s); + s->ref++; + return s; } diff --git a/polyp/memblock.h b/polyp/memblock.h index 6e79aa3ef..949a0a08c 100644 --- a/polyp/memblock.h +++ b/polyp/memblock.h @@ -27,25 +27,37 @@ enum pa_memblock_type { PA_MEMBLOCK_FIXED, PA_MEMBLOCK_APPENDED, PA_MEMBLOCK_DYNAMIC, PA_MEMBLOCK_USER }; +struct pa_memblock_stat; + struct pa_memblock { enum pa_memblock_type type; unsigned ref; size_t length; void *data; void (*free_cb)(void *p); + struct pa_memblock_stat *stat; }; -struct pa_memblock *pa_memblock_new(size_t length); -struct pa_memblock *pa_memblock_new_fixed(void *data, size_t length); -struct pa_memblock *pa_memblock_new_dynamic(void *data, size_t length); -struct pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p)); +struct pa_memblock *pa_memblock_new(size_t length, struct pa_memblock_stat*s); +struct pa_memblock *pa_memblock_new_fixed(void *data, size_t length, struct pa_memblock_stat*s); +struct pa_memblock *pa_memblock_new_dynamic(void *data, size_t length, struct pa_memblock_stat*s); +struct pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p), struct pa_memblock_stat*s); void pa_memblock_unref(struct pa_memblock*b); struct pa_memblock* pa_memblock_ref(struct pa_memblock*b); void pa_memblock_unref_fixed(struct pa_memblock*b); -unsigned pa_memblock_get_count(void); -unsigned pa_memblock_get_total(void); +struct pa_memblock_stat { + int ref; + unsigned total; + unsigned total_size; + unsigned allocated; + unsigned allocated_size; +}; + +struct pa_memblock_stat* pa_memblock_stat_new(void); +void pa_memblock_stat_unref(struct pa_memblock_stat *s); +struct pa_memblock_stat * pa_memblock_stat_ref(struct pa_memblock_stat *s); #endif diff --git a/polyp/memblockq.c b/polyp/memblockq.c index 8f499df0b..bc5d74371 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -45,9 +45,10 @@ struct pa_memblockq { int measure_delay; uint32_t delay; struct pa_mcalign *mcalign; + struct pa_memblock_stat *memblock_stat; }; -struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t base, size_t prebuf, size_t minreq) { +struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t base, size_t prebuf, size_t minreq, struct pa_memblock_stat *s) { struct pa_memblockq* bq; assert(maxlength && base && maxlength); @@ -83,6 +84,8 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b bq->delay = 0; bq->mcalign = NULL; + + bq->memblock_stat = s; return bq; } @@ -306,7 +309,7 @@ void pa_memblockq_push_align(struct pa_memblockq* bq, const struct pa_memchunk * } if (!bq->mcalign) { - bq->mcalign = pa_mcalign_new(bq->base); + bq->mcalign = pa_mcalign_new(bq->base, bq->memblock_stat); assert(bq->mcalign); } diff --git a/polyp/memblockq.h b/polyp/memblockq.h index 40184703e..af8fa3746 100644 --- a/polyp/memblockq.h +++ b/polyp/memblockq.h @@ -40,7 +40,8 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t base, size_t prebuf, - size_t minreq); + size_t minreq, + struct pa_memblock_stat *s); void pa_memblockq_free(struct pa_memblockq*bq); /* Push a new memory chunk into the queue. Optionally specify a value for future cancellation. This is currently not implemented, however! */ diff --git a/polyp/memchunk.c b/polyp/memchunk.c index 77e1b7dda..5913c6e33 100644 --- a/polyp/memchunk.c +++ b/polyp/memchunk.c @@ -31,14 +31,14 @@ #include "memchunk.h" #include "xmalloc.h" -void pa_memchunk_make_writable(struct pa_memchunk *c) { +void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s) { struct pa_memblock *n; assert(c && c->memblock && c->memblock->ref >= 1); if (c->memblock->ref == 1) return; - n = pa_memblock_new(c->length); + n = pa_memblock_new(c->length, s); assert(n); memcpy(n->data, c->memblock->data+c->index, c->length); pa_memblock_unref(c->memblock); @@ -52,9 +52,10 @@ struct pa_mcalign { struct pa_memchunk chunk; uint8_t *buffer; size_t buffer_fill; + struct pa_memblock_stat *memblock_stat; }; -struct pa_mcalign *pa_mcalign_new(size_t base) { +struct pa_mcalign *pa_mcalign_new(size_t base, struct pa_memblock_stat *s) { struct pa_mcalign *m; assert(base); @@ -64,6 +65,7 @@ struct pa_mcalign *pa_mcalign_new(size_t base) { m->chunk.length = m->chunk.index = 0; m->buffer = NULL; m->buffer_fill = 0; + m->memblock_stat = s; return m; } @@ -111,7 +113,7 @@ int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) { assert(m->buffer_fill <= m->base); if (m->buffer_fill == m->base) { - c->memblock = pa_memblock_new_dynamic(m->buffer, m->base); + c->memblock = pa_memblock_new_dynamic(m->buffer, m->base, m->memblock_stat); assert(c->memblock); c->index = 0; c->length = m->base; diff --git a/polyp/memchunk.h b/polyp/memchunk.h index 341c145cd..3a592f049 100644 --- a/polyp/memchunk.h +++ b/polyp/memchunk.h @@ -29,11 +29,11 @@ struct pa_memchunk { size_t index, length; }; -void pa_memchunk_make_writable(struct pa_memchunk *c); +void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s); struct pa_mcalign; -struct pa_mcalign *pa_mcalign_new(size_t base); +struct pa_mcalign *pa_mcalign_new(size_t base, struct pa_memblock_stat *s); void pa_mcalign_free(struct pa_mcalign *m); void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c); int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c); diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 5b4a7b732..06b07f337 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -217,7 +217,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { fprintf(stderr, __FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); - u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size); + u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size, c->memblock_stat); assert(u->silence.memblock); pa_silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index df716f737..9dc623d4d 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -89,7 +89,7 @@ static void do_read(struct userdata *u) { size_t l; if (!u->memchunk.memblock) { - u->memchunk.memblock = pa_memblock_new(u->memchunk.length = u->fragment_size); + u->memchunk.memblock = pa_memblock_new(u->memchunk.length = u->fragment_size, u->source->core->memblock_stat); u->memchunk.index = 0; } diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index ea768a987..7c7750d1b 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -100,7 +100,7 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { if (u->out_memblocks[u->out_current]) pa_memblock_unref_fixed(u->out_memblocks[u->out_current]); - chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed(u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size); + chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed(u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size, u->core->memblock_stat); assert(chunk.memblock); chunk.length = chunk.memblock->length; chunk.index = 0; @@ -141,7 +141,7 @@ static void in_post_memblocks(struct userdata *u, unsigned n) { struct pa_memchunk chunk; if (!u->in_memblocks[u->in_current]) { - chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size); + chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, u->core->memblock_stat); chunk.length = chunk.memblock->length; chunk.index = 0; diff --git a/polyp/module-oss.c b/polyp/module-oss.c index a8db4a337..d5517b5e5 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -131,7 +131,7 @@ static void do_read(struct userdata *u) { update_usage(u); - memchunk.memblock = pa_memblock_new(u->in_fragment_size); + memchunk.memblock = pa_memblock_new(u->in_fragment_size, u->core->memblock_stat); assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); @@ -273,7 +273,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->out_fragment_size = out_frag_size; u->in_fragment_size = in_frag_size; - u->silence.memblock = pa_memblock_new(u->silence.length = u->out_fragment_size); + u->silence.memblock = pa_memblock_new(u->silence.length = u->out_fragment_size, u->core->memblock_stat); assert(u->silence.memblock); pa_silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; diff --git a/polyp/pactl.c b/polyp/pactl.c index 0ff2aa909..f2556706b 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -88,7 +88,9 @@ static void stat_callback(struct pa_context *c, const struct pa_stat_info *i, vo return; } - fprintf(stderr, "Currently in use: %u blocks containing %u bytes total.\n", i->memblock_count, i->memblock_total); + fprintf(stderr, "Currently in use: %u blocks containing %u bytes total.\n" + "Allocated during whole lifetime: %u blocks containing %u bytes total.\n", + i->memblock_total, i->memblock_total_size, i->memblock_allocated, i->memblock_allocated_size); drain(); } diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 2a0c24a52..fcf3f6b91 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -78,6 +78,8 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->subscribe_callback = NULL; c->subscribe_userdata = NULL; + c->memblock_stat = pa_memblock_stat_new(); + pa_check_for_sigpipe(); return c; } @@ -104,7 +106,9 @@ static void context_free(struct pa_context *c) { pa_dynarray_free(c->record_streams, NULL, NULL); if (c->playback_streams) pa_dynarray_free(c->playback_streams, NULL, NULL); - + + pa_memblock_stat_unref(c->memblock_stat); + pa_xfree(c->name); pa_xfree(c); } @@ -280,7 +284,7 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i } assert(!c->pstream); - c->pstream = pa_pstream_new(c->mainloop, io); + c->pstream = pa_pstream_new(c->mainloop, io, c->memblock_stat); assert(c->pstream); pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index c8228a862..fd6cd38fb 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -73,6 +73,8 @@ struct pa_context { void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); void *subscribe_userdata; + + struct pa_memblock_stat *memblock_stat; }; struct pa_stream { diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 9a7ec1579..0efc599d0 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -42,8 +42,10 @@ static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uin goto finish; p = NULL; - } else if (pa_tagstruct_getu32(t, &i.memblock_count) < 0 || - pa_tagstruct_getu32(t, &i.memblock_total) < 0 || + } else if (pa_tagstruct_getu32(t, &i.memblock_total) < 0 || + pa_tagstruct_getu32(t, &i.memblock_total_size) < 0 || + pa_tagstruct_getu32(t, &i.memblock_allocated) < 0 || + pa_tagstruct_getu32(t, &i.memblock_allocated_size) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index dfa24ed55..c453eb2fb 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -130,8 +130,10 @@ struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint /** Memory block statistics */ struct pa_stat_info { - uint32_t memblock_count; /**< Allocated memory blocks */ - uint32_t memblock_total; /**< Total size of allocated memory blocks */ + uint32_t memblock_total; /**< Currently allocated memory blocks */ + uint32_t memblock_total_size; /**< Currentl total size of allocated memory blocks */ + uint32_t memblock_allocated; /**< Allocated memory blocks during the whole lifetime of the daemon */ + uint32_t memblock_allocated_size; /**< Total size of all memory blocks allocated during the whole lifetime of the daemon */ }; /** Get daemon memory block statistics */ diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 362dbad14..2b591f369 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -272,10 +272,10 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void assert(s && s->context && data && length && s->state == PA_STREAM_READY && s->ref >= 1); if (free_cb) { - chunk.memblock = pa_memblock_new_user((void*) data, length, free_cb); + chunk.memblock = pa_memblock_new_user((void*) data, length, free_cb, s->context->memblock_stat); assert(chunk.memblock && chunk.memblock->data); } else { - chunk.memblock = pa_memblock_new(length); + chunk.memblock = pa_memblock_new(length, s->context->memblock_stat); assert(chunk.memblock && chunk.memblock->data); memcpy(chunk.memblock->data, data, length); } diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index fb639b7fb..f5efa419b 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -291,7 +291,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons assert(!c->input_memblockq); l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); - c->input_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&ss), l/2, l/PLAYBACK_BUFFER_FRAGMENTS); + c->input_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&ss), l/2, l/PLAYBACK_BUFFER_FRAGMENTS, c->protocol->core->memblock_stat); assert(c->input_memblockq); pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2); c->playback.fragment_size = l/10; @@ -355,7 +355,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co assert(!c->output_memblockq); l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS); - c->output_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&ss), 0, 0); + c->output_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&ss), 0, 0, c->protocol->core->memblock_stat); assert(c->output_memblockq); pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2); @@ -574,7 +574,7 @@ static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, con name[sizeof(name)-1] = 0; assert(!c->scache_memchunk.memblock); - c->scache_memchunk.memblock = pa_memblock_new(sc_length); + c->scache_memchunk.memblock = pa_memblock_new(sc_length, c->protocol->core->memblock_stat); c->scache_memchunk.index = 0; c->scache_memchunk.length = sc_length; c->scache_sample_spec = ss; @@ -778,7 +778,7 @@ static int do_read(struct connection *c) { } if (!c->playback.current_memblock) { - c->playback.current_memblock = pa_memblock_new(c->playback.fragment_size*2); + c->playback.current_memblock = pa_memblock_new(c->playback.fragment_size*2, c->protocol->core->memblock_stat); assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); c->playback.memblock_index = 0; } diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index e86c78f00..060b42418 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -229,7 +229,7 @@ static struct record_stream* record_stream_new(struct connection *c, struct pa_s s->source_output->owner = c->protocol->module; s->source_output->client = c->client; - s->memblockq = pa_memblockq_new(maxlength, 0, base = pa_frame_size(ss), 0, 0); + s->memblockq = pa_memblockq_new(maxlength, 0, base = pa_frame_size(ss), 0, 0, c->protocol->core->memblock_stat); assert(s->memblockq); s->fragment_size = (fragment_size/base)*base; @@ -274,7 +274,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct s->sink_input->owner = c->protocol->module; s->sink_input->client = c->client; - s->memblockq = pa_memblockq_new(maxlength, tlength, pa_frame_size(ss), prebuf, minreq); + s->memblockq = pa_memblockq_new(maxlength, tlength, pa_frame_size(ss), prebuf, minreq, c->protocol->core->memblock_stat); assert(s->memblockq); s->requested_bytes = 0; @@ -780,8 +780,10 @@ static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag assert(reply); pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); pa_tagstruct_putu32(reply, tag); - pa_tagstruct_putu32(reply, pa_memblock_get_count()); - pa_tagstruct_putu32(reply, pa_memblock_get_total()); + pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total); + pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total_size); + pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated); + pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated_size); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1313,7 +1315,7 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, in u->length = 0; fprintf(stderr, "COPY\n"); } else { - u->memchunk.memblock = pa_memblock_new(u->length); + u->memchunk.memblock = pa_memblock_new(u->length, c->protocol->core->memblock_stat); u->memchunk.index = u->memchunk.length = 0; } } @@ -1372,7 +1374,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->client->userdata = c; c->client->owner = p->module; - c->pstream = pa_pstream_new(p->core->mainloop, io); + c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->memblock_stat); assert(c->pstream); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index bd0e14889..583434860 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -115,7 +115,7 @@ static int do_read(struct connection *c) { } if (!c->playback.current_memblock) { - c->playback.current_memblock = pa_memblock_new(c->playback.fragment_size*2); + c->playback.current_memblock = pa_memblock_new(c->playback.fragment_size*2, c->protocol->core->memblock_stat); assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); c->playback.memblock_index = 0; } @@ -318,7 +318,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->sink_input->userdata = c; l = (size_t) (pa_bytes_per_second(&p->sample_spec)*PLAYBACK_BUFFER_SECONDS); - c->input_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&p->sample_spec), l/2, l/PLAYBACK_BUFFER_FRAGMENTS); + c->input_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&p->sample_spec), l/2, l/PLAYBACK_BUFFER_FRAGMENTS, p->core->memblock_stat); assert(c->input_memblockq); pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5); c->playback.fragment_size = l/10; @@ -346,7 +346,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->source_output->userdata = c; l = (size_t) (pa_bytes_per_second(&p->sample_spec)*RECORD_BUFFER_SECONDS); - c->output_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&p->sample_spec), 0, 0); + c->output_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&p->sample_spec), 0, 0, p->core->memblock_stat); pa_iochannel_socket_set_sndbuf(io, l/RECORD_BUFFER_FRAGMENTS*2); } diff --git a/polyp/pstream.c b/polyp/pstream.c index 2d147e03a..5664e18a1 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -91,6 +91,8 @@ struct pa_pstream { void (*drain_callback)(struct pa_pstream *p, void *userdata); void *drain_userdata; + + struct pa_memblock_stat *memblock_stat; }; static void do_write(struct pa_pstream *p); @@ -129,7 +131,7 @@ static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, do_something(p); } -struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io) { +struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io, struct pa_memblock_stat *s) { struct pa_pstream *p; assert(io); @@ -165,6 +167,8 @@ struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel p->drain_callback = NULL; p->drain_userdata = NULL; + p->memblock_stat = s; + return p; } @@ -350,7 +354,7 @@ static void do_read(struct pa_pstream *p) { p->read.data = p->read.packet->data; } else { /* Frame is a memblock frame */ - p->read.memblock = pa_memblock_new(ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])); + p->read.memblock = pa_memblock_new(ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]), p->memblock_stat); assert(p->read.memblock); p->read.data = p->read.memblock->data; } diff --git a/polyp/pstream.h b/polyp/pstream.h index ff70a8559..9a2895073 100644 --- a/polyp/pstream.h +++ b/polyp/pstream.h @@ -32,7 +32,7 @@ struct pa_pstream; -struct pa_pstream* pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io); +struct pa_pstream* pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io, struct pa_memblock_stat *s); void pa_pstream_unref(struct pa_pstream*p); struct pa_pstream* pa_pstream_ref(struct pa_pstream*p); diff --git a/polyp/resampler.c b/polyp/resampler.c index 241f97c49..ed44cbb7e 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -43,9 +43,11 @@ struct pa_resampler { pa_convert_to_float32_func_t to_float32_func; pa_convert_from_float32_func_t from_float32_func; SRC_STATE *src_state; + + struct pa_memblock_stat *memblock_stat; }; -struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b) { +struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s) { struct pa_resampler *r = NULL; int err; assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b)); @@ -82,6 +84,8 @@ struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const stru r->from_float32_func = pa_get_convert_from_float32_function(b->format); assert(r->to_float32_func && r->from_float32_func); + + r->memblock_stat = s; return r; @@ -134,7 +138,7 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru eff_ons = ons; } - out->memblock = pa_memblock_new(out->length = (ons*r->o_sz)); + out->memblock = pa_memblock_new(out->length = (ons*r->o_sz), r->memblock_stat); out->index = 0; assert(out->memblock); diff --git a/polyp/resampler.h b/polyp/resampler.h index 8e979478f..e23d145d9 100644 --- a/polyp/resampler.h +++ b/polyp/resampler.h @@ -28,7 +28,7 @@ struct pa_resampler; -struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b); +struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s); void pa_resampler_free(struct pa_resampler *r); size_t pa_resampler_request(struct pa_resampler *r, size_t out_length); diff --git a/polyp/sink-input.c b/polyp/sink-input.c index efa8c551c..c57dd8e05 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -43,7 +43,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con assert(s && spec); if (!pa_sample_spec_equal(spec, &s->sample_spec)) - if (!(resampler = pa_resampler_new(spec, &s->sample_spec))) + if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat))) return NULL; i = pa_xmalloc(sizeof(struct pa_sink_input)); diff --git a/polyp/sink.c b/polyp/sink.c index becaef9e5..62b9a7af2 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -179,11 +179,11 @@ int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) volume = pa_volume_multiply(s->volume, info[0].volume); if (volume != PA_VOLUME_NORM) { - pa_memchunk_make_writable(result); + pa_memchunk_make_writable(result, s->core->memblock_stat); pa_volume_memchunk(result, &s->sample_spec, volume); } } else { - result->memblock = pa_memblock_new(length); + result->memblock = pa_memblock_new(length, s->core->memblock_stat); assert(result->memblock); result->length = l = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, s->volume); diff --git a/polyp/sound-file.c b/polyp/sound-file.c index b0df7185e..bf635fa08 100644 --- a/polyp/sound-file.c +++ b/polyp/sound-file.c @@ -8,7 +8,7 @@ #define MAX_FILE_SIZE (1024*1024) -int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk) { +int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk, struct pa_memblock_stat *s) { SNDFILE*sf = NULL; SF_INFO sfinfo; int ret = -1; @@ -39,7 +39,7 @@ int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_m goto finish; } - chunk->memblock = pa_memblock_new(l); + chunk->memblock = pa_memblock_new(l, s); assert(chunk->memblock); chunk->index = 0; chunk->length = l; diff --git a/polyp/sound-file.h b/polyp/sound-file.h index 3a6fa4151..62a4a3716 100644 --- a/polyp/sound-file.h +++ b/polyp/sound-file.h @@ -4,6 +4,6 @@ #include "memchunk.h" #include "sample.h" -int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk); +int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk, struct pa_memblock_stat *s); #endif diff --git a/polyp/source-output.c b/polyp/source-output.c index c53831c7b..b8083a79a 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -38,7 +38,7 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n assert(s && spec); if (!pa_sample_spec_equal(&s->sample_spec, spec)) - if (!(resampler = pa_resampler_new(&s->sample_spec, spec))) + if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat))) return NULL; o = pa_xmalloc(sizeof(struct pa_source_output)); From ac595189fdc311ae30fa8061cd5bbaeb72fc0ef1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Aug 2004 19:47:42 +0000 Subject: [PATCH 0137/1514] add missing copyright headers git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@138 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 ++- polyp/autoload.c | 25 +++++++++++++++++++++++++ polyp/autoload.h | 21 +++++++++++++++++++++ polyp/cdecl.h | 21 +++++++++++++++++++++ polyp/debug.h | 23 ++++++++++++++++++++++- polyp/glib-mainloop.c | 25 +++++++++++++++++++++++++ polyp/glib-mainloop.h | 21 +++++++++++++++++++++ polyp/llist.h | 21 +++++++++++++++++++++ polyp/mainloop-test.c | 25 +++++++++++++++++++++++++ polyp/module-x11-bell.c | 25 +++++++++++++++++++++++++ polyp/play-memchunk.c | 25 +++++++++++++++++++++++++ polyp/play-memchunk.h | 22 ++++++++++++++++++++++ polyp/polyplib-operation.c | 25 +++++++++++++++++++++++++ polyp/scache.c | 25 +++++++++++++++++++++++++ polyp/scache.h | 21 +++++++++++++++++++++ polyp/sound-file.c | 25 +++++++++++++++++++++++++ polyp/sound-file.h | 21 +++++++++++++++++++++ polyp/subscribe.c | 25 +++++++++++++++++++++++++ polyp/subscribe.h | 21 +++++++++++++++++++++ polyp/xmalloc.c | 25 +++++++++++++++++++++++++ polyp/xmalloc.h | 21 +++++++++++++++++++++ 21 files changed, 464 insertions(+), 2 deletions(-) diff --git a/doc/todo b/doc/todo index 7814321d0..c4b390dea 100644 --- a/doc/todo +++ b/doc/todo @@ -2,8 +2,9 @@ *** 0.2 *** -- several files: copyright and config.h - enable searchdir +- run dep script +- version routines *** 0.3 *** - future cancellation diff --git a/polyp/autoload.c b/polyp/autoload.c index f0d70d2dc..988b0921e 100644 --- a/polyp/autoload.c +++ b/polyp/autoload.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/polyp/autoload.h b/polyp/autoload.h index f1862e77d..004dae266 100644 --- a/polyp/autoload.h +++ b/polyp/autoload.h @@ -1,6 +1,27 @@ #ifndef fooautoloadhfoo #define fooautoloadhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "namereg.h" struct pa_autoload_entry { diff --git a/polyp/cdecl.h b/polyp/cdecl.h index 39880a474..7102f6496 100644 --- a/polyp/cdecl.h +++ b/polyp/cdecl.h @@ -1,6 +1,27 @@ #ifndef foocdeclhfoo #define foocdeclhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + /** \file * C++ compatibility support */ diff --git a/polyp/debug.h b/polyp/debug.h index fb2b889e6..c6ec5c7e2 100644 --- a/polyp/debug.h +++ b/polyp/debug.h @@ -1,7 +1,28 @@ #ifndef foodebughfoo #define foodebughfoo -/* A nice trick for debuggers, working on x86 only */ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* A nice trick for debuggers, working on x86 with GCC only */ #define DEBUG_TRAP __asm__("int $3") diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c index 9abb1e472..a91f48eca 100644 --- a/polyp/glib-mainloop.c +++ b/polyp/glib-mainloop.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include "glib-mainloop.h" diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h index dbbf2a62a..1fc7f64aa 100644 --- a/polyp/glib-mainloop.h +++ b/polyp/glib-mainloop.h @@ -1,6 +1,27 @@ #ifndef fooglibmainloophfoo #define fooglibmainloophfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include "mainloop-api.h" diff --git a/polyp/llist.h b/polyp/llist.h index 1f145de21..12a33e903 100644 --- a/polyp/llist.h +++ b/polyp/llist.h @@ -1,6 +1,27 @@ #ifndef foollistfoo #define foollistfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #define PA_LLIST_HEAD(t,name) t *name #define PA_LLIST_FIELDS(t) t *next, *prev; diff --git a/polyp/mainloop-test.c b/polyp/mainloop-test.c index 31caaa033..c2517065e 100644 --- a/polyp/mainloop-test.c +++ b/polyp/mainloop-test.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index 2414e36be..3ed9b0682 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index 866344070..5c4235670 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/polyp/play-memchunk.h b/polyp/play-memchunk.h index 76f9dbd0f..edd327c55 100644 --- a/polyp/play-memchunk.h +++ b/polyp/play-memchunk.h @@ -1,7 +1,29 @@ #ifndef fooplaychunkhfoo #define fooplaychunkhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "sink.h" +#include "memchunk.h" int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, uint32_t volume); diff --git a/polyp/polyplib-operation.c b/polyp/polyplib-operation.c index 994ac016a..cdc5394eb 100644 --- a/polyp/polyplib-operation.c +++ b/polyp/polyplib-operation.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include "xmalloc.h" diff --git a/polyp/scache.c b/polyp/scache.c index 9485a2b6e..f0d261f6d 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/polyp/scache.h b/polyp/scache.h index 15cd5d488..8ccca156e 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -1,6 +1,27 @@ #ifndef fooscachehfoo #define fooscachehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "core.h" #include "memchunk.h" #include "sink.h" diff --git a/polyp/sound-file.c b/polyp/sound-file.c index bf635fa08..01fda78e0 100644 --- a/polyp/sound-file.c +++ b/polyp/sound-file.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/polyp/sound-file.h b/polyp/sound-file.h index 62a4a3716..4d0cf670d 100644 --- a/polyp/sound-file.h +++ b/polyp/sound-file.h @@ -1,6 +1,27 @@ #ifndef soundfilehfoo #define soundfilehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "memchunk.h" #include "sample.h" diff --git a/polyp/subscribe.c b/polyp/subscribe.c index 104566d1b..5f7651fd8 100644 --- a/polyp/subscribe.c +++ b/polyp/subscribe.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/polyp/subscribe.h b/polyp/subscribe.h index a88677d2d..8d5e971dc 100644 --- a/polyp/subscribe.h +++ b/polyp/subscribe.h @@ -1,6 +1,27 @@ #ifndef foosubscribehfoo #define foosubscribehfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "core.h" #include "native-common.h" diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c index 7d8b4821e..47f46bbe5 100644 --- a/polyp/xmalloc.c +++ b/polyp/xmalloc.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/polyp/xmalloc.h b/polyp/xmalloc.h index eaf8f708b..35eda622c 100644 --- a/polyp/xmalloc.h +++ b/polyp/xmalloc.h @@ -1,6 +1,27 @@ #ifndef foomemoryhfoo #define foomemoryhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include #include From befd734aac2c925df9c5701d1ddfb3063b45ac76 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 18 Aug 2004 01:00:18 +0000 Subject: [PATCH 0138/1514] add version routines to polyplib git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@139 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 2 ++ polyp/module-protocol-stub.c | 54 ++++++++++++++++-------------------- polyp/polyplib-context.c | 4 +++ polyp/polyplib-version.h.in | 33 ++++++++++++++++++++++ polyp/polyplib.h | 11 +++++++- 5 files changed, 73 insertions(+), 31 deletions(-) create mode 100644 polyp/polyplib-version.h.in diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 5a49201ab..ac98e86e7 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -27,6 +27,8 @@ EXTRA_DIST = polypaudio.pa depmod.py bin_PROGRAMS = polypaudio pacat pactl noinst_PROGRAMS = mainloop-test mainloop-test-glib pacat-simple parec-simple +BUILT_SOURCES=polyplib-version.h + polypinclude_HEADERS=polyplib.h \ polyplib-def.h \ polyplib-simple.h \ diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 3b1a02706..e681732fb 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -36,43 +36,37 @@ #include "util.h" #include "modargs.h" -#ifdef USE_PROTOCOL_SIMPLE +#if defined(USE_PROTOCOL_SIMPLE) #include "protocol-simple.h" #define protocol_new pa_protocol_simple_new #define protocol_free pa_protocol_simple_free #define IPV4_PORT 4711 #define UNIX_SOCKET "/tmp/polypaudio/simple" #define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record", +#elif defined(USE_PROTOCOL_CLI) + #include "protocol-cli.h" + #define protocol_new pa_protocol_cli_new + #define protocol_free pa_protocol_cli_free + #define IPV4_PORT 4712 + #define UNIX_SOCKET "/tmp/polypaudio/cli" + #define MODULE_ARGUMENTS +#elif defined(USE_PROTOCOL_NATIVE) + #include "protocol-native.h" + #define protocol_new pa_protocol_native_new + #define protocol_free pa_protocol_native_free + #define IPV4_PORT 4713 + #define UNIX_SOCKET "/tmp/polypaudio/native" + #define MODULE_ARGUMENTS "public", "cookie", +#elif defined(USE_PROTOCOL_ESOUND) + #include "protocol-esound.h" + #include "esound.h" + #define protocol_new pa_protocol_esound_new + #define protocol_free pa_protocol_esound_free + #define IPV4_PORT ESD_DEFAULT_PORT + #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME + #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", #else - #ifdef USE_PROTOCOL_CLI - #include "protocol-cli.h" - #define protocol_new pa_protocol_cli_new - #define protocol_free pa_protocol_cli_free - #define IPV4_PORT 4712 - #define UNIX_SOCKET "/tmp/polypaudio/cli" - #define MODULE_ARGUMENTS - #else - #ifdef USE_PROTOCOL_NATIVE - #include "protocol-native.h" - #define protocol_new pa_protocol_native_new - #define protocol_free pa_protocol_native_free - #define IPV4_PORT 4713 - #define UNIX_SOCKET "/tmp/polypaudio/native" - #define MODULE_ARGUMENTS "public", "cookie", - #else - #ifdef USE_PROTOCOL_ESOUND - #include "protocol-esound.h" - #include "esound.h" - #define protocol_new pa_protocol_esound_new - #define protocol_free pa_protocol_esound_free - #define IPV4_PORT ESD_DEFAULT_PORT - #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME - #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", - #else - #error "Broken build system" - #endif - #endif - #endif + #error "Broken build system" #endif static const char* const valid_modargs[] = { diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index fcf3f6b91..d048cda99 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -532,3 +532,7 @@ struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32 return pa_operation_ref(o); } + +const char* pa_get_library_version(void) { + return PACKAGE_VERSION; +} diff --git a/polyp/polyplib-version.h.in b/polyp/polyplib-version.h.in new file mode 100644 index 000000000..b44dc0088 --- /dev/null +++ b/polyp/polyplib-version.h.in @@ -0,0 +1,33 @@ +#ifndef foopolyplibversionhfoo /*-*-C-*-*/ +#define foopolyplibversionhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/** \file + * Define header version */ + +/** Return the version of the header files. Keep in mind that this is +a macro and not a function, so it is impossible to get the pointer of +it. */ +#define pa_get_headers_version() ("@PACKAGE_VERSION@") + +#endif diff --git a/polyp/polyplib.h b/polyp/polyplib.h index daaed6494..f4e419346 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -22,6 +22,7 @@ USA. ***/ +#include "cdecl.h" #include "mainloop-api.h" #include "sample.h" #include "polyplib-def.h" @@ -30,11 +31,12 @@ #include "polyplib-introspect.h" #include "polyplib-subscribe.h" #include "polyplib-scache.h" +#include "polyplib-version.h" /** \file * Include all polyplib header file at once. The following files are included: \ref mainloop-api.h, \ref sample.h, * \ref polyplib-def.h, \ref polyplib-context.h, \ref polyplib-stream.h, - * \ref polyplib-introspect.h, \ref polyplib-subscribe.h and \ref polyplib-scache.h + * \ref polyplib-introspect.h, \ref polyplib-subscribe.h and \ref polyplib-scache.h \ref polyplib-version.h * at once */ /** \mainpage @@ -81,4 +83,11 @@ * synchronous API is available as "polyplib-simple". */ +PA_C_DECL_BEGIN + +/** Return the version of the library the current application is linked to */ +const char* pa_get_library_version(void); + +PA_C_DECL_END + #endif From e0fe68a2d4e967c2b3d7afd300c854d173dcd95b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 19 Aug 2004 06:24:40 +0000 Subject: [PATCH 0139/1514] minor stuff git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@140 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- doc/todo | 4 ++-- doxygen/Makefile.am | 17 +++++++++++++++++ doxygen/doxygen.conf.in | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 4e4bf3aa3..a8c452696 100644 --- a/configure.ac +++ b/configure.ac @@ -111,5 +111,5 @@ AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) -AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf]) +AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h]) AC_OUTPUT diff --git a/doc/todo b/doc/todo index c4b390dea..9085d7fd4 100644 --- a/doc/todo +++ b/doc/todo @@ -3,8 +3,8 @@ *** 0.2 *** - enable searchdir -- run dep script -- version routines +- update docs +- pacat drain *** 0.3 *** - future cancellation diff --git a/doxygen/Makefile.am b/doxygen/Makefile.am index d2f508c72..007a37d69 100644 --- a/doxygen/Makefile.am +++ b/doxygen/Makefile.am @@ -1,4 +1,21 @@ # $Id$ +# +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. noinst_DATA=html diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 7d4c44c95..51b2a1138 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../polyp/polyplib-context.h ../polyp/polyplib-stream.h ../polyp/polyplib.h ../polyp/sample.h ../polyp/polyplib-def.h ../polyp/polyplib-subscribe.h ../polyp/polyplib-introspect.h ../polyp/polyplib-scache.h ../polyp/mainloop-api.h ../polyp/cdecl.h ../polyp/glib-mainloop.h ../polyp/mainloop.h ../polyp/mainloop-signal.h ../polyp/polyplib-error.h ../polyp/polyplib-operation.h ../polyp/polyplib-simple.h +INPUT = ../polyp/polyplib-context.h ../polyp/polyplib-stream.h ../polyp/polyplib.h ../polyp/sample.h ../polyp/polyplib-def.h ../polyp/polyplib-subscribe.h ../polyp/polyplib-introspect.h ../polyp/polyplib-scache.h ../polyp/mainloop-api.h ../polyp/cdecl.h ../polyp/glib-mainloop.h ../polyp/mainloop.h ../polyp/mainloop-signal.h ../polyp/polyplib-error.h ../polyp/polyplib-operation.h ../polyp/polyplib-simple.h ../polyp/polyplib-version.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp From f9b58fb0eafdc332e500a0851b0506146c2b14cd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 19 Aug 2004 23:14:59 +0000 Subject: [PATCH 0140/1514] move sample cache to namereg documentation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@141 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- doc/README.html.in | 41 +++++++++-------- polyp/cli-text.c | 8 ++-- polyp/core.c | 9 ++-- polyp/core.h | 4 +- polyp/glib-mainloop.c | 28 ++++++------ polyp/llist.h | 2 +- polyp/mainloop-api.h | 2 +- polyp/mainloop.c | 37 +++++++-------- polyp/memblockq.c | 2 +- polyp/memchunk.c | 2 +- polyp/module-oss-mmap.c | 2 +- polyp/module-oss.c | 2 +- polyp/namereg.c | 9 ++-- polyp/namereg.h | 3 +- polyp/polyplib-def.h | 8 ++-- polyp/polyplib-introspect.c | 89 +++++++++++++++++++++++++++++++++++++ polyp/polyplib-introspect.h | 12 +++++ polyp/polyplib-operation.h | 1 + polyp/polyplib-stream.c | 2 +- polyp/protocol-esound.c | 4 +- polyp/protocol-native.c | 45 ++++++++++++++----- polyp/sample.c | 2 +- polyp/scache.c | 66 ++++++++++++--------------- polyp/scache.h | 2 +- polyp/strbuf.c | 2 +- polyp/strbuf.h | 2 +- 27 files changed, 252 insertions(+), 136 deletions(-) diff --git a/configure.ac b/configure.ac index a8c452696..96b4cf3ae 100644 --- a/configure.ac +++ b/configure.ac @@ -87,7 +87,7 @@ AC_SUBST(GLIB20_LIBS) # If using GCC specifiy some additional parameters if test "x$GCC" = "xyes" ; then - CFLAGS="$CFLAGS -pipe -Wall -W -Wno-unused-parameter" + CFLAGS="$CFLAGS -pipe -W -Wall -Wno-unused-parameter -pedantic -std=c99" fi # LYNX documentation generation diff --git a/doc/README.html.in b/doc/README.html.in index 296d4506c..4972c1945 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -42,6 +42,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    News

    +
    Fri Aug 20 2004:

    Version 0.2 released; +changes include: added sample cache, introspection API, client API +documentation, module autoloading, glib support, a module for intercepting X11 bell events, and much more.

    Sat Jul 17 2004:

    Version 0.1 released

    @@ -56,7 +60,7 @@ Daemon (ESOUND). In addition to the features ESOUND provides polypaudio has:

      -
    • Extensible plugin architecture (dlopen())
    • +
    • Extensible plugin architecture (by loading dynamic loadable modules with dlopen())
    • Support for more than one sink/source
    • Better low latency behaviour
    • Embedabble into other software (the core is available as C library)
    • @@ -64,6 +68,7 @@ Daemon (ESOUND). In addition to the features ESOUND provides
    • Simple command line interface for reconfiguring the daemon while running
    • Flexible, implicit sample type conversion and resampling
    • "Zero-Copy" architecture
    • +
    • Module autoloading

    Both the core and the client API are completely asynchronous making @@ -74,31 +79,27 @@ available through polyplib is quite difficult to use there is a simplified synchronous API wrapper polyplib-simple available. A simple main loop implementation is available as well.

    -

    polypaudio is the successor of my previous, ill-fated attempt to write a sound server asd.

    +

    polypaudio is the successor of my previous, ill-fated +attempt to write a sound server asd.

    + +

    A GTK GUI manager application for polypaudio is the Polypaudio Manager.

    Status

    -

    Version @PACKAGE_VERSION@ is quite usable. polypaudio does -not yet match all ESOUND features: currently a sample cache and -automatic releasing of unused sound drivers are missing. Have a look -on the more extensive TODO -list.

    +

    Version @PACKAGE_VERSION@ is quite usable. It matches and supersedes ESOUND's feature set in nearly all areas.

    Documentation

    -

    There is some prelimenary documentation available: There is some preliminary documentation available: modules.html, cli.html, daemeon.html.

    +href="daemon.html">daemon.html.

    -

    Documentation for developing with polypaudio is not yet -available. Read the source, Luke! There are some example application -available: for the asynchronous -API and for the simple, -synchronous API.

    +

    You may browser the Doxygen generated programing +documentation for the client API. (Run make doxygen to generate this documentation from the source tree)

    First Steps

    @@ -131,7 +132,9 @@ GNU libtool for source code configuration and shared library management.

    polypaudio needs Secret Rabbit Code (aka libsamplerate) and alsa-lib.

    +href="http://www.mega-nerd.com/SRC/">Secret Rabbit Code (aka +libsamplerate), libsndfile and alsa-lib.

    Installation

    @@ -156,7 +159,7 @@ compilation and make install (as root) for installation of

    If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.


    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, August 2004
    $Id$
    diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 000d6d344..fa1ccdf94 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -212,13 +212,13 @@ char *pa_scache_list_to_string(struct pa_core *c) { s = pa_strbuf_new(); assert(s); - pa_strbuf_printf(s, "%u cache entries available.\n", c->scache_hashmap ? pa_hashmap_ncontents(c->scache_hashmap) : 0); + pa_strbuf_printf(s, "%u cache entries available.\n", c->scache ? pa_idxset_ncontents(c->scache) : 0); - if (c->scache_hashmap) { + if (c->scache) { struct pa_scache_entry *e; - void *state = NULL; + uint32_t index = PA_IDXSET_INVALID; - while ((e = pa_hashmap_iterate(c->scache_hashmap, &state))) { + for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) { double l; char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec); diff --git a/polyp/core.c b/polyp/core.c index b43eb639d..908564c10 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -53,8 +53,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->modules = NULL; c->namereg = NULL; - c->scache_idxset = NULL; - c->scache_hashmap = NULL; + c->scache = NULL; c->autoload_hashmap = NULL; @@ -74,7 +73,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { pa_check_for_sigpipe(); return c; -}; +} void pa_core_free(struct pa_core *c) { assert(c); @@ -97,8 +96,8 @@ void pa_core_free(struct pa_core *c) { assert(pa_idxset_isempty(c->sink_inputs)); pa_idxset_free(c->sink_inputs, NULL, NULL); - pa_namereg_free(c); pa_scache_free(c); + pa_namereg_free(c); pa_autoload_free(c); pa_subscription_free_all(c); @@ -108,5 +107,5 @@ void pa_core_free(struct pa_core *c) { pa_memblock_stat_unref(c->memblock_stat); pa_xfree(c); -}; +} diff --git a/polyp/core.h b/polyp/core.h index c0a2d6d8c..a297d4e0a 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -31,9 +31,9 @@ struct pa_core { struct pa_mainloop_api *mainloop; - struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache_idxset; + struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache; - struct pa_hashmap *namereg, *scache_hashmap, *autoload_hashmap; + struct pa_hashmap *namereg, *autoload_hashmap; char *default_source_name, *default_sink_name; diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c index a91f48eca..4fee0a4a1 100644 --- a/polyp/glib-mainloop.c +++ b/polyp/glib-mainloop.c @@ -384,24 +384,24 @@ static void glib_quit(struct pa_mainloop_api*a, int retval) { } static const struct pa_mainloop_api vtable = { - userdata: NULL, + .userdata = NULL, - io_new: glib_io_new, - io_enable: glib_io_enable, - io_free: glib_io_free, - io_set_destroy: glib_io_set_destroy, + .io_new = glib_io_new, + .io_enable = glib_io_enable, + .io_free = glib_io_free, + .io_set_destroy= glib_io_set_destroy, - time_new : glib_time_new, - time_restart : glib_time_restart, - time_free : glib_time_free, - time_set_destroy : glib_time_set_destroy, + .time_new = glib_time_new, + .time_restart = glib_time_restart, + .time_free = glib_time_free, + .time_set_destroy = glib_time_set_destroy, - defer_new : glib_defer_new, - defer_enable : glib_defer_enable, - defer_free : glib_defer_free, - defer_set_destroy : glib_defer_set_destroy, + .defer_new = glib_defer_new, + .defer_enable = glib_defer_enable, + .defer_free = glib_defer_free, + .defer_set_destroy = glib_defer_set_destroy, - quit : glib_quit, + .quit = glib_quit, }; struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { diff --git a/polyp/llist.h b/polyp/llist.h index 12a33e903..ec8e02997 100644 --- a/polyp/llist.h +++ b/polyp/llist.h @@ -24,7 +24,7 @@ #define PA_LLIST_HEAD(t,name) t *name -#define PA_LLIST_FIELDS(t) t *next, *prev; +#define PA_LLIST_FIELDS(t) t *next, *prev #define PA_LLIST_HEAD_INIT(t,item) do { (item) = NULL; } while(0) diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index e631c7acf..43d150e4c 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -50,7 +50,7 @@ enum pa_io_event_flags { PA_IO_EVENT_INPUT = 1, /**< Input event */ PA_IO_EVENT_OUTPUT = 2, /**< Output event */ PA_IO_EVENT_HANGUP = 4, /**< Hangup event */ - PA_IO_EVENT_ERROR = 8, /**< Error event */ + PA_IO_EVENT_ERROR = 8 /**< Error event */ }; /** \struct pa_io_event diff --git a/polyp/mainloop.c b/polyp/mainloop.c index c678537eb..84505bb6f 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -38,9 +38,6 @@ #include "idxset.h" #include "xmalloc.h" -struct pa_base_event { -}; - struct pa_io_event { struct pa_mainloop *mainloop; int dead; @@ -225,24 +222,24 @@ static void mainloop_quit(struct pa_mainloop_api*a, int retval) { } static const struct pa_mainloop_api vtable = { - userdata: NULL, + .userdata = NULL, - io_new: mainloop_io_new, - io_enable: mainloop_io_enable, - io_free: mainloop_io_free, - io_set_destroy: mainloop_io_set_destroy, + .io_new= mainloop_io_new, + .io_enable= mainloop_io_enable, + .io_free= mainloop_io_free, + .io_set_destroy= mainloop_io_set_destroy, - time_new : mainloop_time_new, - time_restart : mainloop_time_restart, - time_free : mainloop_time_free, - time_set_destroy : mainloop_time_set_destroy, + .time_new = mainloop_time_new, + .time_restart = mainloop_time_restart, + .time_free = mainloop_time_free, + .time_set_destroy = mainloop_time_set_destroy, - defer_new : mainloop_defer_new, - defer_enable : mainloop_defer_enable, - defer_free : mainloop_defer_free, - defer_set_destroy : mainloop_defer_set_destroy, + .defer_new = mainloop_defer_new, + .defer_enable = mainloop_defer_enable, + .defer_free = mainloop_defer_free, + .defer_set_destroy = mainloop_defer_set_destroy, - quit : mainloop_quit, + .quit = mainloop_quit, }; struct pa_mainloop *pa_mainloop_new(void) { @@ -282,7 +279,7 @@ static int io_foreach(void *p, uint32_t index, int *del, void*userdata) { pa_xfree(e); *del = 1; return 0; -}; +} static int time_foreach(void *p, uint32_t index, int *del, void*userdata) { struct pa_time_event *e = p; @@ -297,7 +294,7 @@ static int time_foreach(void *p, uint32_t index, int *del, void*userdata) { pa_xfree(e); *del = 1; return 0; -}; +} static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) { struct pa_defer_event *e = p; @@ -312,7 +309,7 @@ static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) { pa_xfree(e); *del = 1; return 0; -}; +} void pa_mainloop_free(struct pa_mainloop* m) { int all = 1; diff --git a/polyp/memblockq.c b/polyp/memblockq.c index bc5d74371..085c05108 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -189,9 +189,9 @@ int memblockq_pop(struct memblockq* bq, struct pa_memchunk *chunk) { */ static uint32_t age(struct timeval *tv) { - assert(tv); struct timeval now; uint32_t r; + assert(tv); if (tv->tv_sec == 0) return 0; diff --git a/polyp/memchunk.c b/polyp/memchunk.c index 5913c6e33..920189e28 100644 --- a/polyp/memchunk.c +++ b/polyp/memchunk.c @@ -88,8 +88,8 @@ void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) { } int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) { - assert(m && c && m->base > m->buffer_fill); int ret; + assert(m && c && m->base > m->buffer_fill); if (!m->chunk.memblock) return -1; diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 7c7750d1b..05e061783 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -193,7 +193,7 @@ static void do_read(struct userdata *u) { in_post_memblocks(u, info.blocks); in_clear_memblocks(u, u->in_fragments/2); -}; +} static void io_callback(struct pa_mainloop_api *m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; diff --git a/polyp/module-oss.c b/polyp/module-oss.c index d5517b5e5..3fa3d1e35 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -146,7 +146,7 @@ static void do_read(struct userdata *u) { pa_source_post(u->source, &memchunk); pa_memblock_unref(memchunk.memblock); -}; +} static void io_callback(struct pa_iochannel *io, void*userdata) { struct userdata *u = userdata; diff --git a/polyp/namereg.c b/polyp/namereg.c index b6a8c23f7..72a4c648e 100644 --- a/polyp/namereg.c +++ b/polyp/namereg.c @@ -134,8 +134,7 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t name = c->default_source_name; - } else { - assert(type == PA_NAMEREG_SINK); + } else if (type == PA_NAMEREG_SINK) { if (!c->default_sink_name) { struct pa_sink *s; @@ -174,13 +173,15 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t d = pa_idxset_get_by_index(c->sinks, index); else if (type == PA_NAMEREG_SOURCE) d = pa_idxset_get_by_index(c->sources, index); - + else if (type == PA_NAMEREG_SAMPLE && c->scache) + d = pa_idxset_get_by_index(c->scache, index); + return d; } void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_type type) { char **s; - assert(c); + assert(c && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); s = type == PA_NAMEREG_SINK ? &c->default_sink_name : &c->default_source_name; assert(s); diff --git a/polyp/namereg.h b/polyp/namereg.h index 5bc92693d..b8db11053 100644 --- a/polyp/namereg.h +++ b/polyp/namereg.h @@ -26,7 +26,8 @@ enum pa_namereg_type { PA_NAMEREG_SINK, - PA_NAMEREG_SOURCE + PA_NAMEREG_SOURCE, + PA_NAMEREG_SAMPLE }; void pa_namereg_free(struct pa_core *c); diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 8a506c8d8..6420e87e4 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -47,14 +47,14 @@ enum pa_stream_state { PA_STREAM_CREATING, /**< The stream is being created */ PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */ PA_STREAM_FAILED, /**< An error occured that made the stream invalid */ - PA_STREAM_TERMINATED, /**< The stream has been terminated cleanly */ + PA_STREAM_TERMINATED /**< The stream has been terminated cleanly */ }; /** The state of an operation */ enum pa_operation_state { PA_OPERATION_RUNNING, /**< The operation is still running */ PA_OPERATION_DONE, /**< The operation has been completed */ - PA_OPERATION_CANCELED, /**< The operation has been canceled */ + PA_OPERATION_CANCELED /**< The operation has been canceled */ }; /** An invalid index */ @@ -105,7 +105,7 @@ enum pa_subscription_mask { PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8, /**< Source output events */ PA_SUBSCRIPTION_MASK_MODULE = 16, /**< Module events */ PA_SUBSCRIPTION_MASK_CLIENT = 32, /**< Client events */ - PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */ + PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64 /**< Sample cache events */ }; /** Subscription event types, as used by pa_context_subscribe() */ @@ -122,7 +122,7 @@ enum pa_subscription_event_type { PA_SUBSCRIPTION_EVENT_NEW = 0, /**< A new object was created */ PA_SUBSCRIPTION_EVENT_CHANGE = 16, /**< A property of the object was modified */ PA_SUBSCRIPTION_EVENT_REMOVE = 32, /**< An object was removed */ - PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32, /**< A mask to extract the event operation from an event value */ + PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32 /**< A mask to extract the event operation from an event value */ }; /** Return one if an event type t matches an event mask bitfield */ diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 0efc599d0..63422383f 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -580,3 +580,92 @@ struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint return pa_operation_ref(o); } + +/** Sample Cache **/ + +static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_operation *o = userdata; + int eof = 1; + assert(pd && o && o->context && o->ref >= 1); + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; + + eof = -1; + } else { + + while (!pa_tagstruct_eof(t)) { + struct pa_sample_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_getu32(t, &i.duration) < 0 || + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_sample_info*i, int eof, void *userdata) = o->callback; + cb(o->context, &i, 0, o->userdata); + } + } + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_sample_info*i, int eof, void *userdata) = o->callback; + cb(o->context, NULL, eof, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +struct pa_operation* pa_context_get_sample_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb && name); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_tagstruct_puts(t, ""); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_get_sample_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, cb, userdata); +} diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index c453eb2fb..0cc525496 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -139,6 +139,18 @@ struct pa_stat_info { /** Get daemon memory block statistics */ struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info *i, void *userdata), void *userdata); +struct pa_sample_info { + uint32_t index; + const char *name; + uint32_t volume; + struct pa_sample_spec sample_spec; + uint32_t duration; +}; + +struct pa_operation* pa_context_get_sample_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata); +struct pa_operation* pa_context_get_sample_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata); + PA_C_DECL_END #endif diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h index ce2756efb..42d5c8e14 100644 --- a/polyp/polyplib-operation.h +++ b/polyp/polyplib-operation.h @@ -23,6 +23,7 @@ ***/ #include "cdecl.h" +#include "polyplib-def.h" /** \file * Asynchronous operations */ diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 2b591f369..451dd0461 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -32,8 +32,8 @@ #include "pstream-util.h" struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss) { - assert(c && ss); struct pa_stream *s; + assert(c && ss); s = pa_xmalloc(sizeof(struct pa_stream)); s->ref = 1; diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index f5efa419b..be2ef2b94 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -427,7 +427,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v k = sizeof(int)*5+ESD_NAME_MAX; s = sizeof(int)*6+ESD_NAME_MAX; - nsamples = c->protocol->core->scache_idxset ? pa_idxset_ncontents(c->protocol->core->scache_idxset) : 0; + nsamples = c->protocol->core->scache ? pa_idxset_ncontents(c->protocol->core->scache) : 0; response = connection_write(c, (t = s*(nsamples+1) + k*(c->protocol->n_player+1))); assert(k); @@ -482,7 +482,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v struct pa_scache_entry *ce; index = PA_IDXSET_INVALID; - for (ce = pa_idxset_first(c->protocol->core->scache_idxset, &index); ce; ce = pa_idxset_next(c->protocol->core->scache_idxset, &index)) { + for (ce = pa_idxset_first(c->protocol->core->scache, &index); ce; ce = pa_idxset_next(c->protocol->core->scache, &index)) { assert(t >= s*2); /* id */ diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 060b42418..d633c2655 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -164,12 +164,14 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_GET_MODULE_INFO] = { command_get_info }, [PA_COMMAND_GET_SINK_INPUT_INFO] = { command_get_info }, [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = { command_get_info }, + [PA_COMMAND_GET_SAMPLE_INFO] = { command_get_info }, [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_MODULE_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_CLIENT_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = { command_get_info_list }, + [PA_COMMAND_GET_SAMPLE_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info }, [PA_COMMAND_SUBSCRIBE] = { command_subscribe }, [PA_COMMAND_SET_SINK_VOLUME] = { command_set_volume }, @@ -763,8 +765,8 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - assert(c && t); struct pa_tagstruct *reply; + assert(c && t); if (!pa_tagstruct_eof(t)) { protocol_error(c); @@ -789,10 +791,10 @@ static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - assert(c && t); struct pa_tagstruct *reply; struct playback_stream *s; uint32_t index, latency; + assert(c && t); if (pa_tagstruct_getu32(t, &index) < 0 || !pa_tagstruct_eof(t)) { @@ -1021,6 +1023,15 @@ static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_sourc pa_tagstruct_put_sample_spec(t, &s->sample_spec); } +static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry *e) { + assert(t && e); + pa_tagstruct_putu32(t, e->index); + pa_tagstruct_puts(t, e->name); + pa_tagstruct_putu32(t, e->volume); + pa_tagstruct_putu32(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec)); + pa_tagstruct_put_sample_spec(t, &e->sample_spec); +} + static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t index; @@ -1030,6 +1041,7 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t struct pa_module *module = NULL; struct pa_sink_input *si = NULL; struct pa_source_output *so = NULL; + struct pa_scache_entry *sce = NULL; const char *name; struct pa_tagstruct *reply; assert(c && t); @@ -1067,12 +1079,17 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t module = pa_idxset_get_by_index(c->protocol->core->modules, index); else if (command == PA_COMMAND_GET_SINK_INPUT_INFO) si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index); - else { - assert(command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO); + else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO) so = pa_idxset_get_by_index(c->protocol->core->source_outputs, index); + else { + assert(command == PA_COMMAND_GET_SAMPLE_INFO && name); + if (index != (uint32_t) -1) + sce = pa_idxset_get_by_index(c->protocol->core->scache, index); + else + sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0); } - if (!sink && !source && !client && !module && !si && !so) { + if (!sink && !source && !client && !module && !si && !so && !sce) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1091,8 +1108,10 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t module_fill_tagstruct(reply, module); else if (si) sink_input_fill_tagstruct(reply, si); - else + else if (so) source_output_fill_tagstruct(reply, so); + else + scache_fill_tagstruct(reply, sce); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1129,11 +1148,13 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin i = c->protocol->core->modules; else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST) i = c->protocol->core->sink_inputs; - else { - assert(command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST); + else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST) i = c->protocol->core->source_outputs; + else { + assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); + i = c->protocol->core->scache; } - + for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) { if (command == PA_COMMAND_GET_SINK_INFO_LIST) sink_fill_tagstruct(reply, p); @@ -1145,9 +1166,11 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin module_fill_tagstruct(reply, p); else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST) sink_input_fill_tagstruct(reply, p); - else { - assert(command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST); + else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST) source_output_fill_tagstruct(reply, p); + else { + assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); + scache_fill_tagstruct(reply, p); } } diff --git a/polyp/sample.c b/polyp/sample.c index 173de9c1c..f4a80861c 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -29,8 +29,8 @@ #include "sample.h" size_t pa_frame_size(const struct pa_sample_spec *spec) { - assert(spec); size_t b = 1; + assert(spec); switch (spec->format) { case PA_SAMPLE_U8: diff --git a/polyp/scache.c b/polyp/scache.c index f0d261f6d..f3c15934f 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -35,9 +35,11 @@ #include "play-memchunk.h" #include "xmalloc.h" #include "subscribe.h" +#include "namereg.h" static void free_entry(struct pa_scache_entry *e) { assert(e); + pa_namereg_unregister(e->core, e->name); pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_REMOVE, e->index); pa_xfree(e->name); if (e->memchunk.memblock) @@ -45,25 +47,32 @@ static void free_entry(struct pa_scache_entry *e) { pa_xfree(e); } -void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index) { +int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index) { struct pa_scache_entry *e; int put; assert(c && name); - if (c->scache_hashmap && (e = pa_hashmap_get(c->scache_hashmap, name))) { + if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) { put = 0; if (e->memchunk.memblock) pa_memblock_unref(e->memchunk.memblock); assert(e->core == c); } else { + put = 1; e = pa_xmalloc(sizeof(struct pa_scache_entry)); + + if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, 1)) { + pa_xfree(e); + return -1; + } + e->name = pa_xstrdup(name); e->core = c; } - e->volume = 0x100; - + e->volume = PA_VOLUME_NORM; + if (ss) e->sample_spec = *ss; else @@ -78,35 +87,31 @@ void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_sp } if (put) { - if (!c->scache_hashmap) { - c->scache_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - assert(c->scache_hashmap); + if (!c->scache) { + c->scache = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + assert(c->scache); } - if (!c->scache_idxset) { - c->scache_idxset = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); - assert(c->scache_idxset); - } - - pa_idxset_put(c->scache_idxset, e, &e->index); - pa_hashmap_put(c->scache_hashmap, e->name, e); + pa_idxset_put(c->scache, e, &e->index); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index); - } + } else + pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); if (index) *index = e->index; + + return 0; } int pa_scache_remove_item(struct pa_core *c, const char *name) { struct pa_scache_entry *e; assert(c && name); - if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name))) + if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) return -1; - pa_hashmap_remove(c->scache_hashmap, name); - if (pa_idxset_remove_by_data(c->scache_idxset, e, NULL) != e) + if (pa_idxset_remove_by_data(c->scache, e, NULL) != e) assert(0); free_entry(e); @@ -122,14 +127,9 @@ static void free_cb(void *p, void *userdata) { void pa_scache_free(struct pa_core *c) { assert(c); - if (c->scache_hashmap) { - pa_hashmap_free(c->scache_hashmap, free_cb, NULL); - c->scache_hashmap = NULL; - } - - if (c->scache_idxset) { - pa_idxset_free(c->scache_idxset, NULL, NULL); - c->scache_idxset = NULL; + if (c->scache) { + pa_idxset_free(c->scache, free_cb, NULL); + c->scache = NULL; } } @@ -137,7 +137,7 @@ int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sin struct pa_scache_entry *e; assert(c && name && sink); - if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name))) + if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) return -1; if (!e->memchunk.memblock) @@ -153,19 +153,9 @@ const char * pa_scache_get_name_by_id(struct pa_core *c, uint32_t id) { struct pa_scache_entry *e; assert(c && id != PA_IDXSET_INVALID); - if (!c->scache_idxset || !(e = pa_idxset_get_by_index(c->scache_idxset, id))) + if (!c->scache || !(e = pa_idxset_get_by_index(c->scache, id))) return NULL; return e->name; } - -uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { - struct pa_scache_entry *e; - assert(c && name); - - if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name))) - return PA_IDXSET_INVALID; - - return e->index; -} diff --git a/polyp/scache.h b/polyp/scache.h index 8ccca156e..959067f37 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -35,7 +35,7 @@ struct pa_scache_entry { struct pa_memchunk memchunk; }; -void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index); +int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index); int pa_scache_remove_item(struct pa_core *c, const char *name); int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume); diff --git a/polyp/strbuf.c b/polyp/strbuf.c index 169604e82..ef48a3fb2 100644 --- a/polyp/strbuf.c +++ b/polyp/strbuf.c @@ -36,7 +36,7 @@ struct chunk { struct chunk *next; size_t length; - char text[]; + char text[0]; }; struct pa_strbuf { diff --git a/polyp/strbuf.h b/polyp/strbuf.h index d672c42a4..8ca51624b 100644 --- a/polyp/strbuf.h +++ b/polyp/strbuf.h @@ -29,7 +29,7 @@ void pa_strbuf_free(struct pa_strbuf *sb); char *pa_strbuf_tostring(struct pa_strbuf *sb); char *pa_strbuf_tostring_free(struct pa_strbuf *sb); -int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) __attribute__ ((format (printf, 2, 3)));; +int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) __attribute__ ((format (printf, 2, 3))); void pa_strbuf_puts(struct pa_strbuf *sb, const char *t); void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t m); From 6bc53405011e815b95e47a078f89b1a7c0419e56 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 20 Aug 2004 10:54:31 +0000 Subject: [PATCH 0141/1514] build fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@142 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- doc/README.html.in | 4 ++-- doc/todo | 7 +------ polyp/Makefile.am | 4 +++- polyp/main.c | 2 +- polyp/protocol-native.c | 38 ++++++++++++++++++++------------------ 6 files changed, 28 insertions(+), 29 deletions(-) diff --git a/Makefile.am b/Makefile.am index 13a063627..0df5fac1d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,7 +17,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh README LICENSE +EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in SUBDIRS=polyp doc MAINTAINERCLEANFILES=README diff --git a/doc/README.html.in b/doc/README.html.in index 4972c1945..602787d4f 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -133,8 +133,8 @@ management.

    polypaudio needs Secret Rabbit Code (aka -libsamplerate), libsndfile and alsa-lib.

    +libsamplerate), libsndfile, alsa-lib and GLIB. (The latter is required for building the GLIB main loop integration module only.)

    Installation

    diff --git a/doc/todo b/doc/todo index 9085d7fd4..43d7bc6f5 100644 --- a/doc/todo +++ b/doc/todo @@ -1,12 +1,7 @@ *** $Id$ *** -*** 0.2 *** - -- enable searchdir -- update docs -- pacat drain - *** 0.3 *** +- pacat drain fix - future cancellation - make mcalign merge chunks - use ref counting in more objects diff --git a/polyp/Makefile.am b/polyp/Makefile.am index ac98e86e7..f9f6b6ab5 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -17,7 +17,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -AM_CFLAGS=-ansi -D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" -I$(srcdir)/.. $(PTHREAD_CFLAGS) +AM_CFLAGS=-D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" -I$(top_srcdir) $(PTHREAD_CFLAGS) AM_LDADD=$(PTHREAD_LIBS) AM_LIBADD=$(PTHREAD_LIBS) @@ -39,6 +39,7 @@ polypinclude_HEADERS=polyplib.h \ polyplib-subscribe.h \ polyplib-operation.h \ polyplib-scache.h \ + polyplib-version.h \ cdecl.h \ mainloop-api.h \ mainloop.h \ @@ -304,6 +305,7 @@ libpolyp_la_SOURCES = polyplib.h \ polyplib-introspect.c polyplib-introspect.h \ polyplib-scache.c polyplib-scache.h \ polyplib-subscribe.c polyplib-subscribe.h \ + polyplib-internal.h \ cdecl.h \ llist.h libpolyp_la_CFLAGS = $(AM_CFLAGS) diff --git a/polyp/main.c b/polyp/main.c index 9f3d34063..de02a110f 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -126,7 +126,7 @@ int main(int argc, char *argv[]) { r = lt_dlinit(); assert(r == 0); #ifdef DLSEARCHDIR -/* lt_dladdsearchdir(DLSEARCHDIR);*/ + lt_dladdsearchdir(DLSEARCHDIR); #endif mainloop = pa_mainloop_new(); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index d633c2655..c8e5137e4 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -1154,25 +1154,27 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); i = c->protocol->core->scache; } - - for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) { - if (command == PA_COMMAND_GET_SINK_INFO_LIST) - sink_fill_tagstruct(reply, p); - else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST) - source_fill_tagstruct(reply, p); - else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST) - client_fill_tagstruct(reply, p); - else if (command == PA_COMMAND_GET_MODULE_INFO_LIST) - module_fill_tagstruct(reply, p); - else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST) - sink_input_fill_tagstruct(reply, p); - else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST) - source_output_fill_tagstruct(reply, p); - else { - assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); - scache_fill_tagstruct(reply, p); + + if (i) { + for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) { + if (command == PA_COMMAND_GET_SINK_INFO_LIST) + sink_fill_tagstruct(reply, p); + else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST) + source_fill_tagstruct(reply, p); + else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST) + client_fill_tagstruct(reply, p); + else if (command == PA_COMMAND_GET_MODULE_INFO_LIST) + module_fill_tagstruct(reply, p); + else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST) + sink_input_fill_tagstruct(reply, p); + else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST) + source_output_fill_tagstruct(reply, p); + else { + assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); + scache_fill_tagstruct(reply, p); + } } - } + } pa_pstream_send_tagstruct(c->pstream, reply); } From 8f90450ee26117c5950d05c7dcb9ff93fad158a5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 20 Aug 2004 11:04:25 +0000 Subject: [PATCH 0142/1514] Doxygen stuff git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@143 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 0df5fac1d..7372129a4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,11 +31,12 @@ README: $(MAKE) -C doc README cd $(srcdir) && ln -s doc/README README -homepage: all dist +homepage: all dist doxygen test -d $$HOME/homepage/private mkdir -p $$HOME/homepage/private/projects/polypaudio cp *.tar.gz $$HOME/homepage/private/projects/polypaudio cp doc/README.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/polypaudio + cp -a doxygen/html $$HOME/homepage/private/projects/polypaudio/doxygen cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html distcleancheck: From 0b9f91dca59dc5833ddc393c98b2ce7e2f8e1491 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 20 Aug 2004 11:05:53 +0000 Subject: [PATCH 0143/1514] readme update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@144 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README.html.in b/doc/README.html.in index 602787d4f..f3be2b57b 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -97,7 +97,7 @@ href="modules.html">modules.html, cli.html, daemon.html.

    -

    You may browser the Doxygen generated You may browse the Doxygen generated programing documentation for the client API. (Run make doxygen to generate this documentation from the source tree)

    From 9b5ba2bc481bf67237f6ccb098495da13d350ca2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 20 Aug 2004 11:08:19 +0000 Subject: [PATCH 0144/1514] doxygen fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@145 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 7372129a4..632d226f2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,10 +33,10 @@ README: homepage: all dist doxygen test -d $$HOME/homepage/private - mkdir -p $$HOME/homepage/private/projects/polypaudio + mkdir -p $$HOME/homepage/private/projects/polypaudio $$HOME/homepage/private/projects/polypaudio/doxygen cp *.tar.gz $$HOME/homepage/private/projects/polypaudio cp doc/README.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/polypaudio - cp -a doxygen/html $$HOME/homepage/private/projects/polypaudio/doxygen + cp -a doxygen/html/* $$HOME/homepage/private/projects/polypaudio/doxygen cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html distcleancheck: From 8c756d55da58779388cb07a2e135ba3f8ef3988c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 20 Aug 2004 13:06:55 +0000 Subject: [PATCH 0145/1514] documentation update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@146 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 31 ++++++++++++++++----- doc/cli.html.in | 65 ++++++++++++++++++++++++++++++++++++++------- doc/modules.html.in | 11 +++++++- 3 files changed, 90 insertions(+), 17 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index f3be2b57b..e3736c861 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -97,10 +97,6 @@ href="modules.html">modules.html, cli.html, daemon.html.

    -

    You may browse the Doxygen generated programing -documentation for the client API. (Run make doxygen to generate this documentation from the source tree)

    -

    First Steps

    Simply start the polypaudio daemon with the argument -C

    @@ -114,13 +110,36 @@ documentation for the client API. (Run make doxygen to generate thi

    Now you can issue CLI commands as described in cli.html. Another way to start -polypaudio is by specifying a configuration script on the -command line like that one included in the distribution:

    +polypaudio is by specifying a configuration script like that one included in the distribution on the +command line :

    polypaudio -F polypaudio.pa

    This will load some drivers and protocols automatically.

    +

    Developing polypaudio Clients

    + +

    You may browse the Doxygen generated programing +documentation for the client API. (Run make doxygen to generate this documentation from the source tree)

    + +

    Developing polypaudio Modules

    + +

    There are several reasons for writing loadable modules for polypaudio:

    + +
      +
    • Device driver support in addition to ALSA/OSS
    • +
    • Protocol support beyond ESOUND's protocol and the native protocol. (such as NAS or a subset of aRts)
    • +
    • New programming interfaces such as XMLRPC or DBUS for controlling the daemon.
    • +
    • Hooking audio event sources directly into polypaudio (similar to module-x11-bell)
    • +
    • For low latency applications such as VOIP: load the VOIP core directly into polypaudio and have a slim GUI frontend to control it.
    • +
    + +

    There is currently no documentation how to write loadable modules +for polypaudio. Read the source, Luke! If you are interested in +writing new modules feel free to contact the author in case you have any +questions.

    +

    Requirements

    Currently, polypaudio is tested on Linux only. It requires an OSS or ALSA compatible soundcard.

    diff --git a/doc/cli.html.in b/doc/cli.html.in index c67d78db7..01c04cc9a 100644 --- a/doc/cli.html.in +++ b/doc/cli.html.in @@ -87,7 +87,45 @@ input list. The same volume rules apply as with sink_volume.

    (resp. ssource) by its index in the sink (resp. source) list or by its name.

    -

    Killing clients/streams

    +

    Sample Cache

    + +

    scache_list

    + +

    Lists the contents of the sample cache.

    + +

    scache_play

    + +

    Play a sample cache entry to a sink. Expects the sample name and the sink name as arguments.

    + +

    sache_remove

    + +

    Remove an entry from the sample cache. Expects the sample name as argument.

    + +

    sache_load

    + +

    Load an audio file to the sample cache. Expects the file name to load and the desired sample name as arguments.

    + +

    Module Autoloading

    + +

    autoload_list

    + +

    Lists all currently defined autoloading entries.

    + +

    autoload_sink_add/autoload_source_add

    + +

    Adds an autoloading entry for a sink (resp. source). Expects the sink name (resp. source name), the module name and the module arguments as arguments.

    + +

    autoload_sink_remove/autoload_source_remove

    + +

    Remove an autoloading entry. Expects the sink name (resp. source name) as argument.

    + +

    Miscellaneous Commands

    + +

    play_file

    + +

    Play an audio file to a sink. Expects the file name and the sink name as argumens.

    + +

    Killing Clients/Streams

    kill_client

    @@ -120,12 +158,14 @@ on the interactive command line.

    Example Configuration Script

    +

    Mark the following script as executable (chmod +x) and run it for a sensible polypaudio configuration.

    +
     #!/usr/bin/polaudio -F
     
    -# Load audio drivers
    -load module-alsa-sink device=plughw:0,0 rate=48000
    -load module-alsa-source device=hw:1,0
    +# Create autoload entries for the device drivers
    +autoload_sink_add output module-alsa-sink device=plughw:0,0 rate=48000 sink_name=output
    +autoload_source_add input load module-alsa-source device=hw:1,0 source_name=input
     
     # Load several protocols
     load module-esound-protocol-tcp
    @@ -136,17 +176,22 @@ load module-cli-protocol-unix
     # Load the CLI module (This is similar to passing "-C" on the command line of polypaudio)
     load module-cli
     
    +# Make some devices default
    +sink_default output
    +source_default input
    +
    +# Don't fail if the audio files referred to below don't exist
     .nofail
     
    -# Make some devices default
    -sink_default alsa_output
    -source_default alsa_input
    +# Load an audio to the sample cache for usage with module-x11-bell
    +scache_load /usr/share/sounds/KDE_Notify.wav x11-bell
    +load module-x11-bell
     
    -# Use digital amplification
    -sink_volume alsa_output 0x200
    +# Play a welcome sound
    +play_file /usr/share/sounds/startup3.wav output
     

    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, August 2004
    $Id$
    diff --git a/doc/modules.html.in b/doc/modules.html.in index 6954418fb..fe202989e 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -184,8 +184,17 @@ about the two possible suffixes of this module.

    cookie=Name of the cookie file for authentication purposes +

    module-x11-bell

    + +

    Intercepts X11 bell events and plays a sample from the sample cache on each occurence.

    + + + + + +
    display=X11 display to connect to. If ommited defaults to the value of $DISPLAY
    sample=The sample to play. If ommited defaults to x11-bell.
    sink=Name of the sink to play the sample on. If ommited defaults to the default sink.

    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, August 2004
    $Id$
    From 669452e4e59add411023aa3ae1ef1e67d380026c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 20 Aug 2004 13:18:07 +0000 Subject: [PATCH 0146/1514] documentation update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@147 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index e3736c861..8972fe1b7 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -84,7 +84,7 @@ attempt to write a sound server asd.

    A GTK GUI manager application for polypaudio is the Polypaudio Manager.

    +href="http://0pointer.de/lennart/projects/paman/">Polypaudio Manager.

    Status

    @@ -152,7 +152,7 @@ management.

    polypaudio needs Secret Rabbit Code (aka -libsamplerate), libsndfile, libsamplerate), libsndfile, alsa-lib and GLIB. (The latter is required for building the GLIB main loop integration module only.)

    Installation

    From 5e8bb1410e422e144538f1bf6e56dcf47ff0b99d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 20 Aug 2004 20:20:20 +0000 Subject: [PATCH 0147/1514] add support for glib12 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@150 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 + polyp/Makefile.am | 15 +- polyp/glib-mainloop.h | 5 + polyp/glib12-mainloop.c | 497 ++++++++++++++++++++++++++++++++++++++++ polyp/mainloop-test.c | 35 ++- polyp/polypaudio.pa | 5 +- 6 files changed, 551 insertions(+), 10 deletions(-) create mode 100644 polyp/glib12-mainloop.c diff --git a/configure.ac b/configure.ac index 96b4cf3ae..8307bea56 100644 --- a/configure.ac +++ b/configure.ac @@ -85,6 +85,10 @@ PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ]) AC_SUBST(GLIB20_CFLAGS) AC_SUBST(GLIB20_LIBS) +PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ]) +AC_SUBST(GLIB12_CFLAGS) +AC_SUBST(GLIB12_LIBS) + # If using GCC specifiy some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -W -Wall -Wno-unused-parameter -pedantic -std=c99" diff --git a/polyp/Makefile.am b/polyp/Makefile.am index f9f6b6ab5..8acbc012c 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -17,7 +17,8 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -AM_CFLAGS=-D_GNU_SOURCE -DDLSEARCHDIR=\"$(pkglibdir)\" -I$(top_srcdir) $(PTHREAD_CFLAGS) +AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) +#AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" AM_LDADD=$(PTHREAD_LIBS) AM_LIBADD=$(PTHREAD_LIBS) @@ -25,7 +26,7 @@ polypincludedir=$(includedir)/polyp EXTRA_DIST = polypaudio.pa depmod.py bin_PROGRAMS = polypaudio pacat pactl -noinst_PROGRAMS = mainloop-test mainloop-test-glib pacat-simple parec-simple +noinst_PROGRAMS = mainloop-test mainloop-test-glib mainloop-test-glib12 pacat-simple parec-simple BUILT_SOURCES=polyplib-version.h @@ -88,6 +89,7 @@ lib_LTLIBRARIES=libpolyp.la \ libpolyp-error.la \ libpolyp-mainloop.la \ libpolyp-mainloop-glib.la \ + libpolyp-mainloop-glib12.la \ libpolyp-simple.la polypaudio_SOURCES = idxset.c idxset.h \ @@ -333,6 +335,11 @@ libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB20_LIBS) libpolyp_mainloop_glib_la_LDFLAGS = -version-info 0:0:0 +libpolyp_mainloop_glib12_la_SOURCES = glib-mainloop.h glib12-mainloop.c +libpolyp_mainloop_glib12_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) +libpolyp_mainloop_glib12_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB12_LIBS) +libpolyp_mainloop_glib12_la_LDFLAGS = -version-info 0:0:0 + pacat_SOURCES = pacat.c pacat_LDADD = $(AM_LDADD) libpolyp.la libpolyp-error.la libpolyp-mainloop.la pacat_CFLAGS = $(AM_CFLAGS) @@ -357,6 +364,10 @@ mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib.la +mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) +mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP +mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12.la + if BUILD_LIBPOLYPCORE polypinclude_HEADERS+=cli-command.h\ diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h index 1fc7f64aa..afc83be26 100644 --- a/polyp/glib-mainloop.h +++ b/polyp/glib-mainloop.h @@ -37,7 +37,12 @@ PA_C_DECL_BEGIN struct pa_glib_mainloop; /** Create a new GLIB main loop object for the specified GLIB main loop context. If c is NULL the default context is used. */ +#if GLIB_MAJOR_VERSION >= 2 struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c); +#else +struct pa_glib_mainloop *pa_glib_mainloop_new(void); +#endif + /** Free the GLIB main loop object */ void pa_glib_mainloop_free(struct pa_glib_mainloop* g); diff --git a/polyp/glib12-mainloop.c b/polyp/glib12-mainloop.c new file mode 100644 index 000000000..c7085cc96 --- /dev/null +++ b/polyp/glib12-mainloop.c @@ -0,0 +1,497 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "glib-mainloop.h" +#include "idxset.h" +#include "xmalloc.h" + +struct pa_io_event { + struct pa_glib_mainloop *mainloop; + int dead; + GIOChannel *io_channel; + guint source; + GIOCondition io_condition; + int fd; + void (*callback) (struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata); + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_io_event*e, void *userdata); + struct pa_io_event *next, *prev; +}; + +struct pa_time_event { + struct pa_glib_mainloop *mainloop; + int dead; + guint source; + struct timeval timeval; + void (*callback) (struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata); + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_time_event*e, void *userdata); + struct pa_time_event *next, *prev; +}; + +struct pa_defer_event { + struct pa_glib_mainloop *mainloop; + int dead; + guint source; + void (*callback) (struct pa_mainloop_api*m, struct pa_defer_event *e, void *userdata); + void *userdata; + void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata); + struct pa_defer_event *next, *prev; +}; + +struct pa_glib_mainloop { + struct pa_mainloop_api api; + guint cleanup_source; + struct pa_io_event *io_events, *dead_io_events; + struct pa_time_event *time_events, *dead_time_events; + struct pa_defer_event *defer_events, *dead_defer_events; +}; + +static void schedule_free_dead_events(struct pa_glib_mainloop *g); + +static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f); + +static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa_io_event_flags f, void (*callback) (struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata), void *userdata) { + struct pa_io_event *e; + struct pa_glib_mainloop *g; + + assert(m && m->userdata && fd >= 0 && callback); + g = m->userdata; + + e = pa_xmalloc(sizeof(struct pa_io_event)); + e->mainloop = m->userdata; + e->dead = 0; + e->fd = fd; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + + e->io_channel = g_io_channel_unix_new(e->fd); + assert(e->io_channel); + e->source = (guint) -1; + e->io_condition = 0; + + glib_io_enable(e, f); + + e->next = g->io_events; + if (e->next) e->next->prev = e; + g->io_events = e; + e->prev = NULL; + + return e; +} + +static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) { + struct pa_io_event *e = data; + enum pa_io_event_flags f; + assert(source && e && e->io_channel == source); + + f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) | + (condition & G_IO_OUT ? PA_IO_EVENT_OUTPUT : 0) | + (condition & G_IO_ERR ? PA_IO_EVENT_ERROR : 0) | + (condition & G_IO_HUP ? PA_IO_EVENT_HANGUP : 0); + + e->callback(&e->mainloop->api, e, e->fd, f, e->userdata); + return TRUE; +} + +static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f) { + GIOCondition c; + assert(e && !e->dead); + + c = (f & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | (f & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0); + + if (c == e->io_condition) + return; + + if (e->source != (guint) -1) + g_source_remove(e->source); + + e->source = g_io_add_watch_full(e->io_channel, G_PRIORITY_DEFAULT, c | G_IO_ERR | G_IO_HUP, io_cb, e, NULL); + assert(e->source != (guint) -1); + e->io_condition = c; +} + +static void glib_io_free(struct pa_io_event*e) { + assert(e && !e->dead); + + if (e->source != (guint) -1) { + g_source_remove(e->source); + e->source = (guint) -1; + } + + if (e->prev) + e->prev->next = e->next; + else + e->mainloop->io_events = e->next; + + if (e->next) + e->next->prev = e->prev; + + if ((e->next = e->mainloop->dead_io_events)) + e->next->prev = e; + + e->mainloop->dead_io_events = e; + e->prev = NULL; + + e->dead = 1; + schedule_free_dead_events(e->mainloop); +} + +static void glib_io_set_destroy(struct pa_io_event*e, void (*callback)(struct pa_mainloop_api*m, struct pa_io_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* Time sources */ + +static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv); + +static struct pa_time_event* glib_time_new(struct pa_mainloop_api*m, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*m, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { + struct pa_glib_mainloop *g; + struct pa_time_event *e; + + assert(m && m->userdata && tv && callback); + g = m->userdata; + + e = pa_xmalloc(sizeof(struct pa_time_event)); + e->mainloop = g; + e->dead = 0; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + e->source = (guint) -1; + + glib_time_restart(e, tv); + + e->next = g->time_events; + if (e->next) e->next->prev = e; + g->time_events = e; + e->prev = NULL; + + return e; +} + +static guint msec_diff(const struct timeval *a, const struct timeval *b) { + guint r; + assert(a && b); + + if (a->tv_sec < b->tv_sec) + return 0; + + if (a->tv_sec == b->tv_sec && a->tv_sec <= b->tv_sec) + return 0; + + r = (a->tv_sec-b->tv_sec)*1000; + + if (a->tv_usec >= b->tv_usec) + r += (a->tv_usec - b->tv_usec) / 1000; + else + r -= (b->tv_usec - a->tv_usec) / 1000; + + return r; +} + +static gboolean time_cb(gpointer data) { + struct pa_time_event* e = data; + assert(e && e->mainloop && e->source != (guint) -1); + + g_source_remove(e->source); + e->source = (guint) -1; + + e->callback(&e->mainloop->api, e, &e->timeval, e->userdata); + return FALSE; +} + +static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) { + struct timeval now; + assert(e && e->mainloop && !e->dead); + + gettimeofday(&now, NULL); + if (e->source != (guint) -1) + g_source_remove(e->source); + + if (tv) { + e->timeval = *tv; + e->source = g_timeout_add_full(G_PRIORITY_DEFAULT, msec_diff(tv, &now), time_cb, e, NULL); + assert(e->source != (guint) -1); + } else + e->source = (guint) -1; + } + +static void glib_time_free(struct pa_time_event *e) { + assert(e && e->mainloop && !e->dead); + + if (e->source != (guint) -1) { + g_source_remove(e->source); + e->source = (guint) -1; + } + + if (e->prev) + e->prev->next = e->next; + else + e->mainloop->time_events = e->next; + + if (e->next) + e->next->prev = e->prev; + + if ((e->next = e->mainloop->dead_time_events)) + e->next->prev = e; + + e->mainloop->dead_time_events = e; + e->prev = NULL; + + e->dead = 1; + schedule_free_dead_events(e->mainloop); +} + +static void glib_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*m, struct pa_time_event*e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* Deferred sources */ + +static void glib_defer_enable(struct pa_defer_event *e, int b); + +static struct pa_defer_event* glib_defer_new(struct pa_mainloop_api*m, void (*callback) (struct pa_mainloop_api*m, struct pa_defer_event *e, void *userdata), void *userdata) { + struct pa_defer_event *e; + struct pa_glib_mainloop *g; + + assert(m && m->userdata && callback); + g = m->userdata; + + e = pa_xmalloc(sizeof(struct pa_defer_event)); + e->mainloop = g; + e->dead = 0; + e->callback = callback; + e->userdata = userdata; + e->destroy_callback = NULL; + e->source = (guint) -1; + + glib_defer_enable(e, 1); + + e->next = g->defer_events; + if (e->next) e->next->prev = e; + g->defer_events = e; + e->prev = NULL; + return e; +} + +static gboolean idle_cb(gpointer data) { + struct pa_defer_event* e = data; + assert(e && e->mainloop && e->source != (guint) -1); + + e->callback(&e->mainloop->api, e, e->userdata); + return TRUE; +} + +static void glib_defer_enable(struct pa_defer_event *e, int b) { + assert(e && e->mainloop); + + if (e->source != (guint) -1 && !b) { + g_source_remove(e->source); + e->source = (guint) -1; + } else if (e->source == (guint) -1 && b) { + e->source = g_idle_add_full(G_PRIORITY_HIGH, idle_cb, e, NULL); + assert(e->source != (guint) -1); + } +} + +static void glib_defer_free(struct pa_defer_event *e) { + assert(e && e->mainloop && !e->dead); + + if (e->source != (guint) -1) { + g_source_remove(e->source); + e->source = (guint) -1; + } + + if (e->prev) + e->prev->next = e->next; + else + e->mainloop->defer_events = e->next; + + if (e->next) + e->next->prev = e->prev; + + if ((e->next = e->mainloop->dead_defer_events)) + e->next->prev = e; + + e->mainloop->dead_defer_events = e; + e->prev = NULL; + + e->dead = 1; + schedule_free_dead_events(e->mainloop); +} + +static void glib_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata)) { + assert(e); + e->destroy_callback = callback; +} + +/* quit() */ + +static void glib_quit(struct pa_mainloop_api*a, int retval) { + struct pa_glib_mainloop *g; + assert(a && a->userdata); + g = a->userdata; + + /* NOOP */ +} + +static const struct pa_mainloop_api vtable = { + .userdata = NULL, + + .io_new = glib_io_new, + .io_enable = glib_io_enable, + .io_free = glib_io_free, + .io_set_destroy= glib_io_set_destroy, + + .time_new = glib_time_new, + .time_restart = glib_time_restart, + .time_free = glib_time_free, + .time_set_destroy = glib_time_set_destroy, + + .defer_new = glib_defer_new, + .defer_enable = glib_defer_enable, + .defer_free = glib_defer_free, + .defer_set_destroy = glib_defer_set_destroy, + + .quit = glib_quit, +}; + +struct pa_glib_mainloop *pa_glib_mainloop_new(void) { + struct pa_glib_mainloop *g; + + g = pa_xmalloc(sizeof(struct pa_glib_mainloop)); + + g->api = vtable; + g->api.userdata = g; + + g->io_events = g->dead_io_events = NULL; + g->time_events = g->dead_time_events = NULL; + g->defer_events = g->dead_defer_events = NULL; + + g->cleanup_source = (guint) -1; + return g; +} + +static void free_io_events(struct pa_io_event *e) { + while (e) { + struct pa_io_event *r = e; + e = r->next; + + if (r->source != (guint) -1) + g_source_remove(r->source); + + if (r->io_channel) + g_io_channel_unref(r->io_channel); + + if (r->destroy_callback) + r->destroy_callback(&r->mainloop->api, r, r->userdata); + + pa_xfree(r); + } +} + +static void free_time_events(struct pa_time_event *e) { + while (e) { + struct pa_time_event *r = e; + e = r->next; + + if (r->source != (guint) -1) + g_source_remove(r->source); + + if (r->destroy_callback) + r->destroy_callback(&r->mainloop->api, r, r->userdata); + + pa_xfree(r); + } +} + +static void free_defer_events(struct pa_defer_event *e) { + while (e) { + struct pa_defer_event *r = e; + e = r->next; + + if (r->source != (guint) -1) + g_source_remove(r->source); + + if (r->destroy_callback) + r->destroy_callback(&r->mainloop->api, r, r->userdata); + + pa_xfree(r); + } +} + +void pa_glib_mainloop_free(struct pa_glib_mainloop* g) { + assert(g); + + free_io_events(g->io_events); + free_io_events(g->dead_io_events); + free_defer_events(g->defer_events); + free_defer_events(g->dead_defer_events); + free_time_events(g->time_events); + free_time_events(g->dead_time_events); + + if (g->cleanup_source != (guint) -1) + g_source_remove(g->cleanup_source); + + pa_xfree(g); +} + +struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g) { + assert(g); + return &g->api; +} + +static gboolean free_dead_events(gpointer p) { + struct pa_glib_mainloop *g = p; + assert(g); + + free_io_events(g->dead_io_events); + free_defer_events(g->dead_defer_events); + free_time_events(g->dead_time_events); + + g->dead_io_events = NULL; + g->dead_defer_events = NULL; + g->dead_time_events = NULL; + + g_source_remove(g->cleanup_source); + g->cleanup_source = (guint) -1; + + return FALSE; +} + +static void schedule_free_dead_events(struct pa_glib_mainloop *g) { + assert(g); + + if (g->cleanup_source != (guint) -1) + return; + + g->cleanup_source = g_idle_add_full(G_PRIORITY_HIGH, free_dead_events, g, NULL); +} diff --git a/polyp/mainloop-test.c b/polyp/mainloop-test.c index c2517065e..92b83c145 100644 --- a/polyp/mainloop-test.c +++ b/polyp/mainloop-test.c @@ -29,12 +29,21 @@ #include #ifdef GLIB_MAIN_LOOP + #include #include "glib-mainloop.h" static GMainLoop* glib_main_loop = NULL; + +#if GLIB_MAJOR_VERSION >= 2 +#define GLIB20 #else +#undef GLIB20 +#endif + + +#else /* GLIB_MAIN_LOOP */ #include "mainloop.h" -#endif +#endif /* GLIB_MAIN_LOOP */ static struct pa_defer_event *de; @@ -53,8 +62,10 @@ static void dcb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userda static void tcb(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval *tv, void *userdata) { fprintf(stderr, "TIME EVENT\n"); -#ifdef GLIB_MAIN_LOOP +#if defined(GLIB_MAIN_LOOP) && defined(GLIB20) g_main_loop_quit(glib_main_loop); +#elif defined(GLIB_MAIN_LOOP) + g_main_quit(glib_main_loop); #else a->quit(a, 0); #endif @@ -68,15 +79,23 @@ int main(int argc, char *argv[]) { #ifdef GLIB_MAIN_LOOP struct pa_glib_mainloop *g; + +#ifdef GLIB20 glib_main_loop = g_main_loop_new(NULL, FALSE); assert(glib_main_loop); g = pa_glib_mainloop_new(NULL); +#else /* GLIB20 */ + glib_main_loop = g_main_new(FALSE); + assert(glib_main_loop); + + g = pa_glib_mainloop_new(); +#endif /* GLIB20 */ assert(g); a = pa_glib_mainloop_get_api(g); assert(a); -#else +#else /* GLIB_MAIN_LOOP */ struct pa_mainloop *m; m = pa_mainloop_new(); @@ -84,7 +103,7 @@ int main(int argc, char *argv[]) { a = pa_mainloop_get_api(m); assert(a); -#endif +#endif /* GLIB_MAIN_LOOP */ ioe = a->io_new(a, 0, PA_IO_EVENT_INPUT, iocb, NULL); assert(ioe); @@ -96,8 +115,10 @@ int main(int argc, char *argv[]) { tv.tv_sec += 10; te = a->time_new(a, &tv, tcb, NULL); -#ifdef GLIB_MAIN_LOOP +#if defined(GLIB_MAIN_LOOP) && defined(GLIB20) g_main_loop_run(glib_main_loop); +#elif defined(GLIB_MAIN_LOOP) + g_main_run(glib_main_loop); #else pa_mainloop_run(m, NULL); #endif @@ -108,7 +129,11 @@ int main(int argc, char *argv[]) { #ifdef GLIB_MAIN_LOOP pa_glib_mainloop_free(g); +#ifdef GLIB20 g_main_loop_unref(glib_main_loop); +#else + g_main_destroy(glib_main_loop); +#endif #else pa_mainloop_free(m); #endif diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 9f8cf8602..c63e14795 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -30,8 +30,8 @@ load module-pipe-sink #autoload_sink_add output module-oss device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input -#autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_sink_add output module-alsa-sink sink_name=output #autoload_source_add input module-alsa-source source_name=input @@ -52,7 +52,6 @@ source_default input # Load something to the sample cache scache_load /usr/share/sounds/KDE_Notify.wav x11-bell -scache_play x11-bell output # Load X11 bell module load module-x11-bell sample=x11-bell sink=output From ea4805a0fd4aea6db4c99e1187aca8e013e4dc24 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 20 Aug 2004 20:30:06 +0000 Subject: [PATCH 0148/1514] add pkg config file glib12-mainloop git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@151 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- configure.ac | 2 +- polyplib-glib12-mainloop.pc.in | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 polyplib-glib12-mainloop.pc.in diff --git a/Makefile.am b/Makefile.am index 632d226f2..3eeef9561 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ MAINTAINERCLEANFILES=README noinst_DATA = README pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-glib-mainloop.pc +pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc README: rm -f README diff --git a/configure.ac b/configure.ac index 8307bea56..7e0b3c213 100644 --- a/configure.ac +++ b/configure.ac @@ -115,5 +115,5 @@ AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) -AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h]) +AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h]) AC_OUTPUT diff --git a/polyplib-glib12-mainloop.pc.in b/polyplib-glib12-mainloop.pc.in new file mode 100644 index 000000000..3afed38e3 --- /dev/null +++ b/polyplib-glib12-mainloop.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: polyplib-glib-mainloop +Description: GLIB main loop wrapper for polypaudio +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lpolyp-mainloop-glib12 +Cflags: -D_REENTRANT -I${includedir} +Requires: polyplib-mainloop From 41295bbf56ef6df0a0e705149475d91c8d83ff3f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 22 Aug 2004 21:13:58 +0000 Subject: [PATCH 0149/1514] new features: future cancellation corking flushing for playback streams in native protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@152 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/memblockq.c | 171 +++++++++++++++++++-------------------- polyp/memblockq.h | 16 ++-- polyp/native-common.h | 3 + polyp/pacat.c | 2 +- polyp/pactl.c | 2 +- polyp/play-memchunk.c | 3 +- polyp/polyplib-context.c | 2 +- polyp/polyplib-simple.c | 2 +- polyp/polyplib-stream.c | 49 ++++++++++- polyp/polyplib-stream.h | 35 +++++++- polyp/protocol-esound.c | 8 +- polyp/protocol-native.c | 68 ++++++++++++++-- polyp/protocol-simple.c | 6 +- polyp/pstream.c | 10 +-- polyp/pstream.h | 4 +- polyp/sink-input.c | 23 +++++- polyp/sink-input.h | 8 +- polyp/sink.c | 2 +- polyp/util.c | 21 +++++ polyp/util.h | 3 + 20 files changed, 309 insertions(+), 129 deletions(-) diff --git a/polyp/memblockq.c b/polyp/memblockq.c index 085c05108..b6dcca3f5 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -28,22 +28,20 @@ #include #include #include +#include #include "memblockq.h" #include "xmalloc.h" struct memblock_list { - struct memblock_list *next; + struct memblock_list *next, *prev; struct pa_memchunk chunk; - struct timeval stamp; }; struct pa_memblockq { struct memblock_list *blocks, *blocks_tail; unsigned n_blocks; size_t current_length, maxlength, tlength, base, prebuf, minreq; - int measure_delay; - uint32_t delay; struct pa_mcalign *mcalign; struct pa_memblock_stat *memblock_stat; }; @@ -66,7 +64,7 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b assert(bq->maxlength >= base); bq->tlength = ((tlength+base-1)/base)*base; - if (bq->tlength == 0 || bq->tlength >= bq->maxlength) + if (!bq->tlength || bq->tlength >= bq->maxlength) bq->tlength = bq->maxlength; bq->prebuf = (prebuf == (size_t) -1) ? bq->maxlength/2 : prebuf; @@ -80,29 +78,21 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b fprintf(stderr, "memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); - bq->measure_delay = 0; - bq->delay = 0; - bq->mcalign = NULL; bq->memblock_stat = s; - + return bq; } void pa_memblockq_free(struct pa_memblockq* bq) { - struct memblock_list *l; assert(bq); + pa_memblockq_flush(bq); + if (bq->mcalign) pa_mcalign_free(bq->mcalign); - while ((l = bq->blocks)) { - bq->blocks = l->next; - pa_memblock_unref(l->chunk.memblock); - pa_xfree(l); - } - pa_xfree(bq); } @@ -110,31 +100,25 @@ void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, struct memblock_list *q; assert(bq && chunk && chunk->memblock && chunk->length && (chunk->length % bq->base) == 0); + pa_memblockq_seek(bq, delta); + if (bq->blocks_tail && bq->blocks_tail->chunk.memblock == chunk->memblock) { /* Try to merge memory chunks */ if (bq->blocks_tail->chunk.index+bq->blocks_tail->chunk.length == chunk->index) { bq->blocks_tail->chunk.length += chunk->length; bq->current_length += chunk->length; - - /* fprintf(stderr, __FILE__": merge succeeded: %u\n", chunk->length);*/ return; } } q = pa_xmalloc(sizeof(struct memblock_list)); - if (bq->measure_delay) - gettimeofday(&q->stamp, NULL); - else - timerclear(&q->stamp); - q->chunk = *chunk; pa_memblock_ref(q->chunk.memblock); assert(q->chunk.index+q->chunk.length <= q->chunk.memblock->length); q->next = NULL; - - if (bq->blocks_tail) + if ((q->prev = bq->blocks_tail)) bq->blocks_tail->next = q; else bq->blocks = q; @@ -158,57 +142,43 @@ int pa_memblockq_peek(struct pa_memblockq* bq, struct pa_memchunk *chunk) { *chunk = bq->blocks->chunk; pa_memblock_ref(chunk->memblock); -/* if (chunk->memblock->ref != 2) */ -/* fprintf(stderr, "block %p with ref %u peeked.\n", chunk->memblock, chunk->memblock->ref); */ - return 0; } -/* -int memblockq_pop(struct memblockq* bq, struct pa_memchunk *chunk) { - struct memblock_list *q; +void pa_memblockq_drop(struct pa_memblockq *bq, const struct pa_memchunk *chunk, size_t length) { + assert(bq && chunk && length); + + if (!bq->blocks || memcmp(&bq->blocks->chunk, chunk, sizeof(struct pa_memchunk))) + return; + + assert(length <= bq->blocks->chunk.length); + pa_memblockq_skip(bq, length); +} + +static void remove_block(struct pa_memblockq *bq, struct memblock_list *q) { + assert(bq && q); + + if (q->prev) + q->prev->next = q->next; + else { + assert(bq->blocks == q); + bq->blocks = q->next; + } - assert(bq && chunk); - - if (!bq->blocks || bq->current_length < bq->prebuf) - return -1; - - bq->prebuf = 0; - - q = bq->blocks; - bq->blocks = bq->blocks->next; - - *chunk = q->chunk; - - bq->n_blocks--; - bq->current_length -= chunk->length; - + if (q->next) + q->next->prev = q->prev; + else { + assert(bq->blocks_tail == q); + bq->blocks_tail = q->prev; + } + + pa_memblock_unref(q->chunk.memblock); pa_xfree(q); - return 0; -} -*/ - -static uint32_t age(struct timeval *tv) { - struct timeval now; - uint32_t r; - assert(tv); - - if (tv->tv_sec == 0) - return 0; - - gettimeofday(&now, NULL); - r = (now.tv_sec-tv->tv_sec) * 1000000; - - if (now.tv_usec >= tv->tv_usec) - r += now.tv_usec - tv->tv_usec; - else - r -= tv->tv_usec - now.tv_usec; - - return r; + bq->n_blocks--; } -void pa_memblockq_drop(struct pa_memblockq *bq, size_t length) { +void pa_memblockq_skip(struct pa_memblockq *bq, size_t length) { assert(bq && length && (length % bq->base) == 0); while (length > 0) { @@ -218,25 +188,12 @@ void pa_memblockq_drop(struct pa_memblockq *bq, size_t length) { if (l > bq->blocks->chunk.length) l = bq->blocks->chunk.length; - if (bq->measure_delay) - bq->delay = age(&bq->blocks->stamp); - bq->blocks->chunk.index += l; bq->blocks->chunk.length -= l; bq->current_length -= l; - if (bq->blocks->chunk.length == 0) { - struct memblock_list *q; - - q = bq->blocks; - bq->blocks = bq->blocks->next; - if (bq->blocks == NULL) - bq->blocks_tail = NULL; - pa_memblock_unref(q->chunk.memblock); - pa_xfree(q); - - bq->n_blocks--; - } + if (!bq->blocks->chunk.length) + remove_block(bq, bq->blocks); length -= l; } @@ -255,7 +212,7 @@ void pa_memblockq_shorten(struct pa_memblockq *bq, size_t length) { l /= bq->base; l *= bq->base; - pa_memblockq_drop(bq, l); + pa_memblockq_skip(bq, l); } @@ -276,11 +233,6 @@ int pa_memblockq_is_writable(struct pa_memblockq *bq, size_t length) { return bq->current_length + length <= bq->tlength; } -uint32_t pa_memblockq_get_delay(struct pa_memblockq *bq) { - assert(bq); - return bq->delay; -} - uint32_t pa_memblockq_get_length(struct pa_memblockq *bq) { assert(bq); return bq->current_length; @@ -331,3 +283,44 @@ void pa_memblockq_prebuf_disable(struct pa_memblockq *bq) { assert(bq); bq->prebuf = 0; } + +void pa_memblockq_seek(struct pa_memblockq *bq, size_t length) { + assert(bq); + + if (!length) + return; + + while (length >= bq->base) { + size_t l = length; + if (!bq->current_length) + return; + + assert(bq->blocks_tail); + + if (l > bq->blocks_tail->chunk.length) + l = bq->blocks_tail->chunk.length; + + bq->blocks_tail->chunk.length -= l; + bq->current_length -= l; + + if (bq->blocks_tail->chunk.length == 0) + remove_block(bq, bq->blocks); + + length -= l; + } +} + +void pa_memblockq_flush(struct pa_memblockq *bq) { + struct memblock_list *l; + assert(bq); + + while ((l = bq->blocks)) { + bq->blocks = l->next; + pa_memblock_unref(l->chunk.memblock); + pa_xfree(l); + } + + bq->blocks_tail = NULL; + bq->n_blocks = 0; + bq->current_length = 0; +} diff --git a/polyp/memblockq.h b/polyp/memblockq.h index af8fa3746..277beb55f 100644 --- a/polyp/memblockq.h +++ b/polyp/memblockq.h @@ -44,7 +44,7 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, struct pa_memblock_stat *s); void pa_memblockq_free(struct pa_memblockq*bq); -/* Push a new memory chunk into the queue. Optionally specify a value for future cancellation. This is currently not implemented, however! */ +/* Push a new memory chunk into the queue. Optionally specify a value for future cancellation. */ void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta); /* Same as pa_memblockq_push(), however chunks are filtered through a mcalign object, and thus aligned to multiples of base */ @@ -53,8 +53,11 @@ void pa_memblockq_push_align(struct pa_memblockq* bq, const struct pa_memchunk * /* Return a copy of the next memory chunk in the queue. It is not removed from the queue */ int pa_memblockq_peek(struct pa_memblockq* bq, struct pa_memchunk *chunk); +/* Drop the specified bytes from the queue, only valid aufter pa_memblockq_peek() */ +void pa_memblockq_drop(struct pa_memblockq *bq, const struct pa_memchunk *chunk, size_t length); + /* Drop the specified bytes from the queue */ -void pa_memblockq_drop(struct pa_memblockq *bq, size_t length); +void pa_memblockq_skip(struct pa_memblockq *bq, size_t length); /* Shorten the pa_memblockq to the specified length by dropping data at the end of the queue */ void pa_memblockq_shorten(struct pa_memblockq *bq, size_t length); @@ -68,9 +71,6 @@ int pa_memblockq_is_readable(struct pa_memblockq *bq); /* Test if the pa_memblockq is currently writable for the specified amount of bytes */ int pa_memblockq_is_writable(struct pa_memblockq *bq, size_t length); -/* The time memory chunks stay in the queue until they are removed completely in usecs */ -uint32_t pa_memblockq_get_delay(struct pa_memblockq *bq); - /* Return the length of the queue in bytes */ uint32_t pa_memblockq_get_length(struct pa_memblockq *bq); @@ -83,4 +83,10 @@ uint32_t pa_memblockq_get_minreq(struct pa_memblockq *bq); /* Force disabling of pre-buf even when the pre-buffer is not yet filled */ void pa_memblockq_prebuf_disable(struct pa_memblockq *bq); +/* Manipulate the write pointer */ +void pa_memblockq_seek(struct pa_memblockq *bq, size_t delta); + +/* Flush the queue */ +void pa_memblockq_flush(struct pa_memblockq *bq); + #endif diff --git a/polyp/native-common.h b/polyp/native-common.h index b921ccc2c..d826837ae 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -75,6 +75,9 @@ enum { PA_COMMAND_SET_SINK_VOLUME, PA_COMMAND_SET_SINK_INPUT_VOLUME, + + PA_COMMAND_CORK_PLAYBACK_STREAM, + PA_COMMAND_FLUSH_PLAYBACK_STREAM, PA_COMMAND_MAX }; diff --git a/polyp/pacat.c b/polyp/pacat.c index 2c7044b8c..198776d35 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -65,7 +65,7 @@ static void do_stream_write(size_t length) { if (l > buffer_length) l = buffer_length; - pa_stream_write(stream, buffer+buffer_index, l, NULL); + pa_stream_write(stream, buffer+buffer_index, l, NULL, 0); buffer_length -= l; buffer_index += l; diff --git a/polyp/pactl.c b/polyp/pactl.c index f2556706b..dfa11b70d 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -150,7 +150,7 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user quit(1); } - pa_stream_write(s, d, length, free); + pa_stream_write(s, d, length, free, 0); sample_length -= length; diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index 5c4235670..b94a05242 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -59,11 +59,12 @@ static void si_kill(struct pa_mainloop_api *m, void *i) { sink_input_kill(i); } -static void sink_input_drop(struct pa_sink_input *i, size_t length) { +static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk*chunk, size_t length) { struct pa_memchunk *c; assert(i && length && i->userdata); c = i->userdata; + assert(chunk == c); assert(length <= c->length); c->length -= length; diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index d048cda99..9acb2d703 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -193,7 +193,7 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack pa_context_unref(c); } -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata) { struct pa_context *c = userdata; struct pa_stream *s; assert(p && chunk && c && chunk->memblock && chunk->memblock->data); diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index 66ee5995f..c71d59a4a 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -187,7 +187,7 @@ int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *pe if (l > length) l = length; - pa_stream_write(p->stream, data, l, NULL); + pa_stream_write(p->stream, data, l, NULL, 0); data += l; length -= l; } diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 451dd0461..c0ec9e7eb 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -267,7 +267,7 @@ void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct create_stream(s, dev, attr); } -void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void (*free_cb)(void *p)) { +void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void (*free_cb)(void *p), size_t delta) { struct pa_memchunk chunk; assert(s && s->context && data && length && s->state == PA_STREAM_READY && s->ref >= 1); @@ -282,7 +282,7 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void chunk.index = 0; chunk.length = length; - pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk); + pa_pstream_send_memblock(s->context->pstream, s->channel, delta, &chunk); pa_memblock_unref(chunk.memblock); if (length < s->requested_bytes) @@ -452,3 +452,48 @@ finish: pa_operation_done(o); pa_operation_unref(o); } + +struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { + struct pa_operation *o; + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); + + o = pa_operation_new(s->context, s); + assert(o); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_CORK_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_tagstruct_putu32(t, !!b); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { + struct pa_operation *o; + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); + + o = pa_operation_new(s->context, s); + assert(o); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_FLUSH_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); + + return pa_operation_ref(o); +} diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index 1a9d58dd2..ff3133268 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -70,7 +70,30 @@ void pa_stream_disconnect(struct pa_stream *s); * and an internal reference to the specified data is kept, the data * is not copied. If NULL, the data is copied into an internal * buffer. */ -void pa_stream_write(struct pa_stream *p, const void *data, size_t length, void (*free_cb)(void *p)); +void pa_stream_write(struct pa_stream *p /**< The stream to use */, + const void *data /**< The data to write */, + size_t length /**< The length of the data to write */, + void (*free_cb)(void *p) /**< A cleanup routine for the data or NULL to request an internal copy */, + size_t delta /**< Drop this many + bytes in the playback + buffer before writing + this data. Use + (size_t) -1 for + clearing the whole + playback + buffer. Normally you + will specify 0 here, + .i.e. append to the + playback buffer. If + the value given here + is greater than the + buffered data length + the buffer is cleared + and the data is + written to the + buffer's start. This + value is ignored on + upload streams. */); /** Return the amount of bytes that may be written using pa_stream_write() */ size_t pa_stream_writable_size(struct pa_stream *p); @@ -90,6 +113,16 @@ void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stre /** Set the callback function that is called when new data is available from the stream */ void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); +/** Pause (or resume) playback of this stream temporarily + * \since 0.3 */ +struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); + +/** Flush the playback buffer of this stream. Most of the time you're + * better off using the delta of pa_stream_write() instead of this + * function. + * \since 0.3*/ +struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); + PA_C_DECL_END #endif diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index be2ef2b94..5102540b2 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -102,7 +102,7 @@ typedef struct proto_handler { const char *description; } esd_proto_handler_info_t; -static void sink_input_drop_cb(struct pa_sink_input *i, size_t length); +static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); static void sink_input_kill_cb(struct pa_sink_input *i); static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); @@ -835,7 +835,7 @@ static int do_write(struct connection *c) { return -1; } - pa_memblockq_drop(c->output_memblockq, r); + pa_memblockq_drop(c->output_memblockq, &chunk, r); pa_memblock_unref(chunk.memblock); } @@ -894,11 +894,11 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk return 0; } -static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { +static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { struct connection*c = i->userdata; assert(i && c && length); - pa_memblockq_drop(c->input_memblockq, length); + pa_memblockq_drop(c->input_memblockq, chunk, length); /* do something */ assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index c8e5137e4..8b39482ca 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -107,7 +107,7 @@ struct pa_protocol_native { }; static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); -static void sink_input_drop_cb(struct pa_sink_input *i, size_t length); +static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); static void sink_input_kill_cb(struct pa_sink_input *i); static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); @@ -135,6 +135,8 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_flush_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -176,6 +178,8 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SUBSCRIBE] = { command_subscribe }, [PA_COMMAND_SET_SINK_VOLUME] = { command_set_volume }, [PA_COMMAND_SET_SINK_INPUT_VOLUME] = { command_set_volume }, + [PA_COMMAND_CORK_PLAYBACK_STREAM] = { command_cork_playback_stream }, + [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = { command_flush_playback_stream }, }; /* structure management */ @@ -376,7 +380,7 @@ static void send_memblock(struct connection *c) { chunk.length = r->fragment_size; pa_pstream_send_memblock(c->pstream, r->index, 0, &chunk); - pa_memblockq_drop(r->memblockq, chunk.length); + pa_memblockq_drop(r->memblockq, &chunk, chunk.length); pa_memblock_unref(chunk.memblock); return; @@ -422,12 +426,12 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk return 0; } -static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { +static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { struct playback_stream *s; assert(i && i->userdata && length); s = i->userdata; - pa_memblockq_drop(s->memblockq, length); + pa_memblockq_drop(s->memblockq, chunk, length); request_bytes(s); if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) { @@ -1293,6 +1297,59 @@ static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32 pa_pstream_send_simple_ack(c->pstream, tag); } +static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + uint32_t b; + struct playback_stream *s; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + pa_tagstruct_getu32(t, &b) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_sink_input_cork(s->sink_input, b); + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void command_flush_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + struct playback_stream *s; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_memblockq_flush(s->memblockq); + pa_pstream_send_simple_ack(c->pstream, tag); +} /*** pstream callbacks ***/ @@ -1306,7 +1363,7 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack } } -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata) { struct connection *c = userdata; struct output_stream *stream; assert(p && chunk && userdata); @@ -1338,7 +1395,6 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, in u->memchunk = *chunk; pa_memblock_ref(u->memchunk.memblock); u->length = 0; - fprintf(stderr, "COPY\n"); } else { u->memchunk.memblock = pa_memblock_new(u->length, c->protocol->core->memblock_stat); u->memchunk.index = u->memchunk.length = 0; diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 583434860..b03c2e54a 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -159,7 +159,7 @@ static int do_write(struct connection *c) { return -1; } - pa_memblockq_drop(c->output_memblockq, r); + pa_memblockq_drop(c->output_memblockq, &chunk, r); pa_memblock_unref(chunk.memblock); return 0; @@ -202,11 +202,11 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk return 0; } -static void sink_input_drop_cb(struct pa_sink_input *i, size_t length) { +static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { struct connection*c = i->userdata; assert(i && c && length); - pa_memblockq_drop(c->input_memblockq, length); + pa_memblockq_drop(c->input_memblockq, chunk, length); /* do something */ assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); diff --git a/polyp/pstream.c b/polyp/pstream.c index 5664e18a1..ad3dd0e07 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -50,7 +50,7 @@ struct item_info { /* memblock info */ struct pa_memchunk chunk; uint32_t channel; - int32_t delta; + uint32_t delta; /* packet info */ struct pa_packet *packet; @@ -86,7 +86,7 @@ struct pa_pstream { void (*recieve_packet_callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata); void *recieve_packet_callback_userdata; - void (*recieve_memblock_callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata); + void (*recieve_memblock_callback) (struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata); void *recieve_memblock_callback_userdata; void (*drain_callback)(struct pa_pstream *p, void *userdata); @@ -219,7 +219,7 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { p->mainloop->defer_enable(p->defer_event, 1); } -void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk) { +void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk) { struct item_info *i; assert(p && channel != (uint32_t) -1 && chunk); @@ -242,7 +242,7 @@ void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callbac p->recieve_packet_callback_userdata = userdata; } -void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata), void *userdata) { +void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata), void *userdata) { assert(p && callback); p->recieve_memblock_callback = callback; @@ -378,7 +378,7 @@ static void do_read(struct pa_pstream *p) { p->recieve_memblock_callback( p, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]), - (int32_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA]), + ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA]), &chunk, p->recieve_memblock_callback_userdata); } diff --git a/polyp/pstream.h b/polyp/pstream.h index 9a2895073..dfd29983b 100644 --- a/polyp/pstream.h +++ b/polyp/pstream.h @@ -37,10 +37,10 @@ void pa_pstream_unref(struct pa_pstream*p); struct pa_pstream* pa_pstream_ref(struct pa_pstream*p); void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet); -void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk); +void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk); void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata); -void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata), void *userdata); +void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata), void *userdata); void pa_pstream_set_drain_callback(struct pa_pstream *p, void (*cb)(struct pa_pstream *p, void *userdata), void *userdata); void pa_pstream_set_die_callback(struct pa_pstream *p, void (*callback)(struct pa_pstream *p, void *userdata), void *userdata); diff --git a/polyp/sink-input.c b/polyp/sink-input.c index c57dd8e05..5009033f2 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -59,6 +59,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con i->get_latency = NULL; i->userdata = NULL; + i->corked = 0; i->volume = PA_VOLUME_NORM; i->resampled_chunk.memblock = NULL; @@ -120,6 +121,9 @@ uint32_t pa_sink_input_get_latency(struct pa_sink_input *i) { int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { assert(i && chunk && i->peek && i->drop); + if (i->corked == 0) + return -1; + if (!i->resampler) return i->peek(i, chunk); @@ -134,11 +138,12 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { assert(tchunk.length); l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); + + i->drop(i, &tchunk, l); + if (tchunk.length > l) tchunk.length = l; - i->drop(i, tchunk.length); - pa_resampler_run(i->resampler, &tchunk, &i->resampled_chunk); pa_memblock_unref(tchunk.memblock); } @@ -149,11 +154,11 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { return 0; } -void pa_sink_input_drop(struct pa_sink_input *i, size_t length) { +void pa_sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { assert(i && length); if (!i->resampler) { - i->drop(i, length); + i->drop(i, chunk, length); return; } @@ -177,3 +182,13 @@ void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume) { pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); } } + +void pa_sink_input_cork(struct pa_sink_input *i, int b) { + int n; + assert(i); + n = i->corked && !b; + i->corked = b; + + if (n) + pa_sink_notify(i->sink); +} diff --git a/polyp/sink-input.h b/polyp/sink-input.h index 8d7788d8e..b06445409 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -34,6 +34,8 @@ struct pa_sink_input { uint32_t index; + int corked; + char *name; struct pa_module *owner; struct pa_client *client; @@ -42,7 +44,7 @@ struct pa_sink_input { uint32_t volume; int (*peek) (struct pa_sink_input *i, struct pa_memchunk *chunk); - void (*drop) (struct pa_sink_input *i, size_t length); + void (*drop) (struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); void (*kill) (struct pa_sink_input *i); uint32_t (*get_latency) (struct pa_sink_input *i); @@ -62,8 +64,10 @@ void pa_sink_input_kill(struct pa_sink_input *i); uint32_t pa_sink_input_get_latency(struct pa_sink_input *i); int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk); -void pa_sink_input_drop(struct pa_sink_input *i, size_t length); +void pa_sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume); +void pa_sink_input_cork(struct pa_sink_input *i, int b); + #endif diff --git a/polyp/sink.c b/polyp/sink.c index 62b9a7af2..43fd351cf 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -147,8 +147,8 @@ static void inputs_drop(struct pa_sink *s, struct pa_mix_info *info, unsigned ma struct pa_sink_input *i = info->userdata; assert(i && info->chunk.memblock); + pa_sink_input_drop(i, &info->chunk, length); pa_memblock_unref(info->chunk.memblock); - pa_sink_input_drop(i, length); } } diff --git a/polyp/util.c b/polyp/util.c index 2878c546b..6c8febb62 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "util.h" #include "xmalloc.h" @@ -192,3 +193,23 @@ char *pa_get_host_name(char *s, size_t l) { s[l-1] = 0; return s; } + +uint32_t pa_age(struct timeval *tv) { + struct timeval now; + uint32_t r; + assert(tv); + + if (tv->tv_sec == 0) + return 0; + + gettimeofday(&now, NULL); + + r = (now.tv_sec-tv->tv_sec) * 1000000; + + if (now.tv_usec >= tv->tv_usec) + r += now.tv_usec - tv->tv_usec; + else + r -= tv->tv_usec - now.tv_usec; + + return r; +} diff --git a/polyp/util.h b/polyp/util.h index 7dd7b7de4..9dab45d24 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -23,6 +23,7 @@ ***/ #include +#include void pa_make_nonblock_fd(int fd); @@ -38,4 +39,6 @@ char *pa_sprintf_malloc(const char *format, ...) __attribute__ ((format (printf, char *pa_get_user_name(char *s, size_t l); char *pa_get_host_name(char *s, size_t l); +uint32_t pa_age(struct timeval *tv); + #endif From b6b428e5cbfc2440f5950c0744e15bc4d84e6b31 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 23 Aug 2004 18:48:34 +0000 Subject: [PATCH 0150/1514] minor documentation update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@153 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 4 +--- polyp/polyplib-stream.h | 10 ++++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/doc/todo b/doc/todo index 43d7bc6f5..a317b4f33 100644 --- a/doc/todo +++ b/doc/todo @@ -2,7 +2,6 @@ *** 0.3 *** - pacat drain fix -- future cancellation - make mcalign merge chunks - use ref counting in more objects - unix socket directories include user name @@ -19,10 +18,9 @@ *********** backends for: -- libao - xmms -- portaudio - mplayer +- portaudio - python modules: diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index ff3133268..a0cbe521c 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -83,7 +83,7 @@ void pa_stream_write(struct pa_stream *p /**< The stream to use */, playback buffer. Normally you will specify 0 here, - .i.e. append to the + i.e. append to the playback buffer. If the value given here is greater than the @@ -113,14 +113,12 @@ void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stre /** Set the callback function that is called when new data is available from the stream */ void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); -/** Pause (or resume) playback of this stream temporarily - * \since 0.3 */ +/** Pause (or resume) playback of this stream temporarily. \since 0.3 */ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); /** Flush the playback buffer of this stream. Most of the time you're - * better off using the delta of pa_stream_write() instead of this - * function. - * \since 0.3*/ + * better off using the parameter delta of pa_stream_write() instead of this + * function. \since 0.3 */ struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); PA_C_DECL_END From 92bf0a365a3a8390bb3f023458a9e62c31849628 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 27 Aug 2004 01:29:49 +0000 Subject: [PATCH 0151/1514] latency work major main loop bugfix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@154 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/mainloop.c | 10 ++++++--- polyp/module.c | 4 ++-- polyp/native-common.h | 4 +--- polyp/pacat.c | 6 +++--- polyp/pdispatch.c | 11 ++++++++++ polyp/play-memchunk.c | 4 +++- polyp/polypaudio.pa | 8 ++++---- polyp/polyplib-context.c | 5 ++++- polyp/polyplib-def.h | 9 ++++++++ polyp/polyplib-internal.h | 6 +++--- polyp/polyplib-introspect.h | 4 ++-- polyp/polyplib-stream.c | 41 ++++++++++++++++++++++++------------- polyp/polyplib-stream.h | 7 ++++++- polyp/protocol-native.c | 31 +++++++++++++++++++++------- polyp/pstream.c | 4 ++++ polyp/sample.c | 2 +- polyp/sample.h | 5 ++++- polyp/sink-input.c | 18 +++++++--------- polyp/sink-input.h | 2 +- polyp/sink.c | 4 ++-- polyp/sink.h | 2 +- 21 files changed, 126 insertions(+), 61 deletions(-) diff --git a/polyp/mainloop.c b/polyp/mainloop.c index 84505bb6f..20d14e517 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -186,6 +186,7 @@ static struct pa_time_event* mainloop_time_new(struct pa_mainloop_api*a, const s e->destroy_callback = NULL; pa_idxset_put(m->time_events, e, NULL); + return e; } @@ -201,6 +202,7 @@ static void mainloop_time_restart(struct pa_time_event *e, const struct timeval static void mainloop_time_free(struct pa_time_event *e) { assert(e); + e->dead = e->mainloop->time_events_scan_dead = 1; } @@ -271,7 +273,7 @@ static int io_foreach(void *p, uint32_t index, int *del, void*userdata) { int *all = userdata; assert(e && del && all); - if (!*all || !e->dead) + if (!*all && !e->dead) return 0; if (e->destroy_callback) @@ -286,7 +288,7 @@ static int time_foreach(void *p, uint32_t index, int *del, void*userdata) { int *all = userdata; assert(e && del && all); - if (!*all || !e->dead) + if (!*all && !e->dead) return 0; if (e->destroy_callback) @@ -301,7 +303,7 @@ static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) { int *all = userdata; assert(e && del && all); - if (!*all || !e->dead) + if (!*all && !e->dead) return 0; if (e->destroy_callback) @@ -336,6 +338,8 @@ static void scan_dead(struct pa_mainloop *m) { pa_idxset_foreach(m->time_events, time_foreach, &all); if (m->defer_events_scan_dead) pa_idxset_foreach(m->defer_events, defer_foreach, &all); + + m->io_events_scan_dead = m->time_events_scan_dead = m->defer_events_scan_dead = 0; } static void rebuild_pollfds(struct pa_mainloop *m) { diff --git a/polyp/module.c b/polyp/module.c index 1deb7cde8..eb8a8acd6 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -62,10 +62,10 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char if (!(m->dl = lt_dlopenext(name))) goto fail; - if (!(m->init = lt_dlsym(m->dl, "pa_module_init"))) + if (!(m->init = (int (*)(struct pa_core *c, struct pa_module*m)) lt_dlsym(m->dl, "pa_module_init"))) goto fail; - if (!(m->done = lt_dlsym(m->dl, "pa_module_done"))) + if (!(m->done = (void (*)(struct pa_core *c, struct pa_module*m)) lt_dlsym(m->dl, "pa_module_done"))) goto fail; m->userdata = NULL; diff --git a/polyp/native-common.h b/polyp/native-common.h index d826837ae..5250532e0 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -46,15 +46,12 @@ enum { PA_COMMAND_RECORD_STREAM_KILLED, PA_COMMAND_STAT, PA_COMMAND_GET_PLAYBACK_LATENCY, - PA_COMMAND_CREATE_UPLOAD_STREAM, PA_COMMAND_DELETE_UPLOAD_STREAM, PA_COMMAND_FINISH_UPLOAD_STREAM, PA_COMMAND_PLAY_SAMPLE, PA_COMMAND_REMOVE_SAMPLE, - PA_COMMAND_GET_SERVER_INFO, - PA_COMMAND_GET_SINK_INFO, PA_COMMAND_GET_SINK_INFO_LIST, PA_COMMAND_GET_SOURCE_INFO, @@ -78,6 +75,7 @@ enum { PA_COMMAND_CORK_PLAYBACK_STREAM, PA_COMMAND_FLUSH_PLAYBACK_STREAM, + PA_COMMAND_TRIGGER_PLAYBACK_STREAM, PA_COMMAND_MAX }; diff --git a/polyp/pacat.c b/polyp/pacat.c index 198776d35..9efa552a8 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -277,16 +277,16 @@ static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_even } /* Show the current playback latency */ -static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, void *userdata) { +static void stream_get_latency_callback(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) { assert(s); - if (latency == (uint32_t) -1) { + if (!i) { fprintf(stderr, "Failed to get latency: %s\n", strerror(errno)); quit(1); return; } - fprintf(stderr, "Current latency is %u usecs.\n", latency); + fprintf(stderr, "Current latency is %u usecs.\n", i->buffer_usec+i->sink_usec); } /* Someone requested that the latency is shown */ diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index c46d4f770..22f5da09f 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -60,6 +60,17 @@ static const char *command_names[PA_COMMAND_MAX] = { [PA_COMMAND_FINISH_UPLOAD_STREAM] = "FINISH_UPLOAD_STREAM", [PA_COMMAND_PLAY_SAMPLE] = "PLAY_SAMPLE", [PA_COMMAND_REMOVE_SAMPLE] = "REMOVE_SAMPLE", + [PA_COMMAND_GET_SERVER_INFO] = "GET_SERVER_INFO", + [PA_COMMAND_GET_SINK_INFO] = "GET_SET_INFO", + [PA_COMMAND_GET_SINK_INPUT_INFO] = "GET_SINK_INPUT_INFO", + [PA_COMMAND_SUBSCRIBE] = "SUBSCRIBE", + [PA_COMMAND_SUBSCRIBE_EVENT] = "SUBSCRIBE_EVENT", + [PA_COMMAND_SET_SINK_VOLUME] = "SET_SINK_VOLUME", + [PA_COMMAND_SET_SINK_INPUT_VOLUME] = "SET_SINK_INPUT_VOLUME", + [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = "TRIGGER_PLAYBACK_STREAM", + [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = "FLUSH_PLAYBACK_STREAM", + [PA_COMMAND_CORK_PLAYBACK_STREAM] = "CORK_PLAYBACK_STREAM", + }; #endif diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index b94a05242..486f0cf65 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -25,6 +25,8 @@ #include #include +#include +#include #include "play-memchunk.h" #include "sink-input.h" @@ -64,7 +66,7 @@ static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk*ch assert(i && length && i->userdata); c = i->userdata; - assert(chunk == c); + assert(!memcmp(chunk, c, sizeof(chunk))); assert(length <= c->length); c->length -= length; diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index c63e14795..7c31634dd 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -30,10 +30,10 @@ load module-pipe-sink #autoload_sink_add output module-oss device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input -autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#autoload_sink_add output module-alsa-sink sink_name=output -#autoload_source_add input module-alsa-source source_name=input +#autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +autoload_sink_add output module-alsa-sink sink_name=output +autoload_source_add input module-alsa-source source_name=input # Load several protocols load module-esound-protocol-tcp diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 9acb2d703..7542dd9bb 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -463,7 +463,10 @@ static void set_dispatch_callbacks(struct pa_operation *o) { struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct pa_context*c, void *userdata), void *userdata) { struct pa_operation *o; - assert(c && c->ref >= 1 && c->state == PA_CONTEXT_READY); + assert(c && c->ref >= 1); + + if (c->state != PA_CONTEXT_READY) + return NULL; if (!pa_context_is_pending(c)) return NULL; diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 6420e87e4..02f5e526f 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -24,6 +24,7 @@ #include #include "cdecl.h" +#include "sample.h" /** \file * Global definitions */ @@ -128,6 +129,14 @@ enum pa_subscription_event_type { /** Return one if an event type t matches an event mask bitfield */ #define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) +/** A structure for latency info. See pa_stream_get_latency(). */ +struct pa_latency_info { + pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play */ + pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. The total latency is buffer_usec+sink_usec. */ + int playing; /**< Non-zero when the stream is currently playing */ + int queue_length; /**< Queue size in bytes. */ +}; + PA_C_DECL_END #endif diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index fd6cd38fb..8c5d3166a 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -34,9 +34,9 @@ #include "llist.h" #include "native-common.h" -#define DEFAULT_MAXLENGTH 204800 -#define DEFAULT_TLENGTH 10240 -#define DEFAULT_PREBUF 4096 +#define DEFAULT_TLENGTH (10240*2) +#define DEFAULT_MAXLENGTH (DEFAULT_TLENGTH*2) +#define DEFAULT_PREBUF DEFAULT_TLENGTH #define DEFAULT_MINREQ 1024 #define DEFAULT_FRAGSIZE 1024 diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 0cc525496..0c3051843 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -42,7 +42,7 @@ struct pa_sink_info { pa_volume_t volume; uint32_t monitor_source; const char *monitor_source_name; - uint32_t latency; + pa_usec_t latency; }; struct pa_operation* pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); @@ -101,7 +101,7 @@ struct pa_sink_input_info { uint32_t sink; struct pa_sample_spec sample_spec; pa_volume_t volume; - uint32_t latency; + pa_usec_t latency; }; struct pa_operation* pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index c0ec9e7eb..f45e1e7c0 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -168,6 +168,8 @@ void pa_command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, s->requested_bytes += bytes; + fprintf(stderr, "total req: %u (%u)\n", s->requested_bytes, bytes); + if (s->requested_bytes && s->write_callback) s->write_callback(s, s->requested_bytes, s->write_userdata); @@ -320,22 +322,26 @@ struct pa_operation * pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_operation *o = userdata; - uint32_t latency; + struct pa_latency_info i, *p = NULL; assert(pd && o && o->stream && o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - latency = (uint32_t) -1; - } else if (pa_tagstruct_getu32(t, &latency) < 0 || !pa_tagstruct_eof(t)) { + } else if (pa_tagstruct_getu32(t, &i.buffer_usec) < 0 || + pa_tagstruct_getu32(t, &i.sink_usec) < 0 || + pa_tagstruct_getu32(t, &i.playing) < 0 || + pa_tagstruct_getu32(t, &i.queue_length) < 0 || + !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; - } + } else + p = &i; if (o->callback) { - void (*cb)(struct pa_stream *s, uint32_t latency, void *userdata) = o->callback; - cb(o->stream, latency, o->userdata); + void (*cb)(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) = o->callback; + cb(o->stream, p, o->userdata); } finish: @@ -343,7 +349,7 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { +struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struct pa_stream *p, const struct pa_latency_info*i, void *userdata), void *userdata) { uint32_t tag; struct pa_operation *o; struct pa_tagstruct *t; @@ -476,24 +482,31 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru return pa_operation_ref(o); } -struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { - struct pa_operation *o; +struct pa_operation* pa_stream_send_simple_command(struct pa_stream *s, uint32_t command, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { struct pa_tagstruct *t; + struct pa_operation *o; uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); - + o = pa_operation_new(s->context, s); - assert(o); o->callback = cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_FLUSH_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, command); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); - return pa_operation_ref(o); + return pa_operation_ref(o); +} + + +struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { + return pa_stream_send_simple_command(s, PA_COMMAND_FLUSH_PLAYBACK_STREAM, cb, userdata); +} + +struct pa_operation* pa_stream_trigger(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { + return pa_stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata); } diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index a0cbe521c..d74c3cb21 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -102,7 +102,7 @@ size_t pa_stream_writable_size(struct pa_stream *p); struct pa_operation* pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); /** Get the playback latency of a stream */ -struct pa_operation* pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); +struct pa_operation* pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, const struct pa_latency_info *i, void *userdata), void *userdata); /** Set the callback function that is called whenever the state of the stream changes */ void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); @@ -121,6 +121,11 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru * function. \since 0.3 */ struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); +/** Request immediate start of playback on this stream. This disables + * prebuffering as specified in the pa_buffer_attr structure. \since + * 0.3 */ +struct pa_operation* pa_stream_trigger(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); + PA_C_DECL_END #endif diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 8b39482ca..7b7dfef63 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -136,7 +136,7 @@ static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, u static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_flush_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -179,7 +179,8 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SET_SINK_VOLUME] = { command_set_volume }, [PA_COMMAND_SET_SINK_INPUT_VOLUME] = { command_set_volume }, [PA_COMMAND_CORK_PLAYBACK_STREAM] = { command_cork_playback_stream }, - [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = { command_flush_playback_stream }, + [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, + [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, }; /* structure management */ @@ -438,6 +439,8 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk pa_pstream_send_simple_ack(s->connection->pstream, s->drain_tag); s->drain_request = 0; } + + /*fprintf(stderr, "after_drop: %u\n", pa_memblockq_get_length(s->memblockq));*/ } static void sink_input_kill_cb(struct pa_sink_input *i) { @@ -451,6 +454,8 @@ static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { assert(i && i->userdata); s = i->userdata; + /*fprintf(stderr, "get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/ + return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); } @@ -797,7 +802,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma struct connection *c = userdata; struct pa_tagstruct *reply; struct playback_stream *s; - uint32_t index, latency; + uint32_t index; assert(c && t); if (pa_tagstruct_getu32(t, &index) < 0 || @@ -816,12 +821,14 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma return; } - latency = pa_sink_input_get_latency(s->sink_input); reply = pa_tagstruct_new(NULL, 0); assert(reply); pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); pa_tagstruct_putu32(reply, tag); - pa_tagstruct_putu32(reply, latency); + pa_tagstruct_putu32(reply, pa_sink_input_get_latency(s->sink_input)); + pa_tagstruct_putu32(reply, pa_sink_get_latency(s->sink_input->sink)); + pa_tagstruct_putu32(reply, pa_memblockq_is_readable(s->memblockq)); + pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq)); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1325,7 +1332,7 @@ static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t comma pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_flush_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t index; struct playback_stream *s; @@ -1347,7 +1354,14 @@ static void command_flush_playback_stream(struct pa_pdispatch *pd, uint32_t comm return; } - pa_memblockq_flush(s->memblockq); + if (command == PA_COMMAND_TRIGGER_PLAYBACK_STREAM) + pa_memblockq_prebuf_disable(s->memblockq); + else { + assert(command == PA_COMMAND_FLUSH_PLAYBACK_STREAM); + pa_memblockq_flush(s->memblockq); + } + + pa_sink_notify(s->sink_input->sink); pa_pstream_send_simple_ack(c->pstream, tag); } @@ -1383,8 +1397,11 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui pa_memblockq_push_align(p->memblockq, chunk, delta); assert(p->sink_input); + /*fprintf(stderr, "after_recv: %u\n", pa_memblockq_get_length(p->memblockq));*/ + pa_sink_notify(p->sink_input->sink); /*fprintf(stderr, "Recieved %u bytes.\n", chunk->length);*/ + } else { struct upload_stream *u = (struct upload_stream*) stream; size_t l; diff --git a/polyp/pstream.c b/polyp/pstream.c index ad3dd0e07..81ee0b439 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -211,6 +211,8 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { struct item_info *i; assert(p && packet); + /*fprintf(stderr, "push-packet %p\n", packet);*/ + i = pa_xmalloc(sizeof(struct item_info)); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); @@ -258,6 +260,8 @@ static void prepare_next_write_item(struct pa_pstream *p) { p->write.index = 0; if (p->write.current->type == PA_PSTREAM_ITEM_PACKET) { + /*fprintf(stderr, "pop-packet %p\n", p->write.current->packet);*/ + assert(p->write.current->packet); p->write.data = p->write.current->packet->data; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length); diff --git a/polyp/sample.c b/polyp/sample.c index f4a80861c..edfe19594 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -61,7 +61,7 @@ size_t pa_bytes_per_second(const struct pa_sample_spec *spec) { uint32_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec) { assert(spec); - return (uint32_t) (((double) length /pa_frame_size(spec))/spec->rate*1000000); + return (uint32_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate); } int pa_sample_spec_valid(const struct pa_sample_spec *spec) { diff --git a/polyp/sample.h b/polyp/sample.h index 459f8a302..28ae51eab 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -66,6 +66,9 @@ struct pa_sample_spec { uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */ }; +/** Type for usec specifications */ +typedef uint32_t pa_usec_t; + /** Return the amount of bytes playback of a second of audio with the speicified sample type takes */ size_t pa_bytes_per_second(const struct pa_sample_spec *spec); @@ -73,7 +76,7 @@ size_t pa_bytes_per_second(const struct pa_sample_spec *spec); size_t pa_frame_size(const struct pa_sample_spec *spec); /** Calculate the time the specified bytes take to play with the specified sample type */ -uint32_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec); +pa_usec_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec); /** Return non-zero when the sample type specification is valid */ int pa_sample_spec_valid(const struct pa_sample_spec *spec); diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 5009033f2..9238fac0f 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -105,23 +105,19 @@ void pa_sink_input_kill(struct pa_sink_input*i) { i->kill(i); } -uint32_t pa_sink_input_get_latency(struct pa_sink_input *i) { - uint32_t l = 0; - +pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i) { assert(i); + if (i->get_latency) - l += i->get_latency(i); + return i->get_latency(i); - assert(i->sink); - l += pa_sink_get_latency(i->sink); - - return l; + return 0; } int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { assert(i && chunk && i->peek && i->drop); - if (i->corked == 0) + if (i->corked) return -1; if (!i->resampler) @@ -139,11 +135,11 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); - i->drop(i, &tchunk, l); - if (tchunk.length > l) tchunk.length = l; + i->drop(i, &tchunk, tchunk.length); + pa_resampler_run(i->resampler, &tchunk, &i->resampled_chunk); pa_memblock_unref(tchunk.memblock); } diff --git a/polyp/sink-input.h b/polyp/sink-input.h index b06445409..df6ead6be 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -61,7 +61,7 @@ void pa_sink_input_free(struct pa_sink_input* i); * request destruction of it */ void pa_sink_input_kill(struct pa_sink_input *i); -uint32_t pa_sink_input_get_latency(struct pa_sink_input *i); +pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i); int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk); void pa_sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); diff --git a/polyp/sink.c b/polyp/sink.c index 43fd351cf..b520dd8aa 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -142,7 +142,7 @@ static unsigned fill_mix_info(struct pa_sink *s, struct pa_mix_info *info, unsig static void inputs_drop(struct pa_sink *s, struct pa_mix_info *info, unsigned maxinfo, size_t length) { assert(s && info); - + for (; maxinfo > 0; maxinfo--, info++) { struct pa_sink_input *i = info->userdata; assert(i && info->chunk.memblock); @@ -267,7 +267,7 @@ void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target) { } } -uint32_t pa_sink_get_latency(struct pa_sink *s) { +pa_usec_t pa_sink_get_latency(struct pa_sink *s) { assert(s); if (!s->get_latency) diff --git a/polyp/sink.h b/polyp/sink.h index 8248d00cc..9c91692e1 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -56,7 +56,7 @@ int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result); int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target); void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target); -uint32_t pa_sink_get_latency(struct pa_sink *s); +pa_usec_t pa_sink_get_latency(struct pa_sink *s); void pa_sink_notify(struct pa_sink*s); From 761a895d1f8ac3c20710a884560bc77f3789d3af Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 27 Aug 2004 16:24:22 +0000 Subject: [PATCH 0152/1514] minor cleanups git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@155 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- doc/todo | 6 ++++++ polyp/polyplib-def.h | 10 ++++++++-- polyp/polyplib-introspect.c | 3 ++- polyp/polyplib-introspect.h | 18 ++++++++++-------- polyp/polyplib-stream.c | 2 -- polyp/protocol-native.c | 2 ++ polyp/tagstruct.c | 2 +- 8 files changed, 30 insertions(+), 15 deletions(-) diff --git a/configure.ac b/configure.ac index 7e0b3c213..7aa6c5d48 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.2],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.3],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) diff --git a/doc/todo b/doc/todo index a317b4f33..c225dd53e 100644 --- a/doc/todo +++ b/doc/todo @@ -8,7 +8,13 @@ - native library/protocol: module load/unload kill client/... + autoload management - more complete pactl +- daemon autostart +- cleanup tagstruct (add s32, pa_volume_t, pa_usec_t) +- xmlrpc +- remove all gcc warnings +- complete doxygen coverage ** later *** - slp/rendezvous diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 02f5e526f..6c3cd825c 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -129,10 +129,16 @@ enum pa_subscription_event_type { /** Return one if an event type t matches an event mask bitfield */ #define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) -/** A structure for latency info. See pa_stream_get_latency(). */ +/** A structure for latency info. See pa_stream_get_latency(). The + * total latency a sample that is written with pa_stream_write() takes + * to be played is buffer_usec+sink_usec. The buffer to which + * buffer_usec relates may be manipulated freely (with + * pa_stream_write()'s delta argument, pa_stream_flush() and friends), + * the playback buffer sink_usec relates to is a FIFO which cannot be + * flushed or manipulated in any way. */ struct pa_latency_info { pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play */ - pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. The total latency is buffer_usec+sink_usec. */ + pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. */ int playing; /**< Non-zero when the stream is currently playing */ int queue_length; /**< Queue size in bytes. */ }; diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 63422383f..e650fb9fe 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -400,7 +400,8 @@ static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32 pa_tagstruct_getu32(t, &i.sink) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { + pa_tagstruct_getu32(t, &i.buffer_usec) < 0 || + pa_tagstruct_getu32(t, &i.sink_usec) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 0c3051843..fc7aa1233 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -93,15 +93,17 @@ struct pa_client_info { struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); struct pa_operation* pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +/** Stores information about sink inputs */ struct pa_sink_input_info { - uint32_t index; - const char *name; - uint32_t owner_module; - uint32_t client; - uint32_t sink; - struct pa_sample_spec sample_spec; - pa_volume_t volume; - pa_usec_t latency; + uint32_t index; /**< Name of this index */ + const char *name; /**< Name of the sink input */ + uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */ + uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */ + uint32_t sink; /**< Index of the connected sink */ + struct pa_sample_spec sample_spec; /**< The sample specification of the sink input */ + pa_volume_t volume; /**< The volume of this sink input */ + pa_usec_t buffer_usec; /**< Latency due to buffering in sink input, see pa_latency_info for details */ + pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */ }; struct pa_operation* pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index f45e1e7c0..220e4a144 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -168,8 +168,6 @@ void pa_command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, s->requested_bytes += bytes; - fprintf(stderr, "total req: %u (%u)\n", s->requested_bytes, bytes); - if (s->requested_bytes && s->write_callback) s->write_callback(s, s->requested_bytes, s->write_userdata); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 7b7dfef63..213568a05 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -1022,6 +1022,7 @@ static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_inp pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_putu32(t, s->volume); pa_tagstruct_putu32(t, pa_sink_input_get_latency(s)); + pa_tagstruct_putu32(t, pa_sink_get_latency(s->sink)); } static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) { @@ -1363,6 +1364,7 @@ static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, ui pa_sink_notify(s->sink_input->sink); pa_pstream_send_simple_ack(c->pstream, tag); + request_bytes(s); } /*** pstream callbacks ***/ diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 9578a9eb6..742f6b9cb 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -95,7 +95,7 @@ void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s) { l = strlen(s)+2; extend(t, l); t->data[t->length] = TAG_STRING; - strcpy(t->data+t->length+1, s); + strcpy((char*) (t->data+t->length+1), s); t->length += l; } From 8cb1cabfc9a2ffb689f7f4998b81c2c7e18c6f73 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 27 Aug 2004 17:03:38 +0000 Subject: [PATCH 0153/1514] document every polyplib function git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@156 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 12 +++- doc/todo | 4 +- polyp/polyplib-introspect.h | 124 +++++++++++++++++++++++++----------- 3 files changed, 99 insertions(+), 41 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index 8972fe1b7..91edbd64d 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -42,6 +42,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    News

    +
    Fri Aug 27 2004:

    Version 0.3 released; +changes include: support for both glib 2.0 and glib 1.2, future cancellation, API updates, many fixes.

    +
    Fri Aug 20 2004:

    Version 0.2 released; changes include: added sample cache, introspection API, client API @@ -84,12 +88,16 @@ attempt to write a sound server asd.

    A GTK GUI manager application for polypaudio is the Polypaudio Manager.

    +href="http://0pointer.de/lennart/projects/paman/">Polypaudio Manager. There are output plugins for XMMS and libao.

    Status

    Version @PACKAGE_VERSION@ is quite usable. It matches and supersedes ESOUND's feature set in nearly all areas.

    - + +

    Warning: polypaudio's client API and protocol are not stable +yet. The client interface is still a moving target and changes from +release to release. The client API's library version number is currently fixed to 0.0.0.

    +

    Documentation

    There is some preliminary documentation available: Date: Fri, 27 Aug 2004 18:38:23 +0000 Subject: [PATCH 0154/1514] relicense client library to LGPL git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@157 fefdeb5f-60dc-0310-8127-8f9354f1896f --- GPL | 340 ++++++++++++++++++++++++++++++ LGPL | 510 +++++++++++++++++++++++++++++++++++++++++++++ LICENSE | 342 +----------------------------- doc/README.html.in | 2 +- 4 files changed, 854 insertions(+), 340 deletions(-) create mode 100644 GPL create mode 100644 LGPL diff --git a/GPL b/GPL new file mode 100644 index 000000000..d60c31a97 --- /dev/null +++ b/GPL @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/LGPL b/LGPL new file mode 100644 index 000000000..b124cf581 --- /dev/null +++ b/LGPL @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/LICENSE b/LICENSE index d60c31a97..b042db509 100644 --- a/LICENSE +++ b/LICENSE @@ -1,340 +1,4 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 +The client libraries are licensed under LGPL +The daemon itself and all plugings are licensed under GPL - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. +Lennart Poettering, 2004 diff --git a/doc/README.html.in b/doc/README.html.in index 91edbd64d..fea38ce39 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -44,7 +44,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    Fri Aug 27 2004:

    Version 0.3 released; -changes include: support for both glib 2.0 and glib 1.2, future cancellation, API updates, many fixes.

    +changes include: support for both glib 2.0 and glib 1.2, future cancellation, API updates, many fixes; relicense client library to LGPL.

    Fri Aug 20 2004:

    Version 0.2 released; From 4efa9d1cbec96bdc63585dc040ef73c4702e22bb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 27 Aug 2004 18:38:52 +0000 Subject: [PATCH 0155/1514] add LGPL/GPL to dist package git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@158 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 3eeef9561..720059ed8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,7 +17,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in +EXTRA_DIST = bootstrap.sh README LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in SUBDIRS=polyp doc MAINTAINERCLEANFILES=README From b0143403bf8e510f380888c7f6065e156436f684 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 27 Aug 2004 18:41:40 +0000 Subject: [PATCH 0156/1514] readme update (licensing) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@159 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/README.html.in b/doc/README.html.in index fea38ce39..f34546328 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -40,6 +40,8 @@ General Public License for more details.

    along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    +

    Exception: The client libraries are licensed under LGPL, the Lesser GNU General Plublic License.

    +

    News

    Fri Aug 27 2004:

    Date: Fri, 27 Aug 2004 18:52:50 +0000 Subject: [PATCH 0157/1514] minor fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@160 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- doc/todo | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 720059ed8..0c78c1546 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,7 +34,7 @@ README: homepage: all dist doxygen test -d $$HOME/homepage/private mkdir -p $$HOME/homepage/private/projects/polypaudio $$HOME/homepage/private/projects/polypaudio/doxygen - cp *.tar.gz $$HOME/homepage/private/projects/polypaudio + cp polypaudio-$(PACKAGE_VERSION).tar.gz $$HOME/homepage/private/projects/polypaudio cp doc/README.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/polypaudio cp -a doxygen/html/* $$HOME/homepage/private/projects/polypaudio/doxygen cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html diff --git a/doc/todo b/doc/todo index aa3022982..e7b916827 100644 --- a/doc/todo +++ b/doc/todo @@ -1,7 +1,6 @@ *** $Id$ *** -*** 0.3 *** -- pacat drain fix +*** 0.4 *** - make mcalign merge chunks - use ref counting in more objects - unix socket directories include user name From 8c887ab8020ca45ad1781bff928908562bdecada Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 27 Aug 2004 18:55:24 +0000 Subject: [PATCH 0158/1514] fix homepage script git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@161 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 0c78c1546..e27204f6b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,7 +34,7 @@ README: homepage: all dist doxygen test -d $$HOME/homepage/private mkdir -p $$HOME/homepage/private/projects/polypaudio $$HOME/homepage/private/projects/polypaudio/doxygen - cp polypaudio-$(PACKAGE_VERSION).tar.gz $$HOME/homepage/private/projects/polypaudio + cp polypaudio-@PACKAGE_VERSION@.tar.gz $$HOME/homepage/private/projects/polypaudio cp doc/README.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/polypaudio cp -a doxygen/html/* $$HOME/homepage/private/projects/polypaudio/doxygen cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html From 9618aea5df5bf2c5069575f28a935c2039fc55e0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 27 Aug 2004 19:06:29 +0000 Subject: [PATCH 0159/1514] fix module path git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@162 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 8acbc012c..31bfbdeed 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -18,7 +18,7 @@ # USA. AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) -#AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" +AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" AM_LDADD=$(PTHREAD_LIBS) AM_LIBADD=$(PTHREAD_LIBS) From 34fe8bd893ed9c7531bc4898b934ef9d4cdf3e68 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 00:23:51 +0000 Subject: [PATCH 0160/1514] add support for SCHED_FIFO git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@163 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + polyp/Makefile.am | 6 +++++- polyp/cmdline.c | 21 ++++++++++++++++---- polyp/cmdline.h | 2 +- polyp/iochannel.c | 8 ++++++++ polyp/main.c | 20 +++++++++++++++++++ polyp/mainloop.c | 20 +++++++++++++++---- polyp/memblockq.c | 7 ++++++- polyp/memblockq.h | 3 +++ polyp/module-alsa-sink.c | 2 +- polyp/module-alsa-source.c | 2 +- polyp/module-oss.c | 25 ++++++++++++------------ polyp/module-pipe-sink.c | 2 +- polyp/polypaudio.pa | 19 +++++++++--------- polyp/polyplib-context.c | 4 ++-- polyp/polyplib-internal.h | 6 +++--- polyp/protocol-esound.c | 2 ++ polyp/protocol-native.c | 8 ++++++-- polyp/pstream.c | 3 +++ polyp/sink.c | 15 ++++++++++++-- polyp/sink.h | 3 ++- polyp/socket-util.c | 8 ++++++-- polyp/util.c | 40 ++++++++++++++++++++++++++++++++++++-- polyp/util.h | 3 +++ 24 files changed, 181 insertions(+), 49 deletions(-) diff --git a/doc/todo b/doc/todo index e7b916827..f8ebd9bbe 100644 --- a/doc/todo +++ b/doc/todo @@ -13,6 +13,7 @@ - cleanup tagstruct (add s32, pa_volume_t, pa_usec_t) - xmlrpc - remove all gcc warnings +- esd compatible startup script or personality ** later *** - slp/rendezvous diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 31bfbdeed..73e80621e 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -18,7 +18,7 @@ # USA. AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) -AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" +#AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" AM_LDADD=$(PTHREAD_LIBS) AM_LIBADD=$(PTHREAD_LIBS) @@ -437,3 +437,7 @@ libpolypcore_la_SOURCES = idxset.c idxset.h \ endif + +suid: polypaudio + chown root:root $< + chmod u+s $< diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 8acdde6fb..9935e7b66 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -43,13 +43,16 @@ void pa_cmdline_help(const char *argv0) { e = argv0; printf("%s [options]\n" + " -r Try to set high process priority (only available as root)\n" + " -R Don't drop root if SETUID root\n" " -L MODULE Load the specified plugin module with the specified argument\n" " -F FILE Run the specified script\n" " -C Open a command line on the running TTY\n" " -D Daemonize after loading the modules\n" " -f Dont quit when the startup fails\n" " -v Verbose startup\n" - " -h Show this help\n", e); + " -h Show this help\n" + " -V Show version\n", e); } struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { @@ -59,13 +62,13 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { assert(argc && argv); cmdline = pa_xmalloc(sizeof(struct pa_cmdline)); - cmdline->daemonize = cmdline->help = cmdline->verbose = 0; + cmdline->daemonize = cmdline->help = cmdline->verbose = cmdline->high_priority = cmdline->stay_root = cmdline->version = 0; cmdline->fail = 1; buf = pa_strbuf_new(); assert(buf); - while ((c = getopt(argc, argv, "L:F:CDhfv")) != -1) { + while ((c = getopt(argc, argv, "L:F:CDhfvrRV")) != -1) { switch (c) { case 'L': pa_strbuf_printf(buf, "load %s\n", optarg); @@ -86,8 +89,18 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { cmdline->fail = 0; break; case 'v': - cmdline->verbose = 0; + cmdline->verbose = 1; break; + case 'r': + cmdline->high_priority = 1; + break; + case 'R': + cmdline->stay_root = 1; + break; + case 'V': + cmdline->version = 1; + break; + default: goto fail; } diff --git a/polyp/cmdline.h b/polyp/cmdline.h index 95ce91dec..6a7f4dd7d 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -24,7 +24,7 @@ struct pa_cmdline { - int daemonize, help, fail, verbose; + int daemonize, help, fail, verbose, high_priority, stay_root, version; char *cli_commands; }; diff --git a/polyp/iochannel.c b/polyp/iochannel.c index 813347d42..1aa70b935 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -173,8 +173,16 @@ int pa_iochannel_is_hungup(struct pa_iochannel*io) { ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) { ssize_t r; + assert(io); + assert(data); + assert(l); + assert(io->ofd >= 0); + + assert(io && data && l && io->ofd >= 0); + + if ((r = write(io->ofd, data, l)) >= 0) { io->writable = 0; enable_mainloop_sources(io); diff --git a/polyp/main.c b/polyp/main.c index de02a110f..526bf7449 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -46,6 +46,14 @@ static struct pa_mainloop *mainloop; +static void drop_root(void) { + if (getuid() != 0 && geteuid() == 0) { + fprintf(stderr, __FILE__": started SUID root, dropping root rights.\n"); + setuid(getuid()); + seteuid(getuid()); + } +} + static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { m->quit(m, 1); fprintf(stderr, __FILE__": got signal.\n"); @@ -84,6 +92,18 @@ int main(int argc, char *argv[]) { goto finish; } + if (cmdline->version) { + printf(PACKAGE_NAME" "PACKAGE_VERSION"\n"); + retval = 0; + goto finish; + } + + if (cmdline->high_priority) + pa_raise_priority(); + + if (!cmdline->stay_root) + drop_root(); + if (cmdline->daemonize) { pid_t child; diff --git a/polyp/mainloop.c b/polyp/mainloop.c index 20d14e517..83f0b1e82 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -332,6 +332,7 @@ void pa_mainloop_free(struct pa_mainloop* m) { static void scan_dead(struct pa_mainloop *m) { int all = 0; assert(m); + if (m->io_events_scan_dead) pa_idxset_foreach(m->io_events, io_foreach, &all); if (m->time_events_scan_dead) @@ -402,7 +403,7 @@ static void dispatch_defer(struct pa_mainloop *m) { for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) { if (e->dead || !e->enabled) continue; - + assert(e->callback); e->callback(&m->api, e, e->userdata); } @@ -413,18 +414,23 @@ static int calc_next_timeout(struct pa_mainloop *m) { struct pa_time_event *e; struct timeval now; int t = -1; + int got_time = 0; if (pa_idxset_isempty(m->time_events)) return -1; - gettimeofday(&now, NULL); - for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { int tmp; if (e->dead || !e->enabled) continue; + /* Let's save a system call */ + if (!got_time) { + gettimeofday(&now, NULL); + got_time = 1; + } + if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) return 0; @@ -448,17 +454,23 @@ static void dispatch_timeout(struct pa_mainloop *m) { uint32_t index; struct pa_time_event *e; struct timeval now; + int got_time = 0; assert(m); if (pa_idxset_isempty(m->time_events)) return; - gettimeofday(&now, NULL); for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { if (e->dead || !e->enabled) continue; + /* Let's save a system call */ + if (!got_time) { + gettimeofday(&now, NULL); + got_time = 1; + } + if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) { assert(e->callback); diff --git a/polyp/memblockq.c b/polyp/memblockq.c index b6dcca3f5..7feb4685f 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -56,7 +56,7 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b bq->current_length = 0; - fprintf(stderr, "memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq); + /*fprintf(stderr, "memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq);*/ bq->base = base; @@ -324,3 +324,8 @@ void pa_memblockq_flush(struct pa_memblockq *bq) { bq->n_blocks = 0; bq->current_length = 0; } + +uint32_t pa_memblockq_get_tlength(struct pa_memblockq *bq) { + assert(bq); + return bq->tlength; +} diff --git a/polyp/memblockq.h b/polyp/memblockq.h index 277beb55f..16b51d7a8 100644 --- a/polyp/memblockq.h +++ b/polyp/memblockq.h @@ -89,4 +89,7 @@ void pa_memblockq_seek(struct pa_memblockq *bq, size_t delta); /* Flush the queue */ void pa_memblockq_flush(struct pa_memblockq *bq); +/* Get Target length */ +uint32_t pa_memblockq_get_tlength(struct pa_memblockq *bq); + #endif diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 06b07f337..0c9d77b80 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -99,7 +99,7 @@ static void do_write(struct userdata *u) { assert(memchunk->memblock && memchunk->memblock->data && memchunk->length && memchunk->memblock->length && (memchunk->length % u->frame_size) == 0); - if ((frames = snd_pcm_writei(u->pcm_handle, memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) { + if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) { if (frames == -EAGAIN) return; diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 9dc623d4d..13df9f960 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -95,7 +95,7 @@ static void do_read(struct userdata *u) { assert(u->memchunk.memblock && u->memchunk.memblock->data && u->memchunk.length && u->memchunk.memblock->length && (u->memchunk.length % u->frame_size) == 0); - if ((frames = snd_pcm_readi(u->pcm_handle, u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) { + if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) { if (frames == -EAGAIN) return; diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 3fa3d1e35..403716fd8 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -93,21 +93,22 @@ static void do_write(struct userdata *u) { return; update_usage(u); - - if (!u->memchunk.length) { - if (pa_sink_render(u->sink, u->out_fragment_size, &u->memchunk) < 0) - memchunk = &u->silence; - else - memchunk = &u->memchunk; - } - assert(memchunk->memblock && memchunk->length); + memchunk = &u->memchunk; - if ((r = pa_iochannel_write(u->io, memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { + if (!memchunk->length) + if (pa_sink_render(u->sink, u->out_fragment_size, memchunk) < 0) + memchunk = &u->silence; + + assert(memchunk->memblock); + assert(memchunk->memblock->data); + assert(memchunk->length); + + if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { fprintf(stderr, "write() failed: %s\n", strerror(errno)); return; } - + if (memchunk == &u->silence) assert(r % u->sample_size == 0); else { @@ -215,8 +216,8 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); - if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) - goto fail; + if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) + goto fail; if (pa_oss_auto_format(fd, &ss) < 0) goto fail; diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index 22d9f6768..32a2c722b 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -82,7 +82,7 @@ static void do_write(struct userdata *u) { assert(u->memchunk.memblock && u->memchunk.length); - if ((r = pa_iochannel_write(u->io, u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { + if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { fprintf(stderr, "write() failed: %s\n", strerror(errno)); return; } diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 7c31634dd..b683e627b 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -1,4 +1,4 @@ -#!./polypaudio -F +#!./polypaudio -rF # # This file is part of polypaudio. @@ -24,22 +24,23 @@ #load module-alsa-source device=plughw:1,0 #load module-oss device="/dev/dsp" sink_name=output source_name=input #load module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -load module-pipe-sink +#load module-pipe-sink # Load audio drivers automatically on access -#autoload_sink_add output module-oss device="/dev/dsp" sink_name=output source_name=input -#autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input +autoload_sink_add output module-oss device="/dev/adsp" sink_name=output source_name=input +autoload_source_add input module-oss device="/dev/adsp" sink_name=output source_name=input #autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -autoload_sink_add output module-alsa-sink sink_name=output -autoload_source_add input module-alsa-source source_name=input +#autoload_sink_add output module-alsa-sink sink_name=output +#autoload_source_add input module-alsa-source source_name=input # Load several protocols -load module-esound-protocol-tcp -load module-simple-protocol-tcp +#load module-esound-protocol-tcp +#load module-simple-protocol-tcp load module-native-protocol-unix -load module-cli-protocol-unix +#load module-cli-protocol-unix +load module-esound-protocol-unix # Load the CLI module load module-cli diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 7542dd9bb..2ead40041 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -202,7 +202,7 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui if ((s = pa_dynarray_get(c->record_streams, channel))) { if (s->read_callback) - s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); + s->read_callback(s, (uint8_t*) chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); } pa_context_unref(c); @@ -451,7 +451,7 @@ static void set_dispatch_callbacks(struct pa_operation *o) { else { if (o->callback) { void (*cb)(struct pa_context *c, void *userdata); - cb = (void*) o->callback; + cb = (void (*)(struct pa_context*, void*)) o->callback; cb(o->context, o->userdata); } diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 8c5d3166a..8f1a49426 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -34,10 +34,10 @@ #include "llist.h" #include "native-common.h" -#define DEFAULT_TLENGTH (10240*2) -#define DEFAULT_MAXLENGTH (DEFAULT_TLENGTH*2) +#define DEFAULT_TLENGTH (10240*4) +#define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) #define DEFAULT_PREBUF DEFAULT_TLENGTH -#define DEFAULT_MINREQ 1024 +#define DEFAULT_MINREQ 512 #define DEFAULT_FRAGSIZE 1024 #define DEFAULT_TIMEOUT (5*60) diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 5102540b2..2059dab83 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -903,6 +903,8 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk /* do something */ assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 1); + + assert(pa_memblockq_get_length(c->input_memblockq) > 2048); } static void sink_input_kill_cb(struct pa_sink_input *i) { diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 213568a05..9c6996be6 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -421,6 +421,8 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk assert(i && i->userdata && chunk); s = i->userdata; + /*fprintf(stderr, "%3.0f \r", (double) pa_memblockq_get_length(s->memblockq)/pa_memblockq_get_tlength(s->memblockq)*100);*/ + if (pa_memblockq_peek(s->memblockq, chunk) < 0) return -1; @@ -1360,6 +1362,7 @@ static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, ui else { assert(command == PA_COMMAND_FLUSH_PLAYBACK_STREAM); pa_memblockq_flush(s->memblockq); + /*fprintf(stderr, "flush: %u\n", pa_memblockq_get_length(s->memblockq));*/ } pa_sink_notify(s->sink_input->sink); @@ -1427,7 +1430,8 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui l = chunk->length; if (l > 0) { - memcpy(u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length, chunk->memblock->data+chunk->index, l); + memcpy((uint8_t*) u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length, + (uint8_t*) chunk->memblock->data+chunk->index, l); u->memchunk.length += l; u->length -= l; } @@ -1439,7 +1443,7 @@ static void pstream_die_callback(struct pa_pstream *p, void *userdata) { assert(p && c); connection_free(c); - fprintf(stderr, "protocol-native: connection died.\n"); +/* fprintf(stderr, "protocol-native: connection died.\n");*/ } diff --git a/polyp/pstream.c b/polyp/pstream.c index 81ee0b439..02dba72d3 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -169,6 +169,9 @@ struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel p->memblock_stat = s; + pa_iochannel_socket_set_rcvbuf(io, 1024*8); + pa_iochannel_socket_set_sndbuf(io, 1024*8); + return p; } diff --git a/polyp/sink.c b/polyp/sink.c index b520dd8aa..104248a9b 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -220,7 +220,7 @@ int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) { if (l > info[0].chunk.length) l = info[0].chunk.length; - memcpy(target->memblock->data+target->index, info[0].chunk.memblock->data + info[0].chunk.index, l); + memcpy((uint8_t*) target->memblock->data+target->index, (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index, l); target->length = l; if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM) @@ -229,7 +229,7 @@ int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) { if (volume != PA_VOLUME_NORM) pa_volume_memchunk(target, &s->sample_spec, volume); } else - target->length = l = pa_mix(info, n, target->memblock->data+target->index, target->length, &s->sample_spec, s->volume); + target->length = l = pa_mix(info, n, (uint8_t*) target->memblock->data+target->index, target->length, &s->sample_spec, s->volume); assert(l); inputs_drop(s, info, n, l); @@ -267,6 +267,17 @@ void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target) { } } +void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *result) { + assert(s && length && result); + + /*** This needs optimization ***/ + + result->memblock = pa_memblock_new(result->length = length, s->core->memblock_stat); + result->index = 0; + + pa_sink_render_into_full(s, result); +} + pa_usec_t pa_sink_get_latency(struct pa_sink *s) { assert(s); diff --git a/polyp/sink.h b/polyp/sink.h index 9c91692e1..940d16184 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -53,9 +53,10 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co void pa_sink_free(struct pa_sink* s); int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result); +void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *result); int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target); void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target); - + pa_usec_t pa_sink_get_latency(struct pa_sink *s); void pa_sink_notify(struct pa_sink*s); diff --git a/polyp/socket-util.c b/polyp/socket-util.c index 904381b7e..f9d0febfa 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -121,8 +121,10 @@ int pa_socket_tcp_low_delay(int fd) { int pa_socket_set_rcvbuf(int fd, size_t l) { assert(fd >= 0); - if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) { + fprintf(stderr, "SO_RCVBUF: %s\n", strerror(errno)); return -1; + } return 0; } @@ -130,8 +132,10 @@ int pa_socket_set_rcvbuf(int fd, size_t l) { int pa_socket_set_sndbuf(int fd, size_t l) { assert(fd >= 0); - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) { + fprintf(stderr, "SO_SNDBUF: %s\n", strerror(errno)); return -1; + } return 0; } diff --git a/polyp/util.c b/polyp/util.c index 6c8febb62..0d930118b 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include "util.h" #include "xmalloc.h" @@ -83,7 +85,7 @@ ssize_t pa_loop_read(int fd, void*data, size_t size) { break; ret += r; - data += r; + data = (uint8_t*) data + r; size -= r; } @@ -104,7 +106,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) { break; ret += r; - data += r; + data = (uint8_t*) data + r; size -= r; } @@ -213,3 +215,37 @@ uint32_t pa_age(struct timeval *tv) { return r; } + +#define NICE_LEVEL (-15) + +void pa_raise_priority(void) { + if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) + fprintf(stderr, __FILE__": setpriority() failed: %s\n", strerror(errno)); + else + fprintf(stderr, __FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); + +#ifdef _POSIX_PRIORITY_SCHEDULING + { + struct sched_param sp; + sched_getparam(0, &sp); + sp.sched_priority = 1; + if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) + fprintf(stderr, __FILE__": sched_setscheduler() failed: %s\n", strerror(errno)); + else + fprintf(stderr, __FILE__": Successfully gained SCHED_FIFO scheduling.\n"); + } +#endif +} + +void pa_reset_priority(void) { +#ifdef _POSIX_PRIORITY_SCHEDULING + { + struct sched_param sp; + sched_getparam(0, &sp); + sp.sched_priority = 0; + sched_setscheduler(0, SCHED_OTHER, &sp); + } +#endif + + setpriority(PRIO_PROCESS, 0, 0); +} diff --git a/polyp/util.h b/polyp/util.h index 9dab45d24..89505cde2 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -41,4 +41,7 @@ char *pa_get_host_name(char *s, size_t l); uint32_t pa_age(struct timeval *tv); +void pa_raise_priority(void); +void pa_reset_priority(void); + #endif From 36550f4a66ae28e1b81b9b818c38cd0fcd1302a1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 00:46:56 +0000 Subject: [PATCH 0161/1514] remove most -W compiler warnings git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@164 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 8 +++----- polyp/memchunk.c | 6 +++--- polyp/module-oss-mmap.c | 4 ++-- polyp/pacat.c | 4 ++-- polyp/parec-simple.c | 2 +- polyp/polyplib-internal.h | 2 +- polyp/polyplib-simple.c | 6 +++--- polyp/protocol-esound.c | 30 +++++++++++++++--------------- polyp/protocol-simple.c | 4 ++-- polyp/pstream.c | 10 +++++----- polyp/resampler.c | 4 ++-- polyp/sample-util.c | 8 ++++---- polyp/socket-client.c | 3 ++- polyp/strbuf.c | 2 +- 14 files changed, 46 insertions(+), 47 deletions(-) diff --git a/doc/todo b/doc/todo index f8ebd9bbe..d3baff161 100644 --- a/doc/todo +++ b/doc/todo @@ -10,12 +10,13 @@ autoload management - more complete pactl - daemon autostart -- cleanup tagstruct (add s32, pa_volume_t, pa_usec_t) -- xmlrpc +- cleanup tagstruct and modargs (add s32, pa_volume_t, pa_usec_t) - remove all gcc warnings - esd compatible startup script or personality +- limit number of concurrent streams ** later *** +- xmlrpc/http - slp/rendezvous - modinfo - make alsa modules use mmap @@ -28,6 +29,3 @@ backends for: - gstreamer - portaudio - python - -modules: -- http? diff --git a/polyp/memchunk.c b/polyp/memchunk.c index 920189e28..87b9c1bd3 100644 --- a/polyp/memchunk.c +++ b/polyp/memchunk.c @@ -40,7 +40,7 @@ void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s n = pa_memblock_new(c->length, s); assert(n); - memcpy(n->data, c->memblock->data+c->index, c->length); + memcpy(n->data, (uint8_t*) c->memblock->data+c->index, c->length); pa_memblock_unref(c->memblock); c->memblock = n; c->index = 0; @@ -100,7 +100,7 @@ int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) { l = m->chunk.length; assert(m->buffer && l); - memcpy(m->buffer + m->buffer_fill, m->chunk.memblock->data + m->chunk.index, l); + memcpy((uint8_t*) m->buffer + m->buffer_fill, (uint8_t*) m->chunk.memblock->data + m->chunk.index, l); m->buffer_fill += l; m->chunk.index += l; m->chunk.length -= l; @@ -132,7 +132,7 @@ int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) { assert(!m->buffer); m->buffer = pa_xmalloc(m->base); m->chunk.length -= m->buffer_fill; - memcpy(m->buffer, m->chunk.memblock->data + m->chunk.index + m->chunk.length, m->buffer_fill); + memcpy(m->buffer, (uint8_t*) m->chunk.memblock->data + m->chunk.index + m->chunk.length, m->buffer_fill); } if (m->chunk.length) { diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 05e061783..5c3be1ad4 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -100,7 +100,7 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { if (u->out_memblocks[u->out_current]) pa_memblock_unref_fixed(u->out_memblocks[u->out_current]); - chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed(u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size, u->core->memblock_stat); + chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed((uint8_t*)u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size, u->core->memblock_stat); assert(chunk.memblock); chunk.length = chunk.memblock->length; chunk.index = 0; @@ -141,7 +141,7 @@ static void in_post_memblocks(struct userdata *u, unsigned n) { struct pa_memchunk chunk; if (!u->in_memblocks[u->in_current]) { - chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, u->core->memblock_stat); + chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed((uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, u->core->memblock_stat); chunk.length = chunk.memblock->length; chunk.index = 0; diff --git a/polyp/pacat.c b/polyp/pacat.c index 9efa552a8..b251cc35f 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -65,7 +65,7 @@ static void do_stream_write(size_t length) { if (l > buffer_length) l = buffer_length; - pa_stream_write(stream, buffer+buffer_index, l, NULL, 0); + pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0); buffer_length -= l; buffer_index += l; @@ -250,7 +250,7 @@ static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int assert(buffer_length); - if ((r = write(fd, buffer+buffer_index, buffer_length)) <= 0) { + if ((r = write(fd, (uint8_t*) buffer+buffer_index, buffer_length)) <= 0) { fprintf(stderr, "write() failed: %s\n", strerror(errno)); quit(1); diff --git a/polyp/parec-simple.c b/polyp/parec-simple.c index 74f0a0f7a..7e0931ae0 100644 --- a/polyp/parec-simple.c +++ b/polyp/parec-simple.c @@ -47,7 +47,7 @@ static ssize_t loop_write(int fd, const void*data, size_t size) { break; ret += r; - data += r; + data = (uint8_t*) data + r; size -= r; } diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 8f1a49426..813bb04e0 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -34,7 +34,7 @@ #include "llist.h" #include "native-common.h" -#define DEFAULT_TLENGTH (10240*4) +#define DEFAULT_TLENGTH (10240*8) #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) #define DEFAULT_PREBUF DEFAULT_TLENGTH #define DEFAULT_MINREQ 512 diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index c71d59a4a..ccd39c2a6 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -188,7 +188,7 @@ int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *pe l = length; pa_stream_write(p->stream, data, l, NULL, 0); - data += l; + data = (uint8_t*) data + l; length -= l; } @@ -222,9 +222,9 @@ int pa_simple_read(struct pa_simple *p, void*data, size_t length, int *perror) { if (p->read_length <= l) l = p->read_length; - memcpy(data, p->read_data+p->read_index, l); + memcpy(data, (uint8_t*) p->read_data+p->read_index, l); - data += l; + data = (uint8_t*) data + l; length -= l; p->read_index += l; diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 2059dab83..d6e2bf6b1 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -210,7 +210,7 @@ static void* connection_write(struct connection *c, size_t length) { i = c->write_data_length; c->write_data_length += length; - return c->write_data+i; + return (uint8_t*) c->write_data+i; } static void format_esd2native(int format, struct pa_sample_spec *ss) { @@ -245,7 +245,7 @@ static int esd_proto_connect(struct connection *c, esd_proto_t request, const vo c->authorized = 1; } - ekey = *(uint32_t*)(data+ESD_KEY_LEN); + ekey = *(uint32_t*)((uint8_t*) data+ESD_KEY_LEN); if (ekey == ESD_ENDIAN_KEY) c->swap_byte_order = 0; else if (ekey == ESD_SWAP_ENDIAN_KEY) @@ -283,7 +283,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons return -1; } - strncpy(name, data + sizeof(int)*2, sizeof(name)); + strncpy(name, (char*) data + sizeof(int)*2, sizeof(name)); name[sizeof(name)-1] = 0; pa_client_rename(c->client, name); @@ -347,7 +347,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co return -1; } - strncpy(name, data + sizeof(int)*2, sizeof(name)); + strncpy(name, (char*) data + sizeof(int)*2, sizeof(name)); name[sizeof(name)-1] = 0; pa_client_rename(c->client, name); @@ -415,7 +415,7 @@ static int esd_proto_server_info(struct connection *c, esd_proto_t request, cons } static int esd_proto_all_info(struct connection *c, esd_proto_t request, const void *data, size_t length) { - void *response; + uint8_t *response; size_t t, k, s; struct connection *conn; size_t index = PA_IDXSET_INVALID; @@ -451,7 +451,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v /* name */ assert(conn->client); - strncpy(response, conn->client->name, ESD_NAME_MAX); + strncpy((char*) response, conn->client->name, ESD_NAME_MAX); response += ESD_NAME_MAX; /* rate */ @@ -491,9 +491,9 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v /* name */ if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0) - strncpy(response, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX); + strncpy((char*) response, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX); else - snprintf(response, ESD_NAME_MAX, "native.%s", ce->name); + snprintf((char*) response, ESD_NAME_MAX, "native.%s", ce->name); response += ESD_NAME_MAX; /* rate */ @@ -570,7 +570,7 @@ static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, con return -1; strcpy(name, SCACHE_PREFIX); - strncpy(name+sizeof(SCACHE_PREFIX)-1, data+3*sizeof(int), ESD_NAME_MAX); + strncpy(name+sizeof(SCACHE_PREFIX)-1, (char*) data+3*sizeof(int), ESD_NAME_MAX); name[sizeof(name)-1] = 0; assert(!c->scache_memchunk.memblock); @@ -661,7 +661,7 @@ static int do_read(struct connection *c) { ssize_t r; assert(c->read_data_length < sizeof(c->request)); - if ((r = pa_iochannel_read(c->io, ((void*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { + if ((r = pa_iochannel_read(c->io, ((uint8_t*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -708,7 +708,7 @@ static int do_read(struct connection *c) { assert(c->read_data && c->read_data_length < handler->data_length); - if ((r = pa_iochannel_read(c->io, c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { + if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -728,7 +728,7 @@ static int do_read(struct connection *c) { assert(c->scache_memchunk.memblock && c->scache_name && c->scache_memchunk.index < c->scache_memchunk.length); - if ((r = pa_iochannel_read(c->io, c->scache_memchunk.memblock->data+c->scache_memchunk.index, c->scache_memchunk.length-c->scache_memchunk.index)) <= 0) { + if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache_memchunk.memblock->data+c->scache_memchunk.index, c->scache_memchunk.length-c->scache_memchunk.index)) <= 0) { fprintf(stderr, __FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -783,7 +783,7 @@ static int do_read(struct connection *c) { c->playback.memblock_index = 0; } - if ((r = pa_iochannel_read(c->io, c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { + if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { fprintf(stderr, __FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -811,7 +811,7 @@ static int do_write(struct connection *c) { ssize_t r; assert(c->write_data_index < c->write_data_length); - if ((r = pa_iochannel_write(c->io, c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { + if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno)); return -1; } @@ -829,7 +829,7 @@ static int do_write(struct connection *c) { assert(chunk.memblock && chunk.length); - if ((r = pa_iochannel_write(c->io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { + if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); fprintf(stderr, __FILE__": write(): %s\n", strerror(errno)); return -1; diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index b03c2e54a..41c1f4846 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -120,7 +120,7 @@ static int do_read(struct connection *c) { c->playback.memblock_index = 0; } - if ((r = pa_iochannel_read(c->io, c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { + if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { fprintf(stderr, __FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -153,7 +153,7 @@ static int do_write(struct connection *c) { assert(chunk.memblock && chunk.length); - if ((r = pa_iochannel_write(c->io, chunk.memblock->data+chunk.index, chunk.length)) < 0) { + if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); fprintf(stderr, "write(): %s\n", strerror(errno)); return -1; diff --git a/polyp/pstream.c b/polyp/pstream.c index 02dba72d3..438dccc71 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -272,7 +272,7 @@ static void prepare_next_write_item(struct pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA] = 0; } else { assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK && p->write.current->chunk.memblock); - p->write.data = p->write.current->chunk.memblock->data + p->write.current->chunk.index; + p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl(p->write.current->channel); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA] = htonl(p->write.current->delta); @@ -294,10 +294,10 @@ static void do_write(struct pa_pstream *p) { assert(p->write.data); if (p->write.index < PA_PSTREAM_DESCRIPTOR_SIZE) { - d = (void*) p->write.descriptor + p->write.index; + d = (uint8_t*) p->write.descriptor + p->write.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->write.index; } else { - d = (void*) p->write.data + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; + d = (uint8_t*) p->write.data + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } @@ -330,11 +330,11 @@ static void do_read(struct pa_pstream *p) { assert(p); if (p->read.index < PA_PSTREAM_DESCRIPTOR_SIZE) { - d = (void*) p->read.descriptor + p->read.index; + d = (uint8_t*) p->read.descriptor + p->read.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->read.index; } else { assert(p->read.data); - d = (void*) p->read.data + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE; + d = (uint8_t*) p->read.data + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE; l = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE); } diff --git a/polyp/resampler.c b/polyp/resampler.c index ed44cbb7e..b6b876076 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -146,7 +146,7 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru r->i_buf = pa_xrealloc(r->i_buf, sizeof(float) * (r->i_alloc = eff_ins)); assert(r->i_buf); - r->to_float32_func(eff_ins, in->memblock->data+in->index, i_nchannels, r->i_buf); + r->to_float32_func(eff_ins, (uint8_t*) in->memblock->data+in->index, i_nchannels, r->i_buf); if (r->src_state) { int ret; @@ -179,6 +179,6 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru } else cbuf = r->i_buf; - r->from_float32_func(eff_ons, cbuf, out->memblock->data+out->index, o_nchannels); + r->from_float32_func(eff_ons, cbuf, (uint8_t*)out->memblock->data+out->index, o_nchannels); out->length = ons*r->o_sz; } diff --git a/polyp/sample-util.c b/polyp/sample-util.c index 6a09478f6..51b22fbe1 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -37,7 +37,7 @@ struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_s void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spec) { assert(c && c->memblock && c->memblock->data && spec && c->length); - pa_silence_memory(c->memblock->data+c->index, c->length, spec); + pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec); } void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec) { @@ -85,7 +85,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz if (volume == PA_VOLUME_MUTED) v = 0; else { - v = *((int16_t*) (channels[c].chunk.memblock->data + channels[c].chunk.index + d)); + v = *((int16_t*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d)); if (volume != PA_VOLUME_NORM) v = (int32_t) ((float)v*volume/PA_VOLUME_NORM); @@ -103,7 +103,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz if (sum > 0x7FFF) sum = 0x7FFF; *((int16_t*) data) = sum; - data += sizeof(int16_t); + data = (uint8_t*) data + sizeof(int16_t); } } @@ -122,7 +122,7 @@ void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, return; } - for (d = (c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + for (d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t = (int32_t)(*d); t *= volume; diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 3852c1adf..259401223 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -65,7 +65,8 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { static void do_call(struct pa_socket_client *c) { struct pa_iochannel *io = NULL; - int error, lerror; + int error; + socklen_t lerror; assert(c && c->callback); pa_socket_client_ref(c); diff --git a/polyp/strbuf.c b/polyp/strbuf.c index ef48a3fb2..169604e82 100644 --- a/polyp/strbuf.c +++ b/polyp/strbuf.c @@ -36,7 +36,7 @@ struct chunk { struct chunk *next; size_t length; - char text[0]; + char text[]; }; struct pa_strbuf { From fa19d6ab7e2df69902d94a38cc03a183f6d97670 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 12:21:06 +0000 Subject: [PATCH 0162/1514] implement missing scache_get_id_by_name add some more consts to idxset add module-sine, a sine generating sink_input module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@165 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 4 +- polyp/Makefile.am | 7 +- polyp/idxset.c | 11 +-- polyp/idxset.h | 4 +- polyp/module-sine.c | 165 ++++++++++++++++++++++++++++++++++++++++++++ polyp/polypaudio.pa | 8 +-- polyp/scache.c | 11 ++- 7 files changed, 195 insertions(+), 15 deletions(-) create mode 100644 polyp/module-sine.c diff --git a/doc/todo b/doc/todo index d3baff161..cc9c333d6 100644 --- a/doc/todo +++ b/doc/todo @@ -2,7 +2,7 @@ *** 0.4 *** - make mcalign merge chunks -- use ref counting in more objects +- use ref counting in more objects (i.e. sink, source, sink_input, source_output) - unix socket directories include user name - native library/protocol: module load/unload @@ -14,6 +14,7 @@ - remove all gcc warnings - esd compatible startup script or personality - limit number of concurrent streams +- decibel macros ** later *** - xmlrpc/http @@ -28,4 +29,3 @@ backends for: - sdl - gstreamer - portaudio -- python diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 73e80621e..bd71f5509 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -79,7 +79,8 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-esound-protocol-tcp.la \ module-esound-protocol-unix.la \ module-native-protocol-tcp.la \ - module-native-protocol-unix.la + module-native-protocol-unix.la \ + module-sine.la if !X_DISPLAY_MISSING pkglib_LTLIBRARIES+=module-x11-bell.la @@ -273,6 +274,10 @@ module_cli_la_SOURCES = module-cli.c module_cli_la_LDFLAGS = -module -avoid-version module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la +module_sine_la_SOURCES = module-sine.c +module_sine_la_LDFLAGS = -module -avoid-version +module_sine_la_LIBADD = $(AM_LIBADD) -lm + if !X_DISPLAY_MISSING module_x11_bell_la_SOURCES = module-x11-bell.c module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) diff --git a/polyp/idxset.c b/polyp/idxset.c index 83565193c..92cde13f8 100644 --- a/polyp/idxset.c +++ b/polyp/idxset.c @@ -107,7 +107,7 @@ void pa_idxset_free(struct pa_idxset *s, void (*free_func) (void *p, void *userd pa_xfree(s); } -static struct idxset_entry* hash_scan(struct pa_idxset *s, struct idxset_entry* e, void *p) { +static struct idxset_entry* hash_scan(struct pa_idxset *s, struct idxset_entry* e, const void *p) { assert(p); assert(s->compare_func); @@ -221,7 +221,7 @@ void* pa_idxset_get_by_index(struct pa_idxset*s, uint32_t index) { return (*a)->data; } -void* pa_idxset_get_by_data(struct pa_idxset*s, void *p, uint32_t *index) { +void* pa_idxset_get_by_data(struct pa_idxset*s, const void *p, uint32_t *index) { unsigned h; struct idxset_entry *e; assert(s && p); @@ -289,9 +289,10 @@ void* pa_idxset_remove_by_index(struct pa_idxset*s, uint32_t index) { return data; } -void* pa_idxset_remove_by_data(struct pa_idxset*s, void *data, uint32_t *index) { +void* pa_idxset_remove_by_data(struct pa_idxset*s, const void *data, uint32_t *index) { struct idxset_entry *e; unsigned h; + void *r; assert(s->hash_func); h = s->hash_func(data) % s->hash_table_size; @@ -300,13 +301,13 @@ void* pa_idxset_remove_by_data(struct pa_idxset*s, void *data, uint32_t *index) if (!(e = hash_scan(s, s->hash_table[h], data))) return NULL; - data = e->data; + r = e->data; if (index) *index = e->index; remove_entry(s, e); - return data; + return r; } void* pa_idxset_rrobin(struct pa_idxset *s, uint32_t *index) { diff --git a/polyp/idxset.h b/polyp/idxset.h index f26b03fbe..e9a6fb9a1 100644 --- a/polyp/idxset.h +++ b/polyp/idxset.h @@ -40,10 +40,10 @@ void pa_idxset_free(struct pa_idxset *s, void (*free_func) (void *p, void *userd int pa_idxset_put(struct pa_idxset*s, void *p, uint32_t *index); void* pa_idxset_get_by_index(struct pa_idxset*s, uint32_t index); -void* pa_idxset_get_by_data(struct pa_idxset*s, void *p, uint32_t *index); +void* pa_idxset_get_by_data(struct pa_idxset*s, const void *p, uint32_t *index); void* pa_idxset_remove_by_index(struct pa_idxset*s, uint32_t index); -void* pa_idxset_remove_by_data(struct pa_idxset*s, void *p, uint32_t *index); +void* pa_idxset_remove_by_data(struct pa_idxset*s, const void *p, uint32_t *index); /* This may be used to iterate through all entries. When called with an invalid index value it returns the first entry, otherwise the diff --git a/polyp/module-sine.c b/polyp/module-sine.c new file mode 100644 index 000000000..364cc64cc --- /dev/null +++ b/polyp/module-sine.c @@ -0,0 +1,165 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "sink-input.h" +#include "module.h" +#include "modargs.h" +#include "xmalloc.h" +#include "namereg.h" + +struct userdata { + struct pa_core *core; + struct pa_sink_input *sink_input; + struct pa_memblock *memblock; + size_t peek_index; +}; + +static const char* const valid_modargs[] = { + "sink", + "frequency", + NULL, +}; + +static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { + struct userdata *u; + assert(i && chunk && i->userdata); + u = i->userdata; + + chunk->memblock = pa_memblock_ref(u->memblock); + chunk->index = u->peek_index; + chunk->length = u->memblock->length - u->peek_index; + return 0; +} + +static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { + struct userdata *u; + assert(i && chunk && length && i->userdata); + u = i->userdata; + + assert(chunk->memblock == u->memblock && length <= u->memblock->length-u->peek_index); + + u->peek_index += length; + + if (u->peek_index >= u->memblock->length) + u->peek_index = 0; +} + +static void sink_input_kill(struct pa_sink_input *i) { + struct userdata *u; + assert(i && i->userdata); + u = i->userdata; + + pa_sink_input_free(u->sink_input); + u->sink_input = NULL; +} + +static void calc_sine(float *f, size_t l, float freq) { + size_t i; + + l /= sizeof(float); + + for (i = 0; i < l; i++) + f[i] = (float) sin((double) i/l*M_PI*2*freq)/2; +} + +int pa_module_init(struct pa_core *c, struct pa_module*m) { + struct pa_modargs *ma = NULL; + struct userdata *u; + struct pa_sink *sink; + const char *sink_name; + struct pa_sample_spec ss; + uint32_t frequency; + char t[256]; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + fprintf(stderr, __FILE__": Failed to parse module arguments\n"); + goto fail; + } + + m->userdata = u = pa_xmalloc(sizeof(struct userdata)); + u->core = c; + u->sink_input = NULL; + u->memblock = NULL; + + sink_name = pa_modargs_get_value(ma, "sink", NULL); + + if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, 1))) { + fprintf(stderr, __FILE__": No such sink\n"); + goto fail; + } + + ss.format = PA_SAMPLE_FLOAT32; + ss.rate = sink->sample_spec.rate; + ss.channels = 1; + + frequency = 440; + if (pa_modargs_get_value_u32(ma, "frequency", &frequency) < 0 || frequency < 1 || frequency > ss.rate/2) { + fprintf(stderr, __FILE__": Invalid frequency specification\n"); + goto fail; + } + + u->memblock = pa_memblock_new(pa_bytes_per_second(&ss), c->memblock_stat); + calc_sine(u->memblock->data, u->memblock->length, frequency); + + snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); + if (!(u->sink_input = pa_sink_input_new(sink, t, &ss))) + goto fail; + + u->sink_input->peek = sink_input_peek; + u->sink_input->drop = sink_input_drop; + u->sink_input->kill = sink_input_kill; + u->sink_input->userdata = u; + u->sink_input->owner = m; + + u->peek_index = 0; + + pa_modargs_free(ma); + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa_module_done(c, m); + return -1; +} + +void pa_module_done(struct pa_core *c, struct pa_module*m) { + struct userdata *u = m->userdata; + assert(c && m); + + if (!u) + return; + + if (u->sink_input) + pa_sink_input_free(u->sink_input); + if (u->memblock) + pa_memblock_unref(u->memblock); + pa_xfree(u); +} diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index b683e627b..8c5157a1d 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -28,12 +28,12 @@ # Load audio drivers automatically on access -autoload_sink_add output module-oss device="/dev/adsp" sink_name=output source_name=input -autoload_source_add input module-oss device="/dev/adsp" sink_name=output source_name=input +#autoload_sink_add output module-oss device="/dev/adsp" sink_name=output source_name=input +#autoload_source_add input module-oss device="/dev/adsp" sink_name=output source_name=input #autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#autoload_sink_add output module-alsa-sink sink_name=output -#autoload_source_add input module-alsa-source source_name=input +autoload_sink_add output module-alsa-sink sink_name=output +autoload_source_add input module-alsa-source source_name=input # Load several protocols #load module-esound-protocol-tcp diff --git a/polyp/scache.c b/polyp/scache.c index f3c15934f..311d68a42 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -157,5 +157,14 @@ const char * pa_scache_get_name_by_id(struct pa_core *c, uint32_t id) { return NULL; return e->name; - +} + +uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { + struct pa_scache_entry *e; + assert(c && name); + + if (!c->scache || !(e = pa_idxset_get_by_data(c->scache, name, NULL))) + return PA_IDXSET_INVALID; + + return e->index; } From 9c4fd2a2c75b958c22442d2b83e75021bd096be5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 12:48:47 +0000 Subject: [PATCH 0163/1514] add support for dB volumes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@166 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - polyp/Makefile.am | 6 +++--- polyp/cli-text.c | 6 ++++-- polyp/sample.c | 15 +++++++++++++++ polyp/sample.h | 6 ++++++ 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/doc/todo b/doc/todo index cc9c333d6..107fc443c 100644 --- a/doc/todo +++ b/doc/todo @@ -14,7 +14,6 @@ - remove all gcc warnings - esd compatible startup script or personality - limit number of concurrent streams -- decibel macros ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index bd71f5509..6fb7a583e 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -19,8 +19,8 @@ AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) #AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" -AM_LDADD=$(PTHREAD_LIBS) -AM_LIBADD=$(PTHREAD_LIBS) +AM_LDADD=$(PTHREAD_LIBS) -lm +AM_LIBADD=$(PTHREAD_LIBS) -lm polypincludedir=$(includedir)/polyp @@ -276,7 +276,7 @@ module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la module_sine_la_SOURCES = module-sine.c module_sine_la_LDFLAGS = -module -avoid-version -module_sine_la_LIBADD = $(AM_LIBADD) -lm +module_sine_la_LIBADD = $(AM_LIBADD) if !X_DISPLAY_MISSING module_x11_bell_la_SOURCES = module-x11-bell.c diff --git a/polyp/cli-text.c b/polyp/cli-text.c index fa1ccdf94..18a99cfab 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -93,10 +93,11 @@ char *pa_sink_list_to_string(struct pa_core *c) { assert(sink->monitor_source); pa_strbuf_printf( s, - " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", + " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%u usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, + pa_volume_to_dB(sink->volume), pa_sink_get_latency(sink), sink->monitor_source->index, ss); @@ -188,11 +189,12 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x>\n\tlatency: <%u usec>\n\tsample_spec: <%s>\n", + s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%u usec>\n\tsample_spec: <%s>\n", i->index, i->name, i->sink->index, (unsigned) i->volume, + pa_volume_to_dB(i->volume), pa_sink_input_get_latency(i), ss); diff --git a/polyp/sample.c b/polyp/sample.c index edfe19594..3019f93b8 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -25,6 +25,7 @@ #include #include +#include #include "sample.h" @@ -104,3 +105,17 @@ pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b) { return (pa_volume_t) p; } + +pa_volume_t pa_volume_from_dB(double f) { + if (f <= -200) + return PA_VOLUME_MUTED; + + return (pa_volume_t) (pow(10, f/20)*PA_VOLUME_NORM); +} + +double pa_volume_to_dB(pa_volume_t v) { + if (v == PA_VOLUME_MUTED) + return -200; + + return 20*log10((double) v/PA_VOLUME_NORM); +} diff --git a/polyp/sample.h b/polyp/sample.h index 28ae51eab..ca4620717 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -102,6 +102,12 @@ typedef uint32_t pa_volume_t; /** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */ pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b); +/** Convert volume from decibel to linear level */ +pa_volume_t pa_volume_from_dB(double f); + +/** Convert volume from linear level to decibel */ +double pa_volume_to_dB(pa_volume_t v); + PA_C_DECL_END #endif From 9939fba7f5d2e2f39a7156e90f171aa01176f313 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 12:49:39 +0000 Subject: [PATCH 0164/1514] add \since to dB functions git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@167 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/sample.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/polyp/sample.h b/polyp/sample.h index ca4620717..0a6c306e4 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -102,10 +102,12 @@ typedef uint32_t pa_volume_t; /** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */ pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b); -/** Convert volume from decibel to linear level */ +/** Convert volume from decibel to linear level + * \since 0.4 */ pa_volume_t pa_volume_from_dB(double f); -/** Convert volume from linear level to decibel */ +/** Convert volume from linear level to decibel + * \since 0.4 */ double pa_volume_to_dB(pa_volume_t v); PA_C_DECL_END From 63c76bd0691a4b4b1d505ad6eac87af7c296cdab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 12:51:08 +0000 Subject: [PATCH 0165/1514] cleanup comment git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@168 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/sample.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/polyp/sample.h b/polyp/sample.h index 0a6c306e4..958443010 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -102,12 +102,10 @@ typedef uint32_t pa_volume_t; /** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */ pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b); -/** Convert volume from decibel to linear level - * \since 0.4 */ +/** Convert volume from decibel to linear level. \since 0.4 */ pa_volume_t pa_volume_from_dB(double f); -/** Convert volume from linear level to decibel - * \since 0.4 */ +/** Convert volume from linear level to decibel. \since 0.4 */ double pa_volume_to_dB(pa_volume_t v); PA_C_DECL_END From 0205fc57bbfdf03e5cdd5eb3c908f5531c4fdbf1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 13:04:03 +0000 Subject: [PATCH 0166/1514] add PA_MININFTY git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@169 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/oss-util.c | 4 ++-- polyp/sample.c | 4 ++-- polyp/sample.h | 8 ++++++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/polyp/oss-util.c b/polyp/oss-util.c index cf55a6ee6..4fb2b9298 100644 --- a/polyp/oss-util.c +++ b/polyp/oss-util.c @@ -138,7 +138,7 @@ int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { return 0; } -static int log2(int v) { +static int simple_log2(int v) { int k = 0; for (;;) { @@ -152,7 +152,7 @@ static int log2(int v) { int pa_oss_set_fragments(int fd, int nfrags, int frag_size) { int arg; - arg = ((int) nfrags << 16) | log2(frag_size); + arg = ((int) nfrags << 16) | simple_log2(frag_size); if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &arg) < 0) { fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); diff --git a/polyp/sample.c b/polyp/sample.c index 3019f93b8..6ec560003 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -107,7 +107,7 @@ pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b) { } pa_volume_t pa_volume_from_dB(double f) { - if (f <= -200) + if (f <= PA_DECIBEL_MININFTY) return PA_VOLUME_MUTED; return (pa_volume_t) (pow(10, f/20)*PA_VOLUME_NORM); @@ -115,7 +115,7 @@ pa_volume_t pa_volume_from_dB(double f) { double pa_volume_to_dB(pa_volume_t v) { if (v == PA_VOLUME_MUTED) - return -200; + return PA_DECIBEL_MININFTY; return 20*log10((double) v/PA_VOLUME_NORM); } diff --git a/polyp/sample.h b/polyp/sample.h index 958443010..4b28780df 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -24,6 +24,7 @@ #include #include +#include #include "cdecl.h" @@ -108,6 +109,13 @@ pa_volume_t pa_volume_from_dB(double f); /** Convert volume from linear level to decibel. \since 0.4 */ double pa_volume_to_dB(pa_volume_t v); +#ifdef INFINITY +#define PA_DECIBEL_MININFTY -INFINITY +#else +/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). \since 0.4 */ +#define PA_DECIBEL_MININFTY -200 +#endif + PA_C_DECL_END #endif From 50f592b67c9d7364ab0d7ac447c565db4ab83d2a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 15:00:44 +0000 Subject: [PATCH 0167/1514] introduce sink input and source output limits git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@170 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 ++- polyp/module-x11-bell.c | 6 +----- polyp/sample.h | 4 ++-- polyp/sink-input.c | 5 +++++ polyp/sink.h | 2 ++ polyp/source-output.c | 6 ++++++ polyp/source.h | 2 ++ 7 files changed, 20 insertions(+), 8 deletions(-) diff --git a/doc/todo b/doc/todo index 107fc443c..6aacd3a5f 100644 --- a/doc/todo +++ b/doc/todo @@ -13,7 +13,8 @@ - cleanup tagstruct and modargs (add s32, pa_volume_t, pa_usec_t) - remove all gcc warnings - esd compatible startup script or personality -- limit number of concurrent streams +- add total sample size to stat +- implement streamed file playbacj ** later *** - xmlrpc/http diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index 3ed9b0682..ae889b221 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -69,11 +69,7 @@ static int ring_bell(struct userdata *u, int percent) { return -1; } - if (pa_scache_play_item(u->core, u->scache_item, s, percent*2) < 0) { - fprintf(stderr, __FILE__": Failed to play sample\n"); - return -1; - } - + pa_scache_play_item(u->core, u->scache_item, s, percent*2); return 0; } diff --git a/polyp/sample.h b/polyp/sample.h index 4b28780df..a5479562b 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -110,10 +110,10 @@ pa_volume_t pa_volume_from_dB(double f); double pa_volume_to_dB(pa_volume_t v); #ifdef INFINITY -#define PA_DECIBEL_MININFTY -INFINITY +#define PA_DECIBEL_MININFTY (-INFINITY) #else /** This value is used as minus infinity when using pa_volume_{to,from}_dB(). \since 0.4 */ -#define PA_DECIBEL_MININFTY -200 +#define PA_DECIBEL_MININFTY (-200) #endif PA_C_DECL_END diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 9238fac0f..95dc55772 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -42,6 +42,11 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con char st[256]; assert(s && spec); + if (pa_idxset_ncontents(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { + fprintf(stderr, __FILE__": Failed to create sink input: too many inputs per sink.\n"); + return NULL; + } + if (!pa_sample_spec_equal(spec, &s->sample_spec)) if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat))) return NULL; diff --git a/polyp/sink.h b/polyp/sink.h index 940d16184..85addf763 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -31,6 +31,8 @@ struct pa_sink; #include "idxset.h" #include "source.h" +#define PA_MAX_INPUTS_PER_SINK 6 + struct pa_sink { uint32_t index; diff --git a/polyp/source-output.c b/polyp/source-output.c index b8083a79a..9d124f074 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -23,6 +23,7 @@ #include #endif +#include #include #include #include @@ -37,6 +38,11 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n int r; assert(s && spec); + if (pa_idxset_ncontents(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { + fprintf(stderr, __FILE__": Failed to create source output: too many outputs per source.\n"); + return NULL; + } + if (!pa_sample_spec_equal(&s->sample_spec, spec)) if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat))) return NULL; diff --git a/polyp/source.h b/polyp/source.h index 32ef14e60..309b87e72 100644 --- a/polyp/source.h +++ b/polyp/source.h @@ -32,6 +32,8 @@ struct pa_source; #include "memchunk.h" #include "sink.h" +#define PA_MAX_OUTPUTS_PER_SOURCE 16 + struct pa_source { uint32_t index; From dfd440bd5db50d3da6146a7f559e3a4f873f8810 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 15:55:48 +0000 Subject: [PATCH 0168/1514] add sound file streaming git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@171 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +- polyp/Makefile.am | 3 +- polyp/cli-command.c | 12 +-- polyp/play-memchunk.c | 2 +- polyp/play-memchunk.h | 2 +- polyp/sound-file-stream.c | 162 ++++++++++++++++++++++++++++++++++++++ polyp/sound-file-stream.h | 29 +++++++ 7 files changed, 198 insertions(+), 15 deletions(-) create mode 100644 polyp/sound-file-stream.c create mode 100644 polyp/sound-file-stream.h diff --git a/doc/todo b/doc/todo index 6aacd3a5f..8ad59f1b8 100644 --- a/doc/todo +++ b/doc/todo @@ -13,8 +13,7 @@ - cleanup tagstruct and modargs (add s32, pa_volume_t, pa_usec_t) - remove all gcc warnings - esd compatible startup script or personality -- add total sample size to stat -- implement streamed file playbacj +- add total sample cache size to stat ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 6fb7a583e..cd369657a 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -133,7 +133,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ autoload.c autoload.h \ xmalloc.c xmalloc.h \ subscribe.h subscribe.c \ - debug.h + debug.h \ + sound-file-stream.c sound-file-stream.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 5a8ff1770..1d2788fa5 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -46,6 +46,7 @@ #include "play-memchunk.h" #include "autoload.h" #include "xmalloc.h" +#include "sound-file-stream.h" struct command { const char *name; @@ -516,10 +517,7 @@ static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { const char *fname, *sink_name; - struct pa_memchunk chunk; - struct pa_sample_spec ss; struct pa_sink *sink; - int ret; assert(c && t && buf && fail && verbose); if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) { @@ -532,14 +530,8 @@ static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, s return -1; } - if (pa_sound_file_load(fname, &ss, &chunk, c->memblock_stat) < 0) { - pa_strbuf_puts(buf, "Failed to load sound file.\n"); - return -1; - } - ret = pa_play_memchunk(sink, fname, &ss, &chunk, PA_VOLUME_NORM); - pa_memblock_unref(chunk.memblock); - return ret; + return pa_play_file(sink, fname, PA_VOLUME_NORM); } static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index 486f0cf65..e3f0c006e 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -76,7 +76,7 @@ static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk*ch pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); } -int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, uint32_t volume) { +int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, pa_volume_t volume) { struct pa_sink_input *si; struct pa_memchunk *nchunk; diff --git a/polyp/play-memchunk.h b/polyp/play-memchunk.h index edd327c55..0e6a1d8e4 100644 --- a/polyp/play-memchunk.h +++ b/polyp/play-memchunk.h @@ -25,6 +25,6 @@ #include "sink.h" #include "memchunk.h" -int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, uint32_t volume); +int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, pa_volume_t volume); #endif diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c new file mode 100644 index 000000000..a77b58139 --- /dev/null +++ b/polyp/sound-file-stream.c @@ -0,0 +1,162 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include "sound-file-stream.h" +#include "sink-input.h" +#include "xmalloc.h" + +#define BUF_SIZE (1024*10) + +struct userdata { + SNDFILE *sndfile; + struct pa_sink_input *sink_input; + struct pa_memchunk memchunk; +}; + +static void free_userdata(struct userdata *u) { + assert(u); + if (u->sink_input) + pa_sink_input_free(u->sink_input); + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + if (u->sndfile) + sf_close(u->sndfile); + + pa_xfree(u); +} + +static void sink_input_kill(struct pa_sink_input *i) { + assert(i && i->userdata); + free_userdata(i->userdata); +} + +static void si_kill(struct pa_mainloop_api *m, void *i) { + sink_input_kill(i); +} + +static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { + struct userdata *u; + assert(i && chunk && i->userdata); + u = i->userdata; + + if (!u->memchunk.memblock) { + uint32_t fs = pa_frame_size(&i->sample_spec); + sf_count_t samples = BUF_SIZE/fs; + + u->memchunk.memblock = pa_memblock_new(BUF_SIZE, i->sink->core->memblock_stat); + u->memchunk.index = 0; + samples = sf_readf_float(u->sndfile, u->memchunk.memblock->data, samples); + u->memchunk.length = samples*fs; + + if (!u->memchunk.length) { + pa_memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; + u->memchunk.index = u->memchunk.length = 0; + pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); + return -1; + } + } + + *chunk = u->memchunk; + pa_memblock_ref(chunk->memblock); + assert(chunk->length); + return 0; +} + +static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk*chunk, size_t length) { + struct userdata *u; + assert(i && chunk && length && i->userdata); + u = i->userdata; + + assert(!memcmp(chunk, &u->memchunk, sizeof(chunk))); + assert(length <= u->memchunk.length); + + u->memchunk.index += length; + u->memchunk.length -= length; + + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; + u->memchunk.index = u->memchunk.length = 0; + } +} + +int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume) { + struct userdata *u = NULL; + SF_INFO sfinfo; + struct pa_sample_spec ss; + assert(sink && fname); + + if (volume <= 0) + goto fail; + + u = pa_xmalloc(sizeof(struct userdata)); + u->sink_input = NULL; + u->memchunk.memblock = NULL; + u->memchunk.index = u->memchunk.length = 0; + u->sndfile = NULL; + + memset(&sfinfo, 0, sizeof(sfinfo)); + + if (!(u->sndfile = sf_open(fname, SFM_READ, &sfinfo))) { + fprintf(stderr, __FILE__": Failed to open file %s\n", fname); + goto fail; + } + + ss.format = PA_SAMPLE_FLOAT32; + ss.rate = sfinfo.samplerate; + ss.channels = sfinfo.channels; + + if (!pa_sample_spec_valid(&ss)) { + fprintf(stderr, __FILE__": Unsupported sample format in file %s\n", fname); + goto fail; + } + + if (!(u->sink_input = pa_sink_input_new(sink, fname, &ss))) + goto fail; + + u->sink_input->volume = volume; + u->sink_input->peek = sink_input_peek; + u->sink_input->drop = sink_input_drop; + u->sink_input->kill = sink_input_kill; + u->sink_input->userdata = u; + + pa_sink_notify(sink); + + return 0; + +fail: + if (u) + free_userdata(u); + + return -1; +} diff --git a/polyp/sound-file-stream.h b/polyp/sound-file-stream.h new file mode 100644 index 000000000..9cf88cce6 --- /dev/null +++ b/polyp/sound-file-stream.h @@ -0,0 +1,29 @@ +#ifndef foosoundfilestreamhfoo +#define foosoundfilestreamhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "sink.h" + +int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume); + +#endif From ee91cb6c9ded44d7f3ddb23b681df49fe5c8146b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 17:36:46 +0000 Subject: [PATCH 0169/1514] add esd compatible startup script add default configuration script git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@172 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 5 ++- doc/todo | 2 +- polyp/Makefile.am | 9 +++-- polyp/cmdline.c | 11 +++++- polyp/esdcompat.sh.in | 83 +++++++++++++++++++++++++++++++++++++++++++ polyp/main.c | 4 +-- polyp/polypaudio.pa | 2 +- 7 files changed, 108 insertions(+), 8 deletions(-) create mode 100755 polyp/esdcompat.sh.in diff --git a/configure.ac b/configure.ac index 7aa6c5d48..2c470435e 100644 --- a/configure.ac +++ b/configure.ac @@ -115,5 +115,8 @@ AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) -AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h]) +ESDCOMPAT_BINARY=$(bindir)/polypaudio +AC_SUBST(ESDCOMPAT_BINARY) + +AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h polyp/esdcompat.sh]) AC_OUTPUT diff --git a/doc/todo b/doc/todo index 8ad59f1b8..e9c825625 100644 --- a/doc/todo +++ b/doc/todo @@ -12,8 +12,8 @@ - daemon autostart - cleanup tagstruct and modargs (add s32, pa_volume_t, pa_usec_t) - remove all gcc warnings -- esd compatible startup script or personality - add total sample cache size to stat +- make fragments settings runtime configurable ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index cd369657a..7d6d9bb3f 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -17,17 +17,22 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. +polypincludedir=$(includedir)/polyp +polypconfdir=$(sysconfdir)/polyp + AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) -#AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" +#AM_CFLAGS+= -DPA_DLSEARCHDIR=\"$(pkglibdir)\" +AM_CFLAGS+= -DPA_DEFAULT_CONFIG_FILE=\"$(polypconfdir)/polypaudio.pa\" AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm -polypincludedir=$(includedir)/polyp EXTRA_DIST = polypaudio.pa depmod.py bin_PROGRAMS = polypaudio pacat pactl noinst_PROGRAMS = mainloop-test mainloop-test-glib mainloop-test-glib12 pacat-simple parec-simple +polypconf_DATA=polypaudio.pa + BUILT_SOURCES=polyplib-version.h polypinclude_HEADERS=polyplib.h \ diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 9935e7b66..6538b9301 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -48,6 +48,7 @@ void pa_cmdline_help(const char *argv0) { " -L MODULE Load the specified plugin module with the specified argument\n" " -F FILE Run the specified script\n" " -C Open a command line on the running TTY\n" + " -n Don't load configuration file ("PA_DEFAULT_CONFIG_FILE")\n" " -D Daemonize after loading the modules\n" " -f Dont quit when the startup fails\n" " -v Verbose startup\n" @@ -59,6 +60,7 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { char c; struct pa_cmdline *cmdline = NULL; struct pa_strbuf *buf = NULL; + int no_default_config_file = 0; assert(argc && argv); cmdline = pa_xmalloc(sizeof(struct pa_cmdline)); @@ -68,7 +70,7 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { buf = pa_strbuf_new(); assert(buf); - while ((c = getopt(argc, argv, "L:F:CDhfvrRV")) != -1) { + while ((c = getopt(argc, argv, "L:F:CDhfvrRVn")) != -1) { switch (c) { case 'L': pa_strbuf_printf(buf, "load %s\n", optarg); @@ -100,12 +102,19 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { case 'V': cmdline->version = 1; break; + case 'n': + no_default_config_file =1; + break; default: goto fail; } } + if (!no_default_config_file) + pa_strbuf_puts(buf, ".include "PA_DEFAULT_CONFIG_FILE"\n"); + + cmdline->cli_commands = pa_strbuf_tostring_free(buf); return cmdline; diff --git a/polyp/esdcompat.sh.in b/polyp/esdcompat.sh.in new file mode 100755 index 000000000..1033930e7 --- /dev/null +++ b/polyp/esdcompat.sh.in @@ -0,0 +1,83 @@ +#!/bin/sh + +# $Id$ +# +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +VERSION_STRING="@PACKAGE_NAME@ esd wrapper @PACKAGE_VERSION@" + +fail() { + echo "$1" > /dev/stderr + exit 1 +} + +for N in $(seq $#) ; do + + case "$1" in + + -v|--version) + echo "$VERSION_STRING" + exit 0 + ;; + + -h|--help) + cat < Date: Wed, 1 Sep 2004 21:12:27 +0000 Subject: [PATCH 0170/1514] daemon auto spawn git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@173 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 5 +- doc/todo | 5 +- polyp/Makefile.am | 21 ++++- polyp/cmdline.c | 38 +++++++-- polyp/esdcompat.sh.in | 2 +- polyp/main.c | 8 +- polyp/module-native-protocol-fd.c | 78 +++++++++++++++++++ polyp/pacat.c | 2 +- polyp/polypaudio.pa | 2 +- polyp/polyplib-context.c | 125 ++++++++++++++++++++++++++---- polyp/polyplib-context.h | 9 +++ polyp/polyplib-internal.h | 1 + polyp/protocol-native.c | 36 +++++++-- polyp/protocol-native.h | 2 + 14 files changed, 292 insertions(+), 42 deletions(-) create mode 100644 polyp/module-native-protocol-fd.c diff --git a/configure.ac b/configure.ac index 2c470435e..7aa6c5d48 100644 --- a/configure.ac +++ b/configure.ac @@ -115,8 +115,5 @@ AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) -ESDCOMPAT_BINARY=$(bindir)/polypaudio -AC_SUBST(ESDCOMPAT_BINARY) - -AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h polyp/esdcompat.sh]) +AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h]) AC_OUTPUT diff --git a/doc/todo b/doc/todo index e9c825625..19afa7fac 100644 --- a/doc/todo +++ b/doc/todo @@ -9,11 +9,14 @@ kill client/... autoload management - more complete pactl -- daemon autostart - cleanup tagstruct and modargs (add s32, pa_volume_t, pa_usec_t) - remove all gcc warnings - add total sample cache size to stat - make fragments settings runtime configurable +- CLOEXEC +- logging +- automatic termination of daemon if unused +- add sample directory ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 7d6d9bb3f..923a35224 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -21,14 +21,16 @@ polypincludedir=$(includedir)/polyp polypconfdir=$(sysconfdir)/polyp AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) -#AM_CFLAGS+= -DPA_DLSEARCHDIR=\"$(pkglibdir)\" -AM_CFLAGS+= -DPA_DEFAULT_CONFIG_FILE=\"$(polypconfdir)/polypaudio.pa\" +#AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" +AM_CFLAGS+="-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/polypaudio.pa\"" +AM_CFLAGS+="-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\"" + AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm - -EXTRA_DIST = polypaudio.pa depmod.py +EXTRA_DIST = polypaudio.pa depmod.py esdcompat.sh.in bin_PROGRAMS = polypaudio pacat pactl +bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = mainloop-test mainloop-test-glib mainloop-test-glib12 pacat-simple parec-simple polypconf_DATA=polypaudio.pa @@ -85,6 +87,7 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-esound-protocol-unix.la \ module-native-protocol-tcp.la \ module-native-protocol-unix.la \ + module-native-protocol-fd.la \ module-sine.la if !X_DISPLAY_MISSING @@ -244,6 +247,11 @@ module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE module_native_protocol_unix_la_LDFLAGS = -module -avoid-version module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la libsocket-util.la +module_native_protocol_fd_la_SOURCES = module-native-protocol-fd.c +module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS) +module_native_protocol_fd_la_LDFLAGS = -module -avoid-version +module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la libsocket-util.la + module_esound_protocol_tcp_la_SOURCES = module-protocol-stub.c module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version @@ -452,3 +460,8 @@ endif suid: polypaudio chown root:root $< chmod u+s $< + +esdcompat.sh: esdcompat.sh.in Makefile + sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ + -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ + -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 6538b9301..c07e7bdc5 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -28,14 +28,36 @@ #include #include #include +#include #include "cmdline.h" #include "util.h" #include "strbuf.h" #include "xmalloc.h" +#define ENV_CONFIG_FILE "POLYP_CONFIG" + +char* config_file(void) { + char *p, *h; + + if ((p = getenv(ENV_CONFIG_FILE))) + return pa_xstrdup(p); + + if ((h = getenv("HOME"))) { + struct stat st; + p = pa_sprintf_malloc("%s/.polypaudio", h); + if (stat(p, &st) >= 0) + return p; + + pa_xfree(p); + } + + return pa_xstrdup(DEFAULT_CONFIG_FILE); +} + void pa_cmdline_help(const char *argv0) { const char *e; + char *cfg = config_file(); if ((e = strrchr(argv0, '/'))) e++; @@ -48,16 +70,18 @@ void pa_cmdline_help(const char *argv0) { " -L MODULE Load the specified plugin module with the specified argument\n" " -F FILE Run the specified script\n" " -C Open a command line on the running TTY\n" - " -n Don't load configuration file ("PA_DEFAULT_CONFIG_FILE")\n" + " -n Don't load configuration file (%s)\n" " -D Daemonize after loading the modules\n" " -f Dont quit when the startup fails\n" " -v Verbose startup\n" " -h Show this help\n" - " -V Show version\n", e); + " -V Show version\n", e, cfg); + + pa_xfree(cfg); } struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { - char c; + char c, *cfg; struct pa_cmdline *cmdline = NULL; struct pa_strbuf *buf = NULL; int no_default_config_file = 0; @@ -111,9 +135,11 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { } } - if (!no_default_config_file) - pa_strbuf_puts(buf, ".include "PA_DEFAULT_CONFIG_FILE"\n"); - + if (!no_default_config_file) { + cfg = config_file(); + pa_strbuf_printf(buf, ".include %s\n", cfg); + pa_xfree(cfg); + } cmdline->cli_commands = pa_strbuf_tostring_free(buf); return cmdline; diff --git a/polyp/esdcompat.sh.in b/polyp/esdcompat.sh.in index 1033930e7..88ff447f9 100755 --- a/polyp/esdcompat.sh.in +++ b/polyp/esdcompat.sh.in @@ -80,4 +80,4 @@ EOF shift done -exec "@ESDCOMPAT_BINARY@" -r +exec "@POLYPAUDIO_BINARY@" -r diff --git a/polyp/main.c b/polyp/main.c index e41a106f6..87265da64 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -141,12 +141,15 @@ int main(int argc, char *argv[]) { setsid(); setpgrp(); + + close(0); + close(1); } r = lt_dlinit(); assert(r == 0); -#ifdef PA_DLSEARCHDIR - lt_dladdsearchdir(PA_DLSEARCHDIR); +#ifdef DLSEARCHDIR + lt_dladdsearchdir(DLSEARCHDIR); #endif mainloop = pa_mainloop_new(); @@ -155,6 +158,7 @@ int main(int argc, char *argv[]) { r = pa_signal_init(pa_mainloop_get_api(mainloop)); assert(r == 0); pa_signal_new(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGTERM, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); c = pa_core_new(pa_mainloop_get_api(mainloop)); diff --git a/polyp/module-native-protocol-fd.c b/polyp/module-native-protocol-fd.c new file mode 100644 index 000000000..58d09ffec --- /dev/null +++ b/polyp/module-native-protocol-fd.c @@ -0,0 +1,78 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "module.h" +#include "iochannel.h" +#include "modargs.h" +#include "protocol-native.h" + +static const char* const valid_modargs[] = { + "fd", + "public", + "cookie", + NULL, +}; + +int pa_module_init(struct pa_core *c, struct pa_module*m) { + struct pa_iochannel *io; + struct pa_modargs *ma; + int fd, r = -1; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + fprintf(stderr, __FILE__": failed to parse module arguments.\n"); + goto finish; + } + + if (pa_modargs_get_value_u32(ma, "fd", &fd) < 0) { + fprintf(stderr, __FILE__": invalid file descriptor.\n"); + goto finish; + } + + io = pa_iochannel_new(c->mainloop, fd, fd); + + if (!(m->userdata = pa_protocol_native_new_iochannel(c, io, m, ma))) { + pa_iochannel_free(io); + goto finish; + } + + r = 0; + +finish: + if (ma) + pa_modargs_free(ma); + + return r; +} + +void pa_module_done(struct pa_core *c, struct pa_module*m) { + assert(c && m); + + pa_protocol_native_free(m->userdata); +} diff --git a/polyp/pacat.c b/polyp/pacat.c index b251cc35f..fd6e90e19 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -346,7 +346,7 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect(context, NULL); + pa_context_connect_spawn(context, NULL); /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 0c69893a4..715e23b6c 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -43,7 +43,7 @@ load module-native-protocol-unix load module-esound-protocol-unix # Load the CLI module -load module-cli +#load module-cli # Make some devices default sink_default output diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 2ead40041..fb6eadf4a 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -30,6 +30,10 @@ #include #include #include +#include +#include +#include +#include #include "polyplib-internal.h" #include "polyplib-context.h" @@ -234,9 +238,11 @@ static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, u pa_context_ref(c); if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(c, command, t) < 0) pa_context_fail(c, PA_ERROR_PROTOCOL); + pa_context_fail(c, c->error); goto finish; } @@ -267,22 +273,13 @@ finish: pa_context_unref(c); } -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { - struct pa_context *c = userdata; +static void setup_context(struct pa_context *c, struct pa_iochannel *io) { struct pa_tagstruct *t; uint32_t tag; - assert(client && c && c->state == PA_CONTEXT_CONNECTING); + assert(c && io); pa_context_ref(c); - pa_socket_client_unref(client); - c->client = NULL; - - if (!io) { - pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); - goto finish; - } - assert(!c->pstream); c->pstream = pa_pstream_new(c->mainloop, io, c->memblock_stat); assert(c->pstream); @@ -295,6 +292,11 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); assert(c->pdispatch); + if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { + pa_context_fail(c, PA_ERROR_AUTHKEY); + goto finish; + } + t = pa_tagstruct_new(NULL, 0); assert(t); pa_tagstruct_putu32(t, PA_COMMAND_AUTH); @@ -305,6 +307,27 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); +finish: + + pa_context_unref(c); +} + +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { + struct pa_context *c = userdata; + assert(client && c && c->state == PA_CONTEXT_CONNECTING); + + pa_context_ref(c); + + pa_socket_client_unref(client); + c->client = NULL; + + if (!io) { + pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + goto finish; + } + + setup_context(c, io); + finish: pa_context_unref(c); } @@ -343,11 +366,6 @@ int pa_context_connect(struct pa_context *c, const char *server) { pa_context_ref(c); - if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { - pa_context_fail(c, PA_ERROR_AUTHKEY); - goto finish; - } - if (!server) if (!(server = getenv(ENV_DEFAULT_SERVER))) server = DEFAULT_SERVER; @@ -539,3 +557,78 @@ struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32 const char* pa_get_library_version(void) { return PACKAGE_VERSION; } + +static int is_running(void) { + struct stat st; + + if (DEFAULT_SERVER[0] != '/') + return 1; + + if (stat(DEFAULT_SERVER, &st) < 0) + return 0; + + return 1; +} + +int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)) { + pid_t pid; + int status; + int fds[2] = { -1, -1} ; + struct pa_iochannel *io; + + if (getenv(ENV_DEFAULT_SERVER) || is_running()) + return pa_context_connect(c, NULL); + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { + fprintf(stderr, __FILE__": socketpair() failed: %s\n", strerror(errno)); + pa_context_fail(c, PA_ERROR_INTERNAL); + goto fail; + } + + if ((pid = fork()) < 0) { + fprintf(stderr, __FILE__": fork() failed: %s\n", strerror(errno)); + pa_context_fail(c, PA_ERROR_INTERNAL); + goto fail; + } else if (!pid) { + char t[64]; + char *p; + /* Child */ + + close(fds[0]); + + if (atfork) + atfork(); + + if (!(p = getenv(ENV_DEFAULT_BINARY))) + p = POLYPAUDIO_BINARY; + + snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); + execl(p, p, "-r", "-D", t, NULL); + + exit(1); + } + + /* Parent */ + if (waitpid(pid, &status, 0) < 0) { + fprintf(stderr, __FILE__": waitpid() failed: %s\n", strerror(errno)); + pa_context_fail(c, PA_ERROR_INTERNAL); + goto fail; + } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + goto fail; + } + + close(fds[1]); + + io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); + setup_context(c, io); + return 0; + +fail: + if (fds[0] != -1) + close(fds[0]); + if (fds[1] != -1) + close(fds[1]); + + return -1; +} diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 9614ce698..c7d207034 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -1,3 +1,4 @@ + #ifndef foopolyplibcontexthfoo #define foopolyplibcontexthfoo @@ -78,6 +79,14 @@ return synchronously on error. Use pa_context_set_state_callback() to be notified when the connection is established */ int pa_context_connect(struct pa_context *c, const char *server); +/** Connect the context to a server. If the default server is local + * but not accessible, spawn a new daemon. If atfork is not NULL it is + * run after the fork() in the child process. It may be used to close + * file descriptors or to do any other cleanups. Make sure that + * SIGCHLD is handled when calling this function. The function will + * waitpid() on the daemon's PID. \since 0.4 */ +int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)); + /** Terminate the context connection immediately */ void pa_context_disconnect(struct pa_context *c); diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 813bb04e0..de63b1ba4 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -47,6 +47,7 @@ #define ENV_DEFAULT_SINK "POLYP_SINK" #define ENV_DEFAULT_SOURCE "POLYP_SOURCE" #define ENV_DEFAULT_SERVER "POLYP_SERVER" +#define ENV_DEFAULT_BINARY "POLYP_BINARY" struct pa_context { int ref; diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 9c6996be6..9dddf9a10 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -1466,7 +1466,7 @@ static void client_kill_cb(struct pa_client *c) { static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { struct pa_protocol_native *p = userdata; struct connection *c; - assert(s && io && p); + assert(io && p); c = pa_xmalloc(sizeof(struct connection)); c->authorized = p->public; @@ -1501,10 +1501,10 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo /*** module entry points ***/ -struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { +static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struct pa_module *m, struct pa_modargs *ma) { struct pa_protocol_native *p; uint32_t public; - assert(core && server && ma); + assert(c && ma); if (pa_modargs_get_value_u32(ma, "public", &public) < 0) { fprintf(stderr, __FILE__": public= expects numeric argument.\n"); @@ -1520,11 +1520,21 @@ struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct p p->module = m; p->public = public; - p->server = server; - p->core = core; + p->server = NULL; + p->core = c; p->connections = pa_idxset_new(NULL, NULL); assert(p->connections); + return p; +} + +struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { + struct pa_protocol_native *p; + + if (!(p = protocol_new_internal(core, m, ma))) + return NULL; + + p->server = server; pa_socket_server_set_callback(p->server, on_connection, p); return p; @@ -1537,6 +1547,20 @@ void pa_protocol_native_free(struct pa_protocol_native *p) { while ((c = pa_idxset_first(p->connections, NULL))) connection_free(c); pa_idxset_free(p->connections, NULL, NULL); - pa_socket_server_unref(p->server); + + if (p->server) + pa_socket_server_unref(p->server); + pa_xfree(p); } + +struct pa_protocol_native* pa_protocol_native_new_iochannel(struct pa_core*core, struct pa_iochannel *io, struct pa_module *m, struct pa_modargs *ma) { + struct pa_protocol_native *p; + + if (!(p = protocol_new_internal(core, m, ma))) + return NULL; + + on_connection(NULL, io, p); + + return p; +} diff --git a/polyp/protocol-native.h b/polyp/protocol-native.h index 3d9fdde11..edc6acbc2 100644 --- a/polyp/protocol-native.h +++ b/polyp/protocol-native.h @@ -32,4 +32,6 @@ struct pa_protocol_native; struct pa_protocol_native* pa_protocol_native_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); void pa_protocol_native_free(struct pa_protocol_native *n); +struct pa_protocol_native* pa_protocol_native_new_iochannel(struct pa_core*core, struct pa_iochannel *io, struct pa_module *m, struct pa_modargs *ma); + #endif From 5f52999c016495be1c34effdacd230a79cb52d0b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 22:36:49 +0000 Subject: [PATCH 0171/1514] make use F_CLOEXEC wherever useful git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@174 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - polyp/mainloop-signal.c | 2 ++ polyp/module-pipe-sink.c | 2 ++ polyp/oss-util.c | 3 +++ polyp/socket-client.c | 3 +++ polyp/socket-server.c | 7 +++++++ polyp/socket-util.c | 1 + polyp/util.c | 15 +++++++++++++++ polyp/util.h | 2 ++ 9 files changed, 35 insertions(+), 1 deletion(-) diff --git a/doc/todo b/doc/todo index 19afa7fac..7c1cf71e0 100644 --- a/doc/todo +++ b/doc/todo @@ -13,7 +13,6 @@ - remove all gcc warnings - add total sample cache size to stat - make fragments settings runtime configurable -- CLOEXEC - logging - automatic termination of daemon if unused - add sample directory diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c index f7ff7e93b..a16d84571 100644 --- a/polyp/mainloop-signal.c +++ b/polyp/mainloop-signal.c @@ -93,6 +93,8 @@ int pa_signal_init(struct pa_mainloop_api *a) { pa_make_nonblock_fd(signal_pipe[0]); pa_make_nonblock_fd(signal_pipe[1]); + pa_fd_set_cloexec(signal_pipe[0], 1); + pa_fd_set_cloexec(signal_pipe[1], 1); api = a; io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL); diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index 32a2c722b..088ed405d 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -143,6 +143,8 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto fail; } + pa_fd_set_cloexec(fd, 1); + if (fstat(fd, &st) < 0) { fprintf(stderr, __FILE__": fstat('%s'): %s\n", p, strerror(errno)); goto fail; diff --git a/polyp/oss-util.c b/polyp/oss-util.c index 4fb2b9298..b28c3dc95 100644 --- a/polyp/oss-util.c +++ b/polyp/oss-util.c @@ -35,6 +35,7 @@ #include #include "oss-util.h" +#include "util.h" int pa_oss_open(const char *device, int *mode, int* pcaps) { int fd = -1; @@ -77,6 +78,8 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { goto fail; } } + + pa_fd_set_cloexec(fd, 1); return fd; diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 259401223..f697cbdbc 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -152,6 +152,7 @@ struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, ui goto fail; } + pa_fd_set_cloexec(c->fd, 1); pa_socket_tcp_low_delay(c->fd); sa.sin_family = AF_INET; @@ -181,6 +182,7 @@ struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, co goto fail; } + pa_fd_set_cloexec(c->fd, 1); pa_socket_low_delay(c->fd); sa.sun_family = AF_LOCAL; @@ -208,6 +210,7 @@ struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m goto fail; } + pa_fd_set_cloexec(c->fd, 1); if (sa->sa_family == AF_INET) pa_socket_tcp_low_delay(c->fd); else diff --git a/polyp/socket-server.c b/polyp/socket-server.c index f01e417c4..131339eda 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -38,6 +38,7 @@ #include "socket-server.h" #include "socket-util.h" #include "xmalloc.h" +#include "util.h" struct pa_socket_server { int ref; @@ -65,6 +66,8 @@ static void callback(struct pa_mainloop_api *mainloop, struct pa_io_event *e, in goto finish; } + pa_fd_set_cloexec(nfd, 1); + if (!s->on_connection) { close(nfd); goto finish; @@ -122,6 +125,8 @@ struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, co goto fail; } + pa_fd_set_cloexec(fd, 1); + sa.sun_family = AF_LOCAL; strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); sa.sun_path[sizeof(sa.sun_path) - 1] = 0; @@ -166,6 +171,8 @@ struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, ui goto fail; } + pa_fd_set_cloexec(fd, 1); + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) fprintf(stderr, "setsockopt(): %s\n", strerror(errno)); diff --git a/polyp/socket-util.c b/polyp/socket-util.c index f9d0febfa..1f93ef881 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -217,3 +217,4 @@ finish: pa_xfree(dir); return ret; } + diff --git a/polyp/util.c b/polyp/util.c index 0d930118b..a3276fdfc 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -249,3 +249,18 @@ void pa_reset_priority(void) { setpriority(PRIO_PROCESS, 0, 0); } + +int pa_fd_set_cloexec(int fd, int b) { + int v; + assert(fd >= 0); + + if ((v = fcntl(fd, F_GETFD, 0)) < 0) + return -1; + + v = (v & ~FD_CLOEXEC) | (b ? FD_CLOEXEC : 0); + + if (fcntl(fd, F_SETFD, v) < 0) + return -1; + + return 0; +} diff --git a/polyp/util.h b/polyp/util.h index 89505cde2..f8dd3f046 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -44,4 +44,6 @@ uint32_t pa_age(struct timeval *tv); void pa_raise_priority(void); void pa_reset_priority(void); +int pa_fd_set_cloexec(int fd, int b); + #endif From c73a298f8887e5c96bc53dc1b2aad2fdbb674f64 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Sep 2004 22:46:27 +0000 Subject: [PATCH 0172/1514] add total sample cache size to statistics add size to sample cache entry info git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@175 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- polyp/polyplib-introspect.c | 4 +++- polyp/polyplib-introspect.h | 2 ++ polyp/protocol-native.c | 2 ++ polyp/scache.c | 15 +++++++++++++++ polyp/scache.h | 2 ++ 6 files changed, 25 insertions(+), 2 deletions(-) diff --git a/doc/todo b/doc/todo index 7c1cf71e0..49e9a88d0 100644 --- a/doc/todo +++ b/doc/todo @@ -11,11 +11,11 @@ - more complete pactl - cleanup tagstruct and modargs (add s32, pa_volume_t, pa_usec_t) - remove all gcc warnings -- add total sample cache size to stat - make fragments settings runtime configurable - logging - automatic termination of daemon if unused - add sample directory +- paman: show scache and sample size ** later *** - xmlrpc/http diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index e650fb9fe..a4ecf5ee6 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -46,6 +46,7 @@ static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uin pa_tagstruct_getu32(t, &i.memblock_total_size) < 0 || pa_tagstruct_getu32(t, &i.memblock_allocated) < 0 || pa_tagstruct_getu32(t, &i.memblock_allocated_size) < 0 || + pa_tagstruct_getu32(t, &i.scache_size) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; @@ -603,7 +604,8 @@ static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t c pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.volume) < 0 || pa_tagstruct_getu32(t, &i.duration) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0) { + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_getu32(t, &i.bytes) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 25a2db5e9..1cc79d0fd 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -180,6 +180,7 @@ struct pa_stat_info { uint32_t memblock_total_size; /**< Currentl total size of allocated memory blocks */ uint32_t memblock_allocated; /**< Allocated memory blocks during the whole lifetime of the daemon */ uint32_t memblock_allocated_size; /**< Total size of all memory blocks allocated during the whole lifetime of the daemon */ + uint32_t scache_size; /**< Total size of all sample cache entries. \since 0.4 */ }; /** Get daemon memory block statistics */ @@ -192,6 +193,7 @@ struct pa_sample_info { pa_volume_t volume; /**< Default volume of this entry */ struct pa_sample_spec sample_spec; /**< Sample specification of the sampel */ pa_usec_t duration; /**< Duration of this entry */ + uint32_t bytes; /**< Length of this sample in bytes. \since 0.4 */ }; /** Get information about a sample by its name */ diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 9dddf9a10..cce6cc6ca 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -797,6 +797,7 @@ static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total_size); pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated); pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated_size); + pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core)); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1044,6 +1045,7 @@ static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry pa_tagstruct_putu32(t, e->volume); pa_tagstruct_putu32(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec)); pa_tagstruct_put_sample_spec(t, &e->sample_spec); + pa_tagstruct_putu32(t, e->memchunk.length); } static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { diff --git a/polyp/scache.c b/polyp/scache.c index 311d68a42..b7a8ff026 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -168,3 +168,18 @@ uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { return e->index; } + +uint32_t pa_scache_total_size(struct pa_core *c) { + struct pa_scache_entry *e; + uint32_t index; + uint32_t sum; + + if (!c->scache) + return 0; + + for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) + sum += e->memchunk.length; + + + return sum; +} diff --git a/polyp/scache.h b/polyp/scache.h index 959067f37..cfd479b57 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -44,4 +44,6 @@ void pa_scache_free(struct pa_core *c); const char *pa_scache_get_name_by_id(struct pa_core *c, uint32_t id); uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name); +uint32_t pa_scache_total_size(struct pa_core *c); + #endif From 4a9239f808b08cf391ded6052bab9cc499e4b505 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 3 Sep 2004 20:14:23 +0000 Subject: [PATCH 0173/1514] add CPU load limiter git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@176 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 + polyp/Makefile.am | 14 +++- polyp/cpulimit-test.c | 84 +++++++++++++++++++ polyp/cpulimit.c | 175 ++++++++++++++++++++++++++++++++++++++++ polyp/cpulimit.h | 34 ++++++++ polyp/main.c | 49 ++++++++--- polyp/mainloop-signal.c | 43 +++++----- polyp/sample.c | 11 +++ polyp/sample.h | 3 + polyp/util.c | 17 ++-- 10 files changed, 392 insertions(+), 40 deletions(-) create mode 100644 polyp/cpulimit-test.c create mode 100644 polyp/cpulimit.c create mode 100644 polyp/cpulimit.h diff --git a/doc/todo b/doc/todo index 49e9a88d0..0da2a2e0d 100644 --- a/doc/todo +++ b/doc/todo @@ -16,6 +16,8 @@ - automatic termination of daemon if unused - add sample directory - paman: show scache and sample size +- add timing parameter to write callback of stream in client API +- add option for disabling module loading ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 923a35224..33b052f39 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -31,7 +31,7 @@ AM_LIBADD=$(PTHREAD_LIBS) -lm EXTRA_DIST = polypaudio.pa depmod.py esdcompat.sh.in bin_PROGRAMS = polypaudio pacat pactl bin_SCRIPTS = esdcompat.sh -noinst_PROGRAMS = mainloop-test mainloop-test-glib mainloop-test-glib12 pacat-simple parec-simple +noinst_PROGRAMS = mainloop-test mainloop-test-glib mainloop-test-glib12 pacat-simple parec-simple cpulimit-test cpulimit-test2 polypconf_DATA=polypaudio.pa @@ -142,7 +142,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ xmalloc.c xmalloc.h \ subscribe.h subscribe.c \ debug.h \ - sound-file-stream.c sound-file-stream.h + sound-file-stream.c sound-file-stream.h \ + cpulimit.c cpulimit.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) @@ -387,6 +388,15 @@ mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12.la +cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c +cpulimit_test_CFLAGS = $(AM_CFLAGS) +cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop.la + +cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c +cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 +cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop.la + + if BUILD_LIBPOLYPCORE polypinclude_HEADERS+=cli-command.h\ diff --git a/polyp/cpulimit-test.c b/polyp/cpulimit-test.c new file mode 100644 index 000000000..71c06ef7a --- /dev/null +++ b/polyp/cpulimit-test.c @@ -0,0 +1,84 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include +#include + +#include "cpulimit.h" +#include "mainloop.h" + +#ifdef TEST2 +#include "mainloop-signal.h" +#endif + +static time_t start; + +#ifdef TEST2 + +static void func(struct pa_mainloop_api *m, struct pa_signal_event *e, int sig, void *userdata) { + time_t now; + time(&now); + + if ((now - start) >= 30) { + m->quit(m, 1); + fprintf(stderr, "Test failed\n"); + } else + raise(SIGUSR1); +} + +#endif + +int main() { + struct pa_mainloop *m; + + m = pa_mainloop_new(); + assert(m); + + pa_cpu_limit_init(pa_mainloop_get_api(m)); + + time(&start); + +#ifdef TEST2 + pa_signal_init(pa_mainloop_get_api(m)); + pa_signal_new(SIGUSR1, func, NULL); + raise(SIGUSR1); + pa_mainloop_run(m, NULL); + pa_signal_done(); +#else + for (;;) { + time_t now; + time(&now); + + if ((now - start) >= 30) { + fprintf(stderr, "Test failed\n"); + break; + } + } +#endif + + pa_cpu_limit_done(); + + pa_mainloop_free(m); + +} diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c new file mode 100644 index 000000000..822e1f332 --- /dev/null +++ b/polyp/cpulimit.c @@ -0,0 +1,175 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpulimit.h" +#include "util.h" + +/* Utilize this much CPU time at most */ +#define CPUTIME_PERCENT 70 + +#define CPUTIME_INTERVAL_SOFT (5) +#define CPUTIME_INTERVAL_HARD (2) + +static time_t last_time = 0; +static int the_pipe[2] = {-1, -1}; +static struct pa_mainloop_api *api = NULL; +static struct pa_io_event *io_event = NULL; +static struct sigaction sigaction_prev; +static int installed = 0; + +static enum { + PHASE_IDLE, + PHASE_SOFT +} phase = PHASE_IDLE; + +static void reset_cpu_time(int t) { + int r; + long n; + struct rlimit rl; + struct rusage ru; + + r = getrusage(RUSAGE_SELF, &ru); + assert(r >= 0); + + n = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec + t; + + r = getrlimit(RLIMIT_CPU, &rl); + assert(r >= 0); + + rl.rlim_cur = n; + r = setrlimit(RLIMIT_CPU, &rl); + assert(r >= 0); +} + +static void write_err(const char *p) { + pa_loop_write(2, p, strlen(p)); +} + +static void signal_handler(int sig) { + assert(sig == SIGXCPU); + + if (phase == PHASE_IDLE) { + time_t now; + char t[256]; + + time(&now); + + snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100); + write_err(t); + + if (CPUTIME_INTERVAL_SOFT >= ((now-last_time)*(double)CPUTIME_PERCENT/100)) { + static const char c = 'X'; + + write_err("Soft CPU time limit exhausted, terminating.\n"); + + /* Try a soft cleanup */ + write(the_pipe[1], &c, sizeof(c)); + phase = PHASE_SOFT; + reset_cpu_time(CPUTIME_INTERVAL_HARD); + + } else { + + /* Everything's fine */ + reset_cpu_time(CPUTIME_INTERVAL_SOFT); + last_time = now; + } + + } else if (phase == PHASE_SOFT) { + write_err("Hard CPU time limit exhausted, terminating forcibly.\n"); + _exit(1); + } +} + +static void callback(struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) { + char c; + assert(m && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == the_pipe[0]); + read(the_pipe[0], &c, sizeof(c)); + m->quit(m, 1); +} + +int pa_cpu_limit_init(struct pa_mainloop_api *m) { + int r; + struct sigaction sa; + assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1); + + time(&last_time); + + if (pipe(the_pipe) < 0) { + fprintf(stderr, "pipe() failed: %s\n", strerror(errno)); + return -1; + } + + pa_make_nonblock_fd(the_pipe[0]); + pa_make_nonblock_fd(the_pipe[1]); + pa_fd_set_cloexec(the_pipe[0], 1); + pa_fd_set_cloexec(the_pipe[1], 1); + + api = m; + io_event = api->io_new(m, the_pipe[0], PA_IO_EVENT_INPUT, callback, NULL); + + phase = PHASE_IDLE; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + r = sigaction(SIGXCPU, &sa, &sigaction_prev); + assert(r >= 0); + + installed = 1; + + reset_cpu_time(CPUTIME_INTERVAL_SOFT); + + return 0; +} + +void pa_cpu_limit_done(void) { + int r; + + if (io_event) { + assert(api); + api->io_free(io_event); + io_event = NULL; + api = NULL; + } + + if (the_pipe[0] >= 0) + close(the_pipe[0]); + if (the_pipe[1] >= 0) + close(the_pipe[1]); + the_pipe[0] = the_pipe[1] = -1; + + if (installed) { + r = sigaction(SIGXCPU, &sigaction_prev, NULL); + assert(r >= 0); + installed = 0; + } +} diff --git a/polyp/cpulimit.h b/polyp/cpulimit.h new file mode 100644 index 000000000..6d13b6e58 --- /dev/null +++ b/polyp/cpulimit.h @@ -0,0 +1,34 @@ +#ifndef foocpulimithfoo +#define foocpulimithfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "mainloop-api.h" + +/* This kills the polypaudio process if it eats more than 70% of the + * CPU time. This is build around setrlimit() and SIGXCPU. It is handy + * in case of using SCHED_FIFO which may freeze the whole machine */ + +int pa_cpu_limit_init(struct pa_mainloop_api *m); +void pa_cpu_limit_done(void); + +#endif diff --git a/polyp/main.c b/polyp/main.c index 87265da64..eba15c35b 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -43,6 +43,7 @@ #include "util.h" #include "sioman.h" #include "xmalloc.h" +#include "cpulimit.h" static struct pa_mainloop *mainloop; @@ -54,15 +55,37 @@ static void drop_root(void) { } } -static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { - m->quit(m, 1); - fprintf(stderr, __FILE__": got signal.\n"); +static const char* signal_name(int s) { + switch(s) { + case SIGINT: return "SIGINT"; + case SIGTERM: return "SIGTERM"; + case SIGUSR1: return "SIGUSR1"; + case SIGUSR2: return "SIGUSR2"; + case SIGXCPU: return "SIGXCPU"; + case SIGPIPE: return "SIGPIPE"; + default: return "UNKNOWN SIGNAL"; + } } -static void aux_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { - struct pa_core *c = userdata; - assert(c); - pa_module_load(c, sig == SIGUSR1 ? "module-cli" : "module-cli-protocol-unix", NULL); +static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { + fprintf(stderr, __FILE__": got signal %s.\n", signal_name(sig)); + + switch (sig) { + case SIGUSR1: + pa_module_load(userdata, "module-cli", NULL); + return; + + case SIGUSR2: + pa_module_load(userdata, "module-cli-protocol-unix", NULL); + return; + + case SIGINT: + case SIGTERM: + default: + fprintf(stderr, "Exiting.\n"); + m->quit(m, 1); + return; + } } static void close_pipe(int p[2]) { @@ -157,16 +180,19 @@ int main(int argc, char *argv[]) { r = pa_signal_init(pa_mainloop_get_api(mainloop)); assert(r == 0); - pa_signal_new(SIGINT, exit_signal_callback, NULL); - pa_signal_new(SIGTERM, exit_signal_callback, NULL); + pa_signal_new(SIGINT, signal_callback, c); + pa_signal_new(SIGTERM, signal_callback, c); signal(SIGPIPE, SIG_IGN); c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); - pa_signal_new(SIGUSR1, aux_signal_callback, c); - pa_signal_new(SIGUSR2, aux_signal_callback, c); + pa_signal_new(SIGUSR1, signal_callback, c); + pa_signal_new(SIGUSR2, signal_callback, c); + r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop)); + assert(r == 0); + buf = pa_strbuf_new(); assert(buf); r = pa_cli_command_execute(c, cmdline->cli_commands, buf, &cmdline->fail, &cmdline->verbose); @@ -193,6 +219,7 @@ int main(int argc, char *argv[]) { pa_core_free(c); + pa_cpu_limit_done(); pa_signal_done(); pa_mainloop_free(mainloop); diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c index a16d84571..4746837bd 100644 --- a/polyp/mainloop-signal.c +++ b/polyp/mainloop-signal.c @@ -54,33 +54,31 @@ static void signal_handler(int sig) { } static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) { + ssize_t r; + int sig; + struct pa_signal_event*s; assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); - for (;;) { - ssize_t r; - int sig; - struct pa_signal_event*s; - if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { - if (errno == EAGAIN) - return; - - fprintf(stderr, "signal.c: read(): %s\n", strerror(errno)); + if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { + if (errno == EAGAIN) return; - } - if (r != sizeof(sig)) { - fprintf(stderr, "signal.c: short read()\n"); - return; - } - - for (s = signals; s; s = s->next) - if (s->sig == sig) { - assert(s->callback); - s->callback(a, s, sig, s->userdata); - break; - } + fprintf(stderr, "signal.c: read(): %s\n", strerror(errno)); + return; } + + if (r != sizeof(sig)) { + fprintf(stderr, "signal.c: short read()\n"); + return; + } + + for (s = signals; s; s = s->next) + if (s->sig == sig) { + assert(s->callback); + s->callback(a, s, sig, s->userdata); + break; + } } int pa_signal_init(struct pa_mainloop_api *a) { @@ -108,7 +106,8 @@ void pa_signal_done(void) { while (signals) pa_signal_free(signals); - api->io_free(io_event); + + api->io_free(io_event); io_event = NULL; close(signal_pipe[0]); diff --git a/polyp/sample.c b/polyp/sample.c index 6ec560003..747acf185 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -119,3 +119,14 @@ double pa_volume_to_dB(pa_volume_t v) { return 20*log10((double) v/PA_VOLUME_NORM); } + +void pa_bytes_snprint(char *s, size_t l, off_t v) { + if (v >= 1024*1024*1024) + snprintf(s, l, "%0.1f GB", (double) v/1024/1024/1024); + else if (v >= 1024*1024) + snprintf(s, l, "%0.1f MB", (double) v/1024/1024); + else if (v >= 1024) + snprintf(s, l, "%0.1f KB", (double) v/1024); + else + snprintf(s, l, "%u B", (unsigned) v); +} diff --git a/polyp/sample.h b/polyp/sample.h index a5479562b..0141a7cd1 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -116,6 +116,9 @@ double pa_volume_to_dB(pa_volume_t v); #define PA_DECIBEL_MININFTY (-200) #endif +/** Pretty print a byte size value. (i.e. "2.5 MB") */ +void pa_bytes_snprint(char *s, size_t l, off_t v); + PA_C_DECL_END #endif diff --git a/polyp/util.c b/polyp/util.c index a3276fdfc..061d57100 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -223,16 +223,23 @@ void pa_raise_priority(void) { fprintf(stderr, __FILE__": setpriority() failed: %s\n", strerror(errno)); else fprintf(stderr, __FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); - + #ifdef _POSIX_PRIORITY_SCHEDULING { struct sched_param sp; - sched_getparam(0, &sp); + + if (sched_getparam(0, &sp) < 0) { + fprintf(stderr, __FILE__": sched_getparam() failed: %s\n", strerror(errno)); + return; + } + sp.sched_priority = 1; - if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) + if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) { fprintf(stderr, __FILE__": sched_setscheduler() failed: %s\n", strerror(errno)); - else - fprintf(stderr, __FILE__": Successfully gained SCHED_FIFO scheduling.\n"); + return; + } + + fprintf(stderr, __FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); } #endif } From fb962b67dbeb54d1cdd453c6f902b7c679b9197f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 3 Sep 2004 22:44:55 +0000 Subject: [PATCH 0174/1514] add option to disallow module loading after startup git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@177 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - polyp/cmdline.c | 17 +++++++++++++---- polyp/cmdline.h | 2 +- polyp/core.c | 2 ++ polyp/core.h | 2 ++ polyp/cpulimit.c | 14 ++++++++++---- polyp/main.c | 3 +++ polyp/module.c | 3 +++ 8 files changed, 34 insertions(+), 10 deletions(-) diff --git a/doc/todo b/doc/todo index 0da2a2e0d..bfc29fab0 100644 --- a/doc/todo +++ b/doc/todo @@ -17,7 +17,6 @@ - add sample directory - paman: show scache and sample size - add timing parameter to write callback of stream in client API -- add option for disabling module loading ** later *** - xmlrpc/http diff --git a/polyp/cmdline.c b/polyp/cmdline.c index c07e7bdc5..265e0ec88 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -72,6 +72,7 @@ void pa_cmdline_help(const char *argv0) { " -C Open a command line on the running TTY\n" " -n Don't load configuration file (%s)\n" " -D Daemonize after loading the modules\n" + " -d Disallow module loading after startup\n" " -f Dont quit when the startup fails\n" " -v Verbose startup\n" " -h Show this help\n" @@ -88,13 +89,19 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { assert(argc && argv); cmdline = pa_xmalloc(sizeof(struct pa_cmdline)); - cmdline->daemonize = cmdline->help = cmdline->verbose = cmdline->high_priority = cmdline->stay_root = cmdline->version = 0; + cmdline->daemonize = + cmdline->help = + cmdline->verbose = + cmdline->high_priority = + cmdline->stay_root = + cmdline->version = + cmdline->disallow_module_loading = 0; cmdline->fail = 1; buf = pa_strbuf_new(); assert(buf); - while ((c = getopt(argc, argv, "L:F:CDhfvrRVn")) != -1) { + while ((c = getopt(argc, argv, "L:F:CDhfvrRVnd")) != -1) { switch (c) { case 'L': pa_strbuf_printf(buf, "load %s\n", optarg); @@ -127,9 +134,11 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { cmdline->version = 1; break; case 'n': - no_default_config_file =1; + no_default_config_file = 1; + break; + case 'd': + cmdline->disallow_module_loading = 1; break; - default: goto fail; } diff --git a/polyp/cmdline.h b/polyp/cmdline.h index 6a7f4dd7d..7330a7162 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -24,7 +24,7 @@ struct pa_cmdline { - int daemonize, help, fail, verbose, high_priority, stay_root, version; + int daemonize, help, fail, verbose, high_priority, stay_root, version, disallow_module_loading; char *cli_commands; }; diff --git a/polyp/core.c b/polyp/core.c index 908564c10..da6ace6a3 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -69,6 +69,8 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->subscriptions = NULL; c->memblock_stat = pa_memblock_stat_new(); + + c->disallow_module_loading = 0; pa_check_for_sigpipe(); diff --git a/polyp/core.h b/polyp/core.h index a297d4e0a..ffcd018bc 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -46,6 +46,8 @@ struct pa_core { struct pa_subscription *subscriptions; struct pa_memblock_stat *memblock_stat; + + int disallow_module_loading; }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c index 822e1f332..7d6fa8619 100644 --- a/polyp/cpulimit.c +++ b/polyp/cpulimit.c @@ -31,7 +31,7 @@ #include "cpulimit.h" #include "util.h" -/* Utilize this much CPU time at most */ +/* Utilize this much CPU time at maximum */ #define CPUTIME_PERCENT 70 #define CPUTIME_INTERVAL_SOFT (5) @@ -77,12 +77,17 @@ static void signal_handler(int sig) { if (phase == PHASE_IDLE) { time_t now; + +#ifdef PRINT_CPU_LOAD char t[256]; +#endif time(&now); +#ifdef PRINT_CPU_LOAD snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100); write_err(t); +#endif if (CPUTIME_INTERVAL_SOFT >= ((now-last_time)*(double)CPUTIME_PERCENT/100)) { static const char c = 'X'; @@ -115,7 +120,6 @@ static void callback(struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enu } int pa_cpu_limit_init(struct pa_mainloop_api *m) { - int r; struct sigaction sa; assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1); @@ -141,8 +145,10 @@ int pa_cpu_limit_init(struct pa_mainloop_api *m) { sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - r = sigaction(SIGXCPU, &sa, &sigaction_prev); - assert(r >= 0); + if (sigaction(SIGXCPU, &sa, &sigaction_prev) < 0) { + pa_cpu_limit_done(); + return -1; + } installed = 1; diff --git a/polyp/main.c b/polyp/main.c index eba15c35b..1c09276e2 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -211,6 +211,9 @@ int main(int argc, char *argv[]) { retval = 0; if (cmdline->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); + + c->disallow_module_loading = cmdline->disallow_module_loading; + fprintf(stderr, __FILE__": mainloop entry.\n"); if (pa_mainloop_run(mainloop, &retval) < 0) retval = 1; diff --git a/polyp/module.c b/polyp/module.c index eb8a8acd6..fc7149537 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -54,6 +54,9 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char assert(c && name); + if (c->disallow_module_loading) + goto fail; + m = pa_xmalloc(sizeof(struct pa_module)); m->name = pa_xstrdup(name); From 57e473b61cf373f8d9befb03d359b999eca4262b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 4 Sep 2004 00:27:36 +0000 Subject: [PATCH 0175/1514] add support for automatic termination of the daemon after the last client quit remove all gcc warnings add boolean types for tagstruct and modargs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@178 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 6 +---- polyp/client.c | 6 +++++ polyp/cmdline.c | 7 +++++- polyp/cmdline.h | 2 +- polyp/core.c | 28 ++++++++++++++++++++++ polyp/core.h | 6 +++++ polyp/main.c | 1 + polyp/modargs.c | 40 +++++++++++++++++++++++++++++++ polyp/modargs.h | 2 ++ polyp/module-native-protocol-fd.c | 2 +- polyp/module-oss-mmap.c | 9 +++---- polyp/module-oss.c | 11 +++++---- polyp/module-protocol-stub.c | 9 +++---- polyp/module.c | 5 +++- polyp/polyplib-def.h | 2 +- polyp/polyplib-introspect.c | 2 +- polyp/polyplib-introspect.h | 4 ++-- polyp/polyplib-stream.c | 2 +- polyp/protocol-native.c | 8 +++---- polyp/protocol-simple.c | 6 ++--- polyp/scache.c | 2 +- polyp/tagstruct.c | 30 +++++++++++++++++++++-- polyp/tagstruct.h | 2 ++ 23 files changed, 155 insertions(+), 37 deletions(-) diff --git a/doc/todo b/doc/todo index bfc29fab0..5a1a247c8 100644 --- a/doc/todo +++ b/doc/todo @@ -9,17 +9,13 @@ kill client/... autoload management - more complete pactl -- cleanup tagstruct and modargs (add s32, pa_volume_t, pa_usec_t) -- remove all gcc warnings -- make fragments settings runtime configurable - logging -- automatic termination of daemon if unused - add sample directory -- paman: show scache and sample size - add timing parameter to write callback of stream in client API ** later *** - xmlrpc/http +- dbus - slp/rendezvous - modinfo - make alsa modules use mmap diff --git a/polyp/client.c b/polyp/client.c index 0cb42466a..c7fb1e07d 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -51,6 +51,8 @@ struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, fprintf(stderr, "client: created %u \"%s\"\n", c->index, c->name); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); + + pa_core_check_quit(core); return c; } @@ -59,10 +61,14 @@ void pa_client_free(struct pa_client *c) { assert(c && c->core); pa_idxset_remove_by_data(c->core->clients, c, NULL); + + pa_core_check_quit(c->core); + fprintf(stderr, "client: freed %u \"%s\"\n", c->index, c->name); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_xfree(c->name); pa_xfree(c); + } void pa_client_kill(struct pa_client *c) { diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 265e0ec88..aba20af13 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -75,6 +75,7 @@ void pa_cmdline_help(const char *argv0) { " -d Disallow module loading after startup\n" " -f Dont quit when the startup fails\n" " -v Verbose startup\n" + " -X SECS Terminate the daemon after the last client quit and this time passed\n" " -h Show this help\n" " -V Show version\n", e, cfg); @@ -97,11 +98,12 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { cmdline->version = cmdline->disallow_module_loading = 0; cmdline->fail = 1; + cmdline->quit_after_last_client_time = -1; buf = pa_strbuf_new(); assert(buf); - while ((c = getopt(argc, argv, "L:F:CDhfvrRVnd")) != -1) { + while ((c = getopt(argc, argv, "L:F:CDhfvrRVndX:")) != -1) { switch (c) { case 'L': pa_strbuf_printf(buf, "load %s\n", optarg); @@ -139,6 +141,9 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { case 'd': cmdline->disallow_module_loading = 1; break; + case 'X': + cmdline->quit_after_last_client_time = atoi(optarg); + break; default: goto fail; } diff --git a/polyp/cmdline.h b/polyp/cmdline.h index 7330a7162..d1c438d1c 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -24,7 +24,7 @@ struct pa_cmdline { - int daemonize, help, fail, verbose, high_priority, stay_root, version, disallow_module_loading; + int daemonize, help, fail, verbose, high_priority, stay_root, version, disallow_module_loading, quit_after_last_client_time; char *cli_commands; }; diff --git a/polyp/core.c b/polyp/core.c index da6ace6a3..4362f0cb5 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -71,6 +71,9 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->memblock_stat = pa_memblock_stat_new(); c->disallow_module_loading = 0; + + c->quit_event = NULL; + c->quit_after_last_client_time = -1; pa_check_for_sigpipe(); @@ -102,6 +105,11 @@ void pa_core_free(struct pa_core *c) { pa_namereg_free(c); pa_autoload_free(c); pa_subscription_free_all(c); + + if (c->quit_event) { + c->mainloop->time_free(c->quit_event); + c->quit_event = NULL; + } pa_xfree(c->default_source_name); pa_xfree(c->default_sink_name); @@ -111,3 +119,23 @@ void pa_core_free(struct pa_core *c) { pa_xfree(c); } +static void quit_callback(struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata) { + struct pa_core *c = userdata; + assert(c->quit_event = e); + + m->quit(m, 0); +} + +void pa_core_check_quit(struct pa_core *c) { + assert(c); + + if (!c->quit_event && c->quit_after_last_client_time >= 0 && pa_idxset_ncontents(c->clients) == 0) { + struct timeval tv; + gettimeofday(&tv, NULL); + tv.tv_sec+= c->quit_after_last_client_time; + c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c); + } else if (c->quit_event && pa_idxset_ncontents(c->clients) > 0) { + c->mainloop->time_free(c->quit_event); + c->quit_event = NULL; + } +} diff --git a/polyp/core.h b/polyp/core.h index ffcd018bc..513d81729 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -48,9 +48,15 @@ struct pa_core { struct pa_memblock_stat *memblock_stat; int disallow_module_loading; + int quit_after_last_client_time; + + struct pa_time_event *quit_event; + }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); void pa_core_free(struct pa_core*c); +void pa_core_check_quit(struct pa_core *c); + #endif diff --git a/polyp/main.c b/polyp/main.c index 1c09276e2..0f88a76e9 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -213,6 +213,7 @@ int main(int argc, char *argv[]) { pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); c->disallow_module_loading = cmdline->disallow_module_loading; + c->quit_after_last_client_time = cmdline->quit_after_last_client_time; fprintf(stderr, __FILE__": mainloop entry.\n"); if (pa_mainloop_run(mainloop, &retval) < 0) diff --git a/polyp/modargs.c b/polyp/modargs.c index 87d99ad28..4874d808e 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -207,6 +207,46 @@ int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *v return 0; } +int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *value) { + const char *v; + char *e; + signed long l; + assert(ma && key && value); + + if (!(v = pa_modargs_get_value(ma, key, NULL))) + return 0; + + if (!*v) + return -1; + + l = strtol(v, &e, 0); + if (*e) + return -1; + + *value = (int32_t) l; + return 0; +} + +int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *value) { + const char *v; + assert(ma && key && value); + + if (!(v = pa_modargs_get_value(ma, key, NULL))) + return 0; + + if (!*v) + return -1; + + if (!strcmp(v, "1") || !strcasecmp(v, "yes") || !strcasecmp(v, "y") || !strcasecmp(v, "on")) + *value = 1; + else if (!strcmp(v, "0") || !strcasecmp(v, "no") || !strcasecmp(v, "n") || !strcasecmp(v, "off")) + *value = 0; + else + return -1; + + return 0; +} + int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss) { const char *format; uint32_t channels; diff --git a/polyp/modargs.h b/polyp/modargs.h index 872fb14f1..705d9f436 100644 --- a/polyp/modargs.h +++ b/polyp/modargs.h @@ -33,6 +33,8 @@ void pa_modargs_free(struct pa_modargs*ma); const char *pa_modargs_get_value(struct pa_modargs *ma, const char *key, const char *def); int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *value); +int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *value); +int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *value); int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *ss); diff --git a/polyp/module-native-protocol-fd.c b/polyp/module-native-protocol-fd.c index 58d09ffec..213e291ed 100644 --- a/polyp/module-native-protocol-fd.c +++ b/polyp/module-native-protocol-fd.c @@ -50,7 +50,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto finish; } - if (pa_modargs_get_value_u32(ma, "fd", &fd) < 0) { + if (pa_modargs_get_value_s32(ma, "fd", &fd) < 0) { fprintf(stderr, __FILE__": invalid file descriptor.\n"); goto finish; } diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 5c3be1ad4..8a0dd9a4b 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -234,20 +234,21 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto fail; } - if (pa_modargs_get_value_u32(ma, "record", &record) < 0 || pa_modargs_get_value_u32(ma, "playback", &playback) < 0) { + if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { fprintf(stderr, __FILE__": record= and playback= expect numeric arguments.\n"); goto fail; } - mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); - if (mode == 0) { + if (!playback && !record) { fprintf(stderr, __FILE__": neither playback nor record enabled for device.\n"); goto fail; } + mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); + nfrags = 12; frag_size = 1024; - if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) { + if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) { fprintf(stderr, __FILE__": failed to parse fragments arguments\n"); goto fail; } diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 403716fd8..4fd796245 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -177,7 +177,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { int fd = -1; int nfrags, frag_size, in_frag_size, out_frag_size; int mode; - uint32_t record = 1, playback = 1; + int record = 1, playback = 1; struct pa_sample_spec ss; struct pa_modargs *ma = NULL; assert(c && m); @@ -187,20 +187,21 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto fail; } - if (pa_modargs_get_value_u32(ma, "record", &record) < 0 || pa_modargs_get_value_u32(ma, "playback", &playback) < 0) { + if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { fprintf(stderr, __FILE__": record= and playback= expect numeric argument.\n"); goto fail; } - mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); - if (mode == 0) { + if (!playback && !record) { fprintf(stderr, __FILE__": neither playback nor record enabled for device.\n"); goto fail; } + mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); + nfrags = 12; frag_size = 1024; - if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) { + if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) { fprintf(stderr, __FILE__": failed to parse fragments arguments\n"); goto fail; } diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index e681732fb..4d86c28ec 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -83,15 +83,16 @@ static const char* const valid_modargs[] = { static struct pa_socket_server *create_socket_server(struct pa_core *c, struct pa_modargs *ma) { struct pa_socket_server *s; #ifdef USE_TCP_SOCKETS - uint32_t loopback = 1, port = IPV4_PORT; + int loopback = 1; + uint32_t port = IPV4_PORT; - if (pa_modargs_get_value_u32(ma, "loopback", &loopback) < 0) { + if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) { fprintf(stderr, "loopback= expects a numerical argument.\n"); return NULL; } - if (pa_modargs_get_value_u32(ma, "port", &port) < 0) { - fprintf(stderr, "port= expects a numerical argument.\n"); + if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { + fprintf(stderr, "port= expects a numerical argument between 1 and 65535.\n"); return NULL; } diff --git a/polyp/module.c b/polyp/module.c index fc7149537..a06b27541 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -117,6 +117,10 @@ fail: static void pa_module_free(struct pa_module *m) { assert(m && m->done && m->core); + + if (m->core->disallow_module_loading) + return; + m->done(m->core, m); lt_dlclose(m->dl); @@ -130,7 +134,6 @@ static void pa_module_free(struct pa_module *m) { pa_xfree(m); } - void pa_module_unload(struct pa_core *c, struct pa_module *m) { assert(c && m); diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 6c3cd825c..f0ecc5c46 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -140,7 +140,7 @@ struct pa_latency_info { pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play */ pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. */ int playing; /**< Non-zero when the stream is currently playing */ - int queue_length; /**< Queue size in bytes. */ + uint32_t queue_length; /**< Queue size in bytes. */ }; PA_C_DECL_END diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index a4ecf5ee6..b31a40c7a 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -331,7 +331,7 @@ static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t c pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_gets(t, &i.argument) < 0 || pa_tagstruct_getu32(t, &i.n_used) < 0 || - pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + pa_tagstruct_get_boolean(t, &i.auto_unload) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 1cc79d0fd..0a14fad09 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -106,8 +106,8 @@ struct pa_module_info { uint32_t index; /**< Index of the module */ const char*name, /**< Name of the module */ *argument; /**< Argument string of the module */ - uint32_t n_used, /**< Usage counter or PA_INVALID_INDEX */ - auto_unload; /**< Non-zero if this is an autoloaded module */ + uint32_t n_used; /**< Usage counter or PA_INVALID_INDEX */ + int auto_unload; /**< Non-zero if this is an autoloaded module */ }; /** Get some information about a module by its index */ diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 220e4a144..7170a32eb 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -329,7 +329,7 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman } else if (pa_tagstruct_getu32(t, &i.buffer_usec) < 0 || pa_tagstruct_getu32(t, &i.sink_usec) < 0 || - pa_tagstruct_getu32(t, &i.playing) < 0 || + pa_tagstruct_get_boolean(t, &i.playing) < 0 || pa_tagstruct_getu32(t, &i.queue_length) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index cce6cc6ca..2572810fb 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -830,7 +830,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma pa_tagstruct_putu32(reply, tag); pa_tagstruct_putu32(reply, pa_sink_input_get_latency(s->sink_input)); pa_tagstruct_putu32(reply, pa_sink_get_latency(s->sink_input->sink)); - pa_tagstruct_putu32(reply, pa_memblockq_is_readable(s->memblockq)); + pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq)); pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq)); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1012,7 +1012,7 @@ static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *modu pa_tagstruct_puts(t, module->name); pa_tagstruct_puts(t, module->argument ? module->argument : ""); pa_tagstruct_putu32(t, module->n_used); - pa_tagstruct_putu32(t, module->auto_unload); + pa_tagstruct_put_boolean(t, module->auto_unload); } static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_input *s) { @@ -1505,10 +1505,10 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struct pa_module *m, struct pa_modargs *ma) { struct pa_protocol_native *p; - uint32_t public; + int public; assert(c && ma); - if (pa_modargs_get_value_u32(ma, "public", &public) < 0) { + if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { fprintf(stderr, __FILE__": public= expects numeric argument.\n"); return NULL; } diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 41c1f4846..3ccb3068c 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -366,7 +366,7 @@ fail: struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { struct pa_protocol_simple* p = NULL; - uint32_t enable; + int enable; assert(core && server && ma); p = pa_xmalloc0(sizeof(struct pa_protocol_simple)); @@ -385,14 +385,14 @@ struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct p p->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); enable = 0; - if (pa_modargs_get_value_u32(ma, "record", &enable) < 0) { + if (pa_modargs_get_value_boolean(ma, "record", &enable) < 0) { fprintf(stderr, __FILE__": record= expects a numeric argument.\n"); goto fail; } p->mode = enable ? RECORD : 0; enable = 1; - if (pa_modargs_get_value_u32(ma, "playback", &enable) < 0) { + if (pa_modargs_get_value_boolean(ma, "playback", &enable) < 0) { fprintf(stderr, __FILE__": playback= expects a numeric argument.\n"); goto fail; } diff --git a/polyp/scache.c b/polyp/scache.c index b7a8ff026..53e8a3fe2 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -172,7 +172,7 @@ uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { uint32_t pa_scache_total_size(struct pa_core *c) { struct pa_scache_entry *e; uint32_t index; - uint32_t sum; + uint32_t sum = 0; if (!c->scache) return 0; diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 742f6b9cb..5aa79e6c2 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -40,7 +40,9 @@ enum tags { TAG_U8 = 'B', TAG_S8 = 'b', TAG_SAMPLE_SPEC = 'a', - TAG_ARBITRARY = 'x' + TAG_ARBITRARY = 'x', + TAG_BOOLEAN_TRUE = '1', + TAG_BOOLEAN_FALSE = '0', }; struct pa_tagstruct { @@ -125,7 +127,6 @@ void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample t->length += 7; } - void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) { assert(t && p); @@ -137,6 +138,13 @@ void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t le t->length += 5+length; } +void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b) { + assert(t); + extend(t, 1); + t->data[t->length] = b ? TAG_BOOLEAN_TRUE : TAG_BOOLEAN_FALSE; + t->length += 1; +} + int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) { int error = 0; size_t n; @@ -238,3 +246,21 @@ const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l) { return t->data; } +int pa_tagstruct_get_boolean(struct pa_tagstruct*t, int *b) { + assert(t && b); + + if (t->rindex+1 > t->length) + return -1; + + if (t->data[t->rindex] == TAG_BOOLEAN_TRUE) + *b = 1; + else if (t->data[t->rindex] == TAG_BOOLEAN_FALSE) + *b = 0; + else + return -1; + + t->rindex +=1; + return 0; +} + + diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index bcd7f456a..9a91ee962 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -38,12 +38,14 @@ void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i); void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c); void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss); void pa_tagstruct_put_arbitrary(struct pa_tagstruct*t, const void *p, size_t length); +void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b); int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s); int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i); int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c); int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss); int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length); +int pa_tagstruct_get_boolean(struct pa_tagstruct *t, int *b); int pa_tagstruct_eof(struct pa_tagstruct*t); const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l); From 6c4fd620408b3f14a1d4164d58db70df7a252674 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 5 Sep 2004 00:03:16 +0000 Subject: [PATCH 0176/1514] implement proper logging git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@179 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 5 +++- doc/todo | 1 - polyp/Makefile.am | 9 ++++-- polyp/authkey.c | 5 ++-- polyp/cli.c | 5 ++-- polyp/client.c | 7 +++-- polyp/cmdline.c | 20 +++++++++++-- polyp/cmdline.h | 13 ++++++++- polyp/core.h | 1 - polyp/cpulimit.c | 3 +- polyp/gcc-printf.h | 10 +++++++ polyp/log.c | 48 +++++++++++++++++++++++++++++++ polyp/log.h | 17 +++++++++++ polyp/main.c | 39 ++++++++++++++++--------- polyp/mainloop-signal.c | 7 +++-- polyp/mainloop.c | 5 ++-- polyp/memblockq.c | 7 +++-- polyp/module-alsa-sink.c | 23 ++++++++------- polyp/module-alsa-source.c | 21 +++++++------- polyp/module-cli.c | 5 ++-- polyp/module-native-protocol-fd.c | 5 ++-- polyp/module-oss-mmap.c | 39 +++++++++++++------------ polyp/module-oss.c | 25 ++++++++-------- polyp/module-pipe-sink.c | 15 +++++----- polyp/module-protocol-stub.c | 13 +++++---- polyp/module-sine.c | 7 +++-- polyp/module-x11-bell.c | 13 +++++---- polyp/module.c | 10 +++++-- polyp/oss-util.c | 17 +++++------ polyp/pdispatch.c | 5 ++-- polyp/polypaudio.pa | 2 +- polyp/polyplib-context.c | 11 +++---- polyp/polyplib-simple.c | 3 +- polyp/protocol-esound.c | 23 ++++++++------- polyp/protocol-native.c | 27 ++++++++--------- polyp/protocol-simple.c | 21 +++++++------- polyp/pstream.c | 7 +++-- polyp/sink-input.c | 5 ++-- polyp/sink.c | 5 ++-- polyp/socket-client.c | 15 +++++----- polyp/socket-server.c | 17 +++++------ polyp/socket-util.c | 7 +++-- polyp/sound-file-stream.c | 5 ++-- polyp/sound-file.c | 9 +++--- polyp/source-output.c | 3 +- polyp/source.c | 5 ++-- polyp/strbuf.h | 4 ++- polyp/subscribe.c | 25 ++++++++-------- polyp/util.c | 41 ++++++++++++++++++++------ polyp/util.h | 6 +++- 50 files changed, 416 insertions(+), 225 deletions(-) create mode 100644 polyp/gcc-printf.h create mode 100644 polyp/log.c create mode 100644 polyp/log.h diff --git a/configure.ac b/configure.ac index 7aa6c5d48..f221689d4 100644 --- a/configure.ac +++ b/configure.ac @@ -52,6 +52,7 @@ AM_CONDITIONAL(X_DISPLAY_MISSING, test "x$X_DISPLAY_MISSING" != "x") AC_C_CONST AC_TYPE_PID_T AC_TYPE_SIZE_T +AC_TYPE_OFF_T AC_HEADER_TIME # Checks for library functions. @@ -65,7 +66,9 @@ AC_FUNC_MMAP AC_FUNC_REALLOC AC_FUNC_SETPGRP AC_TYPE_SIGNAL -AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul]) +AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul pow strcasecmp]) +AC_FUNC_STAT +AC_HEADER_SYS_WAIT AC_C_BIGENDIAN diff --git a/doc/todo b/doc/todo index 5a1a247c8..8ae9e7399 100644 --- a/doc/todo +++ b/doc/todo @@ -9,7 +9,6 @@ kill client/... autoload management - more complete pactl -- logging - add sample directory - add timing parameter to write callback of stream in client API diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 33b052f39..335fa99a5 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -143,7 +143,9 @@ polypaudio_SOURCES = idxset.c idxset.h \ subscribe.h subscribe.c \ debug.h \ sound-file-stream.c sound-file-stream.h \ - cpulimit.c cpulimit.h + cpulimit.c cpulimit.h \ + log.c log.h \ + gcc-printf.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) @@ -329,7 +331,10 @@ libpolyp_la_SOURCES = polyplib.h \ polyplib-subscribe.c polyplib-subscribe.h \ polyplib-internal.h \ cdecl.h \ - llist.h + llist.h \ + log.c log.h \ + gcc-printf.h + libpolyp_la_CFLAGS = $(AM_CFLAGS) libpolyp_la_LDFLAGS = -version-info 0:0:0 diff --git a/polyp/authkey.c b/polyp/authkey.c index 3180b8fd2..bbc45c378 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -36,6 +36,7 @@ #include "authkey.h" #include "util.h" +#include "log.h" #define RANDOM_DEVICE "/dev/urandom" @@ -80,7 +81,7 @@ static int generate(const char *fn, void *data, size_t length) { } else { uint8_t *p; size_t l; - fprintf(stderr, "WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s, falling back to unsecure pseudo RNG.\n", strerror(errno)); + pa_log(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s, falling back to unsecure pseudo RNG.\n", strerror(errno)); srandom(time(NULL)); @@ -122,7 +123,7 @@ int pa_authkey_load(const char *path, void *data, size_t length) { } if (ret < 0) - fprintf(stderr, "Failed to load authorization key '%s': %s\n", path, (ret == -1) ? strerror(errno) : "file corrupt"); + pa_log(__FILE__": Failed to load authorization key '%s': %s\n", path, (ret == -1) ? strerror(errno) : "file corrupt"); return ret; } diff --git a/polyp/cli.c b/polyp/cli.c index 6fd2c2387..09e9855dc 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -42,6 +42,7 @@ #include "cli-text.h" #include "cli-command.h" #include "xmalloc.h" +#include "log.h" struct pa_cli { struct pa_core *core; @@ -103,7 +104,7 @@ static void client_kill(struct pa_client *client) { assert(client && client->userdata); c = client->userdata; - fprintf(stderr, "CLI client killed.\n"); + pa_log(__FILE__": CLI client killed.\n"); if (c->defer_kill) c->kill_requested = 1; else { @@ -119,7 +120,7 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) assert(line && c); if (!s) { - fprintf(stderr, "CLI got EOF from user.\n"); + pa_log(__FILE__": CLI got EOF from user.\n"); if (c->eof_callback) c->eof_callback(c, c->userdata); diff --git a/polyp/client.c b/polyp/client.c index c7fb1e07d..a544b4fe3 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -31,6 +31,7 @@ #include "client.h" #include "xmalloc.h" #include "subscribe.h" +#include "log.h" struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, char *name) { struct pa_client *c; @@ -49,7 +50,7 @@ struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, r = pa_idxset_put(core->clients, c, &c->index); assert(c->index != PA_IDXSET_INVALID && r >= 0); - fprintf(stderr, "client: created %u \"%s\"\n", c->index, c->name); + pa_log(__FILE__": created %u \"%s\"\n", c->index, c->name); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); pa_core_check_quit(core); @@ -64,7 +65,7 @@ void pa_client_free(struct pa_client *c) { pa_core_check_quit(c->core); - fprintf(stderr, "client: freed %u \"%s\"\n", c->index, c->name); + pa_log(__FILE__": freed %u \"%s\"\n", c->index, c->name); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_xfree(c->name); pa_xfree(c); @@ -74,7 +75,7 @@ void pa_client_free(struct pa_client *c) { void pa_client_kill(struct pa_client *c) { assert(c); if (!c->kill) { - fprintf(stderr, "kill() operation not implemented for client %u\n", c->index); + pa_log(__FILE__": kill() operation not implemented for client %u\n", c->index); return; } diff --git a/polyp/cmdline.c b/polyp/cmdline.c index aba20af13..1d6501859 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -77,6 +77,7 @@ void pa_cmdline_help(const char *argv0) { " -v Verbose startup\n" " -X SECS Terminate the daemon after the last client quit and this time passed\n" " -h Show this help\n" + " -l TARGET Specify the log target (syslog, stderr, auto)\n" " -V Show version\n", e, cfg); pa_xfree(cfg); @@ -97,13 +98,14 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { cmdline->stay_root = cmdline->version = cmdline->disallow_module_loading = 0; - cmdline->fail = 1; + cmdline->fail = cmdline->auto_log_target = 1; cmdline->quit_after_last_client_time = -1; + cmdline->log_target = -1; buf = pa_strbuf_new(); assert(buf); - while ((c = getopt(argc, argv, "L:F:CDhfvrRVndX:")) != -1) { + while ((c = getopt(argc, argv, "L:F:CDhfvrRVndX:l:")) != -1) { switch (c) { case 'L': pa_strbuf_printf(buf, "load %s\n", optarg); @@ -144,6 +146,20 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { case 'X': cmdline->quit_after_last_client_time = atoi(optarg); break; + case 'l': + if (!strcmp(optarg, "syslog")) { + cmdline->auto_log_target = 0; + cmdline->log_target = PA_LOG_SYSLOG; + } else if (!strcmp(optarg, "stderr")) { + cmdline->auto_log_target = 0; + cmdline->log_target = PA_LOG_STDERR; + } else if (!strcmp(optarg, "auto")) + cmdline->auto_log_target = 1; + else { + pa_log(__FILE__": Invalid log target: use either 'syslog', 'stderr' or 'auto'.\n"); + goto fail; + } + break; default: goto fail; } diff --git a/polyp/cmdline.h b/polyp/cmdline.h index d1c438d1c..d49b65fbd 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -22,10 +22,21 @@ USA. ***/ +#include "log.h" struct pa_cmdline { - int daemonize, help, fail, verbose, high_priority, stay_root, version, disallow_module_loading, quit_after_last_client_time; + int daemonize, + help, + fail, + verbose, + high_priority, + stay_root, + version, + disallow_module_loading, + quit_after_last_client_time, + auto_log_target; char *cli_commands; + enum pa_log_target log_target; }; struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []); diff --git a/polyp/core.h b/polyp/core.h index 513d81729..ca37507ca 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -51,7 +51,6 @@ struct pa_core { int quit_after_last_client_time; struct pa_time_event *quit_event; - }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c index 7d6fa8619..fc49f5bb4 100644 --- a/polyp/cpulimit.c +++ b/polyp/cpulimit.c @@ -30,6 +30,7 @@ #include "cpulimit.h" #include "util.h" +#include "log.h" /* Utilize this much CPU time at maximum */ #define CPUTIME_PERCENT 70 @@ -126,7 +127,7 @@ int pa_cpu_limit_init(struct pa_mainloop_api *m) { time(&last_time); if (pipe(the_pipe) < 0) { - fprintf(stderr, "pipe() failed: %s\n", strerror(errno)); + pa_log(__FILE__": pipe() failed: %s\n", strerror(errno)); return -1; } diff --git a/polyp/gcc-printf.h b/polyp/gcc-printf.h new file mode 100644 index 000000000..224552af8 --- /dev/null +++ b/polyp/gcc-printf.h @@ -0,0 +1,10 @@ +#ifndef foogccprintfhfoo +#define foogccprintfhfoo + +#ifdef __GNUC__ +#define PA_GCC_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b))) +#else +#define PA_GCC_PRINTF_ATTR(a,b) +#endif + +#endif diff --git a/polyp/log.c b/polyp/log.c new file mode 100644 index 000000000..413266dfd --- /dev/null +++ b/polyp/log.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +#include "log.h" +#include "xmalloc.h" +#include "util.h" + +static char *log_ident = NULL; +static enum pa_log_target log_target = PA_LOG_STDERR; +static void (*user_log_func)(const char *s) = NULL; + +void pa_log_set_ident(const char *p) { + if (log_ident) + pa_xfree(log_ident); + + log_ident = pa_xstrdup(p); +} + +void pa_log_set_target(enum pa_log_target t, void (*func)(const char*s)) { + assert(t == PA_LOG_USER || !func); + log_target = t; + user_log_func = func; +} + +void pa_log(const char *format, ...) { + va_list ap; + va_start(ap, format); + + switch (log_target) { + case PA_LOG_STDERR: + vfprintf(stderr, format, ap); + break; + case PA_LOG_SYSLOG: + openlog(log_ident ? log_ident : "???", LOG_PID, LOG_USER); + vsyslog(LOG_INFO, format, ap); + closelog(); + break; + case PA_LOG_USER: { + char *t = pa_vsprintf_malloc(format, ap); + assert(user_log_func); + user_log_func(t); + } + } + + va_end(ap); +} diff --git a/polyp/log.h b/polyp/log.h new file mode 100644 index 000000000..1f2c74ef9 --- /dev/null +++ b/polyp/log.h @@ -0,0 +1,17 @@ +#ifndef foologhfoo +#define foologhfoo + +#include "gcc-printf.h" + +enum pa_log_target { + PA_LOG_SYSLOG, + PA_LOG_STDERR, + PA_LOG_USER, +}; + +void pa_log_set_ident(const char *p); +void pa_log_set_target(enum pa_log_target t, void (*func)(const char*s)); + +void pa_log(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); + +#endif diff --git a/polyp/main.c b/polyp/main.c index 0f88a76e9..29a7b548e 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -44,12 +44,13 @@ #include "sioman.h" #include "xmalloc.h" #include "cpulimit.h" +#include "log.h" static struct pa_mainloop *mainloop; static void drop_root(void) { if (getuid() != 0 && geteuid() == 0) { - fprintf(stderr, __FILE__": started SUID root, dropping root rights.\n"); + pa_log(__FILE__": Started SUID root, dropping root rights.\n"); setuid(getuid()); seteuid(getuid()); } @@ -68,7 +69,7 @@ static const char* signal_name(int s) { } static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { - fprintf(stderr, __FILE__": got signal %s.\n", signal_name(sig)); + pa_log(__FILE__": Got signal %s.\n", signal_name(sig)); switch (sig) { case SIGUSR1: @@ -82,7 +83,7 @@ static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, case SIGINT: case SIGTERM: default: - fprintf(stderr, "Exiting.\n"); + pa_log(__FILE__": Exiting.\n"); m->quit(m, 1); return; } @@ -104,11 +105,15 @@ int main(int argc, char *argv[]) { int r, retval = 1; int daemon_pipe[2] = { -1, -1 }; + pa_log_set_ident("polypaudio"); + if (!(cmdline = pa_cmdline_parse(argc, argv))) { - fprintf(stderr, __FILE__": failed to parse command line.\n"); + pa_log(__FILE__": failed to parse command line.\n"); goto finish; } + pa_log_set_target(cmdline->auto_log_target ? PA_LOG_STDERR : cmdline->log_target, NULL); + if (cmdline->help) { pa_cmdline_help(argv[0]); retval = 0; @@ -131,17 +136,17 @@ int main(int argc, char *argv[]) { pid_t child; if (pa_stdio_acquire() < 0) { - fprintf(stderr, __FILE__": failed to acquire stdio.\n"); + pa_log(__FILE__": failed to acquire stdio.\n"); goto finish; } if (pipe(daemon_pipe) < 0) { - fprintf(stderr, __FILE__": failed to create pipe.\n"); + pa_log(__FILE__": failed to create pipe.\n"); goto finish; } if ((child = fork()) < 0) { - fprintf(stderr, __FILE__": fork() failed: %s\n", strerror(errno)); + pa_log(__FILE__": fork() failed: %s\n", strerror(errno)); goto finish; } @@ -152,7 +157,7 @@ int main(int argc, char *argv[]) { daemon_pipe[1] = -1; if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval)) != sizeof(retval)) { - fprintf(stderr, __FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); retval = 1; } @@ -162,6 +167,10 @@ int main(int argc, char *argv[]) { close(daemon_pipe[0]); daemon_pipe[0] = -1; + + if (cmdline->auto_log_target) + pa_log_set_target(PA_LOG_SYSLOG, NULL); + setsid(); setpgrp(); @@ -196,15 +205,15 @@ int main(int argc, char *argv[]) { buf = pa_strbuf_new(); assert(buf); r = pa_cli_command_execute(c, cmdline->cli_commands, buf, &cmdline->fail, &cmdline->verbose); - fprintf(stderr, s = pa_strbuf_tostring_free(buf)); + pa_log(s = pa_strbuf_tostring_free(buf)); pa_xfree(s); if (r < 0 && cmdline->fail) { - fprintf(stderr, __FILE__": failed to initialize daemon.\n"); + pa_log(__FILE__": failed to initialize daemon.\n"); if (cmdline->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); } else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) { - fprintf(stderr, __FILE__": daemon startup without any loaded modules, refusing to work.\n"); + pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n"); if (cmdline->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); } else { @@ -215,10 +224,10 @@ int main(int argc, char *argv[]) { c->disallow_module_loading = cmdline->disallow_module_loading; c->quit_after_last_client_time = cmdline->quit_after_last_client_time; - fprintf(stderr, __FILE__": mainloop entry.\n"); + pa_log(__FILE__": Daemon startup complete.\n"); if (pa_mainloop_run(mainloop, &retval) < 0) retval = 1; - fprintf(stderr, __FILE__": mainloop exit.\n"); + pa_log(__FILE__": Daemon shutdown initiated.\n"); } pa_core_free(c); @@ -229,12 +238,14 @@ int main(int argc, char *argv[]) { lt_dlexit(); + pa_log(__FILE__": Daemon terminated.\n"); + finish: if (cmdline) pa_cmdline_free(cmdline); close_pipe(daemon_pipe); - + return retval; } diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c index 4746837bd..d7ee5010e 100644 --- a/polyp/mainloop-signal.c +++ b/polyp/mainloop-signal.c @@ -34,6 +34,7 @@ #include "mainloop-signal.h" #include "util.h" #include "xmalloc.h" +#include "log.h" struct pa_signal_event { int sig; @@ -64,12 +65,12 @@ static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enu if (errno == EAGAIN) return; - fprintf(stderr, "signal.c: read(): %s\n", strerror(errno)); + pa_log(__FILE__": read(): %s\n", strerror(errno)); return; } if (r != sizeof(sig)) { - fprintf(stderr, "signal.c: short read()\n"); + pa_log(__FILE__": short read()\n"); return; } @@ -85,7 +86,7 @@ int pa_signal_init(struct pa_mainloop_api *a) { assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event); if (pipe(signal_pipe) < 0) { - fprintf(stderr, "pipe() failed: %s\n", strerror(errno)); + pa_log(__FILE__": pipe() failed: %s\n", strerror(errno)); return -1; } diff --git a/polyp/mainloop.c b/polyp/mainloop.c index 83f0b1e82..22cd85c8d 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -37,6 +37,7 @@ #include "util.h" #include "idxset.h" #include "xmalloc.h" +#include "log.h" struct pa_io_event { struct pa_mainloop *mainloop; @@ -502,7 +503,7 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { do { int t = block ? calc_next_timeout(m) : 0; - /*fprintf(stderr, "%u\n", t);*/ + /*pa_log(__FILE__": %u\n", t);*/ r = poll(m->pollfds, m->n_pollfds, t); } while (r < 0 && errno == EINTR); @@ -511,7 +512,7 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { if (r > 0) dispatch_pollfds(m); else if (r < 0) - fprintf(stderr, "select(): %s\n", strerror(errno)); + pa_log(__FILE__": select(): %s\n", strerror(errno)); m->running = 0; return r < 0 ? -1 : 0; diff --git a/polyp/memblockq.c b/polyp/memblockq.c index 7feb4685f..0bba65817 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -32,6 +32,7 @@ #include "memblockq.h" #include "xmalloc.h" +#include "log.h" struct memblock_list { struct memblock_list *next, *prev; @@ -56,7 +57,7 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b bq->current_length = 0; - /*fprintf(stderr, "memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq);*/ + /*pa_log(__FILE__": memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq);*/ bq->base = base; @@ -76,7 +77,7 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b if (bq->minreq == 0) bq->minreq = 1; - fprintf(stderr, "memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); + pa_log(__FILE__": memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); bq->mcalign = NULL; @@ -206,7 +207,7 @@ void pa_memblockq_shorten(struct pa_memblockq *bq, size_t length) { if (bq->current_length <= length) return; - fprintf(stderr, "Warning! pa_memblockq_shorten()\n"); + pa_log(__FILE__": Warning! pa_memblockq_shorten()\n"); l = bq->current_length - length; l /= bq->base; diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 0c9d77b80..9c75ff982 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -38,6 +38,7 @@ #include "sample-util.h" #include "alsa-util.h" #include "xmalloc.h" +#include "log.h" struct userdata { snd_pcm_t *pcm_handle; @@ -73,10 +74,10 @@ static void update_usage(struct userdata *u) { static void xrun_recovery(struct userdata *u) { assert(u); - fprintf(stderr, "*** ALSA-XRUN (playback) ***\n"); + pa_log(__FILE__": *** ALSA-XRUN (playback) ***\n"); if (snd_pcm_prepare(u->pcm_handle) < 0) - fprintf(stderr, "snd_pcm_prepare() failed\n"); + pa_log(__FILE__": snd_pcm_prepare() failed\n"); } static void do_write(struct userdata *u) { @@ -108,7 +109,7 @@ static void do_write(struct userdata *u) { continue; } - fprintf(stderr, "snd_pcm_writei() failed\n"); + pa_log(__FILE__": snd_pcm_writei() failed\n"); return; } @@ -144,7 +145,7 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { assert(s && u && u->sink); if (snd_pcm_delay(u->pcm_handle, &frames) < 0) { - fprintf(stderr, __FILE__": failed to get delay\n"); + pa_log(__FILE__": failed to get delay\n"); s->get_latency = NULL; return 0; } @@ -166,13 +167,13 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { size_t frame_size; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - fprintf(stderr, __FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments\n"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - fprintf(stderr, __FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification\n"); goto fail; } frame_size = pa_frame_size(&ss); @@ -180,7 +181,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { periods = 12; fragsize = 1024; if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { - fprintf(stderr, __FILE__": failed to parse buffer metrics\n"); + pa_log(__FILE__": failed to parse buffer metrics\n"); goto fail; } buffer_size = fragsize/frame_size*periods; @@ -190,12 +191,12 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->module = m; if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) { - fprintf(stderr, __FILE__": Error opening PCM device %s\n", dev); + pa_log(__FILE__": Error opening PCM device %s\n", dev); goto fail; } if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &buffer_size) < 0) { - fprintf(stderr, __FILE__": Failed to set hardware parameters\n"); + pa_log(__FILE__": Failed to set hardware parameters\n"); goto fail; } @@ -208,14 +209,14 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { - fprintf(stderr, __FILE__": failed to obtain file descriptors\n"); + pa_log(__FILE__": failed to obtain file descriptors\n"); goto fail; } u->frame_size = frame_size; u->fragment_size = buffer_size*u->frame_size/periods; - fprintf(stderr, __FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); + pa_log(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size, c->memblock_stat); assert(u->silence.memblock); diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 13df9f960..520b68300 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -38,6 +38,7 @@ #include "sample-util.h" #include "alsa-util.h" #include "xmalloc.h" +#include "log.h" struct userdata { snd_pcm_t *pcm_handle; @@ -72,10 +73,10 @@ static void update_usage(struct userdata *u) { static void xrun_recovery(struct userdata *u) { assert(u); - fprintf(stderr, "*** ALSA-XRUN (capture) ***\n"); + pa_log(__FILE__": *** ALSA-XRUN (capture) ***\n"); if (snd_pcm_prepare(u->pcm_handle) < 0) - fprintf(stderr, "snd_pcm_prepare() failed\n"); + pa_log(__FILE__": snd_pcm_prepare() failed\n"); } static void do_read(struct userdata *u) { @@ -104,7 +105,7 @@ static void do_read(struct userdata *u) { continue; } - fprintf(stderr, "snd_pcm_readi() failed: %s\n", strerror(-frames)); + pa_log(__FILE__": snd_pcm_readi() failed: %s\n", strerror(-frames)); return; } @@ -149,13 +150,13 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { size_t frame_size; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - fprintf(stderr, __FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments\n"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - fprintf(stderr, __FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification\n"); goto fail; } frame_size = pa_frame_size(&ss); @@ -163,7 +164,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { periods = 12; fragsize = 1024; if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { - fprintf(stderr, __FILE__": failed to parse buffer metrics\n"); + pa_log(__FILE__": failed to parse buffer metrics\n"); goto fail; } buffer_size = fragsize/frame_size*periods; @@ -173,12 +174,12 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->module = m; if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) < 0) { - fprintf(stderr, __FILE__": Error opening PCM device %s\n", dev); + pa_log(__FILE__": Error opening PCM device %s\n", dev); goto fail; } if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &buffer_size) < 0) { - fprintf(stderr, __FILE__": Failed to set hardware parameters\n"); + pa_log(__FILE__": Failed to set hardware parameters\n"); goto fail; } @@ -190,14 +191,14 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { - fprintf(stderr, __FILE__": failed to obtain file descriptors\n"); + pa_log(__FILE__": failed to obtain file descriptors\n"); goto fail; } u->frame_size = frame_size; u->fragment_size = buffer_size*u->frame_size/periods; - fprintf(stderr, __FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); + pa_log(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); u->memchunk.memblock = NULL; u->memchunk.index = u->memchunk.length = 0; diff --git a/polyp/module-cli.c b/polyp/module-cli.c index 8897c9c63..9a08a00d9 100644 --- a/polyp/module-cli.c +++ b/polyp/module-cli.c @@ -31,6 +31,7 @@ #include "iochannel.h" #include "cli.h" #include "sioman.h" +#include "log.h" static void eof_cb(struct pa_cli*c, void *userdata) { struct pa_module *m = userdata; @@ -44,12 +45,12 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(c && m); if (m->argument) { - fprintf(stderr, __FILE__": module doesn't accept arguments.\n"); + pa_log(__FILE__": module doesn't accept arguments.\n"); return -1; } if (pa_stdio_acquire() < 0) { - fprintf(stderr, __FILE__": STDIN/STDUSE already in use.\n"); + pa_log(__FILE__": STDIN/STDUSE already in use.\n"); return -1; } diff --git a/polyp/module-native-protocol-fd.c b/polyp/module-native-protocol-fd.c index 213e291ed..632a3d713 100644 --- a/polyp/module-native-protocol-fd.c +++ b/polyp/module-native-protocol-fd.c @@ -31,6 +31,7 @@ #include "iochannel.h" #include "modargs.h" #include "protocol-native.h" +#include "log.h" static const char* const valid_modargs[] = { "fd", @@ -46,12 +47,12 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - fprintf(stderr, __FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments.\n"); goto finish; } if (pa_modargs_get_value_s32(ma, "fd", &fd) < 0) { - fprintf(stderr, __FILE__": invalid file descriptor.\n"); + pa_log(__FILE__": invalid file descriptor.\n"); goto finish; } diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 8a0dd9a4b..8151a13af 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -45,6 +45,7 @@ #include "util.h" #include "modargs.h" #include "xmalloc.h" +#include "log.h" struct userdata { struct pa_sink *sink; @@ -122,7 +123,7 @@ static void do_write(struct userdata *u) { update_usage(u); if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { - fprintf(stderr, "SNDCTL_DSP_GETOPTR: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s\n", strerror(errno)); return; } @@ -184,7 +185,7 @@ static void do_read(struct userdata *u) { update_usage(u); if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { - fprintf(stderr, "SNDCTL_DSP_GETIPTR: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s\n", strerror(errno)); return; } @@ -230,17 +231,17 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->core = c; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - fprintf(stderr, __FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments.\n"); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - fprintf(stderr, __FILE__": record= and playback= expect numeric arguments.\n"); + pa_log(__FILE__": record= and playback= expect numeric arguments.\n"); goto fail; } if (!playback && !record) { - fprintf(stderr, __FILE__": neither playback nor record enabled for device.\n"); + pa_log(__FILE__": neither playback nor record enabled for device.\n"); goto fail; } @@ -249,13 +250,13 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { nfrags = 12; frag_size = 1024; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) { - fprintf(stderr, __FILE__": failed to parse fragments arguments\n"); + pa_log(__FILE__": failed to parse fragments arguments\n"); goto fail; } u->sample_spec = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &u->sample_spec) < 0) { - fprintf(stderr, __FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification\n"); goto fail; } @@ -263,11 +264,11 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto fail; if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_REALTIME) || !(caps & DSP_CAP_TRIGGER)) { - fprintf(stderr, "OSS device not mmap capable.\n"); + pa_log(__FILE__": OSS device not mmap capable.\n"); goto fail; } - fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0) goto fail; @@ -277,19 +278,19 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { if (mode != O_WRONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { - fprintf(stderr, "SNDCTL_DSP_GETISPACE: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETISPACE: %s\n", strerror(errno)); goto fail; } - fprintf(stderr, "module-oss-mmap: input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log(__FILE__": input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); u->in_mmap_length = (u->in_fragment_size = info.fragsize) * (u->in_fragments = info.fragstotal); if ((u->in_mmap = mmap(NULL, u->in_mmap_length, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { if (mode == O_RDWR) { - fprintf(stderr, "module-oss-mmap: mmap failed for input. Changing to O_WRONLY mode.\n"); + pa_log(__FILE__": mmap failed for input. Changing to O_WRONLY mode.\n"); mode = O_WRONLY; } else { - fprintf(stderr, "modeule-oss-mmap: mmap(): %s\n", strerror(errno)); + pa_log(__FILE__": mmap(): %s\n", strerror(errno)); goto fail; } } else { @@ -308,19 +309,19 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { if (mode != O_RDONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { - fprintf(stderr, "SNDCTL_DSP_GETOSPACE: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETOSPACE: %s\n", strerror(errno)); goto fail; } - fprintf(stderr, "module-oss: output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log(__FILE__": output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); u->out_mmap_length = (u->out_fragment_size = info.fragsize) * (u->out_fragments = info.fragstotal); if ((u->out_mmap = mmap(NULL, u->out_mmap_length, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { if (mode == O_RDWR) { - fprintf(stderr, "module-oss-mmap: mmap filed for output. Changing to O_RDONLY mode.\n"); + pa_log(__FILE__": mmap filed for output. Changing to O_RDONLY mode.\n"); mode = O_RDONLY; } else { - fprintf(stderr, "module-oss-mmap: mmap(): %s\n", strerror(errno)); + pa_log(__FILE__": mmap(): %s\n", strerror(errno)); goto fail; } } else { @@ -341,12 +342,12 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { zero = 0; if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero) < 0) { - fprintf(stderr, "SNDCTL_DSP_SETTRIGGER: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s\n", strerror(errno)); goto fail; } if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0) { - fprintf(stderr, "SNDCTL_DSP_SETTRIGGER: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s\n", strerror(errno)); goto fail; } diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 4fd796245..53f1f994d 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -44,6 +44,7 @@ #include "util.h" #include "modargs.h" #include "xmalloc.h" +#include "log.h" struct userdata { struct pa_sink *sink; @@ -105,7 +106,7 @@ static void do_write(struct userdata *u) { assert(memchunk->length); if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { - fprintf(stderr, "write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); return; } @@ -137,7 +138,7 @@ static void do_read(struct userdata *u) { if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) - fprintf(stderr, "read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); return; } @@ -162,7 +163,7 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { assert(s && u && u->sink); if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) { - fprintf(stderr, "module-oss: device doesn't support SNDCTL_DSP_GETODELAY.\n"); + pa_log(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY.\n"); s->get_latency = NULL; return 0; } @@ -183,17 +184,17 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - fprintf(stderr, __FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments.\n"); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - fprintf(stderr, __FILE__": record= and playback= expect numeric argument.\n"); + pa_log(__FILE__": record= and playback= expect numeric argument.\n"); goto fail; } if (!playback && !record) { - fprintf(stderr, __FILE__": neither playback nor record enabled for device.\n"); + pa_log(__FILE__": neither playback nor record enabled for device.\n"); goto fail; } @@ -202,20 +203,20 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { nfrags = 12; frag_size = 1024; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) { - fprintf(stderr, __FILE__": failed to parse fragments arguments\n"); + pa_log(__FILE__": failed to parse fragments arguments\n"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - fprintf(stderr, __FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification\n"); goto fail; } if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, NULL)) < 0) goto fail; - fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) goto fail; @@ -224,19 +225,19 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { goto fail; if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) { - fprintf(stderr, "SNDCTL_DSP_GETBLKSIZE: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETBLKSIZE: %s\n", strerror(errno)); goto fail; } assert(frag_size); in_frag_size = out_frag_size = frag_size; if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { - fprintf(stderr, "module-oss: input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log(__FILE__": input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); in_frag_size = info.fragsize; } if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { - fprintf(stderr, "module-oss: output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log(__FILE__": output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); out_frag_size = info.fragsize; } diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index 088ed405d..5f1ced03b 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -39,6 +39,7 @@ #include "util.h" #include "modargs.h" #include "xmalloc.h" +#include "log.h" #define DEFAULT_FIFO_NAME "/tmp/musicfifo" #define DEFAULT_SINK_NAME "fifo_output" @@ -83,7 +84,7 @@ static void do_write(struct userdata *u) { assert(u->memchunk.memblock && u->memchunk.length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { - fprintf(stderr, "write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); return; } @@ -126,32 +127,32 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - fprintf(stderr, __FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments\n"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - fprintf(stderr, __FILE__": invalid sample format specification\n"); + pa_log(__FILE__": invalid sample format specification\n"); goto fail; } mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); if ((fd = open(p, O_RDWR)) < 0) { - fprintf(stderr, __FILE__": open('%s'): %s\n", p, strerror(errno)); + pa_log(__FILE__": open('%s'): %s\n", p, strerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); if (fstat(fd, &st) < 0) { - fprintf(stderr, __FILE__": fstat('%s'): %s\n", p, strerror(errno)); + pa_log(__FILE__": fstat('%s'): %s\n", p, strerror(errno)); goto fail; } if (!S_ISFIFO(st.st_mode)) { - fprintf(stderr, __FILE__": '%s' is not a FIFO.\n", p); + pa_log(__FILE__": '%s' is not a FIFO.\n", p); goto fail; } @@ -161,7 +162,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->core = c; if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { - fprintf(stderr, __FILE__": failed to create sink.\n"); + pa_log(__FILE__": failed to create sink.\n"); goto fail; } u->sink->notify = notify_cb; diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 4d86c28ec..686e21297 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -35,6 +35,7 @@ #include "socket-util.h" #include "util.h" #include "modargs.h" +#include "log.h" #if defined(USE_PROTOCOL_SIMPLE) #include "protocol-simple.h" @@ -87,12 +88,12 @@ static struct pa_socket_server *create_socket_server(struct pa_core *c, struct p uint32_t port = IPV4_PORT; if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) { - fprintf(stderr, "loopback= expects a numerical argument.\n"); + pa_log(__FILE__": loopback= expects a numerical argument.\n"); return NULL; } if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { - fprintf(stderr, "port= expects a numerical argument between 1 and 65535.\n"); + pa_log(__FILE__": port= expects a numerical argument between 1 and 65535.\n"); return NULL; } @@ -106,17 +107,17 @@ static struct pa_socket_server *create_socket_server(struct pa_core *c, struct p assert(p); if (pa_unix_socket_make_secure_dir(p) < 0) { - fprintf(stderr, "Failed to create secure socket directory.\n"); + pa_log(__FILE__": Failed to create secure socket directory.\n"); return NULL; } if ((r = pa_unix_socket_remove_stale(p)) < 0) { - fprintf(stderr, "Failed to remove stale UNIX socket '%s': %s\n", p, strerror(errno)); + pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s\n", p, strerror(errno)); return NULL; } if (r) - fprintf(stderr, "Removed stale UNIX socket '%s'.", p); + pa_log(__FILE__": Removed stale UNIX socket '%s'.", p); if (!(s = pa_socket_server_new_unix(c->mainloop, p))) return NULL; @@ -132,7 +133,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - fprintf(stderr, "Failed to parse module arguments\n"); + pa_log(__FILE__": Failed to parse module arguments\n"); goto finish; } diff --git a/polyp/module-sine.c b/polyp/module-sine.c index 364cc64cc..868f63c6f 100644 --- a/polyp/module-sine.c +++ b/polyp/module-sine.c @@ -32,6 +32,7 @@ #include "modargs.h" #include "xmalloc.h" #include "namereg.h" +#include "log.h" struct userdata { struct pa_core *core; @@ -98,7 +99,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { char t[256]; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - fprintf(stderr, __FILE__": Failed to parse module arguments\n"); + pa_log(__FILE__": Failed to parse module arguments\n"); goto fail; } @@ -110,7 +111,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { sink_name = pa_modargs_get_value(ma, "sink", NULL); if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, 1))) { - fprintf(stderr, __FILE__": No such sink\n"); + pa_log(__FILE__": No such sink.\n"); goto fail; } @@ -120,7 +121,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { frequency = 440; if (pa_modargs_get_value_u32(ma, "frequency", &frequency) < 0 || frequency < 1 || frequency > ss.rate/2) { - fprintf(stderr, __FILE__": Invalid frequency specification\n"); + pa_log(__FILE__": Invalid frequency specification\n"); goto fail; } diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index ae889b221..d8ec978b0 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -37,6 +37,7 @@ #include "modargs.h" #include "xmalloc.h" #include "namereg.h" +#include "log.h" struct x11_source { struct pa_io_event *io_event; @@ -65,7 +66,7 @@ static int ring_bell(struct userdata *u, int percent) { assert(u); if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { - fprintf(stderr, __FILE__": Invalid sink\n"); + pa_log(__FILE__": Invalid sink\n"); return -1; } @@ -88,7 +89,7 @@ static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, bne = ((XkbBellNotifyEvent*) &e); if (ring_bell(u, bne->percent) < 0) { - fprintf(stderr, __FILE__": Ringing bell failed, reverting to X11 device bell.\n"); + pa_log(__FILE__": Ringing bell failed, reverting to X11 device bell.\n"); XkbForceDeviceBell(u->display, bne->device, bne->bell_class, bne->bell_id, bne->percent); } } @@ -112,7 +113,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - fprintf(stderr, __FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments\n"); goto fail; } @@ -124,7 +125,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); if (!(u->display = XOpenDisplay(pa_modargs_get_value(ma, "display", NULL)))) { - fprintf(stderr, __FILE__": XOpenDisplay() failed\n"); + pa_log(__FILE__": XOpenDisplay() failed\n"); goto fail; } @@ -134,7 +135,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { minor = XkbMinorVersion; if (!XkbLibraryVersion(&major, &minor)) { - fprintf(stderr, __FILE__": XkbLibraryVersion() failed\n"); + pa_log(__FILE__": XkbLibraryVersion() failed\n"); goto fail; } @@ -142,7 +143,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { minor = XkbMinorVersion; if (!XkbQueryExtension(u->display, NULL, &u->xkb_event_base, NULL, &major, &minor)) { - fprintf(stderr, __FILE__": XkbQueryExtension() failed\n"); + pa_log(__FILE__": XkbQueryExtension() failed\n"); goto fail; } diff --git a/polyp/module.c b/polyp/module.c index a06b27541..6eec499b2 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -33,6 +33,7 @@ #include "module.h" #include "xmalloc.h" #include "subscribe.h" +#include "log.h" #define UNLOAD_POLL_TIME 10 @@ -56,6 +57,8 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char if (c->disallow_module_loading) goto fail; + + pa_log(__FILE__": Trying to load \"%s\" with argument \"%s\".\n", name, argument); m = pa_xmalloc(sizeof(struct pa_module)); @@ -95,13 +98,16 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char r = pa_idxset_put(c->modules, m, &m->index); assert(r >= 0 && m->index != PA_IDXSET_INVALID); - fprintf(stderr, "module: loaded %u \"%s\" with argument \"%s\".\n", m->index, m->name, m->argument); + pa_log(__FILE__": Loaded \"%s\" (index: #%u) with argument \"%s\".\n", m->name, m->index, m->argument); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_NEW, m->index); return m; fail: + + pa_log(__FILE__": Failed to load \"%s\" with argument \"%s\".\n", name, argument); + if (m) { pa_xfree(m->argument); pa_xfree(m->name); @@ -125,7 +131,7 @@ static void pa_module_free(struct pa_module *m) { lt_dlclose(m->dl); - fprintf(stderr, "module: unloaded %u \"%s\".\n", m->index, m->name); + pa_log(__FILE__": Unloaded \"%s\" (index: #%u).\n", m->name, m->index); pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE, m->index); diff --git a/polyp/oss-util.c b/polyp/oss-util.c index b28c3dc95..613cda47d 100644 --- a/polyp/oss-util.c +++ b/polyp/oss-util.c @@ -36,6 +36,7 @@ #include "oss-util.h" #include "util.h" +#include "log.h" int pa_oss_open(const char *device, int *mode, int* pcaps) { int fd = -1; @@ -49,7 +50,7 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { tcaps = pcaps ? pcaps : &dcaps; if (ioctl(fd, SNDCTL_DSP_GETCAPS, tcaps) < 0) { - fprintf(stderr, __FILE__": SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); goto fail; } @@ -61,20 +62,20 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) { if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY)) < 0) { - fprintf(stderr, __FILE__": open('%s'): %s\n", device, strerror(errno)); + pa_log(__FILE__": open('%s'): %s\n", device, strerror(errno)); goto fail; } } } else { if ((fd = open(device, *mode|O_NDELAY)) < 0) { - fprintf(stderr, __FILE__": open('%s'): %s\n", device, strerror(errno)); + pa_log(__FILE__": open('%s'): %s\n", device, strerror(errno)); goto fail; } } if (pcaps) { if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { - fprintf(stderr, "SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); goto fail; } } @@ -112,7 +113,7 @@ int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != f) { format = AFMT_U8; if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_U8) { - fprintf(stderr, "SNDCTL_DSP_SETFMT: %s\n", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETFMT: %s\n", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); return -1; } else ss->format = PA_SAMPLE_U8; @@ -124,7 +125,7 @@ int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { channels = ss->channels; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { - fprintf(stderr, "SNDCTL_DSP_CHANNELS: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_CHANNELS: %s\n", strerror(errno)); return -1; } assert(channels); @@ -132,7 +133,7 @@ int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { speed = ss->rate; if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { - fprintf(stderr, "SNDCTL_DSP_SPEED: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SPEED: %s\n", strerror(errno)); return -1; } assert(speed); @@ -158,7 +159,7 @@ int pa_oss_set_fragments(int fd, int nfrags, int frag_size) { arg = ((int) nfrags << 16) | simple_log2(frag_size); if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &arg) < 0) { - fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); return -1; } diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index 22f5da09f..23bdf68be 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -31,6 +31,7 @@ #include "native-common.h" #include "xmalloc.h" #include "llist.h" +#include "log.h" /*#define DEBUG_OPCODES*/ @@ -173,7 +174,7 @@ int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *use goto finish; #ifdef DEBUG_OPCODES - fprintf(stderr, __FILE__": Recieved opcode <%s>\n", command_names[command]); + pa_log(__FILE__": Recieved opcode <%s>\n", command_names[command]); #endif if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) { @@ -191,7 +192,7 @@ int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *use c->proc(pd, command, tag, ts, userdata); } else { - fprintf(stderr, "Recieved unsupported command %u\n", command); + pa_log(__FILE__": Recieved unsupported command %u\n", command); goto finish; } diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 715e23b6c..a31712f53 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -40,7 +40,7 @@ autoload_source_add input module-alsa-source source_name=input #load module-simple-protocol-tcp load module-native-protocol-unix #load module-cli-protocol-unix -load module-esound-protocol-unix +#load module-esound-protocol-unix # Load the CLI module #load module-cli diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index fb6eadf4a..94df7ec00 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -46,6 +46,7 @@ #include "authkey.h" #include "util.h" #include "xmalloc.h" +#include "log.h" static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = { pa_command_request }, @@ -190,7 +191,7 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack pa_context_ref(c); if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - fprintf(stderr, "polyp.c: invalid packet.\n"); + pa_log(__FILE__": invalid packet.\n"); pa_context_fail(c, PA_ERROR_PROTOCOL); } @@ -580,13 +581,13 @@ int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)) { return pa_context_connect(c, NULL); if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - fprintf(stderr, __FILE__": socketpair() failed: %s\n", strerror(errno)); + pa_log(__FILE__": socketpair() failed: %s\n", strerror(errno)); pa_context_fail(c, PA_ERROR_INTERNAL); goto fail; } if ((pid = fork()) < 0) { - fprintf(stderr, __FILE__": fork() failed: %s\n", strerror(errno)); + pa_log(__FILE__": fork() failed: %s\n", strerror(errno)); pa_context_fail(c, PA_ERROR_INTERNAL); goto fail; } else if (!pid) { @@ -603,14 +604,14 @@ int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)) { p = POLYPAUDIO_BINARY; snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); - execl(p, p, "-r", "-D", t, NULL); + execl(p, p, "-r", "-D", "-lsyslog", "-X 5", t, NULL); exit(1); } /* Parent */ if (waitpid(pid, &status, 0) < 0) { - fprintf(stderr, __FILE__": waitpid() failed: %s\n", strerror(errno)); + pa_log(__FILE__": waitpid() failed: %s\n", strerror(errno)); pa_context_fail(c, PA_ERROR_INTERNAL); goto fail; } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index ccd39c2a6..8caae87e0 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -33,6 +33,7 @@ #include "mainloop.h" #include "native-common.h" #include "xmalloc.h" +#include "log.h" struct pa_simple { struct pa_mainloop *mainloop; @@ -204,7 +205,7 @@ static void read_callback(struct pa_stream *s, const void*data, size_t length, v assert(s && data && length && p); if (p->read_data) { - fprintf(stderr, __FILE__": Buffer overflow, dropping incoming memory blocks.\n"); + pa_log(__FILE__": Buffer overflow, dropping incoming memory blocks.\n"); pa_xfree(p->read_data); } diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index d6e2bf6b1..3f87d4d09 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -45,6 +45,7 @@ #include "debug.h" #include "namereg.h" #include "xmalloc.h" +#include "log.h" #define DEFAULT_COOKIE_FILE ".esd_auth" @@ -238,7 +239,7 @@ static int esd_proto_connect(struct connection *c, esd_proto_t request, const vo if (!c->authorized) { if (memcmp(data, c->protocol->esd_key, ESD_KEY_LEN) != 0) { - fprintf(stderr, __FILE__": kicked client with invalid authorization key.\n"); + pa_log(__FILE__": kicked client with invalid authorization key.\n"); return -1; } @@ -251,7 +252,7 @@ static int esd_proto_connect(struct connection *c, esd_proto_t request, const vo else if (ekey == ESD_SWAP_ENDIAN_KEY) c->swap_byte_order = 1; else { - fprintf(stderr, __FILE__": client sent invalid endian key\n"); + pa_log(__FILE__": client sent invalid endian key\n"); return -1; } @@ -279,7 +280,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons return -1; if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { - fprintf(stderr, __FILE__": No output sink\n"); + pa_log(__FILE__": No output sink\n"); return -1; } @@ -662,7 +663,7 @@ static int do_read(struct connection *c) { assert(c->read_data_length < sizeof(c->request)); if ((r = pa_iochannel_read(c->io, ((uint8_t*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { - fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -673,14 +674,14 @@ static int do_read(struct connection *c) { c->request = swap_endian_32(c->request); if (c->request < ESD_PROTO_CONNECT || c->request > ESD_PROTO_MAX) { - fprintf(stderr, "protocol-esound.c: recieved invalid request.\n"); + pa_log(__FILE__": recieved invalid request.\n"); return -1; } handler = proto_map+c->request; if (!handler->proc) { - fprintf(stderr, "protocol-sound.c: recieved unimplemented request.\n"); + pa_log(__FILE__": recieved unimplemented request.\n"); return -1; } @@ -709,7 +710,7 @@ static int do_read(struct connection *c) { assert(c->read_data && c->read_data_length < handler->data_length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { - fprintf(stderr, "protocol-esound.c: read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -729,7 +730,7 @@ static int do_read(struct connection *c) { assert(c->scache_memchunk.memblock && c->scache_name && c->scache_memchunk.index < c->scache_memchunk.length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache_memchunk.memblock->data+c->scache_memchunk.index, c->scache_memchunk.length-c->scache_memchunk.index)) <= 0) { - fprintf(stderr, __FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -784,7 +785,7 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - fprintf(stderr, __FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -812,7 +813,7 @@ static int do_write(struct connection *c) { assert(c->write_data_index < c->write_data_length); if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { - fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); return -1; } @@ -831,7 +832,7 @@ static int do_write(struct connection *c) { if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); - fprintf(stderr, __FILE__": write(): %s\n", strerror(errno)); + pa_log(__FILE__": write(): %s\n", strerror(errno)); return -1; } diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 2572810fb..4c99d5fe4 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -44,6 +44,7 @@ #include "xmalloc.h" #include "util.h" #include "subscribe.h" +#include "log.h" struct connection; struct pa_protocol_native; @@ -357,7 +358,7 @@ static void request_bytes(struct playback_stream *s) { pa_tagstruct_putu32(t, l); pa_pstream_send_tagstruct(s->connection->pstream, t); - /*fprintf(stderr, "Requesting %u bytes\n", l);*/ + /*pa_log(__FILE__": Requesting %u bytes\n", l);*/ } static void send_memblock(struct connection *c) { @@ -421,7 +422,7 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk assert(i && i->userdata && chunk); s = i->userdata; - /*fprintf(stderr, "%3.0f \r", (double) pa_memblockq_get_length(s->memblockq)/pa_memblockq_get_tlength(s->memblockq)*100);*/ + /*pa_log(__FILE__": %3.0f \r", (double) pa_memblockq_get_length(s->memblockq)/pa_memblockq_get_tlength(s->memblockq)*100);*/ if (pa_memblockq_peek(s->memblockq, chunk) < 0) return -1; @@ -442,7 +443,7 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk s->drain_request = 0; } - /*fprintf(stderr, "after_drop: %u\n", pa_memblockq_get_length(s->memblockq));*/ + /*pa_log(__FILE__": after_drop: %u\n", pa_memblockq_get_length(s->memblockq));*/ } static void sink_input_kill_cb(struct pa_sink_input *i) { @@ -456,7 +457,7 @@ static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { assert(i && i->userdata); s = i->userdata; - /*fprintf(stderr, "get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/ + /*pa_log(__FILE__": get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/ return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); } @@ -482,7 +483,7 @@ static void source_output_kill_cb(struct pa_source_output *o) { /*** pdispatch callbacks ***/ static void protocol_error(struct connection *c) { - fprintf(stderr, __FILE__": protocol error, kicking client\n"); + pa_log(__FILE__": protocol error, kicking client\n"); connection_free(c); } @@ -671,7 +672,7 @@ static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag } if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) { - fprintf(stderr, "protocol-native.c: Denied access to client with invalid authorization key.\n"); + pa_log(__FILE__": Denied access to client with invalid authorization key.\n"); pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); return; } @@ -1364,7 +1365,7 @@ static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, ui else { assert(command == PA_COMMAND_FLUSH_PLAYBACK_STREAM); pa_memblockq_flush(s->memblockq); - /*fprintf(stderr, "flush: %u\n", pa_memblockq_get_length(s->memblockq));*/ + /*pa_log(__FILE__": flush: %u\n", pa_memblockq_get_length(s->memblockq));*/ } pa_sink_notify(s->sink_input->sink); @@ -1379,7 +1380,7 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack assert(p && packet && packet->data && c); if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - fprintf(stderr, "protocol-native: invalid packet.\n"); + pa_log(__FILE__": invalid packet.\n"); connection_free(c); } } @@ -1390,7 +1391,7 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui assert(p && chunk && userdata); if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) { - fprintf(stderr, "protocol-native: client sent block for invalid stream.\n"); + pa_log(__FILE__": client sent block for invalid stream.\n"); connection_free(c); return; } @@ -1404,10 +1405,10 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui pa_memblockq_push_align(p->memblockq, chunk, delta); assert(p->sink_input); - /*fprintf(stderr, "after_recv: %u\n", pa_memblockq_get_length(p->memblockq));*/ + /*pa_log(__FILE__": after_recv: %u\n", pa_memblockq_get_length(p->memblockq));*/ pa_sink_notify(p->sink_input->sink); - /*fprintf(stderr, "Recieved %u bytes.\n", chunk->length);*/ + /*pa_log(__FILE__": Recieved %u bytes.\n", chunk->length);*/ } else { struct upload_stream *u = (struct upload_stream*) stream; @@ -1445,7 +1446,7 @@ static void pstream_die_callback(struct pa_pstream *p, void *userdata) { assert(p && c); connection_free(c); -/* fprintf(stderr, "protocol-native: connection died.\n");*/ +/* pa_log(__FILE__": connection died.\n");*/ } @@ -1509,7 +1510,7 @@ static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struc assert(c && ma); if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { - fprintf(stderr, __FILE__": public= expects numeric argument.\n"); + pa_log(__FILE__": public= expects numeric argument.\n"); return NULL; } diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 3ccb3068c..f62404625 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -37,6 +37,7 @@ #include "sample-util.h" #include "namereg.h" #include "xmalloc.h" +#include "log.h" struct connection { struct pa_protocol_simple *protocol; @@ -121,7 +122,7 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - fprintf(stderr, __FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -155,7 +156,7 @@ static int do_write(struct connection *c) { if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); - fprintf(stderr, "write(): %s\n", strerror(errno)); + pa_log(__FILE__": write(): %s\n", strerror(errno)); return -1; } @@ -299,12 +300,12 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo size_t l; if (!(sink = pa_namereg_get(p->core, p->sink_name, PA_NAMEREG_SINK, 1))) { - fprintf(stderr, "Failed to get sink.\n"); + pa_log(__FILE__": Failed to get sink.\n"); goto fail; } if (!(c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec))) { - fprintf(stderr, "Failed to create sink input.\n"); + pa_log(__FILE__": Failed to create sink input.\n"); goto fail; } @@ -329,13 +330,13 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo size_t l; if (!(source = pa_namereg_get(p->core, p->source_name, PA_NAMEREG_SOURCE, 1))) { - fprintf(stderr, "Failed to get source.\n"); + pa_log(__FILE__": Failed to get source.\n"); goto fail; } c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec); if (!c->source_output) { - fprintf(stderr, "Failed to create source output.\n"); + pa_log(__FILE__": Failed to create source output.\n"); goto fail; } c->source_output->owner = p->module; @@ -377,7 +378,7 @@ struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct p p->sample_spec = core->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &p->sample_spec) < 0) { - fprintf(stderr, "Failed to parse sample type specification.\n"); + pa_log(__FILE__": Failed to parse sample type specification.\n"); goto fail; } @@ -386,20 +387,20 @@ struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct p enable = 0; if (pa_modargs_get_value_boolean(ma, "record", &enable) < 0) { - fprintf(stderr, __FILE__": record= expects a numeric argument.\n"); + pa_log(__FILE__": record= expects a numeric argument.\n"); goto fail; } p->mode = enable ? RECORD : 0; enable = 1; if (pa_modargs_get_value_boolean(ma, "playback", &enable) < 0) { - fprintf(stderr, __FILE__": playback= expects a numeric argument.\n"); + pa_log(__FILE__": playback= expects a numeric argument.\n"); goto fail; } p->mode |= enable ? PLAYBACK : 0; if ((p->mode & (RECORD|PLAYBACK)) == 0) { - fprintf(stderr, __FILE__": neither playback nor recording enabled for protocol.\n"); + pa_log(__FILE__": neither playback nor recording enabled for protocol.\n"); goto fail; } diff --git a/polyp/pstream.c b/polyp/pstream.c index 438dccc71..1883c95d6 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -31,6 +31,7 @@ #include "pstream.h" #include "queue.h" #include "xmalloc.h" +#include "log.h" enum pa_pstream_descriptor_index { PA_PSTREAM_DESCRIPTOR_LENGTH, @@ -214,7 +215,7 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { struct item_info *i; assert(p && packet); - /*fprintf(stderr, "push-packet %p\n", packet);*/ + /*pa_log(__FILE__": push-packet %p\n", packet);*/ i = pa_xmalloc(sizeof(struct item_info)); i->type = PA_PSTREAM_ITEM_PACKET; @@ -263,7 +264,7 @@ static void prepare_next_write_item(struct pa_pstream *p) { p->write.index = 0; if (p->write.current->type == PA_PSTREAM_ITEM_PACKET) { - /*fprintf(stderr, "pop-packet %p\n", p->write.current->packet);*/ + /*pa_log(__FILE__": pop-packet %p\n", p->write.current->packet);*/ assert(p->write.current->packet); p->write.data = p->write.current->packet->data; @@ -348,7 +349,7 @@ static void do_read(struct pa_pstream *p) { /* Frame size too large */ if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) > FRAME_SIZE_MAX) { - fprintf(stderr, "frame size too large\n"); + pa_log(__FILE__": Frame size too large\n"); goto die; } diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 95dc55772..f4f573433 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -32,6 +32,7 @@ #include "sample-util.h" #include "xmalloc.h" #include "subscribe.h" +#include "log.h" #define CONVERT_BUFFER_LENGTH 4096 @@ -43,7 +44,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con assert(s && spec); if (pa_idxset_ncontents(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { - fprintf(stderr, __FILE__": Failed to create sink input: too many inputs per sink.\n"); + pa_log(__FILE__": Failed to create sink input: too many inputs per sink.\n"); return NULL; } @@ -78,7 +79,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con assert(r == 0); pa_sample_spec_snprint(st, sizeof(st), spec); - fprintf(stderr, "sink-input: created %u \"%s\" on %u with sample spec \"%s\"\n", i->index, i->name, s->index, st); + pa_log(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"\n", i->index, i->name, s->index, st); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); diff --git a/polyp/sink.c b/polyp/sink.c index 104248a9b..9b8a6492c 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -35,6 +35,7 @@ #include "sample-util.h" #include "xmalloc.h" #include "subscribe.h" +#include "log.h" #define MAX_MIX_CHANNELS 32 @@ -77,7 +78,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co assert(s->index != PA_IDXSET_INVALID && r >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - fprintf(stderr, "sink: created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); + pa_log(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); @@ -100,7 +101,7 @@ void pa_sink_free(struct pa_sink *s) { pa_source_free(s->monitor_source); pa_idxset_remove_by_data(s->core->sinks, s, NULL); - fprintf(stderr, "sink: freed %u \"%s\"\n", s->index, s->name); + pa_log(__FILE__": freed %u \"%s\"\n", s->index, s->name); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); diff --git a/polyp/socket-client.c b/polyp/socket-client.c index f697cbdbc..773e922c0 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -37,6 +37,7 @@ #include "socket-util.h" #include "util.h" #include "xmalloc.h" +#include "log.h" struct pa_socket_client { int ref; @@ -73,17 +74,17 @@ static void do_call(struct pa_socket_client *c) { lerror = sizeof(error); if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &error, &lerror) < 0) { - fprintf(stderr, "getsockopt(): %s\n", strerror(errno)); + pa_log(__FILE__": getsockopt(): %s\n", strerror(errno)); goto finish; } if (lerror != sizeof(error)) { - fprintf(stderr, "getsocktop() returned invalid size.\n"); + pa_log(__FILE__": getsockopt() returned invalid size.\n"); goto finish; } if (error != 0) { - fprintf(stderr, "connect(): %s\n", strerror(error)); + pa_log(__FILE__": connect(): %s\n", strerror(error)); goto finish; } @@ -125,7 +126,7 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc if ((r = connect(c->fd, sa, len)) < 0) { if (errno != EINPROGRESS) { - /*fprintf(stderr, "connect(): %s\n", strerror(errno));*/ + /*pa_log(__FILE__": connect(): %s\n", strerror(errno));*/ return -1; } @@ -148,7 +149,7 @@ struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, ui assert(c); if ((c->fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(): %s\n", strerror(errno)); goto fail; } @@ -178,7 +179,7 @@ struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, co assert(c); if ((c->fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(): %s\n", strerror(errno)); goto fail; } @@ -206,7 +207,7 @@ struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m assert(c); if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(): %s\n", strerror(errno)); goto fail; } diff --git a/polyp/socket-server.c b/polyp/socket-server.c index 131339eda..9f943dc06 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -39,6 +39,7 @@ #include "socket-util.h" #include "xmalloc.h" #include "util.h" +#include "log.h" struct pa_socket_server { int ref; @@ -62,7 +63,7 @@ static void callback(struct pa_mainloop_api *mainloop, struct pa_io_event *e, in pa_socket_server_ref(s); if ((nfd = accept(fd, NULL, NULL)) < 0) { - fprintf(stderr, "accept(): %s\n", strerror(errno)); + pa_log(__FILE__": accept(): %s\n", strerror(errno)); goto finish; } @@ -121,7 +122,7 @@ struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, co assert(m && filename); if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(): %s\n", strerror(errno)); goto fail; } @@ -134,12 +135,12 @@ struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, co pa_socket_low_delay(fd); if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { - fprintf(stderr, "bind(): %s\n", strerror(errno)); + pa_log(__FILE__": bind(): %s\n", strerror(errno)); goto fail; } if (listen(fd, 5) < 0) { - fprintf(stderr, "listen(): %s\n", strerror(errno)); + pa_log(__FILE__": listen(): %s\n", strerror(errno)); goto fail; } @@ -167,14 +168,14 @@ struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, ui assert(m && port); if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(): %s\n", strerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) - fprintf(stderr, "setsockopt(): %s\n", strerror(errno)); + pa_log(__FILE__": setsockopt(): %s\n", strerror(errno)); pa_socket_tcp_low_delay(fd); @@ -183,12 +184,12 @@ struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, ui sa.sin_addr.s_addr = htonl(address); if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { - fprintf(stderr, "bind(): %s\n", strerror(errno)); + pa_log(__FILE__": bind(): %s\n", strerror(errno)); goto fail; } if (listen(fd, 5) < 0) { - fprintf(stderr, "listen(): %s\n", strerror(errno)); + pa_log(__FILE__": listen(): %s\n", strerror(errno)); goto fail; } diff --git a/polyp/socket-util.c b/polyp/socket-util.c index 1f93ef881..2f082bfbe 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -41,6 +41,7 @@ #include "socket-util.h" #include "util.h" #include "xmalloc.h" +#include "log.h" void pa_socket_peer_to_string(int fd, char *c, size_t l) { struct stat st; @@ -122,7 +123,7 @@ int pa_socket_set_rcvbuf(int fd, size_t l) { assert(fd >= 0); if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) { - fprintf(stderr, "SO_RCVBUF: %s\n", strerror(errno)); + pa_log(__FILE__": SO_RCVBUF: %s\n", strerror(errno)); return -1; } @@ -133,7 +134,7 @@ int pa_socket_set_sndbuf(int fd, size_t l) { assert(fd >= 0); if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) { - fprintf(stderr, "SO_SNDBUF: %s\n", strerror(errno)); + pa_log(__FILE__": SO_SNDBUF: %s\n", strerror(errno)); return -1; } @@ -145,7 +146,7 @@ int pa_unix_socket_is_stale(const char *fn) { int fd = -1, ret = -1; if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(): %s\n", strerror(errno)); goto finish; } diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c index a77b58139..c667f5ff6 100644 --- a/polyp/sound-file-stream.c +++ b/polyp/sound-file-stream.c @@ -33,6 +33,7 @@ #include "sound-file-stream.h" #include "sink-input.h" #include "xmalloc.h" +#include "log.h" #define BUF_SIZE (1024*10) @@ -128,7 +129,7 @@ int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume) { memset(&sfinfo, 0, sizeof(sfinfo)); if (!(u->sndfile = sf_open(fname, SFM_READ, &sfinfo))) { - fprintf(stderr, __FILE__": Failed to open file %s\n", fname); + pa_log(__FILE__": Failed to open file %s\n", fname); goto fail; } @@ -137,7 +138,7 @@ int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume) { ss.channels = sfinfo.channels; if (!pa_sample_spec_valid(&ss)) { - fprintf(stderr, __FILE__": Unsupported sample format in file %s\n", fname); + pa_log(__FILE__": Unsupported sample format in file %s\n", fname); goto fail; } diff --git a/polyp/sound-file.c b/polyp/sound-file.c index 01fda78e0..d1f7e0f7b 100644 --- a/polyp/sound-file.c +++ b/polyp/sound-file.c @@ -30,6 +30,7 @@ #include "sound-file.h" #include "sample.h" +#include "log.h" #define MAX_FILE_SIZE (1024*1024) @@ -46,7 +47,7 @@ int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_m chunk->index = chunk->length = 0; if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { - fprintf(stderr, __FILE__": Failed to open file %s\n", fname); + pa_log(__FILE__": Failed to open file %s\n", fname); goto finish; } @@ -55,12 +56,12 @@ int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_m ss->channels = sfinfo.channels; if (!pa_sample_spec_valid(ss)) { - fprintf(stderr, __FILE__": Unsupported sample format in file %s\n", fname); + pa_log(__FILE__": Unsupported sample format in file %s\n", fname); goto finish; } if ((l = pa_frame_size(ss)*sfinfo.frames) > MAX_FILE_SIZE) { - fprintf(stderr, __FILE__": File to large\n"); + pa_log(__FILE__": File to large\n"); goto finish; } @@ -70,7 +71,7 @@ int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_m chunk->length = l; if (sf_readf_float(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) { - fprintf(stderr, __FILE__": Premature file end\n"); + pa_log(__FILE__": Premature file end\n"); goto finish; } diff --git a/polyp/source-output.c b/polyp/source-output.c index 9d124f074..55448b5c5 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -31,6 +31,7 @@ #include "source-output.h" #include "xmalloc.h" #include "subscribe.h" +#include "log.h" struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec) { struct pa_source_output *o; @@ -39,7 +40,7 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n assert(s && spec); if (pa_idxset_ncontents(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { - fprintf(stderr, __FILE__": Failed to create source output: too many outputs per source.\n"); + pa_log(__FILE__": Failed to create source output: too many outputs per source.\n"); return NULL; } diff --git a/polyp/source.c b/polyp/source.c index 6ab439d66..5cdfdb551 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -33,6 +33,7 @@ #include "namereg.h" #include "xmalloc.h" #include "subscribe.h" +#include "log.h" struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) { struct pa_source *s; @@ -63,7 +64,7 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail assert(s->index != PA_IDXSET_INVALID && r >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - fprintf(stderr, "source: created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); + pa_log(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); @@ -85,7 +86,7 @@ void pa_source_free(struct pa_source *s) { pa_idxset_remove_by_data(s->core->sources, s, NULL); - fprintf(stderr, "source: freed %u \"%s\"\n", s->index, s->name); + pa_log(__FILE__": freed %u \"%s\"\n", s->index, s->name); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); diff --git a/polyp/strbuf.h b/polyp/strbuf.h index 8ca51624b..1622d3a0a 100644 --- a/polyp/strbuf.h +++ b/polyp/strbuf.h @@ -22,6 +22,8 @@ USA. ***/ +#include "gcc-printf.h" + struct pa_strbuf; struct pa_strbuf *pa_strbuf_new(void); @@ -29,7 +31,7 @@ void pa_strbuf_free(struct pa_strbuf *sb); char *pa_strbuf_tostring(struct pa_strbuf *sb); char *pa_strbuf_tostring_free(struct pa_strbuf *sb); -int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) __attribute__ ((format (printf, 2, 3))); +int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); void pa_strbuf_puts(struct pa_strbuf *sb, const char *t); void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t m); diff --git a/polyp/subscribe.c b/polyp/subscribe.c index 5f7651fd8..d3b97de7e 100644 --- a/polyp/subscribe.c +++ b/polyp/subscribe.c @@ -29,6 +29,7 @@ #include "queue.h" #include "subscribe.h" #include "xmalloc.h" +#include "log.h" struct pa_subscription { struct pa_core *core; @@ -109,44 +110,44 @@ void pa_subscription_free_all(struct pa_core *c) { /*static void dump_event(struct pa_subscription_event*e) { switch (e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { case PA_SUBSCRIPTION_EVENT_SINK: - fprintf(stderr, "SINK_EVENT"); + pa_log(__FILE__": SINK_EVENT"); break; case PA_SUBSCRIPTION_EVENT_SOURCE: - fprintf(stderr, "SOURCE_EVENT"); + pa_log(__FILE__": SOURCE_EVENT"); break; case PA_SUBSCRIPTION_EVENT_SINK_INPUT: - fprintf(stderr, "SINK_INPUT_EVENT"); + pa_log(__FILE__": SINK_INPUT_EVENT"); break; case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: - fprintf(stderr, "SOURCE_OUTPUT_EVENT"); + pa_log(__FILE__": SOURCE_OUTPUT_EVENT"); break; case PA_SUBSCRIPTION_EVENT_MODULE: - fprintf(stderr, "MODULE_EVENT"); + pa_log(__FILE__": MODULE_EVENT"); break; case PA_SUBSCRIPTION_EVENT_CLIENT: - fprintf(stderr, "CLIENT_EVENT"); + pa_log(__FILE__": CLIENT_EVENT"); break; default: - fprintf(stderr, "OTHER"); + pa_log(__FILE__": OTHER"); break; } switch (e->type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) { case PA_SUBSCRIPTION_EVENT_NEW: - fprintf(stderr, " NEW"); + pa_log(__FILE__": NEW"); break; case PA_SUBSCRIPTION_EVENT_CHANGE: - fprintf(stderr, " CHANGE"); + pa_log(__FILE__": CHANGE"); break; case PA_SUBSCRIPTION_EVENT_REMOVE: - fprintf(stderr, " REMOVE"); + pa_log(__FILE__": REMOVE"); break; default: - fprintf(stderr, " OTHER"); + pa_log(__FILE__": OTHER"); break; } - fprintf(stderr, " %u\n", e->index); + pa_log(__FILE__": %u\n", e->index); }*/ static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { diff --git a/polyp/util.c b/polyp/util.c index 061d57100..408e60e9a 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -42,6 +42,7 @@ #include "util.h" #include "xmalloc.h" +#include "log.h" void pa_make_nonblock_fd(int fd) { int v; @@ -121,7 +122,7 @@ void pa_check_for_sigpipe(void) { if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) { #endif if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) { - fprintf(stderr, __FILE__": sigprocmask() failed: %s\n", strerror(errno)); + pa_log(__FILE__": sigprocmask() failed: %s\n", strerror(errno)); return; } #ifdef HAVE_PTHREAD @@ -132,14 +133,14 @@ void pa_check_for_sigpipe(void) { return; if (sigaction(SIGPIPE, NULL, &sa) < 0) { - fprintf(stderr, __FILE__": sigaction() failed: %s\n", strerror(errno)); + pa_log(__FILE__": sigaction() failed: %s\n", strerror(errno)); return; } if (sa.sa_handler != SIG_DFL) return; - fprintf(stderr, "polypaudio: WARNING: SIGPIPE is not trapped. This might cause malfunction!\n"); + pa_log(__FILE__": WARNING: SIGPIPE is not trapped. This might cause malfunction!\n"); } /* The following is based on an example from the GNU libc documentation */ @@ -169,6 +170,30 @@ char *pa_sprintf_malloc(const char *format, ...) { } } +char *pa_vsprintf_malloc(const char *format, va_list ap) { + int size = 100; + char *c = NULL; + + assert(format); + + for(;;) { + int r; + va_list ap; + + c = pa_xrealloc(c, size); + r = vsnprintf(c, size, format, ap); + + if (r > -1 && r < size) + return c; + + if (r > -1) /* glibc 2.1 */ + size = r+1; + else /* glibc 2.0 */ + size *= 2; + } +} + + char *pa_get_user_name(char *s, size_t l) { struct passwd pw, *r; char buf[1024]; @@ -220,26 +245,26 @@ uint32_t pa_age(struct timeval *tv) { void pa_raise_priority(void) { if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) - fprintf(stderr, __FILE__": setpriority() failed: %s\n", strerror(errno)); + pa_log(__FILE__": setpriority() failed: %s\n", strerror(errno)); else - fprintf(stderr, __FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); + pa_log(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); #ifdef _POSIX_PRIORITY_SCHEDULING { struct sched_param sp; if (sched_getparam(0, &sp) < 0) { - fprintf(stderr, __FILE__": sched_getparam() failed: %s\n", strerror(errno)); + pa_log(__FILE__": sched_getparam() failed: %s\n", strerror(errno)); return; } sp.sched_priority = 1; if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) { - fprintf(stderr, __FILE__": sched_setscheduler() failed: %s\n", strerror(errno)); + pa_log(__FILE__": sched_setscheduler() failed: %s\n", strerror(errno)); return; } - fprintf(stderr, __FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); + pa_log(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); } #endif } diff --git a/polyp/util.h b/polyp/util.h index f8dd3f046..18f883f0b 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -24,6 +24,9 @@ #include #include +#include + +#include "gcc-printf.h" void pa_make_nonblock_fd(int fd); @@ -34,7 +37,8 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size); void pa_check_for_sigpipe(void); -char *pa_sprintf_malloc(const char *format, ...) __attribute__ ((format (printf, 1, 2))); +char *pa_sprintf_malloc(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); +char *pa_vsprintf_malloc(const char *format, va_list ap); char *pa_get_user_name(char *s, size_t l); char *pa_get_host_name(char *s, size_t l); From 566e469bbe570be88a7122009e5128697d931700 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 6 Sep 2004 17:47:04 +0000 Subject: [PATCH 0177/1514] add module-pipe-source git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@180 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 + polyp/Makefile.am | 5 + polyp/memblockq.c | 2 +- polyp/module-pipe-sink.c | 2 +- polyp/module-pipe-source.c | 202 +++++++++++++++++++++++++++++++++++++ polyp/pacat.c | 11 ++ polyp/polypaudio.pa | 11 +- polyp/protocol-native.c | 8 +- 8 files changed, 233 insertions(+), 11 deletions(-) create mode 100644 polyp/module-pipe-source.c diff --git a/doc/todo b/doc/todo index 8ae9e7399..62debb6ee 100644 --- a/doc/todo +++ b/doc/todo @@ -11,6 +11,9 @@ - more complete pactl - add sample directory - add timing parameter to write callback of stream in client API +- config file for command line arguments +- vumeter +- add FAQ ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 335fa99a5..27ada2e19 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -77,6 +77,7 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-cli-protocol-tcp.la \ module-cli-protocol-unix.la \ module-pipe-sink.la \ + module-pipe-source.la \ module-alsa-sink.la \ module-alsa-source.la \ module-oss.la \ @@ -269,6 +270,10 @@ module_pipe_sink_la_SOURCES = module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version module_pipe_sink_la_LIBADD = $(AM_LIBADD) libiochannel.la +module_pipe_source_la_SOURCES = module-pipe-source.c +module_pipe_source_la_LDFLAGS = -module -avoid-version +module_pipe_source_la_LIBADD = $(AM_LIBADD) libiochannel.la + module_alsa_sink_la_SOURCES = module-alsa-sink.c module_alsa_sink_la_LDFLAGS = -module -avoid-version module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la diff --git a/polyp/memblockq.c b/polyp/memblockq.c index 0bba65817..a79814be8 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -207,7 +207,7 @@ void pa_memblockq_shorten(struct pa_memblockq *bq, size_t length) { if (bq->current_length <= length) return; - pa_log(__FILE__": Warning! pa_memblockq_shorten()\n"); + /*pa_log(__FILE__": Warning! pa_memblockq_shorten()\n");*/ l = bq->current_length - length; l /= bq->base; diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index 5f1ced03b..a5a7877fe 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -41,7 +41,7 @@ #include "xmalloc.h" #include "log.h" -#define DEFAULT_FIFO_NAME "/tmp/musicfifo" +#define DEFAULT_FIFO_NAME "/tmp/music.output" #define DEFAULT_SINK_NAME "fifo_output" struct userdata { diff --git a/polyp/module-pipe-source.c b/polyp/module-pipe-source.c new file mode 100644 index 000000000..baed06a59 --- /dev/null +++ b/polyp/module-pipe-source.c @@ -0,0 +1,202 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iochannel.h" +#include "source.h" +#include "module.h" +#include "util.h" +#include "modargs.h" +#include "xmalloc.h" +#include "log.h" + +#define DEFAULT_FIFO_NAME "/tmp/music.input" +#define DEFAULT_SOURCE_NAME "fifo_input" + +struct userdata { + struct pa_core *core; + + char *filename; + + struct pa_source *source; + struct pa_iochannel *io; + struct pa_module *module; + struct pa_memchunk chunk; +}; + +static const char* const valid_modargs[] = { + "file", + "rate", + "channels", + "format", + "source_name", + NULL +}; + +static void do_read(struct userdata *u) { + ssize_t r; + struct pa_memchunk chunk; + assert(u); + + if (!pa_iochannel_is_readable(u->io)) + return; + + pa_module_set_used(u->module, pa_idxset_ncontents(u->source->outputs)); + + if (!u->chunk.memblock) { + u->chunk.memblock = pa_memblock_new(1024, u->core->memblock_stat); + u->chunk.index = chunk.length = 0; + } + + assert(u->chunk.memblock && u->chunk.memblock->length > u->chunk.index); + if ((r = pa_iochannel_read(u->io, (uint8_t*) u->chunk.memblock->data + u->chunk.index, u->chunk.memblock->length - u->chunk.index)) <= 0) { + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + return; + } + + u->chunk.length = r; + pa_source_post(u->source, &u->chunk); + u->chunk.index += r; + + if (u->chunk.index >= u->chunk.memblock->length) { + u->chunk.index = u->chunk.length = 0; + pa_memblock_unref(u->chunk.memblock); + u->chunk.memblock = NULL; + } +} + +static void io_callback(struct pa_iochannel *io, void*userdata) { + struct userdata *u = userdata; + assert(u); + do_read(u); +} + +int pa_module_init(struct pa_core *c, struct pa_module*m) { + struct userdata *u = NULL; + struct stat st; + const char *p; + int fd = -1; + struct pa_sample_spec ss; + struct pa_modargs *ma = NULL; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments\n"); + goto fail; + } + + ss = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + pa_log(__FILE__": invalid sample format specification\n"); + goto fail; + } + + mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); + + if ((fd = open(p, O_RDWR)) < 0) { + pa_log(__FILE__": open('%s'): %s\n", p, strerror(errno)); + goto fail; + } + + pa_fd_set_cloexec(fd, 1); + + if (fstat(fd, &st) < 0) { + pa_log(__FILE__": fstat('%s'): %s\n", p, strerror(errno)); + goto fail; + } + + if (!S_ISFIFO(st.st_mode)) { + pa_log(__FILE__": '%s' is not a FIFO.\n", p); + goto fail; + } + + u = pa_xmalloc0(sizeof(struct userdata)); + + u->filename = pa_xstrdup(p); + u->core = c; + + if (!(u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) { + pa_log(__FILE__": failed to create source.\n"); + goto fail; + } + u->source->userdata = u; + pa_source_set_owner(u->source, m); + u->source->description = pa_sprintf_malloc("Unix FIFO source '%s'", p); + assert(u->source->description); + + u->io = pa_iochannel_new(c->mainloop, fd, -1); + assert(u->io); + pa_iochannel_set_callback(u->io, io_callback, u); + + u->chunk.memblock = NULL; + u->chunk.index = u->chunk.length = 0; + + u->module = m; + m->userdata = u; + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + if (fd >= 0) + close(fd); + + pa_module_done(c, m); + + return -1; +} + +void pa_module_done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + if (u->chunk.memblock) + pa_memblock_unref(u->chunk.memblock); + + pa_source_free(u->source); + pa_iochannel_free(u->io); + + assert(u->filename); + unlink(u->filename); + pa_xfree(u->filename); + + pa_xfree(u); +} diff --git a/polyp/pacat.c b/polyp/pacat.c index fd6e90e19..40301be88 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -313,6 +313,17 @@ int main(int argc, char *argv[]) { else if (strstr(bn, "cat") || strstr(bn, "play")) mode = PLAYBACK; + if (argc >= 2) { + if (!strcmp(argv[1], "-r")) + mode = RECORD; + else if (!strcmp(argv[1], "-p")) + mode = PLAYBACK; + else { + fprintf(stderr, "Invalid argument\n"); + goto quit; + } + } + fprintf(stderr, "Opening a %s stream.\n", mode == RECORD ? "recording" : "playback"); /* Set up a new main loop */ diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index a31712f53..87b4114ac 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -32,8 +32,8 @@ #autoload_source_add input module-oss device="/dev/adsp" sink_name=output source_name=input #autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -autoload_sink_add output module-alsa-sink sink_name=output -autoload_source_add input module-alsa-source source_name=input +#autoload_sink_add output module-alsa-sink sink_name=output +#autoload_source_add input module-alsa-source source_name=input # Load several protocols #load module-esound-protocol-tcp @@ -43,7 +43,7 @@ load module-native-protocol-unix #load module-esound-protocol-unix # Load the CLI module -#load module-cli +load module-cli # Make some devices default sink_default output @@ -55,5 +55,8 @@ source_default input scache_load /usr/share/sounds/KDE_Notify.wav x11-bell # Load X11 bell module -load module-x11-bell sample=x11-bell sink=output +#load module-x11-bell sample=x11-bell sink=output + +load module-pipe-source +load module-pipe-sink diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 4c99d5fe4..67352b3f2 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -422,8 +422,6 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk assert(i && i->userdata && chunk); s = i->userdata; - /*pa_log(__FILE__": %3.0f \r", (double) pa_memblockq_get_length(s->memblockq)/pa_memblockq_get_tlength(s->memblockq)*100);*/ - if (pa_memblockq_peek(s->memblockq, chunk) < 0) return -1; @@ -469,7 +467,7 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me assert(o && o->userdata && chunk); s = o->userdata; - pa_memblockq_push(s->memblockq, chunk, 0); + pa_memblockq_push_align(s->memblockq, chunk, 0); if (!pa_pstream_is_pending(s->connection->pstream)) send_memblock(s->connection); } @@ -765,9 +763,9 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm pa_memblockq_prebuf_disable(s->memblockq); - if (!pa_memblockq_is_readable(s->memblockq)) + if (!pa_memblockq_is_readable(s->memblockq)) { pa_pstream_send_simple_ack(c->pstream, tag); - else { + } else { s->drain_request = 1; s->drain_tag = tag; From 3536be420cf9ec6f4f8fbe1dc60b2da0cefba86c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 6 Sep 2004 18:55:47 +0000 Subject: [PATCH 0178/1514] correct a recording bug in native protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@181 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + polyp/Makefile.am | 4 ++-- polyp/protocol-native.c | 12 +++++++----- polyp/sink.c | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/doc/todo b/doc/todo index 62debb6ee..f48859e06 100644 --- a/doc/todo +++ b/doc/todo @@ -14,6 +14,7 @@ - config file for command line arguments - vumeter - add FAQ +- pa_context_connect_spawn() change function to fork+exec+waitpid-like function ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 27ada2e19..392154972 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -398,11 +398,11 @@ mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12.la -cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c +cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit_test_CFLAGS = $(AM_CFLAGS) cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop.la -cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c +cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop.la diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 67352b3f2..1ec1b6088 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -378,12 +378,14 @@ static void send_memblock(struct connection *c) { return; if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) { - if (chunk.length > r->fragment_size) - chunk.length = r->fragment_size; + struct pa_memchunk schunk = chunk; + + if (schunk.length > r->fragment_size) + schunk.length = r->fragment_size; - pa_pstream_send_memblock(c->pstream, r->index, 0, &chunk); - pa_memblockq_drop(r->memblockq, &chunk, chunk.length); - pa_memblock_unref(chunk.memblock); + pa_pstream_send_memblock(c->pstream, r->index, 0, &schunk); + pa_memblockq_drop(r->memblockq, &chunk, schunk.length); + pa_memblock_unref(schunk.memblock); return; } diff --git a/polyp/sink.c b/polyp/sink.c index 9b8a6492c..1fe38e9f9 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -158,7 +158,7 @@ int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) unsigned n; size_t l; assert(s && length && result); - + n = fill_mix_info(s, info, MAX_MIX_CHANNELS); if (n <= 0) From 0fa499db56dc9111ddd866080606cb8b0379280e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 6 Sep 2004 21:55:09 +0000 Subject: [PATCH 0179/1514] add support for setting/getting default sink/source via native protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@182 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 4 ++-- polyp/namereg.c | 8 +++++++ polyp/native-common.h | 6 ++--- polyp/pdispatch.c | 24 +++++++++++++++++--- polyp/polypaudio.pa | 10 ++++----- polyp/polyplib-context.c | 40 +++++++++++++++++++++++++++++++++ polyp/polyplib-context.h | 6 +++++ polyp/polyplib-def.h | 4 +++- polyp/polyplib-introspect.c | 45 +++++++++++++++++++++++++++++++++++++ polyp/polyplib-introspect.h | 2 ++ polyp/protocol-native.c | 27 ++++++++++++++++++++++ 11 files changed, 161 insertions(+), 15 deletions(-) diff --git a/doc/todo b/doc/todo index f48859e06..9ef5f9c44 100644 --- a/doc/todo +++ b/doc/todo @@ -12,9 +12,9 @@ - add sample directory - add timing parameter to write callback of stream in client API - config file for command line arguments -- vumeter - add FAQ -- pa_context_connect_spawn() change function to fork+exec+waitpid-like function +- pa_context_connect_spawn(): change function to fork+exec+waitpid-like function +- on delete event in paman ** later *** - xmlrpc/http diff --git a/polyp/namereg.c b/polyp/namereg.c index 72a4c648e..44a9cdc6c 100644 --- a/polyp/namereg.c +++ b/polyp/namereg.c @@ -35,6 +35,7 @@ #include "source.h" #include "sink.h" #include "xmalloc.h" +#include "subscribe.h" struct namereg_entry { enum pa_namereg_type type; @@ -186,6 +187,13 @@ void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_ s = type == PA_NAMEREG_SINK ? &c->default_sink_name : &c->default_source_name; assert(s); + if (!name && !*s) + return; + + if (name && *s && !strcmp(name, *s)) + return; + pa_xfree(*s); *s = pa_xstrdup(name); + pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX); } diff --git a/polyp/native-common.h b/polyp/native-common.h index 5250532e0..c5192cecc 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -66,17 +66,15 @@ enum { PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, PA_COMMAND_GET_SAMPLE_INFO, PA_COMMAND_GET_SAMPLE_INFO_LIST, - PA_COMMAND_SUBSCRIBE, PA_COMMAND_SUBSCRIBE_EVENT, - PA_COMMAND_SET_SINK_VOLUME, PA_COMMAND_SET_SINK_INPUT_VOLUME, - PA_COMMAND_CORK_PLAYBACK_STREAM, PA_COMMAND_FLUSH_PLAYBACK_STREAM, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, - + PA_COMMAND_SET_DEFAULT_SINK, + PA_COMMAND_SET_DEFAULT_SOURCE, PA_COMMAND_MAX }; diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index 23bdf68be..88f85e028 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -62,8 +62,20 @@ static const char *command_names[PA_COMMAND_MAX] = { [PA_COMMAND_PLAY_SAMPLE] = "PLAY_SAMPLE", [PA_COMMAND_REMOVE_SAMPLE] = "REMOVE_SAMPLE", [PA_COMMAND_GET_SERVER_INFO] = "GET_SERVER_INFO", - [PA_COMMAND_GET_SINK_INFO] = "GET_SET_INFO", + [PA_COMMAND_GET_SINK_INFO] = "GET_SINK_INFO", + [PA_COMMAND_GET_SINK_INFO_LIST] = "GET_SINK_INFO_LIST", + [PA_COMMAND_GET_SOURCE_INFO] = "GET_SOURCE_INFO", + [PA_COMMAND_GET_SOURCE_INFO_LIST] = "GET_SOURCE_INFO_LIST", + [PA_COMMAND_GET_MODULE_INFO] = "GET_MODULE_INFO", + [PA_COMMAND_GET_MODULE_INFO_LIST] = "GET_MODULE_INFO_LIST", + [PA_COMMAND_GET_CLIENT_INFO] = "GET_CLIENT_INFO", + [PA_COMMAND_GET_CLIENT_INFO_LIST] = "GET_CLIENT_INFO_LIST", + [PA_COMMAND_GET_SAMPLE_INFO] = "GET_SAMPLE_INFO", + [PA_COMMAND_GET_SAMPLE_INFO_LIST] = "GET_SAMPLE_INFO_LIST", [PA_COMMAND_GET_SINK_INPUT_INFO] = "GET_SINK_INPUT_INFO", + [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = "GET_SINK_INPUT_INFO_LIST", + [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = "GET_SOURCE_OUTPUT_INFO", + [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = "GET_SOURCE_OUTPUT_INFO_LIST", [PA_COMMAND_SUBSCRIBE] = "SUBSCRIBE", [PA_COMMAND_SUBSCRIBE_EVENT] = "SUBSCRIBE_EVENT", [PA_COMMAND_SET_SINK_VOLUME] = "SET_SINK_VOLUME", @@ -71,7 +83,6 @@ static const char *command_names[PA_COMMAND_MAX] = { [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = "TRIGGER_PLAYBACK_STREAM", [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = "FLUSH_PLAYBACK_STREAM", [PA_COMMAND_CORK_PLAYBACK_STREAM] = "CORK_PLAYBACK_STREAM", - }; #endif @@ -174,7 +185,14 @@ int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *use goto finish; #ifdef DEBUG_OPCODES - pa_log(__FILE__": Recieved opcode <%s>\n", command_names[command]); +{ + char t[256]; + char const *p; + if (!(p = command_names[command])) + snprintf((char*) (p = t), sizeof(t), "%u", command); + + pa_log(__FILE__": Recieved opcode <%s>\n", p); +} #endif if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) { diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 87b4114ac..9e18abfd1 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -22,7 +22,7 @@ #load module-alsa-sink #load module-alsa-source device=plughw:1,0 -#load module-oss device="/dev/dsp" sink_name=output source_name=input +load module-oss device="/dev/dsp" sink_name=output source_name=input record=0 #load module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #load module-pipe-sink @@ -46,8 +46,8 @@ load module-native-protocol-unix load module-cli # Make some devices default -sink_default output -source_default input +#isink_default output +#source_default input .nofail @@ -57,6 +57,6 @@ scache_load /usr/share/sounds/KDE_Notify.wav x11-bell # Load X11 bell module #load module-x11-bell sample=x11-bell sink=output -load module-pipe-source -load module-pipe-sink +#load module-pipe-source +#load module-pipe-sink diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 94df7ec00..a810bd984 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -633,3 +633,43 @@ fail: return -1; } + +struct pa_operation* pa_context_set_default_sink(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_DEFAULT_SINK); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_set_default_source(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_DEFAULT_SOURCE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); +} diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index c7d207034..65befbb39 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -98,6 +98,12 @@ struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct p * would never complete. */ void pa_context_exit_daemon(struct pa_context *c); +/** Set the name of the default sink. \since 0.4 */ +struct pa_operation* pa_context_set_default_sink(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata); + +/** Set the name of the default source. \since 0.4 */ +struct pa_operation* pa_context_set_default_source(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata); + PA_C_DECL_END #endif diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index f0ecc5c46..067ebf891 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -106,7 +106,8 @@ enum pa_subscription_mask { PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8, /**< Source output events */ PA_SUBSCRIPTION_MASK_MODULE = 16, /**< Module events */ PA_SUBSCRIPTION_MASK_CLIENT = 32, /**< Client events */ - PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64 /**< Sample cache events */ + PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */ + PA_SUBSCRIPTION_MASK_SERVER = 128 /**< Other global server changes. \since 0.4 */ }; /** Subscription event types, as used by pa_context_subscribe() */ @@ -118,6 +119,7 @@ enum pa_subscription_event_type { PA_SUBSCRIPTION_EVENT_MODULE = 4, /**< Event type: Module */ PA_SUBSCRIPTION_EVENT_CLIENT = 5, /**< Event type: Client */ PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6, /**< Event type: Sample cache item */ + PA_SUBSCRIPTION_EVENT_SERVER = 7, /**< Event type: Global server change, only occuring with PA_SUBSCRIPTION_EVENT_CHANGE. \since 0.4 */ PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 7, /**< A mask to extract the event type from an event value */ PA_SUBSCRIPTION_EVENT_NEW = 0, /**< A new object was created */ diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index b31a40c7a..2baeb540d 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -83,7 +83,10 @@ static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t c pa_tagstruct_gets(t, &i.user_name) < 0 || pa_tagstruct_gets(t, &i.host_name) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_gets(t, &i.default_sink_name) < 0 || + pa_tagstruct_gets(t, &i.default_source_name) < 0 || !pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -174,6 +177,27 @@ struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uin return pa_operation_ref(o); } +struct pa_operation* pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o); + + return pa_operation_ref(o); +} + /*** Source info ***/ static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { @@ -244,6 +268,27 @@ struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, u return pa_operation_ref(o); } +struct pa_operation* pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o); + + return pa_operation_ref(o); +} + /*** Client info ***/ static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 0a14fad09..3da71b807 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -96,6 +96,8 @@ struct pa_server_info { const char *server_version; /**< Version string of the daemon */ const char *server_name; /**< Server package name (usually "polypaudio") */ struct pa_sample_spec sample_spec; /**< Default sample specification */ + const char *default_sink_name; /**< Name of default sink. \since 0.4 */ + const char *default_source_name; /**< Name of default sink. \since 0.4*/ }; /** Get some information about the server */ diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 1ec1b6088..3d6114cf8 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -138,6 +138,7 @@ static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_ static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -182,6 +183,8 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_CORK_PLAYBACK_STREAM] = { command_cork_playback_stream }, [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, + [PA_COMMAND_SET_DEFAULT_SINK] = { command_set_default_sink_or_source }, + [PA_COMMAND_SET_DEFAULT_SOURCE] = { command_set_default_sink_or_source }, }; /* structure management */ @@ -1221,6 +1224,8 @@ static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, u pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt))); pa_tagstruct_puts(reply, pa_get_host_name(txt, sizeof(txt))); pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec); + pa_tagstruct_puts(reply, c->protocol->core->default_sink_name ? c->protocol->core->default_sink_name : ""); + pa_tagstruct_puts(reply, c->protocol->core->default_source_name ? c->protocol->core->default_source_name : ""); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1373,6 +1378,28 @@ static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, ui request_bytes(s); } +static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + const char *s; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + pa_tagstruct_gets(t, &s) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + pa_namereg_set_default(c->protocol->core, s, command == PA_COMMAND_SET_DEFAULT_SOURCE ? PA_NAMEREG_SOURCE : PA_NAMEREG_SINK); + pa_pstream_send_simple_ack(c->pstream, tag); +} + /*** pstream callbacks ***/ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { From 93c8fe6577b59176ed6a54a1ae98f8749f122dc8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 7 Sep 2004 14:58:42 +0000 Subject: [PATCH 0180/1514] change the way the default sink/source is selected git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@183 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +- polyp/cli-command.c | 24 +++++++++++++- polyp/core.c | 1 + polyp/core.h | 1 - polyp/namereg.c | 69 +++++++++++++++++++++++++++-------------- polyp/namereg.h | 5 +++ polyp/polypaudio.pa | 2 +- polyp/polyplib-stream.c | 2 +- polyp/protocol-native.c | 8 +++-- 9 files changed, 84 insertions(+), 31 deletions(-) diff --git a/doc/todo b/doc/todo index 9ef5f9c44..f8a5ce866 100644 --- a/doc/todo +++ b/doc/todo @@ -10,11 +10,12 @@ autoload management - more complete pactl - add sample directory -- add timing parameter to write callback of stream in client API - config file for command line arguments + - add FAQ - pa_context_connect_spawn(): change function to fork+exec+waitpid-like function - on delete event in paman +- add feature to dump config file ** later *** - xmlrpc/http diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 1d2788fa5..4c4f566b1 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -210,8 +210,30 @@ static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer } static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + char s[256]; assert(c && t); - pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %u bytes.\nMemory blocks allocated during the whole lifetime: %u, size: %u bytes.\n", c->memblock_stat->total, c->memblock_stat->total_size, c->memblock_stat->allocated, c->memblock_stat->allocated_size); + + pa_bytes_snprint(s, sizeof(s), c->memblock_stat->total_size); + pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n", + c->memblock_stat->total, + s); + + pa_bytes_snprint(s, sizeof(s), c->memblock_stat->allocated_size); + pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n", + c->memblock_stat->allocated, + s); + + pa_bytes_snprint(s, sizeof(s), pa_scache_total_size(c)); + pa_strbuf_printf(buf, "Total sample cache size: %s.\n", s); + + pa_sample_spec_snprint(s, sizeof(s), &c->default_sample_spec); + pa_strbuf_printf(buf, "Default sample spec: %s\n", s); + + pa_strbuf_printf(buf, "Default sink name: %s\n" + "Default source name: %s\n", + pa_namereg_get_default_sink_name(c), + pa_namereg_get_default_source_name(c)); + return 0; } diff --git a/polyp/core.c b/polyp/core.c index 4362f0cb5..5d79a3650 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -139,3 +139,4 @@ void pa_core_check_quit(struct pa_core *c) { c->quit_event = NULL; } } + diff --git a/polyp/core.h b/polyp/core.h index ca37507ca..ddba6a833 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -55,7 +55,6 @@ struct pa_core { struct pa_core* pa_core_new(struct pa_mainloop_api *m); void pa_core_free(struct pa_core*c); - void pa_core_check_quit(struct pa_core *c); #endif diff --git a/polyp/namereg.c b/polyp/namereg.c index 44a9cdc6c..5791a3e45 100644 --- a/polyp/namereg.c +++ b/polyp/namereg.c @@ -122,30 +122,10 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t assert(c); if (!name) { - if (type == PA_NAMEREG_SOURCE) { - if (!c->default_source_name) { - struct pa_source *s; - - for (s = pa_idxset_first(c->sources, &index); s; s = pa_idxset_next(c->sources, &index)) - if (!s->monitor_of) { - pa_namereg_set_default(c, s->name, PA_NAMEREG_SOURCE); - break; - } - } - - name = c->default_source_name; - - } else if (type == PA_NAMEREG_SINK) { - - if (!c->default_sink_name) { - struct pa_sink *s; - - if ((s = pa_idxset_first(c->sinks, NULL))) - pa_namereg_set_default(c, s->name, PA_NAMEREG_SINK); - } - - name = c->default_sink_name; - } + if (type == PA_NAMEREG_SOURCE) + name = pa_namereg_get_default_source_name(c); + else if (type == PA_NAMEREG_SINK) + name = pa_namereg_get_default_sink_name(c); } if (!name) @@ -197,3 +177,44 @@ void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_ *s = pa_xstrdup(name); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX); } + +const char *pa_namereg_get_default_sink_name(struct pa_core *c) { + struct pa_sink *s; + assert(c); + + if (c->default_sink_name) + return c->default_sink_name; + + if ((s = pa_idxset_first(c->sinks, NULL))) + pa_namereg_set_default(c, s->name, PA_NAMEREG_SINK); + + if (c->default_sink_name) + return c->default_sink_name; + + return NULL; +} + +const char *pa_namereg_get_default_source_name(struct pa_core *c) { + struct pa_source *s; + uint32_t index; + + assert(c); + + if (c->default_source_name) + return c->default_source_name; + + for (s = pa_idxset_first(c->sources, &index); s; s = pa_idxset_next(c->sources, &index)) + if (!s->monitor_of) { + pa_namereg_set_default(c, s->name, PA_NAMEREG_SOURCE); + break; + } + + if (!c->default_source_name) + if ((s = pa_idxset_first(c->sources, NULL))) + pa_namereg_set_default(c, s->name, PA_NAMEREG_SOURCE); + + if (c->default_source_name) + return c->default_source_name; + + return NULL; +} diff --git a/polyp/namereg.h b/polyp/namereg.h index b8db11053..f1be39588 100644 --- a/polyp/namereg.h +++ b/polyp/namereg.h @@ -37,4 +37,9 @@ void pa_namereg_unregister(struct pa_core *c, const char *name); void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type, int autoload); void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_type type); + +const char *pa_namereg_get_default_sink_name(struct pa_core *c); +const char *pa_namereg_get_default_source_name(struct pa_core *c); + + #endif diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 9e18abfd1..40012fd66 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -21,7 +21,7 @@ # Load audio drivers statically #load module-alsa-sink -#load module-alsa-source device=plughw:1,0 +load module-alsa-source device=plughw:1,0 load module-oss device="/dev/dsp" sink_name=output source_name=input record=0 #load module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #load module-pipe-sink diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 7170a32eb..a66a0fc6a 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -239,7 +239,7 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_puts(t, s->name); pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, dev ? dev : ""); pa_tagstruct_putu32(t, s->buffer_attr.maxlength); if (s->direction == PA_STREAM_PLAYBACK) { diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 3d6114cf8..943d6b22d 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -1203,6 +1203,7 @@ static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, u struct connection *c = userdata; struct pa_tagstruct *reply; char txt[256]; + const char *n; assert(c && t); if (!pa_tagstruct_eof(t)) { @@ -1224,8 +1225,11 @@ static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, u pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt))); pa_tagstruct_puts(reply, pa_get_host_name(txt, sizeof(txt))); pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec); - pa_tagstruct_puts(reply, c->protocol->core->default_sink_name ? c->protocol->core->default_sink_name : ""); - pa_tagstruct_puts(reply, c->protocol->core->default_source_name ? c->protocol->core->default_source_name : ""); + + n = pa_namereg_get_default_sink_name(c->protocol->core); + pa_tagstruct_puts(reply, n ? n : ""); + n = pa_namereg_get_default_source_name(c->protocol->core); + pa_tagstruct_puts(reply, n ? n : ""); pa_pstream_send_tagstruct(c->pstream, reply); } From 70007175d28cf4c7323e772683bbe084e62df024 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 7 Sep 2004 17:06:54 +0000 Subject: [PATCH 0181/1514] implemented new CLI command: dump add prefork() and postfork() arguments to pa_context_connect_spawn() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@184 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 9 ++-- polyp/cli-command.c | 94 ++++++++++++++++++++++++++++++++++++++++ polyp/pacat.c | 2 +- polyp/polypaudio.pa | 12 ++--- polyp/polyplib-context.c | 19 ++++++-- polyp/polyplib-context.h | 14 ++++-- 6 files changed, 130 insertions(+), 20 deletions(-) diff --git a/doc/todo b/doc/todo index f8a5ce866..4232a4d42 100644 --- a/doc/todo +++ b/doc/todo @@ -1,6 +1,8 @@ *** $Id$ *** -*** 0.4 *** +- add FAQ + +*** 0.5 *** - make mcalign merge chunks - use ref counting in more objects (i.e. sink, source, sink_input, source_output) - unix socket directories include user name @@ -12,11 +14,6 @@ - add sample directory - config file for command line arguments -- add FAQ -- pa_context_connect_spawn(): change function to fork+exec+waitpid-like function -- on delete event in paman -- add feature to dump config file - ** later *** - xmlrpc/http - dbus diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 4c4f566b1..52926199e 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -82,6 +82,7 @@ static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, s static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static const struct command commands[] = { { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, @@ -115,6 +116,7 @@ static const struct command commands[] = { { "autoload_source_add", pa_cli_command_autoload_add, "Add autoload entry for a source (args: source, name, arguments)", 4}, { "autoload_sink_remove", pa_cli_command_autoload_remove, "Remove autoload entry for a sink (args: sink)", 2}, { "autoload_source_remove", pa_cli_command_autoload_remove, "Remove autoload entry for a source (args: source)", 2}, + { "dump", pa_cli_command_dump, "Dump daemon configuration", 1}, { NULL, NULL, NULL, 0 } }; @@ -596,6 +598,98 @@ static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer * return 0; } +static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + struct pa_module *m; + struct pa_sink *s; + int nl; + const char *p; + uint32_t index; + char txt[256]; + time_t now; + void *i; + struct pa_autoload_entry *a; + + assert(c && t); + + time(&now); + + pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt)); + + + for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) { + if (m->auto_unload) + continue; + + pa_strbuf_printf(buf, "load %s", m->name); + + if (m->argument) + pa_strbuf_printf(buf, " %s", m->argument); + + pa_strbuf_puts(buf, "\n"); + } + + nl = 0; + + for (s = pa_idxset_first(c->sinks, &index); s; s = pa_idxset_next(c->sinks, &index)) { + if (s->volume == PA_VOLUME_NORM) + continue; + + if (s->owner && s->owner->auto_unload) + continue; + + if (!nl) { + pa_strbuf_puts(buf, "\n"); + nl = 1; + } + + pa_strbuf_printf(buf, "sink_volume %s 0x%03x\n", s->name, s->volume); + } + + + if (c->autoload_hashmap) { + nl = 0; + + i = NULL; + while ((a = pa_hashmap_iterate(c->autoload_hashmap, &i))) { + + if (!nl) { + pa_strbuf_puts(buf, "\n"); + nl = 1; + } + + pa_strbuf_printf(buf, "autoload_%s_add %s %s", a->type == PA_NAMEREG_SINK ? "sink" : "source", a->name, a->module); + + if (a->argument) + pa_strbuf_printf(buf, " %s", a->argument); + + pa_strbuf_puts(buf, "\n"); + } + } + + nl = 0; + + if ((p = pa_namereg_get_default_sink_name(c))) { + if (!nl) { + pa_strbuf_puts(buf, "\n"); + nl = 1; + } + pa_strbuf_printf(buf, "sink_default %s\n", p); + } + + if ((p = pa_namereg_get_default_source_name(c))) { + if (!nl) { + pa_strbuf_puts(buf, "\n"); + nl = 1; + } + pa_strbuf_printf(buf, "source_default %s\n", p); + } + + pa_strbuf_puts(buf, "\n### EOF\n"); + + return 0; +} + + int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) { const char *cs; diff --git a/polyp/pacat.c b/polyp/pacat.c index 40301be88..0ad5fa525 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -357,7 +357,7 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect_spawn(context, NULL); + pa_context_connect_spawn(context, NULL, NULL, NULL); /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 40012fd66..15434627c 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -28,15 +28,15 @@ load module-oss device="/dev/dsp" sink_name=output source_name=input record=0 # Load audio drivers automatically on access -#autoload_sink_add output module-oss device="/dev/adsp" sink_name=output source_name=input -#autoload_source_add input module-oss device="/dev/adsp" sink_name=output source_name=input +#autoload_sink_add output module-oss device="/dev/dsp" sink_name=output source_name=input +#autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input #autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_sink_add output module-alsa-sink sink_name=output #autoload_source_add input module-alsa-source source_name=input # Load several protocols -#load module-esound-protocol-tcp +load module-esound-protocol-tcp #load module-simple-protocol-tcp load module-native-protocol-unix #load module-cli-protocol-unix @@ -46,8 +46,8 @@ load module-native-protocol-unix load module-cli # Make some devices default -#isink_default output -#source_default input +sink_default output +source_default input .nofail @@ -55,7 +55,7 @@ load module-cli scache_load /usr/share/sounds/KDE_Notify.wav x11-bell # Load X11 bell module -#load module-x11-bell sample=x11-bell sink=output +load module-x11-bell sample=x11-bell sink=output #load module-pipe-source #load module-pipe-sink diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index a810bd984..caaa1dbb9 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -571,9 +571,9 @@ static int is_running(void) { return 1; } -int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)) { +int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void), void (*prefork)(void), void (*postfork)(void)) { pid_t pid; - int status; + int status, r; int fds[2] = { -1, -1} ; struct pa_iochannel *io; @@ -586,9 +586,16 @@ int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)) { goto fail; } + if (prefork) + prefork(); + if ((pid = fork()) < 0) { pa_log(__FILE__": fork() failed: %s\n", strerror(errno)); pa_context_fail(c, PA_ERROR_INTERNAL); + + if (postfork) + postfork(); + goto fail; } else if (!pid) { char t[64]; @@ -610,7 +617,13 @@ int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)) { } /* Parent */ - if (waitpid(pid, &status, 0) < 0) { + + r = waitpid(pid, &status, 0); + + if (postfork) + postfork(); + + if (r < 0) { pa_log(__FILE__": waitpid() failed: %s\n", strerror(errno)); pa_context_fail(c, PA_ERROR_INTERNAL); goto fail; diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 65befbb39..4b199751b 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -82,10 +82,16 @@ int pa_context_connect(struct pa_context *c, const char *server); /** Connect the context to a server. If the default server is local * but not accessible, spawn a new daemon. If atfork is not NULL it is * run after the fork() in the child process. It may be used to close - * file descriptors or to do any other cleanups. Make sure that - * SIGCHLD is handled when calling this function. The function will - * waitpid() on the daemon's PID. \since 0.4 */ -int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)); + * file descriptors or to do any other cleanups. (It is not safe to + * close all file descriptors unconditionally, since a UNIX socket is + * passed to the new process.) if prefork is not NULL it is run just + * before forking in the parent process. Use this to block SIGCHLD + * handling if required. If postfork is not NULL it is run just after + * forking in the parent process. Use this to unblock SIGCHLD if + * required. The function will waitpid() on the daemon's PID, but + * will not block or ignore SIGCHLD signals, since this cannot be done + * in a thread compatible way. \since 0.4 */ +int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void), void (*prefork)(void), void (*postfork)(void)); /** Terminate the context connection immediately */ void pa_context_disconnect(struct pa_context *c); From 13248fd8e6cb44e489bd2d77d5ec3491287a1f4d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 7 Sep 2004 22:40:43 +0000 Subject: [PATCH 0182/1514] documentation update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@185 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 +-- doc/FAQ.html.in | 77 +++++++++++++++++++++++++++++++++++++++++ doc/Makefile.am | 5 +-- doc/README.html.in | 13 +++++-- doc/cli.html.in | 6 +++- doc/daemon.html.in | 13 +++++-- doc/modules.html.in | 30 ++++++++++++++-- doc/todo | 3 +- polyp/Makefile.am | 2 +- polyp/module-oss-mmap.c | 9 ++--- polyp/module-oss.c | 8 +++-- 11 files changed, 147 insertions(+), 23 deletions(-) create mode 100644 doc/FAQ.html.in diff --git a/configure.ac b/configure.ac index f221689d4..d278ff8e4 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.3],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.4],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) @@ -118,5 +118,5 @@ AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) -AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h]) +AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h doc/FAQ.html]) AC_OUTPUT diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in new file mode 100644 index 000000000..074561c1f --- /dev/null +++ b/doc/FAQ.html.in @@ -0,0 +1,77 @@ + + + + +polypaudio: FAQ + + + + + + +

    Frequently Asked Questions

    + +
      +
    1. How does Polypaudio compare with ESOUND/aRts/NAS?

      + +

      Polypaudio is sound daemon similar to ESOUND and NAS, but much more + powerful. aRts is a realtime-synthesizer-cum-sound-server, i.e. it + does much more than Polypaudio. However, I believe that Polypaudio + does what it does much better than any other free sound server.

      +
    2. + +
    3. What about ESOUND compatibility?

      +

      Polypaudio is a drop in replacement for ESOUND. That means: you can + load a esound compatibility module which implements an ESOUND + compatible protocol which allows you to use most of the classic ESOUND + compatible programs (including the command line programs like + esdcat).

      +
    4. + +
    5. Is Polypaudio a GNOME program?

      +

      No, Polypaudio has no dependency on GNOME/GTK/GLIB. All it requires + is a UNIX-like operating system and very few dependency + libraries. However, the accompanying GUI tools are writen with + gtkmm, i.e. require both GLIB and GTK.

    6. + +
    7. Can I integrate Polypaudio in my GLIB/GTK/GNOME application?

      +

      Yes! Polypaudio comes with a GLIB main loop adapter. You can embed + both the client library and the daemon (!) into your GLIB based + application.

    8. + +
    9. Can I integrate Polypaudio in my Qt/KDE application?

      +

      Yes! Polypaudio uses a main loop abstraction layer that allows you + to integrate Polypaudio in any program that supports main + loops. Unfortunately there is no adapter for Qt publicly available yet.

    10. + +
    11. I want to write a new driver for Polypaudio, are there any docs?

      +

      Currently, only the client API is documented with doxygen. Read + the source and base your work on a simple module like + module-pipe-sink.

    12. + +
    13. What about compatibility with NAS?

      +

      Is not available (yet?). It is doable, but noone has implemented it yet.

    14. + +
    15. What about compatibility with aRts?

      +

      Is not available. Since aRts is as synthesizer application you'd have to + reimplement very much code for Polypaudio. It should be easy to + implement limited support for libartsc based + applications. Noone has done this yet. It is probably a better idea to + run arts on top of Polypaudio (through a polypaudio driver + for aRts, which nobody has written yet). Another solution would be to + embed Polypaudio in the aRts process.

    16. + +
    17. I often hear noises when playing back with Polypaudio, what can I do?

      +

      There are to possible solutions: either make the polypaudio + binary SUID root (chmod u+s /usr/bin/polypaudio) and run it + with argument -r or increase the fragment sizes of the audio + drivers. The former will allow Polypaudio to activate + SCHED_FIFO high priority scheduling (root rights are dropped + immediately after this).

    18. + +
    + +
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    +
    $Id$
    + diff --git a/doc/Makefile.am b/doc/Makefile.am index 6101521cf..723a92c8f 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -17,9 +17,9 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. noinst_DATA = README.html cli.html modules.html daemon.html README -EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in todo +EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in todo FAQ.html.in -MAINTAINERCLEANFILES = README README.html cli.html modules.html daemon.html +MAINTAINERCLEANFILES = README README.html cli.html modules.html daemon.html FAQ.html CLEANFILES = if USE_LYNX @@ -34,6 +34,7 @@ tidy: README.html cli.html modules.html daemon.html tidy -e < cli.html tidy -e < daemon.html tidy -e < modules.html + tidy -e < FAQ.html .PHONY: tidy diff --git a/doc/README.html.in b/doc/README.html.in index f34546328..5af5c4438 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -44,9 +44,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    News

    +
    Wed Sep 8 2004:

    Version 0.4 released; +changes include: daemon auto spawning, support for SCHED_FIFO scheduling, three new modules, proper logging, CPU load watchdog, many fixes.

    +
    Fri Aug 27 2004:

    Version 0.3 released; -changes include: support for both glib 2.0 and glib 1.2, future cancellation, API updates, many fixes; relicense client library to LGPL.

    +changes include: support for both glib 2.0 and glib 1.2, future cancellation, API updates, many fixes, relicense client library to LGPL.

    Fri Aug 20 2004:

    Version 0.2 released; @@ -90,7 +94,10 @@ attempt to write a sound server asd.

    A GTK GUI manager application for polypaudio is the Polypaudio Manager. There are output plugins for XMMS and libao.

    +href="http://0pointer.de/lennart/projects/paman/">Polypaudio +Manager. Another GTK GUI tool for Polypaudio is the Polypaudio Volume Meter. There are output plugins for XMMS and libao.

    Status

    @@ -105,7 +112,7 @@ release to release. The client API's library version number is currently fixed t

    There is some preliminary documentation available: modules.html, cli.html, daemon.html.

    +href="daemon.html">daemon.html, FAQ.html, .

    First Steps

    diff --git a/doc/cli.html.in b/doc/cli.html.in index 01c04cc9a..6f84a07d9 100644 --- a/doc/cli.html.in +++ b/doc/cli.html.in @@ -125,6 +125,10 @@ name.

    Play an audio file to a sink. Expects the file name and the sink name as argumens.

    +

    dump

    + +

    Dump the daemon's current configuration in CLI commands.

    +

    Killing Clients/Streams

    kill_client

    @@ -192,6 +196,6 @@ play_file /usr/share/sounds/startup3.wav output
    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, August 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    $Id$
    diff --git a/doc/daemon.html.in b/doc/daemon.html.in index a5d933dbc..e4903a8ba 100644 --- a/doc/daemon.html.in +++ b/doc/daemon.html.in @@ -13,21 +13,28 @@ The polypaudio daemon accepts several command line arguments: +

    -r: Set low nice value (high priority) and SCHED_FIFO scheduling if available. Works only when started as root or SUID root.

    +

    -R: Don't drop root rights if started SUID root.

    -L MODULE: Load the specified module. This option may be specified more than once.

    -F FILE: Run the specified script. This option may be specified more than once.

    -C: Load the module module-cli after startup.

    +

    -n: Don't load the default configuration file. Normally ~/.polypaudio or /etc/polyp/polypaudio.pa are loaded on startup.

    -D: Daemonize after successfully executing all scripts and loading all modules.

    +

    -d: Disallow module load and unload after startup.

    -f: Unless this option is given the daemon will terminate if any of the specified modules failed to load or the script didn't execute successfully.

    -v: Increase the verbosity of the daemon.

    +

    -X SECS: Terminate the daemon after the last client exited an SECS seconds passed.

    -h: Show a quick help.

    +

    -l TARGET: Specify the log target (syslog, stderr, auto). Defaults to auto, which means stderr when run without -D and syslog when run with -D.

    +

    -V: Show version.

    Example

    It is a good idea to run the daemon like this:

    -
    polypaudio -D -F /etc/polypaudio/polypaudio.pa
    +
    polypaudio -rD
    -

    /etc/polypaudio/polypaudio.pa should be a script written in the CLI language described in cli.html +

    This will run /etc/polypaudio/polypaudio.pa after startup. This should be a script written in the CLI language described in cli.html.

    Signals

    @@ -46,6 +53,6 @@ The polypaudio daemon accepts several command line arguments:

    The daemon tries to load the module module-cli-protocol-unix, effectively providing a command line interface on a special UNIX domain socket.


    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    $Id$
    diff --git a/doc/modules.html.in b/doc/modules.html.in index fe202989e..22a565d66 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -30,7 +30,18 @@ special file in the file system. The sink name defaults to pipe_output.

    The following option is supported:

    - + +
    file=The name of the FIFO special file to use
    file=The name of the FIFO special file to use. (defaults to: /tmp/music.output)
    + +

    module-pipe-source

    + +

    Provides a simple test source that reads the audio data from a FIFO +special file in the file system. The source name defaults to pipe_input.

    + +

    The following option is supported:

    + + +
    file=The name of the FIFO special file to use. (defaults to: /tmp/music.input)
    @@ -184,6 +195,12 @@ about the two possible suffixes of this module.

    cookie=Name of the cookie file for authentication purposes +

    module-native-protocol-fd

    + +

    This is used internally when auto spawning a new daemon.

    + +

    Miscellaneous

    +

    module-x11-bell

    Intercepts X11 bell events and plays a sample from the sample cache on each occurence.

    @@ -194,7 +211,16 @@ about the two possible suffixes of this module.

    sink=Name of the sink to play the sample on. If ommited defaults to the default sink. +

    module-sine

    + +

    Creates a sink input and generates a sine waveform stream.

    + + + + +
    sink=The sink to connect to. If ommited defaults to the default sink.
    frequency=The frequency to generate in Hertz. Defaults to 440.
    +
    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, August 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    $Id$
    diff --git a/doc/todo b/doc/todo index 4232a4d42..daed68643 100644 --- a/doc/todo +++ b/doc/todo @@ -1,7 +1,5 @@ *** $Id$ *** -- add FAQ - *** 0.5 *** - make mcalign merge chunks - use ref counting in more objects (i.e. sink, source, sink_input, source_output) @@ -13,6 +11,7 @@ - more complete pactl - add sample directory - config file for command line arguments +- option to use default fragment size on alsa drivers ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 392154972..b5acb3fcf 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -21,7 +21,7 @@ polypincludedir=$(includedir)/polyp polypconfdir=$(sysconfdir)/polyp AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) -#AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" +AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" AM_CFLAGS+="-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/polypaudio.pa\"" AM_CFLAGS+="-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\"" diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 8151a13af..953871d1b 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -249,7 +249,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { nfrags = 12; frag_size = 1024; - if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) { + if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { pa_log(__FILE__": failed to parse fragments arguments\n"); goto fail; } @@ -269,9 +269,10 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { } pa_log(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); - - if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0) - goto fail; + + if (nfrags >= 2 && frag_size >= 1) + if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0) + goto fail; if (pa_oss_auto_format(u->fd, &u->sample_spec) < 0) goto fail; diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 53f1f994d..95deca9c1 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -202,7 +202,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { nfrags = 12; frag_size = 1024; - if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || nfrags < 2 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0 || frag_size < 1) { + if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { pa_log(__FILE__": failed to parse fragments arguments\n"); goto fail; } @@ -218,8 +218,10 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { pa_log(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); - if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) - goto fail; + + if (nfrags >= 2 && frag_size >= 1) + if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) + goto fail; if (pa_oss_auto_format(fd, &ss) < 0) goto fail; From 5fc0cf2308fb38ffdb9ffaf9d5eccd33f21e9aa3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 7 Sep 2004 23:01:14 +0000 Subject: [PATCH 0183/1514] date fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@186 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README.html.in b/doc/README.html.in index 5af5c4438..837cb0120 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -195,7 +195,7 @@ compilation and make install (as root) for installation of

    If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.


    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, August 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    $Id$
    From 0c99fb31826fba0ed4f904d04dd56f1df3663a3e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 8 Sep 2004 00:08:12 +0000 Subject: [PATCH 0184/1514] add FAQ to homepage git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@187 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index e27204f6b..c8592f863 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,7 +35,7 @@ homepage: all dist doxygen test -d $$HOME/homepage/private mkdir -p $$HOME/homepage/private/projects/polypaudio $$HOME/homepage/private/projects/polypaudio/doxygen cp polypaudio-@PACKAGE_VERSION@.tar.gz $$HOME/homepage/private/projects/polypaudio - cp doc/README.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/polypaudio + cp doc/README.html doc/FAQ.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/polypaudio cp -a doxygen/html/* $$HOME/homepage/private/projects/polypaudio/doxygen cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html From 25123469d53e2ef555549984ea4e8b028c1632fb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 10 Sep 2004 22:35:12 +0000 Subject: [PATCH 0185/1514] add support for module search path as command line argument protocol-native: move first data request into ack of stream creation improve mainloop API: return the number of dispatched sources on iterate() fix a resampling bug introduce network latency measurement WARNING: all these changes together may break some applications git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@189 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- doc/todo | 14 +++++++-- polyp/cmdline.c | 10 +++++- polyp/cmdline.h | 1 + polyp/main.c | 4 +++ polyp/mainloop.c | 66 +++++++++++++++++++++++++++------------- polyp/mainloop.h | 2 +- polyp/memblockq.c | 4 +-- polyp/polyplib-context.c | 9 +++--- polyp/polyplib-def.h | 4 ++- polyp/polyplib-stream.c | 22 ++++++++++++++ polyp/protocol-native.c | 12 ++++++-- polyp/pstream.c | 4 ++- polyp/resampler.c | 20 ++++++++++-- polyp/sconv-s16le.c | 4 +++ polyp/sink-input.c | 9 +++--- polyp/tagstruct.c | 24 +++++++++++++++ polyp/tagstruct.h | 2 ++ polyp/util.c | 52 +++++++++++++++++++++++-------- polyp/util.h | 5 ++- 20 files changed, 210 insertions(+), 60 deletions(-) diff --git a/configure.ac b/configure.ac index d278ff8e4..3b12b72bd 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.4],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.5],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) diff --git a/doc/todo b/doc/todo index daed68643..35e0b224e 100644 --- a/doc/todo +++ b/doc/todo @@ -12,6 +12,13 @@ - add sample directory - config file for command line arguments - option to use default fragment size on alsa drivers +- keep volume in xmms-polyp (and allow volume changing when not playing) +- lazy sample cache +- per-channel volume +- add version number to library names +- extend pa_usec_t to 64 bit +- make use of network latency in all apps +- rename streams/contexts ** later *** - xmlrpc/http @@ -23,7 +30,8 @@ *********** backends for: -- mplayer -- sdl -- gstreamer - portaudio +- sdl +- gstreamer (semi-done) +- alsa-lib +- OSS (esddsp style) diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 1d6501859..e6f4101d2 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -78,6 +78,7 @@ void pa_cmdline_help(const char *argv0) { " -X SECS Terminate the daemon after the last client quit and this time passed\n" " -h Show this help\n" " -l TARGET Specify the log target (syslog, stderr, auto)\n" + " -p DIR Append a directory to the search path for dynamic modules\n" " -V Show version\n", e, cfg); pa_xfree(cfg); @@ -101,11 +102,12 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { cmdline->fail = cmdline->auto_log_target = 1; cmdline->quit_after_last_client_time = -1; cmdline->log_target = -1; + cmdline->dl_searchdir = NULL; buf = pa_strbuf_new(); assert(buf); - while ((c = getopt(argc, argv, "L:F:CDhfvrRVndX:l:")) != -1) { + while ((c = getopt(argc, argv, "L:F:CDhfvrRVndX:l:p:")) != -1) { switch (c) { case 'L': pa_strbuf_printf(buf, "load %s\n", optarg); @@ -146,6 +148,11 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { case 'X': cmdline->quit_after_last_client_time = atoi(optarg); break; + case 'p': + if (cmdline->dl_searchdir) + pa_xfree(cmdline->dl_searchdir); + cmdline->dl_searchdir = pa_xstrdup(optarg); + break; case 'l': if (!strcmp(optarg, "syslog")) { cmdline->auto_log_target = 0; @@ -185,5 +192,6 @@ fail: void pa_cmdline_free(struct pa_cmdline *cmd) { assert(cmd); pa_xfree(cmd->cli_commands); + pa_xfree(cmd->dl_searchdir); pa_xfree(cmd); } diff --git a/polyp/cmdline.h b/polyp/cmdline.h index d49b65fbd..bf909c842 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -36,6 +36,7 @@ struct pa_cmdline { quit_after_last_client_time, auto_log_target; char *cli_commands; + char *dl_searchdir; enum pa_log_target log_target; }; diff --git a/polyp/main.c b/polyp/main.c index 29a7b548e..2131877df 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -180,6 +180,10 @@ int main(int argc, char *argv[]) { r = lt_dlinit(); assert(r == 0); + + if (cmdline->dl_searchdir) + lt_dladdsearchdir(cmdline->dl_searchdir); + #ifdef DLSEARCHDIR lt_dladdsearchdir(DLSEARCHDIR); #endif diff --git a/polyp/mainloop.c b/polyp/mainloop.c index 22cd85c8d..c4e12ac1c 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -378,9 +378,10 @@ static void rebuild_pollfds(struct pa_mainloop *m) { } } -static void dispatch_pollfds(struct pa_mainloop *m) { +static int dispatch_pollfds(struct pa_mainloop *m) { uint32_t index = PA_IDXSET_INVALID; struct pa_io_event *e; + int r = 0; for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) { if (e->dead || !e->pollfd || !e->pollfd->revents) @@ -394,12 +395,16 @@ static void dispatch_pollfds(struct pa_mainloop *m) { (e->pollfd->revents & POLLERR ? PA_IO_EVENT_ERROR : 0), e->userdata); e->pollfd->revents = 0; + r++; } + + return r; } -static void dispatch_defer(struct pa_mainloop *m) { +static int dispatch_defer(struct pa_mainloop *m) { uint32_t index; struct pa_defer_event *e; + int r = 0; for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) { if (e->dead || !e->enabled) @@ -407,7 +412,10 @@ static void dispatch_defer(struct pa_mainloop *m) { assert(e->callback); e->callback(&m->api, e, e->userdata); + r++; } + + return r; } static int calc_next_timeout(struct pa_mainloop *m) { @@ -451,15 +459,16 @@ static int calc_next_timeout(struct pa_mainloop *m) { return t; } -static void dispatch_timeout(struct pa_mainloop *m) { +static int dispatch_timeout(struct pa_mainloop *m) { uint32_t index; struct pa_time_event *e; struct timeval now; int got_time = 0; + int r = 0; assert(m); if (pa_idxset_isempty(m->time_events)) - return; + return 0; for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { @@ -477,51 +486,66 @@ static void dispatch_timeout(struct pa_mainloop *m) { e->enabled = 0; e->callback(&m->api, e, &e->timeval, e->userdata); + + r++; } } + + return r; } int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { - int r; + int r, t, dispatched = 0; assert(m && !m->running); if(m->quit) { if (retval) *retval = m->retval; - return 1; + return -2; } m->running = 1; scan_dead(m); - dispatch_defer(m); + dispatched += dispatch_defer(m); if (m->rebuild_pollfds) { rebuild_pollfds(m); m->rebuild_pollfds = 0; } - do { - int t = block ? calc_next_timeout(m) : 0; - /*pa_log(__FILE__": %u\n", t);*/ - r = poll(m->pollfds, m->n_pollfds, t); - } while (r < 0 && errno == EINTR); + t = block ? calc_next_timeout(m) : 0; + r = poll(m->pollfds, m->n_pollfds, t); - dispatch_timeout(m); - - if (r > 0) - dispatch_pollfds(m); - else if (r < 0) - pa_log(__FILE__": select(): %s\n", strerror(errno)); + if (r < 0) { + if (errno == EINTR) + r = 0; + else + pa_log(__FILE__": select(): %s\n", strerror(errno)); + } else { + dispatched += dispatch_timeout(m); + + if (r > 0) + dispatched += dispatch_pollfds(m); + } m->running = 0; - return r < 0 ? -1 : 0; + +/* pa_log("dispatched: %i\n", dispatched); */ + + return r < 0 ? -1 : dispatched; } int pa_mainloop_run(struct pa_mainloop *m, int *retval) { int r; - while ((r = pa_mainloop_iterate(m, 1, retval)) == 0); - return r; + while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0); + + if (r == -2) + return 1; + else if (r < 0) + return -1; + else + return 0; } void pa_mainloop_quit(struct pa_mainloop *m, int r) { diff --git a/polyp/mainloop.h b/polyp/mainloop.h index 5d4fd9904..a0fe126fd 100644 --- a/polyp/mainloop.h +++ b/polyp/mainloop.h @@ -50,7 +50,7 @@ void pa_mainloop_free(struct pa_mainloop* m); on error or exit request. If block is nonzero, block for events if none are queued. Optionally return the return value as specified with the main loop's quit() routine in the integer variable retval points -to */ +to. On success returns the number of source dispatched in this iteration. */ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval); /** Run unlimited iterations of the main loop object until the main loop's quit() routine is called. */ diff --git a/polyp/memblockq.c b/polyp/memblockq.c index a79814be8..59794d6c1 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -149,9 +149,9 @@ int pa_memblockq_peek(struct pa_memblockq* bq, struct pa_memchunk *chunk) { void pa_memblockq_drop(struct pa_memblockq *bq, const struct pa_memchunk *chunk, size_t length) { assert(bq && chunk && length); - if (!bq->blocks || memcmp(&bq->blocks->chunk, chunk, sizeof(struct pa_memchunk))) + if (!bq->blocks || memcmp(&bq->blocks->chunk, chunk, sizeof(struct pa_memchunk))) return; - + assert(length <= bq->blocks->chunk.length); pa_memblockq_skip(bq, length); } diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index caaa1dbb9..a15e4257d 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -431,11 +431,10 @@ void pa_context_set_state_callback(struct pa_context *c, void (*cb)(struct pa_co int pa_context_is_pending(struct pa_context *c) { assert(c && c->ref >= 1); - if (c->state != PA_CONTEXT_READY) - return 0; - - assert(c->pstream && c->pdispatch); - return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch); +/* pa_log("pstream: %i\n", pa_pstream_is_pending(c->pstream)); */ +/* pa_log("pdispatch: %i\n", pa_pdispatch_is_pending(c->pdispatch)); */ + + return (c->pstream && pa_pstream_is_pending(c->pstream)) || (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) || c->client; } static void set_dispatch_callbacks(struct pa_operation *o); diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 067ebf891..176e1d3b5 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -133,7 +133,8 @@ enum pa_subscription_event_type { /** A structure for latency info. See pa_stream_get_latency(). The * total latency a sample that is written with pa_stream_write() takes - * to be played is buffer_usec+sink_usec. The buffer to which + * to be played may be estimated by + * buffer_usec+sink_usec+transport_usec. The buffer to which * buffer_usec relates may be manipulated freely (with * pa_stream_write()'s delta argument, pa_stream_flush() and friends), * the playback buffer sink_usec relates to is a FIFO which cannot be @@ -141,6 +142,7 @@ enum pa_subscription_event_type { struct pa_latency_info { pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play */ pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. */ + pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to the daemon. \since 0.5 */ int playing; /**< Non-zero when the stream is currently playing */ uint32_t queue_length; /**< Queue size in bytes. */ }; diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index a66a0fc6a..e128a773c 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -30,6 +30,7 @@ #include "polyplib-internal.h" #include "xmalloc.h" #include "pstream-util.h" +#include "util.h" struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss) { struct pa_stream *s; @@ -193,6 +194,7 @@ void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32 if (pa_tagstruct_getu32(t, &s->channel) < 0 || ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || + ((s->direction == PA_STREAM_PLAYBACK) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0) || !pa_tagstruct_eof(t)) { pa_context_fail(s->context, PA_ERROR_PROTOCOL); goto finish; @@ -202,6 +204,9 @@ void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32 pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); pa_stream_set_state(s, PA_STREAM_READY); + if (s->requested_bytes && s->ref > 1 && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); + finish: pa_stream_unref(s); } @@ -321,6 +326,7 @@ struct pa_operation * pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_operation *o = userdata; struct pa_latency_info i, *p = NULL; + struct timeval local, remote, now; assert(pd && o && o->stream && o->context); if (command != PA_COMMAND_REPLY) { @@ -331,12 +337,23 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman pa_tagstruct_getu32(t, &i.sink_usec) < 0 || pa_tagstruct_get_boolean(t, &i.playing) < 0 || pa_tagstruct_getu32(t, &i.queue_length) < 0 || + pa_tagstruct_get_timeval(t, &local) < 0 || + pa_tagstruct_get_timeval(t, &remote) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } else p = &i; + gettimeofday(&now, NULL); + + if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) + /* local and remote seem to have synchronized clocks */ + i.transport_usec = pa_timeval_diff(&remote, &local); + else + /* clocks are not synchronized, let's estimate latency then */ + i.transport_usec = pa_timeval_diff(&now, &local)/2; + if (o->callback) { void (*cb)(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) = o->callback; cb(o->stream, p, o->userdata); @@ -351,6 +368,7 @@ struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struc uint32_t tag; struct pa_operation *o; struct pa_tagstruct *t; + struct timeval now; o = pa_operation_new(s->context, s); assert(o); @@ -362,6 +380,10 @@ struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struc pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); + + gettimeofday(&now, NULL); + pa_tagstruct_put_timeval(t, &now); + pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, o); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 943d6b22d..058ba9cc5 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -342,7 +342,7 @@ static void request_bytes(struct playback_stream *s) { if (!(l = pa_memblockq_missing(s->memblockq))) return; - + if (l <= s->requested_bytes) return; @@ -361,7 +361,7 @@ static void request_bytes(struct playback_stream *s) { pa_tagstruct_putu32(t, l); pa_pstream_send_tagstruct(s->connection->pstream, t); - /*pa_log(__FILE__": Requesting %u bytes\n", l);*/ +/* pa_log(__FILE__": Requesting %u bytes\n", l); */ } static void send_memblock(struct connection *c) { @@ -541,6 +541,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com pa_tagstruct_putu32(reply, s->index); assert(s->sink_input); pa_tagstruct_putu32(reply, s->sink_input->index); + pa_tagstruct_putu32(reply, s->requested_bytes = pa_memblockq_missing(s->memblockq)); pa_pstream_send_tagstruct(c->pstream, reply); request_bytes(s); } @@ -809,10 +810,12 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma struct connection *c = userdata; struct pa_tagstruct *reply; struct playback_stream *s; + struct timeval tv, now; uint32_t index; assert(c && t); if (pa_tagstruct_getu32(t, &index) < 0 || + pa_tagstruct_get_timeval(t, &tv) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -836,6 +839,9 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma pa_tagstruct_putu32(reply, pa_sink_get_latency(s->sink_input->sink)); pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq)); pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq)); + pa_tagstruct_put_timeval(reply, &tv); + gettimeofday(&now, NULL); + pa_tagstruct_put_timeval(reply, &now); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1439,7 +1445,7 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui /*pa_log(__FILE__": after_recv: %u\n", pa_memblockq_get_length(p->memblockq));*/ pa_sink_notify(p->sink_input->sink); - /*pa_log(__FILE__": Recieved %u bytes.\n", chunk->length);*/ +/* pa_log(__FILE__": Recieved %u bytes.\n", chunk->length); */ } else { struct upload_stream *u = (struct upload_stream*) stream; diff --git a/polyp/pstream.c b/polyp/pstream.c index 1883c95d6..4ee296cec 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -215,7 +215,7 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { struct item_info *i; assert(p && packet); - /*pa_log(__FILE__": push-packet %p\n", packet);*/ +/* pa_log(__FILE__": push-packet %p\n", packet); */ i = pa_xmalloc(sizeof(struct item_info)); i->type = PA_PSTREAM_ITEM_PACKET; @@ -228,6 +228,8 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk) { struct item_info *i; assert(p && channel != (uint32_t) -1 && chunk); + +/* pa_log(__FILE__": push-memblock %p\n", chunk); */ i = pa_xmalloc(sizeof(struct item_info)); i->type = PA_PSTREAM_ITEM_MEMBLOCK; diff --git a/polyp/resampler.c b/polyp/resampler.c index b6b876076..173c0987f 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -23,7 +23,6 @@ #include #endif -#include #include #include @@ -31,6 +30,7 @@ #include "resampler.h" #include "sconv.h" #include "xmalloc.h" +#include "log.h" struct pa_resampler { struct pa_sample_spec i_ss, o_ss; @@ -120,6 +120,8 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru /* How many input samples? */ ins = in->length/r->i_sz; +/* pa_log("%u / %u = %u\n", in->length, r->i_sz, ins); */ + /* How much space for output samples? */ if (r->src_state) ons = (ins*r->o_ss.rate/r->i_ss.rate)+1024; @@ -137,6 +139,9 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru eff_ins = ins; eff_ons = ons; } + +/* pa_log("eff_ins = %u \n", eff_ins); */ + out->memblock = pa_memblock_new(out->length = (ons*r->o_sz), r->memblock_stat); out->index = 0; @@ -145,7 +150,9 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru if (r->i_alloc < eff_ins) r->i_buf = pa_xrealloc(r->i_buf, sizeof(float) * (r->i_alloc = eff_ins)); assert(r->i_buf); - + +/* pa_log("eff_ins = %u \n", eff_ins); */ + r->to_float32_func(eff_ins, (uint8_t*) in->memblock->data+in->index, i_nchannels, r->i_buf); if (r->src_state) { @@ -179,6 +186,13 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru } else cbuf = r->i_buf; - r->from_float32_func(eff_ons, cbuf, (uint8_t*)out->memblock->data+out->index, o_nchannels); + if (eff_ons) + r->from_float32_func(eff_ons, cbuf, (uint8_t*)out->memblock->data+out->index, o_nchannels); out->length = ons*r->o_sz; + + + if (!out->length) { + pa_memblock_unref(out->memblock); + out->memblock = NULL; + } } diff --git a/polyp/sconv-s16le.c b/polyp/sconv-s16le.c index 45b28bdb5..40376b52f 100644 --- a/polyp/sconv-s16le.c +++ b/polyp/sconv-s16le.c @@ -28,6 +28,7 @@ #include "endianmacros.h" #include "sconv.h" +#include "log.h" #ifndef INT16_FROM #define INT16_FROM INT16_FROM_LE @@ -61,6 +62,9 @@ void pa_sconv_s16le_to_float32(unsigned n, const void *a, unsigned an, float *b) void pa_sconv_s16le_from_float32(unsigned n, const float *a, void *b, unsigned bn) { int16_t *cb = b; + +/* pa_log("%u %p %p %u\n", n, a, b, bn); */ + assert(n && a && b && bn); for (; n > 0; n--) { diff --git a/polyp/sink-input.c b/polyp/sink-input.c index f4f573433..b00961824 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -129,7 +129,7 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { if (!i->resampler) return i->peek(i, chunk); - if (!i->resampled_chunk.memblock) { + while (!i->resampled_chunk.memblock) { struct pa_memchunk tchunk; size_t l; int ret; @@ -141,10 +141,11 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); - if (tchunk.length > l) - tchunk.length = l; + if (l > tchunk.length) + l = tchunk.length; - i->drop(i, &tchunk, tchunk.length); + i->drop(i, &tchunk, l); + tchunk.length = l; pa_resampler_run(i->resampler, &tchunk, &i->resampled_chunk); pa_memblock_unref(tchunk.memblock); diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 5aa79e6c2..55132caee 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -43,6 +43,7 @@ enum tags { TAG_ARBITRARY = 'x', TAG_BOOLEAN_TRUE = '1', TAG_BOOLEAN_FALSE = '0', + TAG_TIMEVAL = 'T', }; struct pa_tagstruct { @@ -145,6 +146,15 @@ void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b) { t->length += 1; } +void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) { + assert(t); + extend(t, 9); + t->data[t->length] = TAG_TIMEVAL; + *((uint32_t*) (t->data+t->length+1)) = htonl(tv->tv_sec); + *((uint32_t*) (t->data+t->length+5)) = htonl(tv->tv_usec); + t->length += 9; +} + int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) { int error = 0; size_t n; @@ -263,4 +273,18 @@ int pa_tagstruct_get_boolean(struct pa_tagstruct*t, int *b) { return 0; } +int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv) { + + if (t->rindex+9 > t->length) + return -1; + + if (t->data[t->rindex] != TAG_TIMEVAL) + return -1; + + tv->tv_sec = ntohl(*((uint32_t*) (t->data+t->rindex+1))); + tv->tv_usec = ntohl(*((uint32_t*) (t->data+t->rindex+5))); + t->rindex += 9; + return 0; + +} diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index 9a91ee962..915a9a65b 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -39,6 +39,7 @@ void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c); void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss); void pa_tagstruct_put_arbitrary(struct pa_tagstruct*t, const void *p, size_t length); void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b); +void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv); int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s); int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i); @@ -46,6 +47,7 @@ int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c); int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss); int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length); int pa_tagstruct_get_boolean(struct pa_tagstruct *t, int *b); +int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv); int pa_tagstruct_eof(struct pa_tagstruct*t); const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l); diff --git a/polyp/util.c b/polyp/util.c index 408e60e9a..eeb1d1922 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -221,26 +221,52 @@ char *pa_get_host_name(char *s, size_t l) { return s; } -uint32_t pa_age(struct timeval *tv) { - struct timeval now; - uint32_t r; - assert(tv); +pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { + pa_usec_t r; + assert(a && b); - if (tv->tv_sec == 0) - return 0; + if (pa_timeval_cmp(a, b) < 0) { + const struct timeval *c; + c = a; + a = b; + b = c; + } - gettimeofday(&now, NULL); - - r = (now.tv_sec-tv->tv_sec) * 1000000; + r = (a->tv_sec - b->tv_sec)* 1000000; - if (now.tv_usec >= tv->tv_usec) - r += now.tv_usec - tv->tv_usec; - else - r -= tv->tv_usec - now.tv_usec; + if (a->tv_usec > b->tv_usec) + r += (a->tv_usec - b->tv_usec); + else if (a->tv_usec < b->tv_usec) + r -= (b->tv_usec - a->tv_usec); return r; } +int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { + assert(a && b); + + if (a->tv_sec < b->tv_sec) + return -1; + + if (a->tv_sec > b->tv_sec) + return 1; + + if (a->tv_usec < b->tv_usec) + return -1; + + if (a->tv_usec > b->tv_usec) + return 1; + + return 0; +} + +pa_usec_t pa_age(const struct timeval *tv) { + struct timeval now; + assert(tv); + gettimeofday(&now, NULL); + return pa_timeval_diff(&now, tv); +} + #define NICE_LEVEL (-15) void pa_raise_priority(void) { diff --git a/polyp/util.h b/polyp/util.h index 18f883f0b..adc4429bc 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -27,6 +27,7 @@ #include #include "gcc-printf.h" +#include "sample.h" void pa_make_nonblock_fd(int fd); @@ -43,7 +44,9 @@ char *pa_vsprintf_malloc(const char *format, va_list ap); char *pa_get_user_name(char *s, size_t l); char *pa_get_host_name(char *s, size_t l); -uint32_t pa_age(struct timeval *tv); +pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); +int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); +pa_usec_t pa_age(const struct timeval *tv); void pa_raise_priority(void); void pa_reset_priority(void); From 11f0aae5d6d087295594a095c889c9c5d956520f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 11 Sep 2004 00:03:00 +0000 Subject: [PATCH 0186/1514] add version number to library names git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@190 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 1 + doc/todo | 1 - polyp/Makefile.am | 88 +++++++++++++++++----------------- polyplib-error.pc.in | 2 +- polyplib-glib-mainloop.pc.in | 2 +- polyplib-glib12-mainloop.pc.in | 4 +- polyplib-mainloop.pc.in | 2 +- polyplib-simple.pc.in | 2 +- polyplib.pc.in | 2 +- 9 files changed, 53 insertions(+), 51 deletions(-) diff --git a/configure.ac b/configure.ac index 3b12b72bd..08b1f3240 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,7 @@ AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) +AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) if type -p stow > /dev/null && test -d /usr/local/stow ; then diff --git a/doc/todo b/doc/todo index 35e0b224e..a6e3dd904 100644 --- a/doc/todo +++ b/doc/todo @@ -15,7 +15,6 @@ - keep volume in xmms-polyp (and allow volume changing when not playing) - lazy sample cache - per-channel volume -- add version number to library names - extend pa_usec_t to 64 bit - make use of network latency in all apps - rename streams/contexts diff --git a/polyp/Makefile.am b/polyp/Makefile.am index b5acb3fcf..448eb2771 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -20,10 +20,12 @@ polypincludedir=$(includedir)/polyp polypconfdir=$(sysconfdir)/polyp +modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ + AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) -AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\" -AM_CFLAGS+="-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/polypaudio.pa\"" -AM_CFLAGS+="-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\"" +AM_CFLAGS+=-DDLSEARCHDIR=\"$(modlibdir)\" +AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/polypaudio.pa\" +AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm @@ -55,7 +57,7 @@ polypinclude_HEADERS=polyplib.h \ sample.h \ glib-mainloop.h -pkglib_LTLIBRARIES=libiochannel.la \ +modlib_LTLIBRARIES=libiochannel.la \ libsocket-server.la \ libsocket-client.la \ libpstream.la \ @@ -92,15 +94,15 @@ pkglib_LTLIBRARIES=libiochannel.la \ module-sine.la if !X_DISPLAY_MISSING -pkglib_LTLIBRARIES+=module-x11-bell.la +modlib_LTLIBRARIES+=module-x11-bell.la endif -lib_LTLIBRARIES=libpolyp.la \ - libpolyp-error.la \ - libpolyp-mainloop.la \ - libpolyp-mainloop-glib.la \ - libpolyp-mainloop-glib12.la \ - libpolyp-simple.la +lib_LTLIBRARIES=libpolyp-@PA_MAJORMINOR@.la \ + libpolyp-error-@PA_MAJORMINOR@.la \ + libpolyp-mainloop-@PA_MAJORMINOR@.la \ + libpolyp-mainloop-glib-@PA_MAJORMINOR@.la \ + libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la \ + libpolyp-simple-@PA_MAJORMINOR@.la polypaudio_SOURCES = idxset.c idxset.h \ queue.c queue.h \ @@ -307,7 +309,7 @@ module_x11_bell_la_LDFLAGS = -module -avoid-version module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) endif -libpolyp_la_SOURCES = polyplib.h \ +libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ polyplib-def.h \ tagstruct.c tagstruct.h \ iochannel.c iochannel.h \ @@ -340,71 +342,71 @@ libpolyp_la_SOURCES = polyplib.h \ log.c log.h \ gcc-printf.h -libpolyp_la_CFLAGS = $(AM_CFLAGS) -libpolyp_la_LDFLAGS = -version-info 0:0:0 +libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) +libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_mainloop_la_SOURCES = mainloop-api.h mainloop-api.c \ +libpolyp_mainloop_@PA_MAJORMINOR@_la_SOURCES = mainloop-api.h mainloop-api.c \ mainloop.c mainloop.h \ mainloop-signal.c mainloop-signal.h -libpolyp_mainloop_la_CFLAGS = $(AM_CFLAGS) -libpolyp_mainloop_la_LIBADD = $(AM_LIBADD) libpolyp.la -libpolyp_mainloop_la_LDFLAGS = -version-info 0:0:0 +libpolyp_mainloop_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) +libpolyp_mainloop_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la +libpolyp_mainloop_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_error_la_SOURCES = polyplib-error.c polyplib-error.h -libpolyp_error_la_CFLAGS = $(AM_CFLAGS) -libpolyp_error_la_LIBADD = $(AM_LIBADD) libpolyp.la -libpolyp_error_la_LDFLAGS = -version-info 0:0:0 +libpolyp_error_@PA_MAJORMINOR@_la_SOURCES = polyplib-error.c polyplib-error.h +libpolyp_error_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) +libpolyp_error_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la +libpolyp_error_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_simple_la_SOURCES = polyplib-simple.c polyplib-simple.h -libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) -libpolyp_simple_la_LIBADD = $(AM_LIBADD) libpolyp.la libpolyp-mainloop.la -libpolyp_simple_la_LDFLAGS = -version-info 0:0:0 +libpolyp_simple_@PA_MAJORMINOR@_la_SOURCES = polyplib-simple.c polyplib-simple.h +libpolyp_simple_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) +libpolyp_simple_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +libpolyp_simple_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_mainloop_glib_la_SOURCES = glib-mainloop.h glib-mainloop.c -libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) -libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB20_LIBS) -libpolyp_mainloop_glib_la_LDFLAGS = -version-info 0:0:0 +libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib-mainloop.c +libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) +libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB20_LIBS) +libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_mainloop_glib12_la_SOURCES = glib-mainloop.h glib12-mainloop.c -libpolyp_mainloop_glib12_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) -libpolyp_mainloop_glib12_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop.la $(GLIB12_LIBS) -libpolyp_mainloop_glib12_la_LDFLAGS = -version-info 0:0:0 +libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib12-mainloop.c +libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) +libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB12_LIBS) +libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 pacat_SOURCES = pacat.c -pacat_LDADD = $(AM_LDADD) libpolyp.la libpolyp-error.la libpolyp-mainloop.la +pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la pacat_CFLAGS = $(AM_CFLAGS) pactl_SOURCES = pactl.c -pactl_LDADD = $(AM_LDADD) libpolyp.la libpolyp-error.la libpolyp-mainloop.la $(LIBSNDFILE_LIBS) +pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) pactl_CFLAGS = $(AM_CFLAGS) $(LIBSDNFILE_CFLAGS) pacat_simple_SOURCES = pacat-simple.c -pacat_simple_LDADD = $(AM_LDADD) libpolyp.la libpolyp-simple.la libpolyp-error.la +pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la pacat_simple_CFLAGS = $(AM_CFLAGS) parec_simple_SOURCES = parec-simple.c -parec_simple_LDADD = $(AM_LDADD) libpolyp.la libpolyp-simple.la libpolyp-error.la +parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la parec_simple_CFLAGS = $(AM_CFLAGS) mainloop_test_SOURCES = mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) -mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop.la libpolyp.la +mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-@PA_MAJORMINOR@.la mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib.la +mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib-@PA_MAJORMINOR@.la mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12.la +mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit_test_CFLAGS = $(AM_CFLAGS) -cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop.la +cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 -cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop.la +cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la if BUILD_LIBPOLYPCORE diff --git a/polyplib-error.pc.in b/polyplib-error.pc.in index b5289959e..45f69dbca 100644 --- a/polyplib-error.pc.in +++ b/polyplib-error.pc.in @@ -6,5 +6,5 @@ includedir=${prefix}/include Name: polyplib-error Description: Error library for the polypaudio sound daemon Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-error +Libs: -L${libdir} -lpolyp-error-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} diff --git a/polyplib-glib-mainloop.pc.in b/polyplib-glib-mainloop.pc.in index f4c093307..431354e8c 100644 --- a/polyplib-glib-mainloop.pc.in +++ b/polyplib-glib-mainloop.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: polyplib-glib-mainloop Description: GLIB main loop wrapper for polypaudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-mainloop-glib +Libs: -L${libdir} -lpolyp-mainloop-glib-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} Requires: polyplib-mainloop diff --git a/polyplib-glib12-mainloop.pc.in b/polyplib-glib12-mainloop.pc.in index 3afed38e3..5c5f4089b 100644 --- a/polyplib-glib12-mainloop.pc.in +++ b/polyplib-glib12-mainloop.pc.in @@ -3,9 +3,9 @@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include -Name: polyplib-glib-mainloop +Name: polyplib-glib12-mainloop Description: GLIB main loop wrapper for polypaudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-mainloop-glib12 +Libs: -L${libdir} -lpolyp-mainloop-glib12-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} Requires: polyplib-mainloop diff --git a/polyplib-mainloop.pc.in b/polyplib-mainloop.pc.in index 73e579a3a..ab9b3e698 100644 --- a/polyplib-mainloop.pc.in +++ b/polyplib-mainloop.pc.in @@ -6,5 +6,5 @@ includedir=${prefix}/include Name: polyplib-mainloop Description: Main loop support for polypaudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-mainloop +Libs: -L${libdir} -lpolyp-mainloop-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} diff --git a/polyplib-simple.pc.in b/polyplib-simple.pc.in index e5dcaa9e0..a28503494 100644 --- a/polyplib-simple.pc.in +++ b/polyplib-simple.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: polyplib-simple Description: Simplified synchronous client interface to polypaudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-simple +Libs: -L${libdir} -lpolyp-simple-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} Requires: polyplib polyplib-mainloop polyplib-error diff --git a/polyplib.pc.in b/polyplib.pc.in index b06c6e514..c79d98d4f 100644 --- a/polyplib.pc.in +++ b/polyplib.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: polyplib Description: Client interface to polypaudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp +Libs: -L${libdir} -lpolyp-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} Requires: polyplib-error polyplib-mainloop From a9ca9c4a3bd8c3c03fe5d30cd2694cf891f5bbc1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 11 Sep 2004 23:17:38 +0000 Subject: [PATCH 0187/1514] add modinfo support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@191 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 4 +- polyp/Makefile.am | 13 ++- polyp/cmdline.c | 10 +-- polyp/cmdline.h | 2 +- polyp/main.c | 10 +-- polyp/modinfo.c | 84 ++++++++++++++++++++ polyp/modinfo.h | 37 +++++++++ polyp/module-alsa-sink.c | 10 ++- polyp/module-alsa-source.c | 10 ++- polyp/module-cli.c | 8 +- polyp/module-native-protocol-fd.c | 8 +- polyp/module-oss-mmap.c | 10 ++- polyp/module-oss.c | 8 +- polyp/module-pipe-sink.c | 10 ++- polyp/module-pipe-source.c | 10 ++- polyp/module-protocol-stub.c | 18 ++++- polyp/module-sine.c | 12 ++- polyp/module-x11-bell.c | 11 ++- polyp/module.c | 30 ++++--- polyp/module.h | 16 +++- polyp/pamodinfo.c | 126 ++++++++++++++++++++++++++++++ 21 files changed, 390 insertions(+), 57 deletions(-) create mode 100644 polyp/modinfo.c create mode 100644 polyp/modinfo.h create mode 100644 polyp/pamodinfo.c diff --git a/doc/todo b/doc/todo index a6e3dd904..c9be66ab5 100644 --- a/doc/todo +++ b/doc/todo @@ -8,6 +8,7 @@ module load/unload kill client/... autoload management + rename streams/contexts - more complete pactl - add sample directory - config file for command line arguments @@ -17,7 +18,8 @@ - per-channel volume - extend pa_usec_t to 64 bit - make use of network latency in all apps -- rename streams/contexts +- fix or work around libtool bug +- merge pa_context_connect_* ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 448eb2771..9cb8c4ba0 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -23,7 +23,7 @@ polypconfdir=$(sysconfdir)/polyp modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) -AM_CFLAGS+=-DDLSEARCHDIR=\"$(modlibdir)\" +AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\" AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/polypaudio.pa\" AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" @@ -31,7 +31,7 @@ AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm EXTRA_DIST = polypaudio.pa depmod.py esdcompat.sh.in -bin_PROGRAMS = polypaudio pacat pactl +bin_PROGRAMS = polypaudio pacat pactl pamodinfo bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = mainloop-test mainloop-test-glib mainloop-test-glib12 pacat-simple parec-simple cpulimit-test cpulimit-test2 @@ -148,13 +148,20 @@ polypaudio_SOURCES = idxset.c idxset.h \ sound-file-stream.c sound-file-stream.h \ cpulimit.c cpulimit.h \ log.c log.h \ - gcc-printf.h + gcc-printf.h \ + modinfo.c modinfo.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) polypaudio_LDFLAGS=-export-dynamic +pamodinfo_SOURCES = log.c log.h pamodinfo.c pamodinfo.h modinfo.c modinfo.h util.c util.h xmalloc.c xmalloc.h +pamodinfo_CFLAGS = $(AM_CFLAGS) +pamodinfo_INCLUDES = $(INCLTDL) +pamodinfo_LDADD = $(AM_LDADD) $(LIBLTDL) +pamodinfo_LDFLAGS=-export-dynamic + libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version libprotocol_simple_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la diff --git a/polyp/cmdline.c b/polyp/cmdline.c index e6f4101d2..b4d58f1fb 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -102,7 +102,7 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { cmdline->fail = cmdline->auto_log_target = 1; cmdline->quit_after_last_client_time = -1; cmdline->log_target = -1; - cmdline->dl_searchdir = NULL; + cmdline->dl_search_path = NULL; buf = pa_strbuf_new(); assert(buf); @@ -149,9 +149,9 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { cmdline->quit_after_last_client_time = atoi(optarg); break; case 'p': - if (cmdline->dl_searchdir) - pa_xfree(cmdline->dl_searchdir); - cmdline->dl_searchdir = pa_xstrdup(optarg); + if (cmdline->dl_search_path) + pa_xfree(cmdline->dl_search_path); + cmdline->dl_search_path = pa_xstrdup(optarg); break; case 'l': if (!strcmp(optarg, "syslog")) { @@ -192,6 +192,6 @@ fail: void pa_cmdline_free(struct pa_cmdline *cmd) { assert(cmd); pa_xfree(cmd->cli_commands); - pa_xfree(cmd->dl_searchdir); + pa_xfree(cmd->dl_search_path); pa_xfree(cmd); } diff --git a/polyp/cmdline.h b/polyp/cmdline.h index bf909c842..5dfe2e0d3 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -36,7 +36,7 @@ struct pa_cmdline { quit_after_last_client_time, auto_log_target; char *cli_commands; - char *dl_searchdir; + char *dl_search_path; enum pa_log_target log_target; }; diff --git a/polyp/main.c b/polyp/main.c index 2131877df..0218f396c 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -181,11 +181,11 @@ int main(int argc, char *argv[]) { r = lt_dlinit(); assert(r == 0); - if (cmdline->dl_searchdir) - lt_dladdsearchdir(cmdline->dl_searchdir); - -#ifdef DLSEARCHDIR - lt_dladdsearchdir(DLSEARCHDIR); + if (cmdline->dl_search_path) + lt_dlsetsearchpath(cmdline->dl_search_path); +#ifdef DLSEARCHPATH + else + lt_dlsetsearchpath(DLSEARCHPATH); #endif mainloop = pa_mainloop_new(); diff --git a/polyp/modinfo.c b/polyp/modinfo.c new file mode 100644 index 000000000..2847c63cd --- /dev/null +++ b/polyp/modinfo.c @@ -0,0 +1,84 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "xmalloc.h" +#include "util.h" +#include "modinfo.h" +#include "log.h" + +#define PA_SYMBOL_AUTHOR "pa__get_author" +#define PA_SYMBOL_DESCRIPTION "pa__get_description" +#define PA_SYMBOL_USAGE "pa__get_usage" +#define PA_SYMBOL_VERSION "pa__get_version" + +struct pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) { + struct pa_modinfo *i; + const char* (*func)(void); + assert(dl); + + i = pa_xmalloc0(sizeof(struct pa_modinfo)); + + if ((func = (const char* (*)(void)) lt_dlsym(dl, PA_SYMBOL_AUTHOR))) + i->author = pa_xstrdup(func()); + + if ((func = (const char* (*)(void)) lt_dlsym(dl, PA_SYMBOL_DESCRIPTION))) + i->description = pa_xstrdup(func()); + + if ((func = (const char* (*)(void)) lt_dlsym(dl, PA_SYMBOL_USAGE))) + i->usage = pa_xstrdup(func()); + + if ((func = (const char* (*)(void)) lt_dlsym(dl, PA_SYMBOL_VERSION))) + i->version = pa_xstrdup(func()); + + return i; +} + +struct pa_modinfo *pa_modinfo_get_by_name(const char *name) { + lt_dlhandle dl; + struct pa_modinfo *i; + assert(name); + + if (!(dl = lt_dlopenext(name))) { + pa_log(__FILE__": Failed to open module \"%s\": %s\n", name, lt_dlerror()); + return NULL; + } + + i = pa_modinfo_get_by_handle(dl); + lt_dlclose(dl); + + return i; +} + +void pa_modinfo_free(struct pa_modinfo *i) { + assert(i); + pa_xfree(i->author); + pa_xfree(i->description); + pa_xfree(i->usage); + pa_xfree(i->version); + pa_xfree(i); +} diff --git a/polyp/modinfo.h b/polyp/modinfo.h new file mode 100644 index 000000000..40b535ce6 --- /dev/null +++ b/polyp/modinfo.h @@ -0,0 +1,37 @@ +#ifndef foomodinfohfoo +#define foomodinfohfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +struct pa_modinfo { + char *author; + char *description; + char *usage; + char *version; +}; + +struct pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl); +struct pa_modinfo *pa_modinfo_get_by_name(const char *name); + +void pa_modinfo_free(struct pa_modinfo *i); + +#endif diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 9c75ff982..73c46ea05 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -40,6 +40,10 @@ #include "xmalloc.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("ALSA Sink") +PA_MODULE_VERSION(PACKAGE_VERSION) + struct userdata { snd_pcm_t *pcm_handle; struct pa_sink *sink; @@ -156,7 +160,7 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { return pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; int ret = -1; struct userdata *u = NULL; @@ -237,12 +241,12 @@ finish: fail: if (u) - pa_module_done(c, m); + pa__done(c, m); goto finish; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 520b68300..3ef54b17c 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -40,6 +40,10 @@ #include "xmalloc.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("ALSA Source") +PA_MODULE_VERSION(PACKAGE_VERSION) + struct userdata { snd_pcm_t *pcm_handle; struct pa_source *source; @@ -139,7 +143,7 @@ static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, do_read(u); } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; int ret = -1; struct userdata *u = NULL; @@ -216,12 +220,12 @@ finish: fail: if (u) - pa_module_done(c, m); + pa__done(c, m); goto finish; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-cli.c b/polyp/module-cli.c index 9a08a00d9..35b69cb68 100644 --- a/polyp/module-cli.c +++ b/polyp/module-cli.c @@ -33,6 +33,10 @@ #include "sioman.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Command line interface") +PA_MODULE_VERSION(PACKAGE_VERSION) + static void eof_cb(struct pa_cli*c, void *userdata) { struct pa_module *m = userdata; assert(c && m); @@ -40,7 +44,7 @@ static void eof_cb(struct pa_cli*c, void *userdata) { pa_module_unload_request(m->core, m); } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_iochannel *io; assert(c && m); @@ -66,7 +70,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { return 0; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { assert(c && m); pa_cli_free(m->userdata); diff --git a/polyp/module-native-protocol-fd.c b/polyp/module-native-protocol-fd.c index 632a3d713..c1ea69756 100644 --- a/polyp/module-native-protocol-fd.c +++ b/polyp/module-native-protocol-fd.c @@ -33,6 +33,10 @@ #include "protocol-native.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Native protocol autospawn helper") +PA_MODULE_VERSION(PACKAGE_VERSION) + static const char* const valid_modargs[] = { "fd", "public", @@ -40,7 +44,7 @@ static const char* const valid_modargs[] = { NULL, }; -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_iochannel *io; struct pa_modargs *ma; int fd, r = -1; @@ -72,7 +76,7 @@ finish: return r; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { assert(c && m); pa_protocol_native_free(m->userdata); diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 953871d1b..4ffc56efa 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -47,6 +47,10 @@ #include "xmalloc.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("OSS Sink/Source (mmap)") +PA_MODULE_VERSION(PACKAGE_VERSION) + struct userdata { struct pa_sink *sink; struct pa_source *source; @@ -214,7 +218,7 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { return pa_bytes_to_usec(u->out_fill, &s->sample_spec); } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; const char *p; @@ -362,7 +366,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { return 0; fail: - pa_module_done(c, m); + pa__done(c, m); if (ma) pa_modargs_free(ma); @@ -370,7 +374,7 @@ fail: return -1; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 95deca9c1..75d72e50d 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -46,6 +46,10 @@ #include "xmalloc.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("OSS Sink/Source") +PA_MODULE_VERSION(PACKAGE_VERSION) + struct userdata { struct pa_sink *sink; struct pa_source *source; @@ -171,7 +175,7 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { return pa_bytes_to_usec(arg, &s->sample_spec); } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; const char *p; @@ -300,7 +304,7 @@ fail: return -1; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index a5a7877fe..1aaf3b6a5 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -41,6 +41,10 @@ #include "xmalloc.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("UNIX pipe sink") +PA_MODULE_VERSION(PACKAGE_VERSION) + #define DEFAULT_FIFO_NAME "/tmp/music.output" #define DEFAULT_SINK_NAME "fifo_output" @@ -117,7 +121,7 @@ static void io_callback(struct pa_iochannel *io, void*userdata) { do_write(u); } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct userdata *u = NULL; struct stat st; const char *p; @@ -196,12 +200,12 @@ fail: if (fd >= 0) close(fd); - pa_module_done(c, m); + pa__done(c, m); return -1; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-pipe-source.c b/polyp/module-pipe-source.c index baed06a59..a226d44e4 100644 --- a/polyp/module-pipe-source.c +++ b/polyp/module-pipe-source.c @@ -41,6 +41,10 @@ #include "xmalloc.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("UNIX pipe source") +PA_MODULE_VERSION(PACKAGE_VERSION) + #define DEFAULT_FIFO_NAME "/tmp/music.input" #define DEFAULT_SOURCE_NAME "fifo_input" @@ -102,7 +106,7 @@ static void io_callback(struct pa_iochannel *io, void*userdata) { do_read(u); } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct userdata *u = NULL; struct stat st; const char *p; @@ -176,12 +180,12 @@ fail: if (fd >= 0) close(fd); - pa_module_done(c, m); + pa__done(c, m); return -1; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 686e21297..fe9e12a18 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -37,6 +37,16 @@ #include "modargs.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_VERSION(PACKAGE_VERSION) + +#ifdef USE_TCP_SOCKETS +#define SOCKET_DESCRIPTION "(TCP sockets)" +#else +#define SOCKET_DESCRIPTION "(UNIX sockets)" +#endif + + #if defined(USE_PROTOCOL_SIMPLE) #include "protocol-simple.h" #define protocol_new pa_protocol_simple_new @@ -44,6 +54,7 @@ #define IPV4_PORT 4711 #define UNIX_SOCKET "/tmp/polypaudio/simple" #define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record", + PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION) #elif defined(USE_PROTOCOL_CLI) #include "protocol-cli.h" #define protocol_new pa_protocol_cli_new @@ -51,6 +62,7 @@ #define IPV4_PORT 4712 #define UNIX_SOCKET "/tmp/polypaudio/cli" #define MODULE_ARGUMENTS + PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION) #elif defined(USE_PROTOCOL_NATIVE) #include "protocol-native.h" #define protocol_new pa_protocol_native_new @@ -58,6 +70,7 @@ #define IPV4_PORT 4713 #define UNIX_SOCKET "/tmp/polypaudio/native" #define MODULE_ARGUMENTS "public", "cookie", + PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) #elif defined(USE_PROTOCOL_ESOUND) #include "protocol-esound.h" #include "esound.h" @@ -66,6 +79,7 @@ #define IPV4_PORT ESD_DEFAULT_PORT #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", + PA_MODULE_DESCRIPTION("EsounD protocol "SOCKET_DESCRIPTION) #else #error "Broken build system" #endif @@ -126,7 +140,7 @@ static struct pa_socket_server *create_socket_server(struct pa_core *c, struct p return s; } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_socket_server *s; struct pa_modargs *ma = NULL; int ret = -1; @@ -154,7 +168,7 @@ finish: return ret; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { assert(c && m); protocol_free(m->userdata); diff --git a/polyp/module-sine.c b/polyp/module-sine.c index 868f63c6f..98e0dc28a 100644 --- a/polyp/module-sine.c +++ b/polyp/module-sine.c @@ -34,6 +34,11 @@ #include "namereg.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Sine wave generator") +PA_MODULE_USAGE("sink= frequency=") +PA_MODULE_VERSION(PACKAGE_VERSION) + struct userdata { struct pa_core *core; struct pa_sink_input *sink_input; @@ -89,7 +94,7 @@ static void calc_sine(float *f, size_t l, float freq) { f[i] = (float) sin((double) i/l*M_PI*2*freq)/2; } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; struct userdata *u; struct pa_sink *sink; @@ -147,11 +152,11 @@ fail: if (ma) pa_modargs_free(ma); - pa_module_done(c, m); + pa__done(c, m); return -1; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { struct userdata *u = m->userdata; assert(c && m); @@ -164,3 +169,4 @@ void pa_module_done(struct pa_core *c, struct pa_module*m) { pa_memblock_unref(u->memblock); pa_xfree(u); } + diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index d8ec978b0..ae69f9cb6 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -39,6 +39,11 @@ #include "namereg.h" #include "log.h" +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("X11 Bell interceptor") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink= sample= display=") + struct x11_source { struct pa_io_event *io_event; struct x11_source *next; @@ -105,7 +110,7 @@ static void new_io_source(struct userdata *u, int fd) { u->x11_sources = s; } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct userdata *u = NULL; struct pa_modargs *ma = NULL; int major, minor; @@ -160,11 +165,11 @@ fail: if (ma) pa_modargs_free(ma); if (m->userdata) - pa_module_done(c, m); + pa__done(c, m); return -1; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { struct userdata *u = m->userdata; assert(c && m && u); diff --git a/polyp/module.c b/polyp/module.c index 6eec499b2..c66faeb89 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -35,6 +35,9 @@ #include "subscribe.h" #include "log.h" +#define PA_SYMBOL_INIT "pa__init" +#define PA_SYMBOL_DONE "pa__done" + #define UNLOAD_POLL_TIME 10 static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { @@ -58,21 +61,25 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char if (c->disallow_module_loading) goto fail; - pa_log(__FILE__": Trying to load \"%s\" with argument \"%s\".\n", name, argument); - m = pa_xmalloc(sizeof(struct pa_module)); m->name = pa_xstrdup(name); m->argument = pa_xstrdup(argument); - if (!(m->dl = lt_dlopenext(name))) + if (!(m->dl = lt_dlopenext(name))) { + pa_log(__FILE__": Failed to open module \"%s\": %s\n", name, lt_dlerror()); goto fail; + } - if (!(m->init = (int (*)(struct pa_core *c, struct pa_module*m)) lt_dlsym(m->dl, "pa_module_init"))) + if (!(m->init = (int (*)(struct pa_core *c, struct pa_module*m)) lt_dlsym(m->dl, PA_SYMBOL_INIT))) { + pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.\n", name); goto fail; + } - if (!(m->done = (void (*)(struct pa_core *c, struct pa_module*m)) lt_dlsym(m->dl, "pa_module_done"))) + if (!(m->done = (void (*)(struct pa_core *c, struct pa_module*m)) lt_dlsym(m->dl, PA_SYMBOL_DONE))) { + pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.\n", name); goto fail; + } m->userdata = NULL; m->core = c; @@ -80,8 +87,10 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char m->auto_unload = 0; assert(m->init); - if (m->init(c, m) < 0) + if (m->init(c, m) < 0) { + pa_log(__FILE__": Failed to load module \"%s\" (argument: \"%s\"): initialization failed.\n", name, argument ? argument : ""); goto fail; + } if (!c->modules) c->modules = pa_idxset_new(NULL, NULL); @@ -98,7 +107,7 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char r = pa_idxset_put(c->modules, m, &m->index); assert(r >= 0 && m->index != PA_IDXSET_INVALID); - pa_log(__FILE__": Loaded \"%s\" (index: #%u) with argument \"%s\".\n", m->name, m->index, m->argument); + pa_log(__FILE__": Loaded \"%s\" (index: #%u; argument: \"%s\").\n", m->name, m->index, m->argument ? m->argument : ""); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_NEW, m->index); @@ -106,8 +115,6 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char fail: - pa_log(__FILE__": Failed to load \"%s\" with argument \"%s\".\n", name, argument); - if (m) { pa_xfree(m->argument); pa_xfree(m->name); @@ -239,3 +246,8 @@ void pa_module_set_used(struct pa_module*m, int used) { m->n_used = used; } +struct pa_modinfo *pa_module_get_info(struct pa_module *m) { + assert(m); + + return pa_modinfo_get_by_handle(m->dl); +} diff --git a/polyp/module.h b/polyp/module.h index acc08c3e0..663e0246b 100644 --- a/polyp/module.h +++ b/polyp/module.h @@ -26,6 +26,7 @@ #include #include "core.h" +#include "modinfo.h" struct pa_module { struct pa_core *core; @@ -53,10 +54,17 @@ void pa_module_unload_unused(struct pa_core *c); void pa_module_unload_request(struct pa_core *c, struct pa_module *m); -/* These to following prototypes are for module entrypoints and not implemented by the core */ -int pa_module_init(struct pa_core *c, struct pa_module*m); -void pa_module_done(struct pa_core *c, struct pa_module*m); - void pa_module_set_used(struct pa_module*m, int used); +/* prototypes for the module's entry points */ +int pa__init(struct pa_core *c, struct pa_module*m); +void pa__done(struct pa_core *c, struct pa_module*m); + +#define PA_MODULE_AUTHOR(s) const char *pa__get_author(void) { return s; } +#define PA_MODULE_DESCRIPTION(s) const char *pa__get_description(void) { return s; } +#define PA_MODULE_USAGE(s) const char *pa__get_usage(void) { return s; } +#define PA_MODULE_VERSION(s) const char *pa__get_version(void) { return s; } + +struct pa_modinfo *pa_module_get_info(struct pa_module *m); + #endif diff --git a/polyp/pamodinfo.c b/polyp/pamodinfo.c new file mode 100644 index 000000000..6eb147f08 --- /dev/null +++ b/polyp/pamodinfo.c @@ -0,0 +1,126 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "modinfo.h" + +#define PREFIX "module-" + +static int verbose = 0; + +static void short_info(const char *name, const char *path, struct pa_modinfo *i) { + assert(name && i); + printf("%-40s%s\n", name, i->description ? i->description : "n/a"); +} + +static void long_info(const char *name, const char *path, struct pa_modinfo *i) { + assert(name && i); + static int nl = 0; + + if (nl) + printf("\n"); + + nl = 1; + + printf("Name: %s\n", name); + + if (!i->description && !i->version && !i->author && !i->usage) + printf("No module information available\n"); + else { + if (i->version) + printf("Version: %s\n", i->version); + if (i->description) + printf("Description: %s\n", i->description); + if (i->author) + printf("Author: %s\n", i->author); + if (i->usage) + printf("Usage: %s\n", i->usage); + } + + if (path) + printf("Path: %s\n", path); +} + +static void show_info(const char *name, const char *path, void (*info)(const char *name, const char *path, struct pa_modinfo*i)) { + struct pa_modinfo *i; + + if ((i = pa_modinfo_get_by_name(path ? path : name))) { + info(name, path, i); + pa_modinfo_free(i); + } +} + +static int callback(const char *path, lt_ptr data) { + const char *e; + + if ((e = (const char*) strrchr(path, '/'))) + e++; + else + e = path; + + if (strlen(e) > sizeof(PREFIX)-1 && !strncmp(e, PREFIX, sizeof(PREFIX)-1)) + show_info(e, path, verbose ? long_info : short_info); + + return 0; +} + +int main(int argc, char *argv[]) { + int r = lt_dlinit(); + char *path = NULL; + int c; + assert(r == 0); + + while ((c = getopt(argc, argv, "p:v")) != -1) { + switch (c) { + case 'p': + path = optarg; + break; + case 'v': + verbose = 1; + break; + default: + return 1; + } + } + + if (path) + lt_dlsetsearchpath(path); +#ifdef DLSEARCHPATH + else + lt_dlsetsearchpath(DLSEARCHPATH); +#endif + + if (argc > optind) + show_info(argv[optind], NULL, long_info); + else + lt_dlforeachfile(NULL, callback, NULL); + + lt_dlexit(); +} From f05a4ac806d8d44ab1377ea2069abb1da7ab9d16 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 12 Sep 2004 13:14:49 +0000 Subject: [PATCH 0188/1514] extend pa_usec_t to 64 bit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@192 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 4 +--- polyp/cli-text.c | 8 ++++---- polyp/main.c | 2 ++ polyp/module-alsa-sink.c | 2 +- polyp/module-oss-mmap.c | 2 +- polyp/module-oss.c | 2 +- polyp/pacat.c | 2 +- polyp/polyplib-introspect.c | 8 ++++---- polyp/polyplib-stream.c | 4 ++-- polyp/protocol-esound.c | 6 +++--- polyp/protocol-native.c | 16 ++++++++-------- polyp/protocol-simple.c | 2 +- polyp/sample.c | 4 ++-- polyp/sample.h | 4 ++-- polyp/sink-input.h | 2 +- polyp/sink.h | 2 +- polyp/tagstruct.c | 26 ++++++++++++++++++++++++++ polyp/tagstruct.h | 2 ++ polyp/util.c | 6 +++--- 19 files changed, 66 insertions(+), 38 deletions(-) diff --git a/doc/todo b/doc/todo index c9be66ab5..af54c6929 100644 --- a/doc/todo +++ b/doc/todo @@ -13,13 +13,11 @@ - add sample directory - config file for command line arguments - option to use default fragment size on alsa drivers -- keep volume in xmms-polyp (and allow volume changing when not playing) - lazy sample cache - per-channel volume -- extend pa_usec_t to 64 bit -- make use of network latency in all apps - fix or work around libtool bug - merge pa_context_connect_* +- input latency ** later *** - xmlrpc/http diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 18a99cfab..1d6711dfa 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -93,12 +93,12 @@ char *pa_sink_list_to_string(struct pa_core *c) { assert(sink->monitor_source); pa_strbuf_printf( s, - " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%u usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", + " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%f usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, pa_volume_to_dB(sink->volume), - pa_sink_get_latency(sink), + (float) pa_sink_get_latency(sink), sink->monitor_source->index, ss); @@ -189,13 +189,13 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%u usec>\n\tsample_spec: <%s>\n", + s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%f usec>\n\tsample_spec: <%s>\n", i->index, i->name, i->sink->index, (unsigned) i->volume, pa_volume_to_dB(i->volume), - pa_sink_input_get_latency(i), + (float) pa_sink_input_get_latency(i), ss); if (i->owner) diff --git a/polyp/main.c b/polyp/main.c index 0218f396c..a2b3d4c70 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -188,6 +188,8 @@ int main(int argc, char *argv[]) { lt_dlsetsearchpath(DLSEARCHPATH); #endif + pa_log(__FILE__": sizeof(pa_usec_t) = %u\n", sizeof(pa_usec_t)); + mainloop = pa_mainloop_new(); assert(mainloop); diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 73c46ea05..95bb81f18 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -143,7 +143,7 @@ static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, do_write(u); } -static uint32_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { struct userdata *u = s->userdata; snd_pcm_sframes_t frames; assert(s && u && u->sink); diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 4ffc56efa..8e1652185 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -210,7 +210,7 @@ static void io_callback(struct pa_mainloop_api *m, struct pa_io_event *e, int fd do_write(u); } -static uint32_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { struct userdata *u = s->userdata; assert(s && u); diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 75d72e50d..51cc42ef7 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -161,7 +161,7 @@ static void io_callback(struct pa_iochannel *io, void*userdata) { do_read(u); } -static uint32_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { int arg; struct userdata *u = s->userdata; assert(s && u && u->sink); diff --git a/polyp/pacat.c b/polyp/pacat.c index 0ad5fa525..ed95c2cac 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -286,7 +286,7 @@ static void stream_get_latency_callback(struct pa_stream *s, const struct pa_lat return; } - fprintf(stderr, "Current latency is %u usecs.\n", i->buffer_usec+i->sink_usec); + fprintf(stderr, "Current latency is %f usecs.\n", (float) (i->buffer_usec+i->sink_usec+i->transport_usec)); } /* Someone requested that the latency is shown */ diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 2baeb540d..e742c2db6 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -130,7 +130,7 @@ static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t com pa_tagstruct_getu32(t, &i.volume) < 0 || pa_tagstruct_getu32(t, &i.monitor_source) < 0 || pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { + pa_tagstruct_get_usec(t, &i.latency) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -446,8 +446,8 @@ static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32 pa_tagstruct_getu32(t, &i.sink) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.buffer_usec) < 0 || - pa_tagstruct_getu32(t, &i.sink_usec) < 0) { + pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || + pa_tagstruct_get_usec(t, &i.sink_usec) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -648,7 +648,7 @@ static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t c if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.duration) < 0 || + pa_tagstruct_get_usec(t, &i.duration) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_getu32(t, &i.bytes) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index e128a773c..98610d612 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -333,8 +333,8 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - } else if (pa_tagstruct_getu32(t, &i.buffer_usec) < 0 || - pa_tagstruct_getu32(t, &i.sink_usec) < 0 || + } else if (pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || + pa_tagstruct_get_usec(t, &i.sink_usec) < 0 || pa_tagstruct_get_boolean(t, &i.playing) < 0 || pa_tagstruct_getu32(t, &i.queue_length) < 0 || pa_tagstruct_get_timeval(t, &local) < 0 || diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 3f87d4d09..178ba0096 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -106,7 +106,7 @@ typedef struct proto_handler { static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); static void sink_input_kill_cb(struct pa_sink_input *i); -static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i); static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk); static void source_output_kill_cb(struct pa_source_output *o); @@ -385,7 +385,7 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) latency = 0; else { - float usec = pa_sink_get_latency(sink); + double usec = pa_sink_get_latency(sink); usec += PLAYBACK_BUFFER_SECONDS*1000000; /* A better estimation would be a good idea! */ latency = (int) ((usec*44100)/1000000); } @@ -914,7 +914,7 @@ static void sink_input_kill_cb(struct pa_sink_input *i) { } -static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 058ba9cc5..3056f7c45 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -110,7 +110,7 @@ struct pa_protocol_native { static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); static void sink_input_kill_cb(struct pa_sink_input *i); -static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i); static void request_bytes(struct playback_stream*s); @@ -455,7 +455,7 @@ static void sink_input_kill_cb(struct pa_sink_input *i) { playback_stream_free((struct playback_stream *) i->userdata); } -static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct playback_stream *s; assert(i && i->userdata); s = i->userdata; @@ -835,8 +835,8 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma assert(reply); pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); pa_tagstruct_putu32(reply, tag); - pa_tagstruct_putu32(reply, pa_sink_input_get_latency(s->sink_input)); - pa_tagstruct_putu32(reply, pa_sink_get_latency(s->sink_input->sink)); + pa_tagstruct_put_usec(reply, pa_sink_input_get_latency(s->sink_input)); + pa_tagstruct_put_usec(reply, pa_sink_get_latency(s->sink_input->sink)); pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq)); pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq)); pa_tagstruct_put_timeval(reply, &tv); @@ -994,7 +994,7 @@ static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) { pa_tagstruct_putu32(t, sink->volume); pa_tagstruct_putu32(t, sink->monitor_source->index); pa_tagstruct_puts(t, sink->monitor_source->name); - pa_tagstruct_putu32(t, pa_sink_get_latency(sink)); + pa_tagstruct_put_usec(t, pa_sink_get_latency(sink)); } static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *source) { @@ -1034,8 +1034,8 @@ static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_inp pa_tagstruct_putu32(t, s->sink->index); pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_putu32(t, s->volume); - pa_tagstruct_putu32(t, pa_sink_input_get_latency(s)); - pa_tagstruct_putu32(t, pa_sink_get_latency(s->sink)); + pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s)); + pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink)); } static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) { @@ -1053,7 +1053,7 @@ static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry pa_tagstruct_putu32(t, e->index); pa_tagstruct_puts(t, e->name); pa_tagstruct_putu32(t, e->volume); - pa_tagstruct_putu32(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec)); + pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec)); pa_tagstruct_put_sample_spec(t, &e->sample_spec); pa_tagstruct_putu32(t, e->memchunk.length); } diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index f62404625..00db0aa05 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -220,7 +220,7 @@ static void sink_input_kill_cb(struct pa_sink_input *i) { } -static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); diff --git a/polyp/sample.c b/polyp/sample.c index 747acf185..dfe98e3fd 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -59,10 +59,10 @@ size_t pa_bytes_per_second(const struct pa_sample_spec *spec) { return spec->rate*pa_frame_size(spec); } -uint32_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec) { +pa_usec_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec) { assert(spec); - return (uint32_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate); + return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate); } int pa_sample_spec_valid(const struct pa_sample_spec *spec) { diff --git a/polyp/sample.h b/polyp/sample.h index 0141a7cd1..1e42a2606 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -67,8 +67,8 @@ struct pa_sample_spec { uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */ }; -/** Type for usec specifications */ -typedef uint32_t pa_usec_t; +/** Type for usec specifications. May be either 32 or 64 bit, depending on the architecture */ +typedef uint64_t pa_usec_t; /** Return the amount of bytes playback of a second of audio with the speicified sample type takes */ size_t pa_bytes_per_second(const struct pa_sample_spec *spec); diff --git a/polyp/sink-input.h b/polyp/sink-input.h index df6ead6be..e2478ed61 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -46,7 +46,7 @@ struct pa_sink_input { int (*peek) (struct pa_sink_input *i, struct pa_memchunk *chunk); void (*drop) (struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); void (*kill) (struct pa_sink_input *i); - uint32_t (*get_latency) (struct pa_sink_input *i); + pa_usec_t (*get_latency) (struct pa_sink_input *i); void *userdata; diff --git a/polyp/sink.h b/polyp/sink.h index 85addf763..881e75d31 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -47,7 +47,7 @@ struct pa_sink { pa_volume_t volume; void (*notify)(struct pa_sink*sink); - uint32_t (*get_latency)(struct pa_sink *s); + pa_usec_t (*get_latency)(struct pa_sink *s); void *userdata; }; diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 55132caee..52db0fe34 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -39,11 +39,14 @@ enum tags { TAG_S16 = 's', TAG_U8 = 'B', TAG_S8 = 'b', + TAG_U64 = 'R', + TAG_S64 = 'r', TAG_SAMPLE_SPEC = 'a', TAG_ARBITRARY = 'x', TAG_BOOLEAN_TRUE = '1', TAG_BOOLEAN_FALSE = '0', TAG_TIMEVAL = 'T', + TAG_USEC = 'U', /* 64bit unsigned */ }; struct pa_tagstruct { @@ -155,6 +158,15 @@ void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) { t->length += 9; } +void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) { + assert(t); + extend(t, 9); + t->data[t->length] = TAG_USEC; + *((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32)); + *((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u); + t->length += 9; +} + int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) { int error = 0; size_t n; @@ -288,3 +300,17 @@ int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv) { } +int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) { + assert(t && u); + + if (t->rindex+9 > t->length) + return -1; + + if (t->data[t->rindex] != TAG_USEC) + return -1; + + *u = (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32; + *u |= (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+5))); + t->rindex +=9; + return 0; +} diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index 915a9a65b..02df74e4d 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -40,6 +40,7 @@ void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample void pa_tagstruct_put_arbitrary(struct pa_tagstruct*t, const void *p, size_t length); void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b); void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv); +void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u); int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s); int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i); @@ -48,6 +49,7 @@ int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec * int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length); int pa_tagstruct_get_boolean(struct pa_tagstruct *t, int *b); int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv); +int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u); int pa_tagstruct_eof(struct pa_tagstruct*t); const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l); diff --git a/polyp/util.c b/polyp/util.c index eeb1d1922..45e1b605f 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -232,12 +232,12 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { b = c; } - r = (a->tv_sec - b->tv_sec)* 1000000; + r = ((pa_usec_t) a->tv_sec - b->tv_sec)* 1000000; if (a->tv_usec > b->tv_usec) - r += (a->tv_usec - b->tv_usec); + r += ((pa_usec_t) a->tv_usec - b->tv_usec); else if (a->tv_usec < b->tv_usec) - r -= (b->tv_usec - a->tv_usec); + r -= ((pa_usec_t) b->tv_usec - a->tv_usec); return r; } From b772564a4eeab6d32ba9b7be9fb9beed1c12c999 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 12 Sep 2004 19:37:04 +0000 Subject: [PATCH 0189/1514] update simple API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@193 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + polyp/cli-text.c | 4 +- polyp/pacat-simple.c | 11 ++++ polyp/polyplib-simple.c | 114 ++++++++++++++++++++++++++++++++++++---- polyp/polyplib-simple.h | 6 +++ polyp/util.c | 25 +++++++++ polyp/util.h | 3 ++ 7 files changed, 153 insertions(+), 11 deletions(-) diff --git a/doc/todo b/doc/todo index af54c6929..2509f76b1 100644 --- a/doc/todo +++ b/doc/todo @@ -18,6 +18,7 @@ - fix or work around libtool bug - merge pa_context_connect_* - input latency +- check if all mainloop stuff works still ** later *** - xmlrpc/http diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 1d6711dfa..2a48d5763 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -93,7 +93,7 @@ char *pa_sink_list_to_string(struct pa_core *c) { assert(sink->monitor_source); pa_strbuf_printf( s, - " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%f usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", + " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, @@ -189,7 +189,7 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%f usec>\n\tsample_spec: <%s>\n", + s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n", i->index, i->name, i->sink->index, diff --git a/polyp/pacat-simple.c b/polyp/pacat-simple.c index f5b696a89..956728fb7 100644 --- a/polyp/pacat-simple.c +++ b/polyp/pacat-simple.c @@ -56,6 +56,17 @@ int main(int argc, char*argv[]) { uint8_t buf[BUFSIZE]; ssize_t r; +#if 0 + pa_usec_t latency; + + if ((latency = pa_simple_get_playback_latency(s, &error)) == (pa_usec_t) -1) { + fprintf(stderr, __FILE__": pa_simple_get_playback_latency() failed: %s\n", pa_strerror(error)); + goto finish; + } + + fprintf(stderr, "%0.0f usec \r", (float)latency); +#endif + /* Read some data ... */ if ((r = read(STDIN_FILENO, buf, sizeof(buf))) <= 0) { if (r == 0) /* EOF */ diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index 8caae87e0..1ac088698 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -41,10 +41,11 @@ struct pa_simple { struct pa_stream *stream; enum pa_stream_direction direction; - int dead, drained; + int dead; void *read_data; size_t read_index, read_length; + pa_usec_t latency; }; static void read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata); @@ -71,6 +72,9 @@ static int check_error(struct pa_simple *p, int *perror) { fail: if (perror) *perror = pa_context_errno(p->context); + + p->dead = 1; + return -1; } @@ -121,6 +125,7 @@ struct pa_simple* pa_simple_new( p->direction = dir; p->read_data = NULL; p->read_index = p->read_length = 0; + p->latency = 0; if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name))) goto fail; @@ -178,6 +183,13 @@ void pa_simple_free(struct pa_simple *s) { int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *perror) { assert(p && data && p->direction == PA_STREAM_PLAYBACK); + if (p->dead) { + if (perror) + *perror = pa_context_errno(p->context); + + return -1; + } + while (length > 0) { size_t l; @@ -216,6 +228,13 @@ static void read_callback(struct pa_stream *s, const void*data, size_t length, v int pa_simple_read(struct pa_simple *p, void*data, size_t length, int *perror) { assert(p && data && p->direction == PA_STREAM_RECORD); + if (p->dead) { + if (perror) + *perror = pa_context_errno(p->context); + + return -1; + } + while (length > 0) { if (p->read_data) { size_t l = length; @@ -250,20 +269,27 @@ int pa_simple_read(struct pa_simple *p, void*data, size_t length, int *perror) { return 0; } -static void drain_complete(struct pa_stream *s, int success, void *userdata) { +static void drain_or_flush_complete(struct pa_stream *s, int success, void *userdata) { struct pa_simple *p = userdata; assert(s && p); - p->drained = success ? 1 : -1; + if (!success) + p->dead = 1; } int pa_simple_drain(struct pa_simple *p, int *perror) { struct pa_operation *o; - assert(p && p->direction == PA_STREAM_PLAYBACK); - p->drained = 0; - o = pa_stream_drain(p->stream, drain_complete, p); - while (!p->drained) { + if (p->dead) { + if (perror) + *perror = pa_context_errno(p->context); + + return -1; + } + + o = pa_stream_drain(p->stream, drain_or_flush_complete, p); + + while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { if (iterate(p, 1, perror) < 0) { pa_operation_cancel(o); pa_operation_unref(o); @@ -273,8 +299,78 @@ int pa_simple_drain(struct pa_simple *p, int *perror) { pa_operation_unref(o); - if (p->drained < 0 && perror) + if (p->dead && perror) *perror = pa_context_errno(p->context); - return 0; + return p->dead ? -1 : 0; +} + +static void latency_complete(struct pa_stream *s, const struct pa_latency_info *l, void *userdata) { + struct pa_simple *p = userdata; + assert(s && p); + + if (!l) + p->dead = 1; + else + p->latency = l->buffer_usec + l->sink_usec + l->transport_usec; +} + +pa_usec_t pa_simple_get_playback_latency(struct pa_simple *p, int *perror) { + struct pa_operation *o; + assert(p && p->direction == PA_STREAM_PLAYBACK); + + if (p->dead) { + if (perror) + *perror = pa_context_errno(p->context); + + return (pa_usec_t) -1; + } + + p->latency = 0; + o = pa_stream_get_latency(p->stream, latency_complete, p); + + while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { + + if (iterate(p, 1, perror) < 0) { + pa_operation_cancel(o); + pa_operation_unref(o); + return -1; + } + } + + pa_operation_unref(o); + + if (p->dead && perror) + *perror = pa_context_errno(p->context); + + return p->dead ? (pa_usec_t) -1 : p->latency; +} + +int pa_simple_flush(struct pa_simple *p, int *perror) { + struct pa_operation *o; + assert(p && p->direction == PA_STREAM_PLAYBACK); + + if (p->dead) { + if (perror) + *perror = pa_context_errno(p->context); + + return -1; + } + + o = pa_stream_flush(p->stream, drain_or_flush_complete, p); + + while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { + if (iterate(p, 1, perror) < 0) { + pa_operation_cancel(o); + pa_operation_unref(o); + return -1; + } + } + + pa_operation_unref(o); + + if (p->dead && perror) + *perror = pa_context_errno(p->context); + + return p->dead ? -1 : 0; } diff --git a/polyp/polyplib-simple.h b/polyp/polyplib-simple.h index ed552cb46..b37bdec60 100644 --- a/polyp/polyplib-simple.h +++ b/polyp/polyplib-simple.h @@ -69,6 +69,12 @@ int pa_simple_drain(struct pa_simple *s, int *error); /** Read some data from the server */ int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *error); +/** Return the playback latency. \since 0.5 */ +pa_usec_t pa_simple_get_playback_latency(struct pa_simple *s, int *perror); + +/** Flush the playback buffer. \since 0.5 */ +int pa_simple_flush(struct pa_simple *s, int *perror); + PA_C_DECL_END #endif diff --git a/polyp/util.c b/polyp/util.c index 45e1b605f..1dbb8697a 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "util.h" #include "xmalloc.h" @@ -322,3 +323,27 @@ int pa_fd_set_cloexec(int fd, int b) { return 0; } + +char *pa_get_binary_name(char *s, size_t l) { + char path[PATH_MAX]; + int i; + assert(s && l); + + /* This works on Linux only */ + + snprintf(path, sizeof(path), "/proc/%u/exe", (unsigned) getpid()); + if ((i = readlink(path, s, l-1)) < 0) + return NULL; + + s[i] = 0; + return s; +} + +char *pa_path_get_filename(const char *p) { + char *fn; + + if ((fn = strrchr(p, '/'))) + return fn+1; + + return (char*) p; +} diff --git a/polyp/util.h b/polyp/util.h index adc4429bc..f34ba4c08 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -43,6 +43,9 @@ char *pa_vsprintf_malloc(const char *format, va_list ap); char *pa_get_user_name(char *s, size_t l); char *pa_get_host_name(char *s, size_t l); +char *pa_get_binary_name(char *s, size_t l); + +char *pa_path_get_filename(const char *p); pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); From b681622b17e23878cdd0683fdf57dcc35c562c43 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 12 Sep 2004 23:29:54 +0000 Subject: [PATCH 0190/1514] build system update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@194 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 20 ++++-- doc/todo | 4 +- polyp/Makefile.am | 146 +++++++++++++++++++++++++--------------- polyp/protocol-esound.c | 2 +- 4 files changed, 110 insertions(+), 62 deletions(-) diff --git a/configure.ac b/configure.ac index 08b1f3240..62dc37d4d 100644 --- a/configure.ac +++ b/configure.ac @@ -47,7 +47,11 @@ AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netin ACX_PTHREAD AC_PATH_XTRA -AM_CONDITIONAL(X_DISPLAY_MISSING, test "x$X_DISPLAY_MISSING" != "x") + +HAVE_X11=0 +test "x$no_x" != "xyes" && HAVE_X11=1 +AC_SUBST(HAVE_X11) +AM_CONDITIONAL(HAVE_X11, test "x$no_x" != "xyes") # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -81,17 +85,23 @@ PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.0 ]) AC_SUBST(LIBSNDFILE_CFLAGS) AC_SUBST(LIBSNDFILE_LIBS) -PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ]) +PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [HAVE_ALSA=1], [HAVE_ALSA=0]) AC_SUBST(ASOUNDLIB_CFLAGS) -AC_SUBST(ASOUNDLIB_LIBS) +AC_SUBST(ASOUNDLIB_LIBS) +AC_SUBST(HAVE_ALSA) +AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1]) -PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ]) +PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], HAVE_GLIB20=1, HAVE_GLIB20=0) AC_SUBST(GLIB20_CFLAGS) AC_SUBST(GLIB20_LIBS) +AC_SUBST(HAVE_GLIB20) +AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1]) -PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ]) +PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], HAVE_GLIB12=1, HAVE_GLIB12=0) AC_SUBST(GLIB12_CFLAGS) AC_SUBST(GLIB12_LIBS) +AC_SUBST(HAVE_GLIB12) +AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) # If using GCC specifiy some additional parameters if test "x$GCC" = "xyes" ; then diff --git a/doc/todo b/doc/todo index 2509f76b1..f0afd106e 100644 --- a/doc/todo +++ b/doc/todo @@ -18,7 +18,9 @@ - fix or work around libtool bug - merge pa_context_connect_* - input latency -- check if all mainloop stuff works still +- fix public= +- fix POLYP_SERVER=foo:4711 +- fix tcp/native ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 9cb8c4ba0..3f94c0528 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -33,13 +33,19 @@ AM_LIBADD=$(PTHREAD_LIBS) -lm EXTRA_DIST = polypaudio.pa depmod.py esdcompat.sh.in bin_PROGRAMS = polypaudio pacat pactl pamodinfo bin_SCRIPTS = esdcompat.sh -noinst_PROGRAMS = mainloop-test mainloop-test-glib mainloop-test-glib12 pacat-simple parec-simple cpulimit-test cpulimit-test2 +noinst_PROGRAMS = \ + mainloop-test \ + pacat-simple \ + parec-simple \ + cpulimit-test \ + cpulimit-test2 polypconf_DATA=polypaudio.pa BUILT_SOURCES=polyplib-version.h -polypinclude_HEADERS=polyplib.h \ +polypinclude_HEADERS= \ + polyplib.h \ polyplib-def.h \ polyplib-simple.h \ polyplib-error.h \ @@ -57,13 +63,14 @@ polypinclude_HEADERS=polyplib.h \ sample.h \ glib-mainloop.h -modlib_LTLIBRARIES=libiochannel.la \ +modlib_LTLIBRARIES= \ + libsocket-util.la \ + libiochannel.la \ libsocket-server.la \ libsocket-client.la \ - libpstream.la \ libpacket.la \ + libpstream.la \ liboss-util.la \ - libalsa-util.la \ libioline.la \ libcli.la \ libprotocol-cli.la \ @@ -71,7 +78,6 @@ modlib_LTLIBRARIES=libiochannel.la \ libpstream-util.la \ libpdispatch.la \ libauthkey.la \ - libsocket-util.la \ libprotocol-simple.la \ libprotocol-esound.la \ libprotocol-native.la \ @@ -80,8 +86,6 @@ modlib_LTLIBRARIES=libiochannel.la \ module-cli-protocol-unix.la \ module-pipe-sink.la \ module-pipe-source.la \ - module-alsa-sink.la \ - module-alsa-source.la \ module-oss.la \ module-oss-mmap.la \ module-simple-protocol-tcp.la \ @@ -93,15 +97,10 @@ modlib_LTLIBRARIES=libiochannel.la \ module-native-protocol-fd.la \ module-sine.la -if !X_DISPLAY_MISSING -modlib_LTLIBRARIES+=module-x11-bell.la -endif - -lib_LTLIBRARIES=libpolyp-@PA_MAJORMINOR@.la \ +lib_LTLIBRARIES= \ + libpolyp-@PA_MAJORMINOR@.la \ libpolyp-error-@PA_MAJORMINOR@.la \ libpolyp-mainloop-@PA_MAJORMINOR@.la \ - libpolyp-mainloop-glib-@PA_MAJORMINOR@.la \ - libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la \ libpolyp-simple-@PA_MAJORMINOR@.la polypaudio_SOURCES = idxset.c idxset.h \ @@ -196,11 +195,6 @@ libpacket_la_LDFLAGS = -avoid-version liboss_util_la_SOURCES = oss-util.c oss-util.h liboss_util_la_LDFLAGS = -avoid-version -libalsa_util_la_SOURCES = alsa-util.c alsa-util.h -libalsa_util_la_LDFLAGS = -avoid-version -libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) -libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) - libioline_la_SOURCES = ioline.c ioline.h libioline_la_LDFLAGS = -avoid-version libioline_la_LIBADD = $(AM_LIBADD) libiochannel.la @@ -283,16 +277,6 @@ module_pipe_source_la_SOURCES = module-pipe-source.c module_pipe_source_la_LDFLAGS = -module -avoid-version module_pipe_source_la_LIBADD = $(AM_LIBADD) libiochannel.la -module_alsa_sink_la_SOURCES = module-alsa-sink.c -module_alsa_sink_la_LDFLAGS = -module -avoid-version -module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la -module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) - -module_alsa_source_la_SOURCES = module-alsa-source.c -module_alsa_source_la_LDFLAGS = -module -avoid-version -module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la -module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) - module_oss_la_SOURCES = module-oss.c module_oss_la_LDFLAGS = -module -avoid-version module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la @@ -309,13 +293,6 @@ module_sine_la_SOURCES = module-sine.c module_sine_la_LDFLAGS = -module -avoid-version module_sine_la_LIBADD = $(AM_LIBADD) -if !X_DISPLAY_MISSING -module_x11_bell_la_SOURCES = module-x11-bell.c -module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -module_x11_bell_la_LDFLAGS = -module -avoid-version -module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) -endif - libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ polyplib-def.h \ tagstruct.c tagstruct.h \ @@ -369,16 +346,6 @@ libpolyp_simple_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_simple_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp_simple_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib-mainloop.c -libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) -libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB20_LIBS) -libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 - -libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib12-mainloop.c -libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) -libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB12_LIBS) -libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 - pacat_SOURCES = pacat.c pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la pacat_CFLAGS = $(AM_CFLAGS) @@ -399,14 +366,6 @@ mainloop_test_SOURCES = mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-@PA_MAJORMINOR@.la -mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) -mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib-@PA_MAJORMINOR@.la - -mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) -mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la - cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit_test_CFLAGS = $(AM_CFLAGS) cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la @@ -415,6 +374,82 @@ cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la +### X11 stuff + +if HAVE_X11 +modlib_LTLIBRARIES+= \ + module-x11-bell.la + +module_x11_bell_la_SOURCES = module-x11-bell.c +module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +module_x11_bell_la_LDFLAGS = -module -avoid-version +module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) +endif + +### ALSA modules + +if HAVE_ALSA +modlib_LTLIBRARIES+= \ + libalsa-util.la \ + module-alsa-sink.la \ + module-alsa-source.la + +libalsa_util_la_SOURCES = alsa-util.c alsa-util.h +libalsa_util_la_LDFLAGS = -avoid-version +libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) +libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) + +module_alsa_sink_la_SOURCES = module-alsa-sink.c +module_alsa_sink_la_LDFLAGS = -module -avoid-version +module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la +module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) + +module_alsa_source_la_SOURCES = module-alsa-source.c +module_alsa_source_la_LDFLAGS = -module -avoid-version +module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la +module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) +endif + +### GLIB 2.0 support + +if HAVE_GLIB20 +lib_LTLIBRARIES+= \ + libpolyp-mainloop-glib-@PA_MAJORMINOR@.la + +noinst_PROGRAMS+= \ + mainloop-test-glib12 + +libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib-mainloop.c +libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) +libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB20_LIBS) +libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 + +mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) +mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP +mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib-@PA_MAJORMINOR@.la +endif + +### GLIB 1.2 support + +if HAVE_GLIB12 + +lib_LTLIBRARIES+= \ + libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la + +noinst_PROGRAMS+= \ + mainloop-test-glib +libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib12-mainloop.c +libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) +libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB12_LIBS) +libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 + +mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) +mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP +mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la + +endif + +### libpolypcore (needs to be updated) if BUILD_LIBPOLYPCORE @@ -485,6 +520,7 @@ libpolypcore_la_SOURCES = idxset.c idxset.h \ endif +### Some minor stuff suid: polypaudio chown root:root $< diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 178ba0096..755ec21d4 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -905,7 +905,7 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 1); - assert(pa_memblockq_get_length(c->input_memblockq) > 2048); +/* assert(pa_memblockq_get_length(c->input_memblockq) > 2048); */ } static void sink_input_kill_cb(struct pa_sink_input *i) { From b1ab6869fbe705f06faa12310c76b7d856030d81 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 12 Sep 2004 23:40:53 +0000 Subject: [PATCH 0191/1514] fix public= on native and esound protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@195 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + polyp/protocol-esound.c | 8 +++++++- polyp/protocol-native.c | 19 +++++++++++-------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/doc/todo b/doc/todo index f0afd106e..f9d9bedc3 100644 --- a/doc/todo +++ b/doc/todo @@ -21,6 +21,7 @@ - fix public= - fix POLYP_SERVER=foo:4711 - fix tcp/native +- suid ** later *** - xmlrpc/http diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 755ec21d4..ee64c4849 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -995,17 +995,23 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { struct pa_protocol_esound *p; + int public; assert(core && server && ma); p = pa_xmalloc(sizeof(struct pa_protocol_esound)); + if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { + pa_log(__FILE__": public= expects a boolean argument.\n"); + return NULL; + } + if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", DEFAULT_COOKIE_FILE), p->esd_key, sizeof(p->esd_key)) < 0) { pa_xfree(p); return NULL; } p->module = m; - p->public = 0; + p->public = public; p->server = server; pa_socket_server_set_callback(p->server, on_connection, p); p->core = core; diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 3056f7c45..2d26c2f53 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -674,14 +674,17 @@ static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag protocol_error(c); return; } - - if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) { - pa_log(__FILE__": Denied access to client with invalid authorization key.\n"); - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); - return; - } - c->authorized = 1; + if (!c->authorized) { + if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) { + pa_log(__FILE__": Denied access to client with invalid authorization key.\n"); + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + c->authorized = 1; + } + pa_pstream_send_simple_ack(c->pstream, tag); return; } @@ -1547,7 +1550,7 @@ static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struc assert(c && ma); if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { - pa_log(__FILE__": public= expects numeric argument.\n"); + pa_log(__FILE__": public= expects a boolean argument.\n"); return NULL; } From 12315982066ee1044840b598624920f8028c7924 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 13 Sep 2004 00:28:16 +0000 Subject: [PATCH 0192/1514] fix parsing of POLYP_SERVER environment variable git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@196 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 --- polyp/Makefile.am | 5 +++++ polyp/polyplib-context.c | 8 ++++++-- polyp/socket-client.c | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/doc/todo b/doc/todo index f9d9bedc3..c09d423aa 100644 --- a/doc/todo +++ b/doc/todo @@ -15,11 +15,8 @@ - option to use default fragment size on alsa drivers - lazy sample cache - per-channel volume -- fix or work around libtool bug - merge pa_context_connect_* - input latency -- fix public= -- fix POLYP_SERVER=foo:4711 - fix tcp/native - suid diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 3f94c0528..99c894913 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -63,6 +63,11 @@ polypinclude_HEADERS= \ sample.h \ glib-mainloop.h +### Warning! Due to an obscure bug in libtool/automake it is required +### that the libraries in modlib_LTLIBRARIES are specified in-order, +### i.e. libraries near the end of the list depend on libraries near +### the head, and not the other way! + modlib_LTLIBRARIES= \ libsocket-util.la \ libiochannel.la \ diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index a15e4257d..63b42eb3e 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -336,11 +336,15 @@ finish: static struct sockaddr *resolve_server(const char *server, size_t *len) { struct sockaddr *sa; struct addrinfo hints, *result = NULL; - char *port; + char *port, host[256]; assert(server && len); + snprintf(host, sizeof(host), "%s", server); + host[strcspn(host, ":")] = 0; + if ((port = strrchr(server, ':'))) port++; + if (!port) port = DEFAULT_PORT; @@ -349,7 +353,7 @@ static struct sockaddr *resolve_server(const char *server, size_t *len) { hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; - if (getaddrinfo(server, port, &hints, &result) != 0) + if (getaddrinfo(host, port, &hints, &result) != 0) return NULL; assert(result); diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 773e922c0..fbc259ff5 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -84,7 +84,7 @@ static void do_call(struct pa_socket_client *c) { } if (error != 0) { - pa_log(__FILE__": connect(): %s\n", strerror(error)); +/* pa_log(__FILE__": connect(): %s\n", strerror(error)); */ goto finish; } From fbefe67d52eb89a429505c653d1ea4ce73d4f4e7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 13 Sep 2004 13:26:44 +0000 Subject: [PATCH 0193/1514] correct latency calculation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@197 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + polyp/module-alsa-sink.c | 8 +++++++- polyp/module-oss.c | 8 +++++++- polyp/sink-input.c | 8 ++++++-- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/doc/todo b/doc/todo index c09d423aa..61cee8444 100644 --- a/doc/todo +++ b/doc/todo @@ -19,6 +19,7 @@ - input latency - fix tcp/native - suid +- add volume to create_stream command in native protocol ** later *** - xmlrpc/http diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 95bb81f18..55e719c90 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -144,6 +144,7 @@ static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, } static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { + pa_usec_t r = 0; struct userdata *u = s->userdata; snd_pcm_sframes_t frames; assert(s && u && u->sink); @@ -157,7 +158,12 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { if (frames < 0) frames = 0; - return pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); + r += pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); + + if (u->memchunk.memblock) + r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); + + return r; } int pa__init(struct pa_core *c, struct pa_module*m) { diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 51cc42ef7..b4e011d84 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -162,6 +162,7 @@ static void io_callback(struct pa_iochannel *io, void*userdata) { } static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { + pa_usec_t r = 0; int arg; struct userdata *u = s->userdata; assert(s && u && u->sink); @@ -172,7 +173,12 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { return 0; } - return pa_bytes_to_usec(arg, &s->sample_spec); + r += pa_bytes_to_usec(arg, &s->sample_spec); + + if (u->memchunk.memblock) + r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); + + return r; } int pa__init(struct pa_core *c, struct pa_module*m) { diff --git a/polyp/sink-input.c b/polyp/sink-input.c index b00961824..7763f2610 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -112,12 +112,16 @@ void pa_sink_input_kill(struct pa_sink_input*i) { } pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i) { + pa_usec_t r = 0; assert(i); if (i->get_latency) - return i->get_latency(i); + r += i->get_latency(i); - return 0; + if (i->resampled_chunk.memblock) + r += pa_bytes_to_usec(i->resampled_chunk.length, &i->sample_spec); + + return r; } int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { From 829656c5fcd7169e4c2f86f4ad5098ea9aaa5643 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 13 Sep 2004 23:28:30 +0000 Subject: [PATCH 0194/1514] new configuration subsystem git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@198 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 12 +- configure.ac | 5 +- doc/todo | 3 +- polyp/Makefile.am | 27 +-- polyp/cmdline.c | 258 ++++++++++++++---------- polyp/cmdline.h | 21 +- polyp/conf.c | 285 +++++++++++++++++++++++++++ polyp/conf.h | 51 +++++ polyp/config | 61 ++++++ polyp/core.c | 9 +- polyp/core.h | 3 +- polyp/{polypaudio.pa => default.pa} | 0 polyp/{pamodinfo.c => dumpmodules.c} | 45 +---- polyp/dumpmodules.h | 29 +++ polyp/main.c | 85 +++++--- polyp/modargs.c | 9 +- polyp/module.c | 4 +- polyp/pacat.c | 5 +- polyp/polyplib-def.h | 11 +- polyp/polyplib-stream.c | 10 +- polyp/socket-util.c | 24 +-- polyp/util.c | 26 +++ polyp/util.h | 3 + 23 files changed, 755 insertions(+), 231 deletions(-) create mode 100644 polyp/conf.c create mode 100644 polyp/conf.h create mode 100644 polyp/config rename polyp/{polypaudio.pa => default.pa} (100%) rename polyp/{pamodinfo.c => dumpmodules.c} (75%) create mode 100644 polyp/dumpmodules.h diff --git a/Makefile.am b/Makefile.am index c8592f863..b15fbac63 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,17 @@ MAINTAINERCLEANFILES=README noinst_DATA = README pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc +pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc + +if HAVE_GLIB20 +pkgconfig_DATA += \ + polyplib-glib-mainloop.pc +endif + +if HAVE_GLIB12 +pkgconfig_DATA += \ + polyplib-glib12-mainloop.pc +endif README: rm -f README diff --git a/configure.ac b/configure.ac index 62dc37d4d..07b2b96ce 100644 --- a/configure.ac +++ b/configure.ac @@ -40,10 +40,12 @@ AC_SUBST(INCLTDL) AC_SUBST(LIBLTDL) AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL +AC_PROG_LEX +AC_PROG_YACC # Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h]) +AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h syslog.h]) ACX_PTHREAD AC_PATH_XTRA @@ -70,6 +72,7 @@ AC_FUNC_MEMCMP AC_FUNC_MMAP AC_FUNC_REALLOC AC_FUNC_SETPGRP +AC_FUNC_VPRINTF AC_TYPE_SIGNAL AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul pow strcasecmp]) AC_FUNC_STAT diff --git a/doc/todo b/doc/todo index 61cee8444..135a336d2 100644 --- a/doc/todo +++ b/doc/todo @@ -11,15 +11,14 @@ rename streams/contexts - more complete pactl - add sample directory -- config file for command line arguments - option to use default fragment size on alsa drivers - lazy sample cache - per-channel volume - merge pa_context_connect_* - input latency - fix tcp/native -- suid - add volume to create_stream command in native protocol +- udp based protocol ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 99c894913..e9e1c295f 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -24,23 +24,24 @@ modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\" -AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/polypaudio.pa\" +AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\" +AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/config\" AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm -EXTRA_DIST = polypaudio.pa depmod.py esdcompat.sh.in -bin_PROGRAMS = polypaudio pacat pactl pamodinfo +EXTRA_DIST = default.pa config depmod.py esdcompat.sh.in +bin_PROGRAMS = polypaudio pacat pactl bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ mainloop-test \ pacat-simple \ parec-simple \ cpulimit-test \ - cpulimit-test2 + cpulimit-test2 -polypconf_DATA=polypaudio.pa +polypconf_DATA=default.pa config BUILT_SOURCES=polyplib-version.h @@ -153,19 +154,15 @@ polypaudio_SOURCES = idxset.c idxset.h \ cpulimit.c cpulimit.h \ log.c log.h \ gcc-printf.h \ - modinfo.c modinfo.h + modinfo.c modinfo.h \ + conf.c conf.h \ + dumpmodules.c dumpmodules.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) -polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) +polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(LEXLIB) polypaudio_LDFLAGS=-export-dynamic -pamodinfo_SOURCES = log.c log.h pamodinfo.c pamodinfo.h modinfo.c modinfo.h util.c util.h xmalloc.c xmalloc.h -pamodinfo_CFLAGS = $(AM_CFLAGS) -pamodinfo_INCLUDES = $(INCLTDL) -pamodinfo_LDADD = $(AM_LDADD) $(LIBLTDL) -pamodinfo_LDFLAGS=-export-dynamic - libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version libprotocol_simple_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la @@ -535,3 +532,7 @@ esdcompat.sh: esdcompat.sh.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ + +install-exec-hook: + chown root:root $(DESTDIR)$(bindir)/polypaudio + chmod u+s $(DESTDIR)$(bindir)/polypaudio diff --git a/polyp/cmdline.c b/polyp/cmdline.c index b4d58f1fb..4e7cde48f 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -35,29 +35,48 @@ #include "strbuf.h" #include "xmalloc.h" -#define ENV_CONFIG_FILE "POLYP_CONFIG" +enum { + ARG_HELP = 256, + ARG_VERSION, + ARG_DUMP_CONF, + ARG_DUMP_MODULES, + ARG_DAEMONIZE, + ARG_FAIL, + ARG_VERBOSE, + ARG_HIGH_PRIORITY, + ARG_STAY_ROOT, + ARG_DISALLOW_MODULE_LOADING, + ARG_EXIT_IDLE_TIME, + ARG_MODULE_IDLE_TIME, + ARG_LOG_TARGET, + ARG_LOAD, + ARG_FILE, + ARG_DL_SEARCH_PATH, +}; -char* config_file(void) { - char *p, *h; +static struct option long_options[] = { + {"help", 0, 0, ARG_HELP}, + {"version", 0, 0, ARG_VERSION}, + {"dump-conf", 0, 0, ARG_DUMP_CONF}, + {"dump-modules", 0, 0, ARG_DUMP_MODULES}, + {"daemonize", 2, 0, ARG_DAEMONIZE}, + {"fail", 2, 0, ARG_FAIL}, + {"verbose", 2, 0, ARG_VERBOSE}, + {"high-priority", 2, 0, ARG_HIGH_PRIORITY}, + {"stay-root", 2, 0, ARG_STAY_ROOT}, + {"disallow-module-loading", 2, 0, ARG_DISALLOW_MODULE_LOADING}, + {"exit-idle-time", 2, 0, ARG_EXIT_IDLE_TIME}, + {"module-idle-time", 2, 0, ARG_MODULE_IDLE_TIME}, + {"log-target", 1, 0, ARG_LOG_TARGET}, + {"load", 1, 0, ARG_LOAD}, + {"file", 1, 0, ARG_FILE}, + {"dl-search-path", 1, 0, ARG_DL_SEARCH_PATH}, + {NULL, 0, 0, 0} +}; - if ((p = getenv(ENV_CONFIG_FILE))) - return pa_xstrdup(p); - - if ((h = getenv("HOME"))) { - struct stat st; - p = pa_sprintf_malloc("%s/.polypaudio", h); - if (stat(p, &st) >= 0) - return p; - - pa_xfree(p); - } - - return pa_xstrdup(DEFAULT_CONFIG_FILE); -} void pa_cmdline_help(const char *argv0) { const char *e; - char *cfg = config_file(); if ((e = strrchr(argv0, '/'))) e++; @@ -65,133 +84,170 @@ void pa_cmdline_help(const char *argv0) { e = argv0; printf("%s [options]\n" - " -r Try to set high process priority (only available as root)\n" - " -R Don't drop root if SETUID root\n" - " -L MODULE Load the specified plugin module with the specified argument\n" - " -F FILE Run the specified script\n" - " -C Open a command line on the running TTY\n" - " -n Don't load configuration file (%s)\n" - " -D Daemonize after loading the modules\n" - " -d Disallow module loading after startup\n" - " -f Dont quit when the startup fails\n" - " -v Verbose startup\n" - " -X SECS Terminate the daemon after the last client quit and this time passed\n" - " -h Show this help\n" - " -l TARGET Specify the log target (syslog, stderr, auto)\n" - " -p DIR Append a directory to the search path for dynamic modules\n" - " -V Show version\n", e, cfg); + " -h, --help Show this help\n" + " --version Show version\n" + " --dump-conf Dump default configuration\n" + " --dump-modules Dump list of available modules\n\n" - pa_xfree(cfg); + " -D, --daemonize[=BOOL] Daemonize after startup\n" + " --fail[=BOOL] Quit when startup fails\n" + " --verbose[=BOOL] Be slightly more verbose\n" + " --high-priority[=BOOL] Try to set high process priority (only available as root)\n" + " --stay-root[=BOOL] Don't drop root if SETUID root\n" + " --disallow-module-loading[=BOOL] Disallow module loading after startup\n" + " --exit-idle-time=SECS Terminate the daemon when idle and this time passed\n" + " --module-idle-time=SECS Unload autoloaded modules when idle and this time passed\n" + " --log-target={auto,syslog,stderr} Specify the log target\n" + " -p, --dl-search-path=PATH Set the search path for dynamic shared objects (plugins)\n\n" + + " -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with the specified argument\n" + " -F, --file=FILENAME Run the specified script\n" + " -C Open a command line on the running TTY after startup\n\n" + + " -n Don't load default script file\n", e); } -struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) { - char c, *cfg; - struct pa_cmdline *cmdline = NULL; +int pa_cmdline_parse(struct pa_conf *conf, int argc, char *const argv [], int *d) { struct pa_strbuf *buf = NULL; - int no_default_config_file = 0; - assert(argc && argv); - - cmdline = pa_xmalloc(sizeof(struct pa_cmdline)); - cmdline->daemonize = - cmdline->help = - cmdline->verbose = - cmdline->high_priority = - cmdline->stay_root = - cmdline->version = - cmdline->disallow_module_loading = 0; - cmdline->fail = cmdline->auto_log_target = 1; - cmdline->quit_after_last_client_time = -1; - cmdline->log_target = -1; - cmdline->dl_search_path = NULL; + int c; + assert(conf && argc && argv); buf = pa_strbuf_new(); assert(buf); + + if (conf->script_commands) + pa_strbuf_puts(buf, conf->script_commands); - while ((c = getopt(argc, argv, "L:F:CDhfvrRVndX:l:p:")) != -1) { + while ((c = getopt_long(argc, argv, "L:F:ChDnp:", long_options, NULL)) != -1) { switch (c) { + case ARG_HELP: + case 'h': + conf->help = 1; + break; + + case ARG_VERSION: + conf->version = 1; + break; + + case ARG_DUMP_CONF: + conf->dump_conf = 1; + break; + + case ARG_DUMP_MODULES: + conf->dump_modules = 1; + break; + + case ARG_LOAD: case 'L': pa_strbuf_printf(buf, "load %s\n", optarg); break; + + case ARG_FILE: case 'F': pa_strbuf_printf(buf, ".include %s\n", optarg); break; + case 'C': pa_strbuf_puts(buf, "load module-cli\n"); break; + + case ARG_DAEMONIZE: case 'D': - cmdline->daemonize = 1; + if ((conf->daemonize = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log(__FILE__": --daemonize expects boolean argument\n"); + goto fail; + } break; - case 'h': - cmdline->help = 1; + + case ARG_FAIL: + if ((conf->fail = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log(__FILE__": --fail expects boolean argument\n"); + goto fail; + } break; - case 'f': - cmdline->fail = 0; + + case ARG_VERBOSE: + if ((conf->verbose = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log(__FILE__": --verbose expects boolean argument\n"); + goto fail; + } break; - case 'v': - cmdline->verbose = 1; + + case ARG_HIGH_PRIORITY: + if ((conf->high_priority = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log(__FILE__": --high-priority expects boolean argument\n"); + goto fail; + } break; - case 'r': - cmdline->high_priority = 1; + + case ARG_STAY_ROOT: + if ((conf->stay_root = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log(__FILE__": --stay-root expects boolean argument\n"); + goto fail; + } break; - case 'R': - cmdline->stay_root = 1; - break; - case 'V': - cmdline->version = 1; - break; - case 'n': - no_default_config_file = 1; - break; - case 'd': - cmdline->disallow_module_loading = 1; - break; - case 'X': - cmdline->quit_after_last_client_time = atoi(optarg); + + case ARG_DISALLOW_MODULE_LOADING: + if ((conf->disallow_module_loading = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log(__FILE__": --disallow-module-loading expects boolean argument\n"); + goto fail; + } break; + case 'p': - if (cmdline->dl_search_path) - pa_xfree(cmdline->dl_search_path); - cmdline->dl_search_path = pa_xstrdup(optarg); + case ARG_DL_SEARCH_PATH: + pa_xfree(conf->dl_search_path); + conf->dl_search_path = *optarg ? pa_xstrdup(optarg) : NULL; break; - case 'l': + + case 'n': + pa_xfree(conf->default_script_file); + conf->default_script_file = NULL; + break; + + case ARG_LOG_TARGET: if (!strcmp(optarg, "syslog")) { - cmdline->auto_log_target = 0; - cmdline->log_target = PA_LOG_SYSLOG; + conf->auto_log_target = 0; + conf->log_target = PA_LOG_SYSLOG; } else if (!strcmp(optarg, "stderr")) { - cmdline->auto_log_target = 0; - cmdline->log_target = PA_LOG_STDERR; + conf->auto_log_target = 0; + conf->log_target = PA_LOG_STDERR; } else if (!strcmp(optarg, "auto")) - cmdline->auto_log_target = 1; + conf->auto_log_target = 1; else { pa_log(__FILE__": Invalid log target: use either 'syslog', 'stderr' or 'auto'.\n"); goto fail; } break; + + case ARG_EXIT_IDLE_TIME: + conf->exit_idle_time = atoi(optarg); + break; + + case ARG_MODULE_IDLE_TIME: + conf->module_idle_time = atoi(optarg); + break; + default: goto fail; } } - if (!no_default_config_file) { - cfg = config_file(); - pa_strbuf_printf(buf, ".include %s\n", cfg); - pa_xfree(cfg); + pa_xfree(conf->script_commands); + conf->script_commands = pa_strbuf_tostring_free(buf); + + if (!conf->script_commands) { + pa_xfree(conf->script_commands); + conf->script_commands = NULL; } - cmdline->cli_commands = pa_strbuf_tostring_free(buf); - return cmdline; + *d = optind; + + return 0; fail: - if (cmdline) - pa_cmdline_free(cmdline); if (buf) pa_strbuf_free(buf); - return NULL; -} - -void pa_cmdline_free(struct pa_cmdline *cmd) { - assert(cmd); - pa_xfree(cmd->cli_commands); - pa_xfree(cmd->dl_search_path); - pa_xfree(cmd); + + return -1; } diff --git a/polyp/cmdline.h b/polyp/cmdline.h index 5dfe2e0d3..e4bd8af6a 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -22,26 +22,9 @@ USA. ***/ -#include "log.h" +#include "conf.h" -struct pa_cmdline { - int daemonize, - help, - fail, - verbose, - high_priority, - stay_root, - version, - disallow_module_loading, - quit_after_last_client_time, - auto_log_target; - char *cli_commands; - char *dl_search_path; - enum pa_log_target log_target; -}; - -struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []); -void pa_cmdline_free(struct pa_cmdline *cmd); +int pa_cmdline_parse(struct pa_conf*c, int argc, char *const argv [], int *d); void pa_cmdline_help(const char *argv0); diff --git a/polyp/conf.c b/polyp/conf.c new file mode 100644 index 000000000..4a11c4807 --- /dev/null +++ b/polyp/conf.c @@ -0,0 +1,285 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "conf.h" +#include "util.h" +#include "xmalloc.h" +#include "strbuf.h" + +static const struct pa_conf default_conf = { + .help = 0, + .daemonize = 0, + .dump_conf = 0, + .dump_modules = 0, + .fail = 1, + .verbose = 0, + .high_priority = 0, + .stay_root = 0, + .version = 0, + .disallow_module_loading = 0, + .exit_idle_time = -1, + .module_idle_time = 20, + .auto_log_target = 1, + .script_commands = NULL, + .dl_search_path = NULL, + .default_script_file = NULL, + .log_target = PA_LOG_SYSLOG, +}; + +#define ENV_SCRIPT_FILE "POLYP_SCRIPT" +#define ENV_CONFIG_FILE "POLYP_CONFIG" + +#ifndef DEFAULT_SCRIPT_FILE +#define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa" +#endif + +#ifndef DEFAULT_CONFIG_FILE +#define DEFAULT_CONFIG_FILE "/etc/polypaudio/config" +#endif + +#define DEFAULT_SCRIPT_FILE_LOCAL ".polypaudio.pa" +#define DEFAULT_CONFIG_FILE_LOCAL ".polypaudio.conf" + +char* default_file(const char *envvar, const char *global, const char *local) { + char *p, *h; + + assert(envvar && global && local); + + if ((p = getenv(envvar))) + return pa_xstrdup(p); + + if ((h = getenv("HOME"))) { + struct stat st; + p = pa_sprintf_malloc("%s/%s", h, local); + if (stat(p, &st) >= 0) + return p; + + pa_xfree(p); + } + + return pa_xstrdup(global); +} + + +struct pa_conf* pa_conf_new(void) { + struct pa_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); + c->default_script_file = default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_LOCAL); + return c; +} + +void pa_conf_free(struct pa_conf *c) { + assert(c); + pa_xfree(c->script_commands); + pa_xfree(c->dl_search_path); + pa_xfree(c->default_script_file); + pa_xfree(c); +} + +#define WHITESPACE " \t\n" +#define COMMENTS "#;\n" + +#define PARSE_BOOLEAN(t, v) \ + do { \ + if (!strcmp(lvalue, t)) { \ + int b; \ + if ((b = pa_parse_boolean(rvalue)) < 0) \ + goto fail; \ + c->v = b; \ + return 0; \ + } \ + } while (0) + +#define PARSE_STRING(t, v) \ + do { \ + if (!strcmp(lvalue, t)) { \ + pa_xfree(c->v); \ + c->v = *rvalue ? pa_xstrdup(rvalue) : NULL; \ + return 0; \ + } \ + } while (0) + +#define PARSE_INTEGER(t, v) \ + do { \ + if (!strcmp(lvalue, t)) { \ + char *x = NULL; \ + int i = strtol(rvalue, &x, 0); \ + if (!x || *x) \ + goto fail; \ + c->v = i; \ + return 0; \ + } \ + } while(0) + +static int next_assignment(struct pa_conf *c, char *lvalue, char *rvalue, unsigned n) { + PARSE_BOOLEAN("daemonize", daemonize); + PARSE_BOOLEAN("fail", fail); + PARSE_BOOLEAN("verbose", verbose); + PARSE_BOOLEAN("high-priority", high_priority); + PARSE_BOOLEAN("stay-root", stay_root); + PARSE_BOOLEAN("disallow-module-loading", disallow_module_loading); + + PARSE_INTEGER("exit-idle-time", exit_idle_time); + PARSE_INTEGER("module-idle-time", module_idle_time); + + PARSE_STRING("dl-search-path", dl_search_path); + PARSE_STRING("default-script-file", default_script_file); + + if (!strcmp(lvalue, "log-target")) { + if (!strcmp(rvalue, "auto")) + c->auto_log_target = 1; + else if (!strcmp(rvalue, "syslog")) { + c->auto_log_target = 0; + c->log_target = PA_LOG_SYSLOG; + } else if (!strcmp(rvalue, "stderr")) { + c->auto_log_target = 0; + c->log_target = PA_LOG_STDERR; + } else + goto fail; + + return 0; + } + +fail: + pa_log(__FILE__": line %u: parse error.\n", n); + return -1; +} + +#undef PARSE_STRING +#undef PARSE_BOOLEAN + +static int in_string(char c, const char *s) { + for (; *s; s++) + if (*s == c) + return 1; + + return 0; +} + +static char *strip(char *s) { + char *b = s+strspn(s, WHITESPACE); + char *e, *l = NULL; + + for (e = b; *e; e++) + if (!in_string(*e, WHITESPACE)) + l = e; + + if (l) + *(l+1) = 0; + + return b; +} + +static int parse_line(struct pa_conf *conf, char *l, unsigned n) { + char *e, *c, *b = l+strspn(l, WHITESPACE); + + if ((c = strpbrk(b, COMMENTS))) + *c = 0; + + if (!*b) + return 0; + + if (!(e = strchr(b, '='))) { + pa_log(__FILE__": line %u: missing '='.\n", n); + return -1; + } + + *e = 0; + e++; + + return next_assignment(conf, strip(b), strip(e), n); +} + + +int pa_conf_load(struct pa_conf *c, const char *filename) { + FILE *f; + int r = 0; + unsigned n = 0; + char *def = NULL; + assert(c); + + if (!filename) + filename = def = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL); + + if (!(f = fopen(filename, "r"))) { + if (errno != ENOENT) + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno)); + + goto finish; + } + + while (!feof(f)) { + char l[256]; + if (!fgets(l, sizeof(l), f)) { + if (!feof(f)) + pa_log(__FILE__": WARNING: failed to read configuration file '%s': %s\n", filename, strerror(errno)); + + break; + } + + if (parse_line(c, l, ++n) < 0) + r = -1; + } + +finish: + + if (f) + fclose(f); + + pa_xfree(def); + + return r; +} + +char *pa_conf_dump(struct pa_conf *c) { + struct pa_strbuf *s = pa_strbuf_new(); + char *d; + + d = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL); + pa_strbuf_printf(s, "### Default configuration file: %s ###\n\n", d); + + pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose); + pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize); + pa_strbuf_printf(s, "fail = %i\n", !!c->fail); + pa_strbuf_printf(s, "high-priority = %i\n", !!c->high_priority); + pa_strbuf_printf(s, "stay-root = %i\n", !!c->stay_root); + pa_strbuf_printf(s, "disallow-module-loading = %i\n", !!c->disallow_module_loading); + pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time); + pa_strbuf_printf(s, "module-idle-time = %i\n", c->module_idle_time); + pa_strbuf_printf(s, "dl-search-path = %s\n", c->dl_search_path ? c->dl_search_path : ""); + pa_strbuf_printf(s, "default-script-file = %s\n", c->default_script_file); + pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); + + pa_strbuf_printf(s, "\n### EOF ###\n"); + + pa_xfree(d); + + return pa_strbuf_tostring_free(s); +} diff --git a/polyp/conf.h b/polyp/conf.h new file mode 100644 index 000000000..bbe253c22 --- /dev/null +++ b/polyp/conf.h @@ -0,0 +1,51 @@ +#ifndef fooconfhfoo +#define fooconfhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "log.h" + +struct pa_conf { + int help, + version, + dump_conf, + dump_modules, + daemonize, + fail, + verbose, + high_priority, + stay_root, + disallow_module_loading, + exit_idle_time, + module_idle_time, + auto_log_target; + char *script_commands, *dl_search_path, *default_script_file; + enum pa_log_target log_target; +}; + +struct pa_conf* pa_conf_new(void); +void pa_conf_free(struct pa_conf*c); + +int pa_conf_load(struct pa_conf *c, const char *filename); +char *pa_conf_dump(struct pa_conf *c); + +#endif diff --git a/polyp/config b/polyp/config new file mode 100644 index 000000000..e0f8de507 --- /dev/null +++ b/polyp/config @@ -0,0 +1,61 @@ +# $Id$ +# +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +## Configuration file for polypaudio. Default values are commented out. +## Use either ; or # for commenting + +# Extra verbositiy +; verbose = 0 + +## Daemonize after startup +; daemonize = 0 + +## Quit if startup fails +; fail = 1 + +## Renice the daemon to level -15 and try to get SCHED_FIFO +## scheduling. This a good idea if you hear annyoing noise in the +## playback. However, this is a certain security issue. +; high-priority = 0 + +## Don't drop root rights on startup if called SUID root. +; stay-root = 0 + +## Disallow module loading after startup +; disallow-module-loading = 0 + +## Terminate the daemon after the last client quit and this time +## passed. Use a negative value to disable this feature. +; exit-idle-time = -1 + +## Unload autoloaded modules after being idle for this time +module-idle-time = 20 + +## The path were to look for dynamic shared objects (DSOs aka plugins). +## Specify an empty string for the default search path. +; dl-search-path = + +## The default script file to load. Specify an empty string for not +## loading a default script file +; default-script-file = /etc/polyp/default.pa + +## The default log target. Use either "stderr", "syslog" or +## "auto". The latter is equivalent to "sylog" in case daemonize is +## true, otherwise to "stderr". +; log-target = auto diff --git a/polyp/core.c b/polyp/core.c index 5d79a3650..0b33c1070 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -61,7 +61,6 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->default_sample_spec.rate = 44100; c->default_sample_spec.channels = 2; - c->auto_unload_time = 20; c->auto_unload_event = NULL; c->subscription_defer_event = NULL; @@ -73,7 +72,9 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->disallow_module_loading = 0; c->quit_event = NULL; - c->quit_after_last_client_time = -1; + + c->exit_idle_time = -1; + c->module_idle_time = 20; pa_check_for_sigpipe(); @@ -129,10 +130,10 @@ static void quit_callback(struct pa_mainloop_api*m, struct pa_time_event *e, con void pa_core_check_quit(struct pa_core *c) { assert(c); - if (!c->quit_event && c->quit_after_last_client_time >= 0 && pa_idxset_ncontents(c->clients) == 0) { + if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_ncontents(c->clients) == 0) { struct timeval tv; gettimeofday(&tv, NULL); - tv.tv_sec+= c->quit_after_last_client_time; + tv.tv_sec+= c->exit_idle_time; c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c); } else if (c->quit_event && pa_idxset_ncontents(c->clients) > 0) { c->mainloop->time_free(c->quit_event); diff --git a/polyp/core.h b/polyp/core.h index ddba6a833..a85dafd4c 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -38,7 +38,6 @@ struct pa_core { char *default_source_name, *default_sink_name; struct pa_sample_spec default_sample_spec; - int auto_unload_time; struct pa_time_event *auto_unload_event; struct pa_defer_event *subscription_defer_event; @@ -48,7 +47,7 @@ struct pa_core { struct pa_memblock_stat *memblock_stat; int disallow_module_loading; - int quit_after_last_client_time; + int exit_idle_time, module_idle_time; struct pa_time_event *quit_event; }; diff --git a/polyp/polypaudio.pa b/polyp/default.pa similarity index 100% rename from polyp/polypaudio.pa rename to polyp/default.pa diff --git a/polyp/pamodinfo.c b/polyp/dumpmodules.c similarity index 75% rename from polyp/pamodinfo.c rename to polyp/dumpmodules.c index 6eb147f08..9ed89692a 100644 --- a/polyp/pamodinfo.c +++ b/polyp/dumpmodules.c @@ -29,12 +29,11 @@ #include #include +#include "dumpmodules.h" #include "modinfo.h" #define PREFIX "module-" -static int verbose = 0; - static void short_info(const char *name, const char *path, struct pa_modinfo *i) { assert(name && i); printf("%-40s%s\n", name, i->description ? i->description : "n/a"); @@ -79,6 +78,7 @@ static void show_info(const char *name, const char *path, void (*info)(const cha static int callback(const char *path, lt_ptr data) { const char *e; + struct pa_conf *c = (data); if ((e = (const char*) strrchr(path, '/'))) e++; @@ -86,41 +86,16 @@ static int callback(const char *path, lt_ptr data) { e = path; if (strlen(e) > sizeof(PREFIX)-1 && !strncmp(e, PREFIX, sizeof(PREFIX)-1)) - show_info(e, path, verbose ? long_info : short_info); + show_info(e, path, c->verbose ? long_info : short_info); return 0; } -int main(int argc, char *argv[]) { - int r = lt_dlinit(); - char *path = NULL; - int c; - assert(r == 0); - - while ((c = getopt(argc, argv, "p:v")) != -1) { - switch (c) { - case 'p': - path = optarg; - break; - case 'v': - verbose = 1; - break; - default: - return 1; - } - } - - if (path) - lt_dlsetsearchpath(path); -#ifdef DLSEARCHPATH - else - lt_dlsetsearchpath(DLSEARCHPATH); -#endif - - if (argc > optind) - show_info(argv[optind], NULL, long_info); - else - lt_dlforeachfile(NULL, callback, NULL); - - lt_dlexit(); +void pa_dump_modules(struct pa_conf *c, int argc, char * const argv[]) { + if (argc > 0) { + int i; + for (i = 0; i < argc; i++) + show_info(argv[i], NULL, long_info); + } else + lt_dlforeachfile(NULL, callback, c); } diff --git a/polyp/dumpmodules.h b/polyp/dumpmodules.h new file mode 100644 index 000000000..6b1bd858b --- /dev/null +++ b/polyp/dumpmodules.h @@ -0,0 +1,29 @@ +#ifndef foodumpmoduleshfoo +#define foodumpmoduleshfoo + +/* $Id*/ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "conf.h" + +void pa_dump_modules(struct pa_conf *c, int argc, char * const argv[]); + +#endif diff --git a/polyp/main.c b/polyp/main.c index a2b3d4c70..148dfac2f 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -45,6 +45,8 @@ #include "xmalloc.h" #include "cpulimit.h" #include "log.h" +#include "conf.h" +#include "dumpmodules.h" static struct pa_mainloop *mainloop; @@ -99,40 +101,69 @@ static void close_pipe(int p[2]) { int main(int argc, char *argv[]) { struct pa_core *c; - struct pa_cmdline *cmdline = NULL; struct pa_strbuf *buf = NULL; + struct pa_conf *conf; char *s; - int r, retval = 1; + int r, retval = 1, d = 0; int daemon_pipe[2] = { -1, -1 }; + r = lt_dlinit(); + assert(r == 0); + pa_log_set_ident("polypaudio"); - if (!(cmdline = pa_cmdline_parse(argc, argv))) { + conf = pa_conf_new(); + + if (pa_conf_load(conf, NULL) < 0) + goto finish; + + if (pa_cmdline_parse(conf, argc, argv, &d) < 0) { pa_log(__FILE__": failed to parse command line.\n"); goto finish; } - pa_log_set_target(cmdline->auto_log_target ? PA_LOG_STDERR : cmdline->log_target, NULL); + pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL); - if (cmdline->help) { + if (conf->dl_search_path) + lt_dlsetsearchpath(conf->dl_search_path); +#ifdef DLSEARCHPATH + else + lt_dlsetsearchpath(DLSEARCHPATH); +#endif + + if (conf->dump_modules) { + pa_dump_modules(conf, argc-d, argv+d); + retval = 0; + goto finish; + } + + if (conf->dump_conf) { + char *s = pa_conf_dump(conf); + fputs(s, stdout); + pa_xfree(s); + retval = 0; + goto finish; + } + + if (conf->help) { pa_cmdline_help(argv[0]); retval = 0; goto finish; } - if (cmdline->version) { + if (conf->version) { printf(PACKAGE_NAME" "PACKAGE_VERSION"\n"); retval = 0; goto finish; } - if (cmdline->high_priority) + if (conf->high_priority) pa_raise_priority(); - if (!cmdline->stay_root) + if (!conf->stay_root) drop_root(); - if (cmdline->daemonize) { + if (conf->daemonize) { pid_t child; if (pa_stdio_acquire() < 0) { @@ -168,7 +199,7 @@ int main(int argc, char *argv[]) { daemon_pipe[0] = -1; - if (cmdline->auto_log_target) + if (conf->auto_log_target) pa_log_set_target(PA_LOG_SYSLOG, NULL); setsid(); @@ -178,15 +209,6 @@ int main(int argc, char *argv[]) { close(1); } - r = lt_dlinit(); - assert(r == 0); - - if (cmdline->dl_search_path) - lt_dlsetsearchpath(cmdline->dl_search_path); -#ifdef DLSEARCHPATH - else - lt_dlsetsearchpath(DLSEARCHPATH); -#endif pa_log(__FILE__": sizeof(pa_usec_t) = %u\n", sizeof(pa_usec_t)); @@ -210,25 +232,28 @@ int main(int argc, char *argv[]) { buf = pa_strbuf_new(); assert(buf); - r = pa_cli_command_execute(c, cmdline->cli_commands, buf, &cmdline->fail, &cmdline->verbose); + if (conf->default_script_file) + pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail, &conf->verbose); + r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail, &conf->verbose); pa_log(s = pa_strbuf_tostring_free(buf)); pa_xfree(s); - if (r < 0 && cmdline->fail) { + if (r < 0 && conf->fail) { pa_log(__FILE__": failed to initialize daemon.\n"); - if (cmdline->daemonize) + if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); } else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) { pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n"); - if (cmdline->daemonize) + if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); } else { retval = 0; - if (cmdline->daemonize) + if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); - c->disallow_module_loading = cmdline->disallow_module_loading; - c->quit_after_last_client_time = cmdline->quit_after_last_client_time; + c->disallow_module_loading = conf->disallow_module_loading; + c->exit_idle_time = conf->exit_idle_time; + c->module_idle_time = conf->module_idle_time; pa_log(__FILE__": Daemon startup complete.\n"); if (pa_mainloop_run(mainloop, &retval) < 0) @@ -242,16 +267,16 @@ int main(int argc, char *argv[]) { pa_signal_done(); pa_mainloop_free(mainloop); - lt_dlexit(); - pa_log(__FILE__": Daemon terminated.\n"); finish: - if (cmdline) - pa_cmdline_free(cmdline); + if (conf) + pa_conf_free(conf); close_pipe(daemon_pipe); + lt_dlexit(); + return retval; } diff --git a/polyp/modargs.c b/polyp/modargs.c index 4874d808e..e1c2c9b8a 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -36,6 +36,7 @@ #include "sink.h" #include "source.h" #include "xmalloc.h" +#include "util.h" struct pa_modargs; @@ -229,6 +230,7 @@ int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *va int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *value) { const char *v; + int r; assert(ma && key && value); if (!(v = pa_modargs_get_value(ma, key, NULL))) @@ -237,13 +239,10 @@ int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *va if (!*v) return -1; - if (!strcmp(v, "1") || !strcasecmp(v, "yes") || !strcasecmp(v, "y") || !strcasecmp(v, "on")) - *value = 1; - else if (!strcmp(v, "0") || !strcasecmp(v, "no") || !strcasecmp(v, "n") || !strcasecmp(v, "off")) - *value = 0; - else + if ((r = pa_parse_boolean(v)) < 0) return -1; + *value = r; return 0; } diff --git a/polyp/module.c b/polyp/module.c index c66faeb89..db21f7901 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -38,7 +38,7 @@ #define PA_SYMBOL_INIT "pa__init" #define PA_SYMBOL_DONE "pa__done" -#define UNLOAD_POLL_TIME 10 +#define UNLOAD_POLL_TIME 2 static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { struct pa_core *c = userdata; @@ -193,7 +193,7 @@ static int unused_callback(void *p, uint32_t index, int *del, void *userdata) { time_t *now = userdata; assert(p && del && now); - if (m->n_used == 0 && m->auto_unload && m->last_used_time+m->core->auto_unload_time <= *now) { + if (m->n_used == 0 && m->auto_unload && m->last_used_time+m->core->module_idle_time <= *now) { pa_module_free(m); *del = 1; } diff --git a/polyp/pacat.c b/polyp/pacat.c index ed95c2cac..b499f71a0 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -286,7 +286,10 @@ static void stream_get_latency_callback(struct pa_stream *s, const struct pa_lat return; } - fprintf(stderr, "Current latency is %f usecs.\n", (float) (i->buffer_usec+i->sink_usec+i->transport_usec)); + fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n", + (float) i->buffer_usec, (float) i->sink_usec, (float) i->transport_usec, + (float) (i->buffer_usec+i->sink_usec+i->transport_usec), + i->synchronized_clocks ? "yes" : "no"); } /* Someone requested that the latency is shown */ diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 176e1d3b5..4a49a1f81 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -144,7 +144,16 @@ struct pa_latency_info { pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. */ pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to the daemon. \since 0.5 */ int playing; /**< Non-zero when the stream is currently playing */ - uint32_t queue_length; /**< Queue size in bytes. */ + uint32_t queue_length; /**< Queue size in bytes. */ + int synchronized_clocks; /**< Non-zero if the local and the + * remote machine have synchronized + * clocks. If synchronized clocks are + * detected transport_usec becomes much + * more reliable. However, the code that + * detects synchronized clocks is very + * limited und unreliable itself. \since + * 0.5 */ + struct timeval timestamp; /**< The time when this latency info was current */ }; PA_C_DECL_END diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 98610d612..b40b7f69c 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -347,12 +347,18 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman gettimeofday(&now, NULL); - if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) + if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) { /* local and remote seem to have synchronized clocks */ i.transport_usec = pa_timeval_diff(&remote, &local); - else + i.synchronized_clocks = 1; + i.timestamp = remote; + } else { /* clocks are not synchronized, let's estimate latency then */ i.transport_usec = pa_timeval_diff(&now, &local)/2; + i.synchronized_clocks = 0; + i.timestamp = local; + pa_timeval_add(&i.timestamp, i.transport_usec); + } if (o->callback) { void (*cb)(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) = o->callback; diff --git a/polyp/socket-util.c b/polyp/socket-util.c index 2f082bfbe..20380653d 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -101,15 +101,15 @@ int pa_socket_low_delay(int fd) { } int pa_socket_tcp_low_delay(int fd) { - int ret, tos; + int ret, tos, on; assert(fd >= 0); ret = pa_socket_low_delay(fd); -/* on = 1; */ -/* if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) */ -/* ret = -1; */ + on = 1; + if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) + ret = -1; tos = IPTOS_LOWDELAY; if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0) @@ -122,10 +122,10 @@ int pa_socket_tcp_low_delay(int fd) { int pa_socket_set_rcvbuf(int fd, size_t l) { assert(fd >= 0); - if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) { - pa_log(__FILE__": SO_RCVBUF: %s\n", strerror(errno)); - return -1; - } +/* if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) { */ +/* pa_log(__FILE__": SO_RCVBUF: %s\n", strerror(errno)); */ +/* return -1; */ +/* } */ return 0; } @@ -133,10 +133,10 @@ int pa_socket_set_rcvbuf(int fd, size_t l) { int pa_socket_set_sndbuf(int fd, size_t l) { assert(fd >= 0); - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) { - pa_log(__FILE__": SO_SNDBUF: %s\n", strerror(errno)); - return -1; - } +/* if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) { */ +/* pa_log(__FILE__": SO_SNDBUF: %s\n", strerror(errno)); */ +/* return -1; */ +/* } */ return 0; } diff --git a/polyp/util.c b/polyp/util.c index 1dbb8697a..039ec264d 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -268,6 +268,22 @@ pa_usec_t pa_age(const struct timeval *tv) { return pa_timeval_diff(&now, tv); } +void pa_timeval_add(struct timeval *tv, pa_usec_t v) { + unsigned long secs; + assert(tv); + + secs = (v/1000000); + tv->tv_sec += (unsigned long) secs; + v -= secs*1000000; + + tv->tv_usec += v; + + while (tv->tv_usec >= 1000000) { + tv->tv_sec++; + tv->tv_usec -= 1000000; + } +} + #define NICE_LEVEL (-15) void pa_raise_priority(void) { @@ -347,3 +363,13 @@ char *pa_path_get_filename(const char *p) { return (char*) p; } + +int pa_parse_boolean(const char *v) { + + if (!strcmp(v, "1") || !strcasecmp(v, "yes") || !strcasecmp(v, "y") || !strcasecmp(v, "on")) + return 1; + else if (!strcmp(v, "0") || !strcasecmp(v, "no") || !strcasecmp(v, "n") || !strcasecmp(v, "off")) + return 0; + + return -1; +} diff --git a/polyp/util.h b/polyp/util.h index f34ba4c08..42e0b22ba 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -50,10 +50,13 @@ char *pa_path_get_filename(const char *p); pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); pa_usec_t pa_age(const struct timeval *tv); +void pa_timeval_add(struct timeval *tv, pa_usec_t v); void pa_raise_priority(void); void pa_reset_priority(void); int pa_fd_set_cloexec(int fd, int b); +int pa_parse_boolean(const char *s); + #endif From 8c6593dabf3253e20fead143855267570a403c9a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Sep 2004 17:52:11 +0000 Subject: [PATCH 0195/1514] add module-combine remove option "stay-root" clean up pa_conf git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@199 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 9 +- polyp/Makefile.am | 7 +- polyp/cmdline.c | 19 +- polyp/conf.c | 8 +- polyp/conf.h | 16 +- polyp/config | 12 +- polyp/log.c | 1 + polyp/main.c | 57 +++--- polyp/module-combine.c | 353 ++++++++++++++++++++++++++++++++++++++ polyp/module-sine.c | 2 +- polyp/play-memchunk.c | 2 +- polyp/protocol-esound.c | 2 +- polyp/protocol-native.c | 2 +- polyp/protocol-simple.c | 2 +- polyp/resampler.c | 18 +- polyp/resampler.h | 2 + polyp/sink-input.c | 14 +- polyp/sink-input.h | 4 +- polyp/sound-file-stream.c | 2 +- polyp/util.c | 16 ++ polyp/util.h | 2 + 21 files changed, 469 insertions(+), 81 deletions(-) create mode 100644 polyp/module-combine.c diff --git a/doc/todo b/doc/todo index 135a336d2..8daabc33d 100644 --- a/doc/todo +++ b/doc/todo @@ -3,22 +3,25 @@ *** 0.5 *** - make mcalign merge chunks - use ref counting in more objects (i.e. sink, source, sink_input, source_output) -- unix socket directories include user name - native library/protocol: module load/unload kill client/... autoload management rename streams/contexts - more complete pactl -- add sample directory - option to use default fragment size on alsa drivers - lazy sample cache -- per-channel volume - merge pa_context_connect_* - input latency - fix tcp/native - add volume to create_stream command in native protocol - udp based protocol +- make sure not to allow recursive auto load + +*** 0.6 **** +- per-channel volume +- unix socket directories include user name +- add sample directory ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index e9e1c295f..9c672a3b7 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -101,7 +101,8 @@ modlib_LTLIBRARIES= \ module-native-protocol-tcp.la \ module-native-protocol-unix.la \ module-native-protocol-fd.la \ - module-sine.la + module-sine.la \ + module-combine.la lib_LTLIBRARIES= \ libpolyp-@PA_MAJORMINOR@.la \ @@ -295,6 +296,10 @@ module_sine_la_SOURCES = module-sine.c module_sine_la_LDFLAGS = -module -avoid-version module_sine_la_LIBADD = $(AM_LIBADD) +module_combine_la_SOURCES = module-combine.c +module_combine_la_LDFLAGS = -module -avoid-version +module_combine_la_LIBADD = $(AM_LIBADD) + libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ polyplib-def.h \ tagstruct.c tagstruct.h \ diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 4e7cde48f..47685ca9c 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -44,7 +44,6 @@ enum { ARG_FAIL, ARG_VERBOSE, ARG_HIGH_PRIORITY, - ARG_STAY_ROOT, ARG_DISALLOW_MODULE_LOADING, ARG_EXIT_IDLE_TIME, ARG_MODULE_IDLE_TIME, @@ -63,7 +62,6 @@ static struct option long_options[] = { {"fail", 2, 0, ARG_FAIL}, {"verbose", 2, 0, ARG_VERBOSE}, {"high-priority", 2, 0, ARG_HIGH_PRIORITY}, - {"stay-root", 2, 0, ARG_STAY_ROOT}, {"disallow-module-loading", 2, 0, ARG_DISALLOW_MODULE_LOADING}, {"exit-idle-time", 2, 0, ARG_EXIT_IDLE_TIME}, {"module-idle-time", 2, 0, ARG_MODULE_IDLE_TIME}, @@ -93,7 +91,6 @@ void pa_cmdline_help(const char *argv0) { " --fail[=BOOL] Quit when startup fails\n" " --verbose[=BOOL] Be slightly more verbose\n" " --high-priority[=BOOL] Try to set high process priority (only available as root)\n" - " --stay-root[=BOOL] Don't drop root if SETUID root\n" " --disallow-module-loading[=BOOL] Disallow module loading after startup\n" " --exit-idle-time=SECS Terminate the daemon when idle and this time passed\n" " --module-idle-time=SECS Unload autoloaded modules when idle and this time passed\n" @@ -113,7 +110,6 @@ int pa_cmdline_parse(struct pa_conf *conf, int argc, char *const argv [], int *d assert(conf && argc && argv); buf = pa_strbuf_new(); - assert(buf); if (conf->script_commands) pa_strbuf_puts(buf, conf->script_commands); @@ -122,19 +118,19 @@ int pa_cmdline_parse(struct pa_conf *conf, int argc, char *const argv [], int *d switch (c) { case ARG_HELP: case 'h': - conf->help = 1; + conf->cmd = PA_CMD_HELP; break; case ARG_VERSION: - conf->version = 1; + conf->cmd = PA_CMD_VERSION; break; case ARG_DUMP_CONF: - conf->dump_conf = 1; + conf->cmd = PA_CMD_DUMP_CONF; break; case ARG_DUMP_MODULES: - conf->dump_modules = 1; + conf->cmd = PA_CMD_DUMP_MODULES; break; case ARG_LOAD: @@ -180,13 +176,6 @@ int pa_cmdline_parse(struct pa_conf *conf, int argc, char *const argv [], int *d } break; - case ARG_STAY_ROOT: - if ((conf->stay_root = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --stay-root expects boolean argument\n"); - goto fail; - } - break; - case ARG_DISALLOW_MODULE_LOADING: if ((conf->disallow_module_loading = optarg ? pa_parse_boolean(optarg) : 1) < 0) { pa_log(__FILE__": --disallow-module-loading expects boolean argument\n"); diff --git a/polyp/conf.c b/polyp/conf.c index 4a11c4807..9f1f6ba23 100644 --- a/polyp/conf.c +++ b/polyp/conf.c @@ -35,15 +35,11 @@ #include "strbuf.h" static const struct pa_conf default_conf = { - .help = 0, + .cmd = PA_CMD_DAEMON, .daemonize = 0, - .dump_conf = 0, - .dump_modules = 0, .fail = 1, .verbose = 0, .high_priority = 0, - .stay_root = 0, - .version = 0, .disallow_module_loading = 0, .exit_idle_time = -1, .module_idle_time = 20, @@ -143,7 +139,6 @@ static int next_assignment(struct pa_conf *c, char *lvalue, char *rvalue, unsign PARSE_BOOLEAN("fail", fail); PARSE_BOOLEAN("verbose", verbose); PARSE_BOOLEAN("high-priority", high_priority); - PARSE_BOOLEAN("stay-root", stay_root); PARSE_BOOLEAN("disallow-module-loading", disallow_module_loading); PARSE_INTEGER("exit-idle-time", exit_idle_time); @@ -269,7 +264,6 @@ char *pa_conf_dump(struct pa_conf *c) { pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize); pa_strbuf_printf(s, "fail = %i\n", !!c->fail); pa_strbuf_printf(s, "high-priority = %i\n", !!c->high_priority); - pa_strbuf_printf(s, "stay-root = %i\n", !!c->stay_root); pa_strbuf_printf(s, "disallow-module-loading = %i\n", !!c->disallow_module_loading); pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time); pa_strbuf_printf(s, "module-idle-time = %i\n", c->module_idle_time); diff --git a/polyp/conf.h b/polyp/conf.h index bbe253c22..da61be337 100644 --- a/polyp/conf.h +++ b/polyp/conf.h @@ -24,16 +24,20 @@ #include "log.h" +enum pa_conf_cmd { + PA_CMD_DAEMON, + PA_CMD_HELP, + PA_CMD_VERSION, + PA_CMD_DUMP_CONF, + PA_CMD_DUMP_MODULES +}; + struct pa_conf { - int help, - version, - dump_conf, - dump_modules, - daemonize, + enum pa_conf_cmd cmd; + int daemonize, fail, verbose, high_priority, - stay_root, disallow_module_loading, exit_idle_time, module_idle_time, diff --git a/polyp/config b/polyp/config index e0f8de507..b404bc408 100644 --- a/polyp/config +++ b/polyp/config @@ -31,11 +31,10 @@ ## Renice the daemon to level -15 and try to get SCHED_FIFO ## scheduling. This a good idea if you hear annyoing noise in the -## playback. However, this is a certain security issue. -; high-priority = 0 - -## Don't drop root rights on startup if called SUID root. -; stay-root = 0 +## playback. However, this is a certain security issue, since it works +## when called SUID root only. root is dropped immediately after gaining +## the nice level and SCHED_FIFO scheduling on startup. +high-priority = 0 ## Disallow module loading after startup ; disallow-module-loading = 0 @@ -48,7 +47,8 @@ module-idle-time = 20 ## The path were to look for dynamic shared objects (DSOs aka plugins). -## Specify an empty string for the default search path. +## Specify an empty string for the default search path. You may specify +## more than one path seperated by colons. ; dl-search-path = ## The default script file to load. Specify an empty string for not diff --git a/polyp/log.c b/polyp/log.c index 413266dfd..516cd2b07 100644 --- a/polyp/log.c +++ b/polyp/log.c @@ -41,6 +41,7 @@ void pa_log(const char *format, ...) { char *t = pa_vsprintf_malloc(format, ap); assert(user_log_func); user_log_func(t); + pa_xfree(t); } } diff --git a/polyp/main.c b/polyp/main.c index 148dfac2f..9de69ca61 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -124,6 +124,11 @@ int main(int argc, char *argv[]) { pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL); + if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) + pa_raise_priority(); + + drop_root(); + if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); #ifdef DLSEARCHPATH @@ -131,37 +136,33 @@ int main(int argc, char *argv[]) { lt_dlsetsearchpath(DLSEARCHPATH); #endif - if (conf->dump_modules) { - pa_dump_modules(conf, argc-d, argv+d); - retval = 0; - goto finish; - } - - if (conf->dump_conf) { - char *s = pa_conf_dump(conf); - fputs(s, stdout); - pa_xfree(s); - retval = 0; - goto finish; - } + switch (conf->cmd) { + case PA_CMD_DUMP_MODULES: + pa_dump_modules(conf, argc-d, argv+d); + retval = 0; + goto finish; - if (conf->help) { - pa_cmdline_help(argv[0]); - retval = 0; - goto finish; - } + case PA_CMD_DUMP_CONF: { + char *s = pa_conf_dump(conf); + fputs(s, stdout); + pa_xfree(s); + retval = 0; + goto finish; + } - if (conf->version) { - printf(PACKAGE_NAME" "PACKAGE_VERSION"\n"); - retval = 0; - goto finish; - } + case PA_CMD_HELP : + pa_cmdline_help(argv[0]); + retval = 0; + goto finish; - if (conf->high_priority) - pa_raise_priority(); - - if (!conf->stay_root) - drop_root(); + case PA_CMD_VERSION : + printf(PACKAGE_NAME" "PACKAGE_VERSION"\n"); + retval = 0; + goto finish; + + default: + assert(conf->cmd == PA_CMD_DAEMON); + } if (conf->daemonize) { pid_t child; diff --git a/polyp/module-combine.c b/polyp/module-combine.c new file mode 100644 index 000000000..0ab9d9ece --- /dev/null +++ b/polyp/module-combine.c @@ -0,0 +1,353 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "module.h" +#include "llist.h" +#include "sink.h" +#include "sink-input.h" +#include "memblockq.h" +#include "log.h" +#include "util.h" +#include "xmalloc.h" +#include "modargs.h" +#include "namereg.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Makes one playback device out of many") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink_name= master= slave=") + +#define DEFAULT_SINK_NAME "combine" +#define MEMBLOCKQ_MAXLENGTH (1024*170) +#define RENDER_SIZE (1024*10) + +#define ADJUST_TIME 5 + +static const char* const valid_modargs[] = { + "sink_name", + "master", + "slaves", + NULL +}; + +struct output { + struct userdata *userdata; + struct pa_sink_input *sink_input; + size_t counter; + struct pa_memblockq *memblockq; + pa_usec_t sink_latency; + PA_LLIST_FIELDS(struct output); +}; + +struct userdata { + struct pa_module *module; + struct pa_core *core; + struct pa_sink *sink; + unsigned n_outputs; + struct output *master; + struct pa_time_event *time_event; + + PA_LLIST_HEAD(struct output, outputs); +}; + +static void output_free(struct output *o); +static void clear_up(struct userdata *u); + +static void adjust_rates(struct userdata *u) { + struct output *o; + pa_usec_t max = 0; + uint32_t base_rate; + assert(u && u->sink); + + for (o = u->outputs; o; o = o->next) { + o->sink_latency = pa_sink_get_latency(o->sink_input->sink); + + if (o->sink_latency > max) + max = o->sink_latency; + } + + pa_log(__FILE__": [%s] maximum latency is %0.0f usec.\n", u->sink->name, (float) max); + + base_rate = u->sink->sample_spec.rate; + + for (o = u->outputs; o; o = o->next) { + pa_usec_t l; + uint32_t r = base_rate; + + l = o->sink_latency + pa_sink_input_get_latency(o->sink_input); + + if (l < max) + r -= (uint32_t) (((((double) max-l))/ADJUST_TIME)*r/ 1000000); + else if (l > max) + r += (uint32_t) (((((double) l-max))/ADJUST_TIME)*r/ 1000000); + + if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) + pa_log(__FILE__": [%s] sample rates too different, not adjusting (%u vs. %u).\n", o->sink_input->name, base_rate, r); + else + pa_log(__FILE__": [%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.\n", o->sink_input->name, r, (double) r / base_rate, (float) l); + + pa_sink_input_set_rate(o->sink_input, r); + } +} + +static void request_memblock(struct userdata *u) { + struct pa_memchunk chunk; + struct output *o; + assert(u && u->sink); + + if (pa_sink_render(u->sink, RENDER_SIZE, &chunk) < 0) + return; + + for (o = u->outputs; o; o = o->next) + pa_memblockq_push_align(o->memblockq, &chunk, 0); + + pa_memblock_unref(chunk.memblock); +} + +static void time_callback(struct pa_mainloop_api*a, struct pa_time_event* e, const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + struct timeval n; + assert(u && a && u->time_event == e); + + adjust_rates(u); + + gettimeofday(&n, NULL); + n.tv_sec += ADJUST_TIME; + u->sink->core->mainloop->time_restart(e, &n); +} + +static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { + struct output *o = i->userdata; + assert(i && o && o->sink_input && chunk); + + if (pa_memblockq_peek(o->memblockq, chunk) >= 0) + return 0; + + /* Try harder */ + request_memblock(o->userdata); + + return pa_memblockq_peek(o->memblockq, chunk); +} + +static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { + struct output *o = i->userdata; + assert(i && o && o->sink_input && chunk && length); + + pa_memblockq_drop(o->memblockq, chunk, length); + o->counter += length; +} + +static void sink_input_kill_cb(struct pa_sink_input *i) { + struct output *o = i->userdata; + assert(i && o && o->sink_input); + clear_up(o->userdata); +} + +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { + struct output *o = i->userdata; + assert(i && o && o->sink_input); + + return pa_bytes_to_usec(pa_memblockq_get_length(o->memblockq), &i->sample_spec); +} + +static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { + struct userdata *u = s->userdata; + assert(s && u && u->sink && u->master); + + return pa_sink_input_get_latency(u->master->sink_input); +} + +static struct output *output_new(struct userdata *u, struct pa_sink *sink) { + struct output *o = NULL; + char t[256]; + assert(u && sink && u->sink); + + o = pa_xmalloc(sizeof(struct output)); + o->userdata = u; + + o->counter = 0; + o->memblockq = pa_memblockq_new(MEMBLOCKQ_MAXLENGTH, MEMBLOCKQ_MAXLENGTH, pa_frame_size(&u->sink->sample_spec), 0, 0, sink->core->memblock_stat); + + snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1); + if (!(o->sink_input = pa_sink_input_new(sink, t, &u->sink->sample_spec, 1))) + goto fail; + + o->sink_input->get_latency = sink_input_get_latency_cb; + o->sink_input->peek = sink_input_peek_cb; + o->sink_input->drop = sink_input_drop_cb; + o->sink_input->kill = sink_input_kill_cb; + o->sink_input->userdata = o; + o->sink_input->owner = u->module; + + PA_LLIST_PREPEND(struct output, u->outputs, o); + u->n_outputs++; + return o; + +fail: + + if (o) { + if (o->sink_input) + pa_sink_input_free(o->sink_input); + + if (o->memblockq) + pa_memblockq_free(o->memblockq); + + pa_xfree(o); + } + + return NULL; +} + +static void output_free(struct output *o) { + assert(o); + PA_LLIST_REMOVE(struct output, o->userdata->outputs, o); + o->userdata->n_outputs--; + pa_memblockq_free(o->memblockq); + pa_sink_input_free(o->sink_input); + pa_xfree(o); +} + +static void clear_up(struct userdata *u) { + struct output *o; + assert(u); + + if (u->time_event) { + u->core->mainloop->time_free(u->time_event); + u->time_event = NULL; + } + + while ((o = u->outputs)) + output_free(o); + + u->master = NULL; + + if (u->sink) { + pa_sink_free(u->sink); + u->sink = NULL; + } +} + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + struct pa_modargs *ma = NULL; + const char *master_name, *slaves; + struct pa_sink *master_sink; + char *n = NULL; + const char*split_state; + struct timeval tv; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments\n"); + goto fail; + } + + u = pa_xmalloc(sizeof(struct userdata)); + m->userdata = u; + u->sink = NULL; + u->n_outputs = 0; + u->master = NULL; + u->module = m; + u->core = c; + u->time_event = NULL; + PA_LLIST_HEAD_INIT(struct output, u->outputs); + + if (!(master_name = pa_modargs_get_value(ma, "master", NULL)) || !(slaves = pa_modargs_get_value(ma, "slaves", NULL))) { + pa_log(__FILE__": no master or slave sinks specified\n"); + goto fail; + } + + if (!(master_sink = pa_namereg_get(c, master_name, PA_NAMEREG_SINK, 1))) { + pa_log(__FILE__": invalid master sink '%s'\n", master_name); + goto fail; + } + + if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec))) { + pa_log(__FILE__": failed to create sink\n"); + goto fail; + } + + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("Combined sink"); + u->sink->get_latency = sink_get_latency_cb; + u->sink->userdata = u; + + if (!(u->master = output_new(u, master_sink))) { + pa_log(__FILE__": failed to create master sink input on sink '%s'.\n", u->sink->name); + goto fail; + } + + split_state = NULL; + while ((n = pa_split(slaves, ",", &split_state))) { + struct pa_sink *slave_sink; + + if (!(slave_sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) { + pa_log(__FILE__": invalid slave sink '%s'\n", n); + goto fail; + } + + pa_xfree(n); + + if (!output_new(u, slave_sink)) { + pa_log(__FILE__": failed to create slave sink input on sink '%s'.\n", slave_sink->name); + goto fail; + } + } + + if (u->n_outputs <= 1) + pa_log(__FILE__": WARNING: no slave sinks specified.\n"); + + gettimeofday(&tv, NULL); + tv.tv_sec += ADJUST_TIME; + u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u); + + pa_modargs_free(ma); + return 0; + +fail: + pa_xfree(n); + + if (ma) + pa_modargs_free(ma); + + pa__done(c, m); + return -1; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + clear_up(u); + pa_xfree(u); +} + + diff --git a/polyp/module-sine.c b/polyp/module-sine.c index 98e0dc28a..b537452a6 100644 --- a/polyp/module-sine.c +++ b/polyp/module-sine.c @@ -134,7 +134,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { calc_sine(u->memblock->data, u->memblock->length, frequency); snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); - if (!(u->sink_input = pa_sink_input_new(sink, t, &ss))) + if (!(u->sink_input = pa_sink_input_new(sink, t, &ss, 0))) goto fail; u->sink_input->peek = sink_input_peek; diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index e3f0c006e..ace8ca698 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -85,7 +85,7 @@ int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sam if (volume <= 0) return 0; - if (!(si = pa_sink_input_new(sink, name, ss))) + if (!(si = pa_sink_input_new(sink, name, ss, 0))) return -1; si->volume = volume; diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index ee64c4849..103b17a31 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -298,7 +298,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons c->playback.fragment_size = l/10; assert(!c->sink_input); - c->sink_input = pa_sink_input_new(sink, name, &ss); + c->sink_input = pa_sink_input_new(sink, name, &ss, 0); assert(c->sink_input); c->sink_input->owner = c->protocol->module; diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 2d26c2f53..c1b197608 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -269,7 +269,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct struct pa_sink_input *sink_input; assert(c && sink && ss && name && maxlength); - if (!(sink_input = pa_sink_input_new(sink, name, ss))) + if (!(sink_input = pa_sink_input_new(sink, name, ss, 0))) return NULL; s = pa_xmalloc(sizeof(struct playback_stream)); diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 00db0aa05..96444f820 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -304,7 +304,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo goto fail; } - if (!(c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec))) { + if (!(c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec, 0))) { pa_log(__FILE__": Failed to create sink input.\n"); goto fail; } diff --git a/polyp/resampler.c b/polyp/resampler.c index 173c0987f..4742ce212 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -67,12 +67,9 @@ struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const stru r->i_buf = r->o_buf = NULL; r->i_alloc = r->o_alloc = 0; - if (a->rate != b->rate) { - r->src_state = src_new(SRC_SINC_FASTEST, r->channels, &err); - if (err != 0 || !r->src_state) - goto fail; - } else - r->src_state = NULL; + r->src_state = src_new(SRC_SINC_FASTEST, r->channels, &err); + if (err != 0 || !r->src_state) + goto fail; r->i_ss = *a; r->o_ss = *b; @@ -196,3 +193,12 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru out->memblock = NULL; } } + +void pa_resampler_set_input_rate(struct pa_resampler *r, uint32_t rate) { + int ret; + assert(r); + + r->i_ss.rate = rate; + ret = src_set_ratio(r->src_state, (double) r->o_ss.rate / r->i_ss.rate); + assert(ret == 0); +} diff --git a/polyp/resampler.h b/polyp/resampler.h index e23d145d9..a6ef30dff 100644 --- a/polyp/resampler.h +++ b/polyp/resampler.h @@ -34,4 +34,6 @@ void pa_resampler_free(struct pa_resampler *r); size_t pa_resampler_request(struct pa_resampler *r, size_t out_length); void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out); +void pa_resampler_set_input_rate(struct pa_resampler *r, uint32_t rate); + #endif diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 7763f2610..0d59062d0 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -36,7 +36,7 @@ #define CONVERT_BUFFER_LENGTH 4096 -struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec) { +struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate) { struct pa_sink_input *i; struct pa_resampler *resampler = NULL; int r; @@ -48,7 +48,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con return NULL; } - if (!pa_sample_spec_equal(spec, &s->sample_spec)) + if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec)) if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat))) return NULL; @@ -199,3 +199,13 @@ void pa_sink_input_cork(struct pa_sink_input *i, int b) { if (n) pa_sink_notify(i->sink); } + +void pa_sink_input_set_rate(struct pa_sink_input *i, uint32_t rate) { + assert(i && i->resampler); + + if (i->sample_spec.rate == rate) + return; + + i->sample_spec.rate = rate; + pa_resampler_set_input_rate(i->resampler, rate); +} diff --git a/polyp/sink-input.h b/polyp/sink-input.h index e2478ed61..e5b063872 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -54,7 +54,7 @@ struct pa_sink_input { struct pa_resampler *resampler; }; -struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec); +struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate); void pa_sink_input_free(struct pa_sink_input* i); /* Code that didn't create the input stream should call this function to @@ -70,4 +70,6 @@ void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume); void pa_sink_input_cork(struct pa_sink_input *i, int b); +void pa_sink_input_set_rate(struct pa_sink_input *i, uint32_t rate); + #endif diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c index c667f5ff6..e77ff1199 100644 --- a/polyp/sound-file-stream.c +++ b/polyp/sound-file-stream.c @@ -142,7 +142,7 @@ int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume) { goto fail; } - if (!(u->sink_input = pa_sink_input_new(sink, fname, &ss))) + if (!(u->sink_input = pa_sink_input_new(sink, fname, &ss, 0))) goto fail; u->sink_input->volume = volume; diff --git a/polyp/util.c b/polyp/util.c index 039ec264d..3ab6d51ac 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -373,3 +373,19 @@ int pa_parse_boolean(const char *v) { return -1; } + +char *pa_split(const char *c, const char *delimiter, const char**state) { + const char *current = *state ? *state : c; + size_t l; + + if (!*current) + return NULL; + + l = strcspn(current, delimiter); + *state = current+l; + + if (**state) + *state++; + + return pa_xstrndup(current, l); +} diff --git a/polyp/util.h b/polyp/util.h index 42e0b22ba..eae98e6e6 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -59,4 +59,6 @@ int pa_fd_set_cloexec(int fd, int b); int pa_parse_boolean(const char *s); +char *pa_split(const char *c, const char*delimiters, const char **state); + #endif From 6e019795bff589ef0a867772975e34da78fffefb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Sep 2004 20:53:25 +0000 Subject: [PATCH 0196/1514] add refernce counting for sinks, sources, sink-inputs and source-outputs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@200 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/cli-command.c | 2 +- polyp/core.c | 1 + polyp/core.h | 1 + polyp/module-alsa-sink.c | 6 +- polyp/module-alsa-source.c | 6 +- polyp/module-cli.c | 2 +- polyp/module-combine.c | 17 ++++-- polyp/module-oss-mmap.c | 12 ++-- polyp/module-oss.c | 13 ++-- polyp/module-pipe-sink.c | 3 +- polyp/module-pipe-source.c | 3 +- polyp/module-sine.c | 14 ++++- polyp/module.c | 57 ++++++++++++------ polyp/module.h | 8 ++- polyp/play-memchunk.c | 5 +- polyp/protocol-esound.c | 14 +++-- polyp/protocol-native.c | 6 +- polyp/protocol-simple.c | 12 ++-- polyp/sink-input.c | 84 ++++++++++++++++++++------ polyp/sink-input.h | 21 +++++-- polyp/sink.c | 119 ++++++++++++++++++++++++++++--------- polyp/sink.h | 13 +++- polyp/sound-file-stream.c | 7 ++- polyp/source-output.c | 56 +++++++++++++---- polyp/source-output.h | 17 +++++- polyp/source.c | 47 ++++++++++++--- polyp/source.h | 12 +++- 27 files changed, 426 insertions(+), 132 deletions(-) diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 52926199e..b44fbf4aa 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -294,7 +294,7 @@ static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, stru return -1; } - pa_module_unload_request(c, m); + pa_module_unload_request(m); return 0; } diff --git a/polyp/core.c b/polyp/core.c index 0b33c1070..0b0bbb561 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -62,6 +62,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->default_sample_spec.channels = 2; c->auto_unload_event = NULL; + c->defer_unload_event = NULL; c->subscription_defer_event = NULL; c->subscription_event_queue = NULL; diff --git a/polyp/core.h b/polyp/core.h index a85dafd4c..b4470577d 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -39,6 +39,7 @@ struct pa_core { struct pa_sample_spec default_sample_spec; struct pa_time_event *auto_unload_event; + struct pa_defer_event *defer_unload_event; struct pa_defer_event *subscription_defer_event; struct pa_queue *subscription_event_queue; diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 55e719c90..c31b73f0c 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -259,8 +259,10 @@ void pa__done(struct pa_core *c, struct pa_module*m) { if (!(u = m->userdata)) return; - if (u->sink) - pa_sink_free(u->sink); + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + } if (u->io_events) pa_free_io_events(c->mainloop, u->io_events, u->n_io_events); diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 3ef54b17c..cf828eb0a 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -232,8 +232,10 @@ void pa__done(struct pa_core *c, struct pa_module*m) { if (!(u = m->userdata)) return; - if (u->source) - pa_source_free(u->source); + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + } if (u->io_events) pa_free_io_events(c->mainloop, u->io_events, u->n_io_events); diff --git a/polyp/module-cli.c b/polyp/module-cli.c index 35b69cb68..94c65d078 100644 --- a/polyp/module-cli.c +++ b/polyp/module-cli.c @@ -41,7 +41,7 @@ static void eof_cb(struct pa_cli*c, void *userdata) { struct pa_module *m = userdata; assert(c && m); - pa_module_unload_request(m->core, m); + pa_module_unload_request(m); } int pa__init(struct pa_core *c, struct pa_module*m) { diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 0ab9d9ece..28e3b39df 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -38,7 +38,7 @@ #include "namereg.h" PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Makes one playback device out of many") +PA_MODULE_DESCRIPTION("Combine multiple sinks to one") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= master= slave=") @@ -85,7 +85,7 @@ static void adjust_rates(struct userdata *u) { assert(u && u->sink); for (o = u->outputs; o; o = o->next) { - o->sink_latency = pa_sink_get_latency(o->sink_input->sink); + o->sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0; if (o->sink_latency > max) max = o->sink_latency; @@ -165,6 +165,7 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk static void sink_input_kill_cb(struct pa_sink_input *i) { struct output *o = i->userdata; assert(i && o && o->sink_input); + pa_module_unload_request(o->userdata->module); clear_up(o->userdata); } @@ -211,8 +212,10 @@ static struct output *output_new(struct userdata *u, struct pa_sink *sink) { fail: if (o) { - if (o->sink_input) - pa_sink_input_free(o->sink_input); + if (o->sink_input) { + pa_sink_input_disconnect(o->sink_input); + pa_sink_input_unref(o->sink_input); + } if (o->memblockq) pa_memblockq_free(o->memblockq); @@ -228,7 +231,8 @@ static void output_free(struct output *o) { PA_LLIST_REMOVE(struct output, o->userdata->outputs, o); o->userdata->n_outputs--; pa_memblockq_free(o->memblockq); - pa_sink_input_free(o->sink_input); + pa_sink_input_disconnect(o->sink_input); + pa_sink_input_unref(o->sink_input); pa_xfree(o); } @@ -247,7 +251,8 @@ static void clear_up(struct userdata *u) { u->master = NULL; if (u->sink) { - pa_sink_free(u->sink); + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); u->sink = NULL; } } diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 8e1652185..015f4c6cf 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -403,11 +403,15 @@ void pa__done(struct pa_core *c, struct pa_module*m) { if (u->out_mmap && u->out_mmap != MAP_FAILED) munmap(u->out_mmap, u->out_mmap_length); - if (u->sink) - pa_sink_free(u->sink); + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + } - if (u->source) - pa_source_free(u->source); + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + } if (u->io_event) u->core->mainloop->io_free(u->io_event); diff --git a/polyp/module-oss.c b/polyp/module-oss.c index b4e011d84..a45f72b8c 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -322,10 +322,15 @@ void pa__done(struct pa_core *c, struct pa_module*m) { if (u->silence.memblock) pa_memblock_unref(u->silence.memblock); - if (u->sink) - pa_sink_free(u->sink); - if (u->source) - pa_source_free(u->source); + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + } + + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + } pa_iochannel_free(u->io); pa_xfree(u); diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index 1aaf3b6a5..57e7425b2 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -215,7 +215,8 @@ void pa__done(struct pa_core *c, struct pa_module*m) { if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); - pa_sink_free(u->sink); + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); pa_iochannel_free(u->io); u->core->mainloop->defer_free(u->defer_event); diff --git a/polyp/module-pipe-source.c b/polyp/module-pipe-source.c index a226d44e4..61fcdce8c 100644 --- a/polyp/module-pipe-source.c +++ b/polyp/module-pipe-source.c @@ -195,7 +195,8 @@ void pa__done(struct pa_core *c, struct pa_module*m) { if (u->chunk.memblock) pa_memblock_unref(u->chunk.memblock); - pa_source_free(u->source); + pa_source_disconnect(u->source); + pa_source_unref(u->source); pa_iochannel_free(u->io); assert(u->filename); diff --git a/polyp/module-sine.c b/polyp/module-sine.c index b537452a6..2fa7759c9 100644 --- a/polyp/module-sine.c +++ b/polyp/module-sine.c @@ -41,6 +41,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) struct userdata { struct pa_core *core; + struct pa_module *module; struct pa_sink_input *sink_input; struct pa_memblock *memblock; size_t peek_index; @@ -81,8 +82,11 @@ static void sink_input_kill(struct pa_sink_input *i) { assert(i && i->userdata); u = i->userdata; - pa_sink_input_free(u->sink_input); + pa_sink_input_disconnect(u->sink_input); + pa_sink_input_unref(u->sink_input); u->sink_input = NULL; + + pa_module_unload_request(u->module); } static void calc_sine(float *f, size_t l, float freq) { @@ -110,6 +114,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { m->userdata = u = pa_xmalloc(sizeof(struct userdata)); u->core = c; + u->module = m; u->sink_input = NULL; u->memblock = NULL; @@ -163,8 +168,11 @@ void pa__done(struct pa_core *c, struct pa_module*m) { if (!u) return; - if (u->sink_input) - pa_sink_input_free(u->sink_input); + if (u->sink_input) { + pa_sink_input_disconnect(u->sink_input); + pa_sink_input_unref(u->sink_input); + } + if (u->memblock) pa_memblock_unref(u->memblock); pa_xfree(u); diff --git a/polyp/module.c b/polyp/module.c index db21f7901..73f5468cf 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -85,6 +85,7 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char m->core = c; m->n_used = -1; m->auto_unload = 0; + m->unload_requested = 0; assert(m->init); if (m->init(c, m) < 0) { @@ -183,9 +184,15 @@ void pa_module_unload_all(struct pa_core *c) { pa_idxset_free(c->modules, free_callback, NULL); c->modules = NULL; - if (c->auto_unload_event) + if (c->auto_unload_event) { c->mainloop->time_free(c->auto_unload_event); - c->auto_unload_event = NULL; + c->auto_unload_event = NULL; + } + + if (c->defer_unload_event) { + c->mainloop->defer_free(c->defer_unload_event); + c->defer_unload_event = NULL; + } } static int unused_callback(void *p, uint32_t index, int *del, void *userdata) { @@ -212,26 +219,38 @@ void pa_module_unload_unused(struct pa_core *c) { pa_idxset_foreach(c->modules, unused_callback, &now); } -struct once_info { - struct pa_core *core; - uint32_t index; -}; - -static void module_unload_once_callback(struct pa_mainloop_api *m, void *userdata) { - struct once_info *i = userdata; - assert(i); - pa_module_unload_by_index(i->core, i->index); - pa_xfree(i); +static int unload_callback(void *p, uint32_t index, int *del, void *userdata) { + struct pa_module *m = p; + assert(m); + + if (m->unload_requested) { + pa_module_free(m); + *del = 1; + } + + return 0; } -void pa_module_unload_request(struct pa_core *c, struct pa_module *m) { - struct once_info *i; - assert(c && m); +static void defer_cb(struct pa_mainloop_api*api, struct pa_defer_event *e, void *userdata) { + struct pa_core *core = userdata; + api->defer_enable(e, 0); - i = pa_xmalloc(sizeof(struct once_info)); - i->core = c; - i->index = m->index; - pa_mainloop_api_once(c->mainloop, module_unload_once_callback, i); + if (!core->modules) + return; + + pa_idxset_foreach(core->modules, unload_callback, NULL); + +} + +void pa_module_unload_request(struct pa_module *m) { + assert(m); + + m->unload_requested = 1; + + if (!m->core->defer_unload_event) + m->core->defer_unload_event = m->core->mainloop->defer_new(m->core->mainloop, defer_cb, m->core); + + m->core->mainloop->defer_enable(m->core->defer_unload_event, 1); } void pa_module_set_used(struct pa_module*m, int used) { diff --git a/polyp/module.h b/polyp/module.h index 663e0246b..f422132ad 100644 --- a/polyp/module.h +++ b/polyp/module.h @@ -43,16 +43,18 @@ struct pa_module { int n_used; int auto_unload; time_t last_used_time; + + int unload_requested; }; struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char*argument); -void pa_module_unload(struct pa_core *c, struct pa_module *m); -void pa_module_unload_by_index(struct pa_core *c, uint32_t index); +/* void pa_module_unload(struct pa_core *c, struct pa_module *m); */ +/* void pa_module_unload_by_index(struct pa_core *c, uint32_t index); */ void pa_module_unload_all(struct pa_core *c); void pa_module_unload_unused(struct pa_core *c); -void pa_module_unload_request(struct pa_core *c, struct pa_module *m); +void pa_module_unload_request(struct pa_module *m); void pa_module_set_used(struct pa_module*m, int used); diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index ace8ca698..6490547eb 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -37,9 +37,12 @@ static void sink_input_kill(struct pa_sink_input *i) { assert(i && i->userdata); c = i->userdata; + pa_sink_input_disconnect(i); + pa_sink_input_unref(i); + pa_memblock_unref(c->memblock); pa_xfree(c); - pa_sink_input_free(i); + } static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 103b17a31..8ec48a342 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -167,10 +167,16 @@ static void connection_free(struct connection *c) { pa_client_free(c->client); - if (c->sink_input) - pa_sink_input_free(c->sink_input); - if (c->source_output) - pa_source_output_free(c->source_output); + if (c->sink_input) { + pa_sink_input_disconnect(c->sink_input); + pa_sink_input_unref(c->sink_input); + } + + if (c->source_output) { + pa_source_output_disconnect(c->source_output); + pa_source_output_unref(c->source_output); + } + if (c->input_memblockq) pa_memblockq_free(c->input_memblockq); if (c->output_memblockq) diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index c1b197608..29821b6c5 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -255,7 +255,8 @@ static void record_stream_free(struct record_stream* r) { assert(r && r->connection); pa_idxset_remove_by_data(r->connection->record_streams, r, NULL); - pa_source_output_free(r->source_output); + pa_source_output_disconnect(r->source_output); + pa_source_output_unref(r->source_output); pa_memblockq_free(r->memblockq); pa_xfree(r); } @@ -302,7 +303,8 @@ static void playback_stream_free(struct playback_stream* p) { pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERROR_NOENTITY); pa_idxset_remove_by_data(p->connection->output_streams, p, NULL); - pa_sink_input_free(p->sink_input); + pa_sink_input_disconnect(p->sink_input); + pa_sink_input_unref(p->sink_input); pa_memblockq_free(p->memblockq); pa_xfree(p); } diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 96444f820..58156329c 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -80,10 +80,14 @@ static void connection_free(struct connection *c) { if (c->playback.current_memblock) pa_memblock_unref(c->playback.current_memblock); - if (c->sink_input) - pa_sink_input_free(c->sink_input); - if (c->source_output) - pa_source_output_free(c->source_output); + if (c->sink_input) { + pa_sink_input_disconnect(c->sink_input); + pa_sink_input_unref(c->sink_input); + } + if (c->source_output) { + pa_source_output_disconnect(c->source_output); + pa_source_output_unref(c->source_output); + } if (c->client) pa_client_free(c->client); if (c->io) diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 0d59062d0..e2b9e0cf5 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -41,7 +41,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con struct pa_resampler *resampler = NULL; int r; char st[256]; - assert(s && spec); + assert(s && spec && s->state == PA_SINK_RUNNING); if (pa_idxset_ncontents(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { pa_log(__FILE__": Failed to create sink input: too many inputs per sink.\n"); @@ -53,6 +53,8 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con return NULL; i = pa_xmalloc(sizeof(struct pa_sink_input)); + i->ref = 1; + i->state = PA_SINK_INPUT_RUNNING; i->name = pa_xstrdup(name); i->client = NULL; i->owner = NULL; @@ -86,26 +88,53 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con return i; } -void pa_sink_input_free(struct pa_sink_input* i) { - assert(i); +void pa_sink_input_disconnect(struct pa_sink_input *i) { + assert(i && i->state == PA_SINK_INPUT_RUNNING && i->sink && i->sink->core); - assert(i->sink && i->sink->core); pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL); pa_idxset_remove_by_data(i->sink->inputs, i, NULL); + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index); + i->sink = NULL; + + i->peek = NULL; + i->drop = NULL; + i->kill = NULL; + i->get_latency = NULL; + + i->state = PA_SINK_INPUT_DISCONNECTED; +} + +static void sink_input_free(struct pa_sink_input* i) { + assert(i); + + if (i->state != PA_SINK_INPUT_DISCONNECTED) + pa_sink_input_disconnect(i); + if (i->resampled_chunk.memblock) pa_memblock_unref(i->resampled_chunk.memblock); if (i->resampler) pa_resampler_free(i->resampler); - pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index); - pa_xfree(i->name); pa_xfree(i); } +void pa_sink_input_unref(struct pa_sink_input *i) { + assert(i && i->ref >= 1); + + if (!(--i->ref)) + sink_input_free(i); +} + +struct pa_sink_input* pa_sink_input_ref(struct pa_sink_input *i) { + assert(i && i->ref >= 1); + i->ref++; + return i; +} + void pa_sink_input_kill(struct pa_sink_input*i) { - assert(i); + assert(i && i->ref >= 1); if (i->kill) i->kill(i); @@ -113,7 +142,7 @@ void pa_sink_input_kill(struct pa_sink_input*i) { pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i) { pa_usec_t r = 0; - assert(i); + assert(i && i->ref >= 1); if (i->get_latency) r += i->get_latency(i); @@ -125,7 +154,11 @@ pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i) { } int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { - assert(i && chunk && i->peek && i->drop); + int ret = 0; + assert(i && chunk && i->ref >= 1); + + if (!i->peek || !i->drop) + return -1; if (i->corked) return -1; @@ -133,13 +166,14 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { if (!i->resampler) return i->peek(i, chunk); + pa_sink_input_ref(i); + while (!i->resampled_chunk.memblock) { struct pa_memchunk tchunk; size_t l; - int ret; if ((ret = i->peek(i, &tchunk)) < 0) - return ret; + goto finish; assert(tchunk.length); @@ -158,14 +192,22 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { assert(i->resampled_chunk.memblock && i->resampled_chunk.length); *chunk = i->resampled_chunk; pa_memblock_ref(i->resampled_chunk.memblock); - return 0; + + ret = 0; + +finish: + + pa_sink_input_unref(i); + + return ret; } void pa_sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { - assert(i && length); + assert(i && length && i->ref >= 1); if (!i->resampler) { - i->drop(i, chunk, length); + if (i->drop) + i->drop(i, chunk, length); return; } @@ -182,7 +224,7 @@ void pa_sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk } void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume) { - assert(i && i->sink && i->sink->core); + assert(i && i->sink && i->sink->core && i->ref >= 1); if (i->volume != volume) { i->volume = volume; @@ -192,7 +234,8 @@ void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume) { void pa_sink_input_cork(struct pa_sink_input *i, int b) { int n; - assert(i); + assert(i && i->ref >= 1); + n = i->corked && !b; i->corked = b; @@ -201,7 +244,7 @@ void pa_sink_input_cork(struct pa_sink_input *i, int b) { } void pa_sink_input_set_rate(struct pa_sink_input *i, uint32_t rate) { - assert(i && i->resampler); + assert(i && i->resampler && i->ref >= 1); if (i->sample_spec.rate == rate) return; @@ -209,3 +252,10 @@ void pa_sink_input_set_rate(struct pa_sink_input *i, uint32_t rate) { i->sample_spec.rate = rate; pa_resampler_set_input_rate(i->resampler, rate); } + +void pa_sink_input_set_name(struct pa_sink_input *i, const char *name) { + assert(i && i->ref >= 1); + + pa_xfree(i->name); + i->name = pa_xstrdup(name); +} diff --git a/polyp/sink-input.h b/polyp/sink-input.h index e5b063872..376783004 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -31,7 +31,15 @@ #include "module.h" #include "client.h" +enum pa_sink_input_state { + PA_SINK_INPUT_RUNNING, + PA_SINK_INPUT_DISCONNECTED +}; + struct pa_sink_input { + int ref; + enum pa_sink_input_state state; + uint32_t index; int corked; @@ -55,11 +63,14 @@ struct pa_sink_input { }; struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate); -void pa_sink_input_free(struct pa_sink_input* i); +void pa_sink_input_unref(struct pa_sink_input* i); +struct pa_sink_input* pa_sink_input_ref(struct pa_sink_input* i); -/* Code that didn't create the input stream should call this function to - * request destruction of it */ -void pa_sink_input_kill(struct pa_sink_input *i); +/* To be called by the implementing module only */ +void pa_sink_input_disconnect(struct pa_sink_input* i); + +/* External code may request disconnection with this funcion */ +void pa_sink_input_kill(struct pa_sink_input*i); pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i); @@ -72,4 +83,6 @@ void pa_sink_input_cork(struct pa_sink_input *i, int b); void pa_sink_input_set_rate(struct pa_sink_input *i, uint32_t rate); +void pa_sink_input_set_name(struct pa_sink_input *i, const char *name); + #endif diff --git a/polyp/sink.c b/polyp/sink.c index 1fe38e9f9..6d3b59c77 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -52,9 +52,12 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co pa_xfree(s); return NULL; } - + s->name = pa_xstrdup(name); s->description = NULL; + + s->ref = 1; + s->state = PA_SINK_RUNNING; s->owner = NULL; s->core = core; @@ -85,9 +88,9 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co return s; } -void pa_sink_free(struct pa_sink *s) { +void pa_sink_disconnect(struct pa_sink* s) { struct pa_sink_input *i, *j = NULL; - assert(s); + assert(s && s->state == PA_SINK_RUNNING); pa_namereg_unregister(s->core, s->name); @@ -96,22 +99,51 @@ void pa_sink_free(struct pa_sink *s) { pa_sink_input_kill(i); j = i; } - pa_idxset_free(s->inputs, NULL, NULL); - pa_source_free(s->monitor_source); + pa_source_disconnect(s->monitor_source); + pa_idxset_remove_by_data(s->core->sinks, s, NULL); + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + + s->notify = NULL; + s->get_latency = NULL; + + s->state = PA_SINK_DISCONNECTED; +} + +static void sink_free(struct pa_sink *s) { + assert(s && s->ref == 0); + + if (s->state != PA_SINK_DISCONNECTED) + pa_sink_disconnect(s); pa_log(__FILE__": freed %u \"%s\"\n", s->index, s->name); - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + pa_source_unref(s->monitor_source); + s->monitor_source = NULL; + pa_idxset_free(s->inputs, NULL, NULL); + pa_xfree(s->name); pa_xfree(s->description); pa_xfree(s); } +void pa_sink_unref(struct pa_sink*s) { + assert(s && s->ref >= 1); + + if (!(--s->ref)) + sink_free(s); +} + +struct pa_sink* pa_sink_ref(struct pa_sink *s) { + assert(s && s->ref >= 1); + s->ref++; + return s; +} + void pa_sink_notify(struct pa_sink*s) { - assert(s); + assert(s && s->ref >= 1); if (s->notify) s->notify(s); @@ -122,16 +154,20 @@ static unsigned fill_mix_info(struct pa_sink *s, struct pa_mix_info *info, unsig struct pa_sink_input *i; unsigned n = 0; - assert(s && info); + assert(s && s->ref >= 1 && info); for (i = pa_idxset_first(s->inputs, &index); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &index)) { - if (pa_sink_input_peek(i, &info->chunk) < 0) + pa_sink_input_ref(i); + + if (pa_sink_input_peek(i, &info->chunk) < 0) { + pa_sink_input_unref(i); continue; + } info->volume = i->volume; + info->userdata = i; assert(info->chunk.memblock && info->chunk.memblock->data && info->chunk.length); - info->userdata = i; info++; maxinfo--; @@ -142,7 +178,7 @@ static unsigned fill_mix_info(struct pa_sink *s, struct pa_mix_info *info, unsig } static void inputs_drop(struct pa_sink *s, struct pa_mix_info *info, unsigned maxinfo, size_t length) { - assert(s && info); + assert(s && s->ref >= 1 && info); for (; maxinfo > 0; maxinfo--, info++) { struct pa_sink_input *i = info->userdata; @@ -150,6 +186,9 @@ static void inputs_drop(struct pa_sink *s, struct pa_mix_info *info, unsigned ma pa_sink_input_drop(i, &info->chunk, length); pa_memblock_unref(info->chunk.memblock); + + pa_sink_input_unref(i); + info->userdata = NULL; } } @@ -157,12 +196,15 @@ int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) struct pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; size_t l; - assert(s && length && result); + int r = -1; + assert(s && s->ref >= 1 && length && result); + pa_sink_ref(s); + n = fill_mix_info(s, info, MAX_MIX_CHANNELS); if (n <= 0) - return -1; + goto finish; if (n == 1) { uint32_t volume = PA_VOLUME_NORM; @@ -198,19 +240,27 @@ int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) assert(s->monitor_source); pa_source_post(s->monitor_source, result); - return 0; + r = 0; + +finish: + pa_sink_unref(s); + + return r; } int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) { struct pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; size_t l; - assert(s && target && target->length && target->memblock && target->memblock->data); + int r = -1; + assert(s && s->ref >= 1 && target && target->length && target->memblock && target->memblock->data); + + pa_sink_ref(s); n = fill_mix_info(s, info, MAX_MIX_CHANNELS); if (n <= 0) - return -1; + goto finish; if (n == 1) { uint32_t volume = PA_VOLUME_NORM; @@ -238,14 +288,21 @@ int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) { assert(s->monitor_source); pa_source_post(s->monitor_source, target); - return 0; + r = 0; + +finish: + pa_sink_unref(s); + + return r; } void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target) { struct pa_memchunk chunk; size_t l, d; - assert(s && target && target->memblock && target->length && target->memblock->data); + assert(s && s->ref >= 1 && target && target->memblock && target->length && target->memblock->data); + pa_sink_ref(s); + l = target->length; d = 0; while (l > 0) { @@ -266,10 +323,12 @@ void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target) { chunk.length -= d; pa_silence_memchunk(&chunk, &s->sample_spec); } + + pa_sink_unref(s); } void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *result) { - assert(s && length && result); + assert(s && s->ref >= 1 && length && result); /*** This needs optimization ***/ @@ -280,7 +339,7 @@ void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *r } pa_usec_t pa_sink_get_latency(struct pa_sink *s) { - assert(s); + assert(s && s->ref >= 1); if (!s->get_latency) return 0; @@ -288,18 +347,20 @@ pa_usec_t pa_sink_get_latency(struct pa_sink *s) { return s->get_latency(s); } -void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) { - sink->owner = m; +void pa_sink_set_owner(struct pa_sink *s, struct pa_module *m) { + assert(s && s->ref >= 1); + + s->owner = m; - if (sink->monitor_source) - pa_source_set_owner(sink->monitor_source, m); + if (s->monitor_source) + pa_source_set_owner(s->monitor_source, m); } -void pa_sink_set_volume(struct pa_sink *sink, pa_volume_t volume) { - assert(sink); +void pa_sink_set_volume(struct pa_sink *s, pa_volume_t volume) { + assert(s && s->ref >= 1); - if (sink->volume != volume) { - sink->volume = volume; - pa_subscription_post(sink->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, sink->index); + if (s->volume != volume) { + s->volume = volume; + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } } diff --git a/polyp/sink.h b/polyp/sink.h index 881e75d31..b34a736cc 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -33,7 +33,15 @@ struct pa_sink; #define PA_MAX_INPUTS_PER_SINK 6 +enum pa_sink_state { + PA_SINK_RUNNING, + PA_SINK_DISCONNECTED +}; + struct pa_sink { + int ref; + enum pa_sink_state state; + uint32_t index; char *name, *description; @@ -52,7 +60,10 @@ struct pa_sink { }; struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec); -void pa_sink_free(struct pa_sink* s); +void pa_sink_disconnect(struct pa_sink* s); +void pa_sink_unref(struct pa_sink*s); +struct pa_sink* pa_sink_ref(struct pa_sink *s); + int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result); void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *result); diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c index e77ff1199..60a58f473 100644 --- a/polyp/sound-file-stream.c +++ b/polyp/sound-file-stream.c @@ -45,8 +45,11 @@ struct userdata { static void free_userdata(struct userdata *u) { assert(u); - if (u->sink_input) - pa_sink_input_free(u->sink_input); + if (u->sink_input) { + pa_sink_input_disconnect(u->sink_input); + pa_sink_input_unref(u->sink_input); + } + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); if (u->sndfile) diff --git a/polyp/source-output.c b/polyp/source-output.c index 55448b5c5..3abf9c187 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -49,6 +49,8 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n return NULL; o = pa_xmalloc(sizeof(struct pa_source_output)); + o->ref = 1; + o->state = PA_SOURCE_OUTPUT_RUNNING; o->name = pa_xstrdup(name); o->client = NULL; o->owner = NULL; @@ -71,27 +73,55 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n return o; } -void pa_source_output_free(struct pa_source_output* o) { - assert(o); - - assert(o->source && o->source->core); +void pa_source_output_disconnect(struct pa_source_output*o) { + assert(o && o->state == PA_SOURCE_OUTPUT_RUNNING && o->source && o->source->core); + pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL); pa_idxset_remove_by_data(o->source->outputs, o, NULL); + pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index); + o->source = NULL; + + o->push = NULL; + o->kill = NULL; + + + o->state = PA_SOURCE_OUTPUT_DISCONNECTED; +} + +static void source_output_free(struct pa_source_output* o) { + assert(o); + + if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED) + pa_source_output_disconnect(o); + if (o->resampler) pa_resampler_free(o->resampler); - pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index); - pa_xfree(o->name); pa_xfree(o); } -void pa_source_output_kill(struct pa_source_output*i) { - assert(i); - if (i->kill) - i->kill(i); +void pa_source_output_unref(struct pa_source_output* o) { + assert(o && o->ref >= 1); + + if (!(--o->ref)) + source_output_free(o); +} + +struct pa_source_output* pa_source_output_ref(struct pa_source_output *o) { + assert(o && o->ref >= 1); + o->ref++; + return o; +} + + +void pa_source_output_kill(struct pa_source_output*o) { + assert(o && o->ref >= 1); + + if (o->kill) + o->kill(o); } void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk *chunk) { @@ -111,3 +141,9 @@ void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk o->push(o, &rchunk); pa_memblock_unref(rchunk.memblock); } + +void pa_source_output_set_name(struct pa_source_output *o, const char *name) { + assert(o && o->ref >= 1); + pa_xfree(o->name); + o->name = pa_xstrdup(name); +} diff --git a/polyp/source-output.h b/polyp/source-output.h index 0e6e2cfdf..709d65ad9 100644 --- a/polyp/source-output.h +++ b/polyp/source-output.h @@ -31,7 +31,15 @@ #include "module.h" #include "client.h" +enum pa_source_output_state { + PA_SOURCE_OUTPUT_RUNNING, + PA_SOURCE_OUTPUT_DISCONNECTED +}; + struct pa_source_output { + int ref; + enum pa_source_output_state state; + uint32_t index; char *name; @@ -49,10 +57,17 @@ struct pa_source_output { }; struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec); -void pa_source_output_free(struct pa_source_output* o); +void pa_source_output_unref(struct pa_source_output* o); +struct pa_source_output* pa_source_output_ref(struct pa_source_output *o); +/* To be called by the implementing module only */ +void pa_source_output_disconnect(struct pa_source_output*o); + +/* External code may request disconnection with this funcion */ void pa_source_output_kill(struct pa_source_output*o); void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk *chunk); +void pa_source_output_set_name(struct pa_source_output *i, const char *name); + #endif diff --git a/polyp/source.c b/polyp/source.c index 5cdfdb551..2c0caca07 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -48,6 +48,9 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail return NULL; } + s->ref = 1; + s->state = PA_SOURCE_RUNNING; + s->name = pa_xstrdup(name); s->description = NULL; @@ -71,9 +74,9 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail return s; } -void pa_source_free(struct pa_source *s) { +void pa_source_disconnect(struct pa_source *s) { struct pa_source_output *o, *j = NULL; - assert(s); + assert(s && s->state == PA_SOURCE_RUNNING); pa_namereg_unregister(s->core, s->name); @@ -82,21 +85,45 @@ void pa_source_free(struct pa_source *s) { pa_source_output_kill(o); j = o; } - pa_idxset_free(s->outputs, NULL, NULL); - - pa_idxset_remove_by_data(s->core->sources, s, NULL); + pa_idxset_remove_by_data(s->core->sources, s, NULL); + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + + s->notify = NULL; + + s->state = PA_SOURCE_DISCONNECTED; +} + +static void source_free(struct pa_source *s) { + assert(s && !s->ref); + + if (s->state != PA_SOURCE_DISCONNECTED) + pa_source_disconnect(s); + pa_log(__FILE__": freed %u \"%s\"\n", s->index, s->name); - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); - + pa_idxset_free(s->outputs, NULL, NULL); + pa_xfree(s->name); pa_xfree(s->description); pa_xfree(s); } +void pa_source_unref(struct pa_source *s) { + assert(s && s->ref >= 1); + + if (!(--s->ref)) + source_free(s); +} + +struct pa_source* pa_source_ref(struct pa_source *s) { + assert(s && s->ref >= 1); + s->ref++; + return s; +} + void pa_source_notify(struct pa_source*s) { - assert(s); + assert(s && s->ref >= 1); if (s->notify) s->notify(s); @@ -112,9 +139,11 @@ static int do_post(void *p, uint32_t index, int *del, void*userdata) { } void pa_source_post(struct pa_source*s, struct pa_memchunk *chunk) { - assert(s && chunk); + assert(s && s->ref >= 1 && chunk); + pa_source_ref(s); pa_idxset_foreach(s->outputs, do_post, chunk); + pa_source_unref(s); } void pa_source_set_owner(struct pa_source *s, struct pa_module *m) { diff --git a/polyp/source.h b/polyp/source.h index 309b87e72..8b03c0d56 100644 --- a/polyp/source.h +++ b/polyp/source.h @@ -34,7 +34,15 @@ struct pa_source; #define PA_MAX_OUTPUTS_PER_SOURCE 16 +enum pa_source_state { + PA_SOURCE_RUNNING, + PA_SOURCE_DISCONNECTED, +}; + struct pa_source { + int ref; + enum pa_source_state state; + uint32_t index; char *name, *description; @@ -49,7 +57,9 @@ struct pa_source { }; struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec); -void pa_source_free(struct pa_source *s); +void pa_source_disconnect(struct pa_source *s); +void pa_source_unref(struct pa_source *s); +struct pa_source* pa_source_ref(struct pa_source *c); /* Pass a new memory block to all output streams */ void pa_source_post(struct pa_source*s, struct pa_memchunk *b); From 935826f4f318a89a0a570f766deb54808a4f9683 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Sep 2004 23:08:39 +0000 Subject: [PATCH 0197/1514] make module-combine autoloadable clean up cli language introduce lazy sample cache git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@201 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 -- polyp/autoload.c | 83 +++++++++++++++++++++++++++++-------- polyp/autoload.h | 7 +++- polyp/cli-command.c | 91 ++++++++++++++++++++++------------------- polyp/cli-text.c | 21 +++++++--- polyp/cmdline.c | 11 ++++- polyp/conf.c | 7 ++-- polyp/conf.h | 1 + polyp/core.c | 12 +++--- polyp/core.h | 8 ++-- polyp/default.pa | 46 ++++++++++----------- polyp/main.c | 6 ++- polyp/module-combine.c | 11 ++++- polyp/module.c | 26 ++++++------ polyp/protocol-esound.c | 4 +- polyp/protocol-native.c | 7 ++-- polyp/scache.c | 64 +++++++++++++++++++++++++++-- polyp/scache.h | 7 +++- 18 files changed, 282 insertions(+), 133 deletions(-) diff --git a/doc/todo b/doc/todo index 8daabc33d..fedfa545d 100644 --- a/doc/todo +++ b/doc/todo @@ -2,7 +2,6 @@ *** 0.5 *** - make mcalign merge chunks -- use ref counting in more objects (i.e. sink, source, sink_input, source_output) - native library/protocol: module load/unload kill client/... @@ -10,13 +9,11 @@ rename streams/contexts - more complete pactl - option to use default fragment size on alsa drivers -- lazy sample cache - merge pa_context_connect_* - input latency - fix tcp/native - add volume to create_stream command in native protocol - udp based protocol -- make sure not to allow recursive auto load *** 0.6 **** - per-channel volume diff --git a/polyp/autoload.c b/polyp/autoload.c index 988b0921e..8eb5bbf53 100644 --- a/polyp/autoload.c +++ b/polyp/autoload.c @@ -30,36 +30,64 @@ #include "autoload.h" #include "module.h" #include "xmalloc.h" +#include "memchunk.h" +#include "sound-file.h" +#include "log.h" +#include "scache.h" static void entry_free(struct pa_autoload_entry *e) { assert(e); pa_xfree(e->name); pa_xfree(e->module); pa_xfree(e->argument); + pa_xfree(e->filename); pa_xfree(e); } -void pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument) { +static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) { + struct pa_autoload_entry *e = NULL; + assert(c && name); + + if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name))) + return NULL; + + e = pa_xmalloc(sizeof(struct pa_autoload_entry)); + e->name = pa_xstrdup(name); + e->module = e->argument = e->filename = NULL; + e->in_action = 0; + + if (!c->autoload_hashmap) + c->autoload_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + assert(c->autoload_hashmap); + + pa_hashmap_put(c->autoload_hashmap, e->name, e); + + return e; +} + +int pa_autoload_add_module(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument) { struct pa_autoload_entry *e = NULL; assert(c && name && module); - - if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name))) { - pa_xfree(e->module); - pa_xfree(e->argument); - } else { - e = pa_xmalloc(sizeof(struct pa_autoload_entry)); - e->name = pa_xstrdup(name); - - if (!c->autoload_hashmap) - c->autoload_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - assert(c->autoload_hashmap); - - pa_hashmap_put(c->autoload_hashmap, e->name, e); - } + if (!(e = entry_new(c, name))) + return -1; + e->module = pa_xstrdup(module); e->argument = pa_xstrdup(argument); e->type = type; + return 0; +} + +int pa_autoload_add_sample(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*filename) { + struct pa_autoload_entry *e = NULL; + assert(c && name && filename); + + if (!(e = entry_new(c, name))) + return -1; + + e->filename = pa_xstrdup(filename); + e->type = PA_NAMEREG_SAMPLE; + return 0; } int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type) { @@ -82,8 +110,29 @@ void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_ty if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || (e->type != type)) return; - if ((m = pa_module_load(c, e->module, e->argument))) - m->auto_unload = 1; + if (e->in_action) + return; + + e->in_action = 1; + + if (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE) { + if ((m = pa_module_load(c, e->module, e->argument))) + m->auto_unload = 1; + + } else { + struct pa_sample_spec ss; + struct pa_memchunk chunk; + assert(type == PA_NAMEREG_SAMPLE); + + if (pa_sound_file_load(e->filename, &ss, &chunk, c->memblock_stat) < 0) + pa_log(__FILE__": failed to load sound file '%s' for autoload entry '%s'.\n", e->filename, e->name); + else { + pa_scache_add_item(c, e->name, &ss, &chunk, NULL, 1); + pa_memblock_unref(chunk.memblock); + } + } + + e->in_action = 0; } static void free_func(void *p, void *userdata) { diff --git a/polyp/autoload.h b/polyp/autoload.h index 004dae266..3d3101b93 100644 --- a/polyp/autoload.h +++ b/polyp/autoload.h @@ -27,10 +27,13 @@ struct pa_autoload_entry { char *name; enum pa_namereg_type type; - char *module, *argument; + int in_action; + char *module, *argument; /* for module autoloading */ + char *filename; /* for sample autoloading */ }; -void pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument); +int pa_autoload_add_module(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument); +int pa_autoload_add_sample(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*filename); void pa_autoload_free(struct pa_core *c); int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type); void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type); diff --git a/polyp/cli-command.c b/polyp/cli-command.c index b44fbf4aa..574af9db9 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -87,35 +87,37 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct static const struct command commands[] = { { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, { "help", pa_cli_command_help, "Show this help", 1 }, - { "modules", pa_cli_command_modules, "List loaded modules", 1 }, - { "sinks", pa_cli_command_sinks, "List loaded sinks", 1 }, - { "sources", pa_cli_command_sources, "List loaded sources", 1 }, - { "clients", pa_cli_command_clients, "List loaded clients", 1 }, - { "sink_inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 }, - { "source_outputs", pa_cli_command_source_outputs, "List source outputs", 1 }, + { "list-modules", pa_cli_command_modules, "List loaded modules", 1 }, + { "list-sinks", pa_cli_command_sinks, "List loaded sinks", 1 }, + { "list-sources", pa_cli_command_sources, "List loaded sources", 1 }, + { "list-clients", pa_cli_command_clients, "List loaded clients", 1 }, + { "list-sink-inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 }, + { "list-source-outputs", pa_cli_command_source_outputs, "List source outputs", 1 }, { "stat", pa_cli_command_stat, "Show memory block statistics", 1 }, { "info", pa_cli_command_info, "Show comprehensive status", 1 }, { "ls", pa_cli_command_info, NULL, 1 }, { "list", pa_cli_command_info, NULL, 1 }, - { "load", pa_cli_command_load, "Load a module (args: name, arguments)", 3}, - { "unload", pa_cli_command_unload, "Unload a module (args: index)", 2}, - { "sink_volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3}, - { "sink_input_volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index|name, volume)", 3}, - { "sink_default", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2}, - { "source_default", pa_cli_command_source_default, "Set the default source (args: index|name)", 2}, - { "kill_client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, - { "kill_sink_input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2}, - { "kill_source_output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2}, - { "scache_list", pa_cli_command_scache_list, "List all entries in the sample cache", 1}, - { "scache_play", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3}, - { "scache_remove", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2}, - { "scache_load", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: filename,name)", 3}, - { "play_file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3}, - { "autoload_list", pa_cli_command_autoload_list, "List autoload entries", 1}, - { "autoload_sink_add", pa_cli_command_autoload_add, "Add autoload entry for a sink (args: sink, name, arguments)", 4}, - { "autoload_source_add", pa_cli_command_autoload_add, "Add autoload entry for a source (args: source, name, arguments)", 4}, - { "autoload_sink_remove", pa_cli_command_autoload_remove, "Remove autoload entry for a sink (args: sink)", 2}, - { "autoload_source_remove", pa_cli_command_autoload_remove, "Remove autoload entry for a source (args: source)", 2}, + { "load-module", pa_cli_command_load, "Load a module (args: name, arguments)", 3}, + { "unload-module", pa_cli_command_unload, "Unload a module (args: index)", 2}, + { "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3}, + { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index|name, volume)", 3}, + { "set-default-sink", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2}, + { "set-default-source", pa_cli_command_source_default, "Set the default source (args: index|name)", 2}, + { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, + { "kill-sink-input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2}, + { "kill-source-output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2}, + { "list-samples", pa_cli_command_scache_list, "List all entries in the sample cache", 1}, + { "play-sample", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3}, + { "remove-sample", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2}, + { "load-sample", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: name, filename)", 3}, + { "play-file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3}, + { "list-autoload", pa_cli_command_autoload_list, "List autoload entries", 1}, + { "add-autoload-sink", pa_cli_command_autoload_add, "Add autoload entry for a sink (args: sink, module name, arguments)", 4}, + { "add-autoload-source", pa_cli_command_autoload_add, "Add autoload entry for a source (args: source, module name, arguments)", 4}, + { "add-autoload-sample", pa_cli_command_autoload_add, "Add autoload entry for a smple (args: name, filename)", 3}, + { "remove-autoload-sink", pa_cli_command_autoload_remove, "Remove autoload entry for a sink (args: name)", 2}, + { "remove-autoload-source", pa_cli_command_autoload_remove, "Remove autoload entry for a source (args: name)", 2}, + { "remove-autoload-sample", pa_cli_command_autoload_remove, "Remove autoload entry for a sample (args: name)", 2}, { "dump", pa_cli_command_dump, "Dump daemon configuration", 1}, { NULL, NULL, NULL, 0 } }; @@ -147,7 +149,7 @@ static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct for (command = commands; command->name; command++) if (command->help) - pa_strbuf_printf(buf, " %-20s %s\n", command->name, command->help); + pa_strbuf_printf(buf, " %-25s %s\n", command->name, command->help); return 0; } @@ -524,7 +526,7 @@ static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_sample_spec ss; assert(c && t && buf && fail && verbose); - if (!(fname = pa_tokenizer_get(t, 1)) || !(n = pa_tokenizer_get(t, 2))) { + if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n"); return -1; } @@ -534,7 +536,7 @@ static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, return -1; } - pa_scache_add_item(c, n, &ss, &chunk, NULL); + pa_scache_add_item(c, n, &ss, &chunk, NULL, 0); pa_memblock_unref(chunk.memblock); return 0; } @@ -559,28 +561,33 @@ static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, s } static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { - const char *devname, *module; + const char *a, *b; assert(c && t && buf && fail && verbose); - if (!(devname = pa_tokenizer_get(t, 1)) || !(module = pa_tokenizer_get(t, 2))) { - pa_strbuf_puts(buf, "You need to specify a device name, a module name and optionally module arguments\n"); + if (!(a = pa_tokenizer_get(t, 1)) || !(b = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a device name, a filename or a module name and optionally module arguments\n"); return -1; } + + if (strstr(pa_tokenizer_get(t, 0), "sample")) + pa_autoload_add_sample(c, a, PA_NAMEREG_SAMPLE, b); + else + pa_autoload_add_module(c, a, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, b, pa_tokenizer_get(t, 3)); - pa_autoload_add(c, devname, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, pa_tokenizer_get(t, 3)); return 0; } static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { - const char *devname; + const char *name; assert(c && t && buf && fail && verbose); - - if (!(devname = pa_tokenizer_get(t, 1))) { + + if (!(name = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a device name\n"); return -1; } - if (pa_autoload_remove(c, devname, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) < 0) { + if (pa_autoload_remove(c, name, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : + (strstr(pa_tokenizer_get(t, 0), "source") ? PA_NAMEREG_SOURCE : PA_NAMEREG_SAMPLE)) < 0) { pa_strbuf_puts(buf, "Failed to remove autload entry\n"); return -1; } @@ -620,7 +627,7 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct if (m->auto_unload) continue; - pa_strbuf_printf(buf, "load %s", m->name); + pa_strbuf_printf(buf, "load-module %s", m->name); if (m->argument) pa_strbuf_printf(buf, " %s", m->argument); @@ -642,7 +649,7 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct nl = 1; } - pa_strbuf_printf(buf, "sink_volume %s 0x%03x\n", s->name, s->volume); + pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", s->name, s->volume); } @@ -651,13 +658,13 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct i = NULL; while ((a = pa_hashmap_iterate(c->autoload_hashmap, &i))) { - + if (!nl) { pa_strbuf_puts(buf, "\n"); nl = 1; } - pa_strbuf_printf(buf, "autoload_%s_add %s %s", a->type == PA_NAMEREG_SINK ? "sink" : "source", a->name, a->module); + pa_strbuf_printf(buf, "add-autoload-%s %s %s", a->type == PA_NAMEREG_SINK ? "sink" : (a->type == PA_NAMEREG_SOURCE ? "source" : "sample"), a->name, a->type == PA_NAMEREG_SAMPLE ? a->filename : a->module); if (a->argument) pa_strbuf_printf(buf, " %s", a->argument); @@ -673,7 +680,7 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf_puts(buf, "\n"); nl = 1; } - pa_strbuf_printf(buf, "sink_default %s\n", p); + pa_strbuf_printf(buf, "set-default-sink %s\n", p); } if ((p = pa_namereg_get_default_source_name(c))) { @@ -681,7 +688,7 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf_puts(buf, "\n"); nl = 1; } - pa_strbuf_printf(buf, "source_default %s\n", p); + pa_strbuf_printf(buf, "set-default-source %s\n", p); } pa_strbuf_puts(buf, "\n### EOF\n"); diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 2a48d5763..dbc14fda6 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -228,13 +228,14 @@ char *pa_scache_list_to_string(struct pa_core *c) { l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec); pa_strbuf_printf( - s, " name: <%s>\n\tindex: <%i>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n", + s, " name: <%s>\n\tindex: <%i>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n\tauto unload: %s\n", e->name, e->index, ss, e->memchunk.length, l, - e->volume); + e->volume, + e->auto_unload ? "yes" : "no"); } } @@ -256,11 +257,19 @@ char *pa_autoload_list_to_string(struct pa_core *c) { while ((e = pa_hashmap_iterate(c->autoload_hashmap, &state))) { pa_strbuf_printf( - s, " name: <%s>\n\ttype: <%s>\n\tmodule_name: <%s>\n\targuments: <%s>\n", + s, " name: <%s>\n\ttype: <%s>\n", e->name, - e->type == PA_NAMEREG_SOURCE ? "source" : "sink", - e->module, - e->argument); + e->type == PA_NAMEREG_SOURCE ? "source" : (e->type == PA_NAMEREG_SINK ? "sink" : "sample")); + + if (e->type != PA_NAMEREG_SAMPLE) + pa_strbuf_printf( + s, "\tmodule_name: <%s>\n\targuments: <%s>\n", + e->module, + e->argument); + else + pa_strbuf_printf( + s, "\tfilename: <%s>\n", + e->filename); } } diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 47685ca9c..d429256f7 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -47,6 +47,7 @@ enum { ARG_DISALLOW_MODULE_LOADING, ARG_EXIT_IDLE_TIME, ARG_MODULE_IDLE_TIME, + ARG_SCACHE_IDLE_TIME, ARG_LOG_TARGET, ARG_LOAD, ARG_FILE, @@ -65,6 +66,7 @@ static struct option long_options[] = { {"disallow-module-loading", 2, 0, ARG_DISALLOW_MODULE_LOADING}, {"exit-idle-time", 2, 0, ARG_EXIT_IDLE_TIME}, {"module-idle-time", 2, 0, ARG_MODULE_IDLE_TIME}, + {"scache-idle-time", 2, 0, ARG_SCACHE_IDLE_TIME}, {"log-target", 1, 0, ARG_LOG_TARGET}, {"load", 1, 0, ARG_LOAD}, {"file", 1, 0, ARG_FILE}, @@ -94,6 +96,7 @@ void pa_cmdline_help(const char *argv0) { " --disallow-module-loading[=BOOL] Disallow module loading after startup\n" " --exit-idle-time=SECS Terminate the daemon when idle and this time passed\n" " --module-idle-time=SECS Unload autoloaded modules when idle and this time passed\n" + " --scache-idle-time=SECS Unload autoloaded samples when idle and this time passed\n" " --log-target={auto,syslog,stderr} Specify the log target\n" " -p, --dl-search-path=PATH Set the search path for dynamic shared objects (plugins)\n\n" @@ -135,7 +138,7 @@ int pa_cmdline_parse(struct pa_conf *conf, int argc, char *const argv [], int *d case ARG_LOAD: case 'L': - pa_strbuf_printf(buf, "load %s\n", optarg); + pa_strbuf_printf(buf, "load-module %s\n", optarg); break; case ARG_FILE: @@ -144,7 +147,7 @@ int pa_cmdline_parse(struct pa_conf *conf, int argc, char *const argv [], int *d break; case 'C': - pa_strbuf_puts(buf, "load module-cli\n"); + pa_strbuf_puts(buf, "load-module module-cli\n"); break; case ARG_DAEMONIZE: @@ -216,6 +219,10 @@ int pa_cmdline_parse(struct pa_conf *conf, int argc, char *const argv [], int *d case ARG_MODULE_IDLE_TIME: conf->module_idle_time = atoi(optarg); break; + + case ARG_SCACHE_IDLE_TIME: + conf->scache_idle_time = atoi(optarg); + break; default: goto fail; diff --git a/polyp/conf.c b/polyp/conf.c index 9f1f6ba23..3a894a9b7 100644 --- a/polyp/conf.c +++ b/polyp/conf.c @@ -43,6 +43,7 @@ static const struct pa_conf default_conf = { .disallow_module_loading = 0, .exit_idle_time = -1, .module_idle_time = 20, + .scache_idle_time = 20, .auto_log_target = 1, .script_commands = NULL, .dl_search_path = NULL, @@ -143,6 +144,7 @@ static int next_assignment(struct pa_conf *c, char *lvalue, char *rvalue, unsign PARSE_INTEGER("exit-idle-time", exit_idle_time); PARSE_INTEGER("module-idle-time", module_idle_time); + PARSE_INTEGER("scache-idle-time", scache_idle_time); PARSE_STRING("dl-search-path", dl_search_path); PARSE_STRING("default-script-file", default_script_file); @@ -258,7 +260,7 @@ char *pa_conf_dump(struct pa_conf *c) { char *d; d = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL); - pa_strbuf_printf(s, "### Default configuration file: %s ###\n\n", d); + pa_strbuf_printf(s, "### Default configuration file: %s ###\n", d); pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose); pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize); @@ -267,11 +269,10 @@ char *pa_conf_dump(struct pa_conf *c) { pa_strbuf_printf(s, "disallow-module-loading = %i\n", !!c->disallow_module_loading); pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time); pa_strbuf_printf(s, "module-idle-time = %i\n", c->module_idle_time); + pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time); pa_strbuf_printf(s, "dl-search-path = %s\n", c->dl_search_path ? c->dl_search_path : ""); pa_strbuf_printf(s, "default-script-file = %s\n", c->default_script_file); pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); - - pa_strbuf_printf(s, "\n### EOF ###\n"); pa_xfree(d); diff --git a/polyp/conf.h b/polyp/conf.h index da61be337..dafb3797a 100644 --- a/polyp/conf.h +++ b/polyp/conf.h @@ -41,6 +41,7 @@ struct pa_conf { disallow_module_loading, exit_idle_time, module_idle_time, + scache_idle_time, auto_log_target; char *script_commands, *dl_search_path, *default_script_file; enum pa_log_target log_target; diff --git a/polyp/core.c b/polyp/core.c index 0b0bbb561..80abe9fe8 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -61,8 +61,9 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->default_sample_spec.rate = 44100; c->default_sample_spec.channels = 2; - c->auto_unload_event = NULL; - c->defer_unload_event = NULL; + c->module_auto_unload_event = NULL; + c->module_defer_unload_event = NULL; + c->scache_auto_unload_event = NULL; c->subscription_defer_event = NULL; c->subscription_event_queue = NULL; @@ -76,6 +77,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->exit_idle_time = -1; c->module_idle_time = 20; + c->scache_idle_time = 20; pa_check_for_sigpipe(); @@ -108,11 +110,9 @@ void pa_core_free(struct pa_core *c) { pa_autoload_free(c); pa_subscription_free_all(c); - if (c->quit_event) { + if (c->quit_event) c->mainloop->time_free(c->quit_event); - c->quit_event = NULL; - } - + pa_xfree(c->default_source_name); pa_xfree(c->default_sink_name); diff --git a/polyp/core.h b/polyp/core.h index b4470577d..980888f62 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -38,8 +38,8 @@ struct pa_core { char *default_source_name, *default_sink_name; struct pa_sample_spec default_sample_spec; - struct pa_time_event *auto_unload_event; - struct pa_defer_event *defer_unload_event; + struct pa_time_event *module_auto_unload_event; + struct pa_defer_event *module_defer_unload_event; struct pa_defer_event *subscription_defer_event; struct pa_queue *subscription_event_queue; @@ -48,9 +48,11 @@ struct pa_core { struct pa_memblock_stat *memblock_stat; int disallow_module_loading; - int exit_idle_time, module_idle_time; + int exit_idle_time, module_idle_time, scache_idle_time; struct pa_time_event *quit_event; + + struct pa_time_event *scache_auto_unload_event; }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/polyp/default.pa b/polyp/default.pa index 15434627c..ae1fbfcb3 100755 --- a/polyp/default.pa +++ b/polyp/default.pa @@ -20,43 +20,43 @@ # Load audio drivers statically -#load module-alsa-sink -load module-alsa-source device=plughw:1,0 -load module-oss device="/dev/dsp" sink_name=output source_name=input record=0 -#load module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#load module-pipe-sink +#load-module module-alsa-sink +load-module module-alsa-source device=plughw:1,0 +load-module module-oss device="/dev/dsp" sink_name=output source_name=input record=0 +#load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#load-module module-pipe-sink # Load audio drivers automatically on access -#autoload_sink_add output module-oss device="/dev/dsp" sink_name=output source_name=input -#autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input -#autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#autoload_sink_add output module-alsa-sink sink_name=output -#autoload_source_add input module-alsa-source source_name=input +#add-autoload_sink output module-oss device="/dev/dsp" sink_name=output source_name=input +#add-autoload_source input module-oss device="/dev/dsp" sink_name=output source_name=input +#add-autoload_sink output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#add-autoload_source input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#add-autoload_sink output module-alsa-sink sink_name=output +#add-autoload_source input module-alsa-source source_name=input # Load several protocols -load module-esound-protocol-tcp -#load module-simple-protocol-tcp -load module-native-protocol-unix -#load module-cli-protocol-unix -#load module-esound-protocol-unix +load-module module-esound-protocol-tcp +#load-module module-simple-protocol-tcp +load-module module-native-protocol-unix +#load-module module-cli-protocol-unix +#load-module module-esound-protocol-unix # Load the CLI module -load module-cli +load-module module-cli # Make some devices default -sink_default output -source_default input +set-default-sink output +set-default-source input .nofail # Load something to the sample cache -scache_load /usr/share/sounds/KDE_Notify.wav x11-bell +load-sample /usr/share/sounds/KDE_Notify.wav x11-bell # Load X11 bell module -load module-x11-bell sample=x11-bell sink=output +load-module module-x11-bell sample=x11-bell sink=output -#load module-pipe-source -#load module-pipe-sink +#load-module module-pipe-source +#load-module module-pipe-sink diff --git a/polyp/main.c b/polyp/main.c index 9de69ca61..04bcceef8 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -234,8 +234,10 @@ int main(int argc, char *argv[]) { buf = pa_strbuf_new(); assert(buf); if (conf->default_script_file) - pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail, &conf->verbose); - r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail, &conf->verbose); + r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail, &conf->verbose); + + if (r >= 0) + r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail, &conf->verbose); pa_log(s = pa_strbuf_tostring_free(buf)); pa_xfree(s); diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 28e3b39df..49a6951e2 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -42,7 +42,7 @@ PA_MODULE_DESCRIPTION("Combine multiple sinks to one") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= master= slave=") -#define DEFAULT_SINK_NAME "combine" +#define DEFAULT_SINK_NAME "combined" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define RENDER_SIZE (1024*10) @@ -78,6 +78,13 @@ struct userdata { static void output_free(struct output *o); static void clear_up(struct userdata *u); +static void update_usage(struct userdata *u) { + pa_module_set_used(u->module, + (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0)); +} + + static void adjust_rates(struct userdata *u) { struct output *o; pa_usec_t max = 0; @@ -120,6 +127,8 @@ static void request_memblock(struct userdata *u) { struct output *o; assert(u && u->sink); + update_usage(u); + if (pa_sink_render(u->sink, RENDER_SIZE, &chunk) < 0) return; diff --git a/polyp/module.c b/polyp/module.c index 73f5468cf..3fb42d875 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -43,7 +43,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { struct pa_core *c = userdata; struct timeval ntv; - assert(c && c->mainloop == m && c->auto_unload_event == e); + assert(c && c->mainloop == m && c->module_auto_unload_event == e); pa_module_unload_unused(c); @@ -96,13 +96,13 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char if (!c->modules) c->modules = pa_idxset_new(NULL, NULL); - if (!c->auto_unload_event) { + if (!c->module_auto_unload_event) { struct timeval ntv; gettimeofday(&ntv, NULL); ntv.tv_sec += UNLOAD_POLL_TIME; - c->auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); + c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } - assert(c->auto_unload_event); + assert(c->module_auto_unload_event); assert(c->modules); r = pa_idxset_put(c->modules, m, &m->index); @@ -184,14 +184,14 @@ void pa_module_unload_all(struct pa_core *c) { pa_idxset_free(c->modules, free_callback, NULL); c->modules = NULL; - if (c->auto_unload_event) { - c->mainloop->time_free(c->auto_unload_event); - c->auto_unload_event = NULL; + if (c->module_auto_unload_event) { + c->mainloop->time_free(c->module_auto_unload_event); + c->module_auto_unload_event = NULL; } - if (c->defer_unload_event) { - c->mainloop->defer_free(c->defer_unload_event); - c->defer_unload_event = NULL; + if (c->module_defer_unload_event) { + c->mainloop->defer_free(c->module_defer_unload_event); + c->module_defer_unload_event = NULL; } } @@ -247,10 +247,10 @@ void pa_module_unload_request(struct pa_module *m) { m->unload_requested = 1; - if (!m->core->defer_unload_event) - m->core->defer_unload_event = m->core->mainloop->defer_new(m->core->mainloop, defer_cb, m->core); + if (!m->core->module_defer_unload_event) + m->core->module_defer_unload_event = m->core->mainloop->defer_new(m->core->mainloop, defer_cb, m->core); - m->core->mainloop->defer_enable(m->core->defer_unload_event, 1); + m->core->mainloop->defer_enable(m->core->module_defer_unload_event, 1); } void pa_module_set_used(struct pa_module*m, int used) { diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 8ec48a342..6944a1110 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -590,7 +590,7 @@ static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, con c->state = ESD_CACHING_SAMPLE; - pa_scache_add_item(c->protocol->core, c->scache_name, NULL, NULL, &index); + pa_scache_add_item(c->protocol->core, c->scache_name, NULL, NULL, &index, 0); ok = connection_write(c, sizeof(int)); assert(ok); @@ -748,7 +748,7 @@ static int do_read(struct connection *c) { int *ok; c->scache_memchunk.index = 0; - pa_scache_add_item(c->protocol->core, c->scache_name, &c->scache_sample_spec, &c->scache_memchunk, &index); + pa_scache_add_item(c->protocol->core, c->scache_name, &c->scache_sample_spec, &c->scache_memchunk, &index, 0); pa_memblock_unref(c->scache_memchunk.memblock); c->scache_memchunk.memblock = NULL; diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 29821b6c5..e132d2370 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -921,7 +921,7 @@ static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t comma return; } - pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &index); + pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &index, 0); pa_pstream_send_simple_ack(c->pstream, tag); upload_stream_free(s); } @@ -1514,7 +1514,8 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo assert(io && p); c = pa_xmalloc(sizeof(struct connection)); - c->authorized = p->public; + + c->authorized =!! p->public; c->protocol = p; assert(p->core); c->client = pa_client_new(p->core, "NATIVE", "Client"); @@ -1548,7 +1549,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struct pa_module *m, struct pa_modargs *ma) { struct pa_protocol_native *p; - int public; + int public = 0; assert(c && ma); if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { diff --git a/polyp/scache.c b/polyp/scache.c index 53e8a3fe2..5725e1284 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -37,6 +37,20 @@ #include "subscribe.h" #include "namereg.h" +#define UNLOAD_POLL_TIME 2 + +static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { + struct pa_core *c = userdata; + struct timeval ntv; + assert(c && c->mainloop == m && c->scache_auto_unload_event == e); + + pa_scache_unload_unused(c); + + gettimeofday(&ntv, NULL); + ntv.tv_sec += UNLOAD_POLL_TIME; + m->time_restart(e, &ntv); +} + static void free_entry(struct pa_scache_entry *e) { assert(e); pa_namereg_unregister(e->core, e->name); @@ -47,7 +61,7 @@ static void free_entry(struct pa_scache_entry *e) { pa_xfree(e); } -int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index) { +int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index, int auto_unload) { struct pa_scache_entry *e; int put; assert(c && name); @@ -72,6 +86,8 @@ int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spe } e->volume = PA_VOLUME_NORM; + e->auto_unload = auto_unload; + e->last_used_time = 0; if (ss) e->sample_spec = *ss; @@ -101,6 +117,13 @@ int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spe if (index) *index = e->index; + if (!c->scache_auto_unload_event) { + struct timeval ntv; + gettimeofday(&ntv, NULL); + ntv.tv_sec += UNLOAD_POLL_TIME; + c->scache_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); + } + return 0; } @@ -131,13 +154,16 @@ void pa_scache_free(struct pa_core *c) { pa_idxset_free(c->scache, free_cb, NULL); c->scache = NULL; } + + if (c->scache_auto_unload_event) + c->mainloop->time_free(c->scache_auto_unload_event); } int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume) { struct pa_scache_entry *e; assert(c && name && sink); - if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) + if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) return -1; if (!e->memchunk.memblock) @@ -145,6 +171,9 @@ int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sin if (pa_play_memchunk(sink, name, &e->sample_spec, &e->memchunk, pa_volume_multiply(volume, e->volume)) < 0) return -1; + + if (e->auto_unload) + time(&e->last_used_time); return 0; } @@ -163,7 +192,7 @@ uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { struct pa_scache_entry *e; assert(c && name); - if (!c->scache || !(e = pa_idxset_get_by_data(c->scache, name, NULL))) + if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) return PA_IDXSET_INVALID; return e->index; @@ -180,6 +209,33 @@ uint32_t pa_scache_total_size(struct pa_core *c) { for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) sum += e->memchunk.length; - return sum; } + +static int unload_func(void *p, uint32_t index, int *del, void *userdata) { + struct pa_scache_entry *e = p; + time_t *now = userdata; + assert(e); + + if (!e->auto_unload) + return 0; + + if (e->last_used_time + e->core->scache_idle_time > *now) + return 0; + + free_entry(e); + *del = 1; + return 0; +} + +void pa_scache_unload_unused(struct pa_core *c) { + time_t now; + assert(c); + + if (!c->scache) + return; + + time(&now); + + pa_idxset_foreach(c->scache, unload_func, &now); +} diff --git a/polyp/scache.h b/polyp/scache.h index cfd479b57..e05744096 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -33,9 +33,12 @@ struct pa_scache_entry { uint32_t volume; struct pa_sample_spec sample_spec; struct pa_memchunk memchunk; + + int auto_unload; + time_t last_used_time; }; -int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index); +int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index, int auto_unload); int pa_scache_remove_item(struct pa_core *c, const char *name); int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume); @@ -46,4 +49,6 @@ uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name); uint32_t pa_scache_total_size(struct pa_core *c); +void pa_scache_unload_unused(struct pa_core *c); + #endif From 8c110d904ddf30ce35c9a0c18449436af18a5095 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 15 Sep 2004 13:03:25 +0000 Subject: [PATCH 0198/1514] correct autospawning git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@202 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 3 +- polyp/conf.c | 30 +++++- polyp/core.c | 3 +- polyp/main.c | 14 +-- polyp/pacat.c | 2 +- polyp/pactl.c | 2 +- polyp/polyplib-context.c | 199 ++++++++++++++++++++------------------ polyp/polyplib-context.h | 21 +--- polyp/polyplib-def.h | 19 ++++ polyp/polyplib-internal.h | 2 + polyp/polyplib-simple.c | 2 +- polyp/util.c | 22 ++++- polyp/util.h | 4 +- 13 files changed, 187 insertions(+), 136 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 9c672a3b7..fc3fb18d2 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -25,7 +25,8 @@ modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\" AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\" -AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/config\" +AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/default.conf\" +AM_CFLAGS+=-DAUTOSPAWN_CONFIG_FILE=\"$(polypconfdir)/autospawn.conf\" AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" AM_LDADD=$(PTHREAD_LIBS) -lm diff --git a/polyp/conf.c b/polyp/conf.c index 3a894a9b7..b74a5ede2 100644 --- a/polyp/conf.c +++ b/polyp/conf.c @@ -53,17 +53,23 @@ static const struct pa_conf default_conf = { #define ENV_SCRIPT_FILE "POLYP_SCRIPT" #define ENV_CONFIG_FILE "POLYP_CONFIG" +#define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED" #ifndef DEFAULT_SCRIPT_FILE #define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa" #endif #ifndef DEFAULT_CONFIG_FILE -#define DEFAULT_CONFIG_FILE "/etc/polypaudio/config" +#define DEFAULT_CONFIG_FILE "/etc/polypaudio/default.conf" +#endif + +#ifndef AUTOSPAWN_CONFIG_FILE +#define AUTOSPAWN_CONFIG_FILE "/etc/polypaudio/autospawn.conf" #endif #define DEFAULT_SCRIPT_FILE_LOCAL ".polypaudio.pa" #define DEFAULT_CONFIG_FILE_LOCAL ".polypaudio.conf" +#define AUTOSPAWN_CONFIG_FILE_LOCAL ".polypaudio-autospawn.conf" char* default_file(const char *envvar, const char *global, const char *local) { char *p, *h; @@ -85,10 +91,26 @@ char* default_file(const char *envvar, const char *global, const char *local) { return pa_xstrdup(global); } +char *default_config_file(void) { + char *b; + int autospawned = 0; + + if ((b = getenv(ENV_AUTOSPAWNED))) + autospawned = pa_parse_boolean(b) > 0; + + return default_file(ENV_CONFIG_FILE, + autospawned ? AUTOSPAWN_CONFIG_FILE : DEFAULT_CONFIG_FILE, + autospawned ? AUTOSPAWN_CONFIG_FILE_LOCAL : DEFAULT_CONFIG_FILE_LOCAL); + +} + +char *default_script_file(void) { + return default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_LOCAL); +} struct pa_conf* pa_conf_new(void) { struct pa_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); - c->default_script_file = default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_LOCAL); + c->default_script_file = default_script_file(); return c; } @@ -223,7 +245,7 @@ int pa_conf_load(struct pa_conf *c, const char *filename) { assert(c); if (!filename) - filename = def = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL); + filename = def = default_config_file(); if (!(f = fopen(filename, "r"))) { if (errno != ENOENT) @@ -259,7 +281,7 @@ char *pa_conf_dump(struct pa_conf *c) { struct pa_strbuf *s = pa_strbuf_new(); char *d; - d = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL); + d = default_config_file(); pa_strbuf_printf(s, "### Default configuration file: %s ###\n", d); pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose); diff --git a/polyp/core.c b/polyp/core.c index 80abe9fe8..58035087a 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "core.h" #include "module.h" @@ -79,7 +80,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->module_idle_time = 20; c->scache_idle_time = 20; - pa_check_for_sigpipe(); + pa_check_signal_is_blocked(SIGPIPE); return c; } diff --git a/polyp/main.c b/polyp/main.c index 04bcceef8..e44fc0134 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -58,20 +58,8 @@ static void drop_root(void) { } } -static const char* signal_name(int s) { - switch(s) { - case SIGINT: return "SIGINT"; - case SIGTERM: return "SIGTERM"; - case SIGUSR1: return "SIGUSR1"; - case SIGUSR2: return "SIGUSR2"; - case SIGXCPU: return "SIGXCPU"; - case SIGPIPE: return "SIGPIPE"; - default: return "UNKNOWN SIGNAL"; - } -} - static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { - pa_log(__FILE__": Got signal %s.\n", signal_name(sig)); + pa_log(__FILE__": Got signal %s.\n", pa_strsignal(sig)); switch (sig) { case SIGUSR1: diff --git a/polyp/pacat.c b/polyp/pacat.c index b499f71a0..f4597714d 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -360,7 +360,7 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect_spawn(context, NULL, NULL, NULL); + pa_context_connect(context, NULL, 1, NULL); /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { diff --git a/polyp/pactl.c b/polyp/pactl.c index dfa11b70d..c93fd2355 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -292,7 +292,7 @@ int main(int argc, char *argv[]) { } pa_context_set_state_callback(context, context_state_callback, NULL); - pa_context_connect(context, NULL); + pa_context_connect(context, NULL, 1, NULL); if (pa_mainloop_run(m, &ret) < 0) { fprintf(stderr, "pa_mainloop_run() failed.\n"); diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 63b42eb3e..7fef6b12c 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -85,7 +85,7 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->memblock_stat = pa_memblock_stat_new(); - pa_check_for_sigpipe(); + pa_check_signal_is_blocked(SIGPIPE); return c; } @@ -365,15 +365,116 @@ static struct sockaddr *resolve_server(const char *server, size_t *len) { return sa; } -int pa_context_connect(struct pa_context *c, const char *server) { +static int is_running(void) { + struct stat st; + + if (DEFAULT_SERVER[0] != '/') + return 1; + + if (stat(DEFAULT_SERVER, &st) < 0) + return 0; + + return 1; +} + +static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api *api) { + pid_t pid; + int status, r; + int fds[2] = { -1, -1} ; + struct pa_iochannel *io; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { + pa_log(__FILE__": socketpair() failed: %s\n", strerror(errno)); + pa_context_fail(c, PA_ERROR_INTERNAL); + goto fail; + } + + if (api && api->prefork) + api->prefork(); + + if ((pid = fork()) < 0) { + pa_log(__FILE__": fork() failed: %s\n", strerror(errno)); + pa_context_fail(c, PA_ERROR_INTERNAL); + + if (api && api->postfork) + api->postfork(); + + goto fail; + } else if (!pid) { + char t[128]; + char *p; + /* Child */ + + close(fds[0]); + + if (api && api->atfork) + api->atfork(); + + if (!(p = getenv(ENV_DEFAULT_BINARY))) + p = POLYPAUDIO_BINARY; + + snprintf(t, sizeof(t), "%s=1", ENV_AUTOSPAWNED); + putenv(t); + + snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); + execl(p, p, t, NULL); + + exit(1); + } + + /* Parent */ + + r = waitpid(pid, &status, 0); + + if (api && api->postfork) + api->postfork(); + + if (r < 0) { + pa_log(__FILE__": waitpid() failed: %s\n", strerror(errno)); + pa_context_fail(c, PA_ERROR_INTERNAL); + goto fail; + } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + goto fail; + } + + close(fds[1]); + + io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); + setup_context(c, io); + return 0; + +fail: + if (fds[0] != -1) + close(fds[0]); + if (fds[1] != -1) + close(fds[1]); + + return -1; +} + + + +int pa_context_connect(struct pa_context *c, const char *server, int spawn, const struct pa_spawn_api *api) { int r = -1; assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED); - pa_context_ref(c); - if (!server) - if (!(server = getenv(ENV_DEFAULT_SERVER))) + if (!(server = getenv(ENV_DEFAULT_SERVER))) { + if (spawn && !is_running()) { + char *b; + + if ((b = getenv(ENV_DISABLE_AUTOSPAWN))) + if (pa_parse_boolean(b) > 1) + return -1; + + return context_connect_spawn(c, api); + } + server = DEFAULT_SERVER; + } + + pa_context_ref(c); assert(!c->client); @@ -562,94 +663,6 @@ const char* pa_get_library_version(void) { return PACKAGE_VERSION; } -static int is_running(void) { - struct stat st; - - if (DEFAULT_SERVER[0] != '/') - return 1; - - if (stat(DEFAULT_SERVER, &st) < 0) - return 0; - - return 1; -} - -int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void), void (*prefork)(void), void (*postfork)(void)) { - pid_t pid; - int status, r; - int fds[2] = { -1, -1} ; - struct pa_iochannel *io; - - if (getenv(ENV_DEFAULT_SERVER) || is_running()) - return pa_context_connect(c, NULL); - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - pa_log(__FILE__": socketpair() failed: %s\n", strerror(errno)); - pa_context_fail(c, PA_ERROR_INTERNAL); - goto fail; - } - - if (prefork) - prefork(); - - if ((pid = fork()) < 0) { - pa_log(__FILE__": fork() failed: %s\n", strerror(errno)); - pa_context_fail(c, PA_ERROR_INTERNAL); - - if (postfork) - postfork(); - - goto fail; - } else if (!pid) { - char t[64]; - char *p; - /* Child */ - - close(fds[0]); - - if (atfork) - atfork(); - - if (!(p = getenv(ENV_DEFAULT_BINARY))) - p = POLYPAUDIO_BINARY; - - snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); - execl(p, p, "-r", "-D", "-lsyslog", "-X 5", t, NULL); - - exit(1); - } - - /* Parent */ - - r = waitpid(pid, &status, 0); - - if (postfork) - postfork(); - - if (r < 0) { - pa_log(__FILE__": waitpid() failed: %s\n", strerror(errno)); - pa_context_fail(c, PA_ERROR_INTERNAL); - goto fail; - } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); - goto fail; - } - - close(fds[1]); - - io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); - setup_context(c, io); - return 0; - -fail: - if (fds[0] != -1) - close(fds[0]); - if (fds[1] != -1) - close(fds[1]); - - return -1; -} - struct pa_operation* pa_context_set_default_sink(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata) { struct pa_tagstruct *t; struct pa_operation *o; diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 4b199751b..84e47b64d 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -76,22 +76,11 @@ enum pa_context_state pa_context_get_state(struct pa_context *c); /** Connect the context to the specified server. If server is NULL, connect to the default server. This routine may but will not always return synchronously on error. Use pa_context_set_state_callback() to -be notified when the connection is established */ -int pa_context_connect(struct pa_context *c, const char *server); - -/** Connect the context to a server. If the default server is local - * but not accessible, spawn a new daemon. If atfork is not NULL it is - * run after the fork() in the child process. It may be used to close - * file descriptors or to do any other cleanups. (It is not safe to - * close all file descriptors unconditionally, since a UNIX socket is - * passed to the new process.) if prefork is not NULL it is run just - * before forking in the parent process. Use this to block SIGCHLD - * handling if required. If postfork is not NULL it is run just after - * forking in the parent process. Use this to unblock SIGCHLD if - * required. The function will waitpid() on the daemon's PID, but - * will not block or ignore SIGCHLD signals, since this cannot be done - * in a thread compatible way. \since 0.4 */ -int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void), void (*prefork)(void), void (*postfork)(void)); +be notified when the connection is established. If spawn is non-zero +and no specific server is specified or accessible a new daemon is +spawned. If api is non-NULL, the functions specified in the structure +are used when forking a new child process. */ +int pa_context_connect(struct pa_context *c, const char *server, int spawn, const struct pa_spawn_api *api); /** Terminate the context connection immediately */ void pa_context_disconnect(struct pa_context *c); diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 4a49a1f81..2aa33338d 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -156,6 +156,25 @@ struct pa_latency_info { struct timeval timestamp; /**< The time when this latency info was current */ }; +/** A structure for the spawn api. This may be used to integrate auto + * spawned daemons into your application. For more information see + * pa_context_connect(). When spawning a new child process the + * waitpid() is used on the child's PID. The spawn routine will not + * block or ignore SIGCHLD signals, since this cannot be done in a + * thread compatible way. You might have to do this in + * prefork/postfork. \since 0.4 */ +struct pa_spawn_api { + void (*prefork)(void); /**< Is called just before the fork in the parent process. May be NULL. */ + void (*postfork)(void); /**< Is called immediately after the fork in the parent process. May be NULL.*/ + void (*atfork)(void); /**< Is called immediately after the + * fork in the child process. May be + * NULL. It is not safe to close all + * file descriptors in this function + * unconditionally, since a UNIX socket + * (created using socketpair()) is + * passed to the new process. */ +}; + PA_C_DECL_END #endif diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index de63b1ba4..98fd79247 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -48,6 +48,8 @@ #define ENV_DEFAULT_SOURCE "POLYP_SOURCE" #define ENV_DEFAULT_SERVER "POLYP_SERVER" #define ENV_DEFAULT_BINARY "POLYP_BINARY" +#define ENV_DISABLE_AUTOSPAWN "POLYP_NOAUTOSPAWN" +#define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED" struct pa_context { int ref; diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index 1ac088698..36e6e7572 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -130,7 +130,7 @@ struct pa_simple* pa_simple_new( if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name))) goto fail; - pa_context_connect(p->context, server); + pa_context_connect(p->context, server, 1, NULL); /* Wait until the context is ready */ while (pa_context_get_state(p->context) != PA_CONTEXT_READY) { diff --git a/polyp/util.c b/polyp/util.c index 3ab6d51ac..bb71bbf95 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -115,7 +115,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) { return ret; } -void pa_check_for_sigpipe(void) { +void pa_check_signal_is_blocked(int sig) { struct sigaction sa; sigset_t set; @@ -130,10 +130,10 @@ void pa_check_for_sigpipe(void) { } #endif - if (sigismember(&set, SIGPIPE)) + if (sigismember(&set, sig)) return; - if (sigaction(SIGPIPE, NULL, &sa) < 0) { + if (sigaction(sig, NULL, &sa) < 0) { pa_log(__FILE__": sigaction() failed: %s\n", strerror(errno)); return; } @@ -141,7 +141,7 @@ void pa_check_for_sigpipe(void) { if (sa.sa_handler != SIG_DFL) return; - pa_log(__FILE__": WARNING: SIGPIPE is not trapped. This might cause malfunction!\n"); + pa_log(__FILE__": WARNING: %s is not trapped. This might cause malfunction!\n", pa_strsignal(sig)); } /* The following is based on an example from the GNU libc documentation */ @@ -389,3 +389,17 @@ char *pa_split(const char *c, const char *delimiter, const char**state) { return pa_xstrndup(current, l); } + +const char *pa_strsignal(int sig) { + switch(sig) { + case SIGINT: return "SIGINT"; + case SIGTERM: return "SIGTERM"; + case SIGUSR1: return "SIGUSR1"; + case SIGUSR2: return "SIGUSR2"; + case SIGXCPU: return "SIGXCPU"; + case SIGPIPE: return "SIGPIPE"; + case SIGCHLD: return "SIGCHLD"; + default: return "UNKNOWN SIGNAL"; + } +} + diff --git a/polyp/util.h b/polyp/util.h index eae98e6e6..f5cda2006 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -36,7 +36,7 @@ int pa_make_secure_dir(const char* dir); ssize_t pa_loop_read(int fd, void*data, size_t size); ssize_t pa_loop_write(int fd, const void*data, size_t size); -void pa_check_for_sigpipe(void); +void pa_check_signal_is_blocked(int sig); char *pa_sprintf_malloc(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); char *pa_vsprintf_malloc(const char *format, va_list ap); @@ -61,4 +61,6 @@ int pa_parse_boolean(const char *s); char *pa_split(const char *c, const char*delimiters, const char **state); +const char *pa_strsignal(int sig); + #endif From 9ca72dce0bda4e279ff82a01847ee09a72434b33 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 15 Sep 2004 14:05:28 +0000 Subject: [PATCH 0199/1514] remove auto-load-sample stuff introduce "lazy samples" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@203 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 + polyp/autoload.c | 35 ++-------- polyp/autoload.h | 6 +- polyp/cli-command.c | 29 ++++---- polyp/cli-text.c | 34 ++++----- polyp/module-combine.c | 26 ++++--- polyp/namereg.h | 2 - polyp/protocol-esound.c | 4 +- polyp/protocol-native.c | 2 +- polyp/scache.c | 149 +++++++++++++++++++++++++--------------- polyp/scache.h | 9 ++- 11 files changed, 158 insertions(+), 140 deletions(-) diff --git a/doc/todo b/doc/todo index fedfa545d..91a2f92f0 100644 --- a/doc/todo +++ b/doc/todo @@ -14,6 +14,8 @@ - fix tcp/native - add volume to create_stream command in native protocol - udp based protocol +- add client config file +- beefup sample_info stuff in native protocol *** 0.6 **** - per-channel volume diff --git a/polyp/autoload.c b/polyp/autoload.c index 8eb5bbf53..344d26e29 100644 --- a/polyp/autoload.c +++ b/polyp/autoload.c @@ -40,7 +40,6 @@ static void entry_free(struct pa_autoload_entry *e) { pa_xfree(e->name); pa_xfree(e->module); pa_xfree(e->argument); - pa_xfree(e->filename); pa_xfree(e); } @@ -53,7 +52,7 @@ static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) e = pa_xmalloc(sizeof(struct pa_autoload_entry)); e->name = pa_xstrdup(name); - e->module = e->argument = e->filename = NULL; + e->module = e->argument = NULL; e->in_action = 0; if (!c->autoload_hashmap) @@ -65,10 +64,10 @@ static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) return e; } -int pa_autoload_add_module(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument) { +int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument) { struct pa_autoload_entry *e = NULL; - assert(c && name && module); - + assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); + if (!(e = entry_new(c, name))) return -1; @@ -78,18 +77,6 @@ int pa_autoload_add_module(struct pa_core *c, const char*name, enum pa_namereg_t return 0; } -int pa_autoload_add_sample(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*filename) { - struct pa_autoload_entry *e = NULL; - assert(c && name && filename); - - if (!(e = entry_new(c, name))) - return -1; - - e->filename = pa_xstrdup(filename); - e->type = PA_NAMEREG_SAMPLE; - return 0; -} - int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type) { struct pa_autoload_entry *e; assert(c && name && type); @@ -118,20 +105,8 @@ void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_ty if (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE) { if ((m = pa_module_load(c, e->module, e->argument))) m->auto_unload = 1; - - } else { - struct pa_sample_spec ss; - struct pa_memchunk chunk; - assert(type == PA_NAMEREG_SAMPLE); - - if (pa_sound_file_load(e->filename, &ss, &chunk, c->memblock_stat) < 0) - pa_log(__FILE__": failed to load sound file '%s' for autoload entry '%s'.\n", e->filename, e->name); - else { - pa_scache_add_item(c, e->name, &ss, &chunk, NULL, 1); - pa_memblock_unref(chunk.memblock); - } } - + e->in_action = 0; } diff --git a/polyp/autoload.h b/polyp/autoload.h index 3d3101b93..cdf762390 100644 --- a/polyp/autoload.h +++ b/polyp/autoload.h @@ -28,12 +28,10 @@ struct pa_autoload_entry { char *name; enum pa_namereg_type type; int in_action; - char *module, *argument; /* for module autoloading */ - char *filename; /* for sample autoloading */ + char *module, *argument; }; -int pa_autoload_add_module(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument); -int pa_autoload_add_sample(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*filename); +int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument); void pa_autoload_free(struct pa_core *c); int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type); void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type); diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 574af9db9..750d67ead 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -110,14 +110,13 @@ static const struct command commands[] = { { "play-sample", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3}, { "remove-sample", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2}, { "load-sample", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: name, filename)", 3}, + { "load-sample-lazy", pa_cli_command_scache_load, "Lazy load a sound file into the sample cache (args: name, filename)", 3}, { "play-file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3}, { "list-autoload", pa_cli_command_autoload_list, "List autoload entries", 1}, { "add-autoload-sink", pa_cli_command_autoload_add, "Add autoload entry for a sink (args: sink, module name, arguments)", 4}, { "add-autoload-source", pa_cli_command_autoload_add, "Add autoload entry for a source (args: source, module name, arguments)", 4}, - { "add-autoload-sample", pa_cli_command_autoload_add, "Add autoload entry for a smple (args: name, filename)", 3}, { "remove-autoload-sink", pa_cli_command_autoload_remove, "Remove autoload entry for a sink (args: name)", 2}, { "remove-autoload-source", pa_cli_command_autoload_remove, "Remove autoload entry for a source (args: name)", 2}, - { "remove-autoload-sample", pa_cli_command_autoload_remove, "Remove autoload entry for a sample (args: name)", 2}, { "dump", pa_cli_command_dump, "Dump daemon configuration", 1}, { NULL, NULL, NULL, 0 } }; @@ -522,8 +521,7 @@ static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer * static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { const char *fname, *n; - struct pa_memchunk chunk; - struct pa_sample_spec ss; + int r; assert(c && t && buf && fail && verbose); if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) { @@ -531,13 +529,14 @@ static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, return -1; } - if (pa_sound_file_load(fname, &ss, &chunk, c->memblock_stat) < 0) { - pa_strbuf_puts(buf, "Failed to load sound file.\n"); - return -1; - } + if (strstr(pa_tokenizer_get(t, 0), "lazy")) + r = pa_scache_add_file_lazy(c, n, fname, NULL); + else + r = pa_scache_add_file(c, n, fname, NULL); + + if (r < 0) + pa_strbuf_puts(buf, "Failed to load sound file.\n"); - pa_scache_add_item(c, n, &ss, &chunk, NULL, 0); - pa_memblock_unref(chunk.memblock); return 0; } @@ -569,10 +568,7 @@ static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t return -1; } - if (strstr(pa_tokenizer_get(t, 0), "sample")) - pa_autoload_add_sample(c, a, PA_NAMEREG_SAMPLE, b); - else - pa_autoload_add_module(c, a, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, b, pa_tokenizer_get(t, 3)); + pa_autoload_add(c, a, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, b, pa_tokenizer_get(t, 3)); return 0; } @@ -586,8 +582,7 @@ static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer return -1; } - if (pa_autoload_remove(c, name, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : - (strstr(pa_tokenizer_get(t, 0), "source") ? PA_NAMEREG_SOURCE : PA_NAMEREG_SAMPLE)) < 0) { + if (pa_autoload_remove(c, name, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) < 0) { pa_strbuf_puts(buf, "Failed to remove autload entry\n"); return -1; } @@ -664,7 +659,7 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct nl = 1; } - pa_strbuf_printf(buf, "add-autoload-%s %s %s", a->type == PA_NAMEREG_SINK ? "sink" : (a->type == PA_NAMEREG_SOURCE ? "source" : "sample"), a->name, a->type == PA_NAMEREG_SAMPLE ? a->filename : a->module); + pa_strbuf_printf(buf, "add-autoload-%s %s %s", a->type == PA_NAMEREG_SINK ? "sink" : "source", a->name, a->module); if (a->argument) pa_strbuf_printf(buf, " %s", a->argument); diff --git a/polyp/cli-text.c b/polyp/cli-text.c index dbc14fda6..0915be8b0 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -221,21 +221,24 @@ char *pa_scache_list_to_string(struct pa_core *c) { uint32_t index = PA_IDXSET_INVALID; for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) { - double l; - char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; - pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec); + double l = 0; + char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH] = "n/a"; - l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec); + if (e->memchunk.memblock) { + pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec); + l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec); + } pa_strbuf_printf( - s, " name: <%s>\n\tindex: <%i>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n\tauto unload: %s\n", + s, " name: <%s>\n\tindex: <%i>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n\tlazy: %s\n\tfilename: %s\n", e->name, e->index, ss, - e->memchunk.length, + e->memchunk.memblock ? e->memchunk.length : 0, l, e->volume, - e->auto_unload ? "yes" : "no"); + e->lazy ? "yes" : "no", + e->filename ? e->filename : "n/a"); } } @@ -257,19 +260,12 @@ char *pa_autoload_list_to_string(struct pa_core *c) { while ((e = pa_hashmap_iterate(c->autoload_hashmap, &state))) { pa_strbuf_printf( - s, " name: <%s>\n\ttype: <%s>\n", + s, " name: <%s>\n\ttype: <%s>\n\tmodule_name: <%s>\n\targuments: <%s>\n", e->name, - e->type == PA_NAMEREG_SOURCE ? "source" : (e->type == PA_NAMEREG_SINK ? "sink" : "sample")); - - if (e->type != PA_NAMEREG_SAMPLE) - pa_strbuf_printf( - s, "\tmodule_name: <%s>\n\targuments: <%s>\n", - e->module, - e->argument); - else - pa_strbuf_printf( - s, "\tfilename: <%s>\n", - e->filename); + e->type == PA_NAMEREG_SOURCE ? "source" : "sink", + e->module, + e->argument); + } } diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 49a6951e2..8535e5147 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -40,18 +40,19 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Combine multiple sinks to one") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= master= slave=") +PA_MODULE_USAGE("sink_name= master= slave= adjust_time") #define DEFAULT_SINK_NAME "combined" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define RENDER_SIZE (1024*10) -#define ADJUST_TIME 5 +#define DEFAULT_ADJUST_TIME 20 static const char* const valid_modargs[] = { "sink_name", "master", "slaves", + "adjust_time", NULL }; @@ -71,6 +72,7 @@ struct userdata { unsigned n_outputs; struct output *master; struct pa_time_event *time_event; + uint32_t adjust_time; PA_LLIST_HEAD(struct output, outputs); }; @@ -109,9 +111,9 @@ static void adjust_rates(struct userdata *u) { l = o->sink_latency + pa_sink_input_get_latency(o->sink_input); if (l < max) - r -= (uint32_t) (((((double) max-l))/ADJUST_TIME)*r/ 1000000); + r -= (uint32_t) (((((double) max-l))/u->adjust_time)*r/ 1000000); else if (l > max) - r += (uint32_t) (((((double) l-max))/ADJUST_TIME)*r/ 1000000); + r += (uint32_t) (((((double) l-max))/u->adjust_time)*r/ 1000000); if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) pa_log(__FILE__": [%s] sample rates too different, not adjusting (%u vs. %u).\n", o->sink_input->name, base_rate, r); @@ -146,7 +148,7 @@ static void time_callback(struct pa_mainloop_api*a, struct pa_time_event* e, con adjust_rates(u); gettimeofday(&n, NULL); - n.tv_sec += ADJUST_TIME; + n.tv_sec += u->adjust_time; u->sink->core->mainloop->time_restart(e, &n); } @@ -289,8 +291,14 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->module = m; u->core = c; u->time_event = NULL; + u->adjust_time = DEFAULT_ADJUST_TIME; PA_LLIST_HEAD_INIT(struct output, u->outputs); + if (pa_modargs_get_value_u32(ma, "adjust_time", &u->adjust_time) < 0) { + pa_log(__FILE__": failed to parse adjust_time value\n"); + goto fail; + } + if (!(master_name = pa_modargs_get_value(ma, "master", NULL)) || !(slaves = pa_modargs_get_value(ma, "slaves", NULL))) { pa_log(__FILE__": no master or slave sinks specified\n"); goto fail; @@ -336,9 +344,11 @@ int pa__init(struct pa_core *c, struct pa_module*m) { if (u->n_outputs <= 1) pa_log(__FILE__": WARNING: no slave sinks specified.\n"); - gettimeofday(&tv, NULL); - tv.tv_sec += ADJUST_TIME; - u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u); + if (u->adjust_time > 0) { + gettimeofday(&tv, NULL); + tv.tv_sec += u->adjust_time; + u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u); + } pa_modargs_free(ma); return 0; diff --git a/polyp/namereg.h b/polyp/namereg.h index f1be39588..b383d9edb 100644 --- a/polyp/namereg.h +++ b/polyp/namereg.h @@ -37,9 +37,7 @@ void pa_namereg_unregister(struct pa_core *c, const char *name); void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type, int autoload); void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_type type); - const char *pa_namereg_get_default_sink_name(struct pa_core *c); const char *pa_namereg_get_default_source_name(struct pa_core *c); - #endif diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 6944a1110..8ec48a342 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -590,7 +590,7 @@ static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, con c->state = ESD_CACHING_SAMPLE; - pa_scache_add_item(c->protocol->core, c->scache_name, NULL, NULL, &index, 0); + pa_scache_add_item(c->protocol->core, c->scache_name, NULL, NULL, &index); ok = connection_write(c, sizeof(int)); assert(ok); @@ -748,7 +748,7 @@ static int do_read(struct connection *c) { int *ok; c->scache_memchunk.index = 0; - pa_scache_add_item(c->protocol->core, c->scache_name, &c->scache_sample_spec, &c->scache_memchunk, &index, 0); + pa_scache_add_item(c->protocol->core, c->scache_name, &c->scache_sample_spec, &c->scache_memchunk, &index); pa_memblock_unref(c->scache_memchunk.memblock); c->scache_memchunk.memblock = NULL; diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index e132d2370..55b98fd48 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -921,7 +921,7 @@ static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t comma return; } - pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &index, 0); + pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &index); pa_pstream_send_simple_ack(c->pstream, tag); upload_stream_free(s); } diff --git a/polyp/scache.c b/polyp/scache.c index 5725e1284..026f4b174 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -36,6 +36,7 @@ #include "xmalloc.h" #include "subscribe.h" #include "namereg.h" +#include "sound-file.h" #define UNLOAD_POLL_TIME 2 @@ -56,74 +57,110 @@ static void free_entry(struct pa_scache_entry *e) { pa_namereg_unregister(e->core, e->name); pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_REMOVE, e->index); pa_xfree(e->name); + pa_xfree(e->filename); if (e->memchunk.memblock) pa_memblock_unref(e->memchunk.memblock); pa_xfree(e); } -int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index, int auto_unload) { +static struct pa_scache_entry* scache_add_item(struct pa_core *c, const char *name) { struct pa_scache_entry *e; - int put; assert(c && name); if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) { - put = 0; if (e->memchunk.memblock) pa_memblock_unref(e->memchunk.memblock); - assert(e->core == c); - } else { - put = 1; + pa_xfree(e->filename); + + assert(e->core == c); + + pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); + } else { e = pa_xmalloc(sizeof(struct pa_scache_entry)); if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, 1)) { pa_xfree(e); - return -1; + return NULL; } - + e->name = pa_xstrdup(name); e->core = c; - } - e->volume = PA_VOLUME_NORM; - e->auto_unload = auto_unload; - e->last_used_time = 0; - - if (ss) - e->sample_spec = *ss; - else - memset(&e->sample_spec, 0, sizeof(struct pa_sample_spec)); - - if (chunk) { - e->memchunk = *chunk; - pa_memblock_ref(e->memchunk.memblock); - } else { - e->memchunk.memblock = NULL; - e->memchunk.index = e->memchunk.length = 0; - } - - if (put) { if (!c->scache) { c->scache = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); assert(c->scache); } - + pa_idxset_put(c->scache, e, &e->index); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index); - } else - pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); - + } + + e->volume = PA_VOLUME_NORM; + e->last_used_time = 0; + e->memchunk.memblock = NULL; + e->memchunk.index = e->memchunk.length = 0; + e->filename = NULL; + e->lazy = 0; + e->last_used_time = 0; + + memset(&e->sample_spec, 0, sizeof(struct pa_sample_spec)); + + return e; +} + +int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index) { + struct pa_scache_entry *e; + assert(c && name); + + if (!(e = scache_add_item(c, name))) + return -1; + + if (ss) + e->sample_spec = *ss; + + if (chunk) { + e->memchunk = *chunk; + pa_memblock_ref(e->memchunk.memblock); + } + if (index) *index = e->index; + return 0; +} + +int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename, uint32_t *index) { + struct pa_sample_spec ss; + struct pa_memchunk chunk; + int r; + + if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0) + return -1; + + r = pa_scache_add_item(c, name, &ss, &chunk, index); + pa_memblock_unref(chunk.memblock); + return r; +} + +int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index) { + struct pa_scache_entry *e; + assert(c && name); + + if (!(e = scache_add_item(c, name))) + return -1; + + e->lazy = 1; + e->filename = pa_xstrdup(filename); + if (!c->scache_auto_unload_event) { struct timeval ntv; gettimeofday(&ntv, NULL); ntv.tv_sec += UNLOAD_POLL_TIME; c->scache_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } - + return 0; } @@ -166,13 +203,17 @@ int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sin if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) return -1; + if (e->lazy && !e->memchunk.memblock) + if (pa_sound_file_load(e->filename, &e->sample_spec, &e->memchunk, c->memblock_stat) < 0) + return -1; + if (!e->memchunk.memblock) return -1; if (pa_play_memchunk(sink, name, &e->sample_spec, &e->memchunk, pa_volume_multiply(volume, e->volume)) < 0) return -1; - if (e->auto_unload) + if (e->lazy) time(&e->last_used_time); return 0; @@ -200,42 +241,40 @@ uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { uint32_t pa_scache_total_size(struct pa_core *c) { struct pa_scache_entry *e; - uint32_t index; - uint32_t sum = 0; + uint32_t index, sum = 0; + assert(c); - if (!c->scache) + if (!c->scache || !pa_idxset_ncontents(c->scache)) return 0; for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) - sum += e->memchunk.length; + if (e->memchunk.memblock) + sum += e->memchunk.length; return sum; } -static int unload_func(void *p, uint32_t index, int *del, void *userdata) { - struct pa_scache_entry *e = p; - time_t *now = userdata; - assert(e); - - if (!e->auto_unload) - return 0; - - if (e->last_used_time + e->core->scache_idle_time > *now) - return 0; - - free_entry(e); - *del = 1; - return 0; -} - void pa_scache_unload_unused(struct pa_core *c) { + struct pa_scache_entry *e; time_t now; + uint32_t index; assert(c); - if (!c->scache) + if (!c->scache || !pa_idxset_ncontents(c->scache)) return; time(&now); - pa_idxset_foreach(c->scache, unload_func, &now); + for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) { + + if (!e->lazy || !e->memchunk.memblock) + continue; + + if (e->last_used_time + c->scache_idle_time > now) + continue; + + pa_memblock_unref(e->memchunk.memblock); + e->memchunk.memblock = NULL; + e->memchunk.index = e->memchunk.length = 0; + } } diff --git a/polyp/scache.h b/polyp/scache.h index e05744096..4fb3dc8eb 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -30,15 +30,20 @@ struct pa_scache_entry { struct pa_core *core; uint32_t index; char *name; + uint32_t volume; struct pa_sample_spec sample_spec; struct pa_memchunk memchunk; - int auto_unload; + char *filename; + + int lazy; time_t last_used_time; }; -int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index, int auto_unload); +int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index); +int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename, uint32_t *index); +int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index); int pa_scache_remove_item(struct pa_core *c, const char *name); int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume); From f5d47a293aa32a8273ef02c597cb263527726465 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 15 Sep 2004 19:16:57 +0000 Subject: [PATCH 0200/1514] work around C99/GCC incompatibility native protocol: add "local" field to pa_context add volume paramter to pa_stream_connect_playback add support for renaming streams/clients support lazy samples add functions to kill clients/source inputs/sink outputs add functions for loading/unloading modules add autoload management API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@204 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 16 +- polyp/client.c | 2 +- polyp/client.h | 2 +- polyp/native-common.h | 13 +- polyp/pacat-simple.c | 2 +- polyp/pacat.c | 2 +- polyp/parec-simple.c | 2 +- polyp/polyplib-context.c | 45 +++++- polyp/polyplib-context.h | 6 + polyp/polyplib-def.h | 1 + polyp/polyplib-internal.h | 2 + polyp/polyplib-introspect.c | 197 ++++++++++++++++++++++- polyp/polyplib-introspect.h | 46 +++++- polyp/polyplib-simple.c | 3 +- polyp/polyplib-simple.h | 3 +- polyp/polyplib-stream.c | 32 +++- polyp/polyplib-stream.h | 5 +- polyp/protocol-esound.c | 4 +- polyp/protocol-native.c | 313 +++++++++++++++++++++++++++++++++++- polyp/scache.c | 8 +- polyp/sink-input.c | 2 + polyp/source-output.c | 2 + polyp/strbuf.c | 12 ++ 23 files changed, 680 insertions(+), 40 deletions(-) diff --git a/doc/todo b/doc/todo index 91a2f92f0..22fa44213 100644 --- a/doc/todo +++ b/doc/todo @@ -1,26 +1,20 @@ *** $Id$ *** *** 0.5 *** -- make mcalign merge chunks -- native library/protocol: - module load/unload - kill client/... - autoload management - rename streams/contexts - more complete pactl -- option to use default fragment size on alsa drivers -- merge pa_context_connect_* - input latency - fix tcp/native -- add volume to create_stream command in native protocol -- udp based protocol +- paman: add support for killing sink inputs, source outputs, clients - add client config file -- beefup sample_info stuff in native protocol +- remove autospawn stuff in conf.c *** 0.6 **** - per-channel volume - unix socket directories include user name - add sample directory +- udp based protocol +- make mcalign merge chunks +- option to use default fragment size on alsa drivers ** later *** - xmlrpc/http diff --git a/polyp/client.c b/polyp/client.c index a544b4fe3..7aee2edd2 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -82,7 +82,7 @@ void pa_client_kill(struct pa_client *c) { c->kill(c); } -void pa_client_rename(struct pa_client *c, const char *name) { +void pa_client_set_name(struct pa_client *c, const char *name) { assert(c); pa_xfree(c->name); c->name = pa_xstrdup(name); diff --git a/polyp/client.h b/polyp/client.h index c926208e8..25a4b1660 100644 --- a/polyp/client.h +++ b/polyp/client.h @@ -46,6 +46,6 @@ void pa_client_free(struct pa_client *c); * request destruction of the client */ void pa_client_kill(struct pa_client *c); -void pa_client_rename(struct pa_client *c, const char *name); +void pa_client_set_name(struct pa_client *c, const char *name); #endif diff --git a/polyp/native-common.h b/polyp/native-common.h index c5192cecc..45e0b1d35 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -38,7 +38,7 @@ enum { PA_COMMAND_EXIT, PA_COMMAND_REQUEST, PA_COMMAND_AUTH, - PA_COMMAND_SET_NAME, + PA_COMMAND_SET_CLIENT_NAME, PA_COMMAND_LOOKUP_SINK, PA_COMMAND_LOOKUP_SOURCE, PA_COMMAND_DRAIN_PLAYBACK_STREAM, @@ -75,6 +75,17 @@ enum { PA_COMMAND_TRIGGER_PLAYBACK_STREAM, PA_COMMAND_SET_DEFAULT_SINK, PA_COMMAND_SET_DEFAULT_SOURCE, + PA_COMMAND_SET_PLAYBACK_STREAM_NAME, + PA_COMMAND_SET_RECORD_STREAM_NAME, + PA_COMMAND_KILL_CLIENT, + PA_COMMAND_KILL_SINK_INPUT, + PA_COMMAND_KILL_SOURCE_OUTPUT, + PA_COMMAND_LOAD_MODULE, + PA_COMMAND_UNLOAD_MODULE, + PA_COMMAND_ADD_AUTOLOAD, + PA_COMMAND_REMOVE_AUTOLOAD, + PA_COMMAND_GET_AUTOLOAD_INFO, + PA_COMMAND_GET_AUTOLOAD_INFO_LIST, PA_COMMAND_MAX }; diff --git a/polyp/pacat-simple.c b/polyp/pacat-simple.c index 956728fb7..2b8ffa081 100644 --- a/polyp/pacat-simple.c +++ b/polyp/pacat-simple.c @@ -47,7 +47,7 @@ int main(int argc, char*argv[]) { int error; /* Create a new playback stream */ - if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, &error))) { + if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, PA_VOLUME_NORM, &error))) { fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); goto finish; } diff --git a/polyp/pacat.c b/polyp/pacat.c index f4597714d..cc7d55f40 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -156,7 +156,7 @@ static void context_state_callback(struct pa_context *c, void *userdata) { pa_stream_set_read_callback(stream, stream_read_callback, NULL); if (mode == PLAYBACK) - pa_stream_connect_playback(stream, NULL, NULL); + pa_stream_connect_playback(stream, NULL, NULL, PA_VOLUME_NORM); else pa_stream_connect_record(stream, NULL, NULL); diff --git a/polyp/parec-simple.c b/polyp/parec-simple.c index 7e0931ae0..cae6ff92b 100644 --- a/polyp/parec-simple.c +++ b/polyp/parec-simple.c @@ -66,7 +66,7 @@ int main(int argc, char*argv[]) { int error; /* Create the recording stream */ - if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, &error))) { + if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, 0, &error))) { fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); goto finish; } diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 7fef6b12c..64f9074c7 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -84,6 +84,7 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->subscribe_userdata = NULL; c->memblock_stat = pa_memblock_stat_new(); + c->local = -1; pa_check_signal_is_blocked(SIGPIPE); return c; @@ -252,7 +253,7 @@ static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, u struct pa_tagstruct *t; t = pa_tagstruct_new(NULL, 0); assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME); + pa_tagstruct_putu32(t, PA_COMMAND_SET_CLIENT_NAME); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_puts(t, c->name); pa_pstream_send_tagstruct(c->pstream, t); @@ -383,6 +384,8 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api int fds[2] = { -1, -1} ; struct pa_iochannel *io; + pa_context_ref(c); + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { pa_log(__FILE__": socketpair() failed: %s\n", strerror(errno)); pa_context_fail(c, PA_ERROR_INTERNAL); @@ -417,7 +420,7 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api putenv(t); snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); - execl(p, p, t, NULL); + execl(p, p, "--daemonize=yes", "--log-target=syslog", t, NULL); exit(1); } @@ -439,9 +442,14 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api } close(fds[1]); + + c->local = 1; io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); setup_context(c, io); + + pa_context_unref(c); + return 0; fail: @@ -450,11 +458,11 @@ fail: if (fds[1] != -1) close(fds[1]); + pa_context_unref(c); + return -1; } - - int pa_context_connect(struct pa_context *c, const char *server, int spawn, const struct pa_spawn_api *api) { int r = -1; assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED); @@ -483,6 +491,8 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); goto finish; } + + c->local = 1; } else { struct sockaddr* sa; size_t sa_len; @@ -499,6 +509,8 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); goto finish; } + + c->local = 0; } pa_socket_client_set_callback(c->client, on_connection, c); @@ -702,3 +714,28 @@ struct pa_operation* pa_context_set_default_source(struct pa_context *c, const c return pa_operation_ref(o); } + +int pa_context_is_local(struct pa_context *c) { + assert(c); + return c->local; +} + +struct pa_operation* pa_context_set_name(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && name && cb); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_CLIENT_NAME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); +} diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 84e47b64d..548a39dd6 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -99,6 +99,12 @@ struct pa_operation* pa_context_set_default_sink(struct pa_context *c, const cha /** Set the name of the default source. \since 0.4 */ struct pa_operation* pa_context_set_default_source(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata); +/** Returns 1 when the connection is to a local daemon. Returns negative when no connection has been made yet. \since 0.5 */ +int pa_context_is_local(struct pa_context *c); + +/** Set a different application name for context on the server. \since 0.5 */ +struct pa_operation* pa_context_set_name(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata); + PA_C_DECL_END #endif diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 2aa33338d..9bba3f32d 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -94,6 +94,7 @@ enum { PA_ERROR_CONNECTIONTERMINATED, /**< Connection terminated */ PA_ERROR_KILLED, /**< Entity killed */ PA_ERROR_INVALIDSERVER, /**< Invalid server */ + PA_ERROR_INITFAILED, /**< Module initialization failed */ PA_ERROR_MAX /**< Not really an error but the first invalid error code */ }; diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 98fd79247..4c44ee98d 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -78,6 +78,8 @@ struct pa_context { void *subscribe_userdata; struct pa_memblock_stat *memblock_stat; + + int local; }; struct pa_stream { diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index e742c2db6..919adb9cc 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -650,7 +650,9 @@ static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t c pa_tagstruct_getu32(t, &i.volume) < 0 || pa_tagstruct_get_usec(t, &i.duration) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.bytes) < 0) { + pa_tagstruct_getu32(t, &i.bytes) < 0 || + pa_tagstruct_get_boolean(t, &i.lazy) < 0 || + pa_tagstruct_gets(t, &i.filename) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -717,3 +719,196 @@ struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, u struct pa_operation* pa_context_get_sample_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) { return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, cb, userdata); } + +static struct pa_operation* command_kill(struct pa_context *c, uint32_t command, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + struct pa_operation *o; + struct pa_tagstruct *t; + uint32_t tag; + assert(c && index != PA_INVALID_INDEX); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, command); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_kill_client(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + return command_kill(c, PA_COMMAND_KILL_CLIENT, index, cb, userdata); +} + +struct pa_operation* pa_context_kill_sink_input(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + return command_kill(c, PA_COMMAND_KILL_SINK_INPUT, index, cb, userdata); +} + +struct pa_operation* pa_context_kill_source_output(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + return command_kill(c, PA_COMMAND_KILL_SOURCE_OUTPUT, index, cb, userdata); +} + +static void load_module_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_operation *o = userdata; + uint32_t index = -1; + assert(pd && o && o->context && o->ref >= 1); + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; + + } else if (pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; + } + + if (o->callback) { + void (*cb)(struct pa_context *c, uint32_t index, void *userdata) = o->callback; + cb(o->context, index, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +struct pa_operation* pa_context_load_module(struct pa_context *c, const char*name, const char *argument, void (*cb)(struct pa_context *c, uint32_t index, void *userdata), void *userdata) { + struct pa_operation *o; + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name && argument); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_LOAD_MODULE); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_puts(t, argument); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, load_module_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_unload_module(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { + return command_kill(c, PA_COMMAND_UNLOAD_MODULE, index, cb, userdata); +} + +/*** Autoload stuff ***/ + +static void context_get_autoload_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_operation *o = userdata; + int eof = 1; + assert(pd && o && o->context && o->ref >= 1); + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; + + eof = -1; + } else { + + while (!pa_tagstruct_eof(t)) { + struct pa_autoload_info i; + + if (pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_getu32(t, &i.type) < 0 || + pa_tagstruct_gets(t, &i.module) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_autoload_info*i, int eof, void *userdata) = o->callback; + cb(o->context, &i, 0, o->userdata); + } + } + } + + if (o->callback) { + void (*cb)(struct pa_context *s, const struct pa_autoload_info*i, int eof, void *userdata) = o->callback; + cb(o->context, NULL, eof, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +struct pa_operation* pa_context_get_autoload_info(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb && name); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_AUTOLOAD_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_putu32(t, type); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_get_autoload_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, cb, userdata); +} + +struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) { + struct pa_operation *o; + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name && module && argument); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_ADD_AUTOLOAD); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_putu32(t, type); + pa_tagstruct_puts(t, module); + pa_tagstruct_puts(t, argument); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); +} + +struct pa_operation* pa_context_remove_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) { + struct pa_operation *o; + struct pa_tagstruct *t; + uint32_t tag; + assert(c && name); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_AUTOLOAD); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_puts(t, name); + pa_tagstruct_putu32(t, type); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); +} diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 3da71b807..51210457d 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -38,8 +38,7 @@ * and the structures themselves point to internal memory that may not * be modified. That memory is only valid during the call to the * callback function. A deep copy is required if you need this data - * outside the callback functions. An error is signalled by a call to - * the callback function with i=NULL and is_last=0. + * outside the callback functions. An error is signalled by a call to * the callback function with i=NULL and is_last=0. * * When using the routines that ask fo a single entry only, a callback * with the same signature is used. However, no finishing call to the @@ -196,6 +195,8 @@ struct pa_sample_info { struct pa_sample_spec sample_spec; /**< Sample specification of the sampel */ pa_usec_t duration; /**< Duration of this entry */ uint32_t bytes; /**< Length of this sample in bytes. \since 0.4 */ + int lazy; /**< Non-zero when this is a lazy cache entry. \since 0.5 */ + const char *filename; /**< In case this is a lazy cache entry, the filename for the sound file to be loaded on demand. \since 0.5 */ }; /** Get information about a sample by its name */ @@ -207,6 +208,47 @@ struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, u /** Get the complete list of samples stored in the daemon. */ struct pa_operation* pa_context_get_sample_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata); +/** Kill a client. \since 0.5 */ +struct pa_operation* pa_context_kill_client(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +/** Kill a sink input. \since 0.5 */ +struct pa_operation* pa_context_kill_sink_input(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +/** Kill a source output. \since 0.5 */ +struct pa_operation* pa_context_kill_source_output(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +/** Load a module. \since 0.5 */ +struct pa_operation* pa_context_load_module(struct pa_context *c, const char*name, const char *argument, void (*cb)(struct pa_context *c, uint32_t index, void *userdata), void *userdata); + +/** Unload a module. \since 0.5 */ +struct pa_operation* pa_context_unload_module(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); + +/** Type of an autoload entry. \since 0.5 */ +enum pa_autoload_type { + PA_AUTOLOAD_SINK = 0, + PA_AUTOLOAD_SOURCE = 1, +}; + +/** Stores information about autoload entries. \since 0.5 */ +struct pa_autoload_info { + const char *name; /**< Name of the sink or source */ + enum pa_autoload_type type; /**< Type of the autoload entry */ + const char *module; /**< Module name to load */ + const char *argument; /**< Argument string for module */ +}; + +/** Get info about a specific autoload entry. \since 0.5 */ +struct pa_operation* pa_context_get_autoload_info(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata); + +/** Get the complete list of autoload entries. \since 0.5 */ +struct pa_operation* pa_context_get_autoload_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata); + +/** Add a new autoload entry. \since 0.5 */ +struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata); + +/** Remove an autoload entry. \since 0.5 */ +struct pa_operation* pa_context_remove_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata); + PA_C_DECL_END #endif diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index 36e6e7572..5cf52d062 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -110,6 +110,7 @@ struct pa_simple* pa_simple_new( const char *stream_name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, + pa_volume_t volume, int *perror) { struct pa_simple *p; @@ -142,7 +143,7 @@ struct pa_simple* pa_simple_new( goto fail; if (dir == PA_STREAM_PLAYBACK) - pa_stream_connect_playback(p->stream, dev, attr); + pa_stream_connect_playback(p->stream, dev, attr, volume); else pa_stream_connect_record(p->stream, dev, attr); diff --git a/polyp/polyplib-simple.h b/polyp/polyplib-simple.h index b37bdec60..1bd46dc63 100644 --- a/polyp/polyplib-simple.h +++ b/polyp/polyplib-simple.h @@ -54,7 +54,8 @@ struct pa_simple* pa_simple_new( const char *stream_name, /**< A descriptive name for this client (application name, song title, ...) */ const struct pa_sample_spec *ss, /**< The sample type to use */ const struct pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */ - int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */ + pa_volume_t volume, /**< Initial volume. Only for playback streams. \since 0.5 */ + int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */ ); /** Close and free the connection to the server. The connection objects becomes invalid when this is called. */ diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index b40b7f69c..89a8d3383 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -211,7 +211,7 @@ finish: pa_stream_unref(s); } -static void create_stream(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) { +static void create_stream(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, pa_volume_t volume) { struct pa_tagstruct *t; uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED); @@ -251,6 +251,7 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ pa_tagstruct_putu32(t, s->buffer_attr.tlength); pa_tagstruct_putu32(t, s->buffer_attr.prebuf); pa_tagstruct_putu32(t, s->buffer_attr.minreq); + pa_tagstruct_putu32(t, volume); } else pa_tagstruct_putu32(t, s->buffer_attr.fragsize); @@ -260,16 +261,16 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ pa_stream_unref(s); } -void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) { +void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, pa_volume_t volume) { assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); s->direction = PA_STREAM_PLAYBACK; - create_stream(s, dev, attr); + create_stream(s, dev, attr, volume); } void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) { assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); s->direction = PA_STREAM_RECORD; - create_stream(s, dev, attr); + create_stream(s, dev, attr, 0); } void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void (*free_cb)(void *p), size_t delta) { @@ -536,3 +537,26 @@ struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_s struct pa_operation* pa_stream_trigger(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { return pa_stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata); } + +struct pa_operation* pa_stream_set_name(struct pa_stream *s, const char *name, void(*cb)(struct pa_stream*c, int success, void *userdata), void *userdata) { + struct pa_operation *o; + struct pa_tagstruct *t; + uint32_t tag; + assert(s && s->ref >= 1 && s->state == PA_STREAM_READY && name && s->direction != PA_STREAM_UPLOAD); + + o = pa_operation_new(s->context, s); + assert(o); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME); + pa_tagstruct_putu32(t, tag = s->context->ctag++); + pa_tagstruct_putu32(t, s->channel); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); + + return pa_operation_ref(o); +} diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index d74c3cb21..257f2b996 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -57,7 +57,7 @@ struct pa_context* pa_stream_get_context(struct pa_stream *p); uint32_t pa_stream_get_index(struct pa_stream *s); /** Connect the stream to a sink */ -void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr); +void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, pa_volume_t volume); /** Connect the stream to a source */ void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr); @@ -126,6 +126,9 @@ struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_s * 0.3 */ struct pa_operation* pa_stream_trigger(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); +/** Rename the stream. \since 0.5 */ +struct pa_operation* pa_stream_set_name(struct pa_stream *s, const char *name, void(*cb)(struct pa_stream*c, int success, void *userdata), void *userdata); + PA_C_DECL_END #endif diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 8ec48a342..5abe474d6 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -293,7 +293,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons strncpy(name, (char*) data + sizeof(int)*2, sizeof(name)); name[sizeof(name)-1] = 0; - pa_client_rename(c->client, name); + pa_client_set_name(c->client, name); assert(!c->input_memblockq); @@ -357,7 +357,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co strncpy(name, (char*) data + sizeof(int)*2, sizeof(name)); name[sizeof(name)-1] = 0; - pa_client_rename(c->client, name); + pa_client_set_name(c->client, name); assert(!c->output_memblockq); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 55b98fd48..be7b76f6f 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -45,6 +45,7 @@ #include "util.h" #include "subscribe.h" #include "log.h" +#include "autoload.h" struct connection; struct pa_protocol_native; @@ -123,7 +124,7 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_delete_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_set_client_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); @@ -139,6 +140,14 @@ static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32 static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_set_stream_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_kill(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_load_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_unload_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_get_autoload_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -152,7 +161,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_AUTH] = { command_auth }, [PA_COMMAND_REQUEST] = { NULL }, [PA_COMMAND_EXIT] = { command_exit }, - [PA_COMMAND_SET_NAME] = { command_set_name }, + [PA_COMMAND_SET_CLIENT_NAME] = { command_set_client_name }, [PA_COMMAND_LOOKUP_SINK] = { command_lookup }, [PA_COMMAND_LOOKUP_SOURCE] = { command_lookup }, [PA_COMMAND_STAT] = { command_stat }, @@ -185,6 +194,17 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, [PA_COMMAND_SET_DEFAULT_SINK] = { command_set_default_sink_or_source }, [PA_COMMAND_SET_DEFAULT_SOURCE] = { command_set_default_sink_or_source }, + [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = { command_set_stream_name }, + [PA_COMMAND_SET_RECORD_STREAM_NAME] = { command_set_stream_name }, + [PA_COMMAND_KILL_CLIENT] = { command_kill }, + [PA_COMMAND_KILL_SINK_INPUT] = { command_kill }, + [PA_COMMAND_KILL_SOURCE_OUTPUT] = { command_kill }, + [PA_COMMAND_LOAD_MODULE] = { command_load_module }, + [PA_COMMAND_UNLOAD_MODULE] = { command_unload_module }, + [PA_COMMAND_GET_AUTOLOAD_INFO] = { command_get_autoload_info }, + [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = { command_get_autoload_info_list }, + [PA_COMMAND_ADD_AUTOLOAD] = { command_add_autoload }, + [PA_COMMAND_REMOVE_AUTOLOAD] = { command_remove_autoload }, }; /* structure management */ @@ -265,7 +285,8 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct size_t maxlength, size_t tlength, size_t prebuf, - size_t minreq) { + size_t minreq, + pa_volume_t volume) { struct playback_stream *s; struct pa_sink_input *sink_input; assert(c && sink && ss && name && maxlength); @@ -291,6 +312,8 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct s->requested_bytes = 0; s->drain_request = 0; + + s->sink_input->volume = volume; pa_idxset_put(c->output_streams, s, &s->index); return s; @@ -501,6 +524,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com struct pa_sample_spec ss; struct pa_tagstruct *reply; struct pa_sink *sink; + pa_volume_t volume; assert(c && t && c->protocol && c->protocol->core); if (pa_tagstruct_gets(t, &name) < 0 || @@ -511,6 +535,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com pa_tagstruct_getu32(t, &tlength) < 0 || pa_tagstruct_getu32(t, &prebuf) < 0 || pa_tagstruct_getu32(t, &minreq) < 0 || + pa_tagstruct_getu32(t, &volume) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -531,7 +556,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com return; } - if (!(s = playback_stream_new(c, sink, &ss, name, maxlength, tlength, prebuf, minreq))) { + if (!(s = playback_stream_new(c, sink, &ss, name, maxlength, tlength, prebuf, minreq, volume))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); return; } @@ -691,7 +716,7 @@ static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag return; } -static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_set_client_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const char *name; assert(c && t); @@ -702,7 +727,7 @@ static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t return; } - pa_client_rename(c->client, name); + pa_client_set_name(c->client, name); pa_pstream_send_simple_ack(c->pstream, tag); return; } @@ -1061,6 +1086,8 @@ static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec)); pa_tagstruct_put_sample_spec(t, &e->sample_spec); pa_tagstruct_putu32(t, e->memchunk.length); + pa_tagstruct_put_boolean(t, e->lazy); + pa_tagstruct_puts(t, e->filename); } static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { @@ -1415,6 +1442,280 @@ static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t pa_pstream_send_simple_ack(c->pstream, tag); } +static void command_set_stream_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + const char *name; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) { + struct playback_stream *s; + + if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_sink_input_set_name(s->sink_input, name); + + } else { + struct record_stream *s; + + if (!(s = pa_idxset_get_by_index(c->record_streams, index))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_source_output_set_name(s->source_output, name); + } + + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void command_kill(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (command == PA_COMMAND_KILL_CLIENT) { + struct pa_client *client; + + if (!(client = pa_idxset_get_by_index(c->protocol->core->clients, index))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_client_kill(client); + } else if (command == PA_COMMAND_KILL_SINK_INPUT) { + struct pa_sink_input *s; + + if (!(s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_sink_input_kill(s); + } else { + struct pa_source_output *s; + + assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT); + + if (!(s = pa_idxset_get_by_index(c->protocol->core->source_outputs, index))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_source_output_kill(s); + } + + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void command_load_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + struct pa_module *m; + const char *name, *argument; + struct pa_tagstruct *reply; + assert(c && t); + + if (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_gets(t, &argument) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(m = pa_module_load(c->protocol->core, name, argument))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_INITFAILED); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + pa_tagstruct_putu32(reply, m->index); + pa_pstream_send_tagstruct(c->pstream, reply); +} + +static void command_unload_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + struct pa_module *m; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(m = pa_idxset_get_by_index(c->protocol->core->modules, index))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_module_unload_request(m); + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + const char *name, *module, *argument; + uint32_t type; + assert(c && t); + + if (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_getu32(t, &type) < 0 || type > 1 || + pa_tagstruct_gets(t, &module) < 0 || + pa_tagstruct_gets(t, &argument) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + return; + } + + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + const char *name; + uint32_t type; + assert(c && t); + + if (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_getu32(t, &type) < 0 || type > 1 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (pa_autoload_remove(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void autoload_fill_tagstruct(struct pa_tagstruct *t, struct pa_autoload_entry *e) { + assert(t && e); + pa_tagstruct_puts(t, e->name); + pa_tagstruct_putu32(t, e->type == PA_NAMEREG_SINK ? 0 : 1); + pa_tagstruct_puts(t, e->module); + pa_tagstruct_puts(t, e->argument); +} + +static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + struct pa_autoload_entry *a = NULL; + uint32_t type; + const char *name; + struct pa_tagstruct *reply; + assert(c && t); + + if (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_getu32(t, &type) < 0 || type > 1 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!c->protocol->core->autoload_hashmap || !(a = pa_hashmap_get(c->protocol->core->autoload_hashmap, name)) || (a->type == PA_NAMEREG_SINK && type != 0) || (a->type == PA_NAMEREG_SOURCE && type != 1)) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + autoload_fill_tagstruct(reply, a); + pa_pstream_send_tagstruct(c->pstream, reply); +} + +static void command_get_autoload_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + struct pa_tagstruct *reply; + assert(c && t); + + if (!pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + + if (c->protocol->core->autoload_hashmap) { + struct pa_autoload_entry *a; + void *state = NULL; + + while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state))) + autoload_fill_tagstruct(reply, a); + } + + pa_pstream_send_tagstruct(c->pstream, reply); +} + /*** pstream callbacks ***/ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { diff --git a/polyp/scache.c b/polyp/scache.c index 026f4b174..963a4f863 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -141,6 +141,7 @@ int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename r = pa_scache_add_item(c, name, &ss, &chunk, index); pa_memblock_unref(chunk.memblock); + return r; } @@ -203,9 +204,12 @@ int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sin if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) return -1; - if (e->lazy && !e->memchunk.memblock) + if (e->lazy && !e->memchunk.memblock) { if (pa_sound_file_load(e->filename, &e->sample_spec, &e->memchunk, c->memblock_stat) < 0) return -1; + + pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); + } if (!e->memchunk.memblock) return -1; @@ -276,5 +280,7 @@ void pa_scache_unload_unused(struct pa_core *c) { pa_memblock_unref(e->memchunk.memblock); e->memchunk.memblock = NULL; e->memchunk.index = e->memchunk.length = 0; + + pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); } } diff --git a/polyp/sink-input.c b/polyp/sink-input.c index e2b9e0cf5..2541c8217 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -258,4 +258,6 @@ void pa_sink_input_set_name(struct pa_sink_input *i, const char *name) { pa_xfree(i->name); i->name = pa_xstrdup(name); + + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); } diff --git a/polyp/source-output.c b/polyp/source-output.c index 3abf9c187..2566ec875 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -146,4 +146,6 @@ void pa_source_output_set_name(struct pa_source_output *o, const char *name) { assert(o && o->ref >= 1); pa_xfree(o->name); o->name = pa_xstrdup(name); + + pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); } diff --git a/polyp/strbuf.c b/polyp/strbuf.c index 169604e82..44cae2ce8 100644 --- a/polyp/strbuf.c +++ b/polyp/strbuf.c @@ -33,10 +33,22 @@ #include "strbuf.h" +#ifdef __STDC_VERSION__ +#if __STDC_VERSION__ >= 199901L +#ifndef STDC99 +#define STDC99 +#endif +#endif +#endif + struct chunk { struct chunk *next; size_t length; +#ifdef STDC99 char text[]; +#else + char text[0]; +#endif }; struct pa_strbuf { From f9e2058820c2a51994708ad11d1ed8e09b12b8b1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Sep 2004 00:05:56 +0000 Subject: [PATCH 0201/1514] add input latency measurement add GETOSPACE support to module-oss git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@205 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 4 +- polyp/cli-text.c | 3 +- polyp/iochannel.c | 11 +++ polyp/iochannel.h | 3 + polyp/module-alsa-source.c | 15 ++++ polyp/module-oss.c | 143 ++++++++++++++++++++++++++---------- polyp/native-common.h | 1 + polyp/pacat.c | 18 +++-- polyp/polyplib-def.h | 28 ++++--- polyp/polyplib-introspect.c | 8 +- polyp/polyplib-introspect.h | 5 +- polyp/polyplib-stream.c | 11 ++- polyp/protocol-esound.c | 9 ++- polyp/protocol-native.c | 62 +++++++++++++++- polyp/protocol-simple.c | 7 ++ polyp/sink.c | 5 +- polyp/source-output.c | 11 +++ polyp/source-output.h | 4 + polyp/source.c | 11 +++ polyp/source.h | 3 + 20 files changed, 293 insertions(+), 69 deletions(-) diff --git a/doc/todo b/doc/todo index 22fa44213..675e8ca38 100644 --- a/doc/todo +++ b/doc/todo @@ -2,7 +2,6 @@ *** 0.5 *** - more complete pactl -- input latency - fix tcp/native - paman: add support for killing sink inputs, source outputs, clients - add client config file @@ -15,6 +14,7 @@ - udp based protocol - make mcalign merge chunks - option to use default fragment size on alsa drivers +- improve module-oss-mmap latency measurement ** later *** - xmlrpc/http @@ -27,7 +27,7 @@ backends for: - portaudio +- alsa-lib - sdl - gstreamer (semi-done) -- alsa-lib - OSS (esddsp style) diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 0915be8b0..9932e5689 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -125,10 +125,11 @@ char *pa_source_list_to_string(struct pa_core *c) { for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec); - pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tsample_spec: <%s>\n", + pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n", c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ', source->index, source->name, + (float) pa_source_get_latency(source), ss); if (source->monitor_of) diff --git a/polyp/iochannel.c b/polyp/iochannel.c index 1aa70b935..72bdac20e 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -229,3 +229,14 @@ int pa_iochannel_socket_set_sndbuf(struct pa_iochannel *io, size_t l) { assert(io); return pa_socket_set_sndbuf(io->ofd, l); } + +void pa_iochannel_force_unreadable(struct pa_iochannel *io) { + assert(io); + io->readable = 0; + enable_mainloop_sources(io); +} + +void pa_iochannel_force_unwritable(struct pa_iochannel *io) { + io->writable = 0; + enable_mainloop_sources(io); +} diff --git a/polyp/iochannel.h b/polyp/iochannel.h index 6f5f351c2..a4edbfad5 100644 --- a/polyp/iochannel.h +++ b/polyp/iochannel.h @@ -39,6 +39,9 @@ int pa_iochannel_is_readable(struct pa_iochannel*io); int pa_iochannel_is_writable(struct pa_iochannel*io); int pa_iochannel_is_hungup(struct pa_iochannel*io); +void pa_iochannel_force_unreadable(struct pa_iochannel *io); +void pa_iochannel_force_unwritable(struct pa_iochannel *io); + void pa_iochannel_set_noclose(struct pa_iochannel*io, int b); void pa_iochannel_set_callback(struct pa_iochannel*io, void (*callback)(struct pa_iochannel*io, void *userdata), void *userdata); diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index cf828eb0a..41a17691f 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -143,6 +143,20 @@ static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, do_read(u); } +static pa_usec_t source_get_latency_cb(struct pa_source *s) { + struct userdata *u = s->userdata; + snd_pcm_sframes_t frames; + assert(s && u && u->source); + + if (snd_pcm_delay(u->pcm_handle, &frames) < 0) { + pa_log(__FILE__": failed to get delay\n"); + s->get_latency = NULL; + return 0; + } + + return pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); +} + int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; int ret = -1; @@ -191,6 +205,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { assert(u->source); u->source->userdata = u; + u->source->get_latency = source_get_latency_cb; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); diff --git a/polyp/module-oss.c b/polyp/module-oss.c index a45f72b8c..68918604f 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -59,6 +59,7 @@ struct userdata { struct pa_memchunk memchunk, silence; uint32_t in_fragment_size, out_fragment_size, sample_size; + int use_getospace, use_getispace; int fd; struct pa_module *module; @@ -92,6 +93,9 @@ static void update_usage(struct userdata *u) { static void do_write(struct userdata *u) { struct pa_memchunk *memchunk; ssize_t r; + size_t l; + int loop = 0; + assert(u); if (!u->sink || !pa_iochannel_is_writable(u->io)) @@ -99,37 +103,58 @@ static void do_write(struct userdata *u) { update_usage(u); - memchunk = &u->memchunk; + l = u->out_fragment_size; - if (!memchunk->length) - if (pa_sink_render(u->sink, u->out_fragment_size, memchunk) < 0) - memchunk = &u->silence; - - assert(memchunk->memblock); - assert(memchunk->memblock->data); - assert(memchunk->length); - - if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); - return; - } + if (u->use_getospace) { + audio_buf_info info; - if (memchunk == &u->silence) - assert(r % u->sample_size == 0); - else { - u->memchunk.index += r; - u->memchunk.length -= r; - - if (u->memchunk.length <= 0) { - pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; + if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) + u->use_getospace = 0; + else { + if (info.bytes/l > 0) { + l = (info.bytes/l)*l; + loop = 1; + } } } + + do { + memchunk = &u->memchunk; + + if (!memchunk->length) + if (pa_sink_render(u->sink, l, memchunk) < 0) + memchunk = &u->silence; + + assert(memchunk->memblock); + assert(memchunk->memblock->data); + assert(memchunk->length); + + if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + break; + } + + if (memchunk == &u->silence) + assert(r % u->sample_size == 0); + else { + u->memchunk.index += r; + u->memchunk.length -= r; + + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; + } + } + + l = l > (size_t) r ? l - r : 0; + } while (loop && l > 0); } static void do_read(struct userdata *u) { struct pa_memchunk memchunk; ssize_t r; + size_t l; + int loop = 0; assert(u); if (!u->source || !pa_iochannel_is_readable(u->io)) @@ -137,21 +162,40 @@ static void do_read(struct userdata *u) { update_usage(u); - memchunk.memblock = pa_memblock_new(u->in_fragment_size, u->core->memblock_stat); - assert(memchunk.memblock); - if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { - pa_memblock_unref(memchunk.memblock); - if (errno != EAGAIN) - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); - return; + l = u->in_fragment_size; + + if (u->use_getispace) { + audio_buf_info info; + + if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) + u->use_getispace = 0; + else { + if (info.bytes/l > 0) { + l = (info.bytes/l)*l; + loop = 1; + } + } } + + do { + memchunk.memblock = pa_memblock_new(l, u->core->memblock_stat); + assert(memchunk.memblock); + if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { + pa_memblock_unref(memchunk.memblock); + if (errno != EAGAIN) + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + break; + } + + assert(r <= (ssize_t) memchunk.memblock->length); + memchunk.length = memchunk.memblock->length = r; + memchunk.index = 0; + + pa_source_post(u->source, &memchunk); + pa_memblock_unref(memchunk.memblock); - assert(r <= (ssize_t) memchunk.memblock->length); - memchunk.length = memchunk.memblock->length = r; - memchunk.index = 0; - - pa_source_post(u->source, &memchunk); - pa_memblock_unref(memchunk.memblock); + l = l > (size_t) r ? l - r : 0; + } while (loop && l > 0); } static void io_callback(struct pa_iochannel *io, void*userdata) { @@ -181,6 +225,25 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { return r; } +static pa_usec_t source_get_latency_cb(struct pa_source *s) { + struct userdata *u = s->userdata; + audio_buf_info info; + assert(s && u && u->sink); + + if (!u->use_getispace) + return 0; + + if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { + u->use_getispace = 0; + return 0; + } + + if (info.bytes <= 0) + return 0; + + return pa_bytes_to_usec(info.bytes, &s->sample_spec); +} + int pa__init(struct pa_core *c, struct pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; @@ -243,23 +306,27 @@ int pa__init(struct pa_core *c, struct pa_module*m) { assert(frag_size); in_frag_size = out_frag_size = frag_size; + u = pa_xmalloc(sizeof(struct userdata)); + u->core = c; + u->use_getospace = u->use_getispace = 0; + if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { pa_log(__FILE__": input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); in_frag_size = info.fragsize; + u->use_getispace = 1; } if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { pa_log(__FILE__": output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); out_frag_size = info.fragsize; + u->use_getospace = 1; } - u = pa_xmalloc(sizeof(struct userdata)); - u->core = c; - if (mode != O_WRONLY) { u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); assert(u->source); u->source->userdata = u; + u->source->get_latency = source_get_latency_cb; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p); } else diff --git a/polyp/native-common.h b/polyp/native-common.h index 45e0b1d35..a052fca27 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -86,6 +86,7 @@ enum { PA_COMMAND_REMOVE_AUTOLOAD, PA_COMMAND_GET_AUTOLOAD_INFO, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, + PA_COMMAND_GET_RECORD_LATENCY, PA_COMMAND_MAX }; diff --git a/polyp/pacat.c b/polyp/pacat.c index cc7d55f40..933b0c3a7 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -276,27 +276,29 @@ static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_even } -/* Show the current playback latency */ +/* Show the current latency */ static void stream_get_latency_callback(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) { + double total; assert(s); if (!i) { - fprintf(stderr, "Failed to get latency: %s\n", strerror(errno)); + fprintf(stderr, "Failed to get latency: %s\n", pa_strerror(pa_context_errno(context))); quit(1); return; } - fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n", - (float) i->buffer_usec, (float) i->sink_usec, (float) i->transport_usec, - (float) (i->buffer_usec+i->sink_usec+i->transport_usec), + if (mode == PLAYBACK) + total = (double) i->sink_usec + i->buffer_usec + i->transport_usec; + else + total = (double) i->source_usec + i->buffer_usec + i->transport_usec - i->sink_usec; + + fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; source: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n", + (float) i->buffer_usec, (float) i->sink_usec, (float) i->source_usec, (float) i->transport_usec, total, i->synchronized_clocks ? "yes" : "no"); } /* Someone requested that the latency is shown */ static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { - if (mode != PLAYBACK) - return; - fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); pa_operation_unref(pa_stream_get_latency(stream, stream_get_latency_callback, NULL)); } diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 9bba3f32d..29f5eb43a 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -132,20 +132,26 @@ enum pa_subscription_event_type { /** Return one if an event type t matches an event mask bitfield */ #define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) -/** A structure for latency info. See pa_stream_get_latency(). The - * total latency a sample that is written with pa_stream_write() takes - * to be played may be estimated by - * buffer_usec+sink_usec+transport_usec. The buffer to which +/** A structure for latency info. See pa_stream_get_latency(). The + * total output latency a sample that is written with + * pa_stream_write() takes to be played may be estimated by + * sink_usec+buffer_usec+transport_usec. The output buffer to which * buffer_usec relates may be manipulated freely (with * pa_stream_write()'s delta argument, pa_stream_flush() and friends), - * the playback buffer sink_usec relates to is a FIFO which cannot be - * flushed or manipulated in any way. */ + * the buffers sink_usec/source_usec relates to is a first-in + * first-out buffer which cannot be flushed or manipulated in any + * way. The total input latency a sample that is recorded takes to be + * delivered to the application is: + * source_usec+buffer_usec+transport_usec-sink_usec. (Take care of + * sign issues!) When connected to a monitor source sink_usec contains + * the latency of the owning sink.*/ struct pa_latency_info { - pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play */ - pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. */ - pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to the daemon. \since 0.5 */ - int playing; /**< Non-zero when the stream is currently playing */ - uint32_t queue_length; /**< Queue size in bytes. */ + pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play. For both playback and record streams. */ + pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. For playback streams and record streams connected to a monitor source. */ + pa_usec_t source_usec; /**< Time in usecs a sample takes from being recorded to being delivered to the application. Only for record streams. \since 0.5*/ + pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to/from the daemon. For both playback and record streams. \since 0.5 */ + int playing; /**< Non-zero when the stream is currently playing. Only for playback streams. */ + uint32_t queue_length; /**< Queue size in bytes. For both playback and recrd streams. */ int synchronized_clocks; /**< Non-zero if the local and the * remote machine have synchronized * clocks. If synchronized clocks are diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 919adb9cc..1673be9bf 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -221,7 +221,9 @@ static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t c pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || - pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) { + pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 || + pa_tagstruct_get_usec(t, &i.latency) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -515,7 +517,9 @@ static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uin pa_tagstruct_getu32(t, &i.owner_module) < 0 || pa_tagstruct_getu32(t, &i.client) < 0 || pa_tagstruct_getu32(t, &i.source) < 0 || - pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0) { + pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || + pa_tagstruct_get_usec(t, &i.source_usec) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 51210457d..28c51fedd 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -56,7 +56,7 @@ struct pa_sink_info { pa_volume_t volume; /**< Volume of the sink */ uint32_t monitor_source; /**< Index of the monitor source connected to this sink */ const char *monitor_source_name; /**< The name of the monitor source */ - pa_usec_t latency; /**< Length of the playback buffer of this sink */ + pa_usec_t latency; /**< Length of filled playback buffer of this sink */ }; /** Get information about a sink by its name */ @@ -77,6 +77,7 @@ struct pa_source_info { uint32_t owner_module; /**< Owning module index, or PA_INVALID_INDEX */ uint32_t monitor_of_sink; /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */ const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */ + pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */ }; /** Get information about a source by its name */ @@ -158,6 +159,8 @@ struct pa_source_output_info { uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */ uint32_t source; /**< Index of the connected source */ struct pa_sample_spec sample_spec; /**< The sample specification of the source output */ + pa_usec_t buffer_usec; /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */ + pa_usec_t source_usec; /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */ }; /** Get information about a source output by its index */ diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 89a8d3383..532d1700f 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -336,6 +336,7 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman } else if (pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || pa_tagstruct_get_usec(t, &i.sink_usec) < 0 || + pa_tagstruct_get_usec(t, &i.source_usec) < 0 || pa_tagstruct_get_boolean(t, &i.playing) < 0 || pa_tagstruct_getu32(t, &i.queue_length) < 0 || pa_tagstruct_get_timeval(t, &local) < 0 || @@ -350,7 +351,12 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) { /* local and remote seem to have synchronized clocks */ - i.transport_usec = pa_timeval_diff(&remote, &local); + + if (o->stream->direction == PA_STREAM_PLAYBACK) + i.transport_usec = pa_timeval_diff(&remote, &local); + else + i.transport_usec = pa_timeval_diff(&now, &remote); + i.synchronized_clocks = 1; i.timestamp = remote; } else { @@ -376,6 +382,7 @@ struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struc struct pa_operation *o; struct pa_tagstruct *t; struct timeval now; + assert(s && s->direction != PA_STREAM_UPLOAD); o = pa_operation_new(s->context, s); assert(o); @@ -384,7 +391,7 @@ struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struc t = pa_tagstruct_new(NULL, 0); assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 5abe474d6..aff450992 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -107,6 +107,7 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); static void sink_input_kill_cb(struct pa_sink_input *i); static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i); +static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o); static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk); static void source_output_kill_cb(struct pa_source_output *o); @@ -374,6 +375,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co c->source_output->client = c->client; c->source_output->push = source_output_push_cb; c->source_output->kill = source_output_kill_cb; + c->source_output->get_latency = source_output_get_latency_cb; c->source_output->userdata = c; c->state = ESD_STREAMING_DATA; @@ -919,7 +921,6 @@ static void sink_input_kill_cb(struct pa_sink_input *i) { connection_free((struct connection *) i->userdata); } - static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); @@ -944,6 +945,12 @@ static void source_output_kill_cb(struct pa_source_output *o) { connection_free((struct connection *) o->userdata); } +static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o) { + struct connection*c = o->userdata; + assert(o && c); + return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec); +} + /*** socket server callback ***/ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index be7b76f6f..e197d1e2b 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -117,6 +117,7 @@ static void request_bytes(struct playback_stream*s); static void source_output_kill_cb(struct pa_source_output *o); static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk); +static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o); static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); @@ -128,6 +129,7 @@ static void command_set_client_name(struct pa_pdispatch *pd, uint32_t command, u static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); @@ -166,6 +168,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_LOOKUP_SOURCE] = { command_lookup }, [PA_COMMAND_STAT] = { command_stat }, [PA_COMMAND_GET_PLAYBACK_LATENCY] = { command_get_playback_latency }, + [PA_COMMAND_GET_RECORD_LATENCY] = { command_get_record_latency }, [PA_COMMAND_CREATE_UPLOAD_STREAM] = { command_create_upload_stream }, [PA_COMMAND_DELETE_UPLOAD_STREAM] = { command_delete_stream }, [PA_COMMAND_FINISH_UPLOAD_STREAM] = { command_finish_upload_stream }, @@ -256,6 +259,7 @@ static struct record_stream* record_stream_new(struct connection *c, struct pa_s s->source_output = source_output; s->source_output->push = source_output_push_cb; s->source_output->kill = source_output_kill_cb; + s->source_output->get_latency = source_output_get_latency_cb; s->source_output->userdata = s; s->source_output->owner = c->protocol->module; s->source_output->client = c->client; @@ -444,7 +448,6 @@ static void send_record_stream_killed(struct record_stream *r) { pa_pstream_send_tagstruct(r->connection->pstream, t); } - /*** sinkinput callbacks ***/ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { @@ -508,6 +511,16 @@ static void source_output_kill_cb(struct pa_source_output *o) { record_stream_free((struct record_stream *) o->userdata); } +static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o) { + struct record_stream *s; + assert(o && o->userdata); + s = o->userdata; + + /*pa_log(__FILE__": get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/ + + return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec); +} + /*** pdispatch callbacks ***/ static void protocol_error(struct connection *c) { @@ -843,7 +856,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma struct timeval tv, now; uint32_t index; assert(c && t); - + if (pa_tagstruct_getu32(t, &index) < 0 || pa_tagstruct_get_timeval(t, &tv) < 0 || !pa_tagstruct_eof(t)) { @@ -867,6 +880,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma pa_tagstruct_putu32(reply, tag); pa_tagstruct_put_usec(reply, pa_sink_input_get_latency(s->sink_input)); pa_tagstruct_put_usec(reply, pa_sink_get_latency(s->sink_input->sink)); + pa_tagstruct_put_usec(reply, 0); pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq)); pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq)); pa_tagstruct_put_timeval(reply, &tv); @@ -875,6 +889,47 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma pa_pstream_send_tagstruct(c->pstream, reply); } +static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + struct pa_tagstruct *reply; + struct record_stream *s; + struct timeval tv, now; + uint32_t index; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + pa_tagstruct_get_timeval(t, &tv) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(s = pa_idxset_get_by_index(c->record_streams, index))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + reply = pa_tagstruct_new(NULL, 0); + assert(reply); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + pa_tagstruct_put_usec(reply, pa_source_output_get_latency(s->source_output)); + pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0); + pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source)); + pa_tagstruct_put_boolean(reply, 0); + pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq)); + pa_tagstruct_put_timeval(reply, &tv); + gettimeofday(&now, NULL); + pa_tagstruct_put_timeval(reply, &now); + pa_pstream_send_tagstruct(c->pstream, reply); +} + + static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct upload_stream *s; @@ -1036,6 +1091,7 @@ static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *sour pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1); pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1); pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : ""); + pa_tagstruct_put_usec(t, pa_source_get_latency(source)); } static void client_fill_tagstruct(struct pa_tagstruct *t, struct pa_client *client) { @@ -1076,6 +1132,8 @@ static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_sourc pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1); pa_tagstruct_putu32(t, s->source->index); pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_put_usec(t, pa_source_output_get_latency(s)); + pa_tagstruct_put_usec(t, pa_source_get_latency(s->source)); } static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry *e) { diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 58156329c..a7bd76fbd 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -248,6 +248,12 @@ static void source_output_kill_cb(struct pa_source_output *o) { connection_free((struct connection *) o->userdata); } +static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o) { + struct connection*c = o->userdata; + assert(o && c); + return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec); +} + /*** client callbacks ***/ static void client_kill_cb(struct pa_client *c) { @@ -348,6 +354,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->source_output->push = source_output_push_cb; c->source_output->kill = source_output_kill_cb; + c->source_output->get_latency = source_output_get_latency_cb; c->source_output->userdata = c; l = (size_t) (pa_bytes_per_second(&p->sample_spec)*RECORD_BUFFER_SECONDS); diff --git a/polyp/sink.c b/polyp/sink.c index 6d3b59c77..8133d65a2 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -197,7 +197,10 @@ int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) unsigned n; size_t l; int r = -1; - assert(s && s->ref >= 1 && length && result); + assert(s); + assert(s->ref >= 1); + assert(length); + assert(result); pa_sink_ref(s); diff --git a/polyp/source-output.c b/polyp/source-output.c index 2566ec875..1db88d3cc 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -60,6 +60,8 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n o->push = NULL; o->kill = NULL; o->userdata = NULL; + o->get_latency = NULL; + o->resampler = resampler; assert(s->core); @@ -149,3 +151,12 @@ void pa_source_output_set_name(struct pa_source_output *o, const char *name) { pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); } + +pa_usec_t pa_source_output_get_latency(struct pa_source_output *o) { + assert(o && o->ref >= 1); + + if (o->get_latency) + return o->get_latency(o); + + return 0; +} diff --git a/polyp/source-output.h b/polyp/source-output.h index 709d65ad9..ed09b5370 100644 --- a/polyp/source-output.h +++ b/polyp/source-output.h @@ -50,6 +50,7 @@ struct pa_source_output { void (*push)(struct pa_source_output *o, const struct pa_memchunk *chunk); void (*kill)(struct pa_source_output* o); + pa_usec_t (*get_latency) (struct pa_source_output *i); struct pa_resampler* resampler; @@ -70,4 +71,7 @@ void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk void pa_source_output_set_name(struct pa_source_output *i, const char *name); +pa_usec_t pa_source_output_get_latency(struct pa_source_output *i); + + #endif diff --git a/polyp/source.c b/polyp/source.c index 2c0caca07..23b8bf8ac 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -60,6 +60,7 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail s->outputs = pa_idxset_new(NULL, NULL); s->monitor_of = NULL; + s->get_latency = NULL; s->notify = NULL; s->userdata = NULL; @@ -150,3 +151,13 @@ void pa_source_set_owner(struct pa_source *s, struct pa_module *m) { assert(s); s->owner = m; } + +pa_usec_t pa_source_get_latency(struct pa_source *s) { + assert(s && s->ref >= 1); + + if (!s->get_latency) + return 0; + + return s->get_latency(s); +} + diff --git a/polyp/source.h b/polyp/source.h index 8b03c0d56..b6262835f 100644 --- a/polyp/source.h +++ b/polyp/source.h @@ -53,6 +53,7 @@ struct pa_source { struct pa_sink *monitor_of; void (*notify)(struct pa_source*source); + pa_usec_t (*get_latency)(struct pa_source *s); void *userdata; }; @@ -68,4 +69,6 @@ void pa_source_notify(struct pa_source *s); void pa_source_set_owner(struct pa_source *s, struct pa_module *m); +pa_usec_t pa_source_get_latency(struct pa_source *s); + #endif From daf3938a9e5b50c3e52c0ae889e4d02b548fa78a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Sep 2004 22:07:41 +0000 Subject: [PATCH 0202/1514] add support for subscribing to autoload table changes fix module-combine so that the sample rate of at least one streams is not changed from the original git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@206 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 5 ++--- polyp/autoload.c | 5 +++++ polyp/autoload.h | 1 + polyp/module-combine.c | 42 ++++++++++++++++++++++++------------------ polyp/polyplib-def.h | 6 ++++-- polyp/pstream.c | 14 ++++++++++++-- polyp/sample.c | 6 +++--- 7 files changed, 51 insertions(+), 28 deletions(-) diff --git a/doc/todo b/doc/todo index 675e8ca38..bcc78f51b 100644 --- a/doc/todo +++ b/doc/todo @@ -1,9 +1,8 @@ *** $Id$ *** *** 0.5 *** -- more complete pactl -- fix tcp/native -- paman: add support for killing sink inputs, source outputs, clients +- more complete pactl/parec +- fix tcp/native in regard to latencies - add client config file - remove autospawn stuff in conf.c diff --git a/polyp/autoload.c b/polyp/autoload.c index 344d26e29..12cd1f91e 100644 --- a/polyp/autoload.c +++ b/polyp/autoload.c @@ -34,9 +34,11 @@ #include "sound-file.h" #include "log.h" #include "scache.h" +#include "subscribe.h" static void entry_free(struct pa_autoload_entry *e) { assert(e); + pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_REMOVE, PA_INVALID_INDEX); pa_xfree(e->name); pa_xfree(e->module); pa_xfree(e->argument); @@ -51,6 +53,7 @@ static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) return NULL; e = pa_xmalloc(sizeof(struct pa_autoload_entry)); + e->core = c; e->name = pa_xstrdup(name); e->module = e->argument = NULL; e->in_action = 0; @@ -61,6 +64,8 @@ static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) pa_hashmap_put(c->autoload_hashmap, e->name, e); + pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_NEW, PA_INVALID_INDEX); + return e; } diff --git a/polyp/autoload.h b/polyp/autoload.h index cdf762390..f80b1f0dd 100644 --- a/polyp/autoload.h +++ b/polyp/autoload.h @@ -25,6 +25,7 @@ #include "namereg.h" struct pa_autoload_entry { + struct pa_core *core; char *name; enum pa_namereg_type type; int in_action; diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 8535e5147..177d7d18d 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -40,7 +40,7 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Combine multiple sinks to one") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= master= slave= adjust_time") +PA_MODULE_USAGE("sink_name= master= slave= adjust_time=") #define DEFAULT_SINK_NAME "combined" #define MEMBLOCKQ_MAXLENGTH (1024*170) @@ -61,7 +61,7 @@ struct output { struct pa_sink_input *sink_input; size_t counter; struct pa_memblockq *memblockq; - pa_usec_t sink_latency; + pa_usec_t total_latency; PA_LLIST_FIELDS(struct output); }; @@ -89,38 +89,44 @@ static void update_usage(struct userdata *u) { static void adjust_rates(struct userdata *u) { struct output *o; - pa_usec_t max = 0; + pa_usec_t max_sink_latency = 0, min_total_latency = (pa_usec_t) -1, target_latency; uint32_t base_rate; assert(u && u->sink); for (o = u->outputs; o; o = o->next) { - o->sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0; + uint32_t sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0; + + o->total_latency = sink_latency + pa_sink_input_get_latency(o->sink_input); + + if (sink_latency > max_sink_latency) + max_sink_latency = sink_latency; - if (o->sink_latency > max) - max = o->sink_latency; + if (o->total_latency < min_total_latency) + min_total_latency = o->total_latency; } - pa_log(__FILE__": [%s] maximum latency is %0.0f usec.\n", u->sink->name, (float) max); + assert(max_sink_latency > 0 && min_total_latency != (pa_usec_t) -1); + + target_latency = max_sink_latency > min_total_latency ? max_sink_latency : min_total_latency; + + pa_log(__FILE__": [%s] target latency is %0.0f usec.\n", u->sink->name, (float) target_latency); base_rate = u->sink->sample_spec.rate; for (o = u->outputs; o; o = o->next) { - pa_usec_t l; uint32_t r = base_rate; - l = o->sink_latency + pa_sink_input_get_latency(o->sink_input); - - if (l < max) - r -= (uint32_t) (((((double) max-l))/u->adjust_time)*r/ 1000000); - else if (l > max) - r += (uint32_t) (((((double) l-max))/u->adjust_time)*r/ 1000000); + if (o->total_latency < target_latency) + r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/ 1000000); + else if (o->total_latency > target_latency) + r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/ 1000000); if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) pa_log(__FILE__": [%s] sample rates too different, not adjusting (%u vs. %u).\n", o->sink_input->name, base_rate, r); - else - pa_log(__FILE__": [%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.\n", o->sink_input->name, r, (double) r / base_rate, (float) l); - - pa_sink_input_set_rate(o->sink_input, r); + else { + pa_log(__FILE__": [%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.\n", o->sink_input->name, r, (double) r / base_rate, (float) o->total_latency); + pa_sink_input_set_rate(o->sink_input, r); + } } } diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 29f5eb43a..591d237d5 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -108,7 +108,8 @@ enum pa_subscription_mask { PA_SUBSCRIPTION_MASK_MODULE = 16, /**< Module events */ PA_SUBSCRIPTION_MASK_CLIENT = 32, /**< Client events */ PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */ - PA_SUBSCRIPTION_MASK_SERVER = 128 /**< Other global server changes. \since 0.4 */ + PA_SUBSCRIPTION_MASK_SERVER = 128, /**< Other global server changes. \since 0.4 */ + PA_SUBSCRIPTION_MASK_AUTOLOAD = 256 /**< Autoload table events. \since 0.5 */ }; /** Subscription event types, as used by pa_context_subscribe() */ @@ -121,7 +122,8 @@ enum pa_subscription_event_type { PA_SUBSCRIPTION_EVENT_CLIENT = 5, /**< Event type: Client */ PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6, /**< Event type: Sample cache item */ PA_SUBSCRIPTION_EVENT_SERVER = 7, /**< Event type: Global server change, only occuring with PA_SUBSCRIPTION_EVENT_CHANGE. \since 0.4 */ - PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 7, /**< A mask to extract the event type from an event value */ + PA_SUBSCRIPTION_EVENT_AUTOLOAD = 8, /**< Event type: Autoload table changes. \since 0.5 */ + PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 15, /**< A mask to extract the event type from an event value */ PA_SUBSCRIPTION_EVENT_NEW = 0, /**< A new object was created */ PA_SUBSCRIPTION_EVENT_CHANGE = 16, /**< A property of the object was modified */ diff --git a/polyp/pstream.c b/polyp/pstream.c index 4ee296cec..b0de9e8c6 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -101,6 +101,10 @@ static void do_read(struct pa_pstream *p); static void do_something(struct pa_pstream *p) { assert(p); + + if (p->dead) + return; + p->mainloop->defer_enable(p->defer_event, 0); pa_pstream_ref(p); @@ -213,8 +217,11 @@ static void pstream_free(struct pa_pstream *p) { void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { struct item_info *i; - assert(p && packet); + assert(p && packet && p->ref >= 1); + if (p->dead) + return; + /* pa_log(__FILE__": push-packet %p\n", packet); */ i = pa_xmalloc(sizeof(struct item_info)); @@ -227,8 +234,11 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk) { struct item_info *i; - assert(p && channel != (uint32_t) -1 && chunk); + assert(p && channel != (uint32_t) -1 && chunk && p->ref >= 1); + if (p->dead) + return; + /* pa_log(__FILE__": push-memblock %p\n", chunk); */ i = pa_xmalloc(sizeof(struct item_info)); diff --git a/polyp/sample.c b/polyp/sample.c index dfe98e3fd..397e57a2d 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -121,11 +121,11 @@ double pa_volume_to_dB(pa_volume_t v) { } void pa_bytes_snprint(char *s, size_t l, off_t v) { - if (v >= 1024*1024*1024) + if (v >= (off_t) 1024*1024*1024) snprintf(s, l, "%0.1f GB", (double) v/1024/1024/1024); - else if (v >= 1024*1024) + else if (v >= (off_t) 1024*1024) snprintf(s, l, "%0.1f MB", (double) v/1024/1024); - else if (v >= 1024) + else if (v >= (off_t) 1024) snprintf(s, l, "%0.1f KB", (double) v/1024); else snprintf(s, l, "%u B", (unsigned) v); From 19294e4b388571ba45162b3704f8aacd38e72158 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Sep 2004 22:44:40 +0000 Subject: [PATCH 0203/1514] fix two gcc 2.95 incompatibilities git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@207 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 7 ++++--- polyp/dumpmodules.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 07b2b96ce..8b5a72ab9 100644 --- a/configure.ac +++ b/configure.ac @@ -40,8 +40,6 @@ AC_SUBST(INCLTDL) AC_SUBST(LIBLTDL) AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL -AC_PROG_LEX -AC_PROG_YACC # Checks for header files. AC_HEADER_STDC @@ -108,7 +106,10 @@ AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) # If using GCC specifiy some additional parameters if test "x$GCC" = "xyes" ; then - CFLAGS="$CFLAGS -pipe -W -Wall -Wno-unused-parameter -pedantic -std=c99" + CFLAGS="$CFLAGS -pipe -W -Wall -pedantic" + + AC_LANG_CONFTEST([int main()]) + $CC -std=c99 -Wno-unused-parameter -E conftest.c -o - > /dev/null 2>&1 && CFLAGS="$CFLAGS -std=c99 -Wno-unused-parameter" fi # LYNX documentation generation diff --git a/polyp/dumpmodules.c b/polyp/dumpmodules.c index 9ed89692a..ae42d36ec 100644 --- a/polyp/dumpmodules.c +++ b/polyp/dumpmodules.c @@ -40,8 +40,8 @@ static void short_info(const char *name, const char *path, struct pa_modinfo *i) } static void long_info(const char *name, const char *path, struct pa_modinfo *i) { - assert(name && i); static int nl = 0; + assert(name && i); if (nl) printf("\n"); From 078f2aa860cc0e0063dd6b4e8ff6ca1cbf5fd45b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Sep 2004 23:34:25 +0000 Subject: [PATCH 0204/1514] gcc 2.95 compatibility, take 2 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@208 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 7 ++++--- polyp/cpulimit-test.c | 3 ++- polyp/log.h | 2 +- polyp/polyplib-introspect.h | 2 +- polyp/source.h | 2 +- polyp/tagstruct.c | 2 +- polyp/util.c | 2 +- 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 8b5a72ab9..5239db1dd 100644 --- a/configure.ac +++ b/configure.ac @@ -104,12 +104,13 @@ AC_SUBST(GLIB12_LIBS) AC_SUBST(HAVE_GLIB12) AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) -# If using GCC specifiy some additional parameters +# If using GCC specify some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -W -Wall -pedantic" - AC_LANG_CONFTEST([int main()]) - $CC -std=c99 -Wno-unused-parameter -E conftest.c -o - > /dev/null 2>&1 && CFLAGS="$CFLAGS -std=c99 -Wno-unused-parameter" + AC_LANG_CONFTEST([int main() {}]) + $CC -c conftest.c -std=c99 -Wno-unused-parameter $CFLAGS > /dev/null 2> /dev/null && CFLAGS="$CFLAGS -std=c99 -Wno-unused-parameter" + rm -f conftest.o fi # LYNX documentation generation diff --git a/polyp/cpulimit-test.c b/polyp/cpulimit-test.c index 71c06ef7a..d1faf92bb 100644 --- a/polyp/cpulimit-test.c +++ b/polyp/cpulimit-test.c @@ -80,5 +80,6 @@ int main() { pa_cpu_limit_done(); pa_mainloop_free(m); - + + return 0; } diff --git a/polyp/log.h b/polyp/log.h index 1f2c74ef9..46a86491c 100644 --- a/polyp/log.h +++ b/polyp/log.h @@ -6,7 +6,7 @@ enum pa_log_target { PA_LOG_SYSLOG, PA_LOG_STDERR, - PA_LOG_USER, + PA_LOG_USER }; void pa_log_set_ident(const char *p); diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 28c51fedd..9e6c31b28 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -229,7 +229,7 @@ struct pa_operation* pa_context_unload_module(struct pa_context *c, uint32_t ind /** Type of an autoload entry. \since 0.5 */ enum pa_autoload_type { PA_AUTOLOAD_SINK = 0, - PA_AUTOLOAD_SOURCE = 1, + PA_AUTOLOAD_SOURCE = 1 }; /** Stores information about autoload entries. \since 0.5 */ diff --git a/polyp/source.h b/polyp/source.h index b6262835f..cda9e6986 100644 --- a/polyp/source.h +++ b/polyp/source.h @@ -36,7 +36,7 @@ struct pa_source; enum pa_source_state { PA_SOURCE_RUNNING, - PA_SOURCE_DISCONNECTED, + PA_SOURCE_DISCONNECTED }; struct pa_source { diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 52db0fe34..d571b7138 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -46,7 +46,7 @@ enum tags { TAG_BOOLEAN_TRUE = '1', TAG_BOOLEAN_FALSE = '0', TAG_TIMEVAL = 'T', - TAG_USEC = 'U', /* 64bit unsigned */ + TAG_USEC = 'U' /* 64bit unsigned */ }; struct pa_tagstruct { diff --git a/polyp/util.c b/polyp/util.c index bb71bbf95..24773a7bc 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -385,7 +385,7 @@ char *pa_split(const char *c, const char *delimiter, const char**state) { *state = current+l; if (**state) - *state++; + (*state)++; return pa_xstrndup(current, l); } From 07d563d6c304166bd5bd47731a337387316991f6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Sep 2004 23:43:19 +0000 Subject: [PATCH 0205/1514] update according to autoscan git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@209 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 5239db1dd..f422ff687 100644 --- a/configure.ac +++ b/configure.ac @@ -72,7 +72,7 @@ AC_FUNC_REALLOC AC_FUNC_SETPGRP AC_FUNC_VPRINTF AC_TYPE_SIGNAL -AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul pow strcasecmp]) +AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul pow strcasecmp putenv strchr strpbrk]) AC_FUNC_STAT AC_HEADER_SYS_WAIT From 63b35d002aa6902618235e1a30dca37de52ff65e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Sep 2004 19:45:44 +0000 Subject: [PATCH 0206/1514] new configuration subsystem git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@210 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + polyp/Makefile.am | 15 +- polyp/client.conf | 39 +++++ polyp/conf.c | 281 +++++++++++++--------------------- polyp/conf.h | 1 + polyp/config-client.c | 138 +++++++++++++++++ polyp/config-client.h | 36 +++++ polyp/confparser.c | 168 ++++++++++++++++++++ polyp/confparser.h | 37 +++++ polyp/core.c | 3 + polyp/core.h | 2 + polyp/{config => daemon.conf} | 22 ++- polyp/main.c | 6 +- polyp/polyplib-context.c | 63 +++++--- polyp/polyplib-internal.h | 9 +- polyp/polyplib-scache.c | 2 +- polyp/polyplib-stream.c | 6 +- polyp/resampler.c | 4 +- polyp/resampler.h | 2 +- polyp/sink-input.c | 2 +- polyp/source-output.c | 2 +- polyp/util.c | 17 ++ polyp/util.h | 1 + 23 files changed, 626 insertions(+), 231 deletions(-) create mode 100644 polyp/client.conf create mode 100644 polyp/config-client.c create mode 100644 polyp/config-client.h create mode 100644 polyp/confparser.c create mode 100644 polyp/confparser.h rename polyp/{config => daemon.conf} (73%) diff --git a/doc/todo b/doc/todo index bcc78f51b..fe06df780 100644 --- a/doc/todo +++ b/doc/todo @@ -5,6 +5,7 @@ - fix tcp/native in regard to latencies - add client config file - remove autospawn stuff in conf.c +- make resampler configurable *** 0.6 **** - per-channel volume diff --git a/polyp/Makefile.am b/polyp/Makefile.am index fc3fb18d2..d49c7c481 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -25,14 +25,14 @@ modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\" AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\" -AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/default.conf\" -AM_CFLAGS+=-DAUTOSPAWN_CONFIG_FILE=\"$(polypconfdir)/autospawn.conf\" +AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/daemon.conf\" +AM_CFLAGS+=-DDEFAULT_CLIENT_CONFIG_FILE=\"$(polypconfdir)/client.conf\" AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm -EXTRA_DIST = default.pa config depmod.py esdcompat.sh.in +EXTRA_DIST = default.pa daemon.conf client.conf config depmod.py esdcompat.sh.in bin_PROGRAMS = polypaudio pacat pactl bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ @@ -42,7 +42,7 @@ noinst_PROGRAMS = \ cpulimit-test \ cpulimit-test2 -polypconf_DATA=default.pa config +polypconf_DATA=default.pa daemon.conf client.conf BUILT_SOURCES=polyplib-version.h @@ -158,7 +158,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ gcc-printf.h \ modinfo.c modinfo.h \ conf.c conf.h \ - dumpmodules.c dumpmodules.h + dumpmodules.c dumpmodules.h \ + conparser.h confparser.c polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) @@ -332,7 +333,9 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ cdecl.h \ llist.h \ log.c log.h \ - gcc-printf.h + gcc-printf.h \ + config-client.c config-client.h \ + confparser.c confparser.h libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 diff --git a/polyp/client.conf b/polyp/client.conf new file mode 100644 index 000000000..070d75bd2 --- /dev/null +++ b/polyp/client.conf @@ -0,0 +1,39 @@ +# $Id$ +# +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with polypaudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +## Configuration file for polypaudio clients. Default values are +## commented out. Use either ; or # for commenting + +## Path to the polypaudio daemon to run when autospawning. +; daemon_binary = @POLYPAUDIO_BINARY + +## Extra arguments to pass to the polypaudio daemon +; extra_arguments = --daemonize=yes --log-target=syslog + +## The default sink to connect to +; default_sink = + +## The default source to connect to +; default_source = + +## The default sever to connect to +; default_server = + +## Autospawn daemons? +; autospawn = 0 diff --git a/polyp/conf.c b/polyp/conf.c index b74a5ede2..efc471af7 100644 --- a/polyp/conf.c +++ b/polyp/conf.c @@ -27,12 +27,34 @@ #include #include #include -#include +#include +#include #include "conf.h" #include "util.h" #include "xmalloc.h" #include "strbuf.h" +#include "confparser.h" + +#ifndef DEFAULT_SCRIPT_FILE +#define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa" +#endif + +#ifndef DEFAULT_SCRIPT_FILE_USER +#define DEFAULT_SCRIPT_FILE_USER ".polypaudio/default.pa" +#endif + +#ifndef DEFAULT_CONFIG_FILE +#define DEFAULT_CONFIG_FILE "/etc/polypaudio/daemon.conf" +#endif + +#ifndef DEFAULT_CONFIG_FILE_USER +#define DEFAULT_CONFIG_FILE_USER ".polypaudio/daemon.conf" +#endif + +#define ENV_SCRIPT_FILE "POLYP_SCRIPT" +#define ENV_CONFIG_FILE "POLYP_CONFIG" +#define ENV_DL_SEARCH_PATH "POLYP_DLPATH" static const struct pa_conf default_conf = { .cmd = PA_CMD_DAEMON, @@ -49,28 +71,9 @@ static const struct pa_conf default_conf = { .dl_search_path = NULL, .default_script_file = NULL, .log_target = PA_LOG_SYSLOG, + .resample_method = SRC_SINC_FASTEST }; -#define ENV_SCRIPT_FILE "POLYP_SCRIPT" -#define ENV_CONFIG_FILE "POLYP_CONFIG" -#define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED" - -#ifndef DEFAULT_SCRIPT_FILE -#define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa" -#endif - -#ifndef DEFAULT_CONFIG_FILE -#define DEFAULT_CONFIG_FILE "/etc/polypaudio/default.conf" -#endif - -#ifndef AUTOSPAWN_CONFIG_FILE -#define AUTOSPAWN_CONFIG_FILE "/etc/polypaudio/autospawn.conf" -#endif - -#define DEFAULT_SCRIPT_FILE_LOCAL ".polypaudio.pa" -#define DEFAULT_CONFIG_FILE_LOCAL ".polypaudio.conf" -#define AUTOSPAWN_CONFIG_FILE_LOCAL ".polypaudio-autospawn.conf" - char* default_file(const char *envvar, const char *global, const char *local) { char *p, *h; @@ -80,9 +83,8 @@ char* default_file(const char *envvar, const char *global, const char *local) { return pa_xstrdup(p); if ((h = getenv("HOME"))) { - struct stat st; p = pa_sprintf_malloc("%s/%s", h, local); - if (stat(p, &st) >= 0) + if (!access(p, F_OK)) return p; pa_xfree(p); @@ -91,26 +93,12 @@ char* default_file(const char *envvar, const char *global, const char *local) { return pa_xstrdup(global); } -char *default_config_file(void) { - char *b; - int autospawned = 0; - - if ((b = getenv(ENV_AUTOSPAWNED))) - autospawned = pa_parse_boolean(b) > 0; - - return default_file(ENV_CONFIG_FILE, - autospawned ? AUTOSPAWN_CONFIG_FILE : DEFAULT_CONFIG_FILE, - autospawned ? AUTOSPAWN_CONFIG_FILE_LOCAL : DEFAULT_CONFIG_FILE_LOCAL); - -} - -char *default_script_file(void) { - return default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_LOCAL); -} - struct pa_conf* pa_conf_new(void) { struct pa_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); - c->default_script_file = default_script_file(); + c->default_script_file = default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER); +#ifdef DLSEARCHPATH + c->dl_search_path = pa_xstrdup(DLSEARCHPATH); +#endif return c; } @@ -122,166 +110,104 @@ void pa_conf_free(struct pa_conf *c) { pa_xfree(c); } -#define WHITESPACE " \t\n" -#define COMMENTS "#;\n" - -#define PARSE_BOOLEAN(t, v) \ - do { \ - if (!strcmp(lvalue, t)) { \ - int b; \ - if ((b = pa_parse_boolean(rvalue)) < 0) \ - goto fail; \ - c->v = b; \ - return 0; \ - } \ - } while (0) - -#define PARSE_STRING(t, v) \ - do { \ - if (!strcmp(lvalue, t)) { \ - pa_xfree(c->v); \ - c->v = *rvalue ? pa_xstrdup(rvalue) : NULL; \ - return 0; \ - } \ - } while (0) - -#define PARSE_INTEGER(t, v) \ - do { \ - if (!strcmp(lvalue, t)) { \ - char *x = NULL; \ - int i = strtol(rvalue, &x, 0); \ - if (!x || *x) \ - goto fail; \ - c->v = i; \ - return 0; \ - } \ - } while(0) - -static int next_assignment(struct pa_conf *c, char *lvalue, char *rvalue, unsigned n) { - PARSE_BOOLEAN("daemonize", daemonize); - PARSE_BOOLEAN("fail", fail); - PARSE_BOOLEAN("verbose", verbose); - PARSE_BOOLEAN("high-priority", high_priority); - PARSE_BOOLEAN("disallow-module-loading", disallow_module_loading); - - PARSE_INTEGER("exit-idle-time", exit_idle_time); - PARSE_INTEGER("module-idle-time", module_idle_time); - PARSE_INTEGER("scache-idle-time", scache_idle_time); +int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { + struct pa_conf *c = data; + assert(filename && lvalue && rvalue && data); - PARSE_STRING("dl-search-path", dl_search_path); - PARSE_STRING("default-script-file", default_script_file); - - if (!strcmp(lvalue, "log-target")) { - if (!strcmp(rvalue, "auto")) - c->auto_log_target = 1; - else if (!strcmp(rvalue, "syslog")) { - c->auto_log_target = 0; - c->log_target = PA_LOG_SYSLOG; - } else if (!strcmp(rvalue, "stderr")) { - c->auto_log_target = 0; - c->log_target = PA_LOG_STDERR; - } else - goto fail; - - return 0; + if (!strcmp(rvalue, "auto")) + c->auto_log_target = 1; + else if (!strcmp(rvalue, "syslog")) { + c->auto_log_target = 0; + c->log_target = PA_LOG_SYSLOG; + } else if (!strcmp(rvalue, "stderr")) { + c->auto_log_target = 0; + c->log_target = PA_LOG_STDERR; + } else { + pa_log(__FILE__": [%s:%u] Invalid log target '%s'.\n", filename, line, rvalue); + return -1; } - -fail: - pa_log(__FILE__": line %u: parse error.\n", n); - return -1; -} - -#undef PARSE_STRING -#undef PARSE_BOOLEAN - -static int in_string(char c, const char *s) { - for (; *s; s++) - if (*s == c) - return 1; return 0; } -static char *strip(char *s) { - char *b = s+strspn(s, WHITESPACE); - char *e, *l = NULL; +int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { + struct pa_conf *c = data; + assert(filename && lvalue && rvalue && data); - for (e = b; *e; e++) - if (!in_string(*e, WHITESPACE)) - l = e; - - if (l) - *(l+1) = 0; - - return b; -} - -static int parse_line(struct pa_conf *conf, char *l, unsigned n) { - char *e, *c, *b = l+strspn(l, WHITESPACE); - - if ((c = strpbrk(b, COMMENTS))) - *c = 0; - - if (!*b) - return 0; - - if (!(e = strchr(b, '='))) { - pa_log(__FILE__": line %u: missing '='.\n", n); + if (!strcmp(rvalue, "sinc-best-quality")) + c->resample_method = SRC_SINC_BEST_QUALITY; + else if (!strcmp(rvalue, "sinc-medium-quality")) + c->resample_method = SRC_SINC_MEDIUM_QUALITY; + else if (!strcmp(rvalue, "sinc-fastest")) + c->resample_method = SRC_SINC_FASTEST; + else if (!strcmp(rvalue, "zero-order-hold")) + c->resample_method = SRC_ZERO_ORDER_HOLD; + else if (!strcmp(rvalue, "linear")) + c->resample_method = SRC_LINEAR; + else { + pa_log(__FILE__": [%s:%u] Inavalid resample method '%s'.\n", filename, line, rvalue); return -1; } - *e = 0; - e++; - - return next_assignment(conf, strip(b), strip(e), n); + return 0; } - int pa_conf_load(struct pa_conf *c, const char *filename) { - FILE *f; - int r = 0; - unsigned n = 0; char *def = NULL; - assert(c); + int r; + const struct pa_config_item table[] = { + { "verbose", pa_config_parse_bool, &c->verbose }, + { "daemonize", pa_config_parse_bool, &c->daemonize }, + { "fail", pa_config_parse_bool, &c->fail }, + { "high-priority", pa_config_parse_bool, &c->high_priority }, + { "disallow-module-loading", pa_config_parse_bool, &c->disallow_module_loading }, + { "exit-idle-time", pa_config_parse_int, &c->exit_idle_time }, + { "module-idle-time", pa_config_parse_int, &c->module_idle_time }, + { "scache-idle-time", pa_config_parse_int, &c->scache_idle_time }, + { "dl-search-path", pa_config_parse_string, &c->dl_search_path }, + { "default-script-file", pa_config_parse_string, &c->default_script_file }, + { "log-target", parse_log_target, c }, + { "resample-method", parse_resample_method, c }, + { NULL, NULL, NULL }, + }; + if (!filename) - filename = def = default_config_file(); - - if (!(f = fopen(filename, "r"))) { - if (errno != ENOENT) - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno)); - - goto finish; - } - - while (!feof(f)) { - char l[256]; - if (!fgets(l, sizeof(l), f)) { - if (!feof(f)) - pa_log(__FILE__": WARNING: failed to read configuration file '%s': %s\n", filename, strerror(errno)); - - break; - } - - if (parse_line(c, l, ++n) < 0) - r = -1; - } - -finish: - - if (f) - fclose(f); + filename = def = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER); + r = pa_config_parse(filename, table, NULL); pa_xfree(def); - return r; } +int pa_conf_env(struct pa_conf *c) { + char *e; + + if ((e = getenv(ENV_DL_SEARCH_PATH))) { + pa_xfree(c->dl_search_path); + c->dl_search_path = pa_xstrdup(e); + } + if ((e = getenv(ENV_SCRIPT_FILE))) { + pa_xfree(c->default_script_file); + c->default_script_file = pa_xstrdup(e); + } + + return 0; +} + char *pa_conf_dump(struct pa_conf *c) { struct pa_strbuf *s = pa_strbuf_new(); char *d; - d = default_config_file(); + static const char const* resample_methods[] = { + "sinc-best-quality", + "sinc-medium-quality", + "sinc-fastest", + "zero-order-hold", + "linear" + }; + + d = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER); pa_strbuf_printf(s, "### Default configuration file: %s ###\n", d); pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose); @@ -295,6 +221,9 @@ char *pa_conf_dump(struct pa_conf *c) { pa_strbuf_printf(s, "dl-search-path = %s\n", c->dl_search_path ? c->dl_search_path : ""); pa_strbuf_printf(s, "default-script-file = %s\n", c->default_script_file); pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); + + assert(c->resample_method <= 4 && c->resample_method >= 0); + pa_strbuf_printf(s, "resample-method = %s\n", resample_methods[c->resample_method]); pa_xfree(d); diff --git a/polyp/conf.h b/polyp/conf.h index dafb3797a..ace5396d4 100644 --- a/polyp/conf.h +++ b/polyp/conf.h @@ -45,6 +45,7 @@ struct pa_conf { auto_log_target; char *script_commands, *dl_search_path, *default_script_file; enum pa_log_target log_target; + int resample_method; }; struct pa_conf* pa_conf_new(void); diff --git a/polyp/config-client.c b/polyp/config-client.c new file mode 100644 index 000000000..758927f3a --- /dev/null +++ b/polyp/config-client.c @@ -0,0 +1,138 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include + +#include "config-client.h" +#include "xmalloc.h" +#include "log.h" +#include "confparser.h" +#include "util.h" + +#ifndef DEFAULT_CLIENT_CONFIG_FILE +#define DEFAULT_CLIENT_CONFIG_FILE "/etc/polypaudio/client.conf" +#endif + +#ifndef DEFAULT_CLIENT_CONFIG_FILE_USER +#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio/client.conf" +#endif + +#define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG" +#define ENV_DEFAULT_SINK "POLYP_SINK" +#define ENV_DEFAULT_SOURCE "POLYP_SOURCE" +#define ENV_DEFAULT_SERVER "POLYP_SERVER" +#define ENV_DAEMON_BINARY "POLYP_BINARY" + + +static const struct pa_client_conf default_conf = { + .daemon_binary = NULL, + .extra_arguments = NULL, + .default_sink = NULL, + .default_source = NULL, + .default_server = NULL, + .autospawn = 0 +}; + +struct pa_client_conf *pa_client_conf_new(void) { + struct pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); + + c->daemon_binary = pa_xstrdup(POLYPAUDIO_BINARY); + c->extra_arguments = pa_xstrdup("--daemonize=yes --log-target=syslog"); + + return c; +} + +void pa_client_conf_free(struct pa_client_conf *c) { + assert(c); + pa_xfree(c->daemon_binary); + pa_xfree(c->extra_arguments); + pa_xfree(c->default_sink); + pa_xfree(c->default_source); + pa_xfree(c->default_server); + pa_xfree(c); +} +int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { + char *def = NULL; + int r; + + const struct pa_config_item table[] = { + { "daemon-binary", pa_config_parse_string, &c->daemon_binary }, + { "extra-arguments", pa_config_parse_string, &c->extra_arguments }, + { "default-sink", pa_config_parse_string, &c->default_sink }, + { "default-source", pa_config_parse_string, &c->default_source }, + { "default-server", pa_config_parse_string, &c->default_server }, + { "autospawn", pa_config_parse_bool, &c->autospawn }, + { NULL, NULL, NULL }, + }; + + if (!filename) + filename = getenv(ENV_CLIENT_CONFIG_FILE); + + if (!filename) { + char *h; + + if ((h = getenv("HOME"))) { + def = pa_sprintf_malloc("%s/%s", h, DEFAULT_CLIENT_CONFIG_FILE_USER); + + if (!access(def, F_OK)) + filename = def; + else { + pa_xfree(def); + def = NULL; + } + } + } + + if (!filename) + filename = DEFAULT_CLIENT_CONFIG_FILE; + + r = pa_config_parse(filename, table, NULL); + pa_xfree(def); + return r; +} + +int pa_client_conf_env(struct pa_client_conf *c) { + char *e; + + if ((e = getenv(ENV_DEFAULT_SINK))) { + pa_xfree(c->default_sink); + c->default_sink = pa_xstrdup(e); + } + + if ((e = getenv(ENV_DEFAULT_SOURCE))) { + pa_xfree(c->default_source); + c->default_source = pa_xstrdup(e); + } + + if ((e = getenv(ENV_DEFAULT_SERVER))) { + pa_xfree(c->default_server); + c->default_server = pa_xstrdup(e); + } + + if ((e = getenv(ENV_DAEMON_BINARY))) { + pa_xfree(c->daemon_binary); + c->daemon_binary = pa_xstrdup(e); + } + + return 0; +} diff --git a/polyp/config-client.h b/polyp/config-client.h new file mode 100644 index 000000000..1b1c519dd --- /dev/null +++ b/polyp/config-client.h @@ -0,0 +1,36 @@ +#ifndef fooconfigclienthfoo +#define fooconfigclienthfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +struct pa_client_conf { + char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server; + int autospawn; +}; + +struct pa_client_conf *pa_client_conf_new(void); +void pa_client_conf_free(struct pa_client_conf *c); + +int pa_client_conf_load(struct pa_client_conf *c, const char *filename); +int pa_client_conf_env(struct pa_client_conf *c); + +#endif diff --git a/polyp/confparser.c b/polyp/confparser.c new file mode 100644 index 000000000..8f551b954 --- /dev/null +++ b/polyp/confparser.c @@ -0,0 +1,168 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include + +#include "confparser.h" +#include "log.h" +#include "util.h" +#include "xmalloc.h" + +#define WHITESPACE " \t\n" +#define COMMENTS "#;\n" + +static int next_assignment(const char *filename, unsigned line, const struct pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) { + assert(filename && t && lvalue && rvalue); + + for (; t->parse; t++) + if (!strcmp(lvalue, t->lvalue)) + return t->parse(filename, line, lvalue, rvalue, t->data, userdata); + + pa_log(__FILE__": [%s:%u] Unknown lvalue '%s'.\n", filename, line, lvalue); + + return -1; +} + +static int in_string(char c, const char *s) { + assert(s); + + for (; *s; s++) + if (*s == c) + return 1; + + return 0; +} + +static char *strip(char *s) { + char *b = s+strspn(s, WHITESPACE); + char *e, *l = NULL; + + for (e = b; *e; e++) + if (!in_string(*e, WHITESPACE)) + l = e; + + if (l) + *(l+1) = 0; + + return b; +} + +static int parse_line(const char *filename, unsigned line, const struct pa_config_item *t, char *l, void *userdata) { + char *e, *c, *b = l+strspn(l, WHITESPACE); + + if ((c = strpbrk(b, COMMENTS))) + *c = 0; + + if (!*b) + return 0; + + if (!(e = strchr(b, '='))) { + pa_log(__FILE__": [%s:%u] Missing '='.\n", filename, line); + return -1; + } + + *e = 0; + e++; + + return next_assignment(filename, line, t, strip(b), strip(e), userdata); +} + + +int pa_config_parse(const char *filename, const struct pa_config_item *t, void *userdata) { + FILE *f; + int r = -1; + unsigned line = 0; + assert(filename && t); + + if (!(f = fopen(filename, "r"))) { + if (errno == ENOENT) { + r = 0; + goto finish; + } + + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno)); + goto finish; + } + + while (!feof(f)) { + char l[256]; + if (!fgets(l, sizeof(l), f)) { + if (feof(f)) + break; + + pa_log(__FILE__": WARNING: failed to read configuration file '%s': %s\n", filename, strerror(errno)); + goto finish; + } + + if (parse_line(filename, ++line, t, l, userdata) < 0) + goto finish; + } + + r = 0; + +finish: + + if (f) + fclose(f); + + return r; +} + +int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { + int *i = data, k; + char *x = NULL; + assert(filename && lvalue && rvalue && data); + + k = strtol(rvalue, &x, 0); + if (!*rvalue || !x || *x) { + pa_log(__FILE__": [%s:%u] Failed to parse numeric value: %s\n", filename, line, rvalue); + return -1; + } + + *i = k; + return 0; +} + +int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { + int *b = data, k; + assert(filename && lvalue && rvalue && data); + + if ((k = pa_parse_boolean(rvalue)) < 0) { + pa_log(__FILE__": [%s:%u] Failed to parse boolean value: %s\n", filename, line, rvalue); + return -1; + } + + *b = k; + + return 0; +} + +int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { + char **s = data; + assert(filename && lvalue && rvalue && data); + + pa_xfree(*s); + *s = *rvalue ? pa_xstrdup(rvalue) : NULL; + return 0; +} diff --git a/polyp/confparser.h b/polyp/confparser.h new file mode 100644 index 000000000..a0eb52d0d --- /dev/null +++ b/polyp/confparser.h @@ -0,0 +1,37 @@ +#ifndef fooconfparserhfoo +#define fooconfparserhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +struct pa_config_item { + const char *lvalue; + int (*parse)(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); + void *data; +}; + +int pa_config_parse(const char *filename, const struct pa_config_item *t, void *userdata); + +int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); + +#endif diff --git a/polyp/core.c b/polyp/core.c index 58035087a..cf2d383c4 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "core.h" #include "module.h" @@ -79,6 +80,8 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->exit_idle_time = -1; c->module_idle_time = 20; c->scache_idle_time = 20; + + c->resample_method = SRC_SINC_FASTEST; pa_check_signal_is_blocked(SIGPIPE); diff --git a/polyp/core.h b/polyp/core.h index 980888f62..62959d0af 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -53,6 +53,8 @@ struct pa_core { struct pa_time_event *quit_event; struct pa_time_event *scache_auto_unload_event; + + int resample_method; }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/polyp/config b/polyp/daemon.conf similarity index 73% rename from polyp/config rename to polyp/daemon.conf index b404bc408..a277bb4fd 100644 --- a/polyp/config +++ b/polyp/daemon.conf @@ -17,8 +17,8 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -## Configuration file for polypaudio. Default values are commented out. -## Use either ; or # for commenting +## Configuration file for the polypaudio daemon. Default values are +## commented out. Use either ; or # for commenting # Extra verbositiy ; verbose = 0 @@ -46,16 +46,22 @@ high-priority = 0 ## Unload autoloaded modules after being idle for this time module-idle-time = 20 -## The path were to look for dynamic shared objects (DSOs aka plugins). -## Specify an empty string for the default search path. You may specify -## more than one path seperated by colons. -; dl-search-path = +## The path were to look for dynamic shared objects (DSOs aka +## plugins). You may specify more than one path seperated by +## colons. +; dl-search-path = @DLSEARCHPATH@ ## The default script file to load. Specify an empty string for not -## loading a default script file -; default-script-file = /etc/polyp/default.pa +## loading a default script file. The +; default-script-file = @DEFAULT_CONFIG_FILE@ ## The default log target. Use either "stderr", "syslog" or ## "auto". The latter is equivalent to "sylog" in case daemonize is ## true, otherwise to "stderr". ; log-target = auto + +## The resampling algorithm to use. Use one of sinc-best-quality, +## sinc-medium-quality, sinc-fastest, zero-order-hold, linear. See +## the documentation of libsamplerate for an explanation fot the +## different methods. +; resample-method = sinc-fastest diff --git a/polyp/main.c b/polyp/main.c index e44fc0134..3b25a030e 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -119,10 +119,6 @@ int main(int argc, char *argv[]) { if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); -#ifdef DLSEARCHPATH - else - lt_dlsetsearchpath(DLSEARCHPATH); -#endif switch (conf->cmd) { case PA_CMD_DUMP_MODULES: @@ -245,6 +241,8 @@ int main(int argc, char *argv[]) { c->disallow_module_loading = conf->disallow_module_loading; c->exit_idle_time = conf->exit_idle_time; c->module_idle_time = conf->module_idle_time; + c->scache_idle_time = conf->scache_idle_time; + c->resample_method = conf->resample_method; pa_log(__FILE__": Daemon startup complete.\n"); if (pa_mainloop_run(mainloop, &retval) < 0) diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 64f9074c7..04ee3d897 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -47,6 +47,9 @@ #include "util.h" #include "xmalloc.h" #include "log.h" +#include "config-client.h" + +#define DEFAULT_SERVER "/tmp/polypaudio/native" static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = { pa_command_request }, @@ -87,6 +90,11 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->local = -1; pa_check_signal_is_blocked(SIGPIPE); + + c->conf = pa_client_conf_new(); + pa_client_conf_load(c->conf, NULL); + pa_client_conf_env(c->conf); + return c; } @@ -114,6 +122,9 @@ static void context_free(struct pa_context *c) { pa_dynarray_free(c->playback_streams, NULL, NULL); pa_memblock_stat_unref(c->memblock_stat); + + if (c->conf) + pa_client_conf_free(c->conf); pa_xfree(c->name); pa_xfree(c); @@ -366,7 +377,7 @@ static struct sockaddr *resolve_server(const char *server, size_t *len) { return sa; } -static int is_running(void) { +static int default_server_is_running(void) { struct stat st; if (DEFAULT_SERVER[0] != '/') @@ -404,24 +415,39 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api goto fail; } else if (!pid) { - char t[128]; - char *p; /* Child */ + + char t[128]; + const char *state = NULL; +#define MAX_ARGS 64 + char *argv[MAX_ARGS+1]; + int n = 0; close(fds[0]); if (api && api->atfork) api->atfork(); - if (!(p = getenv(ENV_DEFAULT_BINARY))) - p = POLYPAUDIO_BINARY; - snprintf(t, sizeof(t), "%s=1", ENV_AUTOSPAWNED); - putenv(t); - + putenv(t); + + argv[n++] = c->conf->daemon_binary; + snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); - execl(p, p, "--daemonize=yes", "--log-target=syslog", t, NULL); - + argv[n++] = pa_xstrdup(t); + + while (n < MAX_ARGS) { + char *a; + + if (!(a = pa_split_spaces(c->conf->extra_arguments, &state))) + break; + + argv[n++] = a; + } + + argv[n++] = NULL; + + execv(argv[0], argv); exit(1); } @@ -468,19 +494,12 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED); if (!server) - if (!(server = getenv(ENV_DEFAULT_SERVER))) { - if (spawn && !is_running()) { - char *b; - - if ((b = getenv(ENV_DISABLE_AUTOSPAWN))) - if (pa_parse_boolean(b) > 1) - return -1; - - return context_connect_spawn(c, api); - } + server = c->conf->default_server; - server = DEFAULT_SERVER; - } + if (!server && spawn && c->conf->autospawn && !default_server_is_running()) + return context_connect_spawn(c, api); + + server = DEFAULT_SERVER; pa_context_ref(c); diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 4c44ee98d..1d0e41d8a 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -33,6 +33,7 @@ #include "polyplib-operation.h" #include "llist.h" #include "native-common.h" +#include "config-client.h" #define DEFAULT_TLENGTH (10240*8) #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) @@ -41,14 +42,8 @@ #define DEFAULT_FRAGSIZE 1024 #define DEFAULT_TIMEOUT (5*60) -#define DEFAULT_SERVER "/tmp/polypaudio/native" #define DEFAULT_PORT "4713" -#define ENV_DEFAULT_SINK "POLYP_SINK" -#define ENV_DEFAULT_SOURCE "POLYP_SOURCE" -#define ENV_DEFAULT_SERVER "POLYP_SERVER" -#define ENV_DEFAULT_BINARY "POLYP_BINARY" -#define ENV_DISABLE_AUTOSPAWN "POLYP_NOAUTOSPAWN" #define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED" struct pa_context { @@ -80,6 +75,8 @@ struct pa_context { struct pa_memblock_stat *memblock_stat; int local; + + struct pa_client_conf *conf; }; struct pa_stream { diff --git a/polyp/polyplib-scache.c b/polyp/polyplib-scache.c index 8215eaec1..7221420c8 100644 --- a/polyp/polyplib-scache.c +++ b/polyp/polyplib-scache.c @@ -88,7 +88,7 @@ struct pa_operation * pa_context_play_sample(struct pa_context *c, const char *n o->userdata = userdata; if (!dev) - dev = getenv(ENV_DEFAULT_SINK); + dev = c->conf->default_sink; t = pa_tagstruct_new(NULL, 0); assert(t); diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 532d1700f..6055a2204 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -217,7 +217,7 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED); pa_stream_ref(s); - + if (attr) s->buffer_attr = *attr; else { @@ -235,9 +235,9 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ if (!dev) { if (s->direction == PA_STREAM_PLAYBACK) - dev = getenv(ENV_DEFAULT_SINK); + dev = s->context->conf->default_sink; else - dev = getenv(ENV_DEFAULT_SOURCE); + dev = s->context->conf->default_source; } pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); diff --git a/polyp/resampler.c b/polyp/resampler.c index 4742ce212..e8dd01b9f 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -47,7 +47,7 @@ struct pa_resampler { struct pa_memblock_stat *memblock_stat; }; -struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s) { +struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, int resample_method) { struct pa_resampler *r = NULL; int err; assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b)); @@ -67,7 +67,7 @@ struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const stru r->i_buf = r->o_buf = NULL; r->i_alloc = r->o_alloc = 0; - r->src_state = src_new(SRC_SINC_FASTEST, r->channels, &err); + r->src_state = src_new(resample_method, r->channels, &err); if (err != 0 || !r->src_state) goto fail; diff --git a/polyp/resampler.h b/polyp/resampler.h index a6ef30dff..b984a4f6d 100644 --- a/polyp/resampler.h +++ b/polyp/resampler.h @@ -28,7 +28,7 @@ struct pa_resampler; -struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s); +struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, int resample_method); void pa_resampler_free(struct pa_resampler *r); size_t pa_resampler_request(struct pa_resampler *r, size_t out_length); diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 2541c8217..486a20443 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -49,7 +49,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con } if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec)) - if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat))) + if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat, s->core->resample_method))) return NULL; i = pa_xmalloc(sizeof(struct pa_sink_input)); diff --git a/polyp/source-output.c b/polyp/source-output.c index 1db88d3cc..252c155cf 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -45,7 +45,7 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n } if (!pa_sample_spec_equal(&s->sample_spec, spec)) - if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat))) + if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat, s->core->resample_method))) return NULL; o = pa_xmalloc(sizeof(struct pa_source_output)); diff --git a/polyp/util.c b/polyp/util.c index 24773a7bc..86f18f258 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -390,6 +390,23 @@ char *pa_split(const char *c, const char *delimiter, const char**state) { return pa_xstrndup(current, l); } +#define WHITESPACE " \t\n" + +char *pa_split_spaces(const char *c, const char **state) { + const char *current = *state ? *state : c; + size_t l; + + if (*current) + return NULL; + + current += strspn(current, WHITESPACE); + l = strcspn(current, WHITESPACE); + + *state = current+l; + + return pa_xstrndup(current, l); +} + const char *pa_strsignal(int sig) { switch(sig) { case SIGINT: return "SIGINT"; diff --git a/polyp/util.h b/polyp/util.h index f5cda2006..07072df6f 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -60,6 +60,7 @@ int pa_fd_set_cloexec(int fd, int b); int pa_parse_boolean(const char *s); char *pa_split(const char *c, const char*delimiters, const char **state); +char *pa_split_spaces(const char *c, const char **state); const char *pa_strsignal(int sig); From 24f378150766faf50445427d6eb02f363a9afc24 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Sep 2004 19:52:38 +0000 Subject: [PATCH 0207/1514] make daemon.conf/client.conf autogenerated git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@211 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 9 ++++++++- polyp/{client.conf => client.conf.in} | 2 +- polyp/{daemon.conf => daemon.conf.in} | 0 3 files changed, 9 insertions(+), 2 deletions(-) rename polyp/{client.conf => client.conf.in} (97%) rename polyp/{daemon.conf => daemon.conf.in} (100%) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index d49c7c481..76f4f2c71 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -32,7 +32,7 @@ AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm -EXTRA_DIST = default.pa daemon.conf client.conf config depmod.py esdcompat.sh.in +EXTRA_DIST = default.pa daemon.conf.in client.conf.in config depmod.py esdcompat.sh.in bin_PROGRAMS = polypaudio pacat pactl bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ @@ -541,6 +541,13 @@ esdcompat.sh: esdcompat.sh.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ + +client.conf: client.conf.in Makefile + sed -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ + +daemon.conf: daemon.conf.in Makefile + sed -e 's,@DLSEARCHPATH\@,$(modlibdir),g' \ + -e 's,@DEFAULT_CONFIG_FILE\@,$(polypconfdir)/daemon.conf,g' < $< > $@ install-exec-hook: chown root:root $(DESTDIR)$(bindir)/polypaudio diff --git a/polyp/client.conf b/polyp/client.conf.in similarity index 97% rename from polyp/client.conf rename to polyp/client.conf.in index 070d75bd2..7ba6549be 100644 --- a/polyp/client.conf +++ b/polyp/client.conf.in @@ -21,7 +21,7 @@ ## commented out. Use either ; or # for commenting ## Path to the polypaudio daemon to run when autospawning. -; daemon_binary = @POLYPAUDIO_BINARY +; daemon_binary = @POLYPAUDIO_BINARY@ ## Extra arguments to pass to the polypaudio daemon ; extra_arguments = --daemonize=yes --log-target=syslog diff --git a/polyp/daemon.conf b/polyp/daemon.conf.in similarity index 100% rename from polyp/daemon.conf rename to polyp/daemon.conf.in From f0779587478f5c4012dc5c9debc8dc562c81f967 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Sep 2004 20:06:17 +0000 Subject: [PATCH 0208/1514] rename some stuff git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@212 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 4 ++-- polyp/{config-client.c => client-conf.c} | 2 +- polyp/{config-client.h => client-conf.h} | 4 ++-- polyp/cmdline.c | 2 +- polyp/cmdline.h | 4 ++-- polyp/{conf.c => daemon-conf.c} | 20 ++++++++++---------- polyp/{conf.h => daemon-conf.h} | 19 ++++++++++--------- polyp/dumpmodules.c | 4 ++-- polyp/dumpmodules.h | 4 ++-- polyp/main.c | 15 +++++++++------ polyp/polyplib-context.c | 2 +- polyp/polyplib-internal.h | 2 +- 12 files changed, 43 insertions(+), 39 deletions(-) rename polyp/{config-client.c => client-conf.c} (99%) rename polyp/{config-client.h => client-conf.h} (95%) rename polyp/{conf.c => daemon-conf.c} (93%) rename polyp/{conf.h => daemon-conf.h} (74%) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 76f4f2c71..9dde211d9 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -157,7 +157,7 @@ polypaudio_SOURCES = idxset.c idxset.h \ log.c log.h \ gcc-printf.h \ modinfo.c modinfo.h \ - conf.c conf.h \ + daemon-conf.c daemon-conf.h \ dumpmodules.c dumpmodules.h \ conparser.h confparser.c @@ -334,7 +334,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ llist.h \ log.c log.h \ gcc-printf.h \ - config-client.c config-client.h \ + client-conf.c client-conf.h \ confparser.c confparser.h libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) diff --git a/polyp/config-client.c b/polyp/client-conf.c similarity index 99% rename from polyp/config-client.c rename to polyp/client-conf.c index 758927f3a..cfc257c64 100644 --- a/polyp/config-client.c +++ b/polyp/client-conf.c @@ -23,7 +23,7 @@ #include #include -#include "config-client.h" +#include "client-conf.h" #include "xmalloc.h" #include "log.h" #include "confparser.h" diff --git a/polyp/config-client.h b/polyp/client-conf.h similarity index 95% rename from polyp/config-client.h rename to polyp/client-conf.h index 1b1c519dd..6fd4a20d7 100644 --- a/polyp/config-client.h +++ b/polyp/client-conf.h @@ -1,5 +1,5 @@ -#ifndef fooconfigclienthfoo -#define fooconfigclienthfoo +#ifndef fooclientconfhfoo +#define fooclientconfhfoo /* $Id$ */ diff --git a/polyp/cmdline.c b/polyp/cmdline.c index d429256f7..7f8a947b7 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -107,7 +107,7 @@ void pa_cmdline_help(const char *argv0) { " -n Don't load default script file\n", e); } -int pa_cmdline_parse(struct pa_conf *conf, int argc, char *const argv [], int *d) { +int pa_cmdline_parse(struct pa_daemon_conf *conf, int argc, char *const argv [], int *d) { struct pa_strbuf *buf = NULL; int c; assert(conf && argc && argv); diff --git a/polyp/cmdline.h b/polyp/cmdline.h index e4bd8af6a..bfbae4707 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -22,9 +22,9 @@ USA. ***/ -#include "conf.h" +#include "daemon-conf.h" -int pa_cmdline_parse(struct pa_conf*c, int argc, char *const argv [], int *d); +int pa_cmdline_parse(struct pa_daemon_conf*c, int argc, char *const argv [], int *d); void pa_cmdline_help(const char *argv0); diff --git a/polyp/conf.c b/polyp/daemon-conf.c similarity index 93% rename from polyp/conf.c rename to polyp/daemon-conf.c index efc471af7..72ded989f 100644 --- a/polyp/conf.c +++ b/polyp/daemon-conf.c @@ -30,7 +30,7 @@ #include #include -#include "conf.h" +#include "daemon-conf.h" #include "util.h" #include "xmalloc.h" #include "strbuf.h" @@ -56,7 +56,7 @@ #define ENV_CONFIG_FILE "POLYP_CONFIG" #define ENV_DL_SEARCH_PATH "POLYP_DLPATH" -static const struct pa_conf default_conf = { +static const struct pa_daemon_conf default_conf = { .cmd = PA_CMD_DAEMON, .daemonize = 0, .fail = 1, @@ -93,8 +93,8 @@ char* default_file(const char *envvar, const char *global, const char *local) { return pa_xstrdup(global); } -struct pa_conf* pa_conf_new(void) { - struct pa_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); +struct pa_daemon_conf* pa_daemon_conf_new(void) { + struct pa_daemon_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); c->default_script_file = default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER); #ifdef DLSEARCHPATH c->dl_search_path = pa_xstrdup(DLSEARCHPATH); @@ -102,7 +102,7 @@ struct pa_conf* pa_conf_new(void) { return c; } -void pa_conf_free(struct pa_conf *c) { +void pa_daemon_conf_free(struct pa_daemon_conf *c) { assert(c); pa_xfree(c->script_commands); pa_xfree(c->dl_search_path); @@ -111,7 +111,7 @@ void pa_conf_free(struct pa_conf *c) { } int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { - struct pa_conf *c = data; + struct pa_daemon_conf *c = data; assert(filename && lvalue && rvalue && data); if (!strcmp(rvalue, "auto")) @@ -131,7 +131,7 @@ int parse_log_target(const char *filename, unsigned line, const char *lvalue, co } int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { - struct pa_conf *c = data; + struct pa_daemon_conf *c = data; assert(filename && lvalue && rvalue && data); if (!strcmp(rvalue, "sinc-best-quality")) @@ -152,7 +152,7 @@ int parse_resample_method(const char *filename, unsigned line, const char *lvalu return 0; } -int pa_conf_load(struct pa_conf *c, const char *filename) { +int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename) { char *def = NULL; int r; @@ -180,7 +180,7 @@ int pa_conf_load(struct pa_conf *c, const char *filename) { return r; } -int pa_conf_env(struct pa_conf *c) { +int pa_daemon_conf_env(struct pa_daemon_conf *c) { char *e; if ((e = getenv(ENV_DL_SEARCH_PATH))) { @@ -195,7 +195,7 @@ int pa_conf_env(struct pa_conf *c) { return 0; } -char *pa_conf_dump(struct pa_conf *c) { +char *pa_daemon_conf_dump(struct pa_daemon_conf *c) { struct pa_strbuf *s = pa_strbuf_new(); char *d; diff --git a/polyp/conf.h b/polyp/daemon-conf.h similarity index 74% rename from polyp/conf.h rename to polyp/daemon-conf.h index ace5396d4..c987a6d5f 100644 --- a/polyp/conf.h +++ b/polyp/daemon-conf.h @@ -1,5 +1,5 @@ -#ifndef fooconfhfoo -#define fooconfhfoo +#ifndef foodaemonconfhfoo +#define foodaemonconfhfoo /* $Id$ */ @@ -24,7 +24,7 @@ #include "log.h" -enum pa_conf_cmd { +enum pa_daemon_conf_cmd { PA_CMD_DAEMON, PA_CMD_HELP, PA_CMD_VERSION, @@ -32,8 +32,8 @@ enum pa_conf_cmd { PA_CMD_DUMP_MODULES }; -struct pa_conf { - enum pa_conf_cmd cmd; +struct pa_daemon_conf { + enum pa_daemon_conf_cmd cmd; int daemonize, fail, verbose, @@ -48,10 +48,11 @@ struct pa_conf { int resample_method; }; -struct pa_conf* pa_conf_new(void); -void pa_conf_free(struct pa_conf*c); +struct pa_daemon_conf* pa_daemon_conf_new(void); +void pa_daemon_conf_free(struct pa_daemon_conf*c); -int pa_conf_load(struct pa_conf *c, const char *filename); -char *pa_conf_dump(struct pa_conf *c); +int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename); +char *pa_daemon_conf_dump(struct pa_daemon_conf *c); +int pa_daemon_conf_env(struct pa_daemon_conf *c); #endif diff --git a/polyp/dumpmodules.c b/polyp/dumpmodules.c index ae42d36ec..a9c028258 100644 --- a/polyp/dumpmodules.c +++ b/polyp/dumpmodules.c @@ -78,7 +78,7 @@ static void show_info(const char *name, const char *path, void (*info)(const cha static int callback(const char *path, lt_ptr data) { const char *e; - struct pa_conf *c = (data); + struct pa_daemon_conf *c = (data); if ((e = (const char*) strrchr(path, '/'))) e++; @@ -91,7 +91,7 @@ static int callback(const char *path, lt_ptr data) { return 0; } -void pa_dump_modules(struct pa_conf *c, int argc, char * const argv[]) { +void pa_dump_modules(struct pa_daemon_conf *c, int argc, char * const argv[]) { if (argc > 0) { int i; for (i = 0; i < argc; i++) diff --git a/polyp/dumpmodules.h b/polyp/dumpmodules.h index 6b1bd858b..544c55d25 100644 --- a/polyp/dumpmodules.h +++ b/polyp/dumpmodules.h @@ -22,8 +22,8 @@ USA. ***/ -#include "conf.h" +#include "daemon-conf.h" -void pa_dump_modules(struct pa_conf *c, int argc, char * const argv[]); +void pa_dump_modules(struct pa_daemon_conf *c, int argc, char * const argv[]); #endif diff --git a/polyp/main.c b/polyp/main.c index 3b25a030e..107743881 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -45,7 +45,7 @@ #include "xmalloc.h" #include "cpulimit.h" #include "log.h" -#include "conf.h" +#include "daemon-conf.h" #include "dumpmodules.h" static struct pa_mainloop *mainloop; @@ -90,7 +90,7 @@ static void close_pipe(int p[2]) { int main(int argc, char *argv[]) { struct pa_core *c; struct pa_strbuf *buf = NULL; - struct pa_conf *conf; + struct pa_daemon_conf *conf; char *s; int r, retval = 1, d = 0; int daemon_pipe[2] = { -1, -1 }; @@ -100,11 +100,14 @@ int main(int argc, char *argv[]) { pa_log_set_ident("polypaudio"); - conf = pa_conf_new(); + conf = pa_daemon_conf_new(); - if (pa_conf_load(conf, NULL) < 0) + if (pa_daemon_conf_load(conf, NULL) < 0) goto finish; + if (pa_daemon_conf_env(conf) < 0) + goto finish; + if (pa_cmdline_parse(conf, argc, argv, &d) < 0) { pa_log(__FILE__": failed to parse command line.\n"); goto finish; @@ -127,7 +130,7 @@ int main(int argc, char *argv[]) { goto finish; case PA_CMD_DUMP_CONF: { - char *s = pa_conf_dump(conf); + char *s = pa_daemon_conf_dump(conf); fputs(s, stdout); pa_xfree(s); retval = 0; @@ -261,7 +264,7 @@ int main(int argc, char *argv[]) { finish: if (conf) - pa_conf_free(conf); + pa_daemon_conf_free(conf); close_pipe(daemon_pipe); diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 04ee3d897..4ed15c4ba 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -47,7 +47,7 @@ #include "util.h" #include "xmalloc.h" #include "log.h" -#include "config-client.h" +#include "client-conf.h" #define DEFAULT_SERVER "/tmp/polypaudio/native" diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 1d0e41d8a..6e64755db 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -33,7 +33,7 @@ #include "polyplib-operation.h" #include "llist.h" #include "native-common.h" -#include "config-client.h" +#include "client-conf.h" #define DEFAULT_TLENGTH (10240*8) #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) From 95612b6b1c01ab62b1dd8d51a9d62d4e502cef11 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Sep 2004 20:08:52 +0000 Subject: [PATCH 0209/1514] rename some more git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@213 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 6 +++--- polyp/client-conf.c | 2 +- polyp/{confparser.c => conf-parser.c} | 2 +- polyp/{confparser.h => conf-parser.h} | 0 polyp/daemon-conf.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) rename polyp/{confparser.c => conf-parser.c} (99%) rename polyp/{confparser.h => conf-parser.h} (100%) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 9dde211d9..7efb46c7d 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -159,7 +159,7 @@ polypaudio_SOURCES = idxset.c idxset.h \ modinfo.c modinfo.h \ daemon-conf.c daemon-conf.h \ dumpmodules.c dumpmodules.h \ - conparser.h confparser.c + conf-parser.h conf-parser.c polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) @@ -334,8 +334,8 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ llist.h \ log.c log.h \ gcc-printf.h \ - client-conf.c client-conf.h \ - confparser.c confparser.h + client-conf.c client-conf.h \ + conf-parser.c conf-parser.h libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 diff --git a/polyp/client-conf.c b/polyp/client-conf.c index cfc257c64..d904cb49d 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -26,7 +26,7 @@ #include "client-conf.h" #include "xmalloc.h" #include "log.h" -#include "confparser.h" +#include "conf-parser.h" #include "util.h" #ifndef DEFAULT_CLIENT_CONFIG_FILE diff --git a/polyp/confparser.c b/polyp/conf-parser.c similarity index 99% rename from polyp/confparser.c rename to polyp/conf-parser.c index 8f551b954..20e8e723b 100644 --- a/polyp/confparser.c +++ b/polyp/conf-parser.c @@ -24,7 +24,7 @@ #include #include -#include "confparser.h" +#include "conf-parser.h" #include "log.h" #include "util.h" #include "xmalloc.h" diff --git a/polyp/confparser.h b/polyp/conf-parser.h similarity index 100% rename from polyp/confparser.h rename to polyp/conf-parser.h diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index 72ded989f..a31853644 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -34,7 +34,7 @@ #include "util.h" #include "xmalloc.h" #include "strbuf.h" -#include "confparser.h" +#include "conf-parser.h" #ifndef DEFAULT_SCRIPT_FILE #define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa" From 08953564bb85356869a1f043b82d1f365c8729a1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Sep 2004 20:43:40 +0000 Subject: [PATCH 0210/1514] add --resample-method argument git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@214 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 5 +--- polyp/client-conf.c | 2 +- polyp/client.conf.in | 10 +++---- polyp/cmdline.c | 22 ++++++++------- polyp/daemon-conf.c | 61 ++++++++++++++++++++++++++-------------- polyp/daemon-conf.h | 3 ++ polyp/polyplib-context.c | 7 +++-- polyp/util.c | 2 +- 8 files changed, 67 insertions(+), 45 deletions(-) diff --git a/doc/todo b/doc/todo index fe06df780..53d4ca56b 100644 --- a/doc/todo +++ b/doc/todo @@ -2,10 +2,7 @@ *** 0.5 *** - more complete pactl/parec -- fix tcp/native in regard to latencies -- add client config file -- remove autospawn stuff in conf.c -- make resampler configurable +- fix tcp/native in regard to latencies (i.e. latency interpolation) *** 0.6 **** - per-channel volume diff --git a/polyp/client-conf.c b/polyp/client-conf.c index d904cb49d..c43788fe5 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -57,7 +57,7 @@ struct pa_client_conf *pa_client_conf_new(void) { struct pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); c->daemon_binary = pa_xstrdup(POLYPAUDIO_BINARY); - c->extra_arguments = pa_xstrdup("--daemonize=yes --log-target=syslog"); + c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5"); return c; } diff --git a/polyp/client.conf.in b/polyp/client.conf.in index 7ba6549be..640e26901 100644 --- a/polyp/client.conf.in +++ b/polyp/client.conf.in @@ -21,19 +21,19 @@ ## commented out. Use either ; or # for commenting ## Path to the polypaudio daemon to run when autospawning. -; daemon_binary = @POLYPAUDIO_BINARY@ +; daemon-binary = @POLYPAUDIO_BINARY@ ## Extra arguments to pass to the polypaudio daemon -; extra_arguments = --daemonize=yes --log-target=syslog +; extra-arguments = --log-target=syslog --exit-idle-time=5 ## The default sink to connect to -; default_sink = +; default-sink = ## The default source to connect to -; default_source = +; default-source = ## The default sever to connect to -; default_server = +; default-server = ## Autospawn daemons? ; autospawn = 0 diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 7f8a947b7..a5bb8101f 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -52,6 +52,7 @@ enum { ARG_LOAD, ARG_FILE, ARG_DL_SEARCH_PATH, + ARG_RESAMPLE_METHOD }; static struct option long_options[] = { @@ -71,6 +72,7 @@ static struct option long_options[] = { {"load", 1, 0, ARG_LOAD}, {"file", 1, 0, ARG_FILE}, {"dl-search-path", 1, 0, ARG_DL_SEARCH_PATH}, + {"resample-method", 1, 0, ARG_RESAMPLE_METHOD}, {NULL, 0, 0, 0} }; @@ -98,7 +100,8 @@ void pa_cmdline_help(const char *argv0) { " --module-idle-time=SECS Unload autoloaded modules when idle and this time passed\n" " --scache-idle-time=SECS Unload autoloaded samples when idle and this time passed\n" " --log-target={auto,syslog,stderr} Specify the log target\n" - " -p, --dl-search-path=PATH Set the search path for dynamic shared objects (plugins)\n\n" + " -p, --dl-search-path=PATH Set the search path for dynamic shared objects (plugins)\n" + " --resample-method=[METHOD] Use the specified resampling method\n\n" " -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with the specified argument\n" " -F, --file=FILENAME Run the specified script\n" @@ -198,15 +201,7 @@ int pa_cmdline_parse(struct pa_daemon_conf *conf, int argc, char *const argv [], break; case ARG_LOG_TARGET: - if (!strcmp(optarg, "syslog")) { - conf->auto_log_target = 0; - conf->log_target = PA_LOG_SYSLOG; - } else if (!strcmp(optarg, "stderr")) { - conf->auto_log_target = 0; - conf->log_target = PA_LOG_STDERR; - } else if (!strcmp(optarg, "auto")) - conf->auto_log_target = 1; - else { + if (pa_daemon_conf_set_log_target(conf, optarg) < 0) { pa_log(__FILE__": Invalid log target: use either 'syslog', 'stderr' or 'auto'.\n"); goto fail; } @@ -223,6 +218,13 @@ int pa_cmdline_parse(struct pa_daemon_conf *conf, int argc, char *const argv [], case ARG_SCACHE_IDLE_TIME: conf->scache_idle_time = atoi(optarg); break; + + case ARG_RESAMPLE_METHOD: + if (pa_daemon_conf_set_resample_method(conf, optarg) < 0) { + pa_log(__FILE__": Invalid resample method '%s'.\n", optarg); + goto fail; + } + break; default: goto fail; diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index a31853644..6dcd540d9 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -110,19 +110,48 @@ void pa_daemon_conf_free(struct pa_daemon_conf *c) { pa_xfree(c); } +int pa_daemon_conf_set_log_target(struct pa_daemon_conf *c, const char *string) { + assert(c && string); + + if (!strcmp(string, "auto")) + c->auto_log_target = 1; + else if (!strcmp(string, "syslog")) { + c->auto_log_target = 0; + c->log_target = PA_LOG_SYSLOG; + } else if (!strcmp(string, "stderr")) { + c->auto_log_target = 0; + c->log_target = PA_LOG_STDERR; + } else + return -1; + + return 0; + +} + +int pa_daemon_conf_set_resample_method(struct pa_daemon_conf *c, const char *string) { + assert(c && string); + + if (!strcmp(string, "sinc-best-quality")) + c->resample_method = SRC_SINC_BEST_QUALITY; + else if (!strcmp(string, "sinc-medium-quality")) + c->resample_method = SRC_SINC_MEDIUM_QUALITY; + else if (!strcmp(string, "sinc-fastest")) + c->resample_method = SRC_SINC_FASTEST; + else if (!strcmp(string, "zero-order-hold")) + c->resample_method = SRC_ZERO_ORDER_HOLD; + else if (!strcmp(string, "linear")) + c->resample_method = SRC_LINEAR; + else + return -1; + + return 0; +} + int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { struct pa_daemon_conf *c = data; assert(filename && lvalue && rvalue && data); - - if (!strcmp(rvalue, "auto")) - c->auto_log_target = 1; - else if (!strcmp(rvalue, "syslog")) { - c->auto_log_target = 0; - c->log_target = PA_LOG_SYSLOG; - } else if (!strcmp(rvalue, "stderr")) { - c->auto_log_target = 0; - c->log_target = PA_LOG_STDERR; - } else { + + if (pa_daemon_conf_set_log_target(c, rvalue) < 0) { pa_log(__FILE__": [%s:%u] Invalid log target '%s'.\n", filename, line, rvalue); return -1; } @@ -134,17 +163,7 @@ int parse_resample_method(const char *filename, unsigned line, const char *lvalu struct pa_daemon_conf *c = data; assert(filename && lvalue && rvalue && data); - if (!strcmp(rvalue, "sinc-best-quality")) - c->resample_method = SRC_SINC_BEST_QUALITY; - else if (!strcmp(rvalue, "sinc-medium-quality")) - c->resample_method = SRC_SINC_MEDIUM_QUALITY; - else if (!strcmp(rvalue, "sinc-fastest")) - c->resample_method = SRC_SINC_FASTEST; - else if (!strcmp(rvalue, "zero-order-hold")) - c->resample_method = SRC_ZERO_ORDER_HOLD; - else if (!strcmp(rvalue, "linear")) - c->resample_method = SRC_LINEAR; - else { + if (pa_daemon_conf_set_resample_method(c, rvalue) < 0) { pa_log(__FILE__": [%s:%u] Inavalid resample method '%s'.\n", filename, line, rvalue); return -1; } diff --git a/polyp/daemon-conf.h b/polyp/daemon-conf.h index c987a6d5f..8be989da1 100644 --- a/polyp/daemon-conf.h +++ b/polyp/daemon-conf.h @@ -55,4 +55,7 @@ int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename); char *pa_daemon_conf_dump(struct pa_daemon_conf *c); int pa_daemon_conf_env(struct pa_daemon_conf *c); +int pa_daemon_conf_set_log_target(struct pa_daemon_conf *c, const char *string); +int pa_daemon_conf_set_resample_method(struct pa_daemon_conf *c, const char *string); + #endif diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 4ed15c4ba..8f6ce6a8c 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -432,16 +432,17 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api putenv(t); argv[n++] = c->conf->daemon_binary; - + argv[n++] = "--daemonize=yes"; + snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); - argv[n++] = pa_xstrdup(t); + argv[n++] = t; while (n < MAX_ARGS) { char *a; if (!(a = pa_split_spaces(c->conf->extra_arguments, &state))) break; - + argv[n++] = a; } diff --git a/polyp/util.c b/polyp/util.c index 86f18f258..e4dcd1c9c 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -396,7 +396,7 @@ char *pa_split_spaces(const char *c, const char **state) { const char *current = *state ? *state : c; size_t l; - if (*current) + if (!*current) return NULL; current += strspn(current, WHITESPACE); From 61ec86c90f1964ab9663b7a72a0885078d372683 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Sep 2004 21:10:05 +0000 Subject: [PATCH 0211/1514] add resample_method option module-combine git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@215 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/daemon-conf.c | 15 +++------------ polyp/module-combine.c | 21 +++++++++++++++------ polyp/module-sine.c | 2 +- polyp/play-memchunk.c | 2 +- polyp/protocol-esound.c | 4 ++-- polyp/protocol-native.c | 4 ++-- polyp/protocol-simple.c | 4 ++-- polyp/sink-input.c | 7 +++++-- polyp/sink-input.h | 2 +- polyp/sound-file-stream.c | 2 +- polyp/source-output.c | 7 +++++-- polyp/source-output.h | 2 +- polyp/util.c | 18 ++++++++++++++++++ polyp/util.h | 2 ++ 14 files changed, 59 insertions(+), 33 deletions(-) diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index 6dcd540d9..befb9602c 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -125,25 +125,16 @@ int pa_daemon_conf_set_log_target(struct pa_daemon_conf *c, const char *string) return -1; return 0; - } int pa_daemon_conf_set_resample_method(struct pa_daemon_conf *c, const char *string) { + int m; assert(c && string); - if (!strcmp(string, "sinc-best-quality")) - c->resample_method = SRC_SINC_BEST_QUALITY; - else if (!strcmp(string, "sinc-medium-quality")) - c->resample_method = SRC_SINC_MEDIUM_QUALITY; - else if (!strcmp(string, "sinc-fastest")) - c->resample_method = SRC_SINC_FASTEST; - else if (!strcmp(string, "zero-order-hold")) - c->resample_method = SRC_ZERO_ORDER_HOLD; - else if (!strcmp(string, "linear")) - c->resample_method = SRC_LINEAR; - else + if ((m = pa_parse_resample_method(string)) < 0) return -1; + c->resample_method = m; return 0; } diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 177d7d18d..f6d596bc7 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -40,7 +40,7 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Combine multiple sinks to one") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= master= slave= adjust_time=") +PA_MODULE_USAGE("sink_name= master= slave= adjust_time= resample_method=") #define DEFAULT_SINK_NAME "combined" #define MEMBLOCKQ_MAXLENGTH (1024*170) @@ -53,6 +53,7 @@ static const char* const valid_modargs[] = { "master", "slaves", "adjust_time", + "resample_method", NULL }; @@ -200,7 +201,7 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { return pa_sink_input_get_latency(u->master->sink_input); } -static struct output *output_new(struct userdata *u, struct pa_sink *sink) { +static struct output *output_new(struct userdata *u, struct pa_sink *sink, int resample_method) { struct output *o = NULL; char t[256]; assert(u && sink && u->sink); @@ -212,7 +213,7 @@ static struct output *output_new(struct userdata *u, struct pa_sink *sink) { o->memblockq = pa_memblockq_new(MEMBLOCKQ_MAXLENGTH, MEMBLOCKQ_MAXLENGTH, pa_frame_size(&u->sink->sample_spec), 0, 0, sink->core->memblock_stat); snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1); - if (!(o->sink_input = pa_sink_input_new(sink, t, &u->sink->sample_spec, 1))) + if (!(o->sink_input = pa_sink_input_new(sink, t, &u->sink->sample_spec, 1, resample_method))) goto fail; o->sink_input->get_latency = sink_input_get_latency_cb; @@ -277,17 +278,25 @@ static void clear_up(struct userdata *u) { int pa__init(struct pa_core *c, struct pa_module*m) { struct userdata *u; struct pa_modargs *ma = NULL; - const char *master_name, *slaves; + const char *master_name, *slaves, *rm; struct pa_sink *master_sink; char *n = NULL; const char*split_state; struct timeval tv; + int resample_method = -1; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments\n"); goto fail; } + + if ((rm = pa_modargs_get_value(ma, "resample_method", NULL))) { + if ((resample_method = pa_parse_resample_method(rm)) < 0) { + pa_log(__FILE__": invalid resample method '%s'\n", rm); + goto fail; + } + } u = pa_xmalloc(sizeof(struct userdata)); m->userdata = u; @@ -325,7 +334,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; - if (!(u->master = output_new(u, master_sink))) { + if (!(u->master = output_new(u, master_sink, resample_method))) { pa_log(__FILE__": failed to create master sink input on sink '%s'.\n", u->sink->name); goto fail; } @@ -341,7 +350,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { pa_xfree(n); - if (!output_new(u, slave_sink)) { + if (!output_new(u, slave_sink, resample_method)) { pa_log(__FILE__": failed to create slave sink input on sink '%s'.\n", slave_sink->name); goto fail; } diff --git a/polyp/module-sine.c b/polyp/module-sine.c index 2fa7759c9..458b87883 100644 --- a/polyp/module-sine.c +++ b/polyp/module-sine.c @@ -139,7 +139,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { calc_sine(u->memblock->data, u->memblock->length, frequency); snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); - if (!(u->sink_input = pa_sink_input_new(sink, t, &ss, 0))) + if (!(u->sink_input = pa_sink_input_new(sink, t, &ss, 0, -1))) goto fail; u->sink_input->peek = sink_input_peek; diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index 6490547eb..aa6d30e99 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -88,7 +88,7 @@ int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sam if (volume <= 0) return 0; - if (!(si = pa_sink_input_new(sink, name, ss, 0))) + if (!(si = pa_sink_input_new(sink, name, ss, 0, -1))) return -1; si->volume = volume; diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index aff450992..293d123a3 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -305,7 +305,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons c->playback.fragment_size = l/10; assert(!c->sink_input); - c->sink_input = pa_sink_input_new(sink, name, &ss, 0); + c->sink_input = pa_sink_input_new(sink, name, &ss, 0, -1); assert(c->sink_input); c->sink_input->owner = c->protocol->module; @@ -368,7 +368,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2); assert(!c->source_output); - c->source_output = pa_source_output_new(source, name, &ss); + c->source_output = pa_source_output_new(source, name, &ss, -1); assert(c->source_output); c->source_output->owner = c->protocol->module; diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index e197d1e2b..021c1a606 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -251,7 +251,7 @@ static struct record_stream* record_stream_new(struct connection *c, struct pa_s size_t base; assert(c && source && ss && name && maxlength); - if (!(source_output = pa_source_output_new(source, name, ss))) + if (!(source_output = pa_source_output_new(source, name, ss, -1))) return NULL; s = pa_xmalloc(sizeof(struct record_stream)); @@ -295,7 +295,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct struct pa_sink_input *sink_input; assert(c && sink && ss && name && maxlength); - if (!(sink_input = pa_sink_input_new(sink, name, ss, 0))) + if (!(sink_input = pa_sink_input_new(sink, name, ss, 0, -1))) return NULL; s = pa_xmalloc(sizeof(struct playback_stream)); diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index a7bd76fbd..ee3bf9d33 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -314,7 +314,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo goto fail; } - if (!(c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec, 0))) { + if (!(c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec, 0, -1))) { pa_log(__FILE__": Failed to create sink input.\n"); goto fail; } @@ -344,7 +344,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo goto fail; } - c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec); + c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec, -1); if (!c->source_output) { pa_log(__FILE__": Failed to create source output.\n"); goto fail; diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 486a20443..949302314 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -36,7 +36,7 @@ #define CONVERT_BUFFER_LENGTH 4096 -struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate) { +struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method) { struct pa_sink_input *i; struct pa_resampler *resampler = NULL; int r; @@ -47,9 +47,12 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con pa_log(__FILE__": Failed to create sink input: too many inputs per sink.\n"); return NULL; } + + if (resample_method < 0) + resample_method = s->core->resample_method; if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec)) - if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat, s->core->resample_method))) + if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat, resample_method))) return NULL; i = pa_xmalloc(sizeof(struct pa_sink_input)); diff --git a/polyp/sink-input.h b/polyp/sink-input.h index 376783004..7c648ac12 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -62,7 +62,7 @@ struct pa_sink_input { struct pa_resampler *resampler; }; -struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate); +struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method); void pa_sink_input_unref(struct pa_sink_input* i); struct pa_sink_input* pa_sink_input_ref(struct pa_sink_input* i); diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c index 60a58f473..b77d6d615 100644 --- a/polyp/sound-file-stream.c +++ b/polyp/sound-file-stream.c @@ -145,7 +145,7 @@ int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume) { goto fail; } - if (!(u->sink_input = pa_sink_input_new(sink, fname, &ss, 0))) + if (!(u->sink_input = pa_sink_input_new(sink, fname, &ss, 0, -1))) goto fail; u->sink_input->volume = volume; diff --git a/polyp/source-output.c b/polyp/source-output.c index 252c155cf..13b396582 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -33,7 +33,7 @@ #include "subscribe.h" #include "log.h" -struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec) { +struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec, int resample_method) { struct pa_source_output *o; struct pa_resampler *resampler = NULL; int r; @@ -44,8 +44,11 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n return NULL; } + if (resample_method < 0) + resample_method = s->core->resample_method; + if (!pa_sample_spec_equal(&s->sample_spec, spec)) - if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat, s->core->resample_method))) + if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat, resample_method))) return NULL; o = pa_xmalloc(sizeof(struct pa_source_output)); diff --git a/polyp/source-output.h b/polyp/source-output.h index ed09b5370..51d5936b4 100644 --- a/polyp/source-output.h +++ b/polyp/source-output.h @@ -57,7 +57,7 @@ struct pa_source_output { void *userdata; }; -struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec); +struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec, int resample_method); void pa_source_output_unref(struct pa_source_output* o); struct pa_source_output* pa_source_output_ref(struct pa_source_output *o); diff --git a/polyp/util.c b/polyp/util.c index e4dcd1c9c..b9bf9f829 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -41,6 +41,8 @@ #include #include +#include + #include "util.h" #include "xmalloc.h" #include "log.h" @@ -420,3 +422,19 @@ const char *pa_strsignal(int sig) { } } +int pa_parse_resample_method(const char *string) { + assert(string); + + if (!strcmp(string, "sinc-best-quality")) + return SRC_SINC_BEST_QUALITY; + else if (!strcmp(string, "sinc-medium-quality")) + return SRC_SINC_MEDIUM_QUALITY; + else if (!strcmp(string, "sinc-fastest")) + return SRC_SINC_FASTEST; + else if (!strcmp(string, "zero-order-hold")) + return SRC_ZERO_ORDER_HOLD; + else if (!strcmp(string, "linear")) + return SRC_LINEAR; + else + return -1; +} diff --git a/polyp/util.h b/polyp/util.h index 07072df6f..c842a1c38 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -64,4 +64,6 @@ char *pa_split_spaces(const char *c, const char **state); const char *pa_strsignal(int sig); +int pa_parse_resample_method(const char *string); + #endif From 0b9bc039f63fb6173fd1b442a22e12c40797bc92 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Sep 2004 21:17:29 +0000 Subject: [PATCH 0212/1514] change sysconf path git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@216 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 7efb46c7d..e75744472 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -18,7 +18,7 @@ # USA. polypincludedir=$(includedir)/polyp -polypconfdir=$(sysconfdir)/polyp +polypconfdir=$(sysconfdir)/polypaudio modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ From 9ad4aa387ebcae2ec2b9f67f1f04eea89eddc241 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Sep 2004 23:45:28 +0000 Subject: [PATCH 0213/1514] minor stuff git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@217 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- polyp/client-conf.c | 1 - polyp/daemon.conf.in | 4 ++-- polyp/polyplib-context.c | 3 ++- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/todo b/doc/todo index 53d4ca56b..300f8d0a9 100644 --- a/doc/todo +++ b/doc/todo @@ -2,7 +2,6 @@ *** 0.5 *** - more complete pactl/parec -- fix tcp/native in regard to latencies (i.e. latency interpolation) *** 0.6 **** - per-channel volume @@ -12,6 +11,7 @@ - make mcalign merge chunks - option to use default fragment size on alsa drivers - improve module-oss-mmap latency measurement +- new mainloop method: defer_pending() ** later *** - xmlrpc/http diff --git a/polyp/client-conf.c b/polyp/client-conf.c index c43788fe5..efaae837d 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -43,7 +43,6 @@ #define ENV_DEFAULT_SERVER "POLYP_SERVER" #define ENV_DAEMON_BINARY "POLYP_BINARY" - static const struct pa_client_conf default_conf = { .daemon_binary = NULL, .extra_arguments = NULL, diff --git a/polyp/daemon.conf.in b/polyp/daemon.conf.in index a277bb4fd..e6d82db17 100644 --- a/polyp/daemon.conf.in +++ b/polyp/daemon.conf.in @@ -34,7 +34,7 @@ ## playback. However, this is a certain security issue, since it works ## when called SUID root only. root is dropped immediately after gaining ## the nice level and SCHED_FIFO scheduling on startup. -high-priority = 0 +; high-priority = 0 ## Disallow module loading after startup ; disallow-module-loading = 0 @@ -44,7 +44,7 @@ high-priority = 0 ; exit-idle-time = -1 ## Unload autoloaded modules after being idle for this time -module-idle-time = 20 +; module-idle-time = 20 ## The path were to look for dynamic shared objects (DSOs aka ## plugins). You may specify more than one path seperated by diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 8f6ce6a8c..8a7c719c2 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -500,7 +500,8 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons if (!server && spawn && c->conf->autospawn && !default_server_is_running()) return context_connect_spawn(c, api); - server = DEFAULT_SERVER; + if (!server) + server = DEFAULT_SERVER; pa_context_ref(c); From 4e31feb4345c617adb2ba44b9be724989b63d093 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 18 Sep 2004 12:28:29 +0000 Subject: [PATCH 0214/1514] work around gcc 2.95 limitation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@218 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/client-conf.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/polyp/client-conf.c b/polyp/client-conf.c index efaae837d..b8a4c778e 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -74,16 +74,23 @@ int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { char *def = NULL; int r; - const struct pa_config_item table[] = { - { "daemon-binary", pa_config_parse_string, &c->daemon_binary }, - { "extra-arguments", pa_config_parse_string, &c->extra_arguments }, - { "default-sink", pa_config_parse_string, &c->default_sink }, - { "default-source", pa_config_parse_string, &c->default_source }, - { "default-server", pa_config_parse_string, &c->default_server }, - { "autospawn", pa_config_parse_bool, &c->autospawn }, + struct pa_config_item table[] = { + { "daemon-binary", pa_config_parse_string, NULL }, + { "extra-arguments", pa_config_parse_string, NULL }, + { "default-sink", pa_config_parse_string, NULL }, + { "default-source", pa_config_parse_string, NULL }, + { "default-server", pa_config_parse_string, NULL }, + { "autospawn", pa_config_parse_bool, NULL }, { NULL, NULL, NULL }, }; + table[0].data = &c->daemon_binary; + table[1].data = &c->extra_arguments; + table[2].data = &c->default_sink; + table[3].data = &c->default_source; + table[4].data = &c->default_server; + table[5].data = &c->autospawn; + if (!filename) filename = getenv(ENV_CLIENT_CONFIG_FILE); From 73125ada06ee7adf75dfbb7518d2334abc606459 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 18 Sep 2004 12:38:37 +0000 Subject: [PATCH 0215/1514] work around gcc 2.95 limitation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@219 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/daemon-conf.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index befb9602c..8a0f94ac0 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -166,22 +166,35 @@ int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename) { char *def = NULL; int r; - const struct pa_config_item table[] = { - { "verbose", pa_config_parse_bool, &c->verbose }, - { "daemonize", pa_config_parse_bool, &c->daemonize }, - { "fail", pa_config_parse_bool, &c->fail }, - { "high-priority", pa_config_parse_bool, &c->high_priority }, - { "disallow-module-loading", pa_config_parse_bool, &c->disallow_module_loading }, - { "exit-idle-time", pa_config_parse_int, &c->exit_idle_time }, - { "module-idle-time", pa_config_parse_int, &c->module_idle_time }, - { "scache-idle-time", pa_config_parse_int, &c->scache_idle_time }, - { "dl-search-path", pa_config_parse_string, &c->dl_search_path }, - { "default-script-file", pa_config_parse_string, &c->default_script_file }, - { "log-target", parse_log_target, c }, - { "resample-method", parse_resample_method, c }, + struct pa_config_item table[] = { + { "verbose", pa_config_parse_bool, NULL }, + { "daemonize", pa_config_parse_bool, NULL }, + { "fail", pa_config_parse_bool, NULL }, + { "high-priority", pa_config_parse_bool, NULL }, + { "disallow-module-loading", pa_config_parse_bool, NULL }, + { "exit-idle-time", pa_config_parse_int, NULL }, + { "module-idle-time", pa_config_parse_int, NULL }, + { "scache-idle-time", pa_config_parse_int, NULL }, + { "dl-search-path", pa_config_parse_string, NULL }, + { "default-script-file", pa_config_parse_string, NULL }, + { "log-target", parse_log_target, NULL }, + { "resample-method", parse_resample_method, NULL }, { NULL, NULL, NULL }, }; - + + table[0].data = &c->verbose; + table[1].data = &c->daemonize; + table[2].data = &c->fail; + table[3].data = &c->high_priority; + table[4].data = &c->disallow_module_loading; + table[5].data = &c->exit_idle_time; + table[6].data = &c->module_idle_time; + table[7].data = &c->scache_idle_time; + table[8].data = &c->dl_search_path; + table[9].data = &c->default_script_file; + table[10].data = c; + table[11].data = c; + if (!filename) filename = def = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER); From 29653ab83b999f545207a007f35e8a52b34bd576 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 18 Sep 2004 23:40:42 +0000 Subject: [PATCH 0216/1514] add pacat command line parsing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@220 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + polyp/cmdline.c | 1 - polyp/pacat.c | 157 ++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 133 insertions(+), 26 deletions(-) diff --git a/doc/todo b/doc/todo index 300f8d0a9..adf305c2b 100644 --- a/doc/todo +++ b/doc/todo @@ -2,6 +2,7 @@ *** 0.5 *** - more complete pactl/parec +- xmms segfault when daemon not executable *** 0.6 **** - per-channel volume diff --git a/polyp/cmdline.c b/polyp/cmdline.c index a5bb8101f..82ac61830 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -76,7 +76,6 @@ static struct option long_options[] = { {NULL, 0, 0, 0} }; - void pa_cmdline_help(const char *argv0) { const char *e; diff --git a/polyp/pacat.c b/polyp/pacat.c index 933b0c3a7..a0db7594d 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,11 @@ static size_t buffer_length = 0, buffer_index = 0; static struct pa_io_event* stdio_event = NULL; +static char *stream_name = NULL, *client_name = NULL, *device = NULL; + +static int verbose = 0; +static pa_volume_t volume = PA_VOLUME_NORM; + /* A shortcut for terminating the application */ static void quit(int ret) { assert(mainloop_api); @@ -117,7 +123,8 @@ static void stream_state_callback(struct pa_stream *s, void *userdata) { break; case PA_STREAM_READY: - fprintf(stderr, "Stream successfully created\n"); + if (verbose) + fprintf(stderr, "Stream successfully created\n"); break; case PA_STREAM_FAILED: @@ -146,9 +153,11 @@ static void context_state_callback(struct pa_context *c, void *userdata) { case PA_CONTEXT_READY: assert(c && !stream); - fprintf(stderr, "Connection established.\n"); - stream = pa_stream_new(c, "pacat", &ss); + if (verbose) + fprintf(stderr, "Connection established.\n"); + + stream = pa_stream_new(c, stream_name, &ss); assert(stream); pa_stream_set_state_callback(stream, stream_state_callback, NULL); @@ -156,9 +165,9 @@ static void context_state_callback(struct pa_context *c, void *userdata) { pa_stream_set_read_callback(stream, stream_read_callback, NULL); if (mode == PLAYBACK) - pa_stream_connect_playback(stream, NULL, NULL, PA_VOLUME_NORM); + pa_stream_connect_playback(stream, device, NULL, volume); else - pa_stream_connect_record(stream, NULL, NULL); + pa_stream_connect_record(stream, device, NULL); break; @@ -186,8 +195,9 @@ static void stream_drain_complete(struct pa_stream*s, int success, void *userdat fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); quit(1); } - - fprintf(stderr, "Playback stream drained.\n"); + + if (verbose) + fprintf(stderr, "Playback stream drained.\n"); pa_stream_disconnect(stream); pa_stream_unref(stream); @@ -197,7 +207,9 @@ static void stream_drain_complete(struct pa_stream*s, int success, void *userdat pa_context_disconnect(context); else { pa_operation_unref(o); - fprintf(stderr, "Draining connection to server.\n"); + + if (verbose) + fprintf(stderr, "Draining connection to server.\n"); } } @@ -219,7 +231,8 @@ static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int assert(buffer); if ((r = read(fd, buffer, l)) <= 0) { if (r == 0) { - fprintf(stderr, "Got EOF.\n"); + if (verbose) + fprintf(stderr, "Got EOF.\n"); pa_operation_unref(pa_stream_drain(stream, stream_drain_complete, NULL)); } else { fprintf(stderr, "read() failed: %s\n", strerror(errno)); @@ -271,7 +284,8 @@ static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int /* UNIX signal to quit recieved */ static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { - fprintf(stderr, "Got SIGINT, exiting.\n"); + if (verbose) + fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); } @@ -303,10 +317,47 @@ static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_e pa_operation_unref(pa_stream_get_latency(stream, stream_get_latency_callback, NULL)); } + +static void help(const char *argv0) { + + printf("%s [options]\n" + " -h, --help Show this help\n" + " --version Show version\n\n" + " -r, --record Create a connection for recording\n" + " -p, --playback Create a connection for playback\n\n" + " -v, --verbose Enable verbose operations\n\n" + " -s, --server=SERVER The name of the server to connect to\n" + " -d, --device=DEVICE The name of the sink/source to connect to\n" + " -n, --client-name=NAME How to call this client on the server\n" + " --stream-name=NAME How to call this stream on the server\n" + " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n", + argv0); +} + +enum { + ARG_VERSION = 256, + ARG_STREAM_NAME, + ARG_VOLUME +}; + int main(int argc, char *argv[]) { struct pa_mainloop* m = NULL; - int ret = 1, r; - char *bn; + int ret = 1, r, c; + char *bn, *server = NULL; + + static const struct option long_options[] = { + {"record", 0, NULL, 'r'}, + {"playback", 0, NULL, 'p'}, + {"device", 1, NULL, 'd'}, + {"server", 1, NULL, 's'}, + {"client-name", 1, NULL, 'n'}, + {"stream-name", 1, NULL, ARG_STREAM_NAME}, + {"version", 0, NULL, ARG_VERSION}, + {"help", 0, NULL, 'h'}, + {"verbose", 0, NULL, 'v'}, + {"volume", 1, NULL, ARG_VOLUME}, + {NULL, 0, NULL, 0} + }; if (!(bn = strrchr(argv[0], '/'))) bn = argv[0]; @@ -318,18 +369,70 @@ int main(int argc, char *argv[]) { else if (strstr(bn, "cat") || strstr(bn, "play")) mode = PLAYBACK; - if (argc >= 2) { - if (!strcmp(argv[1], "-r")) - mode = RECORD; - else if (!strcmp(argv[1], "-p")) - mode = PLAYBACK; - else { - fprintf(stderr, "Invalid argument\n"); - goto quit; + while ((c = getopt_long(argc, argv, "rpd:s:n:hv", long_options, NULL)) != -1) { + + switch (c) { + case 'h' : + help(bn); + ret = 0; + goto quit; + + case ARG_VERSION: + printf("pacat "PACKAGE_VERSION"\n"); + ret = 0; + goto quit; + + case 'r': + mode = RECORD; + break; + + case 'p': + mode = PLAYBACK; + break; + + case 'd': + free(device); + device = strdup(optarg); + break; + + case 's': + free(server); + server = strdup(optarg); + break; + + case 'n': + free(client_name); + client_name = strdup(optarg); + break; + + case ARG_STREAM_NAME: + free(stream_name); + stream_name = strdup(optarg); + break; + + case 'v': + verbose = 1; + break; + + case ARG_VOLUME: { + int v = atoi(optarg); + volume = v < 0 ? 0 : v; + break; + } + + default: + goto quit; } } - fprintf(stderr, "Opening a %s stream.\n", mode == RECORD ? "recording" : "playback"); + if (!client_name) + client_name = strdup(bn); + + if (!stream_name) + stream_name = strdup(client_name); + + if (verbose) + fprintf(stderr, "Opening a %s stream.\n", mode == RECORD ? "recording" : "playback"); /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { @@ -354,7 +457,7 @@ int main(int argc, char *argv[]) { } /* Create a new connection context */ - if (!(context = pa_context_new(mainloop_api, bn))) { + if (!(context = pa_context_new(mainloop_api, client_name))) { fprintf(stderr, "pa_context_new() failed.\n"); goto quit; } @@ -362,7 +465,7 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect(context, NULL, 1, NULL); + pa_context_connect(context, server, 1, NULL); /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { @@ -387,8 +490,12 @@ quit: pa_mainloop_free(m); } - if (buffer) - free(buffer); + free(buffer); + + free(server); + free(device); + free(client_name); + free(stream_name); return ret; } From 70a30530e03ed4c43639575a479d77e38fea56ea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 19 Sep 2004 00:03:12 +0000 Subject: [PATCH 0217/1514] add new function pa_mainloop_deferred_pending() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@221 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - polyp/Makefile.am | 8 +++--- polyp/mainloop.c | 60 ++++++++++++++++++++++++++++++++++------- polyp/mainloop.h | 3 +++ polyp/polyplib-simple.c | 13 +++++++++ 5 files changed, 70 insertions(+), 15 deletions(-) diff --git a/doc/todo b/doc/todo index adf305c2b..22d59e68f 100644 --- a/doc/todo +++ b/doc/todo @@ -12,7 +12,6 @@ - make mcalign merge chunks - option to use default fragment size on alsa drivers - improve module-oss-mmap latency measurement -- new mainloop method: defer_pending() ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index e75744472..4adc8add6 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -334,7 +334,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ llist.h \ log.c log.h \ gcc-printf.h \ - client-conf.c client-conf.h \ + client-conf.c client-conf.h \ conf-parser.c conf-parser.h libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) @@ -366,11 +366,11 @@ pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMI pactl_CFLAGS = $(AM_CFLAGS) $(LIBSDNFILE_CFLAGS) pacat_simple_SOURCES = pacat-simple.c -pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la +pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la pacat_simple_CFLAGS = $(AM_CFLAGS) parec_simple_SOURCES = parec-simple.c -parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la +parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la parec_simple_CFLAGS = $(AM_CFLAGS) mainloop_test_SOURCES = mainloop-test.c @@ -541,7 +541,7 @@ esdcompat.sh: esdcompat.sh.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ - + client.conf: client.conf.in Makefile sed -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ diff --git a/polyp/mainloop.c b/polyp/mainloop.c index c4e12ac1c..80bcb125c 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -79,6 +79,8 @@ struct pa_mainloop { int quit, running, retval; struct pa_mainloop_api api; + + int deferred_pending; }; /* IO events */ @@ -147,17 +149,32 @@ struct pa_defer_event* mainloop_defer_new(struct pa_mainloop_api*a, void (*callb e->destroy_callback = NULL; pa_idxset_put(m->defer_events, e, NULL); + + m->deferred_pending++; return e; } static void mainloop_defer_enable(struct pa_defer_event *e, int b) { assert(e); + + if (e->enabled && !b) { + assert(e->mainloop->deferred_pending > 0); + e->mainloop->deferred_pending--; + } else if (!e->enabled && b) + e->mainloop->deferred_pending++; + e->enabled = b; } static void mainloop_defer_free(struct pa_defer_event *e) { assert(e); e->dead = e->mainloop->defer_events_scan_dead = 1; + + if (e->enabled) { + e->enabled = 0; + assert(e->mainloop->deferred_pending > 0); + e->mainloop->deferred_pending--; + } } static void mainloop_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)) { @@ -265,6 +282,8 @@ struct pa_mainloop *pa_mainloop_new(void) { m->api = vtable; m->api.userdata = m; + + m->deferred_pending = 0; return m; } @@ -383,7 +402,7 @@ static int dispatch_pollfds(struct pa_mainloop *m) { struct pa_io_event *e; int r = 0; - for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) { + for (e = pa_idxset_first(m->io_events, &index); e && !m->quit; e = pa_idxset_next(m->io_events, &index)) { if (e->dead || !e->pollfd || !e->pollfd->revents) continue; @@ -406,7 +425,7 @@ static int dispatch_defer(struct pa_mainloop *m) { struct pa_defer_event *e; int r = 0; - for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) { + for (e = pa_idxset_first(m->defer_events, &index); e && !m->quit; e = pa_idxset_next(m->defer_events, &index)) { if (e->dead || !e->enabled) continue; @@ -470,7 +489,7 @@ static int dispatch_timeout(struct pa_mainloop *m) { if (pa_idxset_isempty(m->time_events)) return 0; - for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { + for (e = pa_idxset_first(m->time_events, &index); e && !m->quit; e = pa_idxset_next(m->time_events, &index)) { if (e->dead || !e->enabled) continue; @@ -498,17 +517,17 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { int r, t, dispatched = 0; assert(m && !m->running); - if(m->quit) { - if (retval) - *retval = m->retval; - return -2; - } - m->running = 1; + if(m->quit) + goto quit; + scan_dead(m); dispatched += dispatch_defer(m); + if(m->quit) + goto quit; + if (m->rebuild_pollfds) { rebuild_pollfds(m); m->rebuild_pollfds = 0; @@ -524,9 +543,16 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { pa_log(__FILE__": select(): %s\n", strerror(errno)); } else { dispatched += dispatch_timeout(m); + + if(m->quit) + goto quit; - if (r > 0) + if (r > 0) { dispatched += dispatch_pollfds(m); + + if(m->quit) + goto quit; + } } m->running = 0; @@ -534,6 +560,15 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { /* pa_log("dispatched: %i\n", dispatched); */ return r < 0 ? -1 : dispatched; + +quit: + + m->running = 0; + + if (retval) + *retval = m->retval; + + return -2; } int pa_mainloop_run(struct pa_mainloop *m, int *retval) { @@ -557,3 +592,8 @@ struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m) { assert(m); return &m->api; } + +int pa_mainloop_deferred_pending(struct pa_mainloop *m) { + assert(m); + return m->deferred_pending > 0; +} diff --git a/polyp/mainloop.h b/polyp/mainloop.h index a0fe126fd..4a64d98f2 100644 --- a/polyp/mainloop.h +++ b/polyp/mainloop.h @@ -59,6 +59,9 @@ int pa_mainloop_run(struct pa_mainloop *m, int *retval); /** Return the abstract main loop abstraction layer vtable for this main loop. This calls pa_mainloop_iterate() iteratively.*/ struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m); +/** Return non-zero when there are any deferred events pending. \since 0.5 */ +int pa_mainloop_deferred_pending(struct pa_mainloop *m); + PA_C_DECL_END #endif diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index 5cf52d062..aa6c88f5a 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -99,6 +99,19 @@ static int iterate(struct pa_simple *p, int block, int *perror) { } while (pa_context_is_pending(p->context)); + + while (pa_mainloop_deferred_pending(p->mainloop)) { + + if (pa_mainloop_iterate(p->mainloop, 0, NULL) < 0) { + if (perror) + *perror = PA_ERROR_INTERNAL; + return -1; + } + + if (check_error(p, perror) < 0) + return -1; + } + return 0; } From b118982674effa44aa1687e8bd0d2bc0eb6254b2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 19 Sep 2004 23:12:41 +0000 Subject: [PATCH 0218/1514] remove obnoxious assert from module-combine tagstruct: add support for NULL strings improve pactl correct pa_bytes_snprint() pa_sample_spec_snprint(): don't fail on invalid sample spec rename PA_SAMPLE_SNPRINT_MAX_LENGTH to PA_SAMPLE_SPEC_SNPRINT_MAX git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@222 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- polyp/cli-command.c | 2 + polyp/cli-text.c | 10 +- polyp/cmdline.c | 2 +- polyp/module-combine.c | 2 +- polyp/pacat.c | 4 +- polyp/pactl.c | 545 ++++++++++++++++++++++++++++++++---- polyp/pdispatch.c | 6 +- polyp/polyplib-introspect.c | 8 +- polyp/polyplib-scache.c | 2 +- polyp/polyplib-stream.c | 5 +- polyp/protocol-native.c | 66 ++--- polyp/sample.c | 20 +- polyp/sample.h | 4 +- polyp/tagstruct.c | 28 +- 15 files changed, 580 insertions(+), 126 deletions(-) diff --git a/doc/todo b/doc/todo index 22d59e68f..ec9e462e1 100644 --- a/doc/todo +++ b/doc/todo @@ -1,8 +1,8 @@ *** $Id$ *** *** 0.5 *** -- more complete pactl/parec - xmms segfault when daemon not executable +- update modinfo *** 0.6 **** - per-channel volume diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 750d67ead..39ea9cc1e 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -236,6 +236,8 @@ static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct "Default source name: %s\n", pa_namereg_get_default_sink_name(c), pa_namereg_get_default_source_name(c)); + + return 0; } diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 9932e5689..3cedf920d 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -88,7 +88,7 @@ char *pa_sink_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_ncontents(c->sinks)); for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index)) { - char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec); assert(sink->monitor_source); pa_strbuf_printf( @@ -123,7 +123,7 @@ char *pa_source_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_ncontents(c->sources)); for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { - char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec); pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n", c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ', @@ -156,7 +156,7 @@ char *pa_source_output_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_ncontents(c->source_outputs)); for (o = pa_idxset_first(c->source_outputs, &index); o; o = pa_idxset_next(c->source_outputs, &index)) { - char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec); assert(o->source); pa_strbuf_printf( @@ -186,7 +186,7 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_ncontents(c->sink_inputs)); for (i = pa_idxset_first(c->sink_inputs, &index); i; i = pa_idxset_next(c->sink_inputs, &index)) { - char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH]; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); pa_strbuf_printf( @@ -223,7 +223,7 @@ char *pa_scache_list_to_string(struct pa_core *c) { for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) { double l = 0; - char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH] = "n/a"; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a"; if (e->memchunk.memblock) { pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec); diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 82ac61830..c32d9a0f1 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -84,7 +84,7 @@ void pa_cmdline_help(const char *argv0) { else e = argv0; - printf("%s [options]\n" + printf("%s [options]\n\n" " -h, --help Show this help\n" " --version Show version\n" " --dump-conf Dump default configuration\n" diff --git a/polyp/module-combine.c b/polyp/module-combine.c index f6d596bc7..1bb183ecf 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -106,7 +106,7 @@ static void adjust_rates(struct userdata *u) { min_total_latency = o->total_latency; } - assert(max_sink_latency > 0 && min_total_latency != (pa_usec_t) -1); + assert(min_total_latency != (pa_usec_t) -1); target_latency = max_sink_latency > min_total_latency ? max_sink_latency : min_total_latency; diff --git a/polyp/pacat.c b/polyp/pacat.c index a0db7594d..b9cb047ad 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -320,7 +320,7 @@ static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_e static void help(const char *argv0) { - printf("%s [options]\n" + printf("%s [options]\n\n" " -h, --help Show this help\n" " --version Show version\n\n" " -r, --record Create a connection for recording\n" @@ -378,7 +378,7 @@ int main(int argc, char *argv[]) { goto quit; case ARG_VERSION: - printf("pacat "PACKAGE_VERSION"\n"); + printf("pacat "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; goto quit; diff --git a/polyp/pactl.c b/polyp/pactl.c index c93fd2355..2a466b39c 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -45,14 +46,16 @@ static struct pa_context *context = NULL; static struct pa_mainloop_api *mainloop_api = NULL; -static char **process_argv = NULL; +static char *device = NULL, *sample_name = NULL; static SNDFILE *sndfile = NULL; static struct pa_stream *sample_stream = NULL; static struct pa_sample_spec sample_spec; static size_t sample_length = 0; -static char *sample_name = NULL; +static int actions = 1; + +static int nl = 0; static enum { NONE, @@ -60,7 +63,8 @@ static enum { STAT, UPLOAD_SAMPLE, PLAY_SAMPLE, - REMOVE_SAMPLE + REMOVE_SAMPLE, + LIST } action = NONE; static void quit(int ret) { @@ -81,37 +85,373 @@ static void drain(void) { pa_operation_unref(o); } + +static void complete_action(void) { + assert(actions > 0); + + if (!(--actions)) + drain(); +} + static void stat_callback(struct pa_context *c, const struct pa_stat_info *i, void *userdata) { + char s[128]; if (!i) { fprintf(stderr, "Failed to get statistics: %s\n", pa_strerror(pa_context_errno(c))); quit(1); return; } + + pa_bytes_snprint(s, sizeof(s), i->memblock_total_size); + printf("Currently in use: %u blocks containing %s bytes total.\n", i->memblock_total, s); + + pa_bytes_snprint(s, sizeof(s), i->memblock_allocated_size); + printf("Allocated during whole lifetime: %u blocks containing %s bytes total.\n", i->memblock_allocated, s); + + pa_bytes_snprint(s, sizeof(s), i->scache_size); + printf("Sample cache size: %s\n", s); - fprintf(stderr, "Currently in use: %u blocks containing %u bytes total.\n" - "Allocated during whole lifetime: %u blocks containing %u bytes total.\n", - i->memblock_total, i->memblock_total_size, i->memblock_allocated, i->memblock_allocated_size); - drain(); + complete_action(); } -static void play_sample_callback(struct pa_context *c, int success, void *userdata) { - if (!success) { - fprintf(stderr, "Failed to play sample: %s\n", pa_strerror(pa_context_errno(c))); +static void get_server_info_callback(struct pa_context *c, const struct pa_server_info *i, void *useerdata) { + char s[PA_SAMPLE_SPEC_SNPRINT_MAX]; + + if (!i) { + fprintf(stderr, "Failed to get server information: %s\n", pa_strerror(pa_context_errno(c))); quit(1); return; } - drain(); + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); + + printf("User name: %s\n" + "Host Name: %s\n" + "Server Name: %s\n" + "Server Version: %s\n" + "Default Sample Specification: %s\n" + "Default Sink: %s\n" + "Default Source: %s\n", + i->user_name, + i->host_name, + i->server_name, + i->server_version, + s, + i->default_sink_name, + i->default_source_name); + + complete_action(); } -static void remove_sample_callback(struct pa_context *c, int success, void *userdata) { - if (!success) { - fprintf(stderr, "Failed to remove sample: %s\n", pa_strerror(pa_context_errno(c))); +static void get_sink_info_callback(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata) { + char s[PA_SAMPLE_SPEC_SNPRINT_MAX]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c))); quit(1); return; } - drain(); + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); + + printf("*** Sink #%u ***\n" + "Name: %s\n" + "Description: %s\n" + "Sample Specification: %s\n" + "Owner Module: %u\n" + "Volume: 0x%03x (%0.2f dB)\n" + "Monitor Source: %u\n" + "Latency: %0.0f usec\n", + i->index, + i->name, + i->description, + s, + i->owner_module, + i->volume, pa_volume_to_dB(i->volume), + i->monitor_source, + (double) i->latency); +} + +static void get_source_info_callback(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata) { + char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get source information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + snprintf(t, sizeof(t), "%u", i->monitor_of_sink); + + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); + + printf("*** Source #%u ***\n" + "Name: %s\n" + "Description: %s\n" + "Sample Specification: %s\n" + "Owner Module: %u\n" + "Monitor of Sink: %s\n" + "Latency: %0.0f usec\n", + i->index, + i->name, + i->description, + s, + i->owner_module, + i->monitor_of_sink != PA_INVALID_INDEX ? t : "no", + (double) i->latency); +} + +static void get_module_info_callback(struct pa_context *c, const struct pa_module_info *i, int is_last, void *userdata) { + char t[32]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get module information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + snprintf(t, sizeof(t), "%u", i->n_used); + + printf("*** Module #%u ***\n" + "Name: %s\n" + "Argument: %s\n" + "Usage counter: %s\n" + "Auto unload: %s\n", + i->index, + i->name, + i->argument, + i->n_used != PA_INVALID_INDEX ? t : "n/a", + i->auto_unload ? "yes" : "no"); +} + +static void get_client_info_callback(struct pa_context *c, const struct pa_client_info *i, int is_last, void *userdata) { + char t[32]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get client information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + snprintf(t, sizeof(t), "%u", i->owner_module); + + printf("*** Client #%u ***\n" + "Name: %s\n" + "Owner Module: %s\n" + "Protocol Name: %s\n", + i->index, + i->name, + i->owner_module != PA_INVALID_INDEX ? t : "n/a", + i->protocol_name); +} + +static void get_sink_input_info_callback(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) { + char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get sink input information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); + snprintf(t, sizeof(t), "%u", i->owner_module); + snprintf(k, sizeof(k), "%u", i->client); + + printf("*** Sink Input #%u ***\n" + "Name: %s\n" + "Owner Module: %s\n" + "Client: %s\n" + "Sink: %u\n" + "Sample Specification: %s\n" + "Volume: 0x%03x (%0.2f dB)\n" + "Buffer Latency: %0.0f usec\n" + "Sink Latency: %0.0f usec\n", + i->index, + i->name, + i->owner_module != PA_INVALID_INDEX ? t : "n/a", + i->client != PA_INVALID_INDEX ? k : "n/a", + i->sink, + s, + i->volume, pa_volume_to_dB(i->volume), + (double) i->buffer_usec, + (double) i->sink_usec); +} + +static void get_source_output_info_callback(struct pa_context *c, const struct pa_source_output_info *i, int is_last, void *userdata) { + char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get source output information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); + snprintf(t, sizeof(t), "%u", i->owner_module); + snprintf(k, sizeof(k), "%u", i->client); + + printf("*** Source Output #%u ***\n" + "Name: %s\n" + "Owner Module: %s\n" + "Client: %s\n" + "Source: %u\n" + "Sample Specification: %s\n" + "Buffer Latency: %0.0f usec\n" + "Source Latency: %0.0f usec\n", + i->index, + i->name, + i->owner_module != PA_INVALID_INDEX ? t : "n/a", + i->client != PA_INVALID_INDEX ? k : "n/a", + i->source, + s, + (double) i->buffer_usec, + (double) i->source_usec); +} + +static void get_sample_info_callback(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata) { + char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX]; + + if (is_last < 0) { + fprintf(stderr, "Failed to get sample information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); + pa_bytes_snprint(t, sizeof(t), i->bytes); + + printf("*** Sample #%u ***\n" + "Name: %s\n" + "Volume: 0x%03x (%0.2f dB)\n" + "Sample Specification: %s\n" + "Duration: %0.1fs\n" + "Size: %s\n" + "Lazy: %s\n" + "Filename: %s\n", + i->index, + i->name, + i->volume, pa_volume_to_dB(i->volume), + pa_sample_spec_valid(&i->sample_spec) ? s : "n/a", + (double) i->duration/1000000, + t, + i->lazy ? "yes" : "no", + i->filename ? i->filename : "n/a"); +} + +static void get_autoload_info_callback(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata) { + if (is_last < 0) { + fprintf(stderr, "Failed to get autoload information: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (is_last) { + complete_action(); + return; + } + + assert(i); + + if (nl) + printf("\n"); + nl = 1; + + printf("*** Autoload Entry ***\n" + "Name: %s\n" + "Type: %s\n" + "Module: %s\n" + "Argument: %s\n", + i->name, + i->type == PA_AUTOLOAD_SINK ? "sink" : "source", + i->module, + i->argument); +} + +static void simple_callback(struct pa_context *c, int success, void *userdata) { + if (!success) { + fprintf(stderr, "Failure: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + complete_action(); } static void stream_state_callback(struct pa_stream *s, void *userdata) { @@ -169,24 +509,48 @@ static void context_state_callback(struct pa_context *c, void *userdata) { break; case PA_CONTEXT_READY: - if (action == STAT) - pa_operation_unref(pa_context_stat(c, stat_callback, NULL)); - else if (action == PLAY_SAMPLE) - pa_operation_unref(pa_context_play_sample(c, process_argv[2], NULL, 0x100, play_sample_callback, NULL)); - else if (action == REMOVE_SAMPLE) - pa_operation_unref(pa_context_remove_sample(c, process_argv[2], remove_sample_callback, NULL)); - else if (action == UPLOAD_SAMPLE) { + switch (action) { + case STAT: + actions = 2; + pa_operation_unref(pa_context_stat(c, stat_callback, NULL)); + pa_operation_unref(pa_context_get_server_info(c, get_server_info_callback, NULL)); + break; - sample_stream = pa_stream_new(c, sample_name, &sample_spec); - assert(sample_stream); + case PLAY_SAMPLE: + pa_operation_unref(pa_context_play_sample(c, sample_name, device, PA_VOLUME_NORM, simple_callback, NULL)); + break; - pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL); - pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL); - pa_stream_connect_upload(sample_stream, sample_length); - } else { - assert(action == EXIT); - pa_context_exit_daemon(c); - drain(); + case REMOVE_SAMPLE: + pa_operation_unref(pa_context_remove_sample(c, sample_name, simple_callback, NULL)); + break; + + case UPLOAD_SAMPLE: + sample_stream = pa_stream_new(c, sample_name, &sample_spec); + assert(sample_stream); + + pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL); + pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL); + pa_stream_connect_upload(sample_stream, sample_length); + break; + + case EXIT: + pa_context_exit_daemon(c); + drain(); + + case LIST: + actions = 8; + pa_operation_unref(pa_context_get_module_info_list(c, get_module_info_callback, NULL)); + pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, NULL)); + pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, NULL)); + pa_operation_unref(pa_context_get_sink_input_info_list(c, get_sink_input_info_callback, NULL)); + pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL)); + pa_operation_unref(pa_context_get_client_info_list(c, get_client_info_callback, NULL)); + pa_operation_unref(pa_context_get_sample_info_list(c, get_sample_info_callback, NULL)); + pa_operation_unref(pa_context_get_autoload_info_list(c, get_autoload_info_callback, NULL)); + break; + + default: + assert(0); } break; @@ -206,43 +570,106 @@ static void exit_signal_callback(struct pa_mainloop_api *m, struct pa_signal_eve quit(0); } +static void help(const char *argv0) { + + printf("%s [options] stat\n" + "%s [options] list\n" + "%s [options] exit\n" + "%s [options] upload-sample FILENAME [NAME]\n" + "%s [options] play-sample NAME [SINK]\n" + "%s [options] remove-sample NAME\n\n" + " -h, --help Show this help\n" + " --version Show version\n\n" + " -s, --server=SERVER The name of the server to connect to\n" + " -n, --client-name=NAME How to call this client on the server\n", + argv0, argv0, argv0, argv0, argv0, argv0); +} + +enum { ARG_VERSION = 256 }; + int main(int argc, char *argv[]) { struct pa_mainloop* m = NULL; char tmp[PATH_MAX]; - - int ret = 1, r; + int ret = 1, r, c; + char *server = NULL, *client_name = NULL, *bn; - if (argc >= 2) { - if (!strcmp(argv[1], "stat")) + static const struct option long_options[] = { + {"server", 1, NULL, 's'}, + {"client-name", 1, NULL, 'n'}, + {"version", 0, NULL, ARG_VERSION}, + {"help", 0, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + if (!(bn = strrchr(argv[0], '/'))) + bn = argv[0]; + else + bn++; + + while ((c = getopt_long(argc, argv, "s:n:h", long_options, NULL)) != -1) { + switch (c) { + case 'h' : + help(bn); + ret = 0; + goto quit; + + case ARG_VERSION: + printf("pactl "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + ret = 0; + goto quit; + + case 's': + free(server); + server = strdup(optarg); + break; + + case 'n': + free(client_name); + client_name = strdup(optarg); + break; + + default: + goto quit; + } + } + + if (!client_name) + client_name = strdup(bn); + + if (optind < argc) { + if (!strcmp(argv[optind], "stat")) action = STAT; - else if (!strcmp(argv[1], "exit")) + else if (!strcmp(argv[optind], "exit")) action = EXIT; - else if (!strcmp(argv[1], "scache_upload")) { + else if (!strcmp(argv[optind], "list")) + action = LIST; + else if (!strcmp(argv[optind], "upload-sample")) { struct SF_INFO sfinfo; action = UPLOAD_SAMPLE; - if (argc < 3) { + if (optind+1 >= argc) { fprintf(stderr, "Please specify a sample file to load\n"); goto quit; } - if (argc >= 4) - sample_name = argv[3]; + if (optind+2 < argc) + sample_name = strdup(argv[optind+2]); else { - char *f = strrchr(argv[2], '/'); + char *f = strrchr(argv[optind+1], '/'); size_t n; if (f) f++; else - f = argv[2]; + f = argv[optind]; n = strcspn(f, "."); - strncpy(sample_name = tmp, f, n); - tmp[n] = 0; + strncpy(tmp, f, n); + tmp[n] = 0; + sample_name = strdup(tmp); } memset(&sfinfo, 0, sizeof(sfinfo)); - if (!(sndfile = sf_open(argv[2], SFM_READ, &sfinfo))) { + if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfinfo))) { fprintf(stderr, "Failed to open sound file.\n"); goto quit; } @@ -252,28 +679,34 @@ int main(int argc, char *argv[]) { sample_spec.channels = sfinfo.channels; sample_length = sfinfo.frames*pa_frame_size(&sample_spec); - } else if (!strcmp(argv[1], "scache_play")) { + } else if (!strcmp(argv[optind], "play-sample")) { action = PLAY_SAMPLE; - if (argc < 3) { + if (optind+1 >= argc) { fprintf(stderr, "You have to specify a sample name to play\n"); goto quit; } - } else if (!strcmp(argv[1], "scache_remove")) { + + sample_name = strdup(argv[optind+1]); + + if (optind+2 < argc) + device = strdup(argv[optind+2]); + + } else if (!strcmp(argv[optind], "remove-sample")) { action = REMOVE_SAMPLE; - if (argc < 3) { + if (optind+1 >= argc) { fprintf(stderr, "You have to specify a sample name to remove\n"); goto quit; } + + sample_name = strdup(argv[optind+1]); } } if (action == NONE) { - fprintf(stderr, "No valid action specified. Use one of: stat, exit, scache_upload, scache_play, scache_remove\n"); + fprintf(stderr, "No valid command specified.\n"); goto quit; } - process_argv = argv; - if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); goto quit; @@ -286,13 +719,13 @@ int main(int argc, char *argv[]) { pa_signal_new(SIGINT, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - if (!(context = pa_context_new(mainloop_api, argv[0]))) { + if (!(context = pa_context_new(mainloop_api, client_name))) { fprintf(stderr, "pa_context_new() failed.\n"); goto quit; } pa_context_set_state_callback(context, context_state_callback, NULL); - pa_context_connect(context, NULL, 1, NULL); + pa_context_connect(context, server, 1, NULL); if (pa_mainloop_run(m, &ret) < 0) { fprintf(stderr, "pa_mainloop_run() failed.\n"); @@ -314,5 +747,9 @@ quit: if (sndfile) sf_close(sndfile); + free(server); + free(device); + free(sample_name); + return ret; } diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index 88f85e028..f6481fa00 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -33,7 +33,7 @@ #include "llist.h" #include "log.h" -/*#define DEBUG_OPCODES*/ +/* #define DEBUG_OPCODES */ #ifdef DEBUG_OPCODES @@ -48,7 +48,7 @@ static const char *command_names[PA_COMMAND_MAX] = { [PA_COMMAND_AUTH] = "AUTH", [PA_COMMAND_REQUEST] = "REQUEST", [PA_COMMAND_EXIT] = "EXIT", - [PA_COMMAND_SET_NAME] = "SET_NAME", + [PA_COMMAND_SET_CLIENT_NAME] = "SET_CLIENT_NAME", [PA_COMMAND_LOOKUP_SINK] = "LOOKUP_SINK", [PA_COMMAND_LOOKUP_SOURCE] = "LOOKUP_SOURCE", [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = "DRAIN_PLAYBACK_STREAM", @@ -83,6 +83,8 @@ static const char *command_names[PA_COMMAND_MAX] = { [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = "TRIGGER_PLAYBACK_STREAM", [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = "FLUSH_PLAYBACK_STREAM", [PA_COMMAND_CORK_PLAYBACK_STREAM] = "CORK_PLAYBACK_STREAM", + [PA_COMMAND_GET_AUTOLOAD_INFO] = "GET_AUTOLOAD_INFO", + [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = "GET_AUTOLOAD_INFO_LIST", }; #endif diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 1673be9bf..267af95b7 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -170,7 +170,7 @@ struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uin pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); + pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o); @@ -263,7 +263,7 @@ struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, u pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); + pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o); @@ -581,7 +581,7 @@ struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, u pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); + pa_tagstruct_puts(t, NULL); pa_tagstruct_putu32(t, volume); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); @@ -713,7 +713,7 @@ struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, u pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, index); - pa_tagstruct_puts(t, ""); + pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, o); diff --git a/polyp/polyplib-scache.c b/polyp/polyplib-scache.c index 7221420c8..45220d102 100644 --- a/polyp/polyplib-scache.c +++ b/polyp/polyplib-scache.c @@ -95,7 +95,7 @@ struct pa_operation * pa_context_play_sample(struct pa_context *c, const char *n pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, (uint32_t) -1); - pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_puts(t, dev); pa_tagstruct_putu32(t, volume); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 6055a2204..8bd098d43 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -194,7 +194,7 @@ void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32 if (pa_tagstruct_getu32(t, &s->channel) < 0 || ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || - ((s->direction == PA_STREAM_PLAYBACK) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0) || + ((s->direction != PA_STREAM_RECORD) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0) || !pa_tagstruct_eof(t)) { pa_context_fail(s->context, PA_ERROR_PROTOCOL); goto finish; @@ -245,7 +245,7 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ pa_tagstruct_puts(t, s->name); pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_putu32(t, PA_INVALID_INDEX); - pa_tagstruct_puts(t, dev ? dev : ""); + pa_tagstruct_puts(t, dev); pa_tagstruct_putu32(t, s->buffer_attr.maxlength); if (s->direction == PA_STREAM_PLAYBACK) { pa_tagstruct_putu32(t, s->buffer_attr.tlength); @@ -536,7 +536,6 @@ struct pa_operation* pa_stream_send_simple_command(struct pa_stream *s, uint32_t return pa_operation_ref(o); } - struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { return pa_stream_send_simple_command(s, PA_COMMAND_FLUSH_PLAYBACK_STREAM, cb, userdata); } diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 021c1a606..4c1e96969 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -540,7 +540,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com pa_volume_t volume; assert(c && t && c->protocol && c->protocol->core); - if (pa_tagstruct_gets(t, &name) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || !name || pa_tagstruct_get_sample_spec(t, &ss) < 0 || pa_tagstruct_getu32(t, &sink_index) < 0 || pa_tagstruct_gets(t, &sink_name) < 0 || @@ -554,6 +554,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com return; } + if (!c->authorized) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); return; @@ -562,7 +563,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com if (sink_index != (uint32_t) -1) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); else - sink = pa_namereg_get(c->protocol->core, *sink_name ? sink_name : NULL, PA_NAMEREG_SINK, 1); + sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1); if (!sink) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); @@ -643,7 +644,7 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma struct pa_source *source; assert(c && t && c->protocol && c->protocol->core); - if (pa_tagstruct_gets(t, &name) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || !name || pa_tagstruct_get_sample_spec(t, &ss) < 0 || pa_tagstruct_getu32(t, &source_index) < 0 || pa_tagstruct_gets(t, &source_name) < 0 || @@ -662,7 +663,7 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma if (source_index != (uint32_t) -1) source = pa_idxset_get_by_index(c->protocol->core->sources, source_index); else - source = pa_namereg_get(c->protocol->core, *source_name ? source_name : NULL, PA_NAMEREG_SOURCE, 1); + source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1); if (!source) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); @@ -734,7 +735,7 @@ static void command_set_client_name(struct pa_pdispatch *pd, uint32_t command, u const char *name; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || !name || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -751,7 +752,7 @@ static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t t uint32_t index = PA_IDXSET_INVALID; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || !name || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -939,7 +940,7 @@ static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t comma struct pa_tagstruct *reply; assert(c && t && c->protocol && c->protocol->core); - if (pa_tagstruct_gets(t, &name) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || !name || pa_tagstruct_get_sample_spec(t, &ss) < 0 || pa_tagstruct_getu32(t, &length) < 0 || !pa_tagstruct_eof(t)) { @@ -967,13 +968,6 @@ static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t comma pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); pa_tagstruct_putu32(reply, tag); pa_tagstruct_putu32(reply, s->index); - pa_pstream_send_tagstruct(c->pstream, reply); - - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REQUEST); - pa_tagstruct_putu32(reply, (uint32_t) -1); /* tag */ - pa_tagstruct_putu32(reply, s->index); pa_tagstruct_putu32(reply, length); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1016,7 +1010,7 @@ static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint3 if (pa_tagstruct_getu32(t, &sink_index) < 0 || pa_tagstruct_gets(t, &sink_name) < 0 || pa_tagstruct_getu32(t, &volume) < 0 || - pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_gets(t, &name) < 0 || !name || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1030,7 +1024,7 @@ static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint3 if (sink_index != (uint32_t) -1) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); else - sink = pa_namereg_get(c->protocol->core, *sink_name ? sink_name : NULL, PA_NAMEREG_SINK, 1); + sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1); if (!sink) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); @@ -1050,7 +1044,7 @@ static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uin const char *name; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || !name || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1073,7 +1067,7 @@ static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) { assert(t && sink); pa_tagstruct_putu32(t, sink->index); pa_tagstruct_puts(t, sink->name); - pa_tagstruct_puts(t, sink->description ? sink->description : ""); + pa_tagstruct_puts(t, sink->description); pa_tagstruct_put_sample_spec(t, &sink->sample_spec); pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1); pa_tagstruct_putu32(t, sink->volume); @@ -1086,11 +1080,11 @@ static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *sour assert(t && source); pa_tagstruct_putu32(t, source->index); pa_tagstruct_puts(t, source->name); - pa_tagstruct_puts(t, source->description ? source->description : ""); + pa_tagstruct_puts(t, source->description); pa_tagstruct_put_sample_spec(t, &source->sample_spec); pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1); pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1); - pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : ""); + pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : NULL); pa_tagstruct_put_usec(t, pa_source_get_latency(source)); } @@ -1106,7 +1100,7 @@ static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *modu assert(t && module); pa_tagstruct_putu32(t, module->index); pa_tagstruct_puts(t, module->name); - pa_tagstruct_puts(t, module->argument ? module->argument : ""); + pa_tagstruct_puts(t, module->argument); pa_tagstruct_putu32(t, module->n_used); pa_tagstruct_put_boolean(t, module->auto_unload); } @@ -1114,7 +1108,7 @@ static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *modu static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_input *s) { assert(t && s); pa_tagstruct_putu32(t, s->index); - pa_tagstruct_puts(t, s->name ? s->name : ""); + pa_tagstruct_puts(t, s->name); pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1); pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1); pa_tagstruct_putu32(t, s->sink->index); @@ -1127,7 +1121,7 @@ static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_inp static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) { assert(t && s); pa_tagstruct_putu32(t, s->index); - pa_tagstruct_puts(t, s->name ? s->name : ""); + pa_tagstruct_puts(t, s->name); pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1); pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1); pa_tagstruct_putu32(t, s->source->index); @@ -1183,12 +1177,12 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t if (index != (uint32_t) -1) sink = pa_idxset_get_by_index(c->protocol->core->sinks, index); else - sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1); + sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); } else if (command == PA_COMMAND_GET_SOURCE_INFO) { if (index != (uint32_t) -1) source = pa_idxset_get_by_index(c->protocol->core->sources, index); else - source = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SOURCE, 1); + source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); } else if (command == PA_COMMAND_GET_CLIENT_INFO) client = pa_idxset_get_by_index(c->protocol->core->clients, index); else if (command == PA_COMMAND_GET_MODULE_INFO) @@ -1198,7 +1192,7 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO) so = pa_idxset_get_by_index(c->protocol->core->source_outputs, index); else { - assert(command == PA_COMMAND_GET_SAMPLE_INFO && name); + assert(command == PA_COMMAND_GET_SAMPLE_INFO); if (index != (uint32_t) -1) sce = pa_idxset_get_by_index(c->protocol->core->scache, index); else @@ -1323,9 +1317,9 @@ static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, u pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec); n = pa_namereg_get_default_sink_name(c->protocol->core); - pa_tagstruct_puts(reply, n ? n : ""); + pa_tagstruct_puts(reply, n); n = pa_namereg_get_default_source_name(c->protocol->core); - pa_tagstruct_puts(reply, n ? n : ""); + pa_tagstruct_puts(reply, n); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1396,7 +1390,7 @@ static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32 if (index != (uint32_t) -1) sink = pa_idxset_get_by_index(c->protocol->core->sinks, index); else - sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1); + sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); } else { assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME); si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index); @@ -1485,7 +1479,7 @@ static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t assert(c && t); if (pa_tagstruct_getu32(t, &index) < 0 || - pa_tagstruct_gets(t, &s) < 0 || + pa_tagstruct_gets(t, &s) < 0 || !s || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1507,7 +1501,7 @@ static void command_set_stream_name(struct pa_pdispatch *pd, uint32_t command, u assert(c && t); if (pa_tagstruct_getu32(t, &index) < 0 || - pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_gets(t, &name) < 0 || !name || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1599,7 +1593,7 @@ static void command_load_module(struct pa_pdispatch *pd, uint32_t command, uint3 struct pa_tagstruct *reply; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || !name || pa_tagstruct_gets(t, &argument) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1655,9 +1649,9 @@ static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint uint32_t type; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || !name || pa_tagstruct_getu32(t, &type) < 0 || type > 1 || - pa_tagstruct_gets(t, &module) < 0 || + pa_tagstruct_gets(t, &module) < 0 || !module || pa_tagstruct_gets(t, &argument) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1683,7 +1677,7 @@ static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, u uint32_t type; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || !name || pa_tagstruct_getu32(t, &type) < 0 || type > 1 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1719,7 +1713,7 @@ static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, struct pa_tagstruct *reply; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || name || pa_tagstruct_getu32(t, &type) < 0 || type > 1 || !pa_tagstruct_eof(t)) { protocol_error(c); diff --git a/polyp/sample.c b/polyp/sample.c index 397e57a2d..143e1e414 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -94,7 +94,11 @@ void pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec [PA_SAMPLE_FLOAT32BE] = "FLOAT32BE", }; - assert(pa_sample_spec_valid(spec)); + if (!pa_sample_spec_valid(spec)) { + snprintf(s, l, "Invalid"); + return; + } + snprintf(s, l, "%s %uch %uHz", table[spec->format], spec->channels, spec->rate); } @@ -120,13 +124,13 @@ double pa_volume_to_dB(pa_volume_t v) { return 20*log10((double) v/PA_VOLUME_NORM); } -void pa_bytes_snprint(char *s, size_t l, off_t v) { - if (v >= (off_t) 1024*1024*1024) - snprintf(s, l, "%0.1f GB", (double) v/1024/1024/1024); - else if (v >= (off_t) 1024*1024) - snprintf(s, l, "%0.1f MB", (double) v/1024/1024); - else if (v >= (off_t) 1024) - snprintf(s, l, "%0.1f KB", (double) v/1024); +void pa_bytes_snprint(char *s, size_t l, unsigned v) { + if (v >= ((unsigned) 1024)*1024*1024) + snprintf(s, l, "%0.1f GB", ((double) v)/1024/1024/1024); + else if (v >= ((unsigned) 1024)*1024) + snprintf(s, l, "%0.1f MB", ((double) v)/1024/1024); + else if (v >= (unsigned) 1024) + snprintf(s, l, "%0.1f KB", ((double) v)/1024); else snprintf(s, l, "%u B", (unsigned) v); } diff --git a/polyp/sample.h b/polyp/sample.h index 1e42a2606..501172a8e 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -86,7 +86,7 @@ int pa_sample_spec_valid(const struct pa_sample_spec *spec); int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b); /** Maximum required string length for pa_sample_spec_snprint() */ -#define PA_SAMPLE_SNPRINT_MAX_LENGTH 32 +#define PA_SAMPLE_SPEC_SNPRINT_MAX 32 /** Pretty print a sample type specification to a string */ void pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec); @@ -117,7 +117,7 @@ double pa_volume_to_dB(pa_volume_t v); #endif /** Pretty print a byte size value. (i.e. "2.5 MB") */ -void pa_bytes_snprint(char *s, size_t l, off_t v); +void pa_bytes_snprint(char *s, size_t l, unsigned v); PA_C_DECL_END diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index d571b7138..39ae87b53 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -33,6 +33,7 @@ enum tags { TAG_STRING = 't', + TAG_NULL_STRING = 'N', TAG_U32 = 'L', TAG_S32 = 'l', TAG_U16 = 'S', @@ -97,12 +98,18 @@ static void extend(struct pa_tagstruct*t, size_t l) { void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s) { size_t l; - assert(t && s); - l = strlen(s)+2; - extend(t, l); - t->data[t->length] = TAG_STRING; - strcpy((char*) (t->data+t->length+1), s); - t->length += l; + assert(t); + if (s) { + l = strlen(s)+2; + extend(t, l); + t->data[t->length] = TAG_STRING; + strcpy((char*) (t->data+t->length+1), s); + t->length += l; + } else { + extend(t, 1); + t->data[t->length] = TAG_NULL_STRING; + t->length += 1; + } } void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) { @@ -173,6 +180,15 @@ int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) { char *c; assert(t && s); + if (t->rindex+1 > t->length) + return -1; + + if (t->data[t->rindex] == TAG_NULL_STRING) { + t->rindex++; + *s = NULL; + return 0; + } + if (t->rindex+2 > t->length) return -1; From 42bba491a897c996219c8aa01897f5b3cba6e33e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Sep 2004 17:19:35 +0000 Subject: [PATCH 0219/1514] update module descriptions git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@223 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + polyp/module-alsa-sink.c | 1 + polyp/module-alsa-source.c | 3 ++- polyp/module-cli.c | 1 + polyp/module-oss-mmap.c | 1 + polyp/module-oss.c | 1 + polyp/module-pipe-sink.c | 3 ++- polyp/module-pipe-source.c | 1 + polyp/module-protocol-stub.c | 8 +++++++- polyp/util.c | 4 ++-- 10 files changed, 19 insertions(+), 5 deletions(-) diff --git a/doc/todo b/doc/todo index ec9e462e1..b857075f2 100644 --- a/doc/todo +++ b/doc/todo @@ -12,6 +12,7 @@ - make mcalign merge chunks - option to use default fragment size on alsa drivers - improve module-oss-mmap latency measurement +- proper locking around native protocol socket ** later *** - xmlrpc/http diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index c31b73f0c..528fe8d30 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -43,6 +43,7 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ALSA Sink") PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink_name= device= format= channels= rate= fragments= fragment_size=") struct userdata { snd_pcm_t *pcm_handle; diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 41a17691f..c0a18d2b5 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -43,6 +43,7 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ALSA Source") PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("source_name= device= format= channels= rate= fragments= fragment_size=") struct userdata { snd_pcm_t *pcm_handle; @@ -58,9 +59,9 @@ struct userdata { static const char* const valid_modargs[] = { "device", "source_name", - "format", "channels", "rate", + "format", "fragments", "fragment_size", NULL diff --git a/polyp/module-cli.c b/polyp/module-cli.c index 94c65d078..6444194c1 100644 --- a/polyp/module-cli.c +++ b/polyp/module-cli.c @@ -36,6 +36,7 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Command line interface") PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("No arguments") static void eof_cb(struct pa_cli*c, void *userdata) { struct pa_module *m = userdata; diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 015f4c6cf..f7fcbd3ba 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -50,6 +50,7 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("OSS Sink/Source (mmap)") PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= fragments= fragment_size=") struct userdata { struct pa_sink *sink; diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 68918604f..c0c6be8ed 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -49,6 +49,7 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("OSS Sink/Source") PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= fragments= fragment_size=") struct userdata { struct pa_sink *sink; diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index 57e7425b2..c5097fb7c 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -44,6 +44,7 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("UNIX pipe sink") PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink_name= file= format= channels= rate=") #define DEFAULT_FIFO_NAME "/tmp/music.output" #define DEFAULT_SINK_NAME "fifo_output" @@ -64,8 +65,8 @@ struct userdata { static const char* const valid_modargs[] = { "file", "rate", - "channels", "format", + "channels", "sink_name", NULL }; diff --git a/polyp/module-pipe-source.c b/polyp/module-pipe-source.c index 61fcdce8c..3decc4159 100644 --- a/polyp/module-pipe-source.c +++ b/polyp/module-pipe-source.c @@ -44,6 +44,7 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("UNIX pipe source") PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("source_name= file= format= channels= rate=") #define DEFAULT_FIFO_NAME "/tmp/music.input" #define DEFAULT_SOURCE_NAME "fifo_input" diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index fe9e12a18..46522d9b5 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -42,11 +42,12 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" +#define SOCKET_USAGE "port= loopback=" #else #define SOCKET_DESCRIPTION "(UNIX sockets)" +#define SOCKET_USAGE "socket=" #endif - #if defined(USE_PROTOCOL_SIMPLE) #include "protocol-simple.h" #define protocol_new pa_protocol_simple_new @@ -55,6 +56,8 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define UNIX_SOCKET "/tmp/polypaudio/simple" #define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record", PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION) + PA_MODULE_USAGE("rate= format= channels= sink= source= playback= record= "SOCKET_USAGE) + #elif defined(USE_PROTOCOL_CLI) #include "protocol-cli.h" #define protocol_new pa_protocol_cli_new @@ -63,6 +66,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define UNIX_SOCKET "/tmp/polypaudio/cli" #define MODULE_ARGUMENTS PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION) + PA_MODULE_USAGE(SOCKET_USAGE) #elif defined(USE_PROTOCOL_NATIVE) #include "protocol-native.h" #define protocol_new pa_protocol_native_new @@ -71,6 +75,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define UNIX_SOCKET "/tmp/polypaudio/native" #define MODULE_ARGUMENTS "public", "cookie", PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) + PA_MODULE_USAGE("public= cookie= "SOCKET_USAGE) #elif defined(USE_PROTOCOL_ESOUND) #include "protocol-esound.h" #include "esound.h" @@ -80,6 +85,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", PA_MODULE_DESCRIPTION("EsounD protocol "SOCKET_DESCRIPTION) + PA_MODULE_USAGE("sink= source= public= cookie= "SOCKET_USAGE) #else #error "Broken build system" #endif diff --git a/polyp/util.c b/polyp/util.c index b9bf9f829..9b74ee759 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -368,9 +368,9 @@ char *pa_path_get_filename(const char *p) { int pa_parse_boolean(const char *v) { - if (!strcmp(v, "1") || !strcasecmp(v, "yes") || !strcasecmp(v, "y") || !strcasecmp(v, "on")) + if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on")) return 1; - else if (!strcmp(v, "0") || !strcasecmp(v, "no") || !strcasecmp(v, "n") || !strcasecmp(v, "off")) + else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off")) return 0; return -1; From bb31eda80647dd0f5ec85b5eb26c14ebd0e9d4d1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Sep 2004 19:37:28 +0000 Subject: [PATCH 0220/1514] fix xmms spawn bug git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@224 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 4 ---- polyp/polyplib-context.c | 14 +++++++------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/doc/todo b/doc/todo index b857075f2..6665de969 100644 --- a/doc/todo +++ b/doc/todo @@ -1,9 +1,5 @@ *** $Id$ *** -*** 0.5 *** -- xmms segfault when daemon not executable -- update modinfo - *** 0.6 **** - per-channel volume - unix socket directories include user name diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 8a7c719c2..32ce38885 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -388,7 +388,6 @@ static int default_server_is_running(void) { return 1; } - static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api *api) { pid_t pid; int status, r; @@ -416,26 +415,27 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api goto fail; } else if (!pid) { /* Child */ - + char t[128]; const char *state = NULL; #define MAX_ARGS 64 char *argv[MAX_ARGS+1]; - int n = 0; + int n; close(fds[0]); if (api && api->atfork) api->atfork(); - snprintf(t, sizeof(t), "%s=1", ENV_AUTOSPAWNED); - putenv(t); + /* Setup argv */ + n = 0; + argv[n++] = c->conf->daemon_binary; argv[n++] = "--daemonize=yes"; snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); - argv[n++] = t; + argv[n++] = strdup(t); while (n < MAX_ARGS) { char *a; @@ -449,7 +449,7 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api argv[n++] = NULL; execv(argv[0], argv); - exit(1); + _exit(1); } /* Parent */ From 2d87bd2d2f088220ccf98af93073cfd807dc2d1b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Sep 2004 20:52:35 +0000 Subject: [PATCH 0221/1514] documentation update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@225 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/FAQ.html.in | 22 +++++++++++-- doc/README.html.in | 46 ++++++++++++++++++++++---- doc/cli.html.in | 75 +++++++++++++++++++++++------------------- doc/daemon.html.in | 42 ++++++++++++++--------- doc/modules.html.in | 23 +++++++++++++ polyp/default.pa | 14 ++++---- polyp/main.c | 4 ++- polyp/module-combine.c | 2 +- 8 files changed, 160 insertions(+), 68 deletions(-) diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in index 074561c1f..ac9bc466c 100644 --- a/doc/FAQ.html.in +++ b/doc/FAQ.html.in @@ -64,11 +64,29 @@
  • I often hear noises when playing back with Polypaudio, what can I do?

    There are to possible solutions: either make the polypaudio binary SUID root (chmod u+s /usr/bin/polypaudio) and run it - with argument -r or increase the fragment sizes of the audio + with argument --high-priority=1 or increase the fragment sizes of the audio drivers. The former will allow Polypaudio to activate SCHED_FIFO high priority scheduling (root rights are dropped - immediately after this).

  • + immediately after this) Keep in mind that is a potential security hole!

    +
  • I only want to run polypaudio when it is needed, how do I do this?

    + +

    Set autospawn = yes in client.conf. That +configuration file may be found either in /etc/polypaudio/ or +in ~/.polypaudio/.

  • + +
  • How do I list all polypaudio modules installed?

    + +

    polypaudio --dump-modules

    + +

    Add -v for terse usage instructions.

    + +
  • What environment does polypaudio care about?

    + +

    The client honors: POLYP_SINK (default sink to connect to), POLYP_SOURCE (default source to connect to), POLYP_SERVER (default server to connect to, like ESPEAKER), POLYP_BINARY (the binary to start when autospawning a daemon), POLYP_CLIENTCONFIG (path to the client configuration file).

    + +

    The daemon honors: POLYP_SCRIPT (default CLI script file run after startup), POLYP_CONFIG (default daemon configuration file), POLYP_DLPATH (colon separated list of paths where to look for modules)

  • +
    diff --git a/doc/README.html.in b/doc/README.html.in index 837cb0120..0a33d6f08 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -44,6 +44,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    News

    +
    Mon Sep 20 2004:

    Version 0.5 released; +changes include: extensive API improvements, new module +module-combine for combining multiple sound cards into one, +gcc 2.95 compatibility, configuration files, add "lazy" samples, +support for source and network latency measurements, add +module-pipe-source, many other fixes and improvements.

    +
    Wed Sep 8 2004:

    Version 0.4 released; changes include: daemon auto spawning, support for SCHED_FIFO scheduling, three new modules, proper logging, CPU load watchdog, many fixes.

    @@ -79,6 +87,8 @@ Daemon (ESOUND). In addition to the features ESOUND provides
  • Flexible, implicit sample type conversion and resampling
  • "Zero-Copy" architecture
  • Module autoloading
  • +
  • Very accurate latency measurement for playback and recordin.
  • +
  • May be used to combine multiple sound cards to one (with sample rate adjustment)

Both the core and the client API are completely asynchronous making @@ -89,15 +99,35 @@ available through polyplib is quite difficult to use there is a simplified synchronous API wrapper polyplib-simple available. A simple main loop implementation is available as well.

+

The following modules are currently available:

+ +
    +
  • module-oss: driver for Open Sound System audio sinks and sources.
  • +
  • module-oss-mmap: same as above, but uses mmap() access to the audio buffer. Not as compatible
  • +
  • module-alsa-sink, module-alsa-source: drivers for ALSA sinks and sources
  • +
  • module-pipe-sink, module-pipe-source: demonstration module providing UNIX fifos backed sinks/sources
  • +
  • module-combine: combine multiple sinks into one.
  • +
  • module-sine: a sine generate sink input.
  • +
  • module-x11-bell: play a sample from the sample cache on every X11 bell event.
  • +
  • module-esound-protocol-tcp, module-esound-protocol-unix: ESOUND compatibility modules (for TCP/IP resp. UNIX domain sockets)
  • +
  • module-native-protocol-tcp, module-native-protocol-unix: Native polypaudio protocol (for TCP/IP resp. UNIX domain sockets)
  • +
  • module-simple-protocol-tcp, module-simple-protocol-unix: Simplistic protocol for playback/capture for usage with tools like netcat (for TCP/IP resp. UNIX domain sockets)
  • +
  • module-cli-protocol-tcp, module-cli-protocol-unix, module-cli: Expose polypaudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
  • +
+

polypaudio is the successor of my previous, ill-fated -attempt to write a sound server asd.

A GTK GUI manager application for polypaudio is the Polypaudio -Manager. Another GTK GUI tool for Polypaudio is the Polypaudio Volume Meter. There are output plugins for . Another GTK GUI tool for Polypaudio is the Polypaudio Volume +Meter. There are output plugins for XMMS and libao.

+href="http://0pointer.de/lennart/projects/libao-polyp/">libao. Drivers +for gstreamer and MPlayer will be released shortly.

Status

@@ -116,9 +146,9 @@ href="daemon.html">daemon.html, FAQ.htmlFirst Steps -

Simply start the polypaudio daemon with the argument -C

+

Simply start the polypaudio daemon with the argument -nC

-
polypaudio -C
+
polypaudio -nC

This will present you a screen like this:

@@ -130,10 +160,12 @@ href="cli.html">cli.html
. Another way to start polypaudio is by specifying a configuration script like that one included in the distribution on the command line :

-
polypaudio -F polypaudio.pa
+
polypaudio -nF polypaudio.pa

This will load some drivers and protocols automatically.

+

The best idea is to configure your daemon in /etc/polypaudio/daemon.conf and /etc/polypaudio/default.pa and to run polypaudio without any arguments.

+

Developing polypaudio Clients

You may browse the Doxygen generated for the client API. (Run make doxygen to generate thi

  • Protocol support beyond ESOUND's protocol and the native protocol. (such as NAS or a subset of aRts)
  • New programming interfaces such as XMLRPC or DBUS for controlling the daemon.
  • Hooking audio event sources directly into polypaudio (similar to module-x11-bell)
  • -
  • For low latency applications such as VOIP: load the VOIP core directly into polypaudio and have a slim GUI frontend to control it.
  • +
  • For low latency applications such as VOIP: load the VOIP core directly into polypaudio and have a slim GUI frontend to control it.
  • There is currently no documentation how to write loadable modules diff --git a/doc/cli.html.in b/doc/cli.html.in index 6f84a07d9..49e568f8f 100644 --- a/doc/cli.html.in +++ b/doc/cli.html.in @@ -28,19 +28,19 @@ commands are supported:

    Status Commands

    -

    modules

    +

    list-modules

    Show all currently loaded modules with their arguments.

    -

    sinks/sources

    +

    list-sinks/list-sources

    Show all currently registered sinks (resp. sources).

    -

    clients

    +

    list-clients

    Show all currently active clients.

    -

    sink_inputs/sink_outputs

    +

    list-sink-inputs/list-sink-outputs

    Show all currently active inputs to sinks (resp. outputs of sources).

    @@ -56,19 +56,19 @@ and list are synonyms for info.

    Module Management

    -

    load

    +

    load-module

    Load a module specified by its name and arguments. For most modules it is OK to be loaded more than once.

    -

    unload

    +

    unload-module

    Unload a module specified by its index in the module list as returned by modules.

    Configuration Commands

    -

    sink_volume

    +

    set-sink-volume

    Set the volume of the specified sink. You may specify the sink either by its index in the sink list or by its name. The volume should be an @@ -76,12 +76,12 @@ integer value greater or equal than 0 (= muted). Volume 256 (0x100) is normal volume, values greater than this amplify the audio signal with clipping.

    -

    sink_input_volume

    +

    set-sink-input-volume

    Set the volume of a sink input specified by its index the the sink input list. The same volume rules apply as with sink_volume.

    -

    sink_default/source_default

    +

    set-default-sink/set-default-source

    Make a sink (resp. source) the default. You may specify the sink (resp. ssource) by its index in the sink (resp. source) list or by its @@ -89,39 +89,46 @@ name.

    Sample Cache

    -

    scache_list

    +

    list-samples

    Lists the contents of the sample cache.

    -

    scache_play

    +

    play-sample

    Play a sample cache entry to a sink. Expects the sample name and the sink name as arguments.

    -

    sache_remove

    +

    remove-sample

    Remove an entry from the sample cache. Expects the sample name as argument.

    -

    sache_load

    +

    load-sample

    Load an audio file to the sample cache. Expects the file name to load and the desired sample name as arguments.

    +

    load-sample-lazy

    + +

    Create a new entry in the sample cache, but don't load the sample +immediately. The sample is loaded only when it is first used. After a +certain idle time it is freed again. Expects the the desired sample +name and file name to load as arguments.

    +

    Module Autoloading

    -

    autoload_list

    +

    list-autoload

    Lists all currently defined autoloading entries.

    -

    autoload_sink_add/autoload_source_add

    +

    add-autoload-sink/add-autoload-source

    Adds an autoloading entry for a sink (resp. source). Expects the sink name (resp. source name), the module name and the module arguments as arguments.

    -

    autoload_sink_remove/autoload_source_remove

    +

    remove-autoload-sink/remove-autoload-source

    Remove an autoloading entry. Expects the sink name (resp. source name) as argument.

    Miscellaneous Commands

    -

    play_file

    +

    play-file

    Play an audio file to a sink. Expects the file name and the sink name as argumens.

    @@ -131,12 +138,12 @@ name.

    Killing Clients/Streams

    -

    kill_client

    +

    kill-client

    Remove a client forcibly from the server. There is no protection that the client reconnects immediately.

    -

    kill_sink_input/kill_source_output

    +

    kill-sink-input/kill-source-output

    Remove a sink input (resp. source output) forcibly from the server. This will not remove the owning client or any other streams @@ -165,34 +172,34 @@ on the interactive command line.

    Mark the following script as executable (chmod +x) and run it for a sensible polypaudio configuration.

    -#!/usr/bin/polaudio -F
    +#!/usr/bin/polaudio -nF
     
     # Create autoload entries for the device drivers
    -autoload_sink_add output module-alsa-sink device=plughw:0,0 rate=48000 sink_name=output
    -autoload_source_add input load module-alsa-source device=hw:1,0 source_name=input
    +add-autoload-sink output module-alsa-sink device=plughw:0,0 rate=48000 sink_name=output
    +add-autoload-sink output2 module-oss device=/dev/dsp1 record=0 sink_name=output2
    +add-autoload-sink combined module-combine master=output slaves=output2 sink_name=combined
    +
    +add-autoload-source input module-alsa-source device=hw:1,0 source_name=input
     
     # Load several protocols
    -load module-esound-protocol-tcp
    -load module-simple-protocol-tcp
    -load module-native-protocol-unix
    -load module-cli-protocol-unix
    -
    -# Load the CLI module (This is similar to passing "-C" on the command line of polypaudio)
    -load module-cli
    +load-module module-esound-protocol-unix
    +load-module module-simple-protocol-tcp
    +load-module module-native-protocol-unix
    +load-module module-cli-protocol-unix
     
     # Make some devices default
    -sink_default output
    -source_default input
    +set-default-sink combined
    +set-default-source input
     
     # Don't fail if the audio files referred to below don't exist
     .nofail
     
     # Load an audio to the sample cache for usage with module-x11-bell
    -scache_load /usr/share/sounds/KDE_Notify.wav x11-bell
    -load module-x11-bell
    +load-sample-lazy  /usr/share/sounds/KDE_Notify.wav x11-bell
    +load-module module-x11-bell sample=x11-bell
     
     # Play a welcome sound
    -play_file /usr/share/sounds/startup3.wav output
    +play-file /usr/share/sounds/startup3.wav combined
     

    diff --git a/doc/daemon.html.in b/doc/daemon.html.in index e4903a8ba..147ee551b 100644 --- a/doc/daemon.html.in +++ b/doc/daemon.html.in @@ -13,28 +13,38 @@ The polypaudio daemon accepts several command line arguments: -

    -r: Set low nice value (high priority) and SCHED_FIFO scheduling if available. Works only when started as root or SUID root.

    -

    -R: Don't drop root rights if started SUID root.

    -

    -L MODULE: Load the specified module. This option may be specified more than once.

    -

    -F FILE: Run the specified script. This option may be specified more than once.

    -

    -C: Load the module module-cli after startup.

    -

    -n: Don't load the default configuration file. Normally ~/.polypaudio or /etc/polyp/polypaudio.pa are loaded on startup.

    -

    -D: Daemonize after successfully executing all scripts and loading all modules.

    -

    -d: Disallow module load and unload after startup.

    -

    -f: Unless this option is given the daemon will terminate if any of the specified modules failed to load or the script didn't execute successfully.

    -

    -v: Increase the verbosity of the daemon.

    -

    -X SECS: Terminate the daemon after the last client exited an SECS seconds passed.

    -

    -h: Show a quick help.

    -

    -l TARGET: Specify the log target (syslog, stderr, auto). Defaults to auto, which means stderr when run without -D and syslog when run with -D.

    -

    -V: Show version.

    +
    +  -h, --help                            Show this help
    +      --version                         Show version
    +      --dump-conf                       Dump default configuration
    +      --dump-modules                    Dump list of available modules
    +
    +  -D, --daemonize[=BOOL]                Daemonize after startup
    +      --fail[=BOOL]                     Quit when startup fails
    +      --verbose[=BOOL]                  Be slightly more verbose
    +      --high-priority[=BOOL]            Try to set high process priority (only available as root)
    +      --disallow-module-loading[=BOOL]  Disallow module loading after startup
    +      --exit-idle-time=SECS             Terminate the daemon when idle and this time passed
    +      --module-idle-time=SECS           Unload autoloaded modules when idle and this time passed
    +      --scache-idle-time=SECS           Unload autoloaded samples when idle and this time passed
    +      --log-target={auto,syslog,stderr} Specify the log target
    +  -p, --dl-search-path=PATH             Set the search path for dynamic shared objects (plugins)
    +      --resample-method=[METHOD]        Use the specified resampling method
    +
    +  -L, --load="MODULE ARGUMENTS"         Load the specified plugin module with the specified argument
    +  -F, --file=FILENAME                   Run the specified script
    +  -C                                    Open a command line on the running TTY after startup (identical to -Lmodule-cli)
    +
    +  -n                                    Don't load default script file
    +

    Example

    It is a good idea to run the daemon like this:

    -
    polypaudio -rD
    +
    polypaudio -D
    -

    This will run /etc/polypaudio/polypaudio.pa after startup. This should be a script written in the CLI language described in cli.html.

    +

    This will run /etc/polypaudio/default.pa after startup. This should be a script written in the CLI language described in cli.html.

    Signals

    diff --git a/doc/modules.html.in b/doc/modules.html.in index 22a565d66..6967b2a16 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -93,6 +93,29 @@ compatible as module-oss.

    This module accepts exactly the same arguments as module-oss.

    +

    module-combine

    + +

    This combines two or more sinks into one. A new virtual sink is +allocated. All data written to it is forwarded to all connected +sinks. In aequidistant intervals the sample rates of the output sinks +is recalculated: i.e. even when the sink's crystals deviate (which is +normally the case) output appears synchronously to the human ear. The +resampling required for this may be very CPU intensive.

    + + + + + + +
    sink_name=The name for the combined sink. (defaults to combined)
    master=The name of the first sink to link into the combined think. The sample rate/type is taken from this sink.
    slaves=Name of additional sinks to link into the combined think, seperated by commas.
    adjust_time=Time in seconds when to readjust the sample rate of all sinks. (defaults to 20)
    resample_method=Resampling algorithm to +use. See libsamplerate's documentation for more +information. Use one of sinc-best-quality, +sinc-medium-quality, sinc-fastest, +zero-order-hold, linear. If the default happens to +be to slow on your machine try using zero-order-hold. This +will decrease output quality however. (defaults to +sinc-fastest)
    +

    Protocols

    diff --git a/polyp/default.pa b/polyp/default.pa index ae1fbfcb3..a3aaa7c87 100755 --- a/polyp/default.pa +++ b/polyp/default.pa @@ -1,4 +1,4 @@ -#!./polypaudio -rnF +#!./polypaudio -nF # # This file is part of polypaudio. @@ -28,12 +28,12 @@ load-module module-oss device="/dev/dsp" sink_name=output source_name=input reco # Load audio drivers automatically on access -#add-autoload_sink output module-oss device="/dev/dsp" sink_name=output source_name=input -#add-autoload_source input module-oss device="/dev/dsp" sink_name=output source_name=input -#add-autoload_sink output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#add-autoload_source input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#add-autoload_sink output module-alsa-sink sink_name=output -#add-autoload_source input module-alsa-source source_name=input +#add-autoload-sink output module-oss device="/dev/dsp" sink_name=output source_name=input +#add-autoload-source input module-oss device="/dev/dsp" sink_name=output source_name=input +#add-autoload-sink output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#add-autoload-source input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#add-autoload-sink output module-alsa-sink sink_name=output +#add-autoload-source input module-alsa-source source_name=input # Load several protocols load-module module-esound-protocol-tcp diff --git a/polyp/main.c b/polyp/main.c index 107743881..dfbd1e4b1 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -180,12 +180,14 @@ int main(int argc, char *argv[]) { retval = 1; } + if (conf->verbose) + pa_log(__FILE__": daemon startup %s.\n", retval ? "failed" : "succeeded"); + goto finish; } close(daemon_pipe[0]); daemon_pipe[0] = -1; - if (conf->auto_log_target) pa_log_set_target(PA_LOG_SYSLOG, NULL); diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 1bb183ecf..6952ce6ca 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -40,7 +40,7 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Combine multiple sinks to one") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= master= slave= adjust_time= resample_method=") +PA_MODULE_USAGE("sink_name= master= slaves= adjust_time= resample_method=") #define DEFAULT_SINK_NAME "combined" #define MEMBLOCKQ_MAXLENGTH (1024*170) From 4d9af54e8c8b57a21ad7ad37570cc2cbc747cf89 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Sep 2004 21:03:52 +0000 Subject: [PATCH 0222/1514] build updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@226 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- polyp/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index f422ff687..e74cc64bb 100644 --- a/configure.ac +++ b/configure.ac @@ -72,7 +72,7 @@ AC_FUNC_REALLOC AC_FUNC_SETPGRP AC_FUNC_VPRINTF AC_TYPE_SIGNAL -AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul pow strcasecmp putenv strchr strpbrk]) +AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul pow strcasecmp putenv strchr strpbrk strdup]) AC_FUNC_STAT AC_HEADER_SYS_WAIT diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 4adc8add6..6e435156a 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -32,7 +32,7 @@ AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm -EXTRA_DIST = default.pa daemon.conf.in client.conf.in config depmod.py esdcompat.sh.in +EXTRA_DIST = default.pa daemon.conf.in client.conf.in depmod.py esdcompat.sh.in bin_PROGRAMS = polypaudio pacat pactl bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ From 766841870a1b1c54398ab168f005393ac76684a7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Sep 2004 22:22:28 +0000 Subject: [PATCH 0223/1514] add link to mailing list git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@227 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/README.html.in b/doc/README.html.in index 0a33d6f08..34caa78cf 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -226,6 +226,8 @@ compilation and make install (as root) for installation of

    If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

    +

    New! There is a general discussion mailing list for polypaudio available.

    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    $Id$
    From df953a11c98d6b8213aa66c6433340d9bb7927f3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Sep 2004 18:43:01 +0000 Subject: [PATCH 0224/1514] show which command is unknown in esound protocol fix esdcompat.sh git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@229 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/esdcompat.sh.in | 2 +- polyp/protocol-esound.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/polyp/esdcompat.sh.in b/polyp/esdcompat.sh.in index 88ff447f9..32f8d8642 100755 --- a/polyp/esdcompat.sh.in +++ b/polyp/esdcompat.sh.in @@ -80,4 +80,4 @@ EOF shift done -exec "@POLYPAUDIO_BINARY@" -r +exec "@POLYPAUDIO_BINARY@" diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 293d123a3..690083647 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -689,7 +689,7 @@ static int do_read(struct connection *c) { handler = proto_map+c->request; if (!handler->proc) { - pa_log(__FILE__": recieved unimplemented request.\n"); + pa_log(__FILE__": recieved unimplemented request #%u.\n", c->request); return -1; } From 3e1bdacd4fcd3779141c53008b983fe78e639b30 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Sep 2004 19:00:03 +0000 Subject: [PATCH 0225/1514] add noop implementation of standby/resume ESOUND commands git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@230 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/esdcompat.sh.in | 2 +- polyp/protocol-esound.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/polyp/esdcompat.sh.in b/polyp/esdcompat.sh.in index 32f8d8642..8b9cbf942 100755 --- a/polyp/esdcompat.sh.in +++ b/polyp/esdcompat.sh.in @@ -22,7 +22,7 @@ VERSION_STRING="@PACKAGE_NAME@ esd wrapper @PACKAGE_VERSION@" fail() { - echo "$1" > /dev/stderr + echo "ERROR: $1" exit 1 } diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 690083647..ccbc61be1 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -122,6 +122,7 @@ static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, const void *data, size_t length); static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t request, const void *data, size_t length); static int esd_proto_sample_get_id(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_noop(struct connection *c, esd_proto_t request, const void *data, size_t length); /* the big map of protocol handler info */ static struct proto_handler proto_map[ESD_PROTO_MAX] = { @@ -140,8 +141,8 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { sizeof(int), NULL, "sample stop" }, { -1, NULL, "TODO: sample kill" }, - { ESD_KEY_LEN + sizeof(int), NULL, "standby" }, - { ESD_KEY_LEN + sizeof(int), NULL, "resume" }, + { ESD_KEY_LEN + sizeof(int), esd_proto_noop, "standby" }, /* NOOP! */ + { ESD_KEY_LEN + sizeof(int), esd_proto_noop, "resume" }, /* NOOP! */ { ESD_NAME_MAX, esd_proto_sample_get_id, "sample getid" }, { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream filter" }, @@ -654,6 +655,14 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque return 0; } +static int esd_proto_noop(struct connection *c, esd_proto_t request, const void *data, size_t length) { + int *ok; + ok = connection_write(c, sizeof(int)); + assert(ok); + *ok = 1; + return 0; +} + /*** client callbacks ***/ static void client_kill_cb(struct pa_client *c) { From 12949d0a65bcbc9550899a6ec7b0f504a4f571b5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Sep 2004 19:40:55 +0000 Subject: [PATCH 0226/1514] support for esd arguments: -spawnpid and -spawnfd git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@231 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 12 +++- polyp/esdcompat.sh.in | 17 +++++- polyp/module-esound-compat-spawnfd.c | 79 +++++++++++++++++++++++++++ polyp/module-esound-compat-spawnpid.c | 77 ++++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 polyp/module-esound-compat-spawnfd.c create mode 100644 polyp/module-esound-compat-spawnpid.c diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 6e435156a..af324dd3e 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -103,7 +103,9 @@ modlib_LTLIBRARIES= \ module-native-protocol-unix.la \ module-native-protocol-fd.la \ module-sine.la \ - module-combine.la + module-combine.la \ + module-esound-compat-spawnfd.la \ + module-esound-compat-spawnpid.la lib_LTLIBRARIES= \ libpolyp-@PA_MAJORMINOR@.la \ @@ -302,6 +304,14 @@ module_combine_la_SOURCES = module-combine.c module_combine_la_LDFLAGS = -module -avoid-version module_combine_la_LIBADD = $(AM_LIBADD) +module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c +module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version +module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) + +module_esound_compat_spawnpid_la_SOURCES = module-esound-compat-spawnpid.c +module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version +module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) + libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ polyplib-def.h \ tagstruct.c tagstruct.h \ diff --git a/polyp/esdcompat.sh.in b/polyp/esdcompat.sh.in index 8b9cbf942..d222e1ba2 100755 --- a/polyp/esdcompat.sh.in +++ b/polyp/esdcompat.sh.in @@ -26,9 +26,13 @@ fail() { exit 1 } +ARGS="" + for N in $(seq $#) ; do case "$1" in + "") + ;; -v|--version) echo "$VERSION_STRING" @@ -62,6 +66,16 @@ Ignored directives: EOF exit 0 ;; + + -spawnpid) + shift + ARGS="$ARGS '-Lmodule-esound-compat-spawnpid pid=$1'" + ;; + + -spawnfd) + shift + ARGS="$ARGS '-Lmodule-esound-compat-spawnfd fd=$1'" + ;; -unix|-b|-public|-terminate|-nobeeps|-trust|-tcp|-promiscuous) # Ignore these commands @@ -70,6 +84,7 @@ EOF -d|-r|-as|-port|-bind) # Ignore these commands and their arguments shift + ;; *) @@ -80,4 +95,4 @@ EOF shift done -exec "@POLYPAUDIO_BINARY@" +eval "exec '@POLYPAUDIO_BINARY@'$ARGS" diff --git a/polyp/module-esound-compat-spawnfd.c b/polyp/module-esound-compat-spawnfd.c new file mode 100644 index 000000000..514159fcf --- /dev/null +++ b/polyp/module-esound-compat-spawnfd.c @@ -0,0 +1,79 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "module.h" +#include "util.h" +#include "modargs.h" +#include "log.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("ESOUND compatibility module: -spawnfd emulation") +PA_MODULE_USAGE("fd=") +PA_MODULE_VERSION(PACKAGE_VERSION) + +static const char* const valid_modargs[] = { + "fd", + NULL, +}; + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct pa_modargs *ma = NULL; + int ret = -1, fd = -1; + char x = 1; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || + pa_modargs_get_value_s32(ma, "fd", &fd) < 0 || + fd < 0) { + pa_log(__FILE__": Failed to parse module arguments\n"); + goto finish; + } + + if (pa_loop_write(fd, &x, sizeof(x)) != sizeof(x)) + pa_log(__FILE__": WARNING: write(%u, 1, 1) failed: %s\n", fd, strerror(errno)); + + close(fd); + + pa_module_unload_request(m); + + ret = 0; + +finish: + if (ma) + pa_modargs_free(ma); + + return ret; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + assert(c && m); +} + + diff --git a/polyp/module-esound-compat-spawnpid.c b/polyp/module-esound-compat-spawnpid.c new file mode 100644 index 000000000..5583f071f --- /dev/null +++ b/polyp/module-esound-compat-spawnpid.c @@ -0,0 +1,77 @@ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "module.h" +#include "util.h" +#include "modargs.h" +#include "log.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("ESOUND compatibility module: -spawnpid emulation") +PA_MODULE_USAGE("pid=") +PA_MODULE_VERSION(PACKAGE_VERSION) + +static const char* const valid_modargs[] = { + "pid", + NULL, +}; + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct pa_modargs *ma = NULL; + int ret = -1; + uint32_t pid = 0; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || + pa_modargs_get_value_u32(ma, "pid", &pid) < 0 || + !pid) { + pa_log(__FILE__": Failed to parse module arguments\n"); + goto finish; + } + + if (kill(pid, SIGUSR1) < 0) + pa_log(__FILE__": WARNING: kill(%u) failed: %s\n", pid, strerror(errno)); + + pa_module_unload_request(m); + + ret = 0; + +finish: + if (ma) + pa_modargs_free(ma); + + return ret; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + assert(c && m); +} + + From 370ff1d7cd2468c0d776bd43aa81d2d3c3a63e4a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Sep 2004 20:46:14 +0000 Subject: [PATCH 0227/1514] improve esound module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@232 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/protocol-esound.c | 21 ++++++++++++--------- polyp/scache.c | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index ccbc61be1..797263f61 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -122,7 +122,7 @@ static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, const void *data, size_t length); static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t request, const void *data, size_t length); static int esd_proto_sample_get_id(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_noop(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_standby_or_resume(struct connection *c, esd_proto_t request, const void *data, size_t length); /* the big map of protocol handler info */ static struct proto_handler proto_map[ESD_PROTO_MAX] = { @@ -134,17 +134,17 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream rec" }, { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream mon" }, - { ESD_NAME_MAX + 3 * sizeof(int), esd_proto_sample_cache, "sample cache" }, + { ESD_NAME_MAX + 3 * sizeof(int), esd_proto_sample_cache, "sample cache" }, /* 6 */ { sizeof(int), esd_proto_sample_free_or_play, "sample free" }, - { sizeof(int), esd_proto_sample_free_or_play, "sample play" }, + { sizeof(int), esd_proto_sample_free_or_play, "sample play" }, /* 8 */ { sizeof(int), NULL, "sample loop" }, { sizeof(int), NULL, "sample stop" }, { -1, NULL, "TODO: sample kill" }, - { ESD_KEY_LEN + sizeof(int), esd_proto_noop, "standby" }, /* NOOP! */ - { ESD_KEY_LEN + sizeof(int), esd_proto_noop, "resume" }, /* NOOP! */ + { ESD_KEY_LEN + sizeof(int), esd_proto_standby_or_resume, "standby" }, /* NOOP! */ + { ESD_KEY_LEN + sizeof(int), esd_proto_standby_or_resume, "resume" }, /* NOOP! */ /* 13 */ - { ESD_NAME_MAX, esd_proto_sample_get_id, "sample getid" }, + { ESD_NAME_MAX, esd_proto_sample_get_id, "sample getid" }, /* 14 */ { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream filter" }, { sizeof(int), esd_proto_server_info, "server info" }, @@ -655,11 +655,12 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque return 0; } -static int esd_proto_noop(struct connection *c, esd_proto_t request, const void *data, size_t length) { +static int esd_proto_standby_or_resume(struct connection *c, esd_proto_t request, const void *data, size_t length) { int *ok; - ok = connection_write(c, sizeof(int)); + ok = connection_write(c, sizeof(int)*2); assert(ok); - *ok = 1; + ok[0] = 1; + ok[1] = 1; return 0; } @@ -697,6 +698,8 @@ static int do_read(struct connection *c) { handler = proto_map+c->request; + pa_log(__FILE__": executing request #%u\n", c->request); + if (!handler->proc) { pa_log(__FILE__": recieved unimplemented request #%u.\n", c->request); return -1; diff --git a/polyp/scache.c b/polyp/scache.c index 963a4f863..b17f32421 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -237,7 +237,7 @@ uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { struct pa_scache_entry *e; assert(c && name); - if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) + if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) return PA_IDXSET_INVALID; return e->index; From 03ee5e2b445becf823dc4dd3db1599849e8c6c06 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Sep 2004 15:47:11 +0000 Subject: [PATCH 0228/1514] add support for capabilities git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@233 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 5 ++ doc/modules.html.in | 4 +- polyp/Makefile.am | 7 +-- polyp/caps.c | 106 +++++++++++++++++++++++++++++++++++++++++++ polyp/caps.h | 29 ++++++++++++ polyp/main.c | 13 ++---- polyp/polyplib-def.h | 3 ++ polyp/tagstruct.h | 2 + polyp/util.c | 5 ++ polyp/util.h | 1 + 10 files changed, 161 insertions(+), 14 deletions(-) create mode 100644 polyp/caps.c create mode 100644 polyp/caps.h diff --git a/configure.ac b/configure.ac index e74cc64bb..5e63d1e04 100644 --- a/configure.ac +++ b/configure.ac @@ -78,6 +78,11 @@ AC_HEADER_SYS_WAIT AC_C_BIGENDIAN +AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS='']) +AC_SUBST(CAP_LIBS) + +AC_CHECK_HEADERS(sys/capability.h) + PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) AC_SUBST(LIBSAMPLERATE_CFLAGS) AC_SUBST(LIBSAMPLERATE_LIBS) diff --git a/doc/modules.html.in b/doc/modules.html.in index 6967b2a16..00fe33887 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -106,8 +106,8 @@ resampling required for this may be very CPU intensive.

    sink_name=The name for the combined sink. (defaults to combined) master=The name of the first sink to link into the combined think. The sample rate/type is taken from this sink. slaves=Name of additional sinks to link into the combined think, seperated by commas. - adjust_time=Time in seconds when to readjust the sample rate of all sinks. (defaults to 20) - resample_method=Resampling algorithm to + adjust_time=Time in seconds when to readjust the sample rate of all sinks. (defaults to 20) + resample_method=Resampling algorithm to use. See libsamplerate's documentation for more information. Use one of sinc-best-quality, sinc-medium-quality, sinc-fastest, diff --git a/polyp/Makefile.am b/polyp/Makefile.am index af324dd3e..e52d9ab85 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -22,7 +22,7 @@ polypconfdir=$(sysconfdir)/polypaudio modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ -AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) +AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\" AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\" AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/daemon.conf\" @@ -161,11 +161,12 @@ polypaudio_SOURCES = idxset.c idxset.h \ modinfo.c modinfo.h \ daemon-conf.c daemon-conf.h \ dumpmodules.c dumpmodules.h \ - conf-parser.h conf-parser.c + conf-parser.h conf-parser.c \ + caps.h caps.c polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) -polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(LEXLIB) +polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) polypaudio_LDFLAGS=-export-dynamic libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h diff --git a/polyp/caps.c b/polyp/caps.c new file mode 100644 index 000000000..db00c604b --- /dev/null +++ b/polyp/caps.c @@ -0,0 +1,106 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#ifdef HAVE_SYS_CAPABILITY_H +#include +#endif + +#include "log.h" +#include "caps.h" + +void pa_drop_root(void) { + if (getuid() != 0 && geteuid() == 0) { + pa_log(__FILE__": Started SUID root, dropping root rights.\n"); + setuid(getuid()); + seteuid(getuid()); + } +} + +#ifdef HAVE_SYS_CAPABILITY_H +int pa_limit_caps(void) { + int r = -1; + cap_t caps; + cap_value_t nice_cap = CAP_SYS_NICE; + + caps = cap_init(); + assert(caps); + + cap_clear(caps); + cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET); + cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET); + + if (cap_set_proc(caps) < 0) + goto fail; + + pa_log(__FILE__": Started SUID root, capabilities limited.\n"); + + r = 0; + +fail: + cap_free (caps); + + return r; +} + +int pa_drop_caps(void) { + cap_t caps; + int r = -1; + + caps = cap_init(); + assert(caps); + + cap_clear(caps); + + if (cap_set_proc(caps) < 0) + goto fail; + + pa_drop_root(); + + r = 0; + +fail: + cap_free (caps); + + return r; +} + +#else + +int pa_limit_caps(void) { + return 0; +} + +int pa_drop_caps(void) { + pa_drop_root(); + return 0; +} + +#endif + diff --git a/polyp/caps.h b/polyp/caps.h new file mode 100644 index 000000000..473462fbc --- /dev/null +++ b/polyp/caps.h @@ -0,0 +1,29 @@ +#ifndef foocapshfoo +#define foocapshfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +void pa_drop_root(void); +int pa_limit_caps(void); +int pa_drop_caps(void); + +#endif diff --git a/polyp/main.c b/polyp/main.c index dfbd1e4b1..2a45ad37c 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -47,17 +47,10 @@ #include "log.h" #include "daemon-conf.h" #include "dumpmodules.h" +#include "caps.h" static struct pa_mainloop *mainloop; -static void drop_root(void) { - if (getuid() != 0 && geteuid() == 0) { - pa_log(__FILE__": Started SUID root, dropping root rights.\n"); - setuid(getuid()); - seteuid(getuid()); - } -} - static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { pa_log(__FILE__": Got signal %s.\n", pa_strsignal(sig)); @@ -95,6 +88,8 @@ int main(int argc, char *argv[]) { int r, retval = 1, d = 0; int daemon_pipe[2] = { -1, -1 }; + pa_limit_caps(); + r = lt_dlinit(); assert(r == 0); @@ -118,7 +113,7 @@ int main(int argc, char *argv[]) { if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) pa_raise_priority(); - drop_root(); + pa_drop_caps(); if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 591d237d5..bab23e473 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -23,6 +23,9 @@ ***/ #include +#include +#include + #include "cdecl.h" #include "sample.h" diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index 02df74e4d..e50551c41 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -24,6 +24,8 @@ #include #include +#include +#include #include "sample.h" diff --git a/polyp/util.c b/polyp/util.c index 9b74ee759..cc132dbb1 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -40,6 +40,11 @@ #include #include #include +#include +#include +#include +#include + #include diff --git a/polyp/util.h b/polyp/util.h index c842a1c38..4a387cef0 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -66,4 +66,5 @@ const char *pa_strsignal(int sig); int pa_parse_resample_method(const char *string); + #endif From 9e3890abb4c8427d69b0be751d516b4c1ff6118d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Sep 2004 15:57:15 +0000 Subject: [PATCH 0229/1514] OSX protability patches from Conrad Parker git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@234 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/authkey.c | 1 + polyp/main.c | 2 +- polyp/module-protocol-stub.c | 1 + polyp/namereg.c | 1 - polyp/pstream.c | 1 + polyp/tagstruct.c | 2 ++ polyp/util.c | 1 + 7 files changed, 7 insertions(+), 2 deletions(-) diff --git a/polyp/authkey.c b/polyp/authkey.c index bbc45c378..9b60506ff 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "authkey.h" #include "util.h" diff --git a/polyp/main.c b/polyp/main.c index 2a45ad37c..0e55528df 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -188,7 +188,7 @@ int main(int argc, char *argv[]) { pa_log_set_target(PA_LOG_SYSLOG, NULL); setsid(); - setpgrp(); + setpgid(0,0); close(0); close(1); diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 46522d9b5..17c491dea 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "module.h" #include "socket-server.h" diff --git a/polyp/namereg.c b/polyp/namereg.c index 5791a3e45..e2f65efd3 100644 --- a/polyp/namereg.c +++ b/polyp/namereg.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include "namereg.h" diff --git a/polyp/pstream.c b/polyp/pstream.c index b0de9e8c6..5fe2b4e75 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "pstream.h" diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 39ae87b53..bbebdab34 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -25,6 +25,8 @@ #include #include +#include +#include #include #include diff --git a/polyp/util.c b/polyp/util.c index cc132dbb1..7148654a2 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include From dfcd161a52285649b6ff63ae5c191f37a494884d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Sep 2004 16:33:38 +0000 Subject: [PATCH 0230/1514] Fix a bug in the build system reported by Iain Fothergill git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@235 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index e52d9ab85..c53913115 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -439,7 +439,7 @@ lib_LTLIBRARIES+= \ libpolyp-mainloop-glib-@PA_MAJORMINOR@.la noinst_PROGRAMS+= \ - mainloop-test-glib12 + mainloop-test-glib libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib-mainloop.c libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) @@ -459,7 +459,8 @@ lib_LTLIBRARIES+= \ libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la noinst_PROGRAMS+= \ - mainloop-test-glib + mainloop-test-glib12 + libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib12-mainloop.c libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB12_LIBS) From 6d2054458ed8bbdcdc4bdf0c57e4294fdc8a7676 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Sep 2004 20:41:49 +0000 Subject: [PATCH 0231/1514] place full binary path in default.pa's shebang line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@236 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 5 ++++- polyp/{default.pa => default.pa.in} | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) rename polyp/{default.pa => default.pa.in} (98%) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index c53913115..4e0754682 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -32,7 +32,7 @@ AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm -EXTRA_DIST = default.pa daemon.conf.in client.conf.in depmod.py esdcompat.sh.in +EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in bin_PROGRAMS = polypaudio pacat pactl bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ @@ -557,6 +557,9 @@ esdcompat.sh: esdcompat.sh.in Makefile client.conf: client.conf.in Makefile sed -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ +default.pa: default.pa.in Makefile + sed -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ + daemon.conf: daemon.conf.in Makefile sed -e 's,@DLSEARCHPATH\@,$(modlibdir),g' \ -e 's,@DEFAULT_CONFIG_FILE\@,$(polypconfdir)/daemon.conf,g' < $< > $@ diff --git a/polyp/default.pa b/polyp/default.pa.in similarity index 98% rename from polyp/default.pa rename to polyp/default.pa.in index a3aaa7c87..54feb5ef7 100755 --- a/polyp/default.pa +++ b/polyp/default.pa.in @@ -1,4 +1,4 @@ -#!./polypaudio -nF +#!@POLYPAUDIO_BINARY@ -nF # # This file is part of polypaudio. From 8176b3a1ba5020e0639f648a7f41f79f54cbcac2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Sep 2004 20:42:52 +0000 Subject: [PATCH 0232/1514] ignore default.in git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@237 fefdeb5f-60dc-0310-8127-8f9354f1896f From ed36241085da8f797adf7d70ab702fee10e8cba0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Sep 2004 22:42:49 +0000 Subject: [PATCH 0233/1514] allow high priority scheduling only for users in group "realtime" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@238 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/caps.c | 26 +++++++++++++-------- polyp/main.c | 26 +++++++++++++++------ polyp/util.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++---- polyp/util.h | 1 + 4 files changed, 96 insertions(+), 21 deletions(-) diff --git a/polyp/caps.c b/polyp/caps.c index db00c604b..258e13e41 100644 --- a/polyp/caps.c +++ b/polyp/caps.c @@ -36,14 +36,19 @@ #include "caps.h" void pa_drop_root(void) { - if (getuid() != 0 && geteuid() == 0) { - pa_log(__FILE__": Started SUID root, dropping root rights.\n"); - setuid(getuid()); - seteuid(getuid()); - } + uid_t uid = getuid(); + + if (uid == 0 || geteuid() != 0) + return; + + pa_log(__FILE__": dropping root rights.\n"); + + setuid(uid); + seteuid(uid); } #ifdef HAVE_SYS_CAPABILITY_H + int pa_limit_caps(void) { int r = -1; cap_t caps; @@ -53,14 +58,15 @@ int pa_limit_caps(void) { assert(caps); cap_clear(caps); + cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET); if (cap_set_proc(caps) < 0) goto fail; - pa_log(__FILE__": Started SUID root, capabilities limited.\n"); - + pa_log(__FILE__": dropped capabilities successfully.\n"); + r = 0; fail: @@ -78,10 +84,10 @@ int pa_drop_caps(void) { cap_clear(caps); - if (cap_set_proc(caps) < 0) + if (cap_set_proc(caps) < 0) { + pa_log(__FILE__": failed to drop capabilities: %s\n", strerror(errno)); goto fail; - - pa_drop_root(); + } r = 0; diff --git a/polyp/main.c b/polyp/main.c index 0e55528df..08677f7fc 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -49,8 +49,6 @@ #include "dumpmodules.h" #include "caps.h" -static struct pa_mainloop *mainloop; - static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { pa_log(__FILE__": Got signal %s.\n", pa_strsignal(sig)); @@ -84,22 +82,33 @@ int main(int argc, char *argv[]) { struct pa_core *c; struct pa_strbuf *buf = NULL; struct pa_daemon_conf *conf; + struct pa_mainloop *mainloop; + char *s; int r, retval = 1, d = 0; int daemon_pipe[2] = { -1, -1 }; + gid_t gid = (gid_t) -1; + int suid_root; pa_limit_caps(); + + suid_root = getuid() != 0 && geteuid() == 0; + + if (suid_root && (pa_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) { + pa_log(__FILE__": WARNING: called SUID root, but not in group 'realtime'.\n"); + pa_drop_root(); + } r = lt_dlinit(); assert(r == 0); pa_log_set_ident("polypaudio"); - + conf = pa_daemon_conf_new(); - + if (pa_daemon_conf_load(conf, NULL) < 0) goto finish; - + if (pa_daemon_conf_env(conf) < 0) goto finish; @@ -107,13 +116,16 @@ int main(int argc, char *argv[]) { pa_log(__FILE__": failed to parse command line.\n"); goto finish; } - + pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL); if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) pa_raise_priority(); - + pa_drop_caps(); + + if (suid_root) + pa_drop_root(); if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); diff --git a/polyp/util.c b/polyp/util.c index 7148654a2..1246bbb5b 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -41,11 +41,8 @@ #include #include #include -#include -#include -#include #include - +#include #include @@ -444,3 +441,62 @@ int pa_parse_resample_method(const char *string) { else return -1; } + +static int is_group(gid_t gid, const char *name) { + struct group group, *result = NULL; + long n = sysconf(_SC_GETGR_R_SIZE_MAX); + void *data; + int r = -1; + + assert(n > 0); + data = pa_xmalloc(n); + + if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) { + pa_log(__FILE__ ": getgrgid_r(%u) failed: %s\n", gid, strerror(errno)); + goto finish; + } + + + r = strcmp(name, result->gr_name) == 0; + +finish: + pa_xfree(data); + + return r; +} + +int pa_uid_in_group(const char *name, gid_t *gid) { + gid_t *gids, tgid; + long n = sysconf(_SC_NGROUPS_MAX); + int r = -1, i; + + assert(n > 0); + + gids = pa_xmalloc(sizeof(gid_t)*n); + + if ((n = getgroups(n, gids)) < 0) { + pa_log(__FILE__": getgroups() failed: %s\n", strerror(errno)); + goto finish; + } + + for (i = 0; i < n; i++) { + if (is_group(gids[i], name) > 0) { + *gid = gids[i]; + r = 1; + goto finish; + } + } + + if (is_group(tgid = getgid(), name) > 0) { + *gid = tgid; + r = 1; + goto finish; + } + + r = 0; + +finish: + + pa_xfree(gids); + return r; +} diff --git a/polyp/util.h b/polyp/util.h index 4a387cef0..8f4323f67 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -66,5 +66,6 @@ const char *pa_strsignal(int sig); int pa_parse_resample_method(const char *string); +int pa_uid_in_group(const char *name, gid_t *gid); #endif From 405fac5ea7070fa7b50a77952fa8042f87f588a8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Sep 2004 23:26:15 +0000 Subject: [PATCH 0234/1514] bump version number and update documentation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@239 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- doc/FAQ.html.in | 57 +++++++++++++++++++++++++++++++++++++++------ doc/README.html.in | 11 ++++++++- doc/modules.html.in | 10 +++++++- 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 5e63d1e04..24a7e9856 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.5],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.5.1],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in index ac9bc466c..f1bf24149 100644 --- a/doc/FAQ.html.in +++ b/doc/FAQ.html.in @@ -62,14 +62,34 @@ embed Polypaudio in the aRts process.

  • I often hear noises when playing back with Polypaudio, what can I do?

    -

    There are to possible solutions: either make the polypaudio - binary SUID root (chmod u+s /usr/bin/polypaudio) and run it - with argument --high-priority=1 or increase the fragment sizes of the audio +

    There are to possible solutions: run polypaudio with argument +--high-priority=1 and make yourself member of the group +realtime, or increase the fragment sizes of the audio drivers. The former will allow Polypaudio to activate SCHED_FIFO high priority scheduling (root rights are dropped - immediately after this) Keep in mind that is a potential security hole!

  • + immediately after this) Keep in mind that this is a potential security hole!

    -
  • I only want to run polypaudio when it is needed, how do I do this?

    +
  • The polypaudio executable is installed SUID root by default. Why this? Isn't this a potential security hole?

    + +

    Polypaudio activates SCHED_FIFO scheduling if the user +passes --high-priority=1. This will only succeed when +executed as root, therefore the binary is marked SUID root by +default. Yes, this is a potential security hole. However, polypaudio +tries its best to minimize the security threat: immediately after +startup polypaudio drops all capabilities except +CAP_SYS_NICE (At least on systems that support it, like Linux; see man 7 +capabilities for more information). If the calling user is not a +member of the group realtime (which is required to have a GID +< 1000), root rights are dropped immediately. This means, you can +install polypaudio SUID root, but only a subset of your users (the +members of the group realtime) may make use of realtime +scheduling. Keep in mind that these users might load their own binary +modules into the polypaudio daemon which may freeze the machine. The +daemon has a minimal protection against CPU hogging (the daemon is +killed after hogging more than 70% CPU for 5 seconds), but this may +be circumvented easily by evildoers.

  • + +
  • I want to run polypaudio only when it is needed, how do I do this?

    Set autospawn = yes in client.conf. That configuration file may be found either in /etc/polypaudio/ or @@ -81,12 +101,35 @@ in ~/.polypaudio/.

  • Add -v for terse usage instructions.

    -
  • What environment does polypaudio care about?

    +
  • How do I use polypaudio over the network?

    + +

    Just set $POLYP_SERVER to the host name of the polypaudio server.

    + +
  • Is polypaudio capable of providing synchronized audio playback over the network for movie players like mplayer?

    + +

    Yes! Unless your network is congested in some way (i.e. transfer latencies vary strongly) it works perfectly. Drop me an email for experimental patches for MPlayer.

    + +
  • What environment variables does polypaudio care about?

    The client honors: POLYP_SINK (default sink to connect to), POLYP_SOURCE (default source to connect to), POLYP_SERVER (default server to connect to, like ESPEAKER), POLYP_BINARY (the binary to start when autospawning a daemon), POLYP_CLIENTCONFIG (path to the client configuration file).

    The daemon honors: POLYP_SCRIPT (default CLI script file run after startup), POLYP_CONFIG (default daemon configuration file), POLYP_DLPATH (colon separated list of paths where to look for modules)

  • - + + +
  • I saw that SIGUSR2 provokes loading of the module module-cli-protocol-unix. But how do I make use of that?

    + +

    A brilliant guy named Lennart Poettering once wrote a nifty tool +for that purpose: bidilink. To +connect to a running polypaudio daemon try using the following commands:

    + +
    killall -USR2 polypaudio
    +bidilink unix-client:/tmp/polypaudio/cli
    + +

    BTW: Someone should package that great tool for Debian!

    + +
  • +
    diff --git a/doc/README.html.in b/doc/README.html.in index 34caa78cf..a0b3e6415 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -44,6 +44,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    News

    +
    Mon Sep 24 2004:

    Version 0.5.1 released; +changes include: improve esound protocol compatibility; fix +autospawning via libesd; make use of POSIX capabilities; +allow SCHED_FIFO scheduling only for users in group +realtime; minor build system fix.

    +
    Mon Sep 20 2004:

    Version 0.5 released; changes include: extensive API improvements, new module @@ -222,7 +229,9 @@ compilation and make install (as root) for installation of

    The current release is @PACKAGE_VERSION@

    -

    Get polypaudio's development sources from the Subversion repository. (viewcvs)

    +

    Get polypaudio's development sources from the Subversion repository (viewcvs):

    + +
    svn checkout svn://seth.intheinter.net/polypaudio/trunk polypaudio

    If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

    diff --git a/doc/modules.html.in b/doc/modules.html.in index 00fe33887..4bf6044ba 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -220,7 +220,7 @@ about the two possible suffixes of this module.

    module-native-protocol-fd

    -

    This is used internally when auto spawning a new daemon.

    +

    This is used internally when auto spawning a new daemon. Don't use it directly.

    Miscellaneous

    @@ -243,6 +243,14 @@ about the two possible suffixes of this module.

    frequency=The frequency to generate in Hertz. Defaults to 440. +

    module-esound-compat-spawnfd

    + +

    This is a compatibility module for libesd based autospawning of polypaudio. Don't use it directly.

    + +

    module-esound-compat-spawnpid

    + +

    This is a compatibility module for libesd based autospawning of polypaudio. Don't use it directly.

    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    $Id$
    From 5bac3c3ce515cb588f3928431db4fe1c396d53e7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 26 Sep 2004 17:02:26 +0000 Subject: [PATCH 0235/1514] bum version number add new macro PA_API_VERSION for preprocessor level conditional compiling add new native APIs: - counter - cork & flush for record streams - add flags parameters to pa_stream_connect_xx() - new prebuf command - time api, and total latency calculator - return sample spec ability to cork source output streams dump server status on SIGHUP to syslog show sink input/source outputs status in cli-text.c don't flush esound output buffer when client disconnects move version api to polyplib-version.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@240 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- doc/todo | 12 +++-- polyp/cli-text.c | 28 ++++++++--- polyp/cpulimit.c | 2 +- polyp/main.c | 47 +++++++++++++++++- polyp/memblockq.c | 9 +++- polyp/memblockq.h | 3 ++ polyp/native-common.h | 3 ++ polyp/pacat.c | 8 ++- polyp/pactl.c | 4 ++ polyp/polyplib-context.c | 4 +- polyp/polyplib-def.h | 5 ++ polyp/polyplib-internal.h | 2 + polyp/polyplib-simple.c | 4 +- polyp/polyplib-stream.c | 102 ++++++++++++++++++++++++++++++++++---- polyp/polyplib-stream.h | 40 ++++++++++++--- polyp/polyplib.h | 7 --- polyp/protocol-esound.c | 89 +++++++++++++++++++-------------- polyp/protocol-native.c | 76 ++++++++++++++++++++++++++-- polyp/sample.c | 2 +- polyp/sample.h | 2 +- polyp/sink-input.c | 14 +++--- polyp/sink-input.h | 3 +- polyp/source-output.c | 14 +++++- polyp/source-output.h | 3 ++ polyp/util.c | 1 + 26 files changed, 392 insertions(+), 94 deletions(-) diff --git a/configure.ac b/configure.ac index 24a7e9856..3a0675c3f 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.5.1],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.6],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) diff --git a/doc/todo b/doc/todo index 6665de969..6bbd70ad8 100644 --- a/doc/todo +++ b/doc/todo @@ -4,23 +4,29 @@ - per-channel volume - unix socket directories include user name - add sample directory -- udp based protocol - make mcalign merge chunks - option to use default fragment size on alsa drivers - improve module-oss-mmap latency measurement - proper locking around native protocol socket +- pacat sample type args +- filter capture data in client through alignment +- paplay +- check module-combine algo +- add redirection module +- add matching module +- add radio module +- make autoload list use idxset ** later *** - xmlrpc/http - dbus - slp/rendezvous -- modinfo - make alsa modules use mmap *********** backends for: -- portaudio +- portaudio (semi-done) - alsa-lib - sdl - gstreamer (semi-done) diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 3cedf920d..f9bc6c7a7 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -64,7 +64,7 @@ char *pa_client_list_to_string(struct pa_core *c) { s = pa_strbuf_new(); assert(s); - pa_strbuf_printf(s, "%u client(s).\n", pa_idxset_ncontents(c->clients)); + pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_ncontents(c->clients)); for (client = pa_idxset_first(c->clients, &index); client; client = pa_idxset_next(c->clients, &index)) { pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tprotocol_name: <%s>\n", client->index, client->name, client->protocol_name); @@ -148,6 +148,11 @@ char *pa_source_output_list_to_string(struct pa_core *c) { struct pa_strbuf *s; struct pa_source_output *o; uint32_t index = PA_IDXSET_INVALID; + static const char* const state_table[] = { + "RUNNING", + "CORKED", + "DISCONNECTED" + }; assert(c); s = pa_strbuf_new(); @@ -160,15 +165,16 @@ char *pa_source_output_list_to_string(struct pa_core *c) { pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec); assert(o->source); pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\tsource: <%u>\n\tsample_spec: <%s>\n", + s, " index: %u\n\tname: '%s'\n\tstate: %s\n\tsource: <%u> '%s'\n\tsample_spec: <%s>\n", o->index, o->name, - o->source->index, + state_table[o->state], + o->source->index, o->source->name, ss); if (o->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", o->owner->index); if (o->client) - pa_strbuf_printf(s, "\tclient: <%u>\n", o->client->index); + pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", o->client->index, o->client->name); } return pa_strbuf_tostring_free(s); @@ -178,8 +184,13 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { struct pa_strbuf *s; struct pa_sink_input *i; uint32_t index = PA_IDXSET_INVALID; - assert(c); + static const char* const state_table[] = { + "RUNNING", + "CORKED", + "DISCONNECTED" + }; + assert(c); s = pa_strbuf_new(); assert(s); @@ -190,10 +201,11 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n", + s, " index: %u\n\tname: <%s>\n\tstate: %s\n\tsink: <%u> '%s'\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n", i->index, i->name, - i->sink->index, + state_table[i->state], + i->sink->index, i->sink->name, (unsigned) i->volume, pa_volume_to_dB(i->volume), (float) pa_sink_input_get_latency(i), @@ -202,7 +214,7 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { if (i->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", i->owner->index); if (i->client) - pa_strbuf_printf(s, "\tclient: <%u>\n", i->client->index); + pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", i->client->index, i->client->name); } return pa_strbuf_tostring_free(s); diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c index fc49f5bb4..a60c03d78 100644 --- a/polyp/cpulimit.c +++ b/polyp/cpulimit.c @@ -35,7 +35,7 @@ /* Utilize this much CPU time at maximum */ #define CPUTIME_PERCENT 70 -#define CPUTIME_INTERVAL_SOFT (5) +#define CPUTIME_INTERVAL_SOFT (10) #define CPUTIME_INTERVAL_HARD (2) static time_t last_time = 0; diff --git a/polyp/main.c b/polyp/main.c index 08677f7fc..0837e58df 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -48,6 +48,7 @@ #include "daemon-conf.h" #include "dumpmodules.h" #include "caps.h" +#include "cli-text.h" static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { pa_log(__FILE__": Got signal %s.\n", pa_strsignal(sig)); @@ -60,7 +61,47 @@ static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, case SIGUSR2: pa_module_load(userdata, "module-cli-protocol-unix", NULL); return; - + + case SIGHUP: { + int i; + + for (i = 0;; i++) { + char *c; + switch (i) { + case 0: + c = pa_sink_list_to_string(userdata); + break; + case 1: + c = pa_source_list_to_string(userdata); + break; + case 2: + c = pa_sink_input_list_to_string(userdata); + break; + case 3: + c = pa_source_output_list_to_string(userdata); + break; + case 4: + c = pa_client_list_to_string(userdata); + break; + case 5: + c = pa_module_list_to_string(userdata); + break; + case 6: + c = pa_scache_list_to_string(userdata); + break; + case 7: + c = pa_autoload_list_to_string(userdata); + break; + default: + return; + } + pa_log(c); + pa_xfree(c); + } + + return; + } + case SIGINT: case SIGTERM: default: @@ -70,7 +111,8 @@ static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, } } -static void close_pipe(int p[2]) { + + static void close_pipe(int p[2]) { if (p[0] != -1) close(p[0]); if (p[1] != -1) @@ -223,6 +265,7 @@ int main(int argc, char *argv[]) { pa_signal_new(SIGUSR1, signal_callback, c); pa_signal_new(SIGUSR2, signal_callback, c); + pa_signal_new(SIGHUP, signal_callback, c); r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop)); assert(r == 0); diff --git a/polyp/memblockq.c b/polyp/memblockq.c index 59794d6c1..0e71fa8c0 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -42,7 +42,7 @@ struct memblock_list { struct pa_memblockq { struct memblock_list *blocks, *blocks_tail; unsigned n_blocks; - size_t current_length, maxlength, tlength, base, prebuf, minreq; + size_t current_length, maxlength, tlength, base, prebuf, orig_prebuf, minreq; struct pa_mcalign *mcalign; struct pa_memblock_stat *memblock_stat; }; @@ -72,6 +72,8 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b bq->prebuf = (bq->prebuf/base)*base; if (bq->prebuf > bq->maxlength) bq->prebuf = bq->maxlength; + + bq->orig_prebuf = bq->prebuf; bq->minreq = (minreq/base)*base; if (bq->minreq == 0) @@ -285,6 +287,11 @@ void pa_memblockq_prebuf_disable(struct pa_memblockq *bq) { bq->prebuf = 0; } +void pa_memblockq_prebuf_reenable(struct pa_memblockq *bq) { + assert(bq); + bq->prebuf = bq->orig_prebuf; +} + void pa_memblockq_seek(struct pa_memblockq *bq, size_t length) { assert(bq); diff --git a/polyp/memblockq.h b/polyp/memblockq.h index 16b51d7a8..aeed41934 100644 --- a/polyp/memblockq.h +++ b/polyp/memblockq.h @@ -83,6 +83,9 @@ uint32_t pa_memblockq_get_minreq(struct pa_memblockq *bq); /* Force disabling of pre-buf even when the pre-buffer is not yet filled */ void pa_memblockq_prebuf_disable(struct pa_memblockq *bq); +/* Reenable pre-buf to the initial level */ +void pa_memblockq_prebuf_reenable(struct pa_memblockq *bq); + /* Manipulate the write pointer */ void pa_memblockq_seek(struct pa_memblockq *bq, size_t delta); diff --git a/polyp/native-common.h b/polyp/native-common.h index a052fca27..5ecb26c07 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -87,6 +87,9 @@ enum { PA_COMMAND_GET_AUTOLOAD_INFO, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, PA_COMMAND_GET_RECORD_LATENCY, + PA_COMMAND_CORK_RECORD_STREAM, + PA_COMMAND_FLUSH_RECORD_STREAM, + PA_COMMAND_PREBUF_PLAYBACK_STREAM, PA_COMMAND_MAX }; diff --git a/polyp/pacat.c b/polyp/pacat.c index b9cb047ad..1eb37d4da 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -37,6 +37,10 @@ #include #include +#if PA_API_VERSION != PA_API_VERSION_0_6 +#error Invalid Polypaudio API version +#endif + static enum { RECORD, PLAYBACK } mode = PLAYBACK; static struct pa_context *context = NULL; @@ -165,9 +169,9 @@ static void context_state_callback(struct pa_context *c, void *userdata) { pa_stream_set_read_callback(stream, stream_read_callback, NULL); if (mode == PLAYBACK) - pa_stream_connect_playback(stream, device, NULL, volume); + pa_stream_connect_playback(stream, device, NULL, 0, volume); else - pa_stream_connect_record(stream, device, NULL); + pa_stream_connect_record(stream, device, NULL, 0); break; diff --git a/polyp/pactl.c b/polyp/pactl.c index 2a466b39c..cf2f51c39 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -41,6 +41,10 @@ #include #include +#if PA_API_VERSION != PA_API_VERSION_0_6 +#error Invalid Polypaudio API version +#endif + #define BUFSIZE 1024 static struct pa_context *context = NULL; diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 32ce38885..d793c186f 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -218,8 +218,10 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui pa_context_ref(c); if ((s = pa_dynarray_get(c->record_streams, channel))) { - if (s->read_callback) + if (s->read_callback) { s->read_callback(s, (uint8_t*) chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); + s->counter += chunk->length; + } } pa_context_unref(c); diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index bab23e473..cd0662dda 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -72,6 +72,11 @@ enum pa_stream_direction { PA_STREAM_UPLOAD /**< Sample upload stream */ }; +/** Some special flags for stream connections. \since 0.6 */ +enum pa_stream_flags { + PA_STREAM_START_CORKED = 1, /**< Create the stream corked, requiring an explicit pa_stream_cork() call to uncork it. */ +}; + /** Playback and record buffer metrics */ struct pa_buffer_attr{ uint32_t maxlength; /**< Maximum length of the buffer */ diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 6e64755db..656d07dbe 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -92,6 +92,8 @@ struct pa_stream { uint32_t device_index; enum pa_stream_direction direction; uint32_t requested_bytes; + uint64_t counter; + pa_usec_t previous_time; enum pa_stream_state state; void (*state_callback)(struct pa_stream*c, void *userdata); diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index aa6c88f5a..9e111e2a1 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -156,9 +156,9 @@ struct pa_simple* pa_simple_new( goto fail; if (dir == PA_STREAM_PLAYBACK) - pa_stream_connect_playback(p->stream, dev, attr, volume); + pa_stream_connect_playback(p->stream, dev, attr, 0, volume); else - pa_stream_connect_record(p->stream, dev, attr); + pa_stream_connect_record(p->stream, dev, attr, 0); /* Wait until the stream is ready */ while (pa_stream_get_state(p->stream) != PA_STREAM_READY) { diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 8bd098d43..291c3cd39 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -47,7 +47,7 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st s->state_callback = NULL; s->state_userdata = NULL; - s->state = PA_STREAM_NODIRECTION; + s->direction = PA_STREAM_NODIRECTION; s->name = pa_xstrdup(name); s->sample_spec = *ss; s->channel = 0; @@ -57,6 +57,9 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st s->state = PA_STREAM_DISCONNECTED; memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + s->counter = 0; + s->previous_time = 0; + PA_LLIST_PREPEND(struct pa_stream, c->streams, s); return pa_stream_ref(s); @@ -211,7 +214,7 @@ finish: pa_stream_unref(s); } -static void create_stream(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, pa_volume_t volume) { +static void create_stream(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, enum pa_stream_flags flags, pa_volume_t volume) { struct pa_tagstruct *t; uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED); @@ -247,6 +250,7 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, dev); pa_tagstruct_putu32(t, s->buffer_attr.maxlength); + pa_tagstruct_put_boolean(t, !!(flags & PA_STREAM_START_CORKED)); if (s->direction == PA_STREAM_PLAYBACK) { pa_tagstruct_putu32(t, s->buffer_attr.tlength); pa_tagstruct_putu32(t, s->buffer_attr.prebuf); @@ -261,16 +265,16 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ pa_stream_unref(s); } -void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, pa_volume_t volume) { +void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, enum pa_stream_flags flags, pa_volume_t volume) { assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); s->direction = PA_STREAM_PLAYBACK; - create_stream(s, dev, attr, volume); + create_stream(s, dev, attr, flags, volume); } -void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) { +void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, enum pa_stream_flags flags) { assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); s->direction = PA_STREAM_RECORD; - create_stream(s, dev, attr, 0); + create_stream(s, dev, attr, flags, 0); } void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void (*free_cb)(void *p), size_t delta) { @@ -295,6 +299,8 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void s->requested_bytes -= length; else s->requested_bytes = 0; + + s->counter += length; } size_t pa_stream_writable_size(struct pa_stream *s) { @@ -506,10 +512,10 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru t = pa_tagstruct_new(NULL, 0); assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_CORK_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CORK_PLAYBACK_STREAM : PA_COMMAND_CORK_RECORD_STREAM); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); - pa_tagstruct_putu32(t, !!b); + pa_tagstruct_put_boolean(t, !!b); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); @@ -537,7 +543,11 @@ struct pa_operation* pa_stream_send_simple_command(struct pa_stream *s, uint32_t } struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { - return pa_stream_send_simple_command(s, PA_COMMAND_FLUSH_PLAYBACK_STREAM, cb, userdata); + return pa_stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata); +} + +struct pa_operation* pa_stream_prebuf(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { + return pa_stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata); } struct pa_operation* pa_stream_trigger(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { @@ -566,3 +576,77 @@ struct pa_operation* pa_stream_set_name(struct pa_stream *s, const char *name, v return pa_operation_ref(o); } + +uint64_t pa_stream_get_counter(struct pa_stream *s) { + assert(s); + return s->counter; +} + +void pa_stream_reset_counter(struct pa_stream *s) { + assert(s); + s->counter = 0; + s->previous_time = 0; +} + +pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info *i) { + pa_usec_t usec; + assert(s); + + usec = pa_bytes_to_usec(s->counter, &s->sample_spec); + + if (i) { + if (s->direction == PA_STREAM_PLAYBACK) { + pa_usec_t latency = i->transport_usec + i->buffer_usec + i->sink_usec; + if (usec < latency) + usec = 0; + else + usec -= latency; + + } else if (s->direction == PA_STREAM_RECORD) { + usec += i->source_usec + i->buffer_usec + i->transport_usec; + + if (usec > i->sink_usec) + usec -= i->sink_usec; + else + usec = 0; + } + } + + if (usec < s->previous_time) + usec = s->previous_time; + + s->previous_time = usec; + + return usec; +} + +pa_usec_t pa_stream_get_total_latency(struct pa_stream *s, const struct pa_latency_info *i, int *negative) { + assert(s && i); + + if (s->direction == PA_STREAM_PLAYBACK) { + if (negative) + *negative = 0; + + return i->transport_usec + i->buffer_usec + i->sink_usec; + } else if (s->direction == PA_STREAM_RECORD) { + pa_usec_t usec = i->source_usec + i->buffer_usec + i->transport_usec; + + if (usec >= i->sink_usec) { + if (negative) + *negative = 0; + return usec - i->sink_usec; + } else { + if (negative) + *negative = 1; + + return i->sink_usec - usec; + } + } + + return 0; +} + +const struct pa_sample_spec* pa_stream_get_sample_spec(struct pa_stream *s) { + assert(s); + return &s->sample_spec; +} diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index 257f2b996..e095d7fa0 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -57,10 +57,10 @@ struct pa_context* pa_stream_get_context(struct pa_stream *p); uint32_t pa_stream_get_index(struct pa_stream *s); /** Connect the stream to a sink */ -void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, pa_volume_t volume); +void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, enum pa_stream_flags flags, pa_volume_t volume); /** Connect the stream to a source */ -void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr); +void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, enum pa_stream_flags flags); /** Disconnect a stream from a source/sink */ void pa_stream_disconnect(struct pa_stream *s); @@ -107,28 +107,56 @@ struct pa_operation* pa_stream_get_latency(struct pa_stream *p, void (*cb)(struc /** Set the callback function that is called whenever the state of the stream changes */ void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); -/** Set the callback function that is called when new data may be written to the stream */ +/** Set the callback function that is called when new data may be + * written to the stream. */ void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); /** Set the callback function that is called when new data is available from the stream */ void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); -/** Pause (or resume) playback of this stream temporarily. \since 0.3 */ +/** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. \since 0.3 */ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); /** Flush the playback buffer of this stream. Most of the time you're * better off using the parameter delta of pa_stream_write() instead of this - * function. \since 0.3 */ + * function. Available on both playback and recording streams. \since 0.3 */ struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); +/** Reenable prebuffering. Available for playback streams only. \since 0.6 */ +struct pa_operation* pa_stream_prebuf(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); + /** Request immediate start of playback on this stream. This disables - * prebuffering as specified in the pa_buffer_attr structure. \since + * prebuffering as specified in the pa_buffer_attr structure. Available for playback streams only. \since * 0.3 */ struct pa_operation* pa_stream_trigger(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); /** Rename the stream. \since 0.5 */ struct pa_operation* pa_stream_set_name(struct pa_stream *s, const char *name, void(*cb)(struct pa_stream*c, int success, void *userdata), void *userdata); +/** Return the total number of bytes written to/read from the + * stream. This counter is not reset on pa_stream_flush(), you may do + * this yourself using pa_stream_reset_counter(). \since 0.6 */ +uint64_t pa_stream_get_counter(struct pa_stream *s); + +/** Reset the total byte count to 0. \since 0.6 */ +void pa_stream_reset_counter(struct pa_stream *s); + +/** Return the current playback/recording time. This is based on the + * counter accessible with pa_stream_get_counter(). This function + * requires a pa_latency_info structure as argument, which should be + * acquired using pa_stream_get_latency(). \since 0.6 */ +pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info *i); + +/** Return the total stream latency. Thus function requires a + * pa_latency_info structure as argument, which should be aquired + * using pa_stream_get_latency(). In case the stream is a monitoring + * stream the result can be negative, i.e. the captured samples are + * not yet played. In this case *negative is set to 1. \since 0.6 */ +pa_usec_t pa_stream_get_total_latency(struct pa_stream *s, const struct pa_latency_info *i, int *negative); + +/** Return a pointer to the streams sample specification. \since 0.6 */ +const struct pa_sample_spec* pa_stream_get_sample_spec(struct pa_stream *s); + PA_C_DECL_END #endif diff --git a/polyp/polyplib.h b/polyp/polyplib.h index f4e419346..3921e2ba8 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -83,11 +83,4 @@ * synchronous API is available as "polyplib-simple". */ -PA_C_DECL_BEGIN - -/** Return the version of the library the current application is linked to */ -const char* pa_get_library_version(void); - -PA_C_DECL_END - #endif diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 797263f61..799787405 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -62,6 +62,7 @@ struct connection { uint32_t index; + int dead; struct pa_protocol_esound *protocol; struct pa_iochannel *io; struct pa_client *client; @@ -76,14 +77,17 @@ struct connection { struct pa_source_output *source_output; struct pa_memblockq *input_memblockq, *output_memblockq; struct pa_defer_event *defer_event; + struct { struct pa_memblock *current_memblock; size_t memblock_index, fragment_size; } playback; - struct pa_memchunk scache_memchunk; - char *scache_name; - struct pa_sample_spec scache_sample_spec; + struct { + struct pa_memchunk memchunk; + char *name; + struct pa_sample_spec sample_spec; + } scache; }; struct pa_protocol_esound { @@ -195,9 +199,9 @@ static void connection_free(struct connection *c) { if (c->defer_event) c->protocol->core->mainloop->defer_free(c->defer_event); - if (c->scache_memchunk.memblock) - pa_memblock_unref(c->scache_memchunk.memblock); - pa_xfree(c->scache_name); + if (c->scache.memchunk.memblock) + pa_memblock_unref(c->scache.memchunk.memblock); + pa_xfree(c->scache.name); pa_xfree(c); } @@ -583,17 +587,17 @@ static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, con strncpy(name+sizeof(SCACHE_PREFIX)-1, (char*) data+3*sizeof(int), ESD_NAME_MAX); name[sizeof(name)-1] = 0; - assert(!c->scache_memchunk.memblock); - c->scache_memchunk.memblock = pa_memblock_new(sc_length, c->protocol->core->memblock_stat); - c->scache_memchunk.index = 0; - c->scache_memchunk.length = sc_length; - c->scache_sample_spec = ss; - assert(!c->scache_name); - c->scache_name = pa_xstrdup(name); + assert(!c->scache.memchunk.memblock); + c->scache.memchunk.memblock = pa_memblock_new(sc_length, c->protocol->core->memblock_stat); + c->scache.memchunk.index = 0; + c->scache.memchunk.length = sc_length; + c->scache.sample_spec = ss; + assert(!c->scache.name); + c->scache.name = pa_xstrdup(name); c->state = ESD_CACHING_SAMPLE; - pa_scache_add_item(c->protocol->core, c->scache_name, NULL, NULL, &index); + pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, &index); ok = connection_write(c, sizeof(int)); assert(ok); @@ -747,29 +751,29 @@ static int do_read(struct connection *c) { } else if (c->state == ESD_CACHING_SAMPLE) { ssize_t r; - assert(c->scache_memchunk.memblock && c->scache_name && c->scache_memchunk.index < c->scache_memchunk.length); + assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length); - if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache_memchunk.memblock->data+c->scache_memchunk.index, c->scache_memchunk.length-c->scache_memchunk.index)) <= 0) { + if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } - c->scache_memchunk.index += r; - assert(c->scache_memchunk.index <= c->scache_memchunk.length); + c->scache.memchunk.index += r; + assert(c->scache.memchunk.index <= c->scache.memchunk.length); - if (c->scache_memchunk.index == c->scache_memchunk.length) { + if (c->scache.memchunk.index == c->scache.memchunk.length) { uint32_t index; int *ok; - c->scache_memchunk.index = 0; - pa_scache_add_item(c->protocol->core, c->scache_name, &c->scache_sample_spec, &c->scache_memchunk, &index); + c->scache.memchunk.index = 0; + pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, &c->scache.memchunk, &index); - pa_memblock_unref(c->scache_memchunk.memblock); - c->scache_memchunk.memblock = NULL; - c->scache_memchunk.index = c->scache_memchunk.length = 0; + pa_memblock_unref(c->scache.memchunk.memblock); + c->scache.memchunk.memblock = NULL; + c->scache.memchunk.index = c->scache.memchunk.length = 0; - pa_xfree(c->scache_name); - c->scache_name = NULL; + pa_xfree(c->scache.name); + c->scache.name = NULL; c->state = ESD_NEXT_REQUEST; @@ -869,21 +873,26 @@ static void do_work(struct connection *c) { assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 0); - if (pa_iochannel_is_hungup(c->io)) - goto fail; + if (c->dead) + return; + + if (pa_iochannel_is_readable(c->io)) + if (do_read(c) < 0) + goto fail; if (pa_iochannel_is_writable(c->io)) if (do_write(c) < 0) goto fail; - if (pa_iochannel_is_readable(c->io)) - if (do_read(c) < 0) - goto fail; - return; fail: - connection_free(c); + + if (c->state == ESD_STREAMING_DATA && c->sink_input) { + c->dead = 1; + pa_memblockq_prebuf_disable(c->input_memblockq); + } else + connection_free(c); } static void io_callback(struct pa_iochannel*io, void *userdata) { @@ -909,8 +918,13 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk assert(i && i->userdata && chunk); c = i->userdata; - if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) + if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) { + + if (c->dead) + connection_free(c); + return -1; + } return 0; } @@ -985,6 +999,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->authorized = c->protocol->public; c->swap_byte_order = 0; + c->dead = 0; c->read_data_length = 0; c->read_data = pa_xmalloc(c->read_data_alloc = proto_map[ESD_PROTO_CONNECT].data_length); @@ -1005,9 +1020,9 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->playback.memblock_index = 0; c->playback.fragment_size = 0; - c->scache_memchunk.length = c->scache_memchunk.index = 0; - c->scache_memchunk.memblock = NULL; - c->scache_name = NULL; + c->scache.memchunk.length = c->scache.memchunk.index = 0; + c->scache.memchunk.memblock = NULL; + c->scache.name = NULL; c->defer_event = c->protocol->core->mainloop->defer_new(c->protocol->core->mainloop, defer_callback, c); assert(c->defer_event); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 4c1e96969..f36bbd717 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -150,6 +150,8 @@ static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static void command_get_autoload_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_cork_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_flush_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = { NULL }, @@ -190,11 +192,18 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_GET_SAMPLE_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info }, [PA_COMMAND_SUBSCRIBE] = { command_subscribe }, + [PA_COMMAND_SET_SINK_VOLUME] = { command_set_volume }, [PA_COMMAND_SET_SINK_INPUT_VOLUME] = { command_set_volume }, + [PA_COMMAND_CORK_PLAYBACK_STREAM] = { command_cork_playback_stream }, [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, + [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, + + [PA_COMMAND_CORK_RECORD_STREAM] = { command_cork_record_stream }, + [PA_COMMAND_FLUSH_RECORD_STREAM] = { command_flush_record_stream }, + [PA_COMMAND_SET_DEFAULT_SINK] = { command_set_default_sink_or_source }, [PA_COMMAND_SET_DEFAULT_SOURCE] = { command_set_default_sink_or_source }, [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = { command_set_stream_name }, @@ -208,6 +217,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = { command_get_autoload_info_list }, [PA_COMMAND_ADD_AUTOLOAD] = { command_add_autoload }, [PA_COMMAND_REMOVE_AUTOLOAD] = { command_remove_autoload }, + }; /* structure management */ @@ -538,6 +548,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com struct pa_tagstruct *reply; struct pa_sink *sink; pa_volume_t volume; + int corked; assert(c && t && c->protocol && c->protocol->core); if (pa_tagstruct_gets(t, &name) < 0 || !name || @@ -545,6 +556,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com pa_tagstruct_getu32(t, &sink_index) < 0 || pa_tagstruct_gets(t, &sink_name) < 0 || pa_tagstruct_getu32(t, &maxlength) < 0 || + pa_tagstruct_get_boolean(t, &corked) < 0 || pa_tagstruct_getu32(t, &tlength) < 0 || pa_tagstruct_getu32(t, &prebuf) < 0 || pa_tagstruct_getu32(t, &minreq) < 0 || @@ -574,6 +586,8 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); return; } + + pa_sink_input_cork(s->sink_input, corked); reply = pa_tagstruct_new(NULL, 0); assert(reply); @@ -1412,12 +1426,12 @@ static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32 static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t index; - uint32_t b; + int b; struct playback_stream *s; assert(c && t); if (pa_tagstruct_getu32(t, &index) < 0 || - pa_tagstruct_getu32(t, &b) < 0 || + pa_tagstruct_get_boolean(t, &b) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1459,7 +1473,9 @@ static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, ui return; } - if (command == PA_COMMAND_TRIGGER_PLAYBACK_STREAM) + if (command == PA_COMMAND_PREBUF_PLAYBACK_STREAM) + pa_memblockq_prebuf_reenable(s->memblockq); + else if (command == PA_COMMAND_TRIGGER_PLAYBACK_STREAM) pa_memblockq_prebuf_disable(s->memblockq); else { assert(command == PA_COMMAND_FLUSH_PLAYBACK_STREAM); @@ -1472,6 +1488,60 @@ static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, ui request_bytes(s); } +static void command_cork_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + struct record_stream *s; + int b; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + pa_tagstruct_get_boolean(t, &b) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(s = pa_idxset_get_by_index(c->record_streams, index))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_source_output_cork(s->source_output, b); + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void command_flush_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t index; + struct record_stream *s; + assert(c && t); + + if (pa_tagstruct_getu32(t, &index) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + return; + } + + if (!(s = pa_idxset_get_by_index(c->record_streams, index))) { + pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + return; + } + + pa_memblockq_flush(s->memblockq); + pa_pstream_send_simple_ack(c->pstream, tag); +} + static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t index; diff --git a/polyp/sample.c b/polyp/sample.c index 143e1e414..65ae8ff38 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -59,7 +59,7 @@ size_t pa_bytes_per_second(const struct pa_sample_spec *spec) { return spec->rate*pa_frame_size(spec); } -pa_usec_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec) { +pa_usec_t pa_bytes_to_usec(uint64_t length, const struct pa_sample_spec *spec) { assert(spec); return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate); diff --git a/polyp/sample.h b/polyp/sample.h index 501172a8e..912cdaa0f 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -77,7 +77,7 @@ size_t pa_bytes_per_second(const struct pa_sample_spec *spec); size_t pa_frame_size(const struct pa_sample_spec *spec); /** Calculate the time the specified bytes take to play with the specified sample type */ -pa_usec_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec); +pa_usec_t pa_bytes_to_usec(uint64_t length, const struct pa_sample_spec *spec); /** Return non-zero when the sample type specification is valid */ int pa_sample_spec_valid(const struct pa_sample_spec *spec); diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 949302314..5c8675dec 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -70,7 +70,6 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con i->get_latency = NULL; i->userdata = NULL; - i->corked = 0; i->volume = PA_VOLUME_NORM; i->resampled_chunk.memblock = NULL; @@ -92,7 +91,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con } void pa_sink_input_disconnect(struct pa_sink_input *i) { - assert(i && i->state == PA_SINK_INPUT_RUNNING && i->sink && i->sink->core); + assert(i && i->state != PA_SINK_INPUT_DISCONNECTED && i->sink && i->sink->core); pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL); pa_idxset_remove_by_data(i->sink->inputs, i, NULL); @@ -163,7 +162,7 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { if (!i->peek || !i->drop) return -1; - if (i->corked) + if (i->state == PA_SINK_INPUT_CORKED) return -1; if (!i->resampler) @@ -238,9 +237,12 @@ void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume) { void pa_sink_input_cork(struct pa_sink_input *i, int b) { int n; assert(i && i->ref >= 1); - - n = i->corked && !b; - i->corked = b; + + if (i->state == PA_SINK_INPUT_DISCONNECTED) + return; + + n = i->state == PA_SINK_INPUT_CORKED && !b; + i->state = b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING; if (n) pa_sink_notify(i->sink); diff --git a/polyp/sink-input.h b/polyp/sink-input.h index 7c648ac12..aed5f521e 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -33,6 +33,7 @@ enum pa_sink_input_state { PA_SINK_INPUT_RUNNING, + PA_SINK_INPUT_CORKED, PA_SINK_INPUT_DISCONNECTED }; @@ -42,8 +43,6 @@ struct pa_sink_input { uint32_t index; - int corked; - char *name; struct pa_module *owner; struct pa_client *client; diff --git a/polyp/source-output.c b/polyp/source-output.c index 13b396582..5a40fa42d 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -79,7 +79,7 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n } void pa_source_output_disconnect(struct pa_source_output*o) { - assert(o && o->state == PA_SOURCE_OUTPUT_RUNNING && o->source && o->source->core); + assert(o && o->state != PA_SOURCE_OUTPUT_DISCONNECTED && o->source && o->source->core); pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL); pa_idxset_remove_by_data(o->source->outputs, o, NULL); @@ -133,6 +133,9 @@ void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk struct pa_memchunk rchunk; assert(o && chunk && chunk->length && o->push); + if (o->state == PA_SOURCE_OUTPUT_CORKED) + return; + if (!o->resampler) { o->push(o, chunk); return; @@ -163,3 +166,12 @@ pa_usec_t pa_source_output_get_latency(struct pa_source_output *o) { return 0; } + +void pa_source_output_cork(struct pa_source_output *o, int b) { + assert(o && o->ref >= 1); + + if (o->state == PA_SOURCE_OUTPUT_DISCONNECTED) + return; + + o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING; +} diff --git a/polyp/source-output.h b/polyp/source-output.h index 51d5936b4..a535782ec 100644 --- a/polyp/source-output.h +++ b/polyp/source-output.h @@ -33,6 +33,7 @@ enum pa_source_output_state { PA_SOURCE_OUTPUT_RUNNING, + PA_SOURCE_OUTPUT_CORKED, PA_SOURCE_OUTPUT_DISCONNECTED }; @@ -73,5 +74,7 @@ void pa_source_output_set_name(struct pa_source_output *i, const char *name); pa_usec_t pa_source_output_get_latency(struct pa_source_output *i); +void pa_source_output_cork(struct pa_source_output *i, int b); + #endif diff --git a/polyp/util.c b/polyp/util.c index 1246bbb5b..6be6ffe48 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -421,6 +421,7 @@ const char *pa_strsignal(int sig) { case SIGXCPU: return "SIGXCPU"; case SIGPIPE: return "SIGPIPE"; case SIGCHLD: return "SIGCHLD"; + case SIGHUP: return "SIGHUP"; default: return "UNKNOWN SIGNAL"; } } From 949014e154dec912e080335630818ed016b45394 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 26 Sep 2004 22:27:04 +0000 Subject: [PATCH 0236/1514] add new tool paplay git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@241 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +- polyp/Makefile.am | 10 +- polyp/module-combine.c | 4 +- polyp/paplay.c | 377 +++++++++++++++++++++++++++++++++++++++ polyp/polyplib-context.h | 3 + polyp/protocol-native.c | 10 +- 6 files changed, 396 insertions(+), 11 deletions(-) create mode 100644 polyp/paplay.c diff --git a/doc/todo b/doc/todo index 6bbd70ad8..b5ae1446d 100644 --- a/doc/todo +++ b/doc/todo @@ -10,12 +10,11 @@ - proper locking around native protocol socket - pacat sample type args - filter capture data in client through alignment -- paplay -- check module-combine algo - add redirection module - add matching module - add radio module - make autoload list use idxset +- improve file load to note force sample typ to PA_SAMPLE_FLOAT32 ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 4e0754682..2d14b420b 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -33,7 +33,7 @@ AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in -bin_PROGRAMS = polypaudio pacat pactl +bin_PROGRAMS = polypaudio pacat pactl paplay bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ mainloop-test \ @@ -372,9 +372,13 @@ pacat_SOURCES = pacat.c pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la pacat_CFLAGS = $(AM_CFLAGS) +paplay_SOURCES = paplay.c +paplay_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) +paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) + pactl_SOURCES = pactl.c pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) -pactl_CFLAGS = $(AM_CFLAGS) $(LIBSDNFILE_CFLAGS) +pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pacat_simple_SOURCES = pacat-simple.c pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la @@ -460,7 +464,7 @@ lib_LTLIBRARIES+= \ noinst_PROGRAMS+= \ mainloop-test-glib12 - + libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib12-mainloop.c libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB12_LIBS) diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 6952ce6ca..1a909087f 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -115,8 +115,8 @@ static void adjust_rates(struct userdata *u) { base_rate = u->sink->sample_spec.rate; for (o = u->outputs; o; o = o->next) { - uint32_t r = base_rate; - + uint32_t r = base_rate; + if (o->total_latency < target_latency) r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/ 1000000); else if (o->total_latency > target_latency) diff --git a/polyp/paplay.c b/polyp/paplay.c new file mode 100644 index 000000000..cc973a7d5 --- /dev/null +++ b/polyp/paplay.c @@ -0,0 +1,377 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#if PA_API_VERSION != PA_API_VERSION_0_6 +#error Invalid Polypaudio API version +#endif + +static struct pa_context *context = NULL; +static struct pa_stream *stream = NULL; +static struct pa_mainloop_api *mainloop_api = NULL; + +static char *stream_name = NULL, *client_name = NULL, *device = NULL; + +static int verbose = 0; +static pa_volume_t volume = PA_VOLUME_NORM; + +static SNDFILE* sndfile = NULL; + +static struct pa_sample_spec sample_spec = { 0, 0, 0 }; + +static sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames); + +/* A shortcut for terminating the application */ +static void quit(int ret) { + assert(mainloop_api); + mainloop_api->quit(mainloop_api, ret); +} + +/* Connection draining complete */ +static void context_drain_complete(struct pa_context*c, void *userdata) { + pa_context_disconnect(c); +} + +/* Stream draining complete */ +static void stream_drain_complete(struct pa_stream*s, int success, void *userdata) { + struct pa_operation *o; + + if (!success) { + fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + } + + if (verbose) + fprintf(stderr, "Playback stream drained.\n"); + + pa_stream_disconnect(stream); + pa_stream_unref(stream); + stream = NULL; + + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) + pa_context_disconnect(context); + else { + pa_operation_unref(o); + + if (verbose) + fprintf(stderr, "Draining connection to server.\n"); + } +} + +/* This is called whenever new data may be written to the stream */ +static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { + size_t k; + sf_count_t f, n; + void *data; + assert(s && length); + + if (!sndfile) + return; + + k = pa_frame_size(&sample_spec); + + data = malloc(length); + + n = length/k; + + f = readf_function(sndfile, data, n); + + if (f > 0) + pa_stream_write(s, data, f*k, free, 0); + + if (f < n) { + sf_close(sndfile); + sndfile = NULL; + pa_operation_unref(pa_stream_drain(s, stream_drain_complete, NULL)); + } +} + +/* This routine is called whenever the stream state changes */ +static void stream_state_callback(struct pa_stream *s, void *userdata) { + assert(s); + + switch (pa_stream_get_state(s)) { + case PA_STREAM_CREATING: + case PA_STREAM_TERMINATED: + break; + + case PA_STREAM_READY: + if (verbose) + fprintf(stderr, "Stream successfully created\n"); + break; + + case PA_STREAM_FAILED: + default: + fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + quit(1); + } +} + +/* This is called whenever the context status changes */ +static void context_state_callback(struct pa_context *c, void *userdata) { + assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: + + assert(c && !stream); + + if (verbose) + fprintf(stderr, "Connection established.\n"); + + stream = pa_stream_new(c, stream_name, &sample_spec); + assert(stream); + + pa_stream_set_state_callback(stream, stream_state_callback, NULL); + pa_stream_set_write_callback(stream, stream_write_callback, NULL); + pa_stream_connect_playback(stream, device, NULL, 0, volume); + + break; + + case PA_CONTEXT_TERMINATED: + quit(0); + break; + + case PA_CONTEXT_FAILED: + default: + fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + } +} + +/* UNIX signal to quit recieved */ +static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { + if (verbose) + fprintf(stderr, "Got SIGINT, exiting.\n"); + quit(0); + +} + +static void help(const char *argv0) { + + printf("%s [options] FILE\n\n" + " -h, --help Show this help\n" + " --version Show version\n\n" + " -v, --verbose Enable verbose operations\n\n" + " -s, --server=SERVER The name of the server to connect to\n" + " -d, --device=DEVICE The name of the sink/source to connect to\n" + " -n, --client-name=NAME How to call this client on the server\n" + " --stream-name=NAME How to call this stream on the server\n" + " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n", + argv0); +} + +enum { + ARG_VERSION = 256, + ARG_STREAM_NAME, + ARG_VOLUME +}; + +int main(int argc, char *argv[]) { + struct pa_mainloop* m = NULL; + int ret = 1, r, c; + char *bn, *server = NULL; + SF_INFO sfinfo; + + static const struct option long_options[] = { + {"device", 1, NULL, 'd'}, + {"server", 1, NULL, 's'}, + {"client-name", 1, NULL, 'n'}, + {"stream-name", 1, NULL, ARG_STREAM_NAME}, + {"version", 0, NULL, ARG_VERSION}, + {"help", 0, NULL, 'h'}, + {"verbose", 0, NULL, 'v'}, + {"volume", 1, NULL, ARG_VOLUME}, + {NULL, 0, NULL, 0} + }; + + if (!(bn = strrchr(argv[0], '/'))) + bn = argv[0]; + else + bn++; + + while ((c = getopt_long(argc, argv, "d:s:n:hv", long_options, NULL)) != -1) { + + switch (c) { + case 'h' : + help(bn); + ret = 0; + goto quit; + + case ARG_VERSION: + printf("paplay "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + ret = 0; + goto quit; + + case 'd': + free(device); + device = strdup(optarg); + break; + + case 's': + free(server); + server = strdup(optarg); + break; + + case 'n': + free(client_name); + client_name = strdup(optarg); + break; + + case ARG_STREAM_NAME: + free(stream_name); + stream_name = strdup(optarg); + break; + + case 'v': + verbose = 1; + break; + + case ARG_VOLUME: { + int v = atoi(optarg); + volume = v < 0 ? 0 : v; + break; + } + + default: + goto quit; + } + } + + if (optind >= argc) { + fprintf(stderr, "Missing file name.\n"); + goto quit; + } + + if (!client_name) + client_name = strdup(bn); + + if (!stream_name) + stream_name = strdup(argv[optind]); + + memset(&sfinfo, 0, sizeof(sfinfo)); + + if (!(sndfile = sf_open(argv[optind], SFM_READ, &sfinfo))) { + fprintf(stderr, "Faile to open file '%s'\n", argv[optind]); + goto quit; + } + + sample_spec.rate = sfinfo.samplerate; + sample_spec.channels = sfinfo.channels; + + switch (sfinfo.format & 0xFF) { + case SF_FORMAT_PCM_16: + case SF_FORMAT_PCM_U8: + case SF_FORMAT_ULAW: + case SF_FORMAT_ALAW: + sample_spec.format = PA_SAMPLE_S16NE; + readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short; + break; + case SF_FORMAT_FLOAT: + default: + sample_spec.format = PA_SAMPLE_FLOAT32NE; + readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float; + break; + } + + if (verbose) { + char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; + pa_sample_spec_snprint(t, sizeof(t), &sample_spec); + fprintf(stderr, "Using sample spec '%s'\n", t); + } + + /* Set up a new main loop */ + if (!(m = pa_mainloop_new())) { + fprintf(stderr, "pa_mainloop_new() failed.\n"); + goto quit; + } + + mainloop_api = pa_mainloop_get_api(m); + + r = pa_signal_init(mainloop_api); + assert(r == 0); + pa_signal_new(SIGINT, exit_signal_callback, NULL); + signal(SIGPIPE, SIG_IGN); + + /* Create a new connection context */ + if (!(context = pa_context_new(mainloop_api, client_name))) { + fprintf(stderr, "pa_context_new() failed.\n"); + goto quit; + } + + pa_context_set_state_callback(context, context_state_callback, NULL); + + /* Connect the context */ + pa_context_connect(context, server, 1, NULL); + + /* Run the main loop */ + if (pa_mainloop_run(m, &ret) < 0) { + fprintf(stderr, "pa_mainloop_run() failed.\n"); + goto quit; + } + +quit: + if (stream) + pa_stream_unref(stream); + + if (context) + pa_context_unref(context); + + if (m) { + pa_signal_done(); + pa_mainloop_free(m); + } + + free(server); + free(device); + free(client_name); + free(stream_name); + + if (sndfile) + sf_close(sndfile); + + return ret; +} diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 548a39dd6..75be59304 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -45,6 +45,9 @@ /** \example pacat.c * A playback and recording tool using the asynchronous API */ +/** \example paplay.c + * A sound file playback tool using the asynchronous API, based on libsndfile */ + PA_C_DECL_BEGIN /** \struct pa_context diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index f36bbd717..aeccd504a 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -484,7 +484,7 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk s->drain_request = 0; } - /*pa_log(__FILE__": after_drop: %u\n", pa_memblockq_get_length(s->memblockq));*/ +/* pa_log(__FILE__": after_drop: %u\n", pa_memblockq_get_length(s->memblockq)); */ } static void sink_input_kill_cb(struct pa_sink_input *i) { @@ -828,8 +828,10 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm pa_memblockq_prebuf_disable(s->memblockq); if (!pa_memblockq_is_readable(s->memblockq)) { +/* pa_log("immediate drain: %u\n", pa_memblockq_get_length(s->memblockq)); */ pa_pstream_send_simple_ack(c->pstream, tag); } else { +/* pa_log("slow drain triggered\n"); */ s->drain_request = 1; s->drain_tag = tag; @@ -1854,7 +1856,7 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui struct connection *c = userdata; struct output_stream *stream; assert(p && chunk && userdata); - + if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) { pa_log(__FILE__": client sent block for invalid stream.\n"); connection_free(c); @@ -1870,10 +1872,10 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui pa_memblockq_push_align(p->memblockq, chunk, delta); assert(p->sink_input); - /*pa_log(__FILE__": after_recv: %u\n", pa_memblockq_get_length(p->memblockq));*/ +/* pa_log(__FILE__": after_recv: %u\n", pa_memblockq_get_length(p->memblockq)); */ pa_sink_notify(p->sink_input->sink); -/* pa_log(__FILE__": Recieved %u bytes.\n", chunk->length); */ +/* pa_log(__FILE__": Recieved %u bytes.\n", chunk->length); */ } else { struct upload_stream *u = (struct upload_stream*) stream; From 35148d8c0565d9b7faafe423367c4bd750461533 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 27 Sep 2004 15:40:18 +0000 Subject: [PATCH 0237/1514] add POSIX locking to authkey.c fix esound protocol cpu consumption when finishing a stream git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@242 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/authkey.c | 113 +++++++++++++++++++++++----------------- polyp/protocol-esound.c | 11 ++-- polyp/util.c | 17 ++++++ polyp/util.h | 3 ++ 4 files changed, 92 insertions(+), 52 deletions(-) diff --git a/polyp/authkey.c b/polyp/authkey.c index 9b60506ff..1e2edb07d 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -41,48 +41,23 @@ #define RANDOM_DEVICE "/dev/urandom" -static int load(const char *fn, void *data, size_t length) { - int fd = -1, ret = -1; +static int generate(int fd, void *data, size_t length) { + int random_fd, ret = -1; ssize_t r; - - assert(fn && data && length); + assert(fd >= 0 && data && length); - if ((fd = open(fn, O_RDONLY)) < 0) - goto finish; - - if ((r = pa_loop_read(fd, data, length)) < 0 || (size_t) r != length) { - ret = -2; - goto finish; - } - - ret = 0; - -finish: - if (fd >= 0) - close(fd); - - return ret; -} - -static int generate(const char *fn, void *data, size_t length) { - int fd = -1, random_fd = -1, ret = -1; - ssize_t r; - assert(fn && data && length); - - if ((fd = open(fn, O_WRONLY|O_EXCL|O_CREAT, S_IRUSR | S_IWUSR)) < 0) - goto finish; - if ((random_fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) { if ((r = pa_loop_read(random_fd, data, length)) < 0 || (size_t) r != length) { - ret = -2; + pa_log(__FILE__": failed to read entropy from '%s'\n", RANDOM_DEVICE); goto finish; } } else { uint8_t *p; size_t l; - pa_log(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s, falling back to unsecure pseudo RNG.\n", strerror(errno)); + pa_log(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s" + ", falling back to unsecure pseudo RNG.\n", strerror(errno)); srandom(time(NULL)); @@ -90,41 +65,81 @@ static int generate(const char *fn, void *data, size_t length) { *p = (uint8_t) random(); } + lseek(fd, 0, SEEK_SET); + if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) { - ret = -2; + pa_log(__FILE__": failed to write cookie file\n"); goto finish; } ret = 0; finish: - if (fd >= 0) { - if (ret != 0) - unlink(fn); - close(fd); - } + if (random_fd >= 0) close(random_fd); return ret; } -int pa_authkey_load(const char *path, void *data, size_t length) { - int ret, i; +static int load(const char *fn, void *data, size_t length) { + int fd = -1; + int writable = 1; + assert(fn && data && length); + int unlock = 0, ret; + ssize_t r; - assert(path && data && length); - - for (i = 0; i < 10; i++) { - if ((ret = load(path, data, length)) < 0) - if (ret == -1 && errno == ENOENT) - if ((ret = generate(path, data, length)) < 0) - if (ret == -1 && errno == EEXIST) - continue; - break; + if ((fd = open(fn, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { + if (errno != EACCES || (fd = open(fn, O_RDONLY)) < 0) { + pa_log(__FILE__": failed to open cookie file '%s'\n", fn); + goto finish; + } else + writable = 0; } + unlock = pa_lock_file(fd, 1) >= 0; + + if ((r = pa_loop_read(fd, data, length)) < 0) { + pa_log(__FILE__": failed to read cookie file '%s'\n", fn); + goto finish; + } + + if ((size_t) r != length) { + + if (!writable) { + pa_log(__FILE__": unable to write cookie to read only file\n"); + goto finish; + } + + if (generate(fd, data, length) < 0) + goto finish; + } + + ret = 0; + +finish: + + if (fd >= 0) { + + if (unlock) + pa_lock_file(fd, 0); + + close(fd); + } + + return ret; +} + +int pa_authkey_load(const char *path, void *data, size_t length) { + int ret; + + assert(path && data && length); + + ret = load(path, data, length); + if (ret < 0) - pa_log(__FILE__": Failed to load authorization key '%s': %s\n", path, (ret == -1) ? strerror(errno) : "file corrupt"); + pa_log(__FILE__": Failed to load authorization key '%s': %s\n", path, + (ret == -1) ? strerror(errno) : "file corrupt"); return ret; } diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 799787405..4498a750d 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -872,7 +872,7 @@ static void do_work(struct connection *c) { assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 0); - + if (c->dead) return; @@ -891,6 +891,7 @@ fail: if (c->state == ESD_STREAMING_DATA && c->sink_input) { c->dead = 1; pa_memblockq_prebuf_disable(c->input_memblockq); + c->protocol->core->mainloop->defer_enable(c->defer_event, 0); } else connection_free(c); } @@ -937,7 +938,9 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk /* do something */ assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); - c->protocol->core->mainloop->defer_enable(c->defer_event, 1); + + if (!c->dead) + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); /* assert(pa_memblockq_get_length(c->input_memblockq) > 2048); */ } @@ -963,7 +966,9 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me /* do something */ assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); - c->protocol->core->mainloop->defer_enable(c->defer_event, 1); + + if (!c->dead) + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } static void source_output_kill_cb(struct pa_source_output *o) { diff --git a/polyp/util.c b/polyp/util.c index 6be6ffe48..166a9a45c 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -501,3 +501,20 @@ finish: pa_xfree(gids); return r; } + +int pa_lock_file(int fd, int b) { + + struct flock flock; + + flock.l_type = b ? F_WRLCK : F_UNLCK; + flock.l_whence = SEEK_SET; + flock.l_start = 0; + flock.l_len = 0; + + if (fcntl(fd, F_SETLKW, &flock) < 0) { + pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno)); + return -1; + } + + return 0; +} diff --git a/polyp/util.h b/polyp/util.h index 8f4323f67..571bb29be 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -68,4 +68,7 @@ int pa_parse_resample_method(const char *string); int pa_uid_in_group(const char *name, gid_t *gid); +int pa_lock_file(int fd, int b); + + #endif From f014d466cd5f65b03a7a1608aa3d4cd83425a56e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 27 Sep 2004 17:21:27 +0000 Subject: [PATCH 0238/1514] really fix cpu usage when using esddsp with polypaudio git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@243 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/iochannel.c | 60 ++++++++++++++++++----------------------- polyp/iochannel.h | 3 --- polyp/protocol-esound.c | 36 +++++++++++++++++++------ 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/polyp/iochannel.c b/polyp/iochannel.c index 72bdac20e..5e3e93606 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -52,7 +52,7 @@ struct pa_iochannel { static void enable_mainloop_sources(struct pa_iochannel *io) { assert(io); - if (io->input_event == io->output_event) { + if (io->input_event == io->output_event && io->input_event) { enum pa_io_event_flags f = PA_IO_EVENT_NULL; assert(io->input_event); @@ -78,18 +78,29 @@ static void callback(struct pa_mainloop_api* m, struct pa_io_event *e, int fd, e if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) { io->hungup = 1; changed = 1; - } - - if ((f & PA_IO_EVENT_INPUT) && !io->readable) { - io->readable = 1; - changed = 1; - assert(e == io->input_event); - } - - if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) { - io->writable = 1; - changed = 1; - assert(e == io->output_event); + + if (e == io->input_event) { + io->mainloop->io_free(io->input_event); + io->input_event = NULL; + } + + if (e == io->output_event) { + io->mainloop->io_free(io->output_event); + io->output_event = NULL; + } + } else { + + if ((f & PA_IO_EVENT_INPUT) && !io->readable) { + io->readable = 1; + changed = 1; + assert(e == io->input_event); + } + + if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) { + io->writable = 1; + changed = 1; + assert(e == io->output_event); + } } if (changed) { @@ -158,12 +169,12 @@ void pa_iochannel_free(struct pa_iochannel*io) { int pa_iochannel_is_readable(struct pa_iochannel*io) { assert(io); - return io->readable; + return io->readable || io->hungup; } int pa_iochannel_is_writable(struct pa_iochannel*io) { assert(io); - return io->writable; + return io->writable && !io->hungup; } int pa_iochannel_is_hungup(struct pa_iochannel*io) { @@ -173,16 +184,8 @@ int pa_iochannel_is_hungup(struct pa_iochannel*io) { ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) { ssize_t r; - assert(io); - assert(data); - assert(l); - assert(io->ofd >= 0); - - assert(io && data && l && io->ofd >= 0); - - if ((r = write(io->ofd, data, l)) >= 0) { io->writable = 0; enable_mainloop_sources(io); @@ -193,7 +196,6 @@ ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) { ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l) { ssize_t r; - assert(io && data && io->ifd >= 0); if ((r = read(io->ifd, data, l)) >= 0) { @@ -230,13 +232,3 @@ int pa_iochannel_socket_set_sndbuf(struct pa_iochannel *io, size_t l) { return pa_socket_set_sndbuf(io->ofd, l); } -void pa_iochannel_force_unreadable(struct pa_iochannel *io) { - assert(io); - io->readable = 0; - enable_mainloop_sources(io); -} - -void pa_iochannel_force_unwritable(struct pa_iochannel *io) { - io->writable = 0; - enable_mainloop_sources(io); -} diff --git a/polyp/iochannel.h b/polyp/iochannel.h index a4edbfad5..6f5f351c2 100644 --- a/polyp/iochannel.h +++ b/polyp/iochannel.h @@ -39,9 +39,6 @@ int pa_iochannel_is_readable(struct pa_iochannel*io); int pa_iochannel_is_writable(struct pa_iochannel*io); int pa_iochannel_is_hungup(struct pa_iochannel*io); -void pa_iochannel_force_unreadable(struct pa_iochannel *io); -void pa_iochannel_force_unwritable(struct pa_iochannel *io); - void pa_iochannel_set_noclose(struct pa_iochannel*io, int b); void pa_iochannel_set_callback(struct pa_iochannel*io, void (*callback)(struct pa_iochannel*io, void *userdata), void *userdata); diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 4498a750d..b6caeb3db 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -193,8 +193,9 @@ static void connection_free(struct connection *c) { pa_xfree(c->read_data); pa_xfree(c->write_data); - - pa_iochannel_free(c->io); + + if (c->io) + pa_iochannel_free(c->io); if (c->defer_event) c->protocol->core->mainloop->defer_free(c->defer_event); @@ -680,6 +681,8 @@ static void client_kill_cb(struct pa_client *c) { static int do_read(struct connection *c) { assert(c && c->io); +/* pa_log("READ\n"); */ + if (c->state == ESD_NEXT_REQUEST) { ssize_t r; assert(c->read_data_length < sizeof(c->request)); @@ -702,7 +705,7 @@ static int do_read(struct connection *c) { handler = proto_map+c->request; - pa_log(__FILE__": executing request #%u\n", c->request); +/* pa_log(__FILE__": executing request #%u\n", c->request); */ if (!handler->proc) { pa_log(__FILE__": recieved unimplemented request #%u.\n", c->request); @@ -789,6 +792,8 @@ static int do_read(struct connection *c) { assert(c->input_memblockq); +/* pa_log("STREAMING_DATA\n"); */ + if (!(l = pa_memblockq_missing(c->input_memblockq))) return 0; @@ -812,6 +817,8 @@ static int do_read(struct connection *c) { pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } + +/* pa_log(__FILE__": read %u\n", r); */ chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; @@ -832,6 +839,8 @@ static int do_read(struct connection *c) { static int do_write(struct connection *c) { assert(c && c->io); +/* pa_log("WRITE\n"); */ + if (c->write_data_length) { ssize_t r; @@ -872,18 +881,20 @@ static void do_work(struct connection *c) { assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 0); + +/* pa_log("DOWORK\n"); */ - if (c->dead) + if (c->dead || !c->io) return; - + if (pa_iochannel_is_readable(c->io)) if (do_read(c) < 0) goto fail; - + if (pa_iochannel_is_writable(c->io)) if (do_write(c) < 0) goto fail; - + return; fail: @@ -891,7 +902,10 @@ fail: if (c->state == ESD_STREAMING_DATA && c->sink_input) { c->dead = 1; pa_memblockq_prebuf_disable(c->input_memblockq); - c->protocol->core->mainloop->defer_enable(c->defer_event, 0); + + pa_iochannel_free(c->io); + c->io = NULL; + } else connection_free(c); } @@ -900,6 +914,8 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); +/* pa_log("IO\n"); */ + do_work(c); } @@ -909,6 +925,8 @@ static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, v struct connection *c = userdata; assert(a && c && c->defer_event == e); +/* pa_log("DEFER\n"); */ + do_work(c); } @@ -934,6 +952,8 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk struct connection*c = i->userdata; assert(i && c && length); +/* pa_log("DROP\n"); */ + pa_memblockq_drop(c->input_memblockq, chunk, length); /* do something */ From 450ad85b35bd600ed020f7ec119d51e7e7bc01a4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 27 Sep 2004 21:05:55 +0000 Subject: [PATCH 0239/1514] try to use file sample type for cache entries and play-file playback allow paplay to use STDIN add new module: module-match git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@244 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 - polyp/Makefile.am | 7 +- polyp/module-match.c | 217 ++++++++++++++++++++++++++++++++++++++ polyp/paplay.c | 26 +++-- polyp/scache.c | 9 +- polyp/sound-file-stream.c | 19 +++- polyp/sound-file.c | 25 ++++- polyp/util.c | 7 ++ polyp/util.h | 2 + 9 files changed, 292 insertions(+), 22 deletions(-) create mode 100644 polyp/module-match.c diff --git a/doc/todo b/doc/todo index b5ae1446d..eb8ebfb3f 100644 --- a/doc/todo +++ b/doc/todo @@ -11,10 +11,8 @@ - pacat sample type args - filter capture data in client through alignment - add redirection module -- add matching module - add radio module - make autoload list use idxset -- improve file load to note force sample typ to PA_SAMPLE_FLOAT32 ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 2d14b420b..d73c27bcf 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -105,7 +105,8 @@ modlib_LTLIBRARIES= \ module-sine.la \ module-combine.la \ module-esound-compat-spawnfd.la \ - module-esound-compat-spawnpid.la + module-esound-compat-spawnpid.la \ + module-match.la lib_LTLIBRARIES= \ libpolyp-@PA_MAJORMINOR@.la \ @@ -305,6 +306,10 @@ module_combine_la_SOURCES = module-combine.c module_combine_la_LDFLAGS = -module -avoid-version module_combine_la_LIBADD = $(AM_LIBADD) +module_match_la_SOURCES = module-match.c +module_match_la_LDFLAGS = -module -avoid-version +module_match_la_LIBADD = $(AM_LIBADD) + module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) diff --git a/polyp/module-match.c b/polyp/module-match.c new file mode 100644 index 000000000..964ff2fd7 --- /dev/null +++ b/polyp/module-match.c @@ -0,0 +1,217 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module.h" +#include "util.h" +#include "modargs.h" +#include "log.h" +#include "subscribe.h" +#include "xmalloc.h" +#include "sink-input.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Sink input matching module") +PA_MODULE_USAGE("table=") +PA_MODULE_VERSION(PACKAGE_VERSION) + +#define WHITESPACE "\n\r \t" + +static const char* const valid_modargs[] = { + "table", + NULL, +}; + +struct rule { + regex_t regex; + pa_volume_t volume; + struct rule *next; +}; + +struct userdata { + struct rule *rules; + struct pa_subscription *subscription; +}; + +static int load_rules(struct userdata *u, const char *filename) { + FILE *f; + int n = 0; + int ret = -1; + struct rule *end = NULL; + + if (!(f = fopen(filename, "r"))) { + pa_log(__FILE__": failed to open file '%s': %s\n", filename, strerror(errno)); + goto finish; + } + + while (!feof(f)) { + char *d, *v, *e = NULL; + pa_volume_t volume; + regex_t regex; + char ln[256]; + struct rule *rule; + + if (!fgets(ln, sizeof(ln), f)) + break; + + n++; + + pa_strip_nl(ln); + + if (ln[0] == '#' || !*ln ) + continue; + + d = ln+strcspn(ln, WHITESPACE); + v = d+strspn(d, WHITESPACE); + + + if (!*v) { + pa_log(__FILE__ ": [%s:%u] failed to parse line - too few words\n", filename, n); + goto finish; + } + + *d = 0; + + volume = (pa_volume_t) strtol(v, &e, 0); + + if (!e || *e) { + pa_log(__FILE__": [%s:%u] failed to parse volume\n", filename, n); + goto finish; + } + + if (regcomp(®ex, ln, REG_EXTENDED|REG_NOSUB) != 0) { + pa_log(__FILE__": [%s:%u] invalid regular expression\n", filename, n); + goto finish; + } + + rule = pa_xmalloc(sizeof(struct rule)); + rule->regex = regex; + rule->volume = volume; + rule->next = NULL; + + if (end) + end->next = rule; + else + u->rules = rule; + end = rule; + + *d = 0; + } + + ret = 0; + +finish: + if (f) + fclose(f); + + return ret; +} + +static void callback(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) { + struct userdata *u = userdata; + struct pa_sink_input *si; + struct rule *r; + assert(c && u); + + if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW)) + return; + + if (!(si = pa_idxset_get_by_index(c->sink_inputs, index))) { + pa_log(__FILE__": WARNING: failed to get sink input\n"); + return; + } + + if (!si->name) + return; + + for (r = u->rules; r; r = r->next) { + if (!regexec(&r->regex, si->name, 0, NULL, 0)) { + pa_log(__FILE__": changing volume of sink input '%s' to 0x%03x\n", si->name, r->volume); + pa_sink_input_set_volume(si, r->volume); + } + } +} + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct pa_modargs *ma = NULL; + int ret = -1; + const char *table_file; + struct userdata *u; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || + !(table_file = pa_modargs_get_value(ma, "table", NULL))) { + pa_log(__FILE__": Failed to parse module arguments\n"); + goto finish; + } + + u = pa_xmalloc(sizeof(struct userdata)); + u->rules = NULL; + u->subscription = NULL; + + if (load_rules(u, table_file) < 0) + goto finish; + + u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); + + ret = 0; + +finish: + if (ma) + pa_modargs_free(ma); + + return ret; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata* u; + struct rule *r, *n; + assert(c && m); + + if (!(u = m->userdata)) + return; + + if (u->subscription) + pa_subscription_free(u->subscription); + + for (r = u->rules; r; r = n) { + n = r->next; + + regfree(&r->regex); + pa_xfree(r); + } + + pa_xfree(u); +} + + diff --git a/polyp/paplay.c b/polyp/paplay.c index cc973a7d5..89358a516 100644 --- a/polyp/paplay.c +++ b/polyp/paplay.c @@ -192,7 +192,7 @@ static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_even static void help(const char *argv0) { - printf("%s [options] FILE\n\n" + printf("%s [options] [FILE]\n\n" " -h, --help Show this help\n" " --version Show version\n\n" " -v, --verbose Enable verbose operations\n\n" @@ -213,7 +213,7 @@ enum { int main(int argc, char *argv[]) { struct pa_mainloop* m = NULL; int ret = 1, r, c; - char *bn, *server = NULL; + char *bn, *server = NULL, *filename; SF_INFO sfinfo; static const struct option long_options[] = { @@ -281,24 +281,28 @@ int main(int argc, char *argv[]) { } } - if (optind >= argc) { - fprintf(stderr, "Missing file name.\n"); - goto quit; - } + filename = optind < argc ? argv[optind] : "STDIN"; + + if (!client_name) client_name = strdup(bn); if (!stream_name) - stream_name = strdup(argv[optind]); + stream_name = strdup(filename); memset(&sfinfo, 0, sizeof(sfinfo)); - - if (!(sndfile = sf_open(argv[optind], SFM_READ, &sfinfo))) { - fprintf(stderr, "Faile to open file '%s'\n", argv[optind]); + + if (optind < argc) + sndfile = sf_open(filename, SFM_READ, &sfinfo); + else + sndfile = sf_open_fd(STDIN_FILENO, SFM_READ, &sfinfo, 0); + + if (!sndfile) { + fprintf(stderr, "Failed to open file '%s'\n", filename); goto quit; } - + sample_spec.rate = sfinfo.samplerate; sample_spec.channels = sfinfo.channels; diff --git a/polyp/scache.c b/polyp/scache.c index b17f32421..329778542 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -37,6 +37,7 @@ #include "subscribe.h" #include "namereg.h" #include "sound-file.h" +#include "util.h" #define UNLOAD_POLL_TIME 2 @@ -199,6 +200,7 @@ void pa_scache_free(struct pa_core *c) { int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume) { struct pa_scache_entry *e; + char *t; assert(c && name && sink); if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) @@ -214,8 +216,13 @@ int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sin if (!e->memchunk.memblock) return -1; - if (pa_play_memchunk(sink, name, &e->sample_spec, &e->memchunk, pa_volume_multiply(volume, e->volume)) < 0) + t = pa_sprintf_malloc("sample:%s", name); + if (pa_play_memchunk(sink, t, &e->sample_spec, &e->memchunk, pa_volume_multiply(volume, e->volume)) < 0) { + free(t); return -1; + } + + free(t); if (e->lazy) time(&e->last_used_time); diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c index b77d6d615..347d45a7b 100644 --- a/polyp/sound-file-stream.c +++ b/polyp/sound-file-stream.c @@ -41,6 +41,7 @@ struct userdata { SNDFILE *sndfile; struct pa_sink_input *sink_input; struct pa_memchunk memchunk; + sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames); }; static void free_userdata(struct userdata *u) { @@ -78,7 +79,7 @@ static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { u->memchunk.memblock = pa_memblock_new(BUF_SIZE, i->sink->core->memblock_stat); u->memchunk.index = 0; - samples = sf_readf_float(u->sndfile, u->memchunk.memblock->data, samples); + samples = u->readf_function(u->sndfile, u->memchunk.memblock->data, samples); u->memchunk.length = samples*fs; if (!u->memchunk.length) { @@ -136,7 +137,21 @@ int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume) { goto fail; } - ss.format = PA_SAMPLE_FLOAT32; + switch (sfinfo.format & 0xFF) { + case SF_FORMAT_PCM_16: + case SF_FORMAT_PCM_U8: + case SF_FORMAT_ULAW: + case SF_FORMAT_ALAW: + ss.format = PA_SAMPLE_S16NE; + u->readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short; + break; + case SF_FORMAT_FLOAT: + default: + ss.format = PA_SAMPLE_FLOAT32NE; + u->readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float; + break; + } + ss.rate = sfinfo.samplerate; ss.channels = sfinfo.channels; diff --git a/polyp/sound-file.c b/polyp/sound-file.c index d1f7e0f7b..c63aa628f 100644 --- a/polyp/sound-file.c +++ b/polyp/sound-file.c @@ -39,19 +39,34 @@ int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_m SF_INFO sfinfo; int ret = -1; size_t l; + sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames); assert(fname && ss && chunk); - memset(&sfinfo, 0, sizeof(sfinfo)); - chunk->memblock = NULL; chunk->index = chunk->length = 0; - + + memset(&sfinfo, 0, sizeof(sfinfo)); + if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { pa_log(__FILE__": Failed to open file %s\n", fname); goto finish; } - ss->format = PA_SAMPLE_FLOAT32; + switch (sfinfo.format & 0xFF) { + case SF_FORMAT_PCM_16: + case SF_FORMAT_PCM_U8: + case SF_FORMAT_ULAW: + case SF_FORMAT_ALAW: + ss->format = PA_SAMPLE_S16NE; + readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short; + break; + case SF_FORMAT_FLOAT: + default: + ss->format = PA_SAMPLE_FLOAT32NE; + readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float; + break; + } + ss->rate = sfinfo.samplerate; ss->channels = sfinfo.channels; @@ -70,7 +85,7 @@ int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_m chunk->index = 0; chunk->length = l; - if (sf_readf_float(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) { + if (readf_function(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) { pa_log(__FILE__": Premature file end\n"); goto finish; } diff --git a/polyp/util.c b/polyp/util.c index 166a9a45c..fa33ffffe 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -518,3 +518,10 @@ int pa_lock_file(int fd, int b) { return 0; } + +char* pa_strip_nl(char *s) { + assert(s); + + s[strcspn(s, "\r\n")] = 0; + return s; +} diff --git a/polyp/util.h b/polyp/util.h index 571bb29be..e1910c831 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -62,6 +62,8 @@ int pa_parse_boolean(const char *s); char *pa_split(const char *c, const char*delimiters, const char **state); char *pa_split_spaces(const char *c, const char **state); +char *pa_strip_nl(char *s); + const char *pa_strsignal(int sig); int pa_parse_resample_method(const char *string); From 6f59ae1763ee48f27448a7de9d635f61886052e1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Sep 2004 22:47:48 +0000 Subject: [PATCH 0240/1514] Add module-tunnel add proper locking when autospawning a daemon git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@245 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- polyp/Makefile.am | 7 +- polyp/authkey.c | 20 +- polyp/module-match.c | 18 +- polyp/module-protocol-stub.c | 3 +- polyp/module-tunnel.c | 423 +++++++++++++++++++++++++++++++++++ polyp/native-common.h | 2 + polyp/polyplib-context.c | 52 ++--- polyp/polyplib-internal.h | 3 +- polyp/sink.h | 1 - polyp/socket-util.c | 33 +++ polyp/socket-util.h | 2 + polyp/util.c | 43 +++- polyp/util.h | 4 +- 14 files changed, 554 insertions(+), 59 deletions(-) create mode 100644 polyp/module-tunnel.c diff --git a/doc/todo b/doc/todo index eb8ebfb3f..ad272ae4c 100644 --- a/doc/todo +++ b/doc/todo @@ -7,12 +7,12 @@ - make mcalign merge chunks - option to use default fragment size on alsa drivers - improve module-oss-mmap latency measurement -- proper locking around native protocol socket - pacat sample type args - filter capture data in client through alignment - add redirection module - add radio module - make autoload list use idxset +- libwrap ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index d73c27bcf..9f6fa1d52 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -106,7 +106,8 @@ modlib_LTLIBRARIES= \ module-combine.la \ module-esound-compat-spawnfd.la \ module-esound-compat-spawnpid.la \ - module-match.la + module-match.la \ + module-tunnel.la lib_LTLIBRARIES= \ libpolyp-@PA_MAJORMINOR@.la \ @@ -310,6 +311,10 @@ module_match_la_SOURCES = module-match.c module_match_la_LDFLAGS = -module -avoid-version module_match_la_LIBADD = $(AM_LIBADD) +module_tunnel_la_SOURCES = module-tunnel.c +module_tunnel_la_LDFLAGS = -module -avoid-version +module_tunnel_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la + module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) diff --git a/polyp/authkey.c b/polyp/authkey.c index 1e2edb07d..c8d8576b9 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -97,7 +97,7 @@ static int load(const char *fn, void *data, size_t length) { writable = 0; } - unlock = pa_lock_file(fd, 1) >= 0; + unlock = pa_lock_fd(fd, 1) >= 0; if ((r = pa_loop_read(fd, data, length)) < 0) { pa_log(__FILE__": failed to read cookie file '%s'\n", fn); @@ -122,7 +122,7 @@ finish: if (fd >= 0) { if (unlock) - pa_lock_file(fd, 0); + pa_lock_fd(fd, 0); close(fd); } @@ -147,15 +147,19 @@ int pa_authkey_load(const char *path, void *data, size_t length) { int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { char *home; char path[PATH_MAX]; + char *p; assert(fn && data && length); - - if (!(home = getenv("HOME"))) - return -2; - - snprintf(path, sizeof(path), "%s/%s", home, fn); - return pa_authkey_load(path, data, length); + if (fn[0] != '/') { + if (!(home = getenv("HOME"))) + return -2; + + snprintf(p = path, sizeof(path), "%s/%s", home, fn); + } else + p = fn; + + return pa_authkey_load(p, data, length); } int pa_authkey_load_auto(const char *fn, void *data, size_t length) { diff --git a/polyp/module-match.c b/polyp/module-match.c index 964ff2fd7..380c6011a 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -164,7 +164,6 @@ static void callback(struct pa_core *c, enum pa_subscription_event_type t, uint3 int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; - int ret = -1; const char *table_file; struct userdata *u; assert(c && m); @@ -172,25 +171,28 @@ int pa__init(struct pa_core *c, struct pa_module*m) { if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || !(table_file = pa_modargs_get_value(ma, "table", NULL))) { pa_log(__FILE__": Failed to parse module arguments\n"); - goto finish; + goto fail; } u = pa_xmalloc(sizeof(struct userdata)); u->rules = NULL; u->subscription = NULL; + m->userdata = u; if (load_rules(u, table_file) < 0) - goto finish; + goto fail; u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); - - ret = 0; -finish: + pa_modargs_free(ma); + return 0; + +fail: + pa__done(c, m); + if (ma) pa_modargs_free(ma); - - return ret; + return -1; } void pa__done(struct pa_core *c, struct pa_module*m) { diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 17c491dea..fc1e9fd92 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -37,6 +37,7 @@ #include "util.h" #include "modargs.h" #include "log.h" +#include "native-common.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_VERSION(PACKAGE_VERSION) @@ -72,7 +73,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #include "protocol-native.h" #define protocol_new pa_protocol_native_new #define protocol_free pa_protocol_native_free - #define IPV4_PORT 4713 + #define IPV4_PORT PA_NATIVE_DEFAULT_PORT #define UNIX_SOCKET "/tmp/polypaudio/native" #define MODULE_ARGUMENTS "public", "cookie", PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c new file mode 100644 index 000000000..0c78b138e --- /dev/null +++ b/polyp/module-tunnel.c @@ -0,0 +1,423 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module.h" +#include "util.h" +#include "modargs.h" +#include "log.h" +#include "subscribe.h" +#include "xmalloc.h" +#include "sink-input.h" +#include "pdispatch.h" +#include "pstream.h" +#include "pstream-util.h" +#include "authkey.h" +#include "socket-client.h" +#include "socket-util.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Tunnel module") +PA_MODULE_USAGE("server= sink= cookie= format= channels= rate= sink_name=") +PA_MODULE_VERSION(PACKAGE_VERSION) + +#define DEFAULT_SINK_NAME "tunnel" + +#define DEFAULT_TLENGTH (10240*8) +#define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) +#define DEFAULT_PREBUF DEFAULT_TLENGTH +#define DEFAULT_MINREQ 512 +#define DEFAULT_FRAGSIZE 1024 + +#define DEFAULT_TIMEOUT 5 + +static const char* const valid_modargs[] = { + "server", + "sink", + "cookie", + "format", + "channels", + "rate", + "sink_name", + NULL, +}; + +static void command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + +static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_REQUEST] = { command_request }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_stream_killed }, + [PA_COMMAND_RECORD_STREAM_KILLED] = { command_stream_killed }, +}; + +struct userdata { + struct pa_socket_client *client; + struct pa_pstream *pstream; + struct pa_pdispatch *pdispatch; + + char *server_name, *sink_name; + + struct pa_sink *sink; + struct pa_module *module; + struct pa_core *core; + + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; + + uint32_t ctag; + uint32_t device_index; + uint32_t requested_bytes; + uint32_t channel; +}; + + +static void close_stuff(struct userdata *u) { + if (u->pstream) { + pa_pstream_close(u->pstream); + pa_pstream_unref(u->pstream); + u->pstream = NULL; + } + + if (u->pdispatch) { + pa_pdispatch_unref(u->pdispatch); + u->pdispatch = NULL; + } + + if (u->client) { + pa_socket_client_unref(u->client); + u->client = NULL; + } + + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + u->sink = NULL; + } +} + +static void die(struct userdata *u) { + assert(u); + close_stuff(u); + pa_module_unload_request(u->module); +} + +static void request_bytes(struct userdata *u) { + assert(u); + + if (!u->pstream) + return; + + while (u->requested_bytes > 0) { + struct pa_memchunk chunk; + if (pa_sink_render(u->sink, u->requested_bytes, &chunk) < 0) + return; + + pa_pstream_send_memblock(u->pstream, u->channel, 0, &chunk); + pa_memblock_unref(chunk.memblock); + + if (chunk.length > u->requested_bytes) + u->requested_bytes = 0; + else + u->requested_bytes -= chunk.length; + } +} + +static void command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + assert(pd && t && u && u->pdispatch == pd); + + pa_log(__FILE__": stream killed\n"); + die(u); +} + +static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + uint32_t bytes, channel; + assert(pd && command == PA_COMMAND_REQUEST && t && u && u->pdispatch == pd); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_getu32(t, &bytes) < 0 || + !pa_tagstruct_eof(t)) { + pa_log(__FILE__": invalid protocol reply\n"); + die(u); + return; + } + + if (channel != u->channel) { + pa_log(__FILE__": recieved data for invalid channel\n"); + die(u); + return; + } + + u->requested_bytes += bytes; + request_bytes(u); +} + + +static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + assert(pd && u && u->pdispatch == pd); + + if (command != PA_COMMAND_REPLY) { + if (command == PA_COMMAND_ERROR) + pa_log(__FILE__": failed to create stream.\n"); + else + pa_log(__FILE__": protocol error.\n"); + die(u); + return; + } + + if (pa_tagstruct_getu32(t, &u->channel) < 0 || + pa_tagstruct_getu32(t, &u->device_index) < 0 || + pa_tagstruct_getu32(t, &u->requested_bytes) < 0 || + !pa_tagstruct_eof(t)) { + pa_log(__FILE__": invalid reply.\n"); + die(u); + return; + } + + request_bytes(u); +} + +static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + struct pa_tagstruct *reply; + char name[256], un[128], hn[128]; + assert(pd && u && u->pdispatch == pd); + + if (command != PA_COMMAND_REPLY || !pa_tagstruct_eof(t)) { + if (command == PA_COMMAND_ERROR) + pa_log(__FILE__": failed to authenticate\n"); + else + pa_log(__FILE__": protocol error.\n"); + die(u); + return; + } + + snprintf(name, sizeof(name), "Tunnel from host '%s', user '%s', sink '%s'", + pa_get_host_name(hn, sizeof(hn)), + pa_get_user_name(un, sizeof(un)), + u->sink->name); + + reply = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME); + pa_tagstruct_putu32(reply, tag = u->ctag++); + pa_tagstruct_puts(reply, name); + pa_pstream_send_tagstruct(u->pstream, reply); + /* We ignore the server's reply here */ + + reply = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(reply, PA_COMMAND_CREATE_PLAYBACK_STREAM); + pa_tagstruct_putu32(reply, tag = u->ctag++); + pa_tagstruct_puts(reply, name); + pa_tagstruct_put_sample_spec(reply, &u->sink->sample_spec); + pa_tagstruct_putu32(reply, PA_INVALID_INDEX); + pa_tagstruct_puts(reply, u->sink_name); + pa_tagstruct_putu32(reply, DEFAULT_MAXLENGTH); + pa_tagstruct_put_boolean(reply, 0); + pa_tagstruct_putu32(reply, DEFAULT_TLENGTH); + pa_tagstruct_putu32(reply, DEFAULT_PREBUF); + pa_tagstruct_putu32(reply, DEFAULT_MINREQ); + pa_tagstruct_putu32(reply, PA_VOLUME_NORM); + + pa_pstream_send_tagstruct(u->pstream, reply); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u); +} + +static void pstream_die_callback(struct pa_pstream *p, void *userdata) { + struct userdata *u = userdata; + assert(p && u); + + pa_log(__FILE__": stream died.\n"); + die(u); +} + + +static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { + struct userdata *u = userdata; + assert(p && packet && u); + + if (pa_pdispatch_run(u->pdispatch, packet, u) < 0) { + pa_log(__FILE__": invalid packet\n"); + die(u); + } +} + +static void on_connection(struct pa_socket_client *sc, struct pa_iochannel *io, void *userdata) { + struct userdata *u = userdata; + struct pa_tagstruct *t; + uint32_t tag; + assert(sc && io && u && u->client == sc); + + pa_socket_client_unref(u->client); + u->client = NULL; + + if (!io) { + pa_log(__FILE__": connection failed.\n"); + pa_module_unload_request(u->module); + return; + } + + u->pstream = pa_pstream_new(u->core->mainloop, io, u->core->memblock_stat); + u->pdispatch = pa_pdispatch_new(u->core->mainloop, command_table, PA_COMMAND_MAX); + + pa_pstream_set_die_callback(u->pstream, pstream_die_callback, u); + pa_pstream_set_recieve_packet_callback(u->pstream, pstream_packet_callback, u); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_AUTH); + pa_tagstruct_putu32(t, tag = u->ctag++); + pa_tagstruct_put_arbitrary(t, u->auth_cookie, sizeof(u->auth_cookie)); + pa_pstream_send_tagstruct(u->pstream, t); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, u); + +} + +static void sink_notify(struct pa_sink*sink) { + struct userdata *u; + assert(sink && sink->userdata); + u = sink->userdata; + + request_bytes(u); +} + +static pa_usec_t sink_get_latency(struct pa_sink *sink) { + struct userdata *u; + assert(sink && sink->userdata); + u = sink->userdata; + + return 0; +} + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct pa_modargs *ma = NULL; + struct userdata *u = NULL; + struct pa_sample_spec ss; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments\n"); + + } + + u = pa_xmalloc(sizeof(struct userdata)); + m->userdata = u; + u->module = m; + u->core = c; + u->client = NULL; + u->pdispatch = NULL; + u->pstream = NULL; + u->server_name = u->sink_name = NULL; + u->sink = NULL; + u->ctag = 1; + u->device_index = u->channel = PA_INVALID_INDEX; + u->requested_bytes = 0; + + if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), u->auth_cookie, sizeof(u->auth_cookie)) < 0) { + pa_log(__FILE__": failed to load cookie.\n"); + goto fail; + } + + if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) { + pa_log(__FILE__": no server specified.\n"); + goto fail; + } + + u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + + ss = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + pa_log(__FILE__": invalid sample format specification\n"); + goto fail; + } + + if (u->server_name[0] == '/') + u->client = pa_socket_client_new_unix(c->mainloop, u->server_name); + else { + size_t len; + struct sockaddr *sa; + + if (!(sa = pa_resolve_server(u->server_name, &len, PA_NATIVE_DEFAULT_PORT))) { + pa_log(__FILE__": failed to resolve server '%s'\n", u->server_name); + goto fail; + } + + u->client = pa_socket_client_new_sockaddr(c->mainloop, sa, len); + pa_xfree(sa); + } + + if (!u->client) + goto fail; + + pa_socket_client_set_callback(u->client, on_connection, u); + + if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + pa_log(__FILE__": failed to create sink.\n"); + goto fail; + } + + u->sink->notify = sink_notify; + u->sink->get_latency = sink_get_latency; + u->sink->userdata = u; + u->sink->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->sink_name ? u->sink_name : "", u->sink_name ? "@" : "", u->server_name); + + pa_sink_set_owner(u->sink, m); + + pa_modargs_free(ma); + + return 0; + +fail: + pa__done(c, m); + + if (ma) + pa_modargs_free(ma); + return -1; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata* u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + close_stuff(u); + + pa_xfree(u->sink_name); + pa_xfree(u->server_name); + + pa_xfree(u); +} + + diff --git a/polyp/native-common.h b/polyp/native-common.h index 5ecb26c07..33ecdc76f 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -96,6 +96,8 @@ enum { #define PA_NATIVE_COOKIE_LENGTH 256 #define PA_NATIVE_COOKIE_FILE ".polypaudio-cookie" +#define PA_NATIVE_DEFAULT_PORT 4713 + PA_C_DECL_END #endif diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index d793c186f..d2fae0af9 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -48,8 +48,10 @@ #include "xmalloc.h" #include "log.h" #include "client-conf.h" +#include "socket-util.h" #define DEFAULT_SERVER "/tmp/polypaudio/native" +#define AUTOSPAWN_LOCK "/tmp/polypaudio/autospawn.lock" static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = { pa_command_request }, @@ -347,38 +349,6 @@ finish: pa_context_unref(c); } -static struct sockaddr *resolve_server(const char *server, size_t *len) { - struct sockaddr *sa; - struct addrinfo hints, *result = NULL; - char *port, host[256]; - assert(server && len); - - snprintf(host, sizeof(host), "%s", server); - host[strcspn(host, ":")] = 0; - - if ((port = strrchr(server, ':'))) - port++; - - if (!port) - port = DEFAULT_PORT; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(host, port, &hints, &result) != 0) - return NULL; - assert(result); - - sa = pa_xmalloc(*len = result->ai_addrlen); - memcpy(sa, result->ai_addr, *len); - - freeaddrinfo(result); - - return sa; -} - static int default_server_is_running(void) { struct stat st; @@ -499,9 +469,21 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons if (!server) server = c->conf->default_server; - if (!server && spawn && c->conf->autospawn && !default_server_is_running()) - return context_connect_spawn(c, api); + if (!server && spawn && c->conf->autospawn) { + int lock_fd = pa_lock_lockfile(AUTOSPAWN_LOCK); + + if (!default_server_is_running()) { + int r = context_connect_spawn(c, api); + if (lock_fd >= 0) + pa_unlock_lockfile(lock_fd); + return r; + } + + if (lock_fd >= 0) + pa_unlock_lockfile(lock_fd); + } + if (!server) server = DEFAULT_SERVER; @@ -520,7 +502,7 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons struct sockaddr* sa; size_t sa_len; - if (!(sa = resolve_server(server, &sa_len))) { + if (!(sa = pa_resolve_server(server, &sa_len, PA_NATIVE_DEFAULT_PORT))) { pa_context_fail(c, PA_ERROR_INVALIDSERVER); goto finish; } diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 656d07dbe..c10ca515a 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -41,8 +41,7 @@ #define DEFAULT_MINREQ 512 #define DEFAULT_FRAGSIZE 1024 -#define DEFAULT_TIMEOUT (5*60) -#define DEFAULT_PORT "4713" +#define DEFAULT_TIMEOUT (10) #define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED" diff --git a/polyp/sink.h b/polyp/sink.h index b34a736cc..a2d34ee5b 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -64,7 +64,6 @@ void pa_sink_disconnect(struct pa_sink* s); void pa_sink_unref(struct pa_sink*s); struct pa_sink* pa_sink_ref(struct pa_sink *s); - int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result); void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *result); int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target); diff --git a/polyp/socket-util.c b/polyp/socket-util.c index 20380653d..499739bd3 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "socket-util.h" #include "util.h" @@ -219,3 +220,35 @@ finish: return ret; } +struct sockaddr *pa_resolve_server(const char *server, size_t *len, uint16_t nport) { + struct sockaddr *sa; + struct addrinfo hints, *result = NULL; + char *port, host[256], tmp[16]; + assert(server && len); + + snprintf(host, sizeof(host), "%s", server); + host[strcspn(host, ":")] = 0; + + if ((port = strrchr(server, ':'))) + port++; + + if (!port) + snprintf(port = tmp, sizeof(tmp), "%u", nport); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + if (getaddrinfo(host, port, &hints, &result) != 0) + return NULL; + assert(result); + + sa = pa_xmalloc(*len = result->ai_addrlen); + memcpy(sa, result->ai_addr, *len); + + freeaddrinfo(result); + + return sa; +} + diff --git a/polyp/socket-util.h b/polyp/socket-util.h index 85133febd..46fcfdc97 100644 --- a/polyp/socket-util.h +++ b/polyp/socket-util.h @@ -38,4 +38,6 @@ int pa_unix_socket_remove_stale(const char *fn); int pa_unix_socket_make_secure_dir(const char *fn); int pa_unix_socket_remove_secure_dir(const char *fn); +struct sockaddr *pa_resolve_server(const char *server, size_t *len, uint16_t port); + #endif diff --git a/polyp/util.c b/polyp/util.c index fa33ffffe..70ec120d3 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -502,7 +502,7 @@ finish: return r; } -int pa_lock_file(int fd, int b) { +int pa_lock_fd(int fd, int b) { struct flock flock; @@ -525,3 +525,44 @@ char* pa_strip_nl(char *s) { s[strcspn(s, "\r\n")] = 0; return s; } + +int pa_lock_lockfile(const char *fn) { + int fd; + assert(fn); + + if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { + pa_log(__FILE__": failed to create lock file '%s'\n", fn); + goto fail; + } + + if (pa_lock_fd(fd, 1) < 0) + goto fail; + + return fd; + +fail: + + if (fd >= 0) + close(fd); + + return -1; +} + + +int pa_unlock_lockfile(int fd) { + int r = 0; + assert(fd >= 0); + + if (pa_lock_fd(fd, 0) < 0) { + pa_log(__FILE__": WARNING: failed to unlock file.\n"); + r = -1; + } + + if (close(fd) < 0) { + pa_log(__FILE__": WARNING: failed to close lock file.\n"); + r = -1; + } + + return r; +} + diff --git a/polyp/util.h b/polyp/util.h index e1910c831..b0a1a0337 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -70,7 +70,9 @@ int pa_parse_resample_method(const char *string); int pa_uid_in_group(const char *name, gid_t *gid); -int pa_lock_file(int fd, int b); +int pa_lock_fd(int fd, int b); +int pa_lock_lockfile(const char *fn); +int pa_unlock_lockfile(int fd); #endif From 33c85aec01f625b4d62eabb5f0e88d5a5ae3d17f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Sep 2004 23:49:54 +0000 Subject: [PATCH 0241/1514] add latency measurement support to tunnel module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@246 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- polyp/module-tunnel.c | 137 +++++++++++++++++++++++++++++++++++--- polyp/polyplib-internal.h | 4 +- 3 files changed, 130 insertions(+), 13 deletions(-) diff --git a/doc/todo b/doc/todo index ad272ae4c..439eb770f 100644 --- a/doc/todo +++ b/doc/todo @@ -9,7 +9,7 @@ - improve module-oss-mmap latency measurement - pacat sample type args - filter capture data in client through alignment -- add redirection module +- add tunnel module for sources - add radio module - make autoload list use idxset - libwrap diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index 0c78b138e..030299216 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -53,14 +53,16 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define DEFAULT_SINK_NAME "tunnel" -#define DEFAULT_TLENGTH (10240*8) +#define DEFAULT_TLENGTH (44100*2*2/10) //(10240*8) #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) -#define DEFAULT_PREBUF DEFAULT_TLENGTH #define DEFAULT_MINREQ 512 +#define DEFAULT_PREBUF (DEFAULT_TLENGTH-DEFAULT_MINREQ) #define DEFAULT_FRAGSIZE 1024 #define DEFAULT_TIMEOUT 5 +#define LATENCY_INTERVAL 10 + static const char* const valid_modargs[] = { "server", "sink", @@ -98,6 +100,10 @@ struct userdata { uint32_t device_index; uint32_t requested_bytes; uint32_t channel; + + pa_usec_t host_latency; + + struct pa_time_event *time_event; }; @@ -123,6 +129,11 @@ static void close_stuff(struct userdata *u) { pa_sink_unref(u->sink); u->sink = NULL; } + + if (u->time_event) { + u->core->mainloop->time_free(u->time_event); + u->time_event = NULL; + } } static void die(struct userdata *u) { @@ -131,16 +142,32 @@ static void die(struct userdata *u) { pa_module_unload_request(u->module); } -static void request_bytes(struct userdata *u) { +static void send_prebuf_request(struct userdata *u) { + struct pa_tagstruct *t; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_PREBUF_PLAYBACK_STREAM); + pa_tagstruct_putu32(t, u->ctag++); + pa_tagstruct_putu32(t, u->channel); + pa_pstream_send_tagstruct(u->pstream, t); +} + +static void send_bytes(struct userdata *u) { assert(u); if (!u->pstream) return; - + while (u->requested_bytes > 0) { struct pa_memchunk chunk; - if (pa_sink_render(u->sink, u->requested_bytes, &chunk) < 0) + if (pa_sink_render(u->sink, u->requested_bytes, &chunk) < 0) { + + + if (u->requested_bytes >= DEFAULT_TLENGTH-DEFAULT_PREBUF) + send_prebuf_request(u); + return; + } pa_pstream_send_memblock(u->pstream, u->channel, 0, &chunk); pa_memblock_unref(chunk.memblock); @@ -180,9 +207,69 @@ static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t } u->requested_bytes += bytes; - request_bytes(u); + send_bytes(u); } +static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + pa_usec_t buffer_usec, sink_usec, source_usec, transport_usec; + int playing; + uint32_t queue_length; + struct timeval local, remote, now; + assert(pd && u && t); + + if (command != PA_COMMAND_REPLY) { + if (command == PA_COMMAND_ERROR) + pa_log(__FILE__": failed to get latency.\n"); + else + pa_log(__FILE__": protocol error.\n"); + die(u); + return; + } + + if (pa_tagstruct_get_usec(t, &buffer_usec) < 0 || + pa_tagstruct_get_usec(t, &sink_usec) < 0 || + pa_tagstruct_get_usec(t, &source_usec) < 0 || + pa_tagstruct_get_boolean(t, &playing) < 0 || + pa_tagstruct_getu32(t, &queue_length) < 0 || + pa_tagstruct_get_timeval(t, &local) < 0 || + pa_tagstruct_get_timeval(t, &remote) < 0 || + !pa_tagstruct_eof(t)) { + pa_log(__FILE__": invalid reply.\n"); + die(u); + return; + } + + gettimeofday(&now, NULL); + + if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) + /* local and remote seem to have synchronized clocks */ + transport_usec = pa_timeval_diff(&remote, &local); + else + transport_usec = pa_timeval_diff(&now, &local)/2; + + u->host_latency = sink_usec + transport_usec; + +/* pa_log(__FILE__": estimated host latency: %0.0f usec\n", (double) u->host_latency); */ +} + +static void request_latency(struct userdata *u) { + struct pa_tagstruct *t; + struct timeval now; + uint32_t tag; + assert(u); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); + pa_tagstruct_putu32(t, tag = u->ctag++); + pa_tagstruct_putu32(t, u->channel); + + gettimeofday(&now, NULL); + pa_tagstruct_put_timeval(t, &now); + + pa_pstream_send_tagstruct(u->pstream, t); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u); +} static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; @@ -206,7 +293,8 @@ static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, ui return; } - request_bytes(u); + request_latency(u); + send_bytes(u); } static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { @@ -308,26 +396,50 @@ static void sink_notify(struct pa_sink*sink) { assert(sink && sink->userdata); u = sink->userdata; - request_bytes(u); + send_bytes(u); } static pa_usec_t sink_get_latency(struct pa_sink *sink) { struct userdata *u; + uint32_t l; + pa_usec_t usec = 0; assert(sink && sink->userdata); u = sink->userdata; - return 0; + l = DEFAULT_TLENGTH; + + if (l > u->requested_bytes) { + l -= u->requested_bytes; + usec += pa_bytes_to_usec(l, &u->sink->sample_spec); + } + + usec += u->host_latency; + + return usec; +} + +static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + struct timeval ntv; + assert(m && e && u); + + request_latency(u); + + gettimeofday(&ntv, NULL); + ntv.tv_sec += LATENCY_INTERVAL; + m->time_restart(e, &ntv); } int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; struct userdata *u = NULL; struct pa_sample_spec ss; + struct timeval ntv; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments\n"); - + goto fail; } u = pa_xmalloc(sizeof(struct userdata)); @@ -342,6 +454,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->ctag = 1; u->device_index = u->channel = PA_INVALID_INDEX; u->requested_bytes = 0; + u->host_latency = 0; if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), u->auth_cookie, sizeof(u->auth_cookie)) < 0) { pa_log(__FILE__": failed to load cookie.\n"); @@ -391,6 +504,10 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->sink->userdata = u; u->sink->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->sink_name ? u->sink_name : "", u->sink_name ? "@" : "", u->server_name); + gettimeofday(&ntv, NULL); + ntv.tv_sec += LATENCY_INTERVAL; + u->time_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, u); + pa_sink_set_owner(u->sink, m); pa_modargs_free(ma); diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index c10ca515a..58c617e45 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -35,10 +35,10 @@ #include "native-common.h" #include "client-conf.h" -#define DEFAULT_TLENGTH (10240*8) +#define DEFAULT_TLENGTH (44100*2*2/10) //(10240*8) #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) -#define DEFAULT_PREBUF DEFAULT_TLENGTH #define DEFAULT_MINREQ 512 +#define DEFAULT_PREBUF (DEFAULT_TLENGTH-DEFAULT_MINREQ) #define DEFAULT_FRAGSIZE 1024 #define DEFAULT_TIMEOUT (10) From d8f700e5395610a83a944502fc82f7cd24f22614 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Sep 2004 23:52:50 +0000 Subject: [PATCH 0242/1514] fix module-tunnel for to aborting when connection fails git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@247 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-tunnel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index 030299216..a151b52a4 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -365,7 +365,7 @@ static void on_connection(struct pa_socket_client *sc, struct pa_iochannel *io, struct userdata *u = userdata; struct pa_tagstruct *t; uint32_t tag; - assert(sc && io && u && u->client == sc); + assert(sc && u && u->client == sc); pa_socket_client_unref(u->client); u->client = NULL; From 6dfab4ec7b8d8702d425b2ec9b5f1aff5c8290cd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 29 Sep 2004 17:38:45 +0000 Subject: [PATCH 0243/1514] renamed module-tunnel to module-tunnel-sink new module module-tunnel-source fix recording git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@248 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 14 +++- polyp/module-tunnel.c | 173 ++++++++++++++++++++++++++++++++++------ polyp/protocol-native.c | 4 + polyp/source.c | 4 +- polyp/source.h | 2 +- 5 files changed, 164 insertions(+), 33 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 9f6fa1d52..29b388c9a 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -107,7 +107,8 @@ modlib_LTLIBRARIES= \ module-esound-compat-spawnfd.la \ module-esound-compat-spawnpid.la \ module-match.la \ - module-tunnel.la + module-tunnel-sink.la \ + module-tunnel-source.la lib_LTLIBRARIES= \ libpolyp-@PA_MAJORMINOR@.la \ @@ -311,9 +312,14 @@ module_match_la_SOURCES = module-match.c module_match_la_LDFLAGS = -module -avoid-version module_match_la_LIBADD = $(AM_LIBADD) -module_tunnel_la_SOURCES = module-tunnel.c -module_tunnel_la_LDFLAGS = -module -avoid-version -module_tunnel_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la +module_tunnel_sink_la_SOURCES = module-tunnel.c +module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) +module_tunnel_sink_la_LDFLAGS = -module -avoid-version +module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la + +module_tunnel_source_la_SOURCES = module-tunnel.c +module_tunnel_source_la_LDFLAGS = -module -avoid-version +module_tunnel_source_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index a151b52a4..1a720f3b5 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -47,11 +47,18 @@ #include "socket-util.h" PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Tunnel module") -PA_MODULE_USAGE("server= sink= cookie= format= channels= rate= sink_name=") PA_MODULE_VERSION(PACKAGE_VERSION) +#ifdef TUNNEL_SINK +PA_MODULE_DESCRIPTION("Tunnel module for sinks") +PA_MODULE_USAGE("server= sink= cookie= format= channels= rate= sink_name=") +#else +PA_MODULE_DESCRIPTION("Tunnel module for sources") +PA_MODULE_USAGE("server= source= cookie= format= channels= rate= source_name=") +#endif + #define DEFAULT_SINK_NAME "tunnel" +#define DEFAULT_SOURCE_NAME "tunnel" #define DEFAULT_TLENGTH (44100*2*2/10) //(10240*8) #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) @@ -65,20 +72,30 @@ PA_MODULE_VERSION(PACKAGE_VERSION) static const char* const valid_modargs[] = { "server", - "sink", "cookie", "format", "channels", "rate", +#ifdef TUNNEL_SINK "sink_name", + "sink", +#else + "source_name", + "source", +#endif NULL, }; static void command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + +#ifdef TUNNEL_SINK static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +#endif static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { +#ifdef TUNNEL_SINK [PA_COMMAND_REQUEST] = { command_request }, +#endif [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_stream_killed }, [PA_COMMAND_RECORD_STREAM_KILLED] = { command_stream_killed }, }; @@ -88,9 +105,16 @@ struct userdata { struct pa_pstream *pstream; struct pa_pdispatch *pdispatch; - char *server_name, *sink_name; - + char *server_name; +#ifdef TUNNEL_SINK + char *sink_name; struct pa_sink *sink; + uint32_t requested_bytes; +#else + char *source_name; + struct pa_source *source; +#endif + struct pa_module *module; struct pa_core *core; @@ -98,9 +122,8 @@ struct userdata { uint32_t ctag; uint32_t device_index; - uint32_t requested_bytes; uint32_t channel; - + pa_usec_t host_latency; struct pa_time_event *time_event; @@ -124,11 +147,19 @@ static void close_stuff(struct userdata *u) { u->client = NULL; } +#ifdef TUNNEL_SINK if (u->sink) { pa_sink_disconnect(u->sink); pa_sink_unref(u->sink); u->sink = NULL; } +#else + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + u->source = NULL; + } +#endif if (u->time_event) { u->core->mainloop->time_free(u->time_event); @@ -142,6 +173,15 @@ static void die(struct userdata *u) { pa_module_unload_request(u->module); } +static void command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + assert(pd && t && u && u->pdispatch == pd); + + pa_log(__FILE__": stream killed\n"); + die(u); +} + +#ifdef TUNNEL_SINK static void send_prebuf_request(struct userdata *u) { struct pa_tagstruct *t; @@ -179,14 +219,6 @@ static void send_bytes(struct userdata *u) { } } -static void command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct userdata *u = userdata; - assert(pd && t && u && u->pdispatch == pd); - - pa_log(__FILE__": stream killed\n"); - die(u); -} - static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; uint32_t bytes, channel; @@ -210,6 +242,8 @@ static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t send_bytes(u); } +#endif + static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; pa_usec_t buffer_usec, sink_usec, source_usec, transport_usec; @@ -242,13 +276,25 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman gettimeofday(&now, NULL); - if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) + if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) { /* local and remote seem to have synchronized clocks */ +#ifdef TUNNEL_SINK transport_usec = pa_timeval_diff(&remote, &local); - else +#else + transport_usec = pa_timeval_diff(&now, &remote); +#endif + } else transport_usec = pa_timeval_diff(&now, &local)/2; - + +#ifdef TUNNEL_SINK u->host_latency = sink_usec + transport_usec; +#else + u->host_latency = source_usec + transport_usec; + if (u->host_latency > sink_usec) + u->host_latency -= sink_usec; + else + u->host_latency = 0; +#endif /* pa_log(__FILE__": estimated host latency: %0.0f usec\n", (double) u->host_latency); */ } @@ -260,7 +306,11 @@ static void request_latency(struct userdata *u) { assert(u); t = pa_tagstruct_new(NULL, 0); +#ifdef TUNNEL_SINK pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); +#else + pa_tagstruct_putu32(t, PA_COMMAND_GET_RECORD_LATENCY); +#endif pa_tagstruct_putu32(t, tag = u->ctag++); pa_tagstruct_putu32(t, u->channel); @@ -286,7 +336,9 @@ static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, ui if (pa_tagstruct_getu32(t, &u->channel) < 0 || pa_tagstruct_getu32(t, &u->device_index) < 0 || +#ifdef TUNNEL_SINK pa_tagstruct_getu32(t, &u->requested_bytes) < 0 || +#endif !pa_tagstruct_eof(t)) { pa_log(__FILE__": invalid reply.\n"); die(u); @@ -294,7 +346,9 @@ static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, ui } request_latency(u); +#ifdef TUNNEL_SINK send_bytes(u); +#endif } static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { @@ -311,11 +365,17 @@ static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, u die(u); return; } - +#ifdef TUNNEL_SINK snprintf(name, sizeof(name), "Tunnel from host '%s', user '%s', sink '%s'", pa_get_host_name(hn, sizeof(hn)), pa_get_user_name(un, sizeof(un)), u->sink->name); +#else + snprintf(name, sizeof(name), "Tunnel from host '%s', user '%s', source '%s'", + pa_get_host_name(hn, sizeof(hn)), + pa_get_user_name(un, sizeof(un)), + u->source->name); +#endif reply = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME); @@ -325,6 +385,7 @@ static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, u /* We ignore the server's reply here */ reply = pa_tagstruct_new(NULL, 0); +#ifdef TUNNEL_SINK pa_tagstruct_putu32(reply, PA_COMMAND_CREATE_PLAYBACK_STREAM); pa_tagstruct_putu32(reply, tag = u->ctag++); pa_tagstruct_puts(reply, name); @@ -337,6 +398,17 @@ static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, u pa_tagstruct_putu32(reply, DEFAULT_PREBUF); pa_tagstruct_putu32(reply, DEFAULT_MINREQ); pa_tagstruct_putu32(reply, PA_VOLUME_NORM); +#else + pa_tagstruct_putu32(reply, PA_COMMAND_CREATE_RECORD_STREAM); + pa_tagstruct_putu32(reply, tag = u->ctag++); + pa_tagstruct_puts(reply, name); + pa_tagstruct_put_sample_spec(reply, &u->source->sample_spec); + pa_tagstruct_putu32(reply, PA_INVALID_INDEX); + pa_tagstruct_puts(reply, u->source_name); + pa_tagstruct_putu32(reply, DEFAULT_MAXLENGTH); + pa_tagstruct_put_boolean(reply, 0); + pa_tagstruct_putu32(reply, DEFAULT_FRAGSIZE); +#endif pa_pstream_send_tagstruct(u->pstream, reply); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u); @@ -361,6 +433,21 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack } } +#ifndef TUNNEL_SINK +static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata) { + struct userdata *u = userdata; + assert(p && chunk && u); + + if (channel != u->channel) { + pa_log(__FILE__": recieved memory block on bad channel.\n"); + die(u); + return; + } + + pa_source_post(u->source, chunk); +} +#endif + static void on_connection(struct pa_socket_client *sc, struct pa_iochannel *io, void *userdata) { struct userdata *u = userdata; struct pa_tagstruct *t; @@ -381,6 +468,9 @@ static void on_connection(struct pa_socket_client *sc, struct pa_iochannel *io, pa_pstream_set_die_callback(u->pstream, pstream_die_callback, u); pa_pstream_set_recieve_packet_callback(u->pstream, pstream_packet_callback, u); +#ifndef TUNNEL_SINK + pa_pstream_set_recieve_memblock_callback(u->pstream, pstream_memblock_callback, u); +#endif t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_AUTH); @@ -391,6 +481,7 @@ static void on_connection(struct pa_socket_client *sc, struct pa_iochannel *io, } +#ifdef TUNNEL_SINK static void sink_notify(struct pa_sink*sink) { struct userdata *u; assert(sink && sink->userdata); @@ -417,6 +508,15 @@ static pa_usec_t sink_get_latency(struct pa_sink *sink) { return usec; } +#else +static pa_usec_t source_get_latency(struct pa_source *source) { + struct userdata *u; + assert(source && source->userdata); + u = source->userdata; + + return u->host_latency; +} +#endif static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { struct userdata *u = userdata; @@ -449,11 +549,17 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->client = NULL; u->pdispatch = NULL; u->pstream = NULL; - u->server_name = u->sink_name = NULL; + u->server_name = NULL; +#ifdef TUNNEL_SINK + u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));; u->sink = NULL; + u->requested_bytes = 0; +#else + u->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));; + u->source = NULL; +#endif u->ctag = 1; u->device_index = u->channel = PA_INVALID_INDEX; - u->requested_bytes = 0; u->host_latency = 0; if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), u->auth_cookie, sizeof(u->auth_cookie)) < 0) { @@ -466,8 +572,6 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; } - u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); - ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { pa_log(__FILE__": invalid sample format specification\n"); @@ -493,7 +597,8 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; pa_socket_client_set_callback(u->client, on_connection, u); - + +#ifdef TUNNEL_SINK if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { pa_log(__FILE__": failed to create sink.\n"); goto fail; @@ -504,12 +609,24 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->sink->userdata = u; u->sink->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->sink_name ? u->sink_name : "", u->sink_name ? "@" : "", u->server_name); + pa_sink_set_owner(u->sink, m); +#else + if (!(u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) { + pa_log(__FILE__": failed to create source.\n"); + goto fail; + } + + u->source->get_latency = source_get_latency; + u->source->userdata = u; + u->source->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->source_name ? u->source_name : "", u->source_name ? "@" : "", u->server_name); + + pa_source_set_owner(u->source, m); +#endif + gettimeofday(&ntv, NULL); ntv.tv_sec += LATENCY_INTERVAL; u->time_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, u); - pa_sink_set_owner(u->sink, m); - pa_modargs_free(ma); return 0; @@ -531,7 +648,11 @@ void pa__done(struct pa_core *c, struct pa_module*m) { close_stuff(u); +#ifdef TUNNEL_SINK pa_xfree(u->sink_name); +#else + pa_xfree(u->source_name); +#endif pa_xfree(u->server_name); pa_xfree(u); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index aeccd504a..3b8164193 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -656,6 +656,7 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma struct pa_sample_spec ss; struct pa_tagstruct *reply; struct pa_source *source; + int corked; assert(c && t && c->protocol && c->protocol->core); if (pa_tagstruct_gets(t, &name) < 0 || !name || @@ -663,6 +664,7 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma pa_tagstruct_getu32(t, &source_index) < 0 || pa_tagstruct_gets(t, &source_name) < 0 || pa_tagstruct_getu32(t, &maxlength) < 0 || + pa_tagstruct_get_boolean(t, &corked) < 0 || pa_tagstruct_getu32(t, &fragment_size) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -688,6 +690,8 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); return; } + + pa_source_output_cork(s->source_output, corked); reply = pa_tagstruct_new(NULL, 0); assert(reply); diff --git a/polyp/source.c b/polyp/source.c index 23b8bf8ac..7df432d52 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -131,7 +131,7 @@ void pa_source_notify(struct pa_source*s) { } static int do_post(void *p, uint32_t index, int *del, void*userdata) { - struct pa_memchunk *chunk = userdata; + const struct pa_memchunk *chunk = userdata; struct pa_source_output *o = p; assert(o && o->push && del && chunk); @@ -139,7 +139,7 @@ static int do_post(void *p, uint32_t index, int *del, void*userdata) { return 0; } -void pa_source_post(struct pa_source*s, struct pa_memchunk *chunk) { +void pa_source_post(struct pa_source*s, const struct pa_memchunk *chunk) { assert(s && s->ref >= 1 && chunk); pa_source_ref(s); diff --git a/polyp/source.h b/polyp/source.h index cda9e6986..3cac2ad1f 100644 --- a/polyp/source.h +++ b/polyp/source.h @@ -63,7 +63,7 @@ void pa_source_unref(struct pa_source *s); struct pa_source* pa_source_ref(struct pa_source *c); /* Pass a new memory block to all output streams */ -void pa_source_post(struct pa_source*s, struct pa_memchunk *b); +void pa_source_post(struct pa_source*s, const struct pa_memchunk *b); void pa_source_notify(struct pa_source *s); From d09240118ce0170c2fc5f504589646746902eb96 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 29 Sep 2004 19:13:55 +0000 Subject: [PATCH 0244/1514] really fix API version API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@249 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 ++ doc/todo | 1 - polyp/pacat.c | 7 ++++--- polyp/pactl.c | 2 +- polyp/paplay.c | 2 +- polyp/polyplib-context.c | 9 +++++---- polyp/polyplib-version.h.in | 10 ++++++++++ 7 files changed, 23 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 3a0675c3f..af7668473 100644 --- a/configure.ac +++ b/configure.ac @@ -28,6 +28,8 @@ AM_INIT_AUTOMAKE([foreign -Wall]) AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) +AC_SUBST(PA_API_VERSION, 6) + if type -p stow > /dev/null && test -d /usr/local/stow ; then AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}" diff --git a/doc/todo b/doc/todo index 439eb770f..bef5b82ae 100644 --- a/doc/todo +++ b/doc/todo @@ -9,7 +9,6 @@ - improve module-oss-mmap latency measurement - pacat sample type args - filter capture data in client through alignment -- add tunnel module for sources - add radio module - make autoload list use idxset - libwrap diff --git a/polyp/pacat.c b/polyp/pacat.c index 1eb37d4da..67242b265 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -36,8 +36,9 @@ #include #include #include +#include -#if PA_API_VERSION != PA_API_VERSION_0_6 +#if PA_API_VERSION != 6 #error Invalid Polypaudio API version #endif @@ -107,7 +108,7 @@ static void stream_read_callback(struct pa_stream *s, const void*data, size_t le mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); if (buffer) { - fprintf(stderr, "Buffer overrrun, dropping incoming data\n"); + fprintf(stderr, "Buffer overrun, dropping incoming data\n"); return; } @@ -133,7 +134,7 @@ static void stream_state_callback(struct pa_stream *s, void *userdata) { case PA_STREAM_FAILED: default: - fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + fprintf(stderr, "Stream error: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); quit(1); } } diff --git a/polyp/pactl.c b/polyp/pactl.c index cf2f51c39..fbedc6fa8 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -41,7 +41,7 @@ #include #include -#if PA_API_VERSION != PA_API_VERSION_0_6 +#if PA_API_VERSION != 6 #error Invalid Polypaudio API version #endif diff --git a/polyp/paplay.c b/polyp/paplay.c index 89358a516..cc466e120 100644 --- a/polyp/paplay.c +++ b/polyp/paplay.c @@ -40,7 +40,7 @@ #include #include -#if PA_API_VERSION != PA_API_VERSION_0_6 +#if PA_API_VERSION != 6 #error Invalid Polypaudio API version #endif diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index d2fae0af9..b736daa7d 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -676,10 +676,6 @@ struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32 return pa_operation_ref(o); } -const char* pa_get_library_version(void) { - return PACKAGE_VERSION; -} - struct pa_operation* pa_context_set_default_sink(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata) { struct pa_tagstruct *t; struct pa_operation *o; @@ -744,3 +740,8 @@ struct pa_operation* pa_context_set_name(struct pa_context *c, const char *name, return pa_operation_ref(o); } + +const char* pa_get_library_version(void) { + return PACKAGE_VERSION; +} + diff --git a/polyp/polyplib-version.h.in b/polyp/polyplib-version.h.in index b44dc0088..75798693e 100644 --- a/polyp/polyplib-version.h.in +++ b/polyp/polyplib-version.h.in @@ -22,6 +22,8 @@ USA. ***/ +/* WARNING: Make sure to edit the real source file polyplib-version.h.in! */ + /** \file * Define header version */ @@ -30,4 +32,12 @@ a macro and not a function, so it is impossible to get the pointer of it. */ #define pa_get_headers_version() ("@PACKAGE_VERSION@") +/** Return the version of the library the current application is linked to. */ +const char* pa_get_library_version(void); + +/** The current API version. Version 6 relates to polypaudio + * 0.6. Prior versions (i.e. Polypaudio 0.5.1 and older) have + * PA_API_VERSION undefined. */ +#define PA_API_VERSION @PA_API_VERSION@ + #endif From 66999e5adaf54256718c638c3ad53acb0d74937b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 29 Sep 2004 20:13:05 +0000 Subject: [PATCH 0245/1514] Add support for libwrap git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@250 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 19 +++++++++++++++++++ doc/todo | 1 - polyp/Makefile.am | 2 +- polyp/authkey.c | 5 +++-- polyp/main.c | 11 +++++++++++ polyp/module-protocol-stub.c | 7 +++++-- polyp/socket-server.c | 31 +++++++++++++++++++++++++++++-- polyp/socket-server.h | 2 +- polyp/source.c | 2 +- 9 files changed, 70 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index af7668473..68df5b850 100644 --- a/configure.ac +++ b/configure.ac @@ -111,6 +111,25 @@ AC_SUBST(GLIB12_LIBS) AC_SUBST(HAVE_GLIB12) AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) +AC_MSG_CHECKING([for tcpwrap library and headers]) +LIBWRAP_LIBS= +saved_LIBS="$LIBS" +LIBS="$LIBS -lwrap" +AC_LINK_IFELSE( +AC_LANG_PROGRAM( +[#include +#include +int allow_severity = LOG_INFO; +int deny_severity = LOG_WARNING;], +[struct request_info *req; +return hosts_access (req);]), +[AC_DEFINE(HAVE_LIBWRAP, [], [Have tcpwrap?]) +LIBWRAP_LIBS="-lwrap" +AC_MSG_RESULT(yes)], +[AC_MSG_RESULT(no)]) +AC_SUBST(LIBWRAP_LIBS) +LIBS="$saved_LIBS" + # If using GCC specify some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -W -Wall -pedantic" diff --git a/doc/todo b/doc/todo index bef5b82ae..668f54d28 100644 --- a/doc/todo +++ b/doc/todo @@ -11,7 +11,6 @@ - filter capture data in client through alignment - add radio module - make autoload list use idxset -- libwrap ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 29b388c9a..94d3373cb 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -178,7 +178,7 @@ libprotocol_simple_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libsocket_server_la_SOURCES = socket-server.c socket-server.h libsocket_server_la_LDFLAGS = -avoid-version -libsocket_server_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la +libsocket_server_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) libsocket_client_la_SOURCES = socket-client.c socket-client.h libsocket_client_la_LDFLAGS = -avoid-version diff --git a/polyp/authkey.c b/polyp/authkey.c index c8d8576b9..09a2c1b40 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -147,7 +147,7 @@ int pa_authkey_load(const char *path, void *data, size_t length) { int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { char *home; char path[PATH_MAX]; - char *p; + const char *p; assert(fn && data && length); @@ -155,7 +155,8 @@ int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { if (!(home = getenv("HOME"))) return -2; - snprintf(p = path, sizeof(path), "%s/%s", home, fn); + snprintf(path, sizeof(path), "%s/%s", home, fn); + p = path; } else p = fn; diff --git a/polyp/main.c b/polyp/main.c index 0837e58df..25fb17413 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -34,6 +34,11 @@ #include #include +#ifdef HAVE_LIBWRAP +#include +#include +#endif + #include "core.h" #include "mainloop.h" #include "module.h" @@ -50,6 +55,12 @@ #include "caps.h" #include "cli-text.h" +#ifdef HAVE_LIBWRAP +/* Only one instance of these variables */ +int allow_severity = LOG_INFO; +int deny_severity = LOG_WARNING; +#endif + static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { pa_log(__FILE__": Got signal %s.\n", pa_strsignal(sig)); diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index fc1e9fd92..1ff70a1ae 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -54,16 +54,17 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #include "protocol-simple.h" #define protocol_new pa_protocol_simple_new #define protocol_free pa_protocol_simple_free + #define TCPWRAP_SERVICE "polypaudio-simple" #define IPV4_PORT 4711 #define UNIX_SOCKET "/tmp/polypaudio/simple" #define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record", PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("rate= format= channels= sink= source= playback= record= "SOCKET_USAGE) - #elif defined(USE_PROTOCOL_CLI) #include "protocol-cli.h" #define protocol_new pa_protocol_cli_new #define protocol_free pa_protocol_cli_free + #define TCPWRAP_SERVICE "polypaudio-cli" #define IPV4_PORT 4712 #define UNIX_SOCKET "/tmp/polypaudio/cli" #define MODULE_ARGUMENTS @@ -73,6 +74,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #include "protocol-native.h" #define protocol_new pa_protocol_native_new #define protocol_free pa_protocol_native_free + #define TCPWRAP_SERVICE "polypaudio-native" #define IPV4_PORT PA_NATIVE_DEFAULT_PORT #define UNIX_SOCKET "/tmp/polypaudio/native" #define MODULE_ARGUMENTS "public", "cookie", @@ -83,6 +85,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #include "esound.h" #define protocol_new pa_protocol_esound_new #define protocol_free pa_protocol_esound_free + #define TCPWRAP_SERVICE "esound" #define IPV4_PORT ESD_DEFAULT_PORT #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", @@ -119,7 +122,7 @@ static struct pa_socket_server *create_socket_server(struct pa_core *c, struct p return NULL; } - if (!(s = pa_socket_server_new_ipv4(c->mainloop, loopback ? INADDR_LOOPBACK : INADDR_ANY, port))) + if (!(s = pa_socket_server_new_ipv4(c->mainloop, loopback ? INADDR_LOOPBACK : INADDR_ANY, port, TCPWRAP_SERVICE))) return NULL; #else int r; diff --git a/polyp/socket-server.c b/polyp/socket-server.c index 9f943dc06..c170bf6ee 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -35,6 +35,10 @@ #include #include +#ifdef HAVE_LIBWRAP +#include +#endif + #include "socket-server.h" #include "socket-util.h" #include "xmalloc.h" @@ -45,6 +49,7 @@ struct pa_socket_server { int ref; int fd; char *filename; + char *tcpwrap_service; void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata); void *userdata; @@ -74,6 +79,23 @@ static void callback(struct pa_mainloop_api *mainloop, struct pa_io_event *e, in goto finish; } +#ifdef HAVE_LIBWRAP + + if (s->type == SOCKET_SERVER_IPV4 && s->tcpwrap_service) { + struct request_info req; + + request_init(&req, RQ_DAEMON, s->tcpwrap_service, RQ_FILE, nfd, NULL); + fromhost(&req); + if (!hosts_access(&req)) { + pa_log(__FILE__": TCP connection refused by tcpwrap.\n"); + close(nfd); + goto finish; + } + + pa_log(__FILE__": TCP connection accepted by tcpwrap.\n"); + } +#endif + /* There should be a check for socket type here */ if (s->type == SOCKET_SERVER_IPV4) pa_socket_tcp_low_delay(fd); @@ -98,6 +120,7 @@ struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) s->filename = NULL; s->on_connection = NULL; s->userdata = NULL; + s->tcpwrap_service = NULL; s->mainloop = m; s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s); @@ -159,7 +182,7 @@ fail: return NULL; } -struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port) { +struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service) { struct pa_socket_server *ss; int fd = -1; struct sockaddr_in sa; @@ -193,8 +216,10 @@ struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, ui goto fail; } - if ((ss = pa_socket_server_new(m, fd))) + if ((ss = pa_socket_server_new(m, fd))) { ss->type = SOCKET_SERVER_IPV4; + ss->tcpwrap_service = pa_xstrdup(tcpwrap_service); + } return ss; @@ -214,6 +239,8 @@ static void socket_server_free(struct pa_socket_server*s) { pa_xfree(s->filename); } + pa_xfree(s->tcpwrap_service); + s->mainloop->io_free(s->io_event); pa_xfree(s); } diff --git a/polyp/socket-server.h b/polyp/socket-server.h index c9d9193d3..f5877e557 100644 --- a/polyp/socket-server.h +++ b/polyp/socket-server.h @@ -32,7 +32,7 @@ struct pa_socket_server; struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd); struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename); -struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); +struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service); void pa_socket_server_unref(struct pa_socket_server*s); struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *s); diff --git a/polyp/source.c b/polyp/source.c index 7df432d52..73645d494 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -143,7 +143,7 @@ void pa_source_post(struct pa_source*s, const struct pa_memchunk *chunk) { assert(s && s->ref >= 1 && chunk); pa_source_ref(s); - pa_idxset_foreach(s->outputs, do_post, chunk); + pa_idxset_foreach(s->outputs, do_post, (void*) chunk); pa_source_unref(s); } From 68d50dc0a6cf6886d0d6e01447bf15f3411c739f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 29 Sep 2004 22:04:44 +0000 Subject: [PATCH 0246/1514] add sample spec parameters to pacat git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@251 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - polyp/modargs.c | 23 ++------------------- polyp/pacat.c | 53 +++++++++++++++++++++++++++++++++++++++---------- polyp/sample.c | 29 +++++++++++++++++++++++++-- polyp/sample.h | 6 +++++- 5 files changed, 76 insertions(+), 36 deletions(-) diff --git a/doc/todo b/doc/todo index 668f54d28..e2cb2fe63 100644 --- a/doc/todo +++ b/doc/todo @@ -7,7 +7,6 @@ - make mcalign merge chunks - option to use default fragment size on alsa drivers - improve module-oss-mmap latency measurement -- pacat sample type args - filter capture data in client through alignment - add radio module - make autoload list use idxset diff --git a/polyp/modargs.c b/polyp/modargs.c index e1c2c9b8a..d58b391b1 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -263,28 +263,9 @@ int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss return -1; ss.channels = (uint8_t) channels; - if ((format = pa_modargs_get_value(ma, "format", NULL))) { - if (strcmp(format, "s16le") == 0) - ss.format = PA_SAMPLE_S16LE; - else if (strcmp(format, "s16be") == 0) - ss.format = PA_SAMPLE_S16BE; - else if (strcmp(format, "s16ne") == 0 || strcmp(format, "s16") == 0 || strcmp(format, "16") == 0) - ss.format = PA_SAMPLE_S16NE; - else if (strcmp(format, "u8") == 0 || strcmp(format, "8") == 0) - ss.format = PA_SAMPLE_U8; - else if (strcmp(format, "float32") == 0 || strcmp(format, "float32ne") == 0) - ss.format = PA_SAMPLE_FLOAT32; - else if (strcmp(format, "float32le") == 0) - ss.format = PA_SAMPLE_FLOAT32LE; - else if (strcmp(format, "float32be") == 0) - ss.format = PA_SAMPLE_FLOAT32BE; - else if (strcmp(format, "ulaw") == 0) - ss.format = PA_SAMPLE_ULAW; - else if (strcmp(format, "alaw") == 0) - ss.format = PA_SAMPLE_ALAW; - else + if ((format = pa_modargs_get_value(ma, "format", NULL))) + if ((ss.format = pa_parse_sample_format(format)) < 0) return -1; - } if (!pa_sample_spec_valid(&ss)) return -1; diff --git a/polyp/pacat.c b/polyp/pacat.c index 67242b265..a2687116c 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -58,6 +58,12 @@ static char *stream_name = NULL, *client_name = NULL, *device = NULL; static int verbose = 0; static pa_volume_t volume = PA_VOLUME_NORM; +static struct pa_sample_spec sample_spec = { + .format = PA_SAMPLE_S16LE, + .rate = 44100, + .channels = 2 +}; + /* A shortcut for terminating the application */ static void quit(int ret) { assert(mainloop_api); @@ -141,12 +147,6 @@ static void stream_state_callback(struct pa_stream *s, void *userdata) { /* This is called whenever the context status changes */ static void context_state_callback(struct pa_context *c, void *userdata) { - static const struct pa_sample_spec ss = { - .format = PA_SAMPLE_S16LE, - .rate = 44100, - .channels = 2 - }; - assert(c); switch (pa_context_get_state(c)) { @@ -162,7 +162,7 @@ static void context_state_callback(struct pa_context *c, void *userdata) { if (verbose) fprintf(stderr, "Connection established.\n"); - stream = pa_stream_new(c, stream_name, &ss); + stream = pa_stream_new(c, stream_name, &sample_spec); assert(stream); pa_stream_set_state_callback(stream, stream_state_callback, NULL); @@ -335,14 +335,22 @@ static void help(const char *argv0) { " -d, --device=DEVICE The name of the sink/source to connect to\n" " -n, --client-name=NAME How to call this client on the server\n" " --stream-name=NAME How to call this stream on the server\n" - " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n", + " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n" + " --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n" + " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" + " float32be, ulaw, alaw (defaults to s16ne)\n" + " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" + " (defaults to 2)\n", argv0); } enum { ARG_VERSION = 256, ARG_STREAM_NAME, - ARG_VOLUME + ARG_VOLUME, + ARG_SAMPLERATE, + ARG_SAMPLEFORMAT, + ARG_CHANNELS }; int main(int argc, char *argv[]) { @@ -361,6 +369,9 @@ int main(int argc, char *argv[]) { {"help", 0, NULL, 'h'}, {"verbose", 0, NULL, 'v'}, {"volume", 1, NULL, ARG_VOLUME}, + {"rate", 1, NULL, ARG_SAMPLERATE}, + {"format", 1, NULL, ARG_SAMPLEFORMAT}, + {"channels", 1, NULL, ARG_CHANNELS}, {NULL, 0, NULL, 0} }; @@ -425,6 +436,18 @@ int main(int argc, char *argv[]) { break; } + case ARG_CHANNELS: + sample_spec.channels = atoi(optarg); + break; + + case ARG_SAMPLEFORMAT: + sample_spec.format = pa_parse_sample_format(optarg); + break; + + case ARG_SAMPLERATE: + sample_spec.rate = atoi(optarg); + break; + default: goto quit; } @@ -435,9 +458,17 @@ int main(int argc, char *argv[]) { if (!stream_name) stream_name = strdup(client_name); + + if (!pa_sample_spec_valid(&sample_spec)) { + fprintf(stderr, "Invalid sample specification\n"); + goto quit; + } - if (verbose) - fprintf(stderr, "Opening a %s stream.\n", mode == RECORD ? "recording" : "playback"); + if (verbose) { + char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; + pa_sample_spec_snprint(t, sizeof(t), &sample_spec); + fprintf(stderr, "Opening a %s stream with sample specification '%s'.\n", mode == RECORD ? "recording" : "playback", t); + } /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { diff --git a/polyp/sample.c b/polyp/sample.c index 65ae8ff38..8c30386bb 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "sample.h" @@ -68,10 +69,10 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const struct pa_sample_spec *spec) { int pa_sample_spec_valid(const struct pa_sample_spec *spec) { assert(spec); - if (!spec->rate || !spec->channels) + if (spec->rate <= 0 || spec->channels <= 0) return 0; - if (spec->format >= PA_SAMPLE_MAX) + if (spec->format >= PA_SAMPLE_MAX || spec->format < 0) return 0; return 1; @@ -134,3 +135,27 @@ void pa_bytes_snprint(char *s, size_t l, unsigned v) { else snprintf(s, l, "%u B", (unsigned) v); } + +enum pa_sample_format pa_parse_sample_format(const char *format) { + + if (strcmp(format, "s16le") == 0) + return PA_SAMPLE_S16LE; + else if (strcmp(format, "s16be") == 0) + return PA_SAMPLE_S16BE; + else if (strcmp(format, "s16ne") == 0 || strcmp(format, "s16") == 0 || strcmp(format, "16") == 0) + return PA_SAMPLE_S16NE; + else if (strcmp(format, "u8") == 0 || strcmp(format, "8") == 0) + return PA_SAMPLE_U8; + else if (strcmp(format, "float32") == 0 || strcmp(format, "float32ne") == 0) + return PA_SAMPLE_FLOAT32; + else if (strcmp(format, "float32le") == 0) + return PA_SAMPLE_FLOAT32LE; + else if (strcmp(format, "float32be") == 0) + return PA_SAMPLE_FLOAT32BE; + else if (strcmp(format, "ulaw") == 0) + return PA_SAMPLE_ULAW; + else if (strcmp(format, "alaw") == 0) + return PA_SAMPLE_ALAW; + + return -1; +} diff --git a/polyp/sample.h b/polyp/sample.h index 912cdaa0f..7e810386d 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -42,7 +42,8 @@ enum pa_sample_format { PA_SAMPLE_S16BE, /**< Signed 16 Bit PCM, big endian */ PA_SAMPLE_FLOAT32LE, /**< 32 Bit IEEE floating point, little endian, range -1..1 */ PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1..1 */ - PA_SAMPLE_MAX /**< Upper limit of valid sample types */ + PA_SAMPLE_MAX, /**< Upper limit of valid sample types */ + PA_SAMPLE_INVALID = -1 /**< An invalid value */ }; #ifdef WORDS_BIGENDIAN @@ -119,6 +120,9 @@ double pa_volume_to_dB(pa_volume_t v); /** Pretty print a byte size value. (i.e. "2.5 MB") */ void pa_bytes_snprint(char *s, size_t l, unsigned v); +/** Parse a sample format text */ +enum pa_sample_format pa_parse_sample_format(const char *format); + PA_C_DECL_END #endif From fde3d1333738c807ef5e43161565590b1f715077 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 1 Oct 2004 12:48:09 +0000 Subject: [PATCH 0247/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@252 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index e2cb2fe63..4526adab2 100644 --- a/doc/todo +++ b/doc/todo @@ -10,6 +10,7 @@ - filter capture data in client through alignment - add radio module - make autoload list use idxset +- enlarge mqmblockq sizes ** later *** - xmlrpc/http From 6ede161cb94f5123e103fae45ea1918bbebb4956 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 11 Oct 2004 16:21:12 +0000 Subject: [PATCH 0248/1514] enlarge default buffers git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@253 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 58c617e45..8a7bf6fbc 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -35,7 +35,7 @@ #include "native-common.h" #include "client-conf.h" -#define DEFAULT_TLENGTH (44100*2*2/10) //(10240*8) +#define DEFAULT_TLENGTH (44100*2*2/2) //(10240*8) #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) #define DEFAULT_MINREQ 512 #define DEFAULT_PREBUF (DEFAULT_TLENGTH-DEFAULT_MINREQ) From a6471e26022a7eada70dd128c51f0fa593718c5d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 12 Oct 2004 21:52:50 +0000 Subject: [PATCH 0249/1514] gcc 2.95 fix default.pa fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@254 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/authkey.c | 2 +- polyp/default.pa.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/polyp/authkey.c b/polyp/authkey.c index 09a2c1b40..d3cb382be 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -85,9 +85,9 @@ finish: static int load(const char *fn, void *data, size_t length) { int fd = -1; int writable = 1; - assert(fn && data && length); int unlock = 0, ret; ssize_t r; + assert(fn && data && length); if ((fd = open(fn, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { if (errno != EACCES || (fd = open(fn, O_RDONLY)) < 0) { diff --git a/polyp/default.pa.in b/polyp/default.pa.in index 54feb5ef7..97b209639 100755 --- a/polyp/default.pa.in +++ b/polyp/default.pa.in @@ -52,7 +52,7 @@ set-default-source input .nofail # Load something to the sample cache -load-sample /usr/share/sounds/KDE_Notify.wav x11-bell +load-sample x11-bell /usr/share/sounds/KDE_Notify.wav # Load X11 bell module load-module module-x11-bell sample=x11-bell sink=output From da45617efc5e3be26d6410857a730c94b32fe24b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 24 Oct 2004 00:48:02 +0000 Subject: [PATCH 0250/1514] add user volume API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@255 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 ++- polyp/Makefile.am | 6 +++++- polyp/polyplib-version.h.in | 4 ++++ polyp/sample.c | 16 ++++++++++++++++ polyp/sample.h | 6 ++++++ polyp/voltest.c | 12 ++++++++++++ 6 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 polyp/voltest.c diff --git a/doc/todo b/doc/todo index 4526adab2..fde49d669 100644 --- a/doc/todo +++ b/doc/todo @@ -1,6 +1,7 @@ *** $Id$ *** *** 0.6 **** +- latency interpolation - per-channel volume - unix socket directories include user name - add sample directory @@ -22,7 +23,7 @@ backends for: - portaudio (semi-done) +- gstreamer (semi-done) - alsa-lib - sdl -- gstreamer (semi-done) - OSS (esddsp style) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 94d3373cb..10e1c6cb7 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -33,7 +33,7 @@ AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in -bin_PROGRAMS = polypaudio pacat pactl paplay +bin_PROGRAMS = polypaudio pacat pactl paplay voltest bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ mainloop-test \ @@ -408,6 +408,10 @@ mainloop_test_SOURCES = mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-@PA_MAJORMINOR@.la +voltest_SOURCES = voltest.c sample.c +voltest_CFLAGS = $(AM_CFLAGS) +voltest_LDADD = $(AM_LDADD) + cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit_test_CFLAGS = $(AM_CFLAGS) cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la diff --git a/polyp/polyplib-version.h.in b/polyp/polyplib-version.h.in index 75798693e..c2442b520 100644 --- a/polyp/polyplib-version.h.in +++ b/polyp/polyplib-version.h.in @@ -27,6 +27,8 @@ /** \file * Define header version */ +PA_C_DECL_BEGIN + /** Return the version of the header files. Keep in mind that this is a macro and not a function, so it is impossible to get the pointer of it. */ @@ -40,4 +42,6 @@ const char* pa_get_library_version(void); * PA_API_VERSION undefined. */ #define PA_API_VERSION @PA_API_VERSION@ +PA_C_DECL_END + #endif diff --git a/polyp/sample.c b/polyp/sample.c index 8c30386bb..7048311c0 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -125,6 +125,22 @@ double pa_volume_to_dB(pa_volume_t v) { return 20*log10((double) v/PA_VOLUME_NORM); } +#define USER_DECIBEL_RANGE 30 + +double pa_volume_to_user(pa_volume_t v) { + double dB = pa_volume_to_dB(v); + + return dB < -USER_DECIBEL_RANGE ? 0 : dB/USER_DECIBEL_RANGE+1; +} + +pa_volume_t pa_volume_from_user(double v) { + + if (v <= 0) + return PA_VOLUME_MUTED; + + return pa_volume_from_dB((v-1)*USER_DECIBEL_RANGE); +} + void pa_bytes_snprint(char *s, size_t l, unsigned v) { if (v >= ((unsigned) 1024)*1024*1024) snprintf(s, l, "%0.1f GB", ((double) v)/1024/1024/1024); diff --git a/polyp/sample.h b/polyp/sample.h index 7e810386d..4ab0b5657 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -110,6 +110,12 @@ pa_volume_t pa_volume_from_dB(double f); /** Convert volume from linear level to decibel. \since 0.4 */ double pa_volume_to_dB(pa_volume_t v); +/** Convert volume to scaled value understandable by the user (between 0 and 1). \since 0.6 */ +double pa_volume_to_user(pa_volume_t v); + +/** Convert user volume to polypaudio volume. \since 0.6 */ +pa_volume_t pa_volume_from_user(double v); + #ifdef INFINITY #define PA_DECIBEL_MININFTY (-INFINITY) #else diff --git a/polyp/voltest.c b/polyp/voltest.c new file mode 100644 index 000000000..a06d4ca2c --- /dev/null +++ b/polyp/voltest.c @@ -0,0 +1,12 @@ +#include + +#include + +int main() { + int p; + for (p = 0; p <= 200; p++) { + pa_volume_t v = pa_volume_from_user((double) p/100); + double dB = pa_volume_to_dB(v); + printf("%3i%% = %u = %0.2f dB = %u = %3i%%\n", p, v, dB, pa_volume_from_dB(dB), (int) (pa_volume_to_user(v)*100)); + } +} From 148202d432cbb4a303b0008b9ff9d64bdab99a51 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Oct 2004 00:10:12 +0000 Subject: [PATCH 0251/1514] support for latency interpolation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@256 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 5 +- polyp/pacat.c | 12 +-- polyp/polyplib-def.h | 18 +++- polyp/polyplib-internal.h | 12 +++ polyp/polyplib-simple.c | 2 +- polyp/polyplib-stream.c | 211 +++++++++++++++++++++++++++++--------- polyp/polyplib-stream.h | 18 +++- polyp/protocol-native.c | 6 ++ polyp/sample.h | 4 +- polyp/tagstruct.c | 24 +++++ polyp/tagstruct.h | 6 +- polyp/util.c | 2 +- polyp/util.h | 2 +- 13 files changed, 250 insertions(+), 72 deletions(-) diff --git a/doc/todo b/doc/todo index fde49d669..df710ecf4 100644 --- a/doc/todo +++ b/doc/todo @@ -1,7 +1,6 @@ *** $Id$ *** *** 0.6 **** -- latency interpolation - per-channel volume - unix socket directories include user name - add sample directory @@ -11,7 +10,9 @@ - filter capture data in client through alignment - add radio module - make autoload list use idxset -- enlarge mqmblockq sizes +- enlarge memblockq sizes +- add null-sink +- add sync API ** later *** - xmlrpc/http diff --git a/polyp/pacat.c b/polyp/pacat.c index a2687116c..a37f5dda9 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -297,7 +297,8 @@ static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_even /* Show the current latency */ static void stream_get_latency_callback(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) { - double total; + pa_usec_t total; + int negative = 0; assert(s); if (!i) { @@ -306,20 +307,17 @@ static void stream_get_latency_callback(struct pa_stream *s, const struct pa_lat return; } - if (mode == PLAYBACK) - total = (double) i->sink_usec + i->buffer_usec + i->transport_usec; - else - total = (double) i->source_usec + i->buffer_usec + i->transport_usec - i->sink_usec; + total = pa_stream_get_latency(s, i, &negative); fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; source: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n", - (float) i->buffer_usec, (float) i->sink_usec, (float) i->source_usec, (float) i->transport_usec, total, + (float) i->buffer_usec, (float) i->sink_usec, (float) i->source_usec, (float) i->transport_usec, (float) total * (negative?-1:1), i->synchronized_clocks ? "yes" : "no"); } /* Someone requested that the latency is shown */ static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); - pa_operation_unref(pa_stream_get_latency(stream, stream_get_latency_callback, NULL)); + pa_operation_unref(pa_stream_get_latency_info(stream, stream_get_latency_callback, NULL)); } diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index cd0662dda..ffa441883 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -74,7 +74,22 @@ enum pa_stream_direction { /** Some special flags for stream connections. \since 0.6 */ enum pa_stream_flags { - PA_STREAM_START_CORKED = 1, /**< Create the stream corked, requiring an explicit pa_stream_cork() call to uncork it. */ + PA_STREAM_START_CORKED = 1, /**< Create the stream corked, requiring an explicit pa_stream_cork() call to uncork it. */ + PA_STREAM_INTERPOLATE_LATENCY = 2 /**< Interpolate the latency for + * this stream. When enabled, + * you can use + * pa_stream_interpolated_xxx() + * for synchronization. Using + * these functions instead of + * pa_stream_get_latency() has + * the advantage of not + * requiring a whole roundtrip + * for responses. Consider using + * this option when frequently + * requesting latency + * information. This is + * especially useful on long latency + * network connections. */ }; /** Playback and record buffer metrics */ @@ -171,6 +186,7 @@ struct pa_latency_info { * limited und unreliable itself. \since * 0.5 */ struct timeval timestamp; /**< The time when this latency info was current */ + uint64_t counter; /**< The byte counter current when the latency info was requested. \since 0.6 */ }; /** A structure for the spawn api. This may be used to integrate auto diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 8a7bf6fbc..e49b25d40 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -81,6 +81,7 @@ struct pa_context { struct pa_stream { int ref; struct pa_context *context; + struct pa_mainloop_api *mainloop; PA_LLIST_FIELDS(struct pa_stream); char *name; @@ -95,6 +96,13 @@ struct pa_stream { pa_usec_t previous_time; enum pa_stream_state state; + int interpolate; + int corked; + + uint32_t ipol_usec; + struct timeval ipol_timestamp; + struct pa_time_event *ipol_event; + void (*state_callback)(struct pa_stream*c, void *userdata); void *state_userdata; @@ -103,6 +111,7 @@ struct pa_stream { void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); void *write_userdata; + }; struct pa_operation { @@ -135,4 +144,7 @@ struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32 void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st); +void pa_stream_trash_ipol(struct pa_stream *s); + + #endif diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index 9e111e2a1..0e180af04 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -341,7 +341,7 @@ pa_usec_t pa_simple_get_playback_latency(struct pa_simple *p, int *perror) { } p->latency = 0; - o = pa_stream_get_latency(p->stream, latency_complete, p); + o = pa_stream_get_latency_info(p->stream, latency_complete, p); while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 291c3cd39..68035b0fe 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -26,12 +26,15 @@ #include #include #include +#include #include "polyplib-internal.h" #include "xmalloc.h" #include "pstream-util.h" #include "util.h" +#define LATENCY_IPOL_INTERVAL_USEC (100000L) + struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss) { struct pa_stream *s; assert(c && ss); @@ -39,6 +42,7 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st s = pa_xmalloc(sizeof(struct pa_stream)); s->ref = 1; s->context = c; + s->mainloop = c->mainloop; s->read_callback = NULL; s->read_userdata = NULL; @@ -60,6 +64,13 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st s->counter = 0; s->previous_time = 0; + s->corked = 0; + s->interpolate = 0; + + s->ipol_usec = 0; + memset(&s->ipol_timestamp, 0, sizeof(s->ipol_timestamp)); + s->ipol_event = NULL; + PA_LLIST_PREPEND(struct pa_stream, c->streams, s); return pa_stream_ref(s); @@ -67,6 +78,12 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st static void stream_free(struct pa_stream *s) { assert(s); + + if (s->ipol_event) { + assert(s->mainloop); + s->mainloop->time_free(s->ipol_event); + } + pa_xfree(s->name); pa_xfree(s); } @@ -181,6 +198,22 @@ finish: pa_context_unref(c); } +static void ipol_callback(struct pa_mainloop_api *m, struct pa_time_event *e, const struct timeval *tv, void *userdata) { + struct timeval tv2; + struct pa_stream *s = userdata; + + pa_stream_ref(s); + pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + + gettimeofday(&tv2, NULL); + tv2.tv_usec += LATENCY_IPOL_INTERVAL_USEC; + + m->time_restart(e, &tv2); + + pa_stream_unref(s); +} + + void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_stream *s = userdata; assert(pd && s && s->state == PA_STREAM_CREATING); @@ -207,6 +240,17 @@ void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32 pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); pa_stream_set_state(s, PA_STREAM_READY); + if (s->interpolate) { + struct timeval tv; + pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + + gettimeofday(&tv, NULL); + tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */ + + assert(!s->ipol_event); + s->ipol_event = s->mainloop->time_new(s->mainloop, &tv, &ipol_callback, s); + } + if (s->requested_bytes && s->ref > 1 && s->write_callback) s->write_callback(s, s->requested_bytes, s->write_userdata); @@ -221,6 +265,9 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ pa_stream_ref(s); + s->interpolate = !!(flags & PA_STREAM_INTERPOLATE_LATENCY); + pa_stream_trash_ipol(s); + if (attr) s->buffer_attr = *attr; else { @@ -330,7 +377,7 @@ struct pa_operation * pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa return pa_operation_ref(o); } -static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct pa_operation *o = userdata; struct pa_latency_info i, *p = NULL; struct timeval local, remote, now; @@ -347,32 +394,39 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman pa_tagstruct_getu32(t, &i.queue_length) < 0 || pa_tagstruct_get_timeval(t, &local) < 0 || pa_tagstruct_get_timeval(t, &remote) < 0 || + pa_tagstruct_getu64(t, &i.counter) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; - } else - p = &i; - - gettimeofday(&now, NULL); - - if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) { - /* local and remote seem to have synchronized clocks */ - - if (o->stream->direction == PA_STREAM_PLAYBACK) - i.transport_usec = pa_timeval_diff(&remote, &local); - else - i.transport_usec = pa_timeval_diff(&now, &remote); - - i.synchronized_clocks = 1; - i.timestamp = remote; } else { - /* clocks are not synchronized, let's estimate latency then */ - i.transport_usec = pa_timeval_diff(&now, &local)/2; - i.synchronized_clocks = 0; - i.timestamp = local; - pa_timeval_add(&i.timestamp, i.transport_usec); - } + gettimeofday(&now, NULL); + + if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) { + /* local and remote seem to have synchronized clocks */ + + if (o->stream->direction == PA_STREAM_PLAYBACK) + i.transport_usec = pa_timeval_diff(&remote, &local); + else + i.transport_usec = pa_timeval_diff(&now, &remote); + + i.synchronized_clocks = 1; + i.timestamp = remote; + } else { + /* clocks are not synchronized, let's estimate latency then */ + i.transport_usec = pa_timeval_diff(&now, &local)/2; + i.synchronized_clocks = 0; + i.timestamp = local; + pa_timeval_add(&i.timestamp, i.transport_usec); + } + + if (o->stream->interpolate) { + o->stream->ipol_timestamp = now; + o->stream->ipol_usec = pa_stream_get_time(o->stream, &i); + } + p = &i; + } + if (o->callback) { void (*cb)(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) = o->callback; cb(o->stream, p, o->userdata); @@ -383,7 +437,7 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struct pa_stream *p, const struct pa_latency_info*i, void *userdata), void *userdata) { +struct pa_operation* pa_stream_get_latency_info(struct pa_stream *s, void (*cb)(struct pa_stream *p, const struct pa_latency_info*i, void *userdata), void *userdata) { uint32_t tag; struct pa_operation *o; struct pa_tagstruct *t; @@ -403,9 +457,10 @@ struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struc gettimeofday(&now, NULL); pa_tagstruct_put_timeval(t, &now); + pa_tagstruct_putu64(t, s->counter); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, o); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_info_callback, o); return pa_operation_ref(o); } @@ -505,6 +560,13 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); + if (!s->corked && b) + s->ipol_usec = pa_stream_get_interpolated_time(s); + else if (s->corked && !b) + gettimeofday(&s->ipol_timestamp, NULL); + + s->corked = b; + o = pa_operation_new(s->context, s); assert(o); o->callback = cb; @@ -519,6 +581,8 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); + pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + return pa_operation_ref(o); } @@ -543,15 +607,24 @@ struct pa_operation* pa_stream_send_simple_command(struct pa_stream *s, uint32_t } struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { - return pa_stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata); + struct pa_operation *o; + o = pa_stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata); + pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + return o; } struct pa_operation* pa_stream_prebuf(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { - return pa_stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata); + struct pa_operation *o; + o = pa_stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata); + pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + return o; } struct pa_operation* pa_stream_trigger(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { - return pa_stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata); + struct pa_operation *o; + o = pa_stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata); + pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + return o; } struct pa_operation* pa_stream_set_name(struct pa_stream *s, const char *name, void(*cb)(struct pa_stream*c, int success, void *userdata), void *userdata) { @@ -582,12 +655,6 @@ uint64_t pa_stream_get_counter(struct pa_stream *s) { return s->counter; } -void pa_stream_reset_counter(struct pa_stream *s) { - assert(s); - s->counter = 0; - s->previous_time = 0; -} - pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info *i) { pa_usec_t usec; assert(s); @@ -620,27 +687,22 @@ pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info * return usec; } -pa_usec_t pa_stream_get_total_latency(struct pa_stream *s, const struct pa_latency_info *i, int *negative) { +pa_usec_t pa_stream_get_latency(struct pa_stream *s, const struct pa_latency_info *i, int *negative) { + pa_usec_t t, c; assert(s && i); - if (s->direction == PA_STREAM_PLAYBACK) { + t = pa_stream_get_time(s, i); + c = pa_bytes_to_usec(s->counter, &s->sample_spec); + + if (t <= c) { + if (negative) + *negative = 1; + + return c-t; + } else { if (negative) *negative = 0; - - return i->transport_usec + i->buffer_usec + i->sink_usec; - } else if (s->direction == PA_STREAM_RECORD) { - pa_usec_t usec = i->source_usec + i->buffer_usec + i->transport_usec; - - if (usec >= i->sink_usec) { - if (negative) - *negative = 0; - return usec - i->sink_usec; - } else { - if (negative) - *negative = 1; - - return i->sink_usec - usec; - } + return t-c; } return 0; @@ -650,3 +712,52 @@ const struct pa_sample_spec* pa_stream_get_sample_spec(struct pa_stream *s) { assert(s); return &s->sample_spec; } + +void pa_stream_trash_ipol(struct pa_stream *s) { + assert(s); + + if (!s->interpolate) + return; + + memset(&s->ipol_timestamp, 0, sizeof(s->ipol_timestamp)); + s->ipol_usec = 0; +} + +pa_usec_t pa_stream_get_interpolated_time(struct pa_stream *s) { + pa_usec_t usec; + assert(s && s->interpolate); + + if (s->corked) + usec = s->ipol_usec; + else { + if (s->ipol_timestamp.tv_sec == 0) + usec = 0; + else + usec = s->ipol_usec + pa_timeval_age(&s->ipol_timestamp); + } + + if (usec < s->previous_time) + usec = s->previous_time; + + s->previous_time = usec; + return usec; +} + +pa_usec_t pa_stream_get_interpolated_latency(struct pa_stream *s, int *negative) { + pa_usec_t t, c; + assert(s && s->interpolate); + + t = pa_stream_get_interpolated_time(s); + c = pa_bytes_to_usec(s->counter, &s->sample_spec); + + if (t <= c) { + if (negative) + *negative = 1; + + return c-t; + } else { + if (negative) + *negative = 0; + return t-c; + } +} diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index e095d7fa0..4ccc0c238 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -102,7 +102,7 @@ size_t pa_stream_writable_size(struct pa_stream *p); struct pa_operation* pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); /** Get the playback latency of a stream */ -struct pa_operation* pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, const struct pa_latency_info *i, void *userdata), void *userdata); +struct pa_operation* pa_stream_get_latency_info(struct pa_stream *p, void (*cb)(struct pa_stream *p, const struct pa_latency_info *i, void *userdata), void *userdata); /** Set the callback function that is called whenever the state of the stream changes */ void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); @@ -138,9 +138,6 @@ struct pa_operation* pa_stream_set_name(struct pa_stream *s, const char *name, v * this yourself using pa_stream_reset_counter(). \since 0.6 */ uint64_t pa_stream_get_counter(struct pa_stream *s); -/** Reset the total byte count to 0. \since 0.6 */ -void pa_stream_reset_counter(struct pa_stream *s); - /** Return the current playback/recording time. This is based on the * counter accessible with pa_stream_get_counter(). This function * requires a pa_latency_info structure as argument, which should be @@ -152,7 +149,18 @@ pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info * * using pa_stream_get_latency(). In case the stream is a monitoring * stream the result can be negative, i.e. the captured samples are * not yet played. In this case *negative is set to 1. \since 0.6 */ -pa_usec_t pa_stream_get_total_latency(struct pa_stream *s, const struct pa_latency_info *i, int *negative); +pa_usec_t pa_stream_get_latency(struct pa_stream *s, const struct pa_latency_info *i, int *negative); + +/** Return the interpolated playback/recording time. Requires the + * PA_STREAM_INTERPOLATE_LATENCY bit set when creating the stream. In + * contrast to pa_stream_get_latency() this function doesn't require + * a whole roundtrip for response. \since 0.6 */ +pa_usec_t pa_stream_get_interpolated_time(struct pa_stream *s); + +/** Return the interpolated playback/recording latency. Requires the + * PA_STREAM_INTERPOLATE_LATENCY bit set when creating the + * stream. \since 0.6 */ +pa_usec_t pa_stream_get_interpolated_latency(struct pa_stream *s, int *negative); /** Return a pointer to the streams sample specification. \since 0.6 */ const struct pa_sample_spec* pa_stream_get_sample_spec(struct pa_stream *s); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 3b8164193..31ab4ab8c 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -875,11 +875,13 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma struct pa_tagstruct *reply; struct playback_stream *s; struct timeval tv, now; + uint64_t counter; uint32_t index; assert(c && t); if (pa_tagstruct_getu32(t, &index) < 0 || pa_tagstruct_get_timeval(t, &tv) < 0 || + pa_tagstruct_getu64(t, &counter) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -907,6 +909,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma pa_tagstruct_put_timeval(reply, &tv); gettimeofday(&now, NULL); pa_tagstruct_put_timeval(reply, &now); + pa_tagstruct_putu64(reply, counter); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -915,11 +918,13 @@ static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command struct pa_tagstruct *reply; struct record_stream *s; struct timeval tv, now; + uint64_t counter; uint32_t index; assert(c && t); if (pa_tagstruct_getu32(t, &index) < 0 || pa_tagstruct_get_timeval(t, &tv) < 0 || + pa_tagstruct_getu64(t, &counter) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -947,6 +952,7 @@ static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command pa_tagstruct_put_timeval(reply, &tv); gettimeofday(&now, NULL); pa_tagstruct_put_timeval(reply, &now); + pa_tagstruct_putu64(reply, counter); pa_pstream_send_tagstruct(c->pstream, reply); } diff --git a/polyp/sample.h b/polyp/sample.h index 4ab0b5657..a02a50fec 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -68,10 +68,10 @@ struct pa_sample_spec { uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */ }; -/** Type for usec specifications. May be either 32 or 64 bit, depending on the architecture */ +/** Type for usec specifications (unsigned). May be either 32 or 64 bit, depending on the architecture */ typedef uint64_t pa_usec_t; -/** Return the amount of bytes playback of a second of audio with the speicified sample type takes */ +/** Return the amount of bytes playback of a second of audio with the specified sample type takes */ size_t pa_bytes_per_second(const struct pa_sample_spec *spec); /** Return the size of a frame with the specific sample type */ diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index bbebdab34..b9ab55f0c 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -176,6 +176,15 @@ void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) { t->length += 9; } +void pa_tagstruct_putu64(struct pa_tagstruct*t, uint64_t u) { + assert(t); + extend(t, 9); + t->data[t->length] = TAG_U64; + *((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32)); + *((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u); + t->length += 9; +} + int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) { int error = 0; size_t n; @@ -332,3 +341,18 @@ int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) { t->rindex +=9; return 0; } + +int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *u) { + assert(t && u); + + if (t->rindex+9 > t->length) + return -1; + + if (t->data[t->rindex] != TAG_U64) + return -1; + + *u = (uint64_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32; + *u |= (uint64_t) ntohl(*((uint32_t*) (t->data+t->rindex+5))); + t->rindex +=9; + return 0; +} diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index e50551c41..b943345bb 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -36,8 +36,9 @@ void pa_tagstruct_free(struct pa_tagstruct*t); uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l); void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s); -void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i); void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c); +void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i); +void pa_tagstruct_putu64(struct pa_tagstruct*t, uint64_t i); void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss); void pa_tagstruct_put_arbitrary(struct pa_tagstruct*t, const void *p, size_t length); void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b); @@ -45,8 +46,9 @@ void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv); void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u); int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s); -int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i); int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c); +int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i); +int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *i); int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss); int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length); int pa_tagstruct_get_boolean(struct pa_tagstruct *t, int *b); diff --git a/polyp/util.c b/polyp/util.c index 70ec120d3..9697a1ebe 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -266,7 +266,7 @@ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { return 0; } -pa_usec_t pa_age(const struct timeval *tv) { +pa_usec_t pa_timeval_age(const struct timeval *tv) { struct timeval now; assert(tv); gettimeofday(&now, NULL); diff --git a/polyp/util.h b/polyp/util.h index b0a1a0337..c5ffa7553 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -49,7 +49,7 @@ char *pa_path_get_filename(const char *p); pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); -pa_usec_t pa_age(const struct timeval *tv); +pa_usec_t pa_timeval_age(const struct timeval *tv); void pa_timeval_add(struct timeval *tv, pa_usec_t v); void pa_raise_priority(void); From ee452b0f06c82dd870de82fb3e6bdd4e14d29f3c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Oct 2004 01:09:51 +0000 Subject: [PATCH 0252/1514] two latency interpolation fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@257 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-context.c | 4 +++- polyp/polyplib-stream.c | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index b736daa7d..cf1a8e60c 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -230,9 +230,11 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui } int pa_context_handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { - assert(c && t); + assert(c); if (command == PA_COMMAND_ERROR) { + assert(t); + if (pa_tagstruct_getu32(t, &c->error) < 0) { pa_context_fail(c, PA_ERROR_PROTOCOL); return -1; diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 68035b0fe..c8fef6737 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -420,7 +420,7 @@ static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t c } if (o->stream->interpolate) { - o->stream->ipol_timestamp = now; + o->stream->ipol_timestamp = i.timestamp; o->stream->ipol_usec = pa_stream_get_time(o->stream, &i); } @@ -659,7 +659,7 @@ pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info * pa_usec_t usec; assert(s); - usec = pa_bytes_to_usec(s->counter, &s->sample_spec); + usec = pa_bytes_to_usec(i->counter, &s->sample_spec); if (i) { if (s->direction == PA_STREAM_PLAYBACK) { From 49e16ffc6c87fd879e4143730fd211560ffee0a4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Oct 2004 14:14:30 +0000 Subject: [PATCH 0253/1514] latency calculation fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@258 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-stream.c | 44 ++++++++++++++++++++--------------------- polyp/sink-input.c | 26 ++++++++++++++---------- polyp/sink-input.h | 3 +++ 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index c8fef6737..286702b24 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -687,6 +687,24 @@ pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info * return usec; } +static pa_usec_t time_counter_diff(struct pa_stream *s, pa_usec_t t, pa_usec_t c, int *negative) { + assert(s); + + if (negative) + *negative = 0; + + if (c < t) { + if (s->direction == PA_STREAM_RECORD) { + if (negative) + *negative = 1; + + return t-c; + } else + return 0; + } else + return c-t; +} + pa_usec_t pa_stream_get_latency(struct pa_stream *s, const struct pa_latency_info *i, int *negative) { pa_usec_t t, c; assert(s && i); @@ -694,18 +712,7 @@ pa_usec_t pa_stream_get_latency(struct pa_stream *s, const struct pa_latency_inf t = pa_stream_get_time(s, i); c = pa_bytes_to_usec(s->counter, &s->sample_spec); - if (t <= c) { - if (negative) - *negative = 1; - - return c-t; - } else { - if (negative) - *negative = 0; - return t-c; - } - - return 0; + return time_counter_diff(s, t, c, negative); } const struct pa_sample_spec* pa_stream_get_sample_spec(struct pa_stream *s) { @@ -749,15 +756,6 @@ pa_usec_t pa_stream_get_interpolated_latency(struct pa_stream *s, int *negative) t = pa_stream_get_interpolated_time(s); c = pa_bytes_to_usec(s->counter, &s->sample_spec); - - if (t <= c) { - if (negative) - *negative = 1; - - return c-t; - } else { - if (negative) - *negative = 0; - return t-c; - } + + return time_counter_diff(s, t, c, negative); } diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 5c8675dec..dac109534 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -69,8 +69,10 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con i->kill = NULL; i->get_latency = NULL; i->userdata = NULL; + i->underrun = NULL; i->volume = PA_VOLUME_NORM; + i->playing = 0; i->resampled_chunk.memblock = NULL; i->resampled_chunk.index = i->resampled_chunk.length = 0; @@ -156,20 +158,19 @@ pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i) { } int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { - int ret = 0; + int ret = -1; assert(i && chunk && i->ref >= 1); - if (!i->peek || !i->drop) - return -1; - - if (i->state == PA_SINK_INPUT_CORKED) - return -1; - - if (!i->resampler) - return i->peek(i, chunk); - pa_sink_input_ref(i); + if (!i->peek || !i->drop || i->state == PA_SINK_INPUT_CORKED) + goto finish; + + if (!i->resampler) { + ret = i->peek(i, chunk); + goto finish; + } + while (!i->resampled_chunk.memblock) { struct pa_memchunk tchunk; size_t l; @@ -199,6 +200,11 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { finish: + if (ret < 0 && i->playing && i->underrun) + i->underrun(i); + + i->playing = ret >= 0; + pa_sink_input_unref(i); return ret; diff --git a/polyp/sink-input.h b/polyp/sink-input.h index aed5f521e..eb2cb2399 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -54,9 +54,12 @@ struct pa_sink_input { void (*drop) (struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); void (*kill) (struct pa_sink_input *i); pa_usec_t (*get_latency) (struct pa_sink_input *i); + void (*underrun) (struct pa_sink_input *i); void *userdata; + int playing; + struct pa_memchunk resampled_chunk; struct pa_resampler *resampler; }; From 19f2acbd0a9d199b77ad71eaf206319f6f12e323 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Oct 2004 14:42:56 +0000 Subject: [PATCH 0254/1514] add null sink git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@259 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 12 +++- polyp/module-null-sink.c | 148 +++++++++++++++++++++++++++++++++++++++ polyp/module-pipe-sink.c | 6 +- polyp/voltest.c | 2 + 4 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 polyp/module-null-sink.c diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 10e1c6cb7..ae551a1bd 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -33,14 +33,15 @@ AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in -bin_PROGRAMS = polypaudio pacat pactl paplay voltest +bin_PROGRAMS = polypaudio pacat pactl paplay bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ mainloop-test \ pacat-simple \ parec-simple \ cpulimit-test \ - cpulimit-test2 + cpulimit-test2 \ + voltest polypconf_DATA=default.pa daemon.conf client.conf @@ -108,7 +109,8 @@ modlib_LTLIBRARIES= \ module-esound-compat-spawnpid.la \ module-match.la \ module-tunnel-sink.la \ - module-tunnel-source.la + module-tunnel-source.la \ + module-null-sink.la lib_LTLIBRARIES= \ libpolyp-@PA_MAJORMINOR@.la \ @@ -308,6 +310,10 @@ module_combine_la_SOURCES = module-combine.c module_combine_la_LDFLAGS = -module -avoid-version module_combine_la_LIBADD = $(AM_LIBADD) +module_null_sink_la_SOURCES = module-null-sink.c +module_null_sink_la_LDFLAGS = -module -avoid-version +module_null_sink_la_LIBADD = $(AM_LIBADD) + module_match_la_SOURCES = module-match.c module_match_la_LDFLAGS = -module -avoid-version module_match_la_LIBADD = $(AM_LIBADD) diff --git a/polyp/module-null-sink.c b/polyp/module-null-sink.c new file mode 100644 index 000000000..e48e96687 --- /dev/null +++ b/polyp/module-null-sink.c @@ -0,0 +1,148 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iochannel.h" +#include "sink.h" +#include "module.h" +#include "util.h" +#include "modargs.h" +#include "xmalloc.h" +#include "log.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Clocked NULL sink") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("format= channels= rate= sink_name=") + +#define DEFAULT_SINK_NAME "null" + +struct userdata { + struct pa_core *core; + struct pa_module *module; + struct pa_sink *sink; + struct pa_time_event *time_event; + size_t block_size; +}; + +static const char* const valid_modargs[] = { + "rate", + "format", + "channels", + "sink_name", + NULL +}; + +static void time_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + struct pa_memchunk chunk; + struct timeval ntv = *tv; + size_t l; + + assert(u); + + if (pa_sink_render(u->sink, u->block_size, &chunk) >= 0) { + l = chunk.length; + pa_memblock_unref(chunk.memblock); + } else + l = u->block_size; + + pa_timeval_add(&ntv, pa_bytes_to_usec(l, &u->sink->sample_spec)); + m->time_restart(e, &ntv); +} + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct userdata *u = NULL; + struct pa_sample_spec ss; + struct pa_modargs *ma = NULL; + struct timeval tv; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments\n"); + goto fail; + } + + ss = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + pa_log(__FILE__": invalid sample format specification\n"); + goto fail; + } + + u = pa_xmalloc0(sizeof(struct userdata)); + u->core = c; + u->module = m; + m->userdata = u; + + if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + pa_log(__FILE__": failed to create sink.\n"); + goto fail; + } + + u->sink->userdata = u; + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("NULL sink"); + + gettimeofday(&tv, NULL); + u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u); + + u->block_size = pa_bytes_per_second(&ss) / 10; + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(c, m); + + return -1; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + + u->core->mainloop->time_free(u->time_event); + + pa_xfree(u); +} diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index c5097fb7c..7c779f7d5 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -162,9 +162,10 @@ int pa__init(struct pa_core *c, struct pa_module*m) { } u = pa_xmalloc0(sizeof(struct userdata)); - u->filename = pa_xstrdup(p); u->core = c; + u->module = m; + m->userdata = u; if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { pa_log(__FILE__": failed to create sink.\n"); @@ -187,9 +188,6 @@ int pa__init(struct pa_core *c, struct pa_module*m) { assert(u->defer_event); c->mainloop->defer_enable(u->defer_event, 0); - u->module = m; - m->userdata = u; - pa_modargs_free(ma); return 0; diff --git a/polyp/voltest.c b/polyp/voltest.c index a06d4ca2c..d8d5c5692 100644 --- a/polyp/voltest.c +++ b/polyp/voltest.c @@ -1,3 +1,5 @@ +/* $Id$ */ + #include #include From 929104afd9d1a37f44999fd110c102480d9a86f5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Oct 2004 14:45:04 +0000 Subject: [PATCH 0255/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@260 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/todo b/doc/todo index df710ecf4..fa97b4a37 100644 --- a/doc/todo +++ b/doc/todo @@ -10,9 +10,8 @@ - filter capture data in client through alignment - add radio module - make autoload list use idxset -- enlarge memblockq sizes -- add null-sink - add sync API +- make most buffer sizes dependant on the sample type ** later *** - xmlrpc/http From f252edb7949c0114b666b1eacea5d6d2774d27a0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Oct 2004 14:46:25 +0000 Subject: [PATCH 0256/1514] minor updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@261 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/default.pa.in | 1 + polyp/module-null-sink.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/polyp/default.pa.in b/polyp/default.pa.in index 97b209639..95d4be581 100755 --- a/polyp/default.pa.in +++ b/polyp/default.pa.in @@ -24,6 +24,7 @@ load-module module-alsa-source device=plughw:1,0 load-module module-oss device="/dev/dsp" sink_name=output source_name=input record=0 #load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +load-module module-null-sink #load-module module-pipe-sink # Load audio drivers automatically on access diff --git a/polyp/module-null-sink.c b/polyp/module-null-sink.c index e48e96687..865420107 100644 --- a/polyp/module-null-sink.c +++ b/polyp/module-null-sink.c @@ -90,13 +90,13 @@ int pa__init(struct pa_core *c, struct pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments.\n"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": invalid sample format specification\n"); + pa_log(__FILE__": invalid sample format specification.\n"); goto fail; } From 1bcec3ef5b83ca72c7d32e553566698607bae0e2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Oct 2004 16:23:23 +0000 Subject: [PATCH 0257/1514] make autoload list use idxset git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@262 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +- polyp/autoload.c | 72 +++++++++++++++++++++++++++++----- polyp/autoload.h | 9 ++++- polyp/cli-command.c | 4 +- polyp/cli-text.c | 5 ++- polyp/core.c | 2 +- polyp/core.h | 2 +- polyp/pactl.c | 3 +- polyp/polyplib-introspect.c | 77 +++++++++++++++++++++++++++++++++++-- polyp/polyplib-introspect.h | 18 ++++++--- polyp/protocol-native.c | 54 +++++++++++++++++++------- 11 files changed, 205 insertions(+), 44 deletions(-) diff --git a/doc/todo b/doc/todo index fa97b4a37..1ffdee491 100644 --- a/doc/todo +++ b/doc/todo @@ -1,6 +1,6 @@ *** $Id$ *** -*** 0.6 **** +*** 0.7 **** - per-channel volume - unix socket directories include user name - add sample directory @@ -9,7 +9,6 @@ - improve module-oss-mmap latency measurement - filter capture data in client through alignment - add radio module -- make autoload list use idxset - add sync API - make most buffer sizes dependant on the sample type diff --git a/polyp/autoload.c b/polyp/autoload.c index 12cd1f91e..d6207962d 100644 --- a/polyp/autoload.c +++ b/polyp/autoload.c @@ -45,6 +45,14 @@ static void entry_free(struct pa_autoload_entry *e) { pa_xfree(e); } +static void entry_remove_and_free(struct pa_autoload_entry *e) { + assert(e && e->core); + + pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL); + pa_hashmap_remove(e->core->autoload_hashmap, e->name); + entry_free(e); +} + static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) { struct pa_autoload_entry *e = NULL; assert(c && name); @@ -64,12 +72,16 @@ static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) pa_hashmap_put(c->autoload_hashmap, e->name, e); - pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_NEW, PA_INVALID_INDEX); + if (!c->autoload_idxset) + c->autoload_idxset = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + pa_idxset_put(c->autoload_idxset, e, &e->index); + + pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_NEW, e->index); return e; } -int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument) { +int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument, uint32_t *index) { struct pa_autoload_entry *e = NULL; assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); @@ -79,18 +91,32 @@ int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type typ e->module = pa_xstrdup(module); e->argument = pa_xstrdup(argument); e->type = type; + + if (index) + *index = e->index; + return 0; } -int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type) { +int pa_autoload_remove_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type) { struct pa_autoload_entry *e; assert(c && name && type); - if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name))) + if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) return -1; - pa_hashmap_remove(c->autoload_hashmap, e->name); - entry_free(e); + entry_remove_and_free(e); + return 0; +} + +int pa_autoload_remove_by_index(struct pa_core *c, uint32_t index) { + struct pa_autoload_entry *e; + assert(c && index != PA_IDXSET_INVALID); + + if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, index))) + return -1; + + entry_remove_and_free(e); return 0; } @@ -117,12 +143,38 @@ void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_ty static void free_func(void *p, void *userdata) { struct pa_autoload_entry *e = p; + pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL); entry_free(e); } void pa_autoload_free(struct pa_core *c) { - if (!c->autoload_hashmap) - return; - - pa_hashmap_free(c->autoload_hashmap, free_func, NULL); + if (c->autoload_hashmap) { + pa_hashmap_free(c->autoload_hashmap, free_func, NULL); + c->autoload_hashmap = NULL; + } + + if (c->autoload_idxset) { + pa_idxset_free(c->autoload_idxset, NULL, NULL); + c->autoload_idxset = NULL; + } +} + +const struct pa_autoload_entry* pa_autoload_get_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type) { + struct pa_autoload_entry *e; + assert(c && name); + + if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) + return NULL; + + return e; +} + +const struct pa_autoload_entry* pa_autoload_get_by_index(struct pa_core *c, uint32_t index) { + struct pa_autoload_entry *e; + assert(c && index != PA_IDXSET_INVALID); + + if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, index))) + return NULL; + + return e; } diff --git a/polyp/autoload.h b/polyp/autoload.h index f80b1f0dd..ec7d38f10 100644 --- a/polyp/autoload.h +++ b/polyp/autoload.h @@ -26,15 +26,20 @@ struct pa_autoload_entry { struct pa_core *core; + uint32_t index; char *name; enum pa_namereg_type type; int in_action; char *module, *argument; }; -int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument); +int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument, uint32_t *index); void pa_autoload_free(struct pa_core *c); -int pa_autoload_remove(struct pa_core *c, const char*name, enum pa_namereg_type type); +int pa_autoload_remove_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type); +int pa_autoload_remove_by_index(struct pa_core *c, uint32_t index); void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type); +const struct pa_autoload_entry* pa_autoload_get_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type); +const struct pa_autoload_entry* pa_autoload_get_by_index(struct pa_core *c, uint32_t index); + #endif diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 39ea9cc1e..62981b4d9 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -570,7 +570,7 @@ static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t return -1; } - pa_autoload_add(c, a, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, b, pa_tokenizer_get(t, 3)); + pa_autoload_add(c, a, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, b, pa_tokenizer_get(t, 3), NULL); return 0; } @@ -584,7 +584,7 @@ static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer return -1; } - if (pa_autoload_remove(c, name, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) < 0) { + if (pa_autoload_remove_by_name(c, name, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) < 0) { pa_strbuf_puts(buf, "Failed to remove autload entry\n"); return -1; } diff --git a/polyp/cli-text.c b/polyp/cli-text.c index f9bc6c7a7..c08b0d9cf 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -243,7 +243,7 @@ char *pa_scache_list_to_string(struct pa_core *c) { } pa_strbuf_printf( - s, " name: <%s>\n\tindex: <%i>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n\tlazy: %s\n\tfilename: %s\n", + s, " name: <%s>\n\tindex: <%u>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n\tlazy: %s\n\tfilename: %s\n", e->name, e->index, ss, @@ -273,9 +273,10 @@ char *pa_autoload_list_to_string(struct pa_core *c) { while ((e = pa_hashmap_iterate(c->autoload_hashmap, &state))) { pa_strbuf_printf( - s, " name: <%s>\n\ttype: <%s>\n\tmodule_name: <%s>\n\targuments: <%s>\n", + s, " name: <%s>\n\ttype: <%s>\n\tindex: <%u>\n\tmodule_name: <%s>\n\targuments: <%s>\n", e->name, e->type == PA_NAMEREG_SOURCE ? "source" : "sink", + e->index, e->module, e->argument); diff --git a/polyp/core.c b/polyp/core.c index cf2d383c4..c53d2e4ee 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -56,7 +56,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->modules = NULL; c->namereg = NULL; c->scache = NULL; - + c->autoload_idxset = NULL; c->autoload_hashmap = NULL; c->default_sample_spec.format = PA_SAMPLE_S16NE; diff --git a/polyp/core.h b/polyp/core.h index 62959d0af..c457c3fd6 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -31,7 +31,7 @@ struct pa_core { struct pa_mainloop_api *mainloop; - struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache; + struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache, *autoload_idxset; struct pa_hashmap *namereg, *autoload_hashmap; diff --git a/polyp/pactl.c b/polyp/pactl.c index fbedc6fa8..29c06f913 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -437,11 +437,12 @@ static void get_autoload_info_callback(struct pa_context *c, const struct pa_aut printf("\n"); nl = 1; - printf("*** Autoload Entry ***\n" + printf("*** Autoload Entry #%u ***\n" "Name: %s\n" "Type: %s\n" "Module: %s\n" "Argument: %s\n", + i->index, i->name, i->type == PA_AUTOLOAD_SINK ? "sink" : "source", i->module, diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 267af95b7..af5fd168e 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -823,7 +823,8 @@ static void context_get_autoload_info_callback(struct pa_pdispatch *pd, uint32_t while (!pa_tagstruct_eof(t)) { struct pa_autoload_info i; - if (pa_tagstruct_gets(t, &i.name) < 0 || + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.type) < 0 || pa_tagstruct_gets(t, &i.module) < 0 || pa_tagstruct_gets(t, &i.argument) < 0) { @@ -848,7 +849,7 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_get_autoload_info(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) { +struct pa_operation* pa_context_get_autoload_info_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) { struct pa_tagstruct *t; struct pa_operation *o; uint32_t tag; @@ -869,10 +870,58 @@ struct pa_operation* pa_context_get_autoload_info(struct pa_context *c, const ch return pa_operation_ref(o); } +struct pa_operation* pa_context_get_autoload_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + struct pa_operation *o; + uint32_t tag; + assert(c && cb && index != PA_INVALID_INDEX); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_AUTOLOAD_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, o); + + return pa_operation_ref(o); +} + struct pa_operation* pa_context_get_autoload_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) { return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, cb, userdata); } +static void context_add_autoload_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_operation *o = userdata; + uint32_t index; + assert(pd && o && o->context && o->ref >= 1); + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; + + index = PA_INVALID_INDEX; + } else if (pa_tagstruct_getu32(t, &index) || + !pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); + goto finish; + } + + if (o->callback) { + void (*cb)(struct pa_context *s, uint32_t index, void *userdata) = o->callback; + cb(o->context, index, o->userdata); + } + + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + + struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) { struct pa_operation *o; struct pa_tagstruct *t; @@ -891,12 +940,12 @@ struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *n pa_tagstruct_puts(t, module); pa_tagstruct_puts(t, argument); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_add_autoload_callback, o); return pa_operation_ref(o); } -struct pa_operation* pa_context_remove_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) { +struct pa_operation* pa_context_remove_autoload_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) { struct pa_operation *o; struct pa_tagstruct *t; uint32_t tag; @@ -916,3 +965,23 @@ struct pa_operation* pa_context_remove_autoload(struct pa_context *c, const char return pa_operation_ref(o); } + +struct pa_operation* pa_context_remove_autoload_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) { + struct pa_operation *o; + struct pa_tagstruct *t; + uint32_t tag; + assert(c && index != PA_INVALID_INDEX); + + o = pa_operation_new(c, NULL); + o->callback = cb; + o->userdata = userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_AUTOLOAD); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + + return pa_operation_ref(o); +} diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 9e6c31b28..f4dbd185e 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -234,23 +234,31 @@ enum pa_autoload_type { /** Stores information about autoload entries. \since 0.5 */ struct pa_autoload_info { + uint32_t index; /**< Index of this autoload entry */ const char *name; /**< Name of the sink or source */ enum pa_autoload_type type; /**< Type of the autoload entry */ const char *module; /**< Module name to load */ const char *argument; /**< Argument string for module */ }; -/** Get info about a specific autoload entry. \since 0.5 */ -struct pa_operation* pa_context_get_autoload_info(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata); +/** Get info about a specific autoload entry. \since 0.6 */ +struct pa_operation* pa_context_get_autoload_info_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata); + +/** Get info about a specific autoload entry. \since 0.6 */ +struct pa_operation* pa_context_get_autoload_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata); /** Get the complete list of autoload entries. \since 0.5 */ struct pa_operation* pa_context_get_autoload_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata); /** Add a new autoload entry. \since 0.5 */ -struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata); +struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int index, void *userdata), void* userdata); + +/** Remove an autoload entry. \since 0.6 */ +struct pa_operation* pa_context_remove_autoload_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata); + +/** Remove an autoload entry. \since 0.6 */ +struct pa_operation* pa_context_remove_autoload_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata); -/** Remove an autoload entry. \since 0.5 */ -struct pa_operation* pa_context_remove_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata); PA_C_DECL_END diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 31ab4ab8c..7af8bdda4 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -1729,6 +1729,8 @@ static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint struct connection *c = userdata; const char *name, *module, *argument; uint32_t type; + uint32_t index; + struct pa_tagstruct *reply; assert(c && t); if (pa_tagstruct_gets(t, &name) < 0 || !name || @@ -1745,22 +1747,30 @@ static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint return; } - if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument) < 0) { + if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &index) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); return; } - pa_pstream_send_simple_ack(c->pstream, tag); + reply = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + pa_tagstruct_putu32(reply, index); + pa_pstream_send_tagstruct(c->pstream, reply); } static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - const char *name; - uint32_t type; + const char *name = NULL; + uint32_t type, index = PA_IDXSET_INVALID; + int r; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || !name || - pa_tagstruct_getu32(t, &type) < 0 || type > 1 || + if ((pa_tagstruct_getu32(t, &index) < 0 && + (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_getu32(t, &type) < 0)) || + (!name && index == PA_IDXSET_INVALID) || + (name && type > 1) || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1771,7 +1781,12 @@ static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, u return; } - if (pa_autoload_remove(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) < 0) { + if (name) + r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE); + else + r = pa_autoload_remove_by_index(c->protocol->core, index); + + if (r < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1779,8 +1794,10 @@ static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, u pa_pstream_send_simple_ack(c->pstream, tag); } -static void autoload_fill_tagstruct(struct pa_tagstruct *t, struct pa_autoload_entry *e) { +static void autoload_fill_tagstruct(struct pa_tagstruct *t, const struct pa_autoload_entry *e) { assert(t && e); + + pa_tagstruct_putu32(t, e->index); pa_tagstruct_puts(t, e->name); pa_tagstruct_putu32(t, e->type == PA_NAMEREG_SINK ? 0 : 1); pa_tagstruct_puts(t, e->module); @@ -1789,14 +1806,17 @@ static void autoload_fill_tagstruct(struct pa_tagstruct *t, struct pa_autoload_e static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - struct pa_autoload_entry *a = NULL; - uint32_t type; + const struct pa_autoload_entry *a = NULL; + uint32_t type, index; const char *name; struct pa_tagstruct *reply; assert(c && t); - - if (pa_tagstruct_gets(t, &name) < 0 || name || - pa_tagstruct_getu32(t, &type) < 0 || type > 1 || + + if ((pa_tagstruct_getu32(t, &index) < 0 && + (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_getu32(t, &type) < 0)) || + (!name && index == PA_IDXSET_INVALID) || + (name && type > 1) || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1807,7 +1827,13 @@ static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, return; } - if (!c->protocol->core->autoload_hashmap || !(a = pa_hashmap_get(c->protocol->core->autoload_hashmap, name)) || (a->type == PA_NAMEREG_SINK && type != 0) || (a->type == PA_NAMEREG_SOURCE && type != 1)) { + + if (name) + a = pa_autoload_get_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE); + else + a = pa_autoload_get_by_index(c->protocol->core, index); + + if (!a) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } From c82105d901682fdbecd409930fdf6d747d37809c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Oct 2004 22:43:36 +0000 Subject: [PATCH 0258/1514] prepare next release 0.6 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@264 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 44 ++++++++++++++++++++++++++++++++++---------- doc/daemon.html.in | 4 ++++ doc/modules.html.in | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 10 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index a0b3e6415..22a30dc21 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -44,6 +44,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    News

    +
    Thu Oct 28 2004:

    Version 0.6 released; +changes include: TCP wrappers support; don't load the complete sound +file into memory when playing back using pa_play_file(); +autoload API change; don't load all sound files as FLOAT32; shorten +default buffers; client-side latency interpolation; add new user +volume metrics; add module-tunnel, module-null-sink, +module-match and new tool paplay; new API version +macros; many client API improvements; correctly lock cookie file +generation; correctly lock daemon autospawning; print daemon layout to +STDERR on SIGHUP; new options for pacat: allow sample type specification.

    +
    Mon Sep 24 2004:

    Version 0.5.1 released; changes include: improve esound protocol compatibility; fix @@ -96,6 +108,7 @@ Daemon (ESOUND). In addition to the features ESOUND provides

  • Module autoloading
  • Very accurate latency measurement for playback and recordin.
  • May be used to combine multiple sound cards to one (with sample rate adjustment)
  • +
  • Client side latency interpolation
  • Both the core and the client API are completely asynchronous making @@ -120,7 +133,10 @@ available. A simple main loop implementation is available as well.

  • module-native-protocol-tcp, module-native-protocol-unix: Native polypaudio protocol (for TCP/IP resp. UNIX domain sockets)
  • module-simple-protocol-tcp, module-simple-protocol-unix: Simplistic protocol for playback/capture for usage with tools like netcat (for TCP/IP resp. UNIX domain sockets)
  • module-cli-protocol-tcp, module-cli-protocol-unix, module-cli: Expose polypaudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
  • - +
  • module-tunnel-sink, module-tunnel-source: make sinks/sources from other hosts available locally.
  • +
  • module-match: adjust volume automatically for newly created playback streams based on a regular expression matching table.
  • +
  • module-null-sink: a clocked sink similar to /dev/null.
  • +

    polypaudio is the successor of my previous, ill-fated attempt to write a sound server, Polypaudio Manager. Another GTK GUI tool for Polypaudio is the Polypaudio Volume Meter. There are output plugins for XMMS and libao. Drivers -for gstreamer and MPlayer will be released shortly.

    +href="http://0pointer.de/lennart/projects/xmms-polyp/">XMMS, libao and gstreamer. Drivers +for MPlayer and PortAudio will be released shortly.

    Status

    @@ -173,6 +188,10 @@ command line :

    The best idea is to configure your daemon in /etc/polypaudio/daemon.conf and /etc/polypaudio/default.pa and to run polypaudio without any arguments.

    +

    Beware! Unless you pass the option --sysconfdir=/etc to +configure, the directory /etc/polypaudio/ is really +/usr/local/etc/polypaudio/.

    +

    Developing polypaudio Clients

    You may browse the Doxygen generated -

    polypaudio needs polypaudio needs libwrap, Secret Rabbit Code (aka -libsamplerate), libsndfile, alsa-lib and GLIB. (The latter is required for building the GLIB main loop integration module only.)

    +libsamplerate), libsndfile, alsa-lib and GLIB. (The latter is required for +building the GLIB main loop integration module only.)

    Installation

    @@ -229,7 +251,7 @@ compilation and make install (as root) for installation of

    The current release is @PACKAGE_VERSION@

    -

    Get polypaudio's development sources from the Subversion repository (viewcvs):

    +

    Get polypaudio's development sources from the Subversion repository (viewcvs):

    svn checkout svn://seth.intheinter.net/polypaudio/trunk polypaudio
    @@ -237,8 +259,10 @@ compilation and make install (as root) for installation of

    New! There is a general discussion mailing list for polypaudio available.

    +

    New! There is now a Polypaudio wiki (based on trac) available.

    +
    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, October 2004
    $Id$
    diff --git a/doc/daemon.html.in b/doc/daemon.html.in index 147ee551b..8d2414c07 100644 --- a/doc/daemon.html.in +++ b/doc/daemon.html.in @@ -62,6 +62,10 @@ The polypaudio daemon accepts several command line arguments:

    The daemon tries to load the module module-cli-protocol-unix, effectively providing a command line interface on a special UNIX domain socket.

    +

    SIGHUP

    + +

    The daemon logs the current server layout.

    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    $Id$
    diff --git a/doc/modules.html.in b/doc/modules.html.in index 4bf6044ba..5e9b8873c 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -44,6 +44,13 @@ special file in the file system. The source name defaults to pipe_input file=The name of the FIFO special file to use. (defaults to: /tmp/music.input) + +

    module-null-sink

    + +

    Provides a simple null sink. All data written to this sink is silently dropped. This sink is clocked using the system time.

    + +

    This module doesn't support any special parameters

    +

    module-alsa-sink

    @@ -116,6 +123,21 @@ be to slow on your machine try using zero-order-hold. This will decrease output quality however. (defaults to sinc-fastest) +

    module-tunnel-{sink,source}

    + +

    Tunnel a remote sink/source to a local "ghost" +sink/source. Requires a running polypaudio daemon on the remote server +with module-native-protocol-tcp loaded. It's probably a +better idea to connect to the remote sink/source directly since some +buffer control is lost through this tunneling.

    + + + + + + +
    server=The server to connect to
    source=The source on the remote server. Only available for module-tunnel-source.
    sink=The sink on the remote server. Only available for module-tunnel-sink.
    cookie=The authentication cookie file to use.
    +

    Protocols

    @@ -251,6 +273,22 @@ about the two possible suffixes of this module.

    This is a compatibility module for libesd based autospawning of polypaudio. Don't use it directly.

    +

    module-match

    + +

    Adjust the volume of a playback stream automatically based on its name.

    + + + +
    table=The regular expression matching table file to use
    + +

    The table file should contain a regexp and volume on each line, seperated by spaces. An example:

    + +
    +^sample: 25
    +
    + +

    The volumes of all streams with titles starting with sample: are automatically set to 25. (FYI: All sample cache streams start with sample:)

    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    $Id$
    From e34c65d0427d7efc4d21a1df877bb5e4acc73154 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 28 Oct 2004 14:41:46 +0000 Subject: [PATCH 0259/1514] require newer libsndfile update todo file git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@265 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- doc/todo | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 68df5b850..14a6842d1 100644 --- a/configure.ac +++ b/configure.ac @@ -89,7 +89,7 @@ PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) AC_SUBST(LIBSAMPLERATE_CFLAGS) AC_SUBST(LIBSAMPLERATE_LIBS) -PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.0 ]) +PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ]) AC_SUBST(LIBSNDFILE_CFLAGS) AC_SUBST(LIBSNDFILE_LIBS) diff --git a/doc/todo b/doc/todo index 1ffdee491..f2155b995 100644 --- a/doc/todo +++ b/doc/todo @@ -22,7 +22,6 @@ backends for: - portaudio (semi-done) -- gstreamer (semi-done) - alsa-lib - sdl - OSS (esddsp style) From 4e5c44de30de40b80354820f8ac1738a9636515a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Oct 2004 13:50:25 +0000 Subject: [PATCH 0260/1514] use setreuid() instead of setuid()/seteuid() when dropping root chdir to / on daemon startup (both are suggestions by alan cox) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@267 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/caps.c | 5 +++-- polyp/main.c | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/polyp/caps.c b/polyp/caps.c index 258e13e41..d03ab14be 100644 --- a/polyp/caps.c +++ b/polyp/caps.c @@ -43,8 +43,9 @@ void pa_drop_root(void) { pa_log(__FILE__": dropping root rights.\n"); - setuid(uid); - seteuid(uid); + setreuid(uid, uid); +/* setuid(uid); + seteuid(uid);*/ } #ifdef HAVE_SYS_CAPABILITY_H diff --git a/polyp/main.c b/polyp/main.c index 25fb17413..5be4118d8 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -259,6 +259,7 @@ int main(int argc, char *argv[]) { close(1); } + chdir("/"); pa_log(__FILE__": sizeof(pa_usec_t) = %u\n", sizeof(pa_usec_t)); From 899788b4c5e23af9dabfb98c5f864c2f933804f4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 30 Oct 2004 01:55:16 +0000 Subject: [PATCH 0261/1514] some updates for pa_hashmap add property infrastructure add module module-x11-publish allow ldpreloading of all modules abstract x11wrap from module-x11-bell git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@268 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 9 + polyp/Makefile.am | 61 ++++++- polyp/cli-command.c | 11 +- polyp/cli-text.c | 2 +- polyp/core.c | 5 + polyp/core.h | 2 +- polyp/hashmap.c | 19 ++- polyp/hashmap.h | 12 +- polyp/main.c | 4 +- polyp/module-alsa-sink.c | 1 + polyp/module-alsa-source.c | 1 + polyp/module-cli.c | 1 + polyp/module-combine.c | 1 + polyp/module-defs.h.m4 | 21 +++ polyp/module-esound-compat-spawnfd.c | 1 + polyp/module-esound-compat-spawnpid.c | 1 + polyp/module-match.c | 1 + polyp/module-native-protocol-fd.c | 1 + polyp/module-null-sink.c | 1 + polyp/module-oss-mmap.c | 1 + polyp/module-oss.c | 1 + polyp/module-pipe-sink.c | 1 + polyp/module-pipe-source.c | 1 + polyp/module-protocol-stub.c | 26 ++- polyp/module-sine.c | 1 + polyp/module-tunnel.c | 8 +- polyp/module-x11-bell.c | 80 ++++----- polyp/module-x11-publish.c | 167 ++++++++++++++++++ polyp/module.h | 12 +- polyp/namereg.c | 6 +- polyp/polyplib-internal.h | 2 - polyp/props.c | 112 ++++++++++++ polyp/props.h | 55 ++++++ polyp/protocol-native.c | 2 +- polyp/x11wrap.c | 235 ++++++++++++++++++++++++++ polyp/x11wrap.h | 52 ++++++ 36 files changed, 827 insertions(+), 90 deletions(-) create mode 100644 polyp/module-defs.h.m4 create mode 100644 polyp/module-x11-publish.c create mode 100644 polyp/props.c create mode 100644 polyp/props.h create mode 100644 polyp/x11wrap.c create mode 100644 polyp/x11wrap.h diff --git a/doc/todo b/doc/todo index f2155b995..8212ea89b 100644 --- a/doc/todo +++ b/doc/todo @@ -12,6 +12,15 @@ - add sync API - make most buffer sizes dependant on the sample type +- X11: support for the X11 synchronization extension +- X11: save auth info in root window +- pass meta info for hearing impaired +- fall back to getpwnam if $HOME doesn't exist +- module-match: look in $HOME for table +- limit all resources +- getaddrinfo +- add LGPL blurb to all concerning files + ** later *** - xmlrpc/http - dbus diff --git a/polyp/Makefile.am b/polyp/Makefile.am index ae551a1bd..d90d32295 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -32,7 +32,7 @@ AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm -EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in +EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in module-defs.h.m4 bin_PROGRAMS = polypaudio pacat pactl paplay bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ @@ -112,6 +112,33 @@ modlib_LTLIBRARIES= \ module-tunnel-source.la \ module-null-sink.la +SYMDEF_FILES= \ + module-cli-symdef.h \ + module-cli-protocol-tcp-symdef.h \ + module-cli-protocol-unix-symdef.h \ + module-pipe-sink-symdef.h \ + module-pipe-source-symdef.h \ + module-oss-symdef.h \ + module-oss-mmap-symdef.h \ + module-simple-protocol-tcp-symdef.h \ + module-simple-protocol-unix-symdef.h \ + module-esound-protocol-tcp-symdef.h \ + module-esound-protocol-unix-symdef.h \ + module-native-protocol-tcp-symdef.h \ + module-native-protocol-unix-symdef.h \ + module-native-protocol-fd-symdef.h \ + module-sine-symdef.h \ + module-combine-symdef.h \ + module-esound-compat-spawnfd-symdef.h \ + module-esound-compat-spawnpid-symdef.h \ + module-match-symdef.h \ + module-tunnel-sink-symdef.h \ + module-tunnel-source-symdef.h \ + module-null-sink-symdef.h + +EXTRA_DIST+=$(SYMDEF_FILES) +BUILT_SOURCES+=$(SYMDEF_FILES) + lib_LTLIBRARIES= \ libpolyp-@PA_MAJORMINOR@.la \ libpolyp-error-@PA_MAJORMINOR@.la \ @@ -167,12 +194,14 @@ polypaudio_SOURCES = idxset.c idxset.h \ daemon-conf.c daemon-conf.h \ dumpmodules.c dumpmodules.h \ conf-parser.h conf-parser.c \ - caps.h caps.c + caps.h caps.c \ + props.h props.c polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) -polypaudio_LDFLAGS=-export-dynamic +polypaudio_LDFLAGS= -export-dynamic -dlopen force +#-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f)) libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version @@ -430,12 +459,28 @@ cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la if HAVE_X11 modlib_LTLIBRARIES+= \ - module-x11-bell.la + libx11wrap.la \ + module-x11-bell.la \ + module-x11-publish.la +SYMDEF_FILES += \ + module-x11-bell-symdef.h \ + module-x11-publish-symdef.h + +libx11wrap_la_SOURCES = x11wrap.c x11wrap.h +libx11wrap_la_LDFLAGS = -avoid-version +libx11wrap_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) module_x11_bell_la_SOURCES = module-x11-bell.c module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_bell_la_LDFLAGS = -module -avoid-version -module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) +module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) libx11wrap.la + +module_x11_publish_la_SOURCES = module-x11-publish.c +module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +module_x11_publish_la_LDFLAGS = -module -avoid-version +module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) libx11wrap.la + endif ### ALSA modules @@ -445,6 +490,9 @@ modlib_LTLIBRARIES+= \ libalsa-util.la \ module-alsa-sink.la \ module-alsa-source.la +SYMDEF_FILES += \ + module-alsa-sink-symdef.h \ + module-alsa-source-symdef.h libalsa_util_la_SOURCES = alsa-util.c alsa-util.h libalsa_util_la_LDFLAGS = -avoid-version @@ -597,3 +645,6 @@ daemon.conf: daemon.conf.in Makefile install-exec-hook: chown root:root $(DESTDIR)$(bindir)/polypaudio chmod u+s $(DESTDIR)$(bindir)/polypaudio + +$(SYMDEF_FILES): module-defs.h.m4 + m4 -Dfname="$@" $< > $@ diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 62981b4d9..d563a0727 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -47,6 +47,7 @@ #include "autoload.h" #include "xmalloc.h" #include "sound-file-stream.h" +#include "props.h" struct command { const char *name; @@ -83,6 +84,7 @@ static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer * static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_list_props(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static const struct command commands[] = { { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, @@ -118,6 +120,7 @@ static const struct command commands[] = { { "remove-autoload-sink", pa_cli_command_autoload_remove, "Remove autoload entry for a sink (args: name)", 2}, { "remove-autoload-source", pa_cli_command_autoload_remove, "Remove autoload entry for a source (args: name)", 2}, { "dump", pa_cli_command_dump, "Dump daemon configuration", 1}, + { "list-props", pa_cli_command_list_props, NULL, 1}, { NULL, NULL, NULL, 0 } }; @@ -602,6 +605,12 @@ static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer * return 0; } +static int pa_cli_command_list_props(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + assert(c && t); + pa_property_dump(c, buf); + return 0; +} + static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { struct pa_module *m; struct pa_sink *s; @@ -654,7 +663,7 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct nl = 0; i = NULL; - while ((a = pa_hashmap_iterate(c->autoload_hashmap, &i))) { + while ((a = pa_hashmap_iterate(c->autoload_hashmap, &i, NULL))) { if (!nl) { pa_strbuf_puts(buf, "\n"); diff --git a/polyp/cli-text.c b/polyp/cli-text.c index c08b0d9cf..39f7b6edd 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -271,7 +271,7 @@ char *pa_autoload_list_to_string(struct pa_core *c) { struct pa_autoload_entry *e; void *state = NULL; - while ((e = pa_hashmap_iterate(c->autoload_hashmap, &state))) { + while ((e = pa_hashmap_iterate(c->autoload_hashmap, &state, NULL))) { pa_strbuf_printf( s, " name: <%s>\n\ttype: <%s>\n\tindex: <%u>\n\tmodule_name: <%s>\n\targuments: <%s>\n", e->name, diff --git a/polyp/core.c b/polyp/core.c index c53d2e4ee..6e155dda7 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -39,6 +39,7 @@ #include "autoload.h" #include "xmalloc.h" #include "subscribe.h" +#include "props.h" struct pa_core* pa_core_new(struct pa_mainloop_api *m) { struct pa_core* c; @@ -82,6 +83,8 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->scache_idle_time = 20; c->resample_method = SRC_SINC_FASTEST; + + pa_property_init(c); pa_check_signal_is_blocked(SIGPIPE); @@ -121,6 +124,8 @@ void pa_core_free(struct pa_core *c) { pa_xfree(c->default_sink_name); pa_memblock_stat_unref(c->memblock_stat); + + pa_property_cleanup(c); pa_xfree(c); } diff --git a/polyp/core.h b/polyp/core.h index c457c3fd6..1438bf720 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -33,7 +33,7 @@ struct pa_core { struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache, *autoload_idxset; - struct pa_hashmap *namereg, *autoload_hashmap; + struct pa_hashmap *namereg, *autoload_hashmap, *properties; char *default_source_name, *default_sink_name; diff --git a/polyp/hashmap.c b/polyp/hashmap.c index 2b9550fda..10b148ddf 100644 --- a/polyp/hashmap.c +++ b/polyp/hashmap.c @@ -30,6 +30,7 @@ #include "hashmap.h" #include "idxset.h" #include "xmalloc.h" +#include "log.h" struct hashmap_entry { struct hashmap_entry *next, *previous, *bucket_next, *bucket_previous; @@ -147,25 +148,27 @@ void* pa_hashmap_get(struct pa_hashmap *h, const void *key) { return e->value; } -int pa_hashmap_remove(struct pa_hashmap *h, const void *key) { +void* pa_hashmap_remove(struct pa_hashmap *h, const void *key) { struct hashmap_entry *e; unsigned hash; + void *data; assert(h && key); hash = h->hash_func(key) % h->size; if (!(e = get(h, hash, key))) - return 1; + return NULL; + data = e->value; remove(h, e); - return 0; + return data; } unsigned pa_hashmap_ncontents(struct pa_hashmap *h) { return h->n_entries; } -void *pa_hashmap_iterate(struct pa_hashmap *h, void **state) { +void *pa_hashmap_iterate(struct pa_hashmap *h, void **state, const void **key) { assert(h && state); if (!*state) { @@ -173,8 +176,14 @@ void *pa_hashmap_iterate(struct pa_hashmap *h, void **state) { } else *state = ((struct hashmap_entry*) *state)->next; - if (!*state) + if (!*state) { + if (key) + *key = NULL; return NULL; + } + + if (key) + *key = ((struct hashmap_entry*) *state)->key; return ((struct hashmap_entry*) *state)->value; } diff --git a/polyp/hashmap.h b/polyp/hashmap.h index 3b79d7ae8..739f89477 100644 --- a/polyp/hashmap.h +++ b/polyp/hashmap.h @@ -30,13 +30,15 @@ void pa_hashmap_free(struct pa_hashmap*, void (*free_func)(void *p, void *userda int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value); void* pa_hashmap_get(struct pa_hashmap *h, const void *key); -int pa_hashmap_remove(struct pa_hashmap *h, const void *key); +void* pa_hashmap_remove(struct pa_hashmap *h, const void *key); unsigned pa_hashmap_ncontents(struct pa_hashmap *h); -/* Maybe used to iterate through the hashmap. Initial state should - point to a NULL pointer. The hashmap may not be modified during - iteration */ -void *pa_hashmap_iterate(struct pa_hashmap *h, void **state); +/* May be used to iterate through the hashmap. Initially the opaque + pointer *state has to be set to NULL. The hashmap may not be + modified during iteration. The key of the entry is returned in + *key, if key is non-NULL. After the last entry in the hashmap NULL + is returned. */ +void *pa_hashmap_iterate(struct pa_hashmap *h, void **state, const void**key); #endif diff --git a/polyp/main.c b/polyp/main.c index 5be4118d8..378cb8a06 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -152,9 +152,11 @@ int main(int argc, char *argv[]) { pa_drop_root(); } + LTDL_SET_PRELOADED_SYMBOLS(); + r = lt_dlinit(); assert(r == 0); - + pa_log_set_ident("polypaudio"); conf = pa_daemon_conf_new(); diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 528fe8d30..e319f6c16 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -39,6 +39,7 @@ #include "alsa-util.h" #include "xmalloc.h" #include "log.h" +#include "module-alsa-sink-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ALSA Sink") diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index c0a18d2b5..34f08f95a 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -39,6 +39,7 @@ #include "alsa-util.h" #include "xmalloc.h" #include "log.h" +#include "module-alsa-source-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ALSA Source") diff --git a/polyp/module-cli.c b/polyp/module-cli.c index 6444194c1..1ebc9b52e 100644 --- a/polyp/module-cli.c +++ b/polyp/module-cli.c @@ -32,6 +32,7 @@ #include "cli.h" #include "sioman.h" #include "log.h" +#include "module-cli-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Command line interface") diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 1a909087f..5df3f1589 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -36,6 +36,7 @@ #include "xmalloc.h" #include "modargs.h" #include "namereg.h" +#include "module-combine-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Combine multiple sinks to one") diff --git a/polyp/module-defs.h.m4 b/polyp/module-defs.h.m4 new file mode 100644 index 000000000..85eb64a24 --- /dev/null +++ b/polyp/module-defs.h.m4 @@ -0,0 +1,21 @@ +dnl $Id$ +changecom(`/*', `*/')dnl +define(`module', patsubst(patsubst(fname, `-symdef.h$'), `[^0-9a-zA-Z]', `_'))dnl +define(`c_symbol', patsubst(module, `[^0-9a-zA-Z]', `_'))dnl +define(`c_macro', patsubst(module, `[^0-9a-zA-Z]', `'))dnl +define(`incmacro', `foo'c_macro`symdeffoo')dnl +define(`gen_symbol', `#define $1 'module`_LTX_$1')dnl +#ifndef incmacro +#define incmacro + +gen_symbol(pa__init) +gen_symbol(pa__done) +gen_symbol(pa__get_author) +gen_symbol(pa__get_description) +gen_symbol(pa__get_usage) +gen_symbol(pa__get_version) + +int pa__init(struct pa_core *c, struct pa_module*m); +void pa__done(struct pa_core *c, struct pa_module*m); + +#endif diff --git a/polyp/module-esound-compat-spawnfd.c b/polyp/module-esound-compat-spawnfd.c index 514159fcf..ae4f9095b 100644 --- a/polyp/module-esound-compat-spawnfd.c +++ b/polyp/module-esound-compat-spawnfd.c @@ -32,6 +32,7 @@ #include "util.h" #include "modargs.h" #include "log.h" +#include "module-esound-compat-spawnfd-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ESOUND compatibility module: -spawnfd emulation") diff --git a/polyp/module-esound-compat-spawnpid.c b/polyp/module-esound-compat-spawnpid.c index 5583f071f..02756cdb6 100644 --- a/polyp/module-esound-compat-spawnpid.c +++ b/polyp/module-esound-compat-spawnpid.c @@ -32,6 +32,7 @@ #include "util.h" #include "modargs.h" #include "log.h" +#include "module-esound-compat-spawnpid-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ESOUND compatibility module: -spawnpid emulation") diff --git a/polyp/module-match.c b/polyp/module-match.c index 380c6011a..6689cc592 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -39,6 +39,7 @@ #include "subscribe.h" #include "xmalloc.h" #include "sink-input.h" +#include "module-match-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Sink input matching module") diff --git a/polyp/module-native-protocol-fd.c b/polyp/module-native-protocol-fd.c index c1ea69756..8f41db641 100644 --- a/polyp/module-native-protocol-fd.c +++ b/polyp/module-native-protocol-fd.c @@ -32,6 +32,7 @@ #include "modargs.h" #include "protocol-native.h" #include "log.h" +#include "module-native-protocol-fd-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Native protocol autospawn helper") diff --git a/polyp/module-null-sink.c b/polyp/module-null-sink.c index 865420107..4a41b74de 100644 --- a/polyp/module-null-sink.c +++ b/polyp/module-null-sink.c @@ -40,6 +40,7 @@ #include "modargs.h" #include "xmalloc.h" #include "log.h" +#include "module-null-sink-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Clocked NULL sink") diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index f7fcbd3ba..bc36d1991 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -46,6 +46,7 @@ #include "modargs.h" #include "xmalloc.h" #include "log.h" +#include "module-oss-mmap-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("OSS Sink/Source (mmap)") diff --git a/polyp/module-oss.c b/polyp/module-oss.c index c0c6be8ed..969761f68 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -45,6 +45,7 @@ #include "modargs.h" #include "xmalloc.h" #include "log.h" +#include "module-oss-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("OSS Sink/Source") diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index 7c779f7d5..bc8abb41f 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -40,6 +40,7 @@ #include "modargs.h" #include "xmalloc.h" #include "log.h" +#include "module-pipe-sink-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("UNIX pipe sink") diff --git a/polyp/module-pipe-source.c b/polyp/module-pipe-source.c index 3decc4159..8bc4c4773 100644 --- a/polyp/module-pipe-source.c +++ b/polyp/module-pipe-source.c @@ -40,6 +40,7 @@ #include "modargs.h" #include "xmalloc.h" #include "log.h" +#include "module-pipe-source-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("UNIX pipe source") diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 1ff70a1ae..8cef3bdb3 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -39,9 +39,6 @@ #include "log.h" #include "native-common.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_VERSION(PACKAGE_VERSION) - #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" #define SOCKET_USAGE "port= loopback=" @@ -58,6 +55,11 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define IPV4_PORT 4711 #define UNIX_SOCKET "/tmp/polypaudio/simple" #define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record", + #ifdef USE_TCP_SOCKETS + #include "module-simple-protocol-tcp-symdef.h" + #else + #include "module-simple-protocol-unix-symdef.h" + #endif PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("rate= format= channels= sink= source= playback= record= "SOCKET_USAGE) #elif defined(USE_PROTOCOL_CLI) @@ -68,6 +70,11 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define IPV4_PORT 4712 #define UNIX_SOCKET "/tmp/polypaudio/cli" #define MODULE_ARGUMENTS + #ifdef USE_TCP_SOCKETS + #include "module-cli-protocol-tcp-symdef.h" + #else + #include "module-cli-protocol-unix-symdef.h" + #endif PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE(SOCKET_USAGE) #elif defined(USE_PROTOCOL_NATIVE) @@ -78,6 +85,11 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define IPV4_PORT PA_NATIVE_DEFAULT_PORT #define UNIX_SOCKET "/tmp/polypaudio/native" #define MODULE_ARGUMENTS "public", "cookie", + #ifdef USE_TCP_SOCKETS + #include "module-native-protocol-tcp-symdef.h" + #else + #include "module-native-protocol-unix-symdef.h" + #endif PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("public= cookie= "SOCKET_USAGE) #elif defined(USE_PROTOCOL_ESOUND) @@ -89,12 +101,20 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define IPV4_PORT ESD_DEFAULT_PORT #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", + #ifdef USE_TCP_SOCKETS + #include "module-esound-protocol-tcp-symdef.h" + #else + #include "module-esound-protocol-unix-symdef.h" + #endif PA_MODULE_DESCRIPTION("EsounD protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("sink= source= public= cookie= "SOCKET_USAGE) #else #error "Broken build system" #endif +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_VERSION(PACKAGE_VERSION) + static const char* const valid_modargs[] = { MODULE_ARGUMENTS #ifdef USE_TCP_SOCKETS diff --git a/polyp/module-sine.c b/polyp/module-sine.c index 458b87883..393f929aa 100644 --- a/polyp/module-sine.c +++ b/polyp/module-sine.c @@ -33,6 +33,7 @@ #include "xmalloc.h" #include "namereg.h" #include "log.h" +#include "module-sine-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Sine wave generator") diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index 1a720f3b5..2e22258ac 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -46,17 +46,19 @@ #include "socket-client.h" #include "socket-util.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_VERSION(PACKAGE_VERSION) - #ifdef TUNNEL_SINK +#include "module-tunnel-sink-symdef.h" PA_MODULE_DESCRIPTION("Tunnel module for sinks") PA_MODULE_USAGE("server= sink= cookie= format= channels= rate= sink_name=") #else +#include "module-tunnel-source-symdef.h" PA_MODULE_DESCRIPTION("Tunnel module for sources") PA_MODULE_USAGE("server= source= cookie= format= channels= rate= source_name=") #endif +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_VERSION(PACKAGE_VERSION) + #define DEFAULT_SINK_NAME "tunnel" #define DEFAULT_SOURCE_NAME "tunnel" diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index ae69f9cb6..23433c8f2 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -38,25 +38,23 @@ #include "xmalloc.h" #include "namereg.h" #include "log.h" +#include "x11wrap.h" +#include "module-x11-bell-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("X11 Bell interceptor") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink= sample= display=") -struct x11_source { - struct pa_io_event *io_event; - struct x11_source *next; -}; - struct userdata { struct pa_core *core; - Display *display; - struct x11_source *x11_sources; int xkb_event_base; - char *sink_name; char *scache_item; + Display *display; + + struct pa_x11_wrapper *x11_wrapper; + struct pa_x11_client *x11_client; }; static const char* const valid_modargs[] = { @@ -79,35 +77,22 @@ static int ring_bell(struct userdata *u, int percent) { return 0; } -static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { +static int x11_event_callback(struct pa_x11_wrapper *w, XEvent *e, void *userdata) { + XkbBellNotifyEvent *bne; struct userdata *u = userdata; - assert(u); - - while (XPending(u->display)) { - XEvent e; - XkbBellNotifyEvent *bne; - XNextEvent(u->display, &e); + assert(w && e && u && u->x11_wrapper == w); - if (((XkbEvent*) &e)->any.xkb_type != XkbBellNotify) - continue; + if (((XkbEvent*) e)->any.xkb_type != XkbBellNotify) + return 0; - bne = ((XkbBellNotifyEvent*) &e); - - if (ring_bell(u, bne->percent) < 0) { - pa_log(__FILE__": Ringing bell failed, reverting to X11 device bell.\n"); - XkbForceDeviceBell(u->display, bne->device, bne->bell_class, bne->bell_id, bne->percent); - } + bne = (XkbBellNotifyEvent*) e; + + if (ring_bell(u, bne->percent) < 0) { + pa_log(__FILE__": Ringing bell failed, reverting to X11 device bell.\n"); + XkbForceDeviceBell(pa_x11_wrapper_get_display(w), bne->device, bne->bell_class, bne->bell_id, bne->percent); } -} -static void new_io_source(struct userdata *u, int fd) { - struct x11_source *s; - - s = pa_xmalloc(sizeof(struct x11_source)); - s->io_event = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, io_callback, u); - assert(s->io_event); - s->next = u->x11_sources; - u->x11_sources = s; + return 1; } int pa__init(struct pa_core *c, struct pa_module*m) { @@ -124,18 +109,15 @@ int pa__init(struct pa_core *c, struct pa_module*m) { m->userdata = u = pa_xmalloc(sizeof(struct userdata)); u->core = c; - u->display = NULL; - u->x11_sources = NULL; u->scache_item = pa_xstrdup(pa_modargs_get_value(ma, "sample", "x11-bell")); u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + u->x11_client = NULL; - if (!(u->display = XOpenDisplay(pa_modargs_get_value(ma, "display", NULL)))) { - pa_log(__FILE__": XOpenDisplay() failed\n"); + if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) goto fail; - } - - new_io_source(u, ConnectionNumber(u->display)); + u->display = pa_x11_wrapper_get_display(u->x11_wrapper); + major = XkbMajorVersion; minor = XkbMinorVersion; @@ -147,6 +129,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { major = XkbMajorVersion; minor = XkbMinorVersion; + if (!XkbQueryExtension(u->display, NULL, &u->xkb_event_base, NULL, &major, &minor)) { pa_log(__FILE__": XkbQueryExtension() failed\n"); goto fail; @@ -157,6 +140,8 @@ int pa__init(struct pa_core *c, struct pa_module*m) { XkbSetAutoResetControls(u->display, XkbAudibleBellMask, &auto_ctrls, &auto_values); XkbChangeEnabledControls(u->display, XkbUseCoreKbd, XkbAudibleBellMask, 0); + u->x11_client = pa_x11_client_new(u->x11_wrapper, x11_event_callback, u); + pa_modargs_free(ma); return 0; @@ -173,17 +158,14 @@ void pa__done(struct pa_core *c, struct pa_module*m) { struct userdata *u = m->userdata; assert(c && m && u); - while (u->x11_sources) { - struct x11_source *s = u->x11_sources; - u->x11_sources = u->x11_sources->next; - c->mainloop->io_free(s->io_event); - pa_xfree(s); - } - pa_xfree(u->scache_item); pa_xfree(u->sink_name); - - if (u->display) - XCloseDisplay(u->display); + + if (u->x11_client) + pa_x11_client_free(u->x11_client); + + if (u->x11_wrapper) + pa_x11_wrapper_unref(u->x11_wrapper); + pa_xfree(u); } diff --git a/polyp/module-x11-publish.c b/polyp/module-x11-publish.c new file mode 100644 index 000000000..fd4df4ad9 --- /dev/null +++ b/polyp/module-x11-publish.c @@ -0,0 +1,167 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include "module.h" +#include "sink.h" +#include "scache.h" +#include "modargs.h" +#include "xmalloc.h" +#include "namereg.h" +#include "log.h" +#include "x11wrap.h" +#include "util.h" + +#include "module-x11-publish-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("X11 Credential Publisher") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("display=") + +static const char* const valid_modargs[] = { + "display", + "sink", + "source", + NULL +}; + +struct userdata { + struct pa_core *core; + struct pa_x11_wrapper *x11_wrapper; + Display *display; + char *id; +}; + +static void set_x11_prop(Display *d, const char *name, const char *data) { + Atom a = XInternAtom(d, name, False); + XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (unsigned char*) data, strlen(data)+1); +} + +static void del_x11_prop(Display *d, const char *name) { + Atom a = XInternAtom(d, name, False); + XDeleteProperty(d, RootWindow(d, 0), a); +} + +static char* get_x11_prop(Display *d, const char *name, char *p, size_t l) { + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long nbytes_after; + unsigned char *prop; + + Atom a = XInternAtom(d, name, False); + if (XGetWindowProperty(d, RootWindow(d, 0), a, 0, (l+2)/4, False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop) != Success) + return NULL; + + memcpy(p, prop, nitems); + p[nitems] = 0; + + XFree(prop); + return p; +} + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + struct pa_modargs *ma = NULL; + char hn[256], un[128]; + const char *t; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments\n"); + goto fail; + } + + m->userdata = u = pa_xmalloc(sizeof(struct userdata)); + u->core = c; + u->id = NULL; + + if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) + goto fail; + + u->display = pa_x11_wrapper_get_display(u->x11_wrapper); + + pa_get_host_name(hn, sizeof(hn)); + pa_get_user_name(un, sizeof(un)); + + u->id = pa_sprintf_malloc("%s@%s/%u", un, hn, (unsigned) getpid()); + + set_x11_prop(u->display, "POLYP_SERVER", hn); + set_x11_prop(u->display, "POLYP_ID", u->id); + + if ((t = pa_modargs_get_value(ma, "source", NULL))) + set_x11_prop(u->display, "POLYP_SOURCE", t); + + if ((t = pa_modargs_get_value(ma, "sink", NULL))) + set_x11_prop(u->display, "POLYP_SINK", t); + + pa_modargs_free(ma); + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(c, m); + return -1; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata*u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + if (u->x11_wrapper) { + char t[256]; + + /* Yes, here is a race condition */ + if (!get_x11_prop(u->display, "POLYP_ID", t, sizeof(t)) || strcmp(t, u->id)) + pa_log("WARNING: Polypaudio information vanished from X11!\n"); + else { + del_x11_prop(u->display, "POLYP_ID"); + del_x11_prop(u->display, "POLYP_SERVER"); + del_x11_prop(u->display, "POLYP_SINK"); + del_x11_prop(u->display, "POLYP_SOURCE"); + XSync(u->display, False); + } + } + + if (u->x11_wrapper) + pa_x11_wrapper_unref(u->x11_wrapper); + + pa_xfree(u->id); + pa_xfree(u); +} + diff --git a/polyp/module.h b/polyp/module.h index f422132ad..7380f795c 100644 --- a/polyp/module.h +++ b/polyp/module.h @@ -58,14 +58,10 @@ void pa_module_unload_request(struct pa_module *m); void pa_module_set_used(struct pa_module*m, int used); -/* prototypes for the module's entry points */ -int pa__init(struct pa_core *c, struct pa_module*m); -void pa__done(struct pa_core *c, struct pa_module*m); - -#define PA_MODULE_AUTHOR(s) const char *pa__get_author(void) { return s; } -#define PA_MODULE_DESCRIPTION(s) const char *pa__get_description(void) { return s; } -#define PA_MODULE_USAGE(s) const char *pa__get_usage(void) { return s; } -#define PA_MODULE_VERSION(s) const char *pa__get_version(void) { return s; } +#define PA_MODULE_AUTHOR(s) const char * pa__get_author(void) { return s; } +#define PA_MODULE_DESCRIPTION(s) const char * pa__get_description(void) { return s; } +#define PA_MODULE_USAGE(s) const char * pa__get_usage(void) { return s; } +#define PA_MODULE_VERSION(s) const char * pa__get_version(void) { return s; } struct pa_modinfo *pa_module_get_info(struct pa_module *m); diff --git a/polyp/namereg.c b/polyp/namereg.c index e2f65efd3..cc25ea2b6 100644 --- a/polyp/namereg.c +++ b/polyp/namereg.c @@ -100,15 +100,11 @@ const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_nam void pa_namereg_unregister(struct pa_core *c, const char *name) { struct namereg_entry *e; - int r; assert(c && name); - e = pa_hashmap_get(c->namereg, name); + e = pa_hashmap_remove(c->namereg, name); assert(e); - r = pa_hashmap_remove(c->namereg, name); - assert(r >= 0); - pa_xfree(e->name); pa_xfree(e); } diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index e49b25d40..623a89b33 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -43,8 +43,6 @@ #define DEFAULT_TIMEOUT (10) -#define ENV_AUTOSPAWNED "POLYP_AUTOSPAWNED" - struct pa_context { int ref; diff --git a/polyp/props.c b/polyp/props.c new file mode 100644 index 000000000..014059ec0 --- /dev/null +++ b/polyp/props.c @@ -0,0 +1,112 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "xmalloc.h" +#include "props.h" +#include "log.h" + +struct pa_property { + char *name; /* Points to memory allocated by the property subsystem */ + void *data; /* Points to memory maintained by the caller */ +}; + +/* Allocate a new property object */ +static struct pa_property* property_new(const char *name, void *data) { + struct pa_property* p; + assert(name && data); + + p = pa_xmalloc(sizeof(struct pa_property)); + p->name = pa_xstrdup(name); + p->data = data; + + return p; +} + +/* Free a property object */ +static void property_free(struct pa_property *p) { + assert(p); + + pa_xfree(p->name); + pa_xfree(p); +} + +void* pa_property_get(struct pa_core *c, const char *name) { + struct pa_property *p; + assert(c && name && c->properties); + + if (!(p = pa_hashmap_get(c->properties, name))) + return NULL; + + return p->data; +} + +int pa_property_set(struct pa_core *c, const char *name, void *data) { + struct pa_property *p; + assert(c && name && data && c->properties); + + if (pa_hashmap_get(c->properties, name)) + return -1; + + p = property_new(name, data); + pa_hashmap_put(c->properties, p->name, p); + return 0; +} + +int pa_property_remove(struct pa_core *c, const char *name) { + struct pa_property *p; + assert(c && name && c->properties); + + if (!(p = pa_hashmap_remove(c->properties, name))) + return -1; + + property_free(p); + return 0; +} + +void pa_property_init(struct pa_core *c) { + assert(c); + + c->properties = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); +} + +void pa_property_cleanup(struct pa_core *c) { + assert(c); + + if (!c->properties) + return; + + assert(!pa_hashmap_ncontents(c->properties)); + + pa_hashmap_free(c->properties, NULL, NULL); + c->properties = NULL; + +} + +void pa_property_dump(struct pa_core *c, struct pa_strbuf *s) { + void *state = NULL; + struct pa_property *p; + assert(c && s); + + while ((p = pa_hashmap_iterate(c->properties, &state, NULL))) + pa_strbuf_printf(s, "[%s] -> [%p]\n", p->name, p->data); +} diff --git a/polyp/props.h b/polyp/props.h new file mode 100644 index 000000000..f19e9260f --- /dev/null +++ b/polyp/props.h @@ -0,0 +1,55 @@ +#ifndef foopropshfoo +#define foopropshfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "core.h" +#include "strbuf.h" + +/* The property subsystem is to be used to share data between + * modules. Consider them to be kind of "global" variables for a + * core. Why not use the hashmap functions directly? The hashmap + * functions copy neither the key nor value, while this property + * system copies the key. Users of this system have to think about + * reference counting themselves. */ + +/* Return a pointer to the value of the specified property. */ +void* pa_property_get(struct pa_core *c, const char *name); + +/* Set the property 'name' to 'data'. This function fails in case a + * property by this name already exists. The property data is not + * copied or reference counted. This is the caller's job. */ +int pa_property_set(struct pa_core *c, const char *name, void *data); + +/* Remove the specified property. Return non-zero on failure */ +int pa_property_remove(struct pa_core *c, const char *name); + +/* Free all memory used by the property system */ +void pa_property_cleanup(struct pa_core *c); + +/* Initialize the properties subsystem */ +void pa_property_init(struct pa_core *c); + +/* Dump the current set of properties */ +void pa_property_dump(struct pa_core *c, struct pa_strbuf *s); + +#endif diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 7af8bdda4..6f3f82be5 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -1869,7 +1869,7 @@ static void command_get_autoload_info_list(struct pa_pdispatch *pd, uint32_t com struct pa_autoload_entry *a; void *state = NULL; - while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state))) + while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state, NULL))) autoload_fill_tagstruct(reply, a); } diff --git a/polyp/x11wrap.c b/polyp/x11wrap.c new file mode 100644 index 000000000..a1a9732a8 --- /dev/null +++ b/polyp/x11wrap.c @@ -0,0 +1,235 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +#include "llist.h" +#include "x11wrap.h" +#include "xmalloc.h" +#include "log.h" +#include "props.h" + +struct pa_x11_client; + +struct pa_x11_internal { + PA_LLIST_FIELDS(struct pa_x11_internal); + struct pa_x11_wrapper *wrapper; + struct pa_io_event* io_event; + int fd; +}; + +struct pa_x11_wrapper { + struct pa_core *core; + int ref; + + char *property_name; + Display *display; + + struct pa_defer_event* defer_event; + struct pa_io_event* io_event; + + PA_LLIST_HEAD(struct pa_x11_client, clients); + PA_LLIST_HEAD(struct pa_x11_internal, internals); +}; + +struct pa_x11_client { + PA_LLIST_FIELDS(struct pa_x11_client); + struct pa_x11_wrapper *wrapper; + int (*callback)(struct pa_x11_wrapper *w, XEvent *e, void *userdata); + void *userdata; +}; + +/* Dispatch all pending X11 events */ +static void work(struct pa_x11_wrapper *w) { + assert(w && w->ref >= 1); + + while (XPending(w->display)) { + struct pa_x11_client *c; + XEvent e; + XNextEvent(w->display, &e); + + for (c = w->clients; c; c = c->next) { + assert(c->callback); + if (c->callback(w, &e, c->userdata) != 0) + break; + } + } +} + +/* IO notification event for the X11 display connection */ +static void display_io_event(struct pa_mainloop_api *m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { + struct pa_x11_wrapper *w = userdata; + assert(m && e && fd >= 0 && w && w->ref >= 1); + work(w); +} + +/* Deferred notification event. Called once each main loop iteration */ +static void defer_event(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { + struct pa_x11_wrapper *w = userdata; + assert(m && e && w && w->ref >= 1); + work(w); +} + +/* IO notification event for X11 internal connections */ +static void internal_io_event(struct pa_mainloop_api *m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { + struct pa_x11_wrapper *w = userdata; + assert(m && e && fd >= 0 && w && w->ref >= 1); + + XProcessInternalConnection(w->display, fd); +} + +/* Add a new IO source for the specified X11 internal connection */ +static struct pa_x11_internal* x11_internal_add(struct pa_x11_wrapper *w, int fd) { + struct pa_x11_internal *i; + assert(i && fd >= 0); + + i = pa_xmalloc(sizeof(struct pa_x11_internal)); + i->wrapper = w; + i->io_event = w->core->mainloop->io_new(w->core->mainloop, fd, PA_IO_EVENT_INPUT, internal_io_event, w); + i->fd = fd; + + PA_LLIST_PREPEND(struct pa_x11_internal, w->internals, i); + return i; +} + +/* Remove an IO source for an X11 internal connection */ +void x11_internal_remove(struct pa_x11_wrapper *w, struct pa_x11_internal *i) { + assert(i); + + PA_LLIST_REMOVE(struct pa_x11_internal, w->internals, i); + w->core->mainloop->io_free(i->io_event); + pa_xfree(i); +} + +/* Implementation of XConnectionWatchProc */ +static void x11_watch(Display *display, XPointer userdata, int fd, Bool opening, XPointer *watch_data) { + struct pa_x11_wrapper *w = (struct pa_x11_wrapper*) userdata; + assert(display && w && fd >= 0); + + if (opening) + *watch_data = (XPointer) x11_internal_add(w, fd); + else + x11_internal_remove(w, (struct pa_x11_internal*) *watch_data); +} + +static struct pa_x11_wrapper* x11_wrapper_new(struct pa_core *c, const char *name, const char *t) { + struct pa_x11_wrapper*w; + Display *d; + int r; + + if (!(d = XOpenDisplay(name))) { + pa_log(__FILE__": XOpenDisplay() failed\n"); + return NULL; + } + + w = pa_xmalloc(sizeof(struct pa_x11_wrapper)); + w->core = c; + w->ref = 1; + w->property_name = pa_xstrdup(t); + w->display = d; + + PA_LLIST_HEAD_INIT(struct pa_x11_client, w->clients); + PA_LLIST_HEAD_INIT(struct pa_x11_internal, w->internals); + + w->defer_event = c->mainloop->defer_new(c->mainloop, defer_event, w); + w->io_event = c->mainloop->io_new(c->mainloop, ConnectionNumber(d), PA_IO_EVENT_INPUT, display_io_event, w); + + XAddConnectionWatch(d, x11_watch, (XPointer) w); + + r = pa_property_set(c, w->property_name, w); + assert(r >= 0); + + return w; +} + +static void x11_wrapper_free(struct pa_x11_wrapper*w) { + int r; + assert(w); + + r = pa_property_remove(w->core, w->property_name); + assert(r >= 0); + + assert(!w->clients); + + XRemoveConnectionWatch(w->display, x11_watch, (XPointer) w); + XCloseDisplay(w->display); + + w->core->mainloop->io_free(w->io_event); + w->core->mainloop->defer_free(w->defer_event); + + while (w->internals) + x11_internal_remove(w, w->internals); + + pa_xfree(w->property_name); + pa_xfree(w); +} + +struct pa_x11_wrapper* pa_x11_wrapper_get(struct pa_core *c, const char *name) { + char t[256]; + struct pa_x11_wrapper *w; + assert(c); + + snprintf(t, sizeof(t), "x11-wrapper%s%s", name ? "-" : "", name ? name : ""); + if ((w = pa_property_get(c, t))) + return pa_x11_wrapper_ref(w); + + return x11_wrapper_new(c, name, t); +} + +struct pa_x11_wrapper* pa_x11_wrapper_ref(struct pa_x11_wrapper *w) { + assert(w && w->ref >= 1); + w->ref++; + return w; +} + +void pa_x11_wrapper_unref(struct pa_x11_wrapper* w) { + assert(w && w->ref >= 1); + + if (!(--w->ref)) + x11_wrapper_free(w); +} + +Display *pa_x11_wrapper_get_display(struct pa_x11_wrapper *w) { + assert(w && w->ref >= 1); + return w->display; +} + +struct pa_x11_client* pa_x11_client_new(struct pa_x11_wrapper *w, int (*cb)(struct pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata) { + struct pa_x11_client *c; + assert(w && w->ref >= 1); + + c = pa_xmalloc(sizeof(struct pa_x11_client)); + c->wrapper = w; + c->callback = cb; + c->userdata = userdata; + + PA_LLIST_PREPEND(struct pa_x11_client, w->clients, c); + + return c; +} + +void pa_x11_client_free(struct pa_x11_client *c) { + assert(c && c->wrapper && c->wrapper->ref >= 1); + + PA_LLIST_REMOVE(struct pa_x11_client, c->wrapper->clients, c); + pa_xfree(c); +} diff --git a/polyp/x11wrap.h b/polyp/x11wrap.h new file mode 100644 index 000000000..79c690159 --- /dev/null +++ b/polyp/x11wrap.h @@ -0,0 +1,52 @@ +#ifndef foox11wraphfoo +#define foox11wraphfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "core.h" + +struct pa_x11_wrapper; + +/* Return the X11 wrapper for this core. In case no wrapper was + existant before, allocate a new one */ +struct pa_x11_wrapper* pa_x11_wrapper_get(struct pa_core *c, const char *name); + +/* Increase the wrapper's reference count by one */ +struct pa_x11_wrapper* pa_x11_wrapper_ref(struct pa_x11_wrapper *w); + +/* Decrease the reference counter of an X11 wrapper object */ +void pa_x11_wrapper_unref(struct pa_x11_wrapper* w); + +/* Return the X11 display object for this connection */ +Display *pa_x11_wrapper_get_display(struct pa_x11_wrapper *w); + +struct pa_x11_client; + +/* Register an X11 client, that is called for each X11 event */ +struct pa_x11_client* pa_x11_client_new(struct pa_x11_wrapper *w, int (*cb)(struct pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata); + +/* Free an X11 client object */ +void pa_x11_client_free(struct pa_x11_client *c); + +#endif From cd3ba7d0f745f8063cc018aeca320939ef3cd637 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 1 Nov 2004 23:37:36 +0000 Subject: [PATCH 0262/1514] Apply Joe Marcus Clarke's FreeBSD patches git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@269 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 6 +++++- polyp/Makefile.am | 4 ++-- polyp/packet.h | 2 +- polyp/polyplib-context.c | 1 + polyp/socket-util.c | 20 +++++++++++++++++++- polyp/util.c | 30 +++++++++++++++++++++++++++--- 6 files changed, 55 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 14a6842d1..ddf0a3411 100644 --- a/configure.ac +++ b/configure.ac @@ -74,11 +74,15 @@ AC_FUNC_REALLOC AC_FUNC_SETPGRP AC_FUNC_VPRINTF AC_TYPE_SIGNAL -AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul pow strcasecmp putenv strchr strpbrk strdup]) +AC_TYPE_UID_T +AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul strcasecmp putenv strchr strpbrk strdup getgrgid_r getpwuid_r regcomp]) +AC_CHECK_LIB(m, pow) +AC_CHECK_FUNCS(pow) AC_FUNC_STAT AC_HEADER_SYS_WAIT AC_C_BIGENDIAN +AC_FUNC_GETGROUPS AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS='']) AC_SUBST(CAP_LIBS) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index d90d32295..e97ed94db 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -624,7 +624,7 @@ endif ### Some minor stuff suid: polypaudio - chown root:root $< + chown root $< chmod u+s $< esdcompat.sh: esdcompat.sh.in Makefile @@ -643,7 +643,7 @@ daemon.conf: daemon.conf.in Makefile -e 's,@DEFAULT_CONFIG_FILE\@,$(polypconfdir)/daemon.conf,g' < $< > $@ install-exec-hook: - chown root:root $(DESTDIR)$(bindir)/polypaudio + chown root $(DESTDIR)$(bindir)/polypaudio chmod u+s $(DESTDIR)$(bindir)/polypaudio $(SYMDEF_FILES): module-defs.h.m4 diff --git a/polyp/packet.h b/polyp/packet.h index 8bea07e19..8f5cb8354 100644 --- a/polyp/packet.h +++ b/polyp/packet.h @@ -23,7 +23,7 @@ ***/ #include -#include +#include struct pa_packet { enum { PA_PACKET_APPENDED, PA_PACKET_DYNAMIC } type; diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index cf1a8e60c..1a25523fd 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "polyplib-internal.h" #include "polyplib-context.h" diff --git a/polyp/socket-util.c b/polyp/socket-util.c index 499739bd3..4e1eb6ab8 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -30,13 +30,16 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include +#include +#include #include #include "socket-util.h" @@ -94,9 +97,11 @@ int pa_socket_low_delay(int fd) { int priority; assert(fd >= 0); +#ifdef SO_PRIORITY priority = 7; if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0) return -1; +#endif return 0; } @@ -109,12 +114,25 @@ int pa_socket_tcp_low_delay(int fd) { ret = pa_socket_low_delay(fd); on = 1; +#if defined(SOL_TCP) || defined(IPPROTO_TCP) +#if defined(SOL_TCP) if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) +#else + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) +#endif ret = -1; +#endif +#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || \ + defined(IPPROTO_IP)) tos = IPTOS_LOWDELAY; +#ifdef SOL_IP if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0) +#else + if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) +#endif ret = -1; +#endif return ret; diff --git a/polyp/util.c b/polyp/util.c index 9697a1ebe..b138266b3 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -209,7 +209,13 @@ char *pa_get_user_name(char *s, size_t l) { if (!(p = getenv("LOGNAME"))) if (!(p = getenv("USERNAME"))) { +#ifdef HAVE_GETPWUID_R if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { +#else + /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) + * that do not support getpwuid_r. */ + if ((r = getpwuid(getuid())) == NULL) { +#endif snprintf(s, l, "%lu", (unsigned long) getuid()); return s; } @@ -445,11 +451,17 @@ int pa_parse_resample_method(const char *string) { static int is_group(gid_t gid, const char *name) { struct group group, *result = NULL; - long n = sysconf(_SC_GETGR_R_SIZE_MAX); + long n; void *data; int r = -1; - - assert(n > 0); + +#ifdef HAVE_GETGRGID_R +#ifdef _SC_GETGR_R_SIZE_MAX + n = sysconf(_SC_GETGR_R_SIZE_MAX); +#else + n = -1; +#endif + if (n < 0) n = 512; data = pa_xmalloc(n); if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) { @@ -462,6 +474,18 @@ static int is_group(gid_t gid, const char *name) { finish: pa_xfree(data); +#else + /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not + * support getgrgid_r. */ + if ((result = getgrgid(gid)) == NULL) { + pa_log(__FILE__ ": getgrgid(%u) failed: %s\n", gid, strerror(errno)); + goto finish; + } + + r = strcmp(name, result->gr_name) == 0; + +finish: +#endif return r; } From 1f6a90c963356d3889cce4717a1a6b03cb039254 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 4 Nov 2004 18:56:09 +0000 Subject: [PATCH 0263/1514] fix client libaryr in case no latency interpolation is required git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@270 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-stream.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 286702b24..312f1debf 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -560,10 +560,12 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); - if (!s->corked && b) - s->ipol_usec = pa_stream_get_interpolated_time(s); - else if (s->corked && !b) - gettimeofday(&s->ipol_timestamp, NULL); + if (s->interpolate) { + if (!s->corked && b) + s->ipol_usec = pa_stream_get_interpolated_time(s); + else if (s->corked && !b) + gettimeofday(&s->ipol_timestamp, NULL); + } s->corked = b; From 344ced4622ffc9d38ab0388d3ed44fe55ce5e86c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 4 Nov 2004 18:57:31 +0000 Subject: [PATCH 0264/1514] add some more comments git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@271 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/util.c | 74 +++++++++++++++++++++++++++++++++++++++++++------ polyp/util.h | 3 ++ polyp/xmalloc.c | 19 +++++++------ 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/polyp/util.c b/polyp/util.c index b138266b3..794ae5145 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -50,16 +50,20 @@ #include "xmalloc.h" #include "log.h" +/** Make a file descriptor nonblock. Doesn't do any error checking */ void pa_make_nonblock_fd(int fd) { int v; + assert(fd >= 0); if ((v = fcntl(fd, F_GETFL)) >= 0) if (!(v & O_NONBLOCK)) fcntl(fd, F_SETFL, v|O_NONBLOCK); } +/** Creates a directory securely */ int pa_make_secure_dir(const char* dir) { struct stat st; + assert(dir); if (mkdir(dir, 0700) < 0) if (errno != EEXIST) @@ -78,6 +82,8 @@ fail: return -1; } +/** Calls read() in a loop. Makes sure that as much as 'size' bytes, + * unless EOF is reached or an error occured */ ssize_t pa_loop_read(int fd, void*data, size_t size) { ssize_t ret = 0; assert(fd >= 0 && data && size); @@ -99,6 +105,7 @@ ssize_t pa_loop_read(int fd, void*data, size_t size) { return ret; } +/** Similar to pa_loop_read(), but wraps write() */ ssize_t pa_loop_write(int fd, const void*data, size_t size) { ssize_t ret = 0; assert(fd >= 0 && data && size); @@ -120,10 +127,16 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) { return ret; } +/* Print a warning messages in case that the given signal is not + * blocked or trapped */ void pa_check_signal_is_blocked(int sig) { struct sigaction sa; sigset_t set; + /* If POSIX threads are supported use thread-aware + * pthread_sigmask() function, to check if the signal is + * blocked. Otherwise fall back to sigprocmask() */ + #ifdef HAVE_PTHREAD if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) { #endif @@ -137,6 +150,8 @@ void pa_check_signal_is_blocked(int sig) { if (sigismember(&set, sig)) return; + + /* Check whether the signal is trapped */ if (sigaction(sig, NULL, &sa) < 0) { pa_log(__FILE__": sigaction() failed: %s\n", strerror(errno)); @@ -149,7 +164,8 @@ void pa_check_signal_is_blocked(int sig) { pa_log(__FILE__": WARNING: %s is not trapped. This might cause malfunction!\n", pa_strsignal(sig)); } -/* The following is based on an example from the GNU libc documentation */ +/* The following function is based on an example from the GNU libc + * documentation. This function is similar to GNU's asprintf(). */ char *pa_sprintf_malloc(const char *format, ...) { int size = 100; char *c = NULL; @@ -176,6 +192,8 @@ char *pa_sprintf_malloc(const char *format, ...) { } } +/* Same as the previous function, but use a va_list instead of an + * ellipsis */ char *pa_vsprintf_malloc(const char *format, va_list ap) { int size = 100; char *c = NULL; @@ -199,11 +217,12 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) { } } - +/* Return the current username in the specified string buffer. */ char *pa_get_user_name(char *s, size_t l) { struct passwd pw, *r; char buf[1024]; char *p; + assert(s && l > 0); if (!(p = getenv("USER"))) if (!(p = getenv("LOGNAME"))) @@ -222,21 +241,50 @@ char *pa_get_user_name(char *s, size_t l) { p = r->pw_name; } - - snprintf(s, l, "%s", p); - return s; + + return pa_strlcpy(s, p, l); } +/* Return the current hostname in the specified buffer. */ char *pa_get_host_name(char *s, size_t l) { + assert(s && l > 0); gethostname(s, l); s[l-1] = 0; return s; } +/* Return the home directory of the current user */ +char *pa_get_home(char *s, size_t l) { + char *e; + char buf[1024]; + struct passwd pw, *r; + assert(s && l); + + if ((e = getenv("HOME"))) + return pa_strlcpy(s, e, l); + + if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) + return NULL; + + return pa_strlcpy(s, r->pw_dir, l); +} + +/* Similar to OpenBSD's strlcpy() function */ +char *pa_strlcpy(char *b, const char *s, size_t l) { + assert(b && s && l > 0); + + strncpy(b, s, l); + b[l-1] = 0; + return b; +} + +/* Calculate the difference between the two specfified timeval + * timestamsps. */ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { pa_usec_t r; assert(a && b); + /* Check which whan is the earlier time and swap the two arguments if reuqired. */ if (pa_timeval_cmp(a, b) < 0) { const struct timeval *c; c = a; @@ -244,8 +292,10 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { b = c; } + /* Calculate the second difference*/ r = ((pa_usec_t) a->tv_sec - b->tv_sec)* 1000000; + /* Calculate the microsecond difference */ if (a->tv_usec > b->tv_usec) r += ((pa_usec_t) a->tv_usec - b->tv_usec); else if (a->tv_usec < b->tv_usec) @@ -254,6 +304,7 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { return r; } +/* Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { assert(a && b); @@ -272,6 +323,7 @@ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { return 0; } +/* Return the time difference between now and the specified timestamp */ pa_usec_t pa_timeval_age(const struct timeval *tv) { struct timeval now; assert(tv); @@ -279,6 +331,7 @@ pa_usec_t pa_timeval_age(const struct timeval *tv) { return pa_timeval_diff(&now, tv); } +/* Add the specified time inmicroseconds to the specified timeval structure */ void pa_timeval_add(struct timeval *tv, pa_usec_t v) { unsigned long secs; assert(tv); @@ -289,6 +342,7 @@ void pa_timeval_add(struct timeval *tv, pa_usec_t v) { tv->tv_usec += v; + /* Normalize */ while (tv->tv_usec >= 1000000) { tv->tv_sec++; tv->tv_usec -= 1000000; @@ -297,12 +351,16 @@ void pa_timeval_add(struct timeval *tv, pa_usec_t v) { #define NICE_LEVEL (-15) +/* Raise the priority of the current process as much as possible and +sensible: set the nice level to -15 and enable realtime scheduling if +supportted.*/ + void pa_raise_priority(void) { + if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) pa_log(__FILE__": setpriority() failed: %s\n", strerror(errno)); - else - pa_log(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); - + else pa_log(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); + #ifdef _POSIX_PRIORITY_SCHEDULING { struct sched_param sp; diff --git a/polyp/util.h b/polyp/util.h index c5ffa7553..85da38d02 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -41,9 +41,12 @@ void pa_check_signal_is_blocked(int sig); char *pa_sprintf_malloc(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); char *pa_vsprintf_malloc(const char *format, va_list ap); +char *pa_strlcpy(char *b, const char *s, size_t l); + char *pa_get_user_name(char *s, size_t l); char *pa_get_host_name(char *s, size_t l); char *pa_get_binary_name(char *s, size_t l); +char *pa_get_home(char *s, size_t l); char *pa_path_get_filename(const char *p); diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c index 47f46bbe5..709e46e5e 100644 --- a/polyp/xmalloc.c +++ b/polyp/xmalloc.c @@ -30,19 +30,22 @@ #include "memory.h" #include "util.h" -#define MAX_ALLOC_SIZE (1024*1024*20) +/* Make sure not to allocate more than this much memory. */ +#define MAX_ALLOC_SIZE (1024*1024*20) /* 20MB */ -#undef malloc -#undef free -#undef realloc -#undef strndup -#undef strdup +/* #undef malloc */ +/* #undef free */ +/* #undef realloc */ +/* #undef strndup */ +/* #undef strdup */ +/** called in case of an OOM situation. Prints an error message and + * exits */ static void oom(void) { static const char e[] = "Not enough memory\n"; - pa_loop_write(2, e, sizeof(e)-1); + pa_loop_write(STDERR_FILENO, e, sizeof(e)-1); raise(SIGQUIT); - exit(1); + _exit(1); } void* pa_xmalloc(size_t size) { From 2aad9e3ae2aa53d13458faf148946cf7e7d87627 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 4 Nov 2004 20:01:13 +0000 Subject: [PATCH 0265/1514] compilation fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@272 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/xmalloc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c index 709e46e5e..981b3c924 100644 --- a/polyp/xmalloc.c +++ b/polyp/xmalloc.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "memory.h" #include "util.h" From 5844a33f0be1af942ee33feae38b9d46169fd61c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 4 Nov 2004 21:27:12 +0000 Subject: [PATCH 0266/1514] some commenting change alogrithm for checking for configuration files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@273 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 4 +-- polyp/client-conf.c | 48 +++++++++++++--------------- polyp/conf-parser.c | 8 ++--- polyp/conf-parser.h | 4 ++- polyp/daemon-conf.c | 76 +++++++++++++++++++------------------------- polyp/daemon-conf.h | 1 + polyp/module-match.c | 19 +++++++++-- polyp/util.c | 75 ++++++++++++++++++++++++++++++++++++++++--- polyp/util.h | 5 ++- 9 files changed, 156 insertions(+), 84 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index e97ed94db..1ed1b28fc 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -24,9 +24,7 @@ modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\" -AM_CFLAGS+=-DDEFAULT_SCRIPT_FILE=\"$(polypconfdir)/default.pa\" -AM_CFLAGS+=-DDEFAULT_CONFIG_FILE=\"$(polypconfdir)/daemon.conf\" -AM_CFLAGS+=-DDEFAULT_CLIENT_CONFIG_FILE=\"$(polypconfdir)/client.conf\" +AM_CFLAGS+=-DDEFAULT_CONFIG_DIR=\"$(polypconfdir)\" AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" AM_LDADD=$(PTHREAD_LIBS) -lm diff --git a/polyp/client-conf.c b/polyp/client-conf.c index b8a4c778e..47c5b49cf 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "client-conf.h" #include "xmalloc.h" @@ -29,13 +31,12 @@ #include "conf-parser.h" #include "util.h" -#ifndef DEFAULT_CLIENT_CONFIG_FILE -#define DEFAULT_CLIENT_CONFIG_FILE "/etc/polypaudio/client.conf" +#ifndef DEFAULT_CONFIG_DIR +#define DEFAULT_CONFIG_DIR "/etc/polypaudio" #endif -#ifndef DEFAULT_CLIENT_CONFIG_FILE_USER +#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR"/client.conf" #define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio/client.conf" -#endif #define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG" #define ENV_DEFAULT_SINK "POLYP_SINK" @@ -71,8 +72,9 @@ void pa_client_conf_free(struct pa_client_conf *c) { pa_xfree(c); } int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { - char *def = NULL; - int r; + FILE *f = NULL; + char *fn = NULL; + int r = -1; struct pa_config_item table[] = { { "daemon-binary", pa_config_parse_string, NULL }, @@ -91,29 +93,23 @@ int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { table[4].data = &c->default_server; table[5].data = &c->autospawn; - if (!filename) - filename = getenv(ENV_CLIENT_CONFIG_FILE); + f = filename ? + fopen((fn = pa_xstrdup(filename)), "r") : + pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn); - if (!filename) { - char *h; - - if ((h = getenv("HOME"))) { - def = pa_sprintf_malloc("%s/%s", h, DEFAULT_CLIENT_CONFIG_FILE_USER); - - if (!access(def, F_OK)) - filename = def; - else { - pa_xfree(def); - def = NULL; - } - } + if (!f && errno != EINTR) { + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno)); + goto finish; } - - if (!filename) - filename = DEFAULT_CLIENT_CONFIG_FILE; - r = pa_config_parse(filename, table, NULL); - pa_xfree(def); + r = pa_config_parse(fn, f, table, NULL); + +finish: + pa_xfree(fn); + + if (f) + fclose(f); + return r; } diff --git a/polyp/conf-parser.c b/polyp/conf-parser.c index 20e8e723b..3d922c209 100644 --- a/polyp/conf-parser.c +++ b/polyp/conf-parser.c @@ -89,13 +89,13 @@ static int parse_line(const char *filename, unsigned line, const struct pa_confi } -int pa_config_parse(const char *filename, const struct pa_config_item *t, void *userdata) { - FILE *f; +int pa_config_parse(const char *filename, FILE *f, const struct pa_config_item *t, void *userdata) { int r = -1; unsigned line = 0; + int do_close = !f; assert(filename && t); - if (!(f = fopen(filename, "r"))) { + if (!f && !(f = fopen(filename, "r"))) { if (errno == ENOENT) { r = 0; goto finish; @@ -123,7 +123,7 @@ int pa_config_parse(const char *filename, const struct pa_config_item *t, void * finish: - if (f) + if (do_close && f) fclose(f); return r; diff --git a/polyp/conf-parser.h b/polyp/conf-parser.h index a0eb52d0d..303308601 100644 --- a/polyp/conf-parser.h +++ b/polyp/conf-parser.h @@ -22,13 +22,15 @@ USA. ***/ +#include + struct pa_config_item { const char *lvalue; int (*parse)(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); void *data; }; -int pa_config_parse(const char *filename, const struct pa_config_item *t, void *userdata); +int pa_config_parse(const char *filename, FILE *f, const struct pa_config_item *t, void *userdata); int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index 8a0f94ac0..e87acd1d8 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -36,21 +36,14 @@ #include "strbuf.h" #include "conf-parser.h" -#ifndef DEFAULT_SCRIPT_FILE -#define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa" +#ifndef DEFAULT_CONFIG_DIR +#define DEFAULT_CONFIG_DIR "/etc/polypaudio" #endif -#ifndef DEFAULT_SCRIPT_FILE_USER +#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR"/default.pa" #define DEFAULT_SCRIPT_FILE_USER ".polypaudio/default.pa" -#endif - -#ifndef DEFAULT_CONFIG_FILE -#define DEFAULT_CONFIG_FILE "/etc/polypaudio/daemon.conf" -#endif - -#ifndef DEFAULT_CONFIG_FILE_USER +#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR"/daemon.conf" #define DEFAULT_CONFIG_FILE_USER ".polypaudio/daemon.conf" -#endif #define ENV_SCRIPT_FILE "POLYP_SCRIPT" #define ENV_CONFIG_FILE "POLYP_CONFIG" @@ -71,31 +64,17 @@ static const struct pa_daemon_conf default_conf = { .dl_search_path = NULL, .default_script_file = NULL, .log_target = PA_LOG_SYSLOG, - .resample_method = SRC_SINC_FASTEST + .resample_method = SRC_SINC_FASTEST, + .config_file = NULL, }; -char* default_file(const char *envvar, const char *global, const char *local) { - char *p, *h; - - assert(envvar && global && local); - - if ((p = getenv(envvar))) - return pa_xstrdup(p); - - if ((h = getenv("HOME"))) { - p = pa_sprintf_malloc("%s/%s", h, local); - if (!access(p, F_OK)) - return p; - - pa_xfree(p); - } - - return pa_xstrdup(global); -} - struct pa_daemon_conf* pa_daemon_conf_new(void) { + FILE *f; struct pa_daemon_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); - c->default_script_file = default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER); + + if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file))) + fclose(f); + #ifdef DLSEARCHPATH c->dl_search_path = pa_xstrdup(DLSEARCHPATH); #endif @@ -107,6 +86,7 @@ void pa_daemon_conf_free(struct pa_daemon_conf *c) { pa_xfree(c->script_commands); pa_xfree(c->dl_search_path); pa_xfree(c->default_script_file); + pa_xfree(c->config_file); pa_xfree(c); } @@ -163,8 +143,8 @@ int parse_resample_method(const char *filename, unsigned line, const char *lvalu } int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename) { - char *def = NULL; - int r; + int r = -1; + FILE *f = NULL; struct pa_config_item table[] = { { "verbose", pa_config_parse_bool, NULL }, @@ -195,11 +175,24 @@ int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename) { table[10].data = c; table[11].data = c; - if (!filename) - filename = def = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER); + pa_xfree(c->config_file); + c->config_file = NULL; + + f = filename ? + fopen(c->config_file = pa_xstrdup(filename), "r") : + pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file); + + if (!f && errno != EINTR) { + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno)); + goto finish; + } + + r = pa_config_parse(c->config_file, f, table, NULL); + +finish: + if (f) + fclose(f); - r = pa_config_parse(filename, table, NULL); - pa_xfree(def); return r; } @@ -220,7 +213,6 @@ int pa_daemon_conf_env(struct pa_daemon_conf *c) { char *pa_daemon_conf_dump(struct pa_daemon_conf *c) { struct pa_strbuf *s = pa_strbuf_new(); - char *d; static const char const* resample_methods[] = { "sinc-best-quality", @@ -230,8 +222,8 @@ char *pa_daemon_conf_dump(struct pa_daemon_conf *c) { "linear" }; - d = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER); - pa_strbuf_printf(s, "### Default configuration file: %s ###\n", d); + if (c->config_file) + pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file); pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose); pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize); @@ -248,7 +240,5 @@ char *pa_daemon_conf_dump(struct pa_daemon_conf *c) { assert(c->resample_method <= 4 && c->resample_method >= 0); pa_strbuf_printf(s, "resample-method = %s\n", resample_methods[c->resample_method]); - pa_xfree(d); - return pa_strbuf_tostring_free(s); } diff --git a/polyp/daemon-conf.h b/polyp/daemon-conf.h index 8be989da1..fc31117f2 100644 --- a/polyp/daemon-conf.h +++ b/polyp/daemon-conf.h @@ -46,6 +46,7 @@ struct pa_daemon_conf { char *script_commands, *dl_search_path, *default_script_file; enum pa_log_target log_target; int resample_method; + char *config_file; }; struct pa_daemon_conf* pa_daemon_conf_new(void); diff --git a/polyp/module-match.c b/polyp/module-match.c index 6689cc592..176c338f3 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -48,6 +48,13 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" +#ifndef DEFAULT_CONFIG_DIR +#define DEFAULT_CONFIG_DIR "/etc/polypaudio" +#endif + +#define DEFAULT_MATCH_TABLE_FILE DEFAULT_CONFIG_DIR"/match.table" +#define DEFAULT_MATCH_TABLE_FILE_USER ".polypaudio/.match.table" + static const char* const valid_modargs[] = { "table", NULL, @@ -69,9 +76,14 @@ static int load_rules(struct userdata *u, const char *filename) { int n = 0; int ret = -1; struct rule *end = NULL; + char *fn = NULL; - if (!(f = fopen(filename, "r"))) { - pa_log(__FILE__": failed to open file '%s': %s\n", filename, strerror(errno)); + f = filename ? + fopen(fn = pa_xstrdup(filename), "r") : + pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn); + + if (!f) { + pa_log(__FILE__": failed to open file '%s': %s\n", fn, strerror(errno)); goto finish; } @@ -135,6 +147,9 @@ finish: if (f) fclose(f); + if (fn) + pa_xfree(fn); + return ret; } diff --git a/polyp/util.c b/polyp/util.c index 794ae5145..6e97bae4a 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -254,7 +254,7 @@ char *pa_get_host_name(char *s, size_t l) { } /* Return the home directory of the current user */ -char *pa_get_home(char *s, size_t l) { +char *pa_get_home_dir(char *s, size_t l) { char *e; char buf[1024]; struct passwd pw, *r; @@ -353,8 +353,7 @@ void pa_timeval_add(struct timeval *tv, pa_usec_t v) { /* Raise the priority of the current process as much as possible and sensible: set the nice level to -15 and enable realtime scheduling if -supportted.*/ - +supported.*/ void pa_raise_priority(void) { if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) @@ -381,6 +380,7 @@ void pa_raise_priority(void) { #endif } +/* Reset the priority to normal, inverting the changes made by pa_raise_priority() */ void pa_reset_priority(void) { #ifdef _POSIX_PRIORITY_SCHEDULING { @@ -394,6 +394,7 @@ void pa_reset_priority(void) { setpriority(PRIO_PROCESS, 0, 0); } +/* Set the FD_CLOEXEC flag for a fd */ int pa_fd_set_cloexec(int fd, int b) { int v; assert(fd >= 0); @@ -409,6 +410,9 @@ int pa_fd_set_cloexec(int fd, int b) { return 0; } +/* Return the binary file name of the current process. Works on Linux + * only. This shoul be used for eyecandy only, don't rely on return + * non-NULL! */ char *pa_get_binary_name(char *s, size_t l) { char path[PATH_MAX]; int i; @@ -424,6 +428,8 @@ char *pa_get_binary_name(char *s, size_t l) { return s; } +/* Return a pointer to the filename inside a path (which is the last + * component). */ char *pa_path_get_filename(const char *p) { char *fn; @@ -433,6 +439,7 @@ char *pa_path_get_filename(const char *p) { return (char*) p; } +/* Try to parse a boolean string value.*/ int pa_parse_boolean(const char *v) { if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on")) @@ -443,6 +450,10 @@ int pa_parse_boolean(const char *v) { return -1; } +/* Split the specified string wherever one of the strings in delimiter + * occurs. Each time it is called returns a newly allocated string + * with pa_xmalloc(). The variable state points to, should be + * initiallized to NULL before the first call. */ char *pa_split(const char *c, const char *delimiter, const char**state) { const char *current = *state ? *state : c; size_t l; @@ -459,8 +470,10 @@ char *pa_split(const char *c, const char *delimiter, const char**state) { return pa_xstrndup(current, l); } +/* What is interpreted as whitespace? */ #define WHITESPACE " \t\n" +/* Split a string into words. Otherwise similar to pa_split(). */ char *pa_split_spaces(const char *c, const char **state) { const char *current = *state ? *state : c; size_t l; @@ -476,6 +489,7 @@ char *pa_split_spaces(const char *c, const char **state) { return pa_xstrndup(current, l); } +/* Return the name of an UNIX signal. Similar to GNU's strsignal() */ const char *pa_strsignal(int sig) { switch(sig) { case SIGINT: return "SIGINT"; @@ -490,6 +504,7 @@ const char *pa_strsignal(int sig) { } } +/* Parse a libsamplrate compatible resampling implementation */ int pa_parse_resample_method(const char *string) { assert(string); @@ -507,6 +522,7 @@ int pa_parse_resample_method(const char *string) { return -1; } +/* Check whether the specified GID and the group name match */ static int is_group(gid_t gid, const char *name) { struct group group, *result = NULL; long n; @@ -548,6 +564,7 @@ finish: return r; } +/* Check the current user is member of the specified group */ int pa_uid_in_group(const char *name, gid_t *gid) { gid_t *gids, tgid; long n = sysconf(_SC_NGROUPS_MAX); @@ -584,6 +601,7 @@ finish: return r; } +/* Lock or unlock a file entirely. (advisory) */ int pa_lock_fd(int fd, int b) { struct flock flock; @@ -601,6 +619,7 @@ int pa_lock_fd(int fd, int b) { return 0; } +/* Remove trailing newlines from a string */ char* pa_strip_nl(char *s) { assert(s); @@ -608,6 +627,7 @@ char* pa_strip_nl(char *s) { return s; } +/* Create a temporary lock file and lock it. */ int pa_lock_lockfile(const char *fn) { int fd; assert(fn); @@ -630,7 +650,7 @@ fail: return -1; } - +/* Unlock a temporary lcok file */ int pa_unlock_lockfile(int fd) { int r = 0; assert(fd >= 0); @@ -648,3 +668,50 @@ int pa_unlock_lockfile(int fd) { return r; } +/* Try to open a configuration file. If "env" is specified, open the + * value of the specified environment variable. Otherwise look for a + * file "local" in the home directory or a file "global" in global + * file system. If "result" is non-NULL, a pointer to a newly + * allocated buffer containing the used configuration file is + * stored there.*/ +FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) { + const char *e; + char h[PATH_MAX]; + + if (env && (e = getenv(env))) { + if (result) + *result = pa_xstrdup(e); + return fopen(e, "r"); + } + + if (local && pa_get_home_dir(h, sizeof(h))) { + FILE *f; + char *l; + + l = pa_sprintf_malloc("%s/%s", h, local); + f = fopen(l, "r"); + + if (f || errno != ENOENT) { + if (result) + *result = l; + else + pa_xfree(l); + return f; + } + + pa_xfree(l); + } + + if (!global) { + if (result) + *result = NULL; + errno = ENOENT; + return NULL; + } + + if (result) + *result = pa_xstrdup(global); + + return fopen(global, "r"); +} + diff --git a/polyp/util.h b/polyp/util.h index 85da38d02..0299148e0 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "gcc-printf.h" #include "sample.h" @@ -46,7 +47,7 @@ char *pa_strlcpy(char *b, const char *s, size_t l); char *pa_get_user_name(char *s, size_t l); char *pa_get_host_name(char *s, size_t l); char *pa_get_binary_name(char *s, size_t l); -char *pa_get_home(char *s, size_t l); +char *pa_get_home_dir(char *s, size_t l); char *pa_path_get_filename(const char *p); @@ -78,4 +79,6 @@ int pa_lock_fd(int fd, int b); int pa_lock_lockfile(const char *fn); int pa_unlock_lockfile(int fd); +FILE *pa_open_config_file(const char *env, const char *global, const char *local, char **result); + #endif From b55923a8d33a1c4ed2f892a0da36c9c679e7d828 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 7 Nov 2004 20:48:46 +0000 Subject: [PATCH 0267/1514] * Look for M4 in configure.ac * Share auth cookies in module-tunnel.c, module-x11-publish.c and native-protocol.c * disable TCP_NODELAY * publish auth cookie in module-x11-publish git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@274 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 5 +++ doc/todo | 6 +-- polyp/Makefile.am | 16 ++++--- polyp/authkey-prop.c | 87 ++++++++++++++++++++++++++++++++++++++ polyp/authkey-prop.h | 39 +++++++++++++++++ polyp/authkey.c | 6 +-- polyp/module-match.c | 2 +- polyp/module-tunnel.c | 43 ++++++++++++++++--- polyp/module-x11-publish.c | 46 +++++++++++++++++++- polyp/module.c | 2 + polyp/native-common.h | 2 + polyp/protocol-native.c | 43 ++++++++++++++++--- polyp/socket-util.c | 2 + polyp/util.c | 17 ++++++++ polyp/util.h | 2 + 15 files changed, 292 insertions(+), 26 deletions(-) create mode 100644 polyp/authkey-prop.c create mode 100644 polyp/authkey-prop.h diff --git a/configure.ac b/configure.ac index ddf0a3411..026d4d97b 100644 --- a/configure.ac +++ b/configure.ac @@ -115,6 +115,11 @@ AC_SUBST(GLIB12_LIBS) AC_SUBST(HAVE_GLIB12) AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) +AC_PATH_PROG([M4], [m4 gm4], [no]) +if test "x$M4" = xno ; then + AC_MSG_ERROR([m4 missing]) +fi + AC_MSG_CHECKING([for tcpwrap library and headers]) LIBWRAP_LIBS= saved_LIBS="$LIBS" diff --git a/doc/todo b/doc/todo index 8212ea89b..cfc4b0441 100644 --- a/doc/todo +++ b/doc/todo @@ -15,11 +15,11 @@ - X11: support for the X11 synchronization extension - X11: save auth info in root window - pass meta info for hearing impaired -- fall back to getpwnam if $HOME doesn't exist -- module-match: look in $HOME for table - limit all resources -- getaddrinfo +- check getaddrinfo results - add LGPL blurb to all concerning files +- non-fp mixing +- non-fp resampling ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 1ed1b28fc..b0b863e5e 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -84,6 +84,7 @@ modlib_LTLIBRARIES= \ libpstream-util.la \ libpdispatch.la \ libauthkey.la \ + libauthkey-prop.la \ libprotocol-simple.la \ libprotocol-esound.la \ libprotocol-native.la \ @@ -199,7 +200,7 @@ polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) polypaudio_LDFLAGS= -export-dynamic -dlopen force -#-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f)) +# -static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f)) libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version @@ -249,7 +250,7 @@ libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la lib libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h native-common.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la +libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libtagstruct_la_SOURCES = tagstruct.c tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version @@ -261,6 +262,9 @@ libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey_la_SOURCES = authkey.c authkey.h libauthkey_la_LDFLAGS = -avoid-version +libauthkey_prop_la_SOURCES = authkey-prop.c authkey-prop.h +libauthkey_prop_la_LDFLAGS = -avoid-version + libsocket_util_la_SOURCES = socket-util.c socket-util.h libsocket_util_la_LDFLAGS = -avoid-version @@ -348,11 +352,11 @@ module_match_la_LIBADD = $(AM_LIBADD) module_tunnel_sink_la_SOURCES = module-tunnel.c module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) module_tunnel_sink_la_LDFLAGS = -module -avoid-version -module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la +module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la module_tunnel_source_la_SOURCES = module-tunnel.c module_tunnel_source_la_LDFLAGS = -module -avoid-version -module_tunnel_source_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la +module_tunnel_source_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version @@ -477,7 +481,7 @@ module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA module_x11_publish_la_SOURCES = module-x11-publish.c module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_publish_la_LDFLAGS = -module -avoid-version -module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) libx11wrap.la +module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) libx11wrap.la libauthkey.la libauthkey-prop.la endif @@ -645,4 +649,4 @@ install-exec-hook: chmod u+s $(DESTDIR)$(bindir)/polypaudio $(SYMDEF_FILES): module-defs.h.m4 - m4 -Dfname="$@" $< > $@ + $(M4) -Dfname="$@" $< > $@ diff --git a/polyp/authkey-prop.c b/polyp/authkey-prop.c new file mode 100644 index 000000000..132279556 --- /dev/null +++ b/polyp/authkey-prop.c @@ -0,0 +1,87 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +#include "xmalloc.h" +#include "authkey-prop.h" +#include "props.h" +#include "log.h" + +struct authkey_data { + int ref; + size_t length; +}; + +int pa_authkey_prop_get(struct pa_core *c, const char *name, void *data, size_t len) { + struct authkey_data *a; + assert(c && name && data && len > 0); + + if (!(a = pa_property_get(c, name))) + return -1; + + assert(a->length == len); + memcpy(data, a+1, len); + return 0; +} + +int pa_authkey_prop_put(struct pa_core *c, const char *name, const void *data, size_t len) { + struct authkey_data *a; + assert(c && name); + + if (pa_property_get(c, name)) + return -1; + + a = pa_xmalloc(sizeof(struct authkey_data) + len); + a->ref = 1; + a->length = len; + memcpy(a+1, data, len); + + pa_property_set(c, name, a); + + return 0; +} + +void pa_authkey_prop_ref(struct pa_core *c, const char *name) { + struct authkey_data *a; + assert(c && name); + + a = pa_property_get(c, name); + assert(a && a->ref >= 1); + + a->ref++; +} + +void pa_authkey_prop_unref(struct pa_core *c, const char *name) { + struct authkey_data *a; + assert(c && name); + + a = pa_property_get(c, name); + assert(a && a->ref >= 1); + + if (!(--a->ref)) { + pa_property_remove(c, name); + pa_xfree(a); + } +} + + diff --git a/polyp/authkey-prop.h b/polyp/authkey-prop.h new file mode 100644 index 000000000..d9ba5122f --- /dev/null +++ b/polyp/authkey-prop.h @@ -0,0 +1,39 @@ +#ifndef fooauthkeyprophfoo +#define fooauthkeyprophfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "core.h" + +/* Return the data of the specified authorization key property. Doesn't alter the refernce count of the key */ +int pa_authkey_prop_get(struct pa_core *c, const char *name, void *data, size_t len); + +/* Store data in the specified authorization key property. The initial reference count is set to 1 */ +int pa_authkey_prop_put(struct pa_core *c, const char *name, const void *data, size_t len); + +/* Increase the reference count of the specified authorization key */ +void pa_authkey_prop_ref(struct pa_core *c, const char *name); + +/* Decrease the reference count of the specified authorization key */ +void pa_authkey_prop_unref(struct pa_core *c, const char *name); + +#endif diff --git a/polyp/authkey.c b/polyp/authkey.c index d3cb382be..773484e91 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -145,17 +145,17 @@ int pa_authkey_load(const char *path, void *data, size_t length) { } int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { - char *home; char path[PATH_MAX]; const char *p; assert(fn && data && length); if (fn[0] != '/') { - if (!(home = getenv("HOME"))) + char homedir[PATH_MAX]; + if (!pa_get_home_dir(homedir, sizeof(homedir))) return -2; - snprintf(path, sizeof(path), "%s/%s", home, fn); + snprintf(path, sizeof(path), "%s/%s", homedir, fn); p = path; } else p = fn; diff --git a/polyp/module-match.c b/polyp/module-match.c index 176c338f3..0398cede0 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -53,7 +53,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #endif #define DEFAULT_MATCH_TABLE_FILE DEFAULT_CONFIG_DIR"/match.table" -#define DEFAULT_MATCH_TABLE_FILE_USER ".polypaudio/.match.table" +#define DEFAULT_MATCH_TABLE_FILE_USER ".polypaudio/match.table" static const char* const valid_modargs[] = { "table", diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index 2e22258ac..c899929fa 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -45,6 +45,7 @@ #include "authkey.h" #include "socket-client.h" #include "socket-util.h" +#include "authkey-prop.h" #ifdef TUNNEL_SINK #include "module-tunnel-sink-symdef.h" @@ -129,10 +130,13 @@ struct userdata { pa_usec_t host_latency; struct pa_time_event *time_event; + + int auth_cookie_in_property; }; - static void close_stuff(struct userdata *u) { + assert(u); + if (u->pstream) { pa_pstream_close(u->pstream); pa_pstream_unref(u->pstream); @@ -532,6 +536,32 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, m->time_restart(e, &ntv); } +static int load_key(struct userdata *u, const char*fn) { + assert(u); + + u->auth_cookie_in_property = 0; + + if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { + pa_log(__FILE__": using already loaded auth cookie.\n"); + pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); + u->auth_cookie_in_property = 1; + return 0; + } + + if (!fn) + fn = PA_NATIVE_COOKIE_FILE; + + if (pa_authkey_load_from_home(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) + return -1; + + pa_log(__FILE__": loading cookie from disk.\n"); + + if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) + u->auth_cookie_in_property = 1; + + return 0; +} + int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; struct userdata *u = NULL; @@ -563,11 +593,11 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->ctag = 1; u->device_index = u->channel = PA_INVALID_INDEX; u->host_latency = 0; - - if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), u->auth_cookie, sizeof(u->auth_cookie)) < 0) { - pa_log(__FILE__": failed to load cookie.\n"); + u->auth_cookie_in_property = 0; + u->time_event = NULL; + + if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0) goto fail; - } if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) { pa_log(__FILE__": no server specified.\n"); @@ -650,6 +680,9 @@ void pa__done(struct pa_core *c, struct pa_module*m) { close_stuff(u); + if (u->auth_cookie_in_property) + pa_authkey_prop_unref(c, PA_NATIVE_COOKIE_PROPERTY_NAME); + #ifdef TUNNEL_SINK pa_xfree(u->sink_name); #else diff --git a/polyp/module-x11-publish.c b/polyp/module-x11-publish.c index fd4df4ad9..a488f6d54 100644 --- a/polyp/module-x11-publish.c +++ b/polyp/module-x11-publish.c @@ -41,8 +41,10 @@ #include "log.h" #include "x11wrap.h" #include "util.h" - +#include "native-common.h" #include "module-x11-publish-symdef.h" +#include "authkey-prop.h" +#include "authkey.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("X11 Credential Publisher") @@ -53,6 +55,7 @@ static const char* const valid_modargs[] = { "display", "sink", "source", + "cookie", NULL }; @@ -61,6 +64,8 @@ struct userdata { struct pa_x11_wrapper *x11_wrapper; Display *display; char *id; + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; + int auth_cookie_in_property; }; static void set_x11_prop(Display *d, const char *name, const char *data) { @@ -91,11 +96,38 @@ static char* get_x11_prop(Display *d, const char *name, char *p, size_t l) { return p; } +static int load_key(struct userdata *u, const char*fn) { + assert(u); + + u->auth_cookie_in_property = 0; + + if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { + pa_log(__FILE__": using already loaded auth cookie.\n"); + pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); + u->auth_cookie_in_property = 1; + return 0; + } + + if (!fn) + fn = PA_NATIVE_COOKIE_FILE; + + if (pa_authkey_load_from_home(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) + return -1; + + pa_log(__FILE__": loading cookie from disk.\n"); + + if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) + u->auth_cookie_in_property = 1; + + return 0; +} + int pa__init(struct pa_core *c, struct pa_module*m) { struct userdata *u; struct pa_modargs *ma = NULL; char hn[256], un[128]; - const char *t; + char hx[PA_NATIVE_COOKIE_LENGTH*2+1]; + const char *t; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments\n"); @@ -105,6 +137,10 @@ int pa__init(struct pa_core *c, struct pa_module*m) { m->userdata = u = pa_xmalloc(sizeof(struct userdata)); u->core = c; u->id = NULL; + u->auth_cookie_in_property = 0; + + if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0) + goto fail; if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) goto fail; @@ -124,6 +160,8 @@ int pa__init(struct pa_core *c, struct pa_module*m) { if ((t = pa_modargs_get_value(ma, "sink", NULL))) set_x11_prop(u->display, "POLYP_SINK", t); + + set_x11_prop(u->display, "POLYP_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), hx, sizeof(hx))); pa_modargs_free(ma); return 0; @@ -154,6 +192,7 @@ void pa__done(struct pa_core *c, struct pa_module*m) { del_x11_prop(u->display, "POLYP_SERVER"); del_x11_prop(u->display, "POLYP_SINK"); del_x11_prop(u->display, "POLYP_SOURCE"); + del_x11_prop(u->display, "POLYP_COOKIE"); XSync(u->display, False); } } @@ -161,6 +200,9 @@ void pa__done(struct pa_core *c, struct pa_module*m) { if (u->x11_wrapper) pa_x11_wrapper_unref(u->x11_wrapper); + if (u->auth_cookie_in_property) + pa_authkey_prop_unref(c, PA_NATIVE_COOKIE_PROPERTY_NAME); + pa_xfree(u->id); pa_xfree(u); } diff --git a/polyp/module.c b/polyp/module.c index 3fb42d875..9ecdfe292 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -135,6 +135,8 @@ static void pa_module_free(struct pa_module *m) { if (m->core->disallow_module_loading) return; + pa_log(__FILE__": Unloading \"%s\" (index: #%u).\n", m->name, m->index); + m->done(m->core, m); lt_dlclose(m->dl); diff --git a/polyp/native-common.h b/polyp/native-common.h index 33ecdc76f..fbee74c90 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -98,6 +98,8 @@ enum { #define PA_NATIVE_DEFAULT_PORT 4713 +#define PA_NATIVE_COOKIE_PROPERTY_NAME "protocol-native-cookie" + PA_C_DECL_END #endif diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 6f3f82be5..fade2a2ff 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -46,6 +46,7 @@ #include "subscribe.h" #include "log.h" #include "autoload.h" +#include "authkey-prop.h" struct connection; struct pa_protocol_native; @@ -106,6 +107,7 @@ struct pa_protocol_native { struct pa_socket_server *server; struct pa_idxset *connections; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; + int auth_cookie_in_property; }; static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); @@ -2008,6 +2010,32 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo /*** module entry points ***/ +static int load_key(struct pa_protocol_native*p, const char*fn) { + assert(p); + + p->auth_cookie_in_property = 0; + + if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) { + pa_log(__FILE__": using already loaded auth cookie.\n"); + pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); + p->auth_cookie_in_property = 1; + return 0; + } + + if (!fn) + fn = PA_NATIVE_COOKIE_FILE; + + if (pa_authkey_load_from_home(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0) + return -1; + + pa_log(__FILE__": loading cookie from disk.\n"); + + if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) + p->auth_cookie_in_property = 1; + + return 0; +} + static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struct pa_module *m, struct pa_modargs *ma) { struct pa_protocol_native *p; int public = 0; @@ -2019,16 +2047,16 @@ static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struc } p = pa_xmalloc(sizeof(struct pa_protocol_native)); + p->core = c; + p->module = m; + p->public = public; + p->server = NULL; - if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), p->auth_cookie, sizeof(p->auth_cookie)) < 0) { + if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0) { pa_xfree(p); return NULL; } - p->module = m; - p->public = public; - p->server = NULL; - p->core = c; p->connections = pa_idxset_new(NULL, NULL); assert(p->connections); @@ -2057,7 +2085,10 @@ void pa_protocol_native_free(struct pa_protocol_native *p) { if (p->server) pa_socket_server_unref(p->server); - + + if (p->auth_cookie_in_property) + pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); + pa_xfree(p); } diff --git a/polyp/socket-util.c b/polyp/socket-util.c index 4e1eb6ab8..96ea2c607 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -114,6 +114,7 @@ int pa_socket_tcp_low_delay(int fd) { ret = pa_socket_low_delay(fd); on = 1; +/* #if defined(SOL_TCP) || defined(IPPROTO_TCP) #if defined(SOL_TCP) if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) @@ -122,6 +123,7 @@ int pa_socket_tcp_low_delay(int fd) { #endif ret = -1; #endif +*/ #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || \ defined(IPPROTO_IP)) diff --git a/polyp/util.c b/polyp/util.c index 6e97bae4a..97b3a26bd 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -715,3 +715,20 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env return fopen(global, "r"); } +/* Format the specified data as a hexademical string */ +char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) { + size_t i = 0, j = 0; + const char hex[] = "0123456789abcdef"; + assert(d && s && slength > 0); + + while (i < dlength && j+3 <= slength) { + s[j++] = hex[*d >> 4]; + s[j++] = hex[*d & 0xF]; + + d++; + i++; + } + + s[j < slength ? j : slength] = 0; + return s; +} diff --git a/polyp/util.h b/polyp/util.h index 0299148e0..2b7e6bbe0 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -81,4 +81,6 @@ int pa_unlock_lockfile(int fd); FILE *pa_open_config_file(const char *env, const char *global, const char *local, char **result); +char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength); + #endif From 4bb14837dd09777e45793bda42512d900c6b500e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 8 Nov 2004 23:48:19 +0000 Subject: [PATCH 0268/1514] implemented pax11publish.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@275 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/FAQ.html.in | 18 ++- polyp/Makefile.am | 6 +- polyp/authkey.c | 71 +++++++++--- polyp/authkey.h | 2 + polyp/client-conf.c | 2 +- polyp/daemon-conf.c | 4 +- polyp/pax11publish.c | 246 ++++++++++++++++++++++++++++++++++++++++ polyp/polyplib-simple.c | 8 +- polyp/util.c | 41 +++++++ polyp/util.h | 1 + 10 files changed, 379 insertions(+), 20 deletions(-) create mode 100644 polyp/pax11publish.c diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in index f1bf24149..751ef562c 100644 --- a/doc/FAQ.html.in +++ b/doc/FAQ.html.in @@ -126,7 +126,23 @@ connect to a running polypaudio daemon try using the following commands:

    killall -USR2 polypaudio
     bidilink unix-client:/tmp/polypaudio/cli
    -

    BTW: Someone should package that great tool for Debian!

    +

    BTW: Someone should package that great tool for Debian!

    + + + +
  • How do the polypaudio libraries decide where to connect to?

    +

    The following rule applies:

    +
      +
    1. If the the application using the library specifies a server to connect to it is used. If the connection fails, the library fails too.
    2. +
    3. If the environment variable POLYP_SERVER is defined the library connects to that server. If the connection fails, the library fails too.
    4. +
    5. If $DISPLAY is set, the library tries to connect to that server and looks for the root window property POYLP_SERVER for the host to connect to. If POLYP_COOKIE is set it is used as authentication cookie.
    6. +
    7. If the client configuration file (~/.polypaudio/client.conf or /etc/polypaudio/client.conf) sets the server address, the library connects to that server. If the connection fails, the library fails too.
    8. +
    9. The library tries to connect to the default local UNIX socket for polypaudio servers. If the connection fails, it proceeds with the next item.
    10. +
    11. The library tries to connect to the default local TCP socket for polypaudio servers. If the connection fails, it proceeds with the next item.
    12. +
    13. If $DISPLAY is set, the library tries to connect to the default TCP port of that host. If the connection fails, it proceeds with the next item.
    14. +
    15. The connection fails.
    16. +
    +

  • diff --git a/polyp/Makefile.am b/polyp/Makefile.am index b0b863e5e..c1d81062d 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -31,7 +31,7 @@ AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in module-defs.h.m4 -bin_PROGRAMS = polypaudio pacat pactl paplay +bin_PROGRAMS = polypaudio pacat pactl paplay pax11publish bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ mainloop-test \ @@ -441,6 +441,10 @@ parec_simple_SOURCES = parec-simple.c parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la parec_simple_CFLAGS = $(AM_CFLAGS) +pax11publish_SOURCES = pax11publish.c util.c xmalloc.c log.c authkey.c client-conf.c conf-parser.c +pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) + mainloop_test_SOURCES = mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-@PA_MAJORMINOR@.la diff --git a/polyp/authkey.c b/polyp/authkey.c index 773484e91..ef395680b 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -68,7 +68,7 @@ static int generate(int fd, void *data, size_t length) { lseek(fd, 0, SEEK_SET); if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) { - pa_log(__FILE__": failed to write cookie file\n"); + pa_log(__FILE__": failed to write cookie file: %s\n", strerror(errno)); goto finish; } @@ -91,7 +91,7 @@ static int load(const char *fn, void *data, size_t length) { if ((fd = open(fn, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { if (errno != EACCES || (fd = open(fn, O_RDONLY)) < 0) { - pa_log(__FILE__": failed to open cookie file '%s'\n", fn); + pa_log(__FILE__": failed to open cookie file '%s': %s\n", fn, strerror(errno)); goto finish; } else writable = 0; @@ -100,7 +100,7 @@ static int load(const char *fn, void *data, size_t length) { unlock = pa_lock_fd(fd, 1) >= 0; if ((r = pa_loop_read(fd, data, length)) < 0) { - pa_log(__FILE__": failed to read cookie file '%s'\n", fn); + pa_log(__FILE__": failed to read cookie file '%s': %s\n", fn, strerror(errno)); goto finish; } @@ -144,21 +144,28 @@ int pa_authkey_load(const char *path, void *data, size_t length) { return ret; } -int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { - char path[PATH_MAX]; - const char *p; - - assert(fn && data && length); +static const char *normalize_path(const char *fn, char *s, size_t l) { + assert(fn && s && l > 0); if (fn[0] != '/') { char homedir[PATH_MAX]; if (!pa_get_home_dir(homedir, sizeof(homedir))) - return -2; + return NULL; - snprintf(path, sizeof(path), "%s/%s", homedir, fn); - p = path; - } else - p = fn; + snprintf(s, l, "%s/%s", homedir, fn); + return s; + } + + return fn; +} + +int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { + char path[PATH_MAX]; + const char *p; + assert(fn && data && length); + + if (!(p = normalize_path(fn, path, sizeof(path)))) + return -2; return pa_authkey_load(p, data, length); } @@ -171,3 +178,41 @@ int pa_authkey_load_auto(const char *fn, void *data, size_t length) { else return pa_authkey_load_from_home(fn, data, length); } + +int pa_authkey_save(const char *fn, const void *data, size_t length) { + int fd = -1; + int unlock = 0, ret = -1; + ssize_t r; + char path[PATH_MAX]; + const char *p; + assert(fn && data && length); + + if (!(p = normalize_path(fn, path, sizeof(path)))) + return -2; + + if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { + pa_log(__FILE__": failed to open cookie file '%s': %s\n", fn, strerror(errno)); + goto finish; + } + + unlock = pa_lock_fd(fd, 1) >= 0; + + if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) { + pa_log(__FILE__": failed to read cookie file '%s': %s\n", fn, strerror(errno)); + goto finish; + } + + ret = 0; + +finish: + + if (fd >= 0) { + + if (unlock) + pa_lock_fd(fd, 0); + + close(fd); + } + + return ret; +} diff --git a/polyp/authkey.h b/polyp/authkey.h index acdcc24d3..2bef35290 100644 --- a/polyp/authkey.h +++ b/polyp/authkey.h @@ -28,4 +28,6 @@ int pa_authkey_load(const char *path, void *data, size_t len); int pa_authkey_load_from_home(const char *fn, void *data, size_t length); int pa_authkey_load_auto(const char *fn, void *data, size_t length); +int pa_authkey_save(const char *path, const void *data, size_t length); + #endif diff --git a/polyp/client-conf.c b/polyp/client-conf.c index 47c5b49cf..0f442c993 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -102,7 +102,7 @@ int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { goto finish; } - r = pa_config_parse(fn, f, table, NULL); + r = f ? pa_config_parse(fn, f, table, NULL) : 0; finish: pa_xfree(fn); diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index e87acd1d8..1c6486b7f 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -182,12 +182,12 @@ int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename) { fopen(c->config_file = pa_xstrdup(filename), "r") : pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file); - if (!f && errno != EINTR) { + if (!f && errno != ENOENT) { pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno)); goto finish; } - r = pa_config_parse(c->config_file, f, table, NULL); + r = f ? pa_config_parse(c->config_file, f, table, NULL) : 0; finish: if (f) diff --git a/polyp/pax11publish.c b/polyp/pax11publish.c new file mode 100644 index 000000000..d1391dcf2 --- /dev/null +++ b/polyp/pax11publish.c @@ -0,0 +1,246 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "util.h" +#include "log.h" +#include "authkey.h" +#include "native-common.h" +#include "client-conf.h" + +static void set_x11_prop(Display *d, const char *name, const char *data) { + Atom a = XInternAtom(d, name, False); + XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (unsigned char*) data, strlen(data)+1); +} + +static void del_x11_prop(Display *d, const char *name) { + Atom a = XInternAtom(d, name, False); + XDeleteProperty(d, RootWindow(d, 0), a); +} + +static char* get_x11_prop(Display *d, const char *name, char *p, size_t l) { + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long nbytes_after; + unsigned char *prop = NULL; + char *ret = NULL; + + Atom a = XInternAtom(d, name, False); + if (XGetWindowProperty(d, RootWindow(d, 0), a, 0, (l+2)/4, False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop) != Success) + goto finish; + + if (actual_type != XA_STRING) + goto finish; + + memcpy(p, prop, nitems); + p[nitems] = 0; + + ret = p; + +finish: + + if (prop) + XFree(prop); + + return ret; +} + +int main(int argc, char *argv[]) { + const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE; + int c, ret = 1; + Display *d = NULL; + enum { DUMP, EXPORT, IMPORT, REMOVE } mode = DUMP; + + while ((c = getopt(argc, argv, "deiD:S:O:I:c:hr")) != -1) { + switch (c) { + case 'D' : + dname = optarg; + break; + case 'h': + printf("%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n", pa_path_get_filename(argv[0])); + ret = 0; + goto finish; + case 'd': + mode = DUMP; + break; + case 'e': + mode = EXPORT; + break; + case 'i': + mode = IMPORT; + break; + case 'r': + mode = REMOVE; + break; + case 'c': + cookie_file = optarg; + break; + case 'I': + source = optarg; + break; + case 'O': + sink = optarg; + break; + case 'S': + server = optarg; + break; + default: + fprintf(stderr, "Failed to parse command line.\n"); + goto finish; + } + } + + if (!(d = XOpenDisplay(dname))) { + pa_log(__FILE__": XOpenDisplay() failed\n"); + goto finish; + } + + switch (mode) { + case DUMP: { + char t[1024]; + if (!get_x11_prop(d, "POLYP_SERVER", t, sizeof(t))) + goto finish; + + printf("Server: %s\n", t); + if (get_x11_prop(d, "POLYP_SOURCE", t, sizeof(t))) + printf("Source: %s\n", t); + if (get_x11_prop(d, "POLYP_SINK", t, sizeof(t))) + printf("Sink: %s\n", t); + if (get_x11_prop(d, "POLYP_COOKIE", t, sizeof(t))) + printf("Cookie: %s\n", t); + + break; + } + + case IMPORT: { + char t[1024]; + if (!get_x11_prop(d, "POLYP_SERVER", t, sizeof(t))) + goto finish; + + printf("POLYP_SERVER='%s'\nexport POLYP_SERVER\n", t); + + if (get_x11_prop(d, "POLYP_SOURCE", t, sizeof(t))) + printf("POLYP_SOURCE='%s'\nexport POLYP_SOURCE\n", t); + if (get_x11_prop(d, "POLYP_SINK", t, sizeof(t))) + printf("POLYP_SINK='%s'\nexport POLYP_SINK\n", t); + + if (get_x11_prop(d, "POLYP_COOKIE", t, sizeof(t))) { + uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; + size_t l; + if ((l = pa_parsehex(t, cookie, sizeof(cookie))) == (size_t) -1) { + fprintf(stderr, "Failed to parse cookie data\n"); + goto finish; + } + + if (pa_authkey_save(cookie_file, cookie, l) < 0) { + fprintf(stderr, "Failed to save cookie data\n"); + goto finish; + } + } + + break; + } + + case EXPORT: { + struct pa_client_conf *c = pa_client_conf_new(); + uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; + char hx[PA_NATIVE_COOKIE_LENGTH*2+1]; + assert(c); + + if (pa_client_conf_load(c, NULL) < 0) { + fprintf(stderr, "Failed to load client configuration file.\n"); + goto finish; + } + + if (pa_client_conf_env(c) < 0) { + fprintf(stderr, "Failed to read environment configuration data.\n"); + goto finish; + } + + del_x11_prop(d, "POLYP_ID"); + + if (server) + set_x11_prop(d, "POLYP_SERVER", c->default_server); + else if (c->default_server) + set_x11_prop(d, "POLYP_SERVER", c->default_server); + else { + char hn[256]; + pa_get_host_name(hn, sizeof(hn)); + set_x11_prop(d, "POLYP_SERVER", hn); + } + + if (sink) + set_x11_prop(d, "POLYP_SINK", sink); + else if (c->default_sink) + set_x11_prop(d, "POLYP_SINK", c->default_sink); + + if (source) + set_x11_prop(d, "POLYP_SOURCE", source); + if (c->default_source) + set_x11_prop(d, "POLYP_SOURCE", c->default_source); + + pa_client_conf_free(c); + + if (pa_authkey_load_auto(cookie_file, cookie, sizeof(cookie)) < 0) { + fprintf(stderr, "Failed to load cookie data\n"); + goto finish; + } + + set_x11_prop(d, "POLYP_COOKIE", pa_hexstr(cookie, sizeof(cookie), hx, sizeof(hx))); + break; + } + + case REMOVE: + del_x11_prop(d, "POLYP_SERVER"); + del_x11_prop(d, "POLYP_SINK"); + del_x11_prop(d, "POLYP_SOURCE"); + del_x11_prop(d, "POLYP_ID"); + del_x11_prop(d, "POLYP_COOKIE"); + break; + + default: + fprintf(stderr, "No yet implemented.\n"); + goto finish; + } + + ret = 0; + +finish: + + if (d) { + XSync(d, False); + XCloseDisplay(d); + } + + return ret; +} diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index 0e180af04..aed1ca55c 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -325,8 +325,12 @@ static void latency_complete(struct pa_stream *s, const struct pa_latency_info * if (!l) p->dead = 1; - else - p->latency = l->buffer_usec + l->sink_usec + l->transport_usec; + else { + int negative = 0; + p->latency = pa_stream_get_latency(s, l, &negative); + if (negative) + p->latency = 0; + } } pa_usec_t pa_simple_get_playback_latency(struct pa_simple *p, int *perror) { diff --git a/polyp/util.c b/polyp/util.c index 97b3a26bd..b4c16dbb4 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -732,3 +732,44 @@ char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) { s[j < slength ? j : slength] = 0; return s; } + +/* Convert a hexadecimal digit to a number or -1 if invalid */ +static int hexc(char c) { + if (c >= '0' && c <= '9') + return c - '0'; + + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + + return -1; +} + +/* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */ +size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) { + size_t j = 0; + assert(p && d); + + while (j < dlength && *p) { + int b; + + if ((b = hexc(*(p++))) < 0) + return (size_t) -1; + + d[j] = (uint8_t) (b << 4); + + if (!*p) + return (size_t) -1; + + if ((b = hexc(*(p++))) < 0) + return (size_t) -1; + + d[j] |= (uint8_t) b; + + j++; + } + + return j; +} diff --git a/polyp/util.h b/polyp/util.h index 2b7e6bbe0..2448b0fa7 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -82,5 +82,6 @@ int pa_unlock_lockfile(int fd); FILE *pa_open_config_file(const char *env, const char *global, const char *local, char **result); char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength); +size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength); #endif From 89e39f13b5b122d7dd17499b9b69fdccc196a30c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 8 Nov 2004 23:53:46 +0000 Subject: [PATCH 0269/1514] build pax11publish only when X11 is available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@276 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index c1d81062d..18aa51c18 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -31,7 +31,7 @@ AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in module-defs.h.m4 -bin_PROGRAMS = polypaudio pacat pactl paplay pax11publish +bin_PROGRAMS = polypaudio pacat pactl paplay bin_SCRIPTS = esdcompat.sh noinst_PROGRAMS = \ mainloop-test \ @@ -441,10 +441,6 @@ parec_simple_SOURCES = parec-simple.c parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la parec_simple_CFLAGS = $(AM_CFLAGS) -pax11publish_SOURCES = pax11publish.c util.c xmalloc.c log.c authkey.c client-conf.c conf-parser.c -pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) - mainloop_test_SOURCES = mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-@PA_MAJORMINOR@.la @@ -487,6 +483,13 @@ module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_publish_la_LDFLAGS = -module -avoid-version module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) libx11wrap.la libauthkey.la libauthkey-prop.la +bin_PROGRAMS+= \ + pax11publish + +pax11publish_SOURCES = pax11publish.c util.c xmalloc.c log.c authkey.c client-conf.c conf-parser.c +pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) + endif ### ALSA modules From 3916a66a87a639a1733cfe4fb33f32904eda7f59 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 9 Nov 2004 00:14:07 +0000 Subject: [PATCH 0270/1514] export FQDN instead of hostname git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@277 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/pax11publish.c | 13 +++++++++++-- polyp/util.c | 20 ++++++++++++++++++++ polyp/util.h | 1 + 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/polyp/pax11publish.c b/polyp/pax11publish.c index d1391dcf2..fc1d6ab7b 100644 --- a/polyp/pax11publish.c +++ b/polyp/pax11publish.c @@ -87,7 +87,12 @@ int main(int argc, char *argv[]) { dname = optarg; break; case 'h': - printf("%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n", pa_path_get_filename(argv[0])); + printf("%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n\n" + " -d Show current Polypaudio data attached to X11 display (default)\n" + " -e Export local Polypaudio data to X11 display\n" + " -i Import Polypaudio data from X11 display to local environment variables and cookie file.\n" + " -r Remove Polypaudio data from X11 display\n", + pa_path_get_filename(argv[0])); ret = 0; goto finish; case 'd': @@ -195,7 +200,11 @@ int main(int argc, char *argv[]) { set_x11_prop(d, "POLYP_SERVER", c->default_server); else { char hn[256]; - pa_get_host_name(hn, sizeof(hn)); + if (!pa_get_fqdn(hn, sizeof(hn))) { + fprintf(stderr, "Failed to get FQDN.\n"); + goto finish; + } + set_x11_prop(d, "POLYP_SERVER", hn); } diff --git a/polyp/util.c b/polyp/util.c index b4c16dbb4..ad91a3078 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -773,3 +774,22 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) { return j; } + +char *pa_get_fqdn(char *s, size_t l) { + char hn[256]; + struct addrinfo *a, hints; + + if (!pa_get_host_name(hn, sizeof(hn))) + return NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_CANONNAME; + + if (getaddrinfo(hn, NULL, &hints, &a) < 0 || !a || !a->ai_canonname || !*a->ai_canonname) + return pa_strlcpy(s, hn, l); + + pa_strlcpy(s, a->ai_canonname, l); + freeaddrinfo(a); + return s; +} diff --git a/polyp/util.h b/polyp/util.h index 2448b0fa7..3f09a9a70 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -46,6 +46,7 @@ char *pa_strlcpy(char *b, const char *s, size_t l); char *pa_get_user_name(char *s, size_t l); char *pa_get_host_name(char *s, size_t l); +char *pa_get_fqdn(char *s, size_t l); char *pa_get_binary_name(char *s, size_t l); char *pa_get_home_dir(char *s, size_t l); From 3fcd7a433c1422c52804181de6a719a527830326 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 9 Nov 2004 01:04:17 +0000 Subject: [PATCH 0271/1514] use fqdn in module-x11-publish as well git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@278 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-x11-publish.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/polyp/module-x11-publish.c b/polyp/module-x11-publish.c index a488f6d54..c862fe3a2 100644 --- a/polyp/module-x11-publish.c +++ b/polyp/module-x11-publish.c @@ -147,8 +147,11 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->display = pa_x11_wrapper_get_display(u->x11_wrapper); - pa_get_host_name(hn, sizeof(hn)); - pa_get_user_name(un, sizeof(un)); + if (!pa_get_fqdn(hn, sizeof(hn))) + goto fail; + + if (!pa_get_user_name(un, sizeof(un))) + goto fail; u->id = pa_sprintf_malloc("%s@%s/%u", un, hn, (unsigned) getpid()); From dbaa83c60730633315aa13d74907c6572985c050 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 9 Nov 2004 23:19:42 +0000 Subject: [PATCH 0272/1514] split out x11prop.[ch] add client support for auth daemon info in X display git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@279 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 1 + doc/todo | 1 + polyp/Makefile.am | 22 ++++++--- polyp/client-conf-x11.c | 89 ++++++++++++++++++++++++++++++++++++ polyp/client-conf-x11.h | 29 ++++++++++++ polyp/client-conf.c | 40 +++++++++++++++- polyp/client-conf.h | 8 +++- polyp/module-protocol-stub.c | 2 +- polyp/module-x11-publish.c | 51 +++++---------------- polyp/native-common.h | 3 ++ polyp/pax11publish.c | 85 ++++++++++------------------------ polyp/polyplib-context.c | 19 +++++--- polyp/polyplib-internal.h | 3 -- polyp/x11prop.c | 70 ++++++++++++++++++++++++++++ polyp/x11prop.h | 33 +++++++++++++ 15 files changed, 337 insertions(+), 119 deletions(-) create mode 100644 polyp/client-conf-x11.c create mode 100644 polyp/client-conf-x11.h create mode 100644 polyp/x11prop.c create mode 100644 polyp/x11prop.h diff --git a/configure.ac b/configure.ac index 026d4d97b..6eec2d812 100644 --- a/configure.ac +++ b/configure.ac @@ -54,6 +54,7 @@ HAVE_X11=0 test "x$no_x" != "xyes" && HAVE_X11=1 AC_SUBST(HAVE_X11) AM_CONDITIONAL(HAVE_X11, test "x$no_x" != "xyes") +AC_DEFINE([HAVE_X11], [], [Have X11]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST diff --git a/doc/todo b/doc/todo index cfc4b0441..2ba697b84 100644 --- a/doc/todo +++ b/doc/todo @@ -20,6 +20,7 @@ - add LGPL blurb to all concerning files - non-fp mixing - non-fp resampling +- esound backend ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 18aa51c18..cc9705c25 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -27,8 +27,8 @@ AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\" AM_CFLAGS+=-DDEFAULT_CONFIG_DIR=\"$(polypconfdir)\" AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" -AM_LDADD=$(PTHREAD_LIBS) -lm AM_LIBADD=$(PTHREAD_LIBS) -lm +AM_LDADD=$(PTHREAD_LIBS) -lm EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in module-defs.h.m4 bin_PROGRAMS = polypaudio pacat pactl paplay @@ -462,6 +462,7 @@ cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la if HAVE_X11 modlib_LTLIBRARIES+= \ libx11wrap.la \ + libx11prop.la \ module-x11-bell.la \ module-x11-publish.la SYMDEF_FILES += \ @@ -471,24 +472,33 @@ SYMDEF_FILES += \ libx11wrap_la_SOURCES = x11wrap.c x11wrap.h libx11wrap_la_LDFLAGS = -avoid-version libx11wrap_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) +libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) + +libx11prop_la_SOURCES = x11prop.c x11prop.h +libx11prop_la_LDFLAGS = -avoid-version +libx11prop_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) module_x11_bell_la_SOURCES = module-x11-bell.c module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_bell_la_LDFLAGS = -module -avoid-version -module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) libx11wrap.la +module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la module_x11_publish_la_SOURCES = module-x11-publish.c module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_publish_la_LDFLAGS = -module -avoid-version -module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) libx11wrap.la libauthkey.la libauthkey-prop.la +module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauthkey-prop.la libx11prop.la bin_PROGRAMS+= \ pax11publish -pax11publish_SOURCES = pax11publish.c util.c xmalloc.c log.c authkey.c client-conf.c conf-parser.c +pax11publish_SOURCES = pax11publish.c util.c xmalloc.c log.c authkey.c client-conf.c conf-parser.c x11prop.c pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIB) +pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) + +libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(X_CFLAGS) +libpolyp_@PA_MAJORMINOR@_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +libpolyp_@PA_MAJORMINOR@_la_SOURCES += x11prop.c client-conf-x11.c endif diff --git a/polyp/client-conf-x11.c b/polyp/client-conf-x11.c new file mode 100644 index 000000000..54c3b06a8 --- /dev/null +++ b/polyp/client-conf-x11.c @@ -0,0 +1,89 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +#include "client-conf-x11.h" +#include "x11prop.h" +#include "log.h" +#include "xmalloc.h" +#include "util.h" + +int pa_client_conf_from_x11(struct pa_client_conf *c, const char *dname) { + Display *d = NULL; + int ret = -1; + char t[1024]; + + if (!(d = XOpenDisplay(dname))) { + pa_log(__FILE__": XOpenDisplay() failed\n"); + goto finish; + } + + if (!pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) + goto finish; + + pa_xfree(c->default_server); + c->default_server = pa_xstrdup(t); + + if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) { + pa_xfree(c->default_sink); + c->default_sink = pa_xstrdup(t); + } + + if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) { + pa_xfree(c->default_source); + c->default_source = pa_xstrdup(t); + } + + if (pa_x11_get_prop(d, "POLYP_COOKIE", t, sizeof(t))) { + uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; + + if (pa_parsehex(t, cookie, sizeof(cookie)) != sizeof(cookie)) { + pa_log(__FILE__": failed to parse cookie data\n"); + goto finish; + } + + assert(sizeof(cookie) == sizeof(c->cookie)); + memcpy(c->cookie, cookie, sizeof(cookie)); + + c->cookie_valid = 1; + + pa_xfree(c->cookie_file); + c->cookie_file = NULL; + } + + ret = 0; + +finish: + if (d) + XCloseDisplay(d); + + return ret; + +} diff --git a/polyp/client-conf-x11.h b/polyp/client-conf-x11.h new file mode 100644 index 000000000..626b4f307 --- /dev/null +++ b/polyp/client-conf-x11.h @@ -0,0 +1,29 @@ +#ifndef fooclientconfx11hfoo +#define fooclientconfx11hfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "client-conf.h" + +int pa_client_conf_from_x11(struct pa_client_conf *c, const char *display); + +#endif diff --git a/polyp/client-conf.c b/polyp/client-conf.c index 0f442c993..4a0fc6298 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -30,6 +30,7 @@ #include "log.h" #include "conf-parser.h" #include "util.h" +#include "authkey.h" #ifndef DEFAULT_CONFIG_DIR #define DEFAULT_CONFIG_DIR "/etc/polypaudio" @@ -43,6 +44,7 @@ #define ENV_DEFAULT_SOURCE "POLYP_SOURCE" #define ENV_DEFAULT_SERVER "POLYP_SERVER" #define ENV_DAEMON_BINARY "POLYP_BINARY" +#define ENV_COOKIE_FILE "POLYP_COOKIE" static const struct pa_client_conf default_conf = { .daemon_binary = NULL, @@ -50,14 +52,20 @@ static const struct pa_client_conf default_conf = { .default_sink = NULL, .default_source = NULL, .default_server = NULL, - .autospawn = 0 + .autospawn = 0, + .cookie_file = NULL, + .cookie_valid = 0 }; struct pa_client_conf *pa_client_conf_new(void) { struct pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); + + c->daemon_binary = pa_xstrdup(POLYPAUDIO_BINARY); c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5"); + + c->cookie_file = pa_xstrdup(PA_NATIVE_COOKIE_FILE); return c; } @@ -69,6 +77,7 @@ void pa_client_conf_free(struct pa_client_conf *c) { pa_xfree(c->default_sink); pa_xfree(c->default_source); pa_xfree(c->default_server); + pa_xfree(c->cookie_file); pa_xfree(c); } int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { @@ -83,6 +92,7 @@ int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { { "default-source", pa_config_parse_string, NULL }, { "default-server", pa_config_parse_string, NULL }, { "autospawn", pa_config_parse_bool, NULL }, + { "cookie-file", pa_config_parse_string, NULL }, { NULL, NULL, NULL }, }; @@ -92,6 +102,7 @@ int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { table[3].data = &c->default_source; table[4].data = &c->default_server; table[5].data = &c->autospawn; + table[6].data = &c->cookie_file; f = filename ? fopen((fn = pa_xstrdup(filename)), "r") : @@ -104,6 +115,10 @@ int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { r = f ? pa_config_parse(fn, f, table, NULL) : 0; + if (!r) + r = pa_client_conf_load_cookie(c); + + finish: pa_xfree(fn); @@ -136,5 +151,28 @@ int pa_client_conf_env(struct pa_client_conf *c) { c->daemon_binary = pa_xstrdup(e); } + if ((e = getenv(ENV_COOKIE_FILE))) { + pa_xfree(c->cookie_file); + c->cookie_file = pa_xstrdup(e); + + return pa_client_conf_load_cookie(c); + } + return 0; } + +int pa_client_conf_load_cookie(struct pa_client_conf* c) { + assert(c); + + c->cookie_valid = 0; + + if (!c->cookie_file) + return -1; + + if (pa_authkey_load_auto(c->cookie_file, c->cookie, sizeof(c->cookie)) < 0) + return -1; + + c->cookie_valid = 1; + return 0; +} + diff --git a/polyp/client-conf.h b/polyp/client-conf.h index 6fd4a20d7..2ce056f4a 100644 --- a/polyp/client-conf.h +++ b/polyp/client-conf.h @@ -22,9 +22,13 @@ USA. ***/ +#include "native-common.h" + struct pa_client_conf { - char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server; + char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; int autospawn; + uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; + int cookie_valid; }; struct pa_client_conf *pa_client_conf_new(void); @@ -33,4 +37,6 @@ void pa_client_conf_free(struct pa_client_conf *c); int pa_client_conf_load(struct pa_client_conf *c, const char *filename); int pa_client_conf_env(struct pa_client_conf *c); +int pa_client_conf_load_cookie(struct pa_client_conf* c); + #endif diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 8cef3bdb3..6ff7d7743 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -83,7 +83,7 @@ #define protocol_free pa_protocol_native_free #define TCPWRAP_SERVICE "polypaudio-native" #define IPV4_PORT PA_NATIVE_DEFAULT_PORT - #define UNIX_SOCKET "/tmp/polypaudio/native" + #define UNIX_SOCKET PA_NATIVE_DEFAULT_SERVER_UNIX #define MODULE_ARGUMENTS "public", "cookie", #ifdef USE_TCP_SOCKETS #include "module-native-protocol-tcp-symdef.h" diff --git a/polyp/module-x11-publish.c b/polyp/module-x11-publish.c index c862fe3a2..6e100153f 100644 --- a/polyp/module-x11-publish.c +++ b/polyp/module-x11-publish.c @@ -45,6 +45,7 @@ #include "module-x11-publish-symdef.h" #include "authkey-prop.h" #include "authkey.h" +#include "x11prop.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("X11 Credential Publisher") @@ -68,34 +69,6 @@ struct userdata { int auth_cookie_in_property; }; -static void set_x11_prop(Display *d, const char *name, const char *data) { - Atom a = XInternAtom(d, name, False); - XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (unsigned char*) data, strlen(data)+1); -} - -static void del_x11_prop(Display *d, const char *name) { - Atom a = XInternAtom(d, name, False); - XDeleteProperty(d, RootWindow(d, 0), a); -} - -static char* get_x11_prop(Display *d, const char *name, char *p, size_t l) { - Atom actual_type; - int actual_format; - unsigned long nitems; - unsigned long nbytes_after; - unsigned char *prop; - - Atom a = XInternAtom(d, name, False); - if (XGetWindowProperty(d, RootWindow(d, 0), a, 0, (l+2)/4, False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop) != Success) - return NULL; - - memcpy(p, prop, nitems); - p[nitems] = 0; - - XFree(prop); - return p; -} - static int load_key(struct userdata *u, const char*fn) { assert(u); @@ -155,16 +128,16 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->id = pa_sprintf_malloc("%s@%s/%u", un, hn, (unsigned) getpid()); - set_x11_prop(u->display, "POLYP_SERVER", hn); - set_x11_prop(u->display, "POLYP_ID", u->id); + pa_x11_set_prop(u->display, "POLYP_SERVER", hn); + pa_x11_set_prop(u->display, "POLYP_ID", u->id); if ((t = pa_modargs_get_value(ma, "source", NULL))) - set_x11_prop(u->display, "POLYP_SOURCE", t); + pa_x11_set_prop(u->display, "POLYP_SOURCE", t); if ((t = pa_modargs_get_value(ma, "sink", NULL))) - set_x11_prop(u->display, "POLYP_SINK", t); + pa_x11_set_prop(u->display, "POLYP_SINK", t); - set_x11_prop(u->display, "POLYP_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), hx, sizeof(hx))); + pa_x11_set_prop(u->display, "POLYP_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), hx, sizeof(hx))); pa_modargs_free(ma); return 0; @@ -188,14 +161,14 @@ void pa__done(struct pa_core *c, struct pa_module*m) { char t[256]; /* Yes, here is a race condition */ - if (!get_x11_prop(u->display, "POLYP_ID", t, sizeof(t)) || strcmp(t, u->id)) + if (!pa_x11_get_prop(u->display, "POLYP_ID", t, sizeof(t)) || strcmp(t, u->id)) pa_log("WARNING: Polypaudio information vanished from X11!\n"); else { - del_x11_prop(u->display, "POLYP_ID"); - del_x11_prop(u->display, "POLYP_SERVER"); - del_x11_prop(u->display, "POLYP_SINK"); - del_x11_prop(u->display, "POLYP_SOURCE"); - del_x11_prop(u->display, "POLYP_COOKIE"); + pa_x11_del_prop(u->display, "POLYP_ID"); + pa_x11_del_prop(u->display, "POLYP_SERVER"); + pa_x11_del_prop(u->display, "POLYP_SINK"); + pa_x11_del_prop(u->display, "POLYP_SOURCE"); + pa_x11_del_prop(u->display, "POLYP_COOKIE"); XSync(u->display, False); } } diff --git a/polyp/native-common.h b/polyp/native-common.h index fbee74c90..597bb56b0 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -100,6 +100,9 @@ enum { #define PA_NATIVE_COOKIE_PROPERTY_NAME "protocol-native-cookie" +#define PA_NATIVE_DEFAULT_SERVER_UNIX "/tmp/polypaudio/native" + + PA_C_DECL_END #endif diff --git a/polyp/pax11publish.c b/polyp/pax11publish.c index fc1d6ab7b..f151c1976 100644 --- a/polyp/pax11publish.c +++ b/polyp/pax11publish.c @@ -36,44 +36,7 @@ #include "authkey.h" #include "native-common.h" #include "client-conf.h" - -static void set_x11_prop(Display *d, const char *name, const char *data) { - Atom a = XInternAtom(d, name, False); - XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (unsigned char*) data, strlen(data)+1); -} - -static void del_x11_prop(Display *d, const char *name) { - Atom a = XInternAtom(d, name, False); - XDeleteProperty(d, RootWindow(d, 0), a); -} - -static char* get_x11_prop(Display *d, const char *name, char *p, size_t l) { - Atom actual_type; - int actual_format; - unsigned long nitems; - unsigned long nbytes_after; - unsigned char *prop = NULL; - char *ret = NULL; - - Atom a = XInternAtom(d, name, False); - if (XGetWindowProperty(d, RootWindow(d, 0), a, 0, (l+2)/4, False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop) != Success) - goto finish; - - if (actual_type != XA_STRING) - goto finish; - - memcpy(p, prop, nitems); - p[nitems] = 0; - - ret = p; - -finish: - - if (prop) - XFree(prop); - - return ret; -} +#include "x11prop.h" int main(int argc, char *argv[]) { const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE; @@ -133,15 +96,15 @@ int main(int argc, char *argv[]) { switch (mode) { case DUMP: { char t[1024]; - if (!get_x11_prop(d, "POLYP_SERVER", t, sizeof(t))) + if (!pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) goto finish; printf("Server: %s\n", t); - if (get_x11_prop(d, "POLYP_SOURCE", t, sizeof(t))) + if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) printf("Source: %s\n", t); - if (get_x11_prop(d, "POLYP_SINK", t, sizeof(t))) + if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) printf("Sink: %s\n", t); - if (get_x11_prop(d, "POLYP_COOKIE", t, sizeof(t))) + if (pa_x11_get_prop(d, "POLYP_COOKIE", t, sizeof(t))) printf("Cookie: %s\n", t); break; @@ -149,20 +112,20 @@ int main(int argc, char *argv[]) { case IMPORT: { char t[1024]; - if (!get_x11_prop(d, "POLYP_SERVER", t, sizeof(t))) + if (!pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) goto finish; printf("POLYP_SERVER='%s'\nexport POLYP_SERVER\n", t); - if (get_x11_prop(d, "POLYP_SOURCE", t, sizeof(t))) + if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) printf("POLYP_SOURCE='%s'\nexport POLYP_SOURCE\n", t); - if (get_x11_prop(d, "POLYP_SINK", t, sizeof(t))) + if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) printf("POLYP_SINK='%s'\nexport POLYP_SINK\n", t); - if (get_x11_prop(d, "POLYP_COOKIE", t, sizeof(t))) { + if (pa_x11_get_prop(d, "POLYP_COOKIE", t, sizeof(t))) { uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; size_t l; - if ((l = pa_parsehex(t, cookie, sizeof(cookie))) == (size_t) -1) { + if ((l = pa_parsehex(t, cookie, sizeof(cookie))) != sizeof(cookie)) { fprintf(stderr, "Failed to parse cookie data\n"); goto finish; } @@ -192,12 +155,12 @@ int main(int argc, char *argv[]) { goto finish; } - del_x11_prop(d, "POLYP_ID"); + pa_x11_del_prop(d, "POLYP_ID"); if (server) - set_x11_prop(d, "POLYP_SERVER", c->default_server); + pa_x11_set_prop(d, "POLYP_SERVER", c->default_server); else if (c->default_server) - set_x11_prop(d, "POLYP_SERVER", c->default_server); + pa_x11_set_prop(d, "POLYP_SERVER", c->default_server); else { char hn[256]; if (!pa_get_fqdn(hn, sizeof(hn))) { @@ -205,18 +168,18 @@ int main(int argc, char *argv[]) { goto finish; } - set_x11_prop(d, "POLYP_SERVER", hn); + pa_x11_set_prop(d, "POLYP_SERVER", hn); } if (sink) - set_x11_prop(d, "POLYP_SINK", sink); + pa_x11_set_prop(d, "POLYP_SINK", sink); else if (c->default_sink) - set_x11_prop(d, "POLYP_SINK", c->default_sink); + pa_x11_set_prop(d, "POLYP_SINK", c->default_sink); if (source) - set_x11_prop(d, "POLYP_SOURCE", source); + pa_x11_set_prop(d, "POLYP_SOURCE", source); if (c->default_source) - set_x11_prop(d, "POLYP_SOURCE", c->default_source); + pa_x11_set_prop(d, "POLYP_SOURCE", c->default_source); pa_client_conf_free(c); @@ -225,16 +188,16 @@ int main(int argc, char *argv[]) { goto finish; } - set_x11_prop(d, "POLYP_COOKIE", pa_hexstr(cookie, sizeof(cookie), hx, sizeof(hx))); + pa_x11_set_prop(d, "POLYP_COOKIE", pa_hexstr(cookie, sizeof(cookie), hx, sizeof(hx))); break; } case REMOVE: - del_x11_prop(d, "POLYP_SERVER"); - del_x11_prop(d, "POLYP_SINK"); - del_x11_prop(d, "POLYP_SOURCE"); - del_x11_prop(d, "POLYP_ID"); - del_x11_prop(d, "POLYP_COOKIE"); + pa_x11_del_prop(d, "POLYP_SERVER"); + pa_x11_del_prop(d, "POLYP_SINK"); + pa_x11_del_prop(d, "POLYP_SOURCE"); + pa_x11_del_prop(d, "POLYP_ID"); + pa_x11_del_prop(d, "POLYP_COOKIE"); break; default: diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 1a25523fd..36512a8a3 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -44,14 +44,16 @@ #include "dynarray.h" #include "socket-client.h" #include "pstream-util.h" -#include "authkey.h" #include "util.h" #include "xmalloc.h" #include "log.h" #include "client-conf.h" #include "socket-util.h" -#define DEFAULT_SERVER "/tmp/polypaudio/native" +#ifdef HAVE_X11 +#include "client-conf-x11.h" +#endif + #define AUTOSPAWN_LOCK "/tmp/polypaudio/autospawn.lock" static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { @@ -96,6 +98,9 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->conf = pa_client_conf_new(); pa_client_conf_load(c->conf, NULL); +#ifdef HAVE_X11 + pa_client_conf_from_x11(c->conf, NULL); +#endif pa_client_conf_env(c->conf); return c; @@ -312,7 +317,7 @@ static void setup_context(struct pa_context *c, struct pa_iochannel *io) { c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); assert(c->pdispatch); - if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) { + if (!c->conf->cookie_valid) { pa_context_fail(c, PA_ERROR_AUTHKEY); goto finish; } @@ -321,7 +326,7 @@ static void setup_context(struct pa_context *c, struct pa_iochannel *io) { assert(t); pa_tagstruct_putu32(t, PA_COMMAND_AUTH); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie)); + pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); @@ -355,10 +360,10 @@ finish: static int default_server_is_running(void) { struct stat st; - if (DEFAULT_SERVER[0] != '/') + if (PA_NATIVE_DEFAULT_SERVER_UNIX[0] != '/') return 1; - if (stat(DEFAULT_SERVER, &st) < 0) + if (stat(PA_NATIVE_DEFAULT_SERVER_UNIX, &st) < 0) return 0; return 1; @@ -488,7 +493,7 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons } if (!server) - server = DEFAULT_SERVER; + server = PA_NATIVE_DEFAULT_SERVER_UNIX; pa_context_ref(c); diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 623a89b33..4e6553a8f 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -61,8 +61,6 @@ struct pa_context { uint32_t error; enum pa_context_state state; - uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; - void (*state_callback)(struct pa_context*c, void *userdata); void *state_userdata; @@ -109,7 +107,6 @@ struct pa_stream { void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); void *write_userdata; - }; struct pa_operation { diff --git a/polyp/x11prop.c b/polyp/x11prop.c new file mode 100644 index 000000000..6ff91ec4e --- /dev/null +++ b/polyp/x11prop.c @@ -0,0 +1,70 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "x11prop.h" + + +void pa_x11_set_prop(Display *d, const char *name, const char *data) { + Atom a = XInternAtom(d, name, False); + XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (unsigned char*) data, strlen(data)+1); +} + +void pa_x11_del_prop(Display *d, const char *name) { + Atom a = XInternAtom(d, name, False); + XDeleteProperty(d, RootWindow(d, 0), a); +} + +char* pa_x11_get_prop(Display *d, const char *name, char *p, size_t l) { + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long nbytes_after; + unsigned char *prop = NULL; + char *ret = NULL; + + Atom a = XInternAtom(d, name, False); + if (XGetWindowProperty(d, RootWindow(d, 0), a, 0, (l+2)/4, False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop) != Success) + goto finish; + + if (actual_type != XA_STRING) + goto finish; + + memcpy(p, prop, nitems); + p[nitems] = 0; + + ret = p; + +finish: + + if (prop) + XFree(prop); + + return ret; +} diff --git a/polyp/x11prop.h b/polyp/x11prop.h new file mode 100644 index 000000000..22461858a --- /dev/null +++ b/polyp/x11prop.h @@ -0,0 +1,33 @@ +#ifndef foox11prophfoo +#define foox11prophfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include + +void pa_x11_set_prop(Display *d, const char *name, const char *data); +void pa_x11_del_prop(Display *d, const char *name); +char* pa_x11_get_prop(Display *d, const char *name, char *p, size_t l); + +#endif From c005bd466651d8720aef3198d73bc0a3d459f953 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 11 Nov 2004 21:18:33 +0000 Subject: [PATCH 0273/1514] add username to runtime directory name in /tmp/ rework autospawning code and x11 credential publishing add support for IPv6 reenable LOWDELAY for tcp sockets git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@280 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 - polyp/Makefile.am | 52 ++++++++- polyp/client-conf-x11.c | 5 +- polyp/module-protocol-stub.c | 53 ++++++--- polyp/module-x11-publish.c | 14 ++- polyp/native-common.h | 3 +- polyp/polyplib-context.c | 218 ++++++++++++++++++++++------------- polyp/polyplib-internal.h | 6 + polyp/props.c | 7 ++ polyp/props.h | 3 + polyp/protocol-native.c | 28 ++++- polyp/socket-client.c | 191 +++++++++++++++++++++++------- polyp/socket-client.h | 6 +- polyp/socket-server.c | 145 ++++++++++++++++++++++- polyp/socket-server.h | 3 + polyp/socket-util.c | 39 +------ polyp/socket-util.h | 3 - polyp/strlist-test.c | 39 +++++++ polyp/strlist.c | 137 ++++++++++++++++++++++ polyp/strlist.h | 47 ++++++++ polyp/util.c | 83 ++++++++++--- polyp/util.h | 5 + 22 files changed, 874 insertions(+), 215 deletions(-) create mode 100644 polyp/strlist-test.c create mode 100644 polyp/strlist.c create mode 100644 polyp/strlist.h diff --git a/doc/todo b/doc/todo index 2ba697b84..99e06569a 100644 --- a/doc/todo +++ b/doc/todo @@ -2,7 +2,6 @@ *** 0.7 **** - per-channel volume -- unix socket directories include user name - add sample directory - make mcalign merge chunks - option to use default fragment size on alsa drivers @@ -13,7 +12,6 @@ - make most buffer sizes dependant on the sample type - X11: support for the X11 synchronization extension -- X11: save auth info in root window - pass meta info for hearing impaired - limit all resources - check getaddrinfo results diff --git a/polyp/Makefile.am b/polyp/Makefile.am index cc9705c25..c4f9e2d26 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -39,7 +39,8 @@ noinst_PROGRAMS = \ parec-simple \ cpulimit-test \ cpulimit-test2 \ - voltest + voltest \ + strlist-test polypconf_DATA=default.pa daemon.conf client.conf @@ -85,21 +86,26 @@ modlib_LTLIBRARIES= \ libpdispatch.la \ libauthkey.la \ libauthkey-prop.la \ + libstrlist.la \ libprotocol-simple.la \ libprotocol-esound.la \ libprotocol-native.la \ module-cli.la \ module-cli-protocol-tcp.la \ + module-cli-protocol-tcp6.la \ module-cli-protocol-unix.la \ module-pipe-sink.la \ module-pipe-source.la \ module-oss.la \ module-oss-mmap.la \ module-simple-protocol-tcp.la \ + module-simple-protocol-tcp6.la \ module-simple-protocol-unix.la \ module-esound-protocol-tcp.la \ + module-esound-protocol-tcp6.la \ module-esound-protocol-unix.la \ module-native-protocol-tcp.la \ + module-native-protocol-tcp6.la \ module-native-protocol-unix.la \ module-native-protocol-fd.la \ module-sine.la \ @@ -114,16 +120,20 @@ modlib_LTLIBRARIES= \ SYMDEF_FILES= \ module-cli-symdef.h \ module-cli-protocol-tcp-symdef.h \ + module-cli-protocol-tcp6-symdef.h \ module-cli-protocol-unix-symdef.h \ module-pipe-sink-symdef.h \ module-pipe-source-symdef.h \ module-oss-symdef.h \ module-oss-mmap-symdef.h \ module-simple-protocol-tcp-symdef.h \ + module-simple-protocol-tcp6-symdef.h \ module-simple-protocol-unix-symdef.h \ module-esound-protocol-tcp-symdef.h \ + module-esound-protocol-tcp6-symdef.h \ module-esound-protocol-unix-symdef.h \ module-native-protocol-tcp-symdef.h \ + module-native-protocol-tcp6-symdef.h \ module-native-protocol-unix-symdef.h \ module-native-protocol-fd-symdef.h \ module-sine-symdef.h \ @@ -244,13 +254,17 @@ libcli_la_SOURCES = cli.c cli.h libcli_la_LDFLAGS = -avoid-version libcli_la_LIBADD = $(AM_LIBADD) libiochannel.la libioline.la +libstrlist_la_SOURCES = strlist.c strlist.h +libstrlist_la_LDFLAGS = -avoid-version +libstrlist_la_LIBADD = $(AM_LIBADD) + libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h libprotocol_cli_la_LDFLAGS = -avoid-version libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h native-common.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la +libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la libtagstruct_la_SOURCES = tagstruct.c tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version @@ -273,6 +287,11 @@ module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $ module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-simple.la libsocket-server.la +module_simple_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_simple_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) +module_simple_protocol_tcp6_la_LDFLAGS = -module -avoid-version +module_simple_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-simple.la libsocket-server.la + module_simple_protocol_unix_la_SOURCES = module-protocol-stub.c module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version @@ -283,6 +302,11 @@ module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CF module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la +module_cli_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_cli_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) +module_cli_protocol_tcp6_la_LDFLAGS = -module -avoid-version +module_cli_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la + module_cli_protocol_unix_la_SOURCES = module-protocol-stub.c module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version @@ -293,6 +317,11 @@ module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $ module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la +module_native_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_native_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) +module_native_protocol_tcp6_la_LDFLAGS = -module -avoid-version +module_native_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la + module_native_protocol_unix_la_SOURCES = module-protocol-stub.c module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_unix_la_LDFLAGS = -module -avoid-version @@ -308,6 +337,11 @@ module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $ module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-esound.la libsocket-server.la +module_esound_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_esound_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) +module_esound_protocol_tcp6_la_LDFLAGS = -module -avoid-version +module_esound_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-esound.la libsocket-server.la + module_esound_protocol_unix_la_SOURCES = module-protocol-stub.c module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version @@ -399,7 +433,9 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ log.c log.h \ gcc-printf.h \ client-conf.c client-conf.h \ - conf-parser.c conf-parser.h + conf-parser.c conf-parser.h \ + strlist.c strlist.h \ + strbuf.c strbuf.h libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 @@ -449,11 +485,15 @@ voltest_SOURCES = voltest.c sample.c voltest_CFLAGS = $(AM_CFLAGS) voltest_LDADD = $(AM_LDADD) -cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c +strlist_test_SOURCES = strlist-test.c strlist.c strlist.h strbuf.c strbuf.h util.c util.h xmalloc.c xmalloc.h log.c log.h +strlist_test_CFLAGS = $(AM_CFLAGS) +strlist_test_LDADD = $(AM_LDADD) + +cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h cpulimit_test_CFLAGS = $(AM_CFLAGS) cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la -cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c +cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la @@ -487,7 +527,7 @@ module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA module_x11_publish_la_SOURCES = module-x11-publish.c module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_publish_la_LDFLAGS = -module -avoid-version -module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauthkey-prop.la libx11prop.la +module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauthkey-prop.la libx11prop.la libstrlist.la bin_PROGRAMS+= \ pax11publish diff --git a/polyp/client-conf-x11.c b/polyp/client-conf-x11.c index 54c3b06a8..f667bd784 100644 --- a/polyp/client-conf-x11.c +++ b/polyp/client-conf-x11.c @@ -39,7 +39,10 @@ int pa_client_conf_from_x11(struct pa_client_conf *c, const char *dname) { Display *d = NULL; int ret = -1; char t[1024]; - + + if (!dname && !getenv("DISPLAY")) + goto finish; + if (!(d = XOpenDisplay(dname))) { pa_log(__FILE__": XOpenDisplay() failed\n"); goto finish; diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 6ff7d7743..6a0f88a28 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -38,10 +38,14 @@ #include "modargs.h" #include "log.h" #include "native-common.h" +#include "util.h" #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" #define SOCKET_USAGE "port= loopback=" +#elif defined(USE_TCP6_SOCKETS) +#define SOCKET_DESCRIPTION "(TCP/IPv6 sockets)" +#define SOCKET_USAGE "port= loopback=" #else #define SOCKET_DESCRIPTION "(UNIX sockets)" #define SOCKET_USAGE "socket=" @@ -53,10 +57,12 @@ #define protocol_free pa_protocol_simple_free #define TCPWRAP_SERVICE "polypaudio-simple" #define IPV4_PORT 4711 - #define UNIX_SOCKET "/tmp/polypaudio/simple" + #define UNIX_SOCKET "simple" #define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record", - #ifdef USE_TCP_SOCKETS + #if defined(USE_TCP_SOCKETS) #include "module-simple-protocol-tcp-symdef.h" + #elif defined(USE_TCP6_SOCKETS) + #include "module-simple-protocol-tcp6-symdef.h" #else #include "module-simple-protocol-unix-symdef.h" #endif @@ -68,10 +74,12 @@ #define protocol_free pa_protocol_cli_free #define TCPWRAP_SERVICE "polypaudio-cli" #define IPV4_PORT 4712 - #define UNIX_SOCKET "/tmp/polypaudio/cli" + #define UNIX_SOCKET "cli" #define MODULE_ARGUMENTS #ifdef USE_TCP_SOCKETS #include "module-cli-protocol-tcp-symdef.h" + #elif defined(USE_TCP6_SOCKETS) + #include "module-cli-protocol-tcp6-symdef.h" #else #include "module-cli-protocol-unix-symdef.h" #endif @@ -83,10 +91,12 @@ #define protocol_free pa_protocol_native_free #define TCPWRAP_SERVICE "polypaudio-native" #define IPV4_PORT PA_NATIVE_DEFAULT_PORT - #define UNIX_SOCKET PA_NATIVE_DEFAULT_SERVER_UNIX + #define UNIX_SOCKET PA_NATIVE_DEFAULT_UNIX_SOCKET #define MODULE_ARGUMENTS "public", "cookie", #ifdef USE_TCP_SOCKETS #include "module-native-protocol-tcp-symdef.h" + #elif defined(USE_TCP6_SOCKETS) + #include "module-native-protocol-tcp6-symdef.h" #else #include "module-native-protocol-unix-symdef.h" #endif @@ -103,6 +113,8 @@ #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", #ifdef USE_TCP_SOCKETS #include "module-esound-protocol-tcp-symdef.h" + #elif defined(USE_TCP6_SOCKETS) + #include "module-esound-protocol-tcp6-symdef.h" #else #include "module-esound-protocol-unix-symdef.h" #endif @@ -117,7 +129,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) static const char* const valid_modargs[] = { MODULE_ARGUMENTS -#ifdef USE_TCP_SOCKETS +#if defined(USE_TCP_SOCKETS) || defined(USE_TCP6_SOCKETS) "port", "loopback", #else @@ -128,7 +140,7 @@ static const char* const valid_modargs[] = { static struct pa_socket_server *create_socket_server(struct pa_core *c, struct pa_modargs *ma) { struct pa_socket_server *s; -#ifdef USE_TCP_SOCKETS +#if defined(USE_TCP_SOCKETS) || defined(USE_TCP6_SOCKETS) int loopback = 1; uint32_t port = IPV4_PORT; @@ -141,30 +153,39 @@ static struct pa_socket_server *create_socket_server(struct pa_core *c, struct p pa_log(__FILE__": port= expects a numerical argument between 1 and 65535.\n"); return NULL; } - - if (!(s = pa_socket_server_new_ipv4(c->mainloop, loopback ? INADDR_LOOPBACK : INADDR_ANY, port, TCPWRAP_SERVICE))) + +#ifdef USE_TCP6_SOCKETS + if (!(s = pa_socket_server_new_ipv6(c->mainloop, loopback ? (uint8_t*) &in6addr_loopback : (uint8_t*) &in6addr_any, port))) return NULL; +#else + if (!(s = pa_socket_server_new_ipv4(c->mainloop, loopback ? INADDR_LOOPBACK : INADDR_ANY, port, TCPWRAP_SERVICE))) + return NULL; +#endif + #else int r; - const char *p; + const char *v; + char tmp[PATH_MAX]; - p = pa_modargs_get_value(ma, "socket", UNIX_SOCKET); - assert(p); + v = pa_modargs_get_value(ma, "socket", UNIX_SOCKET); + assert(v); - if (pa_unix_socket_make_secure_dir(p) < 0) { + pa_runtime_path(v, tmp, sizeof(tmp)); + + if (pa_make_secure_parent_dir(tmp) < 0) { pa_log(__FILE__": Failed to create secure socket directory.\n"); return NULL; } - if ((r = pa_unix_socket_remove_stale(p)) < 0) { - pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s\n", p, strerror(errno)); + if ((r = pa_unix_socket_remove_stale(tmp)) < 0) { + pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s\n", tmp, strerror(errno)); return NULL; } if (r) - pa_log(__FILE__": Removed stale UNIX socket '%s'.", p); + pa_log(__FILE__": Removed stale UNIX socket '%s'.", tmp); - if (!(s = pa_socket_server_new_unix(c->mainloop, p))) + if (!(s = pa_socket_server_new_unix(c->mainloop, tmp))) return NULL; #endif diff --git a/polyp/module-x11-publish.c b/polyp/module-x11-publish.c index 6e100153f..60284bd64 100644 --- a/polyp/module-x11-publish.c +++ b/polyp/module-x11-publish.c @@ -46,6 +46,8 @@ #include "authkey-prop.h" #include "authkey.h" #include "x11prop.h" +#include "strlist.h" +#include "props.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("X11 Credential Publisher") @@ -101,6 +103,8 @@ int pa__init(struct pa_core *c, struct pa_module*m) { char hn[256], un[128]; char hx[PA_NATIVE_COOKIE_LENGTH*2+1]; const char *t; + char *s; + struct pa_strlist *l; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments\n"); @@ -120,15 +124,17 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->display = pa_x11_wrapper_get_display(u->x11_wrapper); - if (!pa_get_fqdn(hn, sizeof(hn))) + if (!(l = pa_property_get(c, PA_NATIVE_SERVER_PROPERTY_NAME))) goto fail; + + s = pa_strlist_tostring(l); + pa_x11_set_prop(u->display, "POLYP_SERVER", s); + pa_xfree(s); - if (!pa_get_user_name(un, sizeof(un))) + if (!pa_get_fqdn(hn, sizeof(hn)) || !pa_get_user_name(un, sizeof(un))) goto fail; u->id = pa_sprintf_malloc("%s@%s/%u", un, hn, (unsigned) getpid()); - - pa_x11_set_prop(u->display, "POLYP_SERVER", hn); pa_x11_set_prop(u->display, "POLYP_ID", u->id); if ((t = pa_modargs_get_value(ma, "source", NULL))) diff --git a/polyp/native-common.h b/polyp/native-common.h index 597bb56b0..28a471d00 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -99,8 +99,9 @@ enum { #define PA_NATIVE_DEFAULT_PORT 4713 #define PA_NATIVE_COOKIE_PROPERTY_NAME "protocol-native-cookie" +#define PA_NATIVE_SERVER_PROPERTY_NAME "protocol-native-server" -#define PA_NATIVE_DEFAULT_SERVER_UNIX "/tmp/polypaudio/native" +#define PA_NATIVE_DEFAULT_UNIX_SOCKET "native" PA_C_DECL_END diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 36512a8a3..a47703130 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -54,7 +54,9 @@ #include "client-conf-x11.h" #endif -#define AUTOSPAWN_LOCK "/tmp/polypaudio/autospawn.lock" +#define AUTOSPAWN_LOCK "autospawn.lock" + + static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = { pa_command_request }, @@ -63,6 +65,16 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SUBSCRIBE_EVENT] = { pa_command_subscribe_event }, }; +static void unlock_autospawn_lock_file(struct pa_context *c) { + assert(c); + + if (c->autospawn_lock_fd >= 0) { + pa_unlock_lockfile(c->autospawn_lock_fd); + c->autospawn_lock_fd = -1; + } + +} + struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { struct pa_context *c; assert(mainloop && name); @@ -93,6 +105,10 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->memblock_stat = pa_memblock_stat_new(); c->local = -1; + c->server_list = NULL; + c->autospawn_lock_fd = -1; + memset(&c->spawn_api, 0, sizeof(c->spawn_api)); + c->do_autospawn = 0; pa_check_signal_is_blocked(SIGPIPE); @@ -109,6 +125,8 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * static void context_free(struct pa_context *c) { assert(c); + unlock_autospawn_lock_file(c); + while (c->operations) pa_operation_cancel(c->operations); @@ -133,6 +151,8 @@ static void context_free(struct pa_context *c) { if (c->conf) pa_client_conf_free(c->conf); + + pa_strlist_free(c->server_list); pa_xfree(c->name); pa_xfree(c); @@ -337,38 +357,9 @@ finish: pa_context_unref(c); } -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { - struct pa_context *c = userdata; - assert(client && c && c->state == PA_CONTEXT_CONNECTING); +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata); - pa_context_ref(c); - - pa_socket_client_unref(client); - c->client = NULL; - - if (!io) { - pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); - goto finish; - } - - setup_context(c, io); - -finish: - pa_context_unref(c); -} - -static int default_server_is_running(void) { - struct stat st; - - if (PA_NATIVE_DEFAULT_SERVER_UNIX[0] != '/') - return 1; - - if (stat(PA_NATIVE_DEFAULT_SERVER_UNIX, &st) < 0) - return 0; - - return 1; -} -static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api *api) { +static int context_connect_spawn(struct pa_context *c) { pid_t pid; int status, r; int fds[2] = { -1, -1} ; @@ -382,15 +373,20 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api goto fail; } - if (api && api->prefork) - api->prefork(); + pa_fd_set_cloexec(fds[0], 1); + + pa_socket_low_delay(fds[0]); + pa_socket_low_delay(fds[1]); + + if (c->spawn_api.prefork) + c->spawn_api.prefork(); if ((pid = fork()) < 0) { pa_log(__FILE__": fork() failed: %s\n", strerror(errno)); pa_context_fail(c, PA_ERROR_INTERNAL); - if (api && api->postfork) - api->postfork(); + if (c->spawn_api.postfork) + c->spawn_api.postfork(); goto fail; } else if (!pid) { @@ -402,10 +398,11 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api char *argv[MAX_ARGS+1]; int n; + /* Not required, since fds[0] has CLOEXEC enabled anyway */ close(fds[0]); - if (api && api->atfork) - api->atfork(); + if (c->spawn_api.atfork) + c->spawn_api.atfork(); /* Setup argv */ @@ -430,14 +427,15 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api execv(argv[0], argv); _exit(1); +#undef MAX_ARGS } /* Parent */ r = waitpid(pid, &status, 0); - if (api && api->postfork) - api->postfork(); + if (c->spawn_api.postfork) + c->spawn_api.postfork(); if (r < 0) { pa_log(__FILE__": waitpid() failed: %s\n", strerror(errno)); @@ -453,7 +451,9 @@ static int context_connect_spawn(struct pa_context *c, const struct pa_spawn_api c->local = 1; io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); + setup_context(c, io); + unlock_autospawn_lock_file(c); pa_context_unref(c); @@ -465,11 +465,84 @@ fail: if (fds[1] != -1) close(fds[1]); + unlock_autospawn_lock_file(c); + pa_context_unref(c); return -1; } +static int try_next_connection(struct pa_context *c) { + char *u = NULL; + int r = -1; + assert(c && !c->client); + + for (;;) { + if (u) + pa_xfree(u); + u = NULL; + + c->server_list = pa_strlist_pop(c->server_list, &u); + + if (!u) { + + if (c->do_autospawn) { + r = context_connect_spawn(c); + goto finish; + } + + pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + goto finish; + } + +/* pa_log(__FILE__": Trying to connect to %s...\n", u); */ + + if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT))) + continue; + + c->local = pa_socket_client_is_local(c->client); + pa_socket_client_set_callback(c->client, on_connection, c); + break; + } + + r = 0; + +finish: + if (u) + pa_xfree(u); + + return r; +} + +static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { + struct pa_context *c = userdata; + assert(client && c && c->state == PA_CONTEXT_CONNECTING); + + pa_context_ref(c); + + pa_socket_client_unref(client); + c->client = NULL; + + if (!io) { + pa_log("failure: %s\n", strerror(errno)); + + /* Try the item in the list */ + if (errno == ECONNREFUSED || errno == ETIMEDOUT || errno == EHOSTUNREACH) { + try_next_connection(c); + goto finish; + } + + pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + goto finish; + } + + unlock_autospawn_lock_file(c); + setup_context(c, io); + +finish: + pa_context_unref(c); +} + int pa_context_connect(struct pa_context *c, const char *server, int spawn, const struct pa_spawn_api *api) { int r = -1; assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED); @@ -477,59 +550,46 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons if (!server) server = c->conf->default_server; - if (!server && spawn && c->conf->autospawn) { - int lock_fd = pa_lock_lockfile(AUTOSPAWN_LOCK); - - if (!default_server_is_running()) { - int r = context_connect_spawn(c, api); - - if (lock_fd >= 0) - pa_unlock_lockfile(lock_fd); - return r; - } - - if (lock_fd >= 0) - pa_unlock_lockfile(lock_fd); - } - - if (!server) - server = PA_NATIVE_DEFAULT_SERVER_UNIX; pa_context_ref(c); - assert(!c->client); + assert(!c->server_list); - if (*server == '/') { - if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) { - pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); - goto finish; - } - - c->local = 1; - } else { - struct sockaddr* sa; - size_t sa_len; - - if (!(sa = pa_resolve_server(server, &sa_len, PA_NATIVE_DEFAULT_PORT))) { + if (server) { + if (!(c->server_list = pa_strlist_parse(server))) { pa_context_fail(c, PA_ERROR_INVALIDSERVER); goto finish; } + } else { + char *d; + char ufn[PATH_MAX]; - c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len); - pa_xfree(sa); + /* Prepend in reverse order */ + + if ((d = getenv("DISPLAY"))) + c->server_list = pa_strlist_prepend(c->server_list, d); + + c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost"); + c->server_list = pa_strlist_prepend(c->server_list, "localhost"); + c->server_list = pa_strlist_prepend(c->server_list, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET, ufn, sizeof(ufn))); - if (!c->client) { - pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); - goto finish; + /* Wrap the connection attempts in a single transaction for sane autospwan locking */ + if (spawn && c->conf->autospawn) { + char lf[PATH_MAX]; + + pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); + assert(c->autospawn_lock_fd <= 0); + c->autospawn_lock_fd = pa_lock_lockfile(lf); + + if (api) + c->spawn_api = *api; + c->do_autospawn = 1; } - c->local = 0; } - pa_socket_client_set_callback(c->client, on_connection, c); pa_context_set_state(c, PA_CONTEXT_CONNECTING); - - r = 0; + r = try_next_connection(c); finish: pa_context_unref(c); diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 4e6553a8f..589388f84 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -34,6 +34,7 @@ #include "llist.h" #include "native-common.h" #include "client-conf.h" +#include "strlist.h" #define DEFAULT_TLENGTH (44100*2*2/2) //(10240*8) #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) @@ -70,6 +71,11 @@ struct pa_context { struct pa_memblock_stat *memblock_stat; int local; + int do_autospawn; + int autospawn_lock_fd; + struct pa_spawn_api spawn_api; + + struct pa_strlist *server_list; struct pa_client_conf *conf; }; diff --git a/polyp/props.c b/polyp/props.c index 014059ec0..596133bc4 100644 --- a/polyp/props.c +++ b/polyp/props.c @@ -110,3 +110,10 @@ void pa_property_dump(struct pa_core *c, struct pa_strbuf *s) { while ((p = pa_hashmap_iterate(c->properties, &state, NULL))) pa_strbuf_printf(s, "[%s] -> [%p]\n", p->name, p->data); } + +int pa_property_replace(struct pa_core *c, const char *name, void *data) { + assert(c && name); + + pa_property_remove(c, name); + return pa_property_set(c, name, data); +} diff --git a/polyp/props.h b/polyp/props.h index f19e9260f..954d25404 100644 --- a/polyp/props.h +++ b/polyp/props.h @@ -43,6 +43,9 @@ int pa_property_set(struct pa_core *c, const char *name, void *data); /* Remove the specified property. Return non-zero on failure */ int pa_property_remove(struct pa_core *c, const char *name); +/* A combination of pa_property_remove() and pa_property_set() */ +int pa_property_replace(struct pa_core *c, const char *name, void *data); + /* Free all memory used by the property system */ void pa_property_cleanup(struct pa_core *c); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index fade2a2ff..0102e0caf 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -47,6 +47,8 @@ #include "log.h" #include "autoload.h" #include "authkey-prop.h" +#include "strlist.h" +#include "props.h" struct connection; struct pa_protocol_native; @@ -2064,6 +2066,7 @@ static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struc } struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { + char t[256]; struct pa_protocol_native *p; if (!(p = protocol_new_internal(core, m, ma))) @@ -2071,6 +2074,13 @@ struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct p p->server = server; pa_socket_server_set_callback(p->server, on_connection, p); + + if (pa_socket_server_get_address(p->server, t, sizeof(t))) { + struct pa_strlist *l; + l = pa_property_get(core, PA_NATIVE_SERVER_PROPERTY_NAME); + l = pa_strlist_prepend(l, t); + pa_property_replace(core, PA_NATIVE_SERVER_PROPERTY_NAME, l); + } return p; } @@ -2083,12 +2093,26 @@ void pa_protocol_native_free(struct pa_protocol_native *p) { connection_free(c); pa_idxset_free(p->connections, NULL, NULL); - if (p->server) + if (p->server) { + char t[256]; + + if (pa_socket_server_get_address(p->server, t, sizeof(t))) { + struct pa_strlist *l; + l = pa_property_get(p->core, PA_NATIVE_SERVER_PROPERTY_NAME); + l = pa_strlist_remove(l, t); + + if (l) + pa_property_replace(p->core, PA_NATIVE_SERVER_PROPERTY_NAME, l); + else + pa_property_remove(p->core, PA_NATIVE_SERVER_PROPERTY_NAME); + } + pa_socket_server_unref(p->server); + } if (p->auth_cookie_in_property) pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); - + pa_xfree(p); } diff --git a/polyp/socket-client.c b/polyp/socket-client.c index fbc259ff5..9b80d8098 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "socket-client.h" #include "socket-util.h" @@ -47,6 +48,7 @@ struct pa_socket_client { struct pa_defer_event *defer_event; void (*callback)(struct pa_socket_client*c, struct pa_iochannel *io, void *userdata); void *userdata; + int local; }; static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { @@ -61,6 +63,7 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { c->defer_event = NULL; c->callback = NULL; c->userdata = NULL; + c->local = 0; return c; } @@ -85,6 +88,7 @@ static void do_call(struct pa_socket_client *c) { if (error != 0) { /* pa_log(__FILE__": connect(): %s\n", strerror(error)); */ + errno = error; goto finish; } @@ -141,63 +145,27 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc } struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port) { - struct pa_socket_client *c; struct sockaddr_in sa; - assert(m && address && port); - - c = pa_socket_client_new(m); - assert(c); - - if ((c->fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s\n", strerror(errno)); - goto fail; - } - - pa_fd_set_cloexec(c->fd, 1); - pa_socket_tcp_low_delay(c->fd); + assert(m && port > 0); + memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(address); - if (do_connect(c, (struct sockaddr*) &sa, sizeof(sa)) < 0) - goto fail; - - return c; - -fail: - pa_socket_client_unref(c); - return NULL; + return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa)); } struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) { - struct pa_socket_client *c; struct sockaddr_un sa; assert(m && filename); - c = pa_socket_client_new(m); - assert(c); - - if ((c->fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s\n", strerror(errno)); - goto fail; - } - - pa_fd_set_cloexec(c->fd, 1); - pa_socket_low_delay(c->fd); - + memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_LOCAL; strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); sa.sun_path[sizeof(sa.sun_path) - 1] = 0; - - if (do_connect(c, (struct sockaddr*) &sa, sizeof(sa)) < 0) - goto fail; - - return c; -fail: - pa_socket_client_unref(c); - return NULL; + return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa)); } struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) { @@ -206,13 +174,30 @@ struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m c = pa_socket_client_new(m); assert(c); + switch (sa->sa_family) { + case AF_UNIX: + c->local = 1; + break; + + case AF_INET: + c->local = ((const struct sockaddr_in*) sa)->sin_addr.s_addr == INADDR_LOOPBACK; + break; + + case AF_INET6: + c->local = memcmp(&((const struct sockaddr_in6*) sa)->sin6_addr, &in6addr_loopback, sizeof(struct in6_addr)) == 0; + break; + + default: + c->local = 0; + } + if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) { pa_log(__FILE__": socket(): %s\n", strerror(errno)); goto fail; } pa_fd_set_cloexec(c->fd, 1); - if (sa->sa_family == AF_INET) + if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6) pa_socket_tcp_low_delay(c->fd); else pa_socket_low_delay(c->fd); @@ -257,3 +242,125 @@ void pa_socket_client_set_callback(struct pa_socket_client *c, void (*on_connect c->callback = on_connection; c->userdata = userdata; } + +struct pa_socket_client* pa_socket_client_new_ipv6(struct pa_mainloop_api *m, uint8_t address[16], uint16_t port) { + struct sockaddr_in6 sa; + + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; + sa.sin6_port = htons(port); + memcpy(&sa.sin6_addr, address, sizeof(sa.sin6_addr)); + + return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa)); +} + +/* Parse addresses in one of the following forms: + * HOSTNAME + * HOSTNAME:PORT + * [HOSTNAME] + * [HOSTNAME]:PORT + * + * Return a newly allocated string of the hostname and fill in *port if specified */ + +static char *parse_address(const char *s, uint16_t *port) { + assert(s && port); + if (*s == '[') { + char *e; + if (!(e = strchr(s+1, ']'))) + return NULL; + + if (e[1] == ':') + *port = atoi(e+2); + else if (e[1] != 0) + return NULL; + + return pa_xstrndup(s+1, e-s-1); + } else { + char *e; + + if (!(e = strrchr(s, ':'))) + return pa_xstrdup(s); + + *port = atoi(e+1); + return pa_xstrndup(s, e-s); + } +} + +struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, const char*name, uint16_t default_port) { + const char *p; + struct pa_socket_client *c = NULL; + enum { KIND_UNIX, KIND_TCP_AUTO, KIND_TCP4, KIND_TCP6 } kind = KIND_TCP_AUTO; + assert(m && name); + + if (*name == '{') { + char hn[256], *pfx; + /* The URL starts with a host specification for detecting local connections */ + + if (!pa_get_host_name(hn, sizeof(hn))) + return NULL; + + pfx = pa_sprintf_malloc("{%s}", hn); + if (!pa_startswith(name, pfx)) + /* Not local */ + return NULL; + + p = name + strlen(pfx); + } else + p = name; + + if (*p == '/') + kind = KIND_UNIX; + else if (pa_startswith(p, "unix:")) { + kind = KIND_UNIX; + p += sizeof("unix:")-1; + } else if (pa_startswith(p, "tcp:") || pa_startswith(p, "tcp4:")) { + kind = KIND_TCP4; + p += sizeof("tcp:")-1; + } else if (pa_startswith(p, "tcp6:")) { + kind = KIND_TCP6; + p += sizeof("tcp6:")-1; + } + + switch (kind) { + case KIND_UNIX: + return pa_socket_client_new_unix(m, p); + + case KIND_TCP_AUTO: /* Fallthrough */ + case KIND_TCP4: + case KIND_TCP6: { + uint16_t port = default_port; + char *h; + struct addrinfo hints, *res; + + if (!(h = parse_address(p, &port))) + return NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = kind == KIND_TCP4 ? AF_INET : (kind == KIND_TCP6 ? AF_INET6 : AF_UNSPEC); + + if (getaddrinfo(h, NULL, &hints, &res) < 0 || !res) + return NULL; + + if (res->ai_addr->sa_family == AF_INET) + ((struct sockaddr_in*) res->ai_addr)->sin_port = htons(port); + else if (res->ai_addr->sa_family == AF_INET6) + ((struct sockaddr_in6*) res->ai_addr)->sin6_port = htons(port); + else + return NULL; + + c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + return c; + } + } + + /* Should never be reached */ + assert(0); + return NULL; + +} + +int pa_socket_client_is_local(struct pa_socket_client *c) { + assert(c); + return c->local; +} diff --git a/polyp/socket-client.h b/polyp/socket-client.h index 1957355c6..262fbac3c 100644 --- a/polyp/socket-client.h +++ b/polyp/socket-client.h @@ -28,17 +28,19 @@ #include "mainloop-api.h" #include "iochannel.h" -/* It is safe to destroy the calling socket_client object from the callback */ - struct pa_socket_client; struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); +struct pa_socket_client* pa_socket_client_new_ipv6(struct pa_mainloop_api *m, uint8_t address[16], uint16_t port); struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename); struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen); +struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, const char *a, uint16_t default_port); void pa_socket_client_unref(struct pa_socket_client *c); struct pa_socket_client* pa_socket_client_ref(struct pa_socket_client *c); void pa_socket_client_set_callback(struct pa_socket_client *c, void (*on_connection)(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata), void *userdata); +int pa_socket_client_is_local(struct pa_socket_client *c); + #endif diff --git a/polyp/socket-server.c b/polyp/socket-server.c index c170bf6ee..a37b3e34e 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -56,7 +56,7 @@ struct pa_socket_server { struct pa_io_event *io_event; struct pa_mainloop_api *mainloop; - enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX } type; + enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX, SOCKET_SERVER_IPV6 } type; }; static void callback(struct pa_mainloop_api *mainloop, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { @@ -202,6 +202,7 @@ struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, ui pa_socket_tcp_low_delay(fd); + memset(&sa, sizeof(sa), 0); sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(address); @@ -230,6 +231,53 @@ fail: return NULL; } +struct pa_socket_server* pa_socket_server_new_ipv6(struct pa_mainloop_api *m, uint8_t address[16], uint16_t port) { + struct pa_socket_server *ss; + int fd = -1; + struct sockaddr_in6 sa; + int on = 1; + + assert(m && port); + + if ((fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) { + pa_log(__FILE__": socket(): %s\n", strerror(errno)); + goto fail; + } + + pa_fd_set_cloexec(fd, 1); + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) + pa_log(__FILE__": setsockopt(): %s\n", strerror(errno)); + + pa_socket_tcp_low_delay(fd); + + memset(&sa, sizeof(sa), 0); + sa.sin6_family = AF_INET6; + sa.sin6_port = htons(port); + memcpy(sa.sin6_addr.s6_addr, address, 16); + + if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { + pa_log(__FILE__": bind(): %s\n", strerror(errno)); + goto fail; + } + + if (listen(fd, 5) < 0) { + pa_log(__FILE__": listen(): %s\n", strerror(errno)); + goto fail; + } + + if ((ss = pa_socket_server_new(m, fd))) + ss->type = SOCKET_SERVER_IPV6; + + return ss; + +fail: + if (fd >= 0) + close(fd); + + return NULL; +} + static void socket_server_free(struct pa_socket_server*s) { assert(s); close(s->fd); @@ -258,3 +306,98 @@ void pa_socket_server_set_callback(struct pa_socket_server*s, void (*on_connecti s->on_connection = on_connection; s->userdata = userdata; } + + +char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l) { + assert(s && c && l > 0); + + switch (s->type) { + case SOCKET_SERVER_IPV6: { + struct sockaddr_in6 sa; + socklen_t l = sizeof(sa); + + if (getsockname(s->fd, (struct sockaddr*) &sa, &l) < 0) { + pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno)); + return NULL; + } + + if (memcmp(&in6addr_any, &sa.sin6_addr, sizeof(in6addr_any)) == 0) { + char fqdn[256]; + if (!pa_get_fqdn(fqdn, sizeof(fqdn))) + return NULL; + + snprintf(c, l, "tcp6:%s:%u", fqdn, (unsigned) ntohs(sa.sin6_port)); + + } else if (memcmp(&in6addr_loopback, &sa.sin6_addr, sizeof(in6addr_loopback)) == 0) { + char hn[256]; + if (!pa_get_host_name(hn, sizeof(hn))) + return NULL; + + snprintf(c, l, "{%s}tcp6:localhost:%u", hn, (unsigned) ntohs(sa.sin6_port)); + } else { + char ip[INET6_ADDRSTRLEN]; + + if (!inet_ntop(AF_INET6, &sa.sin6_addr, ip, sizeof(ip))) { + pa_log(__FILE__": inet_ntop() failed: %s\n", strerror(errno)); + return NULL; + } + + snprintf(c, l, "tcp6:[%s]:%u", ip, (unsigned) ntohs(sa.sin6_port)); + } + + return c; + } + + case SOCKET_SERVER_IPV4: { + struct sockaddr_in sa; + socklen_t l = sizeof(sa); + + if (getsockname(s->fd, &sa, &l) < 0) { + pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno)); + return NULL; + } + + if (sa.sin_addr.s_addr == INADDR_ANY) { + char fqdn[256]; + if (!pa_get_fqdn(fqdn, sizeof(fqdn))) + return NULL; + + snprintf(c, l, "tcp:%s:%u", fqdn, (unsigned) ntohs(sa.sin_port)); + } else if (sa.sin_addr.s_addr == INADDR_LOOPBACK) { + char hn[256]; + if (!pa_get_host_name(hn, sizeof(hn))) + return NULL; + + snprintf(c, l, "{%s}tcp:localhost:%u", hn, (unsigned) ntohs(sa.sin_port)); + } else { + char ip[INET_ADDRSTRLEN]; + + if (!inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip))) { + pa_log(__FILE__": inet_ntop() failed: %s\n", strerror(errno)); + return NULL; + } + + snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port)); + + } + + return c; + } + + case SOCKET_SERVER_UNIX: { + char hn[256]; + + if (!s->filename) + return NULL; + + if (!pa_get_host_name(hn, sizeof(hn))) + return NULL; + + snprintf(c, l, "{%s}unix:%s", hn, s->filename); + return c; + } + + default: + return NULL; + } +} diff --git a/polyp/socket-server.h b/polyp/socket-server.h index f5877e557..cc5524d1e 100644 --- a/polyp/socket-server.h +++ b/polyp/socket-server.h @@ -33,10 +33,13 @@ struct pa_socket_server; struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd); struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename); struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service); +struct pa_socket_server* pa_socket_server_new_ipv6(struct pa_mainloop_api *m, uint8_t address[16], uint16_t port); void pa_socket_server_unref(struct pa_socket_server*s); struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *s); void pa_socket_server_set_callback(struct pa_socket_server*s, void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata), void *userdata); +char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l); + #endif diff --git a/polyp/socket-util.c b/polyp/socket-util.c index 96ea2c607..e0540179a 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -114,7 +114,7 @@ int pa_socket_tcp_low_delay(int fd) { ret = pa_socket_low_delay(fd); on = 1; -/* + #if defined(SOL_TCP) || defined(IPPROTO_TCP) #if defined(SOL_TCP) if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) @@ -123,7 +123,6 @@ int pa_socket_tcp_low_delay(int fd) { #endif ret = -1; #endif -*/ #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || \ defined(IPPROTO_IP)) @@ -204,42 +203,6 @@ int pa_unix_socket_remove_stale(const char *fn) { return 0; } -int pa_unix_socket_make_secure_dir(const char *fn) { - int ret = -1; - char *slash, *dir = pa_xstrdup(fn); - - if (!(slash = strrchr(dir, '/'))) - goto finish; - *slash = 0; - - if (pa_make_secure_dir(dir) < 0) - goto finish; - - ret = 0; - -finish: - pa_xfree(dir); - return ret; -} - -int pa_unix_socket_remove_secure_dir(const char *fn) { - int ret = -1; - char *slash, *dir = pa_xstrdup(fn); - - if (!(slash = strrchr(dir, '/'))) - goto finish; - *slash = 0; - - if (rmdir(dir) < 0) - goto finish; - - ret = 0; - -finish: - pa_xfree(dir); - return ret; -} - struct sockaddr *pa_resolve_server(const char *server, size_t *len, uint16_t nport) { struct sockaddr *sa; struct addrinfo hints, *result = NULL; diff --git a/polyp/socket-util.h b/polyp/socket-util.h index 46fcfdc97..aa2de8a52 100644 --- a/polyp/socket-util.h +++ b/polyp/socket-util.h @@ -35,9 +35,6 @@ int pa_socket_set_rcvbuf(int fd, size_t l); int pa_unix_socket_is_stale(const char *fn); int pa_unix_socket_remove_stale(const char *fn); -int pa_unix_socket_make_secure_dir(const char *fn); -int pa_unix_socket_remove_secure_dir(const char *fn); - struct sockaddr *pa_resolve_server(const char *server, size_t *len, uint16_t port); #endif diff --git a/polyp/strlist-test.c b/polyp/strlist-test.c new file mode 100644 index 000000000..01dcdf127 --- /dev/null +++ b/polyp/strlist-test.c @@ -0,0 +1,39 @@ +#include + +#include "strlist.h" +#include "xmalloc.h" + +int main(int argc, char* argv[]) { + char *t, *u; + struct pa_strlist *l = NULL; + + l = pa_strlist_prepend(l, "e"); + l = pa_strlist_prepend(l, "d"); + l = pa_strlist_prepend(l, "c"); + l = pa_strlist_prepend(l, "b"); + l = pa_strlist_prepend(l, "a"); + + t = pa_strlist_tostring(l); + pa_strlist_free(l); + + fprintf(stderr, "1: %s\n", t); + + l = pa_strlist_parse(t); + pa_xfree(t); + + t = pa_strlist_tostring(l); + fprintf(stderr, "2: %s\n", t); + pa_xfree(t); + + l = pa_strlist_pop(l, &u); + fprintf(stderr, "3: %s\n", u); + pa_xfree(u); + + l = pa_strlist_remove(l, "c"); + + t = pa_strlist_tostring(l); + fprintf(stderr, "4: %s\n", t); + pa_xfree(t); + + pa_strlist_free(l); +} diff --git a/polyp/strlist.c b/polyp/strlist.c new file mode 100644 index 000000000..df7278d23 --- /dev/null +++ b/polyp/strlist.c @@ -0,0 +1,137 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "strlist.h" +#include "xmalloc.h" +#include "strbuf.h" +#include "util.h" + +struct pa_strlist { + struct pa_strlist *next; + char *str; +}; + +struct pa_strlist* pa_strlist_prepend(struct pa_strlist *l, const char *s) { + struct pa_strlist *n; + assert(s); + n = pa_xmalloc(sizeof(struct pa_strlist)); + n->str = pa_xstrdup(s); + n->next = l; + return n; +} + +char *pa_strlist_tostring(struct pa_strlist *l) { + int first = 1; + struct pa_strbuf *b; + + b = pa_strbuf_new(); + for (; l; l = l->next) { + if (!first) + pa_strbuf_puts(b, " "); + first = 0; + pa_strbuf_puts(b, l->str); + } + + return pa_strbuf_tostring_free(b); +} + +struct pa_strlist* pa_strlist_remove(struct pa_strlist *l, const char *s) { + struct pa_strlist *ret = l, *prev = NULL; + assert(l && s); + + while (l) { + if (!strcmp(l->str, s)) { + struct pa_strlist *n = l->next; + + if (!prev) { + assert(ret == l); + ret = n; + } else + prev->next = n; + + pa_xfree(l->str); + pa_xfree(l); + + l = n; + + } else { + prev = l; + l = l->next; + } + } + + return ret; +} + +void pa_strlist_free(struct pa_strlist *l) { + while (l) { + struct pa_strlist *c = l; + l = l->next; + + pa_xfree(c->str); + pa_xfree(c); + } +} + +struct pa_strlist* pa_strlist_pop(struct pa_strlist *l, char **s) { + struct pa_strlist *r; + assert(s); + + if (!l) { + *s = NULL; + return NULL; + } + + *s = l->str; + r = l->next; + pa_xfree(l); + return r; +} + +struct pa_strlist* pa_strlist_parse(const char *s) { + struct pa_strlist *head = NULL, *p = NULL; + const char *state = NULL; + char *r; + + while ((r = pa_split_spaces(s, &state))) { + struct pa_strlist *n; + + n = pa_xmalloc(sizeof(struct pa_strlist)); + n->str = r; + n->next = NULL; + + if (p) + p->next = n; + else + head = n; + + p = n; + } + + return head; +} diff --git a/polyp/strlist.h b/polyp/strlist.h new file mode 100644 index 000000000..2a209dbaa --- /dev/null +++ b/polyp/strlist.h @@ -0,0 +1,47 @@ +#ifndef foostrlisthfoo +#define foostrlisthfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +struct pa_strlist; + +/* Add the specified server string to the list, return the new linked list head */ +struct pa_strlist* pa_strlist_prepend(struct pa_strlist *l, const char *s); + +/* Remove the specified string from the list, return the new linked list head */ +struct pa_strlist* pa_strlist_remove(struct pa_strlist *l, const char *s); + +/* Make a whitespace separated string of all server stringes. Returned memory has to be freed with pa_xfree() */ +char *pa_strlist_tostring(struct pa_strlist *l); + +/* Free the entire list */ +void pa_strlist_free(struct pa_strlist *l); + +/* Return the next entry in the list in *string and remove it from + * the list. Returns the new list head. The memory *string points to + * has to be freed with pa_xfree() */ +struct pa_strlist* pa_strlist_pop(struct pa_strlist *l, char **s); + +/* Parse a whitespace separated server list */ +struct pa_strlist* pa_strlist_parse(const char *s); + +#endif diff --git a/polyp/util.c b/polyp/util.c index ad91a3078..4db92cf44 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -51,6 +51,8 @@ #include "xmalloc.h" #include "log.h" +#define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-" + /** Make a file descriptor nonblock. Doesn't do any error checking */ void pa_make_nonblock_fd(int fd) { int v; @@ -83,6 +85,26 @@ fail: return -1; } +/* Creates a the parent directory of the specified path securely */ +int pa_make_secure_parent_dir(const char *fn) { + int ret = -1; + char *slash, *dir = pa_xstrdup(fn); + + if (!(slash = strrchr(dir, '/'))) + goto finish; + *slash = 0; + + if (pa_make_secure_dir(dir) < 0) + goto finish; + + ret = 0; + +finish: + pa_xfree(dir); + return ret; +} + + /** Calls read() in a loop. Makes sure that as much as 'size' bytes, * unless EOF is reached or an error occured */ ssize_t pa_loop_read(int fd, void*data, size_t size) { @@ -225,31 +247,32 @@ char *pa_get_user_name(char *s, size_t l) { char *p; assert(s && l > 0); - if (!(p = getenv("USER"))) - if (!(p = getenv("LOGNAME"))) - if (!(p = getenv("USERNAME"))) { - + if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) { + #ifdef HAVE_GETPWUID_R - if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { + if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { #else - /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) - * that do not support getpwuid_r. */ - if ((r = getpwuid(getuid())) == NULL) { + /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) + * that do not support getpwuid_r. */ + if ((r = getpwuid(getuid())) == NULL) { #endif - snprintf(s, l, "%lu", (unsigned long) getuid()); - return s; - } - - p = r->pw_name; + snprintf(s, l, "%lu", (unsigned long) getuid()); + return s; } + + p = r->pw_name; + } return pa_strlcpy(s, p, l); -} + } /* Return the current hostname in the specified buffer. */ char *pa_get_host_name(char *s, size_t l) { assert(s && l > 0); - gethostname(s, l); + if (gethostname(s, l) < 0) { + pa_log(__FILE__": gethostname(): %s\n", strerror(errno)); + return NULL; + } s[l-1] = 0; return s; } @@ -264,8 +287,10 @@ char *pa_get_home_dir(char *s, size_t l) { if ((e = getenv("HOME"))) return pa_strlcpy(s, e, l); - if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) + if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { + pa_log(__FILE__": getpwuid_r() failed\n"); return NULL; + } return pa_strlcpy(s, r->pw_dir, l); } @@ -479,7 +504,7 @@ char *pa_split_spaces(const char *c, const char **state) { const char *current = *state ? *state : c; size_t l; - if (!*current) + if (!*current || *c == 0) return NULL; current += strspn(current, WHITESPACE); @@ -768,13 +793,13 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) { return (size_t) -1; d[j] |= (uint8_t) b; - j++; } return j; } +/* Return the fully qualified domain name in *s */ char *pa_get_fqdn(char *s, size_t l) { char hn[256]; struct addrinfo *a, hints; @@ -793,3 +818,25 @@ char *pa_get_fqdn(char *s, size_t l) { freeaddrinfo(a); return s; } + +/* Returns nonzero when *s starts with *pfx */ +int pa_startswith(const char *s, const char *pfx) { + size_t l; + assert(s && pfx); + l = strlen(pfx); + + return strlen(s) >= l && strncmp(s, pfx, l) == 0; +} + +/* if fn is null return the polypaudio run time path in s (/tmp/polypaudio) + * if fn is non-null and starts with / return fn in s + * otherwise append fn to the run time path and return it in s */ +char *pa_runtime_path(const char *fn, char *s, size_t l) { + char u[256]; + + if (fn && *fn == '/') + return pa_strlcpy(s, fn, l); + + snprintf(s, l, PA_RUNTIME_PATH_PREFIX"%s%s%s", pa_get_user_name(u, sizeof(u)), fn ? "/" : "", fn ? fn : ""); + return s; +} diff --git a/polyp/util.h b/polyp/util.h index 3f09a9a70..e9d938cea 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -33,6 +33,7 @@ void pa_make_nonblock_fd(int fd); int pa_make_secure_dir(const char* dir); +int pa_make_secure_parent_dir(const char *fn); ssize_t pa_loop_read(int fd, void*data, size_t size); ssize_t pa_loop_write(int fd, const void*data, size_t size); @@ -85,4 +86,8 @@ FILE *pa_open_config_file(const char *env, const char *global, const char *local char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength); size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength); +int pa_startswith(const char *s, const char *pfx); + +char *pa_runtime_path(const char *fn, char *s, size_t l); + #endif From 6de0cdaaa9eb7d64c915bada450d3afc8746dd9c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Nov 2004 00:42:34 +0000 Subject: [PATCH 0274/1514] remove a debug message git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@281 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-context.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index a47703130..62d1ff0d4 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -524,8 +524,6 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i c->client = NULL; if (!io) { - pa_log("failure: %s\n", strerror(errno)); - /* Try the item in the list */ if (errno == ECONNREFUSED || errno == ETIMEDOUT || errno == EHOSTUNREACH) { try_next_connection(c); From d7d8529c4654a6681b8e5e40dface6cd774f0231 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 Nov 2004 00:04:51 +0000 Subject: [PATCH 0275/1514] * remove as superfluous assert() in polyplib-stream which broke the gstreamer plugin * fix module-tunnel meta info git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@282 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-tunnel.c | 4 ++-- polyp/polyplib-stream.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index c899929fa..712ec359e 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -50,11 +50,11 @@ #ifdef TUNNEL_SINK #include "module-tunnel-sink-symdef.h" PA_MODULE_DESCRIPTION("Tunnel module for sinks") -PA_MODULE_USAGE("server= sink= cookie= format= channels= rate= sink_name=") +PA_MODULE_USAGE("server=
    sink= cookie= format= channels= rate= sink_name=") #else #include "module-tunnel-source-symdef.h" PA_MODULE_DESCRIPTION("Tunnel module for sources") -PA_MODULE_USAGE("server= source= cookie= format= channels= rate= source_name=") +PA_MODULE_USAGE("server=
    source= cookie= format= channels= rate= source_name=") #endif PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 312f1debf..b1f198558 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -351,8 +351,8 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void } size_t pa_stream_writable_size(struct pa_stream *s) { - assert(s && s->state == PA_STREAM_READY && s->ref >= 1); - return s->requested_bytes; + assert(s && s->ref >= 1); + return s->state == PA_STREAM_READY ? s->requested_bytes : 0; } struct pa_operation * pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { From be6a1c28cfa89011f2fa55defe638199e910909b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 Nov 2004 02:36:35 +0000 Subject: [PATCH 0276/1514] * implement module-esound-sink git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@283 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/modules.html.in | 17 +- doc/todo | 1 - polyp/Makefile.am | 10 +- polyp/module-esound-sink.c | 426 +++++++++++++++++++++++++++++++++++++ polyp/module-pipe-sink.c | 8 + 5 files changed, 456 insertions(+), 6 deletions(-) create mode 100644 polyp/module-esound-sink.c diff --git a/doc/modules.html.in b/doc/modules.html.in index 5e9b8873c..14fe72783 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -138,6 +138,17 @@ buffer control is lost through this tunneling.

    cookie=The authentication cookie file to use. +

    module-esound-sink

    + +

    Create a playback sink using an ESOUND server as backend. Whenever you can, try to omit this +module since it has many disadvantages including bad latency +and even worse latency measurement.

    + + + + +
    server=The server to connect to
    cookie=The authentication cookie file to use.
    +

    Protocols

    @@ -157,7 +168,7 @@ module see cli.html. -

    module-cli-protocol-{unix,tcp}

    +

    module-cli-protocol-{unix,tcp,tcp6}

    An implemenation of a simple command line based protocol for controlling the polypaudio daemon. If loaded, the user may @@ -183,7 +194,7 @@ device, i.e. not publicly accessible. (defaults to 1) socket=(only for -unix) The UNIX socket name (defaults to /tmp/polypaudio/cli) -

    module-simple-protocol-{unix,tcp}

    +

    module-simple-protocol-{unix,tcp,tcp6}

    An implementation of a simple protocol which allows playback by using simple tools like netcat. Just connect to the listening @@ -226,7 +237,7 @@ about the two possible suffixes of this module.

    This implementation misses some features the original ESOUND has: e.g. there is no sample cache yet. However: XMMS works fine.

    -

    module-native-protocol-{unix,tcp}

    +

    module-native-protocol-{unix,tcp,tcp6}

    The native protocol of polypaudio.

    diff --git a/doc/todo b/doc/todo index 99e06569a..75983e7e3 100644 --- a/doc/todo +++ b/doc/todo @@ -18,7 +18,6 @@ - add LGPL blurb to all concerning files - non-fp mixing - non-fp resampling -- esound backend ** later *** - xmlrpc/http diff --git a/polyp/Makefile.am b/polyp/Makefile.am index c4f9e2d26..585b16c09 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -115,7 +115,8 @@ modlib_LTLIBRARIES= \ module-match.la \ module-tunnel-sink.la \ module-tunnel-source.la \ - module-null-sink.la + module-null-sink.la \ + module-esound-sink.la SYMDEF_FILES= \ module-cli-symdef.h \ @@ -143,7 +144,8 @@ SYMDEF_FILES= \ module-match-symdef.h \ module-tunnel-sink-symdef.h \ module-tunnel-source-symdef.h \ - module-null-sink-symdef.h + module-null-sink-symdef.h \ + module-esound-sink-symdef.h EXTRA_DIST+=$(SYMDEF_FILES) BUILT_SOURCES+=$(SYMDEF_FILES) @@ -400,6 +402,10 @@ module_esound_compat_spawnpid_la_SOURCES = module-esound-compat-spawnpid.c module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) +module_esound_sink_la_SOURCES = module-esound-sink.c +module_esound_sink_la_LDFLAGS = -module -avoid-version +module_esound_sink_la_LIBADD = $(AM_LIBADD) libsocket-client.la libauthkey.la + libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ polyplib-def.h \ tagstruct.c tagstruct.h \ diff --git a/polyp/module-esound-sink.c b/polyp/module-esound-sink.c new file mode 100644 index 000000000..fadf8456a --- /dev/null +++ b/polyp/module-esound-sink.c @@ -0,0 +1,426 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iochannel.h" +#include "sink.h" +#include "module.h" +#include "util.h" +#include "modargs.h" +#include "xmalloc.h" +#include "log.h" +#include "module-esound-sink-symdef.h" +#include "socket-client.h" +#include "esound.h" +#include "authkey.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Esound ") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink_name= server=
    cookie= format= channels= rate=") + +#define DEFAULT_SINK_NAME "esound_output" + +struct userdata { + struct pa_core *core; + + struct pa_sink *sink; + struct pa_iochannel *io; + struct pa_socket_client *client; + + struct pa_defer_event *defer_event; + + struct pa_memchunk memchunk; + struct pa_module *module; + + void *write_data; + size_t write_length, write_index; + + void *read_data; + size_t read_length, read_index; + + enum { STATE_AUTH, STATE_LATENCY, STATE_RUNNING, STATE_DEAD } state; + + pa_usec_t latency; + + esd_format_t format; + int32_t rate; +}; + +static const char* const valid_modargs[] = { + "server", + "cookie", + "rate", + "format", + "channels", + "sink_name", + NULL +}; + +static void cancel(struct userdata *u) { + assert(u); + + u->state = STATE_DEAD; + + if (u->io) { + pa_iochannel_free(u->io); + u->io = NULL; + } + + if (u->defer_event) { + u->core->mainloop->defer_free(u->defer_event); + u->defer_event = NULL; + } + + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + u->sink = NULL; + } + + if (u->module) { + pa_module_unload_request(u->module); + u->module = NULL; + } +} + +static int do_write(struct userdata *u) { + ssize_t r; + assert(u); + + if (!pa_iochannel_is_writable(u->io)) + return 0; + + if (u->write_data) { + assert(u->write_index < u->write_length); + + if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) <= 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + return -1; + } + + u->write_index += r; + assert(u->write_index <= u->write_length); + + if (u->write_index == u->write_length) { + free(u->write_data); + u->write_data = NULL; + u->write_index = u->write_length = 0; + } + } else if (u->state == STATE_RUNNING) { + pa_module_set_used(u->module, pa_idxset_ncontents(u->sink->inputs) + pa_idxset_ncontents(u->sink->monitor_source->outputs)); + + if (!u->memchunk.length) + if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) + return 0; + + assert(u->memchunk.memblock && u->memchunk.length); + + if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + return -1; + } + + u->memchunk.index += r; + u->memchunk.length -= r; + + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; + } + } + + return 0; +} + +static int handle_response(struct userdata *u) { + assert(u); + + switch (u->state) { + case STATE_AUTH: + assert(u->read_length == sizeof(int32_t)); + + /* Process auth data */ + if (!*(int32_t*) u->read_data) { + pa_log(__FILE__": Authentication failed: %s\n", strerror(errno)); + return -1; + } + + /* Request latency data */ + assert(!u->write_data); + *(int32_t*) (u->write_data = pa_xmalloc(u->write_length = sizeof(int32_t))) = ESD_PROTO_LATENCY; + + u->write_index = 0; + u->state = STATE_LATENCY; + + /* Space for next response */ + assert(u->read_length >= sizeof(int32_t)); + u->read_index = 0; + u->read_length = sizeof(int32_t); + + break; + + case STATE_LATENCY: { + int32_t *p; + assert(u->read_length == sizeof(int32_t)); + + /* Process latency info */ + u->latency = (pa_usec_t) ((double) (*(int32_t*) u->read_data) * 1000000 / 44100); + if (u->latency > 10000000) { + pa_log(__FILE__": WARNING! Invalid latency information received from server\n"); + u->latency = 0; + } + + /* Create stream */ + assert(!u->write_data); + p = u->write_data = pa_xmalloc0(u->write_length = sizeof(int32_t)*3+ESD_NAME_MAX); + *(p++) = ESD_PROTO_STREAM_PLAY; + *(p++) = u->format; + *(p++) = u->rate; + pa_strlcpy((char*) p, "Polypaudio Tunnel", ESD_NAME_MAX); + + u->write_index = 0; + u->state = STATE_RUNNING; + + /* Don't read any further */ + pa_xfree(u->read_data); + u->read_data = NULL; + u->read_index = u->read_length = 0; + + break; + } + + default: + abort(); + } + + return 0; +} + +static int do_read(struct userdata *u) { + assert(u); + + if (!pa_iochannel_is_readable(u->io)) + return 0; + + if (u->state == STATE_AUTH || u->state == STATE_LATENCY) { + ssize_t r; + + if (!u->read_data) + return 0; + + assert(u->read_index < u->read_length); + + if ((r = pa_iochannel_read(u->io, (uint8_t*) u->read_data + u->read_index, u->read_length - u->read_index)) <= 0) { + pa_log(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + cancel(u); + return -1; + } + + u->read_index += r; + assert(u->read_index <= u->read_length); + + if (u->read_index == u->read_length) + return handle_response(u); + } + + return 0; +} + +static void do_work(struct userdata *u) { + assert(u); + + u->core->mainloop->defer_enable(u->defer_event, 0); + + if (do_read(u) < 0 || do_write(u) < 0) + cancel(u); +} + +static void notify_cb(struct pa_sink*s) { + struct userdata *u = s->userdata; + assert(s && u); + + if (pa_iochannel_is_writable(u->io)) + u->core->mainloop->defer_enable(u->defer_event, 1); +} + +static pa_usec_t get_latency_cb(struct pa_sink *s) { + struct userdata *u = s->userdata; + assert(s && u); + + return + u->latency + + (u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0); +} + +static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata) { + struct userdata *u = userdata; + assert(u); + do_work(u); +} + +static void io_callback(struct pa_iochannel *io, void*userdata) { + struct userdata *u = userdata; + assert(u); + do_work(u); +} + +static void on_connection(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata) { + struct userdata *u = userdata; + + pa_socket_client_unref(u->client); + u->client = NULL; + + if (!io) { + pa_log(__FILE__": connection failed: %s\n", strerror(errno)); + cancel(u); + return; + } + + u->io = io; + pa_iochannel_set_callback(u->io, io_callback, u); +} + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct userdata *u = NULL; + const char *p; + struct pa_sample_spec ss; + struct pa_modargs *ma = NULL; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments\n"); + goto fail; + } + + ss = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + pa_log(__FILE__": invalid sample format specification\n"); + goto fail; + } + + if ((ss.format != PA_SAMPLE_U8 && ss.format != PA_SAMPLE_S16NE) || + (ss.channels > 2)) { + pa_log(__FILE__": esound sample type support is limited to mono/stereo and U8 or S16NE sample data\n"); + goto fail; + } + + u = pa_xmalloc0(sizeof(struct userdata)); + u->core = c; + u->module = m; + m->userdata = u; + u->format = + (ss.format == PA_SAMPLE_U8 ? ESD_BITS8 : ESD_BITS16) | + (ss.channels == 2 ? ESD_STEREO : ESD_MONO); + u->rate = ss.rate; + u->sink = NULL; + u->client = NULL; + u->io = NULL; + u->read_data = u->write_data = NULL; + u->read_index = u->write_index = u->read_length = u->write_length = 0; + u->state = STATE_AUTH; + u->latency = 0; + + if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + pa_log(__FILE__": failed to create sink.\n"); + goto fail; + } + + if (!(u->client = pa_socket_client_new_string(u->core->mainloop, p = pa_modargs_get_value(ma, "server", ESD_UNIX_SOCKET_NAME), ESD_DEFAULT_PORT))) { + pa_log(__FILE__": failed to connect to server.\n"); + goto fail; + } + pa_socket_client_set_callback(u->client, on_connection, u); + + /* Prepare the initial request */ + u->write_data = pa_xmalloc(u->write_length = ESD_KEY_LEN + sizeof(int32_t)); + if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", ".esd_auth"), u->write_data, ESD_KEY_LEN) < 0) { + pa_log(__FILE__": failed to load cookie\n"); + goto fail; + } + *(int32_t*) ((uint8_t*) u->write_data + ESD_KEY_LEN) = ESD_ENDIAN_KEY; + + /* Reserve space for the response */ + u->read_data = pa_xmalloc(u->read_length = sizeof(int32_t)); + + u->sink->notify = notify_cb; + u->sink->get_latency = get_latency_cb; + u->sink->userdata = u; + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("Esound sink '%s'", p); + + u->memchunk.memblock = NULL; + u->memchunk.length = 0; + + u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u); + c->mainloop->defer_enable(u->defer_event, 0); + + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(c, m); + + return -1; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + u->module = NULL; + cancel(u); + + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + + if (u->client) + pa_socket_client_unref(u->client); + + pa_xfree(u->read_data); + pa_xfree(u->write_data); + + pa_xfree(u); +} + + + diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index bc8abb41f..e445584e5 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -111,6 +111,13 @@ static void notify_cb(struct pa_sink*s) { u->core->mainloop->defer_enable(u->defer_event, 1); } +static pa_usec_t get_latency_cb(struct pa_sink *s) { + struct userdata *u = s->userdata; + assert(s && u); + + return u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0; +} + static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata) { struct userdata *u = userdata; assert(u); @@ -173,6 +180,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; } u->sink->notify = notify_cb; + u->sink->get_latency = get_latency_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Unix FIFO sink '%s'", p); From fa499dad06ba6558111cdef64c18f2401e803cff Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 Nov 2004 14:58:54 +0000 Subject: [PATCH 0277/1514] Make the whole stuff LGPL only git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@284 fefdeb5f-60dc-0310-8127-8f9354f1896f --- GPL | 340 ----------------- LGPL | 510 ------------------------- LICENSE | 512 +++++++++++++++++++++++++- Makefile.am | 6 +- bootstrap.sh | 4 +- configure.ac | 4 +- doc/Makefile.am | 4 +- doc/README.html.in | 6 +- doc/style.css | 4 +- doc/todo | 1 + doxygen/Makefile.am | 4 +- polyp/Makefile.am | 4 +- polyp/alsa-util.c | 4 +- polyp/alsa-util.h | 4 +- polyp/authkey-prop.c | 4 +- polyp/authkey-prop.h | 4 +- polyp/authkey.c | 12 +- polyp/authkey.h | 12 +- polyp/autoload.c | 4 +- polyp/autoload.h | 4 +- polyp/caps.c | 4 +- polyp/caps.h | 4 +- polyp/cdecl.h | 4 +- polyp/cli-command.c | 4 +- polyp/cli-command.h | 4 +- polyp/cli-text.c | 4 +- polyp/cli-text.h | 4 +- polyp/cli.c | 4 +- polyp/cli.h | 4 +- polyp/client-conf-x11.c | 4 +- polyp/client-conf-x11.h | 4 +- polyp/client-conf.c | 4 +- polyp/client-conf.h | 4 +- polyp/client.c | 4 +- polyp/client.conf.in | 4 +- polyp/client.h | 4 +- polyp/cmdline.c | 4 +- polyp/cmdline.h | 4 +- polyp/conf-parser.c | 4 +- polyp/conf-parser.h | 4 +- polyp/core.c | 4 +- polyp/core.h | 4 +- polyp/cpulimit-test.c | 4 +- polyp/cpulimit.c | 4 +- polyp/cpulimit.h | 4 +- polyp/daemon-conf.c | 4 +- polyp/daemon-conf.h | 4 +- polyp/daemon.conf.in | 4 +- polyp/debug.h | 4 +- polyp/default.pa.in | 4 +- polyp/depmod.py | 4 +- polyp/dumpmodules.c | 4 +- polyp/dumpmodules.h | 4 +- polyp/dynarray.c | 12 +- polyp/dynarray.h | 12 +- polyp/endianmacros.h | 4 +- polyp/esdcompat.sh.in | 4 +- polyp/esound.h | 4 +- polyp/glib-mainloop.c | 4 +- polyp/glib-mainloop.h | 4 +- polyp/glib12-mainloop.c | 4 +- polyp/hashmap.c | 4 +- polyp/hashmap.h | 4 +- polyp/idxset.c | 12 +- polyp/idxset.h | 12 +- polyp/iochannel.c | 12 +- polyp/iochannel.h | 12 +- polyp/ioline.c | 4 +- polyp/ioline.h | 4 +- polyp/llist.h | 4 +- polyp/main.c | 4 +- polyp/mainloop-api.c | 12 +- polyp/mainloop-api.h | 12 +- polyp/mainloop-signal.c | 4 +- polyp/mainloop-signal.h | 4 +- polyp/mainloop-test.c | 4 +- polyp/mainloop.c | 4 +- polyp/mainloop.h | 4 +- polyp/memblock.c | 12 +- polyp/memblock.h | 12 +- polyp/memblockq.c | 4 +- polyp/memblockq.h | 4 +- polyp/memchunk.c | 12 +- polyp/memchunk.h | 12 +- polyp/modargs.c | 4 +- polyp/modargs.h | 4 +- polyp/modinfo.c | 4 +- polyp/modinfo.h | 4 +- polyp/module-alsa-sink.c | 4 +- polyp/module-alsa-source.c | 4 +- polyp/module-cli.c | 4 +- polyp/module-combine.c | 4 +- polyp/module-esound-compat-spawnfd.c | 4 +- polyp/module-esound-compat-spawnpid.c | 4 +- polyp/module-esound-sink.c | 4 +- polyp/module-match.c | 4 +- polyp/module-native-protocol-fd.c | 4 +- polyp/module-null-sink.c | 4 +- polyp/module-oss-mmap.c | 4 +- polyp/module-oss.c | 4 +- polyp/module-pipe-sink.c | 4 +- polyp/module-pipe-source.c | 4 +- polyp/module-protocol-stub.c | 4 +- polyp/module-sine.c | 4 +- polyp/module-tunnel.c | 4 +- polyp/module-x11-bell.c | 4 +- polyp/module-x11-publish.c | 4 +- polyp/module.c | 4 +- polyp/module.h | 4 +- polyp/namereg.c | 4 +- polyp/namereg.h | 4 +- polyp/native-common.h | 12 +- polyp/oss-util.c | 4 +- polyp/oss-util.h | 4 +- polyp/pacat-simple.c | 4 +- polyp/pacat.c | 4 +- polyp/packet.c | 12 +- polyp/packet.h | 12 +- polyp/pactl.c | 4 +- polyp/paplay.c | 4 +- polyp/parec-simple.c | 4 +- polyp/pax11publish.c | 4 +- polyp/pdispatch.c | 12 +- polyp/pdispatch.h | 12 +- polyp/play-memchunk.c | 4 +- polyp/play-memchunk.h | 4 +- polyp/polyplib-context.c | 4 +- polyp/polyplib-context.h | 4 +- polyp/polyplib-def.h | 12 +- polyp/polyplib-error.c | 4 +- polyp/polyplib-error.h | 4 +- polyp/polyplib-internal.h | 4 +- polyp/polyplib-introspect.c | 4 +- polyp/polyplib-introspect.h | 4 +- polyp/polyplib-operation.c | 4 +- polyp/polyplib-operation.h | 4 +- polyp/polyplib-scache.c | 4 +- polyp/polyplib-scache.h | 4 +- polyp/polyplib-simple.c | 4 +- polyp/polyplib-simple.h | 4 +- polyp/polyplib-stream.c | 4 +- polyp/polyplib-stream.h | 4 +- polyp/polyplib-subscribe.c | 4 +- polyp/polyplib-subscribe.h | 4 +- polyp/polyplib-version.h.in | 4 +- polyp/polyplib.h | 12 +- polyp/props.c | 4 +- polyp/props.h | 4 +- polyp/protocol-cli.c | 4 +- polyp/protocol-cli.h | 4 +- polyp/protocol-esound.c | 4 +- polyp/protocol-esound.h | 4 +- polyp/protocol-native.c | 4 +- polyp/protocol-native.h | 4 +- polyp/protocol-simple.c | 4 +- polyp/protocol-simple.h | 4 +- polyp/pstream-util.c | 12 +- polyp/pstream-util.h | 12 +- polyp/pstream.c | 12 +- polyp/pstream.h | 12 +- polyp/queue.c | 12 +- polyp/queue.h | 12 +- polyp/resampler.c | 4 +- polyp/resampler.h | 4 +- polyp/sample-util.c | 4 +- polyp/sample-util.h | 4 +- polyp/sample.c | 4 +- polyp/sample.h | 4 +- polyp/scache.c | 4 +- polyp/scache.h | 4 +- polyp/sconv-s16be.c | 4 +- polyp/sconv-s16be.h | 4 +- polyp/sconv-s16le.c | 4 +- polyp/sconv-s16le.h | 4 +- polyp/sconv.c | 4 +- polyp/sconv.h | 4 +- polyp/sink-input.c | 4 +- polyp/sink-input.h | 4 +- polyp/sink.c | 4 +- polyp/sink.h | 4 +- polyp/sioman.c | 4 +- polyp/sioman.h | 4 +- polyp/socket-client.c | 12 +- polyp/socket-client.h | 12 +- polyp/socket-server.c | 4 +- polyp/socket-server.h | 4 +- polyp/socket-util.c | 4 +- polyp/socket-util.h | 4 +- polyp/sound-file-stream.c | 4 +- polyp/sound-file-stream.h | 4 +- polyp/sound-file.c | 4 +- polyp/sound-file.h | 4 +- polyp/source-output.c | 4 +- polyp/source-output.h | 4 +- polyp/source.c | 4 +- polyp/source.h | 4 +- polyp/strbuf.c | 4 +- polyp/strbuf.h | 4 +- polyp/strlist.c | 4 +- polyp/strlist.h | 4 +- polyp/subscribe.c | 4 +- polyp/subscribe.h | 4 +- polyp/tagstruct.c | 12 +- polyp/tagstruct.h | 12 +- polyp/tokenizer.c | 4 +- polyp/tokenizer.h | 4 +- polyp/util.c | 12 +- polyp/util.h | 12 +- polyp/x11prop.c | 4 +- polyp/x11prop.h | 4 +- polyp/x11wrap.c | 4 +- polyp/x11wrap.h | 4 +- polyp/xmalloc.c | 4 +- polyp/xmalloc.h | 4 +- 214 files changed, 1064 insertions(+), 1407 deletions(-) delete mode 100644 GPL delete mode 100644 LGPL diff --git a/GPL b/GPL deleted file mode 100644 index d60c31a97..000000000 --- a/GPL +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/LGPL b/LGPL deleted file mode 100644 index b124cf581..000000000 --- a/LGPL +++ /dev/null @@ -1,510 +0,0 @@ - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations -below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it -becomes a de-facto standard. To achieve this, non-free programs must -be allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control -compilation and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at least - three years, to give the same user the materials specified in - Subsection 6a, above, for a charge no more than the cost of - performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply, and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License -may add an explicit geographical distribution limitation excluding those -countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms -of the ordinary General Public License). - - To apply these terms, attach the following notices to the library. -It is safest to attach them to the start of each source file to most -effectively convey the exclusion of warranty; and each file should -have at least the "copyright" line and a pointer to where the full -notice is found. - - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or -your school, if any, to sign a "copyright disclaimer" for the library, -if necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James - Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/LICENSE b/LICENSE index b042db509..b124cf581 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,510 @@ -The client libraries are licensed under LGPL -The daemon itself and all plugings are licensed under GPL -Lennart Poettering, 2004 + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/Makefile.am b/Makefile.am index b15fbac63..04c8f2cf7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -12,12 +12,12 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh README LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in +EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in SUBDIRS=polyp doc MAINTAINERCLEANFILES=README diff --git a/bootstrap.sh b/bootstrap.sh index 3592ce75c..7dc081aea 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -4,7 +4,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by +# under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -13,7 +13,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/configure.ac b/configure.ac index 6eec2d812..455334117 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by +# under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -15,7 +15,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/doc/Makefile.am b/doc/Makefile.am index 723a92c8f..17688d3bb 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -3,7 +3,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by +# under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -12,7 +12,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/doc/README.html.in b/doc/README.html.in index 22a30dc21..742ea3d1e 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -27,16 +27,16 @@

    License

    This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License as +modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details.

    +Lesser General Public License for more details.

    -

    You should have received a copy of the GNU General Public License +

    You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    diff --git a/doc/style.css b/doc/style.css index e54a15a35..a46592a27 100644 --- a/doc/style.css +++ b/doc/style.css @@ -4,7 +4,7 @@ * This file is part of polypaudio. * * polypaudio is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by + * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * @@ -13,7 +13,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with polypaudio; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/doc/todo b/doc/todo index 75983e7e3..ad464ea4a 100644 --- a/doc/todo +++ b/doc/todo @@ -18,6 +18,7 @@ - add LGPL blurb to all concerning files - non-fp mixing - non-fp resampling +- make module-tunnel use pa_socket_client_new_string() ** later *** - xmlrpc/http diff --git a/doxygen/Makefile.am b/doxygen/Makefile.am index 007a37d69..9ea724d00 100644 --- a/doxygen/Makefile.am +++ b/doxygen/Makefile.am @@ -3,7 +3,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -12,7 +12,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 585b16c09..9ea6932a0 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -3,7 +3,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -12,7 +12,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index 70e2e0725..408bc5618 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/alsa-util.h b/polyp/alsa-util.h index 2627a75c9..8add361f6 100644 --- a/polyp/alsa-util.h +++ b/polyp/alsa-util.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/authkey-prop.c b/polyp/authkey-prop.c index 132279556..2adfc41f5 100644 --- a/polyp/authkey-prop.c +++ b/polyp/authkey-prop.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/authkey-prop.h b/polyp/authkey-prop.h index d9ba5122f..1a6681173 100644 --- a/polyp/authkey-prop.h +++ b/polyp/authkey-prop.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/authkey.c b/polyp/authkey.c index ef395680b..05324a61e 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/authkey.h b/polyp/authkey.h index 2bef35290..a6006dfca 100644 --- a/polyp/authkey.h +++ b/polyp/authkey.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/autoload.c b/polyp/autoload.c index d6207962d..96fa750ae 100644 --- a/polyp/autoload.c +++ b/polyp/autoload.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/autoload.h b/polyp/autoload.h index ec7d38f10..8537173cf 100644 --- a/polyp/autoload.h +++ b/polyp/autoload.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/caps.c b/polyp/caps.c index d03ab14be..daf0b9168 100644 --- a/polyp/caps.c +++ b/polyp/caps.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/caps.h b/polyp/caps.h index 473462fbc..3bb861d1d 100644 --- a/polyp/caps.h +++ b/polyp/caps.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cdecl.h b/polyp/cdecl.h index 7102f6496..d51ae0266 100644 --- a/polyp/cdecl.h +++ b/polyp/cdecl.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cli-command.c b/polyp/cli-command.c index d563a0727..0c71260de 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cli-command.h b/polyp/cli-command.h index b3c601ada..0f089f615 100644 --- a/polyp/cli-command.h +++ b/polyp/cli-command.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 39f7b6edd..7974275a5 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cli-text.h b/polyp/cli-text.h index 121f2a5d2..1457d0556 100644 --- a/polyp/cli-text.h +++ b/polyp/cli-text.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cli.c b/polyp/cli.c index 09e9855dc..15142f357 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cli.h b/polyp/cli.h index 9cfee0d8c..bfe0c4f89 100644 --- a/polyp/cli.h +++ b/polyp/cli.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/client-conf-x11.c b/polyp/client-conf-x11.c index f667bd784..eb471033e 100644 --- a/polyp/client-conf-x11.c +++ b/polyp/client-conf-x11.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/client-conf-x11.h b/polyp/client-conf-x11.h index 626b4f307..951ef0b1f 100644 --- a/polyp/client-conf-x11.h +++ b/polyp/client-conf-x11.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/client-conf.c b/polyp/client-conf.c index 4a0fc6298..2de1c57fb 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/client-conf.h b/polyp/client-conf.h index 2ce056f4a..cf7dd0958 100644 --- a/polyp/client-conf.h +++ b/polyp/client-conf.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/client.c b/polyp/client.c index 7aee2edd2..b525fe6b1 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/client.conf.in b/polyp/client.conf.in index 640e26901..fbf645a49 100644 --- a/polyp/client.conf.in +++ b/polyp/client.conf.in @@ -3,7 +3,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -12,7 +12,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. diff --git a/polyp/client.h b/polyp/client.h index 25a4b1660..2518011e2 100644 --- a/polyp/client.h +++ b/polyp/client.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cmdline.c b/polyp/cmdline.c index c32d9a0f1..0c381f8c4 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cmdline.h b/polyp/cmdline.h index bfbae4707..28e7bdbc9 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/conf-parser.c b/polyp/conf-parser.c index 3d922c209..40b00cda1 100644 --- a/polyp/conf-parser.c +++ b/polyp/conf-parser.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/conf-parser.h b/polyp/conf-parser.h index 303308601..48cfbc147 100644 --- a/polyp/conf-parser.h +++ b/polyp/conf-parser.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/core.c b/polyp/core.c index 6e155dda7..19e0425fb 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/core.h b/polyp/core.h index 1438bf720..799661aff 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cpulimit-test.c b/polyp/cpulimit-test.c index d1faf92bb..83d403f5e 100644 --- a/polyp/cpulimit-test.c +++ b/polyp/cpulimit-test.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c index a60c03d78..fcbbaf3d2 100644 --- a/polyp/cpulimit.c +++ b/polyp/cpulimit.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/cpulimit.h b/polyp/cpulimit.h index 6d13b6e58..a171da9b4 100644 --- a/polyp/cpulimit.h +++ b/polyp/cpulimit.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index 1c6486b7f..c0ff02f9f 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/daemon-conf.h b/polyp/daemon-conf.h index fc31117f2..9c2784855 100644 --- a/polyp/daemon-conf.h +++ b/polyp/daemon-conf.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/daemon.conf.in b/polyp/daemon.conf.in index e6d82db17..ddc4955c2 100644 --- a/polyp/daemon.conf.in +++ b/polyp/daemon.conf.in @@ -3,7 +3,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -12,7 +12,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. diff --git a/polyp/debug.h b/polyp/debug.h index c6ec5c7e2..fcfa71421 100644 --- a/polyp/debug.h +++ b/polyp/debug.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/default.pa.in b/polyp/default.pa.in index 95d4be581..07ff373ce 100755 --- a/polyp/default.pa.in +++ b/polyp/default.pa.in @@ -4,7 +4,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by +# under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -13,7 +13,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/depmod.py b/polyp/depmod.py index 85dc66a8f..7bb223b19 100755 --- a/polyp/depmod.py +++ b/polyp/depmod.py @@ -4,7 +4,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -13,7 +13,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. diff --git a/polyp/dumpmodules.c b/polyp/dumpmodules.c index a9c028258..1903fe005 100644 --- a/polyp/dumpmodules.c +++ b/polyp/dumpmodules.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/dumpmodules.h b/polyp/dumpmodules.h index 544c55d25..c56d5abc5 100644 --- a/polyp/dumpmodules.h +++ b/polyp/dumpmodules.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/dynarray.c b/polyp/dynarray.c index 23adb5819..eb360b807 100644 --- a/polyp/dynarray.c +++ b/polyp/dynarray.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/dynarray.h b/polyp/dynarray.h index 56ec5386b..2e9b72f6d 100644 --- a/polyp/dynarray.h +++ b/polyp/dynarray.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/endianmacros.h b/polyp/endianmacros.h index cd7b7d833..75c0af0af 100644 --- a/polyp/endianmacros.h +++ b/polyp/endianmacros.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/esdcompat.sh.in b/polyp/esdcompat.sh.in index d222e1ba2..dd94bfea0 100755 --- a/polyp/esdcompat.sh.in +++ b/polyp/esdcompat.sh.in @@ -5,7 +5,7 @@ # This file is part of polypaudio. # # polypaudio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with polypaudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. diff --git a/polyp/esound.h b/polyp/esound.h index 01a2962fb..5dc2583b1 100644 --- a/polyp/esound.h +++ b/polyp/esound.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c index 4fee0a4a1..aa81f82d6 100644 --- a/polyp/glib-mainloop.c +++ b/polyp/glib-mainloop.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h index afc83be26..d830561f2 100644 --- a/polyp/glib-mainloop.h +++ b/polyp/glib-mainloop.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/glib12-mainloop.c b/polyp/glib12-mainloop.c index c7085cc96..2073c01d2 100644 --- a/polyp/glib12-mainloop.c +++ b/polyp/glib12-mainloop.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/hashmap.c b/polyp/hashmap.c index 10b148ddf..43e4456db 100644 --- a/polyp/hashmap.c +++ b/polyp/hashmap.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/hashmap.h b/polyp/hashmap.h index 739f89477..f858c3550 100644 --- a/polyp/hashmap.h +++ b/polyp/hashmap.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/idxset.c b/polyp/idxset.c index 92cde13f8..dcc38423e 100644 --- a/polyp/idxset.c +++ b/polyp/idxset.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/idxset.h b/polyp/idxset.h index e9a6fb9a1..1ed661545 100644 --- a/polyp/idxset.h +++ b/polyp/idxset.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/iochannel.c b/polyp/iochannel.c index 5e3e93606..b93860a58 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/iochannel.h b/polyp/iochannel.h index 6f5f351c2..79600f72d 100644 --- a/polyp/iochannel.h +++ b/polyp/iochannel.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/ioline.c b/polyp/ioline.c index dfa92ab73..b1c980d86 100644 --- a/polyp/ioline.c +++ b/polyp/ioline.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/ioline.h b/polyp/ioline.h index 5f29a16bc..c6150d4b5 100644 --- a/polyp/ioline.h +++ b/polyp/ioline.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/llist.h b/polyp/llist.h index ec8e02997..c48c5c6ea 100644 --- a/polyp/llist.h +++ b/polyp/llist.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/main.c b/polyp/main.c index 378cb8a06..941bf9239 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/mainloop-api.c b/polyp/mainloop-api.c index 952fce0a1..7b80e4fe1 100644 --- a/polyp/mainloop-api.c +++ b/polyp/mainloop-api.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index 43d150e4c..daf71d71d 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c index d7ee5010e..89f195ed3 100644 --- a/polyp/mainloop-signal.c +++ b/polyp/mainloop-signal.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/mainloop-signal.h b/polyp/mainloop-signal.h index fa5ce7184..9ba921412 100644 --- a/polyp/mainloop-signal.h +++ b/polyp/mainloop-signal.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/mainloop-test.c b/polyp/mainloop-test.c index 92b83c145..0d40e76ed 100644 --- a/polyp/mainloop-test.c +++ b/polyp/mainloop-test.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/mainloop.c b/polyp/mainloop.c index 80bcb125c..eb2eddc2c 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/mainloop.h b/polyp/mainloop.h index 4a64d98f2..06a6ccaa1 100644 --- a/polyp/mainloop.h +++ b/polyp/mainloop.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/memblock.c b/polyp/memblock.c index 500d8b206..8ddfb8011 100644 --- a/polyp/memblock.c +++ b/polyp/memblock.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/memblock.h b/polyp/memblock.h index 949a0a08c..69a85a800 100644 --- a/polyp/memblock.h +++ b/polyp/memblock.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/memblockq.c b/polyp/memblockq.c index 0e71fa8c0..0fbeaad09 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/memblockq.h b/polyp/memblockq.h index aeed41934..95e5c5330 100644 --- a/polyp/memblockq.h +++ b/polyp/memblockq.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/memchunk.c b/polyp/memchunk.c index 87b9c1bd3..a8aeb881e 100644 --- a/polyp/memchunk.c +++ b/polyp/memchunk.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/memchunk.h b/polyp/memchunk.h index 3a592f049..e73b6f6ed 100644 --- a/polyp/memchunk.h +++ b/polyp/memchunk.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/modargs.c b/polyp/modargs.c index d58b391b1..01a694cf8 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/modargs.h b/polyp/modargs.h index 705d9f436..53753ba73 100644 --- a/polyp/modargs.h +++ b/polyp/modargs.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/modinfo.c b/polyp/modinfo.c index 2847c63cd..a1328be6b 100644 --- a/polyp/modinfo.c +++ b/polyp/modinfo.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/modinfo.h b/polyp/modinfo.h index 40b535ce6..d6f7c6de6 100644 --- a/polyp/modinfo.h +++ b/polyp/modinfo.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index e319f6c16..a708329d2 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 34f08f95a..ba09d319d 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-cli.c b/polyp/module-cli.c index 1ebc9b52e..55fe8ad42 100644 --- a/polyp/module-cli.c +++ b/polyp/module-cli.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 5df3f1589..95bd958f9 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-esound-compat-spawnfd.c b/polyp/module-esound-compat-spawnfd.c index ae4f9095b..de2cf4e63 100644 --- a/polyp/module-esound-compat-spawnfd.c +++ b/polyp/module-esound-compat-spawnfd.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-esound-compat-spawnpid.c b/polyp/module-esound-compat-spawnpid.c index 02756cdb6..6f945728e 100644 --- a/polyp/module-esound-compat-spawnpid.c +++ b/polyp/module-esound-compat-spawnpid.c @@ -3,7 +3,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-esound-sink.c b/polyp/module-esound-sink.c index fadf8456a..2cc61440f 100644 --- a/polyp/module-esound-sink.c +++ b/polyp/module-esound-sink.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-match.c b/polyp/module-match.c index 0398cede0..6f4fc38c1 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-native-protocol-fd.c b/polyp/module-native-protocol-fd.c index 8f41db641..11f6e5720 100644 --- a/polyp/module-native-protocol-fd.c +++ b/polyp/module-native-protocol-fd.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-null-sink.c b/polyp/module-null-sink.c index 4a41b74de..6d4ea89b2 100644 --- a/polyp/module-null-sink.c +++ b/polyp/module-null-sink.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index bc36d1991..8aecd5602 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 969761f68..fe12b0bb8 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index e445584e5..6c441cc8c 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-pipe-source.c b/polyp/module-pipe-source.c index 8bc4c4773..e8a17b962 100644 --- a/polyp/module-pipe-source.c +++ b/polyp/module-pipe-source.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 6a0f88a28..93e576af7 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-sine.c b/polyp/module-sine.c index 393f929aa..834148218 100644 --- a/polyp/module-sine.c +++ b/polyp/module-sine.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index 712ec359e..368ae422a 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index 23433c8f2..c39877040 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module-x11-publish.c b/polyp/module-x11-publish.c index 60284bd64..acf377597 100644 --- a/polyp/module-x11-publish.c +++ b/polyp/module-x11-publish.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module.c b/polyp/module.c index 9ecdfe292..67d7f44e6 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/module.h b/polyp/module.h index 7380f795c..f5daff95a 100644 --- a/polyp/module.h +++ b/polyp/module.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/namereg.c b/polyp/namereg.c index cc25ea2b6..dce8693ff 100644 --- a/polyp/namereg.c +++ b/polyp/namereg.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/namereg.h b/polyp/namereg.h index b383d9edb..99032be84 100644 --- a/polyp/namereg.h +++ b/polyp/namereg.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/native-common.h b/polyp/native-common.h index 28a471d00..892629e8a 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/oss-util.c b/polyp/oss-util.c index 613cda47d..8c83cbbf6 100644 --- a/polyp/oss-util.c +++ b/polyp/oss-util.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/oss-util.h b/polyp/oss-util.h index cb2ce33c4..c1c696320 100644 --- a/polyp/oss-util.h +++ b/polyp/oss-util.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/pacat-simple.c b/polyp/pacat-simple.c index 2b8ffa081..09cf4d1a1 100644 --- a/polyp/pacat-simple.c +++ b/polyp/pacat-simple.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/pacat.c b/polyp/pacat.c index a37f5dda9..e5e0b7cac 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/packet.c b/polyp/packet.c index 955feeb12..84ac6d625 100644 --- a/polyp/packet.c +++ b/polyp/packet.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/packet.h b/polyp/packet.h index 8f5cb8354..5e4e92f78 100644 --- a/polyp/packet.h +++ b/polyp/packet.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/pactl.c b/polyp/pactl.c index 29c06f913..641106dfc 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/paplay.c b/polyp/paplay.c index cc466e120..418d40b3a 100644 --- a/polyp/paplay.c +++ b/polyp/paplay.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/parec-simple.c b/polyp/parec-simple.c index cae6ff92b..130627d74 100644 --- a/polyp/parec-simple.c +++ b/polyp/parec-simple.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/pax11publish.c b/polyp/pax11publish.c index f151c1976..206ab1cb0 100644 --- a/polyp/pax11publish.c +++ b/polyp/pax11publish.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index f6481fa00..90de345f7 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/pdispatch.h b/polyp/pdispatch.h index ff99b1844..571d0fb44 100644 --- a/polyp/pdispatch.h +++ b/polyp/pdispatch.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index aa6d30e99..1b611db4c 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/play-memchunk.h b/polyp/play-memchunk.h index 0e6a1d8e4..c69165a29 100644 --- a/polyp/play-memchunk.h +++ b/polyp/play-memchunk.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 62d1ff0d4..b15dd8e7d 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 75be59304..565701b22 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -8,7 +8,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -17,7 +17,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index ffa441883..e2fbaea5d 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/polyplib-error.c b/polyp/polyplib-error.c index 24054f2ef..50a672709 100644 --- a/polyp/polyplib-error.c +++ b/polyp/polyplib-error.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-error.h b/polyp/polyplib-error.h index 8b5cd9104..dbbbf0067 100644 --- a/polyp/polyplib-error.h +++ b/polyp/polyplib-error.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 589388f84..d1b53633c 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index af5fd168e..f15f59cc8 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index f4dbd185e..5a8f1bf33 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-operation.c b/polyp/polyplib-operation.c index cdc5394eb..77fe70fa6 100644 --- a/polyp/polyplib-operation.c +++ b/polyp/polyplib-operation.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h index 42d5c8e14..bd1366d28 100644 --- a/polyp/polyplib-operation.h +++ b/polyp/polyplib-operation.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-scache.c b/polyp/polyplib-scache.c index 45220d102..bce5d18a7 100644 --- a/polyp/polyplib-scache.c +++ b/polyp/polyplib-scache.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-scache.h b/polyp/polyplib-scache.h index ce74bef09..051bdd120 100644 --- a/polyp/polyplib-scache.h +++ b/polyp/polyplib-scache.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index aed1ca55c..a73aacfae 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-simple.h b/polyp/polyplib-simple.h index 1bd46dc63..9abef3fa1 100644 --- a/polyp/polyplib-simple.h +++ b/polyp/polyplib-simple.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index b1f198558..a97096b42 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index 4ccc0c238..53873491a 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-subscribe.c b/polyp/polyplib-subscribe.c index 9536bbc65..d7e8e7c15 100644 --- a/polyp/polyplib-subscribe.c +++ b/polyp/polyplib-subscribe.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-subscribe.h b/polyp/polyplib-subscribe.h index bd0e03991..a677bd02c 100644 --- a/polyp/polyplib-subscribe.h +++ b/polyp/polyplib-subscribe.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib-version.h.in b/polyp/polyplib-version.h.in index c2442b520..89e0a0e50 100644 --- a/polyp/polyplib-version.h.in +++ b/polyp/polyplib-version.h.in @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/polyplib.h b/polyp/polyplib.h index 3921e2ba8..a0c418d49 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/props.c b/polyp/props.c index 596133bc4..1046551be 100644 --- a/polyp/props.c +++ b/polyp/props.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/props.h b/polyp/props.h index 954d25404..9b379cf16 100644 --- a/polyp/props.h +++ b/polyp/props.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/protocol-cli.c b/polyp/protocol-cli.c index 266d49697..7ce538878 100644 --- a/polyp/protocol-cli.c +++ b/polyp/protocol-cli.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/protocol-cli.h b/polyp/protocol-cli.h index 7ad2db754..e0fe4bc11 100644 --- a/polyp/protocol-cli.h +++ b/polyp/protocol-cli.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index b6caeb3db..4da7e388b 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/protocol-esound.h b/polyp/protocol-esound.h index b2bdd31b4..dda6977df 100644 --- a/polyp/protocol-esound.h +++ b/polyp/protocol-esound.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 0102e0caf..7d5390148 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/protocol-native.h b/polyp/protocol-native.h index edc6acbc2..57c29e38f 100644 --- a/polyp/protocol-native.h +++ b/polyp/protocol-native.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index ee3bf9d33..f7c69d6b4 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/protocol-simple.h b/polyp/protocol-simple.h index 0fc1e19df..7b15ffcd5 100644 --- a/polyp/protocol-simple.h +++ b/polyp/protocol-simple.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/pstream-util.c b/polyp/pstream-util.c index 3957e6435..95a2ae898 100644 --- a/polyp/pstream-util.c +++ b/polyp/pstream-util.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/pstream-util.h b/polyp/pstream-util.h index b3c89eb04..9560bfe72 100644 --- a/polyp/pstream-util.h +++ b/polyp/pstream-util.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/pstream.c b/polyp/pstream.c index 5fe2b4e75..11ca3963b 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/pstream.h b/polyp/pstream.h index dfd29983b..8fa62f06a 100644 --- a/polyp/pstream.h +++ b/polyp/pstream.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/queue.c b/polyp/queue.c index 9488f4333..e0a06ae11 100644 --- a/polyp/queue.c +++ b/polyp/queue.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/queue.h b/polyp/queue.h index 3ec137345..0b72f37d5 100644 --- a/polyp/queue.h +++ b/polyp/queue.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/resampler.c b/polyp/resampler.c index e8dd01b9f..4ddcfa403 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/resampler.h b/polyp/resampler.h index b984a4f6d..08fad8093 100644 --- a/polyp/resampler.h +++ b/polyp/resampler.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sample-util.c b/polyp/sample-util.c index 51b22fbe1..0d4d18d36 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sample-util.h b/polyp/sample-util.h index 9f3fced16..aafdda630 100644 --- a/polyp/sample-util.h +++ b/polyp/sample-util.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sample.c b/polyp/sample.c index 7048311c0..978a3d6aa 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sample.h b/polyp/sample.h index a02a50fec..93025a103 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/scache.c b/polyp/scache.c index 329778542..32a362899 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/scache.h b/polyp/scache.h index 4fb3dc8eb..afaba31aa 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sconv-s16be.c b/polyp/sconv-s16be.c index a4c25cde9..0ee772c85 100644 --- a/polyp/sconv-s16be.c +++ b/polyp/sconv-s16be.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sconv-s16be.h b/polyp/sconv-s16be.h index d112d9f29..c1876dd08 100644 --- a/polyp/sconv-s16be.h +++ b/polyp/sconv-s16be.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sconv-s16le.c b/polyp/sconv-s16le.c index 40376b52f..2fbcbf310 100644 --- a/polyp/sconv-s16le.c +++ b/polyp/sconv-s16le.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sconv-s16le.h b/polyp/sconv-s16le.h index 0f206ec33..8842140c5 100644 --- a/polyp/sconv-s16le.h +++ b/polyp/sconv-s16le.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sconv.c b/polyp/sconv.c index dd9dd2412..bd670586c 100644 --- a/polyp/sconv.c +++ b/polyp/sconv.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sconv.h b/polyp/sconv.h index 1a62ed20c..0a12890a2 100644 --- a/polyp/sconv.h +++ b/polyp/sconv.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sink-input.c b/polyp/sink-input.c index dac109534..23b4a1364 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sink-input.h b/polyp/sink-input.h index eb2cb2399..1c16a9e61 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sink.c b/polyp/sink.c index 8133d65a2..c17af4ae0 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sink.h b/polyp/sink.h index a2d34ee5b..5da4ca43b 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sioman.c b/polyp/sioman.c index 999b8a5c1..8d7b136c8 100644 --- a/polyp/sioman.c +++ b/polyp/sioman.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sioman.h b/polyp/sioman.h index 1b60d4a9d..840d93f23 100644 --- a/polyp/sioman.h +++ b/polyp/sioman.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 9b80d8098..b77d2aebb 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/socket-client.h b/polyp/socket-client.h index 262fbac3c..9c3e0b37b 100644 --- a/polyp/socket-client.h +++ b/polyp/socket-client.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/socket-server.c b/polyp/socket-server.c index a37b3e34e..7268ccfa4 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/socket-server.h b/polyp/socket-server.h index cc5524d1e..dbd82518d 100644 --- a/polyp/socket-server.h +++ b/polyp/socket-server.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/socket-util.c b/polyp/socket-util.c index e0540179a..1800710f7 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/socket-util.h b/polyp/socket-util.h index aa2de8a52..6c8ffe3b3 100644 --- a/polyp/socket-util.h +++ b/polyp/socket-util.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c index 347d45a7b..43f932305 100644 --- a/polyp/sound-file-stream.c +++ b/polyp/sound-file-stream.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sound-file-stream.h b/polyp/sound-file-stream.h index 9cf88cce6..f5ab8e2c4 100644 --- a/polyp/sound-file-stream.h +++ b/polyp/sound-file-stream.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sound-file.c b/polyp/sound-file.c index c63aa628f..80233da55 100644 --- a/polyp/sound-file.c +++ b/polyp/sound-file.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/sound-file.h b/polyp/sound-file.h index 4d0cf670d..e53598535 100644 --- a/polyp/sound-file.h +++ b/polyp/sound-file.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/source-output.c b/polyp/source-output.c index 5a40fa42d..e339d4acc 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/source-output.h b/polyp/source-output.h index a535782ec..595c08706 100644 --- a/polyp/source-output.h +++ b/polyp/source-output.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/source.c b/polyp/source.c index 73645d494..026ec7a81 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/source.h b/polyp/source.h index 3cac2ad1f..1e6310b08 100644 --- a/polyp/source.h +++ b/polyp/source.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/strbuf.c b/polyp/strbuf.c index 44cae2ce8..8876ba132 100644 --- a/polyp/strbuf.c +++ b/polyp/strbuf.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/strbuf.h b/polyp/strbuf.h index 1622d3a0a..281eee1ec 100644 --- a/polyp/strbuf.h +++ b/polyp/strbuf.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/strlist.c b/polyp/strlist.c index df7278d23..6dc865d1d 100644 --- a/polyp/strlist.c +++ b/polyp/strlist.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/strlist.h b/polyp/strlist.h index 2a209dbaa..533f55335 100644 --- a/polyp/strlist.h +++ b/polyp/strlist.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/subscribe.c b/polyp/subscribe.c index d3b97de7e..b552e4d01 100644 --- a/polyp/subscribe.c +++ b/polyp/subscribe.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/subscribe.h b/polyp/subscribe.h index 8d5e971dc..38323faf5 100644 --- a/polyp/subscribe.h +++ b/polyp/subscribe.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index b9ab55f0c..a6dad868c 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index b943345bb..135825e6d 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/tokenizer.c b/polyp/tokenizer.c index 43d695bd6..8ccbc84f1 100644 --- a/polyp/tokenizer.c +++ b/polyp/tokenizer.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/tokenizer.h b/polyp/tokenizer.h index 7d1cf9b5e..0b1c5022a 100644 --- a/polyp/tokenizer.h +++ b/polyp/tokenizer.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/util.c b/polyp/util.c index 4db92cf44..e8a47df0c 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/util.h b/polyp/util.h index e9d938cea..f38e67391 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/x11prop.c b/polyp/x11prop.c index 6ff91ec4e..bbe3e32c1 100644 --- a/polyp/x11prop.c +++ b/polyp/x11prop.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/x11prop.h b/polyp/x11prop.h index 22461858a..5531c6403 100644 --- a/polyp/x11prop.h +++ b/polyp/x11prop.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/x11wrap.c b/polyp/x11wrap.c index a1a9732a8..4d8d6930f 100644 --- a/polyp/x11wrap.c +++ b/polyp/x11wrap.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/x11wrap.h b/polyp/x11wrap.h index 79c690159..9ed690fe8 100644 --- a/polyp/x11wrap.h +++ b/polyp/x11wrap.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c index 981b3c924..7ddefa94f 100644 --- a/polyp/xmalloc.c +++ b/polyp/xmalloc.c @@ -4,7 +4,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/polyp/xmalloc.h b/polyp/xmalloc.h index 35eda622c..b37ece90d 100644 --- a/polyp/xmalloc.h +++ b/polyp/xmalloc.h @@ -7,7 +7,7 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -16,7 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. From f5f6605254d17c5bc06b8c1ec98e8ee09009af10 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 Nov 2004 14:59:25 +0000 Subject: [PATCH 0278/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@285 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index ad464ea4a..95cf0f4c8 100644 --- a/doc/todo +++ b/doc/todo @@ -15,7 +15,6 @@ - pass meta info for hearing impaired - limit all resources - check getaddrinfo results -- add LGPL blurb to all concerning files - non-fp mixing - non-fp resampling - make module-tunnel use pa_socket_client_new_string() From 0a2bbc528b7865b08139155e0316738a717c4e42 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Nov 2004 00:05:25 +0000 Subject: [PATCH 0279/1514] * some commenting work * add new field "read_only" to memory blocks * add new API function pa_context_get_server() * filter capture data through mcalign on client * make module-tunnel use pa_socket_client_new_string() instead of using pa_resolve_server() directly. * remove pa_resolve_server() * remove debug.h and replace it by a macro definition on the gcc command line * some strbuf cleanups * small fixes in pa_stream for cleanup when server dies * new CLI command "load-sample-dir-lazy" * send FQDN as part of server info * rework mcalign, this time with memory block merging * fix iochannel cleanup when connection dies * check getaddrinfo() results git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@286 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 15 +-- polyp/Makefile.am | 17 +++- polyp/caps.c | 4 + polyp/cli-command.c | 21 ++++- polyp/cpulimit.c | 49 ++++++++-- polyp/debug.h | 29 ------ polyp/iochannel.c | 3 + polyp/mcalign-test.c | 68 ++++++++++++++ polyp/mcalign.c | 188 ++++++++++++++++++++++++++++++++++++++ polyp/mcalign.h | 77 ++++++++++++++++ polyp/memblock.c | 33 ++++--- polyp/memblock.h | 5 +- polyp/memblockq.c | 1 + polyp/memchunk.c | 118 +++--------------------- polyp/memchunk.h | 18 ++-- polyp/module-oss-mmap.c | 4 +- polyp/module-tunnel.c | 16 +--- polyp/polyplib-context.c | 37 ++++++-- polyp/polyplib-context.h | 3 + polyp/polyplib-internal.h | 4 + polyp/polyplib-stream.c | 12 ++- polyp/protocol-esound.c | 1 - polyp/protocol-native.c | 2 +- polyp/scache.c | 62 +++++++++++++ polyp/scache.h | 2 + polyp/sink.c | 2 +- polyp/socket-client.c | 21 ++++- polyp/socket-util.c | 33 ------- polyp/socket-util.h | 2 - polyp/strbuf.c | 62 +++++++------ 30 files changed, 636 insertions(+), 273 deletions(-) delete mode 100644 polyp/debug.h create mode 100644 polyp/mcalign-test.c create mode 100644 polyp/mcalign.c create mode 100644 polyp/mcalign.h diff --git a/doc/todo b/doc/todo index 95cf0f4c8..4f760b7c9 100644 --- a/doc/todo +++ b/doc/todo @@ -2,27 +2,22 @@ *** 0.7 **** - per-channel volume -- add sample directory -- make mcalign merge chunks - option to use default fragment size on alsa drivers - improve module-oss-mmap latency measurement -- filter capture data in client through alignment - add radio module -- add sync API - make most buffer sizes dependant on the sample type - -- X11: support for the X11 synchronization extension -- pass meta info for hearing impaired - limit all resources -- check getaddrinfo results +- commenting - non-fp mixing - non-fp resampling -- make module-tunnel use pa_socket_client_new_string() ** later *** +- pass meta info for hearing impaired +- add sync API +- X11: support for the X11 synchronization extension - xmlrpc/http - dbus -- slp/rendezvous +- rendezvous - make alsa modules use mmap *********** diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 9ea6932a0..506cdc34a 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -27,6 +27,9 @@ AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\" AM_CFLAGS+=-DDEFAULT_CONFIG_DIR=\"$(polypconfdir)\" AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" +# This cool debug trap works on i386/gcc only +AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")' + AM_LIBADD=$(PTHREAD_LIBS) -lm AM_LDADD=$(PTHREAD_LIBS) -lm @@ -40,7 +43,8 @@ noinst_PROGRAMS = \ cpulimit-test \ cpulimit-test2 \ voltest \ - strlist-test + strlist-test \ + mcalign-test polypconf_DATA=default.pa daemon.conf client.conf @@ -196,7 +200,6 @@ polypaudio_SOURCES = idxset.c idxset.h \ autoload.c autoload.h \ xmalloc.c xmalloc.h \ subscribe.h subscribe.c \ - debug.h \ sound-file-stream.c sound-file-stream.h \ cpulimit.c cpulimit.h \ log.c log.h \ @@ -206,7 +209,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ dumpmodules.c dumpmodules.h \ conf-parser.h conf-parser.c \ caps.h caps.c \ - props.h props.c + props.h props.c \ + mcalign.c mcalign.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) @@ -441,7 +445,8 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ client-conf.c client-conf.h \ conf-parser.c conf-parser.h \ strlist.c strlist.h \ - strbuf.c strbuf.h + strbuf.c strbuf.h \ + mcalign.c mcalign.h libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 @@ -495,6 +500,10 @@ strlist_test_SOURCES = strlist-test.c strlist.c strlist.h strbuf.c strbuf.h util strlist_test_CFLAGS = $(AM_CFLAGS) strlist_test_LDADD = $(AM_LDADD) +mcalign_test_SOURCES = mcalign-test.c util.c util.h xmalloc.c xmalloc.h log.c log.h mcalign.c mcalign.h memchunk.c memchunk.h memblock.c memblock.h +mcalign_test_CFLAGS = $(AM_CFLAGS) +mcalign_test_LDADD = $(AM_LDADD) + cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h cpulimit_test_CFLAGS = $(AM_CFLAGS) cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la diff --git a/polyp/caps.c b/polyp/caps.c index daf0b9168..d3719164a 100644 --- a/polyp/caps.c +++ b/polyp/caps.c @@ -35,6 +35,7 @@ #include "log.h" #include "caps.h" +/* Drop root rights when called SUID root */ void pa_drop_root(void) { uid_t uid = getuid(); @@ -50,6 +51,7 @@ void pa_drop_root(void) { #ifdef HAVE_SYS_CAPABILITY_H +/* Limit capabilities set to CAPSYS_NICE */ int pa_limit_caps(void) { int r = -1; cap_t caps; @@ -76,6 +78,7 @@ fail: return r; } +/* Drop all capabilities, effectively becoming a normal user */ int pa_drop_caps(void) { cap_t caps; int r = -1; @@ -100,6 +103,7 @@ fail: #else +/* NOOPs in case capabilities are not available. */ int pa_limit_caps(void) { return 0; } diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 0c71260de..dec877fbd 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -79,6 +79,7 @@ static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_scache_load_dir(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); @@ -112,7 +113,8 @@ static const struct command commands[] = { { "play-sample", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3}, { "remove-sample", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2}, { "load-sample", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: name, filename)", 3}, - { "load-sample-lazy", pa_cli_command_scache_load, "Lazy load a sound file into the sample cache (args: name, filename)", 3}, + { "load-sample-lazy", pa_cli_command_scache_load, "Lazily load a sound file into the sample cache (args: name, filename)", 3}, + { "load-sample-dir-lazy", pa_cli_command_scache_load_dir, "Lazily load all files in a directory into the sample cache (args: pathname)", 2}, { "play-file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3}, { "list-autoload", pa_cli_command_autoload_list, "List autoload entries", 1}, { "add-autoload-sink", pa_cli_command_autoload_add, "Add autoload entry for a sink (args: sink, module name, arguments)", 4}, @@ -545,6 +547,23 @@ static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, return 0; } +static int pa_cli_command_scache_load_dir(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + const char *pname; + assert(c && t && buf && fail && verbose); + + if (!(pname = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a path name.\n"); + return -1; + } + + if (pa_scache_add_directory_lazy(c, pname) < 0) { + pa_strbuf_puts(buf, "Failed to load directory.\n"); + return -1; + } + + return 0; +} + static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { const char *fname, *sink_name; struct pa_sink *sink; diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c index fcbbaf3d2..78dc5e1fd 100644 --- a/polyp/cpulimit.c +++ b/polyp/cpulimit.c @@ -32,30 +32,58 @@ #include "util.h" #include "log.h" + +/* This module implements a watchdog that makes sure that the current + * process doesn't consume more than 70% CPU time for 10 seconds. This + * is very useful when using SCHED_FIFO scheduling which effectively + * disables multitasking. */ + +/* Method of operation: Using SIGXCPU a signal handler is called every + * 10s process CPU time. That function checks if less than 14s system + * time have passed. In that case, it tries to contact the main event + * loop through a pipe. After two additional seconds it is checked + * whether the main event loop contact was successful. If not, the + * program is terminated forcibly. */ + /* Utilize this much CPU time at maximum */ #define CPUTIME_PERCENT 70 +/* Check every 10s */ #define CPUTIME_INTERVAL_SOFT (10) + +/* Recheck after 2s */ #define CPUTIME_INTERVAL_HARD (2) +/* Time of the last CPU load check */ static time_t last_time = 0; + +/* Pipe for communicating with the main loop */ static int the_pipe[2] = {-1, -1}; + +/* Main event loop and IO event for the FIFO */ static struct pa_mainloop_api *api = NULL; static struct pa_io_event *io_event = NULL; -static struct sigaction sigaction_prev; -static int installed = 0; +/* Saved sigaction struct for SIGXCPU */ +static struct sigaction sigaction_prev; + +/* Nonzero after pa_cpu_limit_init() */ +static int installed = 0; + +/* The current state of operation */ static enum { - PHASE_IDLE, - PHASE_SOFT + PHASE_IDLE, /* Normal state */ + PHASE_SOFT /* After CPU overload has been detected */ } phase = PHASE_IDLE; +/* Reset the SIGXCPU timer to the next t seconds */ static void reset_cpu_time(int t) { int r; long n; struct rlimit rl; struct rusage ru; + /* Get the current CPU time of the current process */ r = getrusage(RUSAGE_SELF, &ru); assert(r >= 0); @@ -69,10 +97,12 @@ static void reset_cpu_time(int t) { assert(r >= 0); } +/* A simple, thread-safe puts() work-alike */ static void write_err(const char *p) { pa_loop_write(2, p, strlen(p)); } +/* The signal handler, called on every SIGXCPU */ static void signal_handler(int sig) { assert(sig == SIGXCPU); @@ -109,23 +139,26 @@ static void signal_handler(int sig) { } else if (phase == PHASE_SOFT) { write_err("Hard CPU time limit exhausted, terminating forcibly.\n"); - _exit(1); + _exit(1); /* Forced exit */ } } +/* Callback for IO events on the FIFO */ static void callback(struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) { char c; assert(m && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == the_pipe[0]); read(the_pipe[0], &c, sizeof(c)); - m->quit(m, 1); + m->quit(m, 1); /* Quit the main loop */ } +/* Initializes CPU load limiter */ int pa_cpu_limit_init(struct pa_mainloop_api *m) { struct sigaction sa; - assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1); + assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1 && !installed); time(&last_time); + /* Prepare the main loop pipe */ if (pipe(the_pipe) < 0) { pa_log(__FILE__": pipe() failed: %s\n", strerror(errno)); return -1; @@ -141,6 +174,7 @@ int pa_cpu_limit_init(struct pa_mainloop_api *m) { phase = PHASE_IDLE; + /* Install signal handler for SIGXCPU */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); @@ -158,6 +192,7 @@ int pa_cpu_limit_init(struct pa_mainloop_api *m) { return 0; } +/* Shutdown CPU load limiter */ void pa_cpu_limit_done(void) { int r; diff --git a/polyp/debug.h b/polyp/debug.h deleted file mode 100644 index fcfa71421..000000000 --- a/polyp/debug.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef foodebughfoo -#define foodebughfoo - -/* $Id$ */ - -/*** - This file is part of polypaudio. - - polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - polypaudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -/* A nice trick for debuggers, working on x86 with GCC only */ - -#define DEBUG_TRAP __asm__("int $3") - -#endif diff --git a/polyp/iochannel.c b/polyp/iochannel.c index b93860a58..f174afd0b 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -82,6 +82,9 @@ static void callback(struct pa_mainloop_api* m, struct pa_io_event *e, int fd, e if (e == io->input_event) { io->mainloop->io_free(io->input_event); io->input_event = NULL; + + if (io->output_event == e) + io->output_event = NULL; } if (e == io->output_event) { diff --git a/polyp/mcalign-test.c b/polyp/mcalign-test.c new file mode 100644 index 000000000..ab1f9aed7 --- /dev/null +++ b/polyp/mcalign-test.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "mcalign.h" + +int main(int argc, char *argv[]) { + struct pa_mcalign *a = pa_mcalign_new(11, NULL); + struct pa_memchunk c; + + pa_memchunk_reset(&c); + + srand(time(NULL)); + + for (;;) { + ssize_t r; + size_t l; + + if (!c.memblock) { + c.memblock = pa_memblock_new(2048, NULL); + c.index = c.length = 0; + } + + assert(c.index < c.memblock->length); + + l = c.memblock->length - c.index; + + l = l <= 1 ? l : rand() % (l-1) +1 ; + + if ((r = read(STDIN_FILENO, (uint8_t*) c.memblock->data + c.index, l)) <= 0) { + fprintf(stderr, "read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + break; + } + + c.length = r; + pa_mcalign_push(a, &c); + fprintf(stderr, "Read %u bytes\n", r); + + c.index += r; + + if (c.index >= c.memblock->length) { + pa_memblock_unref(c.memblock); + pa_memchunk_reset(&c); + } + + for (;;) { + struct pa_memchunk t; + + if (pa_mcalign_pop(a, &t) < 0) + break; + + pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length); + fprintf(stderr, "Wrote %u bytes.\n", t.length); + + pa_memblock_unref(t.memblock); + } + } + + pa_mcalign_free(a); + + if (c.memblock) + pa_memblock_unref(c.memblock); +} diff --git a/polyp/mcalign.c b/polyp/mcalign.c new file mode 100644 index 000000000..0b7f0db01 --- /dev/null +++ b/polyp/mcalign.c @@ -0,0 +1,188 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "mcalign.h" +#include "xmalloc.h" + +struct pa_mcalign { + size_t base; + struct pa_memchunk leftover, current; + struct pa_memblock_stat *memblock_stat; +}; + +struct pa_mcalign *pa_mcalign_new(size_t base, struct pa_memblock_stat *s) { + struct pa_mcalign *m; + assert(base); + + m = pa_xmalloc(sizeof(struct pa_mcalign)); + m->base = base; + pa_memchunk_reset(&m->leftover); + pa_memchunk_reset(&m->current); + m->memblock_stat = s; + + return m; +} + +void pa_mcalign_free(struct pa_mcalign *m) { + assert(m); + + if (m->leftover.memblock) + pa_memblock_unref(m->leftover.memblock); + + if (m->current.memblock) + pa_memblock_unref(m->current.memblock); + + pa_xfree(m); +} + +void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) { + assert(m && c && c->memblock && c->length); + + /* Append to the leftover memory block */ + if (m->leftover.memblock) { + assert(!m->current.memblock); + + /* Try to merge */ + if (m->leftover.memblock == c->memblock && + m->leftover.index + m->leftover.length == c->index) { + + /* Merge */ + m->leftover.length += c->length; + + /* If the new chunk is larger than m->base, move it to current */ + if (m->leftover.length >= m->base) { + m->current = m->leftover; + pa_memchunk_reset(&m->leftover); + } + + } else { + size_t l; + + /* We have to copy */ + assert(m->leftover.length < m->base); + l = m->base - m->leftover.length; + + if (l > c->length) + l = c->length; + + /* Can we use the current block? */ + pa_memchunk_make_writable(&m->leftover, m->memblock_stat, m->base); + + memcpy((uint8_t*) m->leftover.memblock->data + m->leftover.index + m->leftover.length, (uint8_t*) c->memblock->data + c->index, l); + m->leftover.length += l; + + assert(m->leftover.length <= m->base && m->leftover.length <= m->leftover.memblock->length); + + if (c->length > l) { + /* Save the remainder of the memory block */ + m->current = *c; + m->current.index += l; + m->current.length -= l; + pa_memblock_ref(m->current.memblock); + } + } + } else { + assert(!m->leftover.memblock && !m->current.memblock); + + /* Nothing to merge or copy, just store it */ + + if (c->length >= m->base) + m->current = *c; + else + m->leftover = *c; + + pa_memblock_ref(c->memblock); + } +} + +int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) { + assert(m && c); + + /* First test if there's a leftover memory block available */ + if (m->leftover.memblock) { + assert(m->leftover.length > 0 && m->leftover.length <= m->base); + + /* The leftover memory block is not yet complete */ + if (m->leftover.length < m->base) + return -1; + + /* Return the leftover memory block */ + *c = m->leftover; + pa_memchunk_reset(&m->leftover); + + /* If the current memblock is too small move it the leftover */ + if (m->current.memblock && m->current.length < m->base) { + m->leftover = m->current; + pa_memchunk_reset(&m->current); + } + + return 0; + } + + /* Now let's see if there is other data available */ + if (m->current.memblock) { + size_t l; + assert(m->current.length >= m->base); + + /* The length of the returned memory block */ + l = m->current.length; + l /= m->base; + l *= m->base; + assert(l > 0); + + /* Prepare the returned block */ + *c = m->current; + pa_memblock_ref(c->memblock); + c->length = l; + + /* Drop that from the current memory block */ + assert(l <= m->current.length); + m->current.index += l; + m->current.length -= l; + + /* In case the whole block was dropped ... */ + if (m->current.length == 0) + pa_memblock_unref(m->current.memblock); + else { + /* Move the raimainder to leftover */ + assert(m->current.length < m->base && !m->leftover.memblock); + + m->leftover = m->current; + } + + pa_memchunk_reset(&m->current); + + return 0; + } + + /* There's simply nothing */ + return -1; + +} diff --git a/polyp/mcalign.h b/polyp/mcalign.h new file mode 100644 index 000000000..925f438a5 --- /dev/null +++ b/polyp/mcalign.h @@ -0,0 +1,77 @@ +#ifndef foomcalignhfoo +#define foomcalignhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "memblock.h" +#include "memchunk.h" + +/* An alignment object, used for aligning memchunks to multiples of + * the frame size. */ + +/* Method of operation: the user creates a new mcalign object by + * calling pa_mcalign_new() with the appropriate aligning + * granularity. After that he may call pa_mcalign_push() for an input + * memchunk. After exactly one memchunk the user has to call + * pa_mcalign_pop() until it returns -1. If pa_mcalign_pop() returns + * 0, the memchunk *c is valid and aligned to the granularity. Some + * pseudocode illustrating this: + * + * struct pa_mcalign *a = pa_mcalign_new(4, NULL); + * + * for (;;) { + * struct pa_memchunk input; + * + * ... fill input ... + * + * pa_mcalign_push(m, &input); + * pa_memblock_unref(input.memblock); + * + * for (;;) { + * struct pa_memchunk output; + * + * if (pa_mcalign_pop(m, &output) < 0) + * break; + * + * ... consume output ... + * + * pa_memblock_unref(output.memblock); + * } + * } + * + * pa_memchunk_free(a); + * */ + +struct pa_mcalign; + +struct pa_mcalign *pa_mcalign_new(size_t base, struct pa_memblock_stat *s); +void pa_mcalign_free(struct pa_mcalign *m); + +/* Push a new memchunk into the aligner. The caller of this routine + * has to free the memchunk by himself. */ +void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c); + +/* Pop a new memchunk from the aligner. Returns 0 when sucessful, + * nonzero otherwise. */ +int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c); + +#endif diff --git a/polyp/memblock.c b/polyp/memblock.c index 8ddfb8011..c070bee65 100644 --- a/polyp/memblock.c +++ b/polyp/memblock.c @@ -34,6 +34,11 @@ static void stat_add(struct pa_memblock*m, struct pa_memblock_stat *s) { assert(m); + if (!s) { + m->stat = NULL; + return; + } + m->stat = pa_memblock_stat_ref(s); s->total++; s->allocated++; @@ -61,17 +66,7 @@ struct pa_memblock *pa_memblock_new(size_t length, struct pa_memblock_stat*s) { b->length = length; b->data = b+1; b->free_cb = NULL; - stat_add(b, s); - return b; -} - -struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length, struct pa_memblock_stat*s) { - struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)); - b->type = PA_MEMBLOCK_FIXED; - b->ref = 1; - b->length = length; - b->data = d; - b->free_cb = NULL; + b->read_only = 0; stat_add(b, s); return b; } @@ -83,11 +78,24 @@ struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length, struct pa_me b->length = length; b->data = d; b->free_cb = NULL; + b->read_only = 0; stat_add(b, s); return b; } -struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p), struct pa_memblock_stat*s) { +struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length, int read_only, struct pa_memblock_stat*s) { + struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)); + b->type = PA_MEMBLOCK_FIXED; + b->ref = 1; + b->length = length; + b->data = d; + b->free_cb = NULL; + b->read_only = read_only; + stat_add(b, s); + return b; +} + +struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p), int read_only, struct pa_memblock_stat*s) { struct pa_memblock *b; assert(d && length && free_cb); b = pa_xmalloc(sizeof(struct pa_memblock)); @@ -96,6 +104,7 @@ struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb) b->length = length; b->data = d; b->free_cb = free_cb; + b->read_only = read_only; stat_add(b, s); return b; } diff --git a/polyp/memblock.h b/polyp/memblock.h index 69a85a800..91612ac93 100644 --- a/polyp/memblock.h +++ b/polyp/memblock.h @@ -32,6 +32,7 @@ struct pa_memblock_stat; struct pa_memblock { enum pa_memblock_type type; unsigned ref; + int read_only; size_t length; void *data; void (*free_cb)(void *p); @@ -39,9 +40,9 @@ struct pa_memblock { }; struct pa_memblock *pa_memblock_new(size_t length, struct pa_memblock_stat*s); -struct pa_memblock *pa_memblock_new_fixed(void *data, size_t length, struct pa_memblock_stat*s); struct pa_memblock *pa_memblock_new_dynamic(void *data, size_t length, struct pa_memblock_stat*s); -struct pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p), struct pa_memblock_stat*s); +struct pa_memblock *pa_memblock_new_fixed(void *data, size_t length, int read_only, struct pa_memblock_stat*s); +struct pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p), int read_only, struct pa_memblock_stat*s); void pa_memblock_unref(struct pa_memblock*b); struct pa_memblock* pa_memblock_ref(struct pa_memblock*b); diff --git a/polyp/memblockq.c b/polyp/memblockq.c index 0fbeaad09..ff16f6279 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -33,6 +33,7 @@ #include "memblockq.h" #include "xmalloc.h" #include "log.h" +#include "mcalign.h" struct memblock_list { struct memblock_list *next, *prev; diff --git a/polyp/memchunk.c b/polyp/memchunk.c index a8aeb881e..d1c923f3c 100644 --- a/polyp/memchunk.c +++ b/polyp/memchunk.c @@ -31,120 +31,28 @@ #include "memchunk.h" #include "xmalloc.h" -void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s) { +void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s, size_t min) { struct pa_memblock *n; + size_t l; assert(c && c->memblock && c->memblock->ref >= 1); - if (c->memblock->ref == 1) + if (c->memblock->ref == 1 && !c->memblock->read_only && c->memblock->length >= c->index+min) return; + + l = c->length; + if (l < min) + l = min; - n = pa_memblock_new(c->length, s); - assert(n); - memcpy(n->data, (uint8_t*) c->memblock->data+c->index, c->length); + n = pa_memblock_new(l, s); + memcpy(n->data, (uint8_t*) c->memblock->data + c->index, c->length); pa_memblock_unref(c->memblock); c->memblock = n; c->index = 0; } +void pa_memchunk_reset(struct pa_memchunk *c) { + assert(c); -struct pa_mcalign { - size_t base; - struct pa_memchunk chunk; - uint8_t *buffer; - size_t buffer_fill; - struct pa_memblock_stat *memblock_stat; -}; - -struct pa_mcalign *pa_mcalign_new(size_t base, struct pa_memblock_stat *s) { - struct pa_mcalign *m; - assert(base); - - m = pa_xmalloc(sizeof(struct pa_mcalign)); - m->base = base; - m->chunk.memblock = NULL; - m->chunk.length = m->chunk.index = 0; - m->buffer = NULL; - m->buffer_fill = 0; - m->memblock_stat = s; - return m; -} - -void pa_mcalign_free(struct pa_mcalign *m) { - assert(m); - - pa_xfree(m->buffer); - - if (m->chunk.memblock) - pa_memblock_unref(m->chunk.memblock); - - pa_xfree(m); -} - -void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) { - assert(m && c && !m->chunk.memblock && c->memblock && c->length); - - m->chunk = *c; - pa_memblock_ref(m->chunk.memblock); -} - -int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) { - int ret; - assert(m && c && m->base > m->buffer_fill); - - if (!m->chunk.memblock) - return -1; - - if (m->buffer_fill) { - size_t l = m->base - m->buffer_fill; - if (l > m->chunk.length) - l = m->chunk.length; - assert(m->buffer && l); - - memcpy((uint8_t*) m->buffer + m->buffer_fill, (uint8_t*) m->chunk.memblock->data + m->chunk.index, l); - m->buffer_fill += l; - m->chunk.index += l; - m->chunk.length -= l; - - if (m->chunk.length == 0) { - m->chunk.length = m->chunk.index = 0; - pa_memblock_unref(m->chunk.memblock); - m->chunk.memblock = NULL; - } - - assert(m->buffer_fill <= m->base); - if (m->buffer_fill == m->base) { - c->memblock = pa_memblock_new_dynamic(m->buffer, m->base, m->memblock_stat); - assert(c->memblock); - c->index = 0; - c->length = m->base; - m->buffer = NULL; - m->buffer_fill = 0; - - return 0; - } - - return -1; - } - - m->buffer_fill = m->chunk.length % m->base; - - if (m->buffer_fill) { - assert(!m->buffer); - m->buffer = pa_xmalloc(m->base); - m->chunk.length -= m->buffer_fill; - memcpy(m->buffer, (uint8_t*) m->chunk.memblock->data + m->chunk.index + m->chunk.length, m->buffer_fill); - } - - if (m->chunk.length) { - *c = m->chunk; - pa_memblock_ref(c->memblock); - ret = 0; - } else - ret = -1; - - m->chunk.length = m->chunk.index = 0; - pa_memblock_unref(m->chunk.memblock); - m->chunk.memblock = NULL; - - return ret; + c->memblock = NULL; + c->length = c->index = 0; } diff --git a/polyp/memchunk.h b/polyp/memchunk.h index e73b6f6ed..a004c2e84 100644 --- a/polyp/memchunk.h +++ b/polyp/memchunk.h @@ -24,18 +24,22 @@ #include "memblock.h" +/* A memchunk is a part of a memblock. In contrast to the memblock, a + * memchunk is not allocated dynamically or reference counted, instead + * it is usually stored on the stack and copied around */ + struct pa_memchunk { struct pa_memblock *memblock; size_t index, length; }; -void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s); +/* Make a memchunk writable, i.e. make sure that the caller may have + * exclusive access to the memblock and it is not read_only. If needed + * the memblock in the structure is replaced by a copy. */ +void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s, size_t min); -struct pa_mcalign; - -struct pa_mcalign *pa_mcalign_new(size_t base, struct pa_memblock_stat *s); -void pa_mcalign_free(struct pa_mcalign *m); -void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c); -int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c); +/* Invalidate a memchunk. This does not free the cotaining memblock, + * but sets all members to zero. */ +void pa_memchunk_reset(struct pa_memchunk *c); #endif diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 8aecd5602..66daa77d8 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -107,7 +107,7 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { if (u->out_memblocks[u->out_current]) pa_memblock_unref_fixed(u->out_memblocks[u->out_current]); - chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed((uint8_t*)u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size, u->core->memblock_stat); + chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed((uint8_t*)u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size, 1, u->core->memblock_stat); assert(chunk.memblock); chunk.length = chunk.memblock->length; chunk.index = 0; @@ -148,7 +148,7 @@ static void in_post_memblocks(struct userdata *u, unsigned n) { struct pa_memchunk chunk; if (!u->in_memblocks[u->in_current]) { - chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed((uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, u->core->memblock_stat); + chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed((uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, 1, u->core->memblock_stat); chunk.length = chunk.memblock->length; chunk.index = 0; diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index 368ae422a..7497011d4 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -610,19 +610,9 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; } - if (u->server_name[0] == '/') - u->client = pa_socket_client_new_unix(c->mainloop, u->server_name); - else { - size_t len; - struct sockaddr *sa; - - if (!(sa = pa_resolve_server(u->server_name, &len, PA_NATIVE_DEFAULT_PORT))) { - pa_log(__FILE__": failed to resolve server '%s'\n", u->server_name); - goto fail; - } - - u->client = pa_socket_client_new_sockaddr(c->mainloop, sa, len); - pa_xfree(sa); + if (!(u->client = pa_socket_client_new_string(c->mainloop, u->server_name, PA_NATIVE_DEFAULT_PORT))) { + pa_log(__FILE__": failed to connect to server '%s'\n", u->server_name); + goto fail; } if (!u->client) diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index b15dd8e7d..15ef60b9f 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -56,8 +56,6 @@ #define AUTOSPAWN_LOCK "autospawn.lock" - - static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = { pa_command_request }, [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { pa_command_stream_killed }, @@ -72,7 +70,6 @@ static void unlock_autospawn_lock_file(struct pa_context *c) { pa_unlock_lockfile(c->autospawn_lock_fd); c->autospawn_lock_fd = -1; } - } struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { @@ -106,6 +103,7 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->memblock_stat = pa_memblock_stat_new(); c->local = -1; c->server_list = NULL; + c->server = NULL; c->autospawn_lock_fd = -1; memset(&c->spawn_api, 0, sizeof(c->spawn_api)); c->do_autospawn = 0; @@ -155,6 +153,7 @@ static void context_free(struct pa_context *c) { pa_strlist_free(c->server_list); pa_xfree(c->name); + pa_xfree(c->server); pa_xfree(c); } @@ -246,9 +245,20 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui pa_context_ref(c); if ((s = pa_dynarray_get(c->record_streams, channel))) { - if (s->read_callback) { - s->read_callback(s, (uint8_t*) chunk->memblock->data + chunk->index, chunk->length, s->read_userdata); - s->counter += chunk->length; + pa_mcalign_push(s->mcalign, chunk); + + for (;;) { + struct pa_memchunk t; + + if (pa_mcalign_pop(s->mcalign, &t) < 0) + break; + + if (s->read_callback) { + s->read_callback(s, (uint8_t*) t.memblock->data + t.index, t.length, s->read_userdata); + s->counter += chunk->length; + } + + pa_memblock_unref(t.memblock); } } @@ -496,6 +506,9 @@ static int try_next_connection(struct pa_context *c) { } /* pa_log(__FILE__": Trying to connect to %s...\n", u); */ + + pa_xfree(c->server); + c->server = pa_xstrdup(u); if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT))) continue; @@ -811,3 +824,15 @@ const char* pa_get_library_version(void) { return PACKAGE_VERSION; } +const char* pa_context_get_server(struct pa_context *c) { + + if (!c->server) + return NULL; + + if (*c->server == '{') { + char *e = strchr(c->server+1, '}'); + return e ? e+1 : c->server; + } + + return c->server; +} diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 565701b22..db4b121dd 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -108,6 +108,9 @@ int pa_context_is_local(struct pa_context *c); /** Set a different application name for context on the server. \since 0.5 */ struct pa_operation* pa_context_set_name(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata); +/** Return the server name this context is connected to. \since 0.7 */ +const char* pa_context_get_server(struct pa_context *c); + PA_C_DECL_END #endif diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index d1b53633c..68ba76a93 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -35,6 +35,7 @@ #include "native-common.h" #include "client-conf.h" #include "strlist.h" +#include "mcalign.h" #define DEFAULT_TLENGTH (44100*2*2/2) //(10240*8) #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) @@ -77,6 +78,8 @@ struct pa_context { struct pa_strlist *server_list; + char *server; + struct pa_client_conf *conf; }; @@ -97,6 +100,7 @@ struct pa_stream { uint64_t counter; pa_usec_t previous_time; enum pa_stream_state state; + struct pa_mcalign *mcalign; int interpolate; int corked; diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index a97096b42..7d3d3a763 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -61,6 +61,8 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st s->state = PA_STREAM_DISCONNECTED; memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + s->mcalign = pa_mcalign_new(pa_frame_size(ss), c->memblock_stat); + s->counter = 0; s->previous_time = 0; @@ -83,6 +85,8 @@ static void stream_free(struct pa_stream *s) { assert(s->mainloop); s->mainloop->time_free(s->ipol_event); } + + pa_mcalign_free(s->mcalign); pa_xfree(s->name); pa_xfree(s); @@ -203,11 +207,13 @@ static void ipol_callback(struct pa_mainloop_api *m, struct pa_time_event *e, co struct pa_stream *s = userdata; pa_stream_ref(s); - pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + if (s->state == PA_STREAM_READY) + pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + gettimeofday(&tv2, NULL); tv2.tv_usec += LATENCY_IPOL_INTERVAL_USEC; - + m->time_restart(e, &tv2); pa_stream_unref(s); @@ -329,7 +335,7 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void assert(s && s->context && data && length && s->state == PA_STREAM_READY && s->ref >= 1); if (free_cb) { - chunk.memblock = pa_memblock_new_user((void*) data, length, free_cb, s->context->memblock_stat); + chunk.memblock = pa_memblock_new_user((void*) data, length, free_cb, 1, s->context->memblock_stat); assert(chunk.memblock && chunk.memblock->data); } else { chunk.memblock = pa_memblock_new(length, s->context->memblock_stat); diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 4da7e388b..07c39e2a0 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -42,7 +42,6 @@ #include "scache.h" #include "sample-util.h" #include "authkey.h" -#include "debug.h" #include "namereg.h" #include "xmalloc.h" #include "log.h" diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 7d5390148..02d81db3e 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -1343,7 +1343,7 @@ static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, u pa_tagstruct_puts(reply, PACKAGE_NAME); pa_tagstruct_puts(reply, PACKAGE_VERSION); pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt))); - pa_tagstruct_puts(reply, pa_get_host_name(txt, sizeof(txt))); + pa_tagstruct_puts(reply, pa_get_fqdn(txt, sizeof(txt))); pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec); n = pa_namereg_get_default_sink_name(c->protocol->core); diff --git a/polyp/scache.c b/polyp/scache.c index 32a362899..ccdc71855 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -27,6 +27,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include "scache.h" #include "sink-input.h" @@ -38,6 +44,7 @@ #include "namereg.h" #include "sound-file.h" #include "util.h" +#include "log.h" #define UNLOAD_POLL_TIME 2 @@ -291,3 +298,58 @@ void pa_scache_unload_unused(struct pa_core *c) { pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); } } + +static void add_file(struct pa_core *c, const char *pathname) { + struct stat st; + const char *e; + + if (!(e = strrchr(pathname, '/'))) + e = pathname; + else + e++; + + if (stat(pathname, &st) < 0) { + pa_log(__FILE__": stat('%s') failed: %s\n", pathname, strerror(errno)); + return; + } + + if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) + pa_scache_add_file_lazy(c, e, pathname, NULL); +} + +int pa_scache_add_directory_lazy(struct pa_core *c, const char *pathname) { + DIR *dir; + assert(c && pathname); + + /* First try to open this as directory */ + if (!(dir = opendir(pathname))) { + glob_t p; + unsigned int i; + /* If that fails, try to open it as shell glob */ + + if (glob(pathname, GLOB_ERR|GLOB_NOSORT, NULL, &p) < 0) { + pa_log(__FILE__": Failed to open directory: %s\n", strerror(errno)); + return -1; + } + + for (i = 0; i < p.gl_pathc; i++) + add_file(c, p.gl_pathv[i]); + + globfree(&p); + } else { + struct dirent *e; + + while ((e = readdir(dir))) { + char p[PATH_MAX]; + + if (e->d_name[0] == '.') + continue; + + snprintf(p, sizeof(p), "%s/%s", pathname, e->d_name); + add_file(c, p); + } + } + + closedir(dir); + return 0; +} diff --git a/polyp/scache.h b/polyp/scache.h index afaba31aa..f7043f163 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -45,6 +45,8 @@ int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spe int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename, uint32_t *index); int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index); +int pa_scache_add_directory_lazy(struct pa_core *c, const char *pathname); + int pa_scache_remove_item(struct pa_core *c, const char *name); int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume); void pa_scache_free(struct pa_core *c); diff --git a/polyp/sink.c b/polyp/sink.c index c17af4ae0..29aef6fba 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -225,7 +225,7 @@ int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) volume = pa_volume_multiply(s->volume, info[0].volume); if (volume != PA_VOLUME_NORM) { - pa_memchunk_make_writable(result, s->core->memblock_stat); + pa_memchunk_make_writable(result, s->core->memblock_stat, 0); pa_volume_memchunk(result, &s->sample_spec, volume); } } else { diff --git a/polyp/socket-client.c b/polyp/socket-client.c index b77d2aebb..aea385867 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -338,16 +338,24 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, memset(&hints, 0, sizeof(hints)); hints.ai_family = kind == KIND_TCP4 ? AF_INET : (kind == KIND_TCP6 ? AF_INET6 : AF_UNSPEC); - if (getaddrinfo(h, NULL, &hints, &res) < 0 || !res) + if (getaddrinfo(h, NULL, &hints, &res) < 0 || !res || !res->ai_addr) return NULL; - if (res->ai_addr->sa_family == AF_INET) + if (res->ai_family == AF_INET) { + if (res->ai_addrlen != sizeof(struct sockaddr_in)) + return NULL; + assert(res->ai_addr->sa_family == res->ai_family); + ((struct sockaddr_in*) res->ai_addr)->sin_port = htons(port); - else if (res->ai_addr->sa_family == AF_INET6) + } else if (res->ai_family == AF_INET6) { + if (res->ai_addrlen != sizeof(struct sockaddr_in6)) + return NULL; + assert(res->ai_addr->sa_family == res->ai_family); + ((struct sockaddr_in6*) res->ai_addr)->sin6_port = htons(port); - else + } else return NULL; - + c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); return c; @@ -360,6 +368,9 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, } +/* Return non-zero when the target sockaddr is considered + local. "local" means UNIX socket or TCP socket on localhost. Other + local IP addresses are not considered local. */ int pa_socket_client_is_local(struct pa_socket_client *c) { assert(c); return c->local; diff --git a/polyp/socket-util.c b/polyp/socket-util.c index 1800710f7..495ee1b06 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -202,36 +202,3 @@ int pa_unix_socket_remove_stale(const char *fn) { return 0; } - -struct sockaddr *pa_resolve_server(const char *server, size_t *len, uint16_t nport) { - struct sockaddr *sa; - struct addrinfo hints, *result = NULL; - char *port, host[256], tmp[16]; - assert(server && len); - - snprintf(host, sizeof(host), "%s", server); - host[strcspn(host, ":")] = 0; - - if ((port = strrchr(server, ':'))) - port++; - - if (!port) - snprintf(port = tmp, sizeof(tmp), "%u", nport); - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - if (getaddrinfo(host, port, &hints, &result) != 0) - return NULL; - assert(result); - - sa = pa_xmalloc(*len = result->ai_addrlen); - memcpy(sa, result->ai_addr, *len); - - freeaddrinfo(result); - - return sa; -} - diff --git a/polyp/socket-util.h b/polyp/socket-util.h index 6c8ffe3b3..ae16fb164 100644 --- a/polyp/socket-util.h +++ b/polyp/socket-util.h @@ -35,6 +35,4 @@ int pa_socket_set_rcvbuf(int fd, size_t l); int pa_unix_socket_is_stale(const char *fn); int pa_unix_socket_remove_stale(const char *fn); -struct sockaddr *pa_resolve_server(const char *server, size_t *len, uint16_t port); - #endif diff --git a/polyp/strbuf.c b/polyp/strbuf.c index 8876ba132..a65216515 100644 --- a/polyp/strbuf.c +++ b/polyp/strbuf.c @@ -33,6 +33,7 @@ #include "strbuf.h" +/* Some magic for zero-length arrays */ #ifdef __STDC_VERSION__ #if __STDC_VERSION__ >= 199901L #ifndef STDC99 @@ -41,6 +42,7 @@ #endif #endif +/* A chunk of the linked list that makes up the string */ struct chunk { struct chunk *next; size_t length; @@ -74,6 +76,8 @@ void pa_strbuf_free(struct pa_strbuf *sb) { pa_xfree(sb); } +/* Make a C string from the string buffer. The caller has to free + * string with pa_xfree(). */ char *pa_strbuf_tostring(struct pa_strbuf *sb) { char *t, *e; struct chunk *c; @@ -83,15 +87,18 @@ char *pa_strbuf_tostring(struct pa_strbuf *sb) { e = t; for (c = sb->head; c; c = c->next) { + assert((size_t) (e-t) <= sb->length); memcpy(e, c->text, c->length); e += c->length; } + /* Trailing NUL */ *e = 0; return t; } +/* Combination of pa_strbuf_free() and pa_strbuf_tostring() */ char *pa_strbuf_tostring_free(struct pa_strbuf *sb) { char *t; assert(sb); @@ -100,23 +107,15 @@ char *pa_strbuf_tostring_free(struct pa_strbuf *sb) { return t; } +/* Append a string to the string buffer */ void pa_strbuf_puts(struct pa_strbuf *sb, const char *t) { assert(sb && t); pa_strbuf_putsn(sb, t, strlen(t)); -} +} -void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t l) { - struct chunk *c; - assert(sb && t); - - if (!l) - return; - - c = pa_xmalloc(sizeof(struct chunk)+l); - - c->next = NULL; - c->length = l; - memcpy(c->text, t, l); +/* Append a new chunk to the linked list */ +static void append(struct pa_strbuf *sb, struct chunk *c) { + assert(sb && c); if (sb->tail) { assert(sb->head); @@ -127,19 +126,36 @@ void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t l) { } sb->tail = c; - sb->length += l; + sb->length += c->length; + c->next = NULL; } -/* The following is based on an example from the GNU libc documentation */ +/* Append up to l bytes of a string to the string buffer */ +void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t l) { + struct chunk *c; + assert(sb && t); + + if (!l) + return; + + c = pa_xmalloc(sizeof(struct chunk)+l); + c->length = l; + memcpy(c->text, t, l); + append(sb, c); +} + +/* Append a printf() style formatted string to the string buffer. */ +/* The following is based on an example from the GNU libc documentation */ int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) { - int r, size = 100; + int size = 100; struct chunk *c = NULL; assert(sb); for(;;) { va_list ap; + int r; c = pa_xrealloc(c, sizeof(struct chunk)+size); @@ -149,19 +165,7 @@ int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) { if (r > -1 && r < size) { c->length = r; - c->next = NULL; - - if (sb->tail) { - assert(sb->head); - sb->tail->next = c; - } else { - assert(!sb->head); - sb->head = c; - } - - sb->tail = c; - sb->length += r; - + append(sb, c); return r; } From 5ea2783dda66ebf343f72350aaa99d22f35f6d0e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Nov 2004 01:04:52 +0000 Subject: [PATCH 0280/1514] * fix a long standing bug in ioline.c (large prints failed) * fix a bug regarding ipv6 binding git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@287 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/cli-command.c | 2 - polyp/cli.c | 12 ++--- polyp/ioline.c | 109 ++++++++++++++++++++++++++---------------- polyp/socket-server.c | 4 +- polyp/strbuf.c | 27 ++++------- 5 files changed, 83 insertions(+), 71 deletions(-) diff --git a/polyp/cli-command.c b/polyp/cli-command.c index dec877fbd..c11647fc5 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -242,8 +242,6 @@ static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_namereg_get_default_sink_name(c), pa_namereg_get_default_source_name(c)); - - return 0; } diff --git a/polyp/cli.c b/polyp/cli.c index 15142f357..2ff359922 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -44,6 +44,8 @@ #include "xmalloc.h" #include "log.h" +#define PROMPT ">>> " + struct pa_cli { struct pa_core *core; struct pa_ioline *line; @@ -57,9 +59,6 @@ struct pa_cli { }; static void line_callback(struct pa_ioline *line, const char *s, void *userdata); - -static const char prompt[] = ">>> "; - static void client_kill(struct pa_client *c); struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct pa_module *m) { @@ -83,8 +82,7 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct c->client->owner = m; pa_ioline_set_callback(c->line, line_callback, c); - pa_ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"); - pa_ioline_puts(c->line, prompt); + pa_ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"PROMPT); c->fail = c->kill_requested = c->defer_kill = 0; c->verbose = 1; @@ -139,11 +137,11 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) if (c->eof_callback) c->eof_callback(c, c->userdata); } else - pa_ioline_puts(line, prompt); + pa_ioline_puts(line, PROMPT); } void pa_cli_set_eof_callback(struct pa_cli *c, void (*cb)(struct pa_cli*c, void *userdata), void *userdata) { - assert(c && cb); + assert(c); c->eof_callback = cb; c->userdata = userdata; } diff --git a/polyp/ioline.c b/polyp/ioline.c index b1c980d86..f3d17b586 100644 --- a/polyp/ioline.c +++ b/polyp/ioline.c @@ -92,8 +92,11 @@ void pa_ioline_puts(struct pa_ioline *l, const char *c) { if (!len) return; - - if (len > l->wbuf_length - l->wbuf_valid_length) { + + assert(l->wbuf_length >= l->wbuf_valid_length); + + /* In case the allocated buffer is too small, enlarge it. */ + if (l->wbuf_valid_length + len > l->wbuf_length) { size_t n = l->wbuf_valid_length+len; char *new = pa_xmalloc(n); if (l->wbuf) { @@ -103,27 +106,64 @@ void pa_ioline_puts(struct pa_ioline *l, const char *c) { l->wbuf = new; l->wbuf_length = n; l->wbuf_index = 0; - } else if (len > l->wbuf_length - l->wbuf_valid_length - l->wbuf_index) { + } else if (l->wbuf_index + l->wbuf_valid_length + len > l->wbuf_length) { + + /* In case the allocated buffer fits, but the current index is too far from the start, move it to the front. */ memmove(l->wbuf, l->wbuf+l->wbuf_index, l->wbuf_valid_length); l->wbuf_index = 0; } - memcpy(l->wbuf+l->wbuf_index+l->wbuf_valid_length, c, len); + assert(l->wbuf_index + l->wbuf_valid_length + len <= l->wbuf_length); + + /* Append the new string */ + memcpy(l->wbuf + l->wbuf_index + l->wbuf_valid_length, c, len); l->wbuf_valid_length += len; do_write(l); } void pa_ioline_set_callback(struct pa_ioline*l, void (*callback)(struct pa_ioline*io, const char *s, void *userdata), void *userdata) { - assert(l && callback); + assert(l); l->callback = callback; l->userdata = userdata; } +static void scan_for_lines(struct pa_ioline *l, size_t skip) { + assert(l && skip < l->rbuf_valid_length); + + while (!l->dead && l->rbuf_valid_length > skip) { + char *e, *p; + size_t m; + + if (!(e = memchr(l->rbuf + l->rbuf_index + skip, '\n', l->rbuf_valid_length - skip))) + break; + + *e = 0; + + p = l->rbuf + l->rbuf_index; + m = strlen(p); + + l->rbuf_index += m+1; + l->rbuf_valid_length -= m+1; + + /* A shortcut for the next time */ + if (l->rbuf_valid_length == 0) + l->rbuf_index = 0; + + if (l->callback) + l->callback(l, p, l->userdata); + + skip = 0; + } + + /* If the buffer became too large and still no newline was found, drop it. */ + if (l->rbuf_valid_length >= BUFFER_LIMIT) + l->rbuf_index = l->rbuf_valid_length = 0; +} + static int do_read(struct pa_ioline *l) { ssize_t r; - size_t m, len; - char *e; + size_t len; assert(l); if (!pa_iochannel_is_readable(l->io)) @@ -131,6 +171,7 @@ static int do_read(struct pa_ioline *l) { len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; + /* Check if we have to enlarge the read buffer */ if (len < READ_SIZE) { size_t n = l->rbuf_valid_length+READ_SIZE; @@ -138,9 +179,11 @@ static int do_read(struct pa_ioline *l) { n = BUFFER_LIMIT; if (l->rbuf_length >= n) { + /* The current buffer is large enough, let's just move the data to the front */ if (l->rbuf_valid_length) memmove(l->rbuf, l->rbuf+l->rbuf_index, l->rbuf_valid_length); } else { + /* Enlarge the buffer */ char *new = pa_xmalloc(n); if (l->rbuf_valid_length) memcpy(new, l->rbuf+l->rbuf_index, l->rbuf_valid_length); @@ -153,37 +196,22 @@ static int do_read(struct pa_ioline *l) { } len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; - + + assert(len >= READ_SIZE); + + /* Read some data */ if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) return -1; - e = memchr(l->rbuf+l->rbuf_index+l->rbuf_valid_length, '\n', r); l->rbuf_valid_length += r; - if (!e &&l->rbuf_valid_length >= BUFFER_LIMIT) - e = l->rbuf+BUFFER_LIMIT-1; - - if (e) { - char *p; - - *e = 0; - - p = l->rbuf+l->rbuf_index; - m = strlen(p); - - l->rbuf_index += m+1; - l->rbuf_valid_length -= m+1; - - if (l->rbuf_valid_length == 0) - l->rbuf_index = 0; - - if (l->callback) - l->callback(l, p, l->userdata); - } + /* Look if a line has been terminated in the newly read data */ + scan_for_lines(l, l->rbuf_valid_length - r); return 0; } +/* Try to flush the buffer */ static int do_write(struct pa_ioline *l) { ssize_t r; assert(l); @@ -194,27 +222,26 @@ static int do_write(struct pa_ioline *l) { if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) return -1; + l->wbuf_index += r; l->wbuf_valid_length -= r; + + /* A shortcut for the next time */ if (l->wbuf_valid_length == 0) l->wbuf_index = 0; return 0; } +/* Try to flush read/write data */ static void io_callback(struct pa_iochannel*io, void *userdata) { struct pa_ioline *l = userdata; assert(io && l); - if (!l->dead && do_write(l) < 0) - goto fail; - - if (!l->dead && do_read(l) < 0) - goto fail; - - return; - -fail: - l->dead = 1; - if (l->callback) - l->callback(l, NULL, l->userdata); + if ((!l->dead && do_write(l) < 0) || + (!l->dead && do_read(l) < 0)) { + + l->dead = 1; + if (l->callback) + l->callback(l, NULL, l->userdata); + } } diff --git a/polyp/socket-server.c b/polyp/socket-server.c index 7268ccfa4..e67a9daa6 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -202,7 +202,7 @@ struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, ui pa_socket_tcp_low_delay(fd); - memset(&sa, sizeof(sa), 0); + memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(address); @@ -251,7 +251,7 @@ struct pa_socket_server* pa_socket_server_new_ipv6(struct pa_mainloop_api *m, ui pa_socket_tcp_low_delay(fd); - memset(&sa, sizeof(sa), 0); + memset(&sa, 0, sizeof(sa)); sa.sin6_family = AF_INET6; sa.sin6_port = htons(port); memcpy(sa.sin6_addr.s6_addr, address, 16); diff --git a/polyp/strbuf.c b/polyp/strbuf.c index a65216515..1aa710ea1 100644 --- a/polyp/strbuf.c +++ b/polyp/strbuf.c @@ -33,26 +33,14 @@ #include "strbuf.h" -/* Some magic for zero-length arrays */ -#ifdef __STDC_VERSION__ -#if __STDC_VERSION__ >= 199901L -#ifndef STDC99 -#define STDC99 -#endif -#endif -#endif - /* A chunk of the linked list that makes up the string */ struct chunk { struct chunk *next; size_t length; -#ifdef STDC99 - char text[]; -#else - char text[0]; -#endif }; +#define CHUNK_TO_TEXT(c) ((char*) (c) + sizeof(struct chunk)) + struct pa_strbuf { size_t length; struct chunk *head, *tail; @@ -83,17 +71,18 @@ char *pa_strbuf_tostring(struct pa_strbuf *sb) { struct chunk *c; assert(sb); - t = pa_xmalloc(sb->length+1); + e = t = pa_xmalloc(sb->length+1); - e = t; for (c = sb->head; c; c = c->next) { assert((size_t) (e-t) <= sb->length); - memcpy(e, c->text, c->length); + memcpy(e, CHUNK_TO_TEXT(c), c->length); e += c->length; } /* Trailing NUL */ *e = 0; + + assert(e == t+sb->length); return t; } @@ -140,7 +129,7 @@ void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t l) { c = pa_xmalloc(sizeof(struct chunk)+l); c->length = l; - memcpy(c->text, t, l); + memcpy(CHUNK_TO_TEXT(c), t, l); append(sb, c); } @@ -160,7 +149,7 @@ int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) { c = pa_xrealloc(c, sizeof(struct chunk)+size); va_start(ap, format); - r = vsnprintf(c->text, size, format, ap); + r = vsnprintf(CHUNK_TO_TEXT(c), size, format, ap); va_end(ap); if (r > -1 && r < size) { From ddf9970b8a2e8851bca90b4d36c0abc64631e2cf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Nov 2004 01:22:14 +0000 Subject: [PATCH 0281/1514] update todo list git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@288 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 4f760b7c9..c61cfa7bf 100644 --- a/doc/todo +++ b/doc/todo @@ -10,6 +10,7 @@ - commenting - non-fp mixing - non-fp resampling +- module-tunnel: use latency interpolation ** later *** - pass meta info for hearing impaired From a58f248ea5116bd7716da4a247c94c41957a9696 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Nov 2004 01:22:43 +0000 Subject: [PATCH 0282/1514] fix module-tunnel.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@289 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-tunnel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index 7497011d4..2b36ce273 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -255,8 +255,9 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman pa_usec_t buffer_usec, sink_usec, source_usec, transport_usec; int playing; uint32_t queue_length; + uint64_t counter; struct timeval local, remote, now; - assert(pd && u && t); + assert(pd && u); if (command != PA_COMMAND_REPLY) { if (command == PA_COMMAND_ERROR) @@ -274,6 +275,7 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman pa_tagstruct_getu32(t, &queue_length) < 0 || pa_tagstruct_get_timeval(t, &local) < 0 || pa_tagstruct_get_timeval(t, &remote) < 0 || + pa_tagstruct_getu64(t, &counter) < 0 || !pa_tagstruct_eof(t)) { pa_log(__FILE__": invalid reply.\n"); die(u); @@ -322,6 +324,7 @@ static void request_latency(struct userdata *u) { gettimeofday(&now, NULL); pa_tagstruct_put_timeval(t, &now); + pa_tagstruct_putu64(t, 0); pa_pstream_send_tagstruct(u->pstream, t); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u); From cd3a98a2ab1b8be413d50db9baa5bf52fa3a3a45 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Nov 2004 03:10:50 +0000 Subject: [PATCH 0283/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@290 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index c61cfa7bf..948ae65b1 100644 --- a/doc/todo +++ b/doc/todo @@ -11,6 +11,7 @@ - non-fp mixing - non-fp resampling - module-tunnel: use latency interpolation +- polish for starting polypaudio as root/system-wide instance ** later *** - pass meta info for hearing impaired From c57d5deef6ee33ab892398c7fd27400cd4ce4542 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Nov 2004 23:11:34 +0000 Subject: [PATCH 0284/1514] minor fixes for latency interpolation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@291 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/alsa-util.c | 1 + polyp/mainloop.c | 59 ++++++++++++++++++++++++++++++++++----- polyp/polyplib-context.c | 4 ++- polyp/polyplib-def.h | 2 +- polyp/polyplib-internal.h | 1 + polyp/polyplib-stream.c | 25 +++++++++++------ 6 files changed, 75 insertions(+), 17 deletions(-) diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index 408bc5618..188ba077f 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -23,6 +23,7 @@ #include #endif +#include #include #include "alsa-util.h" diff --git a/polyp/mainloop.c b/polyp/mainloop.c index eb2eddc2c..e13e7b11d 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -425,6 +425,9 @@ static int dispatch_defer(struct pa_mainloop *m) { struct pa_defer_event *e; int r = 0; + if (!m->deferred_pending) + return 0; + for (e = pa_idxset_first(m->defer_events, &index); e && !m->quit; e = pa_idxset_next(m->defer_events, &index)) { if (e->dead || !e->enabled) continue; @@ -516,10 +519,10 @@ static int dispatch_timeout(struct pa_mainloop *m) { int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { int r, t, dispatched = 0; assert(m && !m->running); - - m->running = 1; - if(m->quit) + m->running ++; + + if (m->quit) goto quit; scan_dead(m); @@ -534,6 +537,7 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { } t = block ? calc_next_timeout(m) : 0; + r = poll(m->pollfds, m->n_pollfds, t); if (r < 0) { @@ -555,15 +559,15 @@ int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { } } - m->running = 0; - + m->running--; + /* pa_log("dispatched: %i\n", dispatched); */ return r < 0 ? -1 : dispatched; quit: - - m->running = 0; + + m->running--; if (retval) *retval = m->retval; @@ -597,3 +601,44 @@ int pa_mainloop_deferred_pending(struct pa_mainloop *m) { assert(m); return m->deferred_pending > 0; } + + +void pa_mainloop_dump(struct pa_mainloop *m) { + assert(m); + + pa_log(__FILE__": Dumping mainloop sources START\n"); + + { + uint32_t index = PA_IDXSET_INVALID; + struct pa_io_event *e; + for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) { + if (e->dead) + continue; + + pa_log(__FILE__": kind=io fd=%i events=%i callback=%p userdata=%p\n", e->fd, (int) e->events, e->callback, e->userdata); + } + } + { + uint32_t index = PA_IDXSET_INVALID; + struct pa_defer_event *e; + for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) { + if (e->dead) + continue; + + pa_log(__FILE__": kind=defer enabled=%i callback=%p userdata=%p\n", e->enabled, e->callback, e->userdata); + } + } + { + uint32_t index = PA_IDXSET_INVALID; + struct pa_time_event *e; + for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { + if (e->dead) + continue; + + pa_log(__FILE__": kind=time enabled=%i time=%u.%u callback=%p userdata=%p\n", e->enabled, e->timeval.tv_sec, e->timeval.tv_usec, e->callback, e->userdata); + } + } + + pa_log(__FILE__": Dumping mainloop sources STOP\n"); + +} diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 15ef60b9f..704295832 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -635,7 +635,9 @@ int pa_context_is_pending(struct pa_context *c) { /* pa_log("pstream: %i\n", pa_pstream_is_pending(c->pstream)); */ /* pa_log("pdispatch: %i\n", pa_pdispatch_is_pending(c->pdispatch)); */ - return (c->pstream && pa_pstream_is_pending(c->pstream)) || (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) || c->client; + return (c->pstream && pa_pstream_is_pending(c->pstream)) || + (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) || + c->client; } static void set_dispatch_callbacks(struct pa_operation *o); diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index e2fbaea5d..44c2034bb 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -176,7 +176,7 @@ struct pa_latency_info { pa_usec_t source_usec; /**< Time in usecs a sample takes from being recorded to being delivered to the application. Only for record streams. \since 0.5*/ pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to/from the daemon. For both playback and record streams. \since 0.5 */ int playing; /**< Non-zero when the stream is currently playing. Only for playback streams. */ - uint32_t queue_length; /**< Queue size in bytes. For both playback and recrd streams. */ + uint32_t queue_length; /**< Queue size in bytes. For both playback and record streams. */ int synchronized_clocks; /**< Non-zero if the local and the * remote machine have synchronized * clocks. If synchronized clocks are diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 68ba76a93..4289b3c87 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -108,6 +108,7 @@ struct pa_stream { uint32_t ipol_usec; struct timeval ipol_timestamp; struct pa_time_event *ipol_event; + int ipol_requested; void (*state_callback)(struct pa_stream*c, void *userdata); void *state_userdata; diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 7d3d3a763..b3f1f8cd7 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -32,8 +32,9 @@ #include "xmalloc.h" #include "pstream-util.h" #include "util.h" +#include "log.h" -#define LATENCY_IPOL_INTERVAL_USEC (100000L) +#define LATENCY_IPOL_INTERVAL_USEC (10000L) struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss) { struct pa_stream *s; @@ -72,6 +73,7 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st s->ipol_usec = 0; memset(&s->ipol_timestamp, 0, sizeof(s->ipol_timestamp)); s->ipol_event = NULL; + s->ipol_requested = 0; PA_LLIST_PREPEND(struct pa_stream, c->streams, s); @@ -208,11 +210,15 @@ static void ipol_callback(struct pa_mainloop_api *m, struct pa_time_event *e, co pa_stream_ref(s); - if (s->state == PA_STREAM_READY) +/* pa_log("requesting new ipol data\n"); */ + + if (s->state == PA_STREAM_READY && !s->ipol_requested) { pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + s->ipol_requested = 1; + } gettimeofday(&tv2, NULL); - tv2.tv_usec += LATENCY_IPOL_INTERVAL_USEC; + pa_timeval_add(&tv2, LATENCY_IPOL_INTERVAL_USEC); m->time_restart(e, &tv2); @@ -426,8 +432,10 @@ static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t c } if (o->stream->interpolate) { +/* pa_log("new interpol data\n"); */ o->stream->ipol_timestamp = i.timestamp; o->stream->ipol_usec = pa_stream_get_time(o->stream, &i); + o->stream->ipol_requested = 0; } p = &i; @@ -567,10 +575,12 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); if (s->interpolate) { - if (!s->corked && b) - s->ipol_usec = pa_stream_get_interpolated_time(s); - else if (s->corked && !b) - gettimeofday(&s->ipol_timestamp, NULL); + if (!s->corked && b) + /* Pausing */ + s->ipol_usec = pa_stream_get_interpolated_time(s); + else if (s->corked && !b) + /* Unpausing */ + gettimeofday(&s->ipol_timestamp, NULL); } s->corked = b; @@ -764,6 +774,5 @@ pa_usec_t pa_stream_get_interpolated_latency(struct pa_stream *s, int *negative) t = pa_stream_get_interpolated_time(s); c = pa_bytes_to_usec(s->counter, &s->sample_spec); - return time_counter_diff(s, t, c, negative); } From eef235d8795df740eb63cb135bd187b7ab9ac4ea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Nov 2004 00:28:26 +0000 Subject: [PATCH 0285/1514] limit the number of concurrent connections for all four protocols kick a client if it doesn't authenticate within 5s on ESD and native protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@292 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/protocol-cli.c | 10 +++++++ polyp/protocol-esound.c | 60 ++++++++++++++++++++++++++++++++--------- polyp/protocol-native.c | 37 +++++++++++++++++++++++++ polyp/protocol-simple.c | 9 +++++++ 4 files changed, 104 insertions(+), 12 deletions(-) diff --git a/polyp/protocol-cli.c b/polyp/protocol-cli.c index 7ce538878..7122d23a4 100644 --- a/polyp/protocol-cli.c +++ b/polyp/protocol-cli.c @@ -29,6 +29,10 @@ #include "protocol-cli.h" #include "cli.h" #include "xmalloc.h" +#include "log.h" + +/* Don't allow more than this many concurrent connections */ +#define MAX_CONNECTIONS 10 struct pa_protocol_cli { struct pa_module *module; @@ -49,6 +53,12 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo struct pa_cli *c; assert(s && io && p); + if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { + pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_iochannel_free(io); + return; + } + c = pa_cli_new(p->core, io, p->module); assert(c); pa_cli_set_eof_callback(c, cli_eof_cb, p); diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 07c39e2a0..11a33315a 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -46,6 +46,12 @@ #include "xmalloc.h" #include "log.h" +/* Don't accept more connection than this */ +#define MAX_CONNECTIONS 10 + +/* Kick a client if it doesn't authenticate within this time */ +#define AUTH_TIMEOUT 5 + #define DEFAULT_COOKIE_FILE ".esd_auth" #define PLAYBACK_BUFFER_SECONDS (.5) @@ -87,6 +93,8 @@ struct connection { char *name; struct pa_sample_spec sample_spec; } scache; + + struct pa_time_event *auth_timeout_event; }; struct pa_protocol_esound { @@ -202,6 +210,9 @@ static void connection_free(struct connection *c) { if (c->scache.memchunk.memblock) pa_memblock_unref(c->scache.memchunk.memblock); pa_xfree(c->scache.name); + + if (c->auth_timeout_event) + c->protocol->core->mainloop->time_free(c->auth_timeout_event); pa_xfree(c); } @@ -256,6 +267,8 @@ static int esd_proto_connect(struct connection *c, esd_proto_t request, const vo } c->authorized = 1; + if (c->auth_timeout_event) + c->protocol->core->mainloop->time_free(c->auth_timeout_event); } ekey = *(uint32_t*)((uint8_t*) data+ESD_KEY_LEN); @@ -1003,25 +1016,40 @@ static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o) { /*** socket server callback ***/ +static void auth_timeout(struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata) { + struct connection *c = userdata; + assert(m && tv && c && c->auth_timeout_event == e); + + if (!c->authorized) + connection_free(c); +} + static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { struct connection *c; + struct pa_protocol_esound *p = userdata; char cname[256]; - assert(s && io && userdata); + assert(s && io && p); + if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { + pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_iochannel_free(io); + return; + } + c = pa_xmalloc(sizeof(struct connection)); - c->protocol = userdata; + c->protocol = p; c->io = io; pa_iochannel_set_callback(c->io, io_callback, c); pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); - assert(c->protocol->core); - c->client = pa_client_new(c->protocol->core, "ESOUND", cname); + assert(p->core); + c->client = pa_client_new(p->core, "ESOUND", cname); assert(c->client); - c->client->owner = c->protocol->module; + c->client->owner = p->module; c->client->kill = client_kill_cb; c->client->userdata = c; - c->authorized = c->protocol->public; + c->authorized = p->public; c->swap_byte_order = 0; c->dead = 0; @@ -1047,19 +1075,27 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->scache.memchunk.length = c->scache.memchunk.index = 0; c->scache.memchunk.memblock = NULL; c->scache.name = NULL; - - c->defer_event = c->protocol->core->mainloop->defer_new(c->protocol->core->mainloop, defer_callback, c); - assert(c->defer_event); - c->protocol->core->mainloop->defer_enable(c->defer_event, 0); - pa_idxset_put(c->protocol->connections, c, &c->index); + if (!c->authorized) { + struct timeval tv; + gettimeofday(&tv, NULL); + tv.tv_sec += AUTH_TIMEOUT; + c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c); + } else + c->auth_timeout_event = NULL; + + c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c); + assert(c->defer_event); + p->core->mainloop->defer_enable(c->defer_event, 0); + + pa_idxset_put(p->connections, c, &c->index); } /*** entry points ***/ struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { struct pa_protocol_esound *p; - int public; + int public = 0; assert(core && server && ma); p = pa_xmalloc(sizeof(struct pa_protocol_esound)); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 02d81db3e..12ecfae14 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -50,6 +50,12 @@ #include "strlist.h" #include "props.h" +/* Kick a client if it doesn't authenticate within this time */ +#define AUTH_TIMEOUT 5 + +/* Don't accept more connection than this */ +#define MAX_CONNECTIONS 10 + struct connection; struct pa_protocol_native; @@ -100,6 +106,7 @@ struct connection { struct pa_idxset *record_streams, *output_streams; uint32_t rrobin_index; struct pa_subscription *subscription; + struct pa_time_event *auth_timeout_event; }; struct pa_protocol_native { @@ -374,6 +381,9 @@ static void connection_free(struct connection *c) { if (c->subscription) pa_subscription_free(c->subscription); + + if (c->auth_timeout_event) + c->protocol->core->mainloop->time_free(c->auth_timeout_event); pa_xfree(c); } @@ -746,6 +756,10 @@ static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag } c->authorized = 1; + if (c->auth_timeout_event) { + c->protocol->core->mainloop->time_free(c->auth_timeout_event); + c->auth_timeout_event = NULL; + } } pa_pstream_send_simple_ack(c->pstream, tag); @@ -1973,14 +1987,37 @@ static void client_kill_cb(struct pa_client *c) { /*** socket server callbacks ***/ +static void auth_timeout(struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata) { + struct connection *c = userdata; + assert(m && tv && c && c->auth_timeout_event == e); + + if (!c->authorized) + connection_free(c); +} + static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { struct pa_protocol_native *p = userdata; struct connection *c; assert(io && p); + if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { + pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_iochannel_free(io); + return; + } + c = pa_xmalloc(sizeof(struct connection)); c->authorized =!! p->public; + + if (!c->authorized) { + struct timeval tv; + gettimeofday(&tv, NULL); + tv.tv_sec += AUTH_TIMEOUT; + c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c); + } else + c->auth_timeout_event = NULL; + c->protocol = p; assert(p->core); c->client = pa_client_new(p->core, "NATIVE", "Client"); diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index f7c69d6b4..058d4b828 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -39,6 +39,9 @@ #include "xmalloc.h" #include "log.h" +/* Don't allow more than this many concurrent connections */ +#define MAX_CONNECTIONS 10 + struct connection { struct pa_protocol_simple *protocol; struct pa_iochannel *io; @@ -287,6 +290,12 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo char cname[256]; assert(s && io && p); + if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { + pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_iochannel_free(io); + return; + } + c = pa_xmalloc(sizeof(struct connection)); c->io = io; c->sink_input = NULL; From 8641af3c6d11e3e6710cb946e9a93d0e9f639519 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Nov 2004 20:50:44 +0000 Subject: [PATCH 0286/1514] * some iochannel fixes * introduce reference counting in ioline * fix memory leak in socket-client.c * fix double-free error in protocol-esound.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@293 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 3 +- polyp/cli.c | 3 +- polyp/iochannel.c | 5 + polyp/iochannel.h | 2 + polyp/ioline.c | 261 +++++++++++++++++++++++++--------------- polyp/ioline.h | 4 +- polyp/mainloop.c | 3 +- polyp/protocol-esound.c | 73 ++++++----- polyp/protocol-simple.c | 6 +- polyp/pstream.c | 19 ++- polyp/socket-client.c | 6 +- 11 files changed, 240 insertions(+), 145 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 506cdc34a..a782685a1 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -215,8 +215,7 @@ polypaudio_SOURCES = idxset.c idxset.h \ polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) -polypaudio_LDFLAGS= -export-dynamic -dlopen force -# -static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f)) +polypaudio_LDFLAGS= -export-dynamic -dlopen force #-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f)) libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version diff --git a/polyp/cli.c b/polyp/cli.c index 2ff359922..7780d03d8 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -92,7 +92,8 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct void pa_cli_free(struct pa_cli *c) { assert(c); - pa_ioline_free(c->line); + pa_ioline_close(c->line); + pa_ioline_unref(c->line); pa_client_free(c->client); pa_xfree(c); } diff --git a/polyp/iochannel.c b/polyp/iochannel.c index f174afd0b..0e7e8db80 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -235,3 +235,8 @@ int pa_iochannel_socket_set_sndbuf(struct pa_iochannel *io, size_t l) { return pa_socket_set_sndbuf(io->ofd, l); } + +struct pa_mainloop_api* pa_iochannel_get_mainloop_api(struct pa_iochannel *io) { + assert(io); + return io->mainloop; +} diff --git a/polyp/iochannel.h b/polyp/iochannel.h index 79600f72d..f8efc9288 100644 --- a/polyp/iochannel.h +++ b/polyp/iochannel.h @@ -47,4 +47,6 @@ void pa_iochannel_socket_peer_to_string(struct pa_iochannel*io, char*s, size_t l int pa_iochannel_socket_set_rcvbuf(struct pa_iochannel*io, size_t l); int pa_iochannel_socket_set_sndbuf(struct pa_iochannel*io, size_t l); +struct pa_mainloop_api* pa_iochannel_get_mainloop_api(struct pa_iochannel *io); + #endif diff --git a/polyp/ioline.c b/polyp/ioline.c index f3d17b586..059591b85 100644 --- a/polyp/ioline.c +++ b/polyp/ioline.c @@ -31,12 +31,16 @@ #include "ioline.h" #include "xmalloc.h" +#include "log.h" #define BUFFER_LIMIT (64*1024) #define READ_SIZE (1024) struct pa_ioline { struct pa_iochannel *io; + struct pa_defer_event *defer_event; + struct pa_mainloop_api *mainloop; + int ref; int dead; char *wbuf; @@ -50,7 +54,7 @@ struct pa_ioline { }; static void io_callback(struct pa_iochannel*io, void *userdata); -static int do_write(struct pa_ioline *l); +static void defer_callback(struct pa_mainloop_api*m, struct pa_defer_event*e, void *userdata); struct pa_ioline* pa_ioline_new(struct pa_iochannel *io) { struct pa_ioline *l; @@ -68,68 +72,112 @@ struct pa_ioline* pa_ioline_new(struct pa_iochannel *io) { l->callback = NULL; l->userdata = NULL; + l->ref = 1; + l->mainloop = pa_iochannel_get_mainloop_api(io); + + l->defer_event = l->mainloop->defer_new(l->mainloop, defer_callback, l); + l->mainloop->defer_enable(l->defer_event, 0); + pa_iochannel_set_callback(io, io_callback, l); return l; } -void pa_ioline_free(struct pa_ioline *l) { +static void ioline_free(struct pa_ioline *l) { assert(l); - pa_iochannel_free(l->io); + + if (l->io) + pa_iochannel_free(l->io); pa_xfree(l->wbuf); pa_xfree(l->rbuf); pa_xfree(l); } +void pa_ioline_unref(struct pa_ioline *l) { + assert(l && l->ref >= 1); + + if ((--l->ref) <= 0) + ioline_free(l); +} + +struct pa_ioline* pa_ioline_ref(struct pa_ioline *l) { + assert(l && l->ref >= 1); + + l->ref++; + return l; +} + +void pa_ioline_close(struct pa_ioline *l) { + assert(l && l->ref >= 1); + + l->dead = 1; + if (l->io) { + pa_iochannel_free(l->io); + l->io = NULL; + } +} + void pa_ioline_puts(struct pa_ioline *l, const char *c) { size_t len; - assert(l && c); + assert(l && c && l->ref >= 1 && !l->dead); + + pa_ioline_ref(l); len = strlen(c); if (len > BUFFER_LIMIT - l->wbuf_valid_length) len = BUFFER_LIMIT - l->wbuf_valid_length; - if (!len) - return; - - assert(l->wbuf_length >= l->wbuf_valid_length); - - /* In case the allocated buffer is too small, enlarge it. */ - if (l->wbuf_valid_length + len > l->wbuf_length) { - size_t n = l->wbuf_valid_length+len; - char *new = pa_xmalloc(n); - if (l->wbuf) { - memcpy(new, l->wbuf+l->wbuf_index, l->wbuf_valid_length); - pa_xfree(l->wbuf); + if (len) { + assert(l->wbuf_length >= l->wbuf_valid_length); + + /* In case the allocated buffer is too small, enlarge it. */ + if (l->wbuf_valid_length + len > l->wbuf_length) { + size_t n = l->wbuf_valid_length+len; + char *new = pa_xmalloc(n); + if (l->wbuf) { + memcpy(new, l->wbuf+l->wbuf_index, l->wbuf_valid_length); + pa_xfree(l->wbuf); + } + l->wbuf = new; + l->wbuf_length = n; + l->wbuf_index = 0; + } else if (l->wbuf_index + l->wbuf_valid_length + len > l->wbuf_length) { + + /* In case the allocated buffer fits, but the current index is too far from the start, move it to the front. */ + memmove(l->wbuf, l->wbuf+l->wbuf_index, l->wbuf_valid_length); + l->wbuf_index = 0; } - l->wbuf = new; - l->wbuf_length = n; - l->wbuf_index = 0; - } else if (l->wbuf_index + l->wbuf_valid_length + len > l->wbuf_length) { + + assert(l->wbuf_index + l->wbuf_valid_length + len <= l->wbuf_length); + + /* Append the new string */ + memcpy(l->wbuf + l->wbuf_index + l->wbuf_valid_length, c, len); + l->wbuf_valid_length += len; - /* In case the allocated buffer fits, but the current index is too far from the start, move it to the front. */ - memmove(l->wbuf, l->wbuf+l->wbuf_index, l->wbuf_valid_length); - l->wbuf_index = 0; + l->mainloop->defer_enable(l->defer_event, 1); } - assert(l->wbuf_index + l->wbuf_valid_length + len <= l->wbuf_length); - - /* Append the new string */ - memcpy(l->wbuf + l->wbuf_index + l->wbuf_valid_length, c, len); - l->wbuf_valid_length += len; - - do_write(l); + pa_ioline_unref(l); } void pa_ioline_set_callback(struct pa_ioline*l, void (*callback)(struct pa_ioline*io, const char *s, void *userdata), void *userdata) { - assert(l); + assert(l && l->ref >= 1); l->callback = callback; l->userdata = userdata; } +static void failure(struct pa_ioline *l) { + assert(l && l->ref >= 1 && !l->dead); + + pa_ioline_close(l); + + if (l->callback) + l->callback(l, NULL, l->userdata); +} + static void scan_for_lines(struct pa_ioline *l, size_t skip) { - assert(l && skip < l->rbuf_valid_length); + assert(l && l->ref >= 1 && skip < l->rbuf_valid_length); while (!l->dead && l->rbuf_valid_length > skip) { char *e, *p; @@ -162,86 +210,109 @@ static void scan_for_lines(struct pa_ioline *l, size_t skip) { } static int do_read(struct pa_ioline *l) { - ssize_t r; - size_t len; - assert(l); + assert(l && l->ref >= 1); - if (!pa_iochannel_is_readable(l->io)) - return 0; + while (!l->dead && pa_iochannel_is_readable(l->io)) { + ssize_t r; + size_t len; - len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; - - /* Check if we have to enlarge the read buffer */ - if (len < READ_SIZE) { - size_t n = l->rbuf_valid_length+READ_SIZE; - - if (n >= BUFFER_LIMIT) - n = BUFFER_LIMIT; + len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; - if (l->rbuf_length >= n) { - /* The current buffer is large enough, let's just move the data to the front */ - if (l->rbuf_valid_length) - memmove(l->rbuf, l->rbuf+l->rbuf_index, l->rbuf_valid_length); - } else { - /* Enlarge the buffer */ - char *new = pa_xmalloc(n); - if (l->rbuf_valid_length) - memcpy(new, l->rbuf+l->rbuf_index, l->rbuf_valid_length); - pa_xfree(l->rbuf); - l->rbuf = new; - l->rbuf_length = n; + /* Check if we have to enlarge the read buffer */ + if (len < READ_SIZE) { + size_t n = l->rbuf_valid_length+READ_SIZE; + + if (n >= BUFFER_LIMIT) + n = BUFFER_LIMIT; + + if (l->rbuf_length >= n) { + /* The current buffer is large enough, let's just move the data to the front */ + if (l->rbuf_valid_length) + memmove(l->rbuf, l->rbuf+l->rbuf_index, l->rbuf_valid_length); + } else { + /* Enlarge the buffer */ + char *new = pa_xmalloc(n); + if (l->rbuf_valid_length) + memcpy(new, l->rbuf+l->rbuf_index, l->rbuf_valid_length); + pa_xfree(l->rbuf); + l->rbuf = new; + l->rbuf_length = n; + } + + l->rbuf_index = 0; } - l->rbuf_index = 0; + len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; + + assert(len >= READ_SIZE); + + /* Read some data */ + if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) { + pa_log(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + failure(l); + return -1; + } + + l->rbuf_valid_length += r; + + /* Look if a line has been terminated in the newly read data */ + scan_for_lines(l, l->rbuf_valid_length - r); } - - len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; - - assert(len >= READ_SIZE); - - /* Read some data */ - if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) - return -1; - - l->rbuf_valid_length += r; - - /* Look if a line has been terminated in the newly read data */ - scan_for_lines(l, l->rbuf_valid_length - r); - + return 0; } /* Try to flush the buffer */ static int do_write(struct pa_ioline *l) { ssize_t r; - assert(l); - - if (!l->wbuf_valid_length || !pa_iochannel_is_writable(l->io)) - return 0; - - if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) - return -1; - - l->wbuf_index += r; - l->wbuf_valid_length -= r; - - /* A shortcut for the next time */ - if (l->wbuf_valid_length == 0) - l->wbuf_index = 0; + assert(l && l->ref >= 1); + while (!l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length) { + + if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) { + pa_log(__FILE__": write() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + failure(l); + return -1; + } + + l->wbuf_index += r; + l->wbuf_valid_length -= r; + + /* A shortcut for the next time */ + if (l->wbuf_valid_length == 0) + l->wbuf_index = 0; + } + return 0; } /* Try to flush read/write data */ +static void do_work(struct pa_ioline *l) { + assert(l && l->ref >= 1); + + pa_ioline_ref(l); + + l->mainloop->defer_enable(l->defer_event, 0); + + if (!l->dead) + do_write(l); + + if (!l->dead) + do_read(l); + + pa_ioline_unref(l); +} + static void io_callback(struct pa_iochannel*io, void *userdata) { struct pa_ioline *l = userdata; - assert(io && l); - - if ((!l->dead && do_write(l) < 0) || - (!l->dead && do_read(l) < 0)) { - - l->dead = 1; - if (l->callback) - l->callback(l, NULL, l->userdata); - } + assert(io && l && l->ref >= 1); + + do_work(l); +} + +static void defer_callback(struct pa_mainloop_api*m, struct pa_defer_event*e, void *userdata) { + struct pa_ioline *l = userdata; + assert(l && l->ref >= 1 && l->mainloop == m && l->defer_event == e); + + do_work(l); } diff --git a/polyp/ioline.h b/polyp/ioline.h index c6150d4b5..5adc0560f 100644 --- a/polyp/ioline.h +++ b/polyp/ioline.h @@ -27,7 +27,9 @@ struct pa_ioline; struct pa_ioline* pa_ioline_new(struct pa_iochannel *io); -void pa_ioline_free(struct pa_ioline *l); +void pa_ioline_unref(struct pa_ioline *l); +struct pa_ioline* pa_ioline_ref(struct pa_ioline *l); +void pa_ioline_close(struct pa_ioline *l); void pa_ioline_puts(struct pa_ioline *s, const char *c); void pa_ioline_set_callback(struct pa_ioline*io, void (*callback)(struct pa_ioline*io, const char *s, void *userdata), void *userdata); diff --git a/polyp/mainloop.c b/polyp/mainloop.c index e13e7b11d..f56614cec 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -116,8 +116,7 @@ static void mainloop_io_enable(struct pa_io_event *e, enum pa_io_event_flags eve e->pollfd->events = (events & PA_IO_EVENT_INPUT ? POLLIN : 0) | (events & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | - POLLHUP | - POLLERR; + POLLERR | POLLHUP; } static void mainloop_io_free(struct pa_io_event *e) { diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 11a33315a..a32a9bd87 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -267,8 +267,10 @@ static int esd_proto_connect(struct connection *c, esd_proto_t request, const vo } c->authorized = 1; - if (c->auth_timeout_event) + if (c->auth_timeout_event) { c->protocol->core->mainloop->time_free(c->auth_timeout_event); + c->auth_timeout_event = NULL; + } } ekey = *(uint32_t*)((uint8_t*) data+ESD_KEY_LEN); @@ -301,11 +303,13 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons ss.rate = rate; format_esd2native(format, &ss); - if (!pa_sample_spec_valid(&ss)) + if (!pa_sample_spec_valid(&ss)) { + pa_log(__FILE__": invalid sample specification\n"); return -1; + } if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": No output sink\n"); + pa_log(__FILE__": no such sink\n"); return -1; } @@ -314,17 +318,17 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons pa_client_set_name(c->client, name); - assert(!c->input_memblockq); + assert(!c->sink_input && !c->input_memblockq); + + if (!(c->sink_input = pa_sink_input_new(sink, name, &ss, 0, -1))) { + pa_log(__FILE__": failed to create sink input.\n"); + return -1; + } l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); c->input_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&ss), l/2, l/PLAYBACK_BUFFER_FRAGMENTS, c->protocol->core->memblock_stat); - assert(c->input_memblockq); pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2); c->playback.fragment_size = l/10; - - assert(!c->sink_input); - c->sink_input = pa_sink_input_new(sink, name, &ss, 0, -1); - assert(c->sink_input); c->sink_input->owner = c->protocol->module; c->sink_input->client = c->client; @@ -355,22 +359,30 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co ss.rate = rate; format_esd2native(format, &ss); - if (!pa_sample_spec_valid(&ss)) + if (!pa_sample_spec_valid(&ss)) { + pa_log(__FILE__": invalid sample specification.\n"); return -1; + } if (request == ESD_PROTO_STREAM_MON) { struct pa_sink* sink; - if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) + if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { + pa_log(__FILE__": no such sink.\n"); return -1; + } - if (!(source = sink->monitor_source)) + if (!(source = sink->monitor_source)) { + pa_log(__FILE__": no such monitor source.\n"); return -1; + } } else { assert(request == ESD_PROTO_STREAM_REC); - if (!(source = pa_namereg_get(c->protocol->core, c->protocol->source_name, PA_NAMEREG_SOURCE, 1))) + if (!(source = pa_namereg_get(c->protocol->core, c->protocol->source_name, PA_NAMEREG_SOURCE, 1))) { + pa_log(__FILE__": no such source.\n"); return -1; + } } strncpy(name, (char*) data + sizeof(int)*2, sizeof(name)); @@ -378,17 +390,17 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co pa_client_set_name(c->client, name); - assert(!c->output_memblockq); + assert(!c->output_memblockq && !c->source_output); + + if (!(c->source_output = pa_source_output_new(source, name, &ss, -1))) { + pa_log(__FILE__": failed to create source output\n"); + return -1; + } l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS); c->output_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&ss), 0, 0, c->protocol->core->memblock_stat); - assert(c->output_memblockq); pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2); - assert(!c->source_output); - c->source_output = pa_source_output_new(source, name, &ss, -1); - assert(c->source_output); - c->source_output->owner = c->protocol->module; c->source_output->client = c->client; c->source_output->push = source_output_push_cb; @@ -829,8 +841,8 @@ static int do_read(struct connection *c) { pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } - -/* pa_log(__FILE__": read %u\n", r); */ + +/* pa_log(__FILE__": read %u\n", r); */ chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; @@ -880,7 +892,7 @@ static int do_write(struct connection *c) { pa_log(__FILE__": write(): %s\n", strerror(errno)); return -1; } - + pa_memblockq_drop(c->output_memblockq, &chunk, r); pa_memblock_unref(chunk.memblock); } @@ -894,18 +906,21 @@ static void do_work(struct connection *c) { assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 0); -/* pa_log("DOWORK\n"); */ - - if (c->dead || !c->io) - return; +/* pa_log("DOWORK %i\n", pa_iochannel_is_hungup(c->io)); */ - if (pa_iochannel_is_readable(c->io)) + if (!c->dead && pa_iochannel_is_readable(c->io)) if (do_read(c) < 0) goto fail; - - if (pa_iochannel_is_writable(c->io)) + + if (!c->dead && pa_iochannel_is_writable(c->io)) if (do_write(c) < 0) goto fail; + + /* In case the line was hungup, make sure to rerun this function + as soon as possible, until all data has been read. */ + + if (!c->dead && pa_iochannel_is_hungup(c->io)) + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); return; diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 058d4b828..3dddc4747 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -180,9 +180,6 @@ static void do_work(struct connection *c) { assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 0); - if (pa_iochannel_is_hungup(c->io)) - goto fail; - if (pa_iochannel_is_writable(c->io)) if (do_write(c) < 0) goto fail; @@ -191,6 +188,9 @@ static void do_work(struct connection *c) { if (do_read(c) < 0) goto fail; + if (pa_iochannel_is_hungup(c->io)) + c->protocol->core->mainloop->defer_enable(c->defer_event, 1); + return; fail: diff --git a/polyp/pstream.c b/polyp/pstream.c index 11ca3963b..c081c2424 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -103,25 +103,22 @@ static void do_read(struct pa_pstream *p); static void do_something(struct pa_pstream *p) { assert(p); - if (p->dead) - return; - p->mainloop->defer_enable(p->defer_event, 0); pa_pstream_ref(p); - if (!p->dead && pa_iochannel_is_hungup(p->io)) { - p->dead = 1; - if (p->die_callback) - p->die_callback(p, p->die_callback_userdata); - } + if (!p->dead && pa_iochannel_is_readable(p->io)) + do_read(p); if (!p->dead && pa_iochannel_is_writable(p->io)) do_write(p); - if (!p->dead && pa_iochannel_is_readable(p->io)) - do_read(p); - + /* In case the line was hungup, make sure to rerun this function + as soon as possible, until all data has been read. */ + + if (!p->dead && pa_iochannel_is_hungup(p->io)) + p->mainloop->defer_enable(p->defer_event, 1); + pa_pstream_unref(p); } diff --git a/polyp/socket-client.c b/polyp/socket-client.c index aea385867..c58c7bd45 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -330,6 +330,7 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, case KIND_TCP6: { uint16_t port = default_port; char *h; + int ret; struct addrinfo hints, *res; if (!(h = parse_address(p, &port))) @@ -338,7 +339,10 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, memset(&hints, 0, sizeof(hints)); hints.ai_family = kind == KIND_TCP4 ? AF_INET : (kind == KIND_TCP6 ? AF_INET6 : AF_UNSPEC); - if (getaddrinfo(h, NULL, &hints, &res) < 0 || !res || !res->ai_addr) + ret = getaddrinfo(h, NULL, &hints, &res); + pa_xfree(h); + + if (ret < 0 || !res || !res->ai_addr) return NULL; if (res->ai_family == AF_INET) { From 5f647c8fef33f35210d550ad1477ef43520b32a3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 20 Nov 2004 16:23:53 +0000 Subject: [PATCH 0287/1514] =?UTF-8?q?*=20add=20=C2=B5law/alaw=20support=20?= =?UTF-8?q?*=20abstracted=20resampler=20API=20*=20add=20integer-only=20res?= =?UTF-8?q?ampler=20("trivial")=20*=20show=20used=20resampler=20wherever?= =?UTF-8?q?=20useful=20*=20add=20mixing/volume=20adjusting=20for=20float32?= =?UTF-8?q?ne=20and=20u8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@294 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 - polyp/Makefile.am | 3 +- polyp/cli-text.c | 20 +- polyp/core.c | 3 +- polyp/core.h | 3 +- polyp/daemon-conf.c | 14 +- polyp/g711.c | 2531 +++++++++++++++++++++++++++++++++++ polyp/g711.h | 40 + polyp/pactl.c | 12 +- polyp/polyplib-introspect.c | 6 +- polyp/polyplib-introspect.h | 2 + polyp/protocol-native.c | 2 + polyp/pstream-util.c | 3 +- polyp/resampler.c | 345 ++++- polyp/resampler.h | 26 + polyp/sample-util.c | 221 ++- polyp/sconv-s16be.c | 4 +- polyp/sconv-s16be.h | 4 +- polyp/sconv-s16le.c | 4 +- polyp/sconv-s16le.h | 4 +- polyp/sconv.c | 128 +- polyp/sconv.h | 8 +- polyp/sink-input.c | 11 +- polyp/sink-input.h | 2 + polyp/source-output.c | 11 +- polyp/source-output.h | 1 + polyp/util.c | 17 - polyp/util.h | 2 - 28 files changed, 3237 insertions(+), 192 deletions(-) create mode 100644 polyp/g711.c create mode 100644 polyp/g711.h diff --git a/doc/todo b/doc/todo index 948ae65b1..9898bc9df 100644 --- a/doc/todo +++ b/doc/todo @@ -8,8 +8,6 @@ - make most buffer sizes dependant on the sample type - limit all resources - commenting -- non-fp mixing -- non-fp resampling - module-tunnel: use latency interpolation - polish for starting polypaudio as root/system-wide instance diff --git a/polyp/Makefile.am b/polyp/Makefile.am index a782685a1..dd7fb8b43 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -210,7 +210,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ conf-parser.h conf-parser.c \ caps.h caps.c \ props.h props.c \ - mcalign.c mcalign.h + mcalign.c mcalign.h \ + g711.c g711.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 7974275a5..629b28e25 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -162,15 +162,21 @@ char *pa_source_output_list_to_string(struct pa_core *c) { for (o = pa_idxset_first(c->source_outputs, &index); o; o = pa_idxset_next(c->source_outputs, &index)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; + const char *rm; pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec); assert(o->source); + + if (!(rm = pa_resample_method_to_string(pa_source_output_get_resample_method(o)))) + rm = "invalid"; + pa_strbuf_printf( - s, " index: %u\n\tname: '%s'\n\tstate: %s\n\tsource: <%u> '%s'\n\tsample_spec: <%s>\n", + s, " index: %u\n\tname: '%s'\n\tstate: %s\n\tsource: <%u> '%s'\n\tsample_spec: <%s>\n\tresample method: %s\n", o->index, o->name, state_table[o->state], o->source->index, o->source->name, - ss); + ss, + rm); if (o->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", o->owner->index); if (o->client) @@ -198,10 +204,15 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { for (i = pa_idxset_first(c->sink_inputs, &index); i; i = pa_idxset_next(c->sink_inputs, &index)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; + const char *rm; + + if (!(rm = pa_resample_method_to_string(pa_sink_input_get_resample_method(i)))) + rm = "invalid"; + pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\tstate: %s\n\tsink: <%u> '%s'\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n", + s, " index: %u\n\tname: <%s>\n\tstate: %s\n\tsink: <%u> '%s'\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n\tresample method: %s\n", i->index, i->name, state_table[i->state], @@ -209,7 +220,8 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { (unsigned) i->volume, pa_volume_to_dB(i->volume), (float) pa_sink_input_get_latency(i), - ss); + ss, + rm); if (i->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", i->owner->index); diff --git a/polyp/core.c b/polyp/core.c index 19e0425fb..03682fdc5 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "core.h" #include "module.h" @@ -82,7 +81,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->module_idle_time = 20; c->scache_idle_time = 20; - c->resample_method = SRC_SINC_FASTEST; + c->resample_method = PA_RESAMPLER_SRC_SINC_FASTEST; pa_property_init(c); diff --git a/polyp/core.h b/polyp/core.h index 799661aff..09e58b467 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -27,6 +27,7 @@ #include "mainloop-api.h" #include "sample.h" #include "memblock.h" +#include "resampler.h" struct pa_core { struct pa_mainloop_api *mainloop; @@ -54,7 +55,7 @@ struct pa_core { struct pa_time_event *scache_auto_unload_event; - int resample_method; + enum pa_resample_method resample_method; }; struct pa_core* pa_core_new(struct pa_mainloop_api *m); diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index c0ff02f9f..191e8d81e 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -28,13 +28,13 @@ #include #include #include -#include #include "daemon-conf.h" #include "util.h" #include "xmalloc.h" #include "strbuf.h" #include "conf-parser.h" +#include "resampler.h" #ifndef DEFAULT_CONFIG_DIR #define DEFAULT_CONFIG_DIR "/etc/polypaudio" @@ -64,7 +64,7 @@ static const struct pa_daemon_conf default_conf = { .dl_search_path = NULL, .default_script_file = NULL, .log_target = PA_LOG_SYSLOG, - .resample_method = SRC_SINC_FASTEST, + .resample_method = PA_RESAMPLER_SRC_SINC_FASTEST, .config_file = NULL, }; @@ -214,14 +214,6 @@ int pa_daemon_conf_env(struct pa_daemon_conf *c) { char *pa_daemon_conf_dump(struct pa_daemon_conf *c) { struct pa_strbuf *s = pa_strbuf_new(); - static const char const* resample_methods[] = { - "sinc-best-quality", - "sinc-medium-quality", - "sinc-fastest", - "zero-order-hold", - "linear" - }; - if (c->config_file) pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file); @@ -238,7 +230,7 @@ char *pa_daemon_conf_dump(struct pa_daemon_conf *c) { pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); assert(c->resample_method <= 4 && c->resample_method >= 0); - pa_strbuf_printf(s, "resample-method = %s\n", resample_methods[c->resample_method]); + pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); return pa_strbuf_tostring_free(s); } diff --git a/polyp/g711.c b/polyp/g711.c new file mode 100644 index 000000000..55a82396c --- /dev/null +++ b/polyp/g711.c @@ -0,0 +1,2531 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g711.c + * + * u-law, A-law and linear PCM conversions. + */ + +/* + * December 30, 1994: + * Functions linear2alaw, linear2ulaw have been updated to correctly + * convert unquantized 16 bit values. + * Tables for direct u- to A-law and A- to u-law conversions have been + * corrected. + * Borge Lindberg, Center for PersonKommunikation, Aalborg University. + * bli@cpk.auc.dk + * + */ + +#include "g711.h" + +#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ +#define SEG_MASK (0x70) /* Segment field mask. */ + +#if !defined(FAST_ALAW_CONVERSION) || !defined(FAST_ULAW_CONVERSION) +static int16_t seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF, + 0x1FF, 0x3FF, 0x7FF, 0xFFF}; +static int16_t seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, + 0x3FF, 0x7FF, 0xFFF, 0x1FFF}; + +static int16_t search( + int16_t val, + int16_t *table, + int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (val <= *table++) + return (i); + } + return (size); +} +#endif /* !FAST_*_CONVERSION */ + +#ifndef FAST_ALAW_CONVERSION +/* + * linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data + * stored in a unsigned char. This function should only be called with + * the data shifted such that it only contains information in the lower + * 13-bits. + * + * Linear Input Code Compressed Code + * ------------------------ --------------- + * 0000000wxyza 000wxyz + * 0000001wxyza 001wxyz + * 000001wxyzab 010wxyz + * 00001wxyzabc 011wxyz + * 0001wxyzabcd 100wxyz + * 001wxyzabcde 101wxyz + * 01wxyzabcdef 110wxyz + * 1wxyzabcdefg 111wxyz + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +unsigned char st_13linear2alaw( + int16_t pcm_val) /* 2's complement (13-bit range) */ +{ + int16_t mask; + short seg; + unsigned char aval; + + /* Have calling software do it since its already doing a shift + * from 32-bits down to 16-bits. + */ + /* pcm_val = pcm_val >> 3; */ + + /* A-law using even bit inversion */ + if (pcm_val >= 0) { + mask = 0xD5; /* sign (7th) bit = 1 */ + } else { + mask = 0x55; /* sign bit = 0 */ + pcm_val = -pcm_val - 1; + } + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_aend, 8); + + /* Combine the sign, segment, and quantization bits. */ + + if (seg >= 8) /* out of range, return maximum value. */ + return (unsigned char) (0x7F ^ mask); + else { + aval = (unsigned char) seg << SEG_SHIFT; + if (seg < 2) + aval |= (pcm_val >> 1) & QUANT_MASK; + else + aval |= (pcm_val >> seg) & QUANT_MASK; + return (aval ^ mask); + } +} + +/* + * alaw2linear() - Convert an A-law value to 16-bit signed linear PCM + * + */ +int16_t st_alaw2linear16( + unsigned char a_val) +{ + int16_t t; + int16_t seg; + + a_val ^= 0x55; + + t = (a_val & QUANT_MASK) << 4; + seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; + switch (seg) { + case 0: + t += 8; + break; + case 1: + t += 0x108; + break; + default: + t += 0x108; + t <<= seg - 1; + } + return ((a_val & SIGN_BIT) ? t : -t); +} +#endif /* !FAST_ALAW_CONVERSION */ + +#define BIAS (0x84) /* Bias for linear code. */ +#define CLIP 8159 + +#ifndef FAST_ULAW_CONVERSION +/* + * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data + * stored in a unsigned char. This function should only be called with + * the data shifted such that it only contains information in the lower + * 14-bits. + * + * In order to simplify the encoding process, the original linear magnitude + * is biased by adding 33 which shifts the encoding range from (0 - 8158) to + * (33 - 8191). The result can be seen in the following encoding table: + * + * Biased Linear Input Code Compressed Code + * ------------------------ --------------- + * 00000001wxyza 000wxyz + * 0000001wxyzab 001wxyz + * 000001wxyzabc 010wxyz + * 00001wxyzabcd 011wxyz + * 0001wxyzabcde 100wxyz + * 001wxyzabcdef 101wxyz + * 01wxyzabcdefg 110wxyz + * 1wxyzabcdefgh 111wxyz + * + * Each biased linear code has a leading 1 which identifies the segment + * number. The value of the segment number is equal to 7 minus the number + * of leading 0's. The quantization interval is directly available as the + * four bits wxyz. * The trailing bits (a - h) are ignored. + * + * Ordinarily the complement of the resulting code word is used for + * transmission, and so the code word is complemented before it is returned. + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +unsigned char st_14linear2ulaw( + int16_t pcm_val) /* 2's complement (14-bit range) */ +{ + int16_t mask; + int16_t seg; + unsigned char uval; + + /* Have calling software do it since its already doing a shift + * from 32-bits down to 16-bits. + */ + /* pcm_val = pcm_val >> 2; */ + + /* u-law inverts all bits */ + /* Get the sign and the magnitude of the value. */ + if (pcm_val < 0) { + pcm_val = -pcm_val; + mask = 0x7F; + } else { + mask = 0xFF; + } + if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */ + pcm_val += (BIAS >> 2); + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_uend, 8); + + /* + * Combine the sign, segment, quantization bits; + * and complement the code word. + */ + if (seg >= 8) /* out of range, return maximum value. */ + return (unsigned char) (0x7F ^ mask); + else { + uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF); + return (uval ^ mask); + } + +} + +/* + * ulaw2linear() - Convert a u-law value to 16-bit linear PCM + * + * First, a biased linear code is derived from the code word. An unbiased + * output can then be obtained by subtracting 33 from the biased code. + * + * Note that this function expects to be passed the complement of the + * original code word. This is in keeping with ISDN conventions. + */ +int16_t st_ulaw2linear16( + unsigned char u_val) +{ + int16_t t; + + /* Complement to obtain normal u-law value. */ + u_val = ~u_val; + + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = ((u_val & QUANT_MASK) << 3) + BIAS; + t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; + + return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); +} +#endif /* !FAST_ULAW_CONVERSION */ + +#ifdef FAST_ALAW_CONVERSION + +int16_t _st_alaw2linear16[256] = { + -5504, -5248, -6016, -5760, -4480, -4224, -4992, + -4736, -7552, -7296, -8064, -7808, -6528, -6272, + -7040, -6784, -2752, -2624, -3008, -2880, -2240, + -2112, -2496, -2368, -3776, -3648, -4032, -3904, + -3264, -3136, -3520, -3392, -22016, -20992, -24064, + -23040, -17920, -16896, -19968, -18944, -30208, -29184, + -32256, -31232, -26112, -25088, -28160, -27136, -11008, + -10496, -12032, -11520, -8960, -8448, -9984, -9472, + -15104, -14592, -16128, -15616, -13056, -12544, -14080, + -13568, -344, -328, -376, -360, -280, -264, + -312, -296, -472, -456, -504, -488, -408, + -392, -440, -424, -88, -72, -120, -104, + -24, -8, -56, -40, -216, -200, -248, + -232, -152, -136, -184, -168, -1376, -1312, + -1504, -1440, -1120, -1056, -1248, -1184, -1888, + -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, + -592, -944, -912, -1008, -976, -816, -784, + -880, -848, 5504, 5248, 6016, 5760, 4480, + 4224, 4992, 4736, 7552, 7296, 8064, 7808, + 6528, 6272, 7040, 6784, 2752, 2624, 3008, + 2880, 2240, 2112, 2496, 2368, 3776, 3648, + 4032, 3904, 3264, 3136, 3520, 3392, 22016, + 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, + 27136, 11008, 10496, 12032, 11520, 8960, 8448, + 9984, 9472, 15104, 14592, 16128, 15616, 13056, + 12544, 14080, 13568, 344, 328, 376, 360, + 280, 264, 312, 296, 472, 456, 504, + 488, 408, 392, 440, 424, 88, 72, + 120, 104, 24, 8, 56, 40, 216, + 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, + 1184, 1888, 1824, 2016, 1952, 1632, 1568, + 1760, 1696, 688, 656, 752, 720, 560, + 528, 624, 592, 944, 912, 1008, 976, + 816, 784, 880, 848 +}; + +uint8_t _st_13linear2alaw[0x2000] = { + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, + 0x6b, 0x6b, 0x6b, 0x6b, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x6e, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, + 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, + 0x6d, 0x6d, 0x6d, 0x6d, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, + 0x67, 0x67, 0x67, 0x67, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x7a, 0x7a, 0x7a, 0x7a, + 0x7b, 0x7b, 0x7b, 0x7b, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79, + 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7d, 0x7d, 0x7d, 0x7d, 0x72, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x73, + 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x71, 0x76, 0x76, 0x76, 0x76, + 0x77, 0x77, 0x77, 0x77, 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, + 0x4a, 0x4a, 0x4b, 0x4b, 0x48, 0x48, 0x49, 0x49, 0x4e, 0x4e, 0x4f, 0x4f, + 0x4c, 0x4c, 0x4d, 0x4d, 0x42, 0x42, 0x43, 0x43, 0x40, 0x40, 0x41, 0x41, + 0x46, 0x46, 0x47, 0x47, 0x44, 0x44, 0x45, 0x45, 0x5a, 0x5a, 0x5b, 0x5b, + 0x58, 0x58, 0x59, 0x59, 0x5e, 0x5e, 0x5f, 0x5f, 0x5c, 0x5c, 0x5d, 0x5d, + 0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51, 0x56, 0x56, 0x57, 0x57, + 0x54, 0x54, 0x55, 0x55, 0xd5, 0xd5, 0xd4, 0xd4, 0xd7, 0xd7, 0xd6, 0xd6, + 0xd1, 0xd1, 0xd0, 0xd0, 0xd3, 0xd3, 0xd2, 0xd2, 0xdd, 0xdd, 0xdc, 0xdc, + 0xdf, 0xdf, 0xde, 0xde, 0xd9, 0xd9, 0xd8, 0xd8, 0xdb, 0xdb, 0xda, 0xda, + 0xc5, 0xc5, 0xc4, 0xc4, 0xc7, 0xc7, 0xc6, 0xc6, 0xc1, 0xc1, 0xc0, 0xc0, + 0xc3, 0xc3, 0xc2, 0xc2, 0xcd, 0xcd, 0xcc, 0xcc, 0xcf, 0xcf, 0xce, 0xce, + 0xc9, 0xc9, 0xc8, 0xc8, 0xcb, 0xcb, 0xca, 0xca, 0xf5, 0xf5, 0xf5, 0xf5, + 0xf4, 0xf4, 0xf4, 0xf4, 0xf7, 0xf7, 0xf7, 0xf7, 0xf6, 0xf6, 0xf6, 0xf6, + 0xf1, 0xf1, 0xf1, 0xf1, 0xf0, 0xf0, 0xf0, 0xf0, 0xf3, 0xf3, 0xf3, 0xf3, + 0xf2, 0xf2, 0xf2, 0xf2, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, 0xfc, 0xfc, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf8, 0xf8, 0xf8, 0xf8, 0xfb, 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xfa, 0xfa, + 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4, + 0xe4, 0xe4, 0xe4, 0xe4, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe1, 0xe1, 0xe1, 0xe1, + 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, + 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, + 0xe2, 0xe2, 0xe2, 0xe2, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, + 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xef, 0xef, 0xef, 0xef, + 0xef, 0xef, 0xef, 0xef, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8, + 0xe8, 0xe8, 0xe8, 0xe8, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, + 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa +}; + +#endif /* FAST_ALAW_CONVERSION */ + +#ifdef FAST_ULAW_CONVERSION + +int16_t _st_ulaw2linear16[256] = { + -32124, -31100, -30076, -29052, -28028, -27004, -25980, + -24956, -23932, -22908, -21884, -20860, -19836, -18812, + -17788, -16764, -15996, -15484, -14972, -14460, -13948, + -13436, -12924, -12412, -11900, -11388, -10876, -10364, + -9852, -9340, -8828, -8316, -7932, -7676, -7420, + -7164, -6908, -6652, -6396, -6140, -5884, -5628, + -5372, -5116, -4860, -4604, -4348, -4092, -3900, + -3772, -3644, -3516, -3388, -3260, -3132, -3004, + -2876, -2748, -2620, -2492, -2364, -2236, -2108, + -1980, -1884, -1820, -1756, -1692, -1628, -1564, + -1500, -1436, -1372, -1308, -1244, -1180, -1116, + -1052, -988, -924, -876, -844, -812, -780, + -748, -716, -684, -652, -620, -588, -556, + -524, -492, -460, -428, -396, -372, -356, + -340, -324, -308, -292, -276, -260, -244, + -228, -212, -196, -180, -164, -148, -132, + -120, -112, -104, -96, -88, -80, -72, + -64, -56, -48, -40, -32, -24, -16, + -8, 0, 32124, 31100, 30076, 29052, 28028, + 27004, 25980, 24956, 23932, 22908, 21884, 20860, + 19836, 18812, 17788, 16764, 15996, 15484, 14972, + 14460, 13948, 13436, 12924, 12412, 11900, 11388, + 10876, 10364, 9852, 9340, 8828, 8316, 7932, + 7676, 7420, 7164, 6908, 6652, 6396, 6140, + 5884, 5628, 5372, 5116, 4860, 4604, 4348, + 4092, 3900, 3772, 3644, 3516, 3388, 3260, + 3132, 3004, 2876, 2748, 2620, 2492, 2364, + 2236, 2108, 1980, 1884, 1820, 1756, 1692, + 1628, 1564, 1500, 1436, 1372, 1308, 1244, + 1180, 1116, 1052, 988, 924, 876, 844, + 812, 780, 748, 716, 684, 652, 620, + 588, 556, 524, 492, 460, 428, 396, + 372, 356, 340, 324, 308, 292, 276, + 260, 244, 228, 212, 196, 180, 164, + 148, 132, 120, 112, 104, 96, 88, + 80, 72, 64, 56, 48, 40, 32, + 24, 16, 8, 0 +}; + +uint8_t _st_14linear2ulaw[0x4000] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x43, 0x43, + 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, + 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, + 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x46, 0x46, + 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, + 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, + 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, + 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, + 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, + 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, + 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, + 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, + 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, + 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, + 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, + 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, + 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, + 0x52, 0x52, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x54, + 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5a, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, + 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, + 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x60, 0x60, + 0x60, 0x60, 0x61, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x62, 0x63, 0x63, + 0x63, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x65, 0x65, 0x65, 0x66, 0x66, + 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, + 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, + 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, + 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74, + 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, + 0x7b, 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0xff, 0xfe, 0xfe, 0xfd, + 0xfd, 0xfc, 0xfc, 0xfb, 0xfb, 0xfa, 0xfa, 0xf9, 0xf9, 0xf8, 0xf8, 0xf7, + 0xf7, 0xf6, 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3, 0xf3, 0xf2, 0xf2, 0xf1, + 0xf1, 0xf0, 0xf0, 0xef, 0xef, 0xef, 0xef, 0xee, 0xee, 0xee, 0xee, 0xed, + 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xeb, 0xeb, 0xeb, 0xeb, 0xea, + 0xea, 0xea, 0xea, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8, 0xe7, + 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe5, 0xe5, 0xe5, 0xe5, 0xe4, + 0xe4, 0xe4, 0xe4, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, + 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, + 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xda, + 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, + 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd7, + 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, + 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd4, + 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, + 0xd3, 0xd3, 0xd3, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd1, + 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, + 0xd0, 0xd0, 0xd0, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, + 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xce, 0xce, 0xce, 0xce, 0xce, + 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, + 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xca, + 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, + 0xca, 0xca, 0xca, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, + 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, + 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc7, + 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, + 0xc7, 0xc7, 0xc7, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, + 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, + 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, + 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80 +}; + +#endif /* FAST_ULAW_CONVERSION */ + +/* The following code was used to generate the lookup tables */ +#if 0 +int main() +{ + int x, y, find2a = 0; + + y = 0; + printf("int16_t _st_alaw2linear16[256] = {\n "); + for (x = 0; x < 256; x++) + { + printf("%8d,", st_alaw2linear16(x)); + y++; + if (y == 7) + { + y = 0; + printf("\n "); + } + } + + printf("\n};\n\nuint8_t _st_13linear2alaw[0x2000] = {\n "); + y = 0; + for (x = 0; x < 0x2000; x++) + { + printf(" 0x%02x,", st_13linear2alaw((-0x1000)+x)); + y++; + if (y == 12) + { + y = 0; + printf("\n "); + } + } + + printf("\n};\n\nint16_t _st_ulaw2linear16[256] = {\n "); + y = 0; + for (x = 0; x < 256; x++) + { + printf("%8d,", st_ulaw2linear16(x)); + y++; + if (y == 7) + { + y = 0; + printf("\n "); + } + } + + printf("\n};\n\nuint8_t _st_14linear2ulaw[0x4000] = {\n "); + y = 0; + for (x = 0; x < 0x4000; x++) + { + printf(" 0x%02x,", st_14linear2ulaw((-0x2000)+x)); + y++; + if (y == 12) + { + y = 0; + printf("\n "); + } + } + printf("\n};\n"); + +} +#endif + +/* The following is not used by SoX but kept for reference */ +#if 0 +/* copy from CCITT G.711 specifications */ +unsigned char _u2a[128] = { /* u- to A-law conversions */ + 1, 1, 2, 2, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 27, 29, 31, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 46, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, +/* corrected: + 81, 82, 83, 84, 85, 86, 87, 88, + should be: */ + 80, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128}; + +unsigned char _a2u[128] = { /* A- to u-law conversions */ + 1, 3, 5, 7, 9, 11, 13, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 33, 34, 34, 35, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 48, 49, 49, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 64, + 65, 66, 67, 68, 69, 70, 71, 72, +/* corrected: + 73, 74, 75, 76, 77, 78, 79, 79, + should be: */ + 73, 74, 75, 76, 77, 78, 79, 80, + + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}; + +/* A-law to u-law conversion */ +unsigned char st_alaw2ulaw( + unsigned char aval) +{ + aval &= 0xff; + return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : + (0x7F ^ _a2u[aval ^ 0x55])); +} + +/* u-law to A-law conversion */ +unsigned char st_ulaw2alaw( + unsigned char uval) +{ + uval &= 0xff; + return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : + (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1))); +} +#endif diff --git a/polyp/g711.h b/polyp/g711.h new file mode 100644 index 000000000..97cedf814 --- /dev/null +++ b/polyp/g711.h @@ -0,0 +1,40 @@ +#ifndef foog711hfoo +#define foog711hfoo + +/* g711.h - include for G711 u-law and a-law conversion routines +** +** Copyright (C) 2001 Chris Bagwell +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + +/** Copied from sox -- Lennart Poettring*/ + +#include + +#ifdef FAST_ALAW_CONVERSION +extern uint8_t _st_13linear2alaw[0x2000]; +extern int16_t _st_alaw2linear16[256]; +#define st_13linear2alaw(sw) (_st_13linear2alaw[(sw + 0x1000)]) +#define st_alaw2linear16(uc) (_st_alaw2linear16[uc]) +#else +unsigned char st_13linear2alaw(int16_t pcm_val); +int16_t st_alaw2linear16(unsigned char); +#endif + +#ifdef FAST_ULAW_CONVERSION +extern uint8_t _st_14linear2ulaw[0x4000]; +extern int16_t _st_ulaw2linear16[256]; +#define st_14linear2ulaw(sw) (_st_14linear2ulaw[(sw + 0x2000)]) +#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc]) +#else +unsigned char st_14linear2ulaw(int16_t pcm_val); +int16_t st_ulaw2linear16(unsigned char); +#endif + +#endif diff --git a/polyp/pactl.c b/polyp/pactl.c index 641106dfc..d73f703ca 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -324,7 +324,8 @@ static void get_sink_input_info_callback(struct pa_context *c, const struct pa_s "Sample Specification: %s\n" "Volume: 0x%03x (%0.2f dB)\n" "Buffer Latency: %0.0f usec\n" - "Sink Latency: %0.0f usec\n", + "Sink Latency: %0.0f usec\n" + "Resample method: %s\n", i->index, i->name, i->owner_module != PA_INVALID_INDEX ? t : "n/a", @@ -333,7 +334,8 @@ static void get_sink_input_info_callback(struct pa_context *c, const struct pa_s s, i->volume, pa_volume_to_dB(i->volume), (double) i->buffer_usec, - (double) i->sink_usec); + (double) i->sink_usec, + i->resample_method ? i->resample_method : "n/a"); } static void get_source_output_info_callback(struct pa_context *c, const struct pa_source_output_info *i, int is_last, void *userdata) { @@ -367,7 +369,8 @@ static void get_source_output_info_callback(struct pa_context *c, const struct p "Source: %u\n" "Sample Specification: %s\n" "Buffer Latency: %0.0f usec\n" - "Source Latency: %0.0f usec\n", + "Source Latency: %0.0f usec\n" + "Resample method: %s\n", i->index, i->name, i->owner_module != PA_INVALID_INDEX ? t : "n/a", @@ -375,7 +378,8 @@ static void get_source_output_info_callback(struct pa_context *c, const struct p i->source, s, (double) i->buffer_usec, - (double) i->source_usec); + (double) i->source_usec, + i->resample_method ? i->resample_method : "n/a"); } static void get_sample_info_callback(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata) { diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index f15f59cc8..fe632c267 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -449,7 +449,8 @@ static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_getu32(t, &i.volume) < 0 || pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || - pa_tagstruct_get_usec(t, &i.sink_usec) < 0) { + pa_tagstruct_get_usec(t, &i.sink_usec) < 0 || + pa_tagstruct_gets(t, &i.resample_method) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -519,7 +520,8 @@ static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uin pa_tagstruct_getu32(t, &i.source) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || - pa_tagstruct_get_usec(t, &i.source_usec) < 0) { + pa_tagstruct_get_usec(t, &i.source_usec) < 0 || + pa_tagstruct_gets(t, &i.resample_method) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 5a8f1bf33..08b36f866 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -143,6 +143,7 @@ struct pa_sink_input_info { pa_volume_t volume; /**< The volume of this sink input */ pa_usec_t buffer_usec; /**< Latency due to buffering in sink input, see pa_latency_info for details */ pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */ + const char *resample_method; /**< Thre resampling method used by this sink input. \since 0.7 */ }; /** Get some information about a sink input by its index */ @@ -161,6 +162,7 @@ struct pa_source_output_info { struct pa_sample_spec sample_spec; /**< The sample specification of the source output */ pa_usec_t buffer_usec; /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */ pa_usec_t source_usec; /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */ + const char *resample_method; /**< Thre resampling method used by this source output. \since 0.7 */ }; /** Get information about a source output by its index */ diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 12ecfae14..e4831e4d9 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -1160,6 +1160,7 @@ static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_inp pa_tagstruct_putu32(t, s->volume); pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s)); pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink)); + pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s))); } static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) { @@ -1172,6 +1173,7 @@ static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_sourc pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_put_usec(t, pa_source_output_get_latency(s)); pa_tagstruct_put_usec(t, pa_source_get_latency(s->source)); + pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s))); } static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry *e) { diff --git a/polyp/pstream-util.c b/polyp/pstream-util.c index 95a2ae898..8526f29ce 100644 --- a/polyp/pstream-util.c +++ b/polyp/pstream-util.c @@ -32,7 +32,8 @@ void pa_pstream_send_tagstruct(struct pa_pstream *p, struct pa_tagstruct *t) { size_t length; uint8_t *data; struct pa_packet *packet; - assert(p && t); + assert(p); + assert(t); data = pa_tagstruct_free_data(t, &length); assert(data && length); diff --git a/polyp/resampler.c b/polyp/resampler.c index 4ddcfa403..6cf51dab5 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -24,6 +24,7 @@ #endif #include +#include #include @@ -34,55 +35,74 @@ struct pa_resampler { struct pa_sample_spec i_ss, o_ss; - float* i_buf, *o_buf; - unsigned i_alloc, o_alloc; - size_t i_sz, o_sz; - - int channels; - - pa_convert_to_float32_func_t to_float32_func; - pa_convert_from_float32_func_t from_float32_func; - SRC_STATE *src_state; - + size_t i_fz, o_fz; struct pa_memblock_stat *memblock_stat; + void *impl_data; + int channels; + enum pa_resample_method resample_method; + + void (*impl_free)(struct pa_resampler *r); + void (*impl_set_input_rate)(struct pa_resampler *r, uint32_t rate); + void (*impl_run)(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out); }; -struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, int resample_method) { +struct impl_libsamplerate { + float* i_buf, *o_buf; + unsigned i_alloc, o_alloc; + pa_convert_to_float32ne_func_t to_float32ne_func; + pa_convert_from_float32ne_func_t from_float32ne_func; + SRC_STATE *src_state; +}; + +struct impl_trivial { + unsigned o_counter; + unsigned i_counter; +}; + +static int libsamplerate_init(struct pa_resampler*r); +static int trivial_init(struct pa_resampler*r); + +struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, enum pa_resample_method resample_method) { struct pa_resampler *r = NULL; - int err; - assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b)); + assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b) && resample_method != PA_RESAMPLER_INVALID); if (a->channels != b->channels && a->channels != 1 && b->channels != 1) goto fail; - if (a->format == PA_SAMPLE_ALAW || a->format == PA_SAMPLE_ULAW || b->format == PA_SAMPLE_ALAW || b->format == PA_SAMPLE_ULAW) - goto fail; - r = pa_xmalloc(sizeof(struct pa_resampler)); + r->impl_data = NULL; + r->memblock_stat = s; + r->resample_method = resample_method; + + r->impl_free = NULL; + r->impl_set_input_rate = NULL; + r->impl_run = NULL; + + /* Fill sample specs */ + r->i_ss = *a; + r->o_ss = *b; + + r->i_fz = pa_frame_size(a); + r->o_fz = pa_frame_size(b); r->channels = a->channels; if (b->channels < r->channels) r->channels = b->channels; - r->i_buf = r->o_buf = NULL; - r->i_alloc = r->o_alloc = 0; + /* Choose implementation */ + if (a->channels != b->channels || a->format != b->format || resample_method != PA_RESAMPLER_TRIVIAL) { + /* Use the libsamplerate based resampler for the complicated cases */ + if (resample_method == PA_RESAMPLER_TRIVIAL) + r->resample_method = PA_RESAMPLER_SRC_ZERO_ORDER_HOLD; - r->src_state = src_new(resample_method, r->channels, &err); - if (err != 0 || !r->src_state) - goto fail; - - r->i_ss = *a; - r->o_ss = *b; - - r->i_sz = pa_frame_size(a); - r->o_sz = pa_frame_size(b); - - r->to_float32_func = pa_get_convert_to_float32_function(a->format); - r->from_float32_func = pa_get_convert_from_float32_function(b->format); - - assert(r->to_float32_func && r->from_float32_func); - - r->memblock_stat = s; + if (libsamplerate_init(r) < 0) + goto fail; + + } else { + /* Use our own simple non-fp resampler for the trivial cases and when the user selects it */ + if (trivial_init(r) < 0) + goto fail; + } return r; @@ -95,32 +115,86 @@ fail: void pa_resampler_free(struct pa_resampler *r) { assert(r); - if (r->src_state) - src_delete(r->src_state); - pa_xfree(r->i_buf); - pa_xfree(r->o_buf); + + if (r->impl_free) + r->impl_free(r); + pa_xfree(r); } -size_t pa_resampler_request(struct pa_resampler *r, size_t out_length) { - assert(r && (out_length % r->o_sz) == 0); - - return (((out_length / r->o_sz)*r->i_ss.rate)/r->o_ss.rate) * r->i_sz; +void pa_resampler_set_input_rate(struct pa_resampler *r, uint32_t rate) { + assert(r && rate); + + r->i_ss.rate = rate; + if (r->impl_set_input_rate) + r->impl_set_input_rate(r, rate); } - void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out) { + assert(r && in && out && r->impl_run); + + r->impl_run(r, in, out); +} + +size_t pa_resampler_request(struct pa_resampler *r, size_t out_length) { + assert(r && (out_length % r->o_fz) == 0); + return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz; +} + +enum pa_resample_method pa_resampler_get_method(struct pa_resampler *r) { + assert(r); + return r->resample_method; +} + +/* Parse a libsamplrate compatible resampling implementation */ +enum pa_resample_method pa_parse_resample_method(const char *string) { + assert(string); + + if (!strcmp(string, "src-sinc-best-quality")) + return PA_RESAMPLER_SRC_SINC_BEST_QUALITY; + else if (!strcmp(string, "src-sinc-medium-quality")) + return PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY; + else if (!strcmp(string, "src-sinc-fastest")) + return PA_RESAMPLER_SRC_SINC_FASTEST; + else if (!strcmp(string, "src-zero-order-hold")) + return PA_RESAMPLER_SRC_ZERO_ORDER_HOLD; + else if (!strcmp(string, "src-linear")) + return PA_RESAMPLER_SRC_LINEAR; + else if (!strcmp(string, "trivial")) + return PA_RESAMPLER_TRIVIAL; + else + return PA_RESAMPLER_INVALID; +} + +/*** libsamplerate based implementation ***/ + +static void libsamplerate_free(struct pa_resampler *r) { + struct impl_libsamplerate *i; + assert(r && r->impl_data); + i = r->impl_data; + + if (i->src_state) + src_delete(i->src_state); + + pa_xfree(i->i_buf); + pa_xfree(i->o_buf); + pa_xfree(i); +} + +static void libsamplerate_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out) { unsigned i_nchannels, o_nchannels, ins, ons, eff_ins, eff_ons; float *cbuf; - assert(r && in && out && in->length && in->memblock && (in->length % r->i_sz) == 0); + struct impl_libsamplerate *i; + assert(r && in && out && in->length && in->memblock && (in->length % r->i_fz) == 0 && r->impl_data); + i = r->impl_data; /* How many input samples? */ - ins = in->length/r->i_sz; + ins = in->length/r->i_fz; -/* pa_log("%u / %u = %u\n", in->length, r->i_sz, ins); */ +/* pa_log("%u / %u = %u\n", in->length, r->i_fz, ins); */ /* How much space for output samples? */ - if (r->src_state) + if (i->src_state) ons = (ins*r->o_ss.rate/r->i_ss.rate)+1024; else ons = ins; @@ -140,40 +214,40 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru /* pa_log("eff_ins = %u \n", eff_ins); */ - out->memblock = pa_memblock_new(out->length = (ons*r->o_sz), r->memblock_stat); + out->memblock = pa_memblock_new(out->length = (ons*r->o_fz), r->memblock_stat); out->index = 0; assert(out->memblock); - if (r->i_alloc < eff_ins) - r->i_buf = pa_xrealloc(r->i_buf, sizeof(float) * (r->i_alloc = eff_ins)); - assert(r->i_buf); + if (i->i_alloc < eff_ins) + i->i_buf = pa_xrealloc(i->i_buf, sizeof(float) * (i->i_alloc = eff_ins)); + assert(i->i_buf); /* pa_log("eff_ins = %u \n", eff_ins); */ - r->to_float32_func(eff_ins, (uint8_t*) in->memblock->data+in->index, i_nchannels, r->i_buf); + i->to_float32ne_func(eff_ins, (uint8_t*) in->memblock->data+in->index, i_nchannels, i->i_buf); - if (r->src_state) { + if (i->src_state) { int ret; SRC_DATA data; - if (r->o_alloc < eff_ons) - r->o_buf = pa_xrealloc(r->o_buf, sizeof(float) * (r->o_alloc = eff_ons)); - assert(r->o_buf); + if (i->o_alloc < eff_ons) + i->o_buf = pa_xrealloc(i->o_buf, sizeof(float) * (i->o_alloc = eff_ons)); + assert(i->o_buf); - data.data_in = r->i_buf; + data.data_in = i->i_buf; data.input_frames = ins; - data.data_out = r->o_buf; + data.data_out = i->o_buf; data.output_frames = ons; data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; data.end_of_input = 0; - ret = src_process(r->src_state, &data); + ret = src_process(i->src_state, &data); assert(ret == 0); assert((unsigned) data.input_frames_used == ins); - cbuf = r->o_buf; + cbuf = i->o_buf; ons = data.output_frames_gen; if (r->i_ss.channels == r->o_ss.channels) @@ -181,12 +255,11 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru else eff_ons = ons; } else - cbuf = r->i_buf; + cbuf = i->i_buf; if (eff_ons) - r->from_float32_func(eff_ons, cbuf, (uint8_t*)out->memblock->data+out->index, o_nchannels); - out->length = ons*r->o_sz; - + i->from_float32ne_func(eff_ons, cbuf, (uint8_t*)out->memblock->data+out->index, o_nchannels); + out->length = ons*r->o_fz; if (!out->length) { pa_memblock_unref(out->memblock); @@ -194,11 +267,147 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru } } -void pa_resampler_set_input_rate(struct pa_resampler *r, uint32_t rate) { +static void libsamplerate_set_input_rate(struct pa_resampler *r, uint32_t rate) { int ret; - assert(r); + struct impl_libsamplerate *i; + assert(r && rate > 0 && r->impl_data); + i = r->impl_data; - r->i_ss.rate = rate; - ret = src_set_ratio(r->src_state, (double) r->o_ss.rate / r->i_ss.rate); + ret = src_set_ratio(i->src_state, (double) r->o_ss.rate / r->i_ss.rate); assert(ret == 0); } + +static int libsamplerate_init(struct pa_resampler *r) { + struct impl_libsamplerate *i = NULL; + int err; + + r->impl_data = i = pa_xmalloc(sizeof(struct impl_libsamplerate)); + + i->to_float32ne_func = pa_get_convert_to_float32ne_function(r->i_ss.format); + i->from_float32ne_func = pa_get_convert_from_float32ne_function(r->o_ss.format); + + if (!i->to_float32ne_func || !i->from_float32ne_func) + goto fail; + + if (!(i->src_state = src_new(r->resample_method, r->channels, &err)) || !i->src_state) + goto fail; + + i->i_buf = i->o_buf = NULL; + i->i_alloc = i->o_alloc = 0; + + r->impl_free = libsamplerate_free; + r->impl_set_input_rate = libsamplerate_set_input_rate; + r->impl_run = libsamplerate_run; + + return 0; + +fail: + pa_xfree(i); + return -1; +} + +/* Trivial implementation */ + +static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out) { + size_t fz; + unsigned nsamples; + struct impl_trivial *i; + assert(r && in && out && r->impl_data); + i = r->impl_data; + + fz = r->i_fz; + assert(fz == r->o_fz); + + nsamples = in->length/fz; + + if (r->i_ss.rate == r->o_ss.rate) { + + /* In case there's no diefference in sample types, do nothing */ + *out = *in; + pa_memblock_ref(in->memblock); + + i->o_counter += nsamples; + } else { + /* Do real resampling */ + size_t l; + unsigned o_index; + + /* The length of the new memory block rounded up */ + l = ((nsamples * r->o_ss.rate + r->i_ss.rate - 1) / r->i_ss.rate) * fz; + + out->index = 0; + out->memblock = pa_memblock_new(l, r->memblock_stat); + + for (o_index = 0;; o_index++, i->o_counter++) { + unsigned j; + + j = (i->o_counter * r->i_ss.rate / r->o_ss.rate); + assert(j >= i->i_counter); + j = j - i->i_counter; + + if (j >= nsamples) + break; + + assert(o_index*fz < out->memblock->length); + + memcpy((uint8_t*) out->memblock->data + fz*o_index, + (uint8_t*) in->memblock->data + fz*j, fz); + + } + + out->length = o_index*fz; + } + + /* Normalize the output counter */ + while (i->o_counter >= r->o_ss.rate) + i->o_counter -= r->o_ss.rate; + + i->i_counter += nsamples; + + while (i->i_counter >= r->i_ss.rate) + i->i_counter -= r->i_ss.rate; +} + +static void trivial_free(struct pa_resampler *r) { + assert(r); + pa_xfree(r->impl_data); +} + +static void trivial_set_input_rate(struct pa_resampler *r, uint32_t rate) { + struct impl_trivial *i; + assert(r && rate > 0 && r->impl_data); + i = r->impl_data; + + i->i_counter = 0; + i->o_counter = 0; +} + +static int trivial_init(struct pa_resampler*r) { + struct impl_trivial *i; + assert(r && r->i_ss.format == r->o_ss.format && r->i_ss.channels == r->o_ss.channels); + + r->impl_data = i = pa_xmalloc(sizeof(struct impl_trivial)); + i->o_counter = i->i_counter = 0; + + r->impl_run = trivial_run; + r->impl_free = trivial_free; + r->impl_set_input_rate = trivial_set_input_rate; + + return 0; +} + +const char *pa_resample_method_to_string(enum pa_resample_method m) { + static const char const* resample_methods[] = { + "src-sinc-best-quality", + "src-sinc-medium-quality", + "src-sinc-fastest", + "src-zero-order-hold", + "src-linear", + "trivial" + }; + + if (m < 0 || m >= PA_RESAMPLER_MAX) + return NULL; + + return resample_methods[m]; +} diff --git a/polyp/resampler.h b/polyp/resampler.h index 08fad8093..0109e7908 100644 --- a/polyp/resampler.h +++ b/polyp/resampler.h @@ -22,18 +22,44 @@ USA. ***/ +#include + #include "sample.h" #include "memblock.h" #include "memchunk.h" struct pa_resampler; +enum pa_resample_method { + PA_RESAMPLER_INVALID = -1, + PA_RESAMPLER_SRC_SINC_BEST_QUALITY = SRC_SINC_BEST_QUALITY, + PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY = SRC_SINC_MEDIUM_QUALITY, + PA_RESAMPLER_SRC_SINC_FASTEST = SRC_SINC_FASTEST, + PA_RESAMPLER_SRC_ZERO_ORDER_HOLD = SRC_ZERO_ORDER_HOLD, + PA_RESAMPLER_SRC_LINEAR = SRC_LINEAR, + PA_RESAMPLER_TRIVIAL, + PA_RESAMPLER_MAX +}; + struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, int resample_method); void pa_resampler_free(struct pa_resampler *r); +/* Returns the size of an input memory block which is required to return the specified amount of output data */ size_t pa_resampler_request(struct pa_resampler *r, size_t out_length); + +/* Pass the specified memory chunk to the resampler and return the newly resampled data */ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out); +/* Change the input rate of the resampler object */ void pa_resampler_set_input_rate(struct pa_resampler *r, uint32_t rate); +/* Return the resampling method of the resampler object */ +enum pa_resample_method pa_resampler_get_method(struct pa_resampler *r); + +/* Try to parse the resampler method */ +enum pa_resample_method pa_parse_resample_method(const char *string); + +/* return a human readable string for the specified resampling method. Inverse of pa_parse_resample_method() */ +const char *pa_resample_method_to_string(enum pa_resample_method m); + #endif diff --git a/polyp/sample-util.c b/polyp/sample-util.c index 0d4d18d36..d521afe4a 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "sample-util.h" @@ -41,12 +42,12 @@ void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spe } void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec) { - char c = 0; + uint8_t c = 0; assert(p && length && spec); switch (spec->format) { case PA_SAMPLE_U8: - c = 127; + c = 0x80; break; case PA_SAMPLE_S16LE: case PA_SAMPLE_S16BE: @@ -65,54 +66,145 @@ void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec } size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, pa_volume_t volume) { - unsigned c, d; assert(channels && data && length && spec); - assert(spec->format == PA_SAMPLE_S16NE); - - for (d = 0;; d += sizeof(int16_t)) { - int32_t sum = 0; - - if (d >= length) - return d; + + if (spec->format == PA_SAMPLE_S16NE) { + size_t d; - for (c = 0; c < nchannels; c++) { - int32_t v; - uint32_t volume = channels[c].volume; + for (d = 0;; d += sizeof(int16_t)) { + unsigned c; + int32_t sum = 0; - if (d >= channels[c].chunk.length) + if (d >= length) return d; - - if (volume == PA_VOLUME_MUTED) - v = 0; - else { - v = *((int16_t*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d)); - - if (volume != PA_VOLUME_NORM) - v = (int32_t) ((float)v*volume/PA_VOLUME_NORM); + + for (c = 0; c < nchannels; c++) { + int32_t v; + pa_volume_t cvolume = channels[c].volume; + + if (d >= channels[c].chunk.length) + return d; + + if (cvolume == PA_VOLUME_MUTED) + v = 0; + else { + v = *((int16_t*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d)); + + if (cvolume != PA_VOLUME_NORM) { + v *= cvolume; + v /= PA_VOLUME_NORM; + } + } + + sum += v; } - - sum += v; + + if (volume == PA_VOLUME_MUTED) + sum = 0; + else if (volume != PA_VOLUME_NORM) { + sum *= volume; + sum /= PA_VOLUME_NORM; + } + + if (sum < -0x8000) sum = -0x8000; + if (sum > 0x7FFF) sum = 0x7FFF; + + *((int16_t*) data) = sum; + data = (uint8_t*) data + sizeof(int16_t); } - - if (volume == PA_VOLUME_MUTED) - sum = 0; - else if (volume != PA_VOLUME_NORM) - sum = (int32_t) ((float) sum*volume/PA_VOLUME_NORM); + } else if (spec->format == PA_SAMPLE_U8) { + size_t d; - if (sum < -0x8000) sum = -0x8000; - if (sum > 0x7FFF) sum = 0x7FFF; + for (d = 0;; d ++) { + int32_t sum = 0; + unsigned c; + + if (d >= length) + return d; + + for (c = 0; c < nchannels; c++) { + int32_t v; + pa_volume_t cvolume = channels[c].volume; + + if (d >= channels[c].chunk.length) + return d; + + if (cvolume == PA_VOLUME_MUTED) + v = 0; + else { + v = (int32_t) *((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d) - 0x80; + + if (cvolume != PA_VOLUME_NORM) { + v *= cvolume; + v /= PA_VOLUME_NORM; + } + } + + sum += v; + } + + if (volume == PA_VOLUME_MUTED) + sum = 0; + else if (volume != PA_VOLUME_NORM) { + sum *= volume; + sum /= PA_VOLUME_NORM; + } + + if (sum < -0x80) sum = -0x80; + if (sum > 0x7F) sum = 0x7F; + + *((uint8_t*) data) = (uint8_t) (sum + 0x80); + data = (uint8_t*) data + 1; + } - *((int16_t*) data) = sum; - data = (uint8_t*) data + sizeof(int16_t); + } else if (spec->format == PA_SAMPLE_FLOAT32NE) { + size_t d; + + for (d = 0;; d += sizeof(float)) { + float_t sum = 0; + unsigned c; + + if (d >= length) + return d; + + for (c = 0; c < nchannels; c++) { + float v; + pa_volume_t cvolume = channels[c].volume; + + if (d >= channels[c].chunk.length) + return d; + + if (cvolume == PA_VOLUME_MUTED) + v = 0; + else { + v = *((float*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d)); + + if (cvolume != PA_VOLUME_NORM) + v = v*cvolume/PA_VOLUME_NORM; + } + + sum += v; + } + + if (volume == PA_VOLUME_MUTED) + sum = 0; + else if (volume != PA_VOLUME_NORM) + sum = sum*volume/PA_VOLUME_NORM; + + if (sum < -1) sum = -1; + if (sum > 1) sum = 1; + + *((float*) data) = sum; + data = (uint8_t*) data + sizeof(float); + } + } else { + abort(); } } void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, pa_volume_t volume) { - int16_t *d; - size_t n; assert(c && spec && (c->length % pa_frame_size(spec) == 0)); - assert(spec->format == PA_SAMPLE_S16NE); if (volume == PA_VOLUME_NORM) return; @@ -122,16 +214,55 @@ void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, return; } - for (d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { - int32_t t = (int32_t)(*d); - - t *= volume; - t /= PA_VOLUME_NORM; - - if (t < -0x8000) t = -0x8000; - if (t > 0x7FFF) t = 0x7FFF; + if (spec->format == PA_SAMPLE_S16NE) { + int16_t *d; + size_t n; - *d = (int16_t) t; + for (d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + int32_t t = (int32_t)(*d); + + t *= volume; + t /= PA_VOLUME_NORM; + + if (t < -0x8000) t = -0x8000; + if (t > 0x7FFF) t = 0x7FFF; + + *d = (int16_t) t; + } + } else if (spec->format == PA_SAMPLE_U8) { + uint8_t *d; + size_t n; + + for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) { + int32_t t = (int32_t) *d - 0x80; + + t *= volume; + t /= PA_VOLUME_NORM; + + if (t < -0x80) t = -0x80; + if (t > 0x7F) t = 0x7F; + + *d = (uint8_t) (t + 0x80); + + } + } else if (spec->format == PA_SAMPLE_FLOAT32NE) { + float *d; + size_t n; + + for (d = (float*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(float); n > 0; d++, n--) { + float t = *d; + + t *= volume; + t /= PA_VOLUME_NORM; + + if (t < -1) t = -1; + if (t > 1) t = 1; + + *d = t; + } + + } else { + abort(); } } diff --git a/polyp/sconv-s16be.c b/polyp/sconv-s16be.c index 0ee772c85..54efc78cb 100644 --- a/polyp/sconv-s16be.c +++ b/polyp/sconv-s16be.c @@ -28,7 +28,7 @@ #define INT16_FROM INT16_FROM_BE #define INT16_TO INT16_TO_BE -#define pa_sconv_s16le_to_float32 pa_sconv_s16be_to_float32 -#define pa_sconv_s16le_from_float32 pa_sconv_s16be_from_float32 +#define pa_sconv_s16le_to_float32ne pa_sconv_s16be_to_float32ne +#define pa_sconv_s16le_from_float32ne pa_sconv_s16be_from_float32ne #include "sconv-s16le.c" diff --git a/polyp/sconv-s16be.h b/polyp/sconv-s16be.h index c1876dd08..86107fb5a 100644 --- a/polyp/sconv-s16be.h +++ b/polyp/sconv-s16be.h @@ -22,7 +22,7 @@ USA. ***/ -void pa_sconv_s16be_to_float32(unsigned n, const void *a, unsigned an, float *b); -void pa_sconv_s16be_from_float32(unsigned n, const float *a, void *b, unsigned bn); +void pa_sconv_s16be_to_float32ne(unsigned n, const void *a, unsigned an, float *b); +void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, void *b, unsigned bn); #endif diff --git a/polyp/sconv-s16le.c b/polyp/sconv-s16le.c index 2fbcbf310..49c474617 100644 --- a/polyp/sconv-s16le.c +++ b/polyp/sconv-s16le.c @@ -38,7 +38,7 @@ #define INT16_TO INT16_TO_LE #endif -void pa_sconv_s16le_to_float32(unsigned n, const void *a, unsigned an, float *b) { +void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, unsigned an, float *b) { const int16_t *ca = a; assert(n && a && an && b); @@ -60,7 +60,7 @@ void pa_sconv_s16le_to_float32(unsigned n, const void *a, unsigned an, float *b) } } -void pa_sconv_s16le_from_float32(unsigned n, const float *a, void *b, unsigned bn) { +void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) { int16_t *cb = b; /* pa_log("%u %p %p %u\n", n, a, b, bn); */ diff --git a/polyp/sconv-s16le.h b/polyp/sconv-s16le.h index 8842140c5..caed826ec 100644 --- a/polyp/sconv-s16le.h +++ b/polyp/sconv-s16le.h @@ -22,7 +22,7 @@ USA. ***/ -void pa_sconv_s16le_to_float32(unsigned n, const void *a, unsigned an, float *b); -void pa_sconv_s16le_from_float32(unsigned n, const float *a, void *b, unsigned bn); +void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, unsigned an, float *b); +void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b, unsigned bn); #endif diff --git a/polyp/sconv.c b/polyp/sconv.c index bd670586c..a404f4320 100644 --- a/polyp/sconv.c +++ b/polyp/sconv.c @@ -28,11 +28,12 @@ #include #include "endianmacros.h" #include "sconv.h" +#include "g711.h" #include "sconv-s16le.h" #include "sconv-s16be.h" -static void u8_to_float32(unsigned n, const void *a, unsigned an, float *b) { +static void u8_to_float32ne(unsigned n, const void *a, unsigned an, float *b) { unsigned i; const uint8_t *ca = a; assert(n && a && an && b); @@ -42,7 +43,7 @@ static void u8_to_float32(unsigned n, const void *a, unsigned an, float *b) { for (i = 0; i < an; i++) { uint8_t v = *(ca++); - sum += (((float) v)-127)/127; + sum += (((float) v)-128)/127; } if (sum > 1) @@ -54,7 +55,7 @@ static void u8_to_float32(unsigned n, const void *a, unsigned an, float *b) { } } -static void u8_from_float32(unsigned n, const float *a, void *b, unsigned bn) { +static void u8_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) { unsigned i; uint8_t *cb = b; @@ -69,14 +70,14 @@ static void u8_from_float32(unsigned n, const float *a, void *b, unsigned bn) { if (v < -1) v = -1; - u = (uint8_t) (v*127+127); + u = (uint8_t) (v*127+128); for (i = 0; i < bn; i++) *(cb++) = u; } } -static void float32_to_float32(unsigned n, const void *a, unsigned an, float *b) { +static void float32ne_to_float32ne(unsigned n, const void *a, unsigned an, float *b) { unsigned i; const float *ca = a; assert(n && a && an && b); @@ -95,7 +96,7 @@ static void float32_to_float32(unsigned n, const void *a, unsigned an, float *b) } } -static void float32_from_float32(unsigned n, const float *a, void *b, unsigned bn) { +static void float32ne_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) { unsigned i; float *cb = b; assert(n && a && b && bn); @@ -106,31 +107,122 @@ static void float32_from_float32(unsigned n, const float *a, void *b, unsigned b } } -pa_convert_to_float32_func_t pa_get_convert_to_float32_function(enum pa_sample_format f) { +static void ulaw_to_float32ne(unsigned n, const void *a, unsigned an, float *b) { + unsigned i; + const uint8_t *ca = a; + assert(n && a && an && b); + for (; n > 0; n--) { + float sum = 0; + + for (i = 0; i < an; i++) + sum += (float) st_ulaw2linear16(*ca++) / 0x7FFF; + + if (sum > 1) + sum = 1; + if (sum < -1) + sum = -1; + + *(b++) = sum; + } +} + +static void ulaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) { + unsigned i; + uint8_t *cb = b; + + assert(n && a && b && bn); + for (; n > 0; n--) { + float v = *(a++); + uint8_t u; + + if (v > 1) + v = 1; + + if (v < -1) + v = -1; + + u = st_14linear2ulaw((int16_t) (v * 0x1FFF)); + + for (i = 0; i < bn; i++) + *(cb++) = u; + } +} + +static void alaw_to_float32ne(unsigned n, const void *a, unsigned an, float *b) { + unsigned i; + const uint8_t *ca = a; + assert(n && a && an && b); + for (; n > 0; n--) { + float sum = 0; + + for (i = 0; i < an; i++) + sum += (float) st_alaw2linear16(*ca++) / 0x7FFF; + + if (sum > 1) + sum = 1; + if (sum < -1) + sum = -1; + + *(b++) = sum; + } +} + +static void alaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) { + unsigned i; + uint8_t *cb = b; + + assert(n && a && b && bn); + for (; n > 0; n--) { + float v = *(a++); + uint8_t u; + + if (v > 1) + v = 1; + + if (v < -1) + v = -1; + + u = st_13linear2alaw((int16_t) (v * 0xFFF)); + + for (i = 0; i < bn; i++) + *(cb++) = u; + } +} + + +pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(enum pa_sample_format f) { switch(f) { case PA_SAMPLE_U8: - return u8_to_float32; + return u8_to_float32ne; case PA_SAMPLE_S16LE: - return pa_sconv_s16le_to_float32; + return pa_sconv_s16le_to_float32ne; case PA_SAMPLE_S16BE: - return pa_sconv_s16be_to_float32; - case PA_SAMPLE_FLOAT32: - return float32_to_float32; + return pa_sconv_s16be_to_float32ne; + case PA_SAMPLE_FLOAT32NE: + return float32ne_to_float32ne; + case PA_SAMPLE_ALAW: + return alaw_to_float32ne; + case PA_SAMPLE_ULAW: + return ulaw_to_float32ne; default: return NULL; } } -pa_convert_from_float32_func_t pa_get_convert_from_float32_function(enum pa_sample_format f) { +pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(enum pa_sample_format f) { switch(f) { case PA_SAMPLE_U8: - return u8_from_float32; + return u8_from_float32ne; case PA_SAMPLE_S16LE: - return pa_sconv_s16le_from_float32; + return pa_sconv_s16le_from_float32ne; case PA_SAMPLE_S16BE: - return pa_sconv_s16be_from_float32; - case PA_SAMPLE_FLOAT32: - return float32_from_float32; + return pa_sconv_s16be_from_float32ne; + case PA_SAMPLE_FLOAT32NE: + return float32ne_from_float32ne; + case PA_SAMPLE_ALAW: + return alaw_from_float32ne; + case PA_SAMPLE_ULAW: + return ulaw_from_float32ne; default: return NULL; } diff --git a/polyp/sconv.h b/polyp/sconv.h index 0a12890a2..71517ec26 100644 --- a/polyp/sconv.h +++ b/polyp/sconv.h @@ -24,10 +24,10 @@ #include "sample.h" -typedef void (*pa_convert_to_float32_func_t)(unsigned n, const void *a, unsigned an, float *b); -typedef void (*pa_convert_from_float32_func_t)(unsigned n, const float *a, void *b, unsigned bn); +typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, unsigned an, float *b); +typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b, unsigned bn); -pa_convert_to_float32_func_t pa_get_convert_to_float32_function(enum pa_sample_format f); -pa_convert_from_float32_func_t pa_get_convert_from_float32_function(enum pa_sample_format f); +pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(enum pa_sample_format f); +pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(enum pa_sample_format f); #endif diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 23b4a1364..e66278ed2 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -48,7 +48,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con return NULL; } - if (resample_method < 0) + if (resample_method == PA_RESAMPLER_INVALID) resample_method = s->core->resample_method; if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec)) @@ -272,3 +272,12 @@ void pa_sink_input_set_name(struct pa_sink_input *i, const char *name) { pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); } + +enum pa_resample_method pa_sink_input_get_resample_method(struct pa_sink_input *i) { + assert(i && i->ref >= 1); + + if (!i->resampler) + return PA_RESAMPLER_INVALID; + + return pa_resampler_get_method(i->resampler); +} diff --git a/polyp/sink-input.h b/polyp/sink-input.h index 1c16a9e61..5482369dd 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -87,4 +87,6 @@ void pa_sink_input_set_rate(struct pa_sink_input *i, uint32_t rate); void pa_sink_input_set_name(struct pa_sink_input *i, const char *name); +enum pa_resample_method pa_sink_input_get_resample_method(struct pa_sink_input *i); + #endif diff --git a/polyp/source-output.c b/polyp/source-output.c index e339d4acc..fb06ff8fc 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -44,7 +44,7 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n return NULL; } - if (resample_method < 0) + if (resample_method == PA_RESAMPLER_INVALID) resample_method = s->core->resample_method; if (!pa_sample_spec_equal(&s->sample_spec, spec)) @@ -175,3 +175,12 @@ void pa_source_output_cork(struct pa_source_output *o, int b) { o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING; } + +enum pa_resample_method pa_source_output_get_resample_method(struct pa_source_output *o) { + assert(o && o->ref >= 1); + + if (!o->resampler) + return PA_RESAMPLER_INVALID; + + return pa_resampler_get_method(o->resampler); +} diff --git a/polyp/source-output.h b/polyp/source-output.h index 595c08706..0247a09a2 100644 --- a/polyp/source-output.h +++ b/polyp/source-output.h @@ -76,5 +76,6 @@ pa_usec_t pa_source_output_get_latency(struct pa_source_output *i); void pa_source_output_cork(struct pa_source_output *i, int b); +enum pa_resample_method pa_source_output_get_resample_method(struct pa_source_output *o); #endif diff --git a/polyp/util.c b/polyp/util.c index e8a47df0c..23515f033 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -530,23 +530,6 @@ const char *pa_strsignal(int sig) { } } -/* Parse a libsamplrate compatible resampling implementation */ -int pa_parse_resample_method(const char *string) { - assert(string); - - if (!strcmp(string, "sinc-best-quality")) - return SRC_SINC_BEST_QUALITY; - else if (!strcmp(string, "sinc-medium-quality")) - return SRC_SINC_MEDIUM_QUALITY; - else if (!strcmp(string, "sinc-fastest")) - return SRC_SINC_FASTEST; - else if (!strcmp(string, "zero-order-hold")) - return SRC_ZERO_ORDER_HOLD; - else if (!strcmp(string, "linear")) - return SRC_LINEAR; - else - return -1; -} /* Check whether the specified GID and the group name match */ static int is_group(gid_t gid, const char *name) { diff --git a/polyp/util.h b/polyp/util.h index f38e67391..f86c30cc3 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -72,8 +72,6 @@ char *pa_strip_nl(char *s); const char *pa_strsignal(int sig); -int pa_parse_resample_method(const char *string); - int pa_uid_in_group(const char *name, gid_t *gid); int pa_lock_fd(int fd, int b); From acc8b7890a0b3878b226f56454eeffc80843fdee Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 20 Nov 2004 22:17:31 +0000 Subject: [PATCH 0288/1514] option to use ALSA default fragment number and size git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@295 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 9 ++++----- polyp/alsa-util.c | 35 +++++++++++++++++++++++++++-------- polyp/alsa-util.h | 2 +- polyp/module-alsa-sink.c | 10 +++++----- polyp/module-alsa-source.c | 8 ++++---- 5 files changed, 41 insertions(+), 23 deletions(-) diff --git a/doc/todo b/doc/todo index 9898bc9df..c5f7dbba9 100644 --- a/doc/todo +++ b/doc/todo @@ -1,17 +1,16 @@ *** $Id$ *** *** 0.7 **** -- per-channel volume -- option to use default fragment size on alsa drivers -- improve module-oss-mmap latency measurement -- add radio module - make most buffer sizes dependant on the sample type - limit all resources - commenting -- module-tunnel: use latency interpolation - polish for starting polypaudio as root/system-wide instance ** later *** +- per-channel volume +- improve module-oss-mmap latency measurement +- module-tunnel: improve latency calculation +- add radio module - pass meta info for hearing impaired - add sync API - X11: support for the X11 synchronization extension diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index 188ba077f..eaa21d49c 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -30,8 +30,9 @@ #include "sample.h" #include "xmalloc.h" -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *buffer_size) { - int ret = 0; +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { + int ret = -1; + snd_pcm_uframes_t buffer_size; snd_pcm_hw_params_t *hwparams = NULL; static const snd_pcm_format_t format_trans[] = { [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8, @@ -42,21 +43,39 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE, [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE, }; - + assert(pcm_handle && ss && periods && period_size); + if (snd_pcm_hw_params_malloc(&hwparams) < 0 || snd_pcm_hw_params_any(pcm_handle, hwparams) < 0 || snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 || snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[ss->format]) < 0 || snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &ss->rate, NULL) < 0 || snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss->channels) < 0 || - snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, periods, NULL) < 0 || - snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, buffer_size) < 0 || - snd_pcm_hw_params(pcm_handle, hwparams) < 0) { - ret = -1; - } + (*periods > 0 && snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, periods, NULL) < 0) || + (*period_size > 0 && snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL) < 0) || + snd_pcm_hw_params(pcm_handle, hwparams) < 0) + goto finish; + + if (snd_pcm_prepare(pcm_handle) < 0) + goto finish; + if (snd_pcm_hw_params_current(pcm_handle, hwparams) < 0) + goto finish; + + if (snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size) < 0 || + snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL) < 0) + goto finish; + + assert(buffer_size > 0 && *period_size > 0); + *periods = buffer_size / *period_size; + assert(*periods > 0); + + ret = 0; + +finish: if (hwparams) snd_pcm_hw_params_free(hwparams); + return ret; } diff --git a/polyp/alsa-util.h b/polyp/alsa-util.h index 8add361f6..c058025f7 100644 --- a/polyp/alsa-util.h +++ b/polyp/alsa-util.h @@ -27,7 +27,7 @@ #include "sample.h" #include "mainloop-api.h" -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *buffer_size); +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api *m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata); void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_sources, unsigned n_io_sources); diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index a708329d2..d7a1cb53e 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -174,8 +174,8 @@ int pa__init(struct pa_core *c, struct pa_module*m) { struct userdata *u = NULL; const char *dev; struct pa_sample_spec ss; - unsigned periods, fragsize; - snd_pcm_uframes_t buffer_size; + uint32_t periods, fragsize; + snd_pcm_uframes_t period_size; size_t frame_size; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -196,7 +196,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { pa_log(__FILE__": failed to parse buffer metrics\n"); goto fail; } - buffer_size = fragsize/frame_size*periods; + period_size = fragsize; u = pa_xmalloc0(sizeof(struct userdata)); m->userdata = u; @@ -207,7 +207,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; } - if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &buffer_size) < 0) { + if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size) < 0) { pa_log(__FILE__": Failed to set hardware parameters\n"); goto fail; } @@ -226,7 +226,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { } u->frame_size = frame_size; - u->fragment_size = buffer_size*u->frame_size/periods; + u->fragment_size = period_size; pa_log(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index ba09d319d..56eb14556 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -166,7 +166,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { const char *dev; struct pa_sample_spec ss; unsigned periods, fragsize; - snd_pcm_uframes_t buffer_size; + snd_pcm_uframes_t period_size; size_t frame_size; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -187,7 +187,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { pa_log(__FILE__": failed to parse buffer metrics\n"); goto fail; } - buffer_size = fragsize/frame_size*periods; + period_size = fragsize; u = pa_xmalloc0(sizeof(struct userdata)); m->userdata = u; @@ -198,7 +198,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; } - if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &buffer_size) < 0) { + if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size) < 0) { pa_log(__FILE__": Failed to set hardware parameters\n"); goto fail; } @@ -217,7 +217,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { } u->frame_size = frame_size; - u->fragment_size = buffer_size*u->frame_size/periods; + u->fragment_size = period_size; pa_log(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); From 3c77c6e7d3f597400b3ae10dd1228aabf1ad6280 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 20 Nov 2004 23:48:18 +0000 Subject: [PATCH 0289/1514] * remove autospawn lock file usage * fix some compiler warnings * implement PID file support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@296 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 3 +- polyp/cmdline.c | 33 ++++++- polyp/daemon-conf.c | 6 +- polyp/daemon-conf.h | 7 +- polyp/main.c | 45 ++++++++- polyp/mainloop.c | 6 +- polyp/pid.c | 197 +++++++++++++++++++++++++++++++++++++++ polyp/pid.h | 30 ++++++ polyp/polyplib-context.c | 5 +- polyp/util.c | 39 +++++--- polyp/util.h | 2 +- 11 files changed, 342 insertions(+), 31 deletions(-) create mode 100644 polyp/pid.c create mode 100644 polyp/pid.h diff --git a/polyp/Makefile.am b/polyp/Makefile.am index dd7fb8b43..13ef893cd 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -211,7 +211,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ caps.h caps.c \ props.h props.c \ mcalign.c mcalign.h \ - g711.c g711.h + g711.c g711.h \ + pid.c pid.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_INCLUDES = $(INCLTDL) diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 0c381f8c4..cdf25638b 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -52,7 +52,10 @@ enum { ARG_LOAD, ARG_FILE, ARG_DL_SEARCH_PATH, - ARG_RESAMPLE_METHOD + ARG_RESAMPLE_METHOD, + ARG_KILL, + ARG_USE_PID_FILE, + ARG_CHECK }; static struct option long_options[] = { @@ -73,6 +76,9 @@ static struct option long_options[] = { {"file", 1, 0, ARG_FILE}, {"dl-search-path", 1, 0, ARG_DL_SEARCH_PATH}, {"resample-method", 1, 0, ARG_RESAMPLE_METHOD}, + {"kill", 0, 0, ARG_KILL}, + {"use-pid-file", 2, 0, ARG_USE_PID_FILE}, + {"check", 0, 0, ARG_CHECK}, {NULL, 0, 0, 0} }; @@ -88,7 +94,9 @@ void pa_cmdline_help(const char *argv0) { " -h, --help Show this help\n" " --version Show version\n" " --dump-conf Dump default configuration\n" - " --dump-modules Dump list of available modules\n\n" + " --dump-modules Dump list of available modules\n" + " -k --kill Kill a running daemon\n" + " --check Check for a running daemon\n\n" " -D, --daemonize[=BOOL] Daemonize after startup\n" " --fail[=BOOL] Quit when startup fails\n" @@ -100,7 +108,8 @@ void pa_cmdline_help(const char *argv0) { " --scache-idle-time=SECS Unload autoloaded samples when idle and this time passed\n" " --log-target={auto,syslog,stderr} Specify the log target\n" " -p, --dl-search-path=PATH Set the search path for dynamic shared objects (plugins)\n" - " --resample-method=[METHOD] Use the specified resampling method\n\n" + " --resample-method=[METHOD] Use the specified resampling method\n" + " --use-pid-file[=BOOL] Create a PID file\n\n" " -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with the specified argument\n" " -F, --file=FILENAME Run the specified script\n" @@ -119,7 +128,7 @@ int pa_cmdline_parse(struct pa_daemon_conf *conf, int argc, char *const argv [], if (conf->script_commands) pa_strbuf_puts(buf, conf->script_commands); - while ((c = getopt_long(argc, argv, "L:F:ChDnp:", long_options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "L:F:ChDnp:k", long_options, NULL)) != -1) { switch (c) { case ARG_HELP: case 'h': @@ -137,6 +146,15 @@ int pa_cmdline_parse(struct pa_daemon_conf *conf, int argc, char *const argv [], case ARG_DUMP_MODULES: conf->cmd = PA_CMD_DUMP_MODULES; break; + + case 'k': + case ARG_KILL: + conf->cmd = PA_CMD_KILL; + break; + + case ARG_CHECK: + conf->cmd = PA_CMD_CHECK; + break; case ARG_LOAD: case 'L': @@ -188,6 +206,13 @@ int pa_cmdline_parse(struct pa_daemon_conf *conf, int argc, char *const argv [], } break; + case ARG_USE_PID_FILE: + if ((conf->use_pid_file = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log(__FILE__": --use-pid-file expects boolean argument\n"); + goto fail; + } + break; + case 'p': case ARG_DL_SEARCH_PATH: pa_xfree(conf->dl_search_path); diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index 191e8d81e..9728019d3 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -66,6 +66,7 @@ static const struct pa_daemon_conf default_conf = { .log_target = PA_LOG_SYSLOG, .resample_method = PA_RESAMPLER_SRC_SINC_FASTEST, .config_file = NULL, + .use_pid_file = 1 }; struct pa_daemon_conf* pa_daemon_conf_new(void) { @@ -159,6 +160,7 @@ int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename) { { "default-script-file", pa_config_parse_string, NULL }, { "log-target", parse_log_target, NULL }, { "resample-method", parse_resample_method, NULL }, + { "use-pid-file", pa_config_parse_bool, NULL }, { NULL, NULL, NULL }, }; @@ -174,6 +176,7 @@ int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename) { table[9].data = &c->default_script_file; table[10].data = c; table[11].data = c; + table[12].data = &c->use_pid_file; pa_xfree(c->config_file); c->config_file = NULL; @@ -228,9 +231,8 @@ char *pa_daemon_conf_dump(struct pa_daemon_conf *c) { pa_strbuf_printf(s, "dl-search-path = %s\n", c->dl_search_path ? c->dl_search_path : ""); pa_strbuf_printf(s, "default-script-file = %s\n", c->default_script_file); pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); - - assert(c->resample_method <= 4 && c->resample_method >= 0); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); + pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file); return pa_strbuf_tostring_free(s); } diff --git a/polyp/daemon-conf.h b/polyp/daemon-conf.h index 9c2784855..8a5742727 100644 --- a/polyp/daemon-conf.h +++ b/polyp/daemon-conf.h @@ -29,7 +29,9 @@ enum pa_daemon_conf_cmd { PA_CMD_HELP, PA_CMD_VERSION, PA_CMD_DUMP_CONF, - PA_CMD_DUMP_MODULES + PA_CMD_DUMP_MODULES, + PA_CMD_KILL, + PA_CMD_CHECK }; struct pa_daemon_conf { @@ -42,7 +44,8 @@ struct pa_daemon_conf { exit_idle_time, module_idle_time, scache_idle_time, - auto_log_target; + auto_log_target, + use_pid_file; char *script_commands, *dl_search_path, *default_script_file; enum pa_log_target log_target; int resample_method; diff --git a/polyp/main.c b/polyp/main.c index 941bf9239..0ba28e5a3 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef HAVE_LIBWRAP #include @@ -54,6 +55,7 @@ #include "dumpmodules.h" #include "caps.h" #include "cli-text.h" +#include "pid.h" #ifdef HAVE_LIBWRAP /* Only one instance of these variables */ @@ -122,8 +124,7 @@ static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, } } - - static void close_pipe(int p[2]) { +static void close_pipe(int p[2]) { if (p[0] != -1) close(p[0]); if (p[1] != -1) @@ -142,6 +143,7 @@ int main(int argc, char *argv[]) { int daemon_pipe[2] = { -1, -1 }; gid_t gid = (gid_t) -1; int suid_root; + int valid_pid_file = 0; pa_limit_caps(); @@ -209,6 +211,30 @@ int main(int argc, char *argv[]) { retval = 0; goto finish; + case PA_CMD_CHECK: { + pid_t pid; + + if (pa_pid_file_check_running(&pid) < 0) { + if (conf->verbose) + pa_log(__FILE__": daemon not running\n"); + } else { + if (conf->verbose) + pa_log(__FILE__": daemon running as PID %u\n", pid); + retval = 0; + } + + goto finish; + + } + case PA_CMD_KILL: + + if (pa_pid_file_kill(SIGINT, NULL) < 0) + pa_log(__FILE__": failed to kill daemon.\n"); + else + retval = 0; + + goto finish; + default: assert(conf->cmd == PA_CMD_DAEMON); } @@ -260,11 +286,16 @@ int main(int argc, char *argv[]) { close(0); close(1); } - - chdir("/"); - pa_log(__FILE__": sizeof(pa_usec_t) = %u\n", sizeof(pa_usec_t)); + chdir("/"); + if (conf->use_pid_file) { + if (pa_pid_file_create() < 0) + goto finish; + + valid_pid_file = 1; + } + mainloop = pa_mainloop_new(); assert(mainloop); @@ -303,6 +334,7 @@ int main(int argc, char *argv[]) { if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); } else { + retval = 0; if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); @@ -332,6 +364,9 @@ finish: if (conf) pa_daemon_conf_free(conf); + if (valid_pid_file) + pa_pid_file_remove(); + close_pipe(daemon_pipe); lt_dlexit(); diff --git a/polyp/mainloop.c b/polyp/mainloop.c index f56614cec..d530419e7 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -614,7 +614,7 @@ void pa_mainloop_dump(struct pa_mainloop *m) { if (e->dead) continue; - pa_log(__FILE__": kind=io fd=%i events=%i callback=%p userdata=%p\n", e->fd, (int) e->events, e->callback, e->userdata); + pa_log(__FILE__": kind=io fd=%i events=%i callback=%p userdata=%p\n", e->fd, (int) e->events, (void*) e->callback, (void*) e->userdata); } } { @@ -624,7 +624,7 @@ void pa_mainloop_dump(struct pa_mainloop *m) { if (e->dead) continue; - pa_log(__FILE__": kind=defer enabled=%i callback=%p userdata=%p\n", e->enabled, e->callback, e->userdata); + pa_log(__FILE__": kind=defer enabled=%i callback=%p userdata=%p\n", e->enabled, (void*) e->callback, (void*) e->userdata); } } { @@ -634,7 +634,7 @@ void pa_mainloop_dump(struct pa_mainloop *m) { if (e->dead) continue; - pa_log(__FILE__": kind=time enabled=%i time=%u.%u callback=%p userdata=%p\n", e->enabled, e->timeval.tv_sec, e->timeval.tv_usec, e->callback, e->userdata); + pa_log(__FILE__": kind=time enabled=%i time=%lu.%lu callback=%p userdata=%p\n", e->enabled, (unsigned long) e->timeval.tv_sec, (unsigned long) e->timeval.tv_usec, (void*) e->callback, (void*) e->userdata); } } diff --git a/polyp/pid.c b/polyp/pid.c new file mode 100644 index 000000000..142c4f6d7 --- /dev/null +++ b/polyp/pid.c @@ -0,0 +1,197 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pid.h" +#include "util.h" +#include "log.h" + +static pid_t read_pid(const char *fn, int fd) { + ssize_t r; + char t[20], *e = NULL; + long int pid; + + assert(fn && fd >= 0); + + if ((r = pa_loop_read(fd, t, sizeof(t)-1)) < 0) { + pa_log(__FILE__": WARNING: failed to read PID file '%s': %s\n", fn, strerror(errno)); + return (pid_t) -1; + } + + if (r == 0) + return (pid_t) 0; + + t[r] = 0; + + if (!t[0] || (pid = strtol(t, &e, 0)) == 0 || (*e != 0 && *e != '\n')) { + pa_log(__FILE__": WARNING: failed to parse PID file '%s'\n", fn); + return (pid_t) -1; + } + + return (pid_t) pid; +} + +int pa_pid_file_create(void) { + int fd = -1, lock = -1; + int ret = -1; + char fn[PATH_MAX]; + char t[20]; + pid_t pid; + size_t l; + + pa_runtime_path("pid", fn, sizeof(fn)); + if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { + pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + lock = pa_lock_fd(fd, 1); + + if ((pid = read_pid(fn, fd)) == (pid_t) -1) + pa_log(__FILE__": corrupt PID file, overwriting.\n"); + else if (pid > 0) { + if (kill(pid, 0) >= 0 || errno != ESRCH) { + pa_log(__FILE__": valid PID file.\n"); + goto fail; + } + + pa_log(__FILE__": stale PID file, overwriting.\n"); + } + + lseek(fd, 0, SEEK_SET); + + snprintf(t, sizeof(t), "%lu", (unsigned long) getpid()); + l = strlen(t); + + if (pa_loop_write(fd, t, l) != (ssize_t) l) { + pa_log(__FILE__": failed to write PID file.\n"); + goto fail; + } + + ret = 0; + +fail: + if (fd >= 0) { + if (lock >= 0) + pa_lock_fd(fd, 0); + + close(fd); + } + + return ret; +} + +int pa_pid_file_remove(void) { + int fd = -1, lock = -1; + char fn[PATH_MAX]; + int ret = -1; + pid_t pid; + + pa_runtime_path("pid", fn, sizeof(fn)); + if ((fd = open(fn, O_RDWR)) < 0) { + pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + lock = pa_lock_fd(fd, 1); + + if ((pid = read_pid(fn, fd)) == (pid_t) -1) + goto fail; + + if (pid != getpid()) { + pa_log(__FILE__": WARNING: PID file '%s' not mine!\n", fn); + goto fail; + } + + if (ftruncate(fd, 0) < 0) { + pa_log(__FILE__": failed to truncate PID file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + if (unlink(fn) < 0) { + pa_log(__FILE__": failed to remove PID file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + ret = 0; + +fail: + + if (fd >= 0) { + if (lock >= 0) + pa_lock_fd(fd, 0); + + close(fd); + } + + return ret; +} + +int pa_pid_file_check_running(pid_t *pid) { + return pa_pid_file_kill(0, pid); +} + +int pa_pid_file_kill(int sig, pid_t *pid) { + int fd = -1, lock = -1; + char fn[PATH_MAX]; + int ret = -1; + pid_t _pid; + + if (!pid) + pid = &_pid; + + pa_runtime_path("pid", fn, sizeof(fn)); + if ((fd = open(fn, O_RDONLY)) < 0) + goto fail; + + lock = pa_lock_fd(fd, 1); + + if ((*pid = read_pid(fn, fd)) == (pid_t) -1) + goto fail; + + ret = kill(*pid, sig); + +fail: + + if (fd >= 0) { + if (lock >= 0) + pa_lock_fd(fd, 0); + + close(fd); + } + + return ret; + +} diff --git a/polyp/pid.h b/polyp/pid.h new file mode 100644 index 000000000..906ab6da8 --- /dev/null +++ b/polyp/pid.h @@ -0,0 +1,30 @@ +#ifndef foopidhfoo +#define foopidhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +int pa_pid_file_create(void); +int pa_pid_file_remove(void); +int pa_pid_file_check_running(pid_t *pid); +int pa_pid_file_kill(int sig, pid_t *pid); + +#endif diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 704295832..899a81765 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -67,7 +67,10 @@ static void unlock_autospawn_lock_file(struct pa_context *c) { assert(c); if (c->autospawn_lock_fd >= 0) { - pa_unlock_lockfile(c->autospawn_lock_fd); + char lf[PATH_MAX]; + pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); + + pa_unlock_lockfile(lf, c->autospawn_lock_fd); c->autospawn_lock_fd = -1; } } diff --git a/polyp/util.c b/polyp/util.c index 23515f033..2ad26c418 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -612,20 +612,27 @@ finish: /* Lock or unlock a file entirely. (advisory) */ int pa_lock_fd(int fd, int b) { - struct flock flock; + /* Try a R/W lock first */ + flock.l_type = b ? F_WRLCK : F_UNLCK; flock.l_whence = SEEK_SET; flock.l_start = 0; flock.l_len = 0; - if (fcntl(fd, F_SETLKW, &flock) < 0) { - pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno)); - return -1; - } + if (fcntl(fd, F_SETLKW, &flock) >= 0) + return 0; - return 0; + /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */ + if (b && errno == EBADF) { + flock.l_type = F_RDLCK; + if (fcntl(fd, F_SETLKW, &flock) >= 0) + return 0; + } + + pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno)); + return -1; } /* Remove trailing newlines from a string */ @@ -642,35 +649,43 @@ int pa_lock_lockfile(const char *fn) { assert(fn); if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": failed to create lock file '%s'\n", fn); + pa_log(__FILE__": failed to create lock file '%s': %s\n", fn, strerror(errno)); goto fail; } if (pa_lock_fd(fd, 1) < 0) + pa_log(__FILE__": failed to lock file '%s'.\n", fn); goto fail; return fd; fail: - if (fd >= 0) + if (fd >= 0) { + unlink(fn); close(fd); + } return -1; } /* Unlock a temporary lcok file */ -int pa_unlock_lockfile(int fd) { +int pa_unlock_lockfile(const char *fn, int fd) { int r = 0; - assert(fd >= 0); + assert(fn && fd >= 0); + if (unlink(fn) < 0) { + pa_log(__FILE__": WARNING: unable to remove lock file '%s': %s\n", fn, strerror(errno)); + r = -1; + } + if (pa_lock_fd(fd, 0) < 0) { - pa_log(__FILE__": WARNING: failed to unlock file.\n"); + pa_log(__FILE__": WARNING: failed to unlock file '%s'.\n", fn); r = -1; } if (close(fd) < 0) { - pa_log(__FILE__": WARNING: failed to close lock file.\n"); + pa_log(__FILE__": WARNING: failed to close lock file '%s': %s\n", fn, strerror(errno)); r = -1; } diff --git a/polyp/util.h b/polyp/util.h index f86c30cc3..ef7e4d96d 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -77,7 +77,7 @@ int pa_uid_in_group(const char *name, gid_t *gid); int pa_lock_fd(int fd, int b); int pa_lock_lockfile(const char *fn); -int pa_unlock_lockfile(int fd); +int pa_unlock_lockfile(const char *fn, int fd); FILE *pa_open_config_file(const char *env, const char *global, const char *local, char **result); From 6985eda9347730d4506de630c310a34e7844df0a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 00:04:17 +0000 Subject: [PATCH 0290/1514] * some minor pid file fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@297 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/pid.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/polyp/pid.c b/polyp/pid.c index 142c4f6d7..a52bed027 100644 --- a/polyp/pid.c +++ b/polyp/pid.c @@ -90,9 +90,12 @@ int pa_pid_file_create(void) { pa_log(__FILE__": stale PID file, overwriting.\n"); } - lseek(fd, 0, SEEK_SET); + if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) { + pa_log(__FILE__": failed to truncate PID fil: %s.\n", strerror(errno)); + goto fail; + } - snprintf(t, sizeof(t), "%lu", (unsigned long) getpid()); + snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid()); l = strlen(t); if (pa_loop_write(fd, t, l) != (ssize_t) l) { From fa751e537db75108f9a1597d83a4e1093173fc28 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 02:43:05 +0000 Subject: [PATCH 0291/1514] some commenting git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@298 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/alsa-util.c | 10 +++++++++- polyp/alsa-util.h | 2 +- polyp/caps.c | 4 ++-- polyp/dynarray.c | 6 +++++- polyp/dynarray.h | 12 ++++++++++++ polyp/hashmap.c | 15 ++++++++++----- polyp/hashmap.h | 9 +++++++++ polyp/idxset.h | 4 ++++ polyp/pid.c | 15 ++++++++++++++- polyp/queue.h | 6 ++++++ polyp/subscribe.c | 14 +++++++++++++- polyp/util.c | 5 +++-- 12 files changed, 88 insertions(+), 14 deletions(-) diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index eaa21d49c..52eaaed49 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -30,7 +30,9 @@ #include "sample.h" #include "xmalloc.h" -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { +/* Set the hardware parameters of the given ALSA device. Returns the + * selected fragment settings in *period/*period_size */ +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { int ret = -1; snd_pcm_uframes_t buffer_size; snd_pcm_hw_params_t *hwparams = NULL; @@ -79,6 +81,11 @@ finish: return ret; } +/* Allocate an IO event for every ALSA poll descriptor for the + * specified ALSA device. Return a pointer to such an array in + * *io_events. Store the length of that array in *n_io_events. Use the + * specified callback function and userdata. The array has to be freed + * with pa_free_io_events(). */ int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) { unsigned i; struct pollfd *pfds, *ppfd; @@ -106,6 +113,7 @@ int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, struct return 0; } +/* Free the memory allocated by pa_create_io_events() */ void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_events, unsigned n_io_events) { unsigned i; struct pa_io_event **ios; diff --git a/polyp/alsa-util.h b/polyp/alsa-util.h index c058025f7..adec143fd 100644 --- a/polyp/alsa-util.h +++ b/polyp/alsa-util.h @@ -27,7 +27,7 @@ #include "sample.h" #include "mainloop-api.h" -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api *m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata); void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_sources, unsigned n_io_sources); diff --git a/polyp/caps.c b/polyp/caps.c index d3719164a..e2f4573a7 100644 --- a/polyp/caps.c +++ b/polyp/caps.c @@ -42,7 +42,7 @@ void pa_drop_root(void) { if (uid == 0 || geteuid() != 0) return; - pa_log(__FILE__": dropping root rights.\n"); +/* pa_log(__FILE__": dropping root rights.\n"); */ setreuid(uid, uid); /* setuid(uid); @@ -68,7 +68,7 @@ int pa_limit_caps(void) { if (cap_set_proc(caps) < 0) goto fail; - pa_log(__FILE__": dropped capabilities successfully.\n"); +/* pa_log(__FILE__": dropped capabilities successfully.\n"); */ r = 0; diff --git a/polyp/dynarray.c b/polyp/dynarray.c index eb360b807..0e406ea1b 100644 --- a/polyp/dynarray.c +++ b/polyp/dynarray.c @@ -30,6 +30,9 @@ #include "dynarray.h" #include "xmalloc.h" +/* If the array becomes to small, increase its size by 100 entries */ +#define INCREASE_BY 100 + struct pa_dynarray { void **data; unsigned n_allocated, n_entries; @@ -66,7 +69,7 @@ void pa_dynarray_put(struct pa_dynarray*a, unsigned i, void *p) { if (!p) return; - n = i+100; + n = i+INCREASE_BY; a->data = pa_xrealloc(a->data, sizeof(void*)*n); memset(a->data+a->n_allocated, 0, sizeof(void*)*(n-a->n_allocated)); a->n_allocated = n; @@ -88,6 +91,7 @@ void *pa_dynarray_get(struct pa_dynarray*a, unsigned i) { assert(a); if (i >= a->n_allocated) return NULL; + assert(a->data); return a->data[i]; } diff --git a/polyp/dynarray.h b/polyp/dynarray.h index 2e9b72f6d..6733e9587 100644 --- a/polyp/dynarray.h +++ b/polyp/dynarray.h @@ -24,10 +24,22 @@ struct pa_dynarray; +/* Implementation of a simple dynamically sized array. The array + * expands if required, but doesn't shrink if possible. Memory + * management of the array's entries is the user's job. */ + struct pa_dynarray* pa_dynarray_new(void); + +/* Free the array calling the specified function for every entry in + * the array. The function may be NULL. */ void pa_dynarray_free(struct pa_dynarray* a, void (*func)(void *p, void *userdata), void *userdata); +/* Store p at position i in the array */ void pa_dynarray_put(struct pa_dynarray*a, unsigned i, void *p); + +/* Store p a the first free position in the array. Returns the index + * of that entry. If entries are removed from the array their position + * are not filled any more by this function. */ unsigned pa_dynarray_append(struct pa_dynarray*a, void *p); void *pa_dynarray_get(struct pa_dynarray*a, unsigned i); diff --git a/polyp/hashmap.c b/polyp/hashmap.c index 43e4456db..3b1265c95 100644 --- a/polyp/hashmap.c +++ b/polyp/hashmap.c @@ -32,6 +32,8 @@ #include "xmalloc.h" #include "log.h" +#define BUCKETS 1023 + struct hashmap_entry { struct hashmap_entry *next, *previous, *bucket_next, *bucket_previous; unsigned hash; @@ -52,7 +54,7 @@ struct pa_hashmap { struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { struct pa_hashmap *h; h = pa_xmalloc(sizeof(struct pa_hashmap)); - h->data = pa_xmalloc0(sizeof(struct hashmap_entry*)*(h->size = 1023)); + h->data = pa_xmalloc0(sizeof(struct hashmap_entry*)*(h->size = BUCKETS)); h->first_entry = NULL; h->n_entries = 0; h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; @@ -74,8 +76,10 @@ static void remove(struct pa_hashmap *h, struct hashmap_entry *e) { e->bucket_next->bucket_previous = e->bucket_previous; if (e->bucket_previous) e->bucket_previous->bucket_next = e->bucket_next; - else + else { + assert(e->hash < h->size); h->data[e->hash] = e->bucket_next; + } pa_xfree(e); h->n_entries--; @@ -96,6 +100,7 @@ void pa_hashmap_free(struct pa_hashmap*h, void (*free_func)(void *p, void *userd static struct hashmap_entry *get(struct pa_hashmap *h, unsigned hash, const void *key) { struct hashmap_entry *e; + assert(h && hash < h->size); for (e = h->data[hash]; e; e = e->bucket_next) if (h->compare_func(e->key, key) == 0) @@ -107,7 +112,7 @@ static struct hashmap_entry *get(struct pa_hashmap *h, unsigned hash, const void int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value) { struct hashmap_entry *e; unsigned hash; - assert(h && key); + assert(h); hash = h->hash_func(key) % h->size; @@ -171,9 +176,9 @@ unsigned pa_hashmap_ncontents(struct pa_hashmap *h) { void *pa_hashmap_iterate(struct pa_hashmap *h, void **state, const void **key) { assert(h && state); - if (!*state) { + if (!*state) *state = h->first_entry; - } else + else *state = ((struct hashmap_entry*) *state)->next; if (!*state) { diff --git a/polyp/hashmap.h b/polyp/hashmap.h index f858c3550..d55834c1a 100644 --- a/polyp/hashmap.h +++ b/polyp/hashmap.h @@ -22,14 +22,23 @@ USA. ***/ +/* Simple Implementation of a hash table. Memory management is the + * user's job. It's a good idea to have the key pointer point to a + * string in the value data. */ + struct pa_hashmap; +/* Create a new hashmap. Use the specified functions for hashing and comparing objects in the map */ struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); + +/* Free the hash table. Calls the specified function for every value in the table. The function may be NULL */ void pa_hashmap_free(struct pa_hashmap*, void (*free_func)(void *p, void *userdata), void *userdata); +/* Returns non-zero when the entry already exists */ int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value); void* pa_hashmap_get(struct pa_hashmap *h, const void *key); +/* Returns the data of the entry while removing */ void* pa_hashmap_remove(struct pa_hashmap *h, const void *key); unsigned pa_hashmap_ncontents(struct pa_hashmap *h); diff --git a/polyp/idxset.h b/polyp/idxset.h index 1ed661545..66689fd42 100644 --- a/polyp/idxset.h +++ b/polyp/idxset.h @@ -24,6 +24,10 @@ #include +/* A combination of a hashtable and a dynamic array. Entries are both + * indexiable through a numeric automaticly generated index and an + * opaque key. As usual, memory management is the user's job. */ + #define PA_IDXSET_INVALID ((uint32_t) -1) unsigned pa_idxset_trivial_hash_func(const void *p); diff --git a/polyp/pid.c b/polyp/pid.c index a52bed027..37a769846 100644 --- a/polyp/pid.c +++ b/polyp/pid.c @@ -38,6 +38,8 @@ #include "util.h" #include "log.h" +/* Read the PID data from the file descriptor fd, and return it. If no + * pid could be read, return 0, on failure (pid_t) -1 */ static pid_t read_pid(const char *fn, int fd) { ssize_t r; char t[20], *e = NULL; @@ -63,6 +65,7 @@ static pid_t read_pid(const char *fn, int fd) { return (pid_t) pid; } +/* Create a new PID file for the current process. */ int pa_pid_file_create(void) { int fd = -1, lock = -1; int ret = -1; @@ -77,19 +80,21 @@ int pa_pid_file_create(void) { goto fail; } + /* Try to lock the file. If that fails, go without */ lock = pa_lock_fd(fd, 1); if ((pid = read_pid(fn, fd)) == (pid_t) -1) pa_log(__FILE__": corrupt PID file, overwriting.\n"); else if (pid > 0) { if (kill(pid, 0) >= 0 || errno != ESRCH) { - pa_log(__FILE__": valid PID file.\n"); + pa_log(__FILE__": daemon already running.\n"); goto fail; } pa_log(__FILE__": stale PID file, overwriting.\n"); } + /* Overwrite the current PID file */ if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) { pa_log(__FILE__": failed to truncate PID fil: %s.\n", strerror(errno)); goto fail; @@ -116,6 +121,7 @@ fail: return ret; } +/* Remove the PID file, if it is ours */ int pa_pid_file_remove(void) { int fd = -1, lock = -1; char fn[PATH_MAX]; @@ -162,10 +168,17 @@ fail: return ret; } +/* Check whether the daemon is currently running, i.e. if a PID file + * exists and the PID therein too. Returns 0 on succcess, -1 + * otherwise. If pid is non-NULL and a running daemon was found, + * return its PID therein */ int pa_pid_file_check_running(pid_t *pid) { return pa_pid_file_kill(0, pid); } +/* Kill a current running daemon. Return non-zero on success, -1 + * otherwise. If successful *pid contains the PID of the daemon + * process. */ int pa_pid_file_kill(int sig, pid_t *pid) { int fd = -1, lock = -1; char fn[PATH_MAX]; diff --git a/polyp/queue.h b/polyp/queue.h index 0b72f37d5..a739ab74c 100644 --- a/polyp/queue.h +++ b/polyp/queue.h @@ -24,8 +24,14 @@ struct pa_queue; +/* A simple implementation of the abstract data type queue. Stores + * pointers as members. The memory has to be managed by the caller. */ + struct pa_queue* pa_queue_new(void); + +/* Free the queue and run the specified callback function for every remaining entry. The callback function may be NULL. */ void pa_queue_free(struct pa_queue* q, void (*destroy)(void *p, void *userdata), void *userdata); + void pa_queue_push(struct pa_queue *q, void *p); void* pa_queue_pop(struct pa_queue *q); diff --git a/polyp/subscribe.c b/polyp/subscribe.c index b552e4d01..ee6ef3aa0 100644 --- a/polyp/subscribe.c +++ b/polyp/subscribe.c @@ -31,6 +31,13 @@ #include "xmalloc.h" #include "log.h" +/* The subscription subsystem may be used to be notified whenever an + * entity (sink, source, ...) is created or deleted. Modules may + * register a callback function that is called whenever an event + * matching a subscription mask happens. The execution of the callback + * function is postponed to the next main loop iteration, i.e. is not + * called from within the stack frame the entity was created in. */ + struct pa_subscription { struct pa_core *core; int dead; @@ -48,6 +55,7 @@ struct pa_subscription_event { static void sched_event(struct pa_core *c); +/* Allocate a new subscription object for the given subscription mask. Use the specified callback function and user data */ struct pa_subscription* pa_subscription_new(struct pa_core *c, enum pa_subscription_mask m, void (*callback)(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { struct pa_subscription *s; assert(c); @@ -66,6 +74,7 @@ struct pa_subscription* pa_subscription_new(struct pa_core *c, enum pa_subscript return s; } +/* Free a subscription object, effectively marking it for deletion */ void pa_subscription_free(struct pa_subscription*s) { assert(s && !s->dead); s->dead = 1; @@ -86,6 +95,7 @@ static void free_item(struct pa_subscription *s) { pa_xfree(s); } +/* Free all subscription objects */ void pa_subscription_free_all(struct pa_core *c) { struct pa_subscription_event *e; assert(c); @@ -150,6 +160,7 @@ void pa_subscription_free_all(struct pa_core *c) { pa_log(__FILE__": %u\n", e->index); }*/ +/* Deferred callback for dispatching subscirption events */ static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { struct pa_core *c = userdata; struct pa_subscription *s; @@ -187,6 +198,7 @@ static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void * } } +/* Schedule an mainloop event so that a pending subscription event is dispatched */ static void sched_event(struct pa_core *c) { assert(c); @@ -198,7 +210,7 @@ static void sched_event(struct pa_core *c) { c->mainloop->defer_enable(c->subscription_defer_event, 1); } - +/* Append a new subscription event to the subscription event queue and schedule a main loop event */ void pa_subscription_post(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index) { struct pa_subscription_event *e; assert(c); diff --git a/polyp/util.c b/polyp/util.c index 2ad26c418..b01b80a15 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -384,7 +384,8 @@ void pa_raise_priority(void) { if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) pa_log(__FILE__": setpriority() failed: %s\n", strerror(errno)); - else pa_log(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); +/* else */ +/* pa_log(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); */ #ifdef _POSIX_PRIORITY_SCHEDULING { @@ -401,7 +402,7 @@ void pa_raise_priority(void) { return; } - pa_log(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); +/* pa_log(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); */ } #endif } From f2b11dbef8bb638ff57baf3225864ed732164fe7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 13:18:56 +0000 Subject: [PATCH 0292/1514] * PID and lock file fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@299 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/pid.c | 97 +++++++++++++++++++++++++++++++++++++--------------- polyp/util.c | 48 +++++++++++++++++++------- 2 files changed, 105 insertions(+), 40 deletions(-) diff --git a/polyp/pid.c b/polyp/pid.c index 37a769846..232de216e 100644 --- a/polyp/pid.c +++ b/polyp/pid.c @@ -65,9 +65,62 @@ static pid_t read_pid(const char *fn, int fd) { return (pid_t) pid; } +static int open_pid_file(const char *fn, int mode) { + int fd = -1; + int lock = -1; + + for (;;) { + struct stat st; + + pa_make_secure_parent_dir(fn); + + if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) { + if (mode != O_RDONLY || errno != ENOENT) + pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + /* Try to lock the file. If that fails, go without */ + if (pa_lock_fd(fd, 1) < 0) + goto fail; + + if (fstat(fd, &st) < 0) { + pa_log(__FILE__": Failed to fstat() PID file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + /* Does the file still exist in the file system? When ye, w're done, otherwise restart */ + if (st.st_nlink >= 1) + break; + + if (pa_lock_fd(fd, 0) < 0) + goto fail; + + if (close(fd) < 0) { + pa_log(__FILE__": Failed to close file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + fd = -1; + } + + return fd; + +fail: + + if (fd < 0) { + if (lock >= 0) + pa_lock_fd(fd, 0); + + close(fd); + } + + return -1; +} + /* Create a new PID file for the current process. */ int pa_pid_file_create(void) { - int fd = -1, lock = -1; + int fd = -1; int ret = -1; char fn[PATH_MAX]; char t[20]; @@ -75,13 +128,9 @@ int pa_pid_file_create(void) { size_t l; pa_runtime_path("pid", fn, sizeof(fn)); - if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno)); - goto fail; - } - /* Try to lock the file. If that fails, go without */ - lock = pa_lock_fd(fd, 1); + if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0) + goto fail; if ((pid = read_pid(fn, fd)) == (pid_t) -1) pa_log(__FILE__": corrupt PID file, overwriting.\n"); @@ -112,9 +161,7 @@ int pa_pid_file_create(void) { fail: if (fd >= 0) { - if (lock >= 0) - pa_lock_fd(fd, 0); - + pa_lock_fd(fd, 0); close(fd); } @@ -123,19 +170,18 @@ fail: /* Remove the PID file, if it is ours */ int pa_pid_file_remove(void) { - int fd = -1, lock = -1; + int fd = -1; char fn[PATH_MAX]; int ret = -1; pid_t pid; pa_runtime_path("pid", fn, sizeof(fn)); - if ((fd = open(fn, O_RDWR)) < 0) { + + if ((fd = open_pid_file(fn, O_RDWR)) < 0) { pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno)); goto fail; } - lock = pa_lock_fd(fd, 1); - if ((pid = read_pid(fn, fd)) == (pid_t) -1) goto fail; @@ -159,9 +205,7 @@ int pa_pid_file_remove(void) { fail: if (fd >= 0) { - if (lock >= 0) - pa_lock_fd(fd, 0); - + pa_lock_fd(fd, 0); close(fd); } @@ -180,31 +224,28 @@ int pa_pid_file_check_running(pid_t *pid) { * otherwise. If successful *pid contains the PID of the daemon * process. */ int pa_pid_file_kill(int sig, pid_t *pid) { - int fd = -1, lock = -1; + int fd = -1; char fn[PATH_MAX]; int ret = -1; pid_t _pid; if (!pid) pid = &_pid; - + pa_runtime_path("pid", fn, sizeof(fn)); - if ((fd = open(fn, O_RDONLY)) < 0) + + if ((fd = open_pid_file(fn, O_RDONLY)) < 0) goto fail; - - lock = pa_lock_fd(fd, 1); - + if ((*pid = read_pid(fn, fd)) == (pid_t) -1) goto fail; - + ret = kill(*pid, sig); fail: - + if (fd >= 0) { - if (lock >= 0) - pa_lock_fd(fd, 0); - + pa_lock_fd(fd, 0); close(fd); } diff --git a/polyp/util.c b/polyp/util.c index b01b80a15..87beafb33 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -646,26 +646,50 @@ char* pa_strip_nl(char *s) { /* Create a temporary lock file and lock it. */ int pa_lock_lockfile(const char *fn) { - int fd; + int fd = -1; assert(fn); - if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": failed to create lock file '%s': %s\n", fn, strerror(errno)); - goto fail; + for (;;) { + struct stat st; + + if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { + pa_log(__FILE__": failed to create lock file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + if (pa_lock_fd(fd, 1) < 0) { + pa_log(__FILE__": failed to lock file '%s'.\n", fn); + goto fail; + } + + if (fstat(fd, &st) < 0) { + pa_log(__FILE__": failed to fstat() file '%s'.\n", fn); + goto fail; + } + + /* Check wheter the file has been removed meanwhile. When yes, restart this loop, otherwise, we're done */ + if (st.st_nlink >= 1) + break; + + if (pa_lock_fd(fd, 0) < 0) { + pa_log(__FILE__": failed to unlock file '%s'.\n", fn); + goto fail; + } + + if (close(fd) < 0) { + pa_log(__FILE__": failed to close file '%s'.\n", fn); + goto fail; + } + + fd = -1; } - - if (pa_lock_fd(fd, 1) < 0) - pa_log(__FILE__": failed to lock file '%s'.\n", fn); - goto fail; - + return fd; fail: - if (fd >= 0) { - unlink(fn); + if (fd >= 0) close(fd); - } return -1; } From 92f73a741f7d439263857ea5c438a612ce24b03d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 15:22:59 +0000 Subject: [PATCH 0293/1514] * fix the trivial resampler git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@300 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- polyp/resampler.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/todo b/doc/todo index c5f7dbba9..d55145049 100644 --- a/doc/todo +++ b/doc/todo @@ -4,9 +4,9 @@ - make most buffer sizes dependant on the sample type - limit all resources - commenting -- polish for starting polypaudio as root/system-wide instance ** later *** +- polish for starting polypaudio as root/system-wide instance - per-channel volume - improve module-oss-mmap latency measurement - module-tunnel: improve latency calculation diff --git a/polyp/resampler.c b/polyp/resampler.c index 6cf51dab5..dbd748f7e 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -310,7 +310,7 @@ fail: static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out) { size_t fz; - unsigned nsamples; + unsigned nframes; struct impl_trivial *i; assert(r && in && out && r->impl_data); i = r->impl_data; @@ -318,22 +318,22 @@ static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, st fz = r->i_fz; assert(fz == r->o_fz); - nsamples = in->length/fz; + nframes = in->length/fz; if (r->i_ss.rate == r->o_ss.rate) { /* In case there's no diefference in sample types, do nothing */ *out = *in; - pa_memblock_ref(in->memblock); + pa_memblock_ref(out->memblock); - i->o_counter += nsamples; + i->o_counter += nframes; } else { /* Do real resampling */ size_t l; unsigned o_index; /* The length of the new memory block rounded up */ - l = ((nsamples * r->o_ss.rate + r->i_ss.rate - 1) / r->i_ss.rate) * fz; + l = ((nframes * r->o_ss.rate + r->i_ss.rate - 1) / r->i_ss.rate) * fz; out->index = 0; out->memblock = pa_memblock_new(l, r->memblock_stat); @@ -345,13 +345,13 @@ static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, st assert(j >= i->i_counter); j = j - i->i_counter; - if (j >= nsamples) + if (j >= nframes) break; assert(o_index*fz < out->memblock->length); memcpy((uint8_t*) out->memblock->data + fz*o_index, - (uint8_t*) in->memblock->data + fz*j, fz); + (uint8_t*) in->memblock->data + in->index + fz*j, fz); } @@ -362,7 +362,7 @@ static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, st while (i->o_counter >= r->o_ss.rate) i->o_counter -= r->o_ss.rate; - i->i_counter += nsamples; + i->i_counter += nframes; while (i->i_counter >= r->i_ss.rate) i->i_counter -= r->i_ss.rate; From 966c78ccae42f6632c742d9369aba53c11b10875 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 16:27:51 +0000 Subject: [PATCH 0294/1514] fixes for bugs found when compiling with gcc 2.95 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@301 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/alsa-util.c | 2 +- polyp/client-conf.c | 3 --- polyp/resampler.c | 2 +- polyp/strlist-test.c | 2 ++ polyp/util.c | 2 -- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index 52eaaed49..b6b9ac11c 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -31,7 +31,7 @@ #include "xmalloc.h" /* Set the hardware parameters of the given ALSA device. Returns the - * selected fragment settings in *period/*period_size */ + * selected fragment settings in *period and *period_size */ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { int ret = -1; snd_pcm_uframes_t buffer_size; diff --git a/polyp/client-conf.c b/polyp/client-conf.c index 2de1c57fb..21e0acab5 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -59,12 +59,9 @@ static const struct pa_client_conf default_conf = { struct pa_client_conf *pa_client_conf_new(void) { struct pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); - - c->daemon_binary = pa_xstrdup(POLYPAUDIO_BINARY); c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5"); - c->cookie_file = pa_xstrdup(PA_NATIVE_COOKIE_FILE); return c; diff --git a/polyp/resampler.c b/polyp/resampler.c index dbd748f7e..377aa7975 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -397,7 +397,7 @@ static int trivial_init(struct pa_resampler*r) { } const char *pa_resample_method_to_string(enum pa_resample_method m) { - static const char const* resample_methods[] = { + static const char * const resample_methods[] = { "src-sinc-best-quality", "src-sinc-medium-quality", "src-sinc-fastest", diff --git a/polyp/strlist-test.c b/polyp/strlist-test.c index 01dcdf127..b68a04154 100644 --- a/polyp/strlist-test.c +++ b/polyp/strlist-test.c @@ -36,4 +36,6 @@ int main(int argc, char* argv[]) { pa_xfree(t); pa_strlist_free(l); + + return 0; } diff --git a/polyp/util.c b/polyp/util.c index 87beafb33..0b459ddc2 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -225,8 +225,6 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) { for(;;) { int r; - va_list ap; - c = pa_xrealloc(c, size); r = vsnprintf(c, size, format, ap); From b03f39099f27d99158d881419ed65060d5be5643 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 17:02:25 +0000 Subject: [PATCH 0295/1514] * add some missing "static"s * include libltdl in distribution git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@302 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- bootstrap.sh | 2 +- configure.ac | 5 ++++- polyp/Makefile.am | 4 ++-- polyp/daemon-conf.c | 4 ++-- polyp/mainloop.c | 2 +- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Makefile.am b/Makefile.am index 04c8f2cf7..9b419d1d9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # USA. EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in -SUBDIRS=polyp doc +SUBDIRS=polyp doc libltdl MAINTAINERCLEANFILES=README noinst_DATA = README diff --git a/bootstrap.sh b/bootstrap.sh index 7dc081aea..4b9032b64 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -36,7 +36,7 @@ else rm -f config.cache run_versioned aclocal 1.7 - libtoolize -c --force + libtoolize -c --force --ltdl autoheader run_versioned automake 1.7 -a -c --foreign autoconf -Wall diff --git a/configure.ac b/configure.ac index 455334117..0a1ebd05e 100644 --- a/configure.ac +++ b/configure.ac @@ -37,11 +37,14 @@ fi # Checks for programs. AC_PROG_CC + +# libtool stuff AC_LIBLTDL_INSTALLABLE -AC_SUBST(INCLTDL) +AC_SUBST(LTDLINCL) AC_SUBST(LIBLTDL) AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL +AC_CONFIG_SUBDIRS(libltdl) # Checks for header files. AC_HEADER_STDC diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 13ef893cd..6d9962d50 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -215,9 +215,9 @@ polypaudio_SOURCES = idxset.c idxset.h \ pid.c pid.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -polypaudio_INCLUDES = $(INCLTDL) +polypaudio_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL) polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) -polypaudio_LDFLAGS= -export-dynamic -dlopen force #-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f)) +polypaudio_LDFLAGS= $(AM_LDFLAGS) -export-dynamic -dlopen force #-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f)) libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index 9728019d3..7753da6af 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -119,7 +119,7 @@ int pa_daemon_conf_set_resample_method(struct pa_daemon_conf *c, const char *str return 0; } -int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { struct pa_daemon_conf *c = data; assert(filename && lvalue && rvalue && data); @@ -131,7 +131,7 @@ int parse_log_target(const char *filename, unsigned line, const char *lvalue, co return 0; } -int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { struct pa_daemon_conf *c = data; assert(filename && lvalue && rvalue && data); diff --git a/polyp/mainloop.c b/polyp/mainloop.c index d530419e7..f6bb4145a 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -130,7 +130,7 @@ static void mainloop_io_set_destroy(struct pa_io_event *e, void (*callback)(stru } /* Defer events */ -struct pa_defer_event* mainloop_defer_new(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata), void *userdata) { +static struct pa_defer_event* mainloop_defer_new(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata), void *userdata) { struct pa_mainloop *m; struct pa_defer_event *e; From c90409e4b74d1a4a405bdf560f280694b3e0bb29 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 17:06:59 +0000 Subject: [PATCH 0296/1514] bump version number git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@303 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 0a1ebd05e..332570dd7 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.6],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.7],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) @@ -28,7 +28,7 @@ AM_INIT_AUTOMAKE([foreign -Wall]) AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) -AC_SUBST(PA_API_VERSION, 6) +AC_SUBST(PA_API_VERSION, 7) if type -p stow > /dev/null && test -d /usr/local/stow ; then AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) From 28d97441e7c88441c4fbc77458932af7fd61a59c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 18:15:33 +0000 Subject: [PATCH 0297/1514] * new tool pacmd * fix pacat/paplay/pactl for new API version * fix memory leak in pa_ioline git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@304 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 13 +++- polyp/ioline.c | 9 +++ polyp/pacat.c | 2 +- polyp/pacmd.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++ polyp/pactl.c | 2 +- polyp/paplay.c | 2 +- polyp/util.c | 9 +++ polyp/util.h | 2 + 8 files changed, 218 insertions(+), 4 deletions(-) create mode 100644 polyp/pacmd.c diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 6d9962d50..2570f7f02 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -34,8 +34,15 @@ AM_LIBADD=$(PTHREAD_LIBS) -lm AM_LDADD=$(PTHREAD_LIBS) -lm EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in module-defs.h.m4 -bin_PROGRAMS = polypaudio pacat pactl paplay +bin_PROGRAMS = \ + polypaudio \ + pacat \ + pactl \ + paplay \ + pacmd + bin_SCRIPTS = esdcompat.sh + noinst_PROGRAMS = \ mainloop-test \ pacat-simple \ @@ -505,6 +512,10 @@ mcalign_test_SOURCES = mcalign-test.c util.c util.h xmalloc.c xmalloc.h log.c lo mcalign_test_CFLAGS = $(AM_CFLAGS) mcalign_test_LDADD = $(AM_LDADD) +pacmd_SOURCES = pacmd.c util.c util.h xmalloc.c xmalloc.h log.c log.h pid.c pid.h +pacmd_CFLAGS = $(AM_CFLAGS) +pacmd_LDADD = $(AM_LDADD) + cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h cpulimit_test_CFLAGS = $(AM_CFLAGS) cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la diff --git a/polyp/ioline.c b/polyp/ioline.c index 059591b85..f52af2db9 100644 --- a/polyp/ioline.c +++ b/polyp/ioline.c @@ -89,6 +89,10 @@ static void ioline_free(struct pa_ioline *l) { if (l->io) pa_iochannel_free(l->io); + + if (l->defer_event) + l->mainloop->defer_free(l->defer_event); + pa_xfree(l->wbuf); pa_xfree(l->rbuf); pa_xfree(l); @@ -116,6 +120,11 @@ void pa_ioline_close(struct pa_ioline *l) { pa_iochannel_free(l->io); l->io = NULL; } + + if (l->defer_event) { + l->mainloop->defer_free(l->defer_event); + l->defer_event = NULL; + } } void pa_ioline_puts(struct pa_ioline *l, const char *c) { diff --git a/polyp/pacat.c b/polyp/pacat.c index e5e0b7cac..8c3ee0ba8 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -38,7 +38,7 @@ #include #include -#if PA_API_VERSION != 6 +#if PA_API_VERSION != 7 #error Invalid Polypaudio API version #endif diff --git a/polyp/pacmd.c b/polyp/pacmd.c new file mode 100644 index 000000000..741059ce3 --- /dev/null +++ b/polyp/pacmd.c @@ -0,0 +1,183 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "log.h" +#include "pid.h" + +int main() { + pid_t pid ; + int fd = -1; + int ret = 1, i; + struct sockaddr_un sa; + char ibuf[256], obuf[256]; + size_t ibuf_index, ibuf_length, obuf_index, obuf_length; + fd_set ifds, ofds; + + if (pa_pid_file_check_running(&pid) < 0) { + pa_log(__FILE__": no Polypaudio daemon running\n"); + goto fail; + } + + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { + pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s\n", strerror(errno)); + goto fail; + } + + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; + pa_runtime_path("cli", sa.sun_path, sizeof(sa.sun_path)); + + for (i = 0; i < 5; i++) { + int r; + + if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { + pa_log(__FILE__": connect() failed: %s\n", strerror(errno)); + goto fail; + } + + if (r >= 0) + break; + + if (pa_pid_file_kill(SIGUSR2, NULL) < 0) { + pa_log(__FILE__": failed to kill Polypaudio daemon.\n"); + goto fail; + } + + pa_msleep(10); + } + + if (i >= 5) { + pa_log(__FILE__": daemon to responding.\n"); + goto fail; + } + + ibuf_index = ibuf_length = obuf_index = obuf_length = 0; + + + FD_ZERO(&ifds); + FD_SET(0, &ifds); + FD_SET(fd, &ifds); + + FD_ZERO(&ofds); + + for (;;) { + if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { + pa_log(__FILE__": select() failed: %s\n", strerror(errno)); + goto fail; + } + + if (FD_ISSET(0, &ifds)) { + ssize_t r; + assert(!ibuf_length); + + if ((r = read(0, ibuf, sizeof(ibuf))) <= 0) { + if (r == 0) + break; + + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + goto fail; + } + + ibuf_length = (size_t) r; + ibuf_index = 0; + } + + if (FD_ISSET(fd, &ifds)) { + ssize_t r; + assert(!obuf_length); + + if ((r = read(fd, obuf, sizeof(obuf))) <= 0) { + if (r == 0) + break; + + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + goto fail; + } + + obuf_length = (size_t) r; + obuf_index = 0; + } + + if (FD_ISSET(1, &ofds)) { + ssize_t r; + assert(obuf_length); + + if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + goto fail; + } + + obuf_length -= (size_t) r; + obuf_index += obuf_index; + + } + + if (FD_ISSET(fd, &ofds)) { + ssize_t r; + assert(ibuf_length); + + if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + goto fail; + } + + ibuf_length -= (size_t) r; + ibuf_index += obuf_index; + + } + + FD_ZERO(&ifds); + FD_ZERO(&ofds); + + if (obuf_length <= 0) + FD_SET(fd, &ifds); + else + FD_SET(1, &ofds); + + if (ibuf_length <= 0) + FD_SET(0, &ifds); + else + FD_SET(fd, &ofds); + } + + + ret = 0; + +fail: + if (fd >= 0) + close(fd); + + return ret; +} diff --git a/polyp/pactl.c b/polyp/pactl.c index d73f703ca..6300b6562 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -41,7 +41,7 @@ #include #include -#if PA_API_VERSION != 6 +#if PA_API_VERSION != 7 #error Invalid Polypaudio API version #endif diff --git a/polyp/paplay.c b/polyp/paplay.c index 418d40b3a..0faa0ff24 100644 --- a/polyp/paplay.c +++ b/polyp/paplay.c @@ -40,7 +40,7 @@ #include #include -#if PA_API_VERSION != 6 +#if PA_API_VERSION != 7 #error Invalid Polypaudio API version #endif diff --git a/polyp/util.c b/polyp/util.c index 0b459ddc2..970ebb93e 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -861,3 +861,12 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) { snprintf(s, l, PA_RUNTIME_PATH_PREFIX"%s%s%s", pa_get_user_name(u, sizeof(u)), fn ? "/" : "", fn ? fn : ""); return s; } + +int pa_msleep(unsigned long t) { + struct timespec ts; + + ts.tv_sec = t/1000; + ts.tv_nsec = (t % 1000) * 1000000; + + return nanosleep(&ts, NULL); +} diff --git a/polyp/util.h b/polyp/util.h index ef7e4d96d..922aa49ef 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -88,4 +88,6 @@ int pa_startswith(const char *s, const char *pfx); char *pa_runtime_path(const char *fn, char *s, size_t l); +int pa_msleep(unsigned long t); + #endif From 4583c22bfd490e2cdc7ebb151a566c85987bd791 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 18:41:00 +0000 Subject: [PATCH 0298/1514] * create parec as link to pacat git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@305 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 2570f7f02..1bae9afcd 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -731,6 +731,7 @@ daemon.conf: daemon.conf.in Makefile install-exec-hook: chown root $(DESTDIR)$(bindir)/polypaudio chmod u+s $(DESTDIR)$(bindir)/polypaudio + ln -s pacat $(DESTDIR)$(bindir)/parec $(SYMDEF_FILES): module-defs.h.m4 $(M4) -Dfname="$@" $< > $@ From d45abba9aa4090ebeaf09ec9ec324709e04a1bbf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 19:39:46 +0000 Subject: [PATCH 0299/1514] calculate buffer sizes from sample spec git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@306 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/memblockq.c | 11 +++++++---- polyp/polyplib-internal.h | 6 ------ polyp/polyplib-stream.c | 11 ++++++----- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/polyp/memblockq.c b/polyp/memblockq.c index ff16f6279..16c0da8e3 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -68,18 +68,21 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b bq->tlength = ((tlength+base-1)/base)*base; if (!bq->tlength || bq->tlength >= bq->maxlength) bq->tlength = bq->maxlength; + + bq->minreq = (minreq/base)*base; + if (bq->minreq == 0) + bq->minreq = 1; bq->prebuf = (prebuf == (size_t) -1) ? bq->maxlength/2 : prebuf; bq->prebuf = (bq->prebuf/base)*base; if (bq->prebuf > bq->maxlength) bq->prebuf = bq->maxlength; + if (bq->prebuf > bq->tlength - bq->minreq) + bq->prebuf = bq->tlength - bq->minreq; + bq->orig_prebuf = bq->prebuf; - bq->minreq = (minreq/base)*base; - if (bq->minreq == 0) - bq->minreq = 1; - pa_log(__FILE__": memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); bq->mcalign = NULL; diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 4289b3c87..d1b3a27f0 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -37,12 +37,6 @@ #include "strlist.h" #include "mcalign.h" -#define DEFAULT_TLENGTH (44100*2*2/2) //(10240*8) -#define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) -#define DEFAULT_MINREQ 512 -#define DEFAULT_PREBUF (DEFAULT_TLENGTH-DEFAULT_MINREQ) -#define DEFAULT_FRAGSIZE 1024 - #define DEFAULT_TIMEOUT (10) struct pa_context { diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index b3f1f8cd7..440217e7b 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -283,11 +283,12 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ if (attr) s->buffer_attr = *attr; else { - s->buffer_attr.maxlength = DEFAULT_MAXLENGTH; - s->buffer_attr.tlength = DEFAULT_TLENGTH; - s->buffer_attr.prebuf = DEFAULT_PREBUF; - s->buffer_attr.minreq = DEFAULT_MINREQ; - s->buffer_attr.fragsize = DEFAULT_FRAGSIZE; + /* half a second */ + s->buffer_attr.tlength = pa_bytes_per_second(&s->sample_spec)/2; + s->buffer_attr.maxlength = (s->buffer_attr.tlength*3)/2; + s->buffer_attr.minreq = s->buffer_attr.tlength/100; + s->buffer_attr.prebuf = s->buffer_attr.tlength - s->buffer_attr.minreq; + s->buffer_attr.fragsize = s->buffer_attr.tlength/100; } pa_stream_set_state(s, PA_STREAM_CREATING); From 82a362655446fdce8dd3d99d0ce41dd6aa328a16 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 19:40:07 +0000 Subject: [PATCH 0300/1514] * update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@307 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index d55145049..3e30af4f5 100644 --- a/doc/todo +++ b/doc/todo @@ -1,7 +1,6 @@ *** $Id$ *** *** 0.7 **** -- make most buffer sizes dependant on the sample type - limit all resources - commenting From 2fb83d13f27214476f90fe619b26f5bbc8f520c8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 19:47:47 +0000 Subject: [PATCH 0301/1514] * make --help fit in 80 columns terminal git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@308 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/cmdline.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/polyp/cmdline.c b/polyp/cmdline.c index cdf25638b..e11d8aad3 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -91,6 +91,7 @@ void pa_cmdline_help(const char *argv0) { e = argv0; printf("%s [options]\n\n" + "COMMANDS:\n" " -h, --help Show this help\n" " --version Show version\n" " --dump-conf Dump default configuration\n" @@ -98,22 +99,34 @@ void pa_cmdline_help(const char *argv0) { " -k --kill Kill a running daemon\n" " --check Check for a running daemon\n\n" + "OPTIONS:\n" " -D, --daemonize[=BOOL] Daemonize after startup\n" " --fail[=BOOL] Quit when startup fails\n" " --verbose[=BOOL] Be slightly more verbose\n" - " --high-priority[=BOOL] Try to set high process priority (only available as root)\n" + " --high-priority[=BOOL] Try to set high process priority\n" + " (only available as root)\n" " --disallow-module-loading[=BOOL] Disallow module loading after startup\n" - " --exit-idle-time=SECS Terminate the daemon when idle and this time passed\n" - " --module-idle-time=SECS Unload autoloaded modules when idle and this time passed\n" - " --scache-idle-time=SECS Unload autoloaded samples when idle and this time passed\n" + " --exit-idle-time=SECS Terminate the daemon when idle and this\n" + " time passed\n" + " --module-idle-time=SECS Unload autoloaded modules when idle and\n" + " this time passed\n" + " --scache-idle-time=SECS Unload autoloaded samples when idle and\n" + " this time passed\n" " --log-target={auto,syslog,stderr} Specify the log target\n" - " -p, --dl-search-path=PATH Set the search path for dynamic shared objects (plugins)\n" + " -p, --dl-search-path=PATH Set the search path for dynamic shared\n" + " objects (plugins)\n" " --resample-method=[METHOD] Use the specified resampling method\n" + " (one of src-sinc-medium-quality,\n" + " src-sinc-best-quality,src-sinc-fastest\n" + " src-zero-order-hold,src-linear,trivial)\n" " --use-pid-file[=BOOL] Create a PID file\n\n" - - " -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with the specified argument\n" + + "STARTUP SCRIPT:\n" + " -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with\n" + " the specified argument\n" " -F, --file=FILENAME Run the specified script\n" - " -C Open a command line on the running TTY after startup\n\n" + " -C Open a command line on the running TTY\n" + " after startup\n\n" " -n Don't load default script file\n", e); } From 4763ca1376fc136158e576de94dc1cf6c6584973 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 21:31:28 +0000 Subject: [PATCH 0302/1514] Comment some more files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@309 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 14 ++++++++++++-- polyp/authkey-prop.h | 4 ++++ polyp/authkey.c | 21 +++++++++++---------- polyp/authkey.h | 1 - polyp/autoload.h | 17 +++++++++++++++-- polyp/caps.c | 1 + polyp/cli-command.c | 4 ++++ polyp/cli-command.h | 9 +++++++++ polyp/cli-text.h | 3 +++ polyp/cli.h | 2 ++ polyp/client-conf-x11.h | 2 ++ polyp/client-conf.c | 1 + polyp/client-conf.h | 12 +++++++++++- polyp/client.c | 3 ++- polyp/client.h | 6 ++++++ polyp/cmdline.c | 2 ++ polyp/cmdline.h | 4 ++++ polyp/conf-parser.c | 7 ++++++- polyp/conf-parser.h | 14 +++++++++++--- polyp/core.h | 9 +++++++++ polyp/cpulimit-test.c | 16 +++++++++++----- polyp/cpulimit.c | 14 +++++++++----- polyp/daemon-conf.h | 28 +++++++++++++++++++++------- polyp/daemon.conf.in | 18 ++++++++++++++---- polyp/default.pa.in | 15 +++++++++------ polyp/dumpmodules.h | 2 ++ polyp/gcc-printf.h | 23 +++++++++++++++++++++++ polyp/glib-mainloop.c | 1 + polyp/glib12-mainloop.c | 2 ++ polyp/idxset.h | 36 +++++++++++++++++++++++++++++++----- polyp/iochannel.h | 21 ++++++++++++++++++++- polyp/ioline.h | 7 +++++++ polyp/llist.h | 19 ++++++++++++++----- polyp/log.c | 27 +++++++++++++++++++++++++++ polyp/log.h | 35 ++++++++++++++++++++++++++++++++--- polyp/mcalign-test.c | 27 +++++++++++++++++++++++++++ polyp/memblock.h | 32 ++++++++++++++++++++++++++++---- polyp/memblockq.h | 16 +++++++++++----- polyp/modargs.c | 2 +- polyp/modargs.h | 10 +++++++++- polyp/modinfo.c | 10 +++++----- polyp/modinfo.h | 6 ++++++ polyp/module-tunnel.c | 2 +- polyp/module-x11-publish.c | 2 +- polyp/protocol-native.c | 2 +- 45 files changed, 428 insertions(+), 81 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index 742ea3d1e..315118860 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -40,10 +40,20 @@ Lesser General Public License for more details.

    along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    -

    Exception: The client libraries are licensed under LGPL, the Lesser GNU General Plublic License.

    -

    News

    +
    Sun Nov 21 2004:

    Version 0.7 released; +changes include: TCP wrappers support; don't load the complete sound +file into memory when playing back using pa_play_file(); +autoload API change; don't load all sound files as FLOAT32; shorten +default buffers; client-side latency interpolation; add new user +volume metrics; add module-tunnel, module-null-sink, +module-match and new tool paplay; new API version +macros; many client API improvements; correctly lock cookie file +generation; correctly lock daemon autospawning; print daemon layout to +STDERR on SIGHUP; new options for pacat: allow sample type specification.

    +
    Thu Oct 28 2004:

    Version 0.6 released; changes include: TCP wrappers support; don't load the complete sound diff --git a/polyp/authkey-prop.h b/polyp/authkey-prop.h index 1a6681173..1b1948c7f 100644 --- a/polyp/authkey-prop.h +++ b/polyp/authkey-prop.h @@ -24,6 +24,10 @@ #include "core.h" +/* The authkey-prop uses a central property to store a previously + * loaded cookie in memory. Useful for sharing the same cookie between + * several modules. */ + /* Return the data of the specified authorization key property. Doesn't alter the refernce count of the key */ int pa_authkey_prop_get(struct pa_core *c, const char *name, void *data, size_t len); diff --git a/polyp/authkey.c b/polyp/authkey.c index 05324a61e..1355c8d98 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -41,6 +41,7 @@ #define RANDOM_DEVICE "/dev/urandom" +/* Generate a new authorization key, store it in file fd and return it in *data */ static int generate(int fd, void *data, size_t length) { int random_fd, ret = -1; ssize_t r; @@ -66,6 +67,7 @@ static int generate(int fd, void *data, size_t length) { } lseek(fd, 0, SEEK_SET); + ftruncate(fd, 0); if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) { pa_log(__FILE__": failed to write cookie file: %s\n", strerror(errno)); @@ -82,6 +84,8 @@ finish: return ret; } +/* Load an euthorization cookie from file fn and store it in data. If + * the cookie file doesn't exist, create it */ static int load(const char *fn, void *data, size_t length) { int fd = -1; int writable = 1; @@ -130,6 +134,7 @@ finish: return ret; } +/* Load a cookie from a cookie file. If the file doesn't exist, create it. */ int pa_authkey_load(const char *path, void *data, size_t length) { int ret; @@ -144,6 +149,8 @@ int pa_authkey_load(const char *path, void *data, size_t length) { return ret; } +/* If the specified file path starts with / return it, otherwise + * return path prepended with home directory */ static const char *normalize_path(const char *fn, char *s, size_t l) { assert(fn && s && l > 0); @@ -159,7 +166,9 @@ static const char *normalize_path(const char *fn, char *s, size_t l) { return fn; } -int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { +/* Load a cookie from a file in the home directory. If the specified + * path starts with /, use it as absolute path instead. */ +int pa_authkey_load_auto(const char *fn, void *data, size_t length) { char path[PATH_MAX]; const char *p; assert(fn && data && length); @@ -170,15 +179,7 @@ int pa_authkey_load_from_home(const char *fn, void *data, size_t length) { return pa_authkey_load(p, data, length); } -int pa_authkey_load_auto(const char *fn, void *data, size_t length) { - assert(fn && data && length); - - if (*fn == '/') - return pa_authkey_load(fn, data, length); - else - return pa_authkey_load_from_home(fn, data, length); -} - +/* Store the specified cookie in the speicified cookie file */ int pa_authkey_save(const char *fn, const void *data, size_t length) { int fd = -1; int unlock = 0, ret = -1; diff --git a/polyp/authkey.h b/polyp/authkey.h index a6006dfca..81b1a578e 100644 --- a/polyp/authkey.h +++ b/polyp/authkey.h @@ -25,7 +25,6 @@ #include int pa_authkey_load(const char *path, void *data, size_t len); -int pa_authkey_load_from_home(const char *fn, void *data, size_t length); int pa_authkey_load_auto(const char *fn, void *data, size_t length); int pa_authkey_save(const char *path, const void *data, size_t length); diff --git a/polyp/autoload.h b/polyp/autoload.h index 8537173cf..234756845 100644 --- a/polyp/autoload.h +++ b/polyp/autoload.h @@ -24,19 +24,32 @@ #include "namereg.h" +/* Using the autoloading facility, modules by be loaded on-demand and + * synchronously. The user may register a "ghost sink" or "ghost + * source". Whenever this sink/source is requested but not available a + * specified module is loaded. */ + +/* An autoload entry, or "ghost" sink/source */ struct pa_autoload_entry { struct pa_core *core; uint32_t index; char *name; - enum pa_namereg_type type; - int in_action; + enum pa_namereg_type type; /* Type of the autoload entry */ + int in_action; /* Currently loaded */ char *module, *argument; }; +/* Add a new autoload entry of the given time, with the speicified + * sink/source name, module name and argument. Return the entry's + * index in *index */ int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument, uint32_t *index); + +/* Free all autoload entries */ void pa_autoload_free(struct pa_core *c); int pa_autoload_remove_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type); int pa_autoload_remove_by_index(struct pa_core *c, uint32_t index); + +/* Request an autoload entry by its name, effectively causing a module to be loaded */ void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type); const struct pa_autoload_entry* pa_autoload_get_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type); diff --git a/polyp/caps.c b/polyp/caps.c index e2f4573a7..34d97eb56 100644 --- a/polyp/caps.c +++ b/polyp/caps.c @@ -45,6 +45,7 @@ void pa_drop_root(void) { /* pa_log(__FILE__": dropping root rights.\n"); */ setreuid(uid, uid); + /* setuid(uid); seteuid(uid);*/ } diff --git a/polyp/cli-command.c b/polyp/cli-command.c index c11647fc5..72e04bf89 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -56,6 +56,7 @@ struct command { unsigned args; }; +/* Prototypes for all available commands */ static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); @@ -87,6 +88,9 @@ static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_list_props(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); + +/* A method table for all available commands */ + static const struct command commands[] = { { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, { "help", pa_cli_command_help, "Show this help", 1 }, diff --git a/polyp/cli-command.h b/polyp/cli-command.h index 0f089f615..4887c55e2 100644 --- a/polyp/cli-command.h +++ b/polyp/cli-command.h @@ -25,8 +25,17 @@ #include "strbuf.h" #include "core.h" +/* Execute a single CLI command. Write the results to the string + * buffer *buf. If *fail is non-zero the function will return -1 when + * one or more of the executed commands failed. If *verbose is + * non-zero the command is executed verbosely. Both *verbose and *fail + * may be modified by the function call. */ int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose); + +/* Execute a whole file of CLI commands */ int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_strbuf *buf, int *fail, int *verbose); + +/* Split the specified string into lines and run pa_cli_command_execute_line() for each. */ int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose); #endif diff --git a/polyp/cli-text.h b/polyp/cli-text.h index 1457d0556..65607e943 100644 --- a/polyp/cli-text.h +++ b/polyp/cli-text.h @@ -24,6 +24,9 @@ #include "core.h" +/* Some functions to generate pretty formatted listings of + * entities. The returned strings have to be freed manually. */ + char *pa_sink_input_list_to_string(struct pa_core *c); char *pa_source_output_list_to_string(struct pa_core *c); char *pa_sink_list_to_string(struct pa_core *core); diff --git a/polyp/cli.h b/polyp/cli.h index bfe0c4f89..44ed706cc 100644 --- a/polyp/cli.h +++ b/polyp/cli.h @@ -28,9 +28,11 @@ struct pa_cli; +/* Create a new command line session on the specified io channel owned by the specified module */ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct pa_module *m); void pa_cli_free(struct pa_cli *cli); +/* Set a callback function that is called whenever the command line session is terminated */ void pa_cli_set_eof_callback(struct pa_cli *cli, void (*cb)(struct pa_cli*c, void *userdata), void *userdata); #endif diff --git a/polyp/client-conf-x11.h b/polyp/client-conf-x11.h index 951ef0b1f..e65e8202b 100644 --- a/polyp/client-conf-x11.h +++ b/polyp/client-conf-x11.h @@ -24,6 +24,8 @@ #include "client-conf.h" +/* Load client configuration data from the specified X11 display, + * overwriting the current settings in *c */ int pa_client_conf_from_x11(struct pa_client_conf *c, const char *display); #endif diff --git a/polyp/client-conf.c b/polyp/client-conf.c index 21e0acab5..4906383d1 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -82,6 +82,7 @@ int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { char *fn = NULL; int r = -1; + /* Prepare the configuration parse table */ struct pa_config_item table[] = { { "daemon-binary", pa_config_parse_string, NULL }, { "extra-arguments", pa_config_parse_string, NULL }, diff --git a/polyp/client-conf.h b/polyp/client-conf.h index cf7dd0958..b46250393 100644 --- a/polyp/client-conf.h +++ b/polyp/client-conf.h @@ -24,19 +24,29 @@ #include "native-common.h" +/* A structure containing configuration data for polypaudio clients. */ + struct pa_client_conf { char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; int autospawn; uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; - int cookie_valid; + int cookie_valid; /* non-zero, when cookie is valid */ }; +/* Create a new configuration data object and reset it to defaults */ struct pa_client_conf *pa_client_conf_new(void); void pa_client_conf_free(struct pa_client_conf *c); +/* Load the configuration data from the speicified file, overwriting + * the current settings in *c. When the filename is NULL, the + * default client configuration file name is used. */ int pa_client_conf_load(struct pa_client_conf *c, const char *filename); + +/* Load the configuration data from the environment of the current + process, overwriting the current settings in *c. */ int pa_client_conf_env(struct pa_client_conf *c); +/* Load cookie data from c->cookie_file into c->cookie */ int pa_client_conf_load_cookie(struct pa_client_conf* c); #endif diff --git a/polyp/client.c b/polyp/client.c index b525fe6b1..22c7197a1 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -42,7 +42,7 @@ struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, c->name = pa_xstrdup(name); c->owner = NULL; c->core = core; - c->protocol_name = protocol_name; + c->protocol_name = pa_xstrdup(protocol_name); c->kill = NULL; c->userdata = NULL; @@ -68,6 +68,7 @@ void pa_client_free(struct pa_client *c) { pa_log(__FILE__": freed %u \"%s\"\n", c->index, c->name); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_xfree(c->name); + pa_xfree(c->protocol_name); pa_xfree(c); } diff --git a/polyp/client.h b/polyp/client.h index 2518011e2..58c5ee319 100644 --- a/polyp/client.h +++ b/polyp/client.h @@ -25,6 +25,10 @@ #include "core.h" #include "module.h" +/* Every connection to the server should have a pa_client + * attached. That way the user may generate a listing of all connected + * clients easily and kill them if he wants.*/ + struct pa_client { uint32_t index; @@ -37,6 +41,7 @@ struct pa_client { void *userdata; }; +/* Protocol name should be something like "ESOUND", "NATIVE", ... */ struct pa_client *pa_client_new(struct pa_core *c, const char *protocol_name, char *name); /* This function should be called only by the code that created the client */ @@ -46,6 +51,7 @@ void pa_client_free(struct pa_client *c); * request destruction of the client */ void pa_client_kill(struct pa_client *c); +/* Rename the client */ void pa_client_set_name(struct pa_client *c, const char *name); #endif diff --git a/polyp/cmdline.c b/polyp/cmdline.c index e11d8aad3..a39f6ca60 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -35,6 +35,7 @@ #include "strbuf.h" #include "xmalloc.h" +/* Argument codes for getopt_long() */ enum { ARG_HELP = 256, ARG_VERSION, @@ -58,6 +59,7 @@ enum { ARG_CHECK }; +/* Tabel for getopt_long() */ static struct option long_options[] = { {"help", 0, 0, ARG_HELP}, {"version", 0, 0, ARG_VERSION}, diff --git a/polyp/cmdline.h b/polyp/cmdline.h index 28e7bdbc9..ca100d1d8 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -24,8 +24,12 @@ #include "daemon-conf.h" +/* Parese the command line and store its data in *c. Return the index + * of the first unparsed argument in *d. */ int pa_cmdline_parse(struct pa_daemon_conf*c, int argc, char *const argv [], int *d); +/* Show the command line help. The command name is extracted from + * argv[0] which should be passed in argv0. */ void pa_cmdline_help(const char *argv0); #endif diff --git a/polyp/conf-parser.c b/polyp/conf-parser.c index 40b00cda1..35c4766e3 100644 --- a/polyp/conf-parser.c +++ b/polyp/conf-parser.c @@ -32,6 +32,7 @@ #define WHITESPACE " \t\n" #define COMMENTS "#;\n" +/* Run the user supplied parser for an assignment */ static int next_assignment(const char *filename, unsigned line, const struct pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) { assert(filename && t && lvalue && rvalue); @@ -44,6 +45,7 @@ static int next_assignment(const char *filename, unsigned line, const struct pa_ return -1; } +/* Returns non-zero when c is contained in s */ static int in_string(char c, const char *s) { assert(s); @@ -54,6 +56,8 @@ static int in_string(char c, const char *s) { return 0; } +/* Remove all whitepsapce from the beginning and the end of *s. *s may + * be modified. */ static char *strip(char *s) { char *b = s+strspn(s, WHITESPACE); char *e, *l = NULL; @@ -68,6 +72,7 @@ static char *strip(char *s) { return b; } +/* Parse a variable assignment line */ static int parse_line(const char *filename, unsigned line, const struct pa_config_item *t, char *l, void *userdata) { char *e, *c, *b = l+strspn(l, WHITESPACE); @@ -88,7 +93,7 @@ static int parse_line(const char *filename, unsigned line, const struct pa_confi return next_assignment(filename, line, t, strip(b), strip(e), userdata); } - +/* Go through the file and parse each line */ int pa_config_parse(const char *filename, FILE *f, const struct pa_config_item *t, void *userdata) { int r = -1; unsigned line = 0; diff --git a/polyp/conf-parser.h b/polyp/conf-parser.h index 48cfbc147..9add0be05 100644 --- a/polyp/conf-parser.h +++ b/polyp/conf-parser.h @@ -24,14 +24,22 @@ #include +/* An abstract parser for simple, line based, shallow configuration + * files consisting of variable assignments only. */ + +/* Wraps info for parsing a specific configuration variable */ struct pa_config_item { - const char *lvalue; - int (*parse)(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); - void *data; + const char *lvalue; /* name of the variable */ + int (*parse)(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); /* Function that is called to parse the variable's value */ + void *data; /* Where to store the variable's data */ }; +/* The configuration file parsing routine. Expects a table of + * pa_config_items in *t that is terminated by an item where lvalue is + * NULL */ int pa_config_parse(const char *filename, FILE *f, const struct pa_config_item *t, void *userdata); +/* Generic parsers for integers, booleans and strings */ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); diff --git a/polyp/core.h b/polyp/core.h index 09e58b467..6c6070b1e 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -29,13 +29,20 @@ #include "memblock.h" #include "resampler.h" +/* The core structure of polypaudio. Every polypaudio daemon contains + * exactly one of these. It is used for storing kind of global + * variables for the daemon. */ + struct pa_core { struct pa_mainloop_api *mainloop; + /* idxset of all kinds of entities */ struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache, *autoload_idxset; + /* Some hashmaps for all sorts of entities */ struct pa_hashmap *namereg, *autoload_hashmap, *properties; + /* The name of the default sink/source */ char *default_source_name, *default_sink_name; struct pa_sample_spec default_sample_spec; @@ -60,6 +67,8 @@ struct pa_core { struct pa_core* pa_core_new(struct pa_mainloop_api *m); void pa_core_free(struct pa_core*c); + +/* Check whether noone is connected to this core */ void pa_core_check_quit(struct pa_core *c); #endif diff --git a/polyp/cpulimit-test.c b/polyp/cpulimit-test.c index 83d403f5e..de5e20ad9 100644 --- a/polyp/cpulimit-test.c +++ b/polyp/cpulimit-test.c @@ -4,21 +4,25 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -32,6 +36,8 @@ #include "mainloop-signal.h" #endif +/* A simple example for testing the cpulimit subsystem */ + static time_t start; #ifdef TEST2 diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c index 78dc5e1fd..0fab98a02 100644 --- a/polyp/cpulimit.c +++ b/polyp/cpulimit.c @@ -4,21 +4,25 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/polyp/daemon-conf.h b/polyp/daemon-conf.h index 8a5742727..f163400f9 100644 --- a/polyp/daemon-conf.h +++ b/polyp/daemon-conf.h @@ -24,16 +24,18 @@ #include "log.h" +/* The actual command to execute */ enum pa_daemon_conf_cmd { - PA_CMD_DAEMON, - PA_CMD_HELP, - PA_CMD_VERSION, - PA_CMD_DUMP_CONF, - PA_CMD_DUMP_MODULES, - PA_CMD_KILL, - PA_CMD_CHECK + PA_CMD_DAEMON, /* the default */ + PA_CMD_HELP, + PA_CMD_VERSION, + PA_CMD_DUMP_CONF, + PA_CMD_DUMP_MODULES, + PA_CMD_KILL, + PA_CMD_CHECK }; +/* A structure containing configuration data for the Polypaudio server . */ struct pa_daemon_conf { enum pa_daemon_conf_cmd cmd; int daemonize, @@ -52,13 +54,25 @@ struct pa_daemon_conf { char *config_file; }; +/* Allocate a new structure and fill it with sane defaults */ struct pa_daemon_conf* pa_daemon_conf_new(void); void pa_daemon_conf_free(struct pa_daemon_conf*c); +/* Load configuration data from the specified file overwriting the + * current settings in *c. If filename is NULL load the default daemon + * configuration file */ int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename); + +/* Pretty print the current configuration data of the daemon. The + * returned string has to be freed manually. The output of this + * function may be parsed with pa_daemon_conf_load(). */ char *pa_daemon_conf_dump(struct pa_daemon_conf *c); + +/* Load the configuration data from the process' environment + * overwriting the current settings in *c. */ int pa_daemon_conf_env(struct pa_daemon_conf *c); +/* Set these configuration variables in the structure by passing a string */ int pa_daemon_conf_set_log_target(struct pa_daemon_conf *c, const char *string); int pa_daemon_conf_set_resample_method(struct pa_daemon_conf *c, const char *string); diff --git a/polyp/daemon.conf.in b/polyp/daemon.conf.in index ddc4955c2..d5373018d 100644 --- a/polyp/daemon.conf.in +++ b/polyp/daemon.conf.in @@ -60,8 +60,18 @@ ## true, otherwise to "stderr". ; log-target = auto -## The resampling algorithm to use. Use one of sinc-best-quality, -## sinc-medium-quality, sinc-fastest, zero-order-hold, linear. See -## the documentation of libsamplerate for an explanation fot the -## different methods. +## The resampling algorithm to use. Use one of src-sinc-best-quality, +## src-sinc-medium-quality, src-sinc-fastest, src-zero-order-hold, +## src-linear, trivial. See the documentation of libsamplerate for an +## explanation for the different methods. The method 'trivial' is the +## only algorithm implemented without usage of floating point +## numbers. If you're tight on CPU consider using this. On the other +## hand it has the worst quality of all. ; resample-method = sinc-fastest + +## Create a PID file in /tmp/polypaudio-$USER/pid. Of this is enabled +## you may use commands like "polypaudio --kill" or "polypaudio +## --check". If you are planning to start more than one polypaudio +## process per user, you better disable this option since it +## effectively disables multiple instances. +; use-pid-file = 1 diff --git a/polyp/default.pa.in b/polyp/default.pa.in index 07ff373ce..3aaeeaf05 100755 --- a/polyp/default.pa.in +++ b/polyp/default.pa.in @@ -21,8 +21,8 @@ # Load audio drivers statically #load-module module-alsa-sink -load-module module-alsa-source device=plughw:1,0 -load-module module-oss device="/dev/dsp" sink_name=output source_name=input record=0 +# load-module module-alsa-source device=plughw:1,0 +load-module module-oss device="/dev/dsp" sink_name=output source_name=input #load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input load-module module-null-sink #load-module module-pipe-sink @@ -37,11 +37,11 @@ load-module module-null-sink #add-autoload-source input module-alsa-source source_name=input # Load several protocols -load-module module-esound-protocol-tcp -#load-module module-simple-protocol-tcp +load-module module-esound-protocol-unix +#load-module module-esound-protocol-tcp load-module module-native-protocol-unix +#load-module module-simple-protocol-tcp #load-module module-cli-protocol-unix -#load-module module-esound-protocol-unix # Load the CLI module load-module module-cli @@ -54,10 +54,13 @@ set-default-source input # Load something to the sample cache load-sample x11-bell /usr/share/sounds/KDE_Notify.wav +load-sample-dir-lazy /usr/share/sounds/*.wav # Load X11 bell module load-module module-x11-bell sample=x11-bell sink=output +# Publish connection data in the X11 root window +load-module module-x11-publish + #load-module module-pipe-source #load-module module-pipe-sink - diff --git a/polyp/dumpmodules.h b/polyp/dumpmodules.h index c56d5abc5..fadc571f3 100644 --- a/polyp/dumpmodules.h +++ b/polyp/dumpmodules.h @@ -24,6 +24,8 @@ #include "daemon-conf.h" +/* Dump all available modules to STDOUT. If argc > 0 print information + * about the modules specified in argv[] instead. */ void pa_dump_modules(struct pa_daemon_conf *c, int argc, char * const argv[]); #endif diff --git a/polyp/gcc-printf.h b/polyp/gcc-printf.h index 224552af8..70679df93 100644 --- a/polyp/gcc-printf.h +++ b/polyp/gcc-printf.h @@ -1,6 +1,29 @@ #ifndef foogccprintfhfoo #define foogccprintfhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* If we're in GNU C, use some magic for detecting invalid format strings */ + #ifdef __GNUC__ #define PA_GCC_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b))) #else diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c index aa81f82d6..809c0b0fb 100644 --- a/polyp/glib-mainloop.c +++ b/polyp/glib-mainloop.c @@ -106,6 +106,7 @@ static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa return e; } +/* The callback GLIB calls whenever an IO condition is met */ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) { struct pa_io_event *e = data; enum pa_io_event_flags f; diff --git a/polyp/glib12-mainloop.c b/polyp/glib12-mainloop.c index 2073c01d2..5f0373471 100644 --- a/polyp/glib12-mainloop.c +++ b/polyp/glib12-mainloop.c @@ -29,6 +29,8 @@ #include "idxset.h" #include "xmalloc.h" +/* A mainloop implementation based on GLIB 1.2 */ + struct pa_io_event { struct pa_glib_mainloop *mainloop; int dead; diff --git a/polyp/idxset.h b/polyp/idxset.h index 66689fd42..4c89eea19 100644 --- a/polyp/idxset.h +++ b/polyp/idxset.h @@ -24,41 +24,67 @@ #include -/* A combination of a hashtable and a dynamic array. Entries are both - * indexiable through a numeric automaticly generated index and an - * opaque key. As usual, memory management is the user's job. */ +/* A combination of a set and a dynamic array. Entries are indexable + * both through a numeric automatically generated index and the entry's + * data pointer. As usual, memory management is the user's job. */ +/* A special index value denoting the invalid index. */ #define PA_IDXSET_INVALID ((uint32_t) -1) +/* Generic implementations for hash and comparison functions. Just + * compares the pointer or calculates the hash value directly from the + * pointer value. */ unsigned pa_idxset_trivial_hash_func(const void *p); int pa_idxset_trivial_compare_func(const void *a, const void *b); +/* Generic implementations for hash and comparison functions for strings. */ unsigned pa_idxset_string_hash_func(const void *p); int pa_idxset_string_compare_func(const void *a, const void *b); struct pa_idxset; +/* Instantiate a new idxset with the specified hash and comparison functions */ struct pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); + +/* Free the idxset. When the idxset is not empty the specified function is called for every entry contained */ void pa_idxset_free(struct pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata); +/* Store a new item in the idxset. The index of the item is returned in *index */ int pa_idxset_put(struct pa_idxset*s, void *p, uint32_t *index); +/* Get the entry by its index */ void* pa_idxset_get_by_index(struct pa_idxset*s, uint32_t index); + +/* Get the entry by its data. The index is returned in *index */ void* pa_idxset_get_by_data(struct pa_idxset*s, const void *p, uint32_t *index); +/* Similar to pa_idxset_get_by_index(), but removes the entry from the idxset. */ void* pa_idxset_remove_by_index(struct pa_idxset*s, uint32_t index); + +/* Similar to pa_idxset_get_by_data(), but removes the entry from the idxset */ void* pa_idxset_remove_by_data(struct pa_idxset*s, const void *p, uint32_t *index); /* This may be used to iterate through all entries. When called with an invalid index value it returns the first entry, otherwise the next following. The function is best called with *index = - PA_IDXSET_VALID first. */ + PA_IDXSET_VALID first. It is safe to manipulate the idxset between + the calls. It is not guaranteed that all entries have already been + returned before the an entry is returned the second time.*/ void* pa_idxset_rrobin(struct pa_idxset *s, uint32_t *index); -/* Return the oldest entry in the idxset */ +/* Return the oldest entry in the idxset. Fill in its index in *index. */ void* pa_idxset_first(struct pa_idxset *s, uint32_t *index); + +/* Return the entry following the entry indexed by *index. After the + * call *index contains the index of the returned + * object. pa_idxset_first() and pa_idxset_next() may be used to + * iterate through the set.*/ void *pa_idxset_next(struct pa_idxset *s, uint32_t *index); +/* Call a function for every item in the set. If the callback function + returns -1, the loop is terminated. If *del is set to non-zero that + specific item is removed. It is not safe to call any other + functions on the idxset while pa_idxset_foreach is executed. */ int pa_idxset_foreach(struct pa_idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata); unsigned pa_idxset_ncontents(struct pa_idxset*s); diff --git a/polyp/iochannel.h b/polyp/iochannel.h index f8efc9288..2a1ba3706 100644 --- a/polyp/iochannel.h +++ b/polyp/iochannel.h @@ -25,10 +25,23 @@ #include #include "mainloop-api.h" -/* It is safe to destroy the calling iochannel object from the callback */ +/* A wrapper around UNIX file descriptors for attaching them to the a + main event loop. Everytime new data may be read or be written to + the channel a callback function is called. It is safe to destroy + the calling iochannel object from the callback */ + +/* When pa_iochannel_is_readable() returns non-zero, the user has to + * call this function in a loop until it is no longer set or EOF + * reached. Otherwise strange things may happen when an EOF is + * reached. */ struct pa_iochannel; +/* Create a new IO channel for the specified file descriptors for +input resp. output. It is safe to pass the same file descriptor for +both parameters (in case of full-duplex channels). For a simplex +channel specify -1 for the other direction. */ + struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd); void pa_iochannel_free(struct pa_iochannel*io); @@ -39,11 +52,17 @@ int pa_iochannel_is_readable(struct pa_iochannel*io); int pa_iochannel_is_writable(struct pa_iochannel*io); int pa_iochannel_is_hungup(struct pa_iochannel*io); +/* Don't close the file descirptors when the io channel is freed. By + * default the file descriptors are closed. */ void pa_iochannel_set_noclose(struct pa_iochannel*io, int b); +/* Set the callback function that is called whenever data becomes available for read or write */ void pa_iochannel_set_callback(struct pa_iochannel*io, void (*callback)(struct pa_iochannel*io, void *userdata), void *userdata); +/* In case the file descriptor is a socket, return a pretty-printed string in *s which describes the peer connected */ void pa_iochannel_socket_peer_to_string(struct pa_iochannel*io, char*s, size_t l); + +/* Use setsockopt() to tune the recieve and send buffers of TCP sockets */ int pa_iochannel_socket_set_rcvbuf(struct pa_iochannel*io, size_t l); int pa_iochannel_socket_set_sndbuf(struct pa_iochannel*io, size_t l); diff --git a/polyp/ioline.h b/polyp/ioline.h index 5adc0560f..f652dddbd 100644 --- a/polyp/ioline.h +++ b/polyp/ioline.h @@ -24,6 +24,10 @@ #include "iochannel.h" +/* An ioline wraps an iochannel for line based communication. A + * callback function is called whenever a new line has been recieved + * from the client */ + struct pa_ioline; struct pa_ioline* pa_ioline_new(struct pa_iochannel *io); @@ -31,7 +35,10 @@ void pa_ioline_unref(struct pa_ioline *l); struct pa_ioline* pa_ioline_ref(struct pa_ioline *l); void pa_ioline_close(struct pa_ioline *l); +/* Write a string to the channel */ void pa_ioline_puts(struct pa_ioline *s, const char *c); + +/* Set the callback function that is called for every recieved line */ void pa_ioline_set_callback(struct pa_ioline*io, void (*callback)(struct pa_ioline*io, const char *s, void *userdata), void *userdata); #endif diff --git a/polyp/llist.h b/polyp/llist.h index c48c5c6ea..eb8cd0173 100644 --- a/polyp/llist.h +++ b/polyp/llist.h @@ -7,33 +7,41 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ +/* Some macros for maintaining doubly linked lists */ + +/* The head of the linked list. Use this in the structure that shall + * contain the head of the linked list */ #define PA_LLIST_HEAD(t,name) t *name +/* The pointers in the linked list's items. Use this in the item structure */ #define PA_LLIST_FIELDS(t) t *next, *prev +/* Initialize the list's head */ #define PA_LLIST_HEAD_INIT(t,item) do { (item) = NULL; } while(0) +/* Initialize a list item */ #define PA_LLIST_INIT(t,item) do { \ t *_item = (item); \ assert(_item); \ _item->prev = _item->next = NULL; \ } while(0) +/* Prepend an item to the list */ #define PA_LLIST_PREPEND(t,head,item) do { \ t **_head = &(head), *_item = (item); \ assert(_item); \ @@ -43,6 +51,7 @@ *_head = _item; \ } while (0) +/* Remove an item from the list */ #define PA_LLIST_REMOVE(t,head,item) do { \ t **_head = &(head), *_item = (item); \ assert(_item); \ diff --git a/polyp/log.c b/polyp/log.c index 516cd2b07..dc41dcd29 100644 --- a/polyp/log.c +++ b/polyp/log.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -43,6 +68,8 @@ void pa_log(const char *format, ...) { user_log_func(t); pa_xfree(t); } + case PA_LOG_NULL: + break; } va_end(ap); diff --git a/polyp/log.h b/polyp/log.h index 46a86491c..cf55386cd 100644 --- a/polyp/log.h +++ b/polyp/log.h @@ -1,17 +1,46 @@ #ifndef foologhfoo #define foologhfoo +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + #include "gcc-printf.h" +/* A simple logging subsystem */ + +/* Where to log to */ enum pa_log_target { + PA_LOG_STDERR, /* default */ PA_LOG_SYSLOG, - PA_LOG_STDERR, - PA_LOG_USER + PA_LOG_USER, /* to user specified function */ + PA_LOG_NULL /* to /dev/null */ }; +/* Set an identifcation for the current daemon. Used when logging to syslog. */ void pa_log_set_ident(const char *p); + +/* Set another log target. If t is PA_LOG_USER you may specify a function that is called every log string */ void pa_log_set_target(enum pa_log_target t, void (*func)(const char*s)); - + +/* Do a log line */ void pa_log(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); #endif diff --git a/polyp/mcalign-test.c b/polyp/mcalign-test.c index ab1f9aed7..f8af4f9fc 100644 --- a/polyp/mcalign-test.c +++ b/polyp/mcalign-test.c @@ -1,3 +1,28 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -9,6 +34,8 @@ #include "util.h" #include "mcalign.h" +/* A simple program for testing pa_mcalign */ + int main(int argc, char *argv[]) { struct pa_mcalign *a = pa_mcalign_new(11, NULL); struct pa_memchunk c; diff --git a/polyp/memblock.h b/polyp/memblock.h index 91612ac93..8555954cd 100644 --- a/polyp/memblock.h +++ b/polyp/memblock.h @@ -25,30 +25,54 @@ #include #include -enum pa_memblock_type { PA_MEMBLOCK_FIXED, PA_MEMBLOCK_APPENDED, PA_MEMBLOCK_DYNAMIC, PA_MEMBLOCK_USER }; +/* A pa_memblock is a reference counted memory block. Polypaudio + * passed references to pa_memblocks around instead of copying + * data. See pa_memchunk for a structure that describes parts of + * memory blocks. */ +/* The type of memory this block points to */ +enum pa_memblock_type { + PA_MEMBLOCK_FIXED, /* data is a pointer to fixed memory that needs not to be freed */ + PA_MEMBLOCK_APPENDED, /* The most common kind: the data is appended to the memory block */ + PA_MEMBLOCK_DYNAMIC, /* data is a pointer to some memory allocated with pa_xmalloc() */ + PA_MEMBLOCK_USER /* User supplied memory, to be freed with free_cb */ +}; + +/* A structure of keeping memory block statistics */ struct pa_memblock_stat; struct pa_memblock { enum pa_memblock_type type; - unsigned ref; - int read_only; + unsigned ref; /* the reference counter */ + int read_only; /* boolean */ size_t length; void *data; - void (*free_cb)(void *p); + void (*free_cb)(void *p); /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ struct pa_memblock_stat *stat; }; +/* Allocate a new memory block of type PA_MEMBLOCK_APPENDED */ struct pa_memblock *pa_memblock_new(size_t length, struct pa_memblock_stat*s); + +/* Allocate a new memory block of type PA_MEMBLOCK_DYNAMIC. The pointer data is to be maintained be the memory block */ struct pa_memblock *pa_memblock_new_dynamic(void *data, size_t length, struct pa_memblock_stat*s); + +/* Allocate a new memory block of type PA_MEMBLOCK_FIXED */ struct pa_memblock *pa_memblock_new_fixed(void *data, size_t length, int read_only, struct pa_memblock_stat*s); + +/* Allocate a new memory block of type PA_MEMBLOCK_USER */ struct pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p), int read_only, struct pa_memblock_stat*s); void pa_memblock_unref(struct pa_memblock*b); struct pa_memblock* pa_memblock_ref(struct pa_memblock*b); +/* This special unref function has to be called by the owner of the +memory of a static memory block when he wants to release all +references to the memory. This causes the memory to be copied and +converted into a PA_MEMBLOCK_DYNAMIC type memory block */ void pa_memblock_unref_fixed(struct pa_memblock*b); +/* Matinatins statistics about memory blocks */ struct pa_memblock_stat { int ref; unsigned total; diff --git a/polyp/memblockq.h b/polyp/memblockq.h index 95e5c5330..2c762bf4c 100644 --- a/polyp/memblockq.h +++ b/polyp/memblockq.h @@ -7,17 +7,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,6 +27,12 @@ #include "memblock.h" #include "memchunk.h" +/* A memblockq is a queue of pa_memchunks (yepp, the name is not + * perfect). It is similar to the ring buffers used by most other + * audio software. In contrast to a ring buffer this memblockq data + * type doesn't need to copy any data around, it just maintains + * references to reference counted memory blocks. */ + struct pa_memblockq; /* Parameters: diff --git a/polyp/modargs.c b/polyp/modargs.c index 01a694cf8..406f610fd 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -44,7 +44,7 @@ struct entry { char *key, *value; }; -static int add_key_value(struct pa_hashmap *map, char *key, char *value, const char* const* valid_keys) { +static int add_key_value(struct pa_hashmap *map, char *key, char *value, const char* const valid_keys[]) { struct entry *e; assert(map && key && value); diff --git a/polyp/modargs.h b/polyp/modargs.h index 53753ba73..07db6ae50 100644 --- a/polyp/modargs.h +++ b/polyp/modargs.h @@ -28,14 +28,22 @@ struct pa_modargs; -struct pa_modargs *pa_modargs_new(const char *args, const char* const* keys); +/* A generic parser for module arguments */ + +/* Parse the string args. The NULL-terminated array keys contains all valid arguments. */ +struct pa_modargs *pa_modargs_new(const char *args, const char* const keys[]); void pa_modargs_free(struct pa_modargs*ma); +/* Return the module argument for the specified name as a string. If + * the argument was not specified, return def instead.*/ const char *pa_modargs_get_value(struct pa_modargs *ma, const char *key, const char *def); + +/* Return a module argument as unsigned 32bit value in *value */ int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *value); int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *value); int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *value); +/* Return sample spec data from the three arguments "rate", "format" and "channels" */ int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *ss); #endif diff --git a/polyp/modinfo.c b/polyp/modinfo.c index a1328be6b..a96bb17e2 100644 --- a/polyp/modinfo.c +++ b/polyp/modinfo.c @@ -4,17 +4,17 @@ This file is part of polypaudio. polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. polypaudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/polyp/modinfo.h b/polyp/modinfo.h index d6f7c6de6..9da9dc4eb 100644 --- a/polyp/modinfo.h +++ b/polyp/modinfo.h @@ -22,6 +22,8 @@ USA. ***/ +/* Some functions for reading module meta data from Polypaudio modules */ + struct pa_modinfo { char *author; char *description; @@ -29,9 +31,13 @@ struct pa_modinfo { char *version; }; +/* Read meta data from an libtool handle */ struct pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl); + +/* Read meta data from a module file */ struct pa_modinfo *pa_modinfo_get_by_name(const char *name); +/* Free meta data */ void pa_modinfo_free(struct pa_modinfo *i); #endif diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index 2b36ce273..39aaab571 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -554,7 +554,7 @@ static int load_key(struct userdata *u, const char*fn) { if (!fn) fn = PA_NATIVE_COOKIE_FILE; - if (pa_authkey_load_from_home(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) + if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) return -1; pa_log(__FILE__": loading cookie from disk.\n"); diff --git a/polyp/module-x11-publish.c b/polyp/module-x11-publish.c index acf377597..598fe5b5d 100644 --- a/polyp/module-x11-publish.c +++ b/polyp/module-x11-publish.c @@ -86,7 +86,7 @@ static int load_key(struct userdata *u, const char*fn) { if (!fn) fn = PA_NATIVE_COOKIE_FILE; - if (pa_authkey_load_from_home(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) + if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) return -1; pa_log(__FILE__": loading cookie from disk.\n"); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index e4831e4d9..84d4efe8f 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -2066,7 +2066,7 @@ static int load_key(struct pa_protocol_native*p, const char*fn) { if (!fn) fn = PA_NATIVE_COOKIE_FILE; - if (pa_authkey_load_from_home(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0) + if (pa_authkey_load_auto(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0) return -1; pa_log(__FILE__": loading cookie from disk.\n"); From 9f23c8f36299635f78475ee9e90b0a20c5cf3b84 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 22:07:47 +0000 Subject: [PATCH 0303/1514] Documentation updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@310 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/FAQ.html.in | 9 +++++--- doc/Makefile.am | 10 ++++----- doc/README.html.in | 52 +++++++++++++++++++++++++++------------------ doc/cli.html.in | 8 ++++++- doc/daemon.html.in | 32 +++++++++++++++++++++------- doc/modules.html.in | 22 ++++++++++++++++++- doc/todo | 7 ++---- 7 files changed, 96 insertions(+), 44 deletions(-) diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in index 751ef562c..9cacfb4c3 100644 --- a/doc/FAQ.html.in +++ b/doc/FAQ.html.in @@ -126,9 +126,11 @@ connect to a running polypaudio daemon try using the following commands:

    killall -USR2 polypaudio
     bidilink unix-client:/tmp/polypaudio/cli
    -

    BTW: Someone should package that great tool for Debian!

    +

    BTW: Someone should package that great tool for Debian!

    +

    New: There's now a tool pacmd that automates sending SIGUSR2 to the daemon and running a bidilink like tool for you.

    +
  • How do the polypaudio libraries decide where to connect to?

    The following rule applies:

    @@ -142,10 +144,11 @@ bidilink unix-client:/tmp/polypaudio/cli
  • If $DISPLAY is set, the library tries to connect to the default TCP port of that host. If the connection fails, it proceeds with the next item.
  • The connection fails.
  • -

    - +
  • Why the heck does libpolyp link against libX11?

    +

    The Polypaudio client libraries look for some X11 root window properties for the credentials of the Polypaudio server to access. You may compile Polypaudio without X11 for disabling this.

  • +
    diff --git a/doc/Makefile.am b/doc/Makefile.am index 17688d3bb..001f5b491 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -30,11 +30,11 @@ CLEANFILES += README endif tidy: README.html cli.html modules.html daemon.html - tidy -e < README.html - tidy -e < cli.html - tidy -e < daemon.html - tidy -e < modules.html - tidy -e < FAQ.html + tidy -qe < README.html + tidy -qe < cli.html + tidy -qe < daemon.html + tidy -qe < modules.html + tidy -qe < FAQ.html .PHONY: tidy diff --git a/doc/README.html.in b/doc/README.html.in index 315118860..eb57fdb78 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -44,15 +44,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    Sun Nov 21 2004:

    Version 0.7 released; -changes include: TCP wrappers support; don't load the complete sound -file into memory when playing back using pa_play_file(); -autoload API change; don't load all sound files as FLOAT32; shorten -default buffers; client-side latency interpolation; add new user -volume metrics; add module-tunnel, module-null-sink, -module-match and new tool paplay; new API version -macros; many client API improvements; correctly lock cookie file -generation; correctly lock daemon autospawning; print daemon layout to -STDERR on SIGHUP; new options for pacat: allow sample type specification.

    +changes include: IPv6 support; PID file support; publish credentials +in X11 root window (module-x11-publish; new tool pacmd; ESOUND backend; new command load-sample-dir-lazy; many, many minor fixes.

    Thu Oct 28 2004:

    Version 0.6 released; @@ -103,8 +96,9 @@ href="@PACKAGE_URL@polypaudio-0.1.tar.gz">Version 0.1 released

    operating systems. It is intended to be an improved drop-in replacement for the Enlightened Sound -Daemon (ESOUND). In addition to the features ESOUND provides -polypaudio has:

    +Daemon (ESOUND). It is my ultimate ambition to get Polypaudio into +Gnome as a replacement for ESOUND. In +addition to the features ESOUND provides polypaudio has:

    • Extensible plugin architecture (by loading dynamic loadable modules with dlopen())
    • @@ -139,13 +133,15 @@ available. A simple main loop implementation is available as well.

    • module-combine: combine multiple sinks into one.
    • module-sine: a sine generate sink input.
    • module-x11-bell: play a sample from the sample cache on every X11 bell event.
    • -
    • module-esound-protocol-tcp, module-esound-protocol-unix: ESOUND compatibility modules (for TCP/IP resp. UNIX domain sockets)
    • -
    • module-native-protocol-tcp, module-native-protocol-unix: Native polypaudio protocol (for TCP/IP resp. UNIX domain sockets)
    • -
    • module-simple-protocol-tcp, module-simple-protocol-unix: Simplistic protocol for playback/capture for usage with tools like netcat (for TCP/IP resp. UNIX domain sockets)
    • -
    • module-cli-protocol-tcp, module-cli-protocol-unix, module-cli: Expose polypaudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
    • +
    • module-x11-publish: store Polypaudio credentials in the X11 root window.
    • +
    • module-esound-protocol-tcp, module-esound-protocol-tcp6, module-esound-protocol-unix: ESOUND compatibility modules (for TCP/IPv6 resp. TCP/IPv6 resp. UNIX domain sockets)
    • +
    • module-native-protocol-tcp, module-native-protocol-tcp6, module-native-protocol-unix: Native polypaudio protocol (for TCP/IPv4 resp. TCP/IPv6 resp. UNIX domain sockets)
    • +
    • module-simple-protocol-tcp, module-simple-protocol-tcp6, module-simple-protocol-unix: Simplistic protocol for playback/capture for usage with tools like netcat (for TCP/IP resp. UNIX domain sockets)
    • +
    • module-cli-protocol-tcp, module-cli-protocol-tcp6, module-cli-protocol-unix, module-cli: Expose polypaudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
    • module-tunnel-sink, module-tunnel-source: make sinks/sources from other hosts available locally.
    • module-match: adjust volume automatically for newly created playback streams based on a regular expression matching table.
    • module-null-sink: a clocked sink similar to /dev/null.
    • +
    • module-esound-sink: a sink for forwarding audio data to an ESOUND server.

    polypaudio is the successor of my previous, ill-fated @@ -156,10 +152,18 @@ href="http://asd.sf.net/">asd.

    href="http://0pointer.de/lennart/projects/paman/">Polypaudio Manager. Another GTK GUI tool for Polypaudio is the Polypaudio Volume -Meter. There are output plugins for .

    + +

    There are output plugins for XMMS, libao and gstreamer. Drivers -for MPlayer and PortAudio will be released shortly.

    +href="http://0pointer.de/lennart/projects/libao-polyp/">libao +(merged in libao SVN) and gstreamer +(merged in gstreamer-plugins CVS), MPlayer (merged in MPlayer CVS) and Xine (merged in Xine CVS). Drivers for +PortAudio will be released +shortly.

    Status

    @@ -227,10 +231,10 @@ questions.

    Requirements

    -

    Currently, polypaudio is tested on Linux only. It requires an OSS or ALSA compatible soundcard.

    +

    Currently, polypaudio is tested on Linux and FreeBSD only. It requires an OSS or ALSA compatible soundcard.

    polypaudio was developed and tested on Debian GNU/Linux -"testing" from July 2004, it should work on most other Linux +"testing" from November 2004, it should work on most other Linux distributions (and maybe Unix versions) since it uses GNU autoconf and GNU libtool for source code configuration and shared library management.

    @@ -255,6 +259,12 @@ compilation and make install (as root) for installation of

    Eric B. Mitchell for writing ESOUND

    +

    Jeff Waugh for creating Ubuntu packages (and hopefully soon Debian)

    + +

    Miguel Freitas for writing a Polypaudio driver for Xine

    + +

    Joe Marcus Clarke for porting Polypaudio to FreeBSD

    +

    Download

    The newest release is always available from @PACKAGE_URL@

    @@ -272,7 +282,7 @@ compilation and make install (as root) for installation of

    New! There is now a Polypaudio wiki (based on trac) available.


    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, October 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, November 2004
    $Id$
    diff --git a/doc/cli.html.in b/doc/cli.html.in index 49e568f8f..61d29e5af 100644 --- a/doc/cli.html.in +++ b/doc/cli.html.in @@ -112,6 +112,12 @@ immediately. The sample is loaded only when it is first used. After a certain idle time it is freed again. Expects the the desired sample name and file name to load as arguments.

    +

    load-sample-dir-lazy

    + +

    Load all entries in the specified directory into the sample cache +as lazy entries. A shell globbing expression (e.g. *.wav) may +be appended to the path of the directory to add.

    +

    Module Autoloading

    list-autoload

    @@ -203,6 +209,6 @@ play-file /usr/share/sounds/startup3.wav combined
    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, November 2004
    $Id$
    diff --git a/doc/daemon.html.in b/doc/daemon.html.in index 8d2414c07..a4db0bd7a 100644 --- a/doc/daemon.html.in +++ b/doc/daemon.html.in @@ -14,26 +14,42 @@ The polypaudio daemon accepts several command line arguments:
    +COMMANDS:
       -h, --help                            Show this help
           --version                         Show version
           --dump-conf                       Dump default configuration
           --dump-modules                    Dump list of available modules
    +  -k  --kill                            Kill a running daemon
    +      --check                           Check for a running daemon
     
    +OPTIONS:
       -D, --daemonize[=BOOL]                Daemonize after startup
           --fail[=BOOL]                     Quit when startup fails
           --verbose[=BOOL]                  Be slightly more verbose
    -      --high-priority[=BOOL]            Try to set high process priority (only available as root)
    +      --high-priority[=BOOL]            Try to set high process priority
    +                                        (only available as root)
           --disallow-module-loading[=BOOL]  Disallow module loading after startup
    -      --exit-idle-time=SECS             Terminate the daemon when idle and this time passed
    -      --module-idle-time=SECS           Unload autoloaded modules when idle and this time passed
    -      --scache-idle-time=SECS           Unload autoloaded samples when idle and this time passed
    +      --exit-idle-time=SECS             Terminate the daemon when idle and this
    +                                        time passed
    +      --module-idle-time=SECS           Unload autoloaded modules when idle and
    +                                        this time passed
    +      --scache-idle-time=SECS           Unload autoloaded samples when idle and
    +                                        this time passed
           --log-target={auto,syslog,stderr} Specify the log target
    -  -p, --dl-search-path=PATH             Set the search path for dynamic shared objects (plugins)
    +  -p, --dl-search-path=PATH             Set the search path for dynamic shared
    +                                        objects (plugins)
           --resample-method=[METHOD]        Use the specified resampling method
    +                                        (one of src-sinc-medium-quality,
    +                                        src-sinc-best-quality,src-sinc-fastest
    +                                        src-zero-order-hold,src-linear,trivial)
    +      --use-pid-file[=BOOL]             Create a PID file
     
    -  -L, --load="MODULE ARGUMENTS"         Load the specified plugin module with the specified argument
    +STARTUP SCRIPT:
    +  -L, --load="MODULE ARGUMENTS"         Load the specified plugin module with
    +                                        the specified argument
       -F, --file=FILENAME                   Run the specified script
    -  -C                                    Open a command line on the running TTY after startup (identical to -Lmodule-cli)
    +  -C                                    Open a command line on the running TTY
    +                                        after startup
     
       -n                                    Don't load default script file
     
    @@ -67,6 +83,6 @@ The polypaudio daemon accepts several command line arguments:

    The daemon logs the current server layout.


    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, November 2004
    $Id$
    diff --git a/doc/modules.html.in b/doc/modules.html.in index 14fe72783..a549396d0 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -267,6 +267,26 @@ about the two possible suffixes of this module.

    sink=Name of the sink to play the sample on. If ommited defaults to the default sink. +

    module-x11-publish

    + +

    Publishes the access credentials to the Polypaudio server in the +X11 root window. The following properties are used: +POLYP_SERVER, POYLP_SINK, POLYP_SOURCE, +POLYP_COOKIE. This is very useful when using SSH or any other +remote login tool for logging into other machines and getting audio +playback to your local speakers. The Polypaudio client libraries make +use of this data automatically. Instead of using this module you may +use the tool pax11publish which may be used to access, modify +and import credential data from/to the X11 display.

    + + + + + +
    display=X11 display to connect to. If ommited defaults to the value of $DISPLAY
    sink=Name of the default sink. If ommited this property isn't stored in the X11 display.
    source=Name of the default source. If ommited this property isn't stored in the X11 display.
    cookie=Name of the cookie file of the +cookie to store in the X11 display. If ommited the cookie of an +already loaded protocol module is used.
    +

    module-sine

    Creates a sink input and generates a sine waveform stream.

    @@ -301,6 +321,6 @@ about the two possible suffixes of this module.

    The volumes of all streams with titles starting with sample: are automatically set to 25. (FYI: All sample cache streams start with sample:)


    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, November 2004
    $Id$
    diff --git a/doc/todo b/doc/todo index 3e30af4f5..d6cfb01ac 100644 --- a/doc/todo +++ b/doc/todo @@ -1,10 +1,7 @@ *** $Id$ *** -*** 0.7 **** -- limit all resources -- commenting - -** later *** +*** later **** +- event more commenting - polish for starting polypaudio as root/system-wide instance - per-channel volume - improve module-oss-mmap latency measurement From c827fca3b9ad589c970c08d792d62e283a8a7852 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 22:25:28 +0000 Subject: [PATCH 0304/1514] prepare for release git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@311 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- configure.ac | 5 +- doc/Makefile.am | 10 +- libtool.m4 | 5951 +++++++++++++++++++++++++++++++++++++++++++++ ltdl.m4 | 431 ++++ polyp/Makefile.am | 2 +- 6 files changed, 6393 insertions(+), 8 deletions(-) create mode 100644 libtool.m4 create mode 100644 ltdl.m4 diff --git a/Makefile.am b/Makefile.am index 9b419d1d9..91f9740b3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,7 +17,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in +EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4 SUBDIRS=polyp doc libltdl MAINTAINERCLEANFILES=README diff --git a/configure.ac b/configure.ac index 332570dd7..47f965e08 100644 --- a/configure.ac +++ b/configure.ac @@ -77,13 +77,16 @@ AC_FUNC_MMAP AC_FUNC_REALLOC AC_FUNC_SETPGRP AC_FUNC_VPRINTF +AC_FUNC_CLOSEDIR_VOID +AC_FUNC_SELECT_ARGTYPES AC_TYPE_SIGNAL AC_TYPE_UID_T -AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul strcasecmp putenv strchr strpbrk strdup getgrgid_r getpwuid_r regcomp]) +AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul strcasecmp putenv strchr strpbrk strdup getgrgid_r getpwuid_r regcomp ftruncate select]) AC_CHECK_LIB(m, pow) AC_CHECK_FUNCS(pow) AC_FUNC_STAT AC_HEADER_SYS_WAIT +AC_HEADER_DIRENT AC_C_BIGENDIAN AC_FUNC_GETGROUPS diff --git a/doc/Makefile.am b/doc/Makefile.am index 001f5b491..f67598f1e 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -30,11 +30,11 @@ CLEANFILES += README endif tidy: README.html cli.html modules.html daemon.html - tidy -qe < README.html - tidy -qe < cli.html - tidy -qe < daemon.html - tidy -qe < modules.html - tidy -qe < FAQ.html + tidy -qe < README.html ; true + tidy -qe < cli.html ; true + tidy -qe < daemon.html ; true + tidy -qe < modules.html ; true + tidy -qe < FAQ.html ; true .PHONY: tidy diff --git a/libtool.m4 b/libtool.m4 new file mode 100644 index 000000000..4f5ac795c --- /dev/null +++ b/libtool.m4 @@ -0,0 +1,5951 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +## As a special exception to the GNU General Public License, if you +## distribute this file as part of a program that contains a +## configuration script generated by Autoconf, you may include it under +## the same distribution terms that you use for the rest of that program. + +# serial 47 AC_PROG_LIBTOOL +# Debian $Rev: 214 $ + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" + ;; + *) + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s conftest.err; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# -------------------- +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ------------------------------------------------------------------ +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_unknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s out/conftest.err; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)"="Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case "$host_cpu" in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`$SED -e 's/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g' /etc/ld.so.conf | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + need_version=yes + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && test "X$CXX" != "Xno"; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 dll's +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +#- set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case "$host_cpu" in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu | knetbsd*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' + else + lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +sco3.2v5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/${ac_tool_prefix}nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + esac + fi + done + IFS="$lt_save_ifs" + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If +# DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will +# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and +# top_srcdir appropriately in the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If +# DIRECTORY is not provided and an installed libltdl is not found, it is +# assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/' +# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single +# quotes!). If your package is not flat and you're not using automake, +# define top_builddir and top_srcdir appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# -------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# +# Check for any special shared library compilation flags. +# +_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= +if test "$GCC" = no; then + case $host_os in + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' + ;; + esac +fi +if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then + AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) + if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[ ]]" >/dev/null; then : + else + AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) + _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no + fi +fi + + +# +# Check to make sure the static flag actually works. +# +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF($1) + +# Report which librarie types wil actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + darwin* | rhapsody*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' + ;; + esac + fi + ;; + esac + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cc + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds it's shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + darwin* | rhapsody*) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' + ;; + esac + fi + ;; + esac + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + dgux*) + case $cc_basename in + ec++) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + *) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC) + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case "$host_cpu" in + ia64*|hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + irix5* | irix6*) + case $cc_basename in + CC) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc) + # Intel C++ + with_gnu_ld=yes + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + cxx) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd* | netbsdelf*-gnu | knetbsd*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + osf3*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sco*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris* | sysv5*) + symcode='[[BDRT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + cxx) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu | knetbsd*-gnu) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + sco*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + *) + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + unixware*) + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $CC in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case "$host_os" in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + linux*) + _LT_AC_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu | knetbsd*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds" + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds" + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=no + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds it's shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi4*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + if test "$GXX" = yes ; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' + ;; + esac + fi + ;; + esac + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10* | hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + *) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd* | netbsdelf*-gnu | knetbsd*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4.2uw2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv5*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && break + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +SED=$lt_cv_path_SED +]) +AC_MSG_RESULT([$SED]) +]) diff --git a/ltdl.m4 b/ltdl.m4 new file mode 100644 index 000000000..aa6a0d134 --- /dev/null +++ b/ltdl.m4 @@ -0,0 +1,431 @@ +## ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- +## Copyright (C) 1999-2000 Free Software Foundation, Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +## As a special exception to the GNU General Public License, if you +## distribute this file as part of a program that contains a +## configuration script generated by Autoconf, you may include it under +## the same distribution terms that you use for the rest of that program. + +# serial 6 AC_LIB_LTDL +# Debian $Rev: 214 $ + +# AC_WITH_LTDL +# ------------ +# Clients of libltdl can use this macro to allow the installer to +# choose between a shipped copy of the ltdl sources or a preinstalled +# version of the library. +AC_DEFUN([AC_WITH_LTDL], +[AC_REQUIRE([AC_LIB_LTDL]) +AC_SUBST([LIBLTDL]) +AC_SUBST([INCLTDL]) + +# Unless the user asks us to check, assume no installed ltdl exists. +use_installed_libltdl=no + +AC_ARG_WITH([included_ltdl], + [ --with-included-ltdl use the GNU ltdl sources included here]) + +if test "x$with_included_ltdl" != xyes; then + # We are not being forced to use the included libltdl sources, so + # decide whether there is a useful installed version we can use. + AC_CHECK_HEADER([ltdl.h], + [AC_CHECK_LIB([ltdl], [lt_dlcaller_register], + [with_included_ltdl=no], + [with_included_ltdl=yes]) + ]) +fi + +if test "x$enable_ltdl_install" != xyes; then + # If the user did not specify an installable libltdl, then default + # to a convenience lib. + AC_LIBLTDL_CONVENIENCE +fi + +if test "x$with_included_ltdl" = xno; then + # If the included ltdl is not to be used. then Use the + # preinstalled libltdl we found. + AC_DEFINE([HAVE_LTDL], 1, + [Define this if a modern libltdl is already installed]) + LIBLTDL=-lltdl +fi + +# Report our decision... +AC_MSG_CHECKING([whether to use included libltdl]) +AC_MSG_RESULT([$with_included_ltdl]) + +AC_CONFIG_SUBDIRS([libltdl]) +])# AC_WITH_LTDL + + +# AC_LIB_LTDL +# ----------- +# Perform all the checks necessary for compilation of the ltdl objects +# -- including compiler checks and header checks. +AC_DEFUN([AC_LIB_LTDL], +[AC_PREREQ(2.50) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_C_CONST]) +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([AC_HEADER_DIRENT]) +AC_REQUIRE([_LT_AC_CHECK_DLFCN]) +AC_REQUIRE([AC_LTDL_ENABLE_INSTALL]) +AC_REQUIRE([AC_LTDL_SHLIBEXT]) +AC_REQUIRE([AC_LTDL_SHLIBPATH]) +AC_REQUIRE([AC_LTDL_SYSSEARCHPATH]) +AC_REQUIRE([AC_LTDL_OBJDIR]) +AC_REQUIRE([AC_LTDL_DLPREOPEN]) +AC_REQUIRE([AC_LTDL_DLLIB]) +AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) +AC_REQUIRE([AC_LTDL_DLSYM_USCORE]) +AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS]) +AC_REQUIRE([AC_LTDL_FUNC_ARGZ]) + +AC_CHECK_HEADERS([assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ + stdio.h unistd.h]) +AC_CHECK_HEADERS([dl.h sys/dl.h dld.h mach-o/dyld.h]) +AC_CHECK_HEADERS([string.h strings.h], [break]) + +AC_CHECK_FUNCS([strchr index], [break]) +AC_CHECK_FUNCS([strrchr rindex], [break]) +AC_CHECK_FUNCS([memcpy bcopy], [break]) +AC_CHECK_FUNCS([memmove strcmp]) +AC_CHECK_FUNCS([closedir opendir readdir]) +])# AC_LIB_LTDL + + +# AC_LTDL_ENABLE_INSTALL +# ---------------------- +AC_DEFUN([AC_LTDL_ENABLE_INSTALL], +[AC_ARG_ENABLE([ltdl-install], + [AC_HELP_STRING([--enable-ltdl-install], [install libltdl])]) + +AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) +AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno) +])])# AC_LTDL_ENABLE_INSTALL + + +# AC_LTDL_SYS_DLOPEN_DEPLIBS +# -------------------------- +AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_CACHE_CHECK([whether deplibs are loaded by dlopen], + [libltdl_cv_sys_dlopen_deplibs], + [# PORTME does your system automatically load deplibs for dlopen? + # or its logical equivalent (e.g. shl_load for HP-UX < 11) + # For now, we just catch OSes we know something about -- in the + # future, we'll try test this programmatically. + libltdl_cv_sys_dlopen_deplibs=unknown + case "$host_os" in + aix3*|aix4.1.*|aix4.2.*) + # Unknown whether this is true for these versions of AIX, but + # we want this `case' here to explicitly catch those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + aix[[45]]*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + darwin*) + # Assuming the user has installed a libdl from somewhere, this is true + # If you are looking for one http://www.opendarwin.org/projects/dlcompat + libltdl_cv_sys_dlopen_deplibs=yes + ;; + gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) + # GNU and its variants, using gnu ld.so (Glibc) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + hpux10*|hpux11*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + irix[[12345]]*|irix6.[[01]]*) + # Catch all versions of IRIX before 6.2, and indicate that we don't + # know how it worked for any of those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + irix*) + # The case above catches anything before 6.2, and it's known that + # at 6.2 and later dlopen does load deplibs. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + netbsd* | netbsdelf*-gnu) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + openbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + osf[[1234]]*) + # dlopen did load deplibs (at least at 4.x), but until the 5.x series, + # it did *not* use an RPATH in a shared library to find objects the + # library depends on, so we explictly say `no'. + libltdl_cv_sys_dlopen_deplibs=no + ;; + osf5.0|osf5.0a|osf5.1) + # dlopen *does* load deplibs and with the right loader patch applied + # it even uses RPATH in a shared library to search for shared objects + # that the library depends on, but there's no easy way to know if that + # patch is installed. Since this is the case, all we can really + # say is unknown -- it depends on the patch being installed. If + # it is, this changes to `yes'. Without it, it would be `no'. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + osf*) + # the two cases above should catch all versions of osf <= 5.1. Read + # the comments above for what we know about them. + # At > 5.1, deplibs are loaded *and* any RPATH in a shared library + # is used to find them so we can finally say `yes'. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + solaris*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + esac + ]) +if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then + AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], + [Define if the OS needs help to load dependent libraries for dlopen().]) +fi +])# AC_LTDL_SYS_DLOPEN_DEPLIBS + + +# AC_LTDL_SHLIBEXT +# ---------------- +AC_DEFUN([AC_LTDL_SHLIBEXT], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([which extension is used for loadable modules], + [libltdl_cv_shlibext], +[ +module=yes +eval libltdl_cv_shlibext=$shrext_cmds + ]) +if test -n "$libltdl_cv_shlibext"; then + AC_DEFINE_UNQUOTED(LTDL_SHLIB_EXT, "$libltdl_cv_shlibext", + [Define to the extension used for shared libraries, say, ".so".]) +fi +])# AC_LTDL_SHLIBEXT + + +# AC_LTDL_SHLIBPATH +# ----------------- +AC_DEFUN([AC_LTDL_SHLIBPATH], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([which variable specifies run-time library path], + [libltdl_cv_shlibpath_var], [libltdl_cv_shlibpath_var="$shlibpath_var"]) +if test -n "$libltdl_cv_shlibpath_var"; then + AC_DEFINE_UNQUOTED(LTDL_SHLIBPATH_VAR, "$libltdl_cv_shlibpath_var", + [Define to the name of the environment variable that determines the dynamic library search path.]) +fi +])# AC_LTDL_SHLIBPATH + + +# AC_LTDL_SYSSEARCHPATH +# --------------------- +AC_DEFUN([AC_LTDL_SYSSEARCHPATH], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([for the default library search path], + [libltdl_cv_sys_search_path], + [libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"]) +if test -n "$libltdl_cv_sys_search_path"; then + sys_search_path= + for dir in $libltdl_cv_sys_search_path; do + if test -z "$sys_search_path"; then + sys_search_path="$dir" + else + sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" + fi + done + AC_DEFINE_UNQUOTED(LTDL_SYSSEARCHPATH, "$sys_search_path", + [Define to the system default library search path.]) +fi +])# AC_LTDL_SYSSEARCHPATH + + +# AC_LTDL_OBJDIR +# -------------- +AC_DEFUN([AC_LTDL_OBJDIR], +[AC_CACHE_CHECK([for objdir], + [libltdl_cv_objdir], + [libltdl_cv_objdir="$objdir" + if test -n "$objdir"; then + : + else + rm -f .libs 2>/dev/null + mkdir .libs 2>/dev/null + if test -d .libs; then + libltdl_cv_objdir=.libs + else + # MS-DOS does not allow filenames that begin with a dot. + libltdl_cv_objdir=_libs + fi + rmdir .libs 2>/dev/null + fi + ]) +AC_DEFINE_UNQUOTED(LTDL_OBJDIR, "$libltdl_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# AC_LTDL_OBJDIR + + +# AC_LTDL_DLPREOPEN +# ----------------- +AC_DEFUN([AC_LTDL_DLPREOPEN], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) +AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], + [libltdl_cv_preloaded_symbols], + [if test -n "$lt_cv_sys_global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + ]) +if test x"$libltdl_cv_preloaded_symbols" = xyes; then + AC_DEFINE(HAVE_PRELOADED_SYMBOLS, 1, + [Define if libtool can extract symbol lists from object files.]) +fi +])# AC_LTDL_DLPREOPEN + + +# AC_LTDL_DLLIB +# ------------- +AC_DEFUN([AC_LTDL_DLLIB], +[LIBADD_DL= +AC_SUBST(LIBADD_DL) +AC_LANG_PUSH([C]) + +AC_CHECK_FUNC([shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.])], + [AC_CHECK_LIB([dld], [shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.]) + LIBADD_DL="$LIBADD_DL -ldld"], + [AC_CHECK_LIB([dl], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"], + [AC_TRY_LINK([#if HAVE_DLFCN_H +# include +#endif + ], + [dlopen(0, 0);], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"], + [AC_CHECK_LIB([svld], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"], + [AC_CHECK_LIB([dld], [dld_link], + [AC_DEFINE([HAVE_DLD], [1], + [Define if you have the GNU dld library.]) + LIBADD_DL="$LIBADD_DL -ldld"], + [AC_CHECK_FUNC([_dyld_func_lookup], + [AC_DEFINE([HAVE_DYLD], [1], + [Define if you have the _dyld_func_lookup function.])]) + ]) + ]) + ]) + ]) + ]) +]) + +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + AC_CHECK_FUNCS([dlerror]) + LIBS="$lt_save_LIBS" +fi +AC_LANG_POP +])# AC_LTDL_DLLIB + + +# AC_LTDL_SYMBOL_USCORE +# --------------------- +# does the compiler prefix global symbols with an underscore? +AC_DEFUN([AC_LTDL_SYMBOL_USCORE], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) +AC_CACHE_CHECK([for _ prefix in compiled symbols], + [ac_cv_sys_symbol_underscore], + [ac_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC + fi + else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC + fi + rm -rf conftest* + ]) +])# AC_LTDL_SYMBOL_USCORE + + +# AC_LTDL_DLSYM_USCORE +# -------------------- +AC_DEFUN([AC_LTDL_DLSYM_USCORE], +[AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + AC_CACHE_CHECK([whether we have to add an underscore for dlsym], + [libltdl_cv_need_uscore], + [libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + _LT_AC_TRY_DLOPEN_SELF( + [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], + [], [libltdl_cv_need_uscore=cross]) + LIBS="$save_LIBS" + ]) + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + AC_DEFINE(NEED_USCORE, 1, + [Define if dlsym() requires a leading underscore in symbol names.]) +fi +])# AC_LTDL_DLSYM_USCORE + +# AC_LTDL_FUNC_ARGZ +# ----------------- +AC_DEFUN([AC_LTDL_FUNC_ARGZ], +[AC_CHECK_HEADERS([argz.h]) + +AC_CHECK_TYPES([error_t], + [], + [AC_DEFINE([error_t], [int], + [Define to a type to use for `error_t' if it is not otherwise available.])], + [#if HAVE_ARGZ_H +# include +#endif]) + +AC_CHECK_FUNCS([argz_append argz_create_sep argz_insert argz_next argz_stringify]) +])# AC_LTDL_FUNC_ARGZ diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 1bae9afcd..8c91ae4bf 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -565,7 +565,7 @@ pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(X_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) -libpolyp_@PA_MAJORMINOR@_la_SOURCES += x11prop.c client-conf-x11.c +libpolyp_@PA_MAJORMINOR@_la_SOURCES += x11prop.c x11prop.h client-conf-x11.c client-conf-x11.h endif From 29ec9d343b3163c03d491170a2182366e26b3408 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 Nov 2004 13:00:53 +0000 Subject: [PATCH 0305/1514] * some fixes for MacOS X by Conrad Parker * Minor build fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@312 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- doc/Makefile.am | 2 +- polyp/Makefile.am | 2 +- polyp/mcalign-test.c | 2 +- polyp/pid.c | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 47f965e08..4db6b5b9f 100644 --- a/configure.ac +++ b/configure.ac @@ -168,7 +168,7 @@ if test x$lynx = xyes ; then AC_CHECK_PROG(have_lynx, lynx, yes, no) if test x$have_lynx = xno ; then - AC_MSG_ERROR([*** Sorry, you have to install lynx or use --disable-lynx ***]) + AC_MSG_WARN([*** lynx not found, plain text README will not be built ***]) fi fi diff --git a/doc/Makefile.am b/doc/Makefile.am index f67598f1e..fff065510 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -19,7 +19,7 @@ noinst_DATA = README.html cli.html modules.html daemon.html README EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in todo FAQ.html.in -MAINTAINERCLEANFILES = README README.html cli.html modules.html daemon.html FAQ.html +MAINTAINERCLEANFILES = README.html cli.html modules.html daemon.html FAQ.html CLEANFILES = if USE_LYNX diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 8c91ae4bf..db508d7af 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -729,7 +729,7 @@ daemon.conf: daemon.conf.in Makefile -e 's,@DEFAULT_CONFIG_FILE\@,$(polypconfdir)/daemon.conf,g' < $< > $@ install-exec-hook: - chown root $(DESTDIR)$(bindir)/polypaudio + chown root $(DESTDIR)$(bindir)/polypaudio ; true chmod u+s $(DESTDIR)$(bindir)/polypaudio ln -s pacat $(DESTDIR)$(bindir)/parec diff --git a/polyp/mcalign-test.c b/polyp/mcalign-test.c index f8af4f9fc..e4a6a2393 100644 --- a/polyp/mcalign-test.c +++ b/polyp/mcalign-test.c @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) { break; pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length); - fprintf(stderr, "Wrote %u bytes.\n", t.length); + fprintf(stderr, "Wrote %lu bytes.\n", (unsigned long) t.length); pa_memblock_unref(t.memblock); } diff --git a/polyp/pid.c b/polyp/pid.c index 232de216e..32365136f 100644 --- a/polyp/pid.c +++ b/polyp/pid.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include From 758647868faf4c37845a3b572544313a34e5c579 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 Nov 2004 13:34:59 +0000 Subject: [PATCH 0306/1514] * install fix * use syslog as standard log target when run from esdcompat.sh git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@313 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 2 +- polyp/esdcompat.sh.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index db508d7af..7338b9e66 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -731,7 +731,7 @@ daemon.conf: daemon.conf.in Makefile install-exec-hook: chown root $(DESTDIR)$(bindir)/polypaudio ; true chmod u+s $(DESTDIR)$(bindir)/polypaudio - ln -s pacat $(DESTDIR)$(bindir)/parec + ln -sf pacat $(DESTDIR)$(bindir)/parec $(SYMDEF_FILES): module-defs.h.m4 $(M4) -Dfname="$@" $< > $@ diff --git a/polyp/esdcompat.sh.in b/polyp/esdcompat.sh.in index dd94bfea0..76023f52a 100755 --- a/polyp/esdcompat.sh.in +++ b/polyp/esdcompat.sh.in @@ -26,7 +26,7 @@ fail() { exit 1 } -ARGS="" +ARGS=" --log-target=syslog" for N in $(seq $#) ; do From 9a9309f5938ecc2b79af72f1921ebd9178c029e4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Nov 2004 00:07:24 +0000 Subject: [PATCH 0307/1514] * use setresuid() instead of setruid() if available * if fix for the non-fp resampler git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@314 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 3 +++ polyp/caps.c | 19 +++++++++++++------ polyp/resampler.c | 4 ++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 4db6b5b9f..3ab9491ff 100644 --- a/configure.ac +++ b/configure.ac @@ -96,6 +96,9 @@ AC_SUBST(CAP_LIBS) AC_CHECK_HEADERS(sys/capability.h) +AC_CHECK_FUNCS(setresuid) +AC_CHECK_FUNCS(setreuid) + PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) AC_SUBST(LIBSAMPLERATE_CFLAGS) AC_SUBST(LIBSAMPLERATE_LIBS) diff --git a/polyp/caps.c b/polyp/caps.c index 34d97eb56..93fca89f1 100644 --- a/polyp/caps.c +++ b/polyp/caps.c @@ -23,6 +23,9 @@ #include #endif +/* setresuid() is only available on GNU */ +#define _GNU_SOURCE + #include #include #include @@ -41,13 +44,17 @@ void pa_drop_root(void) { if (uid == 0 || geteuid() != 0) return; - -/* pa_log(__FILE__": dropping root rights.\n"); */ - - setreuid(uid, uid); -/* setuid(uid); - seteuid(uid);*/ + /* pa_log(__FILE__": dropping root rights.\n"); */ + +#if defined(HAVE_SETRESUID) + setresuid(uid, uid, uid); +#elif defined(HAVE_SETREUID) + setreuid(uid, uid); +#else + setuid(uid); + seteuid(uid); +#endif } #ifdef HAVE_SYS_CAPABILITY_H diff --git a/polyp/resampler.c b/polyp/resampler.c index 377aa7975..68c0129ad 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -342,8 +342,8 @@ static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, st unsigned j; j = (i->o_counter * r->i_ss.rate / r->o_ss.rate); - assert(j >= i->i_counter); - j = j - i->i_counter; + + j = j > i->i_counter ? j - i->i_counter : 0; if (j >= nframes) break; From 7f3c92bad94b2eada69b4303a3f18d2b52a6d8bf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 27 Nov 2004 14:00:59 +0000 Subject: [PATCH 0308/1514] * fix autospawn lock file creation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@315 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 899a81765..517fcbeb4 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -592,6 +592,7 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons char lf[PATH_MAX]; pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); + pa_make_secure_parent_dir(lf); assert(c->autospawn_lock_fd <= 0); c->autospawn_lock_fd = pa_lock_lockfile(lf); From 5be9641ffe18c482294c99345306c382ba4cf750 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 27 Nov 2004 18:50:29 +0000 Subject: [PATCH 0309/1514] * really fix integer only resampler git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@316 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/resampler.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/polyp/resampler.c b/polyp/resampler.c index 68c0129ad..28e49209d 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -333,7 +333,7 @@ static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, st unsigned o_index; /* The length of the new memory block rounded up */ - l = ((nframes * r->o_ss.rate + r->i_ss.rate - 1) / r->i_ss.rate) * fz; + l = ((((nframes+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz; out->index = 0; out->memblock = pa_memblock_new(l, r->memblock_stat); @@ -342,12 +342,11 @@ static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, st unsigned j; j = (i->o_counter * r->i_ss.rate / r->o_ss.rate); - j = j > i->i_counter ? j - i->i_counter : 0; if (j >= nframes) break; - + assert(o_index*fz < out->memblock->length); memcpy((uint8_t*) out->memblock->data + fz*o_index, @@ -357,15 +356,15 @@ static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, st out->length = o_index*fz; } - - /* Normalize the output counter */ - while (i->o_counter >= r->o_ss.rate) - i->o_counter -= r->o_ss.rate; i->i_counter += nframes; - while (i->i_counter >= r->i_ss.rate) + /* Normalize counters */ + while (i->i_counter >= r->i_ss.rate) { i->i_counter -= r->i_ss.rate; + assert(i->o_counter >= r->o_ss.rate); + i->o_counter -= r->o_ss.rate; + } } static void trivial_free(struct pa_resampler *r) { From 73eabece3365c1bb47bf6b009682219c4492fda5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 11 Dec 2004 00:10:41 +0000 Subject: [PATCH 0310/1514] * add first part of zeroconf publisher * bump version to 0.7.1. * improve logging subsystem (introducing log levels) * remove verbose flag on cli * add new API pa_sample_format_to_string() * replace strtol() by usages of pa_atou() and pa_atoi() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@317 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 8 +- polyp/Makefile.am | 21 +++- polyp/caps.c | 4 +- polyp/cli-command.c | 224 +++++++++++++++++-------------------- polyp/cli-command.h | 9 +- polyp/cli.c | 5 +- polyp/client.c | 6 +- polyp/client.h | 2 +- polyp/cmdline.c | 26 +++-- polyp/conf-parser.c | 11 +- polyp/daemon-conf.c | 77 ++++++++++--- polyp/daemon-conf.h | 3 +- polyp/dumpmodules.c | 2 +- polyp/log.c | 74 ++++++++++-- polyp/log.h | 27 ++++- polyp/main.c | 37 +++--- polyp/memblockq.c | 4 +- polyp/modargs.c | 20 +--- polyp/module-combine.c | 8 +- polyp/module-defs.h.m4 | 11 +- polyp/module-match.c | 15 ++- polyp/module-oss-mmap.c | 4 +- polyp/module-oss.c | 10 +- polyp/module-tunnel.c | 4 +- polyp/module-x11-bell.c | 4 +- polyp/module-x11-publish.c | 4 +- polyp/module.c | 8 +- polyp/namereg.c | 17 ++- polyp/pid.c | 8 +- polyp/protocol-native.c | 6 +- polyp/sample.c | 13 ++- polyp/sample.h | 5 +- polyp/sink-input.c | 4 +- polyp/sink.c | 4 +- polyp/source-output.c | 6 + polyp/source.c | 4 +- polyp/util.c | 49 ++++++-- polyp/util.h | 3 + 38 files changed, 467 insertions(+), 280 deletions(-) diff --git a/configure.ac b/configure.ac index 3ab9491ff..5a4a4646b 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.7],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.7.1],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) @@ -125,6 +125,12 @@ AC_SUBST(GLIB12_LIBS) AC_SUBST(HAVE_GLIB12) AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) +PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], HAVE_HOWL=1, HAVE_HOWL=0) +AC_SUBST(HOWL_CFLAGS) +AC_SUBST(HOWL_LIBS) +AC_SUBST(HAVE_HOWL) +AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1]) + AC_PATH_PROG([M4], [m4 gm4], [no]) if test "x$M4" = xno ; then AC_MSG_ERROR([m4 missing]) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 7338b9e66..83b5670a6 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -156,7 +156,8 @@ SYMDEF_FILES= \ module-tunnel-sink-symdef.h \ module-tunnel-source-symdef.h \ module-null-sink-symdef.h \ - module-esound-sink-symdef.h + module-esound-sink-symdef.h \ + module-zeroconf-publish-symdef.h EXTRA_DIST+=$(SYMDEF_FILES) BUILT_SOURCES+=$(SYMDEF_FILES) @@ -596,6 +597,24 @@ module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) endif +### HOWL modules +if HAVE_HOWL +modlib_LTLIBRARIES+= \ + libhowl-wrap.la \ + module-zeroconf-publish.la + +libhowl_wrap_la_SOURCES = howl-wrap.c howl-wrap.h +libhowl_wrap_la_LDFLAGS = -avoid-version +libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) +libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) + +module_zeroconf_publish_la_SOURCES = module-zeroconf-publish.c +module_zeroconf_publish_la_LDFLAGS = -module -avoid-version +module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la +module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) + +endif + ### GLIB 2.0 support if HAVE_GLIB20 diff --git a/polyp/caps.c b/polyp/caps.c index 93fca89f1..01ed15197 100644 --- a/polyp/caps.c +++ b/polyp/caps.c @@ -45,7 +45,7 @@ void pa_drop_root(void) { if (uid == 0 || geteuid() != 0) return; - /* pa_log(__FILE__": dropping root rights.\n"); */ + pa_log_info(__FILE__": dropping root rights.\n"); #if defined(HAVE_SETRESUID) setresuid(uid, uid, uid); @@ -76,7 +76,7 @@ int pa_limit_caps(void) { if (cap_set_proc(caps) < 0) goto fail; -/* pa_log(__FILE__": dropped capabilities successfully.\n"); */ + pa_log_info(__FILE__": dropped capabilities successfully.\n"); r = 0; diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 72e04bf89..0e8e09a56 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -48,45 +48,50 @@ #include "xmalloc.h" #include "sound-file-stream.h" #include "props.h" +#include "util.h" struct command { const char *name; - int (*proc) (struct pa_core *c, struct pa_tokenizer*t, struct pa_strbuf *buf, int *fail, int *verbose); + int (*proc) (struct pa_core *c, struct pa_tokenizer*t, struct pa_strbuf *buf, int *fail); const char *help; unsigned args; }; +#define INCLUDE_META ".include" +#define FAIL_META ".fail" +#define NOFAIL_META ".nofail" + /* Prototypes for all available commands */ -static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_scache_load_dir(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); -static int pa_cli_command_list_props(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_scache_load_dir(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_list_props(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); /* A method table for all available commands */ @@ -134,22 +139,21 @@ static const char whitespace[] = " \t\n\r"; static const char linebreak[] = "\n\r"; static uint32_t parse_index(const char *n) { - long index; - char *x; - index = strtol(n, &x, 0); - if (!x || *x != 0 || index < 0) + uint32_t index; + + if (pa_atou(n, &index) < 0) return (uint32_t) PA_IDXSET_INVALID; - return (uint32_t) index; + return index; } -static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { assert(c && c->mainloop && t); c->mainloop->quit(c->mainloop, 0); return 0; } -static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const struct command*command; assert(c && t && buf); @@ -161,7 +165,7 @@ static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct return 0; } -static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { char *s; assert(c && t); s = pa_module_list_to_string(c); @@ -171,7 +175,7 @@ static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, str return 0; } -static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { char *s; assert(c && t); s = pa_client_list_to_string(c); @@ -181,7 +185,7 @@ static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, str return 0; } -static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { char *s; assert(c && t); s = pa_sink_list_to_string(c); @@ -191,7 +195,7 @@ static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struc return 0; } -static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { char *s; assert(c && t); s = pa_source_list_to_string(c); @@ -201,7 +205,7 @@ static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, str return 0; } -static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { char *s; assert(c && t); s = pa_sink_input_list_to_string(c); @@ -211,7 +215,7 @@ static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { char *s; assert(c && t); s = pa_source_output_list_to_string(c); @@ -221,7 +225,7 @@ static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer return 0; } -static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { char s[256]; assert(c && t); @@ -249,24 +253,23 @@ static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct return 0; } -static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { assert(c && t); - pa_cli_command_stat(c, t, buf, fail, verbose); - pa_cli_command_modules(c, t, buf, fail, verbose); - pa_cli_command_sinks(c, t, buf, fail, verbose); - pa_cli_command_sources(c, t, buf, fail, verbose); - pa_cli_command_clients(c, t, buf, fail, verbose); - pa_cli_command_sink_inputs(c, t, buf, fail, verbose); - pa_cli_command_source_outputs(c, t, buf, fail, verbose); - pa_cli_command_scache_list(c, t, buf, fail, verbose); - pa_cli_command_autoload_list(c, t, buf, fail, verbose); + pa_cli_command_stat(c, t, buf, fail); + pa_cli_command_modules(c, t, buf, fail); + pa_cli_command_sinks(c, t, buf, fail); + pa_cli_command_sources(c, t, buf, fail); + pa_cli_command_clients(c, t, buf, fail); + pa_cli_command_sink_inputs(c, t, buf, fail); + pa_cli_command_source_outputs(c, t, buf, fail); + pa_cli_command_scache_list(c, t, buf, fail); + pa_cli_command_autoload_list(c, t, buf, fail); return 0; } -static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { struct pa_module *m; const char *name; - char txt[256]; assert(c && t); if (!(name = pa_tokenizer_get(t, 1))) { @@ -279,14 +282,10 @@ static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct return -1; } - if (*verbose) { - snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index); - pa_strbuf_puts(buf, txt); - } return 0; } -static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { struct pa_module *m; uint32_t index; const char *i; @@ -308,11 +307,10 @@ static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, stru return 0; } -static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *n, *v; - char *x = NULL; struct pa_sink *sink; - long volume; + uint32_t volume; if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n"); @@ -324,8 +322,7 @@ static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, return -1; } - volume = strtol(v, &x, 0); - if (!x || *x != 0 || volume < 0) { + if (pa_atou(v, &volume) < 0) { pa_strbuf_puts(buf, "Failed to parse volume.\n"); return -1; } @@ -339,12 +336,11 @@ static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *n, *v; struct pa_sink_input *si; - long volume; + uint32_t volume; uint32_t index; - char *x; if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n"); @@ -361,9 +357,7 @@ static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokeniz return -1; } - x = NULL; - volume = strtol(v, &x, 0); - if (!x || *x != 0 || volume < 0) { + if (pa_atou(v, &volume) < 0) { pa_strbuf_puts(buf, "Failed to parse volume.\n"); return -1; } @@ -377,7 +371,7 @@ static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokeniz return 0; } -static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *n; assert(c && t); @@ -390,7 +384,7 @@ static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t return 0; } -static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *n; assert(c && t); @@ -403,7 +397,7 @@ static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer return 0; } -static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *n; struct pa_client *client; uint32_t index; @@ -428,7 +422,7 @@ static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *n; struct pa_sink_input *sink_input; uint32_t index; @@ -453,7 +447,7 @@ static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer return 0; } -static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *n; struct pa_source_output *source_output; uint32_t index; @@ -478,7 +472,7 @@ static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokeni return 0; } -static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { char *s; assert(c && t); s = pa_scache_list_to_string(c); @@ -488,10 +482,10 @@ static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *n, *sink_name; struct pa_sink *sink; - assert(c && t && buf && fail && verbose); + assert(c && t && buf && fail); if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) { pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n"); @@ -511,9 +505,9 @@ static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *n; - assert(c && t && buf && fail && verbose); + assert(c && t && buf && fail); if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sample name.\n"); @@ -528,10 +522,10 @@ static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer * return 0; } -static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *fname, *n; int r; - assert(c && t && buf && fail && verbose); + assert(c && t && buf && fail); if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n"); @@ -549,9 +543,9 @@ static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_scache_load_dir(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_scache_load_dir(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *pname; - assert(c && t && buf && fail && verbose); + assert(c && t && buf && fail); if (!(pname = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a path name.\n"); @@ -566,10 +560,10 @@ static int pa_cli_command_scache_load_dir(struct pa_core *c, struct pa_tokenizer return 0; } -static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *fname, *sink_name; struct pa_sink *sink; - assert(c && t && buf && fail && verbose); + assert(c && t && buf && fail); if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) { pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n"); @@ -585,9 +579,9 @@ static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, s return pa_play_file(sink, fname, PA_VOLUME_NORM); } -static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *a, *b; - assert(c && t && buf && fail && verbose); + assert(c && t && buf && fail); if (!(a = pa_tokenizer_get(t, 1)) || !(b = pa_tokenizer_get(t, 2))) { pa_strbuf_puts(buf, "You need to specify a device name, a filename or a module name and optionally module arguments\n"); @@ -599,9 +593,9 @@ static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t return 0; } -static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { const char *name; - assert(c && t && buf && fail && verbose); + assert(c && t && buf && fail); if (!(name = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a device name\n"); @@ -616,7 +610,7 @@ static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer return 0; } -static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { char *s; assert(c && t); s = pa_autoload_list_to_string(c); @@ -626,13 +620,13 @@ static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer * return 0; } -static int pa_cli_command_list_props(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_list_props(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { assert(c && t); pa_property_dump(c, buf); return 0; } -static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { +static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { struct pa_module *m; struct pa_sink *s; int nl; @@ -724,7 +718,7 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct } -int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) { +int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail) { const char *cs; cs = s+strspn(s, whitespace); @@ -732,28 +726,18 @@ int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strb if (*cs == '#' || !*cs) return 0; else if (*cs == '.') { - static const char fail_meta[] = ".fail"; - static const char nofail_meta[] = ".nofail"; - static const char verbose_meta[] = ".verbose"; - static const char noverbose_meta[] = ".noverbose"; - - if (!strcmp(cs, verbose_meta)) - *verbose = 1; - else if (!strcmp(cs, noverbose_meta)) - *verbose = 0; - else if (!strcmp(cs, fail_meta)) + if (!strcmp(cs, FAIL_META)) *fail = 1; - else if (!strcmp(cs, nofail_meta)) + else if (!strcmp(cs, NOFAIL_META)) *fail = 0; else { size_t l; - static const char include_meta[] = ".include"; l = strcspn(cs, whitespace); - if (l == sizeof(include_meta)-1 && !strncmp(cs, include_meta, l)) { + if (l == sizeof(INCLUDE_META)-1 && !strncmp(cs, INCLUDE_META, l)) { const char *filename = cs+l+strspn(cs+l, whitespace); - if (pa_cli_command_execute_file(c, filename, buf, fail, verbose) < 0) + if (pa_cli_command_execute_file(c, filename, buf, fail) < 0) if (*fail) return -1; } else { pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs); @@ -772,7 +756,7 @@ int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strb int ret; struct pa_tokenizer *t = pa_tokenizer_new(cs, command->args); assert(t); - ret = command->proc(c, t, buf, fail, verbose); + ret = command->proc(c, t, buf, fail); pa_tokenizer_free(t); unknown = 0; @@ -792,7 +776,7 @@ int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strb return 0; } -int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_strbuf *buf, int *fail, int *verbose) { +int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_strbuf *buf, int *fail) { char line[256]; FILE *f = NULL; int ret = -1; @@ -805,20 +789,14 @@ int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_str goto fail; } - if (*verbose) - pa_strbuf_printf(buf, "Executing file: '%s'\n", fn); - while (fgets(line, sizeof(line), f)) { char *e = line + strcspn(line, linebreak); *e = 0; - if (pa_cli_command_execute_line(c, line, buf, fail, verbose) < 0 && *fail) + if (pa_cli_command_execute_line(c, line, buf, fail) < 0 && *fail) goto fail; } - if (*verbose) - pa_strbuf_printf(buf, "Executed file: '%s'\n", fn); - ret = 0; fail: @@ -828,16 +806,16 @@ fail: return ret; } -int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) { +int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail) { const char *p; - assert(c && s && buf && fail && verbose); + assert(c && s && buf && fail); p = s; while (*p) { size_t l = strcspn(p, linebreak); char *line = pa_xstrndup(p, l); - if (pa_cli_command_execute_line(c, line, buf, fail, verbose) < 0&& *fail) { + if (pa_cli_command_execute_line(c, line, buf, fail) < 0&& *fail) { pa_xfree(line); return -1; } diff --git a/polyp/cli-command.h b/polyp/cli-command.h index 4887c55e2..7af9d014b 100644 --- a/polyp/cli-command.h +++ b/polyp/cli-command.h @@ -27,15 +27,14 @@ /* Execute a single CLI command. Write the results to the string * buffer *buf. If *fail is non-zero the function will return -1 when - * one or more of the executed commands failed. If *verbose is - * non-zero the command is executed verbosely. Both *verbose and *fail + * one or more of the executed commands failed. *fail * may be modified by the function call. */ -int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose); +int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail); /* Execute a whole file of CLI commands */ -int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_strbuf *buf, int *fail, int *verbose); +int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_strbuf *buf, int *fail); /* Split the specified string into lines and run pa_cli_command_execute_line() for each. */ -int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose); +int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail); #endif diff --git a/polyp/cli.c b/polyp/cli.c index 7780d03d8..04fbb7e08 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -55,7 +55,7 @@ struct pa_cli { struct pa_client *client; - int fail, verbose, kill_requested, defer_kill; + int fail, kill_requested, defer_kill; }; static void line_callback(struct pa_ioline *line, const char *s, void *userdata); @@ -85,7 +85,6 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct pa_ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"PROMPT); c->fail = c->kill_requested = c->defer_kill = 0; - c->verbose = 1; return c; } @@ -129,7 +128,7 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) buf = pa_strbuf_new(); assert(buf); c->defer_kill++; - pa_cli_command_execute_line(c->core, s, buf, &c->fail, &c->verbose); + pa_cli_command_execute_line(c->core, s, buf, &c->fail); c->defer_kill--; pa_ioline_puts(line, p = pa_strbuf_tostring_free(buf)); pa_xfree(p); diff --git a/polyp/client.c b/polyp/client.c index 22c7197a1..40f5e3858 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -50,7 +50,7 @@ struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, r = pa_idxset_put(core->clients, c, &c->index); assert(c->index != PA_IDXSET_INVALID && r >= 0); - pa_log(__FILE__": created %u \"%s\"\n", c->index, c->name); + pa_log_info(__FILE__": created %u \"%s\"\n", c->index, c->name); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); pa_core_check_quit(core); @@ -65,7 +65,7 @@ void pa_client_free(struct pa_client *c) { pa_core_check_quit(c->core); - pa_log(__FILE__": freed %u \"%s\"\n", c->index, c->name); + pa_log_info(__FILE__": freed %u \"%s\"\n", c->index, c->name); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_xfree(c->name); pa_xfree(c->protocol_name); @@ -76,7 +76,7 @@ void pa_client_free(struct pa_client *c) { void pa_client_kill(struct pa_client *c) { assert(c); if (!c->kill) { - pa_log(__FILE__": kill() operation not implemented for client %u\n", c->index); + pa_log_warn(__FILE__": kill() operation not implemented for client %u\n", c->index); return; } diff --git a/polyp/client.h b/polyp/client.h index 58c5ee319..324bb27cb 100644 --- a/polyp/client.h +++ b/polyp/client.h @@ -35,7 +35,7 @@ struct pa_client { struct pa_module *owner; char *name; struct pa_core *core; - const char *protocol_name; + char *protocol_name; void (*kill)(struct pa_client *c); void *userdata; diff --git a/polyp/cmdline.c b/polyp/cmdline.c index a39f6ca60..0951725a1 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -43,7 +43,7 @@ enum { ARG_DUMP_MODULES, ARG_DAEMONIZE, ARG_FAIL, - ARG_VERBOSE, + ARG_LOG_LEVEL, ARG_HIGH_PRIORITY, ARG_DISALLOW_MODULE_LOADING, ARG_EXIT_IDLE_TIME, @@ -67,7 +67,8 @@ static struct option long_options[] = { {"dump-modules", 0, 0, ARG_DUMP_MODULES}, {"daemonize", 2, 0, ARG_DAEMONIZE}, {"fail", 2, 0, ARG_FAIL}, - {"verbose", 2, 0, ARG_VERBOSE}, + {"verbose", 2, 0, ARG_LOG_LEVEL}, + {"log-level", 2, 0, ARG_LOG_LEVEL}, {"high-priority", 2, 0, ARG_HIGH_PRIORITY}, {"disallow-module-loading", 2, 0, ARG_DISALLOW_MODULE_LOADING}, {"exit-idle-time", 2, 0, ARG_EXIT_IDLE_TIME}, @@ -104,7 +105,6 @@ void pa_cmdline_help(const char *argv0) { "OPTIONS:\n" " -D, --daemonize[=BOOL] Daemonize after startup\n" " --fail[=BOOL] Quit when startup fails\n" - " --verbose[=BOOL] Be slightly more verbose\n" " --high-priority[=BOOL] Try to set high process priority\n" " (only available as root)\n" " --disallow-module-loading[=BOOL] Disallow module loading after startup\n" @@ -114,6 +114,8 @@ void pa_cmdline_help(const char *argv0) { " this time passed\n" " --scache-idle-time=SECS Unload autoloaded samples when idle and\n" " this time passed\n" + " --log-level[=LEVEL] Increase or set verbosity level\n" + " -v Increase the verbosity level\n" " --log-target={auto,syslog,stderr} Specify the log target\n" " -p, --dl-search-path=PATH Set the search path for dynamic shared\n" " objects (plugins)\n" @@ -143,7 +145,7 @@ int pa_cmdline_parse(struct pa_daemon_conf *conf, int argc, char *const argv [], if (conf->script_commands) pa_strbuf_puts(buf, conf->script_commands); - while ((c = getopt_long(argc, argv, "L:F:ChDnp:k", long_options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "L:F:ChDnp:kv", long_options, NULL)) != -1) { switch (c) { case ARG_HELP: case 'h': @@ -200,11 +202,19 @@ int pa_cmdline_parse(struct pa_daemon_conf *conf, int argc, char *const argv [], } break; - case ARG_VERBOSE: - if ((conf->verbose = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --verbose expects boolean argument\n"); - goto fail; + case 'v': + case ARG_LOG_LEVEL: + + if (optarg) { + if (pa_daemon_conf_set_log_level(conf, optarg) < 0) { + pa_log(__FILE__": --log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error).\n"); + goto fail; + } + } else { + if (conf->log_level < PA_LOG_LEVEL_MAX-1) + conf->log_level++; } + break; case ARG_HIGH_PRIORITY: diff --git a/polyp/conf-parser.c b/polyp/conf-parser.c index 35c4766e3..b25508e2d 100644 --- a/polyp/conf-parser.c +++ b/polyp/conf-parser.c @@ -135,17 +135,16 @@ finish: } int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { - int *i = data, k; - char *x = NULL; + int *i = data; + int32_t k; assert(filename && lvalue && rvalue && data); - - k = strtol(rvalue, &x, 0); - if (!*rvalue || !x || *x) { + + if (pa_atoi(rvalue, &k) < 0) { pa_log(__FILE__": [%s:%u] Failed to parse numeric value: %s\n", filename, line, rvalue); return -1; } - *i = k; + *i = (int) k; return 0; } diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index 7753da6af..a6afd05a5 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -53,7 +53,6 @@ static const struct pa_daemon_conf default_conf = { .cmd = PA_CMD_DAEMON, .daemonize = 0, .fail = 1, - .verbose = 0, .high_priority = 0, .disallow_module_loading = 0, .exit_idle_time = -1, @@ -64,6 +63,7 @@ static const struct pa_daemon_conf default_conf = { .dl_search_path = NULL, .default_script_file = NULL, .log_target = PA_LOG_SYSLOG, + .log_level = PA_LOG_NOTICE, .resample_method = PA_RESAMPLER_SRC_SINC_FASTEST, .config_file = NULL, .use_pid_file = 1 @@ -108,6 +108,31 @@ int pa_daemon_conf_set_log_target(struct pa_daemon_conf *c, const char *string) return 0; } +int pa_daemon_conf_set_log_level(struct pa_daemon_conf *c, const char *string) { + uint32_t u; + assert(c && string); + + if (pa_atou(string, &u) >= 0) { + if (u >= PA_LOG_LEVEL_MAX) + return -1; + + c->log_level = (enum pa_log_level) u; + } else if (pa_startswith(string, "debug")) + c->log_level = PA_LOG_DEBUG; + else if (pa_startswith(string, "info")) + c->log_level = PA_LOG_INFO; + else if (pa_startswith(string, "notice")) + c->log_level = PA_LOG_NOTICE; + else if (pa_startswith(string, "warn")) + c->log_level = PA_LOG_WARN; + else if (pa_startswith(string, "err")) + c->log_level = PA_LOG_ERROR; + else + return -1; + + return 0; +} + int pa_daemon_conf_set_resample_method(struct pa_daemon_conf *c, const char *string) { int m; assert(c && string); @@ -131,6 +156,18 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva return 0; } +static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { + struct pa_daemon_conf *c = data; + assert(filename && lvalue && rvalue && data); + + if (pa_daemon_conf_set_log_level(c, rvalue) < 0) { + pa_log(__FILE__": [%s:%u] Invalid log level '%s'.\n", filename, line, rvalue); + return -1; + } + + return 0; +} + static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { struct pa_daemon_conf *c = data; assert(filename && lvalue && rvalue && data); @@ -148,7 +185,6 @@ int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename) { FILE *f = NULL; struct pa_config_item table[] = { - { "verbose", pa_config_parse_bool, NULL }, { "daemonize", pa_config_parse_bool, NULL }, { "fail", pa_config_parse_bool, NULL }, { "high-priority", pa_config_parse_bool, NULL }, @@ -159,24 +195,27 @@ int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename) { { "dl-search-path", pa_config_parse_string, NULL }, { "default-script-file", pa_config_parse_string, NULL }, { "log-target", parse_log_target, NULL }, + { "log-level", parse_log_level, NULL }, + { "verbose", parse_log_level, NULL }, { "resample-method", parse_resample_method, NULL }, { "use-pid-file", pa_config_parse_bool, NULL }, { NULL, NULL, NULL }, }; - table[0].data = &c->verbose; - table[1].data = &c->daemonize; - table[2].data = &c->fail; - table[3].data = &c->high_priority; - table[4].data = &c->disallow_module_loading; - table[5].data = &c->exit_idle_time; - table[6].data = &c->module_idle_time; - table[7].data = &c->scache_idle_time; - table[8].data = &c->dl_search_path; - table[9].data = &c->default_script_file; + table[0].data = &c->daemonize; + table[1].data = &c->fail; + table[2].data = &c->high_priority; + table[3].data = &c->disallow_module_loading; + table[4].data = &c->exit_idle_time; + table[5].data = &c->module_idle_time; + table[6].data = &c->scache_idle_time; + table[7].data = &c->dl_search_path; + table[8].data = &c->default_script_file; + table[9].data = c; table[10].data = c; table[11].data = c; - table[12].data = &c->use_pid_file; + table[12].data = c; + table[13].data = &c->use_pid_file; pa_xfree(c->config_file); c->config_file = NULL; @@ -214,13 +253,22 @@ int pa_daemon_conf_env(struct pa_daemon_conf *c) { return 0; } +static const char* const log_level_to_string[] = { + [PA_LOG_DEBUG] = "debug", + [PA_LOG_INFO] = "info", + [PA_LOG_NOTICE] = "notice", + [PA_LOG_WARN] = "warning", + [PA_LOG_ERROR] = "error" +}; + char *pa_daemon_conf_dump(struct pa_daemon_conf *c) { struct pa_strbuf *s = pa_strbuf_new(); if (c->config_file) pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file); + + assert(c->log_level <= PA_LOG_LEVEL_MAX); - pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose); pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize); pa_strbuf_printf(s, "fail = %i\n", !!c->fail); pa_strbuf_printf(s, "high-priority = %i\n", !!c->high_priority); @@ -231,6 +279,7 @@ char *pa_daemon_conf_dump(struct pa_daemon_conf *c) { pa_strbuf_printf(s, "dl-search-path = %s\n", c->dl_search_path ? c->dl_search_path : ""); pa_strbuf_printf(s, "default-script-file = %s\n", c->default_script_file); pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); + pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file); diff --git a/polyp/daemon-conf.h b/polyp/daemon-conf.h index f163400f9..30137e8bb 100644 --- a/polyp/daemon-conf.h +++ b/polyp/daemon-conf.h @@ -40,7 +40,6 @@ struct pa_daemon_conf { enum pa_daemon_conf_cmd cmd; int daemonize, fail, - verbose, high_priority, disallow_module_loading, exit_idle_time, @@ -50,6 +49,7 @@ struct pa_daemon_conf { use_pid_file; char *script_commands, *dl_search_path, *default_script_file; enum pa_log_target log_target; + enum pa_log_level log_level; int resample_method; char *config_file; }; @@ -74,6 +74,7 @@ int pa_daemon_conf_env(struct pa_daemon_conf *c); /* Set these configuration variables in the structure by passing a string */ int pa_daemon_conf_set_log_target(struct pa_daemon_conf *c, const char *string); +int pa_daemon_conf_set_log_level(struct pa_daemon_conf *c, const char *string); int pa_daemon_conf_set_resample_method(struct pa_daemon_conf *c, const char *string); #endif diff --git a/polyp/dumpmodules.c b/polyp/dumpmodules.c index 1903fe005..1dc14edc4 100644 --- a/polyp/dumpmodules.c +++ b/polyp/dumpmodules.c @@ -86,7 +86,7 @@ static int callback(const char *path, lt_ptr data) { e = path; if (strlen(e) > sizeof(PREFIX)-1 && !strncmp(e, PREFIX, sizeof(PREFIX)-1)) - show_info(e, path, c->verbose ? long_info : short_info); + show_info(e, path, c->log_level >= PA_LOG_INFO ? long_info : short_info); return 0; } diff --git a/polyp/log.c b/polyp/log.c index dc41dcd29..530fa6911 100644 --- a/polyp/log.c +++ b/polyp/log.c @@ -34,7 +34,16 @@ static char *log_ident = NULL; static enum pa_log_target log_target = PA_LOG_STDERR; -static void (*user_log_func)(const char *s) = NULL; +static void (*user_log_func)(enum pa_log_level l, const char *s) = NULL; +static enum pa_log_level maximal_level = PA_LOG_NOTICE; + +static const int level_to_syslog[] = { + [PA_LOG_ERROR] = LOG_ERR, + [PA_LOG_WARN] = LOG_WARNING, + [PA_LOG_NOTICE] = LOG_NOTICE, + [PA_LOG_INFO] = LOG_INFO, + [PA_LOG_DEBUG] = LOG_DEBUG +}; void pa_log_set_ident(const char *p) { if (log_ident) @@ -43,34 +52,85 @@ void pa_log_set_ident(const char *p) { log_ident = pa_xstrdup(p); } -void pa_log_set_target(enum pa_log_target t, void (*func)(const char*s)) { +void pa_log_set_maximal_level(enum pa_log_level l) { + assert(l < PA_LOG_LEVEL_MAX); + maximal_level = l; +} + +void pa_log_set_target(enum pa_log_target t, void (*func)(enum pa_log_level l, const char*s)) { assert(t == PA_LOG_USER || !func); log_target = t; user_log_func = func; } -void pa_log(const char *format, ...) { - va_list ap; - va_start(ap, format); +void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap) { + assert(level < PA_LOG_LEVEL_MAX); + if (level > maximal_level) + return; + switch (log_target) { case PA_LOG_STDERR: vfprintf(stderr, format, ap); break; + case PA_LOG_SYSLOG: openlog(log_ident ? log_ident : "???", LOG_PID, LOG_USER); - vsyslog(LOG_INFO, format, ap); + vsyslog(level_to_syslog[level], format, ap); closelog(); break; + case PA_LOG_USER: { char *t = pa_vsprintf_malloc(format, ap); assert(user_log_func); - user_log_func(t); + user_log_func(level, t); pa_xfree(t); } + case PA_LOG_NULL: break; } +} + +void pa_log_level(enum pa_log_level level, const char *format, ...) { + va_list ap; + va_start(ap, format); + pa_log_levelv(level, format, ap); + va_end(ap); +} + +void pa_log_debug(const char *format, ...) { + va_list ap; + va_start(ap, format); + pa_log_levelv(PA_LOG_DEBUG, format, ap); + va_end(ap); +} + +void pa_log_info(const char *format, ...) { + va_list ap; + va_start(ap, format); + pa_log_levelv(PA_LOG_INFO, format, ap); + va_end(ap); +} + +void pa_log_notice(const char *format, ...) { + va_list ap; + va_start(ap, format); + pa_log_levelv(PA_LOG_INFO, format, ap); + va_end(ap); +} + +void pa_log_warn(const char *format, ...) { + va_list ap; + va_start(ap, format); + pa_log_levelv(PA_LOG_WARN, format, ap); + va_end(ap); +} + +void pa_log_error(const char *format, ...) { + va_list ap; + va_start(ap, format); + pa_log_levelv(PA_LOG_ERROR, format, ap); va_end(ap); } diff --git a/polyp/log.h b/polyp/log.h index cf55386cd..fe2dad59b 100644 --- a/polyp/log.h +++ b/polyp/log.h @@ -22,6 +22,7 @@ USA. ***/ +#include #include "gcc-printf.h" /* A simple logging subsystem */ @@ -34,13 +35,35 @@ enum pa_log_target { PA_LOG_NULL /* to /dev/null */ }; +enum pa_log_level { + PA_LOG_ERROR = 0, /* Error messages */ + PA_LOG_WARN = 1, /* Warning messages */ + PA_LOG_NOTICE = 2, /* Notice messages */ + PA_LOG_INFO = 3, /* Info messages */ + PA_LOG_DEBUG = 4, /* debug message */ + PA_LOG_LEVEL_MAX +}; + /* Set an identifcation for the current daemon. Used when logging to syslog. */ void pa_log_set_ident(const char *p); /* Set another log target. If t is PA_LOG_USER you may specify a function that is called every log string */ -void pa_log_set_target(enum pa_log_target t, void (*func)(const char*s)); +void pa_log_set_target(enum pa_log_target t, void (*func)(enum pa_log_level, const char*s)); + +/* Minimal log level */ +void pa_log_set_maximal_level(enum pa_log_level l); /* Do a log line */ -void pa_log(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); +void pa_log_debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); +void pa_log_info(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); +void pa_log_notice(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); +void pa_log_warn(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); +void pa_log_error(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); + +void pa_log_level(enum pa_log_level level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); + +void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap); + +#define pa_log pa_log_error #endif diff --git a/polyp/main.c b/polyp/main.c index 0ba28e5a3..f49232d4e 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -64,7 +64,7 @@ int deny_severity = LOG_WARNING; #endif static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { - pa_log(__FILE__": Got signal %s.\n", pa_strsignal(sig)); + pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig)); switch (sig) { case SIGUSR1: @@ -108,7 +108,7 @@ static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, default: return; } - pa_log(c); + pa_log_notice(c); pa_xfree(c); } @@ -118,7 +118,7 @@ static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, case SIGINT: case SIGTERM: default: - pa_log(__FILE__": Exiting.\n"); + pa_log_info(__FILE__": Exiting.\n"); m->quit(m, 1); return; } @@ -150,7 +150,7 @@ int main(int argc, char *argv[]) { suid_root = getuid() != 0 && geteuid() == 0; if (suid_root && (pa_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) { - pa_log(__FILE__": WARNING: called SUID root, but not in group 'realtime'.\n"); + pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'.\n"); pa_drop_root(); } @@ -165,15 +165,16 @@ int main(int argc, char *argv[]) { if (pa_daemon_conf_load(conf, NULL) < 0) goto finish; - + if (pa_daemon_conf_env(conf) < 0) goto finish; - + if (pa_cmdline_parse(conf, argc, argv, &d) < 0) { pa_log(__FILE__": failed to parse command line.\n"); goto finish; } - + + pa_log_set_maximal_level(conf->log_level); pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL); if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) @@ -215,11 +216,9 @@ int main(int argc, char *argv[]) { pid_t pid; if (pa_pid_file_check_running(&pid) < 0) { - if (conf->verbose) - pa_log(__FILE__": daemon not running\n"); + pa_log_info(__FILE__": daemon not running\n"); } else { - if (conf->verbose) - pa_log(__FILE__": daemon running as PID %u\n", pid); + pa_log_info(__FILE__": daemon running as PID %u\n", pid); retval = 0; } @@ -268,8 +267,10 @@ int main(int argc, char *argv[]) { retval = 1; } - if (conf->verbose) - pa_log(__FILE__": daemon startup %s.\n", retval ? "failed" : "succeeded"); + if (retval) + pa_log(__FILE__": daemon startup failed .\n"); + else + pa_log_info(__FILE__": daemon startup successful.\n"); goto finish; } @@ -318,10 +319,10 @@ int main(int argc, char *argv[]) { buf = pa_strbuf_new(); assert(buf); if (conf->default_script_file) - r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail, &conf->verbose); + r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail); if (r >= 0) - r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail, &conf->verbose); + r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); pa_log(s = pa_strbuf_tostring_free(buf)); pa_xfree(s); @@ -345,10 +346,10 @@ int main(int argc, char *argv[]) { c->scache_idle_time = conf->scache_idle_time; c->resample_method = conf->resample_method; - pa_log(__FILE__": Daemon startup complete.\n"); + pa_log_info(__FILE__": Daemon startup complete.\n"); if (pa_mainloop_run(mainloop, &retval) < 0) retval = 1; - pa_log(__FILE__": Daemon shutdown initiated.\n"); + pa_log_info(__FILE__": Daemon shutdown initiated.\n"); } pa_core_free(c); @@ -357,7 +358,7 @@ int main(int argc, char *argv[]) { pa_signal_done(); pa_mainloop_free(mainloop); - pa_log(__FILE__": Daemon terminated.\n"); + pa_log_info(__FILE__": Daemon terminated.\n"); finish: diff --git a/polyp/memblockq.c b/polyp/memblockq.c index 16c0da8e3..3f2e4db1d 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -58,7 +58,7 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b bq->current_length = 0; - /*pa_log(__FILE__": memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq);*/ + pa_log_debug(__FILE__": memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq); bq->base = base; @@ -83,7 +83,7 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b bq->orig_prebuf = bq->prebuf; - pa_log(__FILE__": memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); + pa_log_debug(__FILE__": memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); bq->mcalign = NULL; diff --git a/polyp/modargs.c b/polyp/modargs.c index 406f610fd..9437d839b 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -190,41 +190,27 @@ const char *pa_modargs_get_value(struct pa_modargs *ma, const char *key, const c int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *value) { const char *v; - char *e; - unsigned long l; assert(ma && key && value); if (!(v = pa_modargs_get_value(ma, key, NULL))) return 0; - if (!*v) - return -1; - - l = strtoul(v, &e, 0); - if (*e) + if (pa_atou(v, value) < 0) return -1; - *value = (uint32_t) l; return 0; } int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *value) { const char *v; - char *e; - signed long l; assert(ma && key && value); if (!(v = pa_modargs_get_value(ma, key, NULL))) return 0; - if (!*v) + if (pa_atoi(v, value) < 0) return -1; - - l = strtol(v, &e, 0); - if (*e) - return -1; - - *value = (int32_t) l; + return 0; } diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 95bd958f9..7b3c26dd6 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -111,7 +111,7 @@ static void adjust_rates(struct userdata *u) { target_latency = max_sink_latency > min_total_latency ? max_sink_latency : min_total_latency; - pa_log(__FILE__": [%s] target latency is %0.0f usec.\n", u->sink->name, (float) target_latency); + pa_log_info(__FILE__": [%s] target latency is %0.0f usec.\n", u->sink->name, (float) target_latency); base_rate = u->sink->sample_spec.rate; @@ -124,9 +124,9 @@ static void adjust_rates(struct userdata *u) { r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/ 1000000); if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) - pa_log(__FILE__": [%s] sample rates too different, not adjusting (%u vs. %u).\n", o->sink_input->name, base_rate, r); + pa_log_warn(__FILE__": [%s] sample rates too different, not adjusting (%u vs. %u).\n", o->sink_input->name, base_rate, r); else { - pa_log(__FILE__": [%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.\n", o->sink_input->name, r, (double) r / base_rate, (float) o->total_latency); + pa_log_info(__FILE__": [%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.\n", o->sink_input->name, r, (double) r / base_rate, (float) o->total_latency); pa_sink_input_set_rate(o->sink_input, r); } } @@ -358,7 +358,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { } if (u->n_outputs <= 1) - pa_log(__FILE__": WARNING: no slave sinks specified.\n"); + pa_log_warn(__FILE__": WARNING: no slave sinks specified.\n"); if (u->adjust_time > 0) { gettimeofday(&tv, NULL); diff --git a/polyp/module-defs.h.m4 b/polyp/module-defs.h.m4 index 85eb64a24..2b9cdf9e2 100644 --- a/polyp/module-defs.h.m4 +++ b/polyp/module-defs.h.m4 @@ -1,13 +1,16 @@ dnl $Id$ changecom(`/*', `*/')dnl -define(`module', patsubst(patsubst(fname, `-symdef.h$'), `[^0-9a-zA-Z]', `_'))dnl -define(`c_symbol', patsubst(module, `[^0-9a-zA-Z]', `_'))dnl -define(`c_macro', patsubst(module, `[^0-9a-zA-Z]', `'))dnl +define(`module_name', patsubst(patsubst(fname, `-symdef.h$'), `[^0-9a-zA-Z]', `_'))dnl +define(`c_symbol', patsubst(module_name, `[^0-9a-zA-Z]', `_'))dnl +define(`c_macro', patsubst(module_name, `[^0-9a-zA-Z]', `'))dnl define(`incmacro', `foo'c_macro`symdeffoo')dnl -define(`gen_symbol', `#define $1 'module`_LTX_$1')dnl +define(`gen_symbol', `#define $1 'module_name`_LTX_$1')dnl #ifndef incmacro #define incmacro +#include "core.h" +#include "module.h" + gen_symbol(pa__init) gen_symbol(pa__done) gen_symbol(pa__get_author) diff --git a/polyp/module-match.c b/polyp/module-match.c index 6f4fc38c1..7fdc5f3e0 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -88,8 +88,9 @@ static int load_rules(struct userdata *u, const char *filename) { } while (!feof(f)) { - char *d, *v, *e = NULL; + char *d, *v; pa_volume_t volume; + uint32_t k; regex_t regex; char ln[256]; struct rule *rule; @@ -114,14 +115,14 @@ static int load_rules(struct userdata *u, const char *filename) { } *d = 0; - - volume = (pa_volume_t) strtol(v, &e, 0); - - if (!e || *e) { + if (pa_atou(v, &k) < 0) { pa_log(__FILE__": [%s:%u] failed to parse volume\n", filename, n); goto finish; } + volume = (pa_volume_t) k; + + if (regcomp(®ex, ln, REG_EXTENDED|REG_NOSUB) != 0) { pa_log(__FILE__": [%s:%u] invalid regular expression\n", filename, n); goto finish; @@ -162,10 +163,8 @@ static void callback(struct pa_core *c, enum pa_subscription_event_type t, uint3 if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW)) return; - if (!(si = pa_idxset_get_by_index(c->sink_inputs, index))) { - pa_log(__FILE__": WARNING: failed to get sink input\n"); + if (!(si = pa_idxset_get_by_index(c->sink_inputs, index))) return; - } if (!si->name) return; diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 66daa77d8..6fe4fa0cd 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -289,7 +289,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; } - pa_log(__FILE__": input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log_info(__FILE__": input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); u->in_mmap_length = (u->in_fragment_size = info.fragsize) * (u->in_fragments = info.fragstotal); if ((u->in_mmap = mmap(NULL, u->in_mmap_length, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { @@ -320,7 +320,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; } - pa_log(__FILE__": output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log_info(__FILE__": output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); u->out_mmap_length = (u->out_fragment_size = info.fragsize) * (u->out_fragments = info.fragstotal); if ((u->out_mmap = mmap(NULL, u->out_mmap_length, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { diff --git a/polyp/module-oss.c b/polyp/module-oss.c index fe12b0bb8..fa01876dd 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -214,7 +214,7 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { assert(s && u && u->sink); if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) { - pa_log(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY.\n"); + pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY.\n"); s->get_latency = NULL; return 0; } @@ -230,7 +230,7 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { static pa_usec_t source_get_latency_cb(struct pa_source *s) { struct userdata *u = s->userdata; audio_buf_info info; - assert(s && u && u->sink); + assert(s && u && u->source); if (!u->use_getispace) return 0; @@ -291,7 +291,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, NULL)) < 0) goto fail; - pa_log(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (nfrags >= 2 && frag_size >= 1) @@ -313,13 +313,13 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->use_getospace = u->use_getispace = 0; if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { - pa_log(__FILE__": input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log_info(__FILE__": input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); in_frag_size = info.fragsize; u->use_getispace = 1; } if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { - pa_log(__FILE__": output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log_info(__FILE__": output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); out_frag_size = info.fragsize; u->use_getospace = 1; } diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index 39aaab571..d165aab87 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -545,7 +545,7 @@ static int load_key(struct userdata *u, const char*fn) { u->auth_cookie_in_property = 0; if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { - pa_log(__FILE__": using already loaded auth cookie.\n"); + pa_log_debug(__FILE__": using already loaded auth cookie.\n"); pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); u->auth_cookie_in_property = 1; return 0; @@ -557,7 +557,7 @@ static int load_key(struct userdata *u, const char*fn) { if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) return -1; - pa_log(__FILE__": loading cookie from disk.\n"); + pa_log_debug(__FILE__": loading cookie from disk.\n"); if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) u->auth_cookie_in_property = 1; diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index c39877040..084f5d4be 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -69,7 +69,7 @@ static int ring_bell(struct userdata *u, int percent) { assert(u); if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": Invalid sink\n"); + pa_log(__FILE__": Invalid sink: %s\n", u->sink_name); return -1; } @@ -88,7 +88,7 @@ static int x11_event_callback(struct pa_x11_wrapper *w, XEvent *e, void *userdat bne = (XkbBellNotifyEvent*) e; if (ring_bell(u, bne->percent) < 0) { - pa_log(__FILE__": Ringing bell failed, reverting to X11 device bell.\n"); + pa_log_info(__FILE__": Ringing bell failed, reverting to X11 device bell.\n"); XkbForceDeviceBell(pa_x11_wrapper_get_display(w), bne->device, bne->bell_class, bne->bell_id, bne->percent); } diff --git a/polyp/module-x11-publish.c b/polyp/module-x11-publish.c index 598fe5b5d..a47a76060 100644 --- a/polyp/module-x11-publish.c +++ b/polyp/module-x11-publish.c @@ -77,7 +77,7 @@ static int load_key(struct userdata *u, const char*fn) { u->auth_cookie_in_property = 0; if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { - pa_log(__FILE__": using already loaded auth cookie.\n"); + pa_log_debug(__FILE__": using already loaded auth cookie.\n"); pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); u->auth_cookie_in_property = 1; return 0; @@ -89,7 +89,7 @@ static int load_key(struct userdata *u, const char*fn) { if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) return -1; - pa_log(__FILE__": loading cookie from disk.\n"); + pa_log_debug(__FILE__": loading cookie from disk.\n"); if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) u->auth_cookie_in_property = 1; diff --git a/polyp/module.c b/polyp/module.c index 67d7f44e6..aedaae02a 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -89,7 +89,7 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char assert(m->init); if (m->init(c, m) < 0) { - pa_log(__FILE__": Failed to load module \"%s\" (argument: \"%s\"): initialization failed.\n", name, argument ? argument : ""); + pa_log_error(__FILE__": Failed to load module \"%s\" (argument: \"%s\"): initialization failed.\n", name, argument ? argument : ""); goto fail; } @@ -108,7 +108,7 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char r = pa_idxset_put(c->modules, m, &m->index); assert(r >= 0 && m->index != PA_IDXSET_INVALID); - pa_log(__FILE__": Loaded \"%s\" (index: #%u; argument: \"%s\").\n", m->name, m->index, m->argument ? m->argument : ""); + pa_log_info(__FILE__": Loaded \"%s\" (index: #%u; argument: \"%s\").\n", m->name, m->index, m->argument ? m->argument : ""); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_NEW, m->index); @@ -135,13 +135,13 @@ static void pa_module_free(struct pa_module *m) { if (m->core->disallow_module_loading) return; - pa_log(__FILE__": Unloading \"%s\" (index: #%u).\n", m->name, m->index); + pa_log_info(__FILE__": Unloading \"%s\" (index: #%u).\n", m->name, m->index); m->done(m->core, m); lt_dlclose(m->dl); - pa_log(__FILE__": Unloaded \"%s\" (index: #%u).\n", m->name, m->index); + pa_log_info(__FILE__": Unloaded \"%s\" (index: #%u).\n", m->name, m->index); pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE, m->index); diff --git a/polyp/namereg.c b/polyp/namereg.c index dce8693ff..04601442d 100644 --- a/polyp/namereg.c +++ b/polyp/namereg.c @@ -35,6 +35,7 @@ #include "sink.h" #include "xmalloc.h" #include "subscribe.h" +#include "util.h" struct namereg_entry { enum pa_namereg_type type; @@ -112,8 +113,6 @@ void pa_namereg_unregister(struct pa_core *c, const char *name) { void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type, int autoload) { struct namereg_entry *e; uint32_t index; - char *x = NULL; - void *d = NULL; assert(c); if (!name) { @@ -130,9 +129,7 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t if (e->type == e->type) return e->data; - index = (uint32_t) strtol(name, &x, 0); - - if (!x || *x != 0) { + if (pa_atou(name, &index) < 0) { if (autoload) { pa_autoload_request(c, name, type); @@ -146,13 +143,13 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t } if (type == PA_NAMEREG_SINK) - d = pa_idxset_get_by_index(c->sinks, index); + return pa_idxset_get_by_index(c->sinks, index); else if (type == PA_NAMEREG_SOURCE) - d = pa_idxset_get_by_index(c->sources, index); + return pa_idxset_get_by_index(c->sources, index); else if (type == PA_NAMEREG_SAMPLE && c->scache) - d = pa_idxset_get_by_index(c->scache, index); - - return d; + return pa_idxset_get_by_index(c->scache, index); + + return NULL; } void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_type type) { diff --git a/polyp/pid.c b/polyp/pid.c index 32365136f..2fac687ec 100644 --- a/polyp/pid.c +++ b/polyp/pid.c @@ -43,8 +43,8 @@ * pid could be read, return 0, on failure (pid_t) -1 */ static pid_t read_pid(const char *fn, int fd) { ssize_t r; - char t[20], *e = NULL; - long int pid; + char t[20], *e; + uint32_t pid; assert(fn && fd >= 0); @@ -57,8 +57,10 @@ static pid_t read_pid(const char *fn, int fd) { return (pid_t) 0; t[r] = 0; + if ((e = strchr(t, '\n'))) + *e = 0; - if (!t[0] || (pid = strtol(t, &e, 0)) == 0 || (*e != 0 && *e != '\n')) { + if (pa_atou(t, &pid) < 0) { pa_log(__FILE__": WARNING: failed to parse PID file '%s'\n", fn); return (pid_t) -1; } diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 84d4efe8f..94dc5e5fa 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -2003,7 +2003,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo assert(io && p); if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { - pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); pa_iochannel_free(io); return; } @@ -2057,7 +2057,7 @@ static int load_key(struct pa_protocol_native*p, const char*fn) { p->auth_cookie_in_property = 0; if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) { - pa_log(__FILE__": using already loaded auth cookie.\n"); + pa_log_info(__FILE__": using already loaded auth cookie.\n"); pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); p->auth_cookie_in_property = 1; return 0; @@ -2069,7 +2069,7 @@ static int load_key(struct pa_protocol_native*p, const char*fn) { if (pa_authkey_load_auto(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0) return -1; - pa_log(__FILE__": loading cookie from disk.\n"); + pa_log_info(__FILE__": loading cookie from disk.\n"); if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) p->auth_cookie_in_property = 1; diff --git a/polyp/sample.c b/polyp/sample.c index 978a3d6aa..b0723f70e 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -84,7 +84,7 @@ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_s return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels); } -void pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { +const char *pa_sample_format_to_string(enum pa_sample_format f) { static const char* const table[]= { [PA_SAMPLE_U8] = "U8", [PA_SAMPLE_ALAW] = "ALAW", @@ -95,12 +95,21 @@ void pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec [PA_SAMPLE_FLOAT32BE] = "FLOAT32BE", }; + if (f >= PA_SAMPLE_MAX) + return NULL; + + return table[f]; +} + +void pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { + assert(s && l && spec); + if (!pa_sample_spec_valid(spec)) { snprintf(s, l, "Invalid"); return; } - snprintf(s, l, "%s %uch %uHz", table[spec->format], spec->channels, spec->rate); + snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate); } pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b) { diff --git a/polyp/sample.h b/polyp/sample.h index 93025a103..59226c469 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -86,6 +86,9 @@ int pa_sample_spec_valid(const struct pa_sample_spec *spec); /** Return non-zero when the two sample type specifications match */ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b); +/* Return a descriptive string for the specified sample format. \since 0.7.1 */ +const char *pa_sample_format_to_string(enum pa_sample_format f); + /** Maximum required string length for pa_sample_spec_snprint() */ #define PA_SAMPLE_SPEC_SNPRINT_MAX 32 @@ -126,7 +129,7 @@ pa_volume_t pa_volume_from_user(double v); /** Pretty print a byte size value. (i.e. "2.5 MB") */ void pa_bytes_snprint(char *s, size_t l, unsigned v); -/** Parse a sample format text */ +/** Parse a sample format text. Inverse of pa_sample_format_to_string() */ enum pa_sample_format pa_parse_sample_format(const char *format); PA_C_DECL_END diff --git a/polyp/sink-input.c b/polyp/sink-input.c index e66278ed2..347b8f5c6 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -85,7 +85,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con assert(r == 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"\n", i->index, i->name, s->index, st); + pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"\n", i->index, i->name, s->index, st); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); @@ -115,6 +115,8 @@ static void sink_input_free(struct pa_sink_input* i) { if (i->state != PA_SINK_INPUT_DISCONNECTED) pa_sink_input_disconnect(i); + pa_log_info(__FILE__": freed %u \"%s\"\n", i->index, i->name); + if (i->resampled_chunk.memblock) pa_memblock_unref(i->resampled_chunk.memblock); if (i->resampler) diff --git a/polyp/sink.c b/polyp/sink.c index 29aef6fba..3d20884b8 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -81,7 +81,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co assert(s->index != PA_IDXSET_INVALID && r >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); + pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); @@ -117,7 +117,7 @@ static void sink_free(struct pa_sink *s) { if (s->state != PA_SINK_DISCONNECTED) pa_sink_disconnect(s); - pa_log(__FILE__": freed %u \"%s\"\n", s->index, s->name); + pa_log_info(__FILE__": freed %u \"%s\"\n", s->index, s->name); pa_source_unref(s->monitor_source); s->monitor_source = NULL; diff --git a/polyp/source-output.c b/polyp/source-output.c index fb06ff8fc..3568fd6f2 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -37,6 +37,7 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n struct pa_source_output *o; struct pa_resampler *resampler = NULL; int r; + char st[256]; assert(s && spec); if (pa_idxset_ncontents(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { @@ -73,6 +74,9 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n r = pa_idxset_put(s->outputs, o, NULL); assert(r == 0); + pa_sample_spec_snprint(st, sizeof(st), spec); + pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"\n", o->index, o->name, s->index, st); + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index); return o; @@ -100,6 +104,8 @@ static void source_output_free(struct pa_source_output* o) { if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED) pa_source_output_disconnect(o); + pa_log_info(__FILE__": freed %u \"%s\"\n", o->index, o->name); + if (o->resampler) pa_resampler_free(o->resampler); diff --git a/polyp/source.c b/polyp/source.c index 026ec7a81..7cdb9117f 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -68,7 +68,7 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail assert(s->index != PA_IDXSET_INVALID && r >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); + pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); @@ -101,7 +101,7 @@ static void source_free(struct pa_source *s) { if (s->state != PA_SOURCE_DISCONNECTED) pa_source_disconnect(s); - pa_log(__FILE__": freed %u \"%s\"\n", s->index, s->name); + pa_log_info(__FILE__": freed %u \"%s\"\n", s->index, s->name); pa_idxset_free(s->outputs, NULL, NULL); diff --git a/polyp/util.c b/polyp/util.c index 970ebb93e..ff1aebf36 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -381,9 +381,9 @@ supported.*/ void pa_raise_priority(void) { if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) - pa_log(__FILE__": setpriority() failed: %s\n", strerror(errno)); -/* else */ -/* pa_log(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); */ + pa_log_warn(__FILE__": setpriority() failed: %s\n", strerror(errno)); + else + pa_log_info(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); #ifdef _POSIX_PRIORITY_SCHEDULING { @@ -396,11 +396,11 @@ void pa_raise_priority(void) { sp.sched_priority = 1; if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) { - pa_log(__FILE__": sched_setscheduler() failed: %s\n", strerror(errno)); + pa_log_warn(__FILE__": sched_setscheduler() failed: %s\n", strerror(errno)); return; } -/* pa_log(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); */ + pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); } #endif } @@ -698,17 +698,17 @@ int pa_unlock_lockfile(const char *fn, int fd) { assert(fn && fd >= 0); if (unlink(fn) < 0) { - pa_log(__FILE__": WARNING: unable to remove lock file '%s': %s\n", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: unable to remove lock file '%s': %s\n", fn, strerror(errno)); r = -1; } if (pa_lock_fd(fd, 0) < 0) { - pa_log(__FILE__": WARNING: failed to unlock file '%s'.\n", fn); + pa_log_warn(__FILE__": WARNING: failed to unlock file '%s'.\n", fn); r = -1; } if (close(fd) < 0) { - pa_log(__FILE__": WARNING: failed to close lock file '%s': %s\n", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to close lock file '%s': %s\n", fn, strerror(errno)); r = -1; } @@ -862,6 +862,7 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) { return s; } +/* Wait t milliseconds */ int pa_msleep(unsigned long t) { struct timespec ts; @@ -870,3 +871,35 @@ int pa_msleep(unsigned long t) { return nanosleep(&ts, NULL); } + +/* Convert the string s to a signed integer in *ret_i */ +int pa_atoi(const char *s, int32_t *ret_i) { + char *x = NULL; + long l; + assert(s && ret_i); + + l = strtol(s, &x, 0); + + if (x || *x) + return -1; + + *ret_i = (int32_t) l; + + return 0; +} + +/* Convert the string s to an unsigned integer in *ret_u */ +int pa_atou(const char *s, uint32_t *ret_u) { + char *x = NULL; + unsigned long l; + assert(s && ret_u); + + l = strtoul(s, &x, 0); + + if (!x || *x) + return -1; + + *ret_u = (uint32_t) l; + + return 0; +} diff --git a/polyp/util.h b/polyp/util.h index 922aa49ef..2cfc5f6e6 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -90,4 +90,7 @@ char *pa_runtime_path(const char *fn, char *s, size_t l); int pa_msleep(unsigned long t); +int pa_atoi(const char *s, int32_t *ret_i); +int pa_atou(const char *s, uint32_t *ret_u); + #endif From 2d97e7522e6d075e5784659ce538e9dd194e5eae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 11 Dec 2004 16:48:45 +0000 Subject: [PATCH 0311/1514] * fix alsa initialisation * add some missing zeroconf files * make module-match shut up a bit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@318 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- polyp/alsa-util.c | 9 +- polyp/howl-wrap.c | 116 +++++++++ polyp/howl-wrap.h | 37 +++ polyp/module-match.c | 2 +- polyp/module-zeroconf-publish.c | 415 ++++++++++++++++++++++++++++++++ 6 files changed, 574 insertions(+), 7 deletions(-) create mode 100644 polyp/howl-wrap.c create mode 100644 polyp/howl-wrap.h create mode 100644 polyp/module-zeroconf-publish.c diff --git a/configure.ac b/configure.ac index 5a4a4646b..a54f383f8 100644 --- a/configure.ac +++ b/configure.ac @@ -166,7 +166,7 @@ fi # LYNX documentation generation AC_ARG_ENABLE(lynx, - AS_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation), + AC_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation), [case "${enableval}" in yes) lynx=yes ;; no) lynx=no ;; diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index b6b9ac11c..2894c9e8b 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -29,6 +29,7 @@ #include "alsa-util.h" #include "sample.h" #include "xmalloc.h" +#include "log.h" /* Set the hardware parameters of the given ALSA device. Returns the * selected fragment settings in *period and *period_size */ @@ -61,14 +62,12 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const struct pa_sample_spec *ss if (snd_pcm_prepare(pcm_handle) < 0) goto finish; - if (snd_pcm_hw_params_current(pcm_handle, hwparams) < 0) - goto finish; - if (snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size) < 0 || snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL) < 0) goto finish; - - assert(buffer_size > 0 && *period_size > 0); + + assert(buffer_size > 0); + assert(*period_size > 0); *periods = buffer_size / *period_size; assert(*periods > 0); diff --git a/polyp/howl-wrap.c b/polyp/howl-wrap.c new file mode 100644 index 000000000..af0509308 --- /dev/null +++ b/polyp/howl-wrap.c @@ -0,0 +1,116 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "howl-wrap.h" +#include "log.h" +#include "xmalloc.h" +#include "props.h" + +#define HOWL_PROPERTY "howl" + +struct pa_howl_wrapper { + struct pa_core *core; + int ref; + + struct pa_io_event *io_event; + sw_discovery discovery; + +}; + +static void howl_io_event(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { + struct pa_howl_wrapper *w = userdata; + assert(m && e && fd >= 0 && w && w->ref >= 1); + + if (f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) + goto fail; + + if (sw_discovery_read_socket(w->discovery) != SW_OKAY) + goto fail; + + return; + +fail: + pa_log(__FILE__": howl connection died.\n"); + w->core->mainloop->io_free(w->io_event); + w->io_event = NULL; +} + +static struct pa_howl_wrapper* howl_wrapper_new(struct pa_core *c) { + struct pa_howl_wrapper *h; + sw_discovery session; + assert(c); + + if (sw_discovery_init(&session) != SW_OKAY) { + pa_log("sw_discovery_init() failed.\n"); + return NULL; + } + + h = pa_xmalloc(sizeof(struct pa_howl_wrapper)); + h->core = c; + h->ref = 1; + h->discovery = session; + + h->io_event = c->mainloop->io_new(c->mainloop, sw_discovery_socket(session), PA_IO_EVENT_INPUT, howl_io_event, h); + + return h; +} + +static void howl_wrapper_free(struct pa_howl_wrapper *h) { + assert(h); + + sw_discovery_fina(h->discovery); + + if (h->io_event) + h->core->mainloop->io_free(h->io_event); + + pa_xfree(h); +} + +struct pa_howl_wrapper* pa_howl_wrapper_get(struct pa_core *c) { + struct pa_howl_wrapper *h; + assert(c); + + if ((h = pa_property_get(c, HOWL_PROPERTY))) + return pa_howl_wrapper_ref(h); + + return howl_wrapper_new(c); +} + +struct pa_howl_wrapper* pa_howl_wrapper_ref(struct pa_howl_wrapper *h) { + assert(h && h->ref >= 1); + h->ref++; + return h; +} + +void pa_howl_wrapper_unref(struct pa_howl_wrapper *h) { + assert(h && h->ref >= 1); + if (!(--h->ref)) + howl_wrapper_free(h); +} + +sw_discovery pa_howl_wrapper_get_discovery(struct pa_howl_wrapper *h) { + assert(h && h->ref >= 1); + + return h->discovery; +} + diff --git a/polyp/howl-wrap.h b/polyp/howl-wrap.h new file mode 100644 index 000000000..feb54556d --- /dev/null +++ b/polyp/howl-wrap.h @@ -0,0 +1,37 @@ +#ifndef foohowlwrapperhfoo +#define foohowlwrapperhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "core.h" + +struct pa_howl_wrapper; + +struct pa_howl_wrapper* pa_howl_wrapper_get(struct pa_core *c); +struct pa_howl_wrapper* pa_howl_wrapper_ref(struct pa_howl_wrapper *h); +void pa_howl_wrapper_unref(struct pa_howl_wrapper *h); + +sw_discovery pa_howl_wrapper_get_discovery(struct pa_howl_wrapper *h); + +#endif diff --git a/polyp/module-match.c b/polyp/module-match.c index 7fdc5f3e0..9d969b31b 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -171,7 +171,7 @@ static void callback(struct pa_core *c, enum pa_subscription_event_type t, uint3 for (r = u->rules; r; r = r->next) { if (!regexec(&r->regex, si->name, 0, NULL, 0)) { - pa_log(__FILE__": changing volume of sink input '%s' to 0x%03x\n", si->name, r->volume); + pa_log_debug(__FILE__": changing volume of sink input '%s' to 0x%03x\n", si->name, r->volume); pa_sink_input_set_volume(si, r->volume); } } diff --git a/polyp/module-zeroconf-publish.c b/polyp/module-zeroconf-publish.c new file mode 100644 index 000000000..6eee143b9 --- /dev/null +++ b/polyp/module-zeroconf-publish.c @@ -0,0 +1,415 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "module-zeroconf-publish-symdef.h" +#include "howl-wrap.h" +#include "xmalloc.h" +#include "autoload.h" +#include "sink.h" +#include "source.h" +#include "native-common.h" +#include "util.h" +#include "log.h" +#include "subscribe.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher") +PA_MODULE_VERSION(PACKAGE_VERSION) + +#define SERVICE_NAME_SINK "_polypaudio-sink._tcp" +#define SERVICE_NAME_SOURCE "_polypaudio-source._tcp" +#define SERVICE_NAME_SERVER "_polypaudio-server._tcp" + +struct service { + sw_discovery_oid oid; + char *name; + int published; /* 0 -> not yet registered, 1 -> registered with data from real device, 2 -> registered with data from autoload device */ + + struct { + int valid; + enum pa_namereg_type type; + uint32_t index; + } loaded; + + struct { + int valid; + enum pa_namereg_type type; + uint32_t index; + } autoload; +}; + +struct userdata { + struct pa_core *core; + struct pa_howl_wrapper *howl_wrapper; + struct pa_hashmap *services; + struct pa_subscription *subscription; +}; + +static sw_result publish_reply(sw_discovery discovery, sw_discovery_publish_status status, sw_discovery_oid oid, sw_opaque extra) { + return SW_OKAY; +} + +static void get_service_sample_spec(struct userdata *u, struct service *s, struct pa_sample_spec *ret_ss) { + assert(u && s && s->loaded.valid && ret_ss); + + if (s->loaded.type == PA_NAMEREG_SINK) { + struct pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index); + assert(sink); + *ret_ss = sink->sample_spec; + } else if (s->loaded.type == PA_NAMEREG_SOURCE) { + struct pa_source *source = pa_idxset_get_by_index(u->core->sources, s->loaded.index); + assert(source); + *ret_ss = source->sample_spec; + } else + assert(0); +} + +static int publish_service(struct userdata *u, struct service *s) { + assert(u && s); + char t[256]; + char hn[256]; + int r = -1; + sw_text_record txt; + int free_txt = 0; + + if ((s->published == 1 && s->loaded.valid) || + (s->published == 2 && s->autoload.valid && !s->loaded.valid)) + return 0; + + if (s->published) { + sw_discovery_cancel(pa_howl_wrapper_get_discovery(u->howl_wrapper), s->oid); + s->published = 0; + } + + snprintf(t, sizeof(t), "%s@%s", s->name, pa_get_host_name(hn, sizeof(hn))); + + if (sw_text_record_init(&txt) != SW_OKAY) { + pa_log(__FILE__": sw_text_record_init() failed\n"); + goto finish; + } + free_txt = 1; + + sw_text_record_add_key_and_string_value(txt, "device", s->name); + + if (s->loaded.valid) { + char z[64]; + struct pa_sample_spec ss; + + get_service_sample_spec(u, s, &ss); + + snprintf(z, sizeof(z), "%u", ss.rate); + sw_text_record_add_key_and_string_value(txt, "rate", z); + snprintf(z, sizeof(z), "%u", ss.channels); + sw_text_record_add_key_and_string_value(txt, "channels", z); + sw_text_record_add_key_and_string_value(txt, "format", pa_sample_format_to_string(ss.format)); + + if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t, + s->loaded.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE, + NULL, NULL, PA_NATIVE_DEFAULT_PORT, sw_text_record_bytes(txt), sw_text_record_len(txt), + publish_reply, s, &s->oid) != SW_OKAY) { + pa_log(__FILE__": failed to register sink on zeroconf.\n"); + goto finish; + } + + s->published = 1; + } else if (s->autoload.valid) { + + if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t, + s->autoload.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE, + NULL, NULL, PA_NATIVE_DEFAULT_PORT, sw_text_record_bytes(txt), sw_text_record_len(txt), + publish_reply, s, &s->oid) != SW_OKAY) { + pa_log(__FILE__": failed to register sink on zeroconf.\n"); + goto finish; + } + + s->published = 2; + } + + r = 0; + +finish: + + if (!s->published) { + /* Remove this service */ + pa_hashmap_remove(u->services, s->name); + pa_xfree(s->name); + pa_xfree(s); + } + + if (free_txt) + sw_text_record_fina(txt); + + return r; +} + +struct service *get_service(struct userdata *u, const char *name) { + struct service *s; + + if ((s = pa_hashmap_get(u->services, name))) + return s; + + s = pa_xmalloc(sizeof(struct service)); + s->published = 0; + s->name = pa_xstrdup(name); + s->loaded.valid = s->autoload.valid = 0; + + pa_hashmap_put(u->services, s->name, s); + + return s; +} + +static int publish_sink(struct userdata *u, struct pa_sink *s) { + struct service *svc; + assert(u && s); + + svc = get_service(u, s->name); + if (svc->loaded.valid) + return 0; + + svc->loaded.valid = 1; + svc->loaded.type = PA_NAMEREG_SINK; + svc->loaded.index = s->index; + + return publish_service(u, svc); +} + +static int publish_source(struct userdata *u, struct pa_source *s) { + struct service *svc; + assert(u && s); + + svc = get_service(u, s->name); + if (svc->loaded.valid) + return 0; + + svc->loaded.valid = 1; + svc->loaded.type = PA_NAMEREG_SOURCE; + svc->loaded.index = s->index; + + return publish_service(u, svc); +} + +static int publish_autoload(struct userdata *u, struct pa_autoload_entry *s) { + struct service *svc; + assert(u && s); + + svc = get_service(u, s->name); + if (svc->autoload.valid) + return 0; + + svc->autoload.valid = 1; + svc->autoload.type = s->type; + svc->autoload.index = s->index; + + return publish_service(u, svc); +} + +static int remove_sink(struct userdata *u, struct pa_sink *s) { + struct service *svc; + assert(u && s); + + if (!(svc = pa_hashmap_get(u->services, s->name))) + return 0; + + if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SINK) + return 0; + + svc->loaded.valid = 0; + return publish_service(u, svc); +} + +static int remove_source(struct userdata *u, struct pa_source *s) { + struct service *svc; + assert(u && s); + + if (!(svc = pa_hashmap_get(u->services, s->name))) + return 0; + + if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SOURCE) + return 0; + + svc->loaded.valid = 0; + return publish_service(u, svc); +} + +static int remove_autoload(struct userdata *u, struct pa_autoload_entry *s) { + struct service *svc; + assert(u && s); + + if (!(svc = pa_hashmap_get(u->services, s->name))) + return 0; + + if (!svc->autoload.valid || svc->autoload.type != s->type) + return 0; + + svc->autoload.valid = 0; + return publish_service(u, svc); +} + +static void subscribe_callback(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) { + struct userdata *u = userdata; + assert(u && c); + + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { + case PA_SUBSCRIPTION_EVENT_SINK: { + struct pa_sink *sink; + + pa_log("subscribe: %x\n", t); + + + + + if ((sink = pa_idxset_get_by_index(c->sinks, index))) { + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + pa_log("add\n"); + if (publish_sink(u, sink) < 0) + goto fail; + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + pa_log("remove\n"); + + + if (remove_sink(u, sink) < 0) + goto fail; + } + } + + break; + } + + case PA_SUBSCRIPTION_EVENT_SOURCE: { + struct pa_source *source; + + if ((source = pa_idxset_get_by_index(c->sources, index))) { + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + if (publish_source(u, source) < 0) + goto fail; + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (remove_source(u, source) < 0) + goto fail; + } + } + + break; + } + + case PA_SUBSCRIPTION_EVENT_AUTOLOAD: { + struct pa_autoload_entry *autoload; + + if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, index))) { + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + if (publish_autoload(u, autoload) < 0) + goto fail; + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (remove_autoload(u, autoload) < 0) + goto fail; + } + } + + break; + } + } + + return; + +fail: + if (u->subscription) { + pa_subscription_free(u->subscription); + u->subscription = NULL; + } +} + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + uint32_t index; + struct pa_sink *sink; + struct pa_source *source; + struct pa_autoload_entry *autoload; + + m->userdata = u = pa_xmalloc(sizeof(struct userdata)); + u->core = c; + + if (!(u->howl_wrapper = pa_howl_wrapper_get(c))) + goto fail; + + u->services = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + + u->subscription = pa_subscription_new(c, + PA_SUBSCRIPTION_MASK_SINK| + PA_SUBSCRIPTION_MASK_SOURCE| + PA_SUBSCRIPTION_MASK_AUTOLOAD, subscribe_callback, u); + + for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index)) + if (publish_sink(u, sink) < 0) + goto fail; + + for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) + if (publish_source(u, source) < 0) + goto fail; + + if (c->autoload_idxset) + for (autoload = pa_idxset_first(c->autoload_idxset, &index); autoload; autoload = pa_idxset_next(c->autoload_idxset, &index)) + if (publish_autoload(u, autoload) < 0) + goto fail; + + return 0; + +fail: + pa__done(c, m); + return -1; +} + +static void service_free(void *p, void *userdata) { + struct service *s = p; + struct userdata *u = userdata; + assert(s && u); + sw_discovery_cancel(pa_howl_wrapper_get_discovery(u->howl_wrapper), s->oid); + pa_xfree(s->name); + pa_xfree(s); +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata*u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + if (u->services) + pa_hashmap_free(u->services, service_free, u); + + if (u->subscription) + pa_subscription_free(u->subscription); + + if (u->howl_wrapper) + pa_howl_wrapper_unref(u->howl_wrapper); + + pa_xfree(u); +} + From 9a01cf44f09e92e14a720f4f531e943a50f26b72 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 12 Dec 2004 15:56:22 +0000 Subject: [PATCH 0312/1514] * complete zeroconf publisher * make cli.c shut up unless run with -v git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@319 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/cli.c | 4 +- polyp/module-zeroconf-publish.c | 104 ++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 47 deletions(-) diff --git a/polyp/cli.c b/polyp/cli.c index 04fbb7e08..4d4342bfb 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -102,7 +102,7 @@ static void client_kill(struct pa_client *client) { assert(client && client->userdata); c = client->userdata; - pa_log(__FILE__": CLI client killed.\n"); + pa_log_debug(__FILE__": CLI client killed.\n"); if (c->defer_kill) c->kill_requested = 1; else { @@ -118,7 +118,7 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) assert(line && c); if (!s) { - pa_log(__FILE__": CLI got EOF from user.\n"); + pa_log_debug(__FILE__": CLI got EOF from user.\n"); if (c->eof_callback) c->eof_callback(c, c->userdata); diff --git a/polyp/module-zeroconf-publish.c b/polyp/module-zeroconf-publish.c index 6eee143b9..363c24192 100644 --- a/polyp/module-zeroconf-publish.c +++ b/polyp/module-zeroconf-publish.c @@ -39,6 +39,7 @@ #include "util.h" #include "log.h" #include "subscribe.h" +#include "dynarray.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher") @@ -70,6 +71,7 @@ struct userdata { struct pa_core *core; struct pa_howl_wrapper *howl_wrapper; struct pa_hashmap *services; + struct pa_dynarray *sink_dynarray, *source_dynarray, *autoload_dynarray; struct pa_subscription *subscription; }; @@ -198,6 +200,8 @@ static int publish_sink(struct userdata *u, struct pa_sink *s) { svc->loaded.type = PA_NAMEREG_SINK; svc->loaded.index = s->index; + pa_dynarray_put(u->sink_dynarray, s->index, svc); + return publish_service(u, svc); } @@ -212,6 +216,8 @@ static int publish_source(struct userdata *u, struct pa_source *s) { svc->loaded.valid = 1; svc->loaded.type = PA_NAMEREG_SOURCE; svc->loaded.index = s->index; + + pa_dynarray_put(u->source_dynarray, s->index, svc); return publish_service(u, svc); } @@ -227,49 +233,57 @@ static int publish_autoload(struct userdata *u, struct pa_autoload_entry *s) { svc->autoload.valid = 1; svc->autoload.type = s->type; svc->autoload.index = s->index; + + pa_dynarray_put(u->autoload_dynarray, s->index, svc); return publish_service(u, svc); } -static int remove_sink(struct userdata *u, struct pa_sink *s) { +static int remove_sink(struct userdata *u, uint32_t index) { struct service *svc; - assert(u && s); + assert(u && index != PA_INVALID_INDEX); - if (!(svc = pa_hashmap_get(u->services, s->name))) + if (!(svc = pa_dynarray_get(u->sink_dynarray, index))) return 0; if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SINK) return 0; svc->loaded.valid = 0; + pa_dynarray_put(u->sink_dynarray, index, NULL); + return publish_service(u, svc); } -static int remove_source(struct userdata *u, struct pa_source *s) { +static int remove_source(struct userdata *u, uint32_t index) { struct service *svc; - assert(u && s); + assert(u && index != PA_INVALID_INDEX); - if (!(svc = pa_hashmap_get(u->services, s->name))) + if (!(svc = pa_dynarray_get(u->source_dynarray, index))) return 0; if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SOURCE) return 0; svc->loaded.valid = 0; + pa_dynarray_put(u->source_dynarray, index, NULL); + return publish_service(u, svc); } -static int remove_autoload(struct userdata *u, struct pa_autoload_entry *s) { +static int remove_autoload(struct userdata *u, uint32_t index) { struct service *svc; - assert(u && s); + assert(u && index != PA_INVALID_INDEX); - if (!(svc = pa_hashmap_get(u->services, s->name))) + if (!(svc = pa_dynarray_get(u->autoload_dynarray, index))) return 0; - if (!svc->autoload.valid || svc->autoload.type != s->type) + if (!svc->autoload.valid) return 0; svc->autoload.valid = 0; + pa_dynarray_put(u->autoload_dynarray, index, NULL); + return publish_service(u, svc); } @@ -277,63 +291,52 @@ static void subscribe_callback(struct pa_core *c, enum pa_subscription_event_typ struct userdata *u = userdata; assert(u && c); - switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) case PA_SUBSCRIPTION_EVENT_SINK: { - struct pa_sink *sink; + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + struct pa_sink *sink; - pa_log("subscribe: %x\n", t); - - - - - if ((sink = pa_idxset_get_by_index(c->sinks, index))) { - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - pa_log("add\n"); + if ((sink = pa_idxset_get_by_index(c->sinks, index))) { if (publish_sink(u, sink) < 0) goto fail; - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - pa_log("remove\n"); - - - if (remove_sink(u, sink) < 0) - goto fail; } + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (remove_sink(u, index) < 0) + goto fail; } break; - } - case PA_SUBSCRIPTION_EVENT_SOURCE: { - struct pa_source *source; + case PA_SUBSCRIPTION_EVENT_SOURCE: - if ((source = pa_idxset_get_by_index(c->sources, index))) { - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + struct pa_source *source; + + if ((source = pa_idxset_get_by_index(c->sources, index))) { if (publish_source(u, source) < 0) goto fail; - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (remove_source(u, source) < 0) - goto fail; } + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (remove_source(u, index) < 0) + goto fail; } break; - } - case PA_SUBSCRIPTION_EVENT_AUTOLOAD: { - struct pa_autoload_entry *autoload; - - if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, index))) { - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + case PA_SUBSCRIPTION_EVENT_AUTOLOAD: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + struct pa_autoload_entry *autoload; + + if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, index))) { if (publish_autoload(u, autoload) < 0) goto fail; - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (remove_autoload(u, autoload) < 0) - goto fail; } + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (remove_autoload(u, index) < 0) + goto fail; } break; - } } return; @@ -359,7 +362,10 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; u->services = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - + u->sink_dynarray = pa_dynarray_new(); + u->source_dynarray = pa_dynarray_new(); + u->autoload_dynarray = pa_dynarray_new(); + u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK| PA_SUBSCRIPTION_MASK_SOURCE| @@ -404,11 +410,19 @@ void pa__done(struct pa_core *c, struct pa_module*m) { if (u->services) pa_hashmap_free(u->services, service_free, u); + if (u->sink_dynarray) + pa_dynarray_free(u->sink_dynarray, NULL, NULL); + if (u->source_dynarray) + pa_dynarray_free(u->source_dynarray, NULL, NULL); + if (u->autoload_dynarray) + pa_dynarray_free(u->autoload_dynarray, NULL, NULL); + if (u->subscription) pa_subscription_free(u->subscription); if (u->howl_wrapper) pa_howl_wrapper_unref(u->howl_wrapper); + pa_xfree(u); } From e02be6c15beddec976220bce2ee1a68520286c01 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 12 Dec 2004 22:58:53 +0000 Subject: [PATCH 0313/1514] * fix include file names in installed header files * add browsing API * add new tool pabrowse * add typeid subsystem * bump API version * split off random.c * add an identification cookie git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@320 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 +- doc/todo | 26 ++- polyp/Makefile.am | 25 ++- polyp/authkey.c | 40 +---- polyp/cli-text.c | 19 +- polyp/cli.c | 3 +- polyp/client.c | 5 +- polyp/client.h | 6 +- polyp/core.c | 4 +- polyp/core.h | 4 + polyp/endianmacros.h | 14 +- polyp/mainloop-api.h | 2 +- polyp/module-alsa-sink.c | 4 +- polyp/module-alsa-source.c | 4 +- polyp/module-combine.c | 6 +- polyp/module-esound-sink.c | 4 +- polyp/module-null-sink.c | 4 +- polyp/module-oss-mmap.c | 6 +- polyp/module-oss.c | 6 +- polyp/module-pipe-sink.c | 4 +- polyp/module-pipe-source.c | 4 +- polyp/module-sine.c | 4 +- polyp/module-tunnel.c | 6 +- polyp/module-zeroconf-publish.c | 33 +++- polyp/pabrowse.c | 139 +++++++++++++++ polyp/pacat.c | 5 +- polyp/pactl.c | 37 ++-- polyp/paplay.c | 2 +- polyp/play-memchunk.c | 4 +- polyp/polyplib-browser.c | 307 ++++++++++++++++++++++++++++++++ polyp/polyplib-browser.h | 65 +++++++ polyp/polyplib-context.h | 11 +- polyp/polyplib-def.h | 4 +- polyp/polyplib-introspect.c | 21 ++- polyp/polyplib-introspect.h | 16 +- polyp/polyplib-operation.h | 4 +- polyp/polyplib-scache.h | 6 +- polyp/polyplib-stream.h | 8 +- polyp/polyplib-subscribe.h | 6 +- polyp/polyplib.h | 20 +-- polyp/protocol-esound.c | 8 +- polyp/protocol-native.c | 17 +- polyp/protocol-simple.c | 8 +- polyp/random.c | 61 +++++++ polyp/random.h | 27 +++ polyp/sample.c | 18 +- polyp/sample.h | 4 +- polyp/sink-input.c | 3 +- polyp/sink-input.h | 3 +- polyp/sink.c | 5 +- polyp/sink.h | 4 +- polyp/sound-file-stream.c | 3 +- polyp/source-output.c | 4 +- polyp/source-output.h | 3 +- polyp/source.c | 3 +- polyp/source.h | 4 +- polyp/typeid.c | 33 ++++ polyp/typeid.h | 40 +++++ 58 files changed, 971 insertions(+), 169 deletions(-) create mode 100644 polyp/pabrowse.c create mode 100644 polyp/polyplib-browser.c create mode 100644 polyp/polyplib-browser.h create mode 100644 polyp/random.c create mode 100644 polyp/random.h create mode 100644 polyp/typeid.c create mode 100644 polyp/typeid.h diff --git a/configure.ac b/configure.ac index a54f383f8..658910c63 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.7.1],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.8],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) @@ -28,7 +28,7 @@ AM_INIT_AUTOMAKE([foreign -Wall]) AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) -AC_SUBST(PA_API_VERSION, 7) +AC_SUBST(PA_API_VERSION, 8) if type -p stow > /dev/null && test -d /usr/local/stow ; then AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) diff --git a/doc/todo b/doc/todo index d6cfb01ac..efaeb3322 100644 --- a/doc/todo +++ b/doc/todo @@ -1,23 +1,31 @@ *** $Id$ *** -*** later **** -- event more commenting -- polish for starting polypaudio as root/system-wide instance +Architectural changes: - per-channel volume +- channel mapping ("left", "right", "rear", "subwoofer") +- add API for synchronizing multiple sinks/sources to a common clock +- absolutely indexed write()s from client +- remove "polyplib-" prefix + +Fixes: - improve module-oss-mmap latency measurement - module-tunnel: improve latency calculation +- make alsa modules use mmap +- event more commenting + +Features: - add radio module -- pass meta info for hearing impaired -- add sync API -- X11: support for the X11 synchronization extension - xmlrpc/http - dbus - rendezvous -- make alsa modules use mmap +- polish for starting polypaudio as root/system-wide instance +- export connection fd -*********** +Long term: +- pass meta info for hearing impaired +- X11: support for the X11 synchronization extension -backends for: +Backends for: - portaudio (semi-done) - alsa-lib - sdl diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 83b5670a6..700516717 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -220,7 +220,9 @@ polypaudio_SOURCES = idxset.c idxset.h \ props.h props.c \ mcalign.c mcalign.h \ g711.c g711.h \ - pid.c pid.h + pid.c pid.h \ + random.c random.h \ + typeid.c typeid.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL) @@ -455,7 +457,9 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ conf-parser.c conf-parser.h \ strlist.c strlist.h \ strbuf.c strbuf.h \ - mcalign.c mcalign.h + mcalign.c mcalign.h \ + typeid.c typeid.h \ + random.c random.h libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 @@ -560,7 +564,7 @@ module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EX bin_PROGRAMS+= \ pax11publish -pax11publish_SOURCES = pax11publish.c util.c xmalloc.c log.c authkey.c client-conf.c conf-parser.c x11prop.c +pax11publish_SOURCES = pax11publish.c util.c util.h xmalloc.c xmalloc.h log.c log.h authkey.c authkey.h client-conf.c client-conf.h conf-parser.c conf-parser.h x11prop.c x11prop.h random.c random.h pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) @@ -613,6 +617,21 @@ module_zeroconf_publish_la_LDFLAGS = -module -avoid-version module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) +lib_LTLIBRARIES+= \ + libpolyp-browse-@PA_MAJORMINOR@.la + +libpolyp_browse_@PA_MAJORMINOR@_la_SOURCES = polyplib-browser.c polyplib-browser.h +libpolyp_browse_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) +libpolyp_browse_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(HOWL_LIBS) +libpolyp_browse_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 + +bin_PROGRAMS += \ + pabrowse + +pabrowse_SOURCES = pabrowse.c +pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la +pabrowse_CFLAGS = $(AM_CFLAGS) + endif ### GLIB 2.0 support diff --git a/polyp/authkey.c b/polyp/authkey.c index 1355c8d98..e16883d38 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -38,50 +38,24 @@ #include "authkey.h" #include "util.h" #include "log.h" - -#define RANDOM_DEVICE "/dev/urandom" +#include "random.h" /* Generate a new authorization key, store it in file fd and return it in *data */ -static int generate(int fd, void *data, size_t length) { - int random_fd, ret = -1; +static int generate(int fd, void *ret_data, size_t length) { ssize_t r; - assert(fd >= 0 && data && length); + assert(fd >= 0 && ret_data && length); - if ((random_fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) { - - if ((r = pa_loop_read(random_fd, data, length)) < 0 || (size_t) r != length) { - pa_log(__FILE__": failed to read entropy from '%s'\n", RANDOM_DEVICE); - goto finish; - } - - } else { - uint8_t *p; - size_t l; - pa_log(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s" - ", falling back to unsecure pseudo RNG.\n", strerror(errno)); - - srandom(time(NULL)); - - for (p = data, l = length; l > 0; p++, l--) - *p = (uint8_t) random(); - } + pa_random(ret_data, length); lseek(fd, 0, SEEK_SET); ftruncate(fd, 0); - if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) { + if ((r = pa_loop_write(fd, ret_data, length)) < 0 || (size_t) r != length) { pa_log(__FILE__": failed to write cookie file: %s\n", strerror(errno)); - goto finish; + return -1; } - ret = 0; - -finish: - - if (random_fd >= 0) - close(random_fd); - - return ret; + return 0; } /* Load an euthorization cookie from file fn and store it in data. If diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 629b28e25..dd40add26 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -59,6 +59,7 @@ char *pa_client_list_to_string(struct pa_core *c) { struct pa_strbuf *s; struct pa_client *client; uint32_t index = PA_IDXSET_INVALID; + char tid[5]; assert(c); s = pa_strbuf_new(); @@ -67,7 +68,7 @@ char *pa_client_list_to_string(struct pa_core *c) { pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_ncontents(c->clients)); for (client = pa_idxset_first(c->clients, &index); client; client = pa_idxset_next(c->clients, &index)) { - pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tprotocol_name: <%s>\n", client->index, client->name, client->protocol_name); + pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\ttype: <%s>\n", client->index, client->name, pa_typeid_to_string(client->typeid, tid, sizeof(tid))); if (client->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index); @@ -80,6 +81,7 @@ char *pa_sink_list_to_string(struct pa_core *c) { struct pa_strbuf *s; struct pa_sink *sink; uint32_t index = PA_IDXSET_INVALID; + char tid[5]; assert(c); s = pa_strbuf_new(); @@ -93,9 +95,10 @@ char *pa_sink_list_to_string(struct pa_core *c) { assert(sink->monitor_source); pa_strbuf_printf( s, - " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", + " %c index: %u\n\tname: <%s>\n\ttype: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', sink->index, sink->name, + pa_typeid_to_string(sink->typeid, tid, sizeof(tid)), (unsigned) sink->volume, pa_volume_to_dB(sink->volume), (float) pa_sink_get_latency(sink), @@ -115,6 +118,7 @@ char *pa_source_list_to_string(struct pa_core *c) { struct pa_strbuf *s; struct pa_source *source; uint32_t index = PA_IDXSET_INVALID; + char tid[5]; assert(c); s = pa_strbuf_new(); @@ -125,10 +129,11 @@ char *pa_source_list_to_string(struct pa_core *c) { for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec); - pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n", + pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\ttype: <%s>\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n", c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ', source->index, source->name, + pa_typeid_to_string(source->typeid, tid, sizeof(tid)), (float) pa_source_get_latency(source), ss); @@ -148,6 +153,7 @@ char *pa_source_output_list_to_string(struct pa_core *c) { struct pa_strbuf *s; struct pa_source_output *o; uint32_t index = PA_IDXSET_INVALID; + char tid[5]; static const char* const state_table[] = { "RUNNING", "CORKED", @@ -170,9 +176,10 @@ char *pa_source_output_list_to_string(struct pa_core *c) { rm = "invalid"; pa_strbuf_printf( - s, " index: %u\n\tname: '%s'\n\tstate: %s\n\tsource: <%u> '%s'\n\tsample_spec: <%s>\n\tresample method: %s\n", + s, " index: %u\n\tname: '%s'\n\ttype: <%s>\n\tstate: %s\n\tsource: <%u> '%s'\n\tsample_spec: <%s>\n\tresample method: %s\n", o->index, o->name, + pa_typeid_to_string(o->typeid, tid, sizeof(tid)), state_table[o->state], o->source->index, o->source->name, ss, @@ -190,6 +197,7 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { struct pa_strbuf *s; struct pa_sink_input *i; uint32_t index = PA_IDXSET_INVALID; + char tid[5]; static const char* const state_table[] = { "RUNNING", "CORKED", @@ -212,9 +220,10 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\tstate: %s\n\tsink: <%u> '%s'\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n\tresample method: %s\n", + s, " index: %u\n\tname: <%s>\n\ttype: <%s>\n\tstate: %s\n\tsink: <%u> '%s'\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n\tresample method: %s\n", i->index, i->name, + pa_typeid_to_string(i->typeid, tid, sizeof(tid)), state_table[i->state], i->sink->index, i->sink->name, (unsigned) i->volume, diff --git a/polyp/cli.c b/polyp/cli.c index 4d4342bfb..16323cbae 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -45,6 +45,7 @@ #include "log.h" #define PROMPT ">>> " +#define PA_TYPEID_CLI PA_TYPEID_MAKE('C', 'L', 'I', '_') struct pa_cli { struct pa_core *core; @@ -75,7 +76,7 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct c->eof_callback = NULL; pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); - c->client = pa_client_new(core, "CLI", cname); + c->client = pa_client_new(core, PA_TYPEID_CLI, cname); assert(c->client); c->client->kill = client_kill; c->client->userdata = c; diff --git a/polyp/client.c b/polyp/client.c index 40f5e3858..8c7f48009 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -33,7 +33,7 @@ #include "subscribe.h" #include "log.h" -struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, char *name) { +struct pa_client *pa_client_new(struct pa_core *core, pa_typeid_t typeid, const char *name) { struct pa_client *c; int r; assert(core); @@ -42,7 +42,7 @@ struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, c->name = pa_xstrdup(name); c->owner = NULL; c->core = core; - c->protocol_name = pa_xstrdup(protocol_name); + c->typeid = typeid; c->kill = NULL; c->userdata = NULL; @@ -68,7 +68,6 @@ void pa_client_free(struct pa_client *c) { pa_log_info(__FILE__": freed %u \"%s\"\n", c->index, c->name); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_xfree(c->name); - pa_xfree(c->protocol_name); pa_xfree(c); } diff --git a/polyp/client.h b/polyp/client.h index 324bb27cb..2a3a09e09 100644 --- a/polyp/client.h +++ b/polyp/client.h @@ -24,6 +24,7 @@ #include "core.h" #include "module.h" +#include "typeid.h" /* Every connection to the server should have a pa_client * attached. That way the user may generate a listing of all connected @@ -31,18 +32,17 @@ struct pa_client { uint32_t index; + pa_typeid_t typeid; struct pa_module *owner; char *name; struct pa_core *core; - char *protocol_name; void (*kill)(struct pa_client *c); void *userdata; }; -/* Protocol name should be something like "ESOUND", "NATIVE", ... */ -struct pa_client *pa_client_new(struct pa_core *c, const char *protocol_name, char *name); +struct pa_client *pa_client_new(struct pa_core *c, pa_typeid_t typeid, const char *name); /* This function should be called only by the code that created the client */ void pa_client_free(struct pa_client *c); diff --git a/polyp/core.c b/polyp/core.c index 03682fdc5..c213faa0a 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -39,6 +39,7 @@ #include "xmalloc.h" #include "subscribe.h" #include "props.h" +#include "random.h" struct pa_core* pa_core_new(struct pa_mainloop_api *m) { struct pa_core* c; @@ -84,9 +85,10 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->resample_method = PA_RESAMPLER_SRC_SINC_FASTEST; pa_property_init(c); + + pa_random(&c->cookie, sizeof(c->cookie)); pa_check_signal_is_blocked(SIGPIPE); - return c; } diff --git a/polyp/core.h b/polyp/core.h index 6c6070b1e..366044244 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -34,6 +34,10 @@ * variables for the daemon. */ struct pa_core { + /* A random value which may be used to identify this instance of + * polypaudio. Not cryptographically secure in any way. */ + uint32_t cookie; + struct pa_mainloop_api *mainloop; /* idxset of all kinds of entities */ diff --git a/polyp/endianmacros.h b/polyp/endianmacros.h index 75c0af0af..00b992dbc 100644 --- a/polyp/endianmacros.h +++ b/polyp/endianmacros.h @@ -31,32 +31,44 @@ #define INT16_SWAP(x) ((int16_t)(((int16_t) x >> 8) | ((int16_t) x << 8))) #define UINT16_SWAP(x) ((uint16_t)(((uint16_t) x >> 8) | ((uint16_t) x << 8))) #define INT32_SWAP(x) ((int32_t)(((int32_t) x >> 24) | ((int32_t) x << 24) | (((int32_t) x & 0xFF00) << 16) | (((int32_t) x) >> 16) & 0xFF00)) -#define UINT32_SWAP(x) ((uint32_t)(((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 16) | (((uint32_t) x) >> 16) & 0xFF00)) +#define UINT32_SWAP(x) ((uint32_t)(((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 16) | ((((uint32_t) x) >> 16) & 0xFF00))) #ifdef WORDS_BIGENDIAN #define INT16_FROM_LE(x) INT16_SWAP(x) #define INT16_FROM_BE(x) ((int16_t)(x)) + #define INT16_TO_LE(x) INT16_SWAP(x) #define INT16_TO_BE(x) ((int16_t)(x)) #define UINT16_FROM_LE(x) UINT16_SWAP(x) #define UINT16_FROM_BE(x) ((uint16_t)(x)) + #define INT32_FROM_LE(x) INT32_SWAP(x) #define INT32_FROM_BE(x) ((int32_t)(x)) + #define UINT32_FROM_LE(x) UINT32_SWAP(x) #define UINT32_FROM_BE(x) ((uint32_t)(x)) + + #define UINT32_TO_LE(x) UINT32_SWAP(x) + #define UINT32_TO_BE(x) ((uint32_t)(x)) #else #define INT16_FROM_LE(x) ((int16_t)(x)) #define INT16_FROM_BE(x) INT16_SWAP(x) + #define INT16_TO_LE(x) ((int16_t)(x)) #define INT16_TO_BE(x) INT16_SWAP(x) #define UINT16_FROM_LE(x) ((uint16_t)(x)) #define UINT16_FROM_BE(x) UINT16_SWAP(x) + #define INT32_FROM_LE(x) ((int32_t)(x)) #define INT32_FROM_BE(x) INT32_SWAP(x) + #define UINT32_FROM_LE(x) ((uint32_t)(x)) #define UINT32_FROM_BE(x) UINT32_SWAP(x) + + #define UINT32_TO_LE(x) ((uint32_t)(x)) + #define UINT32_TO_BE(x) UINT32_SWAP(x) #endif #endif diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index daf71d71d..3fb221fae 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -25,7 +25,7 @@ #include #include -#include "cdecl.h" +#include /** \file * diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index d7a1cb53e..9933d37a9 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -46,6 +46,8 @@ PA_MODULE_DESCRIPTION("ALSA Sink") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= device= format= channels= rate= fragments= fragment_size=") +#define PA_TYPEID_ALSA PA_TYPEID_MAKE('A', 'L', 'S', 'A') + struct userdata { snd_pcm_t *pcm_handle; struct pa_sink *sink; @@ -212,7 +214,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; } - u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); + u->sink = pa_sink_new(c, PA_TYPEID_ALSA, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 56eb14556..67e38a1d9 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -46,6 +46,8 @@ PA_MODULE_DESCRIPTION("ALSA Source") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("source_name= device= format= channels= rate= fragments= fragment_size=") +#define PA_TYPEID_ALSA PA_TYPEID_MAKE('A', 'L', 'S', 'A') + struct userdata { snd_pcm_t *pcm_handle; struct pa_source *source; @@ -203,7 +205,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; } - u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); + u->source = pa_source_new(c, PA_TYPEID_ALSA, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); assert(u->source); u->source->userdata = u; diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 7b3c26dd6..ca79d7df9 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -43,6 +43,8 @@ PA_MODULE_DESCRIPTION("Combine multiple sinks to one") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= master= slaves= adjust_time= resample_method=") +#define PA_TYPEID_COMBINE PA_TYPEID_MAKE('C', 'M', 'B', 'N') + #define DEFAULT_SINK_NAME "combined" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define RENDER_SIZE (1024*10) @@ -214,7 +216,7 @@ static struct output *output_new(struct userdata *u, struct pa_sink *sink, int r o->memblockq = pa_memblockq_new(MEMBLOCKQ_MAXLENGTH, MEMBLOCKQ_MAXLENGTH, pa_frame_size(&u->sink->sample_spec), 0, 0, sink->core->memblock_stat); snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1); - if (!(o->sink_input = pa_sink_input_new(sink, t, &u->sink->sample_spec, 1, resample_method))) + if (!(o->sink_input = pa_sink_input_new(sink, PA_TYPEID_COMBINE, t, &u->sink->sample_spec, 1, resample_method))) goto fail; o->sink_input->get_latency = sink_input_get_latency_cb; @@ -325,7 +327,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { goto fail; } - if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec))) { + if (!(u->sink = pa_sink_new(c, PA_TYPEID_COMBINE, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec))) { pa_log(__FILE__": failed to create sink\n"); goto fail; } diff --git a/polyp/module-esound-sink.c b/polyp/module-esound-sink.c index 2cc61440f..82c38cc28 100644 --- a/polyp/module-esound-sink.c +++ b/polyp/module-esound-sink.c @@ -52,6 +52,8 @@ PA_MODULE_USAGE("sink_name= server=
    cookie=state = STATE_AUTH; u->latency = 0; - if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + if (!(u->sink = pa_sink_new(c, PA_TYPEID_ESOUND_SINK, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { pa_log(__FILE__": failed to create sink.\n"); goto fail; } diff --git a/polyp/module-null-sink.c b/polyp/module-null-sink.c index 6d4ea89b2..fcac1ea44 100644 --- a/polyp/module-null-sink.c +++ b/polyp/module-null-sink.c @@ -49,6 +49,8 @@ PA_MODULE_USAGE("format= channels= rate=module = m; m->userdata = u; - if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + if (!(u->sink = pa_sink_new(c, PA_TYPEID_NULL, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { pa_log(__FILE__": failed to create sink.\n"); goto fail; } diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 6fe4fa0cd..3c5c0ad86 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -53,6 +53,8 @@ PA_MODULE_DESCRIPTION("OSS Sink/Source (mmap)") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= fragments= fragment_size=") +#define PA_TYPEID_OSS_MMAP PA_TYPEID_MAKE('O', 'S', 'S', 'M') + struct userdata { struct pa_sink *sink; struct pa_source *source; @@ -302,7 +304,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { } } else { - u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec); + u->source = pa_source_new(c, PA_TYPEID_OSS_MMAP, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec); assert(u->source); u->source->userdata = u; pa_source_set_owner(u->source, m); @@ -334,7 +336,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { } else { pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); - u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec); + u->sink = pa_sink_new(c, PA_TYPEID_OSS_MMAP, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; diff --git a/polyp/module-oss.c b/polyp/module-oss.c index fa01876dd..67922d826 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -52,6 +52,8 @@ PA_MODULE_DESCRIPTION("OSS Sink/Source") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= fragments= fragment_size=") +#define PA_TYPEID_OSS PA_TYPEID_MAKE('O', 'S', 'S', '_') + struct userdata { struct pa_sink *sink; struct pa_source *source; @@ -325,7 +327,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { } if (mode != O_WRONLY) { - u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); + u->source = pa_source_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); assert(u->source); u->source->userdata = u; u->source->get_latency = source_get_latency_cb; @@ -335,7 +337,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->source = NULL; if (mode != O_RDONLY) { - u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); + u->sink = pa_sink_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index 6c441cc8c..b6d8dc2e0 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -50,6 +50,8 @@ PA_MODULE_USAGE("sink_name= file= format=module = m; m->userdata = u; - if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + if (!(u->sink = pa_sink_new(c, PA_TYPEID_PIPE, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { pa_log(__FILE__": failed to create sink.\n"); goto fail; } diff --git a/polyp/module-pipe-source.c b/polyp/module-pipe-source.c index e8a17b962..5a397162b 100644 --- a/polyp/module-pipe-source.c +++ b/polyp/module-pipe-source.c @@ -50,6 +50,8 @@ PA_MODULE_USAGE("source_name= file= forma #define DEFAULT_FIFO_NAME "/tmp/music.input" #define DEFAULT_SOURCE_NAME "fifo_input" +#define PA_TYPEID_PIPE PA_TYPEID_MAKE('P', 'I', 'P', 'E') + struct userdata { struct pa_core *core; @@ -152,7 +154,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->filename = pa_xstrdup(p); u->core = c; - if (!(u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) { + if (!(u->source = pa_source_new(c, PA_TYPEID_PIPE, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) { pa_log(__FILE__": failed to create source.\n"); goto fail; } diff --git a/polyp/module-sine.c b/polyp/module-sine.c index 834148218..d8f7e4ef1 100644 --- a/polyp/module-sine.c +++ b/polyp/module-sine.c @@ -40,6 +40,8 @@ PA_MODULE_DESCRIPTION("Sine wave generator") PA_MODULE_USAGE("sink= frequency=") PA_MODULE_VERSION(PACKAGE_VERSION) +#define PA_TYPEID_SINE PA_TYPEID_MAKE('S', 'I', 'N', 'E') + struct userdata { struct pa_core *core; struct pa_module *module; @@ -140,7 +142,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { calc_sine(u->memblock->data, u->memblock->length, frequency); snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); - if (!(u->sink_input = pa_sink_input_new(sink, t, &ss, 0, -1))) + if (!(u->sink_input = pa_sink_input_new(sink, PA_TYPEID_SINE, t, &ss, 0, -1))) goto fail; u->sink_input->peek = sink_input_peek; diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index d165aab87..9da87b3d2 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -60,6 +60,8 @@ PA_MODULE_USAGE("server=
    source= cookie= PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_VERSION(PACKAGE_VERSION) +#define PA_TYPEID_TUNNEL PA_TYPEID_MAKE('T', 'U', 'N', 'L') + #define DEFAULT_SINK_NAME "tunnel" #define DEFAULT_SOURCE_NAME "tunnel" @@ -624,7 +626,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { pa_socket_client_set_callback(u->client, on_connection, u); #ifdef TUNNEL_SINK - if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + if (!(u->sink = pa_sink_new(c, PA_TYPEID_TUNNEL, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { pa_log(__FILE__": failed to create sink.\n"); goto fail; } @@ -636,7 +638,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { pa_sink_set_owner(u->sink, m); #else - if (!(u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) { + if (!(u->source = pa_source_new(c, PA_TYPEID_TUNNEL, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) { pa_log(__FILE__": failed to create source.\n"); goto fail; } diff --git a/polyp/module-zeroconf-publish.c b/polyp/module-zeroconf-publish.c index 363c24192..c88ac766f 100644 --- a/polyp/module-zeroconf-publish.c +++ b/polyp/module-zeroconf-publish.c @@ -40,6 +40,7 @@ #include "log.h" #include "subscribe.h" #include "dynarray.h" +#include "endianmacros.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher") @@ -79,21 +80,36 @@ static sw_result publish_reply(sw_discovery discovery, sw_discovery_publish_stat return SW_OKAY; } -static void get_service_sample_spec(struct userdata *u, struct service *s, struct pa_sample_spec *ret_ss) { - assert(u && s && s->loaded.valid && ret_ss); +static void get_service_data(struct userdata *u, struct service *s, struct pa_sample_spec *ret_ss, char **ret_description, pa_typeid_t *ret_typeid) { + assert(u && s && s->loaded.valid && ret_ss && ret_description && ret_typeid); if (s->loaded.type == PA_NAMEREG_SINK) { struct pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index); assert(sink); *ret_ss = sink->sample_spec; + *ret_description = sink->description; + *ret_typeid = sink->typeid; } else if (s->loaded.type == PA_NAMEREG_SOURCE) { struct pa_source *source = pa_idxset_get_by_index(u->core->sources, s->loaded.index); assert(source); *ret_ss = source->sample_spec; + *ret_description = source->description; + *ret_typeid = source->typeid; } else assert(0); } +static void txt_record_server_data(struct pa_core *c, sw_text_record t) { + char s[256]; + assert(c); + + sw_text_record_add_key_and_string_value(t, "server-version", PACKAGE_NAME" "PACKAGE_VERSION); + sw_text_record_add_key_and_string_value(t, "user-name", pa_get_user_name(s, sizeof(s))); + sw_text_record_add_key_and_string_value(t, "fqdn", pa_get_fqdn(s, sizeof(s))); + snprintf(s, sizeof(s), "0x%08x", c->cookie); + sw_text_record_add_key_and_string_value(t, "cookie", s); +} + static int publish_service(struct userdata *u, struct service *s) { assert(u && s); char t[256]; @@ -120,18 +136,27 @@ static int publish_service(struct userdata *u, struct service *s) { free_txt = 1; sw_text_record_add_key_and_string_value(txt, "device", s->name); + + txt_record_server_data(u->core, txt); if (s->loaded.valid) { - char z[64]; + char z[64], *description; + pa_typeid_t typeid; struct pa_sample_spec ss; - get_service_sample_spec(u, s, &ss); + get_service_data(u, s, &ss, &description, &typeid); snprintf(z, sizeof(z), "%u", ss.rate); sw_text_record_add_key_and_string_value(txt, "rate", z); snprintf(z, sizeof(z), "%u", ss.channels); sw_text_record_add_key_and_string_value(txt, "channels", z); sw_text_record_add_key_and_string_value(txt, "format", pa_sample_format_to_string(ss.format)); + + sw_text_record_add_key_and_string_value(txt, "description", description); + + snprintf(z, sizeof(z), "0x%8x", typeid); + sw_text_record_add_key_and_string_value(txt, "typeid", z); + if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t, s->loaded.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE, diff --git a/polyp/pabrowse.c b/polyp/pabrowse.c new file mode 100644 index 000000000..ccea0cd41 --- /dev/null +++ b/polyp/pabrowse.c @@ -0,0 +1,139 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include + +static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { + fprintf(stderr, "Got signal, exiting\n"); + m->quit(m, 0); +} + +static void dump_server(const struct pa_browse_info *i) { + char t[16]; + + if (i->cookie) + snprintf(t, sizeof(t), "0x%08x", *i->cookie); + + printf("server: %s\n" + "server-version: %s\n" + "user-name: %s\n" + "fqdn: %s\n" + "cookie: %s\n", + i->server, + i->server_version ? i->server_version : "n/a", + i->user_name ? i->user_name : "n/a", + i->fqdn ? i->fqdn : "n/a", + i->cookie ? t : "n/a"); +} + +static void dump_device(const struct pa_browse_info *i) { + char t[16], ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; + + if (i->sample_spec) + pa_sample_spec_snprint(ss, sizeof(ss), i->sample_spec); + + if (i->typeid) + pa_typeid_to_string(*i->typeid, t, sizeof(t)); + + printf("device: %s\n" + "description: %s\n" + "type: %s\n" + "sample spec: %s\n", + i->device, + i->description ? i->description : "n/a", + i->typeid ? t : "n/a", + i->sample_spec ? ss : "n/a"); + +} + +static void browser_callback(struct pa_browser *b, enum pa_browse_opcode c, const struct pa_browse_info *i, void *userdata) { + assert(b && i); + + switch (c) { + + case PA_BROWSE_NEW_SERVER: + printf("\n=> new server <%s>\n", i->name); + dump_server(i); + break; + + case PA_BROWSE_NEW_SINK: + printf("\n=> new sink <%s>\n", i->name); + dump_server(i); + dump_device(i); + break; + + case PA_BROWSE_NEW_SOURCE: + printf("\n=> new source <%s>\n", i->name); + dump_server(i); + dump_device(i); + break; + + case PA_BROWSE_REMOVE: + printf("\n=> removed service <%s>\n", i->name); + break; + + default: + ; + } +} + + +int main(int argc, char *argv[]) { + struct pa_mainloop *mainloop = NULL; + struct pa_browser *browser = NULL; + int ret = 1, r; + + if (!(mainloop = pa_mainloop_new())) + goto finish; + + r = pa_signal_init(pa_mainloop_get_api(mainloop)); + assert(r == 0); + pa_signal_new(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGTERM, exit_signal_callback, NULL); + signal(SIGPIPE, SIG_IGN); + + if (!(browser = pa_browser_new(pa_mainloop_get_api(mainloop)))) + goto finish; + + pa_browser_set_callback(browser, browser_callback, NULL); + + ret = 0; + pa_mainloop_run(mainloop, &ret); + +finish: + if (mainloop) { + pa_signal_done(); + pa_mainloop_free(mainloop); + } + + return ret; +} diff --git a/polyp/pacat.c b/polyp/pacat.c index 8c3ee0ba8..5910d13fc 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -38,7 +38,7 @@ #include #include -#if PA_API_VERSION != 7 +#if PA_API_VERSION != 8 #error Invalid Polypaudio API version #endif @@ -290,7 +290,7 @@ static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int /* UNIX signal to quit recieved */ static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { if (verbose) - fprintf(stderr, "Got SIGINT, exiting.\n"); + fprintf(stderr, "Got signal, exiting.\n"); quit(0); } @@ -479,6 +479,7 @@ int main(int argc, char *argv[]) { r = pa_signal_init(mainloop_api); assert(r == 0); pa_signal_new(SIGINT, exit_signal_callback, NULL); + pa_signal_new(SIGTERM, exit_signal_callback, NULL); pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); diff --git a/polyp/pactl.c b/polyp/pactl.c index 6300b6562..d4dc6ad19 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -41,7 +41,7 @@ #include #include -#if PA_API_VERSION != 7 +#if PA_API_VERSION != 8 #error Invalid Polypaudio API version #endif @@ -134,20 +134,22 @@ static void get_server_info_callback(struct pa_context *c, const struct pa_serve "Server Version: %s\n" "Default Sample Specification: %s\n" "Default Sink: %s\n" - "Default Source: %s\n", + "Default Source: %s\n" + "Cookie: %08x\n", i->user_name, i->host_name, i->server_name, i->server_version, s, i->default_sink_name, - i->default_source_name); + i->default_source_name, + i->cookie); complete_action(); } static void get_sink_info_callback(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata) { - char s[PA_SAMPLE_SPEC_SNPRINT_MAX]; + char s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5]; if (is_last < 0) { fprintf(stderr, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c))); @@ -170,6 +172,7 @@ static void get_sink_info_callback(struct pa_context *c, const struct pa_sink_in printf("*** Sink #%u ***\n" "Name: %s\n" + "Type: %s\n" "Description: %s\n" "Sample Specification: %s\n" "Owner Module: %u\n" @@ -178,16 +181,18 @@ static void get_sink_info_callback(struct pa_context *c, const struct pa_sink_in "Latency: %0.0f usec\n", i->index, i->name, + pa_typeid_to_string(i->typeid, tid, sizeof(tid)), i->description, s, i->owner_module, i->volume, pa_volume_to_dB(i->volume), i->monitor_source, (double) i->latency); + } static void get_source_info_callback(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata) { - char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32]; + char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], tid[5]; if (is_last < 0) { fprintf(stderr, "Failed to get source information: %s\n", pa_strerror(pa_context_errno(c))); @@ -212,18 +217,21 @@ static void get_source_info_callback(struct pa_context *c, const struct pa_sourc printf("*** Source #%u ***\n" "Name: %s\n" + "Type: %s\n" "Description: %s\n" "Sample Specification: %s\n" "Owner Module: %u\n" "Monitor of Sink: %s\n" "Latency: %0.0f usec\n", i->index, + pa_typeid_to_string(i->typeid, tid, sizeof(tid)), i->name, i->description, s, i->owner_module, i->monitor_of_sink != PA_INVALID_INDEX ? t : "no", (double) i->latency); + } static void get_module_info_callback(struct pa_context *c, const struct pa_module_info *i, int is_last, void *userdata) { @@ -261,7 +269,7 @@ static void get_module_info_callback(struct pa_context *c, const struct pa_modul } static void get_client_info_callback(struct pa_context *c, const struct pa_client_info *i, int is_last, void *userdata) { - char t[32]; + char t[32], tid[5]; if (is_last < 0) { fprintf(stderr, "Failed to get client information: %s\n", pa_strerror(pa_context_errno(c))); @@ -284,16 +292,16 @@ static void get_client_info_callback(struct pa_context *c, const struct pa_clien printf("*** Client #%u ***\n" "Name: %s\n" - "Owner Module: %s\n" - "Protocol Name: %s\n", + "Type: %s\n" + "Owner Module: %s\n", i->index, i->name, - i->owner_module != PA_INVALID_INDEX ? t : "n/a", - i->protocol_name); + pa_typeid_to_string(i->typeid, tid, sizeof(tid)), + i->owner_module != PA_INVALID_INDEX ? t : "n/a"); } static void get_sink_input_info_callback(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) { - char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX]; + char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5]; if (is_last < 0) { fprintf(stderr, "Failed to get sink input information: %s\n", pa_strerror(pa_context_errno(c))); @@ -318,6 +326,7 @@ static void get_sink_input_info_callback(struct pa_context *c, const struct pa_s printf("*** Sink Input #%u ***\n" "Name: %s\n" + "Type: %s\n" "Owner Module: %s\n" "Client: %s\n" "Sink: %u\n" @@ -328,6 +337,7 @@ static void get_sink_input_info_callback(struct pa_context *c, const struct pa_s "Resample method: %s\n", i->index, i->name, + pa_typeid_to_string(i->typeid, tid, sizeof(tid)), i->owner_module != PA_INVALID_INDEX ? t : "n/a", i->client != PA_INVALID_INDEX ? k : "n/a", i->sink, @@ -338,8 +348,9 @@ static void get_sink_input_info_callback(struct pa_context *c, const struct pa_s i->resample_method ? i->resample_method : "n/a"); } + static void get_source_output_info_callback(struct pa_context *c, const struct pa_source_output_info *i, int is_last, void *userdata) { - char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX]; + char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5]; if (is_last < 0) { fprintf(stderr, "Failed to get source output information: %s\n", pa_strerror(pa_context_errno(c))); @@ -364,6 +375,7 @@ static void get_source_output_info_callback(struct pa_context *c, const struct p printf("*** Source Output #%u ***\n" "Name: %s\n" + "Type: %s\n" "Owner Module: %s\n" "Client: %s\n" "Source: %u\n" @@ -373,6 +385,7 @@ static void get_source_output_info_callback(struct pa_context *c, const struct p "Resample method: %s\n", i->index, i->name, + pa_typeid_to_string(i->typeid, tid, sizeof(tid)), i->owner_module != PA_INVALID_INDEX ? t : "n/a", i->client != PA_INVALID_INDEX ? k : "n/a", i->source, diff --git a/polyp/paplay.c b/polyp/paplay.c index 0faa0ff24..2eaf07c1e 100644 --- a/polyp/paplay.c +++ b/polyp/paplay.c @@ -40,7 +40,7 @@ #include #include -#if PA_API_VERSION != 7 +#if PA_API_VERSION != 8 #error Invalid Polypaudio API version #endif diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index 1b611db4c..c7a854545 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -32,6 +32,8 @@ #include "sink-input.h" #include "xmalloc.h" +#define PA_TYPEID_MEMCHUNK PA_TYPEID_MAKE('M', 'C', 'N', 'K') + static void sink_input_kill(struct pa_sink_input *i) { struct pa_memchunk *c; assert(i && i->userdata); @@ -88,7 +90,7 @@ int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sam if (volume <= 0) return 0; - if (!(si = pa_sink_input_new(sink, name, ss, 0, -1))) + if (!(si = pa_sink_input_new(sink, PA_TYPEID_MEMCHUNK, name, ss, 0, -1))) return -1; si->volume = volume; diff --git a/polyp/polyplib-browser.c b/polyp/polyplib-browser.c new file mode 100644 index 000000000..a1bd3fb74 --- /dev/null +++ b/polyp/polyplib-browser.c @@ -0,0 +1,307 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +#include "polyplib-browser.h" +#include "xmalloc.h" +#include "log.h" +#include "util.h" + +#define SERVICE_NAME_SINK "_polypaudio-sink._tcp." +#define SERVICE_NAME_SOURCE "_polypaudio-source._tcp." +#define SERVICE_NAME_SERVER "_polypaudio-server._tcp." + +struct pa_browser { + int ref; + struct pa_mainloop_api *mainloop; + + void (*callback)(struct pa_browser *z, enum pa_browse_opcode c, const struct pa_browse_info *i, void *userdata); + void *callback_userdata; + + sw_discovery discovery; + struct pa_io_event *io_event; +}; + + +static void io_callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags events, void *userdata) { + struct pa_browser *b = userdata; + assert(a && b && b->mainloop == a); + + if (events != PA_IO_EVENT_INPUT || sw_discovery_read_socket(b->discovery) != SW_OKAY) { + pa_log(__FILE__": connection to HOWL daemon failed.\n"); + b->mainloop->io_free(b->io_event); + b->io_event = NULL; + return; + } +} + + +static sw_result resolve_reply( + sw_discovery discovery, + sw_discovery_oid oid, + sw_uint32 interface_index, + sw_const_string name, + sw_const_string type, + sw_const_string domain, + sw_ipv4_address address, + sw_port port, + sw_octets text_record, + sw_ulong text_record_len, + sw_opaque extra) { + + struct pa_browser *b = extra; + struct pa_browse_info i; + char ip[256], a[256]; + enum pa_browse_opcode opcode; + int device_found = 0; + uint32_t cookie; + pa_typeid_t typeid; + struct pa_sample_spec ss; + int ss_valid = 0; + sw_text_record_iterator iterator; + int free_iterator = 0; + char *c = NULL; + + assert(b); + + sw_discovery_cancel(discovery, oid); + + memset(&i, 0, sizeof(i)); + i.name = name; + + if (!b->callback) + goto fail; + + if (!strcmp(type, SERVICE_NAME_SINK)) + opcode = PA_BROWSE_NEW_SINK; + else if (!strcmp(type, SERVICE_NAME_SOURCE)) + opcode = PA_BROWSE_NEW_SOURCE; + else if (!strcmp(type, SERVICE_NAME_SERVER)) + opcode = PA_BROWSE_NEW_SERVER; + else + goto fail; + + + snprintf(a, sizeof(a), "tcp:%s:%u", sw_ipv4_address_name(address, ip, sizeof(ip)), port); + i.server = a; + + if (text_record && text_record_len) { + char key[SW_TEXT_RECORD_MAX_LEN]; + uint8_t val[SW_TEXT_RECORD_MAX_LEN]; + uint32_t val_len; + + if (sw_text_record_iterator_init(&iterator, text_record, text_record_len) != SW_OKAY) { + pa_log("sw_text_record_string_iterator_init() failed.\n"); + goto fail; + } + + free_iterator = 1; + + while (sw_text_record_iterator_next(iterator, key, val, &val_len) == SW_OKAY) { + c = pa_xstrndup((char*) val, val_len); + + if (!strcmp(key, "device")) { + device_found = 1; + pa_xfree((char*) i.device); + i.device = c; + c = NULL; + } else if (!strcmp(key, "server-version")) { + pa_xfree((char*) i.server_version); + i.server_version = c; + c = NULL; + } else if (!strcmp(key, "user-name")) { + pa_xfree((char*) i.user_name); + i.user_name = c; + c = NULL; + } else if (!strcmp(key, "fqdn")) { + pa_xfree((char*) i.fqdn); + i.fqdn = c; + c = NULL; + } else if (!strcmp(key, "cookie")) { + + if (pa_atou(c, &cookie) < 0) + goto fail; + + i.cookie = &cookie; + } else if (!strcmp(key, "description")) { + pa_xfree((char*) i.description); + i.description = c; + c = NULL; + } else if (!strcmp(key, "typeid")) { + + if (pa_atou(c, &typeid) < 0) + goto fail; + + i.typeid = &typeid; + } else if (!strcmp(key, "channels")) { + uint32_t ch; + + if (pa_atou(c, &ch) < 0 || ch <= 0 || ch > 255) + goto fail; + + ss.channels = (uint8_t) ch; + ss_valid |= 1; + + } else if (!strcmp(key, "rate")) { + if (pa_atou(c, &ss.rate) < 0) + goto fail; + ss_valid |= 2; + } else if (!strcmp(key, "format")) { + + if ((ss.format = pa_parse_sample_format(c)) == PA_SAMPLE_INVALID) + goto fail; + + ss_valid |= 4; + } + + pa_xfree(c); + c = NULL; + } + + } + + /* No device txt record was sent for a sink or source service */ + if (opcode != PA_BROWSE_NEW_SERVER && !device_found) + goto fail; + + if (ss_valid == 7) + i.sample_spec = &ss; + + + b->callback(b, opcode, &i, b->callback_userdata); + +fail: + pa_xfree((void*) i.device); + pa_xfree((void*) i.fqdn); + pa_xfree((void*) i.server_version); + pa_xfree((void*) i.user_name); + pa_xfree((void*) i.description); + pa_xfree(c); + + if (free_iterator) + sw_text_record_iterator_fina(iterator); + + + return SW_OKAY; +} + +static sw_result browse_reply( + sw_discovery discovery, + sw_discovery_oid id, + sw_discovery_browse_status status, + sw_uint32 interface_index, + sw_const_string name, + sw_const_string type, + sw_const_string domain, + sw_opaque extra) { + + struct pa_browser *b = extra; + assert(b); + + switch (status) { + case SW_DISCOVERY_BROWSE_ADD_SERVICE: { + sw_discovery_oid oid; + fprintf(stderr, "debug: new service: %s\n", name); + + if (sw_discovery_resolve(b->discovery, 0, name, type, domain, resolve_reply, b, &oid) != SW_OKAY) + pa_log("sw_discovery_resolve() failed\n"); + + break; + } + + case SW_DISCOVERY_BROWSE_REMOVE_SERVICE: + if (b->callback) { + struct pa_browse_info i; + memset(&i, 0, sizeof(i)); + i.name = name; + b->callback(b, PA_BROWSE_REMOVE, &i, b->callback_userdata); + } + break; + + default: + ; + } + + return SW_OKAY; +} + +struct pa_browser *pa_browser_new(struct pa_mainloop_api *mainloop) { + struct pa_browser *b; + sw_discovery_oid oid; + + b = pa_xmalloc(sizeof(struct pa_browser)); + b->mainloop = mainloop; + b->ref = 1; + b->callback = NULL; + b->callback_userdata = NULL; + + if (sw_discovery_init(&b->discovery) != SW_OKAY) { + pa_log("sw_discovery_init() failed.\n"); + pa_xfree(b); + return NULL; + } + + if (sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SERVER, NULL, browse_reply, b, &oid) != SW_OKAY || + sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SINK, NULL, browse_reply, b, &oid) != SW_OKAY || + sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SOURCE, NULL, browse_reply, b, &oid) != SW_OKAY) { + + pa_log("sw_discovery_browse() failed.\n"); + + sw_discovery_fina(b->discovery); + pa_xfree(b); + return NULL; + } + + b->io_event = mainloop->io_new(mainloop, sw_discovery_socket(b->discovery), PA_IO_EVENT_INPUT, io_callback, b); + return b; +} + +static void browser_free(struct pa_browser *b) { + assert(b && b->mainloop); + + if (b->io_event) + b->mainloop->io_free(b->io_event); + + sw_discovery_fina(b->discovery); + pa_xfree(b); +} + +struct pa_browser *pa_browser_ref(struct pa_browser *b) { + assert(b && b->ref >= 1); + b->ref++; + return b; +} + +void pa_browser_unref(struct pa_browser *b) { + assert(b && b->ref >= 1); + + if ((-- (b->ref)) <= 0) + browser_free(b); +} + +void pa_browser_set_callback(struct pa_browser *b, void (*cb)(struct pa_browser *z, enum pa_browse_opcode c, const struct pa_browse_info *i, void* userdata), void *userdata) { + assert(b); + + b->callback = cb; + b->callback_userdata = userdata; +} diff --git a/polyp/polyplib-browser.h b/polyp/polyplib-browser.h new file mode 100644 index 000000000..c13eff227 --- /dev/null +++ b/polyp/polyplib-browser.h @@ -0,0 +1,65 @@ +#ifndef foopolyplibbrowserhfoo +#define foopolyplibbrowserhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include + +PA_C_DECL_BEGIN + +struct pa_browser; + +enum pa_browse_opcode { + PA_BROWSE_NEW_SERVER, + PA_BROWSE_NEW_SINK, + PA_BROWSE_NEW_SOURCE, + PA_BROWSE_REMOVE +}; + +struct pa_browser *pa_browser_new(struct pa_mainloop_api *mainloop); +struct pa_browser *pa_browser_ref(struct pa_browser *z); +void pa_browser_unref(struct pa_browser *z); + +struct pa_browse_info { + /* Unique service name */ + const char *name; /* always available */ + + /* Server info */ + const char *server; /* always available */ + const char *server_version, *user_name, *fqdn; /* optional */ + const uint32_t *cookie; /* optional */ + + /* Device info */ + const char *device; /* always available when this information is of a sink/source */ + const char *description; /* optional */ + const pa_typeid_t *typeid; /* optional */ + const struct pa_sample_spec *sample_spec; /* optional */ +}; + +void pa_browser_set_callback(struct pa_browser *z, void (*cb)(struct pa_browser *z, enum pa_browse_opcode c, const struct pa_browse_info *i, void *userdata), void *userdata); + +PA_C_DECL_END + +#endif diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index db4b121dd..0283312a7 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -1,4 +1,3 @@ - #ifndef foopolyplibcontexthfoo #define foopolyplibcontexthfoo @@ -23,11 +22,11 @@ USA. ***/ -#include "sample.h" -#include "polyplib-def.h" -#include "mainloop-api.h" -#include "cdecl.h" -#include "polyplib-operation.h" +#include +#include +#include +#include +#include /** \file * Connection contexts for asynchrononous communication with a diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 44c2034bb..9adb68fc9 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -26,8 +26,8 @@ #include #include -#include "cdecl.h" -#include "sample.h" +#include +#include /** \file * Global definitions */ diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index fe632c267..166555c0a 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -85,6 +85,7 @@ static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t c pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_gets(t, &i.default_sink_name) < 0 || pa_tagstruct_gets(t, &i.default_source_name) < 0 || + pa_tagstruct_getu32(t, &i.cookie) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); @@ -130,7 +131,9 @@ static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t com pa_tagstruct_getu32(t, &i.volume) < 0 || pa_tagstruct_getu32(t, &i.monitor_source) < 0 || pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_get_usec(t, &i.latency) < 0) { + pa_tagstruct_get_usec(t, &i.latency) < 0 || + pa_tagstruct_getu32(t, &i.typeid) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -222,7 +225,8 @@ static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t c pa_tagstruct_getu32(t, &i.owner_module) < 0 || pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 || - pa_tagstruct_get_usec(t, &i.latency) < 0) { + pa_tagstruct_get_usec(t, &i.latency) < 0 || + pa_tagstruct_getu32(t, &i.typeid) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; @@ -310,8 +314,8 @@ static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t c if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.protocol_name) < 0 || - pa_tagstruct_getu32(t, &i.owner_module) < 0) { + pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_getu32(t, &i.typeid) < 0 ) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -450,7 +454,9 @@ static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32 pa_tagstruct_getu32(t, &i.volume) < 0 || pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || pa_tagstruct_get_usec(t, &i.sink_usec) < 0 || - pa_tagstruct_gets(t, &i.resample_method) < 0) { + pa_tagstruct_gets(t, &i.resample_method) < 0 || + pa_tagstruct_getu32(t, &i.typeid) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -521,7 +527,9 @@ static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uin pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || pa_tagstruct_get_usec(t, &i.source_usec) < 0 || - pa_tagstruct_gets(t, &i.resample_method) < 0) { + pa_tagstruct_gets(t, &i.resample_method) < 0 || + pa_tagstruct_getu32(t, &i.typeid) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -659,6 +667,7 @@ static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t c pa_tagstruct_getu32(t, &i.bytes) < 0 || pa_tagstruct_get_boolean(t, &i.lazy) < 0 || pa_tagstruct_gets(t, &i.filename) < 0) { + pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 08b36f866..ba9bde3c2 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -24,9 +24,10 @@ #include -#include "polyplib-operation.h" -#include "polyplib-context.h" -#include "cdecl.h" +#include +#include +#include +#include /** \file * @@ -57,6 +58,7 @@ struct pa_sink_info { uint32_t monitor_source; /**< Index of the monitor source connected to this sink */ const char *monitor_source_name; /**< The name of the monitor source */ pa_usec_t latency; /**< Length of filled playback buffer of this sink */ + pa_typeid_t typeid; /**< Implementation type. \since 0.8 */ }; /** Get information about a sink by its name */ @@ -78,6 +80,7 @@ struct pa_source_info { uint32_t monitor_of_sink; /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */ const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */ pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */ + pa_typeid_t typeid; /**< Implementation type. \since 0.8 */ }; /** Get information about a source by its name */ @@ -97,7 +100,8 @@ struct pa_server_info { const char *server_name; /**< Server package name (usually "polypaudio") */ struct pa_sample_spec sample_spec; /**< Default sample specification */ const char *default_sink_name; /**< Name of default sink. \since 0.4 */ - const char *default_source_name; /**< Name of default sink. \since 0.4*/ + const char *default_source_name; /**< Name of default sink. \since 0.4*/ + uint32_t cookie; /**< A random cookie for identifying this instance of polypaudio. \since 0.8 */ }; /** Get some information about the server */ @@ -123,7 +127,7 @@ struct pa_client_info { uint32_t index; /**< Index of this client */ const char *name; /**< Name of this client */ uint32_t owner_module; /**< Index of the owning module, or PA_INVALID_INDEX */ - const char *protocol_name; /**< A string describing the protocol name this client is connected over (i.e. "ESOUND", "NATIVE", "SIMPLE") */ + pa_typeid_t typeid; /**< Implementation type. \since 0.8 */ }; /** Get information about a client by its index */ @@ -144,6 +148,7 @@ struct pa_sink_input_info { pa_usec_t buffer_usec; /**< Latency due to buffering in sink input, see pa_latency_info for details */ pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */ const char *resample_method; /**< Thre resampling method used by this sink input. \since 0.7 */ + pa_typeid_t typeid; /**< Implementation type. \since 0.8 */ }; /** Get some information about a sink input by its index */ @@ -163,6 +168,7 @@ struct pa_source_output_info { pa_usec_t buffer_usec; /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */ pa_usec_t source_usec; /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */ const char *resample_method; /**< Thre resampling method used by this source output. \since 0.7 */ + pa_typeid_t typeid; /**< Implementation type. \since 0.8 */ }; /** Get information about a source output by its index */ diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h index bd1366d28..5c3af49ca 100644 --- a/polyp/polyplib-operation.h +++ b/polyp/polyplib-operation.h @@ -22,8 +22,8 @@ USA. ***/ -#include "cdecl.h" -#include "polyplib-def.h" +#include +#include /** \file * Asynchronous operations */ diff --git a/polyp/polyplib-scache.h b/polyp/polyplib-scache.h index 051bdd120..8ec375ea1 100644 --- a/polyp/polyplib-scache.h +++ b/polyp/polyplib-scache.h @@ -24,9 +24,9 @@ #include -#include "polyplib-context.h" -#include "polyplib-stream.h" -#include "cdecl.h" +#include +#include +#include /** \file * All sample cache related routines */ diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index 53873491a..939b2ae64 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -24,10 +24,10 @@ #include -#include "sample.h" -#include "polyplib-def.h" -#include "cdecl.h" -#include "polyplib-operation.h" +#include +#include +#include +#include /** \file * Audio streams for input, output and sample upload */ diff --git a/polyp/polyplib-subscribe.h b/polyp/polyplib-subscribe.h index a677bd02c..5c697b716 100644 --- a/polyp/polyplib-subscribe.h +++ b/polyp/polyplib-subscribe.h @@ -24,9 +24,9 @@ #include -#include "polyplib-def.h" -#include "polyplib-context.h" -#include "cdecl.h" +#include +#include +#include /** \file * Daemon introspection event subscription subsystem. Use this diff --git a/polyp/polyplib.h b/polyp/polyplib.h index a0c418d49..b9b9b447d 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -22,16 +22,16 @@ USA. ***/ -#include "cdecl.h" -#include "mainloop-api.h" -#include "sample.h" -#include "polyplib-def.h" -#include "polyplib-context.h" -#include "polyplib-stream.h" -#include "polyplib-introspect.h" -#include "polyplib-subscribe.h" -#include "polyplib-scache.h" -#include "polyplib-version.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /** \file * Include all polyplib header file at once. The following files are included: \ref mainloop-api.h, \ref sample.h, diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index a32a9bd87..d9ed66b98 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -63,6 +63,8 @@ #define SCACHE_PREFIX "esound." +#define PA_TYPEID_ESOUND PA_TYPEID_MAKE('E', 'S', 'D', 'P') + /* This is heavily based on esound's code */ struct connection { @@ -320,7 +322,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons assert(!c->sink_input && !c->input_memblockq); - if (!(c->sink_input = pa_sink_input_new(sink, name, &ss, 0, -1))) { + if (!(c->sink_input = pa_sink_input_new(sink, PA_TYPEID_ESOUND, name, &ss, 0, -1))) { pa_log(__FILE__": failed to create sink input.\n"); return -1; } @@ -392,7 +394,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co assert(!c->output_memblockq && !c->source_output); - if (!(c->source_output = pa_source_output_new(source, name, &ss, -1))) { + if (!(c->source_output = pa_source_output_new(source, PA_TYPEID_ESOUND, name, &ss, -1))) { pa_log(__FILE__": failed to create source output\n"); return -1; } @@ -1058,7 +1060,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); assert(p->core); - c->client = pa_client_new(p->core, "ESOUND", cname); + c->client = pa_client_new(p->core, PA_TYPEID_ESOUND, cname); assert(c->client); c->client->owner = p->module; c->client->kill = client_kill_cb; diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 94dc5e5fa..d5619ef7a 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -56,6 +56,8 @@ /* Don't accept more connection than this */ #define MAX_CONNECTIONS 10 +#define PA_TYPEID_NATIVE PA_TYPEID_MAKE('N', 'A', 'T', 'V') + struct connection; struct pa_protocol_native; @@ -272,7 +274,7 @@ static struct record_stream* record_stream_new(struct connection *c, struct pa_s size_t base; assert(c && source && ss && name && maxlength); - if (!(source_output = pa_source_output_new(source, name, ss, -1))) + if (!(source_output = pa_source_output_new(source, PA_TYPEID_NATIVE, name, ss, -1))) return NULL; s = pa_xmalloc(sizeof(struct record_stream)); @@ -316,7 +318,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct struct pa_sink_input *sink_input; assert(c && sink && ss && name && maxlength); - if (!(sink_input = pa_sink_input_new(sink, name, ss, 0, -1))) + if (!(sink_input = pa_sink_input_new(sink, PA_TYPEID_NATIVE, name, ss, 0, -1))) return NULL; s = pa_xmalloc(sizeof(struct playback_stream)); @@ -1118,6 +1120,7 @@ static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) { pa_tagstruct_putu32(t, sink->monitor_source->index); pa_tagstruct_puts(t, sink->monitor_source->name); pa_tagstruct_put_usec(t, pa_sink_get_latency(sink)); + pa_tagstruct_putu32(t, sink->typeid); } static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *source) { @@ -1130,14 +1133,15 @@ static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *sour pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1); pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : NULL); pa_tagstruct_put_usec(t, pa_source_get_latency(source)); + pa_tagstruct_putu32(t, source->typeid); } static void client_fill_tagstruct(struct pa_tagstruct *t, struct pa_client *client) { assert(t && client); pa_tagstruct_putu32(t, client->index); pa_tagstruct_puts(t, client->name); - pa_tagstruct_puts(t, client->protocol_name); pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1); + pa_tagstruct_putu32(t, client->typeid); } static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *module) { @@ -1161,6 +1165,7 @@ static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_inp pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s)); pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink)); pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s))); + pa_tagstruct_putu32(t, s->typeid); } static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) { @@ -1174,6 +1179,7 @@ static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_sourc pa_tagstruct_put_usec(t, pa_source_output_get_latency(s)); pa_tagstruct_put_usec(t, pa_source_get_latency(s->source)); pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s))); + pa_tagstruct_putu32(t, s->typeid); } static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry *e) { @@ -1366,6 +1372,9 @@ static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, u pa_tagstruct_puts(reply, n); n = pa_namereg_get_default_source_name(c->protocol->core); pa_tagstruct_puts(reply, n); + + pa_tagstruct_putu32(reply, c->protocol->core->cookie); + pa_pstream_send_tagstruct(c->pstream, reply); } @@ -2022,7 +2031,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->protocol = p; assert(p->core); - c->client = pa_client_new(p->core, "NATIVE", "Client"); + c->client = pa_client_new(p->core, PA_TYPEID_NATIVE, "Client"); assert(c->client); c->client->kill = client_kill_cb; c->client->userdata = c; diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 3dddc4747..8d05a7fa0 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -42,6 +42,8 @@ /* Don't allow more than this many concurrent connections */ #define MAX_CONNECTIONS 10 +#define PA_TYPEID_SIMPLE PA_TYPEID_MAKE('S', 'M', 'P', 'L') + struct connection { struct pa_protocol_simple *protocol; struct pa_iochannel *io; @@ -308,7 +310,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->playback.fragment_size = 0; pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); - c->client = pa_client_new(p->core, "SIMPLE", cname); + c->client = pa_client_new(p->core, PA_TYPEID_SIMPLE, cname); assert(c->client); c->client->owner = p->module; c->client->kill = client_kill_cb; @@ -323,7 +325,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo goto fail; } - if (!(c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec, 0, -1))) { + if (!(c->sink_input = pa_sink_input_new(sink, PA_TYPEID_SIMPLE, c->client->name, &p->sample_spec, 0, -1))) { pa_log(__FILE__": Failed to create sink input.\n"); goto fail; } @@ -353,7 +355,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo goto fail; } - c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec, -1); + c->source_output = pa_source_output_new(source, PA_TYPEID_SIMPLE, c->client->name, &p->sample_spec, -1); if (!c->source_output) { pa_log(__FILE__": Failed to create source output.\n"); goto fail; diff --git a/polyp/random.c b/polyp/random.c new file mode 100644 index 000000000..456954a2b --- /dev/null +++ b/polyp/random.c @@ -0,0 +1,61 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include +#include +#include +#include + +#include "random.h" +#include "util.h" +#include "log.h" + +#define RANDOM_DEVICE "/dev/urandom" + +void pa_random(void *ret_data, size_t length) { + int fd; + ssize_t r = 0; + assert(ret_data && length); + + if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) { + + if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length) + pa_log_error(__FILE__": failed to read entropy from '%s'\n", RANDOM_DEVICE); + + close(fd); + } + + if ((size_t) r != length) { + uint8_t *p; + size_t l; + + pa_log_warn(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s" + ", falling back to unsecure pseudo RNG.\n", strerror(errno)); + + srandom(time(NULL)); + + for (p = ret_data, l = length; l > 0; p++, l--) + *p = (uint8_t) random(); + } +} diff --git a/polyp/random.h b/polyp/random.h new file mode 100644 index 000000000..bfb3df084 --- /dev/null +++ b/polyp/random.h @@ -0,0 +1,27 @@ +#ifndef foorandomhfoo +#define foorandomhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +void pa_random(void *ret_data, size_t length); + +#endif diff --git a/polyp/sample.c b/polyp/sample.c index b0723f70e..51afaa016 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -163,23 +163,23 @@ void pa_bytes_snprint(char *s, size_t l, unsigned v) { enum pa_sample_format pa_parse_sample_format(const char *format) { - if (strcmp(format, "s16le") == 0) + if (strcasecmp(format, "s16le") == 0) return PA_SAMPLE_S16LE; - else if (strcmp(format, "s16be") == 0) + else if (strcasecmp(format, "s16be") == 0) return PA_SAMPLE_S16BE; - else if (strcmp(format, "s16ne") == 0 || strcmp(format, "s16") == 0 || strcmp(format, "16") == 0) + else if (strcasecmp(format, "s16ne") == 0 || strcasecmp(format, "s16") == 0 || strcasecmp(format, "16") == 0) return PA_SAMPLE_S16NE; - else if (strcmp(format, "u8") == 0 || strcmp(format, "8") == 0) + else if (strcasecmp(format, "u8") == 0 || strcasecmp(format, "8") == 0) return PA_SAMPLE_U8; - else if (strcmp(format, "float32") == 0 || strcmp(format, "float32ne") == 0) + else if (strcasecmp(format, "float32") == 0 || strcasecmp(format, "float32ne") == 0) return PA_SAMPLE_FLOAT32; - else if (strcmp(format, "float32le") == 0) + else if (strcasecmp(format, "float32le") == 0) return PA_SAMPLE_FLOAT32LE; - else if (strcmp(format, "float32be") == 0) + else if (strcasecmp(format, "float32be") == 0) return PA_SAMPLE_FLOAT32BE; - else if (strcmp(format, "ulaw") == 0) + else if (strcasecmp(format, "ulaw") == 0) return PA_SAMPLE_ULAW; - else if (strcmp(format, "alaw") == 0) + else if (strcasecmp(format, "alaw") == 0) return PA_SAMPLE_ALAW; return -1; diff --git a/polyp/sample.h b/polyp/sample.h index 59226c469..d4873eb5c 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -26,7 +26,7 @@ #include #include -#include "cdecl.h" +#include /** \file * Constants and routines for sample type handling */ @@ -86,7 +86,7 @@ int pa_sample_spec_valid(const struct pa_sample_spec *spec); /** Return non-zero when the two sample type specifications match */ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b); -/* Return a descriptive string for the specified sample format. \since 0.7.1 */ +/* Return a descriptive string for the specified sample format. \since 0.8 */ const char *pa_sample_format_to_string(enum pa_sample_format f); /** Maximum required string length for pa_sample_spec_snprint() */ diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 347b8f5c6..3e7fdf7bf 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -36,7 +36,7 @@ #define CONVERT_BUFFER_LENGTH 4096 -struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method) { +struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method) { struct pa_sink_input *i; struct pa_resampler *resampler = NULL; int r; @@ -59,6 +59,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con i->ref = 1; i->state = PA_SINK_INPUT_RUNNING; i->name = pa_xstrdup(name); + i->typeid = typeid; i->client = NULL; i->owner = NULL; i->sink = s; diff --git a/polyp/sink-input.h b/polyp/sink-input.h index 5482369dd..83abe537d 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -42,6 +42,7 @@ struct pa_sink_input { enum pa_sink_input_state state; uint32_t index; + pa_typeid_t typeid; char *name; struct pa_module *owner; @@ -64,7 +65,7 @@ struct pa_sink_input { struct pa_resampler *resampler; }; -struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method); +struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method); void pa_sink_input_unref(struct pa_sink_input* i); struct pa_sink_input* pa_sink_input_ref(struct pa_sink_input* i); diff --git a/polyp/sink.c b/polyp/sink.c index 3d20884b8..481e5cf7a 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -39,7 +39,7 @@ #define MAX_MIX_CHANNELS 32 -struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) { +struct pa_sink* pa_sink_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec) { struct pa_sink *s; char *n = NULL; char st[256]; @@ -55,6 +55,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co s->name = pa_xstrdup(name); s->description = NULL; + s->typeid = typeid; s->ref = 1; s->state = PA_SINK_RUNNING; @@ -65,7 +66,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co s->inputs = pa_idxset_new(NULL, NULL); n = pa_sprintf_malloc("%s_monitor", name); - s->monitor_source = pa_source_new(core, n, 0, spec); + s->monitor_source = pa_source_new(core, typeid, n, 0, spec); assert(s->monitor_source); pa_xfree(n); s->monitor_source->monitor_of = s; diff --git a/polyp/sink.h b/polyp/sink.h index 5da4ca43b..844af964b 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -30,6 +30,7 @@ struct pa_sink; #include "sample.h" #include "idxset.h" #include "source.h" +#include "typeid.h" #define PA_MAX_INPUTS_PER_SINK 6 @@ -43,6 +44,7 @@ struct pa_sink { enum pa_sink_state state; uint32_t index; + pa_typeid_t typeid; char *name, *description; struct pa_module *owner; @@ -59,7 +61,7 @@ struct pa_sink { void *userdata; }; -struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec); +struct pa_sink* pa_sink_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec); void pa_sink_disconnect(struct pa_sink* s); void pa_sink_unref(struct pa_sink*s); struct pa_sink* pa_sink_ref(struct pa_sink *s); diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c index 43f932305..621c3ed95 100644 --- a/polyp/sound-file-stream.c +++ b/polyp/sound-file-stream.c @@ -36,6 +36,7 @@ #include "log.h" #define BUF_SIZE (1024*10) +#define PA_TYPEID_SOUND_FILE PA_TYPEID_MAKE('S', 'N', 'D', 'F') struct userdata { SNDFILE *sndfile; @@ -160,7 +161,7 @@ int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume) { goto fail; } - if (!(u->sink_input = pa_sink_input_new(sink, fname, &ss, 0, -1))) + if (!(u->sink_input = pa_sink_input_new(sink, PA_TYPEID_SOUND_FILE, fname, &ss, 0, -1))) goto fail; u->sink_input->volume = volume; diff --git a/polyp/source-output.c b/polyp/source-output.c index 3568fd6f2..f954c23fa 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -33,7 +33,7 @@ #include "subscribe.h" #include "log.h" -struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec, int resample_method) { +struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int resample_method) { struct pa_source_output *o; struct pa_resampler *resampler = NULL; int r; @@ -56,6 +56,8 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n o->ref = 1; o->state = PA_SOURCE_OUTPUT_RUNNING; o->name = pa_xstrdup(name); + o->typeid = typeid; + o->client = NULL; o->owner = NULL; o->source = s; diff --git a/polyp/source-output.h b/polyp/source-output.h index 0247a09a2..f3187aa99 100644 --- a/polyp/source-output.h +++ b/polyp/source-output.h @@ -42,6 +42,7 @@ struct pa_source_output { enum pa_source_output_state state; uint32_t index; + pa_typeid_t typeid; char *name; struct pa_module *owner; @@ -58,7 +59,7 @@ struct pa_source_output { void *userdata; }; -struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec, int resample_method); +struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int resample_method); void pa_source_output_unref(struct pa_source_output* o); struct pa_source_output* pa_source_output_ref(struct pa_source_output *o); diff --git a/polyp/source.c b/polyp/source.c index 7cdb9117f..fc73272c0 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -35,7 +35,7 @@ #include "subscribe.h" #include "log.h" -struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) { +struct pa_source* pa_source_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec) { struct pa_source *s; char st[256]; int r; @@ -53,6 +53,7 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail s->name = pa_xstrdup(name); s->description = NULL; + s->typeid = typeid; s->owner = NULL; s->core = core; diff --git a/polyp/source.h b/polyp/source.h index 1e6310b08..0fac2b343 100644 --- a/polyp/source.h +++ b/polyp/source.h @@ -31,6 +31,7 @@ struct pa_source; #include "memblock.h" #include "memchunk.h" #include "sink.h" +#include "typeid.h" #define PA_MAX_OUTPUTS_PER_SOURCE 16 @@ -44,6 +45,7 @@ struct pa_source { enum pa_source_state state; uint32_t index; + pa_typeid_t typeid; char *name, *description; struct pa_module *owner; @@ -57,7 +59,7 @@ struct pa_source { void *userdata; }; -struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec); +struct pa_source* pa_source_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec); void pa_source_disconnect(struct pa_source *s); void pa_source_unref(struct pa_source *s); struct pa_source* pa_source_ref(struct pa_source *c); diff --git a/polyp/typeid.c b/polyp/typeid.c new file mode 100644 index 000000000..70d3df336 --- /dev/null +++ b/polyp/typeid.c @@ -0,0 +1,33 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "typeid.h" + +char *pa_typeid_to_string(pa_typeid_t id, char *ret_s, size_t length) { + if (id == PA_TYPEID_UNKNOWN) + snprintf(ret_s, length, "????"); + else + snprintf(ret_s, length, "%c%c%c%c", (char) (id >> 24), (char) (id >> 16), (char) (id >> 8), (char) (id)); + + return ret_s; +} diff --git a/polyp/typeid.h b/polyp/typeid.h new file mode 100644 index 000000000..bd10b2e4b --- /dev/null +++ b/polyp/typeid.h @@ -0,0 +1,40 @@ +#ifndef footypeidhfoo +#define footypeidhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +typedef uint32_t pa_typeid_t; + +#define PA_TYPEID_UNKNOWN ((pa_typeid_t) -1) + +char *pa_typeid_to_string(pa_typeid_t id, char *ret_s, size_t length); + +#define PA_TYPEID_MAKE(a,b,c,d) (\ + (((pa_typeid_t) a & 0xFF) << 24) | \ + (((pa_typeid_t) b & 0xFF) << 16) | \ + (((pa_typeid_t) c & 0xFF) << 8) | \ + (((pa_typeid_t) d & 0xFF))) + +#endif From fa48de8a12730029fbc38f8ce7d61563ea5f6dcb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Dec 2004 13:17:28 +0000 Subject: [PATCH 0314/1514] * prepare polyplib-browse for installation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@321 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- configure.ac | 2 +- polyp/Makefile.am | 5 ++++- polyplib-browse.pc.in | 11 +++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 polyplib-browse.pc.in diff --git a/Makefile.am b/Makefile.am index 91f9740b3..43e4b58a1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ MAINTAINERCLEANFILES=README noinst_DATA = README pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc +pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-browse.pc if HAVE_GLIB20 pkgconfig_DATA += \ diff --git a/configure.ac b/configure.ac index 658910c63..6917921be 100644 --- a/configure.ac +++ b/configure.ac @@ -185,5 +185,5 @@ AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) -AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h doc/FAQ.html]) +AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-browse.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h doc/FAQ.html]) AC_OUTPUT diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 700516717..79accfe62 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -74,7 +74,8 @@ polypinclude_HEADERS= \ mainloop.h \ mainloop-signal.h \ sample.h \ - glib-mainloop.h + glib-mainloop.h \ + typeid.h ### Warning! Due to an obscure bug in libtool/automake it is required ### that the libraries in modlib_LTLIBRARIES are specified in-order, @@ -632,6 +633,8 @@ pabrowse_SOURCES = pabrowse.c pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la pabrowse_CFLAGS = $(AM_CFLAGS) +polypinclude_HEADERS+=polyplib-browser.h + endif ### GLIB 2.0 support diff --git a/polyplib-browse.pc.in b/polyplib-browse.pc.in new file mode 100644 index 000000000..b77967e00 --- /dev/null +++ b/polyplib-browse.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: polyplib-browse +Description: Polypaudio network browsing API +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lpolyp-browse-@PA_MAJORMINOR@ +Cflags: -D_REENTRANT -I${includedir} +Requires: polyplib-mainloop From a370e6e7635d4a0b50c5c884974764c890959a48 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Dec 2004 14:09:00 +0000 Subject: [PATCH 0315/1514] * fix daemonizing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@322 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/polyp/main.c b/polyp/main.c index f49232d4e..43a48f6b3 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef HAVE_LIBWRAP #include @@ -286,6 +287,11 @@ int main(int argc, char *argv[]) { close(0); close(1); + close(2); + + open("/dev/null", O_RDONLY); + open("/dev/null", O_WRONLY); + open("/dev/null", O_WRONLY); } chdir("/"); From bc5b917f93f39215b54593cc45228e97e14daec3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Dec 2004 14:20:52 +0000 Subject: [PATCH 0316/1514] do mor daemonizing work git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@323 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/main.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/polyp/main.c b/polyp/main.c index 43a48f6b3..f033c38e4 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef HAVE_LIBWRAP #include @@ -241,6 +242,7 @@ int main(int argc, char *argv[]) { if (conf->daemonize) { pid_t child; + int tty_fd; if (pa_stdio_acquire() < 0) { pa_log(__FILE__": failed to acquire stdio.\n"); @@ -292,6 +294,15 @@ int main(int argc, char *argv[]) { open("/dev/null", O_RDONLY); open("/dev/null", O_WRONLY); open("/dev/null", O_WRONLY); + + signal(SIGTTOU, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + signal(SIGTSTP, SIG_IGN); + + if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) { + ioctl(tty_fd, TIOCNOTTY, (char*) 0); + close(tty_fd); + } } chdir("/"); From 99e0779b51ccf4482dd35e78fe2f80744633004e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 15 Dec 2004 01:02:50 +0000 Subject: [PATCH 0317/1514] * Publish server info in mDNS in addition to sinks/sources * Split off address parser * Add port= argument to module-zeroconf-publish git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@324 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 10 ++- polyp/module-zeroconf-publish.c | 61 +++++++++++++++-- polyp/parseaddr.c | 112 ++++++++++++++++++++++++++++++++ polyp/parseaddr.h | 42 ++++++++++++ polyp/polyplib-browser.c | 1 - polyp/socket-client.c | 108 +++++++----------------------- polyp/util.c | 2 +- 7 files changed, 242 insertions(+), 94 deletions(-) create mode 100644 polyp/parseaddr.c create mode 100644 polyp/parseaddr.h diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 79accfe62..0c491ce58 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -87,6 +87,7 @@ modlib_LTLIBRARIES= \ libiochannel.la \ libsocket-server.la \ libsocket-client.la \ + libparseaddr.la \ libpacket.la \ libpstream.la \ liboss-util.la \ @@ -228,7 +229,8 @@ polypaudio_SOURCES = idxset.c idxset.h \ polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) polypaudio_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL) polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) -polypaudio_LDFLAGS= $(AM_LDFLAGS) -export-dynamic -dlopen force #-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f)) +polypaudio_LDFLAGS= $(AM_LDFLAGS) -export-dynamic -dlopen force +#q-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f)) libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version @@ -240,7 +242,10 @@ libsocket_server_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la $(LI libsocket_client_la_SOURCES = socket-client.c socket-client.h libsocket_client_la_LDFLAGS = -avoid-version -libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la +libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la libparseaddr.la + +libparseaddr_la_SOURCES = parseaddr.c parseaddr.h +libparseaddr_la_LDFLAGS = -avoid-version libpstream_la_SOURCES = pstream.c pstream.h libpstream_la_LDFLAGS = -avoid-version @@ -434,6 +439,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ util.c util.h \ memblock.c memblock.h \ socket-client.c socket-client.h \ + parseaddr.c parseaddr.h \ packet.c packet.h \ queue.c queue.h \ dynarray.c dynarray.h \ diff --git a/polyp/module-zeroconf-publish.c b/polyp/module-zeroconf-publish.c index c88ac766f..511ceb475 100644 --- a/polyp/module-zeroconf-publish.c +++ b/polyp/module-zeroconf-publish.c @@ -41,15 +41,22 @@ #include "subscribe.h" #include "dynarray.h" #include "endianmacros.h" +#include "modargs.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher") PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("port=") #define SERVICE_NAME_SINK "_polypaudio-sink._tcp" #define SERVICE_NAME_SOURCE "_polypaudio-source._tcp" #define SERVICE_NAME_SERVER "_polypaudio-server._tcp" +static const char* const valid_modargs[] = { + "port", + NULL +}; + struct service { sw_discovery_oid oid; char *name; @@ -74,6 +81,9 @@ struct userdata { struct pa_hashmap *services; struct pa_dynarray *sink_dynarray, *source_dynarray, *autoload_dynarray; struct pa_subscription *subscription; + + uint16_t port; + sw_discovery_oid server_oid; }; static sw_result publish_reply(sw_discovery discovery, sw_discovery_publish_status status, sw_discovery_oid oid, sw_opaque extra) { @@ -127,7 +137,7 @@ static int publish_service(struct userdata *u, struct service *s) { s->published = 0; } - snprintf(t, sizeof(t), "%s@%s", s->name, pa_get_host_name(hn, sizeof(hn))); + snprintf(t, sizeof(t), "Networked Audio device %s on %s", s->name, pa_get_host_name(hn, sizeof(hn))); if (sw_text_record_init(&txt) != SW_OKAY) { pa_log(__FILE__": sw_text_record_init() failed\n"); @@ -160,7 +170,7 @@ static int publish_service(struct userdata *u, struct service *s) { if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t, s->loaded.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE, - NULL, NULL, PA_NATIVE_DEFAULT_PORT, sw_text_record_bytes(txt), sw_text_record_len(txt), + NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt), publish_reply, s, &s->oid) != SW_OKAY) { pa_log(__FILE__": failed to register sink on zeroconf.\n"); goto finish; @@ -171,7 +181,7 @@ static int publish_service(struct userdata *u, struct service *s) { if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t, s->autoload.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE, - NULL, NULL, PA_NATIVE_DEFAULT_PORT, sw_text_record_bytes(txt), sw_text_record_len(txt), + NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt), publish_reply, s, &s->oid) != SW_OKAY) { pa_log(__FILE__": failed to register sink on zeroconf.\n"); goto finish; @@ -375,13 +385,28 @@ fail: int pa__init(struct pa_core *c, struct pa_module*m) { struct userdata *u; - uint32_t index; + uint32_t index, port = PA_NATIVE_DEFAULT_PORT; struct pa_sink *sink; struct pa_source *source; struct pa_autoload_entry *autoload; + struct pa_modargs *ma = NULL; + char t[256], hn[256]; + int free_txt = 0; + sw_text_record txt; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments.\n"); + goto fail; + } + + if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port == 0 || port >= 0xFFFF) { + pa_log(__FILE__": invalid port specified.\n"); + goto fail; + } m->userdata = u = pa_xmalloc(sizeof(struct userdata)); u->core = c; + u->port = (uint16_t) port; if (!(u->howl_wrapper = pa_howl_wrapper_get(c))) goto fail; @@ -409,10 +434,38 @@ int pa__init(struct pa_core *c, struct pa_module*m) { if (publish_autoload(u, autoload) < 0) goto fail; + snprintf(t, sizeof(t), "Networked Audio on %s", pa_get_host_name(hn, sizeof(hn))); + + if (sw_text_record_init(&txt) != SW_OKAY) { + pa_log(__FILE__": sw_text_record_init() failed\n"); + goto fail; + } + free_txt = 1; + + txt_record_server_data(u->core, txt); + + if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t, + SERVICE_NAME_SERVER, + NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt), + publish_reply, u, &u->server_oid) != SW_OKAY) { + pa_log(__FILE__": failed to register server on zeroconf.\n"); + goto fail; + } + + sw_text_record_fina(txt); + pa_modargs_free(ma); + return 0; fail: pa__done(c, m); + + if (ma) + pa_modargs_free(ma); + + if (free_txt) + sw_text_record_fina(txt); + return -1; } diff --git a/polyp/parseaddr.c b/polyp/parseaddr.c new file mode 100644 index 000000000..05ed508b6 --- /dev/null +++ b/polyp/parseaddr.c @@ -0,0 +1,112 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "xmalloc.h" +#include "util.h" +#include "parseaddr.h" + +/* Parse addresses in one of the following forms: + * HOSTNAME + * HOSTNAME:PORT + * [HOSTNAME] + * [HOSTNAME]:PORT + * + * Return a newly allocated string of the hostname and fill in *ret_port if specified */ + +static char *parse_host(const char *s, uint16_t *ret_port) { + assert(s && ret_port); + if (*s == '[') { + char *e; + if (!(e = strchr(s+1, ']'))) + return NULL; + + if (e[1] == ':') + *ret_port = atoi(e+2); + else if (e[1] != 0) + return NULL; + + return pa_xstrndup(s+1, e-s-1); + } else { + char *e; + + if (!(e = strrchr(s, ':'))) + return pa_xstrdup(s); + + *ret_port = atoi(e+1); + return pa_xstrndup(s, e-s); + } +} + +int pa_parse_address(const char *name, struct pa_parsed_address *ret_p) { + const char *p; + assert(name && ret_p); + memset(ret_p, 0, sizeof(struct pa_parsed_address)); + ret_p->type = PA_PARSED_ADDRESS_TCP_AUTO; + + if (*name == '{') { + char hn[256], *pfx; + /* The URL starts with a host specification for detecting local connections */ + + if (!pa_get_host_name(hn, sizeof(hn))) + return -1; + + pfx = pa_sprintf_malloc("{%s}", hn); + if (!pa_startswith(name, pfx)) { + pa_xfree(pfx); + /* Not local */ + return -1; + } + + p = name + strlen(pfx); + pa_xfree(pfx); + } else + p = name; + + if (*p == '/') + ret_p->type = PA_PARSED_ADDRESS_UNIX; + else if (pa_startswith(p, "unix:")) { + ret_p->type = PA_PARSED_ADDRESS_UNIX; + p += sizeof("unix:")-1; + } else if (pa_startswith(p, "tcp:") || pa_startswith(p, "tcp4:")) { + ret_p->type = PA_PARSED_ADDRESS_TCP4; + p += sizeof("tcp:")-1; + } else if (pa_startswith(p, "tcp6:")) { + ret_p->type = PA_PARSED_ADDRESS_TCP6; + p += sizeof("tcp6:")-1; + } + + if (ret_p->type == PA_PARSED_ADDRESS_UNIX) + ret_p->path_or_host = pa_xstrdup(p); + else + if (!(ret_p->path_or_host = parse_host(p, &ret_p->port))) + return -1; + + + return 0; +} diff --git a/polyp/parseaddr.h b/polyp/parseaddr.h new file mode 100644 index 000000000..5ddc0351e --- /dev/null +++ b/polyp/parseaddr.h @@ -0,0 +1,42 @@ +#ifndef fooparseaddrhfoo +#define fooparseaddrhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +enum pa_parsed_address_type { + PA_PARSED_ADDRESS_UNIX, + PA_PARSED_ADDRESS_TCP4, + PA_PARSED_ADDRESS_TCP6, + PA_PARSED_ADDRESS_TCP_AUTO +}; + +struct pa_parsed_address { + enum pa_parsed_address_type type; + char *path_or_host; + uint16_t port; +}; + +int pa_parse_address(const char *a, struct pa_parsed_address *ret_p); + +#endif diff --git a/polyp/polyplib-browser.c b/polyp/polyplib-browser.c index a1bd3fb74..7e56e2ceb 100644 --- a/polyp/polyplib-browser.c +++ b/polyp/polyplib-browser.c @@ -221,7 +221,6 @@ static sw_result browse_reply( switch (status) { case SW_DISCOVERY_BROWSE_ADD_SERVICE: { sw_discovery_oid oid; - fprintf(stderr, "debug: new service: %s\n", name); if (sw_discovery_resolve(b->discovery, 0, name, type, domain, resolve_reply, b, &oid) != SW_OKAY) pa_log("sw_discovery_resolve() failed\n"); diff --git a/polyp/socket-client.c b/polyp/socket-client.c index c58c7bd45..0581e5534 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -39,6 +39,7 @@ #include "util.h" #include "xmalloc.h" #include "log.h" +#include "parseaddr.h" struct pa_socket_client { int ref; @@ -254,121 +255,56 @@ struct pa_socket_client* pa_socket_client_new_ipv6(struct pa_mainloop_api *m, ui return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa)); } -/* Parse addresses in one of the following forms: - * HOSTNAME - * HOSTNAME:PORT - * [HOSTNAME] - * [HOSTNAME]:PORT - * - * Return a newly allocated string of the hostname and fill in *port if specified */ - -static char *parse_address(const char *s, uint16_t *port) { - assert(s && port); - if (*s == '[') { - char *e; - if (!(e = strchr(s+1, ']'))) - return NULL; - - if (e[1] == ':') - *port = atoi(e+2); - else if (e[1] != 0) - return NULL; - - return pa_xstrndup(s+1, e-s-1); - } else { - char *e; - - if (!(e = strrchr(s, ':'))) - return pa_xstrdup(s); - - *port = atoi(e+1); - return pa_xstrndup(s, e-s); - } -} - struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, const char*name, uint16_t default_port) { - const char *p; struct pa_socket_client *c = NULL; - enum { KIND_UNIX, KIND_TCP_AUTO, KIND_TCP4, KIND_TCP6 } kind = KIND_TCP_AUTO; + struct pa_parsed_address a; assert(m && name); - if (*name == '{') { - char hn[256], *pfx; - /* The URL starts with a host specification for detecting local connections */ - - if (!pa_get_host_name(hn, sizeof(hn))) - return NULL; - - pfx = pa_sprintf_malloc("{%s}", hn); - if (!pa_startswith(name, pfx)) - /* Not local */ - return NULL; - - p = name + strlen(pfx); - } else - p = name; - - if (*p == '/') - kind = KIND_UNIX; - else if (pa_startswith(p, "unix:")) { - kind = KIND_UNIX; - p += sizeof("unix:")-1; - } else if (pa_startswith(p, "tcp:") || pa_startswith(p, "tcp4:")) { - kind = KIND_TCP4; - p += sizeof("tcp:")-1; - } else if (pa_startswith(p, "tcp6:")) { - kind = KIND_TCP6; - p += sizeof("tcp6:")-1; - } + if (pa_parse_address(name, &a) < 0) + return NULL; - switch (kind) { - case KIND_UNIX: - return pa_socket_client_new_unix(m, p); + switch (a.type) { + case PA_PARSED_ADDRESS_UNIX: + c = pa_socket_client_new_unix(m, a.path_or_host); + break; - case KIND_TCP_AUTO: /* Fallthrough */ - case KIND_TCP4: - case KIND_TCP6: { - uint16_t port = default_port; - char *h; + case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */ + case PA_PARSED_ADDRESS_TCP6: /* Fallthrough */ + case PA_PARSED_ADDRESS_TCP_AUTO:{ int ret; struct addrinfo hints, *res; - if (!(h = parse_address(p, &port))) - return NULL; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = kind == KIND_TCP4 ? AF_INET : (kind == KIND_TCP6 ? AF_INET6 : AF_UNSPEC); + hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? AF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? AF_INET6 : AF_UNSPEC); - ret = getaddrinfo(h, NULL, &hints, &res); - pa_xfree(h); + ret = getaddrinfo(a.path_or_host, NULL, &hints, &res); if (ret < 0 || !res || !res->ai_addr) - return NULL; + goto finish; if (res->ai_family == AF_INET) { if (res->ai_addrlen != sizeof(struct sockaddr_in)) - return NULL; + goto finish; assert(res->ai_addr->sa_family == res->ai_family); - ((struct sockaddr_in*) res->ai_addr)->sin_port = htons(port); + ((struct sockaddr_in*) res->ai_addr)->sin_port = htons(a.port); } else if (res->ai_family == AF_INET6) { if (res->ai_addrlen != sizeof(struct sockaddr_in6)) - return NULL; + goto finish; assert(res->ai_addr->sa_family == res->ai_family); - ((struct sockaddr_in6*) res->ai_addr)->sin6_port = htons(port); + ((struct sockaddr_in6*) res->ai_addr)->sin6_port = htons(a.port); } else - return NULL; + goto finish; c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); - return c; } } - /* Should never be reached */ - assert(0); - return NULL; +finish: + pa_xfree(a.path_or_host); + return c; } diff --git a/polyp/util.c b/polyp/util.c index ff1aebf36..ee3fa87d6 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -880,7 +880,7 @@ int pa_atoi(const char *s, int32_t *ret_i) { l = strtol(s, &x, 0); - if (x || *x) + if (!x || *x) return -1; *ret_i = (int32_t) l; From 400dacd66fd6ee60c6394eb9334840b7cd10bc69 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 15 Dec 2004 01:04:13 +0000 Subject: [PATCH 0318/1514] cleanup zeroconf service names git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@325 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-zeroconf-publish.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polyp/module-zeroconf-publish.c b/polyp/module-zeroconf-publish.c index 511ceb475..56696aea6 100644 --- a/polyp/module-zeroconf-publish.c +++ b/polyp/module-zeroconf-publish.c @@ -137,7 +137,7 @@ static int publish_service(struct userdata *u, struct service *s) { s->published = 0; } - snprintf(t, sizeof(t), "Networked Audio device %s on %s", s->name, pa_get_host_name(hn, sizeof(hn))); + snprintf(t, sizeof(t), "Networked Audio Device %s on %s", s->name, pa_get_host_name(hn, sizeof(hn))); if (sw_text_record_init(&txt) != SW_OKAY) { pa_log(__FILE__": sw_text_record_init() failed\n"); @@ -434,7 +434,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { if (publish_autoload(u, autoload) < 0) goto fail; - snprintf(t, sizeof(t), "Networked Audio on %s", pa_get_host_name(hn, sizeof(hn))); + snprintf(t, sizeof(t), "Networked Audio Server on %s", pa_get_host_name(hn, sizeof(hn))); if (sw_text_record_init(&txt) != SW_OKAY) { pa_log(__FILE__": sw_text_record_init() failed\n"); From b1369d29079bee2c8d96ad698da9ec43f569c0e5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 15 Dec 2004 01:17:04 +0000 Subject: [PATCH 0319/1514] * fix error message when starting polypaudio while it is already running git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@326 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/polyp/main.c b/polyp/main.c index f033c38e4..c5b3a7e8e 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -271,7 +271,7 @@ int main(int argc, char *argv[]) { } if (retval) - pa_log(__FILE__": daemon startup failed .\n"); + pa_log(__FILE__": daemon startup failed.\n"); else pa_log_info(__FILE__": daemon startup successful.\n"); @@ -308,8 +308,10 @@ int main(int argc, char *argv[]) { chdir("/"); if (conf->use_pid_file) { - if (pa_pid_file_create() < 0) + if (pa_pid_file_create() < 0) { + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); goto finish; + } valid_pid_file = 1; } From 47ab6bd2fc21c22d98605a18e49a94857eb1e4b3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Dec 2004 20:08:50 +0000 Subject: [PATCH 0320/1514] gcc 2.95 compat git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@327 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-zeroconf-publish.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/module-zeroconf-publish.c b/polyp/module-zeroconf-publish.c index 56696aea6..a7e2073ec 100644 --- a/polyp/module-zeroconf-publish.c +++ b/polyp/module-zeroconf-publish.c @@ -121,12 +121,12 @@ static void txt_record_server_data(struct pa_core *c, sw_text_record t) { } static int publish_service(struct userdata *u, struct service *s) { - assert(u && s); char t[256]; char hn[256]; int r = -1; sw_text_record txt; int free_txt = 0; + assert(u && s); if ((s->published == 1 && s->loaded.valid) || (s->published == 2 && s->autoload.valid && !s->loaded.valid)) From 8199925cec93c9e7908f9afa9d18718623af13ee Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 18 Dec 2004 20:45:46 +0000 Subject: [PATCH 0321/1514] fix conditional X11 compilation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@328 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6917921be..dda1f4c6b 100644 --- a/configure.ac +++ b/configure.ac @@ -57,7 +57,9 @@ HAVE_X11=0 test "x$no_x" != "xyes" && HAVE_X11=1 AC_SUBST(HAVE_X11) AM_CONDITIONAL(HAVE_X11, test "x$no_x" != "xyes") -AC_DEFINE([HAVE_X11], [], [Have X11]) +if test "x$no_x" != "xyes" ; then + AC_DEFINE([HAVE_X11], 1, [Have X11]) +fi # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST From fb11e45cfd84290985e5a3c6f4c7a25fb1eab83c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Jan 2005 01:07:43 +0000 Subject: [PATCH 0322/1514] minor fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@329 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/client-conf-x11.c | 11 +++++------ polyp/pax11publish.c | 21 ++++++++++----------- polyp/polyplib-context.c | 18 +++++++++++++----- polyp/protocol-esound.c | 3 ++- polyp/socket-client.c | 3 +++ 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/polyp/client-conf-x11.c b/polyp/client-conf-x11.c index eb471033e..383aa64e7 100644 --- a/polyp/client-conf-x11.c +++ b/polyp/client-conf-x11.c @@ -15,7 +15,7 @@ You should have received a copy of the GNU Lesser General Public License along with polypaudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-13071 USA. ***/ @@ -48,11 +48,10 @@ int pa_client_conf_from_x11(struct pa_client_conf *c, const char *dname) { goto finish; } - if (!pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) - goto finish; - - pa_xfree(c->default_server); - c->default_server = pa_xstrdup(t); + if (pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) { + pa_xfree(c->default_server); + c->default_server = pa_xstrdup(t); + } if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) { pa_xfree(c->default_sink); diff --git a/polyp/pax11publish.c b/polyp/pax11publish.c index 206ab1cb0..a1cb006ab 100644 --- a/polyp/pax11publish.c +++ b/polyp/pax11publish.c @@ -96,10 +96,8 @@ int main(int argc, char *argv[]) { switch (mode) { case DUMP: { char t[1024]; - if (!pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) - goto finish; - - printf("Server: %s\n", t); + if (pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) + printf("Server: %s\n", t); if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) printf("Source: %s\n", t); if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) @@ -112,11 +110,8 @@ int main(int argc, char *argv[]) { case IMPORT: { char t[1024]; - if (!pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) - goto finish; - - printf("POLYP_SERVER='%s'\nexport POLYP_SERVER\n", t); - + if (pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) + printf("POLYP_SERVER='%s'\nexport POLYP_SERVER\n", t); if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) printf("POLYP_SOURCE='%s'\nexport POLYP_SOURCE\n", t); if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) @@ -155,10 +150,14 @@ int main(int argc, char *argv[]) { goto finish; } + pa_x11_del_prop(d, "POLYP_SERVER"); + pa_x11_del_prop(d, "POLYP_SINK"); + pa_x11_del_prop(d, "POLYP_SOURCE"); pa_x11_del_prop(d, "POLYP_ID"); - + pa_x11_del_prop(d, "POLYP_COOKIE"); + if (server) - pa_x11_set_prop(d, "POLYP_SERVER", c->default_server); + pa_x11_set_prop(d, "POLYP_SERVER", server); else if (c->default_server) pa_x11_set_prop(d, "POLYP_SERVER", c->default_server); else { diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 517fcbeb4..e7ccda3e8 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -512,7 +512,7 @@ static int try_next_connection(struct pa_context *c) { pa_xfree(c->server); c->server = pa_xstrdup(u); - + if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT))) continue; @@ -564,7 +564,6 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons if (!server) server = c->conf->default_server; - pa_context_ref(c); assert(!c->server_list); @@ -580,14 +579,23 @@ int pa_context_connect(struct pa_context *c, const char *server, int spawn, cons /* Prepend in reverse order */ - if ((d = getenv("DISPLAY"))) - c->server_list = pa_strlist_prepend(c->server_list, d); + if ((d = getenv("DISPLAY"))) { + char *e; + d = pa_xstrdup(d); + if ((e = strchr(d, ':'))) + *e = 0; + + if (*d) + c->server_list = pa_strlist_prepend(c->server_list, d); + + pa_xfree(d); + } c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost"); c->server_list = pa_strlist_prepend(c->server_list, "localhost"); c->server_list = pa_strlist_prepend(c->server_list, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET, ufn, sizeof(ufn))); - /* Wrap the connection attempts in a single transaction for sane autospwan locking */ + /* Wrap the connection attempts in a single transaction for sane autospawn locking */ if (spawn && c->conf->autospawn) { char lf[PATH_MAX]; diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index d9ed66b98..744ad4ed1 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -714,7 +714,8 @@ static int do_read(struct connection *c) { assert(c->read_data_length < sizeof(c->request)); if ((r = pa_iochannel_read(c->io, ((uint8_t*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { - pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + if (r != 0) + pa_log_warn(__FILE__": read() failed: %s\n", strerror(errno)); return -1; } diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 0581e5534..4ec42dabc 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -263,6 +263,9 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, if (pa_parse_address(name, &a) < 0) return NULL; + if (!a.port) + a.port = default_port; + switch (a.type) { case PA_PARSED_ADDRESS_UNIX: c = pa_socket_client_new_unix(m, a.path_or_host); From 9b0ec37fcf11805da9511704e976557f4a3a57d2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Jan 2005 01:15:11 +0000 Subject: [PATCH 0323/1514] * add support for asynchronous name resolution * remove directories listing from doxygen git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@330 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 10 +++ doxygen/doxygen.conf.in | 3 + polyp/Makefile.am | 8 +++ polyp/socket-client.c | 144 ++++++++++++++++++++++++++++++++-------- 4 files changed, 136 insertions(+), 29 deletions(-) diff --git a/configure.ac b/configure.ac index dda1f4c6b..e287f279b 100644 --- a/configure.ac +++ b/configure.ac @@ -133,6 +133,16 @@ AC_SUBST(HOWL_LIBS) AC_SUBST(HAVE_HOWL) AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1]) +PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, HAVE_LIBASYNCNS=0) +AC_SUBST(LIBASYNCNS_CFLAGS) +AC_SUBST(LIBASYNCNS_LIBS) +AC_SUBST(HAVE_LIBASYNCNS) +AM_CONDITIONAL([HAVE_LIBASYNCNS], [test "x$HAVE_LIBASYNCNS" = x1]) + +if test "x$HAVE_LIBASYNCNS" != "x0" ; then + AC_DEFINE([HAVE_LIBASYNCNS], 1, [Have libasyncns?]) +fi + AC_PATH_PROG([M4], [m4 gm4], [no]) if test "x$M4" = xno ; then AC_MSG_ERROR([m4 missing]) diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 51b2a1138..c0e122ea8 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -1151,3 +1151,6 @@ DOT_CLEANUP = YES # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO + +SHOW_DIRECTORIES=NO + diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 0c491ce58..352e6a7a7 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -470,6 +470,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 +libpolyp_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp_mainloop_@PA_MAJORMINOR@_la_SOURCES = mainloop-api.h mainloop-api.c \ mainloop.c mainloop.h \ @@ -581,6 +582,13 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES += x11prop.c x11prop.h client-conf-x11.c cli endif +### libasyncns stuff + +if HAVE_LIBASYNCNS +libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(LIBASYNCNS_CFLAGS) +libpolyp_@PA_MAJORMINOR@_la_LIBADD += $(LIBASYNCNS_LIBS) +endif + ### ALSA modules if HAVE_ALSA diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 4ec42dabc..8ac04a8b6 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -23,6 +23,8 @@ #include #endif +/* #undef HAVE_LIBASYNCNS */ + #include #include #include @@ -33,6 +35,9 @@ #include #include #include +#ifdef HAVE_LIBASYNCNS +#include +#endif #include "socket-client.h" #include "socket-util.h" @@ -50,6 +55,11 @@ struct pa_socket_client { void (*callback)(struct pa_socket_client*c, struct pa_iochannel *io, void *userdata); void *userdata; int local; +#ifdef HAVE_LIBASYNCNS + asyncns_t *asyncns; + asyncns_query_t * asyncns_query; + struct pa_io_event *asyncns_io_event; +#endif }; static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { @@ -65,6 +75,13 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { c->callback = NULL; c->userdata = NULL; c->local = 0; + +#ifdef HAVE_LIBASYNCNS + c->asyncns = NULL; + c->asyncns_io_event = NULL; + c->asyncns_query = NULL; +#endif + return c; } @@ -75,6 +92,9 @@ static void do_call(struct pa_socket_client *c) { assert(c && c->callback); pa_socket_client_ref(c); + + if (c->fd < 0) + goto finish; lerror = sizeof(error); if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &error, &lerror) < 0) { @@ -97,7 +117,7 @@ static void do_call(struct pa_socket_client *c) { assert(io); finish: - if (!io) + if (!io && c->fd >= 0) close(c->fd); c->fd = -1; @@ -169,12 +189,11 @@ struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, co return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa)); } -struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) { - struct pa_socket_client *c; - assert(m && sa); - c = pa_socket_client_new(m); +static int sockaddr_prepare(struct pa_socket_client *c, const struct sockaddr *sa, size_t salen) { assert(c); - + assert(sa); + assert(salen); + switch (sa->sa_family) { case AF_UNIX: c->local = 1; @@ -194,7 +213,7 @@ struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) { pa_log(__FILE__": socket(): %s\n", strerror(errno)); - goto fail; + return -1; } pa_fd_set_cloexec(c->fd, 1); @@ -204,6 +223,18 @@ struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m pa_socket_low_delay(c->fd); if (do_connect(c, sa, salen) < 0) + return -1; + + return 0; +} + +struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) { + struct pa_socket_client *c; + assert(m && sa); + c = pa_socket_client_new(m); + assert(c); + + if (sockaddr_prepare(c, sa, salen) < 0) goto fail; return c; @@ -222,6 +253,16 @@ void socket_client_free(struct pa_socket_client *c) { c->mainloop->defer_free(c->defer_event); if (c->fd >= 0) close(c->fd); + +#ifdef HAVE_LIBASYNCNS + if (c->asyncns_query) + asyncns_cancel(c->asyncns, c->asyncns_query); + if (c->asyncns) + asyncns_free(c->asyncns); + if (c->asyncns_io_event) + c->mainloop->io_free(c->asyncns_io_event); +#endif + pa_xfree(c); } @@ -255,6 +296,40 @@ struct pa_socket_client* pa_socket_client_new_ipv6(struct pa_mainloop_api *m, ui return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa)); } +#ifdef HAVE_LIBASYNCNS + +static void asyncns_cb(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { + struct pa_socket_client *c = userdata; + struct addrinfo *res = NULL; + int ret; + assert(m && c && c->asyncns_io_event == e && fd >= 0); + + if (asyncns_wait(c->asyncns, 0) < 0) + goto finish; + + if (!asyncns_isdone(c->asyncns, c->asyncns_query)) + return; + + ret = asyncns_getaddrinfo_done(c->asyncns, c->asyncns_query, &res); + c->asyncns_query = NULL; + + if (ret != 0 || !res) + goto finish; + + if (res->ai_addr) + sockaddr_prepare(c, res->ai_addr, res->ai_addrlen); + + asyncns_freeaddrinfo(res); + +finish: + + m->io_free(c->asyncns_io_event); + c->asyncns_io_event = NULL; + do_call(c); +} + +#endif + struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, const char*name, uint16_t default_port) { struct pa_socket_client *c = NULL; struct pa_parsed_address a; @@ -274,34 +349,45 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */ case PA_PARSED_ADDRESS_TCP6: /* Fallthrough */ case PA_PARSED_ADDRESS_TCP_AUTO:{ - int ret; - struct addrinfo hints, *res; + + struct addrinfo hints; + char port[12]; + + snprintf(port, sizeof(port), "%u", (unsigned) a.port); memset(&hints, 0, sizeof(hints)); - hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? AF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? AF_INET6 : AF_UNSPEC); + hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? PF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? PF_INET6 : PF_UNSPEC); + hints.ai_socktype = SOCK_STREAM; - ret = getaddrinfo(a.path_or_host, NULL, &hints, &res); - - if (ret < 0 || !res || !res->ai_addr) - goto finish; - - if (res->ai_family == AF_INET) { - if (res->ai_addrlen != sizeof(struct sockaddr_in)) - goto finish; - assert(res->ai_addr->sa_family == res->ai_family); +#ifdef HAVE_LIBASYNCNS + { + asyncns_t *asyncns; - ((struct sockaddr_in*) res->ai_addr)->sin_port = htons(a.port); - } else if (res->ai_family == AF_INET6) { - if (res->ai_addrlen != sizeof(struct sockaddr_in6)) + if (!(asyncns = asyncns_new(1))) goto finish; - assert(res->ai_addr->sa_family == res->ai_family); - - ((struct sockaddr_in6*) res->ai_addr)->sin6_port = htons(a.port); - } else - goto finish; - c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); + c = pa_socket_client_new(m); + c->asyncns = asyncns; + c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c); + c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints); + assert(c->asyncns_query); + } +#else + { + int ret; + struct addrinfo *res = NULL; + + ret = getaddrinfo(a.path_or_host, port, &hints, &res); + + if (ret < 0 || !res) + goto finish; + + if (res->ai_addr) + c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen); + + freeaddrinfo(res); + } +#endif } } From 9a59d016ddcf17ab6ce450b1e142fe357213413a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Jan 2005 01:16:41 +0000 Subject: [PATCH 0324/1514] update todo list git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@331 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/todo b/doc/todo index efaeb3322..16383ea9d 100644 --- a/doc/todo +++ b/doc/todo @@ -11,7 +11,7 @@ Fixes: - improve module-oss-mmap latency measurement - module-tunnel: improve latency calculation - make alsa modules use mmap -- event more commenting +- even more commenting Features: - add radio module @@ -20,6 +20,8 @@ Features: - rendezvous - polish for starting polypaudio as root/system-wide instance - export connection fd +- lirc plugin +- /dev/input/event plugin Long term: - pass meta info for hearing impaired From 1e78a1dd02e5b2f9c1b439fdc3c51753adbcb36c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Jan 2005 01:19:34 +0000 Subject: [PATCH 0325/1514] change doxygen build stuff for better compat with moderm automakes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@332 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- doxygen/Makefile.am | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index 43e4b58a1..7935321da 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,6 +53,6 @@ distcleancheck: @: doxygen: - $(MAKE) -C doxygen + $(MAKE) -C doxygen doxygen .PHONY: homepage distcleancheck doxygen diff --git a/doxygen/Makefile.am b/doxygen/Makefile.am index 9ea724d00..79354b217 100644 --- a/doxygen/Makefile.am +++ b/doxygen/Makefile.am @@ -17,12 +17,10 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -noinst_DATA=html - -html: doxygen.conf +doxygen: doxygen.conf doxygen $< clean-local: rm -rf html -.PHONY: all html +.PHONY: all doxygen From fb4cba436c691ebadb24068977643674fb8c143e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Jan 2005 21:36:53 +0000 Subject: [PATCH 0326/1514] * add new module for LIRC volume control git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@333 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 7 ++ polyp/Makefile.am | 20 +++- polyp/module-lirc.c | 221 +++++++++++++++++++++++++++++++++++++++++++ polyp/module-match.c | 6 +- polyp/module-oss.c | 1 - 5 files changed, 248 insertions(+), 7 deletions(-) create mode 100644 polyp/module-lirc.c diff --git a/configure.ac b/configure.ac index e287f279b..644c40503 100644 --- a/configure.ac +++ b/configure.ac @@ -167,6 +167,13 @@ AC_MSG_RESULT(yes)], AC_SUBST(LIBWRAP_LIBS) LIBS="$saved_LIBS" +HAVE_LIRC=1 +AC_CHECK_HEADER(lirc/lirc_client.h,[AC_CHECK_LIB(lirc_client,lirc_init,,HAVE_LIRC=0)],HAVE_LIRC=0) +LIRC_LIBS=-llirc_client +AC_SUBST(LIRC_CFLAGS) +AC_SUBST(LIRC_LIBS) +AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) + # If using GCC specify some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -W -Wall -pedantic" diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 352e6a7a7..95a80ec1e 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -159,7 +159,8 @@ SYMDEF_FILES= \ module-tunnel-source-symdef.h \ module-null-sink-symdef.h \ module-esound-sink-symdef.h \ - module-zeroconf-publish-symdef.h + module-zeroconf-publish-symdef.h \ + module-lirc-symdef.h EXTRA_DIST+=$(SYMDEF_FILES) BUILT_SOURCES+=$(SYMDEF_FILES) @@ -242,7 +243,8 @@ libsocket_server_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la $(LI libsocket_client_la_SOURCES = socket-client.c socket-client.h libsocket_client_la_LDFLAGS = -avoid-version -libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la libparseaddr.la +libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS) +libsocket_client_la_CFLAGS = $(AM_CFLAGS) $(LIBASYNCNS_CFLAGS) libparseaddr_la_SOURCES = parseaddr.c parseaddr.h libparseaddr_la_LDFLAGS = -avoid-version @@ -691,6 +693,20 @@ mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-main endif +### LIRC support + +if HAVE_LIRC + +modlib_LTLIBRARIES+= \ + module-lirc.la + +module_lirc_la_SOURCES = module-lirc.c +module_lirc_la_LDFLAGS = -module -avoid-version +module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) +module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS) + +endif + ### libpolypcore (needs to be updated) if BUILD_LIBPOLYPCORE diff --git a/polyp/module-lirc.c b/polyp/module-lirc.c new file mode 100644 index 000000000..a68b5b995 --- /dev/null +++ b/polyp/module-lirc.c @@ -0,0 +1,221 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "module.h" +#include "iochannel.h" +#include "log.h" +#include "module-lirc-symdef.h" +#include "namereg.h" +#include "sink.h" +#include "xmalloc.h" +#include "modargs.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("LIRC volume control") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("config= sink=") + +static const char* const valid_modargs[] = { + "config", + "sink", + NULL, +}; + +struct userdata { + int lirc_fd; + struct pa_io_event *io; + struct lirc_config *config; + char *sink_name; + struct pa_module *module; + float mute_toggle_save; +}; + +static int lirc_in_use = 0; + +static void io_callback(struct pa_mainloop_api *io, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void*userdata) { + struct userdata *u = userdata; + char *name = NULL, *code = NULL; + assert(io); + assert(u); + + if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { + pa_log(__FILE__": lost connection to LIRC daemon.\n"); + goto fail; + } + + if (events & PA_IO_EVENT_INPUT) { + char *c; + + if (lirc_nextcode(&code) != 0 || !code) { + pa_log(__FILE__": lirc_nextcode() failed.\n"); + goto fail; + } + + c = pa_xstrdup(code); + c[strcspn(c, "\n\r")] = 0; + pa_log_debug(__FILE__": raw IR code '%s'\n", c); + pa_xfree(c); + + while (lirc_code2char(u->config, code, &name) == 0 && name) { + enum { INVALID, UP, DOWN, MUTE, RESET, MUTE_TOGGLE } volchange = INVALID; + + pa_log_info(__FILE__": translated IR code '%s'\n", name); + + if (strcasecmp(name, "volume-up") == 0) + volchange = UP; + else if (strcasecmp(name, "volume-down") == 0) + volchange = DOWN; + else if (strcasecmp(name, "mute") == 0) + volchange = MUTE; + else if (strcasecmp(name, "mute-toggle") == 0) + volchange = MUTE_TOGGLE; + else if (strcasecmp(name, "reset") == 0) + volchange = RESET; + + if (volchange == INVALID) + pa_log_warn(__FILE__": recieved unknown IR code '%s'\n", name); + else { + struct pa_sink *s; + + if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) + pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name); + else { + double v = pa_volume_to_user(s->volume); + + switch (volchange) { + case UP: v += .05; break; + case DOWN: v -= .05; break; + case MUTE: v = 0; break; + case RESET: v = 1; break; + case MUTE_TOGGLE: { + + if (v > 0) { + u->mute_toggle_save = v; + v = 0; + } else + v = u->mute_toggle_save; + } + default: + ; + } + + pa_sink_set_volume(s, pa_volume_from_user(v)); + } + } + } + } + + free(code); + + return; + +fail: + u->module->core->mainloop->io_free(u->io); + u->io = NULL; + + pa_module_unload_request(u->module); + + free(code); +} + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct pa_modargs *ma = NULL; + struct userdata *u; + assert(c && m); + + if (lirc_in_use) { + pa_log(__FILE__": module-lirc may no be loaded twice.\n"); + return -1; + } + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": Failed to parse module arguments\n"); + goto fail; + } + + m->userdata = u = pa_xmalloc(sizeof(struct userdata)); + u->module = m; + u->io = NULL; + u->config = NULL; + u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + u->lirc_fd = -1; + u->mute_toggle_save = 0; + + if ((u->lirc_fd = lirc_init("polypaudio", 1)) < 0) { + pa_log(__FILE__": lirc_init() failed.\n"); + goto fail; + } + + if (lirc_readconfig((char*) pa_modargs_get_value(ma, "config", NULL), &u->config, NULL) < 0) { + pa_log(__FILE__": lirc_readconfig() failed.\n"); + goto fail; + } + + u->io = c->mainloop->io_new(c->mainloop, u->lirc_fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); + + lirc_in_use = 1; + + pa_modargs_free(ma); + + return 0; + +fail: + + if (ma) + pa_modargs_free(ma); + + pa__done(c, m); + return -1; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + assert(c); + assert(m); + + if (!(u = m->userdata)) + return; + + if (u->io) + m->core->mainloop->io_free(u->io); + + if (u->config) + lirc_freeconfig(u->config); + + if (u->lirc_fd >= 0) + lirc_deinit(); + + pa_xfree(u->sink_name); + pa_xfree(u); + + lirc_in_use = 0; +} diff --git a/polyp/module-match.c b/polyp/module-match.c index 9d969b31b..3599a830b 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -179,12 +179,10 @@ static void callback(struct pa_core *c, enum pa_subscription_event_type t, uint3 int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; - const char *table_file; struct userdata *u; assert(c && m); - if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || - !(table_file = pa_modargs_get_value(ma, "table", NULL))) { + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": Failed to parse module arguments\n"); goto fail; } @@ -194,7 +192,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->subscription = NULL; m->userdata = u; - if (load_rules(u, table_file) < 0) + if (load_rules(u, pa_modargs_get_value(ma, "table", NULL)) < 0) goto fail; u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 67922d826..02acc6f46 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -295,7 +295,6 @@ int pa__init(struct pa_core *c, struct pa_module*m) { pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); - if (nfrags >= 2 && frag_size >= 1) if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) goto fail; From c29c95d0aac40c6720fb27d77c60051e420a9d87 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Jan 2005 21:40:25 +0000 Subject: [PATCH 0327/1514] * make lirc program name configurable git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@334 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-lirc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/polyp/module-lirc.c b/polyp/module-lirc.c index a68b5b995..485f570c1 100644 --- a/polyp/module-lirc.c +++ b/polyp/module-lirc.c @@ -42,11 +42,12 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("LIRC volume control") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("config= sink=") +PA_MODULE_USAGE("config= sink= appname=") static const char* const valid_modargs[] = { "config", "sink", + "appname", NULL, }; @@ -170,7 +171,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->lirc_fd = -1; u->mute_toggle_save = 0; - if ((u->lirc_fd = lirc_init("polypaudio", 1)) < 0) { + if ((u->lirc_fd = lirc_init(pa_modargs_get_value(ma, "appname", "polypaudio"), 1)) < 0) { pa_log(__FILE__": lirc_init() failed.\n"); goto fail; } From 6911d7e981c9314ea62ec5fe5adf6bec1d4f7f4f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Jan 2005 21:43:30 +0000 Subject: [PATCH 0328/1514] * increase timeout in pacmd git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@335 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/pacmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polyp/pacmd.c b/polyp/pacmd.c index 741059ce3..d69c14d7f 100644 --- a/polyp/pacmd.c +++ b/polyp/pacmd.c @@ -75,11 +75,11 @@ int main() { goto fail; } - pa_msleep(10); + pa_msleep(50); } if (i >= 5) { - pa_log(__FILE__": daemon to responding.\n"); + pa_log(__FILE__": daemon not responding.\n"); goto fail; } From 474b5683e957471d060ee030e5c19a6f6d73a1a2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Jan 2005 22:32:53 +0000 Subject: [PATCH 0329/1514] * todo update * lirc warning fix * c++ compat git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@336 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 5 ++--- polyp/module-lirc.c | 2 +- polyp/pactl.c | 10 +++++----- polyp/polyplib-introspect.c | 10 +++++----- polyp/polyplib-introspect.h | 10 +++++----- polyp/typeid.h | 6 ++++++ 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/doc/todo b/doc/todo index 16383ea9d..3292342a9 100644 --- a/doc/todo +++ b/doc/todo @@ -16,11 +16,10 @@ Fixes: Features: - add radio module - xmlrpc/http -- dbus -- rendezvous +- dbus/hal +- rendezvous autotunnel module - polish for starting polypaudio as root/system-wide instance - export connection fd -- lirc plugin - /dev/input/event plugin Long term: diff --git a/polyp/module-lirc.c b/polyp/module-lirc.c index 485f570c1..b400be12e 100644 --- a/polyp/module-lirc.c +++ b/polyp/module-lirc.c @@ -171,7 +171,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { u->lirc_fd = -1; u->mute_toggle_save = 0; - if ((u->lirc_fd = lirc_init(pa_modargs_get_value(ma, "appname", "polypaudio"), 1)) < 0) { + if ((u->lirc_fd = lirc_init((char*) pa_modargs_get_value(ma, "appname", "polypaudio"), 1)) < 0) { pa_log(__FILE__": lirc_init() failed.\n"); goto fail; } diff --git a/polyp/pactl.c b/polyp/pactl.c index d4dc6ad19..423cce959 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -181,7 +181,7 @@ static void get_sink_info_callback(struct pa_context *c, const struct pa_sink_in "Latency: %0.0f usec\n", i->index, i->name, - pa_typeid_to_string(i->typeid, tid, sizeof(tid)), + pa_typeid_to_string(i->_typeid, tid, sizeof(tid)), i->description, s, i->owner_module, @@ -224,7 +224,7 @@ static void get_source_info_callback(struct pa_context *c, const struct pa_sourc "Monitor of Sink: %s\n" "Latency: %0.0f usec\n", i->index, - pa_typeid_to_string(i->typeid, tid, sizeof(tid)), + pa_typeid_to_string(i->_typeid, tid, sizeof(tid)), i->name, i->description, s, @@ -296,7 +296,7 @@ static void get_client_info_callback(struct pa_context *c, const struct pa_clien "Owner Module: %s\n", i->index, i->name, - pa_typeid_to_string(i->typeid, tid, sizeof(tid)), + pa_typeid_to_string(i->_typeid, tid, sizeof(tid)), i->owner_module != PA_INVALID_INDEX ? t : "n/a"); } @@ -337,7 +337,7 @@ static void get_sink_input_info_callback(struct pa_context *c, const struct pa_s "Resample method: %s\n", i->index, i->name, - pa_typeid_to_string(i->typeid, tid, sizeof(tid)), + pa_typeid_to_string(i->_typeid, tid, sizeof(tid)), i->owner_module != PA_INVALID_INDEX ? t : "n/a", i->client != PA_INVALID_INDEX ? k : "n/a", i->sink, @@ -385,7 +385,7 @@ static void get_source_output_info_callback(struct pa_context *c, const struct p "Resample method: %s\n", i->index, i->name, - pa_typeid_to_string(i->typeid, tid, sizeof(tid)), + pa_typeid_to_string(i->_typeid, tid, sizeof(tid)), i->owner_module != PA_INVALID_INDEX ? t : "n/a", i->client != PA_INVALID_INDEX ? k : "n/a", i->source, diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 166555c0a..5d6d64abd 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -132,7 +132,7 @@ static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t com pa_tagstruct_getu32(t, &i.monitor_source) < 0 || pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || pa_tagstruct_get_usec(t, &i.latency) < 0 || - pa_tagstruct_getu32(t, &i.typeid) < 0) { + pa_tagstruct_getu32(t, &i._typeid) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; @@ -226,7 +226,7 @@ static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t c pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 || pa_tagstruct_get_usec(t, &i.latency) < 0 || - pa_tagstruct_getu32(t, &i.typeid) < 0) { + pa_tagstruct_getu32(t, &i._typeid) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; @@ -315,7 +315,7 @@ static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t c if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.typeid) < 0 ) { + pa_tagstruct_getu32(t, &i._typeid) < 0 ) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -455,7 +455,7 @@ static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || pa_tagstruct_get_usec(t, &i.sink_usec) < 0 || pa_tagstruct_gets(t, &i.resample_method) < 0 || - pa_tagstruct_getu32(t, &i.typeid) < 0) { + pa_tagstruct_getu32(t, &i._typeid) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; @@ -528,7 +528,7 @@ static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uin pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || pa_tagstruct_get_usec(t, &i.source_usec) < 0 || pa_tagstruct_gets(t, &i.resample_method) < 0 || - pa_tagstruct_getu32(t, &i.typeid) < 0) { + pa_tagstruct_getu32(t, &i._typeid) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index ba9bde3c2..83cdba162 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -58,7 +58,7 @@ struct pa_sink_info { uint32_t monitor_source; /**< Index of the monitor source connected to this sink */ const char *monitor_source_name; /**< The name of the monitor source */ pa_usec_t latency; /**< Length of filled playback buffer of this sink */ - pa_typeid_t typeid; /**< Implementation type. \since 0.8 */ + pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ }; /** Get information about a sink by its name */ @@ -80,7 +80,7 @@ struct pa_source_info { uint32_t monitor_of_sink; /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */ const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */ pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */ - pa_typeid_t typeid; /**< Implementation type. \since 0.8 */ + pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ }; /** Get information about a source by its name */ @@ -127,7 +127,7 @@ struct pa_client_info { uint32_t index; /**< Index of this client */ const char *name; /**< Name of this client */ uint32_t owner_module; /**< Index of the owning module, or PA_INVALID_INDEX */ - pa_typeid_t typeid; /**< Implementation type. \since 0.8 */ + pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ }; /** Get information about a client by its index */ @@ -148,7 +148,7 @@ struct pa_sink_input_info { pa_usec_t buffer_usec; /**< Latency due to buffering in sink input, see pa_latency_info for details */ pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */ const char *resample_method; /**< Thre resampling method used by this sink input. \since 0.7 */ - pa_typeid_t typeid; /**< Implementation type. \since 0.8 */ + pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ }; /** Get some information about a sink input by its index */ @@ -168,7 +168,7 @@ struct pa_source_output_info { pa_usec_t buffer_usec; /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */ pa_usec_t source_usec; /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */ const char *resample_method; /**< Thre resampling method used by this source output. \since 0.7 */ - pa_typeid_t typeid; /**< Implementation type. \since 0.8 */ + pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ }; /** Get information about a source output by its index */ diff --git a/polyp/typeid.h b/polyp/typeid.h index bd10b2e4b..cc1676bc0 100644 --- a/polyp/typeid.h +++ b/polyp/typeid.h @@ -25,6 +25,10 @@ #include #include +#include + +PA_C_DECL_BEGIN + typedef uint32_t pa_typeid_t; #define PA_TYPEID_UNKNOWN ((pa_typeid_t) -1) @@ -37,4 +41,6 @@ char *pa_typeid_to_string(pa_typeid_t id, char *ret_s, size_t length); (((pa_typeid_t) c & 0xFF) << 8) | \ (((pa_typeid_t) d & 0xFF))) +PA_C_DECL_END + #endif From 5ab306402d9efcceb3cc7b1097602c45365f12bd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 9 Jan 2005 01:11:53 +0000 Subject: [PATCH 0330/1514] * add new module module-mmkbd-evdev * fix stupid error message in main.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@337 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 3 + doc/todo | 2 +- polyp/Makefile.am | 18 ++- polyp/main.c | 3 +- polyp/module-lirc.c | 1 - polyp/module-mmkbd-evdev.c | 225 +++++++++++++++++++++++++++++++++++++ polyp/pdispatch.c | 2 +- 7 files changed, 249 insertions(+), 5 deletions(-) create mode 100644 polyp/module-mmkbd-evdev.c diff --git a/configure.ac b/configure.ac index 644c40503..1bf49291c 100644 --- a/configure.ac +++ b/configure.ac @@ -174,6 +174,9 @@ AC_SUBST(LIRC_CFLAGS) AC_SUBST(LIRC_LIBS) AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) +AC_CHECK_HEADER(linux/input.h,HAVE_EVDEV=1,HAVE_EVDEV=0) +AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = x1]) + # If using GCC specify some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -W -Wall -pedantic" diff --git a/doc/todo b/doc/todo index 3292342a9..fd024778f 100644 --- a/doc/todo +++ b/doc/todo @@ -6,6 +6,7 @@ Architectural changes: - add API for synchronizing multiple sinks/sources to a common clock - absolutely indexed write()s from client - remove "polyplib-" prefix +- hardware volume support Fixes: - improve module-oss-mmap latency measurement @@ -20,7 +21,6 @@ Features: - rendezvous autotunnel module - polish for starting polypaudio as root/system-wide instance - export connection fd -- /dev/input/event plugin Long term: - pass meta info for hearing impaired diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 95a80ec1e..72731c1d6 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -160,7 +160,8 @@ SYMDEF_FILES= \ module-null-sink-symdef.h \ module-esound-sink-symdef.h \ module-zeroconf-publish-symdef.h \ - module-lirc-symdef.h + module-lirc-symdef.h \ + module-mmkbd-evdev-symdef.h EXTRA_DIST+=$(SYMDEF_FILES) BUILT_SOURCES+=$(SYMDEF_FILES) @@ -707,6 +708,21 @@ module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS) endif + +### Linux evdev + +if HAVE_EVDEV + +modlib_LTLIBRARIES+= \ + module-mmkbd-evdev.la + +module_mmkbd_evdev_la_SOURCES = module-mmkbd-evdev.c +module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version +module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) +module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS) + +endif + ### libpolypcore (needs to be updated) if BUILD_LIBPOLYPCORE diff --git a/polyp/main.c b/polyp/main.c index c5b3a7e8e..51c414398 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -309,7 +309,8 @@ int main(int argc, char *argv[]) { if (conf->use_pid_file) { if (pa_pid_file_create() < 0) { - pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); + if (conf->daemonize) + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); goto finish; } diff --git a/polyp/module-lirc.c b/polyp/module-lirc.c index b400be12e..4cfc09dee 100644 --- a/polyp/module-lirc.c +++ b/polyp/module-lirc.c @@ -31,7 +31,6 @@ #include #include "module.h" -#include "iochannel.h" #include "log.h" #include "module-lirc-symdef.h" #include "namereg.h" diff --git a/polyp/module-mmkbd-evdev.c b/polyp/module-mmkbd-evdev.c new file mode 100644 index 000000000..758aaae54 --- /dev/null +++ b/polyp/module-mmkbd-evdev.c @@ -0,0 +1,225 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "module.h" +#include "log.h" +#include "module-mmkbd-evdev-symdef.h" +#include "namereg.h" +#include "sink.h" +#include "xmalloc.h" +#include "modargs.h" +#include "util.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Multimedia keyboard support via Linux evdev") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("device= sink=") + +#define DEFAULT_DEVICE "/dev/input/event0" + +static const char* const valid_modargs[] = { + "device", + "sink", + NULL, +}; + +struct userdata { + int fd; + struct pa_io_event *io; + char *sink_name; + struct pa_module *module; + float mute_toggle_save; +}; + +static void io_callback(struct pa_mainloop_api *io, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void*userdata) { + struct userdata *u = userdata; + assert(io); + assert(u); + + if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { + pa_log(__FILE__": lost connection to evdev device.\n"); + goto fail; + } + + if (events & PA_IO_EVENT_INPUT) { + struct input_event e; + + if (pa_loop_read(u->fd, &e, sizeof(e)) <= 0) { + pa_log(__FILE__": failed to read from event device: %s\n", strerror(errno)); + goto fail; + } + + if (e.type == EV_KEY && (e.value == 1 || e.value == 2)) { + enum { INVALID, UP, DOWN, MUTE_TOGGLE } volchange = INVALID; + + pa_log_debug(__FILE__": key code=%u, value=%u\n", e.code, e.value); + + switch (e.code) { + case KEY_VOLUMEDOWN: volchange = DOWN; break; + case KEY_VOLUMEUP: volchange = UP; break; + case KEY_MUTE: volchange = MUTE_TOGGLE; break; + } + + if (volchange != INVALID) { + struct pa_sink *s; + + if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) + pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name); + else { + double v = pa_volume_to_user(s->volume); + + switch (volchange) { + case UP: v += .05; break; + case DOWN: v -= .05; break; + case MUTE_TOGGLE: { + + if (v > 0) { + u->mute_toggle_save = v; + v = 0; + } else + v = u->mute_toggle_save; + } + default: + ; + } + + pa_sink_set_volume(s, pa_volume_from_user(v)); + } + } + } + } + + return; + +fail: + u->module->core->mainloop->io_free(u->io); + u->io = NULL; + + pa_module_unload_request(u->module); +} + +#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8))) + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct pa_modargs *ma = NULL; + struct userdata *u; + int version; + struct input_id input_id; + char name[256]; + uint8_t evtype_bitmask[EV_MAX/8 + 1]; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": Failed to parse module arguments\n"); + goto fail; + } + + m->userdata = u = pa_xmalloc(sizeof(struct userdata)); + u->module = m; + u->io = NULL; + u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + u->fd = -1; + u->mute_toggle_save = 0; + + if ((u->fd = open(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY)) < 0) { + pa_log(__FILE__": failed to open evdev device: %s\n", strerror(errno)); + goto fail; + } + + if (ioctl(u->fd, EVIOCGVERSION, &version) < 0) { + pa_log(__FILE__": EVIOCGVERSION failed: %s\n", strerror(errno)); + goto fail; + } + + pa_log_info(__FILE__": evdev driver version %i.%i.%i\n", version >> 16, (version >> 8) & 0xff, version & 0xff); + + if(ioctl(u->fd, EVIOCGID, &input_id)) { + pa_log(__FILE__": EVIOCGID failed: %s\n", strerror(errno)); + goto fail; + } + + pa_log_info(__FILE__": evdev vendor 0x%04hx product 0x%04hx version 0x%04hx bustype %u\n", + input_id.vendor, input_id.product, input_id.version, input_id.bustype); + + if(ioctl(u->fd, EVIOCGNAME(sizeof(name)), name) < 0) { + pa_log(__FILE__": EVIOCGNAME failed: %s\n", strerror(errno)); + goto fail; + } + + pa_log_info(__FILE__": evdev device name: %s\n", name); + + memset(evtype_bitmask, 0, sizeof(evtype_bitmask)); + if (ioctl(u->fd, EVIOCGBIT(0, EV_MAX), evtype_bitmask) < 0) { + pa_log(__FILE__": EVIOCGBIT failed: %s\n", strerror(errno)); + goto fail; + } + + if (!test_bit(EV_KEY, evtype_bitmask)) { + pa_log(__FILE__": device has no keys.\n"); + goto fail; + } + + u->io = c->mainloop->io_new(c->mainloop, u->fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); + + pa_modargs_free(ma); + + return 0; + +fail: + + if (ma) + pa_modargs_free(ma); + + pa__done(c, m); + return -1; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + assert(c); + assert(m); + + if (!(u = m->userdata)) + return; + + if (u->io) + m->core->mainloop->io_free(u->io); + + if (u->fd >= 0) + close(u->fd); + + pa_xfree(u->sink_name); + pa_xfree(u); +} diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index 90de345f7..7a9e9c680 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -33,7 +33,7 @@ #include "llist.h" #include "log.h" -/* #define DEBUG_OPCODES */ +/*#define DEBUG_OPCODES */ #ifdef DEBUG_OPCODES From 32bf3a106a946303f2175f01f3124354edd95a3e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Jan 2005 20:47:10 +0000 Subject: [PATCH 0331/1514] * new environment variable $POLYP_LOG * fix connection establishing algorithm * add timeout for establishing connections * add fqdn to the server directive to connect to in browse API * quieten ESOUND protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@338 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/log.c | 8 +++- polyp/polyplib-browser.c | 8 +++- polyp/polyplib-context.c | 4 +- polyp/protocol-esound.c | 9 +++-- polyp/socket-client.c | 82 +++++++++++++++++++++++++++++++++------- 5 files changed, 91 insertions(+), 20 deletions(-) diff --git a/polyp/log.c b/polyp/log.c index 530fa6911..78736a476 100644 --- a/polyp/log.c +++ b/polyp/log.c @@ -32,6 +32,8 @@ #include "xmalloc.h" #include "util.h" +#define ENV_LOGLEVEL "POLYP_LOG" + static char *log_ident = NULL; static enum pa_log_target log_target = PA_LOG_STDERR; static void (*user_log_func)(enum pa_log_level l, const char *s) = NULL; @@ -64,11 +66,15 @@ void pa_log_set_target(enum pa_log_target t, void (*func)(enum pa_log_level l, c } void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap) { + const char *e; assert(level < PA_LOG_LEVEL_MAX); + if ((e = getenv(ENV_LOGLEVEL))) + maximal_level = atoi(e); + if (level > maximal_level) return; - + switch (log_target) { case PA_LOG_STDERR: vfprintf(stderr, format, ap); diff --git a/polyp/polyplib-browser.c b/polyp/polyplib-browser.c index 7e56e2ceb..2e75a42dc 100644 --- a/polyp/polyplib-browser.c +++ b/polyp/polyplib-browser.c @@ -55,7 +55,6 @@ static void io_callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, } } - static sw_result resolve_reply( sw_discovery discovery, sw_discovery_oid oid, @@ -134,9 +133,16 @@ static sw_result resolve_reply( i.user_name = c; c = NULL; } else if (!strcmp(key, "fqdn")) { + size_t l; + pa_xfree((char*) i.fqdn); i.fqdn = c; c = NULL; + + l = strlen(a); + assert(l+1 <= sizeof(a)); + strncat(a, " ", sizeof(a)-l-1); + strncat(a, i.fqdn, sizeof(a)-l-2); } else if (!strcmp(key, "cookie")) { if (pa_atou(c, &cookie) < 0) diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index e7ccda3e8..bca7d7ea2 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -508,7 +508,7 @@ static int try_next_connection(struct pa_context *c) { goto finish; } -/* pa_log(__FILE__": Trying to connect to %s...\n", u); */ + pa_log_debug(__FILE__": Trying to connect to %s...\n", u); pa_xfree(c->server); c->server = pa_xstrdup(u); @@ -535,7 +535,7 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i assert(client && c && c->state == PA_CONTEXT_CONNECTING); pa_context_ref(c); - + pa_socket_client_unref(client); c->client = NULL; diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 744ad4ed1..d99b721c1 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -764,7 +764,8 @@ static int do_read(struct connection *c) { assert(c->read_data && c->read_data_length < handler->data_length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { - pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + if (r != 0) + pa_log_warn(__FILE__": read() failed: %s\n", strerror(errno)); return -1; } @@ -784,7 +785,8 @@ static int do_read(struct connection *c) { assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { - pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + if (r!= 0) + pa_log_warn(__FILE__": read() failed: %s\n", strerror(errno)); return -1; } @@ -841,7 +843,8 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + if (r != 0) + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); return -1; } diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 8ac04a8b6..01f66371a 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -46,11 +46,14 @@ #include "log.h" #include "parseaddr.h" +#define CONNECT_TIMEOUT 5 + struct pa_socket_client { int ref; struct pa_mainloop_api *mainloop; int fd; struct pa_io_event *io_event; + struct pa_time_event *timeout_event; struct pa_defer_event *defer_event; void (*callback)(struct pa_socket_client*c, struct pa_iochannel *io, void *userdata); void *userdata; @@ -72,6 +75,7 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { c->fd = -1; c->io_event = NULL; c->defer_event = NULL; + c->timeout_event = NULL; c->callback = NULL; c->userdata = NULL; c->local = 0; @@ -85,6 +89,25 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { return c; } +static void free_events(struct pa_socket_client *c) { + assert(c); + + if (c->io_event) { + c->mainloop->io_free(c->io_event); + c->io_event = NULL; + } + + if (c->defer_event) { + c->mainloop->defer_free(c->defer_event); + c->defer_event = NULL; + } + + if (c->timeout_event) { + c->mainloop->time_free(c->timeout_event); + c->timeout_event = NULL; + } +} + static void do_call(struct pa_socket_client *c) { struct pa_iochannel *io = NULL; int error; @@ -108,7 +131,7 @@ static void do_call(struct pa_socket_client *c) { } if (error != 0) { -/* pa_log(__FILE__": connect(): %s\n", strerror(error)); */ + pa_log_debug(__FILE__": connect(): %s\n", strerror(error)); errno = error; goto finish; } @@ -120,6 +143,8 @@ finish: if (!io && c->fd >= 0) close(c->fd); c->fd = -1; + + free_events(c); assert(c->callback); c->callback(c, io, c->userdata); @@ -130,16 +155,12 @@ finish: static void connect_fixed_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { struct pa_socket_client *c = userdata; assert(m && c && c->defer_event == e); - m->defer_free(c->defer_event); - c->defer_event = NULL; do_call(c); } static void connect_io_cb(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { struct pa_socket_client *c = userdata; assert(m && c && c->io_event == e && fd >= 0); - m->io_free(c->io_event); - c->io_event = NULL; do_call(c); } @@ -247,10 +268,10 @@ fail: void socket_client_free(struct pa_socket_client *c) { assert(c && c->mainloop); - if (c->io_event) - c->mainloop->io_free(c->io_event); - if (c->defer_event) - c->mainloop->defer_free(c->defer_event); + + + free_events(c); + if (c->fd >= 0) close(c->fd); @@ -305,7 +326,7 @@ static void asyncns_cb(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, assert(m && c && c->asyncns_io_event == e && fd >= 0); if (asyncns_wait(c->asyncns, 0) < 0) - goto finish; + goto fail; if (!asyncns_isdone(c->asyncns, c->asyncns_query)) return; @@ -314,22 +335,53 @@ static void asyncns_cb(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, c->asyncns_query = NULL; if (ret != 0 || !res) - goto finish; + goto fail; if (res->ai_addr) sockaddr_prepare(c, res->ai_addr, res->ai_addrlen); asyncns_freeaddrinfo(res); + goto finish; + +fail: + errno == EHOSTUNREACH; + do_call(c); + finish: m->io_free(c->asyncns_io_event); c->asyncns_io_event = NULL; - do_call(c); } #endif +static void timeout_cb(struct pa_mainloop_api *m, struct pa_time_event *e, const struct timeval *tv, void *userdata) { + struct pa_socket_client *c = userdata; + assert(m); + assert(e); + assert(tv); + assert(c); + + if (c->fd >= 0) { + close(c->fd); + c->fd = -1; + } + + errno = ETIMEDOUT; + do_call(c); +} + +static void start_timeout(struct pa_socket_client *c) { + struct timeval tv; + assert(c); + assert(!c->timeout_event); + + gettimeofday(&tv, NULL); + pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000); + c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c); +} + struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, const char*name, uint16_t default_port) { struct pa_socket_client *c = NULL; struct pa_parsed_address a; @@ -344,6 +396,7 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, switch (a.type) { case PA_PARSED_ADDRESS_UNIX: c = pa_socket_client_new_unix(m, a.path_or_host); + start_timeout(c); break; case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */ @@ -371,6 +424,7 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c); c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints); assert(c->asyncns_query); + start_timeout(c); } #else { @@ -382,8 +436,10 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, if (ret < 0 || !res) goto finish; - if (res->ai_addr) + if (res->ai_addr) { c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen); + start_timeout(c); + } freeaddrinfo(res); } From 4590f09d0b44aeb7cef3eed72b419444ea36d8e0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Jan 2005 17:37:31 +0000 Subject: [PATCH 0332/1514] * make pa_sample_spec_snprint return point to written string * first try of a http module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@339 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 30 ++++- polyp/caps.c | 3 - polyp/ioline.c | 33 ++++- polyp/ioline.h | 7 + polyp/module-protocol-stub.c | 17 +++ polyp/protocol-http.c | 244 +++++++++++++++++++++++++++++++++++ polyp/protocol-http.h | 35 +++++ polyp/sample.c | 12 +- polyp/sample.h | 2 +- polyp/socket-client.c | 9 +- 10 files changed, 374 insertions(+), 18 deletions(-) create mode 100644 polyp/protocol-http.c create mode 100644 polyp/protocol-http.h diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 72731c1d6..009707c2d 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -103,6 +103,7 @@ modlib_LTLIBRARIES= \ libprotocol-simple.la \ libprotocol-esound.la \ libprotocol-native.la \ + libprotocol-http.la \ module-cli.la \ module-cli-protocol-tcp.la \ module-cli-protocol-tcp6.la \ @@ -129,7 +130,10 @@ modlib_LTLIBRARIES= \ module-tunnel-sink.la \ module-tunnel-source.la \ module-null-sink.la \ - module-esound-sink.la + module-esound-sink.la \ + module-http-protocol-tcp.la \ + module-http-protocol-tcp6.la \ + module-http-protocol-unix.la SYMDEF_FILES= \ module-cli-symdef.h \ @@ -161,7 +165,10 @@ SYMDEF_FILES= \ module-esound-sink-symdef.h \ module-zeroconf-publish-symdef.h \ module-lirc-symdef.h \ - module-mmkbd-evdev-symdef.h + module-mmkbd-evdev-symdef.h \ + module-http-protocol-tcp-symdef.h \ + module-http-protocol-tcp6-symdef.h \ + module-http-protocol-unix-symdef.h EXTRA_DIST+=$(SYMDEF_FILES) BUILT_SOURCES+=$(SYMDEF_FILES) @@ -288,6 +295,10 @@ libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h libprotocol_cli_la_LDFLAGS = -avoid-version libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la +libprotocol_http_la_SOURCES = protocol-http.c protocol-http.h +libprotocol_http_la_LDFLAGS = -avoid-version +libprotocol_http_la_LIBADD = $(AM_LIBADD) libsocket-server.la libioline.la + libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h native-common.h libprotocol_native_la_LDFLAGS = -avoid-version libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la @@ -338,6 +349,21 @@ module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_ module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la libsocket-util.la +module_http_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_http_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) +module_http_protocol_tcp_la_LDFLAGS = -module -avoid-version +module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-http.la libsocket-server.la + +module_http_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_http_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) +module_http_protocol_tcp6_la_LDFLAGS = -module -avoid-version +module_http_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-http.la libsocket-server.la + +module_http_protocol_unix_la_SOURCES = module-protocol-stub.c +module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) +module_http_protocol_unix_la_LDFLAGS = -module -avoid-version +module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-http.la libsocket-server.la libsocket-util.la + module_native_protocol_tcp_la_SOURCES = module-protocol-stub.c module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version diff --git a/polyp/caps.c b/polyp/caps.c index 01ed15197..739e70712 100644 --- a/polyp/caps.c +++ b/polyp/caps.c @@ -23,9 +23,6 @@ #include #endif -/* setresuid() is only available on GNU */ -#define _GNU_SOURCE - #include #include #include diff --git a/polyp/ioline.c b/polyp/ioline.c index f52af2db9..6f7886da5 100644 --- a/polyp/ioline.c +++ b/polyp/ioline.c @@ -51,6 +51,8 @@ struct pa_ioline { void (*callback)(struct pa_ioline*io, const char *s, void *userdata); void *userdata; + + int defer_close; }; static void io_callback(struct pa_iochannel*io, void *userdata); @@ -78,6 +80,8 @@ struct pa_ioline* pa_ioline_new(struct pa_iochannel *io) { l->defer_event = l->mainloop->defer_new(l->mainloop, defer_callback, l); l->mainloop->defer_enable(l->defer_event, 0); + + l->defer_close = 0; pa_iochannel_set_callback(io, io_callback, l); @@ -181,8 +185,10 @@ static void failure(struct pa_ioline *l) { pa_ioline_close(l); - if (l->callback) + if (l->callback) { l->callback(l, NULL, l->userdata); + l->callback = NULL; + } } static void scan_for_lines(struct pa_ioline *l, size_t skip) { @@ -309,6 +315,9 @@ static void do_work(struct pa_ioline *l) { if (!l->dead) do_read(l); + if (l->defer_close && !l->wbuf_valid_length) + failure(l); + pa_ioline_unref(l); } @@ -325,3 +334,25 @@ static void defer_callback(struct pa_mainloop_api*m, struct pa_defer_event*e, vo do_work(l); } + +void pa_ioline_defer_close(struct pa_ioline *l) { + assert(l); + + l->defer_close = 1; + + if (!l->wbuf_valid_length) + l->mainloop->defer_enable(l->defer_event, 1); +} + +void pa_ioline_printf(struct pa_ioline *s, const char *format, ...) { + char *t; + va_list ap; + + + va_start(ap, format); + t = pa_vsprintf_malloc(format, ap); + va_end(ap); + + pa_ioline_puts(s, t); + pa_xfree(t); +} diff --git a/polyp/ioline.h b/polyp/ioline.h index f652dddbd..6e9c76d08 100644 --- a/polyp/ioline.h +++ b/polyp/ioline.h @@ -23,6 +23,7 @@ ***/ #include "iochannel.h" +#include "util.h" /* An ioline wraps an iochannel for line based communication. A * callback function is called whenever a new line has been recieved @@ -38,7 +39,13 @@ void pa_ioline_close(struct pa_ioline *l); /* Write a string to the channel */ void pa_ioline_puts(struct pa_ioline *s, const char *c); +/* Write a string to the channel */ +void pa_ioline_printf(struct pa_ioline *s, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); + /* Set the callback function that is called for every recieved line */ void pa_ioline_set_callback(struct pa_ioline*io, void (*callback)(struct pa_ioline*io, const char *s, void *userdata), void *userdata); +/* Make sure to close the ioline object as soon as the send buffer is emptied */ +void pa_ioline_defer_close(struct pa_ioline *io); + #endif diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 93e576af7..be27b8e2c 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -85,6 +85,23 @@ #endif PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE(SOCKET_USAGE) +#elif defined(USE_PROTOCOL_HTTP) + #include "protocol-http.h" + #define protocol_new pa_protocol_http_new + #define protocol_free pa_protocol_http_free + #define TCPWRAP_SERVICE "polypaudio-http" + #define IPV4_PORT 4714 + #define UNIX_SOCKET "http" + #define MODULE_ARGUMENTS + #ifdef USE_TCP_SOCKETS + #include "module-http-protocol-tcp-symdef.h" + #elif defined(USE_TCP6_SOCKETS) + #include "module-http-protocol-tcp6-symdef.h" + #else + #include "module-http-protocol-unix-symdef.h" + #endif + PA_MODULE_DESCRIPTION("HTTP "SOCKET_DESCRIPTION) + PA_MODULE_USAGE(SOCKET_USAGE) #elif defined(USE_PROTOCOL_NATIVE) #include "protocol-native.h" #define protocol_new pa_protocol_native_new diff --git a/polyp/protocol-http.c b/polyp/protocol-http.c new file mode 100644 index 000000000..768b75888 --- /dev/null +++ b/polyp/protocol-http.c @@ -0,0 +1,244 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "protocol-http.h" +#include "ioline.h" +#include "xmalloc.h" +#include "log.h" +#include "namereg.h" + +/* Don't allow more than this many concurrent connections */ +#define MAX_CONNECTIONS 10 + +#define internal_server_error(c) http_message((c), 500, "Internal Server Error", NULL) + +#define URL_ROOT "/" +#define URL_CSS "/style.css" + +struct connection { + struct pa_protocol_http *protocol; + struct pa_ioline *line; + enum { REQUEST_LINE, MIME_HEADER, DATA } state; + char *url; +}; + +struct pa_protocol_http { + struct pa_module *module; + struct pa_core *core; + struct pa_socket_server*server; + struct pa_idxset *connections; +}; + +static void http_response(struct connection *c, int code, const char *msg, const char *mime) { + char s[256]; + assert(c); + assert(msg); + assert(mime); + + snprintf(s, sizeof(s), + "HTTP/1.0 %i %s\n" + "Connection: close\n" + "Content-Type: %s\n" + "\n", code, msg, mime); + + pa_ioline_puts(c->line, s); +} + +static void http_message(struct connection *c, int code, const char *msg, const char *text) { + char s[256]; + assert(c); + + http_response(c, code, msg, "text/html"); + + if (!text) + text = msg; + + snprintf(s, sizeof(s), + "%s\n" + "%s\n", + text, text); + + pa_ioline_puts(c->line, s); + pa_ioline_defer_close(c->line); +} + + +static void connection_free(struct connection *c, int del) { + assert(c); + + if (c->url) + pa_xfree(c->url); + + if (del) + pa_idxset_remove_by_data(c->protocol->connections, c, NULL); + pa_ioline_unref(c->line); + pa_xfree(c); +} + +static void line_callback(struct pa_ioline *line, const char *s, void *userdata) { + struct connection *c = userdata; + assert(line); + assert(c); + + if (!s) { + /* EOF */ + connection_free(c, 1); + return; + } + + switch (c->state) { + case REQUEST_LINE: { + if (memcmp(s, "GET ", 4)) + goto fail; + + s +=4; + + c->url = pa_xstrndup(s, strcspn(s, " \r\n\t")); + c->state = MIME_HEADER; + break; + + } + + case MIME_HEADER: { + + /* Ignore MIME headers */ + if (strcspn(s, " \r\n") != 0) + break; + + /* We're done */ + c->state = DATA; + + pa_log("req for %s\n", c->url); + + if (!strcmp(c->url, URL_ROOT)) { + char txt[256]; + http_response(c, 200, "OK", "text/html"); + + pa_ioline_puts(c->line, + ""PACKAGE_NAME" "PACKAGE_VERSION"\n" + "\n"); + + pa_ioline_puts(c->line, + "

    "PACKAGE_NAME" "PACKAGE_VERSION"

    \n" + "

    Server Information

    \n" + ""); + +#define PRINTF_FIELD(a,b) pa_ioline_printf(c->line, "\n",(a),(b)) + + PRINTF_FIELD("User Name:", pa_get_user_name(txt, sizeof(txt))); + PRINTF_FIELD("Fully Qualified Domain Name:", pa_get_fqdn(txt, sizeof(txt))); + PRINTF_FIELD("Default Sample Specification:", pa_sample_spec_snprint(txt, sizeof(txt), &c->protocol->core->default_sample_spec)); + PRINTF_FIELD("Default Sink:", pa_namereg_get_default_sink_name(c->protocol->core)); + PRINTF_FIELD("Default Source:", pa_namereg_get_default_source_name(c->protocol->core)); + pa_ioline_puts(c->line, "
    %s%s
    "); + pa_ioline_puts(c->line, "\n"); + + pa_ioline_defer_close(c->line); + } else if (!strcmp(c->url, URL_CSS)) { + http_response(c, 200, "OK", "text/css"); + + pa_ioline_puts(c->line, + "body { color: black; background-color: white; margin: 0.5cm; }\n" + "a:link, a:visited { color: #900000; }\n" + "p { margin-left: 0.5cm; margin-right: 0.5cm; }\n" + "h1 { color: #00009F; }\n" + "h2 { color: #00009F; }\n" + "ul { margin-left: .5cm; }\n" + "ol { margin-left: .5cm; }\n" + "pre { margin-left: .5cm; background-color: #f0f0f0; padding: 0.4cm;}\n" + ".grey { color: #afafaf; }\n" + "table { margin-left: 1cm; border:1px solid lightgrey; padding: 0.2cm; }\n" + "td { padding-left:10px; padding-right:10px; }\n"); + + pa_ioline_defer_close(c->line); + } else + http_message(c, 404, "Not Found", NULL); + + break; + } + + default: + ; + } + + return; + +fail: + internal_server_error(c); +} + +static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { + struct pa_protocol_http *p = userdata; + struct connection *c; + assert(s && io && p); + + if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { + pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_iochannel_free(io); + return; + } + + c = pa_xmalloc(sizeof(struct connection)); + c->protocol = p; + c->line = pa_ioline_new(io); + c->state = REQUEST_LINE; + c->url = NULL; + + pa_ioline_set_callback(c->line, line_callback, c); + pa_idxset_put(p->connections, c, NULL); +} + +struct pa_protocol_http* pa_protocol_http_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { + struct pa_protocol_http* p; + assert(core && server); + + p = pa_xmalloc(sizeof(struct pa_protocol_http)); + p->module = m; + p->core = core; + p->server = server; + p->connections = pa_idxset_new(NULL, NULL); + + pa_socket_server_set_callback(p->server, on_connection, p); + + return p; +} + +static void free_connection(void *p, void *userdata) { + assert(p); + connection_free(p, 0); +} + +void pa_protocol_http_free(struct pa_protocol_http *p) { + assert(p); + + pa_idxset_free(p->connections, free_connection, NULL); + pa_socket_server_unref(p->server); + pa_xfree(p); +} diff --git a/polyp/protocol-http.h b/polyp/protocol-http.h new file mode 100644 index 000000000..3c9b8d76b --- /dev/null +++ b/polyp/protocol-http.h @@ -0,0 +1,35 @@ +#ifndef fooprotocolhttphfoo +#define fooprotocolhttphfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include "core.h" +#include "socket-server.h" +#include "module.h" +#include "modargs.h" + +struct pa_protocol_http; + +struct pa_protocol_http* pa_protocol_http_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); +void pa_protocol_http_free(struct pa_protocol_http *n); + +#endif diff --git a/polyp/sample.c b/polyp/sample.c index 51afaa016..f9d0c4588 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -101,15 +101,15 @@ const char *pa_sample_format_to_string(enum pa_sample_format f) { return table[f]; } -void pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { +char *pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { assert(s && l && spec); - if (!pa_sample_spec_valid(spec)) { + if (!pa_sample_spec_valid(spec)) snprintf(s, l, "Invalid"); - return; - } - - snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate); + else + snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate); + + return s; } pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b) { diff --git a/polyp/sample.h b/polyp/sample.h index d4873eb5c..0494c7dec 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -93,7 +93,7 @@ const char *pa_sample_format_to_string(enum pa_sample_format f); #define PA_SAMPLE_SPEC_SNPRINT_MAX 32 /** Pretty print a sample type specification to a string */ -void pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec); +char* pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec); /** Volume specification: 0: silence; < 256: diminished volume; 256: normal volume; > 256 amplified volume */ typedef uint32_t pa_volume_t; diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 01f66371a..1bcf82e31 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -395,8 +395,8 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, switch (a.type) { case PA_PARSED_ADDRESS_UNIX: - c = pa_socket_client_new_unix(m, a.path_or_host); - start_timeout(c); + if ((c = pa_socket_client_new_unix(m, a.path_or_host))) + start_timeout(c); break; case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */ @@ -437,9 +437,8 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, goto finish; if (res->ai_addr) { - c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen); - start_timeout(c); - } + if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen))) + tart_timeout(c); freeaddrinfo(res); } From f586ce084244d60961ebd9b2b4555ecdc499c9f9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Jan 2005 18:51:38 +0000 Subject: [PATCH 0333/1514] * extend HTTP module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@340 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- polyp/cli-text.c | 44 ++++++++++++++++++++++++++++++++++++++++++ polyp/cli-text.h | 2 ++ polyp/main.c | 45 ++++++------------------------------------- polyp/protocol-http.c | 41 +++++++++++++++++++++++++++++---------- 5 files changed, 84 insertions(+), 50 deletions(-) diff --git a/doc/todo b/doc/todo index fd024778f..7321396a0 100644 --- a/doc/todo +++ b/doc/todo @@ -16,7 +16,7 @@ Fixes: Features: - add radio module -- xmlrpc/http +- xmlrpc - dbus/hal - rendezvous autotunnel module - polish for starting polypaudio as root/system-wide instance diff --git a/polyp/cli-text.c b/polyp/cli-text.c index dd40add26..d4c46dc09 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -37,6 +37,7 @@ #include "sample-util.h" #include "scache.h" #include "autoload.h" +#include "xmalloc.h" char *pa_module_list_to_string(struct pa_core *c) { struct pa_strbuf *s; @@ -306,3 +307,46 @@ char *pa_autoload_list_to_string(struct pa_core *c) { return pa_strbuf_tostring_free(s); } + +char *pa_full_status_string(struct pa_core *c) { + struct pa_strbuf *s; + int i; + + s = pa_strbuf_new(); + + for (i = 0; i < 8; i++) { + char *t = NULL; + + switch (i) { + case 0: + t = pa_sink_list_to_string(c); + break; + case 1: + t = pa_source_list_to_string(c); + break; + case 2: + t = pa_sink_input_list_to_string(c); + break; + case 3: + t = pa_source_output_list_to_string(c); + break; + case 4: + t = pa_client_list_to_string(c); + break; + case 5: + t = pa_module_list_to_string(c); + break; + case 6: + t = pa_scache_list_to_string(c); + break; + case 7: + t = pa_autoload_list_to_string(c); + break; + } + + pa_strbuf_puts(s, t); + pa_xfree(t); + } + + return pa_strbuf_tostring_free(s); +} diff --git a/polyp/cli-text.h b/polyp/cli-text.h index 65607e943..d19dd48ca 100644 --- a/polyp/cli-text.h +++ b/polyp/cli-text.h @@ -36,5 +36,7 @@ char *pa_module_list_to_string(struct pa_core *c); char *pa_scache_list_to_string(struct pa_core *c); char *pa_autoload_list_to_string(struct pa_core *c); +char *pa_full_status_string(struct pa_core *c); + #endif diff --git a/polyp/main.c b/polyp/main.c index 51c414398..d6c25b4bf 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -71,49 +71,16 @@ static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, switch (sig) { case SIGUSR1: pa_module_load(userdata, "module-cli", NULL); - return; + break; case SIGUSR2: pa_module_load(userdata, "module-cli-protocol-unix", NULL); - return; + break; case SIGHUP: { - int i; - - for (i = 0;; i++) { - char *c; - switch (i) { - case 0: - c = pa_sink_list_to_string(userdata); - break; - case 1: - c = pa_source_list_to_string(userdata); - break; - case 2: - c = pa_sink_input_list_to_string(userdata); - break; - case 3: - c = pa_source_output_list_to_string(userdata); - break; - case 4: - c = pa_client_list_to_string(userdata); - break; - case 5: - c = pa_module_list_to_string(userdata); - break; - case 6: - c = pa_scache_list_to_string(userdata); - break; - case 7: - c = pa_autoload_list_to_string(userdata); - break; - default: - return; - } - pa_log_notice(c); - pa_xfree(c); - } - + char *c = pa_full_status_string(userdata); + pa_log_notice(c); + pa_xfree(c); return; } @@ -122,7 +89,7 @@ static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, default: pa_log_info(__FILE__": Exiting.\n"); m->quit(m, 1); - return; + break; } } diff --git a/polyp/protocol-http.c b/polyp/protocol-http.c index 768b75888..64e6dadfb 100644 --- a/polyp/protocol-http.c +++ b/polyp/protocol-http.c @@ -33,6 +33,7 @@ #include "xmalloc.h" #include "log.h" #include "namereg.h" +#include "cli-text.h" /* Don't allow more than this many concurrent connections */ #define MAX_CONNECTIONS 10 @@ -40,7 +41,8 @@ #define internal_server_error(c) http_message((c), 500, "Internal Server Error", NULL) #define URL_ROOT "/" -#define URL_CSS "/style.css" +#define URL_CSS "/style" +#define URL_STATUS "/status" struct connection { struct pa_protocol_http *protocol; @@ -66,6 +68,9 @@ static void http_response(struct connection *c, int code, const char *msg, const "HTTP/1.0 %i %s\n" "Connection: close\n" "Content-Type: %s\n" + "Cache-Control: no-cache\n" + "Expires: 0\n" + "Server: "PACKAGE_NAME"/"PACKAGE_VERSION"\n" "\n", code, msg, mime); pa_ioline_puts(c->line, s); @@ -80,8 +85,10 @@ static void http_message(struct connection *c, int code, const char *msg, const if (!text) text = msg; - snprintf(s, sizeof(s), - "%s\n" + snprintf(s, sizeof(s), + "\n" + "\n" + "%s\n" "%s\n", text, text); @@ -120,7 +127,7 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) s +=4; - c->url = pa_xstrndup(s, strcspn(s, " \r\n\t")); + c->url = pa_xstrndup(s, strcspn(s, " \r\n\t?")); c->state = MIME_HEADER; break; @@ -135,19 +142,20 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) /* We're done */ c->state = DATA; - pa_log("req for %s\n", c->url); + pa_log_info(__FILE__": request for %s\n", c->url); if (!strcmp(c->url, URL_ROOT)) { char txt[256]; http_response(c, 200, "OK", "text/html"); pa_ioline_puts(c->line, - ""PACKAGE_NAME" "PACKAGE_VERSION"\n" - "\n"); + "\n" + "\n" + ""PACKAGE_NAME" "PACKAGE_VERSION"\n" + "\n"); pa_ioline_puts(c->line, "

    "PACKAGE_NAME" "PACKAGE_VERSION"

    \n" - "

    Server Information

    \n" ""); #define PRINTF_FIELD(a,b) pa_ioline_printf(c->line, "\n",(a),(b)) @@ -157,7 +165,11 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) PRINTF_FIELD("Default Sample Specification:", pa_sample_spec_snprint(txt, sizeof(txt), &c->protocol->core->default_sample_spec)); PRINTF_FIELD("Default Sink:", pa_namereg_get_default_sink_name(c->protocol->core)); PRINTF_FIELD("Default Source:", pa_namereg_get_default_source_name(c->protocol->core)); + pa_ioline_puts(c->line, "
    %s%s
    "); + + pa_ioline_puts(c->line, "

    Click here for an extensive server status report.

    "); + pa_ioline_puts(c->line, "\n"); pa_ioline_defer_close(c->line); @@ -177,7 +189,16 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) "table { margin-left: 1cm; border:1px solid lightgrey; padding: 0.2cm; }\n" "td { padding-left:10px; padding-right:10px; }\n"); - pa_ioline_defer_close(c->line); + pa_ioline_defer_close(c->line); + } else if (!strcmp(c->url, URL_STATUS)) { + char *s; + + http_response(c, 200, "OK", "text/plain"); + s = pa_full_status_string(c->protocol->core); + pa_ioline_puts(c->line, s); + pa_xfree(s); + + pa_ioline_defer_close(c->line); } else http_message(c, 404, "Not Found", NULL); @@ -200,7 +221,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo assert(s && io && p); if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { - pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); pa_iochannel_free(io); return; } From 4daa0c164920de2f50860e71c1b19de0fd40424d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Jan 2005 20:22:08 +0000 Subject: [PATCH 0334/1514] * fix LIRC configuration git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@341 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 7 ++++--- doc/todo | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 1bf49291c..27cfeecd1 100644 --- a/configure.ac +++ b/configure.ac @@ -167,9 +167,10 @@ AC_MSG_RESULT(yes)], AC_SUBST(LIBWRAP_LIBS) LIBS="$saved_LIBS" -HAVE_LIRC=1 -AC_CHECK_HEADER(lirc/lirc_client.h,[AC_CHECK_LIB(lirc_client,lirc_init,,HAVE_LIRC=0)],HAVE_LIRC=0) -LIRC_LIBS=-llirc_client +LIRC_CFLAGS= +LIRC_LIBS= +AC_CHECK_HEADER(lirc/lirc_client.h,[AC_CHECK_LIB(lirc_client,lirc_init,[HAVE_LIRC=1 +LIRC_LIBS=-llirc_client],HAVE_LIRC=0)],HAVE_LIRC=0) AC_SUBST(LIRC_CFLAGS) AC_SUBST(LIRC_LIBS) AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) diff --git a/doc/todo b/doc/todo index 7321396a0..0da832069 100644 --- a/doc/todo +++ b/doc/todo @@ -3,10 +3,10 @@ Architectural changes: - per-channel volume - channel mapping ("left", "right", "rear", "subwoofer") +- hardware volume support - add API for synchronizing multiple sinks/sources to a common clock - absolutely indexed write()s from client - remove "polyplib-" prefix -- hardware volume support Fixes: - improve module-oss-mmap latency measurement From b5f570723c559a95fad1346975b2bb20acc13551 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Sep 2005 23:46:39 +0000 Subject: [PATCH 0335/1514] add libsamplerate/libsndfile CFLAGS git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@345 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 009707c2d..389cb0d3b 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -22,7 +22,7 @@ polypconfdir=$(sysconfdir)/polypaudio modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ -AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) +AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\" AM_CFLAGS+=-DDEFAULT_CONFIG_DIR=\"$(polypconfdir)\" AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" From f1da8ade63568aec84e7f2bc6b92acbd77f5a13c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Sep 2005 23:47:01 +0000 Subject: [PATCH 0336/1514] fix start_timeout() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@346 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/socket-client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 1bcf82e31..21563d35c 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -438,7 +438,8 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, if (res->ai_addr) { if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen))) - tart_timeout(c); + start_timeout(c); + } freeaddrinfo(res); } From fda09b92555bcd9b8e3cbd710557c1b0784cd697 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Sep 2005 23:48:09 +0000 Subject: [PATCH 0337/1514] remove esound protocol directory on unload of module-protocol-esound git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@347 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-protocol-stub.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index be27b8e2c..15697582e 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -240,5 +240,12 @@ finish: void pa__done(struct pa_core *c, struct pa_module*m) { assert(c && m); +#if defined(USE_PROTOCOL_ESOUND) + if (remove (ESD_UNIX_SOCKET_NAME) != 0) + pa_log("%s: Failed to remove %s : %s.\n", __FILE__, ESD_UNIX_SOCKET_NAME, strerror (errno)); + if (remove (ESD_UNIX_SOCKET_DIR) != 0) + pa_log("%s: Failed to remove %s : %s.\n", __FILE__, ESD_UNIX_SOCKET_DIR, strerror (errno)); +#endif + protocol_free(m->userdata); } From db4b25d8b2edbafa898b9ca12b8900bda5c0be1e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Sep 2005 23:50:05 +0000 Subject: [PATCH 0338/1514] handle EOF in ioline.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@348 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/ioline.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/polyp/ioline.c b/polyp/ioline.c index 6f7886da5..f437094d2 100644 --- a/polyp/ioline.c +++ b/polyp/ioline.c @@ -262,8 +262,16 @@ static int do_read(struct pa_ioline *l) { assert(len >= READ_SIZE); /* Read some data */ - if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) { - pa_log(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len); + if (r == 0) { + /* Got an EOF, so fake an exit command. */ + l->rbuf_index = 0; + snprintf (l->rbuf, l->rbuf_length, "exit\n"); + r = 5; + pa_ioline_puts(l, "\nExiting.\n"); + do_write(l); + } else if (r < 0) { + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); failure(l); return -1; } From b993e33cceac379f9ed882a8f4c34965873178cc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Sep 2005 23:50:33 +0000 Subject: [PATCH 0339/1514] alter alsa periods number git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@349 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-alsa-sink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 9933d37a9..f6826c529 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -192,7 +192,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { } frame_size = pa_frame_size(&ss); - periods = 12; + periods = 8; fragsize = 1024; if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { pa_log(__FILE__": failed to parse buffer metrics\n"); From c57cad926c5afea0cabae96183227651e686c633 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:00:39 +0000 Subject: [PATCH 0340/1514] bail out if no sink is defined git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@350 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/polyp/main.c b/polyp/main.c index d6c25b4bf..e881821e0 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -58,6 +58,7 @@ #include "caps.h" #include "cli-text.h" #include "pid.h" +#include "namereg.h" #ifdef HAVE_LIBWRAP /* Only one instance of these variables */ @@ -332,11 +333,16 @@ int main(int argc, char *argv[]) { c->module_idle_time = conf->module_idle_time; c->scache_idle_time = conf->scache_idle_time; c->resample_method = conf->resample_method; - - pa_log_info(__FILE__": Daemon startup complete.\n"); - if (pa_mainloop_run(mainloop, &retval) < 0) + + if (pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) { + pa_log_error("%s : Fatal error. Default sink name (%s) does not exist in name register.\n", __FILE__, c->default_sink_name); retval = 1; - pa_log_info(__FILE__": Daemon shutdown initiated.\n"); + } else { + pa_log_info(__FILE__": Daemon startup complete.\n"); + if (pa_mainloop_run(mainloop, &retval) < 0) + retval = 1; + pa_log_info(__FILE__": Daemon shutdown initiated.\n"); + } } pa_core_free(c); From 6d9dffebaed590706d0fa5a466c90d7ed72e624a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:00:59 +0000 Subject: [PATCH 0341/1514] build fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@351 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/ioline.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/polyp/ioline.c b/polyp/ioline.c index f437094d2..72df6b877 100644 --- a/polyp/ioline.c +++ b/polyp/ioline.c @@ -224,6 +224,8 @@ static void scan_for_lines(struct pa_ioline *l, size_t skip) { l->rbuf_index = l->rbuf_valid_length = 0; } +static int do_write(struct pa_ioline *l); + static int do_read(struct pa_ioline *l) { assert(l && l->ref >= 1); From e0d0f1bb3e93690a18cfb8db96e12f5ae11b3320 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:01:20 +0000 Subject: [PATCH 0342/1514] git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@352 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/protocol-native.c | 1 + 1 file changed, 1 insertion(+) diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index d5619ef7a..7e1a88949 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -594,6 +594,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1); if (!sink) { + pa_log("%s: Can't find a suitable sink.\n", __FILE__); pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } From 652e000f9e3b75fb705abf30c0dc447283a64191 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:02:10 +0000 Subject: [PATCH 0343/1514] print a nice message when libltdl is missing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@353 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure.ac b/configure.ac index 27cfeecd1..125413450 100644 --- a/configure.ac +++ b/configure.ac @@ -46,6 +46,14 @@ AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL AC_CONFIG_SUBDIRS(libltdl) +if test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then + AC_MSG_ERROR([[ + + *** Cannot find the libltdl development files. + *** Maybe you need to install the libltdl-dev package. + ]]) +fi + # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h syslog.h]) From 668f3cdcbc02ebb5074a31016f1766bfe4992240 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:03:19 +0000 Subject: [PATCH 0344/1514] handle float values in sound files sensibly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@354 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/sound-file.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/polyp/sound-file.c b/polyp/sound-file.c index 80233da55..f16d326a1 100644 --- a/polyp/sound-file.c +++ b/polyp/sound-file.c @@ -52,19 +52,18 @@ int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_m goto finish; } - switch (sfinfo.format & 0xFF) { - case SF_FORMAT_PCM_16: - case SF_FORMAT_PCM_U8: - case SF_FORMAT_ULAW: - case SF_FORMAT_ALAW: - ss->format = PA_SAMPLE_S16NE; - readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short; - break; + switch (sfinfo.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_FLOAT: - default: + case SF_FORMAT_DOUBLE: + /* Only float and double need a special case. */ ss->format = PA_SAMPLE_FLOAT32NE; readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float; break; + default: + /* Everything else is cleanly converted to signed 16 bit. */ + ss->format = PA_SAMPLE_S16NE; + readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short; + break; } ss->rate = sfinfo.samplerate; From 48b2a87ed8ef8a40602f4c139432513a49eecf35 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:04:29 +0000 Subject: [PATCH 0345/1514] add pa_sound_file_too_big_to_cache() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@355 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/sound-file.c | 37 ++++++++++++++++++++++++++++++++++++- polyp/sound-file.h | 2 ++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/polyp/sound-file.c b/polyp/sound-file.c index f16d326a1..326ddd8bf 100644 --- a/polyp/sound-file.c +++ b/polyp/sound-file.c @@ -75,7 +75,7 @@ int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_m } if ((l = pa_frame_size(ss)*sfinfo.frames) > MAX_FILE_SIZE) { - pa_log(__FILE__": File to large\n"); + pa_log(__FILE__": File too large\n"); goto finish; } @@ -102,3 +102,38 @@ finish: return ret; } + +int pa_sound_file_too_big_to_cache(const char *fname) { + SNDFILE*sf = NULL; + SF_INFO sfinfo; + struct pa_sample_spec ss; + + if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { + pa_log(__FILE__": Failed to open file %s\n", fname); + return 0; + } + + sf_close(sf); + + switch (sfinfo.format & SF_FORMAT_SUBMASK) { + case SF_FORMAT_FLOAT: + case SF_FORMAT_DOUBLE: + /* Only float and double need a special case. */ + ss.format = PA_SAMPLE_FLOAT32NE; + break; + default: + /* Everything else is cleanly converted to signed 16 bit. */ + ss.format = PA_SAMPLE_S16NE; + break; + } + + ss.rate = sfinfo.samplerate; + ss.channels = sfinfo.channels; + + if ((pa_frame_size(&ss) * sfinfo.frames) > MAX_FILE_SIZE) { + pa_log(__FILE__": File too large %s\n", fname); + return 1; + } + + return 0; +} diff --git a/polyp/sound-file.h b/polyp/sound-file.h index e53598535..855e68832 100644 --- a/polyp/sound-file.h +++ b/polyp/sound-file.h @@ -27,4 +27,6 @@ int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk, struct pa_memblock_stat *s); +int pa_sound_file_too_big_to_cache(const char *fname); + #endif From e4395c223deea8803e2408b5ba57f52b4f65030f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:08:02 +0000 Subject: [PATCH 0346/1514] add new field running_as_daemon to pa_core git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@356 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/core.h | 2 +- polyp/main.c | 2 ++ polyp/module-cli.c | 11 +++++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/polyp/core.h b/polyp/core.h index 366044244..8ef665707 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -59,7 +59,7 @@ struct pa_core { struct pa_memblock_stat *memblock_stat; - int disallow_module_loading; + int disallow_module_loading, running_as_daemon; int exit_idle_time, module_idle_time, scache_idle_time; struct pa_time_event *quit_event; diff --git a/polyp/main.c b/polyp/main.c index e881821e0..26fa4a874 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -296,6 +296,8 @@ int main(int argc, char *argv[]) { c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); + if (conf->daemonize) + c->running_as_daemon = 1; pa_signal_new(SIGUSR1, signal_callback, c); pa_signal_new(SIGUSR2, signal_callback, c); diff --git a/polyp/module-cli.c b/polyp/module-cli.c index 55fe8ad42..7d278f90b 100644 --- a/polyp/module-cli.c +++ b/polyp/module-cli.c @@ -50,6 +50,11 @@ int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_iochannel *io; assert(c && m); + if (c->running_as_daemon) { + pa_log_info(__FILE__": Running as daemon so won't load this module.\n"); + return 0; + } + if (m->argument) { pa_log(__FILE__": module doesn't accept arguments.\n"); return -1; @@ -75,6 +80,8 @@ int pa__init(struct pa_core *c, struct pa_module*m) { void pa__done(struct pa_core *c, struct pa_module*m) { assert(c && m); - pa_cli_free(m->userdata); - pa_stdio_release(); + if (c->running_as_daemon == 0) { + pa_cli_free(m->userdata); + pa_stdio_release(); + } } From d50bfd8496c15552b970079bdfcad86cf3cd59b2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:08:53 +0000 Subject: [PATCH 0347/1514] increase number of allowed connections git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@357 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/protocol-cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/protocol-cli.c b/polyp/protocol-cli.c index 7122d23a4..107acb194 100644 --- a/polyp/protocol-cli.c +++ b/polyp/protocol-cli.c @@ -32,7 +32,7 @@ #include "log.h" /* Don't allow more than this many concurrent connections */ -#define MAX_CONNECTIONS 10 +#define MAX_CONNECTIONS 25 struct pa_protocol_cli { struct pa_module *module; From 3a61b36c9d51b8698d196c91dd16c50d2cbbc48c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:09:19 +0000 Subject: [PATCH 0348/1514] initialize running_as_daemon git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@358 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/polyp/core.c b/polyp/core.c index c213faa0a..e2bebec25 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -59,6 +59,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { c->scache = NULL; c->autoload_idxset = NULL; c->autoload_hashmap = NULL; + c->running_as_daemon = 0; c->default_sample_spec.format = PA_SAMPLE_S16NE; c->default_sample_spec.rate = 44100; From 9177ef4ce22218c02334fa6d3ac9afbeea2913d7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:11:15 +0000 Subject: [PATCH 0349/1514] chance ALSA sink to use "default" as default alsa device git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@359 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-alsa-sink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index f6826c529..840fc5364 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -71,7 +71,7 @@ static const char* const valid_modargs[] = { }; #define DEFAULT_SINK_NAME "alsa_output" -#define DEFAULT_DEVICE "plughw:0,0" +#define DEFAULT_DEVICE "default" static void update_usage(struct userdata *u) { pa_module_set_used(u->module, From 656cf879937440e8764cf9f9429b7b484944dc1e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Sep 2005 00:11:48 +0000 Subject: [PATCH 0350/1514] fix alsa memory leak git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@360 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-alsa-sink.c | 1 + polyp/module-alsa-source.c | 1 + 2 files changed, 2 insertions(+) diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 840fc5364..69db28754 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -204,6 +204,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { m->userdata = u; u->module = m; + snd_config_update_free_global(); if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) { pa_log(__FILE__": Error opening PCM device %s\n", dev); goto fail; diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 67e38a1d9..55abe8e0f 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -195,6 +195,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { m->userdata = u; u->module = m; + snd_config_update_free_global(); if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) < 0) { pa_log(__FILE__": Error opening PCM device %s\n", dev); goto fail; From 794033aa7512f148190cf0ea48b0058dcfe34e32 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 9 Jan 2006 12:37:17 +0000 Subject: [PATCH 0351/1514] fix synchronized clock change git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@425 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 440217e7b..a1a669907 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -414,7 +414,7 @@ static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t c } else { gettimeofday(&now, NULL); - if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) { + if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now) < 0) { /* local and remote seem to have synchronized clocks */ if (o->stream->direction == PA_STREAM_PLAYBACK) From 80ae72ce45dbc23ddc360749924110dcc752491e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 9 Jan 2006 12:38:06 +0000 Subject: [PATCH 0352/1514] improve sync clock change git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@426 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index a1a669907..6a73c608f 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -414,7 +414,7 @@ static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t c } else { gettimeofday(&now, NULL); - if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now) < 0) { + if (pa_timeval_cmp(&local, &remote) <= 0 && pa_timeval_cmp(&remote, &now) <= 0) { /* local and remote seem to have synchronized clocks */ if (o->stream->direction == PA_STREAM_PLAYBACK) From f7a99e90470526bb28cc0c225f96490110094aed Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 10 Jan 2006 17:51:06 +0000 Subject: [PATCH 0353/1514] Merge Pierre's changes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@445 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 18 +- acinclude.m4 | 41 + configure.ac | 454 ++++++---- doc/Makefile.am | 3 +- polyp/Makefile.am | 1582 +++++++++++++++++++--------------- polyp/authkey.c | 10 +- polyp/caps.c | 9 + polyp/cli-command.c | 4 + polyp/client-conf.c | 20 +- polyp/conf-parser.c | 4 + polyp/core.c | 4 +- polyp/cpulimit.c | 20 +- polyp/daemon-conf.c | 20 +- polyp/default.pa.win32 | 43 + polyp/dllmain.c | 46 + polyp/dumpmodules.c | 6 +- polyp/glib-mainloop.c | 2 +- polyp/glib12-mainloop.c | 2 +- polyp/inet_ntop.c | 80 ++ polyp/inet_ntop.h | 12 + polyp/iochannel.c | 30 +- polyp/log.c | 16 +- polyp/main.c | 111 ++- polyp/mainloop-signal.c | 114 ++- polyp/mainloop-test.c | 2 +- polyp/mainloop.c | 33 +- polyp/mcalign-test.c | 2 +- polyp/module-alsa-sink.c | 5 + polyp/module-alsa-source.c | 5 + polyp/module-combine.c | 4 +- polyp/module-esound-sink.c | 2 +- polyp/module-mmkbd-evdev.c | 13 +- polyp/module-null-sink.c | 2 +- polyp/module-protocol-stub.c | 13 +- polyp/module-solaris.c | 436 ++++++++++ polyp/module-tunnel.c | 9 +- polyp/module-waveout.c | 583 +++++++++++++ polyp/module.c | 4 +- polyp/oss-util.c | 2 +- polyp/pacat.c | 4 + polyp/pactl.c | 2 + polyp/paplay.c | 2 + polyp/pdispatch.c | 3 +- polyp/pid.c | 31 +- polyp/poll.c | 190 ++++ polyp/poll.h | 57 ++ polyp/polyplib-context.c | 27 +- polyp/polyplib-internal.h | 1 + polyp/polyplib-stream.c | 20 +- polyp/protocol-esound.c | 16 +- polyp/protocol-native.c | 6 +- polyp/pstream.c | 5 + polyp/random.c | 18 +- polyp/sample-util.c | 2 +- polyp/sample.h | 8 + polyp/scache.c | 37 +- polyp/socket-client.c | 65 +- polyp/socket-client.h | 3 +- polyp/socket-server.c | 49 +- polyp/socket-util.c | 68 +- polyp/tagstruct.c | 73 +- polyp/util.c | 355 +++++++- polyp/util.h | 3 + polyp/winsock.h | 23 + polyp/xmalloc.c | 2 + 65 files changed, 3786 insertions(+), 1050 deletions(-) create mode 100644 polyp/default.pa.win32 create mode 100644 polyp/dllmain.c create mode 100644 polyp/inet_ntop.c create mode 100644 polyp/inet_ntop.h create mode 100644 polyp/module-solaris.c create mode 100644 polyp/module-waveout.c create mode 100644 polyp/poll.c create mode 100644 polyp/poll.h create mode 100644 polyp/winsock.h diff --git a/Makefile.am b/Makefile.am index 7935321da..2cf93c75d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,11 +17,11 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4 -SUBDIRS=polyp doc libltdl +EXTRA_DIST = bootstrap.sh LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4 +SUBDIRS=libltdl polyp doc -MAINTAINERCLEANFILES=README -noinst_DATA = README +MAINTAINERCLEANFILES = +noinst_DATA = pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-browse.pc @@ -36,10 +36,16 @@ pkgconfig_DATA += \ polyplib-glib12-mainloop.pc endif +if USE_LYNX +EXTRA_DIST += README +MAINTAINERCLEANFILES += README +noinst_DATA += README + README: rm -f README $(MAKE) -C doc README cd $(srcdir) && ln -s doc/README README +endif homepage: all dist doxygen test -d $$HOME/homepage/private @@ -49,8 +55,8 @@ homepage: all dist doxygen cp -a doxygen/html/* $$HOME/homepage/private/projects/polypaudio/doxygen cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html -distcleancheck: - @: +#distcleancheck: +# @: doxygen: $(MAKE) -C doxygen doxygen diff --git a/acinclude.m4 b/acinclude.m4 index bedf51c32..02f271b43 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -197,3 +197,44 @@ else fi AC_LANG_RESTORE ])dnl ACX_PTHREAD + +AC_DEFUN([AC_CHECK_DEFINE],[ +AS_VAR_PUSHDEF([ac_var],[ac_cv_defined_$1])dnl +AC_CACHE_CHECK([for $1 defined], ac_var, +AC_TRY_COMPILE([#include <$2>],[ + #ifdef $1 + int ok; + #else + choke me + #endif +],AS_VAR_SET(ac_var, yes),AS_VAR_SET(ac_var, no))) +AS_IF([test AS_VAR_GET(ac_var) != "no"], [$3], [$4])dnl +AS_VAR_POPDEF([ac_var])dnl +]) + +AC_DEFUN([ACX_LIBWRAP], [ +LIBWRAP_LIBS= +saved_LIBS="$LIBS" +LIBS="$LIBS -lwrap" +AC_MSG_CHECKING([for tcpwrap library and headers]) +AC_LINK_IFELSE( +AC_LANG_PROGRAM( +[#include +#include +int allow_severity = LOG_INFO; +int deny_severity = LOG_WARNING;], +[struct request_info *req; +return hosts_access (req);]), +[AC_DEFINE(HAVE_LIBWRAP, [], [Have tcpwrap?]) +LIBWRAP_LIBS="-lwrap" +AC_MSG_RESULT(yes)], +[AC_MSG_RESULT(no)]) +LIBS="$saved_LIBS" +]) + +AC_DEFUN([ACX_LIRC], [ +LIRC_CFLAGS= +LIRC_LIBS= +AC_CHECK_HEADER(lirc/lirc_client.h,[AC_CHECK_LIB(lirc_client,lirc_init,[HAVE_LIRC=1 +LIRC_LIBS=-llirc_client],HAVE_LIRC=0)],HAVE_LIRC=0) +]) diff --git a/configure.ac b/configure.ac index 125413450..e5e03d041 100644 --- a/configure.ac +++ b/configure.ac @@ -35,166 +35,29 @@ if type -p stow > /dev/null && test -d /usr/local/stow ; then ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}" fi -# Checks for programs. +#### Checks for programs. #### + +# CC + AC_PROG_CC - -# libtool stuff -AC_LIBLTDL_INSTALLABLE -AC_SUBST(LTDLINCL) -AC_SUBST(LIBLTDL) -AC_LIBTOOL_DLOPEN -AC_PROG_LIBTOOL -AC_CONFIG_SUBDIRS(libltdl) - -if test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then - AC_MSG_ERROR([[ - - *** Cannot find the libltdl development files. - *** Maybe you need to install the libltdl-dev package. - ]]) -fi - -# Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h syslog.h]) - -ACX_PTHREAD -AC_PATH_XTRA - -HAVE_X11=0 -test "x$no_x" != "xyes" && HAVE_X11=1 -AC_SUBST(HAVE_X11) -AM_CONDITIONAL(HAVE_X11, test "x$no_x" != "xyes") -if test "x$no_x" != "xyes" ; then - AC_DEFINE([HAVE_X11], 1, [Have X11]) -fi - -# Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_TYPE_PID_T -AC_TYPE_SIZE_T -AC_TYPE_OFF_T -AC_HEADER_TIME - -# Checks for library functions. -AC_FUNC_FORK AC_PROG_GCC_TRADITIONAL -AC_FUNC_LSTAT -AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK -AC_FUNC_MALLOC -AC_FUNC_MEMCMP -AC_FUNC_MMAP -AC_FUNC_REALLOC -AC_FUNC_SETPGRP -AC_FUNC_VPRINTF -AC_FUNC_CLOSEDIR_VOID -AC_FUNC_SELECT_ARGTYPES -AC_TYPE_SIGNAL -AC_TYPE_UID_T -AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul strcasecmp putenv strchr strpbrk strdup getgrgid_r getpwuid_r regcomp ftruncate select]) -AC_CHECK_LIB(m, pow) -AC_CHECK_FUNCS(pow) -AC_FUNC_STAT -AC_HEADER_SYS_WAIT -AC_HEADER_DIRENT - -AC_C_BIGENDIAN -AC_FUNC_GETGROUPS - -AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS='']) -AC_SUBST(CAP_LIBS) - -AC_CHECK_HEADERS(sys/capability.h) - -AC_CHECK_FUNCS(setresuid) -AC_CHECK_FUNCS(setreuid) - -PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) -AC_SUBST(LIBSAMPLERATE_CFLAGS) -AC_SUBST(LIBSAMPLERATE_LIBS) - -PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ]) -AC_SUBST(LIBSNDFILE_CFLAGS) -AC_SUBST(LIBSNDFILE_LIBS) - -PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [HAVE_ALSA=1], [HAVE_ALSA=0]) -AC_SUBST(ASOUNDLIB_CFLAGS) -AC_SUBST(ASOUNDLIB_LIBS) -AC_SUBST(HAVE_ALSA) -AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1]) - -PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], HAVE_GLIB20=1, HAVE_GLIB20=0) -AC_SUBST(GLIB20_CFLAGS) -AC_SUBST(GLIB20_LIBS) -AC_SUBST(HAVE_GLIB20) -AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1]) - -PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], HAVE_GLIB12=1, HAVE_GLIB12=0) -AC_SUBST(GLIB12_CFLAGS) -AC_SUBST(GLIB12_LIBS) -AC_SUBST(HAVE_GLIB12) -AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) - -PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], HAVE_HOWL=1, HAVE_HOWL=0) -AC_SUBST(HOWL_CFLAGS) -AC_SUBST(HOWL_LIBS) -AC_SUBST(HAVE_HOWL) -AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1]) - -PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, HAVE_LIBASYNCNS=0) -AC_SUBST(LIBASYNCNS_CFLAGS) -AC_SUBST(LIBASYNCNS_LIBS) -AC_SUBST(HAVE_LIBASYNCNS) -AM_CONDITIONAL([HAVE_LIBASYNCNS], [test "x$HAVE_LIBASYNCNS" = x1]) - -if test "x$HAVE_LIBASYNCNS" != "x0" ; then - AC_DEFINE([HAVE_LIBASYNCNS], 1, [Have libasyncns?]) -fi - -AC_PATH_PROG([M4], [m4 gm4], [no]) -if test "x$M4" = xno ; then - AC_MSG_ERROR([m4 missing]) -fi - -AC_MSG_CHECKING([for tcpwrap library and headers]) -LIBWRAP_LIBS= -saved_LIBS="$LIBS" -LIBS="$LIBS -lwrap" -AC_LINK_IFELSE( -AC_LANG_PROGRAM( -[#include -#include -int allow_severity = LOG_INFO; -int deny_severity = LOG_WARNING;], -[struct request_info *req; -return hosts_access (req);]), -[AC_DEFINE(HAVE_LIBWRAP, [], [Have tcpwrap?]) -LIBWRAP_LIBS="-lwrap" -AC_MSG_RESULT(yes)], -[AC_MSG_RESULT(no)]) -AC_SUBST(LIBWRAP_LIBS) -LIBS="$saved_LIBS" - -LIRC_CFLAGS= -LIRC_LIBS= -AC_CHECK_HEADER(lirc/lirc_client.h,[AC_CHECK_LIB(lirc_client,lirc_init,[HAVE_LIRC=1 -LIRC_LIBS=-llirc_client],HAVE_LIRC=0)],HAVE_LIRC=0) -AC_SUBST(LIRC_CFLAGS) -AC_SUBST(LIRC_LIBS) -AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) - -AC_CHECK_HEADER(linux/input.h,HAVE_EVDEV=1,HAVE_EVDEV=0) -AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = x1]) # If using GCC specify some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -W -Wall -pedantic" AC_LANG_CONFTEST([int main() {}]) - $CC -c conftest.c -std=c99 -Wno-unused-parameter $CFLAGS > /dev/null 2> /dev/null && CFLAGS="$CFLAGS -std=c99 -Wno-unused-parameter" + $CC -c conftest.c -std=gnu9x -Wno-unused-parameter $CFLAGS > /dev/null 2> /dev/null && CFLAGS="$CFLAGS -std=gnu9x -Wno-unused-parameter" rm -f conftest.o fi +# M4 + +AC_PATH_PROG([M4], [m4 gm4], [no]) +if test "x$M4" = xno ; then + AC_MSG_ERROR([m4 missing]) +fi + # LYNX documentation generation AC_ARG_ENABLE(lynx, AC_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation), @@ -212,9 +75,296 @@ if test x$lynx = xyes ; then fi fi -AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes]) +AM_CONDITIONAL([USE_LYNX], [test "x$have_lynx" = xyes]) -AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false) +#### libtool stuff #### -AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-browse.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h doc/FAQ.html]) +AC_LTDL_ENABLE_INSTALL +AC_LIBLTDL_INSTALLABLE +AC_SUBST(LTDLINCL) +AC_SUBST(LIBLTDL) +AC_LIBTOOL_DLOPEN +AC_LIBTOOL_WIN32_DLL +AC_PROG_LIBTOOL +AC_CONFIG_SUBDIRS(libltdl) + +if test "x$enable_ltdl_install" = "xno" && test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then + AC_MSG_ERROR([[ + + *** Cannot find the libltdl development files. + *** Maybe you need to install the libltdl-dev package. + ]]) +fi + +#### Determine build environment #### + +os_is_win32=0 + +case "$host_os" in + mingw*) + AC_DEFINE([OS_IS_WIN32], 1, [Build target is Windows.]) + os_is_win32=1 + ;; + esac + +AM_CONDITIONAL(OS_IS_WIN32, test "x$os_is_win32" = "x1") + +################################### +# Basic environment checks # +################################### + +#### Checks for header files. #### + +# ISO +AC_HEADER_STDC + +# POSIX +AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \ + netinet/in_systm.h netinet/ip.h netinet/tcp.h pwd.h sched.h \ + sys/resource.h sys/select.h sys/socket.h sys/wait.h \ + syslog.h]) +AC_CHECK_HEADERS([regex.h], [HAVE_REGEX=1], [HAVE_REGEX=0]) +AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0]) + +AM_CONDITIONAL(HAVE_REGEX, test "x$HAVE_REGEX" = "x1") +AM_CONDITIONAL(HAVE_AF_UNIX, test "x$HAVE_AF_UNIX" = "x1") + +# XPG4-UNIX +AC_CHECK_HEADERS([sys/poll.h]) + +# Linux +AC_CHECK_HEADERS([linux/input.h], [HAVE_EVDEV=1], [HAVE_EVDEV=0]) + +AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = "x1"]) + +# Windows +AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h]) + +# Other +AC_CHECK_HEADERS([sys/ioctl.h]) + +#### Typdefs, structures, etc. #### + +AC_C_CONST +AC_C_BIGENDIAN +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_CHECK_TYPES(ssize_t, , [AC_DEFINE([ssize_t], [signed long], + [Define ssize_t if it is not done by the standard libs.])]) +AC_TYPE_OFF_T +AC_TYPE_SIGNAL +AC_TYPE_UID_T + +AC_CHECK_DEFINE([SIGXCPU], [signal.h], [HAVE_SIGXCPU=1], [HAVE_SIGXCPU=0]) +AM_CONDITIONAL(HAVE_SIGXCPU, test "x$HAVE_SIGXCPU" = "x1") + +# Solaris lacks this +AC_CHECK_DEFINE([INADDR_NONE], [netinet/in.h], [], + [AC_DEFINE([INADDR_NONE], [0xffffffff], [Define INADDR_NONE if not found in ])]) + +#### Check for libs #### + +# ISO +AC_CHECK_LIB([m], [pow]) + +# POSIX +AC_CHECK_LIB([rt], [sched_setscheduler]) + +# BSD +AC_CHECK_LIB([socket], [connect]) + +# Non-standard + +# This magic is needed so we do not needlessly add static libs to the win32 +# build, disabling its ability to make dlls. +AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])]) + +#### Check for functions #### + +# POSIX +AC_FUNC_FORK +AC_FUNC_GETGROUPS +AC_FUNC_SELECT_ARGTYPES +AC_CHECK_FUNCS([getaddrinfo getgrgid_r getpwuid_r gettimeofday getuid \ + inet_ntop nanosleep setpgid setsid sigaction sleep]) +AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0]) + +AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1") + +# X/OPEN +AC_CHECK_FUNCS([readlink]) + +# SUSv2 +AC_CHECK_FUNCS([ctime_r usleep]) + +# BSD +AC_CHECK_FUNCS([lstat]) + +# Non-standard + +AC_CHECK_FUNCS(setresuid) +AC_CHECK_FUNCS(setreuid) + +#### POSIX threads #### + +ACX_PTHREAD + +################################### +# External libraries # +################################### + +#### X11 (optional) #### + +HAVE_X11=0 + +# The macro tests the host, not the build target +if test "x$os_is_win32" != "x1" ; then + AC_PATH_XTRA + test "x$no_x" != "xyes" && HAVE_X11=1 +fi + +AC_SUBST(HAVE_X11) +AM_CONDITIONAL(HAVE_X11, test "x$HAVE_X11" = "x1") +if test "x$HAVE_X11" = "x1" ; then + AC_DEFINE([HAVE_X11], 1, [Have X11]) +fi + +#### Capabilities (optional) #### + +CAP_LIBS='' + +AC_ARG_WITH( + [caps], + AC_HELP_STRING([--without-caps],[Omit support for POSIX capabilities.])) + +if test "x${with_caps}" != "xno"; then + AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS='']) + AC_CHECK_HEADERS([sys/capability.h]) +fi +AC_SUBST(CAP_LIBS) + +#### Sample rate conversion #### + +PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) +AC_SUBST(LIBSAMPLERATE_CFLAGS) +AC_SUBST(LIBSAMPLERATE_LIBS) + +#### Sound file #### + +PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ]) +AC_SUBST(LIBSNDFILE_CFLAGS) +AC_SUBST(LIBSNDFILE_LIBS) + +#### OSS support (optional) #### + +AC_CHECK_HEADERS([sys/soundcard.h], [HAVE_OSS=1], [HAVE_OSS=0]) +AC_SUBST(HAVE_OSS) +AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1]) + +#### ALSA support (optional) #### + +PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [HAVE_ALSA=1], [HAVE_ALSA=0]) +AC_SUBST(ASOUNDLIB_CFLAGS) +AC_SUBST(ASOUNDLIB_LIBS) +AC_SUBST(HAVE_ALSA) +AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1]) + +#### Solaris audio support (optional) #### + +AC_CHECK_HEADERS([sys/audio.h], [HAVE_SOLARIS=1], [HAVE_SOLARIS=0]) +AC_SUBST(HAVE_SOLARIS) +AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1]) + +#### GLib 2 support (optional) #### + +PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], HAVE_GLIB20=1, HAVE_GLIB20=0) +AC_SUBST(GLIB20_CFLAGS) +AC_SUBST(GLIB20_LIBS) +AC_SUBST(HAVE_GLIB20) +AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1]) + +#### GLib 1 support (optional) #### + +PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], HAVE_GLIB12=1, HAVE_GLIB12=0) +AC_SUBST(GLIB12_CFLAGS) +AC_SUBST(GLIB12_LIBS) +AC_SUBST(HAVE_GLIB12) +AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) + +#### Howl support (optional) #### + +PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], HAVE_HOWL=1, HAVE_HOWL=0) +AC_SUBST(HOWL_CFLAGS) +AC_SUBST(HOWL_LIBS) +AC_SUBST(HAVE_HOWL) +AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1]) + +#### Async DNS support (optional) #### + +PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, HAVE_LIBASYNCNS=0) +AC_SUBST(LIBASYNCNS_CFLAGS) +AC_SUBST(LIBASYNCNS_LIBS) +AC_SUBST(HAVE_LIBASYNCNS) +AM_CONDITIONAL([HAVE_LIBASYNCNS], [test "x$HAVE_LIBASYNCNS" = x1]) + +if test "x$HAVE_LIBASYNCNS" != "x0" ; then + AC_DEFINE([HAVE_LIBASYNCNS], 1, [Have libasyncns?]) +fi + +#### TCP wrappers (optional) #### + +ACX_LIBWRAP +AC_SUBST(LIBWRAP_LIBS) + +#### LIRC support (optional) #### + +ACX_LIRC +AC_SUBST(LIRC_CFLAGS) +AC_SUBST(LIRC_LIBS) +AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) + +################################### +# Output # +################################### + +AC_ARG_ENABLE( + [static-bins], + AC_HELP_STRING([--enable-static-bins],[Statically link executables.]), + [STATIC_BINS=1], [STATIC_BINS=0]) +AM_CONDITIONAL([STATIC_BINS], [test "x$STATIC_BINS" = "x1"]) + +AC_ARG_WITH( + [preopen-mods], + AC_HELP_STRING([--with-preopen-mods],[Modules to preopen in daemon (default: all).]), + [PREOPEN_MODS=$withval], [PREOPEN_MODS="all"]) +AM_CONDITIONAL([PREOPEN_MODS], [test "x$PREOPEN_MODS" != "xall"]) +if test "x$PREOPEN_MODS" != "xall" ; then + tmpLIBS="" + for mod in $PREOPEN_MODS; do + tmpLIBS="$tmpLIBS module-$mod.la" + done + PREOPEN_MODS="$tmpLIBS" + AC_SUBST(PREOPEN_MODS) +fi + +AC_CONFIG_FILES([ +Makefile +polyp/Makefile +polyplib.pc +polyplib-simple.pc +polyplib-mainloop.pc +polyplib-browse.pc +polyplib-error.pc +polyplib-glib-mainloop.pc +polyplib-glib12-mainloop.pc +doc/Makefile +doc/README.html +doc/cli.html +doc/daemon.html +doc/modules.html +doxygen/Makefile +doxygen/doxygen.conf +polyp/polyplib-version.h +doc/FAQ.html +]) AC_OUTPUT diff --git a/doc/Makefile.am b/doc/Makefile.am index fff065510..c68c00f56 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -16,7 +16,7 @@ # along with polypaudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -noinst_DATA = README.html cli.html modules.html daemon.html README +noinst_DATA = README.html cli.html modules.html daemon.html EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in todo FAQ.html.in MAINTAINERCLEANFILES = README.html cli.html modules.html daemon.html FAQ.html @@ -26,6 +26,7 @@ if USE_LYNX README: README.html lynx --dump $^ | sed 's,file://localhost/.*/doc/README.html,README,' > $@ +noinst_DATA += README CLEANFILES += README endif diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 389cb0d3b..22e8da3de 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -17,743 +17,387 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. + +################################### +# Extra directories # +################################### + polypincludedir=$(includedir)/polyp polypconfdir=$(sysconfdir)/polypaudio modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ -AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\" -AM_CFLAGS+=-DDEFAULT_CONFIG_DIR=\"$(polypconfdir)\" -AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\" +################################### +# Defines # +################################### + +POLYPAUDIO_BINARY=$(bindir)/polypaudio$(EXEEXT) +if OS_IS_WIN32 +DEFAULT_CONFIG_DIR=%POLYP_ROOT% +else +DEFAULT_CONFIG_DIR=$(polypconfdir) +endif + +################################### +# Compiler/linker flags # +################################### + +AM_CFLAGS = -D_GNU_SOURCE -I$(top_srcdir) +AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS +AM_CFLAGS += $(LTDLINCL) +AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) +AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" +AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" +AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" # This cool debug trap works on i386/gcc only -AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")' +AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")' -AM_LIBADD=$(PTHREAD_LIBS) -lm -AM_LDADD=$(PTHREAD_LIBS) -lm +AM_LIBADD = $(PTHREAD_LIBS) +AM_LDADD = $(PTHREAD_LIBS) -EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in module-defs.h.m4 -bin_PROGRAMS = \ - polypaudio \ +# Only required on some platforms but defined for all to avoid errors +AM_LDFLAGS = -no-undefined + +if STATIC_BINS +BINLDFLAGS = -static +endif + +if OS_IS_WIN32 +AM_LDFLAGS+=-Wl,--export-all-symbols +WINSOCK_LIBS=-lwsock32 -lws2_32 -lwininet +endif + +################################### +# Extra files # +################################### + +EXTRA_DIST = \ + client.conf.in \ + daemon.conf.in \ + default.pa.in \ + depmod.py \ + esdcompat.sh.in \ + module-defs.h.m4 + +polypconf_DATA = default.pa daemon.conf client.conf + +BUILT_SOURCES = polyplib-version.h + +################################### +# Main daemon # +################################### + +bin_PROGRAMS = polypaudio + +polypaudio_SOURCES = \ + caps.h caps.c \ + cmdline.c cmdline.h \ + cpulimit.c cpulimit.h \ + conf-parser.h conf-parser.c \ + daemon-conf.c daemon-conf.h \ + dumpmodules.c dumpmodules.h \ + gcc-printf.h \ + main.c \ + pid.c pid.h + +polypaudio_CFLAGS = $(AM_CFLAGS) +polypaudio_CPPFLAGS = $(AM_CPPFLAGS) +polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \ + $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) +polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f)) + +if PREOPEN_MODS +PREOPEN_LIBS = $(PREOPEN_MODS) +else +PREOPEN_LIBS = $(modlib_LTLIBRARIES) +endif + +################################### +# Utility programs # +################################### + +bin_PROGRAMS += \ pacat \ pactl \ - paplay \ - pacmd + paplay + +if HAVE_AF_UNIX +bin_PROGRAMS += pacmd +endif + +if HAVE_X11 +bin_PROGRAMS += pax11publish +endif + +if HAVE_HOWL +bin_PROGRAMS += pabrowse +endif bin_SCRIPTS = esdcompat.sh +pacat_SOURCES = pacat.c +pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +pacat_CFLAGS = $(AM_CFLAGS) +pacat_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +paplay_SOURCES = paplay.c +paplay_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) +paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) +paplay_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +pactl_SOURCES = pactl.c +pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) +pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) +pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +pacmd_SOURCES = pacmd.c util.c util.h xmalloc.c xmalloc.h log.c log.h pid.c pid.h +pacmd_CFLAGS = $(AM_CFLAGS) +pacmd_LDADD = $(AM_LDADD) +pacmd_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +pax11publish_SOURCES = pax11publish.c util.c util.h xmalloc.c xmalloc.h log.c log.h authkey.c authkey.h client-conf.c client-conf.h conf-parser.c conf-parser.h x11prop.c x11prop.h random.c random.h +pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +pabrowse_SOURCES = pabrowse.c +pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la +pabrowse_CFLAGS = $(AM_CFLAGS) +pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +################################### +# Test programs # +################################### + noinst_PROGRAMS = \ mainloop-test \ + mcalign-test \ pacat-simple \ parec-simple \ - cpulimit-test \ - cpulimit-test2 \ - voltest \ strlist-test \ - mcalign-test + voltest -polypconf_DATA=default.pa daemon.conf client.conf +if HAVE_SIGXCPU +noinst_PROGRAMS += \ + cpulimit-test \ + cpulimit-test2 +endif -BUILT_SOURCES=polyplib-version.h +if HAVE_GLIB20 +noinst_PROGRAMS += \ + mainloop-test-glib +endif -polypinclude_HEADERS= \ +if HAVE_GLIB12 +noinst_PROGRAMS += \ + mainloop-test-glib12 +endif + +mainloop_test_SOURCES = mainloop-test.c +mainloop_test_CFLAGS = $(AM_CFLAGS) +mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-@PA_MAJORMINOR@.la +mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +mcalign_test_SOURCES = mcalign-test.c util.c util.h xmalloc.c xmalloc.h log.c log.h mcalign.c mcalign.h memchunk.c memchunk.h memblock.c memblock.h +mcalign_test_CFLAGS = $(AM_CFLAGS) +mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) +mcalign_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +pacat_simple_SOURCES = pacat-simple.c +pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +pacat_simple_CFLAGS = $(AM_CFLAGS) +pacat_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +parec_simple_SOURCES = parec-simple.c +parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +parec_simple_CFLAGS = $(AM_CFLAGS) +parec_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +strlist_test_SOURCES = strlist-test.c strlist.c strlist.h strbuf.c strbuf.h util.c util.h xmalloc.c xmalloc.h log.c log.h +strlist_test_CFLAGS = $(AM_CFLAGS) +strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) +strlist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +voltest_SOURCES = voltest.c sample.c +voltest_CFLAGS = $(AM_CFLAGS) +voltest_LDADD = $(AM_LDADD) +voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h +cpulimit_test_CFLAGS = $(AM_CFLAGS) +cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la +cpulimit_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h +cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 +cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la +cpulimit_test2_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) +mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP +mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib-@PA_MAJORMINOR@.la +mainloop_test_glib_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) +mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP +mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la +mainloop_test_glib12_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +################################### +# Client library # +################################### + +polypinclude_HEADERS = \ + cdecl.h \ + glib-mainloop.h \ + mainloop.h \ + mainloop-api.h \ + mainloop-signal.h \ polyplib.h \ - polyplib-def.h \ - polyplib-simple.h \ - polyplib-error.h \ - polyplib-stream.h \ polyplib-context.h \ + polyplib-def.h \ + polyplib-error.h \ polyplib-introspect.h \ - polyplib-subscribe.h \ polyplib-operation.h \ polyplib-scache.h \ + polyplib-simple.h \ + polyplib-stream.h \ + polyplib-subscribe.h \ polyplib-version.h \ - cdecl.h \ - mainloop-api.h \ - mainloop.h \ - mainloop-signal.h \ sample.h \ - glib-mainloop.h \ typeid.h -### Warning! Due to an obscure bug in libtool/automake it is required -### that the libraries in modlib_LTLIBRARIES are specified in-order, -### i.e. libraries near the end of the list depend on libraries near -### the head, and not the other way! +if HAVE_HOWL +polypinclude_HEADERS += \ + polyplib-browser.h +endif -modlib_LTLIBRARIES= \ - libsocket-util.la \ - libiochannel.la \ - libsocket-server.la \ - libsocket-client.la \ - libparseaddr.la \ - libpacket.la \ - libpstream.la \ - liboss-util.la \ - libioline.la \ - libcli.la \ - libprotocol-cli.la \ - libtagstruct.la \ - libpstream-util.la \ - libpdispatch.la \ - libauthkey.la \ - libauthkey-prop.la \ - libstrlist.la \ - libprotocol-simple.la \ - libprotocol-esound.la \ - libprotocol-native.la \ - libprotocol-http.la \ - module-cli.la \ - module-cli-protocol-tcp.la \ - module-cli-protocol-tcp6.la \ - module-cli-protocol-unix.la \ - module-pipe-sink.la \ - module-pipe-source.la \ - module-oss.la \ - module-oss-mmap.la \ - module-simple-protocol-tcp.la \ - module-simple-protocol-tcp6.la \ - module-simple-protocol-unix.la \ - module-esound-protocol-tcp.la \ - module-esound-protocol-tcp6.la \ - module-esound-protocol-unix.la \ - module-native-protocol-tcp.la \ - module-native-protocol-tcp6.la \ - module-native-protocol-unix.la \ - module-native-protocol-fd.la \ - module-sine.la \ - module-combine.la \ - module-esound-compat-spawnfd.la \ - module-esound-compat-spawnpid.la \ - module-match.la \ - module-tunnel-sink.la \ - module-tunnel-source.la \ - module-null-sink.la \ - module-esound-sink.la \ - module-http-protocol-tcp.la \ - module-http-protocol-tcp6.la \ - module-http-protocol-unix.la - -SYMDEF_FILES= \ - module-cli-symdef.h \ - module-cli-protocol-tcp-symdef.h \ - module-cli-protocol-tcp6-symdef.h \ - module-cli-protocol-unix-symdef.h \ - module-pipe-sink-symdef.h \ - module-pipe-source-symdef.h \ - module-oss-symdef.h \ - module-oss-mmap-symdef.h \ - module-simple-protocol-tcp-symdef.h \ - module-simple-protocol-tcp6-symdef.h \ - module-simple-protocol-unix-symdef.h \ - module-esound-protocol-tcp-symdef.h \ - module-esound-protocol-tcp6-symdef.h \ - module-esound-protocol-unix-symdef.h \ - module-native-protocol-tcp-symdef.h \ - module-native-protocol-tcp6-symdef.h \ - module-native-protocol-unix-symdef.h \ - module-native-protocol-fd-symdef.h \ - module-sine-symdef.h \ - module-combine-symdef.h \ - module-esound-compat-spawnfd-symdef.h \ - module-esound-compat-spawnpid-symdef.h \ - module-match-symdef.h \ - module-tunnel-sink-symdef.h \ - module-tunnel-source-symdef.h \ - module-null-sink-symdef.h \ - module-esound-sink-symdef.h \ - module-zeroconf-publish-symdef.h \ - module-lirc-symdef.h \ - module-mmkbd-evdev-symdef.h \ - module-http-protocol-tcp-symdef.h \ - module-http-protocol-tcp6-symdef.h \ - module-http-protocol-unix-symdef.h - -EXTRA_DIST+=$(SYMDEF_FILES) -BUILT_SOURCES+=$(SYMDEF_FILES) - -lib_LTLIBRARIES= \ +lib_LTLIBRARIES = \ libpolyp-@PA_MAJORMINOR@.la \ libpolyp-error-@PA_MAJORMINOR@.la \ libpolyp-mainloop-@PA_MAJORMINOR@.la \ libpolyp-simple-@PA_MAJORMINOR@.la -polypaudio_SOURCES = idxset.c idxset.h \ - queue.c queue.h \ - strbuf.c strbuf.h \ - main.c \ - mainloop.c mainloop.h \ - memblock.c memblock.h \ - sample.c sample.h \ - sample-util.c sample-util.h \ - memblockq.c memblockq.h \ - client.c client.h \ - core.c core.h \ - source-output.c source-output.h \ - sink-input.c sink-input.h \ - source.c source.h \ - sink.c sink.h \ - module.c module.h \ - mainloop-signal.c mainloop-signal.h \ - mainloop-api.c mainloop-api.h \ - util.c util.h \ - hashmap.c hashmap.h \ - namereg.c namereg.h \ - sconv.c sconv.h \ - resampler.c resampler.h \ - endianmacros.h \ - memchunk.c memchunk.h \ - sconv-s16le.c sconv-s16le.h \ - sconv-s16be.c sconv-s16be.h \ - sioman.c sioman.h \ - modargs.c modargs.h \ - cmdline.c cmdline.h \ - cli-command.c cli-command.h \ - cli-text.c cli-text.h \ - tokenizer.c tokenizer.h \ - dynarray.c dynarray.h \ - scache.c scache.h \ - sound-file.c sound-file.h \ - play-memchunk.c play-memchunk.h \ - autoload.c autoload.h \ - xmalloc.c xmalloc.h \ - subscribe.h subscribe.c \ - sound-file-stream.c sound-file-stream.h \ - cpulimit.c cpulimit.h \ - log.c log.h \ - gcc-printf.h \ - modinfo.c modinfo.h \ - daemon-conf.c daemon-conf.h \ - dumpmodules.c dumpmodules.h \ - conf-parser.h conf-parser.c \ - caps.h caps.c \ - props.h props.c \ - mcalign.c mcalign.h \ - g711.c g711.h \ - pid.c pid.h \ - random.c random.h \ - typeid.c typeid.h +if HAVE_HOWL +lib_LTLIBRARIES += \ + libpolyp-browse-@PA_MAJORMINOR@.la +endif -polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -polypaudio_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL) -polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) -polypaudio_LDFLAGS= $(AM_LDFLAGS) -export-dynamic -dlopen force -#q-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f)) +if HAVE_GLIB20 +lib_LTLIBRARIES += \ + libpolyp-mainloop-glib-@PA_MAJORMINOR@.la +endif -libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h -libprotocol_simple_la_LDFLAGS = -avoid-version -libprotocol_simple_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la +if HAVE_GLIB12 +lib_LTLIBRARIES += \ + libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la +endif -libsocket_server_la_SOURCES = socket-server.c socket-server.h -libsocket_server_la_LDFLAGS = -avoid-version -libsocket_server_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) - -libsocket_client_la_SOURCES = socket-client.c socket-client.h -libsocket_client_la_LDFLAGS = -avoid-version -libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS) -libsocket_client_la_CFLAGS = $(AM_CFLAGS) $(LIBASYNCNS_CFLAGS) - -libparseaddr_la_SOURCES = parseaddr.c parseaddr.h -libparseaddr_la_LDFLAGS = -avoid-version - -libpstream_la_SOURCES = pstream.c pstream.h -libpstream_la_LDFLAGS = -avoid-version -libpstream_la_LIBADD = $(AM_LIBADD) libpacket.la libiochannel.la - -libpstream_util_la_SOURCES = pstream-util.c pstream-util.h -libpstream_util_la_LDFLAGS = -avoid-version -libpstream_util_la_LIBADD = $(AM_LIBADD) libpacket.la libpstream.la libtagstruct.la - -libpdispatch_la_SOURCES = pdispatch.c pdispatch.h -libpdispatch_la_LDFLAGS = -avoid-version -libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la - -libiochannel_la_SOURCES = iochannel.c iochannel.h -libiochannel_la_LDFLAGS = -avoid-version -libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la - -libpacket_la_SOURCES = packet.c packet.h -libpacket_la_LDFLAGS = -avoid-version - -liboss_util_la_SOURCES = oss-util.c oss-util.h -liboss_util_la_LDFLAGS = -avoid-version - -libioline_la_SOURCES = ioline.c ioline.h -libioline_la_LDFLAGS = -avoid-version -libioline_la_LIBADD = $(AM_LIBADD) libiochannel.la - -libcli_la_SOURCES = cli.c cli.h -libcli_la_LDFLAGS = -avoid-version -libcli_la_LIBADD = $(AM_LIBADD) libiochannel.la libioline.la - -libstrlist_la_SOURCES = strlist.c strlist.h -libstrlist_la_LDFLAGS = -avoid-version -libstrlist_la_LIBADD = $(AM_LIBADD) - -libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h -libprotocol_cli_la_LDFLAGS = -avoid-version -libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la - -libprotocol_http_la_SOURCES = protocol-http.c protocol-http.h -libprotocol_http_la_LDFLAGS = -avoid-version -libprotocol_http_la_LIBADD = $(AM_LIBADD) libsocket-server.la libioline.la - -libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h native-common.h -libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la - -libtagstruct_la_SOURCES = tagstruct.c tagstruct.h -libtagstruct_la_LDFLAGS = -avoid-version - -libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h esound.h -libprotocol_esound_la_LDFLAGS = -avoid-version -libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la - -libauthkey_la_SOURCES = authkey.c authkey.h -libauthkey_la_LDFLAGS = -avoid-version - -libauthkey_prop_la_SOURCES = authkey-prop.c authkey-prop.h -libauthkey_prop_la_LDFLAGS = -avoid-version - -libsocket_util_la_SOURCES = socket-util.c socket-util.h -libsocket_util_la_LDFLAGS = -avoid-version - -module_simple_protocol_tcp_la_SOURCES = module-protocol-stub.c -module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) -module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-simple.la libsocket-server.la - -module_simple_protocol_tcp6_la_SOURCES = module-protocol-stub.c -module_simple_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) -module_simple_protocol_tcp6_la_LDFLAGS = -module -avoid-version -module_simple_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-simple.la libsocket-server.la - -module_simple_protocol_unix_la_SOURCES = module-protocol-stub.c -module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) -module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version -module_simple_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-simple.la libsocket-server.la libsocket-util.la - -module_cli_protocol_tcp_la_SOURCES = module-protocol-stub.c -module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) -module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la - -module_cli_protocol_tcp6_la_SOURCES = module-protocol-stub.c -module_cli_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) -module_cli_protocol_tcp6_la_LDFLAGS = -module -avoid-version -module_cli_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la - -module_cli_protocol_unix_la_SOURCES = module-protocol-stub.c -module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) -module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version -module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la libsocket-util.la - -module_http_protocol_tcp_la_SOURCES = module-protocol-stub.c -module_http_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) -module_http_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-http.la libsocket-server.la - -module_http_protocol_tcp6_la_SOURCES = module-protocol-stub.c -module_http_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) -module_http_protocol_tcp6_la_LDFLAGS = -module -avoid-version -module_http_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-http.la libsocket-server.la - -module_http_protocol_unix_la_SOURCES = module-protocol-stub.c -module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) -module_http_protocol_unix_la_LDFLAGS = -module -avoid-version -module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-http.la libsocket-server.la libsocket-util.la - -module_native_protocol_tcp_la_SOURCES = module-protocol-stub.c -module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) -module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la - -module_native_protocol_tcp6_la_SOURCES = module-protocol-stub.c -module_native_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) -module_native_protocol_tcp6_la_LDFLAGS = -module -avoid-version -module_native_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la - -module_native_protocol_unix_la_SOURCES = module-protocol-stub.c -module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) -module_native_protocol_unix_la_LDFLAGS = -module -avoid-version -module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la libsocket-util.la - -module_native_protocol_fd_la_SOURCES = module-native-protocol-fd.c -module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS) -module_native_protocol_fd_la_LDFLAGS = -module -avoid-version -module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la libsocket-util.la - -module_esound_protocol_tcp_la_SOURCES = module-protocol-stub.c -module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) -module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-esound.la libsocket-server.la - -module_esound_protocol_tcp6_la_SOURCES = module-protocol-stub.c -module_esound_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) -module_esound_protocol_tcp6_la_LDFLAGS = -module -avoid-version -module_esound_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-esound.la libsocket-server.la - -module_esound_protocol_unix_la_SOURCES = module-protocol-stub.c -module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) -module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version -module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-esound.la libsocket-server.la libsocket-util.la - -module_pipe_sink_la_SOURCES = module-pipe-sink.c -module_pipe_sink_la_LDFLAGS = -module -avoid-version -module_pipe_sink_la_LIBADD = $(AM_LIBADD) libiochannel.la - -module_pipe_source_la_SOURCES = module-pipe-source.c -module_pipe_source_la_LDFLAGS = -module -avoid-version -module_pipe_source_la_LIBADD = $(AM_LIBADD) libiochannel.la - -module_oss_la_SOURCES = module-oss.c -module_oss_la_LDFLAGS = -module -avoid-version -module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la - -module_oss_mmap_la_SOURCES = module-oss-mmap.c -module_oss_mmap_la_LDFLAGS = -module -avoid-version -module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la - -module_cli_la_SOURCES = module-cli.c -module_cli_la_LDFLAGS = -module -avoid-version -module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la - -module_sine_la_SOURCES = module-sine.c -module_sine_la_LDFLAGS = -module -avoid-version -module_sine_la_LIBADD = $(AM_LIBADD) - -module_combine_la_SOURCES = module-combine.c -module_combine_la_LDFLAGS = -module -avoid-version -module_combine_la_LIBADD = $(AM_LIBADD) - -module_null_sink_la_SOURCES = module-null-sink.c -module_null_sink_la_LDFLAGS = -module -avoid-version -module_null_sink_la_LIBADD = $(AM_LIBADD) - -module_match_la_SOURCES = module-match.c -module_match_la_LDFLAGS = -module -avoid-version -module_match_la_LIBADD = $(AM_LIBADD) - -module_tunnel_sink_la_SOURCES = module-tunnel.c -module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) -module_tunnel_sink_la_LDFLAGS = -module -avoid-version -module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la - -module_tunnel_source_la_SOURCES = module-tunnel.c -module_tunnel_source_la_LDFLAGS = -module -avoid-version -module_tunnel_source_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la - -module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c -module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version -module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) - -module_esound_compat_spawnpid_la_SOURCES = module-esound-compat-spawnpid.c -module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version -module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) - -module_esound_sink_la_SOURCES = module-esound-sink.c -module_esound_sink_la_LDFLAGS = -module -avoid-version -module_esound_sink_la_LIBADD = $(AM_LIBADD) libsocket-client.la libauthkey.la - -libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \ - polyplib-def.h \ - tagstruct.c tagstruct.h \ - iochannel.c iochannel.h \ - pstream.c pstream.h \ - pstream-util.c pstream-util.h \ - pdispatch.c pdispatch.h \ - mainloop-api.c mainloop-api.h \ - idxset.c idxset.h \ - util.c util.h \ - memblock.c memblock.h \ - socket-client.c socket-client.h \ - parseaddr.c parseaddr.h \ - packet.c packet.h \ - queue.c queue.h \ - dynarray.c dynarray.h \ - memchunk.c memchunk.h \ +libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ authkey.c authkey.h \ - socket-util.c socket-util.h \ - native-common.h \ - sample.c sample.h \ - xmalloc.c xmalloc.h \ - polyplib-operation.c polyplib-operation.h \ - polyplib-context.c polyplib-context.h \ - polyplib-stream.c polyplib-stream.h \ - polyplib-introspect.c polyplib-introspect.h \ - polyplib-scache.c polyplib-scache.h \ - polyplib-subscribe.c polyplib-subscribe.h \ - polyplib-internal.h \ cdecl.h \ - llist.h \ - log.c log.h \ - gcc-printf.h \ client-conf.c client-conf.h \ conf-parser.c conf-parser.h \ - strlist.c strlist.h \ - strbuf.c strbuf.h \ + dllmain.c \ + dynarray.c dynarray.h \ + gcc-printf.h \ + idxset.c idxset.h \ + iochannel.c iochannel.h \ + llist.h \ + log.c log.h \ + mainloop-api.c mainloop-api.h \ mcalign.c mcalign.h \ + memblock.c memblock.h \ + memchunk.c memchunk.h \ + native-common.h \ + packet.c packet.h \ + parseaddr.c parseaddr.h \ + pdispatch.c pdispatch.h \ + polyplib.h \ + polyplib-context.c polyplib-context.h \ + polyplib-def.h \ + polyplib-internal.h \ + polyplib-introspect.c polyplib-introspect.h \ + polyplib-operation.c polyplib-operation.h \ + polyplib-scache.c polyplib-scache.h \ + polyplib-stream.c polyplib-stream.h \ + polyplib-subscribe.c polyplib-subscribe.h \ + pstream.c pstream.h \ + pstream-util.c pstream-util.h \ + queue.c queue.h \ + random.c random.h \ + sample.c sample.h \ + socket-client.c socket-client.h \ + socket-util.c socket-util.h \ + strbuf.c strbuf.h \ + strlist.c strlist.h \ + tagstruct.c tagstruct.h \ typeid.c typeid.h \ - random.c random.h + util.c util.h \ + winsock.h \ + xmalloc.c xmalloc.h + +if HAVE_X11 +libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ + client-conf-x11.c client-conf-x11.h \ + x11prop.c x11prop.h +endif libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) - -libpolyp_mainloop_@PA_MAJORMINOR@_la_SOURCES = mainloop-api.h mainloop-api.c \ - mainloop.c mainloop.h \ - mainloop-signal.c mainloop-signal.h -libpolyp_mainloop_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) -libpolyp_mainloop_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la -libpolyp_mainloop_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 - -libpolyp_error_@PA_MAJORMINOR@_la_SOURCES = polyplib-error.c polyplib-error.h -libpolyp_error_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) -libpolyp_error_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la -libpolyp_error_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 - -libpolyp_simple_@PA_MAJORMINOR@_la_SOURCES = polyplib-simple.c polyplib-simple.h -libpolyp_simple_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) -libpolyp_simple_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la -libpolyp_simple_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 - -pacat_SOURCES = pacat.c -pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la -pacat_CFLAGS = $(AM_CFLAGS) - -paplay_SOURCES = paplay.c -paplay_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) -paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) - -pactl_SOURCES = pactl.c -pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) -pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) - -pacat_simple_SOURCES = pacat-simple.c -pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la -pacat_simple_CFLAGS = $(AM_CFLAGS) - -parec_simple_SOURCES = parec-simple.c -parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la -parec_simple_CFLAGS = $(AM_CFLAGS) - -mainloop_test_SOURCES = mainloop-test.c -mainloop_test_CFLAGS = $(AM_CFLAGS) -mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-@PA_MAJORMINOR@.la - -voltest_SOURCES = voltest.c sample.c -voltest_CFLAGS = $(AM_CFLAGS) -voltest_LDADD = $(AM_LDADD) - -strlist_test_SOURCES = strlist-test.c strlist.c strlist.h strbuf.c strbuf.h util.c util.h xmalloc.c xmalloc.h log.c log.h -strlist_test_CFLAGS = $(AM_CFLAGS) -strlist_test_LDADD = $(AM_LDADD) - -mcalign_test_SOURCES = mcalign-test.c util.c util.h xmalloc.c xmalloc.h log.c log.h mcalign.c mcalign.h memchunk.c memchunk.h memblock.c memblock.h -mcalign_test_CFLAGS = $(AM_CFLAGS) -mcalign_test_LDADD = $(AM_LDADD) - -pacmd_SOURCES = pacmd.c util.c util.h xmalloc.c xmalloc.h log.c log.h pid.c pid.h -pacmd_CFLAGS = $(AM_CFLAGS) -pacmd_LDADD = $(AM_LDADD) - -cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h -cpulimit_test_CFLAGS = $(AM_CFLAGS) -cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la - -cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h -cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 -cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la - -### X11 stuff +libpolyp_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) if HAVE_X11 -modlib_LTLIBRARIES+= \ - libx11wrap.la \ - libx11prop.la \ - module-x11-bell.la \ - module-x11-publish.la -SYMDEF_FILES += \ - module-x11-bell-symdef.h \ - module-x11-publish-symdef.h - -libx11wrap_la_SOURCES = x11wrap.c x11wrap.h -libx11wrap_la_LDFLAGS = -avoid-version -libx11wrap_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) - -libx11prop_la_SOURCES = x11prop.c x11prop.h -libx11prop_la_LDFLAGS = -avoid-version -libx11prop_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) - -module_x11_bell_la_SOURCES = module-x11-bell.c -module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -module_x11_bell_la_LDFLAGS = -module -avoid-version -module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la - -module_x11_publish_la_SOURCES = module-x11-publish.c -module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -module_x11_publish_la_LDFLAGS = -module -avoid-version -module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauthkey-prop.la libx11prop.la libstrlist.la - -bin_PROGRAMS+= \ - pax11publish - -pax11publish_SOURCES = pax11publish.c util.c util.h xmalloc.c xmalloc.h log.c log.h authkey.c authkey.h client-conf.c client-conf.h conf-parser.c conf-parser.h x11prop.c x11prop.h random.c random.h -pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) - libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(X_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) -libpolyp_@PA_MAJORMINOR@_la_SOURCES += x11prop.c x11prop.h client-conf-x11.c client-conf-x11.h - endif -### libasyncns stuff - if HAVE_LIBASYNCNS libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(LIBASYNCNS_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LIBADD += $(LIBASYNCNS_LIBS) endif -### ALSA modules +libpolyp_error_@PA_MAJORMINOR@_la_SOURCES = polyplib-error.c polyplib-error.h +libpolyp_error_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) +libpolyp_error_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la +libpolyp_error_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -if HAVE_ALSA -modlib_LTLIBRARIES+= \ - libalsa-util.la \ - module-alsa-sink.la \ - module-alsa-source.la -SYMDEF_FILES += \ - module-alsa-sink-symdef.h \ - module-alsa-source-symdef.h +libpolyp_mainloop_@PA_MAJORMINOR@_la_SOURCES = \ + mainloop.c mainloop.h \ + mainloop-api.h mainloop-api.c \ + mainloop-signal.c mainloop-signal.h \ + poll.c poll.h +libpolyp_mainloop_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) +libpolyp_mainloop_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(WINSOCK_LIBS) +libpolyp_mainloop_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libalsa_util_la_SOURCES = alsa-util.c alsa-util.h -libalsa_util_la_LDFLAGS = -avoid-version -libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) -libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) - -module_alsa_sink_la_SOURCES = module-alsa-sink.c -module_alsa_sink_la_LDFLAGS = -module -avoid-version -module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la -module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) - -module_alsa_source_la_SOURCES = module-alsa-source.c -module_alsa_source_la_LDFLAGS = -module -avoid-version -module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la -module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) -endif - -### HOWL modules -if HAVE_HOWL -modlib_LTLIBRARIES+= \ - libhowl-wrap.la \ - module-zeroconf-publish.la - -libhowl_wrap_la_SOURCES = howl-wrap.c howl-wrap.h -libhowl_wrap_la_LDFLAGS = -avoid-version -libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) -libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) - -module_zeroconf_publish_la_SOURCES = module-zeroconf-publish.c -module_zeroconf_publish_la_LDFLAGS = -module -avoid-version -module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la -module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) - -lib_LTLIBRARIES+= \ - libpolyp-browse-@PA_MAJORMINOR@.la +libpolyp_simple_@PA_MAJORMINOR@_la_SOURCES = polyplib-simple.c polyplib-simple.h +libpolyp_simple_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) +libpolyp_simple_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +libpolyp_simple_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 libpolyp_browse_@PA_MAJORMINOR@_la_SOURCES = polyplib-browser.c polyplib-browser.h libpolyp_browse_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) libpolyp_browse_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(HOWL_LIBS) libpolyp_browse_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -bin_PROGRAMS += \ - pabrowse - -pabrowse_SOURCES = pabrowse.c -pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la -pabrowse_CFLAGS = $(AM_CFLAGS) - -polypinclude_HEADERS+=polyplib-browser.h - -endif - -### GLIB 2.0 support - -if HAVE_GLIB20 -lib_LTLIBRARIES+= \ - libpolyp-mainloop-glib-@PA_MAJORMINOR@.la - -noinst_PROGRAMS+= \ - mainloop-test-glib - libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib-mainloop.c libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB20_LIBS) libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) -mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib-@PA_MAJORMINOR@.la -endif - -### GLIB 1.2 support - -if HAVE_GLIB12 - -lib_LTLIBRARIES+= \ - libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la - -noinst_PROGRAMS+= \ - mainloop-test-glib12 - libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib12-mainloop.c libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB12_LIBS) libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) -mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la +################################### +# Daemon core library # +################################### -endif - -### LIRC support - -if HAVE_LIRC - -modlib_LTLIBRARIES+= \ - module-lirc.la - -module_lirc_la_SOURCES = module-lirc.c -module_lirc_la_LDFLAGS = -module -avoid-version -module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) -module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS) - -endif - - -### Linux evdev - -if HAVE_EVDEV - -modlib_LTLIBRARIES+= \ - module-mmkbd-evdev.la - -module_mmkbd_evdev_la_SOURCES = module-mmkbd-evdev.c -module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version -module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) -module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS) - -endif - -### libpolypcore (needs to be updated) - -if BUILD_LIBPOLYPCORE - -polypinclude_HEADERS+=cli-command.h\ +polypinclude_HEADERS += \ + cli-command.h \ client.h \ core.h \ dynarray.h \ @@ -783,44 +427,588 @@ polypinclude_HEADERS+=cli-command.h\ tagstruct.h \ util.h -lib_LTLIBRARIES+= libpolypcore.la +lib_LTLIBRARIES += libpolypcore.la -libpolypcore_la_SOURCES = idxset.c idxset.h \ - queue.c queue.h \ - strbuf.c strbuf.h \ - mainloop.c mainloop.h \ - memblock.c memblock.h \ - sample.c sample.h \ - sample-util.c sample-util.h \ - memblockq.c memblockq.h \ - client.c client.h \ - core.c core.h \ - source-output.c source-output.h \ - sink-input.c sink-input.h \ - source.c source.h \ - sink.c sink.h \ - module.c module.h \ - mainloop-signal.c mainloop-signal.h \ - mainloop-api.c mainloop-api.h \ - util.c util.h \ - hashmap.c hashmap.h \ - namereg.c namereg.h \ - sconv.c sconv.h \ - resampler.c resampler.h \ - endianmacros.h \ - memchunk.c memchunk.h \ - sconv-s16le.c sconv-s16le.h \ - sconv-s16be.c sconv-s16be.h \ - sioman.c sioman.h \ - modargs.c modargs.h \ +libpolypcore_la_SOURCES = \ + autoload.c autoload.h \ cli-command.c cli-command.h \ cli-text.c cli-text.h \ + client.c client.h \ + core.c core.h \ + dllmain.c \ + dynarray.c dynarray.h \ + endianmacros.h \ + g711.c g711.h \ + hashmap.c hashmap.h \ + idxset.c idxset.h \ + log.c log.h \ + mainloop.c mainloop.h \ + mainloop-api.c mainloop-api.h \ + mainloop-signal.c mainloop-signal.h \ + mcalign.c mcalign.h \ + memblock.c memblock.h \ + memblockq.c memblockq.h \ + memchunk.c memchunk.h \ + modargs.c modargs.h \ + modinfo.c modinfo.h \ + module.c module.h \ + namereg.c namereg.h \ + play-memchunk.c play-memchunk.h \ + poll.c poll.h \ + props.c props.h \ + queue.c queue.h \ + random.c random.h \ + resampler.c resampler.h \ + sample.c sample.h \ + sample-util.c sample-util.h \ + scache.c scache.h \ + sconv.c sconv.h \ + sconv-s16be.c sconv-s16be.h \ + sconv-s16le.c sconv-s16le.h \ + sink.c sink.h \ + sink-input.c sink-input.h \ + sioman.c sioman.h \ + sound-file.c sound-file.h \ + sound-file-stream.c sound-file-stream.h \ + source.c source.h \ + source-output.c source-output.h \ + strbuf.c strbuf.h \ + subscribe.c subscripe.h \ tokenizer.c tokenizer.h \ - dynarray.c dynarray.h + typeid.c typeid.h \ + util.c util.h \ + winsock.h \ + xmalloc.c xmalloc.h +libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS) +libpolypcore_la_LDFLAGS = -avoid-version +libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) + +################################### +# Plug-in support libraries # +################################### + +### Warning! Due to an obscure bug in libtool/automake it is required +### that the libraries in modlib_LTLIBRARIES are specified in-order, +### i.e. libraries near the end of the list depend on libraries near +### the head, and not the other way! + +modlib_LTLIBRARIES = \ + libsocket-util.la \ + libiochannel.la \ + libsocket-server.la \ + libsocket-client.la \ + libparseaddr.la \ + libpacket.la \ + libpstream.la \ + libioline.la \ + libcli.la \ + libprotocol-cli.la \ + libtagstruct.la \ + libpstream-util.la \ + libpdispatch.la \ + libauthkey.la \ + libauthkey-prop.la \ + libstrlist.la \ + libprotocol-simple.la \ + libprotocol-esound.la \ + libprotocol-native.la \ + libprotocol-http.la + +if HAVE_X11 +modlib_LTLIBRARIES += \ + libx11wrap.la \ + libx11prop.la endif -### Some minor stuff +if HAVE_OSS +modlib_LTLIBRARIES += \ + liboss-util.la +endif + +if HAVE_ALSA +modlib_LTLIBRARIES += \ + libalsa-util.la +endif + +if HAVE_HOWL +modlib_LTLIBRARIES += \ + libhowl-wrap.la +endif + +libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h +libprotocol_simple_la_LDFLAGS = -avoid-version +libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-server.la libiochannel.la + +libsocket_server_la_SOURCES = \ + inet_ntop.c inet_ntop.h \ + socket-server.c socket-server.h +libsocket_server_la_LDFLAGS = -avoid-version +libsocket_server_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS) + +libsocket_client_la_SOURCES = socket-client.c socket-client.h +libsocket_client_la_LDFLAGS = -avoid-version +libsocket_client_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS) $(WINSOCK_LIBS) +libsocket_client_la_CFLAGS = $(AM_CFLAGS) $(LIBASYNCNS_CFLAGS) + +libparseaddr_la_SOURCES = parseaddr.c parseaddr.h +libparseaddr_la_LDFLAGS = -avoid-version +libparseaddr_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +libpstream_la_SOURCES = pstream.c pstream.h +libpstream_la_LDFLAGS = -avoid-version +libpstream_la_LIBADD = $(AM_LIBADD) libpolypcore.la libpacket.la libiochannel.la $(WINSOCK_LIBS) + +libpstream_util_la_SOURCES = pstream-util.c pstream-util.h +libpstream_util_la_LDFLAGS = -avoid-version +libpstream_util_la_LIBADD = $(AM_LIBADD) libpacket.la libpstream.la libtagstruct.la + +libpdispatch_la_SOURCES = pdispatch.c pdispatch.h +libpdispatch_la_LDFLAGS = -avoid-version +libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la libpolypcore.la + +libiochannel_la_SOURCES = iochannel.c iochannel.h +libiochannel_la_LDFLAGS = -avoid-version +libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpolypcore.la $(WINSOCK_LIBS) + +libpacket_la_SOURCES = packet.c packet.h +libpacket_la_LDFLAGS = -avoid-version +libpacket_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +libioline_la_SOURCES = ioline.c ioline.h +libioline_la_LDFLAGS = -avoid-version +libioline_la_LIBADD = $(AM_LIBADD) libiochannel.la libpolypcore.la + +libcli_la_SOURCES = cli.c cli.h +libcli_la_CPPFLAGS = $(AM_CPPFLAGS) +libcli_la_LDFLAGS = -avoid-version +libcli_la_LIBADD = $(AM_LIBADD) libiochannel.la libioline.la libpolypcore.la + +libstrlist_la_SOURCES = strlist.c strlist.h +libstrlist_la_LDFLAGS = -avoid-version +libstrlist_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h +libprotocol_cli_la_LDFLAGS = -avoid-version +libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la libpolypcore.la + +libprotocol_http_la_SOURCES = protocol-http.c protocol-http.h +libprotocol_http_la_LDFLAGS = -avoid-version +libprotocol_http_la_LIBADD = $(AM_LIBADD) libsocket-server.la libioline.la libpolypcore.la libiochannel.la + +libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h native-common.h +libprotocol_native_la_LDFLAGS = -avoid-version +libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la libpolypcore.la libiochannel.la + +libtagstruct_la_SOURCES = tagstruct.c tagstruct.h +libtagstruct_la_LDFLAGS = -avoid-version +libtagstruct_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(WINSOCK_LIBS) + +libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h esound.h +libprotocol_esound_la_LDFLAGS = -avoid-version +libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la libpolypcore.la + +libauthkey_la_SOURCES = authkey.c authkey.h +libauthkey_la_LDFLAGS = -avoid-version +libauthkey_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +libauthkey_prop_la_SOURCES = authkey-prop.c authkey-prop.h +libauthkey_prop_la_LDFLAGS = -avoid-version +libauthkey_prop_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +libsocket_util_la_SOURCES = socket-util.c socket-util.h +libsocket_util_la_LDFLAGS = -avoid-version +libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) + +# X11 + +libx11wrap_la_SOURCES = x11wrap.c x11wrap.h +libx11wrap_la_LDFLAGS = -avoid-version +libx11wrap_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) + +libx11prop_la_SOURCES = x11prop.c x11prop.h +libx11prop_la_LDFLAGS = -avoid-version +libx11prop_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) + +# OSS + +liboss_util_la_SOURCES = oss-util.c oss-util.h +liboss_util_la_LDFLAGS = -avoid-version + +# ALSA + +libalsa_util_la_SOURCES = alsa-util.c alsa-util.h +libalsa_util_la_LDFLAGS = -avoid-version +libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) +libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) + +# HOWL + +libhowl_wrap_la_SOURCES = howl-wrap.c howl-wrap.h +libhowl_wrap_la_LDFLAGS = -avoid-version +libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) +libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) + +################################### +# Plug-in libraries # +################################### + +modlib_LTLIBRARIES += \ + module-cli.la \ + module-cli-protocol-tcp.la \ + module-cli-protocol-tcp6.la \ + module-simple-protocol-tcp.la \ + module-simple-protocol-tcp6.la \ + module-esound-protocol-tcp.la \ + module-esound-protocol-tcp6.la \ + module-native-protocol-tcp.la \ + module-native-protocol-tcp6.la \ + module-native-protocol-fd.la \ + module-sine.la \ + module-combine.la \ + module-tunnel-sink.la \ + module-tunnel-source.la \ + module-null-sink.la \ + module-esound-sink.la \ + module-http-protocol-tcp.la \ + module-http-protocol-tcp6.la + +if HAVE_AF_UNIX +modlib_LTLIBRARIES += \ + module-cli-protocol-unix.la \ + module-simple-protocol-unix.la \ + module-esound-protocol-unix.la \ + module-native-protocol-unix.la \ + module-http-protocol-unix.la +endif + +if HAVE_MKFIFO +modlib_LTLIBRARIES += \ + module-pipe-sink.la \ + module-pipe-source.la +endif + +if !OS_IS_WIN32 +modlib_LTLIBRARIES += \ + module-esound-compat-spawnfd.la \ + module-esound-compat-spawnpid.la +endif + +if HAVE_REGEX +modlib_LTLIBRARIES += \ + module-match.la +endif + +if HAVE_X11 +modlib_LTLIBRARIES += \ + module-x11-bell.la \ + module-x11-publish.la +endif + +if HAVE_OSS +modlib_LTLIBRARIES += \ + module-oss.la \ + module-oss-mmap.la +endif + +if HAVE_ALSA +modlib_LTLIBRARIES += \ + module-alsa-sink.la \ + module-alsa-source.la +endif + +if HAVE_SOLARIS +modlib_LTLIBRARIES += \ + module-solaris.la +endif + +if HAVE_HOWL +modlib_LTLIBRARIES += \ + module-zeroconf-publish.la +endif + +if HAVE_LIRC +modlib_LTLIBRARIES += \ + module-lirc.la +endif + +if HAVE_EVDEV +modlib_LTLIBRARIES += \ + module-mmkbd-evdev.la +endif + +if OS_IS_WIN32 +modlib_LTLIBRARIES += \ + module-waveout.la +endif + +# These are generated by a M4 script + +SYMDEF_FILES = \ + module-cli-symdef.h \ + module-cli-protocol-tcp-symdef.h \ + module-cli-protocol-tcp6-symdef.h \ + module-cli-protocol-unix-symdef.h \ + module-pipe-sink-symdef.h \ + module-pipe-source-symdef.h \ + module-simple-protocol-tcp-symdef.h \ + module-simple-protocol-tcp6-symdef.h \ + module-simple-protocol-unix-symdef.h \ + module-esound-protocol-tcp-symdef.h \ + module-esound-protocol-tcp6-symdef.h \ + module-esound-protocol-unix-symdef.h \ + module-native-protocol-tcp-symdef.h \ + module-native-protocol-tcp6-symdef.h \ + module-native-protocol-unix-symdef.h \ + module-native-protocol-fd-symdef.h \ + module-sine-symdef.h \ + module-combine-symdef.h \ + module-esound-compat-spawnfd-symdef.h \ + module-esound-compat-spawnpid-symdef.h \ + module-match-symdef.h \ + module-tunnel-sink-symdef.h \ + module-tunnel-source-symdef.h \ + module-null-sink-symdef.h \ + module-esound-sink-symdef.h \ + module-zeroconf-publish-symdef.h \ + module-lirc-symdef.h \ + module-mmkbd-evdev-symdef.h \ + module-http-protocol-tcp-symdef.h \ + module-http-protocol-tcp6-symdef.h \ + module-http-protocol-unix-symdef.h \ + module-x11-bell-symdef.h \ + module-x11-publish-symdef.h \ + module-oss-symdef.h \ + module-oss-mmap-symdef.h \ + module-alsa-sink-symdef.h \ + module-alsa-source-symdef.h \ + module-solaris-symdef.h \ + module-waveout-symdef.h + +EXTRA_DIST += $(SYMDEF_FILES) +BUILT_SOURCES += $(SYMDEF_FILES) + +$(SYMDEF_FILES): module-defs.h.m4 + $(M4) -Dfname="$@" $< > $@ + +# Simple protocol + +module_simple_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) +module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version +module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la + +module_simple_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_simple_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) +module_simple_protocol_tcp6_la_LDFLAGS = -module -avoid-version +module_simple_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la + +module_simple_protocol_unix_la_SOURCES = module-protocol-stub.c +module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) +module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version +module_simple_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la libsocket-util.la + +# CLI protocol + +module_cli_la_SOURCES = module-cli.c +module_cli_la_LDFLAGS = -module -avoid-version +module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la libpolypcore.la + +module_cli_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) +module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version +module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la + +module_cli_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_cli_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) +module_cli_protocol_tcp6_la_LDFLAGS = -module -avoid-version +module_cli_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la + +module_cli_protocol_unix_la_SOURCES = module-protocol-stub.c +module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) +module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version +module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la libsocket-util.la + +# HTTP protocol + +module_http_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_http_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) +module_http_protocol_tcp_la_LDFLAGS = -module -avoid-version +module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la + +module_http_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_http_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) +module_http_protocol_tcp6_la_LDFLAGS = -module -avoid-version +module_http_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la + +module_http_protocol_unix_la_SOURCES = module-protocol-stub.c +module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) +module_http_protocol_unix_la_LDFLAGS = -module -avoid-version +module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la libsocket-util.la + +# Native protocol + +module_native_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) +module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version +module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la + +module_native_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_native_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) +module_native_protocol_tcp6_la_LDFLAGS = -module -avoid-version +module_native_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la + +module_native_protocol_unix_la_SOURCES = module-protocol-stub.c +module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) +module_native_protocol_unix_la_LDFLAGS = -module -avoid-version +module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la libsocket-util.la + +module_native_protocol_fd_la_SOURCES = module-native-protocol-fd.c +module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS) +module_native_protocol_fd_la_LDFLAGS = -module -avoid-version +module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la libsocket-util.la libiochannel.la + +# EsounD protocol + +module_esound_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) +module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version +module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la + +module_esound_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_esound_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) +module_esound_protocol_tcp6_la_LDFLAGS = -module -avoid-version +module_esound_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la + +module_esound_protocol_unix_la_SOURCES = module-protocol-stub.c +module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) +module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version +module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la libsocket-util.la + +module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c +module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version +module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +module_esound_compat_spawnpid_la_SOURCES = module-esound-compat-spawnpid.c +module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version +module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +module_esound_sink_la_SOURCES = module-esound-sink.c +module_esound_sink_la_LDFLAGS = -module -avoid-version +module_esound_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-client.la libauthkey.la + +# Pipes + +module_pipe_sink_la_SOURCES = module-pipe-sink.c +module_pipe_sink_la_LDFLAGS = -module -avoid-version +module_pipe_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la + +module_pipe_source_la_SOURCES = module-pipe-source.c +module_pipe_source_la_LDFLAGS = -module -avoid-version +module_pipe_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la + +# Fake sources/sinks + +module_sine_la_SOURCES = module-sine.c +module_sine_la_LDFLAGS = -module -avoid-version +module_sine_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +module_null_sink_la_SOURCES = module-null-sink.c +module_null_sink_la_LDFLAGS = -module -avoid-version +module_null_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +# Couplings + +module_combine_la_SOURCES = module-combine.c +module_combine_la_LDFLAGS = -module -avoid-version +module_combine_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +module_match_la_SOURCES = module-match.c +module_match_la_LDFLAGS = -module -avoid-version +module_match_la_LIBADD = $(AM_LIBADD) libpolypcore.la + +module_tunnel_sink_la_SOURCES = module-tunnel.c +module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) +module_tunnel_sink_la_LDFLAGS = -module -avoid-version +module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la + +module_tunnel_source_la_SOURCES = module-tunnel.c +module_tunnel_source_la_LDFLAGS = -module -avoid-version +module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la + +# X11 + +module_x11_bell_la_SOURCES = module-x11-bell.c +module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +module_x11_bell_la_LDFLAGS = -module -avoid-version +module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la + +module_x11_publish_la_SOURCES = module-x11-publish.c +module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +module_x11_publish_la_LDFLAGS = -module -avoid-version +module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauthkey-prop.la libx11prop.la libstrlist.la + +# OSS + +module_oss_la_SOURCES = module-oss.c +module_oss_la_LDFLAGS = -module -avoid-version +module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la + +module_oss_mmap_la_SOURCES = module-oss-mmap.c +module_oss_mmap_la_LDFLAGS = -module -avoid-version +module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la + +# ALSA + +module_alsa_sink_la_SOURCES = module-alsa-sink.c +module_alsa_sink_la_LDFLAGS = -module -avoid-version +module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la +module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) + +module_alsa_source_la_SOURCES = module-alsa-source.c +module_alsa_source_la_LDFLAGS = -module -avoid-version +module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la +module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) + +# Solaris + +module_solaris_la_SOURCES = module-solaris.c +module_solaris_la_LDFLAGS = -module -avoid-version +module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la + +# HOWL + +module_zeroconf_publish_la_SOURCES = module-zeroconf-publish.c +module_zeroconf_publish_la_LDFLAGS = -module -avoid-version +module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la +module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) + +# LIRC + +module_lirc_la_SOURCES = module-lirc.c +module_lirc_la_LDFLAGS = -module -avoid-version +module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) +module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS) + +# Linux evdev + +module_mmkbd_evdev_la_SOURCES = module-mmkbd-evdev.c +module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version +module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) +module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS) + +# Windows waveout + +module_waveout_la_SOURCES = module-waveout.c +module_waveout_la_LDFLAGS = -module -avoid-version +module_waveout_la_LIBADD = $(AM_LIBADD) libpolypcore.la -lwinmm +module_waveout_la_CFLAGS = $(AM_CFLAGS) + +################################### +# Some minor stuff # +################################### suid: polypaudio chown root $< @@ -829,22 +1017,24 @@ suid: polypaudio esdcompat.sh: esdcompat.sh.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ - -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ + -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ client.conf: client.conf.in Makefile - sed -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ + sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ +if OS_IS_WIN32 +default.pa: default.pa.win32 + cp $< $@ +else default.pa: default.pa.in Makefile - sed -e 's,@POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@ + sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ +endif daemon.conf: daemon.conf.in Makefile sed -e 's,@DLSEARCHPATH\@,$(modlibdir),g' \ - -e 's,@DEFAULT_CONFIG_FILE\@,$(polypconfdir)/daemon.conf,g' < $< > $@ + -e 's,@DEFAULT_CONFIG_FILE\@,$(DEFAULT_CONFIG_DIR),g' < $< > $@ install-exec-hook: chown root $(DESTDIR)$(bindir)/polypaudio ; true chmod u+s $(DESTDIR)$(bindir)/polypaudio ln -sf pacat $(DESTDIR)$(bindir)/parec - -$(SYMDEF_FILES): module-defs.h.m4 - $(M4) -Dfname="$@" $< > $@ diff --git a/polyp/authkey.c b/polyp/authkey.c index e16883d38..969f09d90 100644 --- a/polyp/authkey.c +++ b/polyp/authkey.c @@ -63,7 +63,7 @@ static int generate(int fd, void *ret_data, size_t length) { static int load(const char *fn, void *data, size_t length) { int fd = -1; int writable = 1; - int unlock = 0, ret; + int unlock = 0, ret = -1; ssize_t r; assert(fn && data && length); @@ -128,12 +128,20 @@ int pa_authkey_load(const char *path, void *data, size_t length) { static const char *normalize_path(const char *fn, char *s, size_t l) { assert(fn && s && l > 0); +#ifndef OS_IS_WIN32 if (fn[0] != '/') { +#else + if (strlen(fn) < 3 || !isalpha(fn[0]) || fn[1] != ':' || fn[2] != '\\') { +#endif char homedir[PATH_MAX]; if (!pa_get_home_dir(homedir, sizeof(homedir))) return NULL; +#ifndef OS_IS_WIN32 snprintf(s, l, "%s/%s", homedir, fn); +#else + snprintf(s, l, "%s\\%s", homedir, fn); +#endif return s; } diff --git a/polyp/caps.c b/polyp/caps.c index 739e70712..4ecb5848d 100644 --- a/polyp/caps.c +++ b/polyp/caps.c @@ -35,6 +35,8 @@ #include "log.h" #include "caps.h" +#ifdef HAVE_GETUID + /* Drop root rights when called SUID root */ void pa_drop_root(void) { uid_t uid = getuid(); @@ -54,6 +56,13 @@ void pa_drop_root(void) { #endif } +#else + +void pa_drop_root(void) { +} + +#endif + #ifdef HAVE_SYS_CAPABILITY_H /* Limit capabilities set to CAPSYS_NICE */ diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 0e8e09a56..124478794 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -641,7 +641,11 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct time(&now); +#ifdef HAVE_CTIME_R pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt)); +#else + pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now)); +#endif for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) { diff --git a/polyp/client-conf.c b/polyp/client-conf.c index 4906383d1..04c3d2ef7 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -19,6 +19,10 @@ USA. ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -33,11 +37,21 @@ #include "authkey.h" #ifndef DEFAULT_CONFIG_DIR -#define DEFAULT_CONFIG_DIR "/etc/polypaudio" +# ifndef OS_IS_WIN32 +# define DEFAULT_CONFIG_DIR "/etc/polypaudio" +# else +# define DEFAULT_CONFIG_DIR "%POLYP_ROOT%" +# endif #endif -#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR"/client.conf" -#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio/client.conf" +#ifndef OS_IS_WIN32 +# define PATH_SEP "/" +#else +# define PATH_SEP "\\" +#endif + +#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "client.conf" +#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio" PATH_SEP "client.conf" #define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG" #define ENV_DEFAULT_SINK "POLYP_SINK" diff --git a/polyp/conf-parser.c b/polyp/conf-parser.c index b25508e2d..8d2f2f681 100644 --- a/polyp/conf-parser.c +++ b/polyp/conf-parser.c @@ -19,6 +19,10 @@ USA. ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/polyp/core.c b/polyp/core.c index e2bebec25..604392431 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -89,7 +89,9 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { pa_random(&c->cookie, sizeof(c->cookie)); +#ifdef SIGPIPE pa_check_signal_is_blocked(SIGPIPE); +#endif return c; } @@ -144,7 +146,7 @@ void pa_core_check_quit(struct pa_core *c) { if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_ncontents(c->clients) == 0) { struct timeval tv; - gettimeofday(&tv, NULL); + pa_gettimeofday(&tv); tv.tv_sec+= c->exit_idle_time; c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c); } else if (c->quit_event && pa_idxset_ncontents(c->clients) > 0) { diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c index 0fab98a02..53920f50a 100644 --- a/polyp/cpulimit.c +++ b/polyp/cpulimit.c @@ -23,15 +23,20 @@ #include #endif +#ifdef HAVE_SIGXCPU + #include #include #include #include #include -#include #include #include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + #include "cpulimit.h" #include "util.h" #include "log.h" @@ -219,3 +224,16 @@ void pa_cpu_limit_done(void) { installed = 0; } } + +#else /* HAVE_SIGXCPU */ + +struct pa_mainloop_api; + +int pa_cpu_limit_init(struct pa_mainloop_api *m) { + return 0; +} + +void pa_cpu_limit_done(void) { +} + +#endif diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index a6afd05a5..780581b2c 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -37,13 +37,23 @@ #include "resampler.h" #ifndef DEFAULT_CONFIG_DIR -#define DEFAULT_CONFIG_DIR "/etc/polypaudio" +# ifndef OS_IS_WIN32 +# define DEFAULT_CONFIG_DIR "/etc/polypaudio" +# else +# define DEFAULT_CONFIG_DIR "%POLYP_ROOT%" +# endif #endif -#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR"/default.pa" -#define DEFAULT_SCRIPT_FILE_USER ".polypaudio/default.pa" -#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR"/daemon.conf" -#define DEFAULT_CONFIG_FILE_USER ".polypaudio/daemon.conf" +#ifndef OS_IS_WIN32 +# define PATH_SEP "/" +#else +# define PATH_SEP "\\" +#endif + +#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR PATH_SEP "default.pa" +#define DEFAULT_SCRIPT_FILE_USER ".polypaudio" PATH_SEP "default.pa" +#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" +#define DEFAULT_CONFIG_FILE_USER ".polypaudio" PATH_SEP "daemon.conf" #define ENV_SCRIPT_FILE "POLYP_SCRIPT" #define ENV_CONFIG_FILE "POLYP_CONFIG" diff --git a/polyp/default.pa.win32 b/polyp/default.pa.win32 new file mode 100644 index 000000000..3478adab1 --- /dev/null +++ b/polyp/default.pa.win32 @@ -0,0 +1,43 @@ +# +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with polypaudio; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + +# Load audio drivers statically + +load-module module-waveout sink_name=output source_name=input +load-module module-null-sink + +# Load audio drivers automatically on access + +#add-autoload-sink output module-waveout sink_name=output source_name=input +#add-autoload-source input module-waveout sink_name=output source_name=input + +# Load several protocols +#load-module module-esound-protocol-tcp +#load-module module-native-protocol-tcp +#load-module module-simple-protocol-tcp +#load-module module-cli-protocol-tcp + +# Make some devices default +set-default-sink output +set-default-source input + +.nofail + +# Load something to the sample cache +load-sample x11-bell %WINDIR%\Media\ding.wav +load-sample-dir-lazy %WINDIR%\Media\*.wav diff --git a/polyp/dllmain.c b/polyp/dllmain.c new file mode 100644 index 000000000..34d0eed11 --- /dev/null +++ b/polyp/dllmain.c @@ -0,0 +1,46 @@ +/* $Id: dllmain.c 317 2004-12-11 00:10:41Z lennart $ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef OS_IS_WIN32 + +#include +#include +#include + +#include + +extern pa_set_root(HANDLE handle); + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + if (fdwReason != DLL_PROCESS_ATTACH) + return TRUE; + + if (!pa_set_root(hinstDLL)) + return FALSE; + + return TRUE; +} + +#endif /* OS_IS_WIN32 */ diff --git a/polyp/dumpmodules.c b/polyp/dumpmodules.c index 1dc14edc4..5aaa108dd 100644 --- a/polyp/dumpmodules.c +++ b/polyp/dumpmodules.c @@ -31,6 +31,7 @@ #include "dumpmodules.h" #include "modinfo.h" +#include "util.h" #define PREFIX "module-" @@ -80,10 +81,7 @@ static int callback(const char *path, lt_ptr data) { const char *e; struct pa_daemon_conf *c = (data); - if ((e = (const char*) strrchr(path, '/'))) - e++; - else - e = path; + e = pa_path_get_filename(path); if (strlen(e) > sizeof(PREFIX)-1 && !strncmp(e, PREFIX, sizeof(PREFIX)-1)) show_info(e, path, c->log_level >= PA_LOG_INFO ? long_info : short_info); diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c index 809c0b0fb..0f96a594e 100644 --- a/polyp/glib-mainloop.c +++ b/polyp/glib-mainloop.c @@ -241,7 +241,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) struct timeval now; assert(e && e->mainloop && !e->dead); - gettimeofday(&now, NULL); + pa_gettimeofday(&now); if (e->source) { g_source_destroy(e->source); g_source_unref(e->source); diff --git a/polyp/glib12-mainloop.c b/polyp/glib12-mainloop.c index 5f0373471..c328471ca 100644 --- a/polyp/glib12-mainloop.c +++ b/polyp/glib12-mainloop.c @@ -233,7 +233,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) struct timeval now; assert(e && e->mainloop && !e->dead); - gettimeofday(&now, NULL); + pa_gettimeofday(&now); if (e->source != (guint) -1) g_source_remove(e->source); diff --git a/polyp/inet_ntop.c b/polyp/inet_ntop.c new file mode 100644 index 000000000..ac2b5295a --- /dev/null +++ b/polyp/inet_ntop.c @@ -0,0 +1,80 @@ +/* $Id: inet_ntop.c 428 2006-01-09 16:50:39Z ossman $ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#ifndef HAVE_INET_NTOP + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#include "winsock.h" + +#include "inet_ntop.h" + +const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { + struct in_addr *in = (struct in_addr*)src; + struct in6_addr *in6 = (struct in6_addr*)src; + + assert(src && dst); + + switch (af) { + case AF_INET: + snprintf(dst, cnt, "%d.%d.%d.%d", +#ifdef WORDS_BIGENDIAN + (int)(in->s_addr >> 24) & 0xff, + (int)(in->s_addr >> 16) & 0xff, + (int)(in->s_addr >> 8) & 0xff, + (int)(in->s_addr >> 0) & 0xff); +#else + (int)(in->s_addr >> 0) & 0xff, + (int)(in->s_addr >> 8) & 0xff, + (int)(in->s_addr >> 16) & 0xff, + (int)(in->s_addr >> 24) & 0xff); +#endif + break; + case AF_INET6: + snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x", + in6->s6_addr[ 0] << 8 | in6->s6_addr[ 1], + in6->s6_addr[ 2] << 8 | in6->s6_addr[ 3], + in6->s6_addr[ 4] << 8 | in6->s6_addr[ 5], + in6->s6_addr[ 6] << 8 | in6->s6_addr[ 7], + in6->s6_addr[ 8] << 8 | in6->s6_addr[ 9], + in6->s6_addr[10] << 8 | in6->s6_addr[11], + in6->s6_addr[12] << 8 | in6->s6_addr[13], + in6->s6_addr[14] << 8 | in6->s6_addr[15]); + break; + default: + errno = EAFNOSUPPORT; + return NULL; + } + + return dst; +} + +#endif /* INET_NTOP */ diff --git a/polyp/inet_ntop.h b/polyp/inet_ntop.h new file mode 100644 index 000000000..7fb67b442 --- /dev/null +++ b/polyp/inet_ntop.h @@ -0,0 +1,12 @@ +#ifndef fooinet_ntophfoo +#define fooinet_ntophfoo + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#include "winsock.h" + +const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt); + +#endif diff --git a/polyp/iochannel.c b/polyp/iochannel.c index 0e7e8db80..1a0dbf918 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -28,6 +28,8 @@ #include #include +#include "winsock.h" + #include "iochannel.h" #include "util.h" #include "socket-util.h" @@ -189,7 +191,19 @@ ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) { ssize_t r; assert(io && data && l && io->ofd >= 0); - if ((r = write(io->ofd, data, l)) >= 0) { +#ifdef OS_IS_WIN32 + r = send(io->ofd, data, l, 0); + if (r < 0) { + if (WSAGetLastError() != WSAENOTSOCK) { + errno = WSAGetLastError(); + return r; + } + } + + if (r < 0) +#endif + r = write(io->ofd, data, l); + if (r >= 0) { io->writable = 0; enable_mainloop_sources(io); } @@ -201,7 +215,19 @@ ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l) { ssize_t r; assert(io && data && io->ifd >= 0); - if ((r = read(io->ifd, data, l)) >= 0) { +#ifdef OS_IS_WIN32 + r = recv(io->ifd, data, l, 0); + if (r < 0) { + if (WSAGetLastError() != WSAENOTSOCK) { + errno = WSAGetLastError(); + return r; + } + } + + if (r < 0) +#endif + r = read(io->ifd, data, l); + if (r >= 0) { io->readable = 0; enable_mainloop_sources(io); } diff --git a/polyp/log.c b/polyp/log.c index 78736a476..2bbf2e867 100644 --- a/polyp/log.c +++ b/polyp/log.c @@ -25,9 +25,12 @@ #include #include -#include #include +#ifdef HAVE_SYSLOG_H +#include +#endif + #include "log.h" #include "xmalloc.h" #include "util.h" @@ -39,6 +42,7 @@ static enum pa_log_target log_target = PA_LOG_STDERR; static void (*user_log_func)(enum pa_log_level l, const char *s) = NULL; static enum pa_log_level maximal_level = PA_LOG_NOTICE; +#ifdef HAVE_SYSLOG_H static const int level_to_syslog[] = { [PA_LOG_ERROR] = LOG_ERR, [PA_LOG_WARN] = LOG_WARNING, @@ -46,6 +50,7 @@ static const int level_to_syslog[] = { [PA_LOG_INFO] = LOG_INFO, [PA_LOG_DEBUG] = LOG_DEBUG }; +#endif void pa_log_set_ident(const char *p) { if (log_ident) @@ -79,13 +84,15 @@ void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap) { case PA_LOG_STDERR: vfprintf(stderr, format, ap); break; - + +#ifdef HAVE_SYSLOG_H case PA_LOG_SYSLOG: openlog(log_ident ? log_ident : "???", LOG_PID, LOG_USER); vsyslog(level_to_syslog[level], format, ap); closelog(); - break; - + break; +#endif + case PA_LOG_USER: { char *t = pa_vsprintf_malloc(format, ap); assert(user_log_func); @@ -94,6 +101,7 @@ void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap) { } case PA_LOG_NULL: + default: break; } diff --git a/polyp/main.c b/polyp/main.c index 26fa4a874..e481fce16 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -35,13 +35,20 @@ #include #include #include +#include +#include + +#ifdef HAVE_SYS_IOCTL_H #include +#endif #ifdef HAVE_LIBWRAP #include #include #endif +#include "winsock.h" + #include "core.h" #include "mainloop.h" #include "module.h" @@ -66,24 +73,47 @@ int allow_severity = LOG_INFO; int deny_severity = LOG_WARNING; #endif +#ifdef OS_IS_WIN32 + +static void message_cb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { + MSG msg; + + while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (msg.message == WM_QUIT) + raise(SIGTERM); + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + +#endif + static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig)); switch (sig) { +#ifdef SIGUSR1 case SIGUSR1: pa_module_load(userdata, "module-cli", NULL); break; +#endif +#ifdef SIGUSR2 case SIGUSR2: pa_module_load(userdata, "module-cli-protocol-unix", NULL); break; +#endif +#ifdef SIGHUP case SIGHUP: { char *c = pa_full_status_string(userdata); pa_log_notice(c); pa_xfree(c); return; } +#endif case SIGINT: case SIGTERM: @@ -111,24 +141,42 @@ int main(int argc, char *argv[]) { char *s; int r, retval = 1, d = 0; int daemon_pipe[2] = { -1, -1 }; - gid_t gid = (gid_t) -1; int suid_root; int valid_pid_file = 0; +#ifdef HAVE_GETUID + gid_t gid = (gid_t) -1; +#endif + +#ifdef OS_IS_WIN32 + struct pa_defer_event *defer; +#endif + pa_limit_caps(); +#ifdef HAVE_GETUID suid_root = getuid() != 0 && geteuid() == 0; if (suid_root && (pa_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) { pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'.\n"); pa_drop_root(); } +#else + suid_root = 0; +#endif LTDL_SET_PRELOADED_SYMBOLS(); r = lt_dlinit(); assert(r == 0); +#ifdef OS_IS_WIN32 + { + WSADATA data; + WSAStartup(MAKEWORD(2, 0), &data); + } +#endif + pa_log_set_ident("polypaudio"); conf = pa_daemon_conf_new(); @@ -217,6 +265,7 @@ int main(int argc, char *argv[]) { goto finish; } +#ifdef HAVE_FORK if (pipe(daemon_pipe) < 0) { pa_log(__FILE__": failed to create pipe.\n"); goto finish; @@ -248,13 +297,19 @@ int main(int argc, char *argv[]) { close(daemon_pipe[0]); daemon_pipe[0] = -1; +#endif if (conf->auto_log_target) pa_log_set_target(PA_LOG_SYSLOG, NULL); +#ifdef HAVE_SETSID setsid(); +#endif +#ifdef HAVE_SETPGID setpgid(0,0); - +#endif + +#ifndef OS_IS_WIN32 close(0); close(1); close(2); @@ -262,23 +317,37 @@ int main(int argc, char *argv[]) { open("/dev/null", O_RDONLY); open("/dev/null", O_WRONLY); open("/dev/null", O_WRONLY); - +#else + FreeConsole(); +#endif + +#ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); +#endif +#ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); +#endif +#ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); +#endif +#ifdef TIOCNOTTY if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) { ioctl(tty_fd, TIOCNOTTY, (char*) 0); close(tty_fd); } +#endif } chdir("/"); if (conf->use_pid_file) { if (pa_pid_file_create() < 0) { + pa_log(__FILE__": pa_pid_file_create() failed.\n"); +#ifdef HAVE_FORK if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); +#endif goto finish; } @@ -288,20 +357,34 @@ int main(int argc, char *argv[]) { mainloop = pa_mainloop_new(); assert(mainloop); + c = pa_core_new(pa_mainloop_get_api(mainloop)); + assert(c); + r = pa_signal_init(pa_mainloop_get_api(mainloop)); assert(r == 0); pa_signal_new(SIGINT, signal_callback, c); pa_signal_new(SIGTERM, signal_callback, c); +#ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); +#endif + +#ifdef OS_IS_WIN32 + defer = pa_mainloop_get_api(mainloop)->defer_new(pa_mainloop_get_api(mainloop), message_cb, NULL); + assert(defer); +#endif - c = pa_core_new(pa_mainloop_get_api(mainloop)); - assert(c); if (conf->daemonize) c->running_as_daemon = 1; - + +#ifdef SIGUSR1 pa_signal_new(SIGUSR1, signal_callback, c); +#endif +#ifdef SIGUSR2 pa_signal_new(SIGUSR2, signal_callback, c); +#endif +#ifdef SIGHUP pa_signal_new(SIGHUP, signal_callback, c); +#endif r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop)); assert(r == 0); @@ -318,17 +401,23 @@ int main(int argc, char *argv[]) { if (r < 0 && conf->fail) { pa_log(__FILE__": failed to initialize daemon.\n"); +#ifdef HAVE_FORK if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); +#endif } else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) { pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n"); +#ifdef HAVE_FORK if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); +#endif } else { retval = 0; +#ifdef HAVE_FORK if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); +#endif c->disallow_module_loading = conf->disallow_module_loading; c->exit_idle_time = conf->exit_idle_time; @@ -346,7 +435,11 @@ int main(int argc, char *argv[]) { pa_log_info(__FILE__": Daemon shutdown initiated.\n"); } } - + +#ifdef OS_IS_WIN32 + pa_mainloop_get_api(mainloop)->defer_free(defer); +#endif + pa_core_free(c); pa_cpu_limit_done(); @@ -365,6 +458,10 @@ finish: close_pipe(daemon_pipe); +#ifdef OS_IS_WIN32 + WSACleanup(); +#endif + lt_dlexit(); return retval; diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c index 89f195ed3..432498a86 100644 --- a/polyp/mainloop-signal.c +++ b/polyp/mainloop-signal.c @@ -30,6 +30,11 @@ #include #include #include +#include + +#ifdef HAVE_WINDOWS_H +#include +#endif #include "mainloop-signal.h" #include "util.h" @@ -38,7 +43,11 @@ struct pa_signal_event { int sig; +#ifdef HAVE_SIGACTION struct sigaction saved_sigaction; +#else + void (*saved_handler)(int sig); +#endif void (*callback) (struct pa_mainloop_api*a, struct pa_signal_event *e, int signal, void *userdata); void *userdata; void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_signal_event*e, void *userdata); @@ -48,16 +57,70 @@ struct pa_signal_event { static struct pa_mainloop_api *api = NULL; static int signal_pipe[2] = { -1, -1 }; static struct pa_io_event* io_event = NULL; +static struct pa_defer_event *defer_event = NULL; static struct pa_signal_event *signals = NULL; +#ifdef OS_IS_WIN32 +static unsigned int waiting_signals = 0; +static CRITICAL_SECTION crit; +#endif + static void signal_handler(int sig) { +#ifndef HAVE_SIGACTION + signal(sig, signal_handler); +#endif write(signal_pipe[1], &sig, sizeof(sig)); + +#ifdef OS_IS_WIN32 + EnterCriticalSection(&crit); + waiting_signals++; + LeaveCriticalSection(&crit); +#endif +} + +static void dispatch(struct pa_mainloop_api*a, int sig) { + struct pa_signal_event*s; + + for (s = signals; s; s = s->next) + if (s->sig == sig) { + assert(s->callback); + s->callback(a, s, sig, s->userdata); + break; + } +} + +static void defer(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata) { + ssize_t r; + int sig; + unsigned int sigs; + +#ifdef OS_IS_WIN32 + EnterCriticalSection(&crit); + sigs = waiting_signals; + waiting_signals = 0; + LeaveCriticalSection(&crit); +#endif + + while (sigs) { + if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { + pa_log(__FILE__": read(): %s\n", strerror(errno)); + return; + } + + if (r != sizeof(sig)) { + pa_log(__FILE__": short read()\n"); + return; + } + + dispatch(a, sig); + + sigs--; + } } static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) { ssize_t r; int sig; - struct pa_signal_event*s; assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); @@ -73,19 +136,18 @@ static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enu pa_log(__FILE__": short read()\n"); return; } - - for (s = signals; s; s = s->next) - if (s->sig == sig) { - assert(s->callback); - s->callback(a, s, sig, s->userdata); - break; - } + + dispatch(a, sig); } int pa_signal_init(struct pa_mainloop_api *a) { - assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event); - + assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event && !defer_event); + +#ifdef OS_IS_WIN32 + if (_pipe(signal_pipe, 200, _O_BINARY) < 0) { +#else if (pipe(signal_pipe) < 0) { +#endif pa_log(__FILE__": pipe() failed: %s\n", strerror(errno)); return -1; } @@ -96,20 +158,36 @@ int pa_signal_init(struct pa_mainloop_api *a) { pa_fd_set_cloexec(signal_pipe[1], 1); api = a; + +#ifndef OS_IS_WIN32 io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL); assert(io_event); +#else + defer_event = api->defer_new(api, defer, NULL); + assert(defer_event); + + InitializeCriticalSection(&crit); +#endif + return 0; } void pa_signal_done(void) { - assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && io_event); + assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && (io_event || defer_event)); while (signals) pa_signal_free(signals); - api->io_free(io_event); +#ifndef OS_IS_WIN32 + api->io_free(io_event); io_event = NULL; +#else + api->defer_free(defer_event); + defer_event = NULL; + + DeleteCriticalSection(&crit); +#endif close(signal_pipe[0]); close(signal_pipe[1]); @@ -120,7 +198,11 @@ void pa_signal_done(void) { struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int sig, void *userdata), void *userdata) { struct pa_signal_event *e = NULL; + +#ifdef HAVE_SIGACTION struct sigaction sa; +#endif + assert(sig > 0 && callback); for (e = signals; e; e = e->next) @@ -133,12 +215,16 @@ struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainl e->userdata = userdata; e->destroy_callback = NULL; +#ifdef HAVE_SIGACTION memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(sig, &sa, &e->saved_sigaction) < 0) +#else + if ((e->saved_handler = signal(sig, signal_handler)) == SIG_ERR) +#endif goto fail; e->previous = NULL; @@ -162,7 +248,11 @@ void pa_signal_free(struct pa_signal_event *e) { else signals = e->next; +#ifdef HAVE_SIGACTION sigaction(e->sig, &e->saved_sigaction, NULL); +#else + signal(e->sig, e->saved_handler); +#endif if (e->destroy_callback) e->destroy_callback(api, e, e->userdata); diff --git a/polyp/mainloop-test.c b/polyp/mainloop-test.c index 0d40e76ed..dd8f8137c 100644 --- a/polyp/mainloop-test.c +++ b/polyp/mainloop-test.c @@ -111,7 +111,7 @@ int main(int argc, char *argv[]) { de = a->defer_new(a, dcb, NULL); assert(de); - gettimeofday(&tv, NULL); + pa_gettimeofday(&tv); tv.tv_sec += 10; te = a->time_new(a, &tv, tcb, NULL); diff --git a/polyp/mainloop.c b/polyp/mainloop.c index f6bb4145a..ada74afc8 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -26,13 +26,20 @@ #include #include #include -#include #include #include #include #include #include +#ifdef HAVE_SYS_POLL_H +#include +#else +#include "poll.h" +#endif + +#include "winsock.h" + #include "mainloop.h" #include "util.h" #include "idxset.h" @@ -103,6 +110,26 @@ static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enu e->destroy_callback = NULL; e->pollfd = NULL; +#ifdef OS_IS_WIN32 + { + fd_set xset; + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 0; + + FD_ZERO (&xset); + FD_SET (fd, &xset); + + if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset, + SELECT_TYPE_ARG5 &tv) == -1) && + (WSAGetLastError() == WSAENOTSOCK)) { + pa_log_warn(__FILE__": WARNING: cannot monitor non-socket file descriptors.\n"); + e->dead = 1; + } + } +#endif + pa_idxset_put(m->io_events, e, NULL); m->rebuild_pollfds = 1; return e; @@ -457,7 +484,7 @@ static int calc_next_timeout(struct pa_mainloop *m) { /* Let's save a system call */ if (!got_time) { - gettimeofday(&now, NULL); + pa_gettimeofday(&now); got_time = 1; } @@ -498,7 +525,7 @@ static int dispatch_timeout(struct pa_mainloop *m) { /* Let's save a system call */ if (!got_time) { - gettimeofday(&now, NULL); + pa_gettimeofday(&now); got_time = 1; } diff --git a/polyp/mcalign-test.c b/polyp/mcalign-test.c index e4a6a2393..2ace6e592 100644 --- a/polyp/mcalign-test.c +++ b/polyp/mcalign-test.c @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) { c.length = r; pa_mcalign_push(a, &c); - fprintf(stderr, "Read %u bytes\n", r); + fprintf(stderr, "Read %d bytes\n", r); c.index += r; diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 69db28754..dde5d8b69 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -25,7 +25,12 @@ #include #include + +#ifdef HAVE_SYS_POLL_H #include +#else +#include "poll.h" +#endif #include diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 55abe8e0f..5b4076f87 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -25,7 +25,12 @@ #include #include + +#ifdef HAVE_SYS_POLL_H #include +#else +#include "poll.h" +#endif #include diff --git a/polyp/module-combine.c b/polyp/module-combine.c index ca79d7df9..7283c5549 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -157,7 +157,7 @@ static void time_callback(struct pa_mainloop_api*a, struct pa_time_event* e, con adjust_rates(u); - gettimeofday(&n, NULL); + pa_gettimeofday(&n); n.tv_sec += u->adjust_time; u->sink->core->mainloop->time_restart(e, &n); } @@ -363,7 +363,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { pa_log_warn(__FILE__": WARNING: no slave sinks specified.\n"); if (u->adjust_time > 0) { - gettimeofday(&tv, NULL); + pa_gettimeofday(&tv); tv.tv_sec += u->adjust_time; u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u); } diff --git a/polyp/module-esound-sink.c b/polyp/module-esound-sink.c index 82c38cc28..191065069 100644 --- a/polyp/module-esound-sink.c +++ b/polyp/module-esound-sink.c @@ -144,7 +144,7 @@ static int do_write(struct userdata *u) { pa_module_set_used(u->module, pa_idxset_ncontents(u->sink->inputs) + pa_idxset_ncontents(u->sink->monitor_source->outputs)); if (!u->memchunk.length) - if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) + if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0) return 0; assert(u->memchunk.memblock && u->memchunk.length); diff --git a/polyp/module-mmkbd-evdev.c b/polyp/module-mmkbd-evdev.c index 758aaae54..5368af503 100644 --- a/polyp/module-mmkbd-evdev.c +++ b/polyp/module-mmkbd-evdev.c @@ -49,6 +49,17 @@ PA_MODULE_USAGE("device= sink=") #define DEFAULT_DEVICE "/dev/input/event0" +/* + * This isn't defined in older kernel headers and there is no way of + * detecting it. + */ +struct _input_id { + __u16 bustype; + __u16 vendor; + __u16 product; + __u16 version; +}; + static const char* const valid_modargs[] = { "device", "sink", @@ -136,7 +147,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; struct userdata *u; int version; - struct input_id input_id; + struct _input_id input_id; char name[256]; uint8_t evtype_bitmask[EV_MAX/8 + 1]; assert(c && m); diff --git a/polyp/module-null-sink.c b/polyp/module-null-sink.c index fcac1ea44..6c7a44f28 100644 --- a/polyp/module-null-sink.c +++ b/polyp/module-null-sink.c @@ -117,7 +117,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("NULL sink"); - gettimeofday(&tv, NULL); + pa_gettimeofday(&tv); u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u); u->block_size = pa_bytes_per_second(&ss) / 10; diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 15697582e..141eadd39 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -27,9 +27,20 @@ #include #include #include -#include #include +#include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H #include +#endif + +#include "winsock.h" #include "module.h" #include "socket-server.h" diff --git a/polyp/module-solaris.c b/polyp/module-solaris.c new file mode 100644 index 000000000..3eb66462e --- /dev/null +++ b/polyp/module-solaris.c @@ -0,0 +1,436 @@ +/* $Id: module-oss.c 333 2005-01-08 21:36:53Z lennart $ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "iochannel.h" +#include "sink.h" +#include "source.h" +#include "module.h" +#include "sample-util.h" +#include "util.h" +#include "modargs.h" +#include "xmalloc.h" +#include "log.h" +#include "module-solaris-symdef.h" + +PA_MODULE_AUTHOR("Pierre Ossman") +PA_MODULE_DESCRIPTION("Solaris Sink/Source") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= buffer_size=") + +#define PA_TYPEID_SOLARIS PA_TYPEID_MAKE('S', 'L', 'R', 'S') + +struct userdata { + struct pa_sink *sink; + struct pa_source *source; + struct pa_iochannel *io; + struct pa_core *core; + + struct pa_memchunk memchunk, silence; + + uint32_t sample_size; + unsigned int written_bytes, read_bytes; + + int fd; + struct pa_module *module; +}; + +static const char* const valid_modargs[] = { + "sink_name", + "source_name", + "device", + "record", + "playback", + "buffer_size", + "format", + "rate", + "channels", + NULL +}; + +#define DEFAULT_SINK_NAME "solaris_output" +#define DEFAULT_SOURCE_NAME "solaris_input" +#define DEFAULT_DEVICE "/dev/audio" + +#define CHUNK_SIZE 2048 + +static void update_usage(struct userdata *u) { + pa_module_set_used(u->module, + (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) + + (u->source ? pa_idxset_ncontents(u->source->outputs) : 0)); +} + +static void do_write(struct userdata *u) { + struct pa_memchunk *memchunk; + ssize_t r; + + assert(u); + + if (!u->sink || !pa_iochannel_is_writable(u->io)) + return; + + update_usage(u); + + memchunk = &u->memchunk; + + if (!memchunk->length) + if (pa_sink_render(u->sink, CHUNK_SIZE, memchunk) < 0) + memchunk = &u->silence; + + assert(memchunk->memblock); + assert(memchunk->memblock->data); + assert(memchunk->length); + + if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + return; + } + + if (memchunk == &u->silence) + assert(r % u->sample_size == 0); + else { + u->memchunk.index += r; + u->memchunk.length -= r; + + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; + } + } + + u->written_bytes += r; +} + +static void do_read(struct userdata *u) { + struct pa_memchunk memchunk; + int err, l; + ssize_t r; + assert(u); + + if (!u->source || !pa_iochannel_is_readable(u->io)) + return; + + update_usage(u); + + err = ioctl(u->fd, I_NREAD, &l); + assert(err >= 0); + + memchunk.memblock = pa_memblock_new(l, u->core->memblock_stat); + assert(memchunk.memblock); + if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { + pa_memblock_unref(memchunk.memblock); + if (errno != EAGAIN) + pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + return; + } + + assert(r <= (ssize_t) memchunk.memblock->length); + memchunk.length = memchunk.memblock->length = r; + memchunk.index = 0; + + pa_source_post(u->source, &memchunk); + pa_memblock_unref(memchunk.memblock); + + u->read_bytes += r; +} + +static void io_callback(struct pa_iochannel *io, void*userdata) { + struct userdata *u = userdata; + assert(u); + do_write(u); + do_read(u); +} + +static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { + pa_usec_t r = 0; + audio_info_t info; + int err; + struct userdata *u = s->userdata; + assert(s && u && u->sink); + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + r += pa_bytes_to_usec(u->written_bytes, &s->sample_spec); + r -= pa_bytes_to_usec(info.play.samples * u->sample_size, &s->sample_spec); + + if (u->memchunk.memblock) + r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); + + return r; +} + +static pa_usec_t source_get_latency_cb(struct pa_source *s) { + pa_usec_t r = 0; + struct userdata *u = s->userdata; + audio_info_t info; + int err; + assert(s && u && u->source); + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + r += pa_bytes_to_usec(info.record.samples * u->sample_size, &s->sample_spec); + r -= pa_bytes_to_usec(u->read_bytes, &s->sample_spec); + + return r; +} + +static int pa_solaris_auto_format(int fd, int mode, struct pa_sample_spec *ss) { + audio_info_t info; + + AUDIO_INITINFO(&info); + + if (mode != O_RDONLY) { + info.play.sample_rate = ss->rate; + info.play.channels = ss->channels; + switch (ss->format) { + case PA_SAMPLE_U8: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_LINEAR; + break; + case PA_SAMPLE_ALAW: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_ALAW; + break; + case PA_SAMPLE_ULAW: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_ULAW; + break; + case PA_SAMPLE_S16NE: + info.play.precision = 16; + info.play.encoding = AUDIO_ENCODING_LINEAR; + break; + default: + return -1; + } + } + + if (mode != O_WRONLY) { + info.record.sample_rate = ss->rate; + info.record.channels = ss->channels; + switch (ss->format) { + case PA_SAMPLE_U8: + info.record.precision = 8; + info.record.encoding = AUDIO_ENCODING_LINEAR; + break; + case PA_SAMPLE_ALAW: + info.record.precision = 8; + info.record.encoding = AUDIO_ENCODING_ALAW; + break; + case PA_SAMPLE_ULAW: + info.record.precision = 8; + info.record.encoding = AUDIO_ENCODING_ULAW; + break; + case PA_SAMPLE_S16NE: + info.record.precision = 16; + info.record.encoding = AUDIO_ENCODING_LINEAR; + break; + default: + return -1; + } + } + + if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format.\n"); + else + pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + +static int pa_solaris_set_buffer(int fd, int buffer_size) { + audio_info_t info; + + AUDIO_INITINFO(&info); + + info.record.buffer_size = buffer_size; + + if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size.\n"); + else + pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct userdata *u = NULL; + const char *p; + int fd = -1; + int buffer_size; + int mode; + int record = 1, playback = 1; + struct pa_sample_spec ss; + struct pa_modargs *ma = NULL; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments.\n"); + goto fail; + } + + if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { + pa_log(__FILE__": record= and playback= expect numeric argument.\n"); + goto fail; + } + + if (!playback && !record) { + pa_log(__FILE__": neither playback nor record enabled for device.\n"); + goto fail; + } + + mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); + + buffer_size = -1; + if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) { + pa_log(__FILE__": failed to parse buffer size argument\n"); + goto fail; + } + + ss = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + pa_log(__FILE__": failed to parse sample specification\n"); + goto fail; + } + + if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode)) < 0) + goto fail; + + pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + + if (pa_solaris_auto_format(fd, mode, &ss) < 0) + goto fail; + + if ((mode != O_WRONLY) && (buffer_size >= 1)) + if (pa_solaris_set_buffer(fd, buffer_size) < 0) + goto fail; + + u = pa_xmalloc(sizeof(struct userdata)); + u->core = c; + + if (mode != O_WRONLY) { + u->source = pa_source_new(c, PA_TYPEID_SOLARIS, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); + assert(u->source); + u->source->userdata = u; + u->source->get_latency = source_get_latency_cb; + pa_source_set_owner(u->source, m); + u->source->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + } else + u->source = NULL; + + if (mode != O_RDONLY) { + u->sink = pa_sink_new(c, PA_TYPEID_SOLARIS, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); + assert(u->sink); + u->sink->get_latency = sink_get_latency_cb; + u->sink->userdata = u; + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + } else + u->sink = NULL; + + assert(u->source || u->sink); + + u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0); + assert(u->io); + pa_iochannel_set_callback(u->io, io_callback, u); + u->fd = fd; + + u->memchunk.memblock = NULL; + u->memchunk.length = 0; + u->sample_size = pa_frame_size(&ss); + + u->silence.memblock = pa_memblock_new(u->silence.length = CHUNK_SIZE, u->core->memblock_stat); + assert(u->silence.memblock); + pa_silence_memblock(u->silence.memblock, &ss); + u->silence.index = 0; + + u->written_bytes = 0; + u->read_bytes = 0; + + u->module = m; + m->userdata = u; + + pa_modargs_free(ma); + + return 0; + +fail: + if (fd >= 0) + close(fd); + + if (ma) + pa_modargs_free(ma); + + return -1; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + if (u->silence.memblock) + pa_memblock_unref(u->silence.memblock); + + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + } + + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + } + + pa_iochannel_free(u->io); + pa_xfree(u); +} diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index 9da87b3d2..c6a35ca6b 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -284,7 +283,7 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman return; } - gettimeofday(&now, NULL); + pa_gettimeofday(&now); if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) { /* local and remote seem to have synchronized clocks */ @@ -324,7 +323,7 @@ static void request_latency(struct userdata *u) { pa_tagstruct_putu32(t, tag = u->ctag++); pa_tagstruct_putu32(t, u->channel); - gettimeofday(&now, NULL); + pa_gettimeofday(&now); pa_tagstruct_put_timeval(t, &now); pa_tagstruct_putu64(t, 0); @@ -536,7 +535,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, request_latency(u); - gettimeofday(&ntv, NULL); + pa_gettimeofday(&ntv); ntv.tv_sec += LATENCY_INTERVAL; m->time_restart(e, &ntv); } @@ -650,7 +649,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { pa_source_set_owner(u->source, m); #endif - gettimeofday(&ntv, NULL); + pa_gettimeofday(&ntv); ntv.tv_sec += LATENCY_INTERVAL; u->time_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, u); diff --git a/polyp/module-waveout.c b/polyp/module-waveout.c new file mode 100644 index 000000000..4e01bc754 --- /dev/null +++ b/polyp/module-waveout.c @@ -0,0 +1,583 @@ +/* $Id: module-waveout.c 333 2005-01-08 21:36:53Z lennart $ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "sink.h" +#include "source.h" +#include "module.h" +#include "mainloop-api.h" +#include "modargs.h" +#include "sample-util.h" +#include "util.h" +#include "log.h" +#include "xmalloc.h" +#include "module-waveout-symdef.h" + +PA_MODULE_AUTHOR("Pierre Ossman") +PA_MODULE_DESCRIPTION("Windows waveOut Sink/Source") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink_name= source_name= record= playback= format= channels= rate= fragments= fragment_size=") + +#define PA_TYPEID_WAVEOUT PA_TYPEID_MAKE('W', 'A', 'V', 'E') + +#define DEFAULT_SINK_NAME "wave_output" +#define DEFAULT_SOURCE_NAME "wave_input" + +struct userdata { + struct pa_sink *sink; + struct pa_source *source; + struct pa_core *core; + struct pa_time_event *event; + struct pa_defer_event *defer; + pa_usec_t poll_timeout; + + uint32_t fragments, fragment_size; + + uint32_t free_ofrags, free_ifrags; + + DWORD written_bytes; + + int cur_ohdr, cur_ihdr; + unsigned int oremain; + WAVEHDR *ohdrs, *ihdrs; + struct pa_memchunk silence; + + HWAVEOUT hwo; + HWAVEIN hwi; + struct pa_module *module; + + CRITICAL_SECTION crit; +}; + +static const char* const valid_modargs[] = { + "sink_name", + "source_name", + "record", + "playback", + "fragments", + "fragment_size", + "format", + "rate", + "channels", + NULL +}; + +static void update_usage(struct userdata *u) { + pa_module_set_used(u->module, + (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) + + (u->source ? pa_idxset_ncontents(u->source->outputs) : 0)); +} + +static void do_write(struct userdata *u) +{ + uint32_t free_frags, remain; + struct pa_memchunk memchunk, *cur_chunk; + WAVEHDR *hdr; + MMRESULT res; + + if (!u->sink) + return; + + EnterCriticalSection(&u->crit); + + free_frags = u->free_ofrags; + u->free_ofrags = 0; + + LeaveCriticalSection(&u->crit); + + while (free_frags) { + hdr = &u->ohdrs[u->cur_ohdr]; + if (hdr->dwFlags & WHDR_PREPARED) + waveOutUnprepareHeader(u->hwo, hdr, sizeof(WAVEHDR)); + + remain = u->oremain; + while (remain) { + cur_chunk = &memchunk; + + if (pa_sink_render(u->sink, remain, cur_chunk) < 0) { + /* + * Don't fill with silence unless we're getting close to + * underflowing. + */ + if (free_frags > u->fragments/2) + cur_chunk = &u->silence; + else { + EnterCriticalSection(&u->crit); + + u->free_ofrags += free_frags; + + LeaveCriticalSection(&u->crit); + + u->oremain = remain; + return; + } + } + + assert(cur_chunk->memblock); + assert(cur_chunk->memblock->data); + assert(cur_chunk->length); + + memcpy(hdr->lpData + u->fragment_size - remain, + (char*)cur_chunk->memblock->data + cur_chunk->index, + (cur_chunk->length < remain)?cur_chunk->length:remain); + + remain -= (cur_chunk->length < remain)?cur_chunk->length:remain; + + if (cur_chunk != &u->silence) { + pa_memblock_unref(cur_chunk->memblock); + cur_chunk->memblock = NULL; + } + } + + res = waveOutPrepareHeader(u->hwo, hdr, sizeof(WAVEHDR)); + if (res != MMSYSERR_NOERROR) { + pa_log_error(__FILE__ ": ERROR: Unable to prepare waveOut block: %d\n", + res); + } + res = waveOutWrite(u->hwo, hdr, sizeof(WAVEHDR)); + if (res != MMSYSERR_NOERROR) { + pa_log_error(__FILE__ ": ERROR: Unable to write waveOut block: %d\n", + res); + } + + u->written_bytes += u->fragment_size; + + free_frags--; + u->cur_ohdr++; + u->cur_ohdr %= u->fragments; + u->oremain = u->fragment_size; + } +} + +static void do_read(struct userdata *u) +{ + uint32_t free_frags; + struct pa_memchunk memchunk; + WAVEHDR *hdr; + MMRESULT res; + + if (!u->source) + return; + + EnterCriticalSection(&u->crit); + + free_frags = u->free_ifrags; + u->free_ifrags = 0; + + LeaveCriticalSection(&u->crit); + + while (free_frags) { + hdr = &u->ihdrs[u->cur_ihdr]; + if (hdr->dwFlags & WHDR_PREPARED) + waveInUnprepareHeader(u->hwi, hdr, sizeof(WAVEHDR)); + + if (hdr->dwBytesRecorded) { + memchunk.memblock = pa_memblock_new(hdr->dwBytesRecorded, u->core->memblock_stat); + assert(memchunk.memblock); + + memcpy((char*)memchunk.memblock->data, hdr->lpData, hdr->dwBytesRecorded); + + memchunk.length = memchunk.memblock->length = hdr->dwBytesRecorded; + memchunk.index = 0; + + pa_source_post(u->source, &memchunk); + pa_memblock_unref(memchunk.memblock); + } + + res = waveInPrepareHeader(u->hwi, hdr, sizeof(WAVEHDR)); + if (res != MMSYSERR_NOERROR) { + pa_log_error(__FILE__ ": ERROR: Unable to prepare waveIn block: %d\n", + res); + } + res = waveInAddBuffer(u->hwi, hdr, sizeof(WAVEHDR)); + if (res != MMSYSERR_NOERROR) { + pa_log_error(__FILE__ ": ERROR: Unable to add waveIn block: %d\n", + res); + } + + free_frags--; + u->cur_ihdr++; + u->cur_ihdr %= u->fragments; + } +} + +static void poll_cb(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + struct timeval ntv; + + assert(u); + + update_usage(u); + + do_write(u); + do_read(u); + + pa_gettimeofday(&ntv); + pa_timeval_add(&ntv, u->poll_timeout); + + a->time_restart(e, &ntv); +} + +static void defer_cb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { + struct userdata *u = userdata; + + assert(u); + + a->defer_enable(e, 0); + + do_write(u); + do_read(u); +} + +static void CALLBACK chunk_done_cb(HWAVEOUT hwo, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) { + struct userdata *u = (struct userdata *)inst; + + if (msg != WOM_DONE) + return; + + EnterCriticalSection(&u->crit); + + u->free_ofrags++; + assert(u->free_ofrags <= u->fragments); + + LeaveCriticalSection(&u->crit); +} + +static void CALLBACK chunk_ready_cb(HWAVEIN hwi, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) { + struct userdata *u = (struct userdata *)inst; + + if (msg != WIM_DATA) + return; + + EnterCriticalSection(&u->crit); + + u->free_ifrags++; + assert(u->free_ifrags <= u->fragments); + + LeaveCriticalSection(&u->crit); +} + +static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { + struct userdata *u = s->userdata; + uint32_t free_frags; + MMTIME mmt; + assert(s && u && u->sink); + + memset(&mmt, 0, sizeof(mmt)); + mmt.wType = TIME_BYTES; + if (waveOutGetPosition(u->hwo, &mmt, sizeof(mmt)) == MMSYSERR_NOERROR) + return pa_bytes_to_usec(u->written_bytes - mmt.u.cb, &s->sample_spec); + else { + EnterCriticalSection(&u->crit); + + free_frags = u->free_ofrags; + + LeaveCriticalSection(&u->crit); + + return pa_bytes_to_usec((u->fragments - free_frags) * u->fragment_size, + &s->sample_spec); + } +} + +static pa_usec_t source_get_latency_cb(struct pa_source *s) { + pa_usec_t r = 0; + struct userdata *u = s->userdata; + uint32_t free_frags; + assert(s && u && u->sink); + + EnterCriticalSection(&u->crit); + + free_frags = u->free_ifrags; + + LeaveCriticalSection(&u->crit); + + r += pa_bytes_to_usec((free_frags + 1) * u->fragment_size, &s->sample_spec); + + fprintf(stderr, "Latency: %d us\n", (int)r); + + return r; +} + +static void notify_sink_cb(struct pa_sink *s) { + struct userdata *u = s->userdata; + assert(u); + + u->core->mainloop->defer_enable(u->defer, 1); +} + +static void notify_source_cb(struct pa_source *s) { + struct userdata *u = s->userdata; + assert(u); + + u->core->mainloop->defer_enable(u->defer, 1); +} + +static int ss_to_waveformat(struct pa_sample_spec *ss, LPWAVEFORMATEX wf) { + wf->wFormatTag = WAVE_FORMAT_PCM; + + if (ss->channels > 2) { + pa_log_error(__FILE__": ERROR: More than two channels not supported.\n"); + return -1; + } + + wf->nChannels = ss->channels; + + switch (ss->rate) { + case 8000: + case 11025: + case 22005: + case 44100: + break; + default: + pa_log_error(__FILE__": ERROR: Unsupported sample rate.\n"); + return -1; + } + + wf->nSamplesPerSec = ss->rate; + + if (ss->format == PA_SAMPLE_U8) + wf->wBitsPerSample = 8; + else if (ss->format == PA_SAMPLE_S16NE) + wf->wBitsPerSample = 16; + else { + pa_log_error(__FILE__": ERROR: Unsupported sample format.\n"); + return -1; + } + + wf->nBlockAlign = wf->nChannels * wf->wBitsPerSample/8; + wf->nAvgBytesPerSec = wf->nSamplesPerSec * wf->nBlockAlign; + + wf->cbSize = 0; + + return 0; +} + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct userdata *u = NULL; + HWAVEOUT hwo = INVALID_HANDLE_VALUE; + HWAVEIN hwi = INVALID_HANDLE_VALUE; + WAVEFORMATEX wf; + int nfrags, frag_size; + int record = 1, playback = 1; + struct pa_sample_spec ss; + struct pa_modargs *ma = NULL; + unsigned int i; + struct timeval tv; + + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments.\n"); + goto fail; + } + + if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { + pa_log(__FILE__": record= and playback= expect boolean argument.\n"); + goto fail; + } + + if (!playback && !record) { + pa_log(__FILE__": neither playback nor record enabled for device.\n"); + goto fail; + } + + nfrags = 20; + frag_size = 1024; + if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { + pa_log(__FILE__": failed to parse fragments arguments\n"); + goto fail; + } + + ss = c->default_sample_spec; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + pa_log(__FILE__": failed to parse sample specification\n"); + goto fail; + } + + if (ss_to_waveformat(&ss, &wf) < 0) + goto fail; + + u = pa_xmalloc(sizeof(struct userdata)); + + if (record) { + if (waveInOpen(&hwi, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_ready_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) + goto fail; + if (waveInStart(hwi) != MMSYSERR_NOERROR) + goto fail; + pa_log_debug(__FILE__": Opened waveIn subsystem.\n"); + } + + if (playback) { + if (waveOutOpen(&hwo, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) + goto fail; + pa_log_debug(__FILE__": Opened waveOut subsystem.\n"); + } + + InitializeCriticalSection(&u->crit); + + if (hwi != INVALID_HANDLE_VALUE) { + u->source = pa_source_new(c, PA_TYPEID_WAVEOUT, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); + assert(u->source); + u->source->userdata = u; + u->source->notify = notify_source_cb; + u->source->get_latency = source_get_latency_cb; + pa_source_set_owner(u->source, m); + u->source->description = pa_sprintf_malloc("Windows waveIn PCM"); + } else + u->source = NULL; + + if (hwo != INVALID_HANDLE_VALUE) { + u->sink = pa_sink_new(c, PA_TYPEID_WAVEOUT, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); + assert(u->sink); + u->sink->notify = notify_sink_cb; + u->sink->get_latency = sink_get_latency_cb; + u->sink->userdata = u; + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("Windows waveOut PCM"); + } else + u->sink = NULL; + + assert(u->source || u->sink); + + u->core = c; + u->hwi = hwi; + u->hwo = hwo; + + u->fragments = nfrags; + u->free_ifrags = u->fragments; + u->free_ofrags = u->fragments; + u->fragment_size = frag_size - (frag_size % pa_frame_size(&ss)); + + u->written_bytes = 0; + + u->oremain = u->fragment_size; + + u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 3, &ss); + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, u->poll_timeout); + + u->event = c->mainloop->time_new(c->mainloop, &tv, poll_cb, u); + assert(u->event); + + u->defer = c->mainloop->defer_new(c->mainloop, defer_cb, u); + assert(u->defer); + c->mainloop->defer_enable(u->defer, 0); + + u->cur_ihdr = 0; + u->cur_ohdr = 0; + u->ihdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments); + assert(u->ihdrs); + u->ohdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments); + assert(u->ohdrs); + for (i = 0;i < u->fragments;i++) { + u->ihdrs[i].dwBufferLength = u->fragment_size; + u->ohdrs[i].dwBufferLength = u->fragment_size; + u->ihdrs[i].lpData = pa_xmalloc(u->fragment_size); + assert(u->ihdrs); + u->ohdrs[i].lpData = pa_xmalloc(u->fragment_size); + assert(u->ohdrs); + } + + u->silence.length = u->fragment_size; + u->silence.memblock = pa_memblock_new(u->silence.length, u->core->memblock_stat); + assert(u->silence.memblock); + pa_silence_memblock(u->silence.memblock, &ss); + u->silence.index = 0; + + u->module = m; + m->userdata = u; + + pa_modargs_free(ma); + + return 0; + +fail: + if (hwi != INVALID_HANDLE_VALUE) + waveInClose(hwi); + + if (hwo != INVALID_HANDLE_VALUE) + waveOutClose(hwo); + + if (u) + pa_xfree(u); + + if (ma) + pa_modargs_free(ma); + + return -1; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + unsigned int i; + + assert(c && m); + + if (!(u = m->userdata)) + return; + + if (u->event) + c->mainloop->time_free(u->event); + + if (u->defer) + c->mainloop->defer_free(u->defer); + + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + } + + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + } + + if (u->hwi != INVALID_HANDLE_VALUE) { + waveInReset(u->hwi); + waveInClose(u->hwi); + } + + if (u->hwo != INVALID_HANDLE_VALUE) { + waveOutReset(u->hwo); + waveOutClose(u->hwo); + } + + for (i = 0;i < u->fragments;i++) { + pa_xfree(u->ihdrs[i].lpData); + pa_xfree(u->ohdrs[i].lpData); + } + + pa_xfree(u->ihdrs); + pa_xfree(u->ohdrs); + + DeleteCriticalSection(&u->crit); + + pa_xfree(u); +} diff --git a/polyp/module.c b/polyp/module.c index aedaae02a..0a3d569b2 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -47,7 +47,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, pa_module_unload_unused(c); - gettimeofday(&ntv, NULL); + pa_gettimeofday(&ntv); ntv.tv_sec += UNLOAD_POLL_TIME; m->time_restart(e, &ntv); } @@ -98,7 +98,7 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char if (!c->module_auto_unload_event) { struct timeval ntv; - gettimeofday(&ntv, NULL); + pa_gettimeofday(&ntv); ntv.tv_sec += UNLOAD_POLL_TIME; c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } diff --git a/polyp/oss-util.c b/polyp/oss-util.c index 8c83cbbf6..799bc40a3 100644 --- a/polyp/oss-util.c +++ b/polyp/oss-util.c @@ -92,7 +92,7 @@ fail: int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { int format, channels, speed, reqformat; - static const int format_trans[] = { + static const int format_trans[PA_SAMPLE_MAX] = { [PA_SAMPLE_U8] = AFMT_U8, [PA_SAMPLE_ALAW] = AFMT_A_LAW, [PA_SAMPLE_ULAW] = AFMT_MU_LAW, diff --git a/polyp/pacat.c b/polyp/pacat.c index 5910d13fc..1bba2ee47 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -480,8 +480,12 @@ int main(int argc, char *argv[]) { assert(r == 0); pa_signal_new(SIGINT, exit_signal_callback, NULL); pa_signal_new(SIGTERM, exit_signal_callback, NULL); +#ifdef SIGUSR1 pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL); +#endif +#ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); +#endif if (!(stdio_event = mainloop_api->io_new(mainloop_api, mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, diff --git a/polyp/pactl.c b/polyp/pactl.c index 423cce959..725b5460a 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -739,7 +739,9 @@ int main(int argc, char *argv[]) { r = pa_signal_init(mainloop_api); assert(r == 0); pa_signal_new(SIGINT, exit_signal_callback, NULL); +#ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); +#endif if (!(context = pa_context_new(mainloop_api, client_name))) { fprintf(stderr, "pa_context_new() failed.\n"); diff --git a/polyp/paplay.c b/polyp/paplay.c index 2eaf07c1e..4ace1973f 100644 --- a/polyp/paplay.c +++ b/polyp/paplay.c @@ -338,7 +338,9 @@ int main(int argc, char *argv[]) { r = pa_signal_init(mainloop_api); assert(r == 0); pa_signal_new(SIGINT, exit_signal_callback, NULL); +#ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); +#endif /* Create a new connection context */ if (!(context = pa_context_new(mainloop_api, client_name))) { diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index 7a9e9c680..60dd911c3 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -32,6 +32,7 @@ #include "xmalloc.h" #include "llist.h" #include "log.h" +#include "util.h" /*#define DEBUG_OPCODES */ @@ -245,7 +246,7 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time r->userdata = userdata; r->tag = tag; - gettimeofday(&tv, NULL); + pa_gettimeofday(&tv); tv.tv_sec += timeout; r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r); diff --git a/polyp/pid.c b/polyp/pid.c index 2fac687ec..ae3dc7f51 100644 --- a/polyp/pid.c +++ b/polyp/pid.c @@ -35,6 +35,10 @@ #include #include +#ifdef HAVE_WINDOWS_H +#include +#endif + #include "pid.h" #include "util.h" #include "log.h" @@ -130,6 +134,10 @@ int pa_pid_file_create(void) { pid_t pid; size_t l; +#ifdef OS_IS_WIN32 + HANDLE process; +#endif + pa_runtime_path("pid", fn, sizeof(fn)); if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0) @@ -138,7 +146,12 @@ int pa_pid_file_create(void) { if ((pid = read_pid(fn, fd)) == (pid_t) -1) pa_log(__FILE__": corrupt PID file, overwriting.\n"); else if (pid > 0) { +#ifdef OS_IS_WIN32 + if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) { + CloseHandle(process); +#else if (kill(pid, 0) >= 0 || errno != ESRCH) { +#endif pa_log(__FILE__": daemon already running.\n"); goto fail; } @@ -198,6 +211,12 @@ int pa_pid_file_remove(void) { goto fail; } +#ifdef OS_IS_WIN32 + pa_lock_fd(fd, 0); + close(fd); + fd = -1; +#endif + if (unlink(fn) < 0) { pa_log(__FILE__": failed to remove PID file '%s': %s\n", fn, strerror(errno)); goto fail; @@ -223,6 +242,8 @@ int pa_pid_file_check_running(pid_t *pid) { return pa_pid_file_kill(0, pid); } +#ifndef OS_IS_WIN32 + /* Kill a current running daemon. Return non-zero on success, -1 * otherwise. If successful *pid contains the PID of the daemon * process. */ @@ -242,7 +263,7 @@ int pa_pid_file_kill(int sig, pid_t *pid) { if ((*pid = read_pid(fn, fd)) == (pid_t) -1) goto fail; - + ret = kill(*pid, sig); fail: @@ -255,3 +276,11 @@ fail: return ret; } + +#else /* OS_IS_WIN32 */ + +int pa_pid_file_kill(int sig, pid_t *pid) { + return -1; +} + +#endif diff --git a/polyp/poll.c b/polyp/poll.c new file mode 100644 index 000000000..6a260daf0 --- /dev/null +++ b/polyp/poll.c @@ -0,0 +1,190 @@ +/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */ + +/*** + Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 2005, Cendio AB. + This file is part of polypaudio. + Based on work for the GNU C Library. + + polypaudio is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with polypaudio; If not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. +***/ + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#include "winsock.h" + +#ifndef HAVE_SYS_POLL_H + +#include "util.h" +#include "poll.h" + +int poll (struct pollfd *fds, unsigned long int nfds, int timeout) { + struct timeval tv; + fd_set rset, wset, xset; + struct pollfd *f; + int ready; + int maxfd = 0; + char data[64]; + + FD_ZERO (&rset); + FD_ZERO (&wset); + FD_ZERO (&xset); + + if (nfds == 0) { + if (timeout >= 0) { + pa_msleep(timeout); + return 0; + } + +#ifdef OS_IS_WIN32 + /* + * Windows does not support signals properly so waiting for them would + * mean a deadlock. + */ + pa_msleep(100); + return 0; +#else + return select(0, NULL, NULL, NULL, NULL); +#endif + } + + for (f = fds; f < &fds[nfds]; ++f) { + if (f->fd != -1) { + if (f->events & POLLIN) + FD_SET (f->fd, &rset); + if (f->events & POLLOUT) + FD_SET (f->fd, &wset); + if (f->events & POLLPRI) + FD_SET (f->fd, &xset); + if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) + maxfd = f->fd; + } + } + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset, + SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset, + SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv)); + if ((ready == -1) && (errno == EBADF)) { + ready = 0; + + FD_ZERO (&rset); + FD_ZERO (&wset); + FD_ZERO (&xset); + + maxfd = -1; + + for (f = fds; f < &fds[nfds]; ++f) { + if (f->fd != -1) { + fd_set sngl_rset, sngl_wset, sngl_xset; + + FD_ZERO (&sngl_rset); + FD_ZERO (&sngl_wset); + FD_ZERO (&sngl_xset); + + if (f->events & POLLIN) + FD_SET (f->fd, &sngl_rset); + if (f->events & POLLOUT) + FD_SET (f->fd, &sngl_wset); + if (f->events & POLLPRI) + FD_SET (f->fd, &sngl_xset); + if (f->events & (POLLIN|POLLOUT|POLLPRI)) { + struct timeval singl_tv; + + singl_tv.tv_sec = 0; + singl_tv.tv_usec = 0; + + if (select((SELECT_TYPE_ARG1) f->fd, SELECT_TYPE_ARG234 &rset, + SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset, + SELECT_TYPE_ARG5 &singl_tv) != -1) { + if (f->events & POLLIN) + FD_SET (f->fd, &rset); + if (f->events & POLLOUT) + FD_SET (f->fd, &wset); + if (f->events & POLLPRI) + FD_SET (f->fd, &xset); + if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) + maxfd = f->fd; + ++ready; + } else if (errno == EBADF) + f->revents |= POLLNVAL; + } + } + } + + if (ready) { + /* Linux alters the tv struct... but it shouldn't matter here ... + * as we're going to be a little bit out anyway as we've just eaten + * more than a couple of cpu cycles above */ + ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset, + SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset, + SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv)); + } + } + +#ifdef OS_IS_WIN32 + errno = WSAGetLastError(); +#endif + + if (ready > 0) { + ready = 0; + for (f = fds; f < &fds[nfds]; ++f) { + f->revents = 0; + if (f->fd != -1) { + if (FD_ISSET (f->fd, &rset)) { + /* support for POLLHUP. An hung up descriptor does not + increase the return value! */ + if (recv (f->fd, data, 64, MSG_PEEK) == -1) { + if (errno == ESHUTDOWN || errno == ECONNRESET || + errno == ECONNABORTED || errno == ENETRESET) { + fprintf(stderr, "Hangup\n"); + f->revents |= POLLHUP; + } + } + + if (f->revents == 0) + f->revents |= POLLIN; + } + if (FD_ISSET (f->fd, &wset)) + f->revents |= POLLOUT; + if (FD_ISSET (f->fd, &xset)) + f->revents |= POLLPRI; + } + if (f->revents) + ready++; + } + } + + return ready; +} + +#endif /* HAVE_SYS_POLL_H */ diff --git a/polyp/poll.h b/polyp/poll.h new file mode 100644 index 000000000..573f90eac --- /dev/null +++ b/polyp/poll.h @@ -0,0 +1,57 @@ +/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */ + +/*** + Compatibility definitions for System V `poll' interface. + Copyright (C) 1994,96,97,98,99,2000,2001,2004 Free Software Foundation, Inc. + Copyright (C) 2005, Cendio AB. + This file is part of polypaudio. + Based on work for the GNU C Library. + + polypaudio is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with polypaudio; If not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. +***/ + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ + + +/* Type used for the number of file descriptors. */ +typedef unsigned long int nfds_t; + +/* Data structure describing a polling request. */ +struct pollfd + { + int fd; /* File descriptor to poll. */ + short int events; /* Types of events poller cares about. */ + short int revents; /* Types of events that actually occurred. */ + }; + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. */ +extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index bca7d7ea2..f97d9b827 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -28,13 +28,24 @@ #include #include #include -#include -#include #include #include #include -#include #include +#include + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif + +#include "winsock.h" #include "polyplib-internal.h" #include "polyplib-context.h" @@ -110,8 +121,10 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->autospawn_lock_fd = -1; memset(&c->spawn_api, 0, sizeof(c->spawn_api)); c->do_autospawn = 0; - + +#ifdef SIGPIPE pa_check_signal_is_blocked(SIGPIPE); +#endif c->conf = pa_client_conf_new(); pa_client_conf_load(c->conf, NULL); @@ -372,6 +385,8 @@ finish: static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata); +#ifndef OS_IS_WIN32 + static int context_connect_spawn(struct pa_context *c) { pid_t pid; int status, r; @@ -485,6 +500,8 @@ fail: return -1; } +#endif /* OS_IS_WIN32 */ + static int try_next_connection(struct pa_context *c) { char *u = NULL; int r = -1; @@ -499,10 +516,12 @@ static int try_next_connection(struct pa_context *c) { if (!u) { +#ifndef OS_IS_WIN32 if (c->do_autospawn) { r = context_connect_spawn(c); goto finish; } +#endif pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); goto finish; diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index d1b3a27f0..8677c813f 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -93,6 +93,7 @@ struct pa_stream { uint32_t requested_bytes; uint64_t counter; pa_usec_t previous_time; + pa_usec_t previous_ipol_time; enum pa_stream_state state; struct pa_mcalign *mcalign; diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 6a73c608f..b6a091b34 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -66,6 +66,7 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st s->counter = 0; s->previous_time = 0; + s->previous_ipol_time = 0; s->corked = 0; s->interpolate = 0; @@ -217,7 +218,7 @@ static void ipol_callback(struct pa_mainloop_api *m, struct pa_time_event *e, co s->ipol_requested = 1; } - gettimeofday(&tv2, NULL); + pa_gettimeofday(&tv2); pa_timeval_add(&tv2, LATENCY_IPOL_INTERVAL_USEC); m->time_restart(e, &tv2); @@ -256,7 +257,7 @@ void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32 struct timeval tv; pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); - gettimeofday(&tv, NULL); + pa_gettimeofday(&tv); tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */ assert(!s->ipol_event); @@ -412,7 +413,7 @@ static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t c pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } else { - gettimeofday(&now, NULL); + pa_gettimeofday(&now); if (pa_timeval_cmp(&local, &remote) <= 0 && pa_timeval_cmp(&remote, &now) <= 0) { /* local and remote seem to have synchronized clocks */ @@ -470,7 +471,7 @@ struct pa_operation* pa_stream_get_latency_info(struct pa_stream *s, void (*cb)( pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); - gettimeofday(&now, NULL); + pa_gettimeofday(&now); pa_tagstruct_put_timeval(t, &now); pa_tagstruct_putu64(t, s->counter); @@ -581,7 +582,7 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru s->ipol_usec = pa_stream_get_interpolated_time(s); else if (s->corked && !b) /* Unpausing */ - gettimeofday(&s->ipol_timestamp, NULL); + pa_gettimeofday(&s->ipol_timestamp); } s->corked = b; @@ -702,7 +703,7 @@ pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info * usec = s->previous_time; s->previous_time = usec; - + return usec; } @@ -762,10 +763,11 @@ pa_usec_t pa_stream_get_interpolated_time(struct pa_stream *s) { usec = s->ipol_usec + pa_timeval_age(&s->ipol_timestamp); } - if (usec < s->previous_time) - usec = s->previous_time; + if (usec < s->previous_ipol_time) + usec = s->previous_ipol_time; + + s->previous_ipol_time = usec; - s->previous_time = usec; return usec; } diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index d99b721c1..18ecb0ac1 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -239,11 +239,14 @@ static void* connection_write(struct connection *c, size_t length) { return (uint8_t*) c->write_data+i; } -static void format_esd2native(int format, struct pa_sample_spec *ss) { +static void format_esd2native(int format, int swap_bytes, struct pa_sample_spec *ss) { assert(ss); ss->channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1; - ss->format = ((format & ESD_MASK_BITS) == ESD_BITS16) ? PA_SAMPLE_S16NE : PA_SAMPLE_U8; + if ((format & ESD_MASK_BITS) == ESD_BITS16) + ss->format = swap_bytes ? PA_SAMPLE_S16RE : PA_SAMPLE_S16NE; + else + ss->format = PA_SAMPLE_U8; } static int format_native2esd(struct pa_sample_spec *ss) { @@ -303,7 +306,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); ss.rate = rate; - format_esd2native(format, &ss); + format_esd2native(format, c->swap_byte_order, &ss); if (!pa_sample_spec_valid(&ss)) { pa_log(__FILE__": invalid sample specification\n"); @@ -359,7 +362,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); ss.rate = rate; - format_esd2native(format, &ss); + format_esd2native(format, c->swap_byte_order, &ss); if (!pa_sample_spec_valid(&ss)) { pa_log(__FILE__": invalid sample specification.\n"); @@ -426,7 +429,6 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons latency = 0; else { double usec = pa_sink_get_latency(sink); - usec += PLAYBACK_BUFFER_SECONDS*1000000; /* A better estimation would be a good idea! */ latency = (int) ((usec*44100)/1000000); } @@ -603,7 +605,7 @@ static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, con rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); ss.rate = rate; - format_esd2native(format, &ss); + format_esd2native(format, c->swap_byte_order, &ss); sc_length = (size_t) maybe_swap_endian_32(c->swap_byte_order, (*((int*)data + 2))); @@ -1099,7 +1101,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo if (!c->authorized) { struct timeval tv; - gettimeofday(&tv, NULL); + pa_gettimeofday(&tv); tv.tv_sec += AUTH_TIMEOUT; c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c); } else diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 7e1a88949..90dbdaf5b 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -928,7 +928,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq)); pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq)); pa_tagstruct_put_timeval(reply, &tv); - gettimeofday(&now, NULL); + pa_gettimeofday(&now); pa_tagstruct_put_timeval(reply, &now); pa_tagstruct_putu64(reply, counter); pa_pstream_send_tagstruct(c->pstream, reply); @@ -971,7 +971,7 @@ static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command pa_tagstruct_put_boolean(reply, 0); pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq)); pa_tagstruct_put_timeval(reply, &tv); - gettimeofday(&now, NULL); + pa_gettimeofday(&now); pa_tagstruct_put_timeval(reply, &now); pa_tagstruct_putu64(reply, counter); pa_pstream_send_tagstruct(c->pstream, reply); @@ -2024,7 +2024,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo if (!c->authorized) { struct timeval tv; - gettimeofday(&tv, NULL); + pa_gettimeofday(&tv); tv.tv_sec += AUTH_TIMEOUT; c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c); } else diff --git a/polyp/pstream.c b/polyp/pstream.c index c081c2424..6f9832897 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -27,7 +27,12 @@ #include #include #include + +#ifdef HAVE_NETINET_IN_H #include +#endif + +#include "winsock.h" #include "pstream.h" #include "queue.h" diff --git a/polyp/random.c b/polyp/random.c index 456954a2b..12f27bfd6 100644 --- a/polyp/random.c +++ b/polyp/random.c @@ -19,6 +19,10 @@ USA. ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -31,13 +35,16 @@ #include "util.h" #include "log.h" +#ifndef OS_IS_WIN32 #define RANDOM_DEVICE "/dev/urandom" +#endif void pa_random(void *ret_data, size_t length) { int fd; ssize_t r = 0; assert(ret_data && length); - + +#ifdef RANDOM_DEVICE if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) { if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length) @@ -45,17 +52,20 @@ void pa_random(void *ret_data, size_t length) { close(fd); } +#endif if ((size_t) r != length) { uint8_t *p; size_t l; - + +#ifdef RANDOM_DEVICE pa_log_warn(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s" ", falling back to unsecure pseudo RNG.\n", strerror(errno)); +#endif - srandom(time(NULL)); + srand(time(NULL)); for (p = ret_data, l = length; l > 0; p++, l--) - *p = (uint8_t) random(); + *p = (uint8_t) rand(); } } diff --git a/polyp/sample-util.c b/polyp/sample-util.c index d521afe4a..bf8be34e2 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -161,7 +161,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz size_t d; for (d = 0;; d += sizeof(float)) { - float_t sum = 0; + pa_volume_t sum = 0; unsigned c; if (d >= length) diff --git a/polyp/sample.h b/polyp/sample.h index 0494c7dec..82c146152 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -51,11 +51,19 @@ enum pa_sample_format { #define PA_SAMPLE_S16NE PA_SAMPLE_S16BE /** 32 Bit IEEE floating point, native endian */ #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32BE +/** Signed 16 Bit PCM reverse endian */ +#define PA_SAMPLE_S16RE PA_SAMPLE_S16LE +/** 32 Bit IEEE floating point, reverse endian */ +#define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32LE #else /** Signed 16 Bit PCM, native endian */ #define PA_SAMPLE_S16NE PA_SAMPLE_S16LE /** 32 Bit IEEE floating point, native endian */ #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32LE +/** Signed 16 Bit PCM reverse endian */ +#define PA_SAMPLE_S16RE PA_SAMPLE_S16BE +/** 32 Bit IEEE floating point, reverse endian */ +#define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32BE #endif /** A Shortcut for PA_SAMPLE_FLOAT32NE */ diff --git a/polyp/scache.c b/polyp/scache.c index ccdc71855..2953145d9 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -32,7 +32,14 @@ #include #include #include + +#ifdef HAVE_GLOB_H #include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif #include "scache.h" #include "sink-input.h" @@ -55,7 +62,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, pa_scache_unload_unused(c); - gettimeofday(&ntv, NULL); + pa_gettimeofday(&ntv); ntv.tv_sec += UNLOAD_POLL_TIME; m->time_restart(e, &ntv); } @@ -144,6 +151,13 @@ int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename struct pa_memchunk chunk; int r; +#ifdef OS_IS_WIN32 + char buf[MAX_PATH]; + + if (ExpandEnvironmentStrings(filename, buf, MAX_PATH)) + filename = buf; +#endif + if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0) return -1; @@ -155,6 +169,14 @@ int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index) { struct pa_scache_entry *e; + +#ifdef OS_IS_WIN32 + char buf[MAX_PATH]; + + if (ExpandEnvironmentStrings(filename, buf, MAX_PATH)) + filename = buf; +#endif + assert(c && name); if (!(e = scache_add_item(c, name))) @@ -165,7 +187,7 @@ int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *fil if (!c->scache_auto_unload_event) { struct timeval ntv; - gettimeofday(&ntv, NULL); + pa_gettimeofday(&ntv); ntv.tv_sec += UNLOAD_POLL_TIME; c->scache_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } @@ -303,17 +325,16 @@ static void add_file(struct pa_core *c, const char *pathname) { struct stat st; const char *e; - if (!(e = strrchr(pathname, '/'))) - e = pathname; - else - e++; + e = pa_path_get_filename(pathname); if (stat(pathname, &st) < 0) { pa_log(__FILE__": stat('%s') failed: %s\n", pathname, strerror(errno)); return; } +#if defined(S_ISREG) && defined(S_ISLNK) if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) +#endif pa_scache_add_file_lazy(c, e, pathname, NULL); } @@ -323,6 +344,7 @@ int pa_scache_add_directory_lazy(struct pa_core *c, const char *pathname) { /* First try to open this as directory */ if (!(dir = opendir(pathname))) { +#ifdef HAVE_GLOB_H glob_t p; unsigned int i; /* If that fails, try to open it as shell glob */ @@ -336,6 +358,9 @@ int pa_scache_add_directory_lazy(struct pa_core *c, const char *pathname) { add_file(c, p.gl_pathv[i]); globfree(&p); +#else + return -1; +#endif } else { struct dirent *e; diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 21563d35c..51134b84f 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -31,14 +31,29 @@ #include #include #include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_UN_H #include -#include +#endif +#ifdef HAVE_ARPA_INET_H #include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETDB_H #include +#endif + #ifdef HAVE_LIBASYNCNS #include #endif +#include "winsock.h" + #include "socket-client.h" #include "socket-util.h" #include "util.h" @@ -120,7 +135,7 @@ static void do_call(struct pa_socket_client *c) { goto finish; lerror = sizeof(error); - if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &error, &lerror) < 0) { + if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) { pa_log(__FILE__": getsockopt(): %s\n", strerror(errno)); goto finish; } @@ -198,18 +213,28 @@ struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, ui return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa)); } +#ifdef HAVE_SYS_UN_H + struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) { struct sockaddr_un sa; assert(m && filename); memset(&sa, 0, sizeof(sa)); - sa.sun_family = AF_LOCAL; + sa.sun_family = AF_UNIX; strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); sa.sun_path[sizeof(sa.sun_path) - 1] = 0; return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa)); } +#else /* HAVE_SYS_UN_H */ + +struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) { + return NULL; +} + +#endif /* HAVE_SYS_UN_H */ + static int sockaddr_prepare(struct pa_socket_client *c, const struct sockaddr *sa, size_t salen) { assert(c); assert(sa); @@ -377,7 +402,7 @@ static void start_timeout(struct pa_socket_client *c) { assert(c); assert(!c->timeout_event); - gettimeofday(&tv, NULL); + pa_gettimeofday(&tv); pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000); c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c); } @@ -426,8 +451,9 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, assert(c->asyncns_query); start_timeout(c); } -#else +#else /* HAVE_LIBASYNCNS */ { +#ifdef HAVE_GETADDRINFO int ret; struct addrinfo *res = NULL; @@ -438,12 +464,37 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, if (res->ai_addr) { if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen))) - start_timeout(c); + start_timeout(c); } freeaddrinfo(res); +#else /* HAVE_GETADDRINFO */ + struct hostent *host = NULL; + struct sockaddr_in s; + + /* FIXME: PF_INET6 support */ + if (hints.ai_family != PF_INET) + goto finish; + + host = gethostbyname(a.path_or_host); + if (!host) { + unsigned int addr = inet_addr(a.path_or_host); + if (addr != INADDR_NONE) + host = gethostbyaddr((char*)&addr, 4, AF_INET); + } + + if (!host) + goto finish; + + s.sin_family = AF_INET; + memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr)); + s.sin_port = port; + + if ((c = pa_socket_client_new_sockaddr(m, &s, sizeof(s)))) + start_timeout(c); +#endif /* HAVE_GETADDRINFO */ } -#endif +#endif /* HAVE_LIBASYNCNS */ } } diff --git a/polyp/socket-client.h b/polyp/socket-client.h index 9c3e0b37b..b8c73ed87 100644 --- a/polyp/socket-client.h +++ b/polyp/socket-client.h @@ -23,11 +23,12 @@ ***/ #include -#include #include "mainloop-api.h" #include "iochannel.h" +struct sockaddr; + struct pa_socket_client; struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); diff --git a/polyp/socket-server.c b/polyp/socket-server.c index e67a9daa6..a78f04cdb 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -28,17 +28,36 @@ #include #include #include -#include #include #include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_UN_H #include -#include +#ifndef SUN_LEN +#define SUN_LEN(ptr) \ + ((size_t)(((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path)) +#endif +#endif +#ifdef HAVE_ARPA_INET_H #include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif #ifdef HAVE_LIBWRAP #include #endif +#ifndef HAVE_INET_NTOP +#include "inet_ntop.h" +#endif + +#include "winsock.h" + #include "socket-server.h" #include "socket-util.h" #include "xmalloc.h" @@ -137,6 +156,8 @@ struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *s) { return s; } +#ifdef HAVE_SYS_UN_H + struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) { int fd = -1; struct sockaddr_un sa; @@ -144,14 +165,14 @@ struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, co assert(m && filename); - if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { pa_log(__FILE__": socket(): %s\n", strerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); - sa.sun_family = AF_LOCAL; + sa.sun_family = AF_UNIX; strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); sa.sun_path[sizeof(sa.sun_path) - 1] = 0; @@ -182,6 +203,14 @@ fail: return NULL; } +#else /* HAVE_SYS_UN_H */ + +struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) { + return NULL; +} + +#endif /* HAVE_SYS_UN_H */ + struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service) { struct pa_socket_server *ss; int fd = -1; @@ -197,7 +226,7 @@ struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, ui pa_fd_set_cloexec(fd, 1); - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) pa_log(__FILE__": setsockopt(): %s\n", strerror(errno)); pa_socket_tcp_low_delay(fd); @@ -246,7 +275,7 @@ struct pa_socket_server* pa_socket_server_new_ipv6(struct pa_mainloop_api *m, ui pa_fd_set_cloexec(fd, 1); - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) pa_log(__FILE__": setsockopt(): %s\n", strerror(errno)); pa_socket_tcp_low_delay(fd); @@ -314,9 +343,9 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l switch (s->type) { case SOCKET_SERVER_IPV6: { struct sockaddr_in6 sa; - socklen_t l = sizeof(sa); + socklen_t sa_len = sizeof(sa); - if (getsockname(s->fd, (struct sockaddr*) &sa, &l) < 0) { + if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) { pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno)); return NULL; } @@ -350,9 +379,9 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l case SOCKET_SERVER_IPV4: { struct sockaddr_in sa; - socklen_t l = sizeof(sa); + socklen_t sa_len = sizeof(sa); - if (getsockname(s->fd, &sa, &l) < 0) { + if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) { pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno)); return NULL; } diff --git a/polyp/socket-util.c b/polyp/socket-util.c index 495ee1b06..381502b5f 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -31,16 +31,33 @@ #include #include #include -#include -#include #include #include -#include -#include -#include -#include #include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_UN_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif +#ifdef HAVE_NETINET_IP_H +#include +#endif +#ifdef HAVE_NETINET_TCP_H +#include +#endif +#ifdef HAVE_NETDB_H #include +#endif + +#include "winsock.h" #include "socket-util.h" #include "util.h" @@ -57,6 +74,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { return; } +#ifndef OS_IS_WIN32 if (S_ISSOCK(st.st_mode)) { union { struct sockaddr sa; @@ -77,7 +95,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { ip & 0xFF, ntohs(sa.in.sin_port)); return; - } else if (sa.sa.sa_family == AF_LOCAL) { + } else if (sa.sa.sa_family == AF_UNIX) { snprintf(c, l, "UNIX socket client"); return; } @@ -89,17 +107,18 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { snprintf(c, l, "STDIN/STDOUT client"); return; } +#endif /* OS_IS_WIN32 */ snprintf(c, l, "Unknown client"); } int pa_socket_low_delay(int fd) { +#ifdef SO_PRIORITY int priority; assert(fd >= 0); -#ifdef SO_PRIORITY priority = 7; - if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0) + if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0) return -1; #endif @@ -114,12 +133,13 @@ int pa_socket_tcp_low_delay(int fd) { ret = pa_socket_low_delay(fd); on = 1; + tos = 0; #if defined(SOL_TCP) || defined(IPPROTO_TCP) #if defined(SOL_TCP) - if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) + if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0) #else - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0) #endif ret = -1; #endif @@ -128,9 +148,9 @@ int pa_socket_tcp_low_delay(int fd) { defined(IPPROTO_IP)) tos = IPTOS_LOWDELAY; #ifdef SOL_IP - if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0) + if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0) #else - if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) + if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0) #endif ret = -1; #endif @@ -142,7 +162,7 @@ int pa_socket_tcp_low_delay(int fd) { int pa_socket_set_rcvbuf(int fd, size_t l) { assert(fd >= 0); -/* if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) { */ +/* if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&l, sizeof(l)) < 0) { */ /* pa_log(__FILE__": SO_RCVBUF: %s\n", strerror(errno)); */ /* return -1; */ /* } */ @@ -153,7 +173,7 @@ int pa_socket_set_rcvbuf(int fd, size_t l) { int pa_socket_set_sndbuf(int fd, size_t l) { assert(fd >= 0); -/* if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) { */ +/* if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&l, sizeof(l)) < 0) { */ /* pa_log(__FILE__": SO_SNDBUF: %s\n", strerror(errno)); */ /* return -1; */ /* } */ @@ -161,16 +181,18 @@ int pa_socket_set_sndbuf(int fd, size_t l) { return 0; } +#ifdef HAVE_SYS_UN_H + int pa_unix_socket_is_stale(const char *fn) { struct sockaddr_un sa; int fd = -1, ret = -1; - if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { pa_log(__FILE__": socket(): %s\n", strerror(errno)); goto finish; } - sa.sun_family = AF_LOCAL; + sa.sun_family = AF_UNIX; strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1); sa.sun_path[sizeof(sa.sun_path) - 1] = 0; @@ -202,3 +224,15 @@ int pa_unix_socket_remove_stale(const char *fn) { return 0; } + +#else /* HAVE_SYS_UN_H */ + +int pa_unix_socket_is_stale(const char *fn) { + return -1; +} + +int pa_unix_socket_remove_stale(const char *fn) { + return -1; +} + +#endif /* HAVE_SYS_UN_H */ diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index a6dad868c..1ff09cd15 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -27,9 +27,14 @@ #include #include #include -#include #include +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#include "winsock.h" + #include "tagstruct.h" #include "xmalloc.h" @@ -118,7 +123,8 @@ void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) { assert(t); extend(t, 5); t->data[t->length] = TAG_U32; - *((uint32_t*) (t->data+t->length+1)) = htonl(i); + i = htonl(i); + memcpy(t->data+t->length+1, &i, 4); t->length += 5; } @@ -131,21 +137,25 @@ void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c) { } void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss) { + uint32_t rate; assert(t && ss); extend(t, 7); t->data[t->length] = TAG_SAMPLE_SPEC; t->data[t->length+1] = (uint8_t) ss->format; t->data[t->length+2] = ss->channels; - *(uint32_t*) (t->data+t->length+3) = htonl(ss->rate); + rate = htonl(ss->rate); + memcpy(t->data+t->length+3, &rate, 4); t->length += 7; } void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) { + uint32_t tmp; assert(t && p); extend(t, 5+length); t->data[t->length] = TAG_ARBITRARY; - *((uint32_t*) (t->data+t->length+1)) = htonl(length); + tmp = htonl(length); + memcpy(t->data+t->length+1, &tmp, 4); if (length) memcpy(t->data+t->length+5, p, length); t->length += 5+length; @@ -159,29 +169,38 @@ void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b) { } void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) { + uint32_t tmp; assert(t); extend(t, 9); t->data[t->length] = TAG_TIMEVAL; - *((uint32_t*) (t->data+t->length+1)) = htonl(tv->tv_sec); - *((uint32_t*) (t->data+t->length+5)) = htonl(tv->tv_usec); + tmp = htonl(tv->tv_sec); + memcpy(t->data+t->length+1, &tmp, 4); + tmp = htonl(tv->tv_usec); + memcpy(t->data+t->length+5, &tmp, 4); t->length += 9; } void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) { + uint32_t tmp; assert(t); extend(t, 9); t->data[t->length] = TAG_USEC; - *((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32)); - *((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u); + tmp = htonl((uint32_t) (u >> 32)); + memcpy(t->data+t->length+1, &tmp, 4); + tmp = htonl((uint32_t) u); + memcpy(t->data+t->length+5, &tmp, 4); t->length += 9; } void pa_tagstruct_putu64(struct pa_tagstruct*t, uint64_t u) { + uint32_t tmp; assert(t); extend(t, 9); t->data[t->length] = TAG_U64; - *((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32)); - *((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u); + tmp = htonl((uint32_t) (u >> 32)); + memcpy(t->data+t->length+1, &tmp, 4); + tmp = htonl((uint32_t) u); + memcpy(t->data+t->length+5, &tmp, 4); t->length += 9; } @@ -230,8 +249,9 @@ int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i) { if (t->data[t->rindex] != TAG_U32) return -1; - - *i = ntohl(*((uint32_t*) (t->data+t->rindex+1))); + + memcpy(i, t->data+t->rindex+1, 4); + *i = ntohl(*i); t->rindex += 5; return 0; } @@ -261,13 +281,15 @@ int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec * ss->format = t->data[t->rindex+1]; ss->channels = t->data[t->rindex+2]; - ss->rate = ntohl(*(uint32_t*) (t->data+t->rindex+3)); + memcpy(&ss->rate, t->data+t->rindex+3, 4); + ss->rate = ntohl(ss->rate); t->rindex += 7; return 0; } int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length) { + uint32_t len; assert(t && p); if (t->rindex+5+length > t->length) @@ -276,7 +298,8 @@ int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t le if (t->data[t->rindex] != TAG_ARBITRARY) return -1; - if (ntohl(*((uint32_t*) (t->data+t->rindex+1))) != length) + memcpy(&len, t->data+t->rindex+1, 4); + if (ntohl(len) != length) return -1; *p = t->data+t->rindex+5; @@ -319,15 +342,18 @@ int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv) { if (t->data[t->rindex] != TAG_TIMEVAL) return -1; - - tv->tv_sec = ntohl(*((uint32_t*) (t->data+t->rindex+1))); - tv->tv_usec = ntohl(*((uint32_t*) (t->data+t->rindex+5))); + + memcpy(&tv->tv_sec, t->data+t->rindex+1, 4); + tv->tv_sec = ntohl(tv->tv_sec); + memcpy(&tv->tv_usec, t->data+t->rindex+5, 4); + tv->tv_usec = ntohl(tv->tv_usec); t->rindex += 9; return 0; } int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) { + uint32_t tmp; assert(t && u); if (t->rindex+9 > t->length) @@ -336,13 +362,16 @@ int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) { if (t->data[t->rindex] != TAG_USEC) return -1; - *u = (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32; - *u |= (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+5))); + memcpy(&tmp, t->data+t->rindex+1, 4); + *u = (pa_usec_t) ntohl(tmp) << 32; + memcpy(&tmp, t->data+t->rindex+5, 4); + *u |= (pa_usec_t) ntohl(tmp); t->rindex +=9; return 0; } int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *u) { + uint32_t tmp; assert(t && u); if (t->rindex+9 > t->length) @@ -351,8 +380,10 @@ int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *u) { if (t->data[t->rindex] != TAG_U64) return -1; - *u = (uint64_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32; - *u |= (uint64_t) ntohl(*((uint32_t*) (t->data+t->rindex+5))); + memcpy(&tmp, t->data+t->rindex+1, 4); + *u = (pa_usec_t) ntohl(tmp) << 32; + memcpy(&tmp, t->data+t->rindex+5, 4); + *u |= (pa_usec_t) ntohl(tmp); t->rindex +=9; return 0; } diff --git a/polyp/util.c b/polyp/util.c index ee3fa87d6..26d712037 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -32,35 +32,98 @@ #include #include #include +#include +#include +#include #include #include -#include -#include -#include #include + +#ifdef HAVE_SCHED_H #include +#endif + +#ifdef HAVE_SYS_RESOURCE_H #include -#include -#include -#include +#endif + +#ifdef HAVE_PTHREAD +#include +#endif + +#ifdef HAVE_NETDB_H #include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif #include +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif + +#include "winsock.h" + #include "util.h" #include "xmalloc.h" #include "log.h" +#ifndef OS_IS_WIN32 #define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-" +#define PATH_SEP '/' +#else +#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\polypaudio-" +#define PATH_SEP '\\' +#endif + +#ifdef OS_IS_WIN32 + +#define POLYP_ROOTENV "POLYP_ROOT" + +int pa_set_root(HANDLE handle) { + char library_path[MAX_PATH + sizeof(POLYP_ROOTENV) + 1], *sep; + + strcpy(library_path, POLYP_ROOTENV "="); + + if (!GetModuleFileName(handle, library_path + sizeof(POLYP_ROOTENV), MAX_PATH)) + return 0; + + sep = strrchr(library_path, '\\'); + if (sep) + *sep = '\0'; + + if (_putenv(library_path) < 0) + return 0; + + return 1; +} + +#endif /** Make a file descriptor nonblock. Doesn't do any error checking */ void pa_make_nonblock_fd(int fd) { +#ifdef O_NONBLOCK int v; assert(fd >= 0); if ((v = fcntl(fd, F_GETFL)) >= 0) if (!(v & O_NONBLOCK)) fcntl(fd, F_SETFL, v|O_NONBLOCK); +#elif defined(OS_IS_WIN32) + u_long arg = 1; + if (ioctlsocket(fd, FIONBIO, &arg) < 0) { + if (WSAGetLastError() == WSAENOTSOCK) + pa_log_warn(__FILE__": WARNING: Only sockets can be made non-blocking!\n"); + } +#else + pa_log_warn(__FILE__": WARNING: Non-blocking I/O not supported.!\n"); +#endif } /** Creates a directory securely */ @@ -68,15 +131,27 @@ int pa_make_secure_dir(const char* dir) { struct stat st; assert(dir); - if (mkdir(dir, 0700) < 0) +#ifdef OS_IS_WIN32 + if (mkdir(dir) < 0) +#else + if (mkdir(dir, 0700) < 0) +#endif if (errno != EEXIST) return -1; - - if (lstat(dir, &st) < 0) + +#ifdef HAVE_LSTAT + if (lstat(dir, &st) < 0) +#else + if (stat(dir, &st) < 0) +#endif goto fail; - + +#ifndef OS_IS_WIN32 if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700)) goto fail; +#else + fprintf(stderr, "FIXME: pa_make_secure_dir()\n"); +#endif return 0; @@ -89,10 +164,11 @@ fail: int pa_make_secure_parent_dir(const char *fn) { int ret = -1; char *slash, *dir = pa_xstrdup(fn); - - if (!(slash = strrchr(dir, '/'))) + + slash = pa_path_get_filename(dir); + if (slash == fn) goto finish; - *slash = 0; + *(slash-1) = 0; if (pa_make_secure_dir(dir) < 0) goto finish; @@ -153,6 +229,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) { /* Print a warning messages in case that the given signal is not * blocked or trapped */ void pa_check_signal_is_blocked(int sig) { +#ifdef HAVE_SIGACTION struct sigaction sa; sigset_t set; @@ -185,6 +262,9 @@ void pa_check_signal_is_blocked(int sig) { return; pa_log(__FILE__": WARNING: %s is not trapped. This might cause malfunction!\n", pa_strsignal(sig)); +#else /* HAVE_SIGACTION */ + pa_log(__FILE__": WARNING: %s might not be trapped. This might cause malfunction!\n", pa_strsignal(sig)); +#endif } /* The following function is based on an example from the GNU libc @@ -240,29 +320,46 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) { /* Return the current username in the specified string buffer. */ char *pa_get_user_name(char *s, size_t l) { - struct passwd pw, *r; - char buf[1024]; char *p; + char buf[1024]; + +#ifdef HAVE_PWD_H + struct passwd pw, *r; +#endif + assert(s && l > 0); if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) { +#ifdef HAVE_PWD_H #ifdef HAVE_GETPWUID_R if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { #else - /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) - * that do not support getpwuid_r. */ - if ((r = getpwuid(getuid())) == NULL) { + /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) + * that do not support getpwuid_r. */ + if ((r = getpwuid(getuid())) == NULL) { #endif - snprintf(s, l, "%lu", (unsigned long) getuid()); - return s; - } - - p = r->pw_name; + snprintf(s, l, "%lu", (unsigned long) getuid()); + return s; } + + p = r->pw_name; + +#elif defined(OS_IS_WIN32) /* HAVE_PWD_H */ + DWORD size = sizeof(buf); + + if (!GetUserName(buf, &size)) + return NULL; + + p = buf; + +#else /* HAVE_PWD_H */ + return NULL; +#endif /* HAVE_PWD_H */ + } return pa_strlcpy(s, p, l); - } +} /* Return the current hostname in the specified buffer. */ char *pa_get_host_name(char *s, size_t l) { @@ -278,19 +375,37 @@ char *pa_get_host_name(char *s, size_t l) { /* Return the home directory of the current user */ char *pa_get_home_dir(char *s, size_t l) { char *e; + +#ifdef HAVE_PWD_H char buf[1024]; struct passwd pw, *r; +#endif + assert(s && l); if ((e = getenv("HOME"))) return pa_strlcpy(s, e, l); + if ((e = getenv("USERPROFILE"))) + return pa_strlcpy(s, e, l); + +#ifdef HAVE_PWD_H +#ifdef HAVE_GETPWUID_R if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { pa_log(__FILE__": getpwuid_r() failed\n"); +#else + /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) + * that do not support getpwuid_r. */ + if ((r = getpwuid(getuid())) == NULL) { + pa_log(__FILE__": getpwuid_r() failed\n"); +#endif return NULL; } return pa_strlcpy(s, r->pw_dir, l); +#else /* HAVE_PWD_H */ + return NULL; +#endif } /* Similar to OpenBSD's strlcpy() function */ @@ -302,6 +417,42 @@ char *pa_strlcpy(char *b, const char *s, size_t l) { return b; } +int pa_gettimeofday(struct timeval *tv) { +#ifdef HAVE_GETTIMEOFDAY + return gettimeofday(tv, NULL); +#elif defined(OS_IS_WIN32) + /* + * Copied from implementation by Steven Edwards (LGPL). + * Found on wine mailing list. + */ + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define EPOCHFILETIME (116444736000000000i64) +#else +#define EPOCHFILETIME (116444736000000000LL) +#endif + + FILETIME ft; + LARGE_INTEGER li; + __int64 t; + + if (tv) { + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + t = li.QuadPart; /* In 100-nanosecond intervals */ + t -= EPOCHFILETIME; /* Offset to the Epoch time */ + t /= 10; /* In microseconds */ + tv->tv_sec = (long)(t / 1000000); + tv->tv_usec = (long)(t % 1000000); + } + + return 0; +#else +#error "Platform lacks gettimeofday() or equivalent function." +#endif +} + /* Calculate the difference between the two specfified timeval * timestamsps. */ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { @@ -351,7 +502,7 @@ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { pa_usec_t pa_timeval_age(const struct timeval *tv) { struct timeval now; assert(tv); - gettimeofday(&now, NULL); + pa_gettimeofday(&now); return pa_timeval_diff(&now, tv); } @@ -380,10 +531,12 @@ sensible: set the nice level to -15 and enable realtime scheduling if supported.*/ void pa_raise_priority(void) { +#ifdef HAVE_SYS_RESOURCE_H if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) pa_log_warn(__FILE__": setpriority() failed: %s\n", strerror(errno)); else pa_log_info(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); +#endif #ifdef _POSIX_PRIORITY_SCHEDULING { @@ -403,10 +556,21 @@ void pa_raise_priority(void) { pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); } #endif + +#ifdef OS_IS_WIN32 + if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) + pa_log_warn(__FILE__": SetPriorityClass() failed: 0x%08X\n", GetLastError()); + else + pa_log_info(__FILE__": Successfully gained high priority class.\n"); +#endif } /* Reset the priority to normal, inverting the changes made by pa_raise_priority() */ void pa_reset_priority(void) { +#ifdef OS_IS_WIN32 + SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); +#endif + #ifdef _POSIX_PRIORITY_SCHEDULING { struct sched_param sp; @@ -416,11 +580,15 @@ void pa_reset_priority(void) { } #endif +#ifdef HAVE_SYS_RESOURCE_H setpriority(PRIO_PROCESS, 0, 0); +#endif } /* Set the FD_CLOEXEC flag for a fd */ int pa_fd_set_cloexec(int fd, int b) { + +#ifdef FD_CLOEXEC int v; assert(fd >= 0); @@ -431,7 +599,8 @@ int pa_fd_set_cloexec(int fd, int b) { if (fcntl(fd, F_SETFD, v) < 0) return -1; - +#endif + return 0; } @@ -439,6 +608,8 @@ int pa_fd_set_cloexec(int fd, int b) { * only. This shoul be used for eyecandy only, don't rely on return * non-NULL! */ char *pa_get_binary_name(char *s, size_t l) { + +#ifdef HAVE_READLINK char path[PATH_MAX]; int i; assert(s && l); @@ -451,6 +622,15 @@ char *pa_get_binary_name(char *s, size_t l) { s[i] = 0; return s; +#elif defined(OS_IS_WIN32) + char path[PATH_MAX]; + if (!GetModuleFileName(NULL, path, PATH_MAX)) + return NULL; + pa_strlcpy(s, pa_path_get_filename(path), l); + return s; +#else + return NULL; +#endif } /* Return a pointer to the filename inside a path (which is the last @@ -458,7 +638,7 @@ char *pa_get_binary_name(char *s, size_t l) { char *pa_path_get_filename(const char *p) { char *fn; - if ((fn = strrchr(p, '/'))) + if ((fn = strrchr(p, PATH_SEP))) return fn+1; return (char*) p; @@ -519,16 +699,29 @@ const char *pa_strsignal(int sig) { switch(sig) { case SIGINT: return "SIGINT"; case SIGTERM: return "SIGTERM"; +#ifdef SIGUSR1 case SIGUSR1: return "SIGUSR1"; +#endif +#ifdef SIGUSR2 case SIGUSR2: return "SIGUSR2"; +#endif +#ifdef SIGXCPU case SIGXCPU: return "SIGXCPU"; +#endif +#ifdef SIGPIPE case SIGPIPE: return "SIGPIPE"; +#endif +#ifdef SIGCHLD case SIGCHLD: return "SIGCHLD"; +#endif +#ifdef SIGHUP case SIGHUP: return "SIGHUP"; +#endif default: return "UNKNOWN SIGNAL"; } } +#ifdef HAVE_GRP_H /* Check whether the specified GID and the group name match */ static int is_group(gid_t gid, const char *name) { @@ -575,7 +768,7 @@ finish: /* Check the current user is member of the specified group */ int pa_uid_in_group(const char *name, gid_t *gid) { gid_t *gids, tgid; - long n = sysconf(_SC_NGROUPS_MAX); + GETGROUPS_T n = sysconf(_SC_NGROUPS_MAX); int r = -1, i; assert(n > 0); @@ -609,8 +802,18 @@ finish: return r; } -/* Lock or unlock a file entirely. (advisory) */ +#else /* HAVE_GRP_H */ + +int pa_uid_in_group(const char *name, gid_t *gid) { + return -1; +} + +#endif + +/* Lock or unlock a file entirely. + (advisory on UNIX, mandatory on Windows) */ int pa_lock_fd(int fd, int b) { +#ifdef F_SETLKW struct flock flock; /* Try a R/W lock first */ @@ -631,6 +834,19 @@ int pa_lock_fd(int fd, int b) { } pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno)); +#endif + +#ifdef OS_IS_WIN32 + HANDLE h = (HANDLE)_get_osfhandle(fd); + + if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF)) + return 0; + if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF)) + return 0; + + pa_log(__FILE__": %slock failed: 0x%08X\n", !b ? "un" : "", GetLastError()); +#endif + return -1; } @@ -722,31 +938,51 @@ int pa_unlock_lockfile(const char *fn, int fd) { * allocated buffer containing the used configuration file is * stored there.*/ FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) { - const char *e; + const char *fn; char h[PATH_MAX]; - if (env && (e = getenv(env))) { +#ifdef OS_IS_WIN32 + char buf[PATH_MAX]; + + if (!getenv(POLYP_ROOTENV)) + pa_set_root(NULL); +#endif + + if (env && (fn = getenv(env))) { +#ifdef OS_IS_WIN32 + if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX)) + return NULL; + fn = buf; +#endif + if (result) - *result = pa_xstrdup(e); - return fopen(e, "r"); + *result = pa_xstrdup(fn); + + return fopen(fn, "r"); } if (local && pa_get_home_dir(h, sizeof(h))) { FILE *f; - char *l; + char *lfn; - l = pa_sprintf_malloc("%s/%s", h, local); - f = fopen(l, "r"); + lfn = pa_sprintf_malloc("%s/%s", h, local); + +#ifdef OS_IS_WIN32 + if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) + return NULL; + lfn = buf; +#endif + + f = fopen(lfn, "r"); if (f || errno != ENOENT) { if (result) - *result = l; - else - pa_xfree(l); + *result = pa_xstrdup(lfn); + pa_xfree(lfn); return f; } - pa_xfree(l); + pa_xfree(lfn); } if (!global) { @@ -756,6 +992,12 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env return NULL; } +#ifdef OS_IS_WIN32 + if (!ExpandEnvironmentStrings(global, buf, PATH_MAX)) + return NULL; + global = buf; +#endif + if (result) *result = pa_xstrdup(global); @@ -823,11 +1065,14 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) { /* Return the fully qualified domain name in *s */ char *pa_get_fqdn(char *s, size_t l) { char hn[256]; +#ifdef HAVE_GETADDRINFO struct addrinfo *a, hints; +#endif if (!pa_get_host_name(hn, sizeof(hn))) return NULL; +#ifdef HAVE_GETADDRINFO memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_CANONNAME; @@ -838,6 +1083,9 @@ char *pa_get_fqdn(char *s, size_t l) { pa_strlcpy(s, a->ai_canonname, l); freeaddrinfo(a); return s; +#else + return pa_strlcpy(s, hn, l); +#endif } /* Returns nonzero when *s starts with *pfx */ @@ -855,21 +1103,44 @@ int pa_startswith(const char *s, const char *pfx) { char *pa_runtime_path(const char *fn, char *s, size_t l) { char u[256]; +#ifndef OS_IS_WIN32 if (fn && *fn == '/') +#else + if (fn && strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\') +#endif return pa_strlcpy(s, fn, l); - - snprintf(s, l, PA_RUNTIME_PATH_PREFIX"%s%s%s", pa_get_user_name(u, sizeof(u)), fn ? "/" : "", fn ? fn : ""); + + if (fn) + snprintf(s, l, "%s%s%c%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn); + else + snprintf(s, l, "%s%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u))); + +#ifdef OS_IS_WIN32 + { + char buf[l]; + strcpy(buf, s); + ExpandEnvironmentStrings(buf, s, l); + } +#endif + return s; } /* Wait t milliseconds */ int pa_msleep(unsigned long t) { +#ifdef OS_IS_WIN32 + Sleep(t); + return 0; +#elif defined(HAVE_NANOSLEEP) struct timespec ts; ts.tv_sec = t/1000; ts.tv_nsec = (t % 1000) * 1000000; return nanosleep(&ts, NULL); +#else +#error "Platform lacks a sleep function." +#endif } /* Convert the string s to a signed integer in *ret_i */ diff --git a/polyp/util.h b/polyp/util.h index 2cfc5f6e6..d9e18ddbe 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -30,6 +30,8 @@ #include "gcc-printf.h" #include "sample.h" +struct timeval; + void pa_make_nonblock_fd(int fd); int pa_make_secure_dir(const char* dir); @@ -53,6 +55,7 @@ char *pa_get_home_dir(char *s, size_t l); char *pa_path_get_filename(const char *p); +int pa_gettimeofday(struct timeval *tv); pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); pa_usec_t pa_timeval_age(const struct timeval *tv); diff --git a/polyp/winsock.h b/polyp/winsock.h new file mode 100644 index 000000000..b1e0f7d44 --- /dev/null +++ b/polyp/winsock.h @@ -0,0 +1,23 @@ +#ifndef foowinsockhfoo +#define foowinsockhfoo + +#ifdef HAVE_WINSOCK2_H +#include + +#define ESHUTDOWN WSAESHUTDOWN +#define ECONNRESET WSAECONNRESET +#define ECONNABORTED WSAECONNABORTED +#define ENETRESET WSAENETRESET +#define EINPROGRESS WSAEINPROGRESS +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#define ETIMEDOUT WSAETIMEDOUT +#define ECONNREFUSED WSAECONNREFUSED +#define EHOSTUNREACH WSAEHOSTUNREACH + +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +#endif diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c index 7ddefa94f..f2751e52b 100644 --- a/polyp/xmalloc.c +++ b/polyp/xmalloc.c @@ -45,7 +45,9 @@ static void oom(void) { static const char e[] = "Not enough memory\n"; pa_loop_write(STDERR_FILENO, e, sizeof(e)-1); +#ifdef SIGQUIT raise(SIGQUIT); +#endif _exit(1); } From 6c512fb5a3fdb578179be79672c5096de1a1d25b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 10 Jan 2006 18:04:54 +0000 Subject: [PATCH 0354/1514] build system updates, including support for some newer GCC options git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@446 fefdeb5f-60dc-0310-8127-8f9354f1896f --- bootstrap.sh | 38 ++++++++++++++++++++++--------- configure.ac | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 11 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 4b9032b64..7fa1dc9af 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -17,17 +17,32 @@ # along with polypaudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +VERSION=1.9 + run_versioned() { local P - type -p "$1-$2" &> /dev/null && P="$1-$2" || local P="$1" + local V + + V=$(echo "$2" | sed -e 's,\.,,g') + + if [ -e "`which $1$V`" ] ; then + P="$1$V" + else + if [ -e "`which $1-$2`" ] ; then + P="$1-$2" + else + P="$1" + fi + fi shift 2 "$P" "$@" } +set -ex + if [ "x$1" = "xam" ] ; then - set -ex - run_versioned automake 1.7 -a -c --foreign + run_versioned automake "$VERSION" -a -c --foreign ./config.status else set -ex @@ -35,13 +50,16 @@ else rm -rf autom4te.cache rm -f config.cache - run_versioned aclocal 1.7 - libtoolize -c --force --ltdl - autoheader - run_versioned automake 1.7 -a -c --foreign - autoconf -Wall + test "x$LIBTOOLIZE" = "x" && LIBTOOLIZE=libtoolize - CFLAGS="-g -O0" ./configure --sysconfdir=/etc "$@" + "$LIBTOOLIZE" -c --force + run_versioned aclocal "$VERSION" + run_versioned autoconf 2.59 -Wall + run_versioned autoheader 2.59 + run_versioned automake "$VERSION" -a -c --foreign - make clean + if test "x$NOCONFIGURE" = "x"; then + CFLAGS="-g -O0" ./configure --sysconfdir=/etc "$@" + make clean + fi fi diff --git a/configure.ac b/configure.ac index e5e03d041..f69eb636f 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_PREREQ(2.57) AC_INIT([polypaudio],[0.8],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) -AM_INIT_AUTOMAKE([foreign -Wall]) +AM_INIT_AUTOMAKE([foreign 1.9 -Wall]) AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) @@ -41,6 +41,7 @@ fi AC_PROG_CC AC_PROG_GCC_TRADITIONAL +AC_GNU_SOURCE # If using GCC specify some additional parameters if test "x$GCC" = "xyes" ; then @@ -58,6 +59,54 @@ if test "x$M4" = xno ; then AC_MSG_ERROR([m4 missing]) fi +# GCC flags + +test_gcc_flag() { + AC_LANG_CONFTEST([int main() {}]) + $CC -c conftest.c $CFLAGS $@ > /dev/null 2> /dev/null + ret=$? + rm -f conftest.o + return $ret +} + +# If using GCC specify some additional parameters +if test "x$GCC" = "xyes" ; then + + DESIRED_FLAGS="-Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Winline" + + if test "x$HAVE_NETLINK" = "xyes" ; then + # Test whether rtnetlink.h can be included when compiled with -std=c99 + # some distributions (e.g. archlinux) have broken headers that dont + # define __u64 with -std=c99 + AC_MSG_CHECKING([checking whether rtnetlink.h can be included with -std=c99]) + OLDCFLAGS="$CFLAGS" + CFLAGS="-std=c99" + AC_TRY_COMPILE([#include ], [], + use_stdc99=yes, use_stdc99=no) + + if test x"$use_stdc99" = xyes; then + DESIRED_FLAGS="-std=c99 $DESIRED_FLAGS" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + + CFLAGS="$OLDCFLAGS" + else + DESIRED_FLAGS="-std=c99 $DESIRED_FLAGS" + fi + + for flag in $DESIRED_FLAGS ; do + AC_MSG_CHECKING([whether $CC accepts $flag]) + if test_gcc_flag $flag ; then + CFLAGS="$CFLAGS $flag" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + done +fi + # LYNX documentation generation AC_ARG_ENABLE(lynx, AC_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation), @@ -243,6 +292,18 @@ if test "x${with_caps}" != "xno"; then fi AC_SUBST(CAP_LIBS) +#### pkg-config #### + +# Check for pkg-config manually first, as if its not installed the +# PKG_PROG_PKG_CONFIG macro won't be defined. +AC_CHECK_PROG(have_pkg_config, pkg-config, yes, no) + +if test x"$have_pkg_config" = "xno"; then + AC_MSG_ERROR(pkg-config is required to install this program) +fi + +PKG_PROG_PKG_CONFIG + #### Sample rate conversion #### PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) From 1f0961368f58a9fec319d86c79a86a9f0d008cf5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 11 Jan 2006 01:17:39 +0000 Subject: [PATCH 0355/1514] * remove a lot of compiler warnings introduced by using some new GCC flags * add typedefs for public structs and enums and drop the struct/enum prefixs from all uses where it makes sense git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@447 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 6 +- polyp/alsa-util.c | 10 +- polyp/alsa-util.h | 6 +- polyp/authkey-prop.c | 8 +- polyp/authkey-prop.h | 8 +- polyp/autoload.c | 54 +-- polyp/autoload.h | 22 +- polyp/cli-command.c | 196 ++++---- polyp/cli-command.h | 6 +- polyp/cli-text.c | 102 ++--- polyp/cli-text.h | 18 +- polyp/cli.c | 32 +- polyp/cli.h | 8 +- polyp/client-conf-x11.c | 2 +- polyp/client-conf-x11.h | 2 +- polyp/client-conf.c | 16 +- polyp/client-conf.h | 14 +- polyp/client.c | 12 +- polyp/client.h | 16 +- polyp/cmdline.c | 4 +- polyp/cmdline.h | 2 +- polyp/conf-parser.c | 12 +- polyp/conf-parser.h | 6 +- polyp/core.c | 18 +- polyp/core.h | 36 +- polyp/cpulimit-test.c | 7 +- polyp/cpulimit.c | 21 +- polyp/cpulimit.h | 2 +- polyp/daemon-conf.c | 38 +- polyp/daemon-conf.h | 30 +- polyp/dumpmodules.c | 12 +- polyp/dumpmodules.h | 2 +- polyp/dynarray.c | 16 +- polyp/dynarray.h | 14 +- polyp/{gcc-printf.h => gccmacro.h} | 28 +- polyp/glib-mainloop.c | 126 ++--- polyp/glib-mainloop.h | 12 +- polyp/glib12-mainloop.c | 123 ++--- polyp/hashmap.c | 22 +- polyp/hashmap.h | 16 +- polyp/howl-wrap.c | 28 +- polyp/howl-wrap.h | 10 +- polyp/idxset.c | 124 ++--- polyp/idxset.h | 41 +- polyp/iochannel.c | 88 ++-- polyp/iochannel.h | 29 +- polyp/ioline.c | 54 +-- polyp/ioline.h | 18 +- polyp/log.c | 26 +- polyp/log.h | 20 +- polyp/main.c | 20 +- polyp/mainloop-api.c | 13 +- polyp/mainloop-api.h | 48 +- polyp/mainloop-signal.c | 41 +- polyp/mainloop-signal.h | 12 +- polyp/mainloop-test.c | 24 +- polyp/mainloop.c | 168 +++---- polyp/mainloop.h | 19 +- polyp/mcalign-test.c | 9 +- polyp/mcalign.c | 16 +- polyp/mcalign.h | 16 +- polyp/memblock.c | 38 +- polyp/memblock.h | 81 ++-- polyp/memblockq.c | 54 +-- polyp/memblockq.h | 42 +- polyp/memchunk.c | 6 +- polyp/memchunk.h | 12 +- polyp/modargs.c | 32 +- polyp/modargs.h | 16 +- polyp/modinfo.c | 12 +- polyp/modinfo.h | 10 +- polyp/module-alsa-sink.c | 26 +- polyp/module-alsa-source.c | 24 +- polyp/module-cli.c | 10 +- polyp/module-combine.c | 42 +- polyp/module-defs.h.m4 | 5 + polyp/module-esound-compat-spawnfd.c | 6 +- polyp/module-esound-compat-spawnpid.c | 6 +- polyp/module-esound-sink.c | 34 +- polyp/module-lirc.c | 14 +- polyp/module-match.c | 14 +- polyp/module-mmkbd-evdev.c | 24 +- polyp/module-native-protocol-fd.c | 8 +- polyp/module-null-sink.c | 20 +- polyp/module-oss-mmap.c | 36 +- polyp/module-oss.c | 36 +- polyp/module-pipe-sink.c | 30 +- polyp/module-pipe-source.c | 24 +- polyp/module-protocol-stub.c | 14 +- polyp/module-sine.c | 24 +- polyp/module-solaris.c | 38 +- polyp/module-tunnel.c | 72 +-- polyp/module-waveout.c | 46 +- polyp/module-x11-bell.c | 16 +- polyp/module-x11-publish.c | 12 +- polyp/module-zeroconf-publish.c | 50 +- polyp/module.c | 53 +-- polyp/module.h | 24 +- polyp/namereg.c | 36 +- polyp/namereg.h | 18 +- polyp/oss-util.c | 2 +- polyp/oss-util.h | 2 +- polyp/pabrowse.c | 12 +- polyp/pacat-simple.c | 7 +- polyp/pacat.c | 36 +- polyp/packet.c | 16 +- polyp/packet.h | 12 +- polyp/pacmd.c | 2 +- polyp/pactl.c | 44 +- polyp/paplay.c | 33 +- polyp/parec-simple.c | 9 +- polyp/parseaddr.c | 4 +- polyp/parseaddr.h | 12 +- polyp/pax11publish.c | 22 +- polyp/pdispatch.c | 52 +-- polyp/pdispatch.h | 23 +- polyp/play-memchunk.c | 23 +- polyp/play-memchunk.h | 2 +- polyp/polyplib-browser.c | 38 +- polyp/polyplib-browser.h | 16 +- polyp/polyplib-context.c | 166 +++---- polyp/polyplib-context.h | 38 +- polyp/polyplib-def.h | 40 +- polyp/polyplib-internal.h | 94 ++-- polyp/polyplib-introspect.c | 373 +++++++-------- polyp/polyplib-introspect.h | 124 ++--- polyp/polyplib-operation.c | 22 +- polyp/polyplib-operation.h | 12 +- polyp/polyplib-scache.c | 24 +- polyp/polyplib-scache.h | 8 +- polyp/polyplib-simple.c | 130 +++--- polyp/polyplib-simple.h | 24 +- polyp/polyplib-stream.c | 160 +++---- polyp/polyplib-stream.h | 58 +-- polyp/polyplib-subscribe.c | 17 +- polyp/polyplib-subscribe.h | 4 +- polyp/props.c | 36 +- polyp/props.h | 14 +- polyp/protocol-cli.c | 30 +- polyp/protocol-cli.h | 6 +- polyp/protocol-esound.c | 193 ++++---- polyp/protocol-esound.h | 6 +- polyp/protocol-http.c | 38 +- polyp/protocol-http.h | 6 +- polyp/protocol-native.c | 634 +++++++++++++------------- polyp/protocol-native.h | 8 +- polyp/protocol-simple.c | 68 +-- polyp/protocol-simple.h | 6 +- polyp/pstream-util.c | 12 +- polyp/pstream-util.h | 6 +- polyp/pstream.c | 86 ++-- polyp/pstream.h | 24 +- polyp/queue.c | 14 +- polyp/queue.h | 12 +- polyp/resampler.c | 52 +-- polyp/resampler.h | 22 +- polyp/sample-util.c | 12 +- polyp/sample-util.h | 16 +- polyp/sample.c | 16 +- polyp/sample.h | 26 +- polyp/scache.c | 83 ++-- polyp/scache.h | 32 +- polyp/sconv-s16be.c | 3 +- polyp/sconv-s16le.c | 1 + polyp/sconv.c | 8 +- polyp/sconv.h | 4 +- polyp/sink-input.c | 38 +- polyp/sink-input.h | 56 +-- polyp/sink.c | 55 ++- polyp/sink.h | 49 +- polyp/socket-client.c | 74 +-- polyp/socket-client.h | 20 +- polyp/socket-server.c | 42 +- polyp/socket-server.h | 18 +- polyp/sound-file-stream.c | 16 +- polyp/sound-file-stream.h | 2 +- polyp/sound-file.c | 4 +- polyp/sound-file.h | 2 +- polyp/source-output.c | 32 +- polyp/source-output.h | 44 +- polyp/source.c | 30 +- polyp/source.h | 39 +- polyp/strbuf.c | 18 +- polyp/strbuf.h | 18 +- polyp/strlist-test.c | 5 +- polyp/strlist.c | 34 +- polyp/strlist.h | 14 +- polyp/subscribe.c | 49 +- polyp/subscribe.h | 14 +- polyp/tagstruct.c | 52 +-- polyp/tagstruct.h | 48 +- polyp/tokenizer.c | 17 +- polyp/tokenizer.h | 8 +- polyp/util.c | 8 +- polyp/util.h | 2 +- polyp/voltest.c | 3 +- polyp/x11wrap.c | 90 ++-- polyp/x11wrap.h | 16 +- polyp/xmalloc.c | 4 + polyp/xmalloc.h | 20 + 200 files changed, 3582 insertions(+), 3468 deletions(-) rename polyp/{gcc-printf.h => gccmacro.h} (60%) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 22e8da3de..8712782fa 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -42,7 +42,7 @@ endif # Compiler/linker flags # ################################### -AM_CFLAGS = -D_GNU_SOURCE -I$(top_srcdir) +AM_CFLAGS = -I$(top_srcdir) AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) @@ -224,12 +224,12 @@ voltest_CFLAGS = $(AM_CFLAGS) voltest_LDADD = $(AM_LDADD) voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h +cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h idxset.c idxset.h cpulimit_test_CFLAGS = $(AM_CFLAGS) cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la cpulimit_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h +cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h idxset.c idxset.h cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la cpulimit_test2_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index 2894c9e8b..73f3be7dd 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -33,7 +33,7 @@ /* Set the hardware parameters of the given ALSA device. Returns the * selected fragment settings in *period and *period_size */ -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { int ret = -1; snd_pcm_uframes_t buffer_size; snd_pcm_hw_params_t *hwparams = NULL; @@ -85,10 +85,10 @@ finish: * *io_events. Store the length of that array in *n_io_events. Use the * specified callback function and userdata. The array has to be freed * with pa_free_io_events(). */ -int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) { +int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api* m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata) { unsigned i; struct pollfd *pfds, *ppfd; - struct pa_io_event **ios; + pa_io_event **ios; assert(pcm_handle && m && io_events && n_io_events && cb); *n_io_events = snd_pcm_poll_descriptors_count(pcm_handle); @@ -113,9 +113,9 @@ int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api* m, struct } /* Free the memory allocated by pa_create_io_events() */ -void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_events, unsigned n_io_events) { +void pa_free_io_events(pa_mainloop_api* m, pa_io_event **io_events, unsigned n_io_events) { unsigned i; - struct pa_io_event **ios; + pa_io_event **ios; assert(m && io_events); for (ios = io_events, i = 0; i < n_io_events; i++, ios++) diff --git a/polyp/alsa-util.h b/polyp/alsa-util.h index adec143fd..787519f74 100644 --- a/polyp/alsa-util.h +++ b/polyp/alsa-util.h @@ -27,9 +27,9 @@ #include "sample.h" #include "mainloop-api.h" -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const struct pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); -int pa_create_io_events(snd_pcm_t *pcm_handle, struct pa_mainloop_api *m, struct pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata); -void pa_free_io_events(struct pa_mainloop_api* m, struct pa_io_event **io_sources, unsigned n_io_sources); +int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api *m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata); +void pa_free_io_events(pa_mainloop_api* m, pa_io_event **io_sources, unsigned n_io_sources); #endif diff --git a/polyp/authkey-prop.c b/polyp/authkey-prop.c index 2adfc41f5..8657f5a50 100644 --- a/polyp/authkey-prop.c +++ b/polyp/authkey-prop.c @@ -32,7 +32,7 @@ struct authkey_data { size_t length; }; -int pa_authkey_prop_get(struct pa_core *c, const char *name, void *data, size_t len) { +int pa_authkey_prop_get(pa_core *c, const char *name, void *data, size_t len) { struct authkey_data *a; assert(c && name && data && len > 0); @@ -44,7 +44,7 @@ int pa_authkey_prop_get(struct pa_core *c, const char *name, void *data, size_t return 0; } -int pa_authkey_prop_put(struct pa_core *c, const char *name, const void *data, size_t len) { +int pa_authkey_prop_put(pa_core *c, const char *name, const void *data, size_t len) { struct authkey_data *a; assert(c && name); @@ -61,7 +61,7 @@ int pa_authkey_prop_put(struct pa_core *c, const char *name, const void *data, s return 0; } -void pa_authkey_prop_ref(struct pa_core *c, const char *name) { +void pa_authkey_prop_ref(pa_core *c, const char *name) { struct authkey_data *a; assert(c && name); @@ -71,7 +71,7 @@ void pa_authkey_prop_ref(struct pa_core *c, const char *name) { a->ref++; } -void pa_authkey_prop_unref(struct pa_core *c, const char *name) { +void pa_authkey_prop_unref(pa_core *c, const char *name) { struct authkey_data *a; assert(c && name); diff --git a/polyp/authkey-prop.h b/polyp/authkey-prop.h index 1b1948c7f..29b40bb23 100644 --- a/polyp/authkey-prop.h +++ b/polyp/authkey-prop.h @@ -29,15 +29,15 @@ * several modules. */ /* Return the data of the specified authorization key property. Doesn't alter the refernce count of the key */ -int pa_authkey_prop_get(struct pa_core *c, const char *name, void *data, size_t len); +int pa_authkey_prop_get(pa_core *c, const char *name, void *data, size_t len); /* Store data in the specified authorization key property. The initial reference count is set to 1 */ -int pa_authkey_prop_put(struct pa_core *c, const char *name, const void *data, size_t len); +int pa_authkey_prop_put(pa_core *c, const char *name, const void *data, size_t len); /* Increase the reference count of the specified authorization key */ -void pa_authkey_prop_ref(struct pa_core *c, const char *name); +void pa_authkey_prop_ref(pa_core *c, const char *name); /* Decrease the reference count of the specified authorization key */ -void pa_authkey_prop_unref(struct pa_core *c, const char *name); +void pa_authkey_prop_unref(pa_core *c, const char *name); #endif diff --git a/polyp/autoload.c b/polyp/autoload.c index 96fa750ae..7e05c1689 100644 --- a/polyp/autoload.c +++ b/polyp/autoload.c @@ -36,7 +36,7 @@ #include "scache.h" #include "subscribe.h" -static void entry_free(struct pa_autoload_entry *e) { +static void entry_free(pa_autoload_entry *e) { assert(e); pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_REMOVE, PA_INVALID_INDEX); pa_xfree(e->name); @@ -45,7 +45,7 @@ static void entry_free(struct pa_autoload_entry *e) { pa_xfree(e); } -static void entry_remove_and_free(struct pa_autoload_entry *e) { +static void entry_remove_and_free(pa_autoload_entry *e) { assert(e && e->core); pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL); @@ -53,14 +53,14 @@ static void entry_remove_and_free(struct pa_autoload_entry *e) { entry_free(e); } -static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) { - struct pa_autoload_entry *e = NULL; +static pa_autoload_entry* entry_new(pa_core *c, const char *name) { + pa_autoload_entry *e = NULL; assert(c && name); if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name))) return NULL; - e = pa_xmalloc(sizeof(struct pa_autoload_entry)); + e = pa_xmalloc(sizeof(pa_autoload_entry)); e->core = c; e->name = pa_xstrdup(name); e->module = e->argument = NULL; @@ -81,8 +81,8 @@ static struct pa_autoload_entry* entry_new(struct pa_core *c, const char *name) return e; } -int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument, uint32_t *index) { - struct pa_autoload_entry *e = NULL; +int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const char*module, const char *argument, uint32_t *idx) { + pa_autoload_entry *e = NULL; assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); if (!(e = entry_new(c, name))) @@ -92,14 +92,14 @@ int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type typ e->argument = pa_xstrdup(argument); e->type = type; - if (index) - *index = e->index; + if (idx) + *idx = e->index; return 0; } -int pa_autoload_remove_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type) { - struct pa_autoload_entry *e; +int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type type) { + pa_autoload_entry *e; assert(c && name && type); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) @@ -109,20 +109,20 @@ int pa_autoload_remove_by_name(struct pa_core *c, const char*name, enum pa_namer return 0; } -int pa_autoload_remove_by_index(struct pa_core *c, uint32_t index) { - struct pa_autoload_entry *e; - assert(c && index != PA_IDXSET_INVALID); +int pa_autoload_remove_by_index(pa_core *c, uint32_t idx) { + pa_autoload_entry *e; + assert(c && idx != PA_IDXSET_INVALID); - if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, index))) + if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, idx))) return -1; entry_remove_and_free(e); return 0; } -void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type) { - struct pa_autoload_entry *e; - struct pa_module *m; +void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type type) { + pa_autoload_entry *e; + pa_module *m; assert(c && name); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || (e->type != type)) @@ -141,13 +141,13 @@ void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_ty e->in_action = 0; } -static void free_func(void *p, void *userdata) { - struct pa_autoload_entry *e = p; +static void free_func(void *p, PA_GCC_UNUSED void *userdata) { + pa_autoload_entry *e = p; pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL); entry_free(e); } -void pa_autoload_free(struct pa_core *c) { +void pa_autoload_free(pa_core *c) { if (c->autoload_hashmap) { pa_hashmap_free(c->autoload_hashmap, free_func, NULL); c->autoload_hashmap = NULL; @@ -159,8 +159,8 @@ void pa_autoload_free(struct pa_core *c) { } } -const struct pa_autoload_entry* pa_autoload_get_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type) { - struct pa_autoload_entry *e; +const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type type) { + pa_autoload_entry *e; assert(c && name); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) @@ -169,11 +169,11 @@ const struct pa_autoload_entry* pa_autoload_get_by_name(struct pa_core *c, const return e; } -const struct pa_autoload_entry* pa_autoload_get_by_index(struct pa_core *c, uint32_t index) { - struct pa_autoload_entry *e; - assert(c && index != PA_IDXSET_INVALID); +const pa_autoload_entry* pa_autoload_get_by_index(pa_core *c, uint32_t idx) { + pa_autoload_entry *e; + assert(c && idx != PA_IDXSET_INVALID); - if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, index))) + if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, idx))) return NULL; return e; diff --git a/polyp/autoload.h b/polyp/autoload.h index 234756845..622a854e5 100644 --- a/polyp/autoload.h +++ b/polyp/autoload.h @@ -30,29 +30,29 @@ * specified module is loaded. */ /* An autoload entry, or "ghost" sink/source */ -struct pa_autoload_entry { - struct pa_core *core; +typedef struct pa_autoload_entry { + pa_core *core; uint32_t index; char *name; - enum pa_namereg_type type; /* Type of the autoload entry */ + pa_namereg_type type; /* Type of the autoload entry */ int in_action; /* Currently loaded */ char *module, *argument; -}; +} pa_autoload_entry; /* Add a new autoload entry of the given time, with the speicified * sink/source name, module name and argument. Return the entry's * index in *index */ -int pa_autoload_add(struct pa_core *c, const char*name, enum pa_namereg_type type, const char*module, const char *argument, uint32_t *index); +int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const char*module, const char *argument, uint32_t *idx); /* Free all autoload entries */ -void pa_autoload_free(struct pa_core *c); -int pa_autoload_remove_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type); -int pa_autoload_remove_by_index(struct pa_core *c, uint32_t index); +void pa_autoload_free(pa_core *c); +int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type type); +int pa_autoload_remove_by_index(pa_core *c, uint32_t idx); /* Request an autoload entry by its name, effectively causing a module to be loaded */ -void pa_autoload_request(struct pa_core *c, const char *name, enum pa_namereg_type type); +void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type type); -const struct pa_autoload_entry* pa_autoload_get_by_name(struct pa_core *c, const char*name, enum pa_namereg_type type); -const struct pa_autoload_entry* pa_autoload_get_by_index(struct pa_core *c, uint32_t index); +const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type type); +const pa_autoload_entry* pa_autoload_get_by_index(pa_core *c, uint32_t idx); #endif diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 124478794..63241a815 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -52,7 +52,7 @@ struct command { const char *name; - int (*proc) (struct pa_core *c, struct pa_tokenizer*t, struct pa_strbuf *buf, int *fail); + int (*proc) (pa_core *c, pa_tokenizer*t, pa_strbuf *buf, int *fail); const char *help; unsigned args; }; @@ -62,36 +62,36 @@ struct command { #define NOFAIL_META ".nofail" /* Prototypes for all available commands */ -static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_scache_load_dir(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); -static int pa_cli_command_list_props(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail); +static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); /* A method table for all available commands */ @@ -139,21 +139,21 @@ static const char whitespace[] = " \t\n\r"; static const char linebreak[] = "\n\r"; static uint32_t parse_index(const char *n) { - uint32_t index; + uint32_t idx; - if (pa_atou(n, &index) < 0) + if (pa_atou(n, &idx) < 0) return (uint32_t) PA_IDXSET_INVALID; - return index; + return idx; } -static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, PA_GCC_UNUSED pa_strbuf *buf, PA_GCC_UNUSED int *fail) { assert(c && c->mainloop && t); c->mainloop->quit(c->mainloop, 0); return 0; } -static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const struct command*command; assert(c && t && buf); @@ -165,7 +165,7 @@ static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct return 0; } -static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char *s; assert(c && t); s = pa_module_list_to_string(c); @@ -175,7 +175,7 @@ static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, str return 0; } -static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char *s; assert(c && t); s = pa_client_list_to_string(c); @@ -185,7 +185,7 @@ static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, str return 0; } -static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char *s; assert(c && t); s = pa_sink_list_to_string(c); @@ -195,7 +195,7 @@ static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struc return 0; } -static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char *s; assert(c && t); s = pa_source_list_to_string(c); @@ -205,7 +205,7 @@ static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, str return 0; } -static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char *s; assert(c && t); s = pa_sink_input_list_to_string(c); @@ -215,7 +215,7 @@ static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char *s; assert(c && t); s = pa_source_output_list_to_string(c); @@ -225,7 +225,7 @@ static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer return 0; } -static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char s[256]; assert(c && t); @@ -253,7 +253,7 @@ static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct return 0; } -static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { assert(c && t); pa_cli_command_stat(c, t, buf, fail); pa_cli_command_modules(c, t, buf, fail); @@ -267,8 +267,8 @@ static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct return 0; } -static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { - struct pa_module *m; +static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { + pa_module *m; const char *name; assert(c && t); @@ -285,9 +285,9 @@ static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct return 0; } -static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { - struct pa_module *m; - uint32_t index; +static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { + pa_module *m; + uint32_t idx; const char *i; char *e; assert(c && t); @@ -297,8 +297,8 @@ static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, stru return -1; } - index = (uint32_t) strtoul(i, &e, 10); - if (*e || !(m = pa_idxset_get_by_index(c->modules, index))) { + idx = (uint32_t) strtoul(i, &e, 10); + if (*e || !(m = pa_idxset_get_by_index(c->modules, idx))) { pa_strbuf_puts(buf, "Invalid module index.\n"); return -1; } @@ -307,9 +307,9 @@ static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, stru return 0; } -static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const char *n, *v; - struct pa_sink *sink; + pa_sink *sink; uint32_t volume; if (!(n = pa_tokenizer_get(t, 1))) { @@ -336,18 +336,18 @@ static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const char *n, *v; - struct pa_sink_input *si; + pa_sink_input *si; uint32_t volume; - uint32_t index; + uint32_t idx; if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n"); return -1; } - if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + if ((idx = parse_index(n)) == PA_IDXSET_INVALID) { pa_strbuf_puts(buf, "Failed to parse index.\n"); return -1; } @@ -362,7 +362,7 @@ static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokeniz return -1; } - if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) index))) { + if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) { pa_strbuf_puts(buf, "No sink input found with this index.\n"); return -1; } @@ -371,7 +371,7 @@ static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokeniz return 0; } -static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const char *n; assert(c && t); @@ -384,7 +384,7 @@ static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t return 0; } -static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const char *n; assert(c && t); @@ -397,10 +397,10 @@ static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer return 0; } -static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const char *n; - struct pa_client *client; - uint32_t index; + pa_client *client; + uint32_t idx; assert(c && t); if (!(n = pa_tokenizer_get(t, 1))) { @@ -408,12 +408,12 @@ static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, return -1; } - if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + if ((idx = parse_index(n)) == PA_IDXSET_INVALID) { pa_strbuf_puts(buf, "Failed to parse index.\n"); return -1; } - if (!(client = pa_idxset_get_by_index(c->clients, index))) { + if (!(client = pa_idxset_get_by_index(c->clients, idx))) { pa_strbuf_puts(buf, "No client found by this index.\n"); return -1; } @@ -422,10 +422,10 @@ static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const char *n; - struct pa_sink_input *sink_input; - uint32_t index; + pa_sink_input *sink_input; + uint32_t idx; assert(c && t); if (!(n = pa_tokenizer_get(t, 1))) { @@ -433,12 +433,12 @@ static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer return -1; } - if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + if ((idx = parse_index(n)) == PA_IDXSET_INVALID) { pa_strbuf_puts(buf, "Failed to parse index.\n"); return -1; } - if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, index))) { + if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx))) { pa_strbuf_puts(buf, "No sink input found by this index.\n"); return -1; } @@ -447,10 +447,10 @@ static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer return 0; } -static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const char *n; - struct pa_source_output *source_output; - uint32_t index; + pa_source_output *source_output; + uint32_t idx; assert(c && t); if (!(n = pa_tokenizer_get(t, 1))) { @@ -458,12 +458,12 @@ static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokeni return -1; } - if ((index = parse_index(n)) == PA_IDXSET_INVALID) { + if ((idx = parse_index(n)) == PA_IDXSET_INVALID) { pa_strbuf_puts(buf, "Failed to parse index.\n"); return -1; } - if (!(source_output = pa_idxset_get_by_index(c->source_outputs, index))) { + if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx))) { pa_strbuf_puts(buf, "No source output found by this index.\n"); return -1; } @@ -472,7 +472,7 @@ static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokeni return 0; } -static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char *s; assert(c && t); s = pa_scache_list_to_string(c); @@ -482,9 +482,9 @@ static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n, *sink_name; - struct pa_sink *sink; + pa_sink *sink; assert(c && t && buf && fail); if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) { @@ -505,7 +505,7 @@ static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n; assert(c && t && buf && fail); @@ -522,7 +522,7 @@ static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer * return 0; } -static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *fname, *n; int r; assert(c && t && buf && fail); @@ -543,7 +543,7 @@ static int pa_cli_command_scache_load(struct pa_core *c, struct pa_tokenizer *t, return 0; } -static int pa_cli_command_scache_load_dir(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *pname; assert(c && t && buf && fail); @@ -560,9 +560,9 @@ static int pa_cli_command_scache_load_dir(struct pa_core *c, struct pa_tokenizer return 0; } -static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *fname, *sink_name; - struct pa_sink *sink; + pa_sink *sink; assert(c && t && buf && fail); if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) { @@ -579,7 +579,7 @@ static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, s return pa_play_file(sink, fname, PA_VOLUME_NORM); } -static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *a, *b; assert(c && t && buf && fail); @@ -593,7 +593,7 @@ static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t return 0; } -static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *name; assert(c && t && buf && fail); @@ -610,7 +610,7 @@ static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer return 0; } -static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char *s; assert(c && t); s = pa_autoload_list_to_string(c); @@ -620,22 +620,22 @@ static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer * return 0; } -static int pa_cli_command_list_props(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { +static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { assert(c && t); pa_property_dump(c, buf); return 0; } -static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail) { - struct pa_module *m; - struct pa_sink *s; +static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { + pa_module *m; + pa_sink *s; int nl; const char *p; - uint32_t index; + uint32_t idx; char txt[256]; time_t now; void *i; - struct pa_autoload_entry *a; + pa_autoload_entry *a; assert(c && t); @@ -648,7 +648,7 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct #endif - for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) { + for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) { if (m->auto_unload) continue; @@ -662,7 +662,7 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct nl = 0; - for (s = pa_idxset_first(c->sinks, &index); s; s = pa_idxset_next(c->sinks, &index)) { + for (s = pa_idxset_first(c->sinks, &idx); s; s = pa_idxset_next(c->sinks, &idx)) { if (s->volume == PA_VOLUME_NORM) continue; @@ -722,7 +722,7 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct } -int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail) { +int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int *fail) { const char *cs; cs = s+strspn(s, whitespace); @@ -758,7 +758,7 @@ int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strb for (command = commands; command->name; command++) if (strlen(command->name) == l && !strncmp(cs, command->name, l)) { int ret; - struct pa_tokenizer *t = pa_tokenizer_new(cs, command->args); + pa_tokenizer *t = pa_tokenizer_new(cs, command->args); assert(t); ret = command->proc(c, t, buf, fail); pa_tokenizer_free(t); @@ -780,7 +780,7 @@ int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strb return 0; } -int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_strbuf *buf, int *fail) { +int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int *fail) { char line[256]; FILE *f = NULL; int ret = -1; @@ -810,7 +810,7 @@ fail: return ret; } -int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail) { +int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail) { const char *p; assert(c && s && buf && fail); diff --git a/polyp/cli-command.h b/polyp/cli-command.h index 7af9d014b..78b8d5c6d 100644 --- a/polyp/cli-command.h +++ b/polyp/cli-command.h @@ -29,12 +29,12 @@ * buffer *buf. If *fail is non-zero the function will return -1 when * one or more of the executed commands failed. *fail * may be modified by the function call. */ -int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail); +int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int *fail); /* Execute a whole file of CLI commands */ -int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_strbuf *buf, int *fail); +int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int *fail); /* Split the specified string into lines and run pa_cli_command_execute_line() for each. */ -int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail); +int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail); #endif diff --git a/polyp/cli-text.c b/polyp/cli-text.c index d4c46dc09..a19bfc971 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -39,36 +39,36 @@ #include "autoload.h" #include "xmalloc.h" -char *pa_module_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_module *m; - uint32_t index = PA_IDXSET_INVALID; +char *pa_module_list_to_string(pa_core *c) { + pa_strbuf *s; + pa_module *m; + uint32_t idx = PA_IDXSET_INVALID; assert(c); s = pa_strbuf_new(); assert(s); - pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_ncontents(c->modules)); + pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_size(c->modules)); - for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) + for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\targument: <%s>\n\tused: %i\n\tauto unload: %s\n", m->index, m->name, m->argument, m->n_used, m->auto_unload ? "yes" : "no"); return pa_strbuf_tostring_free(s); } -char *pa_client_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_client *client; - uint32_t index = PA_IDXSET_INVALID; +char *pa_client_list_to_string(pa_core *c) { + pa_strbuf *s; + pa_client *client; + uint32_t idx = PA_IDXSET_INVALID; char tid[5]; assert(c); s = pa_strbuf_new(); assert(s); - pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_ncontents(c->clients)); + pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_size(c->clients)); - for (client = pa_idxset_first(c->clients, &index); client; client = pa_idxset_next(c->clients, &index)) { + for (client = pa_idxset_first(c->clients, &idx); client; client = pa_idxset_next(c->clients, &idx)) { pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\ttype: <%s>\n", client->index, client->name, pa_typeid_to_string(client->typeid, tid, sizeof(tid))); if (client->owner) @@ -78,19 +78,19 @@ char *pa_client_list_to_string(struct pa_core *c) { return pa_strbuf_tostring_free(s); } -char *pa_sink_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_sink *sink; - uint32_t index = PA_IDXSET_INVALID; +char *pa_sink_list_to_string(pa_core *c) { + pa_strbuf *s; + pa_sink *sink; + uint32_t idx = PA_IDXSET_INVALID; char tid[5]; assert(c); s = pa_strbuf_new(); assert(s); - pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_ncontents(c->sinks)); + pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks)); - for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index)) { + for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec); assert(sink->monitor_source); @@ -102,7 +102,7 @@ char *pa_sink_list_to_string(struct pa_core *c) { pa_typeid_to_string(sink->typeid, tid, sizeof(tid)), (unsigned) sink->volume, pa_volume_to_dB(sink->volume), - (float) pa_sink_get_latency(sink), + (double) pa_sink_get_latency(sink), sink->monitor_source->index, ss); @@ -115,19 +115,19 @@ char *pa_sink_list_to_string(struct pa_core *c) { return pa_strbuf_tostring_free(s); } -char *pa_source_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_source *source; - uint32_t index = PA_IDXSET_INVALID; +char *pa_source_list_to_string(pa_core *c) { + pa_strbuf *s; + pa_source *source; + uint32_t idx = PA_IDXSET_INVALID; char tid[5]; assert(c); s = pa_strbuf_new(); assert(s); - pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_ncontents(c->sources)); + pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources)); - for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) { + for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec); pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\ttype: <%s>\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n", @@ -135,7 +135,7 @@ char *pa_source_list_to_string(struct pa_core *c) { source->index, source->name, pa_typeid_to_string(source->typeid, tid, sizeof(tid)), - (float) pa_source_get_latency(source), + (double) pa_source_get_latency(source), ss); if (source->monitor_of) @@ -150,10 +150,10 @@ char *pa_source_list_to_string(struct pa_core *c) { } -char *pa_source_output_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_source_output *o; - uint32_t index = PA_IDXSET_INVALID; +char *pa_source_output_list_to_string(pa_core *c) { + pa_strbuf *s; + pa_source_output *o; + uint32_t idx = PA_IDXSET_INVALID; char tid[5]; static const char* const state_table[] = { "RUNNING", @@ -165,9 +165,9 @@ char *pa_source_output_list_to_string(struct pa_core *c) { s = pa_strbuf_new(); assert(s); - pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_ncontents(c->source_outputs)); + pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_size(c->source_outputs)); - for (o = pa_idxset_first(c->source_outputs, &index); o; o = pa_idxset_next(c->source_outputs, &index)) { + for (o = pa_idxset_first(c->source_outputs, &idx); o; o = pa_idxset_next(c->source_outputs, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; const char *rm; pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec); @@ -194,10 +194,10 @@ char *pa_source_output_list_to_string(struct pa_core *c) { return pa_strbuf_tostring_free(s); } -char *pa_sink_input_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; - struct pa_sink_input *i; - uint32_t index = PA_IDXSET_INVALID; +char *pa_sink_input_list_to_string(pa_core *c) { + pa_strbuf *s; + pa_sink_input *i; + uint32_t idx = PA_IDXSET_INVALID; char tid[5]; static const char* const state_table[] = { "RUNNING", @@ -209,9 +209,9 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { s = pa_strbuf_new(); assert(s); - pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_ncontents(c->sink_inputs)); + pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs)); - for (i = pa_idxset_first(c->sink_inputs, &index); i; i = pa_idxset_next(c->sink_inputs, &index)) { + for (i = pa_idxset_first(c->sink_inputs, &idx); i; i = pa_idxset_next(c->sink_inputs, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; const char *rm; @@ -229,7 +229,7 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { i->sink->index, i->sink->name, (unsigned) i->volume, pa_volume_to_dB(i->volume), - (float) pa_sink_input_get_latency(i), + (double) pa_sink_input_get_latency(i), ss, rm); @@ -242,20 +242,20 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { return pa_strbuf_tostring_free(s); } -char *pa_scache_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; +char *pa_scache_list_to_string(pa_core *c) { + pa_strbuf *s; assert(c); s = pa_strbuf_new(); assert(s); - pa_strbuf_printf(s, "%u cache entries available.\n", c->scache ? pa_idxset_ncontents(c->scache) : 0); + pa_strbuf_printf(s, "%u cache entries available.\n", c->scache ? pa_idxset_size(c->scache) : 0); if (c->scache) { - struct pa_scache_entry *e; - uint32_t index = PA_IDXSET_INVALID; + pa_scache_entry *e; + uint32_t idx = PA_IDXSET_INVALID; - for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) { + for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) { double l = 0; char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a"; @@ -280,17 +280,17 @@ char *pa_scache_list_to_string(struct pa_core *c) { return pa_strbuf_tostring_free(s); } -char *pa_autoload_list_to_string(struct pa_core *c) { - struct pa_strbuf *s; +char *pa_autoload_list_to_string(pa_core *c) { + pa_strbuf *s; assert(c); s = pa_strbuf_new(); assert(s); - pa_strbuf_printf(s, "%u autoload entries available.\n", c->autoload_hashmap ? pa_hashmap_ncontents(c->autoload_hashmap) : 0); + pa_strbuf_printf(s, "%u autoload entries available.\n", c->autoload_hashmap ? pa_hashmap_size(c->autoload_hashmap) : 0); if (c->autoload_hashmap) { - struct pa_autoload_entry *e; + pa_autoload_entry *e; void *state = NULL; while ((e = pa_hashmap_iterate(c->autoload_hashmap, &state, NULL))) { @@ -308,8 +308,8 @@ char *pa_autoload_list_to_string(struct pa_core *c) { return pa_strbuf_tostring_free(s); } -char *pa_full_status_string(struct pa_core *c) { - struct pa_strbuf *s; +char *pa_full_status_string(pa_core *c) { + pa_strbuf *s; int i; s = pa_strbuf_new(); diff --git a/polyp/cli-text.h b/polyp/cli-text.h index d19dd48ca..7a1a03610 100644 --- a/polyp/cli-text.h +++ b/polyp/cli-text.h @@ -27,16 +27,16 @@ /* Some functions to generate pretty formatted listings of * entities. The returned strings have to be freed manually. */ -char *pa_sink_input_list_to_string(struct pa_core *c); -char *pa_source_output_list_to_string(struct pa_core *c); -char *pa_sink_list_to_string(struct pa_core *core); -char *pa_source_list_to_string(struct pa_core *c); -char *pa_client_list_to_string(struct pa_core *c); -char *pa_module_list_to_string(struct pa_core *c); -char *pa_scache_list_to_string(struct pa_core *c); -char *pa_autoload_list_to_string(struct pa_core *c); +char *pa_sink_input_list_to_string(pa_core *c); +char *pa_source_output_list_to_string(pa_core *c); +char *pa_sink_list_to_string(pa_core *core); +char *pa_source_list_to_string(pa_core *c); +char *pa_client_list_to_string(pa_core *c); +char *pa_module_list_to_string(pa_core *c); +char *pa_scache_list_to_string(pa_core *c); +char *pa_autoload_list_to_string(pa_core *c); -char *pa_full_status_string(struct pa_core *c); +char *pa_full_status_string(pa_core *c); #endif diff --git a/polyp/cli.c b/polyp/cli.c index 16323cbae..7b1022c1a 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -48,26 +48,26 @@ #define PA_TYPEID_CLI PA_TYPEID_MAKE('C', 'L', 'I', '_') struct pa_cli { - struct pa_core *core; - struct pa_ioline *line; + pa_core *core; + pa_ioline *line; - void (*eof_callback)(struct pa_cli *c, void *userdata); + void (*eof_callback)(pa_cli *c, void *userdata); void *userdata; - struct pa_client *client; + pa_client *client; int fail, kill_requested, defer_kill; }; -static void line_callback(struct pa_ioline *line, const char *s, void *userdata); -static void client_kill(struct pa_client *c); +static void line_callback(pa_ioline *line, const char *s, void *userdata); +static void client_kill(pa_client *c); -struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct pa_module *m) { +pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) { char cname[256]; - struct pa_cli *c; + pa_cli *c; assert(io); - c = pa_xmalloc(sizeof(struct pa_cli)); + c = pa_xmalloc(sizeof(pa_cli)); c->core = core; c->line = pa_ioline_new(io); assert(c->line); @@ -90,7 +90,7 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct return c; } -void pa_cli_free(struct pa_cli *c) { +void pa_cli_free(pa_cli *c) { assert(c); pa_ioline_close(c->line); pa_ioline_unref(c->line); @@ -98,8 +98,8 @@ void pa_cli_free(struct pa_cli *c) { pa_xfree(c); } -static void client_kill(struct pa_client *client) { - struct pa_cli *c; +static void client_kill(pa_client *client) { + pa_cli *c; assert(client && client->userdata); c = client->userdata; @@ -112,9 +112,9 @@ static void client_kill(struct pa_client *client) { } } -static void line_callback(struct pa_ioline *line, const char *s, void *userdata) { - struct pa_strbuf *buf; - struct pa_cli *c = userdata; +static void line_callback(pa_ioline *line, const char *s, void *userdata) { + pa_strbuf *buf; + pa_cli *c = userdata; char *p; assert(line && c); @@ -141,7 +141,7 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) pa_ioline_puts(line, PROMPT); } -void pa_cli_set_eof_callback(struct pa_cli *c, void (*cb)(struct pa_cli*c, void *userdata), void *userdata) { +void pa_cli_set_eof_callback(pa_cli *c, void (*cb)(pa_cli*c, void *userdata), void *userdata) { assert(c); c->eof_callback = cb; c->userdata = userdata; diff --git a/polyp/cli.h b/polyp/cli.h index 44ed706cc..03f31c22c 100644 --- a/polyp/cli.h +++ b/polyp/cli.h @@ -26,13 +26,13 @@ #include "core.h" #include "module.h" -struct pa_cli; +typedef struct pa_cli pa_cli; /* Create a new command line session on the specified io channel owned by the specified module */ -struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct pa_module *m); -void pa_cli_free(struct pa_cli *cli); +pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m); +void pa_cli_free(pa_cli *cli); /* Set a callback function that is called whenever the command line session is terminated */ -void pa_cli_set_eof_callback(struct pa_cli *cli, void (*cb)(struct pa_cli*c, void *userdata), void *userdata); +void pa_cli_set_eof_callback(pa_cli *cli, void (*cb)(pa_cli*c, void *userdata), void *userdata); #endif diff --git a/polyp/client-conf-x11.c b/polyp/client-conf-x11.c index 383aa64e7..4fd757440 100644 --- a/polyp/client-conf-x11.c +++ b/polyp/client-conf-x11.c @@ -35,7 +35,7 @@ #include "xmalloc.h" #include "util.h" -int pa_client_conf_from_x11(struct pa_client_conf *c, const char *dname) { +int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { Display *d = NULL; int ret = -1; char t[1024]; diff --git a/polyp/client-conf-x11.h b/polyp/client-conf-x11.h index e65e8202b..64459224f 100644 --- a/polyp/client-conf-x11.h +++ b/polyp/client-conf-x11.h @@ -26,6 +26,6 @@ /* Load client configuration data from the specified X11 display, * overwriting the current settings in *c */ -int pa_client_conf_from_x11(struct pa_client_conf *c, const char *display); +int pa_client_conf_from_x11(pa_client_conf *c, const char *display); #endif diff --git a/polyp/client-conf.c b/polyp/client-conf.c index 04c3d2ef7..bcd4275d7 100644 --- a/polyp/client-conf.c +++ b/polyp/client-conf.c @@ -60,7 +60,7 @@ #define ENV_DAEMON_BINARY "POLYP_BINARY" #define ENV_COOKIE_FILE "POLYP_COOKIE" -static const struct pa_client_conf default_conf = { +static const pa_client_conf default_conf = { .daemon_binary = NULL, .extra_arguments = NULL, .default_sink = NULL, @@ -71,8 +71,8 @@ static const struct pa_client_conf default_conf = { .cookie_valid = 0 }; -struct pa_client_conf *pa_client_conf_new(void) { - struct pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); +pa_client_conf *pa_client_conf_new(void) { + pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); c->daemon_binary = pa_xstrdup(POLYPAUDIO_BINARY); c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5"); @@ -81,7 +81,7 @@ struct pa_client_conf *pa_client_conf_new(void) { return c; } -void pa_client_conf_free(struct pa_client_conf *c) { +void pa_client_conf_free(pa_client_conf *c) { assert(c); pa_xfree(c->daemon_binary); pa_xfree(c->extra_arguments); @@ -91,13 +91,13 @@ void pa_client_conf_free(struct pa_client_conf *c) { pa_xfree(c->cookie_file); pa_xfree(c); } -int pa_client_conf_load(struct pa_client_conf *c, const char *filename) { +int pa_client_conf_load(pa_client_conf *c, const char *filename) { FILE *f = NULL; char *fn = NULL; int r = -1; /* Prepare the configuration parse table */ - struct pa_config_item table[] = { + pa_config_item table[] = { { "daemon-binary", pa_config_parse_string, NULL }, { "extra-arguments", pa_config_parse_string, NULL }, { "default-sink", pa_config_parse_string, NULL }, @@ -140,7 +140,7 @@ finish: return r; } -int pa_client_conf_env(struct pa_client_conf *c) { +int pa_client_conf_env(pa_client_conf *c) { char *e; if ((e = getenv(ENV_DEFAULT_SINK))) { @@ -173,7 +173,7 @@ int pa_client_conf_env(struct pa_client_conf *c) { return 0; } -int pa_client_conf_load_cookie(struct pa_client_conf* c) { +int pa_client_conf_load_cookie(pa_client_conf* c) { assert(c); c->cookie_valid = 0; diff --git a/polyp/client-conf.h b/polyp/client-conf.h index b46250393..7ca2f2335 100644 --- a/polyp/client-conf.h +++ b/polyp/client-conf.h @@ -26,27 +26,27 @@ /* A structure containing configuration data for polypaudio clients. */ -struct pa_client_conf { +typedef struct pa_client_conf { char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; int autospawn; uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; int cookie_valid; /* non-zero, when cookie is valid */ -}; +} pa_client_conf; /* Create a new configuration data object and reset it to defaults */ -struct pa_client_conf *pa_client_conf_new(void); -void pa_client_conf_free(struct pa_client_conf *c); +pa_client_conf *pa_client_conf_new(void); +void pa_client_conf_free(pa_client_conf *c); /* Load the configuration data from the speicified file, overwriting * the current settings in *c. When the filename is NULL, the * default client configuration file name is used. */ -int pa_client_conf_load(struct pa_client_conf *c, const char *filename); +int pa_client_conf_load(pa_client_conf *c, const char *filename); /* Load the configuration data from the environment of the current process, overwriting the current settings in *c. */ -int pa_client_conf_env(struct pa_client_conf *c); +int pa_client_conf_env(pa_client_conf *c); /* Load cookie data from c->cookie_file into c->cookie */ -int pa_client_conf_load_cookie(struct pa_client_conf* c); +int pa_client_conf_load_cookie(pa_client_conf* c); #endif diff --git a/polyp/client.c b/polyp/client.c index 8c7f48009..1938a4e0c 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -33,12 +33,12 @@ #include "subscribe.h" #include "log.h" -struct pa_client *pa_client_new(struct pa_core *core, pa_typeid_t typeid, const char *name) { - struct pa_client *c; +pa_client *pa_client_new(pa_core *core, pa_typeid_t typeid, const char *name) { + pa_client *c; int r; assert(core); - c = pa_xmalloc(sizeof(struct pa_client)); + c = pa_xmalloc(sizeof(pa_client)); c->name = pa_xstrdup(name); c->owner = NULL; c->core = core; @@ -58,7 +58,7 @@ struct pa_client *pa_client_new(struct pa_core *core, pa_typeid_t typeid, const return c; } -void pa_client_free(struct pa_client *c) { +void pa_client_free(pa_client *c) { assert(c && c->core); pa_idxset_remove_by_data(c->core->clients, c, NULL); @@ -72,7 +72,7 @@ void pa_client_free(struct pa_client *c) { } -void pa_client_kill(struct pa_client *c) { +void pa_client_kill(pa_client *c) { assert(c); if (!c->kill) { pa_log_warn(__FILE__": kill() operation not implemented for client %u\n", c->index); @@ -82,7 +82,7 @@ void pa_client_kill(struct pa_client *c) { c->kill(c); } -void pa_client_set_name(struct pa_client *c, const char *name) { +void pa_client_set_name(pa_client *c, const char *name) { assert(c); pa_xfree(c->name); c->name = pa_xstrdup(name); diff --git a/polyp/client.h b/polyp/client.h index 2a3a09e09..198dbbf66 100644 --- a/polyp/client.h +++ b/polyp/client.h @@ -30,28 +30,30 @@ * attached. That way the user may generate a listing of all connected * clients easily and kill them if he wants.*/ +typedef struct pa_client pa_client; + struct pa_client { uint32_t index; pa_typeid_t typeid; - struct pa_module *owner; + pa_module *owner; char *name; - struct pa_core *core; + pa_core *core; - void (*kill)(struct pa_client *c); + void (*kill)(pa_client *c); void *userdata; }; -struct pa_client *pa_client_new(struct pa_core *c, pa_typeid_t typeid, const char *name); +pa_client *pa_client_new(pa_core *c, pa_typeid_t typeid, const char *name); /* This function should be called only by the code that created the client */ -void pa_client_free(struct pa_client *c); +void pa_client_free(pa_client *c); /* Code that didn't create the client should call this function to * request destruction of the client */ -void pa_client_kill(struct pa_client *c); +void pa_client_kill(pa_client *c); /* Rename the client */ -void pa_client_set_name(struct pa_client *c, const char *name); +void pa_client_set_name(pa_client *c, const char *name); #endif diff --git a/polyp/cmdline.c b/polyp/cmdline.c index 0951725a1..5635707f2 100644 --- a/polyp/cmdline.c +++ b/polyp/cmdline.c @@ -135,8 +135,8 @@ void pa_cmdline_help(const char *argv0) { " -n Don't load default script file\n", e); } -int pa_cmdline_parse(struct pa_daemon_conf *conf, int argc, char *const argv [], int *d) { - struct pa_strbuf *buf = NULL; +int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d) { + pa_strbuf *buf = NULL; int c; assert(conf && argc && argv); diff --git a/polyp/cmdline.h b/polyp/cmdline.h index ca100d1d8..e2eaf0d2f 100644 --- a/polyp/cmdline.h +++ b/polyp/cmdline.h @@ -26,7 +26,7 @@ /* Parese the command line and store its data in *c. Return the index * of the first unparsed argument in *d. */ -int pa_cmdline_parse(struct pa_daemon_conf*c, int argc, char *const argv [], int *d); +int pa_cmdline_parse(pa_daemon_conf*c, int argc, char *const argv [], int *d); /* Show the command line help. The command name is extracted from * argv[0] which should be passed in argv0. */ diff --git a/polyp/conf-parser.c b/polyp/conf-parser.c index 8d2f2f681..507f2bf19 100644 --- a/polyp/conf-parser.c +++ b/polyp/conf-parser.c @@ -37,7 +37,7 @@ #define COMMENTS "#;\n" /* Run the user supplied parser for an assignment */ -static int next_assignment(const char *filename, unsigned line, const struct pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) { +static int next_assignment(const char *filename, unsigned line, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) { assert(filename && t && lvalue && rvalue); for (; t->parse; t++) @@ -77,7 +77,7 @@ static char *strip(char *s) { } /* Parse a variable assignment line */ -static int parse_line(const char *filename, unsigned line, const struct pa_config_item *t, char *l, void *userdata) { +static int parse_line(const char *filename, unsigned line, const pa_config_item *t, char *l, void *userdata) { char *e, *c, *b = l+strspn(l, WHITESPACE); if ((c = strpbrk(b, COMMENTS))) @@ -98,7 +98,7 @@ static int parse_line(const char *filename, unsigned line, const struct pa_confi } /* Go through the file and parse each line */ -int pa_config_parse(const char *filename, FILE *f, const struct pa_config_item *t, void *userdata) { +int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata) { int r = -1; unsigned line = 0; int do_close = !f; @@ -138,7 +138,7 @@ finish: return r; } -int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { int *i = data; int32_t k; assert(filename && lvalue && rvalue && data); @@ -152,7 +152,7 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, return 0; } -int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { int *b = data, k; assert(filename && lvalue && rvalue && data); @@ -166,7 +166,7 @@ int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue return 0; } -int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { +int pa_config_parse_string(const char *filename, PA_GCC_UNUSED unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { char **s = data; assert(filename && lvalue && rvalue && data); diff --git a/polyp/conf-parser.h b/polyp/conf-parser.h index 9add0be05..2dca3bceb 100644 --- a/polyp/conf-parser.h +++ b/polyp/conf-parser.h @@ -28,16 +28,16 @@ * files consisting of variable assignments only. */ /* Wraps info for parsing a specific configuration variable */ -struct pa_config_item { +typedef struct pa_config_item { const char *lvalue; /* name of the variable */ int (*parse)(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); /* Function that is called to parse the variable's value */ void *data; /* Where to store the variable's data */ -}; +} pa_config_item; /* The configuration file parsing routine. Expects a table of * pa_config_items in *t that is terminated by an item where lvalue is * NULL */ -int pa_config_parse(const char *filename, FILE *f, const struct pa_config_item *t, void *userdata); +int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata); /* Generic parsers for integers, booleans and strings */ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); diff --git a/polyp/core.c b/polyp/core.c index 604392431..678e8212c 100644 --- a/polyp/core.c +++ b/polyp/core.c @@ -41,9 +41,9 @@ #include "props.h" #include "random.h" -struct pa_core* pa_core_new(struct pa_mainloop_api *m) { - struct pa_core* c; - c = pa_xmalloc(sizeof(struct pa_core)); +pa_core* pa_core_new(pa_mainloop_api *m) { + pa_core* c; + c = pa_xmalloc(sizeof(pa_core)); c->mainloop = m; c->clients = pa_idxset_new(NULL, NULL); @@ -95,7 +95,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) { return c; } -void pa_core_free(struct pa_core *c) { +void pa_core_free(pa_core *c) { assert(c); pa_module_unload_all(c); @@ -134,22 +134,22 @@ void pa_core_free(struct pa_core *c) { pa_xfree(c); } -static void quit_callback(struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata) { - struct pa_core *c = userdata; +static void quit_callback(pa_mainloop_api*m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { + pa_core *c = userdata; assert(c->quit_event = e); m->quit(m, 0); } -void pa_core_check_quit(struct pa_core *c) { +void pa_core_check_quit(pa_core *c) { assert(c); - if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_ncontents(c->clients) == 0) { + if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_size(c->clients) == 0) { struct timeval tv; pa_gettimeofday(&tv); tv.tv_sec+= c->exit_idle_time; c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c); - } else if (c->quit_event && pa_idxset_ncontents(c->clients) > 0) { + } else if (c->quit_event && pa_idxset_size(c->clients) > 0) { c->mainloop->time_free(c->quit_event); c->quit_event = NULL; } diff --git a/polyp/core.h b/polyp/core.h index 8ef665707..704246a9f 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -22,12 +22,16 @@ USA. ***/ +typedef struct pa_core pa_core; + #include "idxset.h" #include "hashmap.h" #include "mainloop-api.h" #include "sample.h" #include "memblock.h" #include "resampler.h" +#include "queue.h" +#include "subscribe.h" /* The core structure of polypaudio. Every polypaudio daemon contains * exactly one of these. It is used for storing kind of global @@ -38,41 +42,41 @@ struct pa_core { * polypaudio. Not cryptographically secure in any way. */ uint32_t cookie; - struct pa_mainloop_api *mainloop; + pa_mainloop_api *mainloop; /* idxset of all kinds of entities */ - struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache, *autoload_idxset; + pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache, *autoload_idxset; /* Some hashmaps for all sorts of entities */ - struct pa_hashmap *namereg, *autoload_hashmap, *properties; + pa_hashmap *namereg, *autoload_hashmap, *properties; /* The name of the default sink/source */ char *default_source_name, *default_sink_name; - struct pa_sample_spec default_sample_spec; - struct pa_time_event *module_auto_unload_event; - struct pa_defer_event *module_defer_unload_event; + pa_sample_spec default_sample_spec; + pa_time_event *module_auto_unload_event; + pa_defer_event *module_defer_unload_event; - struct pa_defer_event *subscription_defer_event; - struct pa_queue *subscription_event_queue; - struct pa_subscription *subscriptions; + pa_defer_event *subscription_defer_event; + pa_queue *subscription_event_queue; + pa_subscription *subscriptions; - struct pa_memblock_stat *memblock_stat; + pa_memblock_stat *memblock_stat; int disallow_module_loading, running_as_daemon; int exit_idle_time, module_idle_time, scache_idle_time; - struct pa_time_event *quit_event; + pa_time_event *quit_event; - struct pa_time_event *scache_auto_unload_event; + pa_time_event *scache_auto_unload_event; - enum pa_resample_method resample_method; + pa_resample_method resample_method; }; -struct pa_core* pa_core_new(struct pa_mainloop_api *m); -void pa_core_free(struct pa_core*c); +pa_core* pa_core_new(pa_mainloop_api *m); +void pa_core_free(pa_core*c); /* Check whether noone is connected to this core */ -void pa_core_check_quit(struct pa_core *c); +void pa_core_check_quit(pa_core *c); #endif diff --git a/polyp/cpulimit-test.c b/polyp/cpulimit-test.c index de5e20ad9..598b2dd24 100644 --- a/polyp/cpulimit-test.c +++ b/polyp/cpulimit-test.c @@ -31,6 +31,7 @@ #include "cpulimit.h" #include "mainloop.h" +#include "gccmacro.h" #ifdef TEST2 #include "mainloop-signal.h" @@ -42,7 +43,7 @@ static time_t start; #ifdef TEST2 -static void func(struct pa_mainloop_api *m, struct pa_signal_event *e, int sig, void *userdata) { +static void func(pa_mainloop_api *m, PA_GCC_UNUSED pa_signal_event *e, PA_GCC_UNUSED int sig, PA_GCC_UNUSED void *userdata) { time_t now; time(&now); @@ -55,8 +56,8 @@ static void func(struct pa_mainloop_api *m, struct pa_signal_event *e, int sig, #endif -int main() { - struct pa_mainloop *m; +int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { + pa_mainloop *m; m = pa_mainloop_new(); assert(m); diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c index 53920f50a..a834b0948 100644 --- a/polyp/cpulimit.c +++ b/polyp/cpulimit.c @@ -23,6 +23,10 @@ #include #endif +#include "cpulimit.h" +#include "util.h" +#include "log.h" + #ifdef HAVE_SIGXCPU #include @@ -37,11 +41,6 @@ #include #endif -#include "cpulimit.h" -#include "util.h" -#include "log.h" - - /* This module implements a watchdog that makes sure that the current * process doesn't consume more than 70% CPU time for 10 seconds. This * is very useful when using SCHED_FIFO scheduling which effectively @@ -70,8 +69,8 @@ static time_t last_time = 0; static int the_pipe[2] = {-1, -1}; /* Main event loop and IO event for the FIFO */ -static struct pa_mainloop_api *api = NULL; -static struct pa_io_event *io_event = NULL; +static pa_mainloop_api *api = NULL; +static pa_io_event *io_event = NULL; /* Saved sigaction struct for SIGXCPU */ static struct sigaction sigaction_prev; @@ -153,7 +152,7 @@ static void signal_handler(int sig) { } /* Callback for IO events on the FIFO */ -static void callback(struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) { +static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags f, void *userdata) { char c; assert(m && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == the_pipe[0]); read(the_pipe[0], &c, sizeof(c)); @@ -161,7 +160,7 @@ static void callback(struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enu } /* Initializes CPU load limiter */ -int pa_cpu_limit_init(struct pa_mainloop_api *m) { +int pa_cpu_limit_init(pa_mainloop_api *m) { struct sigaction sa; assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1 && !installed); @@ -227,9 +226,7 @@ void pa_cpu_limit_done(void) { #else /* HAVE_SIGXCPU */ -struct pa_mainloop_api; - -int pa_cpu_limit_init(struct pa_mainloop_api *m) { +int pa_cpu_limit_init(PA_GCC_UNUSED pa_mainloop_api *m) { return 0; } diff --git a/polyp/cpulimit.h b/polyp/cpulimit.h index a171da9b4..8ca4f8d9f 100644 --- a/polyp/cpulimit.h +++ b/polyp/cpulimit.h @@ -28,7 +28,7 @@ * CPU time. This is build around setrlimit() and SIGXCPU. It is handy * in case of using SCHED_FIFO which may freeze the whole machine */ -int pa_cpu_limit_init(struct pa_mainloop_api *m); +int pa_cpu_limit_init(pa_mainloop_api *m); void pa_cpu_limit_done(void); #endif diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index 780581b2c..4ad78bab5 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -59,7 +59,7 @@ #define ENV_CONFIG_FILE "POLYP_CONFIG" #define ENV_DL_SEARCH_PATH "POLYP_DLPATH" -static const struct pa_daemon_conf default_conf = { +static const pa_daemon_conf default_conf = { .cmd = PA_CMD_DAEMON, .daemonize = 0, .fail = 1, @@ -79,9 +79,9 @@ static const struct pa_daemon_conf default_conf = { .use_pid_file = 1 }; -struct pa_daemon_conf* pa_daemon_conf_new(void) { +pa_daemon_conf* pa_daemon_conf_new(void) { FILE *f; - struct pa_daemon_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); + pa_daemon_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file))) fclose(f); @@ -92,7 +92,7 @@ struct pa_daemon_conf* pa_daemon_conf_new(void) { return c; } -void pa_daemon_conf_free(struct pa_daemon_conf *c) { +void pa_daemon_conf_free(pa_daemon_conf *c) { assert(c); pa_xfree(c->script_commands); pa_xfree(c->dl_search_path); @@ -101,7 +101,7 @@ void pa_daemon_conf_free(struct pa_daemon_conf *c) { pa_xfree(c); } -int pa_daemon_conf_set_log_target(struct pa_daemon_conf *c, const char *string) { +int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) { assert(c && string); if (!strcmp(string, "auto")) @@ -118,7 +118,7 @@ int pa_daemon_conf_set_log_target(struct pa_daemon_conf *c, const char *string) return 0; } -int pa_daemon_conf_set_log_level(struct pa_daemon_conf *c, const char *string) { +int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) { uint32_t u; assert(c && string); @@ -126,7 +126,7 @@ int pa_daemon_conf_set_log_level(struct pa_daemon_conf *c, const char *string) { if (u >= PA_LOG_LEVEL_MAX) return -1; - c->log_level = (enum pa_log_level) u; + c->log_level = (pa_log_level) u; } else if (pa_startswith(string, "debug")) c->log_level = PA_LOG_DEBUG; else if (pa_startswith(string, "info")) @@ -143,7 +143,7 @@ int pa_daemon_conf_set_log_level(struct pa_daemon_conf *c, const char *string) { return 0; } -int pa_daemon_conf_set_resample_method(struct pa_daemon_conf *c, const char *string) { +int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) { int m; assert(c && string); @@ -154,8 +154,8 @@ int pa_daemon_conf_set_resample_method(struct pa_daemon_conf *c, const char *str return 0; } -static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { - struct pa_daemon_conf *c = data; +static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; assert(filename && lvalue && rvalue && data); if (pa_daemon_conf_set_log_target(c, rvalue) < 0) { @@ -166,8 +166,8 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva return 0; } -static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { - struct pa_daemon_conf *c = data; +static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; assert(filename && lvalue && rvalue && data); if (pa_daemon_conf_set_log_level(c, rvalue) < 0) { @@ -178,8 +178,8 @@ static int parse_log_level(const char *filename, unsigned line, const char *lval return 0; } -static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { - struct pa_daemon_conf *c = data; +static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; assert(filename && lvalue && rvalue && data); if (pa_daemon_conf_set_resample_method(c, rvalue) < 0) { @@ -190,11 +190,11 @@ static int parse_resample_method(const char *filename, unsigned line, const char return 0; } -int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename) { +int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { int r = -1; FILE *f = NULL; - struct pa_config_item table[] = { + pa_config_item table[] = { { "daemonize", pa_config_parse_bool, NULL }, { "fail", pa_config_parse_bool, NULL }, { "high-priority", pa_config_parse_bool, NULL }, @@ -248,7 +248,7 @@ finish: return r; } -int pa_daemon_conf_env(struct pa_daemon_conf *c) { +int pa_daemon_conf_env(pa_daemon_conf *c) { char *e; if ((e = getenv(ENV_DL_SEARCH_PATH))) { @@ -271,8 +271,8 @@ static const char* const log_level_to_string[] = { [PA_LOG_ERROR] = "error" }; -char *pa_daemon_conf_dump(struct pa_daemon_conf *c) { - struct pa_strbuf *s = pa_strbuf_new(); +char *pa_daemon_conf_dump(pa_daemon_conf *c) { + pa_strbuf *s = pa_strbuf_new(); if (c->config_file) pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file); diff --git a/polyp/daemon-conf.h b/polyp/daemon-conf.h index 30137e8bb..4eb61365d 100644 --- a/polyp/daemon-conf.h +++ b/polyp/daemon-conf.h @@ -25,7 +25,7 @@ #include "log.h" /* The actual command to execute */ -enum pa_daemon_conf_cmd { +typedef enum pa_daemon_conf_cmd { PA_CMD_DAEMON, /* the default */ PA_CMD_HELP, PA_CMD_VERSION, @@ -33,11 +33,11 @@ enum pa_daemon_conf_cmd { PA_CMD_DUMP_MODULES, PA_CMD_KILL, PA_CMD_CHECK -}; +} pa_daemon_conf_cmd; /* A structure containing configuration data for the Polypaudio server . */ -struct pa_daemon_conf { - enum pa_daemon_conf_cmd cmd; +typedef struct pa_daemon_conf { + pa_daemon_conf_cmd cmd; int daemonize, fail, high_priority, @@ -48,33 +48,33 @@ struct pa_daemon_conf { auto_log_target, use_pid_file; char *script_commands, *dl_search_path, *default_script_file; - enum pa_log_target log_target; - enum pa_log_level log_level; + pa_log_target log_target; + pa_log_level log_level; int resample_method; char *config_file; -}; +} pa_daemon_conf; /* Allocate a new structure and fill it with sane defaults */ -struct pa_daemon_conf* pa_daemon_conf_new(void); -void pa_daemon_conf_free(struct pa_daemon_conf*c); +pa_daemon_conf* pa_daemon_conf_new(void); +void pa_daemon_conf_free(pa_daemon_conf*c); /* Load configuration data from the specified file overwriting the * current settings in *c. If filename is NULL load the default daemon * configuration file */ -int pa_daemon_conf_load(struct pa_daemon_conf *c, const char *filename); +int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename); /* Pretty print the current configuration data of the daemon. The * returned string has to be freed manually. The output of this * function may be parsed with pa_daemon_conf_load(). */ -char *pa_daemon_conf_dump(struct pa_daemon_conf *c); +char *pa_daemon_conf_dump(pa_daemon_conf *c); /* Load the configuration data from the process' environment * overwriting the current settings in *c. */ -int pa_daemon_conf_env(struct pa_daemon_conf *c); +int pa_daemon_conf_env(pa_daemon_conf *c); /* Set these configuration variables in the structure by passing a string */ -int pa_daemon_conf_set_log_target(struct pa_daemon_conf *c, const char *string); -int pa_daemon_conf_set_log_level(struct pa_daemon_conf *c, const char *string); -int pa_daemon_conf_set_resample_method(struct pa_daemon_conf *c, const char *string); +int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string); +int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string); +int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string); #endif diff --git a/polyp/dumpmodules.c b/polyp/dumpmodules.c index 5aaa108dd..6864b965a 100644 --- a/polyp/dumpmodules.c +++ b/polyp/dumpmodules.c @@ -35,12 +35,12 @@ #define PREFIX "module-" -static void short_info(const char *name, const char *path, struct pa_modinfo *i) { +static void short_info(const char *name, PA_GCC_UNUSED const char *path, pa_modinfo *i) { assert(name && i); printf("%-40s%s\n", name, i->description ? i->description : "n/a"); } -static void long_info(const char *name, const char *path, struct pa_modinfo *i) { +static void long_info(const char *name, const char *path, pa_modinfo *i) { static int nl = 0; assert(name && i); @@ -68,8 +68,8 @@ static void long_info(const char *name, const char *path, struct pa_modinfo *i) printf("Path: %s\n", path); } -static void show_info(const char *name, const char *path, void (*info)(const char *name, const char *path, struct pa_modinfo*i)) { - struct pa_modinfo *i; +static void show_info(const char *name, const char *path, void (*info)(const char *name, const char *path, pa_modinfo*i)) { + pa_modinfo *i; if ((i = pa_modinfo_get_by_name(path ? path : name))) { info(name, path, i); @@ -79,7 +79,7 @@ static void show_info(const char *name, const char *path, void (*info)(const cha static int callback(const char *path, lt_ptr data) { const char *e; - struct pa_daemon_conf *c = (data); + pa_daemon_conf *c = (data); e = pa_path_get_filename(path); @@ -89,7 +89,7 @@ static int callback(const char *path, lt_ptr data) { return 0; } -void pa_dump_modules(struct pa_daemon_conf *c, int argc, char * const argv[]) { +void pa_dump_modules(pa_daemon_conf *c, int argc, char * const argv[]) { if (argc > 0) { int i; for (i = 0; i < argc; i++) diff --git a/polyp/dumpmodules.h b/polyp/dumpmodules.h index fadc571f3..968d2de95 100644 --- a/polyp/dumpmodules.h +++ b/polyp/dumpmodules.h @@ -26,6 +26,6 @@ /* Dump all available modules to STDOUT. If argc > 0 print information * about the modules specified in argv[] instead. */ -void pa_dump_modules(struct pa_daemon_conf *c, int argc, char * const argv[]); +void pa_dump_modules(pa_daemon_conf *c, int argc, char * const argv[]); #endif diff --git a/polyp/dynarray.c b/polyp/dynarray.c index 0e406ea1b..435fd7686 100644 --- a/polyp/dynarray.c +++ b/polyp/dynarray.c @@ -38,16 +38,16 @@ struct pa_dynarray { unsigned n_allocated, n_entries; }; -struct pa_dynarray* pa_dynarray_new(void) { - struct pa_dynarray *a; - a = pa_xmalloc(sizeof(struct pa_dynarray)); +pa_dynarray* pa_dynarray_new(void) { + pa_dynarray *a; + a = pa_xnew(pa_dynarray, 1); a->data = NULL; a->n_entries = 0; a->n_allocated = 0; return a; } -void pa_dynarray_free(struct pa_dynarray* a, void (*func)(void *p, void *userdata), void *userdata) { +void pa_dynarray_free(pa_dynarray* a, void (*func)(void *p, void *userdata), void *userdata) { unsigned i; assert(a); @@ -60,7 +60,7 @@ void pa_dynarray_free(struct pa_dynarray* a, void (*func)(void *p, void *userdat pa_xfree(a); } -void pa_dynarray_put(struct pa_dynarray*a, unsigned i, void *p) { +void pa_dynarray_put(pa_dynarray*a, unsigned i, void *p) { assert(a); if (i >= a->n_allocated) { @@ -81,13 +81,13 @@ void pa_dynarray_put(struct pa_dynarray*a, unsigned i, void *p) { a->n_entries = i+1; } -unsigned pa_dynarray_append(struct pa_dynarray*a, void *p) { +unsigned pa_dynarray_append(pa_dynarray*a, void *p) { unsigned i = a->n_entries; pa_dynarray_put(a, i, p); return i; } -void *pa_dynarray_get(struct pa_dynarray*a, unsigned i) { +void *pa_dynarray_get(pa_dynarray*a, unsigned i) { assert(a); if (i >= a->n_allocated) return NULL; @@ -96,7 +96,7 @@ void *pa_dynarray_get(struct pa_dynarray*a, unsigned i) { return a->data[i]; } -unsigned pa_dynarray_ncontents(struct pa_dynarray*a) { +unsigned pa_dynarray_size(pa_dynarray*a) { assert(a); return a->n_entries; } diff --git a/polyp/dynarray.h b/polyp/dynarray.h index 6733e9587..9b1601bab 100644 --- a/polyp/dynarray.h +++ b/polyp/dynarray.h @@ -22,28 +22,28 @@ USA. ***/ -struct pa_dynarray; +typedef struct pa_dynarray pa_dynarray; /* Implementation of a simple dynamically sized array. The array * expands if required, but doesn't shrink if possible. Memory * management of the array's entries is the user's job. */ -struct pa_dynarray* pa_dynarray_new(void); +pa_dynarray* pa_dynarray_new(void); /* Free the array calling the specified function for every entry in * the array. The function may be NULL. */ -void pa_dynarray_free(struct pa_dynarray* a, void (*func)(void *p, void *userdata), void *userdata); +void pa_dynarray_free(pa_dynarray* a, void (*func)(void *p, void *userdata), void *userdata); /* Store p at position i in the array */ -void pa_dynarray_put(struct pa_dynarray*a, unsigned i, void *p); +void pa_dynarray_put(pa_dynarray*a, unsigned i, void *p); /* Store p a the first free position in the array. Returns the index * of that entry. If entries are removed from the array their position * are not filled any more by this function. */ -unsigned pa_dynarray_append(struct pa_dynarray*a, void *p); +unsigned pa_dynarray_append(pa_dynarray*a, void *p); -void *pa_dynarray_get(struct pa_dynarray*a, unsigned i); +void *pa_dynarray_get(pa_dynarray*a, unsigned i); -unsigned pa_dynarray_ncontents(struct pa_dynarray*a); +unsigned pa_dynarray_size(pa_dynarray*a); #endif diff --git a/polyp/gcc-printf.h b/polyp/gccmacro.h similarity index 60% rename from polyp/gcc-printf.h rename to polyp/gccmacro.h index 70679df93..9e212f2e2 100644 --- a/polyp/gcc-printf.h +++ b/polyp/gccmacro.h @@ -1,5 +1,5 @@ -#ifndef foogccprintfhfoo -#define foogccprintfhfoo +#ifndef foogccmacrohfoo +#define foogccmacrohfoo /* $Id$ */ @@ -22,12 +22,32 @@ USA. ***/ -/* If we're in GNU C, use some magic for detecting invalid format strings */ - #ifdef __GNUC__ #define PA_GCC_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b))) #else +/** If we're in GNU C, use some magic for detecting invalid format strings */ #define PA_GCC_PRINTF_ATTR(a,b) #endif +#if defined(__GNUC__) && (__GNUC__ >= 4) +#define PA_GCC_SENTINEL __attribute__ ((sentinel)) +#else +/** Macro for usage of GCC's sentinel compilation warnings */ +#define PA_GCC_SENTINEL +#endif + +#ifdef __GNUC__ +#define PA_GCC_NORETURN __attribute__((noreturn)) +#else +/** Macro for no-return functions */ +#define PA_GCC_NORETURN +#endif + +#ifdef __GNUC__ +#define PA_GCC_UNUSED __attribute__ ((unused)) +#else +/** Macro for not used parameter */ +#define PA_GCC_UNUSED +#endif + #endif diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c index 0f96a594e..6552da15c 100644 --- a/polyp/glib-mainloop.c +++ b/polyp/glib-mainloop.c @@ -28,62 +28,64 @@ #include "glib-mainloop.h" #include "idxset.h" #include "xmalloc.h" +#include "glib.h" +#include "util.h" -struct pa_io_event { - struct pa_glib_mainloop *mainloop; +struct pa_io_event { + pa_glib_mainloop *mainloop; int dead; GIOChannel *io_channel; GSource *source; GIOCondition io_condition; int fd; - void (*callback) (struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata); + void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata); void *userdata; - void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_io_event*e, void *userdata); - struct pa_io_event *next, *prev; + void (*destroy_callback) (pa_mainloop_api *m, pa_io_event*e, void *userdata); + pa_io_event *next, *prev; }; struct pa_time_event { - struct pa_glib_mainloop *mainloop; + pa_glib_mainloop *mainloop; int dead; GSource *source; struct timeval timeval; - void (*callback) (struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata); + void (*callback) (pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata); void *userdata; - void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_time_event*e, void *userdata); - struct pa_time_event *next, *prev; + void (*destroy_callback) (pa_mainloop_api *m, pa_time_event*e, void *userdata); + pa_time_event *next, *prev; }; struct pa_defer_event { - struct pa_glib_mainloop *mainloop; + pa_glib_mainloop *mainloop; int dead; GSource *source; - void (*callback) (struct pa_mainloop_api*m, struct pa_defer_event *e, void *userdata); + void (*callback) (pa_mainloop_api*m, pa_defer_event *e, void *userdata); void *userdata; - void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata); - struct pa_defer_event *next, *prev; + void (*destroy_callback) (pa_mainloop_api *m, pa_defer_event*e, void *userdata); + pa_defer_event *next, *prev; }; struct pa_glib_mainloop { GMainContext *glib_main_context; - struct pa_mainloop_api api; + pa_mainloop_api api; GSource *cleanup_source; - struct pa_io_event *io_events, *dead_io_events; - struct pa_time_event *time_events, *dead_time_events; - struct pa_defer_event *defer_events, *dead_defer_events; + pa_io_event *io_events, *dead_io_events; + pa_time_event *time_events, *dead_time_events; + pa_defer_event *defer_events, *dead_defer_events; }; -static void schedule_free_dead_events(struct pa_glib_mainloop *g); +static void schedule_free_dead_events(pa_glib_mainloop *g); -static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f); +static void glib_io_enable(pa_io_event*e, pa_io_event_flags f); -static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa_io_event_flags f, void (*callback) (struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata), void *userdata) { - struct pa_io_event *e; - struct pa_glib_mainloop *g; +static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags f, void *userdata), void *userdata) { + pa_io_event *e; + pa_glib_mainloop *g; assert(m && m->userdata && fd >= 0 && callback); g = m->userdata; - e = pa_xmalloc(sizeof(struct pa_io_event)); + e = pa_xmalloc(sizeof(pa_io_event)); e->mainloop = m->userdata; e->dead = 0; e->fd = fd; @@ -108,8 +110,8 @@ static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa /* The callback GLIB calls whenever an IO condition is met */ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) { - struct pa_io_event *e = data; - enum pa_io_event_flags f; + pa_io_event *e = data; + pa_io_event_flags f; assert(source && e && e->io_channel == source); f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) | @@ -121,7 +123,7 @@ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) return TRUE; } -static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f) { +static void glib_io_enable(pa_io_event*e, pa_io_event_flags f) { GIOCondition c; assert(e && !e->dead); @@ -145,7 +147,7 @@ static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f) { e->io_condition = c; } -static void glib_io_free(struct pa_io_event*e) { +static void glib_io_free(pa_io_event*e) { assert(e && !e->dead); if (e->source) { @@ -172,23 +174,23 @@ static void glib_io_free(struct pa_io_event*e) { schedule_free_dead_events(e->mainloop); } -static void glib_io_set_destroy(struct pa_io_event*e, void (*callback)(struct pa_mainloop_api*m, struct pa_io_event *e, void *userdata)) { +static void glib_io_set_destroy(pa_io_event*e, void (*callback)(pa_mainloop_api*m, pa_io_event *e, void *userdata)) { assert(e); e->destroy_callback = callback; } /* Time sources */ -static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv); +static void glib_time_restart(pa_time_event*e, const struct timeval *tv); -static struct pa_time_event* glib_time_new(struct pa_mainloop_api*m, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*m, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { - struct pa_glib_mainloop *g; - struct pa_time_event *e; +static pa_time_event* glib_time_new(pa_mainloop_api*m, const struct timeval *tv, void (*callback) (pa_mainloop_api*m, pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { + pa_glib_mainloop *g; + pa_time_event *e; assert(m && m->userdata && tv && callback); g = m->userdata; - e = pa_xmalloc(sizeof(struct pa_time_event)); + e = pa_xmalloc(sizeof(pa_time_event)); e->mainloop = g; e->dead = 0; e->callback = callback; @@ -227,7 +229,7 @@ static guint msec_diff(const struct timeval *a, const struct timeval *b) { } static gboolean time_cb(gpointer data) { - struct pa_time_event* e = data; + pa_time_event* e = data; assert(e && e->mainloop && e->source); g_source_unref(e->source); @@ -237,7 +239,7 @@ static gboolean time_cb(gpointer data) { return FALSE; } -static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) { +static void glib_time_restart(pa_time_event*e, const struct timeval *tv) { struct timeval now; assert(e && e->mainloop && !e->dead); @@ -258,7 +260,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) e->source = NULL; } -static void glib_time_free(struct pa_time_event *e) { +static void glib_time_free(pa_time_event *e) { assert(e && e->mainloop && !e->dead); if (e->source) { @@ -285,23 +287,23 @@ static void glib_time_free(struct pa_time_event *e) { schedule_free_dead_events(e->mainloop); } -static void glib_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*m, struct pa_time_event*e, void *userdata)) { +static void glib_time_set_destroy(pa_time_event *e, void (*callback)(pa_mainloop_api*m, pa_time_event*e, void *userdata)) { assert(e); e->destroy_callback = callback; } /* Deferred sources */ -static void glib_defer_enable(struct pa_defer_event *e, int b); +static void glib_defer_enable(pa_defer_event *e, int b); -static struct pa_defer_event* glib_defer_new(struct pa_mainloop_api*m, void (*callback) (struct pa_mainloop_api*m, struct pa_defer_event *e, void *userdata), void *userdata) { - struct pa_defer_event *e; - struct pa_glib_mainloop *g; +static pa_defer_event* glib_defer_new(pa_mainloop_api*m, void (*callback) (pa_mainloop_api*m, pa_defer_event *e, void *userdata), void *userdata) { + pa_defer_event *e; + pa_glib_mainloop *g; assert(m && m->userdata && callback); g = m->userdata; - e = pa_xmalloc(sizeof(struct pa_defer_event)); + e = pa_xmalloc(sizeof(pa_defer_event)); e->mainloop = g; e->dead = 0; e->callback = callback; @@ -319,14 +321,14 @@ static struct pa_defer_event* glib_defer_new(struct pa_mainloop_api*m, void (*ca } static gboolean idle_cb(gpointer data) { - struct pa_defer_event* e = data; + pa_defer_event* e = data; assert(e && e->mainloop && e->source); e->callback(&e->mainloop->api, e, e->userdata); return TRUE; } -static void glib_defer_enable(struct pa_defer_event *e, int b) { +static void glib_defer_enable(pa_defer_event *e, int b) { assert(e && e->mainloop); if (e->source && !b) { @@ -342,7 +344,7 @@ static void glib_defer_enable(struct pa_defer_event *e, int b) { } } -static void glib_defer_free(struct pa_defer_event *e) { +static void glib_defer_free(pa_defer_event *e) { assert(e && e->mainloop && !e->dead); if (e->source) { @@ -369,22 +371,22 @@ static void glib_defer_free(struct pa_defer_event *e) { schedule_free_dead_events(e->mainloop); } -static void glib_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata)) { +static void glib_defer_set_destroy(pa_defer_event *e, void (*callback)(pa_mainloop_api *m, pa_defer_event *e, void *userdata)) { assert(e); e->destroy_callback = callback; } /* quit() */ -static void glib_quit(struct pa_mainloop_api*a, int retval) { - struct pa_glib_mainloop *g; +static void glib_quit(pa_mainloop_api*a, PA_GCC_UNUSED int retval) { + pa_glib_mainloop *g; assert(a && a->userdata); g = a->userdata; /* NOOP */ } -static const struct pa_mainloop_api vtable = { +static const pa_mainloop_api vtable = { .userdata = NULL, .io_new = glib_io_new, @@ -405,10 +407,10 @@ static const struct pa_mainloop_api vtable = { .quit = glib_quit, }; -struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { - struct pa_glib_mainloop *g; +pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { + pa_glib_mainloop *g; - g = pa_xmalloc(sizeof(struct pa_glib_mainloop)); + g = pa_xmalloc(sizeof(pa_glib_mainloop)); if (c) { g->glib_main_context = c; g_main_context_ref(c); @@ -426,9 +428,9 @@ struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { return g; } -static void free_io_events(struct pa_io_event *e) { +static void free_io_events(pa_io_event *e) { while (e) { - struct pa_io_event *r = e; + pa_io_event *r = e; e = r->next; if (r->source) { @@ -446,9 +448,9 @@ static void free_io_events(struct pa_io_event *e) { } } -static void free_time_events(struct pa_time_event *e) { +static void free_time_events(pa_time_event *e) { while (e) { - struct pa_time_event *r = e; + pa_time_event *r = e; e = r->next; if (r->source) { @@ -463,9 +465,9 @@ static void free_time_events(struct pa_time_event *e) { } } -static void free_defer_events(struct pa_defer_event *e) { +static void free_defer_events(pa_defer_event *e) { while (e) { - struct pa_defer_event *r = e; + pa_defer_event *r = e; e = r->next; if (r->source) { @@ -480,7 +482,7 @@ static void free_defer_events(struct pa_defer_event *e) { } } -void pa_glib_mainloop_free(struct pa_glib_mainloop* g) { +void pa_glib_mainloop_free(pa_glib_mainloop* g) { assert(g); free_io_events(g->io_events); @@ -499,13 +501,13 @@ void pa_glib_mainloop_free(struct pa_glib_mainloop* g) { pa_xfree(g); } -struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g) { +pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) { assert(g); return &g->api; } static gboolean free_dead_events(gpointer p) { - struct pa_glib_mainloop *g = p; + pa_glib_mainloop *g = p; assert(g); free_io_events(g->dead_io_events); @@ -523,7 +525,7 @@ static gboolean free_dead_events(gpointer p) { return FALSE; } -static void schedule_free_dead_events(struct pa_glib_mainloop *g) { +static void schedule_free_dead_events(pa_glib_mainloop *g) { assert(g && g->glib_main_context); if (g->cleanup_source) diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h index d830561f2..d3e985970 100644 --- a/polyp/glib-mainloop.h +++ b/polyp/glib-mainloop.h @@ -32,23 +32,23 @@ PA_C_DECL_BEGIN -/** \struct pa_glib_mainloop +/** \pa_glib_mainloop * An opaque GLIB main loop object */ -struct pa_glib_mainloop; +typedef struct pa_glib_mainloop pa_glib_mainloop; /** Create a new GLIB main loop object for the specified GLIB main loop context. If c is NULL the default context is used. */ #if GLIB_MAJOR_VERSION >= 2 -struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c); +pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c); #else -struct pa_glib_mainloop *pa_glib_mainloop_new(void); +pa_glib_mainloop *pa_glib_mainloop_new(void); #endif /** Free the GLIB main loop object */ -void pa_glib_mainloop_free(struct pa_glib_mainloop* g); +void pa_glib_mainloop_free(pa_glib_mainloop* g); /** Return the abstract main loop API vtable for the GLIB main loop object */ -struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g); +pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g); PA_C_DECL_END diff --git a/polyp/glib12-mainloop.c b/polyp/glib12-mainloop.c index c328471ca..e322ac075 100644 --- a/polyp/glib12-mainloop.c +++ b/polyp/glib12-mainloop.c @@ -28,63 +28,64 @@ #include "glib-mainloop.h" #include "idxset.h" #include "xmalloc.h" +#include "util.h" /* A mainloop implementation based on GLIB 1.2 */ struct pa_io_event { - struct pa_glib_mainloop *mainloop; + pa_glib_mainloop *mainloop; int dead; GIOChannel *io_channel; guint source; GIOCondition io_condition; int fd; - void (*callback) (struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata); + void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata); void *userdata; - void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_io_event*e, void *userdata); - struct pa_io_event *next, *prev; + void (*destroy_callback) (pa_mainloop_api *m, pa_io_event*e, void *userdata); + pa_io_event *next, *prev; }; struct pa_time_event { - struct pa_glib_mainloop *mainloop; + pa_glib_mainloop *mainloop; int dead; guint source; struct timeval timeval; - void (*callback) (struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata); + void (*callback) (pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata); void *userdata; - void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_time_event*e, void *userdata); - struct pa_time_event *next, *prev; + void (*destroy_callback) (pa_mainloop_api *m, pa_time_event*e, void *userdata); + pa_time_event *next, *prev; }; struct pa_defer_event { - struct pa_glib_mainloop *mainloop; + pa_glib_mainloop *mainloop; int dead; guint source; - void (*callback) (struct pa_mainloop_api*m, struct pa_defer_event *e, void *userdata); + void (*callback) (pa_mainloop_api*m, pa_defer_event *e, void *userdata); void *userdata; - void (*destroy_callback) (struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata); - struct pa_defer_event *next, *prev; + void (*destroy_callback) (pa_mainloop_api *m, pa_defer_event*e, void *userdata); + pa_defer_event *next, *prev; }; struct pa_glib_mainloop { - struct pa_mainloop_api api; + pa_mainloop_api api; guint cleanup_source; - struct pa_io_event *io_events, *dead_io_events; - struct pa_time_event *time_events, *dead_time_events; - struct pa_defer_event *defer_events, *dead_defer_events; + pa_io_event *io_events, *dead_io_events; + pa_time_event *time_events, *dead_time_events; + pa_defer_event *defer_events, *dead_defer_events; }; -static void schedule_free_dead_events(struct pa_glib_mainloop *g); +static void schedule_free_dead_events(pa_glib_mainloop *g); -static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f); +static void glib_io_enable(pa_io_event*e, pa_io_event_flags f); -static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa_io_event_flags f, void (*callback) (struct pa_mainloop_api*m, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata), void *userdata) { - struct pa_io_event *e; - struct pa_glib_mainloop *g; +static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags f, void *userdata), void *userdata) { + pa_io_event *e; + pa_glib_mainloop *g; assert(m && m->userdata && fd >= 0 && callback); g = m->userdata; - e = pa_xmalloc(sizeof(struct pa_io_event)); + e = pa_xmalloc(sizeof(pa_io_event)); e->mainloop = m->userdata; e->dead = 0; e->fd = fd; @@ -108,8 +109,8 @@ static struct pa_io_event* glib_io_new(struct pa_mainloop_api*m, int fd, enum pa } static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) { - struct pa_io_event *e = data; - enum pa_io_event_flags f; + pa_io_event *e = data; + pa_io_event_flags f; assert(source && e && e->io_channel == source); f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) | @@ -121,7 +122,7 @@ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) return TRUE; } -static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f) { +static void glib_io_enable(pa_io_event*e, pa_io_event_flags f) { GIOCondition c; assert(e && !e->dead); @@ -138,7 +139,7 @@ static void glib_io_enable(struct pa_io_event*e, enum pa_io_event_flags f) { e->io_condition = c; } -static void glib_io_free(struct pa_io_event*e) { +static void glib_io_free(pa_io_event*e) { assert(e && !e->dead); if (e->source != (guint) -1) { @@ -164,23 +165,23 @@ static void glib_io_free(struct pa_io_event*e) { schedule_free_dead_events(e->mainloop); } -static void glib_io_set_destroy(struct pa_io_event*e, void (*callback)(struct pa_mainloop_api*m, struct pa_io_event *e, void *userdata)) { +static void glib_io_set_destroy(pa_io_event*e, void (*callback)(pa_mainloop_api*m, pa_io_event *e, void *userdata)) { assert(e); e->destroy_callback = callback; } /* Time sources */ -static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv); +static void glib_time_restart(pa_time_event*e, const struct timeval *tv); -static struct pa_time_event* glib_time_new(struct pa_mainloop_api*m, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*m, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { - struct pa_glib_mainloop *g; - struct pa_time_event *e; +static pa_time_event* glib_time_new(pa_mainloop_api*m, const struct timeval *tv, void (*callback) (pa_mainloop_api*m, pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { + pa_glib_mainloop *g; + pa_time_event *e; assert(m && m->userdata && tv && callback); g = m->userdata; - e = pa_xmalloc(sizeof(struct pa_time_event)); + e = pa_xmalloc(sizeof(pa_time_event)); e->mainloop = g; e->dead = 0; e->callback = callback; @@ -219,7 +220,7 @@ static guint msec_diff(const struct timeval *a, const struct timeval *b) { } static gboolean time_cb(gpointer data) { - struct pa_time_event* e = data; + pa_time_event* e = data; assert(e && e->mainloop && e->source != (guint) -1); g_source_remove(e->source); @@ -229,7 +230,7 @@ static gboolean time_cb(gpointer data) { return FALSE; } -static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) { +static void glib_time_restart(pa_time_event*e, const struct timeval *tv) { struct timeval now; assert(e && e->mainloop && !e->dead); @@ -245,7 +246,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv) e->source = (guint) -1; } -static void glib_time_free(struct pa_time_event *e) { +static void glib_time_free(pa_time_event *e) { assert(e && e->mainloop && !e->dead); if (e->source != (guint) -1) { @@ -271,23 +272,23 @@ static void glib_time_free(struct pa_time_event *e) { schedule_free_dead_events(e->mainloop); } -static void glib_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*m, struct pa_time_event*e, void *userdata)) { +static void glib_time_set_destroy(pa_time_event *e, void (*callback)(pa_mainloop_api*m, pa_time_event*e, void *userdata)) { assert(e); e->destroy_callback = callback; } /* Deferred sources */ -static void glib_defer_enable(struct pa_defer_event *e, int b); +static void glib_defer_enable(pa_defer_event *e, int b); -static struct pa_defer_event* glib_defer_new(struct pa_mainloop_api*m, void (*callback) (struct pa_mainloop_api*m, struct pa_defer_event *e, void *userdata), void *userdata) { - struct pa_defer_event *e; - struct pa_glib_mainloop *g; +static pa_defer_event* glib_defer_new(pa_mainloop_api*m, void (*callback) (pa_mainloop_api*m, pa_defer_event *e, void *userdata), void *userdata) { + pa_defer_event *e; + pa_glib_mainloop *g; assert(m && m->userdata && callback); g = m->userdata; - e = pa_xmalloc(sizeof(struct pa_defer_event)); + e = pa_xmalloc(sizeof(pa_defer_event)); e->mainloop = g; e->dead = 0; e->callback = callback; @@ -305,14 +306,14 @@ static struct pa_defer_event* glib_defer_new(struct pa_mainloop_api*m, void (*ca } static gboolean idle_cb(gpointer data) { - struct pa_defer_event* e = data; + pa_defer_event* e = data; assert(e && e->mainloop && e->source != (guint) -1); e->callback(&e->mainloop->api, e, e->userdata); return TRUE; } -static void glib_defer_enable(struct pa_defer_event *e, int b) { +static void glib_defer_enable(pa_defer_event *e, int b) { assert(e && e->mainloop); if (e->source != (guint) -1 && !b) { @@ -324,7 +325,7 @@ static void glib_defer_enable(struct pa_defer_event *e, int b) { } } -static void glib_defer_free(struct pa_defer_event *e) { +static void glib_defer_free(pa_defer_event *e) { assert(e && e->mainloop && !e->dead); if (e->source != (guint) -1) { @@ -350,22 +351,22 @@ static void glib_defer_free(struct pa_defer_event *e) { schedule_free_dead_events(e->mainloop); } -static void glib_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata)) { +static void glib_defer_set_destroy(pa_defer_event *e, void (*callback)(pa_mainloop_api *m, pa_defer_event *e, void *userdata)) { assert(e); e->destroy_callback = callback; } /* quit() */ -static void glib_quit(struct pa_mainloop_api*a, int retval) { - struct pa_glib_mainloop *g; +static void glib_quit(pa_mainloop_api*a, PA_GCC_UNUSED int retval) { + pa_glib_mainloop *g; assert(a && a->userdata); g = a->userdata; /* NOOP */ } -static const struct pa_mainloop_api vtable = { +static const pa_mainloop_api vtable = { .userdata = NULL, .io_new = glib_io_new, @@ -386,10 +387,10 @@ static const struct pa_mainloop_api vtable = { .quit = glib_quit, }; -struct pa_glib_mainloop *pa_glib_mainloop_new(void) { - struct pa_glib_mainloop *g; +pa_glib_mainloop *pa_glib_mainloop_new(void) { + pa_glib_mainloop *g; - g = pa_xmalloc(sizeof(struct pa_glib_mainloop)); + g = pa_xmalloc(sizeof(pa_glib_mainloop)); g->api = vtable; g->api.userdata = g; @@ -402,9 +403,9 @@ struct pa_glib_mainloop *pa_glib_mainloop_new(void) { return g; } -static void free_io_events(struct pa_io_event *e) { +static void free_io_events(pa_io_event *e) { while (e) { - struct pa_io_event *r = e; + pa_io_event *r = e; e = r->next; if (r->source != (guint) -1) @@ -420,9 +421,9 @@ static void free_io_events(struct pa_io_event *e) { } } -static void free_time_events(struct pa_time_event *e) { +static void free_time_events(pa_time_event *e) { while (e) { - struct pa_time_event *r = e; + pa_time_event *r = e; e = r->next; if (r->source != (guint) -1) @@ -435,9 +436,9 @@ static void free_time_events(struct pa_time_event *e) { } } -static void free_defer_events(struct pa_defer_event *e) { +static void free_defer_events(pa_defer_event *e) { while (e) { - struct pa_defer_event *r = e; + pa_defer_event *r = e; e = r->next; if (r->source != (guint) -1) @@ -450,7 +451,7 @@ static void free_defer_events(struct pa_defer_event *e) { } } -void pa_glib_mainloop_free(struct pa_glib_mainloop* g) { +void pa_glib_mainloop_free(pa_glib_mainloop* g) { assert(g); free_io_events(g->io_events); @@ -466,13 +467,13 @@ void pa_glib_mainloop_free(struct pa_glib_mainloop* g) { pa_xfree(g); } -struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g) { +pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) { assert(g); return &g->api; } static gboolean free_dead_events(gpointer p) { - struct pa_glib_mainloop *g = p; + pa_glib_mainloop *g = p; assert(g); free_io_events(g->dead_io_events); @@ -489,7 +490,7 @@ static gboolean free_dead_events(gpointer p) { return FALSE; } -static void schedule_free_dead_events(struct pa_glib_mainloop *g) { +static void schedule_free_dead_events(pa_glib_mainloop *g) { assert(g); if (g->cleanup_source != (guint) -1) diff --git a/polyp/hashmap.c b/polyp/hashmap.c index 3b1265c95..a37decb8c 100644 --- a/polyp/hashmap.c +++ b/polyp/hashmap.c @@ -51,9 +51,9 @@ struct pa_hashmap { int (*compare_func) (const void*a, const void*b); }; -struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { - struct pa_hashmap *h; - h = pa_xmalloc(sizeof(struct pa_hashmap)); +pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { + pa_hashmap *h; + h = pa_xmalloc(sizeof(pa_hashmap)); h->data = pa_xmalloc0(sizeof(struct hashmap_entry*)*(h->size = BUCKETS)); h->first_entry = NULL; h->n_entries = 0; @@ -62,7 +62,7 @@ struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*c return h; } -static void remove(struct pa_hashmap *h, struct hashmap_entry *e) { +static void remove(pa_hashmap *h, struct hashmap_entry *e) { assert(e); if (e->next) @@ -85,7 +85,7 @@ static void remove(struct pa_hashmap *h, struct hashmap_entry *e) { h->n_entries--; } -void pa_hashmap_free(struct pa_hashmap*h, void (*free_func)(void *p, void *userdata), void *userdata) { +void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), void *userdata) { assert(h); while (h->first_entry) { @@ -98,7 +98,7 @@ void pa_hashmap_free(struct pa_hashmap*h, void (*free_func)(void *p, void *userd pa_xfree(h); } -static struct hashmap_entry *get(struct pa_hashmap *h, unsigned hash, const void *key) { +static struct hashmap_entry *get(pa_hashmap *h, unsigned hash, const void *key) { struct hashmap_entry *e; assert(h && hash < h->size); @@ -109,7 +109,7 @@ static struct hashmap_entry *get(struct pa_hashmap *h, unsigned hash, const void return NULL; } -int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value) { +int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) { struct hashmap_entry *e; unsigned hash; assert(h); @@ -140,7 +140,7 @@ int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value) { return 0; } -void* pa_hashmap_get(struct pa_hashmap *h, const void *key) { +void* pa_hashmap_get(pa_hashmap *h, const void *key) { unsigned hash; struct hashmap_entry *e; assert(h && key); @@ -153,7 +153,7 @@ void* pa_hashmap_get(struct pa_hashmap *h, const void *key) { return e->value; } -void* pa_hashmap_remove(struct pa_hashmap *h, const void *key) { +void* pa_hashmap_remove(pa_hashmap *h, const void *key) { struct hashmap_entry *e; unsigned hash; void *data; @@ -169,11 +169,11 @@ void* pa_hashmap_remove(struct pa_hashmap *h, const void *key) { return data; } -unsigned pa_hashmap_ncontents(struct pa_hashmap *h) { +unsigned pa_hashmap_size(pa_hashmap *h) { return h->n_entries; } -void *pa_hashmap_iterate(struct pa_hashmap *h, void **state, const void **key) { +void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) { assert(h && state); if (!*state) diff --git a/polyp/hashmap.h b/polyp/hashmap.h index d55834c1a..14f827059 100644 --- a/polyp/hashmap.h +++ b/polyp/hashmap.h @@ -26,28 +26,28 @@ * user's job. It's a good idea to have the key pointer point to a * string in the value data. */ -struct pa_hashmap; +typedef struct pa_hashmap pa_hashmap; /* Create a new hashmap. Use the specified functions for hashing and comparing objects in the map */ -struct pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); +pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); /* Free the hash table. Calls the specified function for every value in the table. The function may be NULL */ -void pa_hashmap_free(struct pa_hashmap*, void (*free_func)(void *p, void *userdata), void *userdata); +void pa_hashmap_free(pa_hashmap*, void (*free_func)(void *p, void *userdata), void *userdata); /* Returns non-zero when the entry already exists */ -int pa_hashmap_put(struct pa_hashmap *h, const void *key, void *value); -void* pa_hashmap_get(struct pa_hashmap *h, const void *key); +int pa_hashmap_put(pa_hashmap *h, const void *key, void *value); +void* pa_hashmap_get(pa_hashmap *h, const void *key); /* Returns the data of the entry while removing */ -void* pa_hashmap_remove(struct pa_hashmap *h, const void *key); +void* pa_hashmap_remove(pa_hashmap *h, const void *key); -unsigned pa_hashmap_ncontents(struct pa_hashmap *h); +unsigned pa_hashmap_size(pa_hashmap *h); /* May be used to iterate through the hashmap. Initially the opaque pointer *state has to be set to NULL. The hashmap may not be modified during iteration. The key of the entry is returned in *key, if key is non-NULL. After the last entry in the hashmap NULL is returned. */ -void *pa_hashmap_iterate(struct pa_hashmap *h, void **state, const void**key); +void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void**key); #endif diff --git a/polyp/howl-wrap.c b/polyp/howl-wrap.c index af0509308..77d096ac2 100644 --- a/polyp/howl-wrap.c +++ b/polyp/howl-wrap.c @@ -28,17 +28,17 @@ #define HOWL_PROPERTY "howl" -struct pa_howl_wrapper { - struct pa_core *core; +pa_howl_wrapper { + pa_core *core; int ref; - struct pa_io_event *io_event; + pa_io_event *io_event; sw_discovery discovery; }; -static void howl_io_event(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { - struct pa_howl_wrapper *w = userdata; +static void howl_io_event(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) { + pa_howl_wrapper *w = userdata; assert(m && e && fd >= 0 && w && w->ref >= 1); if (f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) @@ -55,8 +55,8 @@ fail: w->io_event = NULL; } -static struct pa_howl_wrapper* howl_wrapper_new(struct pa_core *c) { - struct pa_howl_wrapper *h; +static pa_howl_wrapper* howl_wrapper_new(pa_core *c) { + pa_howl_wrapper *h; sw_discovery session; assert(c); @@ -65,7 +65,7 @@ static struct pa_howl_wrapper* howl_wrapper_new(struct pa_core *c) { return NULL; } - h = pa_xmalloc(sizeof(struct pa_howl_wrapper)); + h = pa_xmalloc(sizeof(pa_howl_wrapper)); h->core = c; h->ref = 1; h->discovery = session; @@ -75,7 +75,7 @@ static struct pa_howl_wrapper* howl_wrapper_new(struct pa_core *c) { return h; } -static void howl_wrapper_free(struct pa_howl_wrapper *h) { +static void howl_wrapper_free(pa_howl_wrapper *h) { assert(h); sw_discovery_fina(h->discovery); @@ -86,8 +86,8 @@ static void howl_wrapper_free(struct pa_howl_wrapper *h) { pa_xfree(h); } -struct pa_howl_wrapper* pa_howl_wrapper_get(struct pa_core *c) { - struct pa_howl_wrapper *h; +pa_howl_wrapper* pa_howl_wrapper_get(pa_core *c) { + pa_howl_wrapper *h; assert(c); if ((h = pa_property_get(c, HOWL_PROPERTY))) @@ -96,19 +96,19 @@ struct pa_howl_wrapper* pa_howl_wrapper_get(struct pa_core *c) { return howl_wrapper_new(c); } -struct pa_howl_wrapper* pa_howl_wrapper_ref(struct pa_howl_wrapper *h) { +pa_howl_wrapper* pa_howl_wrapper_ref(pa_howl_wrapper *h) { assert(h && h->ref >= 1); h->ref++; return h; } -void pa_howl_wrapper_unref(struct pa_howl_wrapper *h) { +void pa_howl_wrapper_unref(pa_howl_wrapper *h) { assert(h && h->ref >= 1); if (!(--h->ref)) howl_wrapper_free(h); } -sw_discovery pa_howl_wrapper_get_discovery(struct pa_howl_wrapper *h) { +sw_discovery pa_howl_wrapper_get_discovery(pa_howl_wrapper *h) { assert(h && h->ref >= 1); return h->discovery; diff --git a/polyp/howl-wrap.h b/polyp/howl-wrap.h index feb54556d..a670b082b 100644 --- a/polyp/howl-wrap.h +++ b/polyp/howl-wrap.h @@ -26,12 +26,12 @@ #include "core.h" -struct pa_howl_wrapper; +pa_howl_wrapper; -struct pa_howl_wrapper* pa_howl_wrapper_get(struct pa_core *c); -struct pa_howl_wrapper* pa_howl_wrapper_ref(struct pa_howl_wrapper *h); -void pa_howl_wrapper_unref(struct pa_howl_wrapper *h); +pa_howl_wrapper* pa_howl_wrapper_get(pa_core *c); +pa_howl_wrapper* pa_howl_wrapper_ref(pa_howl_wrapper *h); +void pa_howl_wrapper_unref(pa_howl_wrapper *h); -sw_discovery pa_howl_wrapper_get_discovery(struct pa_howl_wrapper *h); +sw_discovery pa_howl_wrapper_get_discovery(pa_howl_wrapper *h); #endif diff --git a/polyp/idxset.c b/polyp/idxset.c index dcc38423e..409d1fab9 100644 --- a/polyp/idxset.c +++ b/polyp/idxset.c @@ -31,21 +31,21 @@ #include "idxset.h" #include "xmalloc.h" -struct idxset_entry { +typedef struct idxset_entry { void *data; uint32_t index; unsigned hash_value; struct idxset_entry *hash_prev, *hash_next; struct idxset_entry* iterate_prev, *iterate_next; -}; +} idxset_entry; struct pa_idxset { unsigned (*hash_func) (const void *p); int (*compare_func)(const void *a, const void *b); unsigned hash_table_size, n_entries; - struct idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail; + idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail; uint32_t index, start_index, array_size; }; @@ -71,14 +71,14 @@ int pa_idxset_trivial_compare_func(const void *a, const void *b) { return a != b; } -struct pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { - struct pa_idxset *s; +pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { + pa_idxset *s; - s = pa_xmalloc(sizeof(struct pa_idxset)); + s = pa_xnew(pa_idxset, 1); s->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; s->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; s->hash_table_size = 1023; - s->hash_table = pa_xmalloc0(sizeof(struct idxset_entry*)*s->hash_table_size); + s->hash_table = pa_xmalloc0(sizeof(idxset_entry*)*s->hash_table_size); s->array = NULL; s->array_size = 0; s->index = 0; @@ -90,11 +90,11 @@ struct pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*com return s; } -void pa_idxset_free(struct pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata) { +void pa_idxset_free(pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata) { assert(s); while (s->iterate_list_head) { - struct idxset_entry *e = s->iterate_list_head; + idxset_entry *e = s->iterate_list_head; s->iterate_list_head = s->iterate_list_head->iterate_next; if (free_func) @@ -107,7 +107,7 @@ void pa_idxset_free(struct pa_idxset *s, void (*free_func) (void *p, void *userd pa_xfree(s); } -static struct idxset_entry* hash_scan(struct pa_idxset *s, struct idxset_entry* e, const void *p) { +static idxset_entry* hash_scan(pa_idxset *s, idxset_entry* e, const void *p) { assert(p); assert(s->compare_func); @@ -118,20 +118,20 @@ static struct idxset_entry* hash_scan(struct pa_idxset *s, struct idxset_entry* return NULL; } -static void extend_array(struct pa_idxset *s, uint32_t index) { +static void extend_array(pa_idxset *s, uint32_t idx) { uint32_t i, j, l; - struct idxset_entry** n; - assert(index >= s->start_index); + idxset_entry** n; + assert(idx >= s->start_index); - if (index < s->start_index + s->array_size) + if (idx < s->start_index + s->array_size) return; for (i = 0; i < s->array_size; i++) if (s->array[i]) break; - l = index - s->start_index - i + 100; - n = pa_xmalloc0(sizeof(struct hash_table_entry*)*l); + l = idx - s->start_index - i + 100; + n = pa_xnew0(idxset_entry*, l); for (j = 0; j < s->array_size-i; j++) n[j] = s->array[i+j]; @@ -143,19 +143,19 @@ static void extend_array(struct pa_idxset *s, uint32_t index) { s->start_index += i; } -static struct idxset_entry** array_index(struct pa_idxset*s, uint32_t index) { - if (index >= s->start_index + s->array_size) +static idxset_entry** array_index(pa_idxset*s, uint32_t idx) { + if (idx >= s->start_index + s->array_size) return NULL; - if (index < s->start_index) + if (idx < s->start_index) return NULL; - return s->array + (index - s->start_index); + return s->array + (idx - s->start_index); } -int pa_idxset_put(struct pa_idxset*s, void *p, uint32_t *index) { +int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { unsigned h; - struct idxset_entry *e, **a; + idxset_entry *e, **a; assert(s && p); assert(s->hash_func); @@ -163,13 +163,13 @@ int pa_idxset_put(struct pa_idxset*s, void *p, uint32_t *index) { assert(s->hash_table); if ((e = hash_scan(s, s->hash_table[h], p))) { - if (index) - *index = e->index; + if (idx) + *idx = e->index; return -1; } - e = pa_xmalloc(sizeof(struct idxset_entry)); + e = pa_xmalloc(sizeof(idxset_entry)); e->data = p; e->index = s->index++; e->hash_value = h; @@ -202,17 +202,17 @@ int pa_idxset_put(struct pa_idxset*s, void *p, uint32_t *index) { s->n_entries++; assert(s->n_entries >= 1); - if (index) - *index = e->index; + if (idx) + *idx = e->index; return 0; } -void* pa_idxset_get_by_index(struct pa_idxset*s, uint32_t index) { - struct idxset_entry **a; +void* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx) { + idxset_entry **a; assert(s); - if (!(a = array_index(s, index))) + if (!(a = array_index(s, idx))) return NULL; if (!*a) @@ -221,9 +221,9 @@ void* pa_idxset_get_by_index(struct pa_idxset*s, uint32_t index) { return (*a)->data; } -void* pa_idxset_get_by_data(struct pa_idxset*s, const void *p, uint32_t *index) { +void* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx) { unsigned h; - struct idxset_entry *e; + idxset_entry *e; assert(s && p); assert(s->hash_func); @@ -233,14 +233,14 @@ void* pa_idxset_get_by_data(struct pa_idxset*s, const void *p, uint32_t *index) if (!(e = hash_scan(s, s->hash_table[h], p))) return NULL; - if (index) - *index = e->index; + if (idx) + *idx = e->index; return e->data; } -static void remove_entry(struct pa_idxset *s, struct idxset_entry *e) { - struct idxset_entry **a; +static void remove_entry(pa_idxset *s, idxset_entry *e) { + idxset_entry **a; assert(s && e); /* Remove from array */ @@ -274,13 +274,13 @@ static void remove_entry(struct pa_idxset *s, struct idxset_entry *e) { s->n_entries--; } -void* pa_idxset_remove_by_index(struct pa_idxset*s, uint32_t index) { - struct idxset_entry **a; +void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) { + idxset_entry **a; void *data; assert(s); - if (!(a = array_index(s, index))) + if (!(a = array_index(s, idx))) return NULL; data = (*a)->data; @@ -289,8 +289,8 @@ void* pa_idxset_remove_by_index(struct pa_idxset*s, uint32_t index) { return data; } -void* pa_idxset_remove_by_data(struct pa_idxset*s, const void *data, uint32_t *index) { - struct idxset_entry *e; +void* pa_idxset_remove_by_data(pa_idxset*s, const void *data, uint32_t *idx) { + idxset_entry *e; unsigned h; void *r; @@ -302,19 +302,19 @@ void* pa_idxset_remove_by_data(struct pa_idxset*s, const void *data, uint32_t *i return NULL; r = e->data; - if (index) - *index = e->index; + if (idx) + *idx = e->index; remove_entry(s, e); return r; } -void* pa_idxset_rrobin(struct pa_idxset *s, uint32_t *index) { - struct idxset_entry **a, *e = NULL; - assert(s && index); +void* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx) { + idxset_entry **a, *e = NULL; + assert(s && idx); - if ((a = array_index(s, *index)) && *a) + if ((a = array_index(s, *idx)) && *a) e = (*a)->iterate_next; if (!e) @@ -323,46 +323,46 @@ void* pa_idxset_rrobin(struct pa_idxset *s, uint32_t *index) { if (!e) return NULL; - *index = e->index; + *idx = e->index; return e->data; } -void* pa_idxset_first(struct pa_idxset *s, uint32_t *index) { +void* pa_idxset_first(pa_idxset *s, uint32_t *idx) { assert(s); if (!s->iterate_list_head) return NULL; - if (index) - *index = s->iterate_list_head->index; + if (idx) + *idx = s->iterate_list_head->index; return s->iterate_list_head->data; } -void *pa_idxset_next(struct pa_idxset *s, uint32_t *index) { - struct idxset_entry **a, *e = NULL; - assert(s && index); +void *pa_idxset_next(pa_idxset *s, uint32_t *idx) { + idxset_entry **a, *e = NULL; + assert(s && idx); - if ((a = array_index(s, *index)) && *a) + if ((a = array_index(s, *idx)) && *a) e = (*a)->iterate_next; if (e) { - *index = e->index; + *idx = e->index; return e->data; } else { - *index = PA_IDXSET_INVALID; + *idx = PA_IDXSET_INVALID; return NULL; } } -int pa_idxset_foreach(struct pa_idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata) { - struct idxset_entry *e; +int pa_idxset_foreach(pa_idxset*s, int (*func)(void *p, uint32_t idx, int *del, void*userdata), void *userdata) { + idxset_entry *e; assert(s && func); e = s->iterate_list_head; while (e) { int del = 0, r; - struct idxset_entry *n = e->iterate_next; + idxset_entry *n = e->iterate_next; r = func(e->data, e->index, &del, userdata); @@ -378,12 +378,12 @@ int pa_idxset_foreach(struct pa_idxset*s, int (*func)(void *p, uint32_t index, i return 0; } -unsigned pa_idxset_ncontents(struct pa_idxset*s) { +unsigned pa_idxset_size(pa_idxset*s) { assert(s); return s->n_entries; } -int pa_idxset_isempty(struct pa_idxset *s) { +int pa_idxset_isempty(pa_idxset *s) { assert(s); return s->n_entries == 0; } diff --git a/polyp/idxset.h b/polyp/idxset.h index 4c89eea19..17ae16cba 100644 --- a/polyp/idxset.h +++ b/polyp/idxset.h @@ -41,53 +41,54 @@ int pa_idxset_trivial_compare_func(const void *a, const void *b); unsigned pa_idxset_string_hash_func(const void *p); int pa_idxset_string_compare_func(const void *a, const void *b); -struct pa_idxset; +typedef struct pa_idxset pa_idxset; /* Instantiate a new idxset with the specified hash and comparison functions */ -struct pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); +pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); /* Free the idxset. When the idxset is not empty the specified function is called for every entry contained */ -void pa_idxset_free(struct pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata); +void pa_idxset_free(pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata); -/* Store a new item in the idxset. The index of the item is returned in *index */ -int pa_idxset_put(struct pa_idxset*s, void *p, uint32_t *index); +/* Store a new item in the idxset. The index of the item is returned in *idx */ +int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx); -/* Get the entry by its index */ -void* pa_idxset_get_by_index(struct pa_idxset*s, uint32_t index); +/* Get the entry by its idx */ +void* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx); -/* Get the entry by its data. The index is returned in *index */ -void* pa_idxset_get_by_data(struct pa_idxset*s, const void *p, uint32_t *index); +/* Get the entry by its data. The idx is returned in *index */ +void* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx); /* Similar to pa_idxset_get_by_index(), but removes the entry from the idxset. */ -void* pa_idxset_remove_by_index(struct pa_idxset*s, uint32_t index); +void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx); /* Similar to pa_idxset_get_by_data(), but removes the entry from the idxset */ -void* pa_idxset_remove_by_data(struct pa_idxset*s, const void *p, uint32_t *index); +void* pa_idxset_remove_by_data(pa_idxset*s, const void *p, uint32_t *idx); /* This may be used to iterate through all entries. When called with an invalid index value it returns the first entry, otherwise the - next following. The function is best called with *index = + next following. The function is best called with *idx = PA_IDXSET_VALID first. It is safe to manipulate the idxset between the calls. It is not guaranteed that all entries have already been returned before the an entry is returned the second time.*/ -void* pa_idxset_rrobin(struct pa_idxset *s, uint32_t *index); +void* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx); -/* Return the oldest entry in the idxset. Fill in its index in *index. */ -void* pa_idxset_first(struct pa_idxset *s, uint32_t *index); +/* Return the oldest entry in the idxset. Fill in its index in *idx. */ +void* pa_idxset_first(pa_idxset *s, uint32_t *idx); -/* Return the entry following the entry indexed by *index. After the +/* Return the entry following the entry indexed by *idx. After the * call *index contains the index of the returned * object. pa_idxset_first() and pa_idxset_next() may be used to * iterate through the set.*/ -void *pa_idxset_next(struct pa_idxset *s, uint32_t *index); +void *pa_idxset_next(pa_idxset *s, uint32_t *idx); /* Call a function for every item in the set. If the callback function returns -1, the loop is terminated. If *del is set to non-zero that specific item is removed. It is not safe to call any other functions on the idxset while pa_idxset_foreach is executed. */ -int pa_idxset_foreach(struct pa_idxset*s, int (*func)(void *p, uint32_t index, int *del, void*userdata), void *userdata); +int pa_idxset_foreach(pa_idxset*s, int (*func)(void *p, uint32_t idx, int *del, void*userdata), void *userdata); -unsigned pa_idxset_ncontents(struct pa_idxset*s); -int pa_idxset_isempty(struct pa_idxset *s); +unsigned pa_idxset_size(pa_idxset*s); + +int pa_idxset_isempty(pa_idxset *s); #endif diff --git a/polyp/iochannel.c b/polyp/iochannel.c index 1a0dbf918..e62713190 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -37,9 +37,9 @@ struct pa_iochannel { int ifd, ofd; - struct pa_mainloop_api* mainloop; + pa_mainloop_api* mainloop; - void (*callback)(struct pa_iochannel*io, void *userdata); + pa_iochannel_callback_t callback; void*userdata; int readable; @@ -48,14 +48,14 @@ struct pa_iochannel { int no_close; - struct pa_io_event* input_event, *output_event; + pa_io_event* input_event, *output_event; }; -static void enable_mainloop_sources(struct pa_iochannel *io) { +static void enable_mainloop_sources(pa_iochannel *io) { assert(io); if (io->input_event == io->output_event && io->input_event) { - enum pa_io_event_flags f = PA_IO_EVENT_NULL; + pa_io_event_flags f = PA_IO_EVENT_NULL; assert(io->input_event); if (!io->readable) @@ -72,10 +72,14 @@ static void enable_mainloop_sources(struct pa_iochannel *io) { } } -static void callback(struct pa_mainloop_api* m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { - struct pa_iochannel *io = userdata; +static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) { + pa_iochannel *io = userdata; int changed = 0; - assert(m && e && fd >= 0 && userdata); + + assert(m); + assert(e); + assert(fd >= 0); + assert(userdata); if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) { io->hungup = 1; @@ -87,9 +91,7 @@ static void callback(struct pa_mainloop_api* m, struct pa_io_event *e, int fd, e if (io->output_event == e) io->output_event = NULL; - } - - if (e == io->output_event) { + } else if (e == io->output_event) { io->mainloop->io_free(io->output_event); io->output_event = NULL; } @@ -116,11 +118,13 @@ static void callback(struct pa_mainloop_api* m, struct pa_io_event *e, int fd, e } } -struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd) { - struct pa_iochannel *io; - assert(m && (ifd >= 0 || ofd >= 0)); +pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) { + pa_iochannel *io; + + assert(m); + assert(ifd >= 0 || ofd >= 0); - io = pa_xmalloc(sizeof(struct pa_iochannel)); + io = pa_xnew(pa_iochannel, 1); io->ifd = ifd; io->ofd = ofd; io->mainloop = m; @@ -154,16 +158,18 @@ struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd return io; } -void pa_iochannel_free(struct pa_iochannel*io) { +void pa_iochannel_free(pa_iochannel*io) { assert(io); if (io->input_event) io->mainloop->io_free(io->input_event); + if (io->output_event && (io->output_event != io->input_event)) io->mainloop->io_free(io->output_event); if (!io->no_close) { if (io->ifd >= 0) + close(io->ifd); if (io->ofd >= 0 && io->ofd != io->ifd) close(io->ofd); @@ -172,24 +178,31 @@ void pa_iochannel_free(struct pa_iochannel*io) { pa_xfree(io); } -int pa_iochannel_is_readable(struct pa_iochannel*io) { +int pa_iochannel_is_readable(pa_iochannel*io) { assert(io); + return io->readable || io->hungup; } -int pa_iochannel_is_writable(struct pa_iochannel*io) { +int pa_iochannel_is_writable(pa_iochannel*io) { assert(io); + return io->writable && !io->hungup; } -int pa_iochannel_is_hungup(struct pa_iochannel*io) { +int pa_iochannel_is_hungup(pa_iochannel*io) { assert(io); + return io->hungup; } -ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) { +ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) { ssize_t r; - assert(io && data && l && io->ofd >= 0); + + assert(io); + assert(data); + assert(l); + assert(io->ofd >= 0); #ifdef OS_IS_WIN32 r = send(io->ofd, data, l, 0); @@ -211,9 +224,12 @@ ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) { return r; } -ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l) { +ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { ssize_t r; - assert(io && data && io->ifd >= 0); + + assert(io); + assert(data); + assert(io->ifd >= 0); #ifdef OS_IS_WIN32 r = recv(io->ifd, data, l, 0); @@ -227,6 +243,7 @@ ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l) { if (r < 0) #endif r = read(io->ifd, data, l); + if (r >= 0) { io->readable = 0; enable_mainloop_sources(io); @@ -235,34 +252,41 @@ ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l) { return r; } -void pa_iochannel_set_callback(struct pa_iochannel*io, void (*callback)(struct pa_iochannel*io, void *userdata), void *userdata) { +void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_callback_t _callback, void *userdata) { assert(io); - io->callback = callback; + + io->callback = _callback; io->userdata = userdata; } -void pa_iochannel_set_noclose(struct pa_iochannel*io, int b) { +void pa_iochannel_set_noclose(pa_iochannel*io, int b) { assert(io); + io->no_close = b; } -void pa_iochannel_socket_peer_to_string(struct pa_iochannel*io, char*s, size_t l) { - assert(io && s && l); +void pa_iochannel_socket_peer_to_string(pa_iochannel*io, char*s, size_t l) { + assert(io); + assert(s); + assert(l); + pa_socket_peer_to_string(io->ifd, s, l); } -int pa_iochannel_socket_set_rcvbuf(struct pa_iochannel *io, size_t l) { +int pa_iochannel_socket_set_rcvbuf(pa_iochannel *io, size_t l) { assert(io); + return pa_socket_set_rcvbuf(io->ifd, l); } -int pa_iochannel_socket_set_sndbuf(struct pa_iochannel *io, size_t l) { +int pa_iochannel_socket_set_sndbuf(pa_iochannel *io, size_t l) { assert(io); + return pa_socket_set_sndbuf(io->ofd, l); } - -struct pa_mainloop_api* pa_iochannel_get_mainloop_api(struct pa_iochannel *io) { +pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io) { assert(io); + return io->mainloop; } diff --git a/polyp/iochannel.h b/polyp/iochannel.h index 2a1ba3706..e2b8bccf0 100644 --- a/polyp/iochannel.h +++ b/polyp/iochannel.h @@ -35,37 +35,38 @@ * reached. Otherwise strange things may happen when an EOF is * reached. */ -struct pa_iochannel; +typedef struct pa_iochannel pa_iochannel; /* Create a new IO channel for the specified file descriptors for input resp. output. It is safe to pass the same file descriptor for both parameters (in case of full-duplex channels). For a simplex channel specify -1 for the other direction. */ -struct pa_iochannel* pa_iochannel_new(struct pa_mainloop_api*m, int ifd, int ofd); -void pa_iochannel_free(struct pa_iochannel*io); +pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd); +void pa_iochannel_free(pa_iochannel*io); -ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l); -ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l); +ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l); +ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l); -int pa_iochannel_is_readable(struct pa_iochannel*io); -int pa_iochannel_is_writable(struct pa_iochannel*io); -int pa_iochannel_is_hungup(struct pa_iochannel*io); +int pa_iochannel_is_readable(pa_iochannel*io); +int pa_iochannel_is_writable(pa_iochannel*io); +int pa_iochannel_is_hungup(pa_iochannel*io); /* Don't close the file descirptors when the io channel is freed. By * default the file descriptors are closed. */ -void pa_iochannel_set_noclose(struct pa_iochannel*io, int b); +void pa_iochannel_set_noclose(pa_iochannel*io, int b); /* Set the callback function that is called whenever data becomes available for read or write */ -void pa_iochannel_set_callback(struct pa_iochannel*io, void (*callback)(struct pa_iochannel*io, void *userdata), void *userdata); +typedef void (*pa_iochannel_callback_t)(pa_iochannel*io, void *userdata); +void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_callback_t callback, void *userdata); /* In case the file descriptor is a socket, return a pretty-printed string in *s which describes the peer connected */ -void pa_iochannel_socket_peer_to_string(struct pa_iochannel*io, char*s, size_t l); +void pa_iochannel_socket_peer_to_string(pa_iochannel*io, char*s, size_t l); /* Use setsockopt() to tune the recieve and send buffers of TCP sockets */ -int pa_iochannel_socket_set_rcvbuf(struct pa_iochannel*io, size_t l); -int pa_iochannel_socket_set_sndbuf(struct pa_iochannel*io, size_t l); +int pa_iochannel_socket_set_rcvbuf(pa_iochannel*io, size_t l); +int pa_iochannel_socket_set_sndbuf(pa_iochannel*io, size_t l); -struct pa_mainloop_api* pa_iochannel_get_mainloop_api(struct pa_iochannel *io); +pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io); #endif diff --git a/polyp/ioline.c b/polyp/ioline.c index 72df6b877..5b669f5c5 100644 --- a/polyp/ioline.c +++ b/polyp/ioline.c @@ -37,9 +37,9 @@ #define READ_SIZE (1024) struct pa_ioline { - struct pa_iochannel *io; - struct pa_defer_event *defer_event; - struct pa_mainloop_api *mainloop; + pa_iochannel *io; + pa_defer_event *defer_event; + pa_mainloop_api *mainloop; int ref; int dead; @@ -49,20 +49,20 @@ struct pa_ioline { char *rbuf; size_t rbuf_length, rbuf_index, rbuf_valid_length; - void (*callback)(struct pa_ioline*io, const char *s, void *userdata); + void (*callback)(pa_ioline*io, const char *s, void *userdata); void *userdata; int defer_close; }; -static void io_callback(struct pa_iochannel*io, void *userdata); -static void defer_callback(struct pa_mainloop_api*m, struct pa_defer_event*e, void *userdata); +static void io_callback(pa_iochannel*io, void *userdata); +static void defer_callback(pa_mainloop_api*m, pa_defer_event*e, void *userdata); -struct pa_ioline* pa_ioline_new(struct pa_iochannel *io) { - struct pa_ioline *l; +pa_ioline* pa_ioline_new(pa_iochannel *io) { + pa_ioline *l; assert(io); - l = pa_xmalloc(sizeof(struct pa_ioline)); + l = pa_xmalloc(sizeof(pa_ioline)); l->io = io; l->dead = 0; @@ -88,7 +88,7 @@ struct pa_ioline* pa_ioline_new(struct pa_iochannel *io) { return l; } -static void ioline_free(struct pa_ioline *l) { +static void ioline_free(pa_ioline *l) { assert(l); if (l->io) @@ -102,21 +102,21 @@ static void ioline_free(struct pa_ioline *l) { pa_xfree(l); } -void pa_ioline_unref(struct pa_ioline *l) { +void pa_ioline_unref(pa_ioline *l) { assert(l && l->ref >= 1); if ((--l->ref) <= 0) ioline_free(l); } -struct pa_ioline* pa_ioline_ref(struct pa_ioline *l) { +pa_ioline* pa_ioline_ref(pa_ioline *l) { assert(l && l->ref >= 1); l->ref++; return l; } -void pa_ioline_close(struct pa_ioline *l) { +void pa_ioline_close(pa_ioline *l) { assert(l && l->ref >= 1); l->dead = 1; @@ -131,7 +131,7 @@ void pa_ioline_close(struct pa_ioline *l) { } } -void pa_ioline_puts(struct pa_ioline *l, const char *c) { +void pa_ioline_puts(pa_ioline *l, const char *c) { size_t len; assert(l && c && l->ref >= 1 && !l->dead); @@ -174,13 +174,13 @@ void pa_ioline_puts(struct pa_ioline *l, const char *c) { pa_ioline_unref(l); } -void pa_ioline_set_callback(struct pa_ioline*l, void (*callback)(struct pa_ioline*io, const char *s, void *userdata), void *userdata) { +void pa_ioline_set_callback(pa_ioline*l, void (*callback)(pa_ioline*io, const char *s, void *userdata), void *userdata) { assert(l && l->ref >= 1); l->callback = callback; l->userdata = userdata; } -static void failure(struct pa_ioline *l) { +static void failure(pa_ioline *l) { assert(l && l->ref >= 1 && !l->dead); pa_ioline_close(l); @@ -191,7 +191,7 @@ static void failure(struct pa_ioline *l) { } } -static void scan_for_lines(struct pa_ioline *l, size_t skip) { +static void scan_for_lines(pa_ioline *l, size_t skip) { assert(l && l->ref >= 1 && skip < l->rbuf_valid_length); while (!l->dead && l->rbuf_valid_length > skip) { @@ -224,9 +224,9 @@ static void scan_for_lines(struct pa_ioline *l, size_t skip) { l->rbuf_index = l->rbuf_valid_length = 0; } -static int do_write(struct pa_ioline *l); +static int do_write(pa_ioline *l); -static int do_read(struct pa_ioline *l) { +static int do_read(pa_ioline *l) { assert(l && l->ref >= 1); while (!l->dead && pa_iochannel_is_readable(l->io)) { @@ -288,7 +288,7 @@ static int do_read(struct pa_ioline *l) { } /* Try to flush the buffer */ -static int do_write(struct pa_ioline *l) { +static int do_write(pa_ioline *l) { ssize_t r; assert(l && l->ref >= 1); @@ -312,7 +312,7 @@ static int do_write(struct pa_ioline *l) { } /* Try to flush read/write data */ -static void do_work(struct pa_ioline *l) { +static void do_work(pa_ioline *l) { assert(l && l->ref >= 1); pa_ioline_ref(l); @@ -331,21 +331,21 @@ static void do_work(struct pa_ioline *l) { pa_ioline_unref(l); } -static void io_callback(struct pa_iochannel*io, void *userdata) { - struct pa_ioline *l = userdata; +static void io_callback(pa_iochannel*io, void *userdata) { + pa_ioline *l = userdata; assert(io && l && l->ref >= 1); do_work(l); } -static void defer_callback(struct pa_mainloop_api*m, struct pa_defer_event*e, void *userdata) { - struct pa_ioline *l = userdata; +static void defer_callback(pa_mainloop_api*m, pa_defer_event*e, void *userdata) { + pa_ioline *l = userdata; assert(l && l->ref >= 1 && l->mainloop == m && l->defer_event == e); do_work(l); } -void pa_ioline_defer_close(struct pa_ioline *l) { +void pa_ioline_defer_close(pa_ioline *l) { assert(l); l->defer_close = 1; @@ -354,7 +354,7 @@ void pa_ioline_defer_close(struct pa_ioline *l) { l->mainloop->defer_enable(l->defer_event, 1); } -void pa_ioline_printf(struct pa_ioline *s, const char *format, ...) { +void pa_ioline_printf(pa_ioline *s, const char *format, ...) { char *t; va_list ap; diff --git a/polyp/ioline.h b/polyp/ioline.h index 6e9c76d08..84ccb47a6 100644 --- a/polyp/ioline.h +++ b/polyp/ioline.h @@ -29,23 +29,23 @@ * callback function is called whenever a new line has been recieved * from the client */ -struct pa_ioline; +typedef struct pa_ioline pa_ioline; -struct pa_ioline* pa_ioline_new(struct pa_iochannel *io); -void pa_ioline_unref(struct pa_ioline *l); -struct pa_ioline* pa_ioline_ref(struct pa_ioline *l); -void pa_ioline_close(struct pa_ioline *l); +pa_ioline* pa_ioline_new(pa_iochannel *io); +void pa_ioline_unref(pa_ioline *l); +pa_ioline* pa_ioline_ref(pa_ioline *l); +void pa_ioline_close(pa_ioline *l); /* Write a string to the channel */ -void pa_ioline_puts(struct pa_ioline *s, const char *c); +void pa_ioline_puts(pa_ioline *s, const char *c); /* Write a string to the channel */ -void pa_ioline_printf(struct pa_ioline *s, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); +void pa_ioline_printf(pa_ioline *s, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); /* Set the callback function that is called for every recieved line */ -void pa_ioline_set_callback(struct pa_ioline*io, void (*callback)(struct pa_ioline*io, const char *s, void *userdata), void *userdata); +void pa_ioline_set_callback(pa_ioline*io, void (*callback)(pa_ioline*io, const char *s, void *userdata), void *userdata); /* Make sure to close the ioline object as soon as the send buffer is emptied */ -void pa_ioline_defer_close(struct pa_ioline *io); +void pa_ioline_defer_close(pa_ioline *io); #endif diff --git a/polyp/log.c b/polyp/log.c index 2bbf2e867..c41fbbaec 100644 --- a/polyp/log.c +++ b/polyp/log.c @@ -38,9 +38,9 @@ #define ENV_LOGLEVEL "POLYP_LOG" static char *log_ident = NULL; -static enum pa_log_target log_target = PA_LOG_STDERR; -static void (*user_log_func)(enum pa_log_level l, const char *s) = NULL; -static enum pa_log_level maximal_level = PA_LOG_NOTICE; +static pa_log_target log_target = PA_LOG_STDERR; +static void (*user_log_func)(pa_log_level l, const char *s) = NULL; +static pa_log_level maximal_level = PA_LOG_NOTICE; #ifdef HAVE_SYSLOG_H static const int level_to_syslog[] = { @@ -59,18 +59,18 @@ void pa_log_set_ident(const char *p) { log_ident = pa_xstrdup(p); } -void pa_log_set_maximal_level(enum pa_log_level l) { +void pa_log_set_maximal_level(pa_log_level l) { assert(l < PA_LOG_LEVEL_MAX); maximal_level = l; } -void pa_log_set_target(enum pa_log_target t, void (*func)(enum pa_log_level l, const char*s)) { +void pa_log_set_target(pa_log_target t, void (*func)(pa_log_level l, const char*s)) { assert(t == PA_LOG_USER || !func); log_target = t; user_log_func = func; } -void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap) { +void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap) { const char *e; assert(level < PA_LOG_LEVEL_MAX); @@ -107,44 +107,44 @@ void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap) { } -void pa_log_level(enum pa_log_level level, const char *format, ...) { +void pa_log_with_level(pa_log_level level, const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_levelv(level, format, ap); + pa_log_with_levelv(level, format, ap); va_end(ap); } void pa_log_debug(const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_levelv(PA_LOG_DEBUG, format, ap); + pa_log_with_levelv(PA_LOG_DEBUG, format, ap); va_end(ap); } void pa_log_info(const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_levelv(PA_LOG_INFO, format, ap); + pa_log_with_levelv(PA_LOG_INFO, format, ap); va_end(ap); } void pa_log_notice(const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_levelv(PA_LOG_INFO, format, ap); + pa_log_with_levelv(PA_LOG_INFO, format, ap); va_end(ap); } void pa_log_warn(const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_levelv(PA_LOG_WARN, format, ap); + pa_log_with_levelv(PA_LOG_WARN, format, ap); va_end(ap); } void pa_log_error(const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_levelv(PA_LOG_ERROR, format, ap); + pa_log_with_levelv(PA_LOG_ERROR, format, ap); va_end(ap); } diff --git a/polyp/log.h b/polyp/log.h index fe2dad59b..7c6a8e614 100644 --- a/polyp/log.h +++ b/polyp/log.h @@ -23,35 +23,35 @@ ***/ #include -#include "gcc-printf.h" +#include "gccmacro.h" /* A simple logging subsystem */ /* Where to log to */ -enum pa_log_target { +typedef enum pa_log_target { PA_LOG_STDERR, /* default */ PA_LOG_SYSLOG, PA_LOG_USER, /* to user specified function */ PA_LOG_NULL /* to /dev/null */ -}; +} pa_log_target; -enum pa_log_level { +typedef enum pa_log_level { PA_LOG_ERROR = 0, /* Error messages */ PA_LOG_WARN = 1, /* Warning messages */ PA_LOG_NOTICE = 2, /* Notice messages */ PA_LOG_INFO = 3, /* Info messages */ PA_LOG_DEBUG = 4, /* debug message */ PA_LOG_LEVEL_MAX -}; +} pa_log_level; -/* Set an identifcation for the current daemon. Used when logging to syslog. */ +/* Set an identification for the current daemon. Used when logging to syslog. */ void pa_log_set_ident(const char *p); /* Set another log target. If t is PA_LOG_USER you may specify a function that is called every log string */ -void pa_log_set_target(enum pa_log_target t, void (*func)(enum pa_log_level, const char*s)); +void pa_log_set_target(pa_log_target t, void (*func)(pa_log_level, const char*s)); /* Minimal log level */ -void pa_log_set_maximal_level(enum pa_log_level l); +void pa_log_set_maximal_level(pa_log_level l); /* Do a log line */ void pa_log_debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); @@ -60,9 +60,9 @@ void pa_log_notice(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); void pa_log_warn(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); void pa_log_error(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); -void pa_log_level(enum pa_log_level level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); +void pa_log_with_level(pa_log_level level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); -void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap); +void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap); #define pa_log pa_log_error diff --git a/polyp/main.c b/polyp/main.c index e481fce16..1c3b566d8 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -75,7 +75,7 @@ int deny_severity = LOG_WARNING; #ifdef OS_IS_WIN32 -static void message_cb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { +static void message_cb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { MSG msg; while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { @@ -90,7 +90,7 @@ static void message_cb(struct pa_mainloop_api*a, struct pa_defer_event *e, void #endif -static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { +static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, int sig, void *userdata) { pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig)); switch (sig) { @@ -133,12 +133,12 @@ static void close_pipe(int p[2]) { } int main(int argc, char *argv[]) { - struct pa_core *c; - struct pa_strbuf *buf = NULL; - struct pa_daemon_conf *conf; - struct pa_mainloop *mainloop; + pa_core *c; + pa_strbuf *buf = NULL; + pa_daemon_conf *conf; + pa_mainloop *mainloop; - char *s; + char *s; int r, retval = 1, d = 0; int daemon_pipe[2] = { -1, -1 }; int suid_root; @@ -149,7 +149,7 @@ int main(int argc, char *argv[]) { #endif #ifdef OS_IS_WIN32 - struct pa_defer_event *defer; + pa_defer_event *defer; #endif pa_limit_caps(); @@ -213,7 +213,7 @@ int main(int argc, char *argv[]) { goto finish; case PA_CMD_DUMP_CONF: { - char *s = pa_daemon_conf_dump(conf); + s = pa_daemon_conf_dump(conf); fputs(s, stdout); pa_xfree(s); retval = 0; @@ -405,7 +405,7 @@ int main(int argc, char *argv[]) { if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); #endif - } else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) { + } else if (!c->modules || pa_idxset_size(c->modules) == 0) { pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n"); #ifdef HAVE_FORK if (conf->daemonize) diff --git a/polyp/mainloop-api.c b/polyp/mainloop-api.c index 7b80e4fe1..3229ec20b 100644 --- a/polyp/mainloop-api.c +++ b/polyp/mainloop-api.c @@ -28,13 +28,14 @@ #include "mainloop-api.h" #include "xmalloc.h" +#include "gccmacro.h" struct once_info { - void (*callback)(struct pa_mainloop_api*m, void *userdata); + void (*callback)(pa_mainloop_api*m, void *userdata); void *userdata; }; -static void once_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { +static void once_callback(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { struct once_info *i = userdata; assert(m && i && i->callback); @@ -44,18 +45,18 @@ static void once_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, v m->defer_free(e); } -static void free_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { +static void free_callback(pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event *e, void *userdata) { struct once_info *i = userdata; assert(m && i); pa_xfree(i); } -void pa_mainloop_api_once(struct pa_mainloop_api* m, void (*callback)(struct pa_mainloop_api *m, void *userdata), void *userdata) { +void pa_mainloop_api_once(pa_mainloop_api* m, void (*callback)(pa_mainloop_api *m, void *userdata), void *userdata) { struct once_info *i; - struct pa_defer_event *e; + pa_defer_event *e; assert(m && callback); - i = pa_xmalloc(sizeof(struct once_info)); + i = pa_xnew(struct once_info, 1); i->callback = callback; i->userdata = userdata; diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index 3fb221fae..1604e7406 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -45,73 +45,75 @@ PA_C_DECL_BEGIN /** A bitmask for IO events */ -enum pa_io_event_flags { +typedef enum pa_io_event_flags { PA_IO_EVENT_NULL = 0, /**< No event */ PA_IO_EVENT_INPUT = 1, /**< Input event */ PA_IO_EVENT_OUTPUT = 2, /**< Output event */ PA_IO_EVENT_HANGUP = 4, /**< Hangup event */ PA_IO_EVENT_ERROR = 8 /**< Error event */ -}; +} pa_io_event_flags; -/** \struct pa_io_event +/** \pa_io_event * An opaque IO event source object */ -struct pa_io_event; +typedef struct pa_io_event pa_io_event; -/** \struct pa_defer_event +/** \pa_defer_event * An opaque deferred event source object. Events of this type are triggered once in every main loop iteration */ -struct pa_defer_event; +typedef struct pa_defer_event pa_defer_event; -/** \struct pa_time_event +/** \pa_time_event * An opaque timer event source object */ -struct pa_time_event; +typedef struct pa_time_event pa_time_event; /** An abstract mainloop API vtable */ -struct pa_mainloop_api { +typedef struct pa_mainloop_api pa_mainloop_api; + +struct pa_mainloop_api { /** A pointer to some private, arbitrary data of the main loop implementation */ void *userdata; /** Create a new IO event source object */ - struct pa_io_event* (*io_new)(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event* e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata); + pa_io_event* (*io_new)(pa_mainloop_api*a, int fd, pa_io_event_flags events, void (*callback) (pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags events, void *userdata), void *userdata); /** Enable or disable IO events on this object */ - void (*io_enable)(struct pa_io_event* e, enum pa_io_event_flags events); + void (*io_enable)(pa_io_event* e, pa_io_event_flags events); /** Free a IO event source object */ - void (*io_free)(struct pa_io_event* e); + void (*io_free)(pa_io_event* e); /** Set a function that is called when the IO event source is destroyed. Use this to free the userdata argument if required */ - void (*io_set_destroy)(struct pa_io_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata)); + void (*io_set_destroy)(pa_io_event *e, void (*callback) (pa_mainloop_api*a, pa_io_event *e, void *userdata)); /** Create a new timer event source object for the specified Unix time */ - struct pa_time_event* (*time_new)(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event* e, const struct timeval *tv, void *userdata), void *userdata); + pa_time_event* (*time_new)(pa_mainloop_api*a, const struct timeval *tv, void (*callback) (pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata), void *userdata); /** Restart a running or expired timer event source with a new Unix time */ - void (*time_restart)(struct pa_time_event* e, const struct timeval *tv); + void (*time_restart)(pa_time_event* e, const struct timeval *tv); /** Free a deferred timer event source object */ - void (*time_free)(struct pa_time_event* e); + void (*time_free)(pa_time_event* e); /** Set a function that is called when the timer event source is destroyed. Use this to free the userdata argument if required */ - void (*time_set_destroy)(struct pa_time_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)); + void (*time_set_destroy)(pa_time_event *e, void (*callback) (pa_mainloop_api*a, pa_time_event *e, void *userdata)); /** Create a new deferred event source object */ - struct pa_defer_event* (*defer_new)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event* e, void *userdata), void *userdata); + pa_defer_event* (*defer_new)(pa_mainloop_api*a, void (*callback) (pa_mainloop_api*a, pa_defer_event* e, void *userdata), void *userdata); /** Enable or disable a deferred event source temporarily */ - void (*defer_enable)(struct pa_defer_event* e, int b); + void (*defer_enable)(pa_defer_event* e, int b); /** Free a deferred event source object */ - void (*defer_free)(struct pa_defer_event* e); + void (*defer_free)(pa_defer_event* e); /** Set a function that is called when the deferred event source is destroyed. Use this to free the userdata argument if required */ - void (*defer_set_destroy)(struct pa_defer_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)); + void (*defer_set_destroy)(pa_defer_event *e, void (*callback) (pa_mainloop_api*a, pa_defer_event *e, void *userdata)); /** Exit the main loop and return the specfied retval*/ - void (*quit)(struct pa_mainloop_api*a, int retval); + void (*quit)(pa_mainloop_api*a, int retval); }; /** Run the specified callback function once from the main loop using an anonymous defer event. */ -void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(struct pa_mainloop_api*m, void *userdata), void *userdata); +void pa_mainloop_api_once(pa_mainloop_api*m, void (*callback)(pa_mainloop_api*m, void *userdata), void *userdata); PA_C_DECL_END diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c index 432498a86..f225e60b4 100644 --- a/polyp/mainloop-signal.c +++ b/polyp/mainloop-signal.c @@ -40,6 +40,7 @@ #include "util.h" #include "xmalloc.h" #include "log.h" +#include "gccmacro.h" struct pa_signal_event { int sig; @@ -48,17 +49,17 @@ struct pa_signal_event { #else void (*saved_handler)(int sig); #endif - void (*callback) (struct pa_mainloop_api*a, struct pa_signal_event *e, int signal, void *userdata); + void (*callback) (pa_mainloop_api*a, pa_signal_event *e, int sig, void *userdata); void *userdata; - void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_signal_event*e, void *userdata); - struct pa_signal_event *previous, *next; + void (*destroy_callback) (pa_mainloop_api*a, pa_signal_event*e, void *userdata); + pa_signal_event *previous, *next; }; -static struct pa_mainloop_api *api = NULL; +static pa_mainloop_api *api = NULL; static int signal_pipe[2] = { -1, -1 }; -static struct pa_io_event* io_event = NULL; -static struct pa_defer_event *defer_event = NULL; -static struct pa_signal_event *signals = NULL; +static pa_io_event* io_event = NULL; +static pa_defer_event *defer_event = NULL; +static pa_signal_event *signals = NULL; #ifdef OS_IS_WIN32 static unsigned int waiting_signals = 0; @@ -78,8 +79,8 @@ static void signal_handler(int sig) { #endif } -static void dispatch(struct pa_mainloop_api*a, int sig) { - struct pa_signal_event*s; +static void dispatch(pa_mainloop_api*a, int sig) { + pa_signal_event*s; for (s = signals; s; s = s->next) if (s->sig == sig) { @@ -89,7 +90,7 @@ static void dispatch(struct pa_mainloop_api*a, int sig) { } } -static void defer(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata) { +static void defer(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event*e, PA_GCC_UNUSED void *userdata) { ssize_t r; int sig; unsigned int sigs; @@ -118,7 +119,7 @@ static void defer(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userd } } -static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) { +static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags f, PA_GCC_UNUSED void *userdata) { ssize_t r; int sig; assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); @@ -140,7 +141,7 @@ static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enu dispatch(a, sig); } -int pa_signal_init(struct pa_mainloop_api *a) { +int pa_signal_init(pa_mainloop_api *a) { assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event && !defer_event); #ifdef OS_IS_WIN32 @@ -196,22 +197,22 @@ void pa_signal_done(void) { api = NULL; } -struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int sig, void *userdata), void *userdata) { - struct pa_signal_event *e = NULL; +pa_signal_event* pa_signal_new(int sig, void (*_callback) (pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata), void *userdata) { + pa_signal_event *e = NULL; #ifdef HAVE_SIGACTION struct sigaction sa; #endif - assert(sig > 0 && callback); + assert(sig > 0 && _callback); for (e = signals; e; e = e->next) if (e->sig == sig) goto fail; - e = pa_xmalloc(sizeof(struct pa_signal_event)); + e = pa_xmalloc(sizeof(pa_signal_event)); e->sig = sig; - e->callback = callback; + e->callback = _callback; e->userdata = userdata; e->destroy_callback = NULL; @@ -238,7 +239,7 @@ fail: return NULL; } -void pa_signal_free(struct pa_signal_event *e) { +void pa_signal_free(pa_signal_event *e) { assert(e); if (e->next) @@ -260,7 +261,7 @@ void pa_signal_free(struct pa_signal_event *e) { pa_xfree(e); } -void pa_signal_set_destroy(struct pa_signal_event *e, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, void *userdata)) { +void pa_signal_set_destroy(pa_signal_event *e, void (*_callback) (pa_mainloop_api *api, pa_signal_event*e, void *userdata)) { assert(e); - e->destroy_callback = callback; + e->destroy_callback = _callback; } diff --git a/polyp/mainloop-signal.h b/polyp/mainloop-signal.h index 9ba921412..6ce313702 100644 --- a/polyp/mainloop-signal.h +++ b/polyp/mainloop-signal.h @@ -37,23 +37,23 @@ PA_C_DECL_BEGIN */ /** Initialize the UNIX signal subsystem and bind it to the specified main loop */ -int pa_signal_init(struct pa_mainloop_api *api); +int pa_signal_init(pa_mainloop_api *api); /** Cleanup the signal subsystem */ void pa_signal_done(void); -/** \struct pa_signal_event +/** \pa_signal_event * An opaque UNIX signal event source object */ -struct pa_signal_event; +typedef struct pa_signal_event pa_signal_event; /** Create a new UNIX signal event source object */ -struct pa_signal_event* pa_signal_new(int signal, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int signal, void *userdata), void *userdata); +pa_signal_event* pa_signal_new(int sig, void (*callback) (pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata), void *userdata); /** Free a UNIX signal event source object */ -void pa_signal_free(struct pa_signal_event *e); +void pa_signal_free(pa_signal_event *e); /** Set a function that is called when the signal event source is destroyed. Use this to free the userdata argument if required */ -void pa_signal_set_destroy(struct pa_signal_event *e, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, void *userdata)); +void pa_signal_set_destroy(pa_signal_event *e, void (*callback) (pa_mainloop_api *api, pa_signal_event*e, void *userdata)); PA_C_DECL_END diff --git a/polyp/mainloop-test.c b/polyp/mainloop-test.c index dd8f8137c..097ce1c79 100644 --- a/polyp/mainloop-test.c +++ b/polyp/mainloop-test.c @@ -28,10 +28,14 @@ #include #include +#include "util.h" +#include "gccmacro.h" + #ifdef GLIB_MAIN_LOOP #include #include "glib-mainloop.h" + static GMainLoop* glib_main_loop = NULL; #if GLIB_MAJOR_VERSION >= 2 @@ -45,21 +49,21 @@ static GMainLoop* glib_main_loop = NULL; #include "mainloop.h" #endif /* GLIB_MAIN_LOOP */ -static struct pa_defer_event *de; +static pa_defer_event *de; -static void iocb(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { +static void iocb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) { unsigned char c; read(fd, &c, sizeof(c)); fprintf(stderr, "IO EVENT: %c\n", c < 32 ? '.' : c); a->defer_enable(de, 1); } -static void dcb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { +static void dcb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { fprintf(stderr, "DEFER EVENT\n"); a->defer_enable(e, 0); } -static void tcb(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval *tv, void *userdata) { +static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { fprintf(stderr, "TIME EVENT\n"); #if defined(GLIB_MAIN_LOOP) && defined(GLIB20) @@ -71,14 +75,14 @@ static void tcb(struct pa_mainloop_api*a, struct pa_time_event *e, const struct #endif } -int main(int argc, char *argv[]) { - struct pa_mainloop_api *a; - struct pa_io_event *ioe; - struct pa_time_event *te; +int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { + pa_mainloop_api *a; + pa_io_event *ioe; + pa_time_event *te; struct timeval tv; #ifdef GLIB_MAIN_LOOP - struct pa_glib_mainloop *g; + pa_glib_mainloop *g; #ifdef GLIB20 glib_main_loop = g_main_loop_new(NULL, FALSE); @@ -96,7 +100,7 @@ int main(int argc, char *argv[]) { a = pa_glib_mainloop_get_api(g); assert(a); #else /* GLIB_MAIN_LOOP */ - struct pa_mainloop *m; + pa_mainloop *m; m = pa_mainloop_new(); assert(m); diff --git a/polyp/mainloop.c b/polyp/mainloop.c index ada74afc8..599a90f85 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -47,37 +47,37 @@ #include "log.h" struct pa_io_event { - struct pa_mainloop *mainloop; + pa_mainloop *mainloop; int dead; int fd; - enum pa_io_event_flags events; - void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata); + pa_io_event_flags events; + void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata); struct pollfd *pollfd; void *userdata; - void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata); + void (*destroy_callback) (pa_mainloop_api*a, pa_io_event *e, void *userdata); }; struct pa_time_event { - struct pa_mainloop *mainloop; + pa_mainloop *mainloop; int dead; int enabled; struct timeval timeval; - void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval*tv, void *userdata); + void (*callback)(pa_mainloop_api*a, pa_time_event *e, const struct timeval*tv, void *userdata); void *userdata; - void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata); + void (*destroy_callback) (pa_mainloop_api*a, pa_time_event *e, void *userdata); }; struct pa_defer_event { - struct pa_mainloop *mainloop; + pa_mainloop *mainloop; int dead; int enabled; - void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata); + void (*callback)(pa_mainloop_api*a, pa_defer_event*e, void *userdata); void *userdata; - void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata); + void (*destroy_callback) (pa_mainloop_api*a, pa_defer_event *e, void *userdata); }; struct pa_mainloop { - struct pa_idxset *io_events, *time_events, *defer_events; + pa_idxset *io_events, *time_events, *defer_events; int io_events_scan_dead, defer_events_scan_dead, time_events_scan_dead; struct pollfd *pollfds; @@ -85,21 +85,21 @@ struct pa_mainloop { int rebuild_pollfds; int quit, running, retval; - struct pa_mainloop_api api; + pa_mainloop_api api; int deferred_pending; }; /* IO events */ -static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enum pa_io_event_flags events, void (*callback) (struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct pa_io_event *e; +static pa_io_event* mainloop_io_new(pa_mainloop_api*a, int fd, pa_io_event_flags events, void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata) { + pa_mainloop *m; + pa_io_event *e; assert(a && a->userdata && fd >= 0 && callback); m = a->userdata; assert(a == &m->api); - e = pa_xmalloc(sizeof(struct pa_io_event)); + e = pa_xmalloc(sizeof(pa_io_event)); e->mainloop = m; e->dead = 0; @@ -135,7 +135,7 @@ static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enu return e; } -static void mainloop_io_enable(struct pa_io_event *e, enum pa_io_event_flags events) { +static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags events) { assert(e && e->mainloop); e->events = events; @@ -146,26 +146,26 @@ static void mainloop_io_enable(struct pa_io_event *e, enum pa_io_event_flags eve POLLERR | POLLHUP; } -static void mainloop_io_free(struct pa_io_event *e) { +static void mainloop_io_free(pa_io_event *e) { assert(e && e->mainloop); e->dead = e->mainloop->io_events_scan_dead = e->mainloop->rebuild_pollfds = 1; } -static void mainloop_io_set_destroy(struct pa_io_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_io_event *e, void *userdata)) { +static void mainloop_io_set_destroy(pa_io_event *e, void (*callback)(pa_mainloop_api*a, pa_io_event *e, void *userdata)) { assert(e); e->destroy_callback = callback; } /* Defer events */ -static struct pa_defer_event* mainloop_defer_new(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct pa_defer_event *e; +static pa_defer_event* mainloop_defer_new(pa_mainloop_api*a, void (*callback) (pa_mainloop_api*a, pa_defer_event *e, void *userdata), void *userdata) { + pa_mainloop *m; + pa_defer_event *e; assert(a && a->userdata && callback); m = a->userdata; assert(a == &m->api); - e = pa_xmalloc(sizeof(struct pa_defer_event)); + e = pa_xmalloc(sizeof(pa_defer_event)); e->mainloop = m; e->dead = 0; @@ -180,7 +180,7 @@ static struct pa_defer_event* mainloop_defer_new(struct pa_mainloop_api*a, void return e; } -static void mainloop_defer_enable(struct pa_defer_event *e, int b) { +static void mainloop_defer_enable(pa_defer_event *e, int b) { assert(e); if (e->enabled && !b) { @@ -192,7 +192,7 @@ static void mainloop_defer_enable(struct pa_defer_event *e, int b) { e->enabled = b; } -static void mainloop_defer_free(struct pa_defer_event *e) { +static void mainloop_defer_free(pa_defer_event *e) { assert(e); e->dead = e->mainloop->defer_events_scan_dead = 1; @@ -203,21 +203,21 @@ static void mainloop_defer_free(struct pa_defer_event *e) { } } -static void mainloop_defer_set_destroy(struct pa_defer_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata)) { +static void mainloop_defer_set_destroy(pa_defer_event *e, void (*callback)(pa_mainloop_api*a, pa_defer_event *e, void *userdata)) { assert(e); e->destroy_callback = callback; } /* Time events */ -static struct pa_time_event* mainloop_time_new(struct pa_mainloop_api*a, const struct timeval *tv, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { - struct pa_mainloop *m; - struct pa_time_event *e; +static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval *tv, void (*callback) (pa_mainloop_api*a, pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { + pa_mainloop *m; + pa_time_event *e; assert(a && a->userdata && callback); m = a->userdata; assert(a == &m->api); - e = pa_xmalloc(sizeof(struct pa_time_event)); + e = pa_xmalloc(sizeof(pa_time_event)); e->mainloop = m; e->dead = 0; @@ -234,7 +234,7 @@ static struct pa_time_event* mainloop_time_new(struct pa_mainloop_api*a, const s return e; } -static void mainloop_time_restart(struct pa_time_event *e, const struct timeval *tv) { +static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { assert(e); if (tv) { @@ -244,21 +244,21 @@ static void mainloop_time_restart(struct pa_time_event *e, const struct timeval e->enabled = 0; } -static void mainloop_time_free(struct pa_time_event *e) { +static void mainloop_time_free(pa_time_event *e) { assert(e); e->dead = e->mainloop->time_events_scan_dead = 1; } -static void mainloop_time_set_destroy(struct pa_time_event *e, void (*callback)(struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata)) { +static void mainloop_time_set_destroy(pa_time_event *e, void (*callback)(pa_mainloop_api*a, pa_time_event *e, void *userdata)) { assert(e); e->destroy_callback = callback; } /* quit() */ -static void mainloop_quit(struct pa_mainloop_api*a, int retval) { - struct pa_mainloop *m; +static void mainloop_quit(pa_mainloop_api*a, int retval) { + pa_mainloop *m; assert(a && a->userdata); m = a->userdata; assert(a == &m->api); @@ -267,7 +267,7 @@ static void mainloop_quit(struct pa_mainloop_api*a, int retval) { m->retval = retval; } -static const struct pa_mainloop_api vtable = { +static const pa_mainloop_api vtable = { .userdata = NULL, .io_new= mainloop_io_new, @@ -288,10 +288,10 @@ static const struct pa_mainloop_api vtable = { .quit = mainloop_quit, }; -struct pa_mainloop *pa_mainloop_new(void) { - struct pa_mainloop *m; +pa_mainloop *pa_mainloop_new(void) { + pa_mainloop *m; - m = pa_xmalloc(sizeof(struct pa_mainloop)); + m = pa_xmalloc(sizeof(pa_mainloop)); m->io_events = pa_idxset_new(NULL, NULL); m->defer_events = pa_idxset_new(NULL, NULL); @@ -314,8 +314,8 @@ struct pa_mainloop *pa_mainloop_new(void) { return m; } -static int io_foreach(void *p, uint32_t index, int *del, void*userdata) { - struct pa_io_event *e = p; +static int io_foreach(void *p, uint32_t PA_GCC_UNUSED idx, int *del, void*userdata) { + pa_io_event *e = p; int *all = userdata; assert(e && del && all); @@ -329,8 +329,8 @@ static int io_foreach(void *p, uint32_t index, int *del, void*userdata) { return 0; } -static int time_foreach(void *p, uint32_t index, int *del, void*userdata) { - struct pa_time_event *e = p; +static int time_foreach(void *p, uint32_t PA_GCC_UNUSED idx, int *del, void*userdata) { + pa_time_event *e = p; int *all = userdata; assert(e && del && all); @@ -344,8 +344,8 @@ static int time_foreach(void *p, uint32_t index, int *del, void*userdata) { return 0; } -static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) { - struct pa_defer_event *e = p; +static int defer_foreach(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void*userdata) { + pa_defer_event *e = p; int *all = userdata; assert(e && del && all); @@ -359,7 +359,7 @@ static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) { return 0; } -void pa_mainloop_free(struct pa_mainloop* m) { +void pa_mainloop_free(pa_mainloop* m) { int all = 1; assert(m); @@ -375,7 +375,7 @@ void pa_mainloop_free(struct pa_mainloop* m) { pa_xfree(m); } -static void scan_dead(struct pa_mainloop *m) { +static void scan_dead(pa_mainloop *m) { int all = 0; assert(m); @@ -389,13 +389,13 @@ static void scan_dead(struct pa_mainloop *m) { m->io_events_scan_dead = m->time_events_scan_dead = m->defer_events_scan_dead = 0; } -static void rebuild_pollfds(struct pa_mainloop *m) { - struct pa_io_event*e; +static void rebuild_pollfds(pa_mainloop *m) { + pa_io_event*e; struct pollfd *p; - uint32_t index = PA_IDXSET_INVALID; + uint32_t idx = PA_IDXSET_INVALID; unsigned l; - l = pa_idxset_ncontents(m->io_events); + l = pa_idxset_size(m->io_events); if (m->max_pollfds < l) { m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l); m->max_pollfds = l; @@ -403,7 +403,7 @@ static void rebuild_pollfds(struct pa_mainloop *m) { m->n_pollfds = 0; p = m->pollfds; - for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) { + for (e = pa_idxset_first(m->io_events, &idx); e; e = pa_idxset_next(m->io_events, &idx)) { if (e->dead) { e->pollfd = NULL; continue; @@ -423,12 +423,12 @@ static void rebuild_pollfds(struct pa_mainloop *m) { } } -static int dispatch_pollfds(struct pa_mainloop *m) { - uint32_t index = PA_IDXSET_INVALID; - struct pa_io_event *e; +static int dispatch_pollfds(pa_mainloop *m) { + uint32_t idx = PA_IDXSET_INVALID; + pa_io_event *e; int r = 0; - for (e = pa_idxset_first(m->io_events, &index); e && !m->quit; e = pa_idxset_next(m->io_events, &index)) { + for (e = pa_idxset_first(m->io_events, &idx); e && !m->quit; e = pa_idxset_next(m->io_events, &idx)) { if (e->dead || !e->pollfd || !e->pollfd->revents) continue; @@ -446,15 +446,15 @@ static int dispatch_pollfds(struct pa_mainloop *m) { return r; } -static int dispatch_defer(struct pa_mainloop *m) { - uint32_t index; - struct pa_defer_event *e; +static int dispatch_defer(pa_mainloop *m) { + uint32_t idx; + pa_defer_event *e; int r = 0; if (!m->deferred_pending) return 0; - for (e = pa_idxset_first(m->defer_events, &index); e && !m->quit; e = pa_idxset_next(m->defer_events, &index)) { + for (e = pa_idxset_first(m->defer_events, &idx); e && !m->quit; e = pa_idxset_next(m->defer_events, &idx)) { if (e->dead || !e->enabled) continue; @@ -466,9 +466,9 @@ static int dispatch_defer(struct pa_mainloop *m) { return r; } -static int calc_next_timeout(struct pa_mainloop *m) { - uint32_t index; - struct pa_time_event *e; +static int calc_next_timeout(pa_mainloop *m) { + uint32_t idx; + pa_time_event *e; struct timeval now; int t = -1; int got_time = 0; @@ -476,7 +476,7 @@ static int calc_next_timeout(struct pa_mainloop *m) { if (pa_idxset_isempty(m->time_events)) return -1; - for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { + for (e = pa_idxset_first(m->time_events, &idx); e; e = pa_idxset_next(m->time_events, &idx)) { int tmp; if (e->dead || !e->enabled) @@ -507,9 +507,9 @@ static int calc_next_timeout(struct pa_mainloop *m) { return t; } -static int dispatch_timeout(struct pa_mainloop *m) { - uint32_t index; - struct pa_time_event *e; +static int dispatch_timeout(pa_mainloop *m) { + uint32_t idx; + pa_time_event *e; struct timeval now; int got_time = 0; int r = 0; @@ -518,7 +518,7 @@ static int dispatch_timeout(struct pa_mainloop *m) { if (pa_idxset_isempty(m->time_events)) return 0; - for (e = pa_idxset_first(m->time_events, &index); e && !m->quit; e = pa_idxset_next(m->time_events, &index)) { + for (e = pa_idxset_first(m->time_events, &idx); e && !m->quit; e = pa_idxset_next(m->time_events, &idx)) { if (e->dead || !e->enabled) continue; @@ -542,7 +542,7 @@ static int dispatch_timeout(struct pa_mainloop *m) { return r; } -int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) { +int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) { int r, t, dispatched = 0; assert(m && !m->running); @@ -601,7 +601,7 @@ quit: return -2; } -int pa_mainloop_run(struct pa_mainloop *m, int *retval) { +int pa_mainloop_run(pa_mainloop *m, int *retval) { int r; while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0); @@ -613,31 +613,32 @@ int pa_mainloop_run(struct pa_mainloop *m, int *retval) { return 0; } -void pa_mainloop_quit(struct pa_mainloop *m, int r) { +void pa_mainloop_quit(pa_mainloop *m, int r) { assert(m); m->quit = r; } -struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m) { +pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) { assert(m); return &m->api; } -int pa_mainloop_deferred_pending(struct pa_mainloop *m) { +int pa_mainloop_deferred_pending(pa_mainloop *m) { assert(m); return m->deferred_pending > 0; } -void pa_mainloop_dump(struct pa_mainloop *m) { +#if 0 +void pa_mainloop_dump(pa_mainloop *m) { assert(m); pa_log(__FILE__": Dumping mainloop sources START\n"); { - uint32_t index = PA_IDXSET_INVALID; - struct pa_io_event *e; - for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) { + uint32_t idx = PA_IDXSET_INVALID; + pa_io_event *e; + for (e = pa_idxset_first(m->io_events, &idx); e; e = pa_idxset_next(m->io_events, &idx)) { if (e->dead) continue; @@ -645,9 +646,9 @@ void pa_mainloop_dump(struct pa_mainloop *m) { } } { - uint32_t index = PA_IDXSET_INVALID; - struct pa_defer_event *e; - for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) { + uint32_t idx = PA_IDXSET_INVALID; + pa_defer_event *e; + for (e = pa_idxset_first(m->defer_events, &idx); e; e = pa_idxset_next(m->defer_events, &idx)) { if (e->dead) continue; @@ -655,9 +656,9 @@ void pa_mainloop_dump(struct pa_mainloop *m) { } } { - uint32_t index = PA_IDXSET_INVALID; - struct pa_time_event *e; - for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) { + uint32_t idx = PA_IDXSET_INVALID; + pa_time_event *e; + for (e = pa_idxset_first(m->time_events, &idx); e; e = pa_idxset_next(m->time_events, &idx)) { if (e->dead) continue; @@ -668,3 +669,4 @@ void pa_mainloop_dump(struct pa_mainloop *m) { pa_log(__FILE__": Dumping mainloop sources STOP\n"); } +#endif diff --git a/polyp/mainloop.h b/polyp/mainloop.h index 06a6ccaa1..06764907c 100644 --- a/polyp/mainloop.h +++ b/polyp/mainloop.h @@ -35,32 +35,35 @@ PA_C_DECL_BEGIN * defined in \ref mainloop-api.h. This implementation is thread safe * as long as you access the main loop object from a single thread only.*/ -/** \struct pa_mainloop +/** \pa_mainloop * An opaque main loop object */ -struct pa_mainloop; +typedef struct pa_mainloop pa_mainloop; /** Allocate a new main loop object */ -struct pa_mainloop *pa_mainloop_new(void); +pa_mainloop *pa_mainloop_new(void); /** Free a main loop object */ -void pa_mainloop_free(struct pa_mainloop* m); +void pa_mainloop_free(pa_mainloop* m); /** Run a single iteration of the main loop. Returns a negative value on error or exit request. If block is nonzero, block for events if none are queued. Optionally return the return value as specified with the main loop's quit() routine in the integer variable retval points to. On success returns the number of source dispatched in this iteration. */ -int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval); +int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval); /** Run unlimited iterations of the main loop object until the main loop's quit() routine is called. */ -int pa_mainloop_run(struct pa_mainloop *m, int *retval); +int pa_mainloop_run(pa_mainloop *m, int *retval); /** Return the abstract main loop abstraction layer vtable for this main loop. This calls pa_mainloop_iterate() iteratively.*/ -struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m); +pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m); /** Return non-zero when there are any deferred events pending. \since 0.5 */ -int pa_mainloop_deferred_pending(struct pa_mainloop *m); +int pa_mainloop_deferred_pending(pa_mainloop *m); + +/** Shutdown the main loop */ +void pa_mainloop_quit(pa_mainloop *m, int r); PA_C_DECL_END diff --git a/polyp/mcalign-test.c b/polyp/mcalign-test.c index 2ace6e592..c151d8f29 100644 --- a/polyp/mcalign-test.c +++ b/polyp/mcalign-test.c @@ -33,12 +33,13 @@ #include "util.h" #include "mcalign.h" +#include "gccmacro.h" /* A simple program for testing pa_mcalign */ -int main(int argc, char *argv[]) { - struct pa_mcalign *a = pa_mcalign_new(11, NULL); - struct pa_memchunk c; +int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { + pa_mcalign *a = pa_mcalign_new(11, NULL); + pa_memchunk c; pa_memchunk_reset(&c); @@ -76,7 +77,7 @@ int main(int argc, char *argv[]) { } for (;;) { - struct pa_memchunk t; + pa_memchunk t; if (pa_mcalign_pop(a, &t) < 0) break; diff --git a/polyp/mcalign.c b/polyp/mcalign.c index 0b7f0db01..4d7656250 100644 --- a/polyp/mcalign.c +++ b/polyp/mcalign.c @@ -33,15 +33,15 @@ struct pa_mcalign { size_t base; - struct pa_memchunk leftover, current; - struct pa_memblock_stat *memblock_stat; + pa_memchunk leftover, current; + pa_memblock_stat *memblock_stat; }; -struct pa_mcalign *pa_mcalign_new(size_t base, struct pa_memblock_stat *s) { - struct pa_mcalign *m; +pa_mcalign *pa_mcalign_new(size_t base, pa_memblock_stat *s) { + pa_mcalign *m; assert(base); - m = pa_xmalloc(sizeof(struct pa_mcalign)); + m = pa_xnew(pa_mcalign, 1); m->base = base; pa_memchunk_reset(&m->leftover); pa_memchunk_reset(&m->current); @@ -50,7 +50,7 @@ struct pa_mcalign *pa_mcalign_new(size_t base, struct pa_memblock_stat *s) { return m; } -void pa_mcalign_free(struct pa_mcalign *m) { +void pa_mcalign_free(pa_mcalign *m) { assert(m); if (m->leftover.memblock) @@ -62,7 +62,7 @@ void pa_mcalign_free(struct pa_mcalign *m) { pa_xfree(m); } -void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) { +void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { assert(m && c && c->memblock && c->length); /* Append to the leftover memory block */ @@ -122,7 +122,7 @@ void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) { } } -int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) { +int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) { assert(m && c); /* First test if there's a leftover memory block available */ diff --git a/polyp/mcalign.h b/polyp/mcalign.h index 925f438a5..5de75bc7c 100644 --- a/polyp/mcalign.h +++ b/polyp/mcalign.h @@ -36,10 +36,10 @@ * 0, the memchunk *c is valid and aligned to the granularity. Some * pseudocode illustrating this: * - * struct pa_mcalign *a = pa_mcalign_new(4, NULL); + * pa_mcalign *a = pa_mcalign_new(4, NULL); * * for (;;) { - * struct pa_memchunk input; + * pa_memchunk input; * * ... fill input ... * @@ -47,7 +47,7 @@ * pa_memblock_unref(input.memblock); * * for (;;) { - * struct pa_memchunk output; + * pa_memchunk output; * * if (pa_mcalign_pop(m, &output) < 0) * break; @@ -61,17 +61,17 @@ * pa_memchunk_free(a); * */ -struct pa_mcalign; +typedef struct pa_mcalign pa_mcalign; -struct pa_mcalign *pa_mcalign_new(size_t base, struct pa_memblock_stat *s); -void pa_mcalign_free(struct pa_mcalign *m); +pa_mcalign *pa_mcalign_new(size_t base, pa_memblock_stat *s); +void pa_mcalign_free(pa_mcalign *m); /* Push a new memchunk into the aligner. The caller of this routine * has to free the memchunk by himself. */ -void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c); +void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c); /* Pop a new memchunk from the aligner. Returns 0 when sucessful, * nonzero otherwise. */ -int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c); +int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c); #endif diff --git a/polyp/memblock.c b/polyp/memblock.c index c070bee65..8da535252 100644 --- a/polyp/memblock.c +++ b/polyp/memblock.c @@ -31,7 +31,7 @@ #include "memblock.h" #include "xmalloc.h" -static void stat_add(struct pa_memblock*m, struct pa_memblock_stat *s) { +static void stat_add(pa_memblock*m, pa_memblock_stat *s) { assert(m); if (!s) { @@ -46,7 +46,7 @@ static void stat_add(struct pa_memblock*m, struct pa_memblock_stat *s) { s->allocated_size += m->length; } -static void stat_remove(struct pa_memblock *m) { +static void stat_remove(pa_memblock *m) { assert(m); if (!m->stat) @@ -59,8 +59,8 @@ static void stat_remove(struct pa_memblock *m) { m->stat = NULL; } -struct pa_memblock *pa_memblock_new(size_t length, struct pa_memblock_stat*s) { - struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)+length); +pa_memblock *pa_memblock_new(size_t length, pa_memblock_stat*s) { + pa_memblock *b = pa_xmalloc(sizeof(pa_memblock)+length); b->type = PA_MEMBLOCK_APPENDED; b->ref = 1; b->length = length; @@ -71,8 +71,8 @@ struct pa_memblock *pa_memblock_new(size_t length, struct pa_memblock_stat*s) { return b; } -struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length, struct pa_memblock_stat*s) { - struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)); +pa_memblock *pa_memblock_new_dynamic(void *d, size_t length, pa_memblock_stat*s) { + pa_memblock *b = pa_xmalloc(sizeof(pa_memblock)); b->type = PA_MEMBLOCK_DYNAMIC; b->ref = 1; b->length = length; @@ -83,8 +83,8 @@ struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length, struct pa_me return b; } -struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length, int read_only, struct pa_memblock_stat*s) { - struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)); +pa_memblock *pa_memblock_new_fixed(void *d, size_t length, int read_only, pa_memblock_stat*s) { + pa_memblock *b = pa_xmalloc(sizeof(pa_memblock)); b->type = PA_MEMBLOCK_FIXED; b->ref = 1; b->length = length; @@ -95,10 +95,10 @@ struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length, int read_only, return b; } -struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p), int read_only, struct pa_memblock_stat*s) { - struct pa_memblock *b; +pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p), int read_only, pa_memblock_stat*s) { + pa_memblock *b; assert(d && length && free_cb); - b = pa_xmalloc(sizeof(struct pa_memblock)); + b = pa_xmalloc(sizeof(pa_memblock)); b->type = PA_MEMBLOCK_USER; b->ref = 1; b->length = length; @@ -109,13 +109,13 @@ struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb) return b; } -struct pa_memblock* pa_memblock_ref(struct pa_memblock*b) { +pa_memblock* pa_memblock_ref(pa_memblock*b) { assert(b && b->ref >= 1); b->ref++; return b; } -void pa_memblock_unref(struct pa_memblock*b) { +void pa_memblock_unref(pa_memblock*b) { assert(b && b->ref >= 1); if ((--(b->ref)) == 0) { @@ -131,7 +131,7 @@ void pa_memblock_unref(struct pa_memblock*b) { } } -void pa_memblock_unref_fixed(struct pa_memblock *b) { +void pa_memblock_unref_fixed(pa_memblock *b) { assert(b && b->ref >= 1 && b->type == PA_MEMBLOCK_FIXED); if (b->ref == 1) @@ -143,17 +143,17 @@ void pa_memblock_unref_fixed(struct pa_memblock *b) { } } -struct pa_memblock_stat* pa_memblock_stat_new(void) { - struct pa_memblock_stat *s; +pa_memblock_stat* pa_memblock_stat_new(void) { + pa_memblock_stat *s; - s = pa_xmalloc(sizeof(struct pa_memblock_stat)); + s = pa_xmalloc(sizeof(pa_memblock_stat)); s->ref = 1; s->total = s->total_size = s->allocated = s->allocated_size = 0; return s; } -void pa_memblock_stat_unref(struct pa_memblock_stat *s) { +void pa_memblock_stat_unref(pa_memblock_stat *s) { assert(s && s->ref >= 1); if (!(--(s->ref))) { @@ -162,7 +162,7 @@ void pa_memblock_stat_unref(struct pa_memblock_stat *s) { } } -struct pa_memblock_stat * pa_memblock_stat_ref(struct pa_memblock_stat *s) { +pa_memblock_stat * pa_memblock_stat_ref(pa_memblock_stat *s) { assert(s); s->ref++; return s; diff --git a/polyp/memblock.h b/polyp/memblock.h index 8555954cd..cbf5d6843 100644 --- a/polyp/memblock.h +++ b/polyp/memblock.h @@ -31,58 +31,57 @@ * memory blocks. */ /* The type of memory this block points to */ -enum pa_memblock_type { +typedef enum { PA_MEMBLOCK_FIXED, /* data is a pointer to fixed memory that needs not to be freed */ PA_MEMBLOCK_APPENDED, /* The most common kind: the data is appended to the memory block */ PA_MEMBLOCK_DYNAMIC, /* data is a pointer to some memory allocated with pa_xmalloc() */ PA_MEMBLOCK_USER /* User supplied memory, to be freed with free_cb */ -}; +} pa_memblock_type ; /* A structure of keeping memory block statistics */ -struct pa_memblock_stat; - -struct pa_memblock { - enum pa_memblock_type type; - unsigned ref; /* the reference counter */ - int read_only; /* boolean */ - size_t length; - void *data; - void (*free_cb)(void *p); /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ - struct pa_memblock_stat *stat; -}; - -/* Allocate a new memory block of type PA_MEMBLOCK_APPENDED */ -struct pa_memblock *pa_memblock_new(size_t length, struct pa_memblock_stat*s); - -/* Allocate a new memory block of type PA_MEMBLOCK_DYNAMIC. The pointer data is to be maintained be the memory block */ -struct pa_memblock *pa_memblock_new_dynamic(void *data, size_t length, struct pa_memblock_stat*s); - -/* Allocate a new memory block of type PA_MEMBLOCK_FIXED */ -struct pa_memblock *pa_memblock_new_fixed(void *data, size_t length, int read_only, struct pa_memblock_stat*s); - -/* Allocate a new memory block of type PA_MEMBLOCK_USER */ -struct pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p), int read_only, struct pa_memblock_stat*s); - -void pa_memblock_unref(struct pa_memblock*b); -struct pa_memblock* pa_memblock_ref(struct pa_memblock*b); - -/* This special unref function has to be called by the owner of the -memory of a static memory block when he wants to release all -references to the memory. This causes the memory to be copied and -converted into a PA_MEMBLOCK_DYNAMIC type memory block */ -void pa_memblock_unref_fixed(struct pa_memblock*b); - -/* Matinatins statistics about memory blocks */ -struct pa_memblock_stat { +/* Maintains statistics about memory blocks */ +typedef struct pa_memblock_stat { int ref; unsigned total; unsigned total_size; unsigned allocated; unsigned allocated_size; -}; +} pa_memblock_stat; -struct pa_memblock_stat* pa_memblock_stat_new(void); -void pa_memblock_stat_unref(struct pa_memblock_stat *s); -struct pa_memblock_stat * pa_memblock_stat_ref(struct pa_memblock_stat *s); +typedef struct pa_memblock { + pa_memblock_type type; + unsigned ref; /* the reference counter */ + int read_only; /* boolean */ + size_t length; + void *data; + void (*free_cb)(void *p); /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ + pa_memblock_stat *stat; +} pa_memblock; + +/* Allocate a new memory block of type PA_MEMBLOCK_APPENDED */ +pa_memblock *pa_memblock_new(size_t length, pa_memblock_stat*s); + +/* Allocate a new memory block of type PA_MEMBLOCK_DYNAMIC. The pointer data is to be maintained be the memory block */ +pa_memblock *pa_memblock_new_dynamic(void *data, size_t length, pa_memblock_stat*s); + +/* Allocate a new memory block of type PA_MEMBLOCK_FIXED */ +pa_memblock *pa_memblock_new_fixed(void *data, size_t length, int read_only, pa_memblock_stat*s); + +/* Allocate a new memory block of type PA_MEMBLOCK_USER */ +pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p), int read_only, pa_memblock_stat*s); + +void pa_memblock_unref(pa_memblock*b); +pa_memblock* pa_memblock_ref(pa_memblock*b); + +/* This special unref function has to be called by the owner of the +memory of a static memory block when he wants to release all +references to the memory. This causes the memory to be copied and +converted into a PA_MEMBLOCK_DYNAMIC type memory block */ +void pa_memblock_unref_fixed(pa_memblock*b); + + +pa_memblock_stat* pa_memblock_stat_new(void); +void pa_memblock_stat_unref(pa_memblock_stat *s); +pa_memblock_stat * pa_memblock_stat_ref(pa_memblock_stat *s); #endif diff --git a/polyp/memblockq.c b/polyp/memblockq.c index 3f2e4db1d..ba6b76eaa 100644 --- a/polyp/memblockq.c +++ b/polyp/memblockq.c @@ -37,22 +37,22 @@ struct memblock_list { struct memblock_list *next, *prev; - struct pa_memchunk chunk; + pa_memchunk chunk; }; struct pa_memblockq { struct memblock_list *blocks, *blocks_tail; unsigned n_blocks; size_t current_length, maxlength, tlength, base, prebuf, orig_prebuf, minreq; - struct pa_mcalign *mcalign; - struct pa_memblock_stat *memblock_stat; + pa_mcalign *mcalign; + pa_memblock_stat *memblock_stat; }; -struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t base, size_t prebuf, size_t minreq, struct pa_memblock_stat *s) { - struct pa_memblockq* bq; +pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t base, size_t prebuf, size_t minreq, pa_memblock_stat *s) { + pa_memblockq* bq; assert(maxlength && base && maxlength); - bq = pa_xmalloc(sizeof(struct pa_memblockq)); + bq = pa_xmalloc(sizeof(pa_memblockq)); bq->blocks = bq->blocks_tail = 0; bq->n_blocks = 0; @@ -92,7 +92,7 @@ struct pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t b return bq; } -void pa_memblockq_free(struct pa_memblockq* bq) { +void pa_memblockq_free(pa_memblockq* bq) { assert(bq); pa_memblockq_flush(bq); @@ -103,7 +103,7 @@ void pa_memblockq_free(struct pa_memblockq* bq) { pa_xfree(bq); } -void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta) { +void pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *chunk, size_t delta) { struct memblock_list *q; assert(bq && chunk && chunk->memblock && chunk->length && (chunk->length % bq->base) == 0); @@ -138,7 +138,7 @@ void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, pa_memblockq_shorten(bq, bq->maxlength); } -int pa_memblockq_peek(struct pa_memblockq* bq, struct pa_memchunk *chunk) { +int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { assert(bq && chunk); if (!bq->blocks || bq->current_length < bq->prebuf) @@ -152,17 +152,17 @@ int pa_memblockq_peek(struct pa_memblockq* bq, struct pa_memchunk *chunk) { return 0; } -void pa_memblockq_drop(struct pa_memblockq *bq, const struct pa_memchunk *chunk, size_t length) { +void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length) { assert(bq && chunk && length); - if (!bq->blocks || memcmp(&bq->blocks->chunk, chunk, sizeof(struct pa_memchunk))) + if (!bq->blocks || memcmp(&bq->blocks->chunk, chunk, sizeof(pa_memchunk))) return; assert(length <= bq->blocks->chunk.length); pa_memblockq_skip(bq, length); } -static void remove_block(struct pa_memblockq *bq, struct memblock_list *q) { +static void remove_block(pa_memblockq *bq, struct memblock_list *q) { assert(bq && q); if (q->prev) @@ -185,7 +185,7 @@ static void remove_block(struct pa_memblockq *bq, struct memblock_list *q) { bq->n_blocks--; } -void pa_memblockq_skip(struct pa_memblockq *bq, size_t length) { +void pa_memblockq_skip(pa_memblockq *bq, size_t length) { assert(bq && length && (length % bq->base) == 0); while (length > 0) { @@ -206,7 +206,7 @@ void pa_memblockq_skip(struct pa_memblockq *bq, size_t length) { } } -void pa_memblockq_shorten(struct pa_memblockq *bq, size_t length) { +void pa_memblockq_shorten(pa_memblockq *bq, size_t length) { size_t l; assert(bq); @@ -223,29 +223,29 @@ void pa_memblockq_shorten(struct pa_memblockq *bq, size_t length) { } -void pa_memblockq_empty(struct pa_memblockq *bq) { +void pa_memblockq_empty(pa_memblockq *bq) { assert(bq); pa_memblockq_shorten(bq, 0); } -int pa_memblockq_is_readable(struct pa_memblockq *bq) { +int pa_memblockq_is_readable(pa_memblockq *bq) { assert(bq); return bq->current_length && (bq->current_length >= bq->prebuf); } -int pa_memblockq_is_writable(struct pa_memblockq *bq, size_t length) { +int pa_memblockq_is_writable(pa_memblockq *bq, size_t length) { assert(bq); return bq->current_length + length <= bq->tlength; } -uint32_t pa_memblockq_get_length(struct pa_memblockq *bq) { +uint32_t pa_memblockq_get_length(pa_memblockq *bq) { assert(bq); return bq->current_length; } -uint32_t pa_memblockq_missing(struct pa_memblockq *bq) { +uint32_t pa_memblockq_missing(pa_memblockq *bq) { size_t l; assert(bq); @@ -258,8 +258,8 @@ uint32_t pa_memblockq_missing(struct pa_memblockq *bq) { return (l >= bq->minreq) ? l : 0; } -void pa_memblockq_push_align(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta) { - struct pa_memchunk rchunk; +void pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk, size_t delta) { + pa_memchunk rchunk; assert(bq && chunk && bq->base); if (bq->base == 1) { @@ -281,22 +281,22 @@ void pa_memblockq_push_align(struct pa_memblockq* bq, const struct pa_memchunk * } } -uint32_t pa_memblockq_get_minreq(struct pa_memblockq *bq) { +uint32_t pa_memblockq_get_minreq(pa_memblockq *bq) { assert(bq); return bq->minreq; } -void pa_memblockq_prebuf_disable(struct pa_memblockq *bq) { +void pa_memblockq_prebuf_disable(pa_memblockq *bq) { assert(bq); bq->prebuf = 0; } -void pa_memblockq_prebuf_reenable(struct pa_memblockq *bq) { +void pa_memblockq_prebuf_reenable(pa_memblockq *bq) { assert(bq); bq->prebuf = bq->orig_prebuf; } -void pa_memblockq_seek(struct pa_memblockq *bq, size_t length) { +void pa_memblockq_seek(pa_memblockq *bq, size_t length) { assert(bq); if (!length) @@ -322,7 +322,7 @@ void pa_memblockq_seek(struct pa_memblockq *bq, size_t length) { } } -void pa_memblockq_flush(struct pa_memblockq *bq) { +void pa_memblockq_flush(pa_memblockq *bq) { struct memblock_list *l; assert(bq); @@ -337,7 +337,7 @@ void pa_memblockq_flush(struct pa_memblockq *bq) { bq->current_length = 0; } -uint32_t pa_memblockq_get_tlength(struct pa_memblockq *bq) { +uint32_t pa_memblockq_get_tlength(pa_memblockq *bq) { assert(bq); return bq->tlength; } diff --git a/polyp/memblockq.h b/polyp/memblockq.h index 2c762bf4c..1695dabad 100644 --- a/polyp/memblockq.h +++ b/polyp/memblockq.h @@ -33,7 +33,7 @@ * type doesn't need to copy any data around, it just maintains * references to reference counted memory blocks. */ -struct pa_memblockq; +typedef struct pa_memblockq pa_memblockq; /* Parameters: - maxlength: maximum length of queue. If more data is pushed into the queue, data from the front is dropped @@ -42,63 +42,63 @@ struct pa_memblockq; - prebuf: before passing the first byte out, make sure that enough bytes are in the queue - minreq: pa_memblockq_missing() will only return values greater than this value */ -struct pa_memblockq* pa_memblockq_new(size_t maxlength, +pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t base, size_t prebuf, size_t minreq, - struct pa_memblock_stat *s); -void pa_memblockq_free(struct pa_memblockq*bq); + pa_memblock_stat *s); +void pa_memblockq_free(pa_memblockq*bq); /* Push a new memory chunk into the queue. Optionally specify a value for future cancellation. */ -void pa_memblockq_push(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta); +void pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *chunk, size_t delta); /* Same as pa_memblockq_push(), however chunks are filtered through a mcalign object, and thus aligned to multiples of base */ -void pa_memblockq_push_align(struct pa_memblockq* bq, const struct pa_memchunk *chunk, size_t delta); +void pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk, size_t delta); /* Return a copy of the next memory chunk in the queue. It is not removed from the queue */ -int pa_memblockq_peek(struct pa_memblockq* bq, struct pa_memchunk *chunk); +int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk); /* Drop the specified bytes from the queue, only valid aufter pa_memblockq_peek() */ -void pa_memblockq_drop(struct pa_memblockq *bq, const struct pa_memchunk *chunk, size_t length); +void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length); /* Drop the specified bytes from the queue */ -void pa_memblockq_skip(struct pa_memblockq *bq, size_t length); +void pa_memblockq_skip(pa_memblockq *bq, size_t length); /* Shorten the pa_memblockq to the specified length by dropping data at the end of the queue */ -void pa_memblockq_shorten(struct pa_memblockq *bq, size_t length); +void pa_memblockq_shorten(pa_memblockq *bq, size_t length); /* Empty the pa_memblockq */ -void pa_memblockq_empty(struct pa_memblockq *bq); +void pa_memblockq_empty(pa_memblockq *bq); /* Test if the pa_memblockq is currently readable, that is, more data than base */ -int pa_memblockq_is_readable(struct pa_memblockq *bq); +int pa_memblockq_is_readable(pa_memblockq *bq); /* Test if the pa_memblockq is currently writable for the specified amount of bytes */ -int pa_memblockq_is_writable(struct pa_memblockq *bq, size_t length); +int pa_memblockq_is_writable(pa_memblockq *bq, size_t length); /* Return the length of the queue in bytes */ -uint32_t pa_memblockq_get_length(struct pa_memblockq *bq); +uint32_t pa_memblockq_get_length(pa_memblockq *bq); /* Return how many bytes are missing in queue to the specified fill amount */ -uint32_t pa_memblockq_missing(struct pa_memblockq *bq); +uint32_t pa_memblockq_missing(pa_memblockq *bq); /* Returns the minimal request value */ -uint32_t pa_memblockq_get_minreq(struct pa_memblockq *bq); +uint32_t pa_memblockq_get_minreq(pa_memblockq *bq); /* Force disabling of pre-buf even when the pre-buffer is not yet filled */ -void pa_memblockq_prebuf_disable(struct pa_memblockq *bq); +void pa_memblockq_prebuf_disable(pa_memblockq *bq); /* Reenable pre-buf to the initial level */ -void pa_memblockq_prebuf_reenable(struct pa_memblockq *bq); +void pa_memblockq_prebuf_reenable(pa_memblockq *bq); /* Manipulate the write pointer */ -void pa_memblockq_seek(struct pa_memblockq *bq, size_t delta); +void pa_memblockq_seek(pa_memblockq *bq, size_t delta); /* Flush the queue */ -void pa_memblockq_flush(struct pa_memblockq *bq); +void pa_memblockq_flush(pa_memblockq *bq); /* Get Target length */ -uint32_t pa_memblockq_get_tlength(struct pa_memblockq *bq); +uint32_t pa_memblockq_get_tlength(pa_memblockq *bq); #endif diff --git a/polyp/memchunk.c b/polyp/memchunk.c index d1c923f3c..bfd74f9e4 100644 --- a/polyp/memchunk.c +++ b/polyp/memchunk.c @@ -31,8 +31,8 @@ #include "memchunk.h" #include "xmalloc.h" -void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s, size_t min) { - struct pa_memblock *n; +void pa_memchunk_make_writable(pa_memchunk *c, pa_memblock_stat *s, size_t min) { + pa_memblock *n; size_t l; assert(c && c->memblock && c->memblock->ref >= 1); @@ -50,7 +50,7 @@ void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s c->index = 0; } -void pa_memchunk_reset(struct pa_memchunk *c) { +void pa_memchunk_reset(pa_memchunk *c) { assert(c); c->memblock = NULL; diff --git a/polyp/memchunk.h b/polyp/memchunk.h index a004c2e84..4eefc8c10 100644 --- a/polyp/memchunk.h +++ b/polyp/memchunk.h @@ -24,22 +24,22 @@ #include "memblock.h" -/* A memchunk is a part of a memblock. In contrast to the memblock, a +/* A memchunk describes a part of a memblock. In contrast to the memblock, a * memchunk is not allocated dynamically or reference counted, instead * it is usually stored on the stack and copied around */ -struct pa_memchunk { - struct pa_memblock *memblock; +typedef struct pa_memchunk { + pa_memblock *memblock; size_t index, length; -}; +} pa_memchunk; /* Make a memchunk writable, i.e. make sure that the caller may have * exclusive access to the memblock and it is not read_only. If needed * the memblock in the structure is replaced by a copy. */ -void pa_memchunk_make_writable(struct pa_memchunk *c, struct pa_memblock_stat *s, size_t min); +void pa_memchunk_make_writable(pa_memchunk *c, pa_memblock_stat *s, size_t min); /* Invalidate a memchunk. This does not free the cotaining memblock, * but sets all members to zero. */ -void pa_memchunk_reset(struct pa_memchunk *c); +void pa_memchunk_reset(pa_memchunk *c); #endif diff --git a/polyp/modargs.c b/polyp/modargs.c index 9437d839b..070629467 100644 --- a/polyp/modargs.c +++ b/polyp/modargs.c @@ -38,13 +38,11 @@ #include "xmalloc.h" #include "util.h" -struct pa_modargs; - struct entry { char *key, *value; }; -static int add_key_value(struct pa_hashmap *map, char *key, char *value, const char* const valid_keys[]) { +static int add_key_value(pa_hashmap *map, char *key, char *value, const char* const valid_keys[]) { struct entry *e; assert(map && key && value); @@ -68,8 +66,8 @@ static int add_key_value(struct pa_hashmap *map, char *key, char *value, const c return 0; } -struct pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) { - struct pa_hashmap *map = NULL; +pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) { + pa_hashmap *map = NULL; map = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); assert(map); @@ -154,18 +152,18 @@ struct pa_modargs *pa_modargs_new(const char *args, const char* const* valid_key goto fail; } - return (struct pa_modargs*) map; + return (pa_modargs*) map; fail: if (map) - pa_modargs_free((struct pa_modargs*) map); + pa_modargs_free((pa_modargs*) map); return NULL; } -static void free_func(void *p, void*userdata) { +static void free_func(void *p, PA_GCC_UNUSED void*userdata) { struct entry *e = p; assert(e); pa_xfree(e->key); @@ -173,13 +171,13 @@ static void free_func(void *p, void*userdata) { pa_xfree(e); } -void pa_modargs_free(struct pa_modargs*ma) { - struct pa_hashmap *map = (struct pa_hashmap*) ma; +void pa_modargs_free(pa_modargs*ma) { + pa_hashmap *map = (pa_hashmap*) ma; pa_hashmap_free(map, free_func, NULL); } -const char *pa_modargs_get_value(struct pa_modargs *ma, const char *key, const char *def) { - struct pa_hashmap *map = (struct pa_hashmap*) ma; +const char *pa_modargs_get_value(pa_modargs *ma, const char *key, const char *def) { + pa_hashmap *map = (pa_hashmap*) ma; struct entry*e; if (!(e = pa_hashmap_get(map, key))) @@ -188,7 +186,7 @@ const char *pa_modargs_get_value(struct pa_modargs *ma, const char *key, const c return e->value; } -int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *value) { +int pa_modargs_get_value_u32(pa_modargs *ma, const char *key, uint32_t *value) { const char *v; assert(ma && key && value); @@ -201,7 +199,7 @@ int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *v return 0; } -int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *value) { +int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value) { const char *v; assert(ma && key && value); @@ -214,7 +212,7 @@ int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *va return 0; } -int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *value) { +int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value) { const char *v; int r; assert(ma && key && value); @@ -232,10 +230,10 @@ int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *va return 0; } -int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss) { +int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) { const char *format; uint32_t channels; - struct pa_sample_spec ss; + pa_sample_spec ss; assert(ma && rss); /* DEBUG_TRAP;*/ diff --git a/polyp/modargs.h b/polyp/modargs.h index 07db6ae50..566053795 100644 --- a/polyp/modargs.h +++ b/polyp/modargs.h @@ -26,24 +26,24 @@ #include "sample.h" #include "core.h" -struct pa_modargs; +typedef struct pa_modargs pa_modargs; /* A generic parser for module arguments */ /* Parse the string args. The NULL-terminated array keys contains all valid arguments. */ -struct pa_modargs *pa_modargs_new(const char *args, const char* const keys[]); -void pa_modargs_free(struct pa_modargs*ma); +pa_modargs *pa_modargs_new(const char *args, const char* const keys[]); +void pa_modargs_free(pa_modargs*ma); /* Return the module argument for the specified name as a string. If * the argument was not specified, return def instead.*/ -const char *pa_modargs_get_value(struct pa_modargs *ma, const char *key, const char *def); +const char *pa_modargs_get_value(pa_modargs *ma, const char *key, const char *def); /* Return a module argument as unsigned 32bit value in *value */ -int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *value); -int pa_modargs_get_value_s32(struct pa_modargs *ma, const char *key, int32_t *value); -int pa_modargs_get_value_boolean(struct pa_modargs *ma, const char *key, int *value); +int pa_modargs_get_value_u32(pa_modargs *ma, const char *key, uint32_t *value); +int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value); +int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value); /* Return sample spec data from the three arguments "rate", "format" and "channels" */ -int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *ss); +int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *ss); #endif diff --git a/polyp/modinfo.c b/polyp/modinfo.c index a96bb17e2..534406127 100644 --- a/polyp/modinfo.c +++ b/polyp/modinfo.c @@ -36,12 +36,12 @@ #define PA_SYMBOL_USAGE "pa__get_usage" #define PA_SYMBOL_VERSION "pa__get_version" -struct pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) { - struct pa_modinfo *i; +pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) { + pa_modinfo *i; const char* (*func)(void); assert(dl); - i = pa_xmalloc0(sizeof(struct pa_modinfo)); + i = pa_xmalloc0(sizeof(pa_modinfo)); if ((func = (const char* (*)(void)) lt_dlsym(dl, PA_SYMBOL_AUTHOR))) i->author = pa_xstrdup(func()); @@ -58,9 +58,9 @@ struct pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) { return i; } -struct pa_modinfo *pa_modinfo_get_by_name(const char *name) { +pa_modinfo *pa_modinfo_get_by_name(const char *name) { lt_dlhandle dl; - struct pa_modinfo *i; + pa_modinfo *i; assert(name); if (!(dl = lt_dlopenext(name))) { @@ -74,7 +74,7 @@ struct pa_modinfo *pa_modinfo_get_by_name(const char *name) { return i; } -void pa_modinfo_free(struct pa_modinfo *i) { +void pa_modinfo_free(pa_modinfo *i) { assert(i); pa_xfree(i->author); pa_xfree(i->description); diff --git a/polyp/modinfo.h b/polyp/modinfo.h index 9da9dc4eb..531761475 100644 --- a/polyp/modinfo.h +++ b/polyp/modinfo.h @@ -24,20 +24,20 @@ /* Some functions for reading module meta data from Polypaudio modules */ -struct pa_modinfo { +typedef struct pa_modinfo { char *author; char *description; char *usage; char *version; -}; +} pa_modinfo; /* Read meta data from an libtool handle */ -struct pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl); +pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl); /* Read meta data from a module file */ -struct pa_modinfo *pa_modinfo_get_by_name(const char *name); +pa_modinfo *pa_modinfo_get_by_name(const char *name); /* Free meta data */ -void pa_modinfo_free(struct pa_modinfo *i); +void pa_modinfo_free(pa_modinfo *i); #endif diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index dde5d8b69..14070d635 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -55,13 +55,13 @@ PA_MODULE_USAGE("sink_name= device= format=module, - (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0)); + (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0)); } static void xrun_recovery(struct userdata *u) { @@ -99,7 +99,7 @@ static void do_write(struct userdata *u) { update_usage(u); for (;;) { - struct pa_memchunk *memchunk = NULL; + pa_memchunk *memchunk = NULL; snd_pcm_sframes_t frames; if (u->memchunk.memblock) @@ -142,7 +142,7 @@ static void do_write(struct userdata *u) { } } -static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { +static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; assert(u && a && e); @@ -152,7 +152,7 @@ static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, do_write(u); } -static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(pa_sink *s) { pa_usec_t r = 0; struct userdata *u = s->userdata; snd_pcm_sframes_t frames; @@ -175,12 +175,12 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { return r; } -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_modargs *ma = NULL; +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; int ret = -1; struct userdata *u = NULL; const char *dev; - struct pa_sample_spec ss; + pa_sample_spec ss; uint32_t periods, fragsize; snd_pcm_uframes_t period_size; size_t frame_size; @@ -262,7 +262,7 @@ fail: goto finish; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 5b4076f87..4ad8dd84c 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -55,13 +55,13 @@ PA_MODULE_USAGE("source_name= device= format=< struct userdata { snd_pcm_t *pcm_handle; - struct pa_source *source; - struct pa_io_event **io_events; + pa_source *source; + pa_io_event **io_events; unsigned n_io_events; size_t frame_size, fragment_size; - struct pa_memchunk memchunk; - struct pa_module *module; + pa_memchunk memchunk; + pa_module *module; }; static const char* const valid_modargs[] = { @@ -80,7 +80,7 @@ static const char* const valid_modargs[] = { static void update_usage(struct userdata *u) { pa_module_set_used(u->module, - (u->source ? pa_idxset_ncontents(u->source->outputs) : 0)); + (u->source ? pa_idxset_size(u->source->outputs) : 0)); } static void xrun_recovery(struct userdata *u) { @@ -98,7 +98,7 @@ static void do_read(struct userdata *u) { update_usage(u); for (;;) { - struct pa_memchunk post_memchunk; + pa_memchunk post_memchunk; snd_pcm_sframes_t frames; size_t l; @@ -142,7 +142,7 @@ static void do_read(struct userdata *u) { } } -static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { +static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; assert(u && a && e); @@ -152,7 +152,7 @@ static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, do_read(u); } -static pa_usec_t source_get_latency_cb(struct pa_source *s) { +static pa_usec_t source_get_latency_cb(pa_source *s) { struct userdata *u = s->userdata; snd_pcm_sframes_t frames; assert(s && u && u->source); @@ -166,12 +166,12 @@ static pa_usec_t source_get_latency_cb(struct pa_source *s) { return pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); } -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_modargs *ma = NULL; +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; int ret = -1; struct userdata *u = NULL; const char *dev; - struct pa_sample_spec ss; + pa_sample_spec ss; unsigned periods, fragsize; snd_pcm_uframes_t period_size; size_t frame_size; @@ -250,7 +250,7 @@ fail: goto finish; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-cli.c b/polyp/module-cli.c index 7d278f90b..db0e895ce 100644 --- a/polyp/module-cli.c +++ b/polyp/module-cli.c @@ -39,15 +39,15 @@ PA_MODULE_DESCRIPTION("Command line interface") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("No arguments") -static void eof_cb(struct pa_cli*c, void *userdata) { - struct pa_module *m = userdata; +static void eof_cb(pa_cli*c, void *userdata) { + pa_module *m = userdata; assert(c && m); pa_module_unload_request(m); } -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_iochannel *io; +int pa__init(pa_core *c, pa_module*m) { + pa_iochannel *io; assert(c && m); if (c->running_as_daemon) { @@ -77,7 +77,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { return 0; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { assert(c && m); if (c->running_as_daemon == 0) { diff --git a/polyp/module-combine.c b/polyp/module-combine.c index 7283c5549..cee0a5dc3 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -62,20 +62,20 @@ static const char* const valid_modargs[] = { struct output { struct userdata *userdata; - struct pa_sink_input *sink_input; + pa_sink_input *sink_input; size_t counter; - struct pa_memblockq *memblockq; + pa_memblockq *memblockq; pa_usec_t total_latency; PA_LLIST_FIELDS(struct output); }; struct userdata { - struct pa_module *module; - struct pa_core *core; - struct pa_sink *sink; + pa_module *module; + pa_core *core; + pa_sink *sink; unsigned n_outputs; struct output *master; - struct pa_time_event *time_event; + pa_time_event *time_event; uint32_t adjust_time; PA_LLIST_HEAD(struct output, outputs); @@ -86,8 +86,8 @@ static void clear_up(struct userdata *u); static void update_usage(struct userdata *u) { pa_module_set_used(u->module, - (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0)); + (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0)); } @@ -135,7 +135,7 @@ static void adjust_rates(struct userdata *u) { } static void request_memblock(struct userdata *u) { - struct pa_memchunk chunk; + pa_memchunk chunk; struct output *o; assert(u && u->sink); @@ -150,7 +150,7 @@ static void request_memblock(struct userdata *u) { pa_memblock_unref(chunk.memblock); } -static void time_callback(struct pa_mainloop_api*a, struct pa_time_event* e, const struct timeval *tv, void *userdata) { +static void time_callback(pa_mainloop_api*a, pa_time_event* e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { struct userdata *u = userdata; struct timeval n; assert(u && a && u->time_event == e); @@ -162,7 +162,7 @@ static void time_callback(struct pa_mainloop_api*a, struct pa_time_event* e, con u->sink->core->mainloop->time_restart(e, &n); } -static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { struct output *o = i->userdata; assert(i && o && o->sink_input && chunk); @@ -175,7 +175,7 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk return pa_memblockq_peek(o->memblockq, chunk); } -static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { +static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { struct output *o = i->userdata; assert(i && o && o->sink_input && chunk && length); @@ -183,28 +183,28 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk o->counter += length; } -static void sink_input_kill_cb(struct pa_sink_input *i) { +static void sink_input_kill_cb(pa_sink_input *i) { struct output *o = i->userdata; assert(i && o && o->sink_input); pa_module_unload_request(o->userdata->module); clear_up(o->userdata); } -static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { +static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { struct output *o = i->userdata; assert(i && o && o->sink_input); return pa_bytes_to_usec(pa_memblockq_get_length(o->memblockq), &i->sample_spec); } -static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(pa_sink *s) { struct userdata *u = s->userdata; assert(s && u && u->sink && u->master); return pa_sink_input_get_latency(u->master->sink_input); } -static struct output *output_new(struct userdata *u, struct pa_sink *sink, int resample_method) { +static struct output *output_new(struct userdata *u, pa_sink *sink, int resample_method) { struct output *o = NULL; char t[256]; assert(u && sink && u->sink); @@ -278,11 +278,11 @@ static void clear_up(struct userdata *u) { } } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct userdata *u; - struct pa_modargs *ma = NULL; + pa_modargs *ma = NULL; const char *master_name, *slaves, *rm; - struct pa_sink *master_sink; + pa_sink *master_sink; char *n = NULL; const char*split_state; struct timeval tv; @@ -344,7 +344,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { split_state = NULL; while ((n = pa_split(slaves, ",", &split_state))) { - struct pa_sink *slave_sink; + pa_sink *slave_sink; if (!(slave_sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) { pa_log(__FILE__": invalid slave sink '%s'\n", n); @@ -381,7 +381,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-defs.h.m4 b/polyp/module-defs.h.m4 index 2b9cdf9e2..2eff25a72 100644 --- a/polyp/module-defs.h.m4 +++ b/polyp/module-defs.h.m4 @@ -21,4 +21,9 @@ gen_symbol(pa__get_version) int pa__init(struct pa_core *c, struct pa_module*m); void pa__done(struct pa_core *c, struct pa_module*m); +const char* pa__get_author(void); +const char* pa__get_description(void); +const char* pa__get_usage(void); +const char* pa__get_version(void); + #endif diff --git a/polyp/module-esound-compat-spawnfd.c b/polyp/module-esound-compat-spawnfd.c index de2cf4e63..5051e4d00 100644 --- a/polyp/module-esound-compat-spawnfd.c +++ b/polyp/module-esound-compat-spawnfd.c @@ -44,8 +44,8 @@ static const char* const valid_modargs[] = { NULL, }; -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_modargs *ma = NULL; +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; int ret = -1, fd = -1; char x = 1; assert(c && m); @@ -73,7 +73,7 @@ finish: return ret; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { assert(c && m); } diff --git a/polyp/module-esound-compat-spawnpid.c b/polyp/module-esound-compat-spawnpid.c index 6f945728e..aa8b0f822 100644 --- a/polyp/module-esound-compat-spawnpid.c +++ b/polyp/module-esound-compat-spawnpid.c @@ -44,8 +44,8 @@ static const char* const valid_modargs[] = { NULL, }; -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_modargs *ma = NULL; +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; int ret = -1; uint32_t pid = 0; assert(c && m); @@ -71,7 +71,7 @@ finish: return ret; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { assert(c && m); } diff --git a/polyp/module-esound-sink.c b/polyp/module-esound-sink.c index 191065069..ac211a316 100644 --- a/polyp/module-esound-sink.c +++ b/polyp/module-esound-sink.c @@ -55,16 +55,16 @@ PA_MODULE_USAGE("sink_name= server=
    cookie=write_index = u->write_length = 0; } } else if (u->state == STATE_RUNNING) { - pa_module_set_used(u->module, pa_idxset_ncontents(u->sink->inputs) + pa_idxset_ncontents(u->sink->monitor_source->outputs)); + pa_module_set_used(u->module, pa_idxset_size(u->sink->inputs) + pa_idxset_size(u->sink->monitor_source->outputs)); if (!u->memchunk.length) if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0) @@ -269,7 +269,7 @@ static void do_work(struct userdata *u) { cancel(u); } -static void notify_cb(struct pa_sink*s) { +static void notify_cb(pa_sink*s) { struct userdata *u = s->userdata; assert(s && u); @@ -277,7 +277,7 @@ static void notify_cb(struct pa_sink*s) { u->core->mainloop->defer_enable(u->defer_event, 1); } -static pa_usec_t get_latency_cb(struct pa_sink *s) { +static pa_usec_t get_latency_cb(pa_sink *s) { struct userdata *u = s->userdata; assert(s && u); @@ -286,19 +286,19 @@ static pa_usec_t get_latency_cb(struct pa_sink *s) { (u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0); } -static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata) { +static void defer_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event*e, void *userdata) { struct userdata *u = userdata; assert(u); do_work(u); } -static void io_callback(struct pa_iochannel *io, void*userdata) { +static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { struct userdata *u = userdata; assert(u); do_work(u); } -static void on_connection(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata) { +static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, void *userdata) { struct userdata *u = userdata; pa_socket_client_unref(u->client); @@ -314,11 +314,11 @@ static void on_connection(struct pa_socket_client *c, struct pa_iochannel*io, vo pa_iochannel_set_callback(u->io, io_callback, u); } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; const char *p; - struct pa_sample_spec ss; - struct pa_modargs *ma = NULL; + pa_sample_spec ss; + pa_modargs *ma = NULL; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -402,7 +402,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-lirc.c b/polyp/module-lirc.c index 4cfc09dee..eb71c47f5 100644 --- a/polyp/module-lirc.c +++ b/polyp/module-lirc.c @@ -52,16 +52,16 @@ static const char* const valid_modargs[] = { struct userdata { int lirc_fd; - struct pa_io_event *io; + pa_io_event *io; struct lirc_config *config; char *sink_name; - struct pa_module *module; + pa_module *module; float mute_toggle_save; }; static int lirc_in_use = 0; -static void io_callback(struct pa_mainloop_api *io, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void*userdata) { +static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags events, void*userdata) { struct userdata *u = userdata; char *name = NULL, *code = NULL; assert(io); @@ -104,7 +104,7 @@ static void io_callback(struct pa_mainloop_api *io, struct pa_io_event *e, int f if (volchange == INVALID) pa_log_warn(__FILE__": recieved unknown IR code '%s'\n", name); else { - struct pa_sink *s; + pa_sink *s; if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name); @@ -147,8 +147,8 @@ fail: free(code); } -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_modargs *ma = NULL; +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; struct userdata *u; assert(c && m); @@ -197,7 +197,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c); assert(m); diff --git a/polyp/module-match.c b/polyp/module-match.c index 3599a830b..e48d55ca0 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -68,7 +68,7 @@ struct rule { struct userdata { struct rule *rules; - struct pa_subscription *subscription; + pa_subscription *subscription; }; static int load_rules(struct userdata *u, const char *filename) { @@ -154,16 +154,16 @@ finish: return ret; } -static void callback(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) { +static void callback(pa_core *c, pa_subscription_event_type t, uint32_t idx, void *userdata) { struct userdata *u = userdata; - struct pa_sink_input *si; + pa_sink_input *si; struct rule *r; assert(c && u); if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW)) return; - if (!(si = pa_idxset_get_by_index(c->sink_inputs, index))) + if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) return; if (!si->name) @@ -177,8 +177,8 @@ static void callback(struct pa_core *c, enum pa_subscription_event_type t, uint3 } } -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_modargs *ma = NULL; +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; struct userdata *u; assert(c && m); @@ -208,7 +208,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata* u; struct rule *r, *n; assert(c && m); diff --git a/polyp/module-mmkbd-evdev.c b/polyp/module-mmkbd-evdev.c index 5368af503..5eb55e35c 100644 --- a/polyp/module-mmkbd-evdev.c +++ b/polyp/module-mmkbd-evdev.c @@ -68,13 +68,13 @@ static const char* const valid_modargs[] = { struct userdata { int fd; - struct pa_io_event *io; + pa_io_event *io; char *sink_name; - struct pa_module *module; + pa_module *module; float mute_toggle_save; }; -static void io_callback(struct pa_mainloop_api *io, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void*userdata) { +static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags events, void*userdata) { struct userdata *u = userdata; assert(io); assert(u); @@ -85,26 +85,26 @@ static void io_callback(struct pa_mainloop_api *io, struct pa_io_event *e, int f } if (events & PA_IO_EVENT_INPUT) { - struct input_event e; + struct input_event ev; - if (pa_loop_read(u->fd, &e, sizeof(e)) <= 0) { + if (pa_loop_read(u->fd, &ev, sizeof(ev)) <= 0) { pa_log(__FILE__": failed to read from event device: %s\n", strerror(errno)); goto fail; } - if (e.type == EV_KEY && (e.value == 1 || e.value == 2)) { + if (ev.type == EV_KEY && (ev.value == 1 || ev.value == 2)) { enum { INVALID, UP, DOWN, MUTE_TOGGLE } volchange = INVALID; - pa_log_debug(__FILE__": key code=%u, value=%u\n", e.code, e.value); + pa_log_debug(__FILE__": key code=%u, value=%u\n", ev.code, ev.value); - switch (e.code) { + switch (ev.code) { case KEY_VOLUMEDOWN: volchange = DOWN; break; case KEY_VOLUMEUP: volchange = UP; break; case KEY_MUTE: volchange = MUTE_TOGGLE; break; } if (volchange != INVALID) { - struct pa_sink *s; + pa_sink *s; if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name); @@ -143,8 +143,8 @@ fail: #define test_bit(bit, array) (array[bit/8] & (1<<(bit%8))) -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_modargs *ma = NULL; +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; struct userdata *u; int version; struct _input_id input_id; @@ -217,7 +217,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c); assert(m); diff --git a/polyp/module-native-protocol-fd.c b/polyp/module-native-protocol-fd.c index 11f6e5720..7f09ff914 100644 --- a/polyp/module-native-protocol-fd.c +++ b/polyp/module-native-protocol-fd.c @@ -45,9 +45,9 @@ static const char* const valid_modargs[] = { NULL, }; -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_iochannel *io; - struct pa_modargs *ma; +int pa__init(pa_core *c, pa_module*m) { + pa_iochannel *io; + pa_modargs *ma; int fd, r = -1; assert(c && m); @@ -77,7 +77,7 @@ finish: return r; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { assert(c && m); pa_protocol_native_free(m->userdata); diff --git a/polyp/module-null-sink.c b/polyp/module-null-sink.c index 6c7a44f28..b26ea50bd 100644 --- a/polyp/module-null-sink.c +++ b/polyp/module-null-sink.c @@ -52,10 +52,10 @@ PA_MODULE_USAGE("format= channels= rate=time_restart(e, &ntv); } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; - struct pa_sample_spec ss; - struct pa_modargs *ma = NULL; + pa_sample_spec ss; + pa_modargs *ma = NULL; struct timeval tv; assert(c && m); @@ -135,7 +135,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 3c5c0ad86..ac510f96c 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -56,10 +56,10 @@ PA_MODULE_USAGE("sink_name= source_name= #define PA_TYPEID_OSS_MMAP PA_TYPEID_MAKE('O', 'S', 'S', 'M') struct userdata { - struct pa_sink *sink; - struct pa_source *source; - struct pa_core *core; - struct pa_sample_spec sample_spec; + pa_sink *sink; + pa_source *source; + pa_core *core; + pa_sample_spec sample_spec; size_t in_fragment_size, out_fragment_size, in_fragments, out_fragments, out_fill; @@ -68,11 +68,11 @@ struct userdata { void *in_mmap, *out_mmap; size_t in_mmap_length, out_mmap_length; - struct pa_io_event *io_event; + pa_io_event *io_event; - struct pa_memblock **in_memblocks, **out_memblocks; + pa_memblock **in_memblocks, **out_memblocks; unsigned out_current, in_current; - struct pa_module *module; + pa_module *module; }; static const char* const valid_modargs[] = { @@ -95,16 +95,16 @@ static const char* const valid_modargs[] = { static void update_usage(struct userdata *u) { pa_module_set_used(u->module, - (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) + - (u->source ? pa_idxset_ncontents(u->source->outputs) : 0)); + (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) + + (u->source ? pa_idxset_size(u->source->outputs) : 0)); } static void out_fill_memblocks(struct userdata *u, unsigned n) { assert(u && u->out_memblocks); while (n > 0) { - struct pa_memchunk chunk; + pa_memchunk chunk; if (u->out_memblocks[u->out_current]) pa_memblock_unref_fixed(u->out_memblocks[u->out_current]); @@ -147,7 +147,7 @@ static void in_post_memblocks(struct userdata *u, unsigned n) { assert(u && u->in_memblocks); while (n > 0) { - struct pa_memchunk chunk; + pa_memchunk chunk; if (!u->in_memblocks[u->in_current]) { chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed((uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, 1, u->core->memblock_stat); @@ -204,7 +204,7 @@ static void do_read(struct userdata *u) { in_clear_memblocks(u, u->in_fragments/2); } -static void io_callback(struct pa_mainloop_api *m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { +static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags f, void *userdata) { struct userdata *u = userdata; assert (u && u->core->mainloop == m && u->io_event == e); @@ -214,7 +214,7 @@ static void io_callback(struct pa_mainloop_api *m, struct pa_io_event *e, int fd do_write(u); } -static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(pa_sink *s) { struct userdata *u = s->userdata; assert(s && u); @@ -222,7 +222,7 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { return pa_bytes_to_usec(u->out_fill, &s->sample_spec); } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; const char *p; @@ -230,7 +230,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { int mode, caps; int enable_bits = 0, zero = 0; int playback = 1, record = 1; - struct pa_modargs *ma = NULL; + pa_modargs *ma = NULL; assert(c && m); m->userdata = u = pa_xmalloc0(sizeof(struct userdata)); @@ -310,7 +310,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) { pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'", p); - u->in_memblocks = pa_xmalloc0(sizeof(struct pa_memblock *)*u->in_fragments); + u->in_memblocks = pa_xmalloc0(sizeof(pa_memblock *)*u->in_fragments); enable_bits |= PCM_ENABLE_INPUT; } @@ -378,7 +378,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 02acc6f46..7c331893f 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -55,18 +55,18 @@ PA_MODULE_USAGE("sink_name= source_name= #define PA_TYPEID_OSS PA_TYPEID_MAKE('O', 'S', 'S', '_') struct userdata { - struct pa_sink *sink; - struct pa_source *source; - struct pa_iochannel *io; - struct pa_core *core; + pa_sink *sink; + pa_source *source; + pa_iochannel *io; + pa_core *core; - struct pa_memchunk memchunk, silence; + pa_memchunk memchunk, silence; uint32_t in_fragment_size, out_fragment_size, sample_size; int use_getospace, use_getispace; int fd; - struct pa_module *module; + pa_module *module; }; static const char* const valid_modargs[] = { @@ -89,13 +89,13 @@ static const char* const valid_modargs[] = { static void update_usage(struct userdata *u) { pa_module_set_used(u->module, - (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) + - (u->source ? pa_idxset_ncontents(u->source->outputs) : 0)); + (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) + + (u->source ? pa_idxset_size(u->source->outputs) : 0)); } static void do_write(struct userdata *u) { - struct pa_memchunk *memchunk; + pa_memchunk *memchunk; ssize_t r; size_t l; int loop = 0; @@ -155,7 +155,7 @@ static void do_write(struct userdata *u) { } static void do_read(struct userdata *u) { - struct pa_memchunk memchunk; + pa_memchunk memchunk; ssize_t r; size_t l; int loop = 0; @@ -202,14 +202,14 @@ static void do_read(struct userdata *u) { } while (loop && l > 0); } -static void io_callback(struct pa_iochannel *io, void*userdata) { +static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { struct userdata *u = userdata; assert(u); do_write(u); do_read(u); } -static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(pa_sink *s) { pa_usec_t r = 0; int arg; struct userdata *u = s->userdata; @@ -229,7 +229,7 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { return r; } -static pa_usec_t source_get_latency_cb(struct pa_source *s) { +static pa_usec_t source_get_latency_cb(pa_source *s) { struct userdata *u = s->userdata; audio_buf_info info; assert(s && u && u->source); @@ -248,7 +248,7 @@ static pa_usec_t source_get_latency_cb(struct pa_source *s) { return pa_bytes_to_usec(info.bytes, &s->sample_spec); } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; const char *p; @@ -256,8 +256,8 @@ int pa__init(struct pa_core *c, struct pa_module*m) { int nfrags, frag_size, in_frag_size, out_frag_size; int mode; int record = 1, playback = 1; - struct pa_sample_spec ss; - struct pa_modargs *ma = NULL; + pa_sample_spec ss; + pa_modargs *ma = NULL; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -380,7 +380,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index b6d8dc2e0..537cb86bf 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -53,16 +53,16 @@ PA_MODULE_USAGE("sink_name= file= format=io)) return; - pa_module_set_used(u->module, pa_idxset_ncontents(u->sink->inputs) + pa_idxset_ncontents(u->sink->monitor_source->outputs)); + pa_module_set_used(u->module, pa_idxset_size(u->sink->inputs) + pa_idxset_size(u->sink->monitor_source->outputs)); if (!u->memchunk.length) if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) @@ -105,7 +105,7 @@ static void do_write(struct userdata *u) { } } -static void notify_cb(struct pa_sink*s) { +static void notify_cb(pa_sink*s) { struct userdata *u = s->userdata; assert(s && u); @@ -113,32 +113,32 @@ static void notify_cb(struct pa_sink*s) { u->core->mainloop->defer_enable(u->defer_event, 1); } -static pa_usec_t get_latency_cb(struct pa_sink *s) { +static pa_usec_t get_latency_cb(pa_sink *s) { struct userdata *u = s->userdata; assert(s && u); return u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0; } -static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event*e, void *userdata) { +static void defer_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event*e, void *userdata) { struct userdata *u = userdata; assert(u); do_write(u); } -static void io_callback(struct pa_iochannel *io, void*userdata) { +static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { struct userdata *u = userdata; assert(u); do_write(u); } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; struct stat st; const char *p; int fd = -1; - struct pa_sample_spec ss; - struct pa_modargs *ma = NULL; + pa_sample_spec ss; + pa_modargs *ma = NULL; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -215,7 +215,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-pipe-source.c b/polyp/module-pipe-source.c index 5a397162b..31653627c 100644 --- a/polyp/module-pipe-source.c +++ b/polyp/module-pipe-source.c @@ -53,14 +53,14 @@ PA_MODULE_USAGE("source_name= file= forma #define PA_TYPEID_PIPE PA_TYPEID_MAKE('P', 'I', 'P', 'E') struct userdata { - struct pa_core *core; + pa_core *core; char *filename; - struct pa_source *source; - struct pa_iochannel *io; - struct pa_module *module; - struct pa_memchunk chunk; + pa_source *source; + pa_iochannel *io; + pa_module *module; + pa_memchunk chunk; }; static const char* const valid_modargs[] = { @@ -74,13 +74,13 @@ static const char* const valid_modargs[] = { static void do_read(struct userdata *u) { ssize_t r; - struct pa_memchunk chunk; + pa_memchunk chunk; assert(u); if (!pa_iochannel_is_readable(u->io)) return; - pa_module_set_used(u->module, pa_idxset_ncontents(u->source->outputs)); + pa_module_set_used(u->module, pa_idxset_size(u->source->outputs)); if (!u->chunk.memblock) { u->chunk.memblock = pa_memblock_new(1024, u->core->memblock_stat); @@ -104,19 +104,19 @@ static void do_read(struct userdata *u) { } } -static void io_callback(struct pa_iochannel *io, void*userdata) { +static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { struct userdata *u = userdata; assert(u); do_read(u); } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; struct stat st; const char *p; int fd = -1; - struct pa_sample_spec ss; - struct pa_modargs *ma = NULL; + pa_sample_spec ss; + pa_modargs *ma = NULL; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -189,7 +189,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 141eadd39..3cf3d9d4a 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -166,8 +166,8 @@ static const char* const valid_modargs[] = { NULL }; -static struct pa_socket_server *create_socket_server(struct pa_core *c, struct pa_modargs *ma) { - struct pa_socket_server *s; +static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) { + pa_socket_server *s; #if defined(USE_TCP_SOCKETS) || defined(USE_TCP6_SOCKETS) int loopback = 1; uint32_t port = IPV4_PORT; @@ -183,7 +183,7 @@ static struct pa_socket_server *create_socket_server(struct pa_core *c, struct p } #ifdef USE_TCP6_SOCKETS - if (!(s = pa_socket_server_new_ipv6(c->mainloop, loopback ? (uint8_t*) &in6addr_loopback : (uint8_t*) &in6addr_any, port))) + if (!(s = pa_socket_server_new_ipv6(c->mainloop, loopback ? (const uint8_t*) &in6addr_loopback : (const uint8_t*) &in6addr_any, port))) return NULL; #else if (!(s = pa_socket_server_new_ipv4(c->mainloop, loopback ? INADDR_LOOPBACK : INADDR_ANY, port, TCPWRAP_SERVICE))) @@ -220,9 +220,9 @@ static struct pa_socket_server *create_socket_server(struct pa_core *c, struct p return s; } -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_socket_server *s; - struct pa_modargs *ma = NULL; +int pa__init(pa_core *c, pa_module*m) { + pa_socket_server *s; + pa_modargs *ma = NULL; int ret = -1; assert(c && m); @@ -248,7 +248,7 @@ finish: return ret; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { assert(c && m); #if defined(USE_PROTOCOL_ESOUND) diff --git a/polyp/module-sine.c b/polyp/module-sine.c index d8f7e4ef1..c531386a6 100644 --- a/polyp/module-sine.c +++ b/polyp/module-sine.c @@ -43,10 +43,10 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define PA_TYPEID_SINE PA_TYPEID_MAKE('S', 'I', 'N', 'E') struct userdata { - struct pa_core *core; - struct pa_module *module; - struct pa_sink_input *sink_input; - struct pa_memblock *memblock; + pa_core *core; + pa_module *module; + pa_sink_input *sink_input; + pa_memblock *memblock; size_t peek_index; }; @@ -56,7 +56,7 @@ static const char* const valid_modargs[] = { NULL, }; -static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { +static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { struct userdata *u; assert(i && chunk && i->userdata); u = i->userdata; @@ -67,7 +67,7 @@ static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { return 0; } -static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { +static void sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { struct userdata *u; assert(i && chunk && length && i->userdata); u = i->userdata; @@ -80,7 +80,7 @@ static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *c u->peek_index = 0; } -static void sink_input_kill(struct pa_sink_input *i) { +static void sink_input_kill(pa_sink_input *i) { struct userdata *u; assert(i && i->userdata); u = i->userdata; @@ -101,12 +101,12 @@ static void calc_sine(float *f, size_t l, float freq) { f[i] = (float) sin((double) i/l*M_PI*2*freq)/2; } -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_modargs *ma = NULL; +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; struct userdata *u; - struct pa_sink *sink; + pa_sink *sink; const char *sink_name; - struct pa_sample_spec ss; + pa_sample_spec ss; uint32_t frequency; char t[256]; @@ -164,7 +164,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u = m->userdata; assert(c && m); diff --git a/polyp/module-solaris.c b/polyp/module-solaris.c index 3eb66462e..c8ad7cf11 100644 --- a/polyp/module-solaris.c +++ b/polyp/module-solaris.c @@ -58,18 +58,18 @@ PA_MODULE_USAGE("sink_name= source_name= #define PA_TYPEID_SOLARIS PA_TYPEID_MAKE('S', 'L', 'R', 'S') struct userdata { - struct pa_sink *sink; - struct pa_source *source; - struct pa_iochannel *io; - struct pa_core *core; + pa_sink *sink; + pa_source *source; + pa_iochannel *io; + pa_core *core; - struct pa_memchunk memchunk, silence; + pa_memchunk memchunk, silence; uint32_t sample_size; unsigned int written_bytes, read_bytes; int fd; - struct pa_module *module; + pa_module *module; }; static const char* const valid_modargs[] = { @@ -93,13 +93,13 @@ static const char* const valid_modargs[] = { static void update_usage(struct userdata *u) { pa_module_set_used(u->module, - (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) + - (u->source ? pa_idxset_ncontents(u->source->outputs) : 0)); + (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) + + (u->source ? pa_idxset_size(u->source->outputs) : 0)); } static void do_write(struct userdata *u) { - struct pa_memchunk *memchunk; + pa_memchunk *memchunk; ssize_t r; assert(u); @@ -140,7 +140,7 @@ static void do_write(struct userdata *u) { } static void do_read(struct userdata *u) { - struct pa_memchunk memchunk; + pa_memchunk memchunk; int err, l; ssize_t r; assert(u); @@ -172,14 +172,14 @@ static void do_read(struct userdata *u) { u->read_bytes += r; } -static void io_callback(struct pa_iochannel *io, void*userdata) { +static void io_callback(pa_iochannel *io, void*userdata) { struct userdata *u = userdata; assert(u); do_write(u); do_read(u); } -static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(pa_sink *s) { pa_usec_t r = 0; audio_info_t info; int err; @@ -198,7 +198,7 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { return r; } -static pa_usec_t source_get_latency_cb(struct pa_source *s) { +static pa_usec_t source_get_latency_cb(pa_source *s) { pa_usec_t r = 0; struct userdata *u = s->userdata; audio_info_t info; @@ -214,7 +214,7 @@ static pa_usec_t source_get_latency_cb(struct pa_source *s) { return r; } -static int pa_solaris_auto_format(int fd, int mode, struct pa_sample_spec *ss) { +static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { audio_info_t info; AUDIO_INITINFO(&info); @@ -298,15 +298,15 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { return 0; } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; const char *p; int fd = -1; int buffer_size; int mode; int record = 1, playback = 1; - struct pa_sample_spec ss; - struct pa_modargs *ma = NULL; + pa_sample_spec ss; + pa_modargs *ma = NULL; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -409,7 +409,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; assert(c && m); diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index c6a35ca6b..e0eab6c2d 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -90,37 +90,37 @@ static const char* const valid_modargs[] = { NULL, }; -static void command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); #ifdef TUNNEL_SINK -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); #endif -static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { +static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = { #ifdef TUNNEL_SINK - [PA_COMMAND_REQUEST] = { command_request }, + [PA_COMMAND_REQUEST] = command_request, #endif - [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_stream_killed }, - [PA_COMMAND_RECORD_STREAM_KILLED] = { command_stream_killed }, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = command_stream_killed, + [PA_COMMAND_RECORD_STREAM_KILLED] = command_stream_killed }; struct userdata { - struct pa_socket_client *client; - struct pa_pstream *pstream; - struct pa_pdispatch *pdispatch; + pa_socket_client *client; + pa_pstream *pstream; + pa_pdispatch *pdispatch; char *server_name; #ifdef TUNNEL_SINK char *sink_name; - struct pa_sink *sink; + pa_sink *sink; uint32_t requested_bytes; #else char *source_name; - struct pa_source *source; + pa_source *source; #endif - struct pa_module *module; - struct pa_core *core; + pa_module *module; + pa_core *core; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; @@ -130,7 +130,7 @@ struct userdata { pa_usec_t host_latency; - struct pa_time_event *time_event; + pa_time_event *time_event; int auth_cookie_in_property; }; @@ -180,7 +180,7 @@ static void die(struct userdata *u) { pa_module_unload_request(u->module); } -static void command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_stream_killed(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; assert(pd && t && u && u->pdispatch == pd); @@ -190,7 +190,7 @@ static void command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uin #ifdef TUNNEL_SINK static void send_prebuf_request(struct userdata *u) { - struct pa_tagstruct *t; + pa_tagstruct *t; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_PREBUF_PLAYBACK_STREAM); @@ -206,7 +206,7 @@ static void send_bytes(struct userdata *u) { return; while (u->requested_bytes > 0) { - struct pa_memchunk chunk; + pa_memchunk chunk; if (pa_sink_render(u->sink, u->requested_bytes, &chunk) < 0) { @@ -226,7 +226,7 @@ static void send_bytes(struct userdata *u) { } } -static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; uint32_t bytes, channel; assert(pd && command == PA_COMMAND_REQUEST && t && u && u->pdispatch == pd); @@ -251,7 +251,7 @@ static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t #endif -static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; pa_usec_t buffer_usec, sink_usec, source_usec, transport_usec; int playing; @@ -309,7 +309,7 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman } static void request_latency(struct userdata *u) { - struct pa_tagstruct *t; + pa_tagstruct *t; struct timeval now; uint32_t tag; assert(u); @@ -331,7 +331,7 @@ static void request_latency(struct userdata *u) { pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u); } -static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; assert(pd && u && u->pdispatch == pd); @@ -361,9 +361,9 @@ static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, ui #endif } -static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; - struct pa_tagstruct *reply; + pa_tagstruct *reply; char name[256], un[128], hn[128]; assert(pd && u && u->pdispatch == pd); @@ -424,7 +424,7 @@ static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, u pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u); } -static void pstream_die_callback(struct pa_pstream *p, void *userdata) { +static void pstream_die_callback(pa_pstream *p, void *userdata) { struct userdata *u = userdata; assert(p && u); @@ -433,7 +433,7 @@ static void pstream_die_callback(struct pa_pstream *p, void *userdata) { } -static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *userdata) { struct userdata *u = userdata; assert(p && packet && u); @@ -444,7 +444,7 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack } #ifndef TUNNEL_SINK -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk, void *userdata) { struct userdata *u = userdata; assert(p && chunk && u); @@ -458,9 +458,9 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui } #endif -static void on_connection(struct pa_socket_client *sc, struct pa_iochannel *io, void *userdata) { +static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata) { struct userdata *u = userdata; - struct pa_tagstruct *t; + pa_tagstruct *t; uint32_t tag; assert(sc && u && u->client == sc); @@ -492,7 +492,7 @@ static void on_connection(struct pa_socket_client *sc, struct pa_iochannel *io, } #ifdef TUNNEL_SINK -static void sink_notify(struct pa_sink*sink) { +static void sink_notify(pa_sink*sink) { struct userdata *u; assert(sink && sink->userdata); u = sink->userdata; @@ -500,7 +500,7 @@ static void sink_notify(struct pa_sink*sink) { send_bytes(u); } -static pa_usec_t sink_get_latency(struct pa_sink *sink) { +static pa_usec_t sink_get_latency(pa_sink *sink) { struct userdata *u; uint32_t l; pa_usec_t usec = 0; @@ -519,7 +519,7 @@ static pa_usec_t sink_get_latency(struct pa_sink *sink) { return usec; } #else -static pa_usec_t source_get_latency(struct pa_source *source) { +static pa_usec_t source_get_latency(pa_source *source) { struct userdata *u; assert(source && source->userdata); u = source->userdata; @@ -528,7 +528,7 @@ static pa_usec_t source_get_latency(struct pa_source *source) { } #endif -static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { +static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { struct userdata *u = userdata; struct timeval ntv; assert(m && e && u); @@ -566,10 +566,10 @@ static int load_key(struct userdata *u, const char*fn) { return 0; } -int pa__init(struct pa_core *c, struct pa_module*m) { - struct pa_modargs *ma = NULL; +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; struct userdata *u = NULL; - struct pa_sample_spec ss; + pa_sample_spec ss; struct timeval ntv; assert(c && m); @@ -665,7 +665,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata* u; assert(c && m); diff --git a/polyp/module-waveout.c b/polyp/module-waveout.c index 4e01bc754..4d6d8c7b6 100644 --- a/polyp/module-waveout.c +++ b/polyp/module-waveout.c @@ -49,11 +49,11 @@ PA_MODULE_USAGE("sink_name= source_name= #define DEFAULT_SOURCE_NAME "wave_input" struct userdata { - struct pa_sink *sink; - struct pa_source *source; - struct pa_core *core; - struct pa_time_event *event; - struct pa_defer_event *defer; + pa_sink *sink; + pa_source *source; + pa_core *core; + pa_time_event *event; + pa_defer_event *defer; pa_usec_t poll_timeout; uint32_t fragments, fragment_size; @@ -65,11 +65,11 @@ struct userdata { int cur_ohdr, cur_ihdr; unsigned int oremain; WAVEHDR *ohdrs, *ihdrs; - struct pa_memchunk silence; + pa_memchunk silence; HWAVEOUT hwo; HWAVEIN hwi; - struct pa_module *module; + pa_module *module; CRITICAL_SECTION crit; }; @@ -89,15 +89,15 @@ static const char* const valid_modargs[] = { static void update_usage(struct userdata *u) { pa_module_set_used(u->module, - (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) + - (u->source ? pa_idxset_ncontents(u->source->outputs) : 0)); + (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + + (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) + + (u->source ? pa_idxset_size(u->source->outputs) : 0)); } static void do_write(struct userdata *u) { uint32_t free_frags, remain; - struct pa_memchunk memchunk, *cur_chunk; + pa_memchunk memchunk, *cur_chunk; WAVEHDR *hdr; MMRESULT res; @@ -178,7 +178,7 @@ static void do_write(struct userdata *u) static void do_read(struct userdata *u) { uint32_t free_frags; - struct pa_memchunk memchunk; + pa_memchunk memchunk; WAVEHDR *hdr; MMRESULT res; @@ -227,7 +227,7 @@ static void do_read(struct userdata *u) } } -static void poll_cb(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval *tv, void *userdata) { +static void poll_cb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { struct userdata *u = userdata; struct timeval ntv; @@ -244,7 +244,7 @@ static void poll_cb(struct pa_mainloop_api*a, struct pa_time_event *e, const str a->time_restart(e, &ntv); } -static void defer_cb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { +static void defer_cb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { struct userdata *u = userdata; assert(u); @@ -283,7 +283,7 @@ static void CALLBACK chunk_ready_cb(HWAVEIN hwi, UINT msg, DWORD_PTR inst, DWORD LeaveCriticalSection(&u->crit); } -static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(pa_sink *s) { struct userdata *u = s->userdata; uint32_t free_frags; MMTIME mmt; @@ -305,7 +305,7 @@ static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { } } -static pa_usec_t source_get_latency_cb(struct pa_source *s) { +static pa_usec_t source_get_latency_cb(pa_source *s) { pa_usec_t r = 0; struct userdata *u = s->userdata; uint32_t free_frags; @@ -324,21 +324,21 @@ static pa_usec_t source_get_latency_cb(struct pa_source *s) { return r; } -static void notify_sink_cb(struct pa_sink *s) { +static void notify_sink_cb(pa_sink *s) { struct userdata *u = s->userdata; assert(u); u->core->mainloop->defer_enable(u->defer, 1); } -static void notify_source_cb(struct pa_source *s) { +static void notify_source_cb(pa_source *s) { struct userdata *u = s->userdata; assert(u); u->core->mainloop->defer_enable(u->defer, 1); } -static int ss_to_waveformat(struct pa_sample_spec *ss, LPWAVEFORMATEX wf) { +static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) { wf->wFormatTag = WAVE_FORMAT_PCM; if (ss->channels > 2) { @@ -378,15 +378,15 @@ static int ss_to_waveformat(struct pa_sample_spec *ss, LPWAVEFORMATEX wf) { return 0; } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; HWAVEOUT hwo = INVALID_HANDLE_VALUE; HWAVEIN hwi = INVALID_HANDLE_VALUE; WAVEFORMATEX wf; int nfrags, frag_size; int record = 1, playback = 1; - struct pa_sample_spec ss; - struct pa_modargs *ma = NULL; + pa_sample_spec ss; + pa_modargs *ma = NULL; unsigned int i; struct timeval tv; @@ -534,7 +534,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u; unsigned int i; diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index 084f5d4be..9b08c1667 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -47,14 +47,14 @@ PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink= sample= display=") struct userdata { - struct pa_core *core; + pa_core *core; int xkb_event_base; char *sink_name; char *scache_item; Display *display; - struct pa_x11_wrapper *x11_wrapper; - struct pa_x11_client *x11_client; + pa_x11_wrapper *x11_wrapper; + pa_x11_client *x11_client; }; static const char* const valid_modargs[] = { @@ -65,7 +65,7 @@ static const char* const valid_modargs[] = { }; static int ring_bell(struct userdata *u, int percent) { - struct pa_sink *s; + pa_sink *s; assert(u); if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { @@ -77,7 +77,7 @@ static int ring_bell(struct userdata *u, int percent) { return 0; } -static int x11_event_callback(struct pa_x11_wrapper *w, XEvent *e, void *userdata) { +static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) { XkbBellNotifyEvent *bne; struct userdata *u = userdata; assert(w && e && u && u->x11_wrapper == w); @@ -95,9 +95,9 @@ static int x11_event_callback(struct pa_x11_wrapper *w, XEvent *e, void *userdat return 1; } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; - struct pa_modargs *ma = NULL; + pa_modargs *ma = NULL; int major, minor; unsigned int auto_ctrls, auto_values; assert(c && m); @@ -154,7 +154,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata *u = m->userdata; assert(c && m && u); diff --git a/polyp/module-x11-publish.c b/polyp/module-x11-publish.c index a47a76060..0116914f2 100644 --- a/polyp/module-x11-publish.c +++ b/polyp/module-x11-publish.c @@ -63,8 +63,8 @@ static const char* const valid_modargs[] = { }; struct userdata { - struct pa_core *core; - struct pa_x11_wrapper *x11_wrapper; + pa_core *core; + pa_x11_wrapper *x11_wrapper; Display *display; char *id; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; @@ -97,14 +97,14 @@ static int load_key(struct userdata *u, const char*fn) { return 0; } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct userdata *u; - struct pa_modargs *ma = NULL; + pa_modargs *ma = NULL; char hn[256], un[128]; char hx[PA_NATIVE_COOKIE_LENGTH*2+1]; const char *t; char *s; - struct pa_strlist *l; + pa_strlist *l; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments\n"); @@ -156,7 +156,7 @@ fail: return -1; } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata*u; assert(c && m); diff --git a/polyp/module-zeroconf-publish.c b/polyp/module-zeroconf-publish.c index a7e2073ec..7e0a2764d 100644 --- a/polyp/module-zeroconf-publish.c +++ b/polyp/module-zeroconf-publish.c @@ -64,23 +64,23 @@ struct service { struct { int valid; - enum pa_namereg_type type; + pa_namereg_type type; uint32_t index; } loaded; struct { int valid; - enum pa_namereg_type type; + pa_namereg_type type; uint32_t index; } autoload; }; struct userdata { - struct pa_core *core; - struct pa_howl_wrapper *howl_wrapper; - struct pa_hashmap *services; - struct pa_dynarray *sink_dynarray, *source_dynarray, *autoload_dynarray; - struct pa_subscription *subscription; + pa_core *core; + pa_howl_wrapper *howl_wrapper; + pa_hashmap *services; + pa_dynarray *sink_dynarray, *source_dynarray, *autoload_dynarray; + pa_subscription *subscription; uint16_t port; sw_discovery_oid server_oid; @@ -90,17 +90,17 @@ static sw_result publish_reply(sw_discovery discovery, sw_discovery_publish_stat return SW_OKAY; } -static void get_service_data(struct userdata *u, struct service *s, struct pa_sample_spec *ret_ss, char **ret_description, pa_typeid_t *ret_typeid) { +static void get_service_data(struct userdata *u, struct service *s, pa_sample_spec *ret_ss, char **ret_description, pa_typeid_t *ret_typeid) { assert(u && s && s->loaded.valid && ret_ss && ret_description && ret_typeid); if (s->loaded.type == PA_NAMEREG_SINK) { - struct pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index); + pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index); assert(sink); *ret_ss = sink->sample_spec; *ret_description = sink->description; *ret_typeid = sink->typeid; } else if (s->loaded.type == PA_NAMEREG_SOURCE) { - struct pa_source *source = pa_idxset_get_by_index(u->core->sources, s->loaded.index); + pa_source *source = pa_idxset_get_by_index(u->core->sources, s->loaded.index); assert(source); *ret_ss = source->sample_spec; *ret_description = source->description; @@ -109,7 +109,7 @@ static void get_service_data(struct userdata *u, struct service *s, struct pa_sa assert(0); } -static void txt_record_server_data(struct pa_core *c, sw_text_record t) { +static void txt_record_server_data(pa_core *c, sw_text_record t) { char s[256]; assert(c); @@ -152,7 +152,7 @@ static int publish_service(struct userdata *u, struct service *s) { if (s->loaded.valid) { char z[64], *description; pa_typeid_t typeid; - struct pa_sample_spec ss; + pa_sample_spec ss; get_service_data(u, s, &ss, &description, &typeid); @@ -223,7 +223,7 @@ struct service *get_service(struct userdata *u, const char *name) { return s; } -static int publish_sink(struct userdata *u, struct pa_sink *s) { +static int publish_sink(struct userdata *u, pa_sink *s) { struct service *svc; assert(u && s); @@ -240,7 +240,7 @@ static int publish_sink(struct userdata *u, struct pa_sink *s) { return publish_service(u, svc); } -static int publish_source(struct userdata *u, struct pa_source *s) { +static int publish_source(struct userdata *u, pa_source *s) { struct service *svc; assert(u && s); @@ -257,7 +257,7 @@ static int publish_source(struct userdata *u, struct pa_source *s) { return publish_service(u, svc); } -static int publish_autoload(struct userdata *u, struct pa_autoload_entry *s) { +static int publish_autoload(struct userdata *u, pa_autoload_entry *s) { struct service *svc; assert(u && s); @@ -322,14 +322,14 @@ static int remove_autoload(struct userdata *u, uint32_t index) { return publish_service(u, svc); } -static void subscribe_callback(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) { +static void subscribe_callback(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata) { struct userdata *u = userdata; assert(u && c); switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) case PA_SUBSCRIPTION_EVENT_SINK: { if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - struct pa_sink *sink; + pa_sink *sink; if ((sink = pa_idxset_get_by_index(c->sinks, index))) { if (publish_sink(u, sink) < 0) @@ -345,7 +345,7 @@ static void subscribe_callback(struct pa_core *c, enum pa_subscription_event_typ case PA_SUBSCRIPTION_EVENT_SOURCE: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - struct pa_source *source; + pa_source *source; if ((source = pa_idxset_get_by_index(c->sources, index))) { if (publish_source(u, source) < 0) @@ -360,7 +360,7 @@ static void subscribe_callback(struct pa_core *c, enum pa_subscription_event_typ case PA_SUBSCRIPTION_EVENT_AUTOLOAD: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - struct pa_autoload_entry *autoload; + pa_autoload_entry *autoload; if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, index))) { if (publish_autoload(u, autoload) < 0) @@ -383,13 +383,13 @@ fail: } } -int pa__init(struct pa_core *c, struct pa_module*m) { +int pa__init(pa_core *c, pa_module*m) { struct userdata *u; uint32_t index, port = PA_NATIVE_DEFAULT_PORT; - struct pa_sink *sink; - struct pa_source *source; - struct pa_autoload_entry *autoload; - struct pa_modargs *ma = NULL; + pa_sink *sink; + pa_source *source; + pa_autoload_entry *autoload; + pa_modargs *ma = NULL; char t[256], hn[256]; int free_txt = 0; sw_text_record txt; @@ -478,7 +478,7 @@ static void service_free(void *p, void *userdata) { pa_xfree(s); } -void pa__done(struct pa_core *c, struct pa_module*m) { +void pa__done(pa_core *c, pa_module*m) { struct userdata*u; assert(c && m); diff --git a/polyp/module.c b/polyp/module.c index 0a3d569b2..499ea2990 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -34,14 +34,15 @@ #include "xmalloc.h" #include "subscribe.h" #include "log.h" +#include "util.h" #define PA_SYMBOL_INIT "pa__init" #define PA_SYMBOL_DONE "pa__done" #define UNLOAD_POLL_TIME 2 -static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { - struct pa_core *c = userdata; +static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { + pa_core *c = userdata; struct timeval ntv; assert(c && c->mainloop == m && c->module_auto_unload_event == e); @@ -52,8 +53,8 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, m->time_restart(e, &ntv); } -struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char *argument) { - struct pa_module *m = NULL; +pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { + pa_module *m = NULL; int r; assert(c && name); @@ -61,7 +62,7 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char if (c->disallow_module_loading) goto fail; - m = pa_xmalloc(sizeof(struct pa_module)); + m = pa_xmalloc(sizeof(pa_module)); m->name = pa_xstrdup(name); m->argument = pa_xstrdup(argument); @@ -71,12 +72,12 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char goto fail; } - if (!(m->init = (int (*)(struct pa_core *c, struct pa_module*m)) lt_dlsym(m->dl, PA_SYMBOL_INIT))) { + if (!(m->init = (int (*)(pa_core *_c, pa_module*_m)) lt_dlsym(m->dl, PA_SYMBOL_INIT))) { pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.\n", name); goto fail; } - if (!(m->done = (void (*)(struct pa_core *c, struct pa_module*m)) lt_dlsym(m->dl, PA_SYMBOL_DONE))) { + if (!(m->done = (void (*)(pa_core *_c, pa_module*_m)) lt_dlsym(m->dl, PA_SYMBOL_DONE))) { pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.\n", name); goto fail; } @@ -129,7 +130,7 @@ fail: return NULL; } -static void pa_module_free(struct pa_module *m) { +static void pa_module_free(pa_module *m) { assert(m && m->done && m->core); if (m->core->disallow_module_loading) @@ -150,7 +151,7 @@ static void pa_module_free(struct pa_module *m) { pa_xfree(m); } -void pa_module_unload(struct pa_core *c, struct pa_module *m) { +void pa_module_unload(pa_core *c, pa_module *m) { assert(c && m); assert(c->modules); @@ -160,24 +161,24 @@ void pa_module_unload(struct pa_core *c, struct pa_module *m) { pa_module_free(m); } -void pa_module_unload_by_index(struct pa_core *c, uint32_t index) { - struct pa_module *m; - assert(c && index != PA_IDXSET_INVALID); +void pa_module_unload_by_index(pa_core *c, uint32_t idx) { + pa_module *m; + assert(c && idx != PA_IDXSET_INVALID); assert(c->modules); - if (!(m = pa_idxset_remove_by_index(c->modules, index))) + if (!(m = pa_idxset_remove_by_index(c->modules, idx))) return; pa_module_free(m); } -static void free_callback(void *p, void *userdata) { - struct pa_module *m = p; +static void free_callback(void *p, PA_GCC_UNUSED void *userdata) { + pa_module *m = p; assert(m); pa_module_free(m); } -void pa_module_unload_all(struct pa_core *c) { +void pa_module_unload_all(pa_core *c) { assert(c); if (!c->modules) @@ -197,8 +198,8 @@ void pa_module_unload_all(struct pa_core *c) { } } -static int unused_callback(void *p, uint32_t index, int *del, void *userdata) { - struct pa_module *m = p; +static int unused_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void *userdata) { + pa_module *m = p; time_t *now = userdata; assert(p && del && now); @@ -210,7 +211,7 @@ static int unused_callback(void *p, uint32_t index, int *del, void *userdata) { return 0; } -void pa_module_unload_unused(struct pa_core *c) { +void pa_module_unload_unused(pa_core *c) { time_t now; assert(c); @@ -221,8 +222,8 @@ void pa_module_unload_unused(struct pa_core *c) { pa_idxset_foreach(c->modules, unused_callback, &now); } -static int unload_callback(void *p, uint32_t index, int *del, void *userdata) { - struct pa_module *m = p; +static int unload_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, PA_GCC_UNUSED void *userdata) { + pa_module *m = p; assert(m); if (m->unload_requested) { @@ -233,8 +234,8 @@ static int unload_callback(void *p, uint32_t index, int *del, void *userdata) { return 0; } -static void defer_cb(struct pa_mainloop_api*api, struct pa_defer_event *e, void *userdata) { - struct pa_core *core = userdata; +static void defer_cb(pa_mainloop_api*api, pa_defer_event *e, void *userdata) { + pa_core *core = userdata; api->defer_enable(e, 0); if (!core->modules) @@ -244,7 +245,7 @@ static void defer_cb(struct pa_mainloop_api*api, struct pa_defer_event *e, void } -void pa_module_unload_request(struct pa_module *m) { +void pa_module_unload_request(pa_module *m) { assert(m); m->unload_requested = 1; @@ -255,7 +256,7 @@ void pa_module_unload_request(struct pa_module *m) { m->core->mainloop->defer_enable(m->core->module_defer_unload_event, 1); } -void pa_module_set_used(struct pa_module*m, int used) { +void pa_module_set_used(pa_module*m, int used) { assert(m); if (m->n_used != used) @@ -267,7 +268,7 @@ void pa_module_set_used(struct pa_module*m, int used) { m->n_used = used; } -struct pa_modinfo *pa_module_get_info(struct pa_module *m) { +pa_modinfo *pa_module_get_info(pa_module *m) { assert(m); return pa_modinfo_get_by_handle(m->dl); diff --git a/polyp/module.h b/polyp/module.h index f5daff95a..6f137c157 100644 --- a/polyp/module.h +++ b/polyp/module.h @@ -28,15 +28,17 @@ #include "core.h" #include "modinfo.h" +typedef struct pa_module pa_module; + struct pa_module { - struct pa_core *core; + pa_core *core; char *name, *argument; uint32_t index; lt_dlhandle dl; - int (*init)(struct pa_core *c, struct pa_module*m); - void (*done)(struct pa_core *c, struct pa_module*m); + int (*init)(pa_core *c, pa_module*m); + void (*done)(pa_core *c, pa_module*m); void *userdata; @@ -47,22 +49,22 @@ struct pa_module { int unload_requested; }; -struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char*argument); -/* void pa_module_unload(struct pa_core *c, struct pa_module *m); */ -/* void pa_module_unload_by_index(struct pa_core *c, uint32_t index); */ +pa_module* pa_module_load(pa_core *c, const char *name, const char*argument); +void pa_module_unload(pa_core *c, pa_module *m); +void pa_module_unload_by_index(pa_core *c, uint32_t idx); -void pa_module_unload_all(struct pa_core *c); -void pa_module_unload_unused(struct pa_core *c); +void pa_module_unload_all(pa_core *c); +void pa_module_unload_unused(pa_core *c); -void pa_module_unload_request(struct pa_module *m); +void pa_module_unload_request(pa_module *m); -void pa_module_set_used(struct pa_module*m, int used); +void pa_module_set_used(pa_module*m, int used); #define PA_MODULE_AUTHOR(s) const char * pa__get_author(void) { return s; } #define PA_MODULE_DESCRIPTION(s) const char * pa__get_description(void) { return s; } #define PA_MODULE_USAGE(s) const char * pa__get_usage(void) { return s; } #define PA_MODULE_VERSION(s) const char * pa__get_version(void) { return s; } -struct pa_modinfo *pa_module_get_info(struct pa_module *m); +pa_modinfo *pa_module_get_info(pa_module *m); #endif diff --git a/polyp/namereg.c b/polyp/namereg.c index 04601442d..7c53a05d0 100644 --- a/polyp/namereg.c +++ b/polyp/namereg.c @@ -38,20 +38,20 @@ #include "util.h" struct namereg_entry { - enum pa_namereg_type type; + pa_namereg_type type; char *name; void *data; }; -void pa_namereg_free(struct pa_core *c) { +void pa_namereg_free(pa_core *c) { assert(c); if (!c->namereg) return; - assert(pa_hashmap_ncontents(c->namereg) == 0); + assert(pa_hashmap_size(c->namereg) == 0); pa_hashmap_free(c->namereg, NULL, NULL); } -const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_namereg_type type, void *data, int fail) { +const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type type, void *data, int fail) { struct namereg_entry *e; char *n = NULL; int r; @@ -99,7 +99,7 @@ const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_nam } -void pa_namereg_unregister(struct pa_core *c, const char *name) { +void pa_namereg_unregister(pa_core *c, const char *name) { struct namereg_entry *e; assert(c && name); @@ -110,9 +110,9 @@ void pa_namereg_unregister(struct pa_core *c, const char *name) { pa_xfree(e); } -void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type, int autoload) { +void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int autoload) { struct namereg_entry *e; - uint32_t index; + uint32_t idx; assert(c); if (!name) { @@ -129,7 +129,7 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t if (e->type == e->type) return e->data; - if (pa_atou(name, &index) < 0) { + if (pa_atou(name, &idx) < 0) { if (autoload) { pa_autoload_request(c, name, type); @@ -143,16 +143,16 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t } if (type == PA_NAMEREG_SINK) - return pa_idxset_get_by_index(c->sinks, index); + return pa_idxset_get_by_index(c->sinks, idx); else if (type == PA_NAMEREG_SOURCE) - return pa_idxset_get_by_index(c->sources, index); + return pa_idxset_get_by_index(c->sources, idx); else if (type == PA_NAMEREG_SAMPLE && c->scache) - return pa_idxset_get_by_index(c->scache, index); + return pa_idxset_get_by_index(c->scache, idx); return NULL; } -void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_type type) { +void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type type) { char **s; assert(c && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); @@ -170,8 +170,8 @@ void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_ pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX); } -const char *pa_namereg_get_default_sink_name(struct pa_core *c) { - struct pa_sink *s; +const char *pa_namereg_get_default_sink_name(pa_core *c) { + pa_sink *s; assert(c); if (c->default_sink_name) @@ -186,16 +186,16 @@ const char *pa_namereg_get_default_sink_name(struct pa_core *c) { return NULL; } -const char *pa_namereg_get_default_source_name(struct pa_core *c) { - struct pa_source *s; - uint32_t index; +const char *pa_namereg_get_default_source_name(pa_core *c) { + pa_source *s; + uint32_t idx; assert(c); if (c->default_source_name) return c->default_source_name; - for (s = pa_idxset_first(c->sources, &index); s; s = pa_idxset_next(c->sources, &index)) + for (s = pa_idxset_first(c->sources, &idx); s; s = pa_idxset_next(c->sources, &idx)) if (!s->monitor_of) { pa_namereg_set_default(c, s->name, PA_NAMEREG_SOURCE); break; diff --git a/polyp/namereg.h b/polyp/namereg.h index 99032be84..04f1737ba 100644 --- a/polyp/namereg.h +++ b/polyp/namereg.h @@ -24,20 +24,20 @@ #include "core.h" -enum pa_namereg_type { +typedef enum pa_namereg_type { PA_NAMEREG_SINK, PA_NAMEREG_SOURCE, PA_NAMEREG_SAMPLE -}; +} pa_namereg_type ; -void pa_namereg_free(struct pa_core *c); +void pa_namereg_free(pa_core *c); -const char *pa_namereg_register(struct pa_core *c, const char *name, enum pa_namereg_type type, void *data, int fail); -void pa_namereg_unregister(struct pa_core *c, const char *name); -void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type type, int autoload); -void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_type type); +const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type type, void *data, int fail); +void pa_namereg_unregister(pa_core *c, const char *name); +void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int autoload); +void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type type); -const char *pa_namereg_get_default_sink_name(struct pa_core *c); -const char *pa_namereg_get_default_source_name(struct pa_core *c); +const char *pa_namereg_get_default_sink_name(pa_core *c); +const char *pa_namereg_get_default_source_name(pa_core *c); #endif diff --git a/polyp/oss-util.c b/polyp/oss-util.c index 799bc40a3..20a2965a3 100644 --- a/polyp/oss-util.c +++ b/polyp/oss-util.c @@ -90,7 +90,7 @@ fail: return fd; } -int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) { +int pa_oss_auto_format(int fd, pa_sample_spec *ss) { int format, channels, speed, reqformat; static const int format_trans[PA_SAMPLE_MAX] = { [PA_SAMPLE_U8] = AFMT_U8, diff --git a/polyp/oss-util.h b/polyp/oss-util.h index c1c696320..3ee51cc58 100644 --- a/polyp/oss-util.h +++ b/polyp/oss-util.h @@ -25,7 +25,7 @@ #include "sample.h" int pa_oss_open(const char *device, int *mode, int* pcaps); -int pa_oss_auto_format(int fd, struct pa_sample_spec *ss); +int pa_oss_auto_format(int fd, pa_sample_spec *ss); int pa_oss_set_fragments(int fd, int frags, int frag_size); diff --git a/polyp/pabrowse.c b/polyp/pabrowse.c index ccea0cd41..634c308a2 100644 --- a/polyp/pabrowse.c +++ b/polyp/pabrowse.c @@ -32,12 +32,12 @@ #include #include -static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { +static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got signal, exiting\n"); m->quit(m, 0); } -static void dump_server(const struct pa_browse_info *i) { +static void dump_server(const pa_browse_info *i) { char t[16]; if (i->cookie) @@ -55,7 +55,7 @@ static void dump_server(const struct pa_browse_info *i) { i->cookie ? t : "n/a"); } -static void dump_device(const struct pa_browse_info *i) { +static void dump_device(const pa_browse_info *i) { char t[16], ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; if (i->sample_spec) @@ -75,7 +75,7 @@ static void dump_device(const struct pa_browse_info *i) { } -static void browser_callback(struct pa_browser *b, enum pa_browse_opcode c, const struct pa_browse_info *i, void *userdata) { +static void browser_callback(pa_browser *b, pa_browse_opcode c, const pa_browse_info *i, void *userdata) { assert(b && i); switch (c) { @@ -108,8 +108,8 @@ static void browser_callback(struct pa_browser *b, enum pa_browse_opcode c, cons int main(int argc, char *argv[]) { - struct pa_mainloop *mainloop = NULL; - struct pa_browser *browser = NULL; + pa_mainloop *mainloop = NULL; + pa_browser *browser = NULL; int ret = 1, r; if (!(mainloop = pa_mainloop_new())) diff --git a/polyp/pacat-simple.c b/polyp/pacat-simple.c index 09cf4d1a1..373cdd576 100644 --- a/polyp/pacat-simple.c +++ b/polyp/pacat-simple.c @@ -30,19 +30,20 @@ #include #include +#include "gccmacro.h" #define BUFSIZE 1024 -int main(int argc, char*argv[]) { +int main(PA_GCC_UNUSED int argc, char*argv[]) { /* The Sample format to use */ - static const struct pa_sample_spec ss = { + static const pa_sample_spec ss = { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 }; - struct pa_simple *s = NULL; + pa_simple *s = NULL; int ret = 1; int error; diff --git a/polyp/pacat.c b/polyp/pacat.c index 1bba2ee47..6842d61ac 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -44,21 +44,21 @@ static enum { RECORD, PLAYBACK } mode = PLAYBACK; -static struct pa_context *context = NULL; -static struct pa_stream *stream = NULL; -static struct pa_mainloop_api *mainloop_api = NULL; +static pa_context *context = NULL; +static pa_stream *stream = NULL; +static pa_mainloop_api *mainloop_api = NULL; static void *buffer = NULL; static size_t buffer_length = 0, buffer_index = 0; -static struct pa_io_event* stdio_event = NULL; +static pa_io_event* stdio_event = NULL; static char *stream_name = NULL, *client_name = NULL, *device = NULL; static int verbose = 0; static pa_volume_t volume = PA_VOLUME_NORM; -static struct pa_sample_spec sample_spec = { +static pa_sample_spec sample_spec = { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 @@ -94,7 +94,7 @@ static void do_stream_write(size_t length) { } /* This is called whenever new data may be written to the stream */ -static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { +static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { assert(s && length); if (stdio_event) @@ -107,7 +107,7 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user } /* This is called whenever new data may is available */ -static void stream_read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata) { +static void stream_read_callback(pa_stream *s, const void*data, size_t length, void *userdata) { assert(s && data && length); if (stdio_event) @@ -125,7 +125,7 @@ static void stream_read_callback(struct pa_stream *s, const void*data, size_t le } /* This routine is called whenever the stream state changes */ -static void stream_state_callback(struct pa_stream *s, void *userdata) { +static void stream_state_callback(pa_stream *s, void *userdata) { assert(s); switch (pa_stream_get_state(s)) { @@ -146,7 +146,7 @@ static void stream_state_callback(struct pa_stream *s, void *userdata) { } /* This is called whenever the context status changes */ -static void context_state_callback(struct pa_context *c, void *userdata) { +static void context_state_callback(pa_context *c, void *userdata) { assert(c); switch (pa_context_get_state(c)) { @@ -188,13 +188,13 @@ static void context_state_callback(struct pa_context *c, void *userdata) { } /* Connection draining complete */ -static void context_drain_complete(struct pa_context*c, void *userdata) { +static void context_drain_complete(pa_context*c, void *userdata) { pa_context_disconnect(c); } /* Stream draining complete */ -static void stream_drain_complete(struct pa_stream*s, int success, void *userdata) { - struct pa_operation *o; +static void stream_drain_complete(pa_stream*s, int success, void *userdata) { + pa_operation *o; if (!success) { fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); @@ -219,7 +219,7 @@ static void stream_drain_complete(struct pa_stream*s, int success, void *userdat } /* New data on STDIN **/ -static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { +static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) { size_t l, w = 0; ssize_t r; assert(a == mainloop_api && e && stdio_event == e); @@ -257,7 +257,7 @@ static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int } /* Some data may be written to STDOUT */ -static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { +static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) { ssize_t r; assert(a == mainloop_api && e && stdio_event == e); @@ -288,7 +288,7 @@ static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int } /* UNIX signal to quit recieved */ -static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { +static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { if (verbose) fprintf(stderr, "Got signal, exiting.\n"); quit(0); @@ -296,7 +296,7 @@ static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_even } /* Show the current latency */ -static void stream_get_latency_callback(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) { +static void stream_get_latency_callback(pa_stream *s, const pa_latency_info *i, void *userdata) { pa_usec_t total; int negative = 0; assert(s); @@ -315,7 +315,7 @@ static void stream_get_latency_callback(struct pa_stream *s, const struct pa_lat } /* Someone requested that the latency is shown */ -static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { +static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); pa_operation_unref(pa_stream_get_latency_info(stream, stream_get_latency_callback, NULL)); } @@ -352,7 +352,7 @@ enum { }; int main(int argc, char *argv[]) { - struct pa_mainloop* m = NULL; + pa_mainloop* m = NULL; int ret = 1, r, c; char *bn, *server = NULL; diff --git a/polyp/packet.c b/polyp/packet.c index 84ac6d625..b3a2e0742 100644 --- a/polyp/packet.c +++ b/polyp/packet.c @@ -29,10 +29,10 @@ #include "packet.h" #include "xmalloc.h" -struct pa_packet* pa_packet_new(size_t length) { - struct pa_packet *p; +pa_packet* pa_packet_new(size_t length) { + pa_packet *p; assert(length); - p = pa_xmalloc(sizeof(struct pa_packet)+length); + p = pa_xmalloc(sizeof(pa_packet)+length); p->ref = 1; p->length = length; p->data = (uint8_t*) (p+1); @@ -40,10 +40,10 @@ struct pa_packet* pa_packet_new(size_t length) { return p; } -struct pa_packet* pa_packet_new_dynamic(uint8_t* data, size_t length) { - struct pa_packet *p; +pa_packet* pa_packet_new_dynamic(uint8_t* data, size_t length) { + pa_packet *p; assert(data && length); - p = pa_xmalloc(sizeof(struct pa_packet)); + p = pa_xmalloc(sizeof(pa_packet)); p->ref = 1; p->length = length; p->data = data; @@ -51,13 +51,13 @@ struct pa_packet* pa_packet_new_dynamic(uint8_t* data, size_t length) { return p; } -struct pa_packet* pa_packet_ref(struct pa_packet *p) { +pa_packet* pa_packet_ref(pa_packet *p) { assert(p && p->ref >= 1); p->ref++; return p; } -void pa_packet_unref(struct pa_packet *p) { +void pa_packet_unref(pa_packet *p) { assert(p && p->ref >= 1); p->ref--; diff --git a/polyp/packet.h b/polyp/packet.h index 5e4e92f78..0ac474857 100644 --- a/polyp/packet.h +++ b/polyp/packet.h @@ -25,17 +25,17 @@ #include #include -struct pa_packet { +typedef struct pa_packet { enum { PA_PACKET_APPENDED, PA_PACKET_DYNAMIC } type; unsigned ref; size_t length; uint8_t *data; -}; +} pa_packet; -struct pa_packet* pa_packet_new(size_t length); -struct pa_packet* pa_packet_new_dynamic(uint8_t* data, size_t length); +pa_packet* pa_packet_new(size_t length); +pa_packet* pa_packet_new_dynamic(uint8_t* data, size_t length); -struct pa_packet* pa_packet_ref(struct pa_packet *p); -void pa_packet_unref(struct pa_packet *p); +pa_packet* pa_packet_ref(pa_packet *p); +void pa_packet_unref(pa_packet *p); #endif diff --git a/polyp/pacmd.c b/polyp/pacmd.c index d69c14d7f..e6c0da6af 100644 --- a/polyp/pacmd.c +++ b/polyp/pacmd.c @@ -36,7 +36,7 @@ #include "log.h" #include "pid.h" -int main() { +int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { pid_t pid ; int fd = -1; int ret = 1, i; diff --git a/polyp/pactl.c b/polyp/pactl.c index 725b5460a..6943a11f1 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -47,14 +47,14 @@ #define BUFSIZE 1024 -static struct pa_context *context = NULL; -static struct pa_mainloop_api *mainloop_api = NULL; +static pa_context *context = NULL; +static pa_mainloop_api *mainloop_api = NULL; static char *device = NULL, *sample_name = NULL; static SNDFILE *sndfile = NULL; -static struct pa_stream *sample_stream = NULL; -static struct pa_sample_spec sample_spec; +static pa_stream *sample_stream = NULL; +static pa_sample_spec sample_spec; static size_t sample_length = 0; static int actions = 1; @@ -77,12 +77,12 @@ static void quit(int ret) { } -static void context_drain_complete(struct pa_context *c, void *userdata) { +static void context_drain_complete(pa_context *c, void *userdata) { pa_context_disconnect(c); } static void drain(void) { - struct pa_operation *o; + pa_operation *o; if (!(o = pa_context_drain(context, context_drain_complete, NULL))) pa_context_disconnect(context); else @@ -97,7 +97,7 @@ static void complete_action(void) { drain(); } -static void stat_callback(struct pa_context *c, const struct pa_stat_info *i, void *userdata) { +static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata) { char s[128]; if (!i) { fprintf(stderr, "Failed to get statistics: %s\n", pa_strerror(pa_context_errno(c))); @@ -117,7 +117,7 @@ static void stat_callback(struct pa_context *c, const struct pa_stat_info *i, vo complete_action(); } -static void get_server_info_callback(struct pa_context *c, const struct pa_server_info *i, void *useerdata) { +static void get_server_info_callback(pa_context *c, const pa_server_info *i, void *useerdata) { char s[PA_SAMPLE_SPEC_SNPRINT_MAX]; if (!i) { @@ -148,7 +148,7 @@ static void get_server_info_callback(struct pa_context *c, const struct pa_serve complete_action(); } -static void get_sink_info_callback(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata) { +static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) { char s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5]; if (is_last < 0) { @@ -191,7 +191,7 @@ static void get_sink_info_callback(struct pa_context *c, const struct pa_sink_in } -static void get_source_info_callback(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata) { +static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) { char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], tid[5]; if (is_last < 0) { @@ -234,7 +234,7 @@ static void get_source_info_callback(struct pa_context *c, const struct pa_sourc } -static void get_module_info_callback(struct pa_context *c, const struct pa_module_info *i, int is_last, void *userdata) { +static void get_module_info_callback(pa_context *c, const pa_module_info *i, int is_last, void *userdata) { char t[32]; if (is_last < 0) { @@ -268,7 +268,7 @@ static void get_module_info_callback(struct pa_context *c, const struct pa_modul i->auto_unload ? "yes" : "no"); } -static void get_client_info_callback(struct pa_context *c, const struct pa_client_info *i, int is_last, void *userdata) { +static void get_client_info_callback(pa_context *c, const pa_client_info *i, int is_last, void *userdata) { char t[32], tid[5]; if (is_last < 0) { @@ -300,7 +300,7 @@ static void get_client_info_callback(struct pa_context *c, const struct pa_clien i->owner_module != PA_INVALID_INDEX ? t : "n/a"); } -static void get_sink_input_info_callback(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) { +static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) { char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5]; if (is_last < 0) { @@ -349,7 +349,7 @@ static void get_sink_input_info_callback(struct pa_context *c, const struct pa_s } -static void get_source_output_info_callback(struct pa_context *c, const struct pa_source_output_info *i, int is_last, void *userdata) { +static void get_source_output_info_callback(pa_context *c, const pa_source_output_info *i, int is_last, void *userdata) { char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5]; if (is_last < 0) { @@ -395,7 +395,7 @@ static void get_source_output_info_callback(struct pa_context *c, const struct p i->resample_method ? i->resample_method : "n/a"); } -static void get_sample_info_callback(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata) { +static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) { char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX]; if (is_last < 0) { @@ -436,7 +436,7 @@ static void get_sample_info_callback(struct pa_context *c, const struct pa_sampl i->filename ? i->filename : "n/a"); } -static void get_autoload_info_callback(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata) { +static void get_autoload_info_callback(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata) { if (is_last < 0) { fprintf(stderr, "Failed to get autoload information: %s\n", pa_strerror(pa_context_errno(c))); quit(1); @@ -466,7 +466,7 @@ static void get_autoload_info_callback(struct pa_context *c, const struct pa_aut i->argument); } -static void simple_callback(struct pa_context *c, int success, void *userdata) { +static void simple_callback(pa_context *c, int success, void *userdata) { if (!success) { fprintf(stderr, "Failure: %s\n", pa_strerror(pa_context_errno(c))); quit(1); @@ -476,7 +476,7 @@ static void simple_callback(struct pa_context *c, int success, void *userdata) { complete_action(); } -static void stream_state_callback(struct pa_stream *s, void *userdata) { +static void stream_state_callback(pa_stream *s, void *userdata) { assert(s); switch (pa_stream_get_state(s)) { @@ -495,7 +495,7 @@ static void stream_state_callback(struct pa_stream *s, void *userdata) { } } -static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { +static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { sf_count_t l; float *d; assert(s && length && sndfile); @@ -522,7 +522,7 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user } } -static void context_state_callback(struct pa_context *c, void *userdata) { +static void context_state_callback(pa_context *c, void *userdata) { assert(c); switch (pa_context_get_state(c)) { case PA_CONTEXT_CONNECTING: @@ -587,7 +587,7 @@ static void context_state_callback(struct pa_context *c, void *userdata) { } } -static void exit_signal_callback(struct pa_mainloop_api *m, struct pa_signal_event *e, int sig, void *userdata) { +static void exit_signal_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); } @@ -610,7 +610,7 @@ static void help(const char *argv0) { enum { ARG_VERSION = 256 }; int main(int argc, char *argv[]) { - struct pa_mainloop* m = NULL; + pa_mainloop* m = NULL; char tmp[PATH_MAX]; int ret = 1, r, c; char *server = NULL, *client_name = NULL, *bn; diff --git a/polyp/paplay.c b/polyp/paplay.c index 4ace1973f..d9aa71a6d 100644 --- a/polyp/paplay.c +++ b/polyp/paplay.c @@ -44,9 +44,9 @@ #error Invalid Polypaudio API version #endif -static struct pa_context *context = NULL; -static struct pa_stream *stream = NULL; -static struct pa_mainloop_api *mainloop_api = NULL; +static pa_context *context = NULL; +static pa_stream *stream = NULL; +static pa_mainloop_api *mainloop_api = NULL; static char *stream_name = NULL, *client_name = NULL, *device = NULL; @@ -55,9 +55,9 @@ static pa_volume_t volume = PA_VOLUME_NORM; static SNDFILE* sndfile = NULL; -static struct pa_sample_spec sample_spec = { 0, 0, 0 }; +static pa_sample_spec sample_spec = { 0, 0, 0 }; -static sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames); +static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames); /* A shortcut for terminating the application */ static void quit(int ret) { @@ -66,13 +66,13 @@ static void quit(int ret) { } /* Connection draining complete */ -static void context_drain_complete(struct pa_context*c, void *userdata) { +static void context_drain_complete(pa_context*c, void *userdata) { pa_context_disconnect(c); } /* Stream draining complete */ -static void stream_drain_complete(struct pa_stream*s, int success, void *userdata) { - struct pa_operation *o; +static void stream_drain_complete(pa_stream*s, int success, void *userdata) { + pa_operation *o; if (!success) { fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); @@ -97,7 +97,7 @@ static void stream_drain_complete(struct pa_stream*s, int success, void *userdat } /* This is called whenever new data may be written to the stream */ -static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) { +static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { size_t k; sf_count_t f, n; void *data; @@ -125,7 +125,7 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user } /* This routine is called whenever the stream state changes */ -static void stream_state_callback(struct pa_stream *s, void *userdata) { +static void stream_state_callback(pa_stream *s, void *userdata) { assert(s); switch (pa_stream_get_state(s)) { @@ -146,7 +146,7 @@ static void stream_state_callback(struct pa_stream *s, void *userdata) { } /* This is called whenever the context status changes */ -static void context_state_callback(struct pa_context *c, void *userdata) { +static void context_state_callback(pa_context *c, void *userdata) { assert(c); switch (pa_context_get_state(c)) { @@ -183,7 +183,7 @@ static void context_state_callback(struct pa_context *c, void *userdata) { } /* UNIX signal to quit recieved */ -static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) { +static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { if (verbose) fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); @@ -211,9 +211,10 @@ enum { }; int main(int argc, char *argv[]) { - struct pa_mainloop* m = NULL; + pa_mainloop* m = NULL; int ret = 1, r, c; - char *bn, *server = NULL, *filename; + char *bn, *server = NULL; + const char *filename; SF_INFO sfinfo; static const struct option long_options[] = { @@ -312,12 +313,12 @@ int main(int argc, char *argv[]) { case SF_FORMAT_ULAW: case SF_FORMAT_ALAW: sample_spec.format = PA_SAMPLE_S16NE; - readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short; + readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_short; break; case SF_FORMAT_FLOAT: default: sample_spec.format = PA_SAMPLE_FLOAT32NE; - readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float; + readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_float; break; } diff --git a/polyp/parec-simple.c b/polyp/parec-simple.c index 130627d74..5f5abe111 100644 --- a/polyp/parec-simple.c +++ b/polyp/parec-simple.c @@ -30,6 +30,7 @@ #include #include +#include "gccmacro.h" #define BUFSIZE 1024 @@ -47,21 +48,21 @@ static ssize_t loop_write(int fd, const void*data, size_t size) { break; ret += r; - data = (uint8_t*) data + r; + data = (const uint8_t*) data + r; size -= r; } return ret; } -int main(int argc, char*argv[]) { +int main(PA_GCC_UNUSED int argc, char*argv[]) { /* The sample type to use */ - static const struct pa_sample_spec ss = { + static const pa_sample_spec ss = { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 }; - struct pa_simple *s = NULL; + pa_simple *s = NULL; int ret = 1; int error; diff --git a/polyp/parseaddr.c b/polyp/parseaddr.c index 05ed508b6..5e4c689ca 100644 --- a/polyp/parseaddr.c +++ b/polyp/parseaddr.c @@ -63,10 +63,10 @@ static char *parse_host(const char *s, uint16_t *ret_port) { } } -int pa_parse_address(const char *name, struct pa_parsed_address *ret_p) { +int pa_parse_address(const char *name, pa_parsed_address *ret_p) { const char *p; assert(name && ret_p); - memset(ret_p, 0, sizeof(struct pa_parsed_address)); + memset(ret_p, 0, sizeof(pa_parsed_address)); ret_p->type = PA_PARSED_ADDRESS_TCP_AUTO; if (*name == '{') { diff --git a/polyp/parseaddr.h b/polyp/parseaddr.h index 5ddc0351e..f0efd766a 100644 --- a/polyp/parseaddr.h +++ b/polyp/parseaddr.h @@ -24,19 +24,19 @@ #include -enum pa_parsed_address_type { +typedef enum pa_parsed_address_type { PA_PARSED_ADDRESS_UNIX, PA_PARSED_ADDRESS_TCP4, PA_PARSED_ADDRESS_TCP6, PA_PARSED_ADDRESS_TCP_AUTO -}; +} pa_parsed_address_type; -struct pa_parsed_address { - enum pa_parsed_address_type type; +typedef struct pa_parsed_address { + pa_parsed_address_type type; char *path_or_host; uint16_t port; -}; +} pa_parsed_address; -int pa_parse_address(const char *a, struct pa_parsed_address *ret_p); +int pa_parse_address(const char *a, pa_parsed_address *ret_p); #endif diff --git a/polyp/pax11publish.c b/polyp/pax11publish.c index a1cb006ab..42947836f 100644 --- a/polyp/pax11publish.c +++ b/polyp/pax11publish.c @@ -135,17 +135,17 @@ int main(int argc, char *argv[]) { } case EXPORT: { - struct pa_client_conf *c = pa_client_conf_new(); + pa_client_conf *conf = pa_client_conf_new(); uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; char hx[PA_NATIVE_COOKIE_LENGTH*2+1]; - assert(c); + assert(conf); - if (pa_client_conf_load(c, NULL) < 0) { + if (pa_client_conf_load(conf, NULL) < 0) { fprintf(stderr, "Failed to load client configuration file.\n"); goto finish; } - if (pa_client_conf_env(c) < 0) { + if (pa_client_conf_env(conf) < 0) { fprintf(stderr, "Failed to read environment configuration data.\n"); goto finish; } @@ -158,8 +158,8 @@ int main(int argc, char *argv[]) { if (server) pa_x11_set_prop(d, "POLYP_SERVER", server); - else if (c->default_server) - pa_x11_set_prop(d, "POLYP_SERVER", c->default_server); + else if (conf->default_server) + pa_x11_set_prop(d, "POLYP_SERVER", conf->default_server); else { char hn[256]; if (!pa_get_fqdn(hn, sizeof(hn))) { @@ -172,15 +172,15 @@ int main(int argc, char *argv[]) { if (sink) pa_x11_set_prop(d, "POLYP_SINK", sink); - else if (c->default_sink) - pa_x11_set_prop(d, "POLYP_SINK", c->default_sink); + else if (conf->default_sink) + pa_x11_set_prop(d, "POLYP_SINK", conf->default_sink); if (source) pa_x11_set_prop(d, "POLYP_SOURCE", source); - if (c->default_source) - pa_x11_set_prop(d, "POLYP_SOURCE", c->default_source); + if (conf->default_source) + pa_x11_set_prop(d, "POLYP_SOURCE", conf->default_source); - pa_client_conf_free(c); + pa_client_conf_free(conf); if (pa_authkey_load_auto(cookie_file, cookie, sizeof(cookie)) < 0) { fprintf(stderr, "Failed to load cookie data\n"); diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index 60dd911c3..5a50a0d57 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -91,21 +91,21 @@ static const char *command_names[PA_COMMAND_MAX] = { #endif struct reply_info { - struct pa_pdispatch *pdispatch; + pa_pdispatch *pdispatch; PA_LLIST_FIELDS(struct reply_info); - void (*callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); + pa_pdispatch_callback callback; void *userdata; uint32_t tag; - struct pa_time_event *time_event; + pa_time_event *time_event; }; struct pa_pdispatch { int ref; - struct pa_mainloop_api *mainloop; - const struct pa_pdispatch_command *command_table; + pa_mainloop_api *mainloop; + const pa_pdispatch_callback *callback_table; unsigned n_commands; PA_LLIST_HEAD(struct reply_info, replies); - void (*drain_callback)(struct pa_pdispatch *pd, void *userdata); + pa_pdispatch_drain_callback drain_callback; void *drain_userdata; }; @@ -120,25 +120,25 @@ static void reply_info_free(struct reply_info *r) { pa_xfree(r); } -struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *mainloop, const struct pa_pdispatch_command*table, unsigned entries) { - struct pa_pdispatch *pd; +pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_callback*table, unsigned entries) { + pa_pdispatch *pd; assert(mainloop); assert((entries && table) || (!entries && !table)); - pd = pa_xmalloc(sizeof(struct pa_pdispatch)); + pd = pa_xmalloc(sizeof(pa_pdispatch)); pd->ref = 1; pd->mainloop = mainloop; - pd->command_table = table; + pd->callback_table = table; pd->n_commands = entries; - PA_LLIST_HEAD_INIT(struct pa_reply_info, pd->replies); + PA_LLIST_HEAD_INIT(pa_reply_info, pd->replies); pd->drain_callback = NULL; pd->drain_userdata = NULL; return pd; } -void pdispatch_free(struct pa_pdispatch *pd) { +static void pdispatch_free(pa_pdispatch *pd) { assert(pd); while (pd->replies) @@ -147,8 +147,8 @@ void pdispatch_free(struct pa_pdispatch *pd) { pa_xfree(pd); } -static void run_action(struct pa_pdispatch *pd, struct reply_info *r, uint32_t command, struct pa_tagstruct *ts) { - void (*callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command, pa_tagstruct *ts) { + pa_pdispatch_callback callback; void *userdata; uint32_t tag; assert(r); @@ -169,9 +169,9 @@ static void run_action(struct pa_pdispatch *pd, struct reply_info *r, uint32_t c pa_pdispatch_unref(pd); } -int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *userdata) { +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, void *userdata) { uint32_t tag, command; - struct pa_tagstruct *ts = NULL; + pa_tagstruct *ts = NULL; int ret = -1; assert(pd && packet && packet->data); @@ -208,10 +208,10 @@ int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *use if (r) run_action(pd, r, command, ts); - } else if (pd->command_table && (command < pd->n_commands) && pd->command_table[command].proc) { - const struct pa_pdispatch_command *c = pd->command_table+command; + } else if (pd->callback_table && (command < pd->n_commands) && pd->callback_table[command]) { + const pa_pdispatch_callback *c = pd->callback_table+command; - c->proc(pd, command, tag, ts, userdata); + (*c)(pd, command, tag, ts, userdata); } else { pa_log(__FILE__": Recieved unsupported command %u\n", command); goto finish; @@ -228,14 +228,14 @@ finish: return ret; } -static void timeout_callback(struct pa_mainloop_api*m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { +static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { struct reply_info*r = userdata; assert(r && r->time_event == e && r->pdispatch && r->pdispatch->mainloop == m && r->callback); run_action(r->pdispatch, r, PA_COMMAND_TIMEOUT, NULL); } -void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int timeout, void (*cb)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void *userdata) { +void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_callback cb, void *userdata) { struct reply_info *r; struct timeval tv; assert(pd && pd->ref >= 1 && cb); @@ -255,13 +255,13 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time PA_LLIST_PREPEND(struct reply_info, pd->replies, r); } -int pa_pdispatch_is_pending(struct pa_pdispatch *pd) { +int pa_pdispatch_is_pending(pa_pdispatch *pd) { assert(pd); return !!pd->replies; } -void pa_pdispatch_set_drain_callback(struct pa_pdispatch *pd, void (*cb)(struct pa_pdispatch *pd, void *userdata), void *userdata) { +void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, void (*cb)(pa_pdispatch *pd, void *userdata), void *userdata) { assert(pd); assert(!cb || pa_pdispatch_is_pending(pd)); @@ -269,7 +269,7 @@ void pa_pdispatch_set_drain_callback(struct pa_pdispatch *pd, void (*cb)(struct pd->drain_userdata = userdata; } -void pa_pdispatch_unregister_reply(struct pa_pdispatch *pd, void *userdata) { +void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata) { struct reply_info *r, *n; assert(pd); @@ -281,14 +281,14 @@ void pa_pdispatch_unregister_reply(struct pa_pdispatch *pd, void *userdata) { } } -void pa_pdispatch_unref(struct pa_pdispatch *pd) { +void pa_pdispatch_unref(pa_pdispatch *pd) { assert(pd && pd->ref >= 1); if (!(--(pd->ref))) pdispatch_free(pd); } -struct pa_pdispatch* pa_pdispatch_ref(struct pa_pdispatch *pd) { +pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd) { assert(pd && pd->ref >= 1); pd->ref++; return pd; diff --git a/polyp/pdispatch.h b/polyp/pdispatch.h index 571d0fb44..40f5d4c42 100644 --- a/polyp/pdispatch.h +++ b/polyp/pdispatch.h @@ -27,25 +27,24 @@ #include "packet.h" #include "mainloop-api.h" -struct pa_pdispatch; +typedef struct pa_pdispatch pa_pdispatch; -struct pa_pdispatch_command { - void (*proc)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -}; +typedef void (*pa_pdispatch_callback)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -struct pa_pdispatch* pa_pdispatch_new(struct pa_mainloop_api *m, const struct pa_pdispatch_command*table, unsigned entries); -void pa_pdispatch_unref(struct pa_pdispatch *pd); -struct pa_pdispatch* pa_pdispatch_ref(struct pa_pdispatch *pd); +pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_callback*table, unsigned entries); +void pa_pdispatch_unref(pa_pdispatch *pd); +pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); -int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*p, void *userdata); +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, void *userdata); -void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int timeout, void (*cb)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void *userdata); +void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_callback callback, void *userdata); -int pa_pdispatch_is_pending(struct pa_pdispatch *pd); +int pa_pdispatch_is_pending(pa_pdispatch *pd); -void pa_pdispatch_set_drain_callback(struct pa_pdispatch *pd, void (*cb)(struct pa_pdispatch *pd, void *userdata), void *userdata); +typedef void (*pa_pdispatch_drain_callback)(pa_pdispatch *pd, void *userdata); +void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, pa_pdispatch_drain_callback callback, void *userdata); /* Remove all reply slots with the give userdata parameter */ -void pa_pdispatch_unregister_reply(struct pa_pdispatch *pd, void *userdata); +void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata); #endif diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index c7a854545..c3db14627 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -31,11 +31,12 @@ #include "play-memchunk.h" #include "sink-input.h" #include "xmalloc.h" +#include "gccmacro.h" #define PA_TYPEID_MEMCHUNK PA_TYPEID_MAKE('M', 'C', 'N', 'K') -static void sink_input_kill(struct pa_sink_input *i) { - struct pa_memchunk *c; +static void sink_input_kill(pa_sink_input *i) { + pa_memchunk *c; assert(i && i->userdata); c = i->userdata; @@ -47,8 +48,8 @@ static void sink_input_kill(struct pa_sink_input *i) { } -static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { - struct pa_memchunk *c; +static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { + pa_memchunk *c; assert(i && chunk && i->userdata); c = i->userdata; @@ -62,12 +63,12 @@ static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { return 0; } -static void si_kill(struct pa_mainloop_api *m, void *i) { +static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) { sink_input_kill(i); } -static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk*chunk, size_t length) { - struct pa_memchunk *c; +static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) { + pa_memchunk *c; assert(i && length && i->userdata); c = i->userdata; @@ -81,9 +82,9 @@ static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk*ch pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); } -int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, pa_volume_t volume) { - struct pa_sink_input *si; - struct pa_memchunk *nchunk; +int pa_play_memchunk(pa_sink *sink, const char *name, const pa_sample_spec *ss, const pa_memchunk *chunk, pa_volume_t volume) { + pa_sink_input *si; + pa_memchunk *nchunk; assert(sink && chunk); @@ -98,7 +99,7 @@ int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sam si->drop = sink_input_drop; si->kill = sink_input_kill; - si->userdata = nchunk = pa_xmalloc(sizeof(struct pa_memchunk)); + si->userdata = nchunk = pa_xmalloc(sizeof(pa_memchunk)); *nchunk = *chunk; pa_memblock_ref(chunk->memblock); diff --git a/polyp/play-memchunk.h b/polyp/play-memchunk.h index c69165a29..247cc8708 100644 --- a/polyp/play-memchunk.h +++ b/polyp/play-memchunk.h @@ -25,6 +25,6 @@ #include "sink.h" #include "memchunk.h" -int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sample_spec *ss, const struct pa_memchunk *chunk, pa_volume_t volume); +int pa_play_memchunk(pa_sink *sink, const char *name, const pa_sample_spec *ss, const pa_memchunk *chunk, pa_volume_t volume); #endif diff --git a/polyp/polyplib-browser.c b/polyp/polyplib-browser.c index 2e75a42dc..6fee84a4a 100644 --- a/polyp/polyplib-browser.c +++ b/polyp/polyplib-browser.c @@ -31,20 +31,20 @@ #define SERVICE_NAME_SOURCE "_polypaudio-source._tcp." #define SERVICE_NAME_SERVER "_polypaudio-server._tcp." -struct pa_browser { +pa_browser { int ref; - struct pa_mainloop_api *mainloop; + pa_mainloop_api *mainloop; - void (*callback)(struct pa_browser *z, enum pa_browse_opcode c, const struct pa_browse_info *i, void *userdata); + void (*callback)(pa_browser *z, pa_browse_opcode c, const pa_browse_info *i, void *userdata); void *callback_userdata; sw_discovery discovery; - struct pa_io_event *io_event; + pa_io_event *io_event; }; -static void io_callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags events, void *userdata) { - struct pa_browser *b = userdata; +static void io_callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags events, void *userdata) { + pa_browser *b = userdata; assert(a && b && b->mainloop == a); if (events != PA_IO_EVENT_INPUT || sw_discovery_read_socket(b->discovery) != SW_OKAY) { @@ -68,14 +68,14 @@ static sw_result resolve_reply( sw_ulong text_record_len, sw_opaque extra) { - struct pa_browser *b = extra; - struct pa_browse_info i; + pa_browser *b = extra; + pa_browse_info i; char ip[256], a[256]; - enum pa_browse_opcode opcode; + pa_browse_opcode opcode; int device_found = 0; uint32_t cookie; pa_typeid_t typeid; - struct pa_sample_spec ss; + pa_sample_spec ss; int ss_valid = 0; sw_text_record_iterator iterator; int free_iterator = 0; @@ -221,7 +221,7 @@ static sw_result browse_reply( sw_const_string domain, sw_opaque extra) { - struct pa_browser *b = extra; + pa_browser *b = extra; assert(b); switch (status) { @@ -236,7 +236,7 @@ static sw_result browse_reply( case SW_DISCOVERY_BROWSE_REMOVE_SERVICE: if (b->callback) { - struct pa_browse_info i; + pa_browse_info i; memset(&i, 0, sizeof(i)); i.name = name; b->callback(b, PA_BROWSE_REMOVE, &i, b->callback_userdata); @@ -250,11 +250,11 @@ static sw_result browse_reply( return SW_OKAY; } -struct pa_browser *pa_browser_new(struct pa_mainloop_api *mainloop) { - struct pa_browser *b; +pa_browser *pa_browser_new(pa_mainloop_api *mainloop) { + pa_browser *b; sw_discovery_oid oid; - b = pa_xmalloc(sizeof(struct pa_browser)); + b = pa_xmalloc(sizeof(pa_browser)); b->mainloop = mainloop; b->ref = 1; b->callback = NULL; @@ -281,7 +281,7 @@ struct pa_browser *pa_browser_new(struct pa_mainloop_api *mainloop) { return b; } -static void browser_free(struct pa_browser *b) { +static void browser_free(pa_browser *b) { assert(b && b->mainloop); if (b->io_event) @@ -291,20 +291,20 @@ static void browser_free(struct pa_browser *b) { pa_xfree(b); } -struct pa_browser *pa_browser_ref(struct pa_browser *b) { +pa_browser *pa_browser_ref(pa_browser *b) { assert(b && b->ref >= 1); b->ref++; return b; } -void pa_browser_unref(struct pa_browser *b) { +void pa_browser_unref(pa_browser *b) { assert(b && b->ref >= 1); if ((-- (b->ref)) <= 0) browser_free(b); } -void pa_browser_set_callback(struct pa_browser *b, void (*cb)(struct pa_browser *z, enum pa_browse_opcode c, const struct pa_browse_info *i, void* userdata), void *userdata) { +void pa_browser_set_callback(pa_browser *b, void (*cb)(pa_browser *z, pa_browse_opcode c, const pa_browse_info *i, void* userdata), void *userdata) { assert(b); b->callback = cb; diff --git a/polyp/polyplib-browser.h b/polyp/polyplib-browser.h index c13eff227..853304d7d 100644 --- a/polyp/polyplib-browser.h +++ b/polyp/polyplib-browser.h @@ -29,20 +29,20 @@ PA_C_DECL_BEGIN -struct pa_browser; +pa_browser; -enum pa_browse_opcode { +pa_browse_opcode { PA_BROWSE_NEW_SERVER, PA_BROWSE_NEW_SINK, PA_BROWSE_NEW_SOURCE, PA_BROWSE_REMOVE }; -struct pa_browser *pa_browser_new(struct pa_mainloop_api *mainloop); -struct pa_browser *pa_browser_ref(struct pa_browser *z); -void pa_browser_unref(struct pa_browser *z); +pa_browser *pa_browser_new(pa_mainloop_api *mainloop); +pa_browser *pa_browser_ref(pa_browser *z); +void pa_browser_unref(pa_browser *z); -struct pa_browse_info { +pa_browse_info { /* Unique service name */ const char *name; /* always available */ @@ -55,10 +55,10 @@ struct pa_browse_info { const char *device; /* always available when this information is of a sink/source */ const char *description; /* optional */ const pa_typeid_t *typeid; /* optional */ - const struct pa_sample_spec *sample_spec; /* optional */ + const pa_sample_spec *sample_spec; /* optional */ }; -void pa_browser_set_callback(struct pa_browser *z, void (*cb)(struct pa_browser *z, enum pa_browse_opcode c, const struct pa_browse_info *i, void *userdata), void *userdata); +void pa_browser_set_callback(pa_browser *z, void (*cb)(pa_browser *z, pa_browse_opcode c, const pa_browse_info *i, void *userdata), void *userdata); PA_C_DECL_END diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index f97d9b827..0cf324901 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -49,6 +49,7 @@ #include "polyplib-internal.h" #include "polyplib-context.h" +#include "polyplib-version.h" #include "native-common.h" #include "pdispatch.h" #include "pstream.h" @@ -67,14 +68,14 @@ #define AUTOSPAWN_LOCK "autospawn.lock" -static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { - [PA_COMMAND_REQUEST] = { pa_command_request }, - [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { pa_command_stream_killed }, - [PA_COMMAND_RECORD_STREAM_KILLED] = { pa_command_stream_killed }, - [PA_COMMAND_SUBSCRIBE_EVENT] = { pa_command_subscribe_event }, +static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_REQUEST] = pa_command_request, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = pa_command_stream_killed, + [PA_COMMAND_RECORD_STREAM_KILLED] = pa_command_stream_killed, + [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event }; -static void unlock_autospawn_lock_file(struct pa_context *c) { +static void unlock_autospawn_lock_file(pa_context *c) { assert(c); if (c->autospawn_lock_fd >= 0) { @@ -86,11 +87,11 @@ static void unlock_autospawn_lock_file(struct pa_context *c) { } } -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) { - struct pa_context *c; +pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { + pa_context *c; assert(mainloop && name); - c = pa_xmalloc(sizeof(struct pa_context)); + c = pa_xmalloc(sizeof(pa_context)); c->ref = 1; c->name = pa_xstrdup(name); c->mainloop = mainloop; @@ -101,8 +102,8 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->record_streams = pa_dynarray_new(); assert(c->playback_streams && c->record_streams); - PA_LLIST_HEAD_INIT(struct pa_stream, c->streams); - PA_LLIST_HEAD_INIT(struct pa_operation, c->operations); + PA_LLIST_HEAD_INIT(pa_stream, c->streams); + PA_LLIST_HEAD_INIT(pa_operation, c->operations); c->error = PA_ERROR_OK; c->state = PA_CONTEXT_UNCONNECTED; @@ -136,7 +137,7 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * return c; } -static void context_free(struct pa_context *c) { +static void context_free(pa_context *c) { assert(c); unlock_autospawn_lock_file(c); @@ -173,20 +174,20 @@ static void context_free(struct pa_context *c) { pa_xfree(c); } -struct pa_context* pa_context_ref(struct pa_context *c) { +pa_context* pa_context_ref(pa_context *c) { assert(c && c->ref >= 1); c->ref++; return c; } -void pa_context_unref(struct pa_context *c) { +void pa_context_unref(pa_context *c) { assert(c && c->ref >= 1); if ((--(c->ref)) == 0) context_free(c); } -void pa_context_set_state(struct pa_context *c, enum pa_context_state st) { +void pa_context_set_state(pa_context *c, pa_context_state st) { assert(c); if (c->state == st) @@ -195,11 +196,11 @@ void pa_context_set_state(struct pa_context *c, enum pa_context_state st) { pa_context_ref(c); if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) { - struct pa_stream *s; + pa_stream *s; s = c->streams ? pa_stream_ref(c->streams) : NULL; while (s) { - struct pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL; + pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL; pa_stream_set_state(s, st == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED); pa_stream_unref(s); s = n; @@ -227,20 +228,20 @@ void pa_context_set_state(struct pa_context *c, enum pa_context_state st) { pa_context_unref(c); } -void pa_context_fail(struct pa_context *c, int error) { +void pa_context_fail(pa_context *c, int error) { assert(c); c->error = error; pa_context_set_state(c, PA_CONTEXT_FAILED); } -static void pstream_die_callback(struct pa_pstream *p, void *userdata) { - struct pa_context *c = userdata; +static void pstream_die_callback(pa_pstream *p, void *userdata) { + pa_context *c = userdata; assert(p && c); pa_context_fail(c, PA_ERROR_CONNECTIONTERMINATED); } -static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { - struct pa_context *c = userdata; +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *userdata) { + pa_context *c = userdata; assert(p && packet && c); pa_context_ref(c); @@ -253,9 +254,9 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack pa_context_unref(c); } -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; +static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, PA_GCC_UNUSED uint32_t delta, const pa_memchunk *chunk, void *userdata) { + pa_context *c = userdata; + pa_stream *s; assert(p && chunk && c && chunk->memblock && chunk->memblock->data); pa_context_ref(c); @@ -264,7 +265,7 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui pa_mcalign_push(s->mcalign, chunk); for (;;) { - struct pa_memchunk t; + pa_memchunk t; if (pa_mcalign_pop(s->mcalign, &t) < 0) break; @@ -281,7 +282,7 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui pa_context_unref(c); } -int pa_context_handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) { +int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { assert(c); if (command == PA_COMMAND_ERROR) { @@ -302,8 +303,8 @@ int pa_context_handle_error(struct pa_context *c, uint32_t command, struct pa_ta return 0; } -static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; +static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_context *c = userdata; assert(pd && c && (c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME)); pa_context_ref(c); @@ -319,13 +320,12 @@ static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, u switch(c->state) { case PA_CONTEXT_AUTHORIZING: { - struct pa_tagstruct *t; - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_SET_CLIENT_NAME); - pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_puts(t, c->name); - pa_pstream_send_tagstruct(c->pstream, t); + pa_tagstruct *reply; + reply = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME); + pa_tagstruct_putu32(reply, tag = c->ctag++); + pa_tagstruct_puts(reply, c->name); + pa_pstream_send_tagstruct(c->pstream, reply); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); pa_context_set_state(c, PA_CONTEXT_SETTING_NAME); @@ -344,8 +344,8 @@ finish: pa_context_unref(c); } -static void setup_context(struct pa_context *c, struct pa_iochannel *io) { - struct pa_tagstruct *t; +static void setup_context(pa_context *c, pa_iochannel *io) { + pa_tagstruct *t; uint32_t tag; assert(c && io); @@ -383,15 +383,15 @@ finish: pa_context_unref(c); } -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata); +static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata); #ifndef OS_IS_WIN32 -static int context_connect_spawn(struct pa_context *c) { +static int context_connect_spawn(pa_context *c) { pid_t pid; int status, r; int fds[2] = { -1, -1} ; - struct pa_iochannel *io; + pa_iochannel *io; pa_context_ref(c); @@ -423,7 +423,7 @@ static int context_connect_spawn(struct pa_context *c) { char t[128]; const char *state = NULL; #define MAX_ARGS 64 - char *argv[MAX_ARGS+1]; + const char * argv[MAX_ARGS+1]; int n; /* Not required, since fds[0] has CLOEXEC enabled anyway */ @@ -453,7 +453,7 @@ static int context_connect_spawn(struct pa_context *c) { argv[n++] = NULL; - execv(argv[0], argv); + execv(argv[0], (char * const *) argv); _exit(1); #undef MAX_ARGS } @@ -502,7 +502,7 @@ fail: #endif /* OS_IS_WIN32 */ -static int try_next_connection(struct pa_context *c) { +static int try_next_connection(pa_context *c) { char *u = NULL; int r = -1; assert(c && !c->client); @@ -549,8 +549,8 @@ finish: return r; } -static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) { - struct pa_context *c = userdata; +static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) { + pa_context *c = userdata; assert(client && c && c->state == PA_CONTEXT_CONNECTING); pa_context_ref(c); @@ -576,7 +576,7 @@ finish: pa_context_unref(c); } -int pa_context_connect(struct pa_context *c, const char *server, int spawn, const struct pa_spawn_api *api) { +int pa_context_connect(pa_context *c, const char *server, int spawn, const pa_spawn_api *api) { int r = -1; assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED); @@ -639,28 +639,28 @@ finish: return r; } -void pa_context_disconnect(struct pa_context *c) { +void pa_context_disconnect(pa_context *c) { assert(c); pa_context_set_state(c, PA_CONTEXT_TERMINATED); } -enum pa_context_state pa_context_get_state(struct pa_context *c) { +pa_context_state pa_context_get_state(pa_context *c) { assert(c && c->ref >= 1); return c->state; } -int pa_context_errno(struct pa_context *c) { +int pa_context_errno(pa_context *c) { assert(c && c->ref >= 1); return c->error; } -void pa_context_set_state_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) { +void pa_context_set_state_callback(pa_context *c, void (*cb)(pa_context *c, void *userdata), void *userdata) { assert(c && c->ref >= 1); c->state_callback = cb; c->state_userdata = userdata; } -int pa_context_is_pending(struct pa_context *c) { +int pa_context_is_pending(pa_context *c) { assert(c && c->ref >= 1); /* pa_log("pstream: %i\n", pa_pstream_is_pending(c->pstream)); */ @@ -671,17 +671,17 @@ int pa_context_is_pending(struct pa_context *c) { c->client; } -static void set_dispatch_callbacks(struct pa_operation *o); +static void set_dispatch_callbacks(pa_operation *o); -static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) { +static void pdispatch_drain_callback(PA_GCC_UNUSED pa_pdispatch*pd, void *userdata) { set_dispatch_callbacks(userdata); } -static void pstream_drain_callback(struct pa_pstream *s, void *userdata) { +static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata) { set_dispatch_callbacks(userdata); } -static void set_dispatch_callbacks(struct pa_operation *o) { +static void set_dispatch_callbacks(pa_operation *o) { int done = 1; assert(o && o->context && o->context->ref >= 1 && o->ref >= 1 && o->context->state == PA_CONTEXT_READY); @@ -702,8 +702,8 @@ static void set_dispatch_callbacks(struct pa_operation *o) { pa_operation_ref(o); else { if (o->callback) { - void (*cb)(struct pa_context *c, void *userdata); - cb = (void (*)(struct pa_context*, void*)) o->callback; + void (*cb)(pa_context *c, void *userdata); + cb = (void (*)(pa_context*, void*)) o->callback; cb(o->context, o->userdata); } @@ -713,8 +713,8 @@ static void set_dispatch_callbacks(struct pa_operation *o) { pa_operation_unref(o); } -struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct pa_context*c, void *userdata), void *userdata) { - struct pa_operation *o; +pa_operation* pa_context_drain(pa_context *c, void (*cb) (pa_context*c, void *userdata), void *userdata) { + pa_operation *o; assert(c && c->ref >= 1); if (c->state != PA_CONTEXT_READY) @@ -725,7 +725,7 @@ struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct p o = pa_operation_new(c, NULL); assert(o); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; set_dispatch_callbacks(pa_operation_ref(o)); @@ -733,8 +733,8 @@ struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct p return o; } -void pa_context_exit_daemon(struct pa_context *c) { - struct pa_tagstruct *t; +void pa_context_exit_daemon(pa_context *c) { + pa_tagstruct *t; assert(c && c->ref >= 1); t = pa_tagstruct_new(NULL, 0); @@ -744,8 +744,8 @@ void pa_context_exit_daemon(struct pa_context *c) { pa_pstream_send_tagstruct(c->pstream, t); } -void pa_context_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; +void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; int success = 1; assert(pd && o && o->context && o->ref >= 1); @@ -760,7 +760,7 @@ void pa_context_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, u } if (o->callback) { - void (*cb)(struct pa_context *c, int success, void *userdata) = o->callback; + void (*cb)(pa_context *c, int _success, void *_userdata) = (void (*)(pa_context *c, int _success, void *_userdata)) o->callback; cb(o->context, success, o->userdata); } @@ -769,9 +769,9 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32_t command, void (*internal_callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void (*cb)(), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, void (*internal_callback)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata), void (*cb)(void), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); @@ -788,14 +788,14 @@ struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32 return pa_operation_ref(o); } -struct pa_operation* pa_context_set_default_sink(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -808,14 +808,14 @@ struct pa_operation* pa_context_set_default_sink(struct pa_context *c, const cha return pa_operation_ref(o); } -struct pa_operation* pa_context_set_default_source(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_set_default_source(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -828,19 +828,19 @@ struct pa_operation* pa_context_set_default_source(struct pa_context *c, const c return pa_operation_ref(o); } -int pa_context_is_local(struct pa_context *c) { +int pa_context_is_local(pa_context *c) { assert(c); return c->local; } -struct pa_operation* pa_context_set_name(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_set_name(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && name && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -857,7 +857,7 @@ const char* pa_get_library_version(void) { return PACKAGE_VERSION; } -const char* pa_context_get_server(struct pa_context *c) { +const char* pa_context_get_server(pa_context *c) { if (!c->server) return NULL; diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 0283312a7..80c1b6014 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -49,31 +49,33 @@ PA_C_DECL_BEGIN -/** \struct pa_context +/** \pa_context * An opaque connection context to a daemon */ -struct pa_context; +typedef struct pa_context pa_context; /** Instantiate a new connection context with an abstract mainloop API * and an application name */ -struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name); +pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name); /** Decrease the reference counter of the context by one */ -void pa_context_unref(struct pa_context *c); +void pa_context_unref(pa_context *c); /** Increase the reference counter of the context by one */ -struct pa_context* pa_context_ref(struct pa_context *c); +pa_context* pa_context_ref(pa_context *c); + +typedef void (*pa_context_state_callback)(pa_context *c, void *userdata); /** Set a callback function that is called whenever the context status changes */ -void pa_context_set_state_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata); +void pa_context_set_state_callback(pa_context *c, pa_context_state_callback callback, void *userdata); /** Return the error number of the last failed operation */ -int pa_context_errno(struct pa_context *c); +int pa_context_errno(pa_context *c); /** Return non-zero if some data is pending to be written to the connection */ -int pa_context_is_pending(struct pa_context *c); +int pa_context_is_pending(pa_context *c); /** Return the current context status */ -enum pa_context_state pa_context_get_state(struct pa_context *c); +pa_context_state pa_context_get_state(pa_context *c); /** Connect the context to the specified server. If server is NULL, connect to the default server. This routine may but will not always @@ -82,33 +84,33 @@ be notified when the connection is established. If spawn is non-zero and no specific server is specified or accessible a new daemon is spawned. If api is non-NULL, the functions specified in the structure are used when forking a new child process. */ -int pa_context_connect(struct pa_context *c, const char *server, int spawn, const struct pa_spawn_api *api); +int pa_context_connect(pa_context *c, const char *server, int spawn, const pa_spawn_api *api); /** Terminate the context connection immediately */ -void pa_context_disconnect(struct pa_context *c); +void pa_context_disconnect(pa_context *c); /** Drain the context. If there is nothing to drain, the function returns NULL */ -struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct pa_context*c, void *userdata), void *userdata); +pa_operation* pa_context_drain(pa_context *c, void (*cb) (pa_context*c, void *userdata), void *userdata); /** Tell the daemon to exit. No operation object is returned as the * connection is terminated when the daemon quits, thus this operation * would never complete. */ -void pa_context_exit_daemon(struct pa_context *c); +void pa_context_exit_daemon(pa_context *c); /** Set the name of the default sink. \since 0.4 */ -struct pa_operation* pa_context_set_default_sink(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata); /** Set the name of the default source. \since 0.4 */ -struct pa_operation* pa_context_set_default_source(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_default_source(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata); /** Returns 1 when the connection is to a local daemon. Returns negative when no connection has been made yet. \since 0.5 */ -int pa_context_is_local(struct pa_context *c); +int pa_context_is_local(pa_context *c); /** Set a different application name for context on the server. \since 0.5 */ -struct pa_operation* pa_context_set_name(struct pa_context *c, const char *name, void(*cb)(struct pa_context*c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_name(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata); /** Return the server name this context is connected to. \since 0.7 */ -const char* pa_context_get_server(struct pa_context *c); +const char* pa_context_get_server(pa_context *c); PA_C_DECL_END diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 9adb68fc9..499282c4d 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -35,7 +35,7 @@ PA_C_DECL_BEGIN /** The state of a connection context */ -enum pa_context_state { +typedef enum pa_context_state { PA_CONTEXT_UNCONNECTED, /**< The context hasn't been connected yet */ PA_CONTEXT_CONNECTING, /**< A connection is being established */ PA_CONTEXT_AUTHORIZING, /**< The client is authorizing itself to the daemon */ @@ -43,37 +43,37 @@ enum pa_context_state { PA_CONTEXT_READY, /**< The connection is established, the context is ready to execute operations */ PA_CONTEXT_FAILED, /**< The connection failed or was disconnected */ PA_CONTEXT_TERMINATED /**< The connection was terminated cleanly */ -}; +} pa_context_state; /** The state of a stream */ -enum pa_stream_state { +typedef enum pa_stream_state { PA_STREAM_DISCONNECTED, /**< The stream is not yet connected to any sink or source */ PA_STREAM_CREATING, /**< The stream is being created */ PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */ PA_STREAM_FAILED, /**< An error occured that made the stream invalid */ PA_STREAM_TERMINATED /**< The stream has been terminated cleanly */ -}; +} pa_stream_state; /** The state of an operation */ -enum pa_operation_state { +typedef enum pa_operation_state { PA_OPERATION_RUNNING, /**< The operation is still running */ PA_OPERATION_DONE, /**< The operation has been completed */ PA_OPERATION_CANCELED /**< The operation has been canceled */ -}; +} pa_operation_state; /** An invalid index */ #define PA_INVALID_INDEX ((uint32_t) -1) /** The direction of a pa_stream object */ -enum pa_stream_direction { +typedef enum pa_stream_direction { PA_STREAM_NODIRECTION, /**< Invalid direction */ PA_STREAM_PLAYBACK, /**< Playback stream */ PA_STREAM_RECORD, /**< Record stream */ PA_STREAM_UPLOAD /**< Sample upload stream */ -}; +} pa_stream_direction; /** Some special flags for stream connections. \since 0.6 */ -enum pa_stream_flags { +typedef enum pa_stream_flags { PA_STREAM_START_CORKED = 1, /**< Create the stream corked, requiring an explicit pa_stream_cork() call to uncork it. */ PA_STREAM_INTERPOLATE_LATENCY = 2 /**< Interpolate the latency for * this stream. When enabled, @@ -90,16 +90,16 @@ enum pa_stream_flags { * information. This is * especially useful on long latency * network connections. */ -}; +} pa_stream_flags; /** Playback and record buffer metrics */ -struct pa_buffer_attr{ +typedef struct pa_buffer_attr { uint32_t maxlength; /**< Maximum length of the buffer */ uint32_t tlength; /**< Playback only: target length of the buffer. The server tries to assure that at least tlength bytes are always available in the buffer */ uint32_t prebuf; /**< Playback only: pre-buffering. The server does not start with playback before at least prebug bytes are available in the buffer */ uint32_t minreq; /**< Playback only: minimum request. The server does not request less than minreq bytes from the client, instead waints until the buffer is free enough to request more bytes at once */ uint32_t fragsize; /**< Recording only: fragment size. The server sends data in blocks of fragsize bytes size. Large values deminish interactivity with other operations on the connection context but decrease control overhead. */ -}; +} pa_buffer_attr; /** Error values as used by pa_context_errno(). Use pa_strerror() to convert these values to human readable strings */ enum { @@ -122,7 +122,7 @@ enum { }; /** Subscription event mask, as used by pa_context_subscribe() */ -enum pa_subscription_mask { +typedef enum pa_subscription_mask { PA_SUBSCRIPTION_MASK_NULL = 0, /**< No events */ PA_SUBSCRIPTION_MASK_SINK = 1, /**< Sink events */ PA_SUBSCRIPTION_MASK_SOURCE = 2, /**< Source events */ @@ -133,10 +133,10 @@ enum pa_subscription_mask { PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */ PA_SUBSCRIPTION_MASK_SERVER = 128, /**< Other global server changes. \since 0.4 */ PA_SUBSCRIPTION_MASK_AUTOLOAD = 256 /**< Autoload table events. \since 0.5 */ -}; +} pa_subscription_mask; /** Subscription event types, as used by pa_context_subscribe() */ -enum pa_subscription_event_type { +typedef enum pa_subscription_event_type { PA_SUBSCRIPTION_EVENT_SINK = 0, /**< Event type: Sink */ PA_SUBSCRIPTION_EVENT_SOURCE = 1, /**< Event type: Source */ PA_SUBSCRIPTION_EVENT_SINK_INPUT = 2, /**< Event type: Sink input */ @@ -152,7 +152,7 @@ enum pa_subscription_event_type { PA_SUBSCRIPTION_EVENT_CHANGE = 16, /**< A property of the object was modified */ PA_SUBSCRIPTION_EVENT_REMOVE = 32, /**< An object was removed */ PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32 /**< A mask to extract the event operation from an event value */ -}; +} pa_subscription_event_type; /** Return one if an event type t matches an event mask bitfield */ #define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) @@ -170,7 +170,7 @@ enum pa_subscription_event_type { * source_usec+buffer_usec+transport_usec-sink_usec. (Take care of * sign issues!) When connected to a monitor source sink_usec contains * the latency of the owning sink.*/ -struct pa_latency_info { +typedef struct pa_latency_info { pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play. For both playback and record streams. */ pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. For playback streams and record streams connected to a monitor source. */ pa_usec_t source_usec; /**< Time in usecs a sample takes from being recorded to being delivered to the application. Only for record streams. \since 0.5*/ @@ -187,7 +187,7 @@ struct pa_latency_info { * 0.5 */ struct timeval timestamp; /**< The time when this latency info was current */ uint64_t counter; /**< The byte counter current when the latency info was requested. \since 0.6 */ -}; +} pa_latency_info; /** A structure for the spawn api. This may be used to integrate auto * spawned daemons into your application. For more information see @@ -196,7 +196,7 @@ struct pa_latency_info { * block or ignore SIGCHLD signals, since this cannot be done in a * thread compatible way. You might have to do this in * prefork/postfork. \since 0.4 */ -struct pa_spawn_api { +typedef struct pa_spawn_api { void (*prefork)(void); /**< Is called just before the fork in the parent process. May be NULL. */ void (*postfork)(void); /**< Is called immediately after the fork in the parent process. May be NULL.*/ void (*atfork)(void); /**< Is called immediately after the @@ -206,7 +206,7 @@ struct pa_spawn_api { * unconditionally, since a UNIX socket * (created using socketpair()) is * passed to the new process. */ -}; +} pa_spawn_api; PA_C_DECL_END diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 8677c813f..09f9473ac 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -43,109 +43,111 @@ struct pa_context { int ref; char *name; - struct pa_mainloop_api* mainloop; + pa_mainloop_api* mainloop; - struct pa_socket_client *client; - struct pa_pstream *pstream; - struct pa_pdispatch *pdispatch; + pa_socket_client *client; + pa_pstream *pstream; + pa_pdispatch *pdispatch; - struct pa_dynarray *record_streams, *playback_streams; - PA_LLIST_HEAD(struct pa_stream, streams); - PA_LLIST_HEAD(struct pa_operation, operations); + pa_dynarray *record_streams, *playback_streams; + PA_LLIST_HEAD(pa_stream, streams); + PA_LLIST_HEAD(pa_operation, operations); uint32_t ctag; uint32_t error; - enum pa_context_state state; + pa_context_state state; - void (*state_callback)(struct pa_context*c, void *userdata); + void (*state_callback)(pa_context*c, void *userdata); void *state_userdata; - void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void (*subscribe_callback)(pa_context *c, pa_subscription_event_type t, uint32_t idx, void *userdata); void *subscribe_userdata; - struct pa_memblock_stat *memblock_stat; + pa_memblock_stat *memblock_stat; int local; int do_autospawn; int autospawn_lock_fd; - struct pa_spawn_api spawn_api; + pa_spawn_api spawn_api; - struct pa_strlist *server_list; + pa_strlist *server_list; char *server; - struct pa_client_conf *conf; + pa_client_conf *conf; }; struct pa_stream { int ref; - struct pa_context *context; - struct pa_mainloop_api *mainloop; - PA_LLIST_FIELDS(struct pa_stream); + pa_context *context; + pa_mainloop_api *mainloop; + PA_LLIST_FIELDS(pa_stream); char *name; - struct pa_buffer_attr buffer_attr; - struct pa_sample_spec sample_spec; + pa_buffer_attr buffer_attr; + pa_sample_spec sample_spec; uint32_t channel; int channel_valid; uint32_t device_index; - enum pa_stream_direction direction; + pa_stream_direction direction; uint32_t requested_bytes; uint64_t counter; pa_usec_t previous_time; pa_usec_t previous_ipol_time; - enum pa_stream_state state; - struct pa_mcalign *mcalign; + pa_stream_state state; + pa_mcalign *mcalign; int interpolate; int corked; uint32_t ipol_usec; struct timeval ipol_timestamp; - struct pa_time_event *ipol_event; + pa_time_event *ipol_event; int ipol_requested; - void (*state_callback)(struct pa_stream*c, void *userdata); + void (*state_callback)(pa_stream*c, void *userdata); void *state_userdata; - void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata); + void (*read_callback)(pa_stream *p, const void*data, size_t length, void *userdata); void *read_userdata; - void (*write_callback)(struct pa_stream *p, size_t length, void *userdata); + void (*write_callback)(pa_stream *p, size_t length, void *userdata); void *write_userdata; }; +typedef void (*pa_operation_callback)(void); + struct pa_operation { int ref; - struct pa_context *context; - struct pa_stream *stream; - PA_LLIST_FIELDS(struct pa_operation); + pa_context *context; + pa_stream *stream; + PA_LLIST_FIELDS(pa_operation); - enum pa_operation_state state; + pa_operation_state state; void *userdata; - void (*callback)(); + pa_operation_callback callback; }; -void pa_command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -void pa_command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -void pa_command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -struct pa_operation *pa_operation_new(struct pa_context *c, struct pa_stream *s); -void pa_operation_done(struct pa_operation *o); +pa_operation *pa_operation_new(pa_context *c, pa_stream *s); +void pa_operation_done(pa_operation *o); -void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -void pa_stream_disconnect_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -void pa_context_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -void pa_stream_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -void pa_context_fail(struct pa_context *c, int error); -void pa_context_set_state(struct pa_context *c, enum pa_context_state st); -int pa_context_handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t); -struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32_t command, void (*internal_callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void (*cb)(), void *userdata); +void pa_context_fail(pa_context *c, int error); +void pa_context_set_state(pa_context *c, pa_context_state st); +int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t); +pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, void (*internal_callback)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata), void (*cb)(void), void *userdata); -void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st); +void pa_stream_set_state(pa_stream *s, pa_stream_state st); -void pa_stream_trash_ipol(struct pa_stream *s); +void pa_stream_trash_ipol(pa_stream *s); #endif diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 5d6d64abd..911059690 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -29,12 +29,13 @@ #include "polyplib-context.h" #include "polyplib-internal.h" #include "pstream-util.h" +#include "gccmacro.h" /*** Statistics ***/ -static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; - struct pa_stat_info i, *p = &i; +static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + pa_stat_info i, *p = &i; assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { @@ -53,7 +54,7 @@ static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uin } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_stat_info*i, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_stat_info*_i, void *_userdata) = (void (*)(pa_context *s, const pa_stat_info*_i, void *_userdata)) o->callback; cb(o->context, p, o->userdata); } @@ -62,15 +63,15 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info*i, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, cb, userdata); +pa_operation* pa_context_stat(pa_context *c, void (*cb)(pa_context *c, const pa_stat_info*i, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, (pa_operation_callback) cb, userdata); } /*** Server Info ***/ -static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; - struct pa_server_info i, *p = &i; +static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + pa_server_info i, *p = &i; assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { @@ -93,7 +94,7 @@ static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t c } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_server_info*i, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_server_info*_i, void *_userdata) = (void (*)(pa_context *s, const pa_server_info*_i, void *_userdata)) o->callback; cb(o->context, p, o->userdata); } @@ -102,14 +103,14 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, cb, userdata); +pa_operation* pa_context_get_server_info(pa_context *c, void (*cb)(pa_context *c, const pa_server_info*i, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, (pa_operation_callback) cb, userdata); } /*** Sink Info ***/ -static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; +static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; int eof = 1; assert(pd && o && o->context && o->ref >= 1); @@ -121,7 +122,7 @@ static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t com } else { while (!pa_tagstruct_eof(t)) { - struct pa_sink_info i; + pa_sink_info i; if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -139,14 +140,14 @@ static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t com } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_sink_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sink_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_sink_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sink_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, NULL, eof, o->userdata); } @@ -155,24 +156,24 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, cb, userdata); +pa_operation* pa_context_get_sink_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, (pa_operation_callback) cb, userdata); } -struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o); @@ -180,14 +181,14 @@ struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uin return pa_operation_ref(o); } -struct pa_operation* pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -203,8 +204,8 @@ struct pa_operation* pa_context_get_sink_info_by_name(struct pa_context *c, cons /*** Source info ***/ -static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; +static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; int eof = 1; assert(pd && o && o->context && o->ref >= 1); @@ -216,7 +217,7 @@ static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t c } else { while (!pa_tagstruct_eof(t)) { - struct pa_source_info i; + pa_source_info i; if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -233,14 +234,14 @@ static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t c } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_source_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_source_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_source_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_source_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, NULL, eof, o->userdata); } @@ -249,24 +250,24 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, cb, userdata); +pa_operation* pa_context_get_source_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, (pa_operation_callback) cb, userdata); } -struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o); @@ -274,14 +275,14 @@ struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, u return pa_operation_ref(o); } -struct pa_operation* pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -297,8 +298,8 @@ struct pa_operation* pa_context_get_source_info_by_name(struct pa_context *c, co /*** Client info ***/ -static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; +static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; int eof = 1; assert(pd && o && o->context && o->ref >= 1); @@ -310,7 +311,7 @@ static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t c } else { while (!pa_tagstruct_eof(t)) { - struct pa_client_info i; + pa_client_info i; if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -321,14 +322,14 @@ static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t c } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_client_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_client_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_client_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_client_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, NULL, eof, o->userdata); } @@ -337,34 +338,34 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_client_info*i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, o); return pa_operation_ref(o); } -struct pa_operation* pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, cb, userdata); +pa_operation* pa_context_get_client_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_client_info*i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, (pa_operation_callback) cb, userdata); } /*** Module info ***/ -static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; +static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; int eof = 1; assert(pd && o && o->context && o->ref >= 1); @@ -376,7 +377,7 @@ static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t c } else { while (!pa_tagstruct_eof(t)) { - struct pa_module_info i; + pa_module_info i; if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -388,14 +389,14 @@ static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t c } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_module_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_module_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_module_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_module_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, NULL, eof, o->userdata); } @@ -404,34 +405,34 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_module_info*i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, o); return pa_operation_ref(o); } -struct pa_operation* pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, cb, userdata); +pa_operation* pa_context_get_module_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_module_info*i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, (pa_operation_callback) cb, userdata); } /*** Sink input info ***/ -static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; +static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; int eof = 1; assert(pd && o && o->context && o->ref >= 1); @@ -443,7 +444,7 @@ static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32 } else { while (!pa_tagstruct_eof(t)) { - struct pa_sink_input_info i; + pa_sink_input_info i; if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -462,14 +463,14 @@ static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32 } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_sink_input_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_sink_input_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sink_input_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_sink_input_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_sink_input_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sink_input_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, NULL, eof, o->userdata); } @@ -478,34 +479,34 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INPUT_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, o); return pa_operation_ref(o); } -struct pa_operation* pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, cb, userdata); +pa_operation* pa_context_get_sink_input_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, (pa_operation_callback) cb, userdata); } /*** Source output info ***/ -static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; +static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; int eof = 1; assert(pd && o && o->context && o->ref >= 1); @@ -517,7 +518,7 @@ static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uin } else { while (!pa_tagstruct_eof(t)) { - struct pa_source_output_info i; + pa_source_output_info i; if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -535,14 +536,14 @@ static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uin } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_source_output_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_source_output_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_source_output_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_source_output_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_source_output_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_source_output_info*_i, int _eof, void *_userdata))o->callback; cb(o->context, NULL, eof, o->userdata); } @@ -551,46 +552,46 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_source_output_info*i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_OUTPUT_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, o); return pa_operation_ref(o); } -struct pa_operation* pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, cb, userdata); +pa_operation* pa_context_get_source_output_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_output_info*i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, (pa_operation_callback) cb, userdata); } /*** Volume manipulation ***/ -struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; - assert(c && index != PA_INVALID_INDEX); + assert(c && idx != PA_INVALID_INDEX); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_tagstruct_putu32(t, volume); pa_pstream_send_tagstruct(c->pstream, t); @@ -599,14 +600,14 @@ struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, u return pa_operation_ref(o); } -struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; assert(c && name); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -621,20 +622,20 @@ struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, co return pa_operation_ref(o); } -struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; - assert(c && index != PA_INVALID_INDEX); + assert(c && idx != PA_INVALID_INDEX); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_tagstruct_putu32(t, volume); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); @@ -644,8 +645,8 @@ struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint /** Sample Cache **/ -static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; +static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; int eof = 1; assert(pd && o && o->context && o->ref >= 1); @@ -657,7 +658,7 @@ static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t c } else { while (!pa_tagstruct_eof(t)) { - struct pa_sample_info i; + pa_sample_info i; if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -673,14 +674,14 @@ static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t c } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_sample_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_sample_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sample_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_sample_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_sample_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sample_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, NULL, eof, o->userdata); } @@ -689,14 +690,14 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_get_sample_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb && name); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -710,20 +711,20 @@ struct pa_operation* pa_context_get_sample_info_by_name(struct pa_context *c, co return pa_operation_ref(o); } -struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, o); @@ -731,60 +732,60 @@ struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, u return pa_operation_ref(o); } -struct pa_operation* pa_context_get_sample_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, cb, userdata); +pa_operation* pa_context_get_sample_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, (pa_operation_callback) cb, userdata); } -static struct pa_operation* command_kill(struct pa_context *c, uint32_t command, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; - assert(c && index != PA_INVALID_INDEX); + assert(c && idx != PA_INVALID_INDEX); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, command); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); return pa_operation_ref(o); } -struct pa_operation* pa_context_kill_client(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - return command_kill(c, PA_COMMAND_KILL_CLIENT, index, cb, userdata); +pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + return command_kill(c, PA_COMMAND_KILL_CLIENT, idx, cb, userdata); } -struct pa_operation* pa_context_kill_sink_input(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - return command_kill(c, PA_COMMAND_KILL_SINK_INPUT, index, cb, userdata); +pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + return command_kill(c, PA_COMMAND_KILL_SINK_INPUT, idx, cb, userdata); } -struct pa_operation* pa_context_kill_source_output(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - return command_kill(c, PA_COMMAND_KILL_SOURCE_OUTPUT, index, cb, userdata); +pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + return command_kill(c, PA_COMMAND_KILL_SOURCE_OUTPUT, idx, cb, userdata); } -static void load_module_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; - uint32_t index = -1; +static void load_module_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + uint32_t idx = -1; assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - } else if (pa_tagstruct_getu32(t, &index) < 0 || + } else if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } if (o->callback) { - void (*cb)(struct pa_context *c, uint32_t index, void *userdata) = o->callback; - cb(o->context, index, o->userdata); + void (*cb)(pa_context *c, uint32_t _idx, void *_userdata) = (void (*)(pa_context *c, uint32_t _idx, void *_userdata)) o->callback; + cb(o->context, idx, o->userdata); } finish: @@ -792,14 +793,14 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_load_module(struct pa_context *c, const char*name, const char *argument, void (*cb)(struct pa_context *c, uint32_t index, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, void (*cb)(pa_context *c, uint32_t idx, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; assert(c && name && argument); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -813,14 +814,14 @@ struct pa_operation* pa_context_load_module(struct pa_context *c, const char*nam return pa_operation_ref(o); } -struct pa_operation* pa_context_unload_module(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - return command_kill(c, PA_COMMAND_UNLOAD_MODULE, index, cb, userdata); +pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + return command_kill(c, PA_COMMAND_UNLOAD_MODULE, idx, cb, userdata); } /*** Autoload stuff ***/ -static void context_get_autoload_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; +static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; int eof = 1; assert(pd && o && o->context && o->ref >= 1); @@ -832,7 +833,7 @@ static void context_get_autoload_info_callback(struct pa_pdispatch *pd, uint32_t } else { while (!pa_tagstruct_eof(t)) { - struct pa_autoload_info i; + pa_autoload_info i; if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -844,14 +845,14 @@ static void context_get_autoload_info_callback(struct pa_pdispatch *pd, uint32_t } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_autoload_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_autoload_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_autoload_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(struct pa_context *s, const struct pa_autoload_info*i, int eof, void *userdata) = o->callback; + void (*cb)(pa_context *s, const pa_autoload_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_autoload_info*_i, int _eof, void *_userdata)) o->callback; cb(o->context, NULL, eof, o->userdata); } @@ -860,14 +861,14 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_context_get_autoload_info_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(c && cb && name); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -881,49 +882,49 @@ struct pa_operation* pa_context_get_autoload_info_by_name(struct pa_context *c, return pa_operation_ref(o); } -struct pa_operation* pa_context_get_autoload_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; - assert(c && cb && index != PA_INVALID_INDEX); + assert(c && cb && idx != PA_INVALID_INDEX); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_AUTOLOAD_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, o); return pa_operation_ref(o); } -struct pa_operation* pa_context_get_autoload_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, cb, userdata); +pa_operation* pa_context_get_autoload_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, (pa_operation_callback) cb, userdata); } -static void context_add_autoload_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; - uint32_t index; +static void context_add_autoload_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + uint32_t idx; assert(pd && o && o->context && o->ref >= 1); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - index = PA_INVALID_INDEX; - } else if (pa_tagstruct_getu32(t, &index) || + idx = PA_INVALID_INDEX; + } else if (pa_tagstruct_getu32(t, &idx) || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } if (o->callback) { - void (*cb)(struct pa_context *s, uint32_t index, void *userdata) = o->callback; - cb(o->context, index, o->userdata); + void (*cb)(pa_context *s, uint32_t _idx, void *_userdata) = (void (*)(pa_context *s, uint32_t _idx, void *_userdata)) o->callback; + cb(o->context, idx, o->userdata); } @@ -933,14 +934,14 @@ finish: } -struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type type, const char *module, const char*argument, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; assert(c && name && module && argument); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -956,14 +957,14 @@ struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *n return pa_operation_ref(o); } -struct pa_operation* pa_context_remove_autoload_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; assert(c && name); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -977,20 +978,20 @@ struct pa_operation* pa_context_remove_autoload_by_name(struct pa_context *c, co return pa_operation_ref(o); } -struct pa_operation* pa_context_remove_autoload_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; - assert(c && index != PA_INVALID_INDEX); + assert(c && idx != PA_INVALID_INDEX); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_AUTOLOAD); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 83cdba162..2848e22f9 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -48,224 +48,224 @@ PA_C_DECL_BEGIN /** Stores information about sinks */ -struct pa_sink_info { +typedef struct pa_sink_info { const char *name; /**< Name of the sink */ uint32_t index; /**< Index of the sink */ const char *description; /**< Description of this sink */ - struct pa_sample_spec sample_spec; /**< Sample spec of this sink */ + pa_sample_spec sample_spec; /**< Sample spec of this sink */ uint32_t owner_module; /**< Index of the owning module of this sink, or PA_INVALID_INDEX */ pa_volume_t volume; /**< Volume of the sink */ uint32_t monitor_source; /**< Index of the monitor source connected to this sink */ const char *monitor_source_name; /**< The name of the monitor source */ pa_usec_t latency; /**< Length of filled playback buffer of this sink */ pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ -}; +} pa_sink_info; /** Get information about a sink by its name */ -struct pa_operation* pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata); /** Get information about a sink by its index */ -struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t id, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata); /** Get the complete sink list */ -struct pa_operation* pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sink_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata); /** Stores information about sources */ -struct pa_source_info { +typedef struct pa_source_info { const char *name ; /**< Name of the source */ uint32_t index; /**< Index of the source */ const char *description; /**< Description of this source */ - struct pa_sample_spec sample_spec; /**< Sample spec of this source */ + pa_sample_spec sample_spec; /**< Sample spec of this source */ uint32_t owner_module; /**< Owning module index, or PA_INVALID_INDEX */ uint32_t monitor_of_sink; /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */ const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */ pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */ pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ -}; +} pa_source_info; /** Get information about a source by its name */ -struct pa_operation* pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata); /** Get information about a source by its index */ -struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t id, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata); /** Get the complete source list */ -struct pa_operation* pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_source_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata); /** Server information */ -struct pa_server_info { +typedef struct pa_server_info { const char *user_name; /**< User name of the daemon process */ const char *host_name; /**< Host name the daemon is running on */ const char *server_version; /**< Version string of the daemon */ const char *server_name; /**< Server package name (usually "polypaudio") */ - struct pa_sample_spec sample_spec; /**< Default sample specification */ + pa_sample_spec sample_spec; /**< Default sample specification */ const char *default_sink_name; /**< Name of default sink. \since 0.4 */ const char *default_source_name; /**< Name of default sink. \since 0.4*/ uint32_t cookie; /**< A random cookie for identifying this instance of polypaudio. \since 0.8 */ -}; +} pa_server_info; /** Get some information about the server */ -struct pa_operation* pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); +pa_operation* pa_context_get_server_info(pa_context *c, void (*cb)(pa_context *c, const pa_server_info*i, void *userdata), void *userdata); /** Stores information about modules */ -struct pa_module_info { +typedef struct pa_module_info { uint32_t index; /**< Index of the module */ const char*name, /**< Name of the module */ *argument; /**< Argument string of the module */ uint32_t n_used; /**< Usage counter or PA_INVALID_INDEX */ int auto_unload; /**< Non-zero if this is an autoloaded module */ -}; +} pa_module_info; /** Get some information about a module by its index */ -struct pa_operation* pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_module_info*i, int is_last, void *userdata), void *userdata); /** Get the complete list of currently loaded modules */ -struct pa_operation* pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_module_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_module_info*i, int is_last, void *userdata), void *userdata); /** Stores information about clients */ -struct pa_client_info { +typedef struct pa_client_info { uint32_t index; /**< Index of this client */ const char *name; /**< Name of this client */ uint32_t owner_module; /**< Index of the owning module, or PA_INVALID_INDEX */ pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ -}; +} pa_client_info; /** Get information about a client by its index */ -struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_client_info*i, int is_last, void *userdata), void *userdata); /** Get the complete client list */ -struct pa_operation* pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_client_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_client_info*i, int is_last, void *userdata), void *userdata); /** Stores information about sink inputs */ -struct pa_sink_input_info { +typedef struct pa_sink_input_info { uint32_t index; /**< Index of the sink input */ const char *name; /**< Name of the sink input */ uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */ uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */ uint32_t sink; /**< Index of the connected sink */ - struct pa_sample_spec sample_spec; /**< The sample specification of the sink input */ + pa_sample_spec sample_spec; /**< The sample specification of the sink input */ pa_volume_t volume; /**< The volume of this sink input */ pa_usec_t buffer_usec; /**< Latency due to buffering in sink input, see pa_latency_info for details */ pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */ const char *resample_method; /**< Thre resampling method used by this sink input. \since 0.7 */ pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ -}; +} pa_sink_input_info; /** Get some information about a sink input by its index */ -struct pa_operation* pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata); /** Get the complete sink input list */ -struct pa_operation* pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sink_input_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata); /** Stores information about source outputs */ -struct pa_source_output_info { +typedef struct pa_source_output_info { uint32_t index; /**< Index of the sink input */ const char *name; /**< Name of the sink input */ uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */ uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */ uint32_t source; /**< Index of the connected source */ - struct pa_sample_spec sample_spec; /**< The sample specification of the source output */ + pa_sample_spec sample_spec; /**< The sample specification of the source output */ pa_usec_t buffer_usec; /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */ pa_usec_t source_usec; /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */ const char *resample_method; /**< Thre resampling method used by this source output. \since 0.7 */ pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ -}; +} pa_source_output_info; /** Get information about a source output by its index */ -struct pa_operation* pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_source_output_info*i, int is_last, void *userdata), void *userdata); /** Get the complete list of source outputs */ -struct pa_operation* pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_source_output_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_output_info*i, int is_last, void *userdata), void *userdata); /** Set the volume of a sink device specified by its index */ -struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Set the volume of a sink device specified by its name */ -struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Set the volume of a sink input stream */ -struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Memory block statistics */ -struct pa_stat_info { +typedef struct pa_stat_info { uint32_t memblock_total; /**< Currently allocated memory blocks */ uint32_t memblock_total_size; /**< Currentl total size of allocated memory blocks */ uint32_t memblock_allocated; /**< Allocated memory blocks during the whole lifetime of the daemon */ uint32_t memblock_allocated_size; /**< Total size of all memory blocks allocated during the whole lifetime of the daemon */ uint32_t scache_size; /**< Total size of all sample cache entries. \since 0.4 */ -}; +} pa_stat_info; /** Get daemon memory block statistics */ -struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info *i, void *userdata), void *userdata); +pa_operation* pa_context_stat(pa_context *c, void (*cb)(pa_context *c, const pa_stat_info *i, void *userdata), void *userdata); /** Stores information about sample cache entries */ -struct pa_sample_info { +typedef struct pa_sample_info { uint32_t index; /**< Index of this entry */ const char *name; /**< Name of this entry */ pa_volume_t volume; /**< Default volume of this entry */ - struct pa_sample_spec sample_spec; /**< Sample specification of the sampel */ + pa_sample_spec sample_spec; /**< Sample specification of the sampel */ pa_usec_t duration; /**< Duration of this entry */ uint32_t bytes; /**< Length of this sample in bytes. \since 0.4 */ int lazy; /**< Non-zero when this is a lazy cache entry. \since 0.5 */ const char *filename; /**< In case this is a lazy cache entry, the filename for the sound file to be loaded on demand. \since 0.5 */ -}; +} pa_sample_info; /** Get information about a sample by its name */ -struct pa_operation* pa_context_get_sample_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata); /** Get information about a sample by its index */ -struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata); /** Get the complete list of samples stored in the daemon. */ -struct pa_operation* pa_context_get_sample_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sample_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata); /** Kill a client. \since 0.5 */ -struct pa_operation* pa_context_kill_client(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Kill a sink input. \since 0.5 */ -struct pa_operation* pa_context_kill_sink_input(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Kill a source output. \since 0.5 */ -struct pa_operation* pa_context_kill_source_output(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Load a module. \since 0.5 */ -struct pa_operation* pa_context_load_module(struct pa_context *c, const char*name, const char *argument, void (*cb)(struct pa_context *c, uint32_t index, void *userdata), void *userdata); +pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, void (*cb)(pa_context *c, uint32_t idx, void *userdata), void *userdata); /** Unload a module. \since 0.5 */ -struct pa_operation* pa_context_unload_module(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Type of an autoload entry. \since 0.5 */ -enum pa_autoload_type { +typedef enum pa_autoload_type { PA_AUTOLOAD_SINK = 0, PA_AUTOLOAD_SOURCE = 1 -}; +} pa_autoload_type; /** Stores information about autoload entries. \since 0.5 */ -struct pa_autoload_info { +typedef struct pa_autoload_info { uint32_t index; /**< Index of this autoload entry */ const char *name; /**< Name of the sink or source */ - enum pa_autoload_type type; /**< Type of the autoload entry */ + pa_autoload_type type; /**< Type of the autoload entry */ const char *module; /**< Module name to load */ const char *argument; /**< Argument string for module */ -}; +} pa_autoload_info; /** Get info about a specific autoload entry. \since 0.6 */ -struct pa_operation* pa_context_get_autoload_info_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata); /** Get info about a specific autoload entry. \since 0.6 */ -struct pa_operation* pa_context_get_autoload_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata); /** Get the complete list of autoload entries. \since 0.5 */ -struct pa_operation* pa_context_get_autoload_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_autoload_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata); /** Add a new autoload entry. \since 0.5 */ -struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int index, void *userdata), void* userdata); +pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type type, const char *module, const char*argument, void (*cb)(pa_context *c, int idx, void *userdata), void* userdata); /** Remove an autoload entry. \since 0.6 */ -struct pa_operation* pa_context_remove_autoload_by_name(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata); +pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata); /** Remove an autoload entry. \since 0.6 */ -struct pa_operation* pa_context_remove_autoload_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata); +pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void* userdata); PA_C_DECL_END diff --git a/polyp/polyplib-operation.c b/polyp/polyplib-operation.c index 77fe70fa6..3bee8cc72 100644 --- a/polyp/polyplib-operation.c +++ b/polyp/polyplib-operation.c @@ -29,11 +29,11 @@ #include "polyplib-internal.h" #include "polyplib-operation.h" -struct pa_operation *pa_operation_new(struct pa_context *c, struct pa_stream *s) { - struct pa_operation *o; +pa_operation *pa_operation_new(pa_context *c, pa_stream *s) { + pa_operation *o; assert(c); - o = pa_xmalloc(sizeof(struct pa_operation)); + o = pa_xmalloc(sizeof(pa_operation)); o->ref = 1; o->context = pa_context_ref(c); o->stream = s ? pa_stream_ref(s) : NULL; @@ -42,17 +42,17 @@ struct pa_operation *pa_operation_new(struct pa_context *c, struct pa_stream *s) o->userdata = NULL; o->callback = NULL; - PA_LLIST_PREPEND(struct pa_operation, o->context->operations, o); + PA_LLIST_PREPEND(pa_operation, o->context->operations, o); return pa_operation_ref(o); } -struct pa_operation *pa_operation_ref(struct pa_operation *o) { +pa_operation *pa_operation_ref(pa_operation *o) { assert(o && o->ref >= 1); o->ref++; return o; } -void pa_operation_unref(struct pa_operation *o) { +void pa_operation_unref(pa_operation *o) { assert(o && o->ref >= 1); if ((--(o->ref)) == 0) { @@ -62,7 +62,7 @@ void pa_operation_unref(struct pa_operation *o) { } } -static void operation_set_state(struct pa_operation *o, enum pa_operation_state st) { +static void operation_set_state(pa_operation *o, pa_operation_state st) { assert(o && o->ref >= 1); if (st == o->state) @@ -74,7 +74,7 @@ static void operation_set_state(struct pa_operation *o, enum pa_operation_state o->state = st; if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) { - PA_LLIST_REMOVE(struct pa_operation, o->context->operations, o); + PA_LLIST_REMOVE(pa_operation, o->context->operations, o); pa_context_unref(o->context); if (o->stream) pa_stream_unref(o->stream); @@ -87,17 +87,17 @@ static void operation_set_state(struct pa_operation *o, enum pa_operation_state } } -void pa_operation_cancel(struct pa_operation *o) { +void pa_operation_cancel(pa_operation *o) { assert(o && o->ref >= 1); operation_set_state(o, PA_OPERATION_CANCELED); } -void pa_operation_done(struct pa_operation *o) { +void pa_operation_done(pa_operation *o) { assert(o && o->ref >= 1); operation_set_state(o, PA_OPERATION_DONE); } -enum pa_operation_state pa_operation_get_state(struct pa_operation *o) { +pa_operation_state pa_operation_get_state(pa_operation *o) { assert(o && o->ref >= 1); return o->state; } diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h index 5c3af49ca..63dcbc9fb 100644 --- a/polyp/polyplib-operation.h +++ b/polyp/polyplib-operation.h @@ -30,21 +30,21 @@ PA_C_DECL_BEGIN -/** \struct pa_operation +/** \pa_operation * An asynchronous operation object */ -struct pa_operation; +typedef struct pa_operation pa_operation; /** Increase the reference count by one */ -struct pa_operation *pa_operation_ref(struct pa_operation *o); +pa_operation *pa_operation_ref(pa_operation *o); /** Decrease the reference count by one */ -void pa_operation_unref(struct pa_operation *o); +void pa_operation_unref(pa_operation *o); /** Cancel the operation. Beware! This will not necessarily cancel the execution of the operation on the server side. */ -void pa_operation_cancel(struct pa_operation *o); +void pa_operation_cancel(pa_operation *o); /** Return the current status of the operation */ -enum pa_operation_state pa_operation_get_state(struct pa_operation *o); +pa_operation_state pa_operation_get_state(pa_operation *o); PA_C_DECL_END diff --git a/polyp/polyplib-scache.c b/polyp/polyplib-scache.c index bce5d18a7..01c648282 100644 --- a/polyp/polyplib-scache.c +++ b/polyp/polyplib-scache.c @@ -32,8 +32,8 @@ #include "polyplib-internal.h" #include "pstream-util.h" -void pa_stream_connect_upload(struct pa_stream *s, size_t length) { - struct pa_tagstruct *t; +void pa_stream_connect_upload(pa_stream *s, size_t length) { + pa_tagstruct *t; uint32_t tag; assert(s && length); @@ -55,8 +55,8 @@ void pa_stream_connect_upload(struct pa_stream *s, size_t length) { pa_stream_unref(s); } -void pa_stream_finish_upload(struct pa_stream *s) { - struct pa_tagstruct *t; +void pa_stream_finish_upload(pa_stream *s) { + pa_tagstruct *t; uint32_t tag; assert(s); @@ -77,14 +77,14 @@ void pa_stream_finish_upload(struct pa_stream *s) { pa_stream_unref(s); } -struct pa_operation * pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation * pa_context_play_sample(pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; assert(c && name && *name && (!dev || *dev)); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; if (!dev) @@ -104,14 +104,14 @@ struct pa_operation * pa_context_play_sample(struct pa_context *c, const char *n return pa_operation_ref(o); } -struct pa_operation* pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_context_remove_sample(pa_context *c, const char *name, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; assert(c && name); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); diff --git a/polyp/polyplib-scache.h b/polyp/polyplib-scache.h index 8ec375ea1..89d27597f 100644 --- a/polyp/polyplib-scache.h +++ b/polyp/polyplib-scache.h @@ -34,16 +34,16 @@ PA_C_DECL_BEGIN /** Make this stream a sample upload stream */ -void pa_stream_connect_upload(struct pa_stream *s, size_t length); +void pa_stream_connect_upload(pa_stream *s, size_t length); /** Finish the sample upload, the stream name will become the sample name. You cancel a sample upload by issuing pa_stream_disconnect() */ -void pa_stream_finish_upload(struct pa_stream *s); +void pa_stream_finish_upload(pa_stream *s); /** Play a sample from the sample cache to the specified device. If the latter is NULL use the default sink. Returns an operation object */ -struct pa_operation* pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_play_sample(pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Remove a sample from the sample cache. Returns an operation object which may be used to cancel the operation while it is running */ -struct pa_operation* pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_remove_sample(pa_context *c, const char *name, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); PA_C_DECL_END diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index a73aacfae..b13571289 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -36,10 +36,10 @@ #include "log.h" struct pa_simple { - struct pa_mainloop *mainloop; - struct pa_context *context; - struct pa_stream *stream; - enum pa_stream_direction direction; + pa_mainloop *mainloop; + pa_context *context; + pa_stream *stream; + pa_stream_direction direction; int dead; @@ -48,11 +48,11 @@ struct pa_simple { pa_usec_t latency; }; -static void read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata); +static void read_callback(pa_stream *s, const void*data, size_t length, void *userdata); -static int check_error(struct pa_simple *p, int *perror) { - enum pa_context_state cst; - enum pa_stream_state sst; +static int check_error(pa_simple *p, int *rerror) { + pa_context_state cst; + pa_stream_state sst; assert(p); if ((cst = pa_context_get_state(p->context)) == PA_CONTEXT_FAILED) @@ -70,18 +70,18 @@ static int check_error(struct pa_simple *p, int *perror) { return 0; fail: - if (perror) - *perror = pa_context_errno(p->context); + if (rerror) + *rerror = pa_context_errno(p->context); p->dead = 1; return -1; } -static int iterate(struct pa_simple *p, int block, int *perror) { +static int iterate(pa_simple *p, int block, int *rerror) { assert(p && p->context && p->mainloop); - if (check_error(p, perror) < 0) + if (check_error(p, rerror) < 0) return -1; if (!block && !pa_context_is_pending(p->context)) @@ -89,12 +89,12 @@ static int iterate(struct pa_simple *p, int block, int *perror) { do { if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) { - if (perror) - *perror = PA_ERROR_INTERNAL; + if (rerror) + *rerror = PA_ERROR_INTERNAL; return -1; } - if (check_error(p, perror) < 0) + if (check_error(p, rerror) < 0) return -1; } while (pa_context_is_pending(p->context)); @@ -103,34 +103,34 @@ static int iterate(struct pa_simple *p, int block, int *perror) { while (pa_mainloop_deferred_pending(p->mainloop)) { if (pa_mainloop_iterate(p->mainloop, 0, NULL) < 0) { - if (perror) - *perror = PA_ERROR_INTERNAL; + if (rerror) + *rerror = PA_ERROR_INTERNAL; return -1; } - if (check_error(p, perror) < 0) + if (check_error(p, rerror) < 0) return -1; } return 0; } -struct pa_simple* pa_simple_new( +pa_simple* pa_simple_new( const char *server, const char *name, - enum pa_stream_direction dir, + pa_stream_direction dir, const char *dev, const char *stream_name, - const struct pa_sample_spec *ss, - const struct pa_buffer_attr *attr, + const pa_sample_spec *ss, + const pa_buffer_attr *attr, pa_volume_t volume, - int *perror) { + int *rerror) { - struct pa_simple *p; + pa_simple *p; int error = PA_ERROR_INTERNAL; assert(ss && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); - p = pa_xmalloc(sizeof(struct pa_simple)); + p = pa_xmalloc(sizeof(pa_simple)); p->context = NULL; p->stream = NULL; p->mainloop = pa_mainloop_new(); @@ -171,13 +171,13 @@ struct pa_simple* pa_simple_new( return p; fail: - if (perror) - *perror = error; + if (rerror) + *rerror = error; pa_simple_free(p); return NULL; } -void pa_simple_free(struct pa_simple *s) { +void pa_simple_free(pa_simple *s) { assert(s); pa_xfree(s->read_data); @@ -194,12 +194,12 @@ void pa_simple_free(struct pa_simple *s) { pa_xfree(s); } -int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *perror) { +int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) { assert(p && data && p->direction == PA_STREAM_PLAYBACK); if (p->dead) { - if (perror) - *perror = pa_context_errno(p->context); + if (rerror) + *rerror = pa_context_errno(p->context); return -1; } @@ -208,26 +208,26 @@ int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *pe size_t l; while (!(l = pa_stream_writable_size(p->stream))) - if (iterate(p, 1, perror) < 0) + if (iterate(p, 1, rerror) < 0) return -1; if (l > length) l = length; pa_stream_write(p->stream, data, l, NULL, 0); - data = (uint8_t*) data + l; + data = (const uint8_t*) data + l; length -= l; } /* Make sure that no data is pending for write */ - if (iterate(p, 0, perror) < 0) + if (iterate(p, 0, rerror) < 0) return -1; return 0; } -static void read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata) { - struct pa_simple *p = userdata; +static void read_callback(pa_stream *s, const void*data, size_t length, void *userdata) { + pa_simple *p = userdata; assert(s && data && length && p); if (p->read_data) { @@ -239,12 +239,12 @@ static void read_callback(struct pa_stream *s, const void*data, size_t length, v p->read_index = 0; } -int pa_simple_read(struct pa_simple *p, void*data, size_t length, int *perror) { +int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { assert(p && data && p->direction == PA_STREAM_RECORD); if (p->dead) { - if (perror) - *perror = pa_context_errno(p->context); + if (rerror) + *rerror = pa_context_errno(p->context); return -1; } @@ -276,27 +276,27 @@ int pa_simple_read(struct pa_simple *p, void*data, size_t length, int *perror) { assert(!p->read_data); } - if (iterate(p, 1, perror) < 0) + if (iterate(p, 1, rerror) < 0) return -1; } return 0; } -static void drain_or_flush_complete(struct pa_stream *s, int success, void *userdata) { - struct pa_simple *p = userdata; +static void drain_or_flush_complete(pa_stream *s, int success, void *userdata) { + pa_simple *p = userdata; assert(s && p); if (!success) p->dead = 1; } -int pa_simple_drain(struct pa_simple *p, int *perror) { - struct pa_operation *o; +int pa_simple_drain(pa_simple *p, int *rerror) { + pa_operation *o; assert(p && p->direction == PA_STREAM_PLAYBACK); if (p->dead) { - if (perror) - *perror = pa_context_errno(p->context); + if (rerror) + *rerror = pa_context_errno(p->context); return -1; } @@ -304,7 +304,7 @@ int pa_simple_drain(struct pa_simple *p, int *perror) { o = pa_stream_drain(p->stream, drain_or_flush_complete, p); while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { - if (iterate(p, 1, perror) < 0) { + if (iterate(p, 1, rerror) < 0) { pa_operation_cancel(o); pa_operation_unref(o); return -1; @@ -313,14 +313,14 @@ int pa_simple_drain(struct pa_simple *p, int *perror) { pa_operation_unref(o); - if (p->dead && perror) - *perror = pa_context_errno(p->context); + if (p->dead && rerror) + *rerror = pa_context_errno(p->context); return p->dead ? -1 : 0; } -static void latency_complete(struct pa_stream *s, const struct pa_latency_info *l, void *userdata) { - struct pa_simple *p = userdata; +static void latency_complete(pa_stream *s, const pa_latency_info *l, void *userdata) { + pa_simple *p = userdata; assert(s && p); if (!l) @@ -333,13 +333,13 @@ static void latency_complete(struct pa_stream *s, const struct pa_latency_info * } } -pa_usec_t pa_simple_get_playback_latency(struct pa_simple *p, int *perror) { - struct pa_operation *o; +pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) { + pa_operation *o; assert(p && p->direction == PA_STREAM_PLAYBACK); if (p->dead) { - if (perror) - *perror = pa_context_errno(p->context); + if (rerror) + *rerror = pa_context_errno(p->context); return (pa_usec_t) -1; } @@ -349,7 +349,7 @@ pa_usec_t pa_simple_get_playback_latency(struct pa_simple *p, int *perror) { while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { - if (iterate(p, 1, perror) < 0) { + if (iterate(p, 1, rerror) < 0) { pa_operation_cancel(o); pa_operation_unref(o); return -1; @@ -358,19 +358,19 @@ pa_usec_t pa_simple_get_playback_latency(struct pa_simple *p, int *perror) { pa_operation_unref(o); - if (p->dead && perror) - *perror = pa_context_errno(p->context); + if (p->dead && rerror) + *rerror = pa_context_errno(p->context); return p->dead ? (pa_usec_t) -1 : p->latency; } -int pa_simple_flush(struct pa_simple *p, int *perror) { - struct pa_operation *o; +int pa_simple_flush(pa_simple *p, int *rerror) { + pa_operation *o; assert(p && p->direction == PA_STREAM_PLAYBACK); if (p->dead) { - if (perror) - *perror = pa_context_errno(p->context); + if (rerror) + *rerror = pa_context_errno(p->context); return -1; } @@ -378,7 +378,7 @@ int pa_simple_flush(struct pa_simple *p, int *perror) { o = pa_stream_flush(p->stream, drain_or_flush_complete, p); while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { - if (iterate(p, 1, perror) < 0) { + if (iterate(p, 1, rerror) < 0) { pa_operation_cancel(o); pa_operation_unref(o); return -1; @@ -387,8 +387,8 @@ int pa_simple_flush(struct pa_simple *p, int *perror) { pa_operation_unref(o); - if (p->dead && perror) - *perror = pa_context_errno(p->context); + if (p->dead && rerror) + *rerror = pa_context_errno(p->context); return p->dead ? -1 : 0; } diff --git a/polyp/polyplib-simple.h b/polyp/polyplib-simple.h index 9abef3fa1..d15891159 100644 --- a/polyp/polyplib-simple.h +++ b/polyp/polyplib-simple.h @@ -41,40 +41,40 @@ PA_C_DECL_BEGIN -/** \struct pa_simple +/** \pa_simple * An opaque simple connection object */ -struct pa_simple; +typedef struct pa_simple pa_simple; /** Create a new connection to the server */ -struct pa_simple* pa_simple_new( +pa_simple* pa_simple_new( const char *server, /**< Server name, or NULL for default */ const char *name, /**< A descriptive name for this client (application name, ...) */ - enum pa_stream_direction dir, /**< Open this stream for recording or playback? */ + pa_stream_direction dir, /**< Open this stream for recording or playback? */ const char *dev, /**< Sink (resp. source) name, or NULL for default */ const char *stream_name, /**< A descriptive name for this client (application name, song title, ...) */ - const struct pa_sample_spec *ss, /**< The sample type to use */ - const struct pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */ + const pa_sample_spec *ss, /**< The sample type to use */ + const pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */ pa_volume_t volume, /**< Initial volume. Only for playback streams. \since 0.5 */ int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */ ); /** Close and free the connection to the server. The connection objects becomes invalid when this is called. */ -void pa_simple_free(struct pa_simple *s); +void pa_simple_free(pa_simple *s); /** Write some data to the server */ -int pa_simple_write(struct pa_simple *s, const void*data, size_t length, int *error); +int pa_simple_write(pa_simple *s, const void*data, size_t length, int *error); /** Wait until all data already written is played by the daemon */ -int pa_simple_drain(struct pa_simple *s, int *error); +int pa_simple_drain(pa_simple *s, int *error); /** Read some data from the server */ -int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *error); +int pa_simple_read(pa_simple *s, void*data, size_t length, int *error); /** Return the playback latency. \since 0.5 */ -pa_usec_t pa_simple_get_playback_latency(struct pa_simple *s, int *perror); +pa_usec_t pa_simple_get_playback_latency(pa_simple *s, int *error); /** Flush the playback buffer. \since 0.5 */ -int pa_simple_flush(struct pa_simple *s, int *perror); +int pa_simple_flush(pa_simple *s, int *error); PA_C_DECL_END diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index b6a091b34..6c8ed9c5d 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -36,11 +36,11 @@ #define LATENCY_IPOL_INTERVAL_USEC (10000L) -struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss) { - struct pa_stream *s; +pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss) { + pa_stream *s; assert(c && ss); - s = pa_xmalloc(sizeof(struct pa_stream)); + s = pa_xmalloc(sizeof(pa_stream)); s->ref = 1; s->context = c; s->mainloop = c->mainloop; @@ -76,12 +76,12 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st s->ipol_event = NULL; s->ipol_requested = 0; - PA_LLIST_PREPEND(struct pa_stream, c->streams, s); + PA_LLIST_PREPEND(pa_stream, c->streams, s); return pa_stream_ref(s); } -static void stream_free(struct pa_stream *s) { +static void stream_free(pa_stream *s) { assert(s); if (s->ipol_event) { @@ -95,35 +95,35 @@ static void stream_free(struct pa_stream *s) { pa_xfree(s); } -void pa_stream_unref(struct pa_stream *s) { +void pa_stream_unref(pa_stream *s) { assert(s && s->ref >= 1); if (--(s->ref) == 0) stream_free(s); } -struct pa_stream* pa_stream_ref(struct pa_stream *s) { +pa_stream* pa_stream_ref(pa_stream *s) { assert(s && s->ref >= 1); s->ref++; return s; } -enum pa_stream_state pa_stream_get_state(struct pa_stream *s) { +pa_stream_state pa_stream_get_state(pa_stream *s) { assert(s && s->ref >= 1); return s->state; } -struct pa_context* pa_stream_get_context(struct pa_stream *s) { +pa_context* pa_stream_get_context(pa_stream *s) { assert(s && s->ref >= 1); return s->context; } -uint32_t pa_stream_get_index(struct pa_stream *s) { +uint32_t pa_stream_get_index(pa_stream *s) { assert(s && s->ref >= 1); return s->device_index; } -void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st) { +void pa_stream_set_state(pa_stream *s, pa_stream_state st) { assert(s && s->ref >= 1); if (s->state == st) @@ -137,7 +137,7 @@ void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st) { if (s->channel_valid) pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - PA_LLIST_REMOVE(struct pa_stream, s->context->streams, s); + PA_LLIST_REMOVE(pa_stream, s->context->streams, s); pa_stream_unref(s); } @@ -147,9 +147,9 @@ void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st) { pa_stream_unref(s); } -void pa_command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - struct pa_stream *s; +void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_context *c = userdata; + pa_stream *s; uint32_t channel; assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); @@ -171,9 +171,9 @@ finish: pa_context_unref(c); } -void pa_command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s; - struct pa_context *c = userdata; +void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_stream *s; + pa_context *c = userdata; uint32_t bytes, channel; assert(pd && command == PA_COMMAND_REQUEST && t && c); @@ -205,9 +205,9 @@ finish: pa_context_unref(c); } -static void ipol_callback(struct pa_mainloop_api *m, struct pa_time_event *e, const struct timeval *tv, void *userdata) { +static void ipol_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { struct timeval tv2; - struct pa_stream *s = userdata; + pa_stream *s = userdata; pa_stream_ref(s); @@ -227,8 +227,8 @@ static void ipol_callback(struct pa_mainloop_api *m, struct pa_time_event *e, co } -void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; +void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_stream *s = userdata; assert(pd && s && s->state == PA_STREAM_CREATING); pa_stream_ref(s); @@ -271,8 +271,8 @@ finish: pa_stream_unref(s); } -static void create_stream(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, enum pa_stream_flags flags, pa_volume_t volume) { - struct pa_tagstruct *t; +static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume) { + pa_tagstruct *t; uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED); @@ -326,20 +326,20 @@ static void create_stream(struct pa_stream *s, const char *dev, const struct pa_ pa_stream_unref(s); } -void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, enum pa_stream_flags flags, pa_volume_t volume) { +void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume) { assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); s->direction = PA_STREAM_PLAYBACK; create_stream(s, dev, attr, flags, volume); } -void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, enum pa_stream_flags flags) { +void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags) { assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); s->direction = PA_STREAM_RECORD; create_stream(s, dev, attr, flags, 0); } -void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void (*free_cb)(void *p), size_t delta) { - struct pa_memchunk chunk; +void pa_stream_write(pa_stream *s, const void *data, size_t length, void (*free_cb)(void *p), size_t delta) { + pa_memchunk chunk; assert(s && s->context && data && length && s->state == PA_STREAM_READY && s->ref >= 1); if (free_cb) { @@ -364,20 +364,20 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void s->counter += length; } -size_t pa_stream_writable_size(struct pa_stream *s) { +size_t pa_stream_writable_size(pa_stream *s) { assert(s && s->ref >= 1); return s->state == PA_STREAM_READY ? s->requested_bytes : 0; } -struct pa_operation * pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation * pa_stream_drain(pa_stream *s, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); o = pa_operation_new(s->context, s); assert(o); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -391,9 +391,9 @@ struct pa_operation * pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa return pa_operation_ref(o); } -static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; - struct pa_latency_info i, *p = NULL; +static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + pa_latency_info i, *p = NULL; struct timeval local, remote, now; assert(pd && o && o->stream && o->context); @@ -444,7 +444,7 @@ static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t c } if (o->callback) { - void (*cb)(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) = o->callback; + void (*cb)(pa_stream *s, const pa_latency_info *_i, void *_userdata) = (void (*)(pa_stream *s, const pa_latency_info *_i, void *_userdata)) o->callback; cb(o->stream, p, o->userdata); } @@ -453,16 +453,16 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_stream_get_latency_info(struct pa_stream *s, void (*cb)(struct pa_stream *p, const struct pa_latency_info*i, void *userdata), void *userdata) { +pa_operation* pa_stream_get_latency_info(pa_stream *s, void (*cb)(pa_stream *p, const pa_latency_info*i, void *userdata), void *userdata) { uint32_t tag; - struct pa_operation *o; - struct pa_tagstruct *t; + pa_operation *o; + pa_tagstruct *t; struct timeval now; assert(s && s->direction != PA_STREAM_UPLOAD); o = pa_operation_new(s->context, s); assert(o); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -481,8 +481,8 @@ struct pa_operation* pa_stream_get_latency_info(struct pa_stream *s, void (*cb)( return pa_operation_ref(o); } -void pa_stream_disconnect_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_stream *s = userdata; +void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_stream *s = userdata; assert(pd && s && s->ref >= 1); pa_stream_ref(s); @@ -504,8 +504,8 @@ finish: pa_stream_unref(s); } -void pa_stream_disconnect(struct pa_stream *s) { - struct pa_tagstruct *t; +void pa_stream_disconnect(pa_stream *s) { + pa_tagstruct *t; uint32_t tag; assert(s && s->ref >= 1); @@ -527,26 +527,26 @@ void pa_stream_disconnect(struct pa_stream *s) { pa_stream_unref(s); } -void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { +void pa_stream_set_read_callback(pa_stream *s, void (*cb)(pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { assert(s && s->ref >= 1); s->read_callback = cb; s->read_userdata = userdata; } -void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) { +void pa_stream_set_write_callback(pa_stream *s, void (*cb)(pa_stream *p, size_t length, void *userdata), void *userdata) { assert(s && s->ref >= 1); s->write_callback = cb; s->write_userdata = userdata; } -void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) { +void pa_stream_set_state_callback(pa_stream *s, void (*cb)(pa_stream *s, void *userdata), void *userdata) { assert(s && s->ref >= 1); s->state_callback = cb; s->state_userdata = userdata; } -void pa_stream_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_operation *o = userdata; +void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; int success = 1; assert(pd && o && o->context && o->ref >= 1); @@ -561,7 +561,7 @@ void pa_stream_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, ui } if (o->callback) { - void (*cb)(struct pa_stream *s, int success, void *userdata) = o->callback; + void (*cb)(pa_stream *s, int _success, void *_userdata) = (void (*)(pa_stream *s, int _success, void *_userdata)) o->callback; cb(o->stream, success, o->userdata); } @@ -570,9 +570,9 @@ finish: pa_operation_unref(o); } -struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_stream_cork(pa_stream *s, int b, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); @@ -589,7 +589,7 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru o = pa_operation_new(s->context, s); assert(o); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -606,14 +606,14 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru return pa_operation_ref(o); } -struct pa_operation* pa_stream_send_simple_command(struct pa_stream *s, uint32_t command, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { - struct pa_tagstruct *t; - struct pa_operation *o; +static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata) { + pa_tagstruct *t; + pa_operation *o; uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); o = pa_operation_new(s->context, s); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -626,36 +626,36 @@ struct pa_operation* pa_stream_send_simple_command(struct pa_stream *s, uint32_t return pa_operation_ref(o); } -struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { - struct pa_operation *o; - o = pa_stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata); +pa_operation* pa_stream_flush(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata) { + pa_operation *o; + o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata); pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); return o; } -struct pa_operation* pa_stream_prebuf(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { - struct pa_operation *o; - o = pa_stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata); +pa_operation* pa_stream_prebuf(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata) { + pa_operation *o; + o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata); pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); return o; } -struct pa_operation* pa_stream_trigger(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata) { - struct pa_operation *o; - o = pa_stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata); +pa_operation* pa_stream_trigger(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata) { + pa_operation *o; + o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata); pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); return o; } -struct pa_operation* pa_stream_set_name(struct pa_stream *s, const char *name, void(*cb)(struct pa_stream*c, int success, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_stream_set_name(pa_stream *s, const char *name, void(*cb)(pa_stream*c, int success, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_READY && name && s->direction != PA_STREAM_UPLOAD); o = pa_operation_new(s->context, s); assert(o); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -670,12 +670,12 @@ struct pa_operation* pa_stream_set_name(struct pa_stream *s, const char *name, v return pa_operation_ref(o); } -uint64_t pa_stream_get_counter(struct pa_stream *s) { +uint64_t pa_stream_get_counter(pa_stream *s) { assert(s); return s->counter; } -pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info *i) { +pa_usec_t pa_stream_get_time(pa_stream *s, const pa_latency_info *i) { pa_usec_t usec; assert(s); @@ -707,7 +707,7 @@ pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info * return usec; } -static pa_usec_t time_counter_diff(struct pa_stream *s, pa_usec_t t, pa_usec_t c, int *negative) { +static pa_usec_t time_counter_diff(pa_stream *s, pa_usec_t t, pa_usec_t c, int *negative) { assert(s); if (negative) @@ -725,7 +725,7 @@ static pa_usec_t time_counter_diff(struct pa_stream *s, pa_usec_t t, pa_usec_t c return c-t; } -pa_usec_t pa_stream_get_latency(struct pa_stream *s, const struct pa_latency_info *i, int *negative) { +pa_usec_t pa_stream_get_latency(pa_stream *s, const pa_latency_info *i, int *negative) { pa_usec_t t, c; assert(s && i); @@ -735,12 +735,12 @@ pa_usec_t pa_stream_get_latency(struct pa_stream *s, const struct pa_latency_inf return time_counter_diff(s, t, c, negative); } -const struct pa_sample_spec* pa_stream_get_sample_spec(struct pa_stream *s) { +const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s) { assert(s); return &s->sample_spec; } -void pa_stream_trash_ipol(struct pa_stream *s) { +void pa_stream_trash_ipol(pa_stream *s) { assert(s); if (!s->interpolate) @@ -750,7 +750,7 @@ void pa_stream_trash_ipol(struct pa_stream *s) { s->ipol_usec = 0; } -pa_usec_t pa_stream_get_interpolated_time(struct pa_stream *s) { +pa_usec_t pa_stream_get_interpolated_time(pa_stream *s) { pa_usec_t usec; assert(s && s->interpolate); @@ -771,7 +771,7 @@ pa_usec_t pa_stream_get_interpolated_time(struct pa_stream *s) { return usec; } -pa_usec_t pa_stream_get_interpolated_latency(struct pa_stream *s, int *negative) { +pa_usec_t pa_stream_get_interpolated_latency(pa_stream *s, int *negative) { pa_usec_t t, c; assert(s && s->interpolate); diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index 939b2ae64..806579f57 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -34,43 +34,43 @@ PA_C_DECL_BEGIN -/** \struct pa_stream +/** \pa_stream * An opaque stream for playback or recording */ -struct pa_stream; +typedef struct pa_stream pa_stream; /** Create a new, unconnected stream with the specified name and sample type */ -struct pa_stream* pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss); +pa_stream* pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss); /** Decrease the reference counter by one */ -void pa_stream_unref(struct pa_stream *s); +void pa_stream_unref(pa_stream *s); /** Increase the reference counter by one */ -struct pa_stream *pa_stream_ref(struct pa_stream *s); +pa_stream *pa_stream_ref(pa_stream *s); /** Return the current state of the stream */ -enum pa_stream_state pa_stream_get_state(struct pa_stream *p); +pa_stream_state pa_stream_get_state(pa_stream *p); /** Return the context this stream is attached to */ -struct pa_context* pa_stream_get_context(struct pa_stream *p); +pa_context* pa_stream_get_context(pa_stream *p); /** Return the device (sink input or source output) index this stream is connected to */ -uint32_t pa_stream_get_index(struct pa_stream *s); +uint32_t pa_stream_get_index(pa_stream *s); /** Connect the stream to a sink */ -void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, enum pa_stream_flags flags, pa_volume_t volume); +void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume); /** Connect the stream to a source */ -void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr, enum pa_stream_flags flags); +void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags); /** Disconnect a stream from a source/sink */ -void pa_stream_disconnect(struct pa_stream *s); +void pa_stream_disconnect(pa_stream *s); /** Write some data to the server (for playback sinks), if free_cb is * non-NULL this routine is called when all data has been written out * and an internal reference to the specified data is kept, the data * is not copied. If NULL, the data is copied into an internal * buffer. */ -void pa_stream_write(struct pa_stream *p /**< The stream to use */, +void pa_stream_write(pa_stream *p /**< The stream to use */, const void *data /**< The data to write */, size_t length /**< The length of the data to write */, void (*free_cb)(void *p) /**< A cleanup routine for the data or NULL to request an internal copy */, @@ -96,74 +96,74 @@ void pa_stream_write(struct pa_stream *p /**< The stream to use */, upload streams. */); /** Return the amount of bytes that may be written using pa_stream_write() */ -size_t pa_stream_writable_size(struct pa_stream *p); +size_t pa_stream_writable_size(pa_stream *p); /** Drain a playback stream */ -struct pa_operation* pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); +pa_operation* pa_stream_drain(pa_stream *s, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata); /** Get the playback latency of a stream */ -struct pa_operation* pa_stream_get_latency_info(struct pa_stream *p, void (*cb)(struct pa_stream *p, const struct pa_latency_info *i, void *userdata), void *userdata); +pa_operation* pa_stream_get_latency_info(pa_stream *p, void (*cb)(pa_stream *p, const pa_latency_info *i, void *userdata), void *userdata); /** Set the callback function that is called whenever the state of the stream changes */ -void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata); +void pa_stream_set_state_callback(pa_stream *s, void (*cb)(pa_stream *s, void *userdata), void *userdata); /** Set the callback function that is called when new data may be * written to the stream. */ -void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata); +void pa_stream_set_write_callback(pa_stream *p, void (*cb)(pa_stream *p, size_t length, void *userdata), void *userdata); /** Set the callback function that is called when new data is available from the stream */ -void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); +void pa_stream_set_read_callback(pa_stream *p, void (*cb)(pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); /** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. \since 0.3 */ -struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata); +pa_operation* pa_stream_cork(pa_stream *s, int b, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata); /** Flush the playback buffer of this stream. Most of the time you're * better off using the parameter delta of pa_stream_write() instead of this * function. Available on both playback and recording streams. \since 0.3 */ -struct pa_operation* pa_stream_flush(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); +pa_operation* pa_stream_flush(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata); /** Reenable prebuffering. Available for playback streams only. \since 0.6 */ -struct pa_operation* pa_stream_prebuf(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); +pa_operation* pa_stream_prebuf(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata); /** Request immediate start of playback on this stream. This disables * prebuffering as specified in the pa_buffer_attr structure. Available for playback streams only. \since * 0.3 */ -struct pa_operation* pa_stream_trigger(struct pa_stream *s, void (*cb)(struct pa_stream *s, int success, void *userdata), void *userdata); +pa_operation* pa_stream_trigger(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata); /** Rename the stream. \since 0.5 */ -struct pa_operation* pa_stream_set_name(struct pa_stream *s, const char *name, void(*cb)(struct pa_stream*c, int success, void *userdata), void *userdata); +pa_operation* pa_stream_set_name(pa_stream *s, const char *name, void(*cb)(pa_stream*c, int success, void *userdata), void *userdata); /** Return the total number of bytes written to/read from the * stream. This counter is not reset on pa_stream_flush(), you may do * this yourself using pa_stream_reset_counter(). \since 0.6 */ -uint64_t pa_stream_get_counter(struct pa_stream *s); +uint64_t pa_stream_get_counter(pa_stream *s); /** Return the current playback/recording time. This is based on the * counter accessible with pa_stream_get_counter(). This function * requires a pa_latency_info structure as argument, which should be * acquired using pa_stream_get_latency(). \since 0.6 */ -pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info *i); +pa_usec_t pa_stream_get_time(pa_stream *s, const pa_latency_info *i); /** Return the total stream latency. Thus function requires a * pa_latency_info structure as argument, which should be aquired * using pa_stream_get_latency(). In case the stream is a monitoring * stream the result can be negative, i.e. the captured samples are * not yet played. In this case *negative is set to 1. \since 0.6 */ -pa_usec_t pa_stream_get_latency(struct pa_stream *s, const struct pa_latency_info *i, int *negative); +pa_usec_t pa_stream_get_latency(pa_stream *s, const pa_latency_info *i, int *negative); /** Return the interpolated playback/recording time. Requires the * PA_STREAM_INTERPOLATE_LATENCY bit set when creating the stream. In * contrast to pa_stream_get_latency() this function doesn't require * a whole roundtrip for response. \since 0.6 */ -pa_usec_t pa_stream_get_interpolated_time(struct pa_stream *s); +pa_usec_t pa_stream_get_interpolated_time(pa_stream *s); /** Return the interpolated playback/recording latency. Requires the * PA_STREAM_INTERPOLATE_LATENCY bit set when creating the * stream. \since 0.6 */ -pa_usec_t pa_stream_get_interpolated_latency(struct pa_stream *s, int *negative); +pa_usec_t pa_stream_get_interpolated_latency(pa_stream *s, int *negative); /** Return a pointer to the streams sample specification. \since 0.6 */ -const struct pa_sample_spec* pa_stream_get_sample_spec(struct pa_stream *s); +const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s); PA_C_DECL_END diff --git a/polyp/polyplib-subscribe.c b/polyp/polyplib-subscribe.c index d7e8e7c15..69ae588fb 100644 --- a/polyp/polyplib-subscribe.c +++ b/polyp/polyplib-subscribe.c @@ -29,10 +29,11 @@ #include "polyplib-subscribe.h" #include "polyplib-internal.h" #include "pstream-util.h" +#include "gccmacro.h" -void pa_command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { - struct pa_context *c = userdata; - enum pa_subscription_event_type e; +void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_context *c = userdata; + pa_subscription_event_type e; uint32_t index; assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); @@ -53,14 +54,14 @@ finish: } -struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) { - struct pa_operation *o; - struct pa_tagstruct *t; +pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { + pa_operation *o; + pa_tagstruct *t; uint32_t tag; assert(c); o = pa_operation_new(c, NULL); - o->callback = cb; + o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -73,7 +74,7 @@ struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscrip return pa_operation_ref(o); } -void pa_context_set_subscribe_callback(struct pa_context *c, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { +void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { assert(c); c->subscribe_callback = cb; c->subscribe_userdata = userdata; diff --git a/polyp/polyplib-subscribe.h b/polyp/polyplib-subscribe.h index 5c697b716..f2760ee63 100644 --- a/polyp/polyplib-subscribe.h +++ b/polyp/polyplib-subscribe.h @@ -37,10 +37,10 @@ PA_C_DECL_BEGIN /** Enable event notification */ -struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Set the context specific call back function that is called whenever the state of the daemon changes */ -void pa_context_set_subscribe_callback(struct pa_context *c, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); +void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); PA_C_DECL_END diff --git a/polyp/props.c b/polyp/props.c index 1046551be..df748c1ea 100644 --- a/polyp/props.c +++ b/polyp/props.c @@ -25,17 +25,17 @@ #include "props.h" #include "log.h" -struct pa_property { +typedef struct pa_property { char *name; /* Points to memory allocated by the property subsystem */ void *data; /* Points to memory maintained by the caller */ -}; +} pa_property; /* Allocate a new property object */ -static struct pa_property* property_new(const char *name, void *data) { - struct pa_property* p; +static pa_property* property_new(const char *name, void *data) { + pa_property* p; assert(name && data); - p = pa_xmalloc(sizeof(struct pa_property)); + p = pa_xmalloc(sizeof(pa_property)); p->name = pa_xstrdup(name); p->data = data; @@ -43,15 +43,15 @@ static struct pa_property* property_new(const char *name, void *data) { } /* Free a property object */ -static void property_free(struct pa_property *p) { +static void property_free(pa_property *p) { assert(p); pa_xfree(p->name); pa_xfree(p); } -void* pa_property_get(struct pa_core *c, const char *name) { - struct pa_property *p; +void* pa_property_get(pa_core *c, const char *name) { + pa_property *p; assert(c && name && c->properties); if (!(p = pa_hashmap_get(c->properties, name))) @@ -60,8 +60,8 @@ void* pa_property_get(struct pa_core *c, const char *name) { return p->data; } -int pa_property_set(struct pa_core *c, const char *name, void *data) { - struct pa_property *p; +int pa_property_set(pa_core *c, const char *name, void *data) { + pa_property *p; assert(c && name && data && c->properties); if (pa_hashmap_get(c->properties, name)) @@ -72,8 +72,8 @@ int pa_property_set(struct pa_core *c, const char *name, void *data) { return 0; } -int pa_property_remove(struct pa_core *c, const char *name) { - struct pa_property *p; +int pa_property_remove(pa_core *c, const char *name) { + pa_property *p; assert(c && name && c->properties); if (!(p = pa_hashmap_remove(c->properties, name))) @@ -83,35 +83,35 @@ int pa_property_remove(struct pa_core *c, const char *name) { return 0; } -void pa_property_init(struct pa_core *c) { +void pa_property_init(pa_core *c) { assert(c); c->properties = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); } -void pa_property_cleanup(struct pa_core *c) { +void pa_property_cleanup(pa_core *c) { assert(c); if (!c->properties) return; - assert(!pa_hashmap_ncontents(c->properties)); + assert(!pa_hashmap_size(c->properties)); pa_hashmap_free(c->properties, NULL, NULL); c->properties = NULL; } -void pa_property_dump(struct pa_core *c, struct pa_strbuf *s) { +void pa_property_dump(pa_core *c, pa_strbuf *s) { void *state = NULL; - struct pa_property *p; + pa_property *p; assert(c && s); while ((p = pa_hashmap_iterate(c->properties, &state, NULL))) pa_strbuf_printf(s, "[%s] -> [%p]\n", p->name, p->data); } -int pa_property_replace(struct pa_core *c, const char *name, void *data) { +int pa_property_replace(pa_core *c, const char *name, void *data) { assert(c && name); pa_property_remove(c, name); diff --git a/polyp/props.h b/polyp/props.h index 9b379cf16..5abf8787c 100644 --- a/polyp/props.h +++ b/polyp/props.h @@ -33,26 +33,26 @@ * reference counting themselves. */ /* Return a pointer to the value of the specified property. */ -void* pa_property_get(struct pa_core *c, const char *name); +void* pa_property_get(pa_core *c, const char *name); /* Set the property 'name' to 'data'. This function fails in case a * property by this name already exists. The property data is not * copied or reference counted. This is the caller's job. */ -int pa_property_set(struct pa_core *c, const char *name, void *data); +int pa_property_set(pa_core *c, const char *name, void *data); /* Remove the specified property. Return non-zero on failure */ -int pa_property_remove(struct pa_core *c, const char *name); +int pa_property_remove(pa_core *c, const char *name); /* A combination of pa_property_remove() and pa_property_set() */ -int pa_property_replace(struct pa_core *c, const char *name, void *data); +int pa_property_replace(pa_core *c, const char *name, void *data); /* Free all memory used by the property system */ -void pa_property_cleanup(struct pa_core *c); +void pa_property_cleanup(pa_core *c); /* Initialize the properties subsystem */ -void pa_property_init(struct pa_core *c); +void pa_property_init(pa_core *c); /* Dump the current set of properties */ -void pa_property_dump(struct pa_core *c, struct pa_strbuf *s); +void pa_property_dump(pa_core *c, pa_strbuf *s); #endif diff --git a/polyp/protocol-cli.c b/polyp/protocol-cli.c index 107acb194..d2d73550b 100644 --- a/polyp/protocol-cli.c +++ b/polyp/protocol-cli.c @@ -35,25 +35,25 @@ #define MAX_CONNECTIONS 25 struct pa_protocol_cli { - struct pa_module *module; - struct pa_core *core; - struct pa_socket_server*server; - struct pa_idxset *connections; + pa_module *module; + pa_core *core; + pa_socket_server*server; + pa_idxset *connections; }; -static void cli_eof_cb(struct pa_cli*c, void*userdata) { - struct pa_protocol_cli *p = userdata; +static void cli_eof_cb(pa_cli*c, void*userdata) { + pa_protocol_cli *p = userdata; assert(p); pa_idxset_remove_by_data(p->connections, c, NULL); pa_cli_free(c); } -static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { - struct pa_protocol_cli *p = userdata; - struct pa_cli *c; +static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) { + pa_protocol_cli *p = userdata; + pa_cli *c; assert(s && io && p); - if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { + if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); pa_iochannel_free(io); return; @@ -66,11 +66,11 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo pa_idxset_put(p->connections, c, NULL); } -struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { - struct pa_protocol_cli* p; +pa_protocol_cli* pa_protocol_cli_new(pa_core *core, pa_socket_server *server, pa_module *m, PA_GCC_UNUSED pa_modargs *ma) { + pa_protocol_cli* p; assert(core && server); - p = pa_xmalloc(sizeof(struct pa_protocol_cli)); + p = pa_xmalloc(sizeof(pa_protocol_cli)); p->module = m; p->core = core; p->server = server; @@ -81,12 +81,12 @@ struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_sock return p; } -static void free_connection(void *p, void *userdata) { +static void free_connection(void *p, PA_GCC_UNUSED void *userdata) { assert(p); pa_cli_free(p); } -void pa_protocol_cli_free(struct pa_protocol_cli *p) { +void pa_protocol_cli_free(pa_protocol_cli *p) { assert(p); pa_idxset_free(p->connections, free_connection, NULL); diff --git a/polyp/protocol-cli.h b/polyp/protocol-cli.h index e0fe4bc11..aed733c13 100644 --- a/polyp/protocol-cli.h +++ b/polyp/protocol-cli.h @@ -27,9 +27,9 @@ #include "module.h" #include "modargs.h" -struct pa_protocol_cli; +typedef struct pa_protocol_cli pa_protocol_cli; -struct pa_protocol_cli* pa_protocol_cli_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); -void pa_protocol_cli_free(struct pa_protocol_cli *n); +pa_protocol_cli* pa_protocol_cli_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma); +void pa_protocol_cli_free(pa_protocol_cli *n); #endif diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 18ecb0ac1..a97bc25ce 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -45,6 +45,7 @@ #include "namereg.h" #include "xmalloc.h" #include "log.h" +#include "util.h" /* Don't accept more connection than this */ #define MAX_CONNECTIONS 10 @@ -70,9 +71,9 @@ struct connection { uint32_t index; int dead; - struct pa_protocol_esound *protocol; - struct pa_iochannel *io; - struct pa_client *client; + pa_protocol_esound *protocol; + pa_iochannel *io; + pa_client *client; int authorized, swap_byte_order; void *write_data; size_t write_data_alloc, write_data_index, write_data_length; @@ -80,31 +81,31 @@ struct connection { size_t read_data_alloc, read_data_length; esd_proto_t request; esd_client_state_t state; - struct pa_sink_input *sink_input; - struct pa_source_output *source_output; - struct pa_memblockq *input_memblockq, *output_memblockq; - struct pa_defer_event *defer_event; + pa_sink_input *sink_input; + pa_source_output *source_output; + pa_memblockq *input_memblockq, *output_memblockq; + pa_defer_event *defer_event; struct { - struct pa_memblock *current_memblock; + pa_memblock *current_memblock; size_t memblock_index, fragment_size; } playback; struct { - struct pa_memchunk memchunk; + pa_memchunk memchunk; char *name; - struct pa_sample_spec sample_spec; + pa_sample_spec sample_spec; } scache; - struct pa_time_event *auth_timeout_event; + pa_time_event *auth_timeout_event; }; struct pa_protocol_esound { int public; - struct pa_module *module; - struct pa_core *core; - struct pa_socket_server *server; - struct pa_idxset *connections; + pa_module *module; + pa_core *core; + pa_socket_server *server; + pa_idxset *connections; char *sink_name, *source_name; unsigned n_player; uint8_t esd_key[ESD_KEY_LEN]; @@ -116,14 +117,14 @@ typedef struct proto_handler { const char *description; } esd_proto_handler_info_t; -static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); -static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); -static void sink_input_kill_cb(struct pa_sink_input *i); -static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i); -static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o); +static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length); +static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk); +static void sink_input_kill_cb(pa_sink_input *i); +static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i); +static pa_usec_t source_output_get_latency_cb(pa_source_output *o); -static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk); -static void source_output_kill_cb(struct pa_source_output *o); +static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk); +static void source_output_kill_cb(pa_source_output *o); static int esd_proto_connect(struct connection *c, esd_proto_t request, const void *data, size_t length); static int esd_proto_stream_play(struct connection *c, esd_proto_t request, const void *data, size_t length); @@ -239,7 +240,7 @@ static void* connection_write(struct connection *c, size_t length) { return (uint8_t*) c->write_data+i; } -static void format_esd2native(int format, int swap_bytes, struct pa_sample_spec *ss) { +static void format_esd2native(int format, int swap_bytes, pa_sample_spec *ss) { assert(ss); ss->channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1; @@ -249,7 +250,7 @@ static void format_esd2native(int format, int swap_bytes, struct pa_sample_spec ss->format = PA_SAMPLE_U8; } -static int format_native2esd(struct pa_sample_spec *ss) { +static int format_native2esd(pa_sample_spec *ss) { int format = 0; format = (ss->format == PA_SAMPLE_U8) ? ESD_BITS8 : ESD_BITS16; @@ -260,7 +261,7 @@ static int format_native2esd(struct pa_sample_spec *ss) { /*** esound commands ***/ -static int esd_proto_connect(struct connection *c, esd_proto_t request, const void *data, size_t length) { +static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { uint32_t ekey; int *ok; assert(length == (ESD_KEY_LEN + sizeof(uint32_t))); @@ -278,7 +279,7 @@ static int esd_proto_connect(struct connection *c, esd_proto_t request, const vo } } - ekey = *(uint32_t*)((uint8_t*) data+ESD_KEY_LEN); + ekey = *(const uint32_t*)((const uint8_t*) data+ESD_KEY_LEN); if (ekey == ESD_ENDIAN_KEY) c->swap_byte_order = 0; else if (ekey == ESD_SWAP_ENDIAN_KEY) @@ -294,16 +295,16 @@ static int esd_proto_connect(struct connection *c, esd_proto_t request, const vo return 0; } -static int esd_proto_stream_play(struct connection *c, esd_proto_t request, const void *data, size_t length) { +static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { char name[ESD_NAME_MAX]; int format, rate; - struct pa_sink *sink; - struct pa_sample_spec ss; + pa_sink *sink; + pa_sample_spec ss; size_t l; assert(c && length == (sizeof(int)*2+ESD_NAME_MAX)); - format = maybe_swap_endian_32(c->swap_byte_order, *(int*)data); - rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); + format = maybe_swap_endian_32(c->swap_byte_order, *(const int*)data); + rate = maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -318,7 +319,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons return -1; } - strncpy(name, (char*) data + sizeof(int)*2, sizeof(name)); + strncpy(name, (const char*) data + sizeof(int)*2, sizeof(name)); name[sizeof(name)-1] = 0; pa_client_set_name(c->client, name); @@ -353,13 +354,13 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length) { char name[ESD_NAME_MAX]; int format, rate; - struct pa_source *source; - struct pa_sample_spec ss; + pa_source *source; + pa_sample_spec ss; size_t l; assert(c && length == (sizeof(int)*2+ESD_NAME_MAX)); - format = maybe_swap_endian_32(c->swap_byte_order, *(int*)data); - rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); + format = maybe_swap_endian_32(c->swap_byte_order, *(const int*)data); + rate = maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -370,7 +371,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co } if (request == ESD_PROTO_STREAM_MON) { - struct pa_sink* sink; + pa_sink* sink; if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { pa_log(__FILE__": no such sink.\n"); @@ -390,7 +391,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co } } - strncpy(name, (char*) data + sizeof(int)*2, sizeof(name)); + strncpy(name, (const char*) data + sizeof(int)*2, sizeof(name)); name[sizeof(name)-1] = 0; pa_client_set_name(c->client, name); @@ -420,8 +421,8 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co return 0; } -static int esd_proto_get_latency(struct connection *c, esd_proto_t request, const void *data, size_t length) { - struct pa_sink *sink; +static int esd_proto_get_latency(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { + pa_sink *sink; int latency, *lag; assert(c && !data && length == 0); @@ -438,10 +439,10 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons return 0; } -static int esd_proto_server_info(struct connection *c, esd_proto_t request, const void *data, size_t length) { +static int esd_proto_server_info(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { int rate = 44100, format = ESD_STEREO|ESD_BITS16; int *response; - struct pa_sink *sink; + pa_sink *sink; assert(c && data && length == sizeof(int)); if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { @@ -461,7 +462,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v uint8_t *response; size_t t, k, s; struct connection *conn; - size_t index = PA_IDXSET_INVALID; + size_t idx = PA_IDXSET_INVALID; unsigned nsamples; assert(c && data && length == sizeof(int)); @@ -470,11 +471,11 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v k = sizeof(int)*5+ESD_NAME_MAX; s = sizeof(int)*6+ESD_NAME_MAX; - nsamples = c->protocol->core->scache ? pa_idxset_ncontents(c->protocol->core->scache) : 0; + nsamples = c->protocol->core->scache ? pa_idxset_size(c->protocol->core->scache) : 0; response = connection_write(c, (t = s*(nsamples+1) + k*(c->protocol->n_player+1))); assert(k); - for (conn = pa_idxset_first(c->protocol->connections, &index); conn; conn = pa_idxset_next(c->protocol->connections, &index)) { + for (conn = pa_idxset_first(c->protocol->connections, &idx); conn; conn = pa_idxset_next(c->protocol->connections, &idx)) { int format = ESD_BITS16 | ESD_STEREO, rate = 44100, volume = 0xFF; if (conn->state != ESD_STREAMING_DATA) @@ -522,10 +523,10 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v t -= k; if (nsamples) { - struct pa_scache_entry *ce; + pa_scache_entry *ce; - index = PA_IDXSET_INVALID; - for (ce = pa_idxset_first(c->protocol->core->scache, &index); ce; ce = pa_idxset_next(c->protocol->core->scache, &index)) { + idx = PA_IDXSET_INVALID; + for (ce = pa_idxset_first(c->protocol->core->scache, &idx); ce; ce = pa_idxset_next(c->protocol->core->scache, &idx)) { assert(t >= s*2); /* id */ @@ -569,20 +570,20 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v return 0; } -static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const void *data, size_t length) { +static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { int *ok; - uint32_t index, volume; + uint32_t idx, volume; struct connection *conn; assert(c && data && length == sizeof(int)*3); - index = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(int*)data)-1; - volume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); + idx = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(const int*)data)-1; + volume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); volume = (volume*0x100)/0xFF; ok = connection_write(c, sizeof(int)); assert(ok); - if ((conn = pa_idxset_get_by_index(c->protocol->connections, index))) { + if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx))) { assert(conn->sink_input); conn->sink_input->volume = volume; *ok = 1; @@ -592,28 +593,28 @@ static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const return 0; } -static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, const void *data, size_t length) { - struct pa_sample_spec ss; +static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { + pa_sample_spec ss; int format, rate; size_t sc_length; - uint32_t index; + uint32_t idx; int *ok; char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1]; assert(c && data && length == (ESD_NAME_MAX+3*sizeof(int))); - format = maybe_swap_endian_32(c->swap_byte_order, *(int*)data); - rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1)); + format = maybe_swap_endian_32(c->swap_byte_order, *(const int*)data); + rate = maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); - sc_length = (size_t) maybe_swap_endian_32(c->swap_byte_order, (*((int*)data + 2))); + sc_length = (size_t) maybe_swap_endian_32(c->swap_byte_order, (*((const int*)data + 2))); if (sc_length >= MAX_CACHE_SAMPLE_SIZE) return -1; strcpy(name, SCACHE_PREFIX); - strncpy(name+sizeof(SCACHE_PREFIX)-1, (char*) data+3*sizeof(int), ESD_NAME_MAX); + strncpy(name+sizeof(SCACHE_PREFIX)-1, (const char*) data+3*sizeof(int), ESD_NAME_MAX); name[sizeof(name)-1] = 0; assert(!c->scache.memchunk.memblock); @@ -626,19 +627,19 @@ static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, con c->state = ESD_CACHING_SAMPLE; - pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, &index); + pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, &idx); ok = connection_write(c, sizeof(int)); assert(ok); - *ok = index+1; + *ok = idx+1; return 0; } -static int esd_proto_sample_get_id(struct connection *c, esd_proto_t request, const void *data, size_t length) { +static int esd_proto_sample_get_id(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { int *ok; - uint32_t index; + uint32_t idx; char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1]; assert(c && data && length == ESD_NAME_MAX); @@ -651,8 +652,8 @@ static int esd_proto_sample_get_id(struct connection *c, esd_proto_t request, co strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX); name[sizeof(name)-1] = 0; - if ((index = pa_scache_get_id_by_name(c->protocol->core, name)) != PA_IDXSET_INVALID) - *ok = (int) index +1; + if ((idx = pa_scache_get_id_by_name(c->protocol->core, name)) != PA_IDXSET_INVALID) + *ok = (int) idx +1; return 0; } @@ -660,35 +661,35 @@ static int esd_proto_sample_get_id(struct connection *c, esd_proto_t request, co static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t request, const void *data, size_t length) { int *ok; const char *name; - uint32_t index; + uint32_t idx; assert(c && data && length == sizeof(int)); - index = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(int*)data)-1; + idx = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(const int*)data)-1; ok = connection_write(c, sizeof(int)); assert(ok); *ok = 0; - if ((name = pa_scache_get_name_by_id(c->protocol->core, index))) { + if ((name = pa_scache_get_name_by_id(c->protocol->core, idx))) { if (request == ESD_PROTO_SAMPLE_PLAY) { - struct pa_sink *sink; + pa_sink *sink; if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0) - *ok = (int) index+1; + *ok = (int) idx+1; } else { assert(request == ESD_PROTO_SAMPLE_FREE); if (pa_scache_remove_item(c->protocol->core, name) >= 0) - *ok = (int) index+1; + *ok = (int) idx+1; } } return 0; } -static int esd_proto_standby_or_resume(struct connection *c, esd_proto_t request, const void *data, size_t length) { +static int esd_proto_standby_or_resume(struct connection *c, PA_GCC_UNUSED esd_proto_t request, PA_GCC_UNUSED const void *data, PA_GCC_UNUSED size_t length) { int *ok; ok = connection_write(c, sizeof(int)*2); assert(ok); @@ -699,7 +700,7 @@ static int esd_proto_standby_or_resume(struct connection *c, esd_proto_t request /*** client callbacks ***/ -static void client_kill_cb(struct pa_client *c) { +static void client_kill_cb(pa_client *c) { assert(c && c->userdata); connection_free(c->userdata); } @@ -796,11 +797,11 @@ static int do_read(struct connection *c) { assert(c->scache.memchunk.index <= c->scache.memchunk.length); if (c->scache.memchunk.index == c->scache.memchunk.length) { - uint32_t index; + uint32_t idx; int *ok; c->scache.memchunk.index = 0; - pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, &c->scache.memchunk, &index); + pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, &c->scache.memchunk, &idx); pa_memblock_unref(c->scache.memchunk.memblock); c->scache.memchunk.memblock = NULL; @@ -813,11 +814,11 @@ static int do_read(struct connection *c) { ok = connection_write(c, sizeof(int)); assert(ok); - *ok = index+1; + *ok = idx+1; } } else if (c->state == ESD_STREAMING_DATA && c->sink_input) { - struct pa_memchunk chunk; + pa_memchunk chunk; ssize_t r; size_t l; @@ -886,7 +887,7 @@ static int do_write(struct connection *c) { c->write_data_length = c->write_data_index = 0; } else if (c->state == ESD_STREAMING_DATA && c->source_output) { - struct pa_memchunk chunk; + pa_memchunk chunk; ssize_t r; assert(c->output_memblockq); @@ -945,7 +946,7 @@ fail: connection_free(c); } -static void io_callback(struct pa_iochannel*io, void *userdata) { +static void io_callback(pa_iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); @@ -956,7 +957,7 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { /*** defer callback ***/ -static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { +static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { struct connection *c = userdata; assert(a && c && c->defer_event == e); @@ -967,7 +968,7 @@ static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, v /*** sink_input callbacks ***/ -static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { struct connection*c; assert(i && i->userdata && chunk); c = i->userdata; @@ -983,7 +984,7 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk return 0; } -static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { +static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { struct connection*c = i->userdata; assert(i && c && length); @@ -1000,12 +1001,12 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk /* assert(pa_memblockq_get_length(c->input_memblockq) > 2048); */ } -static void sink_input_kill_cb(struct pa_sink_input *i) { +static void sink_input_kill_cb(pa_sink_input *i) { assert(i && i->userdata); connection_free((struct connection *) i->userdata); } -static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { +static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); @@ -1013,7 +1014,7 @@ static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { /*** source_output callbacks ***/ -static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk) { +static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) { struct connection *c = o->userdata; assert(o && c && chunk); @@ -1026,12 +1027,12 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } -static void source_output_kill_cb(struct pa_source_output *o) { +static void source_output_kill_cb(pa_source_output *o) { assert(o && o->userdata); connection_free((struct connection *) o->userdata); } -static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o) { +static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { struct connection*c = o->userdata; assert(o && c); return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec); @@ -1039,7 +1040,7 @@ static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o) { /*** socket server callback ***/ -static void auth_timeout(struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata) { +static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { struct connection *c = userdata; assert(m && tv && c && c->auth_timeout_event == e); @@ -1047,13 +1048,13 @@ static void auth_timeout(struct pa_mainloop_api*m, struct pa_time_event *e, cons connection_free(c); } -static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { +static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) { struct connection *c; - struct pa_protocol_esound *p = userdata; + pa_protocol_esound *p = userdata; char cname[256]; assert(s && io && p); - if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { + if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); pa_iochannel_free(io); return; @@ -1116,12 +1117,12 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo /*** entry points ***/ -struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { - struct pa_protocol_esound *p; +pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *server, pa_module *m, pa_modargs *ma) { + pa_protocol_esound *p; int public = 0; assert(core && server && ma); - p = pa_xmalloc(sizeof(struct pa_protocol_esound)); + p = pa_xmalloc(sizeof(pa_protocol_esound)); if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { pa_log(__FILE__": public= expects a boolean argument.\n"); @@ -1148,7 +1149,7 @@ struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa return p; } -void pa_protocol_esound_free(struct pa_protocol_esound *p) { +void pa_protocol_esound_free(pa_protocol_esound *p) { struct connection *c; assert(p); diff --git a/polyp/protocol-esound.h b/polyp/protocol-esound.h index dda6977df..71d58464e 100644 --- a/polyp/protocol-esound.h +++ b/polyp/protocol-esound.h @@ -27,9 +27,9 @@ #include "module.h" #include "modargs.h" -struct pa_protocol_esound; +typedef struct pa_protocol_esound pa_protocol_esound; -struct pa_protocol_esound* pa_protocol_esound_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); -void pa_protocol_esound_free(struct pa_protocol_esound *p); +pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *server, pa_module *m, pa_modargs *ma); +void pa_protocol_esound_free(pa_protocol_esound *p); #endif diff --git a/polyp/protocol-http.c b/polyp/protocol-http.c index 64e6dadfb..3e55df03a 100644 --- a/polyp/protocol-http.c +++ b/polyp/protocol-http.c @@ -45,17 +45,17 @@ #define URL_STATUS "/status" struct connection { - struct pa_protocol_http *protocol; - struct pa_ioline *line; + pa_protocol_http *protocol; + pa_ioline *line; enum { REQUEST_LINE, MIME_HEADER, DATA } state; char *url; }; struct pa_protocol_http { - struct pa_module *module; - struct pa_core *core; - struct pa_socket_server*server; - struct pa_idxset *connections; + pa_module *module; + pa_core *core; + pa_socket_server*server; + pa_idxset *connections; }; static void http_response(struct connection *c, int code, const char *msg, const char *mime) { @@ -109,7 +109,7 @@ static void connection_free(struct connection *c, int del) { pa_xfree(c); } -static void line_callback(struct pa_ioline *line, const char *s, void *userdata) { +static void line_callback(pa_ioline *line, const char *s, void *userdata) { struct connection *c = userdata; assert(line); assert(c); @@ -191,12 +191,12 @@ static void line_callback(struct pa_ioline *line, const char *s, void *userdata) pa_ioline_defer_close(c->line); } else if (!strcmp(c->url, URL_STATUS)) { - char *s; + char *r; http_response(c, 200, "OK", "text/plain"); - s = pa_full_status_string(c->protocol->core); - pa_ioline_puts(c->line, s); - pa_xfree(s); + r = pa_full_status_string(c->protocol->core); + pa_ioline_puts(c->line, r); + pa_xfree(r); pa_ioline_defer_close(c->line); } else @@ -215,12 +215,12 @@ fail: internal_server_error(c); } -static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { - struct pa_protocol_http *p = userdata; +static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) { + pa_protocol_http *p = userdata; struct connection *c; assert(s && io && p); - if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { + if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); pa_iochannel_free(io); return; @@ -236,11 +236,11 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo pa_idxset_put(p->connections, c, NULL); } -struct pa_protocol_http* pa_protocol_http_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { - struct pa_protocol_http* p; +pa_protocol_http* pa_protocol_http_new(pa_core *core, pa_socket_server *server, pa_module *m, PA_GCC_UNUSED pa_modargs *ma) { + pa_protocol_http* p; assert(core && server); - p = pa_xmalloc(sizeof(struct pa_protocol_http)); + p = pa_xmalloc(sizeof(pa_protocol_http)); p->module = m; p->core = core; p->server = server; @@ -251,12 +251,12 @@ struct pa_protocol_http* pa_protocol_http_new(struct pa_core *core, struct pa_so return p; } -static void free_connection(void *p, void *userdata) { +static void free_connection(void *p, PA_GCC_UNUSED void *userdata) { assert(p); connection_free(p, 0); } -void pa_protocol_http_free(struct pa_protocol_http *p) { +void pa_protocol_http_free(pa_protocol_http *p) { assert(p); pa_idxset_free(p->connections, free_connection, NULL); diff --git a/polyp/protocol-http.h b/polyp/protocol-http.h index 3c9b8d76b..0a1855e9b 100644 --- a/polyp/protocol-http.h +++ b/polyp/protocol-http.h @@ -27,9 +27,9 @@ #include "module.h" #include "modargs.h" -struct pa_protocol_http; +typedef struct pa_protocol_http pa_protocol_http; -struct pa_protocol_http* pa_protocol_http_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); -void pa_protocol_http_free(struct pa_protocol_http *n); +pa_protocol_http* pa_protocol_http_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma); +void pa_protocol_http_free(pa_protocol_http *n); #endif diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 90dbdaf5b..b19d30d93 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -64,8 +64,8 @@ struct pa_protocol_native; struct record_stream { struct connection *connection; uint32_t index; - struct pa_source_output *source_output; - struct pa_memblockq *memblockq; + pa_source_output *source_output; + pa_memblockq *memblockq; size_t fragment_size; }; @@ -73,8 +73,8 @@ struct playback_stream { int type; struct connection *connection; uint32_t index; - struct pa_sink_input *sink_input; - struct pa_memblockq *memblockq; + pa_sink_input *sink_input; + pa_memblockq *memblockq; size_t requested_bytes; int drain_request; uint32_t drain_tag; @@ -84,10 +84,10 @@ struct upload_stream { int type; struct connection *connection; uint32_t index; - struct pa_memchunk memchunk; + pa_memchunk memchunk; size_t length; char *name; - struct pa_sample_spec sample_spec; + pa_sample_spec sample_spec; }; struct output_stream { @@ -101,141 +101,141 @@ enum { struct connection { int authorized; - struct pa_protocol_native *protocol; - struct pa_client *client; - struct pa_pstream *pstream; - struct pa_pdispatch *pdispatch; - struct pa_idxset *record_streams, *output_streams; + pa_protocol_native *protocol; + pa_client *client; + pa_pstream *pstream; + pa_pdispatch *pdispatch; + pa_idxset *record_streams, *output_streams; uint32_t rrobin_index; - struct pa_subscription *subscription; - struct pa_time_event *auth_timeout_event; + pa_subscription *subscription; + pa_time_event *auth_timeout_event; }; struct pa_protocol_native { - struct pa_module *module; + pa_module *module; int public; - struct pa_core *core; - struct pa_socket_server *server; - struct pa_idxset *connections; + pa_core *core; + pa_socket_server *server; + pa_idxset *connections; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; int auth_cookie_in_property; }; -static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); -static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); -static void sink_input_kill_cb(struct pa_sink_input *i); -static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i); +static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk); +static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length); +static void sink_input_kill_cb(pa_sink_input *i); +static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i); static void request_bytes(struct playback_stream*s); -static void source_output_kill_cb(struct pa_source_output *o); -static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk); -static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o); +static void source_output_kill_cb(pa_source_output *o); +static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk); +static pa_usec_t source_output_get_latency_cb(pa_source_output *o); -static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_delete_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_set_client_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_set_stream_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_kill(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_load_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_unload_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_get_autoload_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_cork_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); -static void command_flush_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); +static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_flush_or_trigger_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_add_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_remove_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_get_autoload_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { - [PA_COMMAND_ERROR] = { NULL }, - [PA_COMMAND_TIMEOUT] = { NULL }, - [PA_COMMAND_REPLY] = { NULL }, - [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream }, - [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_stream }, - [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = { command_drain_playback_stream }, - [PA_COMMAND_CREATE_RECORD_STREAM] = { command_create_record_stream }, - [PA_COMMAND_DELETE_RECORD_STREAM] = { command_delete_stream }, - [PA_COMMAND_AUTH] = { command_auth }, - [PA_COMMAND_REQUEST] = { NULL }, - [PA_COMMAND_EXIT] = { command_exit }, - [PA_COMMAND_SET_CLIENT_NAME] = { command_set_client_name }, - [PA_COMMAND_LOOKUP_SINK] = { command_lookup }, - [PA_COMMAND_LOOKUP_SOURCE] = { command_lookup }, - [PA_COMMAND_STAT] = { command_stat }, - [PA_COMMAND_GET_PLAYBACK_LATENCY] = { command_get_playback_latency }, - [PA_COMMAND_GET_RECORD_LATENCY] = { command_get_record_latency }, - [PA_COMMAND_CREATE_UPLOAD_STREAM] = { command_create_upload_stream }, - [PA_COMMAND_DELETE_UPLOAD_STREAM] = { command_delete_stream }, - [PA_COMMAND_FINISH_UPLOAD_STREAM] = { command_finish_upload_stream }, - [PA_COMMAND_PLAY_SAMPLE] = { command_play_sample }, - [PA_COMMAND_REMOVE_SAMPLE] = { command_remove_sample }, - [PA_COMMAND_GET_SINK_INFO] = { command_get_info }, - [PA_COMMAND_GET_SOURCE_INFO] = { command_get_info }, - [PA_COMMAND_GET_CLIENT_INFO] = { command_get_info }, - [PA_COMMAND_GET_MODULE_INFO] = { command_get_info }, - [PA_COMMAND_GET_SINK_INPUT_INFO] = { command_get_info }, - [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = { command_get_info }, - [PA_COMMAND_GET_SAMPLE_INFO] = { command_get_info }, - [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list }, - [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list }, - [PA_COMMAND_GET_MODULE_INFO_LIST] = { command_get_info_list }, - [PA_COMMAND_GET_CLIENT_INFO_LIST] = { command_get_info_list }, - [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = { command_get_info_list }, - [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = { command_get_info_list }, - [PA_COMMAND_GET_SAMPLE_INFO_LIST] = { command_get_info_list }, - [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info }, - [PA_COMMAND_SUBSCRIBE] = { command_subscribe }, +static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_ERROR] = NULL, + [PA_COMMAND_TIMEOUT] = NULL, + [PA_COMMAND_REPLY] = NULL, + [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream, + [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream, + [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream, + [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream, + [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream, + [PA_COMMAND_AUTH] = command_auth, + [PA_COMMAND_REQUEST] = NULL, + [PA_COMMAND_EXIT] = command_exit, + [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name, + [PA_COMMAND_LOOKUP_SINK] = command_lookup, + [PA_COMMAND_LOOKUP_SOURCE] = command_lookup, + [PA_COMMAND_STAT] = command_stat, + [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency, + [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency, + [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream, + [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream, + [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream, + [PA_COMMAND_PLAY_SAMPLE] = command_play_sample, + [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample, + [PA_COMMAND_GET_SINK_INFO] = command_get_info, + [PA_COMMAND_GET_SOURCE_INFO] = command_get_info, + [PA_COMMAND_GET_CLIENT_INFO] = command_get_info, + [PA_COMMAND_GET_MODULE_INFO] = command_get_info, + [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info, + [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info, + [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info, + [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list, + [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list, + [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list, + [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list, + [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list, + [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list, + [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list, + [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info, + [PA_COMMAND_SUBSCRIBE] = command_subscribe, - [PA_COMMAND_SET_SINK_VOLUME] = { command_set_volume }, - [PA_COMMAND_SET_SINK_INPUT_VOLUME] = { command_set_volume }, + [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume, + [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume, - [PA_COMMAND_CORK_PLAYBACK_STREAM] = { command_cork_playback_stream }, - [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, - [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, - [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream }, + [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream, + [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_or_trigger_playback_stream, + [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_flush_or_trigger_playback_stream, + [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_flush_or_trigger_playback_stream, - [PA_COMMAND_CORK_RECORD_STREAM] = { command_cork_record_stream }, - [PA_COMMAND_FLUSH_RECORD_STREAM] = { command_flush_record_stream }, + [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream, + [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream, - [PA_COMMAND_SET_DEFAULT_SINK] = { command_set_default_sink_or_source }, - [PA_COMMAND_SET_DEFAULT_SOURCE] = { command_set_default_sink_or_source }, - [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = { command_set_stream_name }, - [PA_COMMAND_SET_RECORD_STREAM_NAME] = { command_set_stream_name }, - [PA_COMMAND_KILL_CLIENT] = { command_kill }, - [PA_COMMAND_KILL_SINK_INPUT] = { command_kill }, - [PA_COMMAND_KILL_SOURCE_OUTPUT] = { command_kill }, - [PA_COMMAND_LOAD_MODULE] = { command_load_module }, - [PA_COMMAND_UNLOAD_MODULE] = { command_unload_module }, - [PA_COMMAND_GET_AUTOLOAD_INFO] = { command_get_autoload_info }, - [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = { command_get_autoload_info_list }, - [PA_COMMAND_ADD_AUTOLOAD] = { command_add_autoload }, - [PA_COMMAND_REMOVE_AUTOLOAD] = { command_remove_autoload }, + [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source, + [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source, + [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name, + [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name, + [PA_COMMAND_KILL_CLIENT] = command_kill, + [PA_COMMAND_KILL_SINK_INPUT] = command_kill, + [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill, + [PA_COMMAND_LOAD_MODULE] = command_load_module, + [PA_COMMAND_UNLOAD_MODULE] = command_unload_module, + [PA_COMMAND_GET_AUTOLOAD_INFO] = command_get_autoload_info, + [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = command_get_autoload_info_list, + [PA_COMMAND_ADD_AUTOLOAD] = command_add_autoload, + [PA_COMMAND_REMOVE_AUTOLOAD] = command_remove_autoload, }; /* structure management */ -static struct upload_stream* upload_stream_new(struct connection *c, const struct pa_sample_spec *ss, const char *name, size_t length) { +static struct upload_stream* upload_stream_new(struct connection *c, const pa_sample_spec *ss, const char *name, size_t length) { struct upload_stream *s; assert(c && ss && name && length); @@ -268,9 +268,9 @@ static void upload_stream_free(struct upload_stream *o) { pa_xfree(o); } -static struct record_stream* record_stream_new(struct connection *c, struct pa_source *source, const struct pa_sample_spec *ss, const char *name, size_t maxlength, size_t fragment_size) { +static struct record_stream* record_stream_new(struct connection *c, pa_source *source, const pa_sample_spec *ss, const char *name, size_t maxlength, size_t fragment_size) { struct record_stream *s; - struct pa_source_output *source_output; + pa_source_output *source_output; size_t base; assert(c && source && ss && name && maxlength); @@ -308,14 +308,14 @@ static void record_stream_free(struct record_stream* r) { pa_xfree(r); } -static struct playback_stream* playback_stream_new(struct connection *c, struct pa_sink *sink, const struct pa_sample_spec *ss, const char *name, +static struct playback_stream* playback_stream_new(struct connection *c, pa_sink *sink, const pa_sample_spec *ss, const char *name, size_t maxlength, size_t tlength, size_t prebuf, size_t minreq, pa_volume_t volume) { struct playback_stream *s; - struct pa_sink_input *sink_input; + pa_sink_input *sink_input; assert(c && sink && ss && name && maxlength); if (!(sink_input = pa_sink_input_new(sink, PA_TYPEID_NATIVE, name, ss, 0, -1))) @@ -391,7 +391,7 @@ static void connection_free(struct connection *c) { } static void request_bytes(struct playback_stream *s) { - struct pa_tagstruct *t; + pa_tagstruct *t; size_t l; assert(s); @@ -425,7 +425,7 @@ static void send_memblock(struct connection *c) { start = PA_IDXSET_INVALID; for (;;) { - struct pa_memchunk chunk; + pa_memchunk chunk; if (!(r = pa_idxset_rrobin(c->record_streams, &c->rrobin_index))) return; @@ -436,7 +436,7 @@ static void send_memblock(struct connection *c) { return; if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) { - struct pa_memchunk schunk = chunk; + pa_memchunk schunk = chunk; if (schunk.length > r->fragment_size) schunk.length = r->fragment_size; @@ -451,7 +451,7 @@ static void send_memblock(struct connection *c) { } static void send_playback_stream_killed(struct playback_stream *p) { - struct pa_tagstruct *t; + pa_tagstruct *t; assert(p); t = pa_tagstruct_new(NULL, 0); @@ -463,7 +463,7 @@ static void send_playback_stream_killed(struct playback_stream *p) { } static void send_record_stream_killed(struct record_stream *r) { - struct pa_tagstruct *t; + pa_tagstruct *t; assert(r); t = pa_tagstruct_new(NULL, 0); @@ -476,7 +476,7 @@ static void send_record_stream_killed(struct record_stream *r) { /*** sinkinput callbacks ***/ -static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { struct playback_stream *s; assert(i && i->userdata && chunk); s = i->userdata; @@ -487,7 +487,7 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk return 0; } -static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { +static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { struct playback_stream *s; assert(i && i->userdata && length); s = i->userdata; @@ -503,13 +503,13 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk /* pa_log(__FILE__": after_drop: %u\n", pa_memblockq_get_length(s->memblockq)); */ } -static void sink_input_kill_cb(struct pa_sink_input *i) { +static void sink_input_kill_cb(pa_sink_input *i) { assert(i && i->userdata); send_playback_stream_killed((struct playback_stream *) i->userdata); playback_stream_free((struct playback_stream *) i->userdata); } -static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { +static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { struct playback_stream *s; assert(i && i->userdata); s = i->userdata; @@ -521,7 +521,7 @@ static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { /*** source_output callbacks ***/ -static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk) { +static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) { struct record_stream *s; assert(o && o->userdata && chunk); s = o->userdata; @@ -531,13 +531,13 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me send_memblock(s->connection); } -static void source_output_kill_cb(struct pa_source_output *o) { +static void source_output_kill_cb(pa_source_output *o) { assert(o && o->userdata); send_record_stream_killed((struct record_stream *) o->userdata); record_stream_free((struct record_stream *) o->userdata); } -static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o) { +static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { struct record_stream *s; assert(o && o->userdata); s = o->userdata; @@ -554,15 +554,15 @@ static void protocol_error(struct connection *c) { connection_free(c); } -static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct playback_stream *s; size_t maxlength, tlength, prebuf, minreq; uint32_t sink_index; const char *name, *sink_name; - struct pa_sample_spec ss; - struct pa_tagstruct *reply; - struct pa_sink *sink; + pa_sample_spec ss; + pa_tagstruct *reply; + pa_sink *sink; pa_volume_t volume; int corked; assert(c && t && c->protocol && c->protocol->core); @@ -618,7 +618,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com request_bytes(s); } -static void command_delete_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t channel; assert(c && t); @@ -664,15 +664,15 @@ static void command_delete_stream(struct pa_pdispatch *pd, uint32_t command, uin pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct record_stream *s; size_t maxlength, fragment_size; uint32_t source_index; const char *name, *source_name; - struct pa_sample_spec ss; - struct pa_tagstruct *reply; - struct pa_source *source; + pa_sample_spec ss; + pa_tagstruct *reply; + pa_source *source; int corked; assert(c && t && c->protocol && c->protocol->core); @@ -720,7 +720,7 @@ static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t comma pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; assert(c && t); @@ -740,7 +740,7 @@ static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag return; } -static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const void*cookie; assert(c && t); @@ -769,7 +769,7 @@ static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag return; } -static void command_set_client_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const char *name; assert(c && t); @@ -785,10 +785,10 @@ static void command_set_client_name(struct pa_pdispatch *pd, uint32_t command, u return; } -static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const char *name; - uint32_t index = PA_IDXSET_INVALID; + uint32_t idx = PA_IDXSET_INVALID; assert(c && t); if (pa_tagstruct_gets(t, &name) < 0 || !name || @@ -803,36 +803,36 @@ static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t t } if (command == PA_COMMAND_LOOKUP_SINK) { - struct pa_sink *sink; + pa_sink *sink; if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1))) - index = sink->index; + idx = sink->index; } else { - struct pa_source *source; + pa_source *source; assert(command == PA_COMMAND_LOOKUP_SOURCE); if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1))) - index = source->index; + idx = source->index; } - if (index == PA_IDXSET_INVALID) + if (idx == PA_IDXSET_INVALID) pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); else { - struct pa_tagstruct *reply; + pa_tagstruct *reply; reply = pa_tagstruct_new(NULL, 0); assert(reply); pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); pa_tagstruct_putu32(reply, tag); - pa_tagstruct_putu32(reply, index); + pa_tagstruct_putu32(reply, idx); pa_pstream_send_tagstruct(c->pstream, reply); } } -static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index; + uint32_t idx; struct playback_stream *s; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -843,7 +843,7 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm return; } - if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) { + if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -864,9 +864,9 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm } } -static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - struct pa_tagstruct *reply; + pa_tagstruct *reply; assert(c && t); if (!pa_tagstruct_eof(t)) { @@ -891,16 +891,16 @@ static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - struct pa_tagstruct *reply; + pa_tagstruct *reply; struct playback_stream *s; struct timeval tv, now; uint64_t counter; - uint32_t index; + uint32_t idx; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_timeval(t, &tv) < 0 || pa_tagstruct_getu64(t, &counter) < 0 || !pa_tagstruct_eof(t)) { @@ -913,7 +913,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma return; } - if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) { + if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -934,16 +934,16 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - struct pa_tagstruct *reply; + pa_tagstruct *reply; struct record_stream *s; struct timeval tv, now; uint64_t counter; - uint32_t index; + uint32_t idx; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_timeval(t, &tv) < 0 || pa_tagstruct_getu64(t, &counter) < 0 || !pa_tagstruct_eof(t)) { @@ -956,7 +956,7 @@ static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command return; } - if (!(s = pa_idxset_get_by_index(c->record_streams, index))) { + if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -978,13 +978,13 @@ static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command } -static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct upload_stream *s; size_t length; const char *name; - struct pa_sample_spec ss; - struct pa_tagstruct *reply; + pa_sample_spec ss; + pa_tagstruct *reply; assert(c && t && c->protocol && c->protocol->core); if (pa_tagstruct_gets(t, &name) < 0 || !name || @@ -1019,11 +1019,11 @@ static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t comma pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t channel; struct upload_stream *s; - uint32_t index; + uint32_t idx; assert(c && t); if (pa_tagstruct_getu32(t, &channel) < 0 || @@ -1042,15 +1042,15 @@ static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t comma return; } - pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &index); + pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &idx); pa_pstream_send_simple_ack(c->pstream, tag); upload_stream_free(s); } -static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t sink_index, volume; - struct pa_sink *sink; + pa_sink *sink; const char *name, *sink_name; assert(c && t); @@ -1086,7 +1086,7 @@ static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint3 pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const char *name; assert(c && t); @@ -1110,7 +1110,7 @@ static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uin pa_pstream_send_simple_ack(c->pstream, tag); } -static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) { +static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { assert(t && sink); pa_tagstruct_putu32(t, sink->index); pa_tagstruct_puts(t, sink->name); @@ -1124,7 +1124,7 @@ static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) { pa_tagstruct_putu32(t, sink->typeid); } -static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *source) { +static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { assert(t && source); pa_tagstruct_putu32(t, source->index); pa_tagstruct_puts(t, source->name); @@ -1137,7 +1137,7 @@ static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *sour pa_tagstruct_putu32(t, source->typeid); } -static void client_fill_tagstruct(struct pa_tagstruct *t, struct pa_client *client) { +static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) { assert(t && client); pa_tagstruct_putu32(t, client->index); pa_tagstruct_puts(t, client->name); @@ -1145,7 +1145,7 @@ static void client_fill_tagstruct(struct pa_tagstruct *t, struct pa_client *clie pa_tagstruct_putu32(t, client->typeid); } -static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *module) { +static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) { assert(t && module); pa_tagstruct_putu32(t, module->index); pa_tagstruct_puts(t, module->name); @@ -1154,7 +1154,7 @@ static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *modu pa_tagstruct_put_boolean(t, module->auto_unload); } -static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_input *s) { +static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) { assert(t && s); pa_tagstruct_putu32(t, s->index); pa_tagstruct_puts(t, s->name); @@ -1169,7 +1169,7 @@ static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_inp pa_tagstruct_putu32(t, s->typeid); } -static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) { +static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) { assert(t && s); pa_tagstruct_putu32(t, s->index); pa_tagstruct_puts(t, s->name); @@ -1183,7 +1183,7 @@ static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_sourc pa_tagstruct_putu32(t, s->typeid); } -static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry *e) { +static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) { assert(t && e); pa_tagstruct_putu32(t, e->index); pa_tagstruct_puts(t, e->name); @@ -1195,22 +1195,22 @@ static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry pa_tagstruct_puts(t, e->filename); } -static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index; - struct pa_sink *sink = NULL; - struct pa_source *source = NULL; - struct pa_client *client = NULL; - struct pa_module *module = NULL; - struct pa_sink_input *si = NULL; - struct pa_source_output *so = NULL; - struct pa_scache_entry *sce = NULL; + uint32_t idx; + pa_sink *sink = NULL; + pa_source *source = NULL; + pa_client *client = NULL; + pa_module *module = NULL; + pa_sink_input *si = NULL; + pa_source_output *so = NULL; + pa_scache_entry *sce = NULL; const char *name; - struct pa_tagstruct *reply; + pa_tagstruct *reply; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || (command != PA_COMMAND_GET_CLIENT_INFO && command != PA_COMMAND_GET_MODULE_INFO && command != PA_COMMAND_GET_SINK_INPUT_INFO && @@ -1227,27 +1227,27 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t } if (command == PA_COMMAND_GET_SINK_INFO) { - if (index != (uint32_t) -1) - sink = pa_idxset_get_by_index(c->protocol->core->sinks, index); + if (idx != (uint32_t) -1) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); else sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); } else if (command == PA_COMMAND_GET_SOURCE_INFO) { - if (index != (uint32_t) -1) - source = pa_idxset_get_by_index(c->protocol->core->sources, index); + if (idx != (uint32_t) -1) + source = pa_idxset_get_by_index(c->protocol->core->sources, idx); else source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); } else if (command == PA_COMMAND_GET_CLIENT_INFO) - client = pa_idxset_get_by_index(c->protocol->core->clients, index); + client = pa_idxset_get_by_index(c->protocol->core->clients, idx); else if (command == PA_COMMAND_GET_MODULE_INFO) - module = pa_idxset_get_by_index(c->protocol->core->modules, index); + module = pa_idxset_get_by_index(c->protocol->core->modules, idx); else if (command == PA_COMMAND_GET_SINK_INPUT_INFO) - si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index); + si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO) - so = pa_idxset_get_by_index(c->protocol->core->source_outputs, index); + so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx); else { assert(command == PA_COMMAND_GET_SAMPLE_INFO); - if (index != (uint32_t) -1) - sce = pa_idxset_get_by_index(c->protocol->core->scache, index); + if (idx != (uint32_t) -1) + sce = pa_idxset_get_by_index(c->protocol->core->scache, idx); else sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0); } @@ -1278,12 +1278,12 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - struct pa_idxset *i; - uint32_t index; + pa_idxset *i; + uint32_t idx; void *p; - struct pa_tagstruct *reply; + pa_tagstruct *reply; assert(c && t); if (!pa_tagstruct_eof(t)) { @@ -1319,7 +1319,7 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin } if (i) { - for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) { + for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) { if (command == PA_COMMAND_GET_SINK_INFO_LIST) sink_fill_tagstruct(reply, p); else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST) @@ -1342,9 +1342,9 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - struct pa_tagstruct *reply; + pa_tagstruct *reply; char txt[256]; const char *n; assert(c && t); @@ -1379,8 +1379,8 @@ static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, u pa_pstream_send_tagstruct(c->pstream, reply); } -static void subscription_cb(struct pa_core *core, enum pa_subscription_event_type e, uint32_t index, void *userdata) { - struct pa_tagstruct *t; +static void subscription_cb(pa_core *core, pa_subscription_event_type e, uint32_t idx, void *userdata) { + pa_tagstruct *t; struct connection *c = userdata; assert(c && core); @@ -1389,13 +1389,13 @@ static void subscription_cb(struct pa_core *core, enum pa_subscription_event_typ pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT); pa_tagstruct_putu32(t, (uint32_t) -1); pa_tagstruct_putu32(t, e); - pa_tagstruct_putu32(t, index); + pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); } -static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - enum pa_subscription_mask m; + pa_subscription_mask m; assert(c && t); if (pa_tagstruct_getu32(t, &m) < 0 || @@ -1421,15 +1421,15 @@ static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_ pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index, volume; - struct pa_sink *sink = NULL; - struct pa_sink_input *si = NULL; + uint32_t idx, volume; + pa_sink *sink = NULL; + pa_sink_input *si = NULL; const char *name = NULL; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) || pa_tagstruct_getu32(t, &volume) || !pa_tagstruct_eof(t)) { @@ -1443,13 +1443,13 @@ static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32 } if (command == PA_COMMAND_SET_SINK_VOLUME) { - if (index != (uint32_t) -1) - sink = pa_idxset_get_by_index(c->protocol->core->sinks, index); + if (idx != (uint32_t) -1) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); else sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); } else { assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME); - si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index); + si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); } if (!si && !sink) { @@ -1465,14 +1465,14 @@ static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32 pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index; + uint32_t idx; int b; struct playback_stream *s; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_boolean(t, &b) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1484,7 +1484,7 @@ static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t comma return; } - if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) { + if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1493,13 +1493,13 @@ static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t comma pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_flush_or_trigger_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index; + uint32_t idx; struct playback_stream *s; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1510,7 +1510,7 @@ static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, ui return; } - if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) { + if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1530,14 +1530,14 @@ static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, ui request_bytes(s); } -static void command_cork_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index; + uint32_t idx; struct record_stream *s; int b; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_boolean(t, &b) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1549,7 +1549,7 @@ static void command_cork_record_stream(struct pa_pdispatch *pd, uint32_t command return; } - if (!(s = pa_idxset_get_by_index(c->record_streams, index))) { + if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1558,13 +1558,13 @@ static void command_cork_record_stream(struct pa_pdispatch *pd, uint32_t command pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_flush_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index; + uint32_t idx; struct record_stream *s; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1575,7 +1575,7 @@ static void command_flush_record_stream(struct pa_pdispatch *pd, uint32_t comman return; } - if (!(s = pa_idxset_get_by_index(c->record_streams, index))) { + if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1584,13 +1584,13 @@ static void command_flush_record_stream(struct pa_pdispatch *pd, uint32_t comman pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index; + uint32_t idx; const char *s; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_gets(t, &s) < 0 || !s || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1606,13 +1606,13 @@ static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_set_stream_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index; + uint32_t idx; const char *name; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_gets(t, &name) < 0 || !name || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1627,7 +1627,7 @@ static void command_set_stream_name(struct pa_pdispatch *pd, uint32_t command, u if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) { struct playback_stream *s; - if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) { + if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1637,7 +1637,7 @@ static void command_set_stream_name(struct pa_pdispatch *pd, uint32_t command, u } else { struct record_stream *s; - if (!(s = pa_idxset_get_by_index(c->record_streams, index))) { + if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1648,12 +1648,12 @@ static void command_set_stream_name(struct pa_pdispatch *pd, uint32_t command, u pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_kill(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index; + uint32_t idx; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1665,29 +1665,29 @@ static void command_kill(struct pa_pdispatch *pd, uint32_t command, uint32_t tag } if (command == PA_COMMAND_KILL_CLIENT) { - struct pa_client *client; + pa_client *client; - if (!(client = pa_idxset_get_by_index(c->protocol->core->clients, index))) { + if (!(client = pa_idxset_get_by_index(c->protocol->core->clients, idx))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } pa_client_kill(client); } else if (command == PA_COMMAND_KILL_SINK_INPUT) { - struct pa_sink_input *s; + pa_sink_input *s; - if (!(s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index))) { + if (!(s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } pa_sink_input_kill(s); } else { - struct pa_source_output *s; + pa_source_output *s; assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT); - if (!(s = pa_idxset_get_by_index(c->protocol->core->source_outputs, index))) { + if (!(s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1698,11 +1698,11 @@ static void command_kill(struct pa_pdispatch *pd, uint32_t command, uint32_t tag pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_load_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - struct pa_module *m; + pa_module *m; const char *name, *argument; - struct pa_tagstruct *reply; + pa_tagstruct *reply; assert(c && t); if (pa_tagstruct_gets(t, &name) < 0 || !name || @@ -1729,13 +1729,13 @@ static void command_load_module(struct pa_pdispatch *pd, uint32_t command, uint3 pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_unload_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t index; - struct pa_module *m; + uint32_t idx; + pa_module *m; assert(c && t); - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1746,7 +1746,7 @@ static void command_unload_module(struct pa_pdispatch *pd, uint32_t command, uin return; } - if (!(m = pa_idxset_get_by_index(c->protocol->core->modules, index))) { + if (!(m = pa_idxset_get_by_index(c->protocol->core->modules, idx))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1755,12 +1755,12 @@ static void command_unload_module(struct pa_pdispatch *pd, uint32_t command, uin pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const char *name, *module, *argument; uint32_t type; - uint32_t index; - struct pa_tagstruct *reply; + uint32_t idx; + pa_tagstruct *reply; assert(c && t); if (pa_tagstruct_gets(t, &name) < 0 || !name || @@ -1777,7 +1777,7 @@ static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint return; } - if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &index) < 0) { + if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &idx) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); return; } @@ -1785,21 +1785,21 @@ static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint reply = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); pa_tagstruct_putu32(reply, tag); - pa_tagstruct_putu32(reply, index); + pa_tagstruct_putu32(reply, idx); pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const char *name = NULL; - uint32_t type, index = PA_IDXSET_INVALID; + uint32_t type, idx = PA_IDXSET_INVALID; int r; assert(c && t); - if ((pa_tagstruct_getu32(t, &index) < 0 && + if ((pa_tagstruct_getu32(t, &idx) < 0 && (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_getu32(t, &type) < 0)) || - (!name && index == PA_IDXSET_INVALID) || + (!name && idx == PA_IDXSET_INVALID) || (name && type > 1) || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1814,7 +1814,7 @@ static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, u if (name) r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE); else - r = pa_autoload_remove_by_index(c->protocol->core, index); + r = pa_autoload_remove_by_index(c->protocol->core, idx); if (r < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); @@ -1824,7 +1824,7 @@ static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, u pa_pstream_send_simple_ack(c->pstream, tag); } -static void autoload_fill_tagstruct(struct pa_tagstruct *t, const struct pa_autoload_entry *e) { +static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e) { assert(t && e); pa_tagstruct_putu32(t, e->index); @@ -1834,18 +1834,18 @@ static void autoload_fill_tagstruct(struct pa_tagstruct *t, const struct pa_auto pa_tagstruct_puts(t, e->argument); } -static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - const struct pa_autoload_entry *a = NULL; - uint32_t type, index; + const pa_autoload_entry *a = NULL; + uint32_t type, idx; const char *name; - struct pa_tagstruct *reply; + pa_tagstruct *reply; assert(c && t); - if ((pa_tagstruct_getu32(t, &index) < 0 && + if ((pa_tagstruct_getu32(t, &idx) < 0 && (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_getu32(t, &type) < 0)) || - (!name && index == PA_IDXSET_INVALID) || + (!name && idx == PA_IDXSET_INVALID) || (name && type > 1) || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1861,7 +1861,7 @@ static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, if (name) a = pa_autoload_get_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE); else - a = pa_autoload_get_by_index(c->protocol->core, index); + a = pa_autoload_get_by_index(c->protocol->core, idx); if (!a) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); @@ -1876,9 +1876,9 @@ static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, pa_pstream_send_tagstruct(c->pstream, reply); } -static void command_get_autoload_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { +static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - struct pa_tagstruct *reply; + pa_tagstruct *reply; assert(c && t); if (!pa_tagstruct_eof(t)) { @@ -1896,7 +1896,7 @@ static void command_get_autoload_info_list(struct pa_pdispatch *pd, uint32_t com pa_tagstruct_putu32(reply, tag); if (c->protocol->core->autoload_hashmap) { - struct pa_autoload_entry *a; + pa_autoload_entry *a; void *state = NULL; while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state, NULL))) @@ -1908,7 +1908,7 @@ static void command_get_autoload_info_list(struct pa_pdispatch *pd, uint32_t com /*** pstream callbacks ***/ -static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *userdata) { struct connection *c = userdata; assert(p && packet && packet->data && c); @@ -1918,7 +1918,7 @@ static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *pack } } -static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk, void *userdata) { struct connection *c = userdata; struct output_stream *stream; assert(p && chunk && userdata); @@ -1930,17 +1930,17 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui } if (stream->type == PLAYBACK_STREAM) { - struct playback_stream *p = (struct playback_stream*) stream; - if (chunk->length >= p->requested_bytes) - p->requested_bytes = 0; + struct playback_stream *ps = (struct playback_stream*) stream; + if (chunk->length >= ps->requested_bytes) + ps->requested_bytes = 0; else - p->requested_bytes -= chunk->length; + ps->requested_bytes -= chunk->length; - pa_memblockq_push_align(p->memblockq, chunk, delta); - assert(p->sink_input); + pa_memblockq_push_align(ps->memblockq, chunk, delta); + assert(ps->sink_input); /* pa_log(__FILE__": after_recv: %u\n", pa_memblockq_get_length(p->memblockq)); */ - pa_sink_notify(p->sink_input->sink); + pa_sink_notify(ps->sink_input->sink); /* pa_log(__FILE__": Recieved %u bytes.\n", chunk->length); */ } else { @@ -1974,7 +1974,7 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui } } -static void pstream_die_callback(struct pa_pstream *p, void *userdata) { +static void pstream_die_callback(pa_pstream *p, void *userdata) { struct connection *c = userdata; assert(p && c); connection_free(c); @@ -1983,7 +1983,7 @@ static void pstream_die_callback(struct pa_pstream *p, void *userdata) { } -static void pstream_drain_callback(struct pa_pstream *p, void *userdata) { +static void pstream_drain_callback(pa_pstream *p, void *userdata) { struct connection *c = userdata; assert(p && c); @@ -1992,14 +1992,14 @@ static void pstream_drain_callback(struct pa_pstream *p, void *userdata) { /*** client callbacks ***/ -static void client_kill_cb(struct pa_client *c) { +static void client_kill_cb(pa_client *c) { assert(c && c->userdata); connection_free(c->userdata); } /*** socket server callbacks ***/ -static void auth_timeout(struct pa_mainloop_api*m, struct pa_time_event *e, const struct timeval *tv, void *userdata) { +static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { struct connection *c = userdata; assert(m && tv && c && c->auth_timeout_event == e); @@ -2007,12 +2007,12 @@ static void auth_timeout(struct pa_mainloop_api*m, struct pa_time_event *e, cons connection_free(c); } -static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { - struct pa_protocol_native *p = userdata; +static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, void *userdata) { + pa_protocol_native *p = userdata; struct connection *c; assert(io && p); - if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { + if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); pa_iochannel_free(io); return; @@ -2061,7 +2061,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo /*** module entry points ***/ -static int load_key(struct pa_protocol_native*p, const char*fn) { +static int load_key(pa_protocol_native*p, const char*fn) { assert(p); p->auth_cookie_in_property = 0; @@ -2087,8 +2087,8 @@ static int load_key(struct pa_protocol_native*p, const char*fn) { return 0; } -static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struct pa_module *m, struct pa_modargs *ma) { - struct pa_protocol_native *p; +static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_modargs *ma) { + pa_protocol_native *p; int public = 0; assert(c && ma); @@ -2097,7 +2097,7 @@ static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struc return NULL; } - p = pa_xmalloc(sizeof(struct pa_protocol_native)); + p = pa_xmalloc(sizeof(pa_protocol_native)); p->core = c; p->module = m; p->public = public; @@ -2114,9 +2114,9 @@ static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struc return p; } -struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { +pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) { char t[256]; - struct pa_protocol_native *p; + pa_protocol_native *p; if (!(p = protocol_new_internal(core, m, ma))) return NULL; @@ -2125,7 +2125,7 @@ struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct p pa_socket_server_set_callback(p->server, on_connection, p); if (pa_socket_server_get_address(p->server, t, sizeof(t))) { - struct pa_strlist *l; + pa_strlist *l; l = pa_property_get(core, PA_NATIVE_SERVER_PROPERTY_NAME); l = pa_strlist_prepend(l, t); pa_property_replace(core, PA_NATIVE_SERVER_PROPERTY_NAME, l); @@ -2134,7 +2134,7 @@ struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct p return p; } -void pa_protocol_native_free(struct pa_protocol_native *p) { +void pa_protocol_native_free(pa_protocol_native *p) { struct connection *c; assert(p); @@ -2146,7 +2146,7 @@ void pa_protocol_native_free(struct pa_protocol_native *p) { char t[256]; if (pa_socket_server_get_address(p->server, t, sizeof(t))) { - struct pa_strlist *l; + pa_strlist *l; l = pa_property_get(p->core, PA_NATIVE_SERVER_PROPERTY_NAME); l = pa_strlist_remove(l, t); @@ -2165,8 +2165,8 @@ void pa_protocol_native_free(struct pa_protocol_native *p) { pa_xfree(p); } -struct pa_protocol_native* pa_protocol_native_new_iochannel(struct pa_core*core, struct pa_iochannel *io, struct pa_module *m, struct pa_modargs *ma) { - struct pa_protocol_native *p; +pa_protocol_native* pa_protocol_native_new_iochannel(pa_core*core, pa_iochannel *io, pa_module *m, pa_modargs *ma) { + pa_protocol_native *p; if (!(p = protocol_new_internal(core, m, ma))) return NULL; diff --git a/polyp/protocol-native.h b/polyp/protocol-native.h index 57c29e38f..12e85d0b7 100644 --- a/polyp/protocol-native.h +++ b/polyp/protocol-native.h @@ -27,11 +27,11 @@ #include "module.h" #include "modargs.h" -struct pa_protocol_native; +typedef struct pa_protocol_native pa_protocol_native; -struct pa_protocol_native* pa_protocol_native_new(struct pa_core*core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); -void pa_protocol_native_free(struct pa_protocol_native *n); +pa_protocol_native* pa_protocol_native_new(pa_core*core, pa_socket_server *server, pa_module *m, pa_modargs *ma); +void pa_protocol_native_free(pa_protocol_native *n); -struct pa_protocol_native* pa_protocol_native_new_iochannel(struct pa_core*core, struct pa_iochannel *io, struct pa_module *m, struct pa_modargs *ma); +pa_protocol_native* pa_protocol_native_new_iochannel(pa_core*core, pa_iochannel *io, pa_module *m, pa_modargs *ma); #endif diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index 8d05a7fa0..a3d7099c8 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -45,31 +45,31 @@ #define PA_TYPEID_SIMPLE PA_TYPEID_MAKE('S', 'M', 'P', 'L') struct connection { - struct pa_protocol_simple *protocol; - struct pa_iochannel *io; - struct pa_sink_input *sink_input; - struct pa_source_output *source_output; - struct pa_client *client; - struct pa_memblockq *input_memblockq, *output_memblockq; - struct pa_defer_event *defer_event; + pa_protocol_simple *protocol; + pa_iochannel *io; + pa_sink_input *sink_input; + pa_source_output *source_output; + pa_client *client; + pa_memblockq *input_memblockq, *output_memblockq; + pa_defer_event *defer_event; struct { - struct pa_memblock *current_memblock; + pa_memblock *current_memblock; size_t memblock_index, fragment_size; } playback; }; struct pa_protocol_simple { - struct pa_module *module; - struct pa_core *core; - struct pa_socket_server*server; - struct pa_idxset *connections; + pa_module *module; + pa_core *core; + pa_socket_server*server; + pa_idxset *connections; enum { RECORD = 1, PLAYBACK = 2, DUPLEX = 3 } mode; - struct pa_sample_spec sample_spec; + pa_sample_spec sample_spec; char *source_name, *sink_name; }; @@ -107,7 +107,7 @@ static void connection_free(struct connection *c) { } static int do_read(struct connection *c) { - struct pa_memchunk chunk; + pa_memchunk chunk; ssize_t r; size_t l; @@ -151,7 +151,7 @@ static int do_read(struct connection *c) { } static int do_write(struct connection *c) { - struct pa_memchunk chunk; + pa_memchunk chunk; ssize_t r; if (!c->source_output) @@ -201,7 +201,7 @@ fail: /*** sink_input callbacks ***/ -static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { struct connection*c; assert(i && i->userdata && chunk); c = i->userdata; @@ -212,7 +212,7 @@ static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk return 0; } -static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { +static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { struct connection*c = i->userdata; assert(i && c && length); @@ -223,13 +223,13 @@ static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } -static void sink_input_kill_cb(struct pa_sink_input *i) { +static void sink_input_kill_cb(pa_sink_input *i) { assert(i && i->userdata); connection_free((struct connection *) i->userdata); } -static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { +static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); @@ -237,7 +237,7 @@ static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { /*** source_output callbacks ***/ -static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk) { +static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) { struct connection *c = o->userdata; assert(o && c && chunk); @@ -248,12 +248,12 @@ static void source_output_push_cb(struct pa_source_output *o, const struct pa_me c->protocol->core->mainloop->defer_enable(c->defer_event, 1); } -static void source_output_kill_cb(struct pa_source_output *o) { +static void source_output_kill_cb(pa_source_output *o) { assert(o && o->userdata); connection_free((struct connection *) o->userdata); } -static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o) { +static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { struct connection*c = o->userdata; assert(o && c); return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec); @@ -261,14 +261,14 @@ static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o) { /*** client callbacks ***/ -static void client_kill_cb(struct pa_client *c) { +static void client_kill_cb(pa_client *c) { assert(c && c->userdata); connection_free((struct connection *) c->userdata); } /*** pa_iochannel callbacks ***/ -static void io_callback(struct pa_iochannel*io, void *userdata) { +static void io_callback(pa_iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); @@ -277,7 +277,7 @@ static void io_callback(struct pa_iochannel*io, void *userdata) { /*** fixed callback ***/ -static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) { +static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { struct connection *c = userdata; assert(a && c && c->defer_event == e); @@ -286,13 +286,13 @@ static void defer_callback(struct pa_mainloop_api*a, struct pa_defer_event *e, v /*** socket_server callbacks ***/ -static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) { - struct pa_protocol_simple *p = userdata; +static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) { + pa_protocol_simple *p = userdata; struct connection *c = NULL; char cname[256]; assert(s && io && p); - if (pa_idxset_ncontents(p->connections)+1 > MAX_CONNECTIONS) { + if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); pa_iochannel_free(io); return; @@ -317,7 +317,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo c->client->userdata = c; if (p->mode & PLAYBACK) { - struct pa_sink *sink; + pa_sink *sink; size_t l; if (!(sink = pa_namereg_get(p->core, p->sink_name, PA_NAMEREG_SINK, 1))) { @@ -347,7 +347,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo } if (p->mode & RECORD) { - struct pa_source *source; + pa_source *source; size_t l; if (!(source = pa_namereg_get(p->core, p->source_name, PA_NAMEREG_SOURCE, 1))) { @@ -387,12 +387,12 @@ fail: connection_free(c); } -struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) { - struct pa_protocol_simple* p = NULL; +pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) { + pa_protocol_simple* p = NULL; int enable; assert(core && server && ma); - p = pa_xmalloc0(sizeof(struct pa_protocol_simple)); + p = pa_xmalloc0(sizeof(pa_protocol_simple)); p->module = m; p->core = core; p->server = server; @@ -437,7 +437,7 @@ fail: } -void pa_protocol_simple_free(struct pa_protocol_simple *p) { +void pa_protocol_simple_free(pa_protocol_simple *p) { struct connection *c; assert(p); diff --git a/polyp/protocol-simple.h b/polyp/protocol-simple.h index 7b15ffcd5..63455a53e 100644 --- a/polyp/protocol-simple.h +++ b/polyp/protocol-simple.h @@ -27,9 +27,9 @@ #include "core.h" #include "modargs.h" -struct pa_protocol_simple; +typedef struct pa_protocol_simple pa_protocol_simple; -struct pa_protocol_simple* pa_protocol_simple_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma); -void pa_protocol_simple_free(struct pa_protocol_simple *n); +pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma); +void pa_protocol_simple_free(pa_protocol_simple *n); #endif diff --git a/polyp/pstream-util.c b/polyp/pstream-util.c index 8526f29ce..ecd63d15f 100644 --- a/polyp/pstream-util.c +++ b/polyp/pstream-util.c @@ -28,10 +28,10 @@ #include "native-common.h" #include "pstream-util.h" -void pa_pstream_send_tagstruct(struct pa_pstream *p, struct pa_tagstruct *t) { +void pa_pstream_send_tagstruct(pa_pstream *p, pa_tagstruct *t) { size_t length; uint8_t *data; - struct pa_packet *packet; + pa_packet *packet; assert(p); assert(t); @@ -43,8 +43,8 @@ void pa_pstream_send_tagstruct(struct pa_pstream *p, struct pa_tagstruct *t) { pa_packet_unref(packet); } -void pa_pstream_send_error(struct pa_pstream *p, uint32_t tag, uint32_t error) { - struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); +void pa_pstream_send_error(pa_pstream *p, uint32_t tag, uint32_t error) { + pa_tagstruct *t = pa_tagstruct_new(NULL, 0); assert(t); pa_tagstruct_putu32(t, PA_COMMAND_ERROR); pa_tagstruct_putu32(t, tag); @@ -52,8 +52,8 @@ void pa_pstream_send_error(struct pa_pstream *p, uint32_t tag, uint32_t error) { pa_pstream_send_tagstruct(p, t); } -void pa_pstream_send_simple_ack(struct pa_pstream *p, uint32_t tag) { - struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0); +void pa_pstream_send_simple_ack(pa_pstream *p, uint32_t tag) { + pa_tagstruct *t = pa_tagstruct_new(NULL, 0); assert(t); pa_tagstruct_putu32(t, PA_COMMAND_REPLY); pa_tagstruct_putu32(t, tag); diff --git a/polyp/pstream-util.h b/polyp/pstream-util.h index 9560bfe72..601a9e99a 100644 --- a/polyp/pstream-util.h +++ b/polyp/pstream-util.h @@ -27,9 +27,9 @@ #include "tagstruct.h" /* The tagstruct is freed!*/ -void pa_pstream_send_tagstruct(struct pa_pstream *p, struct pa_tagstruct *t); +void pa_pstream_send_tagstruct(pa_pstream *p, pa_tagstruct *t); -void pa_pstream_send_error(struct pa_pstream *p, uint32_t tag, uint32_t error); -void pa_pstream_send_simple_ack(struct pa_pstream *p, uint32_t tag); +void pa_pstream_send_error(pa_pstream *p, uint32_t tag, uint32_t error); +void pa_pstream_send_simple_ack(pa_pstream *p, uint32_t tag); #endif diff --git a/polyp/pstream.c b/polyp/pstream.c index 6f9832897..bd00ba4f9 100644 --- a/polyp/pstream.c +++ b/polyp/pstream.c @@ -39,12 +39,12 @@ #include "xmalloc.h" #include "log.h" -enum pa_pstream_descriptor_index { +typedef enum pa_pstream_descriptor_index { PA_PSTREAM_DESCRIPTOR_LENGTH, PA_PSTREAM_DESCRIPTOR_CHANNEL, PA_PSTREAM_DESCRIPTOR_DELTA, PA_PSTREAM_DESCRIPTOR_MAX -}; +} pa_pstream_descriptor_index; typedef uint32_t pa_pstream_descriptor[PA_PSTREAM_DESCRIPTOR_MAX]; @@ -55,24 +55,24 @@ struct item_info { enum { PA_PSTREAM_ITEM_PACKET, PA_PSTREAM_ITEM_MEMBLOCK } type; /* memblock info */ - struct pa_memchunk chunk; + pa_memchunk chunk; uint32_t channel; uint32_t delta; /* packet info */ - struct pa_packet *packet; + pa_packet *packet; }; struct pa_pstream { int ref; - struct pa_mainloop_api *mainloop; - struct pa_defer_event *defer_event; - struct pa_iochannel *io; - struct pa_queue *send_queue; + pa_mainloop_api *mainloop; + pa_defer_event *defer_event; + pa_iochannel *io; + pa_queue *send_queue; int dead; - void (*die_callback) (struct pa_pstream *p, void *userdata); + void (*die_callback) (pa_pstream *p, void *userdata); void *die_callback_userdata; struct { @@ -83,29 +83,29 @@ struct pa_pstream { } write; struct { - struct pa_memblock *memblock; - struct pa_packet *packet; + pa_memblock *memblock; + pa_packet *packet; pa_pstream_descriptor descriptor; void *data; size_t index; } read; - void (*recieve_packet_callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata); + void (*recieve_packet_callback) (pa_pstream *p, pa_packet *packet, void *userdata); void *recieve_packet_callback_userdata; - void (*recieve_memblock_callback) (struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata); + void (*recieve_memblock_callback) (pa_pstream *p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk, void *userdata); void *recieve_memblock_callback_userdata; - void (*drain_callback)(struct pa_pstream *p, void *userdata); + void (*drain_callback)(pa_pstream *p, void *userdata); void *drain_userdata; - struct pa_memblock_stat *memblock_stat; + pa_memblock_stat *memblock_stat; }; -static void do_write(struct pa_pstream *p); -static void do_read(struct pa_pstream *p); +static void do_write(pa_pstream *p); +static void do_read(pa_pstream *p); -static void do_something(struct pa_pstream *p) { +static void do_something(pa_pstream *p) { assert(p); p->mainloop->defer_enable(p->defer_event, 0); @@ -127,23 +127,23 @@ static void do_something(struct pa_pstream *p) { pa_pstream_unref(p); } -static void io_callback(struct pa_iochannel*io, void *userdata) { - struct pa_pstream *p = userdata; +static void io_callback(pa_iochannel*io, void *userdata) { + pa_pstream *p = userdata; assert(p && p->io == io); do_something(p); } -static void defer_callback(struct pa_mainloop_api *m, struct pa_defer_event *e, void*userdata) { - struct pa_pstream *p = userdata; +static void defer_callback(pa_mainloop_api *m, pa_defer_event *e, void*userdata) { + pa_pstream *p = userdata; assert(p && p->defer_event == e && p->mainloop == m); do_something(p); } -struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io, struct pa_memblock_stat *s) { - struct pa_pstream *p; +pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_stat *s) { + pa_pstream *p; assert(io); - p = pa_xmalloc(sizeof(struct pa_pstream)); + p = pa_xmalloc(sizeof(pa_pstream)); p->ref = 1; p->io = io; pa_iochannel_set_callback(io, io_callback, p); @@ -183,7 +183,7 @@ struct pa_pstream *pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel return p; } -static void item_free(void *item, void *p) { +static void item_free(void *item, PA_GCC_UNUSED void *p) { struct item_info *i = item; assert(i); @@ -199,7 +199,7 @@ static void item_free(void *item, void *p) { pa_xfree(i); } -static void pstream_free(struct pa_pstream *p) { +static void pstream_free(pa_pstream *p) { assert(p); pa_pstream_close(p); @@ -218,7 +218,7 @@ static void pstream_free(struct pa_pstream *p) { pa_xfree(p); } -void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet) { struct item_info *i; assert(p && packet && p->ref >= 1); @@ -235,7 +235,7 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) { p->mainloop->defer_enable(p->defer_event, 1); } -void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk) { +void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk) { struct item_info *i; assert(p && channel != (uint32_t) -1 && chunk && p->ref >= 1); @@ -256,21 +256,21 @@ void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, uint32_t de p->mainloop->defer_enable(p->defer_event, 1); } -void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata) { +void pa_pstream_set_recieve_packet_callback(pa_pstream *p, void (*callback) (pa_pstream *p, pa_packet *packet, void *userdata), void *userdata) { assert(p && callback); p->recieve_packet_callback = callback; p->recieve_packet_callback_userdata = userdata; } -void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata), void *userdata) { +void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, void (*callback) (pa_pstream *p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk, void *userdata), void *userdata) { assert(p && callback); p->recieve_memblock_callback = callback; p->recieve_memblock_callback_userdata = userdata; } -static void prepare_next_write_item(struct pa_pstream *p) { +static void prepare_next_write_item(pa_pstream *p) { assert(p); if (!(p->write.current = pa_queue_pop(p->send_queue))) @@ -295,7 +295,7 @@ static void prepare_next_write_item(struct pa_pstream *p) { } } -static void do_write(struct pa_pstream *p) { +static void do_write(pa_pstream *p) { void *d; size_t l; ssize_t r; @@ -339,9 +339,9 @@ die: p->die_callback(p, p->die_callback_userdata); } -static void do_read(struct pa_pstream *p) { +static void do_read(pa_pstream *p) { void *d; - size_t l; + size_t l; ssize_t r; assert(p); @@ -386,12 +386,10 @@ static void do_read(struct pa_pstream *p) { /* Frame payload available */ if (p->read.memblock && p->recieve_memblock_callback) { /* Is this memblock data? Than pass it to the user */ - size_t l; - l = (p->read.index - r) < PA_PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE : (size_t) r; if (l > 0) { - struct pa_memchunk chunk; + pa_memchunk chunk; chunk.memblock = p->read.memblock; chunk.index = p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE - l; @@ -437,13 +435,13 @@ die: } -void pa_pstream_set_die_callback(struct pa_pstream *p, void (*callback)(struct pa_pstream *p, void *userdata), void *userdata) { +void pa_pstream_set_die_callback(pa_pstream *p, void (*callback)(pa_pstream *p, void *userdata), void *userdata) { assert(p && callback); p->die_callback = callback; p->die_callback_userdata = userdata; } -int pa_pstream_is_pending(struct pa_pstream *p) { +int pa_pstream_is_pending(pa_pstream *p) { assert(p); if (p->dead) @@ -452,27 +450,27 @@ int pa_pstream_is_pending(struct pa_pstream *p) { return p->write.current || !pa_queue_is_empty(p->send_queue); } -void pa_pstream_set_drain_callback(struct pa_pstream *p, void (*cb)(struct pa_pstream *p, void *userdata), void *userdata) { +void pa_pstream_set_drain_callback(pa_pstream *p, void (*cb)(pa_pstream *p, void *userdata), void *userdata) { assert(p); p->drain_callback = cb; p->drain_userdata = userdata; } -void pa_pstream_unref(struct pa_pstream*p) { +void pa_pstream_unref(pa_pstream*p) { assert(p && p->ref >= 1); if (!(--(p->ref))) pstream_free(p); } -struct pa_pstream* pa_pstream_ref(struct pa_pstream*p) { +pa_pstream* pa_pstream_ref(pa_pstream*p) { assert(p && p->ref >= 1); p->ref++; return p; } -void pa_pstream_close(struct pa_pstream *p) { +void pa_pstream_close(pa_pstream *p) { assert(p); p->dead = 1; diff --git a/polyp/pstream.h b/polyp/pstream.h index 8fa62f06a..77c92802e 100644 --- a/polyp/pstream.h +++ b/polyp/pstream.h @@ -30,23 +30,23 @@ #include "mainloop-api.h" #include "memchunk.h" -struct pa_pstream; +typedef struct pa_pstream pa_pstream; -struct pa_pstream* pa_pstream_new(struct pa_mainloop_api *m, struct pa_iochannel *io, struct pa_memblock_stat *s); -void pa_pstream_unref(struct pa_pstream*p); -struct pa_pstream* pa_pstream_ref(struct pa_pstream*p); +pa_pstream* pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_stat *s); +void pa_pstream_unref(pa_pstream*p); +pa_pstream* pa_pstream_ref(pa_pstream*p); -void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet); -void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk); +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet); +void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk); -void pa_pstream_set_recieve_packet_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, struct pa_packet *packet, void *userdata), void *userdata); -void pa_pstream_set_recieve_memblock_callback(struct pa_pstream *p, void (*callback) (struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata), void *userdata); -void pa_pstream_set_drain_callback(struct pa_pstream *p, void (*cb)(struct pa_pstream *p, void *userdata), void *userdata); +void pa_pstream_set_recieve_packet_callback(pa_pstream *p, void (*callback) (pa_pstream *p, pa_packet *packet, void *userdata), void *userdata); +void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, void (*callback) (pa_pstream *p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk, void *userdata), void *userdata); +void pa_pstream_set_drain_callback(pa_pstream *p, void (*cb)(pa_pstream *p, void *userdata), void *userdata); -void pa_pstream_set_die_callback(struct pa_pstream *p, void (*callback)(struct pa_pstream *p, void *userdata), void *userdata); +void pa_pstream_set_die_callback(pa_pstream *p, void (*callback)(pa_pstream *p, void *userdata), void *userdata); -int pa_pstream_is_pending(struct pa_pstream *p); +int pa_pstream_is_pending(pa_pstream *p); -void pa_pstream_close(struct pa_pstream *p); +void pa_pstream_close(pa_pstream *p); #endif diff --git a/polyp/queue.c b/polyp/queue.c index e0a06ae11..80ec00685 100644 --- a/polyp/queue.c +++ b/polyp/queue.c @@ -39,14 +39,14 @@ struct pa_queue { unsigned length; }; -struct pa_queue* pa_queue_new(void) { - struct pa_queue *q = pa_xmalloc(sizeof(struct pa_queue)); +pa_queue* pa_queue_new(void) { + pa_queue *q = pa_xnew(pa_queue, 1); q->front = q->back = NULL; q->length = 0; return q; } -void pa_queue_free(struct pa_queue* q, void (*destroy)(void *p, void *userdata), void *userdata) { +void pa_queue_free(pa_queue* q, void (*destroy)(void *p, void *userdata), void *userdata) { struct queue_entry *e; assert(q); @@ -64,10 +64,10 @@ void pa_queue_free(struct pa_queue* q, void (*destroy)(void *p, void *userdata), pa_xfree(q); } -void pa_queue_push(struct pa_queue *q, void *p) { +void pa_queue_push(pa_queue *q, void *p) { struct queue_entry *e; - e = pa_xmalloc(sizeof(struct queue_entry)); + e = pa_xnew(struct queue_entry, 1); e->data = p; e->next = NULL; @@ -82,7 +82,7 @@ void pa_queue_push(struct pa_queue *q, void *p) { q->length++; } -void* pa_queue_pop(struct pa_queue *q) { +void* pa_queue_pop(pa_queue *q) { void *p; struct queue_entry *e; assert(q); @@ -102,7 +102,7 @@ void* pa_queue_pop(struct pa_queue *q) { return p; } -int pa_queue_is_empty(struct pa_queue *q) { +int pa_queue_is_empty(pa_queue *q) { assert(q); return q->length == 0; } diff --git a/polyp/queue.h b/polyp/queue.h index a739ab74c..3edcfb635 100644 --- a/polyp/queue.h +++ b/polyp/queue.h @@ -22,19 +22,19 @@ USA. ***/ -struct pa_queue; +typedef struct pa_queue pa_queue; /* A simple implementation of the abstract data type queue. Stores * pointers as members. The memory has to be managed by the caller. */ -struct pa_queue* pa_queue_new(void); +pa_queue* pa_queue_new(void); /* Free the queue and run the specified callback function for every remaining entry. The callback function may be NULL. */ -void pa_queue_free(struct pa_queue* q, void (*destroy)(void *p, void *userdata), void *userdata); +void pa_queue_free(pa_queue* q, void (*destroy)(void *p, void *userdata), void *userdata); -void pa_queue_push(struct pa_queue *q, void *p); -void* pa_queue_pop(struct pa_queue *q); +void pa_queue_push(pa_queue *q, void *p); +void* pa_queue_pop(pa_queue *q); -int pa_queue_is_empty(struct pa_queue *q); +int pa_queue_is_empty(pa_queue *q); #endif diff --git a/polyp/resampler.c b/polyp/resampler.c index 28e49209d..96a1678f4 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -34,16 +34,16 @@ #include "log.h" struct pa_resampler { - struct pa_sample_spec i_ss, o_ss; + pa_sample_spec i_ss, o_ss; size_t i_fz, o_fz; - struct pa_memblock_stat *memblock_stat; + pa_memblock_stat *memblock_stat; void *impl_data; int channels; - enum pa_resample_method resample_method; + pa_resample_method resample_method; - void (*impl_free)(struct pa_resampler *r); - void (*impl_set_input_rate)(struct pa_resampler *r, uint32_t rate); - void (*impl_run)(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out); + void (*impl_free)(pa_resampler *r); + void (*impl_set_input_rate)(pa_resampler *r, uint32_t rate); + void (*impl_run)(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out); }; struct impl_libsamplerate { @@ -59,17 +59,17 @@ struct impl_trivial { unsigned i_counter; }; -static int libsamplerate_init(struct pa_resampler*r); -static int trivial_init(struct pa_resampler*r); +static int libsamplerate_init(pa_resampler*r); +static int trivial_init(pa_resampler*r); -struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, enum pa_resample_method resample_method) { - struct pa_resampler *r = NULL; +pa_resampler* pa_resampler_new(const pa_sample_spec *a, const pa_sample_spec *b, pa_memblock_stat *s, pa_resample_method resample_method) { + pa_resampler *r = NULL; assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b) && resample_method != PA_RESAMPLER_INVALID); if (a->channels != b->channels && a->channels != 1 && b->channels != 1) goto fail; - r = pa_xmalloc(sizeof(struct pa_resampler)); + r = pa_xmalloc(sizeof(pa_resampler)); r->impl_data = NULL; r->memblock_stat = s; r->resample_method = resample_method; @@ -113,7 +113,7 @@ fail: return NULL; } -void pa_resampler_free(struct pa_resampler *r) { +void pa_resampler_free(pa_resampler *r) { assert(r); if (r->impl_free) @@ -122,7 +122,7 @@ void pa_resampler_free(struct pa_resampler *r) { pa_xfree(r); } -void pa_resampler_set_input_rate(struct pa_resampler *r, uint32_t rate) { +void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) { assert(r && rate); r->i_ss.rate = rate; @@ -130,24 +130,24 @@ void pa_resampler_set_input_rate(struct pa_resampler *r, uint32_t rate) { r->impl_set_input_rate(r, rate); } -void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out) { +void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { assert(r && in && out && r->impl_run); r->impl_run(r, in, out); } -size_t pa_resampler_request(struct pa_resampler *r, size_t out_length) { +size_t pa_resampler_request(pa_resampler *r, size_t out_length) { assert(r && (out_length % r->o_fz) == 0); return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz; } -enum pa_resample_method pa_resampler_get_method(struct pa_resampler *r) { +pa_resample_method pa_resampler_get_method(pa_resampler *r) { assert(r); return r->resample_method; } /* Parse a libsamplrate compatible resampling implementation */ -enum pa_resample_method pa_parse_resample_method(const char *string) { +pa_resample_method pa_parse_resample_method(const char *string) { assert(string); if (!strcmp(string, "src-sinc-best-quality")) @@ -168,7 +168,7 @@ enum pa_resample_method pa_parse_resample_method(const char *string) { /*** libsamplerate based implementation ***/ -static void libsamplerate_free(struct pa_resampler *r) { +static void libsamplerate_free(pa_resampler *r) { struct impl_libsamplerate *i; assert(r && r->impl_data); i = r->impl_data; @@ -181,7 +181,7 @@ static void libsamplerate_free(struct pa_resampler *r) { pa_xfree(i); } -static void libsamplerate_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out) { +static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { unsigned i_nchannels, o_nchannels, ins, ons, eff_ins, eff_ons; float *cbuf; struct impl_libsamplerate *i; @@ -267,7 +267,7 @@ static void libsamplerate_run(struct pa_resampler *r, const struct pa_memchunk * } } -static void libsamplerate_set_input_rate(struct pa_resampler *r, uint32_t rate) { +static void libsamplerate_set_input_rate(pa_resampler *r, uint32_t rate) { int ret; struct impl_libsamplerate *i; assert(r && rate > 0 && r->impl_data); @@ -277,7 +277,7 @@ static void libsamplerate_set_input_rate(struct pa_resampler *r, uint32_t rate) assert(ret == 0); } -static int libsamplerate_init(struct pa_resampler *r) { +static int libsamplerate_init(pa_resampler *r) { struct impl_libsamplerate *i = NULL; int err; @@ -308,7 +308,7 @@ fail: /* Trivial implementation */ -static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out) { +static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { size_t fz; unsigned nframes; struct impl_trivial *i; @@ -367,12 +367,12 @@ static void trivial_run(struct pa_resampler *r, const struct pa_memchunk *in, st } } -static void trivial_free(struct pa_resampler *r) { +static void trivial_free(pa_resampler *r) { assert(r); pa_xfree(r->impl_data); } -static void trivial_set_input_rate(struct pa_resampler *r, uint32_t rate) { +static void trivial_set_input_rate(pa_resampler *r, uint32_t rate) { struct impl_trivial *i; assert(r && rate > 0 && r->impl_data); i = r->impl_data; @@ -381,7 +381,7 @@ static void trivial_set_input_rate(struct pa_resampler *r, uint32_t rate) { i->o_counter = 0; } -static int trivial_init(struct pa_resampler*r) { +static int trivial_init(pa_resampler*r) { struct impl_trivial *i; assert(r && r->i_ss.format == r->o_ss.format && r->i_ss.channels == r->o_ss.channels); @@ -395,7 +395,7 @@ static int trivial_init(struct pa_resampler*r) { return 0; } -const char *pa_resample_method_to_string(enum pa_resample_method m) { +const char *pa_resample_method_to_string(pa_resample_method m) { static const char * const resample_methods[] = { "src-sinc-best-quality", "src-sinc-medium-quality", diff --git a/polyp/resampler.h b/polyp/resampler.h index 0109e7908..358c872a3 100644 --- a/polyp/resampler.h +++ b/polyp/resampler.h @@ -28,9 +28,9 @@ #include "memblock.h" #include "memchunk.h" -struct pa_resampler; +typedef struct pa_resampler pa_resampler; -enum pa_resample_method { +typedef enum pa_resample_method { PA_RESAMPLER_INVALID = -1, PA_RESAMPLER_SRC_SINC_BEST_QUALITY = SRC_SINC_BEST_QUALITY, PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY = SRC_SINC_MEDIUM_QUALITY, @@ -39,27 +39,27 @@ enum pa_resample_method { PA_RESAMPLER_SRC_LINEAR = SRC_LINEAR, PA_RESAMPLER_TRIVIAL, PA_RESAMPLER_MAX -}; +} pa_resample_method; -struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, int resample_method); -void pa_resampler_free(struct pa_resampler *r); +pa_resampler* pa_resampler_new(const pa_sample_spec *a, const pa_sample_spec *b, pa_memblock_stat *s, int resample_method); +void pa_resampler_free(pa_resampler *r); /* Returns the size of an input memory block which is required to return the specified amount of output data */ -size_t pa_resampler_request(struct pa_resampler *r, size_t out_length); +size_t pa_resampler_request(pa_resampler *r, size_t out_length); /* Pass the specified memory chunk to the resampler and return the newly resampled data */ -void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out); +void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out); /* Change the input rate of the resampler object */ -void pa_resampler_set_input_rate(struct pa_resampler *r, uint32_t rate); +void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate); /* Return the resampling method of the resampler object */ -enum pa_resample_method pa_resampler_get_method(struct pa_resampler *r); +pa_resample_method pa_resampler_get_method(pa_resampler *r); /* Try to parse the resampler method */ -enum pa_resample_method pa_parse_resample_method(const char *string); +pa_resample_method pa_parse_resample_method(const char *string); /* return a human readable string for the specified resampling method. Inverse of pa_parse_resample_method() */ -const char *pa_resample_method_to_string(enum pa_resample_method m); +const char *pa_resample_method_to_string(pa_resample_method m); #endif diff --git a/polyp/sample-util.c b/polyp/sample-util.c index bf8be34e2..cb5dd1c38 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -30,18 +30,18 @@ #include "sample-util.h" -struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_sample_spec *spec) { +pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { assert(b && b->data && spec); pa_silence_memory(b->data, b->length, spec); return b; } -void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spec) { +void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) { assert(c && c->memblock && c->memblock->data && spec && c->length); pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec); } -void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec) { +void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { uint8_t c = 0; assert(p && length && spec); @@ -65,7 +65,7 @@ void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec memset(p, c, length); } -size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, pa_volume_t volume) { +size_t pa_mix(pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const pa_sample_spec *spec, pa_volume_t volume) { assert(channels && data && length && spec); if (spec->format == PA_SAMPLE_S16NE) { @@ -161,7 +161,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz size_t d; for (d = 0;; d += sizeof(float)) { - pa_volume_t sum = 0; + float sum = 0; unsigned c; if (d >= length) @@ -203,7 +203,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz } -void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, pa_volume_t volume) { +void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, pa_volume_t volume) { assert(c && spec && (c->length % pa_frame_size(spec) == 0)); if (volume == PA_VOLUME_NORM) diff --git a/polyp/sample-util.h b/polyp/sample-util.h index aafdda630..eaebe91d9 100644 --- a/polyp/sample-util.h +++ b/polyp/sample-util.h @@ -27,18 +27,18 @@ #include "memchunk.h" -struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_sample_spec *spec); -void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spec); -void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec); +pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec); +void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec); +void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec); -struct pa_mix_info { - struct pa_memchunk chunk; +typedef struct pa_mix_info { + pa_memchunk chunk; pa_volume_t volume; void *userdata; -}; +} pa_mix_info ; -size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, pa_volume_t volume); +size_t pa_mix(pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const pa_sample_spec *spec, pa_volume_t volume); -void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, pa_volume_t volume); +void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, pa_volume_t volume); #endif diff --git a/polyp/sample.c b/polyp/sample.c index f9d0c4588..37ab96a0a 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -30,7 +30,7 @@ #include "sample.h" -size_t pa_frame_size(const struct pa_sample_spec *spec) { +size_t pa_frame_size(const pa_sample_spec *spec) { size_t b = 1; assert(spec); @@ -55,18 +55,18 @@ size_t pa_frame_size(const struct pa_sample_spec *spec) { return b * spec->channels; } -size_t pa_bytes_per_second(const struct pa_sample_spec *spec) { +size_t pa_bytes_per_second(const pa_sample_spec *spec) { assert(spec); return spec->rate*pa_frame_size(spec); } -pa_usec_t pa_bytes_to_usec(uint64_t length, const struct pa_sample_spec *spec) { +pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) { assert(spec); return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate); } -int pa_sample_spec_valid(const struct pa_sample_spec *spec) { +int pa_sample_spec_valid(const pa_sample_spec *spec) { assert(spec); if (spec->rate <= 0 || spec->channels <= 0) @@ -78,13 +78,13 @@ int pa_sample_spec_valid(const struct pa_sample_spec *spec) { return 1; } -int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b) { +int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) { assert(a && b); return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels); } -const char *pa_sample_format_to_string(enum pa_sample_format f) { +const char *pa_sample_format_to_string(pa_sample_format f) { static const char* const table[]= { [PA_SAMPLE_U8] = "U8", [PA_SAMPLE_ALAW] = "ALAW", @@ -101,7 +101,7 @@ const char *pa_sample_format_to_string(enum pa_sample_format f) { return table[f]; } -char *pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec) { +char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) { assert(s && l && spec); if (!pa_sample_spec_valid(spec)) @@ -161,7 +161,7 @@ void pa_bytes_snprint(char *s, size_t l, unsigned v) { snprintf(s, l, "%u B", (unsigned) v); } -enum pa_sample_format pa_parse_sample_format(const char *format) { +pa_sample_format pa_parse_sample_format(const char *format) { if (strcasecmp(format, "s16le") == 0) return PA_SAMPLE_S16LE; diff --git a/polyp/sample.h b/polyp/sample.h index 82c146152..739cb337b 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -34,7 +34,7 @@ PA_C_DECL_BEGIN /** Sample format */ -enum pa_sample_format { +typedef enum pa_sample_format { PA_SAMPLE_U8, /**< Unsigned 8 Bit PCM */ PA_SAMPLE_ALAW, /**< 8 Bit a-Law */ PA_SAMPLE_ULAW, /**< 8 Bit mu-Law */ @@ -44,7 +44,7 @@ enum pa_sample_format { PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1..1 */ PA_SAMPLE_MAX, /**< Upper limit of valid sample types */ PA_SAMPLE_INVALID = -1 /**< An invalid value */ -}; +} pa_sample_format; #ifdef WORDS_BIGENDIAN /** Signed 16 Bit PCM, native endian */ @@ -70,38 +70,38 @@ enum pa_sample_format { #define PA_SAMPLE_FLOAT32 PA_SAMPLE_FLOAT32NE /** A sample format and attribute specification */ -struct pa_sample_spec { - enum pa_sample_format format; /**< The sample format */ +typedef struct pa_sample_spec { + pa_sample_format format; /**< The sample format */ uint32_t rate; /**< The sample rate. (e.g. 44100) */ uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */ -}; +} pa_sample_spec; /** Type for usec specifications (unsigned). May be either 32 or 64 bit, depending on the architecture */ typedef uint64_t pa_usec_t; /** Return the amount of bytes playback of a second of audio with the specified sample type takes */ -size_t pa_bytes_per_second(const struct pa_sample_spec *spec); +size_t pa_bytes_per_second(const pa_sample_spec *spec); /** Return the size of a frame with the specific sample type */ -size_t pa_frame_size(const struct pa_sample_spec *spec); +size_t pa_frame_size(const pa_sample_spec *spec); /** Calculate the time the specified bytes take to play with the specified sample type */ -pa_usec_t pa_bytes_to_usec(uint64_t length, const struct pa_sample_spec *spec); +pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec); /** Return non-zero when the sample type specification is valid */ -int pa_sample_spec_valid(const struct pa_sample_spec *spec); +int pa_sample_spec_valid(const pa_sample_spec *spec); /** Return non-zero when the two sample type specifications match */ -int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b); +int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b); /* Return a descriptive string for the specified sample format. \since 0.8 */ -const char *pa_sample_format_to_string(enum pa_sample_format f); +const char *pa_sample_format_to_string(pa_sample_format f); /** Maximum required string length for pa_sample_spec_snprint() */ #define PA_SAMPLE_SPEC_SNPRINT_MAX 32 /** Pretty print a sample type specification to a string */ -char* pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec); +char* pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec); /** Volume specification: 0: silence; < 256: diminished volume; 256: normal volume; > 256 amplified volume */ typedef uint32_t pa_volume_t; @@ -138,7 +138,7 @@ pa_volume_t pa_volume_from_user(double v); void pa_bytes_snprint(char *s, size_t l, unsigned v); /** Parse a sample format text. Inverse of pa_sample_format_to_string() */ -enum pa_sample_format pa_parse_sample_format(const char *format); +pa_sample_format pa_parse_sample_format(const char *format); PA_C_DECL_END diff --git a/polyp/scache.c b/polyp/scache.c index 2953145d9..32c89a998 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -55,8 +55,8 @@ #define UNLOAD_POLL_TIME 2 -static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, const struct timeval *tv, void *userdata) { - struct pa_core *c = userdata; +static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { + pa_core *c = userdata; struct timeval ntv; assert(c && c->mainloop == m && c->scache_auto_unload_event == e); @@ -67,7 +67,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e, m->time_restart(e, &ntv); } -static void free_entry(struct pa_scache_entry *e) { +static void free_entry(pa_scache_entry *e) { assert(e); pa_namereg_unregister(e->core, e->name); pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_REMOVE, e->index); @@ -78,8 +78,8 @@ static void free_entry(struct pa_scache_entry *e) { pa_xfree(e); } -static struct pa_scache_entry* scache_add_item(struct pa_core *c, const char *name) { - struct pa_scache_entry *e; +static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { + pa_scache_entry *e; assert(c && name); if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) { @@ -92,7 +92,7 @@ static struct pa_scache_entry* scache_add_item(struct pa_core *c, const char *na pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); } else { - e = pa_xmalloc(sizeof(struct pa_scache_entry)); + e = pa_xmalloc(sizeof(pa_scache_entry)); if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, 1)) { pa_xfree(e); @@ -120,13 +120,13 @@ static struct pa_scache_entry* scache_add_item(struct pa_core *c, const char *na e->lazy = 0; e->last_used_time = 0; - memset(&e->sample_spec, 0, sizeof(struct pa_sample_spec)); + memset(&e->sample_spec, 0, sizeof(pa_sample_spec)); return e; } -int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index) { - struct pa_scache_entry *e; +int pa_scache_add_item(pa_core *c, const char *name, pa_sample_spec *ss, pa_memchunk *chunk, uint32_t *idx) { + pa_scache_entry *e; assert(c && name); if (!(e = scache_add_item(c, name))) @@ -140,15 +140,15 @@ int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spe pa_memblock_ref(e->memchunk.memblock); } - if (index) - *index = e->index; + if (idx) + *idx = e->index; return 0; } -int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename, uint32_t *index) { - struct pa_sample_spec ss; - struct pa_memchunk chunk; +int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint32_t *idx) { + pa_sample_spec ss; + pa_memchunk chunk; int r; #ifdef OS_IS_WIN32 @@ -161,14 +161,14 @@ int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0) return -1; - r = pa_scache_add_item(c, name, &ss, &chunk, index); + r = pa_scache_add_item(c, name, &ss, &chunk, idx); pa_memblock_unref(chunk.memblock); return r; } -int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index) { - struct pa_scache_entry *e; +int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, uint32_t *idx) { + pa_scache_entry *e; #ifdef OS_IS_WIN32 char buf[MAX_PATH]; @@ -192,11 +192,14 @@ int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *fil c->scache_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } + if (idx) + *idx = e->index; + return 0; } -int pa_scache_remove_item(struct pa_core *c, const char *name) { - struct pa_scache_entry *e; +int pa_scache_remove_item(pa_core *c, const char *name) { + pa_scache_entry *e; assert(c && name); if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) @@ -209,13 +212,13 @@ int pa_scache_remove_item(struct pa_core *c, const char *name) { return 0; } -static void free_cb(void *p, void *userdata) { - struct pa_scache_entry *e = p; +static void free_cb(void *p, PA_GCC_UNUSED void *userdata) { + pa_scache_entry *e = p; assert(e); free_entry(e); } -void pa_scache_free(struct pa_core *c) { +void pa_scache_free(pa_core *c) { assert(c); if (c->scache) { @@ -227,8 +230,8 @@ void pa_scache_free(struct pa_core *c) { c->mainloop->time_free(c->scache_auto_unload_event); } -int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume) { - struct pa_scache_entry *e; +int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t volume) { + pa_scache_entry *e; char *t; assert(c && name && sink); @@ -259,8 +262,8 @@ int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sin return 0; } -const char * pa_scache_get_name_by_id(struct pa_core *c, uint32_t id) { - struct pa_scache_entry *e; +const char * pa_scache_get_name_by_id(pa_core *c, uint32_t id) { + pa_scache_entry *e; assert(c && id != PA_IDXSET_INVALID); if (!c->scache || !(e = pa_idxset_get_by_index(c->scache, id))) @@ -269,8 +272,8 @@ const char * pa_scache_get_name_by_id(struct pa_core *c, uint32_t id) { return e->name; } -uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { - struct pa_scache_entry *e; +uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) { + pa_scache_entry *e; assert(c && name); if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) @@ -279,33 +282,33 @@ uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) { return e->index; } -uint32_t pa_scache_total_size(struct pa_core *c) { - struct pa_scache_entry *e; - uint32_t index, sum = 0; +uint32_t pa_scache_total_size(pa_core *c) { + pa_scache_entry *e; + uint32_t idx, sum = 0; assert(c); - if (!c->scache || !pa_idxset_ncontents(c->scache)) + if (!c->scache || !pa_idxset_size(c->scache)) return 0; - for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) + for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) if (e->memchunk.memblock) sum += e->memchunk.length; return sum; } -void pa_scache_unload_unused(struct pa_core *c) { - struct pa_scache_entry *e; +void pa_scache_unload_unused(pa_core *c) { + pa_scache_entry *e; time_t now; - uint32_t index; + uint32_t idx; assert(c); - if (!c->scache || !pa_idxset_ncontents(c->scache)) + if (!c->scache || !pa_idxset_size(c->scache)) return; time(&now); - for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) { + for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) { if (!e->lazy || !e->memchunk.memblock) continue; @@ -321,7 +324,7 @@ void pa_scache_unload_unused(struct pa_core *c) { } } -static void add_file(struct pa_core *c, const char *pathname) { +static void add_file(pa_core *c, const char *pathname) { struct stat st; const char *e; @@ -338,7 +341,7 @@ static void add_file(struct pa_core *c, const char *pathname) { pa_scache_add_file_lazy(c, e, pathname, NULL); } -int pa_scache_add_directory_lazy(struct pa_core *c, const char *pathname) { +int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) { DIR *dir; assert(c && pathname); diff --git a/polyp/scache.h b/polyp/scache.h index f7043f163..c23e33de1 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -26,36 +26,36 @@ #include "memchunk.h" #include "sink.h" -struct pa_scache_entry { - struct pa_core *core; +typedef struct pa_scache_entry { + pa_core *core; uint32_t index; char *name; uint32_t volume; - struct pa_sample_spec sample_spec; - struct pa_memchunk memchunk; + pa_sample_spec sample_spec; + pa_memchunk memchunk; char *filename; int lazy; time_t last_used_time; -}; +} pa_scache_entry; -int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index); -int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename, uint32_t *index); -int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index); +int pa_scache_add_item(pa_core *c, const char *name, pa_sample_spec *ss, pa_memchunk *chunk, uint32_t *idx); +int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint32_t *idx); +int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, uint32_t *idx); -int pa_scache_add_directory_lazy(struct pa_core *c, const char *pathname); +int pa_scache_add_directory_lazy(pa_core *c, const char *pathname); -int pa_scache_remove_item(struct pa_core *c, const char *name); -int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume); -void pa_scache_free(struct pa_core *c); +int pa_scache_remove_item(pa_core *c, const char *name); +int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t volume); +void pa_scache_free(pa_core *c); -const char *pa_scache_get_name_by_id(struct pa_core *c, uint32_t id); -uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name); +const char *pa_scache_get_name_by_id(pa_core *c, uint32_t id); +uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name); -uint32_t pa_scache_total_size(struct pa_core *c); +uint32_t pa_scache_total_size(pa_core *c); -void pa_scache_unload_unused(struct pa_core *c); +void pa_scache_unload_unused(pa_core *c); #endif diff --git a/polyp/sconv-s16be.c b/polyp/sconv-s16be.c index 54efc78cb..3880b0431 100644 --- a/polyp/sconv-s16be.c +++ b/polyp/sconv-s16be.c @@ -23,12 +23,11 @@ #include #endif -#include "sconv-s16be.h" - #define INT16_FROM INT16_FROM_BE #define INT16_TO INT16_TO_BE #define pa_sconv_s16le_to_float32ne pa_sconv_s16be_to_float32ne #define pa_sconv_s16le_from_float32ne pa_sconv_s16be_from_float32ne +#include "sconv-s16le.h" #include "sconv-s16le.c" diff --git a/polyp/sconv-s16le.c b/polyp/sconv-s16le.c index 49c474617..c9682fff1 100644 --- a/polyp/sconv-s16le.c +++ b/polyp/sconv-s16le.c @@ -28,6 +28,7 @@ #include "endianmacros.h" #include "sconv.h" +#include "sconv-s16le.h" #include "log.h" #ifndef INT16_FROM diff --git a/polyp/sconv.c b/polyp/sconv.c index a404f4320..223df5d9b 100644 --- a/polyp/sconv.c +++ b/polyp/sconv.c @@ -115,7 +115,7 @@ static void ulaw_to_float32ne(unsigned n, const void *a, unsigned an, float *b) float sum = 0; for (i = 0; i < an; i++) - sum += (float) st_ulaw2linear16(*ca++) / 0x7FFF; + sum += st_ulaw2linear16(*ca++) * 1.0F / 0x7FFF; if (sum > 1) sum = 1; @@ -156,7 +156,7 @@ static void alaw_to_float32ne(unsigned n, const void *a, unsigned an, float *b) float sum = 0; for (i = 0; i < an; i++) - sum += (float) st_alaw2linear16(*ca++) / 0x7FFF; + sum += st_alaw2linear16(*ca++) * 1.0F / 0x7FFF; if (sum > 1) sum = 1; @@ -190,7 +190,7 @@ static void alaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn } -pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(enum pa_sample_format f) { +pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format f) { switch(f) { case PA_SAMPLE_U8: return u8_to_float32ne; @@ -209,7 +209,7 @@ pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(enum pa_samp } } -pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(enum pa_sample_format f) { +pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format f) { switch(f) { case PA_SAMPLE_U8: return u8_from_float32ne; diff --git a/polyp/sconv.h b/polyp/sconv.h index 71517ec26..2866fd419 100644 --- a/polyp/sconv.h +++ b/polyp/sconv.h @@ -27,7 +27,7 @@ typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, unsigned an, float *b); typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b, unsigned bn); -pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(enum pa_sample_format f); -pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(enum pa_sample_format f); +pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format f); +pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format f); #endif diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 3e7fdf7bf..682b3222d 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -36,14 +36,14 @@ #define CONVERT_BUFFER_LENGTH 4096 -struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method) { - struct pa_sink_input *i; - struct pa_resampler *resampler = NULL; +pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int variable_rate, int resample_method) { + pa_sink_input *i; + pa_resampler *resampler = NULL; int r; char st[256]; assert(s && spec && s->state == PA_SINK_RUNNING); - if (pa_idxset_ncontents(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { + if (pa_idxset_size(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { pa_log(__FILE__": Failed to create sink input: too many inputs per sink.\n"); return NULL; } @@ -55,7 +55,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, c if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat, resample_method))) return NULL; - i = pa_xmalloc(sizeof(struct pa_sink_input)); + i = pa_xmalloc(sizeof(pa_sink_input)); i->ref = 1; i->state = PA_SINK_INPUT_RUNNING; i->name = pa_xstrdup(name); @@ -93,7 +93,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, c return i; } -void pa_sink_input_disconnect(struct pa_sink_input *i) { +void pa_sink_input_disconnect(pa_sink_input *i) { assert(i && i->state != PA_SINK_INPUT_DISCONNECTED && i->sink && i->sink->core); pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL); @@ -110,7 +110,7 @@ void pa_sink_input_disconnect(struct pa_sink_input *i) { i->state = PA_SINK_INPUT_DISCONNECTED; } -static void sink_input_free(struct pa_sink_input* i) { +static void sink_input_free(pa_sink_input* i) { assert(i); if (i->state != PA_SINK_INPUT_DISCONNECTED) @@ -127,27 +127,27 @@ static void sink_input_free(struct pa_sink_input* i) { pa_xfree(i); } -void pa_sink_input_unref(struct pa_sink_input *i) { +void pa_sink_input_unref(pa_sink_input *i) { assert(i && i->ref >= 1); if (!(--i->ref)) sink_input_free(i); } -struct pa_sink_input* pa_sink_input_ref(struct pa_sink_input *i) { +pa_sink_input* pa_sink_input_ref(pa_sink_input *i) { assert(i && i->ref >= 1); i->ref++; return i; } -void pa_sink_input_kill(struct pa_sink_input*i) { +void pa_sink_input_kill(pa_sink_input*i) { assert(i && i->ref >= 1); if (i->kill) i->kill(i); } -pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i) { +pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) { pa_usec_t r = 0; assert(i && i->ref >= 1); @@ -160,7 +160,7 @@ pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i) { return r; } -int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { +int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { int ret = -1; assert(i && chunk && i->ref >= 1); @@ -175,7 +175,7 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { } while (!i->resampled_chunk.memblock) { - struct pa_memchunk tchunk; + pa_memchunk tchunk; size_t l; if ((ret = i->peek(i, &tchunk)) < 0) @@ -213,7 +213,7 @@ finish: return ret; } -void pa_sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) { +void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { assert(i && length && i->ref >= 1); if (!i->resampler) { @@ -234,7 +234,7 @@ void pa_sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk } } -void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume) { +void pa_sink_input_set_volume(pa_sink_input *i, pa_volume_t volume) { assert(i && i->sink && i->sink->core && i->ref >= 1); if (i->volume != volume) { @@ -243,7 +243,7 @@ void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume) { } } -void pa_sink_input_cork(struct pa_sink_input *i, int b) { +void pa_sink_input_cork(pa_sink_input *i, int b) { int n; assert(i && i->ref >= 1); @@ -257,7 +257,7 @@ void pa_sink_input_cork(struct pa_sink_input *i, int b) { pa_sink_notify(i->sink); } -void pa_sink_input_set_rate(struct pa_sink_input *i, uint32_t rate) { +void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) { assert(i && i->resampler && i->ref >= 1); if (i->sample_spec.rate == rate) @@ -267,7 +267,7 @@ void pa_sink_input_set_rate(struct pa_sink_input *i, uint32_t rate) { pa_resampler_set_input_rate(i->resampler, rate); } -void pa_sink_input_set_name(struct pa_sink_input *i, const char *name) { +void pa_sink_input_set_name(pa_sink_input *i, const char *name) { assert(i && i->ref >= 1); pa_xfree(i->name); @@ -276,7 +276,7 @@ void pa_sink_input_set_name(struct pa_sink_input *i, const char *name) { pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); } -enum pa_resample_method pa_sink_input_get_resample_method(struct pa_sink_input *i) { +pa_resample_method pa_sink_input_get_resample_method(pa_sink_input *i) { assert(i && i->ref >= 1); if (!i->resampler) diff --git a/polyp/sink-input.h b/polyp/sink-input.h index 83abe537d..b4c3ec7f8 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -24,6 +24,8 @@ #include +typedef struct pa_sink_input pa_sink_input; + #include "sink.h" #include "sample.h" #include "memblockq.h" @@ -31,63 +33,63 @@ #include "module.h" #include "client.h" -enum pa_sink_input_state { +typedef enum { PA_SINK_INPUT_RUNNING, PA_SINK_INPUT_CORKED, PA_SINK_INPUT_DISCONNECTED -}; +} pa_sink_input_state ; struct pa_sink_input { int ref; - enum pa_sink_input_state state; + pa_sink_input_state state; uint32_t index; pa_typeid_t typeid; char *name; - struct pa_module *owner; - struct pa_client *client; - struct pa_sink *sink; - struct pa_sample_spec sample_spec; + pa_module *owner; + pa_client *client; + pa_sink *sink; + pa_sample_spec sample_spec; uint32_t volume; - int (*peek) (struct pa_sink_input *i, struct pa_memchunk *chunk); - void (*drop) (struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); - void (*kill) (struct pa_sink_input *i); - pa_usec_t (*get_latency) (struct pa_sink_input *i); - void (*underrun) (struct pa_sink_input *i); + int (*peek) (pa_sink_input *i, pa_memchunk *chunk); + void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length); + void (*kill) (pa_sink_input *i); + pa_usec_t (*get_latency) (pa_sink_input *i); + void (*underrun) (pa_sink_input *i); void *userdata; int playing; - struct pa_memchunk resampled_chunk; - struct pa_resampler *resampler; + pa_memchunk resampled_chunk; + pa_resampler *resampler; }; -struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method); -void pa_sink_input_unref(struct pa_sink_input* i); -struct pa_sink_input* pa_sink_input_ref(struct pa_sink_input* i); +pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int variable_rate, int resample_method); +void pa_sink_input_unref(pa_sink_input* i); +pa_sink_input* pa_sink_input_ref(pa_sink_input* i); /* To be called by the implementing module only */ -void pa_sink_input_disconnect(struct pa_sink_input* i); +void pa_sink_input_disconnect(pa_sink_input* i); /* External code may request disconnection with this funcion */ -void pa_sink_input_kill(struct pa_sink_input*i); +void pa_sink_input_kill(pa_sink_input*i); -pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i); +pa_usec_t pa_sink_input_get_latency(pa_sink_input *i); -int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk); -void pa_sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); +int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk); +void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length); -void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume); +void pa_sink_input_set_volume(pa_sink_input *i, pa_volume_t volume); -void pa_sink_input_cork(struct pa_sink_input *i, int b); +void pa_sink_input_cork(pa_sink_input *i, int b); -void pa_sink_input_set_rate(struct pa_sink_input *i, uint32_t rate); +void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate); -void pa_sink_input_set_name(struct pa_sink_input *i, const char *name); +void pa_sink_input_set_name(pa_sink_input *i, const char *name); -enum pa_resample_method pa_sink_input_get_resample_method(struct pa_sink_input *i); +pa_resample_method pa_sink_input_get_resample_method(pa_sink_input *i); #endif diff --git a/polyp/sink.c b/polyp/sink.c index 481e5cf7a..aac90c047 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -36,17 +36,18 @@ #include "xmalloc.h" #include "subscribe.h" #include "log.h" +#include "polyplib-introspect.h" #define MAX_MIX_CHANNELS 32 -struct pa_sink* pa_sink_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec) { - struct pa_sink *s; +pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec) { + pa_sink *s; char *n = NULL; char st[256]; int r; assert(core && name && *name && spec); - s = pa_xmalloc(sizeof(struct pa_sink)); + s = pa_xmalloc(sizeof(pa_sink)); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) { pa_xfree(s); @@ -89,8 +90,8 @@ struct pa_sink* pa_sink_new(struct pa_core *core, pa_typeid_t typeid, const char return s; } -void pa_sink_disconnect(struct pa_sink* s) { - struct pa_sink_input *i, *j = NULL; +void pa_sink_disconnect(pa_sink* s) { + pa_sink_input *i, *j = NULL; assert(s && s->state == PA_SINK_RUNNING); pa_namereg_unregister(s->core, s->name); @@ -112,7 +113,7 @@ void pa_sink_disconnect(struct pa_sink* s) { s->state = PA_SINK_DISCONNECTED; } -static void sink_free(struct pa_sink *s) { +static void sink_free(pa_sink *s) { assert(s && s->ref == 0); if (s->state != PA_SINK_DISCONNECTED) @@ -130,34 +131,34 @@ static void sink_free(struct pa_sink *s) { pa_xfree(s); } -void pa_sink_unref(struct pa_sink*s) { +void pa_sink_unref(pa_sink*s) { assert(s && s->ref >= 1); if (!(--s->ref)) sink_free(s); } -struct pa_sink* pa_sink_ref(struct pa_sink *s) { +pa_sink* pa_sink_ref(pa_sink *s) { assert(s && s->ref >= 1); s->ref++; return s; } -void pa_sink_notify(struct pa_sink*s) { +void pa_sink_notify(pa_sink*s) { assert(s && s->ref >= 1); if (s->notify) s->notify(s); } -static unsigned fill_mix_info(struct pa_sink *s, struct pa_mix_info *info, unsigned maxinfo) { - uint32_t index = PA_IDXSET_INVALID; - struct pa_sink_input *i; +static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) { + uint32_t idx = PA_IDXSET_INVALID; + pa_sink_input *i; unsigned n = 0; assert(s && s->ref >= 1 && info); - for (i = pa_idxset_first(s->inputs, &index); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &index)) { + for (i = pa_idxset_first(s->inputs, &idx); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &idx)) { pa_sink_input_ref(i); if (pa_sink_input_peek(i, &info->chunk) < 0) { @@ -178,11 +179,11 @@ static unsigned fill_mix_info(struct pa_sink *s, struct pa_mix_info *info, unsig return n; } -static void inputs_drop(struct pa_sink *s, struct pa_mix_info *info, unsigned maxinfo, size_t length) { +static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t length) { assert(s && s->ref >= 1 && info); for (; maxinfo > 0; maxinfo--, info++) { - struct pa_sink_input *i = info->userdata; + pa_sink_input *i = info->userdata; assert(i && info->chunk.memblock); pa_sink_input_drop(i, &info->chunk, length); @@ -193,8 +194,8 @@ static void inputs_drop(struct pa_sink *s, struct pa_mix_info *info, unsigned ma } } -int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) { - struct pa_mix_info info[MAX_MIX_CHANNELS]; +int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { + pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; size_t l; int r = -1; @@ -212,7 +213,7 @@ int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result) if (n == 1) { uint32_t volume = PA_VOLUME_NORM; - struct pa_sink_input *i = info[0].userdata; + pa_sink_input *i = info[0].userdata; assert(i); *result = info[0].chunk; pa_memblock_ref(result->memblock); @@ -252,8 +253,8 @@ finish: return r; } -int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) { - struct pa_mix_info info[MAX_MIX_CHANNELS]; +int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { + pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; size_t l; int r = -1; @@ -268,8 +269,6 @@ int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target) { if (n == 1) { uint32_t volume = PA_VOLUME_NORM; - struct pa_sink_info *i = info[0].userdata; - assert(i); l = target->length; if (l > info[0].chunk.length) @@ -300,8 +299,8 @@ finish: return r; } -void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target) { - struct pa_memchunk chunk; +void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { + pa_memchunk chunk; size_t l, d; assert(s && s->ref >= 1 && target && target->memblock && target->length && target->memblock->data); @@ -331,7 +330,7 @@ void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target) { pa_sink_unref(s); } -void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *result) { +void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { assert(s && s->ref >= 1 && length && result); /*** This needs optimization ***/ @@ -342,7 +341,7 @@ void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *r pa_sink_render_into_full(s, result); } -pa_usec_t pa_sink_get_latency(struct pa_sink *s) { +pa_usec_t pa_sink_get_latency(pa_sink *s) { assert(s && s->ref >= 1); if (!s->get_latency) @@ -351,7 +350,7 @@ pa_usec_t pa_sink_get_latency(struct pa_sink *s) { return s->get_latency(s); } -void pa_sink_set_owner(struct pa_sink *s, struct pa_module *m) { +void pa_sink_set_owner(pa_sink *s, pa_module *m) { assert(s && s->ref >= 1); s->owner = m; @@ -360,7 +359,7 @@ void pa_sink_set_owner(struct pa_sink *s, struct pa_module *m) { pa_source_set_owner(s->monitor_source, m); } -void pa_sink_set_volume(struct pa_sink *s, pa_volume_t volume) { +void pa_sink_set_volume(pa_sink *s, pa_volume_t volume) { assert(s && s->ref >= 1); if (s->volume != volume) { diff --git a/polyp/sink.h b/polyp/sink.h index 844af964b..22d908582 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -22,61 +22,62 @@ USA. ***/ -struct pa_sink; - #include +typedef struct pa_sink pa_sink; + #include "core.h" #include "sample.h" #include "idxset.h" #include "source.h" #include "typeid.h" +#include "module.h" #define PA_MAX_INPUTS_PER_SINK 6 -enum pa_sink_state { +typedef enum pa_sink_state { PA_SINK_RUNNING, PA_SINK_DISCONNECTED -}; +} pa_sink_state; struct pa_sink { int ref; - enum pa_sink_state state; + pa_sink_state state; uint32_t index; pa_typeid_t typeid; char *name, *description; - struct pa_module *owner; - struct pa_core *core; - struct pa_sample_spec sample_spec; - struct pa_idxset *inputs; + pa_module *owner; + pa_core *core; + pa_sample_spec sample_spec; + pa_idxset *inputs; - struct pa_source *monitor_source; + pa_source *monitor_source; pa_volume_t volume; - void (*notify)(struct pa_sink*sink); - pa_usec_t (*get_latency)(struct pa_sink *s); + void (*notify)(pa_sink*sink); + pa_usec_t (*get_latency)(pa_sink *s); void *userdata; }; -struct pa_sink* pa_sink_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec); -void pa_sink_disconnect(struct pa_sink* s); -void pa_sink_unref(struct pa_sink*s); -struct pa_sink* pa_sink_ref(struct pa_sink *s); +pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec); +void pa_sink_disconnect(pa_sink* s); +void pa_sink_unref(pa_sink*s); +pa_sink* pa_sink_ref(pa_sink *s); -int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result); -void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *result); -int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target); -void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target); +int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result); +void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result); +int pa_sink_render_into(pa_sink*s, pa_memchunk *target); +void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target); -pa_usec_t pa_sink_get_latency(struct pa_sink *s); +pa_usec_t pa_sink_get_latency(pa_sink *s); -void pa_sink_notify(struct pa_sink*s); +void pa_sink_notify(pa_sink*s); -void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m); +void pa_sink_set_owner(pa_sink *sink, pa_module *m); -void pa_sink_set_volume(struct pa_sink *sink, pa_volume_t volume); +void pa_sink_set_volume(pa_sink *sink, pa_volume_t volume); #endif diff --git a/polyp/socket-client.c b/polyp/socket-client.c index 51134b84f..a884aa617 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -65,26 +65,26 @@ struct pa_socket_client { int ref; - struct pa_mainloop_api *mainloop; + pa_mainloop_api *mainloop; int fd; - struct pa_io_event *io_event; - struct pa_time_event *timeout_event; - struct pa_defer_event *defer_event; - void (*callback)(struct pa_socket_client*c, struct pa_iochannel *io, void *userdata); + pa_io_event *io_event; + pa_time_event *timeout_event; + pa_defer_event *defer_event; + void (*callback)(pa_socket_client*c, pa_iochannel *io, void *userdata); void *userdata; int local; #ifdef HAVE_LIBASYNCNS asyncns_t *asyncns; asyncns_query_t * asyncns_query; - struct pa_io_event *asyncns_io_event; + pa_io_event *asyncns_io_event; #endif }; -static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { - struct pa_socket_client *c; +static pa_socket_client*pa_socket_client_new(pa_mainloop_api *m) { + pa_socket_client *c; assert(m); - c = pa_xmalloc(sizeof(struct pa_socket_client)); + c = pa_xmalloc(sizeof(pa_socket_client)); c->ref = 1; c->mainloop = m; c->fd = -1; @@ -104,7 +104,7 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) { return c; } -static void free_events(struct pa_socket_client *c) { +static void free_events(pa_socket_client *c) { assert(c); if (c->io_event) { @@ -123,8 +123,8 @@ static void free_events(struct pa_socket_client *c) { } } -static void do_call(struct pa_socket_client *c) { - struct pa_iochannel *io = NULL; +static void do_call(pa_socket_client *c) { + pa_iochannel *io = NULL; int error; socklen_t lerror; assert(c && c->callback); @@ -167,19 +167,19 @@ finish: pa_socket_client_unref(c); } -static void connect_fixed_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { - struct pa_socket_client *c = userdata; +static void connect_fixed_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { + pa_socket_client *c = userdata; assert(m && c && c->defer_event == e); do_call(c); } -static void connect_io_cb(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { - struct pa_socket_client *c = userdata; +static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { + pa_socket_client *c = userdata; assert(m && c && c->io_event == e && fd >= 0); do_call(c); } -static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, socklen_t len) { +static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) { int r; assert(c && sa && len); @@ -201,7 +201,7 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc return 0; } -struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port) { +pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port) { struct sockaddr_in sa; assert(m && port > 0); @@ -215,7 +215,7 @@ struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, ui #ifdef HAVE_SYS_UN_H -struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) { +pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) { struct sockaddr_un sa; assert(m && filename); @@ -229,13 +229,13 @@ struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, co #else /* HAVE_SYS_UN_H */ -struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) { +pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) { return NULL; } #endif /* HAVE_SYS_UN_H */ -static int sockaddr_prepare(struct pa_socket_client *c, const struct sockaddr *sa, size_t salen) { +static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) { assert(c); assert(sa); assert(salen); @@ -274,8 +274,8 @@ static int sockaddr_prepare(struct pa_socket_client *c, const struct sockaddr *s return 0; } -struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) { - struct pa_socket_client *c; +pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) { + pa_socket_client *c; assert(m && sa); c = pa_socket_client_new(m); assert(c); @@ -291,7 +291,7 @@ fail: } -void socket_client_free(struct pa_socket_client *c) { +static void socket_client_free(pa_socket_client *c) { assert(c && c->mainloop); @@ -312,26 +312,26 @@ void socket_client_free(struct pa_socket_client *c) { pa_xfree(c); } -void pa_socket_client_unref(struct pa_socket_client *c) { +void pa_socket_client_unref(pa_socket_client *c) { assert(c && c->ref >= 1); if (!(--(c->ref))) socket_client_free(c); } -struct pa_socket_client* pa_socket_client_ref(struct pa_socket_client *c) { +pa_socket_client* pa_socket_client_ref(pa_socket_client *c) { assert(c && c->ref >= 1); c->ref++; return c; } -void pa_socket_client_set_callback(struct pa_socket_client *c, void (*on_connection)(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata), void *userdata) { +void pa_socket_client_set_callback(pa_socket_client *c, void (*on_connection)(pa_socket_client *c, pa_iochannel*io, void *userdata), void *userdata) { assert(c); c->callback = on_connection; c->userdata = userdata; } -struct pa_socket_client* pa_socket_client_new_ipv6(struct pa_mainloop_api *m, uint8_t address[16], uint16_t port) { +pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) { struct sockaddr_in6 sa; memset(&sa, 0, sizeof(sa)); @@ -344,8 +344,8 @@ struct pa_socket_client* pa_socket_client_new_ipv6(struct pa_mainloop_api *m, ui #ifdef HAVE_LIBASYNCNS -static void asyncns_cb(struct pa_mainloop_api*m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { - struct pa_socket_client *c = userdata; +static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { + pa_socket_client *c = userdata; struct addrinfo *res = NULL; int ret; assert(m && c && c->asyncns_io_event == e && fd >= 0); @@ -381,8 +381,8 @@ finish: #endif -static void timeout_cb(struct pa_mainloop_api *m, struct pa_time_event *e, const struct timeval *tv, void *userdata) { - struct pa_socket_client *c = userdata; +static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) { + pa_socket_client *c = userdata; assert(m); assert(e); assert(tv); @@ -397,7 +397,7 @@ static void timeout_cb(struct pa_mainloop_api *m, struct pa_time_event *e, const do_call(c); } -static void start_timeout(struct pa_socket_client *c) { +static void start_timeout(pa_socket_client *c) { struct timeval tv; assert(c); assert(!c->timeout_event); @@ -407,9 +407,9 @@ static void start_timeout(struct pa_socket_client *c) { c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c); } -struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, const char*name, uint16_t default_port) { - struct pa_socket_client *c = NULL; - struct pa_parsed_address a; +pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*name, uint16_t default_port) { + pa_socket_client *c = NULL; + pa_parsed_address a; assert(m && name); if (pa_parse_address(name, &a) < 0) @@ -507,7 +507,7 @@ finish: /* Return non-zero when the target sockaddr is considered local. "local" means UNIX socket or TCP socket on localhost. Other local IP addresses are not considered local. */ -int pa_socket_client_is_local(struct pa_socket_client *c) { +int pa_socket_client_is_local(pa_socket_client *c) { assert(c); return c->local; } diff --git a/polyp/socket-client.h b/polyp/socket-client.h index b8c73ed87..40e9629a2 100644 --- a/polyp/socket-client.h +++ b/polyp/socket-client.h @@ -29,19 +29,19 @@ struct sockaddr; -struct pa_socket_client; +typedef struct pa_socket_client pa_socket_client; -struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port); -struct pa_socket_client* pa_socket_client_new_ipv6(struct pa_mainloop_api *m, uint8_t address[16], uint16_t port); -struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename); -struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen); -struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m, const char *a, uint16_t default_port); +pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port); +pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port); +pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename); +pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen); +pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char *a, uint16_t default_port); -void pa_socket_client_unref(struct pa_socket_client *c); -struct pa_socket_client* pa_socket_client_ref(struct pa_socket_client *c); +void pa_socket_client_unref(pa_socket_client *c); +pa_socket_client* pa_socket_client_ref(pa_socket_client *c); -void pa_socket_client_set_callback(struct pa_socket_client *c, void (*on_connection)(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata), void *userdata); +void pa_socket_client_set_callback(pa_socket_client *c, void (*on_connection)(pa_socket_client *c, pa_iochannel*io, void *userdata), void *userdata); -int pa_socket_client_is_local(struct pa_socket_client *c); +int pa_socket_client_is_local(pa_socket_client *c); #endif diff --git a/polyp/socket-server.c b/polyp/socket-server.c index a78f04cdb..6f1794bc9 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -70,17 +70,17 @@ struct pa_socket_server { char *filename; char *tcpwrap_service; - void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata); + void (*on_connection)(pa_socket_server*s, pa_iochannel *io, void *userdata); void *userdata; - struct pa_io_event *io_event; - struct pa_mainloop_api *mainloop; + pa_io_event *io_event; + pa_mainloop_api *mainloop; enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX, SOCKET_SERVER_IPV6 } type; }; -static void callback(struct pa_mainloop_api *mainloop, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { - struct pa_socket_server *s = userdata; - struct pa_iochannel *io; +static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { + pa_socket_server *s = userdata; + pa_iochannel *io; int nfd; assert(s && s->mainloop == mainloop && s->io_event == e && e && fd >= 0 && fd == s->fd); @@ -129,11 +129,11 @@ finish: pa_socket_server_unref(s); } -struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) { - struct pa_socket_server *s; +pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) { + pa_socket_server *s; assert(m && fd >= 0); - s = pa_xmalloc(sizeof(struct pa_socket_server)); + s = pa_xmalloc(sizeof(pa_socket_server)); s->ref = 1; s->fd = fd; s->filename = NULL; @@ -150,7 +150,7 @@ struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd) return s; } -struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *s) { +pa_socket_server* pa_socket_server_ref(pa_socket_server *s) { assert(s && s->ref >= 1); s->ref++; return s; @@ -158,10 +158,10 @@ struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *s) { #ifdef HAVE_SYS_UN_H -struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) { +pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename) { int fd = -1; struct sockaddr_un sa; - struct pa_socket_server *s; + pa_socket_server *s; assert(m && filename); @@ -205,14 +205,14 @@ fail: #else /* HAVE_SYS_UN_H */ -struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) { +pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename) { return NULL; } #endif /* HAVE_SYS_UN_H */ -struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service) { - struct pa_socket_server *ss; +pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service) { + pa_socket_server *ss; int fd = -1; struct sockaddr_in sa; int on = 1; @@ -260,8 +260,8 @@ fail: return NULL; } -struct pa_socket_server* pa_socket_server_new_ipv6(struct pa_mainloop_api *m, uint8_t address[16], uint16_t port) { - struct pa_socket_server *ss; +pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port) { + pa_socket_server *ss; int fd = -1; struct sockaddr_in6 sa; int on = 1; @@ -307,7 +307,7 @@ fail: return NULL; } -static void socket_server_free(struct pa_socket_server*s) { +static void socket_server_free(pa_socket_server*s) { assert(s); close(s->fd); @@ -322,14 +322,14 @@ static void socket_server_free(struct pa_socket_server*s) { pa_xfree(s); } -void pa_socket_server_unref(struct pa_socket_server *s) { +void pa_socket_server_unref(pa_socket_server *s) { assert(s && s->ref >= 1); if (!(--(s->ref))) socket_server_free(s); } -void pa_socket_server_set_callback(struct pa_socket_server*s, void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata), void *userdata) { +void pa_socket_server_set_callback(pa_socket_server*s, void (*on_connection)(pa_socket_server*s, pa_iochannel *io, void *userdata), void *userdata) { assert(s && s->ref >= 1); s->on_connection = on_connection; @@ -337,7 +337,7 @@ void pa_socket_server_set_callback(struct pa_socket_server*s, void (*on_connecti } -char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l) { +char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { assert(s && c && l > 0); switch (s->type) { diff --git a/polyp/socket-server.h b/polyp/socket-server.h index dbd82518d..6c5d7bacc 100644 --- a/polyp/socket-server.h +++ b/polyp/socket-server.h @@ -28,18 +28,18 @@ /* It is safe to destroy the calling socket_server object from the callback */ -struct pa_socket_server; +typedef struct pa_socket_server pa_socket_server; -struct pa_socket_server* pa_socket_server_new(struct pa_mainloop_api *m, int fd); -struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename); -struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service); -struct pa_socket_server* pa_socket_server_new_ipv6(struct pa_mainloop_api *m, uint8_t address[16], uint16_t port); +pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd); +pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename); +pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port); -void pa_socket_server_unref(struct pa_socket_server*s); -struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *s); +void pa_socket_server_unref(pa_socket_server*s); +pa_socket_server* pa_socket_server_ref(pa_socket_server *s); -void pa_socket_server_set_callback(struct pa_socket_server*s, void (*on_connection)(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata), void *userdata); +void pa_socket_server_set_callback(pa_socket_server*s, void (*on_connection)(pa_socket_server*s, pa_iochannel *io, void *userdata), void *userdata); -char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l); +char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l); #endif diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c index 621c3ed95..a277eb254 100644 --- a/polyp/sound-file-stream.c +++ b/polyp/sound-file-stream.c @@ -40,8 +40,8 @@ struct userdata { SNDFILE *sndfile; - struct pa_sink_input *sink_input; - struct pa_memchunk memchunk; + pa_sink_input *sink_input; + pa_memchunk memchunk; sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames); }; @@ -60,16 +60,16 @@ static void free_userdata(struct userdata *u) { pa_xfree(u); } -static void sink_input_kill(struct pa_sink_input *i) { +static void sink_input_kill(pa_sink_input *i) { assert(i && i->userdata); free_userdata(i->userdata); } -static void si_kill(struct pa_mainloop_api *m, void *i) { +static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) { sink_input_kill(i); } -static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { +static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { struct userdata *u; assert(i && chunk && i->userdata); u = i->userdata; @@ -98,7 +98,7 @@ static int sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) { return 0; } -static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk*chunk, size_t length) { +static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) { struct userdata *u; assert(i && chunk && length && i->userdata); u = i->userdata; @@ -116,10 +116,10 @@ static void sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk*ch } } -int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume) { +int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume) { struct userdata *u = NULL; SF_INFO sfinfo; - struct pa_sample_spec ss; + pa_sample_spec ss; assert(sink && fname); if (volume <= 0) diff --git a/polyp/sound-file-stream.h b/polyp/sound-file-stream.h index f5ab8e2c4..0b383f963 100644 --- a/polyp/sound-file-stream.h +++ b/polyp/sound-file-stream.h @@ -24,6 +24,6 @@ #include "sink.h" -int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume); +int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume); #endif diff --git a/polyp/sound-file.c b/polyp/sound-file.c index 326ddd8bf..0048ed74a 100644 --- a/polyp/sound-file.c +++ b/polyp/sound-file.c @@ -34,7 +34,7 @@ #define MAX_FILE_SIZE (1024*1024) -int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk, struct pa_memblock_stat *s) { +int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_memchunk *chunk, pa_memblock_stat *s) { SNDFILE*sf = NULL; SF_INFO sfinfo; int ret = -1; @@ -106,7 +106,7 @@ finish: int pa_sound_file_too_big_to_cache(const char *fname) { SNDFILE*sf = NULL; SF_INFO sfinfo; - struct pa_sample_spec ss; + pa_sample_spec ss; if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { pa_log(__FILE__": Failed to open file %s\n", fname); diff --git a/polyp/sound-file.h b/polyp/sound-file.h index 855e68832..e0534275a 100644 --- a/polyp/sound-file.h +++ b/polyp/sound-file.h @@ -25,7 +25,7 @@ #include "memchunk.h" #include "sample.h" -int pa_sound_file_load(const char *fname, struct pa_sample_spec *ss, struct pa_memchunk *chunk, struct pa_memblock_stat *s); +int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_memchunk *chunk, pa_memblock_stat *s); int pa_sound_file_too_big_to_cache(const char *fname); diff --git a/polyp/source-output.c b/polyp/source-output.c index f954c23fa..7a5406336 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -33,14 +33,14 @@ #include "subscribe.h" #include "log.h" -struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int resample_method) { - struct pa_source_output *o; - struct pa_resampler *resampler = NULL; +pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int resample_method) { + pa_source_output *o; + pa_resampler *resampler = NULL; int r; char st[256]; assert(s && spec); - if (pa_idxset_ncontents(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { + if (pa_idxset_size(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { pa_log(__FILE__": Failed to create source output: too many outputs per source.\n"); return NULL; } @@ -52,7 +52,7 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t t if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat, resample_method))) return NULL; - o = pa_xmalloc(sizeof(struct pa_source_output)); + o = pa_xmalloc(sizeof(pa_source_output)); o->ref = 1; o->state = PA_SOURCE_OUTPUT_RUNNING; o->name = pa_xstrdup(name); @@ -84,7 +84,7 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t t return o; } -void pa_source_output_disconnect(struct pa_source_output*o) { +void pa_source_output_disconnect(pa_source_output*o) { assert(o && o->state != PA_SOURCE_OUTPUT_DISCONNECTED && o->source && o->source->core); pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL); @@ -100,7 +100,7 @@ void pa_source_output_disconnect(struct pa_source_output*o) { o->state = PA_SOURCE_OUTPUT_DISCONNECTED; } -static void source_output_free(struct pa_source_output* o) { +static void source_output_free(pa_source_output* o) { assert(o); if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED) @@ -116,29 +116,29 @@ static void source_output_free(struct pa_source_output* o) { } -void pa_source_output_unref(struct pa_source_output* o) { +void pa_source_output_unref(pa_source_output* o) { assert(o && o->ref >= 1); if (!(--o->ref)) source_output_free(o); } -struct pa_source_output* pa_source_output_ref(struct pa_source_output *o) { +pa_source_output* pa_source_output_ref(pa_source_output *o) { assert(o && o->ref >= 1); o->ref++; return o; } -void pa_source_output_kill(struct pa_source_output*o) { +void pa_source_output_kill(pa_source_output*o) { assert(o && o->ref >= 1); if (o->kill) o->kill(o); } -void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk *chunk) { - struct pa_memchunk rchunk; +void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { + pa_memchunk rchunk; assert(o && chunk && chunk->length && o->push); if (o->state == PA_SOURCE_OUTPUT_CORKED) @@ -158,7 +158,7 @@ void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk pa_memblock_unref(rchunk.memblock); } -void pa_source_output_set_name(struct pa_source_output *o, const char *name) { +void pa_source_output_set_name(pa_source_output *o, const char *name) { assert(o && o->ref >= 1); pa_xfree(o->name); o->name = pa_xstrdup(name); @@ -166,7 +166,7 @@ void pa_source_output_set_name(struct pa_source_output *o, const char *name) { pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); } -pa_usec_t pa_source_output_get_latency(struct pa_source_output *o) { +pa_usec_t pa_source_output_get_latency(pa_source_output *o) { assert(o && o->ref >= 1); if (o->get_latency) @@ -175,7 +175,7 @@ pa_usec_t pa_source_output_get_latency(struct pa_source_output *o) { return 0; } -void pa_source_output_cork(struct pa_source_output *o, int b) { +void pa_source_output_cork(pa_source_output *o, int b) { assert(o && o->ref >= 1); if (o->state == PA_SOURCE_OUTPUT_DISCONNECTED) @@ -184,7 +184,7 @@ void pa_source_output_cork(struct pa_source_output *o, int b) { o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING; } -enum pa_resample_method pa_source_output_get_resample_method(struct pa_source_output *o) { +pa_resample_method pa_source_output_get_resample_method(pa_source_output *o) { assert(o && o->ref >= 1); if (!o->resampler) diff --git a/polyp/source-output.h b/polyp/source-output.h index f3187aa99..ef8f9fa92 100644 --- a/polyp/source-output.h +++ b/polyp/source-output.h @@ -24,6 +24,8 @@ #include +typedef struct pa_source_output pa_source_output; + #include "source.h" #include "sample.h" #include "memblockq.h" @@ -31,52 +33,52 @@ #include "module.h" #include "client.h" -enum pa_source_output_state { +typedef enum { PA_SOURCE_OUTPUT_RUNNING, PA_SOURCE_OUTPUT_CORKED, PA_SOURCE_OUTPUT_DISCONNECTED -}; +} pa_source_output_state; struct pa_source_output { int ref; - enum pa_source_output_state state; + pa_source_output_state state; uint32_t index; pa_typeid_t typeid; char *name; - struct pa_module *owner; - struct pa_client *client; - struct pa_source *source; - struct pa_sample_spec sample_spec; + pa_module *owner; + pa_client *client; + pa_source *source; + pa_sample_spec sample_spec; - void (*push)(struct pa_source_output *o, const struct pa_memchunk *chunk); - void (*kill)(struct pa_source_output* o); - pa_usec_t (*get_latency) (struct pa_source_output *i); + void (*push)(pa_source_output *o, const pa_memchunk *chunk); + void (*kill)(pa_source_output* o); + pa_usec_t (*get_latency) (pa_source_output *i); - struct pa_resampler* resampler; + pa_resampler* resampler; void *userdata; }; -struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int resample_method); -void pa_source_output_unref(struct pa_source_output* o); -struct pa_source_output* pa_source_output_ref(struct pa_source_output *o); +pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int resample_method); +void pa_source_output_unref(pa_source_output* o); +pa_source_output* pa_source_output_ref(pa_source_output *o); /* To be called by the implementing module only */ -void pa_source_output_disconnect(struct pa_source_output*o); +void pa_source_output_disconnect(pa_source_output*o); /* External code may request disconnection with this funcion */ -void pa_source_output_kill(struct pa_source_output*o); +void pa_source_output_kill(pa_source_output*o); -void pa_source_output_push(struct pa_source_output *o, const struct pa_memchunk *chunk); +void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk); -void pa_source_output_set_name(struct pa_source_output *i, const char *name); +void pa_source_output_set_name(pa_source_output *i, const char *name); -pa_usec_t pa_source_output_get_latency(struct pa_source_output *i); +pa_usec_t pa_source_output_get_latency(pa_source_output *i); -void pa_source_output_cork(struct pa_source_output *i, int b); +void pa_source_output_cork(pa_source_output *i, int b); -enum pa_resample_method pa_source_output_get_resample_method(struct pa_source_output *o); +pa_resample_method pa_source_output_get_resample_method(pa_source_output *o); #endif diff --git a/polyp/source.c b/polyp/source.c index fc73272c0..c287899e4 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -35,13 +35,13 @@ #include "subscribe.h" #include "log.h" -struct pa_source* pa_source_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec) { - struct pa_source *s; +pa_source* pa_source_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec) { + pa_source *s; char st[256]; int r; assert(core && spec && name && *name); - s = pa_xmalloc(sizeof(struct pa_source)); + s = pa_xmalloc(sizeof(pa_source)); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) { pa_xfree(s); @@ -76,8 +76,8 @@ struct pa_source* pa_source_new(struct pa_core *core, pa_typeid_t typeid, const return s; } -void pa_source_disconnect(struct pa_source *s) { - struct pa_source_output *o, *j = NULL; +void pa_source_disconnect(pa_source *s) { + pa_source_output *o, *j = NULL; assert(s && s->state == PA_SOURCE_RUNNING); pa_namereg_unregister(s->core, s->name); @@ -96,7 +96,7 @@ void pa_source_disconnect(struct pa_source *s) { s->state = PA_SOURCE_DISCONNECTED; } -static void source_free(struct pa_source *s) { +static void source_free(pa_source *s) { assert(s && !s->ref); if (s->state != PA_SOURCE_DISCONNECTED) @@ -111,36 +111,36 @@ static void source_free(struct pa_source *s) { pa_xfree(s); } -void pa_source_unref(struct pa_source *s) { +void pa_source_unref(pa_source *s) { assert(s && s->ref >= 1); if (!(--s->ref)) source_free(s); } -struct pa_source* pa_source_ref(struct pa_source *s) { +pa_source* pa_source_ref(pa_source *s) { assert(s && s->ref >= 1); s->ref++; return s; } -void pa_source_notify(struct pa_source*s) { +void pa_source_notify(pa_source*s) { assert(s && s->ref >= 1); if (s->notify) s->notify(s); } -static int do_post(void *p, uint32_t index, int *del, void*userdata) { - const struct pa_memchunk *chunk = userdata; - struct pa_source_output *o = p; +static int do_post(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void*userdata) { + const pa_memchunk *chunk = userdata; + pa_source_output *o = p; assert(o && o->push && del && chunk); pa_source_output_push(o, chunk); return 0; } -void pa_source_post(struct pa_source*s, const struct pa_memchunk *chunk) { +void pa_source_post(pa_source*s, const pa_memchunk *chunk) { assert(s && s->ref >= 1 && chunk); pa_source_ref(s); @@ -148,12 +148,12 @@ void pa_source_post(struct pa_source*s, const struct pa_memchunk *chunk) { pa_source_unref(s); } -void pa_source_set_owner(struct pa_source *s, struct pa_module *m) { +void pa_source_set_owner(pa_source *s, pa_module *m) { assert(s); s->owner = m; } -pa_usec_t pa_source_get_latency(struct pa_source *s) { +pa_usec_t pa_source_get_latency(pa_source *s) { assert(s && s->ref >= 1); if (!s->get_latency) diff --git a/polyp/source.h b/polyp/source.h index 0fac2b343..c7f8d059a 100644 --- a/polyp/source.h +++ b/polyp/source.h @@ -22,7 +22,7 @@ USA. ***/ -struct pa_source; +typedef struct pa_source pa_source; #include #include "core.h" @@ -32,45 +32,46 @@ struct pa_source; #include "memchunk.h" #include "sink.h" #include "typeid.h" +#include "module.h" #define PA_MAX_OUTPUTS_PER_SOURCE 16 -enum pa_source_state { +typedef enum pa_source_state { PA_SOURCE_RUNNING, PA_SOURCE_DISCONNECTED -}; +} pa_source_state; struct pa_source { int ref; - enum pa_source_state state; + pa_source_state state; uint32_t index; pa_typeid_t typeid; char *name, *description; - struct pa_module *owner; - struct pa_core *core; - struct pa_sample_spec sample_spec; - struct pa_idxset *outputs; - struct pa_sink *monitor_of; + pa_module *owner; + pa_core *core; + pa_sample_spec sample_spec; + pa_idxset *outputs; + pa_sink *monitor_of; - void (*notify)(struct pa_source*source); - pa_usec_t (*get_latency)(struct pa_source *s); + void (*notify)(pa_source*source); + pa_usec_t (*get_latency)(pa_source *s); void *userdata; }; -struct pa_source* pa_source_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec); -void pa_source_disconnect(struct pa_source *s); -void pa_source_unref(struct pa_source *s); -struct pa_source* pa_source_ref(struct pa_source *c); +pa_source* pa_source_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec); +void pa_source_disconnect(pa_source *s); +void pa_source_unref(pa_source *s); +pa_source* pa_source_ref(pa_source *c); /* Pass a new memory block to all output streams */ -void pa_source_post(struct pa_source*s, const struct pa_memchunk *b); +void pa_source_post(pa_source*s, const pa_memchunk *b); -void pa_source_notify(struct pa_source *s); +void pa_source_notify(pa_source *s); -void pa_source_set_owner(struct pa_source *s, struct pa_module *m); +void pa_source_set_owner(pa_source *s, pa_module *m); -pa_usec_t pa_source_get_latency(struct pa_source *s); +pa_usec_t pa_source_get_latency(pa_source *s); #endif diff --git a/polyp/strbuf.c b/polyp/strbuf.c index 1aa710ea1..aa20218aa 100644 --- a/polyp/strbuf.c +++ b/polyp/strbuf.c @@ -46,14 +46,14 @@ struct pa_strbuf { struct chunk *head, *tail; }; -struct pa_strbuf *pa_strbuf_new(void) { - struct pa_strbuf *sb = pa_xmalloc(sizeof(struct pa_strbuf)); +pa_strbuf *pa_strbuf_new(void) { + pa_strbuf *sb = pa_xmalloc(sizeof(pa_strbuf)); sb->length = 0; sb->head = sb->tail = NULL; return sb; } -void pa_strbuf_free(struct pa_strbuf *sb) { +void pa_strbuf_free(pa_strbuf *sb) { assert(sb); while (sb->head) { struct chunk *c = sb->head; @@ -66,7 +66,7 @@ void pa_strbuf_free(struct pa_strbuf *sb) { /* Make a C string from the string buffer. The caller has to free * string with pa_xfree(). */ -char *pa_strbuf_tostring(struct pa_strbuf *sb) { +char *pa_strbuf_tostring(pa_strbuf *sb) { char *t, *e; struct chunk *c; assert(sb); @@ -88,7 +88,7 @@ char *pa_strbuf_tostring(struct pa_strbuf *sb) { } /* Combination of pa_strbuf_free() and pa_strbuf_tostring() */ -char *pa_strbuf_tostring_free(struct pa_strbuf *sb) { +char *pa_strbuf_tostring_free(pa_strbuf *sb) { char *t; assert(sb); t = pa_strbuf_tostring(sb); @@ -97,13 +97,13 @@ char *pa_strbuf_tostring_free(struct pa_strbuf *sb) { } /* Append a string to the string buffer */ -void pa_strbuf_puts(struct pa_strbuf *sb, const char *t) { +void pa_strbuf_puts(pa_strbuf *sb, const char *t) { assert(sb && t); pa_strbuf_putsn(sb, t, strlen(t)); } /* Append a new chunk to the linked list */ -static void append(struct pa_strbuf *sb, struct chunk *c) { +static void append(pa_strbuf *sb, struct chunk *c) { assert(sb && c); if (sb->tail) { @@ -120,7 +120,7 @@ static void append(struct pa_strbuf *sb, struct chunk *c) { } /* Append up to l bytes of a string to the string buffer */ -void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t l) { +void pa_strbuf_putsn(pa_strbuf *sb, const char *t, size_t l) { struct chunk *c; assert(sb && t); @@ -136,7 +136,7 @@ void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t l) { /* Append a printf() style formatted string to the string buffer. */ /* The following is based on an example from the GNU libc documentation */ -int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) { +int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) { int size = 100; struct chunk *c = NULL; diff --git a/polyp/strbuf.h b/polyp/strbuf.h index 281eee1ec..a88f5190c 100644 --- a/polyp/strbuf.h +++ b/polyp/strbuf.h @@ -22,17 +22,17 @@ USA. ***/ -#include "gcc-printf.h" +#include "gccmacro.h" -struct pa_strbuf; +typedef struct pa_strbuf pa_strbuf; -struct pa_strbuf *pa_strbuf_new(void); -void pa_strbuf_free(struct pa_strbuf *sb); -char *pa_strbuf_tostring(struct pa_strbuf *sb); -char *pa_strbuf_tostring_free(struct pa_strbuf *sb); +pa_strbuf *pa_strbuf_new(void); +void pa_strbuf_free(pa_strbuf *sb); +char *pa_strbuf_tostring(pa_strbuf *sb); +char *pa_strbuf_tostring_free(pa_strbuf *sb); -int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); -void pa_strbuf_puts(struct pa_strbuf *sb, const char *t); -void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t m); +int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); +void pa_strbuf_puts(pa_strbuf *sb, const char *t); +void pa_strbuf_putsn(pa_strbuf *sb, const char *t, size_t m); #endif diff --git a/polyp/strlist-test.c b/polyp/strlist-test.c index b68a04154..c670a105c 100644 --- a/polyp/strlist-test.c +++ b/polyp/strlist-test.c @@ -2,10 +2,11 @@ #include "strlist.h" #include "xmalloc.h" +#include "gccmacro.h" -int main(int argc, char* argv[]) { +int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) { char *t, *u; - struct pa_strlist *l = NULL; + pa_strlist *l = NULL; l = pa_strlist_prepend(l, "e"); l = pa_strlist_prepend(l, "d"); diff --git a/polyp/strlist.c b/polyp/strlist.c index 6dc865d1d..09eb0c8aa 100644 --- a/polyp/strlist.c +++ b/polyp/strlist.c @@ -32,22 +32,22 @@ #include "util.h" struct pa_strlist { - struct pa_strlist *next; + pa_strlist *next; char *str; }; -struct pa_strlist* pa_strlist_prepend(struct pa_strlist *l, const char *s) { - struct pa_strlist *n; +pa_strlist* pa_strlist_prepend(pa_strlist *l, const char *s) { + pa_strlist *n; assert(s); - n = pa_xmalloc(sizeof(struct pa_strlist)); + n = pa_xmalloc(sizeof(pa_strlist)); n->str = pa_xstrdup(s); n->next = l; return n; } -char *pa_strlist_tostring(struct pa_strlist *l) { +char *pa_strlist_tostring(pa_strlist *l) { int first = 1; - struct pa_strbuf *b; + pa_strbuf *b; b = pa_strbuf_new(); for (; l; l = l->next) { @@ -60,13 +60,13 @@ char *pa_strlist_tostring(struct pa_strlist *l) { return pa_strbuf_tostring_free(b); } -struct pa_strlist* pa_strlist_remove(struct pa_strlist *l, const char *s) { - struct pa_strlist *ret = l, *prev = NULL; +pa_strlist* pa_strlist_remove(pa_strlist *l, const char *s) { + pa_strlist *ret = l, *prev = NULL; assert(l && s); while (l) { if (!strcmp(l->str, s)) { - struct pa_strlist *n = l->next; + pa_strlist *n = l->next; if (!prev) { assert(ret == l); @@ -88,9 +88,9 @@ struct pa_strlist* pa_strlist_remove(struct pa_strlist *l, const char *s) { return ret; } -void pa_strlist_free(struct pa_strlist *l) { +void pa_strlist_free(pa_strlist *l) { while (l) { - struct pa_strlist *c = l; + pa_strlist *c = l; l = l->next; pa_xfree(c->str); @@ -98,8 +98,8 @@ void pa_strlist_free(struct pa_strlist *l) { } } -struct pa_strlist* pa_strlist_pop(struct pa_strlist *l, char **s) { - struct pa_strlist *r; +pa_strlist* pa_strlist_pop(pa_strlist *l, char **s) { + pa_strlist *r; assert(s); if (!l) { @@ -113,15 +113,15 @@ struct pa_strlist* pa_strlist_pop(struct pa_strlist *l, char **s) { return r; } -struct pa_strlist* pa_strlist_parse(const char *s) { - struct pa_strlist *head = NULL, *p = NULL; +pa_strlist* pa_strlist_parse(const char *s) { + pa_strlist *head = NULL, *p = NULL; const char *state = NULL; char *r; while ((r = pa_split_spaces(s, &state))) { - struct pa_strlist *n; + pa_strlist *n; - n = pa_xmalloc(sizeof(struct pa_strlist)); + n = pa_xmalloc(sizeof(pa_strlist)); n->str = r; n->next = NULL; diff --git a/polyp/strlist.h b/polyp/strlist.h index 533f55335..2c54dc748 100644 --- a/polyp/strlist.h +++ b/polyp/strlist.h @@ -22,26 +22,26 @@ USA. ***/ -struct pa_strlist; +typedef struct pa_strlist pa_strlist; /* Add the specified server string to the list, return the new linked list head */ -struct pa_strlist* pa_strlist_prepend(struct pa_strlist *l, const char *s); +pa_strlist* pa_strlist_prepend(pa_strlist *l, const char *s); /* Remove the specified string from the list, return the new linked list head */ -struct pa_strlist* pa_strlist_remove(struct pa_strlist *l, const char *s); +pa_strlist* pa_strlist_remove(pa_strlist *l, const char *s); /* Make a whitespace separated string of all server stringes. Returned memory has to be freed with pa_xfree() */ -char *pa_strlist_tostring(struct pa_strlist *l); +char *pa_strlist_tostring(pa_strlist *l); /* Free the entire list */ -void pa_strlist_free(struct pa_strlist *l); +void pa_strlist_free(pa_strlist *l); /* Return the next entry in the list in *string and remove it from * the list. Returns the new list head. The memory *string points to * has to be freed with pa_xfree() */ -struct pa_strlist* pa_strlist_pop(struct pa_strlist *l, char **s); +pa_strlist* pa_strlist_pop(pa_strlist *l, char **s); /* Parse a whitespace separated server list */ -struct pa_strlist* pa_strlist_parse(const char *s); +pa_strlist* pa_strlist_parse(const char *s); #endif diff --git a/polyp/subscribe.c b/polyp/subscribe.c index ee6ef3aa0..d3db90f74 100644 --- a/polyp/subscribe.c +++ b/polyp/subscribe.c @@ -39,28 +39,28 @@ * called from within the stack frame the entity was created in. */ struct pa_subscription { - struct pa_core *core; + pa_core *core; int dead; - void (*callback)(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata); + void (*callback)(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata); void *userdata; - enum pa_subscription_mask mask; + pa_subscription_mask mask; - struct pa_subscription *prev, *next; + pa_subscription *prev, *next; }; struct pa_subscription_event { - enum pa_subscription_event_type type; + pa_subscription_event_type type; uint32_t index; }; -static void sched_event(struct pa_core *c); +static void sched_event(pa_core *c); /* Allocate a new subscription object for the given subscription mask. Use the specified callback function and user data */ -struct pa_subscription* pa_subscription_new(struct pa_core *c, enum pa_subscription_mask m, void (*callback)(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { - struct pa_subscription *s; +pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask m, void (*callback)(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { + pa_subscription *s; assert(c); - s = pa_xmalloc(sizeof(struct pa_subscription)); + s = pa_xmalloc(sizeof(pa_subscription)); s->core = c; s->dead = 0; s->callback = callback; @@ -75,13 +75,13 @@ struct pa_subscription* pa_subscription_new(struct pa_core *c, enum pa_subscript } /* Free a subscription object, effectively marking it for deletion */ -void pa_subscription_free(struct pa_subscription*s) { +void pa_subscription_free(pa_subscription*s) { assert(s && !s->dead); s->dead = 1; sched_event(s->core); } -static void free_item(struct pa_subscription *s) { +static void free_item(pa_subscription *s) { assert(s && s->core); if (s->prev) @@ -96,8 +96,8 @@ static void free_item(struct pa_subscription *s) { } /* Free all subscription objects */ -void pa_subscription_free_all(struct pa_core *c) { - struct pa_subscription_event *e; +void pa_subscription_free_all(pa_core *c) { + pa_subscription_event *e; assert(c); while (c->subscriptions) @@ -117,7 +117,7 @@ void pa_subscription_free_all(struct pa_core *c) { } } -/*static void dump_event(struct pa_subscription_event*e) { +/*static void dump_event(pa_subscription_event*e) { switch (e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { case PA_SUBSCRIPTION_EVENT_SINK: pa_log(__FILE__": SINK_EVENT"); @@ -161,10 +161,10 @@ void pa_subscription_free_all(struct pa_core *c) { }*/ /* Deferred callback for dispatching subscirption events */ -static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { - struct pa_core *c = userdata; - struct pa_subscription *s; - assert(c && c->subscription_defer_event == e && c->mainloop == m); +static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) { + pa_core *c = userdata; + pa_subscription *s; + assert(c && c->subscription_defer_event == de && c->mainloop == m); c->mainloop->defer_enable(c->subscription_defer_event, 0); @@ -172,10 +172,9 @@ static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void * /* Dispatch queued events */ if (c->subscription_event_queue) { - struct pa_subscription_event *e; + pa_subscription_event *e; while ((e = pa_queue_pop(c->subscription_event_queue))) { - struct pa_subscription *s; for (s = c->subscriptions; s; s = s->next) { @@ -191,7 +190,7 @@ static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void * s = c->subscriptions; while (s) { - struct pa_subscription *n = s->next; + pa_subscription *n = s->next; if (s->dead) free_item(s); s = n; @@ -199,7 +198,7 @@ static void defer_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void * } /* Schedule an mainloop event so that a pending subscription event is dispatched */ -static void sched_event(struct pa_core *c) { +static void sched_event(pa_core *c) { assert(c); if (!c->subscription_defer_event) { @@ -211,11 +210,11 @@ static void sched_event(struct pa_core *c) { } /* Append a new subscription event to the subscription event queue and schedule a main loop event */ -void pa_subscription_post(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index) { - struct pa_subscription_event *e; +void pa_subscription_post(pa_core *c, pa_subscription_event_type t, uint32_t index) { + pa_subscription_event *e; assert(c); - e = pa_xmalloc(sizeof(struct pa_subscription_event)); + e = pa_xmalloc(sizeof(pa_subscription_event)); e->type = t; e->index = index; diff --git a/polyp/subscribe.h b/polyp/subscribe.h index 38323faf5..6980328fb 100644 --- a/polyp/subscribe.h +++ b/polyp/subscribe.h @@ -22,16 +22,16 @@ USA. ***/ +typedef struct pa_subscription pa_subscription; +typedef struct pa_subscription_event pa_subscription_event; + #include "core.h" #include "native-common.h" -struct pa_subscription; -struct pa_subscription_event; +pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask m, void (*callback)(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); +void pa_subscription_free(pa_subscription*s); +void pa_subscription_free_all(pa_core *c); -struct pa_subscription* pa_subscription_new(struct pa_core *c, enum pa_subscription_mask m, void (*callback)(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); -void pa_subscription_free(struct pa_subscription*s); -void pa_subscription_free_all(struct pa_core *c); - -void pa_subscription_post(struct pa_core *c, enum pa_subscription_event_type t, uint32_t index); +void pa_subscription_post(pa_core *c, pa_subscription_event_type t, uint32_t idx); #endif diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 1ff09cd15..28b1afa6c 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -65,12 +65,12 @@ struct pa_tagstruct { int dynamic; }; -struct pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) { - struct pa_tagstruct*t; +pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) { + pa_tagstruct*t; assert(!data || (data && length)); - t = pa_xmalloc(sizeof(struct pa_tagstruct)); + t = pa_xmalloc(sizeof(pa_tagstruct)); t->data = (uint8_t*) data; t->allocated = t->length = data ? length : 0; t->rindex = 0; @@ -78,14 +78,14 @@ struct pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) { return t; } -void pa_tagstruct_free(struct pa_tagstruct*t) { +void pa_tagstruct_free(pa_tagstruct*t) { assert(t); if (t->dynamic) pa_xfree(t->data); pa_xfree(t); } -uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l) { +uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l) { uint8_t *p; assert(t && t->dynamic && l); p = t->data; @@ -94,7 +94,7 @@ uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l) { return p; } -static void extend(struct pa_tagstruct*t, size_t l) { +static void extend(pa_tagstruct*t, size_t l) { assert(t && t->dynamic); if (t->length+l <= t->allocated) @@ -103,7 +103,7 @@ static void extend(struct pa_tagstruct*t, size_t l) { t->data = pa_xrealloc(t->data, t->allocated = t->length+l+100); } -void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s) { +void pa_tagstruct_puts(pa_tagstruct*t, const char *s) { size_t l; assert(t); if (s) { @@ -119,7 +119,7 @@ void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s) { } } -void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) { +void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) { assert(t); extend(t, 5); t->data[t->length] = TAG_U32; @@ -128,7 +128,7 @@ void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) { t->length += 5; } -void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c) { +void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c) { assert(t); extend(t, 2); t->data[t->length] = TAG_U8; @@ -136,7 +136,7 @@ void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c) { t->length += 2; } -void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss) { +void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss) { uint32_t rate; assert(t && ss); extend(t, 7); @@ -148,7 +148,7 @@ void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample t->length += 7; } -void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) { +void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) { uint32_t tmp; assert(t && p); @@ -161,14 +161,14 @@ void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t le t->length += 5+length; } -void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b) { +void pa_tagstruct_put_boolean(pa_tagstruct*t, int b) { assert(t); extend(t, 1); t->data[t->length] = b ? TAG_BOOLEAN_TRUE : TAG_BOOLEAN_FALSE; t->length += 1; } -void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) { +void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) { uint32_t tmp; assert(t); extend(t, 9); @@ -180,7 +180,7 @@ void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) { t->length += 9; } -void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) { +void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u) { uint32_t tmp; assert(t); extend(t, 9); @@ -192,7 +192,7 @@ void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) { t->length += 9; } -void pa_tagstruct_putu64(struct pa_tagstruct*t, uint64_t u) { +void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) { uint32_t tmp; assert(t); extend(t, 9); @@ -204,7 +204,7 @@ void pa_tagstruct_putu64(struct pa_tagstruct*t, uint64_t u) { t->length += 9; } -int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) { +int pa_tagstruct_gets(pa_tagstruct*t, const char **s) { int error = 0; size_t n; char *c; @@ -241,7 +241,7 @@ int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) { return 0; } -int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i) { +int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i) { assert(t && i); if (t->rindex+5 > t->length) @@ -256,7 +256,7 @@ int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i) { return 0; } -int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c) { +int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c) { assert(t && c); if (t->rindex+2 > t->length) @@ -270,7 +270,7 @@ int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c) { return 0; } -int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss) { +int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) { assert(t && ss); if (t->rindex+7 > t->length) @@ -288,7 +288,7 @@ int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec * return 0; } -int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length) { +int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) { uint32_t len; assert(t && p); @@ -307,18 +307,18 @@ int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t le return 0; } -int pa_tagstruct_eof(struct pa_tagstruct*t) { +int pa_tagstruct_eof(pa_tagstruct*t) { assert(t); return t->rindex >= t->length; } -const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l) { +const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l) { assert(t && t->dynamic && l); *l = t->length; return t->data; } -int pa_tagstruct_get_boolean(struct pa_tagstruct*t, int *b) { +int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) { assert(t && b); if (t->rindex+1 > t->length) @@ -335,7 +335,7 @@ int pa_tagstruct_get_boolean(struct pa_tagstruct*t, int *b) { return 0; } -int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv) { +int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) { if (t->rindex+9 > t->length) return -1; @@ -352,7 +352,7 @@ int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv) { } -int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) { +int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) { uint32_t tmp; assert(t && u); @@ -370,7 +370,7 @@ int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) { return 0; } -int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *u) { +int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) { uint32_t tmp; assert(t && u); diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index 135825e6d..85b324b7e 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -29,33 +29,33 @@ #include "sample.h" -struct pa_tagstruct; +typedef struct pa_tagstruct pa_tagstruct; -struct pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length); -void pa_tagstruct_free(struct pa_tagstruct*t); -uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l); +pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length); +void pa_tagstruct_free(pa_tagstruct*t); +uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l); -void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s); -void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c); -void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i); -void pa_tagstruct_putu64(struct pa_tagstruct*t, uint64_t i); -void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss); -void pa_tagstruct_put_arbitrary(struct pa_tagstruct*t, const void *p, size_t length); -void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b); -void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv); -void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u); +void pa_tagstruct_puts(pa_tagstruct*t, const char *s); +void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c); +void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i); +void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t i); +void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss); +void pa_tagstruct_put_arbitrary(pa_tagstruct*t, const void *p, size_t length); +void pa_tagstruct_put_boolean(pa_tagstruct*t, int b); +void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv); +void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u); -int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s); -int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c); -int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i); -int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *i); -int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss); -int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length); -int pa_tagstruct_get_boolean(struct pa_tagstruct *t, int *b); -int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv); -int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u); +int pa_tagstruct_gets(pa_tagstruct*t, const char **s); +int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c); +int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i); +int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *i); +int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss); +int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length); +int pa_tagstruct_get_boolean(pa_tagstruct *t, int *b); +int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv); +int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u); -int pa_tagstruct_eof(struct pa_tagstruct*t); -const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l); +int pa_tagstruct_eof(pa_tagstruct*t); +const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l); #endif diff --git a/polyp/tokenizer.c b/polyp/tokenizer.c index 8ccbc84f1..5e0c1b166 100644 --- a/polyp/tokenizer.c +++ b/polyp/tokenizer.c @@ -30,16 +30,17 @@ #include "tokenizer.h" #include "dynarray.h" #include "xmalloc.h" +#include "gccmacro.h" struct pa_tokenizer { - struct pa_dynarray *dynarray; + pa_dynarray *dynarray; }; -static void token_free(void *p, void *userdata) { +static void token_free(void *p, PA_GCC_UNUSED void *userdata) { pa_xfree(p); } -static void parse(struct pa_dynarray*a, const char *s, unsigned args) { +static void parse(pa_dynarray*a, const char *s, unsigned args) { int infty = 0; const char delimiter[] = " \t\n\r"; const char *p; @@ -64,10 +65,10 @@ static void parse(struct pa_dynarray*a, const char *s, unsigned args) { } } -struct pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args) { - struct pa_tokenizer *t; +pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args) { + pa_tokenizer *t; - t = pa_xmalloc(sizeof(struct pa_tokenizer)); + t = pa_xmalloc(sizeof(pa_tokenizer)); t->dynarray = pa_dynarray_new(); assert(t->dynarray); @@ -75,13 +76,13 @@ struct pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args) { return t; } -void pa_tokenizer_free(struct pa_tokenizer *t) { +void pa_tokenizer_free(pa_tokenizer *t) { assert(t); pa_dynarray_free(t->dynarray, token_free, NULL); pa_xfree(t); } -const char *pa_tokenizer_get(struct pa_tokenizer *t, unsigned i) { +const char *pa_tokenizer_get(pa_tokenizer *t, unsigned i) { assert(t); return pa_dynarray_get(t->dynarray, i); } diff --git a/polyp/tokenizer.h b/polyp/tokenizer.h index 0b1c5022a..bedacb8a9 100644 --- a/polyp/tokenizer.h +++ b/polyp/tokenizer.h @@ -22,11 +22,11 @@ USA. ***/ -struct pa_tokenizer; +typedef struct pa_tokenizer pa_tokenizer; -struct pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args); -void pa_tokenizer_free(struct pa_tokenizer *t); +pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args); +void pa_tokenizer_free(pa_tokenizer *t); -const char *pa_tokenizer_get(struct pa_tokenizer *t, unsigned i); +const char *pa_tokenizer_get(pa_tokenizer *t, unsigned i); #endif diff --git a/polyp/util.c b/polyp/util.c index 26d712037..f9098704b 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -219,7 +219,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) { break; ret += r; - data = (uint8_t*) data + r; + data = (const uint8_t*) data + r; size -= r; } @@ -767,13 +767,13 @@ finish: /* Check the current user is member of the specified group */ int pa_uid_in_group(const char *name, gid_t *gid) { - gid_t *gids, tgid; - GETGROUPS_T n = sysconf(_SC_NGROUPS_MAX); + GETGROUPS_T *gids, tgid; + int n = sysconf(_SC_NGROUPS_MAX); int r = -1, i; assert(n > 0); - gids = pa_xmalloc(sizeof(gid_t)*n); + gids = pa_xmalloc(sizeof(GETGROUPS_T)*n); if ((n = getgroups(n, gids)) < 0) { pa_log(__FILE__": getgroups() failed: %s\n", strerror(errno)); diff --git a/polyp/util.h b/polyp/util.h index d9e18ddbe..95e7b99b1 100644 --- a/polyp/util.h +++ b/polyp/util.h @@ -27,7 +27,7 @@ #include #include -#include "gcc-printf.h" +#include "gccmacro.h" #include "sample.h" struct timeval; diff --git a/polyp/voltest.c b/polyp/voltest.c index d8d5c5692..286334d08 100644 --- a/polyp/voltest.c +++ b/polyp/voltest.c @@ -3,8 +3,9 @@ #include #include +#include "gccmacro.h" -int main() { +int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { int p; for (p = 0; p <= 200; p++) { pa_volume_t v = pa_volume_from_user((double) p/100); diff --git a/polyp/x11wrap.c b/polyp/x11wrap.c index 4d8d6930f..64923320b 100644 --- a/polyp/x11wrap.c +++ b/polyp/x11wrap.c @@ -28,42 +28,42 @@ #include "log.h" #include "props.h" -struct pa_x11_client; +typedef struct pa_x11_internal pa_x11_internal; struct pa_x11_internal { - PA_LLIST_FIELDS(struct pa_x11_internal); - struct pa_x11_wrapper *wrapper; - struct pa_io_event* io_event; + PA_LLIST_FIELDS(pa_x11_internal); + pa_x11_wrapper *wrapper; + pa_io_event* io_event; int fd; }; struct pa_x11_wrapper { - struct pa_core *core; + pa_core *core; int ref; char *property_name; Display *display; - struct pa_defer_event* defer_event; - struct pa_io_event* io_event; + pa_defer_event* defer_event; + pa_io_event* io_event; - PA_LLIST_HEAD(struct pa_x11_client, clients); - PA_LLIST_HEAD(struct pa_x11_internal, internals); + PA_LLIST_HEAD(pa_x11_client, clients); + PA_LLIST_HEAD(pa_x11_internal, internals); }; struct pa_x11_client { - PA_LLIST_FIELDS(struct pa_x11_client); - struct pa_x11_wrapper *wrapper; - int (*callback)(struct pa_x11_wrapper *w, XEvent *e, void *userdata); + PA_LLIST_FIELDS(pa_x11_client); + pa_x11_wrapper *wrapper; + int (*callback)(pa_x11_wrapper *w, XEvent *e, void *userdata); void *userdata; }; /* Dispatch all pending X11 events */ -static void work(struct pa_x11_wrapper *w) { +static void work(pa_x11_wrapper *w) { assert(w && w->ref >= 1); while (XPending(w->display)) { - struct pa_x11_client *c; + pa_x11_client *c; XEvent e; XNextEvent(w->display, &e); @@ -76,63 +76,63 @@ static void work(struct pa_x11_wrapper *w) { } /* IO notification event for the X11 display connection */ -static void display_io_event(struct pa_mainloop_api *m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { - struct pa_x11_wrapper *w = userdata; +static void display_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { + pa_x11_wrapper *w = userdata; assert(m && e && fd >= 0 && w && w->ref >= 1); work(w); } /* Deferred notification event. Called once each main loop iteration */ -static void defer_event(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) { - struct pa_x11_wrapper *w = userdata; +static void defer_event(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { + pa_x11_wrapper *w = userdata; assert(m && e && w && w->ref >= 1); work(w); } /* IO notification event for X11 internal connections */ -static void internal_io_event(struct pa_mainloop_api *m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) { - struct pa_x11_wrapper *w = userdata; +static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { + pa_x11_wrapper *w = userdata; assert(m && e && fd >= 0 && w && w->ref >= 1); XProcessInternalConnection(w->display, fd); } /* Add a new IO source for the specified X11 internal connection */ -static struct pa_x11_internal* x11_internal_add(struct pa_x11_wrapper *w, int fd) { - struct pa_x11_internal *i; +static pa_x11_internal* x11_internal_add(pa_x11_wrapper *w, int fd) { + pa_x11_internal *i; assert(i && fd >= 0); - i = pa_xmalloc(sizeof(struct pa_x11_internal)); + i = pa_xmalloc(sizeof(pa_x11_internal)); i->wrapper = w; i->io_event = w->core->mainloop->io_new(w->core->mainloop, fd, PA_IO_EVENT_INPUT, internal_io_event, w); i->fd = fd; - PA_LLIST_PREPEND(struct pa_x11_internal, w->internals, i); + PA_LLIST_PREPEND(pa_x11_internal, w->internals, i); return i; } /* Remove an IO source for an X11 internal connection */ -void x11_internal_remove(struct pa_x11_wrapper *w, struct pa_x11_internal *i) { +static void x11_internal_remove(pa_x11_wrapper *w, pa_x11_internal *i) { assert(i); - PA_LLIST_REMOVE(struct pa_x11_internal, w->internals, i); + PA_LLIST_REMOVE(pa_x11_internal, w->internals, i); w->core->mainloop->io_free(i->io_event); pa_xfree(i); } /* Implementation of XConnectionWatchProc */ static void x11_watch(Display *display, XPointer userdata, int fd, Bool opening, XPointer *watch_data) { - struct pa_x11_wrapper *w = (struct pa_x11_wrapper*) userdata; + pa_x11_wrapper *w = (pa_x11_wrapper*) userdata; assert(display && w && fd >= 0); if (opening) *watch_data = (XPointer) x11_internal_add(w, fd); else - x11_internal_remove(w, (struct pa_x11_internal*) *watch_data); + x11_internal_remove(w, (pa_x11_internal*) *watch_data); } -static struct pa_x11_wrapper* x11_wrapper_new(struct pa_core *c, const char *name, const char *t) { - struct pa_x11_wrapper*w; +static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char *t) { + pa_x11_wrapper*w; Display *d; int r; @@ -141,14 +141,14 @@ static struct pa_x11_wrapper* x11_wrapper_new(struct pa_core *c, const char *nam return NULL; } - w = pa_xmalloc(sizeof(struct pa_x11_wrapper)); + w = pa_xmalloc(sizeof(pa_x11_wrapper)); w->core = c; w->ref = 1; w->property_name = pa_xstrdup(t); w->display = d; - PA_LLIST_HEAD_INIT(struct pa_x11_client, w->clients); - PA_LLIST_HEAD_INIT(struct pa_x11_internal, w->internals); + PA_LLIST_HEAD_INIT(pa_x11_client, w->clients); + PA_LLIST_HEAD_INIT(pa_x11_internal, w->internals); w->defer_event = c->mainloop->defer_new(c->mainloop, defer_event, w); w->io_event = c->mainloop->io_new(c->mainloop, ConnectionNumber(d), PA_IO_EVENT_INPUT, display_io_event, w); @@ -161,7 +161,7 @@ static struct pa_x11_wrapper* x11_wrapper_new(struct pa_core *c, const char *nam return w; } -static void x11_wrapper_free(struct pa_x11_wrapper*w) { +static void x11_wrapper_free(pa_x11_wrapper*w) { int r; assert(w); @@ -183,9 +183,9 @@ static void x11_wrapper_free(struct pa_x11_wrapper*w) { pa_xfree(w); } -struct pa_x11_wrapper* pa_x11_wrapper_get(struct pa_core *c, const char *name) { +pa_x11_wrapper* pa_x11_wrapper_get(pa_core *c, const char *name) { char t[256]; - struct pa_x11_wrapper *w; + pa_x11_wrapper *w; assert(c); snprintf(t, sizeof(t), "x11-wrapper%s%s", name ? "-" : "", name ? name : ""); @@ -195,41 +195,41 @@ struct pa_x11_wrapper* pa_x11_wrapper_get(struct pa_core *c, const char *name) { return x11_wrapper_new(c, name, t); } -struct pa_x11_wrapper* pa_x11_wrapper_ref(struct pa_x11_wrapper *w) { +pa_x11_wrapper* pa_x11_wrapper_ref(pa_x11_wrapper *w) { assert(w && w->ref >= 1); w->ref++; return w; } -void pa_x11_wrapper_unref(struct pa_x11_wrapper* w) { +void pa_x11_wrapper_unref(pa_x11_wrapper* w) { assert(w && w->ref >= 1); if (!(--w->ref)) x11_wrapper_free(w); } -Display *pa_x11_wrapper_get_display(struct pa_x11_wrapper *w) { +Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w) { assert(w && w->ref >= 1); return w->display; } -struct pa_x11_client* pa_x11_client_new(struct pa_x11_wrapper *w, int (*cb)(struct pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata) { - struct pa_x11_client *c; +pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata) { + pa_x11_client *c; assert(w && w->ref >= 1); - c = pa_xmalloc(sizeof(struct pa_x11_client)); + c = pa_xmalloc(sizeof(pa_x11_client)); c->wrapper = w; c->callback = cb; c->userdata = userdata; - PA_LLIST_PREPEND(struct pa_x11_client, w->clients, c); + PA_LLIST_PREPEND(pa_x11_client, w->clients, c); return c; } -void pa_x11_client_free(struct pa_x11_client *c) { +void pa_x11_client_free(pa_x11_client *c) { assert(c && c->wrapper && c->wrapper->ref >= 1); - PA_LLIST_REMOVE(struct pa_x11_client, c->wrapper->clients, c); + PA_LLIST_REMOVE(pa_x11_client, c->wrapper->clients, c); pa_xfree(c); } diff --git a/polyp/x11wrap.h b/polyp/x11wrap.h index 9ed690fe8..15645168e 100644 --- a/polyp/x11wrap.h +++ b/polyp/x11wrap.h @@ -26,27 +26,27 @@ #include "core.h" -struct pa_x11_wrapper; +typedef struct pa_x11_wrapper pa_x11_wrapper; /* Return the X11 wrapper for this core. In case no wrapper was existant before, allocate a new one */ -struct pa_x11_wrapper* pa_x11_wrapper_get(struct pa_core *c, const char *name); +pa_x11_wrapper* pa_x11_wrapper_get(pa_core *c, const char *name); /* Increase the wrapper's reference count by one */ -struct pa_x11_wrapper* pa_x11_wrapper_ref(struct pa_x11_wrapper *w); +pa_x11_wrapper* pa_x11_wrapper_ref(pa_x11_wrapper *w); /* Decrease the reference counter of an X11 wrapper object */ -void pa_x11_wrapper_unref(struct pa_x11_wrapper* w); +void pa_x11_wrapper_unref(pa_x11_wrapper* w); /* Return the X11 display object for this connection */ -Display *pa_x11_wrapper_get_display(struct pa_x11_wrapper *w); +Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w); -struct pa_x11_client; +typedef struct pa_x11_client pa_x11_client; /* Register an X11 client, that is called for each X11 event */ -struct pa_x11_client* pa_x11_client_new(struct pa_x11_wrapper *w, int (*cb)(struct pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata); +pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata); /* Free an X11 client object */ -void pa_x11_client_free(struct pa_x11_client *c); +void pa_x11_client_free(pa_x11_client *c); #endif diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c index f2751e52b..bf3663470 100644 --- a/polyp/xmalloc.c +++ b/polyp/xmalloc.c @@ -30,6 +30,8 @@ #include "memory.h" #include "util.h" +#include "xmalloc.h" +#include "gccmacro.h" /* Make sure not to allocate more than this much memory. */ #define MAX_ALLOC_SIZE (1024*1024*20) /* 20MB */ @@ -40,6 +42,8 @@ /* #undef strndup */ /* #undef strdup */ +static void oom(void) PA_GCC_NORETURN; + /** called in case of an OOM situation. Prints an error message and * exits */ static void oom(void) { diff --git a/polyp/xmalloc.h b/polyp/xmalloc.h index b37ece90d..2946011af 100644 --- a/polyp/xmalloc.h +++ b/polyp/xmalloc.h @@ -24,6 +24,8 @@ #include #include +#include +#include void* pa_xmalloc(size_t l); void *pa_xmalloc0(size_t l); @@ -35,4 +37,22 @@ char *pa_xstrndup(const char *s, size_t l); void* pa_xmemdup(const void *p, size_t l); +/** Internal helper for pa_xnew() */ +static inline void* pa_xnew_internal(unsigned n, size_t k) { + assert(n < INT_MAX/k); + return pa_xmalloc(n*k); +} + +/** Allocate n new structures of the specified type. */ +#define pa_xnew(type, n) ((type*) pa_xnew_internal((n), sizeof(type))) + +/** Internal helper for pa_xnew0() */ +static inline void* pa_xnew0_internal(unsigned n, size_t k) { + assert(n < INT_MAX/k); + return pa_xmalloc0(n*k); +} + +/** Same as pa_xnew() but set the memory to zero */ +#define pa_xnew0(type, n) ((type*) pa_xnew0_internal((n), sizeof(type))) + #endif From 70ac72ee7fa277705b8c3d8b0245d9a43740ef28 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 11 Jan 2006 14:12:38 +0000 Subject: [PATCH 0356/1514] Our makefiles work just fine on older automakes (1.7 tested). Let's keep this out until we run into something that doesn't work. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@448 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f69eb636f..20d9b8664 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_PREREQ(2.57) AC_INIT([polypaudio],[0.8],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([polyp/main.c]) AC_CONFIG_HEADERS([config.h]) -AM_INIT_AUTOMAKE([foreign 1.9 -Wall]) +AM_INIT_AUTOMAKE([foreign -Wall]) AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) From 2623edcc4222884d57ce161e4ab0ba86feb8a2b8 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 11 Jan 2006 14:13:28 +0000 Subject: [PATCH 0357/1514] Remove the old compiler flag test now that we have a new shiny one. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@449 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 20d9b8664..8a87928bc 100644 --- a/configure.ac +++ b/configure.ac @@ -43,15 +43,6 @@ AC_PROG_CC AC_PROG_GCC_TRADITIONAL AC_GNU_SOURCE -# If using GCC specify some additional parameters -if test "x$GCC" = "xyes" ; then - CFLAGS="$CFLAGS -pipe -W -Wall -pedantic" - - AC_LANG_CONFTEST([int main() {}]) - $CC -c conftest.c -std=gnu9x -Wno-unused-parameter $CFLAGS > /dev/null 2> /dev/null && CFLAGS="$CFLAGS -std=gnu9x -Wno-unused-parameter" - rm -f conftest.o -fi - # M4 AC_PATH_PROG([M4], [m4 gm4], [no]) @@ -72,7 +63,7 @@ test_gcc_flag() { # If using GCC specify some additional parameters if test "x$GCC" = "xyes" ; then - DESIRED_FLAGS="-Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Winline" + DESIRED_FLAGS="-Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter" if test "x$HAVE_NETLINK" = "xyes" ; then # Test whether rtnetlink.h can be included when compiled with -std=c99 From 72316ccf9c8c7fec6fbd5d190852a61168002b24 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 11 Jan 2006 14:36:02 +0000 Subject: [PATCH 0358/1514] Many (FSF and Sun at least) have interpreted the C99 standard in a way that int64_t and similar types are only defined on 64 bit platforms. Using -std=gnu99 lifts this rather silly restriction. The HAVE_NETLINK define is not generated anywhere in our configure. So it was rather pointless to use it for any test. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@450 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/configure.ac b/configure.ac index 8a87928bc..bfe6ecd12 100644 --- a/configure.ac +++ b/configure.ac @@ -63,29 +63,9 @@ test_gcc_flag() { # If using GCC specify some additional parameters if test "x$GCC" = "xyes" ; then - DESIRED_FLAGS="-Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter" - - if test "x$HAVE_NETLINK" = "xyes" ; then - # Test whether rtnetlink.h can be included when compiled with -std=c99 - # some distributions (e.g. archlinux) have broken headers that dont - # define __u64 with -std=c99 - AC_MSG_CHECKING([checking whether rtnetlink.h can be included with -std=c99]) - OLDCFLAGS="$CFLAGS" - CFLAGS="-std=c99" - AC_TRY_COMPILE([#include ], [], - use_stdc99=yes, use_stdc99=no) - - if test x"$use_stdc99" = xyes; then - DESIRED_FLAGS="-std=c99 $DESIRED_FLAGS" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - - CFLAGS="$OLDCFLAGS" - else - DESIRED_FLAGS="-std=c99 $DESIRED_FLAGS" - fi + # We use gnu99 instead of c99 because many have interpreted the standard + # in a way that int64_t isn't defined on non-64 bit platforms. + DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter" for flag in $DESIRED_FLAGS ; do AC_MSG_CHECKING([whether $CC accepts $flag]) From f61be8b654d33f3ab1b693c7e3a5d790617fbf6e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 12 Jan 2006 16:04:21 +0000 Subject: [PATCH 0359/1514] If the card couldn't do duplex when required we would incorrectly return success from this function with a closed fd. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@451 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/oss-util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polyp/oss-util.c b/polyp/oss-util.c index 20a2965a3..ae6772fd9 100644 --- a/polyp/oss-util.c +++ b/polyp/oss-util.c @@ -57,7 +57,7 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { if (*tcaps & DSP_CAP_DUPLEX) return fd; - close(fd); + goto fail; } if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) { @@ -87,7 +87,7 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { fail: if (fd >= 0) close(fd); - return fd; + return -1; } int pa_oss_auto_format(int fd, pa_sample_spec *ss) { From fc93e4b3a722833ca6c1ad8a3c9af0b95b954000 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 12 Jan 2006 16:08:14 +0000 Subject: [PATCH 0360/1514] Used 0 as an invalid fd. Changed to -1. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@452 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-oss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 7c331893f..d060b489a 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -347,7 +347,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(u->source || u->sink); - u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0); + u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : -1); assert(u->io); pa_iochannel_set_callback(u->io, io_callback, u); u->fd = fd; From 289c914b470537234c1de498cf195323826d7984 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 12 Jan 2006 16:09:58 +0000 Subject: [PATCH 0361/1514] Some drivers (via82xx) doesn't start recording until we read something. This is ugly, but unfortunately required. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@453 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-oss.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/polyp/module-oss.c b/polyp/module-oss.c index d060b489a..12cedf19a 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -368,6 +368,15 @@ int pa__init(pa_core *c, pa_module*m) { pa_modargs_free(ma); + /* + * Some crappy drivers do not start the recording until we read something. + * Without this snippet, poll will never register the fd as ready. + */ + if (u->source) { + char buf[u->sample_size]; + read(u->fd, buf, u->sample_size); + } + return 0; fail: From cb2a7ed02840c076f8b53023658920ea8d12d849 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 12 Jan 2006 16:11:54 +0000 Subject: [PATCH 0362/1514] Some crappy hardware generate noise on the output when reading input. To avoid triggering this needlesly we tweak the algorithm a bit to avoid reading when nothing is connected to the source. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@454 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-oss.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 12cedf19a..06679a97d 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -161,7 +161,7 @@ static void do_read(struct userdata *u) { int loop = 0; assert(u); - if (!u->source || !pa_iochannel_is_readable(u->io)) + if (!u->source || !pa_iochannel_is_readable(u->io) || !pa_idxset_size(u->source->outputs)) return; update_usage(u); @@ -209,6 +209,12 @@ static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { do_read(u); } +static void source_notify_cb(pa_source *s) { + struct userdata *u = s->userdata; + assert(u); + do_read(u); +} + static pa_usec_t sink_get_latency_cb(pa_sink *s) { pa_usec_t r = 0; int arg; @@ -329,6 +335,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source = pa_source_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); assert(u->source); u->source->userdata = u; + u->source->notify = source_notify_cb; u->source->get_latency = source_get_latency_cb; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p); From 262c60fcaaa8c0edb6515d2f57bbe41af360ffef Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 12 Jan 2006 17:12:44 +0000 Subject: [PATCH 0363/1514] Under win32 we freed the wrong pointer causing a segmentation fault. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@455 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/util.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/polyp/util.c b/polyp/util.c index f9098704b..4b6edb97f 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -965,19 +965,19 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env FILE *f; char *lfn; - lfn = pa_sprintf_malloc("%s/%s", h, local); + fn = lfn = pa_sprintf_malloc("%s/%s", h, local); #ifdef OS_IS_WIN32 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) return NULL; - lfn = buf; + fn = buf; #endif - f = fopen(lfn, "r"); + f = fopen(fn, "r"); if (f || errno != ENOENT) { if (result) - *result = pa_xstrdup(lfn); + *result = pa_xstrdup(fn); pa_xfree(lfn); return f; } From 719c3773d4314beb9dcd406d780d8df5855a2946 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 16 Jan 2006 13:35:25 +0000 Subject: [PATCH 0364/1514] We need a logical, not an arithmetic shift here. So use unsigned types when doing the shifting. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@456 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/endianmacros.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polyp/endianmacros.h b/polyp/endianmacros.h index 00b992dbc..d07652fb3 100644 --- a/polyp/endianmacros.h +++ b/polyp/endianmacros.h @@ -28,9 +28,9 @@ #include #endif -#define INT16_SWAP(x) ((int16_t)(((int16_t) x >> 8) | ((int16_t) x << 8))) +#define INT16_SWAP(x) ((int16_t)(((uint16_t) x >> 8) | ((uint16_t) x << 8))) #define UINT16_SWAP(x) ((uint16_t)(((uint16_t) x >> 8) | ((uint16_t) x << 8))) -#define INT32_SWAP(x) ((int32_t)(((int32_t) x >> 24) | ((int32_t) x << 24) | (((int32_t) x & 0xFF00) << 16) | (((int32_t) x) >> 16) & 0xFF00)) +#define INT32_SWAP(x) ((int32_t)(((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 16) | (((uint32_t) x) >> 16) & 0xFF00)) #define UINT32_SWAP(x) ((uint32_t)(((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 16) | ((((uint32_t) x) >> 16) & 0xFF00))) #ifdef WORDS_BIGENDIAN From 0ca9a0ea09a8518c9e6b541812a76fa7abac15f1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 19 Jan 2006 10:24:49 +0000 Subject: [PATCH 0365/1514] Ugly hack to get around Solaris particularly brain dead sound system. The system has a buffer size of 0.5 MB which cannot be changed. We emulate a smaller buffer through some SIGPOLL trickery. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@457 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-solaris.c | 58 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/polyp/module-solaris.c b/polyp/module-solaris.c index c8ad7cf11..984a5f662 100644 --- a/polyp/module-solaris.c +++ b/polyp/module-solaris.c @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -48,6 +49,7 @@ #include "modargs.h" #include "xmalloc.h" #include "log.h" +#include "mainloop-signal.h" #include "module-solaris-symdef.h" PA_MODULE_AUTHOR("Pierre Ossman") @@ -62,10 +64,12 @@ struct userdata { pa_source *source; pa_iochannel *io; pa_core *core; + pa_signal_event *sig; pa_memchunk memchunk, silence; uint32_t sample_size; + uint32_t buffer_size; unsigned int written_bytes, read_bytes; int fd; @@ -99,7 +103,10 @@ static void update_usage(struct userdata *u) { } static void do_write(struct userdata *u) { + audio_info_t info; + int err; pa_memchunk *memchunk; + size_t len; ssize_t r; assert(u); @@ -109,17 +116,40 @@ static void do_write(struct userdata *u) { update_usage(u); + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + /* + * Since we cannot modify the size of the output buffer we fake it + * by not filling it more than u->buffer_size. + */ + len = u->buffer_size; + len -= u->written_bytes - (info.play.samples * u->sample_size); + + /* + * Do not fill more than half the buffer in one chunk since we only + * get notifications upon completion of entire chunks. + */ + if (len > (u->buffer_size / 2)) + len = u->buffer_size / 2; + + if (len < u->sample_size) + return; + memchunk = &u->memchunk; if (!memchunk->length) - if (pa_sink_render(u->sink, CHUNK_SIZE, memchunk) < 0) + if (pa_sink_render(u->sink, len, memchunk) < 0) memchunk = &u->silence; assert(memchunk->memblock); assert(memchunk->memblock->data); assert(memchunk->length); + + if (memchunk->length < len) + len = memchunk->length; - if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { + if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { pa_log(__FILE__": write() failed: %s\n", strerror(errno)); return; } @@ -137,6 +167,14 @@ static void do_write(struct userdata *u) { } u->written_bytes += r; + + /* + * Write 0 bytes which will generate a SIGPOLL when "played". + */ + if (write(u->fd, NULL, 0) < 0) { + pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + return; + } } static void do_read(struct userdata *u) { @@ -179,6 +217,12 @@ static void io_callback(pa_iochannel *io, void*userdata) { do_read(u); } +void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { + struct userdata *u = userdata; + assert(u); + do_write(u); +} + static pa_usec_t sink_get_latency_cb(pa_sink *s) { pa_usec_t r = 0; audio_info_t info; @@ -326,7 +370,7 @@ int pa__init(pa_core *c, pa_module*m) { mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); - buffer_size = -1; + buffer_size = 16384; if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) { pa_log(__FILE__": failed to parse buffer size argument\n"); goto fail; @@ -383,6 +427,7 @@ int pa__init(pa_core *c, pa_module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; u->sample_size = pa_frame_size(&ss); + u->buffer_size = buffer_size; u->silence.memblock = pa_memblock_new(u->silence.length = CHUNK_SIZE, u->core->memblock_stat); assert(u->silence.memblock); @@ -395,6 +440,10 @@ int pa__init(pa_core *c, pa_module*m) { u->module = m; m->userdata = u; + u->sig = pa_signal_new(SIGPOLL, sig_callback, u); + assert(u->sig); + ioctl(u->fd, I_SETSIG, S_MSG); + pa_modargs_free(ma); return 0; @@ -415,6 +464,9 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; + + ioctl(u->fd, I_SETSIG, 0); + pa_signal_free(u->sig); if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); From 60dbf8b82d694bba5a4ebbe651e504cb12df927b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 19 Jan 2006 10:26:06 +0000 Subject: [PATCH 0366/1514] Open the device in non-blocking mode. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@458 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/module-solaris.c b/polyp/module-solaris.c index 984a5f662..01a151d63 100644 --- a/polyp/module-solaris.c +++ b/polyp/module-solaris.c @@ -382,7 +382,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode)) < 0) + if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode | O_NONBLOCK)) < 0) goto fail; pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); From 30bb5ceaeea2c612c10245780cf1de80122ac06b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 20 Jan 2006 10:16:37 +0000 Subject: [PATCH 0367/1514] Fix so that peer name can be determined on Windows. We do not support console on Windows at this time so we do not have to worry about that right now. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@459 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/socket-util.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/polyp/socket-util.c b/polyp/socket-util.c index 381502b5f..032a3c914 100644 --- a/polyp/socket-util.c +++ b/polyp/socket-util.c @@ -69,17 +69,22 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { assert(c && l && fd >= 0); +#ifndef OS_IS_WIN32 if (fstat(fd, &st) < 0) { snprintf(c, l, "Invalid client fd"); return; } +#endif #ifndef OS_IS_WIN32 if (S_ISSOCK(st.st_mode)) { +#endif union { struct sockaddr sa; struct sockaddr_in in; +#ifdef HAVE_SYS_UN_H struct sockaddr_un un; +#endif } sa; socklen_t sa_len = sizeof(sa); @@ -95,12 +100,15 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { ip & 0xFF, ntohs(sa.in.sin_port)); return; +#ifdef HAVE_SYS_UN_H } else if (sa.sa.sa_family == AF_UNIX) { snprintf(c, l, "UNIX socket client"); return; +#endif } } +#ifndef OS_IS_WIN32 snprintf(c, l, "Unknown network client"); return; } else if (S_ISCHR(st.st_mode) && (fd == 0 || fd == 1)) { From 104797b5a0c869a668690d13737056646be198bc Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 25 Jan 2006 17:25:28 +0000 Subject: [PATCH 0368/1514] Use AC_SEARCH_LIBS instead of AC_CHECK_LIBS since it is a lot smarter and doesn't add unnecessary libs. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@460 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index bfe6ecd12..1700c8630 100644 --- a/configure.ac +++ b/configure.ac @@ -185,13 +185,13 @@ AC_CHECK_DEFINE([INADDR_NONE], [netinet/in.h], [], #### Check for libs #### # ISO -AC_CHECK_LIB([m], [pow]) +AC_SEARCH_LIBS([pow], [m]) # POSIX -AC_CHECK_LIB([rt], [sched_setscheduler]) +AC_SEARCH_LIBS([sched_setscheduler], [rt]) # BSD -AC_CHECK_LIB([socket], [connect]) +AC_SEARCH_LIBS([connect], [socket]) # Non-standard @@ -258,7 +258,7 @@ AC_ARG_WITH( AC_HELP_STRING([--without-caps],[Omit support for POSIX capabilities.])) if test "x${with_caps}" != "xno"; then - AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS='']) + AC_SEARCH_LIBS([cap_init], [cap], [CAP_LIBS='-lcap'], [CAP_LIBS='']) AC_CHECK_HEADERS([sys/capability.h]) fi AC_SUBST(CAP_LIBS) From 917d8765c62779dc74b9e49dab4f12d9590859c5 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 25 Jan 2006 17:27:10 +0000 Subject: [PATCH 0369/1514] We get the -lcap through LIBS, so no need for CAP_LIBS. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@461 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 3 +-- polyp/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 1700c8630..f2de16539 100644 --- a/configure.ac +++ b/configure.ac @@ -258,10 +258,9 @@ AC_ARG_WITH( AC_HELP_STRING([--without-caps],[Omit support for POSIX capabilities.])) if test "x${with_caps}" != "xno"; then - AC_SEARCH_LIBS([cap_init], [cap], [CAP_LIBS='-lcap'], [CAP_LIBS='']) + AC_SEARCH_LIBS([cap_init], [cap]) AC_CHECK_HEADERS([sys/capability.h]) fi -AC_SUBST(CAP_LIBS) #### pkg-config #### diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 8712782fa..3a0d2f21c 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -104,7 +104,7 @@ polypaudio_SOURCES = \ polypaudio_CFLAGS = $(AM_CFLAGS) polypaudio_CPPFLAGS = $(AM_CPPFLAGS) polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \ - $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) + $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f)) if PREOPEN_MODS From 759721cbbc265cc6ce4c5dd9141e00ca67c8fe2d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 27 Jan 2006 14:52:17 +0000 Subject: [PATCH 0370/1514] Remove the version number from the module directory. Makes life easier for any external projects that need to use that directory. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@462 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 3a0d2f21c..0181ae6a9 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -25,7 +25,7 @@ polypincludedir=$(includedir)/polyp polypconfdir=$(sysconfdir)/polypaudio -modlibdir=$(libdir)/polypaudio-@PA_MAJORMINOR@ +modlibdir=$(libdir)/polypaudio ################################### # Defines # From dd10c982414dfa8fbb9aeeeae61c68e4a6f081cc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 27 Jan 2006 16:25:31 +0000 Subject: [PATCH 0371/1514] Mega patch: * implement inner loops using liboil * drop "typeid" stuff * add support for channel maps * add support for seperate volumes per channel * add support for hardware mixer settings (only module-oss implements this for now) * fix a lot of types for _t suffix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@463 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 5 + polyp/Makefile.am | 26 +- polyp/alsa-util.c | 2 +- polyp/alsa-util.h | 2 +- polyp/autoload.c | 8 +- polyp/autoload.h | 10 +- polyp/channelmap.c | 202 +++++++++++++ polyp/channelmap.h | 94 ++++++ polyp/cli-command.c | 21 +- polyp/cli-text.c | 129 +++++--- polyp/cli.c | 3 +- polyp/client.c | 6 +- polyp/client.h | 6 +- polyp/core.h | 2 +- polyp/daemon-conf.c | 2 +- polyp/daemon-conf.h | 8 +- polyp/dllmain.c | 2 +- polyp/glib-mainloop.c | 12 +- polyp/glib12-mainloop.c | 10 +- polyp/inet_ntop.c | 2 +- polyp/iochannel.c | 4 +- polyp/log.c | 26 +- polyp/log.h | 12 +- polyp/main.c | 3 + polyp/mainloop-api.h | 6 +- polyp/mainloop-signal.c | 2 +- polyp/mainloop-test.c | 2 +- polyp/mainloop.c | 14 +- polyp/memblock.h | 6 +- polyp/module-alsa-sink.c | 8 +- polyp/module-alsa-source.c | 6 +- polyp/module-combine.c | 6 +- polyp/module-esound-sink.c | 6 +- polyp/module-lirc.c | 39 ++- polyp/module-match.c | 6 +- polyp/module-mmkbd-evdev.c | 25 +- polyp/module-null-sink.c | 4 +- polyp/module-oss-mmap.c | 8 +- polyp/module-oss.c | 54 +++- polyp/module-pipe-sink.c | 4 +- polyp/module-pipe-source.c | 4 +- polyp/module-protocol-stub.c | 2 +- polyp/module-sine.c | 4 +- polyp/module-solaris.c | 2 +- polyp/module-tunnel.c | 6 +- polyp/module-waveout.c | 2 +- polyp/module-x11-bell.c | 3 +- polyp/namereg.c | 8 +- polyp/namereg.h | 8 +- polyp/native-common.h | 5 + polyp/pacat-simple.c | 2 +- polyp/pacat.c | 13 +- polyp/pactl.c | 77 ++--- polyp/paplay.c | 8 +- polyp/parec-simple.c | 2 +- polyp/parseaddr.h | 4 +- polyp/play-memchunk.c | 26 +- polyp/play-memchunk.h | 8 +- polyp/poll.c | 2 +- polyp/poll.h | 2 +- polyp/polyplib-context.c | 4 +- polyp/polyplib-context.h | 2 +- polyp/polyplib-def.h | 14 +- polyp/polyplib-internal.h | 15 +- polyp/polyplib-introspect.c | 28 +- polyp/polyplib-introspect.h | 46 +-- polyp/polyplib-operation.c | 4 +- polyp/polyplib-operation.h | 2 +- polyp/polyplib-simple.c | 13 +- polyp/polyplib-simple.h | 3 +- polyp/polyplib-stream.c | 39 ++- polyp/polyplib-stream.h | 19 +- polyp/polyplib-subscribe.c | 6 +- polyp/polyplib-subscribe.h | 4 +- polyp/protocol-esound.c | 40 +-- polyp/protocol-native.c | 108 ++++--- polyp/protocol-simple.c | 8 +- polyp/resampler.c | 572 ++++++++++++++++++++++++----------- polyp/resampler.h | 18 +- polyp/sample-util.c | 396 +++++++++++++----------- polyp/sample-util.h | 19 +- polyp/sample.c | 83 ++--- polyp/sample.h | 49 +-- polyp/scache.c | 21 +- polyp/scache.h | 7 +- polyp/sconv-s16be.c | 8 + polyp/sconv-s16be.h | 4 +- polyp/sconv-s16le.c | 64 ++-- polyp/sconv-s16le.h | 4 +- polyp/sconv.c | 155 +++------- polyp/sconv.h | 8 +- polyp/sink-input.c | 154 +++++++--- polyp/sink-input.h | 37 ++- polyp/sink.c | 226 +++++++++----- polyp/sink.h | 43 ++- polyp/socket-client.c | 4 +- polyp/socket-server.c | 2 +- polyp/sound-file-stream.c | 11 +- polyp/sound-file-stream.h | 2 +- polyp/source-output.c | 74 +++-- polyp/source-output.h | 26 +- polyp/source.c | 65 ++-- polyp/source.h | 29 +- polyp/subscribe.c | 10 +- polyp/subscribe.h | 4 +- polyp/tagstruct.c | 91 +++++- polyp/tagstruct.h | 6 + polyp/typeid.c | 33 -- polyp/typeid.h | 46 --- polyp/voltest.c | 17 +- polyp/volume.c | 176 +++++++++++ polyp/volume.h | 107 +++++++ polyp/x11prop.c | 2 +- polyp/x11wrap.c | 4 +- 114 files changed, 2584 insertions(+), 1329 deletions(-) create mode 100644 polyp/channelmap.c create mode 100644 polyp/channelmap.h delete mode 100644 polyp/typeid.c delete mode 100644 polyp/typeid.h create mode 100644 polyp/volume.c create mode 100644 polyp/volume.h diff --git a/configure.ac b/configure.ac index f2de16539..710f205b9 100644 --- a/configure.ac +++ b/configure.ac @@ -330,6 +330,11 @@ AC_SUBST(HOWL_LIBS) AC_SUBST(HAVE_HOWL) AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1]) + +PKG_CHECK_MODULES(LIBOIL, [ liboil-0.3 >= 0.3.0 ]) +AC_SUBST(LIBOIL_CFLAGS) +AC_SUBST(LIBOIL_LIBS) + #### Async DNS support (optional) #### PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, HAVE_LIBASYNCNS=0) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 0181ae6a9..ad9952a50 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -47,6 +47,7 @@ AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" +#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" @@ -101,10 +102,10 @@ polypaudio_SOURCES = \ main.c \ pid.c pid.h -polypaudio_CFLAGS = $(AM_CFLAGS) -polypaudio_CPPFLAGS = $(AM_CPPFLAGS) +polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) +polypaudio_CPPFLAGS = $(AM_CPPFLAGS) polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \ - $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) + $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f)) if PREOPEN_MODS @@ -219,7 +220,7 @@ strlist_test_CFLAGS = $(AM_CFLAGS) strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) strlist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -voltest_SOURCES = voltest.c sample.c +voltest_SOURCES = voltest.c sample.c volume.c volume.h sample.h voltest_CFLAGS = $(AM_CFLAGS) voltest_LDADD = $(AM_LDADD) voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -265,8 +266,7 @@ polypinclude_HEADERS = \ polyplib-stream.h \ polyplib-subscribe.h \ polyplib-version.h \ - sample.h \ - typeid.h + sample.h if HAVE_HOWL polypinclude_HEADERS += \ @@ -333,10 +333,11 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ strbuf.c strbuf.h \ strlist.c strlist.h \ tagstruct.c tagstruct.h \ - typeid.c typeid.h \ util.c util.h \ winsock.h \ - xmalloc.c xmalloc.h + xmalloc.c xmalloc.h \ + channelmap.c channelmap.h \ + volume.c volume.h if HAVE_X11 libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ @@ -475,14 +476,15 @@ libpolypcore_la_SOURCES = \ strbuf.c strbuf.h \ subscribe.c subscripe.h \ tokenizer.c tokenizer.h \ - typeid.c typeid.h \ util.c util.h \ winsock.h \ - xmalloc.c xmalloc.h + xmalloc.c xmalloc.h \ + volume.c volume.h \ + channelmap.c channelmap.h -libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS) +libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) libpolypcore_la_LDFLAGS = -avoid-version -libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) +libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) ################################### # Plug-in support libraries # diff --git a/polyp/alsa-util.c b/polyp/alsa-util.c index 73f3be7dd..cc65b8de8 100644 --- a/polyp/alsa-util.c +++ b/polyp/alsa-util.c @@ -85,7 +85,7 @@ finish: * *io_events. Store the length of that array in *n_io_events. Use the * specified callback function and userdata. The array has to be freed * with pa_free_io_events(). */ -int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api* m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata) { +int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api* m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata) { unsigned i; struct pollfd *pfds, *ppfd; pa_io_event **ios; diff --git a/polyp/alsa-util.h b/polyp/alsa-util.h index 787519f74..d180db3ec 100644 --- a/polyp/alsa-util.h +++ b/polyp/alsa-util.h @@ -29,7 +29,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); -int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api *m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata); +int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api *m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata); void pa_free_io_events(pa_mainloop_api* m, pa_io_event **io_sources, unsigned n_io_sources); #endif diff --git a/polyp/autoload.c b/polyp/autoload.c index 7e05c1689..ff2916cbf 100644 --- a/polyp/autoload.c +++ b/polyp/autoload.c @@ -81,7 +81,7 @@ static pa_autoload_entry* entry_new(pa_core *c, const char *name) { return e; } -int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const char*module, const char *argument, uint32_t *idx) { +int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const char*module, const char *argument, uint32_t *idx) { pa_autoload_entry *e = NULL; assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); @@ -98,7 +98,7 @@ int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const cha return 0; } -int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type type) { +int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type) { pa_autoload_entry *e; assert(c && name && type); @@ -120,7 +120,7 @@ int pa_autoload_remove_by_index(pa_core *c, uint32_t idx) { return 0; } -void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type type) { +void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type) { pa_autoload_entry *e; pa_module *m; assert(c && name); @@ -159,7 +159,7 @@ void pa_autoload_free(pa_core *c) { } } -const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type type) { +const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type_t type) { pa_autoload_entry *e; assert(c && name); diff --git a/polyp/autoload.h b/polyp/autoload.h index 622a854e5..7350c16a9 100644 --- a/polyp/autoload.h +++ b/polyp/autoload.h @@ -34,7 +34,7 @@ typedef struct pa_autoload_entry { pa_core *core; uint32_t index; char *name; - pa_namereg_type type; /* Type of the autoload entry */ + pa_namereg_type_t type; /* Type of the autoload entry */ int in_action; /* Currently loaded */ char *module, *argument; } pa_autoload_entry; @@ -42,17 +42,17 @@ typedef struct pa_autoload_entry { /* Add a new autoload entry of the given time, with the speicified * sink/source name, module name and argument. Return the entry's * index in *index */ -int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const char*module, const char *argument, uint32_t *idx); +int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const char*module, const char *argument, uint32_t *idx); /* Free all autoload entries */ void pa_autoload_free(pa_core *c); -int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type type); +int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type); int pa_autoload_remove_by_index(pa_core *c, uint32_t idx); /* Request an autoload entry by its name, effectively causing a module to be loaded */ -void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type type); +void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type); -const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type type); +const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type_t type); const pa_autoload_entry* pa_autoload_get_by_index(pa_core *c, uint32_t idx); #endif diff --git a/polyp/channelmap.c b/polyp/channelmap.c new file mode 100644 index 000000000..7bfd21e6e --- /dev/null +++ b/polyp/channelmap.c @@ -0,0 +1,202 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "channelmap.h" + +pa_channel_map* pa_channel_map_init(pa_channel_map *m) { + unsigned c; + assert(m); + + m->channels = 0; + + for (c = 0; c < PA_CHANNELS_MAX; c++) + m->map[c] = PA_CHANNEL_POSITION_INVALID; + + return m; +} + +pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) { + assert(m); + + pa_channel_map_init(m); + + m->channels = 1; + m->map[0] = PA_CHANNEL_POSITION_MONO; + return m; +} + +pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) { + assert(m); + + pa_channel_map_init(m); + + m->channels = 2; + m->map[0] = PA_CHANNEL_POSITION_LEFT; + m->map[1] = PA_CHANNEL_POSITION_RIGHT; + return m; +} + +pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels) { + assert(m); + assert(channels > 0); + assert(channels <= PA_CHANNELS_MAX); + + pa_channel_map_init(m); + + m->channels = channels; + + switch (channels) { + case 1: + m->map[0] = PA_CHANNEL_POSITION_MONO; + return m; + + case 8: + m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT; + m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT; + /* Fall through */ + + case 6: + m->map[5] = PA_CHANNEL_POSITION_LFE; + /* Fall through */ + + case 5: + m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER; + /* Fall through */ + + case 4: + m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT; + m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + /* Fall through */ + + case 2: + m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + return m; + + default: + return NULL; + } +} + +const char* pa_channel_position_to_string(pa_channel_position_t pos) { + + const char *const table[] = { + [PA_CHANNEL_POSITION_MONO] = "mono", + + [PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center", + [PA_CHANNEL_POSITION_FRONT_LEFT] = "front-left", + [PA_CHANNEL_POSITION_FRONT_RIGHT] = "front-right", + + [PA_CHANNEL_POSITION_REAR_CENTER] = "rear-center", + [PA_CHANNEL_POSITION_REAR_LEFT] = "rear-left", + [PA_CHANNEL_POSITION_REAR_RIGHT] = "rear-right", + + [PA_CHANNEL_POSITION_LFE] = "lfe", + + [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "front-left-of-center", + [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "front-right-of-center", + + [PA_CHANNEL_POSITION_SIDE_LEFT] = "side-left", + [PA_CHANNEL_POSITION_SIDE_RIGHT] = "side-right", + + [PA_CHANNEL_POSITION_AUX1] = "aux1", + [PA_CHANNEL_POSITION_AUX2] = "aux2", + [PA_CHANNEL_POSITION_AUX3] = "aux3", + [PA_CHANNEL_POSITION_AUX4] = "aux4", + [PA_CHANNEL_POSITION_AUX5] = "aux5", + [PA_CHANNEL_POSITION_AUX6] = "aux6", + [PA_CHANNEL_POSITION_AUX7] = "aux7", + [PA_CHANNEL_POSITION_AUX8] = "aux8", + [PA_CHANNEL_POSITION_AUX9] = "aux9", + [PA_CHANNEL_POSITION_AUX10] = "aux10", + [PA_CHANNEL_POSITION_AUX11] = "aux11", + [PA_CHANNEL_POSITION_AUX12] = "aux12" + }; + + if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX) + return NULL; + + return table[pos]; +} + +int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) { + unsigned c; + + assert(a); + assert(b); + + if (a->channels != b->channels) + return 0; + + for (c = 0; c < a->channels; c++) + if (a->map[c] != b->map[c]) + return 0; + + return 1; +} + +char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) { + unsigned channel; + int first = 1; + char *e; + + assert(s); + assert(l > 0); + assert(map); + + *(e = s) = 0; + + for (channel = 0; channel < map->channels && l > 1; channel++) { + l -= snprintf(e, l, "%s%u:%s", + first ? "" : " ", + channel, + pa_channel_position_to_string(map->map[channel])); + + e = strchr(e, 0); + first = 0; + } + + return s; +} + +int pa_channel_map_valid(const pa_channel_map *map) { + unsigned c; + + assert(map); + + if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX) + return 0; + + for (c = 0; c < map->channels; c++) + if (map->map[c] < 0 ||map->map[c] >= PA_CHANNEL_POSITION_MAX) + return 0; + + return 1; +} diff --git a/polyp/channelmap.h b/polyp/channelmap.h new file mode 100644 index 000000000..6466eecfd --- /dev/null +++ b/polyp/channelmap.h @@ -0,0 +1,94 @@ +#ifndef foochannelmaphfoo +#define foochannelmaphfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +/** \file + * Constants and routines for channel mapping handling */ + +PA_C_DECL_BEGIN + +typedef enum { + PA_CHANNEL_POSITION_INVALID = -1, + PA_CHANNEL_POSITION_MONO = 0, + + PA_CHANNEL_POSITION_LEFT, + PA_CHANNEL_POSITION_RIGHT, + + PA_CHANNEL_POSITION_FRONT_CENTER, + PA_CHANNEL_POSITION_FRONT_LEFT = PA_CHANNEL_POSITION_LEFT, + PA_CHANNEL_POSITION_FRONT_RIGHT = PA_CHANNEL_POSITION_RIGHT, + + PA_CHANNEL_POSITION_REAR_CENTER, + PA_CHANNEL_POSITION_REAR_LEFT, + PA_CHANNEL_POSITION_REAR_RIGHT, + + PA_CHANNEL_POSITION_LFE, + PA_CHANNEL_POSITION_SUBWOOFER = PA_CHANNEL_POSITION_LFE, + + PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, + + PA_CHANNEL_POSITION_SIDE_LEFT, + PA_CHANNEL_POSITION_SIDE_RIGHT, + + PA_CHANNEL_POSITION_AUX1, + PA_CHANNEL_POSITION_AUX2, + PA_CHANNEL_POSITION_AUX3, + PA_CHANNEL_POSITION_AUX4, + PA_CHANNEL_POSITION_AUX5, + PA_CHANNEL_POSITION_AUX6, + PA_CHANNEL_POSITION_AUX7, + PA_CHANNEL_POSITION_AUX8, + PA_CHANNEL_POSITION_AUX9, + PA_CHANNEL_POSITION_AUX10, + PA_CHANNEL_POSITION_AUX11, + PA_CHANNEL_POSITION_AUX12, + + PA_CHANNEL_POSITION_MAX +} pa_channel_position_t; + +typedef struct pa_channel_map { + uint8_t channels; + pa_channel_position_t map[PA_CHANNELS_MAX]; +} pa_channel_map; + +pa_channel_map* pa_channel_map_init(pa_channel_map *m); +pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m); +pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m); +pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels); + +const char* pa_channel_position_to_string(pa_channel_position_t pos); + +#define PA_CHANNEL_MAP_SNPRINT_MAX 64 +char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map); + +int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b); + +int pa_channel_map_valid(const pa_channel_map *map); + +PA_C_DECL_END + +#endif diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 63241a815..f6192bf87 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -311,6 +311,7 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu const char *n, *v; pa_sink *sink; uint32_t volume; + pa_cvolume cvolume; if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n"); @@ -332,14 +333,16 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return -1; } - pa_sink_set_volume(sink, (uint32_t) volume); + pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume); + pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &cvolume); return 0; } static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const char *n, *v; pa_sink_input *si; - uint32_t volume; + pa_volume_t volume; + pa_cvolume cvolume; uint32_t idx; if (!(n = pa_tokenizer_get(t, 1))) { @@ -367,7 +370,8 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb return -1; } - pa_sink_input_set_volume(si, (uint32_t) volume); + pa_cvolume_set(&cvolume, si->sample_spec.channels, volume); + pa_sink_input_set_volume(si, &cvolume); return 0; } @@ -497,7 +501,7 @@ static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return -1; } - if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM) < 0) { + if (pa_scache_play_item(c, n, sink, NULL) < 0) { pa_strbuf_puts(buf, "Failed to play sample.\n"); return -1; } @@ -576,7 +580,7 @@ static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, } - return pa_play_file(sink, fname, PA_VOLUME_NORM); + return pa_play_file(sink, fname, NULL); } static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { @@ -663,9 +667,6 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G nl = 0; for (s = pa_idxset_first(c->sinks, &idx); s; s = pa_idxset_next(c->sinks, &idx)) { - if (s->volume == PA_VOLUME_NORM) - continue; - if (s->owner && s->owner->auto_unload) continue; @@ -673,8 +674,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_strbuf_puts(buf, "\n"); nl = 1; } - - pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", s->name, s->volume); + + pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", s->name, pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE))); } diff --git a/polyp/cli-text.c b/polyp/cli-text.c index a19bfc971..328aca4cf 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -38,6 +38,7 @@ #include "scache.h" #include "autoload.h" #include "xmalloc.h" +#include "volume.h" char *pa_module_list_to_string(pa_core *c) { pa_strbuf *s; @@ -60,7 +61,6 @@ char *pa_client_list_to_string(pa_core *c) { pa_strbuf *s; pa_client *client; uint32_t idx = PA_IDXSET_INVALID; - char tid[5]; assert(c); s = pa_strbuf_new(); @@ -69,7 +69,7 @@ char *pa_client_list_to_string(pa_core *c) { pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_size(c->clients)); for (client = pa_idxset_first(c->clients, &idx); client; client = pa_idxset_next(c->clients, &idx)) { - pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\ttype: <%s>\n", client->index, client->name, pa_typeid_to_string(client->typeid, tid, sizeof(tid))); + pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tdriver: <%s>\n", client->index, client->name, client->driver); if (client->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index); @@ -82,7 +82,6 @@ char *pa_sink_list_to_string(pa_core *c) { pa_strbuf *s; pa_sink *sink; uint32_t idx = PA_IDXSET_INVALID; - char tid[5]; assert(c); s = pa_strbuf_new(); @@ -91,20 +90,26 @@ char *pa_sink_list_to_string(pa_core *c) { pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks)); for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) { - char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; - pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec); - assert(sink->monitor_source); + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + pa_strbuf_printf( s, - " %c index: %u\n\tname: <%s>\n\ttype: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", + " %c index: %u\n" + "\tname: <%s>\n" + "\tdriver: <%s>\n" + "\tvolume: <%s>\n" + "\tlatency: <%0.0f usec>\n" + "\tmonitor_source: <%u>\n" + "\tsample spec: <%s>\n" + "\tchannel map: <%s>\n", c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', sink->index, sink->name, - pa_typeid_to_string(sink->typeid, tid, sizeof(tid)), - (unsigned) sink->volume, - pa_volume_to_dB(sink->volume), + sink->driver, + pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, PA_MIXER_HARDWARE)), (double) pa_sink_get_latency(sink), sink->monitor_source->index, - ss); + pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &sink->channel_map)); if (sink->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", sink->owner->index); @@ -119,7 +124,6 @@ char *pa_source_list_to_string(pa_core *c) { pa_strbuf *s; pa_source *source; uint32_t idx = PA_IDXSET_INVALID; - char tid[5]; assert(c); s = pa_strbuf_new(); @@ -128,15 +132,24 @@ char *pa_source_list_to_string(pa_core *c) { pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources)); for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) { - char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; - pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec); - pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\ttype: <%s>\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n", - c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ', - source->index, - source->name, - pa_typeid_to_string(source->typeid, tid, sizeof(tid)), - (double) pa_source_get_latency(source), - ss); + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + + + pa_strbuf_printf( + s, + " %c index: %u\n" + "\tname: <%s>\n" + "\tdriver: <%s>\n" + "\tlatency: <%0.0f usec>\n" + "\tsample spec: <%s>\n" + "\tchannel map: <%s>\n", + c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ', + source->index, + source->name, + source->driver, + (double) pa_source_get_latency(source), + pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map)); if (source->monitor_of) pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index); @@ -154,7 +167,6 @@ char *pa_source_output_list_to_string(pa_core *c) { pa_strbuf *s; pa_source_output *o; uint32_t idx = PA_IDXSET_INVALID; - char tid[5]; static const char* const state_table[] = { "RUNNING", "CORKED", @@ -168,23 +180,28 @@ char *pa_source_output_list_to_string(pa_core *c) { pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_size(c->source_outputs)); for (o = pa_idxset_first(c->source_outputs, &idx); o; o = pa_idxset_next(c->source_outputs, &idx)) { - char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; - const char *rm; - pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec); + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + assert(o->source); - - if (!(rm = pa_resample_method_to_string(pa_source_output_get_resample_method(o)))) - rm = "invalid"; pa_strbuf_printf( - s, " index: %u\n\tname: '%s'\n\ttype: <%s>\n\tstate: %s\n\tsource: <%u> '%s'\n\tsample_spec: <%s>\n\tresample method: %s\n", + s, + " index: %u\n" + "\tname: '%s'\n" + "\tdriver: <%s>\n" + "\tstate: %s\n" + "\tsource: <%u> '%s'\n" + "\tsample spec: <%s>\n" + "\tchannel map: <%s>\n" + "\tresample method: %s\n", o->index, o->name, - pa_typeid_to_string(o->typeid, tid, sizeof(tid)), + o->driver, state_table[o->state], o->source->index, o->source->name, - ss, - rm); + pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map), + pa_resample_method_to_string(pa_source_output_get_resample_method(o))); if (o->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", o->owner->index); if (o->client) @@ -198,7 +215,6 @@ char *pa_sink_input_list_to_string(pa_core *c) { pa_strbuf *s; pa_sink_input *i; uint32_t idx = PA_IDXSET_INVALID; - char tid[5]; static const char* const state_table[] = { "RUNNING", "CORKED", @@ -212,26 +228,32 @@ char *pa_sink_input_list_to_string(pa_core *c) { pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs)); for (i = pa_idxset_first(c->sink_inputs, &idx); i; i = pa_idxset_next(c->sink_inputs, &idx)) { - char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; - const char *rm; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; - if (!(rm = pa_resample_method_to_string(pa_sink_input_get_resample_method(i)))) - rm = "invalid"; - - pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); + pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\ttype: <%s>\n\tstate: %s\n\tsink: <%u> '%s'\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n\tresample method: %s\n", + s, + " index: %u\n" + "\tname: <%s>\n" + "\tdriver: <%s>\n" + "\tstate: %s\n" + "\tsink: <%u> '%s'\n" + "\tvolume: <%s>\n" + "\tlatency: <%0.0f usec>\n" + "\tsample spec: <%s>\n" + "\tchannel map: <%s>\n" + "\tresample method: %s\n", i->index, i->name, - pa_typeid_to_string(i->typeid, tid, sizeof(tid)), + i->driver, state_table[i->state], i->sink->index, i->sink->name, - (unsigned) i->volume, - pa_volume_to_dB(i->volume), + pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)), (double) pa_sink_input_get_latency(i), - ss, - rm); + pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), + pa_resample_method_to_string(pa_sink_input_get_resample_method(i))); if (i->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", i->owner->index); @@ -257,21 +279,32 @@ char *pa_scache_list_to_string(pa_core *c) { for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) { double l = 0; - char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a"; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; if (e->memchunk.memblock) { pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec); + pa_channel_map_snprint(cm, sizeof(cm), &e->channel_map); l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec); } pa_strbuf_printf( - s, " name: <%s>\n\tindex: <%u>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n\tlazy: %s\n\tfilename: %s\n", + s, + " name: <%s>\n" + "\tindex: <%u>\n" + "\tsample spec: <%s>\n" + "\tchannel map: <%s>\n" + "\tlength: <%u>\n" + "\tduration: <%0.1fs>\n" + "\tvolume: <%s>\n" + "\tlazy: %s\n" + "\tfilename: %s\n", e->name, e->index, ss, + cm, e->memchunk.memblock ? e->memchunk.length : 0, l, - e->volume, + pa_cvolume_snprint(cv, sizeof(cv), &e->volume), e->lazy ? "yes" : "no", e->filename ? e->filename : "n/a"); } diff --git a/polyp/cli.c b/polyp/cli.c index 7b1022c1a..bc0c285d3 100644 --- a/polyp/cli.c +++ b/polyp/cli.c @@ -45,7 +45,6 @@ #include "log.h" #define PROMPT ">>> " -#define PA_TYPEID_CLI PA_TYPEID_MAKE('C', 'L', 'I', '_') struct pa_cli { pa_core *core; @@ -76,7 +75,7 @@ pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) { c->eof_callback = NULL; pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); - c->client = pa_client_new(core, PA_TYPEID_CLI, cname); + c->client = pa_client_new(core, __FILE__, cname); assert(c->client); c->client->kill = client_kill; c->client->userdata = c; diff --git a/polyp/client.c b/polyp/client.c index 1938a4e0c..3c2084bfb 100644 --- a/polyp/client.c +++ b/polyp/client.c @@ -33,16 +33,16 @@ #include "subscribe.h" #include "log.h" -pa_client *pa_client_new(pa_core *core, pa_typeid_t typeid, const char *name) { +pa_client *pa_client_new(pa_core *core, const char *name, const char *driver) { pa_client *c; int r; assert(core); c = pa_xmalloc(sizeof(pa_client)); c->name = pa_xstrdup(name); + c->driver = pa_xstrdup(driver); c->owner = NULL; c->core = core; - c->typeid = typeid; c->kill = NULL; c->userdata = NULL; @@ -68,8 +68,8 @@ void pa_client_free(pa_client *c) { pa_log_info(__FILE__": freed %u \"%s\"\n", c->index, c->name); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_xfree(c->name); + pa_xfree(c->driver); pa_xfree(c); - } void pa_client_kill(pa_client *c) { diff --git a/polyp/client.h b/polyp/client.h index 198dbbf66..92430338f 100644 --- a/polyp/client.h +++ b/polyp/client.h @@ -24,7 +24,6 @@ #include "core.h" #include "module.h" -#include "typeid.h" /* Every connection to the server should have a pa_client * attached. That way the user may generate a listing of all connected @@ -34,17 +33,16 @@ typedef struct pa_client pa_client; struct pa_client { uint32_t index; - pa_typeid_t typeid; pa_module *owner; - char *name; + char *name, *driver; pa_core *core; void (*kill)(pa_client *c); void *userdata; }; -pa_client *pa_client_new(pa_core *c, pa_typeid_t typeid, const char *name); +pa_client *pa_client_new(pa_core *c, const char *name, const char *driver); /* This function should be called only by the code that created the client */ void pa_client_free(pa_client *c); diff --git a/polyp/core.h b/polyp/core.h index 704246a9f..9241fcd8f 100644 --- a/polyp/core.h +++ b/polyp/core.h @@ -70,7 +70,7 @@ struct pa_core { pa_time_event *scache_auto_unload_event; - pa_resample_method resample_method; + pa_resample_method_t resample_method; }; pa_core* pa_core_new(pa_mainloop_api *m); diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c index 4ad78bab5..103cf46a4 100644 --- a/polyp/daemon-conf.c +++ b/polyp/daemon-conf.c @@ -126,7 +126,7 @@ int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) { if (u >= PA_LOG_LEVEL_MAX) return -1; - c->log_level = (pa_log_level) u; + c->log_level = (pa_log_level_t) u; } else if (pa_startswith(string, "debug")) c->log_level = PA_LOG_DEBUG; else if (pa_startswith(string, "info")) diff --git a/polyp/daemon-conf.h b/polyp/daemon-conf.h index 4eb61365d..cebc0bd63 100644 --- a/polyp/daemon-conf.h +++ b/polyp/daemon-conf.h @@ -33,11 +33,11 @@ typedef enum pa_daemon_conf_cmd { PA_CMD_DUMP_MODULES, PA_CMD_KILL, PA_CMD_CHECK -} pa_daemon_conf_cmd; +} pa_daemon_conf_cmd_t; /* A structure containing configuration data for the Polypaudio server . */ typedef struct pa_daemon_conf { - pa_daemon_conf_cmd cmd; + pa_daemon_conf_cmd_t cmd; int daemonize, fail, high_priority, @@ -48,8 +48,8 @@ typedef struct pa_daemon_conf { auto_log_target, use_pid_file; char *script_commands, *dl_search_path, *default_script_file; - pa_log_target log_target; - pa_log_level log_level; + pa_log_target_t log_target; + pa_log_level_t log_level; int resample_method; char *config_file; } pa_daemon_conf; diff --git a/polyp/dllmain.c b/polyp/dllmain.c index 34d0eed11..d1d120ab8 100644 --- a/polyp/dllmain.c +++ b/polyp/dllmain.c @@ -1,4 +1,4 @@ -/* $Id: dllmain.c 317 2004-12-11 00:10:41Z lennart $ */ +/* $Id$ */ /*** This file is part of polypaudio. diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c index 6552da15c..6f7c1dc54 100644 --- a/polyp/glib-mainloop.c +++ b/polyp/glib-mainloop.c @@ -38,9 +38,9 @@ struct pa_io_event { GSource *source; GIOCondition io_condition; int fd; - void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata); + void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata); void *userdata; - void (*destroy_callback) (pa_mainloop_api *m, pa_io_event*e, void *userdata); + void (*destroy_callback) (pa_mainloop_api *m, pa_io_event *e, void *userdata); pa_io_event *next, *prev; }; @@ -76,9 +76,9 @@ struct pa_glib_mainloop { static void schedule_free_dead_events(pa_glib_mainloop *g); -static void glib_io_enable(pa_io_event*e, pa_io_event_flags f); +static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f); -static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags f, void *userdata), void *userdata) { +static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags_t f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata), void *userdata) { pa_io_event *e; pa_glib_mainloop *g; @@ -111,7 +111,7 @@ static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f, /* The callback GLIB calls whenever an IO condition is met */ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) { pa_io_event *e = data; - pa_io_event_flags f; + pa_io_event_flags_t f; assert(source && e && e->io_channel == source); f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) | @@ -123,7 +123,7 @@ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) return TRUE; } -static void glib_io_enable(pa_io_event*e, pa_io_event_flags f) { +static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) { GIOCondition c; assert(e && !e->dead); diff --git a/polyp/glib12-mainloop.c b/polyp/glib12-mainloop.c index e322ac075..8bc4483bb 100644 --- a/polyp/glib12-mainloop.c +++ b/polyp/glib12-mainloop.c @@ -39,7 +39,7 @@ struct pa_io_event { guint source; GIOCondition io_condition; int fd; - void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata); + void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata); void *userdata; void (*destroy_callback) (pa_mainloop_api *m, pa_io_event*e, void *userdata); pa_io_event *next, *prev; @@ -76,9 +76,9 @@ struct pa_glib_mainloop { static void schedule_free_dead_events(pa_glib_mainloop *g); -static void glib_io_enable(pa_io_event*e, pa_io_event_flags f); +static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f); -static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags f, void *userdata), void *userdata) { +static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags_t f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata), void *userdata) { pa_io_event *e; pa_glib_mainloop *g; @@ -110,7 +110,7 @@ static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f, static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) { pa_io_event *e = data; - pa_io_event_flags f; + pa_io_event_flags_t f; assert(source && e && e->io_channel == source); f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) | @@ -122,7 +122,7 @@ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) return TRUE; } -static void glib_io_enable(pa_io_event*e, pa_io_event_flags f) { +static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) { GIOCondition c; assert(e && !e->dead); diff --git a/polyp/inet_ntop.c b/polyp/inet_ntop.c index ac2b5295a..a25c3c951 100644 --- a/polyp/inet_ntop.c +++ b/polyp/inet_ntop.c @@ -1,4 +1,4 @@ -/* $Id: inet_ntop.c 428 2006-01-09 16:50:39Z ossman $ */ +/* $Id$ */ /*** This file is part of polypaudio. diff --git a/polyp/iochannel.c b/polyp/iochannel.c index e62713190..273d47e0d 100644 --- a/polyp/iochannel.c +++ b/polyp/iochannel.c @@ -55,7 +55,7 @@ static void enable_mainloop_sources(pa_iochannel *io) { assert(io); if (io->input_event == io->output_event && io->input_event) { - pa_io_event_flags f = PA_IO_EVENT_NULL; + pa_io_event_flags_t f = PA_IO_EVENT_NULL; assert(io->input_event); if (!io->readable) @@ -72,7 +72,7 @@ static void enable_mainloop_sources(pa_iochannel *io) { } } -static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) { +static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { pa_iochannel *io = userdata; int changed = 0; diff --git a/polyp/log.c b/polyp/log.c index c41fbbaec..97406f799 100644 --- a/polyp/log.c +++ b/polyp/log.c @@ -38,9 +38,9 @@ #define ENV_LOGLEVEL "POLYP_LOG" static char *log_ident = NULL; -static pa_log_target log_target = PA_LOG_STDERR; -static void (*user_log_func)(pa_log_level l, const char *s) = NULL; -static pa_log_level maximal_level = PA_LOG_NOTICE; +static pa_log_target_t log_target = PA_LOG_STDERR; +static void (*user_log_func)(pa_log_level_t l, const char *s) = NULL; +static pa_log_level_t maximal_level = PA_LOG_NOTICE; #ifdef HAVE_SYSLOG_H static const int level_to_syslog[] = { @@ -59,18 +59,18 @@ void pa_log_set_ident(const char *p) { log_ident = pa_xstrdup(p); } -void pa_log_set_maximal_level(pa_log_level l) { +void pa_log_set_maximal_level(pa_log_level_t l) { assert(l < PA_LOG_LEVEL_MAX); maximal_level = l; } -void pa_log_set_target(pa_log_target t, void (*func)(pa_log_level l, const char*s)) { +void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t l, const char*s)) { assert(t == PA_LOG_USER || !func); log_target = t; user_log_func = func; } -void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap) { +void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { const char *e; assert(level < PA_LOG_LEVEL_MAX); @@ -107,44 +107,44 @@ void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap) { } -void pa_log_with_level(pa_log_level level, const char *format, ...) { +void pa_log_level(pa_log_level_t level, const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_with_levelv(level, format, ap); + pa_log_levelv(level, format, ap); va_end(ap); } void pa_log_debug(const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_with_levelv(PA_LOG_DEBUG, format, ap); + pa_log_levelv(PA_LOG_DEBUG, format, ap); va_end(ap); } void pa_log_info(const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_with_levelv(PA_LOG_INFO, format, ap); + pa_log_levelv(PA_LOG_INFO, format, ap); va_end(ap); } void pa_log_notice(const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_with_levelv(PA_LOG_INFO, format, ap); + pa_log_levelv(PA_LOG_INFO, format, ap); va_end(ap); } void pa_log_warn(const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_with_levelv(PA_LOG_WARN, format, ap); + pa_log_levelv(PA_LOG_WARN, format, ap); va_end(ap); } void pa_log_error(const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_with_levelv(PA_LOG_ERROR, format, ap); + pa_log_levelv(PA_LOG_ERROR, format, ap); va_end(ap); } diff --git a/polyp/log.h b/polyp/log.h index 7c6a8e614..ce8aea986 100644 --- a/polyp/log.h +++ b/polyp/log.h @@ -33,7 +33,7 @@ typedef enum pa_log_target { PA_LOG_SYSLOG, PA_LOG_USER, /* to user specified function */ PA_LOG_NULL /* to /dev/null */ -} pa_log_target; +} pa_log_target_t; typedef enum pa_log_level { PA_LOG_ERROR = 0, /* Error messages */ @@ -42,16 +42,16 @@ typedef enum pa_log_level { PA_LOG_INFO = 3, /* Info messages */ PA_LOG_DEBUG = 4, /* debug message */ PA_LOG_LEVEL_MAX -} pa_log_level; +} pa_log_level_t; /* Set an identification for the current daemon. Used when logging to syslog. */ void pa_log_set_ident(const char *p); /* Set another log target. If t is PA_LOG_USER you may specify a function that is called every log string */ -void pa_log_set_target(pa_log_target t, void (*func)(pa_log_level, const char*s)); +void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t t, const char*s)); /* Minimal log level */ -void pa_log_set_maximal_level(pa_log_level l); +void pa_log_set_maximal_level(pa_log_level_t l); /* Do a log line */ void pa_log_debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); @@ -60,9 +60,9 @@ void pa_log_notice(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); void pa_log_warn(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); void pa_log_error(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); -void pa_log_with_level(pa_log_level level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); +void pa_log_level(pa_log_level_t level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); -void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap); +void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap); #define pa_log pa_log_error diff --git a/polyp/main.c b/polyp/main.c index 1c3b566d8..c984e28e0 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef HAVE_SYS_IOCTL_H #include @@ -386,6 +387,8 @@ int main(int argc, char *argv[]) { pa_signal_new(SIGHUP, signal_callback, c); #endif + oil_init(); + r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop)); assert(r == 0); diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h index 1604e7406..91ee41114 100644 --- a/polyp/mainloop-api.h +++ b/polyp/mainloop-api.h @@ -51,7 +51,7 @@ typedef enum pa_io_event_flags { PA_IO_EVENT_OUTPUT = 2, /**< Output event */ PA_IO_EVENT_HANGUP = 4, /**< Hangup event */ PA_IO_EVENT_ERROR = 8 /**< Error event */ -} pa_io_event_flags; +} pa_io_event_flags_t; /** \pa_io_event * An opaque IO event source object */ @@ -73,10 +73,10 @@ struct pa_mainloop_api { void *userdata; /** Create a new IO event source object */ - pa_io_event* (*io_new)(pa_mainloop_api*a, int fd, pa_io_event_flags events, void (*callback) (pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags events, void *userdata), void *userdata); + pa_io_event* (*io_new)(pa_mainloop_api*a, int fd, pa_io_event_flags_t events, void (*callback) (pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata); /** Enable or disable IO events on this object */ - void (*io_enable)(pa_io_event* e, pa_io_event_flags events); + void (*io_enable)(pa_io_event* e, pa_io_event_flags_t events); /** Free a IO event source object */ void (*io_free)(pa_io_event* e); diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c index f225e60b4..769360311 100644 --- a/polyp/mainloop-signal.c +++ b/polyp/mainloop-signal.c @@ -119,7 +119,7 @@ static void defer(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event*e, PA_GCC_UNUS } } -static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags f, PA_GCC_UNUSED void *userdata) { +static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, PA_GCC_UNUSED void *userdata) { ssize_t r; int sig; assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); diff --git a/polyp/mainloop-test.c b/polyp/mainloop-test.c index 097ce1c79..ee0f8711a 100644 --- a/polyp/mainloop-test.c +++ b/polyp/mainloop-test.c @@ -51,7 +51,7 @@ static GMainLoop* glib_main_loop = NULL; static pa_defer_event *de; -static void iocb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) { +static void iocb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { unsigned char c; read(fd, &c, sizeof(c)); fprintf(stderr, "IO EVENT: %c\n", c < 32 ? '.' : c); diff --git a/polyp/mainloop.c b/polyp/mainloop.c index 599a90f85..26ba2425e 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -50,8 +50,8 @@ struct pa_io_event { pa_mainloop *mainloop; int dead; int fd; - pa_io_event_flags events; - void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata); + pa_io_event_flags_t events; + void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata); struct pollfd *pollfd; void *userdata; void (*destroy_callback) (pa_mainloop_api*a, pa_io_event *e, void *userdata); @@ -91,7 +91,13 @@ struct pa_mainloop { }; /* IO events */ -static pa_io_event* mainloop_io_new(pa_mainloop_api*a, int fd, pa_io_event_flags events, void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata) { +static pa_io_event* mainloop_io_new( + pa_mainloop_api*a, + int fd, + pa_io_event_flags_t events, + void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), + void *userdata) { + pa_mainloop *m; pa_io_event *e; @@ -135,7 +141,7 @@ static pa_io_event* mainloop_io_new(pa_mainloop_api*a, int fd, pa_io_event_flags return e; } -static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags events) { +static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { assert(e && e->mainloop); e->events = events; diff --git a/polyp/memblock.h b/polyp/memblock.h index cbf5d6843..c57514065 100644 --- a/polyp/memblock.h +++ b/polyp/memblock.h @@ -31,12 +31,12 @@ * memory blocks. */ /* The type of memory this block points to */ -typedef enum { +typedef enum pa_memblock_type { PA_MEMBLOCK_FIXED, /* data is a pointer to fixed memory that needs not to be freed */ PA_MEMBLOCK_APPENDED, /* The most common kind: the data is appended to the memory block */ PA_MEMBLOCK_DYNAMIC, /* data is a pointer to some memory allocated with pa_xmalloc() */ PA_MEMBLOCK_USER /* User supplied memory, to be freed with free_cb */ -} pa_memblock_type ; +} pa_memblock_type_t; /* A structure of keeping memory block statistics */ /* Maintains statistics about memory blocks */ @@ -49,7 +49,7 @@ typedef struct pa_memblock_stat { } pa_memblock_stat; typedef struct pa_memblock { - pa_memblock_type type; + pa_memblock_type_t type; unsigned ref; /* the reference counter */ int read_only; /* boolean */ size_t length; diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 14070d635..ea6ca4246 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -51,8 +51,6 @@ PA_MODULE_DESCRIPTION("ALSA Sink") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= device= format= channels= rate= fragments= fragment_size=") -#define PA_TYPEID_ALSA PA_TYPEID_MAKE('A', 'L', 'S', 'A') - struct userdata { snd_pcm_t *pcm_handle; pa_sink *sink; @@ -142,7 +140,7 @@ static void do_write(struct userdata *u) { } } -static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { +static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { struct userdata *u = userdata; assert(u && a && e); @@ -220,7 +218,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - u->sink = pa_sink_new(c, PA_TYPEID_ALSA, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; @@ -236,7 +234,7 @@ int pa__init(pa_core *c, pa_module*m) { u->frame_size = frame_size; u->fragment_size = period_size; - pa_log(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); + pa_log_info(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size, c->memblock_stat); assert(u->silence.memblock); diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 4ad8dd84c..2aa47aadd 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -51,8 +51,6 @@ PA_MODULE_DESCRIPTION("ALSA Source") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("source_name= device= format= channels= rate= fragments= fragment_size=") -#define PA_TYPEID_ALSA PA_TYPEID_MAKE('A', 'L', 'S', 'A') - struct userdata { snd_pcm_t *pcm_handle; pa_source *source; @@ -142,7 +140,7 @@ static void do_read(struct userdata *u) { } } -static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { +static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { struct userdata *u = userdata; assert(u && a && e); @@ -211,7 +209,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - u->source = pa_source_new(c, PA_TYPEID_ALSA, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); assert(u->source); u->source->userdata = u; diff --git a/polyp/module-combine.c b/polyp/module-combine.c index cee0a5dc3..0c21c2f55 100644 --- a/polyp/module-combine.c +++ b/polyp/module-combine.c @@ -43,8 +43,6 @@ PA_MODULE_DESCRIPTION("Combine multiple sinks to one") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= master= slaves= adjust_time= resample_method=") -#define PA_TYPEID_COMBINE PA_TYPEID_MAKE('C', 'M', 'B', 'N') - #define DEFAULT_SINK_NAME "combined" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define RENDER_SIZE (1024*10) @@ -216,7 +214,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample o->memblockq = pa_memblockq_new(MEMBLOCKQ_MAXLENGTH, MEMBLOCKQ_MAXLENGTH, pa_frame_size(&u->sink->sample_spec), 0, 0, sink->core->memblock_stat); snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1); - if (!(o->sink_input = pa_sink_input_new(sink, PA_TYPEID_COMBINE, t, &u->sink->sample_spec, 1, resample_method))) + if (!(o->sink_input = pa_sink_input_new(sink, __FILE__, t, &u->sink->sample_spec, &u->sink->channel_map, 1, resample_method))) goto fail; o->sink_input->get_latency = sink_input_get_latency_cb; @@ -327,7 +325,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (!(u->sink = pa_sink_new(c, PA_TYPEID_COMBINE, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec, &master_sink->channel_map))) { pa_log(__FILE__": failed to create sink\n"); goto fail; } diff --git a/polyp/module-esound-sink.c b/polyp/module-esound-sink.c index ac211a316..afd5feed8 100644 --- a/polyp/module-esound-sink.c +++ b/polyp/module-esound-sink.c @@ -46,14 +46,12 @@ #include "authkey.h" PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Esound ") +PA_MODULE_DESCRIPTION("ESOUND Sink") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= server=
    cookie= format= channels= rate=") #define DEFAULT_SINK_NAME "esound_output" -#define PA_TYPEID_ESOUND_SINK PA_TYPEID_MAKE('E', 'S', 'D', 'S') - struct userdata { pa_core *core; @@ -354,7 +352,7 @@ int pa__init(pa_core *c, pa_module*m) { u->state = STATE_AUTH; u->latency = 0; - if (!(u->sink = pa_sink_new(c, PA_TYPEID_ESOUND_SINK, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { pa_log(__FILE__": failed to create sink.\n"); goto fail; } diff --git a/polyp/module-lirc.c b/polyp/module-lirc.c index eb71c47f5..d2e248aa0 100644 --- a/polyp/module-lirc.c +++ b/polyp/module-lirc.c @@ -61,7 +61,7 @@ struct userdata { static int lirc_in_use = 0; -static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags events, void*userdata) { +static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) { struct userdata *u = userdata; char *name = NULL, *code = NULL; assert(io); @@ -109,26 +109,45 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name); else { - double v = pa_volume_to_user(s->volume); - + pa_volume_t v = pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE)); + pa_cvolume cv; +#define DELTA (PA_VOLUME_NORM/20) + switch (volchange) { - case UP: v += .05; break; - case DOWN: v -= .05; break; - case MUTE: v = 0; break; - case RESET: v = 1; break; + case UP: + v += PA_VOLUME_NORM/20; + break; + + case DOWN: + if (v > DELTA) + v -= DELTA; + else + v = PA_VOLUME_MUTED; + + break; + + case MUTE: + v = PA_VOLUME_MUTED; + break; + + case RESET: + v = PA_VOLUME_NORM; + break; + case MUTE_TOGGLE: { if (v > 0) { u->mute_toggle_save = v; - v = 0; + v = PA_VOLUME_MUTED; } else v = u->mute_toggle_save; } default: ; } - - pa_sink_set_volume(s, pa_volume_from_user(v)); + + pa_cvolume_set(&cv, PA_CHANNELS_MAX, v); + pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); } } } diff --git a/polyp/module-match.c b/polyp/module-match.c index e48d55ca0..e3e7b17d2 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -154,7 +154,7 @@ finish: return ret; } -static void callback(pa_core *c, pa_subscription_event_type t, uint32_t idx, void *userdata) { +static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = userdata; pa_sink_input *si; struct rule *r; @@ -171,8 +171,10 @@ static void callback(pa_core *c, pa_subscription_event_type t, uint32_t idx, voi for (r = u->rules; r; r = r->next) { if (!regexec(&r->regex, si->name, 0, NULL, 0)) { + pa_cvolume cv; pa_log_debug(__FILE__": changing volume of sink input '%s' to 0x%03x\n", si->name, r->volume); - pa_sink_input_set_volume(si, r->volume); + pa_cvolume_set(&cv, r->volume, si->sample_spec.channels); + pa_sink_input_set_volume(si, &cv); } } } diff --git a/polyp/module-mmkbd-evdev.c b/polyp/module-mmkbd-evdev.c index 5eb55e35c..ec45ec4b9 100644 --- a/polyp/module-mmkbd-evdev.c +++ b/polyp/module-mmkbd-evdev.c @@ -74,7 +74,7 @@ struct userdata { float mute_toggle_save; }; -static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags events, void*userdata) { +static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) { struct userdata *u = userdata; assert(io); assert(u); @@ -109,16 +109,28 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name); else { - double v = pa_volume_to_user(s->volume); + pa_volume_t v = pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE)); + pa_cvolume cv; +#define DELTA (PA_VOLUME_NORM/20) switch (volchange) { - case UP: v += .05; break; - case DOWN: v -= .05; break; + case UP: + v += DELTA; + break; + + case DOWN: + if (v > DELTA) + v -= DELTA; + else + v = PA_VOLUME_MUTED; + + break; + case MUTE_TOGGLE: { if (v > 0) { u->mute_toggle_save = v; - v = 0; + v = PA_VOLUME_MUTED; } else v = u->mute_toggle_save; } @@ -126,7 +138,8 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC ; } - pa_sink_set_volume(s, pa_volume_from_user(v)); + pa_cvolume_set(&cv, PA_CHANNELS_MAX, v); + pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); } } } diff --git a/polyp/module-null-sink.c b/polyp/module-null-sink.c index b26ea50bd..93abca78d 100644 --- a/polyp/module-null-sink.c +++ b/polyp/module-null-sink.c @@ -49,8 +49,6 @@ PA_MODULE_USAGE("format= channels= rate=module = m; m->userdata = u; - if (!(u->sink = pa_sink_new(c, PA_TYPEID_NULL, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { pa_log(__FILE__": failed to create sink.\n"); goto fail; } diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index ac510f96c..f976cf81c 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -53,8 +53,6 @@ PA_MODULE_DESCRIPTION("OSS Sink/Source (mmap)") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= fragments= fragment_size=") -#define PA_TYPEID_OSS_MMAP PA_TYPEID_MAKE('O', 'S', 'S', 'M') - struct userdata { pa_sink *sink; pa_source *source; @@ -204,7 +202,7 @@ static void do_read(struct userdata *u) { in_clear_memblocks(u, u->in_fragments/2); } -static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags f, void *userdata) { +static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t f, void *userdata) { struct userdata *u = userdata; assert (u && u->core->mainloop == m && u->io_event == e); @@ -304,7 +302,7 @@ int pa__init(pa_core *c, pa_module*m) { } } else { - u->source = pa_source_new(c, PA_TYPEID_OSS_MMAP, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec); + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec, NULL); assert(u->source); u->source->userdata = u; pa_source_set_owner(u->source, m); @@ -336,7 +334,7 @@ int pa__init(pa_core *c, pa_module*m) { } else { pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); - u->sink = pa_sink_new(c, PA_TYPEID_OSS_MMAP, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec); + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec, NULL); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 06679a97d..b5c7ae8cf 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -52,8 +52,6 @@ PA_MODULE_DESCRIPTION("OSS Sink/Source") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= fragments= fragment_size=") -#define PA_TYPEID_OSS PA_TYPEID_MAKE('O', 'S', 'S', '_') - struct userdata { pa_sink *sink; pa_source *source; @@ -222,7 +220,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { assert(s && u && u->sink); if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) { - pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY.\n"); + pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY: %s\n", strerror(errno)); s->get_latency = NULL; return 0; } @@ -254,6 +252,46 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { return pa_bytes_to_usec(info.bytes, &s->sample_spec); } +static int sink_get_hw_volume(pa_sink *s) { + struct userdata *u = s->userdata; + char cv[PA_CVOLUME_SNPRINT_MAX]; + unsigned vol; + + if (ioctl(u->fd, SOUND_MIXER_READ_PCM, &vol) < 0) { + pa_log_info(__FILE__": device doesn't support reading mixer settings: %s\n", strerror(errno)); + s->get_hw_volume = NULL; + return -1; + } + + s->hw_volume.values[0] = ((vol & 0xFF) * PA_VOLUME_NORM) / 100; + + if ((s->hw_volume.channels = s->sample_spec.channels) >= 2) + s->hw_volume.values[1] = (((vol >> 8) & 0xFF) * PA_VOLUME_NORM) / 100; + + pa_log_info(__FILE__": Read mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), &s->hw_volume)); + return 0; +} + +static int sink_set_hw_volume(pa_sink *s) { + struct userdata *u = s->userdata; + char cv[PA_CVOLUME_SNPRINT_MAX]; + unsigned vol; + + vol = (s->hw_volume.values[0]*100)/PA_VOLUME_NORM; + + if (s->sample_spec.channels >= 2) + vol |= ((s->hw_volume.values[1]*100)/PA_VOLUME_NORM) << 8; + + if (ioctl(u->fd, SOUND_MIXER_WRITE_PCM, &vol) < 0) { + pa_log_info(__FILE__": device doesn't support writing mixer settings: %s\n", strerror(errno)); + s->set_hw_volume = NULL; + return -1; + } + + pa_log_info(__FILE__": Wrote mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), &s->hw_volume)); + return 0; +} + int pa__init(pa_core *c, pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; @@ -332,7 +370,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (mode != O_WRONLY) { - u->source = pa_source_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); assert(u->source); u->source->userdata = u; u->source->notify = source_notify_cb; @@ -343,9 +381,11 @@ int pa__init(pa_core *c, pa_module*m) { u->source = NULL; if (mode != O_RDONLY) { - u->sink = pa_sink_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; + u->sink->get_hw_volume = sink_get_hw_volume; + u->sink->set_hw_volume = sink_set_hw_volume; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p); @@ -384,6 +424,10 @@ int pa__init(pa_core *c, pa_module*m) { read(u->fd, buf, u->sample_size); } + /* Read mixer settings */ + if (u->sink) + sink_get_hw_volume(u->sink); + return 0; fail: diff --git a/polyp/module-pipe-sink.c b/polyp/module-pipe-sink.c index 537cb86bf..20e220ce9 100644 --- a/polyp/module-pipe-sink.c +++ b/polyp/module-pipe-sink.c @@ -50,8 +50,6 @@ PA_MODULE_USAGE("sink_name= file= format=module = m; m->userdata = u; - if (!(u->sink = pa_sink_new(c, PA_TYPEID_PIPE, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { pa_log(__FILE__": failed to create sink.\n"); goto fail; } diff --git a/polyp/module-pipe-source.c b/polyp/module-pipe-source.c index 31653627c..42f13d4b0 100644 --- a/polyp/module-pipe-source.c +++ b/polyp/module-pipe-source.c @@ -50,8 +50,6 @@ PA_MODULE_USAGE("source_name= file= forma #define DEFAULT_FIFO_NAME "/tmp/music.input" #define DEFAULT_SOURCE_NAME "fifo_input" -#define PA_TYPEID_PIPE PA_TYPEID_MAKE('P', 'I', 'P', 'E') - struct userdata { pa_core *core; @@ -154,7 +152,7 @@ int pa__init(pa_core *c, pa_module*m) { u->filename = pa_xstrdup(p); u->core = c; - if (!(u->source = pa_source_new(c, PA_TYPEID_PIPE, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) { + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) { pa_log(__FILE__": failed to create source.\n"); goto fail; } diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 3cf3d9d4a..44d1c0220 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -146,7 +146,7 @@ #else #include "module-esound-protocol-unix-symdef.h" #endif - PA_MODULE_DESCRIPTION("EsounD protocol "SOCKET_DESCRIPTION) + PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("sink= source= public= cookie= "SOCKET_USAGE) #else #error "Broken build system" diff --git a/polyp/module-sine.c b/polyp/module-sine.c index c531386a6..529c061a7 100644 --- a/polyp/module-sine.c +++ b/polyp/module-sine.c @@ -40,8 +40,6 @@ PA_MODULE_DESCRIPTION("Sine wave generator") PA_MODULE_USAGE("sink= frequency=") PA_MODULE_VERSION(PACKAGE_VERSION) -#define PA_TYPEID_SINE PA_TYPEID_MAKE('S', 'I', 'N', 'E') - struct userdata { pa_core *core; pa_module *module; @@ -142,7 +140,7 @@ int pa__init(pa_core *c, pa_module*m) { calc_sine(u->memblock->data, u->memblock->length, frequency); snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); - if (!(u->sink_input = pa_sink_input_new(sink, PA_TYPEID_SINE, t, &ss, 0, -1))) + if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, t, &ss, NULL, 0, -1))) goto fail; u->sink_input->peek = sink_input_peek; diff --git a/polyp/module-solaris.c b/polyp/module-solaris.c index 01a151d63..ce9308be3 100644 --- a/polyp/module-solaris.c +++ b/polyp/module-solaris.c @@ -1,4 +1,4 @@ -/* $Id: module-oss.c 333 2005-01-08 21:36:53Z lennart $ */ +/* $Id$ */ /*** This file is part of polypaudio. diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c index e0eab6c2d..c088dae0b 100644 --- a/polyp/module-tunnel.c +++ b/polyp/module-tunnel.c @@ -59,8 +59,6 @@ PA_MODULE_USAGE("server=
    source= cookie= PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_VERSION(PACKAGE_VERSION) -#define PA_TYPEID_TUNNEL PA_TYPEID_MAKE('T', 'U', 'N', 'L') - #define DEFAULT_SINK_NAME "tunnel" #define DEFAULT_SOURCE_NAME "tunnel" @@ -625,7 +623,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_socket_client_set_callback(u->client, on_connection, u); #ifdef TUNNEL_SINK - if (!(u->sink = pa_sink_new(c, PA_TYPEID_TUNNEL, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { pa_log(__FILE__": failed to create sink.\n"); goto fail; } @@ -637,7 +635,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_sink_set_owner(u->sink, m); #else - if (!(u->source = pa_source_new(c, PA_TYPEID_TUNNEL, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) { + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) { pa_log(__FILE__": failed to create source.\n"); goto fail; } diff --git a/polyp/module-waveout.c b/polyp/module-waveout.c index 4d6d8c7b6..a5ef847b5 100644 --- a/polyp/module-waveout.c +++ b/polyp/module-waveout.c @@ -1,4 +1,4 @@ -/* $Id: module-waveout.c 333 2005-01-08 21:36:53Z lennart $ */ +/* $Id$ */ /*** This file is part of polypaudio. diff --git a/polyp/module-x11-bell.c b/polyp/module-x11-bell.c index 9b08c1667..4fc4a60d4 100644 --- a/polyp/module-x11-bell.c +++ b/polyp/module-x11-bell.c @@ -66,6 +66,7 @@ static const char* const valid_modargs[] = { static int ring_bell(struct userdata *u, int percent) { pa_sink *s; + pa_cvolume cv; assert(u); if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { @@ -73,7 +74,7 @@ static int ring_bell(struct userdata *u, int percent) { return -1; } - pa_scache_play_item(u->core, u->scache_item, s, percent*2); + pa_scache_play_item(u->core, u->scache_item, s, pa_cvolume_set(&cv, PA_CHANNELS_MAX, percent*PA_VOLUME_NORM/100)); return 0; } diff --git a/polyp/namereg.c b/polyp/namereg.c index 7c53a05d0..07fb485c8 100644 --- a/polyp/namereg.c +++ b/polyp/namereg.c @@ -38,7 +38,7 @@ #include "util.h" struct namereg_entry { - pa_namereg_type type; + pa_namereg_type_t type; char *name; void *data; }; @@ -51,7 +51,7 @@ void pa_namereg_free(pa_core *c) { pa_hashmap_free(c->namereg, NULL, NULL); } -const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type type, void *data, int fail) { +const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail) { struct namereg_entry *e; char *n = NULL; int r; @@ -110,7 +110,7 @@ void pa_namereg_unregister(pa_core *c, const char *name) { pa_xfree(e); } -void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int autoload) { +void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload) { struct namereg_entry *e; uint32_t idx; assert(c); @@ -152,7 +152,7 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int aut return NULL; } -void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type type) { +void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) { char **s; assert(c && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); diff --git a/polyp/namereg.h b/polyp/namereg.h index 04f1737ba..961fd44b5 100644 --- a/polyp/namereg.h +++ b/polyp/namereg.h @@ -28,14 +28,14 @@ typedef enum pa_namereg_type { PA_NAMEREG_SINK, PA_NAMEREG_SOURCE, PA_NAMEREG_SAMPLE -} pa_namereg_type ; +} pa_namereg_type_t; void pa_namereg_free(pa_core *c); -const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type type, void *data, int fail); +const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail); void pa_namereg_unregister(pa_core *c, const char *name); -void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int autoload); -void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type type); +void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload); +void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type); const char *pa_namereg_get_default_sink_name(pa_core *c); const char *pa_namereg_get_default_source_name(pa_core *c); diff --git a/polyp/native-common.h b/polyp/native-common.h index 892629e8a..569f3b71a 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -51,6 +51,7 @@ enum { PA_COMMAND_FINISH_UPLOAD_STREAM, PA_COMMAND_PLAY_SAMPLE, PA_COMMAND_REMOVE_SAMPLE, + PA_COMMAND_GET_SERVER_INFO, PA_COMMAND_GET_SINK_INFO, PA_COMMAND_GET_SINK_INFO_LIST, @@ -68,15 +69,19 @@ enum { PA_COMMAND_GET_SAMPLE_INFO_LIST, PA_COMMAND_SUBSCRIBE, PA_COMMAND_SUBSCRIBE_EVENT, + PA_COMMAND_SET_SINK_VOLUME, PA_COMMAND_SET_SINK_INPUT_VOLUME, PA_COMMAND_CORK_PLAYBACK_STREAM, PA_COMMAND_FLUSH_PLAYBACK_STREAM, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, + PA_COMMAND_SET_DEFAULT_SINK, PA_COMMAND_SET_DEFAULT_SOURCE, + PA_COMMAND_SET_PLAYBACK_STREAM_NAME, PA_COMMAND_SET_RECORD_STREAM_NAME, + PA_COMMAND_KILL_CLIENT, PA_COMMAND_KILL_SINK_INPUT, PA_COMMAND_KILL_SOURCE_OUTPUT, diff --git a/polyp/pacat-simple.c b/polyp/pacat-simple.c index 373cdd576..2825fee55 100644 --- a/polyp/pacat-simple.c +++ b/polyp/pacat-simple.c @@ -48,7 +48,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { int error; /* Create a new playback stream */ - if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, PA_VOLUME_NORM, &error))) { + if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, &error))) { fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); goto finish; } diff --git a/polyp/pacat.c b/polyp/pacat.c index 6842d61ac..bd2b64fd5 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -162,16 +162,17 @@ static void context_state_callback(pa_context *c, void *userdata) { if (verbose) fprintf(stderr, "Connection established.\n"); - stream = pa_stream_new(c, stream_name, &sample_spec); + stream = pa_stream_new(c, stream_name, &sample_spec, NULL); assert(stream); pa_stream_set_state_callback(stream, stream_state_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); pa_stream_set_read_callback(stream, stream_read_callback, NULL); - if (mode == PLAYBACK) - pa_stream_connect_playback(stream, device, NULL, 0, volume); - else + if (mode == PLAYBACK) { + pa_cvolume cv; + pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume)); + } else pa_stream_connect_record(stream, device, NULL, 0); break; @@ -219,7 +220,7 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { } /* New data on STDIN **/ -static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) { +static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { size_t l, w = 0; ssize_t r; assert(a == mainloop_api && e && stdio_event == e); @@ -257,7 +258,7 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even } /* Some data may be written to STDOUT */ -static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) { +static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { ssize_t r; assert(a == mainloop_api && e && stdio_event == e); diff --git a/polyp/pactl.c b/polyp/pactl.c index 6943a11f1..23bd924b8 100644 --- a/polyp/pactl.c +++ b/polyp/pactl.c @@ -149,8 +149,8 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi } static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) { - char s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5]; - + char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + if (is_last < 0) { fprintf(stderr, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c))); quit(1); @@ -168,31 +168,31 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ printf("\n"); nl = 1; - pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); - printf("*** Sink #%u ***\n" "Name: %s\n" - "Type: %s\n" + "Driver: %s\n" "Description: %s\n" "Sample Specification: %s\n" + "Channel Map: %s\n" "Owner Module: %u\n" - "Volume: 0x%03x (%0.2f dB)\n" + "Volume: %s\n" "Monitor Source: %u\n" "Latency: %0.0f usec\n", i->index, i->name, - pa_typeid_to_string(i->_typeid, tid, sizeof(tid)), + i->driver, i->description, - s, + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), i->owner_module, - i->volume, pa_volume_to_dB(i->volume), + pa_cvolume_snprint(cv, sizeof(cv), &i->volume), i->monitor_source, (double) i->latency); } static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) { - char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], tid[5]; + char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; if (is_last < 0) { fprintf(stderr, "Failed to get source information: %s\n", pa_strerror(pa_context_errno(c))); @@ -213,21 +213,21 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int snprintf(t, sizeof(t), "%u", i->monitor_of_sink); - pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); - printf("*** Source #%u ***\n" "Name: %s\n" - "Type: %s\n" + "Driver: %s\n" "Description: %s\n" "Sample Specification: %s\n" + "Channel Map: %s\n" "Owner Module: %u\n" "Monitor of Sink: %s\n" "Latency: %0.0f usec\n", i->index, - pa_typeid_to_string(i->_typeid, tid, sizeof(tid)), + i->driver, i->name, i->description, - s, + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), i->owner_module, i->monitor_of_sink != PA_INVALID_INDEX ? t : "no", (double) i->latency); @@ -269,7 +269,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int } static void get_client_info_callback(pa_context *c, const pa_client_info *i, int is_last, void *userdata) { - char t[32], tid[5]; + char t[32]; if (is_last < 0) { fprintf(stderr, "Failed to get client information: %s\n", pa_strerror(pa_context_errno(c))); @@ -292,16 +292,16 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int printf("*** Client #%u ***\n" "Name: %s\n" - "Type: %s\n" + "Driver: %s\n" "Owner Module: %s\n", i->index, i->name, - pa_typeid_to_string(i->_typeid, tid, sizeof(tid)), + i->driver, i->owner_module != PA_INVALID_INDEX ? t : "n/a"); } static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) { - char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5]; + char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; if (is_last < 0) { fprintf(stderr, "Failed to get sink input information: %s\n", pa_strerror(pa_context_errno(c))); @@ -320,29 +320,30 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info printf("\n"); nl = 1; - pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); snprintf(t, sizeof(t), "%u", i->owner_module); snprintf(k, sizeof(k), "%u", i->client); printf("*** Sink Input #%u ***\n" "Name: %s\n" - "Type: %s\n" + "Driver: %s\n" "Owner Module: %s\n" "Client: %s\n" "Sink: %u\n" "Sample Specification: %s\n" - "Volume: 0x%03x (%0.2f dB)\n" + "Channel Map: %s\n" + "Volume: %s\n" "Buffer Latency: %0.0f usec\n" "Sink Latency: %0.0f usec\n" "Resample method: %s\n", i->index, i->name, - pa_typeid_to_string(i->_typeid, tid, sizeof(tid)), + i->driver, i->owner_module != PA_INVALID_INDEX ? t : "n/a", i->client != PA_INVALID_INDEX ? k : "n/a", i->sink, - s, - i->volume, pa_volume_to_dB(i->volume), + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), + pa_cvolume_snprint(cv, sizeof(cv), &i->volume), (double) i->buffer_usec, (double) i->sink_usec, i->resample_method ? i->resample_method : "n/a"); @@ -350,7 +351,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info static void get_source_output_info_callback(pa_context *c, const pa_source_output_info *i, int is_last, void *userdata) { - char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5]; + char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; if (is_last < 0) { fprintf(stderr, "Failed to get source output information: %s\n", pa_strerror(pa_context_errno(c))); @@ -369,34 +370,36 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu printf("\n"); nl = 1; - pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); + snprintf(t, sizeof(t), "%u", i->owner_module); snprintf(k, sizeof(k), "%u", i->client); printf("*** Source Output #%u ***\n" "Name: %s\n" - "Type: %s\n" + "Driver: %s\n" "Owner Module: %s\n" "Client: %s\n" "Source: %u\n" "Sample Specification: %s\n" + "Channel Map: %s\n" "Buffer Latency: %0.0f usec\n" "Source Latency: %0.0f usec\n" "Resample method: %s\n", i->index, i->name, - pa_typeid_to_string(i->_typeid, tid, sizeof(tid)), + i->driver, i->owner_module != PA_INVALID_INDEX ? t : "n/a", i->client != PA_INVALID_INDEX ? k : "n/a", i->source, - s, + pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), (double) i->buffer_usec, (double) i->source_usec, i->resample_method ? i->resample_method : "n/a"); } static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) { - char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX]; + char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; if (is_last < 0) { fprintf(stderr, "Failed to get sample information: %s\n", pa_strerror(pa_context_errno(c))); @@ -415,21 +418,23 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int printf("\n"); nl = 1; - pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec); + pa_bytes_snprint(t, sizeof(t), i->bytes); printf("*** Sample #%u ***\n" "Name: %s\n" - "Volume: 0x%03x (%0.2f dB)\n" + "Volume: %s\n" "Sample Specification: %s\n" + "Channel Map: %s\n" "Duration: %0.1fs\n" "Size: %s\n" "Lazy: %s\n" "Filename: %s\n", i->index, i->name, - i->volume, pa_volume_to_dB(i->volume), - pa_sample_spec_valid(&i->sample_spec) ? s : "n/a", + pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + pa_sample_spec_valid(&i->sample_spec) ? pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec) : "n/a", + pa_sample_spec_valid(&i->sample_spec) ? pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) : "n/a", (double) i->duration/1000000, t, i->lazy ? "yes" : "no", @@ -547,7 +552,7 @@ static void context_state_callback(pa_context *c, void *userdata) { break; case UPLOAD_SAMPLE: - sample_stream = pa_stream_new(c, sample_name, &sample_spec); + sample_stream = pa_stream_new(c, sample_name, &sample_spec, NULL); assert(sample_stream); pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL); diff --git a/polyp/paplay.c b/polyp/paplay.c index d9aa71a6d..ddc1cbc16 100644 --- a/polyp/paplay.c +++ b/polyp/paplay.c @@ -155,21 +155,23 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_SETTING_NAME: break; - case PA_CONTEXT_READY: + case PA_CONTEXT_READY: { + pa_cvolume cv; assert(c && !stream); if (verbose) fprintf(stderr, "Connection established.\n"); - stream = pa_stream_new(c, stream_name, &sample_spec); + stream = pa_stream_new(c, stream_name, &sample_spec, NULL); assert(stream); pa_stream_set_state_callback(stream, stream_state_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); - pa_stream_connect_playback(stream, device, NULL, 0, volume); + pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume)); break; + } case PA_CONTEXT_TERMINATED: quit(0); diff --git a/polyp/parec-simple.c b/polyp/parec-simple.c index 5f5abe111..524cc4f16 100644 --- a/polyp/parec-simple.c +++ b/polyp/parec-simple.c @@ -67,7 +67,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { int error; /* Create the recording stream */ - if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, 0, &error))) { + if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, &error))) { fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); goto finish; } diff --git a/polyp/parseaddr.h b/polyp/parseaddr.h index f0efd766a..eff9dd3bd 100644 --- a/polyp/parseaddr.h +++ b/polyp/parseaddr.h @@ -29,10 +29,10 @@ typedef enum pa_parsed_address_type { PA_PARSED_ADDRESS_TCP4, PA_PARSED_ADDRESS_TCP6, PA_PARSED_ADDRESS_TCP_AUTO -} pa_parsed_address_type; +} pa_parsed_address_type_t; typedef struct pa_parsed_address { - pa_parsed_address_type type; + pa_parsed_address_type_t type; char *path_or_host; uint16_t port; } pa_parsed_address; diff --git a/polyp/play-memchunk.c b/polyp/play-memchunk.c index c3db14627..e24d44273 100644 --- a/polyp/play-memchunk.c +++ b/polyp/play-memchunk.c @@ -33,8 +33,6 @@ #include "xmalloc.h" #include "gccmacro.h" -#define PA_TYPEID_MEMCHUNK PA_TYPEID_MAKE('M', 'C', 'N', 'K') - static void sink_input_kill(pa_sink_input *i) { pa_memchunk *c; assert(i && i->userdata); @@ -45,7 +43,6 @@ static void sink_input_kill(pa_sink_input *i) { pa_memblock_unref(c->memblock); pa_xfree(c); - } static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { @@ -82,24 +79,35 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t le pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); } -int pa_play_memchunk(pa_sink *sink, const char *name, const pa_sample_spec *ss, const pa_memchunk *chunk, pa_volume_t volume) { +int pa_play_memchunk( + pa_sink *sink, + const char *name, + const pa_sample_spec *ss, + const pa_channel_map *map, + const pa_memchunk *chunk, + pa_cvolume *cvolume) { + pa_sink_input *si; pa_memchunk *nchunk; - assert(sink && chunk); + assert(sink); + assert(ss); + assert(chunk); - if (volume <= 0) + if (cvolume && pa_cvolume_is_muted(cvolume)) return 0; - if (!(si = pa_sink_input_new(sink, PA_TYPEID_MEMCHUNK, name, ss, 0, -1))) + if (!(si = pa_sink_input_new(sink, name, __FILE__, ss, map, 0, PA_RESAMPLER_INVALID))) return -1; - si->volume = volume; + if (cvolume) + si->volume = *cvolume; + si->peek = sink_input_peek; si->drop = sink_input_drop; si->kill = sink_input_kill; - si->userdata = nchunk = pa_xmalloc(sizeof(pa_memchunk)); + si->userdata = nchunk = pa_xnew(pa_memchunk, 1); *nchunk = *chunk; pa_memblock_ref(chunk->memblock); diff --git a/polyp/play-memchunk.h b/polyp/play-memchunk.h index 247cc8708..fc0654a6f 100644 --- a/polyp/play-memchunk.h +++ b/polyp/play-memchunk.h @@ -25,6 +25,12 @@ #include "sink.h" #include "memchunk.h" -int pa_play_memchunk(pa_sink *sink, const char *name, const pa_sample_spec *ss, const pa_memchunk *chunk, pa_volume_t volume); +int pa_play_memchunk( + pa_sink *sink, + const char *name, + const pa_sample_spec *ss, + const pa_channel_map *map, + const pa_memchunk *chunk, + pa_cvolume *cvolume); #endif diff --git a/polyp/poll.c b/polyp/poll.c index 6a260daf0..193fc8128 100644 --- a/polyp/poll.c +++ b/polyp/poll.c @@ -1,4 +1,4 @@ -/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */ +/* $Id$ */ /*** Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. diff --git a/polyp/poll.h b/polyp/poll.h index 573f90eac..c201014eb 100644 --- a/polyp/poll.h +++ b/polyp/poll.h @@ -1,4 +1,4 @@ -/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */ +/* $Id$ */ /*** Compatibility definitions for System V `poll' interface. diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index 0cf324901..15f2e4cd7 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -187,7 +187,7 @@ void pa_context_unref(pa_context *c) { context_free(c); } -void pa_context_set_state(pa_context *c, pa_context_state st) { +void pa_context_set_state(pa_context *c, pa_context_state_t st) { assert(c); if (c->state == st) @@ -644,7 +644,7 @@ void pa_context_disconnect(pa_context *c) { pa_context_set_state(c, PA_CONTEXT_TERMINATED); } -pa_context_state pa_context_get_state(pa_context *c) { +pa_context_state_t pa_context_get_state(pa_context *c) { assert(c && c->ref >= 1); return c->state; } diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 80c1b6014..febb75f42 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -75,7 +75,7 @@ int pa_context_errno(pa_context *c); int pa_context_is_pending(pa_context *c); /** Return the current context status */ -pa_context_state pa_context_get_state(pa_context *c); +pa_context_state_t pa_context_get_state(pa_context *c); /** Connect the context to the specified server. If server is NULL, connect to the default server. This routine may but will not always diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h index 499282c4d..0591ce6c1 100644 --- a/polyp/polyplib-def.h +++ b/polyp/polyplib-def.h @@ -43,7 +43,7 @@ typedef enum pa_context_state { PA_CONTEXT_READY, /**< The connection is established, the context is ready to execute operations */ PA_CONTEXT_FAILED, /**< The connection failed or was disconnected */ PA_CONTEXT_TERMINATED /**< The connection was terminated cleanly */ -} pa_context_state; +} pa_context_state_t; /** The state of a stream */ typedef enum pa_stream_state { @@ -52,14 +52,14 @@ typedef enum pa_stream_state { PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */ PA_STREAM_FAILED, /**< An error occured that made the stream invalid */ PA_STREAM_TERMINATED /**< The stream has been terminated cleanly */ -} pa_stream_state; +} pa_stream_state_t; /** The state of an operation */ typedef enum pa_operation_state { PA_OPERATION_RUNNING, /**< The operation is still running */ PA_OPERATION_DONE, /**< The operation has been completed */ PA_OPERATION_CANCELED /**< The operation has been canceled */ -} pa_operation_state; +} pa_operation_state_t; /** An invalid index */ #define PA_INVALID_INDEX ((uint32_t) -1) @@ -70,7 +70,7 @@ typedef enum pa_stream_direction { PA_STREAM_PLAYBACK, /**< Playback stream */ PA_STREAM_RECORD, /**< Record stream */ PA_STREAM_UPLOAD /**< Sample upload stream */ -} pa_stream_direction; +} pa_stream_direction_t; /** Some special flags for stream connections. \since 0.6 */ typedef enum pa_stream_flags { @@ -90,7 +90,7 @@ typedef enum pa_stream_flags { * information. This is * especially useful on long latency * network connections. */ -} pa_stream_flags; +} pa_stream_flags_t; /** Playback and record buffer metrics */ typedef struct pa_buffer_attr { @@ -133,7 +133,7 @@ typedef enum pa_subscription_mask { PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */ PA_SUBSCRIPTION_MASK_SERVER = 128, /**< Other global server changes. \since 0.4 */ PA_SUBSCRIPTION_MASK_AUTOLOAD = 256 /**< Autoload table events. \since 0.5 */ -} pa_subscription_mask; +} pa_subscription_mask_t; /** Subscription event types, as used by pa_context_subscribe() */ typedef enum pa_subscription_event_type { @@ -152,7 +152,7 @@ typedef enum pa_subscription_event_type { PA_SUBSCRIPTION_EVENT_CHANGE = 16, /**< A property of the object was modified */ PA_SUBSCRIPTION_EVENT_REMOVE = 32, /**< An object was removed */ PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32 /**< A mask to extract the event operation from an event value */ -} pa_subscription_event_type; +} pa_subscription_event_type_t; /** Return one if an event type t matches an event mask bitfield */ #define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h index 09f9473ac..295960695 100644 --- a/polyp/polyplib-internal.h +++ b/polyp/polyplib-internal.h @@ -55,12 +55,12 @@ struct pa_context { uint32_t ctag; uint32_t error; - pa_context_state state; + pa_context_state_t state; void (*state_callback)(pa_context*c, void *userdata); void *state_userdata; - void (*subscribe_callback)(pa_context *c, pa_subscription_event_type t, uint32_t idx, void *userdata); + void (*subscribe_callback)(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata); void *subscribe_userdata; pa_memblock_stat *memblock_stat; @@ -86,15 +86,16 @@ struct pa_stream { char *name; pa_buffer_attr buffer_attr; pa_sample_spec sample_spec; + pa_channel_map channel_map; uint32_t channel; int channel_valid; uint32_t device_index; - pa_stream_direction direction; + pa_stream_direction_t direction; uint32_t requested_bytes; uint64_t counter; pa_usec_t previous_time; pa_usec_t previous_ipol_time; - pa_stream_state state; + pa_stream_state_t state; pa_mcalign *mcalign; int interpolate; @@ -123,7 +124,7 @@ struct pa_operation { pa_stream *stream; PA_LLIST_FIELDS(pa_operation); - pa_operation_state state; + pa_operation_state_t state; void *userdata; pa_operation_callback callback; }; @@ -141,11 +142,11 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_context_fail(pa_context *c, int error); -void pa_context_set_state(pa_context *c, pa_context_state st); +void pa_context_set_state(pa_context *c, pa_context_state_t st); int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t); pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, void (*internal_callback)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata), void (*cb)(void), void *userdata); -void pa_stream_set_state(pa_stream *s, pa_stream_state st); +void pa_stream_set_state(pa_stream *s, pa_stream_state_t st); void pa_stream_trash_ipol(pa_stream *s); diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 911059690..8c0c4449b 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -128,12 +128,13 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_gets(t, &i.description) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_get_cvolume(t, &i.volume) < 0 || pa_tagstruct_getu32(t, &i.monitor_source) < 0 || pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || pa_tagstruct_get_usec(t, &i.latency) < 0 || - pa_tagstruct_getu32(t, &i._typeid) < 0) { + pa_tagstruct_gets(t, &i.driver) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; @@ -223,11 +224,12 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_gets(t, &i.description) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 || pa_tagstruct_get_usec(t, &i.latency) < 0 || - pa_tagstruct_getu32(t, &i._typeid) < 0) { + pa_tagstruct_gets(t, &i.driver) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; @@ -316,7 +318,7 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || - pa_tagstruct_getu32(t, &i._typeid) < 0 ) { + pa_tagstruct_gets(t, &i.driver) < 0 ) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -452,11 +454,12 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm pa_tagstruct_getu32(t, &i.client) < 0 || pa_tagstruct_getu32(t, &i.sink) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 || + pa_tagstruct_get_cvolume(t, &i.volume) < 0 || pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || pa_tagstruct_get_usec(t, &i.sink_usec) < 0 || pa_tagstruct_gets(t, &i.resample_method) < 0 || - pa_tagstruct_getu32(t, &i._typeid) < 0) { + pa_tagstruct_gets(t, &i.driver) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; @@ -526,10 +529,11 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c pa_tagstruct_getu32(t, &i.client) < 0 || pa_tagstruct_getu32(t, &i.source) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 || pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || pa_tagstruct_get_usec(t, &i.source_usec) < 0 || pa_tagstruct_gets(t, &i.resample_method) < 0 || - pa_tagstruct_getu32(t, &i._typeid) < 0) { + pa_tagstruct_gets(t, &i.driver) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; @@ -662,9 +666,10 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_getu32(t, &i.volume) < 0 || + pa_tagstruct_get_cvolume(t, &i.volume) < 0 || pa_tagstruct_get_usec(t, &i.duration) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || + pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 || pa_tagstruct_getu32(t, &i.bytes) < 0 || pa_tagstruct_get_boolean(t, &i.lazy) < 0 || pa_tagstruct_gets(t, &i.filename) < 0) { @@ -861,7 +866,7 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; @@ -933,8 +938,7 @@ finish: pa_operation_unref(o); } - -pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type type, const char *module, const char*argument, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) { +pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; @@ -957,7 +961,7 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo return pa_operation_ref(o); } -pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) { +pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 2848e22f9..10e6d0e38 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -27,7 +27,8 @@ #include #include #include -#include +#include +#include /** \file * @@ -52,13 +53,14 @@ typedef struct pa_sink_info { const char *name; /**< Name of the sink */ uint32_t index; /**< Index of the sink */ const char *description; /**< Description of this sink */ - pa_sample_spec sample_spec; /**< Sample spec of this sink */ + pa_sample_spec sample_spec; /**< Sample spec of this sink */ + pa_channel_map channel_map; /**< Channel map \since 0.9 */ uint32_t owner_module; /**< Index of the owning module of this sink, or PA_INVALID_INDEX */ - pa_volume_t volume; /**< Volume of the sink */ + pa_cvolume volume; /**< Volume of the sink */ uint32_t monitor_source; /**< Index of the monitor source connected to this sink */ const char *monitor_source_name; /**< The name of the monitor source */ pa_usec_t latency; /**< Length of filled playback buffer of this sink */ - pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ + const char *driver; /**< Driver name. \since 0.9 */ } pa_sink_info; /** Get information about a sink by its name */ @@ -75,12 +77,13 @@ typedef struct pa_source_info { const char *name ; /**< Name of the source */ uint32_t index; /**< Index of the source */ const char *description; /**< Description of this source */ - pa_sample_spec sample_spec; /**< Sample spec of this source */ + pa_sample_spec sample_spec; /**< Sample spec of this source */ + pa_channel_map channel_map; /**< Channel map \since 0.9 */ uint32_t owner_module; /**< Owning module index, or PA_INVALID_INDEX */ uint32_t monitor_of_sink; /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */ const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */ pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */ - pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ + const char *driver; /**< Driver name \since 0.9 */ } pa_source_info; /** Get information about a source by its name */ @@ -98,7 +101,7 @@ typedef struct pa_server_info { const char *host_name; /**< Host name the daemon is running on */ const char *server_version; /**< Version string of the daemon */ const char *server_name; /**< Server package name (usually "polypaudio") */ - pa_sample_spec sample_spec; /**< Default sample specification */ + pa_sample_spec sample_spec; /**< Default sample specification */ const char *default_sink_name; /**< Name of default sink. \since 0.4 */ const char *default_source_name; /**< Name of default sink. \since 0.4*/ uint32_t cookie; /**< A random cookie for identifying this instance of polypaudio. \since 0.8 */ @@ -127,7 +130,7 @@ typedef struct pa_client_info { uint32_t index; /**< Index of this client */ const char *name; /**< Name of this client */ uint32_t owner_module; /**< Index of the owning module, or PA_INVALID_INDEX */ - pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ + const char *driver; /**< Driver name \since 0.9 */ } pa_client_info; /** Get information about a client by its index */ @@ -143,12 +146,13 @@ typedef struct pa_sink_input_info { uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */ uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */ uint32_t sink; /**< Index of the connected sink */ - pa_sample_spec sample_spec; /**< The sample specification of the sink input */ - pa_volume_t volume; /**< The volume of this sink input */ + pa_sample_spec sample_spec; /**< The sample specification of the sink input */ + pa_channel_map channel_map; /**< Channel map */ + pa_cvolume volume; /**< The volume of this sink input */ pa_usec_t buffer_usec; /**< Latency due to buffering in sink input, see pa_latency_info for details */ pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */ const char *resample_method; /**< Thre resampling method used by this sink input. \since 0.7 */ - pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ + const char *driver; /**< Driver name \since 0.9 */ } pa_sink_input_info; /** Get some information about a sink input by its index */ @@ -164,11 +168,12 @@ typedef struct pa_source_output_info { uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */ uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */ uint32_t source; /**< Index of the connected source */ - pa_sample_spec sample_spec; /**< The sample specification of the source output */ + pa_sample_spec sample_spec; /**< The sample specification of the source output */ + pa_channel_map channel_map; /**< Channel map */ pa_usec_t buffer_usec; /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */ pa_usec_t source_usec; /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */ const char *resample_method; /**< Thre resampling method used by this source output. \since 0.7 */ - pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */ + const char *driver; /**< Driver name \since 0.9 */ } pa_source_output_info; /** Get information about a source output by its index */ @@ -202,8 +207,9 @@ pa_operation* pa_context_stat(pa_context *c, void (*cb)(pa_context *c, const pa_ typedef struct pa_sample_info { uint32_t index; /**< Index of this entry */ const char *name; /**< Name of this entry */ - pa_volume_t volume; /**< Default volume of this entry */ - pa_sample_spec sample_spec; /**< Sample specification of the sampel */ + pa_cvolume volume; /**< Default volume of this entry */ + pa_sample_spec sample_spec; /**< Sample specification of the sample */ + pa_channel_map channel_map; /**< The channel map */ pa_usec_t duration; /**< Duration of this entry */ uint32_t bytes; /**< Length of this sample in bytes. \since 0.4 */ int lazy; /**< Non-zero when this is a lazy cache entry. \since 0.5 */ @@ -238,19 +244,19 @@ pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, void (*cb)(p typedef enum pa_autoload_type { PA_AUTOLOAD_SINK = 0, PA_AUTOLOAD_SOURCE = 1 -} pa_autoload_type; +} pa_autoload_type_t; /** Stores information about autoload entries. \since 0.5 */ typedef struct pa_autoload_info { uint32_t index; /**< Index of this autoload entry */ const char *name; /**< Name of the sink or source */ - pa_autoload_type type; /**< Type of the autoload entry */ + pa_autoload_type_t type; /**< Type of the autoload entry */ const char *module; /**< Module name to load */ const char *argument; /**< Argument string for module */ } pa_autoload_info; /** Get info about a specific autoload entry. \since 0.6 */ -pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata); /** Get info about a specific autoload entry. \since 0.6 */ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata); @@ -259,10 +265,10 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_operation* pa_context_get_autoload_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata); /** Add a new autoload entry. \since 0.5 */ -pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type type, const char *module, const char*argument, void (*cb)(pa_context *c, int idx, void *userdata), void* userdata); +pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, void (*cb)(pa_context *c, int idx, void *userdata), void* userdata); /** Remove an autoload entry. \since 0.6 */ -pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata); +pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata); /** Remove an autoload entry. \since 0.6 */ pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void* userdata); diff --git a/polyp/polyplib-operation.c b/polyp/polyplib-operation.c index 3bee8cc72..68bc8c6a1 100644 --- a/polyp/polyplib-operation.c +++ b/polyp/polyplib-operation.c @@ -62,7 +62,7 @@ void pa_operation_unref(pa_operation *o) { } } -static void operation_set_state(pa_operation *o, pa_operation_state st) { +static void operation_set_state(pa_operation *o, pa_operation_state_t st) { assert(o && o->ref >= 1); if (st == o->state) @@ -97,7 +97,7 @@ void pa_operation_done(pa_operation *o) { operation_set_state(o, PA_OPERATION_DONE); } -pa_operation_state pa_operation_get_state(pa_operation *o) { +pa_operation_state_t pa_operation_get_state(pa_operation *o) { assert(o && o->ref >= 1); return o->state; } diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h index 63dcbc9fb..cac03e30b 100644 --- a/polyp/polyplib-operation.h +++ b/polyp/polyplib-operation.h @@ -44,7 +44,7 @@ void pa_operation_unref(pa_operation *o); void pa_operation_cancel(pa_operation *o); /** Return the current status of the operation */ -pa_operation_state pa_operation_get_state(pa_operation *o); +pa_operation_state_t pa_operation_get_state(pa_operation *o); PA_C_DECL_END diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c index b13571289..e55121529 100644 --- a/polyp/polyplib-simple.c +++ b/polyp/polyplib-simple.c @@ -39,7 +39,7 @@ struct pa_simple { pa_mainloop *mainloop; pa_context *context; pa_stream *stream; - pa_stream_direction direction; + pa_stream_direction_t direction; int dead; @@ -51,8 +51,8 @@ struct pa_simple { static void read_callback(pa_stream *s, const void*data, size_t length, void *userdata); static int check_error(pa_simple *p, int *rerror) { - pa_context_state cst; - pa_stream_state sst; + pa_context_state_t cst; + pa_stream_state_t sst; assert(p); if ((cst = pa_context_get_state(p->context)) == PA_CONTEXT_FAILED) @@ -118,12 +118,11 @@ static int iterate(pa_simple *p, int block, int *rerror) { pa_simple* pa_simple_new( const char *server, const char *name, - pa_stream_direction dir, + pa_stream_direction_t dir, const char *dev, const char *stream_name, const pa_sample_spec *ss, const pa_buffer_attr *attr, - pa_volume_t volume, int *rerror) { pa_simple *p; @@ -152,11 +151,11 @@ pa_simple* pa_simple_new( goto fail; } - if (!(p->stream = pa_stream_new(p->context, stream_name, ss))) + if (!(p->stream = pa_stream_new(p->context, stream_name, ss, NULL))) goto fail; if (dir == PA_STREAM_PLAYBACK) - pa_stream_connect_playback(p->stream, dev, attr, 0, volume); + pa_stream_connect_playback(p->stream, dev, attr, 0, NULL); else pa_stream_connect_record(p->stream, dev, attr, 0); diff --git a/polyp/polyplib-simple.h b/polyp/polyplib-simple.h index d15891159..0c80f460e 100644 --- a/polyp/polyplib-simple.h +++ b/polyp/polyplib-simple.h @@ -49,12 +49,11 @@ typedef struct pa_simple pa_simple; pa_simple* pa_simple_new( const char *server, /**< Server name, or NULL for default */ const char *name, /**< A descriptive name for this client (application name, ...) */ - pa_stream_direction dir, /**< Open this stream for recording or playback? */ + pa_stream_direction_t dir, /**< Open this stream for recording or playback? */ const char *dev, /**< Sink (resp. source) name, or NULL for default */ const char *stream_name, /**< A descriptive name for this client (application name, song title, ...) */ const pa_sample_spec *ss, /**< The sample type to use */ const pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */ - pa_volume_t volume, /**< Initial volume. Only for playback streams. \since 0.5 */ int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */ ); diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 6c8ed9c5d..51ee6a225 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -36,11 +36,18 @@ #define LATENCY_IPOL_INTERVAL_USEC (10000L) -pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss) { +pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) { pa_stream *s; - assert(c && ss); + assert(c); + assert(ss); - s = pa_xmalloc(sizeof(pa_stream)); + if (!pa_sample_spec_valid(ss)) + return NULL; + + if (map && !pa_channel_map_valid(map)) + return NULL; + + s = pa_xnew(pa_stream, 1); s->ref = 1; s->context = c; s->mainloop = c->mainloop; @@ -55,6 +62,12 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->direction = PA_STREAM_NODIRECTION; s->name = pa_xstrdup(name); s->sample_spec = *ss; + + if (map) + s->channel_map = *map; + else + pa_channel_map_init_auto(&s->channel_map, ss->channels); + s->channel = 0; s->channel_valid = 0; s->device_index = PA_INVALID_INDEX; @@ -108,7 +121,7 @@ pa_stream* pa_stream_ref(pa_stream *s) { return s; } -pa_stream_state pa_stream_get_state(pa_stream *s) { +pa_stream_state_t pa_stream_get_state(pa_stream *s) { assert(s && s->ref >= 1); return s->state; } @@ -123,7 +136,7 @@ uint32_t pa_stream_get_index(pa_stream *s) { return s->device_index; } -void pa_stream_set_state(pa_stream *s, pa_stream_state st) { +void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { assert(s && s->ref >= 1); if (s->state == st) @@ -271,7 +284,7 @@ finish: pa_stream_unref(s); } -static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume) { +static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags, const pa_cvolume *volume) { pa_tagstruct *t; uint32_t tag; assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED); @@ -308,15 +321,23 @@ static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *a pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_puts(t, s->name); pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_put_channel_map(t, &s->channel_map); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, dev); pa_tagstruct_putu32(t, s->buffer_attr.maxlength); pa_tagstruct_put_boolean(t, !!(flags & PA_STREAM_START_CORKED)); if (s->direction == PA_STREAM_PLAYBACK) { + pa_cvolume cv; pa_tagstruct_putu32(t, s->buffer_attr.tlength); pa_tagstruct_putu32(t, s->buffer_attr.prebuf); pa_tagstruct_putu32(t, s->buffer_attr.minreq); - pa_tagstruct_putu32(t, volume); + + if (!volume) { + pa_cvolume_reset(&cv, s->sample_spec.channels); + volume = &cv; + } + + pa_tagstruct_put_cvolume(t, volume); } else pa_tagstruct_putu32(t, s->buffer_attr.fragsize); @@ -326,13 +347,13 @@ static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *a pa_stream_unref(s); } -void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume) { +void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags, pa_cvolume *volume) { assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); s->direction = PA_STREAM_PLAYBACK; create_stream(s, dev, attr, flags, volume); } -void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags) { +void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags) { assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); s->direction = PA_STREAM_RECORD; create_stream(s, dev, attr, flags, 0); diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h index 806579f57..bc828b71c 100644 --- a/polyp/polyplib-stream.h +++ b/polyp/polyplib-stream.h @@ -25,6 +25,8 @@ #include #include +#include +#include #include #include #include @@ -39,7 +41,7 @@ PA_C_DECL_BEGIN typedef struct pa_stream pa_stream; /** Create a new, unconnected stream with the specified name and sample type */ -pa_stream* pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss); +pa_stream* pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map); /** Decrease the reference counter by one */ void pa_stream_unref(pa_stream *s); @@ -48,7 +50,7 @@ void pa_stream_unref(pa_stream *s); pa_stream *pa_stream_ref(pa_stream *s); /** Return the current state of the stream */ -pa_stream_state pa_stream_get_state(pa_stream *p); +pa_stream_state_t pa_stream_get_state(pa_stream *p); /** Return the context this stream is attached to */ pa_context* pa_stream_get_context(pa_stream *p); @@ -57,10 +59,19 @@ pa_context* pa_stream_get_context(pa_stream *p); uint32_t pa_stream_get_index(pa_stream *s); /** Connect the stream to a sink */ -void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume); +void pa_stream_connect_playback( + pa_stream *s, + const char *dev, + const pa_buffer_attr *attr, + pa_stream_flags_t flags, + pa_cvolume *volume); /** Connect the stream to a source */ -void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags); +void pa_stream_connect_record( + pa_stream *s, + const char *dev, + const pa_buffer_attr *attr, + pa_stream_flags_t flags); /** Disconnect a stream from a source/sink */ void pa_stream_disconnect(pa_stream *s); diff --git a/polyp/polyplib-subscribe.c b/polyp/polyplib-subscribe.c index 69ae588fb..ef90ab0b6 100644 --- a/polyp/polyplib-subscribe.c +++ b/polyp/polyplib-subscribe.c @@ -33,7 +33,7 @@ void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; - pa_subscription_event_type e; + pa_subscription_event_type_t e; uint32_t index; assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); @@ -54,7 +54,7 @@ finish: } -pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; @@ -74,7 +74,7 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void ( return pa_operation_ref(o); } -void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { +void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata) { assert(c); c->subscribe_callback = cb; c->subscribe_userdata = userdata; diff --git a/polyp/polyplib-subscribe.h b/polyp/polyplib-subscribe.h index f2760ee63..920c98533 100644 --- a/polyp/polyplib-subscribe.h +++ b/polyp/polyplib-subscribe.h @@ -37,10 +37,10 @@ PA_C_DECL_BEGIN /** Enable event notification */ -pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Set the context specific call back function that is called whenever the state of the daemon changes */ -void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); +void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata); PA_C_DECL_END diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index a97bc25ce..ce183a6f4 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -64,8 +64,6 @@ #define SCACHE_PREFIX "esound." -#define PA_TYPEID_ESOUND PA_TYPEID_MAKE('E', 'S', 'D', 'P') - /* This is heavily based on esound's code */ struct connection { @@ -326,7 +324,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t assert(!c->sink_input && !c->input_memblockq); - if (!(c->sink_input = pa_sink_input_new(sink, PA_TYPEID_ESOUND, name, &ss, 0, -1))) { + if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, name, &ss, NULL, 0, -1))) { pa_log(__FILE__": failed to create sink input.\n"); return -1; } @@ -398,7 +396,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co assert(!c->output_memblockq && !c->source_output); - if (!(c->source_output = pa_source_output_new(source, PA_TYPEID_ESOUND, name, &ss, -1))) { + if (!(c->source_output = pa_source_output_new(source, __FILE__, name, &ss, NULL, -1))) { pa_log(__FILE__": failed to create source output\n"); return -1; } @@ -476,7 +474,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v assert(k); for (conn = pa_idxset_first(c->protocol->connections, &idx); conn; conn = pa_idxset_next(c->protocol->connections, &idx)) { - int format = ESD_BITS16 | ESD_STEREO, rate = 44100, volume = 0xFF; + int format = ESD_BITS16 | ESD_STEREO, rate = 44100, lvolume = 0xFF, rvolume = 0xFF; if (conn->state != ESD_STREAMING_DATA) continue; @@ -485,7 +483,8 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v if (conn->sink_input) { rate = conn->sink_input->sample_spec.rate; - volume = (conn->sink_input->volume*0xFF)/0x100; + lvolume = (conn->sink_input->volume.values[0]*0xFF)/0x100; + rvolume = (conn->sink_input->volume.values[1]*0xFF)/0x100; format = format_native2esd(&conn->sink_input->sample_spec); } @@ -503,11 +502,11 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v response += sizeof(int); /* left */ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, volume); + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, lvolume); response += sizeof(int); /*right*/ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, volume); + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, rvolume); response += sizeof(int); /*format*/ @@ -545,11 +544,11 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v response += sizeof(int); /* left */ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume*0xFF)/0x100); + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*0xFF)/0x100); response += sizeof(int); /*right*/ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume*0xFF)/0x100); + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*0xFF)/0x100); response += sizeof(int); /*format*/ @@ -572,20 +571,25 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { int *ok; - uint32_t idx, volume; + uint32_t idx; + pa_volume_t lvolume, rvolume; struct connection *conn; assert(c && data && length == sizeof(int)*3); idx = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(const int*)data)-1; - volume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); - volume = (volume*0x100)/0xFF; + lvolume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); + lvolume = (lvolume*0x100)/0xFF; + rvolume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 2)); + rvolume = (rvolume*0x100)/0xFF; ok = connection_write(c, sizeof(int)); assert(ok); if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx))) { assert(conn->sink_input); - conn->sink_input->volume = volume; + conn->sink_input->volume.values[0] = lvolume; + conn->sink_input->volume.values[1] = rvolume; + conn->sink_input->volume.channels = 2; *ok = 1; } else *ok = 0; @@ -627,7 +631,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ c->state = ESD_CACHING_SAMPLE; - pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, &idx); + pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, &idx); ok = connection_write(c, sizeof(int)); assert(ok); @@ -676,7 +680,7 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque pa_sink *sink; if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) - if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0) + if (pa_scache_play_item(c->protocol->core, name, sink, NULL) >= 0) *ok = (int) idx+1; } else { assert(request == ESD_PROTO_SAMPLE_FREE); @@ -801,7 +805,7 @@ static int do_read(struct connection *c) { int *ok; c->scache.memchunk.index = 0; - pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, &c->scache.memchunk, &idx); + pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, &idx); pa_memblock_unref(c->scache.memchunk.memblock); c->scache.memchunk.memblock = NULL; @@ -1067,7 +1071,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); assert(p->core); - c->client = pa_client_new(p->core, PA_TYPEID_ESOUND, cname); + c->client = pa_client_new(p->core, __FILE__, cname); assert(c->client); c->client->owner = p->module; c->client->kill = client_kill_cb; diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index b19d30d93..0491dc411 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -56,8 +56,6 @@ /* Don't accept more connection than this */ #define MAX_CONNECTIONS 10 -#define PA_TYPEID_NATIVE PA_TYPEID_MAKE('N', 'A', 'T', 'V') - struct connection; struct pa_protocol_native; @@ -88,6 +86,7 @@ struct upload_stream { size_t length; char *name; pa_sample_spec sample_spec; + pa_channel_map channel_map; }; struct output_stream { @@ -235,7 +234,12 @@ static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = { /* structure management */ -static struct upload_stream* upload_stream_new(struct connection *c, const pa_sample_spec *ss, const char *name, size_t length) { +static struct upload_stream* upload_stream_new( + struct connection *c, + const pa_sample_spec *ss, + const pa_channel_map *map, + const char *name, size_t length) { + struct upload_stream *s; assert(c && ss && name && length); @@ -243,6 +247,7 @@ static struct upload_stream* upload_stream_new(struct connection *c, const pa_sa s->type = UPLOAD_STREAM; s->connection = c; s->sample_spec = *ss; + s->channel_map = *map; s->name = pa_xstrdup(name); s->memchunk.memblock = NULL; @@ -268,13 +273,21 @@ static void upload_stream_free(struct upload_stream *o) { pa_xfree(o); } -static struct record_stream* record_stream_new(struct connection *c, pa_source *source, const pa_sample_spec *ss, const char *name, size_t maxlength, size_t fragment_size) { +static struct record_stream* record_stream_new( + struct connection *c, + pa_source *source, + const pa_sample_spec *ss, + const pa_channel_map *map, + const char *name, + size_t maxlength, + size_t fragment_size) { + struct record_stream *s; pa_source_output *source_output; size_t base; assert(c && source && ss && name && maxlength); - if (!(source_output = pa_source_output_new(source, PA_TYPEID_NATIVE, name, ss, -1))) + if (!(source_output = pa_source_output_new(source, __FILE__, name, ss, map, -1))) return NULL; s = pa_xmalloc(sizeof(struct record_stream)); @@ -308,17 +321,23 @@ static void record_stream_free(struct record_stream* r) { pa_xfree(r); } -static struct playback_stream* playback_stream_new(struct connection *c, pa_sink *sink, const pa_sample_spec *ss, const char *name, - size_t maxlength, - size_t tlength, - size_t prebuf, - size_t minreq, - pa_volume_t volume) { +static struct playback_stream* playback_stream_new( + struct connection *c, + pa_sink *sink, + const pa_sample_spec *ss, + const pa_channel_map *map, + const char *name, + size_t maxlength, + size_t tlength, + size_t prebuf, + size_t minreq, + pa_cvolume *volume) { + struct playback_stream *s; pa_sink_input *sink_input; assert(c && sink && ss && name && maxlength); - if (!(sink_input = pa_sink_input_new(sink, PA_TYPEID_NATIVE, name, ss, 0, -1))) + if (!(sink_input = pa_sink_input_new(sink, __FILE__, name, ss, map, 0, -1))) return NULL; s = pa_xmalloc(sizeof(struct playback_stream)); @@ -340,7 +359,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, pa_sink s->requested_bytes = 0; s->drain_request = 0; - s->sink_input->volume = volume; + s->sink_input->volume = *volume; pa_idxset_put(c->output_streams, s, &s->index); return s; @@ -561,14 +580,17 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC uint32_t sink_index; const char *name, *sink_name; pa_sample_spec ss; + pa_channel_map map; pa_tagstruct *reply; pa_sink *sink; - pa_volume_t volume; + pa_cvolume volume; int corked; + assert(c && t && c->protocol && c->protocol->core); if (pa_tagstruct_gets(t, &name) < 0 || !name || pa_tagstruct_get_sample_spec(t, &ss) < 0 || + pa_tagstruct_get_channel_map(t, &map) < 0 || pa_tagstruct_getu32(t, &sink_index) < 0 || pa_tagstruct_gets(t, &sink_name) < 0 || pa_tagstruct_getu32(t, &maxlength) < 0 || @@ -576,13 +598,12 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC pa_tagstruct_getu32(t, &tlength) < 0 || pa_tagstruct_getu32(t, &prebuf) < 0 || pa_tagstruct_getu32(t, &minreq) < 0 || - pa_tagstruct_getu32(t, &volume) < 0 || + pa_tagstruct_get_cvolume(t, &volume) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - if (!c->authorized) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); return; @@ -599,7 +620,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC return; } - if (!(s = playback_stream_new(c, sink, &ss, name, maxlength, tlength, prebuf, minreq, volume))) { + if (!(s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); return; } @@ -671,6 +692,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ uint32_t source_index; const char *name, *source_name; pa_sample_spec ss; + pa_channel_map map; pa_tagstruct *reply; pa_source *source; int corked; @@ -678,6 +700,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ if (pa_tagstruct_gets(t, &name) < 0 || !name || pa_tagstruct_get_sample_spec(t, &ss) < 0 || + pa_tagstruct_get_channel_map(t, &map) < 0 || pa_tagstruct_getu32(t, &source_index) < 0 || pa_tagstruct_gets(t, &source_name) < 0 || pa_tagstruct_getu32(t, &maxlength) < 0 || @@ -703,7 +726,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ return; } - if (!(s = record_stream_new(c, source, &ss, name, maxlength, fragment_size))) { + if (!(s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); return; } @@ -984,11 +1007,13 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ size_t length; const char *name; pa_sample_spec ss; + pa_channel_map map; pa_tagstruct *reply; assert(c && t && c->protocol && c->protocol->core); if (pa_tagstruct_gets(t, &name) < 0 || !name || pa_tagstruct_get_sample_spec(t, &ss) < 0 || + pa_tagstruct_get_channel_map(t, &map) < 0 || pa_tagstruct_getu32(t, &length) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1005,7 +1030,7 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ return; } - if (!(s = upload_stream_new(c, &ss, name, length))) { + if (!(s = upload_stream_new(c, &ss, &map, name, length))) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); return; } @@ -1042,21 +1067,22 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ return; } - pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &idx); + pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx); pa_pstream_send_simple_ack(c->pstream, tag); upload_stream_free(s); } static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t sink_index, volume; + uint32_t sink_index; + pa_cvolume volume; pa_sink *sink; const char *name, *sink_name; assert(c && t); if (pa_tagstruct_getu32(t, &sink_index) < 0 || pa_tagstruct_gets(t, &sink_name) < 0 || - pa_tagstruct_getu32(t, &volume) < 0 || + pa_tagstruct_get_cvolume(t, &volume) < 0 || pa_tagstruct_gets(t, &name) < 0 || !name || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1078,7 +1104,7 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui return; } - if (pa_scache_play_item(c->protocol->core, name, sink, volume) < 0) { + if (pa_scache_play_item(c->protocol->core, name, sink, &volume) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1116,12 +1142,13 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { pa_tagstruct_puts(t, sink->name); pa_tagstruct_puts(t, sink->description); pa_tagstruct_put_sample_spec(t, &sink->sample_spec); + pa_tagstruct_put_channel_map(t, &sink->channel_map); pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1); - pa_tagstruct_putu32(t, sink->volume); + pa_tagstruct_put_cvolume(t, pa_sink_get_volume(sink, PA_MIXER_HARDWARE)); pa_tagstruct_putu32(t, sink->monitor_source->index); pa_tagstruct_puts(t, sink->monitor_source->name); pa_tagstruct_put_usec(t, pa_sink_get_latency(sink)); - pa_tagstruct_putu32(t, sink->typeid); + pa_tagstruct_puts(t, sink->driver); } static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { @@ -1130,11 +1157,12 @@ static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { pa_tagstruct_puts(t, source->name); pa_tagstruct_puts(t, source->description); pa_tagstruct_put_sample_spec(t, &source->sample_spec); + pa_tagstruct_put_channel_map(t, &source->channel_map); pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1); pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1); pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : NULL); pa_tagstruct_put_usec(t, pa_source_get_latency(source)); - pa_tagstruct_putu32(t, source->typeid); + pa_tagstruct_puts(t, source->driver); } static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) { @@ -1142,7 +1170,7 @@ static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) { pa_tagstruct_putu32(t, client->index); pa_tagstruct_puts(t, client->name); pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1); - pa_tagstruct_putu32(t, client->typeid); + pa_tagstruct_puts(t, client->driver); } static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) { @@ -1162,11 +1190,12 @@ static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) { pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1); pa_tagstruct_putu32(t, s->sink->index); pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_putu32(t, s->volume); + pa_tagstruct_put_channel_map(t, &s->channel_map); + pa_tagstruct_put_cvolume(t, &s->volume); pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s)); pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink)); pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s))); - pa_tagstruct_putu32(t, s->typeid); + pa_tagstruct_puts(t, s->driver); } static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) { @@ -1177,19 +1206,21 @@ static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) { pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1); pa_tagstruct_putu32(t, s->source->index); pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_put_channel_map(t, &s->channel_map); pa_tagstruct_put_usec(t, pa_source_output_get_latency(s)); pa_tagstruct_put_usec(t, pa_source_get_latency(s->source)); pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s))); - pa_tagstruct_putu32(t, s->typeid); + pa_tagstruct_puts(t, s->driver); } static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) { assert(t && e); pa_tagstruct_putu32(t, e->index); pa_tagstruct_puts(t, e->name); - pa_tagstruct_putu32(t, e->volume); + pa_tagstruct_put_cvolume(t, &e->volume); pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec)); pa_tagstruct_put_sample_spec(t, &e->sample_spec); + pa_tagstruct_put_channel_map(t, &e->channel_map); pa_tagstruct_putu32(t, e->memchunk.length); pa_tagstruct_put_boolean(t, e->lazy); pa_tagstruct_puts(t, e->filename); @@ -1379,7 +1410,7 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE pa_pstream_send_tagstruct(c->pstream, reply); } -static void subscription_cb(pa_core *core, pa_subscription_event_type e, uint32_t idx, void *userdata) { +static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) { pa_tagstruct *t; struct connection *c = userdata; assert(c && core); @@ -1395,7 +1426,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type e, uint32_ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - pa_subscription_mask m; + pa_subscription_mask_t m; assert(c && t); if (pa_tagstruct_getu32(t, &m) < 0 || @@ -1423,7 +1454,8 @@ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t idx, volume; + uint32_t idx; + pa_cvolume volume; pa_sink *sink = NULL; pa_sink_input *si = NULL; const char *name = NULL; @@ -1431,7 +1463,7 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, if (pa_tagstruct_getu32(t, &idx) < 0 || (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) || - pa_tagstruct_getu32(t, &volume) || + pa_tagstruct_get_cvolume(t, &volume) || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1458,9 +1490,9 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, } if (sink) - pa_sink_set_volume(sink, volume); + pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &volume); else if (si) - pa_sink_input_set_volume(si, volume); + pa_sink_input_set_volume(si, &volume); pa_pstream_send_simple_ack(c->pstream, tag); } @@ -2032,7 +2064,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo c->protocol = p; assert(p->core); - c->client = pa_client_new(p->core, PA_TYPEID_NATIVE, "Client"); + c->client = pa_client_new(p->core, __FILE__, "Client"); assert(c->client); c->client->kill = client_kill_cb; c->client->userdata = c; diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index a3d7099c8..113919b35 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -42,8 +42,6 @@ /* Don't allow more than this many concurrent connections */ #define MAX_CONNECTIONS 10 -#define PA_TYPEID_SIMPLE PA_TYPEID_MAKE('S', 'M', 'P', 'L') - struct connection { pa_protocol_simple *protocol; pa_iochannel *io; @@ -310,7 +308,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->playback.fragment_size = 0; pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); - c->client = pa_client_new(p->core, PA_TYPEID_SIMPLE, cname); + c->client = pa_client_new(p->core, __FILE__, cname); assert(c->client); c->client->owner = p->module; c->client->kill = client_kill_cb; @@ -325,7 +323,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) goto fail; } - if (!(c->sink_input = pa_sink_input_new(sink, PA_TYPEID_SIMPLE, c->client->name, &p->sample_spec, 0, -1))) { + if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, c->client->name, &p->sample_spec, NULL, 0, -1))) { pa_log(__FILE__": Failed to create sink input.\n"); goto fail; } @@ -355,7 +353,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) goto fail; } - c->source_output = pa_source_output_new(source, PA_TYPEID_SIMPLE, c->client->name, &p->sample_spec, -1); + c->source_output = pa_source_output_new(source, __FILE__, c->client->name, &p->sample_spec, NULL, -1); if (!c->source_output) { pa_log(__FILE__": Failed to create source output.\n"); goto fail; diff --git a/polyp/resampler.c b/polyp/resampler.c index 96a1678f4..0417e44ef 100644 --- a/polyp/resampler.c +++ b/polyp/resampler.c @@ -27,6 +27,8 @@ #include #include +#include +#include #include "resampler.h" #include "sconv.h" @@ -34,24 +36,28 @@ #include "log.h" struct pa_resampler { + pa_resample_method_t resample_method; pa_sample_spec i_ss, o_ss; + pa_channel_map i_cm, o_cm; size_t i_fz, o_fz; pa_memblock_stat *memblock_stat; - void *impl_data; - int channels; - pa_resample_method resample_method; void (*impl_free)(pa_resampler *r); - void (*impl_set_input_rate)(pa_resampler *r, uint32_t rate); + void (*impl_update_input_rate)(pa_resampler *r, uint32_t rate); void (*impl_run)(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out); + void *impl_data; }; struct impl_libsamplerate { - float* i_buf, *o_buf; - unsigned i_alloc, o_alloc; + float* buf1, *buf2, *buf3, *buf4; + unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples; + pa_convert_to_float32ne_func_t to_float32ne_func; pa_convert_from_float32ne_func_t from_float32ne_func; SRC_STATE *src_state; + + int map_table[PA_CHANNELS_MAX][PA_CHANNELS_MAX]; + int map_required; }; struct impl_trivial { @@ -62,35 +68,54 @@ struct impl_trivial { static int libsamplerate_init(pa_resampler*r); static int trivial_init(pa_resampler*r); -pa_resampler* pa_resampler_new(const pa_sample_spec *a, const pa_sample_spec *b, pa_memblock_stat *s, pa_resample_method resample_method) { +pa_resampler* pa_resampler_new( + const pa_sample_spec *a, + const pa_channel_map *am, + const pa_sample_spec *b, + const pa_channel_map *bm, + pa_memblock_stat *s, + pa_resample_method_t resample_method) { + pa_resampler *r = NULL; - assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b) && resample_method != PA_RESAMPLER_INVALID); - if (a->channels != b->channels && a->channels != 1 && b->channels != 1) - goto fail; + assert(a); + assert(b); + assert(pa_sample_spec_valid(a)); + assert(pa_sample_spec_valid(b)); + assert(resample_method != PA_RESAMPLER_INVALID); - r = pa_xmalloc(sizeof(pa_resampler)); + r = pa_xnew(pa_resampler, 1); r->impl_data = NULL; r->memblock_stat = s; r->resample_method = resample_method; r->impl_free = NULL; - r->impl_set_input_rate = NULL; + r->impl_update_input_rate = NULL; r->impl_run = NULL; /* Fill sample specs */ r->i_ss = *a; r->o_ss = *b; + if (am) + r->i_cm = *am; + else + pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels); + + if (bm) + r->o_cm = *bm; + else + pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels); + r->i_fz = pa_frame_size(a); r->o_fz = pa_frame_size(b); - r->channels = a->channels; - if (b->channels < r->channels) - r->channels = b->channels; - /* Choose implementation */ - if (a->channels != b->channels || a->format != b->format || resample_method != PA_RESAMPLER_TRIVIAL) { + if (a->channels != b->channels || + a->format != b->format || + !pa_channel_map_equal(&r->i_cm, &r->o_cm) || + resample_method != PA_RESAMPLER_TRIVIAL) { + /* Use the libsamplerate based resampler for the complicated cases */ if (resample_method == PA_RESAMPLER_TRIVIAL) r->resample_method = PA_RESAMPLER_SRC_ZERO_ORDER_HOLD; @@ -123,11 +148,16 @@ void pa_resampler_free(pa_resampler *r) { } void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) { - assert(r && rate); + assert(r); + assert(rate > 0); + if (r->i_ss.rate == rate) + return; + r->i_ss.rate = rate; - if (r->impl_set_input_rate) - r->impl_set_input_rate(r, rate); + + if (r->impl_update_input_rate) + r->impl_update_input_rate(r, rate); } void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { @@ -141,168 +171,342 @@ size_t pa_resampler_request(pa_resampler *r, size_t out_length) { return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz; } -pa_resample_method pa_resampler_get_method(pa_resampler *r) { +pa_resample_method_t pa_resampler_get_method(pa_resampler *r) { assert(r); return r->resample_method; } -/* Parse a libsamplrate compatible resampling implementation */ -pa_resample_method pa_parse_resample_method(const char *string) { +static const char * const resample_methods[] = { + "src-sinc-best-quality", + "src-sinc-medium-quality", + "src-sinc-fastest", + "src-zero-order-hold", + "src-linear", + "trivial" +}; + +const char *pa_resample_method_to_string(pa_resample_method_t m) { + + if (m < 0 || m >= PA_RESAMPLER_MAX) + return NULL; + + return resample_methods[m]; +} + +pa_resample_method_t pa_parse_resample_method(const char *string) { + pa_resample_method_t m; + assert(string); - if (!strcmp(string, "src-sinc-best-quality")) - return PA_RESAMPLER_SRC_SINC_BEST_QUALITY; - else if (!strcmp(string, "src-sinc-medium-quality")) - return PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY; - else if (!strcmp(string, "src-sinc-fastest")) - return PA_RESAMPLER_SRC_SINC_FASTEST; - else if (!strcmp(string, "src-zero-order-hold")) - return PA_RESAMPLER_SRC_ZERO_ORDER_HOLD; - else if (!strcmp(string, "src-linear")) - return PA_RESAMPLER_SRC_LINEAR; - else if (!strcmp(string, "trivial")) - return PA_RESAMPLER_TRIVIAL; - else - return PA_RESAMPLER_INVALID; + for (m = 0; m < PA_RESAMPLER_MAX; m++) + if (!strcmp(string, resample_methods[m])) + return m; + + return PA_RESAMPLER_INVALID; } + /*** libsamplerate based implementation ***/ static void libsamplerate_free(pa_resampler *r) { - struct impl_libsamplerate *i; - assert(r && r->impl_data); - i = r->impl_data; - - if (i->src_state) - src_delete(i->src_state); + struct impl_libsamplerate *u; - pa_xfree(i->i_buf); - pa_xfree(i->o_buf); - pa_xfree(i); + assert(r); + assert(r->impl_data); + + u = r->impl_data; + + if (u->src_state) + src_delete(u->src_state); + + pa_xfree(u->buf1); + pa_xfree(u->buf2); + pa_xfree(u->buf3); + pa_xfree(u->buf4); + pa_xfree(u); +} + +static void calc_map_table(pa_resampler *r) { + struct impl_libsamplerate *u; + unsigned oc; + assert(r); + assert(r->impl_data); + + u = r->impl_data; + + if (!(u->map_required = (!pa_channel_map_equal(&r->i_cm, &r->o_cm) || r->i_ss.channels != r->o_ss.channels))) + return; + + for (oc = 0; oc < r->o_ss.channels; oc++) { + unsigned ic, i = 0; + + for (ic = 0; ic < r->i_ss.channels; ic++) { + pa_channel_position_t a, b; + + a = r->i_cm.map[ic]; + b = r->o_cm.map[oc]; + + if (a == b || + (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_LEFT) || + (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_RIGHT) || + (a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) || + (a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO)) + + u->map_table[oc][i++] = ic; + } + + /* Add an end marker */ + if (i < PA_CHANNELS_MAX) + u->map_table[oc][i] = -1; + } +} + +static float * convert_to_float(pa_resampler *r, float *input, unsigned n_frames) { + struct impl_libsamplerate *u; + unsigned n_samples; + + assert(r); + assert(input); + assert(r->impl_data); + u = r->impl_data; + + /* Convert the incoming sample into floats and place them in buf1 */ + + if (!u->to_float32ne_func) + return input; + + n_samples = n_frames * r->i_ss.channels; + + if (u->buf1_samples < n_samples) + u->buf1 = pa_xrealloc(u->buf1, sizeof(float) * (u->buf1_samples = n_samples)); + + u->to_float32ne_func(n_samples, input, u->buf1); + + return u->buf1; +} + +static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) { + struct impl_libsamplerate *u; + unsigned n_samples; + int i_skip, o_skip; + unsigned oc; + + assert(r); + assert(input); + assert(r->impl_data); + u = r->impl_data; + + /* Remap channels and place the result int buf2 */ + + if (!u->map_required) + return input; + + n_samples = n_frames * r->o_ss.channels; + + if (u->buf2_samples < n_samples) + u->buf2 = pa_xrealloc(u->buf2, sizeof(float) * (u->buf2_samples = n_samples)); + + memset(u->buf2, 0, n_samples * sizeof(float)); + + o_skip = sizeof(float) * r->o_ss.channels; + i_skip = sizeof(float) * r->i_ss.channels; + + for (oc = 0; oc < r->o_ss.channels; oc++) { + unsigned i; + static const float one = 1.0; + + for (i = 0; i < PA_CHANNELS_MAX && u->map_table[oc][i] >= 0; i++) + oil_vectoradd_f32( + u->buf2 + oc, o_skip, + u->buf2 + oc, o_skip, + input + u->map_table[oc][i], i_skip, + n_frames, + &one, &one); + } + + return u->buf2; +} + +static float *resample(pa_resampler *r, float *input, unsigned *n_frames) { + struct impl_libsamplerate *u; + SRC_DATA data; + unsigned out_n_frames, out_n_samples; + int ret; + + assert(r); + assert(input); + assert(n_frames); + assert(r->impl_data); + u = r->impl_data; + + /* Resample the data and place the result in buf3 */ + + if (!u->src_state) + return input; + + out_n_frames = (*n_frames*r->o_ss.rate/r->i_ss.rate)+1024; + out_n_samples = out_n_frames * r->o_ss.channels; + + if (u->buf3_samples < out_n_samples) + u->buf3 = pa_xrealloc(u->buf3, sizeof(float) * (u->buf3_samples = out_n_samples)); + + data.data_in = input; + data.input_frames = *n_frames; + + data.data_out = u->buf3; + data.output_frames = out_n_frames; + + data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; + data.end_of_input = 0; + + ret = src_process(u->src_state, &data); + assert(ret == 0); + assert((unsigned) data.input_frames_used == *n_frames); + + *n_frames = data.output_frames_gen; + + return u->buf3; +} + +static float *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) { + struct impl_libsamplerate *u; + unsigned n_samples; + + assert(r); + assert(input); + assert(r->impl_data); + u = r->impl_data; + + /* Convert the data into the correct sample type and place the result in buf4 */ + + if (!u->from_float32ne_func) + return input; + + n_samples = n_frames * r->o_ss.channels; + + if (u->buf4_samples < n_samples) + u->buf4 = pa_xrealloc(u->buf4, sizeof(float) * (u->buf4_samples = n_samples)); + + u->from_float32ne_func(n_samples, input, u->buf4); + + return u->buf4; } static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { - unsigned i_nchannels, o_nchannels, ins, ons, eff_ins, eff_ons; - float *cbuf; - struct impl_libsamplerate *i; - assert(r && in && out && in->length && in->memblock && (in->length % r->i_fz) == 0 && r->impl_data); - i = r->impl_data; + struct impl_libsamplerate *u; + float *buf, *input; + unsigned n_frames; - /* How many input samples? */ - ins = in->length/r->i_fz; - -/* pa_log("%u / %u = %u\n", in->length, r->i_fz, ins); */ - - /* How much space for output samples? */ - if (i->src_state) - ons = (ins*r->o_ss.rate/r->i_ss.rate)+1024; - else - ons = ins; + assert(r); + assert(in); + assert(out); + assert(in->length); + assert(in->memblock); + assert(in->length % r->i_fz == 0); + assert(r->impl_data); - /* How many channels? */ - if (r->i_ss.channels == r->o_ss.channels) { - i_nchannels = o_nchannels = 1; - eff_ins = ins*r->i_ss.channels; /* effective samples */ - eff_ons = ons*r->o_ss.channels; + u = r->impl_data; + + buf = input = (float*) ((uint8_t*) in->memblock->data + in->index); + n_frames = in->length / r->i_fz; + assert(n_frames > 0); + + buf = convert_to_float(r, buf, n_frames); + buf = remap_channels(r, buf, n_frames); + buf = resample(r, buf, &n_frames); + + if (n_frames) { + buf = convert_from_float(r, buf, n_frames); + + if (buf == input) { + /* Mm, no adjustment has been necessary, so let's return the original block */ + out->memblock = pa_memblock_ref(in->memblock); + out->index = in->index; + out->length = in->length; + } else { + float **p = NULL; + + out->length = n_frames * r->o_fz; + out->index = 0; + + if (buf == u->buf1) { + p = &u->buf1; + u->buf1_samples = 0; + } else if (buf == u->buf2) { + p = &u->buf2; + u->buf2_samples = 0; + } else if (buf == u->buf3) { + p = &u->buf3; + u->buf3_samples = 0; + } else if (buf == u->buf4) { + p = &u->buf4; + u->buf4_samples = 0; + } + + assert(p); + + /* Take the existing buffer and make it a memblock */ + out->memblock = pa_memblock_new_dynamic(*p, out->length, r->memblock_stat); + *p = NULL; + } } else { - i_nchannels = r->i_ss.channels; - o_nchannels = r->o_ss.channels; - eff_ins = ins; - eff_ons = ons; - } - -/* pa_log("eff_ins = %u \n", eff_ins); */ - - - out->memblock = pa_memblock_new(out->length = (ons*r->o_fz), r->memblock_stat); - out->index = 0; - assert(out->memblock); - - if (i->i_alloc < eff_ins) - i->i_buf = pa_xrealloc(i->i_buf, sizeof(float) * (i->i_alloc = eff_ins)); - assert(i->i_buf); - -/* pa_log("eff_ins = %u \n", eff_ins); */ - - i->to_float32ne_func(eff_ins, (uint8_t*) in->memblock->data+in->index, i_nchannels, i->i_buf); - - if (i->src_state) { - int ret; - SRC_DATA data; - - if (i->o_alloc < eff_ons) - i->o_buf = pa_xrealloc(i->o_buf, sizeof(float) * (i->o_alloc = eff_ons)); - assert(i->o_buf); - - data.data_in = i->i_buf; - data.input_frames = ins; - - data.data_out = i->o_buf; - data.output_frames = ons; - - data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; - data.end_of_input = 0; - - ret = src_process(i->src_state, &data); - assert(ret == 0); - assert((unsigned) data.input_frames_used == ins); - - cbuf = i->o_buf; - ons = data.output_frames_gen; - - if (r->i_ss.channels == r->o_ss.channels) - eff_ons = ons*r->o_ss.channels; - else - eff_ons = ons; - } else - cbuf = i->i_buf; - - if (eff_ons) - i->from_float32ne_func(eff_ons, cbuf, (uint8_t*)out->memblock->data+out->index, o_nchannels); - out->length = ons*r->o_fz; - - if (!out->length) { - pa_memblock_unref(out->memblock); out->memblock = NULL; + out->index = out->length = 0; } } -static void libsamplerate_set_input_rate(pa_resampler *r, uint32_t rate) { - int ret; - struct impl_libsamplerate *i; - assert(r && rate > 0 && r->impl_data); - i = r->impl_data; +static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) { + struct impl_libsamplerate *u; + + assert(r); + assert(rate > 0); + assert(r->impl_data); + u = r->impl_data; - ret = src_set_ratio(i->src_state, (double) r->o_ss.rate / r->i_ss.rate); - assert(ret == 0); + if (!u->src_state) { + int err; + u->src_state = src_new(r->resample_method, r->o_ss.channels, &err); + assert(u->src_state); + } else { + int ret = src_set_ratio(u->src_state, (double) r->o_ss.rate / rate); + assert(ret == 0); + } } static int libsamplerate_init(pa_resampler *r) { - struct impl_libsamplerate *i = NULL; + struct impl_libsamplerate *u = NULL; int err; - r->impl_data = i = pa_xmalloc(sizeof(struct impl_libsamplerate)); - - i->to_float32ne_func = pa_get_convert_to_float32ne_function(r->i_ss.format); - i->from_float32ne_func = pa_get_convert_from_float32ne_function(r->o_ss.format); + r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1); - if (!i->to_float32ne_func || !i->from_float32ne_func) - goto fail; - - if (!(i->src_state = src_new(r->resample_method, r->channels, &err)) || !i->src_state) + u->buf1 = u->buf2 = u->buf3 = u->buf4 = NULL; + u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0; + + if (r->i_ss.format == PA_SAMPLE_FLOAT32NE) + u->to_float32ne_func = NULL; + else if (!(u->to_float32ne_func = pa_get_convert_to_float32ne_function(r->i_ss.format))) goto fail; - i->i_buf = i->o_buf = NULL; - i->i_alloc = i->o_alloc = 0; + if (r->o_ss.format == PA_SAMPLE_FLOAT32NE) + u->from_float32ne_func = NULL; + else if (!(u->from_float32ne_func = pa_get_convert_from_float32ne_function(r->o_ss.format))) + goto fail; + + if (r->o_ss.rate == r->i_ss.rate) + u->src_state = NULL; + else if (!(u->src_state = src_new(r->resample_method, r->o_ss.channels, &err))) + goto fail; r->impl_free = libsamplerate_free; - r->impl_set_input_rate = libsamplerate_set_input_rate; + r->impl_update_input_rate = libsamplerate_update_input_rate; r->impl_run = libsamplerate_run; + + calc_map_table(r); return 0; fail: - pa_xfree(i); + pa_xfree(u); return -1; } @@ -310,15 +514,20 @@ fail: static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { size_t fz; - unsigned nframes; - struct impl_trivial *i; - assert(r && in && out && r->impl_data); - i = r->impl_data; + unsigned n_frames; + struct impl_trivial *u; + + assert(r); + assert(in); + assert(out); + assert(r->impl_data); + + u = r->impl_data; fz = r->i_fz; assert(fz == r->o_fz); - nframes = in->length/fz; + n_frames = in->length/fz; if (r->i_ss.rate == r->o_ss.rate) { @@ -326,25 +535,25 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out *out = *in; pa_memblock_ref(out->memblock); - i->o_counter += nframes; + u->o_counter += n_frames; } else { /* Do real resampling */ size_t l; unsigned o_index; /* The length of the new memory block rounded up */ - l = ((((nframes+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz; + l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz; out->index = 0; out->memblock = pa_memblock_new(l, r->memblock_stat); - for (o_index = 0;; o_index++, i->o_counter++) { + for (o_index = 0;; o_index++, u->o_counter++) { unsigned j; - j = (i->o_counter * r->i_ss.rate / r->o_ss.rate); - j = j > i->i_counter ? j - i->i_counter : 0; + j = (u->o_counter * r->i_ss.rate / r->o_ss.rate); + j = j > u->i_counter ? j - u->i_counter : 0; - if (j >= nframes) + if (j >= n_frames) break; assert(o_index*fz < out->memblock->length); @@ -357,56 +566,49 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out out->length = o_index*fz; } - i->i_counter += nframes; + u->i_counter += n_frames; /* Normalize counters */ - while (i->i_counter >= r->i_ss.rate) { - i->i_counter -= r->i_ss.rate; - assert(i->o_counter >= r->o_ss.rate); - i->o_counter -= r->o_ss.rate; + while (u->i_counter >= r->i_ss.rate) { + u->i_counter -= r->i_ss.rate; + assert(u->o_counter >= r->o_ss.rate); + u->o_counter -= r->o_ss.rate; } } static void trivial_free(pa_resampler *r) { assert(r); + pa_xfree(r->impl_data); } -static void trivial_set_input_rate(pa_resampler *r, uint32_t rate) { - struct impl_trivial *i; - assert(r && rate > 0 && r->impl_data); - i = r->impl_data; +static void trivial_update_input_rate(pa_resampler *r, uint32_t rate) { + struct impl_trivial *u; - i->i_counter = 0; - i->o_counter = 0; + assert(r); + assert(rate > 0); + assert(r->impl_data); + + u = r->impl_data; + u->i_counter = 0; + u->o_counter = 0; } static int trivial_init(pa_resampler*r) { - struct impl_trivial *i; - assert(r && r->i_ss.format == r->o_ss.format && r->i_ss.channels == r->o_ss.channels); + struct impl_trivial *u; + + assert(r); + assert(r->i_ss.format == r->o_ss.format); + assert(r->i_ss.channels == r->o_ss.channels); - r->impl_data = i = pa_xmalloc(sizeof(struct impl_trivial)); - i->o_counter = i->i_counter = 0; + r->impl_data = u = pa_xnew(struct impl_trivial, 1); + u->o_counter = u->i_counter = 0; r->impl_run = trivial_run; r->impl_free = trivial_free; - r->impl_set_input_rate = trivial_set_input_rate; + r->impl_update_input_rate = trivial_update_input_rate; return 0; } -const char *pa_resample_method_to_string(pa_resample_method m) { - static const char * const resample_methods[] = { - "src-sinc-best-quality", - "src-sinc-medium-quality", - "src-sinc-fastest", - "src-zero-order-hold", - "src-linear", - "trivial" - }; - if (m < 0 || m >= PA_RESAMPLER_MAX) - return NULL; - - return resample_methods[m]; -} diff --git a/polyp/resampler.h b/polyp/resampler.h index 358c872a3..e14942f32 100644 --- a/polyp/resampler.h +++ b/polyp/resampler.h @@ -27,6 +27,7 @@ #include "sample.h" #include "memblock.h" #include "memchunk.h" +#include "channelmap.h" typedef struct pa_resampler pa_resampler; @@ -39,9 +40,16 @@ typedef enum pa_resample_method { PA_RESAMPLER_SRC_LINEAR = SRC_LINEAR, PA_RESAMPLER_TRIVIAL, PA_RESAMPLER_MAX -} pa_resample_method; +} pa_resample_method_t; + +pa_resampler* pa_resampler_new( + const pa_sample_spec *a, + const pa_channel_map *am, + const pa_sample_spec *b, + const pa_channel_map *bm, + pa_memblock_stat *s, + pa_resample_method_t resample_method); -pa_resampler* pa_resampler_new(const pa_sample_spec *a, const pa_sample_spec *b, pa_memblock_stat *s, int resample_method); void pa_resampler_free(pa_resampler *r); /* Returns the size of an input memory block which is required to return the specified amount of output data */ @@ -54,12 +62,12 @@ void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out); void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate); /* Return the resampling method of the resampler object */ -pa_resample_method pa_resampler_get_method(pa_resampler *r); +pa_resample_method_t pa_resampler_get_method(pa_resampler *r); /* Try to parse the resampler method */ -pa_resample_method pa_parse_resample_method(const char *string); +pa_resample_method_t pa_parse_resample_method(const char *string); /* return a human readable string for the specified resampling method. Inverse of pa_parse_resample_method() */ -const char *pa_resample_method_to_string(pa_resample_method m); +const char *pa_resample_method_to_string(pa_resample_method_t m); #endif diff --git a/polyp/sample-util.c b/polyp/sample-util.c index cb5dd1c38..d2bb31507 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -28,6 +28,8 @@ #include #include +#include + #include "sample-util.h" pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { @@ -38,6 +40,7 @@ pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) { assert(c && c->memblock && c->memblock->data && spec && c->length); + pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec); } @@ -65,204 +68,255 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { memset(p, c, length); } -size_t pa_mix(pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const pa_sample_spec *spec, pa_volume_t volume) { - assert(channels && data && length && spec); +size_t pa_mix( + const pa_mix_info streams[], + unsigned nstreams, + void *data, + size_t length, + const pa_sample_spec *spec, + const pa_cvolume *volume) { - if (spec->format == PA_SAMPLE_S16NE) { - size_t d; - - for (d = 0;; d += sizeof(int16_t)) { - unsigned c; - int32_t sum = 0; + assert(streams && data && length && spec); + + switch (spec->format) { + case PA_SAMPLE_S16NE:{ + size_t d; + unsigned channel = 0; - if (d >= length) - return d; - - for (c = 0; c < nchannels; c++) { - int32_t v; - pa_volume_t cvolume = channels[c].volume; + for (d = 0;; d += sizeof(int16_t)) { + int32_t sum = 0; - if (d >= channels[c].chunk.length) + if (d >= length) + return d; + + if (volume->values[channel] != PA_VOLUME_MUTED) { + unsigned i; + + for (i = 0; i < nstreams; i++) { + int32_t v; + pa_volume_t cvolume = streams[i].volume.values[channel]; + + if (d >= streams[i].chunk.length) + return d; + + if (cvolume == PA_VOLUME_MUTED) + v = 0; + else { + v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); + + if (cvolume != PA_VOLUME_NORM) { + v *= cvolume; + v /= PA_VOLUME_NORM; + } + } + + sum += v; + } + + if (volume->values[channel] != PA_VOLUME_NORM) { + sum *= volume->values[channel]; + sum /= PA_VOLUME_NORM; + } + + if (sum < -0x8000) sum = -0x8000; + if (sum > 0x7FFF) sum = 0x7FFF; + + } + + *((int16_t*) data) = sum; + data = (uint8_t*) data + sizeof(int16_t); + + if (++channel >= spec->channels) + channel = 0; + } + } + + case PA_SAMPLE_U8: { + size_t d; + unsigned channel = 0; + + for (d = 0;; d ++) { + int32_t sum = 0; + + if (d >= length) + return d; + + if (volume->values[channel] != PA_VOLUME_MUTED) { + unsigned i; + + for (i = 0; i < nstreams; i++) { + int32_t v; + pa_volume_t cvolume = streams[i].volume.values[channel]; + + if (d >= streams[i].chunk.length) + return d; + + if (cvolume == PA_VOLUME_MUTED) + v = 0; + else { + v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80; + + if (cvolume != PA_VOLUME_NORM) { + v *= cvolume; + v /= PA_VOLUME_NORM; + } + } + + sum += v; + } + + if (volume->values[channel] != PA_VOLUME_NORM) { + sum *= volume->values[channel]; + sum /= PA_VOLUME_NORM; + } + + if (sum < -0x80) sum = -0x80; + if (sum > 0x7F) sum = 0x7F; + + } + + *((uint8_t*) data) = (uint8_t) (sum + 0x80); + data = (uint8_t*) data + 1; + + if (++channel >= spec->channels) + channel = 0; + } + } + + case PA_SAMPLE_FLOAT32NE: { + size_t d; + unsigned channel = 0; + + for (d = 0;; d += sizeof(float)) { + float sum = 0; + + if (d >= length) return d; - if (cvolume == PA_VOLUME_MUTED) - v = 0; - else { - v = *((int16_t*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d)); + if (volume->values[channel] != PA_VOLUME_MUTED) { + unsigned i; - if (cvolume != PA_VOLUME_NORM) { - v *= cvolume; - v /= PA_VOLUME_NORM; + for (i = 0; i < nstreams; i++) { + float v; + pa_volume_t cvolume = streams[i].volume.values[channel]; + + if (d >= streams[i].chunk.length) + return d; + + if (cvolume == PA_VOLUME_MUTED) + v = 0; + else { + v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); + + if (cvolume != PA_VOLUME_NORM) { + v *= cvolume; + v /= PA_VOLUME_NORM; + } + } + + sum += v; + } + + if (volume->values[channel] != PA_VOLUME_NORM) { + sum *= volume->values[channel]; + sum /= PA_VOLUME_NORM; } } - - sum += v; + + *((float*) data) = sum; + data = (uint8_t*) data + sizeof(float); + + if (++channel >= spec->channels) + channel = 0; } - - if (volume == PA_VOLUME_MUTED) - sum = 0; - else if (volume != PA_VOLUME_NORM) { - sum *= volume; - sum /= PA_VOLUME_NORM; - } - - if (sum < -0x8000) sum = -0x8000; - if (sum > 0x7FFF) sum = 0x7FFF; - - *((int16_t*) data) = sum; - data = (uint8_t*) data + sizeof(int16_t); } - } else if (spec->format == PA_SAMPLE_U8) { - size_t d; - - for (d = 0;; d ++) { - int32_t sum = 0; - unsigned c; - if (d >= length) - return d; - - for (c = 0; c < nchannels; c++) { - int32_t v; - pa_volume_t cvolume = channels[c].volume; - - if (d >= channels[c].chunk.length) - return d; - - if (cvolume == PA_VOLUME_MUTED) - v = 0; - else { - v = (int32_t) *((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d) - 0x80; - - if (cvolume != PA_VOLUME_NORM) { - v *= cvolume; - v /= PA_VOLUME_NORM; - } - } - - sum += v; - } - - if (volume == PA_VOLUME_MUTED) - sum = 0; - else if (volume != PA_VOLUME_NORM) { - sum *= volume; - sum /= PA_VOLUME_NORM; - } - - if (sum < -0x80) sum = -0x80; - if (sum > 0x7F) sum = 0x7F; - - *((uint8_t*) data) = (uint8_t) (sum + 0x80); - data = (uint8_t*) data + 1; - } - - } else if (spec->format == PA_SAMPLE_FLOAT32NE) { - size_t d; - - for (d = 0;; d += sizeof(float)) { - float sum = 0; - unsigned c; - - if (d >= length) - return d; - - for (c = 0; c < nchannels; c++) { - float v; - pa_volume_t cvolume = channels[c].volume; - - if (d >= channels[c].chunk.length) - return d; - - if (cvolume == PA_VOLUME_MUTED) - v = 0; - else { - v = *((float*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d)); - - if (cvolume != PA_VOLUME_NORM) - v = v*cvolume/PA_VOLUME_NORM; - } - - sum += v; - } - - if (volume == PA_VOLUME_MUTED) - sum = 0; - else if (volume != PA_VOLUME_NORM) - sum = sum*volume/PA_VOLUME_NORM; - - if (sum < -1) sum = -1; - if (sum > 1) sum = 1; - - *((float*) data) = sum; - data = (uint8_t*) data + sizeof(float); - } - } else { - abort(); + default: + abort(); } } -void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, pa_volume_t volume) { +void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvolume *volume) { assert(c && spec && (c->length % pa_frame_size(spec) == 0)); + assert(volume); - if (volume == PA_VOLUME_NORM) + if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM)) return; - if (volume == PA_VOLUME_MUTED) { + if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_MUTED)) { pa_silence_memchunk(c, spec); return; } - if (spec->format == PA_SAMPLE_S16NE) { - int16_t *d; - size_t n; + switch (spec->format) { + case PA_SAMPLE_S16NE: { + int16_t *d; + size_t n; + unsigned channel = 0; + + for (d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + int32_t t = (int32_t)(*d); + + t *= volume->values[channel]; + t /= PA_VOLUME_NORM; + + if (t < -0x8000) t = -0x8000; + if (t > 0x7FFF) t = 0x7FFF; + + *d = (int16_t) t; + + if (++channel >= spec->channels) + channel = 0; + } + } + + case PA_SAMPLE_U8: { + uint8_t *d; + size_t n; + unsigned channel = 0; + + for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) { + int32_t t = (int32_t) *d - 0x80; + + t *= volume->values[channel]; + t /= PA_VOLUME_NORM; + + if (t < -0x80) t = -0x80; + if (t > 0x7F) t = 0x7F; + + *d = (uint8_t) (t + 0x80); + + if (++channel >= spec->channels) + channel = 0; + } + } + + case PA_SAMPLE_FLOAT32NE: { + float *d; + int skip; + unsigned n; + unsigned channel; - for (d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { - int32_t t = (int32_t)(*d); + d = (float*) ((uint8_t*) c->memblock->data + c->index); + skip = spec->channels * sizeof(float); + n = c->length/sizeof(float)/spec->channels; - t *= volume; - t /= PA_VOLUME_NORM; - - if (t < -0x8000) t = -0x8000; - if (t > 0x7FFF) t = 0x7FFF; - - *d = (int16_t) t; + for (channel = 0; channel < spec->channels ; channel ++) { + float v, *t; + + if (volume->values[channel] == PA_VOLUME_NORM) + continue; + + v = (float) volume->values[channel] / PA_VOLUME_NORM; + + t = d + channel; + oil_scalarmult_f32(t, skip, t, skip, &v, n); + } } - } else if (spec->format == PA_SAMPLE_U8) { - uint8_t *d; - size_t n; - for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) { - int32_t t = (int32_t) *d - 0x80; - - t *= volume; - t /= PA_VOLUME_NORM; - - if (t < -0x80) t = -0x80; - if (t > 0x7F) t = 0x7F; - - *d = (uint8_t) (t + 0x80); - - } - } else if (spec->format == PA_SAMPLE_FLOAT32NE) { - float *d; - size_t n; - - for (d = (float*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(float); n > 0; d++, n--) { - float t = *d; - - t *= volume; - t /= PA_VOLUME_NORM; - - if (t < -1) t = -1; - if (t > 1) t = 1; - - *d = t; - } - - } else { - abort(); + default: + abort(); } } diff --git a/polyp/sample-util.h b/polyp/sample-util.h index eaebe91d9..e433f9c81 100644 --- a/polyp/sample-util.h +++ b/polyp/sample-util.h @@ -25,7 +25,7 @@ #include "sample.h" #include "memblock.h" #include "memchunk.h" - +#include "volume.h" pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec); void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec); @@ -33,12 +33,21 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec); typedef struct pa_mix_info { pa_memchunk chunk; - pa_volume_t volume; + pa_cvolume volume; void *userdata; -} pa_mix_info ; +} pa_mix_info; -size_t pa_mix(pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const pa_sample_spec *spec, pa_volume_t volume); +size_t pa_mix( + const pa_mix_info channels[], + unsigned nchannels, + void *data, + size_t length, + const pa_sample_spec *spec, + const pa_cvolume *volume); -void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, pa_volume_t volume); +void pa_volume_memchunk( + pa_memchunk*c, + const pa_sample_spec *spec, + const pa_cvolume *volume); #endif diff --git a/polyp/sample.c b/polyp/sample.c index 37ab96a0a..d587170c9 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -30,29 +30,29 @@ #include "sample.h" -size_t pa_frame_size(const pa_sample_spec *spec) { - size_t b = 1; +size_t pa_sample_size(const pa_sample_spec *spec) { assert(spec); switch (spec->format) { case PA_SAMPLE_U8: case PA_SAMPLE_ULAW: case PA_SAMPLE_ALAW: - b = 1; - break; + return 1; case PA_SAMPLE_S16LE: case PA_SAMPLE_S16BE: - b = 2; - break; + return 2; case PA_SAMPLE_FLOAT32LE: case PA_SAMPLE_FLOAT32BE: - b = 4; - break; + return 4; default: assert(0); } +} - return b * spec->channels; +size_t pa_frame_size(const pa_sample_spec *spec) { + assert(spec); + + return pa_sample_size(spec) * spec->channels; } size_t pa_bytes_per_second(const pa_sample_spec *spec) { @@ -69,10 +69,11 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) { int pa_sample_spec_valid(const pa_sample_spec *spec) { assert(spec); - if (spec->rate <= 0 || spec->channels <= 0) - return 0; - - if (spec->format >= PA_SAMPLE_MAX || spec->format < 0) + if (spec->rate <= 0 || + spec->channels <= 0 || + spec->channels > PA_CHANNELS_MAX || + spec->format >= PA_SAMPLE_MAX || + spec->format < 0) return 0; return 1; @@ -84,15 +85,15 @@ int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) { return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels); } -const char *pa_sample_format_to_string(pa_sample_format f) { +const char *pa_sample_format_to_string(pa_sample_format_t f) { static const char* const table[]= { - [PA_SAMPLE_U8] = "U8", - [PA_SAMPLE_ALAW] = "ALAW", - [PA_SAMPLE_ULAW] = "ULAW", - [PA_SAMPLE_S16LE] = "S16LE", - [PA_SAMPLE_S16BE] = "S16BE", - [PA_SAMPLE_FLOAT32LE] = "FLOAT32LE", - [PA_SAMPLE_FLOAT32BE] = "FLOAT32BE", + [PA_SAMPLE_U8] = "u8", + [PA_SAMPLE_ALAW] = "aLaw", + [PA_SAMPLE_ULAW] = "uLaw", + [PA_SAMPLE_S16LE] = "s16le", + [PA_SAMPLE_S16BE] = "s16be", + [PA_SAMPLE_FLOAT32LE] = "float32le", + [PA_SAMPLE_FLOAT32BE] = "float32be", }; if (f >= PA_SAMPLE_MAX) @@ -112,44 +113,6 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) { return s; } -pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b) { - uint64_t p = a; - p *= b; - p /= PA_VOLUME_NORM; - - return (pa_volume_t) p; -} - -pa_volume_t pa_volume_from_dB(double f) { - if (f <= PA_DECIBEL_MININFTY) - return PA_VOLUME_MUTED; - - return (pa_volume_t) (pow(10, f/20)*PA_VOLUME_NORM); -} - -double pa_volume_to_dB(pa_volume_t v) { - if (v == PA_VOLUME_MUTED) - return PA_DECIBEL_MININFTY; - - return 20*log10((double) v/PA_VOLUME_NORM); -} - -#define USER_DECIBEL_RANGE 30 - -double pa_volume_to_user(pa_volume_t v) { - double dB = pa_volume_to_dB(v); - - return dB < -USER_DECIBEL_RANGE ? 0 : dB/USER_DECIBEL_RANGE+1; -} - -pa_volume_t pa_volume_from_user(double v) { - - if (v <= 0) - return PA_VOLUME_MUTED; - - return pa_volume_from_dB((v-1)*USER_DECIBEL_RANGE); -} - void pa_bytes_snprint(char *s, size_t l, unsigned v) { if (v >= ((unsigned) 1024)*1024*1024) snprintf(s, l, "%0.1f GB", ((double) v)/1024/1024/1024); @@ -161,7 +124,7 @@ void pa_bytes_snprint(char *s, size_t l, unsigned v) { snprintf(s, l, "%u B", (unsigned) v); } -pa_sample_format pa_parse_sample_format(const char *format) { +pa_sample_format_t pa_parse_sample_format(const char *format) { if (strcasecmp(format, "s16le") == 0) return PA_SAMPLE_S16LE; diff --git a/polyp/sample.h b/polyp/sample.h index 739cb337b..c1b98f1cf 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -33,6 +33,9 @@ PA_C_DECL_BEGIN +/* Maximum allowed channels */ +#define PA_CHANNELS_MAX 16 + /** Sample format */ typedef enum pa_sample_format { PA_SAMPLE_U8, /**< Unsigned 8 Bit PCM */ @@ -44,7 +47,7 @@ typedef enum pa_sample_format { PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1..1 */ PA_SAMPLE_MAX, /**< Upper limit of valid sample types */ PA_SAMPLE_INVALID = -1 /**< An invalid value */ -} pa_sample_format; +} pa_sample_format_t; #ifdef WORDS_BIGENDIAN /** Signed 16 Bit PCM, native endian */ @@ -71,7 +74,7 @@ typedef enum pa_sample_format { /** A sample format and attribute specification */ typedef struct pa_sample_spec { - pa_sample_format format; /**< The sample format */ + pa_sample_format_t format; /**< The sample format */ uint32_t rate; /**< The sample rate. (e.g. 44100) */ uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */ } pa_sample_spec; @@ -85,6 +88,9 @@ size_t pa_bytes_per_second(const pa_sample_spec *spec); /** Return the size of a frame with the specific sample type */ size_t pa_frame_size(const pa_sample_spec *spec); +/** Return the size of a sample with the specific sample type */ +size_t pa_sample_size(const pa_sample_spec *spec); + /** Calculate the time the specified bytes take to play with the specified sample type */ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec); @@ -95,7 +101,10 @@ int pa_sample_spec_valid(const pa_sample_spec *spec); int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b); /* Return a descriptive string for the specified sample format. \since 0.8 */ -const char *pa_sample_format_to_string(pa_sample_format f); +const char *pa_sample_format_to_string(pa_sample_format_t f); + +/** Parse a sample format text. Inverse of pa_sample_format_to_string() */ +pa_sample_format_t pa_parse_sample_format(const char *format); /** Maximum required string length for pa_sample_spec_snprint() */ #define PA_SAMPLE_SPEC_SNPRINT_MAX 32 @@ -103,43 +112,9 @@ const char *pa_sample_format_to_string(pa_sample_format f); /** Pretty print a sample type specification to a string */ char* pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec); -/** Volume specification: 0: silence; < 256: diminished volume; 256: normal volume; > 256 amplified volume */ -typedef uint32_t pa_volume_t; - -/** Normal volume (100%) */ -#define PA_VOLUME_NORM (0x100) - -/** Muted volume (0%) */ -#define PA_VOLUME_MUTED (0) - -/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */ -pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b); - -/** Convert volume from decibel to linear level. \since 0.4 */ -pa_volume_t pa_volume_from_dB(double f); - -/** Convert volume from linear level to decibel. \since 0.4 */ -double pa_volume_to_dB(pa_volume_t v); - -/** Convert volume to scaled value understandable by the user (between 0 and 1). \since 0.6 */ -double pa_volume_to_user(pa_volume_t v); - -/** Convert user volume to polypaudio volume. \since 0.6 */ -pa_volume_t pa_volume_from_user(double v); - -#ifdef INFINITY -#define PA_DECIBEL_MININFTY (-INFINITY) -#else -/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). \since 0.4 */ -#define PA_DECIBEL_MININFTY (-200) -#endif - /** Pretty print a byte size value. (i.e. "2.5 MB") */ void pa_bytes_snprint(char *s, size_t l, unsigned v); -/** Parse a sample format text. Inverse of pa_sample_format_to_string() */ -pa_sample_format pa_parse_sample_format(const char *format); - PA_C_DECL_END #endif diff --git a/polyp/scache.c b/polyp/scache.c index 32c89a998..39fa26f33 100644 --- a/polyp/scache.c +++ b/polyp/scache.c @@ -52,6 +52,8 @@ #include "sound-file.h" #include "util.h" #include "log.h" +#include "channelmap.h" +#include "volume.h" #define UNLOAD_POLL_TIME 2 @@ -112,7 +114,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index); } - e->volume = PA_VOLUME_NORM; + pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX); e->last_used_time = 0; e->memchunk.memblock = NULL; e->memchunk.index = e->memchunk.length = 0; @@ -125,15 +127,20 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { return e; } -int pa_scache_add_item(pa_core *c, const char *name, pa_sample_spec *ss, pa_memchunk *chunk, uint32_t *idx) { +int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_memchunk *chunk, uint32_t *idx) { pa_scache_entry *e; assert(c && name); if (!(e = scache_add_item(c, name))) return -1; - if (ss) + if (ss) { e->sample_spec = *ss; + pa_channel_map_init_auto(&e->channel_map, ss->channels); + } + + if (map) + e->channel_map = *map; if (chunk) { e->memchunk = *chunk; @@ -161,7 +168,7 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3 if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0) return -1; - r = pa_scache_add_item(c, name, &ss, &chunk, idx); + r = pa_scache_add_item(c, name, &ss, NULL, &chunk, idx); pa_memblock_unref(chunk.memblock); return r; @@ -230,9 +237,10 @@ void pa_scache_free(pa_core *c) { c->mainloop->time_free(c->scache_auto_unload_event); } -int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t volume) { +int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cvolume *volume) { pa_scache_entry *e; char *t; + pa_cvolume r; assert(c && name && sink); if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) @@ -249,7 +257,8 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t vo return -1; t = pa_sprintf_malloc("sample:%s", name); - if (pa_play_memchunk(sink, t, &e->sample_spec, &e->memchunk, pa_volume_multiply(volume, e->volume)) < 0) { + + if (pa_play_memchunk(sink, t, &e->sample_spec, &e->channel_map, &e->memchunk, pa_sw_cvolume_multiply(&r, volume, &e->volume)) < 0) { free(t); return -1; } diff --git a/polyp/scache.h b/polyp/scache.h index c23e33de1..d667ae60c 100644 --- a/polyp/scache.h +++ b/polyp/scache.h @@ -31,8 +31,9 @@ typedef struct pa_scache_entry { uint32_t index; char *name; - uint32_t volume; + pa_cvolume volume; pa_sample_spec sample_spec; + pa_channel_map channel_map; pa_memchunk memchunk; char *filename; @@ -41,14 +42,14 @@ typedef struct pa_scache_entry { time_t last_used_time; } pa_scache_entry; -int pa_scache_add_item(pa_core *c, const char *name, pa_sample_spec *ss, pa_memchunk *chunk, uint32_t *idx); +int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_memchunk *chunk, uint32_t *idx); int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint32_t *idx); int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, uint32_t *idx); int pa_scache_add_directory_lazy(pa_core *c, const char *pathname); int pa_scache_remove_item(pa_core *c, const char *name); -int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t volume); +int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cvolume *cvolume); void pa_scache_free(pa_core *c); const char *pa_scache_get_name_by_id(pa_core *c, uint32_t id); diff --git a/polyp/sconv-s16be.c b/polyp/sconv-s16be.c index 3880b0431..8b076f06f 100644 --- a/polyp/sconv-s16be.c +++ b/polyp/sconv-s16be.c @@ -23,11 +23,19 @@ #include #endif +#include "endianmacros.h" + #define INT16_FROM INT16_FROM_BE #define INT16_TO INT16_TO_BE #define pa_sconv_s16le_to_float32ne pa_sconv_s16be_to_float32ne #define pa_sconv_s16le_from_float32ne pa_sconv_s16be_from_float32ne +#ifdef WORDS_BIGENDIAN +#define SWAP_WORDS 0 +#else +#define SWAP_WORDS 1 +#endif + #include "sconv-s16le.h" #include "sconv-s16le.c" diff --git a/polyp/sconv-s16be.h b/polyp/sconv-s16be.h index 86107fb5a..b2b6a8c74 100644 --- a/polyp/sconv-s16be.h +++ b/polyp/sconv-s16be.h @@ -22,7 +22,7 @@ USA. ***/ -void pa_sconv_s16be_to_float32ne(unsigned n, const void *a, unsigned an, float *b); -void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, void *b, unsigned bn); +void pa_sconv_s16be_to_float32ne(unsigned n, const void *a, float *b); +void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, void *b); #endif diff --git a/polyp/sconv-s16le.c b/polyp/sconv-s16le.c index c9682fff1..e47c5e8e8 100644 --- a/polyp/sconv-s16le.c +++ b/polyp/sconv-s16le.c @@ -26,6 +26,8 @@ #include #include +#include + #include "endianmacros.h" #include "sconv.h" #include "sconv-s16le.h" @@ -39,49 +41,61 @@ #define INT16_TO INT16_TO_LE #endif -void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, unsigned an, float *b) { +#ifndef SWAP_WORDS +#ifdef WORDS_BIGENDIAN +#define SWAP_WORDS 1 +#else +#define SWAP_WORDS 0 +#endif +#endif + +void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b) { const int16_t *ca = a; - assert(n && a && an && b); + assert(a); + assert(b); + +#if SWAP_WORDS == 1 + for (; n > 0; n--) { - unsigned i; - float sum = 0; - - for (i = 0; i < an; i++) { - int16_t s = *(ca++); - sum += ((float) INT16_FROM(s))/0x7FFF; - } - - if (sum > 1) - sum = 1; - if (sum < -1) - sum = -1; - - *(b++) = sum; + int16_t s = *(ca++); + *(b++) = ((float) INT16_FROM(s))/0x7FFF; } + +#else +{ + static const double add = 0, factor = 1.0/0x7FFF; + oil_scaleconv_f32_s16(b, ca, n, &add, &factor); +} +#endif } -void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) { +void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) { int16_t *cb = b; - -/* pa_log("%u %p %p %u\n", n, a, b, bn); */ - assert(n && a && b && bn); + assert(a); + assert(b); + +#if SWAP_WORDS == 1 for (; n > 0; n--) { - unsigned i; int16_t s; float v = *(a++); if (v > 1) v = 1; + if (v < -1) v = -1; s = (int16_t) (v * 0x7FFF); - s = INT16_TO(s); - - for (i = 0; i < bn; i++) - *(cb++) = s; + *(cb++) = INT16_TO(s); } + +#else +{ + static const double add = 0, factor = 0x7FFF; + oil_scaleconv_s16_f32(cb, a, n, &add, &factor); +} +#endif } diff --git a/polyp/sconv-s16le.h b/polyp/sconv-s16le.h index caed826ec..ef5e31e8a 100644 --- a/polyp/sconv-s16le.h +++ b/polyp/sconv-s16le.h @@ -22,7 +22,7 @@ USA. ***/ -void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, unsigned an, float *b); -void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b, unsigned bn); +void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b); +void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b); #endif diff --git a/polyp/sconv.c b/polyp/sconv.c index 223df5d9b..1fcb5a0c8 100644 --- a/polyp/sconv.c +++ b/polyp/sconv.c @@ -26,6 +26,10 @@ #include #include #include + +#include +#include + #include "endianmacros.h" #include "sconv.h" #include "g711.h" @@ -33,107 +37,58 @@ #include "sconv-s16le.h" #include "sconv-s16be.h" -static void u8_to_float32ne(unsigned n, const void *a, unsigned an, float *b) { - unsigned i; +static void u8_to_float32ne(unsigned n, const void *a, float *b) { const uint8_t *ca = a; - assert(n && a && an && b); + static const double add = -128.0/127.0, factor = 1.0/127.0; + + assert(a); + assert(b); - for (; n > 0; n--) { - float sum = 0; - - for (i = 0; i < an; i++) { - uint8_t v = *(ca++); - sum += (((float) v)-128)/127; - } - - if (sum > 1) - sum = 1; - if (sum < -1) - sum = -1; - - *(b++) = sum; - } + oil_scaleconv_f32_u8(b, ca, n, &add, &factor); } -static void u8_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) { - unsigned i; +static void u8_from_float32ne(unsigned n, const float *a, void *b) { uint8_t *cb = b; + static const double add = 128.0, factor = 127.0; - assert(n && a && b && bn); - for (; n > 0; n--) { - float v = *(a++); - uint8_t u; + assert(a); + assert(b); - if (v > 1) - v = 1; - - if (v < -1) - v = -1; - - u = (uint8_t) (v*127+128); - - for (i = 0; i < bn; i++) - *(cb++) = u; - } + oil_scaleconv_u8_f32(cb, a, n, &add, &factor); } -static void float32ne_to_float32ne(unsigned n, const void *a, unsigned an, float *b) { - unsigned i; - const float *ca = a; - assert(n && a && an && b); - for (; n > 0; n--) { - float sum = 0; +static void float32ne_to_float32ne(unsigned n, const void *a, float *b) { + assert(a); + assert(b); - for (i = 0; i < an; i++) - sum += *(ca++); - - if (sum > 1) - sum = 1; - if (sum < -1) - sum = -1; - - *(b++) = sum; - } + oil_memcpy(b, a, sizeof(float) * n); } -static void float32ne_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) { - unsigned i; - float *cb = b; - assert(n && a && b && bn); - for (; n > 0; n--) { - float v = *(a++); - for (i = 0; i < bn; i++) - *(cb++) = v; - } +static void float32ne_from_float32ne(unsigned n, const float *a, void *b) { + assert(a); + assert(b); + + oil_memcpy(b, a, sizeof(float) * n); } -static void ulaw_to_float32ne(unsigned n, const void *a, unsigned an, float *b) { - unsigned i; +static void ulaw_to_float32ne(unsigned n, const void *a, float *b) { const uint8_t *ca = a; - assert(n && a && an && b); - for (; n > 0; n--) { - float sum = 0; - for (i = 0; i < an; i++) - sum += st_ulaw2linear16(*ca++) * 1.0F / 0x7FFF; - - if (sum > 1) - sum = 1; - if (sum < -1) - sum = -1; - - *(b++) = sum; - } + assert(a); + assert(b); + + for (; n > 0; n--) + *(b++) = st_ulaw2linear16(*(ca++)) * 1.0F / 0x7FFF; } -static void ulaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) { - unsigned i; +static void ulaw_from_float32ne(unsigned n, const float *a, void *b) { uint8_t *cb = b; - assert(n && a && b && bn); + assert(a); + assert(b); + for (; n > 0; n--) { float v = *(a++); - uint8_t u; if (v > 1) v = 1; @@ -141,40 +96,28 @@ static void ulaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn if (v < -1) v = -1; - u = st_14linear2ulaw((int16_t) (v * 0x1FFF)); - - for (i = 0; i < bn; i++) - *(cb++) = u; + *(cb++) = st_14linear2ulaw((int16_t) (v * 0x1FFF)); } } -static void alaw_to_float32ne(unsigned n, const void *a, unsigned an, float *b) { - unsigned i; +static void alaw_to_float32ne(unsigned n, const void *a, float *b) { const uint8_t *ca = a; - assert(n && a && an && b); - for (; n > 0; n--) { - float sum = 0; - for (i = 0; i < an; i++) - sum += st_alaw2linear16(*ca++) * 1.0F / 0x7FFF; + assert(a); + assert(b); - if (sum > 1) - sum = 1; - if (sum < -1) - sum = -1; - - *(b++) = sum; - } + for (; n > 0; n--) + *(b++) = st_alaw2linear16(*(ca++)) * 1.0F / 0x7FFF; } -static void alaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) { - unsigned i; +static void alaw_from_float32ne(unsigned n, const float *a, void *b) { uint8_t *cb = b; - assert(n && a && b && bn); + assert(a); + assert(b); + for (; n > 0; n--) { float v = *(a++); - uint8_t u; if (v > 1) v = 1; @@ -182,15 +125,11 @@ static void alaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn if (v < -1) v = -1; - u = st_13linear2alaw((int16_t) (v * 0xFFF)); - - for (i = 0; i < bn; i++) - *(cb++) = u; + *(cb++) = st_13linear2alaw((int16_t) (v * 0xFFF)); } } - -pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format f) { +pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) { switch(f) { case PA_SAMPLE_U8: return u8_to_float32ne; @@ -209,7 +148,7 @@ pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_fo } } -pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format f) { +pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) { switch(f) { case PA_SAMPLE_U8: return u8_from_float32ne; diff --git a/polyp/sconv.h b/polyp/sconv.h index 2866fd419..2a0052196 100644 --- a/polyp/sconv.h +++ b/polyp/sconv.h @@ -24,10 +24,10 @@ #include "sample.h" -typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, unsigned an, float *b); -typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b, unsigned bn); +typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, float *b); +typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b); -pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format f); -pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format f); +pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f); +pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f); #endif diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 682b3222d..4a847e468 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -36,47 +36,66 @@ #define CONVERT_BUFFER_LENGTH 4096 -pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int variable_rate, int resample_method) { +pa_sink_input* pa_sink_input_new( + pa_sink *s, + const char *driver, + const char *name, + const pa_sample_spec *spec, + const pa_channel_map *map, + int variable_rate, + int resample_method) { + pa_sink_input *i; pa_resampler *resampler = NULL; int r; char st[256]; - assert(s && spec && s->state == PA_SINK_RUNNING); + pa_channel_map tmap; + + assert(s); + assert(spec); + assert(s->state == PA_SINK_RUNNING); if (pa_idxset_size(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { - pa_log(__FILE__": Failed to create sink input: too many inputs per sink.\n"); + pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink.\n"); return NULL; } if (resample_method == PA_RESAMPLER_INVALID) resample_method = s->core->resample_method; - if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec)) - if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat, resample_method))) + if (!map) { + pa_channel_map_init_auto(&tmap, spec->channels); + map = &tmap; + } + + if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec) || !pa_channel_map_equal(map, &s->channel_map)) + if (!(resampler = pa_resampler_new(spec, map, &s->sample_spec, &s->channel_map, s->core->memblock_stat, resample_method))) return NULL; - i = pa_xmalloc(sizeof(pa_sink_input)); + i = pa_xnew(pa_sink_input, 1); i->ref = 1; i->state = PA_SINK_INPUT_RUNNING; i->name = pa_xstrdup(name); - i->typeid = typeid; - i->client = NULL; + i->driver = pa_xstrdup(driver); i->owner = NULL; i->sink = s; - i->sample_spec = *spec; + i->client = NULL; + i->sample_spec = *spec; + i->channel_map = *map; + + pa_cvolume_reset(&i->volume, spec->channels); + i->peek = NULL; i->drop = NULL; i->kill = NULL; i->get_latency = NULL; - i->userdata = NULL; i->underrun = NULL; + i->userdata = NULL; - i->volume = PA_VOLUME_NORM; i->playing = 0; - i->resampled_chunk.memblock = NULL; - i->resampled_chunk.index = i->resampled_chunk.length = 0; + pa_memchunk_reset(&i->resampled_chunk); i->resampler = resampler; assert(s->core); @@ -94,7 +113,10 @@ pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *nam } void pa_sink_input_disconnect(pa_sink_input *i) { - assert(i && i->state != PA_SINK_INPUT_DISCONNECTED && i->sink && i->sink->core); + assert(i); + assert(i->state != PA_SINK_INPUT_DISCONNECTED); + assert(i->sink); + assert(i->sink->core); pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL); pa_idxset_remove_by_data(i->sink->inputs, i, NULL); @@ -106,7 +128,9 @@ void pa_sink_input_disconnect(pa_sink_input *i) { i->drop = NULL; i->kill = NULL; i->get_latency = NULL; + i->underrun = NULL; + i->playing = 0; i->state = PA_SINK_INPUT_DISCONNECTED; } @@ -120,28 +144,34 @@ static void sink_input_free(pa_sink_input* i) { if (i->resampled_chunk.memblock) pa_memblock_unref(i->resampled_chunk.memblock); + if (i->resampler) pa_resampler_free(i->resampler); pa_xfree(i->name); + pa_xfree(i->driver); pa_xfree(i); } void pa_sink_input_unref(pa_sink_input *i) { - assert(i && i->ref >= 1); + assert(i); + assert(i->ref >= 1); if (!(--i->ref)) sink_input_free(i); } pa_sink_input* pa_sink_input_ref(pa_sink_input *i) { - assert(i && i->ref >= 1); + assert(i); + assert(i->ref >= 1); + i->ref++; return i; } void pa_sink_input_kill(pa_sink_input*i) { - assert(i && i->ref >= 1); + assert(i); + assert(i->ref >= 1); if (i->kill) i->kill(i); @@ -149,7 +179,9 @@ void pa_sink_input_kill(pa_sink_input*i) { pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) { pa_usec_t r = 0; - assert(i && i->ref >= 1); + + assert(i); + assert(i->ref >= 1); if (i->get_latency) r += i->get_latency(i); @@ -160,20 +192,28 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) { return r; } -int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { +int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) { int ret = -1; - assert(i && chunk && i->ref >= 1); + int do_volume_adj_here; + + assert(i); + assert(i->ref >= 1); + assert(chunk); + assert(volume); pa_sink_input_ref(i); if (!i->peek || !i->drop || i->state == PA_SINK_INPUT_CORKED) goto finish; - + if (!i->resampler) { + do_volume_adj_here = 0; ret = i->peek(i, chunk); goto finish; } + do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map); + while (!i->resampled_chunk.memblock) { pa_memchunk tchunk; size_t l; @@ -182,6 +222,12 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { goto finish; assert(tchunk.length); + + /* It might be necessary to adjust the volume here */ + if (do_volume_adj_here) { + pa_memchunk_make_writable(&tchunk, i->sink->core->memblock_stat, 0); + pa_volume_memchunk(&tchunk, &i->sample_spec, &i->volume); + } l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); @@ -195,7 +241,9 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { pa_memblock_unref(tchunk.memblock); } - assert(i->resampled_chunk.memblock && i->resampled_chunk.length); + assert(i->resampled_chunk.memblock); + assert(i->resampled_chunk.length); + *chunk = i->resampled_chunk; pa_memblock_ref(i->resampled_chunk.memblock); @@ -207,6 +255,19 @@ finish: i->underrun(i); i->playing = ret >= 0; + + if (ret >= 0) { + /* Let's see if we had to apply the volume adjustment + * ourselves, or if this can be done by the sink for us */ + + if (do_volume_adj_here) + /* We've both the same channel map, so let's have the sink do the adjustment for us*/ + + pa_cvolume_reset(volume, i->sample_spec.channels); + else + /* We had different channel maps, so we already did the adjustment */ + *volume = i->volume; + } pa_sink_input_unref(i); @@ -214,7 +275,9 @@ finish: } void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { - assert(i && length && i->ref >= 1); + assert(i); + assert(i->ref >= 1); + assert(length > 0); if (!i->resampler) { if (i->drop) @@ -222,35 +285,50 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt return; } - assert(i->resampled_chunk.memblock && i->resampled_chunk.length >= length); + assert(i->resampled_chunk.memblock); + assert(i->resampled_chunk.length >= length); i->resampled_chunk.index += length; i->resampled_chunk.length -= length; - if (!i->resampled_chunk.length) { + if (i->resampled_chunk.length <= 0) { pa_memblock_unref(i->resampled_chunk.memblock); i->resampled_chunk.memblock = NULL; i->resampled_chunk.index = i->resampled_chunk.length = 0; } } -void pa_sink_input_set_volume(pa_sink_input *i, pa_volume_t volume) { - assert(i && i->sink && i->sink->core && i->ref >= 1); +void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) { + assert(i); + assert(i->ref >= 1); + assert(i->sink); + assert(i->sink->core); - if (i->volume != volume) { - i->volume = volume; - pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); - } + if (pa_cvolume_equal(&i->volume, volume)) + return; + + i->volume = *volume; + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); +} + +const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i) { + assert(i); + assert(i->ref >= 1); + + return &i->volume; } void pa_sink_input_cork(pa_sink_input *i, int b) { int n; - assert(i && i->ref >= 1); + + assert(i); + assert(i->ref >= 1); if (i->state == PA_SINK_INPUT_DISCONNECTED) return; n = i->state == PA_SINK_INPUT_CORKED && !b; + i->state = b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING; if (n) @@ -258,7 +336,9 @@ void pa_sink_input_cork(pa_sink_input *i, int b) { } void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) { - assert(i && i->resampler && i->ref >= 1); + assert(i); + assert(i->resampler); + assert(i->ref >= 1); if (i->sample_spec.rate == rate) return; @@ -268,7 +348,8 @@ void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) { } void pa_sink_input_set_name(pa_sink_input *i, const char *name) { - assert(i && i->ref >= 1); + assert(i); + assert(i->ref >= 1); pa_xfree(i->name); i->name = pa_xstrdup(name); @@ -276,8 +357,9 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name) { pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); } -pa_resample_method pa_sink_input_get_resample_method(pa_sink_input *i) { - assert(i && i->ref >= 1); +pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) { + assert(i); + assert(i->ref >= 1); if (!i->resampler) return PA_RESAMPLER_INVALID; diff --git a/polyp/sink-input.h b/polyp/sink-input.h index b4c3ec7f8..1db993f5c 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -33,25 +33,27 @@ typedef struct pa_sink_input pa_sink_input; #include "module.h" #include "client.h" -typedef enum { +typedef enum pa_sink_input_state { PA_SINK_INPUT_RUNNING, PA_SINK_INPUT_CORKED, PA_SINK_INPUT_DISCONNECTED -} pa_sink_input_state ; +} pa_sink_input_state_t; struct pa_sink_input { int ref; - pa_sink_input_state state; - uint32_t index; - pa_typeid_t typeid; - - char *name; + pa_sink_input_state_t state; + + char *name, *driver; pa_module *owner; - pa_client *client; + pa_sink *sink; + pa_client *client; + pa_sample_spec sample_spec; - uint32_t volume; + pa_channel_map channel_map; + + pa_cvolume volume; int (*peek) (pa_sink_input *i, pa_memchunk *chunk); void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length); @@ -67,7 +69,15 @@ struct pa_sink_input { pa_resampler *resampler; }; -pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int variable_rate, int resample_method); +pa_sink_input* pa_sink_input_new( + pa_sink *s, + const char *driver, + const char *name, + const pa_sample_spec *spec, + const pa_channel_map *map, + int variable_rate, + int resample_method); + void pa_sink_input_unref(pa_sink_input* i); pa_sink_input* pa_sink_input_ref(pa_sink_input* i); @@ -79,10 +89,11 @@ void pa_sink_input_kill(pa_sink_input*i); pa_usec_t pa_sink_input_get_latency(pa_sink_input *i); -int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk); +int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume); void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length); -void pa_sink_input_set_volume(pa_sink_input *i, pa_volume_t volume); +void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume); +const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i); void pa_sink_input_cork(pa_sink_input *i, int b); @@ -90,6 +101,6 @@ void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate); void pa_sink_input_set_name(pa_sink_input *i, const char *name); -pa_resample_method pa_sink_input_get_resample_method(pa_sink_input *i); +pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i); #endif diff --git a/polyp/sink.c b/polyp/sink.c index aac90c047..bb6566498 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -40,43 +40,54 @@ #define MAX_MIX_CHANNELS 32 -pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec) { +pa_sink* pa_sink_new( + pa_core *core, + const char *driver, + const char *name, + int fail, + const pa_sample_spec *spec, + const pa_channel_map *map) { + pa_sink *s; char *n = NULL; char st[256]; int r; - assert(core && name && *name && spec); - s = pa_xmalloc(sizeof(pa_sink)); + assert(core); + assert(name); + assert(*name); + assert(spec); + + s = pa_xnew(pa_sink, 1); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) { pa_xfree(s); return NULL; } + s->ref = 1; + s->core = core; + s->state = PA_SINK_RUNNING; s->name = pa_xstrdup(name); s->description = NULL; - s->typeid = typeid; - - s->ref = 1; - s->state = PA_SINK_RUNNING; - + s->driver = pa_xstrdup(driver); s->owner = NULL; - s->core = core; + s->sample_spec = *spec; + if (map) + s->channel_map = *map; + else + pa_channel_map_init_auto(&s->channel_map, spec->channels); + s->inputs = pa_idxset_new(NULL, NULL); - n = pa_sprintf_malloc("%s_monitor", name); - s->monitor_source = pa_source_new(core, typeid, n, 0, spec); - assert(s->monitor_source); - pa_xfree(n); - s->monitor_source->monitor_of = s; - s->monitor_source->description = pa_sprintf_malloc("Monitor source of sink '%s'", s->name); - - s->volume = PA_VOLUME_NORM; + pa_cvolume_reset(&s->sw_volume, spec->channels); + pa_cvolume_reset(&s->hw_volume, spec->channels); - s->notify = NULL; s->get_latency = NULL; + s->notify = NULL; + s->set_hw_volume = NULL; + s->get_hw_volume = NULL; s->userdata = NULL; r = pa_idxset_put(core->sinks, s, &s->index); @@ -85,6 +96,13 @@ pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fa pa_sample_spec_snprint(st, sizeof(st), spec); pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); + n = pa_sprintf_malloc("%s_monitor", name); + s->monitor_source = pa_source_new(core, driver, n, 0, spec, map); + assert(s->monitor_source); + pa_xfree(n); + s->monitor_source->monitor_of = s; + s->monitor_source->description = pa_sprintf_malloc("Monitor source of sink '%s'", s->name); + pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); return s; @@ -92,7 +110,9 @@ pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fa void pa_sink_disconnect(pa_sink* s) { pa_sink_input *i, *j = NULL; - assert(s && s->state == PA_SINK_RUNNING); + + assert(s); + assert(s->state == PA_SINK_RUNNING); pa_namereg_unregister(s->core, s->name); @@ -105,16 +125,19 @@ void pa_sink_disconnect(pa_sink* s) { pa_source_disconnect(s->monitor_source); pa_idxset_remove_by_data(s->core->sinks, s, NULL); - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); - s->notify = NULL; s->get_latency = NULL; + s->notify = NULL; + s->get_hw_volume = NULL; + s->set_hw_volume = NULL; s->state = PA_SINK_DISCONNECTED; + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); } static void sink_free(pa_sink *s) { - assert(s && s->ref == 0); + assert(s); + assert(!s->ref); if (s->state != PA_SINK_DISCONNECTED) pa_sink_disconnect(s); @@ -128,24 +151,29 @@ static void sink_free(pa_sink *s) { pa_xfree(s->name); pa_xfree(s->description); + pa_xfree(s->driver); pa_xfree(s); } void pa_sink_unref(pa_sink*s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); if (!(--s->ref)) sink_free(s); } pa_sink* pa_sink_ref(pa_sink *s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); + s->ref++; return s; } void pa_sink_notify(pa_sink*s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); if (s->notify) s->notify(s); @@ -156,20 +184,25 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) { pa_sink_input *i; unsigned n = 0; - assert(s && s->ref >= 1 && info); + assert(s); + assert(s->ref >= 1); + assert(info); for (i = pa_idxset_first(s->inputs, &idx); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &idx)) { + /* Increase ref counter, to make sure that this input doesn't + * vanish while we still need it */ pa_sink_input_ref(i); - if (pa_sink_input_peek(i, &info->chunk) < 0) { + if (pa_sink_input_peek(i, &info->chunk, &info->volume) < 0) { pa_sink_input_unref(i); continue; } - info->volume = i->volume; info->userdata = i; - assert(info->chunk.memblock && info->chunk.memblock->data && info->chunk.length); + assert(info->chunk.memblock); + assert(info->chunk.memblock->data); + assert(info->chunk.length); info++; maxinfo--; @@ -180,15 +213,21 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) { } static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t length) { - assert(s && s->ref >= 1 && info); + assert(s); + assert(s->ref >= 1); + assert(info); for (; maxinfo > 0; maxinfo--, info++) { pa_sink_input *i = info->userdata; - assert(i && info->chunk.memblock); + assert(i); + assert(info->chunk.memblock); + + /* Drop read data */ pa_sink_input_drop(i, &info->chunk, length); pa_memblock_unref(info->chunk.memblock); + /* Decrease ref counter */ pa_sink_input_unref(i); info->userdata = NULL; } @@ -197,8 +236,8 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; - size_t l; int r = -1; + assert(s); assert(s->ref >= 1); assert(length); @@ -212,37 +251,29 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { goto finish; if (n == 1) { - uint32_t volume = PA_VOLUME_NORM; - pa_sink_input *i = info[0].userdata; - assert(i); + pa_cvolume volume; + *result = info[0].chunk; pa_memblock_ref(result->memblock); if (result->length > length) result->length = length; - l = result->length; - - if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM) - volume = pa_volume_multiply(s->volume, info[0].volume); + pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); - if (volume != PA_VOLUME_NORM) { + if (!pa_cvolume_is_norm(&volume)) { pa_memchunk_make_writable(result, s->core->memblock_stat, 0); - pa_volume_memchunk(result, &s->sample_spec, volume); + pa_volume_memchunk(result, &s->sample_spec, &volume); } } else { result->memblock = pa_memblock_new(length, s->core->memblock_stat); assert(result->memblock); - result->length = l = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, s->volume); + result->length = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, &s->sw_volume); result->index = 0; - - assert(l); } - inputs_drop(s, info, n, l); - - assert(s->monitor_source); + inputs_drop(s, info, n, result->length); pa_source_post(s->monitor_source, result); r = 0; @@ -256,9 +287,14 @@ finish: int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; - size_t l; int r = -1; - assert(s && s->ref >= 1 && target && target->length && target->memblock && target->memblock->data); + + assert(s); + assert(s->ref >= 1); + assert(target); + assert(target->memblock); + assert(target->length); + assert(target->memblock->data); pa_sink_ref(s); @@ -268,27 +304,27 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { goto finish; if (n == 1) { - uint32_t volume = PA_VOLUME_NORM; + pa_cvolume volume; - l = target->length; - if (l > info[0].chunk.length) - l = info[0].chunk.length; + if (target->length > info[0].chunk.length) + target->length = info[0].chunk.length; - memcpy((uint8_t*) target->memblock->data+target->index, (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index, l); - target->length = l; + memcpy((uint8_t*) target->memblock->data + target->index, + (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index, + target->length); - if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM) - volume = pa_volume_multiply(s->volume, info[0].volume); - - if (volume != PA_VOLUME_NORM) - pa_volume_memchunk(target, &s->sample_spec, volume); + pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); + + if (!pa_cvolume_is_norm(&volume)) + pa_volume_memchunk(target, &s->sample_spec, &volume); } else - target->length = l = pa_mix(info, n, (uint8_t*) target->memblock->data+target->index, target->length, &s->sample_spec, s->volume); + target->length = pa_mix(info, n, + (uint8_t*) target->memblock->data + target->index, + target->length, + &s->sample_spec, + &s->sw_volume); - assert(l); - inputs_drop(s, info, n, l); - - assert(s->monitor_source); + inputs_drop(s, info, n, target->length); pa_source_post(s->monitor_source, target); r = 0; @@ -302,7 +338,13 @@ finish: void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { pa_memchunk chunk; size_t l, d; - assert(s && s->ref >= 1 && target && target->memblock && target->length && target->memblock->data); + + assert(s); + assert(s->ref >= 1); + assert(target); + assert(target->memblock); + assert(target->length); + assert(target->memblock->data); pa_sink_ref(s); @@ -331,7 +373,10 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { } void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { - assert(s && s->ref >= 1 && length && result); + assert(s); + assert(s->ref >= 1); + assert(length); + assert(result); /*** This needs optimization ***/ @@ -342,7 +387,8 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { } pa_usec_t pa_sink_get_latency(pa_sink *s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); if (!s->get_latency) return 0; @@ -351,7 +397,8 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) { } void pa_sink_set_owner(pa_sink *s, pa_module *m) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); s->owner = m; @@ -359,11 +406,40 @@ void pa_sink_set_owner(pa_sink *s, pa_module *m) { pa_source_set_owner(s->monitor_source, m); } -void pa_sink_set_volume(pa_sink *s, pa_volume_t volume) { - assert(s && s->ref >= 1); +void pa_sink_set_volume(pa_sink *s, pa_mixer_t m, const pa_cvolume *volume) { + pa_cvolume *v; - if (s->volume != volume) { - s->volume = volume; - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); - } + assert(s); + assert(s->ref >= 1); + assert(volume); + + if (m == PA_MIXER_HARDWARE && s->set_hw_volume) + v = &s->hw_volume; + else + v = &s->sw_volume; + + if (pa_cvolume_equal(v, volume)) + return; + + *v = *volume; + + if (v == &s->hw_volume) + if (s->set_hw_volume(s) < 0) + s->sw_volume = *volume; + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); +} + +const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_mixer_t m) { + assert(s); + assert(s->ref >= 1); + + if (m == PA_MIXER_HARDWARE && s->set_hw_volume) { + + if (s->get_hw_volume) + s->get_hw_volume(s); + + return &s->hw_volume; + } else + return &s->sw_volume; } diff --git a/polyp/sink.h b/polyp/sink.h index 22d908582..33aba2331 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -30,39 +30,55 @@ typedef struct pa_sink pa_sink; #include "sample.h" #include "idxset.h" #include "source.h" -#include "typeid.h" +#include "channelmap.h" #include "module.h" +#include "volume.h" #define PA_MAX_INPUTS_PER_SINK 6 typedef enum pa_sink_state { PA_SINK_RUNNING, PA_SINK_DISCONNECTED -} pa_sink_state; +} pa_sink_state_t; + +typedef enum pa_mixer { + PA_MIXER_SOFTWARE, + PA_MIXER_HARDWARE +} pa_mixer_t; struct pa_sink { int ref; - pa_sink_state state; - uint32_t index; - pa_typeid_t typeid; - - char *name, *description; - pa_module *owner; pa_core *core; + pa_sink_state_t state; + + char *name, *description, *driver; + pa_module *owner; + pa_sample_spec sample_spec; + pa_channel_map channel_map; + pa_idxset *inputs; - pa_source *monitor_source; - - pa_volume_t volume; + + pa_cvolume hw_volume, sw_volume; void (*notify)(pa_sink*sink); pa_usec_t (*get_latency)(pa_sink *s); + int (*set_hw_volume)(pa_sink *s); + int (*get_hw_volume)(pa_sink *s); + void *userdata; }; -pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec); +pa_sink* pa_sink_new( + pa_core *core, + const char *driver, + const char *name, + int namereg_fail, + const pa_sample_spec *spec, + const pa_channel_map *map); + void pa_sink_disconnect(pa_sink* s); void pa_sink_unref(pa_sink*s); pa_sink* pa_sink_ref(pa_sink *s); @@ -78,6 +94,7 @@ void pa_sink_notify(pa_sink*s); void pa_sink_set_owner(pa_sink *sink, pa_module *m); -void pa_sink_set_volume(pa_sink *sink, pa_volume_t volume); +void pa_sink_set_volume(pa_sink *sink, pa_mixer_t m, const pa_cvolume *volume); +const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_mixer_t m); #endif diff --git a/polyp/socket-client.c b/polyp/socket-client.c index a884aa617..29c9775ef 100644 --- a/polyp/socket-client.c +++ b/polyp/socket-client.c @@ -173,7 +173,7 @@ static void connect_fixed_cb(pa_mainloop_api *m, pa_defer_event *e, void *userda do_call(c); } -static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { +static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { pa_socket_client *c = userdata; assert(m && c && c->io_event == e && fd >= 0); do_call(c); @@ -344,7 +344,7 @@ pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[ #ifdef HAVE_LIBASYNCNS -static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { +static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { pa_socket_client *c = userdata; struct addrinfo *res = NULL; int ret; diff --git a/polyp/socket-server.c b/polyp/socket-server.c index 6f1794bc9..262b32a76 100644 --- a/polyp/socket-server.c +++ b/polyp/socket-server.c @@ -78,7 +78,7 @@ struct pa_socket_server { enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX, SOCKET_SERVER_IPV6 } type; }; -static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { +static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { pa_socket_server *s = userdata; pa_iochannel *io; int nfd; diff --git a/polyp/sound-file-stream.c b/polyp/sound-file-stream.c index a277eb254..881e30772 100644 --- a/polyp/sound-file-stream.c +++ b/polyp/sound-file-stream.c @@ -36,7 +36,6 @@ #include "log.h" #define BUF_SIZE (1024*10) -#define PA_TYPEID_SOUND_FILE PA_TYPEID_MAKE('S', 'N', 'D', 'F') struct userdata { SNDFILE *sndfile; @@ -116,15 +115,12 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t le } } -int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume) { +int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume) { struct userdata *u = NULL; SF_INFO sfinfo; pa_sample_spec ss; assert(sink && fname); - if (volume <= 0) - goto fail; - u = pa_xmalloc(sizeof(struct userdata)); u->sink_input = NULL; u->memchunk.memblock = NULL; @@ -161,10 +157,11 @@ int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume) { goto fail; } - if (!(u->sink_input = pa_sink_input_new(sink, PA_TYPEID_SOUND_FILE, fname, &ss, 0, -1))) + if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, fname, &ss, NULL, 0, -1))) goto fail; - u->sink_input->volume = volume; + if (volume) + u->sink_input->volume = *volume; u->sink_input->peek = sink_input_peek; u->sink_input->drop = sink_input_drop; u->sink_input->kill = sink_input_kill; diff --git a/polyp/sound-file-stream.h b/polyp/sound-file-stream.h index 0b383f963..2e56ef49b 100644 --- a/polyp/sound-file-stream.h +++ b/polyp/sound-file-stream.h @@ -24,6 +24,6 @@ #include "sink.h" -int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume); +int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume); #endif diff --git a/polyp/source-output.c b/polyp/source-output.c index 7a5406336..e1d8ccf72 100644 --- a/polyp/source-output.c +++ b/polyp/source-output.c @@ -33,13 +33,24 @@ #include "subscribe.h" #include "log.h" -pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int resample_method) { +pa_source_output* pa_source_output_new( + pa_source *s, + const char *driver, + const char *name, + const pa_sample_spec *spec, + const pa_channel_map *map, + int resample_method) { + pa_source_output *o; pa_resampler *resampler = NULL; int r; char st[256]; - assert(s && spec); + pa_channel_map tmap; + assert(s); + assert(spec); + assert(s->state == PA_SOURCE_RUNNING); + if (pa_idxset_size(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { pa_log(__FILE__": Failed to create source output: too many outputs per source.\n"); return NULL; @@ -48,25 +59,31 @@ pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const c if (resample_method == PA_RESAMPLER_INVALID) resample_method = s->core->resample_method; - if (!pa_sample_spec_equal(&s->sample_spec, spec)) - if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat, resample_method))) + if (!map) { + pa_channel_map_init_auto(&tmap, spec->channels); + map = &tmap; + } + + if (!pa_sample_spec_equal(&s->sample_spec, spec) || !pa_channel_map_equal(&s->channel_map, map)) + if (!(resampler = pa_resampler_new(&s->sample_spec, &s->channel_map, spec, map, s->core->memblock_stat, resample_method))) return NULL; o = pa_xmalloc(sizeof(pa_source_output)); o->ref = 1; o->state = PA_SOURCE_OUTPUT_RUNNING; o->name = pa_xstrdup(name); - o->typeid = typeid; - - o->client = NULL; + o->driver = pa_xstrdup(driver); o->owner = NULL; o->source = s; + o->client = NULL; + o->sample_spec = *spec; + o->channel_map = *map; o->push = NULL; o->kill = NULL; - o->userdata = NULL; o->get_latency = NULL; + o->userdata = NULL; o->resampler = resampler; @@ -85,7 +102,10 @@ pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const c } void pa_source_output_disconnect(pa_source_output*o) { - assert(o && o->state != PA_SOURCE_OUTPUT_DISCONNECTED && o->source && o->source->core); + assert(o); + assert(o->state != PA_SOURCE_OUTPUT_DISCONNECTED); + assert(o->source); + assert(o->source->core); pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL); pa_idxset_remove_by_data(o->source->outputs, o, NULL); @@ -95,7 +115,7 @@ void pa_source_output_disconnect(pa_source_output*o) { o->push = NULL; o->kill = NULL; - + o->get_latency = NULL; o->state = PA_SOURCE_OUTPUT_DISCONNECTED; } @@ -112,26 +132,31 @@ static void source_output_free(pa_source_output* o) { pa_resampler_free(o->resampler); pa_xfree(o->name); + pa_xfree(o->driver); pa_xfree(o); } void pa_source_output_unref(pa_source_output* o) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); if (!(--o->ref)) source_output_free(o); } pa_source_output* pa_source_output_ref(pa_source_output *o) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); + o->ref++; return o; } void pa_source_output_kill(pa_source_output*o) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); if (o->kill) o->kill(o); @@ -139,7 +164,11 @@ void pa_source_output_kill(pa_source_output*o) { void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { pa_memchunk rchunk; - assert(o && chunk && chunk->length && o->push); + + assert(o); + assert(chunk); + assert(chunk->length); + assert(o->push); if (o->state == PA_SOURCE_OUTPUT_CORKED) return; @@ -159,7 +188,9 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { } void pa_source_output_set_name(pa_source_output *o, const char *name) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); + pa_xfree(o->name); o->name = pa_xstrdup(name); @@ -167,7 +198,8 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) { } pa_usec_t pa_source_output_get_latency(pa_source_output *o) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); if (o->get_latency) return o->get_latency(o); @@ -176,7 +208,8 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) { } void pa_source_output_cork(pa_source_output *o, int b) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); if (o->state == PA_SOURCE_OUTPUT_DISCONNECTED) return; @@ -184,9 +217,10 @@ void pa_source_output_cork(pa_source_output *o, int b) { o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING; } -pa_resample_method pa_source_output_get_resample_method(pa_source_output *o) { - assert(o && o->ref >= 1); - +pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) { + assert(o); + assert(o->ref >= 1); + if (!o->resampler) return PA_RESAMPLER_INVALID; diff --git a/polyp/source-output.h b/polyp/source-output.h index ef8f9fa92..f8e4b1525 100644 --- a/polyp/source-output.h +++ b/polyp/source-output.h @@ -37,20 +37,21 @@ typedef enum { PA_SOURCE_OUTPUT_RUNNING, PA_SOURCE_OUTPUT_CORKED, PA_SOURCE_OUTPUT_DISCONNECTED -} pa_source_output_state; +} pa_source_output_state_t; struct pa_source_output { int ref; - pa_source_output_state state; - uint32_t index; - pa_typeid_t typeid; - - char *name; + pa_source_output_state_t state; + + char *name, *driver; pa_module *owner; - pa_client *client; + pa_source *source; + pa_client *client; + pa_sample_spec sample_spec; + pa_channel_map channel_map; void (*push)(pa_source_output *o, const pa_memchunk *chunk); void (*kill)(pa_source_output* o); @@ -61,7 +62,14 @@ struct pa_source_output { void *userdata; }; -pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int resample_method); +pa_source_output* pa_source_output_new( + pa_source *s, + const char *driver, + const char *name, + const pa_sample_spec *spec, + const pa_channel_map *map, + int resample_method); + void pa_source_output_unref(pa_source_output* o); pa_source_output* pa_source_output_ref(pa_source_output *o); @@ -79,6 +87,6 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *i); void pa_source_output_cork(pa_source_output *i, int b); -pa_resample_method pa_source_output_get_resample_method(pa_source_output *o); +pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o); #endif diff --git a/polyp/source.c b/polyp/source.c index c287899e4..6e377b20e 100644 --- a/polyp/source.c +++ b/polyp/source.c @@ -35,13 +35,24 @@ #include "subscribe.h" #include "log.h" -pa_source* pa_source_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec) { +pa_source* pa_source_new( + pa_core *core, + const char *driver, + const char *name, + int fail, + const pa_sample_spec *spec, + const pa_channel_map *map) { + pa_source *s; char st[256]; int r; - assert(core && spec && name && *name); + + assert(core); + assert(name); + assert(*name); + assert(spec); - s = pa_xmalloc(sizeof(pa_source)); + s = pa_xnew(pa_source, 1); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) { pa_xfree(s); @@ -49,15 +60,19 @@ pa_source* pa_source_new(pa_core *core, pa_typeid_t typeid, const char *name, in } s->ref = 1; + s->core = core; s->state = PA_SOURCE_RUNNING; - s->name = pa_xstrdup(name); s->description = NULL; - s->typeid = typeid; - + s->driver = pa_xstrdup(driver); s->owner = NULL; - s->core = core; + s->sample_spec = *spec; + if (map) + s->channel_map = *map; + else + pa_channel_map_init_auto(&s->channel_map, spec->channels); + s->outputs = pa_idxset_new(NULL, NULL); s->monitor_of = NULL; @@ -78,7 +93,9 @@ pa_source* pa_source_new(pa_core *core, pa_typeid_t typeid, const char *name, in void pa_source_disconnect(pa_source *s) { pa_source_output *o, *j = NULL; - assert(s && s->state == PA_SOURCE_RUNNING); + + assert(s); + assert(s->state == PA_SOURCE_RUNNING); pa_namereg_unregister(s->core, s->name); @@ -89,15 +106,17 @@ void pa_source_disconnect(pa_source *s) { } pa_idxset_remove_by_data(s->core->sources, s, NULL); - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + s->get_latency = NULL; s->notify = NULL; s->state = PA_SOURCE_DISCONNECTED; + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); } static void source_free(pa_source *s) { - assert(s && !s->ref); + assert(s); + assert(!s->ref); if (s->state != PA_SOURCE_DISCONNECTED) pa_source_disconnect(s); @@ -108,40 +127,49 @@ static void source_free(pa_source *s) { pa_xfree(s->name); pa_xfree(s->description); + pa_xfree(s->driver); pa_xfree(s); } void pa_source_unref(pa_source *s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); if (!(--s->ref)) source_free(s); } pa_source* pa_source_ref(pa_source *s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); + s->ref++; return s; } void pa_source_notify(pa_source*s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); if (s->notify) s->notify(s); } static int do_post(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void*userdata) { - const pa_memchunk *chunk = userdata; pa_source_output *o = p; - assert(o && o->push && del && chunk); + const pa_memchunk *chunk = userdata; + + assert(o); + assert(chunk); pa_source_output_push(o, chunk); return 0; } void pa_source_post(pa_source*s, const pa_memchunk *chunk) { - assert(s && s->ref >= 1 && chunk); + assert(s); + assert(s->ref >= 1); + assert(chunk); pa_source_ref(s); pa_idxset_foreach(s->outputs, do_post, (void*) chunk); @@ -150,11 +178,14 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) { void pa_source_set_owner(pa_source *s, pa_module *m) { assert(s); + assert(s->ref >= 1); + s->owner = m; } pa_usec_t pa_source_get_latency(pa_source *s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); if (!s->get_latency) return 0; diff --git a/polyp/source.h b/polyp/source.h index c7f8d059a..823a9424d 100644 --- a/polyp/source.h +++ b/polyp/source.h @@ -31,7 +31,7 @@ typedef struct pa_source pa_source; #include "memblock.h" #include "memchunk.h" #include "sink.h" -#include "typeid.h" +#include "channelmap.h" #include "module.h" #define PA_MAX_OUTPUTS_PER_SOURCE 16 @@ -39,28 +39,37 @@ typedef struct pa_source pa_source; typedef enum pa_source_state { PA_SOURCE_RUNNING, PA_SOURCE_DISCONNECTED -} pa_source_state; +} pa_source_state_t; struct pa_source { int ref; - pa_source_state state; - uint32_t index; - pa_typeid_t typeid; - - char *name, *description; - pa_module *owner; pa_core *core; + pa_source_state_t state; + + char *name, *description, *driver; + pa_module *owner; + pa_sample_spec sample_spec; + pa_channel_map channel_map; + pa_idxset *outputs; pa_sink *monitor_of; - + void (*notify)(pa_source*source); pa_usec_t (*get_latency)(pa_source *s); + void *userdata; }; -pa_source* pa_source_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec); +pa_source* pa_source_new( + pa_core *core, + const char *driver, + const char *name, + int namereg_fail, + const pa_sample_spec *spec, + const pa_channel_map *map); + void pa_source_disconnect(pa_source *s); void pa_source_unref(pa_source *s); pa_source* pa_source_ref(pa_source *c); diff --git a/polyp/subscribe.c b/polyp/subscribe.c index d3db90f74..e8b3c8418 100644 --- a/polyp/subscribe.c +++ b/polyp/subscribe.c @@ -41,22 +41,22 @@ struct pa_subscription { pa_core *core; int dead; - void (*callback)(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata); + void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata); void *userdata; - pa_subscription_mask mask; + pa_subscription_mask_t mask; pa_subscription *prev, *next; }; struct pa_subscription_event { - pa_subscription_event_type type; + pa_subscription_event_type_t type; uint32_t index; }; static void sched_event(pa_core *c); /* Allocate a new subscription object for the given subscription mask. Use the specified callback function and user data */ -pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask m, void (*callback)(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) { +pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata) { pa_subscription *s; assert(c); @@ -210,7 +210,7 @@ static void sched_event(pa_core *c) { } /* Append a new subscription event to the subscription event queue and schedule a main loop event */ -void pa_subscription_post(pa_core *c, pa_subscription_event_type t, uint32_t index) { +void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t index) { pa_subscription_event *e; assert(c); diff --git a/polyp/subscribe.h b/polyp/subscribe.h index 6980328fb..625159e37 100644 --- a/polyp/subscribe.h +++ b/polyp/subscribe.h @@ -28,10 +28,10 @@ typedef struct pa_subscription_event pa_subscription_event; #include "core.h" #include "native-common.h" -pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask m, void (*callback)(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); +pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata); void pa_subscription_free(pa_subscription*s); void pa_subscription_free_all(pa_core *c); -void pa_subscription_post(pa_core *c, pa_subscription_event_type t, uint32_t idx); +void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t idx); #endif diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 28b1afa6c..d49804112 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -54,7 +54,9 @@ enum tags { TAG_BOOLEAN_TRUE = '1', TAG_BOOLEAN_FALSE = '0', TAG_TIMEVAL = 'T', - TAG_USEC = 'U' /* 64bit unsigned */ + TAG_USEC = 'U' /* 64bit unsigned */, + TAG_CHANNEL_MAP = 'm', + TAG_CVOLUME = 'v' }; struct pa_tagstruct { @@ -204,6 +206,34 @@ void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) { t->length += 9; } +void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) { + unsigned i; + + assert(t); + extend(t, 2 + map->channels); + + t->data[t->length++] = TAG_CHANNEL_MAP; + t->data[t->length++] = map->channels; + + for (i = 0; i < map->channels; i ++) + t->data[t->length++] = (uint8_t) map->map[i]; +} + +void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) { + unsigned i; + + assert(t); + extend(t, 2 + cvolume->channels * sizeof(pa_volume_t)); + + t->data[t->length++] = TAG_CVOLUME; + t->data[t->length++] = cvolume->channels; + + for (i = 0; i < cvolume->channels; i ++) { + *(pa_volume_t*) (t->data + t->length) = htonl(cvolume->values[i]); + t->length += sizeof(pa_volume_t); + } +} + int pa_tagstruct_gets(pa_tagstruct*t, const char **s) { int error = 0; size_t n; @@ -283,6 +313,9 @@ int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) { ss->channels = t->data[t->rindex+2]; memcpy(&ss->rate, t->data+t->rindex+3, 4); ss->rate = ntohl(ss->rate); + + if (!pa_sample_spec_valid(ss)) + return -1; t->rindex += 7; return 0; @@ -387,3 +420,59 @@ int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) { t->rindex +=9; return 0; } + +int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) { + unsigned i; + + assert(t); + assert(map); + + if (t->rindex+2 > t->length) + return -1; + + if (t->data[t->rindex] != TAG_CHANNEL_MAP) + return -1; + + if ((map->channels = t->data[t->rindex+1]) > PA_CHANNELS_MAX) + return -1; + + if (t->rindex+2+map->channels > t->length) + return -1; + + for (i = 0; i < map->channels; i ++) + map->map[i] = (int8_t) t->data[t->rindex + 2 + i]; + + if (!pa_channel_map_valid(map)) + return -1; + + t->rindex += 2 + map->channels; + return 0; +} + +int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { + unsigned i; + + assert(t); + assert(cvolume); + + if (t->rindex+2 > t->length) + return -1; + + if (t->data[t->rindex] != TAG_CVOLUME) + return -1; + + if ((cvolume->channels = t->data[t->rindex+1]) > PA_CHANNELS_MAX) + return -1; + + if (t->rindex+2+cvolume->channels*sizeof(pa_volume_t) > t->length) + return -1; + + for (i = 0; i < cvolume->channels; i ++) + cvolume->values[i] = (pa_volume_t) ntohl(*((pa_volume_t*) (t->data + t->rindex + 2)+i)); + + if (!pa_cvolume_valid(cvolume)) + return -1; + + t->rindex += 2 + cvolume->channels * sizeof(pa_volume_t); + return 0; +} diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index 85b324b7e..cd6a8f999 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -28,6 +28,8 @@ #include #include "sample.h" +#include "channelmap.h" +#include "volume.h" typedef struct pa_tagstruct pa_tagstruct; @@ -44,6 +46,8 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct*t, const void *p, size_t length); void pa_tagstruct_put_boolean(pa_tagstruct*t, int b); void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv); void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u); +void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map); +void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume); int pa_tagstruct_gets(pa_tagstruct*t, const char **s); int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c); @@ -54,6 +58,8 @@ int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length); int pa_tagstruct_get_boolean(pa_tagstruct *t, int *b); int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv); int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u); +int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map); +int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *v); int pa_tagstruct_eof(pa_tagstruct*t); const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l); diff --git a/polyp/typeid.c b/polyp/typeid.c deleted file mode 100644 index 70d3df336..000000000 --- a/polyp/typeid.c +++ /dev/null @@ -1,33 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of polypaudio. - - polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - polypaudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -#include "typeid.h" - -char *pa_typeid_to_string(pa_typeid_t id, char *ret_s, size_t length) { - if (id == PA_TYPEID_UNKNOWN) - snprintf(ret_s, length, "????"); - else - snprintf(ret_s, length, "%c%c%c%c", (char) (id >> 24), (char) (id >> 16), (char) (id >> 8), (char) (id)); - - return ret_s; -} diff --git a/polyp/typeid.h b/polyp/typeid.h deleted file mode 100644 index cc1676bc0..000000000 --- a/polyp/typeid.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef footypeidhfoo -#define footypeidhfoo - -/* $Id$ */ - -/*** - This file is part of polypaudio. - - polypaudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - polypaudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include -#include - -#include - -PA_C_DECL_BEGIN - -typedef uint32_t pa_typeid_t; - -#define PA_TYPEID_UNKNOWN ((pa_typeid_t) -1) - -char *pa_typeid_to_string(pa_typeid_t id, char *ret_s, size_t length); - -#define PA_TYPEID_MAKE(a,b,c,d) (\ - (((pa_typeid_t) a & 0xFF) << 24) | \ - (((pa_typeid_t) b & 0xFF) << 16) | \ - (((pa_typeid_t) c & 0xFF) << 8) | \ - (((pa_typeid_t) d & 0xFF))) - -PA_C_DECL_END - -#endif diff --git a/polyp/voltest.c b/polyp/voltest.c index 286334d08..917e04d35 100644 --- a/polyp/voltest.c +++ b/polyp/voltest.c @@ -2,14 +2,19 @@ #include -#include +#include #include "gccmacro.h" int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { - int p; - for (p = 0; p <= 200; p++) { - pa_volume_t v = pa_volume_from_user((double) p/100); - double dB = pa_volume_to_dB(v); - printf("%3i%% = %u = %0.2f dB = %u = %3i%%\n", p, v, dB, pa_volume_from_dB(dB), (int) (pa_volume_to_user(v)*100)); + pa_volume_t v; + + for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) { + + double dB = pa_sw_volume_to_dB(v); + double f = pa_sw_volume_to_linear(v); + + printf("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i\n", + v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f)); + } } diff --git a/polyp/volume.c b/polyp/volume.c new file mode 100644 index 000000000..0f1531410 --- /dev/null +++ b/polyp/volume.c @@ -0,0 +1,176 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "volume.h" + +int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) { + int i; + assert(a); + assert(b); + + if (a->channels != b->channels) + return 0; + + for (i = 0; i < a->channels; i++) + if (a->values[i] != b->values[i]) + return 0; + + return 1; +} + +pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) { + int i; + + assert(a); + assert(channels > 0); + assert(channels <= PA_CHANNELS_MAX); + + a->channels = channels; + + for (i = 0; i < a->channels; i++) + a->values[i] = v; + + return a; +} + +pa_volume_t pa_cvolume_avg(const pa_cvolume *a) { + uint64_t sum = 0; + int i; + assert(a); + + for (i = 0; i < a->channels; i++) + sum += a->values[i]; + + sum /= a->channels; + + return (pa_volume_t) sum; +} + +pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) { + return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a)* pa_sw_volume_to_linear(b)); +} + +#define USER_DECIBEL_RANGE 30 + +pa_volume_t pa_sw_volume_from_dB(double dB) { + if (dB <= -USER_DECIBEL_RANGE) + return PA_VOLUME_MUTED; + + return (pa_volume_t) ((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM); +} + +double pa_sw_volume_to_dB(pa_volume_t v) { + if (v == PA_VOLUME_MUTED) + return PA_DECIBEL_MININFTY; + + return ((double) v/PA_VOLUME_NORM-1)*USER_DECIBEL_RANGE; +} + +pa_volume_t pa_sw_volume_from_linear(double v) { + + if (v <= 0) + return PA_VOLUME_MUTED; + + if (v > .999 && v < 1.001) + return PA_VOLUME_NORM; + + return pa_sw_volume_from_dB(20*log10(v)); +} + +double pa_sw_volume_to_linear(pa_volume_t v) { + + if (v == PA_VOLUME_MUTED) + return 0; + + return pow(10, pa_sw_volume_to_dB(v)/20); +} + +char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) { + unsigned channel; + int first = 1; + char *e; + + assert(s); + assert(l > 0); + assert(c); + + *(e = s) = 0; + + for (channel = 0; channel < c->channels && l > 1; channel++) { + l -= snprintf(e, l, "%s%u: %3u%%", + first ? "" : " ", + channel, + (c->values[channel]*100)/PA_VOLUME_NORM); + + e = strchr(e, 0); + first = 0; + } + + return s; +} + +/** Return non-zero if the volume of all channels is equal to the specified value */ +int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) { + unsigned c; + assert(a); + + for (c = 0; c < a->channels; c++) + if (a->values[c] != v) + return 0; + + return 1; +} + +pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) { + unsigned i; + + assert(dest); + assert(a); + assert(b); + + for (i = 0; i < a->channels || i < b->channels || i < PA_CHANNELS_MAX; i++) { + + dest->values[i] = pa_sw_volume_multiply( + i < a->channels ? a->values[i] : PA_VOLUME_NORM, + i < b->channels ? b->values[i] : PA_VOLUME_NORM); + } + + dest->channels = i; + + return dest; +} + +int pa_cvolume_valid(const pa_cvolume *v) { + assert(v); + + if (v->channels <= 0 || v->channels > PA_CHANNELS_MAX) + return 0; + + return 1; +} diff --git a/polyp/volume.h b/polyp/volume.h new file mode 100644 index 000000000..b2a480848 --- /dev/null +++ b/polyp/volume.h @@ -0,0 +1,107 @@ +#ifndef foovolumehfoo +#define foovolumehfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include + +/** \file + * Constants and routines for volume handling */ + +PA_C_DECL_BEGIN + +/** Volume specification: + * PA_VOLUME_MUTED: silence; + * < PA_VOLUME_NORM: decreased volume; + * PA_VOLUME_NORM: normal volume; + * > PA_VOLUME_NORM: increased volume */ +typedef uint32_t pa_volume_t; + +/** Normal volume (100%) */ +#define PA_VOLUME_NORM (0x10000) + +/** Muted volume (0%) */ +#define PA_VOLUME_MUTED (0) + +/** A structure encapsulating a per-channel volume */ +typedef struct pa_cvolume { + uint8_t channels; + pa_volume_t values[PA_CHANNELS_MAX]; +} pa_cvolume; + +/** Return non-zero when *a == *b */ +int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b); + +/** Set the volume of all channels to PA_VOLUME_NORM */ +#define pa_cvolume_reset(a, n) pa_cvolume_set((a), (n), PA_VOLUME_NORM) + +/** Set the volume of all channels to PA_VOLUME_MUTED */ +#define pa_cvolume_mute(a, n) pa_cvolume_set((a), (n), PA_VOLUME_MUTED) + +/** Set the volume of all channels to the specified parameter */ +pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v); + +/** Pretty print a volume structure */ +#define PA_CVOLUME_SNPRINT_MAX 64 +char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c); + +/** Return the average volume of all channels */ +pa_volume_t pa_cvolume_avg(const pa_cvolume *a); + +/** Return TRUE when the passed cvolume structure is valid, FALSE otherwise */ +int pa_cvolume_valid(const pa_cvolume *v); + +/** Return non-zero if the volume of all channels is equal to the specified value */ +int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v); + +#define pa_cvolume_is_muted(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_MUTED) +#define pa_cvolume_is_norm(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_NORM) + +/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */ +pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b); + +pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b); + +/** Convert a decibel value to a volume. \since 0.4 */ +pa_volume_t pa_sw_volume_from_dB(double f); + +/** Convert a volume to a decibel value. \since 0.4 */ +double pa_sw_volume_to_dB(pa_volume_t v); + +/** Convert a linear factor to a volume. \since 0.8 */ +pa_volume_t pa_sw_volume_from_linear(double v); + +/** Convert a volume to a linear factor. \since 0.8 */ +double pa_sw_volume_to_linear(pa_volume_t v); + +#ifdef INFINITY +#define PA_DECIBEL_MININFTY (-INFINITY) +#else +/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). \since 0.4 */ +#define PA_DECIBEL_MININFTY (-200) +#endif + +PA_C_DECL_END + +#endif diff --git a/polyp/x11prop.c b/polyp/x11prop.c index bbe3e32c1..e57fc136e 100644 --- a/polyp/x11prop.c +++ b/polyp/x11prop.c @@ -33,7 +33,7 @@ void pa_x11_set_prop(Display *d, const char *name, const char *data) { Atom a = XInternAtom(d, name, False); - XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (unsigned char*) data, strlen(data)+1); + XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (const unsigned char*) data, strlen(data)+1); } void pa_x11_del_prop(Display *d, const char *name) { diff --git a/polyp/x11wrap.c b/polyp/x11wrap.c index 64923320b..e20a50a63 100644 --- a/polyp/x11wrap.c +++ b/polyp/x11wrap.c @@ -76,7 +76,7 @@ static void work(pa_x11_wrapper *w) { } /* IO notification event for the X11 display connection */ -static void display_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { +static void display_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { pa_x11_wrapper *w = userdata; assert(m && e && fd >= 0 && w && w->ref >= 1); work(w); @@ -90,7 +90,7 @@ static void defer_event(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { } /* IO notification event for X11 internal connections */ -static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) { +static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { pa_x11_wrapper *w = userdata; assert(m && e && fd >= 0 && w && w->ref >= 1); From 8580967062c79d49c35a24052f682533d1baa461 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 27 Jan 2006 16:30:09 +0000 Subject: [PATCH 0372/1514] add support more for up to 16 auxiliary channel positions git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@464 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/channelmap.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/polyp/channelmap.h b/polyp/channelmap.h index 6466eecfd..0b9f6e26e 100644 --- a/polyp/channelmap.h +++ b/polyp/channelmap.h @@ -54,6 +54,7 @@ typedef enum { PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT, + PA_CHANNEL_POSITION_AUX0, PA_CHANNEL_POSITION_AUX1, PA_CHANNEL_POSITION_AUX2, PA_CHANNEL_POSITION_AUX3, @@ -66,6 +67,9 @@ typedef enum { PA_CHANNEL_POSITION_AUX10, PA_CHANNEL_POSITION_AUX11, PA_CHANNEL_POSITION_AUX12, + PA_CHANNEL_POSITION_AUX13, + PA_CHANNEL_POSITION_AUX14, + PA_CHANNEL_POSITION_AUX15, PA_CHANNEL_POSITION_MAX } pa_channel_position_t; From db6dc13e683fbcdb40498f7d1e1e83eba520ac4d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 28 Jan 2006 01:07:09 +0000 Subject: [PATCH 0373/1514] * add variadic function pa_tagstruct_get() and pa_tagstruct_put() for parsing/constructing tagstruct records * convert some of the tagstruct uses to this new API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@466 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 4 +- polyp/polyplib-stream.c | 29 +++--- polyp/protocol-native.c | 53 +++++----- polyp/tagstruct.c | 216 +++++++++++++++++++++++++++++++--------- polyp/tagstruct.h | 29 +++++- 5 files changed, 247 insertions(+), 84 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index ad9952a50..b24d5483a 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -46,8 +46,8 @@ AM_CFLAGS = -I$(top_srcdir) AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" -#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" +#AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" +AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index 51ee6a225..7b9d6863d 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -317,20 +317,25 @@ static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *a dev = s->context->conf->default_source; } - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); - pa_tagstruct_puts(t, s->name); - pa_tagstruct_put_sample_spec(t, &s->sample_spec); - pa_tagstruct_put_channel_map(t, &s->channel_map); - pa_tagstruct_putu32(t, PA_INVALID_INDEX); - pa_tagstruct_puts(t, dev); - pa_tagstruct_putu32(t, s->buffer_attr.maxlength); - pa_tagstruct_put_boolean(t, !!(flags & PA_STREAM_START_CORKED)); + pa_tagstruct_put(t, + PA_TAG_U32, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM, + PA_TAG_U32, tag = s->context->ctag++, + PA_TAG_STRING, s->name, + PA_TAG_SAMPLE_SPEC, &s->sample_spec, + PA_TAG_CHANNEL_MAP, &s->channel_map, + PA_TAG_U32, PA_INVALID_INDEX, + PA_TAG_STRING, dev, + PA_TAG_U32, s->buffer_attr.maxlength, + PA_TAG_BOOLEAN, !!(flags & PA_STREAM_START_CORKED), + PA_TAG_INVALID); + if (s->direction == PA_STREAM_PLAYBACK) { pa_cvolume cv; - pa_tagstruct_putu32(t, s->buffer_attr.tlength); - pa_tagstruct_putu32(t, s->buffer_attr.prebuf); - pa_tagstruct_putu32(t, s->buffer_attr.minreq); + pa_tagstruct_put(t, + PA_TAG_U32, s->buffer_attr.tlength, + PA_TAG_U32, s->buffer_attr.prebuf, + PA_TAG_U32, s->buffer_attr.minreq, + PA_TAG_INVALID); if (!volume) { pa_cvolume_reset(&cv, s->sample_spec.channels); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 0491dc411..b94903d9c 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -588,18 +588,22 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC assert(c && t && c->protocol && c->protocol->core); - if (pa_tagstruct_gets(t, &name) < 0 || !name || - pa_tagstruct_get_sample_spec(t, &ss) < 0 || - pa_tagstruct_get_channel_map(t, &map) < 0 || - pa_tagstruct_getu32(t, &sink_index) < 0 || - pa_tagstruct_gets(t, &sink_name) < 0 || - pa_tagstruct_getu32(t, &maxlength) < 0 || - pa_tagstruct_get_boolean(t, &corked) < 0 || - pa_tagstruct_getu32(t, &tlength) < 0 || - pa_tagstruct_getu32(t, &prebuf) < 0 || - pa_tagstruct_getu32(t, &minreq) < 0 || - pa_tagstruct_get_cvolume(t, &volume) < 0 || - !pa_tagstruct_eof(t)) { + if (pa_tagstruct_get( + t, + PA_TAG_STRING, &name, + PA_TAG_SAMPLE_SPEC, &ss, + PA_TAG_CHANNEL_MAP, &map, + PA_TAG_U32, &sink_index, + PA_TAG_STRING, &sink_name, + PA_TAG_U32, &maxlength, + PA_TAG_BOOLEAN, &corked, + PA_TAG_U32, &tlength, + PA_TAG_U32, &prebuf, + PA_TAG_U32, &minreq, + PA_TAG_CVOLUME, &volume, + PA_TAG_INVALID) < 0 || + !pa_tagstruct_eof(t) || + !name) { protocol_error(c); return; } @@ -1138,17 +1142,20 @@ static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { assert(t && sink); - pa_tagstruct_putu32(t, sink->index); - pa_tagstruct_puts(t, sink->name); - pa_tagstruct_puts(t, sink->description); - pa_tagstruct_put_sample_spec(t, &sink->sample_spec); - pa_tagstruct_put_channel_map(t, &sink->channel_map); - pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1); - pa_tagstruct_put_cvolume(t, pa_sink_get_volume(sink, PA_MIXER_HARDWARE)); - pa_tagstruct_putu32(t, sink->monitor_source->index); - pa_tagstruct_puts(t, sink->monitor_source->name); - pa_tagstruct_put_usec(t, pa_sink_get_latency(sink)); - pa_tagstruct_puts(t, sink->driver); + pa_tagstruct_put( + t, + PA_TAG_U32, sink->index, + PA_TAG_STRING, sink->name, + PA_TAG_STRING, sink->description, + PA_TAG_SAMPLE_SPEC, &sink->sample_spec, + PA_TAG_CHANNEL_MAP, &sink->channel_map, + PA_TAG_U32, sink->owner ? sink->owner->index : PA_INVALID_INDEX, + PA_TAG_CVOLUME, pa_sink_get_volume(sink, PA_MIXER_HARDWARE), + PA_TAG_U32, sink->monitor_source->index, + PA_TAG_STRING, sink->monitor_source->name, + PA_TAG_USEC, pa_sink_get_latency(sink), + PA_TAG_STRING, sink->driver, + PA_TAG_INVALID); } static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index d49804112..64f00e4da 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef HAVE_NETINET_IN_H #include @@ -38,26 +39,6 @@ #include "tagstruct.h" #include "xmalloc.h" -enum tags { - TAG_STRING = 't', - TAG_NULL_STRING = 'N', - TAG_U32 = 'L', - TAG_S32 = 'l', - TAG_U16 = 'S', - TAG_S16 = 's', - TAG_U8 = 'B', - TAG_S8 = 'b', - TAG_U64 = 'R', - TAG_S64 = 'r', - TAG_SAMPLE_SPEC = 'a', - TAG_ARBITRARY = 'x', - TAG_BOOLEAN_TRUE = '1', - TAG_BOOLEAN_FALSE = '0', - TAG_TIMEVAL = 'T', - TAG_USEC = 'U' /* 64bit unsigned */, - TAG_CHANNEL_MAP = 'm', - TAG_CVOLUME = 'v' -}; struct pa_tagstruct { uint8_t *data; @@ -105,18 +86,19 @@ static void extend(pa_tagstruct*t, size_t l) { t->data = pa_xrealloc(t->data, t->allocated = t->length+l+100); } + void pa_tagstruct_puts(pa_tagstruct*t, const char *s) { size_t l; assert(t); if (s) { l = strlen(s)+2; extend(t, l); - t->data[t->length] = TAG_STRING; + t->data[t->length] = PA_TAG_STRING; strcpy((char*) (t->data+t->length+1), s); t->length += l; } else { extend(t, 1); - t->data[t->length] = TAG_NULL_STRING; + t->data[t->length] = PA_TAG_STRING_NULL; t->length += 1; } } @@ -124,7 +106,7 @@ void pa_tagstruct_puts(pa_tagstruct*t, const char *s) { void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) { assert(t); extend(t, 5); - t->data[t->length] = TAG_U32; + t->data[t->length] = PA_TAG_U32; i = htonl(i); memcpy(t->data+t->length+1, &i, 4); t->length += 5; @@ -133,7 +115,7 @@ void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) { void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c) { assert(t); extend(t, 2); - t->data[t->length] = TAG_U8; + t->data[t->length] = PA_TAG_U8; *(t->data+t->length+1) = c; t->length += 2; } @@ -142,7 +124,7 @@ void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss) { uint32_t rate; assert(t && ss); extend(t, 7); - t->data[t->length] = TAG_SAMPLE_SPEC; + t->data[t->length] = PA_TAG_SAMPLE_SPEC; t->data[t->length+1] = (uint8_t) ss->format; t->data[t->length+2] = ss->channels; rate = htonl(ss->rate); @@ -155,7 +137,7 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) { assert(t && p); extend(t, 5+length); - t->data[t->length] = TAG_ARBITRARY; + t->data[t->length] = PA_TAG_ARBITRARY; tmp = htonl(length); memcpy(t->data+t->length+1, &tmp, 4); if (length) @@ -166,7 +148,7 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) { void pa_tagstruct_put_boolean(pa_tagstruct*t, int b) { assert(t); extend(t, 1); - t->data[t->length] = b ? TAG_BOOLEAN_TRUE : TAG_BOOLEAN_FALSE; + t->data[t->length] = b ? PA_TAG_BOOLEAN_TRUE : PA_TAG_BOOLEAN_FALSE; t->length += 1; } @@ -174,7 +156,7 @@ void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) { uint32_t tmp; assert(t); extend(t, 9); - t->data[t->length] = TAG_TIMEVAL; + t->data[t->length] = PA_TAG_TIMEVAL; tmp = htonl(tv->tv_sec); memcpy(t->data+t->length+1, &tmp, 4); tmp = htonl(tv->tv_usec); @@ -186,7 +168,7 @@ void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u) { uint32_t tmp; assert(t); extend(t, 9); - t->data[t->length] = TAG_USEC; + t->data[t->length] = PA_TAG_USEC; tmp = htonl((uint32_t) (u >> 32)); memcpy(t->data+t->length+1, &tmp, 4); tmp = htonl((uint32_t) u); @@ -198,7 +180,7 @@ void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) { uint32_t tmp; assert(t); extend(t, 9); - t->data[t->length] = TAG_U64; + t->data[t->length] = PA_TAG_U64; tmp = htonl((uint32_t) (u >> 32)); memcpy(t->data+t->length+1, &tmp, 4); tmp = htonl((uint32_t) u); @@ -212,7 +194,7 @@ void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) { assert(t); extend(t, 2 + map->channels); - t->data[t->length++] = TAG_CHANNEL_MAP; + t->data[t->length++] = PA_TAG_CHANNEL_MAP; t->data[t->length++] = map->channels; for (i = 0; i < map->channels; i ++) @@ -225,7 +207,7 @@ void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) { assert(t); extend(t, 2 + cvolume->channels * sizeof(pa_volume_t)); - t->data[t->length++] = TAG_CVOLUME; + t->data[t->length++] = PA_TAG_CVOLUME; t->data[t->length++] = cvolume->channels; for (i = 0; i < cvolume->channels; i ++) { @@ -243,7 +225,7 @@ int pa_tagstruct_gets(pa_tagstruct*t, const char **s) { if (t->rindex+1 > t->length) return -1; - if (t->data[t->rindex] == TAG_NULL_STRING) { + if (t->data[t->rindex] == PA_TAG_STRING_NULL) { t->rindex++; *s = NULL; return 0; @@ -252,7 +234,7 @@ int pa_tagstruct_gets(pa_tagstruct*t, const char **s) { if (t->rindex+2 > t->length) return -1; - if (t->data[t->rindex] != TAG_STRING) + if (t->data[t->rindex] != PA_TAG_STRING) return -1; error = 1; @@ -277,7 +259,7 @@ int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i) { if (t->rindex+5 > t->length) return -1; - if (t->data[t->rindex] != TAG_U32) + if (t->data[t->rindex] != PA_TAG_U32) return -1; memcpy(i, t->data+t->rindex+1, 4); @@ -292,7 +274,7 @@ int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c) { if (t->rindex+2 > t->length) return -1; - if (t->data[t->rindex] != TAG_U8) + if (t->data[t->rindex] != PA_TAG_U8) return -1; *c = t->data[t->rindex+1]; @@ -306,7 +288,7 @@ int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) { if (t->rindex+7 > t->length) return -1; - if (t->data[t->rindex] != TAG_SAMPLE_SPEC) + if (t->data[t->rindex] != PA_TAG_SAMPLE_SPEC) return -1; ss->format = t->data[t->rindex+1]; @@ -328,7 +310,7 @@ int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) { if (t->rindex+5+length > t->length) return -1; - if (t->data[t->rindex] != TAG_ARBITRARY) + if (t->data[t->rindex] != PA_TAG_ARBITRARY) return -1; memcpy(&len, t->data+t->rindex+1, 4); @@ -357,9 +339,9 @@ int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) { if (t->rindex+1 > t->length) return -1; - if (t->data[t->rindex] == TAG_BOOLEAN_TRUE) + if (t->data[t->rindex] == PA_TAG_BOOLEAN_TRUE) *b = 1; - else if (t->data[t->rindex] == TAG_BOOLEAN_FALSE) + else if (t->data[t->rindex] == PA_TAG_BOOLEAN_FALSE) *b = 0; else return -1; @@ -373,7 +355,7 @@ int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) { if (t->rindex+9 > t->length) return -1; - if (t->data[t->rindex] != TAG_TIMEVAL) + if (t->data[t->rindex] != PA_TAG_TIMEVAL) return -1; memcpy(&tv->tv_sec, t->data+t->rindex+1, 4); @@ -392,7 +374,7 @@ int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) { if (t->rindex+9 > t->length) return -1; - if (t->data[t->rindex] != TAG_USEC) + if (t->data[t->rindex] != PA_TAG_USEC) return -1; memcpy(&tmp, t->data+t->rindex+1, 4); @@ -410,7 +392,7 @@ int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) { if (t->rindex+9 > t->length) return -1; - if (t->data[t->rindex] != TAG_U64) + if (t->data[t->rindex] != PA_TAG_U64) return -1; memcpy(&tmp, t->data+t->rindex+1, 4); @@ -430,7 +412,7 @@ int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) { if (t->rindex+2 > t->length) return -1; - if (t->data[t->rindex] != TAG_CHANNEL_MAP) + if (t->data[t->rindex] != PA_TAG_CHANNEL_MAP) return -1; if ((map->channels = t->data[t->rindex+1]) > PA_CHANNELS_MAX) @@ -458,7 +440,7 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { if (t->rindex+2 > t->length) return -1; - if (t->data[t->rindex] != TAG_CVOLUME) + if (t->data[t->rindex] != PA_TAG_CVOLUME) return -1; if ((cvolume->channels = t->data[t->rindex+1]) > PA_CHANNELS_MAX) @@ -476,3 +458,147 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { t->rindex += 2 + cvolume->channels * sizeof(pa_volume_t); return 0; } + +void pa_tagstruct_put(pa_tagstruct *t, ...) { + va_list va; + assert(t); + + va_start(va, t); + + for (;;) { + int tag = va_arg(va, int); + + if (tag == PA_TAG_INVALID) + break; + + switch (tag) { + case PA_TAG_STRING: + case PA_TAG_STRING_NULL: + pa_tagstruct_puts(t, va_arg(va, char*)); + break; + + case PA_TAG_U32: + pa_tagstruct_putu32(t, va_arg(va, uint32_t)); + break; + + case PA_TAG_U8: + pa_tagstruct_putu8(t, (uint8_t) va_arg(va, int)); + break; + + case PA_TAG_U64: + pa_tagstruct_putu64(t, va_arg(va, uint64_t)); + break; + + case PA_TAG_SAMPLE_SPEC: + pa_tagstruct_put_sample_spec(t, va_arg(va, pa_sample_spec*)); + break; + + case PA_TAG_ARBITRARY: { + void *p = va_arg(va, void*); + size_t size = va_arg(va, size_t); + pa_tagstruct_put_arbitrary(t, p, size); + break; + } + + case PA_TAG_BOOLEAN_TRUE: + case PA_TAG_BOOLEAN_FALSE: + pa_tagstruct_put_boolean(t, va_arg(va, int)); + break; + + case PA_TAG_TIMEVAL: + pa_tagstruct_put_timeval(t, va_arg(va, struct timeval*)); + break; + + case PA_TAG_USEC: + pa_tagstruct_put_usec(t, va_arg(va, pa_usec_t)); + break; + + case PA_TAG_CHANNEL_MAP: + pa_tagstruct_put_channel_map(t, va_arg(va, pa_channel_map *)); + break; + + case PA_TAG_CVOLUME: + pa_tagstruct_put_cvolume(t, va_arg(va, pa_cvolume *)); + break; + + default: + abort(); + } + } + + va_end(va); +} + +int pa_tagstruct_get(pa_tagstruct *t, ...) { + va_list va; + int ret = 0; + + assert(t); + + va_start(va, t); + while (ret == 0) { + int tag = va_arg(va, int); + + if (tag == PA_TAG_INVALID) + break; + + switch (tag) { + case PA_TAG_STRING: + case PA_TAG_STRING_NULL: + ret = pa_tagstruct_gets(t, va_arg(va, const char**)); + break; + + case PA_TAG_U32: + ret = pa_tagstruct_getu32(t, va_arg(va, uint32_t*)); + break; + + case PA_TAG_U8: + ret = pa_tagstruct_getu8(t, va_arg(va, uint8_t*)); + break; + + case PA_TAG_U64: + ret = pa_tagstruct_getu64(t, va_arg(va, uint64_t*)); + break; + + case PA_TAG_SAMPLE_SPEC: + ret = pa_tagstruct_get_sample_spec(t, va_arg(va, pa_sample_spec*)); + break; + + case PA_TAG_ARBITRARY: { + const void **p = va_arg(va, const void**); + size_t size = va_arg(va, size_t); + ret = pa_tagstruct_get_arbitrary(t, p, size); + break; + } + + case PA_TAG_BOOLEAN_TRUE: + case PA_TAG_BOOLEAN_FALSE: + ret = pa_tagstruct_get_boolean(t, va_arg(va, int*)); + break; + + case PA_TAG_TIMEVAL: + ret = pa_tagstruct_get_timeval(t, va_arg(va, struct timeval*)); + break; + + case PA_TAG_USEC: + ret = pa_tagstruct_get_usec(t, va_arg(va, pa_usec_t*)); + break; + + case PA_TAG_CHANNEL_MAP: + ret = pa_tagstruct_get_channel_map(t, va_arg(va, pa_channel_map *)); + break; + + case PA_TAG_CVOLUME: + ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *)); + break; + + + default: + abort(); + } + + } + + va_end(va); + return ret; +} diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index cd6a8f999..b41936ffa 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -33,10 +33,35 @@ typedef struct pa_tagstruct pa_tagstruct; +enum { + PA_TAG_INVALID = 0, + PA_TAG_STRING = 't', + PA_TAG_STRING_NULL = 'N', + PA_TAG_U32 = 'L', + PA_TAG_U8 = 'B', + PA_TAG_U64 = 'R', + PA_TAG_SAMPLE_SPEC = 'a', + PA_TAG_ARBITRARY = 'x', + PA_TAG_BOOLEAN_TRUE = '1', + PA_TAG_BOOLEAN_FALSE = '0', + PA_TAG_BOOLEAN = PA_TAG_BOOLEAN_TRUE, + PA_TAG_TIMEVAL = 'T', + PA_TAG_USEC = 'U' /* 64bit unsigned */, + PA_TAG_CHANNEL_MAP = 'm', + PA_TAG_CVOLUME = 'v' +}; + + + pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length); void pa_tagstruct_free(pa_tagstruct*t); uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l); +int pa_tagstruct_eof(pa_tagstruct*t); +const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l); + +void pa_tagstruct_put(pa_tagstruct *t, ...); + void pa_tagstruct_puts(pa_tagstruct*t, const char *s); void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c); void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i); @@ -49,6 +74,8 @@ void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u); void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map); void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume); +int pa_tagstruct_get(pa_tagstruct *t, ...); + int pa_tagstruct_gets(pa_tagstruct*t, const char **s); int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c); int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i); @@ -61,7 +88,5 @@ int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u); int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map); int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *v); -int pa_tagstruct_eof(pa_tagstruct*t); -const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l); #endif From f8808a25257a79256f1c7c651386b94c259cbc57 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 30 Jan 2006 11:38:20 +0000 Subject: [PATCH 0374/1514] Print an error message before aborting. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@467 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/sample-util.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/polyp/sample-util.c b/polyp/sample-util.c index d2bb31507..2310f3cb4 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -30,6 +30,7 @@ #include +#include "log.h" #include "sample-util.h" pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { @@ -316,6 +317,8 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol } default: + pa_log_error(__FILE__": ERROR: Unable to change volume of format %s.\n", + pa_sample_format_to_string(spec->format)); abort(); } } From 22db575adc789c9bf6deabefe0843addc7ed2910 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 30 Jan 2006 11:49:03 +0000 Subject: [PATCH 0375/1514] Breaks missing from conversion to a switch statement. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@468 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/sample-util.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/polyp/sample-util.c b/polyp/sample-util.c index 2310f3cb4..52974c46a 100644 --- a/polyp/sample-util.c +++ b/polyp/sample-util.c @@ -270,6 +270,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol if (++channel >= spec->channels) channel = 0; } + break; } case PA_SAMPLE_U8: { @@ -291,6 +292,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol if (++channel >= spec->channels) channel = 0; } + break; } case PA_SAMPLE_FLOAT32NE: { @@ -314,6 +316,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol t = d + channel; oil_scalarmult_f32(t, skip, t, skip, &v, n); } + break; } default: From 7da06d3fe7ce17422e1175339bd59b0dfb716443 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 30 Jan 2006 12:21:53 +0000 Subject: [PATCH 0376/1514] Fixes for the new infrastructure so that the solaris module compiles. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@469 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-solaris.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/polyp/module-solaris.c b/polyp/module-solaris.c index ce9308be3..f85e71dfb 100644 --- a/polyp/module-solaris.c +++ b/polyp/module-solaris.c @@ -57,8 +57,6 @@ PA_MODULE_DESCRIPTION("Solaris Sink/Source") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= buffer_size=") -#define PA_TYPEID_SOLARIS PA_TYPEID_MAKE('S', 'L', 'R', 'S') - struct userdata { pa_sink *sink; pa_source *source; @@ -398,7 +396,7 @@ int pa__init(pa_core *c, pa_module*m) { u->core = c; if (mode != O_WRONLY) { - u->source = pa_source_new(c, PA_TYPEID_SOLARIS, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); assert(u->source); u->source->userdata = u; u->source->get_latency = source_get_latency_cb; @@ -408,7 +406,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source = NULL; if (mode != O_RDONLY) { - u->sink = pa_sink_new(c, PA_TYPEID_SOLARIS, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; From dd7b38024a027155a81f4ead9c1e6732768bf152 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 30 Jan 2006 12:58:53 +0000 Subject: [PATCH 0377/1514] Fixes for the new infrastructure so that the waveout module compiles. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@470 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-waveout.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/polyp/module-waveout.c b/polyp/module-waveout.c index a5ef847b5..e9d9f12e3 100644 --- a/polyp/module-waveout.c +++ b/polyp/module-waveout.c @@ -43,8 +43,6 @@ PA_MODULE_DESCRIPTION("Windows waveOut Sink/Source") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("sink_name= source_name= record= playback= format= channels= rate= fragments= fragment_size=") -#define PA_TYPEID_WAVEOUT PA_TYPEID_MAKE('W', 'A', 'V', 'E') - #define DEFAULT_SINK_NAME "wave_output" #define DEFAULT_SOURCE_NAME "wave_input" @@ -442,7 +440,7 @@ int pa__init(pa_core *c, pa_module*m) { InitializeCriticalSection(&u->crit); if (hwi != INVALID_HANDLE_VALUE) { - u->source = pa_source_new(c, PA_TYPEID_WAVEOUT, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss); + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); assert(u->source); u->source->userdata = u; u->source->notify = notify_source_cb; @@ -453,7 +451,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source = NULL; if (hwo != INVALID_HANDLE_VALUE) { - u->sink = pa_sink_new(c, PA_TYPEID_WAVEOUT, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss); + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); assert(u->sink); u->sink->notify = notify_sink_cb; u->sink->get_latency = sink_get_latency_cb; From c34f35a797590376f8a979c1bfc2a35b3bd80f75 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 3 Feb 2006 09:14:30 +0000 Subject: [PATCH 0378/1514] Reverting an incorrect checkin. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@471 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index b24d5483a..73039ed1b 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -46,8 +46,7 @@ AM_CFLAGS = -I$(top_srcdir) AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -#AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" -AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" +AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" From bbc6dd68e22171670271e694f3a42db736eca60d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 3 Feb 2006 12:23:17 +0000 Subject: [PATCH 0379/1514] Volume adjustment must be done _after_ dropping the chunk since drop will reject a modified chunk. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@472 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/sink-input.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/polyp/sink-input.c b/polyp/sink-input.c index 4a847e468..f447b8cf8 100644 --- a/polyp/sink-input.c +++ b/polyp/sink-input.c @@ -222,12 +222,6 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) goto finish; assert(tchunk.length); - - /* It might be necessary to adjust the volume here */ - if (do_volume_adj_here) { - pa_memchunk_make_writable(&tchunk, i->sink->core->memblock_stat, 0); - pa_volume_memchunk(&tchunk, &i->sample_spec, &i->volume); - } l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); @@ -237,6 +231,12 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) i->drop(i, &tchunk, l); tchunk.length = l; + /* It might be necessary to adjust the volume here */ + if (do_volume_adj_here) { + pa_memchunk_make_writable(&tchunk, i->sink->core->memblock_stat, 0); + pa_volume_memchunk(&tchunk, &i->sample_spec, &i->volume); + } + pa_resampler_run(i->resampler, &tchunk, &i->resampled_chunk); pa_memblock_unref(tchunk.memblock); } From d431e0094b95f671a9f557887dc4cfbc40a28d10 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 3 Feb 2006 13:33:21 +0000 Subject: [PATCH 0380/1514] Use defines and not hard coded values for volume levels. Caused incorrect volume levels for all esound clients that changed the volume. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@473 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/protocol-esound.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index ce183a6f4..40b0be28f 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -474,7 +474,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v assert(k); for (conn = pa_idxset_first(c->protocol->connections, &idx); conn; conn = pa_idxset_next(c->protocol->connections, &idx)) { - int format = ESD_BITS16 | ESD_STEREO, rate = 44100, lvolume = 0xFF, rvolume = 0xFF; + int format = ESD_BITS16 | ESD_STEREO, rate = 44100, lvolume = ESD_VOLUME_BASE, rvolume = ESD_VOLUME_BASE; if (conn->state != ESD_STREAMING_DATA) continue; @@ -483,8 +483,8 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v if (conn->sink_input) { rate = conn->sink_input->sample_spec.rate; - lvolume = (conn->sink_input->volume.values[0]*0xFF)/0x100; - rvolume = (conn->sink_input->volume.values[1]*0xFF)/0x100; + lvolume = (conn->sink_input->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM; + rvolume = (conn->sink_input->volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM; format = format_native2esd(&conn->sink_input->sample_spec); } @@ -544,11 +544,11 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v response += sizeof(int); /* left */ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*0xFF)/0x100); + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); response += sizeof(int); /*right*/ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*0xFF)/0x100); + *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); response += sizeof(int); /*format*/ @@ -578,9 +578,9 @@ static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t idx = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(const int*)data)-1; lvolume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); - lvolume = (lvolume*0x100)/0xFF; + lvolume = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; rvolume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 2)); - rvolume = (rvolume*0x100)/0xFF; + rvolume = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; ok = connection_write(c, sizeof(int)); assert(ok); From 5c01c1029fc73016184119ce81bb9ae95b3c1f0f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 3 Feb 2006 14:36:19 +0000 Subject: [PATCH 0381/1514] Fix endian conversion macros and reformat them to be a bit more readable. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@474 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/endianmacros.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/polyp/endianmacros.h b/polyp/endianmacros.h index d07652fb3..91489cd32 100644 --- a/polyp/endianmacros.h +++ b/polyp/endianmacros.h @@ -28,10 +28,10 @@ #include #endif -#define INT16_SWAP(x) ((int16_t)(((uint16_t) x >> 8) | ((uint16_t) x << 8))) -#define UINT16_SWAP(x) ((uint16_t)(((uint16_t) x >> 8) | ((uint16_t) x << 8))) -#define INT32_SWAP(x) ((int32_t)(((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 16) | (((uint32_t) x) >> 16) & 0xFF00)) -#define UINT32_SWAP(x) ((uint32_t)(((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 16) | ((((uint32_t) x) >> 16) & 0xFF00))) +#define INT16_SWAP(x) ( (int16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) ) +#define UINT16_SWAP(x) ( (uint16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) ) +#define INT32_SWAP(x) ( (int32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) ) +#define UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) ) #ifdef WORDS_BIGENDIAN #define INT16_FROM_LE(x) INT16_SWAP(x) From d9bfd5b294f2771d9c41fa100d835067dcc7f718 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 3 Feb 2006 14:39:39 +0000 Subject: [PATCH 0382/1514] Let's have just one endian conversion macro suite. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@475 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/endianmacros.h | 3 +++ polyp/esound.h | 6 +---- polyp/protocol-esound.c | 54 ++++++++++++++++++++--------------------- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/polyp/endianmacros.h b/polyp/endianmacros.h index 91489cd32..3ab1826a5 100644 --- a/polyp/endianmacros.h +++ b/polyp/endianmacros.h @@ -33,6 +33,9 @@ #define INT32_SWAP(x) ( (int32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) ) #define UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) ) +#define MAYBE_INT32_SWAP(c,x) ((c) ? INT32_SWAP(x) : x) +#define MAYBE_UINT32_SWAP(c,x) ((c) ? UINT32_SWAP(x) : x) + #ifdef WORDS_BIGENDIAN #define INT16_FROM_LE(x) INT16_SWAP(x) #define INT16_FROM_BE(x) ((int16_t)(x)) diff --git a/polyp/esound.h b/polyp/esound.h index 5dc2583b1..9c507ef9c 100644 --- a/polyp/esound.h +++ b/polyp/esound.h @@ -200,14 +200,10 @@ enum esd_client_state { }; typedef int esd_client_state_t; -/* switch endian order for cross platform playing */ -#define swap_endian_32(x) ((x >> 24) | ((x >> 8) & 0xFF00) | (((x & 0xFF00) << 8)) | (x << 24)) -#define maybe_swap_endian_32(c,x) ((c) ? swap_endian_32(x) : x) - /* the endian key is transferred in binary, if it's read into int, */ /* and matches ESD_ENDIAN_KEY (ENDN), then the endianness of the */ /* server and the client match; if it's SWAP_ENDIAN_KEY, swap data */ -#define ESD_SWAP_ENDIAN_KEY ((uint32_t) swap_endian_32(ESD_ENDIAN_KEY)) +#define ESD_SWAP_ENDIAN_KEY (UINT32_SWAP(ESD_ENDIAN_KEY)) #endif diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 40b0be28f..6f004e168 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -46,6 +46,7 @@ #include "xmalloc.h" #include "log.h" #include "util.h" +#include "endianmacros.h" /* Don't accept more connection than this */ #define MAX_CONNECTIONS 10 @@ -301,8 +302,8 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t size_t l; assert(c && length == (sizeof(int)*2+ESD_NAME_MAX)); - format = maybe_swap_endian_32(c->swap_byte_order, *(const int*)data); - rate = maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); + format = MAYBE_INT32_SWAP(c->swap_byte_order, *(const int*)data); + rate = MAYBE_INT32_SWAP(c->swap_byte_order, *((const int*)data + 1)); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -357,8 +358,8 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co size_t l; assert(c && length == (sizeof(int)*2+ESD_NAME_MAX)); - format = maybe_swap_endian_32(c->swap_byte_order, *(const int*)data); - rate = maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); + format = MAYBE_INT32_SWAP(c->swap_byte_order, *(const int*)data); + rate = MAYBE_INT32_SWAP(c->swap_byte_order, *((const int*)data + 1)); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -433,7 +434,7 @@ static int esd_proto_get_latency(struct connection *c, PA_GCC_UNUSED esd_proto_t lag = connection_write(c, sizeof(int)); assert(lag); - *lag = c->swap_byte_order ? swap_endian_32(latency) : latency; + *lag = MAYBE_INT32_SWAP(c->swap_byte_order, latency); return 0; } @@ -451,8 +452,8 @@ static int esd_proto_server_info(struct connection *c, PA_GCC_UNUSED esd_proto_t response = connection_write(c, sizeof(int)*3); assert(response); *(response++) = 0; - *(response++) = maybe_swap_endian_32(c->swap_byte_order, rate); - *(response++) = maybe_swap_endian_32(c->swap_byte_order, format); + *(response++) = MAYBE_INT32_SWAP(c->swap_byte_order, rate); + *(response++) = MAYBE_INT32_SWAP(c->swap_byte_order, format); return 0; } @@ -489,7 +490,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v } /* id */ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (int) (conn->index+1)); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, (int) (conn->index+1)); response += sizeof(int); /* name */ @@ -498,19 +499,19 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v response += ESD_NAME_MAX; /* rate */ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, rate); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, rate); response += sizeof(int); /* left */ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, lvolume); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, lvolume); response += sizeof(int); /*right*/ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, rvolume); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, rvolume); response += sizeof(int); /*format*/ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, format); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, format); response += sizeof(int); t-= k; @@ -529,7 +530,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v assert(t >= s*2); /* id */ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (int) (ce->index+1)); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1)); response += sizeof(int); /* name */ @@ -540,23 +541,23 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v response += ESD_NAME_MAX; /* rate */ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, ce->sample_spec.rate); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, ce->sample_spec.rate); response += sizeof(int); /* left */ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); response += sizeof(int); /*right*/ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); response += sizeof(int); /*format*/ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, format_native2esd(&ce->sample_spec)); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ce->sample_spec)); response += sizeof(int); /*length*/ - *((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (int) ce->memchunk.length); + *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, (int) ce->memchunk.length); response += sizeof(int); t -= s; @@ -576,10 +577,10 @@ static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t struct connection *conn; assert(c && data && length == sizeof(int)*3); - idx = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(const int*)data)-1; - lvolume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); + idx = MAYBE_UINT32_SWAP(c->swap_byte_order, *(const int*)data)-1; + lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, *((const int*)data + 1)); lvolume = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; - rvolume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 2)); + rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, *((const int*)data + 2)); rvolume = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; ok = connection_write(c, sizeof(int)); @@ -606,13 +607,13 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1]; assert(c && data && length == (ESD_NAME_MAX+3*sizeof(int))); - format = maybe_swap_endian_32(c->swap_byte_order, *(const int*)data); - rate = maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1)); + format = MAYBE_INT32_SWAP(c->swap_byte_order, *(const int*)data); + rate = MAYBE_INT32_SWAP(c->swap_byte_order, *((const int*)data + 1)); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); - sc_length = (size_t) maybe_swap_endian_32(c->swap_byte_order, (*((const int*)data + 2))); + sc_length = (size_t) MAYBE_INT32_SWAP(c->swap_byte_order, (*((const int*)data + 2))); if (sc_length >= MAX_CACHE_SAMPLE_SIZE) return -1; @@ -668,7 +669,7 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque uint32_t idx; assert(c && data && length == sizeof(int)); - idx = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(const int*)data)-1; + idx = (uint32_t) MAYBE_INT32_SWAP(c->swap_byte_order, *(const int*)data)-1; ok = connection_write(c, sizeof(int)); assert(ok); @@ -729,8 +730,7 @@ static int do_read(struct connection *c) { if ((c->read_data_length+= r) >= sizeof(c->request)) { struct proto_handler *handler; - if (c->swap_byte_order) - c->request = swap_endian_32(c->request); + c->request = MAYBE_INT32_SWAP(c->swap_byte_order, c->request); if (c->request < ESD_PROTO_CONNECT || c->request > ESD_PROTO_MAX) { pa_log(__FILE__": recieved invalid request.\n"); From 8d91ffe4b42d460efff32c36edc51ee01f3af442 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 10 Feb 2006 08:44:42 +0000 Subject: [PATCH 0383/1514] Install the new headers for channels and volume. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@476 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 73039ed1b..e2154b322 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -250,6 +250,7 @@ mainloop_test_glib12_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) polypinclude_HEADERS = \ cdecl.h \ + channelmap.h \ glib-mainloop.h \ mainloop.h \ mainloop-api.h \ @@ -265,7 +266,8 @@ polypinclude_HEADERS = \ polyplib-stream.h \ polyplib-subscribe.h \ polyplib-version.h \ - sample.h + sample.h \ + volume.h if HAVE_HOWL polypinclude_HEADERS += \ From 4ab432a81952b5ef608775522d27ad9709b97307 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 10 Feb 2006 12:05:33 +0000 Subject: [PATCH 0384/1514] Fix some new alignment bugs in the tagstruct handling. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@477 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/tagstruct.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 64f00e4da..676f67ded 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -203,6 +203,7 @@ void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) { void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) { unsigned i; + pa_volume_t vol; assert(t); extend(t, 2 + cvolume->channels * sizeof(pa_volume_t)); @@ -211,7 +212,8 @@ void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) { t->data[t->length++] = cvolume->channels; for (i = 0; i < cvolume->channels; i ++) { - *(pa_volume_t*) (t->data + t->length) = htonl(cvolume->values[i]); + vol = htonl(cvolume->values[i]); + memcpy(t->data + t->length, &vol, sizeof(pa_volume_t)); t->length += sizeof(pa_volume_t); } } @@ -433,6 +435,7 @@ int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) { int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { unsigned i; + pa_volume_t vol; assert(t); assert(cvolume); @@ -449,8 +452,10 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { if (t->rindex+2+cvolume->channels*sizeof(pa_volume_t) > t->length) return -1; - for (i = 0; i < cvolume->channels; i ++) - cvolume->values[i] = (pa_volume_t) ntohl(*((pa_volume_t*) (t->data + t->rindex + 2)+i)); + for (i = 0; i < cvolume->channels; i ++) { + memcpy(&vol, t->data + t->rindex + 2 + i * sizeof(pa_volume_t), sizeof(pa_volume_t)); + cvolume->values[i] = (pa_volume_t) ntohl(vol); + } if (!pa_cvolume_valid(cvolume)) return -1; From bbaf1543bd77e5c428e5e4c7d40fde0a42bf3daf Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 13 Feb 2006 13:28:45 +0000 Subject: [PATCH 0385/1514] Split mainloop_iterate() into three, distinct parts. Allows for more flexible use, like having the poll() run in a separate thread. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@478 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/mainloop.c | 165 +++++++++++++++++++++++++++++++++-------------- polyp/mainloop.h | 25 +++++-- 2 files changed, 137 insertions(+), 53 deletions(-) diff --git a/polyp/mainloop.c b/polyp/mainloop.c index 26ba2425e..e131e1a16 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -84,10 +84,20 @@ struct pa_mainloop { unsigned max_pollfds, n_pollfds; int rebuild_pollfds; - int quit, running, retval; + int prepared_timeout; + + int quit, retval; pa_mainloop_api api; int deferred_pending; + + enum { + STATE_PASSIVE, + STATE_PREPARED, + STATE_POLLING, + STATE_POLLED, + STATE_QUIT + } state; }; /* IO events */ @@ -145,11 +155,7 @@ static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { assert(e && e->mainloop); e->events = events; - if (e->pollfd) - e->pollfd->events = - (events & PA_IO_EVENT_INPUT ? POLLIN : 0) | - (events & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | - POLLERR | POLLHUP; + e->mainloop->rebuild_pollfds = 1; } static void mainloop_io_free(pa_io_event *e) { @@ -310,12 +316,14 @@ pa_mainloop *pa_mainloop_new(void) { m->pollfds = NULL; m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0; - m->quit = m->running = m->retval = 0; + m->quit = m->retval = 0; m->api = vtable; m->api.userdata = m; m->deferred_pending = 0; + + m->state = STATE_PASSIVE; return m; } @@ -367,7 +375,7 @@ static int defer_foreach(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void*use void pa_mainloop_free(pa_mainloop* m) { int all = 1; - assert(m); + assert(m && (m->state != STATE_POLLING)); pa_idxset_foreach(m->io_events, io_foreach, &all); pa_idxset_foreach(m->time_events, time_foreach, &all); @@ -427,6 +435,8 @@ static void rebuild_pollfds(pa_mainloop *m) { p++; m->n_pollfds++; } + + m->rebuild_pollfds = 0; } static int dispatch_pollfds(pa_mainloop *m) { @@ -548,65 +558,122 @@ static int dispatch_timeout(pa_mainloop *m) { return r; } -int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) { - int r, t, dispatched = 0; - assert(m && !m->running); +int pa_mainloop_prepare(pa_mainloop *m, int timeout) { + int dispatched = 0; - m->running ++; + assert(m && (m->state == STATE_PASSIVE)); + + scan_dead(m); if (m->quit) goto quit; - scan_dead(m); dispatched += dispatch_defer(m); - if(m->quit) + if (m->quit) goto quit; - - if (m->rebuild_pollfds) { + + if (m->rebuild_pollfds) rebuild_pollfds(m); - m->rebuild_pollfds = 0; - } - t = block ? calc_next_timeout(m) : 0; + m->prepared_timeout = calc_next_timeout(m); + if ((timeout >= 0) && (m->prepared_timeout > timeout)) + m->prepared_timeout = timeout; - r = poll(m->pollfds, m->n_pollfds, t); + m->state = STATE_PREPARED; - if (r < 0) { - if (errno == EINTR) - r = 0; - else - pa_log(__FILE__": select(): %s\n", strerror(errno)); - } else { - dispatched += dispatch_timeout(m); - - if(m->quit) - goto quit; - - if (r > 0) { - dispatched += dispatch_pollfds(m); - - if(m->quit) - goto quit; - } - } - - m->running--; - -/* pa_log("dispatched: %i\n", dispatched); */ - - return r < 0 ? -1 : dispatched; + return dispatched; quit: - - m->running--; - - if (retval) - *retval = m->retval; + + m->state = STATE_QUIT; return -2; } +int pa_mainloop_poll(pa_mainloop *m) { + int r; + + assert(m && (m->state == STATE_PREPARED)); + + m->state = STATE_POLLING; + + r = poll(m->pollfds, m->n_pollfds, m->prepared_timeout); + + if ((r < 0) && (errno == EINTR)) + r = 0; + + if (r < 0) + m->state = STATE_PASSIVE; + else + m->state = STATE_POLLED; + + return r; +} + +int pa_mainloop_dispatch(pa_mainloop *m) { + int dispatched = 0; + + assert(m && (m->state == STATE_POLLED)); + + dispatched += dispatch_timeout(m); + + if (m->quit) + goto quit; + + dispatched += dispatch_pollfds(m); + + if (m->quit) + goto quit; + + m->state = STATE_PASSIVE; + + return dispatched; + +quit: + + m->state = STATE_QUIT; + + return -2; +} + +int pa_mainloop_get_retval(pa_mainloop *m) { + assert(m); + return m->retval; +} + +int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) { + int r, dispatched = 0; + + assert(m); + + r = pa_mainloop_prepare(m, block ? -1 : 0); + if (r < 0) { + if ((r == -2) && retval) + *retval = pa_mainloop_get_retval(m); + return r; + } + + dispatched += r; + + r = pa_mainloop_poll(m); + if (r < 0) { + pa_log(__FILE__": poll(): %s\n", strerror(errno)); + return r; + } + + r = pa_mainloop_dispatch(m); + if (r < 0) { + if ((r == -2) && retval) + *retval = pa_mainloop_get_retval(m); + return r; + } + + dispatched += r; + + return dispatched; +} + int pa_mainloop_run(pa_mainloop *m, int *retval) { int r; while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0); diff --git a/polyp/mainloop.h b/polyp/mainloop.h index 06764907c..2be9e6ff0 100644 --- a/polyp/mainloop.h +++ b/polyp/mainloop.h @@ -46,10 +46,27 @@ pa_mainloop *pa_mainloop_new(void); /** Free a main loop object */ void pa_mainloop_free(pa_mainloop* m); -/** Run a single iteration of the main loop. Returns a negative value -on error or exit request. If block is nonzero, block for events if -none are queued. Optionally return the return value as specified with -the main loop's quit() routine in the integer variable retval points + +/** Prepare for a single iteration of the main loop. Returns a negative value +on error or exit request. timeout specifies a maximum timeout for the subsequent +poll, or -1 for blocking behaviour. Defer events are also dispatched when this +function is called. On success returns the number of source dispatched in this +iteration.*/ +int pa_mainloop_prepare(pa_mainloop *m, int timeout); +/** Execute the previously prepared poll. Returns a negative value on error.*/ +int pa_mainloop_poll(pa_mainloop *m); +/** Dispatch timeout and io events from the previously executed poll. Returns +a negative value on error. On success returns the number of source dispatched. */ +int pa_mainloop_dispatch(pa_mainloop *m); + +/** Return the return value as specified with the main loop's quit() routine. */ +int pa_mainloop_get_retval(pa_mainloop *m); + +/** Run a single iteration of the main loop. This is a convenience function +for pa_mainloop_prepare(), pa_mainloop_poll() and pa_mainloop_dispatch(). +Returns a negative value on error or exit request. If block is nonzero, +block for events if none are queued. Optionally return the return value as +specified with the main loop's quit() routine in the integer variable retval points to. On success returns the number of source dispatched in this iteration. */ int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval); From f77d5e14dc6c18846f228af3f2d6436537077f1d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 13 Feb 2006 13:37:22 +0000 Subject: [PATCH 0386/1514] Add function to "wake up", i.e. interrupt, a running poll(). This is needed when having the poll() in a separate thread. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@479 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/mainloop.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++- polyp/mainloop.h | 3 +++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/polyp/mainloop.c b/polyp/mainloop.c index e131e1a16..d25af78a5 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -91,6 +91,8 @@ struct pa_mainloop { int deferred_pending; + int wakeup_pipe[2]; + enum { STATE_PASSIVE, STATE_PREPARED, @@ -115,6 +117,8 @@ static pa_io_event* mainloop_io_new( m = a->userdata; assert(a == &m->api); + pa_mainloop_wakeup(m); + e = pa_xmalloc(sizeof(pa_io_event)); e->mainloop = m; e->dead = 0; @@ -154,12 +158,17 @@ static pa_io_event* mainloop_io_new( static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { assert(e && e->mainloop); + pa_mainloop_wakeup(e->mainloop); + e->events = events; e->mainloop->rebuild_pollfds = 1; } static void mainloop_io_free(pa_io_event *e) { assert(e && e->mainloop); + + pa_mainloop_wakeup(e->mainloop); + e->dead = e->mainloop->io_events_scan_dead = e->mainloop->rebuild_pollfds = 1; } @@ -229,6 +238,8 @@ static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval m = a->userdata; assert(a == &m->api); + pa_mainloop_wakeup(m); + e = pa_xmalloc(sizeof(pa_time_event)); e->mainloop = m; e->dead = 0; @@ -249,6 +260,8 @@ static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { assert(e); + pa_mainloop_wakeup(e->mainloop); + if (tv) { e->enabled = 1; e->timeval = *tv; @@ -259,6 +272,8 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { static void mainloop_time_free(pa_time_event *e) { assert(e); + pa_mainloop_wakeup(e->mainloop); + e->dead = e->mainloop->time_events_scan_dead = 1; } @@ -275,6 +290,8 @@ static void mainloop_quit(pa_mainloop_api*a, int retval) { m = a->userdata; assert(a == &m->api); + pa_mainloop_wakeup(m); + m->quit = 1; m->retval = retval; } @@ -305,6 +322,19 @@ pa_mainloop *pa_mainloop_new(void) { m = pa_xmalloc(sizeof(pa_mainloop)); +#ifndef OS_ISWIN32 + if (pipe(m->wakeup_pipe) < 0) { + pa_xfree(m); + return NULL; + } + + pa_make_nonblock_fd(m->wakeup_pipe[0]); + pa_make_nonblock_fd(m->wakeup_pipe[1]); +#else + m->wakeup_pipe[0] = -1; + m->wakeup_pipe[1] = -1; +#endif + m->io_events = pa_idxset_new(NULL, NULL); m->defer_events = pa_idxset_new(NULL, NULL); m->time_events = pa_idxset_new(NULL, NULL); @@ -386,6 +416,12 @@ void pa_mainloop_free(pa_mainloop* m) { pa_idxset_free(m->defer_events, NULL, NULL); pa_xfree(m->pollfds); + + if (m->wakeup_pipe[0] >= 0) + close(m->wakeup_pipe[0]); + if (m->wakeup_pipe[1] >= 0) + close(m->wakeup_pipe[1]); + pa_xfree(m); } @@ -409,7 +445,7 @@ static void rebuild_pollfds(pa_mainloop *m) { uint32_t idx = PA_IDXSET_INVALID; unsigned l; - l = pa_idxset_size(m->io_events); + l = pa_idxset_size(m->io_events) + 1; if (m->max_pollfds < l) { m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l); m->max_pollfds = l; @@ -417,6 +453,15 @@ static void rebuild_pollfds(pa_mainloop *m) { m->n_pollfds = 0; p = m->pollfds; + + if (m->wakeup_pipe[0] >= 0) { + m->pollfds[0].fd = m->wakeup_pipe[0]; + m->pollfds[0].events = POLLIN; + m->pollfds[0].revents = 0; + p++; + m->n_pollfds++; + } + for (e = pa_idxset_first(m->io_events, &idx); e; e = pa_idxset_next(m->io_events, &idx)) { if (e->dead) { e->pollfd = NULL; @@ -558,11 +603,32 @@ static int dispatch_timeout(pa_mainloop *m) { return r; } +void pa_mainloop_wakeup(pa_mainloop *m) { + char c = 'W'; + assert(m); + + if (m->wakeup_pipe[1] >= 0) + write(m->wakeup_pipe[1], &c, sizeof(c)); +} + +static void clear_wakeup(pa_mainloop *m) { + char c[10]; + + assert(m); + + if (m->wakeup_pipe[0] < 0) + return; + + while (read(m->wakeup_pipe[0], &c, sizeof(c)) == sizeof(c)); +} + int pa_mainloop_prepare(pa_mainloop *m, int timeout) { int dispatched = 0; assert(m && (m->state == STATE_PASSIVE)); + clear_wakeup(m); + scan_dead(m); if (m->quit) @@ -688,6 +754,7 @@ int pa_mainloop_run(pa_mainloop *m, int *retval) { void pa_mainloop_quit(pa_mainloop *m, int r) { assert(m); + pa_mainloop_wakeup(m); m->quit = r; } diff --git a/polyp/mainloop.h b/polyp/mainloop.h index 2be9e6ff0..921a07093 100644 --- a/polyp/mainloop.h +++ b/polyp/mainloop.h @@ -82,6 +82,9 @@ int pa_mainloop_deferred_pending(pa_mainloop *m); /** Shutdown the main loop */ void pa_mainloop_quit(pa_mainloop *m, int r); +/** Interrupt a running poll (for threaded systems) */ +void pa_mainloop_wakeup(pa_mainloop *m); + PA_C_DECL_END #endif From 0f0fc32a6e93df3fcdac4cfd5e41260ad0c30893 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 14 Feb 2006 13:41:30 +0000 Subject: [PATCH 0387/1514] Fix api. Setting volume is done through a pa_cvolume struct, not a pa_volume_t scalar. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@480 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/polyplib-introspect.c | 12 ++++++------ polyp/polyplib-introspect.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 8c0c4449b..49298a967 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -582,7 +582,7 @@ pa_operation* pa_context_get_source_output_info_list(pa_context *c, void (*cb)(p /*** Volume manipulation ***/ -pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; @@ -597,14 +597,14 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, p pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); - pa_tagstruct_putu32(t, volume); + pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); return pa_operation_ref(o); } -pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; @@ -619,14 +619,14 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); - pa_tagstruct_putu32(t, volume); + pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); return pa_operation_ref(o); } -pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; @@ -640,7 +640,7 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, pa_v pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, idx); - pa_tagstruct_putu32(t, volume); + pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h index 10e6d0e38..d34899086 100644 --- a/polyp/polyplib-introspect.h +++ b/polyp/polyplib-introspect.h @@ -183,13 +183,13 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, voi pa_operation* pa_context_get_source_output_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_output_info*i, int is_last, void *userdata), void *userdata); /** Set the volume of a sink device specified by its index */ -pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Set the volume of a sink device specified by its name */ -pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Set the volume of a sink input stream */ -pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, pa_volume_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); /** Memory block statistics */ typedef struct pa_stat_info { From 22e1f408a2d35f7244086d4532eb5a3ab47d0623 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 15 Feb 2006 23:44:04 +0000 Subject: [PATCH 0388/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@481 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/doc/todo b/doc/todo index 0da832069..345171a69 100644 --- a/doc/todo +++ b/doc/todo @@ -1,9 +1,6 @@ *** $Id$ *** Architectural changes: -- per-channel volume -- channel mapping ("left", "right", "rear", "subwoofer") -- hardware volume support - add API for synchronizing multiple sinks/sources to a common clock - absolutely indexed write()s from client - remove "polyplib-" prefix @@ -28,6 +25,14 @@ Long term: Backends for: - portaudio (semi-done) -- alsa-lib - sdl - OSS (esddsp style) + +------------------ + +Done: +- per-channel volume +- channel mapping ("left", "right", "rear", "subwoofer") +- hardware volume support +- alsa-lib + From cc3fe432afdfe2892ad808d84a90abd1208b5a36 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 01:14:51 +0000 Subject: [PATCH 0389/1514] fix warning text git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@482 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-protocol-stub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c index 44d1c0220..a03143682 100644 --- a/polyp/module-protocol-stub.c +++ b/polyp/module-protocol-stub.c @@ -173,7 +173,7 @@ static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) { uint32_t port = IPV4_PORT; if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) { - pa_log(__FILE__": loopback= expects a numerical argument.\n"); + pa_log(__FILE__": loopback= expects a boolean argument.\n"); return NULL; } From a9950d4ab28a07dcb96d47b4cd44c57be5c825f7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 01:15:31 +0000 Subject: [PATCH 0390/1514] print ALSA error messages on failure git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@483 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/module-alsa-sink.c | 9 +++++---- polyp/module-alsa-source.c | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index ea6ca4246..9aa220be0 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -182,6 +182,7 @@ int pa__init(pa_core *c, pa_module*m) { uint32_t periods, fragsize; snd_pcm_uframes_t period_size; size_t frame_size; + int err; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments\n"); @@ -208,13 +209,13 @@ int pa__init(pa_core *c, pa_module*m) { u->module = m; snd_config_update_free_global(); - if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) { - pa_log(__FILE__": Error opening PCM device %s\n", dev); + if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { + pa_log(__FILE__": Error opening PCM device %s: %s\n", dev, snd_strerror(err)); goto fail; } - if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size) < 0) { - pa_log(__FILE__": Failed to set hardware parameters\n"); + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) { + pa_log(__FILE__": Failed to set hardware parameters: %s\n", snd_strerror(err)); goto fail; } diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 2aa47aadd..efc84efeb 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -173,6 +173,7 @@ int pa__init(pa_core *c, pa_module*m) { unsigned periods, fragsize; snd_pcm_uframes_t period_size; size_t frame_size; + int err; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments\n"); @@ -199,13 +200,13 @@ int pa__init(pa_core *c, pa_module*m) { u->module = m; snd_config_update_free_global(); - if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) < 0) { - pa_log(__FILE__": Error opening PCM device %s\n", dev); + if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { + pa_log(__FILE__": Error opening PCM device %s: %s\n", dev, snd_strerror(err)); goto fail; } - if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size) < 0) { - pa_log(__FILE__": Failed to set hardware parameters\n"); + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) { + pa_log(__FILE__": Failed to set hardware parameters: %s\n", snd_strerror(err)); goto fail; } From 61fbafcb9495744d7ef82fe7dcb56610c8063888 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 01:16:02 +0000 Subject: [PATCH 0391/1514] allow polypaudio to startup without any enabled module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@484 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/polyp/main.c b/polyp/main.c index c984e28e0..b5aac8512 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -428,7 +428,8 @@ int main(int argc, char *argv[]) { c->scache_idle_time = conf->scache_idle_time; c->resample_method = conf->resample_method; - if (pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) { + if (c->default_sink_name && + pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) { pa_log_error("%s : Fatal error. Default sink name (%s) does not exist in name register.\n", __FILE__, c->default_sink_name); retval = 1; } else { From 6ad876efa803de188eaa8e9ffdedb68fd8c9423f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 01:16:39 +0000 Subject: [PATCH 0392/1514] Add HAVE_ALSA and HAVE_OSS defines git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@485 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 710f205b9..036635908 100644 --- a/configure.ac +++ b/configure.ac @@ -288,13 +288,20 @@ AC_SUBST(LIBSNDFILE_LIBS) #### OSS support (optional) #### -AC_CHECK_HEADERS([sys/soundcard.h], [HAVE_OSS=1], [HAVE_OSS=0]) +AC_CHECK_HEADERS([sys/soundcard.h], [ +HAVE_OSS=1 +AC_DEFINE([HAVE_OSS], 1, [Have OSS?]) +], [HAVE_OSS=0]) AC_SUBST(HAVE_OSS) AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1]) + #### ALSA support (optional) #### -PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [HAVE_ALSA=1], [HAVE_ALSA=0]) +PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [ +HAVE_ALSA=1 +AC_DEFINE([HAVE_ALSA], 1, [Have ALSA?]) +], [HAVE_ALSA=0]) AC_SUBST(ASOUNDLIB_CFLAGS) AC_SUBST(ASOUNDLIB_LIBS) AC_SUBST(HAVE_ALSA) From 5b881e62282f26b353635120935d114e0c7c3f3c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 01:17:30 +0000 Subject: [PATCH 0393/1514] add simple hardware auto detection module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@486 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/Makefile.am | 13 ++- polyp/module-detect.c | 226 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 polyp/module-detect.c diff --git a/polyp/Makefile.am b/polyp/Makefile.am index e2154b322..061b82b45 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -47,6 +47,7 @@ AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" +#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" @@ -676,7 +677,8 @@ modlib_LTLIBRARIES += \ module-null-sink.la \ module-esound-sink.la \ module-http-protocol-tcp.la \ - module-http-protocol-tcp6.la + module-http-protocol-tcp6.la \ + module-detect.la if HAVE_AF_UNIX modlib_LTLIBRARIES += \ @@ -788,7 +790,8 @@ SYMDEF_FILES = \ module-alsa-sink-symdef.h \ module-alsa-source-symdef.h \ module-solaris-symdef.h \ - module-waveout-symdef.h + module-waveout-symdef.h \ + module-detect-symdef.h EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) @@ -1009,6 +1012,12 @@ module_waveout_la_LDFLAGS = -module -avoid-version module_waveout_la_LIBADD = $(AM_LIBADD) libpolypcore.la -lwinmm module_waveout_la_CFLAGS = $(AM_CFLAGS) +# Hardware autodetection module +module_detect_la_SOURCES = module-detect.c +module_detect_la_LDFLAGS = -module -avoid-version +module_detect_la_LIBADD = $(AM_LIBADD) +module_detect_la_CFLAGS = $(AM_CFLAGS) + ################################### # Some minor stuff # ################################### diff --git a/polyp/module-detect.c b/polyp/module-detect.c new file mode 100644 index 000000000..ee75da368 --- /dev/null +++ b/polyp/module-detect.c @@ -0,0 +1,226 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "module.h" +#include "log.h" +#include "module-detect-symdef.h" +#include "xmalloc.h" +#include "modargs.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("just-one=") + +static const char *endswith(const char *haystack, const char *needle) { + size_t l, m; + const char *p; + + if ((l = strlen(haystack)) < (m = strlen(needle))) + return NULL; + + if (strcmp(p = haystack + l - m, needle)) + return NULL; + + return p; +} + +#ifdef HAVE_ALSA +static int detect_alsa(pa_core *c, int just_one) { + FILE *f; + int n = 0, n_sink = 0, n_source = 0; + + if (!(f = fopen("/proc/asound/devices", "r"))) { + + if (errno != ENOENT) + pa_log_error(__FILE__": open(\"/proc/asound/devices\") failed: %s\n", strerror(errno)); + + return -1; + } + + while (!feof(f)) { + char line[64], args[64]; + unsigned device, subdevice; + int is_sink; + + if (!fgets(line, sizeof(line), f)) + break; + + line[strcspn(line, "\r\n")] = 0; + + if (endswith(line, "digital audio playback")) + is_sink = 1; + else if (endswith(line, "digital audio capture")) + is_sink = 0; + else + continue; + + if (just_one && is_sink && n_sink >= 1) + continue; + + if (just_one && !is_sink && n_source >= 1) + continue; + + if (sscanf(line, " %*i: [%u- %u]: ", &device, &subdevice) != 2) + continue; + + /* Only one sink per device */ + if (subdevice != 0) + continue; + + snprintf(args, sizeof(args), "device=hw:%u,0", device); + if (!pa_module_load(c, is_sink ? "module-alsa-sink" : "module-alsa-source", args)) + continue; + + n++; + + if (is_sink) + n_sink++; + else + n_source++; + } + + fclose(f); + + return n; +} +#endif + +#ifdef HAVE_OSS +static int detect_oss(pa_core *c, int just_one) { + FILE *f; + int n = 0, b = 0; + + if (!(f = fopen("/dev/sndstat", "r")) && + !(f = fopen("/proc/sndstat", "r")) && + !(f = fopen("/proc/asound/oss/sndstat", "r"))) { + + if (errno != ENOENT) + pa_log_error(__FILE__": failed to open OSS sndstat device: %s\n", strerror(errno)); + + return -1; + } + + while (!feof(f)) { + char line[64], args[64]; + unsigned device; + + if (!fgets(line, sizeof(line), f)) + break; + + line[strcspn(line, "\r\n")] = 0; + + if (!b) { + b = strcmp(line, "Audio devices:") == 0; + continue; + } + + if (line[0] == 0) + break; + + if (sscanf(line, "%u: ", &device) != 1) + continue; + + if (device == 0) + snprintf(args, sizeof(args), "device=/dev/dsp"); + else + snprintf(args, sizeof(args), "device=/dev/dsp%u", device); + + if (!pa_module_load(c, "module-oss", args)) + continue; + + n++; + + if (just_one) + break; + } + + fclose(f); + return n; +} +#endif + +int pa__init(pa_core *c, pa_module*m) { + int just_one = 0, n = 0; + pa_modargs *ma; + + static const char* const valid_modargs[] = { + "just-one", + NULL + }; + + assert(c); + assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": Failed to parse module arguments\n"); + goto fail; + } + + if (pa_modargs_get_value_boolean(ma, "just-one", &just_one) < 0) { + pa_log(__FILE__": just_one= expects a boolean argument.\n"); + goto fail; + } + +#if HAVE_ALSA + if ((n = detect_alsa(c, just_one)) <= 0) +#endif +#if HAVE_OSS + if ((n = detect_oss(c, just_one)) <= 0) +#endif + { + pa_log_warn(__FILE__": failed to detect any sound hardware.\n"); + goto fail; + } + + pa_log_info(__FILE__": loaded %i modules.\n", n); + + /* We were successful and can unload ourselves now. */ + pa_module_unload_request(m); + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + return -1; +} + + +void pa__done(pa_core *c, pa_module*m) { + /* NOP */ +} + From e205b25d65ccb380fa158711e24d55b6de5d9bc1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 16 Feb 2006 19:19:58 +0000 Subject: [PATCH 0394/1514] Reorganised the source tree. We now have src/ with a couple of subdirs: * daemon/ - Contains the files specific to the polypaudio daemon. * modules/ - All loadable modules. * polyp/ - Files that are part of the public, application interface or are only used in libpolyp. * polypcore/ - All other shared files. * tests/ - Test programs. * utils/ - Utility programs. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@487 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- configure.ac | 6 +- {polyp => src}/Makefile.am | 603 +++++++++--------- {polyp => src}/client.conf.in | 0 {polyp => src}/daemon.conf.in | 0 {polyp => src/daemon}/caps.c | 2 +- {polyp => src/daemon}/caps.h | 0 {polyp => src/daemon}/cmdline.c | 6 +- {polyp => src/daemon}/cmdline.h | 0 {polyp => src/daemon}/cpulimit.c | 4 +- {polyp => src/daemon}/cpulimit.h | 2 +- {polyp => src/daemon}/daemon-conf.c | 10 +- {polyp => src/daemon}/daemon-conf.h | 2 +- {polyp => src/daemon}/dumpmodules.c | 4 +- {polyp => src/daemon}/dumpmodules.h | 0 {polyp => src/daemon}/main.c | 28 +- {polyp => src}/default.pa.in | 0 {polyp => src}/default.pa.win32 | 0 {polyp => src}/depmod.py | 0 {polyp => src/modules}/module-alsa-sink.c | 21 +- {polyp => src/modules}/module-alsa-source.c | 21 +- {polyp => src/modules}/module-cli.c | 11 +- {polyp => src/modules}/module-combine.c | 21 +- {polyp => src/modules}/module-defs.h.m4 | 6 +- {polyp => src/modules}/module-detect.c | 9 +- .../modules}/module-esound-compat-spawnfd.c | 9 +- .../modules}/module-esound-compat-spawnpid.c | 9 +- {polyp => src/modules}/module-esound-sink.c | 21 +- {polyp => src/modules}/module-lirc.c | 13 +- {polyp => src/modules}/module-match.c | 15 +- {polyp => src/modules}/module-mmkbd-evdev.c | 15 +- .../modules}/module-native-protocol-fd.c | 11 +- {polyp => src/modules}/module-null-sink.c | 15 +- {polyp => src/modules}/module-oss-mmap.c | 21 +- {polyp => src/modules}/module-oss.c | 21 +- {polyp => src/modules}/module-pipe-sink.c | 15 +- {polyp => src/modules}/module-pipe-source.c | 15 +- {polyp => src/modules}/module-protocol-stub.c | 29 +- {polyp => src/modules}/module-sine.c | 13 +- {polyp => src/modules}/module-solaris.c | 22 +- {polyp => src/modules}/module-tunnel.c | 28 +- {polyp => src/modules}/module-waveout.c | 20 +- {polyp => src/modules}/module-x11-bell.c | 17 +- {polyp => src/modules}/module-x11-publish.c | 31 +- .../modules}/module-zeroconf-publish.c | 25 +- {polyp => src/polyp}/cdecl.h | 0 {polyp => src/polyp}/channelmap.c | 0 {polyp => src/polyp}/channelmap.h | 0 {polyp => src/polyp}/client-conf-x11.c | 8 +- {polyp => src/polyp}/client-conf-x11.h | 2 +- {polyp => src/polyp}/client-conf.c | 13 +- {polyp => src/polyp}/client-conf.h | 2 +- {polyp => src/polyp}/glib-mainloop.c | 8 +- {polyp => src/polyp}/glib-mainloop.h | 4 +- {polyp => src/polyp}/glib12-mainloop.c | 8 +- {polyp => src/polyp}/mainloop-api.c | 4 +- {polyp => src/polyp}/mainloop-api.h | 0 {polyp => src/polyp}/mainloop-signal.c | 10 +- {polyp => src/polyp}/mainloop-signal.h | 4 +- {polyp => src/polyp}/mainloop.c | 10 +- {polyp => src/polyp}/mainloop.h | 4 +- {polyp => src/polyp}/polyplib-browser.c | 6 +- {polyp => src/polyp}/polyplib-browser.h | 0 {polyp => src/polyp}/polyplib-context.c | 24 +- {polyp => src/polyp}/polyplib-context.h | 0 {polyp => src/polyp}/polyplib-def.h | 0 {polyp => src/polyp}/polyplib-error.c | 2 +- {polyp => src/polyp}/polyplib-error.h | 2 +- {polyp => src/polyp}/polyplib-internal.h | 20 +- {polyp => src/polyp}/polyplib-introspect.c | 4 +- {polyp => src/polyp}/polyplib-introspect.h | 0 {polyp => src/polyp}/polyplib-operation.c | 2 +- {polyp => src/polyp}/polyplib-operation.h | 0 {polyp => src/polyp}/polyplib-scache.c | 2 +- {polyp => src/polyp}/polyplib-scache.h | 0 {polyp => src/polyp}/polyplib-simple.c | 6 +- {polyp => src/polyp}/polyplib-simple.h | 2 +- {polyp => src/polyp}/polyplib-stream.c | 8 +- {polyp => src/polyp}/polyplib-stream.h | 0 {polyp => src/polyp}/polyplib-subscribe.c | 4 +- {polyp => src/polyp}/polyplib-subscribe.h | 0 {polyp => src/polyp}/polyplib-version.h.in | 0 {polyp => src/polyp}/polyplib.h | 0 {polyp => src/polyp}/sample.c | 0 {polyp => src/polyp}/sample.h | 0 {polyp => src/polyp}/volume.c | 0 {polyp => src/polyp}/volume.h | 0 {polyp => src/polypcore}/alsa-util.c | 2 +- {polyp => src/polypcore}/alsa-util.h | 4 +- {polyp => src/polypcore}/authkey-prop.c | 0 {polyp => src/polypcore}/authkey-prop.h | 0 {polyp => src/polypcore}/authkey.c | 0 {polyp => src/polypcore}/authkey.h | 0 {polyp => src/polypcore}/autoload.c | 0 {polyp => src/polypcore}/autoload.h | 0 {polyp => src/polypcore}/cli-command.c | 0 {polyp => src/polypcore}/cli-command.h | 0 {polyp => src/polypcore}/cli-text.c | 2 +- {polyp => src/polypcore}/cli-text.h | 0 {polyp => src/polypcore}/cli.c | 0 {polyp => src/polypcore}/cli.h | 0 {polyp => src/polypcore}/client.c | 0 {polyp => src/polypcore}/client.h | 0 {polyp => src/polypcore}/conf-parser.c | 0 {polyp => src/polypcore}/conf-parser.h | 0 {polyp => src/polypcore}/core.c | 0 {polyp => src/polypcore}/core.h | 4 +- {polyp => src/polypcore}/dllmain.c | 0 {polyp => src/polypcore}/dynarray.c | 0 {polyp => src/polypcore}/dynarray.h | 0 {polyp => src/polypcore}/endianmacros.h | 0 {polyp => src/polypcore}/esound.h | 0 {polyp => src/polypcore}/g711.c | 0 {polyp => src/polypcore}/g711.h | 0 {polyp => src/polypcore}/gccmacro.h | 0 {polyp => src/polypcore}/hashmap.c | 0 {polyp => src/polypcore}/hashmap.h | 0 {polyp => src/polypcore}/howl-wrap.c | 0 {polyp => src/polypcore}/howl-wrap.h | 0 {polyp => src/polypcore}/idxset.c | 0 {polyp => src/polypcore}/idxset.h | 0 {polyp => src/polypcore}/inet_ntop.c | 0 {polyp => src/polypcore}/inet_ntop.h | 0 {polyp => src/polypcore}/iochannel.c | 0 {polyp => src/polypcore}/iochannel.h | 2 +- {polyp => src/polypcore}/ioline.c | 0 {polyp => src/polypcore}/ioline.h | 0 {polyp => src/polypcore}/llist.h | 0 {polyp => src/polypcore}/log.c | 0 {polyp => src/polypcore}/log.h | 0 {polyp => src/polypcore}/mcalign.c | 0 {polyp => src/polypcore}/mcalign.h | 0 {polyp => src/polypcore}/memblock.c | 0 {polyp => src/polypcore}/memblock.h | 0 {polyp => src/polypcore}/memblockq.c | 0 {polyp => src/polypcore}/memblockq.h | 0 {polyp => src/polypcore}/memchunk.c | 0 {polyp => src/polypcore}/memchunk.h | 0 {polyp => src/polypcore}/modargs.c | 0 {polyp => src/polypcore}/modargs.h | 2 +- {polyp => src/polypcore}/modinfo.c | 0 {polyp => src/polypcore}/modinfo.h | 0 {polyp => src/polypcore}/module.c | 0 {polyp => src/polypcore}/module.h | 0 {polyp => src/polypcore}/namereg.c | 0 {polyp => src/polypcore}/namereg.h | 0 {polyp => src/polypcore}/native-common.h | 4 +- {polyp => src/polypcore}/oss-util.c | 0 {polyp => src/polypcore}/oss-util.h | 2 +- {polyp => src/polypcore}/packet.c | 0 {polyp => src/polypcore}/packet.h | 0 {polyp => src/polypcore}/parseaddr.c | 0 {polyp => src/polypcore}/parseaddr.h | 0 {polyp => src/polypcore}/pdispatch.c | 0 {polyp => src/polypcore}/pdispatch.h | 2 +- {polyp => src/polypcore}/pid.c | 0 {polyp => src/polypcore}/pid.h | 0 {polyp => src/polypcore}/play-memchunk.c | 0 {polyp => src/polypcore}/play-memchunk.h | 0 {polyp => src/polypcore}/poll.c | 0 {polyp => src/polypcore}/poll.h | 0 {polyp => src/polypcore}/props.c | 0 {polyp => src/polypcore}/props.h | 0 {polyp => src/polypcore}/protocol-cli.c | 0 {polyp => src/polypcore}/protocol-cli.h | 0 {polyp => src/polypcore}/protocol-esound.c | 2 +- {polyp => src/polypcore}/protocol-esound.h | 0 {polyp => src/polypcore}/protocol-http.c | 0 {polyp => src/polypcore}/protocol-http.h | 0 {polyp => src/polypcore}/protocol-native.c | 0 {polyp => src/polypcore}/protocol-native.h | 0 {polyp => src/polypcore}/protocol-simple.c | 0 {polyp => src/polypcore}/protocol-simple.h | 0 {polyp => src/polypcore}/pstream-util.c | 0 {polyp => src/polypcore}/pstream-util.h | 0 {polyp => src/polypcore}/pstream.c | 0 {polyp => src/polypcore}/pstream.h | 2 +- {polyp => src/polypcore}/queue.c | 0 {polyp => src/polypcore}/queue.h | 0 {polyp => src/polypcore}/random.c | 0 {polyp => src/polypcore}/random.h | 0 {polyp => src/polypcore}/resampler.c | 0 {polyp => src/polypcore}/resampler.h | 4 +- {polyp => src/polypcore}/sample-util.c | 0 {polyp => src/polypcore}/sample-util.h | 4 +- {polyp => src/polypcore}/scache.c | 6 +- {polyp => src/polypcore}/scache.h | 0 {polyp => src/polypcore}/sconv-s16be.c | 0 {polyp => src/polypcore}/sconv-s16be.h | 0 {polyp => src/polypcore}/sconv-s16le.c | 0 {polyp => src/polypcore}/sconv-s16le.h | 0 {polyp => src/polypcore}/sconv.c | 0 {polyp => src/polypcore}/sconv.h | 2 +- {polyp => src/polypcore}/sink-input.c | 0 {polyp => src/polypcore}/sink-input.h | 2 +- {polyp => src/polypcore}/sink.c | 2 +- {polyp => src/polypcore}/sink.h | 6 +- {polyp => src/polypcore}/sioman.c | 0 {polyp => src/polypcore}/sioman.h | 0 {polyp => src/polypcore}/socket-client.c | 0 {polyp => src/polypcore}/socket-client.h | 2 +- {polyp => src/polypcore}/socket-server.c | 0 {polyp => src/polypcore}/socket-server.h | 2 +- {polyp => src/polypcore}/socket-util.c | 0 {polyp => src/polypcore}/socket-util.h | 0 {polyp => src/polypcore}/sound-file-stream.c | 0 {polyp => src/polypcore}/sound-file-stream.h | 0 {polyp => src/polypcore}/sound-file.c | 2 +- {polyp => src/polypcore}/sound-file.h | 2 +- {polyp => src/polypcore}/source-output.c | 0 {polyp => src/polypcore}/source-output.h | 2 +- {polyp => src/polypcore}/source.c | 0 {polyp => src/polypcore}/source.h | 4 +- {polyp => src/polypcore}/strbuf.c | 3 +- {polyp => src/polypcore}/strbuf.h | 0 {polyp => src/polypcore}/strlist.c | 0 {polyp => src/polypcore}/strlist.h | 0 {polyp => src/polypcore}/subscribe.c | 0 {polyp => src/polypcore}/subscribe.h | 0 {polyp => src/polypcore}/tagstruct.c | 0 {polyp => src/polypcore}/tagstruct.h | 6 +- {polyp => src/polypcore}/tokenizer.c | 0 {polyp => src/polypcore}/tokenizer.h | 0 {polyp => src/polypcore}/util.c | 0 {polyp => src/polypcore}/util.h | 2 +- {polyp => src/polypcore}/winsock.h | 0 {polyp => src/polypcore}/x11prop.c | 0 {polyp => src/polypcore}/x11prop.h | 0 {polyp => src/polypcore}/x11wrap.c | 0 {polyp => src/polypcore}/x11wrap.h | 0 {polyp => src/polypcore}/xmalloc.c | 0 {polyp => src/polypcore}/xmalloc.h | 0 {polyp => src/tests}/cpulimit-test.c | 8 +- {polyp => src/tests}/mainloop-test.c | 8 +- {polyp => src/tests}/mcalign-test.c | 6 +- {polyp => src/tests}/pacat-simple.c | 2 +- {polyp => src/tests}/parec-simple.c | 2 +- {polyp => src/tests}/strlist-test.c | 6 +- {polyp => src/tests}/voltest.c | 2 +- {polyp => src/utils}/esdcompat.sh.in | 0 {polyp => src/utils}/pabrowse.c | 0 {polyp => src/utils}/pacat.c | 0 {polyp => src/utils}/pacmd.c | 6 +- {polyp => src/utils}/pactl.c | 0 {polyp => src/utils}/paplay.c | 0 {polyp => src/utils}/pax11publish.c | 12 +- 246 files changed, 724 insertions(+), 689 deletions(-) rename {polyp => src}/Makefile.am (64%) rename {polyp => src}/client.conf.in (100%) rename {polyp => src}/daemon.conf.in (100%) rename {polyp => src/daemon}/caps.c (98%) rename {polyp => src/daemon}/caps.h (100%) rename {polyp => src/daemon}/cmdline.c (99%) rename {polyp => src/daemon}/cmdline.h (100%) rename {polyp => src/daemon}/cpulimit.c (99%) rename {polyp => src/daemon}/cpulimit.h (97%) rename {polyp => src/daemon}/daemon-conf.c (98%) rename {polyp => src/daemon}/daemon-conf.h (99%) rename {polyp => src/daemon}/dumpmodules.c (97%) rename {polyp => src/daemon}/dumpmodules.h (100%) rename {polyp => src/daemon}/main.c (96%) rename {polyp => src}/default.pa.in (100%) rename {polyp => src}/default.pa.win32 (100%) rename {polyp => src}/depmod.py (100%) rename {polyp => src/modules}/module-alsa-sink.c (96%) rename {polyp => src/modules}/module-alsa-source.c (96%) rename {polyp => src/modules}/module-cli.c (93%) rename {polyp => src/modules}/module-combine.c (97%) rename {polyp => src/modules}/module-defs.h.m4 (81%) rename {polyp => src/modules}/module-detect.c (97%) rename {polyp => src/modules}/module-esound-compat-spawnfd.c (94%) rename {polyp => src/modules}/module-esound-compat-spawnpid.c (94%) rename {polyp => src/modules}/module-esound-sink.c (97%) rename {polyp => src/modules}/module-lirc.c (97%) rename {polyp => src/modules}/module-match.c (96%) rename {polyp => src/modules}/module-mmkbd-evdev.c (97%) rename {polyp => src/modules}/module-native-protocol-fd.c (92%) rename {polyp => src/modules}/module-null-sink.c (94%) rename {polyp => src/modules}/module-oss-mmap.c (97%) rename {polyp => src/modules}/module-oss.c (97%) rename {polyp => src/modules}/module-pipe-sink.c (96%) rename {polyp => src/modules}/module-pipe-source.c (96%) rename {polyp => src/modules}/module-protocol-stub.c (94%) rename {polyp => src/modules}/module-sine.c (96%) rename {polyp => src/modules}/module-solaris.c (97%) rename {polyp => src/modules}/module-tunnel.c (97%) rename {polyp => src/modules}/module-waveout.c (98%) rename {polyp => src/modules}/module-x11-bell.c (94%) rename {polyp => src/modules}/module-x11-publish.c (91%) rename {polyp => src/modules}/module-zeroconf-publish.c (97%) rename {polyp => src/polyp}/cdecl.h (100%) rename {polyp => src/polyp}/channelmap.c (100%) rename {polyp => src/polyp}/channelmap.h (100%) rename {polyp => src/polyp}/client-conf-x11.c (95%) rename {polyp => src/polyp}/client-conf-x11.h (97%) rename {polyp => src/polyp}/client-conf.c (96%) rename {polyp => src/polyp}/client-conf.h (97%) rename {polyp => src/polyp}/glib-mainloop.c (99%) rename {polyp => src/polyp}/glib-mainloop.h (96%) rename {polyp => src/polyp}/glib12-mainloop.c (99%) rename {polyp => src/polyp}/mainloop-api.c (96%) rename {polyp => src/polyp}/mainloop-api.h (100%) rename {polyp => src/polyp}/mainloop-signal.c (97%) rename {polyp => src/polyp}/mainloop-signal.h (97%) rename {polyp => src/polyp}/mainloop.c (99%) rename {polyp => src/polyp}/mainloop.h (98%) rename {polyp => src/polyp}/polyplib-browser.c (99%) rename {polyp => src/polyp}/polyplib-browser.h (100%) rename {polyp => src/polyp}/polyplib-context.c (98%) rename {polyp => src/polyp}/polyplib-context.h (100%) rename {polyp => src/polyp}/polyplib-def.h (100%) rename {polyp => src/polyp}/polyplib-error.c (97%) rename {polyp => src/polyp}/polyplib-error.h (97%) rename {polyp => src/polyp}/polyplib-internal.h (93%) rename {polyp => src/polyp}/polyplib-introspect.c (99%) rename {polyp => src/polyp}/polyplib-introspect.h (100%) rename {polyp => src/polyp}/polyplib-operation.c (98%) rename {polyp => src/polyp}/polyplib-operation.h (100%) rename {polyp => src/polyp}/polyplib-scache.c (99%) rename {polyp => src/polyp}/polyplib-scache.h (100%) rename {polyp => src/polyp}/polyplib-simple.c (98%) rename {polyp => src/polyp}/polyplib-simple.h (99%) rename {polyp => src/polyp}/polyplib-stream.c (99%) rename {polyp => src/polyp}/polyplib-stream.h (100%) rename {polyp => src/polyp}/polyplib-subscribe.c (97%) rename {polyp => src/polyp}/polyplib-subscribe.h (100%) rename {polyp => src/polyp}/polyplib-version.h.in (100%) rename {polyp => src/polyp}/polyplib.h (100%) rename {polyp => src/polyp}/sample.c (100%) rename {polyp => src/polyp}/sample.h (100%) rename {polyp => src/polyp}/volume.c (100%) rename {polyp => src/polyp}/volume.h (100%) rename {polyp => src/polypcore}/alsa-util.c (99%) rename {polyp => src/polypcore}/alsa-util.h (95%) rename {polyp => src/polypcore}/authkey-prop.c (100%) rename {polyp => src/polypcore}/authkey-prop.h (100%) rename {polyp => src/polypcore}/authkey.c (100%) rename {polyp => src/polypcore}/authkey.h (100%) rename {polyp => src/polypcore}/autoload.c (100%) rename {polyp => src/polypcore}/autoload.h (100%) rename {polyp => src/polypcore}/cli-command.c (100%) rename {polyp => src/polypcore}/cli-command.h (100%) rename {polyp => src/polypcore}/cli-text.c (99%) rename {polyp => src/polypcore}/cli-text.h (100%) rename {polyp => src/polypcore}/cli.c (100%) rename {polyp => src/polypcore}/cli.h (100%) rename {polyp => src/polypcore}/client.c (100%) rename {polyp => src/polypcore}/client.h (100%) rename {polyp => src/polypcore}/conf-parser.c (100%) rename {polyp => src/polypcore}/conf-parser.h (100%) rename {polyp => src/polypcore}/core.c (100%) rename {polyp => src/polypcore}/core.h (97%) rename {polyp => src/polypcore}/dllmain.c (100%) rename {polyp => src/polypcore}/dynarray.c (100%) rename {polyp => src/polypcore}/dynarray.h (100%) rename {polyp => src/polypcore}/endianmacros.h (100%) rename {polyp => src/polypcore}/esound.h (100%) rename {polyp => src/polypcore}/g711.c (100%) rename {polyp => src/polypcore}/g711.h (100%) rename {polyp => src/polypcore}/gccmacro.h (100%) rename {polyp => src/polypcore}/hashmap.c (100%) rename {polyp => src/polypcore}/hashmap.h (100%) rename {polyp => src/polypcore}/howl-wrap.c (100%) rename {polyp => src/polypcore}/howl-wrap.h (100%) rename {polyp => src/polypcore}/idxset.c (100%) rename {polyp => src/polypcore}/idxset.h (100%) rename {polyp => src/polypcore}/inet_ntop.c (100%) rename {polyp => src/polypcore}/inet_ntop.h (100%) rename {polyp => src/polypcore}/iochannel.c (100%) rename {polyp => src/polypcore}/iochannel.h (98%) rename {polyp => src/polypcore}/ioline.c (100%) rename {polyp => src/polypcore}/ioline.h (100%) rename {polyp => src/polypcore}/llist.h (100%) rename {polyp => src/polypcore}/log.c (100%) rename {polyp => src/polypcore}/log.h (100%) rename {polyp => src/polypcore}/mcalign.c (100%) rename {polyp => src/polypcore}/mcalign.h (100%) rename {polyp => src/polypcore}/memblock.c (100%) rename {polyp => src/polypcore}/memblock.h (100%) rename {polyp => src/polypcore}/memblockq.c (100%) rename {polyp => src/polypcore}/memblockq.h (100%) rename {polyp => src/polypcore}/memchunk.c (100%) rename {polyp => src/polypcore}/memchunk.h (100%) rename {polyp => src/polypcore}/modargs.c (100%) rename {polyp => src/polypcore}/modargs.h (98%) rename {polyp => src/polypcore}/modinfo.c (100%) rename {polyp => src/polypcore}/modinfo.h (100%) rename {polyp => src/polypcore}/module.c (100%) rename {polyp => src/polypcore}/module.h (100%) rename {polyp => src/polypcore}/namereg.c (100%) rename {polyp => src/polypcore}/namereg.h (100%) rename {polyp => src/polypcore}/native-common.h (98%) rename {polyp => src/polypcore}/oss-util.c (100%) rename {polyp => src/polypcore}/oss-util.h (97%) rename {polyp => src/polypcore}/packet.c (100%) rename {polyp => src/polypcore}/packet.h (100%) rename {polyp => src/polypcore}/parseaddr.c (100%) rename {polyp => src/polypcore}/parseaddr.h (100%) rename {polyp => src/polypcore}/pdispatch.c (100%) rename {polyp => src/polypcore}/pdispatch.h (98%) rename {polyp => src/polypcore}/pid.c (100%) rename {polyp => src/polypcore}/pid.h (100%) rename {polyp => src/polypcore}/play-memchunk.c (100%) rename {polyp => src/polypcore}/play-memchunk.h (100%) rename {polyp => src/polypcore}/poll.c (100%) rename {polyp => src/polypcore}/poll.h (100%) rename {polyp => src/polypcore}/props.c (100%) rename {polyp => src/polypcore}/props.h (100%) rename {polyp => src/polypcore}/protocol-cli.c (100%) rename {polyp => src/polypcore}/protocol-cli.h (100%) rename {polyp => src/polypcore}/protocol-esound.c (99%) rename {polyp => src/polypcore}/protocol-esound.h (100%) rename {polyp => src/polypcore}/protocol-http.c (100%) rename {polyp => src/polypcore}/protocol-http.h (100%) rename {polyp => src/polypcore}/protocol-native.c (100%) rename {polyp => src/polypcore}/protocol-native.h (100%) rename {polyp => src/polypcore}/protocol-simple.c (100%) rename {polyp => src/polypcore}/protocol-simple.h (100%) rename {polyp => src/polypcore}/pstream-util.c (100%) rename {polyp => src/polypcore}/pstream-util.h (100%) rename {polyp => src/polypcore}/pstream.c (100%) rename {polyp => src/polypcore}/pstream.h (98%) rename {polyp => src/polypcore}/queue.c (100%) rename {polyp => src/polypcore}/queue.h (100%) rename {polyp => src/polypcore}/random.c (100%) rename {polyp => src/polypcore}/random.h (100%) rename {polyp => src/polypcore}/resampler.c (100%) rename {polyp => src/polypcore}/resampler.h (97%) rename {polyp => src/polypcore}/sample-util.c (100%) rename {polyp => src/polypcore}/sample-util.h (96%) rename {polyp => src/polypcore}/scache.c (99%) rename {polyp => src/polypcore}/scache.h (100%) rename {polyp => src/polypcore}/sconv-s16be.c (100%) rename {polyp => src/polypcore}/sconv-s16be.h (100%) rename {polyp => src/polypcore}/sconv-s16le.c (100%) rename {polyp => src/polypcore}/sconv-s16le.h (100%) rename {polyp => src/polypcore}/sconv.c (100%) rename {polyp => src/polypcore}/sconv.h (97%) rename {polyp => src/polypcore}/sink-input.c (100%) rename {polyp => src/polypcore}/sink-input.h (99%) rename {polyp => src/polypcore}/sink.c (99%) rename {polyp => src/polypcore}/sink.h (96%) rename {polyp => src/polypcore}/sioman.c (100%) rename {polyp => src/polypcore}/sioman.h (100%) rename {polyp => src/polypcore}/socket-client.c (100%) rename {polyp => src/polypcore}/socket-client.h (98%) rename {polyp => src/polypcore}/socket-server.c (100%) rename {polyp => src/polypcore}/socket-server.h (98%) rename {polyp => src/polypcore}/socket-util.c (100%) rename {polyp => src/polypcore}/socket-util.h (100%) rename {polyp => src/polypcore}/sound-file-stream.c (100%) rename {polyp => src/polypcore}/sound-file-stream.h (100%) rename {polyp => src/polypcore}/sound-file.c (99%) rename {polyp => src/polypcore}/sound-file.h (97%) rename {polyp => src/polypcore}/source-output.c (100%) rename {polyp => src/polypcore}/source-output.h (98%) rename {polyp => src/polypcore}/source.c (100%) rename {polyp => src/polypcore}/source.h (97%) rename {polyp => src/polypcore}/strbuf.c (99%) rename {polyp => src/polypcore}/strbuf.h (100%) rename {polyp => src/polypcore}/strlist.c (100%) rename {polyp => src/polypcore}/strlist.h (100%) rename {polyp => src/polypcore}/subscribe.c (100%) rename {polyp => src/polypcore}/subscribe.h (100%) rename {polyp => src/polypcore}/tagstruct.c (100%) rename {polyp => src/polypcore}/tagstruct.h (97%) rename {polyp => src/polypcore}/tokenizer.c (100%) rename {polyp => src/polypcore}/tokenizer.h (100%) rename {polyp => src/polypcore}/util.c (100%) rename {polyp => src/polypcore}/util.h (99%) rename {polyp => src/polypcore}/winsock.h (100%) rename {polyp => src/polypcore}/x11prop.c (100%) rename {polyp => src/polypcore}/x11prop.h (100%) rename {polyp => src/polypcore}/x11wrap.c (100%) rename {polyp => src/polypcore}/x11wrap.h (100%) rename {polyp => src/polypcore}/xmalloc.c (100%) rename {polyp => src/polypcore}/xmalloc.h (100%) rename {polyp => src/tests}/cpulimit-test.c (93%) rename {polyp => src/tests}/mainloop-test.c (96%) rename {polyp => src/tests}/mcalign-test.c (96%) rename {polyp => src/tests}/pacat-simple.c (98%) rename {polyp => src/tests}/parec-simple.c (98%) rename {polyp => src/tests}/strlist-test.c (89%) rename {polyp => src/tests}/voltest.c (94%) rename {polyp => src/utils}/esdcompat.sh.in (100%) rename {polyp => src/utils}/pabrowse.c (100%) rename {polyp => src/utils}/pacat.c (100%) rename {polyp => src/utils}/pacmd.c (98%) rename {polyp => src/utils}/pactl.c (100%) rename {polyp => src/utils}/paplay.c (100%) rename {polyp => src/utils}/pax11publish.c (97%) diff --git a/Makefile.am b/Makefile.am index 2cf93c75d..9705d45d0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # USA. EXTRA_DIST = bootstrap.sh LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4 -SUBDIRS=libltdl polyp doc +SUBDIRS=libltdl src doc MAINTAINERCLEANFILES = noinst_DATA = diff --git a/configure.ac b/configure.ac index 036635908..182a2455c 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ AC_PREREQ(2.57) AC_INIT([polypaudio],[0.8],[mzcbylcnhqvb (at) 0pointer (dot) de]) -AC_CONFIG_SRCDIR([polyp/main.c]) +AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) @@ -392,7 +392,7 @@ fi AC_CONFIG_FILES([ Makefile -polyp/Makefile +src/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc @@ -407,7 +407,7 @@ doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf -polyp/polyplib-version.h +src/polyp/polyplib-version.h doc/FAQ.html ]) AC_OUTPUT diff --git a/polyp/Makefile.am b/src/Makefile.am similarity index 64% rename from polyp/Makefile.am rename to src/Makefile.am index 061b82b45..92c7dae18 100644 --- a/polyp/Makefile.am +++ b/src/Makefile.am @@ -23,6 +23,7 @@ ################################### polypincludedir=$(includedir)/polyp +polypcoreincludedir=$(includedir)/polypcore polypconfdir=$(sysconfdir)/polypaudio modlibdir=$(libdir)/polypaudio @@ -42,7 +43,7 @@ endif # Compiler/linker flags # ################################### -AM_CFLAGS = -I$(top_srcdir) +AM_CFLAGS = -I$(top_srcdir)/src AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) @@ -78,12 +79,12 @@ EXTRA_DIST = \ daemon.conf.in \ default.pa.in \ depmod.py \ - esdcompat.sh.in \ - module-defs.h.m4 + utils/esdcompat.sh.in \ + modules/module-defs.h.m4 polypconf_DATA = default.pa daemon.conf client.conf -BUILT_SOURCES = polyplib-version.h +BUILT_SOURCES = polyp/polyplib-version.h ################################### # Main daemon # @@ -92,15 +93,13 @@ BUILT_SOURCES = polyplib-version.h bin_PROGRAMS = polypaudio polypaudio_SOURCES = \ - caps.h caps.c \ - cmdline.c cmdline.h \ - cpulimit.c cpulimit.h \ - conf-parser.h conf-parser.c \ - daemon-conf.c daemon-conf.h \ - dumpmodules.c dumpmodules.h \ - gcc-printf.h \ - main.c \ - pid.c pid.h + daemon/caps.h daemon/caps.c \ + daemon/cmdline.c daemon/cmdline.h \ + daemon/cpulimit.c daemon/cpulimit.h \ + daemon/daemon-conf.c daemon/daemon-conf.h \ + daemon/dumpmodules.c daemon/dumpmodules.h \ + daemon/main.c \ + polypcore/gccmacro.h polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) polypaudio_CPPFLAGS = $(AM_CPPFLAGS) @@ -135,34 +134,34 @@ if HAVE_HOWL bin_PROGRAMS += pabrowse endif -bin_SCRIPTS = esdcompat.sh +bin_SCRIPTS = utils/esdcompat.sh -pacat_SOURCES = pacat.c +pacat_SOURCES = utils/pacat.c pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la pacat_CFLAGS = $(AM_CFLAGS) pacat_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -paplay_SOURCES = paplay.c +paplay_SOURCES = utils/paplay.c paplay_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) paplay_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pactl_SOURCES = pactl.c +pactl_SOURCES = utils/pactl.c pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pacmd_SOURCES = pacmd.c util.c util.h xmalloc.c xmalloc.h log.c log.h pid.c pid.h +pacmd_SOURCES = utils/pacmd.c polypcore/pid.c polypcore/pid.h pacmd_CFLAGS = $(AM_CFLAGS) -pacmd_LDADD = $(AM_LDADD) +pacmd_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la pacmd_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pax11publish_SOURCES = pax11publish.c util.c util.h xmalloc.c xmalloc.h log.c log.h authkey.c authkey.h client-conf.c client-conf.h conf-parser.c conf-parser.h x11prop.c x11prop.h random.c random.h +pax11publish_SOURCES = utils/pax11publish.c pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +pax11publish_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pabrowse_SOURCES = pabrowse.c +pabrowse_SOURCES = utils/pabrowse.c pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la pabrowse_CFLAGS = $(AM_CFLAGS) pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -195,44 +194,44 @@ noinst_PROGRAMS += \ mainloop-test-glib12 endif -mainloop_test_SOURCES = mainloop-test.c +mainloop_test_SOURCES = tests/mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-@PA_MAJORMINOR@.la mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -mcalign_test_SOURCES = mcalign-test.c util.c util.h xmalloc.c xmalloc.h log.c log.h mcalign.c mcalign.h memchunk.c memchunk.h memblock.c memblock.h +mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) -mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) +mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la mcalign_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pacat_simple_SOURCES = pacat-simple.c +pacat_simple_SOURCES = tests/pacat-simple.c pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la pacat_simple_CFLAGS = $(AM_CFLAGS) pacat_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -parec_simple_SOURCES = parec-simple.c +parec_simple_SOURCES = tests/parec-simple.c parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la parec_simple_CFLAGS = $(AM_CFLAGS) parec_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -strlist_test_SOURCES = strlist-test.c strlist.c strlist.h strbuf.c strbuf.h util.c util.h xmalloc.c xmalloc.h log.c log.h +strlist_test_SOURCES = tests/strlist-test.c strlist_test_CFLAGS = $(AM_CFLAGS) -strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) +strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la libstrlist.la strlist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -voltest_SOURCES = voltest.c sample.c volume.c volume.h sample.h +voltest_SOURCES = tests/voltest.c voltest_CFLAGS = $(AM_CFLAGS) -voltest_LDADD = $(AM_LDADD) +voltest_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h idxset.c idxset.h +cpulimit_test_SOURCES = tests/cpulimit-test.c daemon/cpulimit.c daemon/cpulimit.h cpulimit_test_CFLAGS = $(AM_CFLAGS) -cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la +cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolypcore.la cpulimit_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h idxset.c idxset.h +cpulimit_test2_SOURCES = tests/cpulimit-test.c daemon/cpulimit.c daemon/cpulimit.h cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 -cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la +cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolypcore.la cpulimit_test2_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) @@ -250,29 +249,29 @@ mainloop_test_glib12_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) ################################### polypinclude_HEADERS = \ - cdecl.h \ - channelmap.h \ - glib-mainloop.h \ - mainloop.h \ - mainloop-api.h \ - mainloop-signal.h \ - polyplib.h \ - polyplib-context.h \ - polyplib-def.h \ - polyplib-error.h \ - polyplib-introspect.h \ - polyplib-operation.h \ - polyplib-scache.h \ - polyplib-simple.h \ - polyplib-stream.h \ - polyplib-subscribe.h \ - polyplib-version.h \ - sample.h \ - volume.h + polyp/cdecl.h \ + polyp/channelmap.h \ + polyp/glib-mainloop.h \ + polyp/mainloop.h \ + polyp/mainloop-api.h \ + polyp/mainloop-signal.h \ + polyp/polyplib.h \ + polyp/polyplib-context.h \ + polyp/polyplib-def.h \ + polyp/polyplib-error.h \ + polyp/polyplib-introspect.h \ + polyp/polyplib-operation.h \ + polyp/polyplib-scache.h \ + polyp/polyplib-simple.h \ + polyp/polyplib-stream.h \ + polyp/polyplib-subscribe.h \ + polyp/polyplib-version.h \ + polyp/sample.h \ + polyp/volume.h if HAVE_HOWL polypinclude_HEADERS += \ - polyplib-browser.h + polyp/polyplib-browser.h endif lib_LTLIBRARIES = \ @@ -296,55 +295,59 @@ lib_LTLIBRARIES += \ libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la endif +# Public interface libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ - authkey.c authkey.h \ - cdecl.h \ - client-conf.c client-conf.h \ - conf-parser.c conf-parser.h \ - dllmain.c \ - dynarray.c dynarray.h \ - gcc-printf.h \ - idxset.c idxset.h \ - iochannel.c iochannel.h \ - llist.h \ - log.c log.h \ - mainloop-api.c mainloop-api.h \ - mcalign.c mcalign.h \ - memblock.c memblock.h \ - memchunk.c memchunk.h \ - native-common.h \ - packet.c packet.h \ - parseaddr.c parseaddr.h \ - pdispatch.c pdispatch.h \ - polyplib.h \ - polyplib-context.c polyplib-context.h \ - polyplib-def.h \ - polyplib-internal.h \ - polyplib-introspect.c polyplib-introspect.h \ - polyplib-operation.c polyplib-operation.h \ - polyplib-scache.c polyplib-scache.h \ - polyplib-stream.c polyplib-stream.h \ - polyplib-subscribe.c polyplib-subscribe.h \ - pstream.c pstream.h \ - pstream-util.c pstream-util.h \ - queue.c queue.h \ - random.c random.h \ - sample.c sample.h \ - socket-client.c socket-client.h \ - socket-util.c socket-util.h \ - strbuf.c strbuf.h \ - strlist.c strlist.h \ - tagstruct.c tagstruct.h \ - util.c util.h \ - winsock.h \ - xmalloc.c xmalloc.h \ - channelmap.c channelmap.h \ - volume.c volume.h + polyp/cdecl.h \ + polyp/channelmap.c polyp/channelmap.h \ + polyp/client-conf.c polyp/client-conf.h \ + polyp/llist.h \ + polyp/mainloop-api.c polyp/mainloop-api.h \ + polyp/polyplib.h \ + polyp/polyplib-context.c polyp/polyplib-context.h \ + polyp/polyplib-def.h \ + polyp/polyplib-internal.h \ + polyp/polyplib-introspect.c polyp/polyplib-introspect.h \ + polyp/polyplib-operation.c polyp/polyplib-operation.h \ + polyp/polyplib-scache.c polyp/polyplib-scache.h \ + polyp/polyplib-stream.c polyp/polyplib-stream.h \ + polyp/polyplib-subscribe.c polyp/polyplib-subscribe.h \ + polyp/sample.c polyp/sample.h \ + polyp/volume.c polyp/volume.h + +# Internal stuff that is shared with libpolypcore +libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ + polypcore/authkey.c polypcore/authkey.h \ + polypcore/conf-parser.c polypcore/conf-parser.h \ + polypcore/dllmain.c \ + polypcore/dynarray.c polypcore/dynarray.h \ + polypcore/gccmacro.h \ + polypcore/idxset.c polypcore/idxset.h \ + polypcore/iochannel.c polypcore/iochannel.h \ + polypcore/log.c polypcore/log.h \ + polypcore/mcalign.c polypcore/mcalign.h \ + polypcore/memblock.c polypcore/memblock.h \ + polypcore/memchunk.c polypcore/memchunk.h \ + polypcore/native-common.h \ + polypcore/packet.c polypcore/packet.h \ + polypcore/parseaddr.c polypcore/parseaddr.h \ + polypcore/pdispatch.c polypcore/pdispatch.h \ + polypcore/pstream.c polypcore/pstream.h \ + polypcore/pstream-util.c polypcore/pstream-util.h \ + polypcore/queue.c polypcore/queue.h \ + polypcore/random.c polypcore/random.h \ + polypcore/socket-client.c polypcore/socket-client.h \ + polypcore/socket-util.c polypcore/socket-util.h \ + polypcore/strbuf.c polypcore/strbuf.h \ + polypcore/strlist.c polypcore/strlist.h \ + polypcore/tagstruct.c polypcore/tagstruct.h \ + polypcore/util.c polypcore/util.h \ + polypcore/winsock.h \ + polypcore/xmalloc.c polypcore/xmalloc.h if HAVE_X11 libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ - client-conf-x11.c client-conf-x11.h \ - x11prop.c x11prop.h + polyp/client-conf-x11.c polyp/client-conf-x11.h \ + polypcore/x11prop.c polypcore/x11prop.h endif libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) @@ -361,36 +364,35 @@ libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(LIBASYNCNS_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LIBADD += $(LIBASYNCNS_LIBS) endif -libpolyp_error_@PA_MAJORMINOR@_la_SOURCES = polyplib-error.c polyplib-error.h +libpolyp_error_@PA_MAJORMINOR@_la_SOURCES = polyp/polyplib-error.c polyp/polyplib-error.h libpolyp_error_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_error_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la libpolyp_error_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 libpolyp_mainloop_@PA_MAJORMINOR@_la_SOURCES = \ - mainloop.c mainloop.h \ - mainloop-api.h mainloop-api.c \ - mainloop-signal.c mainloop-signal.h \ - poll.c poll.h + polyp/mainloop.c polyp/mainloop.h \ + polyp/mainloop-signal.c polyp/mainloop-signal.h \ + polypcore/poll.c polypcore/poll.h libpolyp_mainloop_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_mainloop_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(WINSOCK_LIBS) libpolyp_mainloop_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_simple_@PA_MAJORMINOR@_la_SOURCES = polyplib-simple.c polyplib-simple.h +libpolyp_simple_@PA_MAJORMINOR@_la_SOURCES = polyp/polyplib-simple.c polyp/polyplib-simple.h libpolyp_simple_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_simple_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp_simple_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_browse_@PA_MAJORMINOR@_la_SOURCES = polyplib-browser.c polyplib-browser.h +libpolyp_browse_@PA_MAJORMINOR@_la_SOURCES = polyp/polyplib-browser.c polyp/polyplib-browser.h libpolyp_browse_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) libpolyp_browse_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(HOWL_LIBS) libpolyp_browse_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib-mainloop.c +libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_SOURCES = polyp/glib-mainloop.h polyp/glib-mainloop.c libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB20_LIBS) libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib12-mainloop.c +libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_SOURCES = polyp/glib-mainloop.h polyp/glib12-mainloop.c libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB12_LIBS) libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 @@ -399,90 +401,97 @@ libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 # Daemon core library # ################################### -polypinclude_HEADERS += \ - cli-command.h \ - client.h \ - core.h \ - dynarray.h \ - endianmacros.h \ - hashmap.h \ - idxset.h \ - iochannel.h \ - memblock.h \ - memblockq.h \ - memchunk.h \ - modargs.h \ - module.h \ - namereg.h \ - queue.h \ - resampler.h \ - sample-util.h \ - sink.h \ - sink-input.h \ - sioman.h \ - socket-server.h \ - socket-client.h \ - socket-util.h \ - source.h \ - source-output.h \ - strbuf.h \ - tokenizer.h \ - tagstruct.h \ - util.h +polypcoreinclude_HEADERS = \ + polypcore/cli-command.h \ + polypcore/client.h \ + polypcore/core.h \ + polypcore/dynarray.h \ + polypcore/endianmacros.h \ + polypcore/hashmap.h \ + polypcore/idxset.h \ + polypcore/iochannel.h \ + polypcore/log.h \ + polypcore/memblock.h \ + polypcore/memblockq.h \ + polypcore/memchunk.h \ + polypcore/modargs.h \ + polypcore/module.h \ + polypcore/namereg.h \ + polypcore/queue.h \ + polypcore/resampler.h \ + polypcore/sample-util.h \ + polypcore/sink.h \ + polypcore/sink-input.h \ + polypcore/sioman.h \ + polypcore/socket-server.h \ + polypcore/socket-client.h \ + polypcore/socket-util.h \ + polypcore/source.h \ + polypcore/source-output.h \ + polypcore/strbuf.h \ + polypcore/tokenizer.h \ + polypcore/tagstruct.h \ + polypcore/util.h lib_LTLIBRARIES += libpolypcore.la +# Some public stuff is used even in the core. libpolypcore_la_SOURCES = \ - autoload.c autoload.h \ - cli-command.c cli-command.h \ - cli-text.c cli-text.h \ - client.c client.h \ - core.c core.h \ - dllmain.c \ - dynarray.c dynarray.h \ - endianmacros.h \ - g711.c g711.h \ - hashmap.c hashmap.h \ - idxset.c idxset.h \ - log.c log.h \ - mainloop.c mainloop.h \ - mainloop-api.c mainloop-api.h \ - mainloop-signal.c mainloop-signal.h \ - mcalign.c mcalign.h \ - memblock.c memblock.h \ - memblockq.c memblockq.h \ - memchunk.c memchunk.h \ - modargs.c modargs.h \ - modinfo.c modinfo.h \ - module.c module.h \ - namereg.c namereg.h \ - play-memchunk.c play-memchunk.h \ - poll.c poll.h \ - props.c props.h \ - queue.c queue.h \ - random.c random.h \ - resampler.c resampler.h \ - sample.c sample.h \ - sample-util.c sample-util.h \ - scache.c scache.h \ - sconv.c sconv.h \ - sconv-s16be.c sconv-s16be.h \ - sconv-s16le.c sconv-s16le.h \ - sink.c sink.h \ - sink-input.c sink-input.h \ - sioman.c sioman.h \ - sound-file.c sound-file.h \ - sound-file-stream.c sound-file-stream.h \ - source.c source.h \ - source-output.c source-output.h \ - strbuf.c strbuf.h \ - subscribe.c subscripe.h \ - tokenizer.c tokenizer.h \ - util.c util.h \ - winsock.h \ - xmalloc.c xmalloc.h \ - volume.c volume.h \ - channelmap.c channelmap.h + polyp/channelmap.c polyp/channelmap.h \ + polyp/mainloop.c polyp/mainloop.h \ + polyp/mainloop-api.c polyp/mainloop-api.h \ + polyp/mainloop-signal.c polyp/mainloop-signal.h \ + polyp/sample.c polyp/sample.h \ + polyp/volume.c polyp/volume.h + +# Pure core stuff (some are shared in libpolyp though). +libpolypcore_la_SOURCES += \ + polypcore/autoload.c polypcore/autoload.h \ + polypcore/cli-command.c polypcore/cli-command.h \ + polypcore/cli-text.c polypcore/cli-text.h \ + polypcore/client.c polypcore/client.h \ + polypcore/conf-parser.c polypcore/conf-parser.h \ + polypcore/core.c polypcore/core.h \ + polypcore/dllmain.c \ + polypcore/dynarray.c polypcore/dynarray.h \ + polypcore/endianmacros.h \ + polypcore/g711.c polypcore/g711.h \ + polypcore/hashmap.c polypcore/hashmap.h \ + polypcore/idxset.c polypcore/idxset.h \ + polypcore/log.c polypcore/log.h \ + polypcore/mcalign.c polypcore/mcalign.h \ + polypcore/memblock.c polypcore/memblock.h \ + polypcore/memblockq.c polypcore/memblockq.h \ + polypcore/memchunk.c polypcore/memchunk.h \ + polypcore/modargs.c polypcore/modargs.h \ + polypcore/modinfo.c polypcore/modinfo.h \ + polypcore/module.c polypcore/module.h \ + polypcore/namereg.c polypcore/namereg.h \ + polypcore/pid.c polypcore/pid.h \ + polypcore/play-memchunk.c polypcore/play-memchunk.h \ + polypcore/poll.c polypcore/poll.h \ + polypcore/props.c polypcore/props.h \ + polypcore/queue.c polypcore/queue.h \ + polypcore/random.c polypcore/random.h \ + polypcore/resampler.c polypcore/resampler.h \ + polypcore/sample-util.c polypcore/sample-util.h \ + polypcore/scache.c polypcore/scache.h \ + polypcore/sconv.c polypcore/sconv.h \ + polypcore/sconv-s16be.c polypcore/sconv-s16be.h \ + polypcore/sconv-s16le.c polypcore/sconv-s16le.h \ + polypcore/sink.c polypcore/sink.h \ + polypcore/sink-input.c polypcore/sink-input.h \ + polypcore/sioman.c polypcore/sioman.h \ + polypcore/sound-file.c polypcore/sound-file.h \ + polypcore/sound-file-stream.c polypcore/sound-file-stream.h \ + polypcore/source.c polypcore/source.h \ + polypcore/source-output.c polypcore/source-output.h \ + polypcore/strbuf.c polypcore/strbuf.h \ + polypcore/subscribe.c polypcore/subscribe.h \ + polypcore/tokenizer.c polypcore/tokenizer.h \ + polypcore/util.c polypcore/util.h \ + polypcore/winsock.h \ + polypcore/xmalloc.c polypcore/xmalloc.h libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) libpolypcore_la_LDFLAGS = -avoid-version @@ -540,117 +549,117 @@ modlib_LTLIBRARIES += \ libhowl-wrap.la endif -libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h +libprotocol_simple_la_SOURCES = polypcore/protocol-simple.c polypcore/protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-server.la libiochannel.la libsocket_server_la_SOURCES = \ - inet_ntop.c inet_ntop.h \ - socket-server.c socket-server.h + polypcore/inet_ntop.c polypcore/inet_ntop.h \ + polypcore/socket-server.c polypcore/socket-server.h libsocket_server_la_LDFLAGS = -avoid-version libsocket_server_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS) -libsocket_client_la_SOURCES = socket-client.c socket-client.h +libsocket_client_la_SOURCES = polypcore/socket-client.c polypcore/socket-client.h libsocket_client_la_LDFLAGS = -avoid-version libsocket_client_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS) $(WINSOCK_LIBS) libsocket_client_la_CFLAGS = $(AM_CFLAGS) $(LIBASYNCNS_CFLAGS) -libparseaddr_la_SOURCES = parseaddr.c parseaddr.h +libparseaddr_la_SOURCES = polypcore/parseaddr.c polypcore/parseaddr.h libparseaddr_la_LDFLAGS = -avoid-version libparseaddr_la_LIBADD = $(AM_LIBADD) libpolypcore.la -libpstream_la_SOURCES = pstream.c pstream.h +libpstream_la_SOURCES = polypcore/pstream.c polypcore/pstream.h libpstream_la_LDFLAGS = -avoid-version libpstream_la_LIBADD = $(AM_LIBADD) libpolypcore.la libpacket.la libiochannel.la $(WINSOCK_LIBS) -libpstream_util_la_SOURCES = pstream-util.c pstream-util.h +libpstream_util_la_SOURCES = polypcore/pstream-util.c polypcore/pstream-util.h libpstream_util_la_LDFLAGS = -avoid-version libpstream_util_la_LIBADD = $(AM_LIBADD) libpacket.la libpstream.la libtagstruct.la -libpdispatch_la_SOURCES = pdispatch.c pdispatch.h +libpdispatch_la_SOURCES = polypcore/pdispatch.c polypcore/pdispatch.h libpdispatch_la_LDFLAGS = -avoid-version libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la libpolypcore.la -libiochannel_la_SOURCES = iochannel.c iochannel.h +libiochannel_la_SOURCES = polypcore/iochannel.c polypcore/iochannel.h libiochannel_la_LDFLAGS = -avoid-version libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpolypcore.la $(WINSOCK_LIBS) -libpacket_la_SOURCES = packet.c packet.h +libpacket_la_SOURCES = polypcore/packet.c polypcore/packet.h libpacket_la_LDFLAGS = -avoid-version libpacket_la_LIBADD = $(AM_LIBADD) libpolypcore.la -libioline_la_SOURCES = ioline.c ioline.h +libioline_la_SOURCES = polypcore/ioline.c polypcore/ioline.h libioline_la_LDFLAGS = -avoid-version libioline_la_LIBADD = $(AM_LIBADD) libiochannel.la libpolypcore.la -libcli_la_SOURCES = cli.c cli.h +libcli_la_SOURCES = polypcore/cli.c polypcore/cli.h libcli_la_CPPFLAGS = $(AM_CPPFLAGS) libcli_la_LDFLAGS = -avoid-version libcli_la_LIBADD = $(AM_LIBADD) libiochannel.la libioline.la libpolypcore.la -libstrlist_la_SOURCES = strlist.c strlist.h +libstrlist_la_SOURCES = polypcore/strlist.c polypcore/strlist.h libstrlist_la_LDFLAGS = -avoid-version libstrlist_la_LIBADD = $(AM_LIBADD) libpolypcore.la -libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h +libprotocol_cli_la_SOURCES = polypcore/protocol-cli.c polypcore/protocol-cli.h libprotocol_cli_la_LDFLAGS = -avoid-version libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la libpolypcore.la -libprotocol_http_la_SOURCES = protocol-http.c protocol-http.h +libprotocol_http_la_SOURCES = polypcore/protocol-http.c polypcore/protocol-http.h libprotocol_http_la_LDFLAGS = -avoid-version libprotocol_http_la_LIBADD = $(AM_LIBADD) libsocket-server.la libioline.la libpolypcore.la libiochannel.la -libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h native-common.h +libprotocol_native_la_SOURCES = polypcore/protocol-native.c polypcore/protocol-native.h polypcore/native-common.h libprotocol_native_la_LDFLAGS = -avoid-version libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la libpolypcore.la libiochannel.la -libtagstruct_la_SOURCES = tagstruct.c tagstruct.h +libtagstruct_la_SOURCES = polypcore/tagstruct.c polypcore/tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version libtagstruct_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(WINSOCK_LIBS) -libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h esound.h +libprotocol_esound_la_SOURCES = polypcore/protocol-esound.c polypcore/protocol-esound.h polypcore/esound.h libprotocol_esound_la_LDFLAGS = -avoid-version libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la libpolypcore.la -libauthkey_la_SOURCES = authkey.c authkey.h +libauthkey_la_SOURCES = polypcore/authkey.c polypcore/authkey.h libauthkey_la_LDFLAGS = -avoid-version libauthkey_la_LIBADD = $(AM_LIBADD) libpolypcore.la -libauthkey_prop_la_SOURCES = authkey-prop.c authkey-prop.h +libauthkey_prop_la_SOURCES = polypcore/authkey-prop.c polypcore/authkey-prop.h libauthkey_prop_la_LDFLAGS = -avoid-version libauthkey_prop_la_LIBADD = $(AM_LIBADD) libpolypcore.la -libsocket_util_la_SOURCES = socket-util.c socket-util.h +libsocket_util_la_SOURCES = polypcore/socket-util.c polypcore/socket-util.h libsocket_util_la_LDFLAGS = -avoid-version libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) # X11 -libx11wrap_la_SOURCES = x11wrap.c x11wrap.h +libx11wrap_la_SOURCES = polypcore/x11wrap.c polypcore/x11wrap.h libx11wrap_la_LDFLAGS = -avoid-version libx11wrap_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) -libx11prop_la_SOURCES = x11prop.c x11prop.h +libx11prop_la_SOURCES = polypcore/x11prop.c polypcore/x11prop.h libx11prop_la_LDFLAGS = -avoid-version libx11prop_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) # OSS -liboss_util_la_SOURCES = oss-util.c oss-util.h +liboss_util_la_SOURCES = polypcore/oss-util.c polypcore/oss-util.h liboss_util_la_LDFLAGS = -avoid-version # ALSA -libalsa_util_la_SOURCES = alsa-util.c alsa-util.h +libalsa_util_la_SOURCES = polypcore/alsa-util.c polypcore/alsa-util.h libalsa_util_la_LDFLAGS = -avoid-version libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) # HOWL -libhowl_wrap_la_SOURCES = howl-wrap.c howl-wrap.h +libhowl_wrap_la_SOURCES = polypcore/howl-wrap.c polypcore/howl-wrap.h libhowl_wrap_la_LDFLAGS = -avoid-version libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) @@ -752,268 +761,268 @@ endif # These are generated by a M4 script SYMDEF_FILES = \ - module-cli-symdef.h \ - module-cli-protocol-tcp-symdef.h \ - module-cli-protocol-tcp6-symdef.h \ - module-cli-protocol-unix-symdef.h \ - module-pipe-sink-symdef.h \ - module-pipe-source-symdef.h \ - module-simple-protocol-tcp-symdef.h \ - module-simple-protocol-tcp6-symdef.h \ - module-simple-protocol-unix-symdef.h \ - module-esound-protocol-tcp-symdef.h \ - module-esound-protocol-tcp6-symdef.h \ - module-esound-protocol-unix-symdef.h \ - module-native-protocol-tcp-symdef.h \ - module-native-protocol-tcp6-symdef.h \ - module-native-protocol-unix-symdef.h \ - module-native-protocol-fd-symdef.h \ - module-sine-symdef.h \ - module-combine-symdef.h \ - module-esound-compat-spawnfd-symdef.h \ - module-esound-compat-spawnpid-symdef.h \ - module-match-symdef.h \ - module-tunnel-sink-symdef.h \ - module-tunnel-source-symdef.h \ - module-null-sink-symdef.h \ - module-esound-sink-symdef.h \ - module-zeroconf-publish-symdef.h \ - module-lirc-symdef.h \ - module-mmkbd-evdev-symdef.h \ - module-http-protocol-tcp-symdef.h \ - module-http-protocol-tcp6-symdef.h \ - module-http-protocol-unix-symdef.h \ - module-x11-bell-symdef.h \ - module-x11-publish-symdef.h \ - module-oss-symdef.h \ - module-oss-mmap-symdef.h \ - module-alsa-sink-symdef.h \ - module-alsa-source-symdef.h \ - module-solaris-symdef.h \ - module-waveout-symdef.h \ - module-detect-symdef.h + modules/module-cli-symdef.h \ + modules/module-cli-protocol-tcp-symdef.h \ + modules/module-cli-protocol-tcp6-symdef.h \ + modules/module-cli-protocol-unix-symdef.h \ + modules/module-pipe-sink-symdef.h \ + modules/module-pipe-source-symdef.h \ + modules/module-simple-protocol-tcp-symdef.h \ + modules/module-simple-protocol-tcp6-symdef.h \ + modules/module-simple-protocol-unix-symdef.h \ + modules/module-esound-protocol-tcp-symdef.h \ + modules/module-esound-protocol-tcp6-symdef.h \ + modules/module-esound-protocol-unix-symdef.h \ + modules/module-native-protocol-tcp-symdef.h \ + modules/module-native-protocol-tcp6-symdef.h \ + modules/module-native-protocol-unix-symdef.h \ + modules/module-native-protocol-fd-symdef.h \ + modules/module-sine-symdef.h \ + modules/module-combine-symdef.h \ + modules/module-esound-compat-spawnfd-symdef.h \ + modules/module-esound-compat-spawnpid-symdef.h \ + modules/module-match-symdef.h \ + modules/module-tunnel-sink-symdef.h \ + modules/module-tunnel-source-symdef.h \ + modules/module-null-sink-symdef.h \ + modules/module-esound-sink-symdef.h \ + modules/module-zeroconf-publish-symdef.h \ + modules/module-lirc-symdef.h \ + modules/module-mmkbd-evdev-symdef.h \ + modules/module-http-protocol-tcp-symdef.h \ + modules/module-http-protocol-tcp6-symdef.h \ + modules/module-http-protocol-unix-symdef.h \ + modules/module-x11-bell-symdef.h \ + modules/module-x11-publish-symdef.h \ + modules/module-oss-symdef.h \ + modules/module-oss-mmap-symdef.h \ + modules/module-alsa-sink-symdef.h \ + modules/module-alsa-source-symdef.h \ + modules/module-solaris-symdef.h \ + modules/module-waveout-symdef.h \ + modules/module-detect-symdef.h EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) -$(SYMDEF_FILES): module-defs.h.m4 +$(SYMDEF_FILES): modules/module-defs.h.m4 $(M4) -Dfname="$@" $< > $@ # Simple protocol -module_simple_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_simple_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la -module_simple_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_simple_protocol_tcp6_la_SOURCES = modules/module-protocol-stub.c module_simple_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_tcp6_la_LDFLAGS = -module -avoid-version module_simple_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la -module_simple_protocol_unix_la_SOURCES = module-protocol-stub.c +module_simple_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version module_simple_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la libsocket-util.la # CLI protocol -module_cli_la_SOURCES = module-cli.c +module_cli_la_SOURCES = modules/module-cli.c module_cli_la_LDFLAGS = -module -avoid-version module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la libpolypcore.la -module_cli_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_cli_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la -module_cli_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_cli_protocol_tcp6_la_SOURCES = modules/module-protocol-stub.c module_cli_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_tcp6_la_LDFLAGS = -module -avoid-version module_cli_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la -module_cli_protocol_unix_la_SOURCES = module-protocol-stub.c +module_cli_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la libsocket-util.la # HTTP protocol -module_http_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_http_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_http_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) module_http_protocol_tcp_la_LDFLAGS = -module -avoid-version module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la -module_http_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_http_protocol_tcp6_la_SOURCES = modules/module-protocol-stub.c module_http_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) module_http_protocol_tcp6_la_LDFLAGS = -module -avoid-version module_http_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la -module_http_protocol_unix_la_SOURCES = module-protocol-stub.c +module_http_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) module_http_protocol_unix_la_LDFLAGS = -module -avoid-version module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la libsocket-util.la # Native protocol -module_native_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_native_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la -module_native_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_native_protocol_tcp6_la_SOURCES = modules/module-protocol-stub.c module_native_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_tcp6_la_LDFLAGS = -module -avoid-version module_native_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la -module_native_protocol_unix_la_SOURCES = module-protocol-stub.c +module_native_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_unix_la_LDFLAGS = -module -avoid-version module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la libsocket-util.la -module_native_protocol_fd_la_SOURCES = module-native-protocol-fd.c +module_native_protocol_fd_la_SOURCES = modules/module-native-protocol-fd.c module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS) module_native_protocol_fd_la_LDFLAGS = -module -avoid-version module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la libsocket-util.la libiochannel.la # EsounD protocol -module_esound_protocol_tcp_la_SOURCES = module-protocol-stub.c +module_esound_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la -module_esound_protocol_tcp6_la_SOURCES = module-protocol-stub.c +module_esound_protocol_tcp6_la_SOURCES = modules/module-protocol-stub.c module_esound_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_tcp6_la_LDFLAGS = -module -avoid-version module_esound_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la -module_esound_protocol_unix_la_SOURCES = module-protocol-stub.c +module_esound_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la libsocket-util.la -module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c +module_esound_compat_spawnfd_la_SOURCES = modules/module-esound-compat-spawnfd.c module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpolypcore.la -module_esound_compat_spawnpid_la_SOURCES = module-esound-compat-spawnpid.c +module_esound_compat_spawnpid_la_SOURCES = modules/module-esound-compat-spawnpid.c module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpolypcore.la -module_esound_sink_la_SOURCES = module-esound-sink.c +module_esound_sink_la_SOURCES = modules/module-esound-sink.c module_esound_sink_la_LDFLAGS = -module -avoid-version module_esound_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-client.la libauthkey.la # Pipes -module_pipe_sink_la_SOURCES = module-pipe-sink.c +module_pipe_sink_la_SOURCES = modules/module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version module_pipe_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la -module_pipe_source_la_SOURCES = module-pipe-source.c +module_pipe_source_la_SOURCES = modules/module-pipe-source.c module_pipe_source_la_LDFLAGS = -module -avoid-version module_pipe_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la # Fake sources/sinks -module_sine_la_SOURCES = module-sine.c +module_sine_la_SOURCES = modules/module-sine.c module_sine_la_LDFLAGS = -module -avoid-version module_sine_la_LIBADD = $(AM_LIBADD) libpolypcore.la -module_null_sink_la_SOURCES = module-null-sink.c +module_null_sink_la_SOURCES = modules/module-null-sink.c module_null_sink_la_LDFLAGS = -module -avoid-version module_null_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la # Couplings -module_combine_la_SOURCES = module-combine.c +module_combine_la_SOURCES = modules/module-combine.c module_combine_la_LDFLAGS = -module -avoid-version module_combine_la_LIBADD = $(AM_LIBADD) libpolypcore.la -module_match_la_SOURCES = module-match.c +module_match_la_SOURCES = modules/module-match.c module_match_la_LDFLAGS = -module -avoid-version module_match_la_LIBADD = $(AM_LIBADD) libpolypcore.la -module_tunnel_sink_la_SOURCES = module-tunnel.c +module_tunnel_sink_la_SOURCES = modules/module-tunnel.c module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) module_tunnel_sink_la_LDFLAGS = -module -avoid-version module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la -module_tunnel_source_la_SOURCES = module-tunnel.c +module_tunnel_source_la_SOURCES = modules/module-tunnel.c module_tunnel_source_la_LDFLAGS = -module -avoid-version module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la # X11 -module_x11_bell_la_SOURCES = module-x11-bell.c +module_x11_bell_la_SOURCES = modules/module-x11-bell.c module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_bell_la_LDFLAGS = -module -avoid-version module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la -module_x11_publish_la_SOURCES = module-x11-publish.c +module_x11_publish_la_SOURCES = modules/module-x11-publish.c module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_publish_la_LDFLAGS = -module -avoid-version module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauthkey-prop.la libx11prop.la libstrlist.la # OSS -module_oss_la_SOURCES = module-oss.c +module_oss_la_SOURCES = modules/module-oss.c module_oss_la_LDFLAGS = -module -avoid-version module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la -module_oss_mmap_la_SOURCES = module-oss-mmap.c +module_oss_mmap_la_SOURCES = modules/module-oss-mmap.c module_oss_mmap_la_LDFLAGS = -module -avoid-version module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la # ALSA -module_alsa_sink_la_SOURCES = module-alsa-sink.c +module_alsa_sink_la_SOURCES = modules/module-alsa-sink.c module_alsa_sink_la_LDFLAGS = -module -avoid-version module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) -module_alsa_source_la_SOURCES = module-alsa-source.c +module_alsa_source_la_SOURCES = modules/module-alsa-source.c module_alsa_source_la_LDFLAGS = -module -avoid-version module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) # Solaris -module_solaris_la_SOURCES = module-solaris.c +module_solaris_la_SOURCES = modules/module-solaris.c module_solaris_la_LDFLAGS = -module -avoid-version module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la # HOWL -module_zeroconf_publish_la_SOURCES = module-zeroconf-publish.c +module_zeroconf_publish_la_SOURCES = modules/module-zeroconf-publish.c module_zeroconf_publish_la_LDFLAGS = -module -avoid-version module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) # LIRC -module_lirc_la_SOURCES = module-lirc.c +module_lirc_la_SOURCES = modules/module-lirc.c module_lirc_la_LDFLAGS = -module -avoid-version module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS) # Linux evdev -module_mmkbd_evdev_la_SOURCES = module-mmkbd-evdev.c +module_mmkbd_evdev_la_SOURCES = modules/module-mmkbd-evdev.c module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS) # Windows waveout -module_waveout_la_SOURCES = module-waveout.c +module_waveout_la_SOURCES = modules/module-waveout.c module_waveout_la_LDFLAGS = -module -avoid-version module_waveout_la_LIBADD = $(AM_LIBADD) libpolypcore.la -lwinmm module_waveout_la_CFLAGS = $(AM_CFLAGS) # Hardware autodetection module -module_detect_la_SOURCES = module-detect.c +module_detect_la_SOURCES = modules/module-detect.c module_detect_la_LDFLAGS = -module -avoid-version module_detect_la_LIBADD = $(AM_LIBADD) module_detect_la_CFLAGS = $(AM_CFLAGS) @@ -1026,7 +1035,7 @@ suid: polypaudio chown root $< chmod u+s $< -esdcompat.sh: esdcompat.sh.in Makefile +utils/esdcompat.sh: utils/esdcompat.sh.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ diff --git a/polyp/client.conf.in b/src/client.conf.in similarity index 100% rename from polyp/client.conf.in rename to src/client.conf.in diff --git a/polyp/daemon.conf.in b/src/daemon.conf.in similarity index 100% rename from polyp/daemon.conf.in rename to src/daemon.conf.in diff --git a/polyp/caps.c b/src/daemon/caps.c similarity index 98% rename from polyp/caps.c rename to src/daemon/caps.c index 4ecb5848d..8d4294594 100644 --- a/polyp/caps.c +++ b/src/daemon/caps.c @@ -32,7 +32,7 @@ #include #endif -#include "log.h" +#include #include "caps.h" #ifdef HAVE_GETUID diff --git a/polyp/caps.h b/src/daemon/caps.h similarity index 100% rename from polyp/caps.h rename to src/daemon/caps.h diff --git a/polyp/cmdline.c b/src/daemon/cmdline.c similarity index 99% rename from polyp/cmdline.c rename to src/daemon/cmdline.c index 5635707f2..0b5f9ec75 100644 --- a/polyp/cmdline.c +++ b/src/daemon/cmdline.c @@ -31,9 +31,9 @@ #include #include "cmdline.h" -#include "util.h" -#include "strbuf.h" -#include "xmalloc.h" +#include +#include +#include /* Argument codes for getopt_long() */ enum { diff --git a/polyp/cmdline.h b/src/daemon/cmdline.h similarity index 100% rename from polyp/cmdline.h rename to src/daemon/cmdline.h diff --git a/polyp/cpulimit.c b/src/daemon/cpulimit.c similarity index 99% rename from polyp/cpulimit.c rename to src/daemon/cpulimit.c index a834b0948..6887796f2 100644 --- a/polyp/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -24,8 +24,8 @@ #endif #include "cpulimit.h" -#include "util.h" -#include "log.h" +#include +#include #ifdef HAVE_SIGXCPU diff --git a/polyp/cpulimit.h b/src/daemon/cpulimit.h similarity index 97% rename from polyp/cpulimit.h rename to src/daemon/cpulimit.h index 8ca4f8d9f..f3c5534d1 100644 --- a/polyp/cpulimit.h +++ b/src/daemon/cpulimit.h @@ -22,7 +22,7 @@ USA. ***/ -#include "mainloop-api.h" +#include /* This kills the polypaudio process if it eats more than 70% of the * CPU time. This is build around setrlimit() and SIGXCPU. It is handy diff --git a/polyp/daemon-conf.c b/src/daemon/daemon-conf.c similarity index 98% rename from polyp/daemon-conf.c rename to src/daemon/daemon-conf.c index 103cf46a4..8fe3c4cc5 100644 --- a/polyp/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -30,11 +30,11 @@ #include #include "daemon-conf.h" -#include "util.h" -#include "xmalloc.h" -#include "strbuf.h" -#include "conf-parser.h" -#include "resampler.h" +#include +#include +#include +#include +#include #ifndef DEFAULT_CONFIG_DIR # ifndef OS_IS_WIN32 diff --git a/polyp/daemon-conf.h b/src/daemon/daemon-conf.h similarity index 99% rename from polyp/daemon-conf.h rename to src/daemon/daemon-conf.h index cebc0bd63..d51314197 100644 --- a/polyp/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -22,7 +22,7 @@ USA. ***/ -#include "log.h" +#include /* The actual command to execute */ typedef enum pa_daemon_conf_cmd { diff --git a/polyp/dumpmodules.c b/src/daemon/dumpmodules.c similarity index 97% rename from polyp/dumpmodules.c rename to src/daemon/dumpmodules.c index 6864b965a..8d8eb0b9f 100644 --- a/polyp/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -30,8 +30,8 @@ #include #include "dumpmodules.h" -#include "modinfo.h" -#include "util.h" +#include +#include #define PREFIX "module-" diff --git a/polyp/dumpmodules.h b/src/daemon/dumpmodules.h similarity index 100% rename from polyp/dumpmodules.h rename to src/daemon/dumpmodules.h diff --git a/polyp/main.c b/src/daemon/main.c similarity index 96% rename from polyp/main.c rename to src/daemon/main.c index b5aac8512..6be83d8c1 100644 --- a/polyp/main.c +++ b/src/daemon/main.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -48,25 +47,26 @@ #include #endif -#include "winsock.h" +#include -#include "core.h" -#include "mainloop.h" -#include "module.h" -#include "mainloop-signal.h" +#include +#include +#include +#include +#include #include "cmdline.h" -#include "cli-command.h" -#include "util.h" -#include "sioman.h" -#include "xmalloc.h" +#include +#include +#include +#include #include "cpulimit.h" -#include "log.h" +#include #include "daemon-conf.h" #include "dumpmodules.h" #include "caps.h" -#include "cli-text.h" -#include "pid.h" -#include "namereg.h" +#include +#include +#include #ifdef HAVE_LIBWRAP /* Only one instance of these variables */ diff --git a/polyp/default.pa.in b/src/default.pa.in similarity index 100% rename from polyp/default.pa.in rename to src/default.pa.in diff --git a/polyp/default.pa.win32 b/src/default.pa.win32 similarity index 100% rename from polyp/default.pa.win32 rename to src/default.pa.win32 diff --git a/polyp/depmod.py b/src/depmod.py similarity index 100% rename from polyp/depmod.py rename to src/depmod.py diff --git a/polyp/module-alsa-sink.c b/src/modules/module-alsa-sink.c similarity index 96% rename from polyp/module-alsa-sink.c rename to src/modules/module-alsa-sink.c index 9aa220be0..48e90e9f2 100644 --- a/polyp/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -34,16 +34,17 @@ #include -#include "module.h" -#include "core.h" -#include "memchunk.h" -#include "sink.h" -#include "modargs.h" -#include "util.h" -#include "sample-util.h" -#include "alsa-util.h" -#include "xmalloc.h" -#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-alsa-sink-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-alsa-source.c b/src/modules/module-alsa-source.c similarity index 96% rename from polyp/module-alsa-source.c rename to src/modules/module-alsa-source.c index efc84efeb..f03e51ad6 100644 --- a/polyp/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -34,16 +34,17 @@ #include -#include "module.h" -#include "core.h" -#include "memchunk.h" -#include "sink.h" -#include "modargs.h" -#include "util.h" -#include "sample-util.h" -#include "alsa-util.h" -#include "xmalloc.h" -#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-alsa-source-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-cli.c b/src/modules/module-cli.c similarity index 93% rename from polyp/module-cli.c rename to src/modules/module-cli.c index db0e895ce..c782ff8db 100644 --- a/polyp/module-cli.c +++ b/src/modules/module-cli.c @@ -27,11 +27,12 @@ #include #include -#include "module.h" -#include "iochannel.h" -#include "cli.h" -#include "sioman.h" -#include "log.h" +#include +#include +#include +#include +#include + #include "module-cli-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-combine.c b/src/modules/module-combine.c similarity index 97% rename from polyp/module-combine.c rename to src/modules/module-combine.c index 0c21c2f55..aabb8f28b 100644 --- a/polyp/module-combine.c +++ b/src/modules/module-combine.c @@ -26,16 +26,17 @@ #include #include -#include "module.h" -#include "llist.h" -#include "sink.h" -#include "sink-input.h" -#include "memblockq.h" -#include "log.h" -#include "util.h" -#include "xmalloc.h" -#include "modargs.h" -#include "namereg.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-combine-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-defs.h.m4 b/src/modules/module-defs.h.m4 similarity index 81% rename from polyp/module-defs.h.m4 rename to src/modules/module-defs.h.m4 index 2eff25a72..8f10d6599 100644 --- a/polyp/module-defs.h.m4 +++ b/src/modules/module-defs.h.m4 @@ -1,6 +1,6 @@ dnl $Id$ changecom(`/*', `*/')dnl -define(`module_name', patsubst(patsubst(fname, `-symdef.h$'), `[^0-9a-zA-Z]', `_'))dnl +define(`module_name', patsubst(patsubst(patsubst(fname, `-symdef.h$'), `^.*/'), `[^0-9a-zA-Z]', `_'))dnl define(`c_symbol', patsubst(module_name, `[^0-9a-zA-Z]', `_'))dnl define(`c_macro', patsubst(module_name, `[^0-9a-zA-Z]', `'))dnl define(`incmacro', `foo'c_macro`symdeffoo')dnl @@ -8,8 +8,8 @@ define(`gen_symbol', `#define $1 'module_name`_LTX_$1')dnl #ifndef incmacro #define incmacro -#include "core.h" -#include "module.h" +#include +#include gen_symbol(pa__init) gen_symbol(pa__done) diff --git a/polyp/module-detect.c b/src/modules/module-detect.c similarity index 97% rename from polyp/module-detect.c rename to src/modules/module-detect.c index ee75da368..e325b22c3 100644 --- a/polyp/module-detect.c +++ b/src/modules/module-detect.c @@ -31,11 +31,12 @@ #include #include -#include "module.h" -#include "log.h" +#include +#include +#include +#include + #include "module-detect-symdef.h" -#include "xmalloc.h" -#include "modargs.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") diff --git a/polyp/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c similarity index 94% rename from polyp/module-esound-compat-spawnfd.c rename to src/modules/module-esound-compat-spawnfd.c index 5051e4d00..5c656be9c 100644 --- a/polyp/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -28,10 +28,11 @@ #include #include -#include "module.h" -#include "util.h" -#include "modargs.h" -#include "log.h" +#include +#include +#include +#include + #include "module-esound-compat-spawnfd-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c similarity index 94% rename from polyp/module-esound-compat-spawnpid.c rename to src/modules/module-esound-compat-spawnpid.c index aa8b0f822..5daa1297a 100644 --- a/polyp/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -28,10 +28,11 @@ #include #include -#include "module.h" -#include "util.h" -#include "modargs.h" -#include "log.h" +#include +#include +#include +#include + #include "module-esound-compat-spawnpid-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-esound-sink.c b/src/modules/module-esound-sink.c similarity index 97% rename from polyp/module-esound-sink.c rename to src/modules/module-esound-sink.c index afd5feed8..4f724811d 100644 --- a/polyp/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -33,17 +33,18 @@ #include #include -#include "iochannel.h" -#include "sink.h" -#include "module.h" -#include "util.h" -#include "modargs.h" -#include "xmalloc.h" -#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-esound-sink-symdef.h" -#include "socket-client.h" -#include "esound.h" -#include "authkey.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ESOUND Sink") diff --git a/polyp/module-lirc.c b/src/modules/module-lirc.c similarity index 97% rename from polyp/module-lirc.c rename to src/modules/module-lirc.c index d2e248aa0..ea8a2bd2b 100644 --- a/polyp/module-lirc.c +++ b/src/modules/module-lirc.c @@ -30,13 +30,14 @@ #include #include -#include "module.h" -#include "log.h" +#include +#include +#include +#include +#include +#include + #include "module-lirc-symdef.h" -#include "namereg.h" -#include "sink.h" -#include "xmalloc.h" -#include "modargs.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("LIRC volume control") diff --git a/polyp/module-match.c b/src/modules/module-match.c similarity index 96% rename from polyp/module-match.c rename to src/modules/module-match.c index e3e7b17d2..10ceb75ed 100644 --- a/polyp/module-match.c +++ b/src/modules/module-match.c @@ -32,13 +32,14 @@ #include #include -#include "module.h" -#include "util.h" -#include "modargs.h" -#include "log.h" -#include "subscribe.h" -#include "xmalloc.h" -#include "sink-input.h" +#include +#include +#include +#include +#include +#include +#include + #include "module-match-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c similarity index 97% rename from polyp/module-mmkbd-evdev.c rename to src/modules/module-mmkbd-evdev.c index ec45ec4b9..b60f786d5 100644 --- a/polyp/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -33,14 +33,15 @@ #include -#include "module.h" -#include "log.h" +#include +#include +#include +#include +#include +#include +#include + #include "module-mmkbd-evdev-symdef.h" -#include "namereg.h" -#include "sink.h" -#include "xmalloc.h" -#include "modargs.h" -#include "util.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Multimedia keyboard support via Linux evdev") diff --git a/polyp/module-native-protocol-fd.c b/src/modules/module-native-protocol-fd.c similarity index 92% rename from polyp/module-native-protocol-fd.c rename to src/modules/module-native-protocol-fd.c index 7f09ff914..abc531b31 100644 --- a/polyp/module-native-protocol-fd.c +++ b/src/modules/module-native-protocol-fd.c @@ -27,11 +27,12 @@ #include #include -#include "module.h" -#include "iochannel.h" -#include "modargs.h" -#include "protocol-native.h" -#include "log.h" +#include +#include +#include +#include +#include + #include "module-native-protocol-fd-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-null-sink.c b/src/modules/module-null-sink.c similarity index 94% rename from polyp/module-null-sink.c rename to src/modules/module-null-sink.c index 93abca78d..5731a4032 100644 --- a/polyp/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -33,13 +33,14 @@ #include #include -#include "iochannel.h" -#include "sink.h" -#include "module.h" -#include "util.h" -#include "modargs.h" -#include "xmalloc.h" -#include "log.h" +#include +#include +#include +#include +#include +#include +#include + #include "module-null-sink-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-oss-mmap.c b/src/modules/module-oss-mmap.c similarity index 97% rename from polyp/module-oss-mmap.c rename to src/modules/module-oss-mmap.c index f976cf81c..6986b03c9 100644 --- a/polyp/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -36,16 +36,17 @@ #include #include -#include "iochannel.h" -#include "sink.h" -#include "source.h" -#include "module.h" -#include "oss-util.h" -#include "sample-util.h" -#include "util.h" -#include "modargs.h" -#include "xmalloc.h" -#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-oss-mmap-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-oss.c b/src/modules/module-oss.c similarity index 97% rename from polyp/module-oss.c rename to src/modules/module-oss.c index b5c7ae8cf..04458419a 100644 --- a/polyp/module-oss.c +++ b/src/modules/module-oss.c @@ -35,16 +35,17 @@ #include #include -#include "iochannel.h" -#include "sink.h" -#include "source.h" -#include "module.h" -#include "oss-util.h" -#include "sample-util.h" -#include "util.h" -#include "modargs.h" -#include "xmalloc.h" -#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-oss-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-pipe-sink.c b/src/modules/module-pipe-sink.c similarity index 96% rename from polyp/module-pipe-sink.c rename to src/modules/module-pipe-sink.c index 20e220ce9..6ace377f0 100644 --- a/polyp/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -33,13 +33,14 @@ #include #include -#include "iochannel.h" -#include "sink.h" -#include "module.h" -#include "util.h" -#include "modargs.h" -#include "xmalloc.h" -#include "log.h" +#include +#include +#include +#include +#include +#include +#include + #include "module-pipe-sink-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-pipe-source.c b/src/modules/module-pipe-source.c similarity index 96% rename from polyp/module-pipe-source.c rename to src/modules/module-pipe-source.c index 42f13d4b0..a7bb0ce7d 100644 --- a/polyp/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -33,13 +33,14 @@ #include #include -#include "iochannel.h" -#include "source.h" -#include "module.h" -#include "util.h" -#include "modargs.h" -#include "xmalloc.h" -#include "log.h" +#include +#include +#include +#include +#include +#include +#include + #include "module-pipe-source-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-protocol-stub.c b/src/modules/module-protocol-stub.c similarity index 94% rename from polyp/module-protocol-stub.c rename to src/modules/module-protocol-stub.c index a03143682..469ddceea 100644 --- a/polyp/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -40,16 +40,15 @@ #include #endif -#include "winsock.h" +#include -#include "module.h" -#include "socket-server.h" -#include "socket-util.h" -#include "util.h" -#include "modargs.h" -#include "log.h" -#include "native-common.h" -#include "util.h" +#include +#include +#include +#include +#include +#include +#include #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" @@ -63,7 +62,7 @@ #endif #if defined(USE_PROTOCOL_SIMPLE) - #include "protocol-simple.h" + #include #define protocol_new pa_protocol_simple_new #define protocol_free pa_protocol_simple_free #define TCPWRAP_SERVICE "polypaudio-simple" @@ -80,7 +79,7 @@ PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("rate= format= channels= sink= source= playback= record= "SOCKET_USAGE) #elif defined(USE_PROTOCOL_CLI) - #include "protocol-cli.h" + #include #define protocol_new pa_protocol_cli_new #define protocol_free pa_protocol_cli_free #define TCPWRAP_SERVICE "polypaudio-cli" @@ -97,7 +96,7 @@ PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE(SOCKET_USAGE) #elif defined(USE_PROTOCOL_HTTP) - #include "protocol-http.h" + #include #define protocol_new pa_protocol_http_new #define protocol_free pa_protocol_http_free #define TCPWRAP_SERVICE "polypaudio-http" @@ -114,7 +113,7 @@ PA_MODULE_DESCRIPTION("HTTP "SOCKET_DESCRIPTION) PA_MODULE_USAGE(SOCKET_USAGE) #elif defined(USE_PROTOCOL_NATIVE) - #include "protocol-native.h" + #include #define protocol_new pa_protocol_native_new #define protocol_free pa_protocol_native_free #define TCPWRAP_SERVICE "polypaudio-native" @@ -131,8 +130,8 @@ PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("public= cookie= "SOCKET_USAGE) #elif defined(USE_PROTOCOL_ESOUND) - #include "protocol-esound.h" - #include "esound.h" + #include + #include #define protocol_new pa_protocol_esound_new #define protocol_free pa_protocol_esound_free #define TCPWRAP_SERVICE "esound" diff --git a/polyp/module-sine.c b/src/modules/module-sine.c similarity index 96% rename from polyp/module-sine.c rename to src/modules/module-sine.c index 529c061a7..446e39749 100644 --- a/polyp/module-sine.c +++ b/src/modules/module-sine.c @@ -27,12 +27,13 @@ #include #include -#include "sink-input.h" -#include "module.h" -#include "modargs.h" -#include "xmalloc.h" -#include "namereg.h" -#include "log.h" +#include +#include +#include +#include +#include +#include + #include "module-sine-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-solaris.c b/src/modules/module-solaris.c similarity index 97% rename from polyp/module-solaris.c rename to src/modules/module-solaris.c index f85e71dfb..e0745fc0d 100644 --- a/polyp/module-solaris.c +++ b/src/modules/module-solaris.c @@ -40,16 +40,18 @@ #include #include -#include "iochannel.h" -#include "sink.h" -#include "source.h" -#include "module.h" -#include "sample-util.h" -#include "util.h" -#include "modargs.h" -#include "xmalloc.h" -#include "log.h" -#include "mainloop-signal.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-solaris-symdef.h" PA_MODULE_AUTHOR("Pierre Ossman") diff --git a/polyp/module-tunnel.c b/src/modules/module-tunnel.c similarity index 97% rename from polyp/module-tunnel.c rename to src/modules/module-tunnel.c index c088dae0b..5ee10fda9 100644 --- a/polyp/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -31,20 +31,20 @@ #include #include -#include "module.h" -#include "util.h" -#include "modargs.h" -#include "log.h" -#include "subscribe.h" -#include "xmalloc.h" -#include "sink-input.h" -#include "pdispatch.h" -#include "pstream.h" -#include "pstream-util.h" -#include "authkey.h" -#include "socket-client.h" -#include "socket-util.h" -#include "authkey-prop.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef TUNNEL_SINK #include "module-tunnel-sink-symdef.h" diff --git a/polyp/module-waveout.c b/src/modules/module-waveout.c similarity index 98% rename from polyp/module-waveout.c rename to src/modules/module-waveout.c index e9d9f12e3..8809c31d3 100644 --- a/polyp/module-waveout.c +++ b/src/modules/module-waveout.c @@ -27,15 +27,17 @@ #include #include -#include "sink.h" -#include "source.h" -#include "module.h" -#include "mainloop-api.h" -#include "modargs.h" -#include "sample-util.h" -#include "util.h" -#include "log.h" -#include "xmalloc.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-waveout-symdef.h" PA_MODULE_AUTHOR("Pierre Ossman") diff --git a/polyp/module-x11-bell.c b/src/modules/module-x11-bell.c similarity index 94% rename from polyp/module-x11-bell.c rename to src/modules/module-x11-bell.c index 4fc4a60d4..d722b732f 100644 --- a/polyp/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -31,14 +31,15 @@ #include #include -#include "module.h" -#include "sink.h" -#include "scache.h" -#include "modargs.h" -#include "xmalloc.h" -#include "namereg.h" -#include "log.h" -#include "x11wrap.h" +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-x11-bell-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/polyp/module-x11-publish.c b/src/modules/module-x11-publish.c similarity index 91% rename from polyp/module-x11-publish.c rename to src/modules/module-x11-publish.c index 0116914f2..dca5d049e 100644 --- a/polyp/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -32,22 +32,23 @@ #include #include -#include "module.h" -#include "sink.h" -#include "scache.h" -#include "modargs.h" -#include "xmalloc.h" -#include "namereg.h" -#include "log.h" -#include "x11wrap.h" -#include "util.h" -#include "native-common.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-x11-publish-symdef.h" -#include "authkey-prop.h" -#include "authkey.h" -#include "x11prop.h" -#include "strlist.h" -#include "props.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("X11 Credential Publisher") diff --git a/polyp/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c similarity index 97% rename from polyp/module-zeroconf-publish.c rename to src/modules/module-zeroconf-publish.c index 7e0a2764d..45d566aee 100644 --- a/polyp/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -29,19 +29,20 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "module-zeroconf-publish-symdef.h" -#include "howl-wrap.h" -#include "xmalloc.h" -#include "autoload.h" -#include "sink.h" -#include "source.h" -#include "native-common.h" -#include "util.h" -#include "log.h" -#include "subscribe.h" -#include "dynarray.h" -#include "endianmacros.h" -#include "modargs.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher") diff --git a/polyp/cdecl.h b/src/polyp/cdecl.h similarity index 100% rename from polyp/cdecl.h rename to src/polyp/cdecl.h diff --git a/polyp/channelmap.c b/src/polyp/channelmap.c similarity index 100% rename from polyp/channelmap.c rename to src/polyp/channelmap.c diff --git a/polyp/channelmap.h b/src/polyp/channelmap.h similarity index 100% rename from polyp/channelmap.h rename to src/polyp/channelmap.h diff --git a/polyp/client-conf-x11.c b/src/polyp/client-conf-x11.c similarity index 95% rename from polyp/client-conf-x11.c rename to src/polyp/client-conf-x11.c index 4fd757440..83d0bd2e4 100644 --- a/polyp/client-conf-x11.c +++ b/src/polyp/client-conf-x11.c @@ -30,10 +30,10 @@ #include #include "client-conf-x11.h" -#include "x11prop.h" -#include "log.h" -#include "xmalloc.h" -#include "util.h" +#include +#include +#include +#include int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { Display *d = NULL; diff --git a/polyp/client-conf-x11.h b/src/polyp/client-conf-x11.h similarity index 97% rename from polyp/client-conf-x11.h rename to src/polyp/client-conf-x11.h index 64459224f..80841171b 100644 --- a/polyp/client-conf-x11.h +++ b/src/polyp/client-conf-x11.h @@ -22,7 +22,7 @@ USA. ***/ -#include "client-conf.h" +#include /* Load client configuration data from the specified X11 display, * overwriting the current settings in *c */ diff --git a/polyp/client-conf.c b/src/polyp/client-conf.c similarity index 96% rename from polyp/client-conf.c rename to src/polyp/client-conf.c index bcd4275d7..2df201cee 100644 --- a/polyp/client-conf.c +++ b/src/polyp/client-conf.c @@ -29,12 +29,13 @@ #include #include -#include "client-conf.h" -#include "xmalloc.h" -#include "log.h" -#include "conf-parser.h" -#include "util.h" -#include "authkey.h" +#include +#include +#include +#include +#include + +#include #ifndef DEFAULT_CONFIG_DIR # ifndef OS_IS_WIN32 diff --git a/polyp/client-conf.h b/src/polyp/client-conf.h similarity index 97% rename from polyp/client-conf.h rename to src/polyp/client-conf.h index 7ca2f2335..2d8a019f4 100644 --- a/polyp/client-conf.h +++ b/src/polyp/client-conf.h @@ -22,7 +22,7 @@ USA. ***/ -#include "native-common.h" +#include "../polypcore/native-common.h" /* A structure containing configuration data for polypaudio clients. */ diff --git a/polyp/glib-mainloop.c b/src/polyp/glib-mainloop.c similarity index 99% rename from polyp/glib-mainloop.c rename to src/polyp/glib-mainloop.c index 6f7c1dc54..962eb5742 100644 --- a/polyp/glib-mainloop.c +++ b/src/polyp/glib-mainloop.c @@ -25,11 +25,11 @@ #include -#include "glib-mainloop.h" -#include "idxset.h" -#include "xmalloc.h" +#include +#include +#include #include "glib.h" -#include "util.h" +#include struct pa_io_event { pa_glib_mainloop *mainloop; diff --git a/polyp/glib-mainloop.h b/src/polyp/glib-mainloop.h similarity index 96% rename from polyp/glib-mainloop.h rename to src/polyp/glib-mainloop.h index d3e985970..b4815ed92 100644 --- a/polyp/glib-mainloop.h +++ b/src/polyp/glib-mainloop.h @@ -24,8 +24,8 @@ #include -#include "mainloop-api.h" -#include "cdecl.h" +#include +#include /** \file * GLIB main loop support */ diff --git a/polyp/glib12-mainloop.c b/src/polyp/glib12-mainloop.c similarity index 99% rename from polyp/glib12-mainloop.c rename to src/polyp/glib12-mainloop.c index 8bc4483bb..80a02b1c2 100644 --- a/polyp/glib12-mainloop.c +++ b/src/polyp/glib12-mainloop.c @@ -25,10 +25,10 @@ #include -#include "glib-mainloop.h" -#include "idxset.h" -#include "xmalloc.h" -#include "util.h" +#include +#include +#include +#include /* A mainloop implementation based on GLIB 1.2 */ diff --git a/polyp/mainloop-api.c b/src/polyp/mainloop-api.c similarity index 96% rename from polyp/mainloop-api.c rename to src/polyp/mainloop-api.c index 3229ec20b..a3eaee9c6 100644 --- a/polyp/mainloop-api.c +++ b/src/polyp/mainloop-api.c @@ -27,8 +27,8 @@ #include #include "mainloop-api.h" -#include "xmalloc.h" -#include "gccmacro.h" +#include +#include struct once_info { void (*callback)(pa_mainloop_api*m, void *userdata); diff --git a/polyp/mainloop-api.h b/src/polyp/mainloop-api.h similarity index 100% rename from polyp/mainloop-api.h rename to src/polyp/mainloop-api.h diff --git a/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c similarity index 97% rename from polyp/mainloop-signal.c rename to src/polyp/mainloop-signal.c index 769360311..a03c91596 100644 --- a/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -36,11 +36,11 @@ #include #endif -#include "mainloop-signal.h" -#include "util.h" -#include "xmalloc.h" -#include "log.h" -#include "gccmacro.h" +#include +#include +#include +#include +#include struct pa_signal_event { int sig; diff --git a/polyp/mainloop-signal.h b/src/polyp/mainloop-signal.h similarity index 97% rename from polyp/mainloop-signal.h rename to src/polyp/mainloop-signal.h index 6ce313702..76065b222 100644 --- a/polyp/mainloop-signal.h +++ b/src/polyp/mainloop-signal.h @@ -22,8 +22,8 @@ USA. ***/ -#include "mainloop-api.h" -#include "cdecl.h" +#include +#include PA_C_DECL_BEGIN diff --git a/polyp/mainloop.c b/src/polyp/mainloop.c similarity index 99% rename from polyp/mainloop.c rename to src/polyp/mainloop.c index d25af78a5..3fa9245ca 100644 --- a/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -38,13 +38,13 @@ #include "poll.h" #endif -#include "winsock.h" +#include #include "mainloop.h" -#include "util.h" -#include "idxset.h" -#include "xmalloc.h" -#include "log.h" +#include +#include +#include +#include struct pa_io_event { pa_mainloop *mainloop; diff --git a/polyp/mainloop.h b/src/polyp/mainloop.h similarity index 98% rename from polyp/mainloop.h rename to src/polyp/mainloop.h index 921a07093..691f8c50c 100644 --- a/polyp/mainloop.h +++ b/src/polyp/mainloop.h @@ -22,8 +22,8 @@ USA. ***/ -#include "mainloop-api.h" -#include "cdecl.h" +#include +#include PA_C_DECL_BEGIN diff --git a/polyp/polyplib-browser.c b/src/polyp/polyplib-browser.c similarity index 99% rename from polyp/polyplib-browser.c rename to src/polyp/polyplib-browser.c index 6fee84a4a..9a3894842 100644 --- a/polyp/polyplib-browser.c +++ b/src/polyp/polyplib-browser.c @@ -23,9 +23,9 @@ #include #include "polyplib-browser.h" -#include "xmalloc.h" -#include "log.h" -#include "util.h" +#include +#include +#include #define SERVICE_NAME_SINK "_polypaudio-sink._tcp." #define SERVICE_NAME_SOURCE "_polypaudio-source._tcp." diff --git a/polyp/polyplib-browser.h b/src/polyp/polyplib-browser.h similarity index 100% rename from polyp/polyplib-browser.h rename to src/polyp/polyplib-browser.h diff --git a/polyp/polyplib-context.c b/src/polyp/polyplib-context.c similarity index 98% rename from polyp/polyplib-context.c rename to src/polyp/polyplib-context.c index 15f2e4cd7..c392f0fcf 100644 --- a/polyp/polyplib-context.c +++ b/src/polyp/polyplib-context.c @@ -45,22 +45,22 @@ #include #endif -#include "winsock.h" +#include #include "polyplib-internal.h" #include "polyplib-context.h" #include "polyplib-version.h" -#include "native-common.h" -#include "pdispatch.h" -#include "pstream.h" -#include "dynarray.h" -#include "socket-client.h" -#include "pstream-util.h" -#include "util.h" -#include "xmalloc.h" -#include "log.h" -#include "client-conf.h" -#include "socket-util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef HAVE_X11 #include "client-conf-x11.h" diff --git a/polyp/polyplib-context.h b/src/polyp/polyplib-context.h similarity index 100% rename from polyp/polyplib-context.h rename to src/polyp/polyplib-context.h diff --git a/polyp/polyplib-def.h b/src/polyp/polyplib-def.h similarity index 100% rename from polyp/polyplib-def.h rename to src/polyp/polyplib-def.h diff --git a/polyp/polyplib-error.c b/src/polyp/polyplib-error.c similarity index 97% rename from polyp/polyplib-error.c rename to src/polyp/polyplib-error.c index 50a672709..188d6a93d 100644 --- a/polyp/polyplib-error.c +++ b/src/polyp/polyplib-error.c @@ -27,7 +27,7 @@ #include #include "polyplib-error.h" -#include "native-common.h" +#include static const char* const errortab[PA_ERROR_MAX] = { [PA_ERROR_OK] = "OK", diff --git a/polyp/polyplib-error.h b/src/polyp/polyplib-error.h similarity index 97% rename from polyp/polyplib-error.h rename to src/polyp/polyplib-error.h index dbbbf0067..1bb978224 100644 --- a/polyp/polyplib-error.h +++ b/src/polyp/polyplib-error.h @@ -23,7 +23,7 @@ ***/ #include -#include "cdecl.h" +#include /** \file * Error management */ diff --git a/polyp/polyplib-internal.h b/src/polyp/polyplib-internal.h similarity index 93% rename from polyp/polyplib-internal.h rename to src/polyp/polyplib-internal.h index 295960695..b95a20f3a 100644 --- a/polyp/polyplib-internal.h +++ b/src/polyp/polyplib-internal.h @@ -22,20 +22,20 @@ USA. ***/ -#include "mainloop-api.h" -#include "socket-client.h" -#include "pstream.h" -#include "pdispatch.h" -#include "dynarray.h" +#include +#include +#include +#include +#include #include "polyplib-context.h" #include "polyplib-stream.h" #include "polyplib-operation.h" -#include "llist.h" -#include "native-common.h" -#include "client-conf.h" -#include "strlist.h" -#include "mcalign.h" +#include +#include +#include +#include +#include #define DEFAULT_TIMEOUT (10) diff --git a/polyp/polyplib-introspect.c b/src/polyp/polyplib-introspect.c similarity index 99% rename from polyp/polyplib-introspect.c rename to src/polyp/polyplib-introspect.c index 49298a967..0bdffa35f 100644 --- a/polyp/polyplib-introspect.c +++ b/src/polyp/polyplib-introspect.c @@ -28,8 +28,8 @@ #include "polyplib-introspect.h" #include "polyplib-context.h" #include "polyplib-internal.h" -#include "pstream-util.h" -#include "gccmacro.h" +#include +#include /*** Statistics ***/ diff --git a/polyp/polyplib-introspect.h b/src/polyp/polyplib-introspect.h similarity index 100% rename from polyp/polyplib-introspect.h rename to src/polyp/polyplib-introspect.h diff --git a/polyp/polyplib-operation.c b/src/polyp/polyplib-operation.c similarity index 98% rename from polyp/polyplib-operation.c rename to src/polyp/polyplib-operation.c index 68bc8c6a1..ea336c173 100644 --- a/polyp/polyplib-operation.c +++ b/src/polyp/polyplib-operation.c @@ -25,7 +25,7 @@ #include -#include "xmalloc.h" +#include #include "polyplib-internal.h" #include "polyplib-operation.h" diff --git a/polyp/polyplib-operation.h b/src/polyp/polyplib-operation.h similarity index 100% rename from polyp/polyplib-operation.h rename to src/polyp/polyplib-operation.h diff --git a/polyp/polyplib-scache.c b/src/polyp/polyplib-scache.c similarity index 99% rename from polyp/polyplib-scache.c rename to src/polyp/polyplib-scache.c index 01c648282..1315af970 100644 --- a/polyp/polyplib-scache.c +++ b/src/polyp/polyplib-scache.c @@ -30,7 +30,7 @@ #include "polyplib-scache.h" #include "polyplib-internal.h" -#include "pstream-util.h" +#include void pa_stream_connect_upload(pa_stream *s, size_t length) { pa_tagstruct *t; diff --git a/polyp/polyplib-scache.h b/src/polyp/polyplib-scache.h similarity index 100% rename from polyp/polyplib-scache.h rename to src/polyp/polyplib-scache.h diff --git a/polyp/polyplib-simple.c b/src/polyp/polyplib-simple.c similarity index 98% rename from polyp/polyplib-simple.c rename to src/polyp/polyplib-simple.c index e55121529..7436f0074 100644 --- a/polyp/polyplib-simple.c +++ b/src/polyp/polyplib-simple.c @@ -31,9 +31,9 @@ #include "polyplib-simple.h" #include "polyplib.h" #include "mainloop.h" -#include "native-common.h" -#include "xmalloc.h" -#include "log.h" +#include +#include +#include struct pa_simple { pa_mainloop *mainloop; diff --git a/polyp/polyplib-simple.h b/src/polyp/polyplib-simple.h similarity index 99% rename from polyp/polyplib-simple.h rename to src/polyp/polyplib-simple.h index 0c80f460e..b01f30d5d 100644 --- a/polyp/polyplib-simple.h +++ b/src/polyp/polyplib-simple.h @@ -26,7 +26,7 @@ #include "sample.h" #include "polyplib-def.h" -#include "cdecl.h" +#include /** \file * A simple but limited synchronous playback and recording diff --git a/polyp/polyplib-stream.c b/src/polyp/polyplib-stream.c similarity index 99% rename from polyp/polyplib-stream.c rename to src/polyp/polyplib-stream.c index 7b9d6863d..63c9245b0 100644 --- a/polyp/polyplib-stream.c +++ b/src/polyp/polyplib-stream.c @@ -29,10 +29,10 @@ #include #include "polyplib-internal.h" -#include "xmalloc.h" -#include "pstream-util.h" -#include "util.h" -#include "log.h" +#include +#include +#include +#include #define LATENCY_IPOL_INTERVAL_USEC (10000L) diff --git a/polyp/polyplib-stream.h b/src/polyp/polyplib-stream.h similarity index 100% rename from polyp/polyplib-stream.h rename to src/polyp/polyplib-stream.h diff --git a/polyp/polyplib-subscribe.c b/src/polyp/polyplib-subscribe.c similarity index 97% rename from polyp/polyplib-subscribe.c rename to src/polyp/polyplib-subscribe.c index ef90ab0b6..13fcfb420 100644 --- a/polyp/polyplib-subscribe.c +++ b/src/polyp/polyplib-subscribe.c @@ -28,8 +28,8 @@ #include "polyplib-subscribe.h" #include "polyplib-internal.h" -#include "pstream-util.h" -#include "gccmacro.h" +#include +#include void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; diff --git a/polyp/polyplib-subscribe.h b/src/polyp/polyplib-subscribe.h similarity index 100% rename from polyp/polyplib-subscribe.h rename to src/polyp/polyplib-subscribe.h diff --git a/polyp/polyplib-version.h.in b/src/polyp/polyplib-version.h.in similarity index 100% rename from polyp/polyplib-version.h.in rename to src/polyp/polyplib-version.h.in diff --git a/polyp/polyplib.h b/src/polyp/polyplib.h similarity index 100% rename from polyp/polyplib.h rename to src/polyp/polyplib.h diff --git a/polyp/sample.c b/src/polyp/sample.c similarity index 100% rename from polyp/sample.c rename to src/polyp/sample.c diff --git a/polyp/sample.h b/src/polyp/sample.h similarity index 100% rename from polyp/sample.h rename to src/polyp/sample.h diff --git a/polyp/volume.c b/src/polyp/volume.c similarity index 100% rename from polyp/volume.c rename to src/polyp/volume.c diff --git a/polyp/volume.h b/src/polyp/volume.h similarity index 100% rename from polyp/volume.h rename to src/polyp/volume.h diff --git a/polyp/alsa-util.c b/src/polypcore/alsa-util.c similarity index 99% rename from polyp/alsa-util.c rename to src/polypcore/alsa-util.c index cc65b8de8..7528ee0b5 100644 --- a/polyp/alsa-util.c +++ b/src/polypcore/alsa-util.c @@ -27,7 +27,7 @@ #include #include "alsa-util.h" -#include "sample.h" +#include #include "xmalloc.h" #include "log.h" diff --git a/polyp/alsa-util.h b/src/polypcore/alsa-util.h similarity index 95% rename from polyp/alsa-util.h rename to src/polypcore/alsa-util.h index d180db3ec..5d6d66348 100644 --- a/polyp/alsa-util.h +++ b/src/polypcore/alsa-util.h @@ -24,8 +24,8 @@ #include -#include "sample.h" -#include "mainloop-api.h" +#include +#include int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); diff --git a/polyp/authkey-prop.c b/src/polypcore/authkey-prop.c similarity index 100% rename from polyp/authkey-prop.c rename to src/polypcore/authkey-prop.c diff --git a/polyp/authkey-prop.h b/src/polypcore/authkey-prop.h similarity index 100% rename from polyp/authkey-prop.h rename to src/polypcore/authkey-prop.h diff --git a/polyp/authkey.c b/src/polypcore/authkey.c similarity index 100% rename from polyp/authkey.c rename to src/polypcore/authkey.c diff --git a/polyp/authkey.h b/src/polypcore/authkey.h similarity index 100% rename from polyp/authkey.h rename to src/polypcore/authkey.h diff --git a/polyp/autoload.c b/src/polypcore/autoload.c similarity index 100% rename from polyp/autoload.c rename to src/polypcore/autoload.c diff --git a/polyp/autoload.h b/src/polypcore/autoload.h similarity index 100% rename from polyp/autoload.h rename to src/polypcore/autoload.h diff --git a/polyp/cli-command.c b/src/polypcore/cli-command.c similarity index 100% rename from polyp/cli-command.c rename to src/polypcore/cli-command.c diff --git a/polyp/cli-command.h b/src/polypcore/cli-command.h similarity index 100% rename from polyp/cli-command.h rename to src/polypcore/cli-command.h diff --git a/polyp/cli-text.c b/src/polypcore/cli-text.c similarity index 99% rename from polyp/cli-text.c rename to src/polypcore/cli-text.c index 328aca4cf..58248d8ec 100644 --- a/polyp/cli-text.c +++ b/src/polypcore/cli-text.c @@ -38,7 +38,7 @@ #include "scache.h" #include "autoload.h" #include "xmalloc.h" -#include "volume.h" +#include char *pa_module_list_to_string(pa_core *c) { pa_strbuf *s; diff --git a/polyp/cli-text.h b/src/polypcore/cli-text.h similarity index 100% rename from polyp/cli-text.h rename to src/polypcore/cli-text.h diff --git a/polyp/cli.c b/src/polypcore/cli.c similarity index 100% rename from polyp/cli.c rename to src/polypcore/cli.c diff --git a/polyp/cli.h b/src/polypcore/cli.h similarity index 100% rename from polyp/cli.h rename to src/polypcore/cli.h diff --git a/polyp/client.c b/src/polypcore/client.c similarity index 100% rename from polyp/client.c rename to src/polypcore/client.c diff --git a/polyp/client.h b/src/polypcore/client.h similarity index 100% rename from polyp/client.h rename to src/polypcore/client.h diff --git a/polyp/conf-parser.c b/src/polypcore/conf-parser.c similarity index 100% rename from polyp/conf-parser.c rename to src/polypcore/conf-parser.c diff --git a/polyp/conf-parser.h b/src/polypcore/conf-parser.h similarity index 100% rename from polyp/conf-parser.h rename to src/polypcore/conf-parser.h diff --git a/polyp/core.c b/src/polypcore/core.c similarity index 100% rename from polyp/core.c rename to src/polypcore/core.c diff --git a/polyp/core.h b/src/polypcore/core.h similarity index 97% rename from polyp/core.h rename to src/polypcore/core.h index 9241fcd8f..f7a90169a 100644 --- a/polyp/core.h +++ b/src/polypcore/core.h @@ -26,8 +26,8 @@ typedef struct pa_core pa_core; #include "idxset.h" #include "hashmap.h" -#include "mainloop-api.h" -#include "sample.h" +#include +#include #include "memblock.h" #include "resampler.h" #include "queue.h" diff --git a/polyp/dllmain.c b/src/polypcore/dllmain.c similarity index 100% rename from polyp/dllmain.c rename to src/polypcore/dllmain.c diff --git a/polyp/dynarray.c b/src/polypcore/dynarray.c similarity index 100% rename from polyp/dynarray.c rename to src/polypcore/dynarray.c diff --git a/polyp/dynarray.h b/src/polypcore/dynarray.h similarity index 100% rename from polyp/dynarray.h rename to src/polypcore/dynarray.h diff --git a/polyp/endianmacros.h b/src/polypcore/endianmacros.h similarity index 100% rename from polyp/endianmacros.h rename to src/polypcore/endianmacros.h diff --git a/polyp/esound.h b/src/polypcore/esound.h similarity index 100% rename from polyp/esound.h rename to src/polypcore/esound.h diff --git a/polyp/g711.c b/src/polypcore/g711.c similarity index 100% rename from polyp/g711.c rename to src/polypcore/g711.c diff --git a/polyp/g711.h b/src/polypcore/g711.h similarity index 100% rename from polyp/g711.h rename to src/polypcore/g711.h diff --git a/polyp/gccmacro.h b/src/polypcore/gccmacro.h similarity index 100% rename from polyp/gccmacro.h rename to src/polypcore/gccmacro.h diff --git a/polyp/hashmap.c b/src/polypcore/hashmap.c similarity index 100% rename from polyp/hashmap.c rename to src/polypcore/hashmap.c diff --git a/polyp/hashmap.h b/src/polypcore/hashmap.h similarity index 100% rename from polyp/hashmap.h rename to src/polypcore/hashmap.h diff --git a/polyp/howl-wrap.c b/src/polypcore/howl-wrap.c similarity index 100% rename from polyp/howl-wrap.c rename to src/polypcore/howl-wrap.c diff --git a/polyp/howl-wrap.h b/src/polypcore/howl-wrap.h similarity index 100% rename from polyp/howl-wrap.h rename to src/polypcore/howl-wrap.h diff --git a/polyp/idxset.c b/src/polypcore/idxset.c similarity index 100% rename from polyp/idxset.c rename to src/polypcore/idxset.c diff --git a/polyp/idxset.h b/src/polypcore/idxset.h similarity index 100% rename from polyp/idxset.h rename to src/polypcore/idxset.h diff --git a/polyp/inet_ntop.c b/src/polypcore/inet_ntop.c similarity index 100% rename from polyp/inet_ntop.c rename to src/polypcore/inet_ntop.c diff --git a/polyp/inet_ntop.h b/src/polypcore/inet_ntop.h similarity index 100% rename from polyp/inet_ntop.h rename to src/polypcore/inet_ntop.h diff --git a/polyp/iochannel.c b/src/polypcore/iochannel.c similarity index 100% rename from polyp/iochannel.c rename to src/polypcore/iochannel.c diff --git a/polyp/iochannel.h b/src/polypcore/iochannel.h similarity index 98% rename from polyp/iochannel.h rename to src/polypcore/iochannel.h index e2b8bccf0..7d355d8f0 100644 --- a/polyp/iochannel.h +++ b/src/polypcore/iochannel.h @@ -23,7 +23,7 @@ ***/ #include -#include "mainloop-api.h" +#include /* A wrapper around UNIX file descriptors for attaching them to the a main event loop. Everytime new data may be read or be written to diff --git a/polyp/ioline.c b/src/polypcore/ioline.c similarity index 100% rename from polyp/ioline.c rename to src/polypcore/ioline.c diff --git a/polyp/ioline.h b/src/polypcore/ioline.h similarity index 100% rename from polyp/ioline.h rename to src/polypcore/ioline.h diff --git a/polyp/llist.h b/src/polypcore/llist.h similarity index 100% rename from polyp/llist.h rename to src/polypcore/llist.h diff --git a/polyp/log.c b/src/polypcore/log.c similarity index 100% rename from polyp/log.c rename to src/polypcore/log.c diff --git a/polyp/log.h b/src/polypcore/log.h similarity index 100% rename from polyp/log.h rename to src/polypcore/log.h diff --git a/polyp/mcalign.c b/src/polypcore/mcalign.c similarity index 100% rename from polyp/mcalign.c rename to src/polypcore/mcalign.c diff --git a/polyp/mcalign.h b/src/polypcore/mcalign.h similarity index 100% rename from polyp/mcalign.h rename to src/polypcore/mcalign.h diff --git a/polyp/memblock.c b/src/polypcore/memblock.c similarity index 100% rename from polyp/memblock.c rename to src/polypcore/memblock.c diff --git a/polyp/memblock.h b/src/polypcore/memblock.h similarity index 100% rename from polyp/memblock.h rename to src/polypcore/memblock.h diff --git a/polyp/memblockq.c b/src/polypcore/memblockq.c similarity index 100% rename from polyp/memblockq.c rename to src/polypcore/memblockq.c diff --git a/polyp/memblockq.h b/src/polypcore/memblockq.h similarity index 100% rename from polyp/memblockq.h rename to src/polypcore/memblockq.h diff --git a/polyp/memchunk.c b/src/polypcore/memchunk.c similarity index 100% rename from polyp/memchunk.c rename to src/polypcore/memchunk.c diff --git a/polyp/memchunk.h b/src/polypcore/memchunk.h similarity index 100% rename from polyp/memchunk.h rename to src/polypcore/memchunk.h diff --git a/polyp/modargs.c b/src/polypcore/modargs.c similarity index 100% rename from polyp/modargs.c rename to src/polypcore/modargs.c diff --git a/polyp/modargs.h b/src/polypcore/modargs.h similarity index 98% rename from polyp/modargs.h rename to src/polypcore/modargs.h index 566053795..678ea1a74 100644 --- a/polyp/modargs.h +++ b/src/polypcore/modargs.h @@ -23,7 +23,7 @@ ***/ #include -#include "sample.h" +#include #include "core.h" typedef struct pa_modargs pa_modargs; diff --git a/polyp/modinfo.c b/src/polypcore/modinfo.c similarity index 100% rename from polyp/modinfo.c rename to src/polypcore/modinfo.c diff --git a/polyp/modinfo.h b/src/polypcore/modinfo.h similarity index 100% rename from polyp/modinfo.h rename to src/polypcore/modinfo.h diff --git a/polyp/module.c b/src/polypcore/module.c similarity index 100% rename from polyp/module.c rename to src/polypcore/module.c diff --git a/polyp/module.h b/src/polypcore/module.h similarity index 100% rename from polyp/module.h rename to src/polypcore/module.h diff --git a/polyp/namereg.c b/src/polypcore/namereg.c similarity index 100% rename from polyp/namereg.c rename to src/polypcore/namereg.c diff --git a/polyp/namereg.h b/src/polypcore/namereg.h similarity index 100% rename from polyp/namereg.h rename to src/polypcore/namereg.h diff --git a/polyp/native-common.h b/src/polypcore/native-common.h similarity index 98% rename from polyp/native-common.h rename to src/polypcore/native-common.h index 569f3b71a..78ae721ef 100644 --- a/polyp/native-common.h +++ b/src/polypcore/native-common.h @@ -22,8 +22,8 @@ USA. ***/ -#include "cdecl.h" -#include "polyplib-def.h" +#include +#include PA_C_DECL_BEGIN diff --git a/polyp/oss-util.c b/src/polypcore/oss-util.c similarity index 100% rename from polyp/oss-util.c rename to src/polypcore/oss-util.c diff --git a/polyp/oss-util.h b/src/polypcore/oss-util.h similarity index 97% rename from polyp/oss-util.h rename to src/polypcore/oss-util.h index 3ee51cc58..6b2746ccd 100644 --- a/polyp/oss-util.h +++ b/src/polypcore/oss-util.h @@ -22,7 +22,7 @@ USA. ***/ -#include "sample.h" +#include int pa_oss_open(const char *device, int *mode, int* pcaps); int pa_oss_auto_format(int fd, pa_sample_spec *ss); diff --git a/polyp/packet.c b/src/polypcore/packet.c similarity index 100% rename from polyp/packet.c rename to src/polypcore/packet.c diff --git a/polyp/packet.h b/src/polypcore/packet.h similarity index 100% rename from polyp/packet.h rename to src/polypcore/packet.h diff --git a/polyp/parseaddr.c b/src/polypcore/parseaddr.c similarity index 100% rename from polyp/parseaddr.c rename to src/polypcore/parseaddr.c diff --git a/polyp/parseaddr.h b/src/polypcore/parseaddr.h similarity index 100% rename from polyp/parseaddr.h rename to src/polypcore/parseaddr.h diff --git a/polyp/pdispatch.c b/src/polypcore/pdispatch.c similarity index 100% rename from polyp/pdispatch.c rename to src/polypcore/pdispatch.c diff --git a/polyp/pdispatch.h b/src/polypcore/pdispatch.h similarity index 98% rename from polyp/pdispatch.h rename to src/polypcore/pdispatch.h index 40f5d4c42..fdd4d7f54 100644 --- a/polyp/pdispatch.h +++ b/src/polypcore/pdispatch.h @@ -25,7 +25,7 @@ #include #include "tagstruct.h" #include "packet.h" -#include "mainloop-api.h" +#include typedef struct pa_pdispatch pa_pdispatch; diff --git a/polyp/pid.c b/src/polypcore/pid.c similarity index 100% rename from polyp/pid.c rename to src/polypcore/pid.c diff --git a/polyp/pid.h b/src/polypcore/pid.h similarity index 100% rename from polyp/pid.h rename to src/polypcore/pid.h diff --git a/polyp/play-memchunk.c b/src/polypcore/play-memchunk.c similarity index 100% rename from polyp/play-memchunk.c rename to src/polypcore/play-memchunk.c diff --git a/polyp/play-memchunk.h b/src/polypcore/play-memchunk.h similarity index 100% rename from polyp/play-memchunk.h rename to src/polypcore/play-memchunk.h diff --git a/polyp/poll.c b/src/polypcore/poll.c similarity index 100% rename from polyp/poll.c rename to src/polypcore/poll.c diff --git a/polyp/poll.h b/src/polypcore/poll.h similarity index 100% rename from polyp/poll.h rename to src/polypcore/poll.h diff --git a/polyp/props.c b/src/polypcore/props.c similarity index 100% rename from polyp/props.c rename to src/polypcore/props.c diff --git a/polyp/props.h b/src/polypcore/props.h similarity index 100% rename from polyp/props.h rename to src/polypcore/props.h diff --git a/polyp/protocol-cli.c b/src/polypcore/protocol-cli.c similarity index 100% rename from polyp/protocol-cli.c rename to src/polypcore/protocol-cli.c diff --git a/polyp/protocol-cli.h b/src/polypcore/protocol-cli.h similarity index 100% rename from polyp/protocol-cli.h rename to src/polypcore/protocol-cli.h diff --git a/polyp/protocol-esound.c b/src/polypcore/protocol-esound.c similarity index 99% rename from polyp/protocol-esound.c rename to src/polypcore/protocol-esound.c index 6f004e168..14f237c75 100644 --- a/polyp/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -38,7 +38,7 @@ #include "sink.h" #include "source-output.h" #include "source.h" -#include "sample.h" +#include #include "scache.h" #include "sample-util.h" #include "authkey.h" diff --git a/polyp/protocol-esound.h b/src/polypcore/protocol-esound.h similarity index 100% rename from polyp/protocol-esound.h rename to src/polypcore/protocol-esound.h diff --git a/polyp/protocol-http.c b/src/polypcore/protocol-http.c similarity index 100% rename from polyp/protocol-http.c rename to src/polypcore/protocol-http.c diff --git a/polyp/protocol-http.h b/src/polypcore/protocol-http.h similarity index 100% rename from polyp/protocol-http.h rename to src/polypcore/protocol-http.h diff --git a/polyp/protocol-native.c b/src/polypcore/protocol-native.c similarity index 100% rename from polyp/protocol-native.c rename to src/polypcore/protocol-native.c diff --git a/polyp/protocol-native.h b/src/polypcore/protocol-native.h similarity index 100% rename from polyp/protocol-native.h rename to src/polypcore/protocol-native.h diff --git a/polyp/protocol-simple.c b/src/polypcore/protocol-simple.c similarity index 100% rename from polyp/protocol-simple.c rename to src/polypcore/protocol-simple.c diff --git a/polyp/protocol-simple.h b/src/polypcore/protocol-simple.h similarity index 100% rename from polyp/protocol-simple.h rename to src/polypcore/protocol-simple.h diff --git a/polyp/pstream-util.c b/src/polypcore/pstream-util.c similarity index 100% rename from polyp/pstream-util.c rename to src/polypcore/pstream-util.c diff --git a/polyp/pstream-util.h b/src/polypcore/pstream-util.h similarity index 100% rename from polyp/pstream-util.h rename to src/polypcore/pstream-util.h diff --git a/polyp/pstream.c b/src/polypcore/pstream.c similarity index 100% rename from polyp/pstream.c rename to src/polypcore/pstream.c diff --git a/polyp/pstream.h b/src/polypcore/pstream.h similarity index 98% rename from polyp/pstream.h rename to src/polypcore/pstream.h index 77c92802e..ec63a98e8 100644 --- a/polyp/pstream.h +++ b/src/polypcore/pstream.h @@ -27,7 +27,7 @@ #include "packet.h" #include "memblock.h" #include "iochannel.h" -#include "mainloop-api.h" +#include #include "memchunk.h" typedef struct pa_pstream pa_pstream; diff --git a/polyp/queue.c b/src/polypcore/queue.c similarity index 100% rename from polyp/queue.c rename to src/polypcore/queue.c diff --git a/polyp/queue.h b/src/polypcore/queue.h similarity index 100% rename from polyp/queue.h rename to src/polypcore/queue.h diff --git a/polyp/random.c b/src/polypcore/random.c similarity index 100% rename from polyp/random.c rename to src/polypcore/random.c diff --git a/polyp/random.h b/src/polypcore/random.h similarity index 100% rename from polyp/random.h rename to src/polypcore/random.h diff --git a/polyp/resampler.c b/src/polypcore/resampler.c similarity index 100% rename from polyp/resampler.c rename to src/polypcore/resampler.c diff --git a/polyp/resampler.h b/src/polypcore/resampler.h similarity index 97% rename from polyp/resampler.h rename to src/polypcore/resampler.h index e14942f32..cad48be50 100644 --- a/polyp/resampler.h +++ b/src/polypcore/resampler.h @@ -24,10 +24,10 @@ #include -#include "sample.h" +#include #include "memblock.h" #include "memchunk.h" -#include "channelmap.h" +#include typedef struct pa_resampler pa_resampler; diff --git a/polyp/sample-util.c b/src/polypcore/sample-util.c similarity index 100% rename from polyp/sample-util.c rename to src/polypcore/sample-util.c diff --git a/polyp/sample-util.h b/src/polypcore/sample-util.h similarity index 96% rename from polyp/sample-util.h rename to src/polypcore/sample-util.h index e433f9c81..d0efbcc43 100644 --- a/polyp/sample-util.h +++ b/src/polypcore/sample-util.h @@ -22,10 +22,10 @@ USA. ***/ -#include "sample.h" +#include #include "memblock.h" #include "memchunk.h" -#include "volume.h" +#include pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec); void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec); diff --git a/polyp/scache.c b/src/polypcore/scache.c similarity index 99% rename from polyp/scache.c rename to src/polypcore/scache.c index 39fa26f33..02c7d34fa 100644 --- a/polyp/scache.c +++ b/src/polypcore/scache.c @@ -43,7 +43,7 @@ #include "scache.h" #include "sink-input.h" -#include "mainloop.h" +#include #include "sample-util.h" #include "play-memchunk.h" #include "xmalloc.h" @@ -52,8 +52,8 @@ #include "sound-file.h" #include "util.h" #include "log.h" -#include "channelmap.h" -#include "volume.h" +#include +#include #define UNLOAD_POLL_TIME 2 diff --git a/polyp/scache.h b/src/polypcore/scache.h similarity index 100% rename from polyp/scache.h rename to src/polypcore/scache.h diff --git a/polyp/sconv-s16be.c b/src/polypcore/sconv-s16be.c similarity index 100% rename from polyp/sconv-s16be.c rename to src/polypcore/sconv-s16be.c diff --git a/polyp/sconv-s16be.h b/src/polypcore/sconv-s16be.h similarity index 100% rename from polyp/sconv-s16be.h rename to src/polypcore/sconv-s16be.h diff --git a/polyp/sconv-s16le.c b/src/polypcore/sconv-s16le.c similarity index 100% rename from polyp/sconv-s16le.c rename to src/polypcore/sconv-s16le.c diff --git a/polyp/sconv-s16le.h b/src/polypcore/sconv-s16le.h similarity index 100% rename from polyp/sconv-s16le.h rename to src/polypcore/sconv-s16le.h diff --git a/polyp/sconv.c b/src/polypcore/sconv.c similarity index 100% rename from polyp/sconv.c rename to src/polypcore/sconv.c diff --git a/polyp/sconv.h b/src/polypcore/sconv.h similarity index 97% rename from polyp/sconv.h rename to src/polypcore/sconv.h index 2a0052196..a0c15c24f 100644 --- a/polyp/sconv.h +++ b/src/polypcore/sconv.h @@ -22,7 +22,7 @@ USA. ***/ -#include "sample.h" +#include typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, float *b); typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b); diff --git a/polyp/sink-input.c b/src/polypcore/sink-input.c similarity index 100% rename from polyp/sink-input.c rename to src/polypcore/sink-input.c diff --git a/polyp/sink-input.h b/src/polypcore/sink-input.h similarity index 99% rename from polyp/sink-input.h rename to src/polypcore/sink-input.h index 1db993f5c..a5ad19584 100644 --- a/polyp/sink-input.h +++ b/src/polypcore/sink-input.h @@ -27,7 +27,7 @@ typedef struct pa_sink_input pa_sink_input; #include "sink.h" -#include "sample.h" +#include #include "memblockq.h" #include "resampler.h" #include "module.h" diff --git a/polyp/sink.c b/src/polypcore/sink.c similarity index 99% rename from polyp/sink.c rename to src/polypcore/sink.c index bb6566498..411befe7f 100644 --- a/polyp/sink.c +++ b/src/polypcore/sink.c @@ -36,7 +36,7 @@ #include "xmalloc.h" #include "subscribe.h" #include "log.h" -#include "polyplib-introspect.h" +#include #define MAX_MIX_CHANNELS 32 diff --git a/polyp/sink.h b/src/polypcore/sink.h similarity index 96% rename from polyp/sink.h rename to src/polypcore/sink.h index 33aba2331..268461eff 100644 --- a/polyp/sink.h +++ b/src/polypcore/sink.h @@ -27,12 +27,12 @@ typedef struct pa_sink pa_sink; #include "core.h" -#include "sample.h" +#include #include "idxset.h" #include "source.h" -#include "channelmap.h" +#include #include "module.h" -#include "volume.h" +#include #define PA_MAX_INPUTS_PER_SINK 6 diff --git a/polyp/sioman.c b/src/polypcore/sioman.c similarity index 100% rename from polyp/sioman.c rename to src/polypcore/sioman.c diff --git a/polyp/sioman.h b/src/polypcore/sioman.h similarity index 100% rename from polyp/sioman.h rename to src/polypcore/sioman.h diff --git a/polyp/socket-client.c b/src/polypcore/socket-client.c similarity index 100% rename from polyp/socket-client.c rename to src/polypcore/socket-client.c diff --git a/polyp/socket-client.h b/src/polypcore/socket-client.h similarity index 98% rename from polyp/socket-client.h rename to src/polypcore/socket-client.h index 40e9629a2..624880d7d 100644 --- a/polyp/socket-client.h +++ b/src/polypcore/socket-client.h @@ -24,7 +24,7 @@ #include -#include "mainloop-api.h" +#include #include "iochannel.h" struct sockaddr; diff --git a/polyp/socket-server.c b/src/polypcore/socket-server.c similarity index 100% rename from polyp/socket-server.c rename to src/polypcore/socket-server.c diff --git a/polyp/socket-server.h b/src/polypcore/socket-server.h similarity index 98% rename from polyp/socket-server.h rename to src/polypcore/socket-server.h index 6c5d7bacc..4d8bfad56 100644 --- a/polyp/socket-server.h +++ b/src/polypcore/socket-server.h @@ -23,7 +23,7 @@ ***/ #include -#include "mainloop-api.h" +#include #include "iochannel.h" /* It is safe to destroy the calling socket_server object from the callback */ diff --git a/polyp/socket-util.c b/src/polypcore/socket-util.c similarity index 100% rename from polyp/socket-util.c rename to src/polypcore/socket-util.c diff --git a/polyp/socket-util.h b/src/polypcore/socket-util.h similarity index 100% rename from polyp/socket-util.h rename to src/polypcore/socket-util.h diff --git a/polyp/sound-file-stream.c b/src/polypcore/sound-file-stream.c similarity index 100% rename from polyp/sound-file-stream.c rename to src/polypcore/sound-file-stream.c diff --git a/polyp/sound-file-stream.h b/src/polypcore/sound-file-stream.h similarity index 100% rename from polyp/sound-file-stream.h rename to src/polypcore/sound-file-stream.h diff --git a/polyp/sound-file.c b/src/polypcore/sound-file.c similarity index 99% rename from polyp/sound-file.c rename to src/polypcore/sound-file.c index 0048ed74a..a81c283a0 100644 --- a/polyp/sound-file.c +++ b/src/polypcore/sound-file.c @@ -29,7 +29,7 @@ #include #include "sound-file.h" -#include "sample.h" +#include #include "log.h" #define MAX_FILE_SIZE (1024*1024) diff --git a/polyp/sound-file.h b/src/polypcore/sound-file.h similarity index 97% rename from polyp/sound-file.h rename to src/polypcore/sound-file.h index e0534275a..f3003bb9e 100644 --- a/polyp/sound-file.h +++ b/src/polypcore/sound-file.h @@ -23,7 +23,7 @@ ***/ #include "memchunk.h" -#include "sample.h" +#include int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_memchunk *chunk, pa_memblock_stat *s); diff --git a/polyp/source-output.c b/src/polypcore/source-output.c similarity index 100% rename from polyp/source-output.c rename to src/polypcore/source-output.c diff --git a/polyp/source-output.h b/src/polypcore/source-output.h similarity index 98% rename from polyp/source-output.h rename to src/polypcore/source-output.h index f8e4b1525..4b1cbf152 100644 --- a/polyp/source-output.h +++ b/src/polypcore/source-output.h @@ -27,7 +27,7 @@ typedef struct pa_source_output pa_source_output; #include "source.h" -#include "sample.h" +#include #include "memblockq.h" #include "resampler.h" #include "module.h" diff --git a/polyp/source.c b/src/polypcore/source.c similarity index 100% rename from polyp/source.c rename to src/polypcore/source.c diff --git a/polyp/source.h b/src/polypcore/source.h similarity index 97% rename from polyp/source.h rename to src/polypcore/source.h index 823a9424d..be2fb9856 100644 --- a/polyp/source.h +++ b/src/polypcore/source.h @@ -26,12 +26,12 @@ typedef struct pa_source pa_source; #include #include "core.h" -#include "sample.h" +#include #include "idxset.h" #include "memblock.h" #include "memchunk.h" #include "sink.h" -#include "channelmap.h" +#include #include "module.h" #define PA_MAX_OUTPUTS_PER_SOURCE 16 diff --git a/polyp/strbuf.c b/src/polypcore/strbuf.c similarity index 99% rename from polyp/strbuf.c rename to src/polypcore/strbuf.c index aa20218aa..dcad5e78d 100644 --- a/polyp/strbuf.c +++ b/src/polypcore/strbuf.c @@ -29,7 +29,8 @@ #include #include #include -#include + +#include #include "strbuf.h" diff --git a/polyp/strbuf.h b/src/polypcore/strbuf.h similarity index 100% rename from polyp/strbuf.h rename to src/polypcore/strbuf.h diff --git a/polyp/strlist.c b/src/polypcore/strlist.c similarity index 100% rename from polyp/strlist.c rename to src/polypcore/strlist.c diff --git a/polyp/strlist.h b/src/polypcore/strlist.h similarity index 100% rename from polyp/strlist.h rename to src/polypcore/strlist.h diff --git a/polyp/subscribe.c b/src/polypcore/subscribe.c similarity index 100% rename from polyp/subscribe.c rename to src/polypcore/subscribe.c diff --git a/polyp/subscribe.h b/src/polypcore/subscribe.h similarity index 100% rename from polyp/subscribe.h rename to src/polypcore/subscribe.h diff --git a/polyp/tagstruct.c b/src/polypcore/tagstruct.c similarity index 100% rename from polyp/tagstruct.c rename to src/polypcore/tagstruct.c diff --git a/polyp/tagstruct.h b/src/polypcore/tagstruct.h similarity index 97% rename from polyp/tagstruct.h rename to src/polypcore/tagstruct.h index b41936ffa..59db67b07 100644 --- a/polyp/tagstruct.h +++ b/src/polypcore/tagstruct.h @@ -27,9 +27,9 @@ #include #include -#include "sample.h" -#include "channelmap.h" -#include "volume.h" +#include +#include +#include typedef struct pa_tagstruct pa_tagstruct; diff --git a/polyp/tokenizer.c b/src/polypcore/tokenizer.c similarity index 100% rename from polyp/tokenizer.c rename to src/polypcore/tokenizer.c diff --git a/polyp/tokenizer.h b/src/polypcore/tokenizer.h similarity index 100% rename from polyp/tokenizer.h rename to src/polypcore/tokenizer.h diff --git a/polyp/util.c b/src/polypcore/util.c similarity index 100% rename from polyp/util.c rename to src/polypcore/util.c diff --git a/polyp/util.h b/src/polypcore/util.h similarity index 99% rename from polyp/util.h rename to src/polypcore/util.h index 95e7b99b1..3dc6c945c 100644 --- a/polyp/util.h +++ b/src/polypcore/util.h @@ -28,7 +28,7 @@ #include #include "gccmacro.h" -#include "sample.h" +#include struct timeval; diff --git a/polyp/winsock.h b/src/polypcore/winsock.h similarity index 100% rename from polyp/winsock.h rename to src/polypcore/winsock.h diff --git a/polyp/x11prop.c b/src/polypcore/x11prop.c similarity index 100% rename from polyp/x11prop.c rename to src/polypcore/x11prop.c diff --git a/polyp/x11prop.h b/src/polypcore/x11prop.h similarity index 100% rename from polyp/x11prop.h rename to src/polypcore/x11prop.h diff --git a/polyp/x11wrap.c b/src/polypcore/x11wrap.c similarity index 100% rename from polyp/x11wrap.c rename to src/polypcore/x11wrap.c diff --git a/polyp/x11wrap.h b/src/polypcore/x11wrap.h similarity index 100% rename from polyp/x11wrap.h rename to src/polypcore/x11wrap.h diff --git a/polyp/xmalloc.c b/src/polypcore/xmalloc.c similarity index 100% rename from polyp/xmalloc.c rename to src/polypcore/xmalloc.c diff --git a/polyp/xmalloc.h b/src/polypcore/xmalloc.h similarity index 100% rename from polyp/xmalloc.h rename to src/polypcore/xmalloc.h diff --git a/polyp/cpulimit-test.c b/src/tests/cpulimit-test.c similarity index 93% rename from polyp/cpulimit-test.c rename to src/tests/cpulimit-test.c index 598b2dd24..97a8a0dd9 100644 --- a/polyp/cpulimit-test.c +++ b/src/tests/cpulimit-test.c @@ -29,12 +29,12 @@ #include #include -#include "cpulimit.h" -#include "mainloop.h" -#include "gccmacro.h" +#include "../daemon/cpulimit.h" +#include +#include #ifdef TEST2 -#include "mainloop-signal.h" +#include #endif /* A simple example for testing the cpulimit subsystem */ diff --git a/polyp/mainloop-test.c b/src/tests/mainloop-test.c similarity index 96% rename from polyp/mainloop-test.c rename to src/tests/mainloop-test.c index ee0f8711a..f62c96939 100644 --- a/polyp/mainloop-test.c +++ b/src/tests/mainloop-test.c @@ -28,13 +28,13 @@ #include #include -#include "util.h" -#include "gccmacro.h" +#include +#include #ifdef GLIB_MAIN_LOOP #include -#include "glib-mainloop.h" +#include static GMainLoop* glib_main_loop = NULL; @@ -46,7 +46,7 @@ static GMainLoop* glib_main_loop = NULL; #else /* GLIB_MAIN_LOOP */ -#include "mainloop.h" +#include #endif /* GLIB_MAIN_LOOP */ static pa_defer_event *de; diff --git a/polyp/mcalign-test.c b/src/tests/mcalign-test.c similarity index 96% rename from polyp/mcalign-test.c rename to src/tests/mcalign-test.c index c151d8f29..861c38c1d 100644 --- a/polyp/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -31,9 +31,9 @@ #include #include -#include "util.h" -#include "mcalign.h" -#include "gccmacro.h" +#include +#include +#include /* A simple program for testing pa_mcalign */ diff --git a/polyp/pacat-simple.c b/src/tests/pacat-simple.c similarity index 98% rename from polyp/pacat-simple.c rename to src/tests/pacat-simple.c index 2825fee55..8b3a7b227 100644 --- a/polyp/pacat-simple.c +++ b/src/tests/pacat-simple.c @@ -30,7 +30,7 @@ #include #include -#include "gccmacro.h" +#include #define BUFSIZE 1024 diff --git a/polyp/parec-simple.c b/src/tests/parec-simple.c similarity index 98% rename from polyp/parec-simple.c rename to src/tests/parec-simple.c index 524cc4f16..10eaea8de 100644 --- a/polyp/parec-simple.c +++ b/src/tests/parec-simple.c @@ -30,7 +30,7 @@ #include #include -#include "gccmacro.h" +#include #define BUFSIZE 1024 diff --git a/polyp/strlist-test.c b/src/tests/strlist-test.c similarity index 89% rename from polyp/strlist-test.c rename to src/tests/strlist-test.c index c670a105c..145431126 100644 --- a/polyp/strlist-test.c +++ b/src/tests/strlist-test.c @@ -1,8 +1,8 @@ #include -#include "strlist.h" -#include "xmalloc.h" -#include "gccmacro.h" +#include +#include +#include int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) { char *t, *u; diff --git a/polyp/voltest.c b/src/tests/voltest.c similarity index 94% rename from polyp/voltest.c rename to src/tests/voltest.c index 917e04d35..58f1da001 100644 --- a/polyp/voltest.c +++ b/src/tests/voltest.c @@ -3,7 +3,7 @@ #include #include -#include "gccmacro.h" +#include int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { pa_volume_t v; diff --git a/polyp/esdcompat.sh.in b/src/utils/esdcompat.sh.in similarity index 100% rename from polyp/esdcompat.sh.in rename to src/utils/esdcompat.sh.in diff --git a/polyp/pabrowse.c b/src/utils/pabrowse.c similarity index 100% rename from polyp/pabrowse.c rename to src/utils/pabrowse.c diff --git a/polyp/pacat.c b/src/utils/pacat.c similarity index 100% rename from polyp/pacat.c rename to src/utils/pacat.c diff --git a/polyp/pacmd.c b/src/utils/pacmd.c similarity index 98% rename from polyp/pacmd.c rename to src/utils/pacmd.c index e6c0da6af..4054bc2c1 100644 --- a/polyp/pacmd.c +++ b/src/utils/pacmd.c @@ -32,9 +32,9 @@ #include #include -#include "util.h" -#include "log.h" -#include "pid.h" +#include +#include +#include int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { pid_t pid ; diff --git a/polyp/pactl.c b/src/utils/pactl.c similarity index 100% rename from polyp/pactl.c rename to src/utils/pactl.c diff --git a/polyp/paplay.c b/src/utils/paplay.c similarity index 100% rename from polyp/paplay.c rename to src/utils/paplay.c diff --git a/polyp/pax11publish.c b/src/utils/pax11publish.c similarity index 97% rename from polyp/pax11publish.c rename to src/utils/pax11publish.c index 42947836f..63ee48212 100644 --- a/polyp/pax11publish.c +++ b/src/utils/pax11publish.c @@ -31,12 +31,12 @@ #include #include -#include "util.h" -#include "log.h" -#include "authkey.h" -#include "native-common.h" -#include "client-conf.h" -#include "x11prop.h" +#include +#include +#include +#include +#include +#include int main(int argc, char *argv[]) { const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE; From b56b9e50e027c22fc56c805d8d0cd10d99a4cd5b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 21:37:20 +0000 Subject: [PATCH 0395/1514] * svn:ignore some files * move configuration files to the directories they belong to * built esd-compat.sh in the src/ dir git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@488 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 30 +++++++++++++++------------ src/{ => daemon}/daemon.conf.in | 0 src/{ => daemon}/default.pa.in | 0 src/{ => daemon}/default.pa.win32 | 0 src/{utils => daemon}/esdcompat.sh.in | 0 src/{ => polyp}/client.conf.in | 0 6 files changed, 17 insertions(+), 13 deletions(-) rename src/{ => daemon}/daemon.conf.in (100%) rename src/{ => daemon}/default.pa.in (100%) rename src/{ => daemon}/default.pa.win32 (100%) rename src/{utils => daemon}/esdcompat.sh.in (100%) rename src/{ => polyp}/client.conf.in (100%) diff --git a/src/Makefile.am b/src/Makefile.am index 92c7dae18..8131794c2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,16 +75,20 @@ endif ################################### EXTRA_DIST = \ - client.conf.in \ - daemon.conf.in \ - default.pa.in \ + polyp/client.conf.in \ + daemon/daemon.conf.in \ + daemon/default.pa.in \ depmod.py \ - utils/esdcompat.sh.in \ + daemon/esdcompat.sh.in \ modules/module-defs.h.m4 -polypconf_DATA = default.pa daemon.conf client.conf +polypconf_DATA = \ + default.pa \ + daemon.conf \ + client.conf -BUILT_SOURCES = polyp/polyplib-version.h +BUILT_SOURCES = \ + polyp/polyplib-version.h ################################### # Main daemon # @@ -131,10 +135,10 @@ bin_PROGRAMS += pax11publish endif if HAVE_HOWL -bin_PROGRAMS += pabrowse +bin_PROGRAMS += pabrowse endif -bin_SCRIPTS = utils/esdcompat.sh +bin_SCRIPTS = daemon/esdcompat.sh pacat_SOURCES = utils/pacat.c pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la @@ -1035,23 +1039,23 @@ suid: polypaudio chown root $< chmod u+s $< -utils/esdcompat.sh: utils/esdcompat.sh.in Makefile +esdcompat.sh: daemon/esdcompat.sh.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ -client.conf: client.conf.in Makefile +client.conf: polyp/client.conf.in Makefile sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ if OS_IS_WIN32 -default.pa: default.pa.win32 +default.pa: daemon/default.pa.win32 cp $< $@ else -default.pa: default.pa.in Makefile +default.pa: daemon/default.pa.in Makefile sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ endif -daemon.conf: daemon.conf.in Makefile +daemon.conf: daemon/daemon.conf.in Makefile sed -e 's,@DLSEARCHPATH\@,$(modlibdir),g' \ -e 's,@DEFAULT_CONFIG_FILE\@,$(DEFAULT_CONFIG_DIR),g' < $< > $@ diff --git a/src/daemon.conf.in b/src/daemon/daemon.conf.in similarity index 100% rename from src/daemon.conf.in rename to src/daemon/daemon.conf.in diff --git a/src/default.pa.in b/src/daemon/default.pa.in similarity index 100% rename from src/default.pa.in rename to src/daemon/default.pa.in diff --git a/src/default.pa.win32 b/src/daemon/default.pa.win32 similarity index 100% rename from src/default.pa.win32 rename to src/daemon/default.pa.win32 diff --git a/src/utils/esdcompat.sh.in b/src/daemon/esdcompat.sh.in similarity index 100% rename from src/utils/esdcompat.sh.in rename to src/daemon/esdcompat.sh.in diff --git a/src/client.conf.in b/src/polyp/client.conf.in similarity index 100% rename from src/client.conf.in rename to src/polyp/client.conf.in From c75972f54a136eda05ab7cd87966526e026edc5a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 22:08:06 +0000 Subject: [PATCH 0396/1514] move alsa-util.[ch], oss-util.[ch] and howl-wrap.[ch] to the modules directory since they are just helper source used exclusively by the modules git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@489 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 8 ++++---- src/{polypcore => modules}/alsa-util.c | 7 ++++--- src/{polypcore => modules}/alsa-util.h | 0 src/{polypcore => modules}/howl-wrap.c | 0 src/{polypcore => modules}/howl-wrap.h | 0 src/modules/module-alsa-sink.c | 2 +- src/modules/module-alsa-source.c | 2 +- src/modules/module-oss-mmap.c | 2 +- src/modules/module-oss.c | 2 +- src/{polypcore => modules}/oss-util.c | 5 +++-- src/{polypcore => modules}/oss-util.h | 0 11 files changed, 15 insertions(+), 13 deletions(-) rename src/{polypcore => modules}/alsa-util.c (98%) rename src/{polypcore => modules}/alsa-util.h (100%) rename src/{polypcore => modules}/howl-wrap.c (100%) rename src/{polypcore => modules}/howl-wrap.h (100%) rename src/{polypcore => modules}/oss-util.c (98%) rename src/{polypcore => modules}/oss-util.h (100%) diff --git a/src/Makefile.am b/src/Makefile.am index 8131794c2..7e8e73b61 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -138,7 +138,7 @@ if HAVE_HOWL bin_PROGRAMS += pabrowse endif -bin_SCRIPTS = daemon/esdcompat.sh +bin_SCRIPTS = esdcompat.sh pacat_SOURCES = utils/pacat.c pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la @@ -651,19 +651,19 @@ libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS # OSS -liboss_util_la_SOURCES = polypcore/oss-util.c polypcore/oss-util.h +liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h liboss_util_la_LDFLAGS = -avoid-version # ALSA -libalsa_util_la_SOURCES = polypcore/alsa-util.c polypcore/alsa-util.h +libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h libalsa_util_la_LDFLAGS = -avoid-version libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) # HOWL -libhowl_wrap_la_SOURCES = polypcore/howl-wrap.c polypcore/howl-wrap.h +libhowl_wrap_la_SOURCES = modules/howl-wrap.c modules/howl-wrap.h libhowl_wrap_la_LDFLAGS = -avoid-version libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) diff --git a/src/polypcore/alsa-util.c b/src/modules/alsa-util.c similarity index 98% rename from src/polypcore/alsa-util.c rename to src/modules/alsa-util.c index 7528ee0b5..8318f9456 100644 --- a/src/polypcore/alsa-util.c +++ b/src/modules/alsa-util.c @@ -26,10 +26,11 @@ #include #include -#include "alsa-util.h" #include -#include "xmalloc.h" -#include "log.h" +#include +#include + +#include "alsa-util.h" /* Set the hardware parameters of the given ALSA device. Returns the * selected fragment settings in *period and *period_size */ diff --git a/src/polypcore/alsa-util.h b/src/modules/alsa-util.h similarity index 100% rename from src/polypcore/alsa-util.h rename to src/modules/alsa-util.h diff --git a/src/polypcore/howl-wrap.c b/src/modules/howl-wrap.c similarity index 100% rename from src/polypcore/howl-wrap.c rename to src/modules/howl-wrap.c diff --git a/src/polypcore/howl-wrap.h b/src/modules/howl-wrap.h similarity index 100% rename from src/polypcore/howl-wrap.h rename to src/modules/howl-wrap.h diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 48e90e9f2..d3fe71a57 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -41,11 +41,11 @@ #include #include #include -#include #include #include #include "module-alsa-sink-symdef.h" +#include "alsa-util.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ALSA Sink") diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index f03e51ad6..9453f8461 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -41,11 +41,11 @@ #include #include #include -#include #include #include #include "module-alsa-source-symdef.h" +#include "alsa-util.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ALSA Source") diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 6986b03c9..80c762f11 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -40,13 +40,13 @@ #include #include #include -#include #include #include #include #include #include +#include "oss-util.h" #include "module-oss-mmap-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 04458419a..264e8792e 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -47,6 +46,7 @@ #include #include "module-oss-symdef.h" +#include "oss-util.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("OSS Sink/Source") diff --git a/src/polypcore/oss-util.c b/src/modules/oss-util.c similarity index 98% rename from src/polypcore/oss-util.c rename to src/modules/oss-util.c index ae6772fd9..e9a133f5d 100644 --- a/src/polypcore/oss-util.c +++ b/src/modules/oss-util.c @@ -34,9 +34,10 @@ #include #include +#include +#include + #include "oss-util.h" -#include "util.h" -#include "log.h" int pa_oss_open(const char *device, int *mode, int* pcaps) { int fd = -1; diff --git a/src/polypcore/oss-util.h b/src/modules/oss-util.h similarity index 100% rename from src/polypcore/oss-util.h rename to src/modules/oss-util.h From 4ad2926eba724771ef29f5aae3757a588bf8818e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 22:11:35 +0000 Subject: [PATCH 0397/1514] add a bunch of simple Makefile in the subdirs, just to make compilation with emacs easier they are not intended to be distributed or anything. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@490 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/Makefile | 1 + src/modules/Makefile | 1 + src/polyp/Makefile | 13 +++++++++++++ src/polypcore/Makefile | 1 + src/tests/Makefile | 1 + src/utils/Makefile | 1 + 6 files changed, 18 insertions(+) create mode 120000 src/daemon/Makefile create mode 120000 src/modules/Makefile create mode 100644 src/polyp/Makefile create mode 120000 src/polypcore/Makefile create mode 120000 src/tests/Makefile create mode 120000 src/utils/Makefile diff --git a/src/daemon/Makefile b/src/daemon/Makefile new file mode 120000 index 000000000..cd2a5c9a6 --- /dev/null +++ b/src/daemon/Makefile @@ -0,0 +1 @@ +../polyp/Makefile \ No newline at end of file diff --git a/src/modules/Makefile b/src/modules/Makefile new file mode 120000 index 000000000..cd2a5c9a6 --- /dev/null +++ b/src/modules/Makefile @@ -0,0 +1 @@ +../polyp/Makefile \ No newline at end of file diff --git a/src/polyp/Makefile b/src/polyp/Makefile new file mode 100644 index 000000000..7c8875f39 --- /dev/null +++ b/src/polyp/Makefile @@ -0,0 +1,13 @@ +# This is a dirty trick just to ease compilation with emacs +# +# This file is not intended to be distributed or anything +# +# So: don't touch it, even better ignore it! + +all: + $(MAKE) -C .. + +clean: + $(MAKE) -C .. clean + +.PHONY: all clean diff --git a/src/polypcore/Makefile b/src/polypcore/Makefile new file mode 120000 index 000000000..cd2a5c9a6 --- /dev/null +++ b/src/polypcore/Makefile @@ -0,0 +1 @@ +../polyp/Makefile \ No newline at end of file diff --git a/src/tests/Makefile b/src/tests/Makefile new file mode 120000 index 000000000..cd2a5c9a6 --- /dev/null +++ b/src/tests/Makefile @@ -0,0 +1 @@ +../polyp/Makefile \ No newline at end of file diff --git a/src/utils/Makefile b/src/utils/Makefile new file mode 120000 index 000000000..cd2a5c9a6 --- /dev/null +++ b/src/utils/Makefile @@ -0,0 +1 @@ +../polyp/Makefile \ No newline at end of file From f49b09df15221dc45526607af380990aebe1537b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 22:34:52 +0000 Subject: [PATCH 0398/1514] make channel naming somewhat RFC2551 compliant git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@491 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.c | 36 ++++++++++++++++++++++++------------ src/polyp/channelmap.h | 5 +++-- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index 7bfd21e6e..bb47deb85 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -71,34 +71,46 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels) { pa_channel_map_init(m); m->channels = channels; + + /* This is somewhat compatible with RFC3551 */ switch (channels) { case 1: m->map[0] = PA_CHANNEL_POSITION_MONO; return m; - case 8: - m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT; - m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT; - /* Fall through */ - case 6: + m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + m->map[1] = PA_CHANNEL_POSITION_SIDE_LEFT; + m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; + m->map[3] = PA_CHANNEL_POSITION_FRONT_RIGHT; + m->map[4] = PA_CHANNEL_POSITION_SIDE_RIGHT; m->map[5] = PA_CHANNEL_POSITION_LFE; - /* Fall through */ + return m; case 5: - m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER; - /* Fall through */ - - case 4: - m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT; - m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; + m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT; + m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT; /* Fall through */ case 2: m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; return m; + + case 3: + m->map[0] = PA_CHANNEL_POSITION_LEFT; + m->map[1] = PA_CHANNEL_POSITION_RIGHT; + m->map[2] = PA_CHANNEL_POSITION_CENTER; + return m; + + case 4: + m->map[0] = PA_CHANNEL_POSITION_LEFT; + m->map[1] = PA_CHANNEL_POSITION_CENTER; + m->map[2] = PA_CHANNEL_POSITION_RIGHT; + m->map[3] = PA_CHANNEL_POSITION_LFE; + return m; default: return NULL; diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index 0b9f6e26e..7c48b76bb 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -36,10 +36,11 @@ typedef enum { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, - - PA_CHANNEL_POSITION_FRONT_CENTER, + PA_CHANNEL_POSITION_CENTER, + PA_CHANNEL_POSITION_FRONT_LEFT = PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT = PA_CHANNEL_POSITION_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER = PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_REAR_CENTER, PA_CHANNEL_POSITION_REAR_LEFT, From 22c8cebb858012e4e9c551bb54456237e7597697 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 22:43:59 +0000 Subject: [PATCH 0399/1514] drop polyplib- prefix from client library files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@492 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- src/Makefile.am | 50 +++++++++---------- src/polyp/{polyplib-browser.c => browser.c} | 2 +- src/polyp/{polyplib-browser.h => browser.h} | 0 src/polyp/{polyplib-context.c => context.c} | 6 +-- src/polyp/{polyplib-context.h => context.h} | 4 +- src/polyp/{polyplib-def.h => def.h} | 0 src/polyp/{polyplib-error.c => error.c} | 2 +- src/polyp/{polyplib-error.h => error.h} | 0 src/polyp/{polyplib-internal.h => internal.h} | 6 +-- .../{polyplib-introspect.c => introspect.c} | 6 +-- .../{polyplib-introspect.h => introspect.h} | 4 +- .../{polyplib-operation.c => operation.c} | 4 +- .../{polyplib-operation.h => operation.h} | 2 +- src/polyp/{polyplib.h => polypaudio.h} | 26 +++++----- src/polyp/{polyplib-scache.c => scache.c} | 4 +- src/polyp/{polyplib-scache.h => scache.h} | 4 +- src/polyp/{polyplib-simple.c => simple.c} | 2 +- src/polyp/{polyplib-simple.h => simple.h} | 2 +- src/polyp/{polyplib-stream.c => stream.c} | 2 +- src/polyp/{polyplib-stream.h => stream.h} | 4 +- .../{polyplib-subscribe.c => subscribe.c} | 4 +- .../{polyplib-subscribe.h => subscribe.h} | 4 +- .../{polyplib-version.h.in => version.h.in} | 2 +- src/polypcore/native-common.h | 2 +- src/polypcore/sink.c | 2 +- src/tests/pacat-simple.c | 4 +- src/tests/parec-simple.c | 4 +- src/utils/pabrowse.c | 2 +- src/utils/pacat.c | 4 +- src/utils/pactl.c | 2 +- src/utils/paplay.c | 4 +- 32 files changed, 83 insertions(+), 83 deletions(-) rename src/polyp/{polyplib-browser.c => browser.c} (99%) rename src/polyp/{polyplib-browser.h => browser.h} (100%) rename src/polyp/{polyplib-context.c => context.c} (99%) rename src/polyp/{polyplib-context.h => context.h} (98%) rename src/polyp/{polyplib-def.h => def.h} (100%) rename src/polyp/{polyplib-error.c => error.c} (98%) rename src/polyp/{polyplib-error.h => error.h} (100%) rename src/polyp/{polyplib-internal.h => internal.h} (98%) rename src/polyp/{polyplib-introspect.c => introspect.c} (99%) rename src/polyp/{polyplib-introspect.h => introspect.h} (99%) rename src/polyp/{polyplib-operation.c => operation.c} (97%) rename src/polyp/{polyplib-operation.h => operation.h} (97%) rename src/polyp/{polyplib.h => polypaudio.h} (79%) rename src/polyp/{polyplib-scache.c => scache.c} (98%) rename src/polyp/{polyplib-scache.h => scache.h} (96%) rename src/polyp/{polyplib-simple.c => simple.c} (99%) rename src/polyp/{polyplib-simple.h => simple.h} (99%) rename src/polyp/{polyplib-stream.c => stream.c} (99%) rename src/polyp/{polyplib-stream.h => stream.h} (99%) rename src/polyp/{polyplib-subscribe.c => subscribe.c} (97%) rename src/polyp/{polyplib-subscribe.h => subscribe.h} (95%) rename src/polyp/{polyplib-version.h.in => version.h.in} (94%) diff --git a/configure.ac b/configure.ac index 182a2455c..4261903f1 100644 --- a/configure.ac +++ b/configure.ac @@ -407,7 +407,7 @@ doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf -src/polyp/polyplib-version.h +src/polyp/version.h doc/FAQ.html ]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index 7e8e73b61..cfd4b7510 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,7 +88,7 @@ polypconf_DATA = \ client.conf BUILT_SOURCES = \ - polyp/polyplib-version.h + polyp/version.h ################################### # Main daemon # @@ -259,23 +259,23 @@ polypinclude_HEADERS = \ polyp/mainloop.h \ polyp/mainloop-api.h \ polyp/mainloop-signal.h \ - polyp/polyplib.h \ - polyp/polyplib-context.h \ - polyp/polyplib-def.h \ - polyp/polyplib-error.h \ - polyp/polyplib-introspect.h \ - polyp/polyplib-operation.h \ - polyp/polyplib-scache.h \ - polyp/polyplib-simple.h \ - polyp/polyplib-stream.h \ - polyp/polyplib-subscribe.h \ - polyp/polyplib-version.h \ + polyp/polypaudio.h \ + polyp/context.h \ + polyp/def.h \ + polyp/error.h \ + polyp/introspect.h \ + polyp/operation.h \ + polyp/scache.h \ + polyp/simple.h \ + polyp/stream.h \ + polyp/subscribe.h \ + polyp/version.h \ polyp/sample.h \ polyp/volume.h if HAVE_HOWL polypinclude_HEADERS += \ - polyp/polyplib-browser.h + polyp/browser.h endif lib_LTLIBRARIES = \ @@ -306,15 +306,15 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ polyp/client-conf.c polyp/client-conf.h \ polyp/llist.h \ polyp/mainloop-api.c polyp/mainloop-api.h \ - polyp/polyplib.h \ - polyp/polyplib-context.c polyp/polyplib-context.h \ - polyp/polyplib-def.h \ - polyp/polyplib-internal.h \ - polyp/polyplib-introspect.c polyp/polyplib-introspect.h \ - polyp/polyplib-operation.c polyp/polyplib-operation.h \ - polyp/polyplib-scache.c polyp/polyplib-scache.h \ - polyp/polyplib-stream.c polyp/polyplib-stream.h \ - polyp/polyplib-subscribe.c polyp/polyplib-subscribe.h \ + polyp/polypaudio.h \ + polyp/context.c polyp/context.h \ + polyp/def.h \ + polyp/internal.h \ + polyp/introspect.c polyp/introspect.h \ + polyp/operation.c polyp/operation.h \ + polyp/scache.c polyp/scache.h \ + polyp/stream.c polyp/stream.h \ + polyp/subscribe.c polyp/subscribe.h \ polyp/sample.c polyp/sample.h \ polyp/volume.c polyp/volume.h @@ -368,7 +368,7 @@ libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(LIBASYNCNS_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LIBADD += $(LIBASYNCNS_LIBS) endif -libpolyp_error_@PA_MAJORMINOR@_la_SOURCES = polyp/polyplib-error.c polyp/polyplib-error.h +libpolyp_error_@PA_MAJORMINOR@_la_SOURCES = polyp/error.c polyp/error.h libpolyp_error_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_error_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la libpolyp_error_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 @@ -381,12 +381,12 @@ libpolyp_mainloop_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_mainloop_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(WINSOCK_LIBS) libpolyp_mainloop_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_simple_@PA_MAJORMINOR@_la_SOURCES = polyp/polyplib-simple.c polyp/polyplib-simple.h +libpolyp_simple_@PA_MAJORMINOR@_la_SOURCES = polyp/simple.c polyp/simple.h libpolyp_simple_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_simple_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp_simple_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_browse_@PA_MAJORMINOR@_la_SOURCES = polyp/polyplib-browser.c polyp/polyplib-browser.h +libpolyp_browse_@PA_MAJORMINOR@_la_SOURCES = polyp/browser.c polyp/browser.h libpolyp_browse_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) libpolyp_browse_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(HOWL_LIBS) libpolyp_browse_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 diff --git a/src/polyp/polyplib-browser.c b/src/polyp/browser.c similarity index 99% rename from src/polyp/polyplib-browser.c rename to src/polyp/browser.c index 9a3894842..80051d545 100644 --- a/src/polyp/polyplib-browser.c +++ b/src/polyp/browser.c @@ -22,7 +22,7 @@ #include #include -#include "polyplib-browser.h" +#include "browser.h" #include #include #include diff --git a/src/polyp/polyplib-browser.h b/src/polyp/browser.h similarity index 100% rename from src/polyp/polyplib-browser.h rename to src/polyp/browser.h diff --git a/src/polyp/polyplib-context.c b/src/polyp/context.c similarity index 99% rename from src/polyp/polyplib-context.c rename to src/polyp/context.c index c392f0fcf..4ac11caa4 100644 --- a/src/polyp/polyplib-context.c +++ b/src/polyp/context.c @@ -47,9 +47,9 @@ #include -#include "polyplib-internal.h" -#include "polyplib-context.h" -#include "polyplib-version.h" +#include "internal.h" +#include "context.h" +#include "version.h" #include #include #include diff --git a/src/polyp/polyplib-context.h b/src/polyp/context.h similarity index 98% rename from src/polyp/polyplib-context.h rename to src/polyp/context.h index febb75f42..6496c7030 100644 --- a/src/polyp/polyplib-context.h +++ b/src/polyp/context.h @@ -23,10 +23,10 @@ ***/ #include -#include +#include #include #include -#include +#include /** \file * Connection contexts for asynchrononous communication with a diff --git a/src/polyp/polyplib-def.h b/src/polyp/def.h similarity index 100% rename from src/polyp/polyplib-def.h rename to src/polyp/def.h diff --git a/src/polyp/polyplib-error.c b/src/polyp/error.c similarity index 98% rename from src/polyp/polyplib-error.c rename to src/polyp/error.c index 188d6a93d..a137ab494 100644 --- a/src/polyp/polyplib-error.c +++ b/src/polyp/error.c @@ -26,7 +26,7 @@ #include #include -#include "polyplib-error.h" +#include "error.h" #include static const char* const errortab[PA_ERROR_MAX] = { diff --git a/src/polyp/polyplib-error.h b/src/polyp/error.h similarity index 100% rename from src/polyp/polyplib-error.h rename to src/polyp/error.h diff --git a/src/polyp/polyplib-internal.h b/src/polyp/internal.h similarity index 98% rename from src/polyp/polyplib-internal.h rename to src/polyp/internal.h index b95a20f3a..feb9f6f41 100644 --- a/src/polyp/polyplib-internal.h +++ b/src/polyp/internal.h @@ -28,9 +28,9 @@ #include #include -#include "polyplib-context.h" -#include "polyplib-stream.h" -#include "polyplib-operation.h" +#include "context.h" +#include "stream.h" +#include "operation.h" #include #include #include diff --git a/src/polyp/polyplib-introspect.c b/src/polyp/introspect.c similarity index 99% rename from src/polyp/polyplib-introspect.c rename to src/polyp/introspect.c index 0bdffa35f..d89eb9ede 100644 --- a/src/polyp/polyplib-introspect.c +++ b/src/polyp/introspect.c @@ -25,9 +25,9 @@ #include -#include "polyplib-introspect.h" -#include "polyplib-context.h" -#include "polyplib-internal.h" +#include "introspect.h" +#include "context.h" +#include "internal.h" #include #include diff --git a/src/polyp/polyplib-introspect.h b/src/polyp/introspect.h similarity index 99% rename from src/polyp/polyplib-introspect.h rename to src/polyp/introspect.h index d34899086..75dc027f6 100644 --- a/src/polyp/polyplib-introspect.h +++ b/src/polyp/introspect.h @@ -24,8 +24,8 @@ #include -#include -#include +#include +#include #include #include #include diff --git a/src/polyp/polyplib-operation.c b/src/polyp/operation.c similarity index 97% rename from src/polyp/polyplib-operation.c rename to src/polyp/operation.c index ea336c173..0baa661b5 100644 --- a/src/polyp/polyplib-operation.c +++ b/src/polyp/operation.c @@ -26,8 +26,8 @@ #include #include -#include "polyplib-internal.h" -#include "polyplib-operation.h" +#include "internal.h" +#include "operation.h" pa_operation *pa_operation_new(pa_context *c, pa_stream *s) { pa_operation *o; diff --git a/src/polyp/polyplib-operation.h b/src/polyp/operation.h similarity index 97% rename from src/polyp/polyplib-operation.h rename to src/polyp/operation.h index cac03e30b..fea82f10e 100644 --- a/src/polyp/polyplib-operation.h +++ b/src/polyp/operation.h @@ -23,7 +23,7 @@ ***/ #include -#include +#include /** \file * Asynchronous operations */ diff --git a/src/polyp/polyplib.h b/src/polyp/polypaudio.h similarity index 79% rename from src/polyp/polyplib.h rename to src/polyp/polypaudio.h index b9b9b447d..232085268 100644 --- a/src/polyp/polyplib.h +++ b/src/polyp/polypaudio.h @@ -25,18 +25,18 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include /** \file * Include all polyplib header file at once. The following files are included: \ref mainloop-api.h, \ref sample.h, - * \ref polyplib-def.h, \ref polyplib-context.h, \ref polyplib-stream.h, - * \ref polyplib-introspect.h, \ref polyplib-subscribe.h and \ref polyplib-scache.h \ref polyplib-version.h + * \ref def.h, \ref context.h, \ref stream.h, + * \ref introspect.h, \ref subscribe.h and \ref scache.h \ref version.h * at once */ /** \mainpage @@ -57,13 +57,13 @@ * * Use this if you develop your program in synchronous style and just * need a way to play or record data on the sound server. See - * \ref polyplib-simple.h for more details. + * \ref simple.h for more details. * * \section async_api Asynchronous API * * Use this if you develop your programs in asynchronous, main loop * based style or want to use advanced features of the polypaudio - * API. A good starting point is \ref polyplib-context.h + * API. A good starting point is \ref context.h * * The asynchronous API relies on an abstract main loop API that is * described in \ref mainloop-api.h. Two distinct implementations are @@ -79,8 +79,8 @@ * * The polypaudio libraries provide pkg-config snippets for the different modules. To use the * asynchronous API use "polyplib" as pkg-config file. GLIB main loop - * support is available as "polyplib-glib-mainloop". The simple - * synchronous API is available as "polyplib-simple". + * support is available as "glib-mainloop". The simple + * synchronous API is available as "simple". */ #endif diff --git a/src/polyp/polyplib-scache.c b/src/polyp/scache.c similarity index 98% rename from src/polyp/polyplib-scache.c rename to src/polyp/scache.c index 1315af970..c274e3597 100644 --- a/src/polyp/polyplib-scache.c +++ b/src/polyp/scache.c @@ -28,8 +28,8 @@ #include #include -#include "polyplib-scache.h" -#include "polyplib-internal.h" +#include "scache.h" +#include "internal.h" #include void pa_stream_connect_upload(pa_stream *s, size_t length) { diff --git a/src/polyp/polyplib-scache.h b/src/polyp/scache.h similarity index 96% rename from src/polyp/polyplib-scache.h rename to src/polyp/scache.h index 89d27597f..41b956d2e 100644 --- a/src/polyp/polyplib-scache.h +++ b/src/polyp/scache.h @@ -24,8 +24,8 @@ #include -#include -#include +#include +#include #include /** \file diff --git a/src/polyp/polyplib-simple.c b/src/polyp/simple.c similarity index 99% rename from src/polyp/polyplib-simple.c rename to src/polyp/simple.c index 7436f0074..6f20da899 100644 --- a/src/polyp/polyplib-simple.c +++ b/src/polyp/simple.c @@ -28,7 +28,7 @@ #include #include -#include "polyplib-simple.h" +#include "simple.h" #include "polyplib.h" #include "mainloop.h" #include diff --git a/src/polyp/polyplib-simple.h b/src/polyp/simple.h similarity index 99% rename from src/polyp/polyplib-simple.h rename to src/polyp/simple.h index b01f30d5d..31dcaef49 100644 --- a/src/polyp/polyplib-simple.h +++ b/src/polyp/simple.h @@ -25,7 +25,7 @@ #include #include "sample.h" -#include "polyplib-def.h" +#include "def.h" #include /** \file diff --git a/src/polyp/polyplib-stream.c b/src/polyp/stream.c similarity index 99% rename from src/polyp/polyplib-stream.c rename to src/polyp/stream.c index 63c9245b0..007d5e24f 100644 --- a/src/polyp/polyplib-stream.c +++ b/src/polyp/stream.c @@ -28,7 +28,7 @@ #include #include -#include "polyplib-internal.h" +#include "internal.h" #include #include #include diff --git a/src/polyp/polyplib-stream.h b/src/polyp/stream.h similarity index 99% rename from src/polyp/polyplib-stream.h rename to src/polyp/stream.h index bc828b71c..d8409b3bf 100644 --- a/src/polyp/polyplib-stream.h +++ b/src/polyp/stream.h @@ -27,9 +27,9 @@ #include #include #include -#include +#include #include -#include +#include /** \file * Audio streams for input, output and sample upload */ diff --git a/src/polyp/polyplib-subscribe.c b/src/polyp/subscribe.c similarity index 97% rename from src/polyp/polyplib-subscribe.c rename to src/polyp/subscribe.c index 13fcfb420..c481f5255 100644 --- a/src/polyp/polyplib-subscribe.c +++ b/src/polyp/subscribe.c @@ -26,8 +26,8 @@ #include #include -#include "polyplib-subscribe.h" -#include "polyplib-internal.h" +#include "subscribe.h" +#include "internal.h" #include #include diff --git a/src/polyp/polyplib-subscribe.h b/src/polyp/subscribe.h similarity index 95% rename from src/polyp/polyplib-subscribe.h rename to src/polyp/subscribe.h index 920c98533..4986272d0 100644 --- a/src/polyp/polyplib-subscribe.h +++ b/src/polyp/subscribe.h @@ -24,8 +24,8 @@ #include -#include -#include +#include +#include #include /** \file diff --git a/src/polyp/polyplib-version.h.in b/src/polyp/version.h.in similarity index 94% rename from src/polyp/polyplib-version.h.in rename to src/polyp/version.h.in index 89e0a0e50..36cafb70f 100644 --- a/src/polyp/polyplib-version.h.in +++ b/src/polyp/version.h.in @@ -22,7 +22,7 @@ USA. ***/ -/* WARNING: Make sure to edit the real source file polyplib-version.h.in! */ +/* WARNING: Make sure to edit the real source file version.h.in! */ /** \file * Define header version */ diff --git a/src/polypcore/native-common.h b/src/polypcore/native-common.h index 78ae721ef..ac3ea8231 100644 --- a/src/polypcore/native-common.h +++ b/src/polypcore/native-common.h @@ -23,7 +23,7 @@ ***/ #include -#include +#include PA_C_DECL_BEGIN diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index 411befe7f..f29afba73 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -36,7 +36,7 @@ #include "xmalloc.h" #include "subscribe.h" #include "log.h" -#include +#include #define MAX_MIX_CHANNELS 32 diff --git a/src/tests/pacat-simple.c b/src/tests/pacat-simple.c index 8b3a7b227..0382ec060 100644 --- a/src/tests/pacat-simple.c +++ b/src/tests/pacat-simple.c @@ -28,8 +28,8 @@ #include #include -#include -#include +#include +#include #include #define BUFSIZE 1024 diff --git a/src/tests/parec-simple.c b/src/tests/parec-simple.c index 10eaea8de..fc2314acc 100644 --- a/src/tests/parec-simple.c +++ b/src/tests/parec-simple.c @@ -28,8 +28,8 @@ #include #include -#include -#include +#include +#include #include #define BUFSIZE 1024 diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 634c308a2..290531e63 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { diff --git a/src/utils/pacat.c b/src/utils/pacat.c index bd2b64fd5..a4f3d3af1 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -33,10 +33,10 @@ #include #include -#include +#include #include #include -#include +#include #if PA_API_VERSION != 8 #error Invalid Polypaudio API version diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 23bd924b8..7d903eb8f 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/utils/paplay.c b/src/utils/paplay.c index ddc1cbc16..1b3697fae 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -35,10 +35,10 @@ #include #include -#include +#include #include #include -#include +#include #if PA_API_VERSION != 8 #error Invalid Polypaudio API version From 45b1eeec6b3fa829dc08e61449105ca93566c4a0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 23:10:33 +0000 Subject: [PATCH 0400/1514] fix compilation of simple API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@493 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/simple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/simple.c b/src/polyp/simple.c index 6f20da899..19c49c9b9 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -29,7 +29,7 @@ #include #include "simple.h" -#include "polyplib.h" +#include "polypaudio.h" #include "mainloop.h" #include #include From 19b5b71feb51544a442b71af725d26aae2c55527 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 23:11:28 +0000 Subject: [PATCH 0401/1514] * drop polylib prefix from #define * include error.h from polypaudio.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@494 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/browser.h | 4 ++-- src/polyp/context.h | 4 ++-- src/polyp/def.h | 4 ++-- src/polyp/error.h | 4 ++-- src/polyp/internal.h | 4 ++-- src/polyp/introspect.h | 4 ++-- src/polyp/operation.h | 4 ++-- src/polyp/polypaudio.h | 7 ++++--- src/polyp/scache.h | 4 ++-- src/polyp/simple.h | 4 ++-- src/polyp/stream.h | 4 ++-- src/polyp/subscribe.h | 4 ++-- src/polyp/version.h.in | 4 ++-- 13 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/polyp/browser.h b/src/polyp/browser.h index 853304d7d..3bb0d2649 100644 --- a/src/polyp/browser.h +++ b/src/polyp/browser.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibbrowserhfoo -#define foopolyplibbrowserhfoo +#ifndef foobrowserhfoo +#define foobrowserhfoo /* $Id$ */ diff --git a/src/polyp/context.h b/src/polyp/context.h index 6496c7030..216d7d87d 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibcontexthfoo -#define foopolyplibcontexthfoo +#ifndef foocontexthfoo +#define foocontexthfoo /* $Id$ */ diff --git a/src/polyp/def.h b/src/polyp/def.h index 0591ce6c1..ba35b31e8 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibdefhfoo -#define foopolyplibdefhfoo +#ifndef foodefhfoo +#define foodefhfoo /* $Id$ */ diff --git a/src/polyp/error.h b/src/polyp/error.h index 1bb978224..ff2507b21 100644 --- a/src/polyp/error.h +++ b/src/polyp/error.h @@ -1,5 +1,5 @@ -#ifndef foopolypliberrorhfoo -#define foopolypliberrorhfoo +#ifndef fooerrorhfoo +#define fooerrorhfoo /* $Id$ */ diff --git a/src/polyp/internal.h b/src/polyp/internal.h index feb9f6f41..bdfd5d8ec 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibinternalhfoo -#define foopolyplibinternalhfoo +#ifndef foointernalhfoo +#define foointernalhfoo /* $Id$ */ diff --git a/src/polyp/introspect.h b/src/polyp/introspect.h index 75dc027f6..0abb54cf2 100644 --- a/src/polyp/introspect.h +++ b/src/polyp/introspect.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibintrospecthfoo -#define foopolyplibintrospecthfoo +#ifndef foointrospecthfoo +#define foointrospecthfoo /* $Id$ */ diff --git a/src/polyp/operation.h b/src/polyp/operation.h index fea82f10e..6a24d6495 100644 --- a/src/polyp/operation.h +++ b/src/polyp/operation.h @@ -1,5 +1,5 @@ -#ifndef foopolypliboperationhfoo -#define foopolypliboperationhfoo +#ifndef foooperationhfoo +#define foooperationhfoo /* $Id$ */ diff --git a/src/polyp/polypaudio.h b/src/polyp/polypaudio.h index 232085268..c6014bbb4 100644 --- a/src/polyp/polypaudio.h +++ b/src/polyp/polypaudio.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibhfoo -#define foopolyplibhfoo +#ifndef foopolypaudiohfoo +#define foopolypaudiohfoo /* $Id$ */ @@ -32,11 +32,12 @@ #include #include #include +#include /** \file * Include all polyplib header file at once. The following files are included: \ref mainloop-api.h, \ref sample.h, * \ref def.h, \ref context.h, \ref stream.h, - * \ref introspect.h, \ref subscribe.h and \ref scache.h \ref version.h + * \ref introspect.h, \ref subscribe.h, \ref scache.h, \ref version.h \ref error.h * at once */ /** \mainpage diff --git a/src/polyp/scache.h b/src/polyp/scache.h index 41b956d2e..5bf004d0a 100644 --- a/src/polyp/scache.h +++ b/src/polyp/scache.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibscachehfoo -#define foopolyplibscachehfoo +#ifndef fooscachehfoo +#define fooscachehfoo /* $Id$ */ diff --git a/src/polyp/simple.h b/src/polyp/simple.h index 31dcaef49..270cbb24a 100644 --- a/src/polyp/simple.h +++ b/src/polyp/simple.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibsimplehfoo -#define foopolyplibsimplehfoo +#ifndef foosimplehfoo +#define foosimplehfoo /* $Id$ */ diff --git a/src/polyp/stream.h b/src/polyp/stream.h index d8409b3bf..e2cab19e9 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibstreamhfoo -#define foopolyplibstreamhfoo +#ifndef foostreamhfoo +#define foostreamhfoo /* $Id$ */ diff --git a/src/polyp/subscribe.h b/src/polyp/subscribe.h index 4986272d0..f1f0642d9 100644 --- a/src/polyp/subscribe.h +++ b/src/polyp/subscribe.h @@ -1,5 +1,5 @@ -#ifndef foopolyplibsubscribehfoo -#define foopolyplibsubscribehfoo +#ifndef foosubscribehfoo +#define foosubscribehfoo /* $Id$ */ diff --git a/src/polyp/version.h.in b/src/polyp/version.h.in index 36cafb70f..c727381f3 100644 --- a/src/polyp/version.h.in +++ b/src/polyp/version.h.in @@ -1,5 +1,5 @@ -#ifndef foopolyplibversionhfoo /*-*-C-*-*/ -#define foopolyplibversionhfoo +#ifndef fooversionhfoo /*-*-C-*-*/ +#define fooversionhfoo /* $Id$ */ From b4cb249d704cbb0458640526a07e1f541b899d3e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 23:12:10 +0000 Subject: [PATCH 0402/1514] shorten include list of utils a little git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@495 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pabrowse.c | 1 - src/utils/pacat.c | 4 +--- src/utils/pactl.c | 4 +--- src/utils/paplay.c | 4 +--- src/utils/pax11publish.c | 2 +- 5 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 290531e63..344e32813 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -30,7 +30,6 @@ #include #include #include -#include static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got signal, exiting\n"); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index a4f3d3af1..3c50402f6 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -32,11 +32,9 @@ #include #include -#include -#include +#include #include #include -#include #if PA_API_VERSION != 8 #error Invalid Polypaudio API version diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 7d903eb8f..4c22c9251 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -35,11 +35,9 @@ #include -#include -#include +#include #include #include -#include #if PA_API_VERSION != 8 #error Invalid Polypaudio API version diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 1b3697fae..9f73b8341 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -34,11 +34,9 @@ #include -#include -#include +#include #include #include -#include #if PA_API_VERSION != 8 #error Invalid Polypaudio API version diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 63ee48212..908a35072 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -35,8 +35,8 @@ #include #include #include -#include #include +#include int main(int argc, char *argv[]) { const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE; From 5ccf4145bcf1760d30962c32f0f4749047c6cae8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 23:13:27 +0000 Subject: [PATCH 0403/1514] * rename polypcore/subscribe.[ch] to polypcore/core-subscribe.[ch] to avoid confusion with polyp/subscribe.[ch] * same for scache.[ch] git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@496 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 ++-- src/modules/module-match.c | 2 +- src/modules/module-tunnel.c | 2 +- src/modules/module-x11-bell.c | 2 +- src/modules/module-x11-publish.c | 2 +- src/polypcore/autoload.c | 4 ++-- src/polypcore/cli-command.c | 2 +- src/polypcore/cli-text.c | 2 +- src/polypcore/client.c | 2 +- src/polypcore/{scache.c => core-scache.c} | 4 ++-- src/polypcore/{scache.h => core-scache.h} | 4 ++-- src/polypcore/{subscribe.c => core-subscribe.c} | 2 +- src/polypcore/{subscribe.h => core-subscribe.h} | 4 ++-- src/polypcore/core.c | 4 ++-- src/polypcore/core.h | 2 +- src/polypcore/module.c | 2 +- src/polypcore/namereg.c | 2 +- src/polypcore/protocol-esound.c | 2 +- src/polypcore/protocol-native.c | 4 ++-- src/polypcore/sink-input.c | 2 +- src/polypcore/sink.c | 2 +- src/polypcore/source-output.c | 2 +- src/polypcore/source.c | 2 +- 23 files changed, 30 insertions(+), 30 deletions(-) rename src/polypcore/{scache.c => core-scache.c} (99%) rename src/polypcore/{scache.h => core-scache.h} (97%) rename src/polypcore/{subscribe.c => core-subscribe.c} (99%) rename src/polypcore/{subscribe.h => core-subscribe.h} (95%) diff --git a/src/Makefile.am b/src/Makefile.am index cfd4b7510..7d87a1199 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -479,7 +479,7 @@ libpolypcore_la_SOURCES += \ polypcore/random.c polypcore/random.h \ polypcore/resampler.c polypcore/resampler.h \ polypcore/sample-util.c polypcore/sample-util.h \ - polypcore/scache.c polypcore/scache.h \ + polypcore/core-scache.c polypcore/core-scache.h \ polypcore/sconv.c polypcore/sconv.h \ polypcore/sconv-s16be.c polypcore/sconv-s16be.h \ polypcore/sconv-s16le.c polypcore/sconv-s16le.h \ @@ -491,7 +491,7 @@ libpolypcore_la_SOURCES += \ polypcore/source.c polypcore/source.h \ polypcore/source-output.c polypcore/source-output.h \ polypcore/strbuf.c polypcore/strbuf.h \ - polypcore/subscribe.c polypcore/subscribe.h \ + polypcore/core-subscribe.c polypcore/core-subscribe.h \ polypcore/tokenizer.c polypcore/tokenizer.h \ polypcore/util.c polypcore/util.h \ polypcore/winsock.h \ diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 10ceb75ed..1fb7233cc 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 5ee10fda9..61b9bb3b3 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index d722b732f..d59f3f592 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index dca5d049e..6d9036f5a 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/polypcore/autoload.c b/src/polypcore/autoload.c index ff2916cbf..83df8ef7f 100644 --- a/src/polypcore/autoload.c +++ b/src/polypcore/autoload.c @@ -33,8 +33,8 @@ #include "memchunk.h" #include "sound-file.h" #include "log.h" -#include "scache.h" -#include "subscribe.h" +#include "core-scache.h" +#include "core-subscribe.h" static void entry_free(pa_autoload_entry *e) { assert(e); diff --git a/src/polypcore/cli-command.c b/src/polypcore/cli-command.c index f6192bf87..dd4cbe463 100644 --- a/src/polypcore/cli-command.c +++ b/src/polypcore/cli-command.c @@ -40,7 +40,7 @@ #include "strbuf.h" #include "namereg.h" #include "cli-text.h" -#include "scache.h" +#include "core-scache.h" #include "sample-util.h" #include "sound-file.h" #include "play-memchunk.h" diff --git a/src/polypcore/cli-text.c b/src/polypcore/cli-text.c index 58248d8ec..d8446b067 100644 --- a/src/polypcore/cli-text.c +++ b/src/polypcore/cli-text.c @@ -35,7 +35,7 @@ #include "source-output.h" #include "strbuf.h" #include "sample-util.h" -#include "scache.h" +#include "core-scache.h" #include "autoload.h" #include "xmalloc.h" #include diff --git a/src/polypcore/client.c b/src/polypcore/client.c index 3c2084bfb..9b2567942 100644 --- a/src/polypcore/client.c +++ b/src/polypcore/client.c @@ -30,7 +30,7 @@ #include "client.h" #include "xmalloc.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "log.h" pa_client *pa_client_new(pa_core *core, const char *name, const char *driver) { diff --git a/src/polypcore/scache.c b/src/polypcore/core-scache.c similarity index 99% rename from src/polypcore/scache.c rename to src/polypcore/core-scache.c index 02c7d34fa..0d926abaf 100644 --- a/src/polypcore/scache.c +++ b/src/polypcore/core-scache.c @@ -41,13 +41,13 @@ #include #endif -#include "scache.h" +#include "core-scache.h" #include "sink-input.h" #include #include "sample-util.h" #include "play-memchunk.h" #include "xmalloc.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "namereg.h" #include "sound-file.h" #include "util.h" diff --git a/src/polypcore/scache.h b/src/polypcore/core-scache.h similarity index 97% rename from src/polypcore/scache.h rename to src/polypcore/core-scache.h index d667ae60c..0918ebe47 100644 --- a/src/polypcore/scache.h +++ b/src/polypcore/core-scache.h @@ -1,5 +1,5 @@ -#ifndef fooscachehfoo -#define fooscachehfoo +#ifndef foocorescachehfoo +#define foocorescachehfoo /* $Id$ */ diff --git a/src/polypcore/subscribe.c b/src/polypcore/core-subscribe.c similarity index 99% rename from src/polypcore/subscribe.c rename to src/polypcore/core-subscribe.c index e8b3c8418..2a258604d 100644 --- a/src/polypcore/subscribe.c +++ b/src/polypcore/core-subscribe.c @@ -27,7 +27,7 @@ #include #include "queue.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "xmalloc.h" #include "log.h" diff --git a/src/polypcore/subscribe.h b/src/polypcore/core-subscribe.h similarity index 95% rename from src/polypcore/subscribe.h rename to src/polypcore/core-subscribe.h index 625159e37..bc9dcba3d 100644 --- a/src/polypcore/subscribe.h +++ b/src/polypcore/core-subscribe.h @@ -1,5 +1,5 @@ -#ifndef foosubscribehfoo -#define foosubscribehfoo +#ifndef foocoresubscribehfoo +#define foocoresubscribehfoo /* $Id$ */ diff --git a/src/polypcore/core.c b/src/polypcore/core.c index 678e8212c..9d040e687 100644 --- a/src/polypcore/core.c +++ b/src/polypcore/core.c @@ -34,10 +34,10 @@ #include "source.h" #include "namereg.h" #include "util.h" -#include "scache.h" +#include "core-scache.h" #include "autoload.h" #include "xmalloc.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "props.h" #include "random.h" diff --git a/src/polypcore/core.h b/src/polypcore/core.h index f7a90169a..293290254 100644 --- a/src/polypcore/core.h +++ b/src/polypcore/core.h @@ -31,7 +31,7 @@ typedef struct pa_core pa_core; #include "memblock.h" #include "resampler.h" #include "queue.h" -#include "subscribe.h" +#include "core-subscribe.h" /* The core structure of polypaudio. Every polypaudio daemon contains * exactly one of these. It is used for storing kind of global diff --git a/src/polypcore/module.c b/src/polypcore/module.c index 499ea2990..73ec5bd40 100644 --- a/src/polypcore/module.c +++ b/src/polypcore/module.c @@ -32,7 +32,7 @@ #include "module.h" #include "xmalloc.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "log.h" #include "util.h" diff --git a/src/polypcore/namereg.c b/src/polypcore/namereg.c index 07fb485c8..ca03c455d 100644 --- a/src/polypcore/namereg.c +++ b/src/polypcore/namereg.c @@ -34,7 +34,7 @@ #include "source.h" #include "sink.h" #include "xmalloc.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "util.h" struct namereg_entry { diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 14f237c75..d2c0f3546 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -39,7 +39,7 @@ #include "source-output.h" #include "source.h" #include -#include "scache.h" +#include "core-scache.h" #include "sample-util.h" #include "authkey.h" #include "namereg.h" diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index b94903d9c..31983bc26 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -40,10 +40,10 @@ #include "pstream-util.h" #include "authkey.h" #include "namereg.h" -#include "scache.h" +#include "core-scache.h" #include "xmalloc.h" #include "util.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "log.h" #include "autoload.h" #include "authkey-prop.h" diff --git a/src/polypcore/sink-input.c b/src/polypcore/sink-input.c index f447b8cf8..696c47a4d 100644 --- a/src/polypcore/sink-input.c +++ b/src/polypcore/sink-input.c @@ -31,7 +31,7 @@ #include "sink-input.h" #include "sample-util.h" #include "xmalloc.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "log.h" #define CONVERT_BUFFER_LENGTH 4096 diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index f29afba73..6c143463b 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -34,7 +34,7 @@ #include "util.h" #include "sample-util.h" #include "xmalloc.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "log.h" #include diff --git a/src/polypcore/source-output.c b/src/polypcore/source-output.c index e1d8ccf72..9b75a8b0d 100644 --- a/src/polypcore/source-output.c +++ b/src/polypcore/source-output.c @@ -30,7 +30,7 @@ #include "source-output.h" #include "xmalloc.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "log.h" pa_source_output* pa_source_output_new( diff --git a/src/polypcore/source.c b/src/polypcore/source.c index 6e377b20e..c64f7b990 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -32,7 +32,7 @@ #include "source-output.h" #include "namereg.h" #include "xmalloc.h" -#include "subscribe.h" +#include "core-subscribe.h" #include "log.h" pa_source* pa_source_new( From 2e0dcc4ff0cbe23d6ac5033f754692f9b4cff36f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Feb 2006 23:48:41 +0000 Subject: [PATCH 0404/1514] include header files in simple.h with <> instead of "" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@497 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/simple.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/polyp/simple.h b/src/polyp/simple.h index 270cbb24a..afb25c8e0 100644 --- a/src/polyp/simple.h +++ b/src/polyp/simple.h @@ -24,8 +24,8 @@ #include -#include "sample.h" -#include "def.h" +#include +#include #include /** \file From b9513089f57d4ee692c12d911823e6f8f1cc6129 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Feb 2006 00:11:54 +0000 Subject: [PATCH 0405/1514] fix doxygen git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@498 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doxygen/doxygen.conf.in | 12 ++++++------ src/polyp/context.h | 2 +- src/polyp/glib-mainloop.h | 2 +- src/polyp/mainloop-api.h | 6 +++--- src/polyp/mainloop-signal.h | 2 +- src/polyp/mainloop.h | 3 +-- src/polyp/operation.h | 2 +- src/polyp/polypaudio.h | 4 ++-- src/polyp/simple.h | 2 +- src/polyp/stream.h | 2 +- 10 files changed, 18 insertions(+), 19 deletions(-) diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index c0e122ea8..fcda21947 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -170,7 +170,7 @@ DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. -TAB_SIZE = 8 +TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../polyp/polyplib-context.h ../polyp/polyplib-stream.h ../polyp/polyplib.h ../polyp/sample.h ../polyp/polyplib-def.h ../polyp/polyplib-subscribe.h ../polyp/polyplib-introspect.h ../polyp/polyplib-scache.h ../polyp/mainloop-api.h ../polyp/cdecl.h ../polyp/glib-mainloop.h ../polyp/mainloop.h ../polyp/mainloop-signal.h ../polyp/polyplib-error.h ../polyp/polyplib-operation.h ../polyp/polyplib-simple.h ../polyp/polyplib-version.h +INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/cdecl.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -455,7 +455,7 @@ EXCLUDE_PATTERNS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = ../polyp/ +EXAMPLE_PATH = ../src/utils ../src/tests # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -550,7 +550,7 @@ VERBATIM_HEADERS = YES # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. -ALPHABETICAL_INDEX = NO +ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns @@ -563,7 +563,7 @@ COLS_IN_ALPHA_INDEX = 5 # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. -IGNORE_PREFIX = +IGNORE_PREFIX = pa_ PA_ #--------------------------------------------------------------------------- # configuration options related to the HTML output @@ -660,7 +660,7 @@ DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. -ENUM_VALUES_PER_LINE = 4 +ENUM_VALUES_PER_LINE = 1 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that diff --git a/src/polyp/context.h b/src/polyp/context.h index 216d7d87d..4efd51564 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -49,7 +49,7 @@ PA_C_DECL_BEGIN -/** \pa_context +/** \struct pa_context * An opaque connection context to a daemon */ typedef struct pa_context pa_context; diff --git a/src/polyp/glib-mainloop.h b/src/polyp/glib-mainloop.h index b4815ed92..e052cff3b 100644 --- a/src/polyp/glib-mainloop.h +++ b/src/polyp/glib-mainloop.h @@ -32,7 +32,7 @@ PA_C_DECL_BEGIN -/** \pa_glib_mainloop +/** \struct pa_glib_mainloop * An opaque GLIB main loop object */ typedef struct pa_glib_mainloop pa_glib_mainloop; diff --git a/src/polyp/mainloop-api.h b/src/polyp/mainloop-api.h index 91ee41114..7bc7522ce 100644 --- a/src/polyp/mainloop-api.h +++ b/src/polyp/mainloop-api.h @@ -53,15 +53,15 @@ typedef enum pa_io_event_flags { PA_IO_EVENT_ERROR = 8 /**< Error event */ } pa_io_event_flags_t; -/** \pa_io_event +/** \struct pa_io_event * An opaque IO event source object */ typedef struct pa_io_event pa_io_event; -/** \pa_defer_event +/** \struct pa_defer_event * An opaque deferred event source object. Events of this type are triggered once in every main loop iteration */ typedef struct pa_defer_event pa_defer_event; -/** \pa_time_event +/** \struct pa_time_event * An opaque timer event source object */ typedef struct pa_time_event pa_time_event; diff --git a/src/polyp/mainloop-signal.h b/src/polyp/mainloop-signal.h index 76065b222..0291f4261 100644 --- a/src/polyp/mainloop-signal.h +++ b/src/polyp/mainloop-signal.h @@ -42,7 +42,7 @@ int pa_signal_init(pa_mainloop_api *api); /** Cleanup the signal subsystem */ void pa_signal_done(void); -/** \pa_signal_event +/** \struct pa_signal_event * An opaque UNIX signal event source object */ typedef struct pa_signal_event pa_signal_event; diff --git a/src/polyp/mainloop.h b/src/polyp/mainloop.h index 691f8c50c..eeb238843 100644 --- a/src/polyp/mainloop.h +++ b/src/polyp/mainloop.h @@ -35,7 +35,7 @@ PA_C_DECL_BEGIN * defined in \ref mainloop-api.h. This implementation is thread safe * as long as you access the main loop object from a single thread only.*/ -/** \pa_mainloop +/** \struct pa_mainloop * An opaque main loop object */ typedef struct pa_mainloop pa_mainloop; @@ -46,7 +46,6 @@ pa_mainloop *pa_mainloop_new(void); /** Free a main loop object */ void pa_mainloop_free(pa_mainloop* m); - /** Prepare for a single iteration of the main loop. Returns a negative value on error or exit request. timeout specifies a maximum timeout for the subsequent poll, or -1 for blocking behaviour. Defer events are also dispatched when this diff --git a/src/polyp/operation.h b/src/polyp/operation.h index 6a24d6495..d286b0c13 100644 --- a/src/polyp/operation.h +++ b/src/polyp/operation.h @@ -30,7 +30,7 @@ PA_C_DECL_BEGIN -/** \pa_operation +/** \struct pa_operation * An asynchronous operation object */ typedef struct pa_operation pa_operation; diff --git a/src/polyp/polypaudio.h b/src/polyp/polypaudio.h index c6014bbb4..c81fdfdb0 100644 --- a/src/polyp/polypaudio.h +++ b/src/polyp/polypaudio.h @@ -70,8 +70,8 @@ * described in \ref mainloop-api.h. Two distinct implementations are * available: * - * \li \ref mainloop.h: a minimal but fast implementation based on poll() - * \li \ref glib-mainloop.h: a wrapper around GLIB's main loop + * \li \ref mainloop.h : a minimal but fast implementation based on poll() + * \li \ref glib-mainloop.h : a wrapper around GLIB's main loop * * UNIX signals may be hooked to a main loop using the functions from * \ref mainloop-signal.h diff --git a/src/polyp/simple.h b/src/polyp/simple.h index afb25c8e0..1a139005e 100644 --- a/src/polyp/simple.h +++ b/src/polyp/simple.h @@ -41,7 +41,7 @@ PA_C_DECL_BEGIN -/** \pa_simple +/** \struct pa_simple * An opaque simple connection object */ typedef struct pa_simple pa_simple; diff --git a/src/polyp/stream.h b/src/polyp/stream.h index e2cab19e9..e20cfdd49 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -36,7 +36,7 @@ PA_C_DECL_BEGIN -/** \pa_stream +/** \struct pa_stream * An opaque stream for playback or recording */ typedef struct pa_stream pa_stream; From c278bc6c370faa5f38de0dcdffee4e301b5f9f1a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 09:12:06 +0000 Subject: [PATCH 0406/1514] Move the util libs to the modules section since they're in that directory. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@499 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 50 ++++++++++++++++--------------------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 7d87a1199..1e898a85f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -538,21 +538,6 @@ modlib_LTLIBRARIES += \ libx11prop.la endif -if HAVE_OSS -modlib_LTLIBRARIES += \ - liboss-util.la -endif - -if HAVE_ALSA -modlib_LTLIBRARIES += \ - libalsa-util.la -endif - -if HAVE_HOWL -modlib_LTLIBRARIES += \ - libhowl-wrap.la -endif - libprotocol_simple_la_SOURCES = polypcore/protocol-simple.c polypcore/protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-server.la libiochannel.la @@ -649,25 +634,6 @@ libx11prop_la_LDFLAGS = -avoid-version libx11prop_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) -# OSS - -liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h -liboss_util_la_LDFLAGS = -avoid-version - -# ALSA - -libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h -libalsa_util_la_LDFLAGS = -avoid-version -libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) -libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) - -# HOWL - -libhowl_wrap_la_SOURCES = modules/howl-wrap.c modules/howl-wrap.h -libhowl_wrap_la_LDFLAGS = -avoid-version -libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) -libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) - ################################### # Plug-in libraries # ################################### @@ -727,12 +693,14 @@ endif if HAVE_OSS modlib_LTLIBRARIES += \ + liboss-util.la \ module-oss.la \ module-oss-mmap.la endif if HAVE_ALSA modlib_LTLIBRARIES += \ + libalsa-util.la \ module-alsa-sink.la \ module-alsa-source.la endif @@ -744,6 +712,7 @@ endif if HAVE_HOWL modlib_LTLIBRARIES += \ + libhowl-wrap.la \ module-zeroconf-publish.la endif @@ -971,6 +940,9 @@ module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EX # OSS +liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h +liboss_util_la_LDFLAGS = -avoid-version + module_oss_la_SOURCES = modules/module-oss.c module_oss_la_LDFLAGS = -module -avoid-version module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la @@ -981,6 +953,11 @@ module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la # ALSA +libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h +libalsa_util_la_LDFLAGS = -avoid-version +libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) +libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) + module_alsa_sink_la_SOURCES = modules/module-alsa-sink.c module_alsa_sink_la_LDFLAGS = -module -avoid-version module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la @@ -999,6 +976,11 @@ module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la # HOWL +libhowl_wrap_la_SOURCES = modules/howl-wrap.c modules/howl-wrap.h +libhowl_wrap_la_LDFLAGS = -avoid-version +libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) +libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) + module_zeroconf_publish_la_SOURCES = modules/module-zeroconf-publish.c module_zeroconf_publish_la_LDFLAGS = -module -avoid-version module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la From 5eda18bf608a325c136a450e58fa154eb0b270f4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 12:10:58 +0000 Subject: [PATCH 0407/1514] Cleaned up the includes after the restructuring. Indicate which headers are public and which are internal through <> vs "". git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@500 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/caps.c | 1 + src/daemon/cmdline.c | 3 +- src/daemon/cpulimit.c | 3 +- src/daemon/daemon-conf.c | 3 +- src/daemon/dumpmodules.c | 3 +- src/daemon/main.c | 20 +++++++------ src/modules/howl-wrap.c | 7 +++-- src/modules/howl-wrap.h | 2 +- src/modules/module-alsa-sink.c | 2 +- src/modules/module-alsa-source.c | 2 +- src/modules/module-oss.c | 2 +- src/modules/module-protocol-stub.c | 2 +- src/modules/module-zeroconf-publish.c | 8 ++++-- src/polyp/browser.c | 3 +- src/polyp/browser.h | 1 - src/polyp/client-conf-x11.c | 3 +- src/polyp/client-conf-x11.h | 2 +- src/polyp/client-conf.c | 2 +- src/polyp/client-conf.h | 2 +- src/polyp/context.c | 14 +++++---- src/polyp/error.c | 3 +- src/polyp/glib-mainloop.c | 5 ++-- src/polyp/glib12-mainloop.c | 3 +- src/polyp/internal.h | 11 +++---- src/polyp/introspect.c | 11 ++++--- src/polyp/mainloop-api.c | 5 ++-- src/polyp/mainloop-signal.c | 3 +- src/polyp/mainloop.c | 5 ++-- src/polyp/operation.c | 2 ++ src/polyp/scache.c | 6 ++-- src/polyp/simple.c | 8 ++++-- src/polyp/stream.c | 3 +- src/polyp/subscribe.c | 8 ++++-- src/polyp/version.h.in | 2 ++ src/polypcore/authkey-prop.c | 7 +++-- src/polypcore/authkey-prop.h | 2 +- src/polypcore/authkey.c | 7 +++-- src/polypcore/autoload.c | 15 +++++----- src/polypcore/autoload.h | 2 +- src/polypcore/cli-command.c | 39 ++++++++++++------------- src/polypcore/cli-command.h | 4 +-- src/polypcore/cli-text.c | 25 ++++++++-------- src/polypcore/cli-text.h | 2 +- src/polypcore/cli.c | 29 ++++++++++--------- src/polypcore/cli.h | 6 ++-- src/polypcore/client.c | 7 +++-- src/polypcore/client.h | 4 +-- src/polypcore/conf-parser.c | 7 +++-- src/polypcore/core-scache.c | 21 +++++++------- src/polypcore/core-scache.h | 6 ++-- src/polypcore/core-subscribe.c | 7 +++-- src/polypcore/core-subscribe.h | 4 +-- src/polypcore/core.c | 23 ++++++++------- src/polypcore/core.h | 12 ++++---- src/polypcore/dynarray.c | 3 +- src/polypcore/hashmap.c | 7 +++-- src/polypcore/idxset.c | 3 +- src/polypcore/iochannel.c | 7 +++-- src/polypcore/ioline.c | 5 ++-- src/polypcore/ioline.h | 4 +-- src/polypcore/log.c | 5 ++-- src/polypcore/log.h | 2 +- src/polypcore/mcalign.c | 3 +- src/polypcore/mcalign.h | 4 +-- src/polypcore/memblock.c | 3 +- src/polypcore/memblockq.c | 7 +++-- src/polypcore/memblockq.h | 4 +-- src/polypcore/memchunk.c | 3 +- src/polypcore/memchunk.h | 2 +- src/polypcore/modargs.c | 17 +++++------ src/polypcore/modargs.h | 2 +- src/polypcore/modinfo.c | 7 +++-- src/polypcore/module.c | 9 +++--- src/polypcore/module.h | 4 +-- src/polypcore/namereg.c | 13 +++++---- src/polypcore/namereg.h | 2 +- src/polypcore/packet.c | 3 +- src/polypcore/parseaddr.c | 5 ++-- src/polypcore/pdispatch.c | 11 +++---- src/polypcore/pdispatch.h | 4 +-- src/polypcore/pid.c | 5 ++-- src/polypcore/play-memchunk.c | 7 +++-- src/polypcore/play-memchunk.h | 4 +-- src/polypcore/poll.c | 3 +- src/polypcore/props.c | 5 ++-- src/polypcore/props.h | 4 +-- src/polypcore/protocol-cli.c | 7 +++-- src/polypcore/protocol-cli.h | 8 +++--- src/polypcore/protocol-esound.c | 32 +++++++++++---------- src/polypcore/protocol-esound.h | 8 +++--- src/polypcore/protocol-http.c | 11 +++---- src/polypcore/protocol-http.h | 8 +++--- src/polypcore/protocol-native.c | 41 ++++++++++++++------------- src/polypcore/protocol-native.h | 8 +++--- src/polypcore/protocol-simple.c | 15 +++++----- src/polypcore/protocol-simple.h | 8 +++--- src/polypcore/pstream-util.c | 3 +- src/polypcore/pstream-util.h | 4 +-- src/polypcore/pstream.c | 7 +++-- src/polypcore/pstream.h | 8 +++--- src/polypcore/queue.c | 3 +- src/polypcore/random.c | 5 ++-- src/polypcore/resampler.c | 7 +++-- src/polypcore/resampler.h | 4 +-- src/polypcore/sample-util.c | 3 +- src/polypcore/sample-util.h | 4 +-- src/polypcore/sconv-s16le.c | 6 ++-- src/polypcore/sconv.c | 7 +++-- src/polypcore/sink-input.c | 9 +++--- src/polypcore/sink-input.h | 10 +++---- src/polypcore/sink.c | 17 +++++------ src/polypcore/sink.h | 8 +++--- src/polypcore/sioman.c | 1 + src/polypcore/socket-client.c | 11 +++---- src/polypcore/socket-client.h | 2 +- src/polypcore/socket-server.c | 9 +++--- src/polypcore/socket-server.h | 2 +- src/polypcore/socket-util.c | 7 +++-- src/polypcore/sound-file-stream.c | 7 +++-- src/polypcore/sound-file-stream.h | 2 +- src/polypcore/sound-file.c | 5 ++-- src/polypcore/sound-file.h | 2 +- src/polypcore/source-output.c | 7 +++-- src/polypcore/source-output.h | 10 +++---- src/polypcore/source.c | 11 +++---- src/polypcore/source.h | 13 +++++---- src/polypcore/strbuf.h | 2 +- src/polypcore/strlist.c | 7 +++-- src/polypcore/tagstruct.c | 3 +- src/polypcore/tokenizer.c | 7 +++-- src/polypcore/util.c | 5 ++-- src/polypcore/util.h | 2 +- src/polypcore/x11wrap.c | 9 +++--- src/polypcore/x11wrap.h | 2 +- src/polypcore/xmalloc.c | 7 +++-- src/tests/cpulimit-test.c | 3 +- src/utils/pax11publish.c | 3 +- 137 files changed, 524 insertions(+), 422 deletions(-) diff --git a/src/daemon/caps.c b/src/daemon/caps.c index 8d4294594..e12d33fb0 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -33,6 +33,7 @@ #endif #include + #include "caps.h" #ifdef HAVE_GETUID diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index 0b5f9ec75..b6ab1283a 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -30,11 +30,12 @@ #include #include -#include "cmdline.h" #include #include #include +#include "cmdline.h" + /* Argument codes for getopt_long() */ enum { ARG_HELP = 256, diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index 6887796f2..d7a24b8e9 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -23,10 +23,11 @@ #include #endif -#include "cpulimit.h" #include #include +#include "cpulimit.h" + #ifdef HAVE_SIGXCPU #include diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 8fe3c4cc5..ecabce401 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -29,13 +29,14 @@ #include #include -#include "daemon-conf.h" #include #include #include #include #include +#include "daemon-conf.h" + #ifndef DEFAULT_CONFIG_DIR # ifndef OS_IS_WIN32 # define DEFAULT_CONFIG_DIR "/etc/polypaudio" diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c index 8d8eb0b9f..bf29a6816 100644 --- a/src/daemon/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -29,10 +29,11 @@ #include #include -#include "dumpmodules.h" #include #include +#include "dumpmodules.h" + #define PREFIX "module-" static void short_info(const char *name, PA_GCC_UNUSED const char *path, pa_modinfo *i) { diff --git a/src/daemon/main.c b/src/daemon/main.c index 6be83d8c1..638c2f3fd 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -47,27 +47,29 @@ #include #endif -#include +#include "../polypcore/winsock.h" + +#include +#include #include #include -#include #include -#include -#include "cmdline.h" #include +#include #include #include #include -#include "cpulimit.h" -#include -#include "daemon-conf.h" -#include "dumpmodules.h" -#include "caps.h" #include #include #include +#include "cmdline.h" +#include "cpulimit.h" +#include "daemon-conf.h" +#include "dumpmodules.h" +#include "caps.h" + #ifdef HAVE_LIBWRAP /* Only one instance of these variables */ int allow_severity = LOG_INFO; diff --git a/src/modules/howl-wrap.c b/src/modules/howl-wrap.c index 77d096ac2..b3acde55a 100644 --- a/src/modules/howl-wrap.c +++ b/src/modules/howl-wrap.c @@ -21,10 +21,11 @@ #include +#include +#include +#include + #include "howl-wrap.h" -#include "log.h" -#include "xmalloc.h" -#include "props.h" #define HOWL_PROPERTY "howl" diff --git a/src/modules/howl-wrap.h b/src/modules/howl-wrap.h index a670b082b..42c26ef2f 100644 --- a/src/modules/howl-wrap.h +++ b/src/modules/howl-wrap.h @@ -24,7 +24,7 @@ #include -#include "core.h" +#include pa_howl_wrapper; diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index d3fe71a57..6ea1e1372 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -44,8 +44,8 @@ #include #include -#include "module-alsa-sink-symdef.h" #include "alsa-util.h" +#include "module-alsa-sink-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ALSA Sink") diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 9453f8461..4f281aa76 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -44,8 +44,8 @@ #include #include -#include "module-alsa-source-symdef.h" #include "alsa-util.h" +#include "module-alsa-source-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ALSA Source") diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 264e8792e..fe43c45e5 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -45,8 +45,8 @@ #include #include -#include "module-oss-symdef.h" #include "oss-util.h" +#include "module-oss-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("OSS Sink/Source") diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 469ddceea..b69716cc7 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -40,7 +40,7 @@ #include #endif -#include +#include "../polypcore/winsock.h" #include #include diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 45d566aee..d2858aac0 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -37,11 +36,14 @@ #include #include #include -#include +#include #include -#include #include +#include "../polypcore/endianmacros.h" + +#include "howl-wrap.h" + #include "module-zeroconf-publish-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") diff --git a/src/polyp/browser.c b/src/polyp/browser.c index 80051d545..482bab81e 100644 --- a/src/polyp/browser.c +++ b/src/polyp/browser.c @@ -22,11 +22,12 @@ #include #include -#include "browser.h" #include #include #include +#include "browser.h" + #define SERVICE_NAME_SINK "_polypaudio-sink._tcp." #define SERVICE_NAME_SOURCE "_polypaudio-source._tcp." #define SERVICE_NAME_SERVER "_polypaudio-server._tcp." diff --git a/src/polyp/browser.h b/src/polyp/browser.h index 3bb0d2649..043b818af 100644 --- a/src/polyp/browser.h +++ b/src/polyp/browser.h @@ -25,7 +25,6 @@ #include #include #include -#include PA_C_DECL_BEGIN diff --git a/src/polyp/client-conf-x11.c b/src/polyp/client-conf-x11.c index 83d0bd2e4..9e863bc78 100644 --- a/src/polyp/client-conf-x11.c +++ b/src/polyp/client-conf-x11.c @@ -29,12 +29,13 @@ #include #include -#include "client-conf-x11.h" #include #include #include #include +#include "client-conf-x11.h" + int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { Display *d = NULL; int ret = -1; diff --git a/src/polyp/client-conf-x11.h b/src/polyp/client-conf-x11.h index 80841171b..64459224f 100644 --- a/src/polyp/client-conf-x11.h +++ b/src/polyp/client-conf-x11.h @@ -22,7 +22,7 @@ USA. ***/ -#include +#include "client-conf.h" /* Load client configuration data from the specified X11 display, * overwriting the current settings in *c */ diff --git a/src/polyp/client-conf.c b/src/polyp/client-conf.c index 2df201cee..328d01c98 100644 --- a/src/polyp/client-conf.c +++ b/src/polyp/client-conf.c @@ -35,7 +35,7 @@ #include #include -#include +#include "client-conf.h" #ifndef DEFAULT_CONFIG_DIR # ifndef OS_IS_WIN32 diff --git a/src/polyp/client-conf.h b/src/polyp/client-conf.h index 2d8a019f4..de3efae70 100644 --- a/src/polyp/client-conf.h +++ b/src/polyp/client-conf.h @@ -22,7 +22,7 @@ USA. ***/ -#include "../polypcore/native-common.h" +#include /* A structure containing configuration data for polypaudio clients. */ diff --git a/src/polyp/context.c b/src/polyp/context.c index 4ac11caa4..b7f7eb997 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -45,11 +45,10 @@ #include #endif -#include +#include "../polypcore/winsock.h" + +#include -#include "internal.h" -#include "context.h" -#include "version.h" #include #include #include @@ -59,13 +58,18 @@ #include #include #include -#include #include +#include "internal.h" + +#include "client-conf.h" + #ifdef HAVE_X11 #include "client-conf-x11.h" #endif +#include "context.h" + #define AUTOSPAWN_LOCK "autospawn.lock" static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = { diff --git a/src/polyp/error.c b/src/polyp/error.c index a137ab494..ece77bf2c 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -26,9 +26,10 @@ #include #include -#include "error.h" #include +#include "error.h" + static const char* const errortab[PA_ERROR_MAX] = { [PA_ERROR_OK] = "OK", [PA_ERROR_ACCESS] = "Access denied", diff --git a/src/polyp/glib-mainloop.c b/src/polyp/glib-mainloop.c index 962eb5742..3937a1a9f 100644 --- a/src/polyp/glib-mainloop.c +++ b/src/polyp/glib-mainloop.c @@ -25,12 +25,13 @@ #include -#include #include #include -#include "glib.h" #include +#include "glib.h" +#include "glib-mainloop.h" + struct pa_io_event { pa_glib_mainloop *mainloop; int dead; diff --git a/src/polyp/glib12-mainloop.c b/src/polyp/glib12-mainloop.c index 80a02b1c2..5ad23adba 100644 --- a/src/polyp/glib12-mainloop.c +++ b/src/polyp/glib12-mainloop.c @@ -25,11 +25,12 @@ #include -#include #include #include #include +#include "glib-mainloop.h" + /* A mainloop implementation based on GLIB 1.2 */ struct pa_io_event { diff --git a/src/polyp/internal.h b/src/polyp/internal.h index bdfd5d8ec..762688c98 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -23,20 +23,21 @@ ***/ #include +#include +#include +#include + #include #include #include #include - -#include "context.h" -#include "stream.h" -#include "operation.h" #include #include -#include #include #include +#include "client-conf.h" + #define DEFAULT_TIMEOUT (10) struct pa_context { diff --git a/src/polyp/introspect.c b/src/polyp/introspect.c index d89eb9ede..4af724b43 100644 --- a/src/polyp/introspect.c +++ b/src/polyp/introspect.c @@ -25,11 +25,14 @@ #include -#include "introspect.h" -#include "context.h" -#include "internal.h" -#include +#include + #include +#include + +#include "internal.h" + +#include "introspect.h" /*** Statistics ***/ diff --git a/src/polyp/mainloop-api.c b/src/polyp/mainloop-api.c index a3eaee9c6..71f55c05d 100644 --- a/src/polyp/mainloop-api.c +++ b/src/polyp/mainloop-api.c @@ -26,9 +26,10 @@ #include #include -#include "mainloop-api.h" -#include #include +#include + +#include "mainloop-api.h" struct once_info { void (*callback)(pa_mainloop_api*m, void *userdata); diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index a03c91596..e474f4617 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -36,12 +36,13 @@ #include #endif -#include #include #include #include #include +#include "mainloop-signal.h" + struct pa_signal_event { int sig; #ifdef HAVE_SIGACTION diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 3fa9245ca..71ea9bc41 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -38,14 +38,15 @@ #include "poll.h" #endif -#include +#include "../polypcore/winsock.h" -#include "mainloop.h" #include #include #include #include +#include "mainloop.h" + struct pa_io_event { pa_mainloop *mainloop; int dead; diff --git a/src/polyp/operation.c b/src/polyp/operation.c index 0baa661b5..5440cf9ea 100644 --- a/src/polyp/operation.c +++ b/src/polyp/operation.c @@ -26,7 +26,9 @@ #include #include + #include "internal.h" + #include "operation.h" pa_operation *pa_operation_new(pa_context *c, pa_stream *s) { diff --git a/src/polyp/scache.c b/src/polyp/scache.c index c274e3597..393b069e6 100644 --- a/src/polyp/scache.c +++ b/src/polyp/scache.c @@ -28,10 +28,12 @@ #include #include -#include "scache.h" -#include "internal.h" #include +#include "internal.h" + +#include "scache.h" + void pa_stream_connect_upload(pa_stream *s, size_t length) { pa_tagstruct *t; uint32_t tag; diff --git a/src/polyp/simple.c b/src/polyp/simple.c index 19c49c9b9..e14cab2eb 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -28,13 +28,15 @@ #include #include -#include "simple.h" -#include "polypaudio.h" -#include "mainloop.h" +#include +#include + #include #include #include +#include "simple.h" + struct pa_simple { pa_mainloop *mainloop; pa_context *context; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 007d5e24f..6e5bc0671 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -28,12 +28,13 @@ #include #include -#include "internal.h" #include #include #include #include +#include "internal.h" + #define LATENCY_IPOL_INTERVAL_USEC (10000L) pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) { diff --git a/src/polyp/subscribe.c b/src/polyp/subscribe.c index c481f5255..b90e0bf1d 100644 --- a/src/polyp/subscribe.c +++ b/src/polyp/subscribe.c @@ -26,10 +26,12 @@ #include #include -#include "subscribe.h" -#include "internal.h" -#include #include +#include + +#include "internal.h" + +#include "subscribe.h" void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; diff --git a/src/polyp/version.h.in b/src/polyp/version.h.in index c727381f3..67b7495b8 100644 --- a/src/polyp/version.h.in +++ b/src/polyp/version.h.in @@ -24,6 +24,8 @@ /* WARNING: Make sure to edit the real source file version.h.in! */ +#include + /** \file * Define header version */ diff --git a/src/polypcore/authkey-prop.c b/src/polypcore/authkey-prop.c index 8657f5a50..3faf0ef1f 100644 --- a/src/polypcore/authkey-prop.c +++ b/src/polypcore/authkey-prop.c @@ -22,10 +22,11 @@ #include #include -#include "xmalloc.h" +#include +#include +#include + #include "authkey-prop.h" -#include "props.h" -#include "log.h" struct authkey_data { int ref; diff --git a/src/polypcore/authkey-prop.h b/src/polypcore/authkey-prop.h index 29b40bb23..63fde5d8d 100644 --- a/src/polypcore/authkey-prop.h +++ b/src/polypcore/authkey-prop.h @@ -22,7 +22,7 @@ USA. ***/ -#include "core.h" +#include /* The authkey-prop uses a central property to store a previously * loaded cookie in memory. Useful for sharing the same cookie between diff --git a/src/polypcore/authkey.c b/src/polypcore/authkey.c index 969f09d90..e3fc9f607 100644 --- a/src/polypcore/authkey.c +++ b/src/polypcore/authkey.c @@ -35,10 +35,11 @@ #include #include +#include +#include +#include + #include "authkey.h" -#include "util.h" -#include "log.h" -#include "random.h" /* Generate a new authorization key, store it in file fd and return it in *data */ static int generate(int fd, void *ret_data, size_t length) { diff --git a/src/polypcore/autoload.c b/src/polypcore/autoload.c index 83df8ef7f..8d2dca30f 100644 --- a/src/polypcore/autoload.c +++ b/src/polypcore/autoload.c @@ -27,14 +27,15 @@ #include #include +#include +#include +#include +#include +#include +#include +#include + #include "autoload.h" -#include "module.h" -#include "xmalloc.h" -#include "memchunk.h" -#include "sound-file.h" -#include "log.h" -#include "core-scache.h" -#include "core-subscribe.h" static void entry_free(pa_autoload_entry *e) { assert(e); diff --git a/src/polypcore/autoload.h b/src/polypcore/autoload.h index 7350c16a9..a8931fc7e 100644 --- a/src/polypcore/autoload.h +++ b/src/polypcore/autoload.h @@ -22,7 +22,7 @@ USA. ***/ -#include "namereg.h" +#include /* Using the autoloading facility, modules by be loaded on-demand and * synchronously. The user may register a "ghost sink" or "ghost diff --git a/src/polypcore/cli-command.c b/src/polypcore/cli-command.c index dd4cbe463..6c9fc4b14 100644 --- a/src/polypcore/cli-command.c +++ b/src/polypcore/cli-command.c @@ -29,26 +29,27 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "cli-command.h" -#include "module.h" -#include "sink.h" -#include "source.h" -#include "client.h" -#include "sink-input.h" -#include "source-output.h" -#include "tokenizer.h" -#include "strbuf.h" -#include "namereg.h" -#include "cli-text.h" -#include "core-scache.h" -#include "sample-util.h" -#include "sound-file.h" -#include "play-memchunk.h" -#include "autoload.h" -#include "xmalloc.h" -#include "sound-file-stream.h" -#include "props.h" -#include "util.h" struct command { const char *name; diff --git a/src/polypcore/cli-command.h b/src/polypcore/cli-command.h index 78b8d5c6d..e7c70ecfe 100644 --- a/src/polypcore/cli-command.h +++ b/src/polypcore/cli-command.h @@ -22,8 +22,8 @@ USA. ***/ -#include "strbuf.h" -#include "core.h" +#include +#include /* Execute a single CLI command. Write the results to the string * buffer *buf. If *fail is non-zero the function will return -1 when diff --git a/src/polypcore/cli-text.c b/src/polypcore/cli-text.c index d8446b067..8bffd0a73 100644 --- a/src/polypcore/cli-text.c +++ b/src/polypcore/cli-text.c @@ -26,19 +26,20 @@ #include #include -#include "cli-text.h" -#include "module.h" -#include "client.h" -#include "sink.h" -#include "source.h" -#include "sink-input.h" -#include "source-output.h" -#include "strbuf.h" -#include "sample-util.h" -#include "core-scache.h" -#include "autoload.h" -#include "xmalloc.h" #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cli-text.h" char *pa_module_list_to_string(pa_core *c) { pa_strbuf *s; diff --git a/src/polypcore/cli-text.h b/src/polypcore/cli-text.h index 7a1a03610..a8f400035 100644 --- a/src/polypcore/cli-text.h +++ b/src/polypcore/cli-text.h @@ -22,7 +22,7 @@ USA. ***/ -#include "core.h" +#include /* Some functions to generate pretty formatted listings of * entities. The returned strings have to be freed manually. */ diff --git a/src/polypcore/cli.c b/src/polypcore/cli.c index bc0c285d3..295ce625d 100644 --- a/src/polypcore/cli.c +++ b/src/polypcore/cli.c @@ -28,21 +28,22 @@ #include #include -#include "ioline.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "cli.h" -#include "module.h" -#include "sink.h" -#include "source.h" -#include "client.h" -#include "sink-input.h" -#include "source-output.h" -#include "tokenizer.h" -#include "strbuf.h" -#include "namereg.h" -#include "cli-text.h" -#include "cli-command.h" -#include "xmalloc.h" -#include "log.h" #define PROMPT ">>> " diff --git a/src/polypcore/cli.h b/src/polypcore/cli.h index 03f31c22c..12ffd848f 100644 --- a/src/polypcore/cli.h +++ b/src/polypcore/cli.h @@ -22,9 +22,9 @@ USA. ***/ -#include "iochannel.h" -#include "core.h" -#include "module.h" +#include +#include +#include typedef struct pa_cli pa_cli; diff --git a/src/polypcore/client.c b/src/polypcore/client.c index 9b2567942..7fe5a9fc3 100644 --- a/src/polypcore/client.c +++ b/src/polypcore/client.c @@ -28,10 +28,11 @@ #include #include +#include +#include +#include + #include "client.h" -#include "xmalloc.h" -#include "core-subscribe.h" -#include "log.h" pa_client *pa_client_new(pa_core *core, const char *name, const char *driver) { pa_client *c; diff --git a/src/polypcore/client.h b/src/polypcore/client.h index 92430338f..8ddc6d942 100644 --- a/src/polypcore/client.h +++ b/src/polypcore/client.h @@ -22,8 +22,8 @@ USA. ***/ -#include "core.h" -#include "module.h" +#include +#include /* Every connection to the server should have a pa_client * attached. That way the user may generate a listing of all connected diff --git a/src/polypcore/conf-parser.c b/src/polypcore/conf-parser.c index 507f2bf19..7eeda02b6 100644 --- a/src/polypcore/conf-parser.c +++ b/src/polypcore/conf-parser.c @@ -28,10 +28,11 @@ #include #include +#include +#include +#include + #include "conf-parser.h" -#include "log.h" -#include "util.h" -#include "xmalloc.h" #define WHITESPACE " \t\n" #define COMMENTS "#;\n" diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 0d926abaf..69199a33c 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -41,19 +41,20 @@ #include #endif -#include "core-scache.h" -#include "sink-input.h" #include -#include "sample-util.h" -#include "play-memchunk.h" -#include "xmalloc.h" -#include "core-subscribe.h" -#include "namereg.h" -#include "sound-file.h" -#include "util.h" -#include "log.h" #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core-scache.h" #define UNLOAD_POLL_TIME 2 diff --git a/src/polypcore/core-scache.h b/src/polypcore/core-scache.h index 0918ebe47..a383e50ac 100644 --- a/src/polypcore/core-scache.h +++ b/src/polypcore/core-scache.h @@ -22,9 +22,9 @@ USA. ***/ -#include "core.h" -#include "memchunk.h" -#include "sink.h" +#include +#include +#include typedef struct pa_scache_entry { pa_core *core; diff --git a/src/polypcore/core-subscribe.c b/src/polypcore/core-subscribe.c index 2a258604d..4d792966e 100644 --- a/src/polypcore/core-subscribe.c +++ b/src/polypcore/core-subscribe.c @@ -26,10 +26,11 @@ #include #include -#include "queue.h" +#include +#include +#include + #include "core-subscribe.h" -#include "xmalloc.h" -#include "log.h" /* The subscription subsystem may be used to be notified whenever an * entity (sink, source, ...) is created or deleted. Modules may diff --git a/src/polypcore/core-subscribe.h b/src/polypcore/core-subscribe.h index bc9dcba3d..7c8569542 100644 --- a/src/polypcore/core-subscribe.h +++ b/src/polypcore/core-subscribe.h @@ -25,8 +25,8 @@ typedef struct pa_subscription pa_subscription; typedef struct pa_subscription_event pa_subscription_event; -#include "core.h" -#include "native-common.h" +#include +#include pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata); void pa_subscription_free(pa_subscription*s); diff --git a/src/polypcore/core.c b/src/polypcore/core.c index 9d040e687..0093aebd7 100644 --- a/src/polypcore/core.c +++ b/src/polypcore/core.c @@ -28,18 +28,19 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "core.h" -#include "module.h" -#include "sink.h" -#include "source.h" -#include "namereg.h" -#include "util.h" -#include "core-scache.h" -#include "autoload.h" -#include "xmalloc.h" -#include "core-subscribe.h" -#include "props.h" -#include "random.h" pa_core* pa_core_new(pa_mainloop_api *m) { pa_core* c; diff --git a/src/polypcore/core.h b/src/polypcore/core.h index 293290254..a323ae8e1 100644 --- a/src/polypcore/core.h +++ b/src/polypcore/core.h @@ -24,14 +24,14 @@ typedef struct pa_core pa_core; -#include "idxset.h" -#include "hashmap.h" +#include +#include #include #include -#include "memblock.h" -#include "resampler.h" -#include "queue.h" -#include "core-subscribe.h" +#include +#include +#include +#include /* The core structure of polypaudio. Every polypaudio daemon contains * exactly one of these. It is used for storing kind of global diff --git a/src/polypcore/dynarray.c b/src/polypcore/dynarray.c index 435fd7686..1aff7f511 100644 --- a/src/polypcore/dynarray.c +++ b/src/polypcore/dynarray.c @@ -27,8 +27,9 @@ #include #include +#include + #include "dynarray.h" -#include "xmalloc.h" /* If the array becomes to small, increase its size by 100 entries */ #define INCREASE_BY 100 diff --git a/src/polypcore/hashmap.c b/src/polypcore/hashmap.c index a37decb8c..8861fd3df 100644 --- a/src/polypcore/hashmap.c +++ b/src/polypcore/hashmap.c @@ -27,10 +27,11 @@ #include #include +#include +#include +#include + #include "hashmap.h" -#include "idxset.h" -#include "xmalloc.h" -#include "log.h" #define BUCKETS 1023 diff --git a/src/polypcore/idxset.c b/src/polypcore/idxset.c index 409d1fab9..8d3a2370d 100644 --- a/src/polypcore/idxset.c +++ b/src/polypcore/idxset.c @@ -28,8 +28,9 @@ #include #include +#include + #include "idxset.h" -#include "xmalloc.h" typedef struct idxset_entry { void *data; diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index 273d47e0d..7fd091523 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -30,10 +30,11 @@ #include "winsock.h" +#include +#include +#include + #include "iochannel.h" -#include "util.h" -#include "socket-util.h" -#include "xmalloc.h" struct pa_iochannel { int ifd, ofd; diff --git a/src/polypcore/ioline.c b/src/polypcore/ioline.c index 5b669f5c5..3f2de5a2e 100644 --- a/src/polypcore/ioline.c +++ b/src/polypcore/ioline.c @@ -29,9 +29,10 @@ #include #include +#include +#include + #include "ioline.h" -#include "xmalloc.h" -#include "log.h" #define BUFFER_LIMIT (64*1024) #define READ_SIZE (1024) diff --git a/src/polypcore/ioline.h b/src/polypcore/ioline.h index 84ccb47a6..e2dadf557 100644 --- a/src/polypcore/ioline.h +++ b/src/polypcore/ioline.h @@ -22,8 +22,8 @@ USA. ***/ -#include "iochannel.h" -#include "util.h" +#include +#include /* An ioline wraps an iochannel for line based communication. A * callback function is called whenever a new line has been recieved diff --git a/src/polypcore/log.c b/src/polypcore/log.c index 97406f799..c7bf7be9e 100644 --- a/src/polypcore/log.c +++ b/src/polypcore/log.c @@ -31,9 +31,10 @@ #include #endif +#include +#include + #include "log.h" -#include "xmalloc.h" -#include "util.h" #define ENV_LOGLEVEL "POLYP_LOG" diff --git a/src/polypcore/log.h b/src/polypcore/log.h index ce8aea986..c306acaff 100644 --- a/src/polypcore/log.h +++ b/src/polypcore/log.h @@ -23,7 +23,7 @@ ***/ #include -#include "gccmacro.h" +#include /* A simple logging subsystem */ diff --git a/src/polypcore/mcalign.c b/src/polypcore/mcalign.c index 4d7656250..0f229e282 100644 --- a/src/polypcore/mcalign.c +++ b/src/polypcore/mcalign.c @@ -28,8 +28,9 @@ #include #include +#include + #include "mcalign.h" -#include "xmalloc.h" struct pa_mcalign { size_t base; diff --git a/src/polypcore/mcalign.h b/src/polypcore/mcalign.h index 5de75bc7c..a9107e0e4 100644 --- a/src/polypcore/mcalign.h +++ b/src/polypcore/mcalign.h @@ -22,8 +22,8 @@ USA. ***/ -#include "memblock.h" -#include "memchunk.h" +#include +#include /* An alignment object, used for aligning memchunks to multiples of * the frame size. */ diff --git a/src/polypcore/memblock.c b/src/polypcore/memblock.c index 8da535252..2c0bef57c 100644 --- a/src/polypcore/memblock.c +++ b/src/polypcore/memblock.c @@ -28,8 +28,9 @@ #include #include +#include + #include "memblock.h" -#include "xmalloc.h" static void stat_add(pa_memblock*m, pa_memblock_stat *s) { assert(m); diff --git a/src/polypcore/memblockq.c b/src/polypcore/memblockq.c index ba6b76eaa..4a0225e58 100644 --- a/src/polypcore/memblockq.c +++ b/src/polypcore/memblockq.c @@ -30,10 +30,11 @@ #include #include +#include +#include +#include + #include "memblockq.h" -#include "xmalloc.h" -#include "log.h" -#include "mcalign.h" struct memblock_list { struct memblock_list *next, *prev; diff --git a/src/polypcore/memblockq.h b/src/polypcore/memblockq.h index 1695dabad..7bb25f908 100644 --- a/src/polypcore/memblockq.h +++ b/src/polypcore/memblockq.h @@ -24,8 +24,8 @@ #include -#include "memblock.h" -#include "memchunk.h" +#include +#include /* A memblockq is a queue of pa_memchunks (yepp, the name is not * perfect). It is similar to the ring buffers used by most other diff --git a/src/polypcore/memchunk.c b/src/polypcore/memchunk.c index bfd74f9e4..d6856ab83 100644 --- a/src/polypcore/memchunk.c +++ b/src/polypcore/memchunk.c @@ -28,8 +28,9 @@ #include #include +#include + #include "memchunk.h" -#include "xmalloc.h" void pa_memchunk_make_writable(pa_memchunk *c, pa_memblock_stat *s, size_t min) { pa_memblock *n; diff --git a/src/polypcore/memchunk.h b/src/polypcore/memchunk.h index 4eefc8c10..3ddb28eeb 100644 --- a/src/polypcore/memchunk.h +++ b/src/polypcore/memchunk.h @@ -22,7 +22,7 @@ USA. ***/ -#include "memblock.h" +#include /* A memchunk describes a part of a memblock. In contrast to the memblock, a * memchunk is not allocated dynamically or reference counted, instead diff --git a/src/polypcore/modargs.c b/src/polypcore/modargs.c index 070629467..6bd13c3b7 100644 --- a/src/polypcore/modargs.c +++ b/src/polypcore/modargs.c @@ -28,15 +28,16 @@ #include #include -#include "hashmap.h" +#include +#include +#include +#include +#include +#include +#include +#include + #include "modargs.h" -#include "idxset.h" -#include "sample-util.h" -#include "namereg.h" -#include "sink.h" -#include "source.h" -#include "xmalloc.h" -#include "util.h" struct entry { char *key, *value; diff --git a/src/polypcore/modargs.h b/src/polypcore/modargs.h index 678ea1a74..47e2d522e 100644 --- a/src/polypcore/modargs.h +++ b/src/polypcore/modargs.h @@ -24,7 +24,7 @@ #include #include -#include "core.h" +#include typedef struct pa_modargs pa_modargs; diff --git a/src/polypcore/modinfo.c b/src/polypcore/modinfo.c index 534406127..4204bb34a 100644 --- a/src/polypcore/modinfo.c +++ b/src/polypcore/modinfo.c @@ -26,10 +26,11 @@ #include #include -#include "xmalloc.h" -#include "util.h" +#include +#include +#include + #include "modinfo.h" -#include "log.h" #define PA_SYMBOL_AUTHOR "pa__get_author" #define PA_SYMBOL_DESCRIPTION "pa__get_description" diff --git a/src/polypcore/module.c b/src/polypcore/module.c index 73ec5bd40..753853542 100644 --- a/src/polypcore/module.c +++ b/src/polypcore/module.c @@ -30,11 +30,12 @@ #include #include +#include +#include +#include +#include + #include "module.h" -#include "xmalloc.h" -#include "core-subscribe.h" -#include "log.h" -#include "util.h" #define PA_SYMBOL_INIT "pa__init" #define PA_SYMBOL_DONE "pa__done" diff --git a/src/polypcore/module.h b/src/polypcore/module.h index 6f137c157..03b9bc877 100644 --- a/src/polypcore/module.h +++ b/src/polypcore/module.h @@ -25,8 +25,8 @@ #include #include -#include "core.h" -#include "modinfo.h" +#include +#include typedef struct pa_module pa_module; diff --git a/src/polypcore/namereg.c b/src/polypcore/namereg.c index ca03c455d..d4dbd14bb 100644 --- a/src/polypcore/namereg.c +++ b/src/polypcore/namereg.c @@ -29,13 +29,14 @@ #include #include +#include +#include +#include +#include +#include +#include + #include "namereg.h" -#include "autoload.h" -#include "source.h" -#include "sink.h" -#include "xmalloc.h" -#include "core-subscribe.h" -#include "util.h" struct namereg_entry { pa_namereg_type_t type; diff --git a/src/polypcore/namereg.h b/src/polypcore/namereg.h index 961fd44b5..a98295ff9 100644 --- a/src/polypcore/namereg.h +++ b/src/polypcore/namereg.h @@ -22,7 +22,7 @@ USA. ***/ -#include "core.h" +#include typedef enum pa_namereg_type { PA_NAMEREG_SINK, diff --git a/src/polypcore/packet.c b/src/polypcore/packet.c index b3a2e0742..41803cf99 100644 --- a/src/polypcore/packet.c +++ b/src/polypcore/packet.c @@ -26,8 +26,9 @@ #include #include +#include + #include "packet.h" -#include "xmalloc.h" pa_packet* pa_packet_new(size_t length) { pa_packet *p; diff --git a/src/polypcore/parseaddr.c b/src/polypcore/parseaddr.c index 5e4c689ca..c2b25c896 100644 --- a/src/polypcore/parseaddr.c +++ b/src/polypcore/parseaddr.c @@ -27,8 +27,9 @@ #include #include -#include "xmalloc.h" -#include "util.h" +#include +#include + #include "parseaddr.h" /* Parse addresses in one of the following forms: diff --git a/src/polypcore/pdispatch.c b/src/polypcore/pdispatch.c index 5a50a0d57..7941e4a82 100644 --- a/src/polypcore/pdispatch.c +++ b/src/polypcore/pdispatch.c @@ -27,12 +27,13 @@ #include #include +#include +#include +#include +#include +#include + #include "pdispatch.h" -#include "native-common.h" -#include "xmalloc.h" -#include "llist.h" -#include "log.h" -#include "util.h" /*#define DEBUG_OPCODES */ diff --git a/src/polypcore/pdispatch.h b/src/polypcore/pdispatch.h index fdd4d7f54..57666259c 100644 --- a/src/polypcore/pdispatch.h +++ b/src/polypcore/pdispatch.h @@ -23,9 +23,9 @@ ***/ #include -#include "tagstruct.h" -#include "packet.h" #include +#include +#include typedef struct pa_pdispatch pa_pdispatch; diff --git a/src/polypcore/pid.c b/src/polypcore/pid.c index ae3dc7f51..3f33365ac 100644 --- a/src/polypcore/pid.c +++ b/src/polypcore/pid.c @@ -39,9 +39,10 @@ #include #endif +#include +#include + #include "pid.h" -#include "util.h" -#include "log.h" /* Read the PID data from the file descriptor fd, and return it. If no * pid could be read, return 0, on failure (pid_t) -1 */ diff --git a/src/polypcore/play-memchunk.c b/src/polypcore/play-memchunk.c index e24d44273..ec79254b1 100644 --- a/src/polypcore/play-memchunk.c +++ b/src/polypcore/play-memchunk.c @@ -28,10 +28,11 @@ #include #include +#include +#include +#include + #include "play-memchunk.h" -#include "sink-input.h" -#include "xmalloc.h" -#include "gccmacro.h" static void sink_input_kill(pa_sink_input *i) { pa_memchunk *c; diff --git a/src/polypcore/play-memchunk.h b/src/polypcore/play-memchunk.h index fc0654a6f..72aeda955 100644 --- a/src/polypcore/play-memchunk.h +++ b/src/polypcore/play-memchunk.h @@ -22,8 +22,8 @@ USA. ***/ -#include "sink.h" -#include "memchunk.h" +#include +#include int pa_play_memchunk( pa_sink *sink, diff --git a/src/polypcore/poll.c b/src/polypcore/poll.c index 193fc8128..6a29a9530 100644 --- a/src/polypcore/poll.c +++ b/src/polypcore/poll.c @@ -42,7 +42,8 @@ #ifndef HAVE_SYS_POLL_H -#include "util.h" +#include + #include "poll.h" int poll (struct pollfd *fds, unsigned long int nfds, int timeout) { diff --git a/src/polypcore/props.c b/src/polypcore/props.c index df748c1ea..96cdc4f2d 100644 --- a/src/polypcore/props.c +++ b/src/polypcore/props.c @@ -21,9 +21,10 @@ #include -#include "xmalloc.h" +#include +#include + #include "props.h" -#include "log.h" typedef struct pa_property { char *name; /* Points to memory allocated by the property subsystem */ diff --git a/src/polypcore/props.h b/src/polypcore/props.h index 5abf8787c..9430db5eb 100644 --- a/src/polypcore/props.h +++ b/src/polypcore/props.h @@ -22,8 +22,8 @@ USA. ***/ -#include "core.h" -#include "strbuf.h" +#include +#include /* The property subsystem is to be used to share data between * modules. Consider them to be kind of "global" variables for a diff --git a/src/polypcore/protocol-cli.c b/src/polypcore/protocol-cli.c index d2d73550b..cb7e8f6f1 100644 --- a/src/polypcore/protocol-cli.c +++ b/src/polypcore/protocol-cli.c @@ -26,10 +26,11 @@ #include #include +#include +#include +#include + #include "protocol-cli.h" -#include "cli.h" -#include "xmalloc.h" -#include "log.h" /* Don't allow more than this many concurrent connections */ #define MAX_CONNECTIONS 25 diff --git a/src/polypcore/protocol-cli.h b/src/polypcore/protocol-cli.h index aed733c13..c47b14d61 100644 --- a/src/polypcore/protocol-cli.h +++ b/src/polypcore/protocol-cli.h @@ -22,10 +22,10 @@ USA. ***/ -#include "core.h" -#include "socket-server.h" -#include "module.h" -#include "modargs.h" +#include +#include +#include +#include typedef struct pa_protocol_cli pa_protocol_cli; diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index d2c0f3546..a16ac2808 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -30,24 +30,26 @@ #include #include -#include "protocol-esound.h" -#include "esound.h" -#include "memblock.h" -#include "client.h" -#include "sink-input.h" -#include "sink.h" -#include "source-output.h" -#include "source.h" #include -#include "core-scache.h" -#include "sample-util.h" -#include "authkey.h" -#include "namereg.h" -#include "xmalloc.h" -#include "log.h" -#include "util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "endianmacros.h" +#include "protocol-esound.h" + /* Don't accept more connection than this */ #define MAX_CONNECTIONS 10 diff --git a/src/polypcore/protocol-esound.h b/src/polypcore/protocol-esound.h index 71d58464e..a94d1c724 100644 --- a/src/polypcore/protocol-esound.h +++ b/src/polypcore/protocol-esound.h @@ -22,10 +22,10 @@ USA. ***/ -#include "core.h" -#include "socket-server.h" -#include "module.h" -#include "modargs.h" +#include +#include +#include +#include typedef struct pa_protocol_esound pa_protocol_esound; diff --git a/src/polypcore/protocol-http.c b/src/polypcore/protocol-http.c index 3e55df03a..f0b78124b 100644 --- a/src/polypcore/protocol-http.c +++ b/src/polypcore/protocol-http.c @@ -28,12 +28,13 @@ #include #include +#include +#include +#include +#include +#include + #include "protocol-http.h" -#include "ioline.h" -#include "xmalloc.h" -#include "log.h" -#include "namereg.h" -#include "cli-text.h" /* Don't allow more than this many concurrent connections */ #define MAX_CONNECTIONS 10 diff --git a/src/polypcore/protocol-http.h b/src/polypcore/protocol-http.h index 0a1855e9b..10dd656b6 100644 --- a/src/polypcore/protocol-http.h +++ b/src/polypcore/protocol-http.h @@ -22,10 +22,10 @@ USA. ***/ -#include "core.h" -#include "socket-server.h" -#include "module.h" -#include "modargs.h" +#include +#include +#include +#include typedef struct pa_protocol_http pa_protocol_http; diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 31983bc26..1362fdf2e 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -28,27 +28,28 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "protocol-native.h" -#include "native-common.h" -#include "packet.h" -#include "client.h" -#include "source-output.h" -#include "sink-input.h" -#include "pstream.h" -#include "tagstruct.h" -#include "pdispatch.h" -#include "pstream-util.h" -#include "authkey.h" -#include "namereg.h" -#include "core-scache.h" -#include "xmalloc.h" -#include "util.h" -#include "core-subscribe.h" -#include "log.h" -#include "autoload.h" -#include "authkey-prop.h" -#include "strlist.h" -#include "props.h" /* Kick a client if it doesn't authenticate within this time */ #define AUTH_TIMEOUT 5 diff --git a/src/polypcore/protocol-native.h b/src/polypcore/protocol-native.h index 12e85d0b7..88aa8494f 100644 --- a/src/polypcore/protocol-native.h +++ b/src/polypcore/protocol-native.h @@ -22,10 +22,10 @@ USA. ***/ -#include "core.h" -#include "socket-server.h" -#include "module.h" -#include "modargs.h" +#include +#include +#include +#include typedef struct pa_protocol_native pa_protocol_native; diff --git a/src/polypcore/protocol-simple.c b/src/polypcore/protocol-simple.c index 113919b35..4d3f8e1d9 100644 --- a/src/polypcore/protocol-simple.c +++ b/src/polypcore/protocol-simple.c @@ -30,14 +30,15 @@ #include #include -#include "sink-input.h" -#include "source-output.h" +#include +#include +#include +#include +#include +#include +#include + #include "protocol-simple.h" -#include "client.h" -#include "sample-util.h" -#include "namereg.h" -#include "xmalloc.h" -#include "log.h" /* Don't allow more than this many concurrent connections */ #define MAX_CONNECTIONS 10 diff --git a/src/polypcore/protocol-simple.h b/src/polypcore/protocol-simple.h index 63455a53e..f11c77592 100644 --- a/src/polypcore/protocol-simple.h +++ b/src/polypcore/protocol-simple.h @@ -22,10 +22,10 @@ USA. ***/ -#include "socket-server.h" -#include "module.h" -#include "core.h" -#include "modargs.h" +#include +#include +#include +#include typedef struct pa_protocol_simple pa_protocol_simple; diff --git a/src/polypcore/pstream-util.c b/src/polypcore/pstream-util.c index ecd63d15f..62986456e 100644 --- a/src/polypcore/pstream-util.c +++ b/src/polypcore/pstream-util.c @@ -25,7 +25,8 @@ #include -#include "native-common.h" +#include + #include "pstream-util.h" void pa_pstream_send_tagstruct(pa_pstream *p, pa_tagstruct *t) { diff --git a/src/polypcore/pstream-util.h b/src/polypcore/pstream-util.h index 601a9e99a..c400c6d8a 100644 --- a/src/polypcore/pstream-util.h +++ b/src/polypcore/pstream-util.h @@ -23,8 +23,8 @@ ***/ #include -#include "pstream.h" -#include "tagstruct.h" +#include +#include /* The tagstruct is freed!*/ void pa_pstream_send_tagstruct(pa_pstream *p, pa_tagstruct *t); diff --git a/src/polypcore/pstream.c b/src/polypcore/pstream.c index bd00ba4f9..eec93a0f7 100644 --- a/src/polypcore/pstream.c +++ b/src/polypcore/pstream.c @@ -34,10 +34,11 @@ #include "winsock.h" +#include +#include +#include + #include "pstream.h" -#include "queue.h" -#include "xmalloc.h" -#include "log.h" typedef enum pa_pstream_descriptor_index { PA_PSTREAM_DESCRIPTOR_LENGTH, diff --git a/src/polypcore/pstream.h b/src/polypcore/pstream.h index ec63a98e8..10ce58f60 100644 --- a/src/polypcore/pstream.h +++ b/src/polypcore/pstream.h @@ -24,11 +24,11 @@ #include -#include "packet.h" -#include "memblock.h" -#include "iochannel.h" #include -#include "memchunk.h" +#include +#include +#include +#include typedef struct pa_pstream pa_pstream; diff --git a/src/polypcore/queue.c b/src/polypcore/queue.c index 80ec00685..77ca1ed39 100644 --- a/src/polypcore/queue.c +++ b/src/polypcore/queue.c @@ -26,8 +26,9 @@ #include #include +#include + #include "queue.h" -#include "xmalloc.h" struct queue_entry { struct queue_entry *next; diff --git a/src/polypcore/random.c b/src/polypcore/random.c index 12f27bfd6..756c3218c 100644 --- a/src/polypcore/random.c +++ b/src/polypcore/random.c @@ -31,9 +31,10 @@ #include #include +#include +#include + #include "random.h" -#include "util.h" -#include "log.h" #ifndef OS_IS_WIN32 #define RANDOM_DEVICE "/dev/urandom" diff --git a/src/polypcore/resampler.c b/src/polypcore/resampler.c index 0417e44ef..c1740bf1d 100644 --- a/src/polypcore/resampler.c +++ b/src/polypcore/resampler.c @@ -30,10 +30,11 @@ #include #include +#include +#include +#include + #include "resampler.h" -#include "sconv.h" -#include "xmalloc.h" -#include "log.h" struct pa_resampler { pa_resample_method_t resample_method; diff --git a/src/polypcore/resampler.h b/src/polypcore/resampler.h index cad48be50..2f4d3cbe8 100644 --- a/src/polypcore/resampler.h +++ b/src/polypcore/resampler.h @@ -25,9 +25,9 @@ #include #include -#include "memblock.h" -#include "memchunk.h" #include +#include +#include typedef struct pa_resampler pa_resampler; diff --git a/src/polypcore/sample-util.c b/src/polypcore/sample-util.c index 52974c46a..e3bb4aa6c 100644 --- a/src/polypcore/sample-util.c +++ b/src/polypcore/sample-util.c @@ -30,7 +30,8 @@ #include -#include "log.h" +#include + #include "sample-util.h" pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { diff --git a/src/polypcore/sample-util.h b/src/polypcore/sample-util.h index d0efbcc43..486d284ba 100644 --- a/src/polypcore/sample-util.h +++ b/src/polypcore/sample-util.h @@ -23,9 +23,9 @@ ***/ #include -#include "memblock.h" -#include "memchunk.h" #include +#include +#include pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec); void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec); diff --git a/src/polypcore/sconv-s16le.c b/src/polypcore/sconv-s16le.c index e47c5e8e8..0814c35b5 100644 --- a/src/polypcore/sconv-s16le.c +++ b/src/polypcore/sconv-s16le.c @@ -28,10 +28,12 @@ #include +#include +#include + #include "endianmacros.h" -#include "sconv.h" + #include "sconv-s16le.h" -#include "log.h" #ifndef INT16_FROM #define INT16_FROM INT16_FROM_LE diff --git a/src/polypcore/sconv.c b/src/polypcore/sconv.c index 1fcb5a0c8..c557be67b 100644 --- a/src/polypcore/sconv.c +++ b/src/polypcore/sconv.c @@ -30,13 +30,14 @@ #include #include -#include "endianmacros.h" -#include "sconv.h" -#include "g711.h" +#include +#include "endianmacros.h" #include "sconv-s16le.h" #include "sconv-s16be.h" +#include "sconv.h" + static void u8_to_float32ne(unsigned n, const void *a, float *b) { const uint8_t *ca = a; static const double add = -128.0/127.0, factor = 1.0/127.0; diff --git a/src/polypcore/sink-input.c b/src/polypcore/sink-input.c index 696c47a4d..1dc7df0f2 100644 --- a/src/polypcore/sink-input.c +++ b/src/polypcore/sink-input.c @@ -28,11 +28,12 @@ #include #include +#include +#include +#include +#include + #include "sink-input.h" -#include "sample-util.h" -#include "xmalloc.h" -#include "core-subscribe.h" -#include "log.h" #define CONVERT_BUFFER_LENGTH 4096 diff --git a/src/polypcore/sink-input.h b/src/polypcore/sink-input.h index a5ad19584..e4b8bda47 100644 --- a/src/polypcore/sink-input.h +++ b/src/polypcore/sink-input.h @@ -26,12 +26,12 @@ typedef struct pa_sink_input pa_sink_input; -#include "sink.h" #include -#include "memblockq.h" -#include "resampler.h" -#include "module.h" -#include "client.h" +#include +#include +#include +#include +#include typedef enum pa_sink_input_state { PA_SINK_INPUT_RUNNING, diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index 6c143463b..9bc478c3c 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -28,15 +28,16 @@ #include #include -#include "sink.h" -#include "sink-input.h" -#include "namereg.h" -#include "util.h" -#include "sample-util.h" -#include "xmalloc.h" -#include "core-subscribe.h" -#include "log.h" #include +#include +#include +#include +#include +#include +#include +#include + +#include "sink.h" #define MAX_MIX_CHANNELS 32 diff --git a/src/polypcore/sink.h b/src/polypcore/sink.h index 268461eff..5fd9784f9 100644 --- a/src/polypcore/sink.h +++ b/src/polypcore/sink.h @@ -26,13 +26,13 @@ typedef struct pa_sink pa_sink; -#include "core.h" #include -#include "idxset.h" -#include "source.h" #include -#include "module.h" #include +#include +#include +#include +#include #define PA_MAX_INPUTS_PER_SINK 6 diff --git a/src/polypcore/sioman.c b/src/polypcore/sioman.c index 8d7b136c8..b389eceef 100644 --- a/src/polypcore/sioman.c +++ b/src/polypcore/sioman.c @@ -24,6 +24,7 @@ #endif #include + #include "sioman.h" static int stdio_inuse = 0; diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index 29c9775ef..3662e89c7 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -54,12 +54,13 @@ #include "winsock.h" +#include +#include +#include +#include +#include + #include "socket-client.h" -#include "socket-util.h" -#include "util.h" -#include "xmalloc.h" -#include "log.h" -#include "parseaddr.h" #define CONNECT_TIMEOUT 5 diff --git a/src/polypcore/socket-client.h b/src/polypcore/socket-client.h index 624880d7d..d00053310 100644 --- a/src/polypcore/socket-client.h +++ b/src/polypcore/socket-client.h @@ -25,7 +25,7 @@ #include #include -#include "iochannel.h" +#include struct sockaddr; diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index 262b32a76..d1646984c 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -58,11 +58,12 @@ #include "winsock.h" +#include +#include +#include +#include + #include "socket-server.h" -#include "socket-util.h" -#include "xmalloc.h" -#include "util.h" -#include "log.h" struct pa_socket_server { int ref; diff --git a/src/polypcore/socket-server.h b/src/polypcore/socket-server.h index 4d8bfad56..6bb834276 100644 --- a/src/polypcore/socket-server.h +++ b/src/polypcore/socket-server.h @@ -24,7 +24,7 @@ #include #include -#include "iochannel.h" +#include /* It is safe to destroy the calling socket_server object from the callback */ diff --git a/src/polypcore/socket-util.c b/src/polypcore/socket-util.c index 032a3c914..5ffe5302b 100644 --- a/src/polypcore/socket-util.c +++ b/src/polypcore/socket-util.c @@ -59,10 +59,11 @@ #include "winsock.h" +#include +#include +#include + #include "socket-util.h" -#include "util.h" -#include "xmalloc.h" -#include "log.h" void pa_socket_peer_to_string(int fd, char *c, size_t l) { struct stat st; diff --git a/src/polypcore/sound-file-stream.c b/src/polypcore/sound-file-stream.c index 881e30772..644e578f7 100644 --- a/src/polypcore/sound-file-stream.c +++ b/src/polypcore/sound-file-stream.c @@ -30,10 +30,11 @@ #include +#include +#include +#include + #include "sound-file-stream.h" -#include "sink-input.h" -#include "xmalloc.h" -#include "log.h" #define BUF_SIZE (1024*10) diff --git a/src/polypcore/sound-file-stream.h b/src/polypcore/sound-file-stream.h index 2e56ef49b..5effc7f03 100644 --- a/src/polypcore/sound-file-stream.h +++ b/src/polypcore/sound-file-stream.h @@ -22,7 +22,7 @@ USA. ***/ -#include "sink.h" +#include int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume); diff --git a/src/polypcore/sound-file.c b/src/polypcore/sound-file.c index a81c283a0..cf23e0acd 100644 --- a/src/polypcore/sound-file.c +++ b/src/polypcore/sound-file.c @@ -28,9 +28,10 @@ #include -#include "sound-file.h" #include -#include "log.h" +#include + +#include "sound-file.h" #define MAX_FILE_SIZE (1024*1024) diff --git a/src/polypcore/sound-file.h b/src/polypcore/sound-file.h index f3003bb9e..ffa551b52 100644 --- a/src/polypcore/sound-file.h +++ b/src/polypcore/sound-file.h @@ -22,8 +22,8 @@ USA. ***/ -#include "memchunk.h" #include +#include int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_memchunk *chunk, pa_memblock_stat *s); diff --git a/src/polypcore/source-output.c b/src/polypcore/source-output.c index 9b75a8b0d..d6201b4dc 100644 --- a/src/polypcore/source-output.c +++ b/src/polypcore/source-output.c @@ -28,10 +28,11 @@ #include #include +#include +#include +#include + #include "source-output.h" -#include "xmalloc.h" -#include "core-subscribe.h" -#include "log.h" pa_source_output* pa_source_output_new( pa_source *s, diff --git a/src/polypcore/source-output.h b/src/polypcore/source-output.h index 4b1cbf152..98f6ab0c0 100644 --- a/src/polypcore/source-output.h +++ b/src/polypcore/source-output.h @@ -26,12 +26,12 @@ typedef struct pa_source_output pa_source_output; -#include "source.h" #include -#include "memblockq.h" -#include "resampler.h" -#include "module.h" -#include "client.h" +#include +#include +#include +#include +#include typedef enum { PA_SOURCE_OUTPUT_RUNNING, diff --git a/src/polypcore/source.c b/src/polypcore/source.c index c64f7b990..b70cb1293 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -28,12 +28,13 @@ #include #include +#include +#include +#include +#include +#include + #include "source.h" -#include "source-output.h" -#include "namereg.h" -#include "xmalloc.h" -#include "core-subscribe.h" -#include "log.h" pa_source* pa_source_new( pa_core *core, diff --git a/src/polypcore/source.h b/src/polypcore/source.h index be2fb9856..a267e73c1 100644 --- a/src/polypcore/source.h +++ b/src/polypcore/source.h @@ -25,14 +25,15 @@ typedef struct pa_source pa_source; #include -#include "core.h" + #include -#include "idxset.h" -#include "memblock.h" -#include "memchunk.h" -#include "sink.h" #include -#include "module.h" +#include +#include +#include +#include +#include +#include #define PA_MAX_OUTPUTS_PER_SOURCE 16 diff --git a/src/polypcore/strbuf.h b/src/polypcore/strbuf.h index a88f5190c..4b06a7e60 100644 --- a/src/polypcore/strbuf.h +++ b/src/polypcore/strbuf.h @@ -22,7 +22,7 @@ USA. ***/ -#include "gccmacro.h" +#include typedef struct pa_strbuf pa_strbuf; diff --git a/src/polypcore/strlist.c b/src/polypcore/strlist.c index 09eb0c8aa..e165aefdd 100644 --- a/src/polypcore/strlist.c +++ b/src/polypcore/strlist.c @@ -26,10 +26,11 @@ #include #include +#include +#include +#include + #include "strlist.h" -#include "xmalloc.h" -#include "strbuf.h" -#include "util.h" struct pa_strlist { pa_strlist *next; diff --git a/src/polypcore/tagstruct.c b/src/polypcore/tagstruct.c index 676f67ded..1f5f370bf 100644 --- a/src/polypcore/tagstruct.c +++ b/src/polypcore/tagstruct.c @@ -36,8 +36,9 @@ #include "winsock.h" +#include + #include "tagstruct.h" -#include "xmalloc.h" struct pa_tagstruct { diff --git a/src/polypcore/tokenizer.c b/src/polypcore/tokenizer.c index 5e0c1b166..556a190a0 100644 --- a/src/polypcore/tokenizer.c +++ b/src/polypcore/tokenizer.c @@ -27,10 +27,11 @@ #include #include +#include +#include +#include + #include "tokenizer.h" -#include "dynarray.h" -#include "xmalloc.h" -#include "gccmacro.h" struct pa_tokenizer { pa_dynarray *dynarray; diff --git a/src/polypcore/util.c b/src/polypcore/util.c index 4b6edb97f..a53c36bc6 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -70,9 +70,10 @@ #include "winsock.h" +#include +#include + #include "util.h" -#include "xmalloc.h" -#include "log.h" #ifndef OS_IS_WIN32 #define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-" diff --git a/src/polypcore/util.h b/src/polypcore/util.h index 3dc6c945c..14f763a3f 100644 --- a/src/polypcore/util.h +++ b/src/polypcore/util.h @@ -27,8 +27,8 @@ #include #include -#include "gccmacro.h" #include +#include struct timeval; diff --git a/src/polypcore/x11wrap.c b/src/polypcore/x11wrap.c index e20a50a63..9414fbdfd 100644 --- a/src/polypcore/x11wrap.c +++ b/src/polypcore/x11wrap.c @@ -22,11 +22,12 @@ #include #include -#include "llist.h" +#include +#include +#include +#include + #include "x11wrap.h" -#include "xmalloc.h" -#include "log.h" -#include "props.h" typedef struct pa_x11_internal pa_x11_internal; diff --git a/src/polypcore/x11wrap.h b/src/polypcore/x11wrap.h index 15645168e..15969869d 100644 --- a/src/polypcore/x11wrap.h +++ b/src/polypcore/x11wrap.h @@ -24,7 +24,7 @@ #include -#include "core.h" +#include typedef struct pa_x11_wrapper pa_x11_wrapper; diff --git a/src/polypcore/xmalloc.c b/src/polypcore/xmalloc.c index bf3663470..4c8689a6c 100644 --- a/src/polypcore/xmalloc.c +++ b/src/polypcore/xmalloc.c @@ -27,11 +27,12 @@ #include #include #include +#include + +#include +#include -#include "memory.h" -#include "util.h" #include "xmalloc.h" -#include "gccmacro.h" /* Make sure not to allocate more than this much memory. */ #define MAX_ALLOC_SIZE (1024*1024*20) /* 20MB */ diff --git a/src/tests/cpulimit-test.c b/src/tests/cpulimit-test.c index 97a8a0dd9..b51014c85 100644 --- a/src/tests/cpulimit-test.c +++ b/src/tests/cpulimit-test.c @@ -29,7 +29,6 @@ #include #include -#include "../daemon/cpulimit.h" #include #include @@ -37,6 +36,8 @@ #include #endif +#include "../daemon/cpulimit.h" + /* A simple example for testing the cpulimit subsystem */ static time_t start; diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 908a35072..56b62d372 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -36,7 +36,8 @@ #include #include #include -#include + +#include "../polyp/client-conf.h" int main(int argc, char *argv[]) { const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE; From 1eae42f7ed6e5a3dffa896ecb266224854246206 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 12:34:44 +0000 Subject: [PATCH 0408/1514] Make sure that all polypcore headers are installed. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@501 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 56 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 1e898a85f..9fd24a057 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -406,36 +406,46 @@ libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 ################################### polypcoreinclude_HEADERS = \ + polypcore/autoload.h \ polypcore/cli-command.h \ + polypcore/cli-text.h \ polypcore/client.h \ polypcore/core.h \ + polypcore/core-scache.h \ + polypcore/core-subscribe.h \ + polypcore/conf-parser.h \ polypcore/dynarray.h \ - polypcore/endianmacros.h \ + polypcore/g711.h \ polypcore/hashmap.h \ polypcore/idxset.h \ - polypcore/iochannel.h \ polypcore/log.h \ + polypcore/mcalign.h \ polypcore/memblock.h \ polypcore/memblockq.h \ polypcore/memchunk.h \ polypcore/modargs.h \ + polypcore/modinfo.h \ polypcore/module.h \ polypcore/namereg.h \ + polypcore/pid.h \ + polypcore/play-memchunk.h \ + polypcore/props.h \ polypcore/queue.h \ + polypcore/random.h \ polypcore/resampler.h \ polypcore/sample-util.h \ + polypcore/sconv.h \ polypcore/sink.h \ polypcore/sink-input.h \ polypcore/sioman.h \ - polypcore/socket-server.h \ - polypcore/socket-client.h \ - polypcore/socket-util.h \ + polypcore/sound-file.h \ + polypcore/sound-file-stream.h \ polypcore/source.h \ polypcore/source-output.h \ polypcore/strbuf.h \ polypcore/tokenizer.h \ - polypcore/tagstruct.h \ - polypcore/util.h + polypcore/util.h \ + polypcore/xmalloc.h lib_LTLIBRARIES += libpolypcore.la @@ -456,6 +466,8 @@ libpolypcore_la_SOURCES += \ polypcore/client.c polypcore/client.h \ polypcore/conf-parser.c polypcore/conf-parser.h \ polypcore/core.c polypcore/core.h \ + polypcore/core-scache.c polypcore/core-scache.h \ + polypcore/core-subscribe.c polypcore/core-subscribe.h \ polypcore/dllmain.c \ polypcore/dynarray.c polypcore/dynarray.h \ polypcore/endianmacros.h \ @@ -479,7 +491,6 @@ libpolypcore_la_SOURCES += \ polypcore/random.c polypcore/random.h \ polypcore/resampler.c polypcore/resampler.h \ polypcore/sample-util.c polypcore/sample-util.h \ - polypcore/core-scache.c polypcore/core-scache.h \ polypcore/sconv.c polypcore/sconv.h \ polypcore/sconv-s16be.c polypcore/sconv-s16be.h \ polypcore/sconv-s16le.c polypcore/sconv-s16le.h \ @@ -491,7 +502,6 @@ libpolypcore_la_SOURCES += \ polypcore/source.c polypcore/source.h \ polypcore/source-output.c polypcore/source-output.h \ polypcore/strbuf.c polypcore/strbuf.h \ - polypcore/core-subscribe.c polypcore/core-subscribe.h \ polypcore/tokenizer.c polypcore/tokenizer.h \ polypcore/util.c polypcore/util.h \ polypcore/winsock.h \ @@ -505,6 +515,30 @@ libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDF # Plug-in support libraries # ################################### +polypcoreinclude_HEADERS += \ + polypcore/socket-util.h \ + polypcore/iochannel.h \ + polypcore/socket-server.h \ + polypcore/socket-client.h \ + polypcore/parseaddr.h \ + polypcore/packet.h \ + polypcore/pstream.h \ + polypcore/ioline.h \ + polypcore/cli.h \ + polypcore/protocol-cli.h \ + polypcore/tagstruct.h \ + polypcore/pstream-util.h \ + polypcore/pdispatch.h \ + polypcore/authkey.h \ + polypcore/authkey-prop.h \ + polypcore/strlist.h \ + polypcore/protocol-simple.h \ + polypcore/esound.h \ + polypcore/protocol-esound.h \ + polypcore/native-common.h \ + polypcore/protocol-native.h \ + polypcore/protocol-http.h + ### Warning! Due to an obscure bug in libtool/automake it is required ### that the libraries in modlib_LTLIBRARIES are specified in-order, ### i.e. libraries near the end of the list depend on libraries near @@ -533,6 +567,10 @@ modlib_LTLIBRARIES = \ libprotocol-http.la if HAVE_X11 +polypcoreinclude_HEADERS += \ + polypcore/x11wrap.h \ + polypcore/x11prop.h + modlib_LTLIBRARIES += \ libx11wrap.la \ libx11prop.la From da665d5e61d82e84a2ee5cda317a114143be0d12 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 13:08:03 +0000 Subject: [PATCH 0409/1514] Integrate error routines into libpolyp. Not much point in having this as a separate library. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@502 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 9fd24a057..443a97939 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -141,17 +141,17 @@ endif bin_SCRIPTS = esdcompat.sh pacat_SOURCES = utils/pacat.c -pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la pacat_CFLAGS = $(AM_CFLAGS) pacat_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) paplay_SOURCES = utils/paplay.c -paplay_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) +paplay_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) paplay_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pactl_SOURCES = utils/pactl.c -pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) +pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -166,7 +166,7 @@ pax11publish_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la $(X_PRE_LIBS) -lX11 pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pabrowse_SOURCES = utils/pabrowse.c -pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la +pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la pabrowse_CFLAGS = $(AM_CFLAGS) pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -209,12 +209,12 @@ mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la mcalign_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pacat_simple_SOURCES = tests/pacat-simple.c -pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la pacat_simple_CFLAGS = $(AM_CFLAGS) pacat_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) parec_simple_SOURCES = tests/parec-simple.c -parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la parec_simple_CFLAGS = $(AM_CFLAGS) parec_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -280,7 +280,6 @@ endif lib_LTLIBRARIES = \ libpolyp-@PA_MAJORMINOR@.la \ - libpolyp-error-@PA_MAJORMINOR@.la \ libpolyp-mainloop-@PA_MAJORMINOR@.la \ libpolyp-simple-@PA_MAJORMINOR@.la @@ -309,6 +308,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ polyp/polypaudio.h \ polyp/context.c polyp/context.h \ polyp/def.h \ + polyp/error.c polyp/error.h \ polyp/internal.h \ polyp/introspect.c polyp/introspect.h \ polyp/operation.c polyp/operation.h \ @@ -368,11 +368,6 @@ libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(LIBASYNCNS_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LIBADD += $(LIBASYNCNS_LIBS) endif -libpolyp_error_@PA_MAJORMINOR@_la_SOURCES = polyp/error.c polyp/error.h -libpolyp_error_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) -libpolyp_error_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la -libpolyp_error_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 - libpolyp_mainloop_@PA_MAJORMINOR@_la_SOURCES = \ polyp/mainloop.c polyp/mainloop.h \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ From c4cf7adacac03af50c52b6470bf620f76ce2f533 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 13:11:37 +0000 Subject: [PATCH 0410/1514] Fix typo in #ifndef. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@503 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/mainloop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 71ea9bc41..a694c1443 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -323,7 +323,7 @@ pa_mainloop *pa_mainloop_new(void) { m = pa_xmalloc(sizeof(pa_mainloop)); -#ifndef OS_ISWIN32 +#ifndef OS_IS_WIN32 if (pipe(m->wakeup_pipe) < 0) { pa_xfree(m); return NULL; From 2686857b8c4f512958a8bf2018f5394b16f1a2e4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 13:18:30 +0000 Subject: [PATCH 0411/1514] Fix path to poll.h. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@504 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/mainloop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index a694c1443..e975d7d79 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -35,7 +35,7 @@ #ifdef HAVE_SYS_POLL_H #include #else -#include "poll.h" +#include "../polypcore/poll.h" #endif #include "../polypcore/winsock.h" From 162a95d56631726cf7c142945da2a9660719df03 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 13:18:53 +0000 Subject: [PATCH 0412/1514] Module needs stuff in libpolypcore. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@505 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 443a97939..1be713cef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1043,7 +1043,7 @@ module_waveout_la_CFLAGS = $(AM_CFLAGS) # Hardware autodetection module module_detect_la_SOURCES = modules/module-detect.c module_detect_la_LDFLAGS = -module -avoid-version -module_detect_la_LIBADD = $(AM_LIBADD) +module_detect_la_LIBADD = $(AM_LIBADD) libpolypcore.la module_detect_la_CFLAGS = $(AM_CFLAGS) ################################### From 6f9a367abc8d8949e980d30645420fb31f8eb6af Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 13:20:09 +0000 Subject: [PATCH 0413/1514] Ignore generated win32 binaries. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@506 fefdeb5f-60dc-0310-8127-8f9354f1896f From 45700da4ebf2986126d7a4d6889c028599fd3085 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 15:42:47 +0000 Subject: [PATCH 0414/1514] Have a memblock queue on the client side during recording. This makes the record callback optional in stead of mandatory. For applications that wish to retain the old behaviour, simply call pa_stream_peek() followed by pa_stream_drop() in the callback. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@507 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 1 + src/polyp/context.c | 10 ++++---- src/polyp/internal.h | 5 +++- src/polyp/stream.c | 61 +++++++++++++++++++++++++++++++++++++++++++- src/polyp/stream.h | 22 ++++++++++++++-- src/utils/pacat.c | 10 ++++++-- 6 files changed, 98 insertions(+), 11 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 1be713cef..f973dc469 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -330,6 +330,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ polypcore/log.c polypcore/log.h \ polypcore/mcalign.c polypcore/mcalign.h \ polypcore/memblock.c polypcore/memblock.h \ + polypcore/memblockq.c polypcore/memblockq.h \ polypcore/memchunk.c polypcore/memchunk.h \ polypcore/native-common.h \ polypcore/packet.c polypcore/packet.h \ diff --git a/src/polyp/context.c b/src/polyp/context.c index b7f7eb997..c40041c59 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -273,11 +273,11 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, PA_GCC_UN if (pa_mcalign_pop(s->mcalign, &t) < 0) break; - - if (s->read_callback) { - s->read_callback(s, (uint8_t*) t.memblock->data + t.index, t.length, s->read_userdata); - s->counter += chunk->length; - } + + assert(s->record_memblockq); + pa_memblockq_push(s->record_memblockq, &t, t.length); + if (s->read_callback) + s->read_callback(s, pa_stream_readable_size(s), s->read_userdata); pa_memblock_unref(t.memblock); } diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 762688c98..7f4d38ac5 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -35,6 +35,7 @@ #include #include #include +#include #include "client-conf.h" @@ -98,6 +99,8 @@ struct pa_stream { pa_usec_t previous_ipol_time; pa_stream_state_t state; pa_mcalign *mcalign; + pa_memchunk peek_memchunk; + pa_memblockq *record_memblockq; int interpolate; int corked; @@ -110,7 +113,7 @@ struct pa_stream { void (*state_callback)(pa_stream*c, void *userdata); void *state_userdata; - void (*read_callback)(pa_stream *p, const void*data, size_t length, void *userdata); + void (*read_callback)(pa_stream *p, size_t length, void *userdata); void *read_userdata; void (*write_callback)(pa_stream *p, size_t length, void *userdata); diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 6e5bc0671..fef3c00f8 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -103,6 +103,12 @@ static void stream_free(pa_stream *s) { s->mainloop->time_free(s->ipol_event); } + if (s->peek_memchunk.memblock) + pa_memblock_unref(s->peek_memchunk.memblock); + + if (s->record_memblockq) + pa_memblockq_free(s->record_memblockq); + pa_mcalign_free(s->mcalign); pa_xfree(s->name); @@ -263,6 +269,13 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED goto finish; } + if (s->direction == PA_STREAM_RECORD) { + assert(!s->record_memblockq); + s->record_memblockq = pa_memblockq_new(s->buffer_attr.maxlength, 0, + pa_frame_size(&s->sample_spec), 0, 0, s->context->memblock_stat); + assert(s->record_memblockq); + } + s->channel_valid = 1; pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); pa_stream_set_state(s, PA_STREAM_READY); @@ -391,11 +404,57 @@ void pa_stream_write(pa_stream *s, const void *data, size_t length, void (*free_ s->counter += length; } +void pa_stream_peek(pa_stream *s, void **data, size_t *length) { + assert(s && s->record_memblockq && data && length && s->state == PA_STREAM_READY && s->ref >= 1); + + if (!s->peek_memchunk.memblock) { + *data = NULL; + *length = 0; + + if (pa_memblockq_peek(s->record_memblockq, &s->peek_memchunk) < 0) + return; + + pa_memblockq_drop(s->record_memblockq, &s->peek_memchunk, s->peek_memchunk.length); + } + + *data = (char*)s->peek_memchunk.memblock->data + s->peek_memchunk.index; + *length = s->peek_memchunk.length; +} + +void pa_stream_drop(pa_stream *s) { + assert(s && s->peek_memchunk.memblock && s->state == PA_STREAM_READY && s->ref >= 1); + + s->counter += s->peek_memchunk.length; + + pa_memblock_unref(s->peek_memchunk.memblock); + + s->peek_memchunk.length = 0; + s->peek_memchunk.memblock = NULL; +} + size_t pa_stream_writable_size(pa_stream *s) { assert(s && s->ref >= 1); return s->state == PA_STREAM_READY ? s->requested_bytes : 0; } +size_t pa_stream_readable_size(pa_stream *s) { + size_t sz; + + assert(s && s->ref >= 1); + + if (s->state != PA_STREAM_READY) + return 0; + + assert(s->record_memblockq); + + sz = (size_t)pa_memblockq_get_length(s->record_memblockq); + + if (s->peek_memchunk.memblock) + sz += s->peek_memchunk.length; + + return sz; +} + pa_operation * pa_stream_drain(pa_stream *s, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata) { pa_operation *o; pa_tagstruct *t; @@ -554,7 +613,7 @@ void pa_stream_disconnect(pa_stream *s) { pa_stream_unref(s); } -void pa_stream_set_read_callback(pa_stream *s, void (*cb)(pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) { +void pa_stream_set_read_callback(pa_stream *s, void (*cb)(pa_stream *p, size_t length, void *userdata), void *userdata) { assert(s && s->ref >= 1); s->read_callback = cb; s->read_userdata = userdata; diff --git a/src/polyp/stream.h b/src/polyp/stream.h index e20cfdd49..9bbda4360 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -106,9 +106,25 @@ void pa_stream_write(pa_stream *p /**< The stream to use */, value is ignored on upload streams. */); +/** Read the next fragment from the buffer (for capture sources). + * data will point to the actual data and length will contain the size + * of the data in bytes (which can be less than a complete framgnet). + * Use pa_stream_drop() to actually remove the data from the buffer. + * \since 0.8 */ +void pa_stream_peek(pa_stream *p /**< The stream to use */, + void **data /**< Pointer to pointer that will point to data */, + size_t *length /**< The length of the data read */); + +/** Remove the current fragment. It is invalid to do this without first + * calling pa_stream_peek(). \since 0.8 */ +void pa_stream_drop(pa_stream *p); + /** Return the amount of bytes that may be written using pa_stream_write() */ size_t pa_stream_writable_size(pa_stream *p); +/** Return the ammount of bytes that may be read using pa_stream_read() \since 0.8 */ +size_t pa_stream_readable_size(pa_stream *p); + /** Drain a playback stream */ pa_operation* pa_stream_drain(pa_stream *s, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata); @@ -122,8 +138,10 @@ void pa_stream_set_state_callback(pa_stream *s, void (*cb)(pa_stream *s, void *u * written to the stream. */ void pa_stream_set_write_callback(pa_stream *p, void (*cb)(pa_stream *p, size_t length, void *userdata), void *userdata); -/** Set the callback function that is called when new data is available from the stream */ -void pa_stream_set_read_callback(pa_stream *p, void (*cb)(pa_stream *p, const void*data, size_t length, void *userdata), void *userdata); +/** Set the callback function that is called when new data is available from the stream. + * Return the number of bytes read. \since 0.8 + */ +void pa_stream_set_read_callback(pa_stream *p, void (*cb)(pa_stream *p, size_t length, void *userdata), void *userdata); /** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. \since 0.3 */ pa_operation* pa_stream_cork(pa_stream *s, int b, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 3c50402f6..a3c3f2c8b 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -105,14 +105,19 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { } /* This is called whenever new data may is available */ -static void stream_read_callback(pa_stream *s, const void*data, size_t length, void *userdata) { - assert(s && data && length); +static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { + assert(s && length); + void *data; if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); + pa_stream_peek(s, &data, &length); + assert(data && length); + if (buffer) { fprintf(stderr, "Buffer overrun, dropping incoming data\n"); + pa_stream_drop(s); return; } @@ -120,6 +125,7 @@ static void stream_read_callback(pa_stream *s, const void*data, size_t length, v assert(buffer); memcpy(buffer, data, length); buffer_index = 0; + pa_stream_drop(s); } /* This routine is called whenever the stream state changes */ From d142c12c608b6fe594549961b1a5d845b60b1a1c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 16:48:44 +0000 Subject: [PATCH 0415/1514] That's a delta parameter, not a size parameter. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@508 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/context.c b/src/polyp/context.c index c40041c59..6b7785626 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -275,7 +275,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, PA_GCC_UN break; assert(s->record_memblockq); - pa_memblockq_push(s->record_memblockq, &t, t.length); + pa_memblockq_push(s->record_memblockq, &t, 0); if (s->read_callback) s->read_callback(s, pa_stream_readable_size(s), s->read_userdata); From b26df7e4a0df6783d4b8ef4bb18d4d2ae5695912 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Feb 2006 17:00:33 +0000 Subject: [PATCH 0416/1514] Properly clear members during init. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@509 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index fef3c00f8..35de2d012 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -78,6 +78,11 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->mcalign = pa_mcalign_new(pa_frame_size(ss), c->memblock_stat); + s->peek_memchunk.length = 0; + s->peek_memchunk.memblock = NULL; + + s->record_memblockq = NULL; + s->counter = 0; s->previous_time = 0; s->previous_ipol_time = 0; From 0876b1ba82ea9c988df90ca98d202765ac697313 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 18 Feb 2006 14:58:25 +0000 Subject: [PATCH 0417/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@510 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/todo b/doc/todo index 345171a69..41333b75d 100644 --- a/doc/todo +++ b/doc/todo @@ -3,7 +3,6 @@ Architectural changes: - add API for synchronizing multiple sinks/sources to a common clock - absolutely indexed write()s from client -- remove "polyplib-" prefix Fixes: - improve module-oss-mmap latency measurement @@ -13,11 +12,10 @@ Fixes: Features: - add radio module -- xmlrpc - dbus/hal -- rendezvous autotunnel module - polish for starting polypaudio as root/system-wide instance -- export connection fd +- add threading API +- add support for auth using SCM_CREDENTIALS Long term: - pass meta info for hearing impaired @@ -35,4 +33,5 @@ Done: - channel mapping ("left", "right", "rear", "subwoofer") - hardware volume support - alsa-lib +- remove "polyplib-" prefix From 304449002cbc84fdcf235b5dfaec891278dd7085 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 04:05:16 +0000 Subject: [PATCH 0418/1514] 1) Add flexible seeking support (including absolute) for memory block queues and playback streams 2) Add support to synchronize multiple playback streams 3) add two tests for 1) and 2) 4) s/PA_ERROR/PA_ERR/ 5) s/PA_ERROR_OK/PA_OK/ 6) update simple API to deal properly with new peek/drop recording API 7) add beginnings of proper validity checking on API calls in client libs (needs to be extended) 8) report playback buffer overflows/underflows to the client 9) move client side recording mcalign stuff into the memblockq 10) create typedefs for a bunch of API callback prototypes 11) simplify handling of HUP poll() events Yes, i know, it's usually better to commit a lot of small patches instead of a single big one. In this case however, this would have contradicted the other rule: never commit broken or incomplete stuff. *** This stuff needs a lot of additional testing! *** git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@511 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 22 +- src/modules/module-combine.c | 12 +- src/modules/module-tunnel.c | 4 +- src/polyp/context.c | 73 ++-- src/polyp/def.h | 45 +- src/polyp/error.c | 37 +- src/polyp/error.h | 2 +- src/polyp/internal.h | 37 +- src/polyp/introspect.c | 24 +- src/polyp/simple.c | 41 +- src/polyp/stream.c | 372 ++++++++++++----- src/polyp/stream.h | 138 ++++--- src/polyp/subscribe.c | 2 +- src/polypcore/iochannel.c | 45 +- src/polypcore/llist.h | 10 + src/polypcore/mcalign.c | 27 +- src/polypcore/mcalign.h | 3 + src/polypcore/memblock.c | 7 +- src/polypcore/memblock.h | 1 - src/polypcore/memblockq.c | 704 ++++++++++++++++++++++---------- src/polypcore/memblockq.h | 102 +++-- src/polypcore/native-common.h | 16 +- src/polypcore/packet.c | 25 +- src/polypcore/packet.h | 2 +- src/polypcore/protocol-esound.c | 62 +-- src/polypcore/protocol-native.c | 390 +++++++++++++----- src/polypcore/protocol-simple.c | 66 ++- src/polypcore/pstream.c | 140 ++++--- src/polypcore/pstream.h | 5 +- src/polypcore/sample-util.c | 9 + src/polypcore/sample-util.h | 1 + src/polypcore/sink.c | 2 + src/polypcore/sink.h | 2 +- src/tests/memblockq-test.c | 147 +++++++ src/tests/sync-playback.c | 192 +++++++++ src/utils/pacat.c | 6 +- src/utils/pactl.c | 2 +- src/utils/paplay.c | 4 +- 38 files changed, 1983 insertions(+), 796 deletions(-) create mode 100644 src/tests/memblockq-test.c create mode 100644 src/tests/sync-playback.c diff --git a/src/Makefile.am b/src/Makefile.am index f973dc469..4cf61f27a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -180,7 +180,9 @@ noinst_PROGRAMS = \ pacat-simple \ parec-simple \ strlist-test \ - voltest + voltest \ + memblockq-test \ + sync-playback if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -248,6 +250,24 @@ mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MA mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la mainloop_test_glib12_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +memblockq_test_SOURCES = \ + tests/memblockq-test.c \ + polypcore/memblockq.c \ + polypcore/log.c \ + polypcore/memblock.c \ + polypcore/xmalloc.c \ + polypcore/util.c \ + polypcore/mcalign.c \ + polypcore/memchunk.c +memblockq_test_CFLAGS = $(AM_CFLAGS) +memblockq_test_LDADD = $(AM_LDADD) +memblockq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +sync_playback_SOURCES = tests/sync-playback.c +sync_playback_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +sync_playback_CFLAGS = $(AM_CFLAGS) +sync_playback_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + ################################### # Client library # ################################### diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index aabb8f28b..750eca672 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -144,7 +144,7 @@ static void request_memblock(struct userdata *u) { return; for (o = u->outputs; o; o = o->next) - pa_memblockq_push_align(o->memblockq, &chunk, 0); + pa_memblockq_push_align(o->memblockq, &chunk); pa_memblock_unref(chunk.memblock); } @@ -212,7 +212,15 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample o->userdata = u; o->counter = 0; - o->memblockq = pa_memblockq_new(MEMBLOCKQ_MAXLENGTH, MEMBLOCKQ_MAXLENGTH, pa_frame_size(&u->sink->sample_spec), 0, 0, sink->core->memblock_stat); + o->memblockq = pa_memblockq_new( + 0, + MEMBLOCKQ_MAXLENGTH, + MEMBLOCKQ_MAXLENGTH, + pa_frame_size(&u->sink->sample_spec), + 1, + 0, + NULL, + sink->core->memblock_stat); snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1); if (!(o->sink_input = pa_sink_input_new(sink, __FILE__, t, &u->sink->sample_spec, &u->sink->channel_map, 1, resample_method))) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 61b9bb3b3..672365887 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -214,7 +214,7 @@ static void send_bytes(struct userdata *u) { return; } - pa_pstream_send_memblock(u->pstream, u->channel, 0, &chunk); + pa_pstream_send_memblock(u->pstream, u->channel, 0, PA_SEEK_RELATIVE, &chunk); pa_memblock_unref(chunk.memblock); if (chunk.length > u->requested_bytes) @@ -442,7 +442,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *user } #ifndef TUNNEL_SINK -static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { struct userdata *u = userdata; assert(p && chunk && u); diff --git a/src/polyp/context.c b/src/polyp/context.c index 6b7785626..eac5dd231 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -74,6 +74,8 @@ static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = pa_command_request, + [PA_COMMAND_OVERFLOW] = pa_command_overflow_or_underflow, + [PA_COMMAND_UNDERFLOW] = pa_command_overflow_or_underflow, [PA_COMMAND_PLAYBACK_STREAM_KILLED] = pa_command_stream_killed, [PA_COMMAND_RECORD_STREAM_KILLED] = pa_command_stream_killed, [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event @@ -109,9 +111,10 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { PA_LLIST_HEAD_INIT(pa_stream, c->streams); PA_LLIST_HEAD_INIT(pa_operation, c->operations); - c->error = PA_ERROR_OK; + c->error = PA_OK; c->state = PA_CONTEXT_UNCONNECTED; c->ctag = 0; + c->csyncid = 0; c->state_callback = NULL; c->state_userdata = NULL; @@ -234,14 +237,24 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { void pa_context_fail(pa_context *c, int error) { assert(c); - c->error = error; + + pa_context_set_error(c, error); pa_context_set_state(c, PA_CONTEXT_FAILED); } +int pa_context_set_error(pa_context *c, int error) { + assert(error >= 0 && error < PA_ERR_MAX); + + if (c) + c->error = error; + + return error; +} + static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context *c = userdata; assert(p && c); - pa_context_fail(c, PA_ERROR_CONNECTIONTERMINATED); + pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *userdata) { @@ -252,34 +265,34 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *user if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { pa_log(__FILE__": invalid packet.\n"); - pa_context_fail(c, PA_ERROR_PROTOCOL); + pa_context_fail(c, PA_ERR_PROTOCOL); } pa_context_unref(c); } -static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, PA_GCC_UNUSED uint32_t delta, const pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { pa_context *c = userdata; pa_stream *s; - assert(p && chunk && c && chunk->memblock && chunk->memblock->data); + + assert(p); + assert(chunk); + assert(chunk->memblock); + assert(chunk->length); + assert(c); pa_context_ref(c); if ((s = pa_dynarray_get(c->record_streams, channel))) { - pa_mcalign_push(s->mcalign, chunk); - for (;;) { - pa_memchunk t; + pa_memblockq_seek(s->record_memblockq, offset, seek); + pa_memblockq_push_align(s->record_memblockq, chunk); - if (pa_mcalign_pop(s->mcalign, &t) < 0) - break; + if (s->read_callback) { + size_t l; - assert(s->record_memblockq); - pa_memblockq_push(s->record_memblockq, &t, 0); - if (s->read_callback) - s->read_callback(s, pa_stream_readable_size(s), s->read_userdata); - - pa_memblock_unref(t.memblock); + if ((l = pa_memblockq_get_length(s->record_memblockq)) > 0) + s->read_callback(s, l, s->read_userdata); } } @@ -293,14 +306,14 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { assert(t); if (pa_tagstruct_getu32(t, &c->error) < 0) { - pa_context_fail(c, PA_ERROR_PROTOCOL); + pa_context_fail(c, PA_ERR_PROTOCOL); return -1; } } else if (command == PA_COMMAND_TIMEOUT) - c->error = PA_ERROR_TIMEOUT; + c->error = PA_ERR_TIMEOUT; else { - pa_context_fail(c, PA_ERROR_PROTOCOL); + pa_context_fail(c, PA_ERR_PROTOCOL); return -1; } @@ -316,7 +329,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(c, command, t) < 0) - pa_context_fail(c, PA_ERROR_PROTOCOL); + pa_context_fail(c, PA_ERR_PROTOCOL); pa_context_fail(c, c->error); goto finish; @@ -368,7 +381,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) { assert(c->pdispatch); if (!c->conf->cookie_valid) { - pa_context_fail(c, PA_ERROR_AUTHKEY); + pa_context_fail(c, PA_ERR_AUTHKEY); goto finish; } @@ -401,7 +414,7 @@ static int context_connect_spawn(pa_context *c) { if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { pa_log(__FILE__": socketpair() failed: %s\n", strerror(errno)); - pa_context_fail(c, PA_ERROR_INTERNAL); + pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } @@ -415,7 +428,7 @@ static int context_connect_spawn(pa_context *c) { if ((pid = fork()) < 0) { pa_log(__FILE__": fork() failed: %s\n", strerror(errno)); - pa_context_fail(c, PA_ERROR_INTERNAL); + pa_context_fail(c, PA_ERR_INTERNAL); if (c->spawn_api.postfork) c->spawn_api.postfork(); @@ -471,10 +484,10 @@ static int context_connect_spawn(pa_context *c) { if (r < 0) { pa_log(__FILE__": waitpid() failed: %s\n", strerror(errno)); - pa_context_fail(c, PA_ERROR_INTERNAL); + pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); goto fail; } @@ -527,7 +540,7 @@ static int try_next_connection(pa_context *c) { } #endif - pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); goto finish; } @@ -569,7 +582,7 @@ static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userd goto finish; } - pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED); + pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); goto finish; } @@ -593,7 +606,7 @@ int pa_context_connect(pa_context *c, const char *server, int spawn, const pa_sp if (server) { if (!(c->server_list = pa_strlist_parse(server))) { - pa_context_fail(c, PA_ERROR_INVALIDSERVER); + pa_context_fail(c, PA_ERR_INVALIDSERVER); goto finish; } } else { @@ -759,7 +772,7 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_U success = 0; } else if (!pa_tagstruct_eof(t)) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } diff --git a/src/polyp/def.h b/src/polyp/def.h index ba35b31e8..f8e0bed42 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -47,7 +47,7 @@ typedef enum pa_context_state { /** The state of a stream */ typedef enum pa_stream_state { - PA_STREAM_DISCONNECTED, /**< The stream is not yet connected to any sink or source */ + PA_STREAM_UNCONNECTED, /**< The stream is not yet connected to any sink or source */ PA_STREAM_CREATING, /**< The stream is being created */ PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */ PA_STREAM_FAILED, /**< An error occured that made the stream invalid */ @@ -103,22 +103,24 @@ typedef struct pa_buffer_attr { /** Error values as used by pa_context_errno(). Use pa_strerror() to convert these values to human readable strings */ enum { - PA_ERROR_OK, /**< No error */ - PA_ERROR_ACCESS, /**< Access failure */ - PA_ERROR_COMMAND, /**< Unknown command */ - PA_ERROR_INVALID, /**< Invalid argument */ - PA_ERROR_EXIST, /**< Entity exists */ - PA_ERROR_NOENTITY, /**< No such entity */ - PA_ERROR_CONNECTIONREFUSED, /**< Connection refused */ - PA_ERROR_PROTOCOL, /**< Protocol error */ - PA_ERROR_TIMEOUT, /**< Timeout */ - PA_ERROR_AUTHKEY, /**< No authorization key */ - PA_ERROR_INTERNAL, /**< Internal error */ - PA_ERROR_CONNECTIONTERMINATED, /**< Connection terminated */ - PA_ERROR_KILLED, /**< Entity killed */ - PA_ERROR_INVALIDSERVER, /**< Invalid server */ - PA_ERROR_INITFAILED, /**< Module initialization failed */ - PA_ERROR_MAX /**< Not really an error but the first invalid error code */ + PA_OK = 0, /**< No error */ + PA_ERR_ACCESS, /**< Access failure */ + PA_ERR_COMMAND, /**< Unknown command */ + PA_ERR_INVALID, /**< Invalid argument */ + PA_ERR_EXIST, /**< Entity exists */ + PA_ERR_NOENTITY, /**< No such entity */ + PA_ERR_CONNECTIONREFUSED, /**< Connection refused */ + PA_ERR_PROTOCOL, /**< Protocol error */ + PA_ERR_TIMEOUT, /**< Timeout */ + PA_ERR_AUTHKEY, /**< No authorization key */ + PA_ERR_INTERNAL, /**< Internal error */ + PA_ERR_CONNECTIONTERMINATED, /**< Connection terminated */ + PA_ERR_KILLED, /**< Entity killed */ + PA_ERR_INVALIDSERVER, /**< Invalid server */ + PA_ERR_MODINITFAILED, /**< Module initialization failed */ + PA_ERR_BADSTATE, /**< Bad state */ + PA_ERR_NODATA, /**< No data */ + PA_ERR_MAX /**< Not really an error but the first invalid error code */ }; /** Subscription event mask, as used by pa_context_subscribe() */ @@ -208,6 +210,15 @@ typedef struct pa_spawn_api { * passed to the new process. */ } pa_spawn_api; +/** Seek type \since 0.8*/ +typedef enum pa_seek_mode { + PA_SEEK_RELATIVE = 0, /**< Seek relatively to the write index */ + PA_SEEK_ABSOLUTE = 1, /**< Seek relatively to the start of the buffer queue */ + PA_SEEK_RELATIVE_ON_READ = 2, /**< Seek relatively to the read index */ + PA_SEEK_RELATIVE_END = 3, /**< Seek relatively to the current end of the buffer queue */ +} pa_seek_mode_t; + + PA_C_DECL_END #endif diff --git a/src/polyp/error.c b/src/polyp/error.c index ece77bf2c..eff37cc86 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -30,25 +30,28 @@ #include "error.h" -static const char* const errortab[PA_ERROR_MAX] = { - [PA_ERROR_OK] = "OK", - [PA_ERROR_ACCESS] = "Access denied", - [PA_ERROR_COMMAND] = "Unknown command", - [PA_ERROR_INVALID] = "Invalid argument", - [PA_ERROR_EXIST] = "Entity exists", - [PA_ERROR_NOENTITY] = "No such entity", - [PA_ERROR_CONNECTIONREFUSED] = "Connection refused", - [PA_ERROR_PROTOCOL] = "Protocol error", - [PA_ERROR_TIMEOUT] = "Timeout", - [PA_ERROR_AUTHKEY] = "No authorization key", - [PA_ERROR_INTERNAL] = "Internal error", - [PA_ERROR_CONNECTIONTERMINATED] = "Connection terminated", - [PA_ERROR_KILLED] = "Entity killed", - [PA_ERROR_INVALIDSERVER] = "Invalid server", +static const char* const errortab[PA_ERR_MAX] = { + [PA_OK] = "OK", + [PA_ERR_ACCESS] = "Access denied", + [PA_ERR_COMMAND] = "Unknown command", + [PA_ERR_INVALID] = "Invalid argument", + [PA_ERR_EXIST] = "Entity exists", + [PA_ERR_NOENTITY] = "No such entity", + [PA_ERR_CONNECTIONREFUSED] = "Connection refused", + [PA_ERR_PROTOCOL] = "Protocol error", + [PA_ERR_TIMEOUT] = "Timeout", + [PA_ERR_AUTHKEY] = "No authorization key", + [PA_ERR_INTERNAL] = "Internal error", + [PA_ERR_CONNECTIONTERMINATED] = "Connection terminated", + [PA_ERR_KILLED] = "Entity killed", + [PA_ERR_INVALIDSERVER] = "Invalid server", + [PA_ERR_MODINITFAILED] = "Module initalization failed", + [PA_ERR_BADSTATE] = "Bad state", + [PA_ERR_NODATA] = "No data", }; -const char*pa_strerror(uint32_t error) { - if (error >= PA_ERROR_MAX) +const char*pa_strerror(int error) { + if (error < 0 || error >= PA_ERR_MAX) return NULL; return errortab[error]; diff --git a/src/polyp/error.h b/src/polyp/error.h index ff2507b21..9856c1af3 100644 --- a/src/polyp/error.h +++ b/src/polyp/error.h @@ -31,7 +31,7 @@ PA_C_DECL_BEGIN /** Return a human readable error message for the specified numeric error code */ -const char* pa_strerror(uint32_t error); +const char* pa_strerror(int error); PA_C_DECL_END diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 7f4d38ac5..578969ee4 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -54,8 +54,9 @@ struct pa_context { pa_dynarray *record_streams, *playback_streams; PA_LLIST_HEAD(pa_stream, streams); PA_LLIST_HEAD(pa_operation, operations); - + uint32_t ctag; + uint32_t csyncid; uint32_t error; pa_context_state_t state; @@ -90,6 +91,7 @@ struct pa_stream { pa_sample_spec sample_spec; pa_channel_map channel_map; uint32_t channel; + uint32_t syncid; int channel_valid; uint32_t device_index; pa_stream_direction_t direction; @@ -98,7 +100,6 @@ struct pa_stream { pa_usec_t previous_time; pa_usec_t previous_ipol_time; pa_stream_state_t state; - pa_mcalign *mcalign; pa_memchunk peek_memchunk; pa_memblockq *record_memblockq; @@ -110,14 +111,20 @@ struct pa_stream { pa_time_event *ipol_event; int ipol_requested; - void (*state_callback)(pa_stream*c, void *userdata); + pa_stream_notify_cb_t state_callback; void *state_userdata; - void (*read_callback)(pa_stream *p, size_t length, void *userdata); + pa_stream_request_cb_t read_callback; void *read_userdata; - void (*write_callback)(pa_stream *p, size_t length, void *userdata); + pa_stream_request_cb_t write_callback; void *write_userdata; + + pa_stream_notify_cb_t overflow_callback; + void *overflow_userdata; + + pa_stream_notify_cb_t underflow_callback; + void *underflow_userdata; }; typedef void (*pa_operation_callback)(void); @@ -136,6 +143,7 @@ struct pa_operation { void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); pa_operation *pa_operation_new(pa_context *c, pa_stream *s); void pa_operation_done(pa_operation *o); @@ -146,6 +154,7 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_context_fail(pa_context *c, int error); +int pa_context_set_error(pa_context *c, int error); void pa_context_set_state(pa_context *c, pa_context_state_t st); int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t); pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, void (*internal_callback)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata), void (*cb)(void), void *userdata); @@ -154,5 +163,23 @@ void pa_stream_set_state(pa_stream *s, pa_stream_state_t st); void pa_stream_trash_ipol(pa_stream *s); +#define PA_CHECK_VALIDITY(context, expression, error) do { \ + if (!(expression)) \ + return -pa_context_set_error((context), (error)); \ +} while(0) + +#define PA_CHECK_VALIDITY_RETURN_NULL(context, expression, error) do { \ + if (!(expression)) { \ + pa_context_set_error((context), (error)); \ + return NULL; \ + } \ +} while(0) + +#define PA_CHECK_VALIDITY_RETURN_ANY(context, expression, error, value) do { \ + if (!(expression)) { \ + pa_context_set_error((context), (error)); \ + return value; \ + } \ +} while(0) #endif diff --git a/src/polyp/introspect.c b/src/polyp/introspect.c index 4af724b43..75ce3ff99 100644 --- a/src/polyp/introspect.c +++ b/src/polyp/introspect.c @@ -52,7 +52,7 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNU pa_tagstruct_getu32(t, &i.memblock_allocated_size) < 0 || pa_tagstruct_getu32(t, &i.scache_size) < 0 || !pa_tagstruct_eof(t)) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -92,7 +92,7 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_getu32(t, &i.cookie) < 0 || !pa_tagstruct_eof(t)) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -139,7 +139,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P pa_tagstruct_get_usec(t, &i.latency) < 0 || pa_tagstruct_gets(t, &i.driver) < 0) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -234,7 +234,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_get_usec(t, &i.latency) < 0 || pa_tagstruct_gets(t, &i.driver) < 0) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -322,7 +322,7 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || pa_tagstruct_gets(t, &i.driver) < 0 ) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -389,7 +389,7 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_gets(t, &i.argument) < 0 || pa_tagstruct_getu32(t, &i.n_used) < 0 || pa_tagstruct_get_boolean(t, &i.auto_unload) < 0) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -464,7 +464,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm pa_tagstruct_gets(t, &i.resample_method) < 0 || pa_tagstruct_gets(t, &i.driver) < 0) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -538,7 +538,7 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c pa_tagstruct_gets(t, &i.resample_method) < 0 || pa_tagstruct_gets(t, &i.driver) < 0) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -677,7 +677,7 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_get_boolean(t, &i.lazy) < 0 || pa_tagstruct_gets(t, &i.filename) < 0) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -787,7 +787,7 @@ static void load_module_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUS } else if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -848,7 +848,7 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman pa_tagstruct_getu32(t, &i.type) < 0 || pa_tagstruct_gets(t, &i.module) < 0 || pa_tagstruct_gets(t, &i.argument) < 0) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -926,7 +926,7 @@ static void context_add_autoload_callback(pa_pdispatch *pd, uint32_t command, PA idx = PA_INVALID_INDEX; } else if (pa_tagstruct_getu32(t, &idx) || !pa_tagstruct_eof(t)) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } diff --git a/src/polyp/simple.c b/src/polyp/simple.c index e14cab2eb..8a20c2239 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -45,13 +45,11 @@ struct pa_simple { int dead; - void *read_data; + const void *read_data; size_t read_index, read_length; pa_usec_t latency; }; -static void read_callback(pa_stream *s, const void*data, size_t length, void *userdata); - static int check_error(pa_simple *p, int *rerror) { pa_context_state_t cst; pa_stream_state_t sst; @@ -92,7 +90,7 @@ static int iterate(pa_simple *p, int block, int *rerror) { do { if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) { if (rerror) - *rerror = PA_ERROR_INTERNAL; + *rerror = PA_ERR_INTERNAL; return -1; } @@ -106,7 +104,7 @@ static int iterate(pa_simple *p, int block, int *rerror) { if (pa_mainloop_iterate(p->mainloop, 0, NULL) < 0) { if (rerror) - *rerror = PA_ERROR_INTERNAL; + *rerror = PA_ERR_INTERNAL; return -1; } @@ -128,7 +126,7 @@ pa_simple* pa_simple_new( int *rerror) { pa_simple *p; - int error = PA_ERROR_INTERNAL; + int error = PA_ERR_INTERNAL; assert(ss && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); p = pa_xmalloc(sizeof(pa_simple)); @@ -157,7 +155,7 @@ pa_simple* pa_simple_new( goto fail; if (dir == PA_STREAM_PLAYBACK) - pa_stream_connect_playback(p->stream, dev, attr, 0, NULL); + pa_stream_connect_playback(p->stream, dev, attr, 0, NULL, NULL); else pa_stream_connect_record(p->stream, dev, attr, 0); @@ -167,8 +165,6 @@ pa_simple* pa_simple_new( goto fail; } - pa_stream_set_read_callback(p->stream, read_callback, p); - return p; fail: @@ -181,8 +177,6 @@ fail: void pa_simple_free(pa_simple *s) { assert(s); - pa_xfree(s->read_data); - if (s->stream) pa_stream_unref(s->stream); @@ -215,7 +209,7 @@ int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) { if (l > length) l = length; - pa_stream_write(p->stream, data, l, NULL, 0); + pa_stream_write(p->stream, data, l, NULL, 0, PA_SEEK_RELATIVE); data = (const uint8_t*) data + l; length -= l; } @@ -227,19 +221,6 @@ int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) { return 0; } -static void read_callback(pa_stream *s, const void*data, size_t length, void *userdata) { - pa_simple *p = userdata; - assert(s && data && length && p); - - if (p->read_data) { - pa_log(__FILE__": Buffer overflow, dropping incoming memory blocks.\n"); - pa_xfree(p->read_data); - } - - p->read_data = pa_xmemdup(data, p->read_length = length); - p->read_index = 0; -} - int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { assert(p && data && p->direction == PA_STREAM_RECORD); @@ -251,13 +232,18 @@ int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { } while (length > 0) { + + if (!p->read_data) + if (pa_stream_peek(p->stream, &p->read_data, &p->read_length) >= 0) + p->read_index = 0; + if (p->read_data) { size_t l = length; if (p->read_length <= l) l = p->read_length; - memcpy(data, (uint8_t*) p->read_data+p->read_index, l); + memcpy(data, (const uint8_t*) p->read_data+p->read_index, l); data = (uint8_t*) data + l; length -= l; @@ -266,8 +252,9 @@ int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { p->read_length -= l; if (!p->read_length) { - pa_xfree(p->read_data); + pa_stream_drop(p->stream); p->read_data = NULL; + p->read_length = 0; p->read_index = 0; } diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 35de2d012..5497f0c42 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -39,14 +40,11 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) { pa_stream *s; + assert(c); - assert(ss); - if (!pa_sample_spec_valid(ss)) - return NULL; - - if (map && !pa_channel_map_valid(map)) - return NULL; + PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, !map || pa_channel_map_valid(map), PA_ERR_INVALID); s = pa_xnew(pa_stream, 1); s->ref = 1; @@ -59,6 +57,10 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->write_userdata = NULL; s->state_callback = NULL; s->state_userdata = NULL; + s->overflow_callback = NULL; + s->overflow_userdata = NULL; + s->underflow_callback = NULL; + s->underflow_userdata = NULL; s->direction = PA_STREAM_NODIRECTION; s->name = pa_xstrdup(name); @@ -71,13 +73,13 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->channel = 0; s->channel_valid = 0; + s->syncid = c->csyncid++; s->device_index = PA_INVALID_INDEX; s->requested_bytes = 0; - s->state = PA_STREAM_DISCONNECTED; + s->state = PA_STREAM_UNCONNECTED; memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - s->mcalign = pa_mcalign_new(pa_frame_size(ss), c->memblock_stat); - + s->peek_memchunk.index = 0; s->peek_memchunk.length = 0; s->peek_memchunk.memblock = NULL; @@ -114,42 +116,52 @@ static void stream_free(pa_stream *s) { if (s->record_memblockq) pa_memblockq_free(s->record_memblockq); - pa_mcalign_free(s->mcalign); - pa_xfree(s->name); pa_xfree(s); } void pa_stream_unref(pa_stream *s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); if (--(s->ref) == 0) stream_free(s); } pa_stream* pa_stream_ref(pa_stream *s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); + s->ref++; return s; } pa_stream_state_t pa_stream_get_state(pa_stream *s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); + return s->state; } pa_context* pa_stream_get_context(pa_stream *s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); + return s->context; } uint32_t pa_stream_get_index(pa_stream *s) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX); + return s->device_index; } void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { - assert(s && s->ref >= 1); + assert(s); + assert(s->ref >= 1); if (s->state == st) return; @@ -159,6 +171,8 @@ void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { s->state = st; if ((st == PA_STREAM_FAILED || st == PA_STREAM_TERMINATED) && s->context) { + /* Detach from context */ + if (s->channel_valid) pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); @@ -182,14 +196,14 @@ void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED if (pa_tagstruct_getu32(t, &channel) < 0 || !pa_tagstruct_eof(t)) { - pa_context_fail(c, PA_ERROR_PROTOCOL); + pa_context_fail(c, PA_ERR_PROTOCOL); goto finish; } if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) goto finish; - c->error = PA_ERROR_KILLED; + c->error = PA_ERR_KILLED; pa_stream_set_state(s, PA_STREAM_FAILED); finish: @@ -207,24 +221,55 @@ void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32 if (pa_tagstruct_getu32(t, &channel) < 0 || pa_tagstruct_getu32(t, &bytes) < 0 || !pa_tagstruct_eof(t)) { - pa_context_fail(c, PA_ERROR_PROTOCOL); + pa_context_fail(c, PA_ERR_PROTOCOL); goto finish; } if (!(s = pa_dynarray_get(c->playback_streams, channel))) goto finish; - if (s->state != PA_STREAM_READY) + if (s->state == PA_STREAM_READY) { + s->requested_bytes += bytes; + + if (s->requested_bytes > 0 && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); + } + +finish: + pa_context_unref(c); +} + +void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_stream *s; + pa_context *c = userdata; + uint32_t channel; + + assert(pd); + assert(command == PA_COMMAND_OVERFLOW || command == PA_COMMAND_UNDERFLOW); + assert(t); + assert(c); + + pa_context_ref(c); + + if (pa_tagstruct_getu32(t, &channel) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + if (!(s = pa_dynarray_get(c->playback_streams, channel))) goto finish; - pa_stream_ref(s); - - s->requested_bytes += bytes; + if (s->state == PA_STREAM_READY) { - if (s->requested_bytes && s->write_callback) - s->write_callback(s, s->requested_bytes, s->write_userdata); - - pa_stream_unref(s); + if (command == PA_COMMAND_OVERFLOW) { + if (s->overflow_callback) + s->overflow_callback(s, s->overflow_userdata); + } else if (command == PA_COMMAND_UNDERFLOW) { + if (s->underflow_callback) + s->underflow_callback(s, s->underflow_userdata); + } + } finish: pa_context_unref(c); @@ -270,14 +315,21 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || ((s->direction != PA_STREAM_RECORD) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0) || !pa_tagstruct_eof(t)) { - pa_context_fail(s->context, PA_ERROR_PROTOCOL); + pa_context_fail(s->context, PA_ERR_PROTOCOL); goto finish; } if (s->direction == PA_STREAM_RECORD) { assert(!s->record_memblockq); - s->record_memblockq = pa_memblockq_new(s->buffer_attr.maxlength, 0, - pa_frame_size(&s->sample_spec), 0, 0, s->context->memblock_stat); + s->record_memblockq = pa_memblockq_new( + 0, + s->buffer_attr.maxlength, + 0, + pa_frame_size(&s->sample_spec), + 1, + 0, + NULL, + s->context->memblock_stat); assert(s->record_memblockq); } @@ -303,13 +355,32 @@ finish: pa_stream_unref(s); } -static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags, const pa_cvolume *volume) { +static int create_stream( + pa_stream_direction_t direction, + pa_stream *s, + const char *dev, + const pa_buffer_attr *attr, + pa_stream_flags_t flags, + const pa_cvolume *volume, + pa_stream *sync_stream) { + pa_tagstruct *t; uint32_t tag; - assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED); + + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, (flags & ~(PA_STREAM_START_CORKED|PA_STREAM_INTERPOLATE_LATENCY)) == 0, PA_ERR_INVALID); + PA_CHECK_VALIDITY(s->context, direction == PA_STREAM_PLAYBACK || flags == 0, PA_ERR_INVALID); pa_stream_ref(s); + s->direction = direction; + + if (sync_stream) + s->syncid = sync_stream->syncid; + s->interpolate = !!(flags & PA_STREAM_INTERPOLATE_LATENCY); pa_stream_trash_ipol(s); @@ -336,25 +407,28 @@ static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *a dev = s->context->conf->default_source; } - pa_tagstruct_put(t, - PA_TAG_U32, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM, - PA_TAG_U32, tag = s->context->ctag++, - PA_TAG_STRING, s->name, - PA_TAG_SAMPLE_SPEC, &s->sample_spec, - PA_TAG_CHANNEL_MAP, &s->channel_map, - PA_TAG_U32, PA_INVALID_INDEX, - PA_TAG_STRING, dev, - PA_TAG_U32, s->buffer_attr.maxlength, - PA_TAG_BOOLEAN, !!(flags & PA_STREAM_START_CORKED), - PA_TAG_INVALID); + pa_tagstruct_put( + t, + PA_TAG_U32, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM, + PA_TAG_U32, tag = s->context->ctag++, + PA_TAG_STRING, s->name, + PA_TAG_SAMPLE_SPEC, &s->sample_spec, + PA_TAG_CHANNEL_MAP, &s->channel_map, + PA_TAG_U32, PA_INVALID_INDEX, + PA_TAG_STRING, dev, + PA_TAG_U32, s->buffer_attr.maxlength, + PA_TAG_BOOLEAN, !!(flags & PA_STREAM_START_CORKED), + PA_TAG_INVALID); if (s->direction == PA_STREAM_PLAYBACK) { pa_cvolume cv; - pa_tagstruct_put(t, - PA_TAG_U32, s->buffer_attr.tlength, - PA_TAG_U32, s->buffer_attr.prebuf, - PA_TAG_U32, s->buffer_attr.minreq, - PA_TAG_INVALID); + pa_tagstruct_put( + t, + PA_TAG_U32, s->buffer_attr.tlength, + PA_TAG_U32, s->buffer_attr.prebuf, + PA_TAG_U32, s->buffer_attr.minreq, + PA_TAG_U32, s->syncid, + PA_TAG_INVALID); if (!volume) { pa_cvolume_reset(&cv, s->sample_spec.channels); @@ -369,23 +443,57 @@ static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *a pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s); pa_stream_unref(s); + return 0; } -void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags, pa_cvolume *volume) { - assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); - s->direction = PA_STREAM_PLAYBACK; - create_stream(s, dev, attr, flags, volume); +int pa_stream_connect_playback( + pa_stream *s, + const char *dev, + const pa_buffer_attr *attr, + pa_stream_flags_t flags, + pa_cvolume *volume, + pa_stream *sync_stream) { + + assert(s); + assert(s->ref >= 1); + + return create_stream(PA_STREAM_PLAYBACK, s, dev, attr, flags, volume, sync_stream); } -void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags) { - assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1); - s->direction = PA_STREAM_RECORD; - create_stream(s, dev, attr, flags, 0); +int pa_stream_connect_record( + pa_stream *s, + const char *dev, + const pa_buffer_attr *attr, + pa_stream_flags_t flags) { + + assert(s); + assert(s->ref >= 1); + + return create_stream(PA_STREAM_RECORD, s, dev, attr, flags, NULL, NULL); } -void pa_stream_write(pa_stream *s, const void *data, size_t length, void (*free_cb)(void *p), size_t delta) { +int pa_stream_write( + pa_stream *s, + const void *data, + size_t length, + void (*free_cb)(void *p), + int64_t offset, + pa_seek_mode_t seek) { + pa_memchunk chunk; - assert(s && s->context && data && length && s->state == PA_STREAM_READY && s->ref >= 1); + + assert(s); + assert(s->ref >= 1); + assert(s->context); + assert(data); + + PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK || s->direction == PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, seek <= PA_SEEK_RELATIVE_END, PA_ERR_INVALID); + PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK || (seek == PA_SEEK_RELATIVE && offset == 0), PA_ERR_INVALID); + + if (length <= 0) + return 0; if (free_cb) { chunk.memblock = pa_memblock_new_user((void*) data, length, free_cb, 1, s->context->memblock_stat); @@ -398,7 +506,7 @@ void pa_stream_write(pa_stream *s, const void *data, size_t length, void (*free_ chunk.index = 0; chunk.length = length; - pa_pstream_send_memblock(s->context->pstream, s->channel, delta, &chunk); + pa_pstream_send_memblock(s->context->pstream, s->channel, offset, seek, &chunk); pa_memblock_unref(chunk.memblock); if (length < s->requested_bytes) @@ -407,72 +515,87 @@ void pa_stream_write(pa_stream *s, const void *data, size_t length, void (*free_ s->requested_bytes = 0; s->counter += length; + return 0; } -void pa_stream_peek(pa_stream *s, void **data, size_t *length) { - assert(s && s->record_memblockq && data && length && s->state == PA_STREAM_READY && s->ref >= 1); +int pa_stream_peek(pa_stream *s, const void **data, size_t *length) { + assert(s); + assert(s->ref >= 1); + assert(data); + assert(length); + PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE); + if (!s->peek_memchunk.memblock) { - *data = NULL; - *length = 0; - if (pa_memblockq_peek(s->record_memblockq, &s->peek_memchunk) < 0) - return; - - pa_memblockq_drop(s->record_memblockq, &s->peek_memchunk, s->peek_memchunk.length); + if (pa_memblockq_peek(s->record_memblockq, &s->peek_memchunk) < 0) { + *data = NULL; + *length = 0; + return 0; + } } - *data = (char*)s->peek_memchunk.memblock->data + s->peek_memchunk.index; + *data = (const char*) s->peek_memchunk.memblock->data + s->peek_memchunk.index; *length = s->peek_memchunk.length; + return 0; } -void pa_stream_drop(pa_stream *s) { - assert(s && s->peek_memchunk.memblock && s->state == PA_STREAM_READY && s->ref >= 1); +int pa_stream_drop(pa_stream *s) { + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->peek_memchunk.memblock, PA_ERR_BADSTATE); + + pa_memblockq_drop(s->record_memblockq, &s->peek_memchunk, s->peek_memchunk.length); + + pa_memblock_unref(s->peek_memchunk.memblock); + s->peek_memchunk.length = 0; + s->peek_memchunk.index = 0; + s->peek_memchunk.memblock = NULL; s->counter += s->peek_memchunk.length; - - pa_memblock_unref(s->peek_memchunk.memblock); - - s->peek_memchunk.length = 0; - s->peek_memchunk.memblock = NULL; + return 0; } size_t pa_stream_writable_size(pa_stream *s) { - assert(s && s->ref >= 1); - return s->state == PA_STREAM_READY ? s->requested_bytes : 0; + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, (size_t) -1); + + return s->requested_bytes; } size_t pa_stream_readable_size(pa_stream *s) { - size_t sz; + assert(s); + assert(s->ref >= 1); - assert(s && s->ref >= 1); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, (size_t) -1); - if (s->state != PA_STREAM_READY) - return 0; - - assert(s->record_memblockq); - - sz = (size_t)pa_memblockq_get_length(s->record_memblockq); - - if (s->peek_memchunk.memblock) - sz += s->peek_memchunk.length; - - return sz; + return pa_memblockq_get_length(s->record_memblockq); } pa_operation * pa_stream_drain(pa_stream *s, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); + + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); o = pa_operation_new(s->context, s); - assert(o); o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); @@ -501,7 +624,7 @@ static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_get_timeval(t, &remote) < 0 || pa_tagstruct_getu64(t, &i.counter) < 0 || !pa_tagstruct_eof(t)) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } else { pa_gettimeofday(&now); @@ -549,15 +672,18 @@ pa_operation* pa_stream_get_latency_info(pa_stream *s, void (*cb)(pa_stream *p, pa_operation *o; pa_tagstruct *t; struct timeval now; - assert(s && s->direction != PA_STREAM_UPLOAD); + + assert(s); + assert(s->ref >= 1); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + o = pa_operation_new(s->context, s); - assert(o); o->callback = (pa_operation_callback) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); @@ -585,7 +711,7 @@ void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN pa_stream_set_state(s, PA_STREAM_FAILED); goto finish; } else if (!pa_tagstruct_eof(t)) { - pa_context_fail(s->context, PA_ERROR_PROTOCOL); + pa_context_fail(s->context, PA_ERR_PROTOCOL); goto finish; } @@ -595,18 +721,19 @@ finish: pa_stream_unref(s); } -void pa_stream_disconnect(pa_stream *s) { +int pa_stream_disconnect(pa_stream *s) { pa_tagstruct *t; uint32_t tag; - assert(s && s->ref >= 1); - if (!s->channel_valid || !s->context->state == PA_CONTEXT_READY) - return; + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY(s->context, s->channel_valid, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); pa_stream_ref(s); t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); @@ -616,26 +743,49 @@ void pa_stream_disconnect(pa_stream *s) { pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s); pa_stream_unref(s); + return 0; } -void pa_stream_set_read_callback(pa_stream *s, void (*cb)(pa_stream *p, size_t length, void *userdata), void *userdata) { - assert(s && s->ref >= 1); +void pa_stream_set_read_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata) { + assert(s); + assert(s->ref >= 1); + s->read_callback = cb; s->read_userdata = userdata; } -void pa_stream_set_write_callback(pa_stream *s, void (*cb)(pa_stream *p, size_t length, void *userdata), void *userdata) { - assert(s && s->ref >= 1); +void pa_stream_set_write_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata) { + assert(s); + assert(s->ref >= 1); + s->write_callback = cb; s->write_userdata = userdata; } -void pa_stream_set_state_callback(pa_stream *s, void (*cb)(pa_stream *s, void *userdata), void *userdata) { - assert(s && s->ref >= 1); +void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { + assert(s); + assert(s->ref >= 1); + s->state_callback = cb; s->state_userdata = userdata; } +void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { + assert(s); + assert(s->ref >= 1); + + s->overflow_callback = cb; + s->overflow_userdata = userdata; +} + +void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { + assert(s); + assert(s->ref >= 1); + + s->underflow_callback = cb; + s->underflow_userdata = userdata; +} + void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; @@ -647,7 +797,7 @@ void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN success = 0; } else if (!pa_tagstruct_eof(t)) { - pa_context_fail(o->context, PA_ERROR_PROTOCOL); + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } diff --git a/src/polyp/stream.h b/src/polyp/stream.h index 9bbda4360..ce5359637 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -40,8 +40,27 @@ PA_C_DECL_BEGIN * An opaque stream for playback or recording */ typedef struct pa_stream pa_stream; +/** A generic callback for operation completion */ +typedef void (*pa_stream_success_cb_t) (pa_stream*s, int success, void *userdata); + +/** A generic free callback */ +typedef void (*pa_free_cb_t)(void *p); + +/** A generic request callback */ +typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t length, void *userdata); + +/** A generic notification callback */ +typedef void (*pa_stream_notify_cb_t)(pa_stream *p, void *userdata); + +/** Callback prototype for pa_stream_get_latency_info() */ +typedef void (*pa_stream_get_latency_info_cb_t)(pa_stream *p, const pa_latency_info *i, void *userdata); + /** Create a new, unconnected stream with the specified name and sample type */ -pa_stream* pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map); +pa_stream* pa_stream_new( + pa_context *c, + const char *name, + const pa_sample_spec *ss, + const pa_channel_map *map); /** Decrease the reference counter by one */ void pa_stream_unref(pa_stream *s); @@ -59,108 +78,101 @@ pa_context* pa_stream_get_context(pa_stream *p); uint32_t pa_stream_get_index(pa_stream *s); /** Connect the stream to a sink */ -void pa_stream_connect_playback( - pa_stream *s, - const char *dev, - const pa_buffer_attr *attr, - pa_stream_flags_t flags, - pa_cvolume *volume); +int pa_stream_connect_playback( + pa_stream *s /**< The stream to connect to a sink */, + const char *dev /**< Name of the sink to connect to, or NULL for default */ , + const pa_buffer_attr *attr /**< Buffering attributes, or NULL for default */, + pa_stream_flags_t flags /**< Additional flags, or 0 for default */, + pa_cvolume *volume /**< Initial volume, or NULL for default */, + pa_stream *sync_stream /**< Synchronize this stream with the specified one, or NULL for a standalone stream*/); /** Connect the stream to a source */ -void pa_stream_connect_record( - pa_stream *s, - const char *dev, - const pa_buffer_attr *attr, - pa_stream_flags_t flags); +int pa_stream_connect_record( + pa_stream *s, + const char *dev, + const pa_buffer_attr *attr, + pa_stream_flags_t flags); /** Disconnect a stream from a source/sink */ -void pa_stream_disconnect(pa_stream *s); +int pa_stream_disconnect(pa_stream *s); /** Write some data to the server (for playback sinks), if free_cb is * non-NULL this routine is called when all data has been written out * and an internal reference to the specified data is kept, the data * is not copied. If NULL, the data is copied into an internal - * buffer. */ -void pa_stream_write(pa_stream *p /**< The stream to use */, - const void *data /**< The data to write */, - size_t length /**< The length of the data to write */, - void (*free_cb)(void *p) /**< A cleanup routine for the data or NULL to request an internal copy */, - size_t delta /**< Drop this many - bytes in the playback - buffer before writing - this data. Use - (size_t) -1 for - clearing the whole - playback - buffer. Normally you - will specify 0 here, - i.e. append to the - playback buffer. If - the value given here - is greater than the - buffered data length - the buffer is cleared - and the data is - written to the - buffer's start. This - value is ignored on - upload streams. */); + * buffer. The client my freely seek around in the output buffer. For + * most applications passing 0 and PA_SEEK_RELATIVE as arguments for + * offset and seek should be useful.*/ +int pa_stream_write( + pa_stream *p /**< The stream to use */, + const void *data /**< The data to write */, + size_t length /**< The length of the data to write */, + pa_free_cb_t free_cb /**< A cleanup routine for the data or NULL to request an internal copy */, + int64_t offset, /**< Offset for seeking, must be 0 for upload streams */ + pa_seek_mode_t seek /**< Seek mode, must be PA_SEEK_RELATIVE for upload streams */); -/** Read the next fragment from the buffer (for capture sources). +/** Read the next fragment from the buffer (for recording). * data will point to the actual data and length will contain the size * of the data in bytes (which can be less than a complete framgnet). - * Use pa_stream_drop() to actually remove the data from the buffer. - * \since 0.8 */ -void pa_stream_peek(pa_stream *p /**< The stream to use */, - void **data /**< Pointer to pointer that will point to data */, - size_t *length /**< The length of the data read */); + * Use pa_stream_drop() to actually remove the data from the + * buffer. If no data is available will return a NULL pointer \since 0.8 */ +int pa_stream_peek( + pa_stream *p /**< The stream to use */, + const void **data /**< Pointer to pointer that will point to data */, + size_t *length /**< The length of the data read */); /** Remove the current fragment. It is invalid to do this without first * calling pa_stream_peek(). \since 0.8 */ -void pa_stream_drop(pa_stream *p); +int pa_stream_drop(pa_stream *p); -/** Return the amount of bytes that may be written using pa_stream_write() */ +/** Return the nember of bytes that may be written using pa_stream_write() */ size_t pa_stream_writable_size(pa_stream *p); -/** Return the ammount of bytes that may be read using pa_stream_read() \since 0.8 */ +/** Return the number of bytes that may be read using pa_stream_read() \since 0.8 */ size_t pa_stream_readable_size(pa_stream *p); -/** Drain a playback stream */ -pa_operation* pa_stream_drain(pa_stream *s, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata); +/** Drain a playback stream. Use this for notification when the buffer is empty */ +pa_operation* pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *userdata); /** Get the playback latency of a stream */ -pa_operation* pa_stream_get_latency_info(pa_stream *p, void (*cb)(pa_stream *p, const pa_latency_info *i, void *userdata), void *userdata); +pa_operation* pa_stream_get_latency_info(pa_stream *p, pa_stream_get_latency_info_cb_t cby, void *userdata); /** Set the callback function that is called whenever the state of the stream changes */ -void pa_stream_set_state_callback(pa_stream *s, void (*cb)(pa_stream *s, void *userdata), void *userdata); +void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata); /** Set the callback function that is called when new data may be * written to the stream. */ -void pa_stream_set_write_callback(pa_stream *p, void (*cb)(pa_stream *p, size_t length, void *userdata), void *userdata); +void pa_stream_set_write_callback(pa_stream *p, pa_stream_request_cb_t cb, void *userdata); /** Set the callback function that is called when new data is available from the stream. - * Return the number of bytes read. \since 0.8 - */ -void pa_stream_set_read_callback(pa_stream *p, void (*cb)(pa_stream *p, size_t length, void *userdata), void *userdata); + * Return the number of bytes read. \since 0.8 */ +void pa_stream_set_read_callback(pa_stream *p, pa_stream_request_cb_t cb, void *userdata); + +/** Set the callback function that is called when a buffer overflow happens. (Only for playback streams) \since 0.8 */ +void pa_stream_set_overflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata); + +/** Set the callback function that is called when a buffer underflow happens. (Only for playback streams) \since 0.8 */ +void pa_stream_set_underflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata); /** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. \since 0.3 */ -pa_operation* pa_stream_cork(pa_stream *s, int b, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata); +pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata); /** Flush the playback buffer of this stream. Most of the time you're * better off using the parameter delta of pa_stream_write() instead of this * function. Available on both playback and recording streams. \since 0.3 */ -pa_operation* pa_stream_flush(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata); +pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata); -/** Reenable prebuffering. Available for playback streams only. \since 0.6 */ -pa_operation* pa_stream_prebuf(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata); +/** Reenable prebuffering as specified in the pa_buffer_attr + * structure. Available for playback streams only. \since 0.6 */ +pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *userdata); /** Request immediate start of playback on this stream. This disables - * prebuffering as specified in the pa_buffer_attr structure. Available for playback streams only. \since - * 0.3 */ -pa_operation* pa_stream_trigger(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata); + * prebuffering as specified in the pa_buffer_attr + * structure, temporarily. Available for playback streams only. \since 0.3 */ +pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata); /** Rename the stream. \since 0.5 */ -pa_operation* pa_stream_set_name(pa_stream *s, const char *name, void(*cb)(pa_stream*c, int success, void *userdata), void *userdata); +pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata); /** Return the total number of bytes written to/read from the * stream. This counter is not reset on pa_stream_flush(), you may do diff --git a/src/polyp/subscribe.c b/src/polyp/subscribe.c index b90e0bf1d..4e00997ab 100644 --- a/src/polyp/subscribe.c +++ b/src/polyp/subscribe.c @@ -44,7 +44,7 @@ void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSE if (pa_tagstruct_getu32(t, &e) < 0 || pa_tagstruct_getu32(t, &index) < 0 || !pa_tagstruct_eof(t)) { - pa_context_fail(c, PA_ERROR_PROTOCOL); + pa_context_fail(c, PA_ERR_PROTOCOL); goto finish; } diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index 7fd091523..c33f593ed 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -59,17 +59,17 @@ static void enable_mainloop_sources(pa_iochannel *io) { pa_io_event_flags_t f = PA_IO_EVENT_NULL; assert(io->input_event); - if (!io->readable) + if (!pa_iochannel_is_readable(io)) f |= PA_IO_EVENT_INPUT; - if (!io->writable) + if (!pa_iochannel_is_writable(io)) f |= PA_IO_EVENT_OUTPUT; io->mainloop->io_enable(io->input_event, f); } else { if (io->input_event) - io->mainloop->io_enable(io->input_event, io->readable ? PA_IO_EVENT_NULL : PA_IO_EVENT_INPUT); + io->mainloop->io_enable(io->input_event, pa_iochannel_is_readable(io) ? PA_IO_EVENT_NULL : PA_IO_EVENT_INPUT); if (io->output_event) - io->mainloop->io_enable(io->output_event, io->writable ? PA_IO_EVENT_NULL : PA_IO_EVENT_OUTPUT); + io->mainloop->io_enable(io->output_event, pa_iochannel_is_writable(io) ? PA_IO_EVENT_NULL : PA_IO_EVENT_OUTPUT); } } @@ -82,33 +82,21 @@ static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_fla assert(fd >= 0); assert(userdata); - if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) { + if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) & !io->hungup) { io->hungup = 1; changed = 1; + } - if (e == io->input_event) { - io->mainloop->io_free(io->input_event); - io->input_event = NULL; - - if (io->output_event == e) - io->output_event = NULL; - } else if (e == io->output_event) { - io->mainloop->io_free(io->output_event); - io->output_event = NULL; - } - } else { - - if ((f & PA_IO_EVENT_INPUT) && !io->readable) { - io->readable = 1; - changed = 1; - assert(e == io->input_event); - } - - if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) { - io->writable = 1; - changed = 1; - assert(e == io->output_event); - } + if ((f & PA_IO_EVENT_INPUT) && !io->readable) { + io->readable = 1; + changed = 1; + assert(e == io->input_event); + } + + if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) { + io->writable = 1; + changed = 1; + assert(e == io->output_event); } if (changed) { @@ -217,6 +205,7 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) { if (r < 0) #endif r = write(io->ofd, data, l); + if (r >= 0) { io->writable = 0; enable_mainloop_sources(io); diff --git a/src/polypcore/llist.h b/src/polypcore/llist.h index eb8cd0173..c54742d32 100644 --- a/src/polypcore/llist.h +++ b/src/polypcore/llist.h @@ -66,4 +66,14 @@ _item->next = _item->prev = NULL; \ } while(0) +#define PA_LLIST_FIND_HEAD(t,item,head) \ +do { \ + t **_head = (head), *_item = (item); \ + *_head = _item; \ + assert(_head); \ + while ((*_head)->prev) \ + *_head = (*_head)->prev; \ +} while (0) \ + + #endif diff --git a/src/polypcore/mcalign.c b/src/polypcore/mcalign.c index 0f229e282..f90fd7e8c 100644 --- a/src/polypcore/mcalign.c +++ b/src/polypcore/mcalign.c @@ -43,6 +43,7 @@ pa_mcalign *pa_mcalign_new(size_t base, pa_memblock_stat *s) { assert(base); m = pa_xnew(pa_mcalign, 1); + m->base = base; pa_memchunk_reset(&m->leftover); pa_memchunk_reset(&m->current); @@ -64,11 +65,16 @@ void pa_mcalign_free(pa_mcalign *m) { } void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { - assert(m && c && c->memblock && c->length); + assert(m); + assert(c); + + assert(c->memblock); + assert(c->length > 0); + + assert(!m->current.memblock); /* Append to the leftover memory block */ if (m->leftover.memblock) { - assert(!m->current.memblock); /* Try to merge */ if (m->leftover.memblock == c->memblock && @@ -110,8 +116,6 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { } } } else { - assert(!m->leftover.memblock && !m->current.memblock); - /* Nothing to merge or copy, just store it */ if (c->length >= m->base) @@ -124,7 +128,8 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { } int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) { - assert(m && c); + assert(m); + assert(c); /* First test if there's a leftover memory block available */ if (m->leftover.memblock) { @@ -187,3 +192,15 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) { return -1; } + +size_t pa_mcalign_csize(pa_mcalign *m, size_t l) { + assert(m); + assert(l > 0); + + assert(!m->current.memblock); + + if (m->leftover.memblock) + l += m->leftover.length; + + return (l/m->base)*m->base; +} diff --git a/src/polypcore/mcalign.h b/src/polypcore/mcalign.h index a9107e0e4..580194629 100644 --- a/src/polypcore/mcalign.h +++ b/src/polypcore/mcalign.h @@ -74,4 +74,7 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c); * nonzero otherwise. */ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c); +/* If we pass l bytes in now, how many bytes would we get out? */ +size_t pa_mcalign_csize(pa_mcalign *m, size_t l); + #endif diff --git a/src/polypcore/memblock.c b/src/polypcore/memblock.c index 2c0bef57c..04e8436fc 100644 --- a/src/polypcore/memblock.c +++ b/src/polypcore/memblock.c @@ -111,13 +111,16 @@ pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void * } pa_memblock* pa_memblock_ref(pa_memblock*b) { - assert(b && b->ref >= 1); + assert(b); + assert(b->ref >= 1); + b->ref++; return b; } void pa_memblock_unref(pa_memblock*b) { - assert(b && b->ref >= 1); + assert(b); + assert(b->ref >= 1); if ((--(b->ref)) == 0) { stat_remove(b); diff --git a/src/polypcore/memblock.h b/src/polypcore/memblock.h index c57514065..9471278ad 100644 --- a/src/polypcore/memblock.h +++ b/src/polypcore/memblock.h @@ -79,7 +79,6 @@ references to the memory. This causes the memory to be copied and converted into a PA_MEMBLOCK_DYNAMIC type memory block */ void pa_memblock_unref_fixed(pa_memblock*b); - pa_memblock_stat* pa_memblock_stat_new(void); void pa_memblock_stat_unref(pa_memblock_stat *s); pa_memblock_stat * pa_memblock_stat_ref(pa_memblock_stat *s); diff --git a/src/polypcore/memblockq.c b/src/polypcore/memblockq.c index 4a0225e58..05c810bd2 100644 --- a/src/polypcore/memblockq.c +++ b/src/polypcore/memblockq.c @@ -38,30 +38,45 @@ struct memblock_list { struct memblock_list *next, *prev; + int64_t index; pa_memchunk chunk; }; struct pa_memblockq { struct memblock_list *blocks, *blocks_tail; unsigned n_blocks; - size_t current_length, maxlength, tlength, base, prebuf, orig_prebuf, minreq; - pa_mcalign *mcalign; + size_t maxlength, tlength, base, prebuf, minreq; + int64_t read_index, write_index; + enum { PREBUF, RUNNING } state; pa_memblock_stat *memblock_stat; + pa_memblock *silence; + pa_mcalign *mcalign; }; -pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t base, size_t prebuf, size_t minreq, pa_memblock_stat *s) { - pa_memblockq* bq; - assert(maxlength && base && maxlength); +pa_memblockq* pa_memblockq_new( + int64_t idx, + size_t maxlength, + size_t tlength, + size_t base, + size_t prebuf, + size_t minreq, + pa_memblock *silence, + pa_memblock_stat *s) { - bq = pa_xmalloc(sizeof(pa_memblockq)); - bq->blocks = bq->blocks_tail = 0; + pa_memblockq* bq; + + assert(base > 0); + assert(maxlength >= base); + + bq = pa_xnew(pa_memblockq, 1); + bq->blocks = bq->blocks_tail = NULL; bq->n_blocks = 0; - bq->current_length = 0; + bq->base = base; + bq->read_index = bq->write_index = idx; + bq->memblock_stat = s; pa_log_debug(__FILE__": memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq); - - bq->base = base; bq->maxlength = ((maxlength+base-1)/base)*base; assert(bq->maxlength >= base); @@ -70,26 +85,25 @@ pa_memblockq* pa_memblockq_new(size_t maxlength, size_t tlength, size_t base, si if (!bq->tlength || bq->tlength >= bq->maxlength) bq->tlength = bq->maxlength; - bq->minreq = (minreq/base)*base; - if (bq->minreq == 0) - bq->minreq = 1; - - bq->prebuf = (prebuf == (size_t) -1) ? bq->maxlength/2 : prebuf; - bq->prebuf = (bq->prebuf/base)*base; + bq->prebuf = (prebuf == (size_t) -1) ? bq->tlength/2 : prebuf; + bq->prebuf = ((bq->prebuf+base-1)/base)*base; if (bq->prebuf > bq->maxlength) bq->prebuf = bq->maxlength; - if (bq->prebuf > bq->tlength - bq->minreq) - bq->prebuf = bq->tlength - bq->minreq; + bq->minreq = (minreq/base)*base; + + if (bq->minreq > bq->tlength - bq->prebuf) + bq->minreq = bq->tlength - bq->prebuf; - bq->orig_prebuf = bq->prebuf; + if (!bq->minreq) + bq->minreq = 1; pa_log_debug(__FILE__": memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); - + + bq->state = bq->prebuf ? PREBUF : RUNNING; + bq->silence = silence ? pa_memblock_ref(silence) : NULL; bq->mcalign = NULL; - - bq->memblock_stat = s; - + return bq; } @@ -97,56 +111,271 @@ void pa_memblockq_free(pa_memblockq* bq) { assert(bq); pa_memblockq_flush(bq); - + + if (bq->silence) + pa_memblock_unref(bq->silence); + if (bq->mcalign) pa_mcalign_free(bq->mcalign); - + pa_xfree(bq); } -void pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *chunk, size_t delta) { - struct memblock_list *q; - assert(bq && chunk && chunk->memblock && chunk->length && (chunk->length % bq->base) == 0); +static void drop_block(pa_memblockq *bq, struct memblock_list *q) { + assert(bq); + assert(q); - pa_memblockq_seek(bq, delta); + assert(bq->n_blocks >= 1); - if (bq->blocks_tail && bq->blocks_tail->chunk.memblock == chunk->memblock) { - /* Try to merge memory chunks */ + if (q->prev) + q->prev->next = q->next; + else + bq->blocks = q->next; + + if (q->next) + q->next->prev = q->prev; + else + bq->blocks_tail = q->prev; - if (bq->blocks_tail->chunk.index+bq->blocks_tail->chunk.length == chunk->index) { - bq->blocks_tail->chunk.length += chunk->length; - bq->current_length += chunk->length; - return; + pa_memblock_unref(q->chunk.memblock); + pa_xfree(q); + + bq->n_blocks--; +} + +static int can_push(pa_memblockq *bq, size_t l) { + int64_t end; + + assert(bq); + + if (bq->read_index > bq->write_index) { + int64_t d = bq->read_index - bq->write_index; + + if (l > d) + l -= d; + else + return 1; + } + + end = bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : 0; + + /* Make sure that the list doesn't get too long */ + if (bq->write_index + l > end) + if (bq->write_index + l - bq->read_index > bq->maxlength) + return 0; + + return 1; +} + +int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { + + struct memblock_list *q, *n; + pa_memchunk chunk; + + assert(bq); + assert(uchunk); + assert(uchunk->memblock); + assert(uchunk->length > 0); + assert(uchunk->index + uchunk->length <= uchunk->memblock->length); + + if (uchunk->length % bq->base) + return -1; + + if (!can_push(bq, uchunk->length)) + return -1; + + chunk = *uchunk; + + if (bq->read_index > bq->write_index) { + + /* We currently have a buffer underflow, we need to drop some + * incoming data */ + + int64_t d = bq->read_index - bq->write_index; + + if (chunk.length > d) { + chunk.index += d; + chunk.length -= d; + bq->write_index = bq->read_index; + } else { + /* We drop the incoming data completely */ + bq->write_index += chunk.length; + return 0; } } - q = pa_xmalloc(sizeof(struct memblock_list)); + /* We go from back to front to look for the right place to add + * this new entry. Drop data we will overwrite on the way */ - q->chunk = *chunk; - pa_memblock_ref(q->chunk.memblock); - assert(q->chunk.index+q->chunk.length <= q->chunk.memblock->length); - q->next = NULL; - if ((q->prev = bq->blocks_tail)) - bq->blocks_tail->next = q; + q = bq->blocks_tail; + while (q) { + + if (bq->write_index >= q->index + q->chunk.length) + /* We found the entry where we need to place the new entry immediately after */ + break; + else if (bq->write_index + chunk.length <= q->index) { + /* This entry isn't touched at all, let's skip it */ + q = q->prev; + } else if (bq->write_index <= q->index && + bq->write_index + chunk.length >= q->index + q->chunk.length) { + + /* This entry is fully replaced by the new entry, so let's drop it */ + + struct memblock_list *p; + p = q; + q = q->prev; + drop_block(bq, p); + } else if (bq->write_index >= q->index) { + /* The write index points into this memblock, so let's + * truncate or split it */ + + if (bq->write_index + chunk.length < q->index + q->chunk.length) { + + /* We need to save the end of this memchunk */ + struct memblock_list *p; + size_t d; + + /* Create a new list entry for the end of thie memchunk */ + p = pa_xnew(struct memblock_list, 1); + p->chunk = q->chunk; + pa_memblock_ref(p->chunk.memblock); + + /* Calculate offset */ + d = bq->write_index + chunk.length - q->index; + assert(d > 0); + + /* Drop it from the new entry */ + p->index = q->index + d; + p->chunk.length -= d; + + /* Add it to the list */ + p->prev = q; + if ((p->next = q->next)) + q->next->prev = p; + else + bq->blocks_tail = p; + q->next = p; + + bq->n_blocks++; + } + + /* Truncate the chunk */ + if (!(q->chunk.length = bq->write_index - q->index)) { + struct memblock_list *p; + p = q; + q = q->prev; + drop_block(bq, p); + } + + /* We had to truncate this block, hence we're now at the right position */ + break; + } else { + size_t d; + + assert(bq->write_index + chunk.length > q->index && + bq->write_index + chunk.length < q->index + q->chunk.length && + bq->write_index < q->index); + + /* The job overwrites the current entry at the end, so let's drop the beginning of this entry */ + + d = bq->write_index + chunk.length - q->index; + q->index += d; + q->chunk.index += d; + q->chunk.length -= d; + + q = q->prev; + } + + } + + if (q) { + assert(bq->write_index >= q->index + q->chunk.length); + assert(!q->next || (bq->write_index+chunk.length <= q->next->index)); + + /* Try to merge memory blocks */ + + if (q->chunk.memblock == chunk.memblock && + q->chunk.index + q->chunk.length == chunk.index && + bq->write_index == q->index + q->chunk.length) { + + q->chunk.length += chunk.length; + bq->write_index += chunk.length; + return 0; + } + } else + assert(!bq->blocks || (bq->write_index+chunk.length <= bq->blocks->index)); + + + n = pa_xnew(struct memblock_list, 1); + n->chunk = chunk; + pa_memblock_ref(n->chunk.memblock); + n->index = bq->write_index; + bq->write_index += n->chunk.length; + + n->next = q ? q->next : bq->blocks; + n->prev = q; + + if (n->next) + n->next->prev = n; else - bq->blocks = q; + bq->blocks_tail = n; + + if (n->prev) + n->prev->next = n; + else + bq->blocks = n; - bq->blocks_tail = q; - bq->n_blocks++; - bq->current_length += chunk->length; - - pa_memblockq_shorten(bq, bq->maxlength); + return 0; } int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { - assert(bq && chunk); + assert(bq); + assert(chunk); - if (!bq->blocks || bq->current_length < bq->prebuf) + if (bq->state == PREBUF) { + + /* We need to pre-buffer */ + if (pa_memblockq_get_length(bq) < bq->prebuf) + return -1; + + bq->state = RUNNING; + + } else if (bq->prebuf > 0 && bq->read_index >= bq->write_index) { + + /* Buffer underflow protection */ + bq->state = PREBUF; return -1; + } + + /* Do we need to spit out silence? */ + if (!bq->blocks || bq->blocks->index > bq->read_index) { - bq->prebuf = 0; + size_t length; + /* How much silence shall we return? */ + length = bq->blocks ? bq->blocks->index - bq->read_index : 0; + + /* We need to return silence, since no data is yet available */ + if (bq->silence) { + chunk->memblock = pa_memblock_ref(bq->silence); + + if (!length || length > chunk->memblock->length) + length = chunk->memblock->length; + + chunk->length = length; + } else { + chunk->memblock = NULL; + chunk->length = length; + } + + chunk->index = 0; + return 0; + } + + /* Ok, let's pass real data to the caller */ + assert(bq->blocks->index == bq->read_index); + *chunk = bq->blocks->chunk; pa_memblock_ref(chunk->memblock); @@ -154,191 +383,238 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { } void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length) { - assert(bq && chunk && length); + assert(bq); + assert(length % bq->base == 0); - if (!bq->blocks || memcmp(&bq->blocks->chunk, chunk, sizeof(pa_memchunk))) - return; - - assert(length <= bq->blocks->chunk.length); - pa_memblockq_skip(bq, length); -} + assert(!chunk || length <= chunk->length); -static void remove_block(pa_memblockq *bq, struct memblock_list *q) { - assert(bq && q); + if (chunk) { - if (q->prev) - q->prev->next = q->next; - else { - assert(bq->blocks == q); - bq->blocks = q->next; + if (bq->blocks && bq->blocks->index == bq->read_index) { + /* The first item in queue is valid */ + + /* Does the chunk match with what the user supplied us? */ + if (memcmp(chunk, &bq->blocks->chunk, sizeof(pa_memchunk)) != 0) + return; + + } else { + size_t l; + + /* The first item in the queue is not yet relevant */ + + assert(!bq->blocks || bq->blocks->index > bq->read_index); + l = bq->blocks ? bq->blocks->index - bq->read_index : 0; + + if (bq->silence) { + + if (!l || l > bq->silence->length) + l = bq->silence->length; + + } + + /* Do the entries still match? */ + if (chunk->index != 0 || chunk->length != l || chunk->memblock != bq->silence) + return; + } } - - if (q->next) - q->next->prev = q->prev; - else { - assert(bq->blocks_tail == q); - bq->blocks_tail = q->prev; - } - - pa_memblock_unref(q->chunk.memblock); - pa_xfree(q); - - bq->n_blocks--; -} - -void pa_memblockq_skip(pa_memblockq *bq, size_t length) { - assert(bq && length && (length % bq->base) == 0); while (length > 0) { - size_t l = length; - assert(bq->blocks && bq->current_length >= length); - - if (l > bq->blocks->chunk.length) - l = bq->blocks->chunk.length; - bq->blocks->chunk.index += l; - bq->blocks->chunk.length -= l; - bq->current_length -= l; - - if (!bq->blocks->chunk.length) - remove_block(bq, bq->blocks); + if (bq->blocks) { + size_t d; - length -= l; + assert(bq->blocks->index >= bq->read_index); + + d = (size_t) (bq->blocks->index - bq->read_index); + + if (d >= length) { + /* The first block is too far in the future */ + + bq->read_index += length; + break; + } else { + + length -= d; + bq->read_index += d; + } + + assert(bq->blocks->index == bq->read_index); + + if (bq->blocks->chunk.length <= length) { + /* We need to drop the full block */ + + length -= bq->blocks->chunk.length; + bq->read_index += bq->blocks->chunk.length; + + drop_block(bq, bq->blocks); + } else { + /* Only the start of this block needs to be dropped */ + + bq->blocks->chunk.index += length; + bq->blocks->chunk.length -= length; + bq->blocks->index += length; + bq->read_index += length; + break; + } + + } else { + + /* The list is empty, there's nothing we could drop */ + bq->read_index += length; + break; + } } } +int pa_memblockq_is_readable(pa_memblockq *bq) { + assert(bq); + + if (bq->prebuf > 0) { + size_t l = pa_memblockq_get_length(bq); + + if (bq->state == PREBUF && l < bq->prebuf) + return 0; + + if (l <= 0) + return 0; + } + + return 1; +} + +int pa_memblockq_is_writable(pa_memblockq *bq, size_t length) { + assert(bq); + + if (length % bq->base) + return 0; + + return pa_memblockq_get_length(bq) + length <= bq->tlength; +} + +size_t pa_memblockq_get_length(pa_memblockq *bq) { + assert(bq); + + if (bq->write_index <= bq->read_index) + return 0; + + return (size_t) (bq->write_index - bq->read_index); +} + +size_t pa_memblockq_missing(pa_memblockq *bq) { + size_t l; + assert(bq); + + if ((l = pa_memblockq_get_length(bq)) >= bq->tlength) + return 0; + + l = bq->tlength - l; + return (l >= bq->minreq) ? l : 0; +} + +size_t pa_memblockq_get_minreq(pa_memblockq *bq) { + assert(bq); + + return bq->minreq; +} + +void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) { + assert(bq); + + switch (seek) { + case PA_SEEK_RELATIVE: + bq->write_index += offset; + return; + case PA_SEEK_ABSOLUTE: + bq->write_index = offset; + return; + case PA_SEEK_RELATIVE_ON_READ: + bq->write_index = bq->read_index + offset; + return; + case PA_SEEK_RELATIVE_END: + bq->write_index = (bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : bq->read_index) + offset; + return; + } + + assert(0); +} + +void pa_memblockq_flush(pa_memblockq *bq) { + assert(bq); + + while (bq->blocks) + drop_block(bq, bq->blocks); + + assert(bq->n_blocks == 0); + bq->write_index = bq->read_index; + + pa_memblockq_prebuf_force(bq); +} + +size_t pa_memblockq_get_tlength(pa_memblockq *bq) { + assert(bq); + + return bq->tlength; +} + +int64_t pa_memblockq_get_read_index(pa_memblockq *bq) { + assert(bq); + return bq->read_index; +} + +int64_t pa_memblockq_get_write_index(pa_memblockq *bq) { + assert(bq); + return bq->write_index; +} + +int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk) { + pa_memchunk rchunk; + + assert(bq); + assert(chunk && bq->base); + + if (bq->base == 1) + return pa_memblockq_push(bq, chunk); + + if (!bq->mcalign) + bq->mcalign = pa_mcalign_new(bq->base, bq->memblock_stat); + + if (!can_push(bq, pa_mcalign_csize(bq->mcalign, chunk->length))) + return -1; + + pa_mcalign_push(bq->mcalign, chunk); + + while (pa_mcalign_pop(bq->mcalign, &rchunk) >= 0) { + int r; + r = pa_memblockq_push(bq, &rchunk); + pa_memblock_unref(rchunk.memblock); + + if (r < 0) + return -1; + } + + return 0; +} + void pa_memblockq_shorten(pa_memblockq *bq, size_t length) { size_t l; assert(bq); - if (bq->current_length <= length) - return; + l = pa_memblockq_get_length(bq); - /*pa_log(__FILE__": Warning! pa_memblockq_shorten()\n");*/ - - l = bq->current_length - length; - l /= bq->base; - l *= bq->base; - - pa_memblockq_skip(bq, l); -} - - -void pa_memblockq_empty(pa_memblockq *bq) { - assert(bq); - pa_memblockq_shorten(bq, 0); -} - -int pa_memblockq_is_readable(pa_memblockq *bq) { - assert(bq); - - return bq->current_length && (bq->current_length >= bq->prebuf); -} - -int pa_memblockq_is_writable(pa_memblockq *bq, size_t length) { - assert(bq); - - return bq->current_length + length <= bq->tlength; -} - -uint32_t pa_memblockq_get_length(pa_memblockq *bq) { - assert(bq); - return bq->current_length; -} - -uint32_t pa_memblockq_missing(pa_memblockq *bq) { - size_t l; - assert(bq); - - if (bq->current_length >= bq->tlength) - return 0; - - l = bq->tlength - bq->current_length; - assert(l); - - return (l >= bq->minreq) ? l : 0; -} - -void pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk, size_t delta) { - pa_memchunk rchunk; - assert(bq && chunk && bq->base); - - if (bq->base == 1) { - pa_memblockq_push(bq, chunk, delta); - return; - } - - if (!bq->mcalign) { - bq->mcalign = pa_mcalign_new(bq->base, bq->memblock_stat); - assert(bq->mcalign); - } - - pa_mcalign_push(bq->mcalign, chunk); - - while (pa_mcalign_pop(bq->mcalign, &rchunk) >= 0) { - pa_memblockq_push(bq, &rchunk, delta); - pa_memblock_unref(rchunk.memblock); - delta = 0; - } -} - -uint32_t pa_memblockq_get_minreq(pa_memblockq *bq) { - assert(bq); - return bq->minreq; + if (l > length) + pa_memblockq_drop(bq, NULL, l - length); } void pa_memblockq_prebuf_disable(pa_memblockq *bq) { assert(bq); - bq->prebuf = 0; + + if (bq->state == PREBUF) + bq->state = RUNNING; } -void pa_memblockq_prebuf_reenable(pa_memblockq *bq) { - assert(bq); - bq->prebuf = bq->orig_prebuf; -} - -void pa_memblockq_seek(pa_memblockq *bq, size_t length) { +void pa_memblockq_prebuf_force(pa_memblockq *bq) { assert(bq); - if (!length) - return; - - while (length >= bq->base) { - size_t l = length; - if (!bq->current_length) - return; - - assert(bq->blocks_tail); - - if (l > bq->blocks_tail->chunk.length) - l = bq->blocks_tail->chunk.length; - - bq->blocks_tail->chunk.length -= l; - bq->current_length -= l; - - if (bq->blocks_tail->chunk.length == 0) - remove_block(bq, bq->blocks); - - length -= l; - } -} - -void pa_memblockq_flush(pa_memblockq *bq) { - struct memblock_list *l; - assert(bq); - - while ((l = bq->blocks)) { - bq->blocks = l->next; - pa_memblock_unref(l->chunk.memblock); - pa_xfree(l); - } - - bq->blocks_tail = NULL; - bq->n_blocks = 0; - bq->current_length = 0; -} - -uint32_t pa_memblockq_get_tlength(pa_memblockq *bq) { - assert(bq); - return bq->tlength; + if (bq->state == RUNNING && bq->prebuf > 0) + bq->state = PREBUF; } diff --git a/src/polypcore/memblockq.h b/src/polypcore/memblockq.h index 7bb25f908..210f1a078 100644 --- a/src/polypcore/memblockq.h +++ b/src/polypcore/memblockq.h @@ -23,9 +23,11 @@ ***/ #include +#include #include #include +#include /* A memblockq is a queue of pa_memchunks (yepp, the name is not * perfect). It is similar to the ring buffers used by most other @@ -35,42 +37,59 @@ typedef struct pa_memblockq pa_memblockq; + /* Parameters: - - maxlength: maximum length of queue. If more data is pushed into the queue, data from the front is dropped - - length: the target length of the queue. - - base: a base value for all metrics. Only multiples of this value are popped from the queue - - prebuf: before passing the first byte out, make sure that enough bytes are in the queue - - minreq: pa_memblockq_missing() will only return values greater than this value + + - idx: start value for both read and write index + + - maxlength: maximum length of queue. If more data is pushed into + the queue, the operation will fail. Must not be 0. + + - tlength: the target length of the queue. Pass 0 for the default. + + - base: a base value for all metrics. Only multiples of this value + are popped from the queue or should be pushed into + it. Must not be 0. + + - prebuf: If the queue runs empty wait until this many bytes are in + queue again before passing the first byte out. If set + to 0 pa_memblockq_pop() will return a silence memblock + if no data is in the queue and will never fail. Pass + (size_t) -1 for the default. + + - minreq: pa_memblockq_missing() will only return values greater + than this value. Pass 0 for the default. + + - silence: return this memblock whzen reading unitialized data */ -pa_memblockq* pa_memblockq_new(size_t maxlength, - size_t tlength, - size_t base, - size_t prebuf, - size_t minreq, - pa_memblock_stat *s); +pa_memblockq* pa_memblockq_new( + int64_t idx, + size_t maxlength, + size_t tlength, + size_t base, + size_t prebuf, + size_t minreq, + pa_memblock *silence, + pa_memblock_stat *s); + void pa_memblockq_free(pa_memblockq*bq); -/* Push a new memory chunk into the queue. Optionally specify a value for future cancellation. */ -void pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *chunk, size_t delta); +/* Push a new memory chunk into the queue. */ +int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *chunk); -/* Same as pa_memblockq_push(), however chunks are filtered through a mcalign object, and thus aligned to multiples of base */ -void pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk, size_t delta); +/* Push a new memory chunk into the queue, but filter it through a + * pa_mcalign object. Don't mix this with pa_memblockq_seek() unless + * you know what you do. */ +int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk); /* Return a copy of the next memory chunk in the queue. It is not removed from the queue */ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk); -/* Drop the specified bytes from the queue, only valid aufter pa_memblockq_peek() */ +/* Drop the specified bytes from the queue, but only if the first + * chunk in the queue matches the one passed here. If NULL is passed, + * this check isn't done. */ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length); -/* Drop the specified bytes from the queue */ -void pa_memblockq_skip(pa_memblockq *bq, size_t length); - -/* Shorten the pa_memblockq to the specified length by dropping data at the end of the queue */ -void pa_memblockq_shorten(pa_memblockq *bq, size_t length); - -/* Empty the pa_memblockq */ -void pa_memblockq_empty(pa_memblockq *bq); - /* Test if the pa_memblockq is currently readable, that is, more data than base */ int pa_memblockq_is_readable(pa_memblockq *bq); @@ -78,27 +97,38 @@ int pa_memblockq_is_readable(pa_memblockq *bq); int pa_memblockq_is_writable(pa_memblockq *bq, size_t length); /* Return the length of the queue in bytes */ -uint32_t pa_memblockq_get_length(pa_memblockq *bq); +size_t pa_memblockq_get_length(pa_memblockq *bq); /* Return how many bytes are missing in queue to the specified fill amount */ -uint32_t pa_memblockq_missing(pa_memblockq *bq); +size_t pa_memblockq_missing(pa_memblockq *bq); /* Returns the minimal request value */ -uint32_t pa_memblockq_get_minreq(pa_memblockq *bq); - -/* Force disabling of pre-buf even when the pre-buffer is not yet filled */ -void pa_memblockq_prebuf_disable(pa_memblockq *bq); - -/* Reenable pre-buf to the initial level */ -void pa_memblockq_prebuf_reenable(pa_memblockq *bq); +size_t pa_memblockq_get_minreq(pa_memblockq *bq); /* Manipulate the write pointer */ -void pa_memblockq_seek(pa_memblockq *bq, size_t delta); +void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek); -/* Flush the queue */ +/* Set the queue to silence, set write index to read index */ void pa_memblockq_flush(pa_memblockq *bq); /* Get Target length */ uint32_t pa_memblockq_get_tlength(pa_memblockq *bq); +/* Return the current read index */ +int64_t pa_memblockq_get_read_index(pa_memblockq *bq); + +/* Return the current write index */ +int64_t pa_memblockq_get_write_index(pa_memblockq *bq); + +/* Shorten the pa_memblockq to the specified length by dropping data + * at the read end of the queue. The read index is increased until the + * queue has the specified length */ +void pa_memblockq_shorten(pa_memblockq *bq, size_t length); + +/* Ignore prebuf for now */ +void pa_memblockq_prebuf_disable(pa_memblockq *bq); + +/* Force prebuf */ +void pa_memblockq_prebuf_force(pa_memblockq *bq); + #endif diff --git a/src/polypcore/native-common.h b/src/polypcore/native-common.h index ac3ea8231..0d17b0222 100644 --- a/src/polypcore/native-common.h +++ b/src/polypcore/native-common.h @@ -28,22 +28,22 @@ PA_C_DECL_BEGIN enum { + /* Generic commands */ PA_COMMAND_ERROR, PA_COMMAND_TIMEOUT, /* pseudo command */ PA_COMMAND_REPLY, + + /* Commands from client to server */ PA_COMMAND_CREATE_PLAYBACK_STREAM, PA_COMMAND_DELETE_PLAYBACK_STREAM, PA_COMMAND_CREATE_RECORD_STREAM, PA_COMMAND_DELETE_RECORD_STREAM, PA_COMMAND_EXIT, - PA_COMMAND_REQUEST, PA_COMMAND_AUTH, PA_COMMAND_SET_CLIENT_NAME, PA_COMMAND_LOOKUP_SINK, PA_COMMAND_LOOKUP_SOURCE, PA_COMMAND_DRAIN_PLAYBACK_STREAM, - PA_COMMAND_PLAYBACK_STREAM_KILLED, - PA_COMMAND_RECORD_STREAM_KILLED, PA_COMMAND_STAT, PA_COMMAND_GET_PLAYBACK_LATENCY, PA_COMMAND_CREATE_UPLOAD_STREAM, @@ -68,7 +68,6 @@ enum { PA_COMMAND_GET_SAMPLE_INFO, PA_COMMAND_GET_SAMPLE_INFO_LIST, PA_COMMAND_SUBSCRIBE, - PA_COMMAND_SUBSCRIBE_EVENT, PA_COMMAND_SET_SINK_VOLUME, PA_COMMAND_SET_SINK_INPUT_VOLUME, @@ -95,6 +94,15 @@ enum { PA_COMMAND_CORK_RECORD_STREAM, PA_COMMAND_FLUSH_RECORD_STREAM, PA_COMMAND_PREBUF_PLAYBACK_STREAM, + + /* Commands from server to client */ + PA_COMMAND_REQUEST, + PA_COMMAND_OVERFLOW, + PA_COMMAND_UNDERFLOW, + PA_COMMAND_PLAYBACK_STREAM_KILLED, + PA_COMMAND_RECORD_STREAM_KILLED, + PA_COMMAND_SUBSCRIBE_EVENT, + PA_COMMAND_MAX }; diff --git a/src/polypcore/packet.c b/src/polypcore/packet.c index 41803cf99..31ddad95b 100644 --- a/src/polypcore/packet.c +++ b/src/polypcore/packet.c @@ -32,37 +32,46 @@ pa_packet* pa_packet_new(size_t length) { pa_packet *p; + assert(length); + p = pa_xmalloc(sizeof(pa_packet)+length); p->ref = 1; p->length = length; p->data = (uint8_t*) (p+1); p->type = PA_PACKET_APPENDED; + return p; } -pa_packet* pa_packet_new_dynamic(uint8_t* data, size_t length) { +pa_packet* pa_packet_new_dynamic(void* data, size_t length) { pa_packet *p; - assert(data && length); - p = pa_xmalloc(sizeof(pa_packet)); + + assert(data); + assert(length); + + p = pa_xnew(pa_packet, 1); p->ref = 1; p->length = length; p->data = data; p->type = PA_PACKET_DYNAMIC; + return p; } pa_packet* pa_packet_ref(pa_packet *p) { - assert(p && p->ref >= 1); + assert(p); + assert(p->ref >= 1); + p->ref++; return p; } void pa_packet_unref(pa_packet *p) { - assert(p && p->ref >= 1); - p->ref--; - - if (p->ref == 0) { + assert(p); + assert(p->ref >= 1); + + if (--p->ref == 0) { if (p->type == PA_PACKET_DYNAMIC) pa_xfree(p->data); pa_xfree(p); diff --git a/src/polypcore/packet.h b/src/polypcore/packet.h index 0ac474857..fbc582325 100644 --- a/src/polypcore/packet.h +++ b/src/polypcore/packet.h @@ -33,7 +33,7 @@ typedef struct pa_packet { } pa_packet; pa_packet* pa_packet_new(size_t length); -pa_packet* pa_packet_new_dynamic(uint8_t* data, size_t length); +pa_packet* pa_packet_new_dynamic(void* data, size_t length); pa_packet* pa_packet_ref(pa_packet *p); void pa_packet_unref(pa_packet *p); diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index a16ac2808..5adff57af 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -186,6 +186,7 @@ static void connection_free(struct connection *c) { if (c->sink_input) { pa_sink_input_disconnect(c->sink_input); + pa_log("disconnect\n"); pa_sink_input_unref(c->sink_input); } @@ -333,7 +334,15 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t } l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); - c->input_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&ss), l/2, l/PLAYBACK_BUFFER_FRAGMENTS, c->protocol->core->memblock_stat); + c->input_memblockq = pa_memblockq_new( + 0, + l, + 0, + pa_frame_size(&ss), + (size_t) -1, + l/PLAYBACK_BUFFER_FRAGMENTS, + NULL, + c->protocol->core->memblock_stat); pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2); c->playback.fragment_size = l/10; @@ -405,7 +414,15 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co } l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS); - c->output_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&ss), 0, 0, c->protocol->core->memblock_stat); + c->output_memblockq = pa_memblockq_new( + 0, + l, + 0, + pa_frame_size(&ss), + 1, + 0, + NULL, + c->protocol->core->memblock_stat); pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2); c->source_output->owner = c->protocol->module; @@ -724,8 +741,7 @@ static int do_read(struct connection *c) { assert(c->read_data_length < sizeof(c->request)); if ((r = pa_iochannel_read(c->io, ((uint8_t*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { - if (r != 0) - pa_log_warn(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log_debug(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); return -1; } @@ -773,8 +789,7 @@ static int do_read(struct connection *c) { assert(c->read_data && c->read_data_length < handler->data_length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { - if (r != 0) - pa_log_warn(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log_debug(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); return -1; } @@ -794,8 +809,7 @@ static int do_read(struct connection *c) { assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { - if (r!= 0) - pa_log_warn(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log_debug(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); return -1; } @@ -852,13 +866,10 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - if (r != 0) - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log_debug(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); return -1; } -/* pa_log(__FILE__": read %u\n", r); */ - chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; chunk.length = r; @@ -867,7 +878,7 @@ static int do_read(struct connection *c) { c->playback.memblock_index += r; assert(c->input_memblockq); - pa_memblockq_push_align(c->input_memblockq, &chunk, 0); + pa_memblockq_push_align(c->input_memblockq, &chunk); assert(c->sink_input); pa_sink_notify(c->sink_input->sink); } @@ -910,6 +921,8 @@ static int do_write(struct connection *c) { pa_memblockq_drop(c->output_memblockq, &chunk, r); pa_memblock_unref(chunk.memblock); + + pa_source_notify(c->source_output->source); } return 0; @@ -921,21 +934,18 @@ static void do_work(struct connection *c) { assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 0); -/* pa_log("DOWORK %i\n", pa_iochannel_is_hungup(c->io)); */ + if (c->dead) + return; - if (!c->dead && pa_iochannel_is_readable(c->io)) + if (pa_iochannel_is_readable(c->io)) { if (do_read(c) < 0) goto fail; + } else if (pa_iochannel_is_hungup(c->io)) + goto fail; - if (!c->dead && pa_iochannel_is_writable(c->io)) + if (pa_iochannel_is_writable(c->io)) if (do_write(c) < 0) goto fail; - - /* In case the line was hungup, make sure to rerun this function - as soon as possible, until all data has been read. */ - - if (!c->dead && pa_iochannel_is_hungup(c->io)) - c->protocol->core->mainloop->defer_enable(c->defer_event, 1); return; @@ -943,15 +953,17 @@ fail: if (c->state == ESD_STREAMING_DATA && c->sink_input) { c->dead = 1; - pa_memblockq_prebuf_disable(c->input_memblockq); pa_iochannel_free(c->io); c->io = NULL; - + + pa_memblockq_prebuf_disable(c->input_memblockq); + pa_sink_notify(c->sink_input->sink); } else connection_free(c); } + static void io_callback(pa_iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); @@ -1024,7 +1036,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) struct connection *c = o->userdata; assert(o && c && chunk); - pa_memblockq_push(c->output_memblockq, chunk, 0); + pa_memblockq_push(c->output_memblockq, chunk); /* do something */ assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 1362fdf2e..aaa4fc48a 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include "protocol-native.h" @@ -77,6 +79,11 @@ struct playback_stream { size_t requested_bytes; int drain_request; uint32_t drain_tag; + uint32_t syncid; + int underrun; + + /* Sync group members */ + PA_LLIST_FIELDS(struct playback_stream); }; struct upload_stream { @@ -153,7 +160,8 @@ static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -static void command_flush_or_trigger_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_flush_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_trigger_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); @@ -210,9 +218,9 @@ static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume, [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream, - [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_or_trigger_playback_stream, - [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_flush_or_trigger_playback_stream, - [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_flush_or_trigger_playback_stream, + [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_playback_stream, + [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream, + [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream, [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream, [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream, @@ -244,7 +252,7 @@ static struct upload_stream* upload_stream_new( struct upload_stream *s; assert(c && ss && name && length); - s = pa_xmalloc(sizeof(struct upload_stream)); + s = pa_xnew(struct upload_stream, 1); s->type = UPLOAD_STREAM; s->connection = c; s->sample_spec = *ss; @@ -291,7 +299,7 @@ static struct record_stream* record_stream_new( if (!(source_output = pa_source_output_new(source, __FILE__, name, ss, map, -1))) return NULL; - s = pa_xmalloc(sizeof(struct record_stream)); + s = pa_xnew(struct record_stream, 1); s->connection = c; s->source_output = source_output; s->source_output->push = source_output_push_cb; @@ -301,7 +309,15 @@ static struct record_stream* record_stream_new( s->source_output->owner = c->protocol->module; s->source_output->client = c->client; - s->memblockq = pa_memblockq_new(maxlength, 0, base = pa_frame_size(ss), 0, 0, c->protocol->core->memblock_stat); + s->memblockq = pa_memblockq_new( + 0, + maxlength, + 0, + base = pa_frame_size(ss), + 1, + 0, + NULL, + c->protocol->core->memblock_stat); assert(s->memblockq); s->fragment_size = (fragment_size/base)*base; @@ -332,19 +348,40 @@ static struct playback_stream* playback_stream_new( size_t tlength, size_t prebuf, size_t minreq, - pa_cvolume *volume) { + pa_cvolume *volume, + uint32_t syncid) { - struct playback_stream *s; + struct playback_stream *s, *sync; pa_sink_input *sink_input; + pa_memblock *silence; + uint32_t idx; + int64_t start_index; + assert(c && sink && ss && name && maxlength); + /* Find syncid group */ + for (sync = pa_idxset_first(c->output_streams, &idx); sync; sync = pa_idxset_next(c->output_streams, &idx)) { + + if (sync->type != PLAYBACK_STREAM) + continue; + + if (sync->syncid == syncid) + break; + } + + /* Synced streams must connect to the same sink */ + if (sync && sync->sink_input->sink != sink) + return NULL; + if (!(sink_input = pa_sink_input_new(sink, __FILE__, name, ss, map, 0, -1))) return NULL; - s = pa_xmalloc(sizeof(struct playback_stream)); + s = pa_xnew(struct playback_stream, 1); s->type = PLAYBACK_STREAM; s->connection = c; + s->syncid = syncid; s->sink_input = sink_input; + s->underrun = 1; s->sink_input->peek = sink_input_peek_cb; s->sink_input->drop = sink_input_drop_cb; @@ -353,24 +390,56 @@ static struct playback_stream* playback_stream_new( s->sink_input->userdata = s; s->sink_input->owner = c->protocol->module; s->sink_input->client = c->client; - - s->memblockq = pa_memblockq_new(maxlength, tlength, pa_frame_size(ss), prebuf, minreq, c->protocol->core->memblock_stat); - assert(s->memblockq); + if (sync) { + /* Sync id found, now find head of list */ + PA_LLIST_FIND_HEAD(struct playback_stream, sync, &sync); + + /* Prepend ourselves */ + PA_LLIST_PREPEND(struct playback_stream, sync, s); + + /* Set our start index to the current read index of the other grozp member(s) */ + assert(sync->next); + start_index = pa_memblockq_get_read_index(sync->next->memblockq); + } else { + /* This ia a new sync group */ + PA_LLIST_INIT(struct playback_stream, s); + start_index = 0; + } + + silence = pa_silence_memblock_new(ss, 0, c->protocol->core->memblock_stat); + + s->memblockq = pa_memblockq_new( + start_index, + maxlength, + tlength, + pa_frame_size(ss), + prebuf, + minreq, + silence, + c->protocol->core->memblock_stat); + + pa_memblock_unref(silence); + s->requested_bytes = 0; s->drain_request = 0; s->sink_input->volume = *volume; pa_idxset_put(c->output_streams, s, &s->index); + return s; } static void playback_stream_free(struct playback_stream* p) { + struct playback_stream *head; assert(p && p->connection); if (p->drain_request) - pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERR_NOENTITY); + + PA_LLIST_FIND_HEAD(struct playback_stream, p, &head); + PA_LLIST_REMOVE(struct playback_stream, head, p); pa_idxset_remove_by_data(p->connection->output_streams, p, NULL); pa_sink_input_disconnect(p->sink_input); @@ -436,7 +505,7 @@ static void request_bytes(struct playback_stream *s) { pa_tagstruct_putu32(t, l); pa_pstream_send_tagstruct(s->connection->pstream, t); -/* pa_log(__FILE__": Requesting %u bytes\n", l); */ +/* pa_log(__FILE__": Requesting %u bytes\n", l); */ } static void send_memblock(struct connection *c) { @@ -461,7 +530,7 @@ static void send_memblock(struct connection *c) { if (schunk.length > r->fragment_size) schunk.length = r->fragment_size; - pa_pstream_send_memblock(c->pstream, r->index, 0, &schunk); + pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk); pa_memblockq_drop(r->memblockq, &chunk, schunk.length); pa_memblock_unref(schunk.memblock); @@ -501,9 +570,27 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { assert(i && i->userdata && chunk); s = i->userdata; - if (pa_memblockq_peek(s->memblockq, chunk) < 0) - return -1; + if (pa_memblockq_get_length(s->memblockq) <= 0 && !s->underrun) { + pa_tagstruct *t; + /* Report that we're empty */ + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, s->index); + pa_pstream_send_tagstruct(s->connection->pstream, t); + + s->underrun = 1; + } + + if (pa_memblockq_peek(s->memblockq, chunk) < 0) { + pa_log(__FILE__": peek: failure\n"); + return -1; + } + +/* pa_log(__FILE__": peek: %u\n", chunk->length); */ + return 0; } @@ -513,6 +600,7 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_ s = i->userdata; pa_memblockq_drop(s->memblockq, chunk, length); + request_bytes(s); if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) { @@ -520,7 +608,7 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_ s->drain_request = 0; } -/* pa_log(__FILE__": after_drop: %u\n", pa_memblockq_get_length(s->memblockq)); */ +/* pa_log(__FILE__": after_drop: %u %u\n", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */ } static void sink_input_kill_cb(pa_sink_input *i) { @@ -546,7 +634,11 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) assert(o && o->userdata && chunk); s = o->userdata; - pa_memblockq_push_align(s->memblockq, chunk, 0); + if (pa_memblockq_push_align(s->memblockq, chunk) < 0) { + pa_log_warn(__FILE__": Failed to push data into output queue.\n"); + return; + } + if (!pa_pstream_is_pending(s->connection->pstream)) send_memblock(s->connection); } @@ -578,7 +670,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC struct connection *c = userdata; struct playback_stream *s; size_t maxlength, tlength, prebuf, minreq; - uint32_t sink_index; + uint32_t sink_index, syncid; const char *name, *sink_name; pa_sample_spec ss; pa_channel_map map; @@ -601,6 +693,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC PA_TAG_U32, &tlength, PA_TAG_U32, &prebuf, PA_TAG_U32, &minreq, + PA_TAG_U32, &syncid, PA_TAG_CVOLUME, &volume, PA_TAG_INVALID) < 0 || !pa_tagstruct_eof(t) || @@ -610,23 +703,23 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } - if (sink_index != (uint32_t) -1) + if (sink_index != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); else sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1); if (!sink) { - pa_log("%s: Can't find a suitable sink.\n", __FILE__); - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_log_warn(__FILE__": Can't find a suitable sink.\n"); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } - if (!(s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); + if (!(s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume, syncid))) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); return; } @@ -656,14 +749,14 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (command == PA_COMMAND_DELETE_PLAYBACK_STREAM) { struct playback_stream *s; if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != PLAYBACK_STREAM)) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); return; } @@ -671,7 +764,7 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma } else if (command == PA_COMMAND_DELETE_RECORD_STREAM) { struct record_stream *s; if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); return; } @@ -680,7 +773,7 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma struct upload_stream *s; assert(command == PA_COMMAND_DELETE_UPLOAD_STREAM); if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); return; } @@ -717,7 +810,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -727,12 +820,12 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1); if (!source) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } if (!(s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); return; } @@ -758,7 +851,7 @@ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -782,7 +875,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t if (!c->authorized) { if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) { pa_log(__FILE__": Denied access to client with invalid authorization key.\n"); - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -826,7 +919,7 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -842,7 +935,7 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin } if (idx == PA_IDXSET_INVALID) - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); else { pa_tagstruct *reply; reply = pa_tagstruct_new(NULL, 0); @@ -867,12 +960,12 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -881,10 +974,10 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC pa_memblockq_prebuf_disable(s->memblockq); if (!pa_memblockq_is_readable(s->memblockq)) { -/* pa_log("immediate drain: %u\n", pa_memblockq_get_length(s->memblockq)); */ +/* pa_log("immediate drain: %u\n", pa_memblockq_get_length(s->memblockq)); */ pa_pstream_send_simple_ack(c->pstream, tag); } else { -/* pa_log("slow drain triggered\n"); */ +/* pa_log("slow drain triggered\n"); */ s->drain_request = 1; s->drain_tag = tag; @@ -903,7 +996,7 @@ static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -937,12 +1030,12 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -980,12 +1073,12 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1026,17 +1119,17 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if ((length % pa_frame_size(&ss)) != 0 || length <= 0 || !*name) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); return; } if (!(s = upload_stream_new(c, &ss, &map, name, length))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID); + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); return; } @@ -1063,12 +1156,12 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); return; } @@ -1095,7 +1188,7 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1105,12 +1198,12 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1); if (!sink) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } if (pa_scache_play_item(c->protocol->core, name, sink, &volume) < 0) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1129,12 +1222,12 @@ static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (pa_scache_remove_item(c->protocol->core, name) < 0) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1261,7 +1354,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1292,7 +1385,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u } if (!sink && !source && !client && !module && !si && !so && !sce) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1331,7 +1424,7 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1394,7 +1487,7 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1444,7 +1537,7 @@ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1478,7 +1571,7 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1493,7 +1586,7 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, } if (!si && !sink) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1509,7 +1602,7 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ struct connection *c = userdata; uint32_t idx; int b; - struct playback_stream *s; + struct playback_stream *s, *sync; assert(c && t); if (pa_tagstruct_getu32(t, &idx) < 0 || @@ -1520,20 +1613,82 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } + fprintf(stderr, "Corking %i\n", b); + pa_sink_input_cork(s->sink_input, b); + pa_memblockq_prebuf_force(s->memblockq); + + /* Do the same for all other members in the sync group */ + for (sync = s->prev; sync; sync = sync->prev) { + pa_sink_input_cork(sync->sink_input, b); + pa_memblockq_prebuf_force(sync->memblockq); + } + + for (sync = s->next; sync; sync = sync->next) { + pa_sink_input_cork(sync->sink_input, b); + pa_memblockq_prebuf_force(sync->memblockq); + } + pa_pstream_send_simple_ack(c->pstream, tag); +} + +static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t idx; + struct playback_stream *s, *sync; + assert(c && t); + + if (pa_tagstruct_getu32(t, &idx) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + if (!c->authorized) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); + return; + } + + if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); + return; + } + + pa_memblockq_flush(s->memblockq); + s->underrun = 0; + + /* Do the same for all other members in the sync group */ + for (sync = s->prev; sync; sync = sync->prev) { + pa_memblockq_flush(sync->memblockq); + sync->underrun = 0; + } + + for (sync = s->next; sync; sync = sync->next) { + pa_memblockq_flush(sync->memblockq); + sync->underrun = 0; + } + + pa_pstream_send_simple_ack(c->pstream, tag); + pa_sink_notify(s->sink_input->sink); + request_bytes(s); + + for (sync = s->prev; sync; sync = sync->prev) + request_bytes(sync); + + for (sync = s->next; sync; sync = sync->next) + request_bytes(sync); } -static void command_flush_or_trigger_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_trigger_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t idx; struct playback_stream *s; @@ -1546,23 +1701,26 @@ static void command_flush_or_trigger_playback_stream(PA_GCC_UNUSED pa_pdispatch } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } - if (command == PA_COMMAND_PREBUF_PLAYBACK_STREAM) - pa_memblockq_prebuf_reenable(s->memblockq); - else if (command == PA_COMMAND_TRIGGER_PLAYBACK_STREAM) - pa_memblockq_prebuf_disable(s->memblockq); - else { - assert(command == PA_COMMAND_FLUSH_PLAYBACK_STREAM); - pa_memblockq_flush(s->memblockq); - /*pa_log(__FILE__": flush: %u\n", pa_memblockq_get_length(s->memblockq));*/ + switch (command) { + case PA_COMMAND_PREBUF_PLAYBACK_STREAM: + pa_memblockq_prebuf_force(s->memblockq); + break; + + case PA_COMMAND_TRIGGER_PLAYBACK_STREAM: + pa_memblockq_prebuf_disable(s->memblockq); + break; + + default: + abort(); } pa_sink_notify(s->sink_input->sink); @@ -1585,16 +1743,17 @@ static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } pa_source_output_cork(s->source_output, b); + pa_memblockq_prebuf_force(s->memblockq); pa_pstream_send_simple_ack(c->pstream, tag); } @@ -1611,12 +1770,12 @@ static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_U } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1638,7 +1797,7 @@ static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, u } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1660,7 +1819,7 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1668,7 +1827,7 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com struct playback_stream *s; if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1678,7 +1837,7 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com struct record_stream *s; if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1700,7 +1859,7 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1708,7 +1867,7 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 pa_client *client; if (!(client = pa_idxset_get_by_index(c->protocol->core->clients, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1717,7 +1876,7 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 pa_sink_input *s; if (!(s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1728,7 +1887,7 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT); if (!(s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1753,12 +1912,12 @@ static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (!(m = pa_module_load(c->protocol->core, name, argument))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_INITFAILED); + pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED); return; } @@ -1782,12 +1941,12 @@ static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (!(m = pa_idxset_get_by_index(c->protocol->core->modules, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1813,12 +1972,12 @@ static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED u } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &idx) < 0) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST); + pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); return; } @@ -1847,7 +2006,7 @@ static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1857,7 +2016,7 @@ static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE r = pa_autoload_remove_by_index(c->protocol->core, idx); if (r < 0) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1893,7 +2052,7 @@ static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNU } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1904,7 +2063,7 @@ static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNU a = pa_autoload_get_by_index(c->protocol->core, idx); if (!a) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } @@ -1927,7 +2086,7 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC } if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); + pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1958,7 +2117,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *user } } -static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { struct connection *c = userdata; struct output_stream *stream; assert(p && chunk && userdata); @@ -1975,13 +2134,30 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, uint32_t ps->requested_bytes = 0; else ps->requested_bytes -= chunk->length; - - pa_memblockq_push_align(ps->memblockq, chunk, delta); - assert(ps->sink_input); -/* pa_log(__FILE__": after_recv: %u\n", pa_memblockq_get_length(p->memblockq)); */ + pa_memblockq_seek(ps->memblockq, offset, seek); + + if (pa_memblockq_push_align(ps->memblockq, chunk) < 0) { + pa_tagstruct *t; + + pa_log_warn(__FILE__": failed to push data into queue\n"); + + /* Pushing this block into the queue failed, so we simulate + * it by skipping ahead */ + + pa_memblockq_seek(ps->memblockq, chunk->length, PA_SEEK_RELATIVE); + + /* Notify the user */ + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, ps->index); + pa_pstream_send_tagstruct(p, t); + } + + ps->underrun = 0; + pa_sink_notify(ps->sink_input->sink); -/* pa_log(__FILE__": Recieved %u bytes.\n", chunk->length); */ } else { struct upload_stream *u = (struct upload_stream*) stream; diff --git a/src/polypcore/protocol-simple.c b/src/polypcore/protocol-simple.c index 4d3f8e1d9..fac542391 100644 --- a/src/polypcore/protocol-simple.c +++ b/src/polypcore/protocol-simple.c @@ -52,6 +52,8 @@ struct connection { pa_memblockq *input_memblockq, *output_memblockq; pa_defer_event *defer_event; + int dead; + struct { pa_memblock *current_memblock; size_t memblock_index, fragment_size; @@ -130,7 +132,7 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - pa_log(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + pa_log_debug(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -142,7 +144,7 @@ static int do_read(struct connection *c) { c->playback.memblock_index += r; assert(c->input_memblockq); - pa_memblockq_push_align(c->input_memblockq, &chunk, 0); + pa_memblockq_push_align(c->input_memblockq, &chunk); assert(c->sink_input); pa_sink_notify(c->sink_input->sink); @@ -170,32 +172,46 @@ static int do_write(struct connection *c) { pa_memblockq_drop(c->output_memblockq, &chunk, r); pa_memblock_unref(chunk.memblock); + + pa_source_notify(c->source_output->source); return 0; } - static void do_work(struct connection *c) { assert(c); assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 0); - if (pa_iochannel_is_writable(c->io)) - if (do_write(c) < 0) - goto fail; + if (c->dead) + return; - if (pa_iochannel_is_readable(c->io)) + if (pa_iochannel_is_readable(c->io)) { if (do_read(c) < 0) goto fail; + } else if (pa_iochannel_is_hungup(c->io)) + goto fail; - if (pa_iochannel_is_hungup(c->io)) - c->protocol->core->mainloop->defer_enable(c->defer_event, 1); + if (pa_iochannel_is_writable(c->io)) { + if (do_write(c) < 0) + goto fail; + } return; fail: - connection_free(c); + + if (c->sink_input) { + c->dead = 1; + + pa_iochannel_free(c->io); + c->io = NULL; + + pa_memblockq_prebuf_disable(c->input_memblockq); + pa_sink_notify(c->sink_input->sink); + } else + connection_free(c); } /*** sink_input callbacks ***/ @@ -205,8 +221,13 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { assert(i && i->userdata && chunk); c = i->userdata; - if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) + if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) { + + if (c->dead) + connection_free(c); + return -1; + } return 0; } @@ -240,7 +261,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) struct connection *c = o->userdata; assert(o && c && chunk); - pa_memblockq_push(c->output_memblockq, chunk, 0); + pa_memblockq_push(c->output_memblockq, chunk); /* do something */ assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); @@ -307,6 +328,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->playback.current_memblock = NULL; c->playback.memblock_index = 0; c->playback.fragment_size = 0; + c->dead = 0; pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); c->client = pa_client_new(p->core, __FILE__, cname); @@ -339,7 +361,15 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->sink_input->userdata = c; l = (size_t) (pa_bytes_per_second(&p->sample_spec)*PLAYBACK_BUFFER_SECONDS); - c->input_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&p->sample_spec), l/2, l/PLAYBACK_BUFFER_FRAGMENTS, p->core->memblock_stat); + c->input_memblockq = pa_memblockq_new( + 0, + l, + 0, + pa_frame_size(&p->sample_spec), + (size_t) -1, + l/PLAYBACK_BUFFER_FRAGMENTS, + NULL, + p->core->memblock_stat); assert(c->input_memblockq); pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5); c->playback.fragment_size = l/10; @@ -368,7 +398,15 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->source_output->userdata = c; l = (size_t) (pa_bytes_per_second(&p->sample_spec)*RECORD_BUFFER_SECONDS); - c->output_memblockq = pa_memblockq_new(l, 0, pa_frame_size(&p->sample_spec), 0, 0, p->core->memblock_stat); + c->output_memblockq = pa_memblockq_new( + 0, + l, + 0, + pa_frame_size(&p->sample_spec), + 1, + 0, + NULL, + p->core->memblock_stat); pa_iochannel_socket_set_sndbuf(io, l/RECORD_BUFFER_FRAGMENTS*2); } diff --git a/src/polypcore/pstream.c b/src/polypcore/pstream.c index eec93a0f7..c697dc3d6 100644 --- a/src/polypcore/pstream.c +++ b/src/polypcore/pstream.c @@ -40,12 +40,14 @@ #include "pstream.h" -typedef enum pa_pstream_descriptor_index { +enum { PA_PSTREAM_DESCRIPTOR_LENGTH, PA_PSTREAM_DESCRIPTOR_CHANNEL, - PA_PSTREAM_DESCRIPTOR_DELTA, + PA_PSTREAM_DESCRIPTOR_OFFSET_HI, + PA_PSTREAM_DESCRIPTOR_OFFSET_LO, + PA_PSTREAM_DESCRIPTOR_SEEK, PA_PSTREAM_DESCRIPTOR_MAX -} pa_pstream_descriptor_index; +}; typedef uint32_t pa_pstream_descriptor[PA_PSTREAM_DESCRIPTOR_MAX]; @@ -58,7 +60,8 @@ struct item_info { /* memblock info */ pa_memchunk chunk; uint32_t channel; - uint32_t delta; + int64_t offset; + pa_seek_mode_t seek_mode; /* packet info */ pa_packet *packet; @@ -94,7 +97,7 @@ struct pa_pstream { void (*recieve_packet_callback) (pa_pstream *p, pa_packet *packet, void *userdata); void *recieve_packet_callback_userdata; - void (*recieve_memblock_callback) (pa_pstream *p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk, void *userdata); + void (*recieve_memblock_callback) (pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata); void *recieve_memblock_callback_userdata; void (*drain_callback)(pa_pstream *p, void *userdata); @@ -103,8 +106,8 @@ struct pa_pstream { pa_memblock_stat *memblock_stat; }; -static void do_write(pa_pstream *p); -static void do_read(pa_pstream *p); +static int do_write(pa_pstream *p); +static int do_read(pa_pstream *p); static void do_something(pa_pstream *p) { assert(p); @@ -112,31 +115,47 @@ static void do_something(pa_pstream *p) { p->mainloop->defer_enable(p->defer_event, 0); pa_pstream_ref(p); - - if (!p->dead && pa_iochannel_is_readable(p->io)) - do_read(p); - if (!p->dead && pa_iochannel_is_writable(p->io)) - do_write(p); + if (!p->dead && pa_iochannel_is_readable(p->io)) { + if (do_read(p) < 0) + goto fail; + } else if (!p->dead && pa_iochannel_is_hungup(p->io)) + goto fail; - /* In case the line was hungup, make sure to rerun this function - as soon as possible, until all data has been read. */ + if (!p->dead && pa_iochannel_is_writable(p->io)) { + if (do_write(p) < 0) + goto fail; + } + + pa_pstream_unref(p); + return; + +fail: + + p->dead = 1; - if (!p->dead && pa_iochannel_is_hungup(p->io)) - p->mainloop->defer_enable(p->defer_event, 1); + if (p->die_callback) + p->die_callback(p, p->die_callback_userdata); pa_pstream_unref(p); } static void io_callback(pa_iochannel*io, void *userdata) { pa_pstream *p = userdata; - assert(p && p->io == io); + + assert(p); + assert(p->io == io); + do_something(p); } static void defer_callback(pa_mainloop_api *m, pa_defer_event *e, void*userdata) { pa_pstream *p = userdata; - assert(p && p->defer_event == e && p->mainloop == m); + + assert(p); + assert(p->defer_event == e); + assert(p->mainloop == m); + do_something(p); } @@ -144,7 +163,8 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta pa_pstream *p; assert(io); - p = pa_xmalloc(sizeof(pa_pstream)); + p = pa_xnew(pa_pstream, 1); + p->ref = 1; p->io = io; pa_iochannel_set_callback(io, io_callback, p); @@ -228,7 +248,7 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet) { /* pa_log(__FILE__": push-packet %p\n", packet); */ - i = pa_xmalloc(sizeof(struct item_info)); + i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); @@ -236,7 +256,7 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet) { p->mainloop->defer_enable(p->defer_event, 1); } -void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk) { +void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) { struct item_info *i; assert(p && channel != (uint32_t) -1 && chunk && p->ref >= 1); @@ -245,11 +265,12 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, uint32_t delta, co /* pa_log(__FILE__": push-memblock %p\n", chunk); */ - i = pa_xmalloc(sizeof(struct item_info)); + i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_MEMBLOCK; i->chunk = *chunk; i->channel = channel; - i->delta = delta; + i->offset = offset; + i->seek_mode = seek_mode; pa_memblock_ref(i->chunk.memblock); @@ -264,7 +285,7 @@ void pa_pstream_set_recieve_packet_callback(pa_pstream *p, void (*callback) (pa_ p->recieve_packet_callback_userdata = userdata; } -void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, void (*callback) (pa_pstream *p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk, void *userdata), void *userdata) { +void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, void (*callback) (pa_pstream *p, uint32_t channel, int64_t delta, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata), void *userdata) { assert(p && callback); p->recieve_memblock_callback = callback; @@ -286,17 +307,21 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.data = p->write.current->packet->data; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1); - p->write.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA] = 0; + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = 0; + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = 0; + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = 0; } else { assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK && p->write.current->chunk.memblock); p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl(p->write.current->channel); - p->write.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA] = htonl(p->write.current->delta); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl((uint32_t) (((uint64_t) p->write.current->offset) >> 32)); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = htonl((uint32_t) ((uint64_t) p->write.current->offset)); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = htonl(p->write.current->seek_mode); } } -static void do_write(pa_pstream *p) { +static int do_write(pa_pstream *p) { void *d; size_t l; ssize_t r; @@ -306,7 +331,7 @@ static void do_write(pa_pstream *p) { prepare_next_write_item(p); if (!p->write.current) - return; + return 0; assert(p->write.data); @@ -319,7 +344,7 @@ static void do_write(pa_pstream *p) { } if ((r = pa_iochannel_write(p->io, d, l)) < 0) - goto die; + return -1; p->write.index += r; @@ -332,15 +357,10 @@ static void do_write(pa_pstream *p) { p->drain_callback(p, p->drain_userdata); } - return; - -die: - p->dead = 1; - if (p->die_callback) - p->die_callback(p, p->die_callback_userdata); + return 0; } -static void do_read(pa_pstream *p) { +static int do_read(pa_pstream *p) { void *d; size_t l; ssize_t r; @@ -356,7 +376,7 @@ static void do_read(pa_pstream *p) { } if ((r = pa_iochannel_read(p->io, d, l)) <= 0) - goto die; + return -1; p->read.index += r; @@ -365,8 +385,8 @@ static void do_read(pa_pstream *p) { /* Frame size too large */ if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) > FRAME_SIZE_MAX) { - pa_log(__FILE__": Frame size too large\n"); - goto die; + pa_log_warn(__FILE__": Frame size too large\n"); + return -1; } assert(!p->read.packet && !p->read.memblock); @@ -374,13 +394,16 @@ static void do_read(pa_pstream *p) { if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]) == (uint32_t) -1) { /* Frame is a packet frame */ p->read.packet = pa_packet_new(ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])); - assert(p->read.packet); p->read.data = p->read.packet->data; } else { /* Frame is a memblock frame */ p->read.memblock = pa_memblock_new(ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]), p->memblock_stat); - assert(p->read.memblock); p->read.data = p->read.memblock->data; + + if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK]) > PA_SEEK_RELATIVE_END) { + pa_log_warn(__FILE__": Invalid seek mode\n"); + return -1; + } } } else if (p->read.index > PA_PSTREAM_DESCRIPTOR_SIZE) { @@ -396,13 +419,26 @@ static void do_read(pa_pstream *p) { chunk.index = p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE - l; chunk.length = l; - if (p->recieve_memblock_callback) + if (p->recieve_memblock_callback) { + int64_t offset; + + offset = (int64_t) ( + (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) | + (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO])))); + p->recieve_memblock_callback( p, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]), - ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_DELTA]), + offset, + ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK]), &chunk, p->recieve_memblock_callback_userdata); + } + + /* Drop seek info for following callbacks */ + p->read.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = + p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = + p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = 0; } } @@ -427,13 +463,7 @@ static void do_read(pa_pstream *p) { } } - return; - -die: - p->dead = 1; - if (p->die_callback) - p->die_callback(p, p->die_callback_userdata); - + return 0; } void pa_pstream_set_die_callback(pa_pstream *p, void (*callback)(pa_pstream *p, void *userdata), void *userdata) { @@ -453,20 +483,24 @@ int pa_pstream_is_pending(pa_pstream *p) { void pa_pstream_set_drain_callback(pa_pstream *p, void (*cb)(pa_pstream *p, void *userdata), void *userdata) { assert(p); + assert(p->ref >= 1); p->drain_callback = cb; p->drain_userdata = userdata; } void pa_pstream_unref(pa_pstream*p) { - assert(p && p->ref >= 1); + assert(p); + assert(p->ref >= 1); - if (!(--(p->ref))) + if (--p->ref == 0) pstream_free(p); } pa_pstream* pa_pstream_ref(pa_pstream*p) { - assert(p && p->ref >= 1); + assert(p); + assert(p->ref >= 1); + p->ref++; return p; } diff --git a/src/polypcore/pstream.h b/src/polypcore/pstream.h index 10ce58f60..741ba9b53 100644 --- a/src/polypcore/pstream.h +++ b/src/polypcore/pstream.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -37,10 +38,10 @@ void pa_pstream_unref(pa_pstream*p); pa_pstream* pa_pstream_ref(pa_pstream*p); void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet); -void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk); +void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk); void pa_pstream_set_recieve_packet_callback(pa_pstream *p, void (*callback) (pa_pstream *p, pa_packet *packet, void *userdata), void *userdata); -void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, void (*callback) (pa_pstream *p, uint32_t channel, uint32_t delta, const pa_memchunk *chunk, void *userdata), void *userdata); +void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, void (*callback) (pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata), void *userdata); void pa_pstream_set_drain_callback(pa_pstream *p, void (*cb)(pa_pstream *p, void *userdata), void *userdata); void pa_pstream_set_die_callback(pa_pstream *p, void (*callback)(pa_pstream *p, void *userdata), void *userdata); diff --git a/src/polypcore/sample-util.c b/src/polypcore/sample-util.c index e3bb4aa6c..e588446d3 100644 --- a/src/polypcore/sample-util.c +++ b/src/polypcore/sample-util.c @@ -34,6 +34,15 @@ #include "sample-util.h" +pa_memblock *pa_silence_memblock_new(const pa_sample_spec *spec, size_t length, pa_memblock_stat*s) { + assert(spec); + + if (length == 0) + length = pa_bytes_per_second(spec)/10; /* 100 ms */ + + return pa_silence_memblock(pa_memblock_new(length, s), spec); +} + pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { assert(b && b->data && spec); pa_silence_memory(b->data, b->length, spec); diff --git a/src/polypcore/sample-util.h b/src/polypcore/sample-util.h index 486d284ba..7ea01a30b 100644 --- a/src/polypcore/sample-util.h +++ b/src/polypcore/sample-util.h @@ -28,6 +28,7 @@ #include pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec); +pa_memblock *pa_silence_memblock_new(const pa_sample_spec *spec, size_t length, pa_memblock_stat*s); void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec); void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec); diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index 9bc478c3c..1f374f5ed 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -270,6 +270,8 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { result->memblock = pa_memblock_new(length, s->core->memblock_stat); assert(result->memblock); +/* pa_log("mixing %i\n", n); */ + result->length = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, &s->sw_volume); result->index = 0; } diff --git a/src/polypcore/sink.h b/src/polypcore/sink.h index 5fd9784f9..fa120ebf4 100644 --- a/src/polypcore/sink.h +++ b/src/polypcore/sink.h @@ -34,7 +34,7 @@ typedef struct pa_sink pa_sink; #include #include -#define PA_MAX_INPUTS_PER_SINK 6 +#define PA_MAX_INPUTS_PER_SINK 32 typedef enum pa_sink_state { PA_SINK_RUNNING, diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c new file mode 100644 index 000000000..b01084da1 --- /dev/null +++ b/src/tests/memblockq-test.c @@ -0,0 +1,147 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +int main(int argc, char *argv[]) { + int ret; + pa_memblockq *bq; + pa_memchunk chunk1, chunk2, chunk3, chunk4; + pa_memblock *silence; + + pa_log_set_maximal_level(PA_LOG_DEBUG); + + silence = pa_memblock_new_fixed("__", 2, 1, NULL); + assert(silence); + + bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, silence, NULL); + assert(bq); + + chunk1.memblock = pa_memblock_new_fixed("AA", 2, 1, NULL); + chunk1.index = 0; + chunk1.length = 2; + assert(chunk1.memblock); + + chunk2.memblock = pa_memblock_new_fixed("TTBB", 4, 1, NULL); + chunk2.index = 2; + chunk2.length = 2; + assert(chunk2.memblock); + + chunk3.memblock = pa_memblock_new_fixed("ZZZZ", 4, 1, NULL); + chunk3.index = 0; + chunk3.length = 4; + assert(chunk3.memblock); + + chunk4.memblock = pa_memblock_new_fixed("KKKKKKKK", 8, 1, NULL); + chunk4.index = 0; + chunk4.length = 8; + assert(chunk4.memblock); + + ret = pa_memblockq_push(bq, &chunk1); + assert(ret == 0); + + ret = pa_memblockq_push(bq, &chunk1); + assert(ret == 0); + + ret = pa_memblockq_push(bq, &chunk2); + assert(ret == 0); + + ret = pa_memblockq_push(bq, &chunk2); + assert(ret == 0); + + pa_memblockq_seek(bq, -6, 0); + ret = pa_memblockq_push(bq, &chunk3); + assert(ret == 0); + + pa_memblockq_seek(bq, -2, 0); + ret = pa_memblockq_push(bq, &chunk3); + assert(ret == 0); + + pa_memblockq_seek(bq, -10, 0); + ret = pa_memblockq_push(bq, &chunk4); + assert(ret == 0); + + pa_memblockq_seek(bq, 10, 0); + + ret = pa_memblockq_push(bq, &chunk1); + assert(ret == 0); + + pa_memblockq_seek(bq, -6, 0); + ret = pa_memblockq_push(bq, &chunk2); + assert(ret == 0); + + /* Test splitting */ + pa_memblockq_seek(bq, -12, 0); + ret = pa_memblockq_push(bq, &chunk1); + assert(ret == 0); + + pa_memblockq_seek(bq, 20, 0); + + /* Test merging */ + ret = pa_memblockq_push(bq, &chunk3); + assert(ret == 0); + pa_memblockq_seek(bq, -2, 0); + + chunk3.index += 2; + chunk3.length -= 2; + + ret = pa_memblockq_push(bq, &chunk3); + assert(ret == 0); + + printf(">"); + + pa_memblockq_shorten(bq, 6); + + for (;;) { + pa_memchunk out; + char *e; + size_t n; + + if (pa_memblockq_peek(bq, &out) < 0) + break; + + for (e = (char*) out.memblock->data + out.index, n = 0; n < out.length; n++) + printf("%c", *e); + + pa_memblock_unref(out.memblock); + pa_memblockq_drop(bq, &out, out.length); + } + + printf("<\n"); + + pa_memblockq_free(bq); + pa_memblock_unref(silence); + pa_memblock_unref(chunk1.memblock); + pa_memblock_unref(chunk2.memblock); + pa_memblock_unref(chunk3.memblock); + pa_memblock_unref(chunk4.memblock); + + return 0; +} diff --git a/src/tests/sync-playback.c b/src/tests/sync-playback.c new file mode 100644 index 000000000..5df790c9a --- /dev/null +++ b/src/tests/sync-playback.c @@ -0,0 +1,192 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define NSTREAMS 4 +#define SINE_HZ 440 +#define SAMPLE_HZ 8000 + +static pa_context *context = NULL; +static pa_stream *streams[NSTREAMS]; +static pa_mainloop_api *mainloop_api = NULL; + +static float data[SAMPLE_HZ]; /* one second space */ + +static int n_streams_ready = 0; + +static const pa_sample_spec sample_spec = { + .format = PA_SAMPLE_FLOAT32, + .rate = SAMPLE_HZ, + .channels = 1 +}; + +static const pa_buffer_attr buffer_attr = { + .maxlength = SAMPLE_HZ*sizeof(float)*NSTREAMS, /* exactly space for the entire play time */ + .tlength = 0, + .prebuf = 0, /* Setting prebuf to 0 guarantees us the the streams will run synchronously, no matter what */ + .minreq = 0 +}; + +static void nop_free_cb(void *p) {} + +static void underflow_cb(struct pa_stream *s, void *userdata) { + int i = (int) userdata; + + fprintf(stderr, "Stream %i finished\n", i); + + if (++n_streams_ready >= 2*NSTREAMS) { + fprintf(stderr, "We're done\n"); + mainloop_api->quit(mainloop_api, 0); + } +} + +/* This routine is called whenever the stream state changes */ +static void stream_state_callback(pa_stream *s, void *userdata) { + assert(s); + + switch (pa_stream_get_state(s)) { + case PA_STREAM_UNCONNECTED: + case PA_STREAM_CREATING: + case PA_STREAM_TERMINATED: + break; + + case PA_STREAM_READY: { + + int r, i = (int) userdata; + + fprintf(stderr, "Writing data to stream %i.\n", i); + + r = pa_stream_write(s, data, sizeof(data), nop_free_cb, sizeof(data) * i, PA_SEEK_ABSOLUTE); + assert(r == 0); + + /* Be notified when this stream is drained */ + pa_stream_set_underflow_callback(s, underflow_cb, userdata); + + /* All streams have been set up, let's go! */ + if (++n_streams_ready >= NSTREAMS) { + fprintf(stderr, "Uncorking\n"); + pa_operation_unref(pa_stream_cork(s, 0, NULL, NULL)); + } + + break; + } + + default: + case PA_STREAM_FAILED: + fprintf(stderr, "Stream error: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + abort(); + } +} + +/* This is called whenever the context status changes */ +static void context_state_callback(pa_context *c, void *userdata) { + assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: { + + int i; + fprintf(stderr, "Connection established.\n"); + + for (i = 0; i < NSTREAMS; i++) { + char name[64]; + + fprintf(stderr, "Creating stream %i\n", i); + + snprintf(name, sizeof(name), "stream #%i", i); + + streams[i] = pa_stream_new(c, name, &sample_spec, NULL); + assert(streams[i]); + pa_stream_set_state_callback(streams[i], stream_state_callback, (void*) i); + pa_stream_connect_playback(streams[i], NULL, &buffer_attr, PA_STREAM_START_CORKED, NULL, i == 0 ? NULL : streams[0]); + } + + break; + } + + case PA_CONTEXT_TERMINATED: + mainloop_api->quit(mainloop_api, 0); + break; + + case PA_CONTEXT_FAILED: + default: + fprintf(stderr, "Context error: %s\n", pa_strerror(pa_context_errno(c))); + abort(); + } +} + +int main(int argc, char *argv[]) { + pa_mainloop* m = NULL; + int i, ret = 0; + + for (i = 0; i < SAMPLE_HZ; i++) + data[i] = (float) sin(((double) i/SAMPLE_HZ)*2*M_PI*SINE_HZ)/2; + + for (i = 0; i < NSTREAMS; i++) + streams[i] = NULL; + + /* Set up a new main loop */ + m = pa_mainloop_new(); + assert(m); + + mainloop_api = pa_mainloop_get_api(m); + + context = pa_context_new(mainloop_api, argv[0]); + assert(context); + + pa_context_set_state_callback(context, context_state_callback, NULL); + + pa_context_connect(context, NULL, 1, NULL); + + if (pa_mainloop_run(m, &ret) < 0) + fprintf(stderr, "pa_mainloop_run() failed.\n"); + + pa_context_unref(context); + + for (i = 0; i < NSTREAMS; i++) + if (streams[i]) + pa_stream_unref(streams[i]); + + pa_mainloop_free(m); + + return ret; +} diff --git a/src/utils/pacat.c b/src/utils/pacat.c index a3c3f2c8b..4e126c8ad 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -80,7 +80,7 @@ static void do_stream_write(size_t length) { if (l > buffer_length) l = buffer_length; - pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0); + pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE); buffer_length -= l; buffer_index += l; @@ -106,8 +106,8 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { /* This is called whenever new data may is available */ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { + const void *data; assert(s && length); - void *data; if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); @@ -175,7 +175,7 @@ static void context_state_callback(pa_context *c, void *userdata) { if (mode == PLAYBACK) { pa_cvolume cv; - pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume)); + pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume), NULL); } else pa_stream_connect_record(stream, device, NULL, 0); diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 4c22c9251..e3305f0f5 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -515,7 +515,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { quit(1); } - pa_stream_write(s, d, length, free, 0); + pa_stream_write(s, d, length, free, 0, PA_SEEK_RELATIVE); sample_length -= length; diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 9f73b8341..5f985ee9d 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -113,7 +113,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { f = readf_function(sndfile, data, n); if (f > 0) - pa_stream_write(s, data, f*k, free, 0); + pa_stream_write(s, data, f*k, free, 0, PA_SEEK_RELATIVE); if (f < n) { sf_close(sndfile); @@ -166,7 +166,7 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_stream_set_state_callback(stream, stream_state_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); - pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume)); + pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL); break; } From 16285f9cc35a8fd4b8920fd65c309b3a419e3d0d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 04:05:59 +0000 Subject: [PATCH 0419/1514] make doxygen ignore PA_CDECL_BEGIN/PA_CDECL_END git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@512 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doxygen/doxygen.conf.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index fcda21947..747abbd97 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -950,14 +950,14 @@ INCLUDE_FILE_PATTERNS = # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. -PREDEFINED = PA_C_DECL_BEGIN=,PA_C_DECL_END +PREDEFINED = PA_C_DECL_BEGIN= PA_C_DECL_END= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. -EXPAND_AS_DEFINED = PA_C_DECL_BEGIN, PA_C_DECL_END +#EXPAND_AS_DEFINED = PA_C_DECL_BEGIN, PA_C_DECL_END # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone From 081fb74c00562acea32d0c8ce04317de5035dc0d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 04:06:13 +0000 Subject: [PATCH 0420/1514] update TODO git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@513 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/doc/todo b/doc/todo index 41333b75d..550f392c2 100644 --- a/doc/todo +++ b/doc/todo @@ -1,14 +1,16 @@ *** $Id$ *** -Architectural changes: -- add API for synchronizing multiple sinks/sources to a common clock -- absolutely indexed write()s from client +Test: +- module-combine +- latency foo Fixes: - improve module-oss-mmap latency measurement - module-tunnel: improve latency calculation - make alsa modules use mmap -- even more commenting +- better validity checking in libpolyp and protocol-{native,esound} +- don't build ipv4 and ipv6 modules seperately +- change pa_log to not require \n Features: - add radio module @@ -16,6 +18,12 @@ Features: - polish for starting polypaudio as root/system-wide instance - add threading API - add support for auth using SCM_CREDENTIALS +- include hw description in sink/source info +- use scatter/gather io for sockets +- hw volume support for alsa, oss-mmap, windows, solaris +- notifcation on hw volume change +- source volume control +- deal with underflows reported by OSS/ALSA properly Long term: - pass meta info for hearing impaired @@ -34,4 +42,5 @@ Done: - hardware volume support - alsa-lib - remove "polyplib-" prefix - +- add API for synchronizing multiple sinks/sources to a common clock +- absolutely indexed write()s from client From e9658bb9972e693ed93d55f5bf767b660aa10dce Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 20 Feb 2006 10:38:57 +0000 Subject: [PATCH 0421/1514] util.c uses some socket functions so we need winsock on Windows. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@514 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 4cf61f27a..5581d77ed 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -260,7 +260,7 @@ memblockq_test_SOURCES = \ polypcore/mcalign.c \ polypcore/memchunk.c memblockq_test_CFLAGS = $(AM_CFLAGS) -memblockq_test_LDADD = $(AM_LDADD) +memblockq_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) memblockq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) sync_playback_SOURCES = tests/sync-playback.c From 0eed96d7649d63a24c2a251b143d26a46ab91742 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 20 Feb 2006 10:40:40 +0000 Subject: [PATCH 0422/1514] Remove a debug fprintf that was left in. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@515 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 8809c31d3..3a8600c7d 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -319,8 +319,6 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { r += pa_bytes_to_usec((free_frags + 1) * u->fragment_size, &s->sample_spec); - fprintf(stderr, "Latency: %d us\n", (int)r); - return r; } From d1bc972e6955601836c476093cb07ba961e51738 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 20 Feb 2006 12:42:28 +0000 Subject: [PATCH 0423/1514] Detect support for Solaris (/dev/audio). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@516 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 5 ++++- src/modules/module-detect.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4261903f1..5ffea5ef2 100644 --- a/configure.ac +++ b/configure.ac @@ -309,7 +309,10 @@ AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1]) #### Solaris audio support (optional) #### -AC_CHECK_HEADERS([sys/audio.h], [HAVE_SOLARIS=1], [HAVE_SOLARIS=0]) +AC_CHECK_HEADERS([sys/audio.h], [ +HAVE_SOLARIS=1 +AC_DEFINE([HAVE_SOLARIS], 1, [Have Solaris audio?]) +], [HAVE_SOLARIS=0]) AC_SUBST(HAVE_SOLARIS) AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1]) diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index e325b22c3..4c0cdb4b7 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -171,6 +171,34 @@ static int detect_oss(pa_core *c, int just_one) { } #endif +#ifdef HAVE_SOLARIS +static int detect_solaris(pa_core *c, int just_one) { + struct stat s; + const char *dev; + char args[64]; + + dev = getenv("AUDIODEV"); + if (!dev) + dev = "/dev/audio"; + + if (stat(dev, &s) < 0) { + if (errno != ENOENT) + pa_log_error(__FILE__": failed to open device %s: %s\n", dev, strerror(errno)); + return -1; + } + + if (!S_ISCHR(s)) + return 0; + + snprintf(args, sizeof(args), "device=%s", dev); + + if (!pa_module_load(c, "module-solaris", args)) + return 0; + + return 1; +} +#endif + int pa__init(pa_core *c, pa_module*m) { int just_one = 0, n = 0; pa_modargs *ma; @@ -198,6 +226,9 @@ int pa__init(pa_core *c, pa_module*m) { #endif #if HAVE_OSS if ((n = detect_oss(c, just_one)) <= 0) +#endif +#if HAVE_SOLARIS + if ((n = detect_solaris(c, just_one)) <= 0) #endif { pa_log_warn(__FILE__": failed to detect any sound hardware.\n"); From 6c2d414e5879dccff78ebf1cb155fd1809fc785a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 20 Feb 2006 12:47:03 +0000 Subject: [PATCH 0424/1514] Detect support for Windows' waveout. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@517 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-detect.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 4c0cdb4b7..718b2eb44 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -199,6 +199,19 @@ static int detect_solaris(pa_core *c, int just_one) { } #endif +#ifdef OS_IS_WIN32 +static int detect_waveout(pa_core *c, int just_one) { + /* + * FIXME: No point in enumerating devices until the plugin supports + * selecting anything but the first. + */ + if (!pa_module_load(c, "module-waveout", "")) + return 0; + + return 1; +} +#endif + int pa__init(pa_core *c, pa_module*m) { int just_one = 0, n = 0; pa_modargs *ma; @@ -229,6 +242,9 @@ int pa__init(pa_core *c, pa_module*m) { #endif #if HAVE_SOLARIS if ((n = detect_solaris(c, just_one)) <= 0) +#endif +#if OS_IS_WIN32 + if ((n = detect_waveout(c, just_one)) <= 0) #endif { pa_log_warn(__FILE__": failed to detect any sound hardware.\n"); From 5cc0d0e68213a4ec49a3bb24001812dda1c4f665 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 20 Feb 2006 12:49:16 +0000 Subject: [PATCH 0425/1514] Add mute switch to todo. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@518 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 550f392c2..45989b451 100644 --- a/doc/todo +++ b/doc/todo @@ -24,6 +24,7 @@ Features: - notifcation on hw volume change - source volume control - deal with underflows reported by OSS/ALSA properly +- mute switch support (like ALSA does it) Long term: - pass meta info for hearing impaired From f2292aeeff200e45b46929c9d02e5d4a91fe0124 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 20 Feb 2006 13:59:42 +0000 Subject: [PATCH 0426/1514] Fixes for the Solaris detection. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@519 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-detect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 718b2eb44..18e22de64 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -187,7 +189,7 @@ static int detect_solaris(pa_core *c, int just_one) { return -1; } - if (!S_ISCHR(s)) + if (!S_ISCHR(s.st_mode)) return 0; snprintf(args, sizeof(args), "device=%s", dev); From b36ed4d23a70ecac070233eb47e374c94b735682 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 15:55:05 +0000 Subject: [PATCH 0427/1514] remove cdecl.h from doxygen docs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@520 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doxygen/doxygen.conf.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 747abbd97..9e426027a 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/cdecl.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h +INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp From 4566d56e31c58211763ddbb4669c7f04152669d0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 16:01:53 +0000 Subject: [PATCH 0428/1514] * Make typdefs for the pa_context callback prototypes * s/pa_context_notify_cb/pa_context_notify_cb_t/g git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@521 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 2 +- src/polyp/context.c | 14 +++++++------- src/polyp/context.h | 18 +++++++++++------- src/polyp/internal.h | 4 ++-- src/polypcore/pdispatch.c | 12 ++++++------ src/polypcore/pdispatch.h | 6 +++--- src/polypcore/protocol-native.c | 2 +- 7 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 672365887..3ecca7457 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -94,7 +94,7 @@ static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t t static void command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); #endif -static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = { +static const pa_pdispatch_callback_t command_table[PA_COMMAND_MAX] = { #ifdef TUNNEL_SINK [PA_COMMAND_REQUEST] = command_request, #endif diff --git a/src/polyp/context.c b/src/polyp/context.c index eac5dd231..e2d9d33d2 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -72,7 +72,7 @@ #define AUTOSPAWN_LOCK "autospawn.lock" -static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = { +static const pa_pdispatch_callback_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = pa_command_request, [PA_COMMAND_OVERFLOW] = pa_command_overflow_or_underflow, [PA_COMMAND_UNDERFLOW] = pa_command_overflow_or_underflow, @@ -671,7 +671,7 @@ int pa_context_errno(pa_context *c) { return c->error; } -void pa_context_set_state_callback(pa_context *c, void (*cb)(pa_context *c, void *userdata), void *userdata) { +void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { assert(c && c->ref >= 1); c->state_callback = cb; c->state_userdata = userdata; @@ -730,7 +730,7 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_operation_unref(o); } -pa_operation* pa_context_drain(pa_context *c, void (*cb) (pa_context*c, void *userdata), void *userdata) { +pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { pa_operation *o; assert(c && c->ref >= 1); @@ -777,7 +777,7 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_U } if (o->callback) { - void (*cb)(pa_context *c, int _success, void *_userdata) = (void (*)(pa_context *c, int _success, void *_userdata)) o->callback; + pa_context_success_cb_t cb = (pa_context_success_cb_t) o->callback; cb(o->context, success, o->userdata); } @@ -805,7 +805,7 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, vo return pa_operation_ref(o); } -pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; @@ -825,7 +825,7 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, void( return pa_operation_ref(o); } -pa_operation* pa_context_set_default_source(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; @@ -850,7 +850,7 @@ int pa_context_is_local(pa_context *c) { return c->local; } -pa_operation* pa_context_set_name(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; diff --git a/src/polyp/context.h b/src/polyp/context.h index 4efd51564..1c06c4342 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -53,6 +53,12 @@ PA_C_DECL_BEGIN * An opaque connection context to a daemon */ typedef struct pa_context pa_context; +/** Generic notification callback prototype */ +typedef void (*pa_context_notify_cb_t)(pa_context *c, void *userdata); + +/** A generic callback for operation completion */ +typedef void (*pa_context_success_cb_t) (pa_context *c, int success, void *userdata); + /** Instantiate a new connection context with an abstract mainloop API * and an application name */ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name); @@ -63,10 +69,8 @@ void pa_context_unref(pa_context *c); /** Increase the reference counter of the context by one */ pa_context* pa_context_ref(pa_context *c); -typedef void (*pa_context_state_callback)(pa_context *c, void *userdata); - /** Set a callback function that is called whenever the context status changes */ -void pa_context_set_state_callback(pa_context *c, pa_context_state_callback callback, void *userdata); +void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata); /** Return the error number of the last failed operation */ int pa_context_errno(pa_context *c); @@ -90,7 +94,7 @@ int pa_context_connect(pa_context *c, const char *server, int spawn, const pa_sp void pa_context_disconnect(pa_context *c); /** Drain the context. If there is nothing to drain, the function returns NULL */ -pa_operation* pa_context_drain(pa_context *c, void (*cb) (pa_context*c, void *userdata), void *userdata); +pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata); /** Tell the daemon to exit. No operation object is returned as the * connection is terminated when the daemon quits, thus this operation @@ -98,16 +102,16 @@ pa_operation* pa_context_drain(pa_context *c, void (*cb) (pa_context*c, void *us void pa_context_exit_daemon(pa_context *c); /** Set the name of the default sink. \since 0.4 */ -pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata); /** Set the name of the default source. \since 0.4 */ -pa_operation* pa_context_set_default_source(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata); /** Returns 1 when the connection is to a local daemon. Returns negative when no connection has been made yet. \since 0.5 */ int pa_context_is_local(pa_context *c); /** Set a different application name for context on the server. \since 0.5 */ -pa_operation* pa_context_set_name(pa_context *c, const char *name, void(*cb)(pa_context*c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata); /** Return the server name this context is connected to. \since 0.7 */ const char* pa_context_get_server(pa_context *c); diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 578969ee4..f0374b67c 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -59,8 +59,8 @@ struct pa_context { uint32_t csyncid; uint32_t error; pa_context_state_t state; - - void (*state_callback)(pa_context*c, void *userdata); + + pa_context_notify_cb_t state_callback; void *state_userdata; void (*subscribe_callback)(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata); diff --git a/src/polypcore/pdispatch.c b/src/polypcore/pdispatch.c index 7941e4a82..fbb1b6974 100644 --- a/src/polypcore/pdispatch.c +++ b/src/polypcore/pdispatch.c @@ -94,7 +94,7 @@ static const char *command_names[PA_COMMAND_MAX] = { struct reply_info { pa_pdispatch *pdispatch; PA_LLIST_FIELDS(struct reply_info); - pa_pdispatch_callback callback; + pa_pdispatch_callback_t callback; void *userdata; uint32_t tag; pa_time_event *time_event; @@ -103,7 +103,7 @@ struct reply_info { struct pa_pdispatch { int ref; pa_mainloop_api *mainloop; - const pa_pdispatch_callback *callback_table; + const pa_pdispatch_callback_t *callback_table; unsigned n_commands; PA_LLIST_HEAD(struct reply_info, replies); pa_pdispatch_drain_callback drain_callback; @@ -121,7 +121,7 @@ static void reply_info_free(struct reply_info *r) { pa_xfree(r); } -pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_callback*table, unsigned entries) { +pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_callback_t*table, unsigned entries) { pa_pdispatch *pd; assert(mainloop); @@ -149,7 +149,7 @@ static void pdispatch_free(pa_pdispatch *pd) { } static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command, pa_tagstruct *ts) { - pa_pdispatch_callback callback; + pa_pdispatch_callback_t callback; void *userdata; uint32_t tag; assert(r); @@ -210,7 +210,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, void *userdata) { run_action(pd, r, command, ts); } else if (pd->callback_table && (command < pd->n_commands) && pd->callback_table[command]) { - const pa_pdispatch_callback *c = pd->callback_table+command; + const pa_pdispatch_callback_t *c = pd->callback_table+command; (*c)(pd, command, tag, ts, userdata); } else { @@ -236,7 +236,7 @@ static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, PA_GCC_UNUSED c run_action(r->pdispatch, r, PA_COMMAND_TIMEOUT, NULL); } -void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_callback cb, void *userdata) { +void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_callback_t cb, void *userdata) { struct reply_info *r; struct timeval tv; assert(pd && pd->ref >= 1 && cb); diff --git a/src/polypcore/pdispatch.h b/src/polypcore/pdispatch.h index 57666259c..27d2d61f9 100644 --- a/src/polypcore/pdispatch.h +++ b/src/polypcore/pdispatch.h @@ -29,15 +29,15 @@ typedef struct pa_pdispatch pa_pdispatch; -typedef void (*pa_pdispatch_callback)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +typedef void (*pa_pdispatch_callback_t)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_callback*table, unsigned entries); +pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_callback_t*table, unsigned entries); void pa_pdispatch_unref(pa_pdispatch *pd); pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, void *userdata); -void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_callback callback, void *userdata); +void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_callback_t callback, void *userdata); int pa_pdispatch_is_pending(pa_pdispatch *pd); diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index aaa4fc48a..21800e6c5 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -174,7 +174,7 @@ static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, u static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = { +static const pa_pdispatch_callback_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = NULL, [PA_COMMAND_TIMEOUT] = NULL, [PA_COMMAND_REPLY] = NULL, From e078f084e44de3c4a87bb4fd7a0be9dbda64b604 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 16:09:25 +0000 Subject: [PATCH 0429/1514] explcitily cast strings to make gcc shut up git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@522 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/memblockq-test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c index b01084da1..e9764627c 100644 --- a/src/tests/memblockq-test.c +++ b/src/tests/memblockq-test.c @@ -38,28 +38,28 @@ int main(int argc, char *argv[]) { pa_log_set_maximal_level(PA_LOG_DEBUG); - silence = pa_memblock_new_fixed("__", 2, 1, NULL); + silence = pa_memblock_new_fixed((char*) "__", 2, 1, NULL); assert(silence); bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, silence, NULL); assert(bq); - chunk1.memblock = pa_memblock_new_fixed("AA", 2, 1, NULL); + chunk1.memblock = pa_memblock_new_fixed((char*) "AA", 2, 1, NULL); chunk1.index = 0; chunk1.length = 2; assert(chunk1.memblock); - chunk2.memblock = pa_memblock_new_fixed("TTBB", 4, 1, NULL); + chunk2.memblock = pa_memblock_new_fixed((char*) "TTBB", 4, 1, NULL); chunk2.index = 2; chunk2.length = 2; assert(chunk2.memblock); - chunk3.memblock = pa_memblock_new_fixed("ZZZZ", 4, 1, NULL); + chunk3.memblock = pa_memblock_new_fixed((char*) "ZZZZ", 4, 1, NULL); chunk3.index = 0; chunk3.length = 4; assert(chunk3.memblock); - chunk4.memblock = pa_memblock_new_fixed("KKKKKKKK", 8, 1, NULL); + chunk4.memblock = pa_memblock_new_fixed((char*) "KKKKKKKK", 8, 1, NULL); chunk4.index = 0; chunk4.length = 8; assert(chunk4.memblock); From 6d0960246036564a6a8bf36b0839158cacc6a81a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 16:10:20 +0000 Subject: [PATCH 0430/1514] replace "spawn" parameter of pa_context_new() with a proper flags parameter git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@523 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 4 ++-- src/polyp/context.h | 10 +++++----- src/polyp/def.h | 5 +++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/polyp/context.c b/src/polyp/context.c index e2d9d33d2..b174b505c 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -593,7 +593,7 @@ finish: pa_context_unref(c); } -int pa_context_connect(pa_context *c, const char *server, int spawn, const pa_spawn_api *api) { +int pa_context_connect(pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api) { int r = -1; assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED); @@ -632,7 +632,7 @@ int pa_context_connect(pa_context *c, const char *server, int spawn, const pa_sp c->server_list = pa_strlist_prepend(c->server_list, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET, ufn, sizeof(ufn))); /* Wrap the connection attempts in a single transaction for sane autospawn locking */ - if (spawn && c->conf->autospawn) { + if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) { char lf[PATH_MAX]; pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); diff --git a/src/polyp/context.h b/src/polyp/context.h index 1c06c4342..a299400ae 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -84,11 +84,11 @@ pa_context_state_t pa_context_get_state(pa_context *c); /** Connect the context to the specified server. If server is NULL, connect to the default server. This routine may but will not always return synchronously on error. Use pa_context_set_state_callback() to -be notified when the connection is established. If spawn is non-zero -and no specific server is specified or accessible a new daemon is -spawned. If api is non-NULL, the functions specified in the structure -are used when forking a new child process. */ -int pa_context_connect(pa_context *c, const char *server, int spawn, const pa_spawn_api *api); +be notified when the connection is established. If flags doesn't have +PA_NOAUTOSPAWN set and no specific server is specified or accessible a +new daemon is spawned. If api is non-NULL, the functions specified in +the structure are used when forking a new child process. */ +int pa_context_connect(pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api); /** Terminate the context connection immediately */ void pa_context_disconnect(pa_context *c); diff --git a/src/polyp/def.h b/src/polyp/def.h index f8e0bed42..e94da2530 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -64,6 +64,11 @@ typedef enum pa_operation_state { /** An invalid index */ #define PA_INVALID_INDEX ((uint32_t) -1) +/** Some special flags for contexts. \ since 0.8 */ +typedef enum pa_context_flags { + PA_CONTEXT_NOAUTOSPAWN = 1 /**< Disabled autospawning of the polypaudio daemon if required */ +} pa_context_flags_t; + /** The direction of a pa_stream object */ typedef enum pa_stream_direction { PA_STREAM_NODIRECTION, /**< Invalid direction */ From 502d3f551bb8a168b6686b6d0c833a5f6e40c98c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 20 Feb 2006 16:13:10 +0000 Subject: [PATCH 0431/1514] Hardware volume support for Solaris. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@524 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index e0745fc0d..7356cb7b6 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -258,6 +258,40 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { return r; } +static int sink_get_hw_volume_cb(pa_sink *s) { + struct userdata *u = s->userdata; + audio_info_t info; + int err; + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, + info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); + + return 0; +} + +static int sink_set_hw_volume_cb(pa_sink *s) { + struct userdata *u = s->userdata; + audio_info_t info; + + AUDIO_INITINFO(&info); + + info.play.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; + assert(info.play.gain <= AUDIO_MAX_GAIN); + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume.\n"); + else + pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { audio_info_t info; @@ -411,6 +445,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; + u->sink->get_hw_volume = sink_get_hw_volume_cb; + u->sink->set_hw_volume = sink_set_hw_volume_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); From 5d253cd30cd73dc8d159f198e2b63edbe1f971ab Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 20 Feb 2006 16:21:19 +0000 Subject: [PATCH 0432/1514] Fix some warnings by making sure we have the right signedness on things. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@525 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 5adff57af..4a5dd7733 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -560,15 +560,15 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v response += ESD_NAME_MAX; /* rate */ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, ce->sample_spec.rate); + *((uint32_t*) response) = MAYBE_UINT32_SWAP(c->swap_byte_order, ce->sample_spec.rate); response += sizeof(int); /* left */ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + *((uint32_t*) response) = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); response += sizeof(int); /*right*/ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + *((uint32_t*) response) = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); response += sizeof(int); /*format*/ @@ -596,10 +596,10 @@ static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t struct connection *conn; assert(c && data && length == sizeof(int)*3); - idx = MAYBE_UINT32_SWAP(c->swap_byte_order, *(const int*)data)-1; - lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, *((const int*)data + 1)); + idx = MAYBE_UINT32_SWAP(c->swap_byte_order, *(const uint32_t*)data)-1; + lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, *((const uint32_t*)data + 1)); lvolume = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; - rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, *((const int*)data + 2)); + rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, *((const uint32_t*)data + 2)); rvolume = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; ok = connection_write(c, sizeof(int)); From 3bc09025edc8d1b7a86b3ca5d08b1c0146950707 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 16:23:12 +0000 Subject: [PATCH 0433/1514] minor doxygen fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@526 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.h | 3 +-- src/polyp/def.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/polyp/context.h b/src/polyp/context.h index a299400ae..db268759f 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -49,8 +49,7 @@ PA_C_DECL_BEGIN -/** \struct pa_context - * An opaque connection context to a daemon */ +/** An opaque connection context to a daemon */ typedef struct pa_context pa_context; /** Generic notification callback prototype */ diff --git a/src/polyp/def.h b/src/polyp/def.h index e94da2530..2ce1bd0c2 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -64,7 +64,7 @@ typedef enum pa_operation_state { /** An invalid index */ #define PA_INVALID_INDEX ((uint32_t) -1) -/** Some special flags for contexts. \ since 0.8 */ +/** Some special flags for contexts. \since 0.8 */ typedef enum pa_context_flags { PA_CONTEXT_NOAUTOSPAWN = 1 /**< Disabled autospawning of the polypaudio daemon if required */ } pa_context_flags_t; From 7905e819ab6a6cc90e28c1e31f2ed957a1d00489 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 20 Feb 2006 16:24:02 +0000 Subject: [PATCH 0434/1514] Add aligment fix in esound to todo. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@527 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 45989b451..744820c46 100644 --- a/doc/todo +++ b/doc/todo @@ -11,6 +11,7 @@ Fixes: - better validity checking in libpolyp and protocol-{native,esound} - don't build ipv4 and ipv6 modules seperately - change pa_log to not require \n +- proper use of memcpy in procotol-esound.c so we don't get alignment problems Features: - add radio module From ddd51e2c6cba3fa1ba56193976a63306a10f7645 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 16:31:39 +0000 Subject: [PATCH 0435/1514] add doxygen docs for channel map git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@528 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.h | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index 7c48b76bb..ae1d11c87 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -30,7 +30,8 @@ PA_C_DECL_BEGIN -typedef enum { +/** A list of channel labels */ +typedef enum pa_channel_position { PA_CHANNEL_POSITION_INVALID = -1, PA_CHANNEL_POSITION_MONO = 0, @@ -75,23 +76,39 @@ typedef enum { PA_CHANNEL_POSITION_MAX } pa_channel_position_t; +/** A channel map which can be used to attach labels to specific + * channels of a stream. These values are relevant for conversion and + * mixing of streams */ typedef struct pa_channel_map { - uint8_t channels; - pa_channel_position_t map[PA_CHANNELS_MAX]; + uint8_t channels; /**< Number of channels */ + pa_channel_position_t map[PA_CHANNELS_MAX]; /**< Channel labels */ } pa_channel_map; +/** Initialize the specified channel map and return a pointer to it */ pa_channel_map* pa_channel_map_init(pa_channel_map *m); + +/** Initialize the specified channel map for monoaural audio and return a pointer to it */ pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m); + +/** Initialize the specified channel map for stereophonic audio and return a pointer to it */ pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m); + +/** Initialize the specified channel map for the specified number of channels using default labels and return a pointer to it */ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels); +/** Return a text label for the specified channel position */ const char* pa_channel_position_to_string(pa_channel_position_t pos); +/** The maximum length of strings returned by pa_channel_map_snprint() */ #define PA_CHANNEL_MAP_SNPRINT_MAX 64 + +/** Make a humand readable string from the specified channel map */ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map); +/** Compare two channel maps. Return 0 if both match. */ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b); +/** Return non-zero of the specified channel map is considered valid */ int pa_channel_map_valid(const pa_channel_map *map); PA_C_DECL_END From 71e063a69533fedc283c55eed735332e5b00713e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 16:34:46 +0000 Subject: [PATCH 0436/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@529 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 744820c46..280747fe0 100644 --- a/doc/todo +++ b/doc/todo @@ -26,6 +26,7 @@ Features: - source volume control - deal with underflows reported by OSS/ALSA properly - mute switch support (like ALSA does it) +- get rid of a seperate main loop lib Long term: - pass meta info for hearing impaired From 98cb6aa4a30a993ddf2c15f0a03cb4d94383d4d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 17:09:39 +0000 Subject: [PATCH 0437/1514] * a lot of doxygen updates * s/pa_operation_callback/pa_operation_callback_t/g * add more typedefs for function prototypes * add API to query the channel map used by a pa_stream git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@530 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.h | 2 +- src/polyp/context.c | 8 ++--- src/polyp/glib-mainloop.h | 8 ++--- src/polyp/internal.h | 7 +++-- src/polyp/introspect.c | 60 ++++++++++++++++++------------------- src/polyp/mainloop-api.h | 10 +++---- src/polyp/mainloop-signal.h | 3 +- src/polyp/mainloop.h | 6 ++-- src/polyp/operation.h | 3 +- src/polyp/polypaudio.h | 13 ++++---- src/polyp/sample.h | 8 ++--- src/polyp/scache.c | 8 ++--- src/polyp/scache.h | 13 ++++++-- src/polyp/stream.c | 17 +++++++---- src/polyp/stream.h | 24 ++++++++------- src/polyp/subscribe.c | 6 ++-- src/polyp/subscribe.h | 7 +++-- src/polyp/volume.h | 22 +++++++++----- 18 files changed, 125 insertions(+), 100 deletions(-) diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index ae1d11c87..dd508abe1 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -105,7 +105,7 @@ const char* pa_channel_position_to_string(pa_channel_position_t pos); /** Make a humand readable string from the specified channel map */ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map); -/** Compare two channel maps. Return 0 if both match. */ +/** Compare two channel maps. Return 1 if both match. */ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b); /** Return non-zero of the specified channel map is considered valid */ diff --git a/src/polyp/context.c b/src/polyp/context.c index b174b505c..00c097107 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -742,7 +742,7 @@ pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *u o = pa_operation_new(c, NULL); assert(o); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; set_dispatch_callbacks(pa_operation_ref(o)); @@ -812,7 +812,7 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_co assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -832,7 +832,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -857,7 +857,7 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su assert(c && name && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); diff --git a/src/polyp/glib-mainloop.h b/src/polyp/glib-mainloop.h index e052cff3b..b7717685a 100644 --- a/src/polyp/glib-mainloop.h +++ b/src/polyp/glib-mainloop.h @@ -32,18 +32,18 @@ PA_C_DECL_BEGIN -/** \struct pa_glib_mainloop - * An opaque GLIB main loop object */ +/** An opaque GLIB main loop object */ typedef struct pa_glib_mainloop pa_glib_mainloop; -/** Create a new GLIB main loop object for the specified GLIB main loop context. If c is NULL the default context is used. */ +/** Create a new GLIB main loop object for the specified GLIB main + * loop context. The GLIB 2.0 version takes an argument c for the + * GMainContext to use. If c is NULL the default context is used. */ #if GLIB_MAJOR_VERSION >= 2 pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c); #else pa_glib_mainloop *pa_glib_mainloop_new(void); #endif - /** Free the GLIB main loop object */ void pa_glib_mainloop_free(pa_glib_mainloop* g); diff --git a/src/polyp/internal.h b/src/polyp/internal.h index f0374b67c..e9e0246ff 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -63,7 +64,7 @@ struct pa_context { pa_context_notify_cb_t state_callback; void *state_userdata; - void (*subscribe_callback)(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata); + pa_context_subscribe_cb_t subscribe_callback; void *subscribe_userdata; pa_memblock_stat *memblock_stat; @@ -127,7 +128,7 @@ struct pa_stream { void *underflow_userdata; }; -typedef void (*pa_operation_callback)(void); +typedef void (*pa_operation_callback_t)(void); struct pa_operation { int ref; @@ -137,7 +138,7 @@ struct pa_operation { pa_operation_state_t state; void *userdata; - pa_operation_callback callback; + pa_operation_callback_t callback; }; void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); diff --git a/src/polyp/introspect.c b/src/polyp/introspect.c index 75ce3ff99..404cead5e 100644 --- a/src/polyp/introspect.c +++ b/src/polyp/introspect.c @@ -67,7 +67,7 @@ finish: } pa_operation* pa_context_stat(pa_context *c, void (*cb)(pa_context *c, const pa_stat_info*i, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, (pa_operation_callback) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, (pa_operation_callback_t) cb, userdata); } /*** Server Info ***/ @@ -107,7 +107,7 @@ finish: } pa_operation* pa_context_get_server_info(pa_context *c, void (*cb)(pa_context *c, const pa_server_info*i, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, (pa_operation_callback) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, (pa_operation_callback_t) cb, userdata); } /*** Sink Info ***/ @@ -161,7 +161,7 @@ finish: } pa_operation* pa_context_get_sink_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, (pa_operation_callback) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, (pa_operation_callback_t) cb, userdata); } pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata) { @@ -171,7 +171,7 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, voi assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -192,7 +192,7 @@ pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -256,7 +256,7 @@ finish: } pa_operation* pa_context_get_source_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, (pa_operation_callback) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, (pa_operation_callback_t) cb, userdata); } pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata) { @@ -266,7 +266,7 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, v assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -287,7 +287,7 @@ pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -350,7 +350,7 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, void (*cb) assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -364,7 +364,7 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, void (*cb) } pa_operation* pa_context_get_client_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_client_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, (pa_operation_callback) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, (pa_operation_callback_t) cb, userdata); } /*** Module info ***/ @@ -417,7 +417,7 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, void (*cb) assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -431,7 +431,7 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, void (*cb) } pa_operation* pa_context_get_module_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_module_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, (pa_operation_callback) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, (pa_operation_callback_t) cb, userdata); } /*** Sink input info ***/ @@ -492,7 +492,7 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, void ( assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -506,7 +506,7 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, void ( } pa_operation* pa_context_get_sink_input_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, (pa_operation_callback) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, (pa_operation_callback_t) cb, userdata); } /*** Source output info ***/ @@ -566,7 +566,7 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, voi assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -580,7 +580,7 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, voi } pa_operation* pa_context_get_source_output_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_output_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, (pa_operation_callback) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, (pa_operation_callback_t) cb, userdata); } /*** Volume manipulation ***/ @@ -592,7 +592,7 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, c assert(c && idx != PA_INVALID_INDEX); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -614,7 +614,7 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name assert(c && name); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -636,7 +636,7 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons assert(c && idx != PA_INVALID_INDEX); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -705,7 +705,7 @@ pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name assert(c && cb && name); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -726,7 +726,7 @@ pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, v assert(c && cb); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -741,7 +741,7 @@ pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, v } pa_operation* pa_context_get_sample_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, (pa_operation_callback) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, (pa_operation_callback_t) cb, userdata); } static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { @@ -751,7 +751,7 @@ static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, assert(c && idx != PA_INVALID_INDEX); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -808,7 +808,7 @@ pa_operation* pa_context_load_module(pa_context *c, const char*name, const char assert(c && name && argument); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -876,7 +876,7 @@ pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *na assert(c && cb && name); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -897,7 +897,7 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, assert(c && cb && idx != PA_INVALID_INDEX); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -911,7 +911,7 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, } pa_operation* pa_context_get_autoload_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, (pa_operation_callback) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, (pa_operation_callback_t) cb, userdata); } static void context_add_autoload_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -948,7 +948,7 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo assert(c && name && module && argument); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -971,7 +971,7 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name assert(c && name); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -992,7 +992,7 @@ pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, v assert(c && idx != PA_INVALID_INDEX); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); diff --git a/src/polyp/mainloop-api.h b/src/polyp/mainloop-api.h index 7bc7522ce..12d74aa16 100644 --- a/src/polyp/mainloop-api.h +++ b/src/polyp/mainloop-api.h @@ -53,21 +53,19 @@ typedef enum pa_io_event_flags { PA_IO_EVENT_ERROR = 8 /**< Error event */ } pa_io_event_flags_t; -/** \struct pa_io_event - * An opaque IO event source object */ +/** An opaque IO event source object */ typedef struct pa_io_event pa_io_event; -/** \struct pa_defer_event - * An opaque deferred event source object. Events of this type are triggered once in every main loop iteration */ +/** An opaque deferred event source object. Events of this type are triggered once in every main loop iteration */ typedef struct pa_defer_event pa_defer_event; -/** \struct pa_time_event - * An opaque timer event source object */ +/** An opaque timer event source object */ typedef struct pa_time_event pa_time_event; /** An abstract mainloop API vtable */ typedef struct pa_mainloop_api pa_mainloop_api; +/** An abstract mainloop API vtable */ struct pa_mainloop_api { /** A pointer to some private, arbitrary data of the main loop implementation */ void *userdata; diff --git a/src/polyp/mainloop-signal.h b/src/polyp/mainloop-signal.h index 0291f4261..20e97988f 100644 --- a/src/polyp/mainloop-signal.h +++ b/src/polyp/mainloop-signal.h @@ -42,8 +42,7 @@ int pa_signal_init(pa_mainloop_api *api); /** Cleanup the signal subsystem */ void pa_signal_done(void); -/** \struct pa_signal_event - * An opaque UNIX signal event source object */ +/** An opaque UNIX signal event source object */ typedef struct pa_signal_event pa_signal_event; /** Create a new UNIX signal event source object */ diff --git a/src/polyp/mainloop.h b/src/polyp/mainloop.h index eeb238843..d0a409148 100644 --- a/src/polyp/mainloop.h +++ b/src/polyp/mainloop.h @@ -35,9 +35,7 @@ PA_C_DECL_BEGIN * defined in \ref mainloop-api.h. This implementation is thread safe * as long as you access the main loop object from a single thread only.*/ -/** \struct pa_mainloop - * An opaque main loop object - */ +/** An opaque main loop object */ typedef struct pa_mainloop pa_mainloop; /** Allocate a new main loop object */ @@ -52,8 +50,10 @@ poll, or -1 for blocking behaviour. Defer events are also dispatched when this function is called. On success returns the number of source dispatched in this iteration.*/ int pa_mainloop_prepare(pa_mainloop *m, int timeout); + /** Execute the previously prepared poll. Returns a negative value on error.*/ int pa_mainloop_poll(pa_mainloop *m); + /** Dispatch timeout and io events from the previously executed poll. Returns a negative value on error. On success returns the number of source dispatched. */ int pa_mainloop_dispatch(pa_mainloop *m); diff --git a/src/polyp/operation.h b/src/polyp/operation.h index d286b0c13..2fbac2e27 100644 --- a/src/polyp/operation.h +++ b/src/polyp/operation.h @@ -30,8 +30,7 @@ PA_C_DECL_BEGIN -/** \struct pa_operation - * An asynchronous operation object */ +/** An asynchronous operation object */ typedef struct pa_operation pa_operation; /** Increase the reference count by one */ diff --git a/src/polyp/polypaudio.h b/src/polyp/polypaudio.h index c81fdfdb0..b70b8d703 100644 --- a/src/polyp/polypaudio.h +++ b/src/polyp/polypaudio.h @@ -22,7 +22,6 @@ USA. ***/ -#include #include #include #include @@ -33,12 +32,16 @@ #include #include #include +#include +#include +#include /** \file - * Include all polyplib header file at once. The following files are included: \ref mainloop-api.h, \ref sample.h, - * \ref def.h, \ref context.h, \ref stream.h, - * \ref introspect.h, \ref subscribe.h, \ref scache.h, \ref version.h \ref error.h - * at once */ + * Include all polyplib header file at once. The following + * files are included: \ref mainloop-api.h, \ref sample.h, \ref def.h, + * \ref context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h, + * \ref scache.h, \ref version.h, \ref error.h, \ref channelmap.h, + * \ref operation.h and \ref volume.h at once */ /** \mainpage * diff --git a/src/polyp/sample.h b/src/polyp/sample.h index c1b98f1cf..db4c6c704 100644 --- a/src/polyp/sample.h +++ b/src/polyp/sample.h @@ -33,7 +33,7 @@ PA_C_DECL_BEGIN -/* Maximum allowed channels */ +/** Maximum allowed channels */ #define PA_CHANNELS_MAX 16 /** Sample format */ @@ -43,8 +43,8 @@ typedef enum pa_sample_format { PA_SAMPLE_ULAW, /**< 8 Bit mu-Law */ PA_SAMPLE_S16LE, /**< Signed 16 Bit PCM, little endian (PC) */ PA_SAMPLE_S16BE, /**< Signed 16 Bit PCM, big endian */ - PA_SAMPLE_FLOAT32LE, /**< 32 Bit IEEE floating point, little endian, range -1..1 */ - PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1..1 */ + PA_SAMPLE_FLOAT32LE, /**< 32 Bit IEEE floating point, little endian, range -1 to 1 */ + PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1 to 1 */ PA_SAMPLE_MAX, /**< Upper limit of valid sample types */ PA_SAMPLE_INVALID = -1 /**< An invalid value */ } pa_sample_format_t; @@ -100,7 +100,7 @@ int pa_sample_spec_valid(const pa_sample_spec *spec); /** Return non-zero when the two sample type specifications match */ int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b); -/* Return a descriptive string for the specified sample format. \since 0.8 */ +/** Return a descriptive string for the specified sample format. \since 0.8 */ const char *pa_sample_format_to_string(pa_sample_format_t f); /** Parse a sample format text. Inverse of pa_sample_format_to_string() */ diff --git a/src/polyp/scache.c b/src/polyp/scache.c index 393b069e6..f6a3a7e64 100644 --- a/src/polyp/scache.c +++ b/src/polyp/scache.c @@ -79,14 +79,14 @@ void pa_stream_finish_upload(pa_stream *s) { pa_stream_unref(s); } -pa_operation * pa_context_play_sample(pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation * pa_context_play_sample(pa_context *c, const char *name, const char *dev, uint32_t volume, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; assert(c && name && *name && (!dev || *dev)); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; if (!dev) @@ -106,14 +106,14 @@ pa_operation * pa_context_play_sample(pa_context *c, const char *name, const cha return pa_operation_ref(o); } -pa_operation* pa_context_remove_sample(pa_context *c, const char *name, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; assert(c && name); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); diff --git a/src/polyp/scache.h b/src/polyp/scache.h index 5bf004d0a..3480d8766 100644 --- a/src/polyp/scache.h +++ b/src/polyp/scache.h @@ -36,14 +36,21 @@ PA_C_DECL_BEGIN /** Make this stream a sample upload stream */ void pa_stream_connect_upload(pa_stream *s, size_t length); -/** Finish the sample upload, the stream name will become the sample name. You cancel a sample upload by issuing pa_stream_disconnect() */ +/** Finish the sample upload, the stream name will become the sample name. You cancel a samp + * le upload by issuing pa_stream_disconnect() */ void pa_stream_finish_upload(pa_stream *s); /** Play a sample from the sample cache to the specified device. If the latter is NULL use the default sink. Returns an operation object */ -pa_operation* pa_context_play_sample(pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_play_sample( + pa_context *c /**< Context */, + const char *name /**< Name of the sample to play */, + const char *dev /**< Sink to play this sample on */, + pa_volume_t volume /**< Volume to play this sample with */ , + pa_context_success_cb_t cb /**< Call this function after successfully starting playback, or NULL */, + void *userdata /**< Userdata to pass to the callback */); /** Remove a sample from the sample cache. Returns an operation object which may be used to cancel the operation while it is running */ -pa_operation* pa_context_remove_sample(pa_context *c, const char *name, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t, void *userdata); PA_C_DECL_END diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 5497f0c42..88971085b 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -592,7 +592,7 @@ pa_operation * pa_stream_drain(pa_stream *s, void (*cb) (pa_stream*s, int succes PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); o = pa_operation_new(s->context, s); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -680,7 +680,7 @@ pa_operation* pa_stream_get_latency_info(pa_stream *s, void (*cb)(pa_stream *p, PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); o = pa_operation_new(s->context, s); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -830,7 +830,7 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, void (*cb) (pa_stream*s, int s o = pa_operation_new(s->context, s); assert(o); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -854,7 +854,7 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); o = pa_operation_new(s->context, s); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -896,7 +896,7 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, void(*cb)(pa_st o = pa_operation_new(s->context, s); assert(o); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -978,9 +978,16 @@ pa_usec_t pa_stream_get_latency(pa_stream *s, const pa_latency_info *i, int *neg const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s) { assert(s); + return &s->sample_spec; } +const pa_channel_map* pa_stream_get_channel_map(pa_stream *s) { + assert(s); + + return &s->channel_map; +} + void pa_stream_trash_ipol(pa_stream *s) { assert(s); diff --git a/src/polyp/stream.h b/src/polyp/stream.h index ce5359637..75b0a9001 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -36,8 +36,7 @@ PA_C_DECL_BEGIN -/** \struct pa_stream - * An opaque stream for playback or recording */ +/** An opaque stream for playback or recording */ typedef struct pa_stream pa_stream; /** A generic callback for operation completion */ @@ -57,10 +56,10 @@ typedef void (*pa_stream_get_latency_info_cb_t)(pa_stream *p, const pa_latency_i /** Create a new, unconnected stream with the specified name and sample type */ pa_stream* pa_stream_new( - pa_context *c, - const char *name, - const pa_sample_spec *ss, - const pa_channel_map *map); + pa_context *c /**< The context to create this stream in */, + const char *name /**< A name for this stream */, + const pa_sample_spec *ss /**< The desired sample format */, + const pa_channel_map *map /**< The desired channel map, or NULL for default */); /** Decrease the reference counter by one */ void pa_stream_unref(pa_stream *s); @@ -88,10 +87,10 @@ int pa_stream_connect_playback( /** Connect the stream to a source */ int pa_stream_connect_record( - pa_stream *s, - const char *dev, - const pa_buffer_attr *attr, - pa_stream_flags_t flags); + pa_stream *s /**< The stream to connect to a source */ , + const char *dev /**< Name of the source to connect to, or NULL for default */, + const pa_buffer_attr *attr /**< Buffer attributes, or NULL for default */, + pa_stream_flags_t flags /**< Additional flags, or 0 for default */); /** Disconnect a stream from a source/sink */ int pa_stream_disconnect(pa_stream *s); @@ -203,9 +202,12 @@ pa_usec_t pa_stream_get_interpolated_time(pa_stream *s); * stream. \since 0.6 */ pa_usec_t pa_stream_get_interpolated_latency(pa_stream *s, int *negative); -/** Return a pointer to the streams sample specification. \since 0.6 */ +/** Return a pointer to the stream's sample specification. \since 0.6 */ const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s); +/** Return a pointer to the stream's channel map. \since 0.8 */ +const pa_channel_map* pa_stream_get_channel_map(pa_stream *s); + PA_C_DECL_END #endif diff --git a/src/polyp/subscribe.c b/src/polyp/subscribe.c index 4e00997ab..97f76cb79 100644 --- a/src/polyp/subscribe.c +++ b/src/polyp/subscribe.c @@ -56,14 +56,14 @@ finish: } -pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; assert(c); o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback) cb; + o->callback = (pa_operation_callback_t) cb; o->userdata = userdata; t = pa_tagstruct_new(NULL, 0); @@ -76,7 +76,7 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, void return pa_operation_ref(o); } -void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata) { +void pa_context_set_subscribe_callback(pa_context *c, pa_context_subscribe_cb_t cb, void *userdata) { assert(c); c->subscribe_callback = cb; c->subscribe_userdata = userdata; diff --git a/src/polyp/subscribe.h b/src/polyp/subscribe.h index f1f0642d9..5301739a4 100644 --- a/src/polyp/subscribe.h +++ b/src/polyp/subscribe.h @@ -36,11 +36,14 @@ PA_C_DECL_BEGIN +/** Subscription event callback prototype */ +typedef void (*pa_context_subscribe_cb_t)(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata); + /** Enable event notification */ -pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata); /** Set the context specific call back function that is called whenever the state of the daemon changes */ -void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata); +void pa_context_set_subscribe_callback(pa_context *c, pa_context_subscribe_cb_t cb, void *userdata); PA_C_DECL_END diff --git a/src/polyp/volume.h b/src/polyp/volume.h index b2a480848..d1e858c43 100644 --- a/src/polyp/volume.h +++ b/src/polyp/volume.h @@ -46,8 +46,8 @@ typedef uint32_t pa_volume_t; /** A structure encapsulating a per-channel volume */ typedef struct pa_cvolume { - uint8_t channels; - pa_volume_t values[PA_CHANNELS_MAX]; + uint8_t channels; /**< Number of channels */ + pa_volume_t values[PA_CHANNELS_MAX]; /**< Per-channel volume */ } pa_cvolume; /** Return non-zero when *a == *b */ @@ -62,8 +62,10 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b); /** Set the volume of all channels to the specified parameter */ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v); -/** Pretty print a volume structure */ +/** Maximum length of the strings returned by pa_cvolume_snprint() */ #define PA_CVOLUME_SNPRINT_MAX 64 + +/** Pretty print a volume structure */ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c); /** Return the average volume of all channels */ @@ -75,24 +77,28 @@ int pa_cvolume_valid(const pa_cvolume *v); /** Return non-zero if the volume of all channels is equal to the specified value */ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v); +/** Return 1 if the specified volume has all channels muted */ #define pa_cvolume_is_muted(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_MUTED) + +/** Return 1 if the specified volume has all channels on normal level */ #define pa_cvolume_is_norm(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_NORM) -/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */ +/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. This is only valid for software volumes! */ pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b); +/** Multiply to per-channel volumes and return the result in *dest. This is only valid for software volumes! */ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b); -/** Convert a decibel value to a volume. \since 0.4 */ +/** Convert a decibel value to a volume. This is only valid for software volumes! \since 0.4 */ pa_volume_t pa_sw_volume_from_dB(double f); -/** Convert a volume to a decibel value. \since 0.4 */ +/** Convert a volume to a decibel value. This is only valid for software volumes! \since 0.4 */ double pa_sw_volume_to_dB(pa_volume_t v); -/** Convert a linear factor to a volume. \since 0.8 */ +/** Convert a linear factor to a volume. This is only valid for software volumes! \since 0.8 */ pa_volume_t pa_sw_volume_from_linear(double v); -/** Convert a volume to a linear factor. \since 0.8 */ +/** Convert a volume to a linear factor. This is only valid for software volumes! \since 0.8 */ double pa_sw_volume_to_linear(pa_volume_t v); #ifdef INFINITY From 71b3bff6816b857a6a9613cc45b06f0b9e5a65e1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 22:41:02 +0000 Subject: [PATCH 0438/1514] * modify pa_context_exit_daemon() to return a pa_operation object * add callback prototypes to all introspection functions in client lib * add proper validity checking and error handling to all functions in the client lib * other minor cleanups * todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@531 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + src/Makefile.am | 4 +- src/modules/module-tunnel.c | 2 +- src/polyp/context.c | 228 +++++++----- src/polyp/context.h | 8 +- src/polyp/internal.h | 15 +- src/polyp/introspect.c | 591 +++++++++++++++++++------------- src/polyp/introspect.h | 112 +++--- src/polyp/operation.c | 6 +- src/polyp/scache.c | 57 +-- src/polyp/scache.h | 4 +- src/polyp/stream.c | 217 +++++++----- src/polyp/subscribe.c | 22 +- src/polypcore/iochannel.c | 4 +- src/polypcore/iochannel.h | 4 +- src/polypcore/pdispatch.c | 12 +- src/polypcore/pdispatch.h | 6 +- src/polypcore/protocol-native.c | 2 +- src/polypcore/tagstruct.h | 2 - src/utils/pactl.c | 2 +- 20 files changed, 784 insertions(+), 515 deletions(-) diff --git a/doc/todo b/doc/todo index 280747fe0..1fc55df96 100644 --- a/doc/todo +++ b/doc/todo @@ -12,6 +12,7 @@ Fixes: - don't build ipv4 and ipv6 modules seperately - change pa_log to not require \n - proper use of memcpy in procotol-esound.c so we don't get alignment problems +- sigpipe Features: - add radio module diff --git a/src/Makefile.am b/src/Makefile.am index 5581d77ed..ed97f4905 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,8 +47,8 @@ AM_CFLAGS = -I$(top_srcdir)/src AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" -#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" +#AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" +AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 3ecca7457..136702fc6 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -94,7 +94,7 @@ static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t t static void command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); #endif -static const pa_pdispatch_callback_t command_table[PA_COMMAND_MAX] = { +static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { #ifdef TUNNEL_SINK [PA_COMMAND_REQUEST] = command_request, #endif diff --git a/src/polyp/context.c b/src/polyp/context.c index 00c097107..2cb9e7e38 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -72,7 +72,7 @@ #define AUTOSPAWN_LOCK "autospawn.lock" -static const pa_pdispatch_callback_t command_table[PA_COMMAND_MAX] = { +static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = pa_command_request, [PA_COMMAND_OVERFLOW] = pa_command_overflow_or_underflow, [PA_COMMAND_UNDERFLOW] = pa_command_overflow_or_underflow, @@ -95,9 +95,11 @@ static void unlock_autospawn_lock_file(pa_context *c) { pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { pa_context *c; - assert(mainloop && name); - c = pa_xmalloc(sizeof(pa_context)); + assert(mainloop); + assert(name); + + c = pa_xnew(pa_context, 1); c->ref = 1; c->name = pa_xstrdup(name); c->mainloop = mainloop; @@ -106,7 +108,6 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { c->pdispatch = NULL; c->playback_streams = pa_dynarray_new(); c->record_streams = pa_dynarray_new(); - assert(c->playback_streams && c->record_streams); PA_LLIST_HEAD_INIT(pa_stream, c->streams); PA_LLIST_HEAD_INIT(pa_operation, c->operations); @@ -182,20 +183,24 @@ static void context_free(pa_context *c) { } pa_context* pa_context_ref(pa_context *c) { - assert(c && c->ref >= 1); + assert(c); + assert(c->ref >= 1); + c->ref++; return c; } void pa_context_unref(pa_context *c) { - assert(c && c->ref >= 1); + assert(c); + assert(c->ref >= 1); - if ((--(c->ref)) == 0) + if (--c->ref <= 0) context_free(c); } void pa_context_set_state(pa_context *c, pa_context_state_t st) { assert(c); + assert(c->ref >= 1); if (c->state == st) return; @@ -237,13 +242,15 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { void pa_context_fail(pa_context *c, int error) { assert(c); - + assert(c->ref >= 1); + pa_context_set_error(c, error); pa_context_set_state(c, PA_CONTEXT_FAILED); } int pa_context_set_error(pa_context *c, int error) { - assert(error >= 0 && error < PA_ERR_MAX); + assert(error >= 0); + assert(error < PA_ERR_MAX); if (c) c->error = error; @@ -253,20 +260,24 @@ int pa_context_set_error(pa_context *c, int error) { static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context *c = userdata; - assert(p && c); + + assert(p); + assert(c); + pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *userdata) { pa_context *c = userdata; - assert(p && packet && c); + + assert(p); + assert(packet); + assert(c); pa_context_ref(c); - if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - pa_log(__FILE__": invalid packet.\n"); + if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) pa_context_fail(c, PA_ERR_PROTOCOL); - } pa_context_unref(c); } @@ -280,6 +291,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o assert(chunk->memblock); assert(chunk->length); assert(c); + assert(c->ref >= 1); pa_context_ref(c); @@ -301,6 +313,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { assert(c); + assert(c->ref >= 1); if (command == PA_COMMAND_ERROR) { assert(t); @@ -322,7 +335,10 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; - assert(pd && c && (c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME)); + + assert(pd); + assert(c); + assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME); pa_context_ref(c); @@ -364,13 +380,14 @@ finish: static void setup_context(pa_context *c, pa_iochannel *io) { pa_tagstruct *t; uint32_t tag; - assert(c && io); + + assert(c); + assert(io); pa_context_ref(c); assert(!c->pstream); c->pstream = pa_pstream_new(c->mainloop, io, c->memblock_stat); - assert(c->pstream); pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); @@ -378,7 +395,6 @@ static void setup_context(pa_context *c, pa_iochannel *io) { assert(!c->pdispatch); c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); - assert(c->pdispatch); if (!c->conf->cookie_valid) { pa_context_fail(c, PA_ERR_AUTHKEY); @@ -386,7 +402,6 @@ static void setup_context(pa_context *c, pa_iochannel *io) { } t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_AUTH); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); @@ -522,11 +537,12 @@ fail: static int try_next_connection(pa_context *c) { char *u = NULL; int r = -1; - assert(c && !c->client); + + assert(c); + assert(!c->client); for (;;) { - if (u) - pa_xfree(u); + pa_xfree(u); u = NULL; c->server_list = pa_strlist_pop(c->server_list, &u); @@ -560,15 +576,17 @@ static int try_next_connection(pa_context *c) { r = 0; finish: - if (u) - pa_xfree(u); + pa_xfree(u); return r; } static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) { pa_context *c = userdata; - assert(client && c && c->state == PA_CONTEXT_CONNECTING); + + assert(client); + assert(c); + assert(c->state == PA_CONTEXT_CONNECTING); pa_context_ref(c); @@ -593,9 +611,19 @@ finish: pa_context_unref(c); } -int pa_context_connect(pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api) { +int pa_context_connect( + pa_context *c, + const char *server, + pa_context_flags_t flags, + const pa_spawn_api *api) { + int r = -1; - assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED); + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(c, !(flags & ~PA_CONTEXT_NOAUTOSPAWN), PA_ERR_INVALID); if (!server) server = c->conf->default_server; @@ -658,27 +686,36 @@ finish: void pa_context_disconnect(pa_context *c) { assert(c); + assert(c->ref >= 1); + pa_context_set_state(c, PA_CONTEXT_TERMINATED); } pa_context_state_t pa_context_get_state(pa_context *c) { - assert(c && c->ref >= 1); + assert(c); + assert(c->ref >= 1); + return c->state; } int pa_context_errno(pa_context *c) { - assert(c && c->ref >= 1); + assert(c); + assert(c->ref >= 1); + return c->error; } void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { - assert(c && c->ref >= 1); + assert(c); + assert(c->ref >= 1); + c->state_callback = cb; c->state_userdata = userdata; } int pa_context_is_pending(pa_context *c) { - assert(c && c->ref >= 1); + assert(c); + assert(c->ref >= 1); /* pa_log("pstream: %i\n", pa_pstream_is_pending(c->pstream)); */ /* pa_log("pdispatch: %i\n", pa_pdispatch_is_pending(c->pdispatch)); */ @@ -700,7 +737,12 @@ static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata) static void set_dispatch_callbacks(pa_operation *o) { int done = 1; - assert(o && o->context && o->context->ref >= 1 && o->ref >= 1 && o->context->state == PA_CONTEXT_READY); + + assert(o); + assert(o->ref >= 1); + assert(o->context); + assert(o->context->ref >= 1); + assert(o->context->state == PA_CONTEXT_READY); pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL); pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL); @@ -719,8 +761,7 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_operation_ref(o); else { if (o->callback) { - void (*cb)(pa_context *c, void *userdata); - cb = (void (*)(pa_context*, void*)) o->callback; + pa_context_notify_cb_t cb = (pa_context_notify_cb_t) o->callback; cb(o->context, o->userdata); } @@ -732,39 +773,27 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { pa_operation *o; - assert(c && c->ref >= 1); - - if (c->state != PA_CONTEXT_READY) - return NULL; - - if (!pa_context_is_pending(c)) - return NULL; - - o = pa_operation_new(c, NULL); - assert(o); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + + assert(c); + assert(c->ref >= 1); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); set_dispatch_callbacks(pa_operation_ref(o)); return o; } -void pa_context_exit_daemon(pa_context *c) { - pa_tagstruct *t; - assert(c && c->ref >= 1); - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_EXIT); - pa_tagstruct_putu32(t, c->ctag++); - pa_pstream_send_tagstruct(c->pstream, t); -} - void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; - assert(pd && o && o->context && o->ref >= 1); + + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -786,67 +815,95 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, void (*internal_callback)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata), void (*cb)(void), void *userdata) { +pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); - o = pa_operation_new(c, NULL); - o->callback = cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_EXIT); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + + return o; +} + +pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa_pdispatch_cb_t internal_cb, pa_operation_cb_t cb, void *userdata) { + pa_tagstruct *t; + pa_operation *o; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, cb, o->userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, command); pa_tagstruct_putu32(t, tag = c->ctag++); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); + + assert(c); + assert(c->ref >= 1); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SET_DEFAULT_SINK); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SET_DEFAULT_SOURCE); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } int pa_context_is_local(pa_context *c) { assert(c); + return c->local; } @@ -854,20 +911,23 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && name && cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(name); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SET_CLIENT_NAME); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } const char* pa_get_library_version(void) { @@ -875,6 +935,8 @@ const char* pa_get_library_version(void) { } const char* pa_context_get_server(pa_context *c) { + assert(c); + assert(c->ref >= 1); if (!c->server) return NULL; diff --git a/src/polyp/context.h b/src/polyp/context.h index db268759f..73bcb698a 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -95,10 +95,10 @@ void pa_context_disconnect(pa_context *c); /** Drain the context. If there is nothing to drain, the function returns NULL */ pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata); -/** Tell the daemon to exit. No operation object is returned as the - * connection is terminated when the daemon quits, thus this operation - * would never complete. */ -void pa_context_exit_daemon(pa_context *c); +/** Tell the daemon to exit. The returned operation is unlikely to + * complete succesfully, since the daemon probably died before + * returning a success notification */ +pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata); /** Set the name of the default sink. \since 0.4 */ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata); diff --git a/src/polyp/internal.h b/src/polyp/internal.h index e9e0246ff..9907fae08 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -128,7 +128,7 @@ struct pa_stream { void *underflow_userdata; }; -typedef void (*pa_operation_callback_t)(void); +typedef void (*pa_operation_cb_t)(void); struct pa_operation { int ref; @@ -138,7 +138,7 @@ struct pa_operation { pa_operation_state_t state; void *userdata; - pa_operation_callback_t callback; + pa_operation_cb_t callback; }; void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); @@ -146,7 +146,7 @@ void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -pa_operation *pa_operation_new(pa_context *c, pa_stream *s); +pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t callback, void *userdata); void pa_operation_done(pa_operation *o); void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); @@ -169,12 +169,6 @@ void pa_stream_trash_ipol(pa_stream *s); return -pa_context_set_error((context), (error)); \ } while(0) -#define PA_CHECK_VALIDITY_RETURN_NULL(context, expression, error) do { \ - if (!(expression)) { \ - pa_context_set_error((context), (error)); \ - return NULL; \ - } \ -} while(0) #define PA_CHECK_VALIDITY_RETURN_ANY(context, expression, error, value) do { \ if (!(expression)) { \ @@ -183,4 +177,7 @@ void pa_stream_trash_ipol(pa_stream *s); } \ } while(0) +#define PA_CHECK_VALIDITY_RETURN_NULL(context, expression, error) PA_CHECK_VALIDITY_RETURN_ANY(context, expression, error, NULL) + + #endif diff --git a/src/polyp/introspect.c b/src/polyp/introspect.c index 404cead5e..043d2076e 100644 --- a/src/polyp/introspect.c +++ b/src/polyp/introspect.c @@ -39,7 +39,11 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; pa_stat_info i, *p = &i; - assert(pd && o && o->context && o->ref >= 1); + + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -57,7 +61,7 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNU } if (o->callback) { - void (*cb)(pa_context *s, const pa_stat_info*_i, void *_userdata) = (void (*)(pa_context *s, const pa_stat_info*_i, void *_userdata)) o->callback; + pa_stat_info_cb_t cb = (pa_stat_info_cb_t) o->callback; cb(o->context, p, o->userdata); } @@ -66,8 +70,8 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_stat(pa_context *c, void (*cb)(pa_context *c, const pa_stat_info*i, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, (pa_operation_callback_t) cb, userdata); +pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, (pa_operation_cb_t) cb, userdata); } /*** Server Info ***/ @@ -75,7 +79,11 @@ pa_operation* pa_context_stat(pa_context *c, void (*cb)(pa_context *c, const pa_ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; pa_server_info i, *p = &i; - assert(pd && o && o->context && o->ref >= 1); + + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -97,7 +105,7 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, } if (o->callback) { - void (*cb)(pa_context *s, const pa_server_info*_i, void *_userdata) = (void (*)(pa_context *s, const pa_server_info*_i, void *_userdata)) o->callback; + pa_server_info_cb_t cb = (pa_server_info_cb_t) o->callback; cb(o->context, p, o->userdata); } @@ -106,22 +114,26 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_get_server_info(pa_context *c, void (*cb)(pa_context *c, const pa_server_info*i, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, (pa_operation_callback_t) cb, userdata); +pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, (pa_operation_cb_t) cb, userdata); } /*** Sink Info ***/ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; - int eof = 1; - assert(pd && o && o->context && o->ref >= 1); + int eol = 1; + + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - eof = -1; + eol = -1; } else { while (!pa_tagstruct_eof(t)) { @@ -144,15 +156,15 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P } if (o->callback) { - void (*cb)(pa_context *s, const pa_sink_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sink_info*_i, int _eof, void *_userdata)) o->callback; + pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(pa_context *s, const pa_sink_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sink_info*_i, int _eof, void *_userdata)) o->callback; - cb(o->context, NULL, eof, o->userdata); + pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback; + cb(o->context, NULL, eol, o->userdata); } finish: @@ -160,19 +172,22 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_get_sink_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, (pa_operation_callback_t) cb, userdata); +pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, (pa_operation_cb_t) cb, userdata); } -pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_sink_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); + + assert(c); + assert(c->ref >= 1); + assert(cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); @@ -180,20 +195,24 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, voi pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); + + assert(c); + assert(c->ref >= 1); + assert(cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); @@ -201,23 +220,27 @@ pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } /*** Source info ***/ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; - int eof = 1; - assert(pd && o && o->context && o->ref >= 1); + int eol = 1; + + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - eof = -1; + eol = -1; } else { while (!pa_tagstruct_eof(t)) { @@ -239,15 +262,15 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, } if (o->callback) { - void (*cb)(pa_context *s, const pa_source_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_source_info*_i, int _eof, void *_userdata)) o->callback; + pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(pa_context *s, const pa_source_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_source_info*_i, int _eof, void *_userdata)) o->callback; - cb(o->context, NULL, eof, o->userdata); + pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback; + cb(o->context, NULL, eol, o->userdata); } finish: @@ -255,40 +278,47 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_get_source_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, (pa_operation_callback_t) cb, userdata); +pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, (pa_operation_cb_t) cb, userdata); } -pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, pa_source_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(cb); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(cb); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); @@ -305,14 +335,18 @@ pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; - int eof = 1; - assert(pd && o && o->context && o->ref >= 1); + int eol = 1; + + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - eof = -1; + eol = -1; } else { while (!pa_tagstruct_eof(t)) { @@ -327,15 +361,15 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, } if (o->callback) { - void (*cb)(pa_context *s, const pa_client_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_client_info*_i, int _eof, void *_userdata)) o->callback; + pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(pa_context *s, const pa_client_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_client_info*_i, int _eof, void *_userdata)) o->callback; - cb(o->context, NULL, eof, o->userdata); + pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback; + cb(o->context, NULL, eol, o->userdata); } finish: @@ -343,42 +377,50 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_client_info*i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(cb); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_get_client_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_client_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, (pa_operation_callback_t) cb, userdata); +pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t cb, void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, (pa_operation_cb_t) cb, userdata); } /*** Module info ***/ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; - int eof = 1; - assert(pd && o && o->context && o->ref >= 1); + int eol = 1; + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - eof = -1; + eol = -1; } else { while (!pa_tagstruct_eof(t)) { @@ -394,15 +436,15 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, } if (o->callback) { - void (*cb)(pa_context *s, const pa_module_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_module_info*_i, int _eof, void *_userdata)) o->callback; + pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(pa_context *s, const pa_module_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_module_info*_i, int _eof, void *_userdata)) o->callback; - cb(o->context, NULL, eof, o->userdata); + pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback; + cb(o->context, NULL, eol, o->userdata); } finish: @@ -410,42 +452,50 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_module_info*i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(cb); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_get_module_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_module_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, (pa_operation_callback_t) cb, userdata); +pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t cb, void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, (pa_operation_cb_t) cb, userdata); } /*** Sink input info ***/ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; - int eof = 1; - assert(pd && o && o->context && o->ref >= 1); + int eol = 1; + + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - eof = -1; + eol = -1; } else { while (!pa_tagstruct_eof(t)) { @@ -469,15 +519,15 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm } if (o->callback) { - void (*cb)(pa_context *s, const pa_sink_input_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sink_input_info*_i, int _eof, void *_userdata)) o->callback; + pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(pa_context *s, const pa_sink_input_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sink_input_info*_i, int _eof, void *_userdata)) o->callback; - cb(o->context, NULL, eof, o->userdata); + pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback; + cb(o->context, NULL, eol, o->userdata); } finish: @@ -485,42 +535,50 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(cb); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INPUT_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } pa_operation* pa_context_get_sink_input_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, (pa_operation_callback_t) cb, userdata); + return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, (pa_operation_cb_t) cb, userdata); } /*** Source output info ***/ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; - int eof = 1; - assert(pd && o && o->context && o->ref >= 1); + int eol = 1; + + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - eof = -1; + eol = -1; } else { while (!pa_tagstruct_eof(t)) { @@ -543,15 +601,15 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c } if (o->callback) { - void (*cb)(pa_context *s, const pa_source_output_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_source_output_info*_i, int _eof, void *_userdata)) o->callback; + pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(pa_context *s, const pa_source_output_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_source_output_info*_i, int _eof, void *_userdata))o->callback; - cb(o->context, NULL, eof, o->userdata); + pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback; + cb(o->context, NULL, eol, o->userdata); } finish: @@ -559,41 +617,49 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_source_output_info*i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_source_output_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(cb); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_OUTPUT_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_get_source_output_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_output_info*i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, (pa_operation_callback_t) cb, userdata); +pa_operation* pa_context_get_source_output_info_list(pa_context *c, pa_source_output_info_cb_t cb, void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, (pa_operation_cb_t) cb, userdata); } /*** Volume manipulation ***/ -pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c && idx != PA_INVALID_INDEX); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(volume); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME); @@ -602,20 +668,26 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, c pa_tagstruct_puts(t, NULL); pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c && name); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(name); + assert(volume); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME); @@ -624,20 +696,25 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name pa_tagstruct_puts(t, name); pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c && idx != PA_INVALID_INDEX); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(volume); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME); @@ -645,23 +722,27 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons pa_tagstruct_putu32(t, idx); pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } /** Sample Cache **/ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; - int eof = 1; - assert(pd && o && o->context && o->ref >= 1); + int eol = 1; + + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - eof = -1; + eol = -1; } else { while (!pa_tagstruct_eof(t)) { @@ -682,15 +763,15 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, } if (o->callback) { - void (*cb)(pa_context *s, const pa_sample_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sample_info*_i, int _eof, void *_userdata)) o->callback; + pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(pa_context *s, const pa_sample_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_sample_info*_i, int _eof, void *_userdata)) o->callback; - cb(o->context, NULL, eof, o->userdata); + pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback; + cb(o->context, NULL, eol, o->userdata); } finish: @@ -698,15 +779,19 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name, pa_sample_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb && name); + + assert(c); + assert(c->ref >= 1); + assert(cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO); @@ -714,20 +799,24 @@ pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, pa_sample_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(cb); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO); @@ -735,81 +824,93 @@ pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, v pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_get_sample_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, (pa_operation_callback_t) cb, userdata); +pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t cb, void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, (pa_operation_cb_t) cb, userdata); } -static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c && idx != PA_INVALID_INDEX); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, command); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) { return command_kill(c, PA_COMMAND_KILL_CLIENT, idx, cb, userdata); } -pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) { return command_kill(c, PA_COMMAND_KILL_SINK_INPUT, idx, cb, userdata); } -pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) { return command_kill(c, PA_COMMAND_KILL_SOURCE_OUTPUT, idx, cb, userdata); } -static void load_module_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void context_index_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; - uint32_t idx = -1; - assert(pd && o && o->context && o->ref >= 1); + uint32_t idx; + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - } else if (pa_tagstruct_getu32(t, &idx) < 0 || + idx = PA_INVALID_INDEX; + } else if (pa_tagstruct_getu32(t, &idx) || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } - + if (o->callback) { - void (*cb)(pa_context *c, uint32_t _idx, void *_userdata) = (void (*)(pa_context *c, uint32_t _idx, void *_userdata)) o->callback; + pa_context_index_cb_t cb = (pa_context_index_cb_t) o->callback; cb(o->context, idx, o->userdata); } + finish: pa_operation_done(o); pa_operation_unref(o); } -pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, void (*cb)(pa_context *c, uint32_t idx, void *userdata), void *userdata) { +pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c && name && argument); + + assert(c); + assert(c->ref >= 1); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_LOAD_MODULE); @@ -817,12 +918,12 @@ pa_operation* pa_context_load_module(pa_context *c, const char*name, const char pa_tagstruct_puts(t, name); pa_tagstruct_puts(t, argument); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, load_module_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_index_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) { +pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) { return command_kill(c, PA_COMMAND_UNLOAD_MODULE, idx, cb, userdata); } @@ -830,14 +931,18 @@ pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, void (*cb)(p static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; - int eof = 1; - assert(pd && o && o->context && o->ref >= 1); + int eol = 1; + + assert(pd); + assert(o); + assert(o->ref >= 1); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - eof = -1; + eol = -1; } else { while (!pa_tagstruct_eof(t)) { @@ -853,15 +958,15 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman } if (o->callback) { - void (*cb)(pa_context *s, const pa_autoload_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_autoload_info*_i, int _eof, void *_userdata)) o->callback; + pa_autoload_info_cb_t cb = (pa_autoload_info_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); } } } if (o->callback) { - void (*cb)(pa_context *s, const pa_autoload_info*_i, int _eof, void *_userdata) = (void (*)(pa_context *s, const pa_autoload_info*_i, int _eof, void *_userdata)) o->callback; - cb(o->context, NULL, eof, o->userdata); + pa_autoload_info_cb_t cb = (pa_autoload_info_cb_t) o->callback; + cb(o->context, NULL, eol, o->userdata); } finish: @@ -869,15 +974,20 @@ finish: pa_operation_unref(o); } -pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb && name); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + assert(cb); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, type == PA_AUTOLOAD_SINK || type == PA_AUTOLOAD_SOURCE, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_AUTOLOAD_INFO); @@ -885,71 +995,53 @@ pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *na pa_tagstruct_puts(t, name); pa_tagstruct_putu32(t, type); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) { +pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(c && cb && idx != PA_INVALID_INDEX); + + assert(c); + assert(c->ref >= 1); + assert(cb); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_AUTOLOAD_INFO); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_get_autoload_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) { - return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, (pa_operation_callback_t) cb, userdata); +pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata) { + return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, (pa_operation_cb_t) cb, userdata); } -static void context_add_autoload_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { - pa_operation *o = userdata; - uint32_t idx; - assert(pd && o && o->context && o->ref >= 1); - - if (command != PA_COMMAND_REPLY) { - if (pa_context_handle_error(o->context, command, t) < 0) - goto finish; - - idx = PA_INVALID_INDEX; - } else if (pa_tagstruct_getu32(t, &idx) || - !pa_tagstruct_eof(t)) { - pa_context_fail(o->context, PA_ERR_PROTOCOL); - goto finish; - } - - if (o->callback) { - void (*cb)(pa_context *s, uint32_t _idx, void *_userdata) = (void (*)(pa_context *s, uint32_t _idx, void *_userdata)) o->callback; - cb(o->context, idx, o->userdata); - } - - -finish: - pa_operation_done(o); - pa_operation_unref(o); -} - -pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) { +pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t cb, void* userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c && name && module && argument); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, type == PA_AUTOLOAD_SINK || type == PA_AUTOLOAD_SOURCE, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, module && *module, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_ADD_AUTOLOAD); @@ -959,20 +1051,24 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo pa_tagstruct_puts(t, module); pa_tagstruct_puts(t, argument); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_add_autoload_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_index_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) { +pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c && name); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, type == PA_AUTOLOAD_SINK || type == PA_AUTOLOAD_SOURCE, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_AUTOLOAD); @@ -980,27 +1076,30 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name pa_tagstruct_puts(t, name); pa_tagstruct_putu32(t, type); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } -pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) { +pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c && idx != PA_INVALID_INDEX); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_AUTOLOAD); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } diff --git a/src/polyp/introspect.h b/src/polyp/introspect.h index 0abb54cf2..d4ff65fb4 100644 --- a/src/polyp/introspect.h +++ b/src/polyp/introspect.h @@ -36,11 +36,12 @@ * of a certain kind, use the pa_context_xxx_list() functions. The * specified callback function is called once for each entry. The * enumeration is finished by a call to the callback function with - * is_last=1 and i=NULL. Strings referenced in pa_xxx_info structures - * and the structures themselves point to internal memory that may not - * be modified. That memory is only valid during the call to the - * callback function. A deep copy is required if you need this data - * outside the callback functions. An error is signalled by a call to * the callback function with i=NULL and is_last=0. + * eol=1 and i=NULL. Strings referenced in pa_xxx_info structures and + * the structures themselves point to internal memory that may not be + * modified. That memory is only valid during the call to the callback + * function. A deep copy is required if you need this data outside the + * callback functions. An error is signalled by a call to the callback + * function with i=NULL and eol=0. * * When using the routines that ask fo a single entry only, a callback * with the same signature is used. However, no finishing call to the @@ -63,14 +64,17 @@ typedef struct pa_sink_info { const char *driver; /**< Driver name. \since 0.9 */ } pa_sink_info; +/** Callback prototype for pa_context_get_sink_info_by_name() and friends */ +typedef void (*pa_sink_info_cb_t)(pa_context *c, const pa_sink_info *i, int eol, void *userdata); + /** Get information about a sink by its name */ -pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata); /** Get information about a sink by its index */ -pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t id, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t id, pa_sink_info_cb_t cb, void *userdata); /** Get the complete sink list */ -pa_operation* pa_context_get_sink_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata); /** Stores information about sources */ typedef struct pa_source_info { @@ -86,14 +90,17 @@ typedef struct pa_source_info { const char *driver; /**< Driver name \since 0.9 */ } pa_source_info; +/** Callback prototype for pa_context_get_source_info_by_name() and friends */ +typedef void (*pa_source_info_cb_t)(pa_context *c, const pa_source_info *i, int eol, void *userdata); + /** Get information about a source by its name */ -pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata); /** Get information about a source by its index */ -pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t id, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t id, pa_source_info_cb_t cb, void *userdata); /** Get the complete source list */ -pa_operation* pa_context_get_source_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata); /** Server information */ typedef struct pa_server_info { @@ -107,8 +114,11 @@ typedef struct pa_server_info { uint32_t cookie; /**< A random cookie for identifying this instance of polypaudio. \since 0.8 */ } pa_server_info; +/** Callback prototype for pa_context_get_server_info() */ +typedef void (*pa_server_info_cb_t) (pa_context *c, const pa_server_info*i, void *userdata); + /** Get some information about the server */ -pa_operation* pa_context_get_server_info(pa_context *c, void (*cb)(pa_context *c, const pa_server_info*i, void *userdata), void *userdata); +pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata); /** Stores information about modules */ typedef struct pa_module_info { @@ -119,11 +129,14 @@ typedef struct pa_module_info { int auto_unload; /**< Non-zero if this is an autoloaded module */ } pa_module_info; +/** Callback prototype for pa_context_get_module_info() and firends*/ +typedef void (*pa_module_info_cb_t) (pa_context *c, const pa_module_info*i, int eol, void *userdata); + /** Get some information about a module by its index */ -pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_module_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_info_cb_t cb, void *userdata); /** Get the complete list of currently loaded modules */ -pa_operation* pa_context_get_module_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_module_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t cb, void *userdata); /** Stores information about clients */ typedef struct pa_client_info { @@ -133,11 +146,14 @@ typedef struct pa_client_info { const char *driver; /**< Driver name \since 0.9 */ } pa_client_info; +/** Callback prototype for pa_context_get_client_info() and firends*/ +typedef void (*pa_client_info_cb_t) (pa_context *c, const pa_client_info*i, int eol, void *userdata); + /** Get information about a client by its index */ -pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_client_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_info_cb_t cb, void *userdata); /** Get the complete client list */ -pa_operation* pa_context_get_client_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_client_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t cb, void *userdata); /** Stores information about sink inputs */ typedef struct pa_sink_input_info { @@ -155,11 +171,14 @@ typedef struct pa_sink_input_info { const char *driver; /**< Driver name \since 0.9 */ } pa_sink_input_info; +/** Callback prototype for pa_context_get_sink_input_info() and firends*/ +typedef void (*pa_sink_input_info_cb_t) (pa_context *c, const pa_sink_input_info *i, int eol, void *userdata); + /** Get some information about a sink input by its index */ -pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata); /** Get the complete sink input list */ -pa_operation* pa_context_get_sink_input_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sink_input_info_list(pa_context *c, pa_sink_input_info_cb_t cb, void *userdata); /** Stores information about source outputs */ typedef struct pa_source_output_info { @@ -176,20 +195,23 @@ typedef struct pa_source_output_info { const char *driver; /**< Driver name \since 0.9 */ } pa_source_output_info; +/** Callback prototype for pa_context_get_source_output_info() and firends*/ +typedef void (*pa_source_output_info_cb_t) (pa_context *c, const pa_source_output_info *i, int eol, void *userdata); + /** Get information about a source output by its index */ -pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_source_output_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_source_output_info_cb_t cb, void *userdata); /** Get the complete list of source outputs */ -pa_operation* pa_context_get_source_output_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_source_output_info*i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_source_output_info_list(pa_context *c, pa_source_output_info_cb_t cb, void *userdata); /** Set the volume of a sink device specified by its index */ -pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); /** Set the volume of a sink device specified by its name */ -pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); /** Set the volume of a sink input stream */ -pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); /** Memory block statistics */ typedef struct pa_stat_info { @@ -200,8 +222,11 @@ typedef struct pa_stat_info { uint32_t scache_size; /**< Total size of all sample cache entries. \since 0.4 */ } pa_stat_info; +/** Callback prototype for pa_context_stat() */ +typedef void (*pa_stat_info_cb_t) (pa_context *c, const pa_stat_info *i, void *userdata); + /** Get daemon memory block statistics */ -pa_operation* pa_context_stat(pa_context *c, void (*cb)(pa_context *c, const pa_stat_info *i, void *userdata), void *userdata); +pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdata); /** Stores information about sample cache entries */ typedef struct pa_sample_info { @@ -216,29 +241,35 @@ typedef struct pa_sample_info { const char *filename; /**< In case this is a lazy cache entry, the filename for the sound file to be loaded on demand. \since 0.5 */ } pa_sample_info; +/** Callback prototype for pa_context_get_sample_info_by_name() and firends */ +typedef void (*pa_sample_info_cb_t)(pa_context *c, const pa_sample_info *i, int eol, void *userdata); + /** Get information about a sample by its name */ -pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name, pa_sample_info_cb_t cb, void *userdata); /** Get information about a sample by its index */ -pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, pa_sample_info_cb_t cb, void *userdata); /** Get the complete list of samples stored in the daemon. */ -pa_operation* pa_context_get_sample_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sample_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t cb, void *userdata); /** Kill a client. \since 0.5 */ -pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata); /** Kill a sink input. \since 0.5 */ -pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata); /** Kill a source output. \since 0.5 */ -pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata); + +/** Callback prototype for pa_context_load_module() and pa_context_add_autoload() */ +typedef void (*pa_context_index_cb_t)(pa_context *c, uint32_t idx, void *userdata); /** Load a module. \since 0.5 */ -pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, void (*cb)(pa_context *c, uint32_t idx, void *userdata), void *userdata); +pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata); /** Unload a module. \since 0.5 */ -pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void *userdata); +pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata); /** Type of an autoload entry. \since 0.5 */ typedef enum pa_autoload_type { @@ -255,23 +286,26 @@ typedef struct pa_autoload_info { const char *argument; /**< Argument string for module */ } pa_autoload_info; -/** Get info about a specific autoload entry. \since 0.6 */ -pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata); +/** Callback prototype for pa_context_get_autoload_info_by_name() and firends */ +typedef void (*pa_autoload_info_cb_t)(pa_context *c, const pa_autoload_info *i, int eol, void *userdata); /** Get info about a specific autoload entry. \since 0.6 */ -pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata); + +/** Get info about a specific autoload entry. \since 0.6 */ +pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata); /** Get the complete list of autoload entries. \since 0.5 */ -pa_operation* pa_context_get_autoload_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata); +pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata); /** Add a new autoload entry. \since 0.5 */ -pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, void (*cb)(pa_context *c, int idx, void *userdata), void* userdata); +pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t, void* userdata); /** Remove an autoload entry. \since 0.6 */ -pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata); +pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata); /** Remove an autoload entry. \since 0.6 */ -pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void* userdata); +pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata); PA_C_DECL_END diff --git a/src/polyp/operation.c b/src/polyp/operation.c index 5440cf9ea..0216888c4 100644 --- a/src/polyp/operation.c +++ b/src/polyp/operation.c @@ -31,7 +31,7 @@ #include "operation.h" -pa_operation *pa_operation_new(pa_context *c, pa_stream *s) { +pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb, void *userdata) { pa_operation *o; assert(c); @@ -41,8 +41,8 @@ pa_operation *pa_operation_new(pa_context *c, pa_stream *s) { o->stream = s ? pa_stream_ref(s) : NULL; o->state = PA_OPERATION_RUNNING; - o->userdata = NULL; - o->callback = NULL; + o->callback = cb; + o->userdata = userdata; PA_LLIST_PREPEND(pa_operation, o->context->operations, o); return pa_operation_ref(o); diff --git a/src/polyp/scache.c b/src/polyp/scache.c index f6a3a7e64..792d7cbfc 100644 --- a/src/polyp/scache.c +++ b/src/polyp/scache.c @@ -34,15 +34,17 @@ #include "scache.h" -void pa_stream_connect_upload(pa_stream *s, size_t length) { +int pa_stream_connect_upload(pa_stream *s, size_t length) { pa_tagstruct *t; uint32_t tag; - assert(s && length); + assert(s); + PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, length <= 0, PA_ERR_INVALID); + pa_stream_ref(s); - s->state = PA_STREAM_CREATING; s->direction = PA_STREAM_UPLOAD; t = pa_tagstruct_new(NULL, 0); @@ -54,22 +56,23 @@ void pa_stream_connect_upload(pa_stream *s, size_t length) { pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s); + pa_stream_set_state(s, PA_STREAM_CREATING); + pa_stream_unref(s); + return 0; } -void pa_stream_finish_upload(pa_stream *s) { +int pa_stream_finish_upload(pa_stream *s) { pa_tagstruct *t; uint32_t tag; assert(s); - if (!s->channel_valid || !s->context->state == PA_CONTEXT_READY) - return; + PA_CHECK_VALIDITY(s->context, s->channel_valid, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); pa_stream_ref(s); t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); @@ -77,53 +80,59 @@ void pa_stream_finish_upload(pa_stream *s) { pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s); pa_stream_unref(s); + return 0; } -pa_operation * pa_context_play_sample(pa_context *c, const char *name, const char *dev, uint32_t volume, pa_context_success_cb_t cb, void *userdata) { +pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char *dev, pa_volume_t volume, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c && name && *name && (!dev || *dev)); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, !dev || *dev, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); if (!dev) dev = c->conf->default_sink; t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); pa_tagstruct_putu32(t, tag = c->ctag++); - pa_tagstruct_putu32(t, (uint32_t) -1); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, dev); pa_tagstruct_putu32(t, volume); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c && name); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } diff --git a/src/polyp/scache.h b/src/polyp/scache.h index 3480d8766..cdb47cab5 100644 --- a/src/polyp/scache.h +++ b/src/polyp/scache.h @@ -34,11 +34,11 @@ PA_C_DECL_BEGIN /** Make this stream a sample upload stream */ -void pa_stream_connect_upload(pa_stream *s, size_t length); +int pa_stream_connect_upload(pa_stream *s, size_t length); /** Finish the sample upload, the stream name will become the sample name. You cancel a samp * le upload by issuing pa_stream_disconnect() */ -void pa_stream_finish_upload(pa_stream *s); +int pa_stream_finish_upload(pa_stream *s); /** Play a sample from the sample cache to the specified device. If the latter is NULL use the default sink. Returns an operation object */ pa_operation* pa_context_play_sample( diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 88971085b..1ffb4c16a 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -44,7 +44,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * assert(c); PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID); - PA_CHECK_VALIDITY_RETURN_NULL(c, !map || pa_channel_map_valid(map), PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID); s = pa_xnew(pa_stream, 1); s->ref = 1; @@ -190,7 +190,11 @@ void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED pa_context *c = userdata; pa_stream *s; uint32_t channel; - assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c); + + assert(pd); + assert(command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED); + assert(t); + assert(c); pa_context_ref(c); @@ -203,7 +207,7 @@ void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) goto finish; - c->error = PA_ERR_KILLED; + pa_context_set_error(c, PA_ERR_KILLED); pa_stream_set_state(s, PA_STREAM_FAILED); finish: @@ -214,7 +218,11 @@ void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32 pa_stream *s; pa_context *c = userdata; uint32_t bytes, channel; - assert(pd && command == PA_COMMAND_REQUEST && t && c); + + assert(pd); + assert(command == PA_COMMAND_REQUEST); + assert(t); + assert(c); pa_context_ref(c); @@ -276,7 +284,7 @@ finish: } static void ipol_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { - struct timeval tv2; + struct timeval next; pa_stream *s = userdata; pa_stream_ref(s); @@ -288,10 +296,9 @@ static void ipol_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED co s->ipol_requested = 1; } - pa_gettimeofday(&tv2); - pa_timeval_add(&tv2, LATENCY_IPOL_INTERVAL_USEC); - - m->time_restart(e, &tv2); + pa_gettimeofday(&next); + pa_timeval_add(&next, LATENCY_IPOL_INTERVAL_USEC); + m->time_restart(e, &next); pa_stream_unref(s); } @@ -299,8 +306,12 @@ static void ipol_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED co void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s = userdata; - assert(pd && s && s->state == PA_STREAM_CREATING); - + + assert(pd); + assert(t); + assert(s); + assert(s->state == PA_STREAM_CREATING); + pa_stream_ref(s); if (command != PA_COMMAND_REPLY) { @@ -321,6 +332,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED if (s->direction == PA_STREAM_RECORD) { assert(!s->record_memblockq); + s->record_memblockq = pa_memblockq_new( 0, s->buffer_attr.maxlength, @@ -330,12 +342,10 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED 0, NULL, s->context->memblock_stat); - assert(s->record_memblockq); } s->channel_valid = 1; pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - pa_stream_set_state(s, PA_STREAM_READY); if (s->interpolate) { struct timeval tv; @@ -348,7 +358,9 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED s->ipol_event = s->mainloop->time_new(s->mainloop, &tv, &ipol_callback, s); } - if (s->requested_bytes && s->ref > 1 && s->write_callback) + pa_stream_set_state(s, PA_STREAM_READY); + + if (s->requested_bytes > 0 && s->ref > 1 && s->write_callback) s->write_callback(s, s->requested_bytes, s->write_userdata); finish: @@ -371,8 +383,10 @@ static int create_stream( assert(s->ref >= 1); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY(s->context, (flags & ~(PA_STREAM_START_CORKED|PA_STREAM_INTERPOLATE_LATENCY)) == 0, PA_ERR_INVALID); + PA_CHECK_VALIDITY(s->context, !(flags & ~(PA_STREAM_START_CORKED|PA_STREAM_INTERPOLATE_LATENCY)), PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, direction == PA_STREAM_PLAYBACK || flags == 0, PA_ERR_INVALID); + PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID); + PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID); pa_stream_ref(s); @@ -395,17 +409,10 @@ static int create_stream( s->buffer_attr.fragsize = s->buffer_attr.tlength/100; } - pa_stream_set_state(s, PA_STREAM_CREATING); - t = pa_tagstruct_new(NULL, 0); - assert(t); - if (!dev) { - if (s->direction == PA_STREAM_PLAYBACK) - dev = s->context->conf->default_sink; - else - dev = s->context->conf->default_source; - } + if (!dev) + dev = s->direction == PA_STREAM_PLAYBACK ? s->context->conf->default_sink : s->context->conf->default_source; pa_tagstruct_put( t, @@ -422,6 +429,7 @@ static int create_stream( if (s->direction == PA_STREAM_PLAYBACK) { pa_cvolume cv; + pa_tagstruct_put( t, PA_TAG_U32, s->buffer_attr.tlength, @@ -430,10 +438,8 @@ static int create_stream( PA_TAG_U32, s->syncid, PA_TAG_INVALID); - if (!volume) { - pa_cvolume_reset(&cv, s->sample_spec.channels); - volume = &cv; - } + if (!volume) + volume = pa_cvolume_reset(&cv, s->sample_spec.channels); pa_tagstruct_put_cvolume(t, volume); } else @@ -442,6 +448,8 @@ static int create_stream( pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s); + pa_stream_set_state(s, PA_STREAM_CREATING); + pa_stream_unref(s); return 0; } @@ -484,7 +492,6 @@ int pa_stream_write( assert(s); assert(s->ref >= 1); - assert(s->context); assert(data); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); @@ -495,14 +502,13 @@ int pa_stream_write( if (length <= 0) return 0; - if (free_cb) { + if (free_cb) chunk.memblock = pa_memblock_new_user((void*) data, length, free_cb, 1, s->context->memblock_stat); - assert(chunk.memblock && chunk.memblock->data); - } else { + else { chunk.memblock = pa_memblock_new(length, s->context->memblock_stat); - assert(chunk.memblock && chunk.memblock->data); memcpy(chunk.memblock->data, data, length); } + chunk.index = 0; chunk.length = length; @@ -580,7 +586,7 @@ size_t pa_stream_readable_size(pa_stream *s) { return pa_memblockq_get_length(s->record_memblockq); } -pa_operation * pa_stream_drain(pa_stream *s, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata) { +pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; @@ -591,9 +597,7 @@ pa_operation * pa_stream_drain(pa_stream *s, void (*cb) (pa_stream*s, int succes PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); - o = pa_operation_new(s->context, s); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); @@ -609,7 +613,11 @@ static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, pa_operation *o = userdata; pa_latency_info i, *p = NULL; struct timeval local, remote, now; - assert(pd && o && o->stream && o->context); + + assert(pd); + assert(o); + assert(o->stream); + assert(o->context); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -658,7 +666,7 @@ static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, } if (o->callback) { - void (*cb)(pa_stream *s, const pa_latency_info *_i, void *_userdata) = (void (*)(pa_stream *s, const pa_latency_info *_i, void *_userdata)) o->callback; + pa_stream_get_latency_info_cb_t cb = (pa_stream_get_latency_info_cb_t) o->callback; cb(o->stream, p, o->userdata); } @@ -667,7 +675,7 @@ finish: pa_operation_unref(o); } -pa_operation* pa_stream_get_latency_info(pa_stream *s, void (*cb)(pa_stream *p, const pa_latency_info*i, void *userdata), void *userdata) { +pa_operation* pa_stream_get_latency_info(pa_stream *s, pa_stream_get_latency_info_cb_t cb, void *userdata) { uint32_t tag; pa_operation *o; pa_tagstruct *t; @@ -679,9 +687,7 @@ pa_operation* pa_stream_get_latency_info(pa_stream *s, void (*cb)(pa_stream *p, PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - o = pa_operation_new(s->context, s); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY); @@ -700,7 +706,10 @@ pa_operation* pa_stream_get_latency_info(pa_stream *s, void (*cb)(pa_stream *p, void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s = userdata; - assert(pd && s && s->ref >= 1); + + assert(pd); + assert(s); + assert(s->ref >= 1); pa_stream_ref(s); @@ -789,7 +798,11 @@ void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, vo void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; - assert(pd && o && o->context && o->ref >= 1); + + assert(pd); + assert(o); + assert(o->context); + assert(o->ref >= 1); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -802,7 +815,7 @@ void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN } if (o->callback) { - void (*cb)(pa_stream *s, int _success, void *_userdata) = (void (*)(pa_stream *s, int _success, void *_userdata)) o->callback; + pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback; cb(o->stream, success, o->userdata); } @@ -811,11 +824,16 @@ finish: pa_operation_unref(o); } -pa_operation* pa_stream_cork(pa_stream *s, int b, void (*cb) (pa_stream*s, int success, void *userdata), void *userdata) { +pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); + + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); if (s->interpolate) { if (!s->corked && b) @@ -828,13 +846,9 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, void (*cb) (pa_stream*s, int s s->corked = b; - o = pa_operation_new(s->context, s); - assert(o); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CORK_PLAYBACK_STREAM : PA_COMMAND_CORK_RECORD_STREAM); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); @@ -847,15 +861,17 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, void (*cb) (pa_stream*s, int s return pa_operation_ref(o); } -static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata) { +static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, pa_stream_success_cb_t cb, void *userdata) { pa_tagstruct *t; pa_operation *o; uint32_t tag; - assert(s && s->ref >= 1 && s->state == PA_STREAM_READY); - o = pa_operation_new(s->context, s); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, command); @@ -867,40 +883,54 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, return pa_operation_ref(o); } -pa_operation* pa_stream_flush(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata) { +pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; - o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata); - pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + + if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) + pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + return o; } -pa_operation* pa_stream_prebuf(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata) { +pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; - o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata); - pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); + + if ((o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata))) + pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + return o; } -pa_operation* pa_stream_trigger(pa_stream *s, void (*cb)(pa_stream *s, int success, void *userdata), void *userdata) { +pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; - o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata); - pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); + + if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata))) + pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + return o; } -pa_operation* pa_stream_set_name(pa_stream *s, const char *name, void(*cb)(pa_stream*c, int success, void *userdata), void *userdata) { +pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(s && s->ref >= 1 && s->state == PA_STREAM_READY && name && s->direction != PA_STREAM_UPLOAD); + + assert(s); + assert(s->ref >= 1); + assert(name); - o = pa_operation_new(s->context, s); - assert(o); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME); pa_tagstruct_putu32(t, tag = s->context->ctag++); pa_tagstruct_putu32(t, s->channel); @@ -913,12 +943,21 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, void(*cb)(pa_st uint64_t pa_stream_get_counter(pa_stream *s) { assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (uint64_t) -1); + return s->counter; } pa_usec_t pa_stream_get_time(pa_stream *s, const pa_latency_info *i) { pa_usec_t usec; + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (pa_usec_t) -1); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE, (pa_usec_t) -1); usec = pa_bytes_to_usec(i->counter, &s->sample_spec); @@ -950,6 +989,7 @@ pa_usec_t pa_stream_get_time(pa_stream *s, const pa_latency_info *i) { static pa_usec_t time_counter_diff(pa_stream *s, pa_usec_t t, pa_usec_t c, int *negative) { assert(s); + assert(s->ref >= 1); if (negative) *negative = 0; @@ -968,8 +1008,14 @@ static pa_usec_t time_counter_diff(pa_stream *s, pa_usec_t t, pa_usec_t c, int * pa_usec_t pa_stream_get_latency(pa_stream *s, const pa_latency_info *i, int *negative) { pa_usec_t t, c; - assert(s && i); + assert(s); + assert(s->ref >= 1); + assert(i); + + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (pa_usec_t) -1); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE, (pa_usec_t) -1); + t = pa_stream_get_time(s, i); c = pa_bytes_to_usec(s->counter, &s->sample_spec); @@ -978,18 +1024,21 @@ pa_usec_t pa_stream_get_latency(pa_stream *s, const pa_latency_info *i, int *neg const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s) { assert(s); - + assert(s->ref >= 1); + return &s->sample_spec; } const pa_channel_map* pa_stream_get_channel_map(pa_stream *s) { assert(s); + assert(s->ref >= 1); return &s->channel_map; } void pa_stream_trash_ipol(pa_stream *s) { assert(s); + assert(s->ref >= 1); if (!s->interpolate) return; @@ -1000,8 +1049,14 @@ void pa_stream_trash_ipol(pa_stream *s) { pa_usec_t pa_stream_get_interpolated_time(pa_stream *s) { pa_usec_t usec; - assert(s && s->interpolate); + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (pa_usec_t) -1); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE, (pa_usec_t) -1); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->interpolate, PA_ERR_BADSTATE, (pa_usec_t) -1); + if (s->corked) usec = s->ipol_usec; else { @@ -1021,8 +1076,14 @@ pa_usec_t pa_stream_get_interpolated_time(pa_stream *s) { pa_usec_t pa_stream_get_interpolated_latency(pa_stream *s, int *negative) { pa_usec_t t, c; - assert(s && s->interpolate); + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (pa_usec_t) -1); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE, (pa_usec_t) -1); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->interpolate, PA_ERR_BADSTATE, (pa_usec_t) -1); + t = pa_stream_get_interpolated_time(s); c = pa_bytes_to_usec(s->counter, &s->sample_spec); return time_counter_diff(s, t, c, negative); diff --git a/src/polyp/subscribe.c b/src/polyp/subscribe.c index 97f76cb79..65849b6d4 100644 --- a/src/polyp/subscribe.c +++ b/src/polyp/subscribe.c @@ -37,7 +37,11 @@ void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSE pa_context *c = userdata; pa_subscription_event_type_t e; uint32_t index; - assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c); + + assert(pd); + assert(command == PA_COMMAND_SUBSCRIBE_EVENT); + assert(t); + assert(c); pa_context_ref(c); @@ -60,24 +64,28 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_c pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c); - o = pa_operation_new(c, NULL); - o->callback = (pa_operation_callback_t) cb; - o->userdata = userdata; + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); pa_tagstruct_putu32(t, tag = c->ctag++); pa_tagstruct_putu32(t, m); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); - return pa_operation_ref(o); + return o; } void pa_context_set_subscribe_callback(pa_context *c, pa_context_subscribe_cb_t cb, void *userdata) { assert(c); + assert(c->ref >= 1); + c->subscribe_callback = cb; c->subscribe_userdata = userdata; } diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index c33f593ed..89b061c27 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -40,7 +40,7 @@ struct pa_iochannel { int ifd, ofd; pa_mainloop_api* mainloop; - pa_iochannel_callback_t callback; + pa_iochannel_cb_t callback; void*userdata; int readable; @@ -242,7 +242,7 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { return r; } -void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_callback_t _callback, void *userdata) { +void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) { assert(io); io->callback = _callback; diff --git a/src/polypcore/iochannel.h b/src/polypcore/iochannel.h index 7d355d8f0..977fe2c36 100644 --- a/src/polypcore/iochannel.h +++ b/src/polypcore/iochannel.h @@ -57,8 +57,8 @@ int pa_iochannel_is_hungup(pa_iochannel*io); void pa_iochannel_set_noclose(pa_iochannel*io, int b); /* Set the callback function that is called whenever data becomes available for read or write */ -typedef void (*pa_iochannel_callback_t)(pa_iochannel*io, void *userdata); -void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_callback_t callback, void *userdata); +typedef void (*pa_iochannel_cb_t)(pa_iochannel*io, void *userdata); +void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t callback, void *userdata); /* In case the file descriptor is a socket, return a pretty-printed string in *s which describes the peer connected */ void pa_iochannel_socket_peer_to_string(pa_iochannel*io, char*s, size_t l); diff --git a/src/polypcore/pdispatch.c b/src/polypcore/pdispatch.c index fbb1b6974..c082b8cc5 100644 --- a/src/polypcore/pdispatch.c +++ b/src/polypcore/pdispatch.c @@ -94,7 +94,7 @@ static const char *command_names[PA_COMMAND_MAX] = { struct reply_info { pa_pdispatch *pdispatch; PA_LLIST_FIELDS(struct reply_info); - pa_pdispatch_callback_t callback; + pa_pdispatch_cb_t callback; void *userdata; uint32_t tag; pa_time_event *time_event; @@ -103,7 +103,7 @@ struct reply_info { struct pa_pdispatch { int ref; pa_mainloop_api *mainloop; - const pa_pdispatch_callback_t *callback_table; + const pa_pdispatch_cb_t *callback_table; unsigned n_commands; PA_LLIST_HEAD(struct reply_info, replies); pa_pdispatch_drain_callback drain_callback; @@ -121,7 +121,7 @@ static void reply_info_free(struct reply_info *r) { pa_xfree(r); } -pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_callback_t*table, unsigned entries) { +pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_t*table, unsigned entries) { pa_pdispatch *pd; assert(mainloop); @@ -149,7 +149,7 @@ static void pdispatch_free(pa_pdispatch *pd) { } static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command, pa_tagstruct *ts) { - pa_pdispatch_callback_t callback; + pa_pdispatch_cb_t callback; void *userdata; uint32_t tag; assert(r); @@ -210,7 +210,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, void *userdata) { run_action(pd, r, command, ts); } else if (pd->callback_table && (command < pd->n_commands) && pd->callback_table[command]) { - const pa_pdispatch_callback_t *c = pd->callback_table+command; + const pa_pdispatch_cb_t *c = pd->callback_table+command; (*c)(pd, command, tag, ts, userdata); } else { @@ -236,7 +236,7 @@ static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, PA_GCC_UNUSED c run_action(r->pdispatch, r, PA_COMMAND_TIMEOUT, NULL); } -void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_callback_t cb, void *userdata) { +void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t cb, void *userdata) { struct reply_info *r; struct timeval tv; assert(pd && pd->ref >= 1 && cb); diff --git a/src/polypcore/pdispatch.h b/src/polypcore/pdispatch.h index 27d2d61f9..31533d57f 100644 --- a/src/polypcore/pdispatch.h +++ b/src/polypcore/pdispatch.h @@ -29,15 +29,15 @@ typedef struct pa_pdispatch pa_pdispatch; -typedef void (*pa_pdispatch_callback_t)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +typedef void (*pa_pdispatch_cb_t)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_callback_t*table, unsigned entries); +pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_cb_t*table, unsigned entries); void pa_pdispatch_unref(pa_pdispatch *pd); pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, void *userdata); -void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_callback_t callback, void *userdata); +void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t callback, void *userdata); int pa_pdispatch_is_pending(pa_pdispatch *pd); diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 21800e6c5..1bca1c1ed 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -174,7 +174,7 @@ static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, u static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -static const pa_pdispatch_callback_t command_table[PA_COMMAND_MAX] = { +static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = NULL, [PA_COMMAND_TIMEOUT] = NULL, [PA_COMMAND_REPLY] = NULL, diff --git a/src/polypcore/tagstruct.h b/src/polypcore/tagstruct.h index 59db67b07..0ed751710 100644 --- a/src/polypcore/tagstruct.h +++ b/src/polypcore/tagstruct.h @@ -51,8 +51,6 @@ enum { PA_TAG_CVOLUME = 'v' }; - - pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length); void pa_tagstruct_free(pa_tagstruct*t); uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l); diff --git a/src/utils/pactl.c b/src/utils/pactl.c index e3305f0f5..86c4e7be1 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -559,7 +559,7 @@ static void context_state_callback(pa_context *c, void *userdata) { break; case EXIT: - pa_context_exit_daemon(c); + pa_operation_unref(pa_context_exit_daemon(c, NULL, NULL)); drain(); case LIST: From b008941f821785b89f0b8914d4e08ee9c6ee97a5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 22:41:20 +0000 Subject: [PATCH 0439/1514] fix moddir git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@532 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index ed97f4905..5581d77ed 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,8 +47,8 @@ AM_CFLAGS = -I$(top_srcdir)/src AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -#AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" -AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" +AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" +#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" From 31a027b78b5081903ecdde5cff1b42770c93b075 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:29:46 +0000 Subject: [PATCH 0440/1514] change calls of pa_context_connect() to pass flags arugment correctly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@533 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- src/utils/pactl.c | 2 +- src/utils/paplay.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 4e126c8ad..6efc3a47c 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -509,7 +509,7 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect(context, server, 1, NULL); + pa_context_connect(context, server, 0, NULL); /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 86c4e7be1..907746aad 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -752,7 +752,7 @@ int main(int argc, char *argv[]) { } pa_context_set_state_callback(context, context_state_callback, NULL); - pa_context_connect(context, server, 1, NULL); + pa_context_connect(context, server, 0, NULL); if (pa_mainloop_run(m, &ret) < 0) { fprintf(stderr, "pa_mainloop_run() failed.\n"); diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 5f985ee9d..4efb4cf66 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -352,7 +352,7 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect(context, server, 1, NULL); + pa_context_connect(context, server, 0, NULL); /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { From a8e85ba688db823ef79ab47b6b6c97214b1c417e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:30:15 +0000 Subject: [PATCH 0441/1514] remove a superfluous log line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@534 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-native.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 1bca1c1ed..e73ff761a 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -585,7 +585,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { } if (pa_memblockq_peek(s->memblockq, chunk) < 0) { - pa_log(__FILE__": peek: failure\n"); +/* pa_log(__FILE__": peek: failure\n"); */ return -1; } From 0858ef9bed00bf9cd14062e3980e495a01dafa66 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:30:53 +0000 Subject: [PATCH 0442/1514] fix yet another pa_context_connect() occurance with regards to the flags parameter git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@535 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/sync-playback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/sync-playback.c b/src/tests/sync-playback.c index 5df790c9a..4ac65c2f4 100644 --- a/src/tests/sync-playback.c +++ b/src/tests/sync-playback.c @@ -175,7 +175,7 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); - pa_context_connect(context, NULL, 1, NULL); + pa_context_connect(context, NULL, 0, NULL); if (pa_mainloop_run(m, &ret) < 0) fprintf(stderr, "pa_mainloop_run() failed.\n"); From 2bdc07e2eabd791e48112593e0cec8baaa38a2fa Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:31:38 +0000 Subject: [PATCH 0443/1514] add validity check for the "server" parameter of pa_context_connect() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@536 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/polyp/context.c b/src/polyp/context.c index 2cb9e7e38..63acf19fc 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -624,6 +624,7 @@ int pa_context_connect( PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(c, !(flags & ~PA_CONTEXT_NOAUTOSPAWN), PA_ERR_INVALID); + PA_CHECK_VALIDITY(c, !server || *server, PA_ERR_INVALID); if (!server) server = c->conf->default_server; From d48912ba04e30de6d997712c8c2e41664cd70484 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:32:12 +0000 Subject: [PATCH 0444/1514] improve error checking in simple API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@537 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/simple.c | 90 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/src/polyp/simple.c b/src/polyp/simple.c index 8a20c2239..eabcf1eaf 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -37,6 +37,14 @@ #include "simple.h" +#define CHECK_VALIDITY_RETURN_ANY(rerror, expression, error, ret) do { \ +if (!(expression)) { \ + if (rerror) \ + *(rerror) = error; \ + return ret; \ + } \ +} while(0); + struct pa_simple { pa_mainloop *mainloop; pa_context *context; @@ -126,10 +134,14 @@ pa_simple* pa_simple_new( int *rerror) { pa_simple *p; - int error = PA_ERR_INTERNAL; - assert(ss && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD)); + int error = PA_ERR_INTERNAL, r; - p = pa_xmalloc(sizeof(pa_simple)); + CHECK_VALIDITY_RETURN_ANY(rerror, !server || *server, PA_ERR_INVALID, NULL); + CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL); + CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL); + CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL); + + p = pa_xnew(pa_simple, 1); p->context = NULL; p->stream = NULL; p->mainloop = pa_mainloop_new(); @@ -143,21 +155,31 @@ pa_simple* pa_simple_new( if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name))) goto fail; - pa_context_connect(p->context, server, 1, NULL); - + if (pa_context_connect(p->context, server, 0, NULL) < 0) { + error = pa_context_errno(p->context); + goto fail; + } + /* Wait until the context is ready */ while (pa_context_get_state(p->context) != PA_CONTEXT_READY) { if (iterate(p, 1, &error) < 0) goto fail; } - if (!(p->stream = pa_stream_new(p->context, stream_name, ss, NULL))) + if (!(p->stream = pa_stream_new(p->context, stream_name, ss, NULL))) { + error = pa_context_errno(p->context); goto fail; + } if (dir == PA_STREAM_PLAYBACK) - pa_stream_connect_playback(p->stream, dev, attr, 0, NULL, NULL); + r = pa_stream_connect_playback(p->stream, dev, attr, 0, NULL, NULL); else - pa_stream_connect_record(p->stream, dev, attr, 0); + r = pa_stream_connect_record(p->stream, dev, attr, 0); + + if (r < 0) { + error = pa_context_errno(p->context); + goto fail; + } /* Wait until the stream is ready */ while (pa_stream_get_state(p->stream) != PA_STREAM_READY) { @@ -190,7 +212,10 @@ void pa_simple_free(pa_simple *s) { } int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) { - assert(p && data && p->direction == PA_STREAM_PLAYBACK); + assert(p); + assert(data); + + CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); if (p->dead) { if (rerror) @@ -222,8 +247,11 @@ int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) { } int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { - assert(p && data && p->direction == PA_STREAM_RECORD); + assert(p); + assert(data); + CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1); + if (p->dead) { if (rerror) *rerror = pa_context_errno(p->context); @@ -273,14 +301,20 @@ int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { static void drain_or_flush_complete(pa_stream *s, int success, void *userdata) { pa_simple *p = userdata; - assert(s && p); + + assert(s); + assert(p); + if (!success) p->dead = 1; } int pa_simple_drain(pa_simple *p, int *rerror) { pa_operation *o; - assert(p && p->direction == PA_STREAM_PLAYBACK); + + assert(p); + + CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); if (p->dead) { if (rerror) @@ -289,7 +323,11 @@ int pa_simple_drain(pa_simple *p, int *rerror) { return -1; } - o = pa_stream_drain(p->stream, drain_or_flush_complete, p); + if (!(o = pa_stream_drain(p->stream, drain_or_flush_complete, p))) { + if (rerror) + *rerror = pa_context_errno(p->context); + return -1; + } while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { if (iterate(p, 1, rerror) < 0) { @@ -309,7 +347,9 @@ int pa_simple_drain(pa_simple *p, int *rerror) { static void latency_complete(pa_stream *s, const pa_latency_info *l, void *userdata) { pa_simple *p = userdata; - assert(s && p); + + assert(s); + assert(p); if (!l) p->dead = 1; @@ -323,7 +363,10 @@ static void latency_complete(pa_stream *s, const pa_latency_info *l, void *userd pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) { pa_operation *o; - assert(p && p->direction == PA_STREAM_PLAYBACK); + + assert(p); + + CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); if (p->dead) { if (rerror) @@ -333,7 +376,11 @@ pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) { } p->latency = 0; - o = pa_stream_get_latency_info(p->stream, latency_complete, p); + if (!(o = pa_stream_get_latency_info(p->stream, latency_complete, p))) { + if (rerror) + *rerror = pa_context_errno(p->context); + return (pa_usec_t) -1; + } while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { @@ -354,7 +401,10 @@ pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) { int pa_simple_flush(pa_simple *p, int *rerror) { pa_operation *o; - assert(p && p->direction == PA_STREAM_PLAYBACK); + + assert(p); + + CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); if (p->dead) { if (rerror) @@ -363,7 +413,11 @@ int pa_simple_flush(pa_simple *p, int *rerror) { return -1; } - o = pa_stream_flush(p->stream, drain_or_flush_complete, p); + if (!(o = pa_stream_flush(p->stream, drain_or_flush_complete, p))) { + if (rerror) + *rerror = pa_context_errno(p->context); + return -1; + } while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { if (iterate(p, 1, rerror) < 0) { From f5e8953d02283ae0adeda9474bb7d274aad528fa Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:32:44 +0000 Subject: [PATCH 0445/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@538 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/todo b/doc/todo index 1fc55df96..35401abb1 100644 --- a/doc/todo +++ b/doc/todo @@ -8,7 +8,7 @@ Fixes: - improve module-oss-mmap latency measurement - module-tunnel: improve latency calculation - make alsa modules use mmap -- better validity checking in libpolyp and protocol-{native,esound} +- better validity checking in protocol-{native,esound} - don't build ipv4 and ipv6 modules seperately - change pa_log to not require \n - proper use of memcpy in procotol-esound.c so we don't get alignment problems From 56ce62a020c4a0261a72518ac950e1eeb04c206b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:40:49 +0000 Subject: [PATCH 0446/1514] build dllmain.c only on win32 (makes gcc shut up a little more) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@539 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 5581d77ed..d3a10a3b6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -342,7 +342,6 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ polypcore/authkey.c polypcore/authkey.h \ polypcore/conf-parser.c polypcore/conf-parser.h \ - polypcore/dllmain.c \ polypcore/dynarray.c polypcore/dynarray.h \ polypcore/gccmacro.h \ polypcore/idxset.c polypcore/idxset.h \ @@ -369,6 +368,11 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ polypcore/winsock.h \ polypcore/xmalloc.c polypcore/xmalloc.h +if OS_IS_WIN32 +libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ + polypcore/dllmain.c +endif + if HAVE_X11 libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ polyp/client-conf-x11.c polyp/client-conf-x11.h \ @@ -484,7 +488,6 @@ libpolypcore_la_SOURCES += \ polypcore/core.c polypcore/core.h \ polypcore/core-scache.c polypcore/core-scache.h \ polypcore/core-subscribe.c polypcore/core-subscribe.h \ - polypcore/dllmain.c \ polypcore/dynarray.c polypcore/dynarray.h \ polypcore/endianmacros.h \ polypcore/g711.c polypcore/g711.h \ @@ -523,6 +526,11 @@ libpolypcore_la_SOURCES += \ polypcore/winsock.h \ polypcore/xmalloc.c polypcore/xmalloc.h +if OS_IS_WIN32 +libpolypcore_la_SOURCES += \ + polypcore/dllmain.c +endif + libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) libpolypcore_la_LDFLAGS = -avoid-version libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) From 9bcb4134137902b886ae4debe34f2d5c372c177b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:47:46 +0000 Subject: [PATCH 0447/1514] fix snd_pcm_hw_params_set_rate_near() usage git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@540 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 8318f9456..68e9f9751 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -38,6 +38,8 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 int ret = -1; snd_pcm_uframes_t buffer_size; snd_pcm_hw_params_t *hwparams = NULL; + unsigned int r = ss->rate; + static const snd_pcm_format_t format_trans[] = { [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8, [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW, @@ -53,12 +55,15 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 snd_pcm_hw_params_any(pcm_handle, hwparams) < 0 || snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 || snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[ss->format]) < 0 || - snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &ss->rate, NULL) < 0 || + snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL) < 0 || snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss->channels) < 0 || (*periods > 0 && snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, periods, NULL) < 0) || (*period_size > 0 && snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL) < 0) || snd_pcm_hw_params(pcm_handle, hwparams) < 0) goto finish; + + if (ss->rate != r) + pa_log_info(__FILE__": device doesn't support %u Hz, changed to %u Hz.\n", ss->rate, r); if (snd_pcm_prepare(pcm_handle) < 0) goto finish; From 1506c15a8ea8fd59bf97c5d41a0a99d59f86c656 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:50:46 +0000 Subject: [PATCH 0448/1514] build defer() function in src/polyp/mainloop-signal.c only on win32 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@541 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/mainloop-signal.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index e474f4617..008043240 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -91,17 +91,16 @@ static void dispatch(pa_mainloop_api*a, int sig) { } } +#ifdef OS_IS_WIN32 static void defer(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event*e, PA_GCC_UNUSED void *userdata) { ssize_t r; int sig; unsigned int sigs; -#ifdef OS_IS_WIN32 EnterCriticalSection(&crit); sigs = waiting_signals; waiting_signals = 0; LeaveCriticalSection(&crit); -#endif while (sigs) { if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { @@ -119,6 +118,7 @@ static void defer(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event*e, PA_GCC_UNUS sigs--; } } +#endif static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, PA_GCC_UNUSED void *userdata) { ssize_t r; @@ -179,8 +179,7 @@ void pa_signal_done(void) { while (signals) pa_signal_free(signals); - - + #ifndef OS_IS_WIN32 api->io_free(io_event); io_event = NULL; From cae2d8007650ac3bf9501177a389b69be7ae0eab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:58:51 +0000 Subject: [PATCH 0449/1514] disable SIGPIPE before calling pa_core_new(), this way the warning message is not printed git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@542 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 638c2f3fd..3124ad1d0 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -357,6 +357,10 @@ int main(int argc, char *argv[]) { valid_pid_file = 1; } +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif + mainloop = pa_mainloop_new(); assert(mainloop); @@ -367,17 +371,6 @@ int main(int argc, char *argv[]) { assert(r == 0); pa_signal_new(SIGINT, signal_callback, c); pa_signal_new(SIGTERM, signal_callback, c); -#ifdef SIGPIPE - signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef OS_IS_WIN32 - defer = pa_mainloop_get_api(mainloop)->defer_new(pa_mainloop_get_api(mainloop), message_cb, NULL); - assert(defer); -#endif - - if (conf->daemonize) - c->running_as_daemon = 1; #ifdef SIGUSR1 pa_signal_new(SIGUSR1, signal_callback, c); @@ -388,6 +381,14 @@ int main(int argc, char *argv[]) { #ifdef SIGHUP pa_signal_new(SIGHUP, signal_callback, c); #endif + +#ifdef OS_IS_WIN32 + defer = pa_mainloop_get_api(mainloop)->defer_new(pa_mainloop_get_api(mainloop), message_cb, NULL); + assert(defer); +#endif + + if (conf->daemonize) + c->running_as_daemon = 1; oil_init(); From 86124abfe22016315729eebdabb280137480fbc5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Feb 2006 23:59:13 +0000 Subject: [PATCH 0450/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@543 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 35401abb1..10a64ea59 100644 --- a/doc/todo +++ b/doc/todo @@ -12,7 +12,6 @@ Fixes: - don't build ipv4 and ipv6 modules seperately - change pa_log to not require \n - proper use of memcpy in procotol-esound.c so we don't get alignment problems -- sigpipe Features: - add radio module From 893204fd5789acff9ca03fe4d46beec5d55a6aa4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 00:14:25 +0000 Subject: [PATCH 0451/1514] add hw volume control for module-oss-mmap git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@544 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss-mmap.c | 32 ++++++++++++++++++++++++++++++- src/modules/module-oss.c | 20 ++----------------- src/modules/oss-util.c | 36 +++++++++++++++++++++++++++++++++++ src/modules/oss-util.h | 4 ++++ 4 files changed, 73 insertions(+), 19 deletions(-) diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 80c762f11..617e51e28 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -221,6 +221,30 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { return pa_bytes_to_usec(u->out_fill, &s->sample_spec); } +static int sink_get_hw_volume(pa_sink *s) { + struct userdata *u = s->userdata; + + if (pa_oss_get_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + pa_log_info(__FILE__": device doesn't support reading mixer settings: %s\n", strerror(errno)); + s->get_hw_volume = NULL; + return -1; + } + + return 0; +} + +static int sink_set_hw_volume(pa_sink *s) { + struct userdata *u = s->userdata; + + if (pa_oss_set_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + pa_log_info(__FILE__": device doesn't support writing mixer settings: %s\n", strerror(errno)); + s->set_hw_volume = NULL; + return -1; + } + + return 0; +} + int pa__init(pa_core *c, pa_module*m) { struct audio_buf_info info; struct userdata *u = NULL; @@ -275,7 +299,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - pa_log(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (nfrags >= 2 && frag_size >= 1) if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0) @@ -338,6 +362,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec, NULL); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; + u->sink->get_hw_volume = sink_get_hw_volume; + u->sink->set_hw_volume = sink_set_hw_volume; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'", p); @@ -365,6 +391,10 @@ int pa__init(pa_core *c, pa_module*m) { assert(u->io_event); pa_modargs_free(ma); + + /* Read mixer settings */ + if (u->sink) + sink_get_hw_volume(u->sink); return 0; diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index fe43c45e5..34743a1d4 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -255,41 +255,25 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { static int sink_get_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; - char cv[PA_CVOLUME_SNPRINT_MAX]; - unsigned vol; - if (ioctl(u->fd, SOUND_MIXER_READ_PCM, &vol) < 0) { + if (pa_oss_get_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { pa_log_info(__FILE__": device doesn't support reading mixer settings: %s\n", strerror(errno)); s->get_hw_volume = NULL; return -1; } - s->hw_volume.values[0] = ((vol & 0xFF) * PA_VOLUME_NORM) / 100; - - if ((s->hw_volume.channels = s->sample_spec.channels) >= 2) - s->hw_volume.values[1] = (((vol >> 8) & 0xFF) * PA_VOLUME_NORM) / 100; - - pa_log_info(__FILE__": Read mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), &s->hw_volume)); return 0; } static int sink_set_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; - char cv[PA_CVOLUME_SNPRINT_MAX]; - unsigned vol; - vol = (s->hw_volume.values[0]*100)/PA_VOLUME_NORM; - - if (s->sample_spec.channels >= 2) - vol |= ((s->hw_volume.values[1]*100)/PA_VOLUME_NORM) << 8; - - if (ioctl(u->fd, SOUND_MIXER_WRITE_PCM, &vol) < 0) { + if (pa_oss_set_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { pa_log_info(__FILE__": device doesn't support writing mixer settings: %s\n", strerror(errno)); s->set_hw_volume = NULL; return -1; } - pa_log_info(__FILE__": Wrote mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), &s->hw_volume)); return 0; } diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index e9a133f5d..597d16d7e 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -166,3 +166,39 @@ int pa_oss_set_fragments(int fd, int nfrags, int frag_size) { return 0; } + +int pa_oss_get_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { + char cv[PA_CVOLUME_SNPRINT_MAX]; + unsigned vol; + + assert(fd >= 0); + assert(ss); + assert(volume); + + if (ioctl(fd, SOUND_MIXER_READ_PCM, &vol) < 0) + return -1; + + volume->values[0] = ((vol & 0xFF) * PA_VOLUME_NORM) / 100; + + if ((volume->channels = ss->channels) >= 2) + volume->values[1] = (((vol >> 8) & 0xFF) * PA_VOLUME_NORM) / 100; + + pa_log_debug(__FILE__": Read mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), volume)); + return 0; +} + +int pa_oss_set_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume) { + char cv[PA_CVOLUME_SNPRINT_MAX]; + unsigned vol; + + vol = (volume->values[0]*100)/PA_VOLUME_NORM; + + if (ss->channels >= 2) + vol |= ((volume->values[1]*100)/PA_VOLUME_NORM) << 8; + + if (ioctl(fd, SOUND_MIXER_WRITE_PCM, &vol) < 0) + return -1; + + pa_log_debug(__FILE__": Wrote mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), volume)); + return 0; +} diff --git a/src/modules/oss-util.h b/src/modules/oss-util.h index 6b2746ccd..d8c36c567 100644 --- a/src/modules/oss-util.h +++ b/src/modules/oss-util.h @@ -23,10 +23,14 @@ ***/ #include +#include int pa_oss_open(const char *device, int *mode, int* pcaps); int pa_oss_auto_format(int fd, pa_sample_spec *ss); int pa_oss_set_fragments(int fd, int frags, int frag_size); +int pa_oss_get_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume); +int pa_oss_set_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume); + #endif From f1a0ee78bf471bb271f9b05333da88e3621109bc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 00:16:52 +0000 Subject: [PATCH 0452/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@545 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/todo b/doc/todo index 10a64ea59..2a9c4bb2e 100644 --- a/doc/todo +++ b/doc/todo @@ -21,7 +21,7 @@ Features: - add support for auth using SCM_CREDENTIALS - include hw description in sink/source info - use scatter/gather io for sockets -- hw volume support for alsa, oss-mmap, windows, solaris +- hw volume support for alsa, windows - notifcation on hw volume change - source volume control - deal with underflows reported by OSS/ALSA properly From 4f511bb7f0102b22862294ff4664ee07c4f6b9ca Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 00:37:22 +0000 Subject: [PATCH 0453/1514] * Get rid of libpolyp-mainloop * Remove pkg-config file of polyplib-error git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@546 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- configure.ac | 2 -- polyplib-error.pc.in | 10 ---------- polyplib-mainloop.pc.in | 10 ---------- src/Makefile.am | 40 +++++++++++++++++----------------------- 5 files changed, 18 insertions(+), 46 deletions(-) delete mode 100644 polyplib-error.pc.in delete mode 100644 polyplib-mainloop.pc.in diff --git a/Makefile.am b/Makefile.am index 9705d45d0..d8032baa5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ MAINTAINERCLEANFILES = noinst_DATA = pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-browse.pc +pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-browse.pc if HAVE_GLIB20 pkgconfig_DATA += \ diff --git a/configure.ac b/configure.ac index 5ffea5ef2..76b964254 100644 --- a/configure.ac +++ b/configure.ac @@ -398,9 +398,7 @@ Makefile src/Makefile polyplib.pc polyplib-simple.pc -polyplib-mainloop.pc polyplib-browse.pc -polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile diff --git a/polyplib-error.pc.in b/polyplib-error.pc.in deleted file mode 100644 index 45f69dbca..000000000 --- a/polyplib-error.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include - -Name: polyplib-error -Description: Error library for the polypaudio sound daemon -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-error-@PA_MAJORMINOR@ -Cflags: -D_REENTRANT -I${includedir} diff --git a/polyplib-mainloop.pc.in b/polyplib-mainloop.pc.in deleted file mode 100644 index ab9b3e698..000000000 --- a/polyplib-mainloop.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include - -Name: polyplib-mainloop -Description: Main loop support for polypaudio -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-mainloop-@PA_MAJORMINOR@ -Cflags: -D_REENTRANT -I${includedir} diff --git a/src/Makefile.am b/src/Makefile.am index d3a10a3b6..1a179359b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -141,17 +141,17 @@ endif bin_SCRIPTS = esdcompat.sh pacat_SOURCES = utils/pacat.c -pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la pacat_CFLAGS = $(AM_CFLAGS) pacat_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) paplay_SOURCES = utils/paplay.c -paplay_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) +paplay_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) paplay_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pactl_SOURCES = utils/pactl.c -pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) +pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -166,7 +166,7 @@ pax11publish_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la $(X_PRE_LIBS) -lX11 pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pabrowse_SOURCES = utils/pabrowse.c -pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la +pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la pabrowse_CFLAGS = $(AM_CFLAGS) pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -202,7 +202,7 @@ endif mainloop_test_SOURCES = tests/mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) -mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-@PA_MAJORMINOR@.la +mainloop_test_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mcalign_test_SOURCES = tests/mcalign-test.c @@ -211,12 +211,12 @@ mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la mcalign_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pacat_simple_SOURCES = tests/pacat-simple.c -pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la pacat_simple_CFLAGS = $(AM_CFLAGS) pacat_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) parec_simple_SOURCES = tests/parec-simple.c -parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la parec_simple_CFLAGS = $(AM_CFLAGS) parec_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -232,12 +232,12 @@ voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) cpulimit_test_SOURCES = tests/cpulimit-test.c daemon/cpulimit.c daemon/cpulimit.h cpulimit_test_CFLAGS = $(AM_CFLAGS) -cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolypcore.la +cpulimit_test_LDADD = $(AM_LDADD) libpolypcore.la cpulimit_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) cpulimit_test2_SOURCES = tests/cpulimit-test.c daemon/cpulimit.c daemon/cpulimit.h cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 -cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop-@PA_MAJORMINOR@.la libpolypcore.la +cpulimit_test2_LDADD = $(AM_LDADD) libpolypcore.la cpulimit_test2_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) @@ -264,7 +264,7 @@ memblockq_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) memblockq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) sync_playback_SOURCES = tests/sync-playback.c -sync_playback_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +sync_playback_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la sync_playback_CFLAGS = $(AM_CFLAGS) sync_playback_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -300,7 +300,6 @@ endif lib_LTLIBRARIES = \ libpolyp-@PA_MAJORMINOR@.la \ - libpolyp-mainloop-@PA_MAJORMINOR@.la \ libpolyp-simple-@PA_MAJORMINOR@.la if HAVE_HOWL @@ -336,7 +335,10 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ polyp/stream.c polyp/stream.h \ polyp/subscribe.c polyp/subscribe.h \ polyp/sample.c polyp/sample.h \ - polyp/volume.c polyp/volume.h + polyp/volume.c polyp/volume.h \ + polyp/mainloop.c polyp/mainloop.h \ + polyp/mainloop-signal.c polyp/mainloop-signal.h \ + polypcore/poll.c polypcore/poll.h # Internal stuff that is shared with libpolypcore libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ @@ -393,17 +395,9 @@ libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(LIBASYNCNS_CFLAGS) libpolyp_@PA_MAJORMINOR@_la_LIBADD += $(LIBASYNCNS_LIBS) endif -libpolyp_mainloop_@PA_MAJORMINOR@_la_SOURCES = \ - polyp/mainloop.c polyp/mainloop.h \ - polyp/mainloop-signal.c polyp/mainloop-signal.h \ - polypcore/poll.c polypcore/poll.h -libpolyp_mainloop_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) -libpolyp_mainloop_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(WINSOCK_LIBS) -libpolyp_mainloop_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 - libpolyp_simple_@PA_MAJORMINOR@_la_SOURCES = polyp/simple.c polyp/simple.h libpolyp_simple_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) -libpolyp_simple_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la +libpolyp_simple_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la libpolyp_simple_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 libpolyp_browse_@PA_MAJORMINOR@_la_SOURCES = polyp/browser.c polyp/browser.h @@ -413,12 +407,12 @@ libpolyp_browse_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_SOURCES = polyp/glib-mainloop.h polyp/glib-mainloop.c libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) -libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB20_LIBS) +libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(GLIB20_LIBS) libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_SOURCES = polyp/glib-mainloop.h polyp/glib12-mainloop.c libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) -libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop-@PA_MAJORMINOR@.la $(GLIB12_LIBS) +libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(GLIB12_LIBS) libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 ################################### From c07928a32dd5041c272be2e85581cc5773f81577 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 00:37:49 +0000 Subject: [PATCH 0454/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@547 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/todo b/doc/todo index 2a9c4bb2e..2e0ad893f 100644 --- a/doc/todo +++ b/doc/todo @@ -3,6 +3,7 @@ Test: - module-combine - latency foo +- howl Fixes: - improve module-oss-mmap latency measurement @@ -26,7 +27,6 @@ Features: - source volume control - deal with underflows reported by OSS/ALSA properly - mute switch support (like ALSA does it) -- get rid of a seperate main loop lib Long term: - pass meta info for hearing impaired From 8c80dd63025251d4f73997f24c68fdbe318b1f52 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 01:08:53 +0000 Subject: [PATCH 0455/1514] * Don't build seperate ipv4/ipv6 versions of the protocol plugins * Instead try IPv6 and if that fails fall back to IPv4 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@548 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 35 ------------------------ src/modules/module-protocol-stub.c | 38 +++++++++----------------- src/polypcore/socket-server.c | 43 ++++++++++++++++++++++++------ src/polypcore/socket-server.h | 4 ++- 4 files changed, 51 insertions(+), 69 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 1a179359b..410fd7027 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -697,13 +697,9 @@ libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS modlib_LTLIBRARIES += \ module-cli.la \ module-cli-protocol-tcp.la \ - module-cli-protocol-tcp6.la \ module-simple-protocol-tcp.la \ - module-simple-protocol-tcp6.la \ module-esound-protocol-tcp.la \ - module-esound-protocol-tcp6.la \ module-native-protocol-tcp.la \ - module-native-protocol-tcp6.la \ module-native-protocol-fd.la \ module-sine.la \ module-combine.la \ @@ -712,7 +708,6 @@ modlib_LTLIBRARIES += \ module-null-sink.la \ module-esound-sink.la \ module-http-protocol-tcp.la \ - module-http-protocol-tcp6.la \ module-detect.la if HAVE_AF_UNIX @@ -792,18 +787,14 @@ endif SYMDEF_FILES = \ modules/module-cli-symdef.h \ modules/module-cli-protocol-tcp-symdef.h \ - modules/module-cli-protocol-tcp6-symdef.h \ modules/module-cli-protocol-unix-symdef.h \ modules/module-pipe-sink-symdef.h \ modules/module-pipe-source-symdef.h \ modules/module-simple-protocol-tcp-symdef.h \ - modules/module-simple-protocol-tcp6-symdef.h \ modules/module-simple-protocol-unix-symdef.h \ modules/module-esound-protocol-tcp-symdef.h \ - modules/module-esound-protocol-tcp6-symdef.h \ modules/module-esound-protocol-unix-symdef.h \ modules/module-native-protocol-tcp-symdef.h \ - modules/module-native-protocol-tcp6-symdef.h \ modules/module-native-protocol-unix-symdef.h \ modules/module-native-protocol-fd-symdef.h \ modules/module-sine-symdef.h \ @@ -819,7 +810,6 @@ SYMDEF_FILES = \ modules/module-lirc-symdef.h \ modules/module-mmkbd-evdev-symdef.h \ modules/module-http-protocol-tcp-symdef.h \ - modules/module-http-protocol-tcp6-symdef.h \ modules/module-http-protocol-unix-symdef.h \ modules/module-x11-bell-symdef.h \ modules/module-x11-publish-symdef.h \ @@ -844,11 +834,6 @@ module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $ module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la -module_simple_protocol_tcp6_la_SOURCES = modules/module-protocol-stub.c -module_simple_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) -module_simple_protocol_tcp6_la_LDFLAGS = -module -avoid-version -module_simple_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la - module_simple_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version @@ -865,11 +850,6 @@ module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CF module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la -module_cli_protocol_tcp6_la_SOURCES = modules/module-protocol-stub.c -module_cli_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) -module_cli_protocol_tcp6_la_LDFLAGS = -module -avoid-version -module_cli_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la - module_cli_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version @@ -882,11 +862,6 @@ module_http_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_ module_http_protocol_tcp_la_LDFLAGS = -module -avoid-version module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la -module_http_protocol_tcp6_la_SOURCES = modules/module-protocol-stub.c -module_http_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) -module_http_protocol_tcp6_la_LDFLAGS = -module -avoid-version -module_http_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la - module_http_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) module_http_protocol_unix_la_LDFLAGS = -module -avoid-version @@ -899,11 +874,6 @@ module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $ module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la -module_native_protocol_tcp6_la_SOURCES = modules/module-protocol-stub.c -module_native_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) -module_native_protocol_tcp6_la_LDFLAGS = -module -avoid-version -module_native_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la - module_native_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_unix_la_LDFLAGS = -module -avoid-version @@ -921,11 +891,6 @@ module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $ module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la -module_esound_protocol_tcp6_la_SOURCES = modules/module-protocol-stub.c -module_esound_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) -module_esound_protocol_tcp6_la_LDFLAGS = -module -avoid-version -module_esound_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la - module_esound_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index b69716cc7..f72a68a59 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -53,9 +53,6 @@ #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" #define SOCKET_USAGE "port= loopback=" -#elif defined(USE_TCP6_SOCKETS) -#define SOCKET_DESCRIPTION "(TCP/IPv6 sockets)" -#define SOCKET_USAGE "port= loopback=" #else #define SOCKET_DESCRIPTION "(UNIX sockets)" #define SOCKET_USAGE "socket=" @@ -71,8 +68,6 @@ #define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record", #if defined(USE_TCP_SOCKETS) #include "module-simple-protocol-tcp-symdef.h" - #elif defined(USE_TCP6_SOCKETS) - #include "module-simple-protocol-tcp6-symdef.h" #else #include "module-simple-protocol-unix-symdef.h" #endif @@ -88,8 +83,6 @@ #define MODULE_ARGUMENTS #ifdef USE_TCP_SOCKETS #include "module-cli-protocol-tcp-symdef.h" - #elif defined(USE_TCP6_SOCKETS) - #include "module-cli-protocol-tcp6-symdef.h" #else #include "module-cli-protocol-unix-symdef.h" #endif @@ -105,8 +98,6 @@ #define MODULE_ARGUMENTS #ifdef USE_TCP_SOCKETS #include "module-http-protocol-tcp-symdef.h" - #elif defined(USE_TCP6_SOCKETS) - #include "module-http-protocol-tcp6-symdef.h" #else #include "module-http-protocol-unix-symdef.h" #endif @@ -122,8 +113,6 @@ #define MODULE_ARGUMENTS "public", "cookie", #ifdef USE_TCP_SOCKETS #include "module-native-protocol-tcp-symdef.h" - #elif defined(USE_TCP6_SOCKETS) - #include "module-native-protocol-tcp6-symdef.h" #else #include "module-native-protocol-unix-symdef.h" #endif @@ -140,8 +129,6 @@ #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", #ifdef USE_TCP_SOCKETS #include "module-esound-protocol-tcp-symdef.h" - #elif defined(USE_TCP6_SOCKETS) - #include "module-esound-protocol-tcp6-symdef.h" #else #include "module-esound-protocol-unix-symdef.h" #endif @@ -156,7 +143,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) static const char* const valid_modargs[] = { MODULE_ARGUMENTS -#if defined(USE_TCP_SOCKETS) || defined(USE_TCP6_SOCKETS) +#if defined(USE_TCP_SOCKETS) "port", "loopback", #else @@ -167,7 +154,7 @@ static const char* const valid_modargs[] = { static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) { pa_socket_server *s; -#if defined(USE_TCP_SOCKETS) || defined(USE_TCP6_SOCKETS) +#if defined(USE_TCP_SOCKETS) int loopback = 1; uint32_t port = IPV4_PORT; @@ -181,13 +168,14 @@ static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) { return NULL; } -#ifdef USE_TCP6_SOCKETS - if (!(s = pa_socket_server_new_ipv6(c->mainloop, loopback ? (const uint8_t*) &in6addr_loopback : (const uint8_t*) &in6addr_any, port))) - return NULL; -#else - if (!(s = pa_socket_server_new_ipv4(c->mainloop, loopback ? INADDR_LOOPBACK : INADDR_ANY, port, TCPWRAP_SERVICE))) - return NULL; -#endif + + if (loopback) { + if (!(s = pa_socket_server_new_ip_loopback(c->mainloop, port, TCPWRAP_SERVICE))) + return NULL; + } else { + if (!(s = pa_socket_server_new_ip_any(c->mainloop, port, TCPWRAP_SERVICE))) + return NULL; + } #else int r; @@ -250,10 +238,10 @@ finish: void pa__done(pa_core *c, pa_module*m) { assert(c && m); -#if defined(USE_PROTOCOL_ESOUND) - if (remove (ESD_UNIX_SOCKET_NAME) != 0) +#if defined(USE_PROTOCOL_ESOUND) && !defined(USE_TCP_SOCKETS) + if (remove(ESD_UNIX_SOCKET_NAME) != 0) pa_log("%s: Failed to remove %s : %s.\n", __FILE__, ESD_UNIX_SOCKET_NAME, strerror (errno)); - if (remove (ESD_UNIX_SOCKET_DIR) != 0) + if (remove(ESD_UNIX_SOCKET_DIR) != 0) pa_log("%s: Failed to remove %s : %s.\n", __FILE__, ESD_UNIX_SOCKET_DIR, strerror (errno)); #endif diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index d1646984c..5f84911d7 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -101,18 +101,18 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U #ifdef HAVE_LIBWRAP - if (s->type == SOCKET_SERVER_IPV4 && s->tcpwrap_service) { + if (s->tcpwrap_service) { struct request_info req; request_init(&req, RQ_DAEMON, s->tcpwrap_service, RQ_FILE, nfd, NULL); fromhost(&req); if (!hosts_access(&req)) { - pa_log(__FILE__": TCP connection refused by tcpwrap.\n"); + pa_log_warn(__FILE__": TCP connection refused by tcpwrap.\n"); close(nfd); goto finish; } - pa_log(__FILE__": TCP connection accepted by tcpwrap.\n"); + pa_log_info(__FILE__": TCP connection accepted by tcpwrap.\n"); } #endif @@ -221,7 +221,7 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address assert(m && port); if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(PF_INET): %s\n", strerror(errno)); goto fail; } @@ -261,7 +261,7 @@ fail: return NULL; } -pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port) { +pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, const char *tcpwrap_service) { pa_socket_server *ss; int fd = -1; struct sockaddr_in6 sa; @@ -270,7 +270,7 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad assert(m && port); if ((fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(PF_INET6): %s\n", strerror(errno)); goto fail; } @@ -296,9 +296,11 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad goto fail; } - if ((ss = pa_socket_server_new(m, fd))) + if ((ss = pa_socket_server_new(m, fd))) { ss->type = SOCKET_SERVER_IPV6; - + ss->tcpwrap_service = pa_xstrdup(tcpwrap_service); + } + return ss; fail: @@ -308,6 +310,31 @@ fail: return NULL; } +pa_socket_server* pa_socket_server_new_ip_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { + pa_socket_server *s; + + assert(m); + assert(port > 0); + + if (!(s = pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, tcpwrap_service))) + s = pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, tcpwrap_service); + + return s; +} + +pa_socket_server* pa_socket_server_new_ip_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { + pa_socket_server *s; + + assert(m); + assert(port > 0); + + if (!(s = pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service))) + s = pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service); + + return s; +} + + static void socket_server_free(pa_socket_server*s) { assert(s); close(s->fd); diff --git a/src/polypcore/socket-server.h b/src/polypcore/socket-server.h index 6bb834276..d11cee495 100644 --- a/src/polypcore/socket-server.h +++ b/src/polypcore/socket-server.h @@ -33,7 +33,9 @@ typedef struct pa_socket_server pa_socket_server; pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd); pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename); pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service); -pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port); +pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ip_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ip_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); void pa_socket_server_unref(pa_socket_server*s); pa_socket_server* pa_socket_server_ref(pa_socket_server *s); From 36c8861db6b8188b844d97b0910d32051f2530d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 01:09:22 +0000 Subject: [PATCH 0456/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@549 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 2e0ad893f..2c7f28b28 100644 --- a/doc/todo +++ b/doc/todo @@ -10,7 +10,6 @@ Fixes: - module-tunnel: improve latency calculation - make alsa modules use mmap - better validity checking in protocol-{native,esound} -- don't build ipv4 and ipv6 modules seperately - change pa_log to not require \n - proper use of memcpy in procotol-esound.c so we don't get alignment problems From a10257d680d178d493ccae7a2f273ee6987c2dae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 01:22:42 +0000 Subject: [PATCH 0457/1514] fix pacat git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@550 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 64 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 6efc3a47c..43e671444 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -80,7 +80,12 @@ static void do_stream_write(size_t length) { if (l > buffer_length) l = buffer_length; - pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE); + if (pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE) < 0) { + fprintf(stderr, "pa_stream_write() failed: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + return; + } + buffer_length -= l; buffer_index += l; @@ -112,12 +117,20 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); - pa_stream_peek(s, &data, &length); + if (pa_stream_peek(s, &data, &length) < 0) { + fprintf(stderr, "pa_stream_peek() failed: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + return; + } + assert(data && length); if (buffer) { fprintf(stderr, "Buffer overrun, dropping incoming data\n"); - pa_stream_drop(s); + if (pa_stream_drop(s) < 0) { + fprintf(stderr, "pa_stream_drop() failed: %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + } return; } @@ -159,15 +172,18 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_SETTING_NAME: break; - case PA_CONTEXT_READY: + case PA_CONTEXT_READY: { + int r; assert(c && !stream); if (verbose) fprintf(stderr, "Connection established.\n"); - stream = pa_stream_new(c, stream_name, &sample_spec, NULL); - assert(stream); + if (!(stream = pa_stream_new(c, stream_name, &sample_spec, NULL))) { + fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(c))); + goto fail; + } pa_stream_set_state_callback(stream, stream_state_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); @@ -175,11 +191,20 @@ static void context_state_callback(pa_context *c, void *userdata) { if (mode == PLAYBACK) { pa_cvolume cv; - pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume), NULL); - } else - pa_stream_connect_record(stream, device, NULL, 0); + if ((r = pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL)) < 0) { + fprintf(stderr, "pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(c))); + goto fail; + } + + } else { + if ((r = pa_stream_connect_record(stream, device, NULL, 0)) < 0) { + fprintf(stderr, "pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(c))); + goto fail; + } + } break; + } case PA_CONTEXT_TERMINATED: quit(0); @@ -188,8 +213,14 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_FAILED: default: fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c))); - quit(1); + goto fail; } + + return; + +fail: + quit(1); + } /* Connection draining complete */ @@ -216,8 +247,6 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { if (!(o = pa_context_drain(context, context_drain_complete, NULL))) pa_context_disconnect(context); else { - pa_operation_unref(o); - if (verbose) fprintf(stderr, "Draining connection to server.\n"); } @@ -241,9 +270,18 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even assert(buffer); if ((r = read(fd, buffer, l)) <= 0) { if (r == 0) { + pa_operation *o; + if (verbose) fprintf(stderr, "Got EOF.\n"); - pa_operation_unref(pa_stream_drain(stream, stream_drain_complete, NULL)); + + if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { + fprintf(stderr, "pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + return; + } + + pa_operation_unref(o); } else { fprintf(stderr, "read() failed: %s\n", strerror(errno)); quit(1); From 7e5123705a4811d168890e35cff2354922777c71 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 21 Feb 2006 16:35:12 +0000 Subject: [PATCH 0458/1514] Hardware volume support on Windows. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@551 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 3a8600c7d..2176e6e73 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -48,6 +48,8 @@ PA_MODULE_USAGE("sink_name= source_name= #define DEFAULT_SINK_NAME "wave_output" #define DEFAULT_SOURCE_NAME "wave_input" +#define WAVEOUT_MAX_VOLUME 0xFFFF + struct userdata { pa_sink *sink; pa_source *source; @@ -336,6 +338,42 @@ static void notify_source_cb(pa_source *s) { u->core->mainloop->defer_enable(u->defer, 1); } +static int sink_get_hw_volume_cb(pa_sink *s) { + struct userdata *u = s->userdata; + DWORD vol; + pa_volume_t left, right; + + if (waveOutGetVolume(u->hwo, &vol) != MMSYSERR_NOERROR) + return -1; + + left = (vol & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME; + right = ((vol >> 16) & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME; + + /* Windows supports > 2 channels, except for volume control */ + if (s->hw_volume.channels > 2) + pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, (left + right)/2); + + s->hw_volume.values[0] = left; + if (s->hw_volume.channels > 1) + s->hw_volume.values[1] = right; + + return 0; +} + +static int sink_set_hw_volume_cb(pa_sink *s) { + struct userdata *u = s->userdata; + DWORD vol; + + vol = s->hw_volume.values[0] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM; + if (s->hw_volume.channels > 1) + vol |= (s->hw_volume.values[0] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM) << 16; + + if (waveOutSetVolume(u->hwo, vol) != MMSYSERR_NOERROR) + return -1; + + return 0; +} + static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) { wf->wFormatTag = WAVE_FORMAT_PCM; @@ -455,6 +493,8 @@ int pa__init(pa_core *c, pa_module*m) { assert(u->sink); u->sink->notify = notify_sink_cb; u->sink->get_latency = sink_get_latency_cb; + u->sink->get_hw_volume = sink_get_hw_volume_cb; + u->sink->set_hw_volume = sink_set_hw_volume_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Windows waveOut PCM"); From 48b2e1ab966c14d9fc08fbadf7bcf0980de47523 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 21 Feb 2006 16:35:53 +0000 Subject: [PATCH 0459/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@552 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/todo b/doc/todo index 2c7f28b28..63da73ce2 100644 --- a/doc/todo +++ b/doc/todo @@ -21,7 +21,7 @@ Features: - add support for auth using SCM_CREDENTIALS - include hw description in sink/source info - use scatter/gather io for sockets -- hw volume support for alsa, windows +- hw volume support for alsa - notifcation on hw volume change - source volume control - deal with underflows reported by OSS/ALSA properly From 9d3dcefad1d052ce9cf7a7c769d008b72dad5879 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 20:28:41 +0000 Subject: [PATCH 0460/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@553 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 63da73ce2..e23233e69 100644 --- a/doc/todo +++ b/doc/todo @@ -26,6 +26,7 @@ Features: - source volume control - deal with underflows reported by OSS/ALSA properly - mute switch support (like ALSA does it) +- add listen-on paramater to protocol modules Long term: - pass meta info for hearing impaired From 13b421327483e6f97e5c6541815195f13778dbf2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 23:34:22 +0000 Subject: [PATCH 0461/1514] remove left-over log line in protocol-esound.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@554 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 4a5dd7733..8a0a33560 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -186,7 +186,6 @@ static void connection_free(struct connection *c) { if (c->sink_input) { pa_sink_input_disconnect(c->sink_input); - pa_log("disconnect\n"); pa_sink_input_unref(c->sink_input); } From 6169bd81aa405a4ef2632b6ceb26a7225118f7d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 23:34:50 +0000 Subject: [PATCH 0462/1514] add new utility function pa_endswith() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@555 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/util.c | 18 +++++++++++++++++- src/polypcore/util.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/polypcore/util.c b/src/polypcore/util.c index a53c36bc6..2ae94d25a 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -1092,12 +1092,28 @@ char *pa_get_fqdn(char *s, size_t l) { /* Returns nonzero when *s starts with *pfx */ int pa_startswith(const char *s, const char *pfx) { size_t l; - assert(s && pfx); + + assert(s); + assert(pfx); + l = strlen(pfx); return strlen(s) >= l && strncmp(s, pfx, l) == 0; } +/* Returns nonzero when *s ends with *sfx */ +int pa_endswith(const char *s, const char *sfx) { + size_t l1, l2; + + assert(s); + assert(sfx); + + l1 = strlen(s); + l2 = strlen(sfx); + + return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0; +} + /* if fn is null return the polypaudio run time path in s (/tmp/polypaudio) * if fn is non-null and starts with / return fn in s * otherwise append fn to the run time path and return it in s */ diff --git a/src/polypcore/util.h b/src/polypcore/util.h index 14f763a3f..af4e14c85 100644 --- a/src/polypcore/util.h +++ b/src/polypcore/util.h @@ -88,6 +88,7 @@ char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength); size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength); int pa_startswith(const char *s, const char *pfx); +int pa_endswith(const char *s, const char *sfx); char *pa_runtime_path(const char *fn, char *s, size_t l); From 5014db91d55ce1b4f6b3691f6fd75078da588a40 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 23:40:07 +0000 Subject: [PATCH 0463/1514] include hw description gathered from /dev/sndstat in sink/source description string git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@556 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss.c | 22 +++++++++++-- src/modules/oss-util.c | 69 ++++++++++++++++++++++++++++++++++++++++ src/modules/oss-util.h | 2 ++ 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 34743a1d4..0a3c61433 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -287,7 +287,10 @@ int pa__init(pa_core *c, pa_module*m) { int record = 1, playback = 1; pa_sample_spec ss; pa_modargs *ma = NULL; - assert(c && m); + char hwdesc[64]; + + assert(c); + assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments.\n"); @@ -322,6 +325,11 @@ int pa__init(pa_core *c, pa_module*m) { if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, NULL)) < 0) goto fail; + if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0) + pa_log_info(__FILE__": hardware name is '%s'.\n", hwdesc); + else + hwdesc[0] = 0; + pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (nfrags >= 2 && frag_size >= 1) @@ -361,7 +369,11 @@ int pa__init(pa_core *c, pa_module*m) { u->source->notify = source_notify_cb; u->source->get_latency = source_get_latency_cb; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p); + u->source->description = pa_sprintf_malloc("Open Sound System PCM on '%s'%s%s%s", + p, + hwdesc[0] ? " (" : "", + hwdesc[0] ? hwdesc : "", + hwdesc[0] ? ")" : ""); } else u->source = NULL; @@ -373,7 +385,11 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->set_hw_volume = sink_set_hw_volume; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p); + u->sink->description = pa_sprintf_malloc("Open Sound System PCM on '%s'%s%s%s", + p, + hwdesc[0] ? " (" : "", + hwdesc[0] ? hwdesc : "", + hwdesc[0] ? ")" : ""); } else u->sink = NULL; diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 597d16d7e..9fb5d38a9 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -202,3 +202,72 @@ int pa_oss_set_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume pa_log_debug(__FILE__": Wrote mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), volume)); return 0; } + +int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { + FILE *f; + const char *e = NULL; + int n, r = -1; + int b = 0; + + if (strncmp(dev, "/dev/dsp", 8) == 0) + e = dev+8; + else if (strncmp(dev, "/dev/adsp", 9) == 0) + e = dev+9; + else + return -1; + + if (*e == 0) + n = 0; + else if (*e >= '0' && *e <= '9' && *(e+1) == 0) + n = *e - '0'; + else + return -1; + + if (!(f = fopen("/dev/sndstat", "r")) && + !(f = fopen("/proc/sndstat", "r")) && + !(f = fopen("/proc/asound/oss/sndstat", "r"))) { + + if (errno != ENOENT) + pa_log_warn(__FILE__": failed to open OSS sndstat device: %s\n", strerror(errno)); + + return -1; + } + + while (!feof(f)) { + char line[64]; + int device; + + if (!fgets(line, sizeof(line), f)) + break; + + line[strcspn(line, "\r\n")] = 0; + + if (!b) { + b = strcmp(line, "Audio devices:") == 0; + continue; + } + + if (line[0] == 0) + break; + + if (sscanf(line, "%i: ", &device) != 1) + continue; + + if (device == n) { + char *k = strchr(line, ':'); + assert(k); + k++; + k += strspn(k, " "); + + if (pa_endswith(k, " (DUPLEX)")) + k[strlen(k)-9] = 0; + + pa_strlcpy(name, k, l); + r = 0; + break; + } + } + + fclose(f); + return r; +} diff --git a/src/modules/oss-util.h b/src/modules/oss-util.h index d8c36c567..3033c76fc 100644 --- a/src/modules/oss-util.h +++ b/src/modules/oss-util.h @@ -33,4 +33,6 @@ int pa_oss_set_fragments(int fd, int frags, int frag_size); int pa_oss_get_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume); int pa_oss_set_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume); +int pa_oss_get_hw_description(const char *dev, char *name, size_t l); + #endif From 8d882644be745509ee4cc1d02c8c524977195ebf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Feb 2006 23:56:46 +0000 Subject: [PATCH 0464/1514] add hw info to description for oss-mmap, too git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@557 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss-mmap.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 617e51e28..82f65a3c1 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -254,7 +254,10 @@ int pa__init(pa_core *c, pa_module*m) { int enable_bits = 0, zero = 0; int playback = 1, record = 1; pa_modargs *ma = NULL; - assert(c && m); + char hwdesc[64]; + + assert(c); + assert(m); m->userdata = u = pa_xmalloc0(sizeof(struct userdata)); u->module = m; @@ -294,6 +297,11 @@ int pa__init(pa_core *c, pa_module*m) { if ((u->fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0) goto fail; + if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0) + pa_log_info(__FILE__": hardware name is '%s'.\n", hwdesc); + else + hwdesc[0] = 0; + if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_REALTIME) || !(caps & DSP_CAP_TRIGGER)) { pa_log(__FILE__": OSS device not mmap capable.\n"); goto fail; @@ -331,7 +339,11 @@ int pa__init(pa_core *c, pa_module*m) { assert(u->source); u->source->userdata = u; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'", p); + u->source->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'%s%s%s", + p, + hwdesc[0] ? " (" : "", + hwdesc[0] ? hwdesc : "", + hwdesc[0] ? ")" : ""); u->in_memblocks = pa_xmalloc0(sizeof(pa_memblock *)*u->in_fragments); @@ -366,7 +378,11 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->set_hw_volume = sink_set_hw_volume; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'", p); + u->sink->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'%s%s%s", + p, + hwdesc[0] ? " (" : "", + hwdesc[0] ? hwdesc : "", + hwdesc[0] ? ")" : ""); u->out_memblocks = pa_xmalloc0(sizeof(struct memblock *)*u->out_fragments); From bf013f89104c1a0d5561ce89185c6acbe0a3a72e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 00:06:16 +0000 Subject: [PATCH 0465/1514] todo update - outline what i consider pre-0.8 and post-0.8 issues git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@558 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/doc/todo b/doc/todo index e23233e69..feac0c754 100644 --- a/doc/todo +++ b/doc/todo @@ -2,31 +2,36 @@ Test: - module-combine -- latency foo +- module-tunnel - howl Fixes: -- improve module-oss-mmap latency measurement -- module-tunnel: improve latency calculation -- make alsa modules use mmap - better validity checking in protocol-{native,esound} - change pa_log to not require \n - proper use of memcpy in procotol-esound.c so we don't get alignment problems +- latency api for native protocol +- add support for auth using SCM_CREDENTIALS +- use scatter/gather io for sockets +- notification on hw volume change +- source volume control +- mute switch support (like ALSA does it) +- add listen-on paramater to protocol modules +- module-oss-* love: + - deal with underflows propely + - improve latency measurement for mmap +- module-alsa-* love: + - volume control + - add hw driver name to sink/source description + - deal with underflows properly -Features: +Post 0.8: +- alsa mmap driver - add radio module - dbus/hal - polish for starting polypaudio as root/system-wide instance +- chroot() - add threading API -- add support for auth using SCM_CREDENTIALS -- include hw description in sink/source info -- use scatter/gather io for sockets -- hw volume support for alsa -- notifcation on hw volume change -- source volume control -- deal with underflows reported by OSS/ALSA properly -- mute switch support (like ALSA does it) -- add listen-on paramater to protocol modules +- module-tunnel: improve latency calculation Long term: - pass meta info for hearing impaired @@ -36,14 +41,3 @@ Backends for: - portaudio (semi-done) - sdl - OSS (esddsp style) - ------------------- - -Done: -- per-channel volume -- channel mapping ("left", "right", "rear", "subwoofer") -- hardware volume support -- alsa-lib -- remove "polyplib-" prefix -- add API for synchronizing multiple sinks/sources to a common clock -- absolutely indexed write()s from client From 6cd225010f3b740a7db95f4ca7dd051501fb55dc Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 22 Feb 2006 09:39:33 +0000 Subject: [PATCH 0466/1514] Remove polyplib-error and polyplib-mainloop for requirements. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@559 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyplib.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyplib.pc.in b/polyplib.pc.in index c79d98d4f..f495def2b 100644 --- a/polyplib.pc.in +++ b/polyplib.pc.in @@ -8,4 +8,4 @@ Description: Client interface to polypaudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpolyp-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib-error polyplib-mainloop +Requires: From cc2178e5c39f0c2da2d4d5dff14210d5934bcc32 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 22 Feb 2006 14:11:23 +0000 Subject: [PATCH 0467/1514] Support for setting volume on sources. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@560 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 1 + src/polyp/introspect.c | 55 +++++++++++++++++++++++++++++++++ src/polyp/introspect.h | 7 +++++ src/polypcore/cli-command.c | 54 +++++++++++++++++++++++++++++--- src/polypcore/core-def.h | 30 ++++++++++++++++++ src/polypcore/native-common.h | 2 ++ src/polypcore/pdispatch.c | 1 + src/polypcore/protocol-native.c | 36 ++++++++++++++------- src/polypcore/sink.h | 6 +--- src/polypcore/source.c | 51 ++++++++++++++++++++++++++++++ src/polypcore/source.h | 9 ++++++ 11 files changed, 232 insertions(+), 20 deletions(-) create mode 100644 src/polypcore/core-def.h diff --git a/src/Makefile.am b/src/Makefile.am index 410fd7027..f36630e76 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -425,6 +425,7 @@ polypcoreinclude_HEADERS = \ polypcore/cli-text.h \ polypcore/client.h \ polypcore/core.h \ + polypcore/core-def.h \ polypcore/core-scache.h \ polypcore/core-subscribe.h \ polypcore/conf-parser.h \ diff --git a/src/polyp/introspect.c b/src/polyp/introspect.c index 043d2076e..4fa238417 100644 --- a/src/polyp/introspect.c +++ b/src/polyp/introspect.c @@ -252,6 +252,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || + pa_tagstruct_get_cvolume(t, &i.volume) < 0 || pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 || pa_tagstruct_get_usec(t, &i.latency) < 0 || @@ -727,6 +728,60 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons return o; } +pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + assert(volume); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SOURCE_VOLUME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, idx); + pa_tagstruct_puts(t, NULL); + pa_tagstruct_put_cvolume(t, volume); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + + return o; +} + +pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + assert(name); + assert(volume); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SOURCE_VOLUME); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_cvolume(t, volume); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + + return o; +} + /** Sample Cache **/ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { diff --git a/src/polyp/introspect.h b/src/polyp/introspect.h index d4ff65fb4..d7fad9c44 100644 --- a/src/polyp/introspect.h +++ b/src/polyp/introspect.h @@ -84,6 +84,7 @@ typedef struct pa_source_info { pa_sample_spec sample_spec; /**< Sample spec of this source */ pa_channel_map channel_map; /**< Channel map \since 0.9 */ uint32_t owner_module; /**< Owning module index, or PA_INVALID_INDEX */ + pa_cvolume volume; /**< Volume of the source \since 0.8 */ uint32_t monitor_of_sink; /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */ const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */ pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */ @@ -213,6 +214,12 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name /** Set the volume of a sink input stream */ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); +/** Set the volume of a source device specified by its index \since 0.8 */ +pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); + +/** Set the volume of a source device specified by its name \since 0.8 */ +pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); + /** Memory block statistics */ typedef struct pa_stat_info { uint32_t memblock_total; /**< Currently allocated memory blocks */ diff --git a/src/polypcore/cli-command.c b/src/polypcore/cli-command.c index 6c9fc4b14..cd7993a8e 100644 --- a/src/polypcore/cli-command.c +++ b/src/polypcore/cli-command.c @@ -77,6 +77,7 @@ static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); @@ -114,6 +115,7 @@ static const struct command commands[] = { { "unload-module", pa_cli_command_unload, "Unload a module (args: index)", 2}, { "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3}, { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index|name, volume)", 3}, + { "set-source-volume", pa_cli_command_source_volume, "Set the volume of a source (args: index|name, volume)", 3}, { "set-default-sink", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2}, { "set-default-source", pa_cli_command_source_default, "Set the default source (args: index|name)", 2}, { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, @@ -376,6 +378,37 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb return 0; } +static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { + const char *n, *v; + pa_source *source; + uint32_t volume; + pa_cvolume cvolume; + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n"); + return -1; + } + + if (!(v = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); + return -1; + } + + if (pa_atou(v, &volume) < 0) { + pa_strbuf_puts(buf, "Failed to parse volume.\n"); + return -1; + } + + if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE, 1))) { + pa_strbuf_puts(buf, "No source found by this name or index.\n"); + return -1; + } + + pa_cvolume_set(&cvolume, source->sample_spec.channels, volume); + pa_source_set_volume(source, PA_MIXER_HARDWARE, &cvolume); + return 0; +} + static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const char *n; assert(c && t); @@ -633,7 +666,8 @@ static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { pa_module *m; - pa_sink *s; + pa_sink *sink; + pa_source *source; int nl; const char *p; uint32_t idx; @@ -667,8 +701,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G nl = 0; - for (s = pa_idxset_first(c->sinks, &idx); s; s = pa_idxset_next(c->sinks, &idx)) { - if (s->owner && s->owner->auto_unload) + for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) { + if (sink->owner && sink->owner->auto_unload) continue; if (!nl) { @@ -676,7 +710,19 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G nl = 1; } - pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", s->name, pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE))); + pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, PA_MIXER_HARDWARE))); + } + + for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) { + if (source->owner && source->owner->auto_unload) + continue; + + if (!nl) { + pa_strbuf_puts(buf, "\n"); + nl = 1; + } + + pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source, PA_MIXER_HARDWARE))); } diff --git a/src/polypcore/core-def.h b/src/polypcore/core-def.h new file mode 100644 index 000000000..89cc47f1e --- /dev/null +++ b/src/polypcore/core-def.h @@ -0,0 +1,30 @@ +#ifndef foocoredefhfoo +#define foocoredefhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +typedef enum pa_mixer { + PA_MIXER_SOFTWARE, + PA_MIXER_HARDWARE +} pa_mixer_t; + +#endif diff --git a/src/polypcore/native-common.h b/src/polypcore/native-common.h index 0d17b0222..a5ca5c961 100644 --- a/src/polypcore/native-common.h +++ b/src/polypcore/native-common.h @@ -71,6 +71,8 @@ enum { PA_COMMAND_SET_SINK_VOLUME, PA_COMMAND_SET_SINK_INPUT_VOLUME, + PA_COMMAND_SET_SOURCE_VOLUME, + PA_COMMAND_CORK_PLAYBACK_STREAM, PA_COMMAND_FLUSH_PLAYBACK_STREAM, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, diff --git a/src/polypcore/pdispatch.c b/src/polypcore/pdispatch.c index c082b8cc5..2cc90bc25 100644 --- a/src/polypcore/pdispatch.c +++ b/src/polypcore/pdispatch.c @@ -82,6 +82,7 @@ static const char *command_names[PA_COMMAND_MAX] = { [PA_COMMAND_SUBSCRIBE_EVENT] = "SUBSCRIBE_EVENT", [PA_COMMAND_SET_SINK_VOLUME] = "SET_SINK_VOLUME", [PA_COMMAND_SET_SINK_INPUT_VOLUME] = "SET_SINK_INPUT_VOLUME", + [PA_COMMAND_SET_SOURCE_VOLUME] = "SET_SOURCE_VOLME", [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = "TRIGGER_PLAYBACK_STREAM", [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = "FLUSH_PLAYBACK_STREAM", [PA_COMMAND_CORK_PLAYBACK_STREAM] = "CORK_PLAYBACK_STREAM", diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index e73ff761a..cd1a685f8 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -216,6 +216,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume, [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume, + [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume, [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream, [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_playback_stream, @@ -1254,16 +1255,20 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { assert(t && source); - pa_tagstruct_putu32(t, source->index); - pa_tagstruct_puts(t, source->name); - pa_tagstruct_puts(t, source->description); - pa_tagstruct_put_sample_spec(t, &source->sample_spec); - pa_tagstruct_put_channel_map(t, &source->channel_map); - pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1); - pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1); - pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : NULL); - pa_tagstruct_put_usec(t, pa_source_get_latency(source)); - pa_tagstruct_puts(t, source->driver); + pa_tagstruct_put( + t, + PA_TAG_U32, source->index, + PA_TAG_STRING, source->name, + PA_TAG_STRING, source->description, + PA_TAG_SAMPLE_SPEC, &source->sample_spec, + PA_TAG_CHANNEL_MAP, &source->channel_map, + PA_TAG_U32, source->owner ? source->owner->index : PA_INVALID_INDEX, + PA_TAG_CVOLUME, pa_source_get_volume(source, PA_MIXER_HARDWARE), + PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX, + PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL, + PA_TAG_USEC, pa_source_get_latency(source), + PA_TAG_STRING, source->driver, + PA_TAG_INVALID); } static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) { @@ -1558,12 +1563,14 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t idx; pa_cvolume volume; pa_sink *sink = NULL; + pa_source *source = NULL; pa_sink_input *si = NULL; const char *name = NULL; assert(c && t); if (pa_tagstruct_getu32(t, &idx) < 0 || (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) || + (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) || pa_tagstruct_get_cvolume(t, &volume) || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1580,18 +1587,25 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); else sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); + } else if (command == PA_COMMAND_SET_SOURCE_VOLUME) { + if (idx != (uint32_t) -1) + source = pa_idxset_get_by_index(c->protocol->core->sources, idx); + else + source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); } else { assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME); si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); } - if (!si && !sink) { + if (!si && !sink && !source) { pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } if (sink) pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &volume); + else if (source) + pa_source_set_volume(source, PA_MIXER_HARDWARE, &volume); else if (si) pa_sink_input_set_volume(si, &volume); diff --git a/src/polypcore/sink.h b/src/polypcore/sink.h index fa120ebf4..5f1a6cc85 100644 --- a/src/polypcore/sink.h +++ b/src/polypcore/sink.h @@ -29,6 +29,7 @@ typedef struct pa_sink pa_sink; #include #include #include +#include #include #include #include @@ -41,11 +42,6 @@ typedef enum pa_sink_state { PA_SINK_DISCONNECTED } pa_sink_state_t; -typedef enum pa_mixer { - PA_MIXER_SOFTWARE, - PA_MIXER_HARDWARE -} pa_mixer_t; - struct pa_sink { int ref; uint32_t index; diff --git a/src/polypcore/source.c b/src/polypcore/source.c index b70cb1293..47325a1b6 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -77,8 +77,13 @@ pa_source* pa_source_new( s->outputs = pa_idxset_new(NULL, NULL); s->monitor_of = NULL; + pa_cvolume_reset(&s->sw_volume, spec->channels); + pa_cvolume_reset(&s->hw_volume, spec->channels); + s->get_latency = NULL; s->notify = NULL; + s->set_hw_volume = NULL; + s->get_hw_volume = NULL; s->userdata = NULL; r = pa_idxset_put(core->sources, s, &s->index); @@ -110,6 +115,8 @@ void pa_source_disconnect(pa_source *s) { s->get_latency = NULL; s->notify = NULL; + s->get_hw_volume = NULL; + s->set_hw_volume = NULL; s->state = PA_SOURCE_DISCONNECTED; pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); @@ -173,7 +180,14 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) { assert(chunk); pa_source_ref(s); + + if (!pa_cvolume_is_norm(&s->sw_volume)) { + pa_memchunk_make_writable(chunk, s->core->memblock_stat, 0); + pa_volume_memchunk(chunk, &s->sample_spec, &s->sw_volume); + } + pa_idxset_foreach(s->outputs, do_post, (void*) chunk); + pa_source_unref(s); } @@ -194,3 +208,40 @@ pa_usec_t pa_source_get_latency(pa_source *s) { return s->get_latency(s); } +void pa_source_set_volume(pa_source *s, pa_mixer_t m, const pa_cvolume *volume) { + pa_cvolume *v; + + assert(s); + assert(s->ref >= 1); + assert(volume); + + if (m == PA_MIXER_HARDWARE && s->set_hw_volume) + v = &s->hw_volume; + else + v = &s->sw_volume; + + if (pa_cvolume_equal(v, volume)) + return; + + *v = *volume; + + if (v == &s->hw_volume) + if (s->set_hw_volume(s) < 0) + s->sw_volume = *volume; + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); +} + +const pa_cvolume *pa_source_get_volume(pa_source *s, pa_mixer_t m) { + assert(s); + assert(s->ref >= 1); + + if (m == PA_MIXER_HARDWARE && s->set_hw_volume) { + + if (s->get_hw_volume) + s->get_hw_volume(s); + + return &s->hw_volume; + } else + return &s->sw_volume; +} diff --git a/src/polypcore/source.h b/src/polypcore/source.h index a267e73c1..3c5bb6c4f 100644 --- a/src/polypcore/source.h +++ b/src/polypcore/source.h @@ -28,6 +28,8 @@ typedef struct pa_source pa_source; #include #include +#include +#include #include #include #include @@ -56,9 +58,13 @@ struct pa_source { pa_idxset *outputs; pa_sink *monitor_of; + + pa_cvolume hw_volume, sw_volume; void (*notify)(pa_source*source); pa_usec_t (*get_latency)(pa_source *s); + int (*set_hw_volume)(pa_source *s); + int (*get_hw_volume)(pa_source *s); void *userdata; }; @@ -84,4 +90,7 @@ void pa_source_set_owner(pa_source *s, pa_module *m); pa_usec_t pa_source_get_latency(pa_source *s); +void pa_source_set_volume(pa_source *source, pa_mixer_t m, const pa_cvolume *volume); +const pa_cvolume *pa_source_get_volume(pa_source *source, pa_mixer_t m); + #endif From 71fd26f895690f7e14b10b30a61b98f8ab7c8b24 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 22 Feb 2006 15:36:11 +0000 Subject: [PATCH 0468/1514] Wrong userdata used to init operation. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@561 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/context.c b/src/polyp/context.c index 63acf19fc..15e6cd762 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -847,7 +847,7 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); - o = pa_operation_new(c, NULL, cb, o->userdata); + o = pa_operation_new(c, NULL, cb, userdata); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, command); From f62b66ae41ad9ae9c89c1aba3e55aa466fbe42df Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 18:43:26 +0000 Subject: [PATCH 0469/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@562 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/todo b/doc/todo index feac0c754..a0ad6bbfe 100644 --- a/doc/todo +++ b/doc/todo @@ -23,6 +23,7 @@ Fixes: - volume control - add hw driver name to sink/source description - deal with underflows properly +- multiline configuration statements Post 0.8: - alsa mmap driver @@ -32,6 +33,7 @@ Post 0.8: - chroot() - add threading API - module-tunnel: improve latency calculation +- port from howl to avahi Long term: - pass meta info for hearing impaired From a99e46dd0b146d7f3d0c57821ccc26ead6b01f65 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 18:54:21 +0000 Subject: [PATCH 0470/1514] rework parameter validity checking in protocol-native server side git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@563 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/def.h | 3 +- src/polypcore/protocol-native.c | 522 +++++++++++--------------------- 2 files changed, 182 insertions(+), 343 deletions(-) diff --git a/src/polyp/def.h b/src/polyp/def.h index 2ce1bd0c2..0d095e9ad 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -139,7 +139,8 @@ typedef enum pa_subscription_mask { PA_SUBSCRIPTION_MASK_CLIENT = 32, /**< Client events */ PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */ PA_SUBSCRIPTION_MASK_SERVER = 128, /**< Other global server changes. \since 0.4 */ - PA_SUBSCRIPTION_MASK_AUTOLOAD = 256 /**< Autoload table events. \since 0.5 */ + PA_SUBSCRIPTION_MASK_AUTOLOAD = 256, /**< Autoload table events. \since 0.5 */ + PA_SUBSCRIPTION_MASK_ALL = 511 /**< Catch all events \since 0.8 */ } pa_subscription_mask_t; /** Subscription event types, as used by pa_context_subscribe() */ diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index cd1a685f8..34d3a247d 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -545,7 +545,6 @@ static void send_playback_stream_killed(struct playback_stream *p) { assert(p); t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED); pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ pa_tagstruct_putu32(t, p->index); @@ -557,7 +556,6 @@ static void send_record_stream_killed(struct record_stream *r) { assert(r); t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED); pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ pa_tagstruct_putu32(t, r->index); @@ -667,6 +665,22 @@ static void protocol_error(struct connection *c) { connection_free(c); } +#define CHECK_VALIDITY(pstream, expression, tag, error) do { \ +if (!(expression)) { \ + pa_pstream_send_error((pstream), (tag), (error)); \ + return; \ +} \ +} while(0); + +static pa_tagstruct *reply_new(uint32_t tag) { + pa_tagstruct *reply; + + reply = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + return reply; +} + static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct playback_stream *s; @@ -703,33 +717,24 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || *sink_name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID); if (sink_index != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); else sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1); - if (!sink) { - pa_log_warn(__FILE__": Can't find a suitable sink.\n"); - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } - - if (!(s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume, syncid))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); - return; - } + CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); + + s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume, syncid); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); pa_sink_input_cork(s->sink_input, corked); - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); pa_tagstruct_putu32(reply, s->index); assert(s->sink_input); pa_tagstruct_putu32(reply, s->sink_input->index); @@ -749,10 +754,7 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); if (command == PA_COMMAND_DELETE_PLAYBACK_STREAM) { struct playback_stream *s; @@ -797,7 +799,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ int corked; assert(c && t && c->protocol && c->protocol->core); - if (pa_tagstruct_gets(t, &name) < 0 || !name || + if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_get_sample_spec(t, &ss) < 0 || pa_tagstruct_get_channel_map(t, &map) < 0 || pa_tagstruct_getu32(t, &source_index) < 0 || @@ -810,32 +812,24 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || *source_name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID); - if (source_index != (uint32_t) -1) + if (source_index != PA_INVALID_INDEX) source = pa_idxset_get_by_index(c->protocol->core->sources, source_index); else source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1); - if (!source) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY); + + s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); - if (!(s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); - return; - } - pa_source_output_cork(s->source_output, corked); - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); pa_tagstruct_putu32(reply, s->index); assert(s->source_output); pa_tagstruct_putu32(reply, s->source_output->index); @@ -851,15 +845,11 @@ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); assert(c->protocol && c->protocol->core && c->protocol->core->mainloop); c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0); pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */ - return; } static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -888,7 +878,6 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t } pa_pstream_send_simple_ack(c->pstream, tag); - return; } static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -896,15 +885,16 @@ static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE const char *name; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || !name || + if (pa_tagstruct_gets(t, &name) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } + CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_INVALID); + pa_client_set_name(c->client, name); pa_pstream_send_simple_ack(c->pstream, tag); - return; } static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -913,16 +903,14 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin uint32_t idx = PA_IDXSET_INVALID; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || !name || + if (pa_tagstruct_gets(t, &name) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); if (command == PA_COMMAND_LOOKUP_SINK) { pa_sink *sink; @@ -939,10 +927,7 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); else { pa_tagstruct *reply; - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); pa_tagstruct_putu32(reply, idx); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -960,16 +945,11 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } - - if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + s = pa_idxset_get_by_index(c->output_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); + s->drain_request = 0; pa_memblockq_prebuf_disable(s->memblockq); @@ -996,15 +976,9 @@ static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total); pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total_size); pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated); @@ -1030,20 +1004,12 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + s = pa_idxset_get_by_index(c->output_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); - if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } - - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); pa_tagstruct_put_usec(reply, pa_sink_input_get_latency(s->sink_input)); pa_tagstruct_put_usec(reply, pa_sink_get_latency(s->sink_input->sink)); pa_tagstruct_put_usec(reply, 0); @@ -1073,20 +1039,11 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + s = pa_idxset_get_by_index(c->record_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); - if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } - - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); pa_tagstruct_put_usec(reply, pa_source_output_get_latency(s->source_output)); pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0); pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source)); @@ -1099,7 +1056,6 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN pa_pstream_send_tagstruct(c->pstream, reply); } - static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct upload_stream *s; @@ -1110,7 +1066,7 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct *reply; assert(c && t && c->protocol && c->protocol->core); - if (pa_tagstruct_gets(t, &name) < 0 || !name || + if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_get_sample_spec(t, &ss) < 0 || pa_tagstruct_get_channel_map(t, &map) < 0 || pa_tagstruct_getu32(t, &length) < 0 || @@ -1119,25 +1075,14 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } - - if ((length % pa_frame_size(&ss)) != 0 || length <= 0 || !*name) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); - if (!(s = upload_stream_new(c, &ss, &map, name, length))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); - return; - } + s = upload_stream_new(c, &ss, &map, name, length); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); pa_tagstruct_putu32(reply, s->index); pa_tagstruct_putu32(reply, length); pa_pstream_send_tagstruct(c->pstream, reply); @@ -1156,15 +1101,11 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); - return; - } + s = pa_idxset_get_by_index(c->output_streams, channel); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, s->type == UPLOAD_STREAM, tag, PA_ERR_NOENTITY); pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx); pa_pstream_send_simple_ack(c->pstream, tag); @@ -1182,26 +1123,22 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui if (pa_tagstruct_getu32(t, &sink_index) < 0 || pa_tagstruct_gets(t, &sink_name) < 0 || pa_tagstruct_get_cvolume(t, &volume) < 0 || - pa_tagstruct_gets(t, &name) < 0 || !name || + pa_tagstruct_gets(t, &name) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || *sink_name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); - if (sink_index != (uint32_t) -1) + if (sink_index != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); else sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1); - if (!sink) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); if (pa_scache_play_item(c->protocol->core, name, sink, &volume) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); @@ -1216,16 +1153,14 @@ static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED const char *name; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || !name || + if (pa_tagstruct_gets(t, &name) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); if (pa_scache_remove_item(c->protocol->core, name) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); @@ -1275,7 +1210,7 @@ static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) { assert(t && client); pa_tagstruct_putu32(t, client->index); pa_tagstruct_puts(t, client->name); - pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1); + pa_tagstruct_putu32(t, client->owner ? client->owner->index : PA_INVALID_INDEX); pa_tagstruct_puts(t, client->driver); } @@ -1292,8 +1227,8 @@ static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) { assert(t && s); pa_tagstruct_putu32(t, s->index); pa_tagstruct_puts(t, s->name); - pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1); - pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1); + pa_tagstruct_putu32(t, s->owner ? s->owner->index : PA_INVALID_INDEX); + pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX); pa_tagstruct_putu32(t, s->sink->index); pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_put_channel_map(t, &s->channel_map); @@ -1308,8 +1243,8 @@ static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) { assert(t && s); pa_tagstruct_putu32(t, s->index); pa_tagstruct_puts(t, s->name); - pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1); - pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1); + pa_tagstruct_putu32(t, s->owner ? s->owner->index : PA_INVALID_INDEX); + pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX); pa_tagstruct_putu32(t, s->source->index); pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_put_channel_map(t, &s->channel_map); @@ -1357,19 +1292,16 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u protocol_error(c); return; } - - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); if (command == PA_COMMAND_GET_SINK_INFO) { - if (idx != (uint32_t) -1) + if (idx != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); else sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); } else if (command == PA_COMMAND_GET_SOURCE_INFO) { - if (idx != (uint32_t) -1) + if (idx != PA_INVALID_INDEX) source = pa_idxset_get_by_index(c->protocol->core->sources, idx); else source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); @@ -1383,7 +1315,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx); else { assert(command == PA_COMMAND_GET_SAMPLE_INFO); - if (idx != (uint32_t) -1) + if (idx != PA_INVALID_INDEX) sce = pa_idxset_get_by_index(c->protocol->core->scache, idx); else sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0); @@ -1394,10 +1326,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u return; } - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); if (sink) sink_fill_tagstruct(reply, sink); else if (source) @@ -1427,16 +1356,10 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma protocol_error(c); return; } - - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + + reply = reply_new(tag); if (command == PA_COMMAND_GET_SINK_INFO_LIST) i = c->protocol->core->sinks; @@ -1491,15 +1414,9 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); pa_tagstruct_puts(reply, PACKAGE_NAME); pa_tagstruct_puts(reply, PACKAGE_VERSION); pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt))); @@ -1522,7 +1439,6 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint3 assert(c && core); t = pa_tagstruct_new(NULL, 0); - assert(t); pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT); pa_tagstruct_putu32(t, (uint32_t) -1); pa_tagstruct_putu32(t, e); @@ -1540,12 +1456,10 @@ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint protocol_error(c); return; } - - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID); + if (c->subscription) pa_subscription_free(c->subscription); @@ -1558,7 +1472,13 @@ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_set_volume( + PA_GCC_UNUSED pa_pdispatch *pd, + uint32_t command, + uint32_t tag, + pa_tagstruct *t, + void *userdata) { + struct connection *c = userdata; uint32_t idx; pa_cvolume volume; @@ -1577,13 +1497,11 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || *name, tag, PA_ERR_INVALID); if (command == PA_COMMAND_SET_SINK_VOLUME) { - if (idx != (uint32_t) -1) + if (idx != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); else sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); @@ -1597,10 +1515,7 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); } - if (!si && !sink && !source) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY); if (sink) pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &volume); @@ -1626,17 +1541,11 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } - - if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } - - fprintf(stderr, "Corking %i\n", b); + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); + s = pa_idxset_get_by_index(c->output_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); pa_sink_input_cork(s->sink_input, b); pa_memblockq_prebuf_force(s->memblockq); @@ -1667,15 +1576,11 @@ static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } - - if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); + s = pa_idxset_get_by_index(c->output_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); pa_memblockq_flush(s->memblockq); s->underrun = 0; @@ -1714,15 +1619,11 @@ static void command_trigger_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } - - if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); + s = pa_idxset_get_by_index(c->output_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); switch (command) { case PA_COMMAND_PREBUF_PLAYBACK_STREAM: @@ -1756,15 +1657,9 @@ static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } - - if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + s = pa_idxset_get_by_index(c->record_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); pa_source_output_cork(s->source_output, b); pa_memblockq_prebuf_force(s->memblockq); @@ -1783,15 +1678,9 @@ static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_U return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } - - if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + s = pa_idxset_get_by_index(c->record_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); pa_memblockq_flush(s->memblockq); pa_pstream_send_simple_ack(c->pstream, tag); @@ -1799,21 +1688,17 @@ static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_U static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; - uint32_t idx; const char *s; assert(c && t); - if (pa_tagstruct_getu32(t, &idx) < 0 || - pa_tagstruct_gets(t, &s) < 0 || !s || + if (pa_tagstruct_gets(t, &s) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, !s || *s, tag, PA_ERR_INVALID); pa_namereg_set_default(c->protocol->core, s, command == PA_COMMAND_SET_DEFAULT_SOURCE ? PA_NAMEREG_SOURCE : PA_NAMEREG_SINK); pa_pstream_send_simple_ack(c->pstream, tag); @@ -1826,34 +1711,29 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com assert(c && t); if (pa_tagstruct_getu32(t, &idx) < 0 || - pa_tagstruct_gets(t, &name) < 0 || !name || + pa_tagstruct_gets(t, &name) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_INVALID); if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) { struct playback_stream *s; - if (!(s = pa_idxset_get_by_index(c->output_streams, idx)) || s->type != PLAYBACK_STREAM) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + s = pa_idxset_get_by_index(c->output_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); pa_sink_input_set_name(s->sink_input, name); } else { struct record_stream *s; - if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + s = pa_idxset_get_by_index(c->record_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); pa_source_output_set_name(s->source_output, name); } @@ -1871,28 +1751,21 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 protocol_error(c); return; } - - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); if (command == PA_COMMAND_KILL_CLIENT) { pa_client *client; - if (!(client = pa_idxset_get_by_index(c->protocol->core->clients, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } - + client = pa_idxset_get_by_index(c->protocol->core->clients, idx); + CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY); pa_client_kill(client); + } else if (command == PA_COMMAND_KILL_SINK_INPUT) { pa_sink_input *s; - if (!(s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); pa_sink_input_kill(s); } else { @@ -1900,10 +1773,8 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT); - if (!(s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); pa_source_output_kill(s); } @@ -1918,26 +1789,22 @@ static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui pa_tagstruct *reply; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || !name || + if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_gets(t, &argument) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); if (!(m = pa_module_load(c->protocol->core, name, argument))) { pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED); return; } - reply = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); pa_tagstruct_putu32(reply, m->index); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1954,15 +1821,9 @@ static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } - - if (!(m = pa_idxset_get_by_index(c->protocol->core->modules, idx))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + m = pa_idxset_get_by_index(c->protocol->core->modules, idx); + CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY); pa_module_unload_request(m); pa_pstream_send_simple_ack(c->pstream, tag); @@ -1976,28 +1837,26 @@ static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED u pa_tagstruct *reply; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || !name || - pa_tagstruct_getu32(t, &type) < 0 || type > 1 || - pa_tagstruct_gets(t, &module) < 0 || !module || + if (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_getu32(t, &type) < 0 || + pa_tagstruct_gets(t, &module) < 0 || pa_tagstruct_gets(t, &argument) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, type == 0 || type == 1, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, module && *module, tag, PA_ERR_INVALID); if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &idx) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); return; } - reply = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); pa_tagstruct_putu32(reply, idx); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -2012,27 +1871,21 @@ static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE if ((pa_tagstruct_getu32(t, &idx) < 0 && (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_getu32(t, &type) < 0)) || - (!name && idx == PA_IDXSET_INVALID) || - (name && type > 1) || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || (*name && (type == 0 || type == 1)), tag, PA_ERR_INVALID); if (name) r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE); else r = pa_autoload_remove_by_index(c->protocol->core, idx); - if (r < 0) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + CHECK_VALIDITY(c->pstream, r >= 0, tag, PA_ERR_NOENTITY); pa_pstream_send_simple_ack(c->pstream, tag); } @@ -2058,33 +1911,23 @@ static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNU if ((pa_tagstruct_getu32(t, &idx) < 0 && (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_getu32(t, &type) < 0)) || - (!name && idx == PA_IDXSET_INVALID) || - (name && type > 1) || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || (*name && (type == 0 || type == 1)), tag, PA_ERR_INVALID); if (name) a = pa_autoload_get_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE); else a = pa_autoload_get_by_index(c->protocol->core, idx); - if (!a) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); - return; - } + CHECK_VALIDITY(c->pstream, a, tag, PA_ERR_NOENTITY); - reply = pa_tagstruct_new(NULL, 0); - assert(reply); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); autoload_fill_tagstruct(reply, a); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -2099,14 +1942,9 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC return; } - if (!c->authorized) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); - return; - } + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - reply = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); - pa_tagstruct_putu32(reply, tag); + reply = reply_new(tag); if (c->protocol->core->autoload_hashmap) { pa_autoload_entry *a; @@ -2327,7 +2165,7 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo return NULL; } - p = pa_xmalloc(sizeof(pa_protocol_native)); + p = pa_xnew(pa_protocol_native, 1); p->core = c; p->module = m; p->public = public; From 63165d83cb5ec9709cdf35b81fe90122e4bcb0a4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 18:59:27 +0000 Subject: [PATCH 0471/1514] todo test git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@564 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- src/Makefile.am | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/todo b/doc/todo index a0ad6bbfe..ddefde482 100644 --- a/doc/todo +++ b/doc/todo @@ -6,7 +6,7 @@ Test: - howl Fixes: -- better validity checking in protocol-{native,esound} +- better validity checking in protocol-esound - change pa_log to not require \n - proper use of memcpy in procotol-esound.c so we don't get alignment problems - latency api for native protocol diff --git a/src/Makefile.am b/src/Makefile.am index f36630e76..ab50d8259 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,8 +47,8 @@ AM_CFLAGS = -I$(top_srcdir)/src AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" -#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" +#AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" +AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" From 361f16718f672e6627f74358540ab0a98e82857b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 19:00:27 +0000 Subject: [PATCH 0472/1514] unbreak Makefile.am git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@565 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index ab50d8259..f36630e76 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,8 +47,8 @@ AM_CFLAGS = -I$(top_srcdir)/src AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -#AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" -AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" +AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" +#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" From 7f68c913f1c54114a538ccca680db3a3ba4d6e26 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 20:11:56 +0000 Subject: [PATCH 0473/1514] revive howl support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@566 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/howl-wrap.c | 4 +- src/modules/howl-wrap.h | 2 +- src/modules/module-zeroconf-publish.c | 65 +++++++-------- src/polyp/browser.c | 116 +++++++++++++++----------- src/polyp/browser.h | 22 +++-- src/utils/pabrowse.c | 23 ++--- 6 files changed, 126 insertions(+), 106 deletions(-) diff --git a/src/modules/howl-wrap.c b/src/modules/howl-wrap.c index b3acde55a..b3fe81662 100644 --- a/src/modules/howl-wrap.c +++ b/src/modules/howl-wrap.c @@ -29,7 +29,7 @@ #define HOWL_PROPERTY "howl" -pa_howl_wrapper { +struct pa_howl_wrapper { pa_core *core; int ref; @@ -38,7 +38,7 @@ pa_howl_wrapper { }; -static void howl_io_event(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) { +static void howl_io_event(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { pa_howl_wrapper *w = userdata; assert(m && e && fd >= 0 && w && w->ref >= 1); diff --git a/src/modules/howl-wrap.h b/src/modules/howl-wrap.h index 42c26ef2f..a4b26490d 100644 --- a/src/modules/howl-wrap.h +++ b/src/modules/howl-wrap.h @@ -26,7 +26,7 @@ #include -pa_howl_wrapper; +typedef struct pa_howl_wrapper pa_howl_wrapper; pa_howl_wrapper* pa_howl_wrapper_get(pa_core *c); pa_howl_wrapper* pa_howl_wrapper_ref(pa_howl_wrapper *h); diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index d2858aac0..d79355ce6 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -67,13 +67,13 @@ struct service { struct { int valid; - pa_namereg_type type; + pa_namereg_type_t type; uint32_t index; } loaded; struct { int valid; - pa_namereg_type type; + pa_namereg_type_t type; uint32_t index; } autoload; }; @@ -93,21 +93,19 @@ static sw_result publish_reply(sw_discovery discovery, sw_discovery_publish_stat return SW_OKAY; } -static void get_service_data(struct userdata *u, struct service *s, pa_sample_spec *ret_ss, char **ret_description, pa_typeid_t *ret_typeid) { - assert(u && s && s->loaded.valid && ret_ss && ret_description && ret_typeid); +static void get_service_data(struct userdata *u, struct service *s, pa_sample_spec *ret_ss, char **ret_description) { + assert(u && s && s->loaded.valid && ret_ss && ret_description); if (s->loaded.type == PA_NAMEREG_SINK) { pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index); assert(sink); *ret_ss = sink->sample_spec; *ret_description = sink->description; - *ret_typeid = sink->typeid; } else if (s->loaded.type == PA_NAMEREG_SOURCE) { pa_source *source = pa_idxset_get_by_index(u->core->sources, s->loaded.index); assert(source); *ret_ss = source->sample_spec; *ret_description = source->description; - *ret_typeid = source->typeid; } else assert(0); } @@ -154,10 +152,9 @@ static int publish_service(struct userdata *u, struct service *s) { if (s->loaded.valid) { char z[64], *description; - pa_typeid_t typeid; pa_sample_spec ss; - get_service_data(u, s, &ss, &description, &typeid); + get_service_data(u, s, &ss, &description); snprintf(z, sizeof(z), "%u", ss.rate); sw_text_record_add_key_and_string_value(txt, "rate", z); @@ -167,10 +164,6 @@ static int publish_service(struct userdata *u, struct service *s) { sw_text_record_add_key_and_string_value(txt, "description", description); - snprintf(z, sizeof(z), "0x%8x", typeid); - sw_text_record_add_key_and_string_value(txt, "typeid", z); - - if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t, s->loaded.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE, NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt), @@ -210,7 +203,7 @@ finish: return r; } -struct service *get_service(struct userdata *u, const char *name) { +static struct service *get_service(struct userdata *u, const char *name) { struct service *s; if ((s = pa_hashmap_get(u->services, name))) @@ -277,55 +270,55 @@ static int publish_autoload(struct userdata *u, pa_autoload_entry *s) { return publish_service(u, svc); } -static int remove_sink(struct userdata *u, uint32_t index) { +static int remove_sink(struct userdata *u, uint32_t idx) { struct service *svc; - assert(u && index != PA_INVALID_INDEX); + assert(u && idx != PA_INVALID_INDEX); - if (!(svc = pa_dynarray_get(u->sink_dynarray, index))) + if (!(svc = pa_dynarray_get(u->sink_dynarray, idx))) return 0; if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SINK) return 0; svc->loaded.valid = 0; - pa_dynarray_put(u->sink_dynarray, index, NULL); + pa_dynarray_put(u->sink_dynarray, idx, NULL); return publish_service(u, svc); } -static int remove_source(struct userdata *u, uint32_t index) { +static int remove_source(struct userdata *u, uint32_t idx) { struct service *svc; - assert(u && index != PA_INVALID_INDEX); + assert(u && idx != PA_INVALID_INDEX); - if (!(svc = pa_dynarray_get(u->source_dynarray, index))) + if (!(svc = pa_dynarray_get(u->source_dynarray, idx))) return 0; if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SOURCE) return 0; svc->loaded.valid = 0; - pa_dynarray_put(u->source_dynarray, index, NULL); + pa_dynarray_put(u->source_dynarray, idx, NULL); return publish_service(u, svc); } -static int remove_autoload(struct userdata *u, uint32_t index) { +static int remove_autoload(struct userdata *u, uint32_t idx) { struct service *svc; - assert(u && index != PA_INVALID_INDEX); + assert(u && idx != PA_INVALID_INDEX); - if (!(svc = pa_dynarray_get(u->autoload_dynarray, index))) + if (!(svc = pa_dynarray_get(u->autoload_dynarray, idx))) return 0; if (!svc->autoload.valid) return 0; svc->autoload.valid = 0; - pa_dynarray_put(u->autoload_dynarray, index, NULL); + pa_dynarray_put(u->autoload_dynarray, idx, NULL); return publish_service(u, svc); } -static void subscribe_callback(pa_core *c, pa_subscription_event_type t, uint32_t index, void *userdata) { +static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = userdata; assert(u && c); @@ -334,12 +327,12 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type t, uint32_ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { pa_sink *sink; - if ((sink = pa_idxset_get_by_index(c->sinks, index))) { + if ((sink = pa_idxset_get_by_index(c->sinks, idx))) { if (publish_sink(u, sink) < 0) goto fail; } } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (remove_sink(u, index) < 0) + if (remove_sink(u, idx) < 0) goto fail; } @@ -350,12 +343,12 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type t, uint32_ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { pa_source *source; - if ((source = pa_idxset_get_by_index(c->sources, index))) { + if ((source = pa_idxset_get_by_index(c->sources, idx))) { if (publish_source(u, source) < 0) goto fail; } } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (remove_source(u, index) < 0) + if (remove_source(u, idx) < 0) goto fail; } @@ -365,12 +358,12 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type t, uint32_ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { pa_autoload_entry *autoload; - if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, index))) { + if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, idx))) { if (publish_autoload(u, autoload) < 0) goto fail; } } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (remove_autoload(u, index) < 0) + if (remove_autoload(u, idx) < 0) goto fail; } @@ -388,7 +381,7 @@ fail: int pa__init(pa_core *c, pa_module*m) { struct userdata *u; - uint32_t index, port = PA_NATIVE_DEFAULT_PORT; + uint32_t idx, port = PA_NATIVE_DEFAULT_PORT; pa_sink *sink; pa_source *source; pa_autoload_entry *autoload; @@ -424,16 +417,16 @@ int pa__init(pa_core *c, pa_module*m) { PA_SUBSCRIPTION_MASK_SOURCE| PA_SUBSCRIPTION_MASK_AUTOLOAD, subscribe_callback, u); - for (sink = pa_idxset_first(c->sinks, &index); sink; sink = pa_idxset_next(c->sinks, &index)) + for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) if (publish_sink(u, sink) < 0) goto fail; - for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) + for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) if (publish_source(u, source) < 0) goto fail; if (c->autoload_idxset) - for (autoload = pa_idxset_first(c->autoload_idxset, &index); autoload; autoload = pa_idxset_next(c->autoload_idxset, &index)) + for (autoload = pa_idxset_first(c->autoload_idxset, &idx); autoload; autoload = pa_idxset_next(c->autoload_idxset, &idx)) if (publish_autoload(u, autoload) < 0) goto fail; diff --git a/src/polyp/browser.c b/src/polyp/browser.c index 482bab81e..ce4c01035 100644 --- a/src/polyp/browser.c +++ b/src/polyp/browser.c @@ -32,19 +32,18 @@ #define SERVICE_NAME_SOURCE "_polypaudio-source._tcp." #define SERVICE_NAME_SERVER "_polypaudio-server._tcp." -pa_browser { +struct pa_browser { int ref; pa_mainloop_api *mainloop; - void (*callback)(pa_browser *z, pa_browse_opcode c, const pa_browse_info *i, void *userdata); - void *callback_userdata; + pa_browse_cb_t callback; + void *userdata; sw_discovery discovery; pa_io_event *io_event; }; - -static void io_callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags events, void *userdata) { +static void io_callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t events, void *userdata) { pa_browser *b = userdata; assert(a && b && b->mainloop == a); @@ -56,26 +55,54 @@ static void io_callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_fl } } +static int type_equal(const char *a, const char *b) { + size_t la, lb; + + if (strcasecmp(a, b) == 0) + return 1; + + la = strlen(a); + lb = strlen(b); + + if (la > 0 && a[la-1] == '.' && la == lb+1 && strncasecmp(a, b, la-1) == 0) + return 1; + + if (lb > 0 && b[lb-1] == '.' && lb == la+1 && strncasecmp(a, b, lb-1) == 0) + return 1; + + return 0; +} + +static int map_to_opcode(const char *type, int new) { + if (type_equal(type, SERVICE_NAME_SINK)) + return new ? PA_BROWSE_NEW_SINK : PA_BROWSE_REMOVE_SINK; + else if (type_equal(type, SERVICE_NAME_SOURCE)) + return new ? PA_BROWSE_NEW_SOURCE : PA_BROWSE_REMOVE_SOURCE; + else if (type_equal(type, SERVICE_NAME_SERVER)) + return new ? PA_BROWSE_NEW_SERVER : PA_BROWSE_REMOVE_SERVER; + + return -1; +} + static sw_result resolve_reply( - sw_discovery discovery, - sw_discovery_oid oid, - sw_uint32 interface_index, - sw_const_string name, - sw_const_string type, - sw_const_string domain, - sw_ipv4_address address, - sw_port port, - sw_octets text_record, - sw_ulong text_record_len, - sw_opaque extra) { + sw_discovery discovery, + sw_discovery_oid oid, + sw_uint32 interface_index, + sw_const_string name, + sw_const_string type, + sw_const_string domain, + sw_ipv4_address address, + sw_port port, + sw_octets text_record, + sw_ulong text_record_len, + sw_opaque extra) { pa_browser *b = extra; pa_browse_info i; char ip[256], a[256]; - pa_browse_opcode opcode; + int opcode; int device_found = 0; uint32_t cookie; - pa_typeid_t typeid; pa_sample_spec ss; int ss_valid = 0; sw_text_record_iterator iterator; @@ -91,17 +118,10 @@ static sw_result resolve_reply( if (!b->callback) goto fail; - - if (!strcmp(type, SERVICE_NAME_SINK)) - opcode = PA_BROWSE_NEW_SINK; - else if (!strcmp(type, SERVICE_NAME_SOURCE)) - opcode = PA_BROWSE_NEW_SOURCE; - else if (!strcmp(type, SERVICE_NAME_SERVER)) - opcode = PA_BROWSE_NEW_SERVER; - else - goto fail; - + opcode = map_to_opcode(type, 1); + assert(opcode >= 0); + snprintf(a, sizeof(a), "tcp:%s:%u", sw_ipv4_address_name(address, ip, sizeof(ip)), port); i.server = a; @@ -154,12 +174,6 @@ static sw_result resolve_reply( pa_xfree((char*) i.description); i.description = c; c = NULL; - } else if (!strcmp(key, "typeid")) { - - if (pa_atou(c, &typeid) < 0) - goto fail; - - i.typeid = &typeid; } else if (!strcmp(key, "channels")) { uint32_t ch; @@ -195,7 +209,7 @@ static sw_result resolve_reply( i.sample_spec = &ss; - b->callback(b, opcode, &i, b->callback_userdata); + b->callback(b, opcode, &i, b->userdata); fail: pa_xfree((void*) i.device); @@ -213,14 +227,14 @@ fail: } static sw_result browse_reply( - sw_discovery discovery, - sw_discovery_oid id, - sw_discovery_browse_status status, - sw_uint32 interface_index, - sw_const_string name, - sw_const_string type, - sw_const_string domain, - sw_opaque extra) { + sw_discovery discovery, + sw_discovery_oid id, + sw_discovery_browse_status status, + sw_uint32 interface_index, + sw_const_string name, + sw_const_string type, + sw_const_string domain, + sw_opaque extra) { pa_browser *b = extra; assert(b); @@ -238,9 +252,15 @@ static sw_result browse_reply( case SW_DISCOVERY_BROWSE_REMOVE_SERVICE: if (b->callback) { pa_browse_info i; + int opcode; + memset(&i, 0, sizeof(i)); i.name = name; - b->callback(b, PA_BROWSE_REMOVE, &i, b->callback_userdata); + + opcode = map_to_opcode(type, 0); + assert(opcode >= 0); + + b->callback(b, opcode, &i, b->userdata); } break; @@ -255,11 +275,11 @@ pa_browser *pa_browser_new(pa_mainloop_api *mainloop) { pa_browser *b; sw_discovery_oid oid; - b = pa_xmalloc(sizeof(pa_browser)); + b = pa_xnew(pa_browser, 1); b->mainloop = mainloop; b->ref = 1; b->callback = NULL; - b->callback_userdata = NULL; + b->userdata = NULL; if (sw_discovery_init(&b->discovery) != SW_OKAY) { pa_log("sw_discovery_init() failed.\n"); @@ -305,9 +325,9 @@ void pa_browser_unref(pa_browser *b) { browser_free(b); } -void pa_browser_set_callback(pa_browser *b, void (*cb)(pa_browser *z, pa_browse_opcode c, const pa_browse_info *i, void* userdata), void *userdata) { +void pa_browser_set_callback(pa_browser *b, pa_browse_cb_t cb, void *userdata) { assert(b); b->callback = cb; - b->callback_userdata = userdata; + b->userdata = userdata; } diff --git a/src/polyp/browser.h b/src/polyp/browser.h index 043b818af..1ff58d8c7 100644 --- a/src/polyp/browser.h +++ b/src/polyp/browser.h @@ -24,24 +24,27 @@ #include #include +#include #include PA_C_DECL_BEGIN -pa_browser; +typedef struct pa_browser pa_browser; -pa_browse_opcode { - PA_BROWSE_NEW_SERVER, +typedef enum pa_browse_opcode { + PA_BROWSE_NEW_SERVER = 0, PA_BROWSE_NEW_SINK, PA_BROWSE_NEW_SOURCE, - PA_BROWSE_REMOVE -}; + PA_BROWSE_REMOVE_SERVER, + PA_BROWSE_REMOVE_SINK, + PA_BROWSE_REMOVE_SOURCE +} pa_browse_opcode_t; pa_browser *pa_browser_new(pa_mainloop_api *mainloop); pa_browser *pa_browser_ref(pa_browser *z); void pa_browser_unref(pa_browser *z); -pa_browse_info { +typedef struct pa_browse_info { /* Unique service name */ const char *name; /* always available */ @@ -53,11 +56,12 @@ pa_browse_info { /* Device info */ const char *device; /* always available when this information is of a sink/source */ const char *description; /* optional */ - const pa_typeid_t *typeid; /* optional */ const pa_sample_spec *sample_spec; /* optional */ -}; +} pa_browse_info; -void pa_browser_set_callback(pa_browser *z, void (*cb)(pa_browser *z, pa_browse_opcode c, const pa_browse_info *i, void *userdata), void *userdata); +typedef void (*pa_browse_cb_t)(pa_browser *z, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata); + +void pa_browser_set_callback(pa_browser *z, pa_browse_cb_t cb, void *userdata); PA_C_DECL_END diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 344e32813..c1bab6b1c 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -55,26 +55,21 @@ static void dump_server(const pa_browse_info *i) { } static void dump_device(const pa_browse_info *i) { - char t[16], ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; if (i->sample_spec) pa_sample_spec_snprint(ss, sizeof(ss), i->sample_spec); - if (i->typeid) - pa_typeid_to_string(*i->typeid, t, sizeof(t)); - printf("device: %s\n" "description: %s\n" - "type: %s\n" "sample spec: %s\n", i->device, i->description ? i->description : "n/a", - i->typeid ? t : "n/a", i->sample_spec ? ss : "n/a"); } -static void browser_callback(pa_browser *b, pa_browse_opcode c, const pa_browse_info *i, void *userdata) { +static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata) { assert(b && i); switch (c) { @@ -96,10 +91,18 @@ static void browser_callback(pa_browser *b, pa_browse_opcode c, const pa_browse_ dump_device(i); break; - case PA_BROWSE_REMOVE: - printf("\n=> removed service <%s>\n", i->name); + case PA_BROWSE_REMOVE_SERVER: + printf("\n=> removed server <%s>\n", i->name); break; - + + case PA_BROWSE_REMOVE_SINK: + printf("\n=> removed sink <%s>\n", i->name); + break; + + case PA_BROWSE_REMOVE_SOURCE: + printf("\n=> removed source <%s>\n", i->name); + break; + default: ; } From 5c7ab7746694ed08fbf3f290f338ca45231f1543 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 20:14:00 +0000 Subject: [PATCH 0474/1514] pkg-config update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@567 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyplib-browse.pc.in | 2 +- polyplib-glib-mainloop.pc.in | 2 +- polyplib-glib12-mainloop.pc.in | 2 +- polyplib-simple.pc.in | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/polyplib-browse.pc.in b/polyplib-browse.pc.in index b77967e00..b9d57eef5 100644 --- a/polyplib-browse.pc.in +++ b/polyplib-browse.pc.in @@ -8,4 +8,4 @@ Description: Polypaudio network browsing API Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpolyp-browse-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib-mainloop +Requires: polyplib diff --git a/polyplib-glib-mainloop.pc.in b/polyplib-glib-mainloop.pc.in index 431354e8c..0e8b4d8c3 100644 --- a/polyplib-glib-mainloop.pc.in +++ b/polyplib-glib-mainloop.pc.in @@ -8,4 +8,4 @@ Description: GLIB main loop wrapper for polypaudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpolyp-mainloop-glib-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib-mainloop +Requires: polyplib-mainloop glib-2.0 diff --git a/polyplib-glib12-mainloop.pc.in b/polyplib-glib12-mainloop.pc.in index 5c5f4089b..8687776bd 100644 --- a/polyplib-glib12-mainloop.pc.in +++ b/polyplib-glib12-mainloop.pc.in @@ -8,4 +8,4 @@ Description: GLIB main loop wrapper for polypaudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpolyp-mainloop-glib12-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib-mainloop +Requires: polyplib-mainloop glib diff --git a/polyplib-simple.pc.in b/polyplib-simple.pc.in index a28503494..94644df67 100644 --- a/polyplib-simple.pc.in +++ b/polyplib-simple.pc.in @@ -8,4 +8,4 @@ Description: Simplified synchronous client interface to polypaudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpolyp-simple-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib polyplib-mainloop polyplib-error +Requires: polyplib From 8df72bceb5c29aa0b5b974f0bc3a416b6733cbdb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 20:14:37 +0000 Subject: [PATCH 0475/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@568 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index ddefde482..13600ce3b 100644 --- a/doc/todo +++ b/doc/todo @@ -3,7 +3,6 @@ Test: - module-combine - module-tunnel -- howl Fixes: - better validity checking in protocol-esound From ecd346fa9a3ebf786bff8c5a9579b5096f90fc04 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 20:44:37 +0000 Subject: [PATCH 0476/1514] add listen= parameter to tcp protocol modules git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@569 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-protocol-stub.c | 10 ++++++++-- src/polypcore/socket-server.c | 18 ++++++++++++++++++ src/polypcore/socket-server.h | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index f72a68a59..641e3624d 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -52,7 +52,7 @@ #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" -#define SOCKET_USAGE "port= loopback=" +#define SOCKET_USAGE "port= loopback= listen=
    " #else #define SOCKET_DESCRIPTION "(UNIX sockets)" #define SOCKET_USAGE "socket=" @@ -146,6 +146,7 @@ static const char* const valid_modargs[] = { #if defined(USE_TCP_SOCKETS) "port", "loopback", + "listen", #else "socket", #endif @@ -157,6 +158,7 @@ static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) { #if defined(USE_TCP_SOCKETS) int loopback = 1; uint32_t port = IPV4_PORT; + const char *listen_on; if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) { pa_log(__FILE__": loopback= expects a boolean argument.\n"); @@ -168,8 +170,12 @@ static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) { return NULL; } + listen_on = pa_modargs_get_value(ma, "listen", NULL); - if (loopback) { + if (listen_on) { + if (!(s = pa_socket_server_new_ip_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE))) + return NULL; + } else if (loopback) { if (!(s = pa_socket_server_new_ip_loopback(c->mainloop, port, TCPWRAP_SERVICE))) return NULL; } else { diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index 5f84911d7..b12974969 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -334,6 +334,24 @@ pa_socket_server* pa_socket_server_new_ip_any(pa_mainloop_api *m, uint16_t port, return s; } +pa_socket_server* pa_socket_server_new_ip_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { + uint8_t ipv6[16]; + uint32_t ipv4; + + assert(m); + assert(name); + assert(port > 0); + + if (inet_pton(AF_INET6, name, ipv6) > 0) + return pa_socket_server_new_ipv6(m, ipv6, port, tcpwrap_service); + + if (inet_pton(AF_INET, name, &ipv4) > 0) + return pa_socket_server_new_ipv4(m, ntohl(ipv4), port, tcpwrap_service); + + pa_log_warn(__FILE__": failed to parse '%s'.\n", name); + + return NULL; +} static void socket_server_free(pa_socket_server*s) { assert(s); diff --git a/src/polypcore/socket-server.h b/src/polypcore/socket-server.h index d11cee495..3babbc140 100644 --- a/src/polypcore/socket-server.h +++ b/src/polypcore/socket-server.h @@ -36,6 +36,7 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ip_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ip_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ip_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service); void pa_socket_server_unref(pa_socket_server*s); pa_socket_server* pa_socket_server_ref(pa_socket_server *s); From bad8fd7cc0ab399786fb23cb39f824948947feba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 20:45:42 +0000 Subject: [PATCH 0477/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@570 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 13600ce3b..9abfd2d07 100644 --- a/doc/todo +++ b/doc/todo @@ -14,7 +14,6 @@ Fixes: - notification on hw volume change - source volume control - mute switch support (like ALSA does it) -- add listen-on paramater to protocol modules - module-oss-* love: - deal with underflows propely - improve latency measurement for mmap From 708c650ad1366a0686d4c2b1932762205097081c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Feb 2006 21:02:27 +0000 Subject: [PATCH 0478/1514] enforce maximum memblockq length for clients git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@571 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-native.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 34d3a247d..aba12036a 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -59,6 +59,8 @@ /* Don't accept more connection than this */ #define MAX_CONNECTIONS 10 +#define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */ + struct connection; struct pa_protocol_native; @@ -238,8 +240,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_GET_AUTOLOAD_INFO] = command_get_autoload_info, [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = command_get_autoload_info_list, [PA_COMMAND_ADD_AUTOLOAD] = command_add_autoload, - [PA_COMMAND_REMOVE_AUTOLOAD] = command_remove_autoload, - + [PA_COMMAND_REMOVE_AUTOLOAD] = command_remove_autoload }; /* structure management */ @@ -721,6 +722,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || *sink_name, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); if (sink_index != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); @@ -816,6 +818,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || *source_name, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); if (source_index != PA_INVALID_INDEX) source = pa_idxset_get_by_index(c->protocol->core->sources, source_index); From 57713350d7fc3c39c44aecd02c2eda6ff2041cb4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Feb 2006 01:17:54 +0000 Subject: [PATCH 0479/1514] fix source volume adjustment: copy memchunk before changing the volume of it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@572 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/source.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/polypcore/source.c b/src/polypcore/source.c index 47325a1b6..8bca8a1de 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "source.h" @@ -182,11 +183,15 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) { pa_source_ref(s); if (!pa_cvolume_is_norm(&s->sw_volume)) { - pa_memchunk_make_writable(chunk, s->core->memblock_stat, 0); - pa_volume_memchunk(chunk, &s->sample_spec, &s->sw_volume); - } - - pa_idxset_foreach(s->outputs, do_post, (void*) chunk); + pa_memchunk vchunk = *chunk; + + pa_memblock_ref(vchunk.memblock); + pa_memchunk_make_writable(&vchunk, s->core->memblock_stat, 0); + pa_volume_memchunk(&vchunk, &s->sample_spec, &s->sw_volume); + pa_idxset_foreach(s->outputs, do_post, &vchunk); + pa_memblock_unref(vchunk.memblock); + } else + pa_idxset_foreach(s->outputs, do_post, (void*) chunk); pa_source_unref(s); } From cb59817b4a2e1f640bd9279d0c7863e7a09c1fa6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Feb 2006 01:24:16 +0000 Subject: [PATCH 0480/1514] simplify tagstruct creation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@573 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 43 ++++++++++----------- src/polyp/internal.h | 2 + src/polyp/introspect.c | 88 +++++++++++------------------------------- src/polyp/scache.c | 16 ++------ src/polyp/stream.c | 48 +++++++++++------------ src/polyp/subscribe.c | 4 +- 6 files changed, 74 insertions(+), 127 deletions(-) diff --git a/src/polyp/context.c b/src/polyp/context.c index 15e6cd762..906a0d89d 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -354,9 +354,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t switch(c->state) { case PA_CONTEXT_AUTHORIZING: { pa_tagstruct *reply; - reply = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME); - pa_tagstruct_putu32(reply, tag = c->ctag++); + reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); pa_tagstruct_puts(reply, c->name); pa_pstream_send_tagstruct(c->pstream, reply); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); @@ -401,9 +399,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) { goto finish; } - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_AUTH); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); @@ -827,10 +823,8 @@ pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_EXIT); - pa_tagstruct_putu32(t, tag = c->ctag++); + + t = pa_tagstruct_command(c, PA_COMMAND_EXIT, &tag); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); @@ -849,9 +843,7 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa o = pa_operation_new(c, NULL, cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, command); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, command, &tag); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o)); @@ -870,9 +862,7 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_co o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_DEFAULT_SINK); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SINK, &tag); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); @@ -892,9 +882,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_DEFAULT_SOURCE); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); @@ -921,9 +909,7 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_CLIENT_NAME); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); @@ -949,3 +935,16 @@ const char* pa_context_get_server(pa_context *c) { return c->server; } + +pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) { + pa_tagstruct *t; + + assert(c); + assert(tag); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, command); + pa_tagstruct_putu32(t, *tag = c->ctag++); + + return t; +} diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 9907fae08..2e4d859ac 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -164,6 +164,8 @@ void pa_stream_set_state(pa_stream *s, pa_stream_state_t st); void pa_stream_trash_ipol(pa_stream *s); +pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag); + #define PA_CHECK_VALIDITY(context, expression, error) do { \ if (!(expression)) \ return -pa_context_set_error((context), (error)); \ diff --git a/src/polyp/introspect.c b/src/polyp/introspect.c index 4fa238417..6a9917a70 100644 --- a/src/polyp/introspect.c +++ b/src/polyp/introspect.c @@ -189,9 +189,7 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); @@ -214,9 +212,7 @@ pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INFO, &tag); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); @@ -296,9 +292,7 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, p o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); @@ -321,9 +315,7 @@ pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_INFO, &tag); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); @@ -392,9 +384,7 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_CLIENT_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, pa_operation_ref(o)); @@ -467,9 +457,7 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_MODULE_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, pa_operation_ref(o)); @@ -550,9 +538,7 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sin o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INPUT_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INPUT_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, pa_operation_ref(o)); @@ -632,9 +618,7 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_OUTPUT_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, pa_operation_ref(o)); @@ -662,9 +646,7 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, c o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_VOLUME, &tag); pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_tagstruct_put_cvolume(t, volume); @@ -690,9 +672,7 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_VOLUME, &tag); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); pa_tagstruct_put_cvolume(t, volume); @@ -717,9 +697,7 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_VOLUME, &tag); pa_tagstruct_putu32(t, idx); pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); @@ -742,9 +720,7 @@ pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_SOURCE_VOLUME); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_VOLUME, &tag); pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_tagstruct_put_cvolume(t, volume); @@ -770,9 +746,7 @@ pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *na o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_SOURCE_VOLUME); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_VOLUME, &tag); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); pa_tagstruct_put_cvolume(t, volume); @@ -848,9 +822,7 @@ pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_SAMPLE_INFO, &tag); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); @@ -873,9 +845,7 @@ pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, p o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_SAMPLE_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); @@ -901,9 +871,7 @@ static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, command); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, command, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); @@ -967,9 +935,7 @@ pa_operation* pa_context_load_module(pa_context *c, const char*name, const char o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_LOAD_MODULE); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_LOAD_MODULE, &tag); pa_tagstruct_puts(t, name); pa_tagstruct_puts(t, argument); pa_pstream_send_tagstruct(c->pstream, t); @@ -1044,9 +1010,7 @@ pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *na o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_AUTOLOAD_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_AUTOLOAD_INFO, &tag); pa_tagstruct_puts(t, name); pa_tagstruct_putu32(t, type); pa_pstream_send_tagstruct(c->pstream, t); @@ -1069,9 +1033,7 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_GET_AUTOLOAD_INFO); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_GET_AUTOLOAD_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, pa_operation_ref(o)); @@ -1098,9 +1060,7 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_ADD_AUTOLOAD); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_ADD_AUTOLOAD, &tag); pa_tagstruct_puts(t, name); pa_tagstruct_putu32(t, type); pa_tagstruct_puts(t, module); @@ -1125,9 +1085,7 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_AUTOLOAD); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_AUTOLOAD, &tag); pa_tagstruct_puts(t, name); pa_tagstruct_putu32(t, type); pa_pstream_send_tagstruct(c->pstream, t); @@ -1149,9 +1107,7 @@ pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, p o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_AUTOLOAD); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_AUTOLOAD, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); diff --git a/src/polyp/scache.c b/src/polyp/scache.c index 792d7cbfc..891798fbd 100644 --- a/src/polyp/scache.c +++ b/src/polyp/scache.c @@ -47,9 +47,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) { s->direction = PA_STREAM_UPLOAD; - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); + t = pa_tagstruct_command(s->context, PA_COMMAND_CREATE_UPLOAD_STREAM, &tag); pa_tagstruct_puts(t, s->name); pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_putu32(t, length); @@ -72,9 +70,7 @@ int pa_stream_finish_upload(pa_stream *s) { pa_stream_ref(s); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); + t = pa_tagstruct_command(s->context, PA_COMMAND_FINISH_UPLOAD_STREAM, &tag); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s); @@ -100,9 +96,7 @@ pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char if (!dev) dev = c->conf->default_sink; - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_PLAY_SAMPLE, &tag); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, dev); pa_tagstruct_putu32(t, volume); @@ -126,9 +120,7 @@ pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_conte o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_SAMPLE, &tag); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 1ffb4c16a..5ab91815f 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -409,15 +409,16 @@ static int create_stream( s->buffer_attr.fragsize = s->buffer_attr.tlength/100; } - t = pa_tagstruct_new(NULL, 0); - if (!dev) dev = s->direction == PA_STREAM_PLAYBACK ? s->context->conf->default_sink : s->context->conf->default_source; + + t = pa_tagstruct_command( + s->context, + s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM, + &tag); pa_tagstruct_put( t, - PA_TAG_U32, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM, - PA_TAG_U32, tag = s->context->ctag++, PA_TAG_STRING, s->name, PA_TAG_SAMPLE_SPEC, &s->sample_spec, PA_TAG_CHANNEL_MAP, &s->channel_map, @@ -599,9 +600,7 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); + t = pa_tagstruct_command(s->context, PA_COMMAND_DRAIN_PLAYBACK_STREAM, &tag); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); @@ -689,9 +688,10 @@ pa_operation* pa_stream_get_latency_info(pa_stream *s, pa_stream_get_latency_inf o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY); - pa_tagstruct_putu32(t, tag = s->context->ctag++); + t = pa_tagstruct_command( + s->context, + s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY, + &tag); pa_tagstruct_putu32(t, s->channel); pa_gettimeofday(&now); @@ -742,11 +742,11 @@ int pa_stream_disconnect(pa_stream *s) { pa_stream_ref(s); - t = pa_tagstruct_new(NULL, 0); - - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : - (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM)); - pa_tagstruct_putu32(t, tag = s->context->ctag++); + t = pa_tagstruct_command( + s->context, + s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM : + (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM), + &tag); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s); @@ -848,9 +848,10 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CORK_PLAYBACK_STREAM : PA_COMMAND_CORK_RECORD_STREAM); - pa_tagstruct_putu32(t, tag = s->context->ctag++); + t = pa_tagstruct_command( + s->context, + s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CORK_PLAYBACK_STREAM : PA_COMMAND_CORK_RECORD_STREAM, + &tag); pa_tagstruct_putu32(t, s->channel); pa_tagstruct_put_boolean(t, !!b); pa_pstream_send_tagstruct(s->context->pstream, t); @@ -873,9 +874,7 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, command); - pa_tagstruct_putu32(t, tag = s->context->ctag++); + t = pa_tagstruct_command(s->context, command, &tag); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); @@ -930,9 +929,10 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME); - pa_tagstruct_putu32(t, tag = s->context->ctag++); + t = pa_tagstruct_command( + s->context, + s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME, + &tag); pa_tagstruct_putu32(t, s->channel); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(s->context->pstream, t); diff --git a/src/polyp/subscribe.c b/src/polyp/subscribe.c index 65849b6d4..a4eadbc67 100644 --- a/src/polyp/subscribe.c +++ b/src/polyp/subscribe.c @@ -72,9 +72,7 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_c o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); - pa_tagstruct_putu32(t, tag = c->ctag++); + t = pa_tagstruct_command(c, PA_COMMAND_SUBSCRIBE, &tag); pa_tagstruct_putu32(t, m); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); From 4a64b0d1167e980d81b798d813f35209895f0674 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Feb 2006 02:27:19 +0000 Subject: [PATCH 0481/1514] change pa_log() and friends to not require a trailing \n on all logged strings git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@574 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/caps.c | 6 +- src/daemon/cmdline.c | 16 ++--- src/daemon/cpulimit.c | 2 +- src/daemon/daemon-conf.c | 8 +-- src/daemon/main.c | 45 +++++++------ src/modules/alsa-util.c | 2 +- src/modules/howl-wrap.c | 5 +- src/modules/module-alsa-sink.c | 22 +++---- src/modules/module-alsa-source.c | 22 +++---- src/modules/module-cli.c | 6 +- src/modules/module-combine.c | 26 ++++---- src/modules/module-detect.c | 14 ++--- src/modules/module-esound-compat-spawnfd.c | 4 +- src/modules/module-esound-compat-spawnpid.c | 4 +- src/modules/module-esound-sink.c | 24 +++---- src/modules/module-lirc.c | 20 +++--- src/modules/module-match.c | 12 ++-- src/modules/module-mmkbd-evdev.c | 28 ++++----- src/modules/module-native-protocol-fd.c | 4 +- src/modules/module-null-sink.c | 6 +- src/modules/module-oss-mmap.c | 44 ++++++------- src/modules/module-oss.c | 30 ++++----- src/modules/module-pipe-sink.c | 14 ++--- src/modules/module-pipe-source.c | 14 ++--- src/modules/module-protocol-stub.c | 14 ++--- src/modules/module-sine.c | 6 +- src/modules/module-solaris.c | 30 ++++----- src/modules/module-tunnel.c | 48 +++++++------- src/modules/module-waveout.c | 28 ++++----- src/modules/module-x11-bell.c | 10 +-- src/modules/module-x11-publish.c | 8 +-- src/modules/module-zeroconf-publish.c | 14 ++--- src/modules/oss-util.c | 22 +++---- src/polyp/browser.c | 10 +-- src/polyp/client-conf-x11.c | 4 +- src/polyp/client-conf.c | 2 +- src/polyp/context.c | 12 ++-- src/polyp/mainloop-signal.c | 10 +-- src/polyp/mainloop.c | 14 ++--- src/polyp/stream.c | 4 +- src/polypcore/authkey.c | 14 ++--- src/polypcore/cli.c | 4 +- src/polypcore/client.c | 6 +- src/polypcore/conf-parser.c | 12 ++-- src/polypcore/core-scache.c | 4 +- src/polypcore/core-subscribe.c | 2 +- src/polypcore/ioline.c | 4 +- src/polypcore/log.c | 70 ++++++++++++++------- src/polypcore/memblockq.c | 4 +- src/polypcore/modinfo.c | 2 +- src/polypcore/module.c | 14 ++--- src/polypcore/pdispatch.c | 4 +- src/polypcore/pid.c | 28 ++++----- src/polypcore/protocol-cli.c | 2 +- src/polypcore/protocol-esound.c | 54 ++++++++-------- src/polypcore/protocol-http.c | 4 +- src/polypcore/protocol-native.c | 38 +++++------ src/polypcore/protocol-simple.c | 22 +++---- src/polypcore/pstream.c | 10 +-- src/polypcore/random.c | 2 +- src/polypcore/sample-util.c | 2 +- src/polypcore/sink-input.c | 6 +- src/polypcore/sink.c | 6 +- src/polypcore/socket-client.c | 10 +-- src/polypcore/socket-server.c | 38 +++++------ src/polypcore/socket-util.c | 6 +- src/polypcore/sound-file-stream.c | 4 +- src/polypcore/sound-file.c | 12 ++-- src/polypcore/source-output.c | 6 +- src/polypcore/source.c | 4 +- src/polypcore/util.c | 58 ++++++++--------- src/polypcore/x11wrap.c | 2 +- src/utils/pacmd.c | 20 +++--- src/utils/pax11publish.c | 2 +- 74 files changed, 558 insertions(+), 532 deletions(-) diff --git a/src/daemon/caps.c b/src/daemon/caps.c index e12d33fb0..5c52b77a0 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -45,7 +45,7 @@ void pa_drop_root(void) { if (uid == 0 || geteuid() != 0) return; - pa_log_info(__FILE__": dropping root rights.\n"); + pa_log_info(__FILE__": dropping root rights."); #if defined(HAVE_SETRESUID) setresuid(uid, uid, uid); @@ -83,7 +83,7 @@ int pa_limit_caps(void) { if (cap_set_proc(caps) < 0) goto fail; - pa_log_info(__FILE__": dropped capabilities successfully.\n"); + pa_log_info(__FILE__": dropped capabilities successfully."); r = 0; @@ -104,7 +104,7 @@ int pa_drop_caps(void) { cap_clear(caps); if (cap_set_proc(caps) < 0) { - pa_log(__FILE__": failed to drop capabilities: %s\n", strerror(errno)); + pa_log(__FILE__": failed to drop capabilities: %s", strerror(errno)); goto fail; } diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index b6ab1283a..a6b95a812 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -191,14 +191,14 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_DAEMONIZE: case 'D': if ((conf->daemonize = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --daemonize expects boolean argument\n"); + pa_log(__FILE__": --daemonize expects boolean argument"); goto fail; } break; case ARG_FAIL: if ((conf->fail = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --fail expects boolean argument\n"); + pa_log(__FILE__": --fail expects boolean argument"); goto fail; } break; @@ -208,7 +208,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d if (optarg) { if (pa_daemon_conf_set_log_level(conf, optarg) < 0) { - pa_log(__FILE__": --log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error).\n"); + pa_log(__FILE__": --log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."); goto fail; } } else { @@ -220,21 +220,21 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_HIGH_PRIORITY: if ((conf->high_priority = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --high-priority expects boolean argument\n"); + pa_log(__FILE__": --high-priority expects boolean argument"); goto fail; } break; case ARG_DISALLOW_MODULE_LOADING: if ((conf->disallow_module_loading = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --disallow-module-loading expects boolean argument\n"); + pa_log(__FILE__": --disallow-module-loading expects boolean argument"); goto fail; } break; case ARG_USE_PID_FILE: if ((conf->use_pid_file = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --use-pid-file expects boolean argument\n"); + pa_log(__FILE__": --use-pid-file expects boolean argument"); goto fail; } break; @@ -252,7 +252,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_LOG_TARGET: if (pa_daemon_conf_set_log_target(conf, optarg) < 0) { - pa_log(__FILE__": Invalid log target: use either 'syslog', 'stderr' or 'auto'.\n"); + pa_log(__FILE__": Invalid log target: use either 'syslog', 'stderr' or 'auto'."); goto fail; } break; @@ -271,7 +271,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_RESAMPLE_METHOD: if (pa_daemon_conf_set_resample_method(conf, optarg) < 0) { - pa_log(__FILE__": Invalid resample method '%s'.\n", optarg); + pa_log(__FILE__": Invalid resample method '%s'.", optarg); goto fail; } break; diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index d7a24b8e9..54f111da8 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -169,7 +169,7 @@ int pa_cpu_limit_init(pa_mainloop_api *m) { /* Prepare the main loop pipe */ if (pipe(the_pipe) < 0) { - pa_log(__FILE__": pipe() failed: %s\n", strerror(errno)); + pa_log(__FILE__": pipe() failed: %s", strerror(errno)); return -1; } diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index ecabce401..ac5fbb166 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -160,7 +160,7 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva assert(filename && lvalue && rvalue && data); if (pa_daemon_conf_set_log_target(c, rvalue) < 0) { - pa_log(__FILE__": [%s:%u] Invalid log target '%s'.\n", filename, line, rvalue); + pa_log(__FILE__": [%s:%u] Invalid log target '%s'.", filename, line, rvalue); return -1; } @@ -172,7 +172,7 @@ static int parse_log_level(const char *filename, unsigned line, const char *lval assert(filename && lvalue && rvalue && data); if (pa_daemon_conf_set_log_level(c, rvalue) < 0) { - pa_log(__FILE__": [%s:%u] Invalid log level '%s'.\n", filename, line, rvalue); + pa_log(__FILE__": [%s:%u] Invalid log level '%s'.", filename, line, rvalue); return -1; } @@ -184,7 +184,7 @@ static int parse_resample_method(const char *filename, unsigned line, const char assert(filename && lvalue && rvalue && data); if (pa_daemon_conf_set_resample_method(c, rvalue) < 0) { - pa_log(__FILE__": [%s:%u] Inavalid resample method '%s'.\n", filename, line, rvalue); + pa_log(__FILE__": [%s:%u] Inavalid resample method '%s'.", filename, line, rvalue); return -1; } @@ -236,7 +236,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file); if (!f && errno != ENOENT) { - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno)); + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, strerror(errno)); goto finish; } diff --git a/src/daemon/main.c b/src/daemon/main.c index 3124ad1d0..4b972fe23 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -94,7 +94,7 @@ static void message_cb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { #endif static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, int sig, void *userdata) { - pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig)); + pa_log_info(__FILE__": Got signal %s.", pa_strsignal(sig)); switch (sig) { #ifdef SIGUSR1 @@ -112,7 +112,7 @@ static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, #ifdef SIGHUP case SIGHUP: { char *c = pa_full_status_string(userdata); - pa_log_notice(c); + pa_log_notice("%s", c); pa_xfree(c); return; } @@ -121,7 +121,7 @@ static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, case SIGINT: case SIGTERM: default: - pa_log_info(__FILE__": Exiting.\n"); + pa_log_info(__FILE__": Exiting."); m->quit(m, 1); break; } @@ -161,7 +161,7 @@ int main(int argc, char *argv[]) { suid_root = getuid() != 0 && geteuid() == 0; if (suid_root && (pa_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) { - pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'.\n"); + pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'."); pa_drop_root(); } #else @@ -191,7 +191,7 @@ int main(int argc, char *argv[]) { goto finish; if (pa_cmdline_parse(conf, argc, argv, &d) < 0) { - pa_log(__FILE__": failed to parse command line.\n"); + pa_log(__FILE__": failed to parse command line."); goto finish; } @@ -237,9 +237,9 @@ int main(int argc, char *argv[]) { pid_t pid; if (pa_pid_file_check_running(&pid) < 0) { - pa_log_info(__FILE__": daemon not running\n"); + pa_log_info(__FILE__": daemon not running"); } else { - pa_log_info(__FILE__": daemon running as PID %u\n", pid); + pa_log_info(__FILE__": daemon running as PID %u", pid); retval = 0; } @@ -249,7 +249,7 @@ int main(int argc, char *argv[]) { case PA_CMD_KILL: if (pa_pid_file_kill(SIGINT, NULL) < 0) - pa_log(__FILE__": failed to kill daemon.\n"); + pa_log(__FILE__": failed to kill daemon."); else retval = 0; @@ -264,18 +264,18 @@ int main(int argc, char *argv[]) { int tty_fd; if (pa_stdio_acquire() < 0) { - pa_log(__FILE__": failed to acquire stdio.\n"); + pa_log(__FILE__": failed to acquire stdio."); goto finish; } #ifdef HAVE_FORK if (pipe(daemon_pipe) < 0) { - pa_log(__FILE__": failed to create pipe.\n"); + pa_log(__FILE__": failed to create pipe."); goto finish; } if ((child = fork()) < 0) { - pa_log(__FILE__": fork() failed: %s\n", strerror(errno)); + pa_log(__FILE__": fork() failed: %s", strerror(errno)); goto finish; } @@ -286,14 +286,14 @@ int main(int argc, char *argv[]) { daemon_pipe[1] = -1; if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval)) != sizeof(retval)) { - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s", strerror(errno)); retval = 1; } if (retval) - pa_log(__FILE__": daemon startup failed.\n"); + pa_log(__FILE__": daemon startup failed."); else - pa_log_info(__FILE__": daemon startup successful.\n"); + pa_log_info(__FILE__": daemon startup successful."); goto finish; } @@ -346,7 +346,7 @@ int main(int argc, char *argv[]) { if (conf->use_pid_file) { if (pa_pid_file_create() < 0) { - pa_log(__FILE__": pa_pid_file_create() failed.\n"); + pa_log(__FILE__": pa_pid_file_create() failed."); #ifdef HAVE_FORK if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); @@ -396,23 +396,22 @@ int main(int argc, char *argv[]) { assert(r == 0); buf = pa_strbuf_new(); - assert(buf); if (conf->default_script_file) r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail); if (r >= 0) r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); - pa_log(s = pa_strbuf_tostring_free(buf)); + pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); pa_xfree(s); if (r < 0 && conf->fail) { - pa_log(__FILE__": failed to initialize daemon.\n"); + pa_log(__FILE__": failed to initialize daemon."); #ifdef HAVE_FORK if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); #endif } else if (!c->modules || pa_idxset_size(c->modules) == 0) { - pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n"); + pa_log(__FILE__": daemon startup without any loaded modules, refusing to work."); #ifdef HAVE_FORK if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); @@ -433,13 +432,13 @@ int main(int argc, char *argv[]) { if (c->default_sink_name && pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) { - pa_log_error("%s : Fatal error. Default sink name (%s) does not exist in name register.\n", __FILE__, c->default_sink_name); + pa_log_error("%s : Fatal error. Default sink name (%s) does not exist in name register.", __FILE__, c->default_sink_name); retval = 1; } else { - pa_log_info(__FILE__": Daemon startup complete.\n"); + pa_log_info(__FILE__": Daemon startup complete."); if (pa_mainloop_run(mainloop, &retval) < 0) retval = 1; - pa_log_info(__FILE__": Daemon shutdown initiated.\n"); + pa_log_info(__FILE__": Daemon shutdown initiated."); } } @@ -453,7 +452,7 @@ int main(int argc, char *argv[]) { pa_signal_done(); pa_mainloop_free(mainloop); - pa_log_info(__FILE__": Daemon terminated.\n"); + pa_log_info(__FILE__": Daemon terminated."); finish: diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 68e9f9751..1b254f514 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -63,7 +63,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 goto finish; if (ss->rate != r) - pa_log_info(__FILE__": device doesn't support %u Hz, changed to %u Hz.\n", ss->rate, r); + pa_log_info(__FILE__": device doesn't support %u Hz, changed to %u Hz.", ss->rate, r); if (snd_pcm_prepare(pcm_handle) < 0) goto finish; diff --git a/src/modules/howl-wrap.c b/src/modules/howl-wrap.c index b3fe81662..f4605fb2d 100644 --- a/src/modules/howl-wrap.c +++ b/src/modules/howl-wrap.c @@ -35,7 +35,6 @@ struct pa_howl_wrapper { pa_io_event *io_event; sw_discovery discovery; - }; static void howl_io_event(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { @@ -51,7 +50,7 @@ static void howl_io_event(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event return; fail: - pa_log(__FILE__": howl connection died.\n"); + pa_log_error(__FILE__": howl connection died."); w->core->mainloop->io_free(w->io_event); w->io_event = NULL; } @@ -62,7 +61,7 @@ static pa_howl_wrapper* howl_wrapper_new(pa_core *c) { assert(c); if (sw_discovery_init(&session) != SW_OKAY) { - pa_log("sw_discovery_init() failed.\n"); + pa_log_error(__FILE__": sw_discovery_init() failed."); return NULL; } diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 6ea1e1372..e37367c89 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -86,10 +86,10 @@ static void update_usage(struct userdata *u) { static void xrun_recovery(struct userdata *u) { assert(u); - pa_log(__FILE__": *** ALSA-XRUN (playback) ***\n"); + pa_log(__FILE__": *** ALSA-XRUN (playback) ***"); if (snd_pcm_prepare(u->pcm_handle) < 0) - pa_log(__FILE__": snd_pcm_prepare() failed\n"); + pa_log(__FILE__": snd_pcm_prepare() failed"); } static void do_write(struct userdata *u) { @@ -121,7 +121,7 @@ static void do_write(struct userdata *u) { continue; } - pa_log(__FILE__": snd_pcm_writei() failed\n"); + pa_log(__FILE__": snd_pcm_writei() failed"); return; } @@ -158,7 +158,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { assert(s && u && u->sink); if (snd_pcm_delay(u->pcm_handle, &frames) < 0) { - pa_log(__FILE__": failed to get delay\n"); + pa_log(__FILE__": failed to get delay"); s->get_latency = NULL; return 0; } @@ -186,13 +186,13 @@ int pa__init(pa_core *c, pa_module*m) { int err; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification"); goto fail; } frame_size = pa_frame_size(&ss); @@ -200,7 +200,7 @@ int pa__init(pa_core *c, pa_module*m) { periods = 8; fragsize = 1024; if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { - pa_log(__FILE__": failed to parse buffer metrics\n"); + pa_log(__FILE__": failed to parse buffer metrics"); goto fail; } period_size = fragsize; @@ -211,12 +211,12 @@ int pa__init(pa_core *c, pa_module*m) { snd_config_update_free_global(); if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { - pa_log(__FILE__": Error opening PCM device %s: %s\n", dev, snd_strerror(err)); + pa_log(__FILE__": Error opening PCM device %s: %s", dev, snd_strerror(err)); goto fail; } if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) { - pa_log(__FILE__": Failed to set hardware parameters: %s\n", snd_strerror(err)); + pa_log(__FILE__": Failed to set hardware parameters: %s", snd_strerror(err)); goto fail; } @@ -229,14 +229,14 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { - pa_log(__FILE__": failed to obtain file descriptors\n"); + pa_log(__FILE__": failed to obtain file descriptors"); goto fail; } u->frame_size = frame_size; u->fragment_size = period_size; - pa_log_info(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); + pa_log_info(__FILE__": using %u fragments of size %u bytes.", periods, u->fragment_size); u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size, c->memblock_stat); assert(u->silence.memblock); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 4f281aa76..bf031350d 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -85,10 +85,10 @@ static void update_usage(struct userdata *u) { static void xrun_recovery(struct userdata *u) { assert(u); - pa_log(__FILE__": *** ALSA-XRUN (capture) ***\n"); + pa_log(__FILE__": *** ALSA-XRUN (capture) ***"); if (snd_pcm_prepare(u->pcm_handle) < 0) - pa_log(__FILE__": snd_pcm_prepare() failed\n"); + pa_log(__FILE__": snd_pcm_prepare() failed"); } static void do_read(struct userdata *u) { @@ -117,7 +117,7 @@ static void do_read(struct userdata *u) { continue; } - pa_log(__FILE__": snd_pcm_readi() failed: %s\n", strerror(-frames)); + pa_log(__FILE__": snd_pcm_readi() failed: %s", strerror(-frames)); return; } @@ -157,7 +157,7 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { assert(s && u && u->source); if (snd_pcm_delay(u->pcm_handle, &frames) < 0) { - pa_log(__FILE__": failed to get delay\n"); + pa_log(__FILE__": failed to get delay"); s->get_latency = NULL; return 0; } @@ -177,13 +177,13 @@ int pa__init(pa_core *c, pa_module*m) { int err; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification"); goto fail; } frame_size = pa_frame_size(&ss); @@ -191,7 +191,7 @@ int pa__init(pa_core *c, pa_module*m) { periods = 12; fragsize = 1024; if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { - pa_log(__FILE__": failed to parse buffer metrics\n"); + pa_log(__FILE__": failed to parse buffer metrics"); goto fail; } period_size = fragsize; @@ -202,12 +202,12 @@ int pa__init(pa_core *c, pa_module*m) { snd_config_update_free_global(); if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { - pa_log(__FILE__": Error opening PCM device %s: %s\n", dev, snd_strerror(err)); + pa_log(__FILE__": Error opening PCM device %s: %s", dev, snd_strerror(err)); goto fail; } if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) { - pa_log(__FILE__": Failed to set hardware parameters: %s\n", snd_strerror(err)); + pa_log(__FILE__": Failed to set hardware parameters: %s", snd_strerror(err)); goto fail; } @@ -220,14 +220,14 @@ int pa__init(pa_core *c, pa_module*m) { u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { - pa_log(__FILE__": failed to obtain file descriptors\n"); + pa_log(__FILE__": failed to obtain file descriptors"); goto fail; } u->frame_size = frame_size; u->fragment_size = period_size; - pa_log(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); + pa_log(__FILE__": using %u fragments of size %u bytes.", periods, u->fragment_size); u->memchunk.memblock = NULL; u->memchunk.index = u->memchunk.length = 0; diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c index c782ff8db..41e33c7f0 100644 --- a/src/modules/module-cli.c +++ b/src/modules/module-cli.c @@ -52,17 +52,17 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (c->running_as_daemon) { - pa_log_info(__FILE__": Running as daemon so won't load this module.\n"); + pa_log_info(__FILE__": Running as daemon so won't load this module."); return 0; } if (m->argument) { - pa_log(__FILE__": module doesn't accept arguments.\n"); + pa_log(__FILE__": module doesn't accept arguments."); return -1; } if (pa_stdio_acquire() < 0) { - pa_log(__FILE__": STDIN/STDUSE already in use.\n"); + pa_log(__FILE__": STDIN/STDUSE already in use."); return -1; } diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 750eca672..28e854279 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -112,7 +112,7 @@ static void adjust_rates(struct userdata *u) { target_latency = max_sink_latency > min_total_latency ? max_sink_latency : min_total_latency; - pa_log_info(__FILE__": [%s] target latency is %0.0f usec.\n", u->sink->name, (float) target_latency); + pa_log_info(__FILE__": [%s] target latency is %0.0f usec.", u->sink->name, (float) target_latency); base_rate = u->sink->sample_spec.rate; @@ -125,9 +125,9 @@ static void adjust_rates(struct userdata *u) { r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/ 1000000); if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) - pa_log_warn(__FILE__": [%s] sample rates too different, not adjusting (%u vs. %u).\n", o->sink_input->name, base_rate, r); + pa_log_warn(__FILE__": [%s] sample rates too different, not adjusting (%u vs. %u).", o->sink_input->name, base_rate, r); else { - pa_log_info(__FILE__": [%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.\n", o->sink_input->name, r, (double) r / base_rate, (float) o->total_latency); + pa_log_info(__FILE__": [%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.", o->sink_input->name, r, (double) r / base_rate, (float) o->total_latency); pa_sink_input_set_rate(o->sink_input, r); } } @@ -297,13 +297,13 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments"); goto fail; } if ((rm = pa_modargs_get_value(ma, "resample_method", NULL))) { if ((resample_method = pa_parse_resample_method(rm)) < 0) { - pa_log(__FILE__": invalid resample method '%s'\n", rm); + pa_log(__FILE__": invalid resample method '%s'", rm); goto fail; } } @@ -320,22 +320,22 @@ int pa__init(pa_core *c, pa_module*m) { PA_LLIST_HEAD_INIT(struct output, u->outputs); if (pa_modargs_get_value_u32(ma, "adjust_time", &u->adjust_time) < 0) { - pa_log(__FILE__": failed to parse adjust_time value\n"); + pa_log(__FILE__": failed to parse adjust_time value"); goto fail; } if (!(master_name = pa_modargs_get_value(ma, "master", NULL)) || !(slaves = pa_modargs_get_value(ma, "slaves", NULL))) { - pa_log(__FILE__": no master or slave sinks specified\n"); + pa_log(__FILE__": no master or slave sinks specified"); goto fail; } if (!(master_sink = pa_namereg_get(c, master_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": invalid master sink '%s'\n", master_name); + pa_log(__FILE__": invalid master sink '%s'", master_name); goto fail; } if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec, &master_sink->channel_map))) { - pa_log(__FILE__": failed to create sink\n"); + pa_log(__FILE__": failed to create sink"); goto fail; } @@ -345,7 +345,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->userdata = u; if (!(u->master = output_new(u, master_sink, resample_method))) { - pa_log(__FILE__": failed to create master sink input on sink '%s'.\n", u->sink->name); + pa_log(__FILE__": failed to create master sink input on sink '%s'.", u->sink->name); goto fail; } @@ -354,20 +354,20 @@ int pa__init(pa_core *c, pa_module*m) { pa_sink *slave_sink; if (!(slave_sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": invalid slave sink '%s'\n", n); + pa_log(__FILE__": invalid slave sink '%s'", n); goto fail; } pa_xfree(n); if (!output_new(u, slave_sink, resample_method)) { - pa_log(__FILE__": failed to create slave sink input on sink '%s'.\n", slave_sink->name); + pa_log(__FILE__": failed to create slave sink input on sink '%s'.", slave_sink->name); goto fail; } } if (u->n_outputs <= 1) - pa_log_warn(__FILE__": WARNING: no slave sinks specified.\n"); + pa_log_warn(__FILE__": WARNING: no slave sinks specified."); if (u->adjust_time > 0) { pa_gettimeofday(&tv); diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 18e22de64..b24d838be 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -66,7 +66,7 @@ static int detect_alsa(pa_core *c, int just_one) { if (!(f = fopen("/proc/asound/devices", "r"))) { if (errno != ENOENT) - pa_log_error(__FILE__": open(\"/proc/asound/devices\") failed: %s\n", strerror(errno)); + pa_log_error(__FILE__": open(\"/proc/asound/devices\") failed: %s", strerror(errno)); return -1; } @@ -129,7 +129,7 @@ static int detect_oss(pa_core *c, int just_one) { !(f = fopen("/proc/asound/oss/sndstat", "r"))) { if (errno != ENOENT) - pa_log_error(__FILE__": failed to open OSS sndstat device: %s\n", strerror(errno)); + pa_log_error(__FILE__": failed to open OSS sndstat device: %s", strerror(errno)); return -1; } @@ -185,7 +185,7 @@ static int detect_solaris(pa_core *c, int just_one) { if (stat(dev, &s) < 0) { if (errno != ENOENT) - pa_log_error(__FILE__": failed to open device %s: %s\n", dev, strerror(errno)); + pa_log_error(__FILE__": failed to open device %s: %s", dev, strerror(errno)); return -1; } @@ -227,12 +227,12 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments\n"); + pa_log(__FILE__": Failed to parse module arguments"); goto fail; } if (pa_modargs_get_value_boolean(ma, "just-one", &just_one) < 0) { - pa_log(__FILE__": just_one= expects a boolean argument.\n"); + pa_log(__FILE__": just_one= expects a boolean argument."); goto fail; } @@ -249,11 +249,11 @@ int pa__init(pa_core *c, pa_module*m) { if ((n = detect_waveout(c, just_one)) <= 0) #endif { - pa_log_warn(__FILE__": failed to detect any sound hardware.\n"); + pa_log_warn(__FILE__": failed to detect any sound hardware."); goto fail; } - pa_log_info(__FILE__": loaded %i modules.\n", n); + pa_log_info(__FILE__": loaded %i modules.", n); /* We were successful and can unload ourselves now. */ pa_module_unload_request(m); diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index 5c656be9c..9b72448fa 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -54,12 +54,12 @@ int pa__init(pa_core *c, pa_module*m) { if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || pa_modargs_get_value_s32(ma, "fd", &fd) < 0 || fd < 0) { - pa_log(__FILE__": Failed to parse module arguments\n"); + pa_log(__FILE__": Failed to parse module arguments"); goto finish; } if (pa_loop_write(fd, &x, sizeof(x)) != sizeof(x)) - pa_log(__FILE__": WARNING: write(%u, 1, 1) failed: %s\n", fd, strerror(errno)); + pa_log(__FILE__": WARNING: write(%u, 1, 1) failed: %s", fd, strerror(errno)); close(fd); diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index 5daa1297a..f8c07d316 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -54,12 +54,12 @@ int pa__init(pa_core *c, pa_module*m) { if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || pa_modargs_get_value_u32(ma, "pid", &pid) < 0 || !pid) { - pa_log(__FILE__": Failed to parse module arguments\n"); + pa_log(__FILE__": Failed to parse module arguments"); goto finish; } if (kill(pid, SIGUSR1) < 0) - pa_log(__FILE__": WARNING: kill(%u) failed: %s\n", pid, strerror(errno)); + pa_log(__FILE__": WARNING: kill(%u) failed: %s", pid, strerror(errno)); pa_module_unload_request(m); diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 4f724811d..1cc75502d 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -127,7 +127,7 @@ static int do_write(struct userdata *u) { assert(u->write_index < u->write_length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) <= 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); return -1; } @@ -149,7 +149,7 @@ static int do_write(struct userdata *u) { assert(u->memchunk.memblock && u->memchunk.length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); return -1; } @@ -174,7 +174,7 @@ static int handle_response(struct userdata *u) { /* Process auth data */ if (!*(int32_t*) u->read_data) { - pa_log(__FILE__": Authentication failed: %s\n", strerror(errno)); + pa_log(__FILE__": Authentication failed: %s", strerror(errno)); return -1; } @@ -199,7 +199,7 @@ static int handle_response(struct userdata *u) { /* Process latency info */ u->latency = (pa_usec_t) ((double) (*(int32_t*) u->read_data) * 1000000 / 44100); if (u->latency > 10000000) { - pa_log(__FILE__": WARNING! Invalid latency information received from server\n"); + pa_log(__FILE__": WARNING! Invalid latency information received from server"); u->latency = 0; } @@ -244,7 +244,7 @@ static int do_read(struct userdata *u) { assert(u->read_index < u->read_length); if ((r = pa_iochannel_read(u->io, (uint8_t*) u->read_data + u->read_index, u->read_length - u->read_index)) <= 0) { - pa_log(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + pa_log(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF"); cancel(u); return -1; } @@ -304,7 +304,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, vo u->client = NULL; if (!io) { - pa_log(__FILE__": connection failed: %s\n", strerror(errno)); + pa_log(__FILE__": connection failed: %s", strerror(errno)); cancel(u); return; } @@ -321,19 +321,19 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": invalid sample format specification\n"); + pa_log(__FILE__": invalid sample format specification"); goto fail; } if ((ss.format != PA_SAMPLE_U8 && ss.format != PA_SAMPLE_S16NE) || (ss.channels > 2)) { - pa_log(__FILE__": esound sample type support is limited to mono/stereo and U8 or S16NE sample data\n"); + pa_log(__FILE__": esound sample type support is limited to mono/stereo and U8 or S16NE sample data"); goto fail; } @@ -354,12 +354,12 @@ int pa__init(pa_core *c, pa_module*m) { u->latency = 0; if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { - pa_log(__FILE__": failed to create sink.\n"); + pa_log(__FILE__": failed to create sink."); goto fail; } if (!(u->client = pa_socket_client_new_string(u->core->mainloop, p = pa_modargs_get_value(ma, "server", ESD_UNIX_SOCKET_NAME), ESD_DEFAULT_PORT))) { - pa_log(__FILE__": failed to connect to server.\n"); + pa_log(__FILE__": failed to connect to server."); goto fail; } pa_socket_client_set_callback(u->client, on_connection, u); @@ -367,7 +367,7 @@ int pa__init(pa_core *c, pa_module*m) { /* Prepare the initial request */ u->write_data = pa_xmalloc(u->write_length = ESD_KEY_LEN + sizeof(int32_t)); if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", ".esd_auth"), u->write_data, ESD_KEY_LEN) < 0) { - pa_log(__FILE__": failed to load cookie\n"); + pa_log(__FILE__": failed to load cookie"); goto fail; } *(int32_t*) ((uint8_t*) u->write_data + ESD_KEY_LEN) = ESD_ENDIAN_KEY; diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index ea8a2bd2b..3bb0dc749 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -69,7 +69,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC assert(u); if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { - pa_log(__FILE__": lost connection to LIRC daemon.\n"); + pa_log(__FILE__": lost connection to LIRC daemon."); goto fail; } @@ -77,19 +77,19 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC char *c; if (lirc_nextcode(&code) != 0 || !code) { - pa_log(__FILE__": lirc_nextcode() failed.\n"); + pa_log(__FILE__": lirc_nextcode() failed."); goto fail; } c = pa_xstrdup(code); c[strcspn(c, "\n\r")] = 0; - pa_log_debug(__FILE__": raw IR code '%s'\n", c); + pa_log_debug(__FILE__": raw IR code '%s'", c); pa_xfree(c); while (lirc_code2char(u->config, code, &name) == 0 && name) { enum { INVALID, UP, DOWN, MUTE, RESET, MUTE_TOGGLE } volchange = INVALID; - pa_log_info(__FILE__": translated IR code '%s'\n", name); + pa_log_info(__FILE__": translated IR code '%s'", name); if (strcasecmp(name, "volume-up") == 0) volchange = UP; @@ -103,12 +103,12 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC volchange = RESET; if (volchange == INVALID) - pa_log_warn(__FILE__": recieved unknown IR code '%s'\n", name); + pa_log_warn(__FILE__": recieved unknown IR code '%s'", name); else { pa_sink *s; if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) - pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name); + pa_log(__FILE__": failed to get sink '%s'", u->sink_name); else { pa_volume_t v = pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE)); pa_cvolume cv; @@ -173,12 +173,12 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (lirc_in_use) { - pa_log(__FILE__": module-lirc may no be loaded twice.\n"); + pa_log(__FILE__": module-lirc may no be loaded twice."); return -1; } if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments\n"); + pa_log(__FILE__": Failed to parse module arguments"); goto fail; } @@ -191,12 +191,12 @@ int pa__init(pa_core *c, pa_module*m) { u->mute_toggle_save = 0; if ((u->lirc_fd = lirc_init((char*) pa_modargs_get_value(ma, "appname", "polypaudio"), 1)) < 0) { - pa_log(__FILE__": lirc_init() failed.\n"); + pa_log(__FILE__": lirc_init() failed."); goto fail; } if (lirc_readconfig((char*) pa_modargs_get_value(ma, "config", NULL), &u->config, NULL) < 0) { - pa_log(__FILE__": lirc_readconfig() failed.\n"); + pa_log(__FILE__": lirc_readconfig() failed."); goto fail; } diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 1fb7233cc..598175170 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -84,7 +84,7 @@ static int load_rules(struct userdata *u, const char *filename) { pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn); if (!f) { - pa_log(__FILE__": failed to open file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": failed to open file '%s': %s", fn, strerror(errno)); goto finish; } @@ -111,13 +111,13 @@ static int load_rules(struct userdata *u, const char *filename) { if (!*v) { - pa_log(__FILE__ ": [%s:%u] failed to parse line - too few words\n", filename, n); + pa_log(__FILE__ ": [%s:%u] failed to parse line - too few words", filename, n); goto finish; } *d = 0; if (pa_atou(v, &k) < 0) { - pa_log(__FILE__": [%s:%u] failed to parse volume\n", filename, n); + pa_log(__FILE__": [%s:%u] failed to parse volume", filename, n); goto finish; } @@ -125,7 +125,7 @@ static int load_rules(struct userdata *u, const char *filename) { if (regcomp(®ex, ln, REG_EXTENDED|REG_NOSUB) != 0) { - pa_log(__FILE__": [%s:%u] invalid regular expression\n", filename, n); + pa_log(__FILE__": [%s:%u] invalid regular expression", filename, n); goto finish; } @@ -173,7 +173,7 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v for (r = u->rules; r; r = r->next) { if (!regexec(&r->regex, si->name, 0, NULL, 0)) { pa_cvolume cv; - pa_log_debug(__FILE__": changing volume of sink input '%s' to 0x%03x\n", si->name, r->volume); + pa_log_debug(__FILE__": changing volume of sink input '%s' to 0x%03x", si->name, r->volume); pa_cvolume_set(&cv, r->volume, si->sample_spec.channels); pa_sink_input_set_volume(si, &cv); } @@ -186,7 +186,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments\n"); + pa_log(__FILE__": Failed to parse module arguments"); goto fail; } diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index b60f786d5..79194ad8b 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -81,7 +81,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC assert(u); if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { - pa_log(__FILE__": lost connection to evdev device.\n"); + pa_log(__FILE__": lost connection to evdev device."); goto fail; } @@ -89,14 +89,14 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC struct input_event ev; if (pa_loop_read(u->fd, &ev, sizeof(ev)) <= 0) { - pa_log(__FILE__": failed to read from event device: %s\n", strerror(errno)); + pa_log(__FILE__": failed to read from event device: %s", strerror(errno)); goto fail; } if (ev.type == EV_KEY && (ev.value == 1 || ev.value == 2)) { enum { INVALID, UP, DOWN, MUTE_TOGGLE } volchange = INVALID; - pa_log_debug(__FILE__": key code=%u, value=%u\n", ev.code, ev.value); + pa_log_debug(__FILE__": key code=%u, value=%u", ev.code, ev.value); switch (ev.code) { case KEY_VOLUMEDOWN: volchange = DOWN; break; @@ -108,7 +108,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_sink *s; if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) - pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name); + pa_log(__FILE__": failed to get sink '%s'", u->sink_name); else { pa_volume_t v = pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE)); pa_cvolume cv; @@ -167,7 +167,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments\n"); + pa_log(__FILE__": Failed to parse module arguments"); goto fail; } @@ -179,40 +179,40 @@ int pa__init(pa_core *c, pa_module*m) { u->mute_toggle_save = 0; if ((u->fd = open(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY)) < 0) { - pa_log(__FILE__": failed to open evdev device: %s\n", strerror(errno)); + pa_log(__FILE__": failed to open evdev device: %s", strerror(errno)); goto fail; } if (ioctl(u->fd, EVIOCGVERSION, &version) < 0) { - pa_log(__FILE__": EVIOCGVERSION failed: %s\n", strerror(errno)); + pa_log(__FILE__": EVIOCGVERSION failed: %s", strerror(errno)); goto fail; } - pa_log_info(__FILE__": evdev driver version %i.%i.%i\n", version >> 16, (version >> 8) & 0xff, version & 0xff); + pa_log_info(__FILE__": evdev driver version %i.%i.%i", version >> 16, (version >> 8) & 0xff, version & 0xff); if(ioctl(u->fd, EVIOCGID, &input_id)) { - pa_log(__FILE__": EVIOCGID failed: %s\n", strerror(errno)); + pa_log(__FILE__": EVIOCGID failed: %s", strerror(errno)); goto fail; } - pa_log_info(__FILE__": evdev vendor 0x%04hx product 0x%04hx version 0x%04hx bustype %u\n", + pa_log_info(__FILE__": evdev vendor 0x%04hx product 0x%04hx version 0x%04hx bustype %u", input_id.vendor, input_id.product, input_id.version, input_id.bustype); if(ioctl(u->fd, EVIOCGNAME(sizeof(name)), name) < 0) { - pa_log(__FILE__": EVIOCGNAME failed: %s\n", strerror(errno)); + pa_log(__FILE__": EVIOCGNAME failed: %s", strerror(errno)); goto fail; } - pa_log_info(__FILE__": evdev device name: %s\n", name); + pa_log_info(__FILE__": evdev device name: %s", name); memset(evtype_bitmask, 0, sizeof(evtype_bitmask)); if (ioctl(u->fd, EVIOCGBIT(0, EV_MAX), evtype_bitmask) < 0) { - pa_log(__FILE__": EVIOCGBIT failed: %s\n", strerror(errno)); + pa_log(__FILE__": EVIOCGBIT failed: %s", strerror(errno)); goto fail; } if (!test_bit(EV_KEY, evtype_bitmask)) { - pa_log(__FILE__": device has no keys.\n"); + pa_log(__FILE__": device has no keys."); goto fail; } diff --git a/src/modules/module-native-protocol-fd.c b/src/modules/module-native-protocol-fd.c index abc531b31..e3caf55a0 100644 --- a/src/modules/module-native-protocol-fd.c +++ b/src/modules/module-native-protocol-fd.c @@ -53,12 +53,12 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments."); goto finish; } if (pa_modargs_get_value_s32(ma, "fd", &fd) < 0) { - pa_log(__FILE__": invalid file descriptor.\n"); + pa_log(__FILE__": invalid file descriptor."); goto finish; } diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 5731a4032..611782399 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -92,13 +92,13 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments."); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": invalid sample format specification.\n"); + pa_log(__FILE__": invalid sample format specification."); goto fail; } @@ -108,7 +108,7 @@ int pa__init(pa_core *c, pa_module*m) { m->userdata = u; if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { - pa_log(__FILE__": failed to create sink.\n"); + pa_log(__FILE__": failed to create sink."); goto fail; } diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 82f65a3c1..9687c9084 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -130,7 +130,7 @@ static void do_write(struct userdata *u) { update_usage(u); if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s", strerror(errno)); return; } @@ -192,7 +192,7 @@ static void do_read(struct userdata *u) { update_usage(u); if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s", strerror(errno)); return; } @@ -225,7 +225,7 @@ static int sink_get_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_get_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support reading mixer settings: %s\n", strerror(errno)); + pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); s->get_hw_volume = NULL; return -1; } @@ -237,7 +237,7 @@ static int sink_set_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_set_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support writing mixer settings: %s\n", strerror(errno)); + pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); s->set_hw_volume = NULL; return -1; } @@ -265,17 +265,17 @@ int pa__init(pa_core *c, pa_module*m) { u->core = c; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log(__FILE__": record= and playback= expect numeric arguments.\n"); + pa_log(__FILE__": record= and playback= expect numeric arguments."); goto fail; } if (!playback && !record) { - pa_log(__FILE__": neither playback nor record enabled for device.\n"); + pa_log(__FILE__": neither playback nor record enabled for device."); goto fail; } @@ -284,13 +284,13 @@ int pa__init(pa_core *c, pa_module*m) { nfrags = 12; frag_size = 1024; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { - pa_log(__FILE__": failed to parse fragments arguments\n"); + pa_log(__FILE__": failed to parse fragments arguments"); goto fail; } u->sample_spec = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &u->sample_spec) < 0) { - pa_log(__FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification"); goto fail; } @@ -298,16 +298,16 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0) - pa_log_info(__FILE__": hardware name is '%s'.\n", hwdesc); + pa_log_info(__FILE__": hardware name is '%s'.", hwdesc); else hwdesc[0] = 0; if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_REALTIME) || !(caps & DSP_CAP_TRIGGER)) { - pa_log(__FILE__": OSS device not mmap capable.\n"); + pa_log(__FILE__": OSS device not mmap capable."); goto fail; } - pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info(__FILE__": device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (nfrags >= 2 && frag_size >= 1) if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0) @@ -318,19 +318,19 @@ int pa__init(pa_core *c, pa_module*m) { if (mode != O_WRONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETISPACE: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETISPACE: %s", strerror(errno)); goto fail; } - pa_log_info(__FILE__": input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log_info(__FILE__": input -- %u fragments of size %u.", info.fragstotal, info.fragsize); u->in_mmap_length = (u->in_fragment_size = info.fragsize) * (u->in_fragments = info.fragstotal); if ((u->in_mmap = mmap(NULL, u->in_mmap_length, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { if (mode == O_RDWR) { - pa_log(__FILE__": mmap failed for input. Changing to O_WRONLY mode.\n"); + pa_log(__FILE__": mmap failed for input. Changing to O_WRONLY mode."); mode = O_WRONLY; } else { - pa_log(__FILE__": mmap(): %s\n", strerror(errno)); + pa_log(__FILE__": mmap(): %s", strerror(errno)); goto fail; } } else { @@ -353,19 +353,19 @@ int pa__init(pa_core *c, pa_module*m) { if (mode != O_RDONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETOSPACE: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETOSPACE: %s", strerror(errno)); goto fail; } - pa_log_info(__FILE__": output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log_info(__FILE__": output -- %u fragments of size %u.", info.fragstotal, info.fragsize); u->out_mmap_length = (u->out_fragment_size = info.fragsize) * (u->out_fragments = info.fragstotal); if ((u->out_mmap = mmap(NULL, u->out_mmap_length, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { if (mode == O_RDWR) { - pa_log(__FILE__": mmap filed for output. Changing to O_RDONLY mode.\n"); + pa_log(__FILE__": mmap filed for output. Changing to O_RDONLY mode."); mode = O_RDONLY; } else { - pa_log(__FILE__": mmap(): %s\n", strerror(errno)); + pa_log(__FILE__": mmap(): %s", strerror(errno)); goto fail; } } else { @@ -392,12 +392,12 @@ int pa__init(pa_core *c, pa_module*m) { zero = 0; if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s", strerror(errno)); goto fail; } if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s", strerror(errno)); goto fail; } diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 0a3c61433..67ece5a71 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -133,7 +133,7 @@ static void do_write(struct userdata *u) { assert(memchunk->length); if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); break; } @@ -186,7 +186,7 @@ static void do_read(struct userdata *u) { if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s", strerror(errno)); break; } @@ -221,7 +221,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { assert(s && u && u->sink); if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) { - pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY: %s\n", strerror(errno)); + pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY: %s", strerror(errno)); s->get_latency = NULL; return 0; } @@ -257,7 +257,7 @@ static int sink_get_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_get_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support reading mixer settings: %s\n", strerror(errno)); + pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); s->get_hw_volume = NULL; return -1; } @@ -269,7 +269,7 @@ static int sink_set_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_set_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support writing mixer settings: %s\n", strerror(errno)); + pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); s->set_hw_volume = NULL; return -1; } @@ -293,17 +293,17 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log(__FILE__": record= and playback= expect numeric argument.\n"); + pa_log(__FILE__": record= and playback= expect numeric argument."); goto fail; } if (!playback && !record) { - pa_log(__FILE__": neither playback nor record enabled for device.\n"); + pa_log(__FILE__": neither playback nor record enabled for device."); goto fail; } @@ -312,13 +312,13 @@ int pa__init(pa_core *c, pa_module*m) { nfrags = 12; frag_size = 1024; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { - pa_log(__FILE__": failed to parse fragments arguments\n"); + pa_log(__FILE__": failed to parse fragments arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification"); goto fail; } @@ -326,11 +326,11 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0) - pa_log_info(__FILE__": hardware name is '%s'.\n", hwdesc); + pa_log_info(__FILE__": hardware name is '%s'.", hwdesc); else hwdesc[0] = 0; - pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info(__FILE__": device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (nfrags >= 2 && frag_size >= 1) if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) @@ -340,7 +340,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETBLKSIZE: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETBLKSIZE: %s", strerror(errno)); goto fail; } assert(frag_size); @@ -351,13 +351,13 @@ int pa__init(pa_core *c, pa_module*m) { u->use_getospace = u->use_getispace = 0; if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { - pa_log_info(__FILE__": input -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log_info(__FILE__": input -- %u fragments of size %u.", info.fragstotal, info.fragsize); in_frag_size = info.fragsize; u->use_getispace = 1; } if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { - pa_log_info(__FILE__": output -- %u fragments of size %u.\n", info.fragstotal, info.fragsize); + pa_log_info(__FILE__": output -- %u fragments of size %u.", info.fragstotal, info.fragsize); out_frag_size = info.fragsize; u->use_getospace = 1; } diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 6ace377f0..4ddf26acb 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -91,7 +91,7 @@ static void do_write(struct userdata *u) { assert(u->memchunk.memblock && u->memchunk.length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); return; } @@ -141,32 +141,32 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": invalid sample format specification\n"); + pa_log(__FILE__": invalid sample format specification"); goto fail; } mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); if ((fd = open(p, O_RDWR)) < 0) { - pa_log(__FILE__": open('%s'): %s\n", p, strerror(errno)); + pa_log(__FILE__": open('%s'): %s", p, strerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); if (fstat(fd, &st) < 0) { - pa_log(__FILE__": fstat('%s'): %s\n", p, strerror(errno)); + pa_log(__FILE__": fstat('%s'): %s", p, strerror(errno)); goto fail; } if (!S_ISFIFO(st.st_mode)) { - pa_log(__FILE__": '%s' is not a FIFO.\n", p); + pa_log(__FILE__": '%s' is not a FIFO.", p); goto fail; } @@ -177,7 +177,7 @@ int pa__init(pa_core *c, pa_module*m) { m->userdata = u; if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { - pa_log(__FILE__": failed to create sink.\n"); + pa_log(__FILE__": failed to create sink."); goto fail; } u->sink->notify = notify_cb; diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index a7bb0ce7d..d3753d25c 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -88,7 +88,7 @@ static void do_read(struct userdata *u) { assert(u->chunk.memblock && u->chunk.memblock->length > u->chunk.index); if ((r = pa_iochannel_read(u->io, (uint8_t*) u->chunk.memblock->data + u->chunk.index, u->chunk.memblock->length - u->chunk.index)) <= 0) { - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s", strerror(errno)); return; } @@ -119,32 +119,32 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": invalid sample format specification\n"); + pa_log(__FILE__": invalid sample format specification"); goto fail; } mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); if ((fd = open(p, O_RDWR)) < 0) { - pa_log(__FILE__": open('%s'): %s\n", p, strerror(errno)); + pa_log(__FILE__": open('%s'): %s", p, strerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); if (fstat(fd, &st) < 0) { - pa_log(__FILE__": fstat('%s'): %s\n", p, strerror(errno)); + pa_log(__FILE__": fstat('%s'): %s", p, strerror(errno)); goto fail; } if (!S_ISFIFO(st.st_mode)) { - pa_log(__FILE__": '%s' is not a FIFO.\n", p); + pa_log(__FILE__": '%s' is not a FIFO.", p); goto fail; } @@ -154,7 +154,7 @@ int pa__init(pa_core *c, pa_module*m) { u->core = c; if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) { - pa_log(__FILE__": failed to create source.\n"); + pa_log(__FILE__": failed to create source."); goto fail; } u->source->userdata = u; diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 641e3624d..749a7ace6 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -161,12 +161,12 @@ static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) { const char *listen_on; if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) { - pa_log(__FILE__": loopback= expects a boolean argument.\n"); + pa_log(__FILE__": loopback= expects a boolean argument."); return NULL; } if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { - pa_log(__FILE__": port= expects a numerical argument between 1 and 65535.\n"); + pa_log(__FILE__": port= expects a numerical argument between 1 and 65535."); return NULL; } @@ -194,12 +194,12 @@ static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) { pa_runtime_path(v, tmp, sizeof(tmp)); if (pa_make_secure_parent_dir(tmp) < 0) { - pa_log(__FILE__": Failed to create secure socket directory.\n"); + pa_log(__FILE__": Failed to create secure socket directory."); return NULL; } if ((r = pa_unix_socket_remove_stale(tmp)) < 0) { - pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s\n", tmp, strerror(errno)); + pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s", tmp, strerror(errno)); return NULL; } @@ -220,7 +220,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments\n"); + pa_log(__FILE__": Failed to parse module arguments"); goto finish; } @@ -246,9 +246,9 @@ void pa__done(pa_core *c, pa_module*m) { #if defined(USE_PROTOCOL_ESOUND) && !defined(USE_TCP_SOCKETS) if (remove(ESD_UNIX_SOCKET_NAME) != 0) - pa_log("%s: Failed to remove %s : %s.\n", __FILE__, ESD_UNIX_SOCKET_NAME, strerror (errno)); + pa_log("%s: Failed to remove %s : %s.", __FILE__, ESD_UNIX_SOCKET_NAME, strerror (errno)); if (remove(ESD_UNIX_SOCKET_DIR) != 0) - pa_log("%s: Failed to remove %s : %s.\n", __FILE__, ESD_UNIX_SOCKET_DIR, strerror (errno)); + pa_log("%s: Failed to remove %s : %s.", __FILE__, ESD_UNIX_SOCKET_DIR, strerror (errno)); #endif protocol_free(m->userdata); diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index 446e39749..d5a0fa479 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -110,7 +110,7 @@ int pa__init(pa_core *c, pa_module*m) { char t[256]; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments\n"); + pa_log(__FILE__": Failed to parse module arguments"); goto fail; } @@ -123,7 +123,7 @@ int pa__init(pa_core *c, pa_module*m) { sink_name = pa_modargs_get_value(ma, "sink", NULL); if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": No such sink.\n"); + pa_log(__FILE__": No such sink."); goto fail; } @@ -133,7 +133,7 @@ int pa__init(pa_core *c, pa_module*m) { frequency = 440; if (pa_modargs_get_value_u32(ma, "frequency", &frequency) < 0 || frequency < 1 || frequency > ss.rate/2) { - pa_log(__FILE__": Invalid frequency specification\n"); + pa_log(__FILE__": Invalid frequency specification"); goto fail; } diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 7356cb7b6..1de21aed5 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -150,7 +150,7 @@ static void do_write(struct userdata *u) { len = memchunk->length; if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); return; } @@ -172,7 +172,7 @@ static void do_write(struct userdata *u) { * Write 0 bytes which will generate a SIGPOLL when "played". */ if (write(u->fd, NULL, 0) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); return; } } @@ -196,7 +196,7 @@ static void do_read(struct userdata *u) { if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s", strerror(errno)); return; } @@ -283,9 +283,9 @@ static int sink_set_hw_volume_cb(pa_sink *s) { if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume.\n"); + pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); else - pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); return -1; } @@ -349,9 +349,9 @@ static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format.\n"); + pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format."); else - pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); return -1; } @@ -367,9 +367,9 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size.\n"); + pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size."); else - pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); return -1; } @@ -388,17 +388,17 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log(__FILE__": record= and playback= expect numeric argument.\n"); + pa_log(__FILE__": record= and playback= expect numeric argument."); goto fail; } if (!playback && !record) { - pa_log(__FILE__": neither playback nor record enabled for device.\n"); + pa_log(__FILE__": neither playback nor record enabled for device."); goto fail; } @@ -406,20 +406,20 @@ int pa__init(pa_core *c, pa_module*m) { buffer_size = 16384; if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) { - pa_log(__FILE__": failed to parse buffer size argument\n"); + pa_log(__FILE__": failed to parse buffer size argument"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification"); goto fail; } if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode | O_NONBLOCK)) < 0) goto fail; - pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info(__FILE__": device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (pa_solaris_auto_format(fd, mode, &ss) < 0) goto fail; diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 136702fc6..df9c51fbc 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -182,7 +182,7 @@ static void command_stream_killed(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t comma struct userdata *u = userdata; assert(pd && t && u && u->pdispatch == pd); - pa_log(__FILE__": stream killed\n"); + pa_log(__FILE__": stream killed"); die(u); } @@ -232,13 +232,13 @@ static void command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED ui if (pa_tagstruct_getu32(t, &channel) < 0 || pa_tagstruct_getu32(t, &bytes) < 0 || !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid protocol reply\n"); + pa_log(__FILE__": invalid protocol reply"); die(u); return; } if (channel != u->channel) { - pa_log(__FILE__": recieved data for invalid channel\n"); + pa_log(__FILE__": recieved data for invalid channel"); die(u); return; } @@ -260,9 +260,9 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G if (command != PA_COMMAND_REPLY) { if (command == PA_COMMAND_ERROR) - pa_log(__FILE__": failed to get latency.\n"); + pa_log(__FILE__": failed to get latency."); else - pa_log(__FILE__": protocol error.\n"); + pa_log(__FILE__": protocol error."); die(u); return; } @@ -276,7 +276,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G pa_tagstruct_get_timeval(t, &remote) < 0 || pa_tagstruct_getu64(t, &counter) < 0 || !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid reply.\n"); + pa_log(__FILE__": invalid reply."); die(u); return; } @@ -303,7 +303,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G u->host_latency = 0; #endif -/* pa_log(__FILE__": estimated host latency: %0.0f usec\n", (double) u->host_latency); */ +/* pa_log(__FILE__": estimated host latency: %0.0f usec", (double) u->host_latency); */ } static void request_latency(struct userdata *u) { @@ -335,9 +335,9 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN if (command != PA_COMMAND_REPLY) { if (command == PA_COMMAND_ERROR) - pa_log(__FILE__": failed to create stream.\n"); + pa_log(__FILE__": failed to create stream."); else - pa_log(__FILE__": protocol error.\n"); + pa_log(__FILE__": protocol error."); die(u); return; } @@ -348,7 +348,7 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN pa_tagstruct_getu32(t, &u->requested_bytes) < 0 || #endif !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid reply.\n"); + pa_log(__FILE__": invalid reply."); die(u); return; } @@ -367,9 +367,9 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t if (command != PA_COMMAND_REPLY || !pa_tagstruct_eof(t)) { if (command == PA_COMMAND_ERROR) - pa_log(__FILE__": failed to authenticate\n"); + pa_log(__FILE__": failed to authenticate"); else - pa_log(__FILE__": protocol error.\n"); + pa_log(__FILE__": protocol error."); die(u); return; } @@ -426,7 +426,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { struct userdata *u = userdata; assert(p && u); - pa_log(__FILE__": stream died.\n"); + pa_log(__FILE__": stream died."); die(u); } @@ -436,7 +436,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *user assert(p && packet && u); if (pa_pdispatch_run(u->pdispatch, packet, u) < 0) { - pa_log(__FILE__": invalid packet\n"); + pa_log(__FILE__": invalid packet"); die(u); } } @@ -447,7 +447,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o assert(p && chunk && u); if (channel != u->channel) { - pa_log(__FILE__": recieved memory block on bad channel.\n"); + pa_log(__FILE__": recieved memory block on bad channel."); die(u); return; } @@ -466,7 +466,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata u->client = NULL; if (!io) { - pa_log(__FILE__": connection failed.\n"); + pa_log(__FILE__": connection failed."); pa_module_unload_request(u->module); return; } @@ -544,7 +544,7 @@ static int load_key(struct userdata *u, const char*fn) { u->auth_cookie_in_property = 0; if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { - pa_log_debug(__FILE__": using already loaded auth cookie.\n"); + pa_log_debug(__FILE__": using already loaded auth cookie."); pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); u->auth_cookie_in_property = 1; return 0; @@ -556,7 +556,7 @@ static int load_key(struct userdata *u, const char*fn) { if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) return -1; - pa_log_debug(__FILE__": loading cookie from disk.\n"); + pa_log_debug(__FILE__": loading cookie from disk."); if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) u->auth_cookie_in_property = 1; @@ -572,7 +572,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments"); goto fail; } @@ -602,18 +602,18 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) { - pa_log(__FILE__": no server specified.\n"); + pa_log(__FILE__": no server specified."); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": invalid sample format specification\n"); + pa_log(__FILE__": invalid sample format specification"); goto fail; } if (!(u->client = pa_socket_client_new_string(c->mainloop, u->server_name, PA_NATIVE_DEFAULT_PORT))) { - pa_log(__FILE__": failed to connect to server '%s'\n", u->server_name); + pa_log(__FILE__": failed to connect to server '%s'", u->server_name); goto fail; } @@ -624,7 +624,7 @@ int pa__init(pa_core *c, pa_module*m) { #ifdef TUNNEL_SINK if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { - pa_log(__FILE__": failed to create sink.\n"); + pa_log(__FILE__": failed to create sink."); goto fail; } @@ -636,7 +636,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_sink_set_owner(u->sink, m); #else if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) { - pa_log(__FILE__": failed to create source.\n"); + pa_log(__FILE__": failed to create source."); goto fail; } diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 2176e6e73..02f865c55 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -159,12 +159,12 @@ static void do_write(struct userdata *u) res = waveOutPrepareHeader(u->hwo, hdr, sizeof(WAVEHDR)); if (res != MMSYSERR_NOERROR) { - pa_log_error(__FILE__ ": ERROR: Unable to prepare waveOut block: %d\n", + pa_log_error(__FILE__ ": ERROR: Unable to prepare waveOut block: %d", res); } res = waveOutWrite(u->hwo, hdr, sizeof(WAVEHDR)); if (res != MMSYSERR_NOERROR) { - pa_log_error(__FILE__ ": ERROR: Unable to write waveOut block: %d\n", + pa_log_error(__FILE__ ": ERROR: Unable to write waveOut block: %d", res); } @@ -214,12 +214,12 @@ static void do_read(struct userdata *u) res = waveInPrepareHeader(u->hwi, hdr, sizeof(WAVEHDR)); if (res != MMSYSERR_NOERROR) { - pa_log_error(__FILE__ ": ERROR: Unable to prepare waveIn block: %d\n", + pa_log_error(__FILE__ ": ERROR: Unable to prepare waveIn block: %d", res); } res = waveInAddBuffer(u->hwi, hdr, sizeof(WAVEHDR)); if (res != MMSYSERR_NOERROR) { - pa_log_error(__FILE__ ": ERROR: Unable to add waveIn block: %d\n", + pa_log_error(__FILE__ ": ERROR: Unable to add waveIn block: %d", res); } @@ -378,7 +378,7 @@ static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) { wf->wFormatTag = WAVE_FORMAT_PCM; if (ss->channels > 2) { - pa_log_error(__FILE__": ERROR: More than two channels not supported.\n"); + pa_log_error(__FILE__": ERROR: More than two channels not supported."); return -1; } @@ -391,7 +391,7 @@ static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) { case 44100: break; default: - pa_log_error(__FILE__": ERROR: Unsupported sample rate.\n"); + pa_log_error(__FILE__": ERROR: Unsupported sample rate."); return -1; } @@ -402,7 +402,7 @@ static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) { else if (ss->format == PA_SAMPLE_S16NE) wf->wBitsPerSample = 16; else { - pa_log_error(__FILE__": ERROR: Unsupported sample format.\n"); + pa_log_error(__FILE__": ERROR: Unsupported sample format."); return -1; } @@ -429,30 +429,30 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log(__FILE__": record= and playback= expect boolean argument.\n"); + pa_log(__FILE__": record= and playback= expect boolean argument."); goto fail; } if (!playback && !record) { - pa_log(__FILE__": neither playback nor record enabled for device.\n"); + pa_log(__FILE__": neither playback nor record enabled for device."); goto fail; } nfrags = 20; frag_size = 1024; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { - pa_log(__FILE__": failed to parse fragments arguments\n"); + pa_log(__FILE__": failed to parse fragments arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification"); goto fail; } @@ -466,13 +466,13 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (waveInStart(hwi) != MMSYSERR_NOERROR) goto fail; - pa_log_debug(__FILE__": Opened waveIn subsystem.\n"); + pa_log_debug(__FILE__": Opened waveIn subsystem."); } if (playback) { if (waveOutOpen(&hwo, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) goto fail; - pa_log_debug(__FILE__": Opened waveOut subsystem.\n"); + pa_log_debug(__FILE__": Opened waveOut subsystem."); } InitializeCriticalSection(&u->crit); diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index d59f3f592..27ceb7f9c 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -71,7 +71,7 @@ static int ring_bell(struct userdata *u, int percent) { assert(u); if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": Invalid sink: %s\n", u->sink_name); + pa_log(__FILE__": Invalid sink: %s", u->sink_name); return -1; } @@ -90,7 +90,7 @@ static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) { bne = (XkbBellNotifyEvent*) e; if (ring_bell(u, bne->percent) < 0) { - pa_log_info(__FILE__": Ringing bell failed, reverting to X11 device bell.\n"); + pa_log_info(__FILE__": Ringing bell failed, reverting to X11 device bell."); XkbForceDeviceBell(pa_x11_wrapper_get_display(w), bne->device, bne->bell_class, bne->bell_id, bne->percent); } @@ -105,7 +105,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments"); goto fail; } @@ -124,7 +124,7 @@ int pa__init(pa_core *c, pa_module*m) { minor = XkbMinorVersion; if (!XkbLibraryVersion(&major, &minor)) { - pa_log(__FILE__": XkbLibraryVersion() failed\n"); + pa_log(__FILE__": XkbLibraryVersion() failed"); goto fail; } @@ -133,7 +133,7 @@ int pa__init(pa_core *c, pa_module*m) { if (!XkbQueryExtension(u->display, NULL, &u->xkb_event_base, NULL, &major, &minor)) { - pa_log(__FILE__": XkbQueryExtension() failed\n"); + pa_log(__FILE__": XkbQueryExtension() failed"); goto fail; } diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index 6d9036f5a..cee9cb3fd 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -78,7 +78,7 @@ static int load_key(struct userdata *u, const char*fn) { u->auth_cookie_in_property = 0; if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { - pa_log_debug(__FILE__": using already loaded auth cookie.\n"); + pa_log_debug(__FILE__": using already loaded auth cookie."); pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); u->auth_cookie_in_property = 1; return 0; @@ -90,7 +90,7 @@ static int load_key(struct userdata *u, const char*fn) { if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) return -1; - pa_log_debug(__FILE__": loading cookie from disk.\n"); + pa_log_debug(__FILE__": loading cookie from disk."); if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) u->auth_cookie_in_property = 1; @@ -108,7 +108,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_strlist *l; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments"); goto fail; } @@ -169,7 +169,7 @@ void pa__done(pa_core *c, pa_module*m) { /* Yes, here is a race condition */ if (!pa_x11_get_prop(u->display, "POLYP_ID", t, sizeof(t)) || strcmp(t, u->id)) - pa_log("WARNING: Polypaudio information vanished from X11!\n"); + pa_log_warn(__FILE__": Polypaudio information vanished from X11!"); else { pa_x11_del_prop(u->display, "POLYP_ID"); pa_x11_del_prop(u->display, "POLYP_SERVER"); diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index d79355ce6..f8607befa 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -141,7 +141,7 @@ static int publish_service(struct userdata *u, struct service *s) { snprintf(t, sizeof(t), "Networked Audio Device %s on %s", s->name, pa_get_host_name(hn, sizeof(hn))); if (sw_text_record_init(&txt) != SW_OKAY) { - pa_log(__FILE__": sw_text_record_init() failed\n"); + pa_log(__FILE__": sw_text_record_init() failed"); goto finish; } free_txt = 1; @@ -168,7 +168,7 @@ static int publish_service(struct userdata *u, struct service *s) { s->loaded.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE, NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt), publish_reply, s, &s->oid) != SW_OKAY) { - pa_log(__FILE__": failed to register sink on zeroconf.\n"); + pa_log(__FILE__": failed to register sink on zeroconf."); goto finish; } @@ -179,7 +179,7 @@ static int publish_service(struct userdata *u, struct service *s) { s->autoload.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE, NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt), publish_reply, s, &s->oid) != SW_OKAY) { - pa_log(__FILE__": failed to register sink on zeroconf.\n"); + pa_log(__FILE__": failed to register sink on zeroconf."); goto finish; } @@ -391,12 +391,12 @@ int pa__init(pa_core *c, pa_module*m) { sw_text_record txt; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments.\n"); + pa_log(__FILE__": failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port == 0 || port >= 0xFFFF) { - pa_log(__FILE__": invalid port specified.\n"); + pa_log(__FILE__": invalid port specified."); goto fail; } @@ -433,7 +433,7 @@ int pa__init(pa_core *c, pa_module*m) { snprintf(t, sizeof(t), "Networked Audio Server on %s", pa_get_host_name(hn, sizeof(hn))); if (sw_text_record_init(&txt) != SW_OKAY) { - pa_log(__FILE__": sw_text_record_init() failed\n"); + pa_log(__FILE__": sw_text_record_init() failed"); goto fail; } free_txt = 1; @@ -444,7 +444,7 @@ int pa__init(pa_core *c, pa_module*m) { SERVICE_NAME_SERVER, NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt), publish_reply, u, &u->server_oid) != SW_OKAY) { - pa_log(__FILE__": failed to register server on zeroconf.\n"); + pa_log(__FILE__": failed to register server on zeroconf."); goto fail; } diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 9fb5d38a9..2c12e28d3 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -51,7 +51,7 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { tcaps = pcaps ? pcaps : &dcaps; if (ioctl(fd, SNDCTL_DSP_GETCAPS, tcaps) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", strerror(errno)); goto fail; } @@ -63,20 +63,20 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) { if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY)) < 0) { - pa_log(__FILE__": open('%s'): %s\n", device, strerror(errno)); + pa_log(__FILE__": open('%s'): %s", device, strerror(errno)); goto fail; } } } else { if ((fd = open(device, *mode|O_NDELAY)) < 0) { - pa_log(__FILE__": open('%s'): %s\n", device, strerror(errno)); + pa_log(__FILE__": open('%s'): %s", device, strerror(errno)); goto fail; } } if (pcaps) { if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", strerror(errno)); goto fail; } } @@ -114,7 +114,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != f) { format = AFMT_U8; if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_U8) { - pa_log(__FILE__": SNDCTL_DSP_SETFMT: %s\n", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETFMT: %s", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); return -1; } else ss->format = PA_SAMPLE_U8; @@ -126,7 +126,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { channels = ss->channels; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { - pa_log(__FILE__": SNDCTL_DSP_CHANNELS: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_CHANNELS: %s", strerror(errno)); return -1; } assert(channels); @@ -134,7 +134,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { speed = ss->rate; if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SPEED: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SPEED: %s", strerror(errno)); return -1; } assert(speed); @@ -160,7 +160,7 @@ int pa_oss_set_fragments(int fd, int nfrags, int frag_size) { arg = ((int) nfrags << 16) | simple_log2(frag_size); if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &arg) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SETFRAGMENT: %s\n", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETFRAGMENT: %s", strerror(errno)); return -1; } @@ -183,7 +183,7 @@ int pa_oss_get_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { if ((volume->channels = ss->channels) >= 2) volume->values[1] = (((vol >> 8) & 0xFF) * PA_VOLUME_NORM) / 100; - pa_log_debug(__FILE__": Read mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), volume)); + pa_log_debug(__FILE__": Read mixer settings: %s", pa_cvolume_snprint(cv, sizeof(cv), volume)); return 0; } @@ -199,7 +199,7 @@ int pa_oss_set_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume if (ioctl(fd, SOUND_MIXER_WRITE_PCM, &vol) < 0) return -1; - pa_log_debug(__FILE__": Wrote mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), volume)); + pa_log_debug(__FILE__": Wrote mixer settings: %s", pa_cvolume_snprint(cv, sizeof(cv), volume)); return 0; } @@ -228,7 +228,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { !(f = fopen("/proc/asound/oss/sndstat", "r"))) { if (errno != ENOENT) - pa_log_warn(__FILE__": failed to open OSS sndstat device: %s\n", strerror(errno)); + pa_log_warn(__FILE__": failed to open OSS sndstat device: %s", strerror(errno)); return -1; } diff --git a/src/polyp/browser.c b/src/polyp/browser.c index ce4c01035..de5c751a3 100644 --- a/src/polyp/browser.c +++ b/src/polyp/browser.c @@ -48,7 +48,7 @@ static void io_callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_fl assert(a && b && b->mainloop == a); if (events != PA_IO_EVENT_INPUT || sw_discovery_read_socket(b->discovery) != SW_OKAY) { - pa_log(__FILE__": connection to HOWL daemon failed.\n"); + pa_log(__FILE__": connection to HOWL daemon failed."); b->mainloop->io_free(b->io_event); b->io_event = NULL; return; @@ -131,7 +131,7 @@ static sw_result resolve_reply( uint32_t val_len; if (sw_text_record_iterator_init(&iterator, text_record, text_record_len) != SW_OKAY) { - pa_log("sw_text_record_string_iterator_init() failed.\n"); + pa_log_error(__FILE__": sw_text_record_string_iterator_init() failed."); goto fail; } @@ -244,7 +244,7 @@ static sw_result browse_reply( sw_discovery_oid oid; if (sw_discovery_resolve(b->discovery, 0, name, type, domain, resolve_reply, b, &oid) != SW_OKAY) - pa_log("sw_discovery_resolve() failed\n"); + pa_log_error(__FILE__": sw_discovery_resolve() failed"); break; } @@ -282,7 +282,7 @@ pa_browser *pa_browser_new(pa_mainloop_api *mainloop) { b->userdata = NULL; if (sw_discovery_init(&b->discovery) != SW_OKAY) { - pa_log("sw_discovery_init() failed.\n"); + pa_log_error(__FILE__": sw_discovery_init() failed."); pa_xfree(b); return NULL; } @@ -291,7 +291,7 @@ pa_browser *pa_browser_new(pa_mainloop_api *mainloop) { sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SINK, NULL, browse_reply, b, &oid) != SW_OKAY || sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SOURCE, NULL, browse_reply, b, &oid) != SW_OKAY) { - pa_log("sw_discovery_browse() failed.\n"); + pa_log_error(__FILE__": sw_discovery_browse() failed."); sw_discovery_fina(b->discovery); pa_xfree(b); diff --git a/src/polyp/client-conf-x11.c b/src/polyp/client-conf-x11.c index 9e863bc78..7187d86b2 100644 --- a/src/polyp/client-conf-x11.c +++ b/src/polyp/client-conf-x11.c @@ -45,7 +45,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { goto finish; if (!(d = XOpenDisplay(dname))) { - pa_log(__FILE__": XOpenDisplay() failed\n"); + pa_log(__FILE__": XOpenDisplay() failed"); goto finish; } @@ -68,7 +68,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; if (pa_parsehex(t, cookie, sizeof(cookie)) != sizeof(cookie)) { - pa_log(__FILE__": failed to parse cookie data\n"); + pa_log(__FILE__": failed to parse cookie data"); goto finish; } diff --git a/src/polyp/client-conf.c b/src/polyp/client-conf.c index 328d01c98..4202b14c6 100644 --- a/src/polyp/client-conf.c +++ b/src/polyp/client-conf.c @@ -122,7 +122,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn); if (!f && errno != EINTR) { - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno)); + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, strerror(errno)); goto finish; } diff --git a/src/polyp/context.c b/src/polyp/context.c index 906a0d89d..8e9992257 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -424,7 +424,7 @@ static int context_connect_spawn(pa_context *c) { pa_context_ref(c); if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - pa_log(__FILE__": socketpair() failed: %s\n", strerror(errno)); + pa_log(__FILE__": socketpair() failed: %s", strerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } @@ -438,7 +438,7 @@ static int context_connect_spawn(pa_context *c) { c->spawn_api.prefork(); if ((pid = fork()) < 0) { - pa_log(__FILE__": fork() failed: %s\n", strerror(errno)); + pa_log(__FILE__": fork() failed: %s", strerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); if (c->spawn_api.postfork) @@ -494,7 +494,7 @@ static int context_connect_spawn(pa_context *c) { c->spawn_api.postfork(); if (r < 0) { - pa_log(__FILE__": waitpid() failed: %s\n", strerror(errno)); + pa_log(__FILE__": waitpid() failed: %s", strerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { @@ -556,7 +556,7 @@ static int try_next_connection(pa_context *c) { goto finish; } - pa_log_debug(__FILE__": Trying to connect to %s...\n", u); + pa_log_debug(__FILE__": Trying to connect to %s...", u); pa_xfree(c->server); c->server = pa_xstrdup(u); @@ -714,8 +714,8 @@ int pa_context_is_pending(pa_context *c) { assert(c); assert(c->ref >= 1); -/* pa_log("pstream: %i\n", pa_pstream_is_pending(c->pstream)); */ -/* pa_log("pdispatch: %i\n", pa_pdispatch_is_pending(c->pdispatch)); */ +/* pa_log("pstream: %i", pa_pstream_is_pending(c->pstream)); */ +/* pa_log("pdispatch: %i", pa_pdispatch_is_pending(c->pdispatch)); */ return (c->pstream && pa_pstream_is_pending(c->pstream)) || (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) || diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index 008043240..0b33c44bc 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -104,12 +104,12 @@ static void defer(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event*e, PA_GCC_UNUS while (sigs) { if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { - pa_log(__FILE__": read(): %s\n", strerror(errno)); + pa_log(__FILE__": read(): %s", strerror(errno)); return; } if (r != sizeof(sig)) { - pa_log(__FILE__": short read()\n"); + pa_log(__FILE__": short read()"); return; } @@ -130,12 +130,12 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags if (errno == EAGAIN) return; - pa_log(__FILE__": read(): %s\n", strerror(errno)); + pa_log(__FILE__": read(): %s", strerror(errno)); return; } if (r != sizeof(sig)) { - pa_log(__FILE__": short read()\n"); + pa_log(__FILE__": short read()"); return; } @@ -150,7 +150,7 @@ int pa_signal_init(pa_mainloop_api *a) { #else if (pipe(signal_pipe) < 0) { #endif - pa_log(__FILE__": pipe() failed: %s\n", strerror(errno)); + pa_log(__FILE__": pipe() failed: %s", strerror(errno)); return -1; } diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index e975d7d79..95c336e4b 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -145,7 +145,7 @@ static pa_io_event* mainloop_io_new( if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset, SELECT_TYPE_ARG5 &tv) == -1) && (WSAGetLastError() == WSAENOTSOCK)) { - pa_log_warn(__FILE__": WARNING: cannot monitor non-socket file descriptors.\n"); + pa_log_warn(__FILE__": WARNING: cannot monitor non-socket file descriptors."); e->dead = 1; } } @@ -725,7 +725,7 @@ int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) { r = pa_mainloop_poll(m); if (r < 0) { - pa_log(__FILE__": poll(): %s\n", strerror(errno)); + pa_log(__FILE__": poll(): %s", strerror(errno)); return r; } @@ -774,7 +774,7 @@ int pa_mainloop_deferred_pending(pa_mainloop *m) { void pa_mainloop_dump(pa_mainloop *m) { assert(m); - pa_log(__FILE__": Dumping mainloop sources START\n"); + pa_log(__FILE__": Dumping mainloop sources START"); { uint32_t idx = PA_IDXSET_INVALID; @@ -783,7 +783,7 @@ void pa_mainloop_dump(pa_mainloop *m) { if (e->dead) continue; - pa_log(__FILE__": kind=io fd=%i events=%i callback=%p userdata=%p\n", e->fd, (int) e->events, (void*) e->callback, (void*) e->userdata); + pa_log(__FILE__": kind=io fd=%i events=%i callback=%p userdata=%p", e->fd, (int) e->events, (void*) e->callback, (void*) e->userdata); } } { @@ -793,7 +793,7 @@ void pa_mainloop_dump(pa_mainloop *m) { if (e->dead) continue; - pa_log(__FILE__": kind=defer enabled=%i callback=%p userdata=%p\n", e->enabled, (void*) e->callback, (void*) e->userdata); + pa_log(__FILE__": kind=defer enabled=%i callback=%p userdata=%p", e->enabled, (void*) e->callback, (void*) e->userdata); } } { @@ -803,11 +803,11 @@ void pa_mainloop_dump(pa_mainloop *m) { if (e->dead) continue; - pa_log(__FILE__": kind=time enabled=%i time=%lu.%lu callback=%p userdata=%p\n", e->enabled, (unsigned long) e->timeval.tv_sec, (unsigned long) e->timeval.tv_usec, (void*) e->callback, (void*) e->userdata); + pa_log(__FILE__": kind=time enabled=%i time=%lu.%lu callback=%p userdata=%p", e->enabled, (unsigned long) e->timeval.tv_sec, (unsigned long) e->timeval.tv_usec, (void*) e->callback, (void*) e->userdata); } } - pa_log(__FILE__": Dumping mainloop sources STOP\n"); + pa_log(__FILE__": Dumping mainloop sources STOP"); } #endif diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 5ab91815f..8bdb90590 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -289,7 +289,7 @@ static void ipol_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED co pa_stream_ref(s); -/* pa_log("requesting new ipol data\n"); */ +/* pa_log("requesting new ipol data"); */ if (s->state == PA_STREAM_READY && !s->ipol_requested) { pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); @@ -655,7 +655,7 @@ static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, } if (o->stream->interpolate) { -/* pa_log("new interpol data\n"); */ +/* pa_log("new interpol data"); */ o->stream->ipol_timestamp = i.timestamp; o->stream->ipol_usec = pa_stream_get_time(o->stream, &i); o->stream->ipol_requested = 0; diff --git a/src/polypcore/authkey.c b/src/polypcore/authkey.c index e3fc9f607..80480c16e 100644 --- a/src/polypcore/authkey.c +++ b/src/polypcore/authkey.c @@ -52,7 +52,7 @@ static int generate(int fd, void *ret_data, size_t length) { ftruncate(fd, 0); if ((r = pa_loop_write(fd, ret_data, length)) < 0 || (size_t) r != length) { - pa_log(__FILE__": failed to write cookie file: %s\n", strerror(errno)); + pa_log(__FILE__": failed to write cookie file: %s", strerror(errno)); return -1; } @@ -70,7 +70,7 @@ static int load(const char *fn, void *data, size_t length) { if ((fd = open(fn, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { if (errno != EACCES || (fd = open(fn, O_RDONLY)) < 0) { - pa_log(__FILE__": failed to open cookie file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": failed to open cookie file '%s': %s", fn, strerror(errno)); goto finish; } else writable = 0; @@ -79,14 +79,14 @@ static int load(const char *fn, void *data, size_t length) { unlock = pa_lock_fd(fd, 1) >= 0; if ((r = pa_loop_read(fd, data, length)) < 0) { - pa_log(__FILE__": failed to read cookie file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": failed to read cookie file '%s': %s", fn, strerror(errno)); goto finish; } if ((size_t) r != length) { if (!writable) { - pa_log(__FILE__": unable to write cookie to read only file\n"); + pa_log(__FILE__": unable to write cookie to read only file"); goto finish; } @@ -118,7 +118,7 @@ int pa_authkey_load(const char *path, void *data, size_t length) { ret = load(path, data, length); if (ret < 0) - pa_log(__FILE__": Failed to load authorization key '%s': %s\n", path, + pa_log(__FILE__": Failed to load authorization key '%s': %s", path, (ret == -1) ? strerror(errno) : "file corrupt"); return ret; @@ -175,14 +175,14 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) { return -2; if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": failed to open cookie file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": failed to open cookie file '%s': %s", fn, strerror(errno)); goto finish; } unlock = pa_lock_fd(fd, 1) >= 0; if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) { - pa_log(__FILE__": failed to read cookie file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": failed to read cookie file '%s': %s", fn, strerror(errno)); goto finish; } diff --git a/src/polypcore/cli.c b/src/polypcore/cli.c index 295ce625d..583f6845a 100644 --- a/src/polypcore/cli.c +++ b/src/polypcore/cli.c @@ -103,7 +103,7 @@ static void client_kill(pa_client *client) { assert(client && client->userdata); c = client->userdata; - pa_log_debug(__FILE__": CLI client killed.\n"); + pa_log_debug(__FILE__": CLI client killed."); if (c->defer_kill) c->kill_requested = 1; else { @@ -119,7 +119,7 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { assert(line && c); if (!s) { - pa_log_debug(__FILE__": CLI got EOF from user.\n"); + pa_log_debug(__FILE__": CLI got EOF from user."); if (c->eof_callback) c->eof_callback(c, c->userdata); diff --git a/src/polypcore/client.c b/src/polypcore/client.c index 7fe5a9fc3..852f87b02 100644 --- a/src/polypcore/client.c +++ b/src/polypcore/client.c @@ -51,7 +51,7 @@ pa_client *pa_client_new(pa_core *core, const char *name, const char *driver) { r = pa_idxset_put(core->clients, c, &c->index); assert(c->index != PA_IDXSET_INVALID && r >= 0); - pa_log_info(__FILE__": created %u \"%s\"\n", c->index, c->name); + pa_log_info(__FILE__": created %u \"%s\"", c->index, c->name); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); pa_core_check_quit(core); @@ -66,7 +66,7 @@ void pa_client_free(pa_client *c) { pa_core_check_quit(c->core); - pa_log_info(__FILE__": freed %u \"%s\"\n", c->index, c->name); + pa_log_info(__FILE__": freed %u \"%s\"", c->index, c->name); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_xfree(c->name); pa_xfree(c->driver); @@ -76,7 +76,7 @@ void pa_client_free(pa_client *c) { void pa_client_kill(pa_client *c) { assert(c); if (!c->kill) { - pa_log_warn(__FILE__": kill() operation not implemented for client %u\n", c->index); + pa_log_warn(__FILE__": kill() operation not implemented for client %u", c->index); return; } diff --git a/src/polypcore/conf-parser.c b/src/polypcore/conf-parser.c index 7eeda02b6..26fc33b56 100644 --- a/src/polypcore/conf-parser.c +++ b/src/polypcore/conf-parser.c @@ -45,7 +45,7 @@ static int next_assignment(const char *filename, unsigned line, const pa_config_ if (!strcmp(lvalue, t->lvalue)) return t->parse(filename, line, lvalue, rvalue, t->data, userdata); - pa_log(__FILE__": [%s:%u] Unknown lvalue '%s'.\n", filename, line, lvalue); + pa_log(__FILE__": [%s:%u] Unknown lvalue '%s'.", filename, line, lvalue); return -1; } @@ -88,7 +88,7 @@ static int parse_line(const char *filename, unsigned line, const pa_config_item return 0; if (!(e = strchr(b, '='))) { - pa_log(__FILE__": [%s:%u] Missing '='.\n", filename, line); + pa_log(__FILE__": [%s:%u] Missing '='.", filename, line); return -1; } @@ -111,7 +111,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void goto finish; } - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno)); + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, strerror(errno)); goto finish; } @@ -121,7 +121,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void if (feof(f)) break; - pa_log(__FILE__": WARNING: failed to read configuration file '%s': %s\n", filename, strerror(errno)); + pa_log(__FILE__": WARNING: failed to read configuration file '%s': %s", filename, strerror(errno)); goto finish; } @@ -145,7 +145,7 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, assert(filename && lvalue && rvalue && data); if (pa_atoi(rvalue, &k) < 0) { - pa_log(__FILE__": [%s:%u] Failed to parse numeric value: %s\n", filename, line, rvalue); + pa_log(__FILE__": [%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); return -1; } @@ -158,7 +158,7 @@ int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue assert(filename && lvalue && rvalue && data); if ((k = pa_parse_boolean(rvalue)) < 0) { - pa_log(__FILE__": [%s:%u] Failed to parse boolean value: %s\n", filename, line, rvalue); + pa_log(__FILE__": [%s:%u] Failed to parse boolean value: %s", filename, line, rvalue); return -1; } diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 69199a33c..1803931ed 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -341,7 +341,7 @@ static void add_file(pa_core *c, const char *pathname) { e = pa_path_get_filename(pathname); if (stat(pathname, &st) < 0) { - pa_log(__FILE__": stat('%s') failed: %s\n", pathname, strerror(errno)); + pa_log(__FILE__": stat('%s') failed: %s", pathname, strerror(errno)); return; } @@ -363,7 +363,7 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) { /* If that fails, try to open it as shell glob */ if (glob(pathname, GLOB_ERR|GLOB_NOSORT, NULL, &p) < 0) { - pa_log(__FILE__": Failed to open directory: %s\n", strerror(errno)); + pa_log(__FILE__": Failed to open directory: %s", strerror(errno)); return -1; } diff --git a/src/polypcore/core-subscribe.c b/src/polypcore/core-subscribe.c index 4d792966e..e2dd9ae3b 100644 --- a/src/polypcore/core-subscribe.c +++ b/src/polypcore/core-subscribe.c @@ -158,7 +158,7 @@ void pa_subscription_free_all(pa_core *c) { break; } - pa_log(__FILE__": %u\n", e->index); + pa_log(__FILE__": %u", e->index); }*/ /* Deferred callback for dispatching subscirption events */ diff --git a/src/polypcore/ioline.c b/src/polypcore/ioline.c index 3f2de5a2e..eb8fdda53 100644 --- a/src/polypcore/ioline.c +++ b/src/polypcore/ioline.c @@ -274,7 +274,7 @@ static int do_read(pa_ioline *l) { pa_ioline_puts(l, "\nExiting.\n"); do_write(l); } else if (r < 0) { - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s", strerror(errno)); failure(l); return -1; } @@ -296,7 +296,7 @@ static int do_write(pa_ioline *l) { while (!l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length) { if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) { - pa_log(__FILE__": write() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + pa_log(__FILE__": write() failed: %s", r < 0 ? strerror(errno) : "EOF"); failure(l); return -1; } diff --git a/src/polypcore/log.c b/src/polypcore/log.c index c7bf7be9e..29c4c4808 100644 --- a/src/polypcore/log.c +++ b/src/polypcore/log.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #ifdef HAVE_SYSLOG_H #include @@ -73,6 +75,8 @@ void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t l, const c void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { const char *e; + char *text, *t, *n; + assert(level < PA_LOG_LEVEL_MAX); if ((e = getenv(ENV_LOGLEVEL))) @@ -81,31 +85,55 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { if (level > maximal_level) return; - switch (log_target) { - case PA_LOG_STDERR: - vfprintf(stderr, format, ap); - break; + text = pa_vsprintf_malloc(format, ap); -#ifdef HAVE_SYSLOG_H - case PA_LOG_SYSLOG: - openlog(log_ident ? log_ident : "???", LOG_PID, LOG_USER); - vsyslog(level_to_syslog[level], format, ap); - closelog(); - break; -#endif - - case PA_LOG_USER: { - char *t = pa_vsprintf_malloc(format, ap); - assert(user_log_func); - user_log_func(level, t); - pa_xfree(t); + for (t = text; t; t = n) { + if ((n = strchr(t, '\n'))) { + *n = 0; + n++; + } + + if (!*t) + continue; + + switch (log_target) { + case PA_LOG_STDERR: { + const char *prefix = "", *suffix = ""; + + /* Yes indeed. Useless, but fun! */ + if (isatty(STDERR_FILENO)) { + if (level <= PA_LOG_ERROR) { + prefix = "\x1B[1;31m"; + suffix = "\x1B[0m"; + } else if (level <= PA_LOG_WARN) { + prefix = "\x1B[1m"; + suffix = "\x1B[0m"; + } + } + fprintf(stderr, "%s%s%s\n", prefix, t, suffix); + break; + } + +#ifdef HAVE_SYSLOG_H + case PA_LOG_SYSLOG: + openlog(log_ident ? log_ident : "???", LOG_PID, LOG_USER); + syslog(level_to_syslog[level], "%s", t); + closelog(); + break; +#endif + + case PA_LOG_USER: + user_log_func(level, t); + break; + + case PA_LOG_NULL: + default: + break; } - - case PA_LOG_NULL: - default: - break; } + pa_xfree(text); + } void pa_log_level(pa_log_level_t level, const char *format, ...) { diff --git a/src/polypcore/memblockq.c b/src/polypcore/memblockq.c index 05c810bd2..9b12a8105 100644 --- a/src/polypcore/memblockq.c +++ b/src/polypcore/memblockq.c @@ -76,7 +76,7 @@ pa_memblockq* pa_memblockq_new( bq->read_index = bq->write_index = idx; bq->memblock_stat = s; - pa_log_debug(__FILE__": memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq); + pa_log_debug(__FILE__": memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u", maxlength, tlength, base, prebuf, minreq); bq->maxlength = ((maxlength+base-1)/base)*base; assert(bq->maxlength >= base); @@ -98,7 +98,7 @@ pa_memblockq* pa_memblockq_new( if (!bq->minreq) bq->minreq = 1; - pa_log_debug(__FILE__": memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); + pa_log_debug(__FILE__": memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); bq->state = bq->prebuf ? PREBUF : RUNNING; bq->silence = silence ? pa_memblock_ref(silence) : NULL; diff --git a/src/polypcore/modinfo.c b/src/polypcore/modinfo.c index 4204bb34a..e090a42fd 100644 --- a/src/polypcore/modinfo.c +++ b/src/polypcore/modinfo.c @@ -65,7 +65,7 @@ pa_modinfo *pa_modinfo_get_by_name(const char *name) { assert(name); if (!(dl = lt_dlopenext(name))) { - pa_log(__FILE__": Failed to open module \"%s\": %s\n", name, lt_dlerror()); + pa_log(__FILE__": Failed to open module \"%s\": %s", name, lt_dlerror()); return NULL; } diff --git a/src/polypcore/module.c b/src/polypcore/module.c index 753853542..5412f3973 100644 --- a/src/polypcore/module.c +++ b/src/polypcore/module.c @@ -69,17 +69,17 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { m->argument = pa_xstrdup(argument); if (!(m->dl = lt_dlopenext(name))) { - pa_log(__FILE__": Failed to open module \"%s\": %s\n", name, lt_dlerror()); + pa_log(__FILE__": Failed to open module \"%s\": %s", name, lt_dlerror()); goto fail; } if (!(m->init = (int (*)(pa_core *_c, pa_module*_m)) lt_dlsym(m->dl, PA_SYMBOL_INIT))) { - pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.\n", name); + pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name); goto fail; } if (!(m->done = (void (*)(pa_core *_c, pa_module*_m)) lt_dlsym(m->dl, PA_SYMBOL_DONE))) { - pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.\n", name); + pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.", name); goto fail; } @@ -91,7 +91,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { assert(m->init); if (m->init(c, m) < 0) { - pa_log_error(__FILE__": Failed to load module \"%s\" (argument: \"%s\"): initialization failed.\n", name, argument ? argument : ""); + pa_log_error(__FILE__": Failed to load module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : ""); goto fail; } @@ -110,7 +110,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { r = pa_idxset_put(c->modules, m, &m->index); assert(r >= 0 && m->index != PA_IDXSET_INVALID); - pa_log_info(__FILE__": Loaded \"%s\" (index: #%u; argument: \"%s\").\n", m->name, m->index, m->argument ? m->argument : ""); + pa_log_info(__FILE__": Loaded \"%s\" (index: #%u; argument: \"%s\").", m->name, m->index, m->argument ? m->argument : ""); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_NEW, m->index); @@ -137,13 +137,13 @@ static void pa_module_free(pa_module *m) { if (m->core->disallow_module_loading) return; - pa_log_info(__FILE__": Unloading \"%s\" (index: #%u).\n", m->name, m->index); + pa_log_info(__FILE__": Unloading \"%s\" (index: #%u).", m->name, m->index); m->done(m->core, m); lt_dlclose(m->dl); - pa_log_info(__FILE__": Unloaded \"%s\" (index: #%u).\n", m->name, m->index); + pa_log_info(__FILE__": Unloaded \"%s\" (index: #%u).", m->name, m->index); pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE, m->index); diff --git a/src/polypcore/pdispatch.c b/src/polypcore/pdispatch.c index 2cc90bc25..56a21bd6b 100644 --- a/src/polypcore/pdispatch.c +++ b/src/polypcore/pdispatch.c @@ -196,7 +196,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, void *userdata) { if (!(p = command_names[command])) snprintf((char*) (p = t), sizeof(t), "%u", command); - pa_log(__FILE__": Recieved opcode <%s>\n", p); + pa_log(__FILE__": Recieved opcode <%s>", p); } #endif @@ -215,7 +215,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, void *userdata) { (*c)(pd, command, tag, ts, userdata); } else { - pa_log(__FILE__": Recieved unsupported command %u\n", command); + pa_log(__FILE__": Recieved unsupported command %u", command); goto finish; } diff --git a/src/polypcore/pid.c b/src/polypcore/pid.c index 3f33365ac..374b55063 100644 --- a/src/polypcore/pid.c +++ b/src/polypcore/pid.c @@ -54,7 +54,7 @@ static pid_t read_pid(const char *fn, int fd) { assert(fn && fd >= 0); if ((r = pa_loop_read(fd, t, sizeof(t)-1)) < 0) { - pa_log(__FILE__": WARNING: failed to read PID file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": WARNING: failed to read PID file '%s': %s", fn, strerror(errno)); return (pid_t) -1; } @@ -66,7 +66,7 @@ static pid_t read_pid(const char *fn, int fd) { *e = 0; if (pa_atou(t, &pid) < 0) { - pa_log(__FILE__": WARNING: failed to parse PID file '%s'\n", fn); + pa_log(__FILE__": WARNING: failed to parse PID file '%s'", fn); return (pid_t) -1; } @@ -84,7 +84,7 @@ static int open_pid_file(const char *fn, int mode) { if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) { if (mode != O_RDONLY || errno != ENOENT) - pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": WARNING: failed to open PID file '%s': %s", fn, strerror(errno)); goto fail; } @@ -93,7 +93,7 @@ static int open_pid_file(const char *fn, int mode) { goto fail; if (fstat(fd, &st) < 0) { - pa_log(__FILE__": Failed to fstat() PID file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": Failed to fstat() PID file '%s': %s", fn, strerror(errno)); goto fail; } @@ -105,7 +105,7 @@ static int open_pid_file(const char *fn, int mode) { goto fail; if (close(fd) < 0) { - pa_log(__FILE__": Failed to close file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": Failed to close file '%s': %s", fn, strerror(errno)); goto fail; } @@ -145,7 +145,7 @@ int pa_pid_file_create(void) { goto fail; if ((pid = read_pid(fn, fd)) == (pid_t) -1) - pa_log(__FILE__": corrupt PID file, overwriting.\n"); + pa_log(__FILE__": corrupt PID file, overwriting."); else if (pid > 0) { #ifdef OS_IS_WIN32 if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) { @@ -153,16 +153,16 @@ int pa_pid_file_create(void) { #else if (kill(pid, 0) >= 0 || errno != ESRCH) { #endif - pa_log(__FILE__": daemon already running.\n"); + pa_log(__FILE__": daemon already running."); goto fail; } - pa_log(__FILE__": stale PID file, overwriting.\n"); + pa_log(__FILE__": stale PID file, overwriting."); } /* Overwrite the current PID file */ if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) { - pa_log(__FILE__": failed to truncate PID fil: %s.\n", strerror(errno)); + pa_log(__FILE__": failed to truncate PID fil: %s.", strerror(errno)); goto fail; } @@ -170,7 +170,7 @@ int pa_pid_file_create(void) { l = strlen(t); if (pa_loop_write(fd, t, l) != (ssize_t) l) { - pa_log(__FILE__": failed to write PID file.\n"); + pa_log(__FILE__": failed to write PID file."); goto fail; } @@ -195,7 +195,7 @@ int pa_pid_file_remove(void) { pa_runtime_path("pid", fn, sizeof(fn)); if ((fd = open_pid_file(fn, O_RDWR)) < 0) { - pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": WARNING: failed to open PID file '%s': %s", fn, strerror(errno)); goto fail; } @@ -203,12 +203,12 @@ int pa_pid_file_remove(void) { goto fail; if (pid != getpid()) { - pa_log(__FILE__": WARNING: PID file '%s' not mine!\n", fn); + pa_log(__FILE__": WARNING: PID file '%s' not mine!", fn); goto fail; } if (ftruncate(fd, 0) < 0) { - pa_log(__FILE__": failed to truncate PID file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": failed to truncate PID file '%s': %s", fn, strerror(errno)); goto fail; } @@ -219,7 +219,7 @@ int pa_pid_file_remove(void) { #endif if (unlink(fn) < 0) { - pa_log(__FILE__": failed to remove PID file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": failed to remove PID file '%s': %s", fn, strerror(errno)); goto fail; } diff --git a/src/polypcore/protocol-cli.c b/src/polypcore/protocol-cli.c index cb7e8f6f1..7dd489f7e 100644 --- a/src/polypcore/protocol-cli.c +++ b/src/polypcore/protocol-cli.c @@ -55,7 +55,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) assert(s && io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { - pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); pa_iochannel_free(io); return; } diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 8a0a33560..aa46e2b94 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -269,7 +269,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req if (!c->authorized) { if (memcmp(data, c->protocol->esd_key, ESD_KEY_LEN) != 0) { - pa_log(__FILE__": kicked client with invalid authorization key.\n"); + pa_log(__FILE__": kicked client with invalid authorization key."); return -1; } @@ -286,7 +286,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req else if (ekey == ESD_SWAP_ENDIAN_KEY) c->swap_byte_order = 1; else { - pa_log(__FILE__": client sent invalid endian key\n"); + pa_log(__FILE__": client sent invalid endian key"); return -1; } @@ -311,12 +311,12 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t format_esd2native(format, c->swap_byte_order, &ss); if (!pa_sample_spec_valid(&ss)) { - pa_log(__FILE__": invalid sample specification\n"); + pa_log(__FILE__": invalid sample specification"); return -1; } if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": no such sink\n"); + pa_log(__FILE__": no such sink"); return -1; } @@ -328,7 +328,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t assert(!c->sink_input && !c->input_memblockq); if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, name, &ss, NULL, 0, -1))) { - pa_log(__FILE__": failed to create sink input.\n"); + pa_log(__FILE__": failed to create sink input."); return -1; } @@ -375,7 +375,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co format_esd2native(format, c->swap_byte_order, &ss); if (!pa_sample_spec_valid(&ss)) { - pa_log(__FILE__": invalid sample specification.\n"); + pa_log(__FILE__": invalid sample specification."); return -1; } @@ -383,19 +383,19 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co pa_sink* sink; if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": no such sink.\n"); + pa_log(__FILE__": no such sink."); return -1; } if (!(source = sink->monitor_source)) { - pa_log(__FILE__": no such monitor source.\n"); + pa_log(__FILE__": no such monitor source."); return -1; } } else { assert(request == ESD_PROTO_STREAM_REC); if (!(source = pa_namereg_get(c->protocol->core, c->protocol->source_name, PA_NAMEREG_SOURCE, 1))) { - pa_log(__FILE__": no such source.\n"); + pa_log(__FILE__": no such source."); return -1; } } @@ -408,7 +408,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co assert(!c->output_memblockq && !c->source_output); if (!(c->source_output = pa_source_output_new(source, __FILE__, name, &ss, NULL, -1))) { - pa_log(__FILE__": failed to create source output\n"); + pa_log(__FILE__": failed to create source output"); return -1; } @@ -733,14 +733,14 @@ static void client_kill_cb(pa_client *c) { static int do_read(struct connection *c) { assert(c && c->io); -/* pa_log("READ\n"); */ +/* pa_log("READ"); */ if (c->state == ESD_NEXT_REQUEST) { ssize_t r; assert(c->read_data_length < sizeof(c->request)); if ((r = pa_iochannel_read(c->io, ((uint8_t*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { - pa_log_debug(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF"); return -1; } @@ -750,16 +750,16 @@ static int do_read(struct connection *c) { c->request = MAYBE_INT32_SWAP(c->swap_byte_order, c->request); if (c->request < ESD_PROTO_CONNECT || c->request > ESD_PROTO_MAX) { - pa_log(__FILE__": recieved invalid request.\n"); + pa_log(__FILE__": recieved invalid request."); return -1; } handler = proto_map+c->request; -/* pa_log(__FILE__": executing request #%u\n", c->request); */ +/* pa_log(__FILE__": executing request #%u", c->request); */ if (!handler->proc) { - pa_log(__FILE__": recieved unimplemented request #%u.\n", c->request); + pa_log(__FILE__": recieved unimplemented request #%u.", c->request); return -1; } @@ -788,7 +788,7 @@ static int do_read(struct connection *c) { assert(c->read_data && c->read_data_length < handler->data_length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { - pa_log_debug(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF"); return -1; } @@ -808,7 +808,7 @@ static int do_read(struct connection *c) { assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { - pa_log_debug(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF"); return -1; } @@ -843,7 +843,7 @@ static int do_read(struct connection *c) { assert(c->input_memblockq); -/* pa_log("STREAMING_DATA\n"); */ +/* pa_log("STREAMING_DATA"); */ if (!(l = pa_memblockq_missing(c->input_memblockq))) return 0; @@ -865,7 +865,7 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - pa_log_debug(__FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); + pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF"); return -1; } @@ -888,14 +888,14 @@ static int do_read(struct connection *c) { static int do_write(struct connection *c) { assert(c && c->io); -/* pa_log("WRITE\n"); */ +/* pa_log("WRITE"); */ if (c->write_data_length) { ssize_t r; assert(c->write_data_index < c->write_data_length); if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); return -1; } @@ -914,7 +914,7 @@ static int do_write(struct connection *c) { if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); - pa_log(__FILE__": write(): %s\n", strerror(errno)); + pa_log(__FILE__": write(): %s", strerror(errno)); return -1; } @@ -967,7 +967,7 @@ static void io_callback(pa_iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); -/* pa_log("IO\n"); */ +/* pa_log("IO"); */ do_work(c); } @@ -978,7 +978,7 @@ static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) struct connection *c = userdata; assert(a && c && c->defer_event == e); -/* pa_log("DEFER\n"); */ +/* pa_log("DEFER"); */ do_work(c); } @@ -1005,7 +1005,7 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_ struct connection*c = i->userdata; assert(i && c && length); -/* pa_log("DROP\n"); */ +/* pa_log("DROP"); */ pa_memblockq_drop(c->input_memblockq, chunk, length); @@ -1072,7 +1072,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) assert(s && io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { - pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); pa_iochannel_free(io); return; } @@ -1142,7 +1142,7 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve p = pa_xmalloc(sizeof(pa_protocol_esound)); if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { - pa_log(__FILE__": public= expects a boolean argument.\n"); + pa_log(__FILE__": public= expects a boolean argument."); return NULL; } diff --git a/src/polypcore/protocol-http.c b/src/polypcore/protocol-http.c index f0b78124b..85ddebee4 100644 --- a/src/polypcore/protocol-http.c +++ b/src/polypcore/protocol-http.c @@ -143,7 +143,7 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { /* We're done */ c->state = DATA; - pa_log_info(__FILE__": request for %s\n", c->url); + pa_log_info(__FILE__": request for %s", c->url); if (!strcmp(c->url, URL_ROOT)) { char txt[256]; @@ -222,7 +222,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) assert(s && io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { - pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); pa_iochannel_free(io); return; } diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index aba12036a..dce6b346a 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -507,7 +507,7 @@ static void request_bytes(struct playback_stream *s) { pa_tagstruct_putu32(t, l); pa_pstream_send_tagstruct(s->connection->pstream, t); -/* pa_log(__FILE__": Requesting %u bytes\n", l); */ +/* pa_log(__FILE__": Requesting %u bytes", l); */ } static void send_memblock(struct connection *c) { @@ -585,11 +585,11 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { } if (pa_memblockq_peek(s->memblockq, chunk) < 0) { -/* pa_log(__FILE__": peek: failure\n"); */ +/* pa_log(__FILE__": peek: failure"); */ return -1; } -/* pa_log(__FILE__": peek: %u\n", chunk->length); */ +/* pa_log(__FILE__": peek: %u", chunk->length); */ return 0; } @@ -608,7 +608,7 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_ s->drain_request = 0; } -/* pa_log(__FILE__": after_drop: %u %u\n", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */ +/* pa_log(__FILE__": after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */ } static void sink_input_kill_cb(pa_sink_input *i) { @@ -622,7 +622,7 @@ static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { assert(i && i->userdata); s = i->userdata; - /*pa_log(__FILE__": get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/ + /*pa_log(__FILE__": get_latency: %u", pa_memblockq_get_length(s->memblockq));*/ return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); } @@ -635,7 +635,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) s = o->userdata; if (pa_memblockq_push_align(s->memblockq, chunk) < 0) { - pa_log_warn(__FILE__": Failed to push data into output queue.\n"); + pa_log_warn(__FILE__": Failed to push data into output queue."); return; } @@ -654,7 +654,7 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { assert(o && o->userdata); s = o->userdata; - /*pa_log(__FILE__": get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/ + /*pa_log(__FILE__": get_latency: %u", pa_memblockq_get_length(s->memblockq));*/ return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec); } @@ -662,7 +662,7 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { /*** pdispatch callbacks ***/ static void protocol_error(struct connection *c) { - pa_log(__FILE__": protocol error, kicking client\n"); + pa_log(__FILE__": protocol error, kicking client"); connection_free(c); } @@ -868,7 +868,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t if (!c->authorized) { if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) { - pa_log(__FILE__": Denied access to client with invalid authorization key.\n"); + pa_log(__FILE__": Denied access to client with invalid authorization key."); pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -958,10 +958,10 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC pa_memblockq_prebuf_disable(s->memblockq); if (!pa_memblockq_is_readable(s->memblockq)) { -/* pa_log("immediate drain: %u\n", pa_memblockq_get_length(s->memblockq)); */ +/* pa_log("immediate drain: %u", pa_memblockq_get_length(s->memblockq)); */ pa_pstream_send_simple_ack(c->pstream, tag); } else { -/* pa_log("slow drain triggered\n"); */ +/* pa_log("slow drain triggered"); */ s->drain_request = 1; s->drain_tag = tag; @@ -1967,7 +1967,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *user assert(p && packet && packet->data && c); if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { - pa_log(__FILE__": invalid packet.\n"); + pa_log(__FILE__": invalid packet."); connection_free(c); } } @@ -1978,7 +1978,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o assert(p && chunk && userdata); if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) { - pa_log(__FILE__": client sent block for invalid stream.\n"); + pa_log(__FILE__": client sent block for invalid stream."); connection_free(c); return; } @@ -1995,7 +1995,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o if (pa_memblockq_push_align(ps->memblockq, chunk) < 0) { pa_tagstruct *t; - pa_log_warn(__FILE__": failed to push data into queue\n"); + pa_log_warn(__FILE__": failed to push data into queue"); /* Pushing this block into the queue failed, so we simulate * it by skipping ahead */ @@ -2050,7 +2050,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { assert(p && c); connection_free(c); -/* pa_log(__FILE__": connection died.\n");*/ +/* pa_log(__FILE__": connection died.");*/ } @@ -2084,7 +2084,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo assert(io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { - pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); pa_iochannel_free(io); return; } @@ -2138,7 +2138,7 @@ static int load_key(pa_protocol_native*p, const char*fn) { p->auth_cookie_in_property = 0; if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) { - pa_log_info(__FILE__": using already loaded auth cookie.\n"); + pa_log_info(__FILE__": using already loaded auth cookie."); pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); p->auth_cookie_in_property = 1; return 0; @@ -2150,7 +2150,7 @@ static int load_key(pa_protocol_native*p, const char*fn) { if (pa_authkey_load_auto(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0) return -1; - pa_log_info(__FILE__": loading cookie from disk.\n"); + pa_log_info(__FILE__": loading cookie from disk."); if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) p->auth_cookie_in_property = 1; @@ -2164,7 +2164,7 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo assert(c && ma); if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { - pa_log(__FILE__": public= expects a boolean argument.\n"); + pa_log(__FILE__": public= expects a boolean argument."); return NULL; } diff --git a/src/polypcore/protocol-simple.c b/src/polypcore/protocol-simple.c index fac542391..c2f534443 100644 --- a/src/polypcore/protocol-simple.c +++ b/src/polypcore/protocol-simple.c @@ -132,7 +132,7 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - pa_log_debug(__FILE__": read() failed: %s\n", r == 0 ? "EOF" : strerror(errno)); + pa_log_debug(__FILE__": read() failed: %s", r == 0 ? "EOF" : strerror(errno)); return -1; } @@ -166,7 +166,7 @@ static int do_write(struct connection *c) { if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); - pa_log(__FILE__": write(): %s\n", strerror(errno)); + pa_log(__FILE__": write(): %s", strerror(errno)); return -1; } @@ -313,7 +313,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) assert(s && io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { - pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.\n", MAX_CONNECTIONS); + pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); pa_iochannel_free(io); return; } @@ -342,12 +342,12 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) size_t l; if (!(sink = pa_namereg_get(p->core, p->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": Failed to get sink.\n"); + pa_log(__FILE__": Failed to get sink."); goto fail; } if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, c->client->name, &p->sample_spec, NULL, 0, -1))) { - pa_log(__FILE__": Failed to create sink input.\n"); + pa_log(__FILE__": Failed to create sink input."); goto fail; } @@ -380,13 +380,13 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) size_t l; if (!(source = pa_namereg_get(p->core, p->source_name, PA_NAMEREG_SOURCE, 1))) { - pa_log(__FILE__": Failed to get source.\n"); + pa_log(__FILE__": Failed to get source."); goto fail; } c->source_output = pa_source_output_new(source, __FILE__, c->client->name, &p->sample_spec, NULL, -1); if (!c->source_output) { - pa_log(__FILE__": Failed to create source output.\n"); + pa_log(__FILE__": Failed to create source output."); goto fail; } c->source_output->owner = p->module; @@ -437,7 +437,7 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv p->sample_spec = core->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &p->sample_spec) < 0) { - pa_log(__FILE__": Failed to parse sample type specification.\n"); + pa_log(__FILE__": Failed to parse sample type specification."); goto fail; } @@ -446,20 +446,20 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv enable = 0; if (pa_modargs_get_value_boolean(ma, "record", &enable) < 0) { - pa_log(__FILE__": record= expects a numeric argument.\n"); + pa_log(__FILE__": record= expects a numeric argument."); goto fail; } p->mode = enable ? RECORD : 0; enable = 1; if (pa_modargs_get_value_boolean(ma, "playback", &enable) < 0) { - pa_log(__FILE__": playback= expects a numeric argument.\n"); + pa_log(__FILE__": playback= expects a numeric argument."); goto fail; } p->mode |= enable ? PLAYBACK : 0; if ((p->mode & (RECORD|PLAYBACK)) == 0) { - pa_log(__FILE__": neither playback nor recording enabled for protocol.\n"); + pa_log(__FILE__": neither playback nor recording enabled for protocol."); goto fail; } diff --git a/src/polypcore/pstream.c b/src/polypcore/pstream.c index c697dc3d6..b1e8bd061 100644 --- a/src/polypcore/pstream.c +++ b/src/polypcore/pstream.c @@ -246,7 +246,7 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet) { if (p->dead) return; -/* pa_log(__FILE__": push-packet %p\n", packet); */ +/* pa_log(__FILE__": push-packet %p", packet); */ i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; @@ -263,7 +263,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa if (p->dead) return; -/* pa_log(__FILE__": push-memblock %p\n", chunk); */ +/* pa_log(__FILE__": push-memblock %p", chunk); */ i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_MEMBLOCK; @@ -301,7 +301,7 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.index = 0; if (p->write.current->type == PA_PSTREAM_ITEM_PACKET) { - /*pa_log(__FILE__": pop-packet %p\n", p->write.current->packet);*/ + /*pa_log(__FILE__": pop-packet %p", p->write.current->packet);*/ assert(p->write.current->packet); p->write.data = p->write.current->packet->data; @@ -385,7 +385,7 @@ static int do_read(pa_pstream *p) { /* Frame size too large */ if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) > FRAME_SIZE_MAX) { - pa_log_warn(__FILE__": Frame size too large\n"); + pa_log_warn(__FILE__": Frame size too large"); return -1; } @@ -401,7 +401,7 @@ static int do_read(pa_pstream *p) { p->read.data = p->read.memblock->data; if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK]) > PA_SEEK_RELATIVE_END) { - pa_log_warn(__FILE__": Invalid seek mode\n"); + pa_log_warn(__FILE__": Invalid seek mode"); return -1; } } diff --git a/src/polypcore/random.c b/src/polypcore/random.c index 756c3218c..1c2280e3f 100644 --- a/src/polypcore/random.c +++ b/src/polypcore/random.c @@ -49,7 +49,7 @@ void pa_random(void *ret_data, size_t length) { if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) { if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length) - pa_log_error(__FILE__": failed to read entropy from '%s'\n", RANDOM_DEVICE); + pa_log_error(__FILE__": failed to read entropy from '%s'", RANDOM_DEVICE); close(fd); } diff --git a/src/polypcore/sample-util.c b/src/polypcore/sample-util.c index e588446d3..2c3fbd790 100644 --- a/src/polypcore/sample-util.c +++ b/src/polypcore/sample-util.c @@ -330,7 +330,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol } default: - pa_log_error(__FILE__": ERROR: Unable to change volume of format %s.\n", + pa_log_error(__FILE__": ERROR: Unable to change volume of format %s.", pa_sample_format_to_string(spec->format)); abort(); } diff --git a/src/polypcore/sink-input.c b/src/polypcore/sink-input.c index 1dc7df0f2..f12a85e17 100644 --- a/src/polypcore/sink-input.c +++ b/src/polypcore/sink-input.c @@ -57,7 +57,7 @@ pa_sink_input* pa_sink_input_new( assert(s->state == PA_SINK_RUNNING); if (pa_idxset_size(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { - pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink.\n"); + pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink."); return NULL; } @@ -106,7 +106,7 @@ pa_sink_input* pa_sink_input_new( assert(r == 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"\n", i->index, i->name, s->index, st); + pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"", i->index, i->name, s->index, st); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); @@ -141,7 +141,7 @@ static void sink_input_free(pa_sink_input* i) { if (i->state != PA_SINK_INPUT_DISCONNECTED) pa_sink_input_disconnect(i); - pa_log_info(__FILE__": freed %u \"%s\"\n", i->index, i->name); + pa_log_info(__FILE__": freed %u \"%s\"", i->index, i->name); if (i->resampled_chunk.memblock) pa_memblock_unref(i->resampled_chunk.memblock); diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index 1f374f5ed..cb072c35c 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -95,7 +95,7 @@ pa_sink* pa_sink_new( assert(s->index != PA_IDXSET_INVALID && r >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); + pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); n = pa_sprintf_malloc("%s_monitor", name); s->monitor_source = pa_source_new(core, driver, n, 0, spec, map); @@ -143,7 +143,7 @@ static void sink_free(pa_sink *s) { if (s->state != PA_SINK_DISCONNECTED) pa_sink_disconnect(s); - pa_log_info(__FILE__": freed %u \"%s\"\n", s->index, s->name); + pa_log_info(__FILE__": freed %u \"%s\"", s->index, s->name); pa_source_unref(s->monitor_source); s->monitor_source = NULL; @@ -270,7 +270,7 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { result->memblock = pa_memblock_new(length, s->core->memblock_stat); assert(result->memblock); -/* pa_log("mixing %i\n", n); */ +/* pa_log("mixing %i", n); */ result->length = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, &s->sw_volume); result->index = 0; diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index 3662e89c7..d73b22d13 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -137,17 +137,17 @@ static void do_call(pa_socket_client *c) { lerror = sizeof(error); if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) { - pa_log(__FILE__": getsockopt(): %s\n", strerror(errno)); + pa_log(__FILE__": getsockopt(): %s", strerror(errno)); goto finish; } if (lerror != sizeof(error)) { - pa_log(__FILE__": getsockopt() returned invalid size.\n"); + pa_log(__FILE__": getsockopt() returned invalid size."); goto finish; } if (error != 0) { - pa_log_debug(__FILE__": connect(): %s\n", strerror(error)); + pa_log_debug(__FILE__": connect(): %s", strerror(error)); errno = error; goto finish; } @@ -188,7 +188,7 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t if ((r = connect(c->fd, sa, len)) < 0) { if (errno != EINPROGRESS) { - /*pa_log(__FILE__": connect(): %s\n", strerror(errno));*/ + /*pa_log(__FILE__": connect(): %s", strerror(errno));*/ return -1; } @@ -259,7 +259,7 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size } if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(): %s", strerror(errno)); return -1; } diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index b12974969..f2e15085b 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -88,7 +88,7 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U pa_socket_server_ref(s); if ((nfd = accept(fd, NULL, NULL)) < 0) { - pa_log(__FILE__": accept(): %s\n", strerror(errno)); + pa_log(__FILE__": accept(): %s", strerror(errno)); goto finish; } @@ -107,12 +107,12 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U request_init(&req, RQ_DAEMON, s->tcpwrap_service, RQ_FILE, nfd, NULL); fromhost(&req); if (!hosts_access(&req)) { - pa_log_warn(__FILE__": TCP connection refused by tcpwrap.\n"); + pa_log_warn(__FILE__": TCP connection refused by tcpwrap."); close(nfd); goto finish; } - pa_log_info(__FILE__": TCP connection accepted by tcpwrap.\n"); + pa_log_info(__FILE__": TCP connection accepted by tcpwrap."); } #endif @@ -167,7 +167,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file assert(m && filename); if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(): %s", strerror(errno)); goto fail; } @@ -180,12 +180,12 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file pa_socket_low_delay(fd); if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { - pa_log(__FILE__": bind(): %s\n", strerror(errno)); + pa_log(__FILE__": bind(): %s", strerror(errno)); goto fail; } if (listen(fd, 5) < 0) { - pa_log(__FILE__": listen(): %s\n", strerror(errno)); + pa_log(__FILE__": listen(): %s", strerror(errno)); goto fail; } @@ -221,14 +221,14 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address assert(m && port); if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_INET): %s\n", strerror(errno)); + pa_log(__FILE__": socket(PF_INET): %s", strerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) - pa_log(__FILE__": setsockopt(): %s\n", strerror(errno)); + pa_log(__FILE__": setsockopt(): %s", strerror(errno)); pa_socket_tcp_low_delay(fd); @@ -238,12 +238,12 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address sa.sin_addr.s_addr = htonl(address); if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { - pa_log(__FILE__": bind(): %s\n", strerror(errno)); + pa_log(__FILE__": bind(): %s", strerror(errno)); goto fail; } if (listen(fd, 5) < 0) { - pa_log(__FILE__": listen(): %s\n", strerror(errno)); + pa_log(__FILE__": listen(): %s", strerror(errno)); goto fail; } @@ -270,14 +270,14 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad assert(m && port); if ((fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_INET6): %s\n", strerror(errno)); + pa_log(__FILE__": socket(PF_INET6): %s", strerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) - pa_log(__FILE__": setsockopt(): %s\n", strerror(errno)); + pa_log(__FILE__": setsockopt(): %s", strerror(errno)); pa_socket_tcp_low_delay(fd); @@ -287,12 +287,12 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad memcpy(sa.sin6_addr.s6_addr, address, 16); if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { - pa_log(__FILE__": bind(): %s\n", strerror(errno)); + pa_log(__FILE__": bind(): %s", strerror(errno)); goto fail; } if (listen(fd, 5) < 0) { - pa_log(__FILE__": listen(): %s\n", strerror(errno)); + pa_log(__FILE__": listen(): %s", strerror(errno)); goto fail; } @@ -348,7 +348,7 @@ pa_socket_server* pa_socket_server_new_ip_string(pa_mainloop_api *m, const char if (inet_pton(AF_INET, name, &ipv4) > 0) return pa_socket_server_new_ipv4(m, ntohl(ipv4), port, tcpwrap_service); - pa_log_warn(__FILE__": failed to parse '%s'.\n", name); + pa_log_warn(__FILE__": failed to parse '%s'.", name); return NULL; } @@ -392,7 +392,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { socklen_t sa_len = sizeof(sa); if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) { - pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno)); + pa_log(__FILE__": getsockname() failed: %s", strerror(errno)); return NULL; } @@ -413,7 +413,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { char ip[INET6_ADDRSTRLEN]; if (!inet_ntop(AF_INET6, &sa.sin6_addr, ip, sizeof(ip))) { - pa_log(__FILE__": inet_ntop() failed: %s\n", strerror(errno)); + pa_log(__FILE__": inet_ntop() failed: %s", strerror(errno)); return NULL; } @@ -428,7 +428,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { socklen_t sa_len = sizeof(sa); if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) { - pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno)); + pa_log(__FILE__": getsockname() failed: %s", strerror(errno)); return NULL; } @@ -448,7 +448,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { char ip[INET_ADDRSTRLEN]; if (!inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip))) { - pa_log(__FILE__": inet_ntop() failed: %s\n", strerror(errno)); + pa_log(__FILE__": inet_ntop() failed: %s", strerror(errno)); return NULL; } diff --git a/src/polypcore/socket-util.c b/src/polypcore/socket-util.c index 5ffe5302b..915c7f224 100644 --- a/src/polypcore/socket-util.c +++ b/src/polypcore/socket-util.c @@ -172,7 +172,7 @@ int pa_socket_set_rcvbuf(int fd, size_t l) { assert(fd >= 0); /* if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&l, sizeof(l)) < 0) { */ -/* pa_log(__FILE__": SO_RCVBUF: %s\n", strerror(errno)); */ +/* pa_log(__FILE__": SO_RCVBUF: %s", strerror(errno)); */ /* return -1; */ /* } */ @@ -183,7 +183,7 @@ int pa_socket_set_sndbuf(int fd, size_t l) { assert(fd >= 0); /* if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&l, sizeof(l)) < 0) { */ -/* pa_log(__FILE__": SO_SNDBUF: %s\n", strerror(errno)); */ +/* pa_log(__FILE__": SO_SNDBUF: %s", strerror(errno)); */ /* return -1; */ /* } */ @@ -197,7 +197,7 @@ int pa_unix_socket_is_stale(const char *fn) { int fd = -1, ret = -1; if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s\n", strerror(errno)); + pa_log(__FILE__": socket(): %s", strerror(errno)); goto finish; } diff --git a/src/polypcore/sound-file-stream.c b/src/polypcore/sound-file-stream.c index 644e578f7..e242cfea0 100644 --- a/src/polypcore/sound-file-stream.c +++ b/src/polypcore/sound-file-stream.c @@ -131,7 +131,7 @@ int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume) { memset(&sfinfo, 0, sizeof(sfinfo)); if (!(u->sndfile = sf_open(fname, SFM_READ, &sfinfo))) { - pa_log(__FILE__": Failed to open file %s\n", fname); + pa_log(__FILE__": Failed to open file %s", fname); goto fail; } @@ -154,7 +154,7 @@ int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume) { ss.channels = sfinfo.channels; if (!pa_sample_spec_valid(&ss)) { - pa_log(__FILE__": Unsupported sample format in file %s\n", fname); + pa_log(__FILE__": Unsupported sample format in file %s", fname); goto fail; } diff --git a/src/polypcore/sound-file.c b/src/polypcore/sound-file.c index cf23e0acd..d86141ce4 100644 --- a/src/polypcore/sound-file.c +++ b/src/polypcore/sound-file.c @@ -49,7 +49,7 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_memchunk *chunk memset(&sfinfo, 0, sizeof(sfinfo)); if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { - pa_log(__FILE__": Failed to open file %s\n", fname); + pa_log(__FILE__": Failed to open file %s", fname); goto finish; } @@ -71,12 +71,12 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_memchunk *chunk ss->channels = sfinfo.channels; if (!pa_sample_spec_valid(ss)) { - pa_log(__FILE__": Unsupported sample format in file %s\n", fname); + pa_log(__FILE__": Unsupported sample format in file %s", fname); goto finish; } if ((l = pa_frame_size(ss)*sfinfo.frames) > MAX_FILE_SIZE) { - pa_log(__FILE__": File too large\n"); + pa_log(__FILE__": File too large"); goto finish; } @@ -86,7 +86,7 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_memchunk *chunk chunk->length = l; if (readf_function(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) { - pa_log(__FILE__": Premature file end\n"); + pa_log(__FILE__": Premature file end"); goto finish; } @@ -110,7 +110,7 @@ int pa_sound_file_too_big_to_cache(const char *fname) { pa_sample_spec ss; if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { - pa_log(__FILE__": Failed to open file %s\n", fname); + pa_log(__FILE__": Failed to open file %s", fname); return 0; } @@ -132,7 +132,7 @@ int pa_sound_file_too_big_to_cache(const char *fname) { ss.channels = sfinfo.channels; if ((pa_frame_size(&ss) * sfinfo.frames) > MAX_FILE_SIZE) { - pa_log(__FILE__": File too large %s\n", fname); + pa_log(__FILE__": File too large %s", fname); return 1; } diff --git a/src/polypcore/source-output.c b/src/polypcore/source-output.c index d6201b4dc..0cb5f3567 100644 --- a/src/polypcore/source-output.c +++ b/src/polypcore/source-output.c @@ -53,7 +53,7 @@ pa_source_output* pa_source_output_new( assert(s->state == PA_SOURCE_RUNNING); if (pa_idxset_size(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { - pa_log(__FILE__": Failed to create source output: too many outputs per source.\n"); + pa_log(__FILE__": Failed to create source output: too many outputs per source."); return NULL; } @@ -95,7 +95,7 @@ pa_source_output* pa_source_output_new( assert(r == 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"\n", o->index, o->name, s->index, st); + pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"", o->index, o->name, s->index, st); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index); @@ -127,7 +127,7 @@ static void source_output_free(pa_source_output* o) { if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED) pa_source_output_disconnect(o); - pa_log_info(__FILE__": freed %u \"%s\"\n", o->index, o->name); + pa_log_info(__FILE__": freed %u \"%s\"", o->index, o->name); if (o->resampler) pa_resampler_free(o->resampler); diff --git a/src/polypcore/source.c b/src/polypcore/source.c index 8bca8a1de..e97c31d8a 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -91,7 +91,7 @@ pa_source* pa_source_new( assert(s->index != PA_IDXSET_INVALID && r >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st); + pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); @@ -130,7 +130,7 @@ static void source_free(pa_source *s) { if (s->state != PA_SOURCE_DISCONNECTED) pa_source_disconnect(s); - pa_log_info(__FILE__": freed %u \"%s\"\n", s->index, s->name); + pa_log_info(__FILE__": freed %u \"%s\"", s->index, s->name); pa_idxset_free(s->outputs, NULL, NULL); diff --git a/src/polypcore/util.c b/src/polypcore/util.c index 2ae94d25a..f53eef343 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -120,10 +120,10 @@ void pa_make_nonblock_fd(int fd) { u_long arg = 1; if (ioctlsocket(fd, FIONBIO, &arg) < 0) { if (WSAGetLastError() == WSAENOTSOCK) - pa_log_warn(__FILE__": WARNING: Only sockets can be made non-blocking!\n"); + pa_log_warn(__FILE__": WARNING: Only sockets can be made non-blocking!"); } #else - pa_log_warn(__FILE__": WARNING: Non-blocking I/O not supported.!\n"); + pa_log_warn(__FILE__": WARNING: Non-blocking I/O not supported.!"); #endif } @@ -242,7 +242,7 @@ void pa_check_signal_is_blocked(int sig) { if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) { #endif if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) { - pa_log(__FILE__": sigprocmask() failed: %s\n", strerror(errno)); + pa_log(__FILE__": sigprocmask() failed: %s", strerror(errno)); return; } #ifdef HAVE_PTHREAD @@ -255,16 +255,16 @@ void pa_check_signal_is_blocked(int sig) { /* Check whether the signal is trapped */ if (sigaction(sig, NULL, &sa) < 0) { - pa_log(__FILE__": sigaction() failed: %s\n", strerror(errno)); + pa_log(__FILE__": sigaction() failed: %s", strerror(errno)); return; } if (sa.sa_handler != SIG_DFL) return; - pa_log(__FILE__": WARNING: %s is not trapped. This might cause malfunction!\n", pa_strsignal(sig)); + pa_log(__FILE__": WARNING: %s is not trapped. This might cause malfunction!", pa_strsignal(sig)); #else /* HAVE_SIGACTION */ - pa_log(__FILE__": WARNING: %s might not be trapped. This might cause malfunction!\n", pa_strsignal(sig)); + pa_log(__FILE__": WARNING: %s might not be trapped. This might cause malfunction!", pa_strsignal(sig)); #endif } @@ -366,7 +366,7 @@ char *pa_get_user_name(char *s, size_t l) { char *pa_get_host_name(char *s, size_t l) { assert(s && l > 0); if (gethostname(s, l) < 0) { - pa_log(__FILE__": gethostname(): %s\n", strerror(errno)); + pa_log(__FILE__": gethostname(): %s", strerror(errno)); return NULL; } s[l-1] = 0; @@ -393,12 +393,12 @@ char *pa_get_home_dir(char *s, size_t l) { #ifdef HAVE_PWD_H #ifdef HAVE_GETPWUID_R if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { - pa_log(__FILE__": getpwuid_r() failed\n"); + pa_log(__FILE__": getpwuid_r() failed"); #else /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) * that do not support getpwuid_r. */ if ((r = getpwuid(getuid())) == NULL) { - pa_log(__FILE__": getpwuid_r() failed\n"); + pa_log(__FILE__": getpwuid_r() failed"); #endif return NULL; } @@ -534,9 +534,9 @@ void pa_raise_priority(void) { #ifdef HAVE_SYS_RESOURCE_H if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) - pa_log_warn(__FILE__": setpriority() failed: %s\n", strerror(errno)); + pa_log_warn(__FILE__": setpriority() failed: %s", strerror(errno)); else - pa_log_info(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); + pa_log_info(__FILE__": Successfully gained nice level %i.", NICE_LEVEL); #endif #ifdef _POSIX_PRIORITY_SCHEDULING @@ -544,25 +544,25 @@ void pa_raise_priority(void) { struct sched_param sp; if (sched_getparam(0, &sp) < 0) { - pa_log(__FILE__": sched_getparam() failed: %s\n", strerror(errno)); + pa_log(__FILE__": sched_getparam() failed: %s", strerror(errno)); return; } sp.sched_priority = 1; if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) { - pa_log_warn(__FILE__": sched_setscheduler() failed: %s\n", strerror(errno)); + pa_log_warn(__FILE__": sched_setscheduler() failed: %s", strerror(errno)); return; } - pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); + pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling."); } #endif #ifdef OS_IS_WIN32 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) - pa_log_warn(__FILE__": SetPriorityClass() failed: 0x%08X\n", GetLastError()); + pa_log_warn(__FILE__": SetPriorityClass() failed: 0x%08X", GetLastError()); else - pa_log_info(__FILE__": Successfully gained high priority class.\n"); + pa_log_info(__FILE__": Successfully gained high priority class."); #endif } @@ -741,7 +741,7 @@ static int is_group(gid_t gid, const char *name) { data = pa_xmalloc(n); if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) { - pa_log(__FILE__ ": getgrgid_r(%u) failed: %s\n", gid, strerror(errno)); + pa_log(__FILE__ ": getgrgid_r(%u) failed: %s", gid, strerror(errno)); goto finish; } @@ -754,7 +754,7 @@ finish: /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not * support getgrgid_r. */ if ((result = getgrgid(gid)) == NULL) { - pa_log(__FILE__ ": getgrgid(%u) failed: %s\n", gid, strerror(errno)); + pa_log(__FILE__ ": getgrgid(%u) failed: %s", gid, strerror(errno)); goto finish; } @@ -777,7 +777,7 @@ int pa_uid_in_group(const char *name, gid_t *gid) { gids = pa_xmalloc(sizeof(GETGROUPS_T)*n); if ((n = getgroups(n, gids)) < 0) { - pa_log(__FILE__": getgroups() failed: %s\n", strerror(errno)); + pa_log(__FILE__": getgroups() failed: %s", strerror(errno)); goto finish; } @@ -834,7 +834,7 @@ int pa_lock_fd(int fd, int b) { return 0; } - pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno)); + pa_log(__FILE__": %slock failed: %s", !b ? "un" : "", strerror(errno)); #endif #ifdef OS_IS_WIN32 @@ -845,7 +845,7 @@ int pa_lock_fd(int fd, int b) { if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF)) return 0; - pa_log(__FILE__": %slock failed: 0x%08X\n", !b ? "un" : "", GetLastError()); + pa_log(__FILE__": %slock failed: 0x%08X", !b ? "un" : "", GetLastError()); #endif return -1; @@ -868,17 +868,17 @@ int pa_lock_lockfile(const char *fn) { struct stat st; if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": failed to create lock file '%s': %s\n", fn, strerror(errno)); + pa_log(__FILE__": failed to create lock file '%s': %s", fn, strerror(errno)); goto fail; } if (pa_lock_fd(fd, 1) < 0) { - pa_log(__FILE__": failed to lock file '%s'.\n", fn); + pa_log(__FILE__": failed to lock file '%s'.", fn); goto fail; } if (fstat(fd, &st) < 0) { - pa_log(__FILE__": failed to fstat() file '%s'.\n", fn); + pa_log(__FILE__": failed to fstat() file '%s'.", fn); goto fail; } @@ -887,12 +887,12 @@ int pa_lock_lockfile(const char *fn) { break; if (pa_lock_fd(fd, 0) < 0) { - pa_log(__FILE__": failed to unlock file '%s'.\n", fn); + pa_log(__FILE__": failed to unlock file '%s'.", fn); goto fail; } if (close(fd) < 0) { - pa_log(__FILE__": failed to close file '%s'.\n", fn); + pa_log(__FILE__": failed to close file '%s'.", fn); goto fail; } @@ -915,17 +915,17 @@ int pa_unlock_lockfile(const char *fn, int fd) { assert(fn && fd >= 0); if (unlink(fn) < 0) { - pa_log_warn(__FILE__": WARNING: unable to remove lock file '%s': %s\n", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: unable to remove lock file '%s': %s", fn, strerror(errno)); r = -1; } if (pa_lock_fd(fd, 0) < 0) { - pa_log_warn(__FILE__": WARNING: failed to unlock file '%s'.\n", fn); + pa_log_warn(__FILE__": WARNING: failed to unlock file '%s'.", fn); r = -1; } if (close(fd) < 0) { - pa_log_warn(__FILE__": WARNING: failed to close lock file '%s': %s\n", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to close lock file '%s': %s", fn, strerror(errno)); r = -1; } diff --git a/src/polypcore/x11wrap.c b/src/polypcore/x11wrap.c index 9414fbdfd..21a7f3076 100644 --- a/src/polypcore/x11wrap.c +++ b/src/polypcore/x11wrap.c @@ -138,7 +138,7 @@ static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char int r; if (!(d = XOpenDisplay(name))) { - pa_log(__FILE__": XOpenDisplay() failed\n"); + pa_log(__FILE__": XOpenDisplay() failed"); return NULL; } diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 4054bc2c1..a71e0e934 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -46,12 +46,12 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { fd_set ifds, ofds; if (pa_pid_file_check_running(&pid) < 0) { - pa_log(__FILE__": no Polypaudio daemon running\n"); + pa_log(__FILE__": no Polypaudio daemon running"); goto fail; } if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s\n", strerror(errno)); + pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); goto fail; } @@ -63,7 +63,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { int r; if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { - pa_log(__FILE__": connect() failed: %s\n", strerror(errno)); + pa_log(__FILE__": connect() failed: %s", strerror(errno)); goto fail; } @@ -71,7 +71,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { break; if (pa_pid_file_kill(SIGUSR2, NULL) < 0) { - pa_log(__FILE__": failed to kill Polypaudio daemon.\n"); + pa_log(__FILE__": failed to kill Polypaudio daemon."); goto fail; } @@ -79,7 +79,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { } if (i >= 5) { - pa_log(__FILE__": daemon not responding.\n"); + pa_log(__FILE__": daemon not responding."); goto fail; } @@ -94,7 +94,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { for (;;) { if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { - pa_log(__FILE__": select() failed: %s\n", strerror(errno)); + pa_log(__FILE__": select() failed: %s", strerror(errno)); goto fail; } @@ -106,7 +106,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s", strerror(errno)); goto fail; } @@ -122,7 +122,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read() failed: %s\n", strerror(errno)); + pa_log(__FILE__": read() failed: %s", strerror(errno)); goto fail; } @@ -135,7 +135,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { assert(obuf_length); if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); goto fail; } @@ -149,7 +149,7 @@ int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { assert(ibuf_length); if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { - pa_log(__FILE__": write() failed: %s\n", strerror(errno)); + pa_log(__FILE__": write() failed: %s", strerror(errno)); goto fail; } diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 56b62d372..e43588949 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -90,7 +90,7 @@ int main(int argc, char *argv[]) { } if (!(d = XOpenDisplay(dname))) { - pa_log(__FILE__": XOpenDisplay() failed\n"); + pa_log(__FILE__": XOpenDisplay() failed"); goto finish; } From 275611722336a138d74bdf892ee12cbf73f0e734 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Feb 2006 02:28:17 +0000 Subject: [PATCH 0482/1514] ignore pabrowse git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@575 fefdeb5f-60dc-0310-8127-8f9354f1896f From a4ab652a7c2833c084dcc274d14cbd892520f298 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Feb 2006 02:29:36 +0000 Subject: [PATCH 0483/1514] really ignore pabrowse git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@576 fefdeb5f-60dc-0310-8127-8f9354f1896f From c2290c52a4af1be39cb9ecbaa26eb524426f98dc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 23 Feb 2006 02:29:52 +0000 Subject: [PATCH 0484/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@577 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/todo b/doc/todo index 9abfd2d07..18a2218d2 100644 --- a/doc/todo +++ b/doc/todo @@ -6,9 +6,8 @@ Test: Fixes: - better validity checking in protocol-esound -- change pa_log to not require \n - proper use of memcpy in procotol-esound.c so we don't get alignment problems -- latency api for native protocol +- latency api rework for native protocol - add support for auth using SCM_CREDENTIALS - use scatter/gather io for sockets - notification on hw volume change From ce9b035b7bf2af53bbfcabbc474e62f422224f87 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 08:59:31 +0000 Subject: [PATCH 0485/1514] Hardware source volume support in OSS. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@578 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss-mmap.c | 32 ++++++++++++++++++++++++++++++-- src/modules/module-oss.c | 32 ++++++++++++++++++++++++++++++-- src/modules/oss-util.c | 24 ++++++++++++++++++++---- src/modules/oss-util.h | 7 +++++-- 4 files changed, 85 insertions(+), 10 deletions(-) diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 9687c9084..e1e54fb58 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -224,7 +224,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { static int sink_get_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; - if (pa_oss_get_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); s->get_hw_volume = NULL; return -1; @@ -236,7 +236,31 @@ static int sink_get_hw_volume(pa_sink *s) { static int sink_set_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; - if (pa_oss_set_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); + s->set_hw_volume = NULL; + return -1; + } + + return 0; +} + +static int source_get_hw_volume(pa_source *s) { + struct userdata *u = s->userdata; + + if (pa_oss_get_imix_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); + s->get_hw_volume = NULL; + return -1; + } + + return 0; +} + +static int source_set_hw_volume(pa_source *s) { + struct userdata *u = s->userdata; + + if (pa_oss_set_imix_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); s->set_hw_volume = NULL; return -1; @@ -337,6 +361,8 @@ int pa__init(pa_core *c, pa_module*m) { u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec, NULL); assert(u->source); + u->source->get_hw_volume = source_get_hw_volume; + u->source->set_hw_volume = source_set_hw_volume; u->source->userdata = u; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'%s%s%s", @@ -409,6 +435,8 @@ int pa__init(pa_core *c, pa_module*m) { pa_modargs_free(ma); /* Read mixer settings */ + if (u->source) + source_get_hw_volume(u->source); if (u->sink) sink_get_hw_volume(u->sink); diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 67ece5a71..3a3f6b88e 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -256,7 +256,7 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { static int sink_get_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; - if (pa_oss_get_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); s->get_hw_volume = NULL; return -1; @@ -268,7 +268,31 @@ static int sink_get_hw_volume(pa_sink *s) { static int sink_set_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; - if (pa_oss_set_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); + s->set_hw_volume = NULL; + return -1; + } + + return 0; +} + +static int source_get_hw_volume(pa_source *s) { + struct userdata *u = s->userdata; + + if (pa_oss_get_imix_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); + s->get_hw_volume = NULL; + return -1; + } + + return 0; +} + +static int source_set_hw_volume(pa_source *s) { + struct userdata *u = s->userdata; + + if (pa_oss_set_imix_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); s->set_hw_volume = NULL; return -1; @@ -368,6 +392,8 @@ int pa__init(pa_core *c, pa_module*m) { u->source->userdata = u; u->source->notify = source_notify_cb; u->source->get_latency = source_get_latency_cb; + u->source->get_hw_volume = source_get_hw_volume; + u->source->set_hw_volume = source_set_hw_volume; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Open Sound System PCM on '%s'%s%s%s", p, @@ -426,6 +452,8 @@ int pa__init(pa_core *c, pa_module*m) { } /* Read mixer settings */ + if (u->source) + source_get_hw_volume(u->source); if (u->sink) sink_get_hw_volume(u->sink); diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 2c12e28d3..30a4b9980 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -167,7 +167,7 @@ int pa_oss_set_fragments(int fd, int nfrags, int frag_size) { return 0; } -int pa_oss_get_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { +static int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *volume) { char cv[PA_CVOLUME_SNPRINT_MAX]; unsigned vol; @@ -175,7 +175,7 @@ int pa_oss_get_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { assert(ss); assert(volume); - if (ioctl(fd, SOUND_MIXER_READ_PCM, &vol) < 0) + if (ioctl(fd, mixer, &vol) < 0) return -1; volume->values[0] = ((vol & 0xFF) * PA_VOLUME_NORM) / 100; @@ -187,7 +187,7 @@ int pa_oss_get_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { return 0; } -int pa_oss_set_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume) { +static int pa_oss_set_volume(int fd, int mixer, const pa_sample_spec *ss, const pa_cvolume *volume) { char cv[PA_CVOLUME_SNPRINT_MAX]; unsigned vol; @@ -196,13 +196,29 @@ int pa_oss_set_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume if (ss->channels >= 2) vol |= ((volume->values[1]*100)/PA_VOLUME_NORM) << 8; - if (ioctl(fd, SOUND_MIXER_WRITE_PCM, &vol) < 0) + if (ioctl(fd, mixer, &vol) < 0) return -1; pa_log_debug(__FILE__": Wrote mixer settings: %s", pa_cvolume_snprint(cv, sizeof(cv), volume)); return 0; } +int pa_oss_get_pcm_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { + return pa_oss_get_volume(fd, SOUND_MIXER_READ_PCM, ss, volume); +} + +int pa_oss_set_pcm_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume) { + return pa_oss_set_volume(fd, SOUND_MIXER_WRITE_PCM, ss, volume); +} + +int pa_oss_get_imix_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { + return pa_oss_get_volume(fd, SOUND_MIXER_READ_IMIX, ss, volume); +} + +int pa_oss_set_imix_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume) { + return pa_oss_set_volume(fd, SOUND_MIXER_WRITE_IMIX, ss, volume); +} + int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { FILE *f; const char *e = NULL; diff --git a/src/modules/oss-util.h b/src/modules/oss-util.h index 3033c76fc..dd494d0cc 100644 --- a/src/modules/oss-util.h +++ b/src/modules/oss-util.h @@ -30,8 +30,11 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss); int pa_oss_set_fragments(int fd, int frags, int frag_size); -int pa_oss_get_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume); -int pa_oss_set_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume); +int pa_oss_get_pcm_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume); +int pa_oss_set_pcm_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume); + +int pa_oss_get_imix_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume); +int pa_oss_set_imix_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume); int pa_oss_get_hw_description(const char *dev, char *name, size_t l); From 12e35c546c97e3b36d8c0656c571b6b3f2c7d46a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 09:07:49 +0000 Subject: [PATCH 0486/1514] Make sure hardware volume gets a correct initial value. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@579 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 1de21aed5..76f50935d 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -482,6 +482,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_modargs_free(ma); + /* Read mixer settings */ + if (u->sink) + sink_get_hw_volume(u->sink); + return 0; fail: From f8aca21379e6caf09ebcd1129ee90195c7e24714 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 09:08:06 +0000 Subject: [PATCH 0487/1514] Wrong function name. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@580 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 76f50935d..eb909e4f7 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -484,7 +484,7 @@ int pa__init(pa_core *c, pa_module*m) { /* Read mixer settings */ if (u->sink) - sink_get_hw_volume(u->sink); + sink_get_hw_volume_cb(u->sink); return 0; From 7050dbfdae212c56e23bbb42c9300e4c72726568 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 09:28:39 +0000 Subject: [PATCH 0488/1514] Update hardware volume to a correct initial value. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@581 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 02f865c55..45ed10b97 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -554,6 +554,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_modargs_free(ma); + /* Read mixer settings */ + if (u->sink) + sink_get_hw_volume_cb(u->sink); + return 0; fail: From adad7dc672361142fef33d73264e6c053a2a29ce Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 09:30:31 +0000 Subject: [PATCH 0489/1514] Add inet_pton emulation for platforms that lack it. Only support IPv4 at this point. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@582 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- src/Makefile.am | 1 + src/polypcore/inet_pton.c | 62 +++++++++++++++++++++++++++++++++++ src/polypcore/inet_pton.h | 12 +++++++ src/polypcore/socket-server.c | 4 +++ 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/polypcore/inet_pton.c create mode 100644 src/polypcore/inet_pton.h diff --git a/configure.ac b/configure.ac index 76b964254..25a89edc0 100644 --- a/configure.ac +++ b/configure.ac @@ -206,7 +206,7 @@ AC_FUNC_FORK AC_FUNC_GETGROUPS AC_FUNC_SELECT_ARGTYPES AC_CHECK_FUNCS([getaddrinfo getgrgid_r getpwuid_r gettimeofday getuid \ - inet_ntop nanosleep setpgid setsid sigaction sleep]) + inet_ntop inet_pton nanosleep setpgid setsid sigaction sleep]) AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0]) AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1") diff --git a/src/Makefile.am b/src/Makefile.am index f36630e76..01ec9ef7a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -601,6 +601,7 @@ libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-server.la libsocket_server_la_SOURCES = \ polypcore/inet_ntop.c polypcore/inet_ntop.h \ + polypcore/inet_pton.c polypcore/inet_pton.h \ polypcore/socket-server.c polypcore/socket-server.h libsocket_server_la_LDFLAGS = -avoid-version libsocket_server_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS) diff --git a/src/polypcore/inet_pton.c b/src/polypcore/inet_pton.c new file mode 100644 index 000000000..17860f6d2 --- /dev/null +++ b/src/polypcore/inet_pton.c @@ -0,0 +1,62 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#ifndef HAVE_INET_PTON + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#include "winsock.h" + +#include "inet_pton.h" + +int inet_pton(int af, const char *src, void *dst) { + struct in_addr *in = (struct in_addr*)dst; + struct in6_addr *in6 = (struct in6_addr*)dst; + + assert(src && dst); + + switch (af) { + case AF_INET: + in->s_addr = inet_addr(src); + if (in->s_addr == INADDR_NONE) + return 0; + break; + case AF_INET6: + /* FIXME */ + default: + errno = EAFNOSUPPORT; + return -1; + } + + return 1; +} + +#endif /* INET_PTON */ diff --git a/src/polypcore/inet_pton.h b/src/polypcore/inet_pton.h new file mode 100644 index 000000000..111b4a07f --- /dev/null +++ b/src/polypcore/inet_pton.h @@ -0,0 +1,12 @@ +#ifndef fooinet_ptonhfoo +#define fooinet_ptonhfoo + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#include "winsock.h" + +int inet_pton(int af, const char *src, void *dst); + +#endif diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index f2e15085b..4e89c5d30 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -56,6 +56,10 @@ #include "inet_ntop.h" #endif +#ifndef HAVE_INET_PTON +#include "inet_pton.h" +#endif + #include "winsock.h" #include From 4e8faa6debe0495a924aadb40ff033aeb93d0e4e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 09:37:44 +0000 Subject: [PATCH 0490/1514] inet_pton expects in[6]_addr structures, nothing else. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@583 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/socket-server.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index 4e89c5d30..d457d626a 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -339,18 +339,18 @@ pa_socket_server* pa_socket_server_new_ip_any(pa_mainloop_api *m, uint16_t port, } pa_socket_server* pa_socket_server_new_ip_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { - uint8_t ipv6[16]; - uint32_t ipv4; + struct in6_addr ipv6; + struct in_addr ipv4; assert(m); assert(name); assert(port > 0); - if (inet_pton(AF_INET6, name, ipv6) > 0) - return pa_socket_server_new_ipv6(m, ipv6, port, tcpwrap_service); + if (inet_pton(AF_INET6, name, &ipv6) > 0) + return pa_socket_server_new_ipv6(m, ipv6.s6_addr, port, tcpwrap_service); if (inet_pton(AF_INET, name, &ipv4) > 0) - return pa_socket_server_new_ipv4(m, ntohl(ipv4), port, tcpwrap_service); + return pa_socket_server_new_ipv4(m, ntohl(ipv4.s_addr), port, tcpwrap_service); pa_log_warn(__FILE__": failed to parse '%s'.", name); From 79e800904500fd3adcb14a19d7a8ec0436f9d5bf Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 09:44:50 +0000 Subject: [PATCH 0491/1514] Hardware source volume support. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@584 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index eb909e4f7..a74a70c23 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -292,6 +292,40 @@ static int sink_set_hw_volume_cb(pa_sink *s) { return 0; } +static int source_get_hw_volume_cb(pa_source *s) { + struct userdata *u = s->userdata; + audio_info_t info; + int err; + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, + info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); + + return 0; +} + +static int source_set_hw_volume_cb(pa_source *s) { + struct userdata *u = s->userdata; + audio_info_t info; + + AUDIO_INITINFO(&info); + + info.record.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; + assert(info.record.gain <= AUDIO_MAX_GAIN); + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); + else + pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + return -1; + } + + return 0; +} + static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { audio_info_t info; @@ -436,6 +470,8 @@ int pa__init(pa_core *c, pa_module*m) { assert(u->source); u->source->userdata = u; u->source->get_latency = source_get_latency_cb; + u->source->get_hw_volume = source_get_hw_volume_cb; + u->source->set_hw_volume = source_set_hw_volume_cb; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); } else @@ -483,6 +519,8 @@ int pa__init(pa_core *c, pa_module*m) { pa_modargs_free(ma); /* Read mixer settings */ + if (u->source) + sink_get_hw_volume_cb(u->source); if (u->sink) sink_get_hw_volume_cb(u->sink); From 607b2796dada282fd33fd9f075a1d7f339cd96ac Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 09:45:32 +0000 Subject: [PATCH 0492/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@585 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 18a2218d2..3bd0c716d 100644 --- a/doc/todo +++ b/doc/todo @@ -11,7 +11,6 @@ Fixes: - add support for auth using SCM_CREDENTIALS - use scatter/gather io for sockets - notification on hw volume change -- source volume control - mute switch support (like ALSA does it) - module-oss-* love: - deal with underflows propely From bd4ae44e9a4b4cf3071cbbbaf9bbb4f84397cd90 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 12:00:58 +0000 Subject: [PATCH 0493/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@586 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 3bd0c716d..3c478e500 100644 --- a/doc/todo +++ b/doc/todo @@ -20,6 +20,7 @@ Fixes: - add hw driver name to sink/source description - deal with underflows properly - multiline configuration statements +- module-tunnel volume support (sink, source, notify) Post 0.8: - alsa mmap driver From 04c8926739cd5d979077b81b73a0ead0458594a7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 12:04:31 +0000 Subject: [PATCH 0494/1514] Mute switch for sinks and sources. This is independent of the volume setting (similar to ALSA). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@587 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/introspect.c | 94 +++++++++++++++++++++++++++++++++ src/polyp/introspect.h | 14 +++++ src/polypcore/cli-command.c | 64 ++++++++++++++++++++++ src/polypcore/native-common.h | 3 ++ src/polypcore/protocol-native.c | 55 +++++++++++++++++++ src/polypcore/sample-util.c | 9 ++-- src/polypcore/sample-util.h | 3 +- src/polypcore/sink.c | 62 +++++++++++++++++++--- src/polypcore/sink.h | 5 ++ src/polypcore/source.c | 50 +++++++++++++++++- src/polypcore/source.h | 5 ++ 11 files changed, 351 insertions(+), 13 deletions(-) diff --git a/src/polyp/introspect.c b/src/polyp/introspect.c index 6a9917a70..6a28998c4 100644 --- a/src/polyp/introspect.c +++ b/src/polyp/introspect.c @@ -146,6 +146,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || pa_tagstruct_get_cvolume(t, &i.volume) < 0 || + pa_tagstruct_get_boolean(t, &i.mute) < 0 || pa_tagstruct_getu32(t, &i.monitor_source) < 0 || pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || pa_tagstruct_get_usec(t, &i.latency) < 0 || @@ -249,6 +250,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || pa_tagstruct_get_cvolume(t, &i.volume) < 0 || + pa_tagstruct_get_boolean(t, &i.mute) < 0 || pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 || pa_tagstruct_get_usec(t, &i.latency) < 0 || @@ -682,6 +684,52 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name return o; } +pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_MUTE, &tag); + pa_tagstruct_putu32(t, idx); + pa_tagstruct_puts(t, NULL); + pa_tagstruct_put_boolean(t, mute); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + + return o; +} + +pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + assert(name); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_MUTE, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_boolean(t, mute); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + + return o; +} + pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; @@ -756,6 +804,52 @@ pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *na return o; } +pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_MUTE, &tag); + pa_tagstruct_putu32(t, idx); + pa_tagstruct_puts(t, NULL); + pa_tagstruct_put_boolean(t, mute); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + + return o; +} + +pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + assert(name); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_MUTE, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, name); + pa_tagstruct_put_boolean(t, mute); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + + return o; +} + /** Sample Cache **/ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { diff --git a/src/polyp/introspect.h b/src/polyp/introspect.h index d7fad9c44..4ef776f8a 100644 --- a/src/polyp/introspect.h +++ b/src/polyp/introspect.h @@ -58,6 +58,7 @@ typedef struct pa_sink_info { pa_channel_map channel_map; /**< Channel map \since 0.9 */ uint32_t owner_module; /**< Index of the owning module of this sink, or PA_INVALID_INDEX */ pa_cvolume volume; /**< Volume of the sink */ + int mute; /**< Mute switch of the sink \since 0.8 */ uint32_t monitor_source; /**< Index of the monitor source connected to this sink */ const char *monitor_source_name; /**< The name of the monitor source */ pa_usec_t latency; /**< Length of filled playback buffer of this sink */ @@ -85,6 +86,7 @@ typedef struct pa_source_info { pa_channel_map channel_map; /**< Channel map \since 0.9 */ uint32_t owner_module; /**< Owning module index, or PA_INVALID_INDEX */ pa_cvolume volume; /**< Volume of the source \since 0.8 */ + int mute; /**< Mute switch of the sink \since 0.8 */ uint32_t monitor_of_sink; /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */ const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */ pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */ @@ -211,6 +213,12 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, c /** Set the volume of a sink device specified by its name */ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); +/** Set the mute switch of a sink device specified by its index \since 0.8 */ +pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata); + +/** Set the mute switch of a sink device specified by its name \since 0.8 */ +pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata); + /** Set the volume of a sink input stream */ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); @@ -220,6 +228,12 @@ pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, /** Set the volume of a source device specified by its name \since 0.8 */ pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); +/** Set the mute switch of a source device specified by its index \since 0.8 */ +pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata); + +/** Set the mute switch of a source device specified by its name \since 0.8 */ +pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata); + /** Memory block statistics */ typedef struct pa_stat_info { uint32_t memblock_total; /**< Currently allocated memory blocks */ diff --git a/src/polypcore/cli-command.c b/src/polypcore/cli-command.c index cd7993a8e..0251ab0a9 100644 --- a/src/polypcore/cli-command.c +++ b/src/polypcore/cli-command.c @@ -78,6 +78,8 @@ static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, in static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); @@ -116,6 +118,8 @@ static const struct command commands[] = { { "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3}, { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index|name, volume)", 3}, { "set-source-volume", pa_cli_command_source_volume, "Set the volume of a source (args: index|name, volume)", 3}, + { "set-sink-mute", pa_cli_command_sink_mute, "Set the mute switch of a sink (args: index|name, mute)", 3}, + { "set-source-mute", pa_cli_command_source_mute, "Set the mute switch of a source (args: index|name, mute)", 3}, { "set-default-sink", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2}, { "set-default-source", pa_cli_command_source_default, "Set the default source (args: index|name)", 2}, { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, @@ -409,6 +413,64 @@ static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf * return 0; } +static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { + const char *n, *m; + pa_sink *sink; + int mute; + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n"); + return -1; + } + + if (!(m = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n"); + return -1; + } + + if (pa_atoi(m, &mute) < 0) { + pa_strbuf_puts(buf, "Failed to parse mute switch.\n"); + return -1; + } + + if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) { + pa_strbuf_puts(buf, "No sink found by this name or index.\n"); + return -1; + } + + pa_sink_set_mute(sink, PA_MIXER_HARDWARE, mute); + return 0; +} + +static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { + const char *n, *m; + pa_source *source; + int mute; + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n"); + return -1; + } + + if (!(m = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n"); + return -1; + } + + if (pa_atoi(m, &mute) < 0) { + pa_strbuf_puts(buf, "Failed to parse mute switch.\n"); + return -1; + } + + if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE, 1))) { + pa_strbuf_puts(buf, "No sink found by this name or index.\n"); + return -1; + } + + pa_source_set_mute(source, PA_MIXER_HARDWARE, mute); + return 0; +} + static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { const char *n; assert(c && t); @@ -711,6 +773,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G } pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, PA_MIXER_HARDWARE))); + pa_strbuf_printf(buf, "set-sink-mute %s %d\n", sink->name, pa_sink_get_mute(sink, PA_MIXER_HARDWARE)); } for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) { @@ -723,6 +786,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G } pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source, PA_MIXER_HARDWARE))); + pa_strbuf_printf(buf, "set-source-mute %s %d\n", source->name, pa_source_get_mute(source, PA_MIXER_HARDWARE)); } diff --git a/src/polypcore/native-common.h b/src/polypcore/native-common.h index a5ca5c961..1107da552 100644 --- a/src/polypcore/native-common.h +++ b/src/polypcore/native-common.h @@ -72,6 +72,9 @@ enum { PA_COMMAND_SET_SINK_VOLUME, PA_COMMAND_SET_SINK_INPUT_VOLUME, PA_COMMAND_SET_SOURCE_VOLUME, + + PA_COMMAND_SET_SINK_MUTE, + PA_COMMAND_SET_SOURCE_MUTE, PA_COMMAND_CORK_PLAYBACK_STREAM, PA_COMMAND_FLUSH_PLAYBACK_STREAM, diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index dce6b346a..52eaed4f1 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -161,6 +161,7 @@ static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t t static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_set_mute(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_flush_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_trigger_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); @@ -220,6 +221,9 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume, [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume, + [PA_COMMAND_SET_SINK_MUTE] = command_set_mute, + [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute, + [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream, [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_playback_stream, [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream, @@ -1184,6 +1188,7 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { PA_TAG_CHANNEL_MAP, &sink->channel_map, PA_TAG_U32, sink->owner ? sink->owner->index : PA_INVALID_INDEX, PA_TAG_CVOLUME, pa_sink_get_volume(sink, PA_MIXER_HARDWARE), + PA_TAG_BOOLEAN, pa_sink_get_mute(sink, PA_MIXER_HARDWARE), PA_TAG_U32, sink->monitor_source->index, PA_TAG_STRING, sink->monitor_source->name, PA_TAG_USEC, pa_sink_get_latency(sink), @@ -1202,6 +1207,7 @@ static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { PA_TAG_CHANNEL_MAP, &source->channel_map, PA_TAG_U32, source->owner ? source->owner->index : PA_INVALID_INDEX, PA_TAG_CVOLUME, pa_source_get_volume(source, PA_MIXER_HARDWARE), + PA_TAG_BOOLEAN, pa_source_get_mute(source, PA_MIXER_HARDWARE), PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX, PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL, PA_TAG_USEC, pa_source_get_latency(source), @@ -1530,6 +1536,55 @@ static void command_set_volume( pa_pstream_send_simple_ack(c->pstream, tag); } +static void command_set_mute( + PA_GCC_UNUSED pa_pdispatch *pd, + uint32_t command, + uint32_t tag, + pa_tagstruct *t, + void *userdata) { + + struct connection *c = userdata; + uint32_t idx; + int mute; + pa_sink *sink = NULL; + pa_source *source = NULL; + const char *name = NULL; + assert(c && t); + + if (pa_tagstruct_getu32(t, &idx) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_get_boolean(t, &mute) || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || *name, tag, PA_ERR_INVALID); + + if (command == PA_COMMAND_SET_SINK_MUTE) { + if (idx != PA_INVALID_INDEX) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); + else + sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); + } else { + assert(command == PA_COMMAND_SET_SOURCE_MUTE); + if (idx != (uint32_t) -1) + source = pa_idxset_get_by_index(c->protocol->core->sources, idx); + else + source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); + } + + CHECK_VALIDITY(c->pstream, sink || source, tag, PA_ERR_NOENTITY); + + if (sink) + pa_sink_set_mute(sink, PA_MIXER_HARDWARE, mute); + else if (source) + pa_source_set_mute(source, PA_MIXER_HARDWARE, mute); + + pa_pstream_send_simple_ack(c->pstream, tag); +} + static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t idx; diff --git a/src/polypcore/sample-util.c b/src/polypcore/sample-util.c index 2c3fbd790..7afb9d11b 100644 --- a/src/polypcore/sample-util.c +++ b/src/polypcore/sample-util.c @@ -85,7 +85,8 @@ size_t pa_mix( void *data, size_t length, const pa_sample_spec *spec, - const pa_cvolume *volume) { + const pa_cvolume *volume, + int mute) { assert(streams && data && length && spec); @@ -100,7 +101,7 @@ size_t pa_mix( if (d >= length) return d; - if (volume->values[channel] != PA_VOLUME_MUTED) { + if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; for (i = 0; i < nstreams; i++) { @@ -152,7 +153,7 @@ size_t pa_mix( if (d >= length) return d; - if (volume->values[channel] != PA_VOLUME_MUTED) { + if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; for (i = 0; i < nstreams; i++) { @@ -204,7 +205,7 @@ size_t pa_mix( if (d >= length) return d; - if (volume->values[channel] != PA_VOLUME_MUTED) { + if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; for (i = 0; i < nstreams; i++) { diff --git a/src/polypcore/sample-util.h b/src/polypcore/sample-util.h index 7ea01a30b..da7f56e15 100644 --- a/src/polypcore/sample-util.h +++ b/src/polypcore/sample-util.h @@ -44,7 +44,8 @@ size_t pa_mix( void *data, size_t length, const pa_sample_spec *spec, - const pa_cvolume *volume); + const pa_cvolume *volume, + int mute); void pa_volume_memchunk( pa_memchunk*c, diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index cb072c35c..17294059a 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -84,11 +84,15 @@ pa_sink* pa_sink_new( pa_cvolume_reset(&s->sw_volume, spec->channels); pa_cvolume_reset(&s->hw_volume, spec->channels); + s->sw_muted = 0; + s->hw_muted = 0; s->get_latency = NULL; s->notify = NULL; s->set_hw_volume = NULL; s->get_hw_volume = NULL; + s->set_hw_mute = NULL; + s->get_hw_mute = NULL; s->userdata = NULL; r = pa_idxset_put(core->sinks, s, &s->index); @@ -131,6 +135,8 @@ void pa_sink_disconnect(pa_sink* s) { s->notify = NULL; s->get_hw_volume = NULL; s->set_hw_volume = NULL; + s->set_hw_mute = NULL; + s->get_hw_mute = NULL; s->state = PA_SINK_DISCONNECTED; pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); @@ -262,9 +268,12 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); - if (!pa_cvolume_is_norm(&volume)) { + if (s->sw_muted || !pa_cvolume_is_norm(&volume)) { pa_memchunk_make_writable(result, s->core->memblock_stat, 0); - pa_volume_memchunk(result, &s->sample_spec, &volume); + if (s->sw_muted) + pa_silence_memchunk(result, &s->sample_spec); + else + pa_volume_memchunk(result, &s->sample_spec, &volume); } } else { result->memblock = pa_memblock_new(length, s->core->memblock_stat); @@ -272,7 +281,8 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { /* pa_log("mixing %i", n); */ - result->length = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, &s->sw_volume); + result->length = pa_mix(info, n, result->memblock->data, length, + &s->sample_spec, &s->sw_volume, s->sw_muted); result->index = 0; } @@ -317,15 +327,18 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { target->length); pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); - - if (!pa_cvolume_is_norm(&volume)) + + if (s->sw_muted) + pa_silence_memchunk(target, &s->sample_spec); + else if (!pa_cvolume_is_norm(&volume)) pa_volume_memchunk(target, &s->sample_spec, &volume); } else target->length = pa_mix(info, n, (uint8_t*) target->memblock->data + target->index, target->length, &s->sample_spec, - &s->sw_volume); + &s->sw_volume, + s->sw_muted); inputs_drop(s, info, n, target->length); pa_source_post(s->monitor_source, target); @@ -446,3 +459,40 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_mixer_t m) { } else return &s->sw_volume; } + +void pa_sink_set_mute(pa_sink *s, pa_mixer_t m, int mute) { + int *t; + + assert(s); + assert(s->ref >= 1); + + if (m == PA_MIXER_HARDWARE && s->set_hw_mute) + t = &s->hw_muted; + else + t = &s->sw_muted; + + if (!!*t == !!mute) + return; + + *t = !!mute; + + if (t == &s->hw_muted) + if (s->set_hw_mute(s) < 0) + s->sw_muted = !!mute; + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); +} + +int pa_sink_get_mute(pa_sink *s, pa_mixer_t m) { + assert(s); + assert(s->ref >= 1); + + if (m == PA_MIXER_HARDWARE && s->set_hw_mute) { + + if (s->get_hw_mute) + s->get_hw_mute(s); + + return s->hw_muted; + } else + return s->sw_muted; +} diff --git a/src/polypcore/sink.h b/src/polypcore/sink.h index 5f1a6cc85..59d455972 100644 --- a/src/polypcore/sink.h +++ b/src/polypcore/sink.h @@ -58,11 +58,14 @@ struct pa_sink { pa_source *monitor_source; pa_cvolume hw_volume, sw_volume; + int hw_muted, sw_muted; void (*notify)(pa_sink*sink); pa_usec_t (*get_latency)(pa_sink *s); int (*set_hw_volume)(pa_sink *s); int (*get_hw_volume)(pa_sink *s); + int (*set_hw_mute)(pa_sink *s); + int (*get_hw_mute)(pa_sink *s); void *userdata; }; @@ -92,5 +95,7 @@ void pa_sink_set_owner(pa_sink *sink, pa_module *m); void pa_sink_set_volume(pa_sink *sink, pa_mixer_t m, const pa_cvolume *volume); const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_mixer_t m); +void pa_sink_set_mute(pa_sink *sink, pa_mixer_t m, int mute); +int pa_sink_get_mute(pa_sink *sink, pa_mixer_t m); #endif diff --git a/src/polypcore/source.c b/src/polypcore/source.c index e97c31d8a..9e9415b63 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -80,11 +80,15 @@ pa_source* pa_source_new( pa_cvolume_reset(&s->sw_volume, spec->channels); pa_cvolume_reset(&s->hw_volume, spec->channels); + s->sw_muted = 0; + s->hw_muted = 0; s->get_latency = NULL; s->notify = NULL; s->set_hw_volume = NULL; s->get_hw_volume = NULL; + s->set_hw_mute = NULL; + s->get_hw_mute = NULL; s->userdata = NULL; r = pa_idxset_put(core->sources, s, &s->index); @@ -118,6 +122,8 @@ void pa_source_disconnect(pa_source *s) { s->notify = NULL; s->get_hw_volume = NULL; s->set_hw_volume = NULL; + s->set_hw_mute = NULL; + s->get_hw_mute = NULL; s->state = PA_SOURCE_DISCONNECTED; pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); @@ -182,12 +188,15 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) { pa_source_ref(s); - if (!pa_cvolume_is_norm(&s->sw_volume)) { + if (s->sw_muted || !pa_cvolume_is_norm(&s->sw_volume)) { pa_memchunk vchunk = *chunk; pa_memblock_ref(vchunk.memblock); pa_memchunk_make_writable(&vchunk, s->core->memblock_stat, 0); - pa_volume_memchunk(&vchunk, &s->sample_spec, &s->sw_volume); + if (s->sw_muted) + pa_silence_memchunk(&vchunk, &s->sample_spec); + else + pa_volume_memchunk(&vchunk, &s->sample_spec, &s->sw_volume); pa_idxset_foreach(s->outputs, do_post, &vchunk); pa_memblock_unref(vchunk.memblock); } else @@ -250,3 +259,40 @@ const pa_cvolume *pa_source_get_volume(pa_source *s, pa_mixer_t m) { } else return &s->sw_volume; } + +void pa_source_set_mute(pa_source *s, pa_mixer_t m, int mute) { + int *t; + + assert(s); + assert(s->ref >= 1); + + if (m == PA_MIXER_HARDWARE && s->set_hw_mute) + t = &s->hw_muted; + else + t = &s->sw_muted; + + if (!!*t == !!mute) + return; + + *t = !!mute; + + if (t == &s->hw_muted) + if (s->set_hw_mute(s) < 0) + s->sw_muted = !!mute; + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); +} + +int pa_source_get_mute(pa_source *s, pa_mixer_t m) { + assert(s); + assert(s->ref >= 1); + + if (m == PA_MIXER_HARDWARE && s->set_hw_mute) { + + if (s->get_hw_mute) + s->get_hw_mute(s); + + return s->hw_muted; + } else + return s->sw_muted; +} diff --git a/src/polypcore/source.h b/src/polypcore/source.h index 3c5bb6c4f..63b77624b 100644 --- a/src/polypcore/source.h +++ b/src/polypcore/source.h @@ -60,11 +60,14 @@ struct pa_source { pa_sink *monitor_of; pa_cvolume hw_volume, sw_volume; + int hw_muted, sw_muted; void (*notify)(pa_source*source); pa_usec_t (*get_latency)(pa_source *s); int (*set_hw_volume)(pa_source *s); int (*get_hw_volume)(pa_source *s); + int (*set_hw_mute)(pa_source *s); + int (*get_hw_mute)(pa_source *s); void *userdata; }; @@ -92,5 +95,7 @@ pa_usec_t pa_source_get_latency(pa_source *s); void pa_source_set_volume(pa_source *source, pa_mixer_t m, const pa_cvolume *volume); const pa_cvolume *pa_source_get_volume(pa_source *source, pa_mixer_t m); +void pa_source_set_mute(pa_source *source, pa_mixer_t m, int mute); +int pa_source_get_mute(pa_source *source, pa_mixer_t m); #endif From 65736a2651c6c182fbd6c9dcf7aa948291360534 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 23 Feb 2006 12:06:00 +0000 Subject: [PATCH 0495/1514] Some new additions were mislabeled as '\since 0.9'. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@588 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/introspect.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/polyp/introspect.h b/src/polyp/introspect.h index 4ef776f8a..f1f0989ca 100644 --- a/src/polyp/introspect.h +++ b/src/polyp/introspect.h @@ -55,14 +55,14 @@ typedef struct pa_sink_info { uint32_t index; /**< Index of the sink */ const char *description; /**< Description of this sink */ pa_sample_spec sample_spec; /**< Sample spec of this sink */ - pa_channel_map channel_map; /**< Channel map \since 0.9 */ + pa_channel_map channel_map; /**< Channel map \since 0.8 */ uint32_t owner_module; /**< Index of the owning module of this sink, or PA_INVALID_INDEX */ pa_cvolume volume; /**< Volume of the sink */ int mute; /**< Mute switch of the sink \since 0.8 */ uint32_t monitor_source; /**< Index of the monitor source connected to this sink */ const char *monitor_source_name; /**< The name of the monitor source */ pa_usec_t latency; /**< Length of filled playback buffer of this sink */ - const char *driver; /**< Driver name. \since 0.9 */ + const char *driver; /**< Driver name. \since 0.8 */ } pa_sink_info; /** Callback prototype for pa_context_get_sink_info_by_name() and friends */ @@ -83,14 +83,14 @@ typedef struct pa_source_info { uint32_t index; /**< Index of the source */ const char *description; /**< Description of this source */ pa_sample_spec sample_spec; /**< Sample spec of this source */ - pa_channel_map channel_map; /**< Channel map \since 0.9 */ + pa_channel_map channel_map; /**< Channel map \since 0.8 */ uint32_t owner_module; /**< Owning module index, or PA_INVALID_INDEX */ pa_cvolume volume; /**< Volume of the source \since 0.8 */ int mute; /**< Mute switch of the sink \since 0.8 */ uint32_t monitor_of_sink; /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */ const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */ pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */ - const char *driver; /**< Driver name \since 0.9 */ + const char *driver; /**< Driver name \since 0.8 */ } pa_source_info; /** Callback prototype for pa_context_get_source_info_by_name() and friends */ @@ -146,7 +146,7 @@ typedef struct pa_client_info { uint32_t index; /**< Index of this client */ const char *name; /**< Name of this client */ uint32_t owner_module; /**< Index of the owning module, or PA_INVALID_INDEX */ - const char *driver; /**< Driver name \since 0.9 */ + const char *driver; /**< Driver name \since 0.8 */ } pa_client_info; /** Callback prototype for pa_context_get_client_info() and firends*/ @@ -171,7 +171,7 @@ typedef struct pa_sink_input_info { pa_usec_t buffer_usec; /**< Latency due to buffering in sink input, see pa_latency_info for details */ pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */ const char *resample_method; /**< Thre resampling method used by this sink input. \since 0.7 */ - const char *driver; /**< Driver name \since 0.9 */ + const char *driver; /**< Driver name \since 0.8 */ } pa_sink_input_info; /** Callback prototype for pa_context_get_sink_input_info() and firends*/ @@ -195,7 +195,7 @@ typedef struct pa_source_output_info { pa_usec_t buffer_usec; /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */ pa_usec_t source_usec; /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */ const char *resample_method; /**< Thre resampling method used by this source output. \since 0.7 */ - const char *driver; /**< Driver name \since 0.9 */ + const char *driver; /**< Driver name \since 0.8 */ } pa_source_output_info; /** Callback prototype for pa_context_get_source_output_info() and firends*/ From c2304d6872b1a60d5a1d6a2a58493ce5272729dd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Feb 2006 00:49:21 +0000 Subject: [PATCH 0496/1514] add a few more validity checks to protocol-esound git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@589 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 42 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index aa46e2b94..3ef1cd044 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -260,6 +260,13 @@ static int format_native2esd(pa_sample_spec *ss) { return format; } +#define CHECK_VALIDITY(expression, string) do { \ + if (!(expression)) { \ + pa_log_warn(__FILE__ ": " string); \ + return -1; \ + } \ +} while(0); + /*** esound commands ***/ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { @@ -310,16 +317,10 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); - if (!pa_sample_spec_valid(&ss)) { - pa_log(__FILE__": invalid sample specification"); - return -1; - } + CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification"); + sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1); + CHECK_VALIDITY(sink, "No such sink"); - if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": no such sink"); - return -1; - } - strncpy(name, (const char*) data + sizeof(int)*2, sizeof(name)); name[sizeof(name)-1] = 0; @@ -327,10 +328,9 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t assert(!c->sink_input && !c->input_memblockq); - if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, name, &ss, NULL, 0, -1))) { - pa_log(__FILE__": failed to create sink input."); - return -1; - } + c->sink_input = pa_sink_input_new(sink, __FILE__, name, &ss, NULL, 0, -1); + + CHECK_VALIDITY(c->sink_input, "Failed to create sink input."); l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); c->input_memblockq = pa_memblockq_new( @@ -374,10 +374,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); - if (!pa_sample_spec_valid(&ss)) { - pa_log(__FILE__": invalid sample specification."); - return -1; - } + CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification."); if (request == ESD_PROTO_STREAM_MON) { pa_sink* sink; @@ -631,10 +628,11 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); + CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification."); + sc_length = (size_t) MAYBE_INT32_SWAP(c->swap_byte_order, (*((const int*)data + 2))); - if (sc_length >= MAX_CACHE_SAMPLE_SIZE) - return -1; + CHECK_VALIDITY(sc_length <= MAX_CACHE_SAMPLE_SIZE, "Sample too large."); strcpy(name, SCACHE_PREFIX); strncpy(name+sizeof(SCACHE_PREFIX)-1, (const char*) data+3*sizeof(int), ESD_NAME_MAX); @@ -792,7 +790,7 @@ static int do_read(struct connection *c) { return -1; } - if ((c->read_data_length+= r) >= handler->data_length) { + if ((c->read_data_length += r) >= handler->data_length) { size_t l = c->read_data_length; assert(handler->proc); @@ -1077,7 +1075,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) return; } - c = pa_xmalloc(sizeof(struct connection)); + c = pa_xnew(struct connection, 1); c->protocol = p; c->io = io; pa_iochannel_set_callback(c->io, io_callback, c); @@ -1139,7 +1137,7 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve int public = 0; assert(core && server && ma); - p = pa_xmalloc(sizeof(pa_protocol_esound)); + p = pa_xnew(pa_protocol_esound, 1); if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { pa_log(__FILE__": public= expects a boolean argument."); From 903b8c093b37f1a016aa4cbcc6cb86f72ba7993d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Feb 2006 00:49:39 +0000 Subject: [PATCH 0497/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@590 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 3c478e500..dd3bc87bc 100644 --- a/doc/todo +++ b/doc/todo @@ -5,7 +5,6 @@ Test: - module-tunnel Fixes: -- better validity checking in protocol-esound - proper use of memcpy in procotol-esound.c so we don't get alignment problems - latency api rework for native protocol - add support for auth using SCM_CREDENTIALS From b967aeb44a44b7f758541d5374c0e34460378027 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Feb 2006 01:07:55 +0000 Subject: [PATCH 0498/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@591 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/todo b/doc/todo index dd3bc87bc..354e66bdc 100644 --- a/doc/todo +++ b/doc/todo @@ -18,7 +18,6 @@ Fixes: - volume control - add hw driver name to sink/source description - deal with underflows properly -- multiline configuration statements - module-tunnel volume support (sink, source, notify) Post 0.8: @@ -30,6 +29,7 @@ Post 0.8: - add threading API - module-tunnel: improve latency calculation - port from howl to avahi +- multiline configuration statements Long term: - pass meta info for hearing impaired From 3374df571d281caffcfa304fb27b2e49c8e509c8 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 09:12:15 +0000 Subject: [PATCH 0499/1514] IGAIN is a better choice than IMIX for source volume. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@592 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss-mmap.c | 4 ++-- src/modules/module-oss.c | 4 ++-- src/modules/oss-util.c | 8 ++++---- src/modules/oss-util.h | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index e1e54fb58..0ed2af938 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -248,7 +248,7 @@ static int sink_set_hw_volume(pa_sink *s) { static int source_get_hw_volume(pa_source *s) { struct userdata *u = s->userdata; - if (pa_oss_get_imix_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); s->get_hw_volume = NULL; return -1; @@ -260,7 +260,7 @@ static int source_get_hw_volume(pa_source *s) { static int source_set_hw_volume(pa_source *s) { struct userdata *u = s->userdata; - if (pa_oss_set_imix_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); s->set_hw_volume = NULL; return -1; diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 3a3f6b88e..524275921 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -280,7 +280,7 @@ static int sink_set_hw_volume(pa_sink *s) { static int source_get_hw_volume(pa_source *s) { struct userdata *u = s->userdata; - if (pa_oss_get_imix_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); s->get_hw_volume = NULL; return -1; @@ -292,7 +292,7 @@ static int source_get_hw_volume(pa_source *s) { static int source_set_hw_volume(pa_source *s) { struct userdata *u = s->userdata; - if (pa_oss_set_imix_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { + if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); s->set_hw_volume = NULL; return -1; diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 30a4b9980..958bd547d 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -211,12 +211,12 @@ int pa_oss_set_pcm_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *vo return pa_oss_set_volume(fd, SOUND_MIXER_WRITE_PCM, ss, volume); } -int pa_oss_get_imix_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { - return pa_oss_get_volume(fd, SOUND_MIXER_READ_IMIX, ss, volume); +int pa_oss_get_input_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { + return pa_oss_get_volume(fd, SOUND_MIXER_READ_IGAIN, ss, volume); } -int pa_oss_set_imix_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume) { - return pa_oss_set_volume(fd, SOUND_MIXER_WRITE_IMIX, ss, volume); +int pa_oss_set_input_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume) { + return pa_oss_set_volume(fd, SOUND_MIXER_WRITE_IGAIN, ss, volume); } int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { diff --git a/src/modules/oss-util.h b/src/modules/oss-util.h index dd494d0cc..c652d2a10 100644 --- a/src/modules/oss-util.h +++ b/src/modules/oss-util.h @@ -33,8 +33,8 @@ int pa_oss_set_fragments(int fd, int frags, int frag_size); int pa_oss_get_pcm_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume); int pa_oss_set_pcm_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume); -int pa_oss_get_imix_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume); -int pa_oss_set_imix_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume); +int pa_oss_get_input_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume); +int pa_oss_set_input_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume); int pa_oss_get_hw_description(const char *dev, char *name, size_t l); From 9366ab9dc9acd687dc41e492d07413d36ba2f3ed Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 10:17:41 +0000 Subject: [PATCH 0500/1514] Hardware sink mute support. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@593 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index a74a70c23..9015cfd28 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -292,6 +292,35 @@ static int sink_set_hw_volume_cb(pa_sink *s) { return 0; } +static int sink_get_hw_mute_cb(pa_sink *s) { + struct userdata *u = s->userdata; + audio_info_t info; + int err; + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + s->hw_muted = !!info.output_muted; + + return 0; +} + +static int sink_set_hw_mute_cb(pa_sink *s) { + struct userdata *u = s->userdata; + audio_info_t info; + + AUDIO_INITINFO(&info); + + info.output_muted = !!s->hw_muted; + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { + pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + return -1; + } + + return 0; +} + static int source_get_hw_volume_cb(pa_source *s) { struct userdata *u = s->userdata; audio_info_t info; @@ -483,6 +512,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_latency = sink_get_latency_cb; u->sink->get_hw_volume = sink_get_hw_volume_cb; u->sink->set_hw_volume = sink_set_hw_volume_cb; + u->sink->get_hw_mute = sink_get_hw_mute_cb; + u->sink->set_hw_mute = sink_set_hw_mute_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); @@ -521,8 +552,10 @@ int pa__init(pa_core *c, pa_module*m) { /* Read mixer settings */ if (u->source) sink_get_hw_volume_cb(u->source); - if (u->sink) + if (u->sink) { sink_get_hw_volume_cb(u->sink); + sink_get_hw_mute_cb(u->sink); + } return 0; From c205ea6ebe1b373fe6b84ee189528809e9fefc90 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 10:18:24 +0000 Subject: [PATCH 0501/1514] Make local function static. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@594 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 9015cfd28..55ef1cd1f 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -217,7 +217,7 @@ static void io_callback(pa_iochannel *io, void*userdata) { do_read(u); } -void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { +static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { struct userdata *u = userdata; assert(u); do_write(u); From a1f5573313e888d39dbe4015bdd993ad9eccb92f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 10:18:53 +0000 Subject: [PATCH 0502/1514] Call correct function. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@595 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 55ef1cd1f..94fa6d8c5 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -551,7 +551,7 @@ int pa__init(pa_core *c, pa_module*m) { /* Read mixer settings */ if (u->source) - sink_get_hw_volume_cb(u->source); + source_get_hw_volume_cb(u->source); if (u->sink) { sink_get_hw_volume_cb(u->sink); sink_get_hw_mute_cb(u->sink); From 3f264b2c4acfaaf8dd9c6b05526708a1d7648db0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Feb 2006 15:12:42 +0000 Subject: [PATCH 0503/1514] add support for authentication using SCM_CREDENTIALS git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@596 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 4 +- src/polyp/context.c | 6 +- src/polyp/subscribe.c | 6 +- src/polypcore/iochannel.c | 130 ++++++++++++++++++++++++++++++ src/polypcore/iochannel.h | 11 +++ src/polypcore/pdispatch.c | 21 ++++- src/polypcore/pdispatch.h | 6 +- src/polypcore/protocol-native.c | 93 ++++++++++++++-------- src/polypcore/pstream-util.c | 4 +- src/polypcore/pstream-util.h | 4 +- src/polypcore/pstream.c | 136 +++++++++++++++++++++++--------- src/polypcore/pstream.h | 14 ++-- 12 files changed, 343 insertions(+), 92 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index df9c51fbc..70bded6c3 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -431,11 +431,11 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void*creds, void *userdata) { struct userdata *u = userdata; assert(p && packet && u); - if (pa_pdispatch_run(u->pdispatch, packet, u) < 0) { + if (pa_pdispatch_run(u->pdispatch, packet, creds, u) < 0) { pa_log(__FILE__": invalid packet"); die(u); } diff --git a/src/polyp/context.c b/src/polyp/context.c index 8e9992257..59079cb07 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -267,7 +267,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata) { pa_context *c = userdata; assert(p); @@ -276,7 +276,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *user pa_context_ref(c); - if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) + if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) pa_context_fail(c, PA_ERR_PROTOCOL); pa_context_unref(c); @@ -401,7 +401,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) { t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); - pa_pstream_send_tagstruct(c->pstream, t); + pa_pstream_send_tagstruct_with_creds(c->pstream, t, 1); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); diff --git a/src/polyp/subscribe.c b/src/polyp/subscribe.c index a4eadbc67..110d4e52a 100644 --- a/src/polyp/subscribe.c +++ b/src/polyp/subscribe.c @@ -36,7 +36,7 @@ void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; pa_subscription_event_type_t e; - uint32_t index; + uint32_t idx; assert(pd); assert(command == PA_COMMAND_SUBSCRIBE_EVENT); @@ -46,14 +46,14 @@ void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSE pa_context_ref(c); if (pa_tagstruct_getu32(t, &e) < 0 || - pa_tagstruct_getu32(t, &index) < 0 || + pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(c, PA_ERR_PROTOCOL); goto finish; } if (c->subscribe_callback) - c->subscribe_callback(c, e, index, c->subscribe_userdata); + c->subscribe_callback(c, e, idx, c->subscribe_userdata); finish: pa_context_unref(c); diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index 89b061c27..ea0ac9882 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -27,12 +27,14 @@ #include #include #include +#include #include "winsock.h" #include #include #include +#include #include "iochannel.h" @@ -242,6 +244,134 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { return r; } +#ifdef SCM_CREDENTIALS + +int pa_iochannel_creds_supported(pa_iochannel *io) { + struct sockaddr_un sa; + socklen_t l; + + assert(io); + assert(io->ifd >= 0); + assert(io->ofd == io->ifd); + + l = sizeof(sa); + + if (getsockname(io->ifd, (struct sockaddr*) &sa, &l) < 0) + return 0; + + return sa.sun_family == AF_UNIX; +} + +int pa_iochannel_creds_enable(pa_iochannel *io) { + int t = 1; + + assert(io); + assert(io->ifd >= 0); + + if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) { + pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", strerror(errno)); + return -1; + } + + return 0; +} + +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l) { + ssize_t r; + struct msghdr mh; + struct iovec iov; + uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))]; + struct ucred *ucred; + struct cmsghdr *cmsg; + + assert(io); + assert(data); + assert(l); + assert(io->ofd >= 0); + + memset(&iov, 0, sizeof(iov)); + iov.iov_base = (void*) data; + iov.iov_len = l; + + memset(cmsg_data, 0, sizeof(cmsg_data)); + cmsg = (struct cmsghdr*) cmsg_data; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + + ucred = (struct ucred*) CMSG_DATA(cmsg); + ucred->pid = getpid(); + ucred->uid = getuid(); + ucred->gid = getgid(); + + memset(&mh, 0, sizeof(mh)); + mh.msg_name = NULL; + mh.msg_namelen = 0; + mh.msg_iov = &iov; + mh.msg_iovlen = 1; + mh.msg_control = cmsg_data; + mh.msg_controllen = sizeof(cmsg_data); + mh.msg_flags = 0; + + if ((r = sendmsg(io->ofd, &mh, MSG_NOSIGNAL)) >= 0) { + io->writable = 0; + enable_mainloop_sources(io); + } + + return r; +} + +ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid) { + ssize_t r; + struct msghdr mh; + struct iovec iov; + uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))]; + + assert(io); + assert(data); + assert(l); + assert(io->ifd >= 0); + assert(ucred); + assert(creds_valid); + + memset(&iov, 0, sizeof(iov)); + iov.iov_base = data; + iov.iov_len = l; + + memset(cmsg_data, 0, sizeof(cmsg_data)); + + memset(&mh, 0, sizeof(mh)); + mh.msg_name = NULL; + mh.msg_namelen = 0; + mh.msg_iov = &iov; + mh.msg_iovlen = 1; + mh.msg_control = cmsg_data; + mh.msg_controllen = sizeof(cmsg_data); + mh.msg_flags = 0; + + if ((r = recvmsg(io->ifd, &mh, MSG_NOSIGNAL)) >= 0) { + struct cmsghdr *cmsg; + + *creds_valid = 0; + + for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { + + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { + assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))); + memcpy(ucred, CMSG_DATA(cmsg), sizeof(struct ucred)); + *creds_valid = 1; + break; + } + } + + io->readable = 0; + enable_mainloop_sources(io); + } + + return r; +} +#endif + void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) { assert(io); diff --git a/src/polypcore/iochannel.h b/src/polypcore/iochannel.h index 977fe2c36..617ce0863 100644 --- a/src/polypcore/iochannel.h +++ b/src/polypcore/iochannel.h @@ -23,6 +23,9 @@ ***/ #include +#include +#include + #include /* A wrapper around UNIX file descriptors for attaching them to the a @@ -48,6 +51,14 @@ void pa_iochannel_free(pa_iochannel*io); ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l); ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l); +#ifdef SCM_CREDENTIALS +int pa_iochannel_creds_supported(pa_iochannel *io); +int pa_iochannel_creds_enable(pa_iochannel *io); + +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l); +ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid); +#endif + int pa_iochannel_is_readable(pa_iochannel*io); int pa_iochannel_is_writable(pa_iochannel*io); int pa_iochannel_is_hungup(pa_iochannel*io); diff --git a/src/polypcore/pdispatch.c b/src/polypcore/pdispatch.c index 56a21bd6b..a4e58f8c4 100644 --- a/src/polypcore/pdispatch.c +++ b/src/polypcore/pdispatch.c @@ -109,6 +109,7 @@ struct pa_pdispatch { PA_LLIST_HEAD(struct reply_info, replies); pa_pdispatch_drain_callback drain_callback; void *drain_userdata; + const void *creds; }; static void reply_info_free(struct reply_info *r) { @@ -136,7 +137,8 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_ PA_LLIST_HEAD_INIT(pa_reply_info, pd->replies); pd->drain_callback = NULL; pd->drain_userdata = NULL; - + pd->creds = NULL; + return pd; } @@ -171,7 +173,7 @@ static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command, pa_pdispatch_unref(pd); } -int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, void *userdata) { +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const void *creds, void *userdata) { uint32_t tag, command; pa_tagstruct *ts = NULL; int ret = -1; @@ -188,18 +190,20 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, void *userdata) { if (pa_tagstruct_getu32(ts, &command) < 0 || pa_tagstruct_getu32(ts, &tag) < 0) goto finish; - + #ifdef DEBUG_OPCODES { char t[256]; char const *p; if (!(p = command_names[command])) snprintf((char*) (p = t), sizeof(t), "%u", command); - + pa_log(__FILE__": Recieved opcode <%s>", p); } #endif + pd->creds = creds; + if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) { struct reply_info *r; @@ -222,6 +226,8 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, void *userdata) { ret = 0; finish: + pd->creds = NULL; + if (ts) pa_tagstruct_free(ts); @@ -295,3 +301,10 @@ pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd) { pd->ref++; return pd; } + +const void * pa_pdispatch_creds(pa_pdispatch *pd) { + assert(pd); + assert(pd->ref >= 1); + + return pd->creds; +} diff --git a/src/polypcore/pdispatch.h b/src/polypcore/pdispatch.h index 31533d57f..aa898abfa 100644 --- a/src/polypcore/pdispatch.h +++ b/src/polypcore/pdispatch.h @@ -30,21 +30,23 @@ typedef struct pa_pdispatch pa_pdispatch; typedef void (*pa_pdispatch_cb_t)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +typedef void (*pa_pdispatch_drain_callback)(pa_pdispatch *pd, void *userdata); pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_cb_t*table, unsigned entries); void pa_pdispatch_unref(pa_pdispatch *pd); pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); -int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, void *userdata); +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const void*creds, void *userdata); void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t callback, void *userdata); int pa_pdispatch_is_pending(pa_pdispatch *pd); -typedef void (*pa_pdispatch_drain_callback)(pa_pdispatch *pd, void *userdata); void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, pa_pdispatch_drain_callback callback, void *userdata); /* Remove all reply slots with the give userdata parameter */ void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata); +const void * pa_pdispatch_creds(pa_pdispatch *pd); + #endif diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 52eaed4f1..0fb9339bf 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -357,7 +358,7 @@ static struct playback_stream* playback_stream_new( pa_cvolume *volume, uint32_t syncid) { - struct playback_stream *s, *sync; + struct playback_stream *s, *ssync; pa_sink_input *sink_input; pa_memblock *silence; uint32_t idx; @@ -366,17 +367,17 @@ static struct playback_stream* playback_stream_new( assert(c && sink && ss && name && maxlength); /* Find syncid group */ - for (sync = pa_idxset_first(c->output_streams, &idx); sync; sync = pa_idxset_next(c->output_streams, &idx)) { + for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) { - if (sync->type != PLAYBACK_STREAM) + if (ssync->type != PLAYBACK_STREAM) continue; - if (sync->syncid == syncid) + if (ssync->syncid == syncid) break; } /* Synced streams must connect to the same sink */ - if (sync && sync->sink_input->sink != sink) + if (ssync && ssync->sink_input->sink != sink) return NULL; if (!(sink_input = pa_sink_input_new(sink, __FILE__, name, ss, map, 0, -1))) @@ -397,16 +398,16 @@ static struct playback_stream* playback_stream_new( s->sink_input->owner = c->protocol->module; s->sink_input->client = c->client; - if (sync) { + if (ssync) { /* Sync id found, now find head of list */ - PA_LLIST_FIND_HEAD(struct playback_stream, sync, &sync); + PA_LLIST_FIND_HEAD(struct playback_stream, ssync, &ssync); /* Prepend ourselves */ - PA_LLIST_PREPEND(struct playback_stream, sync, s); + PA_LLIST_PREPEND(struct playback_stream, ssync, s); /* Set our start index to the current read index of the other grozp member(s) */ - assert(sync->next); - start_index = pa_memblockq_get_read_index(sync->next->memblockq); + assert(ssync->next); + start_index = pa_memblockq_get_read_index(ssync->next->memblockq); } else { /* This ia a new sync group */ PA_LLIST_INIT(struct playback_stream, s); @@ -871,8 +872,29 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t } if (!c->authorized) { - if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) { - pa_log(__FILE__": Denied access to client with invalid authorization key."); + int success = 0; + +#ifdef SCM_CREDENTIALS + const struct ucred *ucred = pa_pdispatch_creds(pd); + + if (ucred) { + if (ucred->uid == getuid()) + success = 1; + + pa_log_info(__FILE__": Got credentials: pid=%lu uid=%lu gid=%lu auth=%i", + (unsigned long) ucred->pid, + (unsigned long) ucred->uid, + (unsigned long) ucred->gid, + success); + + } +#endif + + if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) == 0) + success = 1; + + if (!success) { + pa_log_warn(__FILE__": Denied access to client with invalid authorization data."); pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -1589,7 +1611,7 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ struct connection *c = userdata; uint32_t idx; int b; - struct playback_stream *s, *sync; + struct playback_stream *s, *ssync; assert(c && t); if (pa_tagstruct_getu32(t, &idx) < 0 || @@ -1609,14 +1631,14 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_memblockq_prebuf_force(s->memblockq); /* Do the same for all other members in the sync group */ - for (sync = s->prev; sync; sync = sync->prev) { - pa_sink_input_cork(sync->sink_input, b); - pa_memblockq_prebuf_force(sync->memblockq); + for (ssync = s->prev; ssync; ssync = ssync->prev) { + pa_sink_input_cork(ssync->sink_input, b); + pa_memblockq_prebuf_force(ssync->memblockq); } - for (sync = s->next; sync; sync = sync->next) { - pa_sink_input_cork(sync->sink_input, b); - pa_memblockq_prebuf_force(sync->memblockq); + for (ssync = s->next; ssync; ssync = ssync->next) { + pa_sink_input_cork(ssync->sink_input, b); + pa_memblockq_prebuf_force(ssync->memblockq); } pa_pstream_send_simple_ack(c->pstream, tag); @@ -1625,7 +1647,7 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t idx; - struct playback_stream *s, *sync; + struct playback_stream *s, *ssync; assert(c && t); if (pa_tagstruct_getu32(t, &idx) < 0 || @@ -1644,25 +1666,25 @@ static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC s->underrun = 0; /* Do the same for all other members in the sync group */ - for (sync = s->prev; sync; sync = sync->prev) { - pa_memblockq_flush(sync->memblockq); - sync->underrun = 0; + for (ssync = s->prev; ssync; ssync = ssync->prev) { + pa_memblockq_flush(ssync->memblockq); + ssync->underrun = 0; } - for (sync = s->next; sync; sync = sync->next) { - pa_memblockq_flush(sync->memblockq); - sync->underrun = 0; + for (ssync = s->next; ssync; ssync = ssync->next) { + pa_memblockq_flush(ssync->memblockq); + ssync->underrun = 0; } pa_pstream_send_simple_ack(c->pstream, tag); pa_sink_notify(s->sink_input->sink); request_bytes(s); - for (sync = s->prev; sync; sync = sync->prev) - request_bytes(sync); + for (ssync = s->prev; ssync; ssync = ssync->prev) + request_bytes(ssync); - for (sync = s->next; sync; sync = sync->next) - request_bytes(sync); + for (ssync = s->next; ssync; ssync = ssync->next) + request_bytes(ssync); } static void command_trigger_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -2017,11 +2039,11 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC /*** pstream callbacks ***/ -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata) { struct connection *c = userdata; assert(p && packet && packet->data && c); - if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) { + if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) { pa_log(__FILE__": invalid packet."); connection_free(c); } @@ -2183,6 +2205,13 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo c->subscription = NULL; pa_idxset_put(p->connections, c, NULL); + + +#ifdef SCM_CREDENTIALS + if (pa_iochannel_creds_supported(io)) + pa_iochannel_creds_enable(io); + +#endif } /*** module entry points ***/ diff --git a/src/polypcore/pstream-util.c b/src/polypcore/pstream-util.c index 62986456e..bd1d1a87f 100644 --- a/src/polypcore/pstream-util.c +++ b/src/polypcore/pstream-util.c @@ -29,7 +29,7 @@ #include "pstream-util.h" -void pa_pstream_send_tagstruct(pa_pstream *p, pa_tagstruct *t) { +void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, int creds) { size_t length; uint8_t *data; pa_packet *packet; @@ -40,7 +40,7 @@ void pa_pstream_send_tagstruct(pa_pstream *p, pa_tagstruct *t) { assert(data && length); packet = pa_packet_new_dynamic(data, length); assert(packet); - pa_pstream_send_packet(p, packet); + pa_pstream_send_packet(p, packet, creds); pa_packet_unref(packet); } diff --git a/src/polypcore/pstream-util.h b/src/polypcore/pstream-util.h index c400c6d8a..f2677a440 100644 --- a/src/polypcore/pstream-util.h +++ b/src/polypcore/pstream-util.h @@ -27,7 +27,9 @@ #include /* The tagstruct is freed!*/ -void pa_pstream_send_tagstruct(pa_pstream *p, pa_tagstruct *t); +void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, int creds); + +#define pa_pstream_send_tagstruct(p, t) pa_pstream_send_tagstruct_with_creds((p), (t), 0) void pa_pstream_send_error(pa_pstream *p, uint32_t tag, uint32_t error); void pa_pstream_send_simple_ack(pa_pstream *p, uint32_t tag); diff --git a/src/polypcore/pstream.c b/src/polypcore/pstream.c index b1e8bd061..b93dca08c 100644 --- a/src/polypcore/pstream.c +++ b/src/polypcore/pstream.c @@ -65,6 +65,9 @@ struct item_info { /* packet info */ pa_packet *packet; +#ifdef SCM_CREDENTIALS + int with_creds; +#endif }; struct pa_pstream { @@ -76,8 +79,6 @@ struct pa_pstream { pa_queue *send_queue; int dead; - void (*die_callback) (pa_pstream *p, void *userdata); - void *die_callback_userdata; struct { struct item_info* current; @@ -94,16 +95,25 @@ struct pa_pstream { size_t index; } read; - void (*recieve_packet_callback) (pa_pstream *p, pa_packet *packet, void *userdata); + pa_pstream_packet_cb_t recieve_packet_callback; void *recieve_packet_callback_userdata; - void (*recieve_memblock_callback) (pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata); + pa_pstream_memblock_cb_t recieve_memblock_callback; void *recieve_memblock_callback_userdata; - void (*drain_callback)(pa_pstream *p, void *userdata); - void *drain_userdata; + pa_pstream_notify_cb_t drain_callback; + void *drain_callback_userdata; + + pa_pstream_notify_cb_t die_callback; + void *die_callback_userdata; pa_memblock_stat *memblock_stat; + +#ifdef SCM_CREDENTIALS + int send_creds_now; + struct ucred ucred; + int creds_valid; +#endif }; static int do_write(pa_pstream *p); @@ -170,8 +180,6 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta pa_iochannel_set_callback(io, io_callback, p); p->dead = 0; - p->die_callback = NULL; - p->die_callback_userdata = NULL; p->mainloop = m; p->defer_event = m->defer_new(m, defer_callback, p); @@ -194,13 +202,20 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta p->recieve_memblock_callback_userdata = NULL; p->drain_callback = NULL; - p->drain_userdata = NULL; + p->drain_callback_userdata = NULL; + + p->die_callback = NULL; + p->die_callback_userdata = NULL; p->memblock_stat = s; pa_iochannel_socket_set_rcvbuf(io, 1024*8); - pa_iochannel_socket_set_sndbuf(io, 1024*8); + pa_iochannel_socket_set_sndbuf(io, 1024*8); +#ifdef SCM_CREDENTIALS + p->send_creds_now = 0; + p->creds_valid = 0; +#endif return p; } @@ -239,7 +254,7 @@ static void pstream_free(pa_pstream *p) { pa_xfree(p); } -void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet) { +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, int with_creds) { struct item_info *i; assert(p && packet && p->ref >= 1); @@ -251,6 +266,9 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet) { i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); +#ifdef SCM_CREDENTIALS + i->with_creds = with_creds; +#endif pa_queue_push(p->send_queue, i); p->mainloop->defer_enable(p->defer_event, 1); @@ -278,20 +296,6 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa p->mainloop->defer_enable(p->defer_event, 1); } -void pa_pstream_set_recieve_packet_callback(pa_pstream *p, void (*callback) (pa_pstream *p, pa_packet *packet, void *userdata), void *userdata) { - assert(p && callback); - - p->recieve_packet_callback = callback; - p->recieve_packet_callback_userdata = userdata; -} - -void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, void (*callback) (pa_pstream *p, uint32_t channel, int64_t delta, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata), void *userdata) { - assert(p && callback); - - p->recieve_memblock_callback = callback; - p->recieve_memblock_callback_userdata = userdata; -} - static void prepare_next_write_item(pa_pstream *p) { assert(p); @@ -310,6 +314,11 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = 0; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = 0; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = 0; + +#ifdef SCM_CREDENTIALS + p->send_creds_now = 1; +#endif + } else { assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK && p->write.current->chunk.memblock); p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index; @@ -318,6 +327,10 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl((uint32_t) (((uint64_t) p->write.current->offset) >> 32)); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = htonl((uint32_t) ((uint64_t) p->write.current->offset)); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = htonl(p->write.current->seek_mode); + +#ifdef SCM_CREDENTIALS + p->send_creds_now = 1; +#endif } } @@ -343,6 +356,16 @@ static int do_write(pa_pstream *p) { l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } +#ifdef SCM_CREDENTIALS + if (p->send_creds_now) { + + if ((r = pa_iochannel_write_with_creds(p->io, d, l)) < 0) + return -1; + + p->send_creds_now = 0; + } else +#endif + if ((r = pa_iochannel_write(p->io, d, l)) < 0) return -1; @@ -354,7 +377,7 @@ static int do_write(pa_pstream *p) { p->write.current = NULL; if (p->drain_callback && !pa_pstream_is_pending(p)) - p->drain_callback(p, p->drain_userdata); + p->drain_callback(p, p->drain_callback_userdata); } return 0; @@ -375,8 +398,19 @@ static int do_read(pa_pstream *p) { l = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE); } +#ifdef SCM_CREDENTIALS + { + int b; + + if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->ucred, &b)) <= 0) + return -1; + + p->creds_valid = p->creds_valid || b; + } +#else if ((r = pa_iochannel_read(p->io, d, l)) <= 0) return -1; +#endif p->read.index += r; @@ -453,25 +487,59 @@ static int do_read(pa_pstream *p) { assert(p->read.packet); if (p->recieve_packet_callback) - p->recieve_packet_callback(p, p->read.packet, p->recieve_packet_callback_userdata); +#ifdef SCM_CREDENTIALS + p->recieve_packet_callback(p, p->read.packet, p->creds_valid ? &p->ucred : NULL, p->recieve_packet_callback_userdata); +#else + p->recieve_packet_callback(p, p->read.packet, NULL, p->recieve_packet_callback_userdata); +#endif pa_packet_unref(p->read.packet); p->read.packet = NULL; } p->read.index = 0; +#ifdef SCM_CREDENTIALS + p->creds_valid = 0; +#endif } } return 0; } -void pa_pstream_set_die_callback(pa_pstream *p, void (*callback)(pa_pstream *p, void *userdata), void *userdata) { - assert(p && callback); - p->die_callback = callback; +void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { + assert(p); + assert(p->ref >= 1); + + p->die_callback = cb; p->die_callback_userdata = userdata; } + +void pa_pstream_set_drain_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { + assert(p); + assert(p->ref >= 1); + + p->drain_callback = cb; + p->drain_callback_userdata = userdata; +} + +void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata) { + assert(p); + assert(p->ref >= 1); + + p->recieve_packet_callback = cb; + p->recieve_packet_callback_userdata = userdata; +} + +void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock_cb_t cb, void *userdata) { + assert(p); + assert(p->ref >= 1); + + p->recieve_memblock_callback = cb; + p->recieve_memblock_callback_userdata = userdata; +} + int pa_pstream_is_pending(pa_pstream *p) { assert(p); @@ -481,14 +549,6 @@ int pa_pstream_is_pending(pa_pstream *p) { return p->write.current || !pa_queue_is_empty(p->send_queue); } -void pa_pstream_set_drain_callback(pa_pstream *p, void (*cb)(pa_pstream *p, void *userdata), void *userdata) { - assert(p); - assert(p->ref >= 1); - - p->drain_callback = cb; - p->drain_userdata = userdata; -} - void pa_pstream_unref(pa_pstream*p) { assert(p); assert(p->ref >= 1); diff --git a/src/polypcore/pstream.h b/src/polypcore/pstream.h index 741ba9b53..feb1b1517 100644 --- a/src/polypcore/pstream.h +++ b/src/polypcore/pstream.h @@ -33,18 +33,22 @@ typedef struct pa_pstream pa_pstream; +typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata); +typedef void (*pa_pstream_memblock_cb_t)(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata); +typedef void (*pa_pstream_notify_cb_t)(pa_pstream *p, void *userdata); + pa_pstream* pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_stat *s); void pa_pstream_unref(pa_pstream*p); pa_pstream* pa_pstream_ref(pa_pstream*p); -void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet); +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, int with_creds); void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk); -void pa_pstream_set_recieve_packet_callback(pa_pstream *p, void (*callback) (pa_pstream *p, pa_packet *packet, void *userdata), void *userdata); -void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, void (*callback) (pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata), void *userdata); -void pa_pstream_set_drain_callback(pa_pstream *p, void (*cb)(pa_pstream *p, void *userdata), void *userdata); +void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata); +void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock_cb_t cb, void *userdata); +void pa_pstream_set_drain_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata); -void pa_pstream_set_die_callback(pa_pstream *p, void (*callback)(pa_pstream *p, void *userdata), void *userdata); +void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata); int pa_pstream_is_pending(pa_pstream *p); From 9f1b79368909a57a9de40f98dacd306e15bda3bc Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 16:27:39 +0000 Subject: [PATCH 0504/1514] Tweak the handling of missing credential support so that we minimise non-POSIX headers in our headers. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@597 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/iochannel.c | 29 ++++++++++++++++++++++++++++- src/polypcore/iochannel.h | 6 ++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index ea0ac9882..5da7a9a9f 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -29,6 +29,13 @@ #include #include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_UN_H +#include +#endif + #include "winsock.h" #include @@ -370,7 +377,27 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struc return r; } -#endif +#else /* SCM_CREDENTIALS */ + +int pa_iochannel_creds_supported(pa_iochannel *io) { + return 0; +} + +int pa_iochannel_creds_enable(pa_iochannel *io) { + return -1; +} + +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l) { + pa_log_error("pa_iochannel_write_with_creds() not supported."); + return -1; +} + +ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid) { + pa_log_error("pa_iochannel_read_with_creds() not supported."); + return -1; +} + +#endif /* SCM_CREDENTIALS */ void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) { assert(io); diff --git a/src/polypcore/iochannel.h b/src/polypcore/iochannel.h index 617ce0863..fe7cc0cea 100644 --- a/src/polypcore/iochannel.h +++ b/src/polypcore/iochannel.h @@ -23,8 +23,6 @@ ***/ #include -#include -#include #include @@ -51,13 +49,13 @@ void pa_iochannel_free(pa_iochannel*io); ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l); ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l); -#ifdef SCM_CREDENTIALS int pa_iochannel_creds_supported(pa_iochannel *io); int pa_iochannel_creds_enable(pa_iochannel *io); +struct ucred; + ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l); ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid); -#endif int pa_iochannel_is_readable(pa_iochannel*io); int pa_iochannel_is_writable(pa_iochannel*io); From b418809da125bdd381ea3ac838d8a2bba5d3224b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 16:28:02 +0000 Subject: [PATCH 0505/1514] Wrong variable used for port. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@598 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/socket-client.c | 2 +- src/polypcore/winsock.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index d73b22d13..1888ecc1b 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -489,7 +489,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam s.sin_family = AF_INET; memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr)); - s.sin_port = port; + s.sin_port = htons(a.port); if ((c = pa_socket_client_new_sockaddr(m, &s, sizeof(s)))) start_timeout(c); diff --git a/src/polypcore/winsock.h b/src/polypcore/winsock.h index b1e0f7d44..89e6a4ed7 100644 --- a/src/polypcore/winsock.h +++ b/src/polypcore/winsock.h @@ -18,6 +18,8 @@ #ifdef HAVE_WS2TCPIP_H #include +static const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }}; +static const struct in6_addr in6addr_loopback = {{ IN6ADDR_LOOPBACK_INIT }}; #endif #endif From c3a26709cb0c9af83f4713b807b76b30a5144bb2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 16:28:29 +0000 Subject: [PATCH 0506/1514] This wasn't supposed to be checked in. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@599 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/winsock.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/polypcore/winsock.h b/src/polypcore/winsock.h index 89e6a4ed7..b1e0f7d44 100644 --- a/src/polypcore/winsock.h +++ b/src/polypcore/winsock.h @@ -18,8 +18,6 @@ #ifdef HAVE_WS2TCPIP_H #include -static const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }}; -static const struct in6_addr in6addr_loopback = {{ IN6ADDR_LOOPBACK_INIT }}; #endif #endif From 25bcc106d02b29db0b39e18c8519e4ca51d81310 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Feb 2006 16:29:05 +0000 Subject: [PATCH 0507/1514] Do an explicit cast to shut up gcc. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@600 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/socket-client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index 1888ecc1b..1ee19a599 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -491,7 +491,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr)); s.sin_port = htons(a.port); - if ((c = pa_socket_client_new_sockaddr(m, &s, sizeof(s)))) + if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s)))) start_timeout(c); #endif /* HAVE_GETADDRINFO */ } From 435897741505fbdac30002b02c55a528f6ec8a40 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Feb 2006 17:14:23 +0000 Subject: [PATCH 0508/1514] * Add new "auth-group=" parameter to protocol-native-unix * Rename "public=" argument of protocol-{esound,native} to "auth-anonymous" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@601 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 2 +- src/modules/module-protocol-stub.c | 17 +++++++--- src/polypcore/protocol-esound.c | 4 +-- src/polypcore/protocol-native.c | 25 +++++++++++--- src/polypcore/util.c | 52 ++++++++++++++++++++++++++---- src/polypcore/util.h | 5 +-- 6 files changed, 86 insertions(+), 19 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 4b972fe23..8457916a8 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -160,7 +160,7 @@ int main(int argc, char *argv[]) { #ifdef HAVE_GETUID suid_root = getuid() != 0 && geteuid() == 0; - if (suid_root && (pa_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) { + if (suid_root && (pa_own_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) { pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'."); pa_drop_root(); } diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 749a7ace6..b02b96885 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -110,14 +110,23 @@ #define TCPWRAP_SERVICE "polypaudio-native" #define IPV4_PORT PA_NATIVE_DEFAULT_PORT #define UNIX_SOCKET PA_NATIVE_DEFAULT_UNIX_SOCKET - #define MODULE_ARGUMENTS "public", "cookie", + #define MODULE_ARGUMENTS_COMMON "cookie", "auth-anonymous", #ifdef USE_TCP_SOCKETS #include "module-native-protocol-tcp-symdef.h" #else #include "module-native-protocol-unix-symdef.h" #endif + + #if defined(SCM_CREDENTIALS) && !defined(USE_TCP_SOCKETS) + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", + #define AUTH_USAGE "auth-group=" + #else + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON + #define AUTH_USAGE + #endif + PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) - PA_MODULE_USAGE("public= cookie= "SOCKET_USAGE) + PA_MODULE_USAGE("auth-anonymous= cookie= "AUTH_USAGE SOCKET_USAGE) #elif defined(USE_PROTOCOL_ESOUND) #include #include @@ -126,14 +135,14 @@ #define TCPWRAP_SERVICE "esound" #define IPV4_PORT ESD_DEFAULT_PORT #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME - #define MODULE_ARGUMENTS "sink", "source", "public", "cookie", + #define MODULE_ARGUMENTS "sink", "source", "auth-anonymous", "cookie", #ifdef USE_TCP_SOCKETS #include "module-esound-protocol-tcp-symdef.h" #else #include "module-esound-protocol-unix-symdef.h" #endif PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION) - PA_MODULE_USAGE("sink= source= public= cookie= "SOCKET_USAGE) + PA_MODULE_USAGE("sink= source= auth-anonymous= cookie= "SOCKET_USAGE) #else #error "Broken build system" #endif diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 3ef1cd044..e30ff0671 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -1139,8 +1139,8 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve p = pa_xnew(pa_protocol_esound, 1); - if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { - pa_log(__FILE__": public= expects a boolean argument."); + if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) { + pa_log(__FILE__": auth-anonymous= expects a boolean argument."); return NULL; } diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 0fb9339bf..81d91f0cc 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -129,6 +129,9 @@ struct pa_protocol_native { pa_idxset *connections; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; int auth_cookie_in_property; +#ifdef SCM_CREDENTIALS + char *auth_group; +#endif }; static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk); @@ -878,15 +881,22 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t const struct ucred *ucred = pa_pdispatch_creds(pd); if (ucred) { - if (ucred->uid == getuid()) + if (ucred->uid == getuid()) success = 1; + else if (c->protocol->auth_group) { + int r; + + if ((r = pa_uid_in_group(ucred->uid, c->protocol->auth_group)) < 0) + pa_log_warn(__FILE__": failed to check group membership."); + else if (r > 0) + success = 1; + } pa_log_info(__FILE__": Got credentials: pid=%lu uid=%lu gid=%lu auth=%i", (unsigned long) ucred->pid, (unsigned long) ucred->uid, (unsigned long) ucred->gid, success); - } #endif @@ -2247,8 +2257,8 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo int public = 0; assert(c && ma); - if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) { - pa_log(__FILE__": public= expects a boolean argument."); + if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) { + pa_log(__FILE__": auth-anonymous= expects a boolean argument."); return NULL; } @@ -2258,6 +2268,10 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo p->public = public; p->server = NULL; +#ifdef SCM_CREDENTIALS + p->auth_group = pa_xstrdup(pa_modargs_get_value(ma, "auth-group", NULL)); +#endif + if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0) { pa_xfree(p); return NULL; @@ -2317,6 +2331,9 @@ void pa_protocol_native_free(pa_protocol_native *p) { if (p->auth_cookie_in_property) pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); +#ifdef SCM_CREDENTIALS + pa_xfree(p->auth_group); +#endif pa_xfree(p); } diff --git a/src/polypcore/util.c b/src/polypcore/util.c index f53eef343..f810b3bf2 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -166,7 +166,7 @@ int pa_make_secure_parent_dir(const char *fn) { int ret = -1; char *slash, *dir = pa_xstrdup(fn); - slash = pa_path_get_filename(dir); + slash = (char*) pa_path_get_filename(dir); if (slash == fn) goto finish; *(slash-1) = 0; @@ -636,13 +636,13 @@ char *pa_get_binary_name(char *s, size_t l) { /* Return a pointer to the filename inside a path (which is the last * component). */ -char *pa_path_get_filename(const char *p) { +const char *pa_path_get_filename(const char *p) { char *fn; if ((fn = strrchr(p, PATH_SEP))) return fn+1; - return (char*) p; + return (const char*) p; } /* Try to parse a boolean string value.*/ @@ -745,7 +745,6 @@ static int is_group(gid_t gid, const char *name) { goto finish; } - r = strcmp(name, result->gr_name) == 0; finish: @@ -767,7 +766,7 @@ finish: } /* Check the current user is member of the specified group */ -int pa_uid_in_group(const char *name, gid_t *gid) { +int pa_own_uid_in_group(const char *name, gid_t *gid) { GETGROUPS_T *gids, tgid; int n = sysconf(_SC_NGROUPS_MAX); int r = -1, i; @@ -803,9 +802,50 @@ finish: return r; } +int pa_uid_in_group(uid_t uid, const char *name) { + char *g_buf, *p_buf; + long g_n, p_n; + struct group grbuf, *gr; + char **i; + int r = -1; + + g_n = sysconf(_SC_GETGR_R_SIZE_MAX); + g_buf = pa_xmalloc(g_n); + + p_n = sysconf(_SC_GETPW_R_SIZE_MAX); + p_buf = pa_xmalloc(p_n); + + if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) + goto finish; + + r = 0; + for (i = gr->gr_mem; *i; i++) { + struct passwd pwbuf, *pw; + + if (getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw) != 0 || !pw) + continue; + + if (pw->pw_uid == uid) { + r = 1; + break; + } + } + +finish: + pa_xfree(g_buf); + pa_xfree(p_buf); + + return r; +} + #else /* HAVE_GRP_H */ -int pa_uid_in_group(const char *name, gid_t *gid) { +int pa_own_uid_in_group(const char *name, gid_t *gid) { + return -1; + +} + +int pa_uid_in_group(uid_t uid, const char *name) { return -1; } diff --git a/src/polypcore/util.h b/src/polypcore/util.h index af4e14c85..424283e76 100644 --- a/src/polypcore/util.h +++ b/src/polypcore/util.h @@ -53,7 +53,7 @@ char *pa_get_fqdn(char *s, size_t l); char *pa_get_binary_name(char *s, size_t l); char *pa_get_home_dir(char *s, size_t l); -char *pa_path_get_filename(const char *p); +const char *pa_path_get_filename(const char *p); int pa_gettimeofday(struct timeval *tv); pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); @@ -75,7 +75,8 @@ char *pa_strip_nl(char *s); const char *pa_strsignal(int sig); -int pa_uid_in_group(const char *name, gid_t *gid); +int pa_own_uid_in_group(const char *name, gid_t *gid); +int pa_uid_in_group(uid_t uid, const char *name); int pa_lock_fd(int fd, int b); From 0d8da54f158d4bd10212d38e4a207e14f46946cd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Feb 2006 17:15:02 +0000 Subject: [PATCH 0509/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@602 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 354e66bdc..e683cf8c0 100644 --- a/doc/todo +++ b/doc/todo @@ -7,7 +7,6 @@ Test: Fixes: - proper use of memcpy in procotol-esound.c so we don't get alignment problems - latency api rework for native protocol -- add support for auth using SCM_CREDENTIALS - use scatter/gather io for sockets - notification on hw volume change - mute switch support (like ALSA does it) From c5ec39d87f01716f0d4bb0c577c8d4e6d19ac665 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Feb 2006 17:27:55 +0000 Subject: [PATCH 0510/1514] move scatter/gather todo item to post-0.8, since it's impact on perfomance might not even be worth the effort. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@603 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/todo b/doc/todo index e683cf8c0..598dfddd2 100644 --- a/doc/todo +++ b/doc/todo @@ -7,7 +7,6 @@ Test: Fixes: - proper use of memcpy in procotol-esound.c so we don't get alignment problems - latency api rework for native protocol -- use scatter/gather io for sockets - notification on hw volume change - mute switch support (like ALSA does it) - module-oss-* love: @@ -29,6 +28,7 @@ Post 0.8: - module-tunnel: improve latency calculation - port from howl to avahi - multiline configuration statements +- use scatter/gather io for sockets Long term: - pass meta info for hearing impaired From b125e1c9d579d47865fb0e4015b8e1f2d15b152b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 26 Feb 2006 17:57:58 +0000 Subject: [PATCH 0511/1514] Hardware volume support in ALSA modules. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@604 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 39 +++++++++ src/modules/alsa-util.h | 3 + src/modules/module-alsa-sink.c | 140 +++++++++++++++++++++++++++++++ src/modules/module-alsa-source.c | 140 +++++++++++++++++++++++++++++++ 4 files changed, 322 insertions(+) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 1b254f514..4e1db5454 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -128,3 +128,42 @@ void pa_free_io_events(pa_mainloop_api* m, pa_io_event **io_events, unsigned n_i m->io_free(*ios); pa_xfree(io_events); } + +int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) { + int err; + + assert(mixer && dev); + + if ((err = snd_mixer_attach(mixer, dev)) < 0) { + pa_log_warn(__FILE__": Unable to attach to mixer %s: %s", dev, snd_strerror(err)); + return -1; + } + + if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) { + pa_log_warn(__FILE__": Unable to register mixer: %s", snd_strerror(err)); + return -1; + } + + if ((err = snd_mixer_load(mixer)) < 0) { + pa_log_warn(__FILE__": Unable to load mixer: %s", snd_strerror(err)); + return -1; + } + + return 0; +} + +snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name) { + snd_mixer_elem_t *elem; + snd_mixer_selem_id_t *sid; + snd_mixer_selem_id_alloca(&sid); + + assert(mixer && name); + + snd_mixer_selem_id_set_name(sid, name); + + elem = snd_mixer_find_selem(mixer, sid); + if (!elem) + pa_log_warn(__FILE__": Cannot find mixer control %s", snd_mixer_selem_id_get_name(sid)); + + return elem; +} diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 5d6d66348..489704c78 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -32,4 +32,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api *m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata); void pa_free_io_events(pa_mainloop_api* m, pa_io_event **io_sources, unsigned n_io_sources); +int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev); +snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name); + #endif diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index e37367c89..68a036155 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -54,9 +54,12 @@ PA_MODULE_USAGE("sink_name= device= format=userdata; + long vol; + int err; + + assert(u && u->mixer_elem); + + if (snd_mixer_selem_has_playback_volume_joined(u->mixer_elem)) { + err = snd_mixer_selem_get_playback_volume(u->mixer_elem, 0, &vol); + if (err < 0) + goto fail; + pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, + (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min)); + } else { + int i; + + for (i = 0;i < s->hw_volume.channels;i++) { + err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol); + if (err < 0) + goto fail; + s->hw_volume.values[i] = + (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min); + } + } + + return 0; + +fail: + pa_log_error(__FILE__": Unable to read volume: %s", snd_strerror(err)); + s->get_hw_volume = NULL; + s->set_hw_volume = NULL; + return -1; +} + +static int sink_set_hw_volume_cb(pa_sink *s) { + struct userdata *u = s->userdata; + int err; + pa_volume_t vol; + + assert(u && u->mixer_elem); + + if (snd_mixer_selem_has_playback_volume_joined(u->mixer_elem)) { + vol = pa_cvolume_avg(&s->hw_volume) * (u->hw_volume_max - u->hw_volume_min) / + PA_VOLUME_NORM + u->hw_volume_min; + err = snd_mixer_selem_set_playback_volume_all(u->mixer_elem, vol); + if (err < 0) + goto fail; + } else { + int i; + + for (i = 0;i < s->hw_volume.channels;i++) { + vol = s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min) / + PA_VOLUME_NORM + u->hw_volume_min; + err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, vol); + if (err < 0) + goto fail; + } + } + + return 0; + +fail: + pa_log_error(__FILE__": Unable to set volume: %s", snd_strerror(err)); + s->get_hw_volume = NULL; + s->set_hw_volume = NULL; + return -1; +} + +static int sink_get_hw_mute_cb(pa_sink *s) { + struct userdata *u = s->userdata; + int err, sw; + + assert(u && u->mixer_elem); + + err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw); + if (err) { + pa_log_error(__FILE__": Unable to get switch: %s", snd_strerror(err)); + s->get_hw_mute = NULL; + s->set_hw_mute = NULL; + return -1; + } + + s->hw_muted = !sw; + + return 0; +} + +static int sink_set_hw_mute_cb(pa_sink *s) { + struct userdata *u = s->userdata; + int err; + + assert(u && u->mixer_elem); + + err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->hw_muted); + if (err) { + pa_log_error(__FILE__": Unable to set switch: %s", snd_strerror(err)); + s->get_hw_mute = NULL; + s->set_hw_mute = NULL; + return -1; + } + + return 0; +} + int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; int ret = -1; @@ -220,10 +327,34 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) { + pa_log(__FILE__": Error opening mixer: %s", snd_strerror(err)); + goto fail; + } + + if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || + !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "PCM"))) { + snd_mixer_close(u->mixer_handle); + u->mixer_handle = NULL; + } + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; + if (u->mixer_handle) { + assert(u->mixer_elem); + if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) { + u->sink->get_hw_volume = sink_get_hw_volume_cb; + u->sink->set_hw_volume = sink_set_hw_volume_cb; + snd_mixer_selem_get_playback_volume_range( + u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); + } + if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) { + u->sink->get_hw_mute = sink_get_hw_mute_cb; + u->sink->set_hw_mute = sink_set_hw_mute_cb; + } + } u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); @@ -251,6 +382,12 @@ int pa__init(pa_core *c, pa_module*m) { finish: if (ma) pa_modargs_free(ma); + + /* Get initial mixer settings */ + if (u->sink->get_hw_volume) + u->sink->get_hw_volume(u->sink); + if (u->sink->get_hw_mute) + u->sink->get_hw_mute(u->sink); return ret; @@ -277,6 +414,9 @@ void pa__done(pa_core *c, pa_module*m) { if (u->io_events) pa_free_io_events(c->mainloop, u->io_events, u->n_io_events); + if (u->mixer_handle) + snd_mixer_close(u->mixer_handle); + if (u->pcm_handle) { snd_pcm_drop(u->pcm_handle); snd_pcm_close(u->pcm_handle); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index bf031350d..e2dbc8bf1 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -54,9 +54,12 @@ PA_MODULE_USAGE("source_name= device= format=< struct userdata { snd_pcm_t *pcm_handle; + snd_mixer_t *mixer_handle; + snd_mixer_elem_t *mixer_elem; pa_source *source; pa_io_event **io_events; unsigned n_io_events; + long hw_volume_max, hw_volume_min; size_t frame_size, fragment_size; pa_memchunk memchunk; @@ -165,6 +168,110 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { return pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); } +static int source_get_hw_volume_cb(pa_source *s) { + struct userdata *u = s->userdata; + long vol; + int err; + + assert(u && u->mixer_elem); + + if (snd_mixer_selem_has_capture_volume_joined(u->mixer_elem)) { + err = snd_mixer_selem_get_capture_volume(u->mixer_elem, 0, &vol); + if (err < 0) + goto fail; + pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, + (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min)); + } else { + int i; + + for (i = 0;i < s->hw_volume.channels;i++) { + err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol); + if (err < 0) + goto fail; + s->hw_volume.values[i] = + (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min); + } + } + + return 0; + +fail: + pa_log_error(__FILE__": Unable to read volume: %s", snd_strerror(err)); + s->get_hw_volume = NULL; + s->set_hw_volume = NULL; + return -1; +} + +static int source_set_hw_volume_cb(pa_source *s) { + struct userdata *u = s->userdata; + int err; + pa_volume_t vol; + + assert(u && u->mixer_elem); + + if (snd_mixer_selem_has_capture_volume_joined(u->mixer_elem)) { + vol = pa_cvolume_avg(&s->hw_volume) * (u->hw_volume_max - u->hw_volume_min) / + PA_VOLUME_NORM + u->hw_volume_min; + err = snd_mixer_selem_set_capture_volume_all(u->mixer_elem, vol); + if (err < 0) + goto fail; + } else { + int i; + + for (i = 0;i < s->hw_volume.channels;i++) { + vol = s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min) / + PA_VOLUME_NORM + u->hw_volume_min; + err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, vol); + if (err < 0) + goto fail; + } + } + + return 0; + +fail: + pa_log_error(__FILE__": Unable to set volume: %s", snd_strerror(err)); + s->get_hw_volume = NULL; + s->set_hw_volume = NULL; + return -1; +} + +static int source_get_hw_mute_cb(pa_source *s) { + struct userdata *u = s->userdata; + int err, sw; + + assert(u && u->mixer_elem); + + err = snd_mixer_selem_get_capture_switch(u->mixer_elem, 0, &sw); + if (err) { + pa_log_error(__FILE__": Unable to get switch: %s", snd_strerror(err)); + s->get_hw_mute = NULL; + s->set_hw_mute = NULL; + return -1; + } + + s->hw_muted = !sw; + + return 0; +} + +static int source_set_hw_mute_cb(pa_source *s) { + struct userdata *u = s->userdata; + int err; + + assert(u && u->mixer_elem); + + err = snd_mixer_selem_set_capture_switch_all(u->mixer_elem, !s->hw_muted); + if (err) { + pa_log_error(__FILE__": Unable to set switch: %s", snd_strerror(err)); + s->get_hw_mute = NULL; + s->set_hw_mute = NULL; + return -1; + } + + return 0; +} + int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; int ret = -1; @@ -211,11 +318,35 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) { + pa_log(__FILE__": Error opening mixer: %s", snd_strerror(err)); + goto fail; + } + + if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || + !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture"))) { + snd_mixer_close(u->mixer_handle); + u->mixer_handle = NULL; + } + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); assert(u->source); u->source->userdata = u; u->source->get_latency = source_get_latency_cb; + if (u->mixer_handle) { + assert(u->mixer_elem); + if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) { + u->source->get_hw_volume = source_get_hw_volume_cb; + u->source->set_hw_volume = source_set_hw_volume_cb; + snd_mixer_selem_get_capture_volume_range( + u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); + } + if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) { + u->source->get_hw_mute = source_get_hw_mute_cb; + u->source->set_hw_mute = source_set_hw_mute_cb; + } + } pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); @@ -239,6 +370,12 @@ int pa__init(pa_core *c, pa_module*m) { finish: if (ma) pa_modargs_free(ma); + + /* Get initial mixer settings */ + if (u->source->get_hw_volume) + u->source->get_hw_volume(u->source); + if (u->source->get_hw_mute) + u->source->get_hw_mute(u->source); return ret; @@ -264,6 +401,9 @@ void pa__done(pa_core *c, pa_module*m) { if (u->io_events) pa_free_io_events(c->mainloop, u->io_events, u->n_io_events); + + if (u->mixer_handle) + snd_mixer_close(u->mixer_handle); if (u->pcm_handle) { snd_pcm_drop(u->pcm_handle); From c119996c73e540f0c0579c3a6aa45b9cd27c2509 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 26 Feb 2006 17:58:27 +0000 Subject: [PATCH 0512/1514] Fix correct default device. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@605 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-source.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index e2dbc8bf1..a35704731 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -78,7 +78,7 @@ static const char* const valid_modargs[] = { }; #define DEFAULT_SOURCE_NAME "alsa_input" -#define DEFAULT_DEVICE "hw:0,0" +#define DEFAULT_DEVICE "default" static void update_usage(struct userdata *u) { pa_module_set_used(u->module, From ae07d5abd5fe680367723cc6913eb759d22d8551 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 26 Feb 2006 19:09:26 +0000 Subject: [PATCH 0513/1514] Handle ALSA file descriptors more correctly. This means a bit more overhead, but following their API properly should avoid problems in the future. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@606 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 225 +++++++++++++++++++++++++------ src/modules/alsa-util.h | 10 +- src/modules/module-alsa-sink.c | 17 +-- src/modules/module-alsa-source.c | 17 +-- 4 files changed, 207 insertions(+), 62 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 4e1db5454..5f4323f81 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -32,6 +32,188 @@ #include "alsa-util.h" +struct pa_alsa_fdlist { + int num_fds; + struct pollfd *fds; + /* This is a temporary buffer used to avoid lots of mallocs */ + struct pollfd *work_fds; + + snd_pcm_t *pcm; + + pa_mainloop_api *m; + pa_defer_event *defer; + pa_io_event **ios; + + int polled; + + void (*cb)(void *userdata); + void *userdata; +}; + +static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) { + struct pa_alsa_fdlist *fdl = (struct pa_alsa_fdlist*)userdata; + int err, i; + unsigned short revents; + + assert(a && fdl && fdl->pcm); + + if (fdl->polled) + return; + + fdl->polled = 1; + + memcpy(fdl->work_fds, fdl->fds, sizeof(struct pollfd) * fdl->num_fds); + + for (i = 0;i < fdl->num_fds;i++) { + if (e == fdl->ios[i]) { + if (events & PA_IO_EVENT_INPUT) + fdl->work_fds[i].revents |= POLLIN; + if (events & PA_IO_EVENT_OUTPUT) + fdl->work_fds[i].revents |= POLLOUT; + if (events & PA_IO_EVENT_ERROR) + fdl->work_fds[i].revents |= POLLERR; + if (events & PA_IO_EVENT_HANGUP) + fdl->work_fds[i].revents |= POLLHUP; + break; + } + } + + assert(i != fdl->num_fds); + + err = snd_pcm_poll_descriptors_revents(fdl->pcm, fdl->work_fds, fdl->num_fds, &revents); + if (err < 0) { + pa_log_error(__FILE__": Unable to get poll revent: %s", + snd_strerror(err)); + a->defer_enable(fdl->defer, 0); + return; + } + + if (revents) + fdl->cb(fdl->userdata); +} + +static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) { + struct pa_alsa_fdlist *fdl = (struct pa_alsa_fdlist*)userdata; + int num_fds, i, err; + struct pollfd *temp; + + assert(a && fdl && fdl->pcm); + + num_fds = snd_pcm_poll_descriptors_count(fdl->pcm); + assert(num_fds > 0); + + if (num_fds != fdl->num_fds) { + if (fdl->fds) + pa_xfree(fdl->fds); + if (fdl->work_fds) + pa_xfree(fdl->work_fds); + fdl->fds = pa_xmalloc(sizeof(struct pollfd) * num_fds); + fdl->work_fds = pa_xmalloc(sizeof(struct pollfd) * num_fds); + } + + memset(fdl->work_fds, 0, sizeof(struct pollfd) * num_fds); + err = snd_pcm_poll_descriptors(fdl->pcm, fdl->work_fds, num_fds); + if (err < 0) { + pa_log_error(__FILE__": Unable to get poll descriptors: %s", + snd_strerror(err)); + a->defer_enable(fdl->defer, 0); + return; + } + + fdl->polled = 0; + + if (memcmp(fdl->fds, fdl->work_fds, sizeof(struct pollfd) * num_fds) == 0) + return; + + if (fdl->ios) { + for (i = 0;i < fdl->num_fds;i++) + a->io_free(fdl->ios[i]); + if (num_fds != fdl->num_fds) { + pa_xfree(fdl->ios); + fdl->ios = pa_xmalloc(sizeof(pa_io_event*) * num_fds); + assert(fdl->ios); + } + } else { + fdl->ios = pa_xmalloc(sizeof(pa_io_event*) * num_fds); + assert(fdl->ios); + } + + /* Swap pointers */ + temp = fdl->work_fds; + fdl->work_fds = fdl->fds; + fdl->fds = temp; + + fdl->num_fds = num_fds; + + for (i = 0;i < num_fds;i++) { + fdl->ios[i] = a->io_new(a, fdl->fds[i].fd, + ((fdl->fds[i].events & POLLIN) ? PA_IO_EVENT_INPUT : 0) | + ((fdl->fds[i].events & POLLOUT) ? PA_IO_EVENT_OUTPUT : 0), + io_cb, fdl); + assert(fdl->ios[i]); + } +} + +struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) { + struct pa_alsa_fdlist *fdl; + + fdl = pa_xmalloc(sizeof(struct pa_alsa_fdlist)); + assert(fdl); + + fdl->num_fds = 0; + fdl->fds = NULL; + fdl->work_fds = NULL; + + fdl->pcm = NULL; + + fdl->m = NULL; + fdl->defer = NULL; + fdl->ios = NULL; + + fdl->polled = 0; + + return fdl; +} + +void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) { + assert(fdl); + + if (fdl->defer) { + assert(fdl->m); + fdl->m->defer_free(fdl->defer); + } + + if (fdl->ios) { + int i; + assert(fdl->m); + for (i = 0;i < fdl->num_fds;i++) + fdl->m->io_free(fdl->ios[0]); + pa_xfree(fdl->ios); + } + + if (fdl->fds) + pa_xfree(fdl->fds); + if (fdl->work_fds) + pa_xfree(fdl->work_fds); + + pa_xfree(fdl); +} + +int pa_alsa_fdlist_init_pcm(struct pa_alsa_fdlist *fdl, snd_pcm_t *pcm_handle, pa_mainloop_api* m, void (*cb)(void *userdata), void *userdata) { + assert(fdl && pcm_handle && m && !fdl->m && cb); + + fdl->pcm = pcm_handle; + fdl->m = m; + + fdl->defer = m->defer_new(m, defer_cb, fdl); + assert(fdl->defer); + + fdl->cb = cb; + fdl->userdata = userdata; + + return 0; +} + /* Set the hardware parameters of the given ALSA device. Returns the * selected fragment settings in *period and *period_size */ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { @@ -86,49 +268,6 @@ finish: return ret; } -/* Allocate an IO event for every ALSA poll descriptor for the - * specified ALSA device. Return a pointer to such an array in - * *io_events. Store the length of that array in *n_io_events. Use the - * specified callback function and userdata. The array has to be freed - * with pa_free_io_events(). */ -int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api* m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata) { - unsigned i; - struct pollfd *pfds, *ppfd; - pa_io_event **ios; - assert(pcm_handle && m && io_events && n_io_events && cb); - - *n_io_events = snd_pcm_poll_descriptors_count(pcm_handle); - - pfds = pa_xmalloc(sizeof(struct pollfd) * *n_io_events); - if (snd_pcm_poll_descriptors(pcm_handle, pfds, *n_io_events) < 0) { - pa_xfree(pfds); - return -1; - } - - *io_events = pa_xmalloc(sizeof(void*) * *n_io_events); - - for (i = 0, ios = *io_events, ppfd = pfds; i < *n_io_events; i++, ios++, ppfd++) { - *ios = m->io_new(m, ppfd->fd, - ((ppfd->events & POLLIN) ? PA_IO_EVENT_INPUT : 0) | - ((ppfd->events & POLLOUT) ? PA_IO_EVENT_OUTPUT : 0), cb, userdata); - assert(*ios); - } - - pa_xfree(pfds); - return 0; -} - -/* Free the memory allocated by pa_create_io_events() */ -void pa_free_io_events(pa_mainloop_api* m, pa_io_event **io_events, unsigned n_io_events) { - unsigned i; - pa_io_event **ios; - assert(m && io_events); - - for (ios = io_events, i = 0; i < n_io_events; i++, ios++) - m->io_free(*ios); - pa_xfree(io_events); -} - int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) { int err; diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 489704c78..79f4c64bb 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -27,10 +27,14 @@ #include #include -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); +struct pa_alsa_fdlist; -int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api *m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata); -void pa_free_io_events(pa_mainloop_api* m, pa_io_event **io_sources, unsigned n_io_sources); +struct pa_alsa_fdlist *pa_alsa_fdlist_new(void); +void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl); + +int pa_alsa_fdlist_init_pcm(struct pa_alsa_fdlist *fdl, snd_pcm_t *pcm_handle, pa_mainloop_api* m, void (*cb)(void *userdata), void *userdata); + +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev); snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name); diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 68a036155..ab4037b2b 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -57,8 +57,7 @@ struct userdata { snd_mixer_t *mixer_handle; snd_mixer_elem_t *mixer_elem; pa_sink *sink; - pa_io_event **io_events; - unsigned n_io_events; + struct pa_alsa_fdlist *fdl; long hw_volume_max, hw_volume_min; size_t frame_size, fragment_size; @@ -144,9 +143,9 @@ static void do_write(struct userdata *u) { } } -static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { +static void fdl_callback(void *userdata) { struct userdata *u = userdata; - assert(u && a && e); + assert(u); if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) xrun_recovery(u); @@ -359,8 +358,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); - if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { - pa_log(__FILE__": failed to obtain file descriptors"); + u->fdl = pa_alsa_fdlist_new(); + assert(u->fdl); + if (pa_alsa_fdlist_init_pcm(u->fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) { + pa_log(__FILE__": failed to initialise file descriptor monitoring"); goto fail; } @@ -411,8 +412,8 @@ void pa__done(pa_core *c, pa_module*m) { pa_sink_unref(u->sink); } - if (u->io_events) - pa_free_io_events(c->mainloop, u->io_events, u->n_io_events); + if (u->fdl) + pa_alsa_fdlist_free(u->fdl); if (u->mixer_handle) snd_mixer_close(u->mixer_handle); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index a35704731..2adefa6a7 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -57,8 +57,7 @@ struct userdata { snd_mixer_t *mixer_handle; snd_mixer_elem_t *mixer_elem; pa_source *source; - pa_io_event **io_events; - unsigned n_io_events; + struct pa_alsa_fdlist *fdl; long hw_volume_max, hw_volume_min; size_t frame_size, fragment_size; @@ -144,9 +143,9 @@ static void do_read(struct userdata *u) { } } -static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { +static void fdl_callback(void *userdata) { struct userdata *u = userdata; - assert(u && a && e); + assert(u); if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) xrun_recovery(u); @@ -350,8 +349,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); - if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { - pa_log(__FILE__": failed to obtain file descriptors"); + u->fdl = pa_alsa_fdlist_new(); + assert(u->fdl); + if (pa_alsa_fdlist_init_pcm(u->fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) { + pa_log(__FILE__": failed to initialise file descriptor monitoring"); goto fail; } @@ -399,8 +400,8 @@ void pa__done(pa_core *c, pa_module*m) { pa_source_unref(u->source); } - if (u->io_events) - pa_free_io_events(c->mainloop, u->io_events, u->n_io_events); + if (u->fdl) + pa_alsa_fdlist_free(u->fdl); if (u->mixer_handle) snd_mixer_close(u->mixer_handle); From 1e68539dc41f73722402f4678d002197289e37c5 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 26 Feb 2006 21:50:55 +0000 Subject: [PATCH 0514/1514] Get notifications about mixer changes from ALSA. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@607 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 44 +++++++++++++++++++++++++++----- src/modules/alsa-util.h | 1 + src/modules/module-alsa-sink.c | 44 +++++++++++++++++++++++++++----- src/modules/module-alsa-source.c | 44 +++++++++++++++++++++++++++----- 4 files changed, 114 insertions(+), 19 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 5f4323f81..adb6f3f18 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -39,6 +39,7 @@ struct pa_alsa_fdlist { struct pollfd *work_fds; snd_pcm_t *pcm; + snd_mixer_t *mixer; pa_mainloop_api *m; pa_defer_event *defer; @@ -55,7 +56,7 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t int err, i; unsigned short revents; - assert(a && fdl && fdl->pcm); + assert(a && fdl && (fdl->pcm || fdl->mixer) && fdl->fds && fdl->work_fds); if (fdl->polled) return; @@ -80,7 +81,11 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t assert(i != fdl->num_fds); - err = snd_pcm_poll_descriptors_revents(fdl->pcm, fdl->work_fds, fdl->num_fds, &revents); + if (fdl->pcm) + err = snd_pcm_poll_descriptors_revents(fdl->pcm, fdl->work_fds, fdl->num_fds, &revents); + else + err = snd_mixer_poll_descriptors_revents(fdl->mixer, fdl->work_fds, fdl->num_fds, &revents); + if (err < 0) { pa_log_error(__FILE__": Unable to get poll revent: %s", snd_strerror(err)); @@ -88,8 +93,12 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t return; } - if (revents) - fdl->cb(fdl->userdata); + if (revents) { + if (fdl->pcm) + fdl->cb(fdl->userdata); + else + snd_mixer_handle_events(fdl->mixer); + } } static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) { @@ -97,9 +106,12 @@ static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) { int num_fds, i, err; struct pollfd *temp; - assert(a && fdl && fdl->pcm); + assert(a && fdl && (fdl->pcm || fdl->mixer)); - num_fds = snd_pcm_poll_descriptors_count(fdl->pcm); + if (fdl->pcm) + num_fds = snd_pcm_poll_descriptors_count(fdl->pcm); + else + num_fds = snd_mixer_poll_descriptors_count(fdl->mixer); assert(num_fds > 0); if (num_fds != fdl->num_fds) { @@ -112,7 +124,12 @@ static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) { } memset(fdl->work_fds, 0, sizeof(struct pollfd) * num_fds); - err = snd_pcm_poll_descriptors(fdl->pcm, fdl->work_fds, num_fds); + + if (fdl->pcm) + err = snd_pcm_poll_descriptors(fdl->pcm, fdl->work_fds, num_fds); + else + err = snd_mixer_poll_descriptors(fdl->mixer, fdl->work_fds, num_fds); + if (err < 0) { pa_log_error(__FILE__": Unable to get poll descriptors: %s", snd_strerror(err)); @@ -165,6 +182,7 @@ struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) { fdl->work_fds = NULL; fdl->pcm = NULL; + fdl->mixer = NULL; fdl->m = NULL; fdl->defer = NULL; @@ -214,6 +232,18 @@ int pa_alsa_fdlist_init_pcm(struct pa_alsa_fdlist *fdl, snd_pcm_t *pcm_handle, p return 0; } +int pa_alsa_fdlist_init_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m) { + assert(fdl && mixer_handle && m && !fdl->m); + + fdl->mixer = mixer_handle; + fdl->m = m; + + fdl->defer = m->defer_new(m, defer_cb, fdl); + assert(fdl->defer); + + return 0; +} + /* Set the hardware parameters of the given ALSA device. Returns the * selected fragment settings in *period and *period_size */ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 79f4c64bb..c908d7e04 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -33,6 +33,7 @@ struct pa_alsa_fdlist *pa_alsa_fdlist_new(void); void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl); int pa_alsa_fdlist_init_pcm(struct pa_alsa_fdlist *fdl, snd_pcm_t *pcm_handle, pa_mainloop_api* m, void (*cb)(void *userdata), void *userdata); +int pa_alsa_fdlist_init_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m); int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index ab4037b2b..732612ef1 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -57,7 +57,8 @@ struct userdata { snd_mixer_t *mixer_handle; snd_mixer_elem_t *mixer_elem; pa_sink *sink; - struct pa_alsa_fdlist *fdl; + struct pa_alsa_fdlist *pcm_fdl; + struct pa_alsa_fdlist *mixer_fdl; long hw_volume_max, hw_volume_min; size_t frame_size, fragment_size; @@ -153,6 +154,24 @@ static void fdl_callback(void *userdata) { do_write(u); } +static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { + struct userdata *u = snd_mixer_elem_get_callback_private(elem); + + assert(u && u->mixer_handle); + + if (mask & SND_CTL_EVENT_MASK_VALUE) { + if (u->sink->get_hw_volume) + u->sink->get_hw_volume(u->sink); + if (u->sink->get_hw_mute) + u->sink->get_hw_mute(u->sink); + pa_subscription_post(u->sink->core, + PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, + u->sink->index); + } + + return 0; +} + static pa_usec_t sink_get_latency_cb(pa_sink *s) { pa_usec_t r = 0; struct userdata *u = s->userdata; @@ -358,12 +377,23 @@ int pa__init(pa_core *c, pa_module*m) { pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); - u->fdl = pa_alsa_fdlist_new(); - assert(u->fdl); - if (pa_alsa_fdlist_init_pcm(u->fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) { + u->pcm_fdl = pa_alsa_fdlist_new(); + assert(u->pcm_fdl); + if (pa_alsa_fdlist_init_pcm(u->pcm_fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) { pa_log(__FILE__": failed to initialise file descriptor monitoring"); goto fail; } + + if (u->mixer_handle) { + u->mixer_fdl = pa_alsa_fdlist_new(); + assert(u->mixer_fdl); + if (pa_alsa_fdlist_init_mixer(u->mixer_fdl, u->mixer_handle, c->mainloop) < 0) { + pa_log(__FILE__": failed to initialise file descriptor monitoring"); + goto fail; + } + snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback); + snd_mixer_elem_set_callback_private(u->mixer_elem, u); + } u->frame_size = frame_size; u->fragment_size = period_size; @@ -412,8 +442,10 @@ void pa__done(pa_core *c, pa_module*m) { pa_sink_unref(u->sink); } - if (u->fdl) - pa_alsa_fdlist_free(u->fdl); + if (u->pcm_fdl) + pa_alsa_fdlist_free(u->pcm_fdl); + if (u->mixer_fdl) + pa_alsa_fdlist_free(u->mixer_fdl); if (u->mixer_handle) snd_mixer_close(u->mixer_handle); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 2adefa6a7..1b7ae7d35 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -57,7 +57,8 @@ struct userdata { snd_mixer_t *mixer_handle; snd_mixer_elem_t *mixer_elem; pa_source *source; - struct pa_alsa_fdlist *fdl; + struct pa_alsa_fdlist *pcm_fdl; + struct pa_alsa_fdlist *mixer_fdl; long hw_volume_max, hw_volume_min; size_t frame_size, fragment_size; @@ -153,6 +154,24 @@ static void fdl_callback(void *userdata) { do_read(u); } +static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { + struct userdata *u = snd_mixer_elem_get_callback_private(elem); + + assert(u && u->mixer_handle); + + if (mask & SND_CTL_EVENT_MASK_VALUE) { + if (u->source->get_hw_volume) + u->source->get_hw_volume(u->source); + if (u->source->get_hw_mute) + u->source->get_hw_mute(u->source); + pa_subscription_post(u->source->core, + PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, + u->source->index); + } + + return 0; +} + static pa_usec_t source_get_latency_cb(pa_source *s) { struct userdata *u = s->userdata; snd_pcm_sframes_t frames; @@ -349,13 +368,24 @@ int pa__init(pa_core *c, pa_module*m) { pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); - u->fdl = pa_alsa_fdlist_new(); - assert(u->fdl); - if (pa_alsa_fdlist_init_pcm(u->fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) { + u->pcm_fdl = pa_alsa_fdlist_new(); + assert(u->pcm_fdl); + if (pa_alsa_fdlist_init_pcm(u->pcm_fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) { pa_log(__FILE__": failed to initialise file descriptor monitoring"); goto fail; } + if (u->mixer_handle) { + u->mixer_fdl = pa_alsa_fdlist_new(); + assert(u->mixer_fdl); + if (pa_alsa_fdlist_init_mixer(u->mixer_fdl, u->mixer_handle, c->mainloop) < 0) { + pa_log(__FILE__": failed to initialise file descriptor monitoring"); + goto fail; + } + snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback); + snd_mixer_elem_set_callback_private(u->mixer_elem, u); + } + u->frame_size = frame_size; u->fragment_size = period_size; @@ -400,8 +430,10 @@ void pa__done(pa_core *c, pa_module*m) { pa_source_unref(u->source); } - if (u->fdl) - pa_alsa_fdlist_free(u->fdl); + if (u->pcm_fdl) + pa_alsa_fdlist_free(u->pcm_fdl); + if (u->mixer_fdl) + pa_alsa_fdlist_free(u->mixer_fdl); if (u->mixer_handle) snd_mixer_close(u->mixer_handle); From 0c65922d3933d310f81e3f73b354e610d8e3cdf1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 26 Feb 2006 21:55:08 +0000 Subject: [PATCH 0515/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@608 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 598dfddd2..a5ab5c427 100644 --- a/doc/todo +++ b/doc/todo @@ -13,7 +13,6 @@ Fixes: - deal with underflows propely - improve latency measurement for mmap - module-alsa-* love: - - volume control - add hw driver name to sink/source description - deal with underflows properly - module-tunnel volume support (sink, source, notify) From e37f008a033a61feb0bc5a03d051a4ca3babf382 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 27 Feb 2006 08:57:41 +0000 Subject: [PATCH 0516/1514] Function prototype didn't match actual definition. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@609 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/memblockq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polypcore/memblockq.h b/src/polypcore/memblockq.h index 210f1a078..302a53668 100644 --- a/src/polypcore/memblockq.h +++ b/src/polypcore/memblockq.h @@ -112,7 +112,7 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek); void pa_memblockq_flush(pa_memblockq *bq); /* Get Target length */ -uint32_t pa_memblockq_get_tlength(pa_memblockq *bq); +size_t pa_memblockq_get_tlength(pa_memblockq *bq); /* Return the current read index */ int64_t pa_memblockq_get_read_index(pa_memblockq *bq); From f59bc1ff2b0dce8ec0a7aba4ac564019300fb7ab Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 27 Feb 2006 08:58:29 +0000 Subject: [PATCH 0517/1514] Fix some signed/unsigned warnings. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@610 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/memblockq.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/polypcore/memblockq.c b/src/polypcore/memblockq.c index 9b12a8105..38403ec2a 100644 --- a/src/polypcore/memblockq.c +++ b/src/polypcore/memblockq.c @@ -76,7 +76,8 @@ pa_memblockq* pa_memblockq_new( bq->read_index = bq->write_index = idx; bq->memblock_stat = s; - pa_log_debug(__FILE__": memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u", maxlength, tlength, base, prebuf, minreq); + pa_log_debug(__FILE__": memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", + (unsigned long)maxlength, (unsigned long)tlength, (unsigned long)base, (unsigned long)prebuf, (unsigned long)minreq); bq->maxlength = ((maxlength+base-1)/base)*base; assert(bq->maxlength >= base); @@ -98,7 +99,8 @@ pa_memblockq* pa_memblockq_new( if (!bq->minreq) bq->minreq = 1; - pa_log_debug(__FILE__": memblockq sanitized: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u", bq->maxlength, bq->tlength, bq->base, bq->prebuf, bq->minreq); + pa_log_debug(__FILE__": memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", + (unsigned long)bq->maxlength, (unsigned long)bq->tlength, (unsigned long)bq->base, (unsigned long)bq->prebuf, (unsigned long)bq->minreq); bq->state = bq->prebuf ? PREBUF : RUNNING; bq->silence = silence ? pa_memblock_ref(silence) : NULL; @@ -149,7 +151,7 @@ static int can_push(pa_memblockq *bq, size_t l) { assert(bq); if (bq->read_index > bq->write_index) { - int64_t d = bq->read_index - bq->write_index; + size_t d = bq->read_index - bq->write_index; if (l > d) l -= d; @@ -160,7 +162,7 @@ static int can_push(pa_memblockq *bq, size_t l) { end = bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : 0; /* Make sure that the list doesn't get too long */ - if (bq->write_index + l > end) + if (bq->write_index + (int64_t)l > end) if (bq->write_index + l - bq->read_index > bq->maxlength) return 0; @@ -191,7 +193,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { /* We currently have a buffer underflow, we need to drop some * incoming data */ - int64_t d = bq->read_index - bq->write_index; + size_t d = bq->read_index - bq->write_index; if (chunk.length > d) { chunk.index += d; @@ -210,10 +212,10 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { q = bq->blocks_tail; while (q) { - if (bq->write_index >= q->index + q->chunk.length) + if (bq->write_index >= q->index + (int64_t)q->chunk.length) /* We found the entry where we need to place the new entry immediately after */ break; - else if (bq->write_index + chunk.length <= q->index) { + else if (bq->write_index + (int64_t)chunk.length <= q->index) { /* This entry isn't touched at all, let's skip it */ q = q->prev; } else if (bq->write_index <= q->index && @@ -272,8 +274,8 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { } else { size_t d; - assert(bq->write_index + chunk.length > q->index && - bq->write_index + chunk.length < q->index + q->chunk.length && + assert(bq->write_index + (int64_t)chunk.length > q->index && + bq->write_index + (int64_t)chunk.length < q->index + (int64_t)q->chunk.length && bq->write_index < q->index); /* The job overwrites the current entry at the end, so let's drop the beginning of this entry */ @@ -289,21 +291,21 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { } if (q) { - assert(bq->write_index >= q->index + q->chunk.length); - assert(!q->next || (bq->write_index+chunk.length <= q->next->index)); + assert(bq->write_index >= q->index + (int64_t)q->chunk.length); + assert(!q->next || (bq->write_index + (int64_t)chunk.length <= q->next->index)); /* Try to merge memory blocks */ if (q->chunk.memblock == chunk.memblock && - q->chunk.index + q->chunk.length == chunk.index && - bq->write_index == q->index + q->chunk.length) { + q->chunk.index + (int64_t)q->chunk.length == chunk.index && + bq->write_index == q->index + (int64_t)q->chunk.length) { q->chunk.length += chunk.length; bq->write_index += chunk.length; return 0; } } else - assert(!bq->blocks || (bq->write_index+chunk.length <= bq->blocks->index)); + assert(!bq->blocks || (bq->write_index + (int64_t)chunk.length <= bq->blocks->index)); n = pa_xnew(struct memblock_list, 1); @@ -531,7 +533,7 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) { bq->write_index = bq->read_index + offset; return; case PA_SEEK_RELATIVE_END: - bq->write_index = (bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : bq->read_index) + offset; + bq->write_index = (bq->blocks_tail ? bq->blocks_tail->index + (int64_t)bq->blocks_tail->chunk.length : bq->read_index) + offset; return; } From 1bb14c3a1df2a9114a892df9bff10b6a2efc3388 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 27 Feb 2006 09:09:15 +0000 Subject: [PATCH 0518/1514] 64-bit fixes. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@611 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/idxset.c | 2 +- src/polypcore/protocol-esound.c | 2 +- src/polypcore/protocol-native.c | 4 ++-- src/tests/sync-playback.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/polypcore/idxset.c b/src/polypcore/idxset.c index 8d3a2370d..f970ae5e0 100644 --- a/src/polypcore/idxset.c +++ b/src/polypcore/idxset.c @@ -65,7 +65,7 @@ int pa_idxset_string_compare_func(const void *a, const void *b) { } unsigned pa_idxset_trivial_hash_func(const void *p) { - return (unsigned) p; + return (unsigned) (long) p; } int pa_idxset_trivial_compare_func(const void *a, const void *b) { diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index e30ff0671..04fbc3e43 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -476,7 +476,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v uint8_t *response; size_t t, k, s; struct connection *conn; - size_t idx = PA_IDXSET_INVALID; + uint32_t idx = PA_IDXSET_INVALID; unsigned nsamples; assert(c && data && length == sizeof(int)); diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 81d91f0cc..20ba51313 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -799,7 +799,7 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct record_stream *s; - size_t maxlength, fragment_size; + uint32_t maxlength, fragment_size; uint32_t source_index; const char *name, *source_name; pa_sample_spec ss; @@ -1098,7 +1098,7 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct upload_stream *s; - size_t length; + uint32_t length; const char *name; pa_sample_spec ss; pa_channel_map map; diff --git a/src/tests/sync-playback.c b/src/tests/sync-playback.c index 4ac65c2f4..d675e01cc 100644 --- a/src/tests/sync-playback.c +++ b/src/tests/sync-playback.c @@ -64,7 +64,7 @@ static const pa_buffer_attr buffer_attr = { static void nop_free_cb(void *p) {} static void underflow_cb(struct pa_stream *s, void *userdata) { - int i = (int) userdata; + int i = (int) (long) userdata; fprintf(stderr, "Stream %i finished\n", i); @@ -86,7 +86,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_READY: { - int r, i = (int) userdata; + int r, i = (int) (long) userdata; fprintf(stderr, "Writing data to stream %i.\n", i); @@ -136,7 +136,7 @@ static void context_state_callback(pa_context *c, void *userdata) { streams[i] = pa_stream_new(c, name, &sample_spec, NULL); assert(streams[i]); - pa_stream_set_state_callback(streams[i], stream_state_callback, (void*) i); + pa_stream_set_state_callback(streams[i], stream_state_callback, (void*) (long) i); pa_stream_connect_playback(streams[i], NULL, &buffer_attr, PA_STREAM_START_CORKED, NULL, i == 0 ? NULL : streams[0]); } From e8b3819ac87e96e6ad3442ca29eaecb1c57efcc4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 27 Feb 2006 09:18:18 +0000 Subject: [PATCH 0519/1514] Catch volume update events. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@612 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 94fa6d8c5..12d6719ed 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -219,8 +219,20 @@ static void io_callback(pa_iochannel *io, void*userdata) { static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { struct userdata *u = userdata; - assert(u); + pa_cvolume old_vol; + + assert(u && u->sink && u->sink->get_hw_volume); + do_write(u); + + memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)); + if (u->sink->get_hw_volume(u->sink) < 0) + return; + if (memcmp(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)) != 0) { + pa_subscription_post(u->sink->core, + PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, + u->sink->index); + } } static pa_usec_t sink_get_latency_cb(pa_sink *s) { From 4756d186ab461322470a57b0f1e8ca5fdd4eb6fb Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 27 Feb 2006 09:20:25 +0000 Subject: [PATCH 0520/1514] We have both sink and source in this module. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@613 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 12d6719ed..9f93f9d88 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -221,17 +221,32 @@ static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void struct userdata *u = userdata; pa_cvolume old_vol; - assert(u && u->sink && u->sink->get_hw_volume); + assert(u); do_write(u); - memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)); - if (u->sink->get_hw_volume(u->sink) < 0) - return; - if (memcmp(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)) != 0) { - pa_subscription_post(u->sink->core, - PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, - u->sink->index); + if (u->sink) { + assert(u->sink->get_hw_volume); + memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)); + if (u->sink->get_hw_volume(u->sink) < 0) + return; + if (memcmp(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)) != 0) { + pa_subscription_post(u->sink->core, + PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, + u->sink->index); + } + } + + if (u->source) { + assert(u->source->get_hw_volume); + memcpy(&old_vol, &u->source->hw_volume, sizeof(pa_cvolume)); + if (u->source->get_hw_volume(u->source) < 0) + return; + if (memcmp(&old_vol, &u->source->hw_volume, sizeof(pa_cvolume)) != 0) { + pa_subscription_post(u->source->core, + PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, + u->source->index); + } } } From 5b9849eaefeab3e87350e9e122502e6d4a1fa246 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 27 Feb 2006 09:21:38 +0000 Subject: [PATCH 0521/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@614 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index a5ab5c427..530a980ce 100644 --- a/doc/todo +++ b/doc/todo @@ -7,7 +7,6 @@ Test: Fixes: - proper use of memcpy in procotol-esound.c so we don't get alignment problems - latency api rework for native protocol -- notification on hw volume change - mute switch support (like ALSA does it) - module-oss-* love: - deal with underflows propely From 76f56ab462e27b69ce5b1094da512de0259b5568 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 27 Feb 2006 09:22:33 +0000 Subject: [PATCH 0522/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@615 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 530a980ce..df13e56f8 100644 --- a/doc/todo +++ b/doc/todo @@ -7,7 +7,6 @@ Test: Fixes: - proper use of memcpy in procotol-esound.c so we don't get alignment problems - latency api rework for native protocol -- mute switch support (like ALSA does it) - module-oss-* love: - deal with underflows propely - improve latency measurement for mmap From 8cf9b972e2bdb888b25506c312a7b44ba0af198c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Mar 2006 14:22:25 +0000 Subject: [PATCH 0523/1514] protocol changes for new latency API (partial!) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@616 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/memblockq.c | 1 - src/polypcore/protocol-native.c | 10 ++++------ src/polypcore/tagstruct.c | 34 +++++++++++++++++++++++++++++++-- src/polypcore/tagstruct.h | 3 +++ 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/polypcore/memblockq.c b/src/polypcore/memblockq.c index 38403ec2a..517495ebb 100644 --- a/src/polypcore/memblockq.c +++ b/src/polypcore/memblockq.c @@ -547,7 +547,6 @@ void pa_memblockq_flush(pa_memblockq *bq) { drop_block(bq, bq->blocks); assert(bq->n_blocks == 0); - bq->write_index = bq->read_index; pa_memblockq_prebuf_force(bq); } diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 20ba51313..76761b732 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -1031,13 +1031,11 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct *reply; struct playback_stream *s; struct timeval tv, now; - uint64_t counter; uint32_t idx; assert(c && t); if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_timeval(t, &tv) < 0 || - pa_tagstruct_getu64(t, &counter) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1057,7 +1055,8 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct_put_timeval(reply, &tv); pa_gettimeofday(&now); pa_tagstruct_put_timeval(reply, &now); - pa_tagstruct_putu64(reply, counter); + pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq)); + pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq)); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1066,13 +1065,11 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN pa_tagstruct *reply; struct record_stream *s; struct timeval tv, now; - uint64_t counter; uint32_t idx; assert(c && t); if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_timeval(t, &tv) < 0 || - pa_tagstruct_getu64(t, &counter) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; @@ -1091,7 +1088,8 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN pa_tagstruct_put_timeval(reply, &tv); pa_gettimeofday(&now); pa_tagstruct_put_timeval(reply, &now); - pa_tagstruct_putu64(reply, counter); + pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq)); + pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq)); pa_pstream_send_tagstruct(c->pstream, reply); } diff --git a/src/polypcore/tagstruct.c b/src/polypcore/tagstruct.c index 1f5f370bf..3035626ba 100644 --- a/src/polypcore/tagstruct.c +++ b/src/polypcore/tagstruct.c @@ -189,6 +189,18 @@ void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) { t->length += 9; } +void pa_tagstruct_puts64(pa_tagstruct*t, int64_t u) { + uint32_t tmp; + assert(t); + extend(t, 9); + t->data[t->length] = PA_TAG_S64; + tmp = htonl((uint32_t) ((uint64_t) u >> 32)); + memcpy(t->data+t->length+1, &tmp, 4); + tmp = htonl((uint32_t) ((uint64_t) u)); + memcpy(t->data+t->length+5, &tmp, 4); + t->length += 9; +} + void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) { unsigned i; @@ -399,9 +411,27 @@ int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) { return -1; memcpy(&tmp, t->data+t->rindex+1, 4); - *u = (pa_usec_t) ntohl(tmp) << 32; + *u = (uint64_t) ntohl(tmp) << 32; memcpy(&tmp, t->data+t->rindex+5, 4); - *u |= (pa_usec_t) ntohl(tmp); + *u |= (uin64_t) ntohl(tmp); + t->rindex +=9; + return 0; +} + +int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *u) { + uint32_t tmp; + assert(t && u); + + if (t->rindex+9 > t->length) + return -1; + + if (t->data[t->rindex] != PA_TAG_S64) + return -1; + + memcpy(&tmp, t->data+t->rindex+1, 4); + *u = (int64_t) ((uint64_t) ntohl(tmp) << 32); + memcpy(&tmp, t->data+t->rindex+5, 4); + *u |= (int64_t) ntohl(tmp); t->rindex +=9; return 0; } diff --git a/src/polypcore/tagstruct.h b/src/polypcore/tagstruct.h index 0ed751710..d5e6050b6 100644 --- a/src/polypcore/tagstruct.h +++ b/src/polypcore/tagstruct.h @@ -40,6 +40,7 @@ enum { PA_TAG_U32 = 'L', PA_TAG_U8 = 'B', PA_TAG_U64 = 'R', + PA_TAG_S64 = 'r', PA_TAG_SAMPLE_SPEC = 'a', PA_TAG_ARBITRARY = 'x', PA_TAG_BOOLEAN_TRUE = '1', @@ -64,6 +65,7 @@ void pa_tagstruct_puts(pa_tagstruct*t, const char *s); void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c); void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i); void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t i); +void pa_tagstruct_puts64(pa_tagstruct*t, int64_t i); void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss); void pa_tagstruct_put_arbitrary(pa_tagstruct*t, const void *p, size_t length); void pa_tagstruct_put_boolean(pa_tagstruct*t, int b); @@ -78,6 +80,7 @@ int pa_tagstruct_gets(pa_tagstruct*t, const char **s); int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c); int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i); int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *i); +int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *i); int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss); int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length); int pa_tagstruct_get_boolean(pa_tagstruct *t, int *b); From 7f04568444a10ae96f98787d9309cdbaed8a171b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 2 Mar 2006 14:46:31 +0000 Subject: [PATCH 0524/1514] typo fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@617 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/tagstruct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polypcore/tagstruct.c b/src/polypcore/tagstruct.c index 3035626ba..761f6d3d6 100644 --- a/src/polypcore/tagstruct.c +++ b/src/polypcore/tagstruct.c @@ -413,7 +413,7 @@ int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) { memcpy(&tmp, t->data+t->rindex+1, 4); *u = (uint64_t) ntohl(tmp) << 32; memcpy(&tmp, t->data+t->rindex+5, 4); - *u |= (uin64_t) ntohl(tmp); + *u |= (uint64_t) ntohl(tmp); t->rindex +=9; return 0; } From 6cc11fbfc3094cdda5502ef9374104f1d481ab71 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 2 Mar 2006 16:32:36 +0000 Subject: [PATCH 0525/1514] Handle the new latency protocol. This is just a quick fix and does not handle the new memblockq system. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@618 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 1 + src/polyp/def.h | 2 ++ src/polyp/internal.h | 3 +++ src/polyp/stream.c | 24 ++++++++++++++++++++++-- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 01ec9ef7a..a65938efe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -346,6 +346,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ polypcore/conf-parser.c polypcore/conf-parser.h \ polypcore/dynarray.c polypcore/dynarray.h \ polypcore/gccmacro.h \ + polypcore/hashmap.c polypcore/hashmap.h \ polypcore/idxset.c polypcore/idxset.h \ polypcore/iochannel.c polypcore/iochannel.h \ polypcore/log.c polypcore/log.h \ diff --git a/src/polyp/def.h b/src/polyp/def.h index 0d095e9ad..426a0c9ba 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -195,6 +195,8 @@ typedef struct pa_latency_info { * 0.5 */ struct timeval timestamp; /**< The time when this latency info was current */ uint64_t counter; /**< The byte counter current when the latency info was requested. \since 0.6 */ + int64_t write_index; /**< Current absolute write index in the buffer. \since 0.8 */ + int64_t read_index; /**< Current absolute read index in the buffer. \since 0.8 */ } pa_latency_info; /** A structure for the spawn api. This may be used to integrate auto diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 2e4d859ac..1443f7a8d 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -37,6 +37,7 @@ #include #include #include +#include #include "client-conf.h" @@ -104,6 +105,8 @@ struct pa_stream { pa_memchunk peek_memchunk; pa_memblockq *record_memblockq; + pa_hashmap *counter_hashmap; + int interpolate; int corked; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 8bdb90590..3ac026f1f 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -33,10 +33,12 @@ #include #include #include +#include #include "internal.h" #define LATENCY_IPOL_INTERVAL_USEC (10000L) +#define COUNTER_HASHMAP_MAXSIZE (5) pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) { pa_stream *s; @@ -85,6 +87,8 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->record_memblockq = NULL; + s->counter_hashmap = pa_hashmap_new(NULL, NULL); + s->counter = 0; s->previous_time = 0; s->previous_ipol_time = 0; @@ -102,6 +106,10 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * return pa_stream_ref(s); } +static void hashmap_free_func(void *p, void *userdata) { + pa_xfree(p); +} + static void stream_free(pa_stream *s) { assert(s); @@ -116,6 +124,9 @@ static void stream_free(pa_stream *s) { if (s->record_memblockq) pa_memblockq_free(s->record_memblockq); + if (s->counter_hashmap) + pa_hashmap_free(s->counter_hashmap, hashmap_free_func, NULL); + pa_xfree(s->name); pa_xfree(s); } @@ -618,6 +629,9 @@ static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, assert(o->stream); assert(o->context); + i.counter = *(uint64_t*)pa_hashmap_get(o->stream->counter_hashmap, (void*)tag); + pa_xfree(pa_hashmap_remove(o->stream->counter_hashmap, (void*)tag)); + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; @@ -629,7 +643,8 @@ static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_getu32(t, &i.queue_length) < 0 || pa_tagstruct_get_timeval(t, &local) < 0 || pa_tagstruct_get_timeval(t, &remote) < 0 || - pa_tagstruct_getu64(t, &i.counter) < 0 || + pa_tagstruct_gets64(t, &i.write_index) < 0 || + pa_tagstruct_gets64(t, &i.read_index) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; @@ -679,12 +694,14 @@ pa_operation* pa_stream_get_latency_info(pa_stream *s, pa_stream_get_latency_inf pa_operation *o; pa_tagstruct *t; struct timeval now; + uint64_t *counter; assert(s); assert(s->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, pa_hashmap_size(s->counter_hashmap) < COUNTER_HASHMAP_MAXSIZE, PA_ERR_INTERNAL); o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); @@ -696,11 +713,14 @@ pa_operation* pa_stream_get_latency_info(pa_stream *s, pa_stream_get_latency_inf pa_gettimeofday(&now); pa_tagstruct_put_timeval(t, &now); - pa_tagstruct_putu64(t, s->counter); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_info_callback, o); + counter = pa_xmalloc(sizeof(uint64_t)); + *counter = s->counter; + pa_hashmap_put(s->counter_hashmap, (void*)tag, counter); + return pa_operation_ref(o); } From 50268e0dd06f92da3d25137b78ddfa438e4d62de Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 2 Mar 2006 16:37:35 +0000 Subject: [PATCH 0526/1514] Fix warnings on 64-bit systems. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@619 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 3ac026f1f..1257f7e62 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -629,8 +629,8 @@ static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, assert(o->stream); assert(o->context); - i.counter = *(uint64_t*)pa_hashmap_get(o->stream->counter_hashmap, (void*)tag); - pa_xfree(pa_hashmap_remove(o->stream->counter_hashmap, (void*)tag)); + i.counter = *(uint64_t*)pa_hashmap_get(o->stream->counter_hashmap, (void*)(unsigned long)tag); + pa_xfree(pa_hashmap_remove(o->stream->counter_hashmap, (void*)(unsigned long)tag)); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -719,7 +719,7 @@ pa_operation* pa_stream_get_latency_info(pa_stream *s, pa_stream_get_latency_inf counter = pa_xmalloc(sizeof(uint64_t)); *counter = s->counter; - pa_hashmap_put(s->counter_hashmap, (void*)tag, counter); + pa_hashmap_put(s->counter_hashmap, (void*)(unsigned long)tag, counter); return pa_operation_ref(o); } From fbaaf5acb7b391c605585971dac2b417b55f1100 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 2 Mar 2006 16:40:23 +0000 Subject: [PATCH 0527/1514] The tag argument is no longer unused. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@620 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 1257f7e62..ab6ab4089 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -619,7 +619,7 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us return pa_operation_ref(o); } -static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; pa_latency_info i, *p = NULL; struct timeval local, remote, now; From bc97b29447bf5c9932ceccb665fa57dd7f654b36 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 2 Mar 2006 21:56:15 +0000 Subject: [PATCH 0528/1514] Negotiate protocol version between server and client. Will allow smoother protocol modifications in the future. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@621 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 1 + src/polyp/context.c | 25 +++++++++++++++++++++++++ src/polyp/context.h | 6 ++++++ src/polyp/def.h | 1 + src/polyp/error.c | 1 + src/polyp/internal.h | 1 + src/polyp/version.h.in | 4 ++++ src/polypcore/protocol-native.c | 19 ++++++++++++++++--- 8 files changed, 55 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 25a89edc0..a0b16573b 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,7 @@ AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) AC_SUBST(PA_API_VERSION, 8) +AC_SUBST(PA_PROTOCOL_VERSION, 8) if type -p stow > /dev/null && test -d /usr/local/stow ; then AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) diff --git a/src/polyp/context.c b/src/polyp/context.c index 59079cb07..845e88d9a 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -354,6 +354,19 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t switch(c->state) { case PA_CONTEXT_AUTHORIZING: { pa_tagstruct *reply; + + if (pa_tagstruct_getu32(t, &c->version) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + /* Minimum supported version */ + if (c->version < 8) { + pa_context_fail(c, PA_ERR_VERSION); + goto finish; + } + reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); pa_tagstruct_puts(reply, c->name); pa_pstream_send_tagstruct(c->pstream, reply); @@ -400,6 +413,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) { } t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); + pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); pa_pstream_send_tagstruct_with_creds(c->pstream, t, 1); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); @@ -936,6 +950,17 @@ const char* pa_context_get_server(pa_context *c) { return c->server; } +uint32_t pa_context_get_protocol_version(pa_context *c) { + return PA_PROTOCOL_VERSION; +} + +uint32_t pa_context_get_server_protocol_version(pa_context *c) { + assert(c); + assert(c->ref >= 1); + + return c->version; +} + pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) { pa_tagstruct *t; diff --git a/src/polyp/context.h b/src/polyp/context.h index 73bcb698a..89febe92c 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -115,6 +115,12 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su /** Return the server name this context is connected to. \since 0.7 */ const char* pa_context_get_server(pa_context *c); +/** Return the protocol version of the library. \since 0.8 */ +uint32_t pa_context_get_protocol_version(pa_context *c); + +/** Return the protocol version of the connected server. \since 0.8 */ +uint32_t pa_context_get_server_protocol_version(pa_context *c); + PA_C_DECL_END #endif diff --git a/src/polyp/def.h b/src/polyp/def.h index 426a0c9ba..98420bc08 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -125,6 +125,7 @@ enum { PA_ERR_MODINITFAILED, /**< Module initialization failed */ PA_ERR_BADSTATE, /**< Bad state */ PA_ERR_NODATA, /**< No data */ + PA_ERR_VERSION, /**< Incompatible protocol version \since 0.8 */ PA_ERR_MAX /**< Not really an error but the first invalid error code */ }; diff --git a/src/polyp/error.c b/src/polyp/error.c index eff37cc86..3f3e637f9 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -48,6 +48,7 @@ static const char* const errortab[PA_ERR_MAX] = { [PA_ERR_MODINITFAILED] = "Module initalization failed", [PA_ERR_BADSTATE] = "Bad state", [PA_ERR_NODATA] = "No data", + [PA_ERR_VERSION] = "Incompatible protocol version", }; const char*pa_strerror(int error) { diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 1443f7a8d..82d8f7ce6 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -57,6 +57,7 @@ struct pa_context { PA_LLIST_HEAD(pa_stream, streams); PA_LLIST_HEAD(pa_operation, operations); + uint32_t version; uint32_t ctag; uint32_t csyncid; uint32_t error; diff --git a/src/polyp/version.h.in b/src/polyp/version.h.in index 67b7495b8..de7b9c1c0 100644 --- a/src/polyp/version.h.in +++ b/src/polyp/version.h.in @@ -44,6 +44,10 @@ const char* pa_get_library_version(void); * PA_API_VERSION undefined. */ #define PA_API_VERSION @PA_API_VERSION@ +/** The current protocol version. Version 8 relates to polypaudio 0.8. + * \since 0.8 */ +#define PA_PROTOCOL_VERSION @PA_PROTOCOL_VERSION@ + PA_C_DECL_END #endif diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 76761b732..68dc63667 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -29,6 +29,8 @@ #include #include +#include + #include #include #include @@ -111,6 +113,7 @@ enum { struct connection { int authorized; + uint32_t version; pa_protocol_native *protocol; pa_client *client; pa_pstream *pstream; @@ -866,14 +869,22 @@ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; const void*cookie; + pa_tagstruct *reply; assert(c && t); - if (pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 || + if (pa_tagstruct_getu32(t, &c->version) < 0 || + pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } + /* Minimum supported version */ + if (c->version < 8) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION); + return; + } + if (!c->authorized) { int success = 0; @@ -915,8 +926,10 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t c->auth_timeout_event = NULL; } } - - pa_pstream_send_simple_ack(c->pstream, tag); + + reply = reply_new(tag); + pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION); + pa_pstream_send_tagstruct(c->pstream, reply); } static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { From 4e522940ff39b97f278309d4f1ca36ceb3ec73b3 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 4 Mar 2006 13:55:40 +0000 Subject: [PATCH 0529/1514] Alignment safe protocol handling in esound module. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@622 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 302 ++++++++++++++++++-------------- 1 file changed, 175 insertions(+), 127 deletions(-) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 04fbc3e43..08b7c6f71 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -221,24 +221,33 @@ static void connection_free(struct connection *c) { pa_xfree(c); } -static void* connection_write(struct connection *c, size_t length) { - size_t t, i; +static void connection_write_prepare(struct connection *c, size_t length) { + size_t t; + assert(c); + + t = c->write_data_length+length; + + if (c->write_data_alloc < t) + c->write_data = pa_xrealloc(c->write_data, c->write_data_alloc = t); + + assert(c->write_data); +} + +static void connection_write(struct connection *c, const void *data, size_t length) { + size_t i; assert(c); assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 1); - t = c->write_data_length+length; - - if (c->write_data_alloc < t) - c->write_data = pa_xrealloc(c->write_data, c->write_data_alloc = t); + connection_write_prepare(c, length); assert(c->write_data); i = c->write_data_length; c->write_data_length += length; - return (uint8_t*) c->write_data+i; + memcpy((char*)c->write_data + i, data, length); } static void format_esd2native(int format, int swap_bytes, pa_sample_spec *ss) { @@ -271,7 +280,8 @@ static int format_native2esd(pa_sample_spec *ss) { static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { uint32_t ekey; - int *ok; + int ok; + assert(length == (ESD_KEY_LEN + sizeof(uint32_t))); if (!c->authorized) { @@ -286,8 +296,10 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req c->auth_timeout_event = NULL; } } - - ekey = *(const uint32_t*)((const uint8_t*) data+ESD_KEY_LEN); + + data = (char*)data + ESD_KEY_LEN; + + memcpy(&ekey, data, sizeof(uint32_t)); if (ekey == ESD_ENDIAN_KEY) c->swap_byte_order = 0; else if (ekey == ESD_SWAP_ENDIAN_KEY) @@ -297,22 +309,27 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req return -1; } - ok = connection_write(c, sizeof(int)); - assert(ok); - *ok = 1; + ok = 1; + connection_write(c, &ok, sizeof(int)); return 0; } static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { char name[ESD_NAME_MAX]; - int format, rate; + int32_t format, rate; pa_sink *sink; pa_sample_spec ss; size_t l; - assert(c && length == (sizeof(int)*2+ESD_NAME_MAX)); + + assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX)); - format = MAYBE_INT32_SWAP(c->swap_byte_order, *(const int*)data); - rate = MAYBE_INT32_SWAP(c->swap_byte_order, *((const int*)data + 1)); + memcpy(&format, data, sizeof(int32_t)); + format = MAYBE_INT32_SWAP(c->swap_byte_order, format); + data = (char*)data + sizeof(int32_t); + + memcpy(&rate, (char*)data, sizeof(int32_t)); + rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); + data = (char*)data + sizeof(int32_t); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -321,7 +338,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1); CHECK_VALIDITY(sink, "No such sink"); - strncpy(name, (const char*) data + sizeof(int)*2, sizeof(name)); + strncpy(name, data, sizeof(name)); name[sizeof(name)-1] = 0; pa_client_set_name(c->client, name); @@ -362,14 +379,20 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length) { char name[ESD_NAME_MAX]; - int format, rate; + int32_t format, rate; pa_source *source; pa_sample_spec ss; size_t l; - assert(c && length == (sizeof(int)*2+ESD_NAME_MAX)); + + assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX)); - format = MAYBE_INT32_SWAP(c->swap_byte_order, *(const int*)data); - rate = MAYBE_INT32_SWAP(c->swap_byte_order, *((const int*)data + 1)); + memcpy(&format, data, sizeof(int32_t)); + format = MAYBE_INT32_SWAP(c->swap_byte_order, format); + data = (char*)data + sizeof(int32_t); + + memcpy(&rate, (char*)data, sizeof(int32_t)); + rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); + data = (char*)data + sizeof(int32_t); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -397,7 +420,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co } } - strncpy(name, (const char*) data + sizeof(int)*2, sizeof(name)); + strncpy(name, data, sizeof(name)); name[sizeof(name)-1] = 0; pa_client_set_name(c->client, name); @@ -437,7 +460,8 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co static int esd_proto_get_latency(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { pa_sink *sink; - int latency, *lag; + int32_t latency; + assert(c && !data && length == 0); if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) @@ -447,28 +471,32 @@ static int esd_proto_get_latency(struct connection *c, PA_GCC_UNUSED esd_proto_t latency = (int) ((usec*44100)/1000000); } - lag = connection_write(c, sizeof(int)); - assert(lag); - *lag = MAYBE_INT32_SWAP(c->swap_byte_order, latency); + latency = MAYBE_INT32_SWAP(c->swap_byte_order, latency); + connection_write(c, &latency, sizeof(int32_t)); return 0; } static int esd_proto_server_info(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { - int rate = 44100, format = ESD_STEREO|ESD_BITS16; - int *response; + int32_t rate = 44100, format = ESD_STEREO|ESD_BITS16; + int32_t response; pa_sink *sink; - assert(c && data && length == sizeof(int)); + + assert(c && data && length == sizeof(int32_t)); if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { rate = sink->sample_spec.rate; format = format_native2esd(&sink->sample_spec); } - - response = connection_write(c, sizeof(int)*3); - assert(response); - *(response++) = 0; - *(response++) = MAYBE_INT32_SWAP(c->swap_byte_order, rate); - *(response++) = MAYBE_INT32_SWAP(c->swap_byte_order, format); + + connection_write_prepare(c, sizeof(int32_t) * 3); + + response = 0; + connection_write(c, &response, sizeof(int32_t)); + rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); + connection_write(c, &rate, sizeof(int32_t)); + format = MAYBE_INT32_SWAP(c->swap_byte_order, format); + connection_write(c, &format, sizeof(int32_t)); + return 0; } @@ -478,24 +506,30 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v struct connection *conn; uint32_t idx = PA_IDXSET_INVALID; unsigned nsamples; - assert(c && data && length == sizeof(int)); + char terminator[sizeof(int32_t)*6+ESD_NAME_MAX]; + + assert(c && data && length == sizeof(int32_t)); if (esd_proto_server_info(c, request, data, length) < 0) return -1; - k = sizeof(int)*5+ESD_NAME_MAX; - s = sizeof(int)*6+ESD_NAME_MAX; + k = sizeof(int32_t)*5+ESD_NAME_MAX; + s = sizeof(int32_t)*6+ESD_NAME_MAX; nsamples = c->protocol->core->scache ? pa_idxset_size(c->protocol->core->scache) : 0; - response = connection_write(c, (t = s*(nsamples+1) + k*(c->protocol->n_player+1))); - assert(k); + t = s*(nsamples+1) + k*(c->protocol->n_player+1); + + connection_write_prepare(c, t); + + memset(terminator, 0, sizeof(terminator)); for (conn = pa_idxset_first(c->protocol->connections, &idx); conn; conn = pa_idxset_next(c->protocol->connections, &idx)) { - int format = ESD_BITS16 | ESD_STEREO, rate = 44100, lvolume = ESD_VOLUME_BASE, rvolume = ESD_VOLUME_BASE; + int32_t id, format = ESD_BITS16 | ESD_STEREO, rate = 44100, lvolume = ESD_VOLUME_BASE, rvolume = ESD_VOLUME_BASE; + char name[ESD_NAME_MAX]; if (conn->state != ESD_STREAMING_DATA) continue; - assert(t >= s+k+k); + assert(t >= k*2+s); if (conn->sink_input) { rate = conn->sink_input->sample_spec.rate; @@ -505,137 +539,152 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v } /* id */ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, (int) (conn->index+1)); - response += sizeof(int); + id = MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) (conn->index+1)); + connection_write(c, &id, sizeof(int32_t)); /* name */ assert(conn->client); - strncpy((char*) response, conn->client->name, ESD_NAME_MAX); - response += ESD_NAME_MAX; + strncpy(name, conn->client->name, ESD_NAME_MAX); + connection_write(c, name, ESD_NAME_MAX); /* rate */ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, rate); - response += sizeof(int); + rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); + connection_write(c, &rate, sizeof(int32_t)); /* left */ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, lvolume); - response += sizeof(int); + lvolume = MAYBE_INT32_SWAP(c->swap_byte_order, lvolume); + connection_write(c, &lvolume, sizeof(int32_t)); /*right*/ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, rvolume); - response += sizeof(int); + rvolume = MAYBE_INT32_SWAP(c->swap_byte_order, rvolume); + connection_write(c, &rvolume, sizeof(int32_t)); /*format*/ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, format); - response += sizeof(int); + format = MAYBE_INT32_SWAP(c->swap_byte_order, format); + connection_write(c, &format, sizeof(int32_t)); - t-= k; + t -= k; } assert(t == s*(nsamples+1)+k); - memset(response, 0, k); response += k; t -= k; + connection_write(c, terminator, k); + if (nsamples) { pa_scache_entry *ce; idx = PA_IDXSET_INVALID; for (ce = pa_idxset_first(c->protocol->core->scache, &idx); ce; ce = pa_idxset_next(c->protocol->core->scache, &idx)) { + int32_t id, rate, lvolume, rvolume, format, len; + char name[ESD_NAME_MAX]; + assert(t >= s*2); - + /* id */ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1)); - response += sizeof(int); + id = MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1)); + connection_write(c, &id, sizeof(int32_t)); /* name */ if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0) - strncpy((char*) response, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX); + strncpy(name, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX); else - snprintf((char*) response, ESD_NAME_MAX, "native.%s", ce->name); - response += ESD_NAME_MAX; + snprintf(name, ESD_NAME_MAX, "native.%s", ce->name); + connection_write(c, name, ESD_NAME_MAX); /* rate */ - *((uint32_t*) response) = MAYBE_UINT32_SWAP(c->swap_byte_order, ce->sample_spec.rate); - response += sizeof(int); + rate = MAYBE_UINT32_SWAP(c->swap_byte_order, ce->sample_spec.rate); + connection_write(c, &rate, sizeof(int32_t)); /* left */ - *((uint32_t*) response) = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); - response += sizeof(int); + lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + connection_write(c, &lvolume, sizeof(int32_t)); /*right*/ - *((uint32_t*) response) = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); - response += sizeof(int); + rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + connection_write(c, &rvolume, sizeof(int32_t)); /*format*/ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ce->sample_spec)); - response += sizeof(int); + format = MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ce->sample_spec)); + connection_write(c, &format, sizeof(int32_t)); /*length*/ - *((int*) response) = MAYBE_INT32_SWAP(c->swap_byte_order, (int) ce->memchunk.length); - response += sizeof(int); + len = MAYBE_INT32_SWAP(c->swap_byte_order, (int) ce->memchunk.length); + connection_write(c, &len, sizeof(int32_t)); t -= s; } } assert(t == s); - memset(response, 0, s); + + connection_write(c, terminator, s); return 0; } static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { - int *ok; - uint32_t idx; - pa_volume_t lvolume, rvolume; + int32_t ok; + uint32_t idx, lvolume, rvolume; struct connection *conn; - assert(c && data && length == sizeof(int)*3); - - idx = MAYBE_UINT32_SWAP(c->swap_byte_order, *(const uint32_t*)data)-1; - lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, *((const uint32_t*)data + 1)); - lvolume = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; - rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, *((const uint32_t*)data + 2)); - rvolume = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; - ok = connection_write(c, sizeof(int)); - assert(ok); + assert(c && data && length == sizeof(int32_t)*3); + + memcpy(&idx, data, sizeof(uint32_t)); + idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1; + data = (char*)data + sizeof(uint32_t); + + memcpy(&lvolume, data, sizeof(uint32_t)); + lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, lvolume); + data = (char*)data + sizeof(uint32_t); + + memcpy(&rvolume, data, sizeof(uint32_t)); + rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume); + data = (char*)data + sizeof(uint32_t); if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx))) { assert(conn->sink_input); - conn->sink_input->volume.values[0] = lvolume; - conn->sink_input->volume.values[1] = rvolume; + conn->sink_input->volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; + conn->sink_input->volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; conn->sink_input->volume.channels = 2; - *ok = 1; + ok = 1; } else - *ok = 0; + ok = 0; + + connection_write(c, &ok, sizeof(int32_t)); return 0; } static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { pa_sample_spec ss; - int format, rate; - size_t sc_length; + int32_t format, rate, sc_length; uint32_t idx; - int *ok; char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1]; - assert(c && data && length == (ESD_NAME_MAX+3*sizeof(int))); - format = MAYBE_INT32_SWAP(c->swap_byte_order, *(const int*)data); - rate = MAYBE_INT32_SWAP(c->swap_byte_order, *((const int*)data + 1)); + assert(c && data && length == (ESD_NAME_MAX+3*sizeof(int32_t))); + + memcpy(&format, data, sizeof(int32_t)); + format = MAYBE_INT32_SWAP(c->swap_byte_order, format); + data = (char*)data + sizeof(int32_t); + + memcpy(&rate, (char*)data + sizeof(int32_t), sizeof(int32_t)); + rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); + data = (char*)data + sizeof(int32_t); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification."); - - sc_length = (size_t) MAYBE_INT32_SWAP(c->swap_byte_order, (*((const int*)data + 2))); + + memcpy(&sc_length, data, sizeof(int32_t)); + sc_length = MAYBE_INT32_SWAP(c->swap_byte_order, sc_length); CHECK_VALIDITY(sc_length <= MAX_CACHE_SAMPLE_SIZE, "Sample too large."); strcpy(name, SCACHE_PREFIX); - strncpy(name+sizeof(SCACHE_PREFIX)-1, (const char*) data+3*sizeof(int), ESD_NAME_MAX); + strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX); name[sizeof(name)-1] = 0; assert(!c->scache.memchunk.memblock); @@ -650,47 +699,43 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, &idx); - ok = connection_write(c, sizeof(int)); - assert(ok); - - *ok = idx+1; + idx += 1; + connection_write(c, &idx, sizeof(uint32_t)); return 0; } static int esd_proto_sample_get_id(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { - int *ok; + int32_t ok; uint32_t idx; char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1]; + assert(c && data && length == ESD_NAME_MAX); - ok = connection_write(c, sizeof(int)); - assert(ok); - - *ok = -1; - strcpy(name, SCACHE_PREFIX); strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX); name[sizeof(name)-1] = 0; + ok = -1; if ((idx = pa_scache_get_id_by_name(c->protocol->core, name)) != PA_IDXSET_INVALID) - *ok = (int) idx +1; + ok = idx + 1; + + connection_write(c, &ok, sizeof(int32_t)); return 0; } static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t request, const void *data, size_t length) { - int *ok; + int32_t ok; const char *name; uint32_t idx; - assert(c && data && length == sizeof(int)); - idx = (uint32_t) MAYBE_INT32_SWAP(c->swap_byte_order, *(const int*)data)-1; + assert(c && data && length == sizeof(int32_t)); - ok = connection_write(c, sizeof(int)); - assert(ok); + memcpy(&idx, data, sizeof(uint32_t)); + idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1; - *ok = 0; + ok = 0; if ((name = pa_scache_get_name_by_id(c->protocol->core, idx))) { if (request == ESD_PROTO_SAMPLE_PLAY) { @@ -698,24 +743,29 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) if (pa_scache_play_item(c->protocol->core, name, sink, NULL) >= 0) - *ok = (int) idx+1; + ok = idx + 1; } else { assert(request == ESD_PROTO_SAMPLE_FREE); if (pa_scache_remove_item(c->protocol->core, name) >= 0) - *ok = (int) idx+1; + ok = idx + 1; } } + connection_write(c, &ok, sizeof(int32_t)); + return 0; } static int esd_proto_standby_or_resume(struct connection *c, PA_GCC_UNUSED esd_proto_t request, PA_GCC_UNUSED const void *data, PA_GCC_UNUSED size_t length) { - int *ok; - ok = connection_write(c, sizeof(int)*2); - assert(ok); - ok[0] = 1; - ok[1] = 1; + int32_t ok; + + connection_write_prepare(c, sizeof(int32_t) * 2); + + ok = 1; + connection_write(c, &ok, sizeof(int32_t)); + connection_write(c, &ok, sizeof(int32_t)); + return 0; } @@ -815,7 +865,6 @@ static int do_read(struct connection *c) { if (c->scache.memchunk.index == c->scache.memchunk.length) { uint32_t idx; - int *ok; c->scache.memchunk.index = 0; pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, &idx); @@ -829,9 +878,8 @@ static int do_read(struct connection *c) { c->state = ESD_NEXT_REQUEST; - ok = connection_write(c, sizeof(int)); - assert(ok); - *ok = idx+1; + idx += 1; + connection_write(c, &idx, sizeof(uint32_t)); } } else if (c->state == ESD_STREAMING_DATA && c->sink_input) { From ad7640b78982b6bed3999164e522f980e4deb3ac Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 4 Mar 2006 13:56:09 +0000 Subject: [PATCH 0530/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@623 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index df13e56f8..d6df239f0 100644 --- a/doc/todo +++ b/doc/todo @@ -5,7 +5,6 @@ Test: - module-tunnel Fixes: -- proper use of memcpy in procotol-esound.c so we don't get alignment problems - latency api rework for native protocol - module-oss-* love: - deal with underflows propely From 45baa6958edccddd7264b11b8d48b5aec69418bf Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 4 Mar 2006 17:31:23 +0000 Subject: [PATCH 0531/1514] Fix warning caused by missing return in main(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@624 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/mcalign-test.c | 2 ++ src/tests/voltest.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index 861c38c1d..eab5dc88e 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -93,4 +93,6 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { if (c.memblock) pa_memblock_unref(c.memblock); + + return 0; } diff --git a/src/tests/voltest.c b/src/tests/voltest.c index 58f1da001..4db8ef285 100644 --- a/src/tests/voltest.c +++ b/src/tests/voltest.c @@ -17,4 +17,6 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f)); } + + return 0; } From dcd202f8eb94ef14981f2b80c7f28a5936ba35a2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 4 Mar 2006 21:30:29 +0000 Subject: [PATCH 0532/1514] Update module-tunnel to the new protocol. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@625 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 70bded6c3..ff1113ccc 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -31,6 +31,8 @@ #include #include +#include + #include #include #include @@ -122,6 +124,7 @@ struct userdata { uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; + uint32_t version; uint32_t ctag; uint32_t device_index; uint32_t channel; @@ -254,7 +257,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G pa_usec_t buffer_usec, sink_usec, source_usec, transport_usec; int playing; uint32_t queue_length; - uint64_t counter; + int64_t write_index, read_index; struct timeval local, remote, now; assert(pd && u); @@ -274,7 +277,8 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G pa_tagstruct_getu32(t, &queue_length) < 0 || pa_tagstruct_get_timeval(t, &local) < 0 || pa_tagstruct_get_timeval(t, &remote) < 0 || - pa_tagstruct_getu64(t, &counter) < 0 || + pa_tagstruct_gets64(t, &write_index) < 0 || + pa_tagstruct_gets64(t, &read_index) < 0 || !pa_tagstruct_eof(t)) { pa_log(__FILE__": invalid reply."); die(u); @@ -323,7 +327,6 @@ static void request_latency(struct userdata *u) { pa_gettimeofday(&now); pa_tagstruct_put_timeval(t, &now); - pa_tagstruct_putu64(t, 0); pa_pstream_send_tagstruct(u->pstream, t); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u); @@ -363,9 +366,14 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t struct userdata *u = userdata; pa_tagstruct *reply; char name[256], un[128], hn[128]; +#ifdef TUNNEL_SINK + pa_cvolume volume; +#endif assert(pd && u && u->pdispatch == pd); - if (command != PA_COMMAND_REPLY || !pa_tagstruct_eof(t)) { + if (command != PA_COMMAND_REPLY || + pa_tagstruct_getu32(t, &u->version) < 0 || + !pa_tagstruct_eof(t)) { if (command == PA_COMMAND_ERROR) pa_log(__FILE__": failed to authenticate"); else @@ -373,6 +381,14 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t die(u); return; } + + /* Minimum supported protocol version */ + if (u->version < 8) { + pa_log(__FILE__": incompatible protocol version"); + die(u); + return; + } + #ifdef TUNNEL_SINK snprintf(name, sizeof(name), "Tunnel from host '%s', user '%s', sink '%s'", pa_get_host_name(hn, sizeof(hn)), @@ -398,6 +414,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct_putu32(reply, tag = u->ctag++); pa_tagstruct_puts(reply, name); pa_tagstruct_put_sample_spec(reply, &u->sink->sample_spec); + pa_tagstruct_put_channel_map(reply, &u->sink->channel_map); pa_tagstruct_putu32(reply, PA_INVALID_INDEX); pa_tagstruct_puts(reply, u->sink_name); pa_tagstruct_putu32(reply, DEFAULT_MAXLENGTH); @@ -405,12 +422,15 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct_putu32(reply, DEFAULT_TLENGTH); pa_tagstruct_putu32(reply, DEFAULT_PREBUF); pa_tagstruct_putu32(reply, DEFAULT_MINREQ); - pa_tagstruct_putu32(reply, PA_VOLUME_NORM); + pa_tagstruct_putu32(reply, 0); + pa_cvolume_reset(&volume, u->sink->sample_spec.channels); + pa_tagstruct_put_cvolume(reply, &volume); #else pa_tagstruct_putu32(reply, PA_COMMAND_CREATE_RECORD_STREAM); pa_tagstruct_putu32(reply, tag = u->ctag++); pa_tagstruct_puts(reply, name); pa_tagstruct_put_sample_spec(reply, &u->source->sample_spec); + pa_tagstruct_put_channel_map(reply, &u->source->channel_map); pa_tagstruct_putu32(reply, PA_INVALID_INDEX); pa_tagstruct_puts(reply, u->source_name); pa_tagstruct_putu32(reply, DEFAULT_MAXLENGTH); @@ -483,6 +503,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_AUTH); pa_tagstruct_putu32(t, tag = u->ctag++); + pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, u->auth_cookie, sizeof(u->auth_cookie)); pa_pstream_send_tagstruct(u->pstream, t); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, u); From 7b6a9c3829fe17dc836a3220bff1f9b4e35d3a57 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 5 Mar 2006 15:42:37 +0000 Subject: [PATCH 0533/1514] Tried to get the volume information even upon init failure. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@626 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 8 ++++---- src/modules/module-alsa-source.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 732612ef1..0053acd2b 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -409,16 +409,16 @@ int pa__init(pa_core *c, pa_module*m) { u->memchunk.index = u->memchunk.length = 0; ret = 0; - -finish: - if (ma) - pa_modargs_free(ma); /* Get initial mixer settings */ if (u->sink->get_hw_volume) u->sink->get_hw_volume(u->sink); if (u->sink->get_hw_mute) u->sink->get_hw_mute(u->sink); + +finish: + if (ma) + pa_modargs_free(ma); return ret; diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 1b7ae7d35..5a6dc1441 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -398,15 +398,15 @@ int pa__init(pa_core *c, pa_module*m) { ret = 0; -finish: - if (ma) - pa_modargs_free(ma); - /* Get initial mixer settings */ if (u->source->get_hw_volume) u->source->get_hw_volume(u->source); if (u->source->get_hw_mute) u->source->get_hw_mute(u->source); + +finish: + if (ma) + pa_modargs_free(ma); return ret; From f22d8ab3fe46e971f40bed21b159cf0c54d05f98 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 5 Mar 2006 18:35:45 +0000 Subject: [PATCH 0534/1514] Return the proper error code so that we get a correct error message. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@627 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index adb6f3f18..c7be47905 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -263,25 +263,25 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 }; assert(pcm_handle && ss && periods && period_size); - if (snd_pcm_hw_params_malloc(&hwparams) < 0 || - snd_pcm_hw_params_any(pcm_handle, hwparams) < 0 || - snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 || - snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[ss->format]) < 0 || - snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL) < 0 || - snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss->channels) < 0 || - (*periods > 0 && snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, periods, NULL) < 0) || - (*period_size > 0 && snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL) < 0) || - snd_pcm_hw_params(pcm_handle, hwparams) < 0) + if ((ret = snd_pcm_hw_params_malloc(&hwparams)) < 0 || + (ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 || + (ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0 || + (ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[ss->format])) < 0 || + (ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0 || + (ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss->channels)) < 0 || + (*periods > 0 && (ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, periods, NULL)) < 0) || + (*period_size > 0 && (ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL)) < 0) || + (ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) goto finish; if (ss->rate != r) pa_log_info(__FILE__": device doesn't support %u Hz, changed to %u Hz.", ss->rate, r); - if (snd_pcm_prepare(pcm_handle) < 0) + if ((ret = snd_pcm_prepare(pcm_handle)) < 0) goto finish; - if (snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size) < 0 || - snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL) < 0) + if ((ret = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size)) < 0 || + (ret = snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL)) < 0) goto finish; assert(buffer_size > 0); From 4e56725a60da8a1c80442ab16f7fe21147b143e9 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 5 Mar 2006 18:37:13 +0000 Subject: [PATCH 0535/1514] It's safer to set buffer size than to try setting number of periods. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@628 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index c7be47905..683db6c06 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -262,6 +262,8 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE, }; assert(pcm_handle && ss && periods && period_size); + + buffer_size = *periods * *period_size; if ((ret = snd_pcm_hw_params_malloc(&hwparams)) < 0 || (ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 || @@ -269,7 +271,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 (ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[ss->format])) < 0 || (ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0 || (ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss->channels)) < 0 || - (*periods > 0 && (ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, periods, NULL)) < 0) || + (*periods > 0 && (ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0) || (*period_size > 0 && (ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL)) < 0) || (ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) goto finish; From 738734244dc6b28d404953e9133f49c518f6a4e0 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 5 Mar 2006 20:18:04 +0000 Subject: [PATCH 0536/1514] Volume support in tunnel module. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@629 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 261 +++++++++++++++++++++++++++++++++++- 1 file changed, 260 insertions(+), 1 deletion(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index ff1113ccc..aa6b69f54 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -91,6 +91,7 @@ static const char* const valid_modargs[] = { }; static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); #ifdef TUNNEL_SINK static void command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); @@ -101,7 +102,8 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = command_request, #endif [PA_COMMAND_PLAYBACK_STREAM_KILLED] = command_stream_killed, - [PA_COMMAND_RECORD_STREAM_KILLED] = command_stream_killed + [PA_COMMAND_RECORD_STREAM_KILLED] = command_stream_killed, + [PA_COMMAND_SUBSCRIBE_EVENT] = command_subscribe_event, }; struct userdata { @@ -189,6 +191,35 @@ static void command_stream_killed(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t comma die(u); } +static void request_info(struct userdata *u); + +static void command_subscribe_event(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + pa_subscription_event_type_t e; + uint32_t idx; + + assert(pd && t && u); + assert(command == PA_COMMAND_SUBSCRIBE_EVENT); + + if (pa_tagstruct_getu32(t, &e) < 0 || + pa_tagstruct_getu32(t, &idx) < 0 || + !pa_tagstruct_eof(t)) { + pa_log(__FILE__": invalid protocol reply"); + die(u); + return; + } + +#ifdef TUNNEL_SINK + if (e != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE)) + return; +#else + if (e != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE)) + return; +#endif + + request_info(u); +} + #ifdef TUNNEL_SINK static void send_prebuf_request(struct userdata *u) { pa_tagstruct *t; @@ -332,6 +363,115 @@ static void request_latency(struct userdata *u) { pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u); } +static void stream_get_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + uint32_t index, owner_module, monitor_source; + pa_usec_t latency; + const char *name, *description, *monitor_source_name, *driver; + int mute; + pa_sample_spec sample_spec; + pa_channel_map channel_map; + pa_cvolume volume; + assert(pd && u); + + if (command != PA_COMMAND_REPLY) { + if (command == PA_COMMAND_ERROR) + pa_log(__FILE__": failed to get info."); + else + pa_log(__FILE__": protocol error."); + die(u); + return; + } + + if (pa_tagstruct_getu32(t, &index) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_gets(t, &description) < 0 || + pa_tagstruct_get_sample_spec(t, &sample_spec) < 0 || + pa_tagstruct_get_channel_map(t, &channel_map) < 0 || + pa_tagstruct_getu32(t, &owner_module) < 0 || + pa_tagstruct_get_cvolume(t, &volume) < 0 || + pa_tagstruct_get_boolean(t, &mute) < 0 || + pa_tagstruct_getu32(t, &monitor_source) < 0 || + pa_tagstruct_gets(t, &monitor_source_name) < 0 || + pa_tagstruct_get_usec(t, &latency) < 0 || + pa_tagstruct_gets(t, &driver) < 0 || + !pa_tagstruct_eof(t)) { + pa_log(__FILE__": invalid reply."); + die(u); + return; + } + +#ifdef TUNNEL_SINK + assert(u->sink); + if ((!!mute == !!u->sink->hw_muted) && + pa_cvolume_equal(&volume, &u->sink->hw_volume)) + return; +#else + assert(u->source); + if ((!!mute == !!u->source->hw_muted) && + pa_cvolume_equal(&volume, &u->source->hw_volume)) + return; +#endif + +#ifdef TUNNEL_SINK + memcpy(&u->sink->hw_volume, &volume, sizeof(pa_cvolume)); + u->sink->hw_muted = !!mute; + + pa_subscription_post(u->sink->core, + PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, + u->sink->index); +#else + memcpy(&u->source->hw_volume, &volume, sizeof(pa_cvolume)); + u->source->hw_muted = !!mute; + + pa_subscription_post(u->source->core, + PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, + u->source->index); +#endif +} + +static void request_info(struct userdata *u) { + pa_tagstruct *t; + uint32_t tag; + assert(u); + + t = pa_tagstruct_new(NULL, 0); +#ifdef TUNNEL_SINK + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); +#else + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); +#endif + pa_tagstruct_putu32(t, tag = u->ctag++); + + pa_tagstruct_putu32(t, PA_INVALID_INDEX); +#ifdef TUNNEL_SINK + pa_tagstruct_puts(t, u->sink_name); +#else + pa_tagstruct_puts(t, u->source_name); +#endif + + pa_pstream_send_tagstruct(u->pstream, t); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_info_callback, u); +} + +static void start_subscribe(struct userdata *u) { + pa_tagstruct *t; + uint32_t tag; + assert(u); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); + pa_tagstruct_putu32(t, tag = u->ctag++); + +#ifdef TUNNEL_SINK + pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SINK); +#else + pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SOURCE); +#endif + + pa_pstream_send_tagstruct(u->pstream, t); +} + static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; assert(pd && u && u->pdispatch == pd); @@ -356,6 +496,9 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN return; } + start_subscribe(u); + request_info(u); + request_latency(u); #ifdef TUNNEL_SINK send_bytes(u); @@ -537,6 +680,60 @@ static pa_usec_t sink_get_latency(pa_sink *sink) { return usec; } + +static int sink_get_hw_volume(pa_sink *sink) { + struct userdata *u; + assert(sink && sink->userdata); + u = sink->userdata; + + return 0; +} + +static int sink_set_hw_volume(pa_sink *sink) { + struct userdata *u; + pa_tagstruct *t; + uint32_t tag; + assert(sink && sink->userdata); + u = sink->userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME); + pa_tagstruct_putu32(t, tag = u->ctag++); + + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, u->sink_name); + pa_tagstruct_put_cvolume(t, &sink->hw_volume); + pa_pstream_send_tagstruct(u->pstream, t); + + return 0; +} + +static int sink_get_hw_mute(pa_sink *sink) { + struct userdata *u; + assert(sink && sink->userdata); + u = sink->userdata; + + return 0; +} + +static int sink_set_hw_mute(pa_sink *sink) { + struct userdata *u; + pa_tagstruct *t; + uint32_t tag; + assert(sink && sink->userdata); + u = sink->userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_MUTE); + pa_tagstruct_putu32(t, tag = u->ctag++); + + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, u->sink_name); + pa_tagstruct_put_boolean(t, !!sink->hw_muted); + pa_pstream_send_tagstruct(u->pstream, t); + + return 0; +} #else static pa_usec_t source_get_latency(pa_source *source) { struct userdata *u; @@ -545,6 +742,60 @@ static pa_usec_t source_get_latency(pa_source *source) { return u->host_latency; } + +static int source_get_hw_volume(pa_source *source) { + struct userdata *u; + assert(source && source->userdata); + u = source->userdata; + + return 0; +} + +static int source_set_hw_volume(pa_source *source) { + struct userdata *u; + pa_tagstruct *t; + uint32_t tag; + assert(source && source->userdata); + u = source->userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SOURCE_VOLUME); + pa_tagstruct_putu32(t, tag = u->ctag++); + + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, u->source_name); + pa_tagstruct_put_cvolume(t, &source->hw_volume); + pa_pstream_send_tagstruct(u->pstream, t); + + return 0; +} + +static int source_get_hw_mute(pa_source *source) { + struct userdata *u; + assert(source && source->userdata); + u = source->userdata; + + return 0; +} + +static int source_set_hw_mute(pa_source *source) { + struct userdata *u; + pa_tagstruct *t; + uint32_t tag; + assert(source && source->userdata); + u = source->userdata; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SOURCE_MUTE); + pa_tagstruct_putu32(t, tag = u->ctag++); + + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, u->source_name); + pa_tagstruct_put_boolean(t, !!source->hw_muted); + pa_pstream_send_tagstruct(u->pstream, t); + + return 0; +} #endif static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { @@ -651,6 +902,10 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->notify = sink_notify; u->sink->get_latency = sink_get_latency; + u->sink->get_hw_volume = sink_get_hw_volume; + u->sink->set_hw_volume = sink_set_hw_volume; + u->sink->get_hw_mute = sink_get_hw_mute; + u->sink->set_hw_mute = sink_set_hw_mute; u->sink->userdata = u; u->sink->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->sink_name ? u->sink_name : "", u->sink_name ? "@" : "", u->server_name); @@ -662,6 +917,10 @@ int pa__init(pa_core *c, pa_module*m) { } u->source->get_latency = source_get_latency; + u->source->get_hw_volume = source_get_hw_volume; + u->source->set_hw_volume = source_set_hw_volume; + u->source->get_hw_mute = source_get_hw_mute; + u->source->set_hw_mute = source_set_hw_mute; u->source->userdata = u; u->source->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->source_name ? u->source_name : "", u->source_name ? "@" : "", u->server_name); From 06eaebf0b44fbad8c7a85616f6272661de5c1add Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 5 Mar 2006 20:18:35 +0000 Subject: [PATCH 0537/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@630 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index d6df239f0..8d79599e7 100644 --- a/doc/todo +++ b/doc/todo @@ -12,7 +12,6 @@ Fixes: - module-alsa-* love: - add hw driver name to sink/source description - deal with underflows properly -- module-tunnel volume support (sink, source, notify) Post 0.8: - alsa mmap driver From 53c266f6636afd3b9abb88148d7dd2349b1caf13 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 5 Mar 2006 20:59:57 +0000 Subject: [PATCH 0538/1514] Fetch sound card name into sink/source description. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@631 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 12 +++++++++++- src/modules/module-alsa-source.c | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 0053acd2b..6ace7aff3 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -308,6 +308,7 @@ int pa__init(pa_core *c, pa_module*m) { uint32_t periods, fragsize; snd_pcm_uframes_t period_size; size_t frame_size; + snd_pcm_info_t *pcm_info = NULL; int err; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -340,6 +341,12 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 || + (err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) { + pa_log(__FILE__": Error fetching PCM info: %s", snd_strerror(err)); + goto fail; + } + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) { pa_log(__FILE__": Failed to set hardware parameters: %s", snd_strerror(err)); goto fail; @@ -375,7 +382,7 @@ int pa__init(pa_core *c, pa_module*m) { } u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); + u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s' (%s)", dev, snd_pcm_info_get_name(pcm_info)); u->pcm_fdl = pa_alsa_fdlist_new(); assert(u->pcm_fdl); @@ -419,6 +426,9 @@ int pa__init(pa_core *c, pa_module*m) { finish: if (ma) pa_modargs_free(ma); + + if (pcm_info) + snd_pcm_info_free(pcm_info); return ret; diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 5a6dc1441..3343e0b6a 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -299,6 +299,7 @@ int pa__init(pa_core *c, pa_module*m) { unsigned periods, fragsize; snd_pcm_uframes_t period_size; size_t frame_size; + snd_pcm_info_t *pcm_info = NULL; int err; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -331,6 +332,12 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 || + (err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) { + pa_log(__FILE__": Error fetching PCM info: %s", snd_strerror(err)); + goto fail; + } + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) { pa_log(__FILE__": Failed to set hardware parameters: %s", snd_strerror(err)); goto fail; @@ -366,7 +373,7 @@ int pa__init(pa_core *c, pa_module*m) { } } pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); + u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s' (%s)", dev, snd_pcm_info_get_name(pcm_info)); u->pcm_fdl = pa_alsa_fdlist_new(); assert(u->pcm_fdl); @@ -407,6 +414,9 @@ int pa__init(pa_core *c, pa_module*m) { finish: if (ma) pa_modargs_free(ma); + + if (pcm_info) + snd_pcm_info_free(pcm_info); return ret; From 90d6a919fa1e358d1cffeb00b76d297dc9beb1e7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 5 Mar 2006 21:00:31 +0000 Subject: [PATCH 0539/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@632 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 8d79599e7..c1864746b 100644 --- a/doc/todo +++ b/doc/todo @@ -10,7 +10,6 @@ Fixes: - deal with underflows propely - improve latency measurement for mmap - module-alsa-* love: - - add hw driver name to sink/source description - deal with underflows properly Post 0.8: From 64571374b3d7941471838eecc1457046854ed4d9 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 7 Mar 2006 16:02:34 +0000 Subject: [PATCH 0540/1514] Trying to listen on an IPv6 socket by default and only do IPv4 if that fails (which it doesn't most of the time) is terribly confusing. What the user most likely wants is for it to listen to both IPv4 and IPv6 and gracefully continue if only of them succeed. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@633 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-protocol-stub.c | 143 +++++++++++++++++++++-------- src/polypcore/socket-server.c | 53 ++++++----- src/polypcore/socket-server.h | 9 +- 3 files changed, 145 insertions(+), 60 deletions(-) diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index b02b96885..71e17cbcf 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -49,6 +49,7 @@ #include #include #include +#include #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" @@ -162,41 +163,71 @@ static const char* const valid_modargs[] = { NULL }; -static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) { - pa_socket_server *s; +struct userdata { #if defined(USE_TCP_SOCKETS) + void *protocol_ipv4; + void *protocol_ipv6; +#else + void *protocol_unix; +#endif +}; + +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; + int ret = -1; + + struct userdata *u = NULL; + +#if defined(USE_TCP_SOCKETS) + pa_socket_server *s_ipv4 = NULL; + pa_socket_server *s_ipv6 = NULL; int loopback = 1; uint32_t port = IPV4_PORT; const char *listen_on; +#else + pa_socket_server *s; + int r; + const char *v; + char tmp[PATH_MAX]; +#endif + + assert(c && m); + +#if defined(USE_TCP_SOCKETS) + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": Failed to parse module arguments"); + goto finish; + } if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) { pa_log(__FILE__": loopback= expects a boolean argument."); - return NULL; + goto fail; } if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { pa_log(__FILE__": port= expects a numerical argument between 1 and 65535."); - return NULL; + goto fail; } listen_on = pa_modargs_get_value(ma, "listen", NULL); if (listen_on) { - if (!(s = pa_socket_server_new_ip_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE))) - return NULL; + s_ipv4 = pa_socket_server_new_ipv4_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); + s_ipv6 = pa_socket_server_new_ipv6_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); + if (!s_ipv4 && !s_ipv6) + goto fail; } else if (loopback) { - if (!(s = pa_socket_server_new_ip_loopback(c->mainloop, port, TCPWRAP_SERVICE))) - return NULL; + s_ipv4 = pa_socket_server_new_ipv4_loopback(c->mainloop, port, TCPWRAP_SERVICE); + s_ipv6 = pa_socket_server_new_ipv6_loopback(c->mainloop, port, TCPWRAP_SERVICE); + if (!s_ipv4 && !s_ipv6) + goto fail; } else { - if (!(s = pa_socket_server_new_ip_any(c->mainloop, port, TCPWRAP_SERVICE))) - return NULL; + s_ipv4 = pa_socket_server_new_ipv4_any(c->mainloop, port, TCPWRAP_SERVICE); + s_ipv6 = pa_socket_server_new_ipv6_any(c->mainloop, port, TCPWRAP_SERVICE); + if (!s_ipv4 && !s_ipv6) + goto fail; } - #else - int r; - const char *v; - char tmp[PATH_MAX]; - v = pa_modargs_get_value(ma, "socket", UNIX_SOCKET); assert(v); @@ -204,43 +235,43 @@ static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) { if (pa_make_secure_parent_dir(tmp) < 0) { pa_log(__FILE__": Failed to create secure socket directory."); - return NULL; + goto fail; } if ((r = pa_unix_socket_remove_stale(tmp)) < 0) { pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s", tmp, strerror(errno)); - return NULL; + goto fail; } if (r) pa_log(__FILE__": Removed stale UNIX socket '%s'.", tmp); if (!(s = pa_socket_server_new_unix(c->mainloop, tmp))) - return NULL; - + goto fail; #endif - return s; -} -int pa__init(pa_core *c, pa_module*m) { - pa_socket_server *s; - pa_modargs *ma = NULL; - int ret = -1; - assert(c && m); + u = pa_xmalloc0(sizeof(struct userdata)); - if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments"); - goto finish; +#if defined(USE_TCP_SOCKETS) + if (s_ipv4) { + u->protocol_ipv4 = protocol_new(c, s_ipv4, m, ma); + if (!u->protocol_ipv4) + pa_socket_server_unref(s_ipv4); } - if (!(s = create_socket_server(c, ma))) - goto finish; - - if (!(m->userdata = protocol_new(c, s, m, ma))) { - pa_socket_server_unref(s); - goto finish; + if (s_ipv6) { + u->protocol_ipv6 = protocol_new(c, s_ipv4, m, ma); + if (!u->protocol_ipv6) + pa_socket_server_unref(s_ipv6); } + if (!u->protocol_ipv4 && !u->protocol_ipv6) + goto fail; +#else + if (!(u->protocol_unix = protocol_new(c, s, m, ma))) + goto fail; +#endif + ret = 0; finish: @@ -248,9 +279,36 @@ finish: pa_modargs_free(ma); return ret; + +fail: + if (u) { +#if defined(USE_TCP_SOCKETS) + if (u->protocol_ipv4) + protocol_free(u->protocol_ipv4); + if (u->protocol_ipv6) + protocol_free(u->protocol_ipv6); +#else + if (u->protocol_unix) + protocol_free(u->protocol_unix); +#endif + pa_xfree(u); + } else { +#if defined(USE_TCP_SOCKETS) + if (s_ipv4) + pa_socket_server_unref(s_ipv4); + if (s_ipv6) + pa_socket_server_unref(s_ipv6); +#else + if (s) + pa_socket_server_unref(s); +#endif + } + + goto finish; } void pa__done(pa_core *c, pa_module*m) { + struct userdata *u; assert(c && m); #if defined(USE_PROTOCOL_ESOUND) && !defined(USE_TCP_SOCKETS) @@ -260,5 +318,18 @@ void pa__done(pa_core *c, pa_module*m) { pa_log("%s: Failed to remove %s : %s.", __FILE__, ESD_UNIX_SOCKET_DIR, strerror (errno)); #endif - protocol_free(m->userdata); + u = m->userdata; + assert(u); + +#if defined(USE_TCP_SOCKETS) + if (u->protocol_ipv4) + protocol_free(u->protocol_ipv4); + if (u->protocol_ipv6) + protocol_free(u->protocol_ipv6); +#else + if (u->protocol_unix) + protocol_free(u->protocol_unix); +#endif + + pa_xfree(u); } diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index d457d626a..baa31e687 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -314,46 +314,57 @@ fail: return NULL; } -pa_socket_server* pa_socket_server_new_ip_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { - pa_socket_server *s; - +pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { + assert(m); + assert(port > 0); + + return pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, tcpwrap_service); +} + +pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { + assert(m); + assert(port > 0); + + return pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, tcpwrap_service); +} + +pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { assert(m); assert(port > 0); - if (!(s = pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, tcpwrap_service))) - s = pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, tcpwrap_service); - - return s; + return pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service); } -pa_socket_server* pa_socket_server_new_ip_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { - pa_socket_server *s; - +pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { assert(m); assert(port > 0); - if (!(s = pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service))) - s = pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service); - - return s; + return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service); } -pa_socket_server* pa_socket_server_new_ip_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { - struct in6_addr ipv6; +pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { struct in_addr ipv4; assert(m); assert(name); assert(port > 0); + if (inet_pton(AF_INET, name, &ipv4) > 0) + return pa_socket_server_new_ipv4(m, ntohl(ipv4.s_addr), port, tcpwrap_service); + + return NULL; +} + +pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { + struct in6_addr ipv6; + + assert(m); + assert(name); + assert(port > 0); + if (inet_pton(AF_INET6, name, &ipv6) > 0) return pa_socket_server_new_ipv6(m, ipv6.s6_addr, port, tcpwrap_service); - if (inet_pton(AF_INET, name, &ipv4) > 0) - return pa_socket_server_new_ipv4(m, ntohl(ipv4.s_addr), port, tcpwrap_service); - - pa_log_warn(__FILE__": failed to parse '%s'.", name); - return NULL; } diff --git a/src/polypcore/socket-server.h b/src/polypcore/socket-server.h index 3babbc140..cd3276ad8 100644 --- a/src/polypcore/socket-server.h +++ b/src/polypcore/socket-server.h @@ -34,9 +34,12 @@ pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd); pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename); pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, const char *tcpwrap_service); -pa_socket_server* pa_socket_server_new_ip_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); -pa_socket_server* pa_socket_server_new_ip_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); -pa_socket_server* pa_socket_server_new_ip_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service); void pa_socket_server_unref(pa_socket_server*s); pa_socket_server* pa_socket_server_ref(pa_socket_server *s); From b67963cec233f9c4d8c431f560475735e813c7b7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 7 Mar 2006 16:04:32 +0000 Subject: [PATCH 0541/1514] We've already set an initial reference count of 1 so don't count it up again. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@634 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index ab6ab4089..746ea9f99 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -103,7 +103,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * PA_LLIST_PREPEND(pa_stream, c->streams, s); - return pa_stream_ref(s); + return s; } static void hashmap_free_func(void *p, void *userdata) { From 528d15095dd27d401be5d138d144a9df8ba7803a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 7 Mar 2006 18:29:27 +0000 Subject: [PATCH 0542/1514] The extra stream ref actually did some good. Re-add it, but with some more symmetry, assertions and comments. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@635 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 746ea9f99..f4436ff5e 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -103,6 +103,10 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * PA_LLIST_PREPEND(pa_stream, c->streams, s); + /* The context and stream will point at each other. We cannot ref count + both though since that will create a loop. */ + pa_context_ref(s->context); + return s; } @@ -111,7 +115,11 @@ static void hashmap_free_func(void *p, void *userdata) { } static void stream_free(pa_stream *s) { - assert(s); + assert(s && s->context && !s->channel_valid); + + PA_LLIST_REMOVE(pa_stream, s->context->streams, s); + + pa_context_unref(s->context); if (s->ipol_event) { assert(s->mainloop); @@ -187,7 +195,10 @@ void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { if (s->channel_valid) pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - PA_LLIST_REMOVE(pa_stream, s->context->streams, s); + s->channel = 0; + s->channel_valid = 0; + + /* We keep a ref as long as we're connected */ pa_stream_unref(s); } @@ -358,6 +369,9 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED s->channel_valid = 1; pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); + /* We add an extra ref as long as we're connected (i.e. in the dynarray) */ + pa_stream_ref(s); + if (s->interpolate) { struct timeval tv; pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); From 3ef49701428a4ddd135e173ea9beeb6d3931f876 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 8 Mar 2006 13:00:46 +0000 Subject: [PATCH 0543/1514] We filled the volume with the wrong channel count (we used the input, not the output) causing static. Also swapped the comments since they were misplaced. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@636 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/sink-input.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/polypcore/sink-input.c b/src/polypcore/sink-input.c index f12a85e17..e1703b97a 100644 --- a/src/polypcore/sink-input.c +++ b/src/polypcore/sink-input.c @@ -262,11 +262,10 @@ finish: * ourselves, or if this can be done by the sink for us */ if (do_volume_adj_here) - /* We've both the same channel map, so let's have the sink do the adjustment for us*/ - - pa_cvolume_reset(volume, i->sample_spec.channels); - else /* We had different channel maps, so we already did the adjustment */ + pa_cvolume_reset(volume, i->sink->sample_spec.channels); + else + /* We've both the same channel map, so let's have the sink do the adjustment for us*/ *volume = i->volume; } From da90b05785903af020cec289cdf4b377999c98bb Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 11 Mar 2006 21:25:35 +0000 Subject: [PATCH 0544/1514] Remember to store the struct with module info. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@637 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-protocol-stub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 71e17cbcf..3877b1cc1 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -272,6 +272,8 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; #endif + m->userdata = u; + ret = 0; finish: From dc5b2c58ddb52ae205e7d99e504b4386404df69e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 11 Mar 2006 21:26:40 +0000 Subject: [PATCH 0545/1514] We no longer guarantee that an operation object is returned. Need to tweak some parts to handle this. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@638 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index f4436ff5e..672c376a3 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -314,7 +314,10 @@ static void ipol_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED co /* pa_log("requesting new ipol data"); */ if (s->state == PA_STREAM_READY && !s->ipol_requested) { - pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + pa_operation *o; + o = pa_stream_get_latency_info(s, NULL, NULL); + if (o) + pa_operation_unref(o); s->ipol_requested = 1; } @@ -374,7 +377,6 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED if (s->interpolate) { struct timeval tv; - pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); pa_gettimeofday(&tv); tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */ @@ -860,6 +862,7 @@ finish: pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; + pa_operation *lo; pa_tagstruct *t; uint32_t tag; @@ -891,7 +894,9 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); - pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + lo = pa_stream_get_latency_info(s, NULL, NULL); + if (lo) + pa_operation_unref(lo); return pa_operation_ref(o); } @@ -921,8 +926,12 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) - pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) { + pa_operation *lo; + lo = pa_stream_get_latency_info(s, NULL, NULL); + if (lo) + pa_operation_unref(lo); + } return o; } @@ -932,8 +941,12 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); - if ((o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata))) - pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + if ((o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata))) { + pa_operation *lo; + lo = pa_stream_get_latency_info(s, NULL, NULL); + if (lo) + pa_operation_unref(lo); + } return o; } @@ -943,8 +956,12 @@ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *u PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); - if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata))) - pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL)); + if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata))) { + pa_operation *lo; + lo = pa_stream_get_latency_info(s, NULL, NULL); + if (lo) + pa_operation_unref(lo); + } return o; } From 8d4af80383f40f43221e46335004b0eb82e1ea80 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Mar 2006 08:16:23 +0000 Subject: [PATCH 0546/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@639 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/todo b/doc/todo index c1864746b..d36b194ee 100644 --- a/doc/todo +++ b/doc/todo @@ -23,6 +23,7 @@ Post 0.8: - port from howl to avahi - multiline configuration statements - use scatter/gather io for sockets +- add a synchronous API (base it on xmms-polyp) Long term: - pass meta info for hearing impaired @@ -32,3 +33,4 @@ Backends for: - portaudio (semi-done) - sdl - OSS (esddsp style) +- gstreamer (needs to be updated) From 3285403d3c56e1d7ac9361ede675979b2d28fbf6 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 31 Mar 2006 08:34:41 +0000 Subject: [PATCH 0547/1514] Large file support. Polypaudio probably doesn't need it, but it causes warnings when linking libpolyp with applications that do. So this is just to make life easier for other applications. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@640 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.ac b/configure.ac index a0b16573b..7d7f8f73a 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,10 @@ if type -p stow > /dev/null && test -d /usr/local/stow ; then ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}" fi +#### Large File-Support (LFS) #### + +AC_SYS_LARGEFILE + #### Checks for programs. #### # CC From acb96c96fde93dcd87c6509e7c64b403caa44f30 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 31 Mar 2006 08:54:24 +0000 Subject: [PATCH 0548/1514] Fix some warnings caused by size_t having varying size. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@641 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 2 +- src/modules/module-alsa-source.c | 2 +- src/polypcore/cli-text.c | 4 ++-- src/tests/mcalign-test.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 6ace7aff3..2e9459e6c 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -405,7 +405,7 @@ int pa__init(pa_core *c, pa_module*m) { u->frame_size = frame_size; u->fragment_size = period_size; - pa_log_info(__FILE__": using %u fragments of size %u bytes.", periods, u->fragment_size); + pa_log_info(__FILE__": using %u fragments of size %lu bytes.", periods, (long unsigned)u->fragment_size); u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size, c->memblock_stat); assert(u->silence.memblock); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 3343e0b6a..14b35eb81 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -396,7 +396,7 @@ int pa__init(pa_core *c, pa_module*m) { u->frame_size = frame_size; u->fragment_size = period_size; - pa_log(__FILE__": using %u fragments of size %u bytes.", periods, u->fragment_size); + pa_log(__FILE__": using %u fragments of size %lu bytes.", periods, (long unsigned)u->fragment_size); u->memchunk.memblock = NULL; u->memchunk.index = u->memchunk.length = 0; diff --git a/src/polypcore/cli-text.c b/src/polypcore/cli-text.c index 8bffd0a73..d31d09c51 100644 --- a/src/polypcore/cli-text.c +++ b/src/polypcore/cli-text.c @@ -294,7 +294,7 @@ char *pa_scache_list_to_string(pa_core *c) { "\tindex: <%u>\n" "\tsample spec: <%s>\n" "\tchannel map: <%s>\n" - "\tlength: <%u>\n" + "\tlength: <%lu>\n" "\tduration: <%0.1fs>\n" "\tvolume: <%s>\n" "\tlazy: %s\n" @@ -303,7 +303,7 @@ char *pa_scache_list_to_string(pa_core *c) { e->index, ss, cm, - e->memchunk.memblock ? e->memchunk.length : 0, + (long unsigned)(e->memchunk.memblock ? e->memchunk.length : 0), l, pa_cvolume_snprint(cv, sizeof(cv), &e->volume), e->lazy ? "yes" : "no", diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index eab5dc88e..2728def22 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -67,7 +67,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { c.length = r; pa_mcalign_push(a, &c); - fprintf(stderr, "Read %d bytes\n", r); + fprintf(stderr, "Read %ld bytes\n", (long)r); c.index += r; From ac3d11f833ca7eb4ff3a1c0cb2e2cfd82da11813 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Apr 2006 20:17:27 +0000 Subject: [PATCH 0549/1514] remove some GCC warnings introduced by improperly casting to (char*) instead of (const char*) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@642 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 08b7c6f71..e98711780 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -297,7 +297,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req } } - data = (char*)data + ESD_KEY_LEN; + data = (const char*)data + ESD_KEY_LEN; memcpy(&ekey, data, sizeof(uint32_t)); if (ekey == ESD_ENDIAN_KEY) @@ -325,11 +325,11 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t memcpy(&format, data, sizeof(int32_t)); format = MAYBE_INT32_SWAP(c->swap_byte_order, format); - data = (char*)data + sizeof(int32_t); + data = (const char*)data + sizeof(int32_t); - memcpy(&rate, (char*)data, sizeof(int32_t)); + memcpy(&rate, data, sizeof(int32_t)); rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); - data = (char*)data + sizeof(int32_t); + data = (const char*)data + sizeof(int32_t); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -388,11 +388,11 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co memcpy(&format, data, sizeof(int32_t)); format = MAYBE_INT32_SWAP(c->swap_byte_order, format); - data = (char*)data + sizeof(int32_t); + data = (const char*)data + sizeof(int32_t); - memcpy(&rate, (char*)data, sizeof(int32_t)); + memcpy(&rate, data, sizeof(int32_t)); rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); - data = (char*)data + sizeof(int32_t); + data = (const char*)data + sizeof(int32_t); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -633,15 +633,15 @@ static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t memcpy(&idx, data, sizeof(uint32_t)); idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1; - data = (char*)data + sizeof(uint32_t); + data = (const char*)data + sizeof(uint32_t); memcpy(&lvolume, data, sizeof(uint32_t)); lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, lvolume); - data = (char*)data + sizeof(uint32_t); + data = (const char*)data + sizeof(uint32_t); memcpy(&rvolume, data, sizeof(uint32_t)); rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume); - data = (char*)data + sizeof(uint32_t); + data = (const char*)data + sizeof(uint32_t); if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx))) { assert(conn->sink_input); @@ -667,11 +667,11 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ memcpy(&format, data, sizeof(int32_t)); format = MAYBE_INT32_SWAP(c->swap_byte_order, format); - data = (char*)data + sizeof(int32_t); + data = (const char*)data + sizeof(int32_t); - memcpy(&rate, (char*)data + sizeof(int32_t), sizeof(int32_t)); + memcpy(&rate, (const char*)data + sizeof(int32_t), sizeof(int32_t)); rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); - data = (char*)data + sizeof(int32_t); + data = (const char*)data + sizeof(int32_t); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); From 73035a82a7abde862b171daf7b4cb77a50c8e14b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Apr 2006 23:28:15 +0000 Subject: [PATCH 0550/1514] * set IPV6_V6ONLY for IPv6 sockets, to avoid warning when both ipv6 and the ipv4 sockets try to bind to the same port * enable SO_REUSEADDR only on platforms that support it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@643 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/socket-server.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index baa31e687..b27816d43 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -231,8 +231,10 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address pa_fd_set_cloexec(fd, 1); - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) +#ifdef SO_REUSEADDR + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) pa_log(__FILE__": setsockopt(): %s", strerror(errno)); +#endif pa_socket_tcp_low_delay(fd); @@ -280,8 +282,15 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad pa_fd_set_cloexec(fd, 1); - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) - pa_log(__FILE__": setsockopt(): %s", strerror(errno)); +#ifdef IPV6_V6ONLY + if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) + pa_log(__FILE__": setsockopt(IPPROTO_IPV6, IPV6_V6ONLY): %s", strerror(errno)); +#endif + +#ifdef SO_REUSEADDR + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) + pa_log(__FILE__": setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", strerror(errno)); +#endif pa_socket_tcp_low_delay(fd); From e872c751e1bde9dc996d967e32c457d9c8f0f0fc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Apr 2006 23:28:56 +0000 Subject: [PATCH 0551/1514] s/index/idx/, to avoid gcc warning git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@644 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index aa6b69f54..8f5e66e6d 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -365,7 +365,7 @@ static void request_latency(struct userdata *u) { static void stream_get_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; - uint32_t index, owner_module, monitor_source; + uint32_t idx, owner_module, monitor_source; pa_usec_t latency; const char *name, *description, *monitor_source_name, *driver; int mute; @@ -383,7 +383,7 @@ static void stream_get_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_ return; } - if (pa_tagstruct_getu32(t, &index) < 0 || + if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_gets(t, &description) < 0 || pa_tagstruct_get_sample_spec(t, &sample_spec) < 0 || From 1be00173c134b837ddda2eba77b2d914ce244140 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Apr 2006 23:31:40 +0000 Subject: [PATCH 0552/1514] change pa_gettimeofday() to return a pointer to the struct timeval*, instead of an int git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@645 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/util.c | 32 +++++++++++++++++--------------- src/polypcore/util.h | 2 +- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/polypcore/util.c b/src/polypcore/util.c index f810b3bf2..b37a25a34 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -418,9 +418,11 @@ char *pa_strlcpy(char *b, const char *s, size_t l) { return b; } -int pa_gettimeofday(struct timeval *tv) { +struct timeval *pa_gettimeofday(struct timeval *tv) { #ifdef HAVE_GETTIMEOFDAY - return gettimeofday(tv, NULL); + assert(tv); + + return gettimeofday(tv, NULL) < 0 ? NULL : tv; #elif defined(OS_IS_WIN32) /* * Copied from implementation by Steven Edwards (LGPL). @@ -437,18 +439,18 @@ int pa_gettimeofday(struct timeval *tv) { LARGE_INTEGER li; __int64 t; - if (tv) { - GetSystemTimeAsFileTime(&ft); - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - t = li.QuadPart; /* In 100-nanosecond intervals */ - t -= EPOCHFILETIME; /* Offset to the Epoch time */ - t /= 10; /* In microseconds */ - tv->tv_sec = (long)(t / 1000000); - tv->tv_usec = (long)(t % 1000000); - } + assert(tv); - return 0; + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + t = li.QuadPart; /* In 100-nanosecond intervals */ + t -= EPOCHFILETIME; /* Offset to the Epoch time */ + t /= 10; /* In microseconds */ + tv->tv_sec = (long)(t / 1000000); + tv->tv_usec = (long)(t % 1000000); + + return tv; #else #error "Platform lacks gettimeofday() or equivalent function." #endif @@ -503,8 +505,8 @@ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { pa_usec_t pa_timeval_age(const struct timeval *tv) { struct timeval now; assert(tv); - pa_gettimeofday(&now); - return pa_timeval_diff(&now, tv); + + return pa_timeval_diff(pa_gettimeofday(&now), tv); } /* Add the specified time inmicroseconds to the specified timeval structure */ diff --git a/src/polypcore/util.h b/src/polypcore/util.h index 424283e76..f05339c46 100644 --- a/src/polypcore/util.h +++ b/src/polypcore/util.h @@ -55,7 +55,7 @@ char *pa_get_home_dir(char *s, size_t l); const char *pa_path_get_filename(const char *p); -int pa_gettimeofday(struct timeval *tv); +struct timeval *pa_gettimeofday(struct timeval *tv); pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); pa_usec_t pa_timeval_age(const struct timeval *tv); From dd9605ba1f29f959e5d5b0c6f80cec4dcb1574db Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Apr 2006 23:52:48 +0000 Subject: [PATCH 0553/1514] * really pass the ipv6 socket server to protocol_new in case of ipv6. * create the pa_modargs object properly when using TCP * other cleanups git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@646 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-protocol-stub.c | 37 ++++++++++++------------------ 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 3877b1cc1..2f022b992 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -179,8 +179,7 @@ int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; #if defined(USE_TCP_SOCKETS) - pa_socket_server *s_ipv4 = NULL; - pa_socket_server *s_ipv6 = NULL; + pa_socket_server *s_ipv4 = NULL, *s_ipv6 = NULL; int loopback = 1; uint32_t port = IPV4_PORT; const char *listen_on; @@ -193,12 +192,12 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); -#if defined(USE_TCP_SOCKETS) if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": Failed to parse module arguments"); goto finish; } +#if defined(USE_TCP_SOCKETS) if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) { pa_log(__FILE__": loopback= expects a boolean argument."); goto fail; @@ -214,19 +213,17 @@ int pa__init(pa_core *c, pa_module*m) { if (listen_on) { s_ipv4 = pa_socket_server_new_ipv4_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); s_ipv6 = pa_socket_server_new_ipv6_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); - if (!s_ipv4 && !s_ipv6) - goto fail; } else if (loopback) { s_ipv4 = pa_socket_server_new_ipv4_loopback(c->mainloop, port, TCPWRAP_SERVICE); s_ipv6 = pa_socket_server_new_ipv6_loopback(c->mainloop, port, TCPWRAP_SERVICE); - if (!s_ipv4 && !s_ipv6) - goto fail; } else { s_ipv4 = pa_socket_server_new_ipv4_any(c->mainloop, port, TCPWRAP_SERVICE); s_ipv6 = pa_socket_server_new_ipv6_any(c->mainloop, port, TCPWRAP_SERVICE); - if (!s_ipv4 && !s_ipv6) - goto fail; } + + if (!s_ipv4 && !s_ipv6) + goto fail; + #else v = pa_modargs_get_value(ma, "socket", UNIX_SOCKET); assert(v); @@ -250,20 +247,16 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; #endif - u = pa_xmalloc0(sizeof(struct userdata)); + u = pa_xnew0(struct userdata, 1); #if defined(USE_TCP_SOCKETS) - if (s_ipv4) { - u->protocol_ipv4 = protocol_new(c, s_ipv4, m, ma); - if (!u->protocol_ipv4) + if (s_ipv4) + if (!(u->protocol_ipv4 = protocol_new(c, s_ipv4, m, ma))) pa_socket_server_unref(s_ipv4); - } - if (s_ipv6) { - u->protocol_ipv6 = protocol_new(c, s_ipv4, m, ma); - if (!u->protocol_ipv6) + if (s_ipv6) + if (!(u->protocol_ipv6 = protocol_new(c, s_ipv6, m, ma))) pa_socket_server_unref(s_ipv6); - } if (!u->protocol_ipv4 && !u->protocol_ipv6) goto fail; @@ -314,10 +307,10 @@ void pa__done(pa_core *c, pa_module*m) { assert(c && m); #if defined(USE_PROTOCOL_ESOUND) && !defined(USE_TCP_SOCKETS) - if (remove(ESD_UNIX_SOCKET_NAME) != 0) - pa_log("%s: Failed to remove %s : %s.", __FILE__, ESD_UNIX_SOCKET_NAME, strerror (errno)); - if (remove(ESD_UNIX_SOCKET_DIR) != 0) - pa_log("%s: Failed to remove %s : %s.", __FILE__, ESD_UNIX_SOCKET_DIR, strerror (errno)); + if (remove(ESD_UNIX_SOCKET_NAME) != 0) + pa_log("%s: Failed to remove %s : %s.", __FILE__, ESD_UNIX_SOCKET_NAME, strerror (errno)); + if (remove(ESD_UNIX_SOCKET_DIR) != 0) + pa_log("%s: Failed to remove %s : %s.", __FILE__, ESD_UNIX_SOCKET_DIR, strerror (errno)); #endif u = m->userdata; From cc302f2d17b172bec60b25d549a77b1cb3d17d99 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 00:23:38 +0000 Subject: [PATCH 0554/1514] remove queue length field from latency request (server side) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@647 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-native.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 68dc63667..763873c25 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -1064,10 +1064,8 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct_put_usec(reply, pa_sink_get_latency(s->sink_input->sink)); pa_tagstruct_put_usec(reply, 0); pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq)); - pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq)); pa_tagstruct_put_timeval(reply, &tv); - pa_gettimeofday(&now); - pa_tagstruct_put_timeval(reply, &now); + pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now)); pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq)); pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq)); pa_pstream_send_tagstruct(c->pstream, reply); @@ -1097,10 +1095,8 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0); pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source)); pa_tagstruct_put_boolean(reply, 0); - pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq)); pa_tagstruct_put_timeval(reply, &tv); - pa_gettimeofday(&now); - pa_tagstruct_put_timeval(reply, &now); + pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now)); pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq)); pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq)); pa_pstream_send_tagstruct(c->pstream, reply); From 920f045380d70785d6ca483d901610d70daee361 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 00:24:48 +0000 Subject: [PATCH 0555/1514] rework latency querying API (this needs more testing) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@648 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/def.h | 44 +++-- src/polyp/internal.h | 44 +++-- src/polyp/stream.c | 433 ++++++++++++++++++++++++++----------------- src/polyp/stream.h | 28 +-- 4 files changed, 326 insertions(+), 223 deletions(-) diff --git a/src/polyp/def.h b/src/polyp/def.h index 98420bc08..93d0996b3 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -80,7 +80,7 @@ typedef enum pa_stream_direction { /** Some special flags for stream connections. \since 0.6 */ typedef enum pa_stream_flags { PA_STREAM_START_CORKED = 1, /**< Create the stream corked, requiring an explicit pa_stream_cork() call to uncork it. */ - PA_STREAM_INTERPOLATE_LATENCY = 2 /**< Interpolate the latency for + PA_STREAM_INTERPOLATE_LATENCY = 2, /**< Interpolate the latency for * this stream. When enabled, * you can use * pa_stream_interpolated_xxx() @@ -95,6 +95,7 @@ typedef enum pa_stream_flags { * information. This is * especially useful on long latency * network connections. */ + PA_STREAM_NOT_MONOTONOUS = 4, /**< Don't force the time to run monotonically */ } pa_stream_flags_t; /** Playback and record buffer metrics */ @@ -124,7 +125,7 @@ enum { PA_ERR_INVALIDSERVER, /**< Invalid server */ PA_ERR_MODINITFAILED, /**< Module initialization failed */ PA_ERR_BADSTATE, /**< Bad state */ - PA_ERR_NODATA, /**< No data */ + PA_ERR_NODATA, /**< No data */ PA_ERR_VERSION, /**< Incompatible protocol version \since 0.8 */ PA_ERR_MAX /**< Not really an error but the first invalid error code */ }; @@ -171,7 +172,7 @@ typedef enum pa_subscription_event_type { * pa_stream_write() takes to be played may be estimated by * sink_usec+buffer_usec+transport_usec. The output buffer to which * buffer_usec relates may be manipulated freely (with - * pa_stream_write()'s delta argument, pa_stream_flush() and friends), + * pa_stream_write()'s seek argument, pa_stream_flush() and friends), * the buffers sink_usec/source_usec relates to is a first-in * first-out buffer which cannot be flushed or manipulated in any * way. The total input latency a sample that is recorded takes to be @@ -180,12 +181,7 @@ typedef enum pa_subscription_event_type { * sign issues!) When connected to a monitor source sink_usec contains * the latency of the owning sink.*/ typedef struct pa_latency_info { - pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play. For both playback and record streams. */ - pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. For playback streams and record streams connected to a monitor source. */ - pa_usec_t source_usec; /**< Time in usecs a sample takes from being recorded to being delivered to the application. Only for record streams. \since 0.5*/ - pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to/from the daemon. For both playback and record streams. \since 0.5 */ - int playing; /**< Non-zero when the stream is currently playing. Only for playback streams. */ - uint32_t queue_length; /**< Queue size in bytes. For both playback and record streams. */ + struct timeval timestamp; /**< The time when this latency info was current */ int synchronized_clocks; /**< Non-zero if the local and the * remote machine have synchronized * clocks. If synchronized clocks are @@ -194,10 +190,31 @@ typedef struct pa_latency_info { * detects synchronized clocks is very * limited und unreliable itself. \since * 0.5 */ - struct timeval timestamp; /**< The time when this latency info was current */ - uint64_t counter; /**< The byte counter current when the latency info was requested. \since 0.6 */ - int64_t write_index; /**< Current absolute write index in the buffer. \since 0.8 */ - int64_t read_index; /**< Current absolute read index in the buffer. \since 0.8 */ + + pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play. For both playback and record streams. */ + pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. For playback streams and record streams connected to a monitor source. */ + pa_usec_t source_usec; /**< Time in usecs a sample takes from being recorded to being delivered to the application. Only for record streams. \since 0.5*/ + pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to/from the daemon. For both playback and record streams. \since 0.5 */ + + int playing; /**< Non-zero when the stream is currently playing. Only for playback streams. */ + + int write_index_corrupt; /**< Non-Zero if the write_index is not up to date because a local write command corrupted it */ + int64_t write_index; /**< Current write index into the + * playback buffer in bytes. Think twice before + * using this for seeking purposes: it + * might be out of date a the time you + * want to use it. Consider using + * PA_SEEK_RELATIVE instead. \since + * 0.8 */ + int64_t read_index; /**< Current read index into the + * playback buffer in bytes. Think twice before + * using this for seeking purposes: it + * might be out of date a the time you + * want to use it. Consider using + * PA_SEEK_RELATIVE_ON_READ + * instead. \since 0.8 */ + + uint32_t buffer_length; /* Current buffer length. This is usually identical to write_index-read_index. */ } pa_latency_info; /** A structure for the spawn api. This may be used to integrate auto @@ -227,7 +244,6 @@ typedef enum pa_seek_mode { PA_SEEK_RELATIVE_END = 3, /**< Seek relatively to the current end of the buffer queue */ } pa_seek_mode_t; - PA_C_DECL_END #endif diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 82d8f7ce6..8f1603b32 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -83,6 +83,15 @@ struct pa_context { pa_client_conf *conf; }; +#define PA_MAX_LATENCY_CORRECTIONS 10 + +typedef struct pa_latency_correction { + uint32_t tag; + int valid; + int64_t value; + int absolute, corrupt; +} pa_latency_correction; + struct pa_stream { int ref; pa_context *context; @@ -93,41 +102,48 @@ struct pa_stream { pa_buffer_attr buffer_attr; pa_sample_spec sample_spec; pa_channel_map channel_map; + pa_stream_flags_t flags; uint32_t channel; uint32_t syncid; int channel_valid; uint32_t device_index; pa_stream_direction_t direction; - uint32_t requested_bytes; - uint64_t counter; - pa_usec_t previous_time; - pa_usec_t previous_ipol_time; pa_stream_state_t state; + + uint32_t requested_bytes; + pa_memchunk peek_memchunk; pa_memblockq *record_memblockq; - pa_hashmap *counter_hashmap; - - int interpolate; int corked; - uint32_t ipol_usec; - struct timeval ipol_timestamp; + /* Store latest latency info */ + pa_latency_info latency_info; + int latency_info_valid; + + /* Use to make sure that time advances monotonically */ + pa_usec_t previous_time; + + /* Latency correction stuff */ + pa_latency_correction latency_corrections[PA_MAX_LATENCY_CORRECTIONS]; + int idx_latency_correction; + + /* Latency interpolation stuff */ pa_time_event *ipol_event; int ipol_requested; - + pa_usec_t ipol_usec; + int ipol_usec_valid; + struct timeval ipol_timestamp; + + /* Callbacks */ pa_stream_notify_cb_t state_callback; void *state_userdata; - pa_stream_request_cb_t read_callback; void *read_userdata; - pa_stream_request_cb_t write_callback; void *write_userdata; - pa_stream_notify_cb_t overflow_callback; void *overflow_userdata; - pa_stream_notify_cb_t underflow_callback; void *underflow_userdata; }; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 672c376a3..d3599582e 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -38,10 +38,10 @@ #include "internal.h" #define LATENCY_IPOL_INTERVAL_USEC (10000L) -#define COUNTER_HASHMAP_MAXSIZE (5) pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) { pa_stream *s; + int i; assert(c); @@ -67,6 +67,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->direction = PA_STREAM_NODIRECTION; s->name = pa_xstrdup(name); s->sample_spec = *ss; + s->flags = 0; if (map) s->channel_map = *map; @@ -87,20 +88,21 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->record_memblockq = NULL; - s->counter_hashmap = pa_hashmap_new(NULL, NULL); - - s->counter = 0; s->previous_time = 0; - s->previous_ipol_time = 0; + s->latency_info_valid = 0; s->corked = 0; - s->interpolate = 0; - s->ipol_usec = 0; - memset(&s->ipol_timestamp, 0, sizeof(s->ipol_timestamp)); + s->ipol_usec_valid = 0; + s->ipol_timestamp.tv_sec = 0; + s->ipol_timestamp.tv_usec = 0; s->ipol_event = NULL; s->ipol_requested = 0; + for (i = 0; i < PA_MAX_LATENCY_CORRECTIONS; i++) + s->latency_corrections[i].valid = 0; + s->idx_latency_correction = 0; + PA_LLIST_PREPEND(pa_stream, c->streams, s); /* The context and stream will point at each other. We cannot ref count @@ -110,10 +112,6 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * return s; } -static void hashmap_free_func(void *p, void *userdata) { - pa_xfree(p); -} - static void stream_free(pa_stream *s) { assert(s && s->context && !s->channel_valid); @@ -132,9 +130,6 @@ static void stream_free(pa_stream *s) { if (s->record_memblockq) pa_memblockq_free(s->record_memblockq); - if (s->counter_hashmap) - pa_hashmap_free(s->counter_hashmap, hashmap_free_func, NULL); - pa_xfree(s->name); pa_xfree(s); } @@ -315,10 +310,11 @@ static void ipol_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED co if (s->state == PA_STREAM_READY && !s->ipol_requested) { pa_operation *o; - o = pa_stream_get_latency_info(s, NULL, NULL); - if (o) + + if ((o = pa_stream_update_latency_info(s, NULL, NULL))) { pa_operation_unref(o); - s->ipol_requested = 1; + s->ipol_requested = 1; + } } pa_gettimeofday(&next); @@ -375,7 +371,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED /* We add an extra ref as long as we're connected (i.e. in the dynarray) */ pa_stream_ref(s); - if (s->interpolate) { + if (s->flags & PA_STREAM_INTERPOLATE_LATENCY) { struct timeval tv; pa_gettimeofday(&tv); @@ -418,13 +414,11 @@ static int create_stream( pa_stream_ref(s); s->direction = direction; + s->flags = flags; if (sync_stream) s->syncid = sync_stream->syncid; - s->interpolate = !!(flags & PA_STREAM_INTERPOLATE_LATENCY); - pa_stream_trash_ipol(s); - if (attr) s->buffer_attr = *attr; else { @@ -548,7 +542,33 @@ int pa_stream_write( else s->requested_bytes = 0; - s->counter += length; + /* Update latency request correction */ + if (s->latency_corrections[s->idx_latency_correction].valid) { + + if (seek == PA_SEEK_ABSOLUTE) { + s->latency_corrections[s->idx_latency_correction].corrupt = 0; + s->latency_corrections[s->idx_latency_correction].absolute = 1; + s->latency_corrections[s->idx_latency_correction].value = offset + length; + } else if (seek == PA_SEEK_RELATIVE) { + if (!s->latency_corrections[s->idx_latency_correction].corrupt) + s->latency_corrections[s->idx_latency_correction].value += offset + length; + } else + s->latency_corrections[s->idx_latency_correction].corrupt = 1; + } + + /* Update the write index in the already available latency data */ + if (s->latency_info_valid) { + + if (seek == PA_SEEK_ABSOLUTE) { + s->latency_info.write_index_corrupt = 0; + s->latency_info.write_index = offset + length; + } else if (seek == PA_SEEK_RELATIVE) { + if (!s->latency_info.write_index_corrupt) + s->latency_info.write_index += offset + length; + } else + s->latency_info.write_index_corrupt = 1; + } + return 0; } @@ -590,7 +610,6 @@ int pa_stream_drop(pa_stream *s) { s->peek_memchunk.index = 0; s->peek_memchunk.memblock = NULL; - s->counter += s->peek_memchunk.length; return 0; } @@ -637,33 +656,34 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; - pa_latency_info i, *p = NULL; struct timeval local, remote, now; + pa_latency_info *i; assert(pd); assert(o); assert(o->stream); assert(o->context); - i.counter = *(uint64_t*)pa_hashmap_get(o->stream->counter_hashmap, (void*)(unsigned long)tag); - pa_xfree(pa_hashmap_remove(o->stream->counter_hashmap, (void*)(unsigned long)tag)); + i = &o->stream->latency_info; + o->stream->latency_info_valid = 0; + i->write_index_corrupt = 0; if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - } else if (pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || - pa_tagstruct_get_usec(t, &i.sink_usec) < 0 || - pa_tagstruct_get_usec(t, &i.source_usec) < 0 || - pa_tagstruct_get_boolean(t, &i.playing) < 0 || - pa_tagstruct_getu32(t, &i.queue_length) < 0 || + } else if (pa_tagstruct_get_usec(t, &i->buffer_usec) < 0 || + pa_tagstruct_get_usec(t, &i->sink_usec) < 0 || + pa_tagstruct_get_usec(t, &i->source_usec) < 0 || + pa_tagstruct_get_boolean(t, &i->playing) < 0 || pa_tagstruct_get_timeval(t, &local) < 0 || pa_tagstruct_get_timeval(t, &remote) < 0 || - pa_tagstruct_gets64(t, &i.write_index) < 0 || - pa_tagstruct_gets64(t, &i.read_index) < 0 || + pa_tagstruct_gets64(t, &i->write_index) < 0 || + pa_tagstruct_gets64(t, &i->read_index) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; + } else { pa_gettimeofday(&now); @@ -671,72 +691,125 @@ static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, /* local and remote seem to have synchronized clocks */ if (o->stream->direction == PA_STREAM_PLAYBACK) - i.transport_usec = pa_timeval_diff(&remote, &local); + i->transport_usec = pa_timeval_diff(&remote, &local); else - i.transport_usec = pa_timeval_diff(&now, &remote); + i->transport_usec = pa_timeval_diff(&now, &remote); - i.synchronized_clocks = 1; - i.timestamp = remote; + i->synchronized_clocks = 1; + i->timestamp = remote; } else { /* clocks are not synchronized, let's estimate latency then */ - i.transport_usec = pa_timeval_diff(&now, &local)/2; - i.synchronized_clocks = 0; - i.timestamp = local; - pa_timeval_add(&i.timestamp, i.transport_usec); - } - - if (o->stream->interpolate) { -/* pa_log("new interpol data"); */ - o->stream->ipol_timestamp = i.timestamp; - o->stream->ipol_usec = pa_stream_get_time(o->stream, &i); - o->stream->ipol_requested = 0; + i->transport_usec = pa_timeval_diff(&now, &local)/2; + i->synchronized_clocks = 0; + i->timestamp = local; + pa_timeval_add(&i->timestamp, i->transport_usec); } - p = &i; + if (o->stream->direction == PA_STREAM_PLAYBACK) { + /* Write index correction */ + + int n, j; + uint32_t ctag = tag; + + /* Go through the saved correction values and add up the total correction.*/ + + for (n = 0, j = o->stream->idx_latency_correction; + n < PA_MAX_LATENCY_CORRECTIONS; + n++, j = (j + 1) % PA_MAX_LATENCY_CORRECTIONS) { + + /* Step over invalid data or out-of-date data */ + if (!o->stream->latency_corrections[j].valid || + o->stream->latency_corrections[j].tag < ctag) + continue; + + /* Make sure that everything is in order */ + ctag = o->stream->latency_corrections[j].tag+1; + + /* Now fix the write index */ + if (o->stream->latency_corrections[j].corrupt) { + /* A corrupting seek was made */ + i->write_index = 0; + i->write_index_corrupt = 1; + } else if (o->stream->latency_corrections[j].absolute) { + /* An absolute seek was made */ + i->write_index = o->stream->latency_corrections[j].value; + i->write_index_corrupt = 0; + } else if (!i->write_index_corrupt) { + /* A relative seek was made */ + i->write_index += o->stream->latency_corrections[j].value; + } + } + } + + o->stream->latency_info_valid = 1; + + o->stream->ipol_timestamp = now; + o->stream->ipol_usec_valid = 0; + } + + /* Clear old correction entries */ + if (o->stream->direction == PA_STREAM_PLAYBACK) { + int n; + + for (n = 0; n < PA_MAX_LATENCY_CORRECTIONS; n++) { + if (!o->stream->latency_corrections[n].valid) + continue; + + if (o->stream->latency_corrections[n].tag <= tag) + o->stream->latency_corrections[n].valid = 0; + } } if (o->callback) { - pa_stream_get_latency_info_cb_t cb = (pa_stream_get_latency_info_cb_t) o->callback; - cb(o->stream, p, o->userdata); + pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback; + cb(o->stream, o->stream->latency_info_valid, o->userdata); } - + finish: + pa_operation_done(o); pa_operation_unref(o); } -pa_operation* pa_stream_get_latency_info(pa_stream *s, pa_stream_get_latency_info_cb_t cb, void *userdata) { +pa_operation* pa_stream_update_latency_info(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { uint32_t tag; pa_operation *o; pa_tagstruct *t; struct timeval now; - uint64_t *counter; + int cidx; assert(s); assert(s->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY_RETURN_NULL(s->context, pa_hashmap_size(s->counter_hashmap) < COUNTER_HASHMAP_MAXSIZE, PA_ERR_INTERNAL); + + /* Find a place to store the write_index correction data for this entry */ + cidx = (s->idx_latency_correction + 1) % PA_MAX_LATENCY_CORRECTIONS; + + /* Check if we could allocate a correction slot. If not, there are too many outstanding queries */ + PA_CHECK_VALIDITY_RETURN_NULL(s->context, !s->latency_corrections[cidx].valid, PA_ERR_INTERNAL); o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); - + t = pa_tagstruct_command( s->context, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY, &tag); pa_tagstruct_putu32(t, s->channel); - - pa_gettimeofday(&now); - pa_tagstruct_put_timeval(t, &now); + pa_tagstruct_put_timeval(t, pa_gettimeofday(&now)); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_info_callback, o); - counter = pa_xmalloc(sizeof(uint64_t)); - *counter = s->counter; - pa_hashmap_put(s->counter_hashmap, (void*)(unsigned long)tag, counter); - + /* Fill in initial correction data */ + o->stream->idx_latency_correction = cidx; + o->stream->latency_corrections[cidx].valid = 1; + o->stream->latency_corrections[cidx].tag = tag; + o->stream->latency_corrections[cidx].absolute = 0; + o->stream->latency_corrections[cidx].value = 0; + o->stream->latency_corrections[cidx].corrupt = 0; + return pa_operation_ref(o); } @@ -872,11 +945,11 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - if (s->interpolate) { - if (!s->corked && b) - /* Pausing */ - s->ipol_usec = pa_stream_get_interpolated_time(s); - else if (s->corked && !b) + if (s->flags & PA_STREAM_INTERPOLATE_LATENCY) { + if (!s->corked && b) { + /* Refresh the interpolated data just befor pausing */ + pa_stream_get_time(s, NULL); + } else if (s->corked && !b) /* Unpausing */ pa_gettimeofday(&s->ipol_timestamp); } @@ -894,8 +967,7 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); - lo = pa_stream_get_latency_info(s, NULL, NULL); - if (lo) + if ((lo = pa_stream_update_latency_info(s, NULL, NULL))) pa_operation_unref(lo); return pa_operation_ref(o); @@ -928,8 +1000,8 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) { pa_operation *lo; - lo = pa_stream_get_latency_info(s, NULL, NULL); - if (lo) + + if ((lo = pa_stream_update_latency_info(s, NULL, NULL))) pa_operation_unref(lo); } @@ -943,8 +1015,8 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us if ((o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata))) { pa_operation *lo; - lo = pa_stream_get_latency_info(s, NULL, NULL); - if (lo) + + if ((lo = pa_stream_update_latency_info(s, NULL, NULL))) pa_operation_unref(lo); } @@ -958,8 +1030,8 @@ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *u if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata))) { pa_operation *lo; - lo = pa_stream_get_latency_info(s, NULL, NULL); - if (lo) + + if ((lo = pa_stream_update_latency_info(s, NULL, NULL))) pa_operation_unref(lo); } @@ -992,85 +1064,151 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe return pa_operation_ref(o); } -uint64_t pa_stream_get_counter(pa_stream *s) { - assert(s); - assert(s->ref >= 1); - - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (uint64_t) -1); - - return s->counter; -} - -pa_usec_t pa_stream_get_time(pa_stream *s, const pa_latency_info *i) { - pa_usec_t usec; +int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { + pa_usec_t usec = 0; assert(s); assert(s->ref >= 1); - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (pa_usec_t) -1); - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE, (pa_usec_t) -1); - - usec = pa_bytes_to_usec(i->counter, &s->sample_spec); + PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->latency_info_valid, PA_ERR_NODATA); - if (i) { + if (s->flags & PA_STREAM_INTERPOLATE_LATENCY && s->ipol_usec_valid ) + usec = s->ipol_usec; + else { if (s->direction == PA_STREAM_PLAYBACK) { - pa_usec_t latency = i->transport_usec + i->buffer_usec + i->sink_usec; - if (usec < latency) + /* The last byte that was written into the output device + * had this time value associated */ + usec = pa_bytes_to_usec(s->latency_info.read_index < 0 ? 0 : (uint64_t) s->latency_info.read_index, &s->sample_spec); + + /* Because the latency info took a little time to come + * to us, we assume that the real output time is actually + * a little ahead */ + usec += s->latency_info.transport_usec; + + /* However, the output device usually maintains a buffer + too, hence the real sample currently played is a little + back */ + if (s->latency_info.sink_usec >= usec) usec = 0; else - usec -= latency; - + usec -= s->latency_info.sink_usec; + } else if (s->direction == PA_STREAM_RECORD) { - usec += i->source_usec + i->buffer_usec + i->transport_usec; - - if (usec > i->sink_usec) - usec -= i->sink_usec; - else + /* The last byte written into the server side queue had + * this time value associated */ + usec = pa_bytes_to_usec(s->latency_info.write_index < 0 ? 0 : (uint64_t) s->latency_info.write_index, &s->sample_spec); + + /* Add transport latency */ + usec += s->latency_info.transport_usec; + + /* Add latency of data in device buffer */ + usec += s->latency_info.source_usec; + + /* If this is a monitor source, we need to correct the + * time by the playback device buffer */ + if (s->latency_info.sink_usec >= usec) usec = 0; + else + usec -= s->latency_info.sink_usec; + } + + if (s->flags & PA_STREAM_INTERPOLATE_LATENCY) { + s->ipol_usec_valid = 1; + s->ipol_usec = usec; } } - if (usec < s->previous_time) - usec = s->previous_time; + /* Interpolate if requested */ + if (s->flags & PA_STREAM_INTERPOLATE_LATENCY) { - s->previous_time = usec; + /* We just add the time that passed since the latency info was + * current */ + if (!s->corked) { + struct timeval now; + + usec += pa_timeval_diff(pa_gettimeofday(&now), &s->ipol_timestamp); + s->ipol_timestamp = now; + } + } - return usec; + /* Make sure the time runs monotonically */ + if (!(s->flags & PA_STREAM_NOT_MONOTONOUS)) { + if (usec < s->previous_time) + usec = s->previous_time; + else + s->previous_time = usec; + } + + if (r_usec) + *r_usec = usec; + + return 0; } -static pa_usec_t time_counter_diff(pa_stream *s, pa_usec_t t, pa_usec_t c, int *negative) { +static pa_usec_t time_counter_diff(pa_stream *s, pa_usec_t a, pa_usec_t b, int *negative) { assert(s); assert(s->ref >= 1); if (negative) *negative = 0; - if (c < t) { - if (s->direction == PA_STREAM_RECORD) { - if (negative) - *negative = 1; - - return t-c; + if (a >= b) + return a-b; + else { + if (negative && s->direction == PA_STREAM_RECORD) { + *negative = 1; + return b-a; } else return 0; - } else - return c-t; + } } -pa_usec_t pa_stream_get_latency(pa_stream *s, const pa_latency_info *i, int *negative) { +int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) { pa_usec_t t, c; + int r; + int64_t cindex; assert(s); assert(s->ref >= 1); - assert(i); + assert(r_usec); - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (pa_usec_t) -1); - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE, (pa_usec_t) -1); + PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->latency_info_valid, PA_ERR_NODATA); + PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->latency_info.write_index_corrupt, PA_ERR_NODATA); - t = pa_stream_get_time(s, i); - c = pa_bytes_to_usec(s->counter, &s->sample_spec); + if ((r = pa_stream_get_time(s, &t)) < 0) + return r; - return time_counter_diff(s, t, c, negative); + if (s->direction == PA_STREAM_PLAYBACK) + cindex = s->latency_info.write_index; + else + cindex = s->latency_info.read_index; + + if (cindex < 0) + cindex = 0; + + c = pa_bytes_to_usec(cindex, &s->sample_spec); + + if (s->direction == PA_STREAM_PLAYBACK) + *r_usec = time_counter_diff(s, c, t, negative); + else + *r_usec = time_counter_diff(s, t, c, negative); + + return 0; +} + +const pa_latency_info* pa_stream_get_latency_info(pa_stream *s) { + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->latency_info_valid, PA_ERR_BADSTATE); + + return &s->latency_info; } const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s) { @@ -1087,55 +1225,4 @@ const pa_channel_map* pa_stream_get_channel_map(pa_stream *s) { return &s->channel_map; } -void pa_stream_trash_ipol(pa_stream *s) { - assert(s); - assert(s->ref >= 1); - if (!s->interpolate) - return; - - memset(&s->ipol_timestamp, 0, sizeof(s->ipol_timestamp)); - s->ipol_usec = 0; -} - -pa_usec_t pa_stream_get_interpolated_time(pa_stream *s) { - pa_usec_t usec; - - assert(s); - assert(s->ref >= 1); - - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (pa_usec_t) -1); - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE, (pa_usec_t) -1); - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->interpolate, PA_ERR_BADSTATE, (pa_usec_t) -1); - - if (s->corked) - usec = s->ipol_usec; - else { - if (s->ipol_timestamp.tv_sec == 0) - usec = 0; - else - usec = s->ipol_usec + pa_timeval_age(&s->ipol_timestamp); - } - - if (usec < s->previous_ipol_time) - usec = s->previous_ipol_time; - - s->previous_ipol_time = usec; - - return usec; -} - -pa_usec_t pa_stream_get_interpolated_latency(pa_stream *s, int *negative) { - pa_usec_t t, c; - - assert(s); - assert(s->ref >= 1); - - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (pa_usec_t) -1); - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE, (pa_usec_t) -1); - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->interpolate, PA_ERR_BADSTATE, (pa_usec_t) -1); - - t = pa_stream_get_interpolated_time(s); - c = pa_bytes_to_usec(s->counter, &s->sample_spec); - return time_counter_diff(s, t, c, negative); -} diff --git a/src/polyp/stream.h b/src/polyp/stream.h index 75b0a9001..99284ba35 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -51,9 +51,6 @@ typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t length, void *userda /** A generic notification callback */ typedef void (*pa_stream_notify_cb_t)(pa_stream *p, void *userdata); -/** Callback prototype for pa_stream_get_latency_info() */ -typedef void (*pa_stream_get_latency_info_cb_t)(pa_stream *p, const pa_latency_info *i, void *userdata); - /** Create a new, unconnected stream with the specified name and sample type */ pa_stream* pa_stream_new( pa_context *c /**< The context to create this stream in */, @@ -133,8 +130,8 @@ size_t pa_stream_readable_size(pa_stream *p); /** Drain a playback stream. Use this for notification when the buffer is empty */ pa_operation* pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *userdata); -/** Get the playback latency of a stream */ -pa_operation* pa_stream_get_latency_info(pa_stream *p, pa_stream_get_latency_info_cb_t cby, void *userdata); +/** Update the latency info of a stream */ +pa_operation* pa_stream_update_latency_info(pa_stream *p, pa_stream_success_cb_t cb, void *userdata); /** Set the callback function that is called whenever the state of the stream changes */ void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata); @@ -173,34 +170,21 @@ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *u /** Rename the stream. \since 0.5 */ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata); -/** Return the total number of bytes written to/read from the - * stream. This counter is not reset on pa_stream_flush(), you may do - * this yourself using pa_stream_reset_counter(). \since 0.6 */ -uint64_t pa_stream_get_counter(pa_stream *s); - /** Return the current playback/recording time. This is based on the * counter accessible with pa_stream_get_counter(). This function * requires a pa_latency_info structure as argument, which should be * acquired using pa_stream_get_latency(). \since 0.6 */ -pa_usec_t pa_stream_get_time(pa_stream *s, const pa_latency_info *i); +int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec); /** Return the total stream latency. Thus function requires a * pa_latency_info structure as argument, which should be aquired * using pa_stream_get_latency(). In case the stream is a monitoring * stream the result can be negative, i.e. the captured samples are * not yet played. In this case *negative is set to 1. \since 0.6 */ -pa_usec_t pa_stream_get_latency(pa_stream *s, const pa_latency_info *i, int *negative); +int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative); -/** Return the interpolated playback/recording time. Requires the - * PA_STREAM_INTERPOLATE_LATENCY bit set when creating the stream. In - * contrast to pa_stream_get_latency() this function doesn't require - * a whole roundtrip for response. \since 0.6 */ -pa_usec_t pa_stream_get_interpolated_time(pa_stream *s); - -/** Return the interpolated playback/recording latency. Requires the - * PA_STREAM_INTERPOLATE_LATENCY bit set when creating the - * stream. \since 0.6 */ -pa_usec_t pa_stream_get_interpolated_latency(pa_stream *s, int *negative); +/** Return the latest latency data. \since 0.8 */ +const pa_latency_info* pa_stream_get_latency_info(pa_stream *s); /** Return a pointer to the stream's sample specification. \since 0.6 */ const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s); From 53a0056cdf3467cc98740e61b781935ef0ed5ac4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 00:25:05 +0000 Subject: [PATCH 0556/1514] update pacat.c for new latency API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@649 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 43e671444..8d9cff0be 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -339,28 +340,34 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, } /* Show the current latency */ -static void stream_get_latency_callback(pa_stream *s, const pa_latency_info *i, void *userdata) { +static void stream_update_latency_callback(pa_stream *s, int success, void *userdata) { pa_usec_t total; int negative = 0; + const pa_latency_info *i; + assert(s); - if (!i) { + if (!success || + !(i = pa_stream_get_latency_info(s)) || + pa_stream_get_latency(s, &total, &negative) < 0) { fprintf(stderr, "Failed to get latency: %s\n", pa_strerror(pa_context_errno(context))); quit(1); return; } - total = pa_stream_get_latency(s, i, &negative); - fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; source: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n", - (float) i->buffer_usec, (float) i->sink_usec, (float) i->source_usec, (float) i->transport_usec, (float) total * (negative?-1:1), + (float) i->buffer_usec, + (float) i->sink_usec, + (float) i->source_usec, + (float) i->transport_usec, + (float) total * (negative?-1:1), i->synchronized_clocks ? "yes" : "no"); } /* Someone requested that the latency is shown */ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); - pa_operation_unref(pa_stream_get_latency_info(stream, stream_get_latency_callback, NULL)); + pa_operation_unref(pa_stream_update_latency_info(stream, stream_update_latency_callback, NULL)); } @@ -511,6 +518,27 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Opening a %s stream with sample specification '%s'.\n", mode == RECORD ? "recording" : "playback", t); } + if (optind+1 < argc) { + fprintf(stderr, "Too many arguments.\n"); + goto quit; + } + + if (optind+1 == argc) { + int fd; + + if ((fd = open(argv[optind], O_RDONLY)) < 0) { + fprintf(stderr, "open(): %s\n", strerror(errno)); + goto quit; + } + + if (dup2(fd, 0) < 0) { + fprintf(stderr, "dup2(): %s\n", strerror(errno)); + goto quit; + } + + close(fd); + } + /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); From c0592bb27c28b7b7902a6b780daf89344bc3516d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 00:25:19 +0000 Subject: [PATCH 0557/1514] update simple API for new latency API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@650 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/simple.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/polyp/simple.c b/src/polyp/simple.c index eabcf1eaf..2593d5fa8 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -345,18 +345,19 @@ int pa_simple_drain(pa_simple *p, int *rerror) { return p->dead ? -1 : 0; } -static void latency_complete(pa_stream *s, const pa_latency_info *l, void *userdata) { +static void latency_complete(pa_stream *s, int success, void *userdata) { pa_simple *p = userdata; assert(s); assert(p); - if (!l) + if (!success) p->dead = 1; else { int negative = 0; - p->latency = pa_stream_get_latency(s, l, &negative); - if (negative) + if (pa_stream_get_latency(s, &p->latency, &negative) < 0) + p->dead = 1; + else if (negative) p->latency = 0; } } @@ -376,7 +377,7 @@ pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) { } p->latency = 0; - if (!(o = pa_stream_get_latency_info(p->stream, latency_complete, p))) { + if (!(o = pa_stream_update_latency_info(p->stream, latency_complete, p))) { if (rerror) *rerror = pa_context_errno(p->context); return (pa_usec_t) -1; From b8a729a00f170241599e670ee3f3f65457b4320f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 01:29:33 +0000 Subject: [PATCH 0558/1514] * update docs for reworked latency API * rename pa_latency_info to pa_timing_info, since that describes better what it is. Most people will only use pa_stream_get_time() anyway git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@651 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/def.h | 85 ++++++++++++++++++++++++++++--------------- src/polyp/internal.h | 6 ++-- src/polyp/simple.c | 4 +-- src/polyp/stream.c | 86 ++++++++++++++++++++++---------------------- src/polyp/stream.h | 46 +++++++++++++++++------- src/utils/pacat.c | 9 +++-- 6 files changed, 142 insertions(+), 94 deletions(-) diff --git a/src/polyp/def.h b/src/polyp/def.h index 93d0996b3..659b943b5 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -80,22 +80,44 @@ typedef enum pa_stream_direction { /** Some special flags for stream connections. \since 0.6 */ typedef enum pa_stream_flags { PA_STREAM_START_CORKED = 1, /**< Create the stream corked, requiring an explicit pa_stream_cork() call to uncork it. */ - PA_STREAM_INTERPOLATE_LATENCY = 2, /**< Interpolate the latency for + PA_STREAM_INTERPOLATE_TIMING = 2, /**< Interpolate the latency for * this stream. When enabled, - * you can use - * pa_stream_interpolated_xxx() - * for synchronization. Using - * these functions instead of - * pa_stream_get_latency() has - * the advantage of not - * requiring a whole roundtrip - * for responses. Consider using - * this option when frequently - * requesting latency - * information. This is - * especially useful on long latency - * network connections. */ - PA_STREAM_NOT_MONOTONOUS = 4, /**< Don't force the time to run monotonically */ + * pa_stream_get_latency() and pa_stream_get_time() + * will try to estimate the + * current record/playback time + * based on the local time that + * passed since the last timing + * info update. In addition + * timing update requests are + * issued periodically + * automatically. Using this + * option has the advantage of + * not requiring a whole + * roundtrip when the current + * playback/recording time is + * needed. Consider using this + * option when requesting + * latency information + * frequently. This is + * especially useful on long + * latency network + * connections. */ + PA_STREAM_NOT_MONOTONOUS = 4, /**< Don't force the time to + * increase monotonically. If + * this option is enabled, + * pa_stream_get_time() will not + * necessarily return always + * monotonically increasing time + * values on each call. This may + * confuse applications which + * cannot deal with time going + * 'backwards', but has the + * advantage that bad transport + * latency estimations that + * caused the time to to jump + * ahead can be corrected + * quickly, without the need to + * wait. */ } pa_stream_flags_t; /** Playback and record buffer metrics */ @@ -167,21 +189,23 @@ typedef enum pa_subscription_event_type { /** Return one if an event type t matches an event mask bitfield */ #define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)))) -/** A structure for latency info. See pa_stream_get_latency(). The +/** A structure for all kinds of timing information of a stream. See + * pa_stream_update_timing_info() and pa_stream_get_timing_info(). The * total output latency a sample that is written with * pa_stream_write() takes to be played may be estimated by * sink_usec+buffer_usec+transport_usec. The output buffer to which * buffer_usec relates may be manipulated freely (with * pa_stream_write()'s seek argument, pa_stream_flush() and friends), - * the buffers sink_usec/source_usec relates to is a first-in - * first-out buffer which cannot be flushed or manipulated in any + * the buffers sink_usec and source_usec relate to are first-in + * first-out (FIFO) buffers which cannot be flushed or manipulated in any * way. The total input latency a sample that is recorded takes to be * delivered to the application is: * source_usec+buffer_usec+transport_usec-sink_usec. (Take care of * sign issues!) When connected to a monitor source sink_usec contains - * the latency of the owning sink.*/ -typedef struct pa_latency_info { - struct timeval timestamp; /**< The time when this latency info was current */ + * the latency of the owning sink. The two latency estimations + * described here are implemented in pa_stream_get_latency().*/ +typedef struct pa_timing_info { + struct timeval timestamp; /**< The time when this timing info structure was current */ int synchronized_clocks; /**< Non-zero if the local and the * remote machine have synchronized * clocks. If synchronized clocks are @@ -198,7 +222,14 @@ typedef struct pa_latency_info { int playing; /**< Non-zero when the stream is currently playing. Only for playback streams. */ - int write_index_corrupt; /**< Non-Zero if the write_index is not up to date because a local write command corrupted it */ + int write_index_corrupt; /**< Non-zero if write_index is not + * up-to-date because a local write + * command that corrupted it has been + * issued in the time since this latency + * info was current . Only write + * commands with SEEK_RELATIVE_ON_READ + * and SEEK_RELATIVE_END can corrupt + * write_index. */ int64_t write_index; /**< Current write index into the * playback buffer in bytes. Think twice before * using this for seeking purposes: it @@ -213,9 +244,7 @@ typedef struct pa_latency_info { * want to use it. Consider using * PA_SEEK_RELATIVE_ON_READ * instead. \since 0.8 */ - - uint32_t buffer_length; /* Current buffer length. This is usually identical to write_index-read_index. */ -} pa_latency_info; +} pa_timing_info; /** A structure for the spawn api. This may be used to integrate auto * spawned daemons into your application. For more information see @@ -236,12 +265,12 @@ typedef struct pa_spawn_api { * passed to the new process. */ } pa_spawn_api; -/** Seek type \since 0.8*/ +/** Seek type for pa_stream_write(). \since 0.8*/ typedef enum pa_seek_mode { PA_SEEK_RELATIVE = 0, /**< Seek relatively to the write index */ PA_SEEK_ABSOLUTE = 1, /**< Seek relatively to the start of the buffer queue */ - PA_SEEK_RELATIVE_ON_READ = 2, /**< Seek relatively to the read index */ - PA_SEEK_RELATIVE_END = 3, /**< Seek relatively to the current end of the buffer queue */ + PA_SEEK_RELATIVE_ON_READ = 2, /**< Seek relatively to the read index. */ + PA_SEEK_RELATIVE_END = 3, /**< Seek relatively to the current end of the buffer queue. */ } pa_seek_mode_t; PA_C_DECL_END diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 8f1603b32..3b85b3d11 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -118,8 +118,8 @@ struct pa_stream { int corked; /* Store latest latency info */ - pa_latency_info latency_info; - int latency_info_valid; + pa_timing_info timing_info; + int timing_info_valid; /* Use to make sure that time advances monotonically */ pa_usec_t previous_time; @@ -182,8 +182,6 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, vo void pa_stream_set_state(pa_stream *s, pa_stream_state_t st); -void pa_stream_trash_ipol(pa_stream *s); - pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag); #define PA_CHECK_VALIDITY(context, expression, error) do { \ diff --git a/src/polyp/simple.c b/src/polyp/simple.c index 2593d5fa8..f48c0b176 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -345,7 +345,7 @@ int pa_simple_drain(pa_simple *p, int *rerror) { return p->dead ? -1 : 0; } -static void latency_complete(pa_stream *s, int success, void *userdata) { +static void timing_complete(pa_stream *s, int success, void *userdata) { pa_simple *p = userdata; assert(s); @@ -377,7 +377,7 @@ pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) { } p->latency = 0; - if (!(o = pa_stream_update_latency_info(p->stream, latency_complete, p))) { + if (!(o = pa_stream_update_timing_info(p->stream, timing_complete, p))) { if (rerror) *rerror = pa_context_errno(p->context); return (pa_usec_t) -1; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index d3599582e..de27954ca 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -89,7 +89,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->record_memblockq = NULL; s->previous_time = 0; - s->latency_info_valid = 0; + s->timing_info_valid = 0; s->corked = 0; @@ -311,7 +311,7 @@ static void ipol_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED co if (s->state == PA_STREAM_READY && !s->ipol_requested) { pa_operation *o; - if ((o = pa_stream_update_latency_info(s, NULL, NULL))) { + if ((o = pa_stream_update_timing_info(s, NULL, NULL))) { pa_operation_unref(o); s->ipol_requested = 1; } @@ -371,7 +371,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED /* We add an extra ref as long as we're connected (i.e. in the dynarray) */ pa_stream_ref(s); - if (s->flags & PA_STREAM_INTERPOLATE_LATENCY) { + if (s->flags & PA_STREAM_INTERPOLATE_TIMING) { struct timeval tv; pa_gettimeofday(&tv); @@ -406,7 +406,7 @@ static int create_stream( assert(s->ref >= 1); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY(s->context, !(flags & ~(PA_STREAM_START_CORKED|PA_STREAM_INTERPOLATE_LATENCY)), PA_ERR_INVALID); + PA_CHECK_VALIDITY(s->context, !(flags & ~(PA_STREAM_START_CORKED|PA_STREAM_INTERPOLATE_TIMING)), PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, direction == PA_STREAM_PLAYBACK || flags == 0, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID); @@ -557,16 +557,16 @@ int pa_stream_write( } /* Update the write index in the already available latency data */ - if (s->latency_info_valid) { + if (s->timing_info_valid) { if (seek == PA_SEEK_ABSOLUTE) { - s->latency_info.write_index_corrupt = 0; - s->latency_info.write_index = offset + length; + s->timing_info.write_index_corrupt = 0; + s->timing_info.write_index = offset + length; } else if (seek == PA_SEEK_RELATIVE) { - if (!s->latency_info.write_index_corrupt) - s->latency_info.write_index += offset + length; + if (!s->timing_info.write_index_corrupt) + s->timing_info.write_index += offset + length; } else - s->latency_info.write_index_corrupt = 1; + s->timing_info.write_index_corrupt = 1; } return 0; @@ -654,18 +654,18 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us return pa_operation_ref(o); } -static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { +static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; struct timeval local, remote, now; - pa_latency_info *i; + pa_timing_info *i; assert(pd); assert(o); assert(o->stream); assert(o->context); - i = &o->stream->latency_info; - o->stream->latency_info_valid = 0; + i = &o->stream->timing_info; + o->stream->timing_info_valid = 0; i->write_index_corrupt = 0; if (command != PA_COMMAND_REPLY) { @@ -741,7 +741,7 @@ static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, } } - o->stream->latency_info_valid = 1; + o->stream->timing_info_valid = 1; o->stream->ipol_timestamp = now; o->stream->ipol_usec_valid = 0; @@ -762,7 +762,7 @@ static void stream_get_latency_info_callback(pa_pdispatch *pd, uint32_t command, if (o->callback) { pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback; - cb(o->stream, o->stream->latency_info_valid, o->userdata); + cb(o->stream, o->stream->timing_info_valid, o->userdata); } finish: @@ -771,7 +771,7 @@ finish: pa_operation_unref(o); } -pa_operation* pa_stream_update_latency_info(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { +pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { uint32_t tag; pa_operation *o; pa_tagstruct *t; @@ -800,7 +800,7 @@ pa_operation* pa_stream_update_latency_info(pa_stream *s, pa_stream_success_cb_t pa_tagstruct_put_timeval(t, pa_gettimeofday(&now)); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_info_callback, o); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_timing_info_callback, o); /* Fill in initial correction data */ o->stream->idx_latency_correction = cidx; @@ -945,7 +945,7 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - if (s->flags & PA_STREAM_INTERPOLATE_LATENCY) { + if (s->flags & PA_STREAM_INTERPOLATE_TIMING) { if (!s->corked && b) { /* Refresh the interpolated data just befor pausing */ pa_stream_get_time(s, NULL); @@ -967,7 +967,7 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); - if ((lo = pa_stream_update_latency_info(s, NULL, NULL))) + if ((lo = pa_stream_update_timing_info(s, NULL, NULL))) pa_operation_unref(lo); return pa_operation_ref(o); @@ -1001,7 +1001,7 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) { pa_operation *lo; - if ((lo = pa_stream_update_latency_info(s, NULL, NULL))) + if ((lo = pa_stream_update_timing_info(s, NULL, NULL))) pa_operation_unref(lo); } @@ -1016,7 +1016,7 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us if ((o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata))) { pa_operation *lo; - if ((lo = pa_stream_update_latency_info(s, NULL, NULL))) + if ((lo = pa_stream_update_timing_info(s, NULL, NULL))) pa_operation_unref(lo); } @@ -1031,7 +1031,7 @@ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *u if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata))) { pa_operation *lo; - if ((lo = pa_stream_update_latency_info(s, NULL, NULL))) + if ((lo = pa_stream_update_timing_info(s, NULL, NULL))) pa_operation_unref(lo); } @@ -1072,56 +1072,56 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY(s->context, s->latency_info_valid, PA_ERR_NODATA); + PA_CHECK_VALIDITY(s->context, s->timing_info_valid, PA_ERR_NODATA); - if (s->flags & PA_STREAM_INTERPOLATE_LATENCY && s->ipol_usec_valid ) + if (s->flags & PA_STREAM_INTERPOLATE_TIMING && s->ipol_usec_valid ) usec = s->ipol_usec; else { if (s->direction == PA_STREAM_PLAYBACK) { /* The last byte that was written into the output device * had this time value associated */ - usec = pa_bytes_to_usec(s->latency_info.read_index < 0 ? 0 : (uint64_t) s->latency_info.read_index, &s->sample_spec); + usec = pa_bytes_to_usec(s->timing_info.read_index < 0 ? 0 : (uint64_t) s->timing_info.read_index, &s->sample_spec); /* Because the latency info took a little time to come * to us, we assume that the real output time is actually * a little ahead */ - usec += s->latency_info.transport_usec; + usec += s->timing_info.transport_usec; /* However, the output device usually maintains a buffer too, hence the real sample currently played is a little back */ - if (s->latency_info.sink_usec >= usec) + if (s->timing_info.sink_usec >= usec) usec = 0; else - usec -= s->latency_info.sink_usec; + usec -= s->timing_info.sink_usec; } else if (s->direction == PA_STREAM_RECORD) { /* The last byte written into the server side queue had * this time value associated */ - usec = pa_bytes_to_usec(s->latency_info.write_index < 0 ? 0 : (uint64_t) s->latency_info.write_index, &s->sample_spec); + usec = pa_bytes_to_usec(s->timing_info.write_index < 0 ? 0 : (uint64_t) s->timing_info.write_index, &s->sample_spec); /* Add transport latency */ - usec += s->latency_info.transport_usec; + usec += s->timing_info.transport_usec; /* Add latency of data in device buffer */ - usec += s->latency_info.source_usec; + usec += s->timing_info.source_usec; /* If this is a monitor source, we need to correct the * time by the playback device buffer */ - if (s->latency_info.sink_usec >= usec) + if (s->timing_info.sink_usec >= usec) usec = 0; else - usec -= s->latency_info.sink_usec; + usec -= s->timing_info.sink_usec; } - if (s->flags & PA_STREAM_INTERPOLATE_LATENCY) { + if (s->flags & PA_STREAM_INTERPOLATE_TIMING) { s->ipol_usec_valid = 1; s->ipol_usec = usec; } } /* Interpolate if requested */ - if (s->flags & PA_STREAM_INTERPOLATE_LATENCY) { + if (s->flags & PA_STREAM_INTERPOLATE_TIMING) { /* We just add the time that passed since the latency info was * current */ @@ -1176,16 +1176,16 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) { PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY(s->context, s->latency_info_valid, PA_ERR_NODATA); - PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->latency_info.write_index_corrupt, PA_ERR_NODATA); + PA_CHECK_VALIDITY(s->context, s->timing_info_valid, PA_ERR_NODATA); + PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->timing_info.write_index_corrupt, PA_ERR_NODATA); if ((r = pa_stream_get_time(s, &t)) < 0) return r; if (s->direction == PA_STREAM_PLAYBACK) - cindex = s->latency_info.write_index; + cindex = s->timing_info.write_index; else - cindex = s->latency_info.read_index; + cindex = s->timing_info.read_index; if (cindex < 0) cindex = 0; @@ -1200,15 +1200,15 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) { return 0; } -const pa_latency_info* pa_stream_get_latency_info(pa_stream *s) { +const pa_timing_info* pa_stream_get_timing_info(pa_stream *s) { assert(s); assert(s->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->latency_info_valid, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->timing_info_valid, PA_ERR_BADSTATE); - return &s->latency_info; + return &s->timing_info; } const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s) { diff --git a/src/polyp/stream.h b/src/polyp/stream.h index 99284ba35..ce0419868 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -130,8 +130,11 @@ size_t pa_stream_readable_size(pa_stream *p); /** Drain a playback stream. Use this for notification when the buffer is empty */ pa_operation* pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *userdata); -/** Update the latency info of a stream */ -pa_operation* pa_stream_update_latency_info(pa_stream *p, pa_stream_success_cb_t cb, void *userdata); +/** Request a timing info structure update for a stream. Use + * pa_stream_get_timing_info() to get access to the raw timing data, + * or pa_stream_get_time() or pa_stream_get_latency() to get cleaned + * up values. */ +pa_operation* pa_stream_update_timing_info(pa_stream *p, pa_stream_success_cb_t cb, void *userdata); /** Set the callback function that is called whenever the state of the stream changes */ void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata); @@ -171,20 +174,39 @@ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *u pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata); /** Return the current playback/recording time. This is based on the - * counter accessible with pa_stream_get_counter(). This function - * requires a pa_latency_info structure as argument, which should be - * acquired using pa_stream_get_latency(). \since 0.6 */ + * data in the timing info structure returned by + * pa_stream_get_timing_info(). This function will usually only return + * new data if a timing info update has been recieved. Only if timing + * interpolation has been requested (PA_STREAM_INTERPOLATE_TIMING) + * the data from the last timing update is used for an estimation of + * the current playback/recording time based on the local time that + * passed since the timing info structure has been acquired. The time + * value returned by this function is guaranteed to increase + * monotonically. (that means: the returned value is always greater or + * equal to the value returned on the last call) This behaviour can + * be disabled by using PA_STREAM_NOT_MONOTONOUS. This may be + * desirable to deal better with bad estimations of transport + * latencies, but may have strange effects if the application is not + * able to deal with time going 'backwards'. \since 0.6 */ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec); -/** Return the total stream latency. Thus function requires a - * pa_latency_info structure as argument, which should be aquired - * using pa_stream_get_latency(). In case the stream is a monitoring - * stream the result can be negative, i.e. the captured samples are - * not yet played. In this case *negative is set to 1. \since 0.6 */ +/** Return the total stream latency. This function is based on + * pa_stream_get_time(). In case the stream is a monitoring stream the + * result can be negative, i.e. the captured samples are not yet + * played. In this case *negative is set to 1. \since 0.6 */ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative); -/** Return the latest latency data. \since 0.8 */ -const pa_latency_info* pa_stream_get_latency_info(pa_stream *s); +/** Return the latest raw timing data structure. The returned pointer + * points to an internal read-only instance of the timing + * structure. The user should make a copy of this structure if he + * wants to modify it. An in-place update to this data structure may + * be requested using pa_stream_update_timing_info(). If no + * pa_stream_update_timing_info() call was issued before, this + * function will fail with PA_ERR_NODATA. Please note that the + * write_index member field (and only this field) is updated on each + * pa_stream_write() call, not just when a timing update has been + * recieved. \since 0.8 */ +const pa_timing_info* pa_stream_get_timing_info(pa_stream *s); /** Return a pointer to the stream's sample specification. \since 0.6 */ const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 8d9cff0be..441e26070 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -340,15 +340,15 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, } /* Show the current latency */ -static void stream_update_latency_callback(pa_stream *s, int success, void *userdata) { +static void stream_update_timing_callback(pa_stream *s, int success, void *userdata) { pa_usec_t total; int negative = 0; - const pa_latency_info *i; + const pa_timing_info *i; assert(s); if (!success || - !(i = pa_stream_get_latency_info(s)) || + !(i = pa_stream_get_timing_info(s)) || pa_stream_get_latency(s, &total, &negative) < 0) { fprintf(stderr, "Failed to get latency: %s\n", pa_strerror(pa_context_errno(context))); quit(1); @@ -366,8 +366,7 @@ static void stream_update_latency_callback(pa_stream *s, int success, void *user /* Someone requested that the latency is shown */ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { - fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); - pa_operation_unref(pa_stream_update_latency_info(stream, stream_update_latency_callback, NULL)); + pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); } From a9f4896d2e17644f749d1f0c4ff49c7449f8e6e3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 01:31:33 +0000 Subject: [PATCH 0559/1514] hdie some more git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@652 fefdeb5f-60dc-0310-8127-8f9354f1896f From e5a5b56d6efd10279d4a2557f29fce9b5d7e956a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 01:32:33 +0000 Subject: [PATCH 0560/1514] remove yet another item from the todo list git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@653 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index d36b194ee..2c2d7d0d9 100644 --- a/doc/todo +++ b/doc/todo @@ -5,7 +5,6 @@ Test: - module-tunnel Fixes: -- latency api rework for native protocol - module-oss-* love: - deal with underflows propely - improve latency measurement for mmap From add110bd10de93a8f42fc1449ce4e0ff6ee8d261 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 7 Apr 2006 06:29:59 +0000 Subject: [PATCH 0561/1514] Some memcpy arithmetic that wasn't removed when doing the redesign to update the data pointer instead. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@654 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index e98711780..e29c44c9d 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -669,7 +669,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ format = MAYBE_INT32_SWAP(c->swap_byte_order, format); data = (const char*)data + sizeof(int32_t); - memcpy(&rate, (const char*)data + sizeof(int32_t), sizeof(int32_t)); + memcpy(&rate, data, sizeof(int32_t)); rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); data = (const char*)data + sizeof(int32_t); From 22558b5e0e6b185bea178ea3630dcdf1d4ec2bf7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 21:10:35 +0000 Subject: [PATCH 0562/1514] fix pkg-config files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@655 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyplib-glib-mainloop.pc.in | 2 +- polyplib-glib12-mainloop.pc.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/polyplib-glib-mainloop.pc.in b/polyplib-glib-mainloop.pc.in index 0e8b4d8c3..3d8f39315 100644 --- a/polyplib-glib-mainloop.pc.in +++ b/polyplib-glib-mainloop.pc.in @@ -8,4 +8,4 @@ Description: GLIB main loop wrapper for polypaudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpolyp-mainloop-glib-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib-mainloop glib-2.0 +Requires: polyplib glib-2.0 diff --git a/polyplib-glib12-mainloop.pc.in b/polyplib-glib12-mainloop.pc.in index 8687776bd..5ada2e5c8 100644 --- a/polyplib-glib12-mainloop.pc.in +++ b/polyplib-glib12-mainloop.pc.in @@ -8,4 +8,4 @@ Description: GLIB main loop wrapper for polypaudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpolyp-mainloop-glib12-@PA_MAJORMINOR@ Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib-mainloop glib +Requires: polyplib glib From fdb48b43401db4e15857be5239eff2f76abd8c7c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 21:55:55 +0000 Subject: [PATCH 0563/1514] * enable write_index correction and timing interpolation only for playback (and record) streams git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@656 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 85 +++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index de27954ca..4a98dd606 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -371,7 +371,8 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED /* We add an extra ref as long as we're connected (i.e. in the dynarray) */ pa_stream_ref(s); - if (s->flags & PA_STREAM_INTERPOLATE_TIMING) { + if (s->direction != PA_STREAM_UPLOAD && + s->flags & PA_STREAM_INTERPOLATE_TIMING) { struct timeval tv; pa_gettimeofday(&tv); @@ -542,31 +543,33 @@ int pa_stream_write( else s->requested_bytes = 0; - /* Update latency request correction */ - if (s->latency_corrections[s->idx_latency_correction].valid) { - - if (seek == PA_SEEK_ABSOLUTE) { - s->latency_corrections[s->idx_latency_correction].corrupt = 0; - s->latency_corrections[s->idx_latency_correction].absolute = 1; - s->latency_corrections[s->idx_latency_correction].value = offset + length; - } else if (seek == PA_SEEK_RELATIVE) { - if (!s->latency_corrections[s->idx_latency_correction].corrupt) - s->latency_corrections[s->idx_latency_correction].value += offset + length; - } else - s->latency_corrections[s->idx_latency_correction].corrupt = 1; - } - - /* Update the write index in the already available latency data */ - if (s->timing_info_valid) { - - if (seek == PA_SEEK_ABSOLUTE) { - s->timing_info.write_index_corrupt = 0; - s->timing_info.write_index = offset + length; - } else if (seek == PA_SEEK_RELATIVE) { - if (!s->timing_info.write_index_corrupt) - s->timing_info.write_index += offset + length; - } else - s->timing_info.write_index_corrupt = 1; + if (s->direction == PA_STREAM_PLAYBACK) { + /* Update latency request correction */ + if (s->latency_corrections[s->idx_latency_correction].valid) { + + if (seek == PA_SEEK_ABSOLUTE) { + s->latency_corrections[s->idx_latency_correction].corrupt = 0; + s->latency_corrections[s->idx_latency_correction].absolute = 1; + s->latency_corrections[s->idx_latency_correction].value = offset + length; + } else if (seek == PA_SEEK_RELATIVE) { + if (!s->latency_corrections[s->idx_latency_correction].corrupt) + s->latency_corrections[s->idx_latency_correction].value += offset + length; + } else + s->latency_corrections[s->idx_latency_correction].corrupt = 1; + } + + /* Update the write index in the already available latency data */ + if (s->timing_info_valid) { + + if (seek == PA_SEEK_ABSOLUTE) { + s->timing_info.write_index_corrupt = 0; + s->timing_info.write_index = offset + length; + } else if (seek == PA_SEEK_RELATIVE) { + if (!s->timing_info.write_index_corrupt) + s->timing_info.write_index += offset + length; + } else + s->timing_info.write_index_corrupt = 1; + } } return 0; @@ -759,7 +762,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, o->stream->latency_corrections[n].valid = 0; } } - + if (o->callback) { pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback; cb(o->stream, o->stream->timing_info_valid, o->userdata); @@ -784,11 +787,13 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - /* Find a place to store the write_index correction data for this entry */ - cidx = (s->idx_latency_correction + 1) % PA_MAX_LATENCY_CORRECTIONS; - - /* Check if we could allocate a correction slot. If not, there are too many outstanding queries */ - PA_CHECK_VALIDITY_RETURN_NULL(s->context, !s->latency_corrections[cidx].valid, PA_ERR_INTERNAL); + if (s->direction == PA_STREAM_PLAYBACK) { + /* Find a place to store the write_index correction data for this entry */ + cidx = (s->idx_latency_correction + 1) % PA_MAX_LATENCY_CORRECTIONS; + + /* Check if we could allocate a correction slot. If not, there are too many outstanding queries */ + PA_CHECK_VALIDITY_RETURN_NULL(s->context, !s->latency_corrections[cidx].valid, PA_ERR_INTERNAL); + } o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); @@ -802,13 +807,15 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_timing_info_callback, o); - /* Fill in initial correction data */ - o->stream->idx_latency_correction = cidx; - o->stream->latency_corrections[cidx].valid = 1; - o->stream->latency_corrections[cidx].tag = tag; - o->stream->latency_corrections[cidx].absolute = 0; - o->stream->latency_corrections[cidx].value = 0; - o->stream->latency_corrections[cidx].corrupt = 0; + if (s->direction == PA_STREAM_PLAYBACK) { + /* Fill in initial correction data */ + o->stream->idx_latency_correction = cidx; + o->stream->latency_corrections[cidx].valid = 1; + o->stream->latency_corrections[cidx].tag = tag; + o->stream->latency_corrections[cidx].absolute = 0; + o->stream->latency_corrections[cidx].value = 0; + o->stream->latency_corrections[cidx].corrupt = 0; + } return pa_operation_ref(o); } From 2f918f0ede45480ecc355413f5a3ffbee3433e5a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 21:57:41 +0000 Subject: [PATCH 0564/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@657 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/todo b/doc/todo index 2c2d7d0d9..7249a5612 100644 --- a/doc/todo +++ b/doc/todo @@ -11,6 +11,8 @@ Fixes: - module-alsa-* love: - deal with underflows properly +- introspection API: flag reflecting if sink/source supports hw volume control + Post 0.8: - alsa mmap driver - add radio module From 7261494b840b0b9c0ae7bcd6422098e2d795c6c9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 22:28:13 +0000 Subject: [PATCH 0565/1514] remove item from TODO list, since it requires the SNDCTL_DSP_GETERROR ioctl() which isn't supported by the Linux kernel git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@658 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 7249a5612..7cd182a7e 100644 --- a/doc/todo +++ b/doc/todo @@ -6,7 +6,6 @@ Test: Fixes: - module-oss-* love: - - deal with underflows propely - improve latency measurement for mmap - module-alsa-* love: - deal with underflows properly From 4af16e43cb37eb4a0140f7105490e640512e7c13 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 22:45:08 +0000 Subject: [PATCH 0566/1514] minor cleanups git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@659 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 2e9459e6c..f930e6155 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -124,7 +124,7 @@ static void do_write(struct userdata *u) { continue; } - pa_log(__FILE__": snd_pcm_writei() failed"); + pa_log(__FILE__": snd_pcm_writei() failed: %s", snd_strerror(frames)); return; } @@ -176,17 +176,19 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { pa_usec_t r = 0; struct userdata *u = s->userdata; snd_pcm_sframes_t frames; + int err; + assert(s && u && u->sink); - if (snd_pcm_delay(u->pcm_handle, &frames) < 0) { - pa_log(__FILE__": failed to get delay"); + if ((err = snd_pcm_delay(u->pcm_handle, &frames)) < 0) { + pa_log(__FILE__": failed to get delay: %s", snd_strerror(err)); s->get_latency = NULL; return 0; } if (frames < 0) frames = 0; - + r += pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); if (u->memchunk.memblock) From 272ab200c24223a04efcc9f5a5df0e5e70b8de59 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 22:46:02 +0000 Subject: [PATCH 0567/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@660 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/todo b/doc/todo index 7cd182a7e..38d8b7135 100644 --- a/doc/todo +++ b/doc/todo @@ -7,8 +7,6 @@ Test: Fixes: - module-oss-* love: - improve latency measurement for mmap -- module-alsa-* love: - - deal with underflows properly - introspection API: flag reflecting if sink/source supports hw volume control From f6d95b7291f09f63f50d3b258f6a82580faf7bca Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 23:02:48 +0000 Subject: [PATCH 0568/1514] add new introspection data field for sinks/sources: a flags field which specifies whether the sink/source supports hw volume control and latency querying git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@661 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/def.h | 12 ++++++++++++ src/polyp/introspect.c | 12 ++++++++++-- src/polyp/introspect.h | 2 ++ src/polypcore/protocol-native.c | 2 ++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/polyp/def.h b/src/polyp/def.h index 659b943b5..1a7a20c3c 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -273,6 +273,18 @@ typedef enum pa_seek_mode { PA_SEEK_RELATIVE_END = 3, /**< Seek relatively to the current end of the buffer queue. */ } pa_seek_mode_t; +/** Special sink flags. \since 0.8 */ +typedef enum pa_sink_flags { + PA_SINK_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ + PA_SINK_LATENCY = 2 /**< Supports latency querying */ +} pa_sink_flags_t; + +/** Special source flags. \since 0.8 */ +typedef enum pa_source_flags { + PA_SOURCE_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ + PA_SOURCE_LATENCY = 2 /**< Supports latency querying */ +} pa_source_flags_t; + PA_C_DECL_END #endif diff --git a/src/polyp/introspect.c b/src/polyp/introspect.c index 6a28998c4..ea6133e1b 100644 --- a/src/polyp/introspect.c +++ b/src/polyp/introspect.c @@ -135,6 +135,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P eol = -1; } else { + uint32_t flags; while (!pa_tagstruct_eof(t)) { pa_sink_info i; @@ -150,12 +151,15 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P pa_tagstruct_getu32(t, &i.monitor_source) < 0 || pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || pa_tagstruct_get_usec(t, &i.latency) < 0 || - pa_tagstruct_gets(t, &i.driver) < 0) { + pa_tagstruct_gets(t, &i.driver) < 0 || + pa_tagstruct_getu32(t, &flags) < 0) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } + i.flags = (pa_sink_flags_t) flags; + if (o->callback) { pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); @@ -242,6 +246,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, while (!pa_tagstruct_eof(t)) { pa_source_info i; + uint32_t flags; if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -254,12 +259,15 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 || pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 || pa_tagstruct_get_usec(t, &i.latency) < 0 || - pa_tagstruct_gets(t, &i.driver) < 0) { + pa_tagstruct_gets(t, &i.driver) < 0 || + pa_tagstruct_getu32(t, &flags) < 0) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } + i.flags = (pa_source_flags_t) flags; + if (o->callback) { pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); diff --git a/src/polyp/introspect.h b/src/polyp/introspect.h index f1f0989ca..fb05cfb9d 100644 --- a/src/polyp/introspect.h +++ b/src/polyp/introspect.h @@ -63,6 +63,7 @@ typedef struct pa_sink_info { const char *monitor_source_name; /**< The name of the monitor source */ pa_usec_t latency; /**< Length of filled playback buffer of this sink */ const char *driver; /**< Driver name. \since 0.8 */ + pa_sink_flags_t flags; /**< Flags \since 0.8 */ } pa_sink_info; /** Callback prototype for pa_context_get_sink_info_by_name() and friends */ @@ -91,6 +92,7 @@ typedef struct pa_source_info { const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */ pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */ const char *driver; /**< Driver name \since 0.8 */ + pa_source_flags_t flags; /**< Flags \since 0.8 */ } pa_source_info; /** Callback prototype for pa_context_get_source_info_by_name() and friends */ diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 763873c25..51280c848 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -1232,6 +1232,7 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { PA_TAG_STRING, sink->monitor_source->name, PA_TAG_USEC, pa_sink_get_latency(sink), PA_TAG_STRING, sink->driver, + PA_TAG_U32, (sink->get_hw_volume ? PA_SINK_HW_VOLUME_CTRL : 0) | (sink->get_latency ? PA_SINK_LATENCY : 0), PA_TAG_INVALID); } @@ -1251,6 +1252,7 @@ static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL, PA_TAG_USEC, pa_source_get_latency(source), PA_TAG_STRING, source->driver, + PA_TAG_U32, (source->get_hw_volume ? PA_SOURCE_HW_VOLUME_CTRL : 0) | (source->get_latency ? PA_SOURCE_LATENCY : 0), PA_TAG_INVALID); } From a546c76a1c0b85ec481d11e2f9a1524a7abde14b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 23:05:45 +0000 Subject: [PATCH 0569/1514] * show flags value when dumping sink/source info in pactl. * show volume for sources, too * show value of "mute" field for sinks/sources git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@662 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 907746aad..fcc677d9c 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -175,7 +175,8 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ "Owner Module: %u\n" "Volume: %s\n" "Monitor Source: %u\n" - "Latency: %0.0f usec\n", + "Latency: %0.0f usec\n" + "Flags: %s%s\n", i->index, i->name, i->driver, @@ -183,14 +184,16 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), i->owner_module, - pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume), i->monitor_source, - (double) i->latency); + (double) i->latency, + i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", + i->flags & PA_SINK_LATENCY ? "LATENCY" : ""); } static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) { - char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; if (is_last < 0) { fprintf(stderr, "Failed to get source information: %s\n", pa_strerror(pa_context_errno(c))); @@ -218,8 +221,10 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int "Sample Specification: %s\n" "Channel Map: %s\n" "Owner Module: %u\n" + "Volume: %s\n" "Monitor of Sink: %s\n" - "Latency: %0.0f usec\n", + "Latency: %0.0f usec\n" + "Flags: %s%s\n", i->index, i->driver, i->name, @@ -227,9 +232,12 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), i->owner_module, + i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume), i->monitor_of_sink != PA_INVALID_INDEX ? t : "no", - (double) i->latency); - + (double) i->latency, + i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", + i->flags & PA_SOURCE_LATENCY ? "LATENCY" : ""); + } static void get_module_info_callback(pa_context *c, const pa_module_info *i, int is_last, void *userdata) { From 107525ce415edf2b37f867337869c8eeebc8d054 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Apr 2006 23:08:25 +0000 Subject: [PATCH 0570/1514] remove another item from the todo list git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@663 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/todo b/doc/todo index 38d8b7135..5e6357480 100644 --- a/doc/todo +++ b/doc/todo @@ -8,8 +8,6 @@ Fixes: - module-oss-* love: - improve latency measurement for mmap -- introspection API: flag reflecting if sink/source supports hw volume control - Post 0.8: - alsa mmap driver - add radio module From b4a547419c0815add1fc91d35d2a483c5a0e7c20 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Apr 2006 00:09:28 +0000 Subject: [PATCH 0571/1514] when doing software volume adjustments, don't use the volume value as linear factor, but pass it through pa_sw_volume_to_linear() first. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@664 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/sample-util.c | 44 +++++++++++++------------------------ 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/src/polypcore/sample-util.c b/src/polypcore/sample-util.c index 7afb9d11b..d06fa95fa 100644 --- a/src/polypcore/sample-util.c +++ b/src/polypcore/sample-util.c @@ -116,19 +116,15 @@ size_t pa_mix( else { v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); - if (cvolume != PA_VOLUME_NORM) { - v *= cvolume; - v /= PA_VOLUME_NORM; - } + if (cvolume != PA_VOLUME_NORM) + v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); } sum += v; } - if (volume->values[channel] != PA_VOLUME_NORM) { - sum *= volume->values[channel]; - sum /= PA_VOLUME_NORM; - } + if (volume->values[channel] != PA_VOLUME_NORM) + sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); if (sum < -0x8000) sum = -0x8000; if (sum > 0x7FFF) sum = 0x7FFF; @@ -168,19 +164,15 @@ size_t pa_mix( else { v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80; - if (cvolume != PA_VOLUME_NORM) { - v *= cvolume; - v /= PA_VOLUME_NORM; - } + if (cvolume != PA_VOLUME_NORM) + v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); } sum += v; } - if (volume->values[channel] != PA_VOLUME_NORM) { - sum *= volume->values[channel]; - sum /= PA_VOLUME_NORM; - } + if (volume->values[channel] != PA_VOLUME_NORM) + sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); if (sum < -0x80) sum = -0x80; if (sum > 0x7F) sum = 0x7F; @@ -220,19 +212,15 @@ size_t pa_mix( else { v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); - if (cvolume != PA_VOLUME_NORM) { - v *= cvolume; - v /= PA_VOLUME_NORM; - } + if (cvolume != PA_VOLUME_NORM) + v *= pa_sw_volume_to_linear(cvolume); } sum += v; } - if (volume->values[channel] != PA_VOLUME_NORM) { - sum *= volume->values[channel]; - sum /= PA_VOLUME_NORM; - } + if (volume->values[channel] != PA_VOLUME_NORM) + sum *= pa_sw_volume_to_linear(volume->values[channel]); } *((float*) data) = sum; @@ -270,8 +258,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol for (d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t = (int32_t)(*d); - t *= volume->values[channel]; - t /= PA_VOLUME_NORM; + t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel])); if (t < -0x8000) t = -0x8000; if (t > 0x7FFF) t = 0x7FFF; @@ -292,8 +279,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) { int32_t t = (int32_t) *d - 0x80; - t *= volume->values[channel]; - t /= PA_VOLUME_NORM; + t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel])); if (t < -0x80) t = -0x80; if (t > 0x7F) t = 0x7F; @@ -322,7 +308,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol if (volume->values[channel] == PA_VOLUME_NORM) continue; - v = (float) volume->values[channel] / PA_VOLUME_NORM; + v = (float) pa_sw_volume_to_linear(volume->values[channel]); t = d + channel; oil_scalarmult_f32(t, skip, t, skip, &v, n); From 025228f957b9212f889168a61497b6b3470fca20 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Apr 2006 00:19:29 +0000 Subject: [PATCH 0572/1514] add proper volume clipping support for OSS devices git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@665 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/oss-util.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 958bd547d..fac39e7bc 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -190,11 +190,16 @@ static int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvo static int pa_oss_set_volume(int fd, int mixer, const pa_sample_spec *ss, const pa_cvolume *volume) { char cv[PA_CVOLUME_SNPRINT_MAX]; unsigned vol; + pa_volume_t l, r; - vol = (volume->values[0]*100)/PA_VOLUME_NORM; + l = volume->values[0] > PA_VOLUME_NORM ? PA_VOLUME_NORM : volume->values[0]; - if (ss->channels >= 2) - vol |= ((volume->values[1]*100)/PA_VOLUME_NORM) << 8; + vol = (l*100)/PA_VOLUME_NORM; + + if (ss->channels >= 2) { + r = volume->values[1] > PA_VOLUME_NORM ? PA_VOLUME_NORM : volume->values[1]; + vol |= ((r*100)/PA_VOLUME_NORM) << 8; + } if (ioctl(fd, mixer, &vol) < 0) return -1; From a74253606f4f5556e58cb12336d8900dd73226cc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Apr 2006 00:19:52 +0000 Subject: [PATCH 0573/1514] clip volume at PA_VOLUME_NORM for alsa devices git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@666 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 15 +++++++++++++-- src/modules/module-alsa-source.c | 14 ++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index f930e6155..e2e593da3 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -239,8 +239,14 @@ static int sink_set_hw_volume_cb(pa_sink *s) { assert(u && u->mixer_elem); if (snd_mixer_selem_has_playback_volume_joined(u->mixer_elem)) { - vol = pa_cvolume_avg(&s->hw_volume) * (u->hw_volume_max - u->hw_volume_min) / + vol = pa_cvolume_avg(&s->hw_volume); + + if (vol > PA_VOLUME_NORM) + vol = PA_VOLUME_NORM; + + vol = (vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM + u->hw_volume_min; + err = snd_mixer_selem_set_playback_volume_all(u->mixer_elem, vol); if (err < 0) goto fail; @@ -248,7 +254,12 @@ static int sink_set_hw_volume_cb(pa_sink *s) { int i; for (i = 0;i < s->hw_volume.channels;i++) { - vol = s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min) / + vol = s->hw_volume.values[i]; + + if (vol > PA_VOLUME_NORM) + vol = PA_VOLUME_NORM; + + vol = (vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM + u->hw_volume_min; err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, vol); if (err < 0) diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 14b35eb81..2ee16190e 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -228,7 +228,12 @@ static int source_set_hw_volume_cb(pa_source *s) { assert(u && u->mixer_elem); if (snd_mixer_selem_has_capture_volume_joined(u->mixer_elem)) { - vol = pa_cvolume_avg(&s->hw_volume) * (u->hw_volume_max - u->hw_volume_min) / + vol = pa_cvolume_avg(&s->hw_volume); + + if (vol > PA_VOLUME_NORM) + vol = PA_VOLUME_NORM; + + vol = vol * (u->hw_volume_max - u->hw_volume_min) / PA_VOLUME_NORM + u->hw_volume_min; err = snd_mixer_selem_set_capture_volume_all(u->mixer_elem, vol); if (err < 0) @@ -237,7 +242,12 @@ static int source_set_hw_volume_cb(pa_source *s) { int i; for (i = 0;i < s->hw_volume.channels;i++) { - vol = s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min) / + vol = s->hw_volume.values[i]; + + if (vol > PA_VOLUME_NORM) + vol = PA_VOLUME_NORM; + + vol = vol * (u->hw_volume_max - u->hw_volume_min) / PA_VOLUME_NORM + u->hw_volume_min; err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, vol); if (err < 0) From a6ce5c4b1d82870f5db7063680698cebb4ffe156 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 9 Apr 2006 19:31:09 +0000 Subject: [PATCH 0574/1514] Big documentation update. Describe the client API in a more tutorial like manner. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@667 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.h | 34 +++++++ src/polyp/context.h | 116 ++++++++++++++++++++++-- src/polyp/glib-mainloop.h | 11 +++ src/polyp/introspect.h | 184 ++++++++++++++++++++++++++++++++++---- src/polyp/mainloop.h | 35 ++++++++ src/polyp/polypaudio.h | 52 ++++++----- src/polyp/sample.h | 66 ++++++++++++++ src/polyp/scache.h | 43 +++++++++ src/polyp/simple.h | 65 +++++++++++++- src/polyp/stream.h | 131 +++++++++++++++++++++++++++ src/polyp/subscribe.h | 19 +++- src/polyp/volume.h | 53 +++++++++++ 12 files changed, 757 insertions(+), 52 deletions(-) diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index dd508abe1..c74f2ceb1 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -25,6 +25,40 @@ #include #include +/** \page channelmap Channel maps + * + * \section overv_sec Overview + * + * Channel maps provide a way to associate channels in a stream with a + * speaker. This relieves applications of having to make sure their channel + * order is identical to the final output. + * + * \section init_sec Initialisation + * + * A channel map consists of an array of \ref pa_channel_position values, + * one for each channel. This array is stored together with a channel count + * in a pa_channel_map structure. + * + * Before filling the structure, the application must initialise it using + * pa_channel_map_init(). There are also a number of convenience functions + * for standard channel mappings: + * + * \li pa_channel_map_init_mono() - Create a channel map with only mono audio. + * \li pa_channel_map_init_stereo() - Create a standard stereo mapping. + * \li pa_channel_map_init_auto() - Create a standard channel map for up to + * six channels. + * + * \section conv_sec Convenience functions + * + * The library contains a number of convenience functions for dealing with + * channel maps: + * + * \li pa_channel_map_valid() - Tests if a channel map is valid. + * \li pa_channel_map_equal() - Tests if two channel maps are identical. + * \li pa_channel_map_snprint() - Creates a textual description of a channel + * map. + */ + /** \file * Constants and routines for channel mapping handling */ diff --git a/src/polyp/context.h b/src/polyp/context.h index 89febe92c..460034c1e 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -28,18 +28,116 @@ #include #include +/** \page async Asynchronous API + * + * \section overv_sec Overview + * + * The asynchronous API is the native interface to the polypaudio library. + * It allows full access to all available functions. This also means that + * it is rather complex and can take some time to fully master. + * + * \section mainloop_sec Main loop abstraction + * + * The API is based around an asynchronous event loop, or main loop, + * abstraction. This abstraction contains three basic elements: + * + * \li Deferred events - Events that trigger each iteration of the main loop. + * \li I/O events - Events that trigger on file descriptor activities. + * \li Times events - Events that trigger after a fixed ammount of time. + * + * The abstraction is represented as a number of function pointers in the + * pa_mainloop_api structure. + * + * To actually be able to use these functions, an actual implementation + * be coupled to the abstraction. There are two of these shipped with + * polypaudio, but any other can be used with a minimal ammount of work, + * provided it supports the three basic events listed above. + * + * The implementations shipped with polypaudio are: + * + * \li \subpage mainloop - A minimal but fast implementation based on poll(). + * \li \subpage glib-mainloop - A wrapper around GLIB's main loop. Available + * for both GLIB 1.2 and GLIB 2.x. + * + * UNIX signals may be hooked to a main loop using the functions from + * \ref mainloop-signal.h. These rely only on the main loop abstraction + * and can therefore be used with any of the implementations. + * + * \section refcnt_sec Reference counting + * + * Almost all objects in polypaudio are reference counted. What that means + * is that you rarely malloc() or free() any objects. Instead you increase + * and decrease their reference counts. Whenever an object's reference + * count reaches zero, that object gets destroy and any resources it uses + * get freed. + * + * The benefit of this design is that an application need not worry about + * whether or not it needs to keep an object around in case the library is + * using it internally. If it is, then it has made sure it has its own + * reference to it. + * + * Whenever the library creates an object, it will have an initial + * reference count of one. Most of the time, this single reference will be + * sufficient for the application, so all required reference count + * interaction will be a single call to the objects unref function. + * + * \section context_sec Context + * + * A context is the basic object for a connection to a polypaudio server. + * It multiplexes commands, data streams and events through a single + * channel. + * + * There is no need for more than one context per application, unless + * connections to multiple servers is needed. + * + * \subsection ops_subsec Operations + * + * All operations on the context is performed asynchronously. I.e. the + * client will not wait for the server to complete the request. To keep + * track of all these in-flight operations, the application is given a + * pa_operation object for each asynchronous operation. + * + * There are only two actions (besides reference counting) that can be + * performed on a pa_operation: querying its state with + * pa_operation_get_state() and aborting it with pa_operation_cancel(). + * + * A pa_operation object is reference counted, so an application must + * make sure to unreference it, even if it has no intention of using it. + * + * \subsection conn_subsec Connecting + * + * A context must be connected to a server before any operation can be + * issued. Calling pa_context_connect() will initiate the connection + * procedure. Unlike most asynchronous operations, connecting does not + * result in a pa_operation object. Instead, the application should + * register a callback using pa_context_set_state_callback(). + * + * \subsection disc_subsec Disconnecting + * + * When the sound support is no longer needed, the connection needs to be + * closed using pa_context_disconnect(). This is an immediate function that + * works synchronously. + * + * Since the context object has references to other objects it must be + * disconnected after use or there is a high risk of memory leaks. If the + * connection has terminated by itself, then there is no need to explicitly + * disconnect the context using pa_context_disconnect(). + * + * \section Functions + * + * The sound server's functionality can be divided into a number of + * subsections: + * + * \li \subpage streams + * \li \subpage scache + * \li \subpage introspect + * \li \subpage subscribe + */ + /** \file * Connection contexts for asynchrononous communication with a * server. A pa_context object wraps a connection to a polypaudio - * server using its native protocol. A context may be used to issue - * commands on the server or to create playback or recording - * streams. Multiple playback streams may be piped through a single - * connection context. Operations on the contect involving - * communication with the server are executed asynchronously: i.e. the - * client function do not implicitely wait for completion of the - * operation on the server. Instead the caller specifies a call back - * function that is called when the operation is completed. Currently - * running operations may be canceled using pa_operation_cancel(). */ + * server using its native protocol. */ /** \example pacat.c * A playback and recording tool using the asynchronous API */ diff --git a/src/polyp/glib-mainloop.h b/src/polyp/glib-mainloop.h index b7717685a..bc66409b8 100644 --- a/src/polyp/glib-mainloop.h +++ b/src/polyp/glib-mainloop.h @@ -27,6 +27,17 @@ #include #include +/** \page glib-mainloop GLIB main loop bindings + * + * \section overv_sec Overview + * + * The GLIB main loop bindings are extremely easy to use. All that is + * required is to create a pa_glib_mainloop object using + * pa_glib_mainloop_new(). When the main loop abstraction is needed, it is + * provided by pa_glib_mainloop_get_api(). + * + */ + /** \file * GLIB main loop support */ diff --git a/src/polyp/introspect.h b/src/polyp/introspect.h index fb05cfb9d..5d5678360 100644 --- a/src/polyp/introspect.h +++ b/src/polyp/introspect.h @@ -30,22 +30,176 @@ #include #include +/** \page introspect Server query and control + * + * \section overv_sec Overview + * + * Sometimes it is necessary to query and modify global settings in the + * server. For this, Polypaudio has the introspection API. It can list sinks, + * sources, samples and other aspects of the server. It can also modify the + * attributes of the server that will affect operations on a global level, + * and not just the application's context. + * + * \section query_sec Querying + * + * All querying is done through callbacks. This design is necessary to + * maintain an asynchronous design. The client will request the information + * and some time later, the server will respond with the desired data. + * + * Some objects can have multiple entries at the server. When requesting all + * of these at once, the callback will be called multiple times, once for + * each object. When the list has been exhausted, the callback will be called + * without an information structure and the eol parameter set to a non-zero + * value. + * + * Note that even if a single object is requested, and not the entire list, + * the terminating call will still be made. + * + * If an error occurs, the callback will be called without and information + * structure and eol set to zero. + * + * Data members in the information structures are only valid during the + * duration of the callback. If they are required after the callback is + * finished, a deep copy must be performed. + * + * \subsection server_subsec Server information + * + * The server can be queried about its name, the environment it's running on + * and the currently active global defaults. Calling + * pa_context_get_server_info() will get access to a pa_server_info structure + * containing all of these. + * + * \subsection memstat_subsec Memory usage + * + * Statistics about memory usage can be fetched using pa_context_stat(), + * giving a pa_stat_info structure. + * + * \subsection sinksrc_subsec Sinks and sources + * + * The server can have an arbitrary number of sinks and sources. Each sink + * and source have both an index and a name associated with it. As such + * there are three ways to get access to them: + * + * \li By index - pa_context_get_sink_info_by_index() / + * pa_context_get_source_info_by_index() + * \li By name - pa_context_get_sink_info_by_name() / + * pa_context_get_source_info_by_name() + * \li All - pa_context_get_sink_info_list() / + * pa_context_get_source_info_list() + * + * All three method use the same callback and will provide a pa_sink_info or + * pa_source_info structure. + * + * \subsection siso_subsec Sink inputs and source outputs + * + * Sink inputs and source outputs are the representations of the client ends + * of streams inside the server. I.e. they connect a client stream to one of + * the global sinks or sources. + * + * Sink inputs and source outputs only have an index to identify them. As + * such, there are only two ways to get information about them: + * + * \li By index - pa_context_get_sink_input_info() / + * pa_context_get_source_output_info() + * \li All - pa_context_get_sink_input_info_list() / + * pa_context_get_source_output_info_list() + * + * The structure returned is the pa_sink_input_info or pa_source_output_info + * structure. + * + * \subsection samples_subsec Samples + * + * The list of cached samples can be retrieved from the server. Three methods + * exist for querying the sample cache list: + * + * \li By index - pa_context_get_sample_info_by_index() + * \li By name - pa_context_get_sample_info_by_name() + * \li All - pa_context_get_sample_info_list() + * + * Note that this only retrieves information about the sample, not the sample + * data itself. + * + * \subsection module_subsec Modules + * + * Polypaudio modules are identified by index and are retrieved using either + * pa_context_get_module_info() or pa_context_get_module_info_list(). The + * information structure is called pa_module_info. + * + * \subsection autoload_subsec Autoload entries + * + * Modules can be autoloaded as a result of a client requesting a certain + * sink or source. This mapping between sink/source names and modules can be + * queried from the server: + * + * \li By index - pa_context_get_autoload_info_by_index() + * \li By sink/source name - pa_context_get_autoload_info_by_name() + * \li All - pa_context_get_autoload_info_list() + * + * \subsection client_subsec Clients + * + * Polypaudio clients are also identified by index and are retrieved using + * either pa_context_get_client_info() or pa_context_get_client_info_list(). + * The information structure is called pa_client_info. + * + * \section ctrl_sec Control + * + * Some parts of the server are only possible to read, but most can also be + * modified in different ways. Note that these changes will affect all + * connected clients and not just the one issuing the request. + * + * \subsection sinksrc_subsec Sinks and sources + * + * The most common change one would want to do to sinks and sources is to + * modify the volume of the audio. Identical to how sinks and sources can + * be queried, there are two ways of identifying them: + * + * \li By index - pa_context_set_sink_volume_by_index() / + * pa_context_set_source_volume_by_index() + * \li By name - pa_context_set_sink_volume_by_name() / + * pa_context_set_source_volume_by_name() + * + * It is also possible to mute a sink or source: + * + * \li By index - pa_context_set_sink_mute_by_index() / + * pa_context_set_source_mute_by_index() + * \li By name - pa_context_set_sink_mute_by_name() / + * pa_context_set_source_mute_by_name() + * + * \subsection siso_subsec Sink inputs and source outputs + * + * If an application desires to modify the volume of just a single stream + * (commonly one of its own streams), this can be done by setting the volume + * of its associated sink input, using pa_context_set_sink_input_volume(). + * + * There is no support for modifying the volume of source outputs. + * + * It is also possible to remove sink inputs and source outputs, terminating + * the streams associated with them: + * + * \li Sink input - pa_context_kill_sink_input() + * \li Source output - pa_context_kill_source_output() + * + * \subsection module_subsec Modules + * + * Server modules can be remotely loaded and unloaded using + * pa_context_load_module() and pa_context_unload_module(). + * + * \subsection autoload_subsec Autoload entries + * + * New module autoloading rules can be added, and existing can be removed + * using pa_context_add_autoload() and pa_context_remove_autoload_by_index() + * / pa_context_remove_autoload_by_name(). + * + * \subsection client_subsec Clients + * + * The only operation supported on clients, is the possibility of kicking + * them off the server using pa_context_kill_client(). + */ + /** \file * - * Routines for daemon introspection. When enumerating all entitites - * of a certain kind, use the pa_context_xxx_list() functions. The - * specified callback function is called once for each entry. The - * enumeration is finished by a call to the callback function with - * eol=1 and i=NULL. Strings referenced in pa_xxx_info structures and - * the structures themselves point to internal memory that may not be - * modified. That memory is only valid during the call to the callback - * function. A deep copy is required if you need this data outside the - * callback functions. An error is signalled by a call to the callback - * function with i=NULL and eol=0. - * - * When using the routines that ask fo a single entry only, a callback - * with the same signature is used. However, no finishing call to the - * routine is issued. */ + * Routines for daemon introspection. + */ PA_C_DECL_BEGIN @@ -121,7 +275,7 @@ typedef struct pa_server_info { /** Callback prototype for pa_context_get_server_info() */ typedef void (*pa_server_info_cb_t) (pa_context *c, const pa_server_info*i, void *userdata); - +context_ /** Get some information about the server */ pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata); diff --git a/src/polyp/mainloop.h b/src/polyp/mainloop.h index d0a409148..c06b47d00 100644 --- a/src/polyp/mainloop.h +++ b/src/polyp/mainloop.h @@ -27,6 +27,41 @@ PA_C_DECL_BEGIN +/** \page mainloop Mainloop + * + * \section overv_sec Overview + * + * The built-in main loop implementation is based on the poll() system call. + * It supports the functions defined in the main loop abstraction and very + * little else. + * + * The main loop is created using pa_mainloop_new() and destroyed using + * pa_mainloop_free(). To get access to the main loop abstraction, + * pa_mainloop_get_api() is used. + * + * \section iter_sec Iteration + * + * The main loop is designed around the concept of iterations. Each iteration + * consists of three steps that repeat during the application's entire + * lifetime: + * + * -# Prepare - Dispatch deferred events, build a list of file descriptors + * that need to be monitored and calculate the next timeout. + * -# Poll - Execute the actuall poll() system call. + * -# Dispatch - Dispatch any timeouts and file descriptors that have fired. + * + * When using the main loop, the application can either execute each + * iteration, one at a time, using pa_mainloop_iterate(), or let the library + * iterate automatically using pa_mainloop_run(). + * + * \section thread_sec Threads + * + * The main loop functions are designed to be thread safe, but the objects + * are not. What this means is that multiple main loops can be used, but only + * one object per thread. + * + */ + /** \file * * A minimal main loop implementation based on the C library's poll() diff --git a/src/polyp/polypaudio.h b/src/polyp/polypaudio.h index b70b8d703..af80f9ead 100644 --- a/src/polyp/polypaudio.h +++ b/src/polyp/polypaudio.h @@ -48,43 +48,49 @@ * \section intro_sec Introduction * * This document describes the client API for the polypaudio sound - * server. The API comes in two flavours: + * server. The API comes in two flavours to accomodate different styles + * of applications and different needs in complexity: * * \li The complete but somewhat complicated to use asynchronous API - * \li And the simplified, easy to use, but limited synchronous API + * \li The simplified, easy to use, but limited synchronous API * - * The polypaudio client libraries are thread safe as long as all - * objects created by any library function are accessed from the thread - * that created them only. - * * \section simple_sec Simple API * * Use this if you develop your program in synchronous style and just * need a way to play or record data on the sound server. See - * \ref simple.h for more details. + * \subpage simple for more details. * - * \section async_api Asynchronous API + * \section async_sec Asynchronous API * - * Use this if you develop your programs in asynchronous, main loop - * based style or want to use advanced features of the polypaudio - * API. A good starting point is \ref context.h + * Use this if you develop your programs in asynchronous, event loop + * based style or if you want to use the advanced features of the + * polypaudio API. A guide can be found in \subpage async. * - * The asynchronous API relies on an abstract main loop API that is - * described in \ref mainloop-api.h. Two distinct implementations are - * available: - * - * \li \ref mainloop.h : a minimal but fast implementation based on poll() - * \li \ref glib-mainloop.h : a wrapper around GLIB's main loop + * \section thread_sec Threads * - * UNIX signals may be hooked to a main loop using the functions from - * \ref mainloop-signal.h + * The polypaudio client libraries are not designed to be used in a + * heavily threaded environment. They are however designed to be reentrant + * safe. + * + * To use a the libraries in a threaded environment, you must assure that + * all objects are only used in the same thread they were created in. + * Normally, this means that all objects belonging to a single context + * must be accessed from the same thread. + * + * The included main loop implementation is also not thread safe. Take care + * to make sure event lists are not manipulated when any library code is + * using the main loop. * * \section pkgconfig pkg-config * - * The polypaudio libraries provide pkg-config snippets for the different modules. To use the - * asynchronous API use "polyplib" as pkg-config file. GLIB main loop - * support is available as "glib-mainloop". The simple - * synchronous API is available as "simple". + * The polypaudio libraries provide pkg-config snippets for the different + * modules: + * + * \li polyplib - The asynchronous API and the internal main loop + * implementation. + * \li polyplib-glib12-mainloop - GLIB 1.2 main loop bindings. + * \li polyplib-glib-mainloop - GLIB 2.x main loop bindings. + * \li polyplib-simple - The simple polypaudio API. */ #endif diff --git a/src/polyp/sample.h b/src/polyp/sample.h index db4c6c704..a7abdc3ec 100644 --- a/src/polyp/sample.h +++ b/src/polyp/sample.h @@ -28,6 +28,72 @@ #include +/** \page sample Sample format specifications + * + * \section overv_sec Overview + * + * Polypaudio is capable of handling a multitude of sample formats, rates + * and channels, transparently converting and mixing them as needed. + * + * \section format_sec Sample format + * + * Polypaudio supports the following sample formats: + * + * \li PA_SAMPLE_U8 - Unsigned 8 bit PCM. + * \li PA_SAMPLE_S16LE - Signed 16 bit PCM, little endian. + * \li PA_SAMPLE_S16BE - Signed 16 bit PCM, big endian. + * \li PA_SAMPLE_FLOAT32LE - 32 bit IEEE floating point PCM, little endian. + * \li PA_SAMPLE_FLOAT32BE - 32 bit IEEE floating point PCM, big endian. + * \li PA_SAMPLE_ALAW - 8 bit a-Law. + * \li PA_SAMPLE_ULAW - 8 bit mu-Law. + * + * The floating point sample formats have the range from -1 to 1. + * + * The sample formats that are sensitive to endianness have convenience + * macros for native endian (NE), and reverse endian (RE). + * + * \section rate_sec Sample rates + * + * Polypaudio supports any sample rate between 1 Hz and 4 GHz. There is no + * point trying to exceed the sample rate of the output device though as the + * signal will only get downsampled, consuming CPU on the machine running the + * server. + * + * \section chan_sec Channels + * + * Polypaudio supports up to 16 individiual channels. The order of the + * channels is up to the application, but they must be continous. To map + * channels to speakers, see \ref channelmap. + * + * \section calc_sec Calculations + * + * The Polypaudio library contains a number of convenience functions to do + * calculations on sample formats: + * + * \li pa_bytes_per_second() - The number of bytes one second of audio will + * take given a sample format. + * \li pa_frame_size() - The size, in bytes, of one frame (i.e. one set of + * samples, one for each channel). + * \li pa_sample_size() - The size, in bytes, of one sample. + * \li pa_bytes_to_usec() - Calculate the time it would take to play a buffer + * of a certain size. + * + * \section util_sec Convenience functions + * + * The library also contains a couple of other convenience functions: + * + * \li pa_sample_spec_valid() - Tests if a sample format specification is + * valid. + * \li pa_sample_spec_equal() - Tests if the sample format specifications are + * identical. + * \li pa_sample_format_to_string() - Return a textual description of a + * sample format. + * \li pa_parse_sample_format() - Parse a text string into a sample format. + * \li pa_sample_spec_snprint() - Create a textual description of a complete + * sample format specification. + * \li pa_bytes_snprint() - Pretty print a byte value (e.g. 2.5 MB). + */ + /** \file * Constants and routines for sample type handling */ diff --git a/src/polyp/scache.h b/src/polyp/scache.h index cdb47cab5..a6b312f55 100644 --- a/src/polyp/scache.h +++ b/src/polyp/scache.h @@ -28,6 +28,49 @@ #include #include +/** \page scache Sample cache + * + * \section overv_sec Overview + * + * The sample cache provides a simple way of overcoming high network latencies + * and reducing bandwidth. Instead of streaming a sound precisely when it + * should be played, it is stored on the server and only the command to start + * playing it needs to be sent. + * + * \section create_sec Creation + * + * To create a sample, the normal stream API is used (see \ref streams). The + * function pa_stream_connect_upload() will make sure the stream is stored as + * a sample on the server. + * + * To complete the upload, pa_stream_finish_upload() is called and the sample + * will receive the same name as the stream. If the upload should be aborted, + * simply call pa_stream_disconnect(). + * + * \section play_sec Playing samples + * + * To play back a sample, simply call pa_context_play_sample(): + * + * \code + * pa_operation *o; + * + * o = pa_context_play_sample(my_context, + * "sample2", // Name of my sample + * NULL, // Use default sink + * PA_VOLUME_NORM, // Full volume + * NULL, // Don't need a callback + * NULL + * ); + * if (o) + * pa_operation_unref(o); + * \endcode + * + * \section rem_sec Removing samples + * + * When a sample is no longer needed, it should be removed on the server to + * save resources. The sample is deleted using pa_context_remove_sample(). + */ + /** \file * All sample cache related routines */ diff --git a/src/polyp/simple.h b/src/polyp/simple.h index 1a139005e..d2adde022 100644 --- a/src/polyp/simple.h +++ b/src/polyp/simple.h @@ -28,9 +28,72 @@ #include #include +/** \page simple Simple API + * + * \section overv_sec Overview + * + * The simple API is designed for applications with very basic sound + * playback or capture needs. It can only support a single stream per + * connection and has no handling of complex features like events, channel + * mappings and volume control. It is, however, very simple to use and + * quite sufficent for many programs. + * + * \section conn_sec Connecting + * + * The first step before using the sound system is to connect to the + * server. This is normally done this way: + * + * \code + * pa_simple *s; + * pa_sample_spec ss; + * + * ss.format = S16_NE; + * ss.channels = 2; + * ss.rate = 44100; + * + * s = pa_simple_new(NULL, // Use the default server. + * "Fooapp", // Our application's name. + * PA_STREAM_PLAYBACK, + * NULL, // Use the default device. + * "Music", // Description of our stream. + * &ss, // Our sample format. + * NULL, // Use default buffering attributes. + * NULL, // Ignore error code. + * ); + * \endcode + * + * At this point a connected object is returned, or NULL if there was a + * problem connecting. + * + * \section transfer_sec Transferring data + * + * Once the connection is established to the server, data can start flowing. + * Using the connection is very similar to the normal read() and write() + * system calls. The main difference is that they're call pa_simple_read() + * and pa_simple_write(). Note that these operation are always blocking. + * + * \section ctrl_sec Buffer control + * + * If a playback stream is used then a few other operations are available: + * + * \li pa_simple_drain() - Will wait for all sent data to finish playing. + * \li pa_simple_flush() - Will throw away all data currently in buffers. + * \li pa_simple_get_playback_latency() - Will return the total latency of + * the playback pipeline. + * + * \section cleanup_sec Cleanup + * + * Once playback or capture is complete, the connection should be closed + * and resources freed. This is done through: + * + * \code + * pa_simple_free(s); + * \endcode + */ + /** \file * A simple but limited synchronous playback and recording - * API. This is synchronouse, simplified wrapper around the standard + * API. This is a synchronous, simplified wrapper around the standard * asynchronous API. */ /** \example pacat-simple.c diff --git a/src/polyp/stream.h b/src/polyp/stream.h index ce0419868..bb5aa7646 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -31,6 +31,137 @@ #include #include +/** \page streams Audio streams + * + * \section overv_sec Overview + * + * Audio streams form the central functionality of the sound server. Data is + * routed, converted and mixed from several sources before it is passed along + * to a final output. Currently, there are three forms of audio streams: + * + * \li Playback streams - Data flows from the client to the server. + * \li Record streams - Data flows from the server to the client. + * \li Upload streams - Similar to playback streams, but the data is stored in + * the sample cache. See \ref scache for more information + * about controlling the sample cache. + * + * \section create_sec Creating + * + * To access a stream, a pa_stream object must be created using + * pa_stream_new(). At this point the audio sample format and mapping of + * channels must be specified. See \ref sample and \ref channelmap for more + * information about those structures. + * + * This first step will only create a client-side object, representing the + * stream. To use the stream, a server-side object must be created and + * associated with the local object. Depending on which type of stream is + * desired, a different function is needed: + * + * \li Playback stream - pa_stream_connect_playback() + * \li Record stream - pa_stream_connect_record() + * \li Upload stream - pa_stream_connect_upload() (see \ref scache) + * + * Similar to how connections are done in contexts, connecting a stream will + * not generate a pa_operation object. Also like contexts, the application + * should register a state change callback, using + * pa_stream_set_state_callback(), and wait for the stream to enter an active + * state. + * + * \subsection bufattr_subsec Buffer attributes + * + * Playback and record streams always have a buffer as part of the data flow. + * The size of this buffer strikes a compromise between low latency and + * sensitivity for buffer overflows/underruns. + * + * The buffer is described with a pa_buffer_attr structure which contains a + * number of field: + * + * \li maxlength - The absolute maximum number of bytes that can be stored in + * the buffer. If this value is exceeded then data will be + * lost. + * \li tlength - The target length of a playback buffer. The server will only + * send requests for more data as long as the buffer has less + * than this number of bytes of data. + * \li prebuf - Number of bytes that need to be in the buffer before playback + * will commence. Start of playback can be forced using + * pa_stream_trigger() even though the prebuffer size hasn't been + * reached. + * \li minreq - Minimum free number of the bytes in the playback buffer before + * the server will request more data. + * \li fragsize - Maximum number of bytes that the server will push in one + * chunk for record streams. + * + * \section transfer_sec Transferring data + * + * Once the stream is up, data can start flowing between the client and the + * server. Two different access models can be used to transfer the data: + * + * \li Asynchronous - The application register a callback using + * pa_stream_set_write_callback() and + * pa_stream_set_read_callback() to receive notifications + * that data can either be written or read. + * \li Polled - Query the library for available data/space using + * pa_stream_writable_size() and pa_stream_readable_size() and + * transfer data as needed. The sizes are stored locally, in the + * client end, so there is no delay when reading them. + * + * It is also possible to mix the two models freely. + * + * Once there is data/space available, it can be transferred using either + * pa_stream_write() for playback, or pa_stream_peek() / pa_stream_drop() for + * record. Make sure you do not overflow the playback buffers as data will be + * dropped. + * + * \section bufctl_sec Buffer control + * + * The transfer buffers can be controlled through a number of operations: + * + * \li pa_stream_cork() - Start or stop the playback or recording. + * \li pa_stream_trigger() - Start playback immediatly and do not wait for + * the buffer to fill up to the set trigger level. + * \li pa_stream_prebuf() - Reenable the playback trigger level. + * \li pa_stream_drain() - Wait for the playback buffer to go empty. Will + * return a pa_operation object that will indicate when + * the buffer is completely drained. + * \li pa_stream_flush() - Drop all data from the playback buffer and do not + * wait for it to finish playing. + * + * \section latency_sec Latency + * + * A major problem with networked audio is the increased latency caused by + * the network. To remedy this, Polypaudio supports an advanced system of + * monitoring the current latency. + * + * To get the raw data needed to calculate latencies, call + * pa_stream_get_timing_info(). This will give you a pa_timing_info structure + * that contains everything that is known about buffers, transport delays + * and the backend active in the server. + * + * If a more simplistic interface is prefered, you can call + * pa_stream_get_time() or pa_stream_get_latency(). These will do all the + * necessary calculations for you. + * + * The latency information is constantly updated from the server. Be aware + * that between updates, old data will be returned. If you specify the flag + * PA_STREAM_INTERPOLATE_TIMING when creating the stream, pa_stream_get_time() + * and pa_stream_get_latency() will calculate the latency between updates + * based on the time elapsed. + * + * \section flow_sec Overflow and underflow + * + * Even with the best precautions, buffers will sometime over- or underflow. + * To handle this gracefully, the application can be notified when this + * happens. Callbacks are registered using pa_stream_set_overflow_callback() + * and pa_stream_set_underflow_callback(). + * + * \section disc_sec Disconnecting + * + * When a stream has served is purpose it must be disconnected with + * pa_stream_disconnect(). If you only unreference it, then it will live on + * and eat resources both locally and on the server until you disconnect the + * context. + */ + /** \file * Audio streams for input, output and sample upload */ diff --git a/src/polyp/subscribe.h b/src/polyp/subscribe.h index 5301739a4..75b4696fa 100644 --- a/src/polyp/subscribe.h +++ b/src/polyp/subscribe.h @@ -28,11 +28,22 @@ #include #include +/** \page subscribe Event subscription + * + * \section overv_sec Overview + * + * The application can be notified, asynchronously, whenever the internal + * layout of the server changes. Possible notifications are desribed in the + * \ref pa_subscription_event_type and \ref pa_subscription_mask + * enumerations. + * + * The application sets the notification mask using pa_context_subscribe() + * and the function that will be called whenever a notification occurs using + * pa_context_set_subscribe_callback(). + */ + /** \file - * Daemon introspection event subscription subsystem. Use this - * to be notified whenever the internal layout of daemon changes: - * i.e. entities such as sinks or sources are create, removed or - * modified. */ + * Daemon introspection event subscription subsystem. */ PA_C_DECL_BEGIN diff --git a/src/polyp/volume.h b/src/polyp/volume.h index d1e858c43..181784f40 100644 --- a/src/polyp/volume.h +++ b/src/polyp/volume.h @@ -26,6 +26,59 @@ #include #include +/** \page volume Volume control + * + * \section overv_sec Overview + * + * Sinks, sources, sink inputs and samples can all have their own volumes. + * To deal with these, The Polypaudio libray contains a number of functions + * that ease handling. + * + * The basic volume type in Polypaudio is the \ref pa_volume_t type. Most of + * the time, applications will use the aggregated pa_cvolume structure that + * can store the volume of all channels at once. + * + * Volumes commonly span between muted (0%), and normal (100%). It is possible + * to set volumes to higher than 100%, but clipping might occur. + * + * \section calc_sec Calculations + * + * The volumes in Polypaudio are logarithmic in nature and applications + * shouldn't perform calculations with them directly. Instead, they should + * be converted to and from either dB or a linear scale: + * + * \li dB - pa_sw_volume_from_dB() / pa_sw_volume_to_dB() + * \li Linear - pa_sw_volume_from_linear() / pa_sw_volume_to_linear() + * + * For simple multiplication, pa_sw_volume_multiply() and + * pa_sw_cvolume_multiply() can be used. + * + * Calculations can only be reliably be performed on software volumes as + * it is commonly unknown what scale hardware volumes use. + * + * \section conv_sec Convenience functions + * + * To handle the pa_cvolume structure, the Polypaudio library provides a + * number of convenienc functions: + * + * \li pa_cvolume_valid() - Tests if a pa_cvolume structure is valid. + * \li pa_cvolume_equal() - Tests if two pa_cvolume structures are identical. + * \li pa_cvolume_channels_equal_to() - Tests if all channels of a pa_cvolume + * structure have a given volume. + * \li pa_cvolume_is_muted() - Tests if all channels of a pa_cvolume + * structure are muted. + * \li pa_cvolume_is_norm() - Tests if all channels of a pa_cvolume structure + * are at a normal volume. + * \li pa_cvolume_set() - Set all channels of a pa_cvolume structure to a + * certain volume. + * \li pa_cvolume_reset() - Set all channels of a pa_cvolume structure to a + * normal volume. + * \li pa_cvolume_mute() - Set all channels of a pa_cvolume structure to a + * muted volume. + * \li pa_cvolume_avg() - Return the average volume of all channels. + * \li pa_cvolume_snprint() - Pretty print a pa_cvolume structure. + */ + /** \file * Constants and routines for volume handling */ From 0d200ee74345367d5285db59fc32c190146bdcb5 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 9 Apr 2006 19:32:16 +0000 Subject: [PATCH 0575/1514] Use the modern Ki/Mi/Gi prefixes to clarify that 1024 is the base. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@668 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/sample.c | 6 +++--- src/polyp/sample.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/polyp/sample.c b/src/polyp/sample.c index d587170c9..668a485ed 100644 --- a/src/polyp/sample.c +++ b/src/polyp/sample.c @@ -115,11 +115,11 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) { void pa_bytes_snprint(char *s, size_t l, unsigned v) { if (v >= ((unsigned) 1024)*1024*1024) - snprintf(s, l, "%0.1f GB", ((double) v)/1024/1024/1024); + snprintf(s, l, "%0.1f GiB", ((double) v)/1024/1024/1024); else if (v >= ((unsigned) 1024)*1024) - snprintf(s, l, "%0.1f MB", ((double) v)/1024/1024); + snprintf(s, l, "%0.1f MiB", ((double) v)/1024/1024); else if (v >= (unsigned) 1024) - snprintf(s, l, "%0.1f KB", ((double) v)/1024); + snprintf(s, l, "%0.1f KiB", ((double) v)/1024); else snprintf(s, l, "%u B", (unsigned) v); } diff --git a/src/polyp/sample.h b/src/polyp/sample.h index a7abdc3ec..284b428bd 100644 --- a/src/polyp/sample.h +++ b/src/polyp/sample.h @@ -91,7 +91,7 @@ * \li pa_parse_sample_format() - Parse a text string into a sample format. * \li pa_sample_spec_snprint() - Create a textual description of a complete * sample format specification. - * \li pa_bytes_snprint() - Pretty print a byte value (e.g. 2.5 MB). + * \li pa_bytes_snprint() - Pretty print a byte value (e.g. 2.5 MiB). */ /** \file @@ -178,7 +178,7 @@ pa_sample_format_t pa_parse_sample_format(const char *format); /** Pretty print a sample type specification to a string */ char* pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec); -/** Pretty print a byte size value. (i.e. "2.5 MB") */ +/** Pretty print a byte size value. (i.e. "2.5 MiB") */ void pa_bytes_snprint(char *s, size_t l, unsigned v); PA_C_DECL_END From f4119adc8ed7a137a71d60010c129be286cb5a3f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 16:40:29 +0000 Subject: [PATCH 0576/1514] unbreak last commit from ossman git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@669 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/introspect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/introspect.h b/src/polyp/introspect.h index 5d5678360..a8292ba1b 100644 --- a/src/polyp/introspect.h +++ b/src/polyp/introspect.h @@ -275,7 +275,7 @@ typedef struct pa_server_info { /** Callback prototype for pa_context_get_server_info() */ typedef void (*pa_server_info_cb_t) (pa_context *c, const pa_server_info*i, void *userdata); -context_ + /** Get some information about the server */ pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata); From 35ea8aca7de8b513917feecee43967b8f030b43c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 17:17:36 +0000 Subject: [PATCH 0577/1514] update TODO git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@670 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/todo b/doc/todo index 5e6357480..205be4e56 100644 --- a/doc/todo +++ b/doc/todo @@ -7,6 +7,9 @@ Test: Fixes: - module-oss-* love: - improve latency measurement for mmap +- add a client API for setting the "muted" status of devices +- split PA_STREAM_INTERPOLATE_TIMING and PA_STREAM_AUTO_TIMING_UPDATE +- correct API docs regarding timing work Post 0.8: - alsa mmap driver From 4496954514af459a74b6bca692780a64c5599106 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 17:22:10 +0000 Subject: [PATCH 0578/1514] Lennart is blind git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@671 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 205be4e56..a6d3f6c49 100644 --- a/doc/todo +++ b/doc/todo @@ -7,7 +7,6 @@ Test: Fixes: - module-oss-* love: - improve latency measurement for mmap -- add a client API for setting the "muted" status of devices - split PA_STREAM_INTERPOLATE_TIMING and PA_STREAM_AUTO_TIMING_UPDATE - correct API docs regarding timing work From 190a8691326513d8d6e407b3fdded842f8661a52 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 17:38:46 +0000 Subject: [PATCH 0579/1514] add new PA_STREAM_AUTO_TIMING_UPDATE git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@672 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/def.h | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/polyp/def.h b/src/polyp/def.h index 1a7a20c3c..eadddf088 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -82,18 +82,16 @@ typedef enum pa_stream_flags { PA_STREAM_START_CORKED = 1, /**< Create the stream corked, requiring an explicit pa_stream_cork() call to uncork it. */ PA_STREAM_INTERPOLATE_TIMING = 2, /**< Interpolate the latency for * this stream. When enabled, - * pa_stream_get_latency() and pa_stream_get_time() - * will try to estimate the - * current record/playback time - * based on the local time that - * passed since the last timing - * info update. In addition - * timing update requests are - * issued periodically - * automatically. Using this - * option has the advantage of - * not requiring a whole - * roundtrip when the current + * pa_stream_get_latency() and + * pa_stream_get_time() will try + * to estimate the current + * record/playback time based on + * the local time that passed + * since the last timing info + * update. Using this option + * has the advantage of not + * requiring a whole roundtrip + * when the current * playback/recording time is * needed. Consider using this * option when requesting @@ -101,7 +99,10 @@ typedef enum pa_stream_flags { * frequently. This is * especially useful on long * latency network - * connections. */ + * connections. It makes a lot + * of sense to combine this + * option with + * PA_STREAM_AUTO_TIMING_UPDATE. */ PA_STREAM_NOT_MONOTONOUS = 4, /**< Don't force the time to * increase monotonically. If * this option is enabled, @@ -118,6 +119,16 @@ typedef enum pa_stream_flags { * ahead can be corrected * quickly, without the need to * wait. */ + PA_STREAM_AUTO_TIMING_UPDATE = 8 /** If set timing update requests + * are issued periodically + * automatically. Combined with + * PA_STREAM_INTERPOLATE_TIMING + * you will be able to query the + * current time and latency with + * pa_stream_get_time() and + * pa_stream_get_latency() at + * all times without a packet + * round trip.*/ } pa_stream_flags_t; /** Playback and record buffer metrics */ From 137f0a7140271b1151b1d97e1863d237e8458316 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 17:39:24 +0000 Subject: [PATCH 0580/1514] * implement PA_STREAM_AUTO_TIMING_UPDATE * accept PA_STREAM_NOT_MONOTONOUS properly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@673 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 4a98dd606..0fcc36b7a 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -372,7 +372,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED pa_stream_ref(s); if (s->direction != PA_STREAM_UPLOAD && - s->flags & PA_STREAM_INTERPOLATE_TIMING) { + s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { struct timeval tv; pa_gettimeofday(&tv); @@ -407,7 +407,11 @@ static int create_stream( assert(s->ref >= 1); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY(s->context, !(flags & ~(PA_STREAM_START_CORKED|PA_STREAM_INTERPOLATE_TIMING)), PA_ERR_INVALID); + PA_CHECK_VALIDITY(s->context, !(flags & ~((direction != PA_STREAM_UPLOAD ? + PA_STREAM_START_CORKED| + PA_STREAM_INTERPOLATE_TIMING| + PA_STREAM_NOT_MONOTONOUS| + PA_STREAM_AUTO_TIMING_UPDATE : 0))), PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, direction == PA_STREAM_PLAYBACK || flags == 0, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID); @@ -621,7 +625,7 @@ size_t pa_stream_writable_size(pa_stream *s) { assert(s->ref >= 1); PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1); - PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, (size_t) -1); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_RECORD, PA_ERR_BADSTATE, (size_t) -1); return s->requested_bytes; } @@ -952,7 +956,7 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - if (s->flags & PA_STREAM_INTERPOLATE_TIMING) { + if (s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { if (!s->corked && b) { /* Refresh the interpolated data just befor pausing */ pa_stream_get_time(s, NULL); From 6a3b8aeb3fa43c69ca7ad1b89e35040fb5834751 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 17:42:32 +0000 Subject: [PATCH 0581/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@674 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index a6d3f6c49..81d4f863c 100644 --- a/doc/todo +++ b/doc/todo @@ -7,7 +7,6 @@ Test: Fixes: - module-oss-* love: - improve latency measurement for mmap -- split PA_STREAM_INTERPOLATE_TIMING and PA_STREAM_AUTO_TIMING_UPDATE - correct API docs regarding timing work Post 0.8: From 93327083d9273bcf2d6ce94b61449c181dcf6fa2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 19:42:14 +0000 Subject: [PATCH 0582/1514] when using record mode, allow file to save data to to be passed on the command line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@675 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 441e26070..e721befa9 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -517,25 +517,25 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Opening a %s stream with sample specification '%s'.\n", mode == RECORD ? "recording" : "playback", t); } - if (optind+1 < argc) { - fprintf(stderr, "Too many arguments.\n"); - goto quit; - } - - if (optind+1 == argc) { - int fd; - - if ((fd = open(argv[optind], O_RDONLY)) < 0) { - fprintf(stderr, "open(): %s\n", strerror(errno)); + if (!(optind >= argc)) { + if (optind+1 == argc) { + int fd; + + if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT)) < 0) { + fprintf(stderr, "open(): %s\n", strerror(errno)); + goto quit; + } + + if (dup2(fd, mode == PLAYBACK ? 0 : 1) < 0) { + fprintf(stderr, "dup2(): %s\n", strerror(errno)); + goto quit; + } + + close(fd); + } else { + fprintf(stderr, "Too many arguments.\n"); goto quit; } - - if (dup2(fd, 0) < 0) { - fprintf(stderr, "dup2(): %s\n", strerror(errno)); - goto quit; - } - - close(fd); } /* Set up a new main loop */ From 8f2d9aeb9544b128249c2126e561d10ff5d498ad Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 19:42:44 +0000 Subject: [PATCH 0583/1514] minor cleanups for OSS module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@676 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 524275921..d9980d82d 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -51,7 +51,17 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("OSS Sink/Source") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= fragments= fragment_size=") +PA_MODULE_USAGE( + "sink_name= " + "source_name= " + "device= " + "record= " + "playback= " + "format= " + "channels= " + "rate= " + "fragments= " + "fragment_size=") struct userdata { pa_sink *sink; @@ -85,6 +95,8 @@ static const char* const valid_modargs[] = { #define DEFAULT_SINK_NAME "oss_output" #define DEFAULT_SOURCE_NAME "oss_input" #define DEFAULT_DEVICE "/dev/dsp" +#define DEFAULT_NFRAGS 12 +#define DEFAULT_FRAGSIZE 1024 static void update_usage(struct userdata *u) { pa_module_set_used(u->module, @@ -332,9 +344,9 @@ int pa__init(pa_core *c, pa_module*m) { } mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); - - nfrags = 12; - frag_size = 1024; + + nfrags = DEFAULT_NFRAGS; + frag_size = DEFAULT_FRAGSIZE; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { pa_log(__FILE__": failed to parse fragments arguments"); goto fail; @@ -387,8 +399,9 @@ int pa__init(pa_core *c, pa_module*m) { } if (mode != O_WRONLY) { - u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); - assert(u->source); + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) + goto fail; + u->source->userdata = u; u->source->notify = source_notify_cb; u->source->get_latency = source_get_latency_cb; @@ -404,8 +417,9 @@ int pa__init(pa_core *c, pa_module*m) { u->source = NULL; if (mode != O_RDONLY) { - u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); - assert(u->sink); + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) + goto fail; + u->sink->get_latency = sink_get_latency_cb; u->sink->get_hw_volume = sink_get_hw_volume; u->sink->set_hw_volume = sink_set_hw_volume; @@ -471,7 +485,9 @@ fail: void pa__done(pa_core *c, pa_module*m) { struct userdata *u; - assert(c && m); + + assert(c); + assert(m); if (!(u = m->userdata)) return; From 021744debbe2284085cd8eec3f3724f540e30551 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 19:43:51 +0000 Subject: [PATCH 0584/1514] * Beef up latency calculation in module-oss-mmap * Add recording latency code for module-oss-mmap * other cleanups git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@677 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss-mmap.c | 102 +++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 21 deletions(-) diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 0ed2af938..5389a201f 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -52,7 +52,17 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("OSS Sink/Source (mmap)") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= fragments= fragment_size=") +PA_MODULE_USAGE( + "sink_name= " + "source_name= " + "device= " + "record= " + "playback= " + "format= " + "channels= " + "rate= " + "fragments= " + "fragment_size=") struct userdata { pa_sink *sink; @@ -60,7 +70,8 @@ struct userdata { pa_core *core; pa_sample_spec sample_spec; - size_t in_fragment_size, out_fragment_size, in_fragments, out_fragments, out_fill; + size_t in_fragment_size, out_fragment_size, in_fragments, out_fragments; + int out_blocks_saved, in_blocks_saved; int fd; @@ -91,6 +102,8 @@ static const char* const valid_modargs[] = { #define DEFAULT_SINK_NAME "oss_output" #define DEFAULT_SOURCE_NAME "oss_input" #define DEFAULT_DEVICE "/dev/dsp" +#define DEFAULT_NFRAGS 12 +#define DEFAULT_FRAGSIZE 1024 static void update_usage(struct userdata *u) { pa_module_set_used(u->module, @@ -134,8 +147,9 @@ static void do_write(struct userdata *u) { return; } - u->out_fill = (u->out_fragment_size * u->out_fragments) - (info.ptr % u->out_fragment_size); - + info.blocks += u->out_blocks_saved; + u->out_blocks_saved = 0; + if (!info.blocks) return; @@ -196,6 +210,9 @@ static void do_read(struct userdata *u) { return; } + info.blocks += u->in_blocks_saved; + u->in_blocks_saved = 0; + if (!info.blocks) return; @@ -215,10 +232,48 @@ static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd static pa_usec_t sink_get_latency_cb(pa_sink *s) { struct userdata *u = s->userdata; + struct count_info info; + size_t bpos, n; assert(s && u); - do_write(u); - return pa_bytes_to_usec(u->out_fill, &s->sample_spec); + if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { + pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s", strerror(errno)); + return 0; + } + + u->out_blocks_saved += info.blocks; + + bpos = ((u->out_current + u->out_blocks_saved) % u->out_fragments) * u->out_fragment_size; + + if (bpos < (size_t) info.ptr) + n = (u->out_fragments * u->out_fragment_size) - (info.ptr - bpos); + else + n = bpos - info.ptr; + + return pa_bytes_to_usec(n, &s->sample_spec); +} + +static pa_usec_t source_get_latency_cb(pa_source *s) { + struct userdata *u = s->userdata; + struct count_info info; + size_t bpos, n; + assert(s && u); + + if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { + pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s", strerror(errno)); + return 0; + } + + u->in_blocks_saved += info.blocks; + + bpos = ((u->in_current + u->in_blocks_saved) % u->in_fragments) * u->in_fragment_size; + + if (bpos < (size_t) info.ptr) + n = info.ptr - bpos; + else + n = (u->in_fragments * u->in_fragment_size) - bpos + info.ptr; + + return pa_bytes_to_usec(n, &s->sample_spec); } static int sink_get_hw_volume(pa_sink *s) { @@ -283,7 +338,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c); assert(m); - m->userdata = u = pa_xmalloc0(sizeof(struct userdata)); + m->userdata = u = pa_xnew0(struct userdata, 1); u->module = m; u->fd = -1; u->core = c; @@ -305,8 +360,8 @@ int pa__init(pa_core *c, pa_module*m) { mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); - nfrags = 12; - frag_size = 1024; + nfrags = DEFAULT_NFRAGS; + frag_size = DEFAULT_FRAGSIZE; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { pa_log(__FILE__": failed to parse fragments arguments"); goto fail; @@ -321,11 +376,6 @@ int pa__init(pa_core *c, pa_module*m) { if ((u->fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0) goto fail; - if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0) - pa_log_info(__FILE__": hardware name is '%s'.", hwdesc); - else - hwdesc[0] = 0; - if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_REALTIME) || !(caps & DSP_CAP_TRIGGER)) { pa_log(__FILE__": OSS device not mmap capable."); goto fail; @@ -333,6 +383,11 @@ int pa__init(pa_core *c, pa_module*m) { pa_log_info(__FILE__": device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0) + pa_log_info(__FILE__": hardware name is '%s'.", hwdesc); + else + hwdesc[0] = 0; + if (nfrags >= 2 && frag_size >= 1) if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0) goto fail; @@ -359,11 +414,13 @@ int pa__init(pa_core *c, pa_module*m) { } } else { - u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec, NULL); - assert(u->source); + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec, NULL))) + goto fail; + + u->source->userdata = u; + u->source->get_latency = source_get_latency_cb; u->source->get_hw_volume = source_get_hw_volume; u->source->set_hw_volume = source_set_hw_volume; - u->source->userdata = u; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'%s%s%s", p, @@ -371,7 +428,7 @@ int pa__init(pa_core *c, pa_module*m) { hwdesc[0] ? hwdesc : "", hwdesc[0] ? ")" : ""); - u->in_memblocks = pa_xmalloc0(sizeof(pa_memblock *)*u->in_fragments); + u->in_memblocks = pa_xnew0(pa_memblock*, u->in_fragments); enable_bits |= PCM_ENABLE_INPUT; } @@ -397,8 +454,9 @@ int pa__init(pa_core *c, pa_module*m) { } else { pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); - u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec, NULL); - assert(u->sink); + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec, NULL))) + goto fail; + u->sink->get_latency = sink_get_latency_cb; u->sink->get_hw_volume = sink_get_hw_volume; u->sink->set_hw_volume = sink_set_hw_volume; @@ -453,7 +511,9 @@ fail: void pa__done(pa_core *c, pa_module*m) { struct userdata *u; - assert(c && m); + + assert(c); + assert(m); if (!(u = m->userdata)) return; From 09589a75a466e019a2d7dca99f6cae4a3d598e55 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 19:44:11 +0000 Subject: [PATCH 0585/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@678 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/todo b/doc/todo index 81d4f863c..3613217c7 100644 --- a/doc/todo +++ b/doc/todo @@ -5,8 +5,6 @@ Test: - module-tunnel Fixes: -- module-oss-* love: - - improve latency measurement for mmap - correct API docs regarding timing work Post 0.8: From a81209f147c5aa701efda0c911229a0fd6948fc9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 20:38:58 +0000 Subject: [PATCH 0586/1514] validity checks for pa_context_is_pending() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@679 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 5 ++--- src/polyp/stream.c | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/polyp/context.c b/src/polyp/context.c index 845e88d9a..6fe008ea5 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -728,9 +728,8 @@ int pa_context_is_pending(pa_context *c) { assert(c); assert(c->ref >= 1); -/* pa_log("pstream: %i", pa_pstream_is_pending(c->pstream)); */ -/* pa_log("pdispatch: %i", pa_pdispatch_is_pending(c->pdispatch)); */ - + PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, -1); + return (c->pstream && pa_pstream_is_pending(c->pstream)) || (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) || c->client; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 0fcc36b7a..ca107750e 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -1235,5 +1235,3 @@ const pa_channel_map* pa_stream_get_channel_map(pa_stream *s) { return &s->channel_map; } - - From b2668ca063bc37377c324d507a3986879d0dc614 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 20:43:24 +0000 Subject: [PATCH 0587/1514] return the error code and not just -1 when pa_context_is_pending() fails git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@680 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/context.c b/src/polyp/context.c index 6fe008ea5..c16b54b41 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -728,7 +728,7 @@ int pa_context_is_pending(pa_context *c) { assert(c); assert(c->ref >= 1); - PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, -1); + PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); return (c->pstream && pa_pstream_is_pending(c->pstream)) || (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) || From 268c857381810fcfc52da46acc617bbc7e97e5a8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Apr 2006 21:15:39 +0000 Subject: [PATCH 0588/1514] unbreak fresh SVN builds git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@681 fefdeb5f-60dc-0310-8127-8f9354f1896f --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index 7fa1dc9af..31f3868ab 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -52,7 +52,7 @@ else test "x$LIBTOOLIZE" = "x" && LIBTOOLIZE=libtoolize - "$LIBTOOLIZE" -c --force + "$LIBTOOLIZE" -c --force --ltdl run_versioned aclocal "$VERSION" run_versioned autoconf 2.59 -Wall run_versioned autoheader 2.59 From 64d0d9bfbfc3cd89f0d8843e2e9181568dac2914 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 17:09:22 +0000 Subject: [PATCH 0589/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@682 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 3613217c7..10be043b8 100644 --- a/doc/todo +++ b/doc/todo @@ -6,6 +6,7 @@ Test: Fixes: - correct API docs regarding timing work +- incorporate client memblockq into latency calculations for recording streamings Post 0.8: - alsa mmap driver From a0c7ca00e73708844fdb68f63e616e843c828fd8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 17:09:51 +0000 Subject: [PATCH 0590/1514] when flushin a memblockq, set the write index to the read index git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@683 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/memblockq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/polypcore/memblockq.c b/src/polypcore/memblockq.c index 517495ebb..90e1d9ebe 100644 --- a/src/polypcore/memblockq.c +++ b/src/polypcore/memblockq.c @@ -548,6 +548,8 @@ void pa_memblockq_flush(pa_memblockq *bq) { assert(bq->n_blocks == 0); + bq->write_index = bq->read_index; + pa_memblockq_prebuf_force(bq); } From b5d177d90bea33237bb8c55320c2595ba12b0550 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 17:10:25 +0000 Subject: [PATCH 0591/1514] proper validity checking for pa_context_is_pending() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@684 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/polyp/context.c b/src/polyp/context.c index c16b54b41..7c0ed190c 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -728,7 +728,11 @@ int pa_context_is_pending(pa_context *c) { assert(c); assert(c->ref >= 1); - PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(c, + c->state == PA_CONTEXT_CONNECTING || + c->state == PA_CONTEXT_AUTHORIZING || + c->state == PA_CONTEXT_SETTING_NAME || + c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); return (c->pstream && pa_pstream_is_pending(c->pstream)) || (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) || From 77c2a1f561e8995ad62a38dfe1586577d5e93377 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 17:12:16 +0000 Subject: [PATCH 0592/1514] protocol change: don't send stream buffer size in latency update. This data is redundant, since it can be calculated from write_index - read_index anyway git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@685 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-native.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 51280c848..2aedd3909 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -1060,7 +1060,6 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); reply = reply_new(tag); - pa_tagstruct_put_usec(reply, pa_sink_input_get_latency(s->sink_input)); pa_tagstruct_put_usec(reply, pa_sink_get_latency(s->sink_input->sink)); pa_tagstruct_put_usec(reply, 0); pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq)); @@ -1091,7 +1090,6 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); reply = reply_new(tag); - pa_tagstruct_put_usec(reply, pa_source_output_get_latency(s->source_output)); pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0); pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source)); pa_tagstruct_put_boolean(reply, 0); From 49b3150434ee97fbcee33948053ffbf33a7b5505 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 17:17:23 +0000 Subject: [PATCH 0593/1514] * rename "latency correction" to "write index correction" * add read index invalidation code * rename "ipol_event" stuff to "auto_timing_update" * remove buffer_usec field from pa_timing_info, since it can be easily calculated from write_index and read_index anyway * add read_index_corrupt field to "pa_timing_info", similar to the already existing write_index_corrupt field * restart automatic timing update event every time a query is issued, not just when the last event elapsed * proper invalidation code for pa_stream_flush() * do tarsnport/sink/source latency correction for playback time only when device is not corked git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@686 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/def.h | 23 ++-- src/polyp/internal.h | 21 +-- src/polyp/stream.c | 308 ++++++++++++++++++++++++++----------------- 3 files changed, 217 insertions(+), 135 deletions(-) diff --git a/src/polyp/def.h b/src/polyp/def.h index eadddf088..432bd8ce1 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -204,13 +204,14 @@ typedef enum pa_subscription_event_type { * pa_stream_update_timing_info() and pa_stream_get_timing_info(). The * total output latency a sample that is written with * pa_stream_write() takes to be played may be estimated by - * sink_usec+buffer_usec+transport_usec. The output buffer to which - * buffer_usec relates may be manipulated freely (with + * sink_usec+buffer_usec+transport_usec. (where buffer_usec is defined + * as pa_bytes_to_usec(write_index-read_index)) The output buffer + * which buffer_usec relates to may be manipulated freely (with * pa_stream_write()'s seek argument, pa_stream_flush() and friends), * the buffers sink_usec and source_usec relate to are first-in - * first-out (FIFO) buffers which cannot be flushed or manipulated in any - * way. The total input latency a sample that is recorded takes to be - * delivered to the application is: + * first-out (FIFO) buffers which cannot be flushed or manipulated in + * any way. The total input latency a sample that is recorded takes to + * be delivered to the application is: * source_usec+buffer_usec+transport_usec-sink_usec. (Take care of * sign issues!) When connected to a monitor source sink_usec contains * the latency of the owning sink. The two latency estimations @@ -226,7 +227,6 @@ typedef struct pa_timing_info { * limited und unreliable itself. \since * 0.5 */ - pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play. For both playback and record streams. */ pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. For playback streams and record streams connected to a monitor source. */ pa_usec_t source_usec; /**< Time in usecs a sample takes from being recorded to being delivered to the application. Only for record streams. \since 0.5*/ pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to/from the daemon. For both playback and record streams. \since 0.5 */ @@ -240,14 +240,21 @@ typedef struct pa_timing_info { * info was current . Only write * commands with SEEK_RELATIVE_ON_READ * and SEEK_RELATIVE_END can corrupt - * write_index. */ + * write_index. \since 0.8 */ int64_t write_index; /**< Current write index into the * playback buffer in bytes. Think twice before * using this for seeking purposes: it * might be out of date a the time you * want to use it. Consider using * PA_SEEK_RELATIVE instead. \since - * 0.8 */ + * 0.8 */ + + int read_index_corrupt; /**< Non-zero if read_index is not + * up-to-date because a local pause or + * flush request that corrupted it has + * been issued in the time since this + * latency info was current. \since 0.8 */ + int64_t read_index; /**< Current read index into the * playback buffer in bytes. Think twice before * using this for seeking purposes: it diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 3b85b3d11..2bec0294f 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -83,14 +83,14 @@ struct pa_context { pa_client_conf *conf; }; -#define PA_MAX_LATENCY_CORRECTIONS 10 +#define PA_MAX_WRITE_INDEX_CORRECTIONS 10 -typedef struct pa_latency_correction { +typedef struct pa_index_correction { uint32_t tag; int valid; int64_t value; int absolute, corrupt; -} pa_latency_correction; +} pa_index_correction; struct pa_stream { int ref; @@ -124,13 +124,18 @@ struct pa_stream { /* Use to make sure that time advances monotonically */ pa_usec_t previous_time; - /* Latency correction stuff */ - pa_latency_correction latency_corrections[PA_MAX_LATENCY_CORRECTIONS]; - int idx_latency_correction; + /* time updates with tags older than these are invalid */ + uint32_t write_index_not_before; + uint32_t read_index_not_before; + + /* Data about individual timing update correctoins */ + pa_index_correction write_index_corrections[PA_MAX_WRITE_INDEX_CORRECTIONS]; + int current_write_index_correction; /* Latency interpolation stuff */ - pa_time_event *ipol_event; - int ipol_requested; + pa_time_event *auto_timing_update_event; + int auto_timing_update_requested; + pa_usec_t ipol_usec; int ipol_usec_valid; struct timeval ipol_timestamp; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index ca107750e..b3f19d09a 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -90,19 +90,22 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->previous_time = 0; s->timing_info_valid = 0; + s->read_index_not_before = 0; + s->write_index_not_before = 0; + for (i = 0; i < PA_MAX_WRITE_INDEX_CORRECTIONS; i++) + s->write_index_corrections[i].valid = 0; + s->current_write_index_correction = 0; + s->corked = 0; s->ipol_usec_valid = 0; s->ipol_timestamp.tv_sec = 0; s->ipol_timestamp.tv_usec = 0; - s->ipol_event = NULL; - s->ipol_requested = 0; - - for (i = 0; i < PA_MAX_LATENCY_CORRECTIONS; i++) - s->latency_corrections[i].valid = 0; - s->idx_latency_correction = 0; + s->auto_timing_update_event = NULL; + s->auto_timing_update_requested = 0; + PA_LLIST_PREPEND(pa_stream, c->streams, s); /* The context and stream will point at each other. We cannot ref count @@ -119,9 +122,9 @@ static void stream_free(pa_stream *s) { pa_context_unref(s->context); - if (s->ipol_event) { + if (s->auto_timing_update_event) { assert(s->mainloop); - s->mainloop->time_free(s->ipol_event); + s->mainloop->time_free(s->auto_timing_update_event); } if (s->peek_memchunk.memblock) @@ -296,34 +299,77 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC } } -finish: + finish: pa_context_unref(c); } -static void ipol_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { +static void request_auto_timing_update(pa_stream *s, int force) { struct timeval next; - pa_stream *s = userdata; + assert(s); - pa_stream_ref(s); - -/* pa_log("requesting new ipol data"); */ + if (!(s->flags & PA_STREAM_AUTO_TIMING_UPDATE)) + return; - if (s->state == PA_STREAM_READY && !s->ipol_requested) { + if (s->state == PA_STREAM_READY && + (force || !s->auto_timing_update_requested)) { pa_operation *o; +/* pa_log("automatically requesting new timing data"); */ + if ((o = pa_stream_update_timing_info(s, NULL, NULL))) { pa_operation_unref(o); - s->ipol_requested = 1; + s->auto_timing_update_requested = 1; } } - + pa_gettimeofday(&next); pa_timeval_add(&next, LATENCY_IPOL_INTERVAL_USEC); - m->time_restart(e, &next); - - pa_stream_unref(s); + s->mainloop->time_restart(s->auto_timing_update_event, &next); } +static void invalidate_indexes(pa_stream *s, int r, int w) { + assert(s); + + pa_log("invalidate r:%u w:%u tag:%u", r, w, s->context->ctag); + + if (s->state != PA_STREAM_READY) + return; + + if (w) { + s->write_index_not_before = s->context->ctag; + + if (s->timing_info_valid) + s->timing_info.write_index_corrupt = 1; + + pa_log("write_index invalidated"); + + } + + if (r) { + s->read_index_not_before = s->context->ctag; + + if (s->timing_info_valid) + s->timing_info.read_index_corrupt = 1; + + pa_log("read_index invalidated"); + } + + if ((s->direction == PA_STREAM_PLAYBACK && r) || + (s->direction == PA_STREAM_RECORD && w)) + s->ipol_usec_valid = 0; + + request_auto_timing_update(s, 1); +} + +static void auto_timing_update_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { + pa_stream *s = userdata; + + pa_log("time event"); + + pa_stream_ref(s); + request_auto_timing_update(s, 0); + pa_stream_unref(s); +} void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s = userdata; @@ -371,6 +417,8 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED /* We add an extra ref as long as we're connected (i.e. in the dynarray) */ pa_stream_ref(s); + pa_stream_set_state(s, PA_STREAM_READY); + if (s->direction != PA_STREAM_UPLOAD && s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { struct timeval tv; @@ -378,12 +426,12 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED pa_gettimeofday(&tv); tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */ - assert(!s->ipol_event); - s->ipol_event = s->mainloop->time_new(s->mainloop, &tv, &ipol_callback, s); + assert(!s->auto_timing_update_event); + s->auto_timing_update_event = s->mainloop->time_new(s->mainloop, &tv, &auto_timing_update_callback, s); + + request_auto_timing_update(s, 1); } - pa_stream_set_state(s, PA_STREAM_READY); - if (s->requested_bytes > 0 && s->ref > 1 && s->write_callback) s->write_callback(s, s->requested_bytes, s->write_userdata); @@ -548,18 +596,19 @@ int pa_stream_write( s->requested_bytes = 0; if (s->direction == PA_STREAM_PLAYBACK) { + /* Update latency request correction */ - if (s->latency_corrections[s->idx_latency_correction].valid) { + if (s->write_index_corrections[s->current_write_index_correction].valid) { if (seek == PA_SEEK_ABSOLUTE) { - s->latency_corrections[s->idx_latency_correction].corrupt = 0; - s->latency_corrections[s->idx_latency_correction].absolute = 1; - s->latency_corrections[s->idx_latency_correction].value = offset + length; + s->write_index_corrections[s->current_write_index_correction].corrupt = 0; + s->write_index_corrections[s->current_write_index_correction].absolute = 1; + s->write_index_corrections[s->current_write_index_correction].value = offset + length; } else if (seek == PA_SEEK_RELATIVE) { - if (!s->latency_corrections[s->idx_latency_correction].corrupt) - s->latency_corrections[s->idx_latency_correction].value += offset + length; + if (!s->write_index_corrections[s->current_write_index_correction].corrupt) + s->write_index_corrections[s->current_write_index_correction].value += offset + length; } else - s->latency_corrections[s->idx_latency_correction].corrupt = 1; + s->write_index_corrections[s->current_write_index_correction].corrupt = 1; } /* Update the write index in the already available latency data */ @@ -574,6 +623,9 @@ int pa_stream_write( } else s->timing_info.write_index_corrupt = 1; } + + if (!s->timing_info_valid || s->timing_info.write_index_corrupt) + request_auto_timing_update(s, 1); } return 0; @@ -672,15 +724,20 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, assert(o->context); i = &o->stream->timing_info; + + pa_log("pre corrupt w:%u r:%u\n", !o->stream->timing_info_valid || i->write_index_corrupt,!o->stream->timing_info_valid || i->read_index_corrupt); + o->stream->timing_info_valid = 0; i->write_index_corrupt = 0; + i->read_index_corrupt = 0; + + pa_log("timing update %u\n", tag); if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - } else if (pa_tagstruct_get_usec(t, &i->buffer_usec) < 0 || - pa_tagstruct_get_usec(t, &i->sink_usec) < 0 || + } else if (pa_tagstruct_get_usec(t, &i->sink_usec) < 0 || pa_tagstruct_get_usec(t, &i->source_usec) < 0 || pa_tagstruct_get_boolean(t, &i->playing) < 0 || pa_tagstruct_get_timeval(t, &local) < 0 || @@ -692,8 +749,11 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, goto finish; } else { + o->stream->timing_info_valid = 1; + pa_gettimeofday(&now); + /* Calculcate timestamps */ if (pa_timeval_cmp(&local, &remote) <= 0 && pa_timeval_cmp(&remote, &now) <= 0) { /* local and remote seem to have synchronized clocks */ @@ -712,6 +772,13 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, pa_timeval_add(&i->timestamp, i->transport_usec); } + /* Invalidate read and write indexes if necessary */ + if (tag < o->stream->read_index_not_before) + i->read_index_corrupt = 1; + + if (tag < o->stream->write_index_not_before) + i->write_index_corrupt = 1; + if (o->stream->direction == PA_STREAM_PLAYBACK) { /* Write index correction */ @@ -720,53 +787,54 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, /* Go through the saved correction values and add up the total correction.*/ - for (n = 0, j = o->stream->idx_latency_correction; - n < PA_MAX_LATENCY_CORRECTIONS; - n++, j = (j + 1) % PA_MAX_LATENCY_CORRECTIONS) { + for (n = 0, j = o->stream->current_write_index_correction+1; + n < PA_MAX_WRITE_INDEX_CORRECTIONS; + n++, j = (j + 1) % PA_MAX_WRITE_INDEX_CORRECTIONS) { /* Step over invalid data or out-of-date data */ - if (!o->stream->latency_corrections[j].valid || - o->stream->latency_corrections[j].tag < ctag) + if (!o->stream->write_index_corrections[j].valid || + o->stream->write_index_corrections[j].tag < ctag) continue; /* Make sure that everything is in order */ - ctag = o->stream->latency_corrections[j].tag+1; + ctag = o->stream->write_index_corrections[j].tag+1; /* Now fix the write index */ - if (o->stream->latency_corrections[j].corrupt) { + if (o->stream->write_index_corrections[j].corrupt) { /* A corrupting seek was made */ i->write_index = 0; i->write_index_corrupt = 1; - } else if (o->stream->latency_corrections[j].absolute) { + } else if (o->stream->write_index_corrections[j].absolute) { /* An absolute seek was made */ - i->write_index = o->stream->latency_corrections[j].value; + i->write_index = o->stream->write_index_corrections[j].value; i->write_index_corrupt = 0; } else if (!i->write_index_corrupt) { /* A relative seek was made */ - i->write_index += o->stream->latency_corrections[j].value; + i->write_index += o->stream->write_index_corrections[j].value; } } } - - o->stream->timing_info_valid = 1; - + o->stream->ipol_timestamp = now; o->stream->ipol_usec_valid = 0; } + o->stream->auto_timing_update_requested = 0; + pa_log("post corrupt w:%u r:%u\n", i->write_index_corrupt || !o->stream->timing_info_valid, i->read_index_corrupt || !o->stream->timing_info_valid); + /* Clear old correction entries */ if (o->stream->direction == PA_STREAM_PLAYBACK) { int n; - for (n = 0; n < PA_MAX_LATENCY_CORRECTIONS; n++) { - if (!o->stream->latency_corrections[n].valid) + for (n = 0; n < PA_MAX_WRITE_INDEX_CORRECTIONS; n++) { + if (!o->stream->write_index_corrections[n].valid) continue; - if (o->stream->latency_corrections[n].tag <= tag) - o->stream->latency_corrections[n].valid = 0; + if (o->stream->write_index_corrections[n].tag <= tag) + o->stream->write_index_corrections[n].valid = 0; } } - + if (o->callback) { pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback; cb(o->stream, o->stream->timing_info_valid, o->userdata); @@ -790,16 +858,15 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - + if (s->direction == PA_STREAM_PLAYBACK) { /* Find a place to store the write_index correction data for this entry */ - cidx = (s->idx_latency_correction + 1) % PA_MAX_LATENCY_CORRECTIONS; + cidx = (s->current_write_index_correction + 1) % PA_MAX_WRITE_INDEX_CORRECTIONS; /* Check if we could allocate a correction slot. If not, there are too many outstanding queries */ - PA_CHECK_VALIDITY_RETURN_NULL(s->context, !s->latency_corrections[cidx].valid, PA_ERR_INTERNAL); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, !s->write_index_corrections[cidx].valid, PA_ERR_INTERNAL); } - - o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command( s->context, @@ -813,14 +880,16 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t if (s->direction == PA_STREAM_PLAYBACK) { /* Fill in initial correction data */ - o->stream->idx_latency_correction = cidx; - o->stream->latency_corrections[cidx].valid = 1; - o->stream->latency_corrections[cidx].tag = tag; - o->stream->latency_corrections[cidx].absolute = 0; - o->stream->latency_corrections[cidx].value = 0; - o->stream->latency_corrections[cidx].corrupt = 0; + o->stream->current_write_index_correction = cidx; + o->stream->write_index_corrections[cidx].valid = 1; + o->stream->write_index_corrections[cidx].tag = tag; + o->stream->write_index_corrections[cidx].absolute = 0; + o->stream->write_index_corrections[cidx].value = 0; + o->stream->write_index_corrections[cidx].corrupt = 0; } + pa_log("requesting update %u\n", tag); + return pa_operation_ref(o); } @@ -946,7 +1015,6 @@ finish: pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; - pa_operation *lo; pa_tagstruct *t; uint32_t tag; @@ -956,15 +1024,6 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - if (s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { - if (!s->corked && b) { - /* Refresh the interpolated data just befor pausing */ - pa_stream_get_time(s, NULL); - } else if (s->corked && !b) - /* Unpausing */ - pa_gettimeofday(&s->ipol_timestamp); - } - s->corked = b; o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); @@ -978,9 +1037,9 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); - if ((lo = pa_stream_update_timing_info(s, NULL, NULL))) - pa_operation_unref(lo); - + if (s->direction == PA_STREAM_PLAYBACK) + invalidate_indexes(s, 1, 0); + return pa_operation_ref(o); } @@ -1006,14 +1065,24 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; - + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) { - pa_operation *lo; - if ((lo = pa_stream_update_timing_info(s, NULL, NULL))) - pa_operation_unref(lo); + if (s->direction == PA_STREAM_PLAYBACK) { + if (s->write_index_corrections[s->current_write_index_correction].valid) + s->write_index_corrections[s->current_write_index_correction].corrupt = 1; + + if (s->timing_info_valid) + s->timing_info.write_index_corrupt = 1; + + if (s->buffer_attr.prebuf > 0) + invalidate_indexes(s, 1, 0); + else + request_auto_timing_update(s, 1); + } else + invalidate_indexes(s, 0, 1); } return o; @@ -1023,14 +1092,11 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us pa_operation *o; PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE); - if ((o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata))) { - pa_operation *lo; + if ((o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata))) + invalidate_indexes(s, 1, 0); - if ((lo = pa_stream_update_timing_info(s, NULL, NULL))) - pa_operation_unref(lo); - } - return o; } @@ -1038,13 +1104,10 @@ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *u pa_operation *o; PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE); - if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata))) { - pa_operation *lo; - - if ((lo = pa_stream_update_timing_info(s, NULL, NULL))) - pa_operation_unref(lo); - } + if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata))) + invalidate_indexes(s, 1, 0); return o; } @@ -1084,50 +1147,56 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->timing_info_valid, PA_ERR_NODATA); + PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->timing_info.read_index_corrupt, PA_ERR_NODATA); + PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_RECORD || !s->timing_info.write_index_corrupt, PA_ERR_NODATA); - if (s->flags & PA_STREAM_INTERPOLATE_TIMING && s->ipol_usec_valid ) + if (s->flags & PA_STREAM_INTERPOLATE_TIMING && s->ipol_usec_valid) usec = s->ipol_usec; else { if (s->direction == PA_STREAM_PLAYBACK) { /* The last byte that was written into the output device * had this time value associated */ usec = pa_bytes_to_usec(s->timing_info.read_index < 0 ? 0 : (uint64_t) s->timing_info.read_index, &s->sample_spec); - - /* Because the latency info took a little time to come - * to us, we assume that the real output time is actually - * a little ahead */ - usec += s->timing_info.transport_usec; - - /* However, the output device usually maintains a buffer - too, hence the real sample currently played is a little - back */ - if (s->timing_info.sink_usec >= usec) - usec = 0; - else - usec -= s->timing_info.sink_usec; + + if (!s->corked) { + /* Because the latency info took a little time to come + * to us, we assume that the real output time is actually + * a little ahead */ + usec += s->timing_info.transport_usec; + + /* However, the output device usually maintains a buffer + too, hence the real sample currently played is a little + back */ + if (s->timing_info.sink_usec >= usec) + usec = 0; + else + usec -= s->timing_info.sink_usec; + } } else if (s->direction == PA_STREAM_RECORD) { /* The last byte written into the server side queue had * this time value associated */ usec = pa_bytes_to_usec(s->timing_info.write_index < 0 ? 0 : (uint64_t) s->timing_info.write_index, &s->sample_spec); - - /* Add transport latency */ - usec += s->timing_info.transport_usec; - - /* Add latency of data in device buffer */ - usec += s->timing_info.source_usec; - - /* If this is a monitor source, we need to correct the - * time by the playback device buffer */ - if (s->timing_info.sink_usec >= usec) - usec = 0; - else - usec -= s->timing_info.sink_usec; + + if (!s->corked) { + /* Add transport latency */ + usec += s->timing_info.transport_usec; + + /* Add latency of data in device buffer */ + usec += s->timing_info.source_usec; + + /* If this is a monitor source, we need to correct the + * time by the playback device buffer */ + if (s->timing_info.sink_usec >= usec) + usec = 0; + else + usec -= s->timing_info.sink_usec; + } } if (s->flags & PA_STREAM_INTERPOLATE_TIMING) { - s->ipol_usec_valid = 1; s->ipol_usec = usec; + s->ipol_usec_valid = 1; } } @@ -1189,6 +1258,7 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) { PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->timing_info_valid, PA_ERR_NODATA); PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->timing_info.write_index_corrupt, PA_ERR_NODATA); + PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_RECORD || !s->timing_info.read_index_corrupt, PA_ERR_NODATA); if ((r = pa_stream_get_time(s, &t)) < 0) return r; From d42794206db90b0a991c246d12afc409aafcafa5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 17:18:24 +0000 Subject: [PATCH 0594/1514] beefup pacat a little: * when -v is passed, show current playback time and latency * modify SIGUSR1 behaviour to show only playback time and latency git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@687 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 59 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index e721befa9..2c12dbb31 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -36,6 +36,9 @@ #include #include #include +#include + +#define TIME_EVENT_USEC 50000 #if PA_API_VERSION != 8 #error Invalid Polypaudio API version @@ -153,7 +156,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_READY: if (verbose) - fprintf(stderr, "Stream successfully created\n"); + fprintf(stderr, "Stream successfully created.\n"); break; case PA_STREAM_FAILED: @@ -341,34 +344,46 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, /* Show the current latency */ static void stream_update_timing_callback(pa_stream *s, int success, void *userdata) { - pa_usec_t total; + pa_usec_t latency, usec; int negative = 0; - const pa_timing_info *i; assert(s); if (!success || - !(i = pa_stream_get_timing_info(s)) || - pa_stream_get_latency(s, &total, &negative) < 0) { + pa_stream_get_time(s, &usec) < 0 || + pa_stream_get_latency(s, &latency, &negative) < 0) { fprintf(stderr, "Failed to get latency: %s\n", pa_strerror(pa_context_errno(context))); quit(1); return; } - fprintf(stderr, "Latency: buffer: %0.0f usec; sink: %0.0f usec; source: %0.0f usec; transport: %0.0f usec; total: %0.0f usec; synchronized clocks: %s.\n", - (float) i->buffer_usec, - (float) i->sink_usec, - (float) i->source_usec, - (float) i->transport_usec, - (float) total * (negative?-1:1), - i->synchronized_clocks ? "yes" : "no"); + fprintf(stderr, "Time: %0.3f sec; Latency: %0.0f usec. \r", + (float) usec / 1000000, + (float) latency * (negative?-1:1)); } /* Someone requested that the latency is shown */ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { + + if (!stream) + return; + pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); } +static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { + struct timeval next; + + if (!stream) + return; + + pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); + + pa_gettimeofday(&next); + pa_timeval_add(&next, TIME_EVENT_USEC); + + m->time_restart(e, &next); +} static void help(const char *argv0) { @@ -404,6 +419,7 @@ int main(int argc, char *argv[]) { pa_mainloop* m = NULL; int ret = 1, r, c; char *bn, *server = NULL; + pa_time_event *time_event = NULL; static const struct option long_options[] = { {"record", 0, NULL, 'r'}, @@ -561,7 +577,7 @@ int main(int argc, char *argv[]) { mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { - fprintf(stderr, "source_io() failed.\n"); + fprintf(stderr, "io_new() failed.\n"); goto quit; } @@ -576,6 +592,18 @@ int main(int argc, char *argv[]) { /* Connect the context */ pa_context_connect(context, server, 0, NULL); + if (verbose) { + struct timeval tv; + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, TIME_EVENT_USEC); + + if (!(time_event = mainloop_api->time_new(mainloop_api, &tv, time_event_callback, NULL))) { + fprintf(stderr, "time_new() failed.\n"); + goto quit; + } + } + /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { fprintf(stderr, "pa_mainloop_run() failed.\n"); @@ -593,6 +621,11 @@ quit: assert(mainloop_api); mainloop_api->io_free(stdio_event); } + + if (time_event) { + assert(mainloop_api); + mainloop_api->time_free(time_event); + } if (m) { pa_signal_done(); From 0fa56f9b6f87ac230591fdaae70f0390161ab8d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 17:26:24 +0000 Subject: [PATCH 0595/1514] remove a bunch of log messages git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@688 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index b3f19d09a..fc8cc5cc5 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -330,7 +330,7 @@ static void request_auto_timing_update(pa_stream *s, int force) { static void invalidate_indexes(pa_stream *s, int r, int w) { assert(s); - pa_log("invalidate r:%u w:%u tag:%u", r, w, s->context->ctag); +/* pa_log("invalidate r:%u w:%u tag:%u", r, w, s->context->ctag); */ if (s->state != PA_STREAM_READY) return; @@ -341,8 +341,7 @@ static void invalidate_indexes(pa_stream *s, int r, int w) { if (s->timing_info_valid) s->timing_info.write_index_corrupt = 1; - pa_log("write_index invalidated"); - +/* pa_log("write_index invalidated"); */ } if (r) { @@ -351,7 +350,7 @@ static void invalidate_indexes(pa_stream *s, int r, int w) { if (s->timing_info_valid) s->timing_info.read_index_corrupt = 1; - pa_log("read_index invalidated"); +/* pa_log("read_index invalidated"); */ } if ((s->direction == PA_STREAM_PLAYBACK && r) || @@ -364,7 +363,7 @@ static void invalidate_indexes(pa_stream *s, int r, int w) { static void auto_timing_update_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { pa_stream *s = userdata; - pa_log("time event"); +/* pa_log("time event"); */ pa_stream_ref(s); request_auto_timing_update(s, 0); @@ -725,13 +724,13 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, i = &o->stream->timing_info; - pa_log("pre corrupt w:%u r:%u\n", !o->stream->timing_info_valid || i->write_index_corrupt,!o->stream->timing_info_valid || i->read_index_corrupt); +/* pa_log("pre corrupt w:%u r:%u\n", !o->stream->timing_info_valid || i->write_index_corrupt,!o->stream->timing_info_valid || i->read_index_corrupt); */ o->stream->timing_info_valid = 0; i->write_index_corrupt = 0; i->read_index_corrupt = 0; - pa_log("timing update %u\n", tag); +/* pa_log("timing update %u\n", tag); */ if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -820,7 +819,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, } o->stream->auto_timing_update_requested = 0; - pa_log("post corrupt w:%u r:%u\n", i->write_index_corrupt || !o->stream->timing_info_valid, i->read_index_corrupt || !o->stream->timing_info_valid); +/* pa_log("post corrupt w:%u r:%u\n", i->write_index_corrupt || !o->stream->timing_info_valid, i->read_index_corrupt || !o->stream->timing_info_valid); */ /* Clear old correction entries */ if (o->stream->direction == PA_STREAM_PLAYBACK) { @@ -888,7 +887,7 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t o->stream->write_index_corrections[cidx].corrupt = 0; } - pa_log("requesting update %u\n", tag); +/* pa_log("requesting update %u\n", tag); */ return pa_operation_ref(o); } From 853caf12740ed3ff4f4c64c2cb458cb0cc635d25 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 18:33:13 +0000 Subject: [PATCH 0596/1514] * fix latency calculation where a full playback buffer was erroneously taken as empty buffer and vice versa. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@689 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss-mmap.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 5389a201f..c487f40c3 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -70,8 +70,9 @@ struct userdata { pa_core *core; pa_sample_spec sample_spec; - size_t in_fragment_size, out_fragment_size, in_fragments, out_fragments; - int out_blocks_saved, in_blocks_saved; + size_t in_fragment_size, out_fragment_size; + unsigned in_fragments, out_fragments; + unsigned out_blocks_saved, in_blocks_saved; int fd; @@ -121,7 +122,12 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { if (u->out_memblocks[u->out_current]) pa_memblock_unref_fixed(u->out_memblocks[u->out_current]); - chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed((uint8_t*)u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size, 1, u->core->memblock_stat); + chunk.memblock = u->out_memblocks[u->out_current] = + pa_memblock_new_fixed( + (uint8_t*) u->out_mmap+u->out_fragment_size*u->out_current, + u->out_fragment_size, + 1, + u->core->memblock_stat); assert(chunk.memblock); chunk.length = chunk.memblock->length; chunk.index = 0; @@ -233,7 +239,7 @@ static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd static pa_usec_t sink_get_latency_cb(pa_sink *s) { struct userdata *u = s->userdata; struct count_info info; - size_t bpos, n; + size_t bpos, n, total; assert(s && u); if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { @@ -243,12 +249,15 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { u->out_blocks_saved += info.blocks; - bpos = ((u->out_current + u->out_blocks_saved) % u->out_fragments) * u->out_fragment_size; + total = u->out_fragments * u->out_fragment_size; + bpos = ((u->out_current + u->out_blocks_saved) * u->out_fragment_size) % total; - if (bpos < (size_t) info.ptr) - n = (u->out_fragments * u->out_fragment_size) - (info.ptr - bpos); + if (bpos <= (size_t) info.ptr) + n = total - (info.ptr - bpos); else n = bpos - info.ptr; + +/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->out_fragment_size, u->out_fragments); */ return pa_bytes_to_usec(n, &s->sample_spec); } @@ -256,7 +265,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { static pa_usec_t source_get_latency_cb(pa_source *s) { struct userdata *u = s->userdata; struct count_info info; - size_t bpos, n; + size_t bpos, n, total; assert(s && u); if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { @@ -266,12 +275,15 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { u->in_blocks_saved += info.blocks; - bpos = ((u->in_current + u->in_blocks_saved) % u->in_fragments) * u->in_fragment_size; + total = u->in_fragments * u->in_fragment_size; + bpos = ((u->in_current + u->in_blocks_saved) * u->in_fragment_size) % total; - if (bpos < (size_t) info.ptr) + if (bpos <= (size_t) info.ptr) n = info.ptr - bpos; else n = (u->in_fragments * u->in_fragment_size) - bpos + info.ptr; + +/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->in_fragment_size, u->in_fragments); */ return pa_bytes_to_usec(n, &s->sample_spec); } From bf88854e60500f251fefbde8ab678b9d93280201 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 22:45:57 +0000 Subject: [PATCH 0597/1514] * dispatch defer events in pa_mainloop_dispatch() and not already in pa_mainloop_prepare() * fix the "timeout" parameter of pa_mainloop_prepare() * remove pa_mainloop_deferred_pending() and update the simple API accordingly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@690 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/mainloop.c | 125 +++++++++++++++++++++---------------------- src/polyp/mainloop.h | 5 +- src/polyp/simple.c | 37 ++++++------- 3 files changed, 81 insertions(+), 86 deletions(-) diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 95c336e4b..da3f57b2e 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -624,83 +624,95 @@ static void clear_wakeup(pa_mainloop *m) { } int pa_mainloop_prepare(pa_mainloop *m, int timeout) { - int dispatched = 0; - - assert(m && (m->state == STATE_PASSIVE)); + assert(m); + assert(m->state == STATE_PASSIVE); clear_wakeup(m); - scan_dead(m); if (m->quit) goto quit; - dispatched += dispatch_defer(m); - - if (m->quit) - goto quit; - - if (m->rebuild_pollfds) - rebuild_pollfds(m); - - m->prepared_timeout = calc_next_timeout(m); - if ((timeout >= 0) && (m->prepared_timeout > timeout)) - m->prepared_timeout = timeout; + if (!m->deferred_pending) { + + if (m->rebuild_pollfds) + rebuild_pollfds(m); + + m->prepared_timeout = calc_next_timeout(m); + if (timeout >= 0 && (timeout < m->prepared_timeout || m->prepared_timeout < 0)) + m->prepared_timeout = timeout; + } m->state = STATE_PREPARED; - - return dispatched; + return 0; quit: - m->state = STATE_QUIT; - return -2; } int pa_mainloop_poll(pa_mainloop *m) { int r; - assert(m && (m->state == STATE_PREPARED)); + assert(m); + assert(m->state == STATE_PREPARED); + + if (m->quit) + goto quit; m->state = STATE_POLLING; - r = poll(m->pollfds, m->n_pollfds, m->prepared_timeout); + if (m->deferred_pending) + r = 0; + else { + r = poll(m->pollfds, m->n_pollfds, m->prepared_timeout); - if ((r < 0) && (errno == EINTR)) - r = 0; - - if (r < 0) - m->state = STATE_PASSIVE; - else - m->state = STATE_POLLED; + if (r < 0) { + if (errno == EINTR) + r = 0; + else + pa_log(__FILE__": poll(): %s", strerror(errno)); + } + } + m->state = r < 0 ? STATE_PASSIVE : STATE_POLLED; return r; + +quit: + m->state = STATE_QUIT; + return -2; } int pa_mainloop_dispatch(pa_mainloop *m) { int dispatched = 0; - assert(m && (m->state == STATE_POLLED)); - - dispatched += dispatch_timeout(m); + assert(m); + assert(m->state == STATE_POLLED); if (m->quit) goto quit; - dispatched += dispatch_pollfds(m); + if (m->deferred_pending) + dispatched += dispatch_defer(m); + else { + dispatched += dispatch_timeout(m); + + if (m->quit) + goto quit; + + dispatched += dispatch_pollfds(m); + } + if (m->quit) goto quit; - + m->state = STATE_PASSIVE; return dispatched; quit: - m->state = STATE_QUIT; - return -2; } @@ -710,39 +722,30 @@ int pa_mainloop_get_retval(pa_mainloop *m) { } int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) { - int r, dispatched = 0; - + int r; assert(m); - r = pa_mainloop_prepare(m, block ? -1 : 0); - if (r < 0) { - if ((r == -2) && retval) - *retval = pa_mainloop_get_retval(m); - return r; - } + if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0) + goto quit; - dispatched += r; + if ((r = pa_mainloop_poll(m)) < 0) + goto quit; - r = pa_mainloop_poll(m); - if (r < 0) { - pa_log(__FILE__": poll(): %s", strerror(errno)); - return r; - } + if ((r = pa_mainloop_dispatch(m)) < 0) + goto quit; - r = pa_mainloop_dispatch(m); - if (r < 0) { - if ((r == -2) && retval) - *retval = pa_mainloop_get_retval(m); - return r; - } + return r; - dispatched += r; - - return dispatched; +quit: + + if ((r == -2) && retval) + *retval = pa_mainloop_get_retval(m); + return r; } int pa_mainloop_run(pa_mainloop *m, int *retval) { int r; + while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0); if (r == -2) @@ -764,12 +767,6 @@ pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) { return &m->api; } -int pa_mainloop_deferred_pending(pa_mainloop *m) { - assert(m); - return m->deferred_pending > 0; -} - - #if 0 void pa_mainloop_dump(pa_mainloop *m) { assert(m); diff --git a/src/polyp/mainloop.h b/src/polyp/mainloop.h index c06b47d00..82d1adc4a 100644 --- a/src/polyp/mainloop.h +++ b/src/polyp/mainloop.h @@ -107,12 +107,9 @@ int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval); /** Run unlimited iterations of the main loop object until the main loop's quit() routine is called. */ int pa_mainloop_run(pa_mainloop *m, int *retval); -/** Return the abstract main loop abstraction layer vtable for this main loop. This calls pa_mainloop_iterate() iteratively.*/ +/** Return the abstract main loop abstraction layer vtable for this main loop. */ pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m); -/** Return non-zero when there are any deferred events pending. \since 0.5 */ -int pa_mainloop_deferred_pending(pa_mainloop *m); - /** Shutdown the main loop */ void pa_mainloop_quit(pa_mainloop *m, int r); diff --git a/src/polyp/simple.c b/src/polyp/simple.c index f48c0b176..dbf7a3258 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -91,30 +91,31 @@ static int iterate(pa_simple *p, int block, int *rerror) { if (check_error(p, rerror) < 0) return -1; - - if (!block && !pa_context_is_pending(p->context)) - return 0; - do { - if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) { + if (block || pa_context_is_pending(p->context)) { + do { + if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) { + if (rerror) + *rerror = PA_ERR_INTERNAL; + return -1; + } + + if (check_error(p, rerror) < 0) + return -1; + } while (pa_context_is_pending(p->context)); + } + + for (;;) { + int r; + + if ((r = pa_mainloop_iterate(p->mainloop, 0, NULL)) < 0) { if (rerror) *rerror = PA_ERR_INTERNAL; return -1; } - if (check_error(p, rerror) < 0) - return -1; - - } while (pa_context_is_pending(p->context)); - - - while (pa_mainloop_deferred_pending(p->mainloop)) { - - if (pa_mainloop_iterate(p->mainloop, 0, NULL) < 0) { - if (rerror) - *rerror = PA_ERR_INTERNAL; - return -1; - } + if (r == 0) + break; if (check_error(p, rerror) < 0) return -1; From 0af582a8d6297f0e4b156001b49f38bba032b199 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 23:12:54 +0000 Subject: [PATCH 0598/1514] small fix to deal properly with slow links git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@691 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 2c12dbb31..4d3302ab1 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -374,10 +374,13 @@ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int s static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { struct timeval next; - if (!stream) - return; - - pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); + if (stream) { + pa_operation *o; + if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL))) + fprintf(stderr, "pa_stream_update_timing_info() failed: %s\n", pa_strerror(pa_context_errno(context))); + else + pa_operation_unref(o); + } pa_gettimeofday(&next); pa_timeval_add(&next, TIME_EVENT_USEC); From 4a8d3185492f381c88c737097123638bf9f6ed29 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 23:19:07 +0000 Subject: [PATCH 0599/1514] yet anotrher fix for slow links git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@692 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 4d3302ab1..1e22656d6 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -374,7 +374,7 @@ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int s static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { struct timeval next; - if (stream) { + if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) { pa_operation *o; if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL))) fprintf(stderr, "pa_stream_update_timing_info() failed: %s\n", pa_strerror(pa_context_errno(context))); From 06bd27b0433e06f3af573ddc213e2577127972e4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 23:55:21 +0000 Subject: [PATCH 0600/1514] when storing recording data in file, create file with proper access rights git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@693 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 1e22656d6..cce974423 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -540,7 +540,7 @@ int main(int argc, char *argv[]) { if (optind+1 == argc) { int fd; - if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT)) < 0) { + if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { fprintf(stderr, "open(): %s\n", strerror(errno)); goto quit; } From 7fa8323453fab243192bacdae0aeae1e65146f13 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 23:57:25 +0000 Subject: [PATCH 0601/1514] include local record memblockq in latency calculations git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@694 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 6 ++++-- src/polyp/stream.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/polyp/context.c b/src/polyp/context.c index 7c0ed190c..047b739f7 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -294,12 +294,14 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o assert(c->ref >= 1); pa_context_ref(c); - + if ((s = pa_dynarray_get(c->record_streams, channel))) { + assert(seek == PA_SEEK_RELATIVE && offset == 0); + pa_memblockq_seek(s->record_memblockq, offset, seek); pa_memblockq_push_align(s->record_memblockq, chunk); - + if (s->read_callback) { size_t l; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index fc8cc5cc5..ce2470f6f 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -662,6 +662,10 @@ int pa_stream_drop(pa_stream *s) { PA_CHECK_VALIDITY(s->context, s->peek_memchunk.memblock, PA_ERR_BADSTATE); pa_memblockq_drop(s->record_memblockq, &s->peek_memchunk, s->peek_memchunk.length); + + /* Fix the simulated local read index */ + if (s->timing_info_valid && !s->timing_info.read_index_corrupt) + s->timing_info.read_index += s->peek_memchunk.length; pa_memblock_unref(s->peek_memchunk.memblock); s->peek_memchunk.length = 0; @@ -814,6 +818,13 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, } } + if (o->stream->direction == PA_STREAM_RECORD) { + /* Read index correction */ + + if (!i->read_index_corrupt) + i->read_index -= pa_memblockq_get_length(o->stream->record_memblockq); + } + o->stream->ipol_timestamp = now; o->stream->ipol_usec_valid = 0; } From b33ae7913a51b0a33030912ce789f0328f8caaf1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Apr 2006 23:58:19 +0000 Subject: [PATCH 0602/1514] remove yet another item from the todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@695 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 10be043b8..3613217c7 100644 --- a/doc/todo +++ b/doc/todo @@ -6,7 +6,6 @@ Test: Fixes: - correct API docs regarding timing work -- incorporate client memblockq into latency calculations for recording streamings Post 0.8: - alsa mmap driver From ceb09d8ae9bd11380ed3dc7d28054812ff0a0f04 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 00:56:10 +0000 Subject: [PATCH 0603/1514] Documentation updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@696 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.h | 4 +-- src/polyp/context.h | 6 ++-- src/polyp/mainloop.h | 4 +-- src/polyp/sample.h | 2 +- src/polyp/simple.h | 4 +-- src/polyp/stream.h | 75 ++++++++++++++++++++++++++++++++++-------- src/polyp/volume.h | 10 ++++-- 7 files changed, 80 insertions(+), 25 deletions(-) diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index c74f2ceb1..99020583c 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -30,8 +30,8 @@ * \section overv_sec Overview * * Channel maps provide a way to associate channels in a stream with a - * speaker. This relieves applications of having to make sure their channel - * order is identical to the final output. + * specific speaker position. This relieves applications of having to + * make sure their channel order is identical to the final output. * * \section init_sec Initialisation * diff --git a/src/polyp/context.h b/src/polyp/context.h index 460034c1e..848308116 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -48,7 +48,7 @@ * The abstraction is represented as a number of function pointers in the * pa_mainloop_api structure. * - * To actually be able to use these functions, an actual implementation + * To actually be able to use these functions, an implementation needs to * be coupled to the abstraction. There are two of these shipped with * polypaudio, but any other can be used with a minimal ammount of work, * provided it supports the three basic events listed above. @@ -88,11 +88,11 @@ * channel. * * There is no need for more than one context per application, unless - * connections to multiple servers is needed. + * connections to multiple servers are needed. * * \subsection ops_subsec Operations * - * All operations on the context is performed asynchronously. I.e. the + * All operations on the context are performed asynchronously. I.e. the * client will not wait for the server to complete the request. To keep * track of all these in-flight operations, the application is given a * pa_operation object for each asynchronous operation. diff --git a/src/polyp/mainloop.h b/src/polyp/mainloop.h index 82d1adc4a..6fb2a96cd 100644 --- a/src/polyp/mainloop.h +++ b/src/polyp/mainloop.h @@ -45,10 +45,10 @@ PA_C_DECL_BEGIN * consists of three steps that repeat during the application's entire * lifetime: * - * -# Prepare - Dispatch deferred events, build a list of file descriptors + * -# Prepare - Build a list of file descriptors * that need to be monitored and calculate the next timeout. * -# Poll - Execute the actuall poll() system call. - * -# Dispatch - Dispatch any timeouts and file descriptors that have fired. + * -# Dispatch - Dispatch any events that have fired. * * When using the main loop, the application can either execute each * iteration, one at a time, using pa_mainloop_iterate(), or let the library diff --git a/src/polyp/sample.h b/src/polyp/sample.h index 284b428bd..0706be5ae 100644 --- a/src/polyp/sample.h +++ b/src/polyp/sample.h @@ -99,7 +99,7 @@ PA_C_DECL_BEGIN -/** Maximum allowed channels */ +/** Maximum number of allowed channels */ #define PA_CHANNELS_MAX 16 /** Sample format */ diff --git a/src/polyp/simple.h b/src/polyp/simple.h index d2adde022..9066826ba 100644 --- a/src/polyp/simple.h +++ b/src/polyp/simple.h @@ -47,7 +47,7 @@ * pa_simple *s; * pa_sample_spec ss; * - * ss.format = S16_NE; + * ss.format = PA_SAMPLE_S16_NE; * ss.channels = 2; * ss.rate = 44100; * @@ -70,7 +70,7 @@ * Once the connection is established to the server, data can start flowing. * Using the connection is very similar to the normal read() and write() * system calls. The main difference is that they're call pa_simple_read() - * and pa_simple_write(). Note that these operation are always blocking. + * and pa_simple_write(). Note that these operations always block. * * \section ctrl_sec Buffer control * diff --git a/src/polyp/stream.h b/src/polyp/stream.h index bb5aa7646..6367e8683 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -69,7 +69,7 @@ * * \subsection bufattr_subsec Buffer attributes * - * Playback and record streams always have a buffer as part of the data flow. + * Playback and record streams always have a server side buffer as part of the data flow. * The size of this buffer strikes a compromise between low latency and * sensitivity for buffer overflows/underruns. * @@ -133,33 +133,82 @@ * monitoring the current latency. * * To get the raw data needed to calculate latencies, call - * pa_stream_get_timing_info(). This will give you a pa_timing_info structure - * that contains everything that is known about buffers, transport delays - * and the backend active in the server. + * pa_stream_get_timing_info(). This will give you a pa_timing_info + * structure that contains everything that is known about buffers, + * transport delays and the backend active in the server. * - * If a more simplistic interface is prefered, you can call - * pa_stream_get_time() or pa_stream_get_latency(). These will do all the - * necessary calculations for you. + * This structure is updated every time a + * pa_stream_update_timing_info() operation is executed. (i.e. before + * the first call to this function the timing information structure is + * not available!) Since it is a lot of work to keep this structure + * up-to-date manually, Polypaudio can do that automatically for you: + * if PA_STREAM_AUTO_TIMING_UPDATE is passed when connecting the + * stream Polypaudio will automatically update the structure every + * 100ms and every time a function is called that might invalidate the + * previously known timing data (such as pa_stream_write() or + * pa_stream_flush()). Please note however, that there always is a + * short time window when the data in the timing information structure + * is out-of-date. Polypaudio tries to mark these situations by + * setting the write_index_corrupt and read_index_corrupt fields + * accordingly. * - * The latency information is constantly updated from the server. Be aware - * that between updates, old data will be returned. If you specify the flag - * PA_STREAM_INTERPOLATE_TIMING when creating the stream, pa_stream_get_time() - * and pa_stream_get_latency() will calculate the latency between updates - * based on the time elapsed. + * The raw timing data in the pa_timing_info structure is usually hard + * to deal with. Therefore a more simplistic interface is available: + * you can call pa_stream_get_time() or pa_stream_get_latency(). The + * former will return the current playback time of the hardware since + * the stream has been started. The latter returns the time a sample + * that you write now takes to be played by the hardware. * + * Since updating the timing info structure usually requires a full + * round trip and some applications monitor the timing very often + * Polypaudio offers a timing interpolation system. If + * PA_STREAM_INTERPOLATE_TIMING is passed when connecting the stream, + * pa_stream_get_time() and pa_stream_get_latency() will try to + * interpolate the current playback time/latency by estimating the + * number of samples that have been played back by the hardware since + * the last regular timing update. It is espcially useful to combine + * this option with PA_STREAM_AUTO_TIMING_UPDATE, which will enable + * you to monitor the current playback time/latency very precisely + * without requiring a network round trip every time. + * * \section flow_sec Overflow and underflow * - * Even with the best precautions, buffers will sometime over- or underflow. + * Even with the best precautions, buffers will sometime over - or underflow. * To handle this gracefully, the application can be notified when this * happens. Callbacks are registered using pa_stream_set_overflow_callback() * and pa_stream_set_underflow_callback(). * + * \section sync_streams Sychronizing Multiple Playback Streams. + * + * Polypaudio allows applications to fully synchronize multiple playback + * streams that are connected to the same output device. That means + * the streams will always be played back sample-by-sample + * synchronously. If stream operations like pa_stream_cork() are + * issued on one of the synchronized streams, they are simultaneously + * issued on the others. + * + * To synchronize a stream to another, just pass the "master" stream + * as last argument to pa_stream_connect_playack(). To make sure that + * the freshly created stream doesn't start playback right-away, make + * sure to pass PA_STREAM_START_CORKED and - after all streams have + * been created - uncork them all with a single call to + * pa_stream_cork() for the master stream. + * + * To make sure that a particular stream doesn't stop to play when a + * server side buffer underrun happens on it while the other + * synchronized streams continue playing and hence deviate you need to + * pass a "prebuf" pa_buffer_attr of 0 when connecting it. + * + * \section seek_modes Seeking in the Playback Buffer + * + * T.B.D * \section disc_sec Disconnecting * * When a stream has served is purpose it must be disconnected with * pa_stream_disconnect(). If you only unreference it, then it will live on * and eat resources both locally and on the server until you disconnect the * context. + * */ /** \file diff --git a/src/polyp/volume.h b/src/polyp/volume.h index 181784f40..a72069eb8 100644 --- a/src/polyp/volume.h +++ b/src/polyp/volume.h @@ -53,8 +53,14 @@ * For simple multiplication, pa_sw_volume_multiply() and * pa_sw_cvolume_multiply() can be used. * - * Calculations can only be reliably be performed on software volumes as - * it is commonly unknown what scale hardware volumes use. + * Calculations can only be reliably performed on software volumes + * as it is commonly unknown what scale hardware volumes relate to. + * + * The functions described above are only valid when used with + * software volumes. Hence it is usually a better idea to treat all + * volume values as opaque with a range from PA_VOLUME_MUTE (0%) to + * PA_VOLUME_NORM (100%) and to refrain from any calculations with + * them. * * \section conv_sec Convenience functions * From 20f4ae65f2ec49cc0ef733b67c5194a0eb3d453b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 13:45:38 +0000 Subject: [PATCH 0604/1514] more documentation updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@697 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.h | 4 +- src/polyp/context.h | 4 +- src/polyp/def.h | 2 +- src/polyp/glib-mainloop.h | 2 +- src/polyp/introspect.h | 22 ++++---- src/polyp/mainloop.h | 10 ++-- src/polyp/sample.h | 8 +-- src/polyp/scache.h | 2 +- src/polyp/stream.h | 109 +++++++++++++++++++++++++++----------- src/polyp/subscribe.h | 2 +- src/polyp/volume.h | 4 +- 11 files changed, 106 insertions(+), 63 deletions(-) diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index 99020583c..bb9f78b11 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -25,7 +25,7 @@ #include #include -/** \page channelmap Channel maps +/** \page channelmap Channel Maps * * \section overv_sec Overview * @@ -48,7 +48,7 @@ * \li pa_channel_map_init_auto() - Create a standard channel map for up to * six channels. * - * \section conv_sec Convenience functions + * \section conv_sec Convenience Functions * * The library contains a number of convenience functions for dealing with * channel maps: diff --git a/src/polyp/context.h b/src/polyp/context.h index 848308116..01c1b76a0 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -36,7 +36,7 @@ * It allows full access to all available functions. This also means that * it is rather complex and can take some time to fully master. * - * \section mainloop_sec Main loop abstraction + * \section mainloop_sec Main Loop Abstraction * * The API is based around an asynchronous event loop, or main loop, * abstraction. This abstraction contains three basic elements: @@ -63,7 +63,7 @@ * \ref mainloop-signal.h. These rely only on the main loop abstraction * and can therefore be used with any of the implementations. * - * \section refcnt_sec Reference counting + * \section refcnt_sec Reference Counting * * Almost all objects in polypaudio are reference counted. What that means * is that you rarely malloc() or free() any objects. Instead you increase diff --git a/src/polyp/def.h b/src/polyp/def.h index 432bd8ce1..80e3092b4 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -119,7 +119,7 @@ typedef enum pa_stream_flags { * ahead can be corrected * quickly, without the need to * wait. */ - PA_STREAM_AUTO_TIMING_UPDATE = 8 /** If set timing update requests + PA_STREAM_AUTO_TIMING_UPDATE = 8 /**< If set timing update requests * are issued periodically * automatically. Combined with * PA_STREAM_INTERPOLATE_TIMING diff --git a/src/polyp/glib-mainloop.h b/src/polyp/glib-mainloop.h index bc66409b8..ce885e135 100644 --- a/src/polyp/glib-mainloop.h +++ b/src/polyp/glib-mainloop.h @@ -27,7 +27,7 @@ #include #include -/** \page glib-mainloop GLIB main loop bindings +/** \page glib-mainloop GLIB Main Loop Bindings * * \section overv_sec Overview * diff --git a/src/polyp/introspect.h b/src/polyp/introspect.h index a8292ba1b..9a0edb795 100644 --- a/src/polyp/introspect.h +++ b/src/polyp/introspect.h @@ -30,7 +30,7 @@ #include #include -/** \page introspect Server query and control +/** \page introspect Server Query and Control * * \section overv_sec Overview * @@ -62,19 +62,19 @@ * duration of the callback. If they are required after the callback is * finished, a deep copy must be performed. * - * \subsection server_subsec Server information + * \subsection server_subsec Server Information * * The server can be queried about its name, the environment it's running on * and the currently active global defaults. Calling * pa_context_get_server_info() will get access to a pa_server_info structure * containing all of these. * - * \subsection memstat_subsec Memory usage + * \subsection memstat_subsec Memory Usage * * Statistics about memory usage can be fetched using pa_context_stat(), * giving a pa_stat_info structure. * - * \subsection sinksrc_subsec Sinks and sources + * \subsection sinksrc_subsec Sinks and Sources * * The server can have an arbitrary number of sinks and sources. Each sink * and source have both an index and a name associated with it. As such @@ -90,7 +90,7 @@ * All three method use the same callback and will provide a pa_sink_info or * pa_source_info structure. * - * \subsection siso_subsec Sink inputs and source outputs + * \subsection siso_subsec Sink Inputs and Source Outputs * * Sink inputs and source outputs are the representations of the client ends * of streams inside the server. I.e. they connect a client stream to one of @@ -119,13 +119,13 @@ * Note that this only retrieves information about the sample, not the sample * data itself. * - * \subsection module_subsec Modules + * \subsection module_subsec Driver Modules * - * Polypaudio modules are identified by index and are retrieved using either + * Polypaudio driver modules are identified by index and are retrieved using either * pa_context_get_module_info() or pa_context_get_module_info_list(). The * information structure is called pa_module_info. * - * \subsection autoload_subsec Autoload entries + * \subsection autoload_subsec Autoload Entries * * Modules can be autoloaded as a result of a client requesting a certain * sink or source. This mapping between sink/source names and modules can be @@ -147,7 +147,7 @@ * modified in different ways. Note that these changes will affect all * connected clients and not just the one issuing the request. * - * \subsection sinksrc_subsec Sinks and sources + * \subsection sinksrc_subsec Sinks and Sources * * The most common change one would want to do to sinks and sources is to * modify the volume of the audio. Identical to how sinks and sources can @@ -165,7 +165,7 @@ * \li By name - pa_context_set_sink_mute_by_name() / * pa_context_set_source_mute_by_name() * - * \subsection siso_subsec Sink inputs and source outputs + * \subsection siso_subsec Sink Inputs and Source Outputs * * If an application desires to modify the volume of just a single stream * (commonly one of its own streams), this can be done by setting the volume @@ -184,7 +184,7 @@ * Server modules can be remotely loaded and unloaded using * pa_context_load_module() and pa_context_unload_module(). * - * \subsection autoload_subsec Autoload entries + * \subsection autoload_subsec Autoload Entries * * New module autoloading rules can be added, and existing can be removed * using pa_context_add_autoload() and pa_context_remove_autoload_by_index() diff --git a/src/polyp/mainloop.h b/src/polyp/mainloop.h index 6fb2a96cd..fe2b4c5b4 100644 --- a/src/polyp/mainloop.h +++ b/src/polyp/mainloop.h @@ -27,7 +27,7 @@ PA_C_DECL_BEGIN -/** \page mainloop Mainloop +/** \page mainloop Main Loop * * \section overv_sec Overview * @@ -81,15 +81,13 @@ void pa_mainloop_free(pa_mainloop* m); /** Prepare for a single iteration of the main loop. Returns a negative value on error or exit request. timeout specifies a maximum timeout for the subsequent -poll, or -1 for blocking behaviour. Defer events are also dispatched when this -function is called. On success returns the number of source dispatched in this -iteration.*/ +poll, or -1 for blocking behaviour. .*/ int pa_mainloop_prepare(pa_mainloop *m, int timeout); /** Execute the previously prepared poll. Returns a negative value on error.*/ int pa_mainloop_poll(pa_mainloop *m); -/** Dispatch timeout and io events from the previously executed poll. Returns +/** Dispatch timeout, io and deferred events from the previously executed poll. Returns a negative value on error. On success returns the number of source dispatched. */ int pa_mainloop_dispatch(pa_mainloop *m); @@ -101,7 +99,7 @@ for pa_mainloop_prepare(), pa_mainloop_poll() and pa_mainloop_dispatch(). Returns a negative value on error or exit request. If block is nonzero, block for events if none are queued. Optionally return the return value as specified with the main loop's quit() routine in the integer variable retval points -to. On success returns the number of source dispatched in this iteration. */ +to. On success returns the number of sources dispatched in this iteration. */ int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval); /** Run unlimited iterations of the main loop object until the main loop's quit() routine is called. */ diff --git a/src/polyp/sample.h b/src/polyp/sample.h index 0706be5ae..4de84301a 100644 --- a/src/polyp/sample.h +++ b/src/polyp/sample.h @@ -28,14 +28,14 @@ #include -/** \page sample Sample format specifications +/** \page sample Sample Format Specifications * * \section overv_sec Overview * * Polypaudio is capable of handling a multitude of sample formats, rates * and channels, transparently converting and mixing them as needed. * - * \section format_sec Sample format + * \section format_sec Sample Format * * Polypaudio supports the following sample formats: * @@ -52,7 +52,7 @@ * The sample formats that are sensitive to endianness have convenience * macros for native endian (NE), and reverse endian (RE). * - * \section rate_sec Sample rates + * \section rate_sec Sample Rates * * Polypaudio supports any sample rate between 1 Hz and 4 GHz. There is no * point trying to exceed the sample rate of the output device though as the @@ -78,7 +78,7 @@ * \li pa_bytes_to_usec() - Calculate the time it would take to play a buffer * of a certain size. * - * \section util_sec Convenience functions + * \section util_sec Convenience Functions * * The library also contains a couple of other convenience functions: * diff --git a/src/polyp/scache.h b/src/polyp/scache.h index a6b312f55..91890673f 100644 --- a/src/polyp/scache.h +++ b/src/polyp/scache.h @@ -28,7 +28,7 @@ #include #include -/** \page scache Sample cache +/** \page scache Sample Cache * * \section overv_sec Overview * diff --git a/src/polyp/stream.h b/src/polyp/stream.h index 6367e8683..a832fc663 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -31,7 +31,7 @@ #include #include -/** \page streams Audio streams +/** \page streams Audio Streams * * \section overv_sec Overview * @@ -67,14 +67,16 @@ * pa_stream_set_state_callback(), and wait for the stream to enter an active * state. * - * \subsection bufattr_subsec Buffer attributes + * \subsection bufattr_subsec Buffer Attributes * - * Playback and record streams always have a server side buffer as part of the data flow. - * The size of this buffer strikes a compromise between low latency and - * sensitivity for buffer overflows/underruns. + * Playback and record streams always have a server side buffer as + * part of the data flow. The size of this buffer strikes a + * compromise between low latency and sensitivity for buffer + * overflows/underruns. * - * The buffer is described with a pa_buffer_attr structure which contains a - * number of field: + * The buffer metrics may be controlled by the application. They are + * described with a pa_buffer_attr structure which contains a number + * of fields: * * \li maxlength - The absolute maximum number of bytes that can be stored in * the buffer. If this value is exceeded then data will be @@ -82,16 +84,37 @@ * \li tlength - The target length of a playback buffer. The server will only * send requests for more data as long as the buffer has less * than this number of bytes of data. - * \li prebuf - Number of bytes that need to be in the buffer before playback - * will commence. Start of playback can be forced using - * pa_stream_trigger() even though the prebuffer size hasn't been - * reached. + * \li prebuf - Number of bytes that need to be in the buffer before + * playback will commence. Start of playback can be forced using + * pa_stream_trigger() even though the prebuffer size hasn't been + * reached. If a buffer underrun occurs, this prebuffering will be + * again enabled. If the playback shall never stop in case of a buffer + * underrun, this value should be set to 0. In that case the read + * index of the output buffer overtakes the write index, and hence the + * fill level of the buffer is negative. * \li minreq - Minimum free number of the bytes in the playback buffer before * the server will request more data. * \li fragsize - Maximum number of bytes that the server will push in one * chunk for record streams. * - * \section transfer_sec Transferring data + * The server side playback buffers are indexed by a write and a read + * index. The application writes to the write index and the sound + * device reads from the read index. The read index is increased + * monotonically, while the write index may be freely controlled by + * the application. Substracting the read index from the write index + * will give you the current fill level of the buffer. The read/write + * indexes are 64bit values and measured in bytes, they will never + * wrap. The current read/write index may be queried using + * pa_stream_get_timing_info() (see below for more information). In + * case of a buffer underrun the read index is equal or larger than + * the write index. Unless the prebuf value is 0, Polypaudio will + * temporarily pause playback in such a case, and wait until the + * buffer is filled up to prebuf bytes again. If prebuf is 0, the + * read index may be larger than the write index, in which case + * silence is played. If the application writes data to indexes lower + * than the read index, the data is immediately lost. + * + * \section transfer_sec Transferring Data * * Once the stream is up, data can start flowing between the client and the * server. Two different access models can be used to transfer the data: @@ -112,7 +135,7 @@ * record. Make sure you do not overflow the playback buffers as data will be * dropped. * - * \section bufctl_sec Buffer control + * \section bufctl_sec Buffer Control * * The transfer buffers can be controlled through a number of operations: * @@ -126,6 +149,23 @@ * \li pa_stream_flush() - Drop all data from the playback buffer and do not * wait for it to finish playing. * + * \section seek_modes Seeking in the Playback Buffer + * + * A client application may freely seek in the playback buffer. To + * accomplish that the pa_stream_write() function takes a seek mode + * and an offset argument. The seek mode is one of: + * + * \li PA_SEEK_RELATIVE - seek relative to the current write index + * \li PA_SEEK_ABSOLUTE - seek relative to the beginning of the playback buffer, (i.e. the first that was ever played in the stream) + * \li PA_SEEK_RELATIVE_ON_READ - seek relative to the current read index. Use this to write data to the output buffer that should be played as soon as possible + * \li PA_SEEK_RELATIVE_END - seek relative to the last byte ever written. + * + * If an application just wants to append some data to the output + * buffer, PA_SEEK_RELATIVE and an offset of 0 should be used. + * + * After a call to pa_stream_write() the write index will be left at + * the position right after the last byte of the written data. + * * \section latency_sec Latency * * A major problem with networked audio is the increased latency caused by @@ -134,8 +174,10 @@ * * To get the raw data needed to calculate latencies, call * pa_stream_get_timing_info(). This will give you a pa_timing_info - * structure that contains everything that is known about buffers, - * transport delays and the backend active in the server. + * structure that contains everything that is known about the server + * side buffer transport delays and the backend active in the + * server. (Besides other things it contains the write and read index + * values mentioned above.) * * This structure is updated every time a * pa_stream_update_timing_info() operation is executed. (i.e. before @@ -157,32 +199,38 @@ * you can call pa_stream_get_time() or pa_stream_get_latency(). The * former will return the current playback time of the hardware since * the stream has been started. The latter returns the time a sample - * that you write now takes to be played by the hardware. + * that you write now takes to be played by the hardware. These two + * functions base their calculations on the same data that is returned + * by pa_stream_get_timing_info(). Hence the same rules for keeping + * the timing data up-to-date apply here. In case the write or read + * index is corrupted, these two functions will fail with + * PA_ERR_NODATA set. * * Since updating the timing info structure usually requires a full - * round trip and some applications monitor the timing very often - * Polypaudio offers a timing interpolation system. If + * network round trip and some applications monitor the timing very + * often Polypaudio offers a timing interpolation system. If * PA_STREAM_INTERPOLATE_TIMING is passed when connecting the stream, * pa_stream_get_time() and pa_stream_get_latency() will try to * interpolate the current playback time/latency by estimating the * number of samples that have been played back by the hardware since * the last regular timing update. It is espcially useful to combine * this option with PA_STREAM_AUTO_TIMING_UPDATE, which will enable - * you to monitor the current playback time/latency very precisely - * without requiring a network round trip every time. + * you to monitor the current playback time/latency very precisely and + * very frequently without requiring a network round trip every time. * * \section flow_sec Overflow and underflow * - * Even with the best precautions, buffers will sometime over - or underflow. - * To handle this gracefully, the application can be notified when this - * happens. Callbacks are registered using pa_stream_set_overflow_callback() - * and pa_stream_set_underflow_callback(). + * Even with the best precautions, buffers will sometime over - or + * underflow. To handle this gracefully, the application can be + * notified when this happens. Callbacks are registered using + * pa_stream_set_overflow_callback() and + * pa_stream_set_underflow_callback(). * - * \section sync_streams Sychronizing Multiple Playback Streams. + * \section sync_streams Sychronizing Multiple Playback Streams * - * Polypaudio allows applications to fully synchronize multiple playback - * streams that are connected to the same output device. That means - * the streams will always be played back sample-by-sample + * Polypaudio allows applications to fully synchronize multiple + * playback streams that are connected to the same output device. That + * means the streams will always be played back sample-by-sample * synchronously. If stream operations like pa_stream_cork() are * issued on one of the synchronized streams, they are simultaneously * issued on the others. @@ -199,9 +247,6 @@ * synchronized streams continue playing and hence deviate you need to * pass a "prebuf" pa_buffer_attr of 0 when connecting it. * - * \section seek_modes Seeking in the Playback Buffer - * - * T.B.D * \section disc_sec Disconnecting * * When a stream has served is purpose it must be disconnected with @@ -297,7 +342,7 @@ int pa_stream_peek( const void **data /**< Pointer to pointer that will point to data */, size_t *length /**< The length of the data read */); -/** Remove the current fragment. It is invalid to do this without first +/** Remove the current fragment on record streams. It is invalid to do this without first * calling pa_stream_peek(). \since 0.8 */ int pa_stream_drop(pa_stream *p); diff --git a/src/polyp/subscribe.h b/src/polyp/subscribe.h index 75b4696fa..d8326e1ce 100644 --- a/src/polyp/subscribe.h +++ b/src/polyp/subscribe.h @@ -28,7 +28,7 @@ #include #include -/** \page subscribe Event subscription +/** \page subscribe Event Subscription * * \section overv_sec Overview * diff --git a/src/polyp/volume.h b/src/polyp/volume.h index a72069eb8..0da5f54fe 100644 --- a/src/polyp/volume.h +++ b/src/polyp/volume.h @@ -26,7 +26,7 @@ #include #include -/** \page volume Volume control +/** \page volume Volume Control * * \section overv_sec Overview * @@ -62,7 +62,7 @@ * PA_VOLUME_NORM (100%) and to refrain from any calculations with * them. * - * \section conv_sec Convenience functions + * \section conv_sec Convenience Functions * * To handle the pa_cvolume structure, the Polypaudio library provides a * number of convenienc functions: From 5639b7eb7f775738b89ba1af3a8d5ecdf646fb75 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 13:46:02 +0000 Subject: [PATCH 0605/1514] doc updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@698 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/todo b/doc/todo index 3613217c7..101871c5c 100644 --- a/doc/todo +++ b/doc/todo @@ -4,9 +4,6 @@ Test: - module-combine - module-tunnel -Fixes: -- correct API docs regarding timing work - Post 0.8: - alsa mmap driver - add radio module From df108afe352a4f0e8d67510f923878e954714c94 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 15:10:55 +0000 Subject: [PATCH 0606/1514] update documentation for release 0.8 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@699 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/FAQ.html.in | 3 +-- doc/Makefile.am | 2 +- doc/README.html.in | 65 ++++++++++++++++++++++++++++++--------------- doc/cli.html.in | 20 +++++++++----- doc/modules.html.in | 65 ++++++++++++++++++++++++++++++++++++++++----- doc/style.css | 15 +++-------- 6 files changed, 120 insertions(+), 50 deletions(-) diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in index 9cacfb4c3..0e7382178 100644 --- a/doc/FAQ.html.in +++ b/doc/FAQ.html.in @@ -128,7 +128,6 @@ bidilink unix-client:/tmp/polypaudio/cli

    BTW: Someone should package that great tool for Debian!

    -

    New: There's now a tool pacmd that automates sending SIGUSR2 to the daemon and running a bidilink like tool for you.

    @@ -152,6 +151,6 @@ bidilink unix-client:/tmp/polypaudio/cli
    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, September 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, April 2006
    $Id$
    diff --git a/doc/Makefile.am b/doc/Makefile.am index c68c00f56..a5884abda 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -16,7 +16,7 @@ # along with polypaudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -noinst_DATA = README.html cli.html modules.html daemon.html +noinst_DATA = README.html cli.html modules.html daemon.html FAQ.html EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in todo FAQ.html.in MAINTAINERCLEANFILES = README.html cli.html modules.html daemon.html FAQ.html diff --git a/doc/README.html.in b/doc/README.html.in index eb57fdb78..dbf854110 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -10,13 +10,13 @@

    polypaudio @PACKAGE_VERSION@

    -

    Copyright 2004 Lennart Poettering <@PACKAGE_BUGREPORT@>

    +

    Copyright 2004-2006 Lennart Poettering <@PACKAGE_BUGREPORT@> and Pierre Ossman

    • License
    • News
    • Overview
    • -
    • Status
    • +
    • Current Status
    • Documentation
    • Requirements
    • Installation
    • @@ -42,6 +42,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

      News

      +
      Thu Apr 13 2006:

      Version 0.8 released; +changes include: too many to count; many, many minor fixes.

      +
      Sun Nov 21 2004:

      Version 0.7 released; changes include: IPv6 support; PID file support; publish credentials @@ -92,13 +96,12 @@ href="@PACKAGE_URL@polypaudio-0.1.tar.gz">Version 0.1 released

      Overview

      -

      polypaudio is a sound server for Linux and other Unix like -operating systems. It is intended to be an improved drop-in +

      polypaudio is a networked sound server for Linux and other +Unix like operating systems. It is intended to be an improved drop-in replacement for the Enlightened Sound -Daemon (ESOUND). It is my ultimate ambition to get Polypaudio into -Gnome as a replacement for ESOUND. In -addition to the features ESOUND provides polypaudio has:

      +Daemon (ESOUND). In addition to the features ESOUND provides +polypaudio has:

      • Extensible plugin architecture (by loading dynamic loadable modules with dlopen())
      • @@ -110,9 +113,10 @@ addition to the features ESOUND provides polypaudio has:

      • Flexible, implicit sample type conversion and resampling
      • "Zero-Copy" architecture
      • Module autoloading
      • -
      • Very accurate latency measurement for playback and recordin.
      • +
      • Very accurate latency measurement for playback and recording.
      • May be used to combine multiple sound cards to one (with sample rate adjustment)
      • Client side latency interpolation
      • +
      • Ability to fully synchronize multiple playback streams

      Both the core and the client API are completely asynchronous making @@ -129,19 +133,25 @@ available. A simple main loop implementation is available as well.

    • module-oss: driver for Open Sound System audio sinks and sources.
    • module-oss-mmap: same as above, but uses mmap() access to the audio buffer. Not as compatible
    • module-alsa-sink, module-alsa-source: drivers for ALSA sinks and sources
    • +
    • module-solaris: drivers for Solaris audio sinks and sources
    • +
    • module-waveout: drivers for Microsoft Windows audio sinks and sources
    • module-pipe-sink, module-pipe-source: demonstration module providing UNIX fifos backed sinks/sources
    • module-combine: combine multiple sinks into one.
    • module-sine: a sine generate sink input.
    • module-x11-bell: play a sample from the sample cache on every X11 bell event.
    • module-x11-publish: store Polypaudio credentials in the X11 root window.
    • -
    • module-esound-protocol-tcp, module-esound-protocol-tcp6, module-esound-protocol-unix: ESOUND compatibility modules (for TCP/IPv6 resp. TCP/IPv6 resp. UNIX domain sockets)
    • -
    • module-native-protocol-tcp, module-native-protocol-tcp6, module-native-protocol-unix: Native polypaudio protocol (for TCP/IPv4 resp. TCP/IPv6 resp. UNIX domain sockets)
    • -
    • module-simple-protocol-tcp, module-simple-protocol-tcp6, module-simple-protocol-unix: Simplistic protocol for playback/capture for usage with tools like netcat (for TCP/IP resp. UNIX domain sockets)
    • -
    • module-cli-protocol-tcp, module-cli-protocol-tcp6, module-cli-protocol-unix, module-cli: Expose polypaudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
    • +
    • module-esound-protocol-tcp, module-esound-protocol-unix: ESOUND compatibility modules (for TCP/IP resp. UNIX domain sockets)
    • +
    • module-native-protocol-tcp, module-native-protocol-unix: Native polypaudio protocol (for TCP/IP resp. UNIX domain sockets)
    • +
    • module-simple-protocol-tcp, module-simple-protocol-unix: Simplistic protocol for playback/capture for usage with tools like netcat (for TCP/IP resp. UNIX domain sockets)
    • +
    • module-cli-protocol-tcp, module-cli-protocol-unix, module-cli: Expose polypaudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
    • module-tunnel-sink, module-tunnel-source: make sinks/sources from other hosts available locally.
    • module-match: adjust volume automatically for newly created playback streams based on a regular expression matching table.
    • module-null-sink: a clocked sink similar to /dev/null.
    • module-esound-sink: a sink for forwarding audio data to an ESOUND server.
    • +
    • module-detect: a module which automatically detects what sound hardware is available locally and which loads the required driver modules.
    • +
    • module-lirc: a module to control the volume of a sink with infrared remote controls supported by LIRC.
    • +
    • module-mmkbd-evdev: a module to control the volume of a sink with the special volume keys of a multimeda keyboard.
    • +
    • module-zeroconf-publish: a module to publish local sources/sinks using mDNS zeroconf.

    polypaudio is the successor of my previous, ill-fated @@ -165,7 +175,7 @@ href="http://xine.sf.net/">Xine (merged in Xine CVS). Drivers for PortAudio will be released shortly.

    -

    Status

    +

    Current Status

    Version @PACKAGE_VERSION@ is quite usable. It matches and supersedes ESOUND's feature set in nearly all areas.

    @@ -178,7 +188,11 @@ release to release. The client API's library version number is currently fixed t

    There is some preliminary documentation available: modules.html, cli.html, daemon.html, FAQ.html, .

    +href="daemon.html">daemon.html and FAQ.html.

    + +

    There is a Trac based Wiki for Polypaudio available.

    + +

    First Steps

    @@ -231,7 +245,7 @@ questions.

    Requirements

    -

    Currently, polypaudio is tested on Linux and FreeBSD only. It requires an OSS or ALSA compatible soundcard.

    +

    Currently, polypaudio is tested on Linux, FreeBSD, Solaris and Microsoft Windows. It requires an OSS, ALSA, Win32 or Solaris compatible soundcard.

    polypaudio was developed and tested on Debian GNU/Linux "testing" from November 2004, it should work on most other Linux @@ -239,11 +253,16 @@ distributions (and maybe Unix versions) since it uses GNU autoconf and GNU libtool for source code configuration and shared library management.

    -

    polypaudio needs libwrap, polypaudio needs Secret Rabbit Code (aka libsamplerate), libsndfile, alsa-lib and liboil.

    + +

    Optionally it can make use of libwrap, alsa-lib, libasyncns, +lirc, HOWL (or preferably the compatibility layer included in its superior replacement Avahi) and GLIB. (The latter is required for building the GLIB main loop integration module only.)

    @@ -271,18 +290,20 @@ compilation and make install (as root) for installation of

    The current release is @PACKAGE_VERSION@

    -

    Get polypaudio's development sources from the Subversion repository (viewcvs):

    +

    Get polypaudio's development sources from the Subversion repository (viewcvs):

    -
    svn checkout svn://seth.intheinter.net/polypaudio/trunk polypaudio
    +
    svn checkout svn://0pointer.de/polypaudio/trunk polypaudio

    If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

    -

    New! There is a general discussion mailing list for polypaudio available.

    +

    There is a general discussion mailing list for polypaudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

    -

    New! There is now a Polypaudio wiki (based on trac) available.

    +

    There is a Trac based Wiki for Polypaudio available.

    + +

    Please report bugs to our Trac ticket system.


    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, November 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, April 2006
    $Id$
    diff --git a/doc/cli.html.in b/doc/cli.html.in index 61d29e5af..0db96c366 100644 --- a/doc/cli.html.in +++ b/doc/cli.html.in @@ -68,13 +68,19 @@ returned by modules.

    Configuration Commands

    -

    set-sink-volume

    +

    set-sink-volume/set-source-volume

    -

    Set the volume of the specified sink. You may specify the sink either -by its index in the sink list or by its name. The volume should be an -integer value greater or equal than 0 (= muted). Volume 256 -(0x100) is normal volume, values greater than this amplify -the audio signal with clipping.

    +

    Set the volume of the specified sink or source. You may specify the sink/source either +by its index in the sink/source list or by its name. The volume should be an +integer value greater or equal than 0 (= muted). Volume 65536 +(0x10000) is normal volume, values greater than this amplify +the audio signal (with clipping).

    + +

    set-sink-mute/set-source-mute

    + +

    Mute or unmute the specified sink our source. You may specify the +sink/source either by its index or by its name. The mute value is +either 0 or 1.

    set-sink-input-volume

    @@ -209,6 +215,6 @@ play-file /usr/share/sounds/startup3.wav combined
    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, November 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, April 2006
    $Id$
    diff --git a/doc/modules.html.in b/doc/modules.html.in index a549396d0..64bc4bbcd 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -100,6 +100,24 @@ compatible as module-oss.

    This module accepts exactly the same arguments as module-oss.

    +

    module-solaris

    + +

    Provides a sink and source for the Solaris audio device.

    + +

    In addition to the general device driver options described above this module supports:

    + + + + + +
    record=Accepts a binary numerical value for enabling (resp. disabling) the recording on this device. (defaults: to 1)
    playback=Accepts a binary numerical value for enabling (resp. disabling) the playback on this device. (defaults: to 1)
    buffer_size=Record buffer size
    + +

    module-waveout

    + +

    Provides a sink and source for the Win32 audio device.

    + +

    This module supports all arguments thet module-oss supports except device=.

    +

    module-combine

    This combines two or more sinks into one. A new virtual sink is @@ -168,7 +186,7 @@ module see cli.html. -

    module-cli-protocol-{unix,tcp,tcp6}

    +

    module-cli-protocol-{unix,tcp}

    An implemenation of a simple command line based protocol for controlling the polypaudio daemon. If loaded, the user may @@ -182,7 +200,7 @@ service.

    This module exists in two versions: with the suffix -unix the service will listen on an UNIX domain socket in the local file system. With the suffix -tcp it will listen on a network -transparent TCP/IP socket.

    +transparent TCP/IP socket. (Both IPv6 and IPv4 - if available)

    This module supports the following options:

    @@ -191,10 +209,11 @@ transparent TCP/IP socket.

    loopback=(only for -tcp) Accepts a numerical binary value. If 1 the socket is bound to the loopback device, i.e. not publicly accessible. (defaults to 1) + listen=(only for -tcp) The IP address to listen on. If specified, supersedes the value specified in loopback= socket=(only for -unix) The UNIX socket name (defaults to /tmp/polypaudio/cli) -

    module-simple-protocol-{unix,tcp,tcp6}

    +

    module-simple-protocol-{unix,tcp}

    An implementation of a simple protocol which allows playback by using simple tools like netcat. Just connect to the listening @@ -231,13 +250,13 @@ about the two possible suffixes of this module.

    - +
    sink=, source=Specify the sink/source this service connects to
    public=If set to 0 not authentication is required to connect to the service
    auth-anonymous=If set to 1 no authentication is required to connect to the service
    cookie=Name of the cookie file for authentication purposes

    This implementation misses some features the original ESOUND has: e.g. there is no sample cache yet. However: XMMS works fine.

    -

    module-native-protocol-{unix,tcp,tcp6}

    +

    module-native-protocol-{unix,tcp}

    The native protocol of polypaudio.

    @@ -247,7 +266,8 @@ about the two possible suffixes of this module.

    In addition to the options supported by module-cli-protocol-*, this module supports:

    - + +
    public=If set to 0 not authentication is required to connect to the service
    auth-anonymous=If set to 1 no authentication is required to connect to the service
    auth-group=(only for -unix): members of the specified unix group may access the server without further auhentication.
    cookie=Name of the cookie file for authentication purposes
    @@ -320,7 +340,38 @@ already loaded protocol module is used.

    The volumes of all streams with titles starting with sample: are automatically set to 25. (FYI: All sample cache streams start with sample:)

    +

    module-detect

    + +

    Automatically detect the available sound hardware and load modules for it. Supports OSS, ALSA, Solaris and Win32 output drivers. + + + +
    just-one=If set to 1 the module will only try to load a single sink/source and than stop.
    + +

    module-zeroconf-publish

    + +

    Publish all local sinks/sources using mDNS Zeroconf.

    + +

    module-mmkbd-evdev

    + +

    Adjust the volume of a sink when the special multimedia buttons of modern keyboards are pressed.

    + + + + +
    device=Linux input device ("evdev", defaults to /dev/input/event0)
    sink=The sink to control
    + +

    module-lirc

    + +

    Adjust the volume of a sink when the volume buttons of an infrared remote control are pressed (through LIRC).

    + + + + + +
    config=The LIRC configuration file
    appname=The application name to pass to LIRC (defaults to polypaudio)
    sink=The sink to control
    +
    -
    Lennart Poettering <@PACKAGE_BUGREPORT@>, November 2004
    +
    Lennart Poettering <@PACKAGE_BUGREPORT@>, April 2006
    $Id$
    diff --git a/doc/style.css b/doc/style.css index a46592a27..a606c08ef 100644 --- a/doc/style.css +++ b/doc/style.css @@ -18,17 +18,10 @@ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -body { color: black; background-color: white; margin: 0.5cm; } +body { color: black; background-color: white; } a:link, a:visited { color: #900000; } -p { margin-left: 0.5cm; margin-right: 0.5cm; } -div.news-date { margin-left: 0.5cm; font-size: 80%; color: #4f0000; } -p.news-text { margin-left: 1cm; } -h1 { color: #00009F; } -h2 { color: #00009F; } -h3 { color: #00004F; margin-left: 0.5cm; } -ul { margin-left: .5cm; } -ol { margin-left: .5cm; } -pre { margin-left: .5cm; background-color: #f0f0f0; padding: 0.4cm;} -.grey { color: #afafaf; } +div.news-date { font-size: 80%; font-style: italic; } +pre { background-color: #f0f0f0; padding: 0.4cm; } +.grey { color: #8f8f8f; font-size: 80%; } table { margin-left: 1cm; border:1px solid lightgrey; padding: 0.2cm; } td { padding-left:10px; padding-right:10px; } From 1f7a008f4331bfe21e2de6f2ec9cab997f310465 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 17:32:10 +0000 Subject: [PATCH 0607/1514] add new configure option to enable preloading even on architectures that support dlopen(). Useful for debugging git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@700 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 6 ++++++ src/Makefile.am | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 7d7f8f73a..6511137e7 100644 --- a/configure.ac +++ b/configure.ac @@ -398,6 +398,12 @@ if test "x$PREOPEN_MODS" != "xall" ; then AC_SUBST(PREOPEN_MODS) fi +AC_ARG_ENABLE( + [force-preopen], + AC_HELP_STRING([--enable-force-preopen],[Preopen modules, even when dlopen() is supported.]), + [FORCE_PREOPEN=1], [FORCE_PREOPEN=0]) +AM_CONDITIONAL([FORCE_PREOPEN], [test "x$FORCE_PREOPEN" = "x1"]) + AC_CONFIG_FILES([ Makefile src/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index a65938efe..c5e4638bd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -109,7 +109,6 @@ polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) polypaudio_CPPFLAGS = $(AM_CPPFLAGS) polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \ $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) -polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f)) if PREOPEN_MODS PREOPEN_LIBS = $(PREOPEN_MODS) @@ -117,6 +116,12 @@ else PREOPEN_LIBS = $(modlib_LTLIBRARIES) endif +if FORCE_PREOPEN +polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlpreopen force $(foreach f,$(PREOPEN_LIBS),-dlpreopen $(f)) +else +polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f)) +endif + ################################### # Utility programs # ################################### From d4b22f3000316940a2229fb324989a81589d5aca Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 17:32:33 +0000 Subject: [PATCH 0608/1514] make --enable-force-preopen the default for SVN builds git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@701 fefdeb5f-60dc-0310-8127-8f9354f1896f --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index 31f3868ab..19acffb5e 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -59,7 +59,7 @@ else run_versioned automake "$VERSION" -a -c --foreign if test "x$NOCONFIGURE" = "x"; then - CFLAGS="-g -O0" ./configure --sysconfdir=/etc "$@" + CFLAGS="-g -O0" ./configure --sysconfdir=/etc --enable-force-preopen "$@" make clean fi fi From fe64b89fd846518efec535f1b567d3b2bfa9bd70 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 17:33:06 +0000 Subject: [PATCH 0609/1514] add code to allow polypaudio dump preloaded modules using "--dump-modules" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@702 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/dumpmodules.c | 51 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c index bf29a6816..c541c1681 100644 --- a/src/daemon/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -78,15 +78,41 @@ static void show_info(const char *name, const char *path, void (*info)(const cha } } +extern const lt_dlsymlist lt_preloaded_symbols[]; + +static int is_preloaded(const char *name) { + const lt_dlsymlist *l; + + for (l = lt_preloaded_symbols; l->name; l++) { + char buf[64], *e; + + if (l->address) + continue; + + snprintf(buf, sizeof(buf), "%s", l->name); + if ((e = strrchr(buf, '.'))) + *e = 0; + + if (!strcmp(name, buf)) + return 1; + } + + return 0; +} + static int callback(const char *path, lt_ptr data) { const char *e; pa_daemon_conf *c = (data); e = pa_path_get_filename(path); - if (strlen(e) > sizeof(PREFIX)-1 && !strncmp(e, PREFIX, sizeof(PREFIX)-1)) - show_info(e, path, c->log_level >= PA_LOG_INFO ? long_info : short_info); + if (strlen(e) <= sizeof(PREFIX)-1 || strncmp(e, PREFIX, sizeof(PREFIX)-1)) + return 0; + + if (is_preloaded(e)) + return 0; + show_info(e, path, c->log_level >= PA_LOG_INFO ? long_info : short_info); return 0; } @@ -95,6 +121,25 @@ void pa_dump_modules(pa_daemon_conf *c, int argc, char * const argv[]) { int i; for (i = 0; i < argc; i++) show_info(argv[i], NULL, long_info); - } else + } else { + const lt_dlsymlist *l; + + for (l = lt_preloaded_symbols; l->name; l++) { + char buf[64], *e; + + if (l->address) + continue; + + if (strlen(l->name) <= sizeof(PREFIX)-1 || strncmp(l->name, PREFIX, sizeof(PREFIX)-1)) + continue; + + snprintf(buf, sizeof(buf), "%s", l->name); + if ((e = strrchr(buf, '.'))) + *e = 0; + + show_info(buf, NULL, c->log_level >= PA_LOG_INFO ? long_info : short_info); + } + lt_dlforeachfile(NULL, callback, c); + } } From 9854cfc146b555bc0b28008e638d221fe2eecf43 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 17:53:43 +0000 Subject: [PATCH 0610/1514] hmm, nothing important git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@703 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/modinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polypcore/modinfo.c b/src/polypcore/modinfo.c index e090a42fd..39186ceb0 100644 --- a/src/polypcore/modinfo.c +++ b/src/polypcore/modinfo.c @@ -42,7 +42,7 @@ pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) { const char* (*func)(void); assert(dl); - i = pa_xmalloc0(sizeof(pa_modinfo)); + i = pa_xnew0(pa_modinfo, 1); if ((func = (const char* (*)(void)) lt_dlsym(dl, PA_SYMBOL_AUTHOR))) i->author = pa_xstrdup(func()); From c25c549c420fe450b259b2bdcb2e200bf5862147 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 18:20:05 +0000 Subject: [PATCH 0611/1514] fix latency calculations of module-combine git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@704 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-combine.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 28e854279..801539004 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -200,7 +200,9 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { struct userdata *u = s->userdata; assert(s && u && u->sink && u->master); - return pa_sink_input_get_latency(u->master->sink_input); + return + pa_sink_input_get_latency(u->master->sink_input) + + pa_sink_get_latency(u->master->sink_input->sink); } static struct output *output_new(struct userdata *u, pa_sink *sink, int resample_method) { From 010c049db267870138ac6cd0996d4fadaa401a7b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 18:27:35 +0000 Subject: [PATCH 0612/1514] include in-flux resampled chunk in latency calculations of playback streams git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@705 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-native.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 2aedd3909..3f1d5ca2b 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -1045,6 +1045,7 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ struct playback_stream *s; struct timeval tv, now; uint32_t idx; + pa_usec_t latency; assert(c && t); if (pa_tagstruct_getu32(t, &idx) < 0 || @@ -1060,7 +1061,12 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); reply = reply_new(tag); - pa_tagstruct_put_usec(reply, pa_sink_get_latency(s->sink_input->sink)); + + latency = pa_sink_get_latency(s->sink_input->sink); + if (s->sink_input->resampled_chunk.memblock) + latency += pa_bytes_to_usec(s->sink_input->resampled_chunk.length, &s->sink_input->sample_spec); + pa_tagstruct_put_usec(reply, latency); + pa_tagstruct_put_usec(reply, 0); pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq)); pa_tagstruct_put_timeval(reply, &tv); From d153fdadde1a7780496d0d49e4dcc5b9f2c74d6a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 18:28:37 +0000 Subject: [PATCH 0613/1514] remove yet another item from the todo list git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@706 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 101871c5c..e756a41b3 100644 --- a/doc/todo +++ b/doc/todo @@ -1,7 +1,6 @@ *** $Id$ *** Test: -- module-combine - module-tunnel Post 0.8: From 7e8d46e2bbb59876e18d84d701bf499938115e37 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 18:55:55 +0000 Subject: [PATCH 0614/1514] unbreak module-tunnel git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@707 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 8f5e66e6d..70cc950cc 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -240,7 +240,6 @@ static void send_bytes(struct userdata *u) { while (u->requested_bytes > 0) { pa_memchunk chunk; if (pa_sink_render(u->sink, u->requested_bytes, &chunk) < 0) { - if (u->requested_bytes >= DEFAULT_TLENGTH-DEFAULT_PREBUF) send_prebuf_request(u); @@ -285,9 +284,8 @@ static void command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED ui static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; - pa_usec_t buffer_usec, sink_usec, source_usec, transport_usec; + pa_usec_t sink_usec, source_usec, transport_usec; int playing; - uint32_t queue_length; int64_t write_index, read_index; struct timeval local, remote, now; assert(pd && u); @@ -301,17 +299,15 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G return; } - if (pa_tagstruct_get_usec(t, &buffer_usec) < 0 || - pa_tagstruct_get_usec(t, &sink_usec) < 0 || + if (pa_tagstruct_get_usec(t, &sink_usec) < 0 || pa_tagstruct_get_usec(t, &source_usec) < 0 || pa_tagstruct_get_boolean(t, &playing) < 0 || - pa_tagstruct_getu32(t, &queue_length) < 0 || pa_tagstruct_get_timeval(t, &local) < 0 || pa_tagstruct_get_timeval(t, &remote) < 0 || pa_tagstruct_gets64(t, &write_index) < 0 || pa_tagstruct_gets64(t, &read_index) < 0 || !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid reply."); + pa_log(__FILE__": invalid reply. (latency)"); die(u); return; } @@ -369,6 +365,7 @@ static void stream_get_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_ pa_usec_t latency; const char *name, *description, *monitor_source_name, *driver; int mute; + uint32_t flags; pa_sample_spec sample_spec; pa_channel_map channel_map; pa_cvolume volume; @@ -395,8 +392,9 @@ static void stream_get_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_ pa_tagstruct_gets(t, &monitor_source_name) < 0 || pa_tagstruct_get_usec(t, &latency) < 0 || pa_tagstruct_gets(t, &driver) < 0 || + pa_tagstruct_getu32(t, &flags) < 0 || !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid reply."); + pa_log(__FILE__": invalid reply. (get_info)"); die(u); return; } @@ -491,7 +489,7 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN pa_tagstruct_getu32(t, &u->requested_bytes) < 0 || #endif !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid reply."); + pa_log(__FILE__": invalid reply. (create stream)"); die(u); return; } From d981acee2ba121ba7e56ae89dd4e3e470c70fe80 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 18:56:28 +0000 Subject: [PATCH 0615/1514] remove yet another item from the todo list! This means we are now read for 0.8! git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@708 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/todo b/doc/todo index e756a41b3..4a84054f0 100644 --- a/doc/todo +++ b/doc/todo @@ -1,8 +1,5 @@ *** $Id$ *** -Test: -- module-tunnel - Post 0.8: - alsa mmap driver - add radio module From c383a4c1146edb17f8c55c01eaf32c2d83deac09 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 19:07:12 +0000 Subject: [PATCH 0616/1514] * add a link to Cendio to the README git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@709 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/README.html.in b/doc/README.html.in index dbf854110..66c446277 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -97,7 +97,7 @@ href="@PACKAGE_URL@polypaudio-0.1.tar.gz">Version 0.1 released

    Overview

    polypaudio is a networked sound server for Linux and other -Unix like operating systems. It is intended to be an improved drop-in +Unix like operating systems and Microsoft Windows. It is intended to be an improved drop-in replacement for the Enlightened Sound Daemon (ESOUND). In addition to the features ESOUND provides @@ -284,6 +284,8 @@ compilation and make install (as root) for installation of

    Joe Marcus Clarke for porting Polypaudio to FreeBSD

    +

    Cendio AB for paying for Pierre's work on Polypaudio

    +

    Download

    The newest release is always available from @PACKAGE_URL@

    From 9539dc4db483f31a33da7c3ab5b3b1f1a56e1bca Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Apr 2006 19:31:02 +0000 Subject: [PATCH 0617/1514] minor doc updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@710 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 2 -- doc/modules.html.in | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index 66c446277..3847a9e85 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -192,8 +192,6 @@ href="daemon.html">daemon.html and FAQ.html<

    There is a Trac based Wiki for Polypaudio available.

    -

    -

    First Steps

    Simply start the polypaudio daemon with the argument -nC

    diff --git a/doc/modules.html.in b/doc/modules.html.in index 64bc4bbcd..67f0e1723 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -275,6 +275,14 @@ about the two possible suffixes of this module.

    This is used internally when auto spawning a new daemon. Don't use it directly.

    +

    module-http-protocol-tcp

    + +

    A proof-of-concept HTTP module, which can be used to introspect +the current status of the polypaudio daemon using HTTP. Just load this +module and point your browser to http://localhost:4714/. This module takes the same arguments +as module-cli-protocol-tcp.

    +

    Miscellaneous

    module-x11-bell

    From 86ad60185ae90520269d384d90569d2402c25dd1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Apr 2006 23:46:32 +0000 Subject: [PATCH 0618/1514] minor beautification git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@711 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/source-output.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polypcore/source-output.h b/src/polypcore/source-output.h index 98f6ab0c0..1c6120522 100644 --- a/src/polypcore/source-output.h +++ b/src/polypcore/source-output.h @@ -55,7 +55,7 @@ struct pa_source_output { void (*push)(pa_source_output *o, const pa_memchunk *chunk); void (*kill)(pa_source_output* o); - pa_usec_t (*get_latency) (pa_source_output *i); + pa_usec_t (*get_latency) (pa_source_output *o); pa_resampler* resampler; From 9522b4484206ef3a99fb5586831a27fdfea0c373 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Apr 2006 23:47:33 +0000 Subject: [PATCH 0619/1514] add an RTP sender module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@712 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/Makefile | 13 + src/modules/rtp/module-rtp-monitor.c | 340 ++ src/modules/rtp/rfc2327.txt | 2355 +++++++++++ src/modules/rtp/rfc2974.txt | 1011 +++++ src/modules/rtp/rfc3550.txt | 5827 ++++++++++++++++++++++++++ src/modules/rtp/rfc3551.txt | 2467 +++++++++++ src/modules/rtp/rtp.c | 193 + src/modules/rtp/rtp.h | 51 + src/modules/rtp/sap.c | 107 + src/modules/rtp/sap.h | 43 + src/modules/rtp/sdp.c | 87 + src/modules/rtp/sdp.h | 33 + 12 files changed, 12527 insertions(+) create mode 100644 src/modules/rtp/Makefile create mode 100644 src/modules/rtp/module-rtp-monitor.c create mode 100644 src/modules/rtp/rfc2327.txt create mode 100644 src/modules/rtp/rfc2974.txt create mode 100644 src/modules/rtp/rfc3550.txt create mode 100644 src/modules/rtp/rfc3551.txt create mode 100644 src/modules/rtp/rtp.c create mode 100644 src/modules/rtp/rtp.h create mode 100644 src/modules/rtp/sap.c create mode 100644 src/modules/rtp/sap.h create mode 100644 src/modules/rtp/sdp.c create mode 100644 src/modules/rtp/sdp.h diff --git a/src/modules/rtp/Makefile b/src/modules/rtp/Makefile new file mode 100644 index 000000000..316beb72d --- /dev/null +++ b/src/modules/rtp/Makefile @@ -0,0 +1,13 @@ +# This is a dirty trick just to ease compilation with emacs +# +# This file is not intended to be distributed or anything +# +# So: don't touch it, even better ignore it! + +all: + $(MAKE) -C ../.. + +clean: + $(MAKE) -C ../.. clean + +.PHONY: all clean diff --git a/src/modules/rtp/module-rtp-monitor.c b/src/modules/rtp/module-rtp-monitor.c new file mode 100644 index 000000000..663320937 --- /dev/null +++ b/src/modules/rtp/module-rtp-monitor.c @@ -0,0 +1,340 @@ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-rtp-monitor-symdef.h" + +#include "rtp.h" +#include "sdp.h" +#include "sap.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Read data from source and send it to the network via RTP") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE( + "source= " + "format= " + "channels= " + "rate= " + "destinaton= " + "port= " + "mtu= " +) + +#define DEFAULT_PORT 5666 +#define SAP_PORT 9875 +#define DEFAULT_DESTINATION "224.0.0.252" +#define MEMBLOCKQ_MAXLENGTH (1024*170) +#define DEFAULT_MTU 1024 +#define SAP_INTERVAL 5000000 + +static const char* const valid_modargs[] = { + "source", + "format", + "channels", + "rate", + "destination", + "port", + NULL +}; + +struct userdata { + pa_module *module; + pa_core *core; + + pa_source_output *source_output; + pa_memblockq *memblockq; + + pa_rtp_context rtp_context; + pa_sap_context sap_context; + size_t mtu; + + pa_time_event *sap_event; +}; + +static void source_output_push(pa_source_output *o, const pa_memchunk *chunk) { + struct userdata *u; + assert(o); + u = o->userdata; + + if (pa_memblockq_push(u->memblockq, chunk) < 0) { + pa_log(__FILE__": Failed to push chunk into memblockq."); + return; + } + + pa_rtp_send(&u->rtp_context, u->mtu, u->memblockq); +} + +static void source_output_kill(pa_source_output* o) { + struct userdata *u; + assert(o); + u = o->userdata; + + pa_module_unload_request(u->module); + + pa_source_output_disconnect(u->source_output); + pa_source_output_unref(u->source_output); + u->source_output = NULL; +} + +static pa_usec_t source_output_get_latency (pa_source_output *o) { + struct userdata *u; + assert(o); + u = o->userdata; + + return pa_bytes_to_usec(pa_memblockq_get_length(u->memblockq), &o->sample_spec); +} + +static void sap_event(pa_mainloop_api *m, pa_time_event *t, const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + struct timeval next; + + assert(m); + assert(t); + assert(tv); + assert(u); + + pa_sap_send(&u->sap_context, 0); + + pa_log("SAP update"); + pa_gettimeofday(&next); + pa_timeval_add(&next, SAP_INTERVAL); + m->time_restart(t, &next); +} + +int pa__init(pa_core *c, pa_module*m) { + struct userdata *u; + pa_modargs *ma = NULL; + const char *dest; + uint32_t port = DEFAULT_PORT, mtu; + int af, fd = -1, sap_fd = -1; + pa_source *s; + pa_sample_spec ss; + pa_channel_map cm; + struct sockaddr_in sa4, sap_sa4; + struct sockaddr_in6 sa6, sap_sa6; + struct sockaddr_storage sa_dst; + pa_source_output *o = NULL; + uint8_t payload; + char *p; + int r; + socklen_t k; + struct timeval tv; + + assert(c); + assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments"); + goto fail; + } + + if (!(s = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source", NULL), PA_NAMEREG_SOURCE, 1))) { + pa_log(__FILE__": source does not exist."); + goto fail; + } + + ss = s->sample_spec; + pa_rtp_sample_spec_fixup(&ss); + cm = s->channel_map; + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + pa_log(__FILE__": failed to parse sample specification"); + goto fail; + } + + if (!pa_rtp_sample_spec_valid(&ss)) { + pa_log(__FILE__": specified sample type not compatible with RTP"); + goto fail; + } + + if (ss.channels != cm.channels) + pa_channel_map_init_auto(&cm, ss.channels); + + payload = pa_rtp_payload_type(&ss); + + mtu = (DEFAULT_MTU/pa_frame_size(&ss))*pa_frame_size(&ss); + + if (pa_modargs_get_value_u32(ma, "mtu", &mtu) < 0 || mtu < 1 || mtu % pa_frame_size(&ss) != 0) { + pa_log(__FILE__": invalid mtu."); + goto fail; + } + + if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { + pa_log(__FILE__": port= expects a numerical argument between 1 and 65535."); + goto fail; + } + + if ((dest = pa_modargs_get_value(ma, "destination", DEFAULT_DESTINATION))) { + if (inet_pton(AF_INET6, dest, &sa6.sin6_addr) > 0) { + sa6.sin6_family = af = AF_INET6; + sa6.sin6_port = htons(port); + sap_sa6 = sa6; + sap_sa6.sin6_port = htons(SAP_PORT); + } else if (inet_pton(AF_INET, dest, &sa4.sin_addr) > 0) { + sa4.sin_family = af = AF_INET; + sa4.sin_port = htons(port); + sap_sa4 = sa4; + sap_sa4.sin_port = htons(SAP_PORT); + } else { + pa_log(__FILE__": invalid destination '%s'", dest); + goto fail; + } + } + + if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) { + pa_log(__FILE__": socket() failed: %s", strerror(errno)); + goto fail; + } + + if (connect(fd, af == AF_INET ? (struct sockaddr*) &sa4 : (struct sockaddr*) &sa6, af == AF_INET ? sizeof(sa4) : sizeof(sa6)) < 0) { + pa_log(__FILE__": connect() failed: %s", strerror(errno)); + goto fail; + } + + if ((sap_fd = socket(af, SOCK_DGRAM, 0)) < 0) { + pa_log(__FILE__": socket() failed: %s", strerror(errno)); + goto fail; + } + + if (connect(sap_fd, af == AF_INET ? (struct sockaddr*) &sap_sa4 : (struct sockaddr*) &sap_sa6, af == AF_INET ? sizeof(sap_sa4) : sizeof(sap_sa6)) < 0) { + pa_log(__FILE__": connect() failed: %s", strerror(errno)); + goto fail; + } + + if (!(o = pa_source_output_new(s, __FILE__, "RTP Monitor Stream", &ss, &cm, PA_RESAMPLER_INVALID))) { + pa_log(__FILE__": failed to create source output."); + goto fail; + } + + o->push = source_output_push; + o->kill = source_output_kill; + o->get_latency = source_output_get_latency; + o->owner = m; + + u = pa_xnew(struct userdata, 1); + m->userdata = u; + o->userdata = u; + + u->module = m; + u->core = c; + u->source_output = o; + + u->memblockq = pa_memblockq_new( + 0, + MEMBLOCKQ_MAXLENGTH, + MEMBLOCKQ_MAXLENGTH, + pa_frame_size(&ss), + 1, + 0, + NULL, + c->memblock_stat); + + u->mtu = mtu; + + k = sizeof(sa_dst); + r = getsockname(fd, (struct sockaddr*) &sa_dst, &k); + assert(r >= 0); + + p = pa_sdp_build(af, + af == AF_INET ? (void*) &((struct sockaddr_in*) &sa_dst)->sin_addr : (void*) &((struct sockaddr_in6*) &sa_dst)->sin6_addr, + af == AF_INET ? (void*) &sa4.sin_addr : (void*) &sa6.sin6_addr, + "Polypaudio RTP Stream", port, payload, &ss); + + pa_rtp_context_init_send(&u->rtp_context, fd, 0, payload); + pa_sap_context_init_send(&u->sap_context, sap_fd, p); + + pa_log_info("RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence); + pa_log_info("SDP-Data:\n%s\nEOF", p); + + pa_sap_send(&u->sap_context, 0); + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, SAP_INTERVAL); + u->sap_event = c->mainloop->time_new(c->mainloop, &tv, sap_event, u); + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + if (fd >= 0) + close(fd); + + if (sap_fd >= 0) + close(sap_fd); + + if (o) { + pa_source_output_disconnect(o); + pa_source_output_unref(o); + } + + return -1; +} + +void pa__done(pa_core *c, pa_module*m) { + struct userdata *u; + assert(c); + assert(m); + + if (!(u = m->userdata)) + return; + + c->mainloop->time_free(u->sap_event); + + if (u->source_output) { + pa_source_output_disconnect(u->source_output); + pa_source_output_unref(u->source_output); + } + + pa_rtp_context_destroy(&u->rtp_context); + + pa_sap_send(&u->sap_context, 1); + pa_sap_context_destroy(&u->sap_context); + + pa_memblockq_free(u->memblockq); + + pa_xfree(u); +} diff --git a/src/modules/rtp/rfc2327.txt b/src/modules/rtp/rfc2327.txt new file mode 100644 index 000000000..ce77de612 --- /dev/null +++ b/src/modules/rtp/rfc2327.txt @@ -0,0 +1,2355 @@ + + + + + + +Network Working Group M. Handley +Request for Comments: 2327 V. Jacobson +Category: Standards Track ISI/LBNL + April 1998 + + + SDP: Session Description Protocol + +Status of this Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (1998). All Rights Reserved. + +Abstract + + This document defines the Session Description Protocol, SDP. SDP is + intended for describing multimedia sessions for the purposes of + session announcement, session invitation, and other forms of + multimedia session initiation. + + This document is a product of the Multiparty Multimedia Session + Control (MMUSIC) working group of the Internet Engineering Task + Force. Comments are solicited and should be addressed to the working + group's mailing list at confctrl@isi.edu and/or the authors. + +1. Introduction + + On the Internet multicast backbone (Mbone), a session directory tool + is used to advertise multimedia conferences and communicate the + conference addresses and conference tool-specific information + necessary for participation. This document defines a session + description protocol for this purpose, and for general real-time + multimedia session description purposes. This memo does not describe + multicast address allocation or the distribution of SDP messages in + detail. These are described in accompanying memos. SDP is not + intended for negotiation of media encodings. + + + + + + + + +Handley & Jacobson Standards Track [Page 1] + +RFC 2327 SDP April 1998 + + +2. Background + + The Mbone is the part of the internet that supports IP multicast, and + thus permits efficient many-to-many communication. It is used + extensively for multimedia conferencing. Such conferences usually + have the property that tight coordination of conference membership is + not necessary; to receive a conference, a user at an Mbone site only + has to know the conference's multicast group address and the UDP + ports for the conference data streams. + + Session directories assist the advertisement of conference sessions + and communicate the relevant conference setup information to + prospective participants. SDP is designed to convey such information + to recipients. SDP is purely a format for session description - it + does not incorporate a transport protocol, and is intended to use + different transport protocols as appropriate including the Session + Announcement Protocol [4], Session Initiation Protocol [11], Real- + Time Streaming Protocol [12], electronic mail using the MIME + extensions, and the Hypertext Transport Protocol. + + SDP is intended to be general purpose so that it can be used for a + wider range of network environments and applications than just + multicast session directories. However, it is not intended to + support negotiation of session content or media encodings - this is + viewed as outside the scope of session description. + +3. Glossary of Terms + + The following terms are used in this document, and have specific + meaning within the context of this document. + + Conference + A multimedia conference is a set of two or more communicating users + along with the software they are using to communicate. + + Session + A multimedia session is a set of multimedia senders and receivers + and the data streams flowing from senders to receivers. A + multimedia conference is an example of a multimedia session. + + Session Advertisement + See session announcement. + + Session Announcement + A session announcement is a mechanism by which a session + description is conveyed to users in a proactive fashion, i.e., the + session description was not explicitly requested by the user. + + + + +Handley & Jacobson Standards Track [Page 2] + +RFC 2327 SDP April 1998 + + + Session Description + A well defined format for conveying sufficient information to + discover and participate in a multimedia session. + +3.1. Terminology + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119. + +4. SDP Usage + +4.1. Multicast Announcements + + SDP is a session description protocol for multimedia sessions. A + common mode of usage is for a client to announce a conference session + by periodically multicasting an announcement packet to a well known + multicast address and port using the Session Announcement Protocol + (SAP). + + SAP packets are UDP packets with the following format: + + |--------------------| + | SAP header | + |--------------------| + | text payload | + |////////// + + + The header is the Session Announcement Protocol header. SAP is + described in more detail in a companion memo [4] + + The text payload is an SDP session description, as described in this + memo. The text payload should be no greater than 1 Kbyte in length. + If announced by SAP, only one session announcement is permitted in a + single packet. + +4.2. Email and WWW Announcements + + Alternative means of conveying session descriptions include + electronic mail and the World Wide Web. For both email and WWW + distribution, the use of the MIME content type "application/sdp" + should be used. This enables the automatic launching of applications + for participation in the session from the WWW client or mail reader + in a standard manner. + + + + + + +Handley & Jacobson Standards Track [Page 3] + +RFC 2327 SDP April 1998 + + + Note that announcements of multicast sessions made only via email or + the World Wide Web (WWW) do not have the property that the receiver + of a session announcement can necessarily receive the session because + the multicast sessions may be restricted in scope, and access to the + WWW server or reception of email is possible outside this scope. SAP + announcements do not suffer from this mismatch. + +5. Requirements and Recommendations + + The purpose of SDP is to convey information about media streams in + multimedia sessions to allow the recipients of a session description + to participate in the session. SDP is primarily intended for use in + an internetwork, although it is sufficiently general that it can + describe conferences in other network environments. + + A multimedia session, for these purposes, is defined as a set of + media streams that exist for some duration of time. Media streams + can be many-to-many. The times during which the session is active + need not be continuous. + + Thus far, multicast based sessions on the Internet have differed from + many other forms of conferencing in that anyone receiving the traffic + can join the session (unless the session traffic is encrypted). In + such an environment, SDP serves two primary purposes. It is a means + to communicate the existence of a session, and is a means to convey + sufficient information to enable joining and participating in the + session. In a unicast environment, only the latter purpose is likely + to be relevant. + + Thus SDP includes: + + o Session name and purpose + + o Time(s) the session is active + + o The media comprising the session + + o Information to receive those media (addresses, ports, formats and + so on) + + As resources necessary to participate in a session may be limited, + some additional information may also be desirable: + + o Information about the bandwidth to be used by the conference + + o Contact information for the person responsible for the session + + + + + +Handley & Jacobson Standards Track [Page 4] + +RFC 2327 SDP April 1998 + + + In general, SDP must convey sufficient information to be able to join + a session (with the possible exception of encryption keys) and to + announce the resources to be used to non-participants that may need + to know. + +5.1. Media Information + + SDP includes: + + o The type of media (video, audio, etc) + + o The transport protocol (RTP/UDP/IP, H.320, etc) + + o The format of the media (H.261 video, MPEG video, etc) + + For an IP multicast session, the following are also conveyed: + + o Multicast address for media + + o Transport Port for media + + This address and port are the destination address and destination + port of the multicast stream, whether being sent, received, or both. + + For an IP unicast session, the following are conveyed: + + o Remote address for media + + o Transport port for contact address + + The semantics of this address and port depend on the media and + transport protocol defined. By default, this is the remote address + and remote port to which data is sent, and the remote address and + local port on which to receive data. However, some media may define + to use these to establish a control channel for the actual media + flow. + +5.2. Timing Information + + Sessions may either be bounded or unbounded in time. Whether or not + they are bounded, they may be only active at specific times. + + SDP can convey: + + o An arbitrary list of start and stop times bounding the session + + o For each bound, repeat times such as "every Wednesday at 10am for + one hour" + + + +Handley & Jacobson Standards Track [Page 5] + +RFC 2327 SDP April 1998 + + + This timing information is globally consistent, irrespective of local + time zone or daylight saving time. + +5.3. Private Sessions + + It is possible to create both public sessions and private sessions. + Private sessions will typically be conveyed by encrypting the session + description to distribute it. The details of how encryption is + performed are dependent on the mechanism used to convey SDP - see [4] + for how this is done for session announcements. + + If a session announcement is private it is possible to use that + private announcement to convey encryption keys necessary to decode + each of the media in a conference, including enough information to + know which encryption scheme is used for each media. + +5.4. Obtaining Further Information about a Session + + A session description should convey enough information to decide + whether or not to participate in a session. SDP may include + additional pointers in the form of Universal Resources Identifiers + (URIs) for more information about the session. + +5.5. Categorisation + + When many session descriptions are being distributed by SAP or any + other advertisement mechanism, it may be desirable to filter + announcements that are of interest from those that are not. SDP + supports a categorisation mechanism for sessions that is capable of + being automated. + +5.6. Internationalization + + The SDP specification recommends the use of the ISO 10646 character + sets in the UTF-8 encoding (RFC 2044) to allow many different + languages to be represented. However, to assist in compact + representations, SDP also allows other character sets such as ISO + 8859-1 to be used when desired. Internationalization only applies to + free-text fields (session name and background information), and not + to SDP as a whole. + +6. SDP Specification + + SDP session descriptions are entirely textual using the ISO 10646 + character set in UTF-8 encoding. SDP field names and attributes names + use only the US-ASCII subset of UTF-8, but textual fields and + attribute values may use the full ISO 10646 character set. The + textual form, as opposed to a binary encoding such as ASN/1 or XDR, + + + +Handley & Jacobson Standards Track [Page 6] + +RFC 2327 SDP April 1998 + + + was chosen to enhance portability, to enable a variety of transports + to be used (e.g, session description in a MIME email message) and to + allow flexible, text-based toolkits (e.g., Tcl/Tk ) to be used to + generate and to process session descriptions. However, since the + total bandwidth allocated to all SAP announcements is strictly + limited, the encoding is deliberately compact. Also, since + announcements may be transported via very unreliable means (e.g., + email) or damaged by an intermediate caching server, the encoding was + designed with strict order and formatting rules so that most errors + would result in malformed announcements which could be detected + easily and discarded. This also allows rapid discarding of encrypted + announcements for which a receiver does not have the correct key. + + An SDP session description consists of a number of lines of text of + the form = is always exactly one character and is + case-significant. is a structured text string whose format + depends on . It also will be case-significant unless a + specific field defines otherwise. Whitespace is not permitted either + side of the `=' sign. In general is either a number of fields + delimited by a single space character or a free format string. + + A session description consists of a session-level description + (details that apply to the whole session and all media streams) and + optionally several media-level descriptions (details that apply onto + to a single media stream). + + An announcement consists of a session-level section followed by zero + or more media-level sections. The session-level part starts with a + `v=' line and continues to the first media-level section. The media + description starts with an `m=' line and continues to the next media + description or end of the whole session description. In general, + session-level values are the default for all media unless overridden + by an equivalent media-level value. + + When SDP is conveyed by SAP, only one session description is allowed + per packet. When SDP is conveyed by other means, many SDP session + descriptions may be concatenated together (the `v=' line indicating + the start of a session description terminates the previous + description). Some lines in each description are required and some + are optional but all must appear in exactly the order given here (the + fixed order greatly enhances error detection and allows for a simple + parser). Optional items are marked with a `*'. + +Session description + v= (protocol version) + o= (owner/creator and session identifier). + s= (session name) + i=* (session information) + + + +Handley & Jacobson Standards Track [Page 7] + +RFC 2327 SDP April 1998 + + + u=* (URI of description) + e=* (email address) + p=* (phone number) + c=* (connection information - not required if included in all media) + b=* (bandwidth information) + One or more time descriptions (see below) + z=* (time zone adjustments) + k=* (encryption key) + a=* (zero or more session attribute lines) + Zero or more media descriptions (see below) + +Time description + t= (time the session is active) + r=* (zero or more repeat times) + +Media description + m= (media name and transport address) + i=* (media title) + c=* (connection information - optional if included at session-level) + b=* (bandwidth information) + k=* (encryption key) + a=* (zero or more media attribute lines) + + The set of `type' letters is deliberately small and not intended to + be extensible -- SDP parsers must completely ignore any announcement + that contains a `type' letter that it does not understand. The + `attribute' mechanism ("a=" described below) is the primary means for + extending SDP and tailoring it to particular applications or media. + Some attributes (the ones listed in this document) have a defined + meaning but others may be added on an application-, media- or + session-specific basis. A session directory must ignore any + attribute it doesn't understand. + + The connection (`c=') and attribute (`a=') information in the + session-level section applies to all the media of that session unless + overridden by connection information or an attribute of the same name + in the media description. For instance, in the example below, each + media behaves as if it were given a `recvonly' attribute. + + An example SDP description is: + + v=0 + o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4 + s=SDP Seminar + i=A Seminar on the session description protocol + u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps + e=mjh@isi.edu (Mark Handley) + c=IN IP4 224.2.17.12/127 + + + +Handley & Jacobson Standards Track [Page 8] + +RFC 2327 SDP April 1998 + + + t=2873397496 2873404696 + a=recvonly + m=audio 49170 RTP/AVP 0 + m=video 51372 RTP/AVP 31 + m=application 32416 udp wb + a=orient:portrait + + Text records such as the session name and information are bytes + strings which may contain any byte with the exceptions of 0x00 (Nul), + 0x0a (ASCII newline) and 0x0d (ASCII carriage return). The sequence + CRLF (0x0d0a) is used to end a record, although parsers should be + tolerant and also accept records terminated with a single newline + character. By default these byte strings contain ISO-10646 + characters in UTF-8 encoding, but this default may be changed using + the `charset' attribute. + + Protocol Version + + v=0 + + The "v=" field gives the version of the Session Description Protocol. + There is no minor version number. + + Origin + + o=
    +
    + + The "o=" field gives the originator of the session (their username + and the address of the user's host) plus a session id and session + version number. + + is the user's login on the originating host, or it is "-" + if the originating host does not support the concept of user ids. + must not contain spaces. is a numeric string + such that the tuple of , , , +
    and
    form a globally unique identifier for + the session. + + The method of allocation is up to the creating tool, but + it has been suggested that a Network Time Protocol (NTP) timestamp be + used to ensure uniqueness [1]. + + is a version number for this announcement. It is needed + for proxy announcements to detect which of several announcements for + the same session is the most recent. Again its usage is up to the + + + + + +Handley & Jacobson Standards Track [Page 9] + +RFC 2327 SDP April 1998 + + + creating tool, so long as is increased when a modification + is made to the session data. Again, it is recommended (but not + mandatory) that an NTP timestamp is used. + + is a text string giving the type of network. + Initially "IN" is defined to have the meaning "Internet".
    is a text string giving the type of the address that follows. + Initially "IP4" and "IP6" are defined.
    is the globally + unique address of the machine from which the session was created. + For an address type of IP4, this is either the fully-qualified domain + name of the machine, or the dotted-decimal representation of the IP + version 4 address of the machine. For an address type of IP6, this + is either the fully-qualified domain name of the machine, or the + compressed textual representation of the IP version 6 address of the + machine. For both IP4 and IP6, the fully-qualified domain name is + the form that SHOULD be given unless this is unavailable, in which + case the globally unique address may be substituted. A local IP + address MUST NOT be used in any context where the SDP description + might leave the scope in which the address is meaningful. + + In general, the "o=" field serves as a globally unique identifier for + this version of this session description, and the subfields excepting + the version taken together identify the session irrespective of any + modifications. + + Session Name + + s= + + The "s=" field is the session name. There must be one and only one + "s=" field per session description, and it must contain ISO 10646 + characters (but see also the `charset' attribute below). + + Session and Media Information + + i= + + The "i=" field is information about the session. There may be at + most one session-level "i=" field per session description, and at + most one "i=" field per media. Although it may be omitted, this is + discouraged for session announcements, and user interfaces for + composing sessions should require text to be entered. If it is + present it must contain ISO 10646 characters (but see also the + `charset' attribute below). + + A single "i=" field can also be used for each media definition. In + media definitions, "i=" fields are primarily intended for labeling + media streams. As such, they are most likely to be useful when a + + + +Handley & Jacobson Standards Track [Page 10] + +RFC 2327 SDP April 1998 + + + single session has more than one distinct media stream of the same + media type. An example would be two different whiteboards, one for + slides and one for feedback and questions. + + URI + + u= + + o A URI is a Universal Resource Identifier as used by WWW clients + + o The URI should be a pointer to additional information about the + conference + + o This field is optional, but if it is present it should be specified + before the first media field + + o No more than one URI field is allowed per session description + + + Email Address and Phone Number + + e= + p= + + o These specify contact information for the person responsible for + the conference. This is not necessarily the same person that + created the conference announcement. + + o Either an email field or a phone field must be specified. + Additional email and phone fields are allowed. + + o If these are present, they should be specified before the first + media field. + + o More than one email or phone field can be given for a session + description. + + o Phone numbers should be given in the conventional international + + format - preceded by a "+ and the international country code. + There must be a space or a hyphen ("-") between the country code + and the rest of the phone number. Spaces and hyphens may be used + to split up a phone field to aid readability if desired. For + example: + + p=+44-171-380-7777 or p=+1 617 253 6011 + + + + + +Handley & Jacobson Standards Track [Page 11] + +RFC 2327 SDP April 1998 + + + o Both email addresses and phone numbers can have an optional free + text string associated with them, normally giving the name of the + person who may be contacted. This should be enclosed in + parenthesis if it is present. For example: + + e=mjh@isi.edu (Mark Handley) + + The alternative RFC822 name quoting convention is also allowed for + both email addresses and phone numbers. For example, + + e=Mark Handley + + The free text string should be in the ISO-10646 character set with + UTF-8 encoding, or alternatively in ISO-8859-1 or other encodings + if the appropriate charset session-level attribute is set. + + Connection Data + + c=
    + + The "c=" field contains connection data. + + A session announcement must contain one "c=" field in each media + description (see below) or a "c=" field at the session-level. It may + contain a session-level "c=" field and one additional "c=" field per + media description, in which case the per-media values override the + session-level settings for the relevant media. + + The first sub-field is the network type, which is a text string + giving the type of network. Initially "IN" is defined to have the + meaning "Internet". + + The second sub-field is the address type. This allows SDP to be used + for sessions that are not IP based. Currently only IP4 is defined. + + The third sub-field is the connection address. Optional extra + subfields may be added after the connection address depending on the + value of the
    field. + + For IP4 addresses, the connection address is defined as follows: + + o Typically the connection address will be a class-D IP multicast + + group address. If the session is not multicast, then the + connection address contains the fully-qualified domain name or the + unicast IP address of the expected data source or data relay or + data sink as determined by additional attribute fields. It is not + expected that fully-qualified domain names or unicast addresses + + + +Handley & Jacobson Standards Track [Page 12] + +RFC 2327 SDP April 1998 + + + will be given in a session description that is communicated by a + multicast announcement, though this is not prohibited. If a + unicast data stream is to pass through a network address + translator, the use of a fully-qualified domain name rather than an + unicast IP address is RECOMMENDED. In other cases, the use of an + IP address to specify a particular interface on a multi-homed host + might be required. Thus this specification leaves the decision as + to which to use up to the individual application, but all + applications MUST be able to cope with receiving both formats. + + o Conferences using an IP multicast connection address must also have + a time to live (TTL) value present in addition to the multicast + address. The TTL and the address together define the scope with + which multicast packets sent in this conference will be sent. TTL + values must be in the range 0-255. + + The TTL for the session is appended to the address using a slash as + a separator. An example is: + + c=IN IP4 224.2.1.1/127 + + Hierarchical or layered encoding schemes are data streams where the + encoding from a single media source is split into a number of + layers. The receiver can choose the desired quality (and hence + bandwidth) by only subscribing to a subset of these layers. Such + layered encodings are normally transmitted in multiple multicast + groups to allow multicast pruning. This technique keeps unwanted + traffic from sites only requiring certain levels of the hierarchy. + For applications requiring multiple multicast groups, we allow the + following notation to be used for the connection address: + + // + + If the number of addresses is not given it is assumed to be one. + Multicast addresses so assigned are contiguously allocated above + the base address, so that, for example: + + c=IN IP4 224.2.1.1/127/3 + + would state that addresses 224.2.1.1, 224.2.1.2 and 224.2.1.3 are + to be used at a ttl of 127. This is semantically identical to + including multiple "c=" lines in a media description: + + c=IN IP4 224.2.1.1/127 + c=IN IP4 224.2.1.2/127 + c=IN IP4 224.2.1.3/127 + + + + + +Handley & Jacobson Standards Track [Page 13] + +RFC 2327 SDP April 1998 + + + Multiple addresses or "c=" lines can only be specified on a per- + media basis, and not for a session-level "c=" field. + + It is illegal for the slash notation described above to be used for + IP unicast addresses. + + Bandwidth + + b=: + + o This specifies the proposed bandwidth to be used by the session or + media, and is optional. + + o is in kilobits per second + + o is a single alphanumeric word giving the meaning of the + bandwidth figure. + + o Two modifiers are initially defined: + + CT Conference Total: An implicit maximum bandwidth is associated with + each TTL on the Mbone or within a particular multicast + administrative scope region (the Mbone bandwidth vs. TTL limits are + given in the MBone FAQ). If the bandwidth of a session or media in + a session is different from the bandwidth implicit from the scope, + a `b=CT:...' line should be supplied for the session giving the + proposed upper limit to the bandwidth used. The primary purpose of + this is to give an approximate idea as to whether two or more + conferences can co-exist simultaneously. + + AS Application-Specific Maximum: The bandwidth is interpreted to be + application-specific, i.e., will be the application's concept of + maximum bandwidth. Normally this will coincide with what is set on + the application's "maximum bandwidth" control if applicable. + + Note that CT gives a total bandwidth figure for all the media at + all sites. AS gives a bandwidth figure for a single media at a + single site, although there may be many sites sending + simultaneously. + + o Extension Mechanism: Tool writers can define experimental bandwidth + modifiers by prefixing their modifier with "X-". For example: + + b=X-YZ:128 + + SDP parsers should ignore bandwidth fields with unknown modifiers. + Modifiers should be alpha-numeric and, although no length limit is + given, they are recommended to be short. + + + +Handley & Jacobson Standards Track [Page 14] + +RFC 2327 SDP April 1998 + + + Times, Repeat Times and Time Zones + + t= + + o "t=" fields specify the start and stop times for a conference + session. Multiple "t=" fields may be used if a session is active + at multiple irregularly spaced times; each additional "t=" field + specifies an additional period of time for which the session will + be active. If the session is active at regular times, an "r=" + field (see below) should be used in addition to and following a + "t=" field - in which case the "t=" field specifies the start and + stop times of the repeat sequence. + + o The first and second sub-fields give the start and stop times for + the conference respectively. These values are the decimal + representation of Network Time Protocol (NTP) time values in + seconds [1]. To convert these values to UNIX time, subtract + decimal 2208988800. + + o If the stop-time is set to zero, then the session is not bounded, + though it will not become active until after the start-time. If + the start-time is also zero, the session is regarded as permanent. + + User interfaces should strongly discourage the creation of + unbounded and permanent sessions as they give no information about + when the session is actually going to terminate, and so make + scheduling difficult. + + The general assumption may be made, when displaying unbounded + sessions that have not timed out to the user, that an unbounded + session will only be active until half an hour from the current + time or the session start time, whichever is the later. If + behaviour other than this is required, an end-time should be given + and modified as appropriate when new information becomes available + about when the session should really end. + + Permanent sessions may be shown to the user as never being active + unless there are associated repeat times which state precisely when + the session will be active. In general, permanent sessions should + not be created for any session expected to have a duration of less + than 2 months, and should be discouraged for sessions expected to + have a duration of less than 6 months. + + r= + + o "r=" fields specify repeat times for a session. For example, if + a session is active at 10am on Monday and 11am on Tuesday for one + + + +Handley & Jacobson Standards Track [Page 15] + +RFC 2327 SDP April 1998 + + + hour each week for three months, then the in the + corresponding "t=" field would be the NTP representation of 10am on + the first Monday, the would be 1 week, the + would be 1 hour, and the offsets would be zero + and 25 hours. The corresponding "t=" field stop time would be the + NTP representation of the end of the last session three months + later. By default all fields are in seconds, so the "r=" and "t=" + fields might be: + + t=3034423619 3042462419 + r=604800 3600 0 90000 + + To make announcements more compact, times may also be given in units + of days, hours or minutes. The syntax for these is a number + immediately followed by a single case-sensitive character. + Fractional units are not allowed - a smaller unit should be used + instead. The following unit specification characters are allowed: + + d - days (86400 seconds) + h - minutes (3600 seconds) + m - minutes (60 seconds) + s - seconds (allowed for completeness but not recommended) + + Thus, the above announcement could also have been written: + + r=7d 1h 0 25h + + Monthly and yearly repeats cannot currently be directly specified + with a single SDP repeat time - instead separate "t" fields should + be used to explicitly list the session times. + + z= .... + + o To schedule a repeated session which spans a change from daylight- + saving time to standard time or vice-versa, it is necessary to + specify offsets from the base repeat times. This is required + because different time zones change time at different times of day, + different countries change to or from daylight time on different + dates, and some countries do not have daylight saving time at all. + + Thus in order to schedule a session that is at the same time winter + and summer, it must be possible to specify unambiguously by whose + time zone a session is scheduled. To simplify this task for + receivers, we allow the sender to specify the NTP time that a time + zone adjustment happens and the offset from the time when the + session was first scheduled. The "z" field allows the sender to + specify a list of these adjustment times and offsets from the base + time. + + + +Handley & Jacobson Standards Track [Page 16] + +RFC 2327 SDP April 1998 + + + An example might be: + + z=2882844526 -1h 2898848070 0 + + This specifies that at time 2882844526 the time base by which the + session's repeat times are calculated is shifted back by 1 hour, + and that at time 2898848070 the session's original time base is + restored. Adjustments are always relative to the specified start + time - they are not cumulative. + + o If a session is likely to last several years, it is expected + that + the session announcement will be modified periodically rather than + transmit several years worth of adjustments in one announcement. + + Encryption Keys + + k= + k=: + + o The session description protocol may be used to convey encryption + keys. A key field is permitted before the first media entry (in + which case it applies to all media in the session), or for each + media entry as required. + + o The format of keys and their usage is outside the scope of this + document, but see [3]. + + o The method indicates the mechanism to be used to obtain a usable + key by external means, or from the encoded encryption key given. + + The following methods are defined: + + k=clear: + The encryption key (as described in [3] for RTP media streams + under the AV profile) is included untransformed in this key + field. + + k=base64: + The encryption key (as described in [3] for RTP media streams + under the AV profile) is included in this key field but has been + base64 encoded because it includes characters that are + prohibited in SDP. + + k=uri: + A Universal Resource Identifier as used by WWW clients is + included in this key field. The URI refers to the data + containing the key, and may require additional authentication + + + +Handley & Jacobson Standards Track [Page 17] + +RFC 2327 SDP April 1998 + + + before the key can be returned. When a request is made to the + given URI, the MIME content-type of the reply specifies the + encoding for the key in the reply. The key should not be + obtained until the user wishes to join the session to reduce + synchronisation of requests to the WWW server(s). + + k=prompt + No key is included in this SDP description, but the session or + media stream referred to by this key field is encrypted. The + user should be prompted for the key when attempting to join the + session, and this user-supplied key should then be used to + decrypt the media streams. + + Attributes + + a= + a=: + + Attributes are the primary means for extending SDP. Attributes may + be defined to be used as "session-level" attributes, "media-level" + attributes, or both. + + A media description may have any number of attributes ("a=" fields) + which are media specific. These are referred to as "media-level" + attributes and add information about the media stream. Attribute + fields can also be added before the first media field; these + "session-level" attributes convey additional information that applies + to the conference as a whole rather than to individual media; an + example might be the conference's floor control policy. + + Attribute fields may be of two forms: + + o property attributes. A property attribute is simply of the form + "a=". These are binary attributes, and the presence of the + attribute conveys that the attribute is a property of the session. + An example might be "a=recvonly". + + o value attributes. A value attribute is of the form + "a=:". An example might be that a whiteboard + could have the value attribute "a=orient:landscape" + + Attribute interpretation depends on the media tool being invoked. + Thus receivers of session descriptions should be configurable in + their interpretation of announcements in general and of attributes in + particular. + + Attribute names must be in the US-ASCII subset of ISO-10646/UTF-8. + + + + +Handley & Jacobson Standards Track [Page 18] + +RFC 2327 SDP April 1998 + + + Attribute values are byte strings, and MAY use any byte value except + 0x00 (Nul), 0x0A (LF), and 0x0D (CR). By default, attribute values + are to be interpreted as in ISO-10646 character set with UTF-8 + encoding. Unlike other text fields, attribute values are NOT + normally affected by the `charset' attribute as this would make + comparisons against known values problematic. However, when an + attribute is defined, it can be defined to be charset-dependent, in + which case it's value should be interpreted in the session charset + rather than in ISO-10646. + + Attributes that will be commonly used can be registered with IANA + (see Appendix B). Unregistered attributes should begin with "X-" to + prevent inadvertent collision with registered attributes. In either + case, if an attribute is received that is not understood, it should + simply be ignored by the receiver. + + Media Announcements + + m= + + A session description may contain a number of media descriptions. + Each media description starts with an "m=" field, and is terminated + by either the next "m=" field or by the end of the session + description. A media field also has several sub-fields: + + o The first sub-field is the media type. Currently defined media are + "audio", "video", "application", "data" and "control", though this + list may be extended as new communication modalities emerge (e.g., + telepresense). The difference between "application" and "data" is + that the former is a media flow such as whiteboard information, and + the latter is bulk-data transfer such as multicasting of program + executables which will not typically be displayed to the user. + "control" is used to specify an additional conference control + channel for the session. + + o The second sub-field is the transport port to which the media + stream will be sent. The meaning of the transport port depends on + the network being used as specified in the relevant "c" field and + on the transport protocol defined in the third sub-field. Other + ports used by the media application (such as the RTCP port, see + [2]) should be derived algorithmically from the base media port. + + Note: For transports based on UDP, the value should be in the range + 1024 to 65535 inclusive. For RTP compliance it should be an even + number. + + + + + + +Handley & Jacobson Standards Track [Page 19] + +RFC 2327 SDP April 1998 + + + For applications where hierarchically encoded streams are being + sent to a unicast address, it may be necessary to specify multiple + transport ports. This is done using a similar notation to that + used for IP multicast addresses in the "c=" field: + + m= / + + In such a case, the ports used depend on the transport protocol. + For RTP, only the even ports are used for data and the + corresponding one-higher odd port is used for RTCP. For example: + + m=video 49170/2 RTP/AVP 31 + + would specify that ports 49170 and 49171 form one RTP/RTCP pair and + 49172 and 49173 form the second RTP/RTCP pair. RTP/AVP is the + transport protocol and 31 is the format (see below). + + It is illegal for both multiple addresses to be specified in the + "c=" field and for multiple ports to be specified in the "m=" field + in the same session description. + + o The third sub-field is the transport protocol. The transport + protocol values are dependent on the address-type field in the "c=" + fields. Thus a "c=" field of IP4 defines that the transport + protocol runs over IP4. For IP4, it is normally expected that most + media traffic will be carried as RTP over UDP. The following + transport protocols are preliminarily defined, but may be extended + through registration of new protocols with IANA: + + - RTP/AVP - the IETF's Realtime Transport Protocol using the + Audio/Video profile carried over UDP. + + - udp - User Datagram Protocol + + If an application uses a single combined proprietary media format + and transport protocol over UDP, then simply specifying the + transport protocol as udp and using the format field to distinguish + the combined protocol is recommended. If a transport protocol is + used over UDP to carry several distinct media types that need to be + distinguished by a session directory, then specifying the transport + protocol and media format separately is necessary. RTP is an + example of a transport-protocol that carries multiple payload + formats that must be distinguished by the session directory for it + to know how to start appropriate tools, relays, mixers or + recorders. + + + + + + +Handley & Jacobson Standards Track [Page 20] + +RFC 2327 SDP April 1998 + + + The main reason to specify the transport-protocol in addition to + the media format is that the same standard media formats may be + carried over different transport protocols even when the network + protocol is the same - a historical example is vat PCM audio and + RTP PCM audio. In addition, relays and monitoring tools that are + transport-protocol-specific but format-independent are possible. + + For RTP media streams operating under the RTP Audio/Video Profile + [3], the protocol field is "RTP/AVP". Should other RTP profiles be + defined in the future, their profiles will be specified in the same + way. For example, the protocol field "RTP/XYZ" would specify RTP + operating under a profile whose short name is "XYZ". + + o The fourth and subsequent sub-fields are media formats. For audio + and video, these will normally be a media payload type as defined + in the RTP Audio/Video Profile. + + When a list of payload formats is given, this implies that all of + these formats may be used in the session, but the first of these + formats is the default format for the session. + + For media whose transport protocol is not RTP or UDP the format + field is protocol specific. Such formats should be defined in an + additional specification document. + + For media whose transport protocol is RTP, SDP can be used to + provide a dynamic binding of media encoding to RTP payload type. + The encoding names in the RTP AV Profile do not specify unique + audio encodings (in terms of clock rate and number of audio + channels), and so they are not used directly in SDP format fields. + Instead, the payload type number should be used to specify the + format for static payload types and the payload type number along + with additional encoding information should be used for dynamically + allocated payload types. + + An example of a static payload type is u-law PCM coded single + channel audio sampled at 8KHz. This is completely defined in the + RTP Audio/Video profile as payload type 0, so the media field for + such a stream sent to UDP port 49232 is: + + m=video 49232 RTP/AVP 0 + + An example of a dynamic payload type is 16 bit linear encoded + stereo audio sampled at 16KHz. If we wish to use dynamic RTP/AVP + payload type 98 for such a stream, additional information is + required to decode it: + + m=video 49232 RTP/AVP 98 + + + +Handley & Jacobson Standards Track [Page 21] + +RFC 2327 SDP April 1998 + + + a=rtpmap:98 L16/16000/2 + + The general form of an rtpmap attribute is: + + a=rtpmap: /[/] + + For audio streams, may specify the number of + audio channels. This parameter may be omitted if the number of + channels is one provided no additional parameters are needed. For + video streams, no encoding parameters are currently specified. + + Additional parameters may be defined in the future, but + codecspecific parameters should not be added. Parameters added to + an rtpmap attribute should only be those required for a session + directory to make the choice of appropriate media too to + participate in a session. Codec-specific parameters should be + added in other attributes. + + Up to one rtpmap attribute can be defined for each media format + specified. Thus we might have: + + m=audio 49230 RTP/AVP 96 97 98 + a=rtpmap:96 L8/8000 + a=rtpmap:97 L16/8000 + a=rtpmap:98 L16/11025/2 + + RTP profiles that specify the use of dynamic payload types must + define the set of valid encoding names and/or a means to register + encoding names if that profile is to be used with SDP. + + Experimental encoding formats can also be specified using rtpmap. + RTP formats that are not registered as standard format names must + be preceded by "X-". Thus a new experimental redundant audio + stream called GSMLPC using dynamic payload type 99 could be + specified as: + + m=video 49232 RTP/AVP 99 + a=rtpmap:99 X-GSMLPC/8000 + + Such an experimental encoding requires that any site wishing to + receive the media stream has relevant configured state in its + session directory to know which tools are appropriate. + + Note that RTP audio formats typically do not include information + about the number of samples per packet. If a non-default (as + defined in the RTP Audio/Video Profile) packetisation is required, + the "ptime" attribute is used as given below. + + + +Handley & Jacobson Standards Track [Page 22] + +RFC 2327 SDP April 1998 + + + For more details on RTP audio and video formats, see [3]. + + o Formats for non-RTP media should be registered as MIME content + types as described in Appendix B. For example, the LBL whiteboard + application might be registered as MIME content-type application/wb + with encoding considerations specifying that it operates over UDP, + with no appropriate file format. In SDP this would then be + expressed using a combination of the "media" field and the "fmt" + field, as follows: + + m=application 32416 udp wb + + Suggested Attributes + + The following attributes are suggested. Since application writers + may add new attributes as they are required, this list is not + exhaustive. + + a=cat: + This attribute gives the dot-separated hierarchical category of + the session. This is to enable a receiver to filter unwanted + sessions by category. It would probably have been a compulsory + separate field, except for its experimental nature at this time. + It is a session-level attribute, and is not dependent on charset. + + a=keywds: + Like the cat attribute, this is to assist identifying wanted + sessions at the receiver. This allows a receiver to select + interesting session based on keywords describing the purpose of + the session. It is a session-level attribute. It is a charset + dependent attribute, meaning that its value should be interpreted + in the charset specified for the session description if one is + specified, or by default in ISO 10646/UTF-8. + + a=tool: + This gives the name and version number of the tool used to create + the session description. It is a session-level attribute, and is + not dependent on charset. + + a=ptime: + This gives the length of time in milliseconds represented by the + media in a packet. This is probably only meaningful for audio + data. It should not be necessary to know ptime to decode RTP or + vat audio, and it is intended as a recommendation for the + encoding/packetisation of audio. It is a media attribute, and is + not dependent on charset. + + + + + +Handley & Jacobson Standards Track [Page 23] + +RFC 2327 SDP April 1998 + + + a=recvonly + This specifies that the tools should be started in receive-only + mode where applicable. It can be either a session or media + attribute, and is not dependent on charset. + + a=sendrecv + This specifies that the tools should be started in send and + receive mode. This is necessary for interactive conferences with + tools such as wb which defaults to receive only mode. It can be + either a session or media attribute, and is not dependent on + charset. + + a=sendonly + This specifies that the tools should be started in send-only + mode. An example may be where a different unicast address is to + be used for a traffic destination than for a traffic source. In + such a case, two media descriptions may be use, one sendonly and + one recvonly. It can be either a session or media attribute, but + would normally only be used as a media attribute, and is not + dependent on charset. + + a=orient: + Normally this is only used in a whiteboard media specification. + It specifies the orientation of a the whiteboard on the screen. + It is a media attribute. Permitted values are `portrait', + `landscape' and `seascape' (upside down landscape). It is not + dependent on charset + + a=type: + This specifies the type of the conference. Suggested values are + `broadcast', `meeting', `moderated', `test' and `H332'. + `recvonly' should be the default for `type:broadcast' sessions, + `type:meeting' should imply `sendrecv' and `type:moderated' + should indicate the use of a floor control tool and that the + media tools are started so as to "mute" new sites joining the + conference. + + Specifying the attribute type:H332 indicates that this loosely + coupled session is part of a H.332 session as defined in the ITU + H.332 specification [10]. Media tools should be started + `recvonly'. + + Specifying the attribute type:test is suggested as a hint that, + unless explicitly requested otherwise, receivers can safely avoid + displaying this session description to users. + + The type attribute is a session-level attribute, and is not + dependent on charset. + + + +Handley & Jacobson Standards Track [Page 24] + +RFC 2327 SDP April 1998 + + + a=charset: + This specifies the character set to be used to display the + session name and information data. By default, the ISO-10646 + character set in UTF-8 encoding is used. If a more compact + representation is required, other character sets may be used such + as ISO-8859-1 for Northern European languages. In particular, + the ISO 8859-1 is specified with the following SDP attribute: + + a=charset:ISO-8859-1 + + This is a session-level attribute; if this attribute is present, + it must be before the first media field. The charset specified + MUST be one of those registered with IANA, such as ISO-8859-1. + The character set identifier is a US-ASCII string and MUST be + compared against the IANA identifiers using a case-insensitive + comparison. If the identifier is not recognised or not + supported, all strings that are affected by it SHOULD be regarded + as byte strings. + + Note that a character set specified MUST still prohibit the use + of bytes 0x00 (Nul), 0x0A (LF) and 0x0d (CR). Character sets + requiring the use of these characters MUST define a quoting + mechanism that prevents these bytes appearing within text fields. + + a=sdplang: + This can be a session level attribute or a media level attribute. + As a session level attribute, it specifies the language for the + session description. As a media level attribute, it specifies + the language for any media-level SDP information field associated + with that media. Multiple sdplang attributes can be provided + either at session or media level if multiple languages in the + session description or media use multiple languages, in which + case the order of the attributes indicates the order of + importance of the various languages in the session or media from + most important to least important. + + In general, sending session descriptions consisting of multiple + languages should be discouraged. Instead, multiple descriptions + should be sent describing the session, one in each language. + However this is not possible with all transport mechanisms, and + so multiple sdplang attributes are allowed although not + recommended. + + The sdplang attribute value must be a single RFC 1766 language + tag in US-ASCII. It is not dependent on the charset attribute. + An sdplang attribute SHOULD be specified when a session is of + + + + + +Handley & Jacobson Standards Track [Page 25] + +RFC 2327 SDP April 1998 + + + sufficient scope to cross geographic boundaries where the + language of recipients cannot be assumed, or where the session is + in a different language from the locally assumed norm. + + a=lang: + This can be a session level attribute or a media level attribute. + As a session level attribute, it specifies the default language + for the session being described. As a media level attribute, it + specifies the language for that media, overriding any session- + level language specified. Multiple lang attributes can be + provided either at session or media level if multiple languages + if the session description or media use multiple languages, in + which case the order of the attributes indicates the order of + importance of the various languages in the session or media from + most important to least important. + + The lang attribute value must be a single RFC 1766 language tag + in US-ASCII. It is not dependent on the charset attribute. A + lang attribute SHOULD be specified when a session is of + sufficient scope to cross geographic boundaries where the + language of recipients cannot be assumed, or where the session is + in a different language from the locally assumed norm. + + a=framerate: + This gives the maximum video frame rate in frames/sec. It is + intended as a recommendation for the encoding of video data. + Decimal representations of fractional values using the notation + "." are allowed. It is a media attribute, is + only defined for video media, and is not dependent on charset. + + a=quality: + This gives a suggestion for the quality of the encoding as an + integer value. + + The intention of the quality attribute for video is to specify a + non-default trade-off between frame-rate and still-image quality. + For video, the value in the range 0 to 10, with the following + suggested meaning: + + 10 - the best still-image quality the compression scheme can + give. + + 5 - the default behaviour given no quality suggestion. + + 0 - the worst still-image quality the codec designer thinks is + still usable. + + It is a media attribute, and is not dependent on charset. + + + +Handley & Jacobson Standards Track [Page 26] + +RFC 2327 SDP April 1998 + + + a=fmtp: + This attribute allows parameters that are specific to a + particular format to be conveyed in a way that SDP doesn't have + to understand them. The format must be one of the formats + specified for the media. Format-specific parameters may be any + set of parameters required to be conveyed by SDP and given + unchanged to the media tool that will use this format. + + It is a media attribute, and is not dependent on charset. + +6.1. Communicating Conference Control Policy + + There is some debate over the way conference control policy should be + communicated. In general, the authors believe that an implicit + declarative style of specifying conference control is desirable where + possible. + + A simple declarative style uses a single conference attribute field + before the first media field, possibly supplemented by properties + such as `recvonly' for some of the media tools. This conference + attribute conveys the conference control policy. An example might be: + + a=type:moderated + + In some cases, however, it is possible that this may be insufficient + to communicate the details of an unusual conference control policy. + If this is the case, then a conference attribute specifying external + control might be set, and then one or more "media" fields might be + used to specify the conference control tools and configuration data + for those tools. An example is an ITU H.332 session: + + c=IN IP4 224.5.6.7 + a=type:H332 + m=audio 49230 RTP/AVP 0 + m=video 49232 RTP/AVP 31 + m=application 12349 udp wb + m=control 49234 H323 mc + c=IN IP4 134.134.157.81 + + In this example, a general conference attribute (type:H332) is + specified stating that conference control will be provided by an + external H.332 tool, and a contact addresses for the H.323 session + multipoint controller is given. + + In this document, only the declarative style of conference control + declaration is specified. Other forms of conference control should + specify an appropriate type attribute, and should define the + implications this has for control media. + + + +Handley & Jacobson Standards Track [Page 27] + +RFC 2327 SDP April 1998 + + +7. Security Considerations + + SDP is a session description format that describes multimedia + sessions. A session description should not be trusted unless it has + been obtained by an authenticated transport protocol from a trusted + source. Many different transport protocols may be used to distribute + session description, and the nature of the authentication will differ + from transport to transport. + + One transport that will frequently be used to distribute session + descriptions is the Session Announcement Protocol (SAP). SAP + provides both encryption and authentication mechanisms but due to the + nature of session announcements it is likely that there are many + occasions where the originator of a session announcement cannot be + authenticated because they are previously unknown to the receiver of + the announcement and because no common public key infrastructure is + available. + + On receiving a session description over an unauthenticated transport + mechanism or from an untrusted party, software parsing the session + should take a few precautions. Session description contain + information required to start software on the receivers system. + Software that parses a session description MUST not be able to start + other software except that which is specifically configured as + appropriate software to participate in multimedia sessions. It is + normally considered INAPPROPRIATE for software parsing a session + description to start, on a user's system, software that is + appropriate to participate in multimedia sessions, without the user + first being informed that such software will be started and giving + their consent. Thus a session description arriving by session + announcement, email, session invitation, or WWW page SHOULD not + deliver the user into an {it interactive} multimedia session without + the user being aware that this will happen. As it is not always + simple to tell whether a session is interactive or not, applications + that are unsure should assume sessions are interactive. + + In this specification, there are no attributes which would allow the + recipient of a session description to be informed to start multimedia + tools in a mode where they default to transmitting. Under some + circumstances it might be appropriate to define such attributes. If + this is done an application parsing a session description containing + such attributes SHOULD either ignore them, or inform the user that + joining this session will result in the automatic transmission of + multimedia data. The default behaviour for an unknown attribute is + to ignore it. + + + + + + +Handley & Jacobson Standards Track [Page 28] + +RFC 2327 SDP April 1998 + + + Session descriptions may be parsed at intermediate systems such as + firewalls for the purposes of opening a hole in the firewall to allow + the participation in multimedia sessions. It is considered + INAPPROPRIATE for a firewall to open such holes for unicast data + streams unless the session description comes in a request from inside + the firewall. + + For multicast sessions, it is likely that local administrators will + apply their own policies, but the exclusive use of "local" or "site- + local" administrative scope within the firewall and the refusal of + the firewall to open a hole for such scopes will provide separation + of global multicast sessions from local ones. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Handley & Jacobson Standards Track [Page 29] + +RFC 2327 SDP April 1998 + + +Appendix A: SDP Grammar + + This appendix provides an Augmented BNF grammar for SDP. ABNF is + defined in RFC 2234. + + + announcement = proto-version + origin-field + session-name-field + information-field + uri-field + email-fields + phone-fields + connection-field + bandwidth-fields + time-fields + key-field + attribute-fields + media-descriptions + + proto-version = "v=" 1*DIGIT CRLF + ;this memo describes version 0 + + origin-field = "o=" username space + sess-id space sess-version space + nettype space addrtype space + addr CRLF + + session-name-field = "s=" text CRLF + + information-field = ["i=" text CRLF] + + uri-field = ["u=" uri CRLF] + + email-fields = *("e=" email-address CRLF) + + phone-fields = *("p=" phone-number CRLF) + + + connection-field = ["c=" nettype space addrtype space + connection-address CRLF] + ;a connection field must be present + ;in every media description or at the + ;session-level + + + bandwidth-fields = *("b=" bwtype ":" bandwidth CRLF) + + + + +Handley & Jacobson Standards Track [Page 30] + +RFC 2327 SDP April 1998 + + + time-fields = 1*( "t=" start-time space stop-time + *(CRLF repeat-fields) CRLF) + [zone-adjustments CRLF] + + + repeat-fields = "r=" repeat-interval space typed-time + 1*(space typed-time) + + + zone-adjustments = time space ["-"] typed-time + *(space time space ["-"] typed-time) + + + key-field = ["k=" key-type CRLF] + + + key-type = "prompt" | + "clear:" key-data | + "base64:" key-data | + "uri:" uri + + + key-data = email-safe | "~" | " + + + attribute-fields = *("a=" attribute CRLF) + + + media-descriptions = *( media-field + information-field + *(connection-field) + bandwidth-fields + key-field + attribute-fields ) + + + media-field = "m=" media space port ["/" integer] + space proto 1*(space fmt) CRLF + + + media = 1*(alpha-numeric) + ;typically "audio", "video", "application" + ;or "data" + + fmt = 1*(alpha-numeric) + ;typically an RTP payload type for audio + ;and video media + + + + +Handley & Jacobson Standards Track [Page 31] + +RFC 2327 SDP April 1998 + + + proto = 1*(alpha-numeric) + ;typically "RTP/AVP" or "udp" for IP4 + + + port = 1*(DIGIT) + ;should in the range "1024" to "65535" inclusive + ;for UDP based media + + + attribute = (att-field ":" att-value) | att-field + + + att-field = 1*(alpha-numeric) + + + att-value = byte-string + + + sess-id = 1*(DIGIT) + ;should be unique for this originating username/host + + + sess-version = 1*(DIGIT) + ;0 is a new session + + + connection-address = multicast-address + | addr + + + multicast-address = 3*(decimal-uchar ".") decimal-uchar "/" ttl + [ "/" integer ] + ;multicast addresses may be in the range + ;224.0.0.0 to 239.255.255.255 + + ttl = decimal-uchar + + start-time = time | "0" + + stop-time = time | "0" + + time = POS-DIGIT 9*(DIGIT) + ;sufficient for 2 more centuries + + + repeat-interval = typed-time + + + + + +Handley & Jacobson Standards Track [Page 32] + +RFC 2327 SDP April 1998 + + + typed-time = 1*(DIGIT) [fixed-len-time-unit] + + + fixed-len-time-unit = "d" | "h" | "m" | "s" + + + bwtype = 1*(alpha-numeric) + + bandwidth = 1*(DIGIT) + + + username = safe + ;pretty wide definition, but doesn't include space + + + email-address = email | email "(" email-safe ")" | + email-safe "<" email ">" + + + email = ;defined in RFC822 + + + uri= ;defined in RFC1630 + + + phone-number = phone | phone "(" email-safe ")" | + email-safe "<" phone ">" + + + phone = "+" POS-DIGIT 1*(space | "-" | DIGIT) + ;there must be a space or hyphen between the + ;international code and the rest of the number. + + + nettype = "IN" + ;list to be extended + + + addrtype = "IP4" | "IP6" + ;list to be extended + + + addr = FQDN | unicast-address + + + FQDN = 4*(alpha-numeric|"-"|".") + ;fully qualified domain name as specified in RFC1035 + + + + +Handley & Jacobson Standards Track [Page 33] + +RFC 2327 SDP April 1998 + + + unicast-address = IP4-address | IP6-address + + + IP4-address = b1 "." decimal-uchar "." decimal-uchar "." b4 + b1 = decimal-uchar + ;less than "224"; not "0" or "127" + b4 = decimal-uchar + ;not "0" + + IP6-address = ;to be defined + + + text = byte-string + ;default is to interpret this as IS0-10646 UTF8 + ;ISO 8859-1 requires a "a=charset:ISO-8859-1" + ;session-level attribute to be used + + + byte-string = 1*(0x01..0x09|0x0b|0x0c|0x0e..0xff) + ;any byte except NUL, CR or LF + + + decimal-uchar = DIGIT + | POS-DIGIT DIGIT + | ("1" 2*(DIGIT)) + | ("2" ("0"|"1"|"2"|"3"|"4") DIGIT) + | ("2" "5" ("0"|"1"|"2"|"3"|"4"|"5")) + + + integer = POS-DIGIT *(DIGIT) + + + alpha-numeric = ALPHA | DIGIT + + + DIGIT = "0" | POS-DIGIT + + + POS-DIGIT = "1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9" + + + ALPHA = "a"|"b"|"c"|"d"|"e"|"f"|"g"|"h"|"i"|"j"|"k"| + "l"|"m"|"n"|"o "|"p"|"q"|"r"|"s"|"t"|"u"|"v"| + "w"|"x"|"y"|"z"|"A"|"B"|"C "|"D"|"E"|"F"|"G"| + "H"|"I"|"J"|"K"|"L"|"M"|"N"|"O"|"P"|" Q"|"R"| + "S"|"T"|"U"|"V"|"W"|"X"|"Y"|"Z" + + + + + +Handley & Jacobson Standards Track [Page 34] + +RFC 2327 SDP April 1998 + + + email-safe = safe | space | tab + + + safe = alpha-numeric | + "'" | "'" | "-" | "." | "/" | ":" | "?" | """ | + "#" | "$" | "&" | "*" | ";" | "=" | "@" | "[" | + "]" | "^" | "_" | "`" | "{" | "|" | "}" | "+" | + "~" | " + + + space = %d32 + tab = %d9 + CRLF = %d13.10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Handley & Jacobson Standards Track [Page 35] + +RFC 2327 SDP April 1998 + + +Appendix B: Guidelines for registering SDP names with IANA + + There are seven field names that may be registered with IANA. Using + the terminology in the SDP specification BNF, they are "media", + "proto", "fmt", "att-field", "bwtype", "nettype" and "addrtype". + + "media" (eg, audio, video, application, data). + + Packetized media types, such as those used by RTP, share the + namespace used by media types registry [RFC 2048] (i.e. "MIME + types"). The list of valid media names is the set of top-level + MIME content types. The set of media is intended to be small and + not to be extended except under rare circumstances. (The MIME + subtype corresponds to the "fmt" parameter below). + + "proto" + + In general this should be an IETF standards-track transport + protocol identifier such as RTP/AVP (rfc 1889 under the rfc 1890 + profile). + + However, people will want to invent their own proprietary + transport protocols. Some of these should be registered as a + "fmt" using "udp" as the protocol and some of which probably + can't be. + + Where the protocol and the application are intimately linked, + such as with the LBL whiteboard wb which used a proprietary and + special purpose protocol over UDP, the protocol name should be + "udp" and the format name that should be registered is "wb". The + rules for formats (see below) apply to such registrations. + + Where the proprietary transport protocol really carries many + different data formats, it is possible to register a new protocol + name with IANA. In such a case, an RFC MUST be produced + describing the protocol and referenced in the registration. Such + an RFC MAY be informational, although it is preferable if it is + standards-track. + + "fmt" + + The format namespace is dependent on the context of the "proto" + field, so a format cannot be registered without specifying one or + more transport protocols that it applies to. + + Formats cover all the possible encodings that might want to be + transported in a multimedia session. + + + + +Handley & Jacobson Standards Track [Page 36] + +RFC 2327 SDP April 1998 + + + For RTP formats that have been assigned static payload types, the + payload type number is used. For RTP formats using a dynamic + payload type number, the dynamic payload type number is given as + the format and an additional "rtpmap" attribute specifies the + format and parameters. + + For non-RTP formats, any unregistered format name may be + registered through the MIME-type registration process [RFC 2048]. + The type given here is the MIME subtype only (the top-level MIME + content type is specified by the media parameter). The MIME type + registration SHOULD reference a standards-track RFC which + describes the transport protocol for this media type. If there + is an existing MIME type for this format, the MIME registration + should be augmented to reference the transport specification for + this media type. If there is not an existing MIME type for this + format, and there exists no appropriate file format, this should + be noted in the encoding considerations as "no appropriate file + format". + + "att-field" (Attribute names) + + Attribute field names MAY be registered with IANA, although this + is not compulsory, and unknown attributes are simply ignored. + + When an attribute is registered, it must be accompanied by a + brief specification stating the following: + + o contact name, email address and telephone number + + o attribute-name (as it will appear in SDP) + + o long-form attribute name in English + + o type of attribute (session level, media level, or both) + + o whether the attribute value is subject to the charset + attribute. + + o a one paragraph explanation of the purpose of the attribute. + + o a specification of appropriate attribute values for this + attribute. + + IANA will not sanity check such attribute registrations except to + ensure that they do not clash with existing registrations. + + + + + + +Handley & Jacobson Standards Track [Page 37] + +RFC 2327 SDP April 1998 + + + Although the above is the minimum that IANA will accept, if the + attribute is expected to see widespread use and interoperability + is an issue, authors are encouraged to produce a standards-track + RFC that specifies the attribute more precisely. + + Submitters of registrations should ensure that the specification + is in the spirit of SDP attributes, most notably that the + attribute is platform independent in the sense that it makes no + implicit assumptions about operating systems and does not name + specific pieces of software in a manner that might inhibit + interoperability. + + "bwtype" (bandwidth specifiers) + + A proliferation of bandwidth specifiers is strongly discouraged. + + New bandwidth specifiers may be registered with IANA. The + submission MUST reference a standards-track RFC specifying the + semantics of the bandwidth specifier precisely, and indicating + when it should be used, and why the existing registered bandwidth + specifiers do not suffice. + + "nettype" (Network Type) + + New network types may be registered with IANA if SDP needs to be + used in the context of non-internet environments. Whilst these + are not normally the preserve of IANA, there may be circumstances + when an Internet application needs to interoperate with a non- + internet application, such as when gatewaying an internet + telephony call into the PSTN. The number of network types should + be small and should be rarely extended. A new network type + cannot be registered without registering at least one address + type to be used with that network type. A new network type + registration MUST reference an RFC which gives details of the + network type and address type and specifies how and when they + would be used. Such an RFC MAY be Informational. + + "addrtype" (Address Type) + + New address types may be registered with IANA. An address type + is only meaningful in the context of a network type, and any + registration of an address type MUST specify a registered network + type, or be submitted along with a network type registration. A + new address type registration MUST reference an RFC giving + details of the syntax of the address type. Such an RFC MAY be + Informational. Address types are not expected to be registered + frequently. + + + + +Handley & Jacobson Standards Track [Page 38] + +RFC 2327 SDP April 1998 + + + Registration Procedure + + To register a name the above guidelines should be followed regarding + the required level of documentation that is required. The + registration itself should be sent to IANA. Attribute registrations + should include the information given above. Other registrations + should include the following additional information: + + o contact name, email address and telephone number + + o name being registered (as it will appear in SDP) + + o long-form name in English + + o type of name ("media", "proto", "fmt", "bwtype", "nettype", or + "addrtype") + + o a one paragraph explanation of the purpose of the registered name. + + o a reference to the specification (eg RFC number) of the registered + name. + + IANA may refer any registration to the IESG or to any appropriate + IETF working group for review, and may request revisions to be made + before a registration will be made. + + + + + + + + + + + + + + + + + + + + + + + + + + +Handley & Jacobson Standards Track [Page 39] + +RFC 2327 SDP April 1998 + + +Appendix C: Authors' Addresses + + Mark Handley + Information Sciences Institute + c/o MIT Laboratory for Computer Science + 545 Technology Square + Cambridge, MA 02139 + United States + electronic mail: mjh@isi.edu + + Van Jacobson + MS 46a-1121 + Lawrence Berkeley Laboratory + Berkeley, CA 94720 + United States + electronic mail: van@ee.lbl.gov + +Acknowledgments + + Many people in the IETF MMUSIC working group have made comments and + suggestions contributing to this document. In particular, we would + like to thank Eve Schooler, Steve Casner, Bill Fenner, Allison + Mankin, Ross Finlayson, Peter Parnes, Joerg Ott, Carsten Bormann, Rob + Lanphier and Steve Hanna. + +References + + [1] Mills, D., "Network Time Protocol (version 3) specification and + implementation", RFC 1305, March 1992. + + [2] Schulzrinne, H., Casner, S., Frederick, R. and V. Jacobson, "RTP: + A Transport Protocol for Real-Time Applications", RFC 1889, January + 1996. + + [3] Schulzrinne, H., "RTP Profile for Audio and Video Conferences + with Minimal Control", RFC 1890, January 1996 + + [4] Handley, M., "SAP - Session Announcement Protocol", Work in + Progress. + + [5] V. Jacobson, S. McCanne, "vat - X11-based audio teleconferencing + tool" vat manual page, Lawrence Berkeley Laboratory, 1994. + + [6] The Unicode Consortium, "The Unicode Standard -- Version 2.0", + Addison-Wesley, 1996. + + + + + + +Handley & Jacobson Standards Track [Page 40] + +RFC 2327 SDP April 1998 + + + [7] ISO/IEC 10646-1:1993. International Standard -- Information + technol- ogy -- Universal Multiple-Octet Coded Character Set (UCS) -- + Part 1: Architecture and Basic Multilingual Plane. Five amendments + and a techn- ical corrigendum have been published up to now. UTF-8 + is described in Annex R, published as Amendment 2. + + [8] Goldsmith, D., and M. Davis, "Using Unicode with MIME", RFC 1641, + July 1994. + + [9] Yergeau, F., "UTF-8, a transformation format of Unicode and ISO + 10646", RFC 2044, October 1996. + + [10] ITU-T Recommendation H.332 (1998): "Multimedia Terminal for + Receiving Internet-based H.323 Conferences", ITU, Geneva. + + [11] Handley, M., Schooler, E., and H. Schulzrinne, "Session + Initiation Protocol (SIP)", Work in Progress. + + [12] Schulzrinne, H., Rao, A., and R. Lanphier, "Real Time Streaming + Protocol (RTSP)", RFC 2326, April 1998. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Handley & Jacobson Standards Track [Page 41] + +RFC 2327 SDP April 1998 + + +Full Copyright Statement + + Copyright (C) The Internet Society (1998). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + + + + + + + + + + + + + + + + + + + + + + + +Handley & Jacobson Standards Track [Page 42] + diff --git a/src/modules/rtp/rfc2974.txt b/src/modules/rtp/rfc2974.txt new file mode 100644 index 000000000..4a5aa6268 --- /dev/null +++ b/src/modules/rtp/rfc2974.txt @@ -0,0 +1,1011 @@ + + + + + + +Network Working Group M. Handley +Request for Comments: 2974 ACIRI +Category: Experimental C. Perkins + USC/ISI + E. Whelan + UCL + October 2000 + + + Session Announcement Protocol + +Status of this Memo + + This memo defines an Experimental Protocol for the Internet + community. It does not specify an Internet standard of any kind. + Discussion and suggestions for improvement are requested. + Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2000). All Rights Reserved. + +Abstract + + This document describes version 2 of the multicast session directory + announcement protocol, Session Announcement Protocol (SAP), and the + related issues affecting security and scalability that should be + taken into account by implementors. + +1 Introduction + + In order to assist the advertisement of multicast multimedia + conferences and other multicast sessions, and to communicate the + relevant session setup information to prospective participants, a + distributed session directory may be used. An instance of such a + session directory periodically multicasts packets containing a + description of the session, and these advertisements are received by + other session directories such that potential remote participants can + use the session description to start the tools required to + participate in the session. + + This memo describes the issues involved in the multicast announcement + of session description information and defines an announcement + protocol to be used. Sessions are described using the session + description protocol which is described in a companion memo [4]. + + + + + + +Handley, et al. Experimental [Page 1] + +RFC 2974 Session Announcement Protocol October 2000 + + +2 Terminology + + A SAP announcer periodically multicasts an announcement packet to a + well known multicast address and port. The announcement is multicast + with the same scope as the session it is announcing, ensuring that + the recipients of the announcement are within the scope of the + session the announcement describes (bandwidth and other such + constraints permitting). This is also important for the scalability + of the protocol, as it keeps local session announcements local. + + A SAP listener learns of the multicast scopes it is within (for + example, using the Multicast-Scope Zone Announcement Protocol [5]) + and listens on the well known SAP address and port for those scopes. + In this manner, it will eventually learn of all the sessions being + announced, allowing those sessions to be joined. + + The key words `MUST', `MUST NOT', `REQUIRED', `SHALL', `SHALL NOT', + `SHOULD', `SHOULD NOT', `RECOMMENDED', `MAY', and `OPTIONAL' in this + document are to be interpreted as described in [1]. + +3 Session Announcement + + As noted previously, a SAP announcer periodically sends an + announcement packet to a well known multicast address and port. + There is no rendezvous mechanism - the SAP announcer is not aware of + the presence or absence of any SAP listeners - and no additional + reliability is provided over the standard best-effort UDP/IP + semantics. + + That announcement contains a session description and SHOULD contain + an authentication header. The session description MAY be encrypted + although this is NOT RECOMMENDED (see section 7). + + A SAP announcement is multicast with the same scope as the session it + is announcing, ensuring that the recipients of the announcement are + within the scope of the session the announcement describes. There are + a number of possibilities: + + IPv4 global scope sessions use multicast addresses in the range + 224.2.128.0 - 224.2.255.255 with SAP announcements being sent to + 224.2.127.254 (note that 224.2.127.255 is used by the obsolete + SAPv0 and MUST NOT be used). + + + + + + + + + +Handley, et al. Experimental [Page 2] + +RFC 2974 Session Announcement Protocol October 2000 + + + IPv4 administrative scope sessions using administratively scoped IP + multicast as defined in [7]. The multicast address to be used for + announcements is the highest multicast address in the relevant + administrative scope zone. For example, if the scope range is + 239.16.32.0 - 239.16.33.255, then 239.16.33.255 is used for SAP + announcements. + + IPv6 sessions are announced on the address FF0X:0:0:0:0:0:2:7FFE + where X is the 4-bit scope value. For example, an announcement + for a link-local session assigned the address + FF02:0:0:0:0:0:1234:5678, should be advertised on SAP address + FF02:0:0:0:0:0:2:7FFE. + + Ensuring that a description is not used by a potential participant + outside the session scope is not addressed in this memo. + + SAP announcements MUST be sent on port 9875 and SHOULD be sent with + an IP time-to-live of 255 (the use of TTL scoping for multicast is + discouraged [7]). + + If a session uses addresses in multiple administrative scope ranges, + it is necessary for the announcer to send identical copies of the + announcement to each administrative scope range. It is up to the + listeners to parse such multiple announcements as the same session + (as identified by the SDP origin field, for example). The + announcement rate for each administrative scope range MUST be + calculated separately, as if the multiple announcements were + separate. + + Multiple announcers may announce a single session, as an aid to + robustness in the face of packet loss and failure of one or more + announcers. The rate at which each announcer repeats its + announcement MUST be scaled back such that the total announcement + rate is equal to that which a single server would choose. + Announcements made in this manner MUST be identical. + + If multiple announcements are being made for a session, then each + announcement MUST carry an authentication header signed by the same + key, or be treated as a completely separate announcement by + listeners. + + An IPv4 SAP listener SHOULD listen on the IPv4 global scope SAP + address and on the SAP addresses for each IPv4 administrative scope + zone it is within. The discovery of administrative scope zones is + outside the scope of this memo, but it is assumed that each SAP + listener within a particular scope zone is aware of that scope zone. + A SAP listener which supports IPv6 SHOULD also listen to the IPv6 SAP + addresses. + + + +Handley, et al. Experimental [Page 3] + +RFC 2974 Session Announcement Protocol October 2000 + + +3.1 Announcement Interval + + The time period between repetitions of an announcement is chosen such + that the total bandwidth used by all announcements on a single SAP + group remains below a preconfigured limit. If not otherwise + specified, the bandwidth limit SHOULD be assumed to be 4000 bits per + second. + + Each announcer is expected to listen to other announcements in order + to determine the total number of sessions being announced on a + particular group. Sessions are uniquely identified by the + combination of the message identifier hash and originating source + fields of the SAP header (note that SAP v0 announcers always set the + message identifier hash to zero, and if such an announcement is + received the entire message MUST be compared to determine + uniqueness). + + Announcements are made by periodic multicast to the group. The base + interval between announcements is derived from the number of + announcements being made in that group, the size of the announcement + and the configured bandwidth limit. The actual transmission time is + derived from this base interval as follows: + + 1. The announcer initializes the variable tp to be the last time a + particular announcement was transmitted (or the current time if + this is the first time this announcement is to be made). + + 2. Given a configured bandwidth limit in bits/second and an + announcement of ad_size bytes, the base announcement interval + in seconds is + + interval =max(300; (8*no_of_ads*ad_size)/limit) + + 3. An offset is calculated based on the base announcement interval + + offset= rand(interval* 2/3)-(interval/3) + + 4. The next transmission time for an announcement derived as + + tn =tp+ interval+ offset + + The announcer then sets a timer to expire at tn and waits. At time + tn the announcer SHOULD recalculate the next transmission time. If + the new value of tn is before the current time, the announcement is + sent immediately. Otherwise the transmission is rescheduled for the + new tn. This reconsideration prevents transient packet bursts on + startup and when a network partition heals. + + + + +Handley, et al. Experimental [Page 4] + +RFC 2974 Session Announcement Protocol October 2000 + + +4 Session Deletion + + Sessions may be deleted in one of several ways: + + Explicit Timeout The session description payload may contain + timestamp information specifying the start- and end-times of the + session. If the current time is later than the end-time of the + session, then the session SHOULD be deleted from the receiver's + session cache. + + Implicit Timeout A session announcement message should be received + periodically for each session description in a receiver's session + cache. The announcement period can be predicted by the receiver + from the set of sessions currently being announced. If a session + announcement message has not been received for ten times the + announcement period, or one hour, whichever is the greater, then + the session is deleted from the receiver's session cache. The one + hour minimum is to allow for transient network partitionings. + + Explicit Deletion A session deletion packet is received specifying + the session to be deleted. Session deletion packets SHOULD have a + valid authentication header, matching that used to authenticate + previous announcement packets. If this authentication is missing, + the deletion message SHOULD be ignored. + +5 Session Modification + + A pre-announced session can be modified by simply announcing the + modified session description. In this case, the version hash in the + SAP header MUST be changed to indicate to receivers that the packet + contents should be parsed (or decrypted and parsed if it is + encrypted). The session itself, as distinct from the session + announcement, is uniquely identified by the payload and not by the + message identifier hash in the header. + + The same rules apply for session modification as for session + deletion: + + o Either the modified announcement must contain an authentication + header signed by the same key as the cached session announcement + it is modifying, or: + + o The cached session announcement must not contain an authentication + header, and the session modification announcement must originate + from the same host as the session it is modifying. + + + + + + +Handley, et al. Experimental [Page 5] + +RFC 2974 Session Announcement Protocol October 2000 + + + If an announcement is received containing an authentication header + and the cached announcement did not contain an authentication header, + or it contained a different authentication header, then the modified + announcement MUST be treated as a new and different announcement, and + displayed in addition to the un-authenticated announcement. The same + should happen if a modified packet without an authentication header + is received from a different source than the original announcement. + + These rules prevent an announcement having an authentication header + added by a malicious user and then being deleted using that header, + and it also prevents a denial-of-service attack by someone putting + out a spoof announcement which, due to packet loss, reaches some + participants before the original announcement. Note that under such + circumstances, being able to authenticate the message originator is + the only way to discover which session is the correct session. + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | V=1 |A|R|T|E|C| auth len | msg id hash | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + : originating source (32 or 128 bits) : + : : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | optional authentication data | + : .... : + *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* + | optional payload type | + + +-+- - - - - - - - - -+ + | |0| | + + - - - - - - - - - - - - - - - - - - - - +-+ | + | | + : payload : + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 1: Packet format + +6 Packet Format + + SAP data packets have the format described in figure 1. + + V: Version Number. The version number field MUST be set to 1 (SAPv2 + announcements which use only SAPv1 features are backwards + compatible, those which use new features can be detected by other + means, so the SAP version number doesn't need to change). + + + + +Handley, et al. Experimental [Page 6] + +RFC 2974 Session Announcement Protocol October 2000 + + + A: Address type. If the A bit is 0, the originating source field + contains a 32-bit IPv4 address. If the A bit is 1, the + originating source contains a 128-bit IPv6 address. + + R: Reserved. SAP announcers MUST set this to 0, SAP listeners MUST + ignore the contents of this field. + + T: Message Type. If the T field is set to 0 this is a session + announcement packet, if 1 this is a session deletion packet. + + E: Encryption Bit. If the encryption bit is set to 1, the payload of + the SAP packet is encrypted. If this bit is 0 the packet is not + encrypted. See section 7 for details of the encryption process. + + C: Compressed bit. If the compressed bit is set to 1, the payload is + compressed using the zlib compression algorithm [3]. If the + payload is to be compressed and encrypted, the compression MUST be + performed first. + + Authentication Length. An 8 bit unsigned quantity giving the number + of 32 bit words following the main SAP header that contain + authentication data. If it is zero, no authentication header is + present. + + Authentication data containing a digital signature of the packet, + with length as specified by the authentication length header + field. See section 8 for details of the authentication process. + + Message Identifier Hash. A 16 bit quantity that, used in combination + with the originating source, provides a globally unique identifier + indicating the precise version of this announcement. The choice + of value for this field is not specified here, except that it MUST + be unique for each session announced by a particular SAP announcer + and it MUST be changed if the session description is modified (and + a session deletion message SHOULD be sent for the old version of + the session). + + Earlier versions of SAP used a value of zero to mean that the hash + should be ignored and the payload should always be parsed. This + had the unfortunate side-effect that SAP announcers had to study + the payload data to determine how many unique sessions were being + advertised, making the calculation of the announcement interval + more complex that necessary. In order to decouple the session + announcement process from the contents of those announcements, SAP + announcers SHOULD NOT set the message identifier hash to zero. + + SAP listeners MAY silently discard messages if the message + identifier hash is set to zero. + + + +Handley, et al. Experimental [Page 7] + +RFC 2974 Session Announcement Protocol October 2000 + + + Originating Source. This gives the IP address of the original source + of the message. This is an IPv4 address if the A field is set to + zero, else it is an IPv6 address. The address is stored in + network byte order. + + SAPv0 permitted the originating source to be zero if the message + identifier hash was also zero. This practise is no longer legal, + and SAP announcers SHOULD NOT set the originating source to zero. + SAP listeners MAY silently discard packets with the originating + source set to zero. + + The header is followed by an optional payload type field and the + payload data itself. If the E or C bits are set in the header both + the payload type and payload are encrypted and/or compressed. + + The payload type field is a MIME content type specifier, describing + the format of the payload. This is a variable length ASCII text + string, followed by a single zero byte (ASCII NUL). The payload type + SHOULD be included in all packets. If the payload type is + `application/sdp' both the payload type and its terminating zero byte + MAY be omitted, although this is intended for backwards compatibility + with SAP v1 listeners only. + + The absence of a payload type field may be noted since the payload + section of such a packet will start with an SDP `v=0' field, which is + not a legal MIME content type specifier. + + All implementations MUST support payloads of type `application/sdp' + [4]. Other formats MAY be supported although since there is no + negotiation in SAP an announcer which chooses to use a session + description format other than SDP cannot know that the listeners are + able to understand the announcement. A proliferation of payload + types in announcements has the potential to lead to severe + interoperability problems, and for this reason, the use of non-SDP + payloads is NOT RECOMMENDED. + + If the packet is an announcement packet, the payload contains a + session description. + + If the packet is a session deletion packet, the payload contains a + session deletion message. If the payload format is `application/sdp' + the deletion message is a single SDP line consisting of the origin + field of the announcement to be deleted. + + It is desirable for the payload to be sufficiently small that SAP + packets do not get fragmented by the underlying network. + Fragmentation has a loss multiplier effect, which is known to + significantly affect the reliability of announcements. It is + + + +Handley, et al. Experimental [Page 8] + +RFC 2974 Session Announcement Protocol October 2000 + + + RECOMMENDED that SAP packets are smaller than 1kByte in length, + although if it is known that announcements will use a network with a + smaller MTU than this, then that SHOULD be used as the maximum + recommended packet size. + +7 Encrypted Announcements + + An announcement is received by all listeners in the scope to which it + is sent. If an announcement is encrypted, and many of the receivers + do not have the encryption key, there is a considerable waste of + bandwidth since those receivers cannot use the announcement they have + received. For this reason, the use of encrypted SAP announcements is + NOT RECOMMENDED on the global scope SAP group or on administrative + scope groups which may have many receivers which cannot decrypt those + announcements. + + The opinion of the authors is that encrypted SAP is useful in special + cases only, and that the vast majority of scenarios where encrypted + SAP has been proposed may be better served by distributing session + details using another mechanism. There are, however, certain + scenarios where encrypted announcements may be useful. For this + reason, the encryption bit is included in the SAP header to allow + experimentation with encrypted announcements. + + This memo does not specify details of the encryption algorithm to be + used or the means by which keys are generated and distributed. An + additional specification should define these, if it is desired to use + encrypted SAP. + + Note that if an encrypted announcement is being announced via a + proxy, then there may be no way for the proxy to discover that the + announcement has been superseded, and so it may continue to relay the + old announcement in addition to the new announcement. SAP provides + no mechanism to chain modified encrypted announcements, so it is + advisable to announce the unmodified session as deleted for a short + time after the modification has occurred. This does not guarantee + that all proxies have deleted the session, and so receivers of + encrypted sessions should be prepared to discard old versions of + session announcements that they may receive. In most cases however, + the only stateful proxy will be local to (and known to) the sender, + and an additional (local-area) protocol involving a handshake for + such session modifications can be used to avoid this problem. + + Session announcements that are encrypted with a symmetric algorithm + may allow a degree of privacy in the announcement of a session, but + it should be recognized that a user in possession of such a key can + pass it on to other users who should not be in possession of such a + key. Thus announcements to such a group of key holders cannot be + + + +Handley, et al. Experimental [Page 9] + +RFC 2974 Session Announcement Protocol October 2000 + + + assumed to have come from an authorized key holder unless there is an + appropriate authentication header signed by an authorized key holder. + In addition the recipients of such encrypted announcements cannot be + assumed to only be authorized key holders. Such encrypted + announcements do not provide any real security unless all of the + authorized key holders are trusted to maintain security of such + session directory keys. This property is shared by the multicast + session tools themselves, where it is possible for an un-trustworthy + member of the session to pass on encryption keys to un-authorized + users. However it is likely that keys used for the session tools + will be more short lived than those used for session directories. + + Similar considerations should apply when session announcements are + encrypted with an asymmetric algorithm, but then it is possible to + restrict the possessor(s) of the private key, so that announcements + to a key-holder group can not be made, even if one of the untrusted + members of the group proves to be un-trustworthy. + + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | V=1 |P| Auth | | + +-+-+-+-+-+-+-+-+ | + | Format specific authentication subheader | + : .................. : + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 2: Format of the authentication data in the SAP header + +8 Authenticated Announcements + + The authentication header can be used for two purposes: + + o Verification that changes to a session description or deletion of + a session are permitted. + + o Authentication of the identity of the session creator. + + In some circumstances only verification is possible because a + certificate signed by a mutually trusted person or authority is not + available. However, under such circumstances, the session originator + may still be authenticated to be the same as the session originator + of previous sessions claiming to be from the same person. This may + or may not be sufficient depending on the purpose of the session and + the people involved. + + + + + + +Handley, et al. Experimental [Page 10] + +RFC 2974 Session Announcement Protocol October 2000 + + + Clearly the key used for the authentication should not be trusted to + belong to the session originator unless it has been separately + authenticated by some other means, such as being certified by a + trusted third party. Such certificates are not normally included in + an SAP header because they take more space than can normally be + afforded in an SAP packet, and such verification must therefore take + place by some other mechanism. However, as certified public keys are + normally locally cached, authentication of a particular key only has + to take place once, rather than every time the session directory + retransmits the announcement. + + SAP is not tied to any single authentication mechanism. + Authentication data in the header is self-describing, but the precise + format depends on the authentication mechanism in use. The generic + format of the authentication data is given in figure 2. The + structure of the format specific authentication subheader, using both + the PGP and the CMS formats, is discussed in sections 8.1 and 8.2 + respectively. Additional formats may be added in future. + + Version Number, V: The version number of the authentication format + specified by this memo is 1. + + Padding Bit, P: If necessary the authentication data is padded to be + a multiple of 32 bits and the padding bit is set. In this case + the last byte of the authentication data contains the number of + padding bytes (including the last byte) that must be discarded. + + Authentication Type, Auth: The authentication type is a 4 bit + encoded field that denotes the authentication infrastructure the + sender expects the recipients to use to check the authenticity and + integrity of the information. This defines the format of the + authentication subheader and can take the values: 0 = PGP format, + 1 = CMS format. All other values are undefined and SHOULD be + ignored. + + If a SAP packet is to be compressed or encrypted, this MUST be done + before the authentication is added. + + The digital signature in the authentication data MUST be calculated + over the entire packet, including the header. The authentication + length MUST be set to zero and the authentication data excluded when + calculating the digital signature. + + It is to be expected that sessions may be announced by a number of + different mechanisms, not only SAP. For example, a session + description may placed on a web page, sent by email or conveyed in a + + + + + +Handley, et al. Experimental [Page 11] + +RFC 2974 Session Announcement Protocol October 2000 + + + session initiation protocol. To ease interoperability with these + other mechanisms, application level security is employed, rather than + using IPsec authentication headers. + +8.1 PGP Authentication + + A full description of the PGP protocol can be found in [2]. When + using PGP for SAP authentication the basic format specific + authentication subheader comprises a digital signature packet as + described in [2]. The signature type MUST be 0x01 which means the + signature is that of a canonical text document. + +8.2 CMS Authentication + + A full description of the Cryptographic Message Syntax can be found + in [6]. The format specific authentication subheader will, in the + CMS case, have an ASN.1 ContentInfo type with the ContentType being + signedData. + + Use is made of the option available in PKCS#7 to leave the content + itself blank as the content which is signed is already present in the + packet. Inclusion of it within the SignedData type would duplicate + this data and increase the packet length unnecessarily. In addition + this allows recipients with either no interest in the authentication, + or with no mechanism for checking it, to more easily skip the + authentication information. + + There SHOULD be only one signerInfo and related fields corresponding + to the originator of the SAP announcement. The signingTime SHOULD be + present as a signedAttribute. However, due to the strict size + limitations on the size of SAP packets, certificates and CRLs SHOULD + NOT be included in the signedData structure. It is expected that + users of the protocol will have other methods for certificate and CRL + distribution. + +9 Scalability and caching + + SAP is intended to announce the existence of long-lived wide-area + multicast sessions. It is not an especially timely protocol: + sessions are announced by periodic multicast with a repeat rate on + the order of tens of minutes, and no enhanced reliability over UDP. + This leads to a long startup delay before a complete set of + announcements is heard by a listener. This delay is clearly + undesirable for interactive browsing of announced sessions. + + In order to reduce the delays inherent in SAP, it is recommended that + proxy caches are deployed. A SAP proxy cache is expected to listen + to all SAP groups in its scope, and to maintain an up-to-date list of + + + +Handley, et al. Experimental [Page 12] + +RFC 2974 Session Announcement Protocol October 2000 + + + all announced sessions along with the time each announcement was last + received. When a new SAP listeners starts, it should contact its + local proxy to download this information, which is then sufficient + for it to process future announcements directly, as if it has been + continually listening. + + The protocol by which a SAP listener contacts its local proxy cache + is not specified here. + +10 Security Considerations + + SAP contains mechanisms for ensuring integrity of session + announcements, for authenticating the origin of an announcement and + for encrypting such announcements (sections 7 and 8). + + As stated in section 5, if a session modification announcement is + received that contains a valid authentication header, but which is + not signed by the original creator of the session, then the session + must be treated as a new session in addition to the original session + with the same SDP origin information unless the originator of one of + the session descriptions can be authenticated using a certificate + signed by a trusted third party. If this were not done, there would + be a possible denial of service attack whereby a party listens for + new announcements, strips off the original authentication header, + modifies the session description, adds a new authentication header + and re-announces the session. If a rule was imposed that such spoof + announcements were ignored, then if packet loss or late starting of a + session directory instance caused the original announcement to fail + to arrive at a site, but the spoof announcement did so, this would + then prevent the original announcement from being accepted at that + site. + + A similar denial-of-service attack is possible if a session + announcement receiver relies completely on the originating source and + hash fields to indicate change, and fails to parse the remainder of + announcements for which it has seen the origin/hash combination + before. + + A denial of service attack is possible from a malicious site close to + a legitimate site which is making a session announcement. This can + happen if the malicious site floods the legitimate site with huge + numbers of (illegal) low TTL announcements describing high TTL + sessions. This may reduce the session announcement rate of the + legitimate announcement to below a tenth of the rate expected at + remote sites and therefore cause the session to time out. Such an + attack is likely to be easily detectable, and we do not provide any + mechanism here to prevent it. + + + + +Handley, et al. Experimental [Page 13] + +RFC 2974 Session Announcement Protocol October 2000 + + +A. Summary of differences between SAPv0 and SAPv1 + + For this purpose SAPv0 is defined as the protocol in use by version + 2.2 of the session directory tool, sdr. SAPv1 is the protocol + described in the 19 November 1996 version of this memo. The packet + headers of SAP messages are the same in V0 and V1 in that a V1 tool + can parse a V0 announcement header but not vice-versa. In SAPv0, the + fields have the following values: + + o Version Number: 0 + + o Message Type: 0 (Announcement) + + o Authentication Type: 0 (No Authentication) + + o Encryption Bit: 0 (No Encryption) + + o Compression Bit: 0 (No compression) + + o Message Id Hash: 0 (No Hash Specified) + + o Originating Source: 0 (No source specified, announcement has + not been relayed) + +B. Summary of differences between SAPv1 and SAPv2 + + The packet headers of SAP messages are the same in V1 and V2 in that + a V2 tool can parse a V1 announcement header but not necessarily + vice-versa. + + o The A bit has been added to the SAP header, replacing one of the + bits of the SAPv1 message type field. If set to zero the + announcement is of an IPv4 session, and the packet is backwards + compatible with SAPv1. If set to one the announcement is of an + IPv6 session, and SAPv1 listeners (which do not support IPv6) will + see this as an illegal message type (MT) field. + + o The second bit of the message type field in SAPv1 has been + replaced by a reserved, must-be-zero, bit. This bit was unused in + SAPv1, so this change just codifies existing usage. + + o SAPv1 specified encryption of the payload. SAPv2 includes the E + bit in the SAP header to indicate that the payload is encrypted, + but does not specify any details of the encryption. + + o SAPv1 allowed the message identifier hash and originating source + fields to be set to zero, for backwards compatibility. This is no + longer legal. + + + +Handley, et al. Experimental [Page 14] + +RFC 2974 Session Announcement Protocol October 2000 + + + o SAPv1 specified gzip compression. SAPv2 uses zlib (the only known + implementation of SAP compression used zlib, and gzip compression + was a mistake). + + o SAPv2 provides a more complete specification for authentication. + + o SAPv2 allows for non-SDP payloads to be transported. SAPv1 + required that the payload was SDP. + + o SAPv1 included a timeout field for encrypted announcement, SAPv2 + does not (and relies of explicit deletion messages or implicit + timeouts). + +C. Acknowledgements + + SAP and SDP were originally based on the protocol used by the sd + session directory from Van Jacobson at LBNL. Version 1 of SAP was + designed by Mark Handley as part of the European Commission MICE + (Esprit 7602) and MERCI (Telematics 1007) projects. Version 2 + includes authentication features developed by Edmund Whelan, Goli + Montasser-Kohsari and Peter Kirstein as part of the European + Commission ICE-TEL project (Telematics 1005), and support for IPv6 + developed by Maryann P. Maher and Colin Perkins. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Handley, et al. Experimental [Page 15] + +RFC 2974 Session Announcement Protocol October 2000 + + +D. Authors' Addresses + + Mark Handley + AT&T Center for Internet Research at ICSI, + International Computer Science Institute, + 1947 Center Street, Suite 600, + Berkeley, CA 94704, USA + + EMail: mjh@aciri.org + + + Colin Perkins + USC Information Sciences Institute + 4350 N. Fairfax Drive, Suite 620 + Arlington, VA 22203, USA + + EMail: csp@isi.edu + + + Edmund Whelan + Department of Computer Science, + University College London, + Gower Street, + London, WC1E 6BT, UK + + EMail: e.whelan@cs.ucl.ac.uk + + + + + + + + + + + + + + + + + + + + + + + + + +Handley, et al. Experimental [Page 16] + +RFC 2974 Session Announcement Protocol October 2000 + + +References + + [1] Bradner, S., "Key words for use in RFCs to indicate requirement + levels", BCP 14, RFC 2119, March 1997. + + [2] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer. "OpenPGP + message format", RFC 2440, November 1998. + + [3] Deutsch, P. and J.-L. Gailly, "Zlib compressed data format + specification version 3.3", RFC 1950, May 1996. + + [4] Handley, M. and V. Jacobson, "SDP: Session Description Protocol", + RFC 2327, April 1998. + + [5] Handley, M., Thaler, D. and R. Kermode, "Multicast-scope zone + announcement protocol (MZAP)", RFC 2776, February 2000. + + [6] Housley, R., "Cryptographic message syntax", RFC 2630, June 1999. + + [7] Mayer, D., "Administratively scoped IP multicast", RFC 2365, July + 1998. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Handley, et al. Experimental [Page 17] + +RFC 2974 Session Announcement Protocol October 2000 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2000). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Handley, et al. Experimental [Page 18] + diff --git a/src/modules/rtp/rfc3550.txt b/src/modules/rtp/rfc3550.txt new file mode 100644 index 000000000..165736cf6 --- /dev/null +++ b/src/modules/rtp/rfc3550.txt @@ -0,0 +1,5827 @@ + + + + + + +Network Working Group H. Schulzrinne +Request for Comments: 3550 Columbia University +Obsoletes: 1889 S. Casner +Category: Standards Track Packet Design + R. Frederick + Blue Coat Systems Inc. + V. Jacobson + Packet Design + July 2003 + + + RTP: A Transport Protocol for Real-Time Applications + +Status of this Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2003). All Rights Reserved. + +Abstract + + This memorandum describes RTP, the real-time transport protocol. RTP + provides end-to-end network transport functions suitable for + applications transmitting real-time data, such as audio, video or + simulation data, over multicast or unicast network services. RTP + does not address resource reservation and does not guarantee + quality-of-service for real-time services. The data transport is + augmented by a control protocol (RTCP) to allow monitoring of the + data delivery in a manner scalable to large multicast networks, and + to provide minimal control and identification functionality. RTP and + RTCP are designed to be independent of the underlying transport and + network layers. The protocol supports the use of RTP-level + translators and mixers. + + Most of the text in this memorandum is identical to RFC 1889 which it + obsoletes. There are no changes in the packet formats on the wire, + only changes to the rules and algorithms governing how the protocol + is used. The biggest change is an enhancement to the scalable timer + algorithm for calculating when to send RTCP packets in order to + minimize transmission in excess of the intended rate when many + participants join a session simultaneously. + + + + +Schulzrinne, et al. Standards Track [Page 1] + +RFC 3550 RTP July 2003 + + +Table of Contents + + 1. Introduction ................................................ 4 + 1.1 Terminology ............................................ 5 + 2. RTP Use Scenarios ........................................... 5 + 2.1 Simple Multicast Audio Conference ...................... 6 + 2.2 Audio and Video Conference ............................. 7 + 2.3 Mixers and Translators ................................. 7 + 2.4 Layered Encodings ...................................... 8 + 3. Definitions ................................................. 8 + 4. Byte Order, Alignment, and Time Format ...................... 12 + 5. RTP Data Transfer Protocol .................................. 13 + 5.1 RTP Fixed Header Fields ................................ 13 + 5.2 Multiplexing RTP Sessions .............................. 16 + 5.3 Profile-Specific Modifications to the RTP Header ....... 18 + 5.3.1 RTP Header Extension ............................ 18 + 6. RTP Control Protocol -- RTCP ................................ 19 + 6.1 RTCP Packet Format ..................................... 21 + 6.2 RTCP Transmission Interval ............................. 24 + 6.2.1 Maintaining the Number of Session Members ....... 28 + 6.3 RTCP Packet Send and Receive Rules ..................... 28 + 6.3.1 Computing the RTCP Transmission Interval ........ 29 + 6.3.2 Initialization .................................. 30 + 6.3.3 Receiving an RTP or Non-BYE RTCP Packet ......... 31 + 6.3.4 Receiving an RTCP BYE Packet .................... 31 + 6.3.5 Timing Out an SSRC .............................. 32 + 6.3.6 Expiration of Transmission Timer ................ 32 + 6.3.7 Transmitting a BYE Packet ....................... 33 + 6.3.8 Updating we_sent ................................ 34 + 6.3.9 Allocation of Source Description Bandwidth ...... 34 + 6.4 Sender and Receiver Reports ............................ 35 + 6.4.1 SR: Sender Report RTCP Packet ................... 36 + 6.4.2 RR: Receiver Report RTCP Packet ................. 42 + 6.4.3 Extending the Sender and Receiver Reports ....... 42 + 6.4.4 Analyzing Sender and Receiver Reports ........... 43 + 6.5 SDES: Source Description RTCP Packet ................... 45 + 6.5.1 CNAME: Canonical End-Point Identifier SDES Item . 46 + 6.5.2 NAME: User Name SDES Item ....................... 48 + 6.5.3 EMAIL: Electronic Mail Address SDES Item ........ 48 + 6.5.4 PHONE: Phone Number SDES Item ................... 49 + 6.5.5 LOC: Geographic User Location SDES Item ......... 49 + 6.5.6 TOOL: Application or Tool Name SDES Item ........ 49 + 6.5.7 NOTE: Notice/Status SDES Item ................... 50 + 6.5.8 PRIV: Private Extensions SDES Item .............. 50 + 6.6 BYE: Goodbye RTCP Packet ............................... 51 + 6.7 APP: Application-Defined RTCP Packet ................... 52 + 7. RTP Translators and Mixers .................................. 53 + 7.1 General Description .................................... 53 + + + +Schulzrinne, et al. Standards Track [Page 2] + +RFC 3550 RTP July 2003 + + + 7.2 RTCP Processing in Translators ......................... 55 + 7.3 RTCP Processing in Mixers .............................. 57 + 7.4 Cascaded Mixers ........................................ 58 + 8. SSRC Identifier Allocation and Use .......................... 59 + 8.1 Probability of Collision ............................... 59 + 8.2 Collision Resolution and Loop Detection ................ 60 + 8.3 Use with Layered Encodings ............................. 64 + 9. Security .................................................... 65 + 9.1 Confidentiality ........................................ 65 + 9.2 Authentication and Message Integrity ................... 67 + 10. Congestion Control .......................................... 67 + 11. RTP over Network and Transport Protocols .................... 68 + 12. Summary of Protocol Constants ............................... 69 + 12.1 RTCP Packet Types ...................................... 70 + 12.2 SDES Types ............................................. 70 + 13. RTP Profiles and Payload Format Specifications .............. 71 + 14. Security Considerations ..................................... 73 + 15. IANA Considerations ......................................... 73 + 16. Intellectual Property Rights Statement ...................... 74 + 17. Acknowledgments ............................................. 74 + Appendix A. Algorithms ........................................ 75 + Appendix A.1 RTP Data Header Validity Checks ................... 78 + Appendix A.2 RTCP Header Validity Checks ....................... 82 + Appendix A.3 Determining Number of Packets Expected and Lost ... 83 + Appendix A.4 Generating RTCP SDES Packets ...................... 84 + Appendix A.5 Parsing RTCP SDES Packets ......................... 85 + Appendix A.6 Generating a Random 32-bit Identifier ............. 85 + Appendix A.7 Computing the RTCP Transmission Interval .......... 87 + Appendix A.8 Estimating the Interarrival Jitter ................ 94 + Appendix B. Changes from RFC 1889 ............................. 95 + References ...................................................... 100 + Normative References ............................................ 100 + Informative References .......................................... 100 + Authors' Addresses .............................................. 103 + Full Copyright Statement ........................................ 104 + + + + + + + + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 3] + +RFC 3550 RTP July 2003 + + +1. Introduction + + This memorandum specifies the real-time transport protocol (RTP), + which provides end-to-end delivery services for data with real-time + characteristics, such as interactive audio and video. Those services + include payload type identification, sequence numbering, timestamping + and delivery monitoring. Applications typically run RTP on top of + UDP to make use of its multiplexing and checksum services; both + protocols contribute parts of the transport protocol functionality. + However, RTP may be used with other suitable underlying network or + transport protocols (see Section 11). RTP supports data transfer to + multiple destinations using multicast distribution if provided by the + underlying network. + + Note that RTP itself does not provide any mechanism to ensure timely + delivery or provide other quality-of-service guarantees, but relies + on lower-layer services to do so. It does not guarantee delivery or + prevent out-of-order delivery, nor does it assume that the underlying + network is reliable and delivers packets in sequence. The sequence + numbers included in RTP allow the receiver to reconstruct the + sender's packet sequence, but sequence numbers might also be used to + determine the proper location of a packet, for example in video + decoding, without necessarily decoding packets in sequence. + + While RTP is primarily designed to satisfy the needs of multi- + participant multimedia conferences, it is not limited to that + particular application. Storage of continuous data, interactive + distributed simulation, active badge, and control and measurement + applications may also find RTP applicable. + + This document defines RTP, consisting of two closely-linked parts: + + o the real-time transport protocol (RTP), to carry data that has + real-time properties. + + o the RTP control protocol (RTCP), to monitor the quality of service + and to convey information about the participants in an on-going + session. The latter aspect of RTCP may be sufficient for "loosely + controlled" sessions, i.e., where there is no explicit membership + control and set-up, but it is not necessarily intended to support + all of an application's control communication requirements. This + functionality may be fully or partially subsumed by a separate + session control protocol, which is beyond the scope of this + document. + + RTP represents a new style of protocol following the principles of + application level framing and integrated layer processing proposed by + Clark and Tennenhouse [10]. That is, RTP is intended to be malleable + + + +Schulzrinne, et al. Standards Track [Page 4] + +RFC 3550 RTP July 2003 + + + to provide the information required by a particular application and + will often be integrated into the application processing rather than + being implemented as a separate layer. RTP is a protocol framework + that is deliberately not complete. This document specifies those + functions expected to be common across all the applications for which + RTP would be appropriate. Unlike conventional protocols in which + additional functions might be accommodated by making the protocol + more general or by adding an option mechanism that would require + parsing, RTP is intended to be tailored through modifications and/or + additions to the headers as needed. Examples are given in Sections + 5.3 and 6.4.3. + + Therefore, in addition to this document, a complete specification of + RTP for a particular application will require one or more companion + documents (see Section 13): + + o a profile specification document, which defines a set of payload + type codes and their mapping to payload formats (e.g., media + encodings). A profile may also define extensions or modifications + to RTP that are specific to a particular class of applications. + Typically an application will operate under only one profile. A + profile for audio and video data may be found in the companion RFC + 3551 [1]. + + o payload format specification documents, which define how a + particular payload, such as an audio or video encoding, is to be + carried in RTP. + + A discussion of real-time services and algorithms for their + implementation as well as background discussion on some of the RTP + design decisions can be found in [11]. + +1.1 Terminology + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in BCP 14, RFC 2119 [2] + and indicate requirement levels for compliant RTP implementations. + +2. RTP Use Scenarios + + The following sections describe some aspects of the use of RTP. The + examples were chosen to illustrate the basic operation of + applications using RTP, not to limit what RTP may be used for. In + these examples, RTP is carried on top of IP and UDP, and follows the + conventions established by the profile for audio and video specified + in the companion RFC 3551. + + + + +Schulzrinne, et al. Standards Track [Page 5] + +RFC 3550 RTP July 2003 + + +2.1 Simple Multicast Audio Conference + + A working group of the IETF meets to discuss the latest protocol + document, using the IP multicast services of the Internet for voice + communications. Through some allocation mechanism the working group + chair obtains a multicast group address and pair of ports. One port + is used for audio data, and the other is used for control (RTCP) + packets. This address and port information is distributed to the + intended participants. If privacy is desired, the data and control + packets may be encrypted as specified in Section 9.1, in which case + an encryption key must also be generated and distributed. The exact + details of these allocation and distribution mechanisms are beyond + the scope of RTP. + + The audio conferencing application used by each conference + participant sends audio data in small chunks of, say, 20 ms duration. + Each chunk of audio data is preceded by an RTP header; RTP header and + data are in turn contained in a UDP packet. The RTP header indicates + what type of audio encoding (such as PCM, ADPCM or LPC) is contained + in each packet so that senders can change the encoding during a + conference, for example, to accommodate a new participant that is + connected through a low-bandwidth link or react to indications of + network congestion. + + The Internet, like other packet networks, occasionally loses and + reorders packets and delays them by variable amounts of time. To + cope with these impairments, the RTP header contains timing + information and a sequence number that allow the receivers to + reconstruct the timing produced by the source, so that in this + example, chunks of audio are contiguously played out the speaker + every 20 ms. This timing reconstruction is performed separately for + each source of RTP packets in the conference. The sequence number + can also be used by the receiver to estimate how many packets are + being lost. + + Since members of the working group join and leave during the + conference, it is useful to know who is participating at any moment + and how well they are receiving the audio data. For that purpose, + each instance of the audio application in the conference periodically + multicasts a reception report plus the name of its user on the RTCP + (control) port. The reception report indicates how well the current + speaker is being received and may be used to control adaptive + encodings. In addition to the user name, other identifying + information may also be included subject to control bandwidth limits. + A site sends the RTCP BYE packet (Section 6.6) when it leaves the + conference. + + + + + +Schulzrinne, et al. Standards Track [Page 6] + +RFC 3550 RTP July 2003 + + +2.2 Audio and Video Conference + + If both audio and video media are used in a conference, they are + transmitted as separate RTP sessions. That is, separate RTP and RTCP + packets are transmitted for each medium using two different UDP port + pairs and/or multicast addresses. There is no direct coupling at the + RTP level between the audio and video sessions, except that a user + participating in both sessions should use the same distinguished + (canonical) name in the RTCP packets for both so that the sessions + can be associated. + + One motivation for this separation is to allow some participants in + the conference to receive only one medium if they choose. Further + explanation is given in Section 5.2. Despite the separation, + synchronized playback of a source's audio and video can be achieved + using timing information carried in the RTCP packets for both + sessions. + +2.3 Mixers and Translators + + So far, we have assumed that all sites want to receive media data in + the same format. However, this may not always be appropriate. + Consider the case where participants in one area are connected + through a low-speed link to the majority of the conference + participants who enjoy high-speed network access. Instead of forcing + everyone to use a lower-bandwidth, reduced-quality audio encoding, an + RTP-level relay called a mixer may be placed near the low-bandwidth + area. This mixer resynchronizes incoming audio packets to + reconstruct the constant 20 ms spacing generated by the sender, mixes + these reconstructed audio streams into a single stream, translates + the audio encoding to a lower-bandwidth one and forwards the lower- + bandwidth packet stream across the low-speed link. These packets + might be unicast to a single recipient or multicast on a different + address to multiple recipients. The RTP header includes a means for + mixers to identify the sources that contributed to a mixed packet so + that correct talker indication can be provided at the receivers. + + Some of the intended participants in the audio conference may be + connected with high bandwidth links but might not be directly + reachable via IP multicast. For example, they might be behind an + application-level firewall that will not let any IP packets pass. + For these sites, mixing may not be necessary, in which case another + type of RTP-level relay called a translator may be used. Two + translators are installed, one on either side of the firewall, with + the outside one funneling all multicast packets received through a + secure connection to the translator inside the firewall. The + translator inside the firewall sends them again as multicast packets + to a multicast group restricted to the site's internal network. + + + +Schulzrinne, et al. Standards Track [Page 7] + +RFC 3550 RTP July 2003 + + + Mixers and translators may be designed for a variety of purposes. An + example is a video mixer that scales the images of individual people + in separate video streams and composites them into one video stream + to simulate a group scene. Other examples of translation include the + connection of a group of hosts speaking only IP/UDP to a group of + hosts that understand only ST-II, or the packet-by-packet encoding + translation of video streams from individual sources without + resynchronization or mixing. Details of the operation of mixers and + translators are given in Section 7. + +2.4 Layered Encodings + + Multimedia applications should be able to adjust the transmission + rate to match the capacity of the receiver or to adapt to network + congestion. Many implementations place the responsibility of rate- + adaptivity at the source. This does not work well with multicast + transmission because of the conflicting bandwidth requirements of + heterogeneous receivers. The result is often a least-common + denominator scenario, where the smallest pipe in the network mesh + dictates the quality and fidelity of the overall live multimedia + "broadcast". + + Instead, responsibility for rate-adaptation can be placed at the + receivers by combining a layered encoding with a layered transmission + system. In the context of RTP over IP multicast, the source can + stripe the progressive layers of a hierarchically represented signal + across multiple RTP sessions each carried on its own multicast group. + Receivers can then adapt to network heterogeneity and control their + reception bandwidth by joining only the appropriate subset of the + multicast groups. + + Details of the use of RTP with layered encodings are given in + Sections 6.3.9, 8.3 and 11. + +3. Definitions + + RTP payload: The data transported by RTP in a packet, for + example audio samples or compressed video data. The payload + format and interpretation are beyond the scope of this document. + + RTP packet: A data packet consisting of the fixed RTP header, a + possibly empty list of contributing sources (see below), and the + payload data. Some underlying protocols may require an + encapsulation of the RTP packet to be defined. Typically one + packet of the underlying protocol contains a single RTP packet, + but several RTP packets MAY be contained if permitted by the + encapsulation method (see Section 11). + + + + +Schulzrinne, et al. Standards Track [Page 8] + +RFC 3550 RTP July 2003 + + + RTCP packet: A control packet consisting of a fixed header part + similar to that of RTP data packets, followed by structured + elements that vary depending upon the RTCP packet type. The + formats are defined in Section 6. Typically, multiple RTCP + packets are sent together as a compound RTCP packet in a single + packet of the underlying protocol; this is enabled by the length + field in the fixed header of each RTCP packet. + + Port: The "abstraction that transport protocols use to + distinguish among multiple destinations within a given host + computer. TCP/IP protocols identify ports using small positive + integers." [12] The transport selectors (TSEL) used by the OSI + transport layer are equivalent to ports. RTP depends upon the + lower-layer protocol to provide some mechanism such as ports to + multiplex the RTP and RTCP packets of a session. + + Transport address: The combination of a network address and port + that identifies a transport-level endpoint, for example an IP + address and a UDP port. Packets are transmitted from a source + transport address to a destination transport address. + + RTP media type: An RTP media type is the collection of payload + types which can be carried within a single RTP session. The RTP + Profile assigns RTP media types to RTP payload types. + + Multimedia session: A set of concurrent RTP sessions among a + common group of participants. For example, a videoconference + (which is a multimedia session) may contain an audio RTP session + and a video RTP session. + + RTP session: An association among a set of participants + communicating with RTP. A participant may be involved in multiple + RTP sessions at the same time. In a multimedia session, each + medium is typically carried in a separate RTP session with its own + RTCP packets unless the the encoding itself multiplexes multiple + media into a single data stream. A participant distinguishes + multiple RTP sessions by reception of different sessions using + different pairs of destination transport addresses, where a pair + of transport addresses comprises one network address plus a pair + of ports for RTP and RTCP. All participants in an RTP session may + share a common destination transport address pair, as in the case + of IP multicast, or the pairs may be different for each + participant, as in the case of individual unicast network + addresses and port pairs. In the unicast case, a participant may + receive from all other participants in the session using the same + pair of ports, or may use a distinct pair of ports for each. + + + + + +Schulzrinne, et al. Standards Track [Page 9] + +RFC 3550 RTP July 2003 + + + The distinguishing feature of an RTP session is that each + maintains a full, separate space of SSRC identifiers (defined + next). The set of participants included in one RTP session + consists of those that can receive an SSRC identifier transmitted + by any one of the participants either in RTP as the SSRC or a CSRC + (also defined below) or in RTCP. For example, consider a three- + party conference implemented using unicast UDP with each + participant receiving from the other two on separate port pairs. + If each participant sends RTCP feedback about data received from + one other participant only back to that participant, then the + conference is composed of three separate point-to-point RTP + sessions. If each participant provides RTCP feedback about its + reception of one other participant to both of the other + participants, then the conference is composed of one multi-party + RTP session. The latter case simulates the behavior that would + occur with IP multicast communication among the three + participants. + + The RTP framework allows the variations defined here, but a + particular control protocol or application design will usually + impose constraints on these variations. + + Synchronization source (SSRC): The source of a stream of RTP + packets, identified by a 32-bit numeric SSRC identifier carried in + the RTP header so as not to be dependent upon the network address. + All packets from a synchronization source form part of the same + timing and sequence number space, so a receiver groups packets by + synchronization source for playback. Examples of synchronization + sources include the sender of a stream of packets derived from a + signal source such as a microphone or a camera, or an RTP mixer + (see below). A synchronization source may change its data format, + e.g., audio encoding, over time. The SSRC identifier is a + randomly chosen value meant to be globally unique within a + particular RTP session (see Section 8). A participant need not + use the same SSRC identifier for all the RTP sessions in a + multimedia session; the binding of the SSRC identifiers is + provided through RTCP (see Section 6.5.1). If a participant + generates multiple streams in one RTP session, for example from + separate video cameras, each MUST be identified as a different + SSRC. + + Contributing source (CSRC): A source of a stream of RTP packets + that has contributed to the combined stream produced by an RTP + mixer (see below). The mixer inserts a list of the SSRC + identifiers of the sources that contributed to the generation of a + particular packet into the RTP header of that packet. This list + is called the CSRC list. An example application is audio + conferencing where a mixer indicates all the talkers whose speech + + + +Schulzrinne, et al. Standards Track [Page 10] + +RFC 3550 RTP July 2003 + + + was combined to produce the outgoing packet, allowing the receiver + to indicate the current talker, even though all the audio packets + contain the same SSRC identifier (that of the mixer). + + End system: An application that generates the content to be sent + in RTP packets and/or consumes the content of received RTP + packets. An end system can act as one or more synchronization + sources in a particular RTP session, but typically only one. + + Mixer: An intermediate system that receives RTP packets from one + or more sources, possibly changes the data format, combines the + packets in some manner and then forwards a new RTP packet. Since + the timing among multiple input sources will not generally be + synchronized, the mixer will make timing adjustments among the + streams and generate its own timing for the combined stream. + Thus, all data packets originating from a mixer will be identified + as having the mixer as their synchronization source. + + Translator: An intermediate system that forwards RTP packets + with their synchronization source identifier intact. Examples of + translators include devices that convert encodings without mixing, + replicators from multicast to unicast, and application-level + filters in firewalls. + + Monitor: An application that receives RTCP packets sent by + participants in an RTP session, in particular the reception + reports, and estimates the current quality of service for + distribution monitoring, fault diagnosis and long-term statistics. + The monitor function is likely to be built into the application(s) + participating in the session, but may also be a separate + application that does not otherwise participate and does not send + or receive the RTP data packets (since they are on a separate + port). These are called third-party monitors. It is also + acceptable for a third-party monitor to receive the RTP data + packets but not send RTCP packets or otherwise be counted in the + session. + + Non-RTP means: Protocols and mechanisms that may be needed in + addition to RTP to provide a usable service. In particular, for + multimedia conferences, a control protocol may distribute + multicast addresses and keys for encryption, negotiate the + encryption algorithm to be used, and define dynamic mappings + between RTP payload type values and the payload formats they + represent for formats that do not have a predefined payload type + value. Examples of such protocols include the Session Initiation + Protocol (SIP) (RFC 3261 [13]), ITU Recommendation H.323 [14] and + applications using SDP (RFC 2327 [15]), such as RTSP (RFC 2326 + [16]). For simple + + + +Schulzrinne, et al. Standards Track [Page 11] + +RFC 3550 RTP July 2003 + + + applications, electronic mail or a conference database may also be + used. The specification of such protocols and mechanisms is + outside the scope of this document. + +4. Byte Order, Alignment, and Time Format + + All integer fields are carried in network byte order, that is, most + significant byte (octet) first. This byte order is commonly known as + big-endian. The transmission order is described in detail in [3]. + Unless otherwise noted, numeric constants are in decimal (base 10). + + All header data is aligned to its natural length, i.e., 16-bit fields + are aligned on even offsets, 32-bit fields are aligned at offsets + divisible by four, etc. Octets designated as padding have the value + zero. + + Wallclock time (absolute date and time) is represented using the + timestamp format of the Network Time Protocol (NTP), which is in + seconds relative to 0h UTC on 1 January 1900 [4]. The full + resolution NTP timestamp is a 64-bit unsigned fixed-point number with + the integer part in the first 32 bits and the fractional part in the + last 32 bits. In some fields where a more compact representation is + appropriate, only the middle 32 bits are used; that is, the low 16 + bits of the integer part and the high 16 bits of the fractional part. + The high 16 bits of the integer part must be determined + independently. + + An implementation is not required to run the Network Time Protocol in + order to use RTP. Other time sources, or none at all, may be used + (see the description of the NTP timestamp field in Section 6.4.1). + However, running NTP may be useful for synchronizing streams + transmitted from separate hosts. + + The NTP timestamp will wrap around to zero some time in the year + 2036, but for RTP purposes, only differences between pairs of NTP + timestamps are used. So long as the pairs of timestamps can be + assumed to be within 68 years of each other, using modular arithmetic + for subtractions and comparisons makes the wraparound irrelevant. + + + + + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 12] + +RFC 3550 RTP July 2003 + + +5. RTP Data Transfer Protocol + +5.1 RTP Fixed Header Fields + + The RTP header has the following format: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P|X| CC |M| PT | sequence number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | synchronization source (SSRC) identifier | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | contributing source (CSRC) identifiers | + | .... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The first twelve octets are present in every RTP packet, while the + list of CSRC identifiers is present only when inserted by a mixer. + The fields have the following meaning: + + version (V): 2 bits + This field identifies the version of RTP. The version defined by + this specification is two (2). (The value 1 is used by the first + draft version of RTP and the value 0 is used by the protocol + initially implemented in the "vat" audio tool.) + + padding (P): 1 bit + If the padding bit is set, the packet contains one or more + additional padding octets at the end which are not part of the + payload. The last octet of the padding contains a count of how + many padding octets should be ignored, including itself. Padding + may be needed by some encryption algorithms with fixed block sizes + or for carrying several RTP packets in a lower-layer protocol data + unit. + + extension (X): 1 bit + If the extension bit is set, the fixed header MUST be followed by + exactly one header extension, with a format defined in Section + 5.3.1. + + CSRC count (CC): 4 bits + The CSRC count contains the number of CSRC identifiers that follow + the fixed header. + + + + + +Schulzrinne, et al. Standards Track [Page 13] + +RFC 3550 RTP July 2003 + + + marker (M): 1 bit + The interpretation of the marker is defined by a profile. It is + intended to allow significant events such as frame boundaries to + be marked in the packet stream. A profile MAY define additional + marker bits or specify that there is no marker bit by changing the + number of bits in the payload type field (see Section 5.3). + + payload type (PT): 7 bits + This field identifies the format of the RTP payload and determines + its interpretation by the application. A profile MAY specify a + default static mapping of payload type codes to payload formats. + Additional payload type codes MAY be defined dynamically through + non-RTP means (see Section 3). A set of default mappings for + audio and video is specified in the companion RFC 3551 [1]. An + RTP source MAY change the payload type during a session, but this + field SHOULD NOT be used for multiplexing separate media streams + (see Section 5.2). + + A receiver MUST ignore packets with payload types that it does not + understand. + + sequence number: 16 bits + The sequence number increments by one for each RTP data packet + sent, and may be used by the receiver to detect packet loss and to + restore packet sequence. The initial value of the sequence number + SHOULD be random (unpredictable) to make known-plaintext attacks + on encryption more difficult, even if the source itself does not + encrypt according to the method in Section 9.1, because the + packets may flow through a translator that does. Techniques for + choosing unpredictable numbers are discussed in [17]. + + timestamp: 32 bits + The timestamp reflects the sampling instant of the first octet in + the RTP data packet. The sampling instant MUST be derived from a + clock that increments monotonically and linearly in time to allow + synchronization and jitter calculations (see Section 6.4.1). The + resolution of the clock MUST be sufficient for the desired + synchronization accuracy and for measuring packet arrival jitter + (one tick per video frame is typically not sufficient). The clock + frequency is dependent on the format of data carried as payload + and is specified statically in the profile or payload format + specification that defines the format, or MAY be specified + dynamically for payload formats defined through non-RTP means. If + RTP packets are generated periodically, the nominal sampling + instant as determined from the sampling clock is to be used, not a + reading of the system clock. As an example, for fixed-rate audio + the timestamp clock would likely increment by one for each + sampling period. If an audio application reads blocks covering + + + +Schulzrinne, et al. Standards Track [Page 14] + +RFC 3550 RTP July 2003 + + + 160 sampling periods from the input device, the timestamp would be + increased by 160 for each such block, regardless of whether the + block is transmitted in a packet or dropped as silent. + + The initial value of the timestamp SHOULD be random, as for the + sequence number. Several consecutive RTP packets will have equal + timestamps if they are (logically) generated at once, e.g., belong + to the same video frame. Consecutive RTP packets MAY contain + timestamps that are not monotonic if the data is not transmitted + in the order it was sampled, as in the case of MPEG interpolated + video frames. (The sequence numbers of the packets as transmitted + will still be monotonic.) + + RTP timestamps from different media streams may advance at + different rates and usually have independent, random offsets. + Therefore, although these timestamps are sufficient to reconstruct + the timing of a single stream, directly comparing RTP timestamps + from different media is not effective for synchronization. + Instead, for each medium the RTP timestamp is related to the + sampling instant by pairing it with a timestamp from a reference + clock (wallclock) that represents the time when the data + corresponding to the RTP timestamp was sampled. The reference + clock is shared by all media to be synchronized. The timestamp + pairs are not transmitted in every data packet, but at a lower + rate in RTCP SR packets as described in Section 6.4. + + The sampling instant is chosen as the point of reference for the + RTP timestamp because it is known to the transmitting endpoint and + has a common definition for all media, independent of encoding + delays or other processing. The purpose is to allow synchronized + presentation of all media sampled at the same time. + + Applications transmitting stored data rather than data sampled in + real time typically use a virtual presentation timeline derived + from wallclock time to determine when the next frame or other unit + of each medium in the stored data should be presented. In this + case, the RTP timestamp would reflect the presentation time for + each unit. That is, the RTP timestamp for each unit would be + related to the wallclock time at which the unit becomes current on + the virtual presentation timeline. Actual presentation occurs + some time later as determined by the receiver. + + An example describing live audio narration of prerecorded video + illustrates the significance of choosing the sampling instant as + the reference point. In this scenario, the video would be + presented locally for the narrator to view and would be + simultaneously transmitted using RTP. The "sampling instant" of a + video frame transmitted in RTP would be established by referencing + + + +Schulzrinne, et al. Standards Track [Page 15] + +RFC 3550 RTP July 2003 + + + its timestamp to the wallclock time when that video frame was + presented to the narrator. The sampling instant for the audio RTP + packets containing the narrator's speech would be established by + referencing the same wallclock time when the audio was sampled. + The audio and video may even be transmitted by different hosts if + the reference clocks on the two hosts are synchronized by some + means such as NTP. A receiver can then synchronize presentation + of the audio and video packets by relating their RTP timestamps + using the timestamp pairs in RTCP SR packets. + + SSRC: 32 bits + The SSRC field identifies the synchronization source. This + identifier SHOULD be chosen randomly, with the intent that no two + synchronization sources within the same RTP session will have the + same SSRC identifier. An example algorithm for generating a + random identifier is presented in Appendix A.6. Although the + probability of multiple sources choosing the same identifier is + low, all RTP implementations must be prepared to detect and + resolve collisions. Section 8 describes the probability of + collision along with a mechanism for resolving collisions and + detecting RTP-level forwarding loops based on the uniqueness of + the SSRC identifier. If a source changes its source transport + address, it must also choose a new SSRC identifier to avoid being + interpreted as a looped source (see Section 8.2). + + CSRC list: 0 to 15 items, 32 bits each + The CSRC list identifies the contributing sources for the payload + contained in this packet. The number of identifiers is given by + the CC field. If there are more than 15 contributing sources, + only 15 can be identified. CSRC identifiers are inserted by + mixers (see Section 7.1), using the SSRC identifiers of + contributing sources. For example, for audio packets the SSRC + identifiers of all sources that were mixed together to create a + packet are listed, allowing correct talker indication at the + receiver. + +5.2 Multiplexing RTP Sessions + + For efficient protocol processing, the number of multiplexing points + should be minimized, as described in the integrated layer processing + design principle [10]. In RTP, multiplexing is provided by the + destination transport address (network address and port number) which + is different for each RTP session. For example, in a teleconference + composed of audio and video media encoded separately, each medium + SHOULD be carried in a separate RTP session with its own destination + transport address. + + + + + +Schulzrinne, et al. Standards Track [Page 16] + +RFC 3550 RTP July 2003 + + + Separate audio and video streams SHOULD NOT be carried in a single + RTP session and demultiplexed based on the payload type or SSRC + fields. Interleaving packets with different RTP media types but + using the same SSRC would introduce several problems: + + 1. If, say, two audio streams shared the same RTP session and the + same SSRC value, and one were to change encodings and thus acquire + a different RTP payload type, there would be no general way of + identifying which stream had changed encodings. + + 2. An SSRC is defined to identify a single timing and sequence number + space. Interleaving multiple payload types would require + different timing spaces if the media clock rates differ and would + require different sequence number spaces to tell which payload + type suffered packet loss. + + 3. The RTCP sender and receiver reports (see Section 6.4) can only + describe one timing and sequence number space per SSRC and do not + carry a payload type field. + + 4. An RTP mixer would not be able to combine interleaved streams of + incompatible media into one stream. + + 5. Carrying multiple media in one RTP session precludes: the use of + different network paths or network resource allocations if + appropriate; reception of a subset of the media if desired, for + example just audio if video would exceed the available bandwidth; + and receiver implementations that use separate processes for the + different media, whereas using separate RTP sessions permits + either single- or multiple-process implementations. + + Using a different SSRC for each medium but sending them in the same + RTP session would avoid the first three problems but not the last + two. + + On the other hand, multiplexing multiple related sources of the same + medium in one RTP session using different SSRC values is the norm for + multicast sessions. The problems listed above don't apply: an RTP + mixer can combine multiple audio sources, for example, and the same + treatment is applicable for all of them. It may also be appropriate + to multiplex streams of the same medium using different SSRC values + in other scenarios where the last two problems do not apply. + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 17] + +RFC 3550 RTP July 2003 + + +5.3 Profile-Specific Modifications to the RTP Header + + The existing RTP data packet header is believed to be complete for + the set of functions required in common across all the application + classes that RTP might support. However, in keeping with the ALF + design principle, the header MAY be tailored through modifications or + additions defined in a profile specification while still allowing + profile-independent monitoring and recording tools to function. + + o The marker bit and payload type field carry profile-specific + information, but they are allocated in the fixed header since many + applications are expected to need them and might otherwise have to + add another 32-bit word just to hold them. The octet containing + these fields MAY be redefined by a profile to suit different + requirements, for example with more or fewer marker bits. If + there are any marker bits, one SHOULD be located in the most + significant bit of the octet since profile-independent monitors + may be able to observe a correlation between packet loss patterns + and the marker bit. + + o Additional information that is required for a particular payload + format, such as a video encoding, SHOULD be carried in the payload + section of the packet. This might be in a header that is always + present at the start of the payload section, or might be indicated + by a reserved value in the data pattern. + + o If a particular class of applications needs additional + functionality independent of payload format, the profile under + which those applications operate SHOULD define additional fixed + fields to follow immediately after the SSRC field of the existing + fixed header. Those applications will be able to quickly and + directly access the additional fields while profile-independent + monitors or recorders can still process the RTP packets by + interpreting only the first twelve octets. + + If it turns out that additional functionality is needed in common + across all profiles, then a new version of RTP should be defined to + make a permanent change to the fixed header. + +5.3.1 RTP Header Extension + + An extension mechanism is provided to allow individual + implementations to experiment with new payload-format-independent + functions that require additional information to be carried in the + RTP data packet header. This mechanism is designed so that the + header extension may be ignored by other interoperating + implementations that have not been extended. + + + + +Schulzrinne, et al. Standards Track [Page 18] + +RFC 3550 RTP July 2003 + + + Note that this header extension is intended only for limited use. + Most potential uses of this mechanism would be better done another + way, using the methods described in the previous section. For + example, a profile-specific extension to the fixed header is less + expensive to process because it is not conditional nor in a variable + location. Additional information required for a particular payload + format SHOULD NOT use this header extension, but SHOULD be carried in + the payload section of the packet. + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | defined by profile | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | header extension | + | .... | + + If the X bit in the RTP header is one, a variable-length header + extension MUST be appended to the RTP header, following the CSRC list + if present. The header extension contains a 16-bit length field that + counts the number of 32-bit words in the extension, excluding the + four-octet extension header (therefore zero is a valid length). Only + a single extension can be appended to the RTP data header. To allow + multiple interoperating implementations to each experiment + independently with different header extensions, or to allow a + particular implementation to experiment with more than one type of + header extension, the first 16 bits of the header extension are left + open for distinguishing identifiers or parameters. The format of + these 16 bits is to be defined by the profile specification under + which the implementations are operating. This RTP specification does + not define any header extensions itself. + +6. RTP Control Protocol -- RTCP + + The RTP control protocol (RTCP) is based on the periodic transmission + of control packets to all participants in the session, using the same + distribution mechanism as the data packets. The underlying protocol + MUST provide multiplexing of the data and control packets, for + example using separate port numbers with UDP. RTCP performs four + functions: + + 1. The primary function is to provide feedback on the quality of the + data distribution. This is an integral part of the RTP's role as + a transport protocol and is related to the flow and congestion + control functions of other transport protocols (see Section 10 on + the requirement for congestion control). The feedback may be + directly useful for control of adaptive encodings [18,19], but + experiments with IP multicasting have shown that it is also + + + +Schulzrinne, et al. Standards Track [Page 19] + +RFC 3550 RTP July 2003 + + + critical to get feedback from the receivers to diagnose faults in + the distribution. Sending reception feedback reports to all + participants allows one who is observing problems to evaluate + whether those problems are local or global. With a distribution + mechanism like IP multicast, it is also possible for an entity + such as a network service provider who is not otherwise involved + in the session to receive the feedback information and act as a + third-party monitor to diagnose network problems. This feedback + function is performed by the RTCP sender and receiver reports, + described below in Section 6.4. + + 2. RTCP carries a persistent transport-level identifier for an RTP + source called the canonical name or CNAME, Section 6.5.1. Since + the SSRC identifier may change if a conflict is discovered or a + program is restarted, receivers require the CNAME to keep track of + each participant. Receivers may also require the CNAME to + associate multiple data streams from a given participant in a set + of related RTP sessions, for example to synchronize audio and + video. Inter-media synchronization also requires the NTP and RTP + timestamps included in RTCP packets by data senders. + + 3. The first two functions require that all participants send RTCP + packets, therefore the rate must be controlled in order for RTP to + scale up to a large number of participants. By having each + participant send its control packets to all the others, each can + independently observe the number of participants. This number is + used to calculate the rate at which the packets are sent, as + explained in Section 6.2. + + 4. A fourth, OPTIONAL function is to convey minimal session control + information, for example participant identification to be + displayed in the user interface. This is most likely to be useful + in "loosely controlled" sessions where participants enter and + leave without membership control or parameter negotiation. RTCP + serves as a convenient channel to reach all the participants, but + it is not necessarily expected to support all the control + communication requirements of an application. A higher-level + session control protocol, which is beyond the scope of this + document, may be needed. + + Functions 1-3 SHOULD be used in all environments, but particularly in + the IP multicast environment. RTP application designers SHOULD avoid + mechanisms that can only work in unicast mode and will not scale to + larger numbers. Transmission of RTCP MAY be controlled separately + for senders and receivers, as described in Section 6.2, for cases + such as unidirectional links where feedback from receivers is not + possible. + + + + +Schulzrinne, et al. Standards Track [Page 20] + +RFC 3550 RTP July 2003 + + + Non-normative note: In the multicast routing approach + called Source-Specific Multicast (SSM), there is only one sender + per "channel" (a source address, group address pair), and + receivers (except for the channel source) cannot use multicast to + communicate directly with other channel members. The + recommendations here accommodate SSM only through Section 6.2's + option of turning off receivers' RTCP entirely. Future work will + specify adaptation of RTCP for SSM so that feedback from receivers + can be maintained. + +6.1 RTCP Packet Format + + This specification defines several RTCP packet types to carry a + variety of control information: + + SR: Sender report, for transmission and reception statistics from + participants that are active senders + + RR: Receiver report, for reception statistics from participants + that are not active senders and in combination with SR for + active senders reporting on more than 31 sources + + SDES: Source description items, including CNAME + + BYE: Indicates end of participation + + APP: Application-specific functions + + Each RTCP packet begins with a fixed part similar to that of RTP data + packets, followed by structured elements that MAY be of variable + length according to the packet type but MUST end on a 32-bit + boundary. The alignment requirement and a length field in the fixed + part of each packet are included to make RTCP packets "stackable". + Multiple RTCP packets can be concatenated without any intervening + separators to form a compound RTCP packet that is sent in a single + packet of the lower layer protocol, for example UDP. There is no + explicit count of individual RTCP packets in the compound packet + since the lower layer protocols are expected to provide an overall + length to determine the end of the compound packet. + + Each individual RTCP packet in the compound packet may be processed + independently with no requirements upon the order or combination of + packets. However, in order to perform the functions of the protocol, + the following constraints are imposed: + + + + + + + +Schulzrinne, et al. Standards Track [Page 21] + +RFC 3550 RTP July 2003 + + + o Reception statistics (in SR or RR) should be sent as often as + bandwidth constraints will allow to maximize the resolution of the + statistics, therefore each periodically transmitted compound RTCP + packet MUST include a report packet. + + o New receivers need to receive the CNAME for a source as soon as + possible to identify the source and to begin associating media for + purposes such as lip-sync, so each compound RTCP packet MUST also + include the SDES CNAME except when the compound RTCP packet is + split for partial encryption as described in Section 9.1. + + o The number of packet types that may appear first in the compound + packet needs to be limited to increase the number of constant bits + in the first word and the probability of successfully validating + RTCP packets against misaddressed RTP data packets or other + unrelated packets. + + Thus, all RTCP packets MUST be sent in a compound packet of at least + two individual packets, with the following format: + + Encryption prefix: If and only if the compound packet is to be + encrypted according to the method in Section 9.1, it MUST be + prefixed by a random 32-bit quantity redrawn for every compound + packet transmitted. If padding is required for the encryption, it + MUST be added to the last packet of the compound packet. + + SR or RR: The first RTCP packet in the compound packet MUST + always be a report packet to facilitate header validation as + described in Appendix A.2. This is true even if no data has been + sent or received, in which case an empty RR MUST be sent, and even + if the only other RTCP packet in the compound packet is a BYE. + + Additional RRs: If the number of sources for which reception + statistics are being reported exceeds 31, the number that will fit + into one SR or RR packet, then additional RR packets SHOULD follow + the initial report packet. + + SDES: An SDES packet containing a CNAME item MUST be included + in each compound RTCP packet, except as noted in Section 9.1. + Other source description items MAY optionally be included if + required by a particular application, subject to bandwidth + constraints (see Section 6.3.9). + + BYE or APP: Other RTCP packet types, including those yet to be + defined, MAY follow in any order, except that BYE SHOULD be the + last packet sent with a given SSRC/CSRC. Packet types MAY appear + more than once. + + + + +Schulzrinne, et al. Standards Track [Page 22] + +RFC 3550 RTP July 2003 + + + An individual RTP participant SHOULD send only one compound RTCP + packet per report interval in order for the RTCP bandwidth per + participant to be estimated correctly (see Section 6.2), except when + the compound RTCP packet is split for partial encryption as described + in Section 9.1. If there are too many sources to fit all the + necessary RR packets into one compound RTCP packet without exceeding + the maximum transmission unit (MTU) of the network path, then only + the subset that will fit into one MTU SHOULD be included in each + interval. The subsets SHOULD be selected round-robin across multiple + intervals so that all sources are reported. + + It is RECOMMENDED that translators and mixers combine individual RTCP + packets from the multiple sources they are forwarding into one + compound packet whenever feasible in order to amortize the packet + overhead (see Section 7). An example RTCP compound packet as might + be produced by a mixer is shown in Fig. 1. If the overall length of + a compound packet would exceed the MTU of the network path, it SHOULD + be segmented into multiple shorter compound packets to be transmitted + in separate packets of the underlying protocol. This does not impair + the RTCP bandwidth estimation because each compound packet represents + at least one distinct participant. Note that each of the compound + packets MUST begin with an SR or RR packet. + + An implementation SHOULD ignore incoming RTCP packets with types + unknown to it. Additional RTCP packet types may be registered with + the Internet Assigned Numbers Authority (IANA) as described in + Section 15. + + if encrypted: random 32-bit integer + | + |[--------- packet --------][---------- packet ----------][-packet-] + | + | receiver chunk chunk + V reports item item item item + -------------------------------------------------------------------- + R[SR #sendinfo #site1#site2][SDES #CNAME PHONE #CNAME LOC][BYE##why] + -------------------------------------------------------------------- + | | + |<----------------------- compound packet ----------------------->| + |<-------------------------- UDP packet ------------------------->| + + #: SSRC/CSRC identifier + + Figure 1: Example of an RTCP compound packet + + + + + + + +Schulzrinne, et al. Standards Track [Page 23] + +RFC 3550 RTP July 2003 + + +6.2 RTCP Transmission Interval + + RTP is designed to allow an application to scale automatically over + session sizes ranging from a few participants to thousands. For + example, in an audio conference the data traffic is inherently self- + limiting because only one or two people will speak at a time, so with + multicast distribution the data rate on any given link remains + relatively constant independent of the number of participants. + However, the control traffic is not self-limiting. If the reception + reports from each participant were sent at a constant rate, the + control traffic would grow linearly with the number of participants. + Therefore, the rate must be scaled down by dynamically calculating + the interval between RTCP packet transmissions. + + For each session, it is assumed that the data traffic is subject to + an aggregate limit called the "session bandwidth" to be divided among + the participants. This bandwidth might be reserved and the limit + enforced by the network. If there is no reservation, there may be + other constraints, depending on the environment, that establish the + "reasonable" maximum for the session to use, and that would be the + session bandwidth. The session bandwidth may be chosen based on some + cost or a priori knowledge of the available network bandwidth for the + session. It is somewhat independent of the media encoding, but the + encoding choice may be limited by the session bandwidth. Often, the + session bandwidth is the sum of the nominal bandwidths of the senders + expected to be concurrently active. For teleconference audio, this + number would typically be one sender's bandwidth. For layered + encodings, each layer is a separate RTP session with its own session + bandwidth parameter. + + The session bandwidth parameter is expected to be supplied by a + session management application when it invokes a media application, + but media applications MAY set a default based on the single-sender + data bandwidth for the encoding selected for the session. The + application MAY also enforce bandwidth limits based on multicast + scope rules or other criteria. All participants MUST use the same + value for the session bandwidth so that the same RTCP interval will + be calculated. + + Bandwidth calculations for control and data traffic include lower- + layer transport and network protocols (e.g., UDP and IP) since that + is what the resource reservation system would need to know. The + application can also be expected to know which of these protocols are + in use. Link level headers are not included in the calculation since + the packet will be encapsulated with different link level headers as + it travels. + + + + + +Schulzrinne, et al. Standards Track [Page 24] + +RFC 3550 RTP July 2003 + + + The control traffic should be limited to a small and known fraction + of the session bandwidth: small so that the primary function of the + transport protocol to carry data is not impaired; known so that the + control traffic can be included in the bandwidth specification given + to a resource reservation protocol, and so that each participant can + independently calculate its share. The control traffic bandwidth is + in addition to the session bandwidth for the data traffic. It is + RECOMMENDED that the fraction of the session bandwidth added for RTCP + be fixed at 5%. It is also RECOMMENDED that 1/4 of the RTCP + bandwidth be dedicated to participants that are sending data so that + in sessions with a large number of receivers but a small number of + senders, newly joining participants will more quickly receive the + CNAME for the sending sites. When the proportion of senders is + greater than 1/4 of the participants, the senders get their + proportion of the full RTCP bandwidth. While the values of these and + other constants in the interval calculation are not critical, all + participants in the session MUST use the same values so the same + interval will be calculated. Therefore, these constants SHOULD be + fixed for a particular profile. + + A profile MAY specify that the control traffic bandwidth may be a + separate parameter of the session rather than a strict percentage of + the session bandwidth. Using a separate parameter allows rate- + adaptive applications to set an RTCP bandwidth consistent with a + "typical" data bandwidth that is lower than the maximum bandwidth + specified by the session bandwidth parameter. + + The profile MAY further specify that the control traffic bandwidth + may be divided into two separate session parameters for those + participants which are active data senders and those which are not; + let us call the parameters S and R. Following the recommendation + that 1/4 of the RTCP bandwidth be dedicated to data senders, the + RECOMMENDED default values for these two parameters would be 1.25% + and 3.75%, respectively. When the proportion of senders is greater + than S/(S+R) of the participants, the senders get their proportion of + the sum of these parameters. Using two parameters allows RTCP + reception reports to be turned off entirely for a particular session + by setting the RTCP bandwidth for non-data-senders to zero while + keeping the RTCP bandwidth for data senders non-zero so that sender + reports can still be sent for inter-media synchronization. Turning + off RTCP reception reports is NOT RECOMMENDED because they are needed + for the functions listed at the beginning of Section 6, particularly + reception quality feedback and congestion control. However, doing so + may be appropriate for systems operating on unidirectional links or + for sessions that don't require feedback on the quality of reception + or liveness of receivers and that have other means to avoid + congestion. + + + + +Schulzrinne, et al. Standards Track [Page 25] + +RFC 3550 RTP July 2003 + + + The calculated interval between transmissions of compound RTCP + packets SHOULD also have a lower bound to avoid having bursts of + packets exceed the allowed bandwidth when the number of participants + is small and the traffic isn't smoothed according to the law of large + numbers. It also keeps the report interval from becoming too small + during transient outages like a network partition such that + adaptation is delayed when the partition heals. At application + startup, a delay SHOULD be imposed before the first compound RTCP + packet is sent to allow time for RTCP packets to be received from + other participants so the report interval will converge to the + correct value more quickly. This delay MAY be set to half the + minimum interval to allow quicker notification that the new + participant is present. The RECOMMENDED value for a fixed minimum + interval is 5 seconds. + + An implementation MAY scale the minimum RTCP interval to a smaller + value inversely proportional to the session bandwidth parameter with + the following limitations: + + o For multicast sessions, only active data senders MAY use the + reduced minimum value to calculate the interval for transmission + of compound RTCP packets. + + o For unicast sessions, the reduced value MAY be used by + participants that are not active data senders as well, and the + delay before sending the initial compound RTCP packet MAY be zero. + + o For all sessions, the fixed minimum SHOULD be used when + calculating the participant timeout interval (see Section 6.3.5) + so that implementations which do not use the reduced value for + transmitting RTCP packets are not timed out by other participants + prematurely. + + o The RECOMMENDED value for the reduced minimum in seconds is 360 + divided by the session bandwidth in kilobits/second. This minimum + is smaller than 5 seconds for bandwidths greater than 72 kb/s. + + The algorithm described in Section 6.3 and Appendix A.7 was designed + to meet the goals outlined in this section. It calculates the + interval between sending compound RTCP packets to divide the allowed + control traffic bandwidth among the participants. This allows an + application to provide fast response for small sessions where, for + example, identification of all participants is important, yet + automatically adapt to large sessions. The algorithm incorporates + the following characteristics: + + + + + + +Schulzrinne, et al. Standards Track [Page 26] + +RFC 3550 RTP July 2003 + + + o The calculated interval between RTCP packets scales linearly with + the number of members in the group. It is this linear factor + which allows for a constant amount of control traffic when summed + across all members. + + o The interval between RTCP packets is varied randomly over the + range [0.5,1.5] times the calculated interval to avoid unintended + synchronization of all participants [20]. The first RTCP packet + sent after joining a session is also delayed by a random variation + of half the minimum RTCP interval. + + o A dynamic estimate of the average compound RTCP packet size is + calculated, including all those packets received and sent, to + automatically adapt to changes in the amount of control + information carried. + + o Since the calculated interval is dependent on the number of + observed group members, there may be undesirable startup effects + when a new user joins an existing session, or many users + simultaneously join a new session. These new users will initially + have incorrect estimates of the group membership, and thus their + RTCP transmission interval will be too short. This problem can be + significant if many users join the session simultaneously. To + deal with this, an algorithm called "timer reconsideration" is + employed. This algorithm implements a simple back-off mechanism + which causes users to hold back RTCP packet transmission if the + group sizes are increasing. + + o When users leave a session, either with a BYE or by timeout, the + group membership decreases, and thus the calculated interval + should decrease. A "reverse reconsideration" algorithm is used to + allow members to more quickly reduce their intervals in response + to group membership decreases. + + o BYE packets are given different treatment than other RTCP packets. + When a user leaves a group, and wishes to send a BYE packet, it + may do so before its next scheduled RTCP packet. However, + transmission of BYEs follows a back-off algorithm which avoids + floods of BYE packets should a large number of members + simultaneously leave the session. + + This algorithm may be used for sessions in which all participants are + allowed to send. In that case, the session bandwidth parameter is + the product of the individual sender's bandwidth times the number of + participants, and the RTCP bandwidth is 5% of that. + + Details of the algorithm's operation are given in the sections that + follow. Appendix A.7 gives an example implementation. + + + +Schulzrinne, et al. Standards Track [Page 27] + +RFC 3550 RTP July 2003 + + +6.2.1 Maintaining the Number of Session Members + + Calculation of the RTCP packet interval depends upon an estimate of + the number of sites participating in the session. New sites are + added to the count when they are heard, and an entry for each SHOULD + be created in a table indexed by the SSRC or CSRC identifier (see + Section 8.2) to keep track of them. New entries MAY be considered + not valid until multiple packets carrying the new SSRC have been + received (see Appendix A.1), or until an SDES RTCP packet containing + a CNAME for that SSRC has been received. Entries MAY be deleted from + the table when an RTCP BYE packet with the corresponding SSRC + identifier is received, except that some straggler data packets might + arrive after the BYE and cause the entry to be recreated. Instead, + the entry SHOULD be marked as having received a BYE and then deleted + after an appropriate delay. + + A participant MAY mark another site inactive, or delete it if not yet + valid, if no RTP or RTCP packet has been received for a small number + of RTCP report intervals (5 is RECOMMENDED). This provides some + robustness against packet loss. All sites must have the same value + for this multiplier and must calculate roughly the same value for the + RTCP report interval in order for this timeout to work properly. + Therefore, this multiplier SHOULD be fixed for a particular profile. + + For sessions with a very large number of participants, it may be + impractical to maintain a table to store the SSRC identifier and + state information for all of them. An implementation MAY use SSRC + sampling, as described in [21], to reduce the storage requirements. + An implementation MAY use any other algorithm with similar + performance. A key requirement is that any algorithm considered + SHOULD NOT substantially underestimate the group size, although it + MAY overestimate. + +6.3 RTCP Packet Send and Receive Rules + + The rules for how to send, and what to do when receiving an RTCP + packet are outlined here. An implementation that allows operation in + a multicast environment or a multipoint unicast environment MUST meet + the requirements in Section 6.2. Such an implementation MAY use the + algorithm defined in this section to meet those requirements, or MAY + use some other algorithm so long as it provides equivalent or better + performance. An implementation which is constrained to two-party + unicast operation SHOULD still use randomization of the RTCP + transmission interval to avoid unintended synchronization of multiple + instances operating in the same environment, but MAY omit the "timer + reconsideration" and "reverse reconsideration" algorithms in Sections + 6.3.3, 6.3.6 and 6.3.7. + + + + +Schulzrinne, et al. Standards Track [Page 28] + +RFC 3550 RTP July 2003 + + + To execute these rules, a session participant must maintain several + pieces of state: + + tp: the last time an RTCP packet was transmitted; + + tc: the current time; + + tn: the next scheduled transmission time of an RTCP packet; + + pmembers: the estimated number of session members at the time tn + was last recomputed; + + members: the most current estimate for the number of session + members; + + senders: the most current estimate for the number of senders in + the session; + + rtcp_bw: The target RTCP bandwidth, i.e., the total bandwidth + that will be used for RTCP packets by all members of this session, + in octets per second. This will be a specified fraction of the + "session bandwidth" parameter supplied to the application at + startup. + + we_sent: Flag that is true if the application has sent data + since the 2nd previous RTCP report was transmitted. + + avg_rtcp_size: The average compound RTCP packet size, in octets, + over all RTCP packets sent and received by this participant. The + size includes lower-layer transport and network protocol headers + (e.g., UDP and IP) as explained in Section 6.2. + + initial: Flag that is true if the application has not yet sent + an RTCP packet. + + Many of these rules make use of the "calculated interval" between + packet transmissions. This interval is described in the following + section. + +6.3.1 Computing the RTCP Transmission Interval + + To maintain scalability, the average interval between packets from a + session participant should scale with the group size. This interval + is called the calculated interval. It is obtained by combining a + number of the pieces of state described above. The calculated + interval T is then determined as follows: + + + + + +Schulzrinne, et al. Standards Track [Page 29] + +RFC 3550 RTP July 2003 + + + 1. If the number of senders is less than or equal to 25% of the + membership (members), the interval depends on whether the + participant is a sender or not (based on the value of we_sent). + If the participant is a sender (we_sent true), the constant C is + set to the average RTCP packet size (avg_rtcp_size) divided by 25% + of the RTCP bandwidth (rtcp_bw), and the constant n is set to the + number of senders. If we_sent is not true, the constant C is set + to the average RTCP packet size divided by 75% of the RTCP + bandwidth. The constant n is set to the number of receivers + (members - senders). If the number of senders is greater than + 25%, senders and receivers are treated together. The constant C + is set to the average RTCP packet size divided by the total RTCP + bandwidth and n is set to the total number of members. As stated + in Section 6.2, an RTP profile MAY specify that the RTCP bandwidth + may be explicitly defined by two separate parameters (call them S + and R) for those participants which are senders and those which + are not. In that case, the 25% fraction becomes S/(S+R) and the + 75% fraction becomes R/(S+R). Note that if R is zero, the + percentage of senders is never greater than S/(S+R), and the + implementation must avoid division by zero. + + 2. If the participant has not yet sent an RTCP packet (the variable + initial is true), the constant Tmin is set to 2.5 seconds, else it + is set to 5 seconds. + + 3. The deterministic calculated interval Td is set to max(Tmin, n*C). + + 4. The calculated interval T is set to a number uniformly distributed + between 0.5 and 1.5 times the deterministic calculated interval. + + 5. The resulting value of T is divided by e-3/2=1.21828 to compensate + for the fact that the timer reconsideration algorithm converges to + a value of the RTCP bandwidth below the intended average. + + This procedure results in an interval which is random, but which, on + average, gives at least 25% of the RTCP bandwidth to senders and the + rest to receivers. If the senders constitute more than one quarter + of the membership, this procedure splits the bandwidth equally among + all participants, on average. + +6.3.2 Initialization + + Upon joining the session, the participant initializes tp to 0, tc to + 0, senders to 0, pmembers to 1, members to 1, we_sent to false, + rtcp_bw to the specified fraction of the session bandwidth, initial + to true, and avg_rtcp_size to the probable size of the first RTCP + packet that the application will later construct. The calculated + interval T is then computed, and the first packet is scheduled for + + + +Schulzrinne, et al. Standards Track [Page 30] + +RFC 3550 RTP July 2003 + + + time tn = T. This means that a transmission timer is set which + expires at time T. Note that an application MAY use any desired + approach for implementing this timer. + + The participant adds its own SSRC to the member table. + +6.3.3 Receiving an RTP or Non-BYE RTCP Packet + + When an RTP or RTCP packet is received from a participant whose SSRC + is not in the member table, the SSRC is added to the table, and the + value for members is updated once the participant has been validated + as described in Section 6.2.1. The same processing occurs for each + CSRC in a validated RTP packet. + + When an RTP packet is received from a participant whose SSRC is not + in the sender table, the SSRC is added to the table, and the value + for senders is updated. + + For each compound RTCP packet received, the value of avg_rtcp_size is + updated: + + avg_rtcp_size = (1/16) * packet_size + (15/16) * avg_rtcp_size + + where packet_size is the size of the RTCP packet just received. + +6.3.4 Receiving an RTCP BYE Packet + + Except as described in Section 6.3.7 for the case when an RTCP BYE is + to be transmitted, if the received packet is an RTCP BYE packet, the + SSRC is checked against the member table. If present, the entry is + removed from the table, and the value for members is updated. The + SSRC is then checked against the sender table. If present, the entry + is removed from the table, and the value for senders is updated. + + Furthermore, to make the transmission rate of RTCP packets more + adaptive to changes in group membership, the following "reverse + reconsideration" algorithm SHOULD be executed when a BYE packet is + received that reduces members to a value less than pmembers: + + o The value for tn is updated according to the following formula: + + tn = tc + (members/pmembers) * (tn - tc) + + o The value for tp is updated according the following formula: + + tp = tc - (members/pmembers) * (tc - tp). + + + + + +Schulzrinne, et al. Standards Track [Page 31] + +RFC 3550 RTP July 2003 + + + o The next RTCP packet is rescheduled for transmission at time tn, + which is now earlier. + + o The value of pmembers is set equal to members. + + This algorithm does not prevent the group size estimate from + incorrectly dropping to zero for a short time due to premature + timeouts when most participants of a large session leave at once but + some remain. The algorithm does make the estimate return to the + correct value more rapidly. This situation is unusual enough and the + consequences are sufficiently harmless that this problem is deemed + only a secondary concern. + +6.3.5 Timing Out an SSRC + + At occasional intervals, the participant MUST check to see if any of + the other participants time out. To do this, the participant + computes the deterministic (without the randomization factor) + calculated interval Td for a receiver, that is, with we_sent false. + Any other session member who has not sent an RTP or RTCP packet since + time tc - MTd (M is the timeout multiplier, and defaults to 5) is + timed out. This means that its SSRC is removed from the member list, + and members is updated. A similar check is performed on the sender + list. Any member on the sender list who has not sent an RTP packet + since time tc - 2T (within the last two RTCP report intervals) is + removed from the sender list, and senders is updated. + + If any members time out, the reverse reconsideration algorithm + described in Section 6.3.4 SHOULD be performed. + + The participant MUST perform this check at least once per RTCP + transmission interval. + +6.3.6 Expiration of Transmission Timer + + When the packet transmission timer expires, the participant performs + the following operations: + + o The transmission interval T is computed as described in Section + 6.3.1, including the randomization factor. + + o If tp + T is less than or equal to tc, an RTCP packet is + transmitted. tp is set to tc, then another value for T is + calculated as in the previous step and tn is set to tc + T. The + transmission timer is set to expire again at time tn. If tp + T + is greater than tc, tn is set to tp + T. No RTCP packet is + transmitted. The transmission timer is set to expire at time tn. + + + + +Schulzrinne, et al. Standards Track [Page 32] + +RFC 3550 RTP July 2003 + + + o pmembers is set to members. + + If an RTCP packet is transmitted, the value of initial is set to + FALSE. Furthermore, the value of avg_rtcp_size is updated: + + avg_rtcp_size = (1/16) * packet_size + (15/16) * avg_rtcp_size + + where packet_size is the size of the RTCP packet just transmitted. + +6.3.7 Transmitting a BYE Packet + + When a participant wishes to leave a session, a BYE packet is + transmitted to inform the other participants of the event. In order + to avoid a flood of BYE packets when many participants leave the + system, a participant MUST execute the following algorithm if the + number of members is more than 50 when the participant chooses to + leave. This algorithm usurps the normal role of the members variable + to count BYE packets instead: + + o When the participant decides to leave the system, tp is reset to + tc, the current time, members and pmembers are initialized to 1, + initial is set to 1, we_sent is set to false, senders is set to 0, + and avg_rtcp_size is set to the size of the compound BYE packet. + The calculated interval T is computed. The BYE packet is then + scheduled for time tn = tc + T. + + o Every time a BYE packet from another participant is received, + members is incremented by 1 regardless of whether that participant + exists in the member table or not, and when SSRC sampling is in + use, regardless of whether or not the BYE SSRC would be included + in the sample. members is NOT incremented when other RTCP packets + or RTP packets are received, but only for BYE packets. Similarly, + avg_rtcp_size is updated only for received BYE packets. senders + is NOT updated when RTP packets arrive; it remains 0. + + o Transmission of the BYE packet then follows the rules for + transmitting a regular RTCP packet, as above. + + This allows BYE packets to be sent right away, yet controls their + total bandwidth usage. In the worst case, this could cause RTCP + control packets to use twice the bandwidth as normal (10%) -- 5% for + non-BYE RTCP packets and 5% for BYE. + + A participant that does not want to wait for the above mechanism to + allow transmission of a BYE packet MAY leave the group without + sending a BYE at all. That participant will eventually be timed out + by the other group members. + + + + +Schulzrinne, et al. Standards Track [Page 33] + +RFC 3550 RTP July 2003 + + + If the group size estimate members is less than 50 when the + participant decides to leave, the participant MAY send a BYE packet + immediately. Alternatively, the participant MAY choose to execute + the above BYE backoff algorithm. + + In either case, a participant which never sent an RTP or RTCP packet + MUST NOT send a BYE packet when they leave the group. + +6.3.8 Updating we_sent + + The variable we_sent contains true if the participant has sent an RTP + packet recently, false otherwise. This determination is made by + using the same mechanisms as for managing the set of other + participants listed in the senders table. If the participant sends + an RTP packet when we_sent is false, it adds itself to the sender + table and sets we_sent to true. The reverse reconsideration + algorithm described in Section 6.3.4 SHOULD be performed to possibly + reduce the delay before sending an SR packet. Every time another RTP + packet is sent, the time of transmission of that packet is maintained + in the table. The normal sender timeout algorithm is then applied to + the participant -- if an RTP packet has not been transmitted since + time tc - 2T, the participant removes itself from the sender table, + decrements the sender count, and sets we_sent to false. + +6.3.9 Allocation of Source Description Bandwidth + + This specification defines several source description (SDES) items in + addition to the mandatory CNAME item, such as NAME (personal name) + and EMAIL (email address). It also provides a means to define new + application-specific RTCP packet types. Applications should exercise + caution in allocating control bandwidth to this additional + information because it will slow down the rate at which reception + reports and CNAME are sent, thus impairing the performance of the + protocol. It is RECOMMENDED that no more than 20% of the RTCP + bandwidth allocated to a single participant be used to carry the + additional information. Furthermore, it is not intended that all + SDES items will be included in every application. Those that are + included SHOULD be assigned a fraction of the bandwidth according to + their utility. Rather than estimate these fractions dynamically, it + is recommended that the percentages be translated statically into + report interval counts based on the typical length of an item. + + For example, an application may be designed to send only CNAME, NAME + and EMAIL and not any others. NAME might be given much higher + priority than EMAIL because the NAME would be displayed continuously + in the application's user interface, whereas EMAIL would be displayed + only when requested. At every RTCP interval, an RR packet and an + SDES packet with the CNAME item would be sent. For a small session + + + +Schulzrinne, et al. Standards Track [Page 34] + +RFC 3550 RTP July 2003 + + + operating at the minimum interval, that would be every 5 seconds on + the average. Every third interval (15 seconds), one extra item would + be included in the SDES packet. Seven out of eight times this would + be the NAME item, and every eighth time (2 minutes) it would be the + EMAIL item. + + When multiple applications operate in concert using cross-application + binding through a common CNAME for each participant, for example in a + multimedia conference composed of an RTP session for each medium, the + additional SDES information MAY be sent in only one RTP session. The + other sessions would carry only the CNAME item. In particular, this + approach should be applied to the multiple sessions of a layered + encoding scheme (see Section 2.4). + +6.4 Sender and Receiver Reports + + RTP receivers provide reception quality feedback using RTCP report + packets which may take one of two forms depending upon whether or not + the receiver is also a sender. The only difference between the + sender report (SR) and receiver report (RR) forms, besides the packet + type code, is that the sender report includes a 20-byte sender + information section for use by active senders. The SR is issued if a + site has sent any data packets during the interval since issuing the + last report or the previous one, otherwise the RR is issued. + + Both the SR and RR forms include zero or more reception report + blocks, one for each of the synchronization sources from which this + receiver has received RTP data packets since the last report. + Reports are not issued for contributing sources listed in the CSRC + list. Each reception report block provides statistics about the data + received from the particular source indicated in that block. Since a + maximum of 31 reception report blocks will fit in an SR or RR packet, + additional RR packets SHOULD be stacked after the initial SR or RR + packet as needed to contain the reception reports for all sources + heard during the interval since the last report. If there are too + many sources to fit all the necessary RR packets into one compound + RTCP packet without exceeding the MTU of the network path, then only + the subset that will fit into one MTU SHOULD be included in each + interval. The subsets SHOULD be selected round-robin across multiple + intervals so that all sources are reported. + + The next sections define the formats of the two reports, how they may + be extended in a profile-specific manner if an application requires + additional feedback information, and how the reports may be used. + Details of reception reporting by translators and mixers is given in + Section 7. + + + + + +Schulzrinne, et al. Standards Track [Page 35] + +RFC 3550 RTP July 2003 + + +6.4.1 SR: Sender Report RTCP Packet + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +header |V=2|P| RC | PT=SR=200 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of sender | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +sender | NTP timestamp, most significant word | +info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | NTP timestamp, least significant word | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | RTP timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | sender's packet count | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | sender's octet count | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_1 (SSRC of first source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1 | fraction lost | cumulative number of packets lost | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | extended highest sequence number received | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | interarrival jitter | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | last SR (LSR) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | delay since last SR (DLSR) | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_2 (SSRC of second source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 2 : ... : + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | profile-specific extensions | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The sender report packet consists of three sections, possibly + followed by a fourth profile-specific extension section if defined. + The first section, the header, is 8 octets long. The fields have the + following meaning: + + version (V): 2 bits + Identifies the version of RTP, which is the same in RTCP packets + as in RTP data packets. The version defined by this specification + is two (2). + + + + +Schulzrinne, et al. Standards Track [Page 36] + +RFC 3550 RTP July 2003 + + + padding (P): 1 bit + If the padding bit is set, this individual RTCP packet contains + some additional padding octets at the end which are not part of + the control information but are included in the length field. The + last octet of the padding is a count of how many padding octets + should be ignored, including itself (it will be a multiple of + four). Padding may be needed by some encryption algorithms with + fixed block sizes. In a compound RTCP packet, padding is only + required on one individual packet because the compound packet is + encrypted as a whole for the method in Section 9.1. Thus, padding + MUST only be added to the last individual packet, and if padding + is added to that packet, the padding bit MUST be set only on that + packet. This convention aids the header validity checks described + in Appendix A.2 and allows detection of packets from some early + implementations that incorrectly set the padding bit on the first + individual packet and add padding to the last individual packet. + + reception report count (RC): 5 bits + The number of reception report blocks contained in this packet. A + value of zero is valid. + + packet type (PT): 8 bits + Contains the constant 200 to identify this as an RTCP SR packet. + + length: 16 bits + The length of this RTCP packet in 32-bit words minus one, + including the header and any padding. (The offset of one makes + zero a valid length and avoids a possible infinite loop in + scanning a compound RTCP packet, while counting 32-bit words + avoids a validity check for a multiple of 4.) + + SSRC: 32 bits + The synchronization source identifier for the originator of this + SR packet. + + The second section, the sender information, is 20 octets long and is + present in every sender report packet. It summarizes the data + transmissions from this sender. The fields have the following + meaning: + + NTP timestamp: 64 bits + Indicates the wallclock time (see Section 4) when this report was + sent so that it may be used in combination with timestamps + returned in reception reports from other receivers to measure + round-trip propagation to those receivers. Receivers should + expect that the measurement accuracy of the timestamp may be + limited to far less than the resolution of the NTP timestamp. The + measurement uncertainty of the timestamp is not indicated as it + + + +Schulzrinne, et al. Standards Track [Page 37] + +RFC 3550 RTP July 2003 + + + may not be known. On a system that has no notion of wallclock + time but does have some system-specific clock such as "system + uptime", a sender MAY use that clock as a reference to calculate + relative NTP timestamps. It is important to choose a commonly + used clock so that if separate implementations are used to produce + the individual streams of a multimedia session, all + implementations will use the same clock. Until the year 2036, + relative and absolute timestamps will differ in the high bit so + (invalid) comparisons will show a large difference; by then one + hopes relative timestamps will no longer be needed. A sender that + has no notion of wallclock or elapsed time MAY set the NTP + timestamp to zero. + + RTP timestamp: 32 bits + Corresponds to the same time as the NTP timestamp (above), but in + the same units and with the same random offset as the RTP + timestamps in data packets. This correspondence may be used for + intra- and inter-media synchronization for sources whose NTP + timestamps are synchronized, and may be used by media-independent + receivers to estimate the nominal RTP clock frequency. Note that + in most cases this timestamp will not be equal to the RTP + timestamp in any adjacent data packet. Rather, it MUST be + calculated from the corresponding NTP timestamp using the + relationship between the RTP timestamp counter and real time as + maintained by periodically checking the wallclock time at a + sampling instant. + + sender's packet count: 32 bits + The total number of RTP data packets transmitted by the sender + since starting transmission up until the time this SR packet was + generated. The count SHOULD be reset if the sender changes its + SSRC identifier. + + sender's octet count: 32 bits + The total number of payload octets (i.e., not including header or + padding) transmitted in RTP data packets by the sender since + starting transmission up until the time this SR packet was + generated. The count SHOULD be reset if the sender changes its + SSRC identifier. This field can be used to estimate the average + payload data rate. + + The third section contains zero or more reception report blocks + depending on the number of other sources heard by this sender since + the last report. Each reception report block conveys statistics on + the reception of RTP packets from a single synchronization source. + Receivers SHOULD NOT carry over statistics when a source changes its + SSRC identifier due to a collision. These statistics are: + + + + +Schulzrinne, et al. Standards Track [Page 38] + +RFC 3550 RTP July 2003 + + + SSRC_n (source identifier): 32 bits + The SSRC identifier of the source to which the information in this + reception report block pertains. + + fraction lost: 8 bits + The fraction of RTP data packets from source SSRC_n lost since the + previous SR or RR packet was sent, expressed as a fixed point + number with the binary point at the left edge of the field. (That + is equivalent to taking the integer part after multiplying the + loss fraction by 256.) This fraction is defined to be the number + of packets lost divided by the number of packets expected, as + defined in the next paragraph. An implementation is shown in + Appendix A.3. If the loss is negative due to duplicates, the + fraction lost is set to zero. Note that a receiver cannot tell + whether any packets were lost after the last one received, and + that there will be no reception report block issued for a source + if all packets from that source sent during the last reporting + interval have been lost. + + cumulative number of packets lost: 24 bits + The total number of RTP data packets from source SSRC_n that have + been lost since the beginning of reception. This number is + defined to be the number of packets expected less the number of + packets actually received, where the number of packets received + includes any which are late or duplicates. Thus, packets that + arrive late are not counted as lost, and the loss may be negative + if there are duplicates. The number of packets expected is + defined to be the extended last sequence number received, as + defined next, less the initial sequence number received. This may + be calculated as shown in Appendix A.3. + + extended highest sequence number received: 32 bits + The low 16 bits contain the highest sequence number received in an + RTP data packet from source SSRC_n, and the most significant 16 + bits extend that sequence number with the corresponding count of + sequence number cycles, which may be maintained according to the + algorithm in Appendix A.1. Note that different receivers within + the same session will generate different extensions to the + sequence number if their start times differ significantly. + + interarrival jitter: 32 bits + An estimate of the statistical variance of the RTP data packet + interarrival time, measured in timestamp units and expressed as an + unsigned integer. The interarrival jitter J is defined to be the + mean deviation (smoothed absolute value) of the difference D in + packet spacing at the receiver compared to the sender for a pair + of packets. As shown in the equation below, this is equivalent to + the difference in the "relative transit time" for the two packets; + + + +Schulzrinne, et al. Standards Track [Page 39] + +RFC 3550 RTP July 2003 + + + the relative transit time is the difference between a packet's RTP + timestamp and the receiver's clock at the time of arrival, + measured in the same units. + + If Si is the RTP timestamp from packet i, and Ri is the time of + arrival in RTP timestamp units for packet i, then for two packets + i and j, D may be expressed as + + D(i,j) = (Rj - Ri) - (Sj - Si) = (Rj - Sj) - (Ri - Si) + + The interarrival jitter SHOULD be calculated continuously as each + data packet i is received from source SSRC_n, using this + difference D for that packet and the previous packet i-1 in order + of arrival (not necessarily in sequence), according to the formula + + J(i) = J(i-1) + (|D(i-1,i)| - J(i-1))/16 + + Whenever a reception report is issued, the current value of J is + sampled. + + The jitter calculation MUST conform to the formula specified here + in order to allow profile-independent monitors to make valid + interpretations of reports coming from different implementations. + This algorithm is the optimal first-order estimator and the gain + parameter 1/16 gives a good noise reduction ratio while + maintaining a reasonable rate of convergence [22]. A sample + implementation is shown in Appendix A.8. See Section 6.4.4 for a + discussion of the effects of varying packet duration and delay + before transmission. + + last SR timestamp (LSR): 32 bits + The middle 32 bits out of 64 in the NTP timestamp (as explained in + Section 4) received as part of the most recent RTCP sender report + (SR) packet from source SSRC_n. If no SR has been received yet, + the field is set to zero. + + delay since last SR (DLSR): 32 bits + The delay, expressed in units of 1/65536 seconds, between + receiving the last SR packet from source SSRC_n and sending this + reception report block. If no SR packet has been received yet + from SSRC_n, the DLSR field is set to zero. + + Let SSRC_r denote the receiver issuing this receiver report. + Source SSRC_n can compute the round-trip propagation delay to + SSRC_r by recording the time A when this reception report block is + received. It calculates the total round-trip time A-LSR using the + last SR timestamp (LSR) field, and then subtracting this field to + leave the round-trip propagation delay as (A - LSR - DLSR). This + + + +Schulzrinne, et al. Standards Track [Page 40] + +RFC 3550 RTP July 2003 + + + is illustrated in Fig. 2. Times are shown in both a hexadecimal + representation of the 32-bit fields and the equivalent floating- + point decimal representation. Colons indicate a 32-bit field + divided into a 16-bit integer part and 16-bit fraction part. + + This may be used as an approximate measure of distance to cluster + receivers, although some links have very asymmetric delays. + + [10 Nov 1995 11:33:25.125 UTC] [10 Nov 1995 11:33:36.5 UTC] + n SR(n) A=b710:8000 (46864.500 s) + ----------------------------------------------------------------> + v ^ + ntp_sec =0xb44db705 v ^ dlsr=0x0005:4000 ( 5.250s) + ntp_frac=0x20000000 v ^ lsr =0xb705:2000 (46853.125s) + (3024992005.125 s) v ^ + r v ^ RR(n) + ----------------------------------------------------------------> + |<-DLSR->| + (5.250 s) + + A 0xb710:8000 (46864.500 s) + DLSR -0x0005:4000 ( 5.250 s) + LSR -0xb705:2000 (46853.125 s) + ------------------------------- + delay 0x0006:2000 ( 6.125 s) + + Figure 2: Example for round-trip time computation + + + + + + + + + + + + + + + + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 41] + +RFC 3550 RTP July 2003 + + +6.4.2 RR: Receiver Report RTCP Packet + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +header |V=2|P| RC | PT=RR=201 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC of packet sender | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_1 (SSRC of first source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1 | fraction lost | cumulative number of packets lost | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | extended highest sequence number received | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | interarrival jitter | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | last SR (LSR) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | delay since last SR (DLSR) | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +report | SSRC_2 (SSRC of second source) | +block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 2 : ... : + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | profile-specific extensions | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The format of the receiver report (RR) packet is the same as that of + the SR packet except that the packet type field contains the constant + 201 and the five words of sender information are omitted (these are + the NTP and RTP timestamps and sender's packet and octet counts). + The remaining fields have the same meaning as for the SR packet. + + An empty RR packet (RC = 0) MUST be put at the head of a compound + RTCP packet when there is no data transmission or reception to + report. + +6.4.3 Extending the Sender and Receiver Reports + + A profile SHOULD define profile-specific extensions to the sender + report and receiver report if there is additional information that + needs to be reported regularly about the sender or receivers. This + method SHOULD be used in preference to defining another RTCP packet + type because it requires less overhead: + + o fewer octets in the packet (no RTCP header or SSRC field); + + + + +Schulzrinne, et al. Standards Track [Page 42] + +RFC 3550 RTP July 2003 + + + o simpler and faster parsing because applications running under that + profile would be programmed to always expect the extension fields + in the directly accessible location after the reception reports. + + The extension is a fourth section in the sender- or receiver-report + packet which comes at the end after the reception report blocks, if + any. If additional sender information is required, then for sender + reports it would be included first in the extension section, but for + receiver reports it would not be present. If information about + receivers is to be included, that data SHOULD be structured as an + array of blocks parallel to the existing array of reception report + blocks; that is, the number of blocks would be indicated by the RC + field. + +6.4.4 Analyzing Sender and Receiver Reports + + It is expected that reception quality feedback will be useful not + only for the sender but also for other receivers and third-party + monitors. The sender may modify its transmissions based on the + feedback; receivers can determine whether problems are local, + regional or global; network managers may use profile-independent + monitors that receive only the RTCP packets and not the corresponding + RTP data packets to evaluate the performance of their networks for + multicast distribution. + + Cumulative counts are used in both the sender information and + receiver report blocks so that differences may be calculated between + any two reports to make measurements over both short and long time + periods, and to provide resilience against the loss of a report. The + difference between the last two reports received can be used to + estimate the recent quality of the distribution. The NTP timestamp + is included so that rates may be calculated from these differences + over the interval between two reports. Since that timestamp is + independent of the clock rate for the data encoding, it is possible + to implement encoding- and profile-independent quality monitors. + + An example calculation is the packet loss rate over the interval + between two reception reports. The difference in the cumulative + number of packets lost gives the number lost during that interval. + The difference in the extended last sequence numbers received gives + the number of packets expected during the interval. The ratio of + these two is the packet loss fraction over the interval. This ratio + should equal the fraction lost field if the two reports are + consecutive, but otherwise it may not. The loss rate per second can + be obtained by dividing the loss fraction by the difference in NTP + timestamps, expressed in seconds. The number of packets received is + the number of packets expected minus the number lost. The number of + + + + +Schulzrinne, et al. Standards Track [Page 43] + +RFC 3550 RTP July 2003 + + + packets expected may also be used to judge the statistical validity + of any loss estimates. For example, 1 out of 5 packets lost has a + lower significance than 200 out of 1000. + + From the sender information, a third-party monitor can calculate the + average payload data rate and the average packet rate over an + interval without receiving the data. Taking the ratio of the two + gives the average payload size. If it can be assumed that packet + loss is independent of packet size, then the number of packets + received by a particular receiver times the average payload size (or + the corresponding packet size) gives the apparent throughput + available to that receiver. + + In addition to the cumulative counts which allow long-term packet + loss measurements using differences between reports, the fraction + lost field provides a short-term measurement from a single report. + This becomes more important as the size of a session scales up enough + that reception state information might not be kept for all receivers + or the interval between reports becomes long enough that only one + report might have been received from a particular receiver. + + The interarrival jitter field provides a second short-term measure of + network congestion. Packet loss tracks persistent congestion while + the jitter measure tracks transient congestion. The jitter measure + may indicate congestion before it leads to packet loss. The + interarrival jitter field is only a snapshot of the jitter at the + time of a report and is not intended to be taken quantitatively. + Rather, it is intended for comparison across a number of reports from + one receiver over time or from multiple receivers, e.g., within a + single network, at the same time. To allow comparison across + receivers, it is important the the jitter be calculated according to + the same formula by all receivers. + + Because the jitter calculation is based on the RTP timestamp which + represents the instant when the first data in the packet was sampled, + any variation in the delay between that sampling instant and the time + the packet is transmitted will affect the resulting jitter that is + calculated. Such a variation in delay would occur for audio packets + of varying duration. It will also occur for video encodings because + the timestamp is the same for all the packets of one frame but those + packets are not all transmitted at the same time. The variation in + delay until transmission does reduce the accuracy of the jitter + calculation as a measure of the behavior of the network by itself, + but it is appropriate to include considering that the receiver buffer + must accommodate it. When the jitter calculation is used as a + comparative measure, the (constant) component due to variation in + delay until transmission subtracts out so that a change in the + + + + +Schulzrinne, et al. Standards Track [Page 44] + +RFC 3550 RTP July 2003 + + + network jitter component can then be observed unless it is relatively + small. If the change is small, then it is likely to be + inconsequential. + +6.5 SDES: Source Description RTCP Packet + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +header |V=2|P| SC | PT=SDES=202 | length | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +chunk | SSRC/CSRC_1 | + 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SDES items | + | ... | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +chunk | SSRC/CSRC_2 | + 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SDES items | + | ... | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + + The SDES packet is a three-level structure composed of a header and + zero or more chunks, each of which is composed of items describing + the source identified in that chunk. The items are described + individually in subsequent sections. + + version (V), padding (P), length: + As described for the SR packet (see Section 6.4.1). + + packet type (PT): 8 bits + Contains the constant 202 to identify this as an RTCP SDES packet. + + source count (SC): 5 bits + The number of SSRC/CSRC chunks contained in this SDES packet. A + value of zero is valid but useless. + + Each chunk consists of an SSRC/CSRC identifier followed by a list of + zero or more items, which carry information about the SSRC/CSRC. + Each chunk starts on a 32-bit boundary. Each item consists of an 8- + bit type field, an 8-bit octet count describing the length of the + text (thus, not including this two-octet header), and the text + itself. Note that the text can be no longer than 255 octets, but + this is consistent with the need to limit RTCP bandwidth consumption. + + + + + + + +Schulzrinne, et al. Standards Track [Page 45] + +RFC 3550 RTP July 2003 + + + The text is encoded according to the UTF-8 encoding specified in RFC + 2279 [5]. US-ASCII is a subset of this encoding and requires no + additional encoding. The presence of multi-octet encodings is + indicated by setting the most significant bit of a character to a + value of one. + + Items are contiguous, i.e., items are not individually padded to a + 32-bit boundary. Text is not null terminated because some multi- + octet encodings include null octets. The list of items in each chunk + MUST be terminated by one or more null octets, the first of which is + interpreted as an item type of zero to denote the end of the list. + No length octet follows the null item type octet, but additional null + octets MUST be included if needed to pad until the next 32-bit + boundary. Note that this padding is separate from that indicated by + the P bit in the RTCP header. A chunk with zero items (four null + octets) is valid but useless. + + End systems send one SDES packet containing their own source + identifier (the same as the SSRC in the fixed RTP header). A mixer + sends one SDES packet containing a chunk for each contributing source + from which it is receiving SDES information, or multiple complete + SDES packets in the format above if there are more than 31 such + sources (see Section 7). + + The SDES items currently defined are described in the next sections. + Only the CNAME item is mandatory. Some items shown here may be + useful only for particular profiles, but the item types are all + assigned from one common space to promote shared use and to simplify + profile-independent applications. Additional items may be defined in + a profile by registering the type numbers with IANA as described in + Section 15. + +6.5.1 CNAME: Canonical End-Point Identifier SDES Item + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | CNAME=1 | length | user and domain name ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The CNAME identifier has the following properties: + + o Because the randomly allocated SSRC identifier may change if a + conflict is discovered or if a program is restarted, the CNAME + item MUST be included to provide the binding from the SSRC + identifier to an identifier for the source (sender or receiver) + that remains constant. + + + + +Schulzrinne, et al. Standards Track [Page 46] + +RFC 3550 RTP July 2003 + + + o Like the SSRC identifier, the CNAME identifier SHOULD also be + unique among all participants within one RTP session. + + o To provide a binding across multiple media tools used by one + participant in a set of related RTP sessions, the CNAME SHOULD be + fixed for that participant. + + o To facilitate third-party monitoring, the CNAME SHOULD be suitable + for either a program or a person to locate the source. + + Therefore, the CNAME SHOULD be derived algorithmically and not + entered manually, when possible. To meet these requirements, the + following format SHOULD be used unless a profile specifies an + alternate syntax or semantics. The CNAME item SHOULD have the format + "user@host", or "host" if a user name is not available as on single- + user systems. For both formats, "host" is either the fully qualified + domain name of the host from which the real-time data originates, + formatted according to the rules specified in RFC 1034 [6], RFC 1035 + [7] and Section 2.1 of RFC 1123 [8]; or the standard ASCII + representation of the host's numeric address on the interface used + for the RTP communication. For example, the standard ASCII + representation of an IP Version 4 address is "dotted decimal", also + known as dotted quad, and for IP Version 6, addresses are textually + represented as groups of hexadecimal digits separated by colons (with + variations as detailed in RFC 3513 [23]). Other address types are + expected to have ASCII representations that are mutually unique. The + fully qualified domain name is more convenient for a human observer + and may avoid the need to send a NAME item in addition, but it may be + difficult or impossible to obtain reliably in some operating + environments. Applications that may be run in such environments + SHOULD use the ASCII representation of the address instead. + + Examples are "doe@sleepy.example.com", "doe@192.0.2.89" or + "doe@2201:056D::112E:144A:1E24" for a multi-user system. On a system + with no user name, examples would be "sleepy.example.com", + "192.0.2.89" or "2201:056D::112E:144A:1E24". + + The user name SHOULD be in a form that a program such as "finger" or + "talk" could use, i.e., it typically is the login name rather than + the personal name. The host name is not necessarily identical to the + one in the participant's electronic mail address. + + This syntax will not provide unique identifiers for each source if an + application permits a user to generate multiple sources from one + host. Such an application would have to rely on the SSRC to further + identify the source, or the profile for that application would have + to specify additional syntax for the CNAME identifier. + + + + +Schulzrinne, et al. Standards Track [Page 47] + +RFC 3550 RTP July 2003 + + + If each application creates its CNAME independently, the resulting + CNAMEs may not be identical as would be required to provide a binding + across multiple media tools belonging to one participant in a set of + related RTP sessions. If cross-media binding is required, it may be + necessary for the CNAME of each tool to be externally configured with + the same value by a coordination tool. + + Application writers should be aware that private network address + assignments such as the Net-10 assignment proposed in RFC 1918 [24] + may create network addresses that are not globally unique. This + would lead to non-unique CNAMEs if hosts with private addresses and + no direct IP connectivity to the public Internet have their RTP + packets forwarded to the public Internet through an RTP-level + translator. (See also RFC 1627 [25].) To handle this case, + applications MAY provide a means to configure a unique CNAME, but the + burden is on the translator to translate CNAMEs from private + addresses to public addresses if necessary to keep private addresses + from being exposed. + +6.5.2 NAME: User Name SDES Item + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | NAME=2 | length | common name of source ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + This is the real name used to describe the source, e.g., "John Doe, + Bit Recycler". It may be in any form desired by the user. For + applications such as conferencing, this form of name may be the most + desirable for display in participant lists, and therefore might be + sent most frequently of those items other than CNAME. Profiles MAY + establish such priorities. The NAME value is expected to remain + constant at least for the duration of a session. It SHOULD NOT be + relied upon to be unique among all participants in the session. + +6.5.3 EMAIL: Electronic Mail Address SDES Item + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | EMAIL=3 | length | email address of source ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The email address is formatted according to RFC 2822 [9], for + example, "John.Doe@example.com". The EMAIL value is expected to + remain constant for the duration of a session. + + + + +Schulzrinne, et al. Standards Track [Page 48] + +RFC 3550 RTP July 2003 + + +6.5.4 PHONE: Phone Number SDES Item + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | PHONE=4 | length | phone number of source ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The phone number SHOULD be formatted with the plus sign replacing the + international access code. For example, "+1 908 555 1212" for a + number in the United States. + +6.5.5 LOC: Geographic User Location SDES Item + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | LOC=5 | length | geographic location of site ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Depending on the application, different degrees of detail are + appropriate for this item. For conference applications, a string + like "Murray Hill, New Jersey" may be sufficient, while, for an + active badge system, strings like "Room 2A244, AT&T BL MH" might be + appropriate. The degree of detail is left to the implementation + and/or user, but format and content MAY be prescribed by a profile. + The LOC value is expected to remain constant for the duration of a + session, except for mobile hosts. + +6.5.6 TOOL: Application or Tool Name SDES Item + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | TOOL=6 | length |name/version of source appl. ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + A string giving the name and possibly version of the application + generating the stream, e.g., "videotool 1.2". This information may + be useful for debugging purposes and is similar to the Mailer or + Mail-System-Version SMTP headers. The TOOL value is expected to + remain constant for the duration of the session. + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 49] + +RFC 3550 RTP July 2003 + + +6.5.7 NOTE: Notice/Status SDES Item + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | NOTE=7 | length | note about the source ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The following semantics are suggested for this item, but these or + other semantics MAY be explicitly defined by a profile. The NOTE + item is intended for transient messages describing the current state + of the source, e.g., "on the phone, can't talk". Or, during a + seminar, this item might be used to convey the title of the talk. It + should be used only to carry exceptional information and SHOULD NOT + be included routinely by all participants because this would slow + down the rate at which reception reports and CNAME are sent, thus + impairing the performance of the protocol. In particular, it SHOULD + NOT be included as an item in a user's configuration file nor + automatically generated as in a quote-of-the-day. + + Since the NOTE item may be important to display while it is active, + the rate at which other non-CNAME items such as NAME are transmitted + might be reduced so that the NOTE item can take that part of the RTCP + bandwidth. When the transient message becomes inactive, the NOTE + item SHOULD continue to be transmitted a few times at the same + repetition rate but with a string of length zero to signal the + receivers. However, receivers SHOULD also consider the NOTE item + inactive if it is not received for a small multiple of the repetition + rate, or perhaps 20-30 RTCP intervals. + +6.5.8 PRIV: Private Extensions SDES Item + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | PRIV=8 | length | prefix length |prefix string... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ... | value string ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + This item is used to define experimental or application-specific SDES + extensions. The item contains a prefix consisting of a length-string + pair, followed by the value string filling the remainder of the item + and carrying the desired information. The prefix length field is 8 + bits long. The prefix string is a name chosen by the person defining + the PRIV item to be unique with respect to other PRIV items this + application might receive. The application creator might choose to + use the application name plus an additional subtype identification if + + + +Schulzrinne, et al. Standards Track [Page 50] + +RFC 3550 RTP July 2003 + + + needed. Alternatively, it is RECOMMENDED that others choose a name + based on the entity they represent, then coordinate the use of the + name within that entity. + + Note that the prefix consumes some space within the item's total + length of 255 octets, so the prefix should be kept as short as + possible. This facility and the constrained RTCP bandwidth SHOULD + NOT be overloaded; it is not intended to satisfy all the control + communication requirements of all applications. + + SDES PRIV prefixes will not be registered by IANA. If some form of + the PRIV item proves to be of general utility, it SHOULD instead be + assigned a regular SDES item type registered with IANA so that no + prefix is required. This simplifies use and increases transmission + efficiency. + +6.6 BYE: Goodbye RTCP Packet + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| SC | PT=BYE=203 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC/CSRC | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + : ... : + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +(opt) | length | reason for leaving ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The BYE packet indicates that one or more sources are no longer + active. + + version (V), padding (P), length: + As described for the SR packet (see Section 6.4.1). + + packet type (PT): 8 bits + Contains the constant 203 to identify this as an RTCP BYE packet. + + source count (SC): 5 bits + The number of SSRC/CSRC identifiers included in this BYE packet. + A count value of zero is valid, but useless. + + The rules for when a BYE packet should be sent are specified in + Sections 6.3.7 and 8.2. + + + + + + +Schulzrinne, et al. Standards Track [Page 51] + +RFC 3550 RTP July 2003 + + + If a BYE packet is received by a mixer, the mixer SHOULD forward the + BYE packet with the SSRC/CSRC identifier(s) unchanged. If a mixer + shuts down, it SHOULD send a BYE packet listing all contributing + sources it handles, as well as its own SSRC identifier. Optionally, + the BYE packet MAY include an 8-bit octet count followed by that many + octets of text indicating the reason for leaving, e.g., "camera + malfunction" or "RTP loop detected". The string has the same + encoding as that described for SDES. If the string fills the packet + to the next 32-bit boundary, the string is not null terminated. If + not, the BYE packet MUST be padded with null octets to the next 32- + bit boundary. This padding is separate from that indicated by the P + bit in the RTCP header. + +6.7 APP: Application-Defined RTCP Packet + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| subtype | PT=APP=204 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC/CSRC | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | name (ASCII) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | application-dependent data ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The APP packet is intended for experimental use as new applications + and new features are developed, without requiring packet type value + registration. APP packets with unrecognized names SHOULD be ignored. + After testing and if wider use is justified, it is RECOMMENDED that + each APP packet be redefined without the subtype and name fields and + registered with IANA using an RTCP packet type. + + version (V), padding (P), length: + As described for the SR packet (see Section 6.4.1). + + subtype: 5 bits + May be used as a subtype to allow a set of APP packets to be + defined under one unique name, or for any application-dependent + data. + + packet type (PT): 8 bits + Contains the constant 204 to identify this as an RTCP APP packet. + + + + + + + +Schulzrinne, et al. Standards Track [Page 52] + +RFC 3550 RTP July 2003 + + + name: 4 octets + A name chosen by the person defining the set of APP packets to be + unique with respect to other APP packets this application might + receive. The application creator might choose to use the + application name, and then coordinate the allocation of subtype + values to others who want to define new packet types for the + application. Alternatively, it is RECOMMENDED that others choose + a name based on the entity they represent, then coordinate the use + of the name within that entity. The name is interpreted as a + sequence of four ASCII characters, with uppercase and lowercase + characters treated as distinct. + + application-dependent data: variable length + Application-dependent data may or may not appear in an APP packet. + It is interpreted by the application and not RTP itself. It MUST + be a multiple of 32 bits long. + +7. RTP Translators and Mixers + + In addition to end systems, RTP supports the notion of "translators" + and "mixers", which could be considered as "intermediate systems" at + the RTP level. Although this support adds some complexity to the + protocol, the need for these functions has been clearly established + by experiments with multicast audio and video applications in the + Internet. Example uses of translators and mixers given in Section + 2.3 stem from the presence of firewalls and low bandwidth + connections, both of which are likely to remain. + +7.1 General Description + + An RTP translator/mixer connects two or more transport-level + "clouds". Typically, each cloud is defined by a common network and + transport protocol (e.g., IP/UDP) plus a multicast address and + transport level destination port or a pair of unicast addresses and + ports. (Network-level protocol translators, such as IP version 4 to + IP version 6, may be present within a cloud invisibly to RTP.) One + system may serve as a translator or mixer for a number of RTP + sessions, but each is considered a logically separate entity. + + In order to avoid creating a loop when a translator or mixer is + installed, the following rules MUST be observed: + + o Each of the clouds connected by translators and mixers + participating in one RTP session either MUST be distinct from all + the others in at least one of these parameters (protocol, address, + port), or MUST be isolated at the network level from the others. + + + + + +Schulzrinne, et al. Standards Track [Page 53] + +RFC 3550 RTP July 2003 + + + o A derivative of the first rule is that there MUST NOT be multiple + translators or mixers connected in parallel unless by some + arrangement they partition the set of sources to be forwarded. + + Similarly, all RTP end systems that can communicate through one or + more RTP translators or mixers share the same SSRC space, that is, + the SSRC identifiers MUST be unique among all these end systems. + Section 8.2 describes the collision resolution algorithm by which + SSRC identifiers are kept unique and loops are detected. + + There may be many varieties of translators and mixers designed for + different purposes and applications. Some examples are to add or + remove encryption, change the encoding of the data or the underlying + protocols, or replicate between a multicast address and one or more + unicast addresses. The distinction between translators and mixers is + that a translator passes through the data streams from different + sources separately, whereas a mixer combines them to form one new + stream: + + Translator: Forwards RTP packets with their SSRC identifier + intact; this makes it possible for receivers to identify + individual sources even though packets from all the sources pass + through the same translator and carry the translator's network + source address. Some kinds of translators will pass through the + data untouched, but others MAY change the encoding of the data and + thus the RTP data payload type and timestamp. If multiple data + packets are re-encoded into one, or vice versa, a translator MUST + assign new sequence numbers to the outgoing packets. Losses in + the incoming packet stream may induce corresponding gaps in the + outgoing sequence numbers. Receivers cannot detect the presence + of a translator unless they know by some other means what payload + type or transport address was used by the original source. + + Mixer: Receives streams of RTP data packets from one or more + sources, possibly changes the data format, combines the streams in + some manner and then forwards the combined stream. Since the + timing among multiple input sources will not generally be + synchronized, the mixer will make timing adjustments among the + streams and generate its own timing for the combined stream, so it + is the synchronization source. Thus, all data packets forwarded + by a mixer MUST be marked with the mixer's own SSRC identifier. + In order to preserve the identity of the original sources + contributing to the mixed packet, the mixer SHOULD insert their + SSRC identifiers into the CSRC identifier list following the fixed + RTP header of the packet. A mixer that is also itself a + contributing source for some packet SHOULD explicitly include its + own SSRC identifier in the CSRC list for that packet. + + + + +Schulzrinne, et al. Standards Track [Page 54] + +RFC 3550 RTP July 2003 + + + For some applications, it MAY be acceptable for a mixer not to + identify sources in the CSRC list. However, this introduces the + danger that loops involving those sources could not be detected. + + The advantage of a mixer over a translator for applications like + audio is that the output bandwidth is limited to that of one source + even when multiple sources are active on the input side. This may be + important for low-bandwidth links. The disadvantage is that + receivers on the output side don't have any control over which + sources are passed through or muted, unless some mechanism is + implemented for remote control of the mixer. The regeneration of + synchronization information by mixers also means that receivers can't + do inter-media synchronization of the original streams. A multi- + media mixer could do it. + + [E1] [E6] + | | + E1:17 | E6:15 | + | | E6:15 + V M1:48 (1,17) M1:48 (1,17) V M1:48 (1,17) + (M1)------------->----------------->-------------->[E7] + ^ ^ E4:47 ^ E4:47 + E2:1 | E4:47 | | M3:89 (64,45) + | | | + [E2] [E4] M3:89 (64,45) | + | legend: + [E3] --------->(M2)----------->(M3)------------| [End system] + E3:64 M2:12 (64) ^ (Mixer) + | E5:45 + | + [E5] source: SSRC (CSRCs) + -------------------> + + Figure 3: Sample RTP network with end systems, mixers and translators + + A collection of mixers and translators is shown in Fig. 3 to + illustrate their effect on SSRC and CSRC identifiers. In the figure, + end systems are shown as rectangles (named E), translators as + triangles (named T) and mixers as ovals (named M). The notation "M1: + 48(1,17)" designates a packet originating a mixer M1, identified by + M1's (random) SSRC value of 48 and two CSRC identifiers, 1 and 17, + copied from the SSRC identifiers of packets from E1 and E2. + +7.2 RTCP Processing in Translators + + In addition to forwarding data packets, perhaps modified, translators + and mixers MUST also process RTCP packets. In many cases, they will + take apart the compound RTCP packets received from end systems to + + + +Schulzrinne, et al. Standards Track [Page 55] + +RFC 3550 RTP July 2003 + + + aggregate SDES information and to modify the SR or RR packets. + Retransmission of this information may be triggered by the packet + arrival or by the RTCP interval timer of the translator or mixer + itself. + + A translator that does not modify the data packets, for example one + that just replicates between a multicast address and a unicast + address, MAY simply forward RTCP packets unmodified as well. A + translator that transforms the payload in some way MUST make + corresponding transformations in the SR and RR information so that it + still reflects the characteristics of the data and the reception + quality. These translators MUST NOT simply forward RTCP packets. In + general, a translator SHOULD NOT aggregate SR and RR packets from + different sources into one packet since that would reduce the + accuracy of the propagation delay measurements based on the LSR and + DLSR fields. + + SR sender information: A translator does not generate its own + sender information, but forwards the SR packets received from one + cloud to the others. The SSRC is left intact but the sender + information MUST be modified if required by the translation. If a + translator changes the data encoding, it MUST change the "sender's + byte count" field. If it also combines several data packets into + one output packet, it MUST change the "sender's packet count" + field. If it changes the timestamp frequency, it MUST change the + "RTP timestamp" field in the SR packet. + + SR/RR reception report blocks: A translator forwards reception + reports received from one cloud to the others. Note that these + flow in the direction opposite to the data. The SSRC is left + intact. If a translator combines several data packets into one + output packet, and therefore changes the sequence numbers, it MUST + make the inverse manipulation for the packet loss fields and the + "extended last sequence number" field. This may be complex. In + the extreme case, there may be no meaningful way to translate the + reception reports, so the translator MAY pass on no reception + report at all or a synthetic report based on its own reception. + The general rule is to do what makes sense for a particular + translation. + + A translator does not require an SSRC identifier of its own, but + MAY choose to allocate one for the purpose of sending reports + about what it has received. These would be sent to all the + connected clouds, each corresponding to the translation of the + data stream as sent to that cloud, since reception reports are + normally multicast to all participants. + + + + + +Schulzrinne, et al. Standards Track [Page 56] + +RFC 3550 RTP July 2003 + + + SDES: Translators typically forward without change the SDES + information they receive from one cloud to the others, but MAY, + for example, decide to filter non-CNAME SDES information if + bandwidth is limited. The CNAMEs MUST be forwarded to allow SSRC + identifier collision detection to work. A translator that + generates its own RR packets MUST send SDES CNAME information + about itself to the same clouds that it sends those RR packets. + + BYE: Translators forward BYE packets unchanged. A translator + that is about to cease forwarding packets SHOULD send a BYE packet + to each connected cloud containing all the SSRC identifiers that + were previously being forwarded to that cloud, including the + translator's own SSRC identifier if it sent reports of its own. + + APP: Translators forward APP packets unchanged. + +7.3 RTCP Processing in Mixers + + Since a mixer generates a new data stream of its own, it does not + pass through SR or RR packets at all and instead generates new + information for both sides. + + SR sender information: A mixer does not pass through sender + information from the sources it mixes because the characteristics + of the source streams are lost in the mix. As a synchronization + source, the mixer SHOULD generate its own SR packets with sender + information about the mixed data stream and send them in the same + direction as the mixed stream. + + SR/RR reception report blocks: A mixer generates its own + reception reports for sources in each cloud and sends them out + only to the same cloud. It MUST NOT send these reception reports + to the other clouds and MUST NOT forward reception reports from + one cloud to the others because the sources would not be SSRCs + there (only CSRCs). + + SDES: Mixers typically forward without change the SDES + information they receive from one cloud to the others, but MAY, + for example, decide to filter non-CNAME SDES information if + bandwidth is limited. The CNAMEs MUST be forwarded to allow SSRC + identifier collision detection to work. (An identifier in a CSRC + list generated by a mixer might collide with an SSRC identifier + generated by an end system.) A mixer MUST send SDES CNAME + information about itself to the same clouds that it sends SR or RR + packets. + + + + + + +Schulzrinne, et al. Standards Track [Page 57] + +RFC 3550 RTP July 2003 + + + Since mixers do not forward SR or RR packets, they will typically + be extracting SDES packets from a compound RTCP packet. To + minimize overhead, chunks from the SDES packets MAY be aggregated + into a single SDES packet which is then stacked on an SR or RR + packet originating from the mixer. A mixer which aggregates SDES + packets will use more RTCP bandwidth than an individual source + because the compound packets will be longer, but that is + appropriate since the mixer represents multiple sources. + Similarly, a mixer which passes through SDES packets as they are + received will be transmitting RTCP packets at higher than the + single source rate, but again that is correct since the packets + come from multiple sources. The RTCP packet rate may be different + on each side of the mixer. + + A mixer that does not insert CSRC identifiers MAY also refrain + from forwarding SDES CNAMEs. In this case, the SSRC identifier + spaces in the two clouds are independent. As mentioned earlier, + this mode of operation creates a danger that loops can't be + detected. + + BYE: Mixers MUST forward BYE packets. A mixer that is about to + cease forwarding packets SHOULD send a BYE packet to each + connected cloud containing all the SSRC identifiers that were + previously being forwarded to that cloud, including the mixer's + own SSRC identifier if it sent reports of its own. + + APP: The treatment of APP packets by mixers is application-specific. + +7.4 Cascaded Mixers + + An RTP session may involve a collection of mixers and translators as + shown in Fig. 3. If two mixers are cascaded, such as M2 and M3 in + the figure, packets received by a mixer may already have been mixed + and may include a CSRC list with multiple identifiers. The second + mixer SHOULD build the CSRC list for the outgoing packet using the + CSRC identifiers from already-mixed input packets and the SSRC + identifiers from unmixed input packets. This is shown in the output + arc from mixer M3 labeled M3:89(64,45) in the figure. As in the case + of mixers that are not cascaded, if the resulting CSRC list has more + than 15 identifiers, the remainder cannot be included. + + + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 58] + +RFC 3550 RTP July 2003 + + +8. SSRC Identifier Allocation and Use + + The SSRC identifier carried in the RTP header and in various fields + of RTCP packets is a random 32-bit number that is required to be + globally unique within an RTP session. It is crucial that the number + be chosen with care in order that participants on the same network or + starting at the same time are not likely to choose the same number. + + It is not sufficient to use the local network address (such as an + IPv4 address) for the identifier because the address may not be + unique. Since RTP translators and mixers enable interoperation among + multiple networks with different address spaces, the allocation + patterns for addresses within two spaces might result in a much + higher rate of collision than would occur with random allocation. + + Multiple sources running on one host would also conflict. + + It is also not sufficient to obtain an SSRC identifier simply by + calling random() without carefully initializing the state. An + example of how to generate a random identifier is presented in + Appendix A.6. + +8.1 Probability of Collision + + Since the identifiers are chosen randomly, it is possible that two or + more sources will choose the same number. Collision occurs with the + highest probability when all sources are started simultaneously, for + example when triggered automatically by some session management + event. If N is the number of sources and L the length of the + identifier (here, 32 bits), the probability that two sources + independently pick the same value can be approximated for large N + [26] as 1 - exp(-N**2 / 2**(L+1)). For N=1000, the probability is + roughly 10**-4. + + The typical collision probability is much lower than the worst-case + above. When one new source joins an RTP session in which all the + other sources already have unique identifiers, the probability of + collision is just the fraction of numbers used out of the space. + Again, if N is the number of sources and L the length of the + identifier, the probability of collision is N / 2**L. For N=1000, + the probability is roughly 2*10**-7. + + The probability of collision is further reduced by the opportunity + for a new source to receive packets from other participants before + sending its first packet (either data or control). If the new source + keeps track of the other participants (by SSRC identifier), then + + + + + +Schulzrinne, et al. Standards Track [Page 59] + +RFC 3550 RTP July 2003 + + + before transmitting its first packet the new source can verify that + its identifier does not conflict with any that have been received, or + else choose again. + +8.2 Collision Resolution and Loop Detection + + Although the probability of SSRC identifier collision is low, all RTP + implementations MUST be prepared to detect collisions and take the + appropriate actions to resolve them. If a source discovers at any + time that another source is using the same SSRC identifier as its + own, it MUST send an RTCP BYE packet for the old identifier and + choose another random one. (As explained below, this step is taken + only once in case of a loop.) If a receiver discovers that two other + sources are colliding, it MAY keep the packets from one and discard + the packets from the other when this can be detected by different + source transport addresses or CNAMEs. The two sources are expected + to resolve the collision so that the situation doesn't last. + + Because the random SSRC identifiers are kept globally unique for each + RTP session, they can also be used to detect loops that may be + introduced by mixers or translators. A loop causes duplication of + data and control information, either unmodified or possibly mixed, as + in the following examples: + + o A translator may incorrectly forward a packet to the same + multicast group from which it has received the packet, either + directly or through a chain of translators. In that case, the + same packet appears several times, originating from different + network sources. + + o Two translators incorrectly set up in parallel, i.e., with the + same multicast groups on both sides, would both forward packets + from one multicast group to the other. Unidirectional translators + would produce two copies; bidirectional translators would form a + loop. + + o A mixer can close a loop by sending to the same transport + destination upon which it receives packets, either directly or + through another mixer or translator. In this case a source might + show up both as an SSRC on a data packet and a CSRC in a mixed + data packet. + + A source may discover that its own packets are being looped, or that + packets from another source are being looped (a third-party loop). + Both loops and collisions in the random selection of a source + identifier result in packets arriving with the same SSRC identifier + but a different source transport address, which may be that of the + end system originating the packet or an intermediate system. + + + +Schulzrinne, et al. Standards Track [Page 60] + +RFC 3550 RTP July 2003 + + + Therefore, if a source changes its source transport address, it MAY + also choose a new SSRC identifier to avoid being interpreted as a + looped source. (This is not MUST because in some applications of RTP + sources may be expected to change addresses during a session.) Note + that if a translator restarts and consequently changes the source + transport address (e.g., changes the UDP source port number) on which + it forwards packets, then all those packets will appear to receivers + to be looped because the SSRC identifiers are applied by the original + source and will not change. This problem can be avoided by keeping + the source transport address fixed across restarts, but in any case + will be resolved after a timeout at the receivers. + + Loops or collisions occurring on the far side of a translator or + mixer cannot be detected using the source transport address if all + copies of the packets go through the translator or mixer, however, + collisions may still be detected when chunks from two RTCP SDES + packets contain the same SSRC identifier but different CNAMEs. + + To detect and resolve these conflicts, an RTP implementation MUST + include an algorithm similar to the one described below, though the + implementation MAY choose a different policy for which packets from + colliding third-party sources are kept. The algorithm described + below ignores packets from a new source or loop that collide with an + established source. It resolves collisions with the participant's + own SSRC identifier by sending an RTCP BYE for the old identifier and + choosing a new one. However, when the collision was induced by a + loop of the participant's own packets, the algorithm will choose a + new identifier only once and thereafter ignore packets from the + looping source transport address. This is required to avoid a flood + of BYE packets. + + This algorithm requires keeping a table indexed by the source + identifier and containing the source transport addresses from the + first RTP packet and first RTCP packet received with that identifier, + along with other state for that source. Two source transport + addresses are required since, for example, the UDP source port + numbers may be different on RTP and RTCP packets. However, it may be + assumed that the network address is the same in both source transport + addresses. + + Each SSRC or CSRC identifier received in an RTP or RTCP packet is + looked up in the source identifier table in order to process that + data or control information. The source transport address from the + packet is compared to the corresponding source transport address in + the table to detect a loop or collision if they don't match. For + control packets, each element with its own SSRC identifier, for + example an SDES chunk, requires a separate lookup. (The SSRC + identifier in a reception report block is an exception because it + + + +Schulzrinne, et al. Standards Track [Page 61] + +RFC 3550 RTP July 2003 + + + identifies a source heard by the reporter, and that SSRC identifier + is unrelated to the source transport address of the RTCP packet sent + by the reporter.) If the SSRC or CSRC is not found, a new entry is + created. These table entries are removed when an RTCP BYE packet is + received with the corresponding SSRC identifier and validated by a + matching source transport address, or after no packets have arrived + for a relatively long time (see Section 6.2.1). + + Note that if two sources on the same host are transmitting with the + same source identifier at the time a receiver begins operation, it + would be possible that the first RTP packet received came from one of + the sources while the first RTCP packet received came from the other. + This would cause the wrong RTCP information to be associated with the + RTP data, but this situation should be sufficiently rare and harmless + that it may be disregarded. + + In order to track loops of the participant's own data packets, the + implementation MUST also keep a separate list of source transport + addresses (not identifiers) that have been found to be conflicting. + As in the source identifier table, two source transport addresses + MUST be kept to separately track conflicting RTP and RTCP packets. + Note that the conflicting address list should be short, usually + empty. Each element in this list stores the source addresses plus + the time when the most recent conflicting packet was received. An + element MAY be removed from the list when no conflicting packet has + arrived from that source for a time on the order of 10 RTCP report + intervals (see Section 6.2). + + For the algorithm as shown, it is assumed that the participant's own + source identifier and state are included in the source identifier + table. The algorithm could be restructured to first make a separate + comparison against the participant's own source identifier. + + if (SSRC or CSRC identifier is not found in the source + identifier table) { + create a new entry storing the data or control source + transport address, the SSRC or CSRC and other state; + } + + /* Identifier is found in the table */ + + else if (table entry was created on receipt of a control packet + and this is the first data packet or vice versa) { + store the source transport address from this packet; + } + else if (source transport address from the packet does not match + the one saved in the table entry for this identifier) { + + + + +Schulzrinne, et al. Standards Track [Page 62] + +RFC 3550 RTP July 2003 + + + /* An identifier collision or a loop is indicated */ + + if (source identifier is not the participant's own) { + /* OPTIONAL error counter step */ + if (source identifier is from an RTCP SDES chunk + containing a CNAME item that differs from the CNAME + in the table entry) { + count a third-party collision; + } else { + count a third-party loop; + } + abort processing of data packet or control element; + /* MAY choose a different policy to keep new source */ + } + + /* A collision or loop of the participant's own packets */ + + else if (source transport address is found in the list of + conflicting data or control source transport + addresses) { + /* OPTIONAL error counter step */ + if (source identifier is not from an RTCP SDES chunk + containing a CNAME item or CNAME is the + participant's own) { + count occurrence of own traffic looped; + } + mark current time in conflicting address list entry; + abort processing of data packet or control element; + } + + /* New collision, change SSRC identifier */ + + else { + log occurrence of a collision; + create a new entry in the conflicting data or control + source transport address list and mark current time; + send an RTCP BYE packet with the old SSRC identifier; + choose a new SSRC identifier; + create a new entry in the source identifier table with + the old SSRC plus the source transport address from + the data or control packet being processed; + } + } + + In this algorithm, packets from a newly conflicting source address + will be ignored and packets from the original source address will be + kept. If no packets arrive from the original source for an extended + period, the table entry will be timed out and the new source will be + + + +Schulzrinne, et al. Standards Track [Page 63] + +RFC 3550 RTP July 2003 + + + able to take over. This might occur if the original source detects + the collision and moves to a new source identifier, but in the usual + case an RTCP BYE packet will be received from the original source to + delete the state without having to wait for a timeout. + + If the original source address was received through a mixer (i.e., + learned as a CSRC) and later the same source is received directly, + the receiver may be well advised to switch to the new source address + unless other sources in the mix would be lost. Furthermore, for + applications such as telephony in which some sources such as mobile + entities may change addresses during the course of an RTP session, + the RTP implementation SHOULD modify the collision detection + algorithm to accept packets from the new source transport address. + To guard against flip-flopping between addresses if a genuine + collision does occur, the algorithm SHOULD include some means to + detect this case and avoid switching. + + When a new SSRC identifier is chosen due to a collision, the + candidate identifier SHOULD first be looked up in the source + identifier table to see if it was already in use by some other + source. If so, another candidate MUST be generated and the process + repeated. + + A loop of data packets to a multicast destination can cause severe + network flooding. All mixers and translators MUST implement a loop + detection algorithm like the one here so that they can break loops. + This should limit the excess traffic to no more than one duplicate + copy of the original traffic, which may allow the session to continue + so that the cause of the loop can be found and fixed. However, in + extreme cases where a mixer or translator does not properly break the + loop and high traffic levels result, it may be necessary for end + systems to cease transmitting data or control packets entirely. This + decision may depend upon the application. An error condition SHOULD + be indicated as appropriate. Transmission MAY be attempted again + periodically after a long, random time (on the order of minutes). + +8.3 Use with Layered Encodings + + For layered encodings transmitted on separate RTP sessions (see + Section 2.4), a single SSRC identifier space SHOULD be used across + the sessions of all layers and the core (base) layer SHOULD be used + for SSRC identifier allocation and collision resolution. When a + source discovers that it has collided, it transmits an RTCP BYE + packet on only the base layer but changes the SSRC identifier to the + new value in all layers. + + + + + + +Schulzrinne, et al. Standards Track [Page 64] + +RFC 3550 RTP July 2003 + + +9. Security + + Lower layer protocols may eventually provide all the security + services that may be desired for applications of RTP, including + authentication, integrity, and confidentiality. These services have + been specified for IP in [27]. Since the initial audio and video + applications using RTP needed a confidentiality service before such + services were available for the IP layer, the confidentiality service + described in the next section was defined for use with RTP and RTCP. + That description is included here to codify existing practice. New + applications of RTP MAY implement this RTP-specific confidentiality + service for backward compatibility, and/or they MAY implement + alternative security services. The overhead on the RTP protocol for + this confidentiality service is low, so the penalty will be minimal + if this service is obsoleted by other services in the future. + + Alternatively, other services, other implementations of services and + other algorithms may be defined for RTP in the future. In + particular, an RTP profile called Secure Real-time Transport Protocol + (SRTP) [28] is being developed to provide confidentiality of the RTP + payload while leaving the RTP header in the clear so that link-level + header compression algorithms can still operate. It is expected that + SRTP will be the correct choice for many applications. SRTP is based + on the Advanced Encryption Standard (AES) and provides stronger + security than the service described here. No claim is made that the + methods presented here are appropriate for a particular security + need. A profile may specify which services and algorithms should be + offered by applications, and may provide guidance as to their + appropriate use. + + Key distribution and certificates are outside the scope of this + document. + +9.1 Confidentiality + + Confidentiality means that only the intended receiver(s) can decode + the received packets; for others, the packet contains no useful + information. Confidentiality of the content is achieved by + encryption. + + When it is desired to encrypt RTP or RTCP according to the method + specified in this section, all the octets that will be encapsulated + for transmission in a single lower-layer packet are encrypted as a + unit. For RTCP, a 32-bit random number redrawn for each unit MUST be + prepended to the unit before encryption. For RTP, no prefix is + prepended; instead, the sequence number and timestamp fields are + initialized with random offsets. This is considered to be a weak + + + + +Schulzrinne, et al. Standards Track [Page 65] + +RFC 3550 RTP July 2003 + + + initialization vector (IV) because of poor randomness properties. In + addition, if the subsequent field, the SSRC, can be manipulated by an + enemy, there is further weakness of the encryption method. + + For RTCP, an implementation MAY segregate the individual RTCP packets + in a compound RTCP packet into two separate compound RTCP packets, + one to be encrypted and one to be sent in the clear. For example, + SDES information might be encrypted while reception reports were sent + in the clear to accommodate third-party monitors that are not privy + to the encryption key. In this example, depicted in Fig. 4, the SDES + information MUST be appended to an RR packet with no reports (and the + random number) to satisfy the requirement that all compound RTCP + packets begin with an SR or RR packet. The SDES CNAME item is + required in either the encrypted or unencrypted packet, but not both. + The same SDES information SHOULD NOT be carried in both packets as + this may compromise the encryption. + + UDP packet UDP packet + ----------------------------- ------------------------------ + [random][RR][SDES #CNAME ...] [SR #senderinfo #site1 #site2] + ----------------------------- ------------------------------ + encrypted not encrypted + + #: SSRC identifier + + Figure 4: Encrypted and non-encrypted RTCP packets + + The presence of encryption and the use of the correct key are + confirmed by the receiver through header or payload validity checks. + Examples of such validity checks for RTP and RTCP headers are given + in Appendices A.1 and A.2. + + To be consistent with existing implementations of the initial + specification of RTP in RFC 1889, the default encryption algorithm is + the Data Encryption Standard (DES) algorithm in cipher block chaining + (CBC) mode, as described in Section 1.1 of RFC 1423 [29], except that + padding to a multiple of 8 octets is indicated as described for the P + bit in Section 5.1. The initialization vector is zero because random + values are supplied in the RTP header or by the random prefix for + compound RTCP packets. For details on the use of CBC initialization + vectors, see [30]. + + Implementations that support the encryption method specified here + SHOULD always support the DES algorithm in CBC mode as the default + cipher for this method to maximize interoperability. This method was + chosen because it has been demonstrated to be easy and practical to + use in experimental audio and video tools in operation on the + Internet. However, DES has since been found to be too easily broken. + + + +Schulzrinne, et al. Standards Track [Page 66] + +RFC 3550 RTP July 2003 + + + It is RECOMMENDED that stronger encryption algorithms such as + Triple-DES be used in place of the default algorithm. Furthermore, + secure CBC mode requires that the first block of each packet be XORed + with a random, independent IV of the same size as the cipher's block + size. For RTCP, this is (partially) achieved by prepending each + packet with a 32-bit random number, independently chosen for each + packet. For RTP, the timestamp and sequence number start from random + values, but consecutive packets will not be independently randomized. + It should be noted that the randomness in both cases (RTP and RTCP) + is limited. High-security applications SHOULD consider other, more + conventional, protection means. Other encryption algorithms MAY be + specified dynamically for a session by non-RTP means. In particular, + the SRTP profile [28] based on AES is being developed to take into + account known plaintext and CBC plaintext manipulation concerns, and + will be the correct choice in the future. + + As an alternative to encryption at the IP level or at the RTP level + as described above, profiles MAY define additional payload types for + encrypted encodings. Those encodings MUST specify how padding and + other aspects of the encryption are to be handled. This method + allows encrypting only the data while leaving the headers in the + clear for applications where that is desired. It may be particularly + useful for hardware devices that will handle both decryption and + decoding. It is also valuable for applications where link-level + compression of RTP and lower-layer headers is desired and + confidentiality of the payload (but not addresses) is sufficient + since encryption of the headers precludes compression. + +9.2 Authentication and Message Integrity + + Authentication and message integrity services are not defined at the + RTP level since these services would not be directly feasible without + a key management infrastructure. It is expected that authentication + and integrity services will be provided by lower layer protocols. + +10. Congestion Control + + All transport protocols used on the Internet need to address + congestion control in some way [31]. RTP is not an exception, but + because the data transported over RTP is often inelastic (generated + at a fixed or controlled rate), the means to control congestion in + RTP may be quite different from those for other transport protocols + such as TCP. In one sense, inelasticity reduces the risk of + congestion because the RTP stream will not expand to consume all + available bandwidth as a TCP stream can. However, inelasticity also + means that the RTP stream cannot arbitrarily reduce its load on the + network to eliminate congestion when it occurs. + + + + +Schulzrinne, et al. Standards Track [Page 67] + +RFC 3550 RTP July 2003 + + + Since RTP may be used for a wide variety of applications in many + different contexts, there is no single congestion control mechanism + that will work for all. Therefore, congestion control SHOULD be + defined in each RTP profile as appropriate. For some profiles, it + may be sufficient to include an applicability statement restricting + the use of that profile to environments where congestion is avoided + by engineering. For other profiles, specific methods such as data + rate adaptation based on RTCP feedback may be required. + +11. RTP over Network and Transport Protocols + + This section describes issues specific to carrying RTP packets within + particular network and transport protocols. The following rules + apply unless superseded by protocol-specific definitions outside this + specification. + + RTP relies on the underlying protocol(s) to provide demultiplexing of + RTP data and RTCP control streams. For UDP and similar protocols, + RTP SHOULD use an even destination port number and the corresponding + RTCP stream SHOULD use the next higher (odd) destination port number. + For applications that take a single port number as a parameter and + derive the RTP and RTCP port pair from that number, if an odd number + is supplied then the application SHOULD replace that number with the + next lower (even) number to use as the base of the port pair. For + applications in which the RTP and RTCP destination port numbers are + specified via explicit, separate parameters (using a signaling + protocol or other means), the application MAY disregard the + restrictions that the port numbers be even/odd and consecutive + although the use of an even/odd port pair is still encouraged. The + RTP and RTCP port numbers MUST NOT be the same since RTP relies on + the port numbers to demultiplex the RTP data and RTCP control + streams. + + In a unicast session, both participants need to identify a port pair + for receiving RTP and RTCP packets. Both participants MAY use the + same port pair. A participant MUST NOT assume that the source port + of the incoming RTP or RTCP packet can be used as the destination + port for outgoing RTP or RTCP packets. When RTP data packets are + being sent in both directions, each participant's RTCP SR packets + MUST be sent to the port that the other participant has specified for + reception of RTCP. The RTCP SR packets combine sender information + for the outgoing data plus reception report information for the + incoming data. If a side is not actively sending data (see Section + 6.4), an RTCP RR packet is sent instead. + + It is RECOMMENDED that layered encoding applications (see Section + 2.4) use a set of contiguous port numbers. The port numbers MUST be + distinct because of a widespread deficiency in existing operating + + + +Schulzrinne, et al. Standards Track [Page 68] + +RFC 3550 RTP July 2003 + + + systems that prevents use of the same port with multiple multicast + addresses, and for unicast, there is only one permissible address. + Thus for layer n, the data port is P + 2n, and the control port is P + + 2n + 1. When IP multicast is used, the addresses MUST also be + distinct because multicast routing and group membership are managed + on an address granularity. However, allocation of contiguous IP + multicast addresses cannot be assumed because some groups may require + different scopes and may therefore be allocated from different + address ranges. + + The previous paragraph conflicts with the SDP specification, RFC 2327 + [15], which says that it is illegal for both multiple addresses and + multiple ports to be specified in the same session description + because the association of addresses with ports could be ambiguous. + It is intended that this restriction will be relaxed in a revision of + RFC 2327 to allow an equal number of addresses and ports to be + specified with a one-to-one mapping implied. + + RTP data packets contain no length field or other delineation, + therefore RTP relies on the underlying protocol(s) to provide a + length indication. The maximum length of RTP packets is limited only + by the underlying protocols. + + If RTP packets are to be carried in an underlying protocol that + provides the abstraction of a continuous octet stream rather than + messages (packets), an encapsulation of the RTP packets MUST be + defined to provide a framing mechanism. Framing is also needed if + the underlying protocol may contain padding so that the extent of the + RTP payload cannot be determined. The framing mechanism is not + defined here. + + A profile MAY specify a framing method to be used even when RTP is + carried in protocols that do provide framing in order to allow + carrying several RTP packets in one lower-layer protocol data unit, + such as a UDP packet. Carrying several RTP packets in one network or + transport packet reduces header overhead and may simplify + synchronization between different streams. + +12. Summary of Protocol Constants + + This section contains a summary listing of the constants defined in + this specification. + + The RTP payload type (PT) constants are defined in profiles rather + than this document. However, the octet of the RTP header which + contains the marker bit(s) and payload type MUST avoid the reserved + values 200 and 201 (decimal) to distinguish RTP packets from the RTCP + SR and RR packet types for the header validation procedure described + + + +Schulzrinne, et al. Standards Track [Page 69] + +RFC 3550 RTP July 2003 + + + in Appendix A.1. For the standard definition of one marker bit and a + 7-bit payload type field as shown in this specification, this + restriction means that payload types 72 and 73 are reserved. + +12.1 RTCP Packet Types + + abbrev. name value + SR sender report 200 + RR receiver report 201 + SDES source description 202 + BYE goodbye 203 + APP application-defined 204 + + These type values were chosen in the range 200-204 for improved + header validity checking of RTCP packets compared to RTP packets or + other unrelated packets. When the RTCP packet type field is compared + to the corresponding octet of the RTP header, this range corresponds + to the marker bit being 1 (which it usually is not in data packets) + and to the high bit of the standard payload type field being 1 (since + the static payload types are typically defined in the low half). + This range was also chosen to be some distance numerically from 0 and + 255 since all-zeros and all-ones are common data patterns. + + Since all compound RTCP packets MUST begin with SR or RR, these codes + were chosen as an even/odd pair to allow the RTCP validity check to + test the maximum number of bits with mask and value. + + Additional RTCP packet types may be registered through IANA (see + Section 15). + +12.2 SDES Types + + abbrev. name value + END end of SDES list 0 + CNAME canonical name 1 + NAME user name 2 + EMAIL user's electronic mail address 3 + PHONE user's phone number 4 + LOC geographic user location 5 + TOOL name of application or tool 6 + NOTE notice about the source 7 + PRIV private extensions 8 + + Additional SDES types may be registered through IANA (see Section + 15). + + + + + + +Schulzrinne, et al. Standards Track [Page 70] + +RFC 3550 RTP July 2003 + + +13. RTP Profiles and Payload Format Specifications + + A complete specification of RTP for a particular application will + require one or more companion documents of two types described here: + profiles, and payload format specifications. + + RTP may be used for a variety of applications with somewhat differing + requirements. The flexibility to adapt to those requirements is + provided by allowing multiple choices in the main protocol + specification, then selecting the appropriate choices or defining + extensions for a particular environment and class of applications in + a separate profile document. Typically an application will operate + under only one profile in a particular RTP session, so there is no + explicit indication within the RTP protocol itself as to which + profile is in use. A profile for audio and video applications may be + found in the companion RFC 3551. Profiles are typically titled "RTP + Profile for ...". + + The second type of companion document is a payload format + specification, which defines how a particular kind of payload data, + such as H.261 encoded video, should be carried in RTP. These + documents are typically titled "RTP Payload Format for XYZ + Audio/Video Encoding". Payload formats may be useful under multiple + profiles and may therefore be defined independently of any particular + profile. The profile documents are then responsible for assigning a + default mapping of that format to a payload type value if needed. + + Within this specification, the following items have been identified + for possible definition within a profile, but this list is not meant + to be exhaustive: + + RTP data header: The octet in the RTP data header that contains + the marker bit and payload type field MAY be redefined by a + profile to suit different requirements, for example with more or + fewer marker bits (Section 5.3, p. 18). + + Payload types: Assuming that a payload type field is included, + the profile will usually define a set of payload formats (e.g., + media encodings) and a default static mapping of those formats to + payload type values. Some of the payload formats may be defined + by reference to separate payload format specifications. For each + payload type defined, the profile MUST specify the RTP timestamp + clock rate to be used (Section 5.1, p. 14). + + RTP data header additions: Additional fields MAY be appended to + the fixed RTP data header if some additional functionality is + required across the profile's class of applications independent of + payload type (Section 5.3, p. 18). + + + +Schulzrinne, et al. Standards Track [Page 71] + +RFC 3550 RTP July 2003 + + + RTP data header extensions: The contents of the first 16 bits of + the RTP data header extension structure MUST be defined if use of + that mechanism is to be allowed under the profile for + implementation-specific extensions (Section 5.3.1, p. 18). + + RTCP packet types: New application-class-specific RTCP packet + types MAY be defined and registered with IANA. + + RTCP report interval: A profile SHOULD specify that the values + suggested in Section 6.2 for the constants employed in the + calculation of the RTCP report interval will be used. Those are + the RTCP fraction of session bandwidth, the minimum report + interval, and the bandwidth split between senders and receivers. + A profile MAY specify alternate values if they have been + demonstrated to work in a scalable manner. + + SR/RR extension: An extension section MAY be defined for the + RTCP SR and RR packets if there is additional information that + should be reported regularly about the sender or receivers + (Section 6.4.3, p. 42 and 43). + + SDES use: The profile MAY specify the relative priorities for + RTCP SDES items to be transmitted or excluded entirely (Section + 6.3.9); an alternate syntax or semantics for the CNAME item + (Section 6.5.1); the format of the LOC item (Section 6.5.5); the + semantics and use of the NOTE item (Section 6.5.7); or new SDES + item types to be registered with IANA. + + Security: A profile MAY specify which security services and + algorithms should be offered by applications, and MAY provide + guidance as to their appropriate use (Section 9, p. 65). + + String-to-key mapping: A profile MAY specify how a user-provided + password or pass phrase is mapped into an encryption key. + + Congestion: A profile SHOULD specify the congestion control + behavior appropriate for that profile. + + Underlying protocol: Use of a particular underlying network or + transport layer protocol to carry RTP packets MAY be required. + + Transport mapping: A mapping of RTP and RTCP to transport-level + addresses, e.g., UDP ports, other than the standard mapping + defined in Section 11, p. 68 may be specified. + + + + + + + +Schulzrinne, et al. Standards Track [Page 72] + +RFC 3550 RTP July 2003 + + + Encapsulation: An encapsulation of RTP packets may be defined to + allow multiple RTP data packets to be carried in one lower-layer + packet or to provide framing over underlying protocols that do not + already do so (Section 11, p. 69). + + It is not expected that a new profile will be required for every + application. Within one application class, it would be better to + extend an existing profile rather than make a new one in order to + facilitate interoperation among the applications since each will + typically run under only one profile. Simple extensions such as the + definition of additional payload type values or RTCP packet types may + be accomplished by registering them through IANA and publishing their + descriptions in an addendum to the profile or in a payload format + specification. + +14. Security Considerations + + RTP suffers from the same security liabilities as the underlying + protocols. For example, an impostor can fake source or destination + network addresses, or change the header or payload. Within RTCP, the + CNAME and NAME information may be used to impersonate another + participant. In addition, RTP may be sent via IP multicast, which + provides no direct means for a sender to know all the receivers of + the data sent and therefore no measure of privacy. Rightly or not, + users may be more sensitive to privacy concerns with audio and video + communication than they have been with more traditional forms of + network communication [33]. Therefore, the use of security + mechanisms with RTP is important. These mechanisms are discussed in + Section 9. + + RTP-level translators or mixers may be used to allow RTP traffic to + reach hosts behind firewalls. Appropriate firewall security + principles and practices, which are beyond the scope of this + document, should be followed in the design and installation of these + devices and in the admission of RTP applications for use behind the + firewall. + +15. IANA Considerations + + Additional RTCP packet types and SDES item types may be registered + through the Internet Assigned Numbers Authority (IANA). Since these + number spaces are small, allowing unconstrained registration of new + values would not be prudent. To facilitate review of requests and to + promote shared use of new types among multiple applications, requests + for registration of new values must be documented in an RFC or other + permanent and readily available reference such as the product of + another cooperative standards body (e.g., ITU-T). Other requests may + also be accepted, under the advice of a "designated expert." + + + +Schulzrinne, et al. Standards Track [Page 73] + +RFC 3550 RTP July 2003 + + + (Contact the IANA for the contact information of the current expert.) + + RTP profile specifications SHOULD register with IANA a name for the + profile in the form "RTP/xxx", where xxx is a short abbreviation of + the profile title. These names are for use by higher-level control + protocols, such as the Session Description Protocol (SDP), RFC 2327 + [15], to refer to transport methods. + +16. Intellectual Property Rights Statement + + The IETF takes no position regarding the validity or scope of any + intellectual property or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; neither does it represent that it + has made any effort to identify any such rights. Information on the + IETF's procedures with respect to rights in standards-track and + standards-related documentation can be found in BCP-11. Copies of + claims of rights made available for publication and any assurances of + licenses to be made available, or the result of an attempt made to + obtain a general license or permission for the use of such + proprietary rights by implementors or users of this specification can + be obtained from the IETF Secretariat. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights which may cover technology that may be required to practice + this standard. Please address the information to the IETF Executive + Director. + +17. Acknowledgments + + This memorandum is based on discussions within the IETF Audio/Video + Transport working group chaired by Stephen Casner and Colin Perkins. + The current protocol has its origins in the Network Voice Protocol + and the Packet Video Protocol (Danny Cohen and Randy Cole) and the + protocol implemented by the vat application (Van Jacobson and Steve + McCanne). Christian Huitema provided ideas for the random identifier + generator. Extensive analysis and simulation of the timer + reconsideration algorithm was done by Jonathan Rosenberg. The + additions for layered encodings were specified by Michael Speer and + Steve McCanne. + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 74] + +RFC 3550 RTP July 2003 + + +Appendix A - Algorithms + + We provide examples of C code for aspects of RTP sender and receiver + algorithms. There may be other implementation methods that are + faster in particular operating environments or have other advantages. + These implementation notes are for informational purposes only and + are meant to clarify the RTP specification. + + The following definitions are used for all examples; for clarity and + brevity, the structure definitions are only valid for 32-bit big- + endian (most significant octet first) architectures. Bit fields are + assumed to be packed tightly in big-endian bit order, with no + additional padding. Modifications would be required to construct a + portable implementation. + + /* + * rtp.h -- RTP header file + */ + #include + + /* + * The type definitions below are valid for 32-bit architectures and + * may have to be adjusted for 16- or 64-bit architectures. + */ + typedef unsigned char u_int8; + typedef unsigned short u_int16; + typedef unsigned int u_int32; + typedef short int16; + + /* + * Current protocol version. + */ + #define RTP_VERSION 2 + + #define RTP_SEQ_MOD (1<<16) + #define RTP_MAX_SDES 255 /* maximum text length for SDES */ + + typedef enum { + RTCP_SR = 200, + RTCP_RR = 201, + RTCP_SDES = 202, + RTCP_BYE = 203, + RTCP_APP = 204 + } rtcp_type_t; + + typedef enum { + RTCP_SDES_END = 0, + RTCP_SDES_CNAME = 1, + + + +Schulzrinne, et al. Standards Track [Page 75] + +RFC 3550 RTP July 2003 + + + RTCP_SDES_NAME = 2, + RTCP_SDES_EMAIL = 3, + RTCP_SDES_PHONE = 4, + RTCP_SDES_LOC = 5, + RTCP_SDES_TOOL = 6, + RTCP_SDES_NOTE = 7, + RTCP_SDES_PRIV = 8 + } rtcp_sdes_type_t; + + /* + * RTP data header + */ + typedef struct { + unsigned int version:2; /* protocol version */ + unsigned int p:1; /* padding flag */ + unsigned int x:1; /* header extension flag */ + unsigned int cc:4; /* CSRC count */ + unsigned int m:1; /* marker bit */ + unsigned int pt:7; /* payload type */ + unsigned int seq:16; /* sequence number */ + u_int32 ts; /* timestamp */ + u_int32 ssrc; /* synchronization source */ + u_int32 csrc[1]; /* optional CSRC list */ + } rtp_hdr_t; + + /* + * RTCP common header word + */ + typedef struct { + unsigned int version:2; /* protocol version */ + unsigned int p:1; /* padding flag */ + unsigned int count:5; /* varies by packet type */ + unsigned int pt:8; /* RTCP packet type */ + u_int16 length; /* pkt len in words, w/o this word */ + } rtcp_common_t; + + /* + * Big-endian mask for version, padding bit and packet type pair + */ + #define RTCP_VALID_MASK (0xc000 | 0x2000 | 0xfe) + #define RTCP_VALID_VALUE ((RTP_VERSION << 14) | RTCP_SR) + + /* + * Reception report block + */ + typedef struct { + u_int32 ssrc; /* data source being reported */ + unsigned int fraction:8; /* fraction lost since last SR/RR */ + + + +Schulzrinne, et al. Standards Track [Page 76] + +RFC 3550 RTP July 2003 + + + int lost:24; /* cumul. no. pkts lost (signed!) */ + u_int32 last_seq; /* extended last seq. no. received */ + u_int32 jitter; /* interarrival jitter */ + u_int32 lsr; /* last SR packet from this source */ + u_int32 dlsr; /* delay since last SR packet */ + } rtcp_rr_t; + + /* + * SDES item + */ + typedef struct { + u_int8 type; /* type of item (rtcp_sdes_type_t) */ + u_int8 length; /* length of item (in octets) */ + char data[1]; /* text, not null-terminated */ + } rtcp_sdes_item_t; + + /* + * One RTCP packet + */ + typedef struct { + rtcp_common_t common; /* common header */ + union { + /* sender report (SR) */ + struct { + u_int32 ssrc; /* sender generating this report */ + u_int32 ntp_sec; /* NTP timestamp */ + u_int32 ntp_frac; + u_int32 rtp_ts; /* RTP timestamp */ + u_int32 psent; /* packets sent */ + u_int32 osent; /* octets sent */ + rtcp_rr_t rr[1]; /* variable-length list */ + } sr; + + /* reception report (RR) */ + struct { + u_int32 ssrc; /* receiver generating this report */ + rtcp_rr_t rr[1]; /* variable-length list */ + } rr; + + /* source description (SDES) */ + struct rtcp_sdes { + u_int32 src; /* first SSRC/CSRC */ + rtcp_sdes_item_t item[1]; /* list of SDES items */ + } sdes; + + /* BYE */ + struct { + u_int32 src[1]; /* list of sources */ + + + +Schulzrinne, et al. Standards Track [Page 77] + +RFC 3550 RTP July 2003 + + + /* can't express trailing text for reason */ + } bye; + } r; + } rtcp_t; + + typedef struct rtcp_sdes rtcp_sdes_t; + + /* + * Per-source state information + */ + typedef struct { + u_int16 max_seq; /* highest seq. number seen */ + u_int32 cycles; /* shifted count of seq. number cycles */ + u_int32 base_seq; /* base seq number */ + u_int32 bad_seq; /* last 'bad' seq number + 1 */ + u_int32 probation; /* sequ. packets till source is valid */ + u_int32 received; /* packets received */ + u_int32 expected_prior; /* packet expected at last interval */ + u_int32 received_prior; /* packet received at last interval */ + u_int32 transit; /* relative trans time for prev pkt */ + u_int32 jitter; /* estimated jitter */ + /* ... */ + } source; + +A.1 RTP Data Header Validity Checks + + An RTP receiver should check the validity of the RTP header on + incoming packets since they might be encrypted or might be from a + different application that happens to be misaddressed. Similarly, if + encryption according to the method described in Section 9 is enabled, + the header validity check is needed to verify that incoming packets + have been correctly decrypted, although a failure of the header + validity check (e.g., unknown payload type) may not necessarily + indicate decryption failure. + + Only weak validity checks are possible on an RTP data packet from a + source that has not been heard before: + + o RTP version field must equal 2. + + o The payload type must be known, and in particular it must not be + equal to SR or RR. + + o If the P bit is set, then the last octet of the packet must + contain a valid octet count, in particular, less than the total + packet length minus the header size. + + + + + +Schulzrinne, et al. Standards Track [Page 78] + +RFC 3550 RTP July 2003 + + + o The X bit must be zero if the profile does not specify that the + header extension mechanism may be used. Otherwise, the extension + length field must be less than the total packet size minus the + fixed header length and padding. + + o The length of the packet must be consistent with CC and payload + type (if payloads have a known length). + + The last three checks are somewhat complex and not always possible, + leaving only the first two which total just a few bits. If the SSRC + identifier in the packet is one that has been received before, then + the packet is probably valid and checking if the sequence number is + in the expected range provides further validation. If the SSRC + identifier has not been seen before, then data packets carrying that + identifier may be considered invalid until a small number of them + arrive with consecutive sequence numbers. Those invalid packets MAY + be discarded or they MAY be stored and delivered once validation has + been achieved if the resulting delay is acceptable. + + The routine update_seq shown below ensures that a source is declared + valid only after MIN_SEQUENTIAL packets have been received in + sequence. It also validates the sequence number seq of a newly + received packet and updates the sequence state for the packet's + source in the structure to which s points. + + When a new source is heard for the first time, that is, its SSRC + identifier is not in the table (see Section 8.2), and the per-source + state is allocated for it, s->probation is set to the number of + sequential packets required before declaring a source valid + (parameter MIN_SEQUENTIAL) and other variables are initialized: + + init_seq(s, seq); + s->max_seq = seq - 1; + s->probation = MIN_SEQUENTIAL; + + A non-zero s->probation marks the source as not yet valid so the + state may be discarded after a short timeout rather than a long one, + as discussed in Section 6.2.1. + + After a source is considered valid, the sequence number is considered + valid if it is no more than MAX_DROPOUT ahead of s->max_seq nor more + than MAX_MISORDER behind. If the new sequence number is ahead of + max_seq modulo the RTP sequence number range (16 bits), but is + smaller than max_seq, it has wrapped around and the (shifted) count + of sequence number cycles is incremented. A value of one is returned + to indicate a valid sequence number. + + + + + +Schulzrinne, et al. Standards Track [Page 79] + +RFC 3550 RTP July 2003 + + + Otherwise, the value zero is returned to indicate that the validation + failed, and the bad sequence number plus 1 is stored. If the next + packet received carries the next higher sequence number, it is + considered the valid start of a new packet sequence presumably caused + by an extended dropout or a source restart. Since multiple complete + sequence number cycles may have been missed, the packet loss + statistics are reset. + + Typical values for the parameters are shown, based on a maximum + misordering time of 2 seconds at 50 packets/second and a maximum + dropout of 1 minute. The dropout parameter MAX_DROPOUT should be a + small fraction of the 16-bit sequence number space to give a + reasonable probability that new sequence numbers after a restart will + not fall in the acceptable range for sequence numbers from before the + restart. + + void init_seq(source *s, u_int16 seq) + { + s->base_seq = seq; + s->max_seq = seq; + s->bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */ + s->cycles = 0; + s->received = 0; + s->received_prior = 0; + s->expected_prior = 0; + /* other initialization */ + } + + int update_seq(source *s, u_int16 seq) + { + u_int16 udelta = seq - s->max_seq; + const int MAX_DROPOUT = 3000; + const int MAX_MISORDER = 100; + const int MIN_SEQUENTIAL = 2; + + /* + * Source is not valid until MIN_SEQUENTIAL packets with + * sequential sequence numbers have been received. + */ + if (s->probation) { + /* packet is in sequence */ + if (seq == s->max_seq + 1) { + s->probation--; + s->max_seq = seq; + if (s->probation == 0) { + init_seq(s, seq); + s->received++; + return 1; + + + +Schulzrinne, et al. Standards Track [Page 80] + +RFC 3550 RTP July 2003 + + + } + } else { + s->probation = MIN_SEQUENTIAL - 1; + s->max_seq = seq; + } + return 0; + } else if (udelta < MAX_DROPOUT) { + /* in order, with permissible gap */ + if (seq < s->max_seq) { + /* + * Sequence number wrapped - count another 64K cycle. + */ + s->cycles += RTP_SEQ_MOD; + } + s->max_seq = seq; + } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) { + /* the sequence number made a very large jump */ + if (seq == s->bad_seq) { + /* + * Two sequential packets -- assume that the other side + * restarted without telling us so just re-sync + * (i.e., pretend this was the first packet). + */ + init_seq(s, seq); + } + else { + s->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1); + return 0; + } + } else { + /* duplicate or reordered packet */ + } + s->received++; + return 1; + } + + The validity check can be made stronger requiring more than two + packets in sequence. The disadvantages are that a larger number of + initial packets will be discarded (or delayed in a queue) and that + high packet loss rates could prevent validation. However, because + the RTCP header validation is relatively strong, if an RTCP packet is + received from a source before the data packets, the count could be + adjusted so that only two packets are required in sequence. If + initial data loss for a few seconds can be tolerated, an application + MAY choose to discard all data packets from a source until a valid + RTCP packet has been received from that source. + + + + + +Schulzrinne, et al. Standards Track [Page 81] + +RFC 3550 RTP July 2003 + + + Depending on the application and encoding, algorithms may exploit + additional knowledge about the payload format for further validation. + For payload types where the timestamp increment is the same for all + packets, the timestamp values can be predicted from the previous + packet received from the same source using the sequence number + difference (assuming no change in payload type). + + A strong "fast-path" check is possible since with high probability + the first four octets in the header of a newly received RTP data + packet will be just the same as that of the previous packet from the + same SSRC except that the sequence number will have increased by one. + Similarly, a single-entry cache may be used for faster SSRC lookups + in applications where data is typically received from one source at a + time. + +A.2 RTCP Header Validity Checks + + The following checks should be applied to RTCP packets. + + o RTP version field must equal 2. + + o The payload type field of the first RTCP packet in a compound + packet must be equal to SR or RR. + + o The padding bit (P) should be zero for the first packet of a + compound RTCP packet because padding should only be applied, if it + is needed, to the last packet. + + o The length fields of the individual RTCP packets must add up to + the overall length of the compound RTCP packet as received. This + is a fairly strong check. + + The code fragment below performs all of these checks. The packet + type is not checked for subsequent packets since unknown packet types + may be present and should be ignored. + + u_int32 len; /* length of compound RTCP packet in words */ + rtcp_t *r; /* RTCP header */ + rtcp_t *end; /* end of compound RTCP packet */ + + if ((*(u_int16 *)r & RTCP_VALID_MASK) != RTCP_VALID_VALUE) { + /* something wrong with packet format */ + } + end = (rtcp_t *)((u_int32 *)r + len); + + do r = (rtcp_t *)((u_int32 *)r + r->common.length + 1); + while (r < end && r->common.version == 2); + + + + +Schulzrinne, et al. Standards Track [Page 82] + +RFC 3550 RTP July 2003 + + + if (r != end) { + /* something wrong with packet format */ + } + +A.3 Determining Number of Packets Expected and Lost + + In order to compute packet loss rates, the number of RTP packets + expected and actually received from each source needs to be known, + using per-source state information defined in struct source + referenced via pointer s in the code below. The number of packets + received is simply the count of packets as they arrive, including any + late or duplicate packets. The number of packets expected can be + computed by the receiver as the difference between the highest + sequence number received (s->max_seq) and the first sequence number + received (s->base_seq). Since the sequence number is only 16 bits + and will wrap around, it is necessary to extend the highest sequence + number with the (shifted) count of sequence number wraparounds + (s->cycles). Both the received packet count and the count of cycles + are maintained the RTP header validity check routine in Appendix A.1. + + extended_max = s->cycles + s->max_seq; + expected = extended_max - s->base_seq + 1; + + The number of packets lost is defined to be the number of packets + expected less the number of packets actually received: + + lost = expected - s->received; + + Since this signed number is carried in 24 bits, it should be clamped + at 0x7fffff for positive loss or 0x800000 for negative loss rather + than wrapping around. + + The fraction of packets lost during the last reporting interval + (since the previous SR or RR packet was sent) is calculated from + differences in the expected and received packet counts across the + interval, where expected_prior and received_prior are the values + saved when the previous reception report was generated: + + expected_interval = expected - s->expected_prior; + s->expected_prior = expected; + received_interval = s->received - s->received_prior; + s->received_prior = s->received; + lost_interval = expected_interval - received_interval; + if (expected_interval == 0 || lost_interval <= 0) fraction = 0; + else fraction = (lost_interval << 8) / expected_interval; + + The resulting fraction is an 8-bit fixed point number with the binary + point at the left edge. + + + +Schulzrinne, et al. Standards Track [Page 83] + +RFC 3550 RTP July 2003 + + +A.4 Generating RTCP SDES Packets + + This function builds one SDES chunk into buffer b composed of argc + items supplied in arrays type, value and length. It returns a + pointer to the next available location within b. + + char *rtp_write_sdes(char *b, u_int32 src, int argc, + rtcp_sdes_type_t type[], char *value[], + int length[]) + { + rtcp_sdes_t *s = (rtcp_sdes_t *)b; + rtcp_sdes_item_t *rsp; + int i; + int len; + int pad; + + /* SSRC header */ + s->src = src; + rsp = &s->item[0]; + + /* SDES items */ + for (i = 0; i < argc; i++) { + rsp->type = type[i]; + len = length[i]; + if (len > RTP_MAX_SDES) { + /* invalid length, may want to take other action */ + len = RTP_MAX_SDES; + } + rsp->length = len; + memcpy(rsp->data, value[i], len); + rsp = (rtcp_sdes_item_t *)&rsp->data[len]; + } + + /* terminate with end marker and pad to next 4-octet boundary */ + len = ((char *) rsp) - b; + pad = 4 - (len & 0x3); + b = (char *) rsp; + while (pad--) *b++ = RTCP_SDES_END; + + return b; + } + + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 84] + +RFC 3550 RTP July 2003 + + +A.5 Parsing RTCP SDES Packets + + This function parses an SDES packet, calling functions find_member() + to find a pointer to the information for a session member given the + SSRC identifier and member_sdes() to store the new SDES information + for that member. This function expects a pointer to the header of + the RTCP packet. + + void rtp_read_sdes(rtcp_t *r) + { + int count = r->common.count; + rtcp_sdes_t *sd = &r->r.sdes; + rtcp_sdes_item_t *rsp, *rspn; + rtcp_sdes_item_t *end = (rtcp_sdes_item_t *) + ((u_int32 *)r + r->common.length + 1); + source *s; + + while (--count >= 0) { + rsp = &sd->item[0]; + if (rsp >= end) break; + s = find_member(sd->src); + + for (; rsp->type; rsp = rspn ) { + rspn = (rtcp_sdes_item_t *)((char*)rsp+rsp->length+2); + if (rspn >= end) { + rsp = rspn; + break; + } + member_sdes(s, rsp->type, rsp->data, rsp->length); + } + sd = (rtcp_sdes_t *) + ((u_int32 *)sd + (((char *)rsp - (char *)sd) >> 2)+1); + } + if (count >= 0) { + /* invalid packet format */ + } + } + +A.6 Generating a Random 32-bit Identifier + + The following subroutine generates a random 32-bit identifier using + the MD5 routines published in RFC 1321 [32]. The system routines may + not be present on all operating systems, but they should serve as + hints as to what kinds of information may be used. Other system + calls that may be appropriate include + + + + + + +Schulzrinne, et al. Standards Track [Page 85] + +RFC 3550 RTP July 2003 + + + o getdomainname(), + + o getwd(), or + + o getrusage(). + + "Live" video or audio samples are also a good source of random + numbers, but care must be taken to avoid using a turned-off + microphone or blinded camera as a source [17]. + + Use of this or a similar routine is recommended to generate the + initial seed for the random number generator producing the RTCP + period (as shown in Appendix A.7), to generate the initial values for + the sequence number and timestamp, and to generate SSRC values. + Since this routine is likely to be CPU-intensive, its direct use to + generate RTCP periods is inappropriate because predictability is not + an issue. Note that this routine produces the same result on + repeated calls until the value of the system clock changes unless + different values are supplied for the type argument. + + /* + * Generate a random 32-bit quantity. + */ + #include /* u_long */ + #include /* gettimeofday() */ + #include /* get..() */ + #include /* printf() */ + #include /* clock() */ + #include /* uname() */ + #include "global.h" /* from RFC 1321 */ + #include "md5.h" /* from RFC 1321 */ + + #define MD_CTX MD5_CTX + #define MDInit MD5Init + #define MDUpdate MD5Update + #define MDFinal MD5Final + + static u_long md_32(char *string, int length) + { + MD_CTX context; + union { + char c[16]; + u_long x[4]; + } digest; + u_long r; + int i; + + MDInit (&context); + + + +Schulzrinne, et al. Standards Track [Page 86] + +RFC 3550 RTP July 2003 + + + MDUpdate (&context, string, length); + MDFinal ((unsigned char *)&digest, &context); + r = 0; + for (i = 0; i < 3; i++) { + r ^= digest.x[i]; + } + return r; + } /* md_32 */ + + /* + * Return random unsigned 32-bit quantity. Use 'type' argument if + * you need to generate several different values in close succession. + */ + u_int32 random32(int type) + { + struct { + int type; + struct timeval tv; + clock_t cpu; + pid_t pid; + u_long hid; + uid_t uid; + gid_t gid; + struct utsname name; + } s; + + gettimeofday(&s.tv, 0); + uname(&s.name); + s.type = type; + s.cpu = clock(); + s.pid = getpid(); + s.hid = gethostid(); + s.uid = getuid(); + s.gid = getgid(); + /* also: system uptime */ + + return md_32((char *)&s, sizeof(s)); + } /* random32 */ + +A.7 Computing the RTCP Transmission Interval + + The following functions implement the RTCP transmission and reception + rules described in Section 6.2. These rules are coded in several + functions: + + o rtcp_interval() computes the deterministic calculated interval, + measured in seconds. The parameters are defined in Section 6.3. + + + + +Schulzrinne, et al. Standards Track [Page 87] + +RFC 3550 RTP July 2003 + + + o OnExpire() is called when the RTCP transmission timer expires. + + o OnReceive() is called whenever an RTCP packet is received. + + Both OnExpire() and OnReceive() have event e as an argument. This is + the next scheduled event for that participant, either an RTCP report + or a BYE packet. It is assumed that the following functions are + available: + + o Schedule(time t, event e) schedules an event e to occur at time t. + When time t arrives, the function OnExpire is called with e as an + argument. + + o Reschedule(time t, event e) reschedules a previously scheduled + event e for time t. + + o SendRTCPReport(event e) sends an RTCP report. + + o SendBYEPacket(event e) sends a BYE packet. + + o TypeOfEvent(event e) returns EVENT_BYE if the event being + processed is for a BYE packet to be sent, else it returns + EVENT_REPORT. + + o PacketType(p) returns PACKET_RTCP_REPORT if packet p is an RTCP + report (not BYE), PACKET_BYE if its a BYE RTCP packet, and + PACKET_RTP if its a regular RTP data packet. + + o ReceivedPacketSize() and SentPacketSize() return the size of the + referenced packet in octets. + + o NewMember(p) returns a 1 if the participant who sent packet p is + not currently in the member list, 0 otherwise. Note this function + is not sufficient for a complete implementation because each CSRC + identifier in an RTP packet and each SSRC in a BYE packet should + be processed. + + o NewSender(p) returns a 1 if the participant who sent packet p is + not currently in the sender sublist of the member list, 0 + otherwise. + + o AddMember() and RemoveMember() to add and remove participants from + the member list. + + o AddSender() and RemoveSender() to add and remove participants from + the sender sublist of the member list. + + + + + +Schulzrinne, et al. Standards Track [Page 88] + +RFC 3550 RTP July 2003 + + + These functions would have to be extended for an implementation that + allows the RTCP bandwidth fractions for senders and non-senders to be + specified as explicit parameters rather than fixed values of 25% and + 75%. The extended implementation of rtcp_interval() would need to + avoid division by zero if one of the parameters was zero. + + double rtcp_interval(int members, + int senders, + double rtcp_bw, + int we_sent, + double avg_rtcp_size, + int initial) + { + /* + * Minimum average time between RTCP packets from this site (in + * seconds). This time prevents the reports from `clumping' when + * sessions are small and the law of large numbers isn't helping + * to smooth out the traffic. It also keeps the report interval + * from becoming ridiculously small during transient outages like + * a network partition. + */ + double const RTCP_MIN_TIME = 5.; + /* + * Fraction of the RTCP bandwidth to be shared among active + * senders. (This fraction was chosen so that in a typical + * session with one or two active senders, the computed report + * time would be roughly equal to the minimum report time so that + * we don't unnecessarily slow down receiver reports.) The + * receiver fraction must be 1 - the sender fraction. + */ + double const RTCP_SENDER_BW_FRACTION = 0.25; + double const RTCP_RCVR_BW_FRACTION = (1-RTCP_SENDER_BW_FRACTION); + /* + /* To compensate for "timer reconsideration" converging to a + * value below the intended average. + */ + double const COMPENSATION = 2.71828 - 1.5; + + double t; /* interval */ + double rtcp_min_time = RTCP_MIN_TIME; + int n; /* no. of members for computation */ + + /* + * Very first call at application start-up uses half the min + * delay for quicker notification while still allowing some time + * before reporting for randomization and to learn about other + * sources so the report interval will converge to the correct + * interval more quickly. + + + +Schulzrinne, et al. Standards Track [Page 89] + +RFC 3550 RTP July 2003 + + + */ + if (initial) { + rtcp_min_time /= 2; + } + /* + * Dedicate a fraction of the RTCP bandwidth to senders unless + * the number of senders is large enough that their share is + * more than that fraction. + */ + n = members; + if (senders <= members * RTCP_SENDER_BW_FRACTION) { + if (we_sent) { + rtcp_bw *= RTCP_SENDER_BW_FRACTION; + n = senders; + } else { + rtcp_bw *= RTCP_RCVR_BW_FRACTION; + n -= senders; + } + } + + /* + * The effective number of sites times the average packet size is + * the total number of octets sent when each site sends a report. + * Dividing this by the effective bandwidth gives the time + * interval over which those packets must be sent in order to + * meet the bandwidth target, with a minimum enforced. In that + * time interval we send one report so this time is also our + * average time between reports. + */ + t = avg_rtcp_size * n / rtcp_bw; + if (t < rtcp_min_time) t = rtcp_min_time; + + /* + * To avoid traffic bursts from unintended synchronization with + * other sites, we then pick our actual next report interval as a + * random number uniformly distributed between 0.5*t and 1.5*t. + */ + t = t * (drand48() + 0.5); + t = t / COMPENSATION; + return t; + } + + void OnExpire(event e, + int members, + int senders, + double rtcp_bw, + int we_sent, + double *avg_rtcp_size, + + + +Schulzrinne, et al. Standards Track [Page 90] + +RFC 3550 RTP July 2003 + + + int *initial, + time_tp tc, + time_tp *tp, + int *pmembers) + { + /* This function is responsible for deciding whether to send an + * RTCP report or BYE packet now, or to reschedule transmission. + * It is also responsible for updating the pmembers, initial, tp, + * and avg_rtcp_size state variables. This function should be + * called upon expiration of the event timer used by Schedule(). + */ + + double t; /* Interval */ + double tn; /* Next transmit time */ + + /* In the case of a BYE, we use "timer reconsideration" to + * reschedule the transmission of the BYE if necessary */ + + if (TypeOfEvent(e) == EVENT_BYE) { + t = rtcp_interval(members, + senders, + rtcp_bw, + we_sent, + *avg_rtcp_size, + *initial); + tn = *tp + t; + if (tn <= tc) { + SendBYEPacket(e); + exit(1); + } else { + Schedule(tn, e); + } + + } else if (TypeOfEvent(e) == EVENT_REPORT) { + t = rtcp_interval(members, + senders, + rtcp_bw, + we_sent, + *avg_rtcp_size, + *initial); + tn = *tp + t; + if (tn <= tc) { + SendRTCPReport(e); + *avg_rtcp_size = (1./16.)*SentPacketSize(e) + + (15./16.)*(*avg_rtcp_size); + *tp = tc; + + /* We must redraw the interval. Don't reuse the + + + +Schulzrinne, et al. Standards Track [Page 91] + +RFC 3550 RTP July 2003 + + + one computed above, since its not actually + distributed the same, as we are conditioned + on it being small enough to cause a packet to + be sent */ + + t = rtcp_interval(members, + senders, + rtcp_bw, + we_sent, + *avg_rtcp_size, + *initial); + + Schedule(t+tc,e); + *initial = 0; + } else { + Schedule(tn, e); + } + *pmembers = members; + } + } + + void OnReceive(packet p, + event e, + int *members, + int *pmembers, + int *senders, + double *avg_rtcp_size, + double *tp, + double tc, + double tn) + { + /* What we do depends on whether we have left the group, and are + * waiting to send a BYE (TypeOfEvent(e) == EVENT_BYE) or an RTCP + * report. p represents the packet that was just received. */ + + if (PacketType(p) == PACKET_RTCP_REPORT) { + if (NewMember(p) && (TypeOfEvent(e) == EVENT_REPORT)) { + AddMember(p); + *members += 1; + } + *avg_rtcp_size = (1./16.)*ReceivedPacketSize(p) + + (15./16.)*(*avg_rtcp_size); + } else if (PacketType(p) == PACKET_RTP) { + if (NewMember(p) && (TypeOfEvent(e) == EVENT_REPORT)) { + AddMember(p); + *members += 1; + } + if (NewSender(p) && (TypeOfEvent(e) == EVENT_REPORT)) { + + + +Schulzrinne, et al. Standards Track [Page 92] + +RFC 3550 RTP July 2003 + + + AddSender(p); + *senders += 1; + } + } else if (PacketType(p) == PACKET_BYE) { + *avg_rtcp_size = (1./16.)*ReceivedPacketSize(p) + + (15./16.)*(*avg_rtcp_size); + + if (TypeOfEvent(e) == EVENT_REPORT) { + if (NewSender(p) == FALSE) { + RemoveSender(p); + *senders -= 1; + } + + if (NewMember(p) == FALSE) { + RemoveMember(p); + *members -= 1; + } + + if (*members < *pmembers) { + tn = tc + + (((double) *members)/(*pmembers))*(tn - tc); + *tp = tc - + (((double) *members)/(*pmembers))*(tc - *tp); + + /* Reschedule the next report for time tn */ + + Reschedule(tn, e); + *pmembers = *members; + } + + } else if (TypeOfEvent(e) == EVENT_BYE) { + *members += 1; + } + } + } + + + + + + + + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 93] + +RFC 3550 RTP July 2003 + + +A.8 Estimating the Interarrival Jitter + + The code fragments below implement the algorithm given in Section + 6.4.1 for calculating an estimate of the statistical variance of the + RTP data interarrival time to be inserted in the interarrival jitter + field of reception reports. The inputs are r->ts, the timestamp from + the incoming packet, and arrival, the current time in the same units. + Here s points to state for the source; s->transit holds the relative + transit time for the previous packet, and s->jitter holds the + estimated jitter. The jitter field of the reception report is + measured in timestamp units and expressed as an unsigned integer, but + the jitter estimate is kept in a floating point. As each data packet + arrives, the jitter estimate is updated: + + int transit = arrival - r->ts; + int d = transit - s->transit; + s->transit = transit; + if (d < 0) d = -d; + s->jitter += (1./16.) * ((double)d - s->jitter); + + When a reception report block (to which rr points) is generated for + this member, the current jitter estimate is returned: + + rr->jitter = (u_int32) s->jitter; + + Alternatively, the jitter estimate can be kept as an integer, but + scaled to reduce round-off error. The calculation is the same except + for the last line: + + s->jitter += d - ((s->jitter + 8) >> 4); + + In this case, the estimate is sampled for the reception report as: + + rr->jitter = s->jitter >> 4; + + + + + + + + + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 94] + +RFC 3550 RTP July 2003 + + +Appendix B - Changes from RFC 1889 + + Most of this RFC is identical to RFC 1889. There are no changes in + the packet formats on the wire, only changes to the rules and + algorithms governing how the protocol is used. The biggest change is + an enhancement to the scalable timer algorithm for calculating when + to send RTCP packets: + + o The algorithm for calculating the RTCP transmission interval + specified in Sections 6.2 and 6.3 and illustrated in Appendix A.7 + is augmented to include "reconsideration" to minimize transmission + in excess of the intended rate when many participants join a + session simultaneously, and "reverse reconsideration" to reduce + the incidence and duration of false participant timeouts when the + number of participants drops rapidly. Reverse reconsideration is + also used to possibly shorten the delay before sending RTCP SR + when transitioning from passive receiver to active sender mode. + + o Section 6.3.7 specifies new rules controlling when an RTCP BYE + packet should be sent in order to avoid a flood of packets when + many participants leave a session simultaneously. + + o The requirement to retain state for inactive participants for a + period long enough to span typical network partitions was removed + from Section 6.2.1. In a session where many participants join for + a brief time and fail to send BYE, this requirement would cause a + significant overestimate of the number of participants. The + reconsideration algorithm added in this revision compensates for + the large number of new participants joining simultaneously when a + partition heals. + + It should be noted that these enhancements only have a significant + effect when the number of session participants is large (thousands) + and most of the participants join or leave at the same time. This + makes testing in a live network difficult. However, the algorithm + was subjected to a thorough analysis and simulation to verify its + performance. Furthermore, the enhanced algorithm was designed to + interoperate with the algorithm in RFC 1889 such that the degree of + reduction in excess RTCP bandwidth during a step join is proportional + to the fraction of participants that implement the enhanced + algorithm. Interoperation of the two algorithms has been verified + experimentally on live networks. + + Other functional changes were: + + o Section 6.2.1 specifies that implementations may store only a + sampling of the participants' SSRC identifiers to allow scaling to + very large sessions. Algorithms are specified in RFC 2762 [21]. + + + +Schulzrinne, et al. Standards Track [Page 95] + +RFC 3550 RTP July 2003 + + + o In Section 6.2 it is specified that RTCP sender and non-sender + bandwidths may be set as separate parameters of the session rather + than a strict percentage of the session bandwidth, and may be set + to zero. The requirement that RTCP was mandatory for RTP sessions + using IP multicast was relaxed. However, a clarification was also + added that turning off RTCP is NOT RECOMMENDED. + + o In Sections 6.2, 6.3.1 and Appendix A.7, it is specified that the + fraction of participants below which senders get dedicated RTCP + bandwidth changes from the fixed 1/4 to a ratio based on the RTCP + sender and non-sender bandwidth parameters when those are given. + The condition that no bandwidth is dedicated to senders when there + are no senders was removed since that is expected to be a + transitory state. It also keeps non-senders from using sender + RTCP bandwidth when that is not intended. + + o Also in Section 6.2 it is specified that the minimum RTCP interval + may be scaled to smaller values for high bandwidth sessions, and + that the initial RTCP delay may be set to zero for unicast + sessions. + + o Timing out a participant is to be based on inactivity for a number + of RTCP report intervals calculated using the receiver RTCP + bandwidth fraction even for active senders. + + o Sections 7.2 and 7.3 specify that translators and mixers should + send BYE packets for the sources they are no longer forwarding. + + o Rule changes for layered encodings are defined in Sections 2.4, + 6.3.9, 8.3 and 11. In the last of these, it is noted that the + address and port assignment rule conflicts with the SDP + specification, RFC 2327 [15], but it is intended that this + restriction will be relaxed in a revision of RFC 2327. + + o The convention for using even/odd port pairs for RTP and RTCP in + Section 11 was clarified to refer to destination ports. The + requirement to use an even/odd port pair was removed if the two + ports are specified explicitly. For unicast RTP sessions, + distinct port pairs may be used for the two ends (Sections 3, 7.1 + and 11). + + o A new Section 10 was added to explain the requirement for + congestion control in applications using RTP. + + o In Section 8.2, the requirement that a new SSRC identifier MUST be + chosen whenever the source transport address is changed has been + relaxed to say that a new SSRC identifier MAY be chosen. + Correspondingly, it was clarified that an implementation MAY + + + +Schulzrinne, et al. Standards Track [Page 96] + +RFC 3550 RTP July 2003 + + + choose to keep packets from the new source address rather than the + existing source address when an SSRC collision occurs between two + other participants, and SHOULD do so for applications such as + telephony in which some sources such as mobile entities may change + addresses during the course of an RTP session. + + o An indentation bug in the RFC 1889 printing of the pseudo-code for + the collision detection and resolution algorithm in Section 8.2 + has been corrected by translating the syntax to pseudo C language, + and the algorithm has been modified to remove the restriction that + both RTP and RTCP must be sent from the same source port number. + + o The description of the padding mechanism for RTCP packets was + clarified and it is specified that padding MUST only be applied to + the last packet of a compound RTCP packet. + + o In Section A.1, initialization of base_seq was corrected to be seq + rather than seq - 1, and the text was corrected to say the bad + sequence number plus 1 is stored. The initialization of max_seq + and other variables for the algorithm was separated from the text + to make clear that this initialization must be done in addition to + calling the init_seq() function (and a few words lost in RFC 1889 + when processing the document from source to output form were + restored). + + o Clamping of number of packets lost in Section A.3 was corrected to + use both positive and negative limits. + + o The specification of "relative" NTP timestamp in the RTCP SR + section now defines these timestamps to be based on the most + common system-specific clock, such as system uptime, rather than + on session elapsed time which would not be the same for multiple + applications started on the same machine at different times. + + Non-functional changes: + + o It is specified that a receiver MUST ignore packets with payload + types it does not understand. + + o In Fig. 2, the floating point NTP timestamp value was corrected, + some missing leading zeros were added in a hex number, and the UTC + timezone was specified. + + o The inconsequence of NTP timestamps wrapping around in the year + 2036 is explained. + + + + + + +Schulzrinne, et al. Standards Track [Page 97] + +RFC 3550 RTP July 2003 + + + o The policy for registration of RTCP packet types and SDES types + was clarified in a new Section 15, IANA Considerations. The + suggestion that experimenters register the numbers they need and + then unregister those which prove to be unneeded has been removed + in favor of using APP and PRIV. Registration of profile names was + also specified. + + o The reference for the UTF-8 character set was changed from an + X/Open Preliminary Specification to be RFC 2279. + + o The reference for RFC 1597 was updated to RFC 1918 and the + reference for RFC 2543 was updated to RFC 3261. + + o The last paragraph of the introduction in RFC 1889, which + cautioned implementors to limit deployment in the Internet, was + removed because it was deemed no longer relevant. + + o A non-normative note regarding the use of RTP with Source-Specific + Multicast (SSM) was added in Section 6. + + o The definition of "RTP session" in Section 3 was expanded to + acknowledge that a single session may use multiple destination + transport addresses (as was always the case for a translator or + mixer) and to explain that the distinguishing feature of an RTP + session is that each corresponds to a separate SSRC identifier + space. A new definition of "multimedia session" was added to + reduce confusion about the word "session". + + o The meaning of "sampling instant" was explained in more detail as + part of the definition of the timestamp field of the RTP header in + Section 5.1. + + o Small clarifications of the text have been made in several places, + some in response to questions from readers. In particular: + + - In RFC 1889, the first five words of the second sentence of + Section 2.2 were lost in processing the document from source to + output form, but are now restored. + + - A definition for "RTP media type" was added in Section 3 to + allow the explanation of multiplexing RTP sessions in Section + 5.2 to be more clear regarding the multiplexing of multiple + media. That section also now explains that multiplexing + multiple sources of the same medium based on SSRC identifiers + may be appropriate and is the norm for multicast sessions. + + - The definition for "non-RTP means" was expanded to include + examples of other protocols constituting non-RTP means. + + + +Schulzrinne, et al. Standards Track [Page 98] + +RFC 3550 RTP July 2003 + + + - The description of the session bandwidth parameter is expanded + in Section 6.2, including a clarification that the control + traffic bandwidth is in addition to the session bandwidth for + the data traffic. + + - The effect of varying packet duration on the jitter calculation + was explained in Section 6.4.4. + + - The method for terminating and padding a sequence of SDES items + was clarified in Section 6.5. + + - IPv6 address examples were added in the description of SDES + CNAME in Section 6.5.1, and "example.com" was used in place of + other example domain names. + + - The Security section added a formal reference to IPSEC now that + it is available, and says that the confidentiality method + defined in this specification is primarily to codify existing + practice. It is RECOMMENDED that stronger encryption + algorithms such as Triple-DES be used in place of the default + algorithm, and noted that the SRTP profile based on AES will be + the correct choice in the future. A caution about the weakness + of the RTP header as an initialization vector was added. It + was also noted that payload-only encryption is necessary to + allow for header compression. + + - The method for partial encryption of RTCP was clarified; in + particular, SDES CNAME is carried in only one part when the + compound RTCP packet is split. + + - It is clarified that only one compound RTCP packet should be + sent per reporting interval and that if there are too many + active sources for the reports to fit in the MTU, then a subset + of the sources should be selected round-robin over multiple + intervals. + + - A note was added in Appendix A.1 that packets may be saved + during RTP header validation and delivered upon success. + + - Section 7.3 now explains that a mixer aggregating SDES packets + uses more RTCP bandwidth due to longer packets, and a mixer + passing through RTCP naturally sends packets at higher than the + single source rate, but both behaviors are valid. + + - Section 13 clarifies that an RTP application may use multiple + profiles but typically only one in a given session. + + + + + +Schulzrinne, et al. Standards Track [Page 99] + +RFC 3550 RTP July 2003 + + + - The terms MUST, SHOULD, MAY, etc. are used as defined in RFC + 2119. + + - The bibliography was divided into normative and informative + references. + +References + +Normative References + + [1] Schulzrinne, H. and S. Casner, "RTP Profile for Audio and Video + Conferences with Minimal Control", RFC 3551, July 2003. + + [2] Bradner, S., "Key Words for Use in RFCs to Indicate Requirement + Levels", BCP 14, RFC 2119, March 1997. + + [3] Postel, J., "Internet Protocol", STD 5, RFC 791, September 1981. + + [4] Mills, D., "Network Time Protocol (Version 3) Specification, + Implementation and Analysis", RFC 1305, March 1992. + + [5] Yergeau, F., "UTF-8, a Transformation Format of ISO 10646", RFC + 2279, January 1998. + + [6] Mockapetris, P., "Domain Names - Concepts and Facilities", STD + 13, RFC 1034, November 1987. + + [7] Mockapetris, P., "Domain Names - Implementation and + Specification", STD 13, RFC 1035, November 1987. + + [8] Braden, R., "Requirements for Internet Hosts - Application and + Support", STD 3, RFC 1123, October 1989. + + [9] Resnick, P., "Internet Message Format", RFC 2822, April 2001. + +Informative References + + [10] Clark, D. and D. Tennenhouse, "Architectural Considerations for + a New Generation of Protocols," in SIGCOMM Symposium on + Communications Architectures and Protocols , (Philadelphia, + Pennsylvania), pp. 200--208, IEEE Computer Communications + Review, Vol. 20(4), September 1990. + + [11] Schulzrinne, H., "Issues in designing a transport protocol for + audio and video conferences and other multiparticipant real-time + applications." expired Internet Draft, October 1993. + + + + + +Schulzrinne, et al. Standards Track [Page 100] + +RFC 3550 RTP July 2003 + + + [12] Comer, D., Internetworking with TCP/IP , vol. 1. Englewood + Cliffs, New Jersey: Prentice Hall, 1991. + + [13] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., + Peterson, J., Sparks, R., Handley, M. and E. Schooler, "SIP: + Session Initiation Protocol", RFC 3261, June 2002. + + [14] International Telecommunication Union, "Visual telephone systems + and equipment for local area networks which provide a non- + guaranteed quality of service", Recommendation H.323, + Telecommunication Standardization Sector of ITU, Geneva, + Switzerland, July 2003. + + [15] Handley, M. and V. Jacobson, "SDP: Session Description + Protocol", RFC 2327, April 1998. + + [16] Schulzrinne, H., Rao, A. and R. Lanphier, "Real Time Streaming + Protocol (RTSP)", RFC 2326, April 1998. + + [17] Eastlake 3rd, D., Crocker, S. and J. Schiller, "Randomness + Recommendations for Security", RFC 1750, December 1994. + + [18] Bolot, J.-C., Turletti, T. and I. Wakeman, "Scalable Feedback + Control for Multicast Video Distribution in the Internet", in + SIGCOMM Symposium on Communications Architectures and Protocols, + (London, England), pp. 58--67, ACM, August 1994. + + [19] Busse, I., Deffner, B. and H. Schulzrinne, "Dynamic QoS Control + of Multimedia Applications Based on RTP", Computer + Communications , vol. 19, pp. 49--58, January 1996. + + [20] Floyd, S. and V. Jacobson, "The Synchronization of Periodic + Routing Messages", in SIGCOMM Symposium on Communications + Architectures and Protocols (D. P. Sidhu, ed.), (San Francisco, + California), pp. 33--44, ACM, September 1993. Also in [34]. + + [21] Rosenberg, J. and H. Schulzrinne, "Sampling of the Group + Membership in RTP", RFC 2762, February 2000. + + [22] Cadzow, J., Foundations of Digital Signal Processing and Data + Analysis New York, New York: Macmillan, 1987. + + [23] Hinden, R. and S. Deering, "Internet Protocol Version 6 (IPv6) + Addressing Architecture", RFC 3513, April 2003. + + [24] Rekhter, Y., Moskowitz, B., Karrenberg, D., de Groot, G. and E. + Lear, "Address Allocation for Private Internets", RFC 1918, + February 1996. + + + +Schulzrinne, et al. Standards Track [Page 101] + +RFC 3550 RTP July 2003 + + + [25] Lear, E., Fair, E., Crocker, D. and T. Kessler, "Network 10 + Considered Harmful (Some Practices Shouldn't be Codified)", RFC + 1627, July 1994. + + [26] Feller, W., An Introduction to Probability Theory and its + Applications, vol. 1. New York, New York: John Wiley and Sons, + third ed., 1968. + + [27] Kent, S. and R. Atkinson, "Security Architecture for the + Internet Protocol", RFC 2401, November 1998. + + [28] Baugher, M., Blom, R., Carrara, E., McGrew, D., Naslund, M., + Norrman, K. and D. Oran, "Secure Real-time Transport Protocol", + Work in Progress, April 2003. + + [29] Balenson, D., "Privacy Enhancement for Internet Electronic Mail: + Part III", RFC 1423, February 1993. + + [30] Voydock, V. and S. Kent, "Security Mechanisms in High-Level + Network Protocols", ACM Computing Surveys, vol. 15, pp. 135-171, + June 1983. + + [31] Floyd, S., "Congestion Control Principles", BCP 41, RFC 2914, + September 2000. + + [32] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April + 1992. + + [33] Stubblebine, S., "Security Services for Multimedia + Conferencing", in 16th National Computer Security Conference, + (Baltimore, Maryland), pp. 391--395, September 1993. + + [34] Floyd, S. and V. Jacobson, "The Synchronization of Periodic + Routing Messages", IEEE/ACM Transactions on Networking, vol. 2, + pp. 122--136, April 1994. + + + + + + + + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 102] + +RFC 3550 RTP July 2003 + + +Authors' Addresses + + Henning Schulzrinne + Department of Computer Science + Columbia University + 1214 Amsterdam Avenue + New York, NY 10027 + United States + + EMail: schulzrinne@cs.columbia.edu + + + Stephen L. Casner + Packet Design + 3400 Hillview Avenue, Building 3 + Palo Alto, CA 94304 + United States + + EMail: casner@acm.org + + + Ron Frederick + Blue Coat Systems Inc. + 650 Almanor Avenue + Sunnyvale, CA 94085 + United States + + EMail: ronf@bluecoat.com + + + Van Jacobson + Packet Design + 3400 Hillview Avenue, Building 3 + Palo Alto, CA 94304 + United States + + EMail: van@packetdesign.com + + + + + + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 103] + +RFC 3550 RTP July 2003 + + +Full Copyright Statement + + Copyright (C) The Internet Society (2003). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Schulzrinne, et al. Standards Track [Page 104] + diff --git a/src/modules/rtp/rfc3551.txt b/src/modules/rtp/rfc3551.txt new file mode 100644 index 000000000..c43ff34d2 --- /dev/null +++ b/src/modules/rtp/rfc3551.txt @@ -0,0 +1,2467 @@ + + + + + + +Network Working Group H. Schulzrinne +Request for Comments: 3551 Columbia University +Obsoletes: 1890 S. Casner +Category: Standards Track Packet Design + July 2003 + + + RTP Profile for Audio and Video Conferences + with Minimal Control + +Status of this Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2003). All Rights Reserved. + +Abstract + + This document describes a profile called "RTP/AVP" for the use of the + real-time transport protocol (RTP), version 2, and the associated + control protocol, RTCP, within audio and video multiparticipant + conferences with minimal control. It provides interpretations of + generic fields within the RTP specification suitable for audio and + video conferences. In particular, this document defines a set of + default mappings from payload type numbers to encodings. + + This document also describes how audio and video data may be carried + within RTP. It defines a set of standard encodings and their names + when used within RTP. The descriptions provide pointers to reference + implementations and the detailed standards. This document is meant + as an aid for implementors of audio, video and other real-time + multimedia applications. + + This memorandum obsoletes RFC 1890. It is mostly backwards- + compatible except for functions removed because two interoperable + implementations were not found. The additions to RFC 1890 codify + existing practice in the use of payload formats under this profile + and include new payload formats defined since RFC 1890 was published. + + + + + + + +Schulzrinne & Casner Standards Track [Page 1] + +RFC 3551 RTP A/V Profile July 2003 + + +Table of Contents + + 1. Introduction ................................................. 3 + 1.1 Terminology ............................................. 3 + 2. RTP and RTCP Packet Forms and Protocol Behavior .............. 4 + 3. Registering Additional Encodings ............................. 6 + 4. Audio ........................................................ 8 + 4.1 Encoding-Independent Rules .............................. 8 + 4.2 Operating Recommendations ............................... 9 + 4.3 Guidelines for Sample-Based Audio Encodings ............. 10 + 4.4 Guidelines for Frame-Based Audio Encodings .............. 11 + 4.5 Audio Encodings ......................................... 12 + 4.5.1 DVI4 ............................................ 13 + 4.5.2 G722 ............................................ 14 + 4.5.3 G723 ............................................ 14 + 4.5.4 G726-40, G726-32, G726-24, and G726-16 .......... 18 + 4.5.5 G728 ............................................ 19 + 4.5.6 G729 ............................................ 20 + 4.5.7 G729D and G729E ................................. 22 + 4.5.8 GSM ............................................. 24 + 4.5.9 GSM-EFR ......................................... 27 + 4.5.10 L8 .............................................. 27 + 4.5.11 L16 ............................................. 27 + 4.5.12 LPC ............................................. 27 + 4.5.13 MPA ............................................. 28 + 4.5.14 PCMA and PCMU ................................... 28 + 4.5.15 QCELP ........................................... 28 + 4.5.16 RED ............................................. 29 + 4.5.17 VDVI ............................................ 29 + 5. Video ........................................................ 30 + 5.1 CelB .................................................... 30 + 5.2 JPEG .................................................... 30 + 5.3 H261 .................................................... 30 + 5.4 H263 .................................................... 31 + 5.5 H263-1998 ............................................... 31 + 5.6 MPV ..................................................... 31 + 5.7 MP2T .................................................... 31 + 5.8 nv ...................................................... 32 + 6. Payload Type Definitions ..................................... 32 + 7. RTP over TCP and Similar Byte Stream Protocols ............... 34 + 8. Port Assignment .............................................. 34 + 9. Changes from RFC 1890 ........................................ 35 + 10. Security Considerations ...................................... 38 + 11. IANA Considerations .......................................... 39 + 12. References ................................................... 39 + 12.1 Normative References .................................... 39 + 12.2 Informative References .................................. 39 + 13. Current Locations of Related Resources ....................... 41 + + + +Schulzrinne & Casner Standards Track [Page 2] + +RFC 3551 RTP A/V Profile July 2003 + + + 14. Acknowledgments .............................................. 42 + 15. Intellectual Property Rights Statement ....................... 43 + 16. Authors' Addresses ........................................... 43 + 17. Full Copyright Statement ..................................... 44 + +1. Introduction + + This profile defines aspects of RTP left unspecified in the RTP + Version 2 protocol definition (RFC 3550) [1]. This profile is + intended for the use within audio and video conferences with minimal + session control. In particular, no support for the negotiation of + parameters or membership control is provided. The profile is + expected to be useful in sessions where no negotiation or membership + control are used (e.g., using the static payload types and the + membership indications provided by RTCP), but this profile may also + be useful in conjunction with a higher-level control protocol. + + Use of this profile may be implicit in the use of the appropriate + applications; there may be no explicit indication by port number, + protocol identifier or the like. Applications such as session + directories may use the name for this profile specified in Section + 11. + + Other profiles may make different choices for the items specified + here. + + This document also defines a set of encodings and payload formats for + audio and video. These payload format descriptions are included here + only as a matter of convenience since they are too small to warrant + separate documents. Use of these payload formats is NOT REQUIRED to + use this profile. Only the binding of some of the payload formats to + static payload type numbers in Tables 4 and 5 is normative. + +1.1 Terminology + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119 [2] and + indicate requirement levels for implementations compliant with this + RTP profile. + + This document defines the term media type as dividing encodings of + audio and video content into three classes: audio, video and + audio/video (interleaved). + + + + + + + +Schulzrinne & Casner Standards Track [Page 3] + +RFC 3551 RTP A/V Profile July 2003 + + +2. RTP and RTCP Packet Forms and Protocol Behavior + + The section "RTP Profiles and Payload Format Specifications" of RFC + 3550 enumerates a number of items that can be specified or modified + in a profile. This section addresses these items. Generally, this + profile follows the default and/or recommended aspects of the RTP + specification. + + RTP data header: The standard format of the fixed RTP data + header is used (one marker bit). + + Payload types: Static payload types are defined in Section 6. + + RTP data header additions: No additional fixed fields are + appended to the RTP data header. + + RTP data header extensions: No RTP header extensions are + defined, but applications operating under this profile MAY use + such extensions. Thus, applications SHOULD NOT assume that the + RTP header X bit is always zero and SHOULD be prepared to ignore + the header extension. If a header extension is defined in the + future, that definition MUST specify the contents of the first 16 + bits in such a way that multiple different extensions can be + identified. + + RTCP packet types: No additional RTCP packet types are defined + by this profile specification. + + RTCP report interval: The suggested constants are to be used for + the RTCP report interval calculation. Sessions operating under + this profile MAY specify a separate parameter for the RTCP traffic + bandwidth rather than using the default fraction of the session + bandwidth. The RTCP traffic bandwidth MAY be divided into two + separate session parameters for those participants which are + active data senders and those which are not. Following the + recommendation in the RTP specification [1] that 1/4 of the RTCP + bandwidth be dedicated to data senders, the RECOMMENDED default + values for these two parameters would be 1.25% and 3.75%, + respectively. For a particular session, the RTCP bandwidth for + non-data-senders MAY be set to zero when operating on + unidirectional links or for sessions that don't require feedback + on the quality of reception. The RTCP bandwidth for data senders + SHOULD be kept non-zero so that sender reports can still be sent + for inter-media synchronization and to identify the source by + CNAME. The means by which the one or two session parameters for + RTCP bandwidth are specified is beyond the scope of this memo. + + + + + +Schulzrinne & Casner Standards Track [Page 4] + +RFC 3551 RTP A/V Profile July 2003 + + + SR/RR extension: No extension section is defined for the RTCP SR + or RR packet. + + SDES use: Applications MAY use any of the SDES items described + in the RTP specification. While CNAME information MUST be sent + every reporting interval, other items SHOULD only be sent every + third reporting interval, with NAME sent seven out of eight times + within that slot and the remaining SDES items cyclically taking up + the eighth slot, as defined in Section 6.2.2 of the RTP + specification. In other words, NAME is sent in RTCP packets 1, 4, + 7, 10, 13, 16, 19, while, say, EMAIL is used in RTCP packet 22. + + Security: The RTP default security services are also the default + under this profile. + + String-to-key mapping: No mapping is specified by this profile. + + Congestion: RTP and this profile may be used in the context of + enhanced network service, for example, through Integrated Services + (RFC 1633) [4] or Differentiated Services (RFC 2475) [5], or they + may be used with best effort service. + + If enhanced service is being used, RTP receivers SHOULD monitor + packet loss to ensure that the service that was requested is + actually being delivered. If it is not, then they SHOULD assume + that they are receiving best-effort service and behave + accordingly. + + If best-effort service is being used, RTP receivers SHOULD monitor + packet loss to ensure that the packet loss rate is within + acceptable parameters. Packet loss is considered acceptable if a + TCP flow across the same network path and experiencing the same + network conditions would achieve an average throughput, measured + on a reasonable timescale, that is not less than the RTP flow is + achieving. This condition can be satisfied by implementing + congestion control mechanisms to adapt the transmission rate (or + the number of layers subscribed for a layered multicast session), + or by arranging for a receiver to leave the session if the loss + rate is unacceptably high. + + The comparison to TCP cannot be specified exactly, but is intended + as an "order-of-magnitude" comparison in timescale and throughput. + The timescale on which TCP throughput is measured is the round- + trip time of the connection. In essence, this requirement states + that it is not acceptable to deploy an application (using RTP or + any other transport protocol) on the best-effort Internet which + consumes bandwidth arbitrarily and does not compete fairly with + TCP within an order of magnitude. + + + +Schulzrinne & Casner Standards Track [Page 5] + +RFC 3551 RTP A/V Profile July 2003 + + + Underlying protocol: The profile specifies the use of RTP over + unicast and multicast UDP as well as TCP. (This does not preclude + the use of these definitions when RTP is carried by other lower- + layer protocols.) + + Transport mapping: The standard mapping of RTP and RTCP to + transport-level addresses is used. + + Encapsulation: This profile leaves to applications the + specification of RTP encapsulation in protocols other than UDP. + +3. Registering Additional Encodings + + This profile lists a set of encodings, each of which is comprised of + a particular media data compression or representation plus a payload + format for encapsulation within RTP. Some of those payload formats + are specified here, while others are specified in separate RFCs. It + is expected that additional encodings beyond the set listed here will + be created in the future and specified in additional payload format + RFCs. + + This profile also assigns to each encoding a short name which MAY be + used by higher-level control protocols, such as the Session + Description Protocol (SDP), RFC 2327 [6], to identify encodings + selected for a particular RTP session. + + In some contexts it may be useful to refer to these encodings in the + form of a MIME content-type. To facilitate this, RFC 3555 [7] + provides registrations for all of the encodings names listed here as + MIME subtype names under the "audio" and "video" MIME types through + the MIME registration procedure as specified in RFC 2048 [8]. + + Any additional encodings specified for use under this profile (or + others) may also be assigned names registered as MIME subtypes with + the Internet Assigned Numbers Authority (IANA). This registry + provides a means to insure that the names assigned to the additional + encodings are kept unique. RFC 3555 specifies the information that + is required for the registration of RTP encodings. + + In addition to assigning names to encodings, this profile also + assigns static RTP payload type numbers to some of them. However, + the payload type number space is relatively small and cannot + accommodate assignments for all existing and future encodings. + During the early stages of RTP development, it was necessary to use + statically assigned payload types because no other mechanism had been + specified to bind encodings to payload types. It was anticipated + that non-RTP means beyond the scope of this memo (such as directory + services or invitation protocols) would be specified to establish a + + + +Schulzrinne & Casner Standards Track [Page 6] + +RFC 3551 RTP A/V Profile July 2003 + + + dynamic mapping between a payload type and an encoding. Now, + mechanisms for defining dynamic payload type bindings have been + specified in the Session Description Protocol (SDP) and in other + protocols such as ITU-T Recommendation H.323/H.245. These mechanisms + associate the registered name of the encoding/payload format, along + with any additional required parameters, such as the RTP timestamp + clock rate and number of channels, with a payload type number. This + association is effective only for the duration of the RTP session in + which the dynamic payload type binding is made. This association + applies only to the RTP session for which it is made, thus the + numbers can be re-used for different encodings in different sessions + so the number space limitation is avoided. + + This profile reserves payload type numbers in the range 96-127 + exclusively for dynamic assignment. Applications SHOULD first use + values in this range for dynamic payload types. Those applications + which need to define more than 32 dynamic payload types MAY bind + codes below 96, in which case it is RECOMMENDED that unassigned + payload type numbers be used first. However, the statically assigned + payload types are default bindings and MAY be dynamically bound to + new encodings if needed. Redefining payload types below 96 may cause + incorrect operation if an attempt is made to join a session without + obtaining session description information that defines the dynamic + payload types. + + Dynamic payload types SHOULD NOT be used without a well-defined + mechanism to indicate the mapping. Systems that expect to + interoperate with others operating under this profile SHOULD NOT make + their own assignments of proprietary encodings to particular, fixed + payload types. + + This specification establishes the policy that no additional static + payload types will be assigned beyond the ones defined in this + document. Establishing this policy avoids the problem of trying to + create a set of criteria for accepting static assignments and + encourages the implementation and deployment of the dynamic payload + type mechanisms. + + The final set of static payload type assignments is provided in + Tables 4 and 5. + + + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 7] + +RFC 3551 RTP A/V Profile July 2003 + + +4. Audio + +4.1 Encoding-Independent Rules + + Since the ability to suppress silence is one of the primary + motivations for using packets to transmit voice, the RTP header + carries both a sequence number and a timestamp to allow a receiver to + distinguish between lost packets and periods of time when no data was + transmitted. Discontiguous transmission (silence suppression) MAY be + used with any audio payload format. Receivers MUST assume that + senders may suppress silence unless this is restricted by signaling + specified elsewhere. (Even if the transmitter does not suppress + silence, the receiver should be prepared to handle periods when no + data is present since packets may be lost.) + + Some payload formats (see Sections 4.5.3 and 4.5.6) define a "silence + insertion descriptor" or "comfort noise" frame to specify parameters + for artificial noise that may be generated during a period of silence + to approximate the background noise at the source. For other payload + formats, a generic Comfort Noise (CN) payload format is specified in + RFC 3389 [9]. When the CN payload format is used with another + payload format, different values in the RTP payload type field + distinguish comfort-noise packets from those of the selected payload + format. + + For applications which send either no packets or occasional comfort- + noise packets during silence, the first packet of a talkspurt, that + is, the first packet after a silence period during which packets have + not been transmitted contiguously, SHOULD be distinguished by setting + the marker bit in the RTP data header to one. The marker bit in all + other packets is zero. The beginning of a talkspurt MAY be used to + adjust the playout delay to reflect changing network delays. + Applications without silence suppression MUST set the marker bit to + zero. + + The RTP clock rate used for generating the RTP timestamp is + independent of the number of channels and the encoding; it usually + equals the number of sampling periods per second. For N-channel + encodings, each sampling period (say, 1/8,000 of a second) generates + N samples. (This terminology is standard, but somewhat confusing, as + the total number of samples generated per second is then the sampling + rate times the channel count.) + + If multiple audio channels are used, channels are numbered left-to- + right, starting at one. In RTP audio packets, information from + lower-numbered channels precedes that from higher-numbered channels. + + + + + +Schulzrinne & Casner Standards Track [Page 8] + +RFC 3551 RTP A/V Profile July 2003 + + + For more than two channels, the convention followed by the AIFF-C + audio interchange format SHOULD be followed [3], using the following + notation, unless some other convention is specified for a particular + encoding or payload format: + + l left + r right + c center + S surround + F front + R rear + + channels description channel + 1 2 3 4 5 6 + _________________________________________________ + 2 stereo l r + 3 l r c + 4 l c r S + 5 Fl Fr Fc Sl Sr + 6 l lc c r rc S + + Note: RFC 1890 defined two conventions for the ordering of four + audio channels. Since the ordering is indicated implicitly by + the number of channels, this was ambiguous. In this revision, + the order described as "quadrophonic" has been eliminated to + remove the ambiguity. This choice was based on the observation + that quadrophonic consumer audio format did not become popular + whereas surround-sound subsequently has. + + Samples for all channels belonging to a single sampling instant MUST + be within the same packet. The interleaving of samples from + different channels depends on the encoding. General guidelines are + given in Section 4.3 and 4.4. + + The sampling frequency SHOULD be drawn from the set: 8,000, 11,025, + 16,000, 22,050, 24,000, 32,000, 44,100 and 48,000 Hz. (Older Apple + Macintosh computers had a native sample rate of 22,254.54 Hz, which + can be converted to 22,050 with acceptable quality by dropping 4 + samples in a 20 ms frame.) However, most audio encodings are defined + for a more restricted set of sampling frequencies. Receivers SHOULD + be prepared to accept multi-channel audio, but MAY choose to only + play a single channel. + +4.2 Operating Recommendations + + The following recommendations are default operating parameters. + Applications SHOULD be prepared to handle other values. The ranges + given are meant to give guidance to application writers, allowing a + + + +Schulzrinne & Casner Standards Track [Page 9] + +RFC 3551 RTP A/V Profile July 2003 + + + set of applications conforming to these guidelines to interoperate + without additional negotiation. These guidelines are not intended to + restrict operating parameters for applications that can negotiate a + set of interoperable parameters, e.g., through a conference control + protocol. + + For packetized audio, the default packetization interval SHOULD have + a duration of 20 ms or one frame, whichever is longer, unless + otherwise noted in Table 1 (column "ms/packet"). The packetization + interval determines the minimum end-to-end delay; longer packets + introduce less header overhead but higher delay and make packet loss + more noticeable. For non-interactive applications such as lectures + or for links with severe bandwidth constraints, a higher + packetization delay MAY be used. A receiver SHOULD accept packets + representing between 0 and 200 ms of audio data. (For framed audio + encodings, a receiver SHOULD accept packets with a number of frames + equal to 200 ms divided by the frame duration, rounded up.) This + restriction allows reasonable buffer sizing for the receiver. + +4.3 Guidelines for Sample-Based Audio Encodings + + In sample-based encodings, each audio sample is represented by a + fixed number of bits. Within the compressed audio data, codes for + individual samples may span octet boundaries. An RTP audio packet + may contain any number of audio samples, subject to the constraint + that the number of bits per sample times the number of samples per + packet yields an integral octet count. Fractional encodings produce + less than one octet per sample. + + The duration of an audio packet is determined by the number of + samples in the packet. + + For sample-based encodings producing one or more octets per sample, + samples from different channels sampled at the same sampling instant + SHOULD be packed in consecutive octets. For example, for a two- + channel encoding, the octet sequence is (left channel, first sample), + (right channel, first sample), (left channel, second sample), (right + channel, second sample), .... For multi-octet encodings, octets + SHOULD be transmitted in network byte order (i.e., most significant + octet first). + + The packing of sample-based encodings producing less than one octet + per sample is encoding-specific. + + The RTP timestamp reflects the instant at which the first sample in + the packet was sampled, that is, the oldest information in the + packet. + + + + +Schulzrinne & Casner Standards Track [Page 10] + +RFC 3551 RTP A/V Profile July 2003 + + +4.4 Guidelines for Frame-Based Audio Encodings + + Frame-based encodings encode a fixed-length block of audio into + another block of compressed data, typically also of fixed length. + For frame-based encodings, the sender MAY choose to combine several + such frames into a single RTP packet. The receiver can tell the + number of frames contained in an RTP packet, if all the frames have + the same length, by dividing the RTP payload length by the audio + frame size which is defined as part of the encoding. This does not + work when carrying frames of different sizes unless the frame sizes + are relatively prime. If not, the frames MUST indicate their size. + + For frame-based codecs, the channel order is defined for the whole + block. That is, for two-channel audio, right and left samples SHOULD + be coded independently, with the encoded frame for the left channel + preceding that for the right channel. + + All frame-oriented audio codecs SHOULD be able to encode and decode + several consecutive frames within a single packet. Since the frame + size for the frame-oriented codecs is given, there is no need to use + a separate designation for the same encoding, but with different + number of frames per packet. + + RTP packets SHALL contain a whole number of frames, with frames + inserted according to age within a packet, so that the oldest frame + (to be played first) occurs immediately after the RTP packet header. + The RTP timestamp reflects the instant at which the first sample in + the first frame was sampled, that is, the oldest information in the + packet. + + + + + + + + + + + + + + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 11] + +RFC 3551 RTP A/V Profile July 2003 + + +4.5 Audio Encodings + + name of sampling default + encoding sample/frame bits/sample rate ms/frame ms/packet + __________________________________________________________________ + DVI4 sample 4 var. 20 + G722 sample 8 16,000 20 + G723 frame N/A 8,000 30 30 + G726-40 sample 5 8,000 20 + G726-32 sample 4 8,000 20 + G726-24 sample 3 8,000 20 + G726-16 sample 2 8,000 20 + G728 frame N/A 8,000 2.5 20 + G729 frame N/A 8,000 10 20 + G729D frame N/A 8,000 10 20 + G729E frame N/A 8,000 10 20 + GSM frame N/A 8,000 20 20 + GSM-EFR frame N/A 8,000 20 20 + L8 sample 8 var. 20 + L16 sample 16 var. 20 + LPC frame N/A 8,000 20 20 + MPA frame N/A var. var. + PCMA sample 8 var. 20 + PCMU sample 8 var. 20 + QCELP frame N/A 8,000 20 20 + VDVI sample var. var. 20 + + Table 1: Properties of Audio Encodings (N/A: not applicable; var.: + variable) + + The characteristics of the audio encodings described in this document + are shown in Table 1; they are listed in order of their payload type + in Table 4. While most audio codecs are only specified for a fixed + sampling rate, some sample-based algorithms (indicated by an entry of + "var." in the sampling rate column of Table 1) may be used with + different sampling rates, resulting in different coded bit rates. + When used with a sampling rate other than that for which a static + payload type is defined, non-RTP means beyond the scope of this memo + MUST be used to define a dynamic payload type and MUST indicate the + selected RTP timestamp clock rate, which is usually the same as the + sampling rate for audio. + + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 12] + +RFC 3551 RTP A/V Profile July 2003 + + +4.5.1 DVI4 + + DVI4 uses an adaptive delta pulse code modulation (ADPCM) encoding + scheme that was specified by the Interactive Multimedia Association + (IMA) as the "IMA ADPCM wave type". However, the encoding defined + here as DVI4 differs in three respects from the IMA specification: + + o The RTP DVI4 header contains the predicted value rather than the + first sample value contained the IMA ADPCM block header. + + o IMA ADPCM blocks contain an odd number of samples, since the first + sample of a block is contained just in the header (uncompressed), + followed by an even number of compressed samples. DVI4 has an + even number of compressed samples only, using the `predict' word + from the header to decode the first sample. + + o For DVI4, the 4-bit samples are packed with the first sample in + the four most significant bits and the second sample in the four + least significant bits. In the IMA ADPCM codec, the samples are + packed in the opposite order. + + Each packet contains a single DVI block. This profile only defines + the 4-bit-per-sample version, while IMA also specified a 3-bit-per- + sample encoding. + + The "header" word for each channel has the following structure: + + int16 predict; /* predicted value of first sample + from the previous block (L16 format) */ + u_int8 index; /* current index into stepsize table */ + u_int8 reserved; /* set to zero by sender, ignored by receiver */ + + Each octet following the header contains two 4-bit samples, thus the + number of samples per packet MUST be even because there is no means + to indicate a partially filled last octet. + + Packing of samples for multiple channels is for further study. + + The IMA ADPCM algorithm was described in the document IMA Recommended + Practices for Enhancing Digital Audio Compatibility in Multimedia + Systems (version 3.0). However, the Interactive Multimedia + Association ceased operations in 1997. Resources for an archived + copy of that document and a software implementation of the RTP DVI4 + encoding are listed in Section 13. + + + + + + + +Schulzrinne & Casner Standards Track [Page 13] + +RFC 3551 RTP A/V Profile July 2003 + + +4.5.2 G722 + + G722 is specified in ITU-T Recommendation G.722, "7 kHz audio-coding + within 64 kbit/s". The G.722 encoder produces a stream of octets, + each of which SHALL be octet-aligned in an RTP packet. The first bit + transmitted in the G.722 octet, which is the most significant bit of + the higher sub-band sample, SHALL correspond to the most significant + bit of the octet in the RTP packet. + + Even though the actual sampling rate for G.722 audio is 16,000 Hz, + the RTP clock rate for the G722 payload format is 8,000 Hz because + that value was erroneously assigned in RFC 1890 and must remain + unchanged for backward compatibility. The octet rate or sample-pair + rate is 8,000 Hz. + +4.5.3 G723 + + G723 is specified in ITU Recommendation G.723.1, "Dual-rate speech + coder for multimedia communications transmitting at 5.3 and 6.3 + kbit/s". The G.723.1 5.3/6.3 kbit/s codec was defined by the ITU-T + as a mandatory codec for ITU-T H.324 GSTN videophone terminal + applications. The algorithm has a floating point specification in + Annex B to G.723.1, a silence compression algorithm in Annex A to + G.723.1 and a scalable channel coding scheme for wireless + applications in G.723.1 Annex C. + + This Recommendation specifies a coded representation that can be used + for compressing the speech signal component of multi-media services + at a very low bit rate. Audio is encoded in 30 ms frames, with an + additional delay of 7.5 ms due to look-ahead. A G.723.1 frame can be + one of three sizes: 24 octets (6.3 kb/s frame), 20 octets (5.3 kb/s + frame), or 4 octets. These 4-octet frames are called SID frames + (Silence Insertion Descriptor) and are used to specify comfort noise + parameters. There is no restriction on how 4, 20, and 24 octet + frames are intermixed. The least significant two bits of the first + octet in the frame determine the frame size and codec type: + + bits content octets/frame + 00 high-rate speech (6.3 kb/s) 24 + 01 low-rate speech (5.3 kb/s) 20 + 10 SID frame 4 + 11 reserved + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 14] + +RFC 3551 RTP A/V Profile July 2003 + + + It is possible to switch between the two rates at any 30 ms frame + boundary. Both (5.3 kb/s and 6.3 kb/s) rates are a mandatory part of + the encoder and decoder. Receivers MUST accept both data rates and + MUST accept SID frames unless restriction of these capabilities has + been signaled. The MIME registration for G723 in RFC 3555 [7] + specifies parameters that MAY be used with MIME or SDP to restrict to + a single data rate or to restrict the use of SID frames. This coder + was optimized to represent speech with near-toll quality at the above + rates using a limited amount of complexity. + + The packing of the encoded bit stream into octets and the + transmission order of the octets is specified in Rec. G.723.1 and is + the same as that produced by the G.723 C code reference + implementation. For the 6.3 kb/s data rate, this packing is + illustrated as follows, where the header (HDR) bits are always "0 0" + as shown in Fig. 1 to indicate operation at 6.3 kb/s, and the Z bit + is always set to zero. The diagrams show the bit packing in "network + byte order", also known as big-endian order. The bits of each 32-bit + word are numbered 0 to 31, with the most significant bit on the left + and numbered 0. The octets (bytes) of each word are transmitted most + significant octet first. The bits of each data field are numbered in + the order of the bit stream representation of the encoding (least + significant bit first). The vertical bars indicate the boundaries + between field fragments. + + + + + + + + + + + + + + + + + + + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 15] + +RFC 3551 RTP A/V Profile July 2003 + + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | LPC |HDR| LPC | LPC | ACL0 |LPC| + | | | | | | | + |0 0 0 0 0 0|0 0|1 1 1 1 0 0 0 0|2 2 1 1 1 1 1 1|0 0 0 0 0 0|2 2| + |5 4 3 2 1 0| |3 2 1 0 9 8 7 6|1 0 9 8 7 6 5 4|5 4 3 2 1 0|3 2| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ACL2 |ACL|A| GAIN0 |ACL|ACL| GAIN0 | GAIN1 | + | | 1 |C| | 3 | 2 | | | + |0 0 0 0 0|0 0|0|0 0 0 0|0 0|0 0|1 1 0 0 0 0 0 0|0 0 0 0 0 0 0 0| + |4 3 2 1 0|1 0|6|3 2 1 0|1 0|6 5|1 0 9 8 7 6 5 4|7 6 5 4 3 2 1 0| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | GAIN2 | GAIN1 | GAIN2 | GAIN3 | GRID | GAIN3 | + | | | | | | | + |0 0 0 0|1 1 0 0|1 1 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0|1 1 0 0| + |3 2 1 0|1 0 9 8|1 0 9 8 7 6 5 4|7 6 5 4 3 2 1 0|3 2 1 0|1 0 9 8| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | MSBPOS |Z|POS| MSBPOS | POS0 |POS| POS0 | + | | | 0 | | | 1 | | + |0 0 0 0 0 0 0|0|0 0|1 1 1 0 0 0|0 0 0 0 0 0 0 0|0 0|1 1 1 1 1 1| + |6 5 4 3 2 1 0| |1 0|2 1 0 9 8 7|9 8 7 6 5 4 3 2|1 0|5 4 3 2 1 0| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | POS1 | POS2 | POS1 | POS2 | POS3 | POS2 | + | | | | | | | + |0 0 0 0 0 0 0 0|0 0 0 0|1 1 1 1|1 1 0 0 0 0 0 0|0 0 0 0|1 1 1 1| + |9 8 7 6 5 4 3 2|3 2 1 0|3 2 1 0|1 0 9 8 7 6 5 4|3 2 1 0|5 4 3 2| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | POS3 | PSIG0 |POS|PSIG2| PSIG1 | PSIG3 |PSIG2| + | | | 3 | | | | | + |1 1 0 0 0 0 0 0|0 0 0 0 0 0|1 1|0 0 0|0 0 0 0 0|0 0 0 0 0|0 0 0| + |1 0 9 8 7 6 5 4|5 4 3 2 1 0|3 2|2 1 0|4 3 2 1 0|4 3 2 1 0|5 4 3| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 1: G.723 (6.3 kb/s) bit packing + + For the 5.3 kb/s data rate, the header (HDR) bits are always "0 1", + as shown in Fig. 2, to indicate operation at 5.3 kb/s. + + + + + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 16] + +RFC 3551 RTP A/V Profile July 2003 + + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | LPC |HDR| LPC | LPC | ACL0 |LPC| + | | | | | | | + |0 0 0 0 0 0|0 1|1 1 1 1 0 0 0 0|2 2 1 1 1 1 1 1|0 0 0 0 0 0|2 2| + |5 4 3 2 1 0| |3 2 1 0 9 8 7 6|1 0 9 8 7 6 5 4|5 4 3 2 1 0|3 2| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ACL2 |ACL|A| GAIN0 |ACL|ACL| GAIN0 | GAIN1 | + | | 1 |C| | 3 | 2 | | | + |0 0 0 0 0|0 0|0|0 0 0 0|0 0|0 0|1 1 0 0 0 0 0 0|0 0 0 0 0 0 0 0| + |4 3 2 1 0|1 0|6|3 2 1 0|1 0|6 5|1 0 9 8 7 6 5 4|7 6 5 4 3 2 1 0| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | GAIN2 | GAIN1 | GAIN2 | GAIN3 | GRID | GAIN3 | + | | | | | | | + |0 0 0 0|1 1 0 0|1 1 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0|1 1 0 0| + |3 2 1 0|1 0 9 8|1 0 9 8 7 6 5 4|7 6 5 4 3 2 1 0|4 3 2 1|1 0 9 8| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | POS0 | POS1 | POS0 | POS1 | POS2 | + | | | | | | + |0 0 0 0 0 0 0 0|0 0 0 0|1 1 0 0|1 1 0 0 0 0 0 0|0 0 0 0 0 0 0 0| + |7 6 5 4 3 2 1 0|3 2 1 0|1 0 9 8|1 0 9 8 7 6 5 4|7 6 5 4 3 2 1 0| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | POS3 | POS2 | POS3 | PSIG1 | PSIG0 | PSIG3 | PSIG2 | + | | | | | | | | + |0 0 0 0|1 1 0 0|1 1 0 0 0 0 0 0|0 0 0 0|0 0 0 0|0 0 0 0|0 0 0 0| + |3 2 1 0|1 0 9 8|1 0 9 8 7 6 5 4|3 2 1 0|3 2 1 0|3 2 1 0|3 2 1 0| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 2: G.723 (5.3 kb/s) bit packing + + The packing of G.723.1 SID (silence) frames, which are indicated by + the header (HDR) bits having the pattern "1 0", is depicted in Fig. + 3. + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | LPC |HDR| LPC | LPC | GAIN |LPC| + | | | | | | | + |0 0 0 0 0 0|1 0|1 1 1 1 0 0 0 0|2 2 1 1 1 1 1 1|0 0 0 0 0 0|2 2| + |5 4 3 2 1 0| |3 2 1 0 9 8 7 6|1 0 9 8 7 6 5 4|5 4 3 2 1 0|3 2| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 3: G.723 SID mode bit packing + + + + + + +Schulzrinne & Casner Standards Track [Page 17] + +RFC 3551 RTP A/V Profile July 2003 + + +4.5.4 G726-40, G726-32, G726-24, and G726-16 + + ITU-T Recommendation G.726 describes, among others, the algorithm + recommended for conversion of a single 64 kbit/s A-law or mu-law PCM + channel encoded at 8,000 samples/sec to and from a 40, 32, 24, or 16 + kbit/s channel. The conversion is applied to the PCM stream using an + Adaptive Differential Pulse Code Modulation (ADPCM) transcoding + technique. The ADPCM representation consists of a series of + codewords with a one-to-one correspondence to the samples in the PCM + stream. The G726 data rates of 40, 32, 24, and 16 kbit/s have + codewords of 5, 4, 3, and 2 bits, respectively. + + The 16 and 24 kbit/s encodings do not provide toll quality speech. + They are designed for used in overloaded Digital Circuit + Multiplication Equipment (DCME). ITU-T G.726 recommends that the 16 + and 24 kbit/s encodings should be alternated with higher data rate + encodings to provide an average sample size of between 3.5 and 3.7 + bits per sample. + + The encodings of G.726 are here denoted as G726-40, G726-32, G726-24, + and G726-16. Prior to 1990, G721 described the 32 kbit/s ADPCM + encoding, and G723 described the 40, 32, and 16 kbit/s encodings. + Thus, G726-32 designates the same algorithm as G721 in RFC 1890. + + A stream of G726 codewords contains no information on the encoding + being used, therefore transitions between G726 encoding types are not + permitted within a sequence of packed codewords. Applications MUST + determine the encoding type of packed codewords from the RTP payload + identifier. + + No payload-specific header information SHALL be included as part of + the audio data. A stream of G726 codewords MUST be packed into + octets as follows: the first codeword is placed into the first octet + such that the least significant bit of the codeword aligns with the + least significant bit in the octet, the second codeword is then + packed so that its least significant bit coincides with the least + significant unoccupied bit in the octet. When a complete codeword + cannot be placed into an octet, the bits overlapping the octet + boundary are placed into the least significant bits of the next + octet. Packing MUST end with a completely packed final octet. The + number of codewords packed will therefore be a multiple of 8, 2, 8, + and 4 for G726-40, G726-32, G726-24, and G726-16, respectively. An + example of the packing scheme for G726-32 codewords is as shown, + where bit 7 is the least significant bit of the first octet, and bit + A3 is the least significant bit of the first codeword: + + + + + + +Schulzrinne & Casner Standards Track [Page 18] + +RFC 3551 RTP A/V Profile July 2003 + + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- + |B B B B|A A A A|D D D D|C C C C| ... + |0 1 2 3|0 1 2 3|0 1 2 3|0 1 2 3| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- + + An example of the packing scheme for G726-24 codewords follows, where + again bit 7 is the least significant bit of the first octet, and bit + A2 is the least significant bit of the first codeword: + + 0 1 2 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- + |C C|B B B|A A A|F|E E E|D D D|C|H H H|G G G|F F| ... + |1 2|0 1 2|0 1 2|2|0 1 2|0 1 2|0|0 1 2|0 1 2|0 1| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- + + Note that the "little-endian" direction in which samples are packed + into octets in the G726-16, -24, -32 and -40 payload formats + specified here is consistent with ITU-T Recommendation X.420, but is + the opposite of what is specified in ITU-T Recommendation I.366.2 + Annex E for ATM AAL2 transport. A second set of RTP payload formats + matching the packetization of I.366.2 Annex E and identified by MIME + subtypes AAL2-G726-16, -24, -32 and -40 will be specified in a + separate document. + +4.5.5 G728 + + G728 is specified in ITU-T Recommendation G.728, "Coding of speech at + 16 kbit/s using low-delay code excited linear prediction". + + A G.278 encoder translates 5 consecutive audio samples into a 10-bit + codebook index, resulting in a bit rate of 16 kb/s for audio sampled + at 8,000 samples per second. The group of five consecutive samples + is called a vector. Four consecutive vectors, labeled V1 to V4 + (where V1 is to be played first by the receiver), build one G.728 + frame. The four vectors of 40 bits are packed into 5 octets, labeled + B1 through B5. B1 SHALL be placed first in the RTP packet. + + Referring to the figure below, the principle for bit order is + "maintenance of bit significance". Bits from an older vector are + more significant than bits from newer vectors. The MSB of the frame + goes to the MSB of B1 and the LSB of the frame goes to LSB of B5. + + + + + + + +Schulzrinne & Casner Standards Track [Page 19] + +RFC 3551 RTP A/V Profile July 2003 + + + 1 2 3 3 + 0 0 0 0 9 + ++++++++++++++++++++++++++++++++++++++++ + <---V1---><---V2---><---V3---><---V4---> vectors + <--B1--><--B2--><--B3--><--B4--><--B5--> octets + <------------- frame 1 ----------------> + + In particular, B1 contains the eight most significant bits of V1, + with the MSB of V1 being the MSB of B1. B2 contains the two least + significant bits of V1, the more significant of the two in its MSB, + and the six most significant bits of V2. B1 SHALL be placed first in + the RTP packet and B5 last. + +4.5.6 G729 + + G729 is specified in ITU-T Recommendation G.729, "Coding of speech at + 8 kbit/s using conjugate structure-algebraic code excited linear + prediction (CS-ACELP)". A reduced-complexity version of the G.729 + algorithm is specified in Annex A to Rec. G.729. The speech coding + algorithms in the main body of G.729 and in G.729 Annex A are fully + interoperable with each other, so there is no need to further + distinguish between them. An implementation that signals or accepts + use of G729 payload format may implement either G.729 or G.729A + unless restricted by additional signaling specified elsewhere related + specifically to the encoding rather than the payload format. The + G.729 and G.729 Annex A codecs were optimized to represent speech + with high quality, where G.729 Annex A trades some speech quality for + an approximate 50% complexity reduction [10]. See the next Section + (4.5.7) for other data rates added in later G.729 Annexes. For all + data rates, the sampling frequency (and RTP timestamp clock rate) is + 8,000 Hz. + + A voice activity detector (VAD) and comfort noise generator (CNG) + algorithm in Annex B of G.729 is RECOMMENDED for digital simultaneous + voice and data applications and can be used in conjunction with G.729 + or G.729 Annex A. A G.729 or G.729 Annex A frame contains 10 octets, + while the G.729 Annex B comfort noise frame occupies 2 octets. + Receivers MUST accept comfort noise frames if restriction of their + use has not been signaled. The MIME registration for G729 in RFC + 3555 [7] specifies a parameter that MAY be used with MIME or SDP to + restrict the use of comfort noise frames. + + A G729 RTP packet may consist of zero or more G.729 or G.729 Annex A + frames, followed by zero or one G.729 Annex B frames. The presence + of a comfort noise frame can be deduced from the length of the RTP + payload. The default packetization interval is 20 ms (two frames), + but in some situations it may be desirable to send 10 ms packets. An + + + + +Schulzrinne & Casner Standards Track [Page 20] + +RFC 3551 RTP A/V Profile July 2003 + + + example would be a transition from speech to comfort noise in the + first 10 ms of the packet. For some applications, a longer + packetization interval may be required to reduce the packet rate. + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |L| L1 | L2 | L3 | P1 |P| C1 | + |0| | | | |0| | + | |0 1 2 3 4 5 6|0 1 2 3 4|0 1 2 3 4|0 1 2 3 4 5 6 7| |0 1 2 3 4| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | C1 | S1 | GA1 | GB1 | P2 | C2 | + | 1 1 1| | | | | | + |5 6 7 8 9 0 1 2|0 1 2 3|0 1 2|0 1 2 3|0 1 2 3 4|0 1 2 3 4 5 6 7| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | C2 | S2 | GA2 | GB2 | + | 1 1 1| | | | + |8 9 0 1 2|0 1 2 3|0 1 2|0 1 2 3| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 4: G.729 and G.729A bit packing + + The transmitted parameters of a G.729/G.729A 10-ms frame, consisting + of 80 bits, are defined in Recommendation G.729, Table 8/G.729. The + mapping of the these parameters is given below in Fig. 4. The + diagrams show the bit packing in "network byte order", also known as + big-endian order. The bits of each 32-bit word are numbered 0 to 31, + with the most significant bit on the left and numbered 0. The octets + (bytes) of each word are transmitted most significant octet first. + The bits of each data field are numbered in the order as produced by + the G.729 C code reference implementation. + + The packing of the G.729 Annex B comfort noise frame is shown in Fig. + 5. + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |L| LSF1 | LSF2 | GAIN |R| + |S| | | |E| + |F| | | |S| + |0|0 1 2 3 4|0 1 2 3|0 1 2 3 4|V| RESV = Reserved (zero) + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 5: G.729 Annex B bit packing + + + + + + +Schulzrinne & Casner Standards Track [Page 21] + +RFC 3551 RTP A/V Profile July 2003 + + +4.5.7 G729D and G729E + + Annexes D and E to ITU-T Recommendation G.729 provide additional data + rates. Because the data rate is not signaled in the bitstream, the + different data rates are given distinct RTP encoding names which are + mapped to distinct payload type numbers. G729D indicates a 6.4 + kbit/s coding mode (G.729 Annex D, for momentary reduction in channel + capacity), while G729E indicates an 11.8 kbit/s mode (G.729 Annex E, + for improved performance with a wide range of narrow-band input + signals, e.g., music and background noise). Annex E has two + operating modes, backward adaptive and forward adaptive, which are + signaled by the first two bits in each frame (the most significant + two bits of the first octet). + + The voice activity detector (VAD) and comfort noise generator (CNG) + algorithm specified in Annex B of G.729 may be used with Annex D and + Annex E frames in addition to G.729 and G.729 Annex A frames. The + algorithm details for the operation of Annexes D and E with the Annex + B CNG are specified in G.729 Annexes F and G. Note that Annexes F + and G do not introduce any new encodings. Receivers MUST accept + comfort noise frames if restriction of their use has not been + signaled. The MIME registrations for G729D and G729E in RFC 3555 [7] + specify a parameter that MAY be used with MIME or SDP to restrict the + use of comfort noise frames. + + For G729D, an RTP packet may consist of zero or more G.729 Annex D + frames, followed by zero or one G.729 Annex B frame. Similarly, for + G729E, an RTP packet may consist of zero or more G.729 Annex E + frames, followed by zero or one G.729 Annex B frame. The presence of + a comfort noise frame can be deduced from the length of the RTP + payload. + + A single RTP packet must contain frames of only one data rate, + optionally followed by one comfort noise frame. The data rate may be + changed from packet to packet by changing the payload type number. + G.729 Annexes D, E and H describe what the encoding and decoding + algorithms must do to accommodate a change in data rate. + + For G729D, the bits of a G.729 Annex D frame are formatted as shown + below in Fig. 6 (cf. Table D.1/G.729). The frame length is 64 bits. + + + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 22] + +RFC 3551 RTP A/V Profile July 2003 + + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |L| L1 | L2 | L3 | P1 | C1 | + |0| | | | | | + | |0 1 2 3 4 5 6|0 1 2 3 4|0 1 2 3 4|0 1 2 3 4 5 6 7|0 1 2 3 4 5| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | C1 |S1 | GA1 | GB1 | P2 | C2 |S2 | GA2 | GB2 | + | | | | | | | | | | + |6 7 8|0 1|0 1 2|0 1 2|0 1 2 3|0 1 2 3 4 5 6 7 8|0 1|0 1 2|0 1 2| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 6: G.729 Annex D bit packing + + The net bit rate for the G.729 Annex E algorithm is 11.8 kbit/s and a + total of 118 bits are used. Two bits are appended as "don't care" + bits to complete an integer number of octets for the frame. For + G729E, the bits of a data frame are formatted as shown in the next + two diagrams (cf. Table E.1/G.729). The fields for the G729E forward + adaptive mode are packed as shown in Fig. 7. + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |0 0|L| L1 | L2 | L3 | P1 |P| C0_1| + | |0| | | | |0| | + | | |0 1 2 3 4 5 6|0 1 2 3 4|0 1 2 3 4|0 1 2 3 4 5 6 7| |0 1 2| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | C1_1 | C2_1 | C3_1 | C4_1 | + | | | | | | + |3 4 5 6|0 1 2 3 4 5 6|0 1 2 3 4 5 6|0 1 2 3 4 5 6|0 1 2 3 4 5 6| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | GA1 | GB1 | P2 | C0_2 | C1_2 | C2_2 | + | | | | | | | + |0 1 2|0 1 2 3|0 1 2 3 4|0 1 2 3 4 5 6|0 1 2 3 4 5 6|0 1 2 3 4 5| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | C3_2 | C4_2 | GA2 | GB2 |DC | + | | | | | | | + |6|0 1 2 3 4 5 6|0 1 2 3 4 5 6|0 1 2|0 1 2 3|0 1| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 7: G.729 Annex E (forward adaptive mode) bit packing + + The fields for the G729E backward adaptive mode are packed as shown + in Fig. 8. + + + + + + +Schulzrinne & Casner Standards Track [Page 23] + +RFC 3551 RTP A/V Profile July 2003 + + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |1 1| P1 |P| C0_1 | C1_1 | + | | |0| 1 1 1| | + | |0 1 2 3 4 5 6 7|0|0 1 2 3 4 5 6 7 8 9 0 1 2|0 1 2 3 4 5 6 7| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | C2_1 | C3_1 | C4_1 |GA1 | GB1 |P2 | + | | | | | | | | + |8 9|0 1 2 3 4 5 6|0 1 2 3 4 5 6|0 1 2 3 4 5 6|0 1 2|0 1 2 3|0 1| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | C0_2 | C1_2 | C2_2 | + | | 1 1 1| | | + |2 3 4|0 1 2 3 4 5 6 7 8 9 0 1 2|0 1 2 3 4 5 6 7 8 9|0 1 2 3 4 5| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | C3_2 | C4_2 | GA2 | GB2 |DC | + | | | | | | | + |6|0 1 2 3 4 5 6|0 1 2 3 4 5 6|0 1 2|0 1 2 3|0 1| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Figure 8: G.729 Annex E (backward adaptive mode) bit packing + +4.5.8 GSM + + GSM (Group Speciale Mobile) denotes the European GSM 06.10 standard + for full-rate speech transcoding, ETS 300 961, which is based on + RPE/LTP (residual pulse excitation/long term prediction) coding at a + rate of 13 kb/s [11,12,13]. The text of the standard can be obtained + from: + + ETSI (European Telecommunications Standards Institute) + ETSI Secretariat: B.P.152 + F-06561 Valbonne Cedex + France + Phone: +33 92 94 42 00 + Fax: +33 93 65 47 16 + + Blocks of 160 audio samples are compressed into 33 octets, for an + effective data rate of 13,200 b/s. + +4.5.8.1 General Packaging Issues + + The GSM standard (ETS 300 961) specifies the bit stream produced by + the codec, but does not specify how these bits should be packed for + transmission. The packetization specified here has subsequently been + adopted in ETSI Technical Specification TS 101 318. Some software + implementations of the GSM codec use a different packing than that + specified here. + + + +Schulzrinne & Casner Standards Track [Page 24] + +RFC 3551 RTP A/V Profile July 2003 + + + field field name bits field field name bits + ________________________________________________ + 1 LARc[0] 6 39 xmc[22] 3 + 2 LARc[1] 6 40 xmc[23] 3 + 3 LARc[2] 5 41 xmc[24] 3 + 4 LARc[3] 5 42 xmc[25] 3 + 5 LARc[4] 4 43 Nc[2] 7 + 6 LARc[5] 4 44 bc[2] 2 + 7 LARc[6] 3 45 Mc[2] 2 + 8 LARc[7] 3 46 xmaxc[2] 6 + 9 Nc[0] 7 47 xmc[26] 3 + 10 bc[0] 2 48 xmc[27] 3 + 11 Mc[0] 2 49 xmc[28] 3 + 12 xmaxc[0] 6 50 xmc[29] 3 + 13 xmc[0] 3 51 xmc[30] 3 + 14 xmc[1] 3 52 xmc[31] 3 + 15 xmc[2] 3 53 xmc[32] 3 + 16 xmc[3] 3 54 xmc[33] 3 + 17 xmc[4] 3 55 xmc[34] 3 + 18 xmc[5] 3 56 xmc[35] 3 + 19 xmc[6] 3 57 xmc[36] 3 + 20 xmc[7] 3 58 xmc[37] 3 + 21 xmc[8] 3 59 xmc[38] 3 + 22 xmc[9] 3 60 Nc[3] 7 + 23 xmc[10] 3 61 bc[3] 2 + 24 xmc[11] 3 62 Mc[3] 2 + 25 xmc[12] 3 63 xmaxc[3] 6 + 26 Nc[1] 7 64 xmc[39] 3 + 27 bc[1] 2 65 xmc[40] 3 + 28 Mc[1] 2 66 xmc[41] 3 + 29 xmaxc[1] 6 67 xmc[42] 3 + 30 xmc[13] 3 68 xmc[43] 3 + 31 xmc[14] 3 69 xmc[44] 3 + 32 xmc[15] 3 70 xmc[45] 3 + 33 xmc[16] 3 71 xmc[46] 3 + 34 xmc[17] 3 72 xmc[47] 3 + 35 xmc[18] 3 73 xmc[48] 3 + 36 xmc[19] 3 74 xmc[49] 3 + 37 xmc[20] 3 75 xmc[50] 3 + 38 xmc[21] 3 76 xmc[51] 3 + + Table 2: Ordering of GSM variables + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 25] + +RFC 3551 RTP A/V Profile July 2003 + + + Octet Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 + _____________________________________________________________________ + 0 1 1 0 1 LARc0.0 LARc0.1 LARc0.2 LARc0.3 + 1 LARc0.4 LARc0.5 LARc1.0 LARc1.1 LARc1.2 LARc1.3 LARc1.4 LARc1.5 + 2 LARc2.0 LARc2.1 LARc2.2 LARc2.3 LARc2.4 LARc3.0 LARc3.1 LARc3.2 + 3 LARc3.3 LARc3.4 LARc4.0 LARc4.1 LARc4.2 LARc4.3 LARc5.0 LARc5.1 + 4 LARc5.2 LARc5.3 LARc6.0 LARc6.1 LARc6.2 LARc7.0 LARc7.1 LARc7.2 + 5 Nc0.0 Nc0.1 Nc0.2 Nc0.3 Nc0.4 Nc0.5 Nc0.6 bc0.0 + 6 bc0.1 Mc0.0 Mc0.1 xmaxc00 xmaxc01 xmaxc02 xmaxc03 xmaxc04 + 7 xmaxc05 xmc0.0 xmc0.1 xmc0.2 xmc1.0 xmc1.1 xmc1.2 xmc2.0 + 8 xmc2.1 xmc2.2 xmc3.0 xmc3.1 xmc3.2 xmc4.0 xmc4.1 xmc4.2 + 9 xmc5.0 xmc5.1 xmc5.2 xmc6.0 xmc6.1 xmc6.2 xmc7.0 xmc7.1 + 10 xmc7.2 xmc8.0 xmc8.1 xmc8.2 xmc9.0 xmc9.1 xmc9.2 xmc10.0 + 11 xmc10.1 xmc10.2 xmc11.0 xmc11.1 xmc11.2 xmc12.0 xmc12.1 xcm12.2 + 12 Nc1.0 Nc1.1 Nc1.2 Nc1.3 Nc1.4 Nc1.5 Nc1.6 bc1.0 + 13 bc1.1 Mc1.0 Mc1.1 xmaxc10 xmaxc11 xmaxc12 xmaxc13 xmaxc14 + 14 xmax15 xmc13.0 xmc13.1 xmc13.2 xmc14.0 xmc14.1 xmc14.2 xmc15.0 + 15 xmc15.1 xmc15.2 xmc16.0 xmc16.1 xmc16.2 xmc17.0 xmc17.1 xmc17.2 + 16 xmc18.0 xmc18.1 xmc18.2 xmc19.0 xmc19.1 xmc19.2 xmc20.0 xmc20.1 + 17 xmc20.2 xmc21.0 xmc21.1 xmc21.2 xmc22.0 xmc22.1 xmc22.2 xmc23.0 + 18 xmc23.1 xmc23.2 xmc24.0 xmc24.1 xmc24.2 xmc25.0 xmc25.1 xmc25.2 + 19 Nc2.0 Nc2.1 Nc2.2 Nc2.3 Nc2.4 Nc2.5 Nc2.6 bc2.0 + 20 bc2.1 Mc2.0 Mc2.1 xmaxc20 xmaxc21 xmaxc22 xmaxc23 xmaxc24 + 21 xmaxc25 xmc26.0 xmc26.1 xmc26.2 xmc27.0 xmc27.1 xmc27.2 xmc28.0 + 22 xmc28.1 xmc28.2 xmc29.0 xmc29.1 xmc29.2 xmc30.0 xmc30.1 xmc30.2 + 23 xmc31.0 xmc31.1 xmc31.2 xmc32.0 xmc32.1 xmc32.2 xmc33.0 xmc33.1 + 24 xmc33.2 xmc34.0 xmc34.1 xmc34.2 xmc35.0 xmc35.1 xmc35.2 xmc36.0 + 25 Xmc36.1 xmc36.2 xmc37.0 xmc37.1 xmc37.2 xmc38.0 xmc38.1 xmc38.2 + 26 Nc3.0 Nc3.1 Nc3.2 Nc3.3 Nc3.4 Nc3.5 Nc3.6 bc3.0 + 27 bc3.1 Mc3.0 Mc3.1 xmaxc30 xmaxc31 xmaxc32 xmaxc33 xmaxc34 + 28 xmaxc35 xmc39.0 xmc39.1 xmc39.2 xmc40.0 xmc40.1 xmc40.2 xmc41.0 + 29 xmc41.1 xmc41.2 xmc42.0 xmc42.1 xmc42.2 xmc43.0 xmc43.1 xmc43.2 + 30 xmc44.0 xmc44.1 xmc44.2 xmc45.0 xmc45.1 xmc45.2 xmc46.0 xmc46.1 + 31 xmc46.2 xmc47.0 xmc47.1 xmc47.2 xmc48.0 xmc48.1 xmc48.2 xmc49.0 + 32 xmc49.1 xmc49.2 xmc50.0 xmc50.1 xmc50.2 xmc51.0 xmc51.1 xmc51.2 + + Table 3: GSM payload format + + In the GSM packing used by RTP, the bits SHALL be packed beginning + from the most significant bit. Every 160 sample GSM frame is coded + into one 33 octet (264 bit) buffer. Every such buffer begins with a + 4 bit signature (0xD), followed by the MSB encoding of the fields of + the frame. The first octet thus contains 1101 in the 4 most + significant bits (0-3) and the 4 most significant bits of F1 (0-3) in + the 4 least significant bits (4-7). The second octet contains the 2 + least significant bits of F1 in bits 0-1, and F2 in bits 2-7, and so + on. The order of the fields in the frame is described in Table 2. + + + + +Schulzrinne & Casner Standards Track [Page 26] + +RFC 3551 RTP A/V Profile July 2003 + + +4.5.8.2 GSM Variable Names and Numbers + + In the RTP encoding we have the bit pattern described in Table 3, + where F.i signifies the ith bit of the field F, bit 0 is the most + significant bit, and the bits of every octet are numbered from 0 to 7 + from most to least significant. + +4.5.9 GSM-EFR + + GSM-EFR denotes GSM 06.60 enhanced full rate speech transcoding, + specified in ETS 300 726 which is available from ETSI at the address + given in Section 4.5.8. This codec has a frame length of 244 bits. + For transmission in RTP, each codec frame is packed into a 31 octet + (248 bit) buffer beginning with a 4-bit signature 0xC in a manner + similar to that specified here for the original GSM 06.10 codec. The + packing is specified in ETSI Technical Specification TS 101 318. + +4.5.10 L8 + + L8 denotes linear audio data samples, using 8-bits of precision with + an offset of 128, that is, the most negative signal is encoded as + zero. + +4.5.11 L16 + + L16 denotes uncompressed audio data samples, using 16-bit signed + representation with 65,535 equally divided steps between minimum and + maximum signal level, ranging from -32,768 to 32,767. The value is + represented in two's complement notation and transmitted in network + byte order (most significant byte first). + + The MIME registration for L16 in RFC 3555 [7] specifies parameters + that MAY be used with MIME or SDP to indicate that analog pre- + emphasis was applied to the signal before quantization or to indicate + that a multiple-channel audio stream follows a different channel + ordering convention than is specified in Section 4.1. + +4.5.12 LPC + + LPC designates an experimental linear predictive encoding contributed + by Ron Frederick, which is based on an implementation written by Ron + Zuckerman posted to the Usenet group comp.dsp on June 26, 1992. The + codec generates 14 octets for every frame. The framesize is set to + 20 ms, resulting in a bit rate of 5,600 b/s. + + + + + + + +Schulzrinne & Casner Standards Track [Page 27] + +RFC 3551 RTP A/V Profile July 2003 + + +4.5.13 MPA + + MPA denotes MPEG-1 or MPEG-2 audio encapsulated as elementary + streams. The encoding is defined in ISO standards ISO/IEC 11172-3 + and 13818-3. The encapsulation is specified in RFC 2250 [14]. + + The encoding may be at any of three levels of complexity, called + Layer I, II and III. The selected layer as well as the sampling rate + and channel count are indicated in the payload. The RTP timestamp + clock rate is always 90,000, independent of the sampling rate. + MPEG-1 audio supports sampling rates of 32, 44.1, and 48 kHz (ISO/IEC + 11172-3, section 1.1; "Scope"). MPEG-2 supports sampling rates of + 16, 22.05 and 24 kHz. The number of samples per frame is fixed, but + the frame size will vary with the sampling rate and bit rate. + + The MIME registration for MPA in RFC 3555 [7] specifies parameters + that MAY be used with MIME or SDP to restrict the selection of layer, + channel count, sampling rate, and bit rate. + +4.5.14 PCMA and PCMU + + PCMA and PCMU are specified in ITU-T Recommendation G.711. Audio + data is encoded as eight bits per sample, after logarithmic scaling. + PCMU denotes mu-law scaling, PCMA A-law scaling. A detailed + description is given by Jayant and Noll [15]. Each G.711 octet SHALL + be octet-aligned in an RTP packet. The sign bit of each G.711 octet + SHALL correspond to the most significant bit of the octet in the RTP + packet (i.e., assuming the G.711 samples are handled as octets on the + host machine, the sign bit SHALL be the most significant bit of the + octet as defined by the host machine format). The 56 kb/s and 48 + kb/s modes of G.711 are not applicable to RTP, since PCMA and PCMU + MUST always be transmitted as 8-bit samples. + + See Section 4.1 regarding silence suppression. + +4.5.15 QCELP + + The Electronic Industries Association (EIA) & Telecommunications + Industry Association (TIA) standard IS-733, "TR45: High Rate Speech + Service Option for Wideband Spread Spectrum Communications Systems", + defines the QCELP audio compression algorithm for use in wireless + CDMA applications. The QCELP CODEC compresses each 20 milliseconds + of 8,000 Hz, 16-bit sampled input speech into one of four different + size output frames: Rate 1 (266 bits), Rate 1/2 (124 bits), Rate 1/4 + (54 bits) or Rate 1/8 (20 bits). For typical speech patterns, this + results in an average output of 6.8 kb/s for normal mode and 4.7 kb/s + for reduced rate mode. The packetization of the QCELP audio codec is + described in [16]. + + + +Schulzrinne & Casner Standards Track [Page 28] + +RFC 3551 RTP A/V Profile July 2003 + + +4.5.16 RED + + The redundant audio payload format "RED" is specified by RFC 2198 + [17]. It defines a means by which multiple redundant copies of an + audio packet may be transmitted in a single RTP stream. Each packet + in such a stream contains, in addition to the audio data for that + packetization interval, a (more heavily compressed) copy of the data + from a previous packetization interval. This allows an approximation + of the data from lost packets to be recovered upon decoding of a + subsequent packet, giving much improved sound quality when compared + with silence substitution for lost packets. + +4.5.17 VDVI + + VDVI is a variable-rate version of DVI4, yielding speech bit rates of + between 10 and 25 kb/s. It is specified for single-channel operation + only. Samples are packed into octets starting at the most- + significant bit. The last octet is padded with 1 bits if the last + sample does not fill the last octet. This padding is distinct from + the valid codewords. The receiver needs to detect the padding + because there is no explicit count of samples in the packet. + + It uses the following encoding: + + DVI4 codeword VDVI bit pattern + _______________________________ + 0 00 + 1 010 + 2 1100 + 3 11100 + 4 111100 + 5 1111100 + 6 11111100 + 7 11111110 + 8 10 + 9 011 + 10 1101 + 11 11101 + 12 111101 + 13 1111101 + 14 11111101 + 15 11111111 + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 29] + +RFC 3551 RTP A/V Profile July 2003 + + +5. Video + + The following sections describe the video encodings that are defined + in this memo and give their abbreviated names used for + identification. These video encodings and their payload types are + listed in Table 5. + + All of these video encodings use an RTP timestamp frequency of 90,000 + Hz, the same as the MPEG presentation time stamp frequency. This + frequency yields exact integer timestamp increments for the typical + 24 (HDTV), 25 (PAL), and 29.97 (NTSC) and 30 Hz (HDTV) frame rates + and 50, 59.94 and 60 Hz field rates. While 90 kHz is the RECOMMENDED + rate for future video encodings used within this profile, other rates + MAY be used. However, it is not sufficient to use the video frame + rate (typically between 15 and 30 Hz) because that does not provide + adequate resolution for typical synchronization requirements when + calculating the RTP timestamp corresponding to the NTP timestamp in + an RTCP SR packet. The timestamp resolution MUST also be sufficient + for the jitter estimate contained in the receiver reports. + + For most of these video encodings, the RTP timestamp encodes the + sampling instant of the video image contained in the RTP data packet. + If a video image occupies more than one packet, the timestamp is the + same on all of those packets. Packets from different video images + are distinguished by their different timestamps. + + Most of these video encodings also specify that the marker bit of the + RTP header SHOULD be set to one in the last packet of a video frame + and otherwise set to zero. Thus, it is not necessary to wait for a + following packet with a different timestamp to detect that a new + frame should be displayed. + +5.1 CelB + + The CELL-B encoding is a proprietary encoding proposed by Sun + Microsystems. The byte stream format is described in RFC 2029 [18]. + +5.2 JPEG + + The encoding is specified in ISO Standards 10918-1 and 10918-2. The + RTP payload format is as specified in RFC 2435 [19]. + +5.3 H261 + + The encoding is specified in ITU-T Recommendation H.261, "Video codec + for audiovisual services at p x 64 kbit/s". The packetization and + RTP-specific properties are described in RFC 2032 [20]. + + + + +Schulzrinne & Casner Standards Track [Page 30] + +RFC 3551 RTP A/V Profile July 2003 + + +5.4 H263 + + The encoding is specified in the 1996 version of ITU-T Recommendation + H.263, "Video coding for low bit rate communication". The + packetization and RTP-specific properties are described in RFC 2190 + [21]. The H263-1998 payload format is RECOMMENDED over this one for + use by new implementations. + +5.5 H263-1998 + + The encoding is specified in the 1998 version of ITU-T Recommendation + H.263, "Video coding for low bit rate communication". The + packetization and RTP-specific properties are described in RFC 2429 + [22]. Because the 1998 version of H.263 is a superset of the 1996 + syntax, this payload format can also be used with the 1996 version of + H.263, and is RECOMMENDED for this use by new implementations. This + payload format does not replace RFC 2190, which continues to be used + by existing implementations, and may be required for backward + compatibility in new implementations. Implementations using the new + features of the 1998 version of H.263 MUST use the payload format + described in RFC 2429. + +5.6 MPV + + MPV designates the use of MPEG-1 and MPEG-2 video encoding elementary + streams as specified in ISO Standards ISO/IEC 11172 and 13818-2, + respectively. The RTP payload format is as specified in RFC 2250 + [14], Section 3. + + The MIME registration for MPV in RFC 3555 [7] specifies a parameter + that MAY be used with MIME or SDP to restrict the selection of the + type of MPEG video. + +5.7 MP2T + + MP2T designates the use of MPEG-2 transport streams, for either audio + or video. The RTP payload format is described in RFC 2250 [14], + Section 2. + + + + + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 31] + +RFC 3551 RTP A/V Profile July 2003 + + +5.8 nv + + The encoding is implemented in the program `nv', version 4, developed + at Xerox PARC by Ron Frederick. Further information is available + from the author: + + Ron Frederick + Blue Coat Systems Inc. + 650 Almanor Avenue + Sunnyvale, CA 94085 + United States + EMail: ronf@bluecoat.com + +6. Payload Type Definitions + + Tables 4 and 5 define this profile's static payload type values for + the PT field of the RTP data header. In addition, payload type + values in the range 96-127 MAY be defined dynamically through a + conference control protocol, which is beyond the scope of this + document. For example, a session directory could specify that for a + given session, payload type 96 indicates PCMU encoding, 8,000 Hz + sampling rate, 2 channels. Entries in Tables 4 and 5 with payload + type "dyn" have no static payload type assigned and are only used + with a dynamic payload type. Payload type 2 was assigned to G721 in + RFC 1890 and to its equivalent successor G726-32 in draft versions of + this specification, but its use is now deprecated and that static + payload type is marked reserved due to conflicting use for the + payload formats G726-32 and AAL2-G726-32 (see Section 4.5.4). + Payload type 13 indicates the Comfort Noise (CN) payload format + specified in RFC 3389 [9]. Payload type 19 is marked "reserved" + because some draft versions of this specification assigned that + number to an earlier version of the comfort noise payload format. + The payload type range 72-76 is marked "reserved" so that RTCP and + RTP packets can be reliably distinguished (see Section "Summary of + Protocol Constants" of the RTP protocol specification). + + The payload types currently defined in this profile are assigned to + exactly one of three categories or media types: audio only, video + only and those combining audio and video. The media types are marked + in Tables 4 and 5 as "A", "V" and "AV", respectively. Payload types + of different media types SHALL NOT be interleaved or multiplexed + within a single RTP session, but multiple RTP sessions MAY be used in + parallel to send multiple media types. An RTP source MAY change + payload types within the same media type during a session. See the + section "Multiplexing RTP Sessions" of RFC 3550 for additional + explanation. + + + + + +Schulzrinne & Casner Standards Track [Page 32] + +RFC 3551 RTP A/V Profile July 2003 + + + PT encoding media type clock rate channels + name (Hz) + ___________________________________________________ + 0 PCMU A 8,000 1 + 1 reserved A + 2 reserved A + 3 GSM A 8,000 1 + 4 G723 A 8,000 1 + 5 DVI4 A 8,000 1 + 6 DVI4 A 16,000 1 + 7 LPC A 8,000 1 + 8 PCMA A 8,000 1 + 9 G722 A 8,000 1 + 10 L16 A 44,100 2 + 11 L16 A 44,100 1 + 12 QCELP A 8,000 1 + 13 CN A 8,000 1 + 14 MPA A 90,000 (see text) + 15 G728 A 8,000 1 + 16 DVI4 A 11,025 1 + 17 DVI4 A 22,050 1 + 18 G729 A 8,000 1 + 19 reserved A + 20 unassigned A + 21 unassigned A + 22 unassigned A + 23 unassigned A + dyn G726-40 A 8,000 1 + dyn G726-32 A 8,000 1 + dyn G726-24 A 8,000 1 + dyn G726-16 A 8,000 1 + dyn G729D A 8,000 1 + dyn G729E A 8,000 1 + dyn GSM-EFR A 8,000 1 + dyn L8 A var. var. + dyn RED A (see text) + dyn VDVI A var. 1 + + Table 4: Payload types (PT) for audio encodings + + + + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 33] + +RFC 3551 RTP A/V Profile July 2003 + + + PT encoding media type clock rate + name (Hz) + _____________________________________________ + 24 unassigned V + 25 CelB V 90,000 + 26 JPEG V 90,000 + 27 unassigned V + 28 nv V 90,000 + 29 unassigned V + 30 unassigned V + 31 H261 V 90,000 + 32 MPV V 90,000 + 33 MP2T AV 90,000 + 34 H263 V 90,000 + 35-71 unassigned ? + 72-76 reserved N/A N/A + 77-95 unassigned ? + 96-127 dynamic ? + dyn H263-1998 V 90,000 + + Table 5: Payload types (PT) for video and combined + encodings + + Session participants agree through mechanisms beyond the scope of + this specification on the set of payload types allowed in a given + session. This set MAY, for example, be defined by the capabilities + of the applications used, negotiated by a conference control protocol + or established by agreement between the human participants. + + Audio applications operating under this profile SHOULD, at a minimum, + be able to send and/or receive payload types 0 (PCMU) and 5 (DVI4). + This allows interoperability without format negotiation and ensures + successful negotiation with a conference control protocol. + +7. RTP over TCP and Similar Byte Stream Protocols + + Under special circumstances, it may be necessary to carry RTP in + protocols offering a byte stream abstraction, such as TCP, possibly + multiplexed with other data. The application MUST define its own + method of delineating RTP and RTCP packets (RTSP [23] provides an + example of such an encapsulation specification). + +8. Port Assignment + + As specified in the RTP protocol definition, RTP data SHOULD be + carried on an even UDP port number and the corresponding RTCP packets + SHOULD be carried on the next higher (odd) port number. + + + + +Schulzrinne & Casner Standards Track [Page 34] + +RFC 3551 RTP A/V Profile July 2003 + + + Applications operating under this profile MAY use any such UDP port + pair. For example, the port pair MAY be allocated randomly by a + session management program. A single fixed port number pair cannot + be required because multiple applications using this profile are + likely to run on the same host, and there are some operating systems + that do not allow multiple processes to use the same UDP port with + different multicast addresses. + + However, port numbers 5004 and 5005 have been registered for use with + this profile for those applications that choose to use them as the + default pair. Applications that operate under multiple profiles MAY + use this port pair as an indication to select this profile if they + are not subject to the constraint of the previous paragraph. + Applications need not have a default and MAY require that the port + pair be explicitly specified. The particular port numbers were + chosen to lie in the range above 5000 to accommodate port number + allocation practice within some versions of the Unix operating + system, where port numbers below 1024 can only be used by privileged + processes and port numbers between 1024 and 5000 are automatically + assigned by the operating system. + +9. Changes from RFC 1890 + + This RFC revises RFC 1890. It is mostly backwards-compatible with + RFC 1890 except for functions removed because two interoperable + implementations were not found. The additions to RFC 1890 codify + existing practice in the use of payload formats under this profile. + Since this profile may be used without using any of the payload + formats listed here, the addition of new payload formats in this + revision does not affect backwards compatibility. The changes are + listed below, categorized into functional and non-functional changes. + + Functional changes: + + o Section 11, "IANA Considerations" was added to specify the + registration of the name for this profile. That appendix also + references a new Section 3 "Registering Additional Encodings" + which establishes a policy that no additional registration of + static payload types for this profile will be made beyond those + added in this revision and included in Tables 4 and 5. Instead, + additional encoding names may be registered as MIME subtypes for + binding to dynamic payload types. Non-normative references were + added to RFC 3555 [7] where MIME subtypes for all the listed + payload formats are registered, some with optional parameters for + use of the payload formats. + + + + + + +Schulzrinne & Casner Standards Track [Page 35] + +RFC 3551 RTP A/V Profile July 2003 + + + o Static payload types 4, 16, 17 and 34 were added to incorporate + IANA registrations made since the publication of RFC 1890, along + with the corresponding payload format descriptions for G723 and + H263. + + o Following working group discussion, static payload types 12 and 18 + were added along with the corresponding payload format + descriptions for QCELP and G729. Static payload type 13 was + assigned to the Comfort Noise (CN) payload format defined in RFC + 3389. Payload type 19 was marked reserved because it had been + temporarily allocated to an earlier version of Comfort Noise + present in some draft revisions of this document. + + o The payload format for G721 was renamed to G726-32 following the + ITU-T renumbering, and the payload format description for G726 was + expanded to include the -16, -24 and -40 data rates. Because of + confusion regarding draft revisions of this document, some + implementations of these G726 payload formats packed samples into + octets starting with the most significant bit rather than the + least significant bit as specified here. To partially resolve + this incompatibility, new payload formats named AAL2-G726-16, -24, + -32 and -40 will be specified in a separate document (see note in + Section 4.5.4), and use of static payload type 2 is deprecated as + explained in Section 6. + + o Payload formats G729D and G729E were added following the ITU-T + addition of Annexes D and E to Recommendation G.729. Listings + were added for payload formats GSM-EFR, RED, and H263-1998 + published in other documents subsequent to RFC 1890. These + additional payload formats are referenced only by dynamic payload + type numbers. + + o The descriptions of the payload formats for G722, G728, GSM, VDVI + were expanded. + + o The payload format for 1016 audio was removed and its static + payload type assignment 1 was marked "reserved" because two + interoperable implementations were not found. + + o Requirements for congestion control were added in Section 2. + + o This profile follows the suggestion in the revised RTP spec that + RTCP bandwidth may be specified separately from the session + bandwidth and separately for active senders and passive receivers. + + o The mapping of a user pass-phrase string into an encryption key + was deleted from Section 2 because two interoperable + implementations were not found. + + + +Schulzrinne & Casner Standards Track [Page 36] + +RFC 3551 RTP A/V Profile July 2003 + + + o The "quadrophonic" sample ordering convention for four-channel + audio was removed to eliminate an ambiguity as noted in Section + 4.1. + + Non-functional changes: + + o In Section 4.1, it is now explicitly stated that silence + suppression is allowed for all audio payload formats. (This has + always been the case and derives from a fundamental aspect of + RTP's design and the motivations for packet audio, but was not + explicit stated before.) The use of comfort noise is also + explained. + + o In Section 4.1, the requirement level for setting of the marker + bit on the first packet after silence for audio was changed from + "is" to "SHOULD be", and clarified that the marker bit is set only + when packets are intentionally not sent. + + o Similarly, text was added to specify that the marker bit SHOULD be + set to one on the last packet of a video frame, and that video + frames are distinguished by their timestamps. + + o RFC references are added for payload formats published after RFC + 1890. + + o The security considerations and full copyright sections were + added. + + o According to Peter Hoddie of Apple, only pre-1994 Macintosh used + the 22254.54 rate and none the 11127.27 rate, so the latter was + dropped from the discussion of suggested sampling frequencies. + + o Table 1 was corrected to move some values from the "ms/packet" + column to the "default ms/packet" column where they belonged. + + o Since the Interactive Multimedia Association ceased operations, an + alternate resource was provided for a referenced IMA document. + + o A note has been added for G722 to clarify a discrepancy between + the actual sampling rate and the RTP timestamp clock rate. + + o Small clarifications of the text have been made in several places, + some in response to questions from readers. In particular: + + - A definition for "media type" is given in Section 1.1 to allow + the explanation of multiplexing RTP sessions in Section 6 to be + more clear regarding the multiplexing of multiple media. + + + + +Schulzrinne & Casner Standards Track [Page 37] + +RFC 3551 RTP A/V Profile July 2003 + + + - The explanation of how to determine the number of audio frames + in a packet from the length was expanded. + + - More description of the allocation of bandwidth to SDES items + is given. + + - A note was added that the convention for the order of channels + specified in Section 4.1 may be overridden by a particular + encoding or payload format specification. + + - The terms MUST, SHOULD, MAY, etc. are used as defined in RFC + 2119. + + o A second author for this document was added. + +10. Security Considerations + + Implementations using the profile defined in this specification are + subject to the security considerations discussed in the RTP + specification [1]. This profile does not specify any different + security services. The primary function of this profile is to list a + set of data compression encodings for audio and video media. + + Confidentiality of the media streams is achieved by encryption. + Because the data compression used with the payload formats described + in this profile is applied end-to-end, encryption may be performed + after compression so there is no conflict between the two operations. + + A potential denial-of-service threat exists for data encodings using + compression techniques that have non-uniform receiver-end + computational load. The attacker can inject pathological datagrams + into the stream which are complex to decode and cause the receiver to + be overloaded. + + As with any IP-based protocol, in some circumstances a receiver may + be overloaded simply by the receipt of too many packets, either + desired or undesired. Network-layer authentication MAY be used to + discard packets from undesired sources, but the processing cost of + the authentication itself may be too high. In a multicast + environment, source pruning is implemented in IGMPv3 (RFC 3376) [24] + and in multicast routing protocols to allow a receiver to select + which sources are allowed to reach it. + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 38] + +RFC 3551 RTP A/V Profile July 2003 + + +11. IANA Considerations + + The RTP specification establishes a registry of profile names for use + by higher-level control protocols, such as the Session Description + Protocol (SDP), RFC 2327 [6], to refer to transport methods. This + profile registers the name "RTP/AVP". + + Section 3 establishes the policy that no additional registration of + static RTP payload types for this profile will be made beyond those + added in this document revision and included in Tables 4 and 5. IANA + may reference that section in declining to accept any additional + registration requests. In Tables 4 and 5, note that types 1 and 2 + have been marked reserved and the set of "dyn" payload types included + has been updated. These changes are explained in Sections 6 and 9. + +12. References + +12.1 Normative References + + [1] Schulzrinne, H., Casner, S., Frederick, R. and V. Jacobson, + "RTP: A Transport Protocol for Real-Time Applications", RFC + 3550, July 2003. + + [2] Bradner, S., "Key Words for Use in RFCs to Indicate Requirement + Levels", BCP 14, RFC 2119, March 1997. + + [3] Apple Computer, "Audio Interchange File Format AIFF-C", August + 1991. (also ftp://ftp.sgi.com/sgi/aiff-c.9.26.91.ps.Z). + +12.2 Informative References + + [4] Braden, R., Clark, D. and S. Shenker, "Integrated Services in + the Internet Architecture: an Overview", RFC 1633, June 1994. + + [5] Blake, S., Black, D., Carlson, M., Davies, E., Wang, Z. and W. + Weiss, "An Architecture for Differentiated Service", RFC 2475, + December 1998. + + [6] Handley, M. and V. Jacobson, "SDP: Session Description + Protocol", RFC 2327, April 1998. + + [7] Casner, S. and P. Hoschka, "MIME Type Registration of RTP + Payload Types", RFC 3555, July 2003. + + [8] Freed, N., Klensin, J. and J. Postel, "Multipurpose Internet + Mail Extensions (MIME) Part Four: Registration Procedures", BCP + 13, RFC 2048, November 1996. + + + + +Schulzrinne & Casner Standards Track [Page 39] + +RFC 3551 RTP A/V Profile July 2003 + + + [9] Zopf, R., "Real-time Transport Protocol (RTP) Payload for + Comfort Noise (CN)", RFC 3389, September 2002. + + [10] Deleam, D. and J.-P. Petit, "Real-time implementations of the + recent ITU-T low bit rate speech coders on the TI TMS320C54X + DSP: results, methodology, and applications", in Proc. of + International Conference on Signal Processing, Technology, and + Applications (ICSPAT) , (Boston, Massachusetts), pp. 1656--1660, + October 1996. + + [11] Mouly, M. and M.-B. Pautet, The GSM system for mobile + communications Lassay-les-Chateaux, France: Europe Media + Duplication, 1993. + + [12] Degener, J., "Digital Speech Compression", Dr. Dobb's Journal, + December 1994. + + [13] Redl, S., Weber, M. and M. Oliphant, An Introduction to GSM + Boston: Artech House, 1995. + + [14] Hoffman, D., Fernando, G., Goyal, V. and M. Civanlar, "RTP + Payload Format for MPEG1/MPEG2 Video", RFC 2250, January 1998. + + [15] Jayant, N. and P. Noll, Digital Coding of Waveforms--Principles + and Applications to Speech and Video Englewood Cliffs, New + Jersey: Prentice-Hall, 1984. + + [16] McKay, K., "RTP Payload Format for PureVoice(tm) Audio", RFC + 2658, August 1999. + + [17] Perkins, C., Kouvelas, I., Hodson, O., Hardman, V., Handley, M., + Bolot, J.-C., Vega-Garcia, A. and S. Fosse-Parisis, "RTP Payload + for Redundant Audio Data", RFC 2198, September 1997. + + [18] Speer, M. and D. Hoffman, "RTP Payload Format of Sun's CellB + Video Encoding", RFC 2029, October 1996. + + [19] Berc, L., Fenner, W., Frederick, R., McCanne, S. and P. Stewart, + "RTP Payload Format for JPEG-Compressed Video", RFC 2435, + October 1998. + + [20] Turletti, T. and C. Huitema, "RTP Payload Format for H.261 Video + Streams", RFC 2032, October 1996. + + [21] Zhu, C., "RTP Payload Format for H.263 Video Streams", RFC 2190, + September 1997. + + + + + +Schulzrinne & Casner Standards Track [Page 40] + +RFC 3551 RTP A/V Profile July 2003 + + + [22] Bormann, C., Cline, L., Deisher, G., Gardos, T., Maciocco, C., + Newell, D., Ott, J., Sullivan, G., Wenger, S. and C. Zhu, "RTP + Payload Format for the 1998 Version of ITU-T Rec. H.263 Video + (H.263+)", RFC 2429, October 1998. + + [23] Schulzrinne, H., Rao, A. and R. Lanphier, "Real Time Streaming + Protocol (RTSP)", RFC 2326, April 1998. + + [24] Cain, B., Deering, S., Kouvelas, I., Fenner, B. and A. + Thyagarajan, "Internet Group Management Protocol, Version 3", + RFC 3376, October 2002. + +13. Current Locations of Related Resources + + Note: Several sections below refer to the ITU-T Software Tool + Library (STL). It is available from the ITU Sales Service, Place des + Nations, CH-1211 Geneve 20, Switzerland (also check + http://www.itu.int). The ITU-T STL is covered by a license defined + in ITU-T Recommendation G.191, "Software tools for speech and audio + coding standardization". + + DVI4 + + An archived copy of the document IMA Recommended Practices for + Enhancing Digital Audio Compatibility in Multimedia Systems (version + 3.0), which describes the IMA ADPCM algorithm, is available at: + + http://www.cs.columbia.edu/~hgs/audio/dvi/ + + An implementation is available from Jack Jansen at + + ftp://ftp.cwi.nl/local/pub/audio/adpcm.shar + + G722 + + An implementation of the G.722 algorithm is available as part of the + ITU-T STL, described above. + + G723 + + The reference C code implementation defining the G.723.1 algorithm + and its Annexes A, B, and C are available as an integral part of + Recommendation G.723.1 from the ITU Sales Service, address listed + above. Both the algorithm and C code are covered by a specific + license. The ITU-T Secretariat should be contacted to obtain such + licensing information. + + + + + +Schulzrinne & Casner Standards Track [Page 41] + +RFC 3551 RTP A/V Profile July 2003 + + + G726 + + G726 is specified in the ITU-T Recommendation G.726, "40, 32, 24, and + 16 kb/s Adaptive Differential Pulse Code Modulation (ADPCM)". An + implementation of the G.726 algorithm is available as part of the + ITU-T STL, described above. + + G729 + + The reference C code implementation defining the G.729 algorithm and + its Annexes A through I are available as an integral part of + Recommendation G.729 from the ITU Sales Service, listed above. Annex + I contains the integrated C source code for all G.729 operating + modes. The G.729 algorithm and associated C code are covered by a + specific license. The contact information for obtaining the license + is available from the ITU-T Secretariat. + + GSM + + A reference implementation was written by Carsten Bormann and Jutta + Degener (then at TU Berlin, Germany). It is available at + + http://www.dmn.tzi.org/software/gsm/ + + Although the RPE-LTP algorithm is not an ITU-T standard, there is a C + code implementation of the RPE-LTP algorithm available as part of the + ITU-T STL. The STL implementation is an adaptation of the TU Berlin + version. + + LPC + + An implementation is available at + + ftp://parcftp.xerox.com/pub/net-research/lpc.tar.Z + + PCMU, PCMA + + An implementation of these algorithms is available as part of the + ITU-T STL, described above. + +14. Acknowledgments + + The comments and careful review of Simao Campos, Richard Cox and AVT + Working Group participants are gratefully acknowledged. The GSM + description was adopted from the IMTC Voice over IP Forum Service + Interoperability Implementation Agreement (January 1997). Fred Burg + and Terry Lyons helped with the G.729 description. + + + + +Schulzrinne & Casner Standards Track [Page 42] + +RFC 3551 RTP A/V Profile July 2003 + + +15. Intellectual Property Rights Statement + + The IETF takes no position regarding the validity or scope of any + intellectual property or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; neither does it represent that it + has made any effort to identify any such rights. Information on the + IETF's procedures with respect to rights in standards-track and + standards-related documentation can be found in BCP-11. Copies of + claims of rights made available for publication and any assurances of + licenses to be made available, or the result of an attempt made to + obtain a general license or permission for the use of such + proprietary rights by implementors or users of this specification can + be obtained from the IETF Secretariat. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights which may cover technology that may be required to practice + this standard. Please address the information to the IETF Executive + Director. + +16. Authors' Addresses + + Henning Schulzrinne + Department of Computer Science + Columbia University + 1214 Amsterdam Avenue + New York, NY 10027 + United States + + EMail: schulzrinne@cs.columbia.edu + + + Stephen L. Casner + Packet Design + 3400 Hillview Avenue, Building 3 + Palo Alto, CA 94304 + United States + + EMail: casner@acm.org + + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 43] + +RFC 3551 RTP A/V Profile July 2003 + + +17. Full Copyright Statement + + Copyright (C) The Internet Society (2003). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Schulzrinne & Casner Standards Track [Page 44] + diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c new file mode 100644 index 000000000..a3e78d849 --- /dev/null +++ b/src/modules/rtp/rtp.c @@ -0,0 +1,193 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "rtp.h" + +pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload) { + assert(c); + assert(fd >= 0); + + c->fd = fd; + c->sequence = (uint16_t) (rand()*rand()); + c->timestamp = 0; + c->ssrc = ssrc ? ssrc : (uint32_t) (rand()*rand()); + c->payload = payload & 127; + + return c; +} + +#define MAX_IOVECS 16 + +int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { + struct iovec iov[MAX_IOVECS]; + pa_memblock* mb[MAX_IOVECS]; + int iov_idx = 1; + size_t n = 0, skip = 0; + + assert(c); + assert(size > 0); + assert(q); + + if (pa_memblockq_get_length(q) < size) + return 0; + + for (;;) { + int r; + pa_memchunk chunk; + + if ((r = pa_memblockq_peek(q, &chunk)) >= 0) { + + size_t k = n + chunk.length > size ? size - n : chunk.length; + + if (chunk.memblock) { + iov[iov_idx].iov_base = (uint8_t*) chunk.memblock->data + chunk.index; + iov[iov_idx].iov_len = k; + mb[iov_idx] = chunk.memblock; + iov_idx ++; + + n += k; + } + + skip += k; + pa_memblockq_drop(q, &chunk, k); + } + + if (r < 0 || !chunk.memblock || n >= size || iov_idx >= MAX_IOVECS) { + uint32_t header[3]; + struct msghdr m; + int k, i; + + if (n > 0) { + header[0] = htonl(((uint32_t) 2 << 30) | ((uint32_t) c->payload << 16) | ((uint32_t) c->sequence)); + header[1] = htonl(c->timestamp); + header[2] = htonl(c->ssrc); + + iov[0].iov_base = header; + iov[0].iov_len = sizeof(header); + + m.msg_name = NULL; + m.msg_namelen = 0; + m.msg_iov = iov; + m.msg_iovlen = iov_idx; + m.msg_control = NULL; + m.msg_controllen = 0; + m.msg_flags = 0; + + k = sendmsg(c->fd, &m, MSG_DONTWAIT); + + for (i = 1; i < iov_idx; i++) + pa_memblock_unref(mb[i]); + + c->sequence++; + } else + k = 0; + + c->timestamp += skip; + + if (k < 0) { + if (errno != EAGAIN) /* If the queue is full, just ignore it */ + pa_log(__FILE__": sendmsg() failed: %s", strerror(errno)); + return -1; + } + + if (r < 0 || pa_memblockq_get_length(q) < size) + break; + + n = 0; + skip = 0; + iov_idx = 1; + } + } + + return 0; +} + +pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd) { + assert(c); + + c->fd = fd; + return c; +} + +int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk) { + assert(c); + assert(chunk); + + return 0; +} + +uint8_t pa_rtp_payload_type(const pa_sample_spec *ss) { + assert(ss); + + if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1) + return 0; + if (ss->format == PA_SAMPLE_ALAW && ss->rate == 8000 && ss->channels == 1) + return 0; + if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 2) + return 10; + if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1) + return 11; + + return 127; +} + +pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) { + assert(ss); + + if (!pa_rtp_sample_spec_valid(ss)) + ss->format = PA_SAMPLE_S16BE; + + assert(pa_rtp_sample_spec_valid(ss)); + return ss; +} + +int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) { + assert(ss); + + if (!pa_sample_spec_valid(ss)) + return 0; + + return + ss->format == PA_SAMPLE_U8 || + ss->format == PA_SAMPLE_ALAW || + ss->format == PA_SAMPLE_ULAW || + ss->format == PA_SAMPLE_S16BE; +} + +void pa_rtp_context_destroy(pa_rtp_context *c) { + assert(c); + + close(c->fd); +} diff --git a/src/modules/rtp/rtp.h b/src/modules/rtp/rtp.h new file mode 100644 index 000000000..e925cc0eb --- /dev/null +++ b/src/modules/rtp/rtp.h @@ -0,0 +1,51 @@ +#ifndef foortphfoo +#define foortphfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include +#include + +typedef struct pa_rtp_context { + int fd; + uint16_t sequence; + uint32_t timestamp; + uint32_t ssrc; + uint8_t payload; +} pa_rtp_context; + +pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload); +int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q); + +pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd); +int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk); + +uint8_t pa_rtp_payload_type(const pa_sample_spec *ss); +pa_sample_spec* pa_rtp_sample_spec_fixup(pa_sample_spec *ss); +int pa_rtp_sample_spec_valid(const pa_sample_spec *ss); + +void pa_rtp_context_destroy(pa_rtp_context *c); + +#endif diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c new file mode 100644 index 000000000..ebf20bc41 --- /dev/null +++ b/src/modules/rtp/sap.c @@ -0,0 +1,107 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sap.h" + +pa_sap_context* pa_sap_context_init_send(pa_sap_context *c, int fd, char *sdp_data) { + assert(c); + assert(fd >= 0); + assert(sdp_data); + + c->fd = fd; + c->sdp_data = sdp_data; + c->msg_id_hash = (uint16_t) (rand()*rand()); + + return c; +} + +void pa_sap_context_destroy(pa_sap_context *c) { + assert(c); + + close(c->fd); + pa_xfree(c->sdp_data); +} + +int pa_sap_send(pa_sap_context *c, int goodbye) { + uint32_t header; + const char mime[] = "application/sdp"; + struct sockaddr_storage sa_buf; + struct sockaddr *sa = (struct sockaddr*) &sa_buf; + socklen_t salen = sizeof(sa_buf); + struct iovec iov[4]; + struct msghdr m; + int k; + + if (getsockname(c->fd, sa, &salen) < 0) { + pa_log("getsockname() failed: %s\n", strerror(errno)); + return -1; + } + + assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); + + header = htonl(((uint32_t) 1 << 29) | + (sa->sa_family == AF_INET6 ? (uint32_t) 1 << 28 : 0) | + (goodbye ? (uint32_t) 1 << 26 : 0) | + (c->msg_id_hash)); + + iov[0].iov_base = &header; + iov[0].iov_len = sizeof(header); + + iov[1].iov_base = sa->sa_family == AF_INET ? (void*) &((struct sockaddr_in*) sa)->sin_addr : (void*) &((struct sockaddr_in6*) sa)->sin6_addr; + iov[1].iov_len = sa->sa_family == AF_INET ? 4 : 16; + + iov[2].iov_base = (char*) mime; + iov[2].iov_len = sizeof(mime); + + iov[3].iov_base = c->sdp_data; + iov[3].iov_len = strlen(c->sdp_data); + + m.msg_name = NULL; + m.msg_namelen = 0; + m.msg_iov = iov; + m.msg_iovlen = 4; + m.msg_control = NULL; + m.msg_controllen = 0; + m.msg_flags = 0; + + if ((k = sendmsg(c->fd, &m, MSG_DONTWAIT)) < 0) + pa_log("sendmsg() failed: %s\n", strerror(errno)); + + return k; +} diff --git a/src/modules/rtp/sap.h b/src/modules/rtp/sap.h new file mode 100644 index 000000000..787b39f78 --- /dev/null +++ b/src/modules/rtp/sap.h @@ -0,0 +1,43 @@ +#ifndef foosaphfoo +#define foosaphfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include +#include + +typedef struct pa_sap_context { + int fd; + char *sdp_data; + + uint16_t msg_id_hash; +} pa_sap_context; + +pa_sap_context* pa_sap_context_init_send(pa_sap_context *c, int fd, char *sdp_data); +void pa_sap_context_destroy(pa_sap_context *c); + +int pa_sap_send(pa_sap_context *c, int goodbye); + +#endif diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c new file mode 100644 index 000000000..99e8c12bf --- /dev/null +++ b/src/modules/rtp/sdp.c @@ -0,0 +1,87 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include "sdp.h" + +static const char* map_format(pa_sample_format_t f) { + switch (f) { + case PA_SAMPLE_S16BE: return "L16"; + case PA_SAMPLE_U8: return "L8"; + case PA_SAMPLE_ALAW: return "PCMA"; + case PA_SAMPLE_ULAW: return "PCMU"; + default: + return NULL; + } +} + +char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, uint16_t port, uint8_t payload, const pa_sample_spec *ss) { + uint32_t ntp; + char buf_src[64], buf_dst[64]; + const char *u, *f, *a; + + assert(src); + assert(dst); + assert(af == AF_INET || af == AF_INET6); + + f = map_format(ss->format); + assert(f); + + if (!(u = getenv("USER"))) + if (!(u = getenv("USERNAME"))) + u = "-"; + + ntp = time(NULL) + 2208988800; + + a = inet_ntop(af, src, buf_src, sizeof(buf_src)); + assert(a); + a = inet_ntop(af, dst, buf_dst, sizeof(buf_dst)); + assert(a); + + return pa_sprintf_malloc( + "v=0\n" + "o=%s %lu 0 IN %s %s\n" + "s=%s\n" + "c=IN %s %s\n" + "t=%lu 0\n" + "a=recvonly\n" + "m=audio %u RTP/AVP %i\n" + "a=rtpmap:%i %s/%u/%u\n" + "a=type:broadcast\n", + u, (unsigned long) ntp, af == AF_INET ? "IP4" : "IP6", buf_src, + name, + af == AF_INET ? "IP4" : "IP6", buf_dst, + (unsigned long) ntp, + port, payload, + payload, f, ss->rate, ss->channels); +} diff --git a/src/modules/rtp/sdp.h b/src/modules/rtp/sdp.h new file mode 100644 index 000000000..108200678 --- /dev/null +++ b/src/modules/rtp/sdp.h @@ -0,0 +1,33 @@ +#ifndef foosdphfoo +#define foosdphfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include + +#include + +char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, uint16_t port, uint8_t payload, const pa_sample_spec *ss); + +#endif From e0e2b8fdb6d0c4f7caa801206ed6488bb345d523 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Apr 2006 23:49:12 +0000 Subject: [PATCH 0620/1514] * ignore some more files * make necessary changes to Makefile to compile RTP module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@713 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index c5e4638bd..f23778d0f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -589,7 +589,8 @@ modlib_LTLIBRARIES = \ libprotocol-simple.la \ libprotocol-esound.la \ libprotocol-native.la \ - libprotocol-http.la + libprotocol-http.la \ + librtp.la if HAVE_X11 polypcoreinclude_HEADERS += \ @@ -686,6 +687,10 @@ libsocket_util_la_SOURCES = polypcore/socket-util.c polypcore/socket-util.h libsocket_util_la_LDFLAGS = -avoid-version libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) +librtp_la_SOURCES = modules/rtp/rtp.c modules/rtp/rtp.h modules/rtp/sdp.c modules/rtp/sdp.h modules/rtp/sap.c modules/rtp/sap.h +librtp_la_LDFLAGS = -avoid-version +librtp_la_LIBADD = $(AM_LIBADD) libpolypcore.la + # X11 libx11wrap_la_SOURCES = polypcore/x11wrap.c polypcore/x11wrap.h @@ -716,7 +721,8 @@ modlib_LTLIBRARIES += \ module-null-sink.la \ module-esound-sink.la \ module-http-protocol-tcp.la \ - module-detect.la + module-detect.la \ + module-rtp-monitor.la if HAVE_AF_UNIX modlib_LTLIBRARIES += \ @@ -827,7 +833,8 @@ SYMDEF_FILES = \ modules/module-alsa-source-symdef.h \ modules/module-solaris-symdef.h \ modules/module-waveout-symdef.h \ - modules/module-detect-symdef.h + modules/module-detect-symdef.h \ + modules/rtp/module-rtp-monitor-symdef.h EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) @@ -1042,6 +1049,12 @@ module_detect_la_LDFLAGS = -module -avoid-version module_detect_la_LIBADD = $(AM_LIBADD) libpolypcore.la module_detect_la_CFLAGS = $(AM_CFLAGS) +# Hardware autodetection module +module_rtp_monitor_la_SOURCES = modules/rtp/module-rtp-monitor.c +module_rtp_monitor_la_LDFLAGS = -module -avoid-version +module_rtp_monitor_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_rtp_monitor_la_CFLAGS = $(AM_CFLAGS) + ################################### # Some minor stuff # ################################### From 71227de8b233fd12568609a2ac393e432a7c4299 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 15 Apr 2006 15:25:53 +0000 Subject: [PATCH 0621/1514] correct some types git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@714 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/resampler.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/polypcore/resampler.c b/src/polypcore/resampler.c index c1740bf1d..a50b21bfb 100644 --- a/src/polypcore/resampler.c +++ b/src/polypcore/resampler.c @@ -262,7 +262,7 @@ static void calc_map_table(pa_resampler *r) { } } -static float * convert_to_float(pa_resampler *r, float *input, unsigned n_frames) { +static float * convert_to_float(pa_resampler *r, void *input, unsigned n_frames) { struct impl_libsamplerate *u; unsigned n_samples; @@ -369,7 +369,7 @@ static float *resample(pa_resampler *r, float *input, unsigned *n_frames) { return u->buf3; } -static float *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) { +static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) { struct impl_libsamplerate *u; unsigned n_samples; @@ -395,7 +395,8 @@ static float *convert_from_float(pa_resampler *r, float *input, unsigned n_frame static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { struct impl_libsamplerate *u; - float *buf, *input; + float *buf; + void *input, *output; unsigned n_frames; assert(r); @@ -408,18 +409,18 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun u = r->impl_data; - buf = input = (float*) ((uint8_t*) in->memblock->data + in->index); + input = ((uint8_t*) in->memblock->data + in->index); n_frames = in->length / r->i_fz; assert(n_frames > 0); - buf = convert_to_float(r, buf, n_frames); + buf = convert_to_float(r, input, n_frames); buf = remap_channels(r, buf, n_frames); buf = resample(r, buf, &n_frames); if (n_frames) { - buf = convert_from_float(r, buf, n_frames); + output = convert_from_float(r, buf, n_frames); - if (buf == input) { + if (output == input) { /* Mm, no adjustment has been necessary, so let's return the original block */ out->memblock = pa_memblock_ref(in->memblock); out->index = in->index; @@ -430,16 +431,16 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun out->length = n_frames * r->o_fz; out->index = 0; - if (buf == u->buf1) { + if (output == u->buf1) { p = &u->buf1; u->buf1_samples = 0; - } else if (buf == u->buf2) { + } else if (output == u->buf2) { p = &u->buf2; u->buf2_samples = 0; - } else if (buf == u->buf3) { + } else if (output == u->buf3) { p = &u->buf3; u->buf3_samples = 0; - } else if (buf == u->buf4) { + } else if (output == u->buf4) { p = &u->buf4; u->buf4_samples = 0; } From 1fec416db7db4ba8d2d2dd250187939f0b06dbd7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 15 Apr 2006 15:26:42 +0000 Subject: [PATCH 0622/1514] * change default multicast address * fix timestamp calculation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@715 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-monitor.c | 7 +++---- src/modules/rtp/rtp.c | 7 ++++--- src/modules/rtp/rtp.h | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/modules/rtp/module-rtp-monitor.c b/src/modules/rtp/module-rtp-monitor.c index 663320937..c153a9d58 100644 --- a/src/modules/rtp/module-rtp-monitor.c +++ b/src/modules/rtp/module-rtp-monitor.c @@ -61,9 +61,9 @@ PA_MODULE_USAGE( "mtu= " ) -#define DEFAULT_PORT 5666 +#define DEFAULT_PORT 5004 #define SAP_PORT 9875 -#define DEFAULT_DESTINATION "224.0.0.252" +#define DEFAULT_DESTINATION "224.0.1.2" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define DEFAULT_MTU 1024 #define SAP_INTERVAL 5000000 @@ -136,7 +136,6 @@ static void sap_event(pa_mainloop_api *m, pa_time_event *t, const struct timeval pa_sap_send(&u->sap_context, 0); - pa_log("SAP update"); pa_gettimeofday(&next); pa_timeval_add(&next, SAP_INTERVAL); m->time_restart(t, &next); @@ -280,7 +279,7 @@ int pa__init(pa_core *c, pa_module*m) { af == AF_INET ? (void*) &sa4.sin_addr : (void*) &sa6.sin6_addr, "Polypaudio RTP Stream", port, payload, &ss); - pa_rtp_context_init_send(&u->rtp_context, fd, 0, payload); + pa_rtp_context_init_send(&u->rtp_context, fd, 0, payload, pa_frame_size(&ss)); pa_sap_context_init_send(&u->sap_context, sap_fd, p); pa_log_info("RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence); diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index a3e78d849..a3bce38bd 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -35,7 +35,7 @@ #include "rtp.h" -pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload) { +pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size) { assert(c); assert(fd >= 0); @@ -44,7 +44,8 @@ pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssr c->timestamp = 0; c->ssrc = ssrc ? ssrc : (uint32_t) (rand()*rand()); c->payload = payload & 127; - + c->frame_size = frame_size; + return c; } @@ -114,7 +115,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { } else k = 0; - c->timestamp += skip; + c->timestamp += skip/c->frame_size; if (k < 0) { if (errno != EAGAIN) /* If the queue is full, just ignore it */ diff --git a/src/modules/rtp/rtp.h b/src/modules/rtp/rtp.h index e925cc0eb..392881584 100644 --- a/src/modules/rtp/rtp.h +++ b/src/modules/rtp/rtp.h @@ -34,9 +34,10 @@ typedef struct pa_rtp_context { uint32_t timestamp; uint32_t ssrc; uint8_t payload; + size_t frame_size; } pa_rtp_context; -pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload); +pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size); int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q); pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd); From f1ddf052368ad96cf157297a50ffe52ee8f7ca39 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 00:16:53 +0000 Subject: [PATCH 0623/1514] * add RTP/SAP/SDP reciever module * use server cookie as RTP SSRC * enable SVN keywords * add new option "loop" for RTP sender module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@716 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 13 +- src/modules/rtp/module-rtp-monitor.c | 70 ++-- src/modules/rtp/module-rtp-recv.c | 469 +++++++++++++++++++++++++++ src/modules/rtp/rtp.c | 162 ++++++++- src/modules/rtp/rtp.h | 17 +- src/modules/rtp/sap.c | 116 ++++++- src/modules/rtp/sap.h | 3 + src/modules/rtp/sdp.c | 198 ++++++++++- src/modules/rtp/sdp.h | 17 + 9 files changed, 1012 insertions(+), 53 deletions(-) create mode 100644 src/modules/rtp/module-rtp-recv.c diff --git a/src/Makefile.am b/src/Makefile.am index f23778d0f..2ec62dca4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -722,7 +722,8 @@ modlib_LTLIBRARIES += \ module-esound-sink.la \ module-http-protocol-tcp.la \ module-detect.la \ - module-rtp-monitor.la + module-rtp-monitor.la \ + module-rtp-recv.la if HAVE_AF_UNIX modlib_LTLIBRARIES += \ @@ -834,7 +835,8 @@ SYMDEF_FILES = \ modules/module-solaris-symdef.h \ modules/module-waveout-symdef.h \ modules/module-detect-symdef.h \ - modules/rtp/module-rtp-monitor-symdef.h + modules/rtp/module-rtp-monitor-symdef.h \ + modules/rtp/module-rtp-recv-symdef.h EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) @@ -1049,12 +1051,17 @@ module_detect_la_LDFLAGS = -module -avoid-version module_detect_la_LIBADD = $(AM_LIBADD) libpolypcore.la module_detect_la_CFLAGS = $(AM_CFLAGS) -# Hardware autodetection module +# RTP modules module_rtp_monitor_la_SOURCES = modules/rtp/module-rtp-monitor.c module_rtp_monitor_la_LDFLAGS = -module -avoid-version module_rtp_monitor_la_LIBADD = $(AM_LIBADD) libpolypcore.la module_rtp_monitor_la_CFLAGS = $(AM_CFLAGS) +module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c +module_rtp_recv_la_LDFLAGS = -module -avoid-version +module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) + ################################### # Some minor stuff # ################################### diff --git a/src/modules/rtp/module-rtp-monitor.c b/src/modules/rtp/module-rtp-monitor.c index c153a9d58..5ff255575 100644 --- a/src/modules/rtp/module-rtp-monitor.c +++ b/src/modules/rtp/module-rtp-monitor.c @@ -1,3 +1,4 @@ +/* $Id */ /*** This file is part of polypaudio. @@ -49,16 +50,17 @@ #include "sap.h" PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Read data from source and send it to the network via RTP") +PA_MODULE_DESCRIPTION("Read data from source and send it to the network via RTP/SAP/SDP") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE( - "source= " + "source= " "format= " "channels= " "rate= " "destinaton= " "port= " "mtu= " + "loop=" ) #define DEFAULT_PORT 5004 @@ -75,6 +77,7 @@ static const char* const valid_modargs[] = { "rate", "destination", "port", + "loop", NULL }; @@ -125,7 +128,7 @@ static pa_usec_t source_output_get_latency (pa_source_output *o) { return pa_bytes_to_usec(pa_memblockq_get_length(u->memblockq), &o->sample_spec); } -static void sap_event(pa_mainloop_api *m, pa_time_event *t, const struct timeval *tv, void *userdata) { +static void sap_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct timeval *tv, void *userdata) { struct userdata *u = userdata; struct timeval next; @@ -159,6 +162,8 @@ int pa__init(pa_core *c, pa_module*m) { int r; socklen_t k; struct timeval tv; + char hn[128], *n; + int loop = 0; assert(c); assert(m); @@ -173,6 +178,11 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + if (pa_modargs_get_value_boolean(ma, "loop", &loop) < 0) { + pa_log(__FILE__": failed to parse \"loop\" parameter."); + goto fail; + } + ss = s->sample_spec; pa_rtp_sample_spec_fixup(&ss); cm = s->channel_map; @@ -189,7 +199,7 @@ int pa__init(pa_core *c, pa_module*m) { if (ss.channels != cm.channels) pa_channel_map_init_auto(&cm, ss.channels); - payload = pa_rtp_payload_type(&ss); + payload = pa_rtp_payload_from_sample_spec(&ss); mtu = (DEFAULT_MTU/pa_frame_size(&ss))*pa_frame_size(&ss); @@ -203,21 +213,21 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if ((dest = pa_modargs_get_value(ma, "destination", DEFAULT_DESTINATION))) { - if (inet_pton(AF_INET6, dest, &sa6.sin6_addr) > 0) { - sa6.sin6_family = af = AF_INET6; - sa6.sin6_port = htons(port); - sap_sa6 = sa6; - sap_sa6.sin6_port = htons(SAP_PORT); - } else if (inet_pton(AF_INET, dest, &sa4.sin_addr) > 0) { - sa4.sin_family = af = AF_INET; - sa4.sin_port = htons(port); - sap_sa4 = sa4; - sap_sa4.sin_port = htons(SAP_PORT); - } else { - pa_log(__FILE__": invalid destination '%s'", dest); - goto fail; - } + dest = pa_modargs_get_value(ma, "destination", DEFAULT_DESTINATION); + + if (inet_pton(AF_INET6, dest, &sa6.sin6_addr) > 0) { + sa6.sin6_family = af = AF_INET6; + sa6.sin6_port = htons(port); + sap_sa6 = sa6; + sap_sa6.sin6_port = htons(SAP_PORT); + } else if (inet_pton(AF_INET, dest, &sa4.sin_addr) > 0) { + sa4.sin_family = af = AF_INET; + sa4.sin_port = htons(port); + sap_sa4 = sa4; + sap_sa4.sin_port = htons(SAP_PORT); + } else { + pa_log(__FILE__": invalid destination '%s'", dest); + goto fail; } if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) { @@ -240,6 +250,12 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0 || + setsockopt(sap_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) { + pa_log(__FILE__": IP_MULTICAST_LOOP failed: %s", strerror(errno)); + goto fail; + } + if (!(o = pa_source_output_new(s, __FILE__, "RTP Monitor Stream", &ss, &cm, PA_RESAMPLER_INVALID))) { pa_log(__FILE__": failed to create source output."); goto fail; @@ -273,23 +289,27 @@ int pa__init(pa_core *c, pa_module*m) { k = sizeof(sa_dst); r = getsockname(fd, (struct sockaddr*) &sa_dst, &k); assert(r >= 0); + + n = pa_sprintf_malloc("Polypaudio RTP Stream on %s", pa_get_fqdn(hn, sizeof(hn))); p = pa_sdp_build(af, af == AF_INET ? (void*) &((struct sockaddr_in*) &sa_dst)->sin_addr : (void*) &((struct sockaddr_in6*) &sa_dst)->sin6_addr, af == AF_INET ? (void*) &sa4.sin_addr : (void*) &sa6.sin6_addr, - "Polypaudio RTP Stream", port, payload, &ss); + n, port, payload, &ss); + + pa_xfree(n); - pa_rtp_context_init_send(&u->rtp_context, fd, 0, payload, pa_frame_size(&ss)); + pa_rtp_context_init_send(&u->rtp_context, fd, c->cookie, payload, pa_frame_size(&ss)); pa_sap_context_init_send(&u->sap_context, sap_fd, p); - pa_log_info("RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence); - pa_log_info("SDP-Data:\n%s\nEOF", p); - + pa_log_info(__FILE__": RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence); + pa_log_info(__FILE__": SDP-Data:\n%s\n"__FILE__": EOF", p); + pa_sap_send(&u->sap_context, 0); pa_gettimeofday(&tv); pa_timeval_add(&tv, SAP_INTERVAL); - u->sap_event = c->mainloop->time_new(c->mainloop, &tv, sap_event, u); + u->sap_event = c->mainloop->time_new(c->mainloop, &tv, sap_event_cb, u); pa_modargs_free(ma); diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c new file mode 100644 index 000000000..1ac057d0e --- /dev/null +++ b/src/modules/rtp/module-rtp-recv.c @@ -0,0 +1,469 @@ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-rtp-recv-symdef.h" + +#include "rtp.h" +#include "sdp.h" +#include "sap.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Recieve data from a network via RTP/SAP/SDP") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE( + "sink= " + "sap_address= " +) + +#define SAP_PORT 9875 +#define DEFAULT_SAP_ADDRESS "224.0.1.2" +#define MEMBLOCKQ_MAXLENGTH (1024*170) +#define MAX_SESSIONS 16 +#define DEATH_TIMEOUT 20000000 + +static const char* const valid_modargs[] = { + "sink", + "sap_address", + NULL +}; + +struct session { + struct userdata *userdata; + + pa_sink_input *sink_input; + pa_memblockq *memblockq; + + pa_time_event *death_event; + + int first_packet; + uint32_t ssrc; + uint32_t offset; + + struct pa_sdp_info sdp_info; + + pa_rtp_context rtp_context; + pa_io_event* rtp_event; +}; + +struct userdata { + pa_module *module; + pa_core *core; + + pa_sap_context sap_context; + pa_io_event* sap_event; + + pa_hashmap *by_origin; + + char *sink_name; +}; + +static void session_free(struct session *s, int from_hash); + +static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { + struct session *s; + assert(i); + s = i->userdata; + + return pa_memblockq_peek(s->memblockq, chunk); +} + +static void sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { + struct session *s; + assert(i); + s = i->userdata; + + pa_memblockq_drop(s->memblockq, chunk, length); +} + +static void sink_input_kill(pa_sink_input* i) { + struct session *s; + assert(i); + s = i->userdata; + + session_free(s, 1); +} + +static pa_usec_t sink_input_get_latency(pa_sink_input *i) { + struct session *s; + assert(i); + s = i->userdata; + + return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec); +} + +static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { + struct session *s = userdata; + pa_memchunk chunk; + int64_t k, j, delta; + struct timeval tv; + + assert(m); + assert(e); + assert(s); + assert(fd == s->rtp_context.fd); + assert(flags == PA_IO_EVENT_INPUT); + + if (pa_rtp_recv(&s->rtp_context, &chunk, s->userdata->core->memblock_stat) < 0) + return; + + if (s->sdp_info.payload != s->rtp_context.payload) { + pa_memblock_unref(chunk.memblock); + return; + } + + if (!s->first_packet) { + s->first_packet = 1; + + s->ssrc = s->rtp_context.ssrc; + s->offset = s->rtp_context.timestamp; + } else { + if (s->ssrc != s->rtp_context.ssrc) { + pa_memblock_unref(chunk.memblock); + return; + } + } + + /* Check wheter there was a timestamp overflow */ + k = (int64_t) s->rtp_context.timestamp - (int64_t) s->offset; + j = (int64_t) 0x100000000 - (int64_t) s->offset + (int64_t) s->rtp_context.timestamp; + + if ((k < 0 ? -k : k) < (j < 0 ? -j : j)) + delta = k; + else + delta = j; + + pa_memblockq_seek(s->memblockq, delta * s->rtp_context.frame_size, PA_SEEK_RELATIVE); + pa_memblockq_push(s->memblockq, &chunk); + + /* The next timestamp we expect */ + s->offset = s->rtp_context.timestamp + (chunk.length / s->rtp_context.frame_size); + + pa_memblock_unref(chunk.memblock); + + /* Reset death timer */ + pa_gettimeofday(&tv); + pa_timeval_add(&tv, DEATH_TIMEOUT); + m->time_restart(s->death_event, &tv); +} + +static void death_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct timeval *tv, void *userdata) { + struct session *s = userdata; + + assert(m); + assert(t); + assert(tv); + assert(s); + + session_free(s, 1); +} + +static int mcast_socket(const struct sockaddr* sa, socklen_t salen) { + int af, fd = -1, r, one; + + af = sa->sa_family; + if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) { + pa_log(__FILE__": Failed to create socket: %s", strerror(errno)); + goto fail; + } + + one = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) { + pa_log(__FILE__": SO_REUSEADDR failed: %s", strerror(errno)); + goto fail; + } + + if (af == AF_INET) { + struct ip_mreq mr4; + memset(&mr4, 0, sizeof(mr4)); + mr4.imr_multiaddr = ((const struct sockaddr_in*) sa)->sin_addr; + r = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr4, sizeof(mr4)); + } else { + struct ipv6_mreq mr6; + memset(&mr6, 0, sizeof(mr6)); + mr6.ipv6mr_multiaddr = ((const struct sockaddr_in6*) sa)->sin6_addr; + r = setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr6, sizeof(mr6)); + } + + if (r < 0) { + pa_log_info(__FILE__": Joining mcast group failed: %s", strerror(errno)); + goto fail; + } + + if (bind(fd, sa, salen) < 0) { + pa_log(__FILE__": bind() failed: %s", strerror(errno)); + goto fail; + } + + return fd; + +fail: + if (fd >= 0) + close(fd); + + return -1; +} + +static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_info) { + struct session *s = NULL; + struct timeval tv; + char *c; + pa_sink *sink; + int fd = -1; + + if (!(sink = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { + pa_log(__FILE__": sink does not exist."); + goto fail; + } + + s = pa_xnew0(struct session, 1); + s->userdata = u; + s->first_packet = 0; + s->sdp_info = *sdp_info; + + if ((fd = mcast_socket((const struct sockaddr*) &sdp_info->sa, sdp_info->salen)) < 0) + goto fail; + + c = pa_sprintf_malloc("RTP Stream%s%s%s", + sdp_info->session_name ? " (" : "", + sdp_info->session_name ? sdp_info->session_name : "", + sdp_info->session_name ? ")" : ""); + + s->sink_input = pa_sink_input_new(sink, __FILE__, c, &sdp_info->sample_spec, NULL, 0, PA_RESAMPLER_INVALID); + pa_xfree(c); + + if (!s->sink_input) { + pa_log(__FILE__": failed to create sink input."); + goto fail; + } + + s->sink_input->userdata = s; + s->sink_input->owner = u->module; + + s->sink_input->peek = sink_input_peek; + s->sink_input->drop = sink_input_drop; + s->sink_input->kill = sink_input_kill; + s->sink_input->get_latency = sink_input_get_latency; + + s->memblockq = pa_memblockq_new( + 0, + MEMBLOCKQ_MAXLENGTH, + MEMBLOCKQ_MAXLENGTH, + pa_frame_size(&s->sink_input->sample_spec), + 1, + 0, + NULL, + u->core->memblock_stat); + + s->rtp_event = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, rtp_event_cb, s); + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, DEATH_TIMEOUT); + s->death_event = u->core->mainloop->time_new(u->core->mainloop, &tv, death_event_cb, s); + + pa_hashmap_put(s->userdata->by_origin, s->sdp_info.origin, s); + + pa_rtp_context_init_recv(&s->rtp_context, fd, pa_frame_size(&s->sdp_info.sample_spec)); + + pa_log_info(__FILE__": Found new session '%s'", s->sdp_info.session_name); + + return s; + +fail: + if (s) { + if (fd >= 0) + close(fd); + + pa_xfree(s); + } + + return NULL; +} + +static void session_free(struct session *s, int from_hash) { + assert(s); + + pa_log_info(__FILE__": Freeing session '%s'", s->sdp_info.session_name); + + s->userdata->core->mainloop->time_free(s->death_event); + s->userdata->core->mainloop->io_free(s->rtp_event); + + if (from_hash) + pa_hashmap_remove(s->userdata->by_origin, s->sdp_info.origin); + + pa_sink_input_disconnect(s->sink_input); + pa_sink_input_unref(s->sink_input); + + pa_memblockq_free(s->memblockq); + pa_sdp_info_destroy(&s->sdp_info); + pa_rtp_context_destroy(&s->rtp_context); + + pa_xfree(s); +} + +static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { + struct userdata *u = userdata; + int goodbye; + pa_sdp_info info; + struct session *s; + + assert(m); + assert(e); + assert(u); + assert(fd == u->sap_context.fd); + assert(flags == PA_IO_EVENT_INPUT); + + if (pa_sap_recv(&u->sap_context, &goodbye) < 0) + return; + + if (!pa_sdp_parse(u->sap_context.sdp_data, &info, goodbye)) + return; + + if (goodbye) { + + if ((s = pa_hashmap_get(u->by_origin, info.origin))) + session_free(s, 1); + + pa_sdp_info_destroy(&info); + } else { + + if (!(s = pa_hashmap_get(u->by_origin, info.origin))) { + if (!(s = session_new(u, &info))) + pa_sdp_info_destroy(&info); + + } else { + struct timeval tv; + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, DEATH_TIMEOUT); + m->time_restart(s->death_event, &tv); + + pa_sdp_info_destroy(&info); + } + } +} + +int pa__init(pa_core *c, pa_module*m) { + struct userdata *u; + pa_modargs *ma = NULL; + struct sockaddr_in sa4; + struct sockaddr_in6 sa6; + struct sockaddr *sa; + socklen_t salen; + const char *sap_address; + int fd = -1; + + assert(c); + assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments"); + goto fail; + } + + sap_address = pa_modargs_get_value(ma, "sap_address", DEFAULT_SAP_ADDRESS); + + if (inet_pton(AF_INET6, sap_address, &sa6.sin6_addr) > 0) { + sa6.sin6_family = AF_INET6; + sa6.sin6_port = htons(SAP_PORT); + sa = (struct sockaddr*) &sa6; + salen = sizeof(sa6); + } else if (inet_pton(AF_INET, sap_address, &sa4.sin_addr) > 0) { + sa4.sin_family = AF_INET; + sa4.sin_port = htons(SAP_PORT); + sa = (struct sockaddr*) &sa4; + salen = sizeof(sa4); + } else { + pa_log(__FILE__": invalid SAP address '%s'", sap_address); + goto fail; + } + + if ((fd = mcast_socket(sa, salen)) < 0) + goto fail; + + u = pa_xnew(struct userdata, 1); + m->userdata = u; + u->module = m; + u->core = c; + u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + + u->sap_event = c->mainloop->io_new(c->mainloop, fd, PA_IO_EVENT_INPUT, sap_event_cb, u); + + u->by_origin = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + + pa_sap_context_init_recv(&u->sap_context, fd); + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + if (fd >= 0) + close(fd); + + return -1; +} + +static void free_func(void *p, void *userdata) { + session_free(p, 0); +} + +void pa__done(pa_core *c, pa_module*m) { + struct userdata *u; + assert(c); + assert(m); + + if (!(u = m->userdata)) + return; + + c->mainloop->io_free(u->sap_event); + pa_sap_context_destroy(&u->sap_context); + + pa_hashmap_free(u->by_origin, free_func, NULL); + + pa_xfree(u->sink_name); + pa_xfree(u); +} diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index a3bce38bd..ccd3b6c31 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -135,27 +136,114 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { return 0; } -pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd) { +pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size) { assert(c); c->fd = fd; + c->frame_size = frame_size; return c; } -int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk) { +int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_memblock_stat *st) { + int size; + struct msghdr m; + struct iovec iov; + uint32_t header; + int cc; + ssize_t r; + assert(c); assert(chunk); + chunk->memblock = NULL; + + if (ioctl(c->fd, FIONREAD, &size) < 0) { + pa_log(__FILE__": FIONREAD failed: %s", strerror(errno)); + goto fail; + } + + if (!size) + return 0; + + chunk->memblock = pa_memblock_new(size, st); + + iov.iov_base = chunk->memblock->data; + iov.iov_len = size; + + m.msg_name = NULL; + m.msg_namelen = 0; + m.msg_iov = &iov; + m.msg_iovlen = 1; + m.msg_control = NULL; + m.msg_controllen = 0; + m.msg_flags = 0; + + if ((r = recvmsg(c->fd, &m, 0)) != size) { + pa_log(__FILE__": recvmsg() failed: %s", r < 0 ? strerror(errno) : "size mismatch"); + goto fail; + } + + if (size < 12) { + pa_log(__FILE__": RTP packet too short."); + goto fail; + } + + memcpy(&header, chunk->memblock->data, sizeof(uint32_t)); + memcpy(&c->timestamp, (uint8_t*) chunk->memblock->data + 4, sizeof(uint32_t)); + memcpy(&c->ssrc, (uint8_t*) chunk->memblock->data + 8, sizeof(uint32_t)); + + header = ntohl(header); + c->timestamp = ntohl(c->timestamp); + c->ssrc = ntohl(c->ssrc); + + if ((header >> 30) != 2) { + pa_log(__FILE__": Unsupported RTP version."); + goto fail; + } + + if ((header >> 29) & 1) { + pa_log(__FILE__": RTP padding not supported."); + goto fail; + } + + if ((header >> 28) & 1) { + pa_log(__FILE__": RTP header extensions not supported."); + goto fail; + } + + cc = (header >> 24) & 0xF; + c->payload = (header >> 16) & 127; + c->sequence = header & 0xFFFF; + + if (12 + cc*4 > size) { + pa_log(__FILE__": RTP packet too short. (CSRC)"); + goto fail; + } + + chunk->index = 12 + cc*4; + chunk->length = size - chunk->index; + + if (chunk->length % c->frame_size != 0) { + pa_log(__FILE__": Vad RTP packet size."); + goto fail; + } + return 0; + +fail: + if (chunk->memblock) + pa_memblock_unref(chunk->memblock); + + return -1; } -uint8_t pa_rtp_payload_type(const pa_sample_spec *ss) { +uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) { assert(ss); if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1) return 0; if (ss->format == PA_SAMPLE_ALAW && ss->rate == 8000 && ss->channels == 1) - return 0; + return 8; if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 2) return 10; if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1) @@ -164,6 +252,41 @@ uint8_t pa_rtp_payload_type(const pa_sample_spec *ss) { return 127; } +pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) { + assert(ss); + + switch (payload) { + case 0: + ss->channels = 1; + ss->format = PA_SAMPLE_ULAW; + ss->rate = 8000; + break; + + case 8: + ss->channels = 1; + ss->format = PA_SAMPLE_ALAW; + ss->rate = 8000; + break; + + case 10: + ss->channels = 2; + ss->format = PA_SAMPLE_S16BE; + ss->rate = 44100; + break; + + case 11: + ss->channels = 1; + ss->format = PA_SAMPLE_S16BE; + ss->rate = 44100; + break; + + default: + return NULL; + } + + return ss; +} + pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) { assert(ss); @@ -192,3 +315,34 @@ void pa_rtp_context_destroy(pa_rtp_context *c) { close(c->fd); } + +const char* pa_rtp_format_to_string(pa_sample_format_t f) { + switch (f) { + case PA_SAMPLE_S16BE: + return "L16"; + case PA_SAMPLE_U8: + return "L8"; + case PA_SAMPLE_ALAW: + return "PCMA"; + case PA_SAMPLE_ULAW: + return "PCMU"; + default: + return NULL; + } +} + +pa_sample_format_t pa_rtp_string_to_format(const char *s) { + assert(s); + + if (!(strcmp(s, "L16"))) + return PA_SAMPLE_S16BE; + else if (!strcmp(s, "L8")) + return PA_SAMPLE_U8; + else if (!strcmp(s, "PCMA")) + return PA_SAMPLE_ALAW; + else if (!strcmp(s, "PCMU")) + return PA_SAMPLE_ULAW; + else + return PA_SAMPLE_INVALID; +} + diff --git a/src/modules/rtp/rtp.h b/src/modules/rtp/rtp.h index 392881584..49da155b6 100644 --- a/src/modules/rtp/rtp.h +++ b/src/modules/rtp/rtp.h @@ -40,13 +40,18 @@ typedef struct pa_rtp_context { pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size); int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q); -pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd); -int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk); - -uint8_t pa_rtp_payload_type(const pa_sample_spec *ss); -pa_sample_spec* pa_rtp_sample_spec_fixup(pa_sample_spec *ss); -int pa_rtp_sample_spec_valid(const pa_sample_spec *ss); +pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size); +int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_memblock_stat *st); void pa_rtp_context_destroy(pa_rtp_context *c); +pa_sample_spec* pa_rtp_sample_spec_fixup(pa_sample_spec *ss); +int pa_rtp_sample_spec_valid(const pa_sample_spec *ss); + +uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss); +pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss); + +const char* pa_rtp_format_to_string(pa_sample_format_t f); +pa_sample_format_t pa_rtp_string_to_format(const char *s); + #endif diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index ebf20bc41..0c12322e9 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -32,12 +32,16 @@ #include #include #include +#include #include #include #include #include "sap.h" +#include "sdp.h" + +#define MIME_TYPE "application/sdp" pa_sap_context* pa_sap_context_init_send(pa_sap_context *c, int fd, char *sdp_data) { assert(c); @@ -60,7 +64,6 @@ void pa_sap_context_destroy(pa_sap_context *c) { int pa_sap_send(pa_sap_context *c, int goodbye) { uint32_t header; - const char mime[] = "application/sdp"; struct sockaddr_storage sa_buf; struct sockaddr *sa = (struct sockaddr*) &sa_buf; socklen_t salen = sizeof(sa_buf); @@ -86,8 +89,8 @@ int pa_sap_send(pa_sap_context *c, int goodbye) { iov[1].iov_base = sa->sa_family == AF_INET ? (void*) &((struct sockaddr_in*) sa)->sin_addr : (void*) &((struct sockaddr_in6*) sa)->sin6_addr; iov[1].iov_len = sa->sa_family == AF_INET ? 4 : 16; - iov[2].iov_base = (char*) mime; - iov[2].iov_len = sizeof(mime); + iov[2].iov_base = (char*) MIME_TYPE; + iov[2].iov_len = sizeof(MIME_TYPE); iov[3].iov_base = c->sdp_data; iov[3].iov_len = strlen(c->sdp_data); @@ -105,3 +108,110 @@ int pa_sap_send(pa_sap_context *c, int goodbye) { return k; } + +pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) { + assert(c); + assert(fd >= 0); + + c->fd = fd; + c->sdp_data = NULL; + return c; +} + +int pa_sap_recv(pa_sap_context *c, int *goodbye) { + struct msghdr m; + struct iovec iov; + int size, k; + char *buf = NULL, *e; + uint32_t header; + int six, ac; + ssize_t r; + + assert(c); + assert(goodbye); + + if (ioctl(c->fd, FIONREAD, &size) < 0) { + pa_log(__FILE__": FIONREAD failed: %s", strerror(errno)); + goto fail; + } + + if (!size) + return 0; + + buf = pa_xnew(char, size+1); + buf[size] = 0; + + iov.iov_base = buf; + iov.iov_len = size; + + m.msg_name = NULL; + m.msg_namelen = 0; + m.msg_iov = &iov; + m.msg_iovlen = 1; + m.msg_control = NULL; + m.msg_controllen = 0; + m.msg_flags = 0; + + if ((r = recvmsg(c->fd, &m, 0)) != size) { + pa_log(__FILE__": recvmsg() failed: %s", r < 0 ? strerror(errno) : "size mismatch"); + goto fail; + } + + if (size < 4) { + pa_log(__FILE__": SAP packet too short."); + goto fail; + } + + memcpy(&header, buf, sizeof(uint32_t)); + header = ntohl(header); + + if (header >> 29 != 1) { + pa_log(__FILE__": Unsupported SAP version."); + goto fail; + } + + if ((header >> 25) & 1) { + pa_log(__FILE__": Encrypted SAP not supported."); + goto fail; + } + + if ((header >> 24) & 1) { + pa_log(__FILE__": Compressed SAP not supported."); + goto fail; + } + + six = (header >> 28) & 1; + ac = (header >> 16) & 0xFF; + + k = 4 + (six ? 16 : 4) + ac*4; + if (size < k) { + pa_log(__FILE__": SAP packet too short (AD)."); + goto fail; + } + + e = buf + k; + size -= k; + + if ((unsigned) size >= sizeof(MIME_TYPE) && !strcmp(e, MIME_TYPE)) { + e += sizeof(MIME_TYPE); + size -= sizeof(MIME_TYPE); + } else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)) { + pa_log(__FILE__": Invalid SDP header."); + goto fail; + } + + if (c->sdp_data) + pa_xfree(c->sdp_data); + + c->sdp_data = pa_xstrndup(e, size); + pa_xfree(buf); + + *goodbye = !!((header >> 26) & 1); + + return 0; + +fail: + pa_xfree(buf); + + return -1; +} diff --git a/src/modules/rtp/sap.h b/src/modules/rtp/sap.h index 787b39f78..b11b1dd7b 100644 --- a/src/modules/rtp/sap.h +++ b/src/modules/rtp/sap.h @@ -40,4 +40,7 @@ void pa_sap_context_destroy(pa_sap_context *c); int pa_sap_send(pa_sap_context *c, int goodbye); +pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd); +int pa_sap_recv(pa_sap_context *c, int *goodbye); + #endif diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index 99e8c12bf..9dca15baf 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -29,21 +29,15 @@ #include #include #include +#include #include +#include +#include #include "sdp.h" +#include "rtp.h" -static const char* map_format(pa_sample_format_t f) { - switch (f) { - case PA_SAMPLE_S16BE: return "L16"; - case PA_SAMPLE_U8: return "L8"; - case PA_SAMPLE_ALAW: return "PCMA"; - case PA_SAMPLE_ULAW: return "PCMU"; - default: - return NULL; - } -} char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, uint16_t port, uint8_t payload, const pa_sample_spec *ss) { uint32_t ntp; @@ -54,7 +48,7 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u assert(dst); assert(af == AF_INET || af == AF_INET6); - f = map_format(ss->format); + f = pa_rtp_format_to_string(ss->format); assert(f); if (!(u = getenv("USER"))) @@ -69,7 +63,7 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u assert(a); return pa_sprintf_malloc( - "v=0\n" + PA_SDP_HEADER "o=%s %lu 0 IN %s %s\n" "s=%s\n" "c=IN %s %s\n" @@ -85,3 +79,183 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u port, payload, payload, f, ss->rate, ss->channels); } + +static pa_sample_spec *parse_sdp_sample_spec(pa_sample_spec *ss, char *c) { + unsigned rate, channels; + assert(ss); + assert(c); + + if (pa_startswith(c, "L16/")) { + ss->format = PA_SAMPLE_S16BE; + c += 4; + } else if (pa_startswith(c, "L8/")) { + ss->format = PA_SAMPLE_U8; + c += 3; + } else if (pa_startswith(c, "PCMA/")) { + ss->format = PA_SAMPLE_ALAW; + c += 5; + } else if (pa_startswith(c, "PCMU/")) { + ss->format = PA_SAMPLE_ULAW; + c += 5; + } else + return NULL; + + if (sscanf(c, "%u/%u", &rate, &channels) == 2) { + ss->rate = rate; + ss->channels = channels; + } else if (sscanf(c, "%u", &rate) == 2) { + ss->rate = rate; + ss->channels = 1; + } else + return NULL; + + if (!pa_sample_spec_valid(ss)) + return NULL; + + return ss; +} + +pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { + uint16_t port = 0; + int ss_valid = 0; + + assert(t); + assert(i); + + i->origin = i->session_name = NULL; + i->salen = 0; + i->payload = 255; + + if (!pa_startswith(t, PA_SDP_HEADER)) { + pa_log(__FILE__": Failed to parse SDP data: invalid header."); + goto fail; + } + + t += sizeof(PA_SDP_HEADER)-1; + + while (*t) { + size_t l; + + l = strcspn(t, "\n"); + + if (l <= 2) { + pa_log(__FILE__": Failed to parse SDP data: line too short: >%s<.", t); + goto fail; + } + + if (pa_startswith(t, "o=")) + i->origin = pa_xstrndup(t+2, l-2); + else if (pa_startswith(t, "s=")) + i->session_name = pa_xstrndup(t+2, l-2); + else if (pa_startswith(t, "c=IN IP4 ")) { + char a[64]; + size_t k; + + k = l-8 > sizeof(a) ? sizeof(a) : l-8; + + pa_strlcpy(a, t+9, k); + a[strcspn(a, "/")] = 0; + + if (inet_pton(AF_INET, a, &((struct sockaddr_in*) &i->sa)->sin_addr) <= 0) { + pa_log(__FILE__": Failed to parse SDP data: bad address: >%s<.", a); + goto fail; + } + + ((struct sockaddr_in*) &i->sa)->sin_family = AF_INET; + ((struct sockaddr_in*) &i->sa)->sin_port = 0; + i->salen = sizeof(struct sockaddr_in); + } else if (pa_startswith(t, "c=IN IP6 ")) { + char a[64]; + size_t k; + + k = l-8 > sizeof(a) ? sizeof(a) : l-8; + + pa_strlcpy(a, t+9, k); + a[strcspn(a, "/")] = 0; + + if (inet_pton(AF_INET6, a, &((struct sockaddr_in6*) &i->sa)->sin6_addr) <= 0) { + pa_log(__FILE__": Failed to parse SDP data: bad address: >%s<.", a); + goto fail; + } + + ((struct sockaddr_in6*) &i->sa)->sin6_family = AF_INET6; + ((struct sockaddr_in6*) &i->sa)->sin6_port = 0; + i->salen = sizeof(struct sockaddr_in6); + } else if (pa_startswith(t, "m=audio ")) { + + if (i->payload > 127) { + int _port, _payload; + + if (sscanf(t+8, "%i RTP/AVP %i", &_port, &_payload) == 2) { + + if (_port <= 0 || _port > 0xFFFF) { + pa_log(__FILE__": Failed to parse SDP data: invalid port %i.", _port); + goto fail; + } + + if (_payload < 0 || _payload > 127) { + pa_log(__FILE__": Failed to parse SDP data: invalid payload %i.", _payload); + goto fail; + } + + port = (uint16_t) _port; + i->payload = (uint8_t) _payload; + + if (pa_rtp_sample_spec_from_payload(i->payload, &i->sample_spec)) + ss_valid = 1; + } + } + } else if (pa_startswith(t, "a=rtpmap:")) { + + if (i->payload <= 127) { + char c[64]; + int _payload; + + if (sscanf(t+9, "%i %64c", &_payload, c) == 2) { + + if (_payload < 0 || _payload > 127) { + pa_log(__FILE__": Failed to parse SDP data: invalid payload %i.", _payload); + goto fail; + } + if (_payload == i->payload) { + + c[strcspn(c, "\n")] = 0; + + if (parse_sdp_sample_spec(&i->sample_spec, c)) + ss_valid = 1; + } + } + } + } + + t += l; + + if (*t == '\n') + t++; + } + + if (!i->origin || (!is_goodbye && (!i->salen || i->payload > 127 || !ss_valid || port == 0))) { + pa_log(__FILE__": Failed to parse SDP data: missing data."); + goto fail; + } + + if (((struct sockaddr*) &i->sa)->sa_family == AF_INET) + ((struct sockaddr_in*) &i->sa)->sin_port = htons(port); + else + ((struct sockaddr_in6*) &i->sa)->sin6_port = htons(port); + + return i; + +fail: + pa_xfree(i->origin); + pa_xfree(i->session_name); + + return NULL; +} + +void pa_sdp_info_destroy(pa_sdp_info *i) { + assert(i); + + pa_xfree(i->origin); + pa_xfree(i->session_name); +} diff --git a/src/modules/rtp/sdp.h b/src/modules/rtp/sdp.h index 108200678..2aa18056e 100644 --- a/src/modules/rtp/sdp.h +++ b/src/modules/rtp/sdp.h @@ -28,6 +28,23 @@ #include +#define PA_SDP_HEADER "v=0\n" + +typedef struct pa_sdp_info { + char *origin; + char *session_name; + + struct sockaddr_storage sa; + socklen_t salen; + + pa_sample_spec sample_spec; + uint8_t payload; +} pa_sdp_info; + char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, uint16_t port, uint8_t payload, const pa_sample_spec *ss); +pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *info, int is_goodbye); + +void pa_sdp_info_destroy(pa_sdp_info *i); + #endif From a176d77b1bfc8c33a7af520c30dedda596961136 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 00:18:59 +0000 Subject: [PATCH 0624/1514] todo update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@717 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 4a84054f0..8688f05d1 100644 --- a/doc/todo +++ b/doc/todo @@ -2,7 +2,6 @@ Post 0.8: - alsa mmap driver -- add radio module - dbus/hal - polish for starting polypaudio as root/system-wide instance - chroot() From d50255ac1e8856943b9057a365e1b9be83ac9124 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 09:12:31 +0000 Subject: [PATCH 0625/1514] * add new check for $RANDOM_DEVICE * move AC_SYS_LARGEFILE to avoid autoconf warning git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@718 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 6511137e7..e649e0634 100644 --- a/configure.ac +++ b/configure.ac @@ -36,10 +36,6 @@ if type -p stow > /dev/null && test -d /usr/local/stow ; then ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}" fi -#### Large File-Support (LFS) #### - -AC_SYS_LARGEFILE - #### Checks for programs. #### # CC @@ -234,6 +230,10 @@ AC_CHECK_FUNCS(setreuid) ACX_PTHREAD +#### Large File-Support (LFS) #### + +AC_SYS_LARGEFILE + ################################### # External libraries # ################################### @@ -374,6 +374,26 @@ AC_SUBST(LIRC_CFLAGS) AC_SUBST(LIRC_LIBS) AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) +### /dev/random ### + +AC_MSG_CHECKING([whether a random device is available]) + +rnd="no" + +if test -e /dev/urandom ; then + rnd=/dev/urandom +else + if test -e /dev/random ; then + rnd=/dev/random + fi +fi + +if test "x$rnd" != "no" ; then + AC_DEFINE_UNQUOTED([RANDOM_DEVICE], ["$rnd"], [Random device]) +fi + +AC_MSG_RESULT([$rnd]) + ################################### # Output # ################################### From 0990d8c796e9896e791d1ce23557e6d2f5ecf5b0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 09:13:09 +0000 Subject: [PATCH 0626/1514] initialize random seed globaly from $RANDOM_DEVICE git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@719 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 25 +++++++++++++++++++++++++ src/polypcore/random.c | 6 ------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 8457916a8..d783531a0 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -135,6 +135,29 @@ static void close_pipe(int p[2]) { p[0] = p[1] = -1; } +static void set_random_seed(void) { + unsigned int seed = 0; + +#ifdef RANDOM_DEVICE + int fd; + + if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) { + ssize_t r; + + if ((r = pa_loop_read(fd, &seed, sizeof(seed))) < 0 || (size_t) r != sizeof(seed)) { + pa_log_error(__FILE__": failed to read entropy from '"RANDOM_DEVICE"'"); + seed += (unsigned int) time(NULL); + } + + close(fd); + } +#else + seed = (unsigned int) time(NULL); +#endif + + srand(seed); +} + int main(int argc, char *argv[]) { pa_core *c; pa_strbuf *buf = NULL; @@ -180,6 +203,8 @@ int main(int argc, char *argv[]) { } #endif + set_random_seed(); + pa_log_set_ident("polypaudio"); conf = pa_daemon_conf_new(); diff --git a/src/polypcore/random.c b/src/polypcore/random.c index 1c2280e3f..ffd404741 100644 --- a/src/polypcore/random.c +++ b/src/polypcore/random.c @@ -36,10 +36,6 @@ #include "random.h" -#ifndef OS_IS_WIN32 -#define RANDOM_DEVICE "/dev/urandom" -#endif - void pa_random(void *ret_data, size_t length) { int fd; ssize_t r = 0; @@ -64,8 +60,6 @@ void pa_random(void *ret_data, size_t length) { ", falling back to unsecure pseudo RNG.\n", strerror(errno)); #endif - srand(time(NULL)); - for (p = ret_data, l = length; l > 0; p++, l--) *p = (uint8_t) rand(); } From 998affc9842f59bd637cafa2e2361a8000bddc7c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 09:13:41 +0000 Subject: [PATCH 0627/1514] replace homegrown endswith() with pa_endswith() from util.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@720 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-detect.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index b24d838be..6b2e27421 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "module-detect-symdef.h" @@ -45,20 +46,8 @@ PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("just-one=") -static const char *endswith(const char *haystack, const char *needle) { - size_t l, m; - const char *p; - - if ((l = strlen(haystack)) < (m = strlen(needle))) - return NULL; - - if (strcmp(p = haystack + l - m, needle)) - return NULL; - - return p; -} - #ifdef HAVE_ALSA + static int detect_alsa(pa_core *c, int just_one) { FILE *f; int n = 0, n_sink = 0, n_source = 0; @@ -81,9 +70,9 @@ static int detect_alsa(pa_core *c, int just_one) { line[strcspn(line, "\r\n")] = 0; - if (endswith(line, "digital audio playback")) + if (pa_endswith(line, "digital audio playback")) is_sink = 1; - else if (endswith(line, "digital audio capture")) + else if (pa_endswith(line, "digital audio capture")) is_sink = 0; else continue; From 67b105bd7af57c14755fae7bed3efc38766d0c03 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 09:14:55 +0000 Subject: [PATCH 0628/1514] * increase default MTU * change default mcast address to 224.0.1.3 * randomize RTP ports by default git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@721 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-monitor.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/modules/rtp/module-rtp-monitor.c b/src/modules/rtp/module-rtp-monitor.c index 5ff255575..0a050ca59 100644 --- a/src/modules/rtp/module-rtp-monitor.c +++ b/src/modules/rtp/module-rtp-monitor.c @@ -63,11 +63,11 @@ PA_MODULE_USAGE( "loop=" ) -#define DEFAULT_PORT 5004 +#define DEFAULT_PORT 46000 #define SAP_PORT 9875 -#define DEFAULT_DESTINATION "224.0.1.2" +#define DEFAULT_DESTINATION "224.0.1.3" #define MEMBLOCKQ_MAXLENGTH (1024*170) -#define DEFAULT_MTU 1024 +#define DEFAULT_MTU 1280 #define SAP_INTERVAL 5000000 static const char* const valid_modargs[] = { @@ -207,7 +207,8 @@ int pa__init(pa_core *c, pa_module*m) { pa_log(__FILE__": invalid mtu."); goto fail; } - + + port = DEFAULT_PORT + (rand() % 512); if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { pa_log(__FILE__": port= expects a numerical argument between 1 and 65535."); goto fail; From c999fe40b841b035c7d0c873b4a4875e12e9c9a4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 09:15:51 +0000 Subject: [PATCH 0629/1514] * deal properly with underruns, overflows and packet losses * change default mcast address * detect RTP loops git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@722 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-recv.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 1ac057d0e..610dc6e21 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "module-rtp-recv-symdef.h" @@ -57,7 +58,7 @@ PA_MODULE_USAGE( ) #define SAP_PORT 9875 -#define DEFAULT_SAP_ADDRESS "224.0.1.2" +#define DEFAULT_SAP_ADDRESS "224.0.1.3" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define MAX_SESSIONS 16 #define DEATH_TIMEOUT 20000000 @@ -157,6 +158,9 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event s->ssrc = s->rtp_context.ssrc; s->offset = s->rtp_context.timestamp; + + if (s->ssrc == s->userdata->core->cookie) + pa_log_warn(__FILE__": WARNING! Detected RTP packet loop!"); } else { if (s->ssrc != s->rtp_context.ssrc) { pa_memblock_unref(chunk.memblock); @@ -174,7 +178,12 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event delta = j; pa_memblockq_seek(s->memblockq, delta * s->rtp_context.frame_size, PA_SEEK_RELATIVE); - pa_memblockq_push(s->memblockq, &chunk); + + if (pa_memblockq_push(s->memblockq, &chunk) < 0) { + /* queue overflow, let's flush it and try again */ + pa_memblockq_flush(s->memblockq); + pa_memblockq_push(s->memblockq, &chunk); + } /* The next timestamp we expect */ s->offset = s->rtp_context.timestamp + (chunk.length / s->rtp_context.frame_size); @@ -250,6 +259,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in char *c; pa_sink *sink; int fd = -1; + pa_memblock *silence; if (!(sink = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { pa_log(__FILE__": sink does not exist."); @@ -284,19 +294,26 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in s->sink_input->drop = sink_input_drop; s->sink_input->kill = sink_input_kill; s->sink_input->get_latency = sink_input_get_latency; + + silence = pa_silence_memblock_new(&s->sink_input->sample_spec, + (pa_bytes_per_second(&s->sink_input->sample_spec)/128/pa_frame_size(&s->sink_input->sample_spec))* + pa_frame_size(&s->sink_input->sample_spec), + s->userdata->core->memblock_stat); s->memblockq = pa_memblockq_new( 0, MEMBLOCKQ_MAXLENGTH, MEMBLOCKQ_MAXLENGTH, pa_frame_size(&s->sink_input->sample_spec), - 1, + pa_bytes_per_second(&s->sink_input->sample_spec)/10+1, 0, - NULL, + silence, u->core->memblock_stat); - s->rtp_event = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, rtp_event_cb, s); + pa_memblock_unref(silence); + s->rtp_event = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, rtp_event_cb, s); + pa_gettimeofday(&tv); pa_timeval_add(&tv, DEATH_TIMEOUT); s->death_event = u->core->mainloop->time_new(u->core->mainloop, &tv, death_event_cb, s); From e8d9a5dbfb368ae0dc8a3d6aa497ee30ed30f454 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 16 Apr 2006 09:22:08 +0000 Subject: [PATCH 0630/1514] Clarify behaviour of deferred events. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@723 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/polyp/context.h b/src/polyp/context.h index 01c1b76a0..ff93dd110 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -41,7 +41,9 @@ * The API is based around an asynchronous event loop, or main loop, * abstraction. This abstraction contains three basic elements: * - * \li Deferred events - Events that trigger each iteration of the main loop. + * \li Deferred events - Events that will trigger as soon as possible. Note + * that some implementations may block all other events + * when a deferred event is active. * \li I/O events - Events that trigger on file descriptor activities. * \li Times events - Events that trigger after a fixed ammount of time. * From e75cc68685c598deb71fdd0de4b68d43c595362d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 16 Apr 2006 09:23:27 +0000 Subject: [PATCH 0631/1514] Fix ALSA fd handling to be compatible with blocking deferred events. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@724 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 683db6c06..2f9be07a7 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -89,7 +89,6 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t if (err < 0) { pa_log_error(__FILE__": Unable to get poll revent: %s", snd_strerror(err)); - a->defer_enable(fdl->defer, 0); return; } @@ -99,6 +98,8 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t else snd_mixer_handle_events(fdl->mixer); } + + a->defer_enable(fdl->defer, 1); } static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) { @@ -108,6 +109,8 @@ static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) { assert(a && fdl && (fdl->pcm || fdl->mixer)); + a->defer_enable(fdl->defer, 0); + if (fdl->pcm) num_fds = snd_pcm_poll_descriptors_count(fdl->pcm); else @@ -133,7 +136,6 @@ static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) { if (err < 0) { pa_log_error(__FILE__": Unable to get poll descriptors: %s", snd_strerror(err)); - a->defer_enable(fdl->defer, 0); return; } From 3b803e7168a92bbc4c43e47a1db64bce1513ca8b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 10:53:27 +0000 Subject: [PATCH 0632/1514] * make sure RTP ports are chosen to be even git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@725 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-monitor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/rtp/module-rtp-monitor.c b/src/modules/rtp/module-rtp-monitor.c index 0a050ca59..f91849ee3 100644 --- a/src/modules/rtp/module-rtp-monitor.c +++ b/src/modules/rtp/module-rtp-monitor.c @@ -208,12 +208,15 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - port = DEFAULT_PORT + (rand() % 512); + port = DEFAULT_PORT + ((rand() % 512) << 1); if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { pa_log(__FILE__": port= expects a numerical argument between 1 and 65535."); goto fail; } + if (port & 1) + pa_log_warn(__FILE__": WARNING: port number not even as suggested in RFC3550!"); + dest = pa_modargs_get_value(ma, "destination", DEFAULT_DESTINATION); if (inet_pton(AF_INET6, dest, &sa6.sin6_addr) > 0) { From b04a4e65cae6d0fc9e4403b6147db36556d68159 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 10:56:45 +0000 Subject: [PATCH 0633/1514] rename module-rtp-monitor to module-rtp-send git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@726 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 12 ++++++------ .../rtp/{module-rtp-monitor.c => module-rtp-send.c} | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) rename src/modules/rtp/{module-rtp-monitor.c => module-rtp-send.c} (99%) diff --git a/src/Makefile.am b/src/Makefile.am index 2ec62dca4..c30e24c3f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -722,7 +722,7 @@ modlib_LTLIBRARIES += \ module-esound-sink.la \ module-http-protocol-tcp.la \ module-detect.la \ - module-rtp-monitor.la \ + module-rtp-send.la \ module-rtp-recv.la if HAVE_AF_UNIX @@ -835,7 +835,7 @@ SYMDEF_FILES = \ modules/module-solaris-symdef.h \ modules/module-waveout-symdef.h \ modules/module-detect-symdef.h \ - modules/rtp/module-rtp-monitor-symdef.h \ + modules/rtp/module-rtp-send-symdef.h \ modules/rtp/module-rtp-recv-symdef.h EXTRA_DIST += $(SYMDEF_FILES) @@ -1052,10 +1052,10 @@ module_detect_la_LIBADD = $(AM_LIBADD) libpolypcore.la module_detect_la_CFLAGS = $(AM_CFLAGS) # RTP modules -module_rtp_monitor_la_SOURCES = modules/rtp/module-rtp-monitor.c -module_rtp_monitor_la_LDFLAGS = -module -avoid-version -module_rtp_monitor_la_LIBADD = $(AM_LIBADD) libpolypcore.la -module_rtp_monitor_la_CFLAGS = $(AM_CFLAGS) +module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c +module_rtp_send_la_LDFLAGS = -module -avoid-version +module_rtp_send_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_rtp_send_la_CFLAGS = $(AM_CFLAGS) module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c module_rtp_recv_la_LDFLAGS = -module -avoid-version diff --git a/src/modules/rtp/module-rtp-monitor.c b/src/modules/rtp/module-rtp-send.c similarity index 99% rename from src/modules/rtp/module-rtp-monitor.c rename to src/modules/rtp/module-rtp-send.c index f91849ee3..d692cd1db 100644 --- a/src/modules/rtp/module-rtp-monitor.c +++ b/src/modules/rtp/module-rtp-send.c @@ -1,4 +1,4 @@ -/* $Id */ +/* $Id$ */ /*** This file is part of polypaudio. @@ -43,7 +43,7 @@ #include #include -#include "module-rtp-monitor-symdef.h" +#include "module-rtp-send-symdef.h" #include "rtp.h" #include "sdp.h" From 68a6d611721b09b5ad23b0c85907654d8fa96bcc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 10:59:54 +0000 Subject: [PATCH 0634/1514] ignore symdef file of module-rtp-send git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@727 fefdeb5f-60dc-0310-8127-8f9354f1896f From e1887b552ceb324f70732c85c7458119e03718b7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 11:13:20 +0000 Subject: [PATCH 0635/1514] change default mcast address once again, to make sure our traffic doesn't leave the network by default git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@728 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-recv.c | 2 +- src/modules/rtp/module-rtp-send.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 610dc6e21..e47ca95ab 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -58,7 +58,7 @@ PA_MODULE_USAGE( ) #define SAP_PORT 9875 -#define DEFAULT_SAP_ADDRESS "224.0.1.3" +#define DEFAULT_SAP_ADDRESS "224.0.0.56" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define MAX_SESSIONS 16 #define DEATH_TIMEOUT 20000000 diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index d692cd1db..69d8c6c62 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -65,7 +65,7 @@ PA_MODULE_USAGE( #define DEFAULT_PORT 46000 #define SAP_PORT 9875 -#define DEFAULT_DESTINATION "224.0.1.3" +#define DEFAULT_DESTINATION "224.0.0.56" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define DEFAULT_MTU 1280 #define SAP_INTERVAL 5000000 From 08397d98e23d3ec953c66bd8cd90efb316e4bad1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 12:44:15 +0000 Subject: [PATCH 0636/1514] fix typo in module description git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@729 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-send.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 69d8c6c62..0bb20979b 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -57,7 +57,7 @@ PA_MODULE_USAGE( "format= " "channels= " "rate= " - "destinaton= " + "destination= " "port= " "mtu= " "loop=" From 2f3fa42ca6dddc56c4ddab1d7d8ac89ff6eb75d6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 12:44:43 +0000 Subject: [PATCH 0637/1514] limit number of concurrent RTP streams git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@730 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-recv.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index e47ca95ab..95d13c338 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -97,6 +97,8 @@ struct userdata { pa_hashmap *by_origin; char *sink_name; + + int n_sessions; }; static void session_free(struct session *s, int from_hash); @@ -261,6 +263,11 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in int fd = -1; pa_memblock *silence; + if (u->n_sessions >= MAX_SESSIONS) { + pa_log(__FILE__": session limit reached."); + goto fail; + } + if (!(sink = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { pa_log(__FILE__": sink does not exist."); goto fail; @@ -323,6 +330,8 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_rtp_context_init_recv(&s->rtp_context, fd, pa_frame_size(&s->sdp_info.sample_spec)); pa_log_info(__FILE__": Found new session '%s'", s->sdp_info.session_name); + + u->n_sessions++; return s; @@ -354,6 +363,9 @@ static void session_free(struct session *s, int from_hash) { pa_memblockq_free(s->memblockq); pa_sdp_info_destroy(&s->sdp_info); pa_rtp_context_destroy(&s->rtp_context); + + assert(s->userdata->n_sessions >= 1); + s->userdata->n_sessions--; pa_xfree(s); } From 7871f41f2e49978b8c5451516e7a464b0985828b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 13:34:09 +0000 Subject: [PATCH 0638/1514] add documentation for the new RTP modules git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@731 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/FAQ.html.in | 97 +++++++++++++++++++++++++++++++++++++-- doc/README.html.in | 3 +- doc/modules.html.in | 108 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 184 insertions(+), 24 deletions(-) diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in index 0e7382178..7adc24414 100644 --- a/doc/FAQ.html.in +++ b/doc/FAQ.html.in @@ -67,7 +67,7 @@ realtime, or increase the fragment sizes of the audio drivers. The former will allow Polypaudio to activate SCHED_FIFO high priority scheduling (root rights are dropped - immediately after this) Keep in mind that this is a potential security hole!

    + immediately after this). Keep in mind that this is a potential security hole!

  • The polypaudio executable is installed SUID root by default. Why this? Isn't this a potential security hole?

    @@ -103,7 +103,12 @@ in ~/.polypaudio/.

  • How do I use polypaudio over the network?

    -

    Just set $POLYP_SERVER to the host name of the polypaudio server.

    +

    Just set $POLYP_SERVER to the host name of the polypaudio +server. For authentication you need the same auth cookies on all sides. For +that copy ~./polypaudio-cookie to all clients that shall +be allowed to connect.

    + +

    Alternatively the authorization cookies can be stored in the X11 server.

  • Is polypaudio capable of providing synchronized audio playback over the network for movie players like mplayer?

    @@ -126,7 +131,7 @@ connect to a running polypaudio daemon try using the following commands:

    killall -USR2 polypaudio
     bidilink unix-client:/tmp/polypaudio/cli
    -

    BTW: Someone should package that great tool for Debian!

    +

    BTW: Someone should package this great tool for Debian!

    New: There's now a tool pacmd that automates sending SIGUSR2 to the daemon and running a bidilink like tool for you.

  • @@ -146,7 +151,91 @@ bidilink unix-client:/tmp/polypaudio/cli
  • Why the heck does libpolyp link against libX11?

    -

    The Polypaudio client libraries look for some X11 root window properties for the credentials of the Polypaudio server to access. You may compile Polypaudio without X11 for disabling this.

  • +

    The Polypaudio client libraries look for some X11 root window +properties for the credentials of the Polypaudio server to access. You +may compile Polypaudio without X11 for disabling this feature.

    + +
  • How can I use Polypaudio as an RTP based N:N multicast +conferencing solution for the LAN?

    After loading all the +necessary audio drivers for recording and playback, just load the RTP +reciever and sender modules with default parameters:

    + +
    +load-module module-rtp-send
    +load-module module-rtp-recv
    +
    + +

    As long as the Polypaudio daemon runs, the microphone data will be +streamed to the network and the data from other hosts is played back +locally. Please note that this may cause quite a lot of traffic. Hence +consider passing rate=8000 format=ulaw channels=1 to the +sender module to save bandwith while still maintaining good quality +for speech transmission.

  • + +
  • What is this RTP/SDP/SAP thing all about?

    + +

    RTP is the Realtime Transfer Protocol. It is a well-known +protocol for transferring audio and video data over IP. SDP is the Session +Description Protocol and can be used to describe RTP sessions. SAP +is the Session Announcement Protocol and can be used to +announce RTP sessions that are described with SDP. (Modern SIP based VoIP phones use RTP/SDP for their sessions, too)

    + +

    All three protocols are defined in IETF RFCs (RFC3550, RFC3551, +RFC2327, RFC2327). They can be used in both multicast and unicast +fashions. Polypaudio exclusively uses multicast RTP/SDP/SAP containing audio data.

    + +

    For more information about using these technologies with Polypaudio have a look on the respective module's documentation. + +

  • How can I use Polypaudio to stream music from my main PC to my LAN with multiple PCs with speakers?

    + +

    On the sender side create an RTP sink:

    + +
    +load-module module-null-sink sink_name=rtp
    +load-module module-rtp-send source=rtp_monitor
    +set-default-sink rtp
    +
    + +

    This will make rtp the default sink, i.e. all applications will write to this virtual RTP device by default.

    + +

    On the client sides just load the reciever module:

    +
    +load-module module-rtp-recv
    +
    + +

    Now you can play your favourite music on the sender side and all clients will output it simultaneously.

    + + +

    BTW: You can have more than one sender machine set up like this. The audio data will be mixed on the client side.

  • + +
  • How can I use Polypaudio to share a single LINE-IN/MIC jack on the entire LAN?

    + +

    On the sender side simply load the RTP sender module:

    + +
    +load-module module-rtp-send
    +
    + +

    On the reciever sides, create an RTP source:

    + +
    +load-module module-null-sink sink_name=rtp
    +load-module module-rtp-recv sink=rtp
    +set-default-source rtp_monitor
    +
    + +

    Now the audio data will be available from the default source rtp_monitor.

    + +
  • When sending multicast RTP traffic it is recieved on the entire LAN but not by the sender machine itself!

    + +

    Pass loop=1 to the sender module!

  • + +
  • Can I have more than one multicast RTP group?

    + +

    Yes! Simply use a new multicast group address. Use +the destination/sap_address arguments of the RTP +modules to select them. Choose your group addresses from the range +225.0.0.x to make sure the audio data never leaves the LAN.

  • diff --git a/doc/README.html.in b/doc/README.html.in index 3847a9e85..0e9b82610 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -44,7 +44,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    Thu Apr 13 2006:

    Version 0.8 released; -changes include: too many to count; many, many minor fixes.

    +changes include: too many to count - consider reading this blog entry for more information; many, many minor fixes.

    Sun Nov 21 2004:

    Version 0.7 released; @@ -152,6 +152,7 @@ available. A simple main loop implementation is available as well.

  • module-lirc: a module to control the volume of a sink with infrared remote controls supported by LIRC.
  • module-mmkbd-evdev: a module to control the volume of a sink with the special volume keys of a multimeda keyboard.
  • module-zeroconf-publish: a module to publish local sources/sinks using mDNS zeroconf.
  • +
  • module-rtp-send, module-rtp-recv: a module to implement RTP/SAP/SDP based audio streaming.
  • polypaudio is the successor of my previous, ill-fated diff --git a/doc/modules.html.in b/doc/modules.html.in index 67f0e1723..54cec804e 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -283,7 +283,7 @@ module and point your browser to http://localhost:4714/. This module takes the same arguments as module-cli-protocol-tcp.

    -

    Miscellaneous

    +

    X Window System

    module-x11-bell

    @@ -315,6 +315,94 @@ and import credential data from/to the X11 display.

    cookie to store in the X11 display. If ommited the cookie of an already loaded protocol module is used. +

    Volume Control

    + +

    module-mmkbd-evdev

    + +

    Adjust the volume of a sink when the special multimedia buttons of modern keyboards are pressed.

    + + + + +
    device=Linux input device ("evdev", defaults to /dev/input/event0)
    sink=The sink to control
    + +

    module-lirc

    + +

    Adjust the volume of a sink when the volume buttons of an infrared remote control are pressed (through LIRC).

    + + + + + +
    config=The LIRC configuration file
    appname=The application name to pass to LIRC (defaults to polypaudio)
    sink=The sink to control
    + + +

    RTP/SDP/SAP Transport

    + +

    Polypaudio can stream audio data to an IP multicast group via the +standard protocols RTP, +SAP +and SDP +(RFC3550, RFC3551, RFC2327, RFC2327). This can be used for multiple +different purposes: for sharing a single microphone on multiple +computers on the local LAN, for streaming music from a single +controlling PC to multiple PCs with speakers or to implement a simple +"always-on" teleconferencing solution.

    + +

    The current implementation is designed to be used exlusively in +local area networks, though Internet multicasting is theoretically +supported. Only uncompressed audio is supported, hence you won't be +able to multicast more than a few streams at the same time over a +standard LAN.

    + +

    Polypaudio implements both a sender and a reciever for RTP +traffic. The sender announces itself via SAP/SDP on the same multicast +group as it sends the RTP data to. The reciever picks up the SAP/SDP +announcements and creates a playback stream for each +session. Alternatively you can use any RTP capable client to +recieve and play back the RTP data (such as mplayer).

    + +

    module-rtp-send

    + +

    This is the sender side of the RTP/SDP/SAP implementation. It reads +audio data from an existing source and forwards it to the network +encapsulated in RTP. In addition it sends SAP packets with an SDP +session description.

    + +

    In combination with the monitor source of module-null-sink +you can use this module to create an RTP sink.

    + + + + + + + + +
    source=The source to read the audio data from. If ommited defaults to the default source.
    format=, rate=, channels=Sample format to use, defaults to the source's.
    destination=Destination multicast group for both RTP and SAP packets, defaults to 224.0.0.56
    port=Destination port number of the RTP +traffic. If ommited defaults to a randomly chosen even port +number. Please keep in mind that the RFC suggests to use only even +port numbers for RTP traffic.
    mtu=Maximum payload size for RTP packets. If ommited defaults to 1280
    loop=Takes a boolean value, specifying whether locally generated RTP traffic should be looped back to the local host. Disabled by default.
    + +

    module-rtp-recv

    + +

    This is the reciever side of the RTP/SDP/SAP implementation. It +picks up SAP session announcements and creates an RTP playback stream +for each.

    + +

    In combination with module-null-sink you can use this +module to create an RTP source.

    + + + + +
    sink=The sink to connect to. If ommited defaults to the default sink.
    sap_address=The multicast group to join for SAP announcements, defaults to 224.0.0.56.
    + +

    Miscellaneous

    +

    module-sine

    Creates a sink input and generates a sine waveform stream.

    @@ -360,24 +448,6 @@ already loaded protocol module is used.

    Publish all local sinks/sources using mDNS Zeroconf.

    -

    module-mmkbd-evdev

    - -

    Adjust the volume of a sink when the special multimedia buttons of modern keyboards are pressed.

    - - - - -
    device=Linux input device ("evdev", defaults to /dev/input/event0)
    sink=The sink to control
    - -

    module-lirc

    - -

    Adjust the volume of a sink when the volume buttons of an infrared remote control are pressed (through LIRC).

    - - - - - -
    config=The LIRC configuration file
    appname=The application name to pass to LIRC (defaults to polypaudio)
    sink=The sink to control

    Lennart Poettering <@PACKAGE_BUGREPORT@>, April 2006
    From a8bb073acc24c554ed3d8fcbd91b26b2799e641a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 16:45:47 +0000 Subject: [PATCH 0639/1514] properly initialize session counter git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@732 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-recv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 95d13c338..525a88194 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -455,6 +455,7 @@ int pa__init(pa_core *c, pa_module*m) { u->module = m; u->core = c; u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + u->n_sessions = 0; u->sap_event = c->mainloop->io_new(c->mainloop, fd, PA_IO_EVENT_INPUT, sap_event_cb, u); From 76296ca8adccec12aa84163da55c6204d7667bf5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 16:46:26 +0000 Subject: [PATCH 0640/1514] add new API to replace the poll() function used by the main loop implementation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@733 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/mainloop.c | 19 ++++++++++++++++++- src/polyp/mainloop.h | 8 ++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index da3f57b2e..87ef623e1 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -101,6 +101,9 @@ struct pa_mainloop { STATE_POLLED, STATE_QUIT } state; + + pa_poll_func poll_func; + void *poll_func_userdata; }; /* IO events */ @@ -355,6 +358,9 @@ pa_mainloop *pa_mainloop_new(void) { m->deferred_pending = 0; m->state = STATE_PASSIVE; + + m->poll_func = NULL; + m->poll_func_userdata = NULL; return m; } @@ -665,7 +671,10 @@ int pa_mainloop_poll(pa_mainloop *m) { if (m->deferred_pending) r = 0; else { - r = poll(m->pollfds, m->n_pollfds, m->prepared_timeout); + if (m->poll_func) + r = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata); + else + r = poll(m->pollfds, m->n_pollfds, m->prepared_timeout); if (r < 0) { if (errno == EINTR) @@ -767,6 +776,14 @@ pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) { return &m->api; } +void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) { + assert(m); + + m->poll_func = poll_func; + m->poll_func_userdata = userdata; +} + + #if 0 void pa_mainloop_dump(pa_mainloop *m) { assert(m); diff --git a/src/polyp/mainloop.h b/src/polyp/mainloop.h index fe2b4c5b4..f60c355ae 100644 --- a/src/polyp/mainloop.h +++ b/src/polyp/mainloop.h @@ -70,6 +70,8 @@ PA_C_DECL_BEGIN * defined in \ref mainloop-api.h. This implementation is thread safe * as long as you access the main loop object from a single thread only.*/ +#include + /** An opaque main loop object */ typedef struct pa_mainloop pa_mainloop; @@ -114,6 +116,12 @@ void pa_mainloop_quit(pa_mainloop *m, int r); /** Interrupt a running poll (for threaded systems) */ void pa_mainloop_wakeup(pa_mainloop *m); +/** Generic prototype of a poll() like function */ +typedef int (*pa_poll_func)(struct pollfd *ufds, nfds_t nfds, int timeout, void*userdata); + +/** Change the poll() implementation */ +void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata); + PA_C_DECL_END #endif From 40f171f5de18b19b4ea1db40b2f1b2de9bbf73d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Apr 2006 17:25:14 +0000 Subject: [PATCH 0641/1514] * add pa_mainloop_wakeup() calls for deferred events * place pa_mainloop_wakeup() calls a little bit more carfully, to minimize needless wakeups. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@734 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/mainloop.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 87ef623e1..42a411d34 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -121,8 +121,6 @@ static pa_io_event* mainloop_io_new( m = a->userdata; assert(a == &m->api); - pa_mainloop_wakeup(m); - e = pa_xmalloc(sizeof(pa_io_event)); e->mainloop = m; e->dead = 0; @@ -156,24 +154,27 @@ static pa_io_event* mainloop_io_new( pa_idxset_put(m->io_events, e, NULL); m->rebuild_pollfds = 1; + + pa_mainloop_wakeup(m); + return e; } static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { assert(e && e->mainloop); - pa_mainloop_wakeup(e->mainloop); - e->events = events; e->mainloop->rebuild_pollfds = 1; + + pa_mainloop_wakeup(e->mainloop); } static void mainloop_io_free(pa_io_event *e) { assert(e && e->mainloop); - pa_mainloop_wakeup(e->mainloop); - e->dead = e->mainloop->io_events_scan_dead = e->mainloop->rebuild_pollfds = 1; + + pa_mainloop_wakeup(e->mainloop); } static void mainloop_io_set_destroy(pa_io_event *e, void (*callback)(pa_mainloop_api*a, pa_io_event *e, void *userdata)) { @@ -202,6 +203,9 @@ static pa_defer_event* mainloop_defer_new(pa_mainloop_api*a, void (*callback) (p pa_idxset_put(m->defer_events, e, NULL); m->deferred_pending++; + + pa_mainloop_wakeup(e->mainloop); + return e; } @@ -211,8 +215,10 @@ static void mainloop_defer_enable(pa_defer_event *e, int b) { if (e->enabled && !b) { assert(e->mainloop->deferred_pending > 0); e->mainloop->deferred_pending--; - } else if (!e->enabled && b) + } else if (!e->enabled && b) { e->mainloop->deferred_pending++; + pa_mainloop_wakeup(e->mainloop); + } e->enabled = b; } @@ -242,8 +248,6 @@ static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval m = a->userdata; assert(a == &m->api); - pa_mainloop_wakeup(m); - e = pa_xmalloc(sizeof(pa_time_event)); e->mainloop = m; e->dead = 0; @@ -257,6 +261,9 @@ static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval e->destroy_callback = NULL; pa_idxset_put(m->time_events, e, NULL); + + if (e->enabled) + pa_mainloop_wakeup(m); return e; } @@ -264,11 +271,11 @@ static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { assert(e); - pa_mainloop_wakeup(e->mainloop); - if (tv) { e->enabled = 1; e->timeval = *tv; + + pa_mainloop_wakeup(e->mainloop); } else e->enabled = 0; } @@ -276,9 +283,9 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { static void mainloop_time_free(pa_time_event *e) { assert(e); - pa_mainloop_wakeup(e->mainloop); - e->dead = e->mainloop->time_events_scan_dead = 1; + + /* no wakeup needed here. Think about it! */ } static void mainloop_time_set_destroy(pa_time_event *e, void (*callback)(pa_mainloop_api*a, pa_time_event *e, void *userdata)) { @@ -294,10 +301,10 @@ static void mainloop_quit(pa_mainloop_api*a, int retval) { m = a->userdata; assert(a == &m->api); - pa_mainloop_wakeup(m); - m->quit = 1; m->retval = retval; + + pa_mainloop_wakeup(m); } static const pa_mainloop_api vtable = { From 4482e6867df82e889f48a9e7c22f2e0887b1028c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 17 Apr 2006 00:11:04 +0000 Subject: [PATCH 0642/1514] add new JACK sink git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@735 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 9 + src/Makefile.am | 15 +- src/modules/module-jack-sink.c | 382 +++++++++++++++++++++++++++++++++ 3 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 src/modules/module-jack-sink.c diff --git a/configure.ac b/configure.ac index e649e0634..3fd32f821 100644 --- a/configure.ac +++ b/configure.ac @@ -345,11 +345,20 @@ AC_SUBST(HOWL_LIBS) AC_SUBST(HAVE_HOWL) AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1]) +### LIBOIL #### PKG_CHECK_MODULES(LIBOIL, [ liboil-0.3 >= 0.3.0 ]) AC_SUBST(LIBOIL_CFLAGS) AC_SUBST(LIBOIL_LIBS) +### JACK #### + +PKG_CHECK_MODULES(JACK, [ jack >= 0.100 ], HAVE_JACK=1, HAVE_JACK=0) +AC_SUBST(JACK_CFLAGS) +AC_SUBST(JACK_LIBS) +AC_SUBST(HAVE_JACK) +AM_CONDITIONAL([HAVE_JACK], [test "x$HAVE_JACK" = x1]) + #### Async DNS support (optional) #### PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, HAVE_LIBASYNCNS=0) diff --git a/src/Makefile.am b/src/Makefile.am index c30e24c3f..c58643730 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -792,6 +792,11 @@ modlib_LTLIBRARIES += \ module-mmkbd-evdev.la endif +if HAVE_JACK +modlib_LTLIBRARIES += \ + module-jack-sink.la +endif + if OS_IS_WIN32 modlib_LTLIBRARIES += \ module-waveout.la @@ -836,7 +841,8 @@ SYMDEF_FILES = \ modules/module-waveout-symdef.h \ modules/module-detect-symdef.h \ modules/rtp/module-rtp-send-symdef.h \ - modules/rtp/module-rtp-recv-symdef.h + modules/rtp/module-rtp-recv-symdef.h \ + modules/module-jack-sink-symdef.h EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) @@ -1062,6 +1068,13 @@ module_rtp_recv_la_LDFLAGS = -module -avoid-version module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpolypcore.la module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) +# JACK + +module_jack_sink_la_SOURCES = modules/module-jack-sink.c +module_jack_sink_la_LDFLAGS = -module -avoid-version +module_jack_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(JACK_LIBS) +module_jack_sink_la_CFLAGS = $(AM_LIBADD) libpolypcore.la $(JACK_CFLAGS) + ################################### # Some minor stuff # ################################### diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c new file mode 100644 index 000000000..3d3725512 --- /dev/null +++ b/src/modules/module-jack-sink.c @@ -0,0 +1,382 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-jack-sink-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Jack Sink") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE( + "sink_name= " + "server_name= " + "channels= " + "connect=" + "port_prefix=" +) + +#define DEFAULT_SINK_NAME "jack_out" + +struct userdata { + pa_core *core; + pa_module *module; + + pa_sink *sink; + + unsigned channels; + + jack_port_t* port[PA_CHANNELS_MAX]; + jack_client_t *client; + + pthread_mutex_t mutex; + pthread_cond_t cond; + + void * buffer[PA_CHANNELS_MAX]; + jack_nframes_t frames_requested; + int quit_requested; + + int pipe_fds[2]; + pa_io_event *io_event; + + jack_nframes_t frames_in_buffer; + struct timeval timestamp; +}; + +static const char* const valid_modargs[] = { + "sink_name", + "server_name", + "channels", + "connect", + "port_prefix", + NULL +}; + +static void stop_sink(struct userdata *u) { + assert (u); + + jack_client_close(u->client); + u->client = NULL; + u->core->mainloop->io_free(u->io_event); + u->io_event = NULL; + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + u->sink = NULL; + pa_module_unload_request(u->module); +} + +static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { + struct userdata *u = userdata; + char x; + + assert(m); + assert(flags == PA_IO_EVENT_INPUT); + assert(u); + assert(u->pipe_fds[0] == fd); + + read(fd, &x, 1); + + if (u->quit_requested) { + stop_sink(u); + u->quit_requested = 0; + return; + } + + pthread_mutex_lock(&u->mutex); + + if (u->frames_requested > 0) { + unsigned fs; + jack_nframes_t frame_idx; + pa_memchunk chunk; + + fs = pa_frame_size(&u->sink->sample_spec); + + pa_sink_render_full(u->sink, u->frames_requested * fs, &chunk); + + for (frame_idx = 0; frame_idx < u->frames_requested; frame_idx ++) { + unsigned c; + + for (c = 0; c < u->channels; c++) { + float *s = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c; + float *d = ((float*) u->buffer[c]) + frame_idx; + + *d = *s; + } + } + + pa_memblock_unref(chunk.memblock); + + u->frames_requested = 0; + + pthread_cond_signal(&u->cond); + } + + pthread_mutex_unlock(&u->mutex); +} + +static void request_render(struct userdata *u) { + char c = 'x'; + assert(u); + + assert(u->pipe_fds[1] >= 0); + write(u->pipe_fds[1], &c, 1); +} + +static void jack_shutdown(void *arg) { + struct userdata *u = arg; + assert(u); + + u->quit_requested = 1; + request_render(u); +} + +static int jack_process(jack_nframes_t nframes, void *arg) { + struct userdata *u = arg; + assert(u); + + if (jack_transport_query(u->client, NULL) == JackTransportRolling) { + unsigned c; + + pthread_mutex_lock(&u->mutex); + + u->frames_requested = nframes; + + for (c = 0; c < u->channels; c++) { + u->buffer[c] = jack_port_get_buffer(u->port[c], nframes); + assert(u->buffer[c]); + } + + request_render(u); + + pthread_cond_wait(&u->cond, &u->mutex); + + u->frames_in_buffer = nframes; + pa_gettimeofday(&u->timestamp); + + pthread_mutex_unlock(&u->mutex); + } + + return 0; +} + +static pa_usec_t sink_get_latency_cb(pa_sink *s) { + struct userdata *u; + pa_usec_t t, delta; + assert(s); + u = s->userdata; + + if (jack_transport_query(u->client, NULL) != JackTransportRolling) + return 0; + + delta = pa_timeval_age(&u->timestamp); + t = pa_bytes_to_usec(jack_port_get_total_latency(u->client, u->port[0]) * pa_frame_size(&s->sample_spec), &s->sample_spec); + + if (t > delta) + return t - delta; + else + return 0; +} + +static void jack_error_func(const char*t) { + pa_log_warn(__FILE__": JACK error >%s<", t); +} + +int pa__init(pa_core *c, pa_module*m) { + struct userdata *u = NULL; + pa_sample_spec ss; + pa_modargs *ma = NULL; + jack_status_t status; + const char *server_name; + uint32_t channels; + int connect = 1; + const char *pfx; + unsigned i; + + assert(c); + assert(m); + + jack_set_error_function(jack_error_func); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments."); + goto fail; + } + + channels = c->default_sample_spec.channels; + if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { + pa_log(__FILE__": failed to parse channels= argument."); + goto fail; + } + + if (pa_modargs_get_value_boolean(ma, "connect", &connect) < 0) { + pa_log(__FILE__": failed to parse connect= argument."); + goto fail; + } + + server_name = pa_modargs_get_value(ma, "server_name", NULL); + + u = pa_xnew0(struct userdata, 1); + m->userdata = u; + u->core = c; + u->module = m; + u->pipe_fds[0] = u->pipe_fds[1] = -1; + + pthread_mutex_init(&u->mutex, NULL); + pthread_cond_init(&u->cond, NULL); + + if (pipe(u->pipe_fds) < 0) { + pa_log(__FILE__": pipe() failed: %s", strerror(errno)); + goto fail; + } + + pa_make_nonblock_fd(u->pipe_fds[1]); + + if (!(u->client = jack_client_open("polypaudio", server_name ? JackServerName : JackNullOption, &status, server_name))) { + pa_log(__FILE__": jack_client_open() failed."); + goto fail; + } + + pa_log_info(__FILE__": Successfully connected as '%s'", jack_get_client_name(u->client)); + + ss.channels = u->channels = channels; + ss.rate = jack_get_sample_rate(u->client); + ss.format = PA_SAMPLE_FLOAT32NE; + + assert(pa_sample_spec_valid(&ss)); + + pfx = pa_modargs_get_value(ma, "port_prefix", "channel"); + + for (i = 0; i < ss.channels; i++) { + char tmp[64]; + + snprintf(tmp, sizeof(tmp), "%s_%i", pfx, i+1); + + if (!(u->port[i] = jack_port_register(u->client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput/*|JackPortIsTerminal*/, 0))) { + pa_log(__FILE__": jack_port_register() failed."); + goto fail; + } + } + + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { + pa_log(__FILE__": failed to create sink."); + goto fail; + } + + u->sink->userdata = u; + pa_sink_set_owner(u->sink, m); + u->sink->description = pa_sprintf_malloc("Jack sink (%s)", jack_get_client_name(u->client)); + u->sink->get_latency = sink_get_latency_cb; + + jack_set_process_callback(u->client, jack_process, u); + jack_on_shutdown(u->client, jack_shutdown, u); + + if (jack_activate(u->client)) { + pa_log(__FILE__": jack_activate() failed"); + goto fail; + } + + if (connect) { + const char **p, **ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); + + for (i = 0, p = ports; i < ss.channels; i++, p++) { + + if (!p) { + pa_log(__FILE__": not enough physical output ports, leaving unconnected."); + break; + } + + pa_log_info(__FILE__": connecting %s to %s", jack_port_name(u->port[i]), *p); + + if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) { + pa_log(__FILE__": failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); + break; + } + } + + free(ports); + } + + u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u); + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(c, m); + + return -1; +} + +void pa__done(pa_core *c, pa_module*m) { + struct userdata *u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + if (u->client) + jack_client_close(u->client); + + if (u->io_event) + c->mainloop->io_free(u->io_event); + + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + } + + if (u->pipe_fds[0] >= 0) + close(u->pipe_fds[0]); + if (u->pipe_fds[1] >= 0) + close(u->pipe_fds[1]); + + pthread_mutex_destroy(&u->mutex); + pthread_cond_destroy(&u->cond); + pa_xfree(u); +} From 8b99a067a842c439c9b24a2cb62c68447dd8f21f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 18 Apr 2006 12:46:03 +0000 Subject: [PATCH 0643/1514] C99 requires explicit marking of integer literals' size. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@736 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-recv.c | 2 +- src/modules/rtp/sdp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 525a88194..a714e1625 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -172,7 +172,7 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event /* Check wheter there was a timestamp overflow */ k = (int64_t) s->rtp_context.timestamp - (int64_t) s->offset; - j = (int64_t) 0x100000000 - (int64_t) s->offset + (int64_t) s->rtp_context.timestamp; + j = (int64_t) 0x100000000LL - (int64_t) s->offset + (int64_t) s->rtp_context.timestamp; if ((k < 0 ? -k : k) < (j < 0 ? -j : j)) delta = k; diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index 9dca15baf..84bcd83b0 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -55,7 +55,7 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u if (!(u = getenv("USERNAME"))) u = "-"; - ntp = time(NULL) + 2208988800; + ntp = time(NULL) + 2208988800U; a = inet_ntop(af, src, buf_src, sizeof(buf_src)); assert(a); From cf85794e2349631f6d997592bceca2174c044f0c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 13:20:50 +0000 Subject: [PATCH 0644/1514] * allow the user to set the jack client name * take the number of channels for the sink from the number of physical ports in the jack server * name the polypaudio ports in the jack server after their channel position in polypaudio git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@737 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-jack-sink.c | 76 ++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 3d3725512..4f7a66eb5 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -52,10 +52,10 @@ PA_MODULE_DESCRIPTION("Jack Sink") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE( "sink_name= " - "server_name= " + "server_name= " + "client_name= " "channels= " "connect=" - "port_prefix=" ) #define DEFAULT_SINK_NAME "jack_out" @@ -82,15 +82,15 @@ struct userdata { pa_io_event *io_event; jack_nframes_t frames_in_buffer; - struct timeval timestamp; + jack_nframes_t timestamp; }; static const char* const valid_modargs[] = { "sink_name", "server_name", + "client_name", "channels", "connect", - "port_prefix", NULL }; @@ -193,7 +193,7 @@ static int jack_process(jack_nframes_t nframes, void *arg) { pthread_cond_wait(&u->cond, &u->mutex); u->frames_in_buffer = nframes; - pa_gettimeofday(&u->timestamp); + u->timestamp = jack_get_current_transport_frame(u->client); pthread_mutex_unlock(&u->mutex); } @@ -203,20 +203,26 @@ static int jack_process(jack_nframes_t nframes, void *arg) { static pa_usec_t sink_get_latency_cb(pa_sink *s) { struct userdata *u; - pa_usec_t t, delta; + jack_nframes_t n, l, d; + assert(s); u = s->userdata; if (jack_transport_query(u->client, NULL) != JackTransportRolling) return 0; - delta = pa_timeval_age(&u->timestamp); - t = pa_bytes_to_usec(jack_port_get_total_latency(u->client, u->port[0]) * pa_frame_size(&s->sample_spec), &s->sample_spec); + n = jack_get_current_transport_frame(u->client); - if (t > delta) - return t - delta; - else + if (n < u->timestamp) return 0; + + d = n - u->timestamp; + l = jack_port_get_total_latency(u->client, u->port[0]) + u->frames_in_buffer; + + if (d >= l) + return 0; + + return pa_bytes_to_usec((l - d) * pa_frame_size(&s->sample_spec), &s->sample_spec); } static void jack_error_func(const char*t) { @@ -226,13 +232,14 @@ static void jack_error_func(const char*t) { int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; + pa_channel_map cm; pa_modargs *ma = NULL; jack_status_t status; - const char *server_name; - uint32_t channels; + const char *server_name, *client_name; + uint32_t channels = 0; int connect = 1; - const char *pfx; unsigned i; + const char **ports = NULL, **p; assert(c); assert(m); @@ -244,18 +251,13 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - channels = c->default_sample_spec.channels; - if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { - pa_log(__FILE__": failed to parse channels= argument."); - goto fail; - } - if (pa_modargs_get_value_boolean(ma, "connect", &connect) < 0) { pa_log(__FILE__": failed to parse connect= argument."); goto fail; } server_name = pa_modargs_get_value(ma, "server_name", NULL); + client_name = pa_modargs_get_value(ma, "client_name", "polypaudio"); u = pa_xnew0(struct userdata, 1); m->userdata = u; @@ -273,11 +275,25 @@ int pa__init(pa_core *c, pa_module*m) { pa_make_nonblock_fd(u->pipe_fds[1]); - if (!(u->client = jack_client_open("polypaudio", server_name ? JackServerName : JackNullOption, &status, server_name))) { + if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { pa_log(__FILE__": jack_client_open() failed."); goto fail; } + ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); + + channels = 0; + for (p = ports; *p; p++) + channels++; + + if (!channels) + channels = c->default_sample_spec.channels; + + if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { + pa_log(__FILE__": failed to parse channels= argument."); + goto fail; + } + pa_log_info(__FILE__": Successfully connected as '%s'", jack_get_client_name(u->client)); ss.channels = u->channels = channels; @@ -286,20 +302,16 @@ int pa__init(pa_core *c, pa_module*m) { assert(pa_sample_spec_valid(&ss)); - pfx = pa_modargs_get_value(ma, "port_prefix", "channel"); + pa_channel_map_init_auto(&cm, channels); for (i = 0; i < ss.channels; i++) { - char tmp[64]; - - snprintf(tmp, sizeof(tmp), "%s_%i", pfx, i+1); - - if (!(u->port[i] = jack_port_register(u->client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput/*|JackPortIsTerminal*/, 0))) { + if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(cm.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0))) { pa_log(__FILE__": jack_port_register() failed."); goto fail; } } - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &cm))) { pa_log(__FILE__": failed to create sink."); goto fail; } @@ -318,11 +330,9 @@ int pa__init(pa_core *c, pa_module*m) { } if (connect) { - const char **p, **ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); - for (i = 0, p = ports; i < ss.channels; i++, p++) { - if (!p) { + if (!*p) { pa_log(__FILE__": not enough physical output ports, leaving unconnected."); break; } @@ -335,11 +345,11 @@ int pa__init(pa_core *c, pa_module*m) { } } - free(ports); } u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u); + free(ports); pa_modargs_free(ma); return 0; @@ -347,6 +357,8 @@ int pa__init(pa_core *c, pa_module*m) { fail: if (ma) pa_modargs_free(ma); + + free(ports); pa__done(c, m); From abea726d16eecbc0ecfb60c5e23958ed5275b779 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 13:22:41 +0000 Subject: [PATCH 0645/1514] add a jack source module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@738 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-jack-source.c | 393 +++++++++++++++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 src/modules/module-jack-source.c diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c new file mode 100644 index 000000000..eef416f60 --- /dev/null +++ b/src/modules/module-jack-source.c @@ -0,0 +1,393 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-jack-source-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Jack Source") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE( + "source_name= " + "server_name= " + "client_name= " + "channels= " + "connect=" +) + +#define DEFAULT_SOURCE_NAME "jack_in" + +struct userdata { + pa_core *core; + pa_module *module; + + pa_source *source; + + unsigned channels; + + jack_port_t* port[PA_CHANNELS_MAX]; + jack_client_t *client; + + pthread_mutex_t mutex; + pthread_cond_t cond; + + void * buffer[PA_CHANNELS_MAX]; + jack_nframes_t frames_posted; + int quit_requested; + + int pipe_fds[2]; + pa_io_event *io_event; + + jack_nframes_t frames_in_buffer; + jack_nframes_t timestamp; +}; + +static const char* const valid_modargs[] = { + "source_name", + "server_name", + "client_name", + "channels", + "connect", + NULL +}; + +static void stop_source(struct userdata *u) { + assert (u); + + jack_client_close(u->client); + u->client = NULL; + u->core->mainloop->io_free(u->io_event); + u->io_event = NULL; + pa_source_disconnect(u->source); + pa_source_unref(u->source); + u->source = NULL; + pa_module_unload_request(u->module); +} + +static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { + struct userdata *u = userdata; + char x; + + assert(m); + assert(flags == PA_IO_EVENT_INPUT); + assert(u); + assert(u->pipe_fds[0] == fd); + + read(fd, &x, 1); + + if (u->quit_requested) { + stop_source(u); + u->quit_requested = 0; + return; + } + + pthread_mutex_lock(&u->mutex); + + if (u->frames_posted > 0) { + unsigned fs; + jack_nframes_t frame_idx; + pa_memchunk chunk; + + fs = pa_frame_size(&u->source->sample_spec); + + chunk.memblock = pa_memblock_new(chunk.length = u->frames_posted * fs, u->core->memblock_stat); + chunk.index = 0; + + for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) { + unsigned c; + + for (c = 0; c < u->channels; c++) { + float *s = ((float*) u->buffer[c]) + frame_idx; + float *d = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c; + + *d = *s; + } + } + + pa_source_post(u->source, &chunk); + pa_memblock_unref(chunk.memblock); + + u->frames_posted = 0; + + pthread_cond_signal(&u->cond); + } + + pthread_mutex_unlock(&u->mutex); +} + +static void request_post(struct userdata *u) { + char c = 'x'; + assert(u); + + assert(u->pipe_fds[1] >= 0); + write(u->pipe_fds[1], &c, 1); +} + +static void jack_shutdown(void *arg) { + struct userdata *u = arg; + assert(u); + + u->quit_requested = 1; + request_post(u); +} + +static int jack_process(jack_nframes_t nframes, void *arg) { + struct userdata *u = arg; + assert(u); + + if (jack_transport_query(u->client, NULL) == JackTransportRolling) { + unsigned c; + + pthread_mutex_lock(&u->mutex); + + u->frames_posted = nframes; + + for (c = 0; c < u->channels; c++) { + u->buffer[c] = jack_port_get_buffer(u->port[c], nframes); + assert(u->buffer[c]); + } + + request_post(u); + + pthread_cond_wait(&u->cond, &u->mutex); + + u->frames_in_buffer = nframes; + u->timestamp = jack_get_current_transport_frame(u->client); + + pthread_mutex_unlock(&u->mutex); + } + + return 0; +} + +static pa_usec_t source_get_latency_cb(pa_source *s) { + struct userdata *u; + jack_nframes_t n, l, d; + + assert(s); + u = s->userdata; + + if (jack_transport_query(u->client, NULL) != JackTransportRolling) + return 0; + + n = jack_get_current_transport_frame(u->client); + + if (n < u->timestamp) + return 0; + + d = n - u->timestamp; + l = jack_port_get_total_latency(u->client, u->port[0]); + + return pa_bytes_to_usec((l + d) * pa_frame_size(&s->sample_spec), &s->sample_spec); +} + +static void jack_error_func(const char*t) { + pa_log_warn(__FILE__": JACK error >%s<", t); +} + +int pa__init(pa_core *c, pa_module*m) { + struct userdata *u = NULL; + pa_sample_spec ss; + pa_channel_map cm; + pa_modargs *ma = NULL; + jack_status_t status; + const char *server_name, *client_name; + uint32_t channels = 0; + int connect = 1; + unsigned i; + const char **ports = NULL, **p; + + assert(c); + assert(m); + + jack_set_error_function(jack_error_func); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments."); + goto fail; + } + + if (pa_modargs_get_value_boolean(ma, "connect", &connect) < 0) { + pa_log(__FILE__": failed to parse connect= argument."); + goto fail; + } + + server_name = pa_modargs_get_value(ma, "server_name", NULL); + client_name = pa_modargs_get_value(ma, "client_name", "polypaudio"); + + u = pa_xnew0(struct userdata, 1); + m->userdata = u; + u->core = c; + u->module = m; + u->pipe_fds[0] = u->pipe_fds[1] = -1; + + pthread_mutex_init(&u->mutex, NULL); + pthread_cond_init(&u->cond, NULL); + + if (pipe(u->pipe_fds) < 0) { + pa_log(__FILE__": pipe() failed: %s", strerror(errno)); + goto fail; + } + + pa_make_nonblock_fd(u->pipe_fds[1]); + + if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { + pa_log(__FILE__": jack_client_open() failed."); + goto fail; + } + + ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput); + + channels = 0; + for (p = ports; *p; p++) + channels++; + + if (!channels) + channels = c->default_sample_spec.channels; + + if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { + pa_log(__FILE__": failed to parse channels= argument."); + goto fail; + } + + pa_log_info(__FILE__": Successfully connected as '%s'", jack_get_client_name(u->client)); + + ss.channels = u->channels = channels; + ss.rate = jack_get_sample_rate(u->client); + ss.format = PA_SAMPLE_FLOAT32NE; + + assert(pa_sample_spec_valid(&ss)); + + pa_channel_map_init_auto(&cm, channels); + + for (i = 0; i < ss.channels; i++) { + if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(cm.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput|JackPortIsTerminal, 0))) { + pa_log(__FILE__": jack_port_register() failed."); + goto fail; + } + } + + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &cm))) { + pa_log(__FILE__": failed to create source."); + goto fail; + } + + u->source->userdata = u; + pa_source_set_owner(u->source, m); + u->source->description = pa_sprintf_malloc("Jack source (%s)", jack_get_client_name(u->client)); + u->source->get_latency = source_get_latency_cb; + + jack_set_process_callback(u->client, jack_process, u); + jack_on_shutdown(u->client, jack_shutdown, u); + + if (jack_activate(u->client)) { + pa_log(__FILE__": jack_activate() failed"); + goto fail; + } + + if (connect) { + for (i = 0, p = ports; i < ss.channels; i++, p++) { + + if (!*p) { + pa_log(__FILE__": not enough physical output ports, leaving unconnected."); + break; + } + + pa_log_info(__FILE__": connecting %s to %s", jack_port_name(u->port[i]), *p); + + if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) { + pa_log(__FILE__": failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); + break; + } + } + + } + + u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u); + + free(ports); + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + free(ports); + + pa__done(c, m); + + return -1; +} + +void pa__done(pa_core *c, pa_module*m) { + struct userdata *u; + assert(c && m); + + if (!(u = m->userdata)) + return; + + if (u->client) + jack_client_close(u->client); + + if (u->io_event) + c->mainloop->io_free(u->io_event); + + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + } + + if (u->pipe_fds[0] >= 0) + close(u->pipe_fds[0]); + if (u->pipe_fds[1] >= 0) + close(u->pipe_fds[1]); + + pthread_mutex_destroy(&u->mutex); + pthread_cond_destroy(&u->cond); + pa_xfree(u); +} From c3087d02ba272059f86f9b1794f792daf2cd8e89 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 18 Apr 2006 13:36:30 +0000 Subject: [PATCH 0646/1514] Avoid including non-portable header sys/poll.h. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@739 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/mainloop.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/polyp/mainloop.h b/src/polyp/mainloop.h index f60c355ae..4681912bb 100644 --- a/src/polyp/mainloop.h +++ b/src/polyp/mainloop.h @@ -27,6 +27,8 @@ PA_C_DECL_BEGIN +struct pollfd; + /** \page mainloop Main Loop * * \section overv_sec Overview @@ -70,8 +72,6 @@ PA_C_DECL_BEGIN * defined in \ref mainloop-api.h. This implementation is thread safe * as long as you access the main loop object from a single thread only.*/ -#include - /** An opaque main loop object */ typedef struct pa_mainloop pa_mainloop; @@ -117,7 +117,7 @@ void pa_mainloop_quit(pa_mainloop *m, int r); void pa_mainloop_wakeup(pa_mainloop *m); /** Generic prototype of a poll() like function */ -typedef int (*pa_poll_func)(struct pollfd *ufds, nfds_t nfds, int timeout, void*userdata); +typedef int (*pa_poll_func)(struct pollfd *ufds, unsigned long nfds, int timeout, void*userdata); /** Change the poll() implementation */ void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata); From 2d6ab01fbb9c670b5b1831aea0681fd17fcdcf88 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 18 Apr 2006 13:36:59 +0000 Subject: [PATCH 0647/1514] We need to emulate sendmsg/recvmsg to support rtp on Windows. Will do this some time in the future. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@740 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index c58643730..f6fc509bb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -589,8 +589,13 @@ modlib_LTLIBRARIES = \ libprotocol-simple.la \ libprotocol-esound.la \ libprotocol-native.la \ - libprotocol-http.la \ + libprotocol-http.la + +# We need to emulate sendmsg/recvmsg to support this on Win32 +if !OS_IS_WIN32 +modlib_LTLIBRARIES += \ librtp.la +endif if HAVE_X11 polypcoreinclude_HEADERS += \ @@ -721,9 +726,14 @@ modlib_LTLIBRARIES += \ module-null-sink.la \ module-esound-sink.la \ module-http-protocol-tcp.la \ - module-detect.la \ + module-detect.la + +# See comment at librtp.la above +if !OS_IS_WIN32 +modlib_LTLIBRARIES += \ module-rtp-send.la \ module-rtp-recv.la +endif if HAVE_AF_UNIX modlib_LTLIBRARIES += \ From 18055e473c5763e9e391f0d956ff57f84002ba13 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 18 Apr 2006 13:37:34 +0000 Subject: [PATCH 0648/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@741 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 8688f05d1..e7ba47c88 100644 --- a/doc/todo +++ b/doc/todo @@ -11,6 +11,7 @@ Post 0.8: - multiline configuration statements - use scatter/gather io for sockets - add a synchronous API (base it on xmms-polyp) +- rtp module ported to Win32 (sendmsg/recvmsg emulation) Long term: - pass meta info for hearing impaired From 074b7c1df119e358361efb9c2a78b256b3a440ff Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 18 Apr 2006 14:09:56 +0000 Subject: [PATCH 0649/1514] More fixes caused by Sun's complete inability to follow any standard whatsoever. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@742 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 13 +++++++++++++ src/modules/rtp/rtp.c | 8 ++++++-- src/modules/rtp/sap.c | 4 ++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 3fd32f821..4f9b88236 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,16 @@ if type -p stow > /dev/null && test -d /usr/local/stow ; then ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}" fi +#### Platform hacks #### + +case $host in + *-*-solaris* ) + AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, Needed to get declarations for msg_control and msg_controllen on Solaris) + AC_DEFINE(_XOPEN_SOURCE, 2, Needed to get declarations for msg_control and msg_controllen on Solaris) + AC_DEFINE(__EXTENSIONS__, 1, Needed to get declarations for msg_control and msg_controllen on Solaris) + ;; +esac + #### Checks for programs. #### # CC @@ -158,6 +168,9 @@ AC_CHECK_HEADERS([linux/input.h], [HAVE_EVDEV=1], [HAVE_EVDEV=0]) AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = "x1"]) +# Solaris +AC_CHECK_HEADERS([sys/filio.h]) + # Windows AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h]) diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index ccd3b6c31..23e84eb3e 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -32,6 +32,10 @@ #include #include +#ifdef HAVE_SYS_FILIO_H +#include +#endif + #include #include "rtp.h" @@ -74,7 +78,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { size_t k = n + chunk.length > size ? size - n : chunk.length; if (chunk.memblock) { - iov[iov_idx].iov_base = (uint8_t*) chunk.memblock->data + chunk.index; + iov[iov_idx].iov_base = (void*)((uint8_t*) chunk.memblock->data + chunk.index); iov[iov_idx].iov_len = k; mb[iov_idx] = chunk.memblock; iov_idx ++; @@ -96,7 +100,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { header[1] = htonl(c->timestamp); header[2] = htonl(c->ssrc); - iov[0].iov_base = header; + iov[0].iov_base = (void*)header; iov[0].iov_len = sizeof(header); m.msg_name = NULL; diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index 0c12322e9..d2bca04de 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -34,6 +34,10 @@ #include #include +#ifdef HAVE_SYS_FILIO_H +#include +#endif + #include #include #include From e4b2a47bb1de0f457559510837c46707ef9f6d8b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 18 Apr 2006 14:11:02 +0000 Subject: [PATCH 0650/1514] Clarify that JACK libs are optional. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@743 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4f9b88236..c37abfcd5 100644 --- a/configure.ac +++ b/configure.ac @@ -364,7 +364,7 @@ PKG_CHECK_MODULES(LIBOIL, [ liboil-0.3 >= 0.3.0 ]) AC_SUBST(LIBOIL_CFLAGS) AC_SUBST(LIBOIL_LIBS) -### JACK #### +### JACK (optional) #### PKG_CHECK_MODULES(JACK, [ jack >= 0.100 ], HAVE_JACK=1, HAVE_JACK=0) AC_SUBST(JACK_CFLAGS) From c22a0c12e49181d6ea042993e6b4b47db69574b1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 18 Apr 2006 15:16:24 +0000 Subject: [PATCH 0651/1514] Make the probe for RNG sources at runtime since the configure script isn't compatible with cross-compiling. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@744 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 20 ---------- src/daemon/main.c | 26 +------------ src/polypcore/random.c | 83 +++++++++++++++++++++++++++++++----------- src/polypcore/random.h | 1 + 4 files changed, 65 insertions(+), 65 deletions(-) diff --git a/configure.ac b/configure.ac index c37abfcd5..d6239f974 100644 --- a/configure.ac +++ b/configure.ac @@ -396,26 +396,6 @@ AC_SUBST(LIRC_CFLAGS) AC_SUBST(LIRC_LIBS) AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) -### /dev/random ### - -AC_MSG_CHECKING([whether a random device is available]) - -rnd="no" - -if test -e /dev/urandom ; then - rnd=/dev/urandom -else - if test -e /dev/random ; then - rnd=/dev/random - fi -fi - -if test "x$rnd" != "no" ; then - AC_DEFINE_UNQUOTED([RANDOM_DEVICE], ["$rnd"], [Random device]) -fi - -AC_MSG_RESULT([$rnd]) - ################################### # Output # ################################### diff --git a/src/daemon/main.c b/src/daemon/main.c index d783531a0..4ae9fbf1d 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -63,6 +63,7 @@ #include #include #include +#include #include "cmdline.h" #include "cpulimit.h" @@ -135,29 +136,6 @@ static void close_pipe(int p[2]) { p[0] = p[1] = -1; } -static void set_random_seed(void) { - unsigned int seed = 0; - -#ifdef RANDOM_DEVICE - int fd; - - if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) { - ssize_t r; - - if ((r = pa_loop_read(fd, &seed, sizeof(seed))) < 0 || (size_t) r != sizeof(seed)) { - pa_log_error(__FILE__": failed to read entropy from '"RANDOM_DEVICE"'"); - seed += (unsigned int) time(NULL); - } - - close(fd); - } -#else - seed = (unsigned int) time(NULL); -#endif - - srand(seed); -} - int main(int argc, char *argv[]) { pa_core *c; pa_strbuf *buf = NULL; @@ -203,7 +181,7 @@ int main(int argc, char *argv[]) { } #endif - set_random_seed(); + pa_random_seed(); pa_log_set_ident("polypaudio"); diff --git a/src/polypcore/random.c b/src/polypcore/random.c index ffd404741..ffe24994f 100644 --- a/src/polypcore/random.c +++ b/src/polypcore/random.c @@ -36,31 +36,72 @@ #include "random.h" -void pa_random(void *ret_data, size_t length) { - int fd; - ssize_t r = 0; +static int has_whined = 0; + +static const char *devices[] = { "/dev/urandom", "/dev/random", NULL }; + +static int pa_random_proper(void *ret_data, size_t length) { assert(ret_data && length); -#ifdef RANDOM_DEVICE - if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) { +#ifdef OS_IS_WIN32 - if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length) - pa_log_error(__FILE__": failed to read entropy from '%s'", RANDOM_DEVICE); + return -1; - close(fd); +#else /* OS_IS_WIN32 */ + + int fd, ret; + ssize_t r = 0; + const char **device; + + device = devices; + + while (*device) { + ret = 0; + + if ((fd = open(*device, O_RDONLY)) >= 0) { + + if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length) + ret = -1; + + close(fd); + } else + ret = -1; + + if (ret == 0) + break; } -#endif - if ((size_t) r != length) { - uint8_t *p; - size_t l; - -#ifdef RANDOM_DEVICE - pa_log_warn(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s" - ", falling back to unsecure pseudo RNG.\n", strerror(errno)); -#endif - - for (p = ret_data, l = length; l > 0; p++, l--) - *p = (uint8_t) rand(); - } + return ret; +#endif /* OS_IS_WIN32 */ +} + +void pa_random_seed() { + unsigned int seed; + + if (pa_random_proper(&seed, sizeof(unsigned int)) < 0) { + if (!has_whined) + pa_log_warn(__FILE__": failed to get proper entropy. Falling back to seeding with current time."); + has_whined = 1; + + seed = (unsigned int) time(NULL); + } + + srand(seed); +} + +void pa_random(void *ret_data, size_t length) { + uint8_t *p; + size_t l; + + assert(ret_data && length); + + if (pa_random_proper(ret_data, length) >= 0) + return; + + if (!has_whined) + pa_log_warn(__FILE__": failed to get proper entropy. Falling back to unsecure pseudo RNG."); + has_whined = 1; + + for (p = ret_data, l = length; l > 0; p++, l--) + *p = (uint8_t) rand(); } diff --git a/src/polypcore/random.h b/src/polypcore/random.h index bfb3df084..94a6d5056 100644 --- a/src/polypcore/random.h +++ b/src/polypcore/random.h @@ -22,6 +22,7 @@ USA. ***/ +void pa_random_seed(); void pa_random(void *ret_data, size_t length); #endif From f8dbc2f8f8155fcac20bf4aec703022c350a14bd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 15:40:36 +0000 Subject: [PATCH 0652/1514] * fix pa_random_seet() function prototype * drop pa_ prefix from pa_random_proper(), because it is a static function git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@745 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/random.c | 8 ++++---- src/polypcore/random.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/polypcore/random.c b/src/polypcore/random.c index ffe24994f..fe75a614f 100644 --- a/src/polypcore/random.c +++ b/src/polypcore/random.c @@ -40,7 +40,7 @@ static int has_whined = 0; static const char *devices[] = { "/dev/urandom", "/dev/random", NULL }; -static int pa_random_proper(void *ret_data, size_t length) { +static int random_proper(void *ret_data, size_t length) { assert(ret_data && length); #ifdef OS_IS_WIN32 @@ -75,10 +75,10 @@ static int pa_random_proper(void *ret_data, size_t length) { #endif /* OS_IS_WIN32 */ } -void pa_random_seed() { +void pa_random_seed(void) { unsigned int seed; - if (pa_random_proper(&seed, sizeof(unsigned int)) < 0) { + if (random_proper(&seed, sizeof(unsigned int)) < 0) { if (!has_whined) pa_log_warn(__FILE__": failed to get proper entropy. Falling back to seeding with current time."); has_whined = 1; @@ -95,7 +95,7 @@ void pa_random(void *ret_data, size_t length) { assert(ret_data && length); - if (pa_random_proper(ret_data, length) >= 0) + if (random_proper(ret_data, length) >= 0) return; if (!has_whined) diff --git a/src/polypcore/random.h b/src/polypcore/random.h index 94a6d5056..1f152dc73 100644 --- a/src/polypcore/random.h +++ b/src/polypcore/random.h @@ -22,7 +22,7 @@ USA. ***/ -void pa_random_seed(); +void pa_random_seed(void); void pa_random(void *ret_data, size_t length); #endif From 768a6f28e1345da1a0e8d51ae50455835ed8f677 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 16:33:17 +0000 Subject: [PATCH 0653/1514] fix code for pre-C99 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@746 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/random.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/polypcore/random.c b/src/polypcore/random.c index fe75a614f..1221206fd 100644 --- a/src/polypcore/random.c +++ b/src/polypcore/random.c @@ -41,9 +41,8 @@ static int has_whined = 0; static const char *devices[] = { "/dev/urandom", "/dev/random", NULL }; static int random_proper(void *ret_data, size_t length) { - assert(ret_data && length); - #ifdef OS_IS_WIN32 + assert(ret_data && length); return -1; @@ -53,6 +52,8 @@ static int random_proper(void *ret_data, size_t length) { ssize_t r = 0; const char **device; + assert(ret_data && length); + device = devices; while (*device) { From a80912917b348f6371fed4154cb6f2bcfe3ea384 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 17:19:41 +0000 Subject: [PATCH 0654/1514] build jack source git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@747 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index f6fc509bb..e02811b57 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -804,7 +804,8 @@ endif if HAVE_JACK modlib_LTLIBRARIES += \ - module-jack-sink.la + module-jack-sink.la \ + module-jack-source.la endif if OS_IS_WIN32 @@ -852,7 +853,9 @@ SYMDEF_FILES = \ modules/module-detect-symdef.h \ modules/rtp/module-rtp-send-symdef.h \ modules/rtp/module-rtp-recv-symdef.h \ - modules/module-jack-sink-symdef.h + modules/module-jack-sink-symdef.h \ + modules/module-jack-source-symdef.h + EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) @@ -1085,6 +1088,11 @@ module_jack_sink_la_LDFLAGS = -module -avoid-version module_jack_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(JACK_LIBS) module_jack_sink_la_CFLAGS = $(AM_LIBADD) libpolypcore.la $(JACK_CFLAGS) +module_jack_source_la_SOURCES = modules/module-jack-source.c +module_jack_source_la_LDFLAGS = -module -avoid-version +module_jack_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(JACK_LIBS) +module_jack_source_la_CFLAGS = $(AM_LIBADD) libpolypcore.la $(JACK_CFLAGS) + ################################### # Some minor stuff # ################################### From a5100be08335822c9ab87310e12d0d7f1dea870b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 17:20:05 +0000 Subject: [PATCH 0655/1514] fix connecting of jack source in jack daemon git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@748 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-jack-source.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index eef416f60..5f0e560d5 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -338,7 +338,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log_info(__FILE__": connecting %s to %s", jack_port_name(u->port[i]), *p); - if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) { + if (jack_connect(u->client, *p, jack_port_name(u->port[i]))) { pa_log(__FILE__": failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); break; } From c35052aa5a109013b8ed3326aaeede3bd5b2325e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 17:43:32 +0000 Subject: [PATCH 0656/1514] add JACK module documentation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@749 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/modules.html.in | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/doc/modules.html.in b/doc/modules.html.in index 54cec804e..3785912cf 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -401,6 +401,32 @@ module to create an RTP source.

    sap_address=The multicast group to join for SAP announcements, defaults to 224.0.0.56. +

    JACK Connectivity

    + +

    Polypaudio can be hooked up to a JACK Audio Connection Kit server which is a specialized sound server used for professional audio production on Unix/Linux. Both a +Polypaudio sink and a source are available. For each channel a port is +created in the JACK server.

    + +

    module-jack-sink

    + +

    This module implements a Polypaudio sink that connects to JACK and registers as many output ports as requested.

    + + + + + + + +
    sink_name=The name for the Polypaudio sink. If ommited defaults to jack_out.
    server_name=The JACK server to connect to. If ommited defaults to the default server.
    client_name=The client name to tell the JACK server. If ommited defaults to polypaudio.
    channels=Number of channels to register. If ommited defaults to the number of physical playback ports of the JACK server.
    connect=Takes a boolean value. If enabled (the default) Polypaudio will try to connect its ports to the physicial playback ports of the JACK server
    + +

    module-jack-source

    + +

    This module implements a Polypaudio source that connects to JACK +and registers as many input ports as requested. Takes the same +arguments as module-jack-sink, except for sink_name +which is replaced by source_name (with a default of jack_in) for obvious reasons.

    +

    Miscellaneous

    module-sine

    From e454bb1a47c303c119e77257b9c2f6e766416eb1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 17:52:37 +0000 Subject: [PATCH 0657/1514] Documentation updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@750 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 19 +++++++++++-------- doc/modules.html.in | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index 0e9b82610..5dec50563 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -130,29 +130,32 @@ available. A simple main loop implementation is available as well.

    The following modules are currently available:

      -
    • module-oss: driver for Open Sound System audio sinks and sources.
    • -
    • module-oss-mmap: same as above, but uses mmap() access to the audio buffer. Not as compatible
    • -
    • module-alsa-sink, module-alsa-source: drivers for ALSA sinks and sources
    • +
    • module-oss: driver for Open Sound System (OSS) audio sinks and sources.
    • +
    • module-oss-mmap: same as above, but uses mmap() access to the audio buffer. Not as compatible bot more accurate in latency calculations
    • +
    • module-alsa-sink, module-alsa-source: drivers for Advanced Linux +Sound Architecture (ALSA) sinks and sources
    • module-solaris: drivers for Solaris audio sinks and sources
    • module-waveout: drivers for Microsoft Windows audio sinks and sources
    • -
    • module-pipe-sink, module-pipe-source: demonstration module providing UNIX fifos backed sinks/sources
    • -
    • module-combine: combine multiple sinks into one.
    • +
    • module-pipe-sink, module-pipe-source: demonstration module providing UNIX FIFOs backed sinks/sources
    • +
    • module-combine: combine multiple sinks into one, adjusting the sample rate if the their clocks deviate.
    • module-sine: a sine generate sink input.
    • module-x11-bell: play a sample from the sample cache on every X11 bell event.
    • module-x11-publish: store Polypaudio credentials in the X11 root window.
    • -
    • module-esound-protocol-tcp, module-esound-protocol-unix: ESOUND compatibility modules (for TCP/IP resp. UNIX domain sockets)
    • +
    • module-esound-protocol-tcp, module-esound-protocol-unix: ESOUND compatibility modules (for TCP/IP resp. UNIX domain sockets)
    • module-native-protocol-tcp, module-native-protocol-unix: Native polypaudio protocol (for TCP/IP resp. UNIX domain sockets)
    • module-simple-protocol-tcp, module-simple-protocol-unix: Simplistic protocol for playback/capture for usage with tools like netcat (for TCP/IP resp. UNIX domain sockets)
    • module-cli-protocol-tcp, module-cli-protocol-unix, module-cli: Expose polypaudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
    • +
    • module-http-protocol-tcp: Spawns a small HTTP server which can be used to introspect the Polypaudio server with a web browser.
    • module-tunnel-sink, module-tunnel-source: make sinks/sources from other hosts available locally.
    • module-match: adjust volume automatically for newly created playback streams based on a regular expression matching table.
    • module-null-sink: a clocked sink similar to /dev/null.
    • -
    • module-esound-sink: a sink for forwarding audio data to an ESOUND server.
    • +
    • module-esound-sink: a sink for forwarding audio data to an ESOUND server.
    • module-detect: a module which automatically detects what sound hardware is available locally and which loads the required driver modules.
    • module-lirc: a module to control the volume of a sink with infrared remote controls supported by LIRC.
    • module-mmkbd-evdev: a module to control the volume of a sink with the special volume keys of a multimeda keyboard.
    • module-zeroconf-publish: a module to publish local sources/sinks using mDNS zeroconf.
    • -
    • module-rtp-send, module-rtp-recv: a module to implement RTP/SAP/SDP based audio streaming.
    • +
    • module-rtp-send, module-rtp-recv: modules to implement RTP/SAP/SDP based audio streaming.
    • +
    • module-jack-sink, module-jack-source: connect to a JACK Audio Connection Kit server. (A sound server for professional audio production)

    polypaudio is the successor of my previous, ill-fated diff --git a/doc/modules.html.in b/doc/modules.html.in index 3785912cf..f7b6298fa 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -158,7 +158,7 @@ buffer control is lost through this tunneling.

    module-esound-sink

    -

    Create a playback sink using an ESOUND server as backend. Whenever you can, try to omit this +

    Create a playback sink using an ESOUND server as backend. Whenever you can, try to omit this module since it has many disadvantages including bad latency and even worse latency measurement.

    From 65fd9b315b8c5ace2774d255b268187bf52b246d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 18:18:28 +0000 Subject: [PATCH 0658/1514] fix make distcheck git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@751 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doxygen/Makefile.am | 8 +++++++- src/Makefile.am | 6 ++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/doxygen/Makefile.am b/doxygen/Makefile.am index 79354b217..a68db5770 100644 --- a/doxygen/Makefile.am +++ b/doxygen/Makefile.am @@ -20,7 +20,13 @@ doxygen: doxygen.conf doxygen $< +distclean-local: + -rm -f doxygen.conf Makefile + +maintainerc-cleanlocal: + -rm -f Makefile.in + clean-local: - rm -rf html + -rm -rf html .PHONY: all doxygen diff --git a/src/Makefile.am b/src/Makefile.am index e02811b57..0705e1528 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -327,7 +327,6 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ polyp/cdecl.h \ polyp/channelmap.c polyp/channelmap.h \ polyp/client-conf.c polyp/client-conf.h \ - polyp/llist.h \ polyp/mainloop-api.c polyp/mainloop-api.h \ polyp/polypaudio.h \ polyp/context.c polyp/context.h \ @@ -374,7 +373,8 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ polypcore/tagstruct.c polypcore/tagstruct.h \ polypcore/util.c polypcore/util.h \ polypcore/winsock.h \ - polypcore/xmalloc.c polypcore/xmalloc.h + polypcore/xmalloc.c polypcore/xmalloc.h \ + polypcore/llist.h if OS_IS_WIN32 libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ @@ -1101,6 +1101,8 @@ suid: polypaudio chown root $< chmod u+s $< +CLEANFILES=esdcompat.sh client.conf default.pa daemon.conf + esdcompat.sh: daemon/esdcompat.sh.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ From 9ad753ed1f4114f2f1e1fa308958f3ff7815b70a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 18:44:44 +0000 Subject: [PATCH 0659/1514] fix "make distccheck" properly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@752 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- doxygen/Makefile.am | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Makefile.am b/Makefile.am index d8032baa5..8d34ca89d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # USA. EXTRA_DIST = bootstrap.sh LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4 -SUBDIRS=libltdl src doc +SUBDIRS=libltdl src doc doxygen MAINTAINERCLEANFILES = noinst_DATA = diff --git a/doxygen/Makefile.am b/doxygen/Makefile.am index a68db5770..8feec7339 100644 --- a/doxygen/Makefile.am +++ b/doxygen/Makefile.am @@ -20,12 +20,6 @@ doxygen: doxygen.conf doxygen $< -distclean-local: - -rm -f doxygen.conf Makefile - -maintainerc-cleanlocal: - -rm -f Makefile.in - clean-local: -rm -rf html From 60008cb1154696a875e69b7bcb739bc9f85ed378 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 19:12:53 +0000 Subject: [PATCH 0660/1514] fix CFLAGS for jack modules git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@753 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 0705e1528..b646cff78 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1086,12 +1086,12 @@ module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) module_jack_sink_la_SOURCES = modules/module-jack-sink.c module_jack_sink_la_LDFLAGS = -module -avoid-version module_jack_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(JACK_LIBS) -module_jack_sink_la_CFLAGS = $(AM_LIBADD) libpolypcore.la $(JACK_CFLAGS) +module_jack_sink_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS) module_jack_source_la_SOURCES = modules/module-jack-source.c module_jack_source_la_LDFLAGS = -module -avoid-version module_jack_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(JACK_LIBS) -module_jack_source_la_CFLAGS = $(AM_LIBADD) libpolypcore.la $(JACK_CFLAGS) +module_jack_source_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS) ################################### # Some minor stuff # From 746adcfed5dc396bc4820724b2e951369fc63aeb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 19:31:50 +0000 Subject: [PATCH 0661/1514] fix a couple of issues I found when compiling polypaudio with gcc 2.95 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@754 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 4 ++-- src/modules/module-detect.c | 2 +- src/modules/module-jack-sink.c | 1 + src/modules/module-oss.c | 3 ++- src/modules/module-tunnel.c | 2 +- src/modules/rtp/module-rtp-recv.c | 2 +- src/polyp/browser.c | 2 +- src/polyp/context.c | 2 +- src/polyp/def.h | 2 +- src/polyp/stream.c | 2 +- src/polypcore/socket-client.c | 2 +- src/polypcore/source.c | 2 +- src/utils/pacmd.c | 2 +- 13 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 2f9be07a7..dcc0e0203 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -51,7 +51,7 @@ struct pa_alsa_fdlist { void *userdata; }; -static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) { +static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void *userdata) { struct pa_alsa_fdlist *fdl = (struct pa_alsa_fdlist*)userdata; int err, i; unsigned short revents; @@ -102,7 +102,7 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t a->defer_enable(fdl->defer, 1); } -static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) { +static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *userdata) { struct pa_alsa_fdlist *fdl = (struct pa_alsa_fdlist*)userdata; int num_fds, i, err; struct pollfd *temp; diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 6b2e27421..9cc13e817 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -259,7 +259,7 @@ fail: } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(PA_GCC_UNUSED pa_core *c, PA_GCC_UNUSED pa_module*m) { /* NOP */ } diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 4f7a66eb5..f340ab6d2 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -112,6 +112,7 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_ char x; assert(m); + assert(e); assert(flags == PA_IO_EVENT_INPUT); assert(u); assert(u->pipe_fds[0] == fd); diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index d9980d82d..ccc3c7d98 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -461,8 +461,9 @@ int pa__init(pa_core *c, pa_module*m) { * Without this snippet, poll will never register the fd as ready. */ if (u->source) { - char buf[u->sample_size]; + char *buf = pa_xnew(char, u->sample_size); read(u->fd, buf, u->sample_size); + pa_xfree(buf); } /* Read mixer settings */ diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 70cc950cc..b68bc485f 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -603,7 +603,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void } #ifndef TUNNEL_SINK -static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, PA_GCC_UNUSED int64_t offset, PA_GCC_UNUSED pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { struct userdata *u = userdata; assert(p && chunk && u); diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index a714e1625..cd5f10e66 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -477,7 +477,7 @@ fail: return -1; } -static void free_func(void *p, void *userdata) { +static void free_func(void *p, PA_GCC_UNUSED void *userdata) { session_free(p, 0); } diff --git a/src/polyp/browser.c b/src/polyp/browser.c index de5c751a3..cef680e40 100644 --- a/src/polyp/browser.c +++ b/src/polyp/browser.c @@ -43,7 +43,7 @@ struct pa_browser { pa_io_event *io_event; }; -static void io_callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t events, void *userdata) { +static void io_callback(pa_mainloop_api*a, PA_GCC_UNUSED pa_io_event*e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void *userdata) { pa_browser *b = userdata; assert(a && b && b->mainloop == a); diff --git a/src/polyp/context.c b/src/polyp/context.c index 047b739f7..448e2e68b 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -955,7 +955,7 @@ const char* pa_context_get_server(pa_context *c) { return c->server; } -uint32_t pa_context_get_protocol_version(pa_context *c) { +uint32_t pa_context_get_protocol_version(PA_GCC_UNUSED pa_context *c) { return PA_PROTOCOL_VERSION; } diff --git a/src/polyp/def.h b/src/polyp/def.h index 80e3092b4..517dd4226 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -288,7 +288,7 @@ typedef enum pa_seek_mode { PA_SEEK_RELATIVE = 0, /**< Seek relatively to the write index */ PA_SEEK_ABSOLUTE = 1, /**< Seek relatively to the start of the buffer queue */ PA_SEEK_RELATIVE_ON_READ = 2, /**< Seek relatively to the read index. */ - PA_SEEK_RELATIVE_END = 3, /**< Seek relatively to the current end of the buffer queue. */ + PA_SEEK_RELATIVE_END = 3 /**< Seek relatively to the current end of the buffer queue. */ } pa_seek_mode_t; /** Special sink flags. \since 0.8 */ diff --git a/src/polyp/stream.c b/src/polyp/stream.c index ce2470f6f..e400415c7 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -360,7 +360,7 @@ static void invalidate_indexes(pa_stream *s, int r, int w) { request_auto_timing_update(s, 1); } -static void auto_timing_update_callback(pa_mainloop_api *m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { +static void auto_timing_update_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { pa_stream *s = userdata; /* pa_log("time event"); */ diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index 1ee19a599..7c4f4d6be 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -371,7 +371,7 @@ static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED goto finish; fail: - errno == EHOSTUNREACH; + errno = EHOSTUNREACH; do_call(c); finish: diff --git a/src/polypcore/source.c b/src/polypcore/source.c index 9e9415b63..3a78825bb 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -170,7 +170,7 @@ void pa_source_notify(pa_source*s) { s->notify(s); } -static int do_post(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void*userdata) { +static int do_post(void *p, PA_GCC_UNUSED uint32_t idx, PA_GCC_UNUSED int *del, void*userdata) { pa_source_output *o = p; const pa_memchunk *chunk = userdata; diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index a71e0e934..e640ddaf0 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -36,7 +36,7 @@ #include #include -int main(PA_GCC_UNUSED int main, PA_GCC_UNUSED char*argv[]) { +int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { pid_t pid ; int fd = -1; int ret = 1, i; From 494f60207404dc3d155047fab3e3cc1d4870f4f5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Apr 2006 19:44:50 +0000 Subject: [PATCH 0662/1514] make proper use of the muting facility of sinks in module-mmkbd-evdev git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@755 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-mmkbd-evdev.c | 44 +++++++++++++++++--------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index 79194ad8b..8ea568110 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -72,7 +72,6 @@ struct userdata { pa_io_event *io; char *sink_name; pa_module *module; - float mute_toggle_save; }; static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) { @@ -110,37 +109,42 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) pa_log(__FILE__": failed to get sink '%s'", u->sink_name); else { - pa_volume_t v = pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE)); - pa_cvolume cv; + int i; + pa_cvolume cv = *pa_sink_get_volume(s, PA_MIXER_HARDWARE); + #define DELTA (PA_VOLUME_NORM/20) switch (volchange) { case UP: - v += DELTA; + for (i = 0; i < cv.channels; i++) { + cv.values[i] += DELTA; + + if (cv.values[i] > PA_VOLUME_NORM) + cv.values[i] = PA_VOLUME_NORM; + } + + pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); break; case DOWN: - if (v > DELTA) - v -= DELTA; - else - v = PA_VOLUME_MUTED; + for (i = 0; i < cv.channels; i++) { + if (cv.values[i] >= DELTA) + cv.values[i] -= DELTA; + else + cv.values[i] = PA_VOLUME_MUTED; + } + pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); break; - case MUTE_TOGGLE: { + case MUTE_TOGGLE: - if (v > 0) { - u->mute_toggle_save = v; - v = PA_VOLUME_MUTED; - } else - v = u->mute_toggle_save; - } - default: + pa_sink_set_mute(s, PA_MIXER_HARDWARE, !pa_sink_get_mute(s, PA_MIXER_HARDWARE)); + break; + + case INVALID: ; } - - pa_cvolume_set(&cv, PA_CHANNELS_MAX, v); - pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); } } } @@ -176,7 +180,6 @@ int pa__init(pa_core *c, pa_module*m) { u->io = NULL; u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); u->fd = -1; - u->mute_toggle_save = 0; if ((u->fd = open(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY)) < 0) { pa_log(__FILE__": failed to open evdev device: %s", strerror(errno)); @@ -198,6 +201,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log_info(__FILE__": evdev vendor 0x%04hx product 0x%04hx version 0x%04hx bustype %u", input_id.vendor, input_id.product, input_id.version, input_id.bustype); + memset(name, 0, sizeof(name)); if(ioctl(u->fd, EVIOCGNAME(sizeof(name)), name) < 0) { pa_log(__FILE__": EVIOCGNAME failed: %s", strerror(errno)); goto fail; From 4bb58226189763b87abc5b5e0f297dd04f751d89 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 19 Apr 2006 07:31:11 +0000 Subject: [PATCH 0663/1514] Reverse order of IPv6/IPv4 binding to handle systems without IPV6_V6ONLY. System that always do IPV6_V6ONLY will now still bind to both sockets, just in another order. System that never do IPV6_V6ONLY will now fail to bind IPv4 instead of IPv6. But since they force IPv6 sockets to accept IPv4 connections, everything is peachy anyway. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@756 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-protocol-stub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 2f022b992..0ffd81df5 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -211,14 +211,14 @@ int pa__init(pa_core *c, pa_module*m) { listen_on = pa_modargs_get_value(ma, "listen", NULL); if (listen_on) { - s_ipv4 = pa_socket_server_new_ipv4_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); s_ipv6 = pa_socket_server_new_ipv6_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); + s_ipv4 = pa_socket_server_new_ipv4_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); } else if (loopback) { - s_ipv4 = pa_socket_server_new_ipv4_loopback(c->mainloop, port, TCPWRAP_SERVICE); s_ipv6 = pa_socket_server_new_ipv6_loopback(c->mainloop, port, TCPWRAP_SERVICE); + s_ipv4 = pa_socket_server_new_ipv4_loopback(c->mainloop, port, TCPWRAP_SERVICE); } else { - s_ipv4 = pa_socket_server_new_ipv4_any(c->mainloop, port, TCPWRAP_SERVICE); s_ipv6 = pa_socket_server_new_ipv6_any(c->mainloop, port, TCPWRAP_SERVICE); + s_ipv4 = pa_socket_server_new_ipv4_any(c->mainloop, port, TCPWRAP_SERVICE); } if (!s_ipv4 && !s_ipv6) From 6ae8511a66c0f937bdab2786ecdc7e158bd3934d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 19 Apr 2006 11:53:24 +0000 Subject: [PATCH 0664/1514] Having constant deferred events isn't allowed and causes problems. Use timers instead. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@757 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 16 +++++++++++----- src/polyp/mainloop-signal.c | 24 ++++++++++++++++-------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 4ae9fbf1d..e14837a99 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -79,8 +79,9 @@ int deny_severity = LOG_WARNING; #ifdef OS_IS_WIN32 -static void message_cb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { +static void message_cb(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { MSG msg; + struct timeval tvnext; while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) @@ -90,6 +91,9 @@ static void message_cb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { DispatchMessage(&msg); } } + + pa_timeval_add(pa_gettimeofday(&tvnext), 100000); + a->time_restart(e, &tvnext); } #endif @@ -153,7 +157,8 @@ int main(int argc, char *argv[]) { #endif #ifdef OS_IS_WIN32 - pa_defer_event *defer; + pa_time_event *timer; + struct timeval tv; #endif pa_limit_caps(); @@ -386,8 +391,9 @@ int main(int argc, char *argv[]) { #endif #ifdef OS_IS_WIN32 - defer = pa_mainloop_get_api(mainloop)->defer_new(pa_mainloop_get_api(mainloop), message_cb, NULL); - assert(defer); + timer = pa_mainloop_get_api(mainloop)->time_new( + pa_mainloop_get_api(mainloop), pa_gettimeofday(&tv), message_cb, NULL); + assert(timer); #endif if (conf->daemonize) @@ -446,7 +452,7 @@ int main(int argc, char *argv[]) { } #ifdef OS_IS_WIN32 - pa_mainloop_get_api(mainloop)->defer_free(defer); + pa_mainloop_get_api(mainloop)->time_free(timer); #endif pa_core_free(c); diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index 0b33c44bc..73de00025 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -59,7 +59,7 @@ struct pa_signal_event { static pa_mainloop_api *api = NULL; static int signal_pipe[2] = { -1, -1 }; static pa_io_event* io_event = NULL; -static pa_defer_event *defer_event = NULL; +static pa_time_event *time_event = NULL; static pa_signal_event *signals = NULL; #ifdef OS_IS_WIN32 @@ -92,10 +92,11 @@ static void dispatch(pa_mainloop_api*a, int sig) { } #ifdef OS_IS_WIN32 -static void defer(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event*e, PA_GCC_UNUSED void *userdata) { +static void timer(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, PA_GCC_UNUSED void *userdata) { ssize_t r; int sig; unsigned int sigs; + struct timeval tvnext; EnterCriticalSection(&crit); sigs = waiting_signals; @@ -117,6 +118,9 @@ static void defer(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event*e, PA_GCC_UNUS sigs--; } + + pa_timeval_add(pa_gettimeofday(&tvnext), 100000); + a->time_restart(e, &tvnext); } #endif @@ -143,7 +147,11 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags } int pa_signal_init(pa_mainloop_api *a) { - assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event && !defer_event); +#ifdef OS_IS_WIN32 + struct timeval tv; +#endif + + assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event && !time_event); #ifdef OS_IS_WIN32 if (_pipe(signal_pipe, 200, _O_BINARY) < 0) { @@ -165,8 +173,8 @@ int pa_signal_init(pa_mainloop_api *a) { io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL); assert(io_event); #else - defer_event = api->defer_new(api, defer, NULL); - assert(defer_event); + time_event = api->time_new(api, pa_gettimeofday(&tv), timer, NULL); + assert(time_event); InitializeCriticalSection(&crit); #endif @@ -175,7 +183,7 @@ int pa_signal_init(pa_mainloop_api *a) { } void pa_signal_done(void) { - assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && (io_event || defer_event)); + assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && (io_event || time_event)); while (signals) pa_signal_free(signals); @@ -184,8 +192,8 @@ void pa_signal_done(void) { api->io_free(io_event); io_event = NULL; #else - api->defer_free(defer_event); - defer_event = NULL; + api->time_free(time_event); + time_event = NULL; DeleteCriticalSection(&crit); #endif From 5342f3aef17f857dac1f6a4dd2329a301a568f1e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 19 Apr 2006 11:54:43 +0000 Subject: [PATCH 0665/1514] Win32 needs to have the socket subsystem initialised. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@758 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/polyp/context.c b/src/polyp/context.c index 448e2e68b..ff224547b 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -141,6 +141,13 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { pa_client_conf_from_x11(c->conf, NULL); #endif pa_client_conf_env(c->conf); + +#ifdef OS_IS_WIN32 + { + WSADATA data; + WSAStartup(MAKEWORD(2, 0), &data); + } +#endif return c; } @@ -180,6 +187,10 @@ static void context_free(pa_context *c) { pa_xfree(c->name); pa_xfree(c->server); pa_xfree(c); + +#ifdef OS_IS_WIN32 + WSACleanup(); +#endif } pa_context* pa_context_ref(pa_context *c) { From e1513ce68448aea2c1b21e782151a8be8f17f8e1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 19 Apr 2006 11:55:46 +0000 Subject: [PATCH 0666/1514] WaveOut needs to have rather large chunks. This is about as low as we can go without getting underflows. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@759 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 45ed10b97..ef602e8d5 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -113,6 +113,9 @@ static void do_write(struct userdata *u) LeaveCriticalSection(&u->crit); + if (free_frags == u->fragments) + pa_log_debug(__FILE__": WaveOut underflow!"); + while (free_frags) { hdr = &u->ohdrs[u->cur_ohdr]; if (hdr->dwFlags & WHDR_PREPARED) @@ -194,6 +197,9 @@ static void do_read(struct userdata *u) LeaveCriticalSection(&u->crit); + if (free_frags == u->fragments) + pa_log_debug(__FILE__": WaveIn overflow!"); + while (free_frags) { hdr = &u->ihdrs[u->cur_ihdr]; if (hdr->dwFlags & WHDR_PREPARED) @@ -443,8 +449,8 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - nfrags = 20; - frag_size = 1024; + nfrags = 5; + frag_size = 8192; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { pa_log(__FILE__": failed to parse fragments arguments"); goto fail; @@ -516,7 +522,7 @@ int pa__init(pa_core *c, pa_module*m) { u->oremain = u->fragment_size; - u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 3, &ss); + u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 10, &ss); pa_gettimeofday(&tv); pa_timeval_add(&tv, u->poll_timeout); From 1d512470be3d6b87ccb817e0d71aead0d98f497e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 19 Apr 2006 11:56:26 +0000 Subject: [PATCH 0667/1514] Minor fixes for the way Windows handles sockets. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@760 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/socket-client.c | 15 +++++++++++---- src/polypcore/winsock.h | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index 7c4f4d6be..734b9dde5 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -151,7 +151,7 @@ static void do_call(pa_socket_client *c) { errno = error; goto finish; } - + io = pa_iochannel_new(c->mainloop, c->fd, c->fd); assert(io); @@ -187,8 +187,13 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t pa_make_nonblock_fd(c->fd); if ((r = connect(c->fd, sa, len)) < 0) { +#ifdef OS_IS_WIN32 + if (WSAGetLastError() != EWOULDBLOCK) { + pa_log_debug(__FILE__": connect(): %d", WSAGetLastError()); +#else if (errno != EINPROGRESS) { - /*pa_log(__FILE__": connect(): %s", strerror(errno));*/ + pa_log_debug(__FILE__": connect(): %s (%d)", strerror(errno), errno); +#endif return -1; } @@ -473,9 +478,11 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam struct hostent *host = NULL; struct sockaddr_in s; - /* FIXME: PF_INET6 support */ - if (hints.ai_family != PF_INET) + /* FIXME: PF_INET6 support */ + if (hints.ai_family == PF_INET6) { + pa_log_error(__FILE__": IPv6 is not supported on Windows"); goto finish; + } host = gethostbyname(a.path_or_host); if (!host) { diff --git a/src/polypcore/winsock.h b/src/polypcore/winsock.h index b1e0f7d44..ae868b384 100644 --- a/src/polypcore/winsock.h +++ b/src/polypcore/winsock.h @@ -13,6 +13,7 @@ #define ETIMEDOUT WSAETIMEDOUT #define ECONNREFUSED WSAECONNREFUSED #define EHOSTUNREACH WSAEHOSTUNREACH +#define EWOULDBLOCK WSAEWOULDBLOCK #endif From 989fa585b267fbd7b7e40f4dd6e4caf34708910c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 19 Apr 2006 14:30:42 +0000 Subject: [PATCH 0668/1514] Sun's documentation about SIGPOLL on EOF:s is wrong, so use a timer based solution instead. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@761 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 48 +++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 9f93f9d88..a2034f3e7 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -64,6 +64,8 @@ struct userdata { pa_source *source; pa_iochannel *io; pa_core *core; + pa_time_event *timer; + pa_usec_t poll_timeout; pa_signal_event *sig; pa_memchunk memchunk, silence; @@ -111,7 +113,8 @@ static void do_write(struct userdata *u) { assert(u); - if (!u->sink || !pa_iochannel_is_writable(u->io)) + /* We cannot check pa_iochannel_is_writable() because of our buffer hack */ + if (!u->sink) return; update_usage(u); @@ -126,12 +129,8 @@ static void do_write(struct userdata *u) { len = u->buffer_size; len -= u->written_bytes - (info.play.samples * u->sample_size); - /* - * Do not fill more than half the buffer in one chunk since we only - * get notifications upon completion of entire chunks. - */ - if (len > (u->buffer_size / 2)) - len = u->buffer_size / 2; + if (len == u->buffer_size) + pa_log_debug(__FILE__": Solaris buffer underflow!"); if (len < u->sample_size) return; @@ -167,14 +166,6 @@ static void do_write(struct userdata *u) { } u->written_bytes += r; - - /* - * Write 0 bytes which will generate a SIGPOLL when "played". - */ - if (write(u->fd, NULL, 0) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); - return; - } } static void do_read(struct userdata *u) { @@ -217,14 +208,26 @@ static void io_callback(pa_iochannel *io, void*userdata) { do_read(u); } +static void timer_cb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + struct timeval ntv; + + assert(u); + + do_write(u); + + pa_gettimeofday(&ntv); + pa_timeval_add(&ntv, u->poll_timeout); + + a->time_restart(e, &ntv); +} + static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { struct userdata *u = userdata; pa_cvolume old_vol; assert(u); - do_write(u); - if (u->sink) { assert(u->sink->get_hw_volume); memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)); @@ -475,6 +478,7 @@ int pa__init(pa_core *c, pa_module*m) { int record = 1, playback = 1; pa_sample_spec ss; pa_modargs *ma = NULL; + struct timeval tv; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -570,6 +574,14 @@ int pa__init(pa_core *c, pa_module*m) { u->module = m; m->userdata = u; + u->poll_timeout = pa_bytes_to_usec(u->buffer_size / 10, &ss); + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, u->poll_timeout); + + u->timer = c->mainloop->time_new(c->mainloop, &tv, timer_cb, u); + assert(u->timer); + u->sig = pa_signal_new(SIGPOLL, sig_callback, u); assert(u->sig); ioctl(u->fd, I_SETSIG, S_MSG); @@ -603,6 +615,8 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; + if (u->timer) + c->mainloop->time_free(u->timer); ioctl(u->fd, I_SETSIG, 0); pa_signal_free(u->sig); From e4b53b2badbd3679df6154e6d6687fcc2aa57885 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 19 Apr 2006 15:37:52 +0000 Subject: [PATCH 0669/1514] Tweaks for the solaris module. The sound system requires complete frames to be written. Also, the sample counter can magically go backwards sometimes, causing havoc with our buffer handling. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@762 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index a2034f3e7..e1a03272a 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -70,7 +70,7 @@ struct userdata { pa_memchunk memchunk, silence; - uint32_t sample_size; + uint32_t frame_size; uint32_t buffer_size; unsigned int written_bytes, read_bytes; @@ -127,12 +127,18 @@ static void do_write(struct userdata *u) { * by not filling it more than u->buffer_size. */ len = u->buffer_size; - len -= u->written_bytes - (info.play.samples * u->sample_size); + len -= u->written_bytes - (info.play.samples * u->frame_size); + + /* The sample counter can sometimes go backwards :( */ + if (len > u->buffer_size) + len = 0; if (len == u->buffer_size) pa_log_debug(__FILE__": Solaris buffer underflow!"); - if (len < u->sample_size) + len -= len % u->frame_size; + + if (len == 0) return; memchunk = &u->memchunk; @@ -145,17 +151,20 @@ static void do_write(struct userdata *u) { assert(memchunk->memblock->data); assert(memchunk->length); - if (memchunk->length < len) + if (memchunk->length < len) { len = memchunk->length; - + len -= len % u->frame_size; + assert(len); + } + if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { pa_log(__FILE__": write() failed: %s", strerror(errno)); return; } + + assert(r % u->frame_size == 0); - if (memchunk == &u->silence) - assert(r % u->sample_size == 0); - else { + if (memchunk != &u->silence) { u->memchunk.index += r; u->memchunk.length -= r; @@ -264,7 +273,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { assert(err >= 0); r += pa_bytes_to_usec(u->written_bytes, &s->sample_spec); - r -= pa_bytes_to_usec(info.play.samples * u->sample_size, &s->sample_spec); + r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &s->sample_spec); if (u->memchunk.memblock) r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); @@ -282,7 +291,7 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { err = ioctl(u->fd, AUDIO_GETINFO, &info); assert(err >= 0); - r += pa_bytes_to_usec(info.record.samples * u->sample_size, &s->sample_spec); + r += pa_bytes_to_usec(info.record.samples * u->frame_size, &s->sample_spec); r -= pa_bytes_to_usec(u->read_bytes, &s->sample_spec); return r; @@ -560,7 +569,7 @@ int pa__init(pa_core *c, pa_module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; - u->sample_size = pa_frame_size(&ss); + u->frame_size = pa_frame_size(&ss); u->buffer_size = buffer_size; u->silence.memblock = pa_memblock_new(u->silence.length = CHUNK_SIZE, u->core->memblock_stat); From 1b4609774e51037c4f4ccbd591cccb9a9540b476 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Apr 2006 07:44:47 +0000 Subject: [PATCH 0670/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@763 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/todo b/doc/todo index e7ba47c88..bd8145fbb 100644 --- a/doc/todo +++ b/doc/todo @@ -12,6 +12,8 @@ Post 0.8: - use scatter/gather io for sockets - add a synchronous API (base it on xmms-polyp) - rtp module ported to Win32 (sendmsg/recvmsg emulation) +- CODECs to reduce bandwidth usage (plug-in based) +- Remove symdef files and use macros (like most other projects) Long term: - pass meta info for hearing impaired From 2decb6a5d31bf2338394b0288be4c3204f1703ee Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Apr 2006 12:33:00 +0000 Subject: [PATCH 0671/1514] * rename "LICENSE" to "LGPL" * add GPL text * update LGPL text in regards to FSF addresses git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@764 fefdeb5f-60dc-0310-8127-8f9354f1896f --- GPL | 340 ++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE => LGPL | 4 +- 2 files changed, 342 insertions(+), 2 deletions(-) create mode 100644 GPL rename LICENSE => LGPL (99%) diff --git a/GPL b/GPL new file mode 100644 index 000000000..b7b5f53df --- /dev/null +++ b/GPL @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/LICENSE b/LGPL similarity index 99% rename from LICENSE rename to LGPL index b124cf581..2d2d780e6 100644 --- a/LICENSE +++ b/LGPL @@ -3,7 +3,7 @@ Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -490,7 +490,7 @@ notice is found. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. From 81381c4ee71b12d9022e6cbf83f63a95b704c32d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Apr 2006 12:40:10 +0000 Subject: [PATCH 0672/1514] add new explaining LICENSE file git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@765 fefdeb5f-60dc-0310-8127-8f9354f1896f --- LICENSE | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..a4990f690 --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +All Polypaudio sources are licensed under the GNU Lesser General Public +License. (see file LGPL for details) + +However, the server side links to the GPL-only library 'libsamplerate' which +downgrades the license of the server part to GPL (see file GPL for details), +exercising section 3 of the LGPL. + +Hence you should treat the client library ('libpolyp') of Polypaudio as being +LGPL licensed and the server part ('libpolypcore') as being GPL licensed. + +-- Lennart Poettering, April 20th, 2006. From 9c06f5a9599f6967499f79e0cc1f868d8d6e53c0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Apr 2006 12:40:54 +0000 Subject: [PATCH 0673/1514] ship GPL and LGPL files with the tarball git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@766 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 8d34ca89d..be0f70164 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,7 +17,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4 +EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4 SUBDIRS=libltdl src doc doxygen MAINTAINERCLEANFILES = From 5f804cb34c32b6e8209cff8a6627523b6cd148c0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Apr 2006 12:45:52 +0000 Subject: [PATCH 0674/1514] minor improvements to the LICENSE text git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@767 fefdeb5f-60dc-0310-8127-8f9354f1896f --- LICENSE | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/LICENSE b/LICENSE index a4990f690..0ef095127 100644 --- a/LICENSE +++ b/LICENSE @@ -1,11 +1,13 @@ -All Polypaudio sources are licensed under the GNU Lesser General Public +All Polypaudio source files are licensed under the GNU Lesser General Public License. (see file LGPL for details) However, the server side links to the GPL-only library 'libsamplerate' which -downgrades the license of the server part to GPL (see file GPL for details), -exercising section 3 of the LGPL. +practically downgrades the license of the server part to GPL (see file GPL for +details), exercising section 3 of the LGPL. Hence you should treat the client library ('libpolyp') of Polypaudio as being -LGPL licensed and the server part ('libpolypcore') as being GPL licensed. +LGPL licensed and the server part ('libpolypcore') as being GPL licensed. Since +the Polypaudio daemon and the modules link to 'libpolypcore' they are of course +also GPL licensed. -- Lennart Poettering, April 20th, 2006. From a7c5ed19948915a1930ea19ae2c11b5486542cb0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Apr 2006 12:53:49 +0000 Subject: [PATCH 0675/1514] replace copy by symlink when installing homepage git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@768 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index be0f70164..c7ea54f35 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,7 +53,7 @@ homepage: all dist doxygen cp polypaudio-@PACKAGE_VERSION@.tar.gz $$HOME/homepage/private/projects/polypaudio cp doc/README.html doc/FAQ.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/polypaudio cp -a doxygen/html/* $$HOME/homepage/private/projects/polypaudio/doxygen - cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html + ln -sf $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html #distcleancheck: # @: From 0cc2e04157bd4fc6838b3690bd6387fcb3ee4587 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 14:31:47 +0000 Subject: [PATCH 0676/1514] chown() and chmod() /tmp/.esd/ before checking if everything is ok with it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@770 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/util.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/polypcore/util.c b/src/polypcore/util.c index b37a25a34..8418a6924 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -140,13 +140,16 @@ int pa_make_secure_dir(const char* dir) { if (errno != EEXIST) return -1; + chown(dir, getuid(), getgid()); + chmod(dir, 0700); + #ifdef HAVE_LSTAT if (lstat(dir, &st) < 0) #else if (stat(dir, &st) < 0) #endif goto fail; - + #ifndef OS_IS_WIN32 if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700)) goto fail; From b0059c679d1beb3ee2d45b689d3d52d051ad795d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 20:04:06 +0000 Subject: [PATCH 0677/1514] try to remove the directory where the PID file resides in after removing the PID file git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@771 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/pid.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/polypcore/pid.c b/src/polypcore/pid.c index 374b55063..b258290b5 100644 --- a/src/polypcore/pid.c +++ b/src/polypcore/pid.c @@ -41,6 +41,7 @@ #include #include +#include #include "pid.h" @@ -191,6 +192,7 @@ int pa_pid_file_remove(void) { char fn[PATH_MAX]; int ret = -1; pid_t pid; + char *p; pa_runtime_path("pid", fn, sizeof(fn)); @@ -223,6 +225,11 @@ int pa_pid_file_remove(void) { goto fail; } + if ((p = pa_parent_dir(fn))) { + rmdir(p); + pa_xfree(p); + } + ret = 0; fail: From 513df3b9f8af35d11bbdc44d0dcbc9ab35fd1465 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 20:04:25 +0000 Subject: [PATCH 0678/1514] first unlink the socket, the close it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@772 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/socket-server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index b27816d43..f7e0b6477 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -379,13 +379,14 @@ pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const cha static void socket_server_free(pa_socket_server*s) { assert(s); - close(s->fd); if (s->filename) { unlink(s->filename); pa_xfree(s->filename); } + close(s->fd); + pa_xfree(s->tcpwrap_service); s->mainloop->io_free(s->io_event); @@ -406,7 +407,6 @@ void pa_socket_server_set_callback(pa_socket_server*s, void (*on_connection)(pa_ s->userdata = userdata; } - char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { assert(s && c && l > 0); From a4fedcf2dc67a946354ea003424deb3c2489f7fc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 20:05:01 +0000 Subject: [PATCH 0679/1514] add new function pa_parent_dir() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@773 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/util.c | 19 ++++++++++++++----- src/polypcore/util.h | 2 ++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/polypcore/util.c b/src/polypcore/util.c index 8418a6924..615ea881a 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -164,15 +164,25 @@ fail: return -1; } -/* Creates a the parent directory of the specified path securely */ -int pa_make_secure_parent_dir(const char *fn) { - int ret = -1; +/* Return a newly allocated sting containing the parent directory of the specified file */ +char *pa_parent_dir(const char *fn) { char *slash, *dir = pa_xstrdup(fn); slash = (char*) pa_path_get_filename(dir); if (slash == fn) - goto finish; + return NULL; + *(slash-1) = 0; + return dir; +} + +/* Creates a the parent directory of the specified path securely */ +int pa_make_secure_parent_dir(const char *fn) { + int ret = -1; + char *dir; + + if (!(dir = pa_parent_dir(fn))) + goto finish; if (pa_make_secure_dir(dir) < 0) goto finish; @@ -184,7 +194,6 @@ finish: return ret; } - /** Calls read() in a loop. Makes sure that as much as 'size' bytes, * unless EOF is reached or an error occured */ ssize_t pa_loop_read(int fd, void*data, size_t size) { diff --git a/src/polypcore/util.h b/src/polypcore/util.h index f05339c46..ca81b2298 100644 --- a/src/polypcore/util.h +++ b/src/polypcore/util.h @@ -55,6 +55,8 @@ char *pa_get_home_dir(char *s, size_t l); const char *pa_path_get_filename(const char *p); +char *pa_parent_dir(const char *fn); + struct timeval *pa_gettimeofday(struct timeval *tv); pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); From 0e02e844a283cbffe373e702668b88174631fb6e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 20:06:48 +0000 Subject: [PATCH 0680/1514] * for unix sockets: remove the right parent directory on shutdown * other cleanups git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@774 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-protocol-stub.c | 62 +++++++++++++++++------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 0ffd81df5..d5b5f63b1 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -169,6 +169,7 @@ struct userdata { void *protocol_ipv6; #else void *protocol_unix; + char *socket_path; #endif }; @@ -197,6 +198,8 @@ int pa__init(pa_core *c, pa_module*m) { goto finish; } + u = pa_xnew0(struct userdata, 1); + #if defined(USE_TCP_SOCKETS) if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) { pa_log(__FILE__": loopback= expects a boolean argument."); @@ -224,11 +227,21 @@ int pa__init(pa_core *c, pa_module*m) { if (!s_ipv4 && !s_ipv6) goto fail; + if (s_ipv4) + if (!(u->protocol_ipv4 = protocol_new(c, s_ipv4, m, ma))) + pa_socket_server_unref(s_ipv4); + + if (s_ipv6) + if (!(u->protocol_ipv6 = protocol_new(c, s_ipv6, m, ma))) + pa_socket_server_unref(s_ipv6); + + if (!u->protocol_ipv4 && !u->protocol_ipv6) + goto fail; + #else v = pa_modargs_get_value(ma, "socket", UNIX_SOCKET); - assert(v); - pa_runtime_path(v, tmp, sizeof(tmp)); + u->socket_path = pa_xstrdup(tmp); if (pa_make_secure_parent_dir(tmp) < 0) { pa_log(__FILE__": Failed to create secure socket directory."); @@ -245,24 +258,10 @@ int pa__init(pa_core *c, pa_module*m) { if (!(s = pa_socket_server_new_unix(c->mainloop, tmp))) goto fail; -#endif - u = pa_xnew0(struct userdata, 1); - -#if defined(USE_TCP_SOCKETS) - if (s_ipv4) - if (!(u->protocol_ipv4 = protocol_new(c, s_ipv4, m, ma))) - pa_socket_server_unref(s_ipv4); - - if (s_ipv6) - if (!(u->protocol_ipv6 = protocol_new(c, s_ipv6, m, ma))) - pa_socket_server_unref(s_ipv6); - - if (!u->protocol_ipv4 && !u->protocol_ipv6) - goto fail; -#else if (!(u->protocol_unix = protocol_new(c, s, m, ma))) goto fail; + #endif m->userdata = u; @@ -285,7 +284,11 @@ fail: #else if (u->protocol_unix) protocol_free(u->protocol_unix); + + if (u->socket_path) + pa_xfree(u->socket_path); #endif + pa_xfree(u); } else { #if defined(USE_TCP_SOCKETS) @@ -304,17 +307,11 @@ fail: void pa__done(pa_core *c, pa_module*m) { struct userdata *u; - assert(c && m); - -#if defined(USE_PROTOCOL_ESOUND) && !defined(USE_TCP_SOCKETS) - if (remove(ESD_UNIX_SOCKET_NAME) != 0) - pa_log("%s: Failed to remove %s : %s.", __FILE__, ESD_UNIX_SOCKET_NAME, strerror (errno)); - if (remove(ESD_UNIX_SOCKET_DIR) != 0) - pa_log("%s: Failed to remove %s : %s.", __FILE__, ESD_UNIX_SOCKET_DIR, strerror (errno)); -#endif + + assert(c); + assert(m); u = m->userdata; - assert(u); #if defined(USE_TCP_SOCKETS) if (u->protocol_ipv4) @@ -324,6 +321,19 @@ void pa__done(pa_core *c, pa_module*m) { #else if (u->protocol_unix) protocol_free(u->protocol_unix); + + if (u->socket_path) { + char *p; + + if ((p = pa_parent_dir(u->socket_path))) { + if (rmdir(p) < 0 && errno != ENOENT && errno != ENOTEMPTY) + pa_log(__FILE__": Failed to remove %s: %s.", u->socket_path, strerror(errno)); + + pa_xfree(p); + } + + pa_xfree(u->socket_path); + } #endif pa_xfree(u); From 55e19cbc039be4481215d19b39452ab9fc9d0d11 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 21:04:35 +0000 Subject: [PATCH 0681/1514] fix sample cache git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@775 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/core-scache.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 1803931ed..394bdab41 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -115,7 +115,6 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index); } - pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX); e->last_used_time = 0; e->memchunk.memblock = NULL; e->memchunk.index = e->memchunk.length = 0; @@ -124,6 +123,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { e->last_used_time = 0; memset(&e->sample_spec, 0, sizeof(pa_sample_spec)); + pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX); return e; } @@ -138,6 +138,7 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c if (ss) { e->sample_spec = *ss; pa_channel_map_init_auto(&e->channel_map, ss->channels); + e->volume.channels = e->sample_spec.channels; } if (map) @@ -242,7 +243,10 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cv pa_scache_entry *e; char *t; pa_cvolume r; - assert(c && name && sink); + + assert(c); + assert(name); + assert(sink); if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) return -1; @@ -252,19 +256,27 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cv return -1; pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); + e->volume.channels = e->sample_spec.channels; } if (!e->memchunk.memblock) return -1; t = pa_sprintf_malloc("sample:%s", name); - - if (pa_play_memchunk(sink, t, &e->sample_spec, &e->channel_map, &e->memchunk, pa_sw_cvolume_multiply(&r, volume, &e->volume)) < 0) { - free(t); + + if (volume) { + r = *volume; + r.channels = e->volume.channels; + pa_sw_cvolume_multiply(&r, &r, &e->volume); + } else + r = e->volume; + + if (pa_play_memchunk(sink, t, &e->sample_spec, &e->channel_map, &e->memchunk, &r) < 0) { + pa_xfree(t); return -1; } - free(t); + pa_xfree(t); if (e->lazy) time(&e->last_used_time); From 5e50f84e71b948b4737fe8b5860e5fe414258570 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 21:49:30 +0000 Subject: [PATCH 0682/1514] fix x11 handling git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@776 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/x11wrap.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/polypcore/x11wrap.c b/src/polypcore/x11wrap.c index 21a7f3076..c1ca83ca2 100644 --- a/src/polypcore/x11wrap.c +++ b/src/polypcore/x11wrap.c @@ -87,6 +87,9 @@ static void display_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_ static void defer_event(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { pa_x11_wrapper *w = userdata; assert(m && e && w && w->ref >= 1); + + m->defer_enable(e, 0); + work(w); } @@ -96,6 +99,8 @@ static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC assert(m && e && fd >= 0 && w && w->ref >= 1); XProcessInternalConnection(w->display, fd); + + work(w); } /* Add a new IO source for the specified X11 internal connection */ @@ -211,6 +216,10 @@ void pa_x11_wrapper_unref(pa_x11_wrapper* w) { Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w) { assert(w && w->ref >= 1); + + /* Somebody is using us, schedule a output buffer flush */ + w->core->mainloop->defer_enable(w->defer_event, 1); + return w->display; } From ec65ca6ae758610a46c95fbf589729fb15cf1daf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 21:50:15 +0000 Subject: [PATCH 0683/1514] when loading sound files, initialize channel map data properly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@777 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/core-scache.c | 7 ++++--- src/polypcore/sound-file.c | 5 ++++- src/polypcore/sound-file.h | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 394bdab41..6632a1710 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -157,6 +157,7 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint32_t *idx) { pa_sample_spec ss; + pa_channel_map map; pa_memchunk chunk; int r; @@ -167,10 +168,10 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3 filename = buf; #endif - if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0) + if (pa_sound_file_load(filename, &ss, &map, &chunk, c->memblock_stat) < 0) return -1; - r = pa_scache_add_item(c, name, &ss, NULL, &chunk, idx); + r = pa_scache_add_item(c, name, &ss, &map, &chunk, idx); pa_memblock_unref(chunk.memblock); return r; @@ -252,7 +253,7 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cv return -1; if (e->lazy && !e->memchunk.memblock) { - if (pa_sound_file_load(e->filename, &e->sample_spec, &e->memchunk, c->memblock_stat) < 0) + if (pa_sound_file_load(e->filename, &e->sample_spec, &e->channel_map, &e->memchunk, c->memblock_stat) < 0) return -1; pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); diff --git a/src/polypcore/sound-file.c b/src/polypcore/sound-file.c index d86141ce4..7a4ef0755 100644 --- a/src/polypcore/sound-file.c +++ b/src/polypcore/sound-file.c @@ -35,7 +35,7 @@ #define MAX_FILE_SIZE (1024*1024) -int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_memchunk *chunk, pa_memblock_stat *s) { +int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk, pa_memblock_stat *s) { SNDFILE*sf = NULL; SF_INFO sfinfo; int ret = -1; @@ -74,6 +74,9 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_memchunk *chunk pa_log(__FILE__": Unsupported sample format in file %s", fname); goto finish; } + + if (map) + pa_channel_map_init_auto(map, ss->channels); if ((l = pa_frame_size(ss)*sfinfo.frames) > MAX_FILE_SIZE) { pa_log(__FILE__": File too large"); diff --git a/src/polypcore/sound-file.h b/src/polypcore/sound-file.h index ffa551b52..9d687f90e 100644 --- a/src/polypcore/sound-file.h +++ b/src/polypcore/sound-file.h @@ -23,9 +23,10 @@ ***/ #include +#include #include -int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_memchunk *chunk, pa_memblock_stat *s); +int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk, pa_memblock_stat *s); int pa_sound_file_too_big_to_cache(const char *fname); From f6fc410a96c7b0ca8e393d20ffe5771da5b55604 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 21:51:30 +0000 Subject: [PATCH 0684/1514] modify x11 modules to not cache the Display variable since pa_x11wrap_get_display() is now used as notification that the x11 output buffer needs flushing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@778 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-x11-bell.c | 13 +++++-------- src/modules/module-x11-publish.c | 27 ++++++++++++--------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index 27ceb7f9c..fe1711a51 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -52,7 +52,6 @@ struct userdata { int xkb_event_base; char *sink_name; char *scache_item; - Display *display; pa_x11_wrapper *x11_wrapper; pa_x11_client *x11_client; @@ -75,7 +74,7 @@ static int ring_bell(struct userdata *u, int percent) { return -1; } - pa_scache_play_item(u->core, u->scache_item, s, pa_cvolume_set(&cv, PA_CHANNELS_MAX, percent*PA_VOLUME_NORM/100)); + pa_scache_play_item(u->core, u->scache_item, s, pa_cvolume_set(&cv, PA_CHANNELS_MAX, (percent*PA_VOLUME_NORM)/100)); return 0; } @@ -118,8 +117,6 @@ int pa__init(pa_core *c, pa_module*m) { if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) goto fail; - u->display = pa_x11_wrapper_get_display(u->x11_wrapper); - major = XkbMajorVersion; minor = XkbMinorVersion; @@ -132,15 +129,15 @@ int pa__init(pa_core *c, pa_module*m) { minor = XkbMinorVersion; - if (!XkbQueryExtension(u->display, NULL, &u->xkb_event_base, NULL, &major, &minor)) { + if (!XkbQueryExtension(pa_x11_wrapper_get_display(u->x11_wrapper), NULL, &u->xkb_event_base, NULL, &major, &minor)) { pa_log(__FILE__": XkbQueryExtension() failed"); goto fail; } - XkbSelectEvents(u->display, XkbUseCoreKbd, XkbBellNotifyMask, XkbBellNotifyMask); + XkbSelectEvents(pa_x11_wrapper_get_display(u->x11_wrapper), XkbUseCoreKbd, XkbBellNotifyMask, XkbBellNotifyMask); auto_ctrls = auto_values = XkbAudibleBellMask; - XkbSetAutoResetControls(u->display, XkbAudibleBellMask, &auto_ctrls, &auto_values); - XkbChangeEnabledControls(u->display, XkbUseCoreKbd, XkbAudibleBellMask, 0); + XkbSetAutoResetControls(pa_x11_wrapper_get_display(u->x11_wrapper), XkbAudibleBellMask, &auto_ctrls, &auto_values); + XkbChangeEnabledControls(pa_x11_wrapper_get_display(u->x11_wrapper), XkbUseCoreKbd, XkbAudibleBellMask, 0); u->x11_client = pa_x11_client_new(u->x11_wrapper, x11_event_callback, u); diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index cee9cb3fd..7408b930f 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -66,7 +66,6 @@ static const char* const valid_modargs[] = { struct userdata { pa_core *core; pa_x11_wrapper *x11_wrapper; - Display *display; char *id; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; int auth_cookie_in_property; @@ -123,28 +122,26 @@ int pa__init(pa_core *c, pa_module*m) { if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) goto fail; - u->display = pa_x11_wrapper_get_display(u->x11_wrapper); - if (!(l = pa_property_get(c, PA_NATIVE_SERVER_PROPERTY_NAME))) goto fail; s = pa_strlist_tostring(l); - pa_x11_set_prop(u->display, "POLYP_SERVER", s); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SERVER", s); pa_xfree(s); if (!pa_get_fqdn(hn, sizeof(hn)) || !pa_get_user_name(un, sizeof(un))) goto fail; u->id = pa_sprintf_malloc("%s@%s/%u", un, hn, (unsigned) getpid()); - pa_x11_set_prop(u->display, "POLYP_ID", u->id); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_ID", u->id); if ((t = pa_modargs_get_value(ma, "source", NULL))) - pa_x11_set_prop(u->display, "POLYP_SOURCE", t); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SOURCE", t); if ((t = pa_modargs_get_value(ma, "sink", NULL))) - pa_x11_set_prop(u->display, "POLYP_SINK", t); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SINK", t); - pa_x11_set_prop(u->display, "POLYP_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), hx, sizeof(hx))); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), hx, sizeof(hx))); pa_modargs_free(ma); return 0; @@ -168,15 +165,15 @@ void pa__done(pa_core *c, pa_module*m) { char t[256]; /* Yes, here is a race condition */ - if (!pa_x11_get_prop(u->display, "POLYP_ID", t, sizeof(t)) || strcmp(t, u->id)) + if (!pa_x11_get_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_ID", t, sizeof(t)) || strcmp(t, u->id)) pa_log_warn(__FILE__": Polypaudio information vanished from X11!"); else { - pa_x11_del_prop(u->display, "POLYP_ID"); - pa_x11_del_prop(u->display, "POLYP_SERVER"); - pa_x11_del_prop(u->display, "POLYP_SINK"); - pa_x11_del_prop(u->display, "POLYP_SOURCE"); - pa_x11_del_prop(u->display, "POLYP_COOKIE"); - XSync(u->display, False); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_ID"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SERVER"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SINK"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SOURCE"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_COOKIE"); + XSync(pa_x11_wrapper_get_display(u->x11_wrapper), False); } } From 985da9bb5956fa7400e8f9ce861bf6fab2b3b6ce Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 21:53:18 +0000 Subject: [PATCH 0685/1514] require automake 1.9 in configure.ac git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@779 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d6239f974..d73a69299 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_PREREQ(2.57) AC_INIT([polypaudio],[0.8],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_HEADERS([config.h]) -AM_INIT_AUTOMAKE([foreign -Wall]) +AM_INIT_AUTOMAKE([foreign 1.9 -Wall]) AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) From 2bb8283a66a06282f23b55fc47b3d4c1cdb79704 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Apr 2006 21:53:35 +0000 Subject: [PATCH 0686/1514] remove superfluous "set -ex" line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@780 fefdeb5f-60dc-0310-8127-8f9354f1896f --- bootstrap.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 19acffb5e..ea6758a42 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -45,8 +45,6 @@ if [ "x$1" = "xam" ] ; then run_versioned automake "$VERSION" -a -c --foreign ./config.status else - set -ex - rm -rf autom4te.cache rm -f config.cache From 834506318d70d2562cf28539ab922388001d4247 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 14:29:32 +0000 Subject: [PATCH 0687/1514] * Merge build system patch from Igor Zubkov * Build libparseaddr.so before libsocket-client.so git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@781 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index b646cff78..2061b0ca1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -573,8 +573,8 @@ modlib_LTLIBRARIES = \ libsocket-util.la \ libiochannel.la \ libsocket-server.la \ - libsocket-client.la \ libparseaddr.la \ + libsocket-client.la \ libpacket.la \ libpstream.la \ libioline.la \ @@ -690,7 +690,7 @@ libauthkey_prop_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket_util_la_SOURCES = polypcore/socket-util.c polypcore/socket-util.h libsocket_util_la_LDFLAGS = -avoid-version -libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) +libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) libpolypcore.la librtp_la_SOURCES = modules/rtp/rtp.c modules/rtp/rtp.h modules/rtp/sdp.c modules/rtp/sdp.h modules/rtp/sap.c modules/rtp/sap.h librtp_la_LDFLAGS = -avoid-version @@ -701,7 +701,7 @@ librtp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libx11wrap_la_SOURCES = polypcore/x11wrap.c polypcore/x11wrap.h libx11wrap_la_LDFLAGS = -avoid-version libx11wrap_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libpolypcore.la libx11prop_la_SOURCES = polypcore/x11prop.c polypcore/x11prop.h libx11prop_la_LDFLAGS = -avoid-version @@ -988,7 +988,7 @@ module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-client.l module_x11_bell_la_SOURCES = modules/module-x11-bell.c module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_bell_la_LDFLAGS = -module -avoid-version -module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la +module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libpolypcore.la module_x11_publish_la_SOURCES = modules/module-x11-publish.c module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) @@ -999,6 +999,7 @@ module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EX liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h liboss_util_la_LDFLAGS = -avoid-version +liboss_util_la_LIBADD = libpolypcore.la module_oss_la_SOURCES = modules/module-oss.c module_oss_la_LDFLAGS = -module -avoid-version @@ -1006,23 +1007,23 @@ module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la module_oss_mmap_la_SOURCES = modules/module-oss-mmap.c module_oss_mmap_la_LDFLAGS = -module -avoid-version -module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la +module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la libpolypcore.la # ALSA libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h libalsa_util_la_LDFLAGS = -avoid-version -libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) +libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libpolypcore.la libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) module_alsa_sink_la_SOURCES = modules/module-alsa-sink.c module_alsa_sink_la_LDFLAGS = -module -avoid-version -module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la +module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpolypcore.la module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) module_alsa_source_la_SOURCES = modules/module-alsa-source.c module_alsa_source_la_LDFLAGS = -module -avoid-version -module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la +module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpolypcore.la module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) # Solaris @@ -1047,14 +1048,14 @@ module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) module_lirc_la_SOURCES = modules/module-lirc.c module_lirc_la_LDFLAGS = -module -avoid-version -module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) +module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) libpolypcore.la module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS) # Linux evdev module_mmkbd_evdev_la_SOURCES = modules/module-mmkbd-evdev.c module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version -module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) +module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) libpolypcore.la module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS) # Windows waveout @@ -1073,12 +1074,12 @@ module_detect_la_CFLAGS = $(AM_CFLAGS) # RTP modules module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c module_rtp_send_la_LDFLAGS = -module -avoid-version -module_rtp_send_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_rtp_send_la_LIBADD = $(AM_LIBADD) libpolypcore.la librtp.la module_rtp_send_la_CFLAGS = $(AM_CFLAGS) module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c module_rtp_recv_la_LDFLAGS = -module -avoid-version -module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpolypcore.la librtp.la module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) # JACK From b4ac6d05d21742af2558acbdfebc83805750356f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 19:42:58 +0000 Subject: [PATCH 0688/1514] allow recieving of invalid channel maps, volumes and sample specs. This makes handling of uninitialized data better, e.g. when sending info about lazy-load sample chache entries, where the channel mapping and sample spec is still unknown. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@782 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/tagstruct.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/polypcore/tagstruct.c b/src/polypcore/tagstruct.c index 761f6d3d6..86b8368a3 100644 --- a/src/polypcore/tagstruct.c +++ b/src/polypcore/tagstruct.c @@ -311,9 +311,6 @@ int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) { memcpy(&ss->rate, t->data+t->rindex+3, 4); ss->rate = ntohl(ss->rate); - if (!pa_sample_spec_valid(ss)) - return -1; - t->rindex += 7; return 0; } @@ -379,7 +376,6 @@ int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) { tv->tv_usec = ntohl(tv->tv_usec); t->rindex += 9; return 0; - } int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) { @@ -457,9 +453,6 @@ int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) { for (i = 0; i < map->channels; i ++) map->map[i] = (int8_t) t->data[t->rindex + 2 + i]; - if (!pa_channel_map_valid(map)) - return -1; - t->rindex += 2 + map->channels; return 0; } @@ -488,9 +481,6 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { cvolume->values[i] = (pa_volume_t) ntohl(vol); } - if (!pa_cvolume_valid(cvolume)) - return -1; - t->rindex += 2 + cvolume->channels * sizeof(pa_volume_t); return 0; } From 4e61ebb981b218637685d7edbf7faac89916a094 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 19:46:16 +0000 Subject: [PATCH 0689/1514] fix multiplication of software pa_cvolumes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@783 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/volume.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/volume.c b/src/polyp/volume.c index 0f1531410..f10463c3c 100644 --- a/src/polyp/volume.c +++ b/src/polyp/volume.c @@ -154,7 +154,7 @@ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const assert(a); assert(b); - for (i = 0; i < a->channels || i < b->channels || i < PA_CHANNELS_MAX; i++) { + for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++) { dest->values[i] = pa_sw_volume_multiply( i < a->channels ? a->values[i] : PA_VOLUME_NORM, From 335e23473fee2a6e40f838cd920ed13af3f93626 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 19:49:01 +0000 Subject: [PATCH 0690/1514] * when playing back a sample from the sample cache, just take a pa_volume_t and not a pa_cvolume_t as argument for the volume. Usually it is not known to the player of theses samples how many channels it has, hence it doesn't make any sense to allow him to pass a by-channel volume structure here. * fix volume calculation when playing samples from the sample cache git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@784 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-x11-bell.c | 3 +-- src/polypcore/cli-command.c | 2 +- src/polypcore/core-scache.c | 17 ++++++++--------- src/polypcore/core-scache.h | 2 +- src/polypcore/protocol-esound.c | 2 +- src/polypcore/protocol-native.c | 8 ++++---- 6 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index fe1711a51..e4d4020e3 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -66,7 +66,6 @@ static const char* const valid_modargs[] = { static int ring_bell(struct userdata *u, int percent) { pa_sink *s; - pa_cvolume cv; assert(u); if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { @@ -74,7 +73,7 @@ static int ring_bell(struct userdata *u, int percent) { return -1; } - pa_scache_play_item(u->core, u->scache_item, s, pa_cvolume_set(&cv, PA_CHANNELS_MAX, (percent*PA_VOLUME_NORM)/100)); + pa_scache_play_item(u->core, u->scache_item, s, (percent*PA_VOLUME_NORM)/100); return 0; } diff --git a/src/polypcore/cli-command.c b/src/polypcore/cli-command.c index 0251ab0a9..180c61e9a 100644 --- a/src/polypcore/cli-command.c +++ b/src/polypcore/cli-command.c @@ -597,7 +597,7 @@ static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return -1; } - if (pa_scache_play_item(c, n, sink, NULL) < 0) { + if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM) < 0) { pa_strbuf_puts(buf, "Failed to play sample.\n"); return -1; } diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 6632a1710..9c4076230 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -122,7 +122,8 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { e->lazy = 0; e->last_used_time = 0; - memset(&e->sample_spec, 0, sizeof(pa_sample_spec)); + memset(&e->sample_spec, 0, sizeof(e->sample_spec)); + pa_channel_map_init(&e->channel_map); pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX); return e; @@ -240,7 +241,7 @@ void pa_scache_free(pa_core *c) { c->mainloop->time_free(c->scache_auto_unload_event); } -int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cvolume *volume) { +int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume) { pa_scache_entry *e; char *t; pa_cvolume r; @@ -257,7 +258,9 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cv return -1; pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); - e->volume.channels = e->sample_spec.channels; + + if (e->volume.channels > e->sample_spec.channels) + e->volume.channels = e->sample_spec.channels; } if (!e->memchunk.memblock) @@ -265,12 +268,8 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cv t = pa_sprintf_malloc("sample:%s", name); - if (volume) { - r = *volume; - r.channels = e->volume.channels; - pa_sw_cvolume_multiply(&r, &r, &e->volume); - } else - r = e->volume; + pa_cvolume_set(&r, e->volume.channels, volume); + pa_sw_cvolume_multiply(&r, &r, &e->volume); if (pa_play_memchunk(sink, t, &e->sample_spec, &e->channel_map, &e->memchunk, &r) < 0) { pa_xfree(t); diff --git a/src/polypcore/core-scache.h b/src/polypcore/core-scache.h index a383e50ac..151d17613 100644 --- a/src/polypcore/core-scache.h +++ b/src/polypcore/core-scache.h @@ -49,7 +49,7 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, int pa_scache_add_directory_lazy(pa_core *c, const char *pathname); int pa_scache_remove_item(pa_core *c, const char *name); -int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cvolume *cvolume); +int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume); void pa_scache_free(pa_core *c); const char *pa_scache_get_name_by_id(pa_core *c, uint32_t id); diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index e29c44c9d..2c956a7e2 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -742,7 +742,7 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque pa_sink *sink; if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) - if (pa_scache_play_item(c->protocol->core, name, sink, NULL) >= 0) + if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0) ok = idx + 1; } else { assert(request == ESD_PROTO_SAMPLE_FREE); diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 3f1d5ca2b..f8c2d1665 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -57,7 +57,7 @@ #include "protocol-native.h" /* Kick a client if it doesn't authenticate within this time */ -#define AUTH_TIMEOUT 5 +#define AUTH_TIMEOUT 60 /* Don't accept more connection than this */ #define MAX_CONNECTIONS 10 @@ -1165,14 +1165,14 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t sink_index; - pa_cvolume volume; + pa_volume_t volume; pa_sink *sink; const char *name, *sink_name; assert(c && t); if (pa_tagstruct_getu32(t, &sink_index) < 0 || pa_tagstruct_gets(t, &sink_name) < 0 || - pa_tagstruct_get_cvolume(t, &volume) < 0 || + pa_tagstruct_getu32(t, &volume) < 0 || pa_tagstruct_gets(t, &name) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1190,7 +1190,7 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); - if (pa_scache_play_item(c->protocol->core, name, sink, &volume) < 0) { + if (pa_scache_play_item(c->protocol->core, name, sink, volume) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; } From 193fb122287256ff32e3761426207e2a3f224f3c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 20:56:41 +0000 Subject: [PATCH 0691/1514] introduce a new error PA_ERR_TOOLARGE git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@785 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/def.h | 1 + src/polyp/error.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/polyp/def.h b/src/polyp/def.h index 517dd4226..edada3800 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -160,6 +160,7 @@ enum { PA_ERR_BADSTATE, /**< Bad state */ PA_ERR_NODATA, /**< No data */ PA_ERR_VERSION, /**< Incompatible protocol version \since 0.8 */ + PA_ERR_TOOLARGE, /**< Data too large \since 0.8.1 */ PA_ERR_MAX /**< Not really an error but the first invalid error code */ }; diff --git a/src/polyp/error.c b/src/polyp/error.c index 3f3e637f9..e78d072e8 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -49,6 +49,7 @@ static const char* const errortab[PA_ERR_MAX] = { [PA_ERR_BADSTATE] = "Bad state", [PA_ERR_NODATA] = "No data", [PA_ERR_VERSION] = "Incompatible protocol version", + [PA_ERR_TOOLARGE] = "Too large" }; const char*pa_strerror(int error) { From cdba0527a8b33874816da339d06133ec7bc85918 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 20:58:08 +0000 Subject: [PATCH 0692/1514] * fix ref counting of pa_stream: strictly refcount from context to stream and never vice versa to make sure that we never loose memory * don't hit an assert() in case of a timeout events git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@786 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index e400415c7..f11ef4935 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -195,9 +195,6 @@ void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { s->channel = 0; s->channel_valid = 0; - - /* We keep a ref as long as we're connected */ - pa_stream_unref(s); } if (s->state_callback) @@ -374,7 +371,6 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED pa_stream *s = userdata; assert(pd); - assert(t); assert(s); assert(s->state == PA_STREAM_CREATING); @@ -413,9 +409,6 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED s->channel_valid = 1; pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - /* We add an extra ref as long as we're connected (i.e. in the dynarray) */ - pa_stream_ref(s); - pa_stream_set_state(s, PA_STREAM_READY); if (s->direction != PA_STREAM_UPLOAD && From e1ac42dd10e3085cdcc9ed9f0de60c8457c77701 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 20:59:09 +0000 Subject: [PATCH 0693/1514] enforce maximum sample size in sample cache git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@787 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/core-scache.c | 3 +++ src/polypcore/core-scache.h | 2 ++ src/polypcore/pstream.c | 5 +++-- src/polypcore/sound-file.c | 7 +++---- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 9c4076230..2e8d453cd 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -133,6 +133,9 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c pa_scache_entry *e; assert(c && name); + if (chunk->length > PA_SCACHE_ENTRY_SIZE_MAX) + return -1; + if (!(e = scache_add_item(c, name))) return -1; diff --git a/src/polypcore/core-scache.h b/src/polypcore/core-scache.h index 151d17613..9ca05f8f6 100644 --- a/src/polypcore/core-scache.h +++ b/src/polypcore/core-scache.h @@ -26,6 +26,8 @@ #include #include +#define PA_SCACHE_ENTRY_SIZE_MAX (1024*1024*2) + typedef struct pa_scache_entry { pa_core *core; uint32_t index; diff --git a/src/polypcore/pstream.c b/src/polypcore/pstream.c index b93dca08c..09bd1e27e 100644 --- a/src/polypcore/pstream.c +++ b/src/polypcore/pstream.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "pstream.h" @@ -52,7 +53,7 @@ enum { typedef uint32_t pa_pstream_descriptor[PA_PSTREAM_DESCRIPTOR_MAX]; #define PA_PSTREAM_DESCRIPTOR_SIZE (PA_PSTREAM_DESCRIPTOR_MAX*sizeof(uint32_t)) -#define FRAME_SIZE_MAX (1024*500) /* half a megabyte */ +#define FRAME_SIZE_MAX PA_SCACHE_ENTRY_SIZE_MAX /* allow uploading a single sample in one frame at max */ struct item_info { enum { PA_PSTREAM_ITEM_PACKET, PA_PSTREAM_ITEM_MEMBLOCK } type; @@ -419,7 +420,7 @@ static int do_read(pa_pstream *p) { /* Frame size too large */ if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) > FRAME_SIZE_MAX) { - pa_log_warn(__FILE__": Frame size too large"); + pa_log_warn(__FILE__": Frame size too large: %lu > %lu", (unsigned long) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]), (unsigned long) FRAME_SIZE_MAX); return -1; } diff --git a/src/polypcore/sound-file.c b/src/polypcore/sound-file.c index 7a4ef0755..a6ccb0649 100644 --- a/src/polypcore/sound-file.c +++ b/src/polypcore/sound-file.c @@ -32,8 +32,7 @@ #include #include "sound-file.h" - -#define MAX_FILE_SIZE (1024*1024) +#include "core-scache.h" int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk, pa_memblock_stat *s) { SNDFILE*sf = NULL; @@ -78,7 +77,7 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *ma if (map) pa_channel_map_init_auto(map, ss->channels); - if ((l = pa_frame_size(ss)*sfinfo.frames) > MAX_FILE_SIZE) { + if ((l = pa_frame_size(ss)*sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { pa_log(__FILE__": File too large"); goto finish; } @@ -134,7 +133,7 @@ int pa_sound_file_too_big_to_cache(const char *fname) { ss.rate = sfinfo.samplerate; ss.channels = sfinfo.channels; - if ((pa_frame_size(&ss) * sfinfo.frames) > MAX_FILE_SIZE) { + if ((pa_frame_size(&ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { pa_log(__FILE__": File too large %s", fname); return 1; } From 9b52ac4b47f468ad79ef91e337fe727b58ac26ce Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 20:59:31 +0000 Subject: [PATCH 0694/1514] fix sample uploading git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@788 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/scache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/polyp/scache.c b/src/polyp/scache.c index 891798fbd..2b9e9c8f2 100644 --- a/src/polyp/scache.c +++ b/src/polyp/scache.c @@ -41,7 +41,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) { assert(s); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY(s->context, length <= 0, PA_ERR_INVALID); + PA_CHECK_VALIDITY(s->context, length > 0, PA_ERR_INVALID); pa_stream_ref(s); @@ -50,6 +50,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) { t = pa_tagstruct_command(s->context, PA_COMMAND_CREATE_UPLOAD_STREAM, &tag); pa_tagstruct_puts(t, s->name); pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_put_channel_map(t, &s->channel_map); pa_tagstruct_putu32(t, length); pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s); From 286310a563ad52105676243326b6ec2c34d945c5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 20:59:43 +0000 Subject: [PATCH 0695/1514] small optimization git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@789 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/polyp/context.c b/src/polyp/context.c index ff224547b..1e78f97fb 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -784,18 +784,15 @@ static void set_dispatch_callbacks(pa_operation *o) { done = 0; } - if (!done) - pa_operation_ref(o); - else { + if (done) { if (o->callback) { pa_context_notify_cb_t cb = (pa_context_notify_cb_t) o->callback; cb(o->context, o->userdata); } pa_operation_done(o); - } - - pa_operation_unref(o); + pa_operation_unref(o); + } } pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { From 3590ee7581df02152cb2924509752565cd1e3dea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 21:01:44 +0000 Subject: [PATCH 0696/1514] * add validity checking for sample_spec, channel_map and cvolume structures * return PA_ERR_TOOLARGE when the user tries to upload a over-sized sample * notify the user if uploading a simple faield due to some reason git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@790 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-native.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index f8c2d1665..ace9db6fb 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -732,6 +732,9 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || *sink_name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); @@ -827,6 +830,8 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || *source_name, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); @@ -1126,7 +1131,11 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE); CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); s = upload_stream_new(c, &ss, &map, name, length); @@ -1157,8 +1166,11 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); CHECK_VALIDITY(c->pstream, s->type == UPLOAD_STREAM, tag, PA_ERR_NOENTITY); - pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx); - pa_pstream_send_simple_ack(c->pstream, tag); + if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx) < 0) + pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL); + else + pa_pstream_send_simple_ack(c->pstream, tag); + upload_stream_free(s); } @@ -1553,6 +1565,7 @@ static void command_set_volume( CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || *name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); if (command == PA_COMMAND_SET_SINK_VOLUME) { if (idx != PA_INVALID_INDEX) From b92344f3ec2e678c497397074cc1693e9098c0f1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Apr 2006 21:25:27 +0000 Subject: [PATCH 0697/1514] fix a segfault when uploading samples with esound git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@791 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/core-scache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 2e8d453cd..82c61a1d2 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -133,7 +133,7 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c pa_scache_entry *e; assert(c && name); - if (chunk->length > PA_SCACHE_ENTRY_SIZE_MAX) + if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX) return -1; if (!(e = scache_add_item(c, name))) From fade8b0883cc5a22a00e8fd9c1358d9628923355 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 24 Apr 2006 13:59:00 +0000 Subject: [PATCH 0698/1514] Undo invalid automake version requirement. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@792 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d73a69299..d6239f974 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_PREREQ(2.57) AC_INIT([polypaudio],[0.8],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_HEADERS([config.h]) -AM_INIT_AUTOMAKE([foreign 1.9 -Wall]) +AM_INIT_AUTOMAKE([foreign -Wall]) AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) From d26621371e6bf5040fe833f046ff81a1c7cac94b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 24 Apr 2006 15:07:09 +0000 Subject: [PATCH 0699/1514] chown() and chmod() aren't available on Windows. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@793 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 ++-- src/polypcore/util.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index d6239f974..87dc2aab2 100644 --- a/configure.ac +++ b/configure.ac @@ -219,8 +219,8 @@ AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])]) AC_FUNC_FORK AC_FUNC_GETGROUPS AC_FUNC_SELECT_ARGTYPES -AC_CHECK_FUNCS([getaddrinfo getgrgid_r getpwuid_r gettimeofday getuid \ - inet_ntop inet_pton nanosleep setpgid setsid sigaction sleep]) +AC_CHECK_FUNCS([chmod chown getaddrinfo getgrgid_r getpwuid_r gettimeofday \ + getuid inet_ntop inet_pton nanosleep setpgid setsid sigaction sleep]) AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0]) AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1") diff --git a/src/polypcore/util.c b/src/polypcore/util.c index 615ea881a..191fa809d 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -140,8 +140,12 @@ int pa_make_secure_dir(const char* dir) { if (errno != EEXIST) return -1; +#ifdef HAVE_CHOWN chown(dir, getuid(), getgid()); +#endif +#ifdef HAVE_CHMOD chmod(dir, 0700); +#endif #ifdef HAVE_LSTAT if (lstat(dir, &st) < 0) From 820c118f9c57c7a7767765efc802502632ad8da2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Apr 2006 19:29:15 +0000 Subject: [PATCH 0700/1514] * rework reference counting in the client libraries: now refcounting goes strictly "one-way" - the "bigger" object refcounts the "smaller" one, never the other way round. * when registering for a reply packet in pdispatch, specify a function that is called when the pdispatch object is destroyed but the reply hasn't yet been recieved. * move prototype of pa_free_cb from stream.h to def.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@794 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 8 +-- src/polyp/context.c | 28 ++++++----- src/polyp/def.h | 3 ++ src/polyp/internal.h | 1 + src/polyp/introspect.c | 98 +++++++++++++++++++++++-------------- src/polyp/operation.c | 55 ++++++++++++--------- src/polyp/scache.c | 8 +-- src/polyp/stream.c | 72 ++++++++++++++++----------- src/polyp/stream.h | 3 -- src/polyp/subscribe.c | 2 +- src/polypcore/pdispatch.c | 10 +++- src/polypcore/pdispatch.h | 3 +- 12 files changed, 175 insertions(+), 116 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index b68bc485f..abfa68a41 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -356,7 +356,7 @@ static void request_latency(struct userdata *u) { pa_tagstruct_put_timeval(t, &now); pa_pstream_send_tagstruct(u->pstream, t); - pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u, NULL); } static void stream_get_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -449,7 +449,7 @@ static void request_info(struct userdata *u) { #endif pa_pstream_send_tagstruct(u->pstream, t); - pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_info_callback, u); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_info_callback, u, NULL); } static void start_subscribe(struct userdata *u) { @@ -580,7 +580,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t #endif pa_pstream_send_tagstruct(u->pstream, reply); - pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u, NULL); } static void pstream_die_callback(pa_pstream *p, void *userdata) { @@ -647,7 +647,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, u->auth_cookie, sizeof(u->auth_cookie)); pa_pstream_send_tagstruct(u->pstream, t); - pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, u); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, u, NULL); } diff --git a/src/polyp/context.c b/src/polyp/context.c index 1e78f97fb..c9a658477 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -162,7 +162,7 @@ static void context_free(pa_context *c) { while (c->streams) pa_stream_set_state(c->streams, PA_STREAM_TERMINATED); - + if (c->client) pa_socket_client_unref(c->client); if (c->pdispatch) @@ -218,6 +218,10 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { pa_context_ref(c); + c->state = st; + if (c->state_callback) + c->state_callback(c, c->state_userdata); + if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) { pa_stream *s; @@ -244,10 +248,6 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { c->client = NULL; } - c->state = st; - if (c->state_callback) - c->state_callback(c, c->state_userdata); - pa_context_unref(c); } @@ -383,7 +383,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); pa_tagstruct_puts(reply, c->name); pa_pstream_send_tagstruct(c->pstream, reply); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); pa_context_set_state(c, PA_CONTEXT_SETTING_NAME); break; @@ -429,7 +429,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); pa_pstream_send_tagstruct_with_creds(c->pstream, t, 1); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); @@ -817,7 +817,9 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_U assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + + if (!o->context) + goto finish; if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -853,7 +855,7 @@ pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, t = pa_tagstruct_command(c, PA_COMMAND_EXIT, &tag); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -872,7 +874,7 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa t = pa_tagstruct_command(c, command, &tag); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -892,7 +894,7 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_co t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SINK, &tag); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -912,7 +914,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -939,7 +941,7 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } diff --git a/src/polyp/def.h b/src/polyp/def.h index edada3800..579971633 100644 --- a/src/polyp/def.h +++ b/src/polyp/def.h @@ -304,6 +304,9 @@ typedef enum pa_source_flags { PA_SOURCE_LATENCY = 2 /**< Supports latency querying */ } pa_source_flags_t; +/** A generic free() like callback prototype */ +typedef void (*pa_free_cb_t)(void *p); + PA_C_DECL_END #endif diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 2bec0294f..f41744ef5 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -159,6 +159,7 @@ struct pa_operation { int ref; pa_context *context; pa_stream *stream; + PA_LLIST_FIELDS(pa_operation); pa_operation_state_t state; diff --git a/src/polyp/introspect.c b/src/polyp/introspect.c index ea6133e1b..9d0026695 100644 --- a/src/polyp/introspect.c +++ b/src/polyp/introspect.c @@ -43,7 +43,9 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNU assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + + if (!o->context) + goto finish; if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -83,7 +85,9 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + + if (!o->context) + goto finish; if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -127,8 +131,10 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + if (!o->context) + goto finish; + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; @@ -198,7 +204,7 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_ pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -221,7 +227,7 @@ pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -235,7 +241,9 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + + if (!o->context) + goto finish; if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -306,7 +314,7 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, p pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -329,9 +337,9 @@ pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); - return pa_operation_ref(o); + return o; } /*** Client info ***/ @@ -343,7 +351,9 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + + if (!o->context) + goto finish; if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -397,7 +407,7 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_ t = pa_tagstruct_command(c, PA_COMMAND_GET_CLIENT_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -415,7 +425,9 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + + if (!o->context) + goto finish; if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -470,7 +482,7 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_ t = pa_tagstruct_command(c, PA_COMMAND_GET_MODULE_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -488,8 +500,10 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + if (!o->context) + goto finish; + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; @@ -551,7 +565,7 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sin t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INPUT_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -569,7 +583,9 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + + if (!o->context) + goto finish; if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -631,7 +647,7 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_ t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -661,7 +677,7 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, c pa_tagstruct_puts(t, NULL); pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -687,7 +703,7 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name pa_tagstruct_puts(t, name); pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -709,7 +725,7 @@ pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int pa_tagstruct_puts(t, NULL); pa_tagstruct_put_boolean(t, mute); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -733,7 +749,7 @@ pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, pa_tagstruct_puts(t, name); pa_tagstruct_put_boolean(t, mute); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -757,7 +773,7 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons pa_tagstruct_putu32(t, idx); pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -781,7 +797,7 @@ pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, pa_tagstruct_puts(t, NULL); pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -807,7 +823,7 @@ pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *na pa_tagstruct_puts(t, name); pa_tagstruct_put_cvolume(t, volume); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -829,7 +845,7 @@ pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, i pa_tagstruct_puts(t, NULL); pa_tagstruct_put_boolean(t, mute); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -853,7 +869,7 @@ pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name pa_tagstruct_puts(t, name); pa_tagstruct_put_boolean(t, mute); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -867,8 +883,10 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + if (!o->context) + goto finish; + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; @@ -928,7 +946,7 @@ pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -951,7 +969,7 @@ pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, p pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -976,7 +994,7 @@ static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, t = pa_tagstruct_command(c, command, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -1000,7 +1018,9 @@ static void context_index_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + + if (!o->context) + goto finish; if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -1041,7 +1061,7 @@ pa_operation* pa_context_load_module(pa_context *c, const char*name, const char pa_tagstruct_puts(t, name); pa_tagstruct_puts(t, argument); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_index_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_index_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -1059,7 +1079,9 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman assert(pd); assert(o); assert(o->ref >= 1); - assert(o->context); + + if (!o->context) + goto finish; if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) @@ -1116,7 +1138,7 @@ pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *na pa_tagstruct_puts(t, name); pa_tagstruct_putu32(t, type); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -1138,7 +1160,7 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, t = pa_tagstruct_command(c, PA_COMMAND_GET_AUTOLOAD_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -1168,7 +1190,7 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo pa_tagstruct_puts(t, module); pa_tagstruct_puts(t, argument); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_index_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_index_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -1191,7 +1213,7 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name pa_tagstruct_puts(t, name); pa_tagstruct_putu32(t, type); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -1212,7 +1234,7 @@ pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, p t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_AUTOLOAD, &tag); pa_tagstruct_putu32(t, idx); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } diff --git a/src/polyp/operation.c b/src/polyp/operation.c index 0216888c4..1c0cb99f2 100644 --- a/src/polyp/operation.c +++ b/src/polyp/operation.c @@ -28,78 +28,89 @@ #include #include "internal.h" - #include "operation.h" pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb, void *userdata) { pa_operation *o; assert(c); - o = pa_xmalloc(sizeof(pa_operation)); + o = pa_xnew(pa_operation, 1); o->ref = 1; - o->context = pa_context_ref(c); - o->stream = s ? pa_stream_ref(s) : NULL; + o->context = c; + o->stream = s; o->state = PA_OPERATION_RUNNING; o->callback = cb; o->userdata = userdata; - PA_LLIST_PREPEND(pa_operation, o->context->operations, o); - return pa_operation_ref(o); + /* Refcounting is strictly one-way: from the "bigger" to the "smaller" object. */ + PA_LLIST_PREPEND(pa_operation, c->operations, o); + pa_operation_ref(o); + + return o; } pa_operation *pa_operation_ref(pa_operation *o) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); + o->ref++; return o; } void pa_operation_unref(pa_operation *o) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); if ((--(o->ref)) == 0) { assert(!o->context); assert(!o->stream); - free(o); + pa_xfree(o); } } static void operation_set_state(pa_operation *o, pa_operation_state_t st) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); if (st == o->state) return; - if (!o->context) - return; - o->state = st; if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) { - PA_LLIST_REMOVE(pa_operation, o->context->operations, o); - pa_context_unref(o->context); - if (o->stream) - pa_stream_unref(o->stream); + + if (o->context) { + assert(o->ref >= 2); + + PA_LLIST_REMOVE(pa_operation, o->context->operations, o); + pa_operation_unref(o); + } + o->context = NULL; o->stream = NULL; o->callback = NULL; o->userdata = NULL; - - pa_operation_unref(o); } } void pa_operation_cancel(pa_operation *o) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); + operation_set_state(o, PA_OPERATION_CANCELED); } void pa_operation_done(pa_operation *o) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); + operation_set_state(o, PA_OPERATION_DONE); } pa_operation_state_t pa_operation_get_state(pa_operation *o) { - assert(o && o->ref >= 1); + assert(o); + assert(o->ref >= 1); + return o->state; } diff --git a/src/polyp/scache.c b/src/polyp/scache.c index 2b9e9c8f2..22d8a5454 100644 --- a/src/polyp/scache.c +++ b/src/polyp/scache.c @@ -53,7 +53,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) { pa_tagstruct_put_channel_map(t, &s->channel_map); pa_tagstruct_putu32(t, length); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL); pa_stream_set_state(s, PA_STREAM_CREATING); @@ -74,7 +74,7 @@ int pa_stream_finish_upload(pa_stream *s) { t = pa_tagstruct_command(s->context, PA_COMMAND_FINISH_UPLOAD_STREAM, &tag); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s, NULL); pa_stream_unref(s); return 0; @@ -103,7 +103,7 @@ pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char pa_tagstruct_putu32(t, volume); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } @@ -124,7 +124,7 @@ pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_conte t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_SAMPLE, &tag); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } diff --git a/src/polyp/stream.c b/src/polyp/stream.c index f11ef4935..c86a200a8 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -106,21 +106,15 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->auto_timing_update_event = NULL; s->auto_timing_update_requested = 0; + /* Refcounting is strictly one-way: from the "bigger" to the "smaller" object. */ PA_LLIST_PREPEND(pa_stream, c->streams, s); - - /* The context and stream will point at each other. We cannot ref count - both though since that will create a loop. */ - pa_context_ref(s->context); + pa_stream_ref(s); return s; } static void stream_free(pa_stream *s) { - assert(s && s->context && !s->channel_valid); - - PA_LLIST_REMOVE(pa_stream, s->context->streams, s); - - pa_context_unref(s->context); + assert(s && !s->context && !s->channel_valid); if (s->auto_timing_update_event) { assert(s->mainloop); @@ -186,20 +180,38 @@ void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { pa_stream_ref(s); s->state = st; - + if (s->state_callback) + s->state_callback(s, s->state_userdata); + if ((st == PA_STREAM_FAILED || st == PA_STREAM_TERMINATED) && s->context) { + /* Detach from context */ + pa_operation *o, *n; + + /* Unref all operatio object that point to us */ + for (o = s->context->operations; o; o = n) { + n = o->next; + + if (o->stream == s) + pa_operation_cancel(o); + } + /* Drop all outstanding replies for this stream */ + if (s->context->pdispatch) + pa_pdispatch_unregister_reply(s->context->pdispatch, s); + if (s->channel_valid) pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); + + PA_LLIST_REMOVE(pa_stream, s->context->streams, s); + pa_stream_unref(s); s->channel = 0; s->channel_valid = 0; + + s->context = NULL; } - if (s->state_callback) - s->state_callback(s, s->state_userdata); - pa_stream_unref(s); } @@ -513,7 +525,7 @@ static int create_stream( pa_tagstruct_putu32(t, s->buffer_attr.fragsize); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL); pa_stream_set_state(s, PA_STREAM_CREATING); @@ -704,9 +716,9 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us t = pa_tagstruct_command(s->context, PA_COMMAND_DRAIN_PLAYBACK_STREAM, &tag); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); - return pa_operation_ref(o); + return o; } static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -717,7 +729,9 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, assert(pd); assert(o); assert(o->stream); - assert(o->context); + + if (!o->context) + goto finish; i = &o->stream->timing_info; @@ -869,7 +883,7 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t /* Check if we could allocate a correction slot. If not, there are too many outstanding queries */ PA_CHECK_VALIDITY_RETURN_NULL(s->context, !s->write_index_corrections[cidx].valid, PA_ERR_INTERNAL); } - o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command( s->context, @@ -879,7 +893,7 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t pa_tagstruct_put_timeval(t, pa_gettimeofday(&now)); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_timing_info_callback, o); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_timing_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); if (s->direction == PA_STREAM_PLAYBACK) { /* Fill in initial correction data */ @@ -893,7 +907,7 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t /* pa_log("requesting update %u\n", tag); */ - return pa_operation_ref(o); + return o; } void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -941,7 +955,7 @@ int pa_stream_disconnect(pa_stream *s) { &tag); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s, NULL); pa_stream_unref(s); return 0; @@ -993,9 +1007,11 @@ void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN assert(pd); assert(o); - assert(o->context); assert(o->ref >= 1); + if (!o->context) + goto finish; + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; @@ -1038,12 +1054,12 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi pa_tagstruct_putu32(t, s->channel); pa_tagstruct_put_boolean(t, !!b); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); if (s->direction == PA_STREAM_PLAYBACK) invalidate_indexes(s, 1, 0); - return pa_operation_ref(o); + return o; } static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, pa_stream_success_cb_t cb, void *userdata) { @@ -1061,9 +1077,9 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, t = pa_tagstruct_command(s->context, command, &tag); pa_tagstruct_putu32(t, s->channel); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); - return pa_operation_ref(o); + return o; } pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { @@ -1136,9 +1152,9 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe pa_tagstruct_putu32(t, s->channel); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(s->context->pstream, t); - pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); - return pa_operation_ref(o); + return o; } int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { diff --git a/src/polyp/stream.h b/src/polyp/stream.h index a832fc663..b6522efec 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -267,9 +267,6 @@ typedef struct pa_stream pa_stream; /** A generic callback for operation completion */ typedef void (*pa_stream_success_cb_t) (pa_stream*s, int success, void *userdata); -/** A generic free callback */ -typedef void (*pa_free_cb_t)(void *p); - /** A generic request callback */ typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t length, void *userdata); diff --git a/src/polyp/subscribe.c b/src/polyp/subscribe.c index 110d4e52a..21f5f7a57 100644 --- a/src/polyp/subscribe.c +++ b/src/polyp/subscribe.c @@ -75,7 +75,7 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_c t = pa_tagstruct_command(c, PA_COMMAND_SUBSCRIBE, &tag); pa_tagstruct_putu32(t, m); pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o)); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; } diff --git a/src/polypcore/pdispatch.c b/src/polypcore/pdispatch.c index a4e58f8c4..b087f1a50 100644 --- a/src/polypcore/pdispatch.c +++ b/src/polypcore/pdispatch.c @@ -97,6 +97,7 @@ struct reply_info { PA_LLIST_FIELDS(struct reply_info); pa_pdispatch_cb_t callback; void *userdata; + pa_free_cb_t free_cb; uint32_t tag; pa_time_event *time_event; }; @@ -145,8 +146,12 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_ static void pdispatch_free(pa_pdispatch *pd) { assert(pd); - while (pd->replies) + while (pd->replies) { + if (pd->replies->free_cb) + pd->replies->free_cb(pd->replies->userdata); + reply_info_free(pd->replies); + } pa_xfree(pd); } @@ -243,7 +248,7 @@ static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, PA_GCC_UNUSED c run_action(r->pdispatch, r, PA_COMMAND_TIMEOUT, NULL); } -void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t cb, void *userdata) { +void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t cb, void *userdata, pa_free_cb_t free_cb) { struct reply_info *r; struct timeval tv; assert(pd && pd->ref >= 1 && cb); @@ -252,6 +257,7 @@ void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa r->pdispatch = pd; r->callback = cb; r->userdata = userdata; + r->free_cb = free_cb; r->tag = tag; pa_gettimeofday(&tv); diff --git a/src/polypcore/pdispatch.h b/src/polypcore/pdispatch.h index aa898abfa..0074e8b36 100644 --- a/src/polypcore/pdispatch.h +++ b/src/polypcore/pdispatch.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -38,7 +39,7 @@ pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const void*creds, void *userdata); -void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t callback, void *userdata); +void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t callback, void *userdata, pa_free_cb_t free_cb); int pa_pdispatch_is_pending(pa_pdispatch *pd); From f426b58e5c1c584aba8fd37fe7f2e523410b78bc Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 25 Apr 2006 07:13:44 +0000 Subject: [PATCH 0701/1514] glibc <= 2.2 has a broken unistd.h, lacking setresuid(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@795 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/caps.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/daemon/caps.c b/src/daemon/caps.c index 5c52b77a0..8740b7e8d 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -36,6 +36,12 @@ #include "caps.h" +/* Glibc <= 2.2 has broken unistd.h */ +#if defined(linux) && (__GLIBC__ <= 2 && __GLIBC_MINOR__ <= 2) +int setresgid(gid_t r, gid_t e, gid_t s); +int setresuid(uid_t r, uid_t e, uid_t s); +#endif + #ifdef HAVE_GETUID /* Drop root rights when called SUID root */ From 69096f27531381b57fa73dc8e85c812089915031 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 25 Apr 2006 07:54:49 +0000 Subject: [PATCH 0702/1514] Fall back to software volume if hardware mixer cannot control all channels. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@796 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 64 ++++++++++++++------------------ src/modules/module-alsa-source.c | 62 +++++++++++++------------------ 2 files changed, 53 insertions(+), 73 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index e2e593da3..ecdf8cb05 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -201,25 +201,18 @@ static int sink_get_hw_volume_cb(pa_sink *s) { struct userdata *u = s->userdata; long vol; int err; + int i; assert(u && u->mixer_elem); - if (snd_mixer_selem_has_playback_volume_joined(u->mixer_elem)) { - err = snd_mixer_selem_get_playback_volume(u->mixer_elem, 0, &vol); + for (i = 0;i < s->hw_volume.channels;i++) { + assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); + + err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol); if (err < 0) goto fail; - pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, - (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min)); - } else { - int i; - - for (i = 0;i < s->hw_volume.channels;i++) { - err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol); - if (err < 0) - goto fail; - s->hw_volume.values[i] = - (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min); - } + s->hw_volume.values[i] = + (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min); } return 0; @@ -234,37 +227,25 @@ fail: static int sink_set_hw_volume_cb(pa_sink *s) { struct userdata *u = s->userdata; int err; + int i; pa_volume_t vol; assert(u && u->mixer_elem); - if (snd_mixer_selem_has_playback_volume_joined(u->mixer_elem)) { - vol = pa_cvolume_avg(&s->hw_volume); + for (i = 0;i < s->hw_volume.channels;i++) { + assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); + + vol = s->hw_volume.values[i]; if (vol > PA_VOLUME_NORM) vol = PA_VOLUME_NORM; vol = (vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM + u->hw_volume_min; - - err = snd_mixer_selem_set_playback_volume_all(u->mixer_elem, vol); + + err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, vol); if (err < 0) goto fail; - } else { - int i; - - for (i = 0;i < s->hw_volume.channels;i++) { - vol = s->hw_volume.values[i]; - - if (vol > PA_VOLUME_NORM) - vol = PA_VOLUME_NORM; - - vol = (vol * (u->hw_volume_max - u->hw_volume_min)) / - PA_VOLUME_NORM + u->hw_volume_min; - err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, vol); - if (err < 0) - goto fail; - } } return 0; @@ -383,10 +364,19 @@ int pa__init(pa_core *c, pa_module*m) { if (u->mixer_handle) { assert(u->mixer_elem); if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) { - u->sink->get_hw_volume = sink_get_hw_volume_cb; - u->sink->set_hw_volume = sink_set_hw_volume_cb; - snd_mixer_selem_get_playback_volume_range( - u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); + int i; + + for (i = 0;i < ss.channels;i++) { + if (!snd_mixer_selem_has_playback_channel(u->mixer_elem, i)) + break; + } + + if (i == ss.channels) { + u->sink->get_hw_volume = sink_get_hw_volume_cb; + u->sink->set_hw_volume = sink_set_hw_volume_cb; + snd_mixer_selem_get_playback_volume_range( + u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); + } } if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) { u->sink->get_hw_mute = sink_get_hw_mute_cb; diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 2ee16190e..7a3652866 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -190,25 +190,18 @@ static int source_get_hw_volume_cb(pa_source *s) { struct userdata *u = s->userdata; long vol; int err; + int i; assert(u && u->mixer_elem); - if (snd_mixer_selem_has_capture_volume_joined(u->mixer_elem)) { - err = snd_mixer_selem_get_capture_volume(u->mixer_elem, 0, &vol); + for (i = 0;i < s->hw_volume.channels;i++) { + assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i)); + + err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol); if (err < 0) goto fail; - pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, - (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min)); - } else { - int i; - - for (i = 0;i < s->hw_volume.channels;i++) { - err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol); - if (err < 0) - goto fail; - s->hw_volume.values[i] = - (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min); - } + s->hw_volume.values[i] = + (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min); } return 0; @@ -224,35 +217,23 @@ static int source_set_hw_volume_cb(pa_source *s) { struct userdata *u = s->userdata; int err; pa_volume_t vol; + int i; assert(u && u->mixer_elem); - if (snd_mixer_selem_has_capture_volume_joined(u->mixer_elem)) { - vol = pa_cvolume_avg(&s->hw_volume); + for (i = 0;i < s->hw_volume.channels;i++) { + assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i)); + + vol = s->hw_volume.values[i]; if (vol > PA_VOLUME_NORM) vol = PA_VOLUME_NORM; vol = vol * (u->hw_volume_max - u->hw_volume_min) / PA_VOLUME_NORM + u->hw_volume_min; - err = snd_mixer_selem_set_capture_volume_all(u->mixer_elem, vol); + err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, vol); if (err < 0) goto fail; - } else { - int i; - - for (i = 0;i < s->hw_volume.channels;i++) { - vol = s->hw_volume.values[i]; - - if (vol > PA_VOLUME_NORM) - vol = PA_VOLUME_NORM; - - vol = vol * (u->hw_volume_max - u->hw_volume_min) / - PA_VOLUME_NORM + u->hw_volume_min; - err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, vol); - if (err < 0) - goto fail; - } } return 0; @@ -372,10 +353,19 @@ int pa__init(pa_core *c, pa_module*m) { if (u->mixer_handle) { assert(u->mixer_elem); if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) { - u->source->get_hw_volume = source_get_hw_volume_cb; - u->source->set_hw_volume = source_set_hw_volume_cb; - snd_mixer_selem_get_capture_volume_range( - u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); + int i; + + for (i = 0;i < ss.channels;i++) { + if (!snd_mixer_selem_has_capture_channel(u->mixer_elem, i)) + break; + } + + if (i == ss.channels) { + u->source->get_hw_volume = source_get_hw_volume_cb; + u->source->set_hw_volume = source_set_hw_volume_cb; + snd_mixer_selem_get_capture_volume_range( + u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); + } } if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) { u->source->get_hw_mute = source_get_hw_mute_cb; From 129853f9a438c3522938736a99a3a192abd75d06 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 25 Apr 2006 07:55:14 +0000 Subject: [PATCH 0703/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@797 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/todo b/doc/todo index bd8145fbb..99a86be9b 100644 --- a/doc/todo +++ b/doc/todo @@ -14,6 +14,8 @@ Post 0.8: - rtp module ported to Win32 (sendmsg/recvmsg emulation) - CODECs to reduce bandwidth usage (plug-in based) - Remove symdef files and use macros (like most other projects) +- use software volume when hardware doesn't support all channels (alsa done) +- double check channel maps for backends, including that mixer and pcm match Long term: - pass meta info for hearing impaired From 31ad62fa4d464f4298bc8e1ad6fbe4b3c03115fa Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 26 Apr 2006 09:38:33 +0000 Subject: [PATCH 0704/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@798 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/todo b/doc/todo index 99a86be9b..f778d61c7 100644 --- a/doc/todo +++ b/doc/todo @@ -16,6 +16,9 @@ Post 0.8: - Remove symdef files and use macros (like most other projects) - use software volume when hardware doesn't support all channels (alsa done) - double check channel maps for backends, including that mixer and pcm match +- paplay needs to set a channel map. our default is only correct for AIFF. + (for maximum compatiblity, we should let old files, which don't have a + well defined channel map, use the ALSA channel map) Long term: - pass meta info for hearing impaired From 195e96912f062b3faa93547dde014c45ccb74628 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 14:33:45 +0000 Subject: [PATCH 0705/1514] * add new function pa_channel_map_parse() * increase PA_CHANNEL_MAP_SNPRINT_MAX * add "top" channel positions git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@799 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.c | 144 ++++++++++++++++++++++++++++++----------- src/polyp/channelmap.h | 15 ++++- 2 files changed, 122 insertions(+), 37 deletions(-) diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index bb47deb85..8d642a068 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -28,8 +28,57 @@ #include #include +#include +#include #include "channelmap.h" +const char *const table[] = { + [PA_CHANNEL_POSITION_MONO] = "mono", + + [PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center", + [PA_CHANNEL_POSITION_FRONT_LEFT] = "front-left", + [PA_CHANNEL_POSITION_FRONT_RIGHT] = "front-right", + + [PA_CHANNEL_POSITION_REAR_CENTER] = "rear-center", + [PA_CHANNEL_POSITION_REAR_LEFT] = "rear-left", + [PA_CHANNEL_POSITION_REAR_RIGHT] = "rear-right", + + [PA_CHANNEL_POSITION_LFE] = "lfe", + + [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "front-left-of-center", + [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "front-right-of-center", + + [PA_CHANNEL_POSITION_SIDE_LEFT] = "side-left", + [PA_CHANNEL_POSITION_SIDE_RIGHT] = "side-right", + + [PA_CHANNEL_POSITION_AUX0] = "aux0", + [PA_CHANNEL_POSITION_AUX1] = "aux1", + [PA_CHANNEL_POSITION_AUX2] = "aux2", + [PA_CHANNEL_POSITION_AUX3] = "aux3", + [PA_CHANNEL_POSITION_AUX4] = "aux4", + [PA_CHANNEL_POSITION_AUX5] = "aux5", + [PA_CHANNEL_POSITION_AUX6] = "aux6", + [PA_CHANNEL_POSITION_AUX7] = "aux7", + [PA_CHANNEL_POSITION_AUX8] = "aux8", + [PA_CHANNEL_POSITION_AUX9] = "aux9", + [PA_CHANNEL_POSITION_AUX10] = "aux10", + [PA_CHANNEL_POSITION_AUX11] = "aux11", + [PA_CHANNEL_POSITION_AUX12] = "aux12", + [PA_CHANNEL_POSITION_AUX13] = "aux13", + [PA_CHANNEL_POSITION_AUX14] = "aux14", + [PA_CHANNEL_POSITION_AUX15] = "aux15", + + [PA_CHANNEL_POSITION_TOP_CENTER] = "top-center", + + [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "top-front-left", + [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "top-front-right", + [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center", + + [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = "top-rear-left", + [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "top-rear-right", + [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "top-rear-center" +}; + pa_channel_map* pa_channel_map_init(pa_channel_map *m) { unsigned c; assert(m); @@ -117,41 +166,9 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels) { } } + const char* pa_channel_position_to_string(pa_channel_position_t pos) { - const char *const table[] = { - [PA_CHANNEL_POSITION_MONO] = "mono", - - [PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center", - [PA_CHANNEL_POSITION_FRONT_LEFT] = "front-left", - [PA_CHANNEL_POSITION_FRONT_RIGHT] = "front-right", - - [PA_CHANNEL_POSITION_REAR_CENTER] = "rear-center", - [PA_CHANNEL_POSITION_REAR_LEFT] = "rear-left", - [PA_CHANNEL_POSITION_REAR_RIGHT] = "rear-right", - - [PA_CHANNEL_POSITION_LFE] = "lfe", - - [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "front-left-of-center", - [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "front-right-of-center", - - [PA_CHANNEL_POSITION_SIDE_LEFT] = "side-left", - [PA_CHANNEL_POSITION_SIDE_RIGHT] = "side-right", - - [PA_CHANNEL_POSITION_AUX1] = "aux1", - [PA_CHANNEL_POSITION_AUX2] = "aux2", - [PA_CHANNEL_POSITION_AUX3] = "aux3", - [PA_CHANNEL_POSITION_AUX4] = "aux4", - [PA_CHANNEL_POSITION_AUX5] = "aux5", - [PA_CHANNEL_POSITION_AUX6] = "aux6", - [PA_CHANNEL_POSITION_AUX7] = "aux7", - [PA_CHANNEL_POSITION_AUX8] = "aux8", - [PA_CHANNEL_POSITION_AUX9] = "aux9", - [PA_CHANNEL_POSITION_AUX10] = "aux10", - [PA_CHANNEL_POSITION_AUX11] = "aux11", - [PA_CHANNEL_POSITION_AUX12] = "aux12" - }; - if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX) return NULL; @@ -186,9 +203,8 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) { *(e = s) = 0; for (channel = 0; channel < map->channels && l > 1; channel++) { - l -= snprintf(e, l, "%s%u:%s", - first ? "" : " ", - channel, + l -= snprintf(e, l, "%s%s", + first ? "" : ",", pa_channel_position_to_string(map->map[channel])); e = strchr(e, 0); @@ -198,6 +214,61 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) { return s; } +pa_channel_map *pa_channel_map_parse(pa_channel_map *map, const char *s) { + const char *state; + char *p; + + assert(map); + assert(s); + + memset(map, 0, sizeof(pa_channel_map)); + + if (strcmp(s, "stereo") == 0) { + map->channels = 2; + map->map[0] = PA_CHANNEL_POSITION_LEFT; + map->map[1] = PA_CHANNEL_POSITION_RIGHT; + return map; + } + + state = NULL; + map->channels = 0; + + while ((p = pa_split(s, ",", &state))) { + + /* Some special aliases */ + if (strcmp(p, "left") == 0) + map->map[map->channels++] = PA_CHANNEL_POSITION_LEFT; + else if (strcmp(p, "right") == 0) + map->map[map->channels++] = PA_CHANNEL_POSITION_RIGHT; + else if (strcmp(p, "center") == 0) + map->map[map->channels++] = PA_CHANNEL_POSITION_CENTER; + else if (strcmp(p, "subwoofer") == 0) + map->map[map->channels++] = PA_CHANNEL_POSITION_SUBWOOFER; + else { + pa_channel_position_t i; + + for (i = 0; i < PA_CHANNEL_POSITION_MAX; i++) + if (strcmp(p, table[i]) == 0) { + map->map[map->channels++] = i; + break; + } + + if (i >= PA_CHANNEL_POSITION_MAX) { + pa_xfree(p); + return NULL; + } + } + + pa_xfree(p); + } + + if (!map->channels) + return NULL; + + return map; +} + + int pa_channel_map_valid(const pa_channel_map *map) { unsigned c; @@ -212,3 +283,4 @@ int pa_channel_map_valid(const pa_channel_map *map) { return 1; } + diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index bb9f78b11..76380b5f2 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -107,6 +107,16 @@ typedef enum pa_channel_position { PA_CHANNEL_POSITION_AUX14, PA_CHANNEL_POSITION_AUX15, + PA_CHANNEL_POSITION_TOP_CENTER, + + PA_CHANNEL_POSITION_TOP_FRONT_LEFT, + PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, + PA_CHANNEL_POSITION_TOP_FRONT_CENTER, + + PA_CHANNEL_POSITION_TOP_REAR_LEFT, + PA_CHANNEL_POSITION_TOP_REAR_RIGHT, + PA_CHANNEL_POSITION_TOP_REAR_CENTER, + PA_CHANNEL_POSITION_MAX } pa_channel_position_t; @@ -134,11 +144,14 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels); const char* pa_channel_position_to_string(pa_channel_position_t pos); /** The maximum length of strings returned by pa_channel_map_snprint() */ -#define PA_CHANNEL_MAP_SNPRINT_MAX 64 +#define PA_CHANNEL_MAP_SNPRINT_MAX 336 /** Make a humand readable string from the specified channel map */ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map); +/** Parse a channel position list into a channel map structure. \since 0.8.1 */ +pa_channel_map *pa_channel_map_parse(pa_channel_map *map, const char *s); + /** Compare two channel maps. Return 1 if both match. */ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b); From 5f7cc0c870ebe77dd457209503f75d65b35b8014 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 14:34:45 +0000 Subject: [PATCH 0706/1514] add new test 'channelmap-test' git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@800 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 8 +++++++- src/tests/channelmap-test.c | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/tests/channelmap-test.c diff --git a/src/Makefile.am b/src/Makefile.am index 2061b0ca1..fbb14702f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -187,7 +187,8 @@ noinst_PROGRAMS = \ strlist-test \ voltest \ memblockq-test \ - sync-playback + sync-playback \ + channelmap-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -235,6 +236,11 @@ voltest_CFLAGS = $(AM_CFLAGS) voltest_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +channelmap_test_SOURCES = tests/channelmap-test.c +channelmap_test_CFLAGS = $(AM_CFLAGS) +channelmap_test_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la +channelmap_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + cpulimit_test_SOURCES = tests/cpulimit-test.c daemon/cpulimit.c daemon/cpulimit.h cpulimit_test_CFLAGS = $(AM_CFLAGS) cpulimit_test_LDADD = $(AM_LDADD) libpolypcore.la diff --git a/src/tests/channelmap-test.c b/src/tests/channelmap-test.c new file mode 100644 index 000000000..522c136fc --- /dev/null +++ b/src/tests/channelmap-test.c @@ -0,0 +1,25 @@ +/* $Id$ */ + +#include +#include + +#include +#include + +int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { + char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + pa_channel_map map, map2; + + pa_channel_map_init_auto(&map, 5); + + fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map)); + + pa_channel_map_parse(&map2, cm); + + assert(pa_channel_map_equal(&map, &map2)); + + pa_channel_map_parse(&map2, "left,test"); + + + return 0; +} From 292b237e356371f827df7a7a0e52a7152b64bfe0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 15:37:13 +0000 Subject: [PATCH 0707/1514] don't allow channel positions to be specified twice in the same channelmap git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@801 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index 8d642a068..38349bfad 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -277,10 +277,19 @@ int pa_channel_map_valid(const pa_channel_map *map) { if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX) return 0; - for (c = 0; c < map->channels; c++) + for (c = 0; c < map->channels; c++) { + unsigned k; + if (map->map[c] < 0 ||map->map[c] >= PA_CHANNEL_POSITION_MAX) return 0; + /* Don't allow positions to be specified twice */ + for (k = 0; k < c; k++) + if (map->map[k] == map->map[c]) + return 0; + + } + return 1; } From fbb0d1436c5c415e3964d57b0dedaa0d8817c289 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 15:37:44 +0000 Subject: [PATCH 0708/1514] add support for parsing channel maps as module arguments git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@802 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/modargs.c | 47 +++++++++++++++++++++++++++++++++++++++++ src/polypcore/modargs.h | 11 ++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/polypcore/modargs.c b/src/polypcore/modargs.c index 6bd13c3b7..6a02df0a9 100644 --- a/src/polypcore/modargs.c +++ b/src/polypcore/modargs.c @@ -259,3 +259,50 @@ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) { return 0; } + +int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *rmap) { + pa_channel_map map; + const char *cm; + + assert(ma); + assert(rmap); + + map = *rmap; + + if ((cm = pa_modargs_get_value(ma, "channel_map", NULL))) + if (!pa_channel_map_parse(&map, cm)) + return -1; + + if (!pa_channel_map_valid(&map)) + return -1; + + *rmap = map; + return 0; +} + +int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *rss, pa_channel_map *rmap) { + pa_sample_spec ss; + pa_channel_map map; + + assert(ma); + assert(rss); + assert(rmap); + + ss = *rss; + + if (pa_modargs_get_sample_spec(ma, &ss) < 0) + return -1; + + pa_channel_map_init_auto(&map, ss.channels); + + if (pa_modargs_get_channel_map(ma, &map) < 0) + return -1; + + if (map.channels != ss.channels) + return -1; + + *rmap = map; + *rss = ss; + + return 0; +} diff --git a/src/polypcore/modargs.h b/src/polypcore/modargs.h index 47e2d522e..481ead99b 100644 --- a/src/polypcore/modargs.h +++ b/src/polypcore/modargs.h @@ -24,6 +24,7 @@ #include #include +#include #include typedef struct pa_modargs pa_modargs; @@ -46,4 +47,14 @@ int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value); /* Return sample spec data from the three arguments "rate", "format" and "channels" */ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *ss); +/* Return channel map data from the argument "channel_map" */ +int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *map); + +/* Combination of pa_modargs_get_sample_spec() and +pa_modargs_get_channel_map(). Not always suitable, since this routine +initializes the map parameter based on the channels field of the ss +structure if no channel_map is found, using pa_channel_map_init_auto() */ + +int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *ss, pa_channel_map *map); + #endif From 185a57cadd7b4e8e85c7fbecc866d7c279704e12 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 15:40:14 +0000 Subject: [PATCH 0709/1514] support new channel_map argument in sink/source modules git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@803 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 16 +++++++++++--- src/modules/module-alsa-source.c | 16 +++++++++++--- src/modules/module-combine.c | 38 +++++++++++++++++++++++++++++--- src/modules/module-jack-sink.c | 19 ++++++++++------ src/modules/module-jack-source.c | 17 +++++++++----- src/modules/module-null-sink.c | 15 +++++++++---- src/modules/module-oss-mmap.c | 15 ++++++++----- src/modules/module-oss.c | 13 ++++++----- src/modules/module-pipe-sink.c | 14 +++++++++--- src/modules/module-pipe-source.c | 16 ++++++++++---- src/modules/module-tunnel.c | 28 ++++++++++++++++++----- 11 files changed, 158 insertions(+), 49 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index ecdf8cb05..2c2f1f3e4 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -50,7 +50,15 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ALSA Sink") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= device= format= channels= rate= fragments= fragment_size=") +PA_MODULE_USAGE( + "sink_name= " + "device= " + "format= " + "channels= " + "rate= " + "fragments= " + "fragment_size= " + "channel_map=") struct userdata { snd_pcm_t *pcm_handle; @@ -74,6 +82,7 @@ static const char* const valid_modargs[] = { "rate", "fragments", "fragment_size", + "channel_map", NULL }; @@ -299,6 +308,7 @@ int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; const char *dev; pa_sample_spec ss; + pa_channel_map map; uint32_t periods, fragsize; snd_pcm_uframes_t period_size; size_t frame_size; @@ -311,7 +321,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } @@ -357,7 +367,7 @@ int pa__init(pa_core *c, pa_module*m) { u->mixer_handle = NULL; } - u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 7a3652866..e49389173 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -50,7 +50,15 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ALSA Source") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("source_name= device= format= channels= rate= fragments= fragment_size=") +PA_MODULE_USAGE( + "source_name= " + "device= " + "format= " + "channels= " + "rate= " + "fragments= " + "fragment_size= " + "channel_map=") struct userdata { snd_pcm_t *pcm_handle; @@ -74,6 +82,7 @@ static const char* const valid_modargs[] = { "format", "fragments", "fragment_size", + "channel_map", NULL }; @@ -287,6 +296,7 @@ int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; const char *dev; pa_sample_spec ss; + pa_channel_map map; unsigned periods, fragsize; snd_pcm_uframes_t period_size; size_t frame_size; @@ -299,7 +309,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } @@ -345,7 +355,7 @@ int pa__init(pa_core *c, pa_module*m) { u->mixer_handle = NULL; } - u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map); assert(u->source); u->source->userdata = u; diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 801539004..543fffa4a 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -42,7 +42,16 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Combine multiple sinks to one") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= master= slaves= adjust_time= resample_method=") +PA_MODULE_USAGE( + "sink_name= " + "master= " + "slaves= " + "adjust_time= " + "resample_method= " + "format= " + "channels= " + "rate= " + "channel_map= ") #define DEFAULT_SINK_NAME "combined" #define MEMBLOCKQ_MAXLENGTH (1024*170) @@ -56,6 +65,10 @@ static const char* const valid_modargs[] = { "slaves", "adjust_time", "resample_method", + "format", + "channels", + "rate", + "channel_map", NULL }; @@ -296,6 +309,9 @@ int pa__init(pa_core *c, pa_module*m) { const char*split_state; struct timeval tv; int resample_method = -1; + pa_sample_spec ss; + pa_channel_map map; + assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -310,7 +326,7 @@ int pa__init(pa_core *c, pa_module*m) { } } - u = pa_xmalloc(sizeof(struct userdata)); + u = pa_xnew(struct userdata, 1); m->userdata = u; u->sink = NULL; u->n_outputs = 0; @@ -336,7 +352,23 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec, &master_sink->channel_map))) { + ss = master_sink->sample_spec; + if ((pa_modargs_get_sample_spec(ma, &ss) < 0)) { + pa_log(__FILE__": invalid sample specification."); + goto fail; + } + + if (ss.channels == master_sink->sample_spec.channels) + map = master_sink->channel_map; + else + pa_channel_map_init_auto(&map, ss.channels); + + if ((pa_modargs_get_channel_map(ma, &map) < 0)) { + pa_log(__FILE__": invalid channel map."); + goto fail; + } + + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { pa_log(__FILE__": failed to create sink"); goto fail; } diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index f340ab6d2..090305303 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -55,8 +55,8 @@ PA_MODULE_USAGE( "server_name= " "client_name= " "channels= " - "connect=" -) + "connect= " + "channel_map=") #define DEFAULT_SINK_NAME "jack_out" @@ -91,6 +91,7 @@ static const char* const valid_modargs[] = { "client_name", "channels", "connect", + "channel_map", NULL }; @@ -233,7 +234,7 @@ static void jack_error_func(const char*t) { int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; - pa_channel_map cm; + pa_channel_map map; pa_modargs *ma = NULL; jack_status_t status; const char *server_name, *client_name; @@ -294,6 +295,12 @@ int pa__init(pa_core *c, pa_module*m) { pa_log(__FILE__": failed to parse channels= argument."); goto fail; } + + pa_channel_map_init_auto(&map, channels); + if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) { + pa_log(__FILE__": failed to parse channel_map= argument."); + goto fail; + } pa_log_info(__FILE__": Successfully connected as '%s'", jack_get_client_name(u->client)); @@ -303,16 +310,14 @@ int pa__init(pa_core *c, pa_module*m) { assert(pa_sample_spec_valid(&ss)); - pa_channel_map_init_auto(&cm, channels); - for (i = 0; i < ss.channels; i++) { - if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(cm.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0))) { + if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(map.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0))) { pa_log(__FILE__": jack_port_register() failed."); goto fail; } } - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &cm))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { pa_log(__FILE__": failed to create sink."); goto fail; } diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 5f0e560d5..ad39b9ddc 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -56,7 +56,7 @@ PA_MODULE_USAGE( "client_name= " "channels= " "connect=" -) + "channel_map=") #define DEFAULT_SOURCE_NAME "jack_in" @@ -91,6 +91,7 @@ static const char* const valid_modargs[] = { "client_name", "channels", "connect", + "channel_map", NULL }; @@ -231,7 +232,7 @@ static void jack_error_func(const char*t) { int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; - pa_channel_map cm; + pa_channel_map map; pa_modargs *ma = NULL; jack_status_t status; const char *server_name, *client_name; @@ -292,6 +293,12 @@ int pa__init(pa_core *c, pa_module*m) { pa_log(__FILE__": failed to parse channels= argument."); goto fail; } + + pa_channel_map_init_auto(&map, channels); + if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) { + pa_log(__FILE__": failed to parse channel_map= argument."); + goto fail; + } pa_log_info(__FILE__": Successfully connected as '%s'", jack_get_client_name(u->client)); @@ -301,16 +308,14 @@ int pa__init(pa_core *c, pa_module*m) { assert(pa_sample_spec_valid(&ss)); - pa_channel_map_init_auto(&cm, channels); - for (i = 0; i < ss.channels; i++) { - if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(cm.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput|JackPortIsTerminal, 0))) { + if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(map.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput|JackPortIsTerminal, 0))) { pa_log(__FILE__": jack_port_register() failed."); goto fail; } } - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &cm))) { + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { pa_log(__FILE__": failed to create source."); goto fail; } diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 611782399..9c564429c 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -46,7 +46,12 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Clocked NULL sink") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("format= channels= rate= sink_name=") +PA_MODULE_USAGE( + "format= " + "channels= " + "rate= " + "sink_name=" + "channel_map=") #define DEFAULT_SINK_NAME "null" @@ -63,6 +68,7 @@ static const char* const valid_modargs[] = { "format", "channels", "sink_name", + "channel_map", NULL }; @@ -87,6 +93,7 @@ static void time_callback(pa_mainloop_api *m, pa_time_event*e, const struct time int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; + pa_channel_map map; pa_modargs *ma = NULL; struct timeval tv; assert(c && m); @@ -97,8 +104,8 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": invalid sample format specification."); + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + pa_log(__FILE__": invalid sample format specification or channel map."); goto fail; } @@ -107,7 +114,7 @@ int pa__init(pa_core *c, pa_module*m) { u->module = m; m->userdata = u; - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { pa_log(__FILE__": failed to create sink."); goto fail; } diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index c487f40c3..e032ce466 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -62,7 +62,8 @@ PA_MODULE_USAGE( "channels= " "rate= " "fragments= " - "fragment_size=") + "fragment_size= " + "channel_map=") struct userdata { pa_sink *sink; @@ -97,6 +98,7 @@ static const char* const valid_modargs[] = { "format", "rate", "channels", + "channel_map", NULL }; @@ -346,7 +348,8 @@ int pa__init(pa_core *c, pa_module*m) { int playback = 1, record = 1; pa_modargs *ma = NULL; char hwdesc[64]; - + pa_channel_map map; + assert(c); assert(m); @@ -380,8 +383,8 @@ int pa__init(pa_core *c, pa_module*m) { } u->sample_spec = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &u->sample_spec) < 0) { - pa_log(__FILE__": failed to parse sample specification"); + if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->sample_spec, &map) < 0) { + pa_log(__FILE__": failed to parse sample specification or channel map"); goto fail; } @@ -426,7 +429,7 @@ int pa__init(pa_core *c, pa_module*m) { } } else { - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec, NULL))) + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec, &map))) goto fail; u->source->userdata = u; @@ -466,7 +469,7 @@ int pa__init(pa_core *c, pa_module*m) { } else { pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec, NULL))) + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec, &map))) goto fail; u->sink->get_latency = sink_get_latency_cb; diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index ccc3c7d98..0795ae39a 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -61,7 +61,8 @@ PA_MODULE_USAGE( "channels= " "rate= " "fragments= " - "fragment_size=") + "fragment_size= " + "channel_map=") struct userdata { pa_sink *sink; @@ -89,6 +90,7 @@ static const char* const valid_modargs[] = { "format", "rate", "channels", + "channel_map", NULL }; @@ -322,6 +324,7 @@ int pa__init(pa_core *c, pa_module*m) { int mode; int record = 1, playback = 1; pa_sample_spec ss; + pa_channel_map map; pa_modargs *ma = NULL; char hwdesc[64]; @@ -353,8 +356,8 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": failed to parse sample specification"); + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + pa_log(__FILE__": failed to parse sample specification or channel map"); goto fail; } @@ -399,7 +402,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (mode != O_WRONLY) { - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) goto fail; u->source->userdata = u; @@ -417,7 +420,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source = NULL; if (mode != O_RDONLY) { - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) goto fail; u->sink->get_latency = sink_get_latency_cb; diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 4ddf26acb..2be1b297b 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -46,7 +46,13 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("UNIX pipe sink") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= file= format= channels= rate=") +PA_MODULE_USAGE( + "sink_name= " + "file= " + "format= " + "channels= " + "rate=" + "channel_map=") #define DEFAULT_FIFO_NAME "/tmp/music.output" #define DEFAULT_SINK_NAME "fifo_output" @@ -70,6 +76,7 @@ static const char* const valid_modargs[] = { "format", "channels", "sink_name", + "channel_map", NULL }; @@ -137,6 +144,7 @@ int pa__init(pa_core *c, pa_module*m) { const char *p; int fd = -1; pa_sample_spec ss; + pa_channel_map map; pa_modargs *ma = NULL; assert(c && m); @@ -146,7 +154,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { pa_log(__FILE__": invalid sample format specification"); goto fail; } @@ -176,7 +184,7 @@ int pa__init(pa_core *c, pa_module*m) { u->module = m; m->userdata = u; - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { pa_log(__FILE__": failed to create sink."); goto fail; } diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index d3753d25c..c80bfd093 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -46,7 +46,13 @@ PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("UNIX pipe source") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("source_name= file= format= channels= rate=") +PA_MODULE_USAGE( + "source_name= " + "file= " + "format= " + "channels= " + "rate= " + "channel_map=") #define DEFAULT_FIFO_NAME "/tmp/music.input" #define DEFAULT_SOURCE_NAME "fifo_input" @@ -68,6 +74,7 @@ static const char* const valid_modargs[] = { "channels", "format", "source_name", + "channel_map", NULL }; @@ -115,6 +122,7 @@ int pa__init(pa_core *c, pa_module*m) { const char *p; int fd = -1; pa_sample_spec ss; + pa_channel_map map; pa_modargs *ma = NULL; assert(c && m); @@ -124,8 +132,8 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": invalid sample format specification"); + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + pa_log(__FILE__": invalid sample format specification or channel map"); goto fail; } @@ -153,7 +161,7 @@ int pa__init(pa_core *c, pa_module*m) { u->filename = pa_xstrdup(p); u->core = c; - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) { + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { pa_log(__FILE__": failed to create source."); goto fail; } diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index abfa68a41..bffcc7c0c 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -51,11 +51,27 @@ #ifdef TUNNEL_SINK #include "module-tunnel-sink-symdef.h" PA_MODULE_DESCRIPTION("Tunnel module for sinks") -PA_MODULE_USAGE("server=
    sink= cookie= format= channels= rate= sink_name=") +PA_MODULE_USAGE( + "server=
    " + "sink= " + "cookie= " + "format= " + "channels= " + "rate= " + "sink_name= " + "channel_map=") #else #include "module-tunnel-source-symdef.h" PA_MODULE_DESCRIPTION("Tunnel module for sources") -PA_MODULE_USAGE("server=
    source= cookie= format= channels= rate= source_name=") +PA_MODULE_USAGE( + "server=
    " + "source= " + "cookie= " + "format= " + "channels= " + "rate= " + "source_name= " + "channel_map=") #endif PA_MODULE_AUTHOR("Lennart Poettering") @@ -87,6 +103,7 @@ static const char* const valid_modargs[] = { "source_name", "source", #endif + "channel_map", NULL, }; @@ -838,6 +855,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; struct userdata *u = NULL; pa_sample_spec ss; + pa_channel_map map; struct timeval ntv; assert(c && m); @@ -877,7 +895,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { pa_log(__FILE__": invalid sample format specification"); goto fail; } @@ -893,7 +911,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_socket_client_set_callback(u->client, on_connection, u); #ifdef TUNNEL_SINK - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { pa_log(__FILE__": failed to create sink."); goto fail; } @@ -909,7 +927,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_sink_set_owner(u->sink, m); #else - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) { + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { pa_log(__FILE__": failed to create source."); goto fail; } From c478b0f11867cda279d41135a97336f6976007ae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 16:07:05 +0000 Subject: [PATCH 0710/1514] * make a validity check of parsed channel maps before rteurning theme * don't overwrite the return buffer unless the parsed channel map is known to be valid git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@804 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index 38349bfad..afe56170d 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -214,42 +214,48 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) { return s; } -pa_channel_map *pa_channel_map_parse(pa_channel_map *map, const char *s) { +pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) { const char *state; + pa_channel_map map; char *p; - assert(map); + assert(rmap); assert(s); - memset(map, 0, sizeof(pa_channel_map)); + memset(&map, 0, sizeof(map)); if (strcmp(s, "stereo") == 0) { - map->channels = 2; - map->map[0] = PA_CHANNEL_POSITION_LEFT; - map->map[1] = PA_CHANNEL_POSITION_RIGHT; - return map; + map.channels = 2; + map.map[0] = PA_CHANNEL_POSITION_LEFT; + map.map[1] = PA_CHANNEL_POSITION_RIGHT; + goto finish; } state = NULL; - map->channels = 0; + map.channels = 0; while ((p = pa_split(s, ",", &state))) { + + if (map.channels >= PA_CHANNELS_MAX) { + pa_xfree(p); + return NULL; + } /* Some special aliases */ if (strcmp(p, "left") == 0) - map->map[map->channels++] = PA_CHANNEL_POSITION_LEFT; + map.map[map.channels++] = PA_CHANNEL_POSITION_LEFT; else if (strcmp(p, "right") == 0) - map->map[map->channels++] = PA_CHANNEL_POSITION_RIGHT; + map.map[map.channels++] = PA_CHANNEL_POSITION_RIGHT; else if (strcmp(p, "center") == 0) - map->map[map->channels++] = PA_CHANNEL_POSITION_CENTER; + map.map[map.channels++] = PA_CHANNEL_POSITION_CENTER; else if (strcmp(p, "subwoofer") == 0) - map->map[map->channels++] = PA_CHANNEL_POSITION_SUBWOOFER; + map.map[map.channels++] = PA_CHANNEL_POSITION_SUBWOOFER; else { pa_channel_position_t i; for (i = 0; i < PA_CHANNEL_POSITION_MAX; i++) if (strcmp(p, table[i]) == 0) { - map->map[map->channels++] = i; + map.map[map.channels++] = i; break; } @@ -262,13 +268,15 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *map, const char *s) { pa_xfree(p); } - if (!map->channels) +finish: + + if (!pa_channel_map_valid(&map)) return NULL; - - return map; + + *rmap = map; + return rmap; } - int pa_channel_map_valid(const pa_channel_map *map) { unsigned c; From c3cc14153a2f519b2333400bfa942f70bca58c95 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 16:07:33 +0000 Subject: [PATCH 0711/1514] allow specifying the channel map to use on the command line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@805 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index cce974423..a823c88b9 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -66,6 +66,9 @@ static pa_sample_spec sample_spec = { .channels = 2 }; +static pa_channel_map channel_map; +static int channel_map_set = 0; + /* A shortcut for terminating the application */ static void quit(int ret) { assert(mainloop_api); @@ -184,7 +187,7 @@ static void context_state_callback(pa_context *c, void *userdata) { if (verbose) fprintf(stderr, "Connection established.\n"); - if (!(stream = pa_stream_new(c, stream_name, &sample_spec, NULL))) { + if (!(stream = pa_stream_new(c, stream_name, &sample_spec, channel_map_set ? &channel_map : NULL))) { fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } @@ -405,7 +408,8 @@ static void help(const char *argv0) { " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" " float32be, ulaw, alaw (defaults to s16ne)\n" " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" - " (defaults to 2)\n", + " (defaults to 2)\n" + " --channel-map=CHANNELMAP Channel map to use instead of the default\n", argv0); } @@ -415,7 +419,8 @@ enum { ARG_VOLUME, ARG_SAMPLERATE, ARG_SAMPLEFORMAT, - ARG_CHANNELS + ARG_CHANNELS, + ARG_CHANNELMAP, }; int main(int argc, char *argv[]) { @@ -438,6 +443,7 @@ int main(int argc, char *argv[]) { {"rate", 1, NULL, ARG_SAMPLERATE}, {"format", 1, NULL, ARG_SAMPLEFORMAT}, {"channels", 1, NULL, ARG_CHANNELS}, + {"channel-map", 1, NULL, ARG_CHANNELMAP}, {NULL, 0, NULL, 0} }; @@ -514,6 +520,16 @@ int main(int argc, char *argv[]) { sample_spec.rate = atoi(optarg); break; + case ARG_CHANNELMAP: + + if (!pa_channel_map_parse(&channel_map, optarg)) { + fprintf(stderr, "Invalid channel map\n"); + goto quit; + } + + channel_map_set = 1; + break; + default: goto quit; } @@ -529,6 +545,11 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Invalid sample specification\n"); goto quit; } + + if (channel_map_set && channel_map.channels != sample_spec.channels) { + fprintf(stderr, "Channel map doesn't match sample specification\n"); + goto quit; + } if (verbose) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; From d4bad65e22d03a788c0e04ff90ec306d59caf9dc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 16:27:01 +0000 Subject: [PATCH 0712/1514] it was a bad idea to require that a channel map doesn't contain the same position twice git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@806 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index afe56170d..794711ae3 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -286,16 +286,10 @@ int pa_channel_map_valid(const pa_channel_map *map) { return 0; for (c = 0; c < map->channels; c++) { - unsigned k; if (map->map[c] < 0 ||map->map[c] >= PA_CHANNEL_POSITION_MAX) return 0; - /* Don't allow positions to be specified twice */ - for (k = 0; k < c; k++) - if (map->map[k] == map->map[c]) - return 0; - } return 1; From 7b8390459b12081a2c3ae079d1acfb1fd93f1114 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 16:27:33 +0000 Subject: [PATCH 0713/1514] if a sample is not yet loaded, don't print rubbish about its channel map git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@807 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/cli-text.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polypcore/cli-text.c b/src/polypcore/cli-text.c index d31d09c51..74de57816 100644 --- a/src/polypcore/cli-text.c +++ b/src/polypcore/cli-text.c @@ -280,7 +280,7 @@ char *pa_scache_list_to_string(pa_core *c) { for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) { double l = 0; - char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX] = "n/a"; if (e->memchunk.memblock) { pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec); From d78e466a2839ac9d71993cf069f7df4360ecea1e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 16:27:59 +0000 Subject: [PATCH 0714/1514] fix volume range printed on --help git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@808 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index a823c88b9..1ecc0db29 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -403,7 +403,7 @@ static void help(const char *argv0) { " -d, --device=DEVICE The name of the sink/source to connect to\n" " -n, --client-name=NAME How to call this client on the server\n" " --stream-name=NAME How to call this stream on the server\n" - " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n" + " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" " --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n" " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" " float32be, ulaw, alaw (defaults to s16ne)\n" @@ -521,7 +521,6 @@ int main(int argc, char *argv[]) { break; case ARG_CHANNELMAP: - if (!pa_channel_map_parse(&channel_map, optarg)) { fprintf(stderr, "Invalid channel map\n"); goto quit; From c27b1407f8197230136158eae2aeb75f526a12f3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 16:28:29 +0000 Subject: [PATCH 0715/1514] allow the user to specify an alternative channel map in paplay too git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@809 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/paplay.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 4efb4cf66..7f665413f 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -53,7 +53,9 @@ static pa_volume_t volume = PA_VOLUME_NORM; static SNDFILE* sndfile = NULL; -static pa_sample_spec sample_spec = { 0, 0, 0 }; +static pa_sample_spec sample_spec = { 0, 0, 0 }; +static pa_channel_map channel_map; +static int channel_map_set = 0; static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames); @@ -161,7 +163,7 @@ static void context_state_callback(pa_context *c, void *userdata) { if (verbose) fprintf(stderr, "Connection established.\n"); - stream = pa_stream_new(c, stream_name, &sample_spec, NULL); + stream = pa_stream_new(c, stream_name, &sample_spec, channel_map_set ? &channel_map : NULL); assert(stream); pa_stream_set_state_callback(stream, stream_state_callback, NULL); @@ -200,14 +202,16 @@ static void help(const char *argv0) { " -d, --device=DEVICE The name of the sink/source to connect to\n" " -n, --client-name=NAME How to call this client on the server\n" " --stream-name=NAME How to call this stream on the server\n" - " --volume=VOLUME Specify the initial (linear) volume in range 0...256\n", + " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" + " --channel-map=CHANNELMAP Set the channel map to the use\n", argv0); } enum { ARG_VERSION = 256, ARG_STREAM_NAME, - ARG_VOLUME + ARG_VOLUME, + ARG_CHANNELMAP }; int main(int argc, char *argv[]) { @@ -226,6 +230,7 @@ int main(int argc, char *argv[]) { {"help", 0, NULL, 'h'}, {"verbose", 0, NULL, 'v'}, {"volume", 1, NULL, ARG_VOLUME}, + {"channel-map", 1, NULL, ARG_CHANNELMAP}, {NULL, 0, NULL, 0} }; @@ -277,6 +282,15 @@ int main(int argc, char *argv[]) { break; } + case ARG_CHANNELMAP: + if (!pa_channel_map_parse(&channel_map, optarg)) { + fprintf(stderr, "Invalid channel map\n"); + goto quit; + } + + channel_map_set = 1; + break; + default: goto quit; } @@ -322,6 +336,13 @@ int main(int argc, char *argv[]) { break; } + assert(pa_sample_spec_valid(&sample_spec)); + + if (channel_map_set && channel_map.channels != sample_spec.channels) { + fprintf(stderr, "Channel map doesn't match file.\n"); + goto quit; + } + if (verbose) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(t, sizeof(t), &sample_spec); From 9564cefdbf856d9a4ea9d4f3a57a6f53ddcb7085 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 16:50:36 +0000 Subject: [PATCH 0716/1514] fail if the channel map doesn't match the sample specs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@810 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-combine.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 543fffa4a..470104970 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -367,6 +367,11 @@ int pa__init(pa_core *c, pa_module*m) { pa_log(__FILE__": invalid channel map."); goto fail; } + + if (ss.channels != map.channels) { + pa_log(__FILE__": channel map and sample specification don't match."); + goto fail; + } if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { pa_log(__FILE__": failed to create sink"); From dff0822721c87884cd2185ac65c346a284b08542 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 19:24:32 +0000 Subject: [PATCH 0717/1514] bump version number git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@811 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 87dc2aab2..22ab39626 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.8],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.8.1],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) From c29b3f11e271757d60e72480030011913f778878 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Apr 2006 21:31:51 +0000 Subject: [PATCH 0718/1514] doc update for 0.8.1 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@812 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/FAQ.html.in | 48 ++++++++++++++++++++++++++++++++++++++++++++- doc/README.html.in | 19 ++++++++++++++++++ doc/modules.html.in | 17 ++++++++++++++-- 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in index 7adc24414..a042dd7b2 100644 --- a/doc/FAQ.html.in +++ b/doc/FAQ.html.in @@ -224,7 +224,7 @@ load-module module-rtp-recv sink=rtp set-default-source rtp_monitor -

    Now the audio data will be available from the default source rtp_monitor.

    +

    Now the audio data will be available from the default source rtp_monitor.

  • When sending multicast RTP traffic it is recieved on the entire LAN but not by the sender machine itself!

    @@ -237,6 +237,52 @@ the destination/sap_address arguments of the RTP modules to select them. Choose your group addresses from the range 225.0.0.x to make sure the audio data never leaves the LAN.

  • + +
  • Can I use Polypaudio to playback music on two sound cards simultaneously?

    + +

    Yes! Use module-combine for that.

    + +
    +load-module module-oss-mmap device="/dev/dsp" sink_name=output0
    +load-module module-oss-mmap device="/dev/dsp1" sink_name=output1
    +load-module module-combine sink_name=combined master=output0 slaves=output1
    +set-sink-default combined
    +
    + +

    This will combine the two sinks output0 and +output1 into a new sink combined. Every sample +written to the latter will be forwarded to the former two. Polypaudio +will make sure to adjust the sample rate of the slave device in case +it deviates from the master device. You can have more than one slave +sink attached to the combined sink, and hence combine even three and +more sound cards.

  • + +
  • Can I use Polypaudio to combine two stereo soundcards into a virtual surround sound card?

    + +

    Yes! You can use use module-combine for that.

    + +
    +load-module module-oss-mmap device="/dev/dsp" sink_name=output0 channel_map=left,right channels=2
    +load-module module-oss-mmap device="/dev/dsp1" sink_name=output1 channel_map=rear-left,rear-right channels=2
    +load-module module-combine sink_name=combined master=output0 slaves=output1 channel_map=left,right,rear-left,rear-right channels=4
    +
    + +

    This is mostly identical to the previous example. However, this +time we manually specify the channel mappings for the sinks to make +sure everything is routed correctly.

    + +

    Please keep in mind that Polypaudio will constantly adjust the +sample rate to compensate for the deviating quartzes of the sound +devices. This is not perfect, however. Deviations in a range of +1/44100s (or 1/48000s depending on the sampling frequency) can not be +compensated. The human ear will decode these deviations as minor +movements (less than 1cm) of the positions of the sound sources +you hear.

    + +
  • + + +
    diff --git a/doc/README.html.in b/doc/README.html.in index 5dec50563..2ed75edf0 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -22,6 +22,7 @@
  • Installation
  • Acknowledgements
  • Download
  • +
  • Community
  • License

    @@ -42,6 +43,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    News

    +
    Wed Apr 26 2006:

    Version 0.8.1 +released; changes include: support for specifying the channel map on +the command lines of paplay and pacat and as +arguments to the driver modules; ALSA hardware mixer compatibility; +fix linking; properly remove PF_UNIX sockets when unloading +protocol modules; fix sample cache; many other fixes

    +
    Thu Apr 13 2006:

    Version 0.8 released; changes include: too many to count - consider reading this blog entry for more information; many, many minor fixes.

    @@ -288,6 +297,10 @@ compilation and make install (as root) for installation of

    Cendio AB for paying for Pierre's work on Polypaudio

    +

    Sebastien ESTIENNE for testing

    + +

    Igor Zubkov for some portability patches

    +

    Download

    The newest release is always available from @PACKAGE_URL@

    @@ -298,10 +311,16 @@ compilation and make install (as root) for installation of
    svn checkout svn://0pointer.de/polypaudio/trunk polypaudio
    +

    Community

    +

    If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

    There is a general discussion mailing list for polypaudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

    +

    Polypaudio is being tracked at CIA.

    + +

    There's a chance to meet the Polypaudio developers on our IRC channel #polypaudio on irc.freenode.org.

    +

    There is a Trac based Wiki for Polypaudio available.

    Please report bugs to our Trac ticket system.

    diff --git a/doc/modules.html.in b/doc/modules.html.in index f7b6298fa..6a6b78875 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -20,7 +20,19 @@ rate=The sample rate (defaults to 44100) channels=Audio channels (defaults to 2) sink_name=, source_name=Name for the sink (resp. source) - + channel_map=Channel map. A list of +comma-seperated channel names. The currently defined channel names +are: left, right, mono, center, +front-left, front-right, front-center, +rear-center, rear-left, rear-right, +lfe, subwoofer, front-left-of-center, +front-right-of-center, side-left, +side-right, aux0, aux1 to aux15, +top-center, top-front-left, +top-front-right, top-front-center, +top-rear-left, top-rear-right, +top-rear-center, (Default depends on the number of channels +and the driver)

    module-pipe-sink

    @@ -118,12 +130,13 @@ compatible as module-oss.

    This module supports all arguments thet module-oss supports except device=.

    +

    module-combine

    This combines two or more sinks into one. A new virtual sink is allocated. All data written to it is forwarded to all connected sinks. In aequidistant intervals the sample rates of the output sinks -is recalculated: i.e. even when the sink's crystals deviate (which is +is recalculated: i.e. even when the sinks' crystals deviate (which is normally the case) output appears synchronously to the human ear. The resampling required for this may be very CPU intensive.

    From 2c08180ec9ce9c7cb0b878a6deabb7fbb7b68128 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 27 Apr 2006 05:26:29 +0000 Subject: [PATCH 0719/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@813 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/todo b/doc/todo index f778d61c7..4d6422861 100644 --- a/doc/todo +++ b/doc/todo @@ -17,8 +17,7 @@ Post 0.8: - use software volume when hardware doesn't support all channels (alsa done) - double check channel maps for backends, including that mixer and pcm match - paplay needs to set a channel map. our default is only correct for AIFF. - (for maximum compatiblity, we should let old files, which don't have a - well defined channel map, use the ALSA channel map) + (we need help from libsndfile for this) Long term: - pass meta info for hearing impaired @@ -29,3 +28,6 @@ Backends for: - sdl - OSS (esddsp style) - gstreamer (needs to be updated) +- fix channel maps in all external backends. Take care when doing volume + changes if you're modifying a sink/source since those might have a different + map. From 0b95438f102be2f0ffdc08ea37a50558a68ce90f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 27 Apr 2006 05:39:11 +0000 Subject: [PATCH 0720/1514] Channel map argument support for waveout. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@814 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index ef602e8d5..34607421b 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -43,7 +43,17 @@ PA_MODULE_AUTHOR("Pierre Ossman") PA_MODULE_DESCRIPTION("Windows waveOut Sink/Source") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= source_name= record= playback= format= channels= rate= fragments= fragment_size=") +PA_MODULE_USAGE( + "sink_name= " + "source_name=" + "record= " + "playback= " + "format= " + "channels= " + "rate= " + "fragments= " + "fragment_size= " + "channel_map=") #define DEFAULT_SINK_NAME "wave_output" #define DEFAULT_SOURCE_NAME "wave_input" @@ -86,6 +96,7 @@ static const char* const valid_modargs[] = { "format", "rate", "channels", + "channel_map", NULL }; @@ -428,6 +439,7 @@ int pa__init(pa_core *c, pa_module*m) { int nfrags, frag_size; int record = 1, playback = 1; pa_sample_spec ss; + pa_channel_map map; pa_modargs *ma = NULL; unsigned int i; struct timeval tv; @@ -457,7 +469,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } @@ -484,7 +496,7 @@ int pa__init(pa_core *c, pa_module*m) { InitializeCriticalSection(&u->crit); if (hwi != INVALID_HANDLE_VALUE) { - u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map); assert(u->source); u->source->userdata = u; u->source->notify = notify_source_cb; @@ -495,7 +507,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source = NULL; if (hwo != INVALID_HANDLE_VALUE) { - u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map); assert(u->sink); u->sink->notify = notify_sink_cb; u->sink->get_latency = sink_get_latency_cb; From 99612dd88dfee3abd072c3138231549594381ee7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 27 Apr 2006 05:41:18 +0000 Subject: [PATCH 0721/1514] Channel map argument support for solaris. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@815 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index e1a03272a..eaac9e6e4 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -57,7 +57,16 @@ PA_MODULE_AUTHOR("Pierre Ossman") PA_MODULE_DESCRIPTION("Solaris Sink/Source") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= source_name= device= record= playback= format= channels= rate= buffer_size=") +PA_MODULE_USAGE( + "sink_name= " + "source_name= " + "device= record= " + "playback= " + "format= " + "channels= " + "rate= " + "buffer_size= " + "channel_map=") struct userdata { pa_sink *sink; @@ -88,6 +97,7 @@ static const char* const valid_modargs[] = { "format", "rate", "channels", + "channel_map", NULL }; @@ -486,6 +496,7 @@ int pa__init(pa_core *c, pa_module*m) { int mode; int record = 1, playback = 1; pa_sample_spec ss; + pa_channel_map map; pa_modargs *ma = NULL; struct timeval tv; assert(c && m); @@ -514,7 +525,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } @@ -535,7 +546,7 @@ int pa__init(pa_core *c, pa_module*m) { u->core = c; if (mode != O_WRONLY) { - u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL); + u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map); assert(u->source); u->source->userdata = u; u->source->get_latency = source_get_latency_cb; @@ -547,7 +558,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source = NULL; if (mode != O_RDONLY) { - u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL); + u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map); assert(u->sink); u->sink->get_latency = sink_get_latency_cb; u->sink->get_hw_volume = sink_get_hw_volume_cb; From 22c679e393b234158b953b04956c886cbf1a2a5d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 27 Apr 2006 05:43:27 +0000 Subject: [PATCH 0722/1514] Clarify how the automatic channel map is generated. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@816 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index 76380b5f2..0fd1e5933 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -137,7 +137,9 @@ pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m); /** Initialize the specified channel map for stereophonic audio and return a pointer to it */ pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m); -/** Initialize the specified channel map for the specified number of channels using default labels and return a pointer to it */ +/** Initialize the specified channel map for the specified number + * of channels using default labels and return a pointer to it. + * Uses the mapping from RFC3551, which is based on AIFF-C. */ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels); /** Return a text label for the specified channel position */ From cd93661dcbe04081617d932058f472bd496ad3d2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Apr 2006 22:59:54 +0000 Subject: [PATCH 0723/1514] ouch! fix brown paperbag bug which was triggered when runnign "pavumeter" and specifying a sink on the command line. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@817 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/namereg.c | 4 ++-- src/polypcore/protocol-native.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/polypcore/namereg.c b/src/polypcore/namereg.c index d4dbd14bb..9229a0f99 100644 --- a/src/polypcore/namereg.c +++ b/src/polypcore/namereg.c @@ -127,7 +127,7 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int a return NULL; if (c->namereg && (e = pa_hashmap_get(c->namereg, name))) - if (e->type == e->type) + if (e->type == type) return e->data; if (pa_atou(name, &idx) < 0) { @@ -136,7 +136,7 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int a pa_autoload_request(c, name, type); if (c->namereg && (e = pa_hashmap_get(c->namereg, name))) - if (e->type == e->type) + if (e->type == type) return e->data; } diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index ace9db6fb..a0fc286da 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -1347,7 +1347,6 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u pa_tagstruct *reply; assert(c && t); - if (pa_tagstruct_getu32(t, &idx) < 0 || (command != PA_COMMAND_GET_CLIENT_INFO && command != PA_COMMAND_GET_MODULE_INFO && From 53930f4455dddc44fd260b151839aef0c76ce433 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 28 Apr 2006 07:28:48 +0000 Subject: [PATCH 0724/1514] Zero the fd list since we do a memcmp on it later. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@818 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index dcc0e0203..8bb33c2f7 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -122,7 +122,7 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u pa_xfree(fdl->fds); if (fdl->work_fds) pa_xfree(fdl->work_fds); - fdl->fds = pa_xmalloc(sizeof(struct pollfd) * num_fds); + fdl->fds = pa_xmalloc0(sizeof(struct pollfd) * num_fds); fdl->work_fds = pa_xmalloc(sizeof(struct pollfd) * num_fds); } From 6060bff186e028dfc2d90ffb69869b93f9ec01f5 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 28 Apr 2006 07:29:32 +0000 Subject: [PATCH 0725/1514] When a control is removed, all bits are set so we need to test for that first. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@819 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 3 +++ src/modules/module-alsa-source.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 2c2f1f3e4..84b506e16 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -168,6 +168,9 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { assert(u && u->mixer_handle); + if (mask == SND_CTL_EVENT_MASK_REMOVE) + return 0; + if (mask & SND_CTL_EVENT_MASK_VALUE) { if (u->sink->get_hw_volume) u->sink->get_hw_volume(u->sink); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index e49389173..84ae992bb 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -168,6 +168,9 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { assert(u && u->mixer_handle); + if (mask == SND_CTL_EVENT_MASK_REMOVE) + return 0; + if (mask & SND_CTL_EVENT_MASK_VALUE) { if (u->source->get_hw_volume) u->source->get_hw_volume(u->source); From 19c9dbf3614ba911b7d831f362ac04598226a83d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 28 Apr 2006 11:33:22 +0000 Subject: [PATCH 0726/1514] fix date git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@820 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README.html.in b/doc/README.html.in index 2ed75edf0..5c6e49a76 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -43,7 +43,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    News

    -
    Wed Apr 26 2006:

    Fri Apr 28 2006:

    Version 0.8.1 released; changes include: support for specifying the channel map on the command lines of paplay and pacat and as From f2fbceb333421afb98c7d63b8f417bb43442e80f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 30 Apr 2006 23:33:04 +0000 Subject: [PATCH 0727/1514] * make sure the wakeup fd is polled on wven when no other fd is registered for polling * initialize mainloop return value to -1 * some optimizations git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@822 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/mainloop.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 42a411d34..98b3f3c69 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -301,10 +301,7 @@ static void mainloop_quit(pa_mainloop_api*a, int retval) { m = a->userdata; assert(a == &m->api); - m->quit = 1; - m->retval = retval; - - pa_mainloop_wakeup(m); + pa_mainloop_quit(m, retval); } static const pa_mainloop_api vtable = { @@ -355,7 +352,8 @@ pa_mainloop *pa_mainloop_new(void) { m->io_events_scan_dead = m->defer_events_scan_dead = m->time_events_scan_dead = 0; m->pollfds = NULL; - m->max_pollfds = m->n_pollfds = m->rebuild_pollfds = 0; + m->max_pollfds = m->n_pollfds = 0; + m->rebuild_pollfds = 1; m->quit = m->retval = 0; @@ -368,6 +366,8 @@ pa_mainloop *pa_mainloop_new(void) { m->poll_func = NULL; m->poll_func_userdata = NULL; + + m->retval = -1; return m; } @@ -419,7 +419,7 @@ static int defer_foreach(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void*use void pa_mainloop_free(pa_mainloop* m) { int all = 1; - assert(m && (m->state != STATE_POLLING)); + assert(m); pa_idxset_foreach(m->io_events, io_foreach, &all); pa_idxset_foreach(m->time_events, time_foreach, &all); @@ -772,10 +772,12 @@ int pa_mainloop_run(pa_mainloop *m, int *retval) { return 0; } -void pa_mainloop_quit(pa_mainloop *m, int r) { +void pa_mainloop_quit(pa_mainloop *m, int retval) { assert(m); + + m->quit = 1; + m->retval = retval; pa_mainloop_wakeup(m); - m->quit = r; } pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) { From 9e60bad5c3cb938b250e04e2048fdc46353c5719 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 30 Apr 2006 23:34:17 +0000 Subject: [PATCH 0728/1514] add new threaded main loop implementation (with test/example) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@823 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 8 ++ src/polyp/thread-mainloop.c | 203 +++++++++++++++++++++++++++++++ src/polyp/thread-mainloop.h | 58 +++++++++ src/tests/thread-mainloop-test.c | 73 +++++++++++ 4 files changed, 342 insertions(+) create mode 100644 src/polyp/thread-mainloop.c create mode 100644 src/polyp/thread-mainloop.h create mode 100644 src/tests/thread-mainloop-test.c diff --git a/src/Makefile.am b/src/Makefile.am index fbb14702f..8ad4859e8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -181,6 +181,7 @@ pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) noinst_PROGRAMS = \ mainloop-test \ + thread-mainloop-test \ mcalign-test \ pacat-simple \ parec-simple \ @@ -211,6 +212,11 @@ mainloop_test_CFLAGS = $(AM_CFLAGS) mainloop_test_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +thread_mainloop_test_SOURCES = tests/thread-mainloop-test.c +thread_mainloop_test_CFLAGS = $(AM_CFLAGS) +thread_mainloop_test_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la +thread_mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la @@ -290,6 +296,7 @@ polypinclude_HEADERS = \ polyp/mainloop.h \ polyp/mainloop-api.h \ polyp/mainloop-signal.h \ + polyp/thread-mainloop.h \ polyp/polypaudio.h \ polyp/context.h \ polyp/def.h \ @@ -348,6 +355,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ polyp/volume.c polyp/volume.h \ polyp/mainloop.c polyp/mainloop.h \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ + polyp/thread-mainloop.c polyp/thread-mainloop.h \ polypcore/poll.c polypcore/poll.h # Internal stuff that is shared with libpolypcore diff --git a/src/polyp/thread-mainloop.c b/src/polyp/thread-mainloop.c new file mode 100644 index 000000000..894e037f0 --- /dev/null +++ b/src/polyp/thread-mainloop.c @@ -0,0 +1,203 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "mainloop.h" +#include "thread-mainloop.h" + +struct pa_threaded_mainloop { + pa_mainloop *real_mainloop; + pthread_t thread_id; + pthread_mutex_t mutex; + pthread_cond_t cond; + int thread_running; +}; + +static int poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata) { + pthread_mutex_t *mutex = userdata; + int r; + + assert(mutex); + + /* Before entering poll() we unlock the mutex, so that + * avahi_simple_poll_quit() can succeed from another thread. */ + + pthread_mutex_unlock(mutex); + r = poll(ufds, nfds, timeout); + pthread_mutex_lock(mutex); + + return r; +} + +static void* thread(void *userdata){ + pa_threaded_mainloop *m = userdata; + sigset_t mask; + + /* Make sure that signals are delivered to the main thread */ + sigfillset(&mask); + pthread_sigmask(SIG_BLOCK, &mask, NULL); + + pthread_mutex_lock(&m->mutex); + pa_mainloop_run(m->real_mainloop, NULL); + pthread_mutex_unlock(&m->mutex); + + return NULL; +} + +pa_threaded_mainloop *pa_threaded_mainloop_new(void) { + pa_threaded_mainloop *m; + pthread_mutexattr_t a; + + m = pa_xnew(pa_threaded_mainloop, 1); + + if (!(m->real_mainloop = pa_mainloop_new())) { + pa_xfree(m); + return NULL; + } + + pa_mainloop_set_poll_func(m->real_mainloop, poll_func, &m->mutex); + + pthread_mutexattr_init(&a); + pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m->mutex, NULL); + pthread_mutexattr_destroy(&a); + + pthread_cond_init(&m->cond, NULL); + m->thread_running = 0; + + return m; +} + +void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { + assert(m); + + /* Make sure that this function is not called from the helper thread */ + assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + + if (m->thread_running) + pa_threaded_mainloop_stop(m); + + if (m->real_mainloop) + pa_mainloop_free(m->real_mainloop); + + pthread_mutex_destroy(&m->mutex); + pthread_cond_destroy(&m->cond); + + pa_xfree(m); +} + +int pa_threaded_mainloop_start(pa_threaded_mainloop *m) { + assert(m); + + assert(!m->thread_running); + + pthread_mutex_lock(&m->mutex); + + if (pthread_create(&m->thread_id, NULL, thread, m) < 0) { + pthread_mutex_unlock(&m->mutex); + return -1; + } + + m->thread_running = 1; + + pthread_mutex_unlock(&m->mutex); + + return 0; +} + +void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) { + assert(m); + + if (!m->thread_running) + return; + + /* Make sure that this function is not called from the helper thread */ + assert(!pthread_equal(pthread_self(), m->thread_id)); + + pthread_mutex_lock(&m->mutex); + pa_mainloop_quit(m->real_mainloop, 0); + pthread_mutex_unlock(&m->mutex); + + pthread_join(m->thread_id, NULL); + m->thread_running = 0; + + return; +} + +void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) { + assert(m); + + /* Make sure that this function is not called from the helper thread */ + assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + + pthread_mutex_lock(&m->mutex); +} + +void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) { + assert(m); + + /* Make sure that this function is not called from the helper thread */ + assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + + pthread_mutex_unlock(&m->mutex); +} + +void pa_threaded_mainloop_signal(pa_threaded_mainloop *m) { + assert(m); + + /* Make sure that this function is called from the helper thread */ + assert(m->thread_running && pthread_equal(pthread_self(), m->thread_id)); + + pthread_cond_broadcast(&m->cond); +} + +void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { + assert(m); + + /* Make sure that this function is not called from the helper thread */ + assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + + pthread_cond_wait(&m->cond, &m->mutex); +} + +int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) { + assert(m); + + return pa_mainloop_get_retval(m->real_mainloop); +} + +pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) { + assert(m); + + return pa_mainloop_get_api(m->real_mainloop); +} + diff --git a/src/polyp/thread-mainloop.h b/src/polyp/thread-mainloop.h new file mode 100644 index 000000000..8e53de588 --- /dev/null +++ b/src/polyp/thread-mainloop.h @@ -0,0 +1,58 @@ +#ifndef foothreadmainloophfoo +#define foothreadmainloophfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +PA_C_DECL_BEGIN + +/** \file + * + * A thread based main loop implementation based on pa_mainloop.*/ + +/** An opaque main loop object */ +typedef struct pa_threaded_mainloop pa_threaded_mainloop; + +/** Allocate a new main loop object */ +pa_threaded_mainloop *pa_threaded_mainloop_new(void); + +/** Free a main loop object */ +void pa_threaded_mainloop_free(pa_threaded_mainloop* m); + +int pa_threaded_mainloop_start(pa_threaded_mainloop *m); +void pa_threaded_mainloop_stop(pa_threaded_mainloop *m); +void pa_threaded_mainloop_lock(pa_threaded_mainloop *m); +void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m); +void pa_threaded_mainloop_signal(pa_threaded_mainloop *m); +void pa_threaded_mainloop_wait(pa_threaded_mainloop *m); + +/** Return the return value as specified with the main loop's quit() routine. */ +int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m); + +/** Return the abstract main loop abstraction layer vtable for this main loop. */ +pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m); + +PA_C_DECL_END + +#endif diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c new file mode 100644 index 000000000..8232c4a30 --- /dev/null +++ b/src/tests/thread-mainloop-test.c @@ -0,0 +1,73 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include + +static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { + fprintf(stderr, "TIME EVENT\n"); + pa_threaded_mainloop_signal(userdata); +} + +int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { + pa_mainloop_api *a; + pa_threaded_mainloop *m; + struct timeval tv; + + m = pa_threaded_mainloop_new(); + assert(m); + a = pa_threaded_mainloop_get_api(m); + assert(a); + + pa_threaded_mainloop_start(m); + + pa_threaded_mainloop_lock(m); + + pa_gettimeofday(&tv); + tv.tv_sec += 5; + a->time_new(a, &tv, tcb, m); + + fprintf(stderr, "waiting 5s (signal)\n"); + pa_threaded_mainloop_wait(m); + fprintf(stderr, "wait completed\n"); + + pa_threaded_mainloop_unlock(m); + + fprintf(stderr, "waiting 5s (sleep)\n"); + sleep(5); + + fprintf(stderr, "shutting down\n"); + + pa_threaded_mainloop_stop(m); + + pa_threaded_mainloop_free(m); + return 0; +} From 1438bd49dc9bd5b7e57f9a75c6760ae769ee37bf Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 2 May 2006 08:41:41 +0000 Subject: [PATCH 0729/1514] Windows doesn't have POSIX thread. ifdef out things for now. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@824 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 7 ++++++- src/polyp/thread-mainloop.c | 19 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 8ad4859e8..66e20af59 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -181,7 +181,6 @@ pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) noinst_PROGRAMS = \ mainloop-test \ - thread-mainloop-test \ mcalign-test \ pacat-simple \ parec-simple \ @@ -207,6 +206,12 @@ noinst_PROGRAMS += \ mainloop-test-glib12 endif +# FIXME: We need to make thread-mainloop win32-compatible first +if !OS_IS_WIN32 +noinst_PROGRAMS += \ + thread-mainloop-test +endif + mainloop_test_SOURCES = tests/mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) mainloop_test_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la diff --git a/src/polyp/thread-mainloop.c b/src/polyp/thread-mainloop.c index 894e037f0..32be494dd 100644 --- a/src/polyp/thread-mainloop.c +++ b/src/polyp/thread-mainloop.c @@ -23,17 +23,27 @@ #include #endif -#include #include #include -#include #include +#ifdef HAVE_SYS_POLL_H +#include +#else +#include "../polypcore/poll.h" +#endif + +#ifdef HAVE_PTHREAD +#include +#endif + #include #include "mainloop.h" #include "thread-mainloop.h" +#ifndef OS_IS_WIN32 + struct pa_threaded_mainloop { pa_mainloop *real_mainloop; pthread_t thread_id; @@ -201,3 +211,8 @@ pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) { return pa_mainloop_get_api(m->real_mainloop); } +#else /* OS_IS_WIN32 */ + +// FIXME: Use Win32 primitives + +#endif /* OS_IS_WIN32 */ From 27cee2ef52274fe0cb98eded2c7394a5069c3ce8 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 2 May 2006 09:50:37 +0000 Subject: [PATCH 0730/1514] We need to read the cookie in binary mode for things to work correctly. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@825 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/authkey.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/polypcore/authkey.c b/src/polypcore/authkey.c index 80480c16e..6eafb6720 100644 --- a/src/polypcore/authkey.c +++ b/src/polypcore/authkey.c @@ -59,6 +59,10 @@ static int generate(int fd, void *ret_data, size_t length) { return 0; } +#ifndef O_BINARY +#define O_BINARY 0 +#endif + /* Load an euthorization cookie from file fn and store it in data. If * the cookie file doesn't exist, create it */ static int load(const char *fn, void *data, size_t length) { @@ -68,8 +72,8 @@ static int load(const char *fn, void *data, size_t length) { ssize_t r; assert(fn && data && length); - if ((fd = open(fn, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { - if (errno != EACCES || (fd = open(fn, O_RDONLY)) < 0) { + if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR)) < 0) { + if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY)) < 0) { pa_log(__FILE__": failed to open cookie file '%s': %s", fn, strerror(errno)); goto finish; } else @@ -84,6 +88,7 @@ static int load(const char *fn, void *data, size_t length) { } if ((size_t) r != length) { + pa_log_debug(__FILE__": got %d bytes from cookie file '%s', expected %d", (int)r, fn, (int)length); if (!writable) { pa_log(__FILE__": unable to write cookie to read only file"); From c2c9f251004f4f688d1a9a20d1ec19ea3513a60a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 2 May 2006 11:27:24 +0000 Subject: [PATCH 0731/1514] Fix control flow in pa_oss_open(). Also fall back to half duplex when device doesn't support full. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@826 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/oss-util.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index fac39e7bc..2c573b2f5 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -56,9 +56,11 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { } if (*tcaps & DSP_CAP_DUPLEX) - return fd; + goto success; - goto fail; + pa_log_warn(__FILE__": '%s' doesn't support full duplex", device); + + close(fd); } if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) { @@ -74,6 +76,8 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { } } +success: + if (pcaps) { if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", strerror(errno)); From 4cff5d3150297830bc7b348dc9fe238cc663d97f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 3 May 2006 08:56:03 +0000 Subject: [PATCH 0732/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@827 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/todo b/doc/todo index 4d6422861..f7765cded 100644 --- a/doc/todo +++ b/doc/todo @@ -18,6 +18,11 @@ Post 0.8: - double check channel maps for backends, including that mixer and pcm match - paplay needs to set a channel map. our default is only correct for AIFF. (we need help from libsndfile for this) +- silence generation should be moved into the core to avoid races and code + duplication in the backends +- examine if it is possible to mimic esd's handling of half duplex cards + (switch to capture when a recording client connects and drop playback during + that time) Long term: - pass meta info for hearing impaired From 3f92e3efa92d946e0410bc78d7329039b4ad6f47 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 May 2006 16:38:09 +0000 Subject: [PATCH 0733/1514] allow signalling from event loop thread git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@828 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/thread-mainloop.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/polyp/thread-mainloop.c b/src/polyp/thread-mainloop.c index 32be494dd..51fafe927 100644 --- a/src/polyp/thread-mainloop.c +++ b/src/polyp/thread-mainloop.c @@ -184,9 +184,6 @@ void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) { void pa_threaded_mainloop_signal(pa_threaded_mainloop *m) { assert(m); - /* Make sure that this function is called from the helper thread */ - assert(m->thread_running && pthread_equal(pthread_self(), m->thread_id)); - pthread_cond_broadcast(&m->cond); } From bb6c45dee8b2627527429e65637354635cc98ea1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 May 2006 20:55:53 +0000 Subject: [PATCH 0734/1514] remove bogus check that disallowed latency interpolation and stuff for record streams git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@829 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index c86a200a8..2c4e882c1 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -464,7 +464,6 @@ static int create_stream( PA_STREAM_INTERPOLATE_TIMING| PA_STREAM_NOT_MONOTONOUS| PA_STREAM_AUTO_TIMING_UPDATE : 0))), PA_ERR_INVALID); - PA_CHECK_VALIDITY(s->context, direction == PA_STREAM_PLAYBACK || flags == 0, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID); From 5f9bbf005a81a0f7d009e3fad3f6a4e8d4c5e6bb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 May 2006 20:56:43 +0000 Subject: [PATCH 0735/1514] add support for reading audio data from a file instead of plain STDIN in pacat-simple.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@830 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/pacat-simple.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/tests/pacat-simple.c b/src/tests/pacat-simple.c index 0382ec060..6a75c7903 100644 --- a/src/tests/pacat-simple.c +++ b/src/tests/pacat-simple.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,23 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { int ret = 1; int error; + /* replace STDIN with the specified file if needed */ + if (argc > 1) { + int fd; + + if ((fd = open(argv[1], O_RDONLY)) < 0) { + fprintf(stderr, __FILE__": open() failed: %s\n", strerror(errno)); + goto finish; + } + + if (dup2(fd, STDIN_FILENO) < 0) { + fprintf(stderr, __FILE__": dup2() failed: %s\n", strerror(errno)); + goto finish; + } + + close(fd); + } + /* Create a new playback stream */ if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, &error))) { fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); From 4b4c8fd15293a332d3200f70d2244b0c1ed80874 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 May 2006 20:58:02 +0000 Subject: [PATCH 0736/1514] * optionally, make pa_threaded_mainloop_signal() wait until the main thread took over control * more header file comments git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@831 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/thread-mainloop.c | 17 ++++++++++++++--- src/polyp/thread-mainloop.h | 26 +++++++++++++++++++++++++- src/tests/thread-mainloop-test.c | 5 +++-- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/polyp/thread-mainloop.c b/src/polyp/thread-mainloop.c index 51fafe927..62813acd3 100644 --- a/src/polyp/thread-mainloop.c +++ b/src/polyp/thread-mainloop.c @@ -48,7 +48,8 @@ struct pa_threaded_mainloop { pa_mainloop *real_mainloop; pthread_t thread_id; pthread_mutex_t mutex; - pthread_cond_t cond; + int n_waiting; + pthread_cond_t cond, release_cond; int thread_running; }; @@ -98,11 +99,13 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) { pthread_mutexattr_init(&a); pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&m->mutex, NULL); + pthread_mutex_init(&m->mutex, &a); pthread_mutexattr_destroy(&a); pthread_cond_init(&m->cond, NULL); + pthread_cond_init(&m->release_cond, NULL); m->thread_running = 0; + m->n_waiting = 0; return m; } @@ -121,6 +124,7 @@ void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { pthread_mutex_destroy(&m->mutex); pthread_cond_destroy(&m->cond); + pthread_cond_destroy(&m->release_cond); pa_xfree(m); } @@ -181,10 +185,13 @@ void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) { pthread_mutex_unlock(&m->mutex); } -void pa_threaded_mainloop_signal(pa_threaded_mainloop *m) { +void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_release) { assert(m); pthread_cond_broadcast(&m->cond); + + if (wait_for_release && m->n_waiting > 0) + pthread_cond_wait(&m->release_cond, &m->mutex); } void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { @@ -193,7 +200,11 @@ void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { /* Make sure that this function is not called from the helper thread */ assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + m->n_waiting ++; pthread_cond_wait(&m->cond, &m->mutex); + assert(m->n_waiting > 0); + m->n_waiting --; + pthread_cond_signal(&m->release_cond); } int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) { diff --git a/src/polyp/thread-mainloop.h b/src/polyp/thread-mainloop.h index 8e53de588..d4762e276 100644 --- a/src/polyp/thread-mainloop.h +++ b/src/polyp/thread-mainloop.h @@ -40,13 +40,37 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void); /** Free a main loop object */ void pa_threaded_mainloop_free(pa_threaded_mainloop* m); +/** Start the event loop thread. */ int pa_threaded_mainloop_start(pa_threaded_mainloop *m); + +/** Terminate the event loop thread cleanly */ void pa_threaded_mainloop_stop(pa_threaded_mainloop *m); + +/** Lock the event loop object, effectively blocking the event loop + * thread from processing events. You can use this to enforce + * exclusive access to all objects attached to the event loop. This + * function may not be called inside the event loop thread. */ void pa_threaded_mainloop_lock(pa_threaded_mainloop *m); + +/** Unlock the event loop object, inverse of pa_threaded_mainloop_lock() */ void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m); -void pa_threaded_mainloop_signal(pa_threaded_mainloop *m); + +/** Wait for an event to be signalled by the event loop thread. You + * can use this to pass data from the event loop thread to the main + * thread in synchronized fashion. This function may not be called + * inside the event loop thread. Prior to this call the event loop + * object needs to be locked using pa_threaded_mainloop_lock(). While + * waiting the lock will be released, immediately before returning it + * will be acquired again. */ void pa_threaded_mainloop_wait(pa_threaded_mainloop *m); +/** Signal all threads waiting for a signalling event in + * pa_threaded_mainloop_wait(). If wait_for_release is non-zero, do + * not return before the signal was accepted by a + * pa_threaded_mainloop_wait() call. While waiting for that condition + * the event loop object is unlocked. */ +void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_release); + /** Return the return value as specified with the main loop's quit() routine. */ int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m); diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c index 8232c4a30..24e18b376 100644 --- a/src/tests/thread-mainloop-test.c +++ b/src/tests/thread-mainloop-test.c @@ -33,8 +33,9 @@ #include static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { - fprintf(stderr, "TIME EVENT\n"); - pa_threaded_mainloop_signal(userdata); + fprintf(stderr, "TIME EVENT START\n"); + pa_threaded_mainloop_signal(userdata, 1); + fprintf(stderr, "TIME EVENT END\n"); } int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { From df3306c4affdf31abce1bf2cf545b6ac8ecb0f10 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 May 2006 20:58:28 +0000 Subject: [PATCH 0737/1514] rework the simple API to make use of the new threaded mainloop implementation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@832 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/simple.c | 484 ++++++++++++++++++++++----------------------- 1 file changed, 242 insertions(+), 242 deletions(-) diff --git a/src/polyp/simple.c b/src/polyp/simple.c index dbf7a3258..97dcaf113 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -37,91 +37,92 @@ #include "simple.h" -#define CHECK_VALIDITY_RETURN_ANY(rerror, expression, error, ret) do { \ -if (!(expression)) { \ - if (rerror) \ - *(rerror) = error; \ - return ret; \ - } \ -} while(0); - struct pa_simple { - pa_mainloop *mainloop; + pa_threaded_mainloop *mainloop; pa_context *context; pa_stream *stream; pa_stream_direction_t direction; - int dead; - const void *read_data; size_t read_index, read_length; - pa_usec_t latency; + + int operation_success; }; -static int check_error(pa_simple *p, int *rerror) { - pa_context_state_t cst; - pa_stream_state_t sst; +#define CHECK_VALIDITY_RETURN_ANY(rerror, expression, error, ret) do { \ +if (!(expression)) { \ + if (rerror) \ + *(rerror) = error; \ + return (ret); \ + } \ +} while(0); + +#define CHECK_SUCCESS_GOTO(p, rerror, expression, label) do { \ +if (!(expression)) { \ + if (rerror) \ + *(rerror) = pa_context_errno((p)->context); \ + goto label; \ + } \ +} while(0); + +#define CHECK_DEAD_GOTO(p, rerror, label) do { \ +if (!(p)->context || pa_context_get_state((p)->context) != PA_CONTEXT_READY || \ + !(p)->stream || pa_stream_get_state((p)->stream) != PA_STREAM_READY) { \ + if (((p)->context && pa_context_get_state((p)->context) == PA_CONTEXT_FAILED) || \ + ((p)->stream && pa_stream_get_state((p)->stream) == PA_STREAM_FAILED)) { \ + if (rerror) \ + *(rerror) = pa_context_errno((p)->context); \ + } else \ + if (rerror) \ + *(rerror) = PA_ERR_BADSTATE; \ + goto label; \ + } \ +} while(0); + +static void context_state_cb(pa_context *c, void *userdata) { + pa_simple *p = userdata; + assert(c); assert(p); - - if ((cst = pa_context_get_state(p->context)) == PA_CONTEXT_FAILED) - goto fail; - assert(cst != PA_CONTEXT_TERMINATED); - - if (p->stream) { - if ((sst = pa_stream_get_state(p->stream)) == PA_STREAM_FAILED) - goto fail; - - assert(sst != PA_STREAM_TERMINATED); - } - - return 0; - -fail: - if (rerror) - *rerror = pa_context_errno(p->context); - - p->dead = 1; - - return -1; -} - -static int iterate(pa_simple *p, int block, int *rerror) { - assert(p && p->context && p->mainloop); - - if (check_error(p, rerror) < 0) - return -1; - - if (block || pa_context_is_pending(p->context)) { - do { - if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) { - if (rerror) - *rerror = PA_ERR_INTERNAL; - return -1; - } - - if (check_error(p, rerror) < 0) - return -1; - } while (pa_context_is_pending(p->context)); - } - - for (;;) { - int r; - - if ((r = pa_mainloop_iterate(p->mainloop, 0, NULL)) < 0) { - if (rerror) - *rerror = PA_ERR_INTERNAL; - return -1; - } - - if (r == 0) + switch (pa_context_get_state(c)) { + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: + pa_threaded_mainloop_signal(p->mainloop, 0); break; - if (check_error(p, rerror) < 0) - return -1; + case PA_CONTEXT_UNCONNECTED: + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; } - - return 0; +} + +static void stream_state_cb(pa_stream *s, void * userdata) { + pa_simple *p = userdata; + assert(s); + assert(p); + + switch (pa_stream_get_state(s)) { + + case PA_STREAM_READY: + case PA_STREAM_FAILED: + case PA_STREAM_TERMINATED: + pa_threaded_mainloop_signal(p->mainloop, 0); + break; + + case PA_STREAM_UNCONNECTED: + case PA_STREAM_CREATING: + break; + } +} + +static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { + pa_simple *p = userdata; + assert(p); + + pa_threaded_mainloop_signal(p->mainloop, 0); } pa_simple* pa_simple_new( @@ -145,50 +146,70 @@ pa_simple* pa_simple_new( p = pa_xnew(pa_simple, 1); p->context = NULL; p->stream = NULL; - p->mainloop = pa_mainloop_new(); - assert(p->mainloop); - p->dead = 0; p->direction = dir; p->read_data = NULL; p->read_index = p->read_length = 0; - p->latency = 0; - if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name))) + if (!(p->mainloop = pa_threaded_mainloop_new())) goto fail; + if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name))) + goto fail; + + pa_context_set_state_callback(p->context, context_state_cb, p); + if (pa_context_connect(p->context, server, 0, NULL) < 0) { error = pa_context_errno(p->context); goto fail; } - + + pa_threaded_mainloop_lock(p->mainloop); + + if (pa_threaded_mainloop_start(p->mainloop) < 0) + goto unlock_and_fail; + /* Wait until the context is ready */ - while (pa_context_get_state(p->context) != PA_CONTEXT_READY) { - if (iterate(p, 1, &error) < 0) - goto fail; + pa_threaded_mainloop_wait(p->mainloop); + + if (pa_context_get_state(p->context) != PA_CONTEXT_READY) { + error = pa_context_errno(p->context); + goto unlock_and_fail; } if (!(p->stream = pa_stream_new(p->context, stream_name, ss, NULL))) { error = pa_context_errno(p->context); - goto fail; + goto unlock_and_fail; } + pa_stream_set_state_callback(p->stream, stream_state_cb, p); + pa_stream_set_read_callback(p->stream, stream_request_cb, p); + pa_stream_set_write_callback(p->stream, stream_request_cb, p); + if (dir == PA_STREAM_PLAYBACK) - r = pa_stream_connect_playback(p->stream, dev, attr, 0, NULL, NULL); + r = pa_stream_connect_playback(p->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL); else - r = pa_stream_connect_record(p->stream, dev, attr, 0); + r = pa_stream_connect_record(p->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE); if (r < 0) { error = pa_context_errno(p->context); - goto fail; + goto unlock_and_fail; } /* Wait until the stream is ready */ - while (pa_stream_get_state(p->stream) != PA_STREAM_READY) { - if (iterate(p, 1, &error) < 0) - goto fail; + pa_threaded_mainloop_wait(p->mainloop); + + /* Wait until the stream is ready */ + if (pa_stream_get_state(p->stream) != PA_STREAM_READY) { + error = pa_context_errno(p->context); + goto unlock_and_fail; } + pa_threaded_mainloop_unlock(p->mainloop); + return p; + +unlock_and_fail: + pa_threaded_mainloop_unlock(p->mainloop); fail: if (rerror) @@ -200,6 +221,9 @@ fail: void pa_simple_free(pa_simple *s) { assert(s); + if (s->mainloop) + pa_threaded_mainloop_stop(s->mainloop); + if (s->stream) pa_stream_unref(s->stream); @@ -207,232 +231,208 @@ void pa_simple_free(pa_simple *s) { pa_context_unref(s->context); if (s->mainloop) - pa_mainloop_free(s->mainloop); + pa_threaded_mainloop_free(s->mainloop); pa_xfree(s); } int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) { assert(p); - assert(data); - + CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); + CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1); - if (p->dead) { - if (rerror) - *rerror = pa_context_errno(p->context); - - return -1; - } + pa_threaded_mainloop_lock(p->mainloop); + + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); while (length > 0) { size_t l; + int r; - while (!(l = pa_stream_writable_size(p->stream))) - if (iterate(p, 1, rerror) < 0) - return -1; + while (!(l = pa_stream_writable_size(p->stream))) { + pa_threaded_mainloop_wait(p->mainloop); + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); + } + CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail); + if (l > length) l = length; - pa_stream_write(p->stream, data, l, NULL, 0, PA_SEEK_RELATIVE); + r = pa_stream_write(p->stream, data, l, NULL, 0, PA_SEEK_RELATIVE); + CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail); + data = (const uint8_t*) data + l; length -= l; } - /* Make sure that no data is pending for write */ - if (iterate(p, 0, rerror) < 0) - return -1; - + pa_threaded_mainloop_unlock(p->mainloop); return 0; + +unlock_and_fail: + pa_threaded_mainloop_unlock(p->mainloop); + return -1; } int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { assert(p); - assert(data); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1); + CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1); + + pa_threaded_mainloop_lock(p->mainloop); - if (p->dead) { - if (rerror) - *rerror = pa_context_errno(p->context); - - return -1; - } - + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); + while (length > 0) { - - if (!p->read_data) - if (pa_stream_peek(p->stream, &p->read_data, &p->read_length) >= 0) - p->read_index = 0; + size_t l; + + while (!p->read_data) { + int r; - if (p->read_data) { - size_t l = length; + r = pa_stream_peek(p->stream, &p->read_data, &p->read_length); + CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail); - if (p->read_length <= l) - l = p->read_length; - - memcpy(data, (const uint8_t*) p->read_data+p->read_index, l); - - data = (uint8_t*) data + l; - length -= l; - - p->read_index += l; - p->read_length -= l; - - if (!p->read_length) { - pa_stream_drop(p->stream); - p->read_data = NULL; - p->read_length = 0; + if (!p->read_data) { + pa_threaded_mainloop_wait(p->mainloop); + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); + } else p->read_index = 0; - } - - if (!length) - return 0; - - assert(!p->read_data); } + + l = p->read_length < length ? p->read_length : length; + memcpy(data, (const uint8_t*) p->read_data+p->read_index, l); - if (iterate(p, 1, rerror) < 0) - return -1; + data = (uint8_t*) data + l; + length -= l; + + p->read_index += l; + p->read_length -= l; + + if (!p->read_length) { + int r; + + r = pa_stream_drop(p->stream); + p->read_data = NULL; + p->read_length = 0; + p->read_index = 0; + + CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail); + } } + pa_threaded_mainloop_unlock(p->mainloop); return 0; + +unlock_and_fail: + pa_threaded_mainloop_unlock(p->mainloop); + return -1; } -static void drain_or_flush_complete(pa_stream *s, int success, void *userdata) { +static void success_cb(pa_stream *s, int success, void *userdata) { pa_simple *p = userdata; assert(s); assert(p); - - if (!success) - p->dead = 1; + + p->operation_success = success; + pa_threaded_mainloop_signal(p->mainloop, 0); } int pa_simple_drain(pa_simple *p, int *rerror) { - pa_operation *o; + pa_operation *o = NULL; assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); - if (p->dead) { - if (rerror) - *rerror = pa_context_errno(p->context); - - return -1; - } + pa_threaded_mainloop_lock(p->mainloop); + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); - if (!(o = pa_stream_drain(p->stream, drain_or_flush_complete, p))) { - if (rerror) - *rerror = pa_context_errno(p->context); - return -1; - } + o = pa_stream_drain(p->stream, success_cb, p); + CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail); - while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { - if (iterate(p, 1, rerror) < 0) { - pa_operation_cancel(o); - pa_operation_unref(o); - return -1; - } + p->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(p->mainloop); + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); } - + CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail); + pa_operation_unref(o); + pa_threaded_mainloop_unlock(p->mainloop); - if (p->dead && rerror) - *rerror = pa_context_errno(p->context); + return 0; - return p->dead ? -1 : 0; -} +unlock_and_fail: -static void timing_complete(pa_stream *s, int success, void *userdata) { - pa_simple *p = userdata; - - assert(s); - assert(p); - - if (!success) - p->dead = 1; - else { - int negative = 0; - if (pa_stream_get_latency(s, &p->latency, &negative) < 0) - p->dead = 1; - else if (negative) - p->latency = 0; - } -} - -pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) { - pa_operation *o; - - assert(p); - - CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); - - if (p->dead) { - if (rerror) - *rerror = pa_context_errno(p->context); - - return (pa_usec_t) -1; + if (o) { + pa_operation_cancel(o); + pa_operation_unref(o); } - p->latency = 0; - if (!(o = pa_stream_update_timing_info(p->stream, timing_complete, p))) { - if (rerror) - *rerror = pa_context_errno(p->context); - return (pa_usec_t) -1; - } - - while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { - - if (iterate(p, 1, rerror) < 0) { - pa_operation_cancel(o); - pa_operation_unref(o); - return -1; - } - } - - pa_operation_unref(o); - - if (p->dead && rerror) - *rerror = pa_context_errno(p->context); - - return p->dead ? (pa_usec_t) -1 : p->latency; + pa_threaded_mainloop_unlock(p->mainloop); + return -1; } int pa_simple_flush(pa_simple *p, int *rerror) { - pa_operation *o; + pa_operation *o = NULL; assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); - if (p->dead) { - if (rerror) - *rerror = pa_context_errno(p->context); - - return -1; - } + pa_threaded_mainloop_lock(p->mainloop); + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); - if (!(o = pa_stream_flush(p->stream, drain_or_flush_complete, p))) { - if (rerror) - *rerror = pa_context_errno(p->context); - return -1; - } - - while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { - if (iterate(p, 1, rerror) < 0) { - pa_operation_cancel(o); - pa_operation_unref(o); - return -1; - } + o = pa_stream_flush(p->stream, success_cb, p); + CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail); + + p->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(p->mainloop); + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); } + CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail); pa_operation_unref(o); + pa_threaded_mainloop_unlock(p->mainloop); - if (p->dead && rerror) - *rerror = pa_context_errno(p->context); + return 0; - return p->dead ? -1 : 0; +unlock_and_fail: + + if (o) { + pa_operation_cancel(o); + pa_operation_unref(o); + } + + pa_threaded_mainloop_unlock(p->mainloop); + return -1; } + +pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) { + pa_usec_t t; + int r, negative; + + assert(p); + + CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, (pa_usec_t) -1); + + pa_threaded_mainloop_lock(p->mainloop); + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); + + r = pa_stream_get_latency(p->stream, &t, &negative); + CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail); + + pa_threaded_mainloop_unlock(p->mainloop); + + return negative ? 0 : t; + +unlock_and_fail: + + pa_threaded_mainloop_unlock(p->mainloop); + return (pa_usec_t) -1; +} + From 06e1867307777ffa8686762ff3e42143d88b46ed Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 9 May 2006 08:38:37 +0000 Subject: [PATCH 0738/1514] Use pa_msleep() to get platform independence. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@833 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/thread-mainloop-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c index 24e18b376..1434deb97 100644 --- a/src/tests/thread-mainloop-test.c +++ b/src/tests/thread-mainloop-test.c @@ -63,7 +63,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { pa_threaded_mainloop_unlock(m); fprintf(stderr, "waiting 5s (sleep)\n"); - sleep(5); + pa_msleep(5000); fprintf(stderr, "shutting down\n"); From 4e71f20d6cecff245a45233d4953beb4e0b29178 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 9 May 2006 08:39:26 +0000 Subject: [PATCH 0739/1514] Add stubs for the threaded main loop so that we can compile it on non-supported platforms (still can't run it though). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@834 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 9 ++----- src/polyp/thread-mainloop.c | 50 ++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 66e20af59..ee7b2325f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -188,7 +188,8 @@ noinst_PROGRAMS = \ voltest \ memblockq-test \ sync-playback \ - channelmap-test + channelmap-test \ + thread-mainloop-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -206,12 +207,6 @@ noinst_PROGRAMS += \ mainloop-test-glib12 endif -# FIXME: We need to make thread-mainloop win32-compatible first -if !OS_IS_WIN32 -noinst_PROGRAMS += \ - thread-mainloop-test -endif - mainloop_test_SOURCES = tests/mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) mainloop_test_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la diff --git a/src/polyp/thread-mainloop.c b/src/polyp/thread-mainloop.c index 62813acd3..6c14a1d31 100644 --- a/src/polyp/thread-mainloop.c +++ b/src/polyp/thread-mainloop.c @@ -42,7 +42,8 @@ #include "mainloop.h" #include "thread-mainloop.h" -#ifndef OS_IS_WIN32 +/* FIXME: Add defined(OS_IS_WIN32) when support is added */ +#if defined(HAVE_PTHREAD) struct pa_threaded_mainloop { pa_mainloop *real_mainloop; @@ -219,8 +220,49 @@ pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) { return pa_mainloop_get_api(m->real_mainloop); } -#else /* OS_IS_WIN32 */ +#else /* defined(OS_IS_WIN32) || defined(HAVE_PTHREAD) */ -// FIXME: Use Win32 primitives +pa_threaded_mainloop *pa_threaded_mainloop_new(void) { + pa_log_error(__FILE__": Threaded main loop not supported on this platform"); + return NULL; +} -#endif /* OS_IS_WIN32 */ +void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { + assert(0); +} + +int pa_threaded_mainloop_start(pa_threaded_mainloop *m) { + assert(0); + return -1; +} + +void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) { + assert(0); +} + +void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) { + assert(0); +} + +void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) { + assert(0); +} + +void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { + assert(0); +} + +void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_release) { + assert(0); +} + +int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) { + assert(0); +} + +pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) { + assert(0); + return NULL; +} + +#endif /* defined(OS_IS_WIN32) || defined(HAVE_PTHREAD) */ From 9efc2062d6eabdee79be62a248f006eba813f75d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 9 May 2006 15:15:41 +0000 Subject: [PATCH 0740/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@835 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/todo b/doc/todo index f7765cded..e6ad0d5f6 100644 --- a/doc/todo +++ b/doc/todo @@ -23,6 +23,10 @@ Post 0.8: - examine if it is possible to mimic esd's handling of half duplex cards (switch to capture when a recording client connects and drop playback during that time) +- fix channel maps in all external backends. Take care when doing volume + changes if you're modifying a sink/source since those might have a different + map. +- don't install .a files of modules Long term: - pass meta info for hearing impaired @@ -33,6 +37,3 @@ Backends for: - sdl - OSS (esddsp style) - gstreamer (needs to be updated) -- fix channel maps in all external backends. Take care when doing volume - changes if you're modifying a sink/source since those might have a different - map. From 26870176bae0b56d844aadedcfa1888e0c68e378 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 9 May 2006 15:16:12 +0000 Subject: [PATCH 0741/1514] fix handling of timing status requests git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@836 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 2c4e882c1..c67b3e516 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -727,9 +727,8 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, assert(pd); assert(o); - assert(o->stream); - if (!o->context) + if (!o->context || !o->stream) goto finish; i = &o->stream->timing_info; From 6d2a9367bafb8ae4a98fe725bcb52b021f0fa4e6 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 11 May 2006 11:02:25 +0000 Subject: [PATCH 0742/1514] Do WSAStartup() in the DLL entry routine instead of at context creation. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@837 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.c | 11 ----------- src/polypcore/dllmain.c | 17 +++++++++++++---- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/polyp/context.c b/src/polyp/context.c index c9a658477..d5cf90f8e 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -142,13 +142,6 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { #endif pa_client_conf_env(c->conf); -#ifdef OS_IS_WIN32 - { - WSADATA data; - WSAStartup(MAKEWORD(2, 0), &data); - } -#endif - return c; } @@ -187,10 +180,6 @@ static void context_free(pa_context *c) { pa_xfree(c->name); pa_xfree(c->server); pa_xfree(c); - -#ifdef OS_IS_WIN32 - WSACleanup(); -#endif } pa_context* pa_context_ref(pa_context *c) { diff --git a/src/polypcore/dllmain.c b/src/polypcore/dllmain.c index d1d120ab8..95473b068 100644 --- a/src/polypcore/dllmain.c +++ b/src/polypcore/dllmain.c @@ -34,12 +34,21 @@ extern pa_set_root(HANDLE handle); BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - if (fdwReason != DLL_PROCESS_ATTACH) - return TRUE; + WSADATA data; - if (!pa_set_root(hinstDLL)) - return FALSE; + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + if (!pa_set_root(hinstDLL)) + return FALSE; + WSAStartup(MAKEWORD(2, 0), &data); + break; + + case DLL_PROCESS_DETACH: + WSACleanup(); + break; + + } return TRUE; } From 18c5340fb48bb6a56b8a9761628e24d2b236193b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 11 May 2006 11:03:17 +0000 Subject: [PATCH 0743/1514] ANSI codes aren't supported on Windows terminals. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@838 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/log.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/polypcore/log.c b/src/polypcore/log.c index 29c4c4808..9c9ed2fd9 100644 --- a/src/polypcore/log.c +++ b/src/polypcore/log.c @@ -99,7 +99,8 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { switch (log_target) { case PA_LOG_STDERR: { const char *prefix = "", *suffix = ""; - + +#ifndef OS_IS_WIN32 /* Yes indeed. Useless, but fun! */ if (isatty(STDERR_FILENO)) { if (level <= PA_LOG_ERROR) { @@ -110,6 +111,8 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { suffix = "\x1B[0m"; } } +#endif + fprintf(stderr, "%s%s%s\n", prefix, t, suffix); break; } From 12d4b5d952c7a284fd081966a02d34d94dd6be10 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 11 May 2006 11:04:57 +0000 Subject: [PATCH 0744/1514] Include log header to get rid of warnings. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@839 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/thread-mainloop.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/polyp/thread-mainloop.c b/src/polyp/thread-mainloop.c index 6c14a1d31..577e0c2f6 100644 --- a/src/polyp/thread-mainloop.c +++ b/src/polyp/thread-mainloop.c @@ -37,6 +37,7 @@ #include #endif +#include #include #include "mainloop.h" From 48d66cd5e89764b00fe225db4823b3392a759942 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 11 May 2006 11:08:58 +0000 Subject: [PATCH 0745/1514] Handle pipes on platforms where they are non-existant of broken. We do this by creating a TCP socket pair instead of a normal pipe. Since Windows isn't UNIX-y enough to support read()/write() on sockets, we also need a wrapper to handle read() vs recv() and write() vs send(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@840 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- src/Makefile.am | 2 + src/polyp/mainloop-signal.c | 81 +++--------------- src/polyp/mainloop.c | 14 ++-- src/polypcore/iochannel.c | 28 +------ src/polypcore/pipe.c | 160 ++++++++++++++++++++++++++++++++++++ src/polypcore/pipe.h | 22 +++++ src/polypcore/util.c | 45 +++++++++- src/polypcore/util.h | 2 + 9 files changed, 249 insertions(+), 107 deletions(-) create mode 100644 src/polypcore/pipe.c create mode 100644 src/polypcore/pipe.h diff --git a/configure.ac b/configure.ac index 22ab39626..360249eac 100644 --- a/configure.ac +++ b/configure.ac @@ -220,7 +220,7 @@ AC_FUNC_FORK AC_FUNC_GETGROUPS AC_FUNC_SELECT_ARGTYPES AC_CHECK_FUNCS([chmod chown getaddrinfo getgrgid_r getpwuid_r gettimeofday \ - getuid inet_ntop inet_pton nanosleep setpgid setsid sigaction sleep]) + getuid inet_ntop inet_pton nanosleep pipe setpgid setsid sigaction sleep]) AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0]) AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1") diff --git a/src/Makefile.am b/src/Makefile.am index ee7b2325f..72e3c1eb7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -356,6 +356,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ polyp/mainloop.c polyp/mainloop.h \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ polyp/thread-mainloop.c polyp/thread-mainloop.h \ + polypcore/pipe.c polypcore/pipe.h \ polypcore/poll.c polypcore/poll.h # Internal stuff that is shared with libpolypcore @@ -518,6 +519,7 @@ libpolypcore_la_SOURCES += \ polypcore/module.c polypcore/module.h \ polypcore/namereg.c polypcore/namereg.h \ polypcore/pid.c polypcore/pid.h \ + polypcore/pipe.c polypcore/pipe.h \ polypcore/play-memchunk.c polypcore/play-memchunk.h \ polypcore/poll.c polypcore/poll.h \ polypcore/props.c polypcore/props.h \ diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index 73de00025..6073dbb35 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -59,25 +59,17 @@ struct pa_signal_event { static pa_mainloop_api *api = NULL; static int signal_pipe[2] = { -1, -1 }; static pa_io_event* io_event = NULL; -static pa_time_event *time_event = NULL; static pa_signal_event *signals = NULL; -#ifdef OS_IS_WIN32 -static unsigned int waiting_signals = 0; -static CRITICAL_SECTION crit; -#endif - static void signal_handler(int sig) { + int result; #ifndef HAVE_SIGACTION signal(sig, signal_handler); #endif - write(signal_pipe[1], &sig, sizeof(sig)); - -#ifdef OS_IS_WIN32 - EnterCriticalSection(&crit); - waiting_signals++; - LeaveCriticalSection(&crit); -#endif + pa_log(__FILE__": Got signal %d", sig); + result = pa_write(signal_pipe[1], &sig, sizeof(sig)); + if (result != sizeof(sig)) + pa_log(__FILE__": Bad write (%d, %d)", result, WSAGetLastError()); } static void dispatch(pa_mainloop_api*a, int sig) { @@ -91,46 +83,14 @@ static void dispatch(pa_mainloop_api*a, int sig) { } } -#ifdef OS_IS_WIN32 -static void timer(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, PA_GCC_UNUSED void *userdata) { - ssize_t r; - int sig; - unsigned int sigs; - struct timeval tvnext; - - EnterCriticalSection(&crit); - sigs = waiting_signals; - waiting_signals = 0; - LeaveCriticalSection(&crit); - - while (sigs) { - if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { - pa_log(__FILE__": read(): %s", strerror(errno)); - return; - } - - if (r != sizeof(sig)) { - pa_log(__FILE__": short read()"); - return; - } - - dispatch(a, sig); - - sigs--; - } - - pa_timeval_add(pa_gettimeofday(&tvnext), 100000); - a->time_restart(e, &tvnext); -} -#endif - static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, PA_GCC_UNUSED void *userdata) { ssize_t r; int sig; assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); - - if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) { + pa_log(__FILE__": Signal pipe callback"); + + if ((r = pa_read(signal_pipe[0], &sig, sizeof(sig))) < 0) { if (errno == EAGAIN) return; @@ -147,17 +107,10 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags } int pa_signal_init(pa_mainloop_api *a) { -#ifdef OS_IS_WIN32 - struct timeval tv; -#endif - assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event && !time_event); + assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event); -#ifdef OS_IS_WIN32 - if (_pipe(signal_pipe, 200, _O_BINARY) < 0) { -#else if (pipe(signal_pipe) < 0) { -#endif pa_log(__FILE__": pipe() failed: %s", strerror(errno)); return -1; } @@ -169,34 +122,20 @@ int pa_signal_init(pa_mainloop_api *a) { api = a; -#ifndef OS_IS_WIN32 io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL); assert(io_event); -#else - time_event = api->time_new(api, pa_gettimeofday(&tv), timer, NULL); - assert(time_event); - - InitializeCriticalSection(&crit); -#endif return 0; } void pa_signal_done(void) { - assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && (io_event || time_event)); + assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && io_event); while (signals) pa_signal_free(signals); -#ifndef OS_IS_WIN32 api->io_free(io_event); io_event = NULL; -#else - api->time_free(time_event); - time_event = NULL; - - DeleteCriticalSection(&crit); -#endif close(signal_pipe[0]); close(signal_pipe[1]); diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 98b3f3c69..589fe77ef 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -40,6 +40,10 @@ #include "../polypcore/winsock.h" +#ifndef HAVE_PIPE +#include "../polypcore/pipe.h" +#endif + #include #include #include @@ -330,18 +334,14 @@ pa_mainloop *pa_mainloop_new(void) { m = pa_xmalloc(sizeof(pa_mainloop)); -#ifndef OS_IS_WIN32 if (pipe(m->wakeup_pipe) < 0) { + pa_log_error(__FILE__": ERROR: cannot create wakeup pipe"); pa_xfree(m); return NULL; } pa_make_nonblock_fd(m->wakeup_pipe[0]); pa_make_nonblock_fd(m->wakeup_pipe[1]); -#else - m->wakeup_pipe[0] = -1; - m->wakeup_pipe[1] = -1; -#endif m->io_events = pa_idxset_new(NULL, NULL); m->defer_events = pa_idxset_new(NULL, NULL); @@ -622,7 +622,7 @@ void pa_mainloop_wakeup(pa_mainloop *m) { assert(m); if (m->wakeup_pipe[1] >= 0) - write(m->wakeup_pipe[1], &c, sizeof(c)); + pa_write(m->wakeup_pipe[1], &c, sizeof(c)); } static void clear_wakeup(pa_mainloop *m) { @@ -633,7 +633,7 @@ static void clear_wakeup(pa_mainloop *m) { if (m->wakeup_pipe[0] < 0) return; - while (read(m->wakeup_pipe[0], &c, sizeof(c)) == sizeof(c)); + while (pa_read(m->wakeup_pipe[0], &c, sizeof(c)) == sizeof(c)); } int pa_mainloop_prepare(pa_mainloop *m, int timeout) { diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index 5da7a9a9f..623925acd 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -202,19 +202,7 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) { assert(l); assert(io->ofd >= 0); -#ifdef OS_IS_WIN32 - r = send(io->ofd, data, l, 0); - if (r < 0) { - if (WSAGetLastError() != WSAENOTSOCK) { - errno = WSAGetLastError(); - return r; - } - } - - if (r < 0) -#endif - r = write(io->ofd, data, l); - + r = pa_write(io->ofd, data, l); if (r >= 0) { io->writable = 0; enable_mainloop_sources(io); @@ -229,20 +217,8 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { assert(io); assert(data); assert(io->ifd >= 0); - -#ifdef OS_IS_WIN32 - r = recv(io->ifd, data, l, 0); - if (r < 0) { - if (WSAGetLastError() != WSAENOTSOCK) { - errno = WSAGetLastError(); - return r; - } - } - if (r < 0) -#endif - r = read(io->ifd, data, l); - + r = pa_read(io->ifd, data, l); if (r >= 0) { io->readable = 0; enable_mainloop_sources(io); diff --git a/src/polypcore/pipe.c b/src/polypcore/pipe.c new file mode 100644 index 000000000..eef6d5335 --- /dev/null +++ b/src/polypcore/pipe.c @@ -0,0 +1,160 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with polypaudio; If not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#include "winsock.h" + +#include "pipe.h" + +#ifndef HAVE_PIPE + +static int set_block(int fd, int blocking) { +#ifdef O_NONBLOCK + + int v; + + assert(fd >= 0); + + if ((v = fcntl(fd, F_GETFL)) < 0) + return -1; + + if (blocking) + v &= ~O_NONBLOCK; + else + v |= O_NONBLOCK; + + if (fcntl(fd, F_SETFL, v) < 0) + return -1; + + return 0; + +#elif defined(OS_IS_WIN32) + + u_long arg; + + arg = !blocking; + + if (ioctlsocket(fd, FIONBIO, &arg) < 0) + return -1; + + return 0; + +#else + + return -1; + +#endif +} + +int pipe(int filedes[2]) { + int listener; + struct sockaddr_in addr, peer; + socklen_t len; + + listener = -1; + filedes[0] = -1; + filedes[1] = -1; + + listener = socket(PF_INET, SOCK_STREAM, 0); + if (listener < 0) + goto error; + + filedes[0] = socket(PF_INET, SOCK_STREAM, 0); + if (filedes[0] < 0) + goto error; + + filedes[1] = socket(PF_INET, SOCK_STREAM, 0); + if (filedes[1] < 0) + goto error; + + /* Make non-blocking so that connect() won't block */ + if (set_block(filedes[0], 0) < 0) + goto error; + + addr.sin_family = AF_INET; + addr.sin_port = 0; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) < 0) + goto error; + + if (listen(listener, 1) < 0) + goto error; + + len = sizeof(addr); + if (getsockname(listener, (struct sockaddr*)&addr, &len) < 0) + goto error; + + if (connect(filedes[0], (struct sockaddr*)&addr, sizeof(addr)) < 0) { +#ifdef OS_IS_WIN32 + if (WSAGetLastError() != EWOULDBLOCK) +#else + if (errno != EINPROGRESS) +#endif + goto error; + } + + len = sizeof(peer); + filedes[1] = accept(listener, (struct sockaddr*)&peer, &len); + if (filedes[1] < 0) + goto error; + + /* Restore blocking */ + if (set_block(filedes[0], 1) < 0) + goto error; + + len = sizeof(addr); + if (getsockname(filedes[0], (struct sockaddr*)&addr, &len) < 0) + goto error; + + /* Check that someone else didn't steal the connection */ + if ((addr.sin_port != peer.sin_port) || (addr.sin_addr.s_addr != peer.sin_addr.s_addr)) + goto error; + + close(listener); + + return 0; + +error: + if (listener >= 0) + close(listener); + if (filedes[0] >= 0) + close(filedes[0]); + if (filedes[1] >= 0) + close(filedes[0]); + + return -1; +} + +#endif /* HAVE_PIPE */ diff --git a/src/polypcore/pipe.h b/src/polypcore/pipe.h new file mode 100644 index 000000000..a9b088b5c --- /dev/null +++ b/src/polypcore/pipe.h @@ -0,0 +1,22 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with polypaudio; If not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. +***/ + +int pipe(int filedes[2]); diff --git a/src/polypcore/util.c b/src/polypcore/util.c index 191fa809d..beb93f451 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -198,6 +198,47 @@ finish: return ret; } +/** Platform independent read function. Necessary since not all systems + * treat all file descriptors equal. */ +ssize_t pa_read(int fd, void *buf, size_t count) { + ssize_t r; + +#ifdef OS_IS_WIN32 + r = recv(fd, buf, count, 0); + if (r < 0) { + if (WSAGetLastError() != WSAENOTSOCK) { + errno = WSAGetLastError(); + return r; + } + } + + if (r < 0) +#endif + r = read(fd, buf, count); + + return r; +} + +/** Similar to pa_read(), but handles writes */ +ssize_t pa_write(int fd, void *buf, size_t count) { + ssize_t r; + +#ifdef OS_IS_WIN32 + r = send(fd, buf, count, 0); + if (r < 0) { + if (WSAGetLastError() != WSAENOTSOCK) { + errno = WSAGetLastError(); + return r; + } + } + + if (r < 0) +#endif + r = write(fd, buf, count); + + return r; +} + /** Calls read() in a loop. Makes sure that as much as 'size' bytes, * unless EOF is reached or an error occured */ ssize_t pa_loop_read(int fd, void*data, size_t size) { @@ -207,7 +248,7 @@ ssize_t pa_loop_read(int fd, void*data, size_t size) { while (size > 0) { ssize_t r; - if ((r = read(fd, data, size)) < 0) + if ((r = pa_read(fd, data, size)) < 0) return r; if (r == 0) @@ -229,7 +270,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) { while (size > 0) { ssize_t r; - if ((r = write(fd, data, size)) < 0) + if ((r = pa_write(fd, data, size)) < 0) return r; if (r == 0) diff --git a/src/polypcore/util.h b/src/polypcore/util.h index ca81b2298..a7c65381a 100644 --- a/src/polypcore/util.h +++ b/src/polypcore/util.h @@ -37,6 +37,8 @@ void pa_make_nonblock_fd(int fd); int pa_make_secure_dir(const char* dir); int pa_make_secure_parent_dir(const char *fn); +ssize_t pa_read(int fd, void *buf, size_t count); +ssize_t pa_write(int fd, void *buf, size_t count); ssize_t pa_loop_read(int fd, void*data, size_t size); ssize_t pa_loop_write(int fd, const void*data, size_t size); From 5328afe369b0a124bac4243abae4b53f1b3f58e2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 11 May 2006 11:30:35 +0000 Subject: [PATCH 0746/1514] pa_write() should use a const pointer. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@841 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/util.c | 2 +- src/polypcore/util.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/polypcore/util.c b/src/polypcore/util.c index beb93f451..c1f82a208 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -220,7 +220,7 @@ ssize_t pa_read(int fd, void *buf, size_t count) { } /** Similar to pa_read(), but handles writes */ -ssize_t pa_write(int fd, void *buf, size_t count) { +ssize_t pa_write(int fd, const void *buf, size_t count) { ssize_t r; #ifdef OS_IS_WIN32 diff --git a/src/polypcore/util.h b/src/polypcore/util.h index a7c65381a..2d5894c33 100644 --- a/src/polypcore/util.h +++ b/src/polypcore/util.h @@ -38,7 +38,7 @@ int pa_make_secure_dir(const char* dir); int pa_make_secure_parent_dir(const char *fn); ssize_t pa_read(int fd, void *buf, size_t count); -ssize_t pa_write(int fd, void *buf, size_t count); +ssize_t pa_write(int fd, const void *buf, size_t count); ssize_t pa_loop_read(int fd, void*data, size_t size); ssize_t pa_loop_write(int fd, const void*data, size_t size); From 3890f0387fa75fa09da8938931c74cd88e070a53 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 11 May 2006 11:30:55 +0000 Subject: [PATCH 0747/1514] Remove some debug code that wasn't supposed to be committed. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@842 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/mainloop-signal.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index 6073dbb35..2c9484e46 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -62,14 +62,10 @@ static pa_io_event* io_event = NULL; static pa_signal_event *signals = NULL; static void signal_handler(int sig) { - int result; #ifndef HAVE_SIGACTION signal(sig, signal_handler); #endif - pa_log(__FILE__": Got signal %d", sig); - result = pa_write(signal_pipe[1], &sig, sizeof(sig)); - if (result != sizeof(sig)) - pa_log(__FILE__": Bad write (%d, %d)", result, WSAGetLastError()); + pa_write(signal_pipe[1], &sig, sizeof(sig)); } static void dispatch(pa_mainloop_api*a, int sig) { From dbf62d4bc5e984fb33b39292cb5268e73ec8a17a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 11 May 2006 12:59:58 +0000 Subject: [PATCH 0748/1514] add thread-mainloop.h to doxygen docs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@843 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doxygen/doxygen.conf.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 9e426027a..471c21dcd 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h +INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h ../src/polyp/thread-mainloop.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp From e929aabc032ee91705acc8571f09affe41e297ae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 11 May 2006 13:01:24 +0000 Subject: [PATCH 0749/1514] split of signal releasing into its own function and name it pa_threaded_mainloop_accept() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@844 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/thread-mainloop.c | 23 ++++++++++++++++------- src/polyp/thread-mainloop.h | 7 +++++-- src/tests/thread-mainloop-test.c | 4 +++- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/polyp/thread-mainloop.c b/src/polyp/thread-mainloop.c index 577e0c2f6..90274f1c1 100644 --- a/src/polyp/thread-mainloop.c +++ b/src/polyp/thread-mainloop.c @@ -51,7 +51,7 @@ struct pa_threaded_mainloop { pthread_t thread_id; pthread_mutex_t mutex; int n_waiting; - pthread_cond_t cond, release_cond; + pthread_cond_t cond, accept_cond; int thread_running; }; @@ -105,7 +105,7 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) { pthread_mutexattr_destroy(&a); pthread_cond_init(&m->cond, NULL); - pthread_cond_init(&m->release_cond, NULL); + pthread_cond_init(&m->accept_cond, NULL); m->thread_running = 0; m->n_waiting = 0; @@ -126,7 +126,7 @@ void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { pthread_mutex_destroy(&m->mutex); pthread_cond_destroy(&m->cond); - pthread_cond_destroy(&m->release_cond); + pthread_cond_destroy(&m->accept_cond); pa_xfree(m); } @@ -187,13 +187,13 @@ void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) { pthread_mutex_unlock(&m->mutex); } -void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_release) { +void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) { assert(m); pthread_cond_broadcast(&m->cond); - if (wait_for_release && m->n_waiting > 0) - pthread_cond_wait(&m->release_cond, &m->mutex); + if (wait_for_accept && m->n_waiting > 0) + pthread_cond_wait(&m->accept_cond, &m->mutex); } void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { @@ -206,7 +206,16 @@ void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { pthread_cond_wait(&m->cond, &m->mutex); assert(m->n_waiting > 0); m->n_waiting --; - pthread_cond_signal(&m->release_cond); + pthread_cond_signal(&m->accept_cond); +} + +void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) { + assert(m); + + /* Make sure that this function is not called from the helper thread */ + assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + + pthread_cond_signal(&m->accept_cond); } int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) { diff --git a/src/polyp/thread-mainloop.h b/src/polyp/thread-mainloop.h index d4762e276..d0bfd5ae3 100644 --- a/src/polyp/thread-mainloop.h +++ b/src/polyp/thread-mainloop.h @@ -67,9 +67,12 @@ void pa_threaded_mainloop_wait(pa_threaded_mainloop *m); /** Signal all threads waiting for a signalling event in * pa_threaded_mainloop_wait(). If wait_for_release is non-zero, do * not return before the signal was accepted by a - * pa_threaded_mainloop_wait() call. While waiting for that condition + * pa_threaded_mainloop_accept() call. While waiting for that condition * the event loop object is unlocked. */ -void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_release); +void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept); + +/** Accept a signal from the event thread issued with pa_threaded_mainloop_signal() */ +void pa_threaded_mainloop_accept(pa_threaded_mainloop *m); /** Return the return value as specified with the main loop's quit() routine. */ int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m); diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c index 1434deb97..8ca3f92fa 100644 --- a/src/tests/thread-mainloop-test.c +++ b/src/tests/thread-mainloop-test.c @@ -59,7 +59,9 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { fprintf(stderr, "waiting 5s (signal)\n"); pa_threaded_mainloop_wait(m); fprintf(stderr, "wait completed\n"); - + pa_threaded_mainloop_accept(m); + fprintf(stderr, "signal accepted\n"); + pa_threaded_mainloop_unlock(m); fprintf(stderr, "waiting 5s (sleep)\n"); From 68b98f711308ba09a35b78f23a0567f25090d620 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 11 May 2006 13:17:19 +0000 Subject: [PATCH 0750/1514] don't signal the accept_cond automatically when waiting for a signal event git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@845 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/thread-mainloop.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/polyp/thread-mainloop.c b/src/polyp/thread-mainloop.c index 90274f1c1..916c89d81 100644 --- a/src/polyp/thread-mainloop.c +++ b/src/polyp/thread-mainloop.c @@ -206,7 +206,6 @@ void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { pthread_cond_wait(&m->cond, &m->mutex); assert(m->n_waiting > 0); m->n_waiting --; - pthread_cond_signal(&m->accept_cond); } void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) { From f931486c5ded3bdaf1adfde9f98df4c1cfce48d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 11 May 2006 13:17:27 +0000 Subject: [PATCH 0751/1514] update doxygen docs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@846 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/thread-mainloop.h | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/polyp/thread-mainloop.h b/src/polyp/thread-mainloop.h index d0bfd5ae3..94a48d021 100644 --- a/src/polyp/thread-mainloop.h +++ b/src/polyp/thread-mainloop.h @@ -29,27 +29,37 @@ PA_C_DECL_BEGIN /** \file * - * A thread based main loop implementation based on pa_mainloop.*/ + * A thread based event loop implementation based on pa_mainloop. The + * event loop is run in a helper thread in the background. A few + * synchronization primitives are available to access the objects + * attached to the event loop safely. */ -/** An opaque main loop object */ +/** An opaque threaded main loop object */ typedef struct pa_threaded_mainloop pa_threaded_mainloop; -/** Allocate a new main loop object */ +/** Allocate a new threaded main loop object. You have to call + * pa_threaded_mainloop_start() before the event loop thread starts + * running. */ pa_threaded_mainloop *pa_threaded_mainloop_new(void); -/** Free a main loop object */ +/** Free a threaded main loop object. If the event loop thread is + * still running, it is terminated using pa_threaded_mainloop_stop() + * first. */ void pa_threaded_mainloop_free(pa_threaded_mainloop* m); /** Start the event loop thread. */ int pa_threaded_mainloop_start(pa_threaded_mainloop *m); -/** Terminate the event loop thread cleanly */ +/** Terminate the event loop thread cleanly. Make sure to unlock the + * mainloop object before calling this function. */ void pa_threaded_mainloop_stop(pa_threaded_mainloop *m); /** Lock the event loop object, effectively blocking the event loop * thread from processing events. You can use this to enforce * exclusive access to all objects attached to the event loop. This - * function may not be called inside the event loop thread. */ + * lock is recursive. This function may not be called inside the event + * loop thread. Events that are dispatched from the event loop thread + * are executed with this lock held. */ void pa_threaded_mainloop_lock(pa_threaded_mainloop *m); /** Unlock the event loop object, inverse of pa_threaded_mainloop_lock() */ @@ -71,7 +81,10 @@ void pa_threaded_mainloop_wait(pa_threaded_mainloop *m); * the event loop object is unlocked. */ void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept); -/** Accept a signal from the event thread issued with pa_threaded_mainloop_signal() */ +/** Accept a signal from the event thread issued with + * pa_threaded_mainloop_signal(). This call should only be used in + * conjunction with pa_threaded_mainloop_signal() with a non-zero + * wait_for_accept value. */ void pa_threaded_mainloop_accept(pa_threaded_mainloop *m); /** Return the return value as specified with the main loop's quit() routine. */ From af54f9fcc71077fd215054ee3aa3d3a4e8b9f5ad Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 11 May 2006 14:57:24 +0000 Subject: [PATCH 0752/1514] Windows support for the threaded API. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@847 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/thread-mainloop.c | 224 +++++++++++++++++++++++++++++++++--- 1 file changed, 206 insertions(+), 18 deletions(-) diff --git a/src/polyp/thread-mainloop.c b/src/polyp/thread-mainloop.c index 916c89d81..20639e9e7 100644 --- a/src/polyp/thread-mainloop.c +++ b/src/polyp/thread-mainloop.c @@ -37,58 +37,117 @@ #include #endif +#ifdef HAVE_WINDOWS_H +#include +#endif + #include #include +#include #include "mainloop.h" #include "thread-mainloop.h" -/* FIXME: Add defined(OS_IS_WIN32) when support is added */ -#if defined(HAVE_PTHREAD) +#if defined(HAVE_PTHREAD) || defined(OS_IS_WIN32) struct pa_threaded_mainloop { pa_mainloop *real_mainloop; + int n_waiting; + int thread_running; + +#ifdef OS_IS_WIN32 + DWORD thread_id; + HANDLE thread; + CRITICAL_SECTION mutex; + pa_hashmap *cond_events; + HANDLE accept_cond; +#else pthread_t thread_id; pthread_mutex_t mutex; - int n_waiting; pthread_cond_t cond, accept_cond; - int thread_running; +#endif }; +static inline int in_worker(pa_threaded_mainloop *m) { +#ifdef OS_IS_WIN32 + return GetCurrentThreadId() == m->thread_id; +#else + return pthread_equal(pthread_self(), m->thread_id); +#endif +} + static int poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata) { +#ifdef OS_IS_WIN32 + CRITICAL_SECTION *mutex = userdata; +#else pthread_mutex_t *mutex = userdata; +#endif + int r; assert(mutex); - + /* Before entering poll() we unlock the mutex, so that * avahi_simple_poll_quit() can succeed from another thread. */ +#ifdef OS_IS_WIN32 + LeaveCriticalSection(mutex); +#else pthread_mutex_unlock(mutex); +#endif + r = poll(ufds, nfds, timeout); + +#ifdef OS_IS_WIN32 + EnterCriticalSection(mutex); +#else pthread_mutex_lock(mutex); +#endif return r; } -static void* thread(void *userdata){ +#ifdef OS_IS_WIN32 +static DWORD WINAPI thread(void *userdata) { +#else +static void* thread(void *userdata) { +#endif pa_threaded_mainloop *m = userdata; + +#ifndef OS_IS_WIN32 sigset_t mask; /* Make sure that signals are delivered to the main thread */ sigfillset(&mask); pthread_sigmask(SIG_BLOCK, &mask, NULL); +#endif +#ifdef OS_IS_WIN32 + EnterCriticalSection(&m->mutex); +#else pthread_mutex_lock(&m->mutex); - pa_mainloop_run(m->real_mainloop, NULL); - pthread_mutex_unlock(&m->mutex); +#endif + pa_mainloop_run(m->real_mainloop, NULL); + +#ifdef OS_IS_WIN32 + LeaveCriticalSection(&m->mutex); +#else + pthread_mutex_unlock(&m->mutex); +#endif + +#ifdef OS_IS_WIN32 + return 0; +#else return NULL; +#endif } pa_threaded_mainloop *pa_threaded_mainloop_new(void) { pa_threaded_mainloop *m; +#ifndef OS_IS_WIN32 pthread_mutexattr_t a; +#endif m = pa_xnew(pa_threaded_mainloop, 1); @@ -99,6 +158,14 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) { pa_mainloop_set_poll_func(m->real_mainloop, poll_func, &m->mutex); +#ifdef OS_IS_WIN32 + InitializeCriticalSection(&m->mutex); + + m->cond_events = pa_hashmap_new(NULL, NULL); + assert(m->cond_events); + m->accept_cond = CreateEvent(NULL, FALSE, FALSE, NULL); + assert(m->accept_cond); +#else pthread_mutexattr_init(&a); pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&m->mutex, &a); @@ -106,6 +173,8 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) { pthread_cond_init(&m->cond, NULL); pthread_cond_init(&m->accept_cond, NULL); +#endif + m->thread_running = 0; m->n_waiting = 0; @@ -116,7 +185,7 @@ void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + assert(!m->thread_running || !in_worker(m)); if (m->thread_running) pa_threaded_mainloop_stop(m); @@ -124,9 +193,14 @@ void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { if (m->real_mainloop) pa_mainloop_free(m->real_mainloop); +#ifdef OS_IS_WIN32 + pa_hashmap_free(m->cond_events, NULL, NULL); + CloseHandle(m->accept_cond); +#else pthread_mutex_destroy(&m->mutex); pthread_cond_destroy(&m->cond); pthread_cond_destroy(&m->accept_cond); +#endif pa_xfree(m); } @@ -136,6 +210,18 @@ int pa_threaded_mainloop_start(pa_threaded_mainloop *m) { assert(!m->thread_running); +#ifdef OS_IS_WIN32 + + EnterCriticalSection(&m->mutex); + + m->thread = CreateThread(NULL, 0, thread, m, 0, &m->thread_id); + if (!m->thread) { + LeaveCriticalSection(&m->mutex); + return -1; + } + +#else + pthread_mutex_lock(&m->mutex); if (pthread_create(&m->thread_id, NULL, thread, m) < 0) { @@ -143,9 +229,15 @@ int pa_threaded_mainloop_start(pa_threaded_mainloop *m) { return -1; } +#endif + m->thread_running = 1; +#ifdef OS_IS_WIN32 + LeaveCriticalSection(&m->mutex); +#else pthread_mutex_unlock(&m->mutex); +#endif return 0; } @@ -157,13 +249,29 @@ void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) { return; /* Make sure that this function is not called from the helper thread */ - assert(!pthread_equal(pthread_self(), m->thread_id)); + assert(!in_worker(m)); +#ifdef OS_IS_WIN32 + EnterCriticalSection(&m->mutex); +#else pthread_mutex_lock(&m->mutex); - pa_mainloop_quit(m->real_mainloop, 0); - pthread_mutex_unlock(&m->mutex); +#endif + pa_mainloop_quit(m->real_mainloop, 0); + +#ifdef OS_IS_WIN32 + LeaveCriticalSection(&m->mutex); +#else + pthread_mutex_unlock(&m->mutex); +#endif + +#ifdef OS_IS_WIN32 + WaitForSingleObject(m->thread, INFINITE); + CloseHandle(m->thread); +#else pthread_join(m->thread_id, NULL); +#endif + m->thread_running = 0; return; @@ -173,37 +281,113 @@ void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) { assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + assert(!m->thread_running || !in_worker(m)); +#ifdef OS_IS_WIN32 + EnterCriticalSection(&m->mutex); +#else pthread_mutex_lock(&m->mutex); +#endif } void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) { assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + assert(!m->thread_running || !in_worker(m)); +#ifdef OS_IS_WIN32 + LeaveCriticalSection(&m->mutex); +#else pthread_mutex_unlock(&m->mutex); +#endif } void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) { +#ifdef OS_IS_WIN32 + void *iter; + const void *key; + HANDLE event; +#endif + assert(m); - + +#ifdef OS_IS_WIN32 + + iter = NULL; + while (1) { + pa_hashmap_iterate(m->cond_events, &iter, &key); + if (key == NULL) + break; + event = (HANDLE)pa_hashmap_get(m->cond_events, key); + SetEvent(event); + } + +#else + pthread_cond_broadcast(&m->cond); - if (wait_for_accept && m->n_waiting > 0) +#endif + + if (wait_for_accept && m->n_waiting > 0) { + +#ifdef OS_IS_WIN32 + + /* This is just to make sure it's unsignaled */ + WaitForSingleObject(m->accept_cond, 0); + + LeaveCriticalSection(&m->mutex); + + WaitForSingleObject(m->accept_cond, INFINITE); + + EnterCriticalSection(&m->mutex); + +#else + pthread_cond_wait(&m->accept_cond, &m->mutex); + +#endif + + } } void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { +#ifdef OS_IS_WIN32 + HANDLE event; + DWORD result; +#endif + assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + assert(!m->thread_running || !in_worker(m)); m->n_waiting ++; + +#ifdef OS_IS_WIN32 + + event = CreateEvent(NULL, FALSE, FALSE, NULL); + assert(event); + + pa_hashmap_put(m->cond_events, event, event); + + LeaveCriticalSection(&m->mutex); + + result = WaitForSingleObject(event, INFINITE); + assert(result == WAIT_OBJECT_0); + + EnterCriticalSection(&m->mutex); + + pa_hashmap_remove(m->cond_events, event); + + CloseHandle(event); + +#else + pthread_cond_wait(&m->cond, &m->mutex); + +#endif + assert(m->n_waiting > 0); m->n_waiting --; } @@ -212,9 +396,13 @@ void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) { assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id)); + assert(!m->thread_running || !in_worker(m)); +#ifdef OS_IS_WIN32 + SetEvent(m->accept_cond); +#else pthread_cond_signal(&m->accept_cond); +#endif } int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) { From eecc04cf282392afb624fb14ab4f6a564bab4875 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 11 May 2006 21:38:16 +0000 Subject: [PATCH 0753/1514] fix iochannel for hangup signals git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@848 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/iochannel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index 623925acd..aba0399c2 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -91,7 +91,7 @@ static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_fla assert(fd >= 0); assert(userdata); - if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) & !io->hungup) { + if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) { io->hungup = 1; changed = 1; } From 11782f0b749e261a6241570dc160075e9baf0a93 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 11 May 2006 22:37:42 +0000 Subject: [PATCH 0754/1514] fix hangup detection for recording streams git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@849 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 2c956a7e2..7a6861fd5 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -58,7 +58,7 @@ #define DEFAULT_COOKIE_FILE ".esd_auth" -#define PLAYBACK_BUFFER_SECONDS (.5) +#define PLAYBACK_BUFFER_SECONDS (.25) #define PLAYBACK_BUFFER_FRAGMENTS (10) #define RECORD_BUFFER_SECONDS (5) #define RECORD_BUFFER_FRAGMENTS (100) @@ -985,7 +985,12 @@ static void do_work(struct connection *c) { if (pa_iochannel_is_readable(c->io)) { if (do_read(c) < 0) goto fail; - } else if (pa_iochannel_is_hungup(c->io)) + } + + if (c->state == ESD_STREAMING_DATA && c->source_output && pa_iochannel_is_hungup(c->io)) + /* In case we are in capture mode we will never call read() + * on the socket, hence we need to detect the hangup manually + * here, instead of simply waiting for read() to return 0. */ goto fail; if (pa_iochannel_is_writable(c->io)) @@ -1008,13 +1013,10 @@ fail: connection_free(c); } - static void io_callback(pa_iochannel*io, void *userdata) { struct connection *c = userdata; assert(io && c && c->io == io); -/* pa_log("IO"); */ - do_work(c); } From afdec0532fc1fde7d53bce689d8da0b98dc04d3a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 13 May 2006 19:55:28 +0000 Subject: [PATCH 0755/1514] remove superfluous log message git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@850 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/mainloop-signal.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index 2c9484e46..4ffa00ba3 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -84,8 +84,6 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags int sig; assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); - pa_log(__FILE__": Signal pipe callback"); - if ((r = pa_read(signal_pipe[0], &sig, sizeof(sig))) < 0) { if (errno == EAGAIN) return; From b6812029ba32002aea1576339571eafde62f124a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 13 May 2006 20:29:32 +0000 Subject: [PATCH 0756/1514] use default alsa channel map for alsa devices git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@851 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 44 ++++++++++++++++++++++++++++++++ src/modules/alsa-util.h | 4 +++ src/modules/module-alsa-sink.c | 14 +++++++++- src/modules/module-alsa-source.c | 14 +++++++++- 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 8bb33c2f7..4c9cde9e0 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -340,3 +340,47 @@ snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name) { return elem; } + +pa_channel_map* pa_alsa_channel_map_init_auto(pa_channel_map *m, unsigned channels) { + assert(m); + assert(channels > 0); + assert(channels <= PA_CHANNELS_MAX); + + pa_channel_map_init(m); + + m->channels = channels; + + /* The standard ALSA channel order */ + + switch (channels) { + case 1: + m->map[0] = PA_CHANNEL_POSITION_MONO; + return m; + + case 8: + m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT; + m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT; + /* Fall through */ + + case 6: + m->map[5] = PA_CHANNEL_POSITION_LFE; + /* Fall through */ + + case 5: + m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER; + /* Fall through */ + + case 4: + m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT; + m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + /* Fall through */ + + case 2: + m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + return m; + + default: + return NULL; + } +} diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index c908d7e04..bad6e9bf0 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -27,6 +27,8 @@ #include #include +#include + struct pa_alsa_fdlist; struct pa_alsa_fdlist *pa_alsa_fdlist_new(void); @@ -40,4 +42,6 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev); snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name); +pa_channel_map* pa_alsa_channel_map_init_auto(pa_channel_map *m, unsigned channels); + #endif diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 84b506e16..2d90afaf4 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -324,10 +324,22 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } + + pa_alsa_channel_map_init_auto(&map, ss.channels); + if ((pa_modargs_get_channel_map(ma, &map) < 0)) { + pa_log(__FILE__": invalid channel map."); + goto fail; + } + + if (ss.channels != map.channels) { + pa_log(__FILE__": channel map and sample specification don't match."); + goto fail; + } + frame_size = pa_frame_size(&ss); periods = 8; diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 84ae992bb..ad52271ce 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -312,10 +312,22 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec(ma, &ss) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } + + pa_alsa_channel_map_init_auto(&map, ss.channels); + if ((pa_modargs_get_channel_map(ma, &map) < 0)) { + pa_log(__FILE__": invalid channel map."); + goto fail; + } + + if (ss.channels != map.channels) { + pa_log(__FILE__": channel map and sample specification don't match."); + goto fail; + } + frame_size = pa_frame_size(&ss); periods = 12; From 7abf17edcdae7d29231ff6619f22212b0ef9eee7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 13 May 2006 20:47:55 +0000 Subject: [PATCH 0757/1514] fix fragment size calculation for module-alsa-source git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@852 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-source.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index ad52271ce..a47e0bc6f 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -118,7 +118,11 @@ static void do_read(struct userdata *u) { u->memchunk.index = 0; } - assert(u->memchunk.memblock && u->memchunk.memblock->data && u->memchunk.length && u->memchunk.memblock->length && (u->memchunk.length % u->frame_size) == 0); + assert(u->memchunk.memblock); + assert(u->memchunk.length); + assert(u->memchunk.memblock->data); + assert(u->memchunk.memblock->length); + assert(u->memchunk.length % u->frame_size == 0); if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) { if (frames == -EAGAIN) @@ -331,12 +335,12 @@ int pa__init(pa_core *c, pa_module*m) { frame_size = pa_frame_size(&ss); periods = 12; - fragsize = 1024; + fragsize = frame_size*1024; if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { pa_log(__FILE__": failed to parse buffer metrics"); goto fail; } - period_size = fragsize; + period_size = fragsize/frame_size; u = pa_xmalloc0(sizeof(struct userdata)); m->userdata = u; @@ -419,9 +423,9 @@ int pa__init(pa_core *c, pa_module*m) { } u->frame_size = frame_size; - u->fragment_size = period_size; + u->fragment_size = period_size * frame_size; - pa_log(__FILE__": using %u fragments of size %lu bytes.", periods, (long unsigned)u->fragment_size); + pa_log(__FILE__": using %u fragments of size %lu bytes.", periods, (long unsigned) u->fragment_size); u->memchunk.memblock = NULL; u->memchunk.index = u->memchunk.length = 0; From c3b9c3dc73e73e5c671599f914408e9f8e903a1b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 13 May 2006 21:18:32 +0000 Subject: [PATCH 0758/1514] don't hit an assert when trying to resample data for 6channel audio git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@853 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/resampler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/polypcore/resampler.c b/src/polypcore/resampler.c index a50b21bfb..7e85e2708 100644 --- a/src/polypcore/resampler.c +++ b/src/polypcore/resampler.c @@ -168,7 +168,8 @@ void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) } size_t pa_resampler_request(pa_resampler *r, size_t out_length) { - assert(r && (out_length % r->o_fz) == 0); + assert(r); + return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz; } From 0231e6ea4100ccb6c525012c0dd51dbb88aab189 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 13 May 2006 21:19:02 +0000 Subject: [PATCH 0759/1514] first set buffer size, and afterwards period size git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@854 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 4c9cde9e0..a81921651 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -273,8 +273,8 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 (ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[ss->format])) < 0 || (ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0 || (ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss->channels)) < 0 || - (*periods > 0 && (ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0) || (*period_size > 0 && (ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL)) < 0) || + (*periods > 0 && (ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0) || (ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) goto finish; From 0f22d63289779931cfc3ddd3d2cdfb579e4be3c7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 13 May 2006 21:20:34 +0000 Subject: [PATCH 0760/1514] * set default fragment metrics depending on the sample specs of the device in OSS and ALSA * fix fragment size calculation in module-alsa-sink git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@855 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 10 +++++++--- src/modules/module-alsa-source.c | 8 +++++--- src/modules/module-oss.c | 18 +++++++++--------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 2d90afaf4..ad6bbb709 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -342,13 +342,17 @@ int pa__init(pa_core *c, pa_module*m) { frame_size = pa_frame_size(&ss); + /* Fix latency to 100ms */ periods = 8; - fragsize = 1024; + fragsize = pa_bytes_per_second(&ss)/128; + + pa_log("req: %i %i", periods, fragsize); + if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { pa_log(__FILE__": failed to parse buffer metrics"); goto fail; } - period_size = fragsize; + period_size = fragsize/frame_size; u = pa_xmalloc0(sizeof(struct userdata)); m->userdata = u; @@ -431,7 +435,7 @@ int pa__init(pa_core *c, pa_module*m) { } u->frame_size = frame_size; - u->fragment_size = period_size; + u->fragment_size = period_size * frame_size; pa_log_info(__FILE__": using %u fragments of size %lu bytes.", periods, (long unsigned)u->fragment_size); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index a47e0bc6f..660bc83b3 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -333,9 +333,11 @@ int pa__init(pa_core *c, pa_module*m) { } frame_size = pa_frame_size(&ss); - + + /* Fix latency to 100ms */ periods = 12; - fragsize = frame_size*1024; + fragsize = pa_bytes_per_second(&ss)/128; + if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { pa_log(__FILE__": failed to parse buffer metrics"); goto fail; @@ -425,7 +427,7 @@ int pa__init(pa_core *c, pa_module*m) { u->frame_size = frame_size; u->fragment_size = period_size * frame_size; - pa_log(__FILE__": using %u fragments of size %lu bytes.", periods, (long unsigned) u->fragment_size); + pa_log_info(__FILE__": using %u fragments of size %lu bytes.", periods, (long unsigned) u->fragment_size); u->memchunk.memblock = NULL; u->memchunk.index = u->memchunk.length = 0; diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 0795ae39a..4d811a76f 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -97,8 +97,6 @@ static const char* const valid_modargs[] = { #define DEFAULT_SINK_NAME "oss_output" #define DEFAULT_SOURCE_NAME "oss_input" #define DEFAULT_DEVICE "/dev/dsp" -#define DEFAULT_NFRAGS 12 -#define DEFAULT_FRAGSIZE 1024 static void update_usage(struct userdata *u) { pa_module_set_used(u->module, @@ -348,19 +346,21 @@ int pa__init(pa_core *c, pa_module*m) { mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); - nfrags = DEFAULT_NFRAGS; - frag_size = DEFAULT_FRAGSIZE; - if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { - pa_log(__FILE__": failed to parse fragments arguments"); - goto fail; - } - ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { pa_log(__FILE__": failed to parse sample specification or channel map"); goto fail; } + /* Fix latency to 100ms */ + nfrags = 12; + frag_size = pa_bytes_per_second(&ss)/128; + + if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { + pa_log(__FILE__": failed to parse fragments arguments"); + goto fail; + } + if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, NULL)) < 0) goto fail; From 682dfd7adb8aec8d17706a224c6ac24b9b2c08d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 13 May 2006 21:40:38 +0000 Subject: [PATCH 0761/1514] fix esound sample cache names git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@856 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 7a6861fd5..56a113652 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -680,6 +680,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ memcpy(&sc_length, data, sizeof(int32_t)); sc_length = MAYBE_INT32_SWAP(c->swap_byte_order, sc_length); + data = (const char*)data + sizeof(int32_t); CHECK_VALIDITY(sc_length <= MAX_CACHE_SAMPLE_SIZE, "Sample too large."); @@ -694,7 +695,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ c->scache.sample_spec = ss; assert(!c->scache.name); c->scache.name = pa_xstrdup(name); - + c->state = ESD_CACHING_SAMPLE; pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, &idx); From e46f8f8eb3fd586f8728e43292509434e0e8b089 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 00:36:06 +0000 Subject: [PATCH 0762/1514] modify argument order of pa_client_new() to actually match how it is usually called git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@857 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/client.c | 2 +- src/polypcore/client.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/polypcore/client.c b/src/polypcore/client.c index 852f87b02..be970470c 100644 --- a/src/polypcore/client.c +++ b/src/polypcore/client.c @@ -34,7 +34,7 @@ #include "client.h" -pa_client *pa_client_new(pa_core *core, const char *name, const char *driver) { +pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) { pa_client *c; int r; assert(core); diff --git a/src/polypcore/client.h b/src/polypcore/client.h index 8ddc6d942..f6ff935db 100644 --- a/src/polypcore/client.h +++ b/src/polypcore/client.h @@ -42,7 +42,7 @@ struct pa_client { void *userdata; }; -pa_client *pa_client_new(pa_core *c, const char *name, const char *driver); +pa_client *pa_client_new(pa_core *c, const char *driver, const char *name); /* This function should be called only by the code that created the client */ void pa_client_free(pa_client *c); From be05b18c6fb6f0e2e2b74ffdf251692a45eaa045 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 00:41:18 +0000 Subject: [PATCH 0763/1514] * add new parameter to pa_open_config_file() to specify open mode * modify pa_sink_input_new() to take initial volume settings as argument * call pa_sink_input_set_volume() when changing stream volume in protocol-esound.c to make sure that subscribe events are issued properly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@858 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 4 ++-- src/modules/module-combine.c | 2 +- src/modules/module-match.c | 4 ++-- src/modules/module-sine.c | 2 +- src/modules/rtp/module-rtp-recv.c | 2 +- src/polyp/client-conf.c | 2 +- src/polypcore/play-memchunk.c | 5 +---- src/polypcore/protocol-esound.c | 18 ++++++++++-------- src/polypcore/protocol-native.c | 4 +--- src/polypcore/protocol-simple.c | 2 +- src/polypcore/sink-input.c | 17 +++++++++++++++-- src/polypcore/sink-input.h | 1 + src/polypcore/sound-file-stream.c | 4 +--- src/polypcore/util.c | 8 ++++---- src/polypcore/util.h | 2 +- 15 files changed, 43 insertions(+), 34 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index ac5fbb166..f41bb4b19 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -84,7 +84,7 @@ pa_daemon_conf* pa_daemon_conf_new(void) { FILE *f; pa_daemon_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); - if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file))) + if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file, "r"))) fclose(f); #ifdef DLSEARCHPATH @@ -233,7 +233,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { f = filename ? fopen(c->config_file = pa_xstrdup(filename), "r") : - pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file); + pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file, "r"); if (!f && errno != ENOENT) { pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, strerror(errno)); diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 470104970..3b927d135 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -238,7 +238,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample sink->core->memblock_stat); snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1); - if (!(o->sink_input = pa_sink_input_new(sink, __FILE__, t, &u->sink->sample_spec, &u->sink->channel_map, 1, resample_method))) + if (!(o->sink_input = pa_sink_input_new(sink, __FILE__, t, &u->sink->sample_spec, &u->sink->channel_map, NULL, 1, resample_method))) goto fail; o->sink_input->get_latency = sink_input_get_latency_cb; diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 598175170..f6316b93a 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -43,7 +43,7 @@ #include "module-match-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Sink input matching module") +PA_MODULE_DESCRIPTION("Playback stream expression matching module") PA_MODULE_USAGE("table=") PA_MODULE_VERSION(PACKAGE_VERSION) @@ -81,7 +81,7 @@ static int load_rules(struct userdata *u, const char *filename) { f = filename ? fopen(fn = pa_xstrdup(filename), "r") : - pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn); + pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn, "r"); if (!f) { pa_log(__FILE__": failed to open file '%s': %s", fn, strerror(errno)); diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index d5a0fa479..3267d49bb 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -141,7 +141,7 @@ int pa__init(pa_core *c, pa_module*m) { calc_sine(u->memblock->data, u->memblock->length, frequency); snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); - if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, t, &ss, NULL, 0, -1))) + if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, t, &ss, NULL, NULL, 0, -1))) goto fail; u->sink_input->peek = sink_input_peek; diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index cd5f10e66..925a1210c 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -286,7 +286,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in sdp_info->session_name ? sdp_info->session_name : "", sdp_info->session_name ? ")" : ""); - s->sink_input = pa_sink_input_new(sink, __FILE__, c, &sdp_info->sample_spec, NULL, 0, PA_RESAMPLER_INVALID); + s->sink_input = pa_sink_input_new(sink, __FILE__, c, &sdp_info->sample_spec, NULL, NULL, 0, PA_RESAMPLER_INVALID); pa_xfree(c); if (!s->sink_input) { diff --git a/src/polyp/client-conf.c b/src/polyp/client-conf.c index 4202b14c6..d3ad0767e 100644 --- a/src/polyp/client-conf.c +++ b/src/polyp/client-conf.c @@ -119,7 +119,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { f = filename ? fopen((fn = pa_xstrdup(filename)), "r") : - pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn); + pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn, "r"); if (!f && errno != EINTR) { pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, strerror(errno)); diff --git a/src/polypcore/play-memchunk.c b/src/polypcore/play-memchunk.c index ec79254b1..37ebdcf11 100644 --- a/src/polypcore/play-memchunk.c +++ b/src/polypcore/play-memchunk.c @@ -98,12 +98,9 @@ int pa_play_memchunk( if (cvolume && pa_cvolume_is_muted(cvolume)) return 0; - if (!(si = pa_sink_input_new(sink, name, __FILE__, ss, map, 0, PA_RESAMPLER_INVALID))) + if (!(si = pa_sink_input_new(sink, name, __FILE__, ss, map, cvolume, 0, PA_RESAMPLER_INVALID))) return -1; - if (cvolume) - si->volume = *cvolume; - si->peek = sink_input_peek; si->drop = sink_input_drop; si->kill = sink_input_kill; diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 56a113652..50c8b6b5b 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -345,7 +345,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t assert(!c->sink_input && !c->input_memblockq); - c->sink_input = pa_sink_input_new(sink, __FILE__, name, &ss, NULL, 0, -1); + c->sink_input = pa_sink_input_new(sink, __FILE__, name, &ss, NULL, NULL, 0, -1); CHECK_VALIDITY(c->sink_input, "Failed to create sink input."); @@ -532,9 +532,10 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v assert(t >= k*2+s); if (conn->sink_input) { + pa_cvolume volume = *pa_sink_input_get_volume(conn->sink_input); rate = conn->sink_input->sample_spec.rate; - lvolume = (conn->sink_input->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM; - rvolume = (conn->sink_input->volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM; + lvolume = (volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM; + rvolume = (volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM; format = format_native2esd(&conn->sink_input->sample_spec); } @@ -643,11 +644,12 @@ static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume); data = (const char*)data + sizeof(uint32_t); - if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx))) { - assert(conn->sink_input); - conn->sink_input->volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; - conn->sink_input->volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; - conn->sink_input->volume.channels = 2; + if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx)) && conn->sink_input) { + pa_cvolume volume; + volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; + volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; + volume.channels = 2; + pa_sink_input_set_volume(conn->sink_input, &volume); ok = 1; } else ok = 0; diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index a0fc286da..aa6360722 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -386,7 +386,7 @@ static struct playback_stream* playback_stream_new( if (ssync && ssync->sink_input->sink != sink) return NULL; - if (!(sink_input = pa_sink_input_new(sink, __FILE__, name, ss, map, 0, -1))) + if (!(sink_input = pa_sink_input_new(sink, __FILE__, name, ss, map, volume, 0, -1))) return NULL; s = pa_xnew(struct playback_stream, 1); @@ -436,8 +436,6 @@ static struct playback_stream* playback_stream_new( s->requested_bytes = 0; s->drain_request = 0; - - s->sink_input->volume = *volume; pa_idxset_put(c->output_streams, s, &s->index); diff --git a/src/polypcore/protocol-simple.c b/src/polypcore/protocol-simple.c index c2f534443..1e3b169c4 100644 --- a/src/polypcore/protocol-simple.c +++ b/src/polypcore/protocol-simple.c @@ -346,7 +346,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) goto fail; } - if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, c->client->name, &p->sample_spec, NULL, 0, -1))) { + if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, c->client->name, &p->sample_spec, NULL, NULL, 0, -1))) { pa_log(__FILE__": Failed to create sink input."); goto fail; } diff --git a/src/polypcore/sink-input.c b/src/polypcore/sink-input.c index e1703b97a..26e63b850 100644 --- a/src/polypcore/sink-input.c +++ b/src/polypcore/sink-input.c @@ -43,6 +43,7 @@ pa_sink_input* pa_sink_input_new( const char *name, const pa_sample_spec *spec, const pa_channel_map *map, + const pa_cvolume *volume, int variable_rate, int resample_method) { @@ -56,6 +57,7 @@ pa_sink_input* pa_sink_input_new( assert(spec); assert(s->state == PA_SINK_RUNNING); + if (pa_idxset_size(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink."); return NULL; @@ -64,8 +66,16 @@ pa_sink_input* pa_sink_input_new( if (resample_method == PA_RESAMPLER_INVALID) resample_method = s->core->resample_method; + if (map && spec->channels != map->channels) + return NULL; + + if (volume && spec->channels != volume->channels) + return NULL; + if (!map) { - pa_channel_map_init_auto(&tmap, spec->channels); + if (!(pa_channel_map_init_auto(&tmap, spec->channels))) + return NULL; + map = &tmap; } @@ -85,7 +95,10 @@ pa_sink_input* pa_sink_input_new( i->sample_spec = *spec; i->channel_map = *map; - pa_cvolume_reset(&i->volume, spec->channels); + if (volume) + i->volume = *volume; + else + pa_cvolume_reset(&i->volume, spec->channels); i->peek = NULL; i->drop = NULL; diff --git a/src/polypcore/sink-input.h b/src/polypcore/sink-input.h index e4b8bda47..4cf4460a4 100644 --- a/src/polypcore/sink-input.h +++ b/src/polypcore/sink-input.h @@ -75,6 +75,7 @@ pa_sink_input* pa_sink_input_new( const char *name, const pa_sample_spec *spec, const pa_channel_map *map, + const pa_cvolume *volume, int variable_rate, int resample_method); diff --git a/src/polypcore/sound-file-stream.c b/src/polypcore/sound-file-stream.c index e242cfea0..ca762d6a3 100644 --- a/src/polypcore/sound-file-stream.c +++ b/src/polypcore/sound-file-stream.c @@ -158,11 +158,9 @@ int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume) { goto fail; } - if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, fname, &ss, NULL, 0, -1))) + if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, fname, &ss, NULL, volume, 0, -1))) goto fail; - if (volume) - u->sink_input->volume = *volume; u->sink_input->peek = sink_input_peek; u->sink_input->drop = sink_input_drop; u->sink_input->kill = sink_input_kill; diff --git a/src/polypcore/util.c b/src/polypcore/util.c index c1f82a208..6f7f88198 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -1037,7 +1037,7 @@ int pa_unlock_lockfile(const char *fn, int fd) { * file system. If "result" is non-NULL, a pointer to a newly * allocated buffer containing the used configuration file is * stored there.*/ -FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) { +FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result, const char *mode) { const char *fn; char h[PATH_MAX]; @@ -1058,7 +1058,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env if (result) *result = pa_xstrdup(fn); - return fopen(fn, "r"); + return fopen(fn, mode); } if (local && pa_get_home_dir(h, sizeof(h))) { @@ -1073,7 +1073,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env fn = buf; #endif - f = fopen(fn, "r"); + f = fopen(fn, mode); if (f || errno != ENOENT) { if (result) @@ -1101,7 +1101,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env if (result) *result = pa_xstrdup(global); - return fopen(global, "r"); + return fopen(global, mode); } /* Format the specified data as a hexademical string */ diff --git a/src/polypcore/util.h b/src/polypcore/util.h index 2d5894c33..df71672f4 100644 --- a/src/polypcore/util.h +++ b/src/polypcore/util.h @@ -87,7 +87,7 @@ int pa_lock_fd(int fd, int b); int pa_lock_lockfile(const char *fn); int pa_unlock_lockfile(const char *fn, int fd); -FILE *pa_open_config_file(const char *env, const char *global, const char *local, char **result); +FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result, const char *mode); char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength); size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength); From b3e16559fceaef151226b82408c118cef448993b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 00:41:56 +0000 Subject: [PATCH 0764/1514] add new module module-volume-restore which saves and restores volume of playback streams git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@859 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 12 +- src/modules/module-volume-restore.c | 361 ++++++++++++++++++++++++++++ 2 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 src/modules/module-volume-restore.c diff --git a/src/Makefile.am b/src/Makefile.am index 72e3c1eb7..9e7b4a39b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -742,7 +742,8 @@ modlib_LTLIBRARIES += \ module-null-sink.la \ module-esound-sink.la \ module-http-protocol-tcp.la \ - module-detect.la + module-detect.la \ + module-volume-restore.la # See comment at librtp.la above if !OS_IS_WIN32 @@ -870,7 +871,8 @@ SYMDEF_FILES = \ modules/rtp/module-rtp-send-symdef.h \ modules/rtp/module-rtp-recv-symdef.h \ modules/module-jack-sink-symdef.h \ - modules/module-jack-source-symdef.h + modules/module-jack-source-symdef.h \ + modules/module-volume-restore-symdef.h EXTRA_DIST += $(SYMDEF_FILES) @@ -1087,6 +1089,12 @@ module_detect_la_LDFLAGS = -module -avoid-version module_detect_la_LIBADD = $(AM_LIBADD) libpolypcore.la module_detect_la_CFLAGS = $(AM_CFLAGS) +# Volume restore module +module_volume_restore_la_SOURCES = modules/module-volume-restore.c +module_volume_restore_la_LDFLAGS = -module -avoid-version +module_volume_restore_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_volume_restore_la_CFLAGS = $(AM_CFLAGS) + # RTP modules module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c module_rtp_send_la_LDFLAGS = -module -avoid-version diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c new file mode 100644 index 000000000..c32bb3a93 --- /dev/null +++ b/src/modules/module-volume-restore.c @@ -0,0 +1,361 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-volume-restore-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Playback stream automatic volume restore module") +PA_MODULE_USAGE("table=") +PA_MODULE_VERSION(PACKAGE_VERSION) + +#define WHITESPACE "\n\r \t" + +#define DEFAULT_VOLUME_TABLE_FILE ".polypaudio/volume.table" + +static const char* const valid_modargs[] = { + "table", + NULL, +}; + +struct rule { + char* name; + pa_cvolume volume; +}; + +struct userdata { + pa_hashmap *hashmap; + pa_subscription *subscription; + int modified; + char *table_file; +}; + +static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { + char *p; + long k; + unsigned i; + + assert(s); + assert(v); + + if (!isdigit(*s)) + return NULL; + + k = strtol(s, &p, 0); + if (k <= 0 || k > PA_CHANNELS_MAX) + return NULL; + + v->channels = (unsigned) k; + + for (i = 0; i < v->channels; i++) { + p += strspn(p, WHITESPACE); + + if (!isdigit(*p)) + return NULL; + + k = strtol(p, &p, 0); + + if (k < PA_VOLUME_MUTED) + return NULL; + + v->values[i] = (pa_volume_t) k; + } + + if (*p != 0) + return NULL; + + return v; +} + +static int load_rules(struct userdata *u) { + FILE *f; + int n = 0; + int ret = -1; + char buf_name[256], buf_volume[256]; + char *ln = buf_name; + + f = u->table_file ? + fopen(u->table_file, "r") : + pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "r"); + + if (!f) { + if (errno == ENOENT) { + pa_log(__FILE__": starting with empty ruleset."); + ret = 0; + } else + pa_log(__FILE__": failed to open file '%s': %s", u->table_file, strerror(errno)); + + goto finish; + } + + while (!feof(f)) { + struct rule *rule; + pa_cvolume v; + + if (!fgets(ln, sizeof(buf_name), f)) + break; + + n++; + + pa_strip_nl(ln); + + if (ln[0] == '#' || !*ln ) + continue; + + if (ln == buf_name) { + ln = buf_volume; + continue; + } + + assert(ln == buf_volume); + + if (!parse_volume(buf_volume, &v)) { + pa_log(__FILE__": parse failure in %s:%u, stopping parsing", u->table_file, n); + goto finish; + } + + ln = buf_name; + + if (pa_hashmap_get(u->hashmap, buf_name)) { + pa_log(__FILE__": double entry in %s:%u, ignoring", u->table_file, n); + goto finish; + } + + rule = pa_xnew(struct rule, 1); + rule->name = pa_xstrdup(buf_name); + rule->volume = v; + + pa_hashmap_put(u->hashmap, rule->name, rule); + } + + if (ln == buf_volume) { + pa_log(__FILE__": invalid number of lines in %s.", u->table_file); + goto finish; + } + + ret = 0; + +finish: + if (f) + fclose(f); + + return ret; +} + +static int save_rules(struct userdata *u) { + FILE *f; + int ret = -1; + void *state = NULL; + struct rule *rule; + + f = u->table_file ? + fopen(u->table_file, "w") : + pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w"); + + if (!f) { + pa_log(__FILE__": failed to open file '%s': %s", u->table_file, strerror(errno)); + goto finish; + } + + while ((rule = pa_hashmap_iterate(u->hashmap, &state, NULL))) { + unsigned i; + + fprintf(f, "%s\n%u", rule->name, rule->volume.channels); + + for (i = 0; i < rule->volume.channels; i++) + fprintf(f, " %u", rule->volume.values[i]); + + + fprintf(f, "\n"); + } + + ret = 0; + +finish: + if (f) + fclose(f); + + return ret; +} + +static char* client_name(pa_client *c) { + char *t, *e; + + if (!c->name || !c->driver) + return NULL; + + t = pa_sprintf_malloc("%s$%s", c->driver, c->name); + t[strcspn(t, "\n\r#")] = 0; + + if (!*t) + return NULL; + + if ((e = strrchr(t, '('))) { + char *k = e + 1 + strspn(e + 1, "0123456789-"); + + /* Dirty trick: truncate all trailing parens with numbers in + * between, since they are usually used to identify multiple + * sessions of the same application, which is something we + * explicitly don't want. Besides other stuff this makes xmms + * with esound work properly for us. */ + + if (*k == ')' && *(k+1) == 0) + *e = 0; + } + + return t; +} + +static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + struct userdata *u = userdata; + pa_sink_input *si; + struct rule *r; + char *name; + + assert(c); + assert(u); + + if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) && + t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE)) + return; + + if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) + return; + + if (!si->client || !(name = client_name(si->client))) + return; + + if ((r = pa_hashmap_get(u->hashmap, name))) { + pa_xfree(name); + + if (((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) && si->sample_spec.channels == r->volume.channels) { + pa_log_info(__FILE__": Restoring volume for <%s>", r->name); + pa_sink_input_set_volume(si, &r->volume); + } else if (!pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { + pa_log_info(__FILE__": Saving volume for <%s>", r->name); + r->volume = *pa_sink_input_get_volume(si); + u->modified = 1; + } + + } else { + pa_log_info(__FILE__": Creating new entry for <%s>", name); + + r = pa_xnew(struct rule, 1); + r->name = name; + r->volume = *pa_sink_input_get_volume(si); + pa_hashmap_put(u->hashmap, r->name, r); + + u->modified = 1; + } +} + +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; + struct userdata *u; + + assert(c); + assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": Failed to parse module arguments"); + goto fail; + } + + u = pa_xnew(struct userdata, 1); + u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + u->subscription = NULL; + u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL)); + u->modified = 0; + + m->userdata = u; + + if (load_rules(u) < 0) + goto fail; + + u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); + + pa_modargs_free(ma); + return 0; + +fail: + pa__done(c, m); + + if (ma) + pa_modargs_free(ma); + + return -1; +} + +static void free_func(void *p, void *userdata) { + struct rule *r = p; + assert(r); + + pa_xfree(r->name); + pa_xfree(r); +} + +void pa__done(pa_core *c, pa_module*m) { + struct userdata* u; + + assert(c); + assert(m); + + if (!(u = m->userdata)) + return; + + if (u->subscription) + pa_subscription_free(u->subscription); + + if (u->hashmap) { + + if (u->modified) + save_rules(u); + + pa_hashmap_free(u->hashmap, free_func, NULL); + } + + pa_xfree(u->table_file); + pa_xfree(u); +} + + From b10f2dc0ae0f592530c39ee72f05900cd3bbf426 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 14:07:48 +0000 Subject: [PATCH 0765/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@860 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + src/polypcore/core-subscribe.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/todo b/doc/todo index e6ad0d5f6..7f31f0cfc 100644 --- a/doc/todo +++ b/doc/todo @@ -27,6 +27,7 @@ Post 0.8: changes if you're modifying a sink/source since those might have a different map. - don't install .a files of modules +- check utf8 validity of strings Long term: - pass meta info for hearing impaired diff --git a/src/polypcore/core-subscribe.c b/src/polypcore/core-subscribe.c index e2dd9ae3b..fa6c0e509 100644 --- a/src/polypcore/core-subscribe.c +++ b/src/polypcore/core-subscribe.c @@ -118,7 +118,8 @@ void pa_subscription_free_all(pa_core *c) { } } -/*static void dump_event(pa_subscription_event*e) { +#if 0 +static void dump_event(pa_subscription_event*e) { switch (e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { case PA_SUBSCRIPTION_EVENT_SINK: pa_log(__FILE__": SINK_EVENT"); @@ -159,7 +160,8 @@ void pa_subscription_free_all(pa_core *c) { } pa_log(__FILE__": %u", e->index); -}*/ +} +#endif /* Deferred callback for dispatching subscirption events */ static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) { @@ -169,7 +171,6 @@ static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) { c->mainloop->defer_enable(c->subscription_defer_event, 0); - /* Dispatch queued events */ if (c->subscription_event_queue) { From bf52fb93b4fb5cd9e83963d9d2bf572022427eed Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 16:02:09 +0000 Subject: [PATCH 0766/1514] add utf8 validity checking API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@861 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 +- src/polypcore/utf8.c | 115 +++++++++++++++++++++++++++++++++++++++++++ src/polypcore/utf8.h | 27 ++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/polypcore/utf8.c create mode 100644 src/polypcore/utf8.h diff --git a/src/Makefile.am b/src/Makefile.am index 9e7b4a39b..903359ada 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -481,6 +481,7 @@ polypcoreinclude_HEADERS = \ polypcore/strbuf.h \ polypcore/tokenizer.h \ polypcore/util.h \ + polypcore/utf8.h \ polypcore/xmalloc.h lib_LTLIBRARIES += libpolypcore.la @@ -541,7 +542,8 @@ libpolypcore_la_SOURCES += \ polypcore/tokenizer.c polypcore/tokenizer.h \ polypcore/util.c polypcore/util.h \ polypcore/winsock.h \ - polypcore/xmalloc.c polypcore/xmalloc.h + polypcore/xmalloc.c polypcore/xmalloc.h \ + polypcore/utf8.c polypcore/utf8.h if OS_IS_WIN32 libpolypcore_la_SOURCES += \ diff --git a/src/polypcore/utf8.c b/src/polypcore/utf8.c new file mode 100644 index 000000000..b77584393 --- /dev/null +++ b/src/polypcore/utf8.c @@ -0,0 +1,115 @@ +/* $Id */ + +/* This file is based on the GLIB utf8 validation functions. The + * original license text follows. */ + +/* gutf8.c - Operations on UTF-8 strings. + * + * Copyright (C) 1999 Tom Tromey + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "utf8.h" + +#define UNICODE_VALID(Char) \ + ((Char) < 0x110000 && \ + (((Char) & 0xFFFFF800) != 0xD800) && \ + ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ + ((Char) & 0xFFFE) != 0xFFFE) + + +#define CONTINUATION_CHAR \ + do { \ + if ((*(const unsigned char *)p & 0xc0) != 0x80) /* 10xxxxxx */ \ + goto error; \ + val <<= 6; \ + val |= (*(const unsigned char *)p) & 0x3f; \ + } while(0) + + +const char * +pa_utf8_valid (const char *str) + +{ + unsigned val = 0; + unsigned min = 0; + const char *p; + + for (p = str; *p; p++) + { + if (*(const unsigned char *)p < 128) + /* done */; + else + { + const char *last; + + last = p; + if ((*(const unsigned char *)p & 0xe0) == 0xc0) /* 110xxxxx */ + { + if ( ((*(const unsigned char *)p & 0x1e) == 0)) + goto error; + p++; + if ( ((*(const unsigned char *)p & 0xc0) != 0x80)) /* 10xxxxxx */ + goto error; + } + else + { + if ((*(const unsigned char *)p & 0xf0) == 0xe0) /* 1110xxxx */ + { + min = (1 << 11); + val = *(const unsigned char *)p & 0x0f; + goto TWO_REMAINING; + } + else if ((*(const unsigned char *)p & 0xf8) == 0xf0) /* 11110xxx */ + { + min = (1 << 16); + val = *(const unsigned char *)p & 0x07; + } + else + goto error; + + p++; + CONTINUATION_CHAR; + TWO_REMAINING: + p++; + CONTINUATION_CHAR; + p++; + CONTINUATION_CHAR; + + if ( (val < min)) + goto error; + + if ( (!UNICODE_VALID(val))) + goto error; + } + + continue; + + error: + return NULL; + } + } + + return str; +} diff --git a/src/polypcore/utf8.h b/src/polypcore/utf8.h new file mode 100644 index 000000000..7f3949781 --- /dev/null +++ b/src/polypcore/utf8.h @@ -0,0 +1,27 @@ +#ifndef fooutf8hfoo +#define fooutf8hfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +const char *pa_utf8_valid(const char *str); + +#endif From a414cc2f32beb5cbdac60dc0e083be876ab28eb6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 16:02:40 +0000 Subject: [PATCH 0767/1514] check for valid utf8 strings git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@862 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-native.c | 44 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index aa6360722..3b9041342 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "protocol-native.h" @@ -728,8 +729,8 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || *sink_name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); @@ -827,10 +828,10 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || *source_name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); @@ -946,7 +947,7 @@ static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE return; } - CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID); pa_client_set_name(c->client, name); pa_pstream_send_simple_ack(c->pstream, tag); @@ -965,7 +966,7 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); if (command == PA_COMMAND_LOOKUP_SINK) { pa_sink *sink; @@ -1134,7 +1135,7 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE); - CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); s = upload_stream_new(c, &ss, &map, name, length); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); @@ -1190,8 +1191,8 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || *sink_name, tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); if (sink_index != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); @@ -1220,7 +1221,7 @@ static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); if (pa_scache_remove_item(c->protocol->core, name) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); @@ -1357,6 +1358,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); if (command == PA_COMMAND_GET_SINK_INFO) { if (idx != PA_INVALID_INDEX) @@ -1561,7 +1563,7 @@ static void command_set_volume( } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || *name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); if (command == PA_COMMAND_SET_SINK_VOLUME) { @@ -1615,7 +1617,7 @@ static void command_set_mute( } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || *name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); if (command == PA_COMMAND_SET_SINK_MUTE) { if (idx != PA_INVALID_INDEX) @@ -1811,7 +1813,7 @@ static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, u } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, !s || *s, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !s || (*s && pa_utf8_valid(s)), tag, PA_ERR_INVALID); pa_namereg_set_default(c->protocol->core, s, command == PA_COMMAND_SET_DEFAULT_SOURCE ? PA_NAMEREG_SOURCE : PA_NAMEREG_SINK); pa_pstream_send_simple_ack(c->pstream, tag); @@ -1831,7 +1833,7 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID); if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) { struct playback_stream *s; @@ -1910,8 +1912,9 @@ static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); - + CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID); + if (!(m = pa_module_load(c->protocol->core, name, argument))) { pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED); return; @@ -1960,9 +1963,10 @@ static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED u } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, name && *name, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, type == 0 || type == 1, tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, module && *module, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, module && *module && pa_utf8_valid(module), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID); if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &idx) < 0) { pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); @@ -1991,7 +1995,7 @@ static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, !name || (*name && (type == 0 || type == 1)), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || (*name && pa_utf8_valid(name) && (type == 0 || type == 1)), tag, PA_ERR_INVALID); if (name) r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE); @@ -2031,7 +2035,7 @@ static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNU CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, !name || (*name && (type == 0 || type == 1)), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, !name || (*name && (type == 0 || type == 1) && pa_utf8_valid(name)), tag, PA_ERR_INVALID); if (name) a = pa_autoload_get_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE); From cfb082a67c5bfad24fd2d322028d3e87d7c58da6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 16:17:17 +0000 Subject: [PATCH 0768/1514] take the filename specified on the command line as default stream name git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@863 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 1ecc0db29..c8890bbb4 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -534,12 +534,6 @@ int main(int argc, char *argv[]) { } } - if (!client_name) - client_name = strdup(bn); - - if (!stream_name) - stream_name = strdup(client_name); - if (!pa_sample_spec_valid(&sample_spec)) { fprintf(stderr, "Invalid sample specification\n"); goto quit; @@ -571,12 +565,22 @@ int main(int argc, char *argv[]) { } close(fd); + + if (!stream_name) + stream_name = strdup(argv[optind]); + } else { fprintf(stderr, "Too many arguments.\n"); goto quit; } } - + + if (!client_name) + client_name = strdup(bn); + + if (!stream_name) + stream_name = strdup(client_name); + /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); From d419d87a7306d76e3d3f0b174c6af7d39e0d7837 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 16:17:38 +0000 Subject: [PATCH 0769/1514] remove superfluous log line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@864 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index ad6bbb709..99e74bfc8 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -346,8 +346,6 @@ int pa__init(pa_core *c, pa_module*m) { periods = 8; fragsize = pa_bytes_per_second(&ss)/128; - pa_log("req: %i %i", periods, fragsize); - if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { pa_log(__FILE__": failed to parse buffer metrics"); goto fail; From 45bbb3499929726971d2ab84f468413f39f97cb0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 16:18:00 +0000 Subject: [PATCH 0770/1514] add utf8 validity checking to esound protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@865 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 50c8b6b5b..aba408569 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -341,6 +341,8 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t strncpy(name, data, sizeof(name)); name[sizeof(name)-1] = 0; + CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in stream name"); + pa_client_set_name(c->client, name); assert(!c->sink_input && !c->input_memblockq); @@ -423,6 +425,8 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co strncpy(name, data, sizeof(name)); name[sizeof(name)-1] = 0; + CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in stream name."); + pa_client_set_name(c->client, name); assert(!c->output_memblockq && !c->source_output); @@ -689,6 +693,8 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ strcpy(name, SCACHE_PREFIX); strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX); name[sizeof(name)-1] = 0; + + CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name."); assert(!c->scache.memchunk.memblock); c->scache.memchunk.memblock = pa_memblock_new(sc_length, c->protocol->core->memblock_stat); @@ -719,6 +725,8 @@ static int esd_proto_sample_get_id(struct connection *c, PA_GCC_UNUSED esd_proto strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX); name[sizeof(name)-1] = 0; + CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name."); + ok = -1; if ((idx = pa_scache_get_id_by_name(c->protocol->core, name)) != PA_IDXSET_INVALID) ok = idx + 1; From 3f428784d2a0eba1f0be53318518484653150f7b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 16:19:39 +0000 Subject: [PATCH 0771/1514] update TODO git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@866 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/todo b/doc/todo index 7f31f0cfc..b94be1d98 100644 --- a/doc/todo +++ b/doc/todo @@ -27,7 +27,7 @@ Post 0.8: changes if you're modifying a sink/source since those might have a different map. - don't install .a files of modules -- check utf8 validity of strings +- in avahi-simple: sleep until latency data is available again if NODATA has happened Long term: - pass meta info for hearing impaired From f468308e41ddeadaa1b85cb2c7a0ca1a332c31f8 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 15 May 2006 06:36:07 +0000 Subject: [PATCH 0772/1514] Include utf8.h for the validation function. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@867 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index aba408569..0741d2418 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "endianmacros.h" From 9c38744cdd019ef48f321777db7ef7a14cc0fe88 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 15 May 2006 06:41:27 +0000 Subject: [PATCH 0773/1514] module-volume-restore uses regexp() so make sure it's only built on systems that have it. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@868 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 903359ada..e2880acec 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -744,8 +744,7 @@ modlib_LTLIBRARIES += \ module-null-sink.la \ module-esound-sink.la \ module-http-protocol-tcp.la \ - module-detect.la \ - module-volume-restore.la + module-detect.la # See comment at librtp.la above if !OS_IS_WIN32 @@ -777,7 +776,8 @@ endif if HAVE_REGEX modlib_LTLIBRARIES += \ - module-match.la + module-match.la \ + module-volume-restore.la endif if HAVE_X11 From 147da3e36ff8c1ce07a14d44e9c8747069f90c18 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 May 2006 12:33:43 +0000 Subject: [PATCH 0774/1514] remove regex.h from include, since it is actually not used git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@869 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index c32bb3a93..b4606bc3e 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include From e91740f68ce6334935d9440c12f08e8c136d0b45 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 15 May 2006 12:44:44 +0000 Subject: [PATCH 0775/1514] Clean up the UTF-8 validation code. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@870 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/utf8.c | 144 +++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 73 deletions(-) diff --git a/src/polypcore/utf8.c b/src/polypcore/utf8.c index b77584393..a706b2807 100644 --- a/src/polypcore/utf8.c +++ b/src/polypcore/utf8.c @@ -29,87 +29,85 @@ #endif #include +#include #include "utf8.h" -#define UNICODE_VALID(Char) \ - ((Char) < 0x110000 && \ - (((Char) & 0xFFFFF800) != 0xD800) && \ - ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ - ((Char) & 0xFFFE) != 0xFFFE) - - -#define CONTINUATION_CHAR \ - do { \ - if ((*(const unsigned char *)p & 0xc0) != 0x80) /* 10xxxxxx */ \ - goto error; \ - val <<= 6; \ - val |= (*(const unsigned char *)p) & 0x3f; \ - } while(0) +static inline int is_unicode_valid(uint32_t ch) { + if (ch >= 0x110000) /* End of unicode space */ + return 0; + if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */ + return 0; + if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */ + return 0; + if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */ + return 0; + return 1; +} +static inline int is_continuation_char(uint8_t ch) { + if ((ch & 0xc0) != 0x80) /* 10xxxxxx */ + return 0; + return 1; +} -const char * -pa_utf8_valid (const char *str) +static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) { + *u_ch <<= 6; + *u_ch |= ch & 0x3f; +} -{ - unsigned val = 0; - unsigned min = 0; - const char *p; +const char* pa_utf8_valid (const char *str) { + uint32_t val = 0; + uint32_t min = 0; + const uint8_t *p, *last; - for (p = str; *p; p++) - { - if (*(const unsigned char *)p < 128) - /* done */; - else - { - const char *last; - - last = p; - if ((*(const unsigned char *)p & 0xe0) == 0xc0) /* 110xxxxx */ - { - if ( ((*(const unsigned char *)p & 0x1e) == 0)) - goto error; - p++; - if ( ((*(const unsigned char *)p & 0xc0) != 0x80)) /* 10xxxxxx */ - goto error; - } - else - { - if ((*(const unsigned char *)p & 0xf0) == 0xe0) /* 1110xxxx */ - { - min = (1 << 11); - val = *(const unsigned char *)p & 0x0f; - goto TWO_REMAINING; - } - else if ((*(const unsigned char *)p & 0xf8) == 0xf0) /* 11110xxx */ - { - min = (1 << 16); - val = *(const unsigned char *)p & 0x07; - } - else - goto error; - - p++; - CONTINUATION_CHAR; - TWO_REMAINING: - p++; - CONTINUATION_CHAR; - p++; - CONTINUATION_CHAR; - - if ( (val < min)) - goto error; + for (p = (uint8_t*)str; *p; p++) { + if (*p < 128) + /* done */; + else { + last = p; - if ( (!UNICODE_VALID(val))) - goto error; - } - - continue; - - error: - return NULL; - } + if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */ + min = 128; + val = *p & 0x1e; + goto ONE_REMAINING; + } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/ + min = (1 << 11); + val = *p & 0x0f; + goto TWO_REMAINING; + } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */ + min = (1 << 16); + val = *p & 0x07; + } else + goto error; + + p++; + if (!is_continuation_char(*p)) + goto error; + merge_continuation_char(&val, *p); + +TWO_REMAINING: + p++; + if (!is_continuation_char(*p)) + goto error; + merge_continuation_char(&val, *p); + +ONE_REMAINING: + p++; + if (!is_continuation_char(*p)) + goto error; + merge_continuation_char(&val, *p); + + if (val < min) + goto error; + + if (!is_unicode_valid(val)) + goto error; + } } - return str; + return str; + +error: + return NULL; } From 7a92f361c66821a6cf89a85876510c15f851fd1b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 May 2006 12:45:55 +0000 Subject: [PATCH 0776/1514] undo r868 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@871 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index e2880acec..903359ada 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -744,7 +744,8 @@ modlib_LTLIBRARIES += \ module-null-sink.la \ module-esound-sink.la \ module-http-protocol-tcp.la \ - module-detect.la + module-detect.la \ + module-volume-restore.la # See comment at librtp.la above if !OS_IS_WIN32 @@ -776,8 +777,7 @@ endif if HAVE_REGEX modlib_LTLIBRARIES += \ - module-match.la \ - module-volume-restore.la + module-match.la endif if HAVE_X11 From 9c8661c675c92c15793b1f1005816d0d0531e6cf Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 15 May 2006 13:04:13 +0000 Subject: [PATCH 0777/1514] Add function to filter a string of any invalid UTF-8 sequences. User must free() the result. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@872 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/utf8.c | 59 ++++++++++++++++++++++++++++++++++++++------ src/polypcore/utf8.h | 1 + 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/polypcore/utf8.c b/src/polypcore/utf8.c index a706b2807..038655073 100644 --- a/src/polypcore/utf8.c +++ b/src/polypcore/utf8.c @@ -28,11 +28,15 @@ #include #endif +#include #include #include +#include #include "utf8.h" +#define FILTER_CHAR '_' + static inline int is_unicode_valid(uint32_t ch) { if (ch >= 0x110000) /* End of unicode space */ return 0; @@ -56,30 +60,39 @@ static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) { *u_ch |= ch & 0x3f; } -const char* pa_utf8_valid (const char *str) { +static const char* utf8_validate (const char *str, char *output) { uint32_t val = 0; uint32_t min = 0; const uint8_t *p, *last; + int size; + uint8_t *o; - for (p = (uint8_t*)str; *p; p++) { - if (*p < 128) - /* done */; - else { + o = output; + for (p = (uint8_t*)str; *p; p++, o++) { + if (*p < 128) { + if (o) + *output = *p; + } else { last = p; if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */ + size = 2; min = 128; val = *p & 0x1e; goto ONE_REMAINING; } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/ + size = 3; min = (1 << 11); val = *p & 0x0f; goto TWO_REMAINING; } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */ + size = 4; min = (1 << 16); val = *p & 0x07; - } else + } else { + size = 1; goto error; + } p++; if (!is_continuation_char(*p)) @@ -103,11 +116,43 @@ ONE_REMAINING: if (!is_unicode_valid(val)) goto error; + + if (o) { + memcpy(o, last, size); + o += size - 1; + } + + continue; + +error: + if (o) { + *o = FILTER_CHAR; + p = last + 1; /* We retry at the next character */ + } else + goto failure; } } + if (o) { + *o = '\0'; + return output; + } + return str; -error: +failure: return NULL; } + +const char* pa_utf8_valid (const char *str) { + return utf8_validate(str, NULL); +} + +const char* pa_utf8_filter (const char *str) { + char *new_str; + + new_str = malloc(strlen(str) + 1); + assert(new_str); + + return utf8_validate(str, new_str); +} diff --git a/src/polypcore/utf8.h b/src/polypcore/utf8.h index 7f3949781..5f1fc5dff 100644 --- a/src/polypcore/utf8.h +++ b/src/polypcore/utf8.h @@ -23,5 +23,6 @@ ***/ const char *pa_utf8_valid(const char *str); +const char *pa_utf8_filter(const char *str); #endif From 19167a1a2d9bdff5a6685f1d14dc47b2aa7dad5a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 May 2006 20:17:11 +0000 Subject: [PATCH 0778/1514] add notification callback which is called when new latency data becomes available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@873 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/internal.h | 2 ++ src/polyp/stream.c | 15 ++++++++++++++- src/polyp/stream.h | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/polyp/internal.h b/src/polyp/internal.h index f41744ef5..80c286164 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -151,6 +151,8 @@ struct pa_stream { void *overflow_userdata; pa_stream_notify_cb_t underflow_callback; void *underflow_userdata; + pa_stream_notify_cb_t latency_update_callback; + void *latency_update_userdata; }; typedef void (*pa_operation_cb_t)(void); diff --git a/src/polyp/stream.c b/src/polyp/stream.c index c67b3e516..bccdebe5d 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -63,6 +63,8 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->overflow_userdata = NULL; s->underflow_callback = NULL; s->underflow_userdata = NULL; + s->latency_update_callback = NULL; + s->latency_update_userdata = NULL; s->direction = PA_STREAM_NODIRECTION; s->name = pa_xstrdup(name); @@ -849,8 +851,11 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, o->stream->write_index_corrections[n].valid = 0; } } + + if (o->stream->latency_update_callback) + o->stream->latency_update_callback(o->stream, o->stream->latency_update_userdata); - if (o->callback) { + if (o->callback && o->stream && o->stream->state == PA_STREAM_READY) { pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback; cb(o->stream, o->stream->timing_info_valid, o->userdata); } @@ -999,6 +1004,14 @@ void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, vo s->underflow_userdata = userdata; } +void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { + assert(s); + assert(s->ref >= 1); + + s->latency_update_callback = cb; + s->latency_update_userdata = userdata; +} + void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; diff --git a/src/polyp/stream.h b/src/polyp/stream.h index b6522efec..ad77d9383 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -375,6 +375,9 @@ void pa_stream_set_overflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, voi /** Set the callback function that is called when a buffer underflow happens. (Only for playback streams) \since 0.8 */ void pa_stream_set_underflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata); +/** Set the callback function that is called whenever a latency information update happens. Useful on PA_STREAM_AUTO_TIMING_UPDATE streams only. (Only for playback streams) \since 0.8.2 */ +void pa_stream_set_latency_update_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata); + /** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. \since 0.3 */ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata); From 713637cf424a6b4b177c0d353d862ab0ea916d4e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 00:04:14 +0000 Subject: [PATCH 0779/1514] * fix segfault in pa_utf8_validate() * remove some compiler warnings * use our own pa_xmalloc() implementation instead of libc's malloc() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@874 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/utf8.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/polypcore/utf8.c b/src/polypcore/utf8.c index 038655073..95b73d523 100644 --- a/src/polypcore/utf8.c +++ b/src/polypcore/utf8.c @@ -34,6 +34,7 @@ #include #include "utf8.h" +#include "xmalloc.h" #define FILTER_CHAR '_' @@ -67,11 +68,11 @@ static const char* utf8_validate (const char *str, char *output) { int size; uint8_t *o; - o = output; - for (p = (uint8_t*)str; *p; p++, o++) { + o = (uint8_t*) output; + for (p = (const uint8_t*) str; *p; p++) { if (*p < 128) { if (o) - *output = *p; + *o = *p; } else { last = p; @@ -122,6 +123,9 @@ ONE_REMAINING: o += size - 1; } + if (o) + o++; + continue; error: @@ -131,6 +135,9 @@ error: } else goto failure; } + + if (o) + o++; } if (o) { @@ -151,8 +158,7 @@ const char* pa_utf8_valid (const char *str) { const char* pa_utf8_filter (const char *str) { char *new_str; - new_str = malloc(strlen(str) + 1); - assert(new_str); + new_str = pa_xnew(char, strlen(str) + 1); return utf8_validate(str, new_str); } From 724cd9d811c3847c6e46233185f27b4c5201c260 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 00:04:47 +0000 Subject: [PATCH 0780/1514] downgrade a log message git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@875 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index b4606bc3e..b379e53cf 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -119,7 +119,7 @@ static int load_rules(struct userdata *u) { if (!f) { if (errno == ENOENT) { - pa_log(__FILE__": starting with empty ruleset."); + pa_log_info(__FILE__": starting with empty ruleset."); ret = 0; } else pa_log(__FILE__": failed to open file '%s': %s", u->table_file, strerror(errno)); @@ -204,7 +204,6 @@ static int save_rules(struct userdata *u) { for (i = 0; i < rule->volume.channels; i++) fprintf(f, " %u", rule->volume.values[i]); - fprintf(f, "\n"); } From 23e74545adce1e23f6d3e09a0cbb9f1d98a7b933 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 00:06:02 +0000 Subject: [PATCH 0781/1514] use the new latency update callback to be notified when latency data becomes available again after PA_ERR_NODATA is returned by pa_stream_get_latency() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@876 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/simple.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/polyp/simple.c b/src/polyp/simple.c index 97dcaf113..1f25869b3 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -125,6 +125,14 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { pa_threaded_mainloop_signal(p->mainloop, 0); } +static void stream_latency_update_cb(pa_stream *s, void *userdata) { + pa_simple *p = userdata; + + assert(p); + + pa_threaded_mainloop_signal(p->mainloop, 0); +} + pa_simple* pa_simple_new( const char *server, const char *name, @@ -184,6 +192,7 @@ pa_simple* pa_simple_new( pa_stream_set_state_callback(p->stream, stream_state_cb, p); pa_stream_set_read_callback(p->stream, stream_request_cb, p); pa_stream_set_write_callback(p->stream, stream_request_cb, p); + pa_stream_set_latency_update_callback(p->stream, stream_latency_update_cb, p); if (dir == PA_STREAM_PLAYBACK) r = pa_stream_connect_playback(p->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL); @@ -414,17 +423,25 @@ unlock_and_fail: pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) { pa_usec_t t; - int r, negative; + int negative; assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, (pa_usec_t) -1); pa_threaded_mainloop_lock(p->mainloop); - CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); - r = pa_stream_get_latency(p->stream, &t, &negative); - CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail); + for (;;) { + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); + + if (pa_stream_get_latency(p->stream, &t, &negative) >= 0) + break; + + CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail); + + /* Wait until latency data is available again */ + pa_threaded_mainloop_wait(p->mainloop); + } pa_threaded_mainloop_unlock(p->mainloop); From e8cc63d75685bd264efaea2b7bce894ba182e2a2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 00:44:47 +0000 Subject: [PATCH 0782/1514] * remove "const" from return type of pa_utf8_filter() since it desn't make any sense * fix pa_utf8_filter() to not skip the next character too if it found an invalid one git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@877 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/utf8.c | 8 ++++---- src/polypcore/utf8.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/polypcore/utf8.c b/src/polypcore/utf8.c index 95b73d523..bb8621e23 100644 --- a/src/polypcore/utf8.c +++ b/src/polypcore/utf8.c @@ -61,7 +61,7 @@ static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) { *u_ch |= ch & 0x3f; } -static const char* utf8_validate (const char *str, char *output) { +static char* utf8_validate(const char *str, char *output) { uint32_t val = 0; uint32_t min = 0; const uint8_t *p, *last; @@ -131,7 +131,7 @@ ONE_REMAINING: error: if (o) { *o = FILTER_CHAR; - p = last + 1; /* We retry at the next character */ + p = last; /* We retry at the next character */ } else goto failure; } @@ -145,7 +145,7 @@ error: return output; } - return str; + return (char*) str; failure: return NULL; @@ -155,7 +155,7 @@ const char* pa_utf8_valid (const char *str) { return utf8_validate(str, NULL); } -const char* pa_utf8_filter (const char *str) { +char* pa_utf8_filter (const char *str) { char *new_str; new_str = pa_xnew(char, strlen(str) + 1); diff --git a/src/polypcore/utf8.h b/src/polypcore/utf8.h index 5f1fc5dff..6d1e4a7df 100644 --- a/src/polypcore/utf8.h +++ b/src/polypcore/utf8.h @@ -23,6 +23,6 @@ ***/ const char *pa_utf8_valid(const char *str); -const char *pa_utf8_filter(const char *str); +char *pa_utf8_filter(const char *str); #endif From 78b23cc1b96c832265074cdab5265665fe7aefaf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 00:45:21 +0000 Subject: [PATCH 0783/1514] add double include protection git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@878 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/pipe.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/polypcore/pipe.h b/src/polypcore/pipe.h index a9b088b5c..e91677829 100644 --- a/src/polypcore/pipe.h +++ b/src/polypcore/pipe.h @@ -1,3 +1,6 @@ +#ifndef foopipehfoo +#define foopipehfoo + /* $Id$ */ /*** @@ -20,3 +23,5 @@ ***/ int pipe(int filedes[2]); + +#endif From bf58753a99368c56e561106a2e193bcca24935cd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 00:45:40 +0000 Subject: [PATCH 0784/1514] add svn:keywords property git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@879 fefdeb5f-60dc-0310-8127-8f9354f1896f From 53595938d003411e6992e10b6a5c5e51b2a15d4f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 00:46:03 +0000 Subject: [PATCH 0785/1514] add new test programme utf8-test.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@880 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 8 +++++++- src/tests/utf8-test.c | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/tests/utf8-test.c diff --git a/src/Makefile.am b/src/Makefile.am index 903359ada..10dbf2f2d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -189,7 +189,8 @@ noinst_PROGRAMS = \ memblockq-test \ sync-playback \ channelmap-test \ - thread-mainloop-test + thread-mainloop-test \ + utf8-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -217,6 +218,11 @@ thread_mainloop_test_CFLAGS = $(AM_CFLAGS) thread_mainloop_test_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la thread_mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +utf8_test_SOURCES = tests/utf8-test.c +utf8_test_CFLAGS = $(AM_CFLAGS) +utf8_test_LDADD = $(AM_LDADD) libpolypcore.la +utf8_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la diff --git a/src/tests/utf8-test.c b/src/tests/utf8-test.c new file mode 100644 index 000000000..c8b2fabb7 --- /dev/null +++ b/src/tests/utf8-test.c @@ -0,0 +1,26 @@ +/* $Id$ */ + +#include +#include + +#include +#include + +int main(int argc, char *argv[]) { + char *c; + + assert(pa_utf8_valid("hallo")); + assert(pa_utf8_valid("hallo\n")); + assert(!pa_utf8_valid("hüpfburg\n")); + assert(pa_utf8_valid("hallo\n")); + assert(pa_utf8_valid("hüpfburg\n")); + + printf("LATIN1: %s\n", c = pa_utf8_filter("hüpfburg")); + pa_xfree(c); + printf("UTF8: %sx\n", c = pa_utf8_filter("hüpfburg")); + pa_xfree(c); + printf("LATIN1: %sx\n", c = pa_utf8_filter("üxknärzmörzeltörszß³§dsjkfh")); + pa_xfree(c); + + return 0; +} From 56b685ab46ac673c559a1fb6ad25575b38c6cb9e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 01:40:01 +0000 Subject: [PATCH 0786/1514] instead of kicking clients with invalid UTF8 stream names, filter invalid characters and use that instead git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@881 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-esound.c | 40 +++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 0741d2418..fcbeba6d1 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -87,6 +87,8 @@ struct connection { pa_source_output *source_output; pa_memblockq *input_memblockq, *output_memblockq; pa_defer_event *defer_event; + + char *original_name; struct { pa_memblock *current_memblock; @@ -175,7 +177,6 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { 0, esd_proto_get_latency, "get latency" } }; - static void connection_free(struct connection *c) { assert(c); pa_idxset_remove_by_data(c->protocol->connections, c, NULL); @@ -218,7 +219,8 @@ static void connection_free(struct connection *c) { if (c->auth_timeout_event) c->protocol->core->mainloop->time_free(c->auth_timeout_event); - + + pa_xfree(c->original_name); pa_xfree(c); } @@ -316,7 +318,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req } static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { - char name[ESD_NAME_MAX]; + char name[ESD_NAME_MAX], *utf8_name; int32_t format, rate; pa_sink *sink; pa_sample_spec ss; @@ -341,14 +343,16 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t strncpy(name, data, sizeof(name)); name[sizeof(name)-1] = 0; - - CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in stream name"); + utf8_name = pa_utf8_filter(name); - pa_client_set_name(c->client, name); + pa_client_set_name(c->client, utf8_name); + c->original_name = pa_xstrdup(name); assert(!c->sink_input && !c->input_memblockq); - c->sink_input = pa_sink_input_new(sink, __FILE__, name, &ss, NULL, NULL, 0, -1); + c->sink_input = pa_sink_input_new(sink, __FILE__, utf8_name, &ss, NULL, NULL, 0, -1); + + pa_xfree(utf8_name); CHECK_VALIDITY(c->sink_input, "Failed to create sink input."); @@ -381,7 +385,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t } static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length) { - char name[ESD_NAME_MAX]; + char name[ESD_NAME_MAX], *utf8_name; int32_t format, rate; pa_source *source; pa_sample_spec ss; @@ -426,13 +430,15 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co strncpy(name, data, sizeof(name)); name[sizeof(name)-1] = 0; - CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in stream name."); - - pa_client_set_name(c->client, name); + utf8_name = pa_utf8_filter(name); + pa_client_set_name(c->client, utf8_name); + pa_xfree(utf8_name); + + c->original_name = pa_xstrdup(name); assert(!c->output_memblockq && !c->source_output); - if (!(c->source_output = pa_source_output_new(source, __FILE__, name, &ss, NULL, -1))) { + if (!(c->source_output = pa_source_output_new(source, __FILE__, c->client->name, &ss, NULL, -1))) { pa_log(__FILE__": failed to create source output"); return -1; } @@ -549,8 +555,11 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v connection_write(c, &id, sizeof(int32_t)); /* name */ - assert(conn->client); - strncpy(name, conn->client->name, ESD_NAME_MAX); + memset(name, 0, ESD_NAME_MAX); /* don't leak old data */ + if (conn->original_name) + strncpy(name, conn->original_name, ESD_NAME_MAX); + else if (conn->client && conn->client->name) + strncpy(name, conn->client->name, ESD_NAME_MAX); connection_write(c, name, ESD_NAME_MAX); /* rate */ @@ -593,6 +602,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v connection_write(c, &id, sizeof(int32_t)); /* name */ + memset(name, 0, ESD_NAME_MAX); /* don't leak old data */ if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0) strncpy(name, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX); else @@ -1177,6 +1187,8 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->scache.memchunk.memblock = NULL; c->scache.name = NULL; + c->original_name = NULL; + if (!c->authorized) { struct timeval tv; pa_gettimeofday(&tv); From f272e598df8b27068743fdf3d721e4d9217d0dd6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 01:43:36 +0000 Subject: [PATCH 0787/1514] tell svn to ignore the utf8-test binary git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@882 fefdeb5f-60dc-0310-8127-8f9354f1896f From c12206b864439ce3a38cccff1d3fcb9eec75c6d5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 15:29:58 +0000 Subject: [PATCH 0788/1514] * remove .a files from the modules directory after installation * rename $(modlibdir) to $(modlibexecdir) in accordance with secion 11.2 of the automake docs ("The two parts of install") git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@883 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 10dbf2f2d..02060e929 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,7 @@ polypincludedir=$(includedir)/polyp polypcoreincludedir=$(includedir)/polypcore polypconfdir=$(sysconfdir)/polypaudio -modlibdir=$(libdir)/polypaudio +modlibexecdir=$(libdir)/polypaudio ################################### # Defines # @@ -47,7 +47,7 @@ AM_CFLAGS = -I$(top_srcdir)/src AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\" +AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibexecdir)\" #AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" @@ -113,7 +113,7 @@ polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \ if PREOPEN_MODS PREOPEN_LIBS = $(PREOPEN_MODS) else -PREOPEN_LIBS = $(modlib_LTLIBRARIES) +PREOPEN_LIBS = $(modlibexec_LTLIBRARIES) endif if FORCE_PREOPEN @@ -589,11 +589,11 @@ polypcoreinclude_HEADERS += \ polypcore/protocol-http.h ### Warning! Due to an obscure bug in libtool/automake it is required -### that the libraries in modlib_LTLIBRARIES are specified in-order, +### that the libraries in modlibexec_LTLIBRARIES are specified in-order, ### i.e. libraries near the end of the list depend on libraries near ### the head, and not the other way! -modlib_LTLIBRARIES = \ +modlibexec_LTLIBRARIES = \ libsocket-util.la \ libiochannel.la \ libsocket-server.la \ @@ -617,7 +617,7 @@ modlib_LTLIBRARIES = \ # We need to emulate sendmsg/recvmsg to support this on Win32 if !OS_IS_WIN32 -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ librtp.la endif @@ -626,7 +626,7 @@ polypcoreinclude_HEADERS += \ polypcore/x11wrap.h \ polypcore/x11prop.h -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ libx11wrap.la \ libx11prop.la endif @@ -736,7 +736,7 @@ libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS # Plug-in libraries # ################################### -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-cli.la \ module-cli-protocol-tcp.la \ module-simple-protocol-tcp.la \ @@ -755,13 +755,13 @@ modlib_LTLIBRARIES += \ # See comment at librtp.la above if !OS_IS_WIN32 -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-rtp-send.la \ module-rtp-recv.la endif if HAVE_AF_UNIX -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-cli-protocol-unix.la \ module-simple-protocol-unix.la \ module-esound-protocol-unix.la \ @@ -770,71 +770,71 @@ modlib_LTLIBRARIES += \ endif if HAVE_MKFIFO -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-pipe-sink.la \ module-pipe-source.la endif if !OS_IS_WIN32 -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-esound-compat-spawnfd.la \ module-esound-compat-spawnpid.la endif if HAVE_REGEX -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-match.la endif if HAVE_X11 -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-x11-bell.la \ module-x11-publish.la endif if HAVE_OSS -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ liboss-util.la \ module-oss.la \ module-oss-mmap.la endif if HAVE_ALSA -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ libalsa-util.la \ module-alsa-sink.la \ module-alsa-source.la endif if HAVE_SOLARIS -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-solaris.la endif if HAVE_HOWL -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ libhowl-wrap.la \ module-zeroconf-publish.la endif if HAVE_LIRC -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-lirc.la endif if HAVE_EVDEV -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-mmkbd-evdev.la endif if HAVE_JACK -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-jack-sink.la \ module-jack-source.la endif if OS_IS_WIN32 -modlib_LTLIBRARIES += \ +modlibexec_LTLIBRARIES += \ module-waveout.la endif @@ -1153,10 +1153,11 @@ default.pa: daemon/default.pa.in Makefile endif daemon.conf: daemon/daemon.conf.in Makefile - sed -e 's,@DLSEARCHPATH\@,$(modlibdir),g' \ + sed -e 's,@DLSEARCHPATH\@,$(modlibexecdir),g' \ -e 's,@DEFAULT_CONFIG_FILE\@,$(DEFAULT_CONFIG_DIR),g' < $< > $@ install-exec-hook: chown root $(DESTDIR)$(bindir)/polypaudio ; true chmod u+s $(DESTDIR)$(bindir)/polypaudio ln -sf pacat $(DESTDIR)$(bindir)/parec + rm -f $(DESTDIR)$(modlibexecdir)/*.a From 929899015d23f4af2b19b7b7c56fd8bbd50f519f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 15:30:14 +0000 Subject: [PATCH 0789/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@884 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index b94be1d98..8b5daefb1 100644 --- a/doc/todo +++ b/doc/todo @@ -26,7 +26,6 @@ Post 0.8: - fix channel maps in all external backends. Take care when doing volume changes if you're modifying a sink/source since those might have a different map. -- don't install .a files of modules - in avahi-simple: sleep until latency data is available again if NODATA has happened Long term: From 55215597c43e81da1560894645dcd27642cc0a47 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 17:54:33 +0000 Subject: [PATCH 0790/1514] * add new configure option --with-module-dir= * drop version suffix from soname of libpolyp and friends * add version suffix by default to $(modlibexecdir) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@885 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 13 +++++ polyplib-browse.pc.in | 2 +- polyplib-glib-mainloop.pc.in | 2 +- polyplib-glib12-mainloop.pc.in | 2 +- polyplib-simple.pc.in | 2 +- polyplib.pc.in | 2 +- src/Makefile.am | 98 +++++++++++++++++----------------- 7 files changed, 66 insertions(+), 55 deletions(-) diff --git a/configure.ac b/configure.ac index 360249eac..cb8e42f5b 100644 --- a/configure.ac +++ b/configure.ac @@ -31,6 +31,12 @@ AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) AC_SUBST(PA_API_VERSION, 8) AC_SUBST(PA_PROTOCOL_VERSION, 8) +AC_SUBST(LIBPOLYP_VERSION_INFO, [0:0:0]) +AC_SUBST(LIBPOLYPCORE_VERSION_INFO, [0:0:0]) +AC_SUBST(LIBPOLYP_SIMPLE_VERSION_INFO, [0:0:0]) +AC_SUBST(LIBPOLYP_BROWSE_VERSION_INFO, [0:0:0]) +AC_SUBST(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO, [0:0:0]) + if type -p stow > /dev/null && test -d /usr/local/stow ; then AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}" @@ -420,6 +426,13 @@ if test "x$PREOPEN_MODS" != "xall" ; then AC_SUBST(PREOPEN_MODS) fi +AC_ARG_WITH( + [module-dir], + AC_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${libdir}/polypaudio-${PA_MAJORMINOR}]), + [modlibexecdir=$withval], [modlibexecdir="${libdir}/polypaudio-${PA_MAJORMINOR}"]) + +AC_SUBST(modlibexecdir) + AC_ARG_ENABLE( [force-preopen], AC_HELP_STRING([--enable-force-preopen],[Preopen modules, even when dlopen() is supported.]), diff --git a/polyplib-browse.pc.in b/polyplib-browse.pc.in index b9d57eef5..952e28c10 100644 --- a/polyplib-browse.pc.in +++ b/polyplib-browse.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: polyplib-browse Description: Polypaudio network browsing API Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-browse-@PA_MAJORMINOR@ +Libs: -L${libdir} -lpolyp-browse Cflags: -D_REENTRANT -I${includedir} Requires: polyplib diff --git a/polyplib-glib-mainloop.pc.in b/polyplib-glib-mainloop.pc.in index 3d8f39315..03338c55b 100644 --- a/polyplib-glib-mainloop.pc.in +++ b/polyplib-glib-mainloop.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: polyplib-glib-mainloop Description: GLIB main loop wrapper for polypaudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-mainloop-glib-@PA_MAJORMINOR@ +Libs: -L${libdir} -lpolyp-mainloop-glib Cflags: -D_REENTRANT -I${includedir} Requires: polyplib glib-2.0 diff --git a/polyplib-glib12-mainloop.pc.in b/polyplib-glib12-mainloop.pc.in index 5ada2e5c8..c12a838b3 100644 --- a/polyplib-glib12-mainloop.pc.in +++ b/polyplib-glib12-mainloop.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: polyplib-glib12-mainloop Description: GLIB main loop wrapper for polypaudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-mainloop-glib12-@PA_MAJORMINOR@ +Libs: -L${libdir} -lpolyp-mainloop-glib12 Cflags: -D_REENTRANT -I${includedir} Requires: polyplib glib diff --git a/polyplib-simple.pc.in b/polyplib-simple.pc.in index 94644df67..fa0ca0b95 100644 --- a/polyplib-simple.pc.in +++ b/polyplib-simple.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: polyplib-simple Description: Simplified synchronous client interface to polypaudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-simple-@PA_MAJORMINOR@ +Libs: -L${libdir} -lpolyp-simple Cflags: -D_REENTRANT -I${includedir} Requires: polyplib diff --git a/polyplib.pc.in b/polyplib.pc.in index f495def2b..2d073a93d 100644 --- a/polyplib.pc.in +++ b/polyplib.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: polyplib Description: Client interface to polypaudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-@PA_MAJORMINOR@ +Libs: -L${libdir} -lpolyp Cflags: -D_REENTRANT -I${includedir} Requires: diff --git a/src/Makefile.am b/src/Makefile.am index 02060e929..bd48a0fb1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,8 +26,6 @@ polypincludedir=$(includedir)/polyp polypcoreincludedir=$(includedir)/polypcore polypconfdir=$(sysconfdir)/polypaudio -modlibexecdir=$(libdir)/polypaudio - ################################### # Defines # ################################### @@ -146,32 +144,32 @@ endif bin_SCRIPTS = esdcompat.sh pacat_SOURCES = utils/pacat.c -pacat_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la +pacat_LDADD = $(AM_LDADD) libpolyp.la pacat_CFLAGS = $(AM_CFLAGS) pacat_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) paplay_SOURCES = utils/paplay.c -paplay_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) +paplay_LDADD = $(AM_LDADD) libpolyp.la $(LIBSNDFILE_LIBS) paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) paplay_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pactl_SOURCES = utils/pactl.c -pactl_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS) +pactl_LDADD = $(AM_LDADD) libpolyp.la $(LIBSNDFILE_LIBS) pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pacmd_SOURCES = utils/pacmd.c polypcore/pid.c polypcore/pid.h pacmd_CFLAGS = $(AM_CFLAGS) -pacmd_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la +pacmd_LDADD = $(AM_LDADD) libpolyp.la pacmd_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pax11publish_SOURCES = utils/pax11publish.c pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -pax11publish_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +pax11publish_LDADD = $(AM_LDADD) libpolyp.la $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pabrowse_SOURCES = utils/pabrowse.c -pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la +pabrowse_LDADD = $(AM_LDADD) libpolyp.la libpolyp-browse.la pabrowse_CFLAGS = $(AM_CFLAGS) pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -210,12 +208,12 @@ endif mainloop_test_SOURCES = tests/mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) -mainloop_test_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la +mainloop_test_LDADD = $(AM_LDADD) libpolyp.la mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) thread_mainloop_test_SOURCES = tests/thread-mainloop-test.c thread_mainloop_test_CFLAGS = $(AM_CFLAGS) -thread_mainloop_test_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la +thread_mainloop_test_LDADD = $(AM_LDADD) libpolyp.la thread_mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) utf8_test_SOURCES = tests/utf8-test.c @@ -229,12 +227,12 @@ mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la mcalign_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pacat_simple_SOURCES = tests/pacat-simple.c -pacat_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la +pacat_simple_LDADD = $(AM_LDADD) libpolyp.la libpolyp-simple.la pacat_simple_CFLAGS = $(AM_CFLAGS) pacat_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) parec_simple_SOURCES = tests/parec-simple.c -parec_simple_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-simple-@PA_MAJORMINOR@.la +parec_simple_LDADD = $(AM_LDADD) libpolyp.la libpolyp-simple.la parec_simple_CFLAGS = $(AM_CFLAGS) parec_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -245,12 +243,12 @@ strlist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) voltest_SOURCES = tests/voltest.c voltest_CFLAGS = $(AM_CFLAGS) -voltest_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la +voltest_LDADD = $(AM_LDADD) libpolyp.la voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) channelmap_test_SOURCES = tests/channelmap-test.c channelmap_test_CFLAGS = $(AM_CFLAGS) -channelmap_test_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la +channelmap_test_LDADD = $(AM_LDADD) libpolyp.la channelmap_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) cpulimit_test_SOURCES = tests/cpulimit-test.c daemon/cpulimit.c daemon/cpulimit.h @@ -265,12 +263,12 @@ cpulimit_test2_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib-@PA_MAJORMINOR@.la +mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib.la mainloop_test_glib_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la +mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12.la mainloop_test_glib12_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) memblockq_test_SOURCES = \ @@ -287,7 +285,7 @@ memblockq_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) memblockq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) sync_playback_SOURCES = tests/sync-playback.c -sync_playback_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la +sync_playback_LDADD = $(AM_LDADD) libpolyp.la sync_playback_CFLAGS = $(AM_CFLAGS) sync_playback_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -323,26 +321,26 @@ polypinclude_HEADERS += \ endif lib_LTLIBRARIES = \ - libpolyp-@PA_MAJORMINOR@.la \ - libpolyp-simple-@PA_MAJORMINOR@.la + libpolyp.la \ + libpolyp-simple.la if HAVE_HOWL lib_LTLIBRARIES += \ - libpolyp-browse-@PA_MAJORMINOR@.la + libpolyp-browse.la endif if HAVE_GLIB20 lib_LTLIBRARIES += \ - libpolyp-mainloop-glib-@PA_MAJORMINOR@.la + libpolyp-mainloop-glib.la endif if HAVE_GLIB12 lib_LTLIBRARIES += \ - libpolyp-mainloop-glib12-@PA_MAJORMINOR@.la + libpolyp-mainloop-glib12.la endif # Public interface -libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ +libpolyp_la_SOURCES = \ polyp/cdecl.h \ polyp/channelmap.c polyp/channelmap.h \ polyp/client-conf.c polyp/client-conf.h \ @@ -366,7 +364,7 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \ polypcore/poll.c polypcore/poll.h # Internal stuff that is shared with libpolypcore -libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ +libpolyp_la_SOURCES += \ polypcore/authkey.c polypcore/authkey.h \ polypcore/conf-parser.c polypcore/conf-parser.h \ polypcore/dynarray.c polypcore/dynarray.h \ @@ -398,49 +396,49 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ polypcore/llist.h if OS_IS_WIN32 -libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ +libpolyp_la_SOURCES += \ polypcore/dllmain.c endif if HAVE_X11 -libpolyp_@PA_MAJORMINOR@_la_SOURCES += \ +libpolyp_la_SOURCES += \ polyp/client-conf-x11.c polyp/client-conf-x11.h \ polypcore/x11prop.c polypcore/x11prop.h endif -libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) -libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 -libpolyp_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) +libpolyp_la_CFLAGS = $(AM_CFLAGS) +libpolyp_la_LDFLAGS = -version-info $(LIBPOLYP_VERSION_INFO) +libpolyp_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) if HAVE_X11 -libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(X_CFLAGS) -libpolyp_@PA_MAJORMINOR@_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +libpolyp_la_CFLAGS += $(X_CFLAGS) +libpolyp_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) endif if HAVE_LIBASYNCNS -libpolyp_@PA_MAJORMINOR@_la_CFLAGS += $(LIBASYNCNS_CFLAGS) -libpolyp_@PA_MAJORMINOR@_la_LIBADD += $(LIBASYNCNS_LIBS) +libpolyp_la_CFLAGS += $(LIBASYNCNS_CFLAGS) +libpolyp_la_LIBADD += $(LIBASYNCNS_LIBS) endif -libpolyp_simple_@PA_MAJORMINOR@_la_SOURCES = polyp/simple.c polyp/simple.h -libpolyp_simple_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) -libpolyp_simple_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la -libpolyp_simple_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 +libpolyp_simple_la_SOURCES = polyp/simple.c polyp/simple.h +libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) +libpolyp_simple_la_LIBADD = $(AM_LIBADD) libpolyp.la +libpolyp_simple_la_LDFLAGS = -version-info $(LIBPOLYP_SIMPLE_VERSION_INFO) -libpolyp_browse_@PA_MAJORMINOR@_la_SOURCES = polyp/browser.c polyp/browser.h -libpolyp_browse_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) -libpolyp_browse_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(HOWL_LIBS) -libpolyp_browse_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 +libpolyp_browse_la_SOURCES = polyp/browser.c polyp/browser.h +libpolyp_browse_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) +libpolyp_browse_la_LIBADD = $(AM_LIBADD) libpolyp.la $(HOWL_LIBS) +libpolyp_browse_la_LDFLAGS = -version-info $(LIBPOLYP_BROWSE_VERSION_INFO) -libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_SOURCES = polyp/glib-mainloop.h polyp/glib-mainloop.c -libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) -libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(GLIB20_LIBS) -libpolyp_mainloop_glib_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 +libpolyp_mainloop_glib_la_SOURCES = polyp/glib-mainloop.h polyp/glib-mainloop.c +libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) +libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp.la $(GLIB20_LIBS) +libpolyp_mainloop_glib_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO) -libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_SOURCES = polyp/glib-mainloop.h polyp/glib12-mainloop.c -libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) -libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(GLIB12_LIBS) -libpolyp_mainloop_glib12_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 +libpolyp_mainloop_glib12_la_SOURCES = polyp/glib-mainloop.h polyp/glib12-mainloop.c +libpolyp_mainloop_glib12_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) +libpolyp_mainloop_glib12_la_LIBADD = $(AM_LIBADD) libpolyp.la $(GLIB12_LIBS) +libpolyp_mainloop_glib12_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO) ################################### # Daemon core library # @@ -557,7 +555,7 @@ libpolypcore_la_SOURCES += \ endif libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) -libpolypcore_la_LDFLAGS = -avoid-version +libpolypcore_la_LDFLAGS = -version-info $(LIBPOLYPCORE_VERSION_INFO) libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) ################################### From c2c8539201307cf8bf500ce7b77c8f09eaa655b7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 18:28:03 +0000 Subject: [PATCH 0791/1514] bump version number to 0.9 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@886 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 ++-- src/utils/pacat.c | 2 +- src/utils/pactl.c | 2 +- src/utils/paplay.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index cb8e42f5b..52b7a6e32 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.8.1],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.9],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) @@ -28,7 +28,7 @@ AM_INIT_AUTOMAKE([foreign -Wall]) AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) -AC_SUBST(PA_API_VERSION, 8) +AC_SUBST(PA_API_VERSION, 9) AC_SUBST(PA_PROTOCOL_VERSION, 8) AC_SUBST(LIBPOLYP_VERSION_INFO, [0:0:0]) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index c8890bbb4..529cebae0 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -40,7 +40,7 @@ #define TIME_EVENT_USEC 50000 -#if PA_API_VERSION != 8 +#if PA_API_VERSION != 9 #error Invalid Polypaudio API version #endif diff --git a/src/utils/pactl.c b/src/utils/pactl.c index fcc677d9c..7a3d37372 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -39,7 +39,7 @@ #include #include -#if PA_API_VERSION != 8 +#if PA_API_VERSION != 9 #error Invalid Polypaudio API version #endif diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 7f665413f..ad9d45533 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -38,7 +38,7 @@ #include #include -#if PA_API_VERSION != 8 +#if PA_API_VERSION != 9 #error Invalid Polypaudio API version #endif From c63cc7bb79fb60b6493c3e80648501fbe8a83963 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 19:15:06 +0000 Subject: [PATCH 0792/1514] change version number from "0.9" to "0.9.0" to make version comparisons easier git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@887 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 52b7a6e32..18332405f 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.9],[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([polypaudio],[0.9.0],[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) From 4b6ab291a787ff597c938842b569a35434ab11d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 23:47:38 +0000 Subject: [PATCH 0793/1514] * modify pa_channel_map_init_auto() to take an extra argument specifying the standard to use (ALSA, AIFF, ...) * add some more validity checks to pa_source_new(),pa_sink_new(),pa_sink_input_new(),pa_source_output_new() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@888 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 44 ----------- src/modules/alsa-util.h | 2 - src/modules/module-alsa-sink.c | 15 +--- src/modules/module-alsa-source.c | 13 +--- src/modules/module-combine.c | 2 +- src/modules/module-jack-sink.c | 2 +- src/modules/module-jack-source.c | 2 +- src/modules/module-null-sink.c | 2 +- src/modules/module-oss-mmap.c | 2 +- src/modules/module-oss.c | 2 +- src/modules/module-pipe-sink.c | 2 +- src/modules/module-pipe-source.c | 2 +- src/modules/module-tunnel.c | 2 +- src/modules/rtp/module-rtp-send.c | 2 +- src/polyp/channelmap.c | 125 +++++++++++++++++++++--------- src/polyp/channelmap.h | 14 +++- src/polyp/stream.c | 2 +- src/polypcore/core-scache.c | 2 +- src/polypcore/modargs.c | 5 +- src/polypcore/modargs.h | 2 +- src/polypcore/resampler.c | 4 +- src/polypcore/sink-input.c | 58 +++++++------- src/polypcore/sink.c | 37 ++++++--- src/polypcore/sound-file.c | 2 +- src/polypcore/source-output.c | 37 +++++---- src/polypcore/source.c | 36 ++++++--- src/tests/channelmap-test.c | 10 ++- 27 files changed, 237 insertions(+), 191 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index a81921651..503b8efbc 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -340,47 +340,3 @@ snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name) { return elem; } - -pa_channel_map* pa_alsa_channel_map_init_auto(pa_channel_map *m, unsigned channels) { - assert(m); - assert(channels > 0); - assert(channels <= PA_CHANNELS_MAX); - - pa_channel_map_init(m); - - m->channels = channels; - - /* The standard ALSA channel order */ - - switch (channels) { - case 1: - m->map[0] = PA_CHANNEL_POSITION_MONO; - return m; - - case 8: - m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT; - m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT; - /* Fall through */ - - case 6: - m->map[5] = PA_CHANNEL_POSITION_LFE; - /* Fall through */ - - case 5: - m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER; - /* Fall through */ - - case 4: - m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT; - m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; - /* Fall through */ - - case 2: - m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; - m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; - return m; - - default: - return NULL; - } -} diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index bad6e9bf0..69d4eddc2 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -42,6 +42,4 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev); snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name); -pa_channel_map* pa_alsa_channel_map_init_auto(pa_channel_map *m, unsigned channels); - #endif diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 99e74bfc8..47065659c 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -324,19 +324,8 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": failed to parse sample specification"); - goto fail; - } - - pa_alsa_channel_map_init_auto(&map, ss.channels); - if ((pa_modargs_get_channel_map(ma, &map) < 0)) { - pa_log(__FILE__": invalid channel map."); - goto fail; - } - - if (ss.channels != map.channels) { - pa_log(__FILE__": channel map and sample specification don't match."); + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { + pa_log(__FILE__": failed to parse sample specification and channel map"); goto fail; } diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 660bc83b3..d46f8e427 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -316,22 +316,11 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec(ma, &ss) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } - pa_alsa_channel_map_init_auto(&map, ss.channels); - if ((pa_modargs_get_channel_map(ma, &map) < 0)) { - pa_log(__FILE__": invalid channel map."); - goto fail; - } - - if (ss.channels != map.channels) { - pa_log(__FILE__": channel map and sample specification don't match."); - goto fail; - } - frame_size = pa_frame_size(&ss); /* Fix latency to 100ms */ diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 3b927d135..369778a6b 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -361,7 +361,7 @@ int pa__init(pa_core *c, pa_module*m) { if (ss.channels == master_sink->sample_spec.channels) map = master_sink->channel_map; else - pa_channel_map_init_auto(&map, ss.channels); + pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_DEFAULT); if ((pa_modargs_get_channel_map(ma, &map) < 0)) { pa_log(__FILE__": invalid channel map."); diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 090305303..324a2cb3e 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -296,7 +296,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - pa_channel_map_init_auto(&map, channels); + pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA); if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) { pa_log(__FILE__": failed to parse channel_map= argument."); goto fail; diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index ad39b9ddc..94cabbea2 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -294,7 +294,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - pa_channel_map_init_auto(&map, channels); + pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA); if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) { pa_log(__FILE__": failed to parse channel_map= argument."); goto fail; diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 9c564429c..5cdfeab8c 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -104,7 +104,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log(__FILE__": invalid sample format specification or channel map."); goto fail; } diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index e032ce466..b80122144 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -383,7 +383,7 @@ int pa__init(pa_core *c, pa_module*m) { } u->sample_spec = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->sample_spec, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->sample_spec, &map, PA_CHANNEL_MAP_ALSA) < 0) { pa_log(__FILE__": failed to parse sample specification or channel map"); goto fail; } diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 4d811a76f..eab9a60a2 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -347,7 +347,7 @@ int pa__init(pa_core *c, pa_module*m) { mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { pa_log(__FILE__": failed to parse sample specification or channel map"); goto fail; } diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 2be1b297b..0fb73cd88 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -154,7 +154,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log(__FILE__": invalid sample format specification"); goto fail; } diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index c80bfd093..d999754af 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -132,7 +132,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log(__FILE__": invalid sample format specification or channel map"); goto fail; } diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index bffcc7c0c..2e04b1208 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -895,7 +895,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log(__FILE__": invalid sample format specification"); goto fail; } diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 0bb20979b..d0def859e 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -197,7 +197,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (ss.channels != cm.channels) - pa_channel_map_init_auto(&cm, ss.channels); + pa_channel_map_init_auto(&cm, ss.channels, PA_CHANNEL_MAP_AIFF); payload = pa_rtp_payload_from_sample_spec(&ss); diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index 794711ae3..8d16f7b31 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -112,7 +112,7 @@ pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) { return m; } -pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels) { +pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) { assert(m); assert(channels > 0); assert(channels <= PA_CHANNELS_MAX); @@ -121,46 +121,99 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels) { m->channels = channels; - /* This is somewhat compatible with RFC3551 */ - - switch (channels) { - case 1: - m->map[0] = PA_CHANNEL_POSITION_MONO; - return m; - - case 6: - m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; - m->map[1] = PA_CHANNEL_POSITION_SIDE_LEFT; - m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; - m->map[3] = PA_CHANNEL_POSITION_FRONT_RIGHT; - m->map[4] = PA_CHANNEL_POSITION_SIDE_RIGHT; - m->map[5] = PA_CHANNEL_POSITION_LFE; - return m; + switch (def) { + case PA_CHANNEL_MAP_AIFF: - case 5: - m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; - m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT; - m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT; - /* Fall through */ + /* This is somewhat compatible with RFC3551 */ - case 2: - m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; - m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; - return m; + switch (channels) { + case 1: + m->map[0] = PA_CHANNEL_POSITION_MONO; + return m; + + case 6: + m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + m->map[1] = PA_CHANNEL_POSITION_SIDE_LEFT; + m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; + m->map[3] = PA_CHANNEL_POSITION_FRONT_RIGHT; + m->map[4] = PA_CHANNEL_POSITION_SIDE_RIGHT; + m->map[5] = PA_CHANNEL_POSITION_LFE; + return m; + + case 5: + m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; + m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT; + m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT; + /* Fall through */ + + case 2: + m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + return m; + + case 3: + m->map[0] = PA_CHANNEL_POSITION_LEFT; + m->map[1] = PA_CHANNEL_POSITION_RIGHT; + m->map[2] = PA_CHANNEL_POSITION_CENTER; + return m; + + case 4: + m->map[0] = PA_CHANNEL_POSITION_LEFT; + m->map[1] = PA_CHANNEL_POSITION_CENTER; + m->map[2] = PA_CHANNEL_POSITION_RIGHT; + m->map[3] = PA_CHANNEL_POSITION_LFE; + return m; + + default: + return NULL; + } - case 3: - m->map[0] = PA_CHANNEL_POSITION_LEFT; - m->map[1] = PA_CHANNEL_POSITION_RIGHT; - m->map[2] = PA_CHANNEL_POSITION_CENTER; - return m; + case PA_CHANNEL_MAP_ALSA: - case 4: - m->map[0] = PA_CHANNEL_POSITION_LEFT; - m->map[1] = PA_CHANNEL_POSITION_CENTER; - m->map[2] = PA_CHANNEL_POSITION_RIGHT; - m->map[3] = PA_CHANNEL_POSITION_LFE; - return m; + switch (channels) { + case 1: + m->map[0] = PA_CHANNEL_POSITION_MONO; + return m; + + case 8: + m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT; + m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT; + /* Fall through */ + + case 6: + m->map[5] = PA_CHANNEL_POSITION_LFE; + /* Fall through */ + + case 5: + m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER; + /* Fall through */ + + case 4: + m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT; + m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + /* Fall through */ + + case 2: + m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + return m; + + default: + return NULL; + } + + case PA_CHANNEL_MAP_AUX: { + unsigned i; + if (channels >= PA_CHANNELS_MAX) + return NULL; + + for (i = 0; i < channels; i++) + m->map[i] = PA_CHANNEL_POSITION_AUX0 + i; + + return m; + } + default: return NULL; } diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index 0fd1e5933..8270a5b30 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -120,6 +120,15 @@ typedef enum pa_channel_position { PA_CHANNEL_POSITION_MAX } pa_channel_position_t; +/** A list of channel mapping definitions for pa_channel_map_init_auto() */ +typedef enum pa_channel_map_def { + PA_CHANNEL_MAP_AIFF, /**< The mapping from RFC3551, which is based on AIFF-C */ + PA_CHANNEL_MAP_ALSA, /**< The default mapping used by ALSA */ + PA_CHANNEL_MAP_AUX, /**< Only aux channels */ + + PA_CHANNEL_MAP_DEFAULT = PA_CHANNEL_MAP_AIFF /**< The default channel map */ +} pa_channel_map_def_t; + /** A channel map which can be used to attach labels to specific * channels of a stream. These values are relevant for conversion and * mixing of streams */ @@ -138,9 +147,8 @@ pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m); pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m); /** Initialize the specified channel map for the specified number - * of channels using default labels and return a pointer to it. - * Uses the mapping from RFC3551, which is based on AIFF-C. */ -pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels); + * of channels using default labels and return a pointer to it. */ +pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def); /** Return a text label for the specified channel position */ const char* pa_channel_position_to_string(pa_channel_position_t pos); diff --git a/src/polyp/stream.c b/src/polyp/stream.c index bccdebe5d..b2711ce08 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -74,7 +74,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * if (map) s->channel_map = *map; else - pa_channel_map_init_auto(&s->channel_map, ss->channels); + pa_channel_map_init_auto(&s->channel_map, ss->channels, PA_CHANNEL_MAP_DEFAULT); s->channel = 0; s->channel_valid = 0; diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 82c61a1d2..3bba38ed3 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -141,7 +141,7 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c if (ss) { e->sample_spec = *ss; - pa_channel_map_init_auto(&e->channel_map, ss->channels); + pa_channel_map_init_auto(&e->channel_map, ss->channels, PA_CHANNEL_MAP_DEFAULT); e->volume.channels = e->sample_spec.channels; } diff --git a/src/polypcore/modargs.c b/src/polypcore/modargs.c index 6a02df0a9..713326bfc 100644 --- a/src/polypcore/modargs.c +++ b/src/polypcore/modargs.c @@ -280,7 +280,7 @@ int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *rmap) { return 0; } -int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *rss, pa_channel_map *rmap) { +int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *rss, pa_channel_map *rmap, pa_channel_map_def_t def) { pa_sample_spec ss; pa_channel_map map; @@ -293,7 +293,8 @@ int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *r if (pa_modargs_get_sample_spec(ma, &ss) < 0) return -1; - pa_channel_map_init_auto(&map, ss.channels); + if (!pa_channel_map_init_auto(&map, ss.channels, def)) + map.channels = 0; if (pa_modargs_get_channel_map(ma, &map) < 0) return -1; diff --git a/src/polypcore/modargs.h b/src/polypcore/modargs.h index 481ead99b..b6977d370 100644 --- a/src/polypcore/modargs.h +++ b/src/polypcore/modargs.h @@ -55,6 +55,6 @@ pa_modargs_get_channel_map(). Not always suitable, since this routine initializes the map parameter based on the channels field of the ss structure if no channel_map is found, using pa_channel_map_init_auto() */ -int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *ss, pa_channel_map *map); +int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *ss, pa_channel_map *map, pa_channel_map_def_t def); #endif diff --git a/src/polypcore/resampler.c b/src/polypcore/resampler.c index 7e85e2708..b2a8874b6 100644 --- a/src/polypcore/resampler.c +++ b/src/polypcore/resampler.c @@ -101,12 +101,12 @@ pa_resampler* pa_resampler_new( if (am) r->i_cm = *am; else - pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels); + pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels, PA_CHANNEL_MAP_DEFAULT); if (bm) r->o_cm = *bm; else - pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels); + pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels, PA_CHANNEL_MAP_DEFAULT); r->i_fz = pa_frame_size(a); r->o_fz = pa_frame_size(b); diff --git a/src/polypcore/sink-input.c b/src/polypcore/sink-input.c index 26e63b850..c10263903 100644 --- a/src/polypcore/sink-input.c +++ b/src/polypcore/sink-input.c @@ -32,32 +32,53 @@ #include #include #include +#include #include "sink-input.h" #define CONVERT_BUFFER_LENGTH 4096 +#define CHECK_VALIDITY_RETURN_NULL(condition) \ +do {\ +if (!(condition)) \ + return NULL; \ +} while (0) + pa_sink_input* pa_sink_input_new( - pa_sink *s, - const char *driver, - const char *name, - const pa_sample_spec *spec, - const pa_channel_map *map, - const pa_cvolume *volume, - int variable_rate, - int resample_method) { + pa_sink *s, + const char *driver, + const char *name, + const pa_sample_spec *spec, + const pa_channel_map *map, + const pa_cvolume *volume, + int variable_rate, + int resample_method) { pa_sink_input *i; pa_resampler *resampler = NULL; int r; char st[256]; pa_channel_map tmap; + pa_cvolume tvol; assert(s); assert(spec); assert(s->state == PA_SINK_RUNNING); + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + if (!map) + map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); + if (!volume) + volume = pa_cvolume_reset(&tvol, spec->channels); + + CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); + CHECK_VALIDITY_RETURN_NULL(volume && pa_cvolume_valid(volume)); + CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); + CHECK_VALIDITY_RETURN_NULL(volume->channels == spec->channels); + CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); + CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name)); + if (pa_idxset_size(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink."); return NULL; @@ -66,19 +87,6 @@ pa_sink_input* pa_sink_input_new( if (resample_method == PA_RESAMPLER_INVALID) resample_method = s->core->resample_method; - if (map && spec->channels != map->channels) - return NULL; - - if (volume && spec->channels != volume->channels) - return NULL; - - if (!map) { - if (!(pa_channel_map_init_auto(&tmap, spec->channels))) - return NULL; - - map = &tmap; - } - if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec) || !pa_channel_map_equal(map, &s->channel_map)) if (!(resampler = pa_resampler_new(spec, map, &s->sample_spec, &s->channel_map, s->core->memblock_stat, resample_method))) return NULL; @@ -94,12 +102,8 @@ pa_sink_input* pa_sink_input_new( i->sample_spec = *spec; i->channel_map = *map; - - if (volume) - i->volume = *volume; - else - pa_cvolume_reset(&i->volume, spec->channels); - + i->volume = *volume; + i->peek = NULL; i->drop = NULL; i->kill = NULL; diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index 17294059a..b59f1eaa6 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -29,6 +29,7 @@ #include #include + #include #include #include @@ -36,29 +37,46 @@ #include #include #include +#include #include "sink.h" #define MAX_MIX_CHANNELS 32 +#define CHECK_VALIDITY_RETURN_NULL(condition) \ +do {\ +if (!(condition)) \ + return NULL; \ +} while (0) + pa_sink* pa_sink_new( - pa_core *core, - const char *driver, - const char *name, - int fail, - const pa_sample_spec *spec, - const pa_channel_map *map) { + pa_core *core, + const char *driver, + const char *name, + int fail, + const pa_sample_spec *spec, + const pa_channel_map *map) { pa_sink *s; char *n = NULL; char st[256]; int r; + pa_channel_map tmap; assert(core); assert(name); - assert(*name); assert(spec); + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + + if (!map) + map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); + + CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); + CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); + CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); + CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name) && *name); + s = pa_xnew(pa_sink, 1); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) { @@ -75,10 +93,7 @@ pa_sink* pa_sink_new( s->owner = NULL; s->sample_spec = *spec; - if (map) - s->channel_map = *map; - else - pa_channel_map_init_auto(&s->channel_map, spec->channels); + s->channel_map = *map; s->inputs = pa_idxset_new(NULL, NULL); diff --git a/src/polypcore/sound-file.c b/src/polypcore/sound-file.c index a6ccb0649..f0378009b 100644 --- a/src/polypcore/sound-file.c +++ b/src/polypcore/sound-file.c @@ -75,7 +75,7 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *ma } if (map) - pa_channel_map_init_auto(map, ss->channels); + pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT); if ((l = pa_frame_size(ss)*sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { pa_log(__FILE__": File too large"); diff --git a/src/polypcore/source-output.c b/src/polypcore/source-output.c index 0cb5f3567..b31130718 100644 --- a/src/polypcore/source-output.c +++ b/src/polypcore/source-output.c @@ -31,16 +31,23 @@ #include #include #include +#include #include "source-output.h" +#define CHECK_VALIDITY_RETURN_NULL(condition) \ +do {\ +if (!(condition)) \ + return NULL; \ +} while (0) + pa_source_output* pa_source_output_new( - pa_source *s, - const char *driver, - const char *name, - const pa_sample_spec *spec, - const pa_channel_map *map, - int resample_method) { + pa_source *s, + const char *driver, + const char *name, + const pa_sample_spec *spec, + const pa_channel_map *map, + int resample_method) { pa_source_output *o; pa_resampler *resampler = NULL; @@ -51,7 +58,17 @@ pa_source_output* pa_source_output_new( assert(s); assert(spec); assert(s->state == PA_SOURCE_RUNNING); + + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + + if (!map) + map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); + CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); + CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); + CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); + CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name)); + if (pa_idxset_size(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { pa_log(__FILE__": Failed to create source output: too many outputs per source."); return NULL; @@ -60,16 +77,11 @@ pa_source_output* pa_source_output_new( if (resample_method == PA_RESAMPLER_INVALID) resample_method = s->core->resample_method; - if (!map) { - pa_channel_map_init_auto(&tmap, spec->channels); - map = &tmap; - } - if (!pa_sample_spec_equal(&s->sample_spec, spec) || !pa_channel_map_equal(&s->channel_map, map)) if (!(resampler = pa_resampler_new(&s->sample_spec, &s->channel_map, spec, map, s->core->memblock_stat, resample_method))) return NULL; - o = pa_xmalloc(sizeof(pa_source_output)); + o = pa_xnew(pa_source_output, 1); o->ref = 1; o->state = PA_SOURCE_OUTPUT_RUNNING; o->name = pa_xstrdup(name); @@ -137,7 +149,6 @@ static void source_output_free(pa_source_output* o) { pa_xfree(o); } - void pa_source_output_unref(pa_source_output* o) { assert(o); assert(o->ref >= 1); diff --git a/src/polypcore/source.c b/src/polypcore/source.c index 3a78825bb..fca281a79 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -34,26 +34,43 @@ #include #include #include +#include #include "source.h" +#define CHECK_VALIDITY_RETURN_NULL(condition) \ +do {\ +if (!(condition)) \ + return NULL; \ +} while (0) + pa_source* pa_source_new( - pa_core *core, - const char *driver, - const char *name, - int fail, - const pa_sample_spec *spec, - const pa_channel_map *map) { + pa_core *core, + const char *driver, + const char *name, + int fail, + const pa_sample_spec *spec, + const pa_channel_map *map) { pa_source *s; char st[256]; int r; + pa_channel_map tmap; assert(core); assert(name); - assert(*name); assert(spec); + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + + if (!map) + map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); + + CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); + CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); + CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); + CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name) && *name); + s = pa_xnew(pa_source, 1); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) { @@ -70,10 +87,7 @@ pa_source* pa_source_new( s->owner = NULL; s->sample_spec = *spec; - if (map) - s->channel_map = *map; - else - pa_channel_map_init_auto(&s->channel_map, spec->channels); + s->channel_map = *map; s->outputs = pa_idxset_new(NULL, NULL); s->monitor_of = NULL; diff --git a/src/tests/channelmap-test.c b/src/tests/channelmap-test.c index 522c136fc..c6644229b 100644 --- a/src/tests/channelmap-test.c +++ b/src/tests/channelmap-test.c @@ -10,10 +10,18 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_channel_map map, map2; - pa_channel_map_init_auto(&map, 5); + pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_AIFF); fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map)); + pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_AUX); + + fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map)); + + pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_ALSA); + + fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map)); + pa_channel_map_parse(&map2, cm); assert(pa_channel_map_equal(&map, &map2)); From 05c14685203b5ced74bfec0e6a3b3aa3f8721c51 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 06:31:18 +0000 Subject: [PATCH 0794/1514] Use default channel map for Solaris module. There doesn't seem to be a standard for > 2 channels, so we'll have to rely on the user. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@889 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index eaac9e6e4..3e7c2fb46 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -525,7 +525,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } From c752e11c02b0059b0212c3c3358b3cc0ebe902ac Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 06:58:43 +0000 Subject: [PATCH 0795/1514] Add Microsoft's WAVEFORMWATEEXTENSIBLE channel mapping. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@890 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.c | 59 ++++++++++++++++++++++++++++++++++++++++++ src/polyp/channelmap.h | 1 + 2 files changed, 60 insertions(+) diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index 8d16f7b31..1e6347d62 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -214,6 +214,65 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p return m; } + case PA_CHANNEL_MAP_WAVEEX: + + switch (channels) { + case 1: + m->map[0] = PA_CHANNEL_POSITION_MONO; + return m; + + case 18: + m->map[15] = PA_CHANNEL_POSITION_TOP_REAR_LEFT; + m->map[16] = PA_CHANNEL_POSITION_TOP_REAR_CENTER; + m->map[17] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT; + /* Fall through */ + + case 15: + m->map[12] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT; + m->map[13] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER; + m->map[14] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT; + /* Fall through */ + + case 12: + m->map[11] = PA_CHANNEL_POSITION_TOP_CENTER; + /* Fall through */ + + case 11: + m->map[9] = PA_CHANNEL_POSITION_SIDE_LEFT; + m->map[10] = PA_CHANNEL_POSITION_SIDE_RIGHT; + /* Fall through */ + + case 9: + m->map[8] = PA_CHANNEL_POSITION_REAR_CENTER; + /* Fall through */ + + case 8: + m->map[6] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER; + m->map[7] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER; + /* Fall through */ + + case 6: + m->map[4] = PA_CHANNEL_POSITION_REAR_LEFT; + m->map[5] = PA_CHANNEL_POSITION_REAR_RIGHT; + /* Fall through */ + + case 4: + m->map[3] = PA_CHANNEL_POSITION_LFE; + /* Fall through */ + + case 3: + m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; + /* Fall through */ + + case 2: + m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + return m; + + default: + return NULL; + } + default: return NULL; } diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index 8270a5b30..c9fae17e8 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -125,6 +125,7 @@ typedef enum pa_channel_map_def { PA_CHANNEL_MAP_AIFF, /**< The mapping from RFC3551, which is based on AIFF-C */ PA_CHANNEL_MAP_ALSA, /**< The default mapping used by ALSA */ PA_CHANNEL_MAP_AUX, /**< Only aux channels */ + PA_CHANNEL_MAP_WAVEEX, /**< Microsoft's WAVEFORMATEXTENSIBLE mapping */ PA_CHANNEL_MAP_DEFAULT = PA_CHANNEL_MAP_AIFF /**< The default channel map */ } pa_channel_map_def_t; From 71f681aa43156056965a906101e07b27c94eef45 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 06:58:58 +0000 Subject: [PATCH 0796/1514] Set default channel map system for waveout module. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@891 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 34607421b..2d9c42eba 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -469,7 +469,7 @@ int pa__init(pa_core *c, pa_module*m) { } ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_WAVEEX) < 0) { pa_log(__FILE__": failed to parse sample specification"); goto fail; } From d4d1e5edf7af01b0d0e32da9fa323702f5174232 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 11:07:16 +0000 Subject: [PATCH 0797/1514] Documentation for the threaded main loop API. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@892 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/context.h | 6 +- src/polyp/polypaudio.h | 13 ++- src/polyp/thread-mainloop.h | 201 ++++++++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 5 deletions(-) diff --git a/src/polyp/context.h b/src/polyp/context.h index ff93dd110..04e2af4dc 100644 --- a/src/polyp/context.h +++ b/src/polyp/context.h @@ -51,13 +51,17 @@ * pa_mainloop_api structure. * * To actually be able to use these functions, an implementation needs to - * be coupled to the abstraction. There are two of these shipped with + * be coupled to the abstraction. There are three of these shipped with * polypaudio, but any other can be used with a minimal ammount of work, * provided it supports the three basic events listed above. * * The implementations shipped with polypaudio are: * * \li \subpage mainloop - A minimal but fast implementation based on poll(). + * \li \subpage threaded_mainloop - A special version of the previous + * implementation where all of Polypaudio's + * internal handling runs in a separate + * thread. * \li \subpage glib-mainloop - A wrapper around GLIB's main loop. Available * for both GLIB 1.2 and GLIB 2.x. * diff --git a/src/polyp/polypaudio.h b/src/polyp/polypaudio.h index af80f9ead..5dd7aa103 100644 --- a/src/polyp/polypaudio.h +++ b/src/polyp/polypaudio.h @@ -66,6 +66,11 @@ * based style or if you want to use the advanced features of the * polypaudio API. A guide can be found in \subpage async. * + * By using the built-in threaded main loop, it is possible to acheive a + * pseudo-synchronous API, which can be useful in synchronous applications + * where the simple API is insufficient. See the \ref async page for + * details. + * * \section thread_sec Threads * * The polypaudio client libraries are not designed to be used in a @@ -73,12 +78,12 @@ * safe. * * To use a the libraries in a threaded environment, you must assure that - * all objects are only used in the same thread they were created in. - * Normally, this means that all objects belonging to a single context - * must be accessed from the same thread. + * all objects are only used in one thread at a time. Normally, this means + * that all objects belonging to a single context must be accessed from the + * same thread. * * The included main loop implementation is also not thread safe. Take care - * to make sure event lists are not manipulated when any library code is + * to make sure event lists are not manipulated when any other code is * using the main loop. * * \section pkgconfig pkg-config diff --git a/src/polyp/thread-mainloop.h b/src/polyp/thread-mainloop.h index 94a48d021..81e8d6746 100644 --- a/src/polyp/thread-mainloop.h +++ b/src/polyp/thread-mainloop.h @@ -27,6 +27,207 @@ PA_C_DECL_BEGIN +/** \page threaded_mainloop Threaded Main Loop + * + * \section overv_sec Overview + * + * The threaded main loop implementation is a special version of the primary + * main loop implementation (see \ref mainloop). For the basic design, see + * its documentation. + * + * The added feature in the threaded main loop is that it spawns a new thread + * that runs the real main loop. This allows a synchronous application to use + * the asynchronous API without risking to stall the Polypaudio library. + * + * \section creat_sec Creation + * + * A pa_threaded_mainloop object is created using pa_threaded_mainloop_new(). + * This will only allocate the required structures though, so to use it the + * thread must also be started. This is done through + * pa_threaded_mainloop_start(), after which you can start using the main loop. + * + * \section destr_sec Destruction + * + * When the Polypaudio connection has been terminated, the thread must be + * stopped and the resources freed. Stopping the thread is done using + * pa_threaded_mainloop_stop(), which must be called without the lock (see + * below) held. When that function returns, the thread is stopped and the + * pa_threaded_mainloop object can be freed using pa_threaded_mainloop_free(). + * + * \section lock_sec Locking + * + * Since the Polypaudio API doesn't allow concurrent accesses to objects, + * a locking scheme must be used to guarantee safe usage. The threaded main + * loop API provides such a scheme through the functions + * pa_threaded_mainloop_lock() and pa_threaded_mainloop_unlock(). + * + * The lock is recursive, so it's safe to use it multiple times from the same + * thread. Just make sure you call pa_threaded_mainloop_unlock() the same + * number of times you called pa_threaded_mainloop_lock(). + * + * The lock needs to be held whenever you call any Polypaudio function that + * uses an object associated with this main loop. Make sure you do not hold + * on to the lock more than necessary though, as the threaded main loop stops + * while the lock is held. + * + * Example: + * + * \code + * void my_check_stream_func(pa_threaded_mainloop *m, pa_stream *s) { + * pa_stream_state_t state; + * + * pa_threaded_mainloop_lock(m); + * + * state = pa_stream_get_state(s); + * + * pa_threaded_mainloop_unlock(m); + * + * if (state == PA_STREAM_READY) + * printf("Stream is ready!"); + * else + * printf("Stream is not ready!"); + * } + * \endcode + * + * \section cb_sec Callbacks + * + * Callbacks in Polypaudio are asynchronous, so they require extra care when + * using them together with a threaded main loop. + * + * The easiest way to turn the callback based operations into synchronous + * ones, is to simply wait for the callback to be called and continue from + * there. This is the approach chosen in Polypaudio's threaded API. + * + * \subsection basic_subsec Basic callbacks + * + * For the basic case, where all that is required is to wait for the callback + * to be invoked, the code should look something like this: + * + * Example: + * + * \code + * static void my_drain_callback(pa_stream*s, int success, void *userdata) { + * pa_threaded_mainloop *m; + * + * m = (pa_threaded_mainloop*)userdata; + * assert(m); + * + * pa_threaded_mainloop_signal(m, 0); + * } + * + * void my_drain_stream_func(pa_threaded_mainloop *m, pa_stream *s) { + * pa_operation *o; + * + * pa_threaded_mainloop_lock(m); + * + * o = pa_stream_drain(s, my_drain_callback, m); + * assert(o); + * + * while (pa_operation_get_state(o) != OPERATION_DONE) + * pa_threaded_mainloop_wait(m); + * + * pa_operation_unref(o); + * + * pa_threaded_mainloop_unlock(m); + * } + * \endcode + * + * The main function, my_drain_stream_func(), will wait for the callback to + * be called using pa_threaded_mainloop_wait(). + * + * If your application is multi-threaded, then this waiting must be done + * inside a while loop. The reason for this is that multiple threads might be + * using pa_threaded_mainloop_wait() at the same time. Each thread must + * therefore verify that it was its callback that was invoked. + * + * The callback, my_drain_callback(), indicates to the main function that it + * has been called using pa_threaded_mainloop_signal(). + * + * As you can see, both pa_threaded_mainloop_wait() may only be called with + * the lock held. The same thing is true for pa_threaded_mainloop_signal(), + * but as the lock is held before the callback is invoked, you do not have to + * deal with that. + * + * The functions will not dead lock because the wait function will release + * the lock before waiting and then regrab it once it has been signaled. + * For those of you familiar with threads, the behaviour is that of a + * condition variable. + * + * \subsection data_subsec Data callbacks + * + * For many callbacks, simply knowing that they have been called is + * insufficient. The callback also receives some data that is desired. To + * access this data safely, we must extend our example a bit: + * + * \code + * static int *drain_result; + * + * static void my_drain_callback(pa_stream*s, int success, void *userdata) { + * pa_threaded_mainloop *m; + * + * m = (pa_threaded_mainloop*)userdata; + * assert(m); + * + * drain_result = &success; + * + * pa_threaded_mainloop_signal(m, 1); + * } + * + * void my_drain_stream_func(pa_threaded_mainloop *m, pa_stream *s) { + * pa_operation *o; + * + * pa_threaded_mainloop_lock(m); + * + * o = pa_stream_drain(s, my_drain_callback, m); + * assert(o); + * + * while (pa_operation_get_state(o) != OPERATION_DONE) + * pa_threaded_mainloop_wait(m); + * + * pa_operation_unref(o); + * + * if (*drain_result) + * printf("Success!"); + * else + * printf("Bitter defeat..."); + * + * pa_threaded_mainloop_accept(m); + * + * pa_threaded_mainloop_unlock(m); + * } + * \endcode + * + * The example is a bit silly as it would probably have been easier to just + * copy the contents of success, but for larger data structures this can be + * wasteful. + * + * The difference here compared to the basic callback is the 1 sent to + * pa_threaded_mainloop_signal() and the call to + * pa_threaded_mainloop_accept(). What will happen is that + * pa_threaded_mainloop_signal() will signal the main function and then stop. + * The main function is then free to use the data in the callback until + * pa_threaded_mainloop_accept() is called, which will allow the callback + * to continue. + * + * Note that pa_threaded_mainloop_accept() must be called some time between + * exiting the while loop and unlocking the main loop! Failure to do so will + * result in a race condition. I.e. it is not ok to release the lock and + * regrab it before calling pa_threaded_mainloop_accept(). + * + * \subsection async_subsec Asynchronous callbacks + * + * Polypaudio also has callbacks that are completely asynchronous, meaning + * that they can be called at any time. The threading main loop API provides + * the locking mechanism to handle concurrent accesses, but nothing else. + * Applications will have to handle communication from the callback to the + * main program through some own system. + * + * The callbacks that are completely asynchronous are: + * + * \li State callbacks for contexts, streams, etc. + * \li Subscription notifications + */ + /** \file * * A thread based event loop implementation based on pa_mainloop. The From 6ab421381ab9047d92f2679b67a8a4e0ea611d11 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 11:10:59 +0000 Subject: [PATCH 0798/1514] Update documentation to contain the UTF-8 requirement. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@893 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/polypaudio.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/polyp/polypaudio.h b/src/polyp/polypaudio.h index 5dd7aa103..1830dea86 100644 --- a/src/polyp/polypaudio.h +++ b/src/polyp/polypaudio.h @@ -54,6 +54,11 @@ * \li The complete but somewhat complicated to use asynchronous API * \li The simplified, easy to use, but limited synchronous API * + * All strings in Polypaudio are in the UTF-8 encoding, regardless of current + * locale. Some functions will filter invalid sequences from the string, some + * will simply fail. To ensure reliable behaviour, make sure everything you + * pass to the API is already in UTF-8. + * \section simple_sec Simple API * * Use this if you develop your program in synchronous style and just From e767fda182739827c6e8a4b843c826409b8fbc80 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 11:23:07 +0000 Subject: [PATCH 0799/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@894 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/todo b/doc/todo index 8b5daefb1..369f7a266 100644 --- a/doc/todo +++ b/doc/todo @@ -5,17 +5,14 @@ Post 0.8: - dbus/hal - polish for starting polypaudio as root/system-wide instance - chroot() -- add threading API - module-tunnel: improve latency calculation - port from howl to avahi - multiline configuration statements - use scatter/gather io for sockets -- add a synchronous API (base it on xmms-polyp) - rtp module ported to Win32 (sendmsg/recvmsg emulation) - CODECs to reduce bandwidth usage (plug-in based) - Remove symdef files and use macros (like most other projects) - use software volume when hardware doesn't support all channels (alsa done) -- double check channel maps for backends, including that mixer and pcm match - paplay needs to set a channel map. our default is only correct for AIFF. (we need help from libsndfile for this) - silence generation should be moved into the core to avoid races and code @@ -23,10 +20,12 @@ Post 0.8: - examine if it is possible to mimic esd's handling of half duplex cards (switch to capture when a recording client connects and drop playback during that time) -- fix channel maps in all external backends. Take care when doing volume - changes if you're modifying a sink/source since those might have a different - map. - in avahi-simple: sleep until latency data is available again if NODATA has happened +- Fix a way for the threading API to handle state and subscription callbacks + in a nice way. +- iconv stuff sent from utils to server (UTF-8) +- iconv stuff leaving the server (e.g. syslog). Sample loading probably needs + help as well. Long term: - pass meta info for hearing impaired From ed3606c88480de9b348dee451e7ebfd1f6bd15d7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 13:06:04 +0000 Subject: [PATCH 0800/1514] add new channel mapping standard PA_CHANNEL_MAP_OSS git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@895 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.c | 35 +++++++++++++++++++++++++++++++++++ src/polyp/channelmap.h | 7 ++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index 1e6347d62..7266a0a0e 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -273,6 +273,41 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p return NULL; } + case PA_CHANNEL_MAP_OSS: + + switch (channels) { + case 1: + m->map[0] = PA_CHANNEL_POSITION_MONO; + return m; + + case 8: + m->map[6] = PA_CHANNEL_POSITION_REAR_LEFT; + m->map[7] = PA_CHANNEL_POSITION_REAR_RIGHT; + /* Fall through */ + + case 6: + m->map[4] = PA_CHANNEL_POSITION_SIDE_LEFT; + m->map[5] = PA_CHANNEL_POSITION_SIDE_RIGHT; + /* Fall through */ + + case 4: + m->map[3] = PA_CHANNEL_POSITION_LFE; + /* Fall through */ + + case 3: + m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; + /* Fall through */ + + case 2: + m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + return m; + + default: + return NULL; + } + + default: return NULL; } diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index c9fae17e8..feccd284b 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -122,10 +122,11 @@ typedef enum pa_channel_position { /** A list of channel mapping definitions for pa_channel_map_init_auto() */ typedef enum pa_channel_map_def { - PA_CHANNEL_MAP_AIFF, /**< The mapping from RFC3551, which is based on AIFF-C */ - PA_CHANNEL_MAP_ALSA, /**< The default mapping used by ALSA */ - PA_CHANNEL_MAP_AUX, /**< Only aux channels */ + PA_CHANNEL_MAP_AIFF, /**< The mapping from RFC3551, which is based on AIFF-C */ + PA_CHANNEL_MAP_ALSA, /**< The default mapping used by ALSA */ + PA_CHANNEL_MAP_AUX, /**< Only aux channels */ PA_CHANNEL_MAP_WAVEEX, /**< Microsoft's WAVEFORMATEXTENSIBLE mapping */ + PA_CHANNEL_MAP_OSS, /**< The default channel mapping used by OSS as defined in the OSS 4.0 API specs */ PA_CHANNEL_MAP_DEFAULT = PA_CHANNEL_MAP_AIFF /**< The default channel map */ } pa_channel_map_def_t; From 270a409bf543f0ec7152f66e76d22445434aca4d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 13:09:46 +0000 Subject: [PATCH 0801/1514] use PA_CHANNEL_MAP_OSS in module-oss, module-oss-mmap git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@896 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss-mmap.c | 2 +- src/modules/module-oss.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index b80122144..ddf33532f 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -383,7 +383,7 @@ int pa__init(pa_core *c, pa_module*m) { } u->sample_spec = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->sample_spec, &map, PA_CHANNEL_MAP_ALSA) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->sample_spec, &map, PA_CHANNEL_MAP_OSS) < 0) { pa_log(__FILE__": failed to parse sample specification or channel map"); goto fail; } diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index eab9a60a2..f6d19544b 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -347,7 +347,7 @@ int pa__init(pa_core *c, pa_module*m) { mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); ss = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_OSS) < 0) { pa_log(__FILE__": failed to parse sample specification or channel map"); goto fail; } From 106fb20d564b28802143f4916662fe0d10c1a1f0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 13:15:12 +0000 Subject: [PATCH 0802/1514] increase PA_CHANNELS_MAX to 32 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@897 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/channelmap.h | 16 ++++++++++++++++ src/polyp/sample.h | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/polyp/channelmap.h b/src/polyp/channelmap.h index feccd284b..645a8a388 100644 --- a/src/polyp/channelmap.h +++ b/src/polyp/channelmap.h @@ -106,6 +106,22 @@ typedef enum pa_channel_position { PA_CHANNEL_POSITION_AUX13, PA_CHANNEL_POSITION_AUX14, PA_CHANNEL_POSITION_AUX15, + PA_CHANNEL_POSITION_AUX16, + PA_CHANNEL_POSITION_AUX17, + PA_CHANNEL_POSITION_AUX18, + PA_CHANNEL_POSITION_AUX19, + PA_CHANNEL_POSITION_AUX20, + PA_CHANNEL_POSITION_AUX21, + PA_CHANNEL_POSITION_AUX22, + PA_CHANNEL_POSITION_AUX23, + PA_CHANNEL_POSITION_AUX24, + PA_CHANNEL_POSITION_AUX25, + PA_CHANNEL_POSITION_AUX26, + PA_CHANNEL_POSITION_AUX27, + PA_CHANNEL_POSITION_AUX28, + PA_CHANNEL_POSITION_AUX29, + PA_CHANNEL_POSITION_AUX30, + PA_CHANNEL_POSITION_AUX31, PA_CHANNEL_POSITION_TOP_CENTER, diff --git a/src/polyp/sample.h b/src/polyp/sample.h index 4de84301a..09b12fd79 100644 --- a/src/polyp/sample.h +++ b/src/polyp/sample.h @@ -100,7 +100,7 @@ PA_C_DECL_BEGIN /** Maximum number of allowed channels */ -#define PA_CHANNELS_MAX 16 +#define PA_CHANNELS_MAX 32 /** Sample format */ typedef enum pa_sample_format { From 31a9d4fb301bdfed50bee2cf162cc98093bb19f6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 14:06:12 +0000 Subject: [PATCH 0803/1514] when playing an ULAW or ALAW audio file, do not convert to S16NE unconditionally, instead use sf_read_raw() to read raw audio data git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@898 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/paplay.c | 57 ++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/utils/paplay.c b/src/utils/paplay.c index ad9d45533..d4af95c14 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -57,7 +57,7 @@ static pa_sample_spec sample_spec = { 0, 0, 0 }; static pa_channel_map channel_map; static int channel_map_set = 0; -static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames); +static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames) = NULL; /* A shortcut for terminating the application */ static void quit(int ret) { @@ -98,26 +98,30 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { /* This is called whenever new data may be written to the stream */ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { - size_t k; - sf_count_t f, n; + sf_count_t bytes; void *data; assert(s && length); if (!sndfile) return; - - k = pa_frame_size(&sample_spec); data = malloc(length); - n = length/k; - - f = readf_function(sndfile, data, n); + if (readf_function) { + size_t k = pa_frame_size(&sample_spec); - if (f > 0) - pa_stream_write(s, data, f*k, free, 0, PA_SEEK_RELATIVE); + if ((bytes = readf_function(sndfile, data, length/k)) > 0) + bytes *= k; + + } else + bytes = sf_read_raw(sndfile, data, length); - if (f < n) { + if (bytes > 0) + pa_stream_write(s, data, bytes, free, 0, PA_SEEK_RELATIVE); + else + free(data); + + if (bytes < length) { sf_close(sndfile); sndfile = NULL; pa_operation_unref(pa_stream_drain(s, stream_drain_complete, NULL)); @@ -296,16 +300,8 @@ int main(int argc, char *argv[]) { } } - filename = optind < argc ? argv[optind] : "STDIN"; - - if (!client_name) - client_name = strdup(bn); - - if (!stream_name) - stream_name = strdup(filename); - memset(&sfinfo, 0, sizeof(sfinfo)); if (optind < argc) @@ -317,18 +313,27 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Failed to open file '%s'\n", filename); goto quit; } - + sample_spec.rate = sfinfo.samplerate; sample_spec.channels = sfinfo.channels; switch (sfinfo.format & 0xFF) { case SF_FORMAT_PCM_16: case SF_FORMAT_PCM_U8: - case SF_FORMAT_ULAW: - case SF_FORMAT_ALAW: sample_spec.format = PA_SAMPLE_S16NE; readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_short; break; + + case SF_FORMAT_ULAW: + sample_spec.format = PA_SAMPLE_ULAW; + readf_function = NULL; + break; + + case SF_FORMAT_ALAW: + sample_spec.format = PA_SAMPLE_ALAW; + readf_function = NULL; + break; + case SF_FORMAT_FLOAT: default: sample_spec.format = PA_SAMPLE_FLOAT32NE; @@ -343,6 +348,14 @@ int main(int argc, char *argv[]) { goto quit; } + if (!client_name) + client_name = strdup(bn); + + if (!stream_name) { + const char *n = sf_get_string(sndfile, SF_STR_TITLE); + stream_name = strdup(n ? n : filename); + } + if (verbose) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(t, sizeof(t), &sample_spec); From e6695538d721941132db2183e40f142b9e52076e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 14:54:41 +0000 Subject: [PATCH 0804/1514] * use S16NE for SF_FORMAT_PCM_S8 formats, too git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@899 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/paplay.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/utils/paplay.c b/src/utils/paplay.c index d4af95c14..5f2036157 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -317,24 +317,26 @@ int main(int argc, char *argv[]) { sample_spec.rate = sfinfo.samplerate; sample_spec.channels = sfinfo.channels; + readf_function = NULL; + switch (sfinfo.format & 0xFF) { case SF_FORMAT_PCM_16: case SF_FORMAT_PCM_U8: + case SF_FORMAT_PCM_S8: sample_spec.format = PA_SAMPLE_S16NE; readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_short; break; case SF_FORMAT_ULAW: sample_spec.format = PA_SAMPLE_ULAW; - readf_function = NULL; break; case SF_FORMAT_ALAW: sample_spec.format = PA_SAMPLE_ALAW; - readf_function = NULL; break; case SF_FORMAT_FLOAT: + case SF_FORMAT_DOUBLE: default: sample_spec.format = PA_SAMPLE_FLOAT32NE; readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_float; From b47b257a91441dbfb2c716d71f8008ad4f2db1d5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 14:55:17 +0000 Subject: [PATCH 0805/1514] support loading ULAW/ALAW files into ULAW/ALAW memchunks git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@900 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/sound-file.c | 57 ++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/src/polypcore/sound-file.c b/src/polypcore/sound-file.c index f0378009b..bd0cf5961 100644 --- a/src/polypcore/sound-file.c +++ b/src/polypcore/sound-file.c @@ -39,7 +39,7 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *ma SF_INFO sfinfo; int ret = -1; size_t l; - sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames); + sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL; assert(fname && ss && chunk); chunk->memblock = NULL; @@ -53,17 +53,27 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *ma } switch (sfinfo.format & SF_FORMAT_SUBMASK) { - case SF_FORMAT_FLOAT: - case SF_FORMAT_DOUBLE: - /* Only float and double need a special case. */ - ss->format = PA_SAMPLE_FLOAT32NE; - readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float; - break; - default: - /* Everything else is cleanly converted to signed 16 bit. */ + case SF_FORMAT_PCM_16: + case SF_FORMAT_PCM_U8: + case SF_FORMAT_PCM_S8: ss->format = PA_SAMPLE_S16NE; readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short; break; + + case SF_FORMAT_ULAW: + ss->format = PA_SAMPLE_ULAW; + break; + + case SF_FORMAT_ALAW: + ss->format = PA_SAMPLE_ALAW; + break; + + case SF_FORMAT_FLOAT: + case SF_FORMAT_DOUBLE: + default: + ss->format = PA_SAMPLE_FLOAT32NE; + readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float; + break; } ss->rate = sfinfo.samplerate; @@ -87,11 +97,12 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *ma chunk->index = 0; chunk->length = l; - if (readf_function(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) { + if ((readf_function && readf_function(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) || + (!readf_function && sf_read_raw(sf, chunk->memblock->data, l) != l)) { pa_log(__FILE__": Premature file end"); goto finish; } - + ret = 0; finish: @@ -119,15 +130,25 @@ int pa_sound_file_too_big_to_cache(const char *fname) { sf_close(sf); switch (sfinfo.format & SF_FORMAT_SUBMASK) { - case SF_FORMAT_FLOAT: - case SF_FORMAT_DOUBLE: - /* Only float and double need a special case. */ - ss.format = PA_SAMPLE_FLOAT32NE; - break; - default: - /* Everything else is cleanly converted to signed 16 bit. */ + case SF_FORMAT_PCM_16: + case SF_FORMAT_PCM_U8: + case SF_FORMAT_PCM_S8: ss.format = PA_SAMPLE_S16NE; break; + + case SF_FORMAT_ULAW: + ss.format = PA_SAMPLE_ULAW; + break; + + case SF_FORMAT_ALAW: + ss.format = PA_SAMPLE_ALAW; + break; + + case SF_FORMAT_DOUBLE: + case SF_FORMAT_FLOAT: + default: + ss.format = PA_SAMPLE_FLOAT32NE; + break; } ss.rate = sfinfo.samplerate; From fa53ed7aafc681c69aa9a6a28072fe398a845662 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 14:55:54 +0000 Subject: [PATCH 0806/1514] * support native ULAW/ALAW file streams * fix shutdown of file streams git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@901 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/sound-file-stream.c | 39 ++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/polypcore/sound-file-stream.c b/src/polypcore/sound-file-stream.c index ca762d6a3..fdacea54b 100644 --- a/src/polypcore/sound-file-stream.c +++ b/src/polypcore/sound-file-stream.c @@ -65,10 +65,6 @@ static void sink_input_kill(pa_sink_input *i) { free_userdata(i->userdata); } -static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) { - sink_input_kill(i); -} - static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { struct userdata *u; assert(i && chunk && i->userdata); @@ -76,18 +72,25 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { if (!u->memchunk.memblock) { uint32_t fs = pa_frame_size(&i->sample_spec); - sf_count_t samples = BUF_SIZE/fs; + sf_count_t n; u->memchunk.memblock = pa_memblock_new(BUF_SIZE, i->sink->core->memblock_stat); u->memchunk.index = 0; - samples = u->readf_function(u->sndfile, u->memchunk.memblock->data, samples); - u->memchunk.length = samples*fs; + + if (u->readf_function) { + if ((n = u->readf_function(u->sndfile, u->memchunk.memblock->data, BUF_SIZE/fs)) <= 0) + n = 0; + + u->memchunk.length = n * fs; + } else { + if ((n = sf_read_raw(u->sndfile, u->memchunk.memblock->data, BUF_SIZE)) <= 0) + n = 0; + + u->memchunk.length = n; + } if (!u->memchunk.length) { - pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; - u->memchunk.index = u->memchunk.length = 0; - pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); + free_userdata(u); return -1; } } @@ -135,14 +138,24 @@ int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume) { goto fail; } + u->readf_function = NULL; + switch (sfinfo.format & 0xFF) { case SF_FORMAT_PCM_16: case SF_FORMAT_PCM_U8: - case SF_FORMAT_ULAW: - case SF_FORMAT_ALAW: + case SF_FORMAT_PCM_S8: ss.format = PA_SAMPLE_S16NE; u->readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short; break; + + case SF_FORMAT_ULAW: + ss.format = PA_SAMPLE_ULAW; + break; + + case SF_FORMAT_ALAW: + ss.format = PA_SAMPLE_ALAW; + break; + case SF_FORMAT_FLOAT: default: ss.format = PA_SAMPLE_FLOAT32NE; From db242e11b2b7a07231238cbb70277cda48a64e2c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 14:58:50 +0000 Subject: [PATCH 0807/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@902 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 369f7a266..657f4bf33 100644 --- a/doc/todo +++ b/doc/todo @@ -20,7 +20,6 @@ Post 0.8: - examine if it is possible to mimic esd's handling of half duplex cards (switch to capture when a recording client connects and drop playback during that time) -- in avahi-simple: sleep until latency data is available again if NODATA has happened - Fix a way for the threading API to handle state and subscription callbacks in a nice way. - iconv stuff sent from utils to server (UTF-8) From 6d281a57813794d9575b3f7088b8526bcae2e3bb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 15:19:15 +0000 Subject: [PATCH 0808/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@903 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/todo b/doc/todo index 657f4bf33..79b1894a4 100644 --- a/doc/todo +++ b/doc/todo @@ -34,4 +34,3 @@ Backends for: - portaudio (semi-done) - sdl - OSS (esddsp style) -- gstreamer (needs to be updated) From 1267285257aaa60630b59f0f5c62c4c7f4a8d8df Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 15:19:30 +0000 Subject: [PATCH 0809/1514] add documentation for module-volume-restore git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@904 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/modules.html.in | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/doc/modules.html.in b/doc/modules.html.in index 6a6b78875..af6b6de61 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -464,16 +464,30 @@ which is replaced by source_name (with a default of jack_in) f

    Adjust the volume of a playback stream automatically based on its name.

    - +
    table=The regular expression matching table file to use
    table=The regular expression matching table file to use (defaults to ~/.polypaudio/match.table)

    The table file should contain a regexp and volume on each line, seperated by spaces. An example:

    -^sample: 25
    +^sample: 32000
     
    -

    The volumes of all streams with titles starting with sample: are automatically set to 25. (FYI: All sample cache streams start with sample:)

    +

    The volumes of all streams with titles starting with sample: are automatically set to 32000. (FYI: All sample cache streams start with sample:)

    + +

    module-volume-restore

    + +

    Adjust the volume of a playback stream automatically based on its name.

    + + + +
    table=The table file to use (defaults to ~/.polypaudio/volume.table)
    + +

    In contrast to module-match this module needs no explicit +configuration. Instead the volumes are saved and restored in a fully +automatical fashion depending on the client name to identify +streams. The volume for a stream is automatically saved every time it is +changed and than restored when a new stream is created.

    module-detect

    From e0bf4a32f3ca7b9cf472a37c31be4a6202d39fa8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 15:21:08 +0000 Subject: [PATCH 0810/1514] add proper locking when accessing the file volume.table git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@905 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index b379e53cf..f9e7d0132 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "module-volume-restore-symdef.h" @@ -116,7 +117,7 @@ static int load_rules(struct userdata *u) { f = u->table_file ? fopen(u->table_file, "r") : pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "r"); - + if (!f) { if (errno == ENOENT) { pa_log_info(__FILE__": starting with empty ruleset."); @@ -127,6 +128,8 @@ static int load_rules(struct userdata *u) { goto finish; } + pa_lock_fd(fileno(f), 1); + while (!feof(f)) { struct rule *rule; pa_cvolume v; @@ -175,8 +178,10 @@ static int load_rules(struct userdata *u) { ret = 0; finish: - if (f) + if (f) { + pa_lock_fd(fileno(f), 0); fclose(f); + } return ret; } @@ -196,6 +201,8 @@ static int save_rules(struct userdata *u) { goto finish; } + pa_lock_fd(fileno(f), 1); + while ((rule = pa_hashmap_iterate(u->hashmap, &state, NULL))) { unsigned i; @@ -210,8 +217,10 @@ static int save_rules(struct userdata *u) { ret = 0; finish: - if (f) + if (f) { + pa_lock_fd(fileno(f), 0); fclose(f); + } return ret; } From 1cfb01ab0eff7b152125e3facdf6c65f98e2707b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 15:21:34 +0000 Subject: [PATCH 0811/1514] add proper locking when accessing the file match.table git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@906 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-match.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/module-match.c b/src/modules/module-match.c index f6316b93a..9e3edb702 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "module-match-symdef.h" @@ -88,6 +89,8 @@ static int load_rules(struct userdata *u, const char *filename) { goto finish; } + pa_lock_fd(fileno(f), 1); + while (!feof(f)) { char *d, *v; pa_volume_t volume; @@ -146,8 +149,10 @@ static int load_rules(struct userdata *u, const char *filename) { ret = 0; finish: - if (f) + if (f) { + pa_lock_fd(fileno(f), 0); fclose(f); + } if (fn) pa_xfree(fn); From cdd3588f3a0fc9efeff7ce85215304bf33e2504e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 15:38:58 +0000 Subject: [PATCH 0812/1514] more sensible default.pa file git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@907 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/default.pa.in | 49 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index 3aaeeaf05..cba0172fc 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -18,17 +18,18 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -# Load audio drivers statically - +### Load audio drivers statically #load-module module-alsa-sink -# load-module module-alsa-source device=plughw:1,0 -load-module module-oss device="/dev/dsp" sink_name=output source_name=input +#load-module module-alsa-source device=plughw:1,0 +#load-module module-oss device="/dev/dsp" sink_name=output source_name=input #load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -load-module module-null-sink +#load-module module-null-sink #load-module module-pipe-sink -# Load audio drivers automatically on access +### Automatically load driver modules depending on the hardware available +load-module module-detect +### Load audio drivers automatically on access #add-autoload-sink output module-oss device="/dev/dsp" sink_name=output source_name=input #add-autoload-source input module-oss device="/dev/dsp" sink_name=output source_name=input #add-autoload-sink output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input @@ -36,31 +37,35 @@ load-module module-null-sink #add-autoload-sink output module-alsa-sink sink_name=output #add-autoload-source input module-alsa-source source_name=input -# Load several protocols +### Load several protocols load-module module-esound-protocol-unix #load-module module-esound-protocol-tcp load-module module-native-protocol-unix -#load-module module-simple-protocol-tcp -#load-module module-cli-protocol-unix +#load-module module-native-protocol-tcp -# Load the CLI module -load-module module-cli +### Load the RTP reciever module +#load-module module-rtp-recv -# Make some devices default -set-default-sink output -set-default-source input +### Load the RTP sender module +#load-module module-null-sink sink_name=rtp +#load-module module-rtp-send source=rtp_monitor + +### Automatically restore the volume of playback streams +load-module module-volume-restore + +### Make some devices default +#set-default-sink output +#set-default-source input .nofail -# Load something to the sample cache -load-sample x11-bell /usr/share/sounds/KDE_Notify.wav -load-sample-dir-lazy /usr/share/sounds/*.wav +### Load something to the sample cache +load-sample x11-bell /usr/share/sounds/gtk-events/activate.wav +#load-sample-dir-lazy /usr/share/sounds/*.wav -# Load X11 bell module -load-module module-x11-bell sample=x11-bell sink=output +### Load X11 bell module +load-module module-x11-bell sample=x11-bell -# Publish connection data in the X11 root window +### Publish connection data in the X11 root window load-module module-x11-publish -#load-module module-pipe-source -#load-module module-pipe-sink From d9cc2cfcb97c1b0449bcbfb6ab0301a58d77bd55 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 16:34:18 +0000 Subject: [PATCH 0813/1514] Move xmalloc to the public side (libpolyp). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@908 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 14 +++++++------- src/daemon/cmdline.c | 3 ++- src/daemon/daemon-conf.c | 3 ++- src/daemon/main.c | 2 +- src/modules/alsa-util.c | 3 ++- src/modules/howl-wrap.c | 3 ++- src/modules/module-alsa-sink.c | 3 ++- src/modules/module-alsa-source.c | 3 ++- src/modules/module-combine.c | 3 ++- src/modules/module-detect.c | 3 ++- src/modules/module-esound-sink.c | 3 ++- src/modules/module-jack-sink.c | 3 ++- src/modules/module-jack-source.c | 3 ++- src/modules/module-lirc.c | 3 ++- src/modules/module-match.c | 3 ++- src/modules/module-mmkbd-evdev.c | 3 ++- src/modules/module-null-sink.c | 3 ++- src/modules/module-oss-mmap.c | 3 ++- src/modules/module-oss.c | 3 ++- src/modules/module-pipe-sink.c | 3 ++- src/modules/module-pipe-source.c | 3 ++- src/modules/module-protocol-stub.c | 3 ++- src/modules/module-sine.c | 3 ++- src/modules/module-solaris.c | 2 +- src/modules/module-tunnel.c | 2 +- src/modules/module-volume-restore.c | 3 ++- src/modules/module-waveout.c | 3 ++- src/modules/module-x11-bell.c | 3 ++- src/modules/module-x11-publish.c | 3 ++- src/modules/module-zeroconf-publish.c | 3 ++- src/modules/rtp/module-rtp-recv.c | 3 ++- src/modules/rtp/module-rtp-send.c | 3 ++- src/modules/rtp/sap.c | 3 ++- src/modules/rtp/sdp.c | 3 ++- src/polyp/browser.c | 3 ++- src/polyp/channelmap.c | 4 +++- src/polyp/client-conf-x11.c | 3 ++- src/polyp/client-conf.c | 3 ++- src/polyp/context.c | 2 +- src/polyp/glib-mainloop.c | 3 ++- src/polyp/glib12-mainloop.c | 3 ++- src/polyp/mainloop-api.c | 3 ++- src/polyp/mainloop-signal.c | 3 ++- src/polyp/mainloop.c | 3 ++- src/polyp/operation.c | 2 +- src/polyp/simple.c | 2 +- src/polyp/stream.c | 3 ++- src/polyp/thread-mainloop.c | 3 ++- src/{polypcore => polyp}/xmalloc.c | 0 src/{polypcore => polyp}/xmalloc.h | 0 src/polypcore/authkey-prop.c | 3 ++- src/polypcore/autoload.c | 3 ++- src/polypcore/cli-command.c | 3 ++- src/polypcore/cli-text.c | 3 ++- src/polypcore/cli.c | 3 ++- src/polypcore/client.c | 3 ++- src/polypcore/conf-parser.c | 3 ++- src/polypcore/core-scache.c | 3 ++- src/polypcore/core-subscribe.c | 3 ++- src/polypcore/core.c | 3 ++- src/polypcore/dynarray.c | 2 +- src/polypcore/hashmap.c | 3 ++- src/polypcore/idxset.c | 2 +- src/polypcore/iochannel.c | 3 ++- src/polypcore/ioline.c | 3 ++- src/polypcore/log.c | 3 ++- src/polypcore/mcalign.c | 2 +- src/polypcore/memblock.c | 2 +- src/polypcore/memblockq.c | 3 ++- src/polypcore/memchunk.c | 2 +- src/polypcore/modargs.c | 3 ++- src/polypcore/modinfo.c | 3 ++- src/polypcore/module.c | 3 ++- src/polypcore/namereg.c | 3 ++- src/polypcore/packet.c | 2 +- src/polypcore/parseaddr.c | 3 ++- src/polypcore/pdispatch.c | 3 ++- src/polypcore/pid.c | 3 ++- src/polypcore/play-memchunk.c | 3 ++- src/polypcore/props.c | 3 ++- src/polypcore/protocol-cli.c | 3 ++- src/polypcore/protocol-esound.c | 3 ++- src/polypcore/protocol-http.c | 3 ++- src/polypcore/protocol-native.c | 2 +- src/polypcore/protocol-simple.c | 3 ++- src/polypcore/pstream.c | 3 ++- src/polypcore/queue.c | 2 +- src/polypcore/resampler.c | 3 ++- src/polypcore/sink-input.c | 3 ++- src/polypcore/sink.c | 2 +- src/polypcore/socket-client.c | 3 ++- src/polypcore/socket-server.c | 3 ++- src/polypcore/socket-util.c | 3 ++- src/polypcore/sound-file-stream.c | 3 ++- src/polypcore/source-output.c | 3 ++- src/polypcore/source.c | 3 ++- src/polypcore/strbuf.c | 2 +- src/polypcore/strlist.c | 3 ++- src/polypcore/tagstruct.c | 2 +- src/polypcore/tokenizer.c | 3 ++- src/polypcore/utf8.c | 3 ++- src/polypcore/util.c | 3 ++- src/polypcore/x11wrap.c | 3 ++- src/tests/strlist-test.c | 2 +- src/tests/utf8-test.c | 2 +- 105 files changed, 193 insertions(+), 109 deletions(-) rename src/{polypcore => polyp}/xmalloc.c (100%) rename src/{polypcore => polyp}/xmalloc.h (100%) diff --git a/src/Makefile.am b/src/Makefile.am index bd48a0fb1..afbdedee1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -273,10 +273,10 @@ mainloop_test_glib12_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) memblockq_test_SOURCES = \ tests/memblockq-test.c \ + polyp/xmalloc.c \ polypcore/memblockq.c \ polypcore/log.c \ polypcore/memblock.c \ - polypcore/xmalloc.c \ polypcore/util.c \ polypcore/mcalign.c \ polypcore/memchunk.c @@ -313,7 +313,8 @@ polypinclude_HEADERS = \ polyp/subscribe.h \ polyp/version.h \ polyp/sample.h \ - polyp/volume.h + polyp/volume.h \ + polyp/xmalloc.h if HAVE_HOWL polypinclude_HEADERS += \ @@ -360,6 +361,7 @@ libpolyp_la_SOURCES = \ polyp/mainloop.c polyp/mainloop.h \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ polyp/thread-mainloop.c polyp/thread-mainloop.h \ + polyp/xmalloc.c polyp/xmalloc.h \ polypcore/pipe.c polypcore/pipe.h \ polypcore/poll.c polypcore/poll.h @@ -392,7 +394,6 @@ libpolyp_la_SOURCES += \ polypcore/tagstruct.c polypcore/tagstruct.h \ polypcore/util.c polypcore/util.h \ polypcore/winsock.h \ - polypcore/xmalloc.c polypcore/xmalloc.h \ polypcore/llist.h if OS_IS_WIN32 @@ -485,8 +486,7 @@ polypcoreinclude_HEADERS = \ polypcore/strbuf.h \ polypcore/tokenizer.h \ polypcore/util.h \ - polypcore/utf8.h \ - polypcore/xmalloc.h + polypcore/utf8.h lib_LTLIBRARIES += libpolypcore.la @@ -497,7 +497,8 @@ libpolypcore_la_SOURCES = \ polyp/mainloop-api.c polyp/mainloop-api.h \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ polyp/sample.c polyp/sample.h \ - polyp/volume.c polyp/volume.h + polyp/volume.c polyp/volume.h \ + polyp/xmalloc.c polyp/xmalloc.h # Pure core stuff (some are shared in libpolyp though). libpolypcore_la_SOURCES += \ @@ -546,7 +547,6 @@ libpolypcore_la_SOURCES += \ polypcore/tokenizer.c polypcore/tokenizer.h \ polypcore/util.c polypcore/util.h \ polypcore/winsock.h \ - polypcore/xmalloc.c polypcore/xmalloc.h \ polypcore/utf8.c polypcore/utf8.h if OS_IS_WIN32 diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index a6b95a812..1ed16a692 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -30,9 +30,10 @@ #include #include +#include + #include #include -#include #include "cmdline.h" diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index f41bb4b19..f82d3d24f 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -29,8 +29,9 @@ #include #include +#include + #include -#include #include #include #include diff --git a/src/daemon/main.c b/src/daemon/main.c index e14837a99..a7144eba0 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -51,6 +51,7 @@ #include #include +#include #include #include @@ -59,7 +60,6 @@ #include #include #include -#include #include #include #include diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 503b8efbc..122f4419b 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -27,7 +27,8 @@ #include #include -#include +#include + #include #include "alsa-util.h" diff --git a/src/modules/howl-wrap.c b/src/modules/howl-wrap.c index f4605fb2d..467ab9e24 100644 --- a/src/modules/howl-wrap.c +++ b/src/modules/howl-wrap.c @@ -21,8 +21,9 @@ #include +#include + #include -#include #include #include "howl-wrap.h" diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 47065659c..94de771c1 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -34,6 +34,8 @@ #include +#include + #include #include #include @@ -41,7 +43,6 @@ #include #include #include -#include #include #include "alsa-util.h" diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index d46f8e427..b9d1ff87c 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -34,6 +34,8 @@ #include +#include + #include #include #include @@ -41,7 +43,6 @@ #include #include #include -#include #include #include "alsa-util.h" diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 369778a6b..b31fe56ea 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -26,6 +26,8 @@ #include #include +#include + #include #include #include @@ -33,7 +35,6 @@ #include #include #include -#include #include #include diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 9cc13e817..ea14e68fb 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -33,9 +33,10 @@ #include #include +#include + #include #include -#include #include #include diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 1cc75502d..1d61e01b1 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -33,12 +33,13 @@ #include #include +#include + #include #include #include #include #include -#include #include #include #include diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 324a2cb3e..1aa734950 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -36,12 +36,13 @@ #include +#include + #include #include #include #include #include -#include #include #include diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 94cabbea2..29c46d853 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -36,12 +36,13 @@ #include +#include + #include #include #include #include #include -#include #include #include diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index 3bb0dc749..918177a30 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -30,11 +30,12 @@ #include #include +#include + #include #include #include #include -#include #include #include "module-lirc-symdef.h" diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 9e3edb702..1692b5d82 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -32,12 +32,13 @@ #include #include +#include + #include #include #include #include #include -#include #include #include diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index 8ea568110..654fbaa4b 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -33,11 +33,12 @@ #include +#include + #include #include #include #include -#include #include #include diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 5cdfeab8c..2cc490630 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -33,12 +33,13 @@ #include #include +#include + #include #include #include #include #include -#include #include #include "module-null-sink-symdef.h" diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index ddf33532f..82e7d66dd 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -36,6 +36,8 @@ #include #include +#include + #include #include #include @@ -43,7 +45,6 @@ #include #include #include -#include #include #include "oss-util.h" diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index f6d19544b..46d100f15 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -35,6 +35,8 @@ #include #include +#include + #include #include #include @@ -42,7 +44,6 @@ #include #include #include -#include #include #include "oss-util.h" diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 0fb73cd88..b59808fcb 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -33,12 +33,13 @@ #include #include +#include + #include #include #include #include #include -#include #include #include "module-pipe-sink-symdef.h" diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index d999754af..4f3f9a6c9 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -33,12 +33,13 @@ #include #include +#include + #include #include #include #include #include -#include #include #include "module-pipe-source-symdef.h" diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index d5b5f63b1..79a59cd5f 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -42,6 +42,8 @@ #include "../polypcore/winsock.h" +#include + #include #include #include @@ -49,7 +51,6 @@ #include #include #include -#include #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index 3267d49bb..15b6c8a94 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -27,10 +27,11 @@ #include #include +#include + #include #include #include -#include #include #include diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 3e7c2fb46..d82e33620 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -49,7 +50,6 @@ #include #include #include -#include #include #include "module-solaris-symdef.h" diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 2e04b1208..a2a1e33de 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -32,13 +32,13 @@ #include #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index f9e7d0132..ea40d8622 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -32,12 +32,13 @@ #include #include +#include + #include #include #include #include #include -#include #include #include #include diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 2d9c42eba..3d1f1b01a 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -29,6 +29,8 @@ #include +#include + #include #include #include @@ -36,7 +38,6 @@ #include #include #include -#include #include "module-waveout-symdef.h" diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index e4d4020e3..2b891bc12 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -31,11 +31,12 @@ #include #include +#include + #include #include #include #include -#include #include #include #include diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index 7408b930f..e974487d8 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -32,11 +32,12 @@ #include #include +#include + #include #include #include #include -#include #include #include #include diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index f8607befa..e5dce7559 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -29,7 +29,8 @@ #include #include -#include +#include + #include #include #include diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 925a1210c..89aa89830 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -31,6 +31,8 @@ #include #include +#include + #include #include #include @@ -38,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index d0def859e..8fc1d7fee 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -32,6 +32,8 @@ #include #include +#include + #include #include #include @@ -39,7 +41,6 @@ #include #include #include -#include #include #include diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index d2bca04de..e579b5c57 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -38,9 +38,10 @@ #include #endif +#include + #include #include -#include #include "sap.h" #include "sdp.h" diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index 84bcd83b0..3cece7110 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -31,9 +31,10 @@ #include #include +#include + #include #include -#include #include "sdp.h" #include "rtp.h" diff --git a/src/polyp/browser.c b/src/polyp/browser.c index cef680e40..5442fd4c0 100644 --- a/src/polyp/browser.c +++ b/src/polyp/browser.c @@ -22,7 +22,8 @@ #include #include -#include +#include + #include #include diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index 7266a0a0e..ddd7b3ce7 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -28,8 +28,10 @@ #include #include +#include + #include -#include + #include "channelmap.h" const char *const table[] = { diff --git a/src/polyp/client-conf-x11.c b/src/polyp/client-conf-x11.c index 7187d86b2..17ee2d6ae 100644 --- a/src/polyp/client-conf-x11.c +++ b/src/polyp/client-conf-x11.c @@ -29,9 +29,10 @@ #include #include +#include + #include #include -#include #include #include "client-conf-x11.h" diff --git a/src/polyp/client-conf.c b/src/polyp/client-conf.c index d3ad0767e..567d2ae4c 100644 --- a/src/polyp/client-conf.c +++ b/src/polyp/client-conf.c @@ -29,7 +29,8 @@ #include #include -#include +#include + #include #include #include diff --git a/src/polyp/context.c b/src/polyp/context.c index d5cf90f8e..3c46e2e87 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -48,6 +48,7 @@ #include "../polypcore/winsock.h" #include +#include #include #include @@ -56,7 +57,6 @@ #include #include #include -#include #include #include diff --git a/src/polyp/glib-mainloop.c b/src/polyp/glib-mainloop.c index 3937a1a9f..bc5df3a9b 100644 --- a/src/polyp/glib-mainloop.c +++ b/src/polyp/glib-mainloop.c @@ -25,8 +25,9 @@ #include +#include + #include -#include #include #include "glib.h" diff --git a/src/polyp/glib12-mainloop.c b/src/polyp/glib12-mainloop.c index 5ad23adba..7af21210f 100644 --- a/src/polyp/glib12-mainloop.c +++ b/src/polyp/glib12-mainloop.c @@ -25,8 +25,9 @@ #include +#include + #include -#include #include #include "glib-mainloop.h" diff --git a/src/polyp/mainloop-api.c b/src/polyp/mainloop-api.c index 71f55c05d..f29598dc4 100644 --- a/src/polyp/mainloop-api.c +++ b/src/polyp/mainloop-api.c @@ -26,8 +26,9 @@ #include #include +#include + #include -#include #include "mainloop-api.h" diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index 4ffa00ba3..a225f78be 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -36,8 +36,9 @@ #include #endif +#include + #include -#include #include #include diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 589fe77ef..82e789c54 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -44,9 +44,10 @@ #include "../polypcore/pipe.h" #endif +#include + #include #include -#include #include #include "mainloop.h" diff --git a/src/polyp/operation.c b/src/polyp/operation.c index 1c0cb99f2..5af9ec0b8 100644 --- a/src/polyp/operation.c +++ b/src/polyp/operation.c @@ -25,7 +25,7 @@ #include -#include +#include #include "internal.h" #include "operation.h" diff --git a/src/polyp/simple.c b/src/polyp/simple.c index 1f25869b3..b56406c91 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -30,9 +30,9 @@ #include #include +#include #include -#include #include #include "simple.h" diff --git a/src/polyp/stream.c b/src/polyp/stream.c index b2711ce08..f188e7885 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -29,7 +29,8 @@ #include #include -#include +#include + #include #include #include diff --git a/src/polyp/thread-mainloop.c b/src/polyp/thread-mainloop.c index 20639e9e7..d036a2327 100644 --- a/src/polyp/thread-mainloop.c +++ b/src/polyp/thread-mainloop.c @@ -41,8 +41,9 @@ #include #endif +#include + #include -#include #include #include "mainloop.h" diff --git a/src/polypcore/xmalloc.c b/src/polyp/xmalloc.c similarity index 100% rename from src/polypcore/xmalloc.c rename to src/polyp/xmalloc.c diff --git a/src/polypcore/xmalloc.h b/src/polyp/xmalloc.h similarity index 100% rename from src/polypcore/xmalloc.h rename to src/polyp/xmalloc.h diff --git a/src/polypcore/authkey-prop.c b/src/polypcore/authkey-prop.c index 3faf0ef1f..6172d4320 100644 --- a/src/polypcore/authkey-prop.c +++ b/src/polypcore/authkey-prop.c @@ -22,7 +22,8 @@ #include #include -#include +#include + #include #include diff --git a/src/polypcore/autoload.c b/src/polypcore/autoload.c index 8d2dca30f..386de2192 100644 --- a/src/polypcore/autoload.c +++ b/src/polypcore/autoload.c @@ -27,8 +27,9 @@ #include #include +#include + #include -#include #include #include #include diff --git a/src/polypcore/cli-command.c b/src/polypcore/cli-command.c index 180c61e9a..5556bcb34 100644 --- a/src/polypcore/cli-command.c +++ b/src/polypcore/cli-command.c @@ -29,6 +29,8 @@ #include #include +#include + #include #include #include @@ -44,7 +46,6 @@ #include #include #include -#include #include #include #include diff --git a/src/polypcore/cli-text.c b/src/polypcore/cli-text.c index 74de57816..09ccaa00d 100644 --- a/src/polypcore/cli-text.c +++ b/src/polypcore/cli-text.c @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -37,7 +39,6 @@ #include #include #include -#include #include "cli-text.h" diff --git a/src/polypcore/cli.c b/src/polypcore/cli.c index 583f6845a..683d29ec9 100644 --- a/src/polypcore/cli.c +++ b/src/polypcore/cli.c @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -40,7 +42,6 @@ #include #include #include -#include #include #include "cli.h" diff --git a/src/polypcore/client.c b/src/polypcore/client.c index be970470c..b5ed2fd0b 100644 --- a/src/polypcore/client.c +++ b/src/polypcore/client.c @@ -28,7 +28,8 @@ #include #include -#include +#include + #include #include diff --git a/src/polypcore/conf-parser.c b/src/polypcore/conf-parser.c index 26fc33b56..64e66c2e1 100644 --- a/src/polypcore/conf-parser.c +++ b/src/polypcore/conf-parser.c @@ -28,9 +28,10 @@ #include #include +#include + #include #include -#include #include "conf-parser.h" diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 3bba38ed3..8080fcd69 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -44,10 +44,11 @@ #include #include #include +#include + #include #include #include -#include #include #include #include diff --git a/src/polypcore/core-subscribe.c b/src/polypcore/core-subscribe.c index fa6c0e509..52babb7a3 100644 --- a/src/polypcore/core-subscribe.c +++ b/src/polypcore/core-subscribe.c @@ -26,8 +26,9 @@ #include #include +#include + #include -#include #include #include "core-subscribe.h" diff --git a/src/polypcore/core.c b/src/polypcore/core.c index 0093aebd7..ff8ec0810 100644 --- a/src/polypcore/core.c +++ b/src/polypcore/core.c @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -35,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/src/polypcore/dynarray.c b/src/polypcore/dynarray.c index 1aff7f511..234c2c03f 100644 --- a/src/polypcore/dynarray.c +++ b/src/polypcore/dynarray.c @@ -27,7 +27,7 @@ #include #include -#include +#include #include "dynarray.h" diff --git a/src/polypcore/hashmap.c b/src/polypcore/hashmap.c index 8861fd3df..adc322f04 100644 --- a/src/polypcore/hashmap.c +++ b/src/polypcore/hashmap.c @@ -27,8 +27,9 @@ #include #include +#include + #include -#include #include #include "hashmap.h" diff --git a/src/polypcore/idxset.c b/src/polypcore/idxset.c index f970ae5e0..bde5c2791 100644 --- a/src/polypcore/idxset.c +++ b/src/polypcore/idxset.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include "idxset.h" diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index aba0399c2..a1ad5dea2 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -38,9 +38,10 @@ #include "winsock.h" +#include + #include #include -#include #include #include "iochannel.h" diff --git a/src/polypcore/ioline.c b/src/polypcore/ioline.c index eb8fdda53..9bb610fe9 100644 --- a/src/polypcore/ioline.c +++ b/src/polypcore/ioline.c @@ -29,7 +29,8 @@ #include #include -#include +#include + #include #include "ioline.h" diff --git a/src/polypcore/log.c b/src/polypcore/log.c index 9c9ed2fd9..9908d168c 100644 --- a/src/polypcore/log.c +++ b/src/polypcore/log.c @@ -33,7 +33,8 @@ #include #endif -#include +#include + #include #include "log.h" diff --git a/src/polypcore/mcalign.c b/src/polypcore/mcalign.c index f90fd7e8c..d9267f99d 100644 --- a/src/polypcore/mcalign.c +++ b/src/polypcore/mcalign.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include "mcalign.h" diff --git a/src/polypcore/memblock.c b/src/polypcore/memblock.c index 04e8436fc..a0e5135b3 100644 --- a/src/polypcore/memblock.c +++ b/src/polypcore/memblock.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include "memblock.h" diff --git a/src/polypcore/memblockq.c b/src/polypcore/memblockq.c index 90e1d9ebe..caacd96f0 100644 --- a/src/polypcore/memblockq.c +++ b/src/polypcore/memblockq.c @@ -30,7 +30,8 @@ #include #include -#include +#include + #include #include diff --git a/src/polypcore/memchunk.c b/src/polypcore/memchunk.c index d6856ab83..918b3f0f0 100644 --- a/src/polypcore/memchunk.c +++ b/src/polypcore/memchunk.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include "memchunk.h" diff --git a/src/polypcore/modargs.c b/src/polypcore/modargs.c index 713326bfc..63cc779dd 100644 --- a/src/polypcore/modargs.c +++ b/src/polypcore/modargs.c @@ -28,13 +28,14 @@ #include #include +#include + #include #include #include #include #include #include -#include #include #include "modargs.h" diff --git a/src/polypcore/modinfo.c b/src/polypcore/modinfo.c index 39186ceb0..241076c66 100644 --- a/src/polypcore/modinfo.c +++ b/src/polypcore/modinfo.c @@ -26,7 +26,8 @@ #include #include -#include +#include + #include #include diff --git a/src/polypcore/module.c b/src/polypcore/module.c index 5412f3973..fe177a5bf 100644 --- a/src/polypcore/module.c +++ b/src/polypcore/module.c @@ -30,7 +30,8 @@ #include #include -#include +#include + #include #include #include diff --git a/src/polypcore/namereg.c b/src/polypcore/namereg.c index 9229a0f99..cf11f5a4d 100644 --- a/src/polypcore/namereg.c +++ b/src/polypcore/namereg.c @@ -29,10 +29,11 @@ #include #include +#include + #include #include #include -#include #include #include diff --git a/src/polypcore/packet.c b/src/polypcore/packet.c index 31ddad95b..646b59e0e 100644 --- a/src/polypcore/packet.c +++ b/src/polypcore/packet.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include "packet.h" diff --git a/src/polypcore/parseaddr.c b/src/polypcore/parseaddr.c index c2b25c896..7e518a5d4 100644 --- a/src/polypcore/parseaddr.c +++ b/src/polypcore/parseaddr.c @@ -27,7 +27,8 @@ #include #include -#include +#include + #include #include "parseaddr.h" diff --git a/src/polypcore/pdispatch.c b/src/polypcore/pdispatch.c index b087f1a50..21e3644e0 100644 --- a/src/polypcore/pdispatch.c +++ b/src/polypcore/pdispatch.c @@ -27,8 +27,9 @@ #include #include +#include + #include -#include #include #include #include diff --git a/src/polypcore/pid.c b/src/polypcore/pid.c index b258290b5..53b8ad0a2 100644 --- a/src/polypcore/pid.c +++ b/src/polypcore/pid.c @@ -39,9 +39,10 @@ #include #endif +#include + #include #include -#include #include "pid.h" diff --git a/src/polypcore/play-memchunk.c b/src/polypcore/play-memchunk.c index 37ebdcf11..982cedc7b 100644 --- a/src/polypcore/play-memchunk.c +++ b/src/polypcore/play-memchunk.c @@ -28,8 +28,9 @@ #include #include +#include + #include -#include #include #include "play-memchunk.h" diff --git a/src/polypcore/props.c b/src/polypcore/props.c index 96cdc4f2d..1db44ee75 100644 --- a/src/polypcore/props.c +++ b/src/polypcore/props.c @@ -21,7 +21,8 @@ #include -#include +#include + #include #include "props.h" diff --git a/src/polypcore/protocol-cli.c b/src/polypcore/protocol-cli.c index 7dd489f7e..076411cf3 100644 --- a/src/polypcore/protocol-cli.c +++ b/src/polypcore/protocol-cli.c @@ -26,8 +26,9 @@ #include #include +#include + #include -#include #include #include "protocol-cli.h" diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index fcbeba6d1..86a8c9e3c 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -31,6 +31,8 @@ #include #include +#include + #include #include #include @@ -42,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/src/polypcore/protocol-http.c b/src/polypcore/protocol-http.c index 85ddebee4..68864237e 100644 --- a/src/polypcore/protocol-http.c +++ b/src/polypcore/protocol-http.c @@ -28,8 +28,9 @@ #include #include +#include + #include -#include #include #include #include diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 3b9041342..b0ad59551 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -43,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/src/polypcore/protocol-simple.c b/src/polypcore/protocol-simple.c index 1e3b169c4..caffd5c9f 100644 --- a/src/polypcore/protocol-simple.c +++ b/src/polypcore/protocol-simple.c @@ -30,12 +30,13 @@ #include #include +#include + #include #include #include #include #include -#include #include #include "protocol-simple.h" diff --git a/src/polypcore/pstream.c b/src/polypcore/pstream.c index 09bd1e27e..074cab916 100644 --- a/src/polypcore/pstream.c +++ b/src/polypcore/pstream.c @@ -34,8 +34,9 @@ #include "winsock.h" +#include + #include -#include #include #include diff --git a/src/polypcore/queue.c b/src/polypcore/queue.c index 77ca1ed39..01f957d9b 100644 --- a/src/polypcore/queue.c +++ b/src/polypcore/queue.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include "queue.h" diff --git a/src/polypcore/resampler.c b/src/polypcore/resampler.c index b2a8874b6..33e8c2959 100644 --- a/src/polypcore/resampler.c +++ b/src/polypcore/resampler.c @@ -30,8 +30,9 @@ #include #include +#include + #include -#include #include #include "resampler.h" diff --git a/src/polypcore/sink-input.c b/src/polypcore/sink-input.c index c10263903..5c0caa211 100644 --- a/src/polypcore/sink-input.c +++ b/src/polypcore/sink-input.c @@ -28,8 +28,9 @@ #include #include +#include + #include -#include #include #include #include diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index b59f1eaa6..a873c00a3 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -29,12 +29,12 @@ #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index 734b9dde5..a61cf582f 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -54,9 +54,10 @@ #include "winsock.h" +#include + #include #include -#include #include #include diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index f7e0b6477..959173f26 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -62,8 +62,9 @@ #include "winsock.h" +#include + #include -#include #include #include diff --git a/src/polypcore/socket-util.c b/src/polypcore/socket-util.c index 915c7f224..0961db210 100644 --- a/src/polypcore/socket-util.c +++ b/src/polypcore/socket-util.c @@ -59,8 +59,9 @@ #include "winsock.h" +#include + #include -#include #include #include "socket-util.h" diff --git a/src/polypcore/sound-file-stream.c b/src/polypcore/sound-file-stream.c index fdacea54b..68fd8a89c 100644 --- a/src/polypcore/sound-file-stream.c +++ b/src/polypcore/sound-file-stream.c @@ -30,8 +30,9 @@ #include +#include + #include -#include #include #include "sound-file-stream.h" diff --git a/src/polypcore/source-output.c b/src/polypcore/source-output.c index b31130718..c8db870b5 100644 --- a/src/polypcore/source-output.c +++ b/src/polypcore/source-output.c @@ -28,7 +28,8 @@ #include #include -#include +#include + #include #include #include diff --git a/src/polypcore/source.c b/src/polypcore/source.c index fca281a79..4d96622bf 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -28,9 +28,10 @@ #include #include +#include + #include #include -#include #include #include #include diff --git a/src/polypcore/strbuf.c b/src/polypcore/strbuf.c index dcad5e78d..d1517a11e 100644 --- a/src/polypcore/strbuf.c +++ b/src/polypcore/strbuf.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include "strbuf.h" diff --git a/src/polypcore/strlist.c b/src/polypcore/strlist.c index e165aefdd..4d70e9e99 100644 --- a/src/polypcore/strlist.c +++ b/src/polypcore/strlist.c @@ -26,7 +26,8 @@ #include #include -#include +#include + #include #include diff --git a/src/polypcore/tagstruct.c b/src/polypcore/tagstruct.c index 86b8368a3..27582cae1 100644 --- a/src/polypcore/tagstruct.c +++ b/src/polypcore/tagstruct.c @@ -36,7 +36,7 @@ #include "winsock.h" -#include +#include #include "tagstruct.h" diff --git a/src/polypcore/tokenizer.c b/src/polypcore/tokenizer.c index 556a190a0..667643fe6 100644 --- a/src/polypcore/tokenizer.c +++ b/src/polypcore/tokenizer.c @@ -27,8 +27,9 @@ #include #include +#include + #include -#include #include #include "tokenizer.h" diff --git a/src/polypcore/utf8.c b/src/polypcore/utf8.c index bb8621e23..01fbfccd1 100644 --- a/src/polypcore/utf8.c +++ b/src/polypcore/utf8.c @@ -33,8 +33,9 @@ #include #include +#include + #include "utf8.h" -#include "xmalloc.h" #define FILTER_CHAR '_' diff --git a/src/polypcore/util.c b/src/polypcore/util.c index 6f7f88198..9783b7461 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/util.c @@ -70,7 +70,8 @@ #include "winsock.h" -#include +#include + #include #include "util.h" diff --git a/src/polypcore/x11wrap.c b/src/polypcore/x11wrap.c index c1ca83ca2..41a407645 100644 --- a/src/polypcore/x11wrap.c +++ b/src/polypcore/x11wrap.c @@ -22,8 +22,9 @@ #include #include +#include + #include -#include #include #include diff --git a/src/tests/strlist-test.c b/src/tests/strlist-test.c index 145431126..415c94e6a 100644 --- a/src/tests/strlist-test.c +++ b/src/tests/strlist-test.c @@ -1,7 +1,7 @@ #include +#include #include -#include #include int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) { diff --git a/src/tests/utf8-test.c b/src/tests/utf8-test.c index c8b2fabb7..57f445c7e 100644 --- a/src/tests/utf8-test.c +++ b/src/tests/utf8-test.c @@ -3,8 +3,8 @@ #include #include +#include #include -#include int main(int argc, char *argv[]) { char *c; From 7ca25e58e99abb3d640b6012d7cbfc9bc9087849 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 17:30:49 +0000 Subject: [PATCH 0814/1514] Move utf8 to the public part (libpolyp). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@909 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 9 +++++---- src/{polypcore => polyp}/utf8.c | 3 +-- src/{polypcore => polyp}/utf8.h | 0 src/polypcore/protocol-esound.c | 2 +- src/polypcore/protocol-native.c | 2 +- src/polypcore/sink-input.c | 2 +- src/polypcore/sink.c | 2 +- src/polypcore/source-output.c | 2 +- src/polypcore/source.c | 2 +- src/tests/utf8-test.c | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) rename src/{polypcore => polyp}/utf8.c (99%) rename src/{polypcore => polyp}/utf8.h (100%) diff --git a/src/Makefile.am b/src/Makefile.am index afbdedee1..72db5f80e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -313,6 +313,7 @@ polypinclude_HEADERS = \ polyp/subscribe.h \ polyp/version.h \ polyp/sample.h \ + polyp/utf8.h \ polyp/volume.h \ polyp/xmalloc.h @@ -358,6 +359,7 @@ libpolyp_la_SOURCES = \ polyp/subscribe.c polyp/subscribe.h \ polyp/sample.c polyp/sample.h \ polyp/volume.c polyp/volume.h \ + polyp/utf8.c polyp/utf8.h \ polyp/mainloop.c polyp/mainloop.h \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ polyp/thread-mainloop.c polyp/thread-mainloop.h \ @@ -485,8 +487,7 @@ polypcoreinclude_HEADERS = \ polypcore/source-output.h \ polypcore/strbuf.h \ polypcore/tokenizer.h \ - polypcore/util.h \ - polypcore/utf8.h + polypcore/util.h lib_LTLIBRARIES += libpolypcore.la @@ -498,6 +499,7 @@ libpolypcore_la_SOURCES = \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ polyp/sample.c polyp/sample.h \ polyp/volume.c polyp/volume.h \ + polyp/utf8.c polyp/utf8.h \ polyp/xmalloc.c polyp/xmalloc.h # Pure core stuff (some are shared in libpolyp though). @@ -546,8 +548,7 @@ libpolypcore_la_SOURCES += \ polypcore/strbuf.c polypcore/strbuf.h \ polypcore/tokenizer.c polypcore/tokenizer.h \ polypcore/util.c polypcore/util.h \ - polypcore/winsock.h \ - polypcore/utf8.c polypcore/utf8.h + polypcore/winsock.h if OS_IS_WIN32 libpolypcore_la_SOURCES += \ diff --git a/src/polypcore/utf8.c b/src/polyp/utf8.c similarity index 99% rename from src/polypcore/utf8.c rename to src/polyp/utf8.c index 01fbfccd1..bb8621e23 100644 --- a/src/polypcore/utf8.c +++ b/src/polyp/utf8.c @@ -33,9 +33,8 @@ #include #include -#include - #include "utf8.h" +#include "xmalloc.h" #define FILTER_CHAR '_' diff --git a/src/polypcore/utf8.h b/src/polyp/utf8.h similarity index 100% rename from src/polypcore/utf8.h rename to src/polyp/utf8.h diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 86a8c9e3c..8f53694e7 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -46,7 +47,6 @@ #include #include #include -#include #include "endianmacros.h" diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index b0ad59551..338db0020 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -53,7 +54,6 @@ #include #include #include -#include #include "protocol-native.h" diff --git a/src/polypcore/sink-input.c b/src/polypcore/sink-input.c index 5c0caa211..bd2a1dcd1 100644 --- a/src/polypcore/sink-input.c +++ b/src/polypcore/sink-input.c @@ -28,12 +28,12 @@ #include #include +#include #include #include #include #include -#include #include "sink-input.h" diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index a873c00a3..6931d396d 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -37,7 +38,6 @@ #include #include #include -#include #include "sink.h" diff --git a/src/polypcore/source-output.c b/src/polypcore/source-output.c index c8db870b5..8ac3a33d4 100644 --- a/src/polypcore/source-output.c +++ b/src/polypcore/source-output.c @@ -28,11 +28,11 @@ #include #include +#include #include #include #include -#include #include "source-output.h" diff --git a/src/polypcore/source.c b/src/polypcore/source.c index 4d96622bf..c53bf079f 100644 --- a/src/polypcore/source.c +++ b/src/polypcore/source.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -35,7 +36,6 @@ #include #include #include -#include #include "source.h" diff --git a/src/tests/utf8-test.c b/src/tests/utf8-test.c index 57f445c7e..2c21613e9 100644 --- a/src/tests/utf8-test.c +++ b/src/tests/utf8-test.c @@ -3,8 +3,8 @@ #include #include +#include #include -#include int main(int argc, char *argv[]) { char *c; From 5f6d8c9c8b0f113dee34d3f3c17464a9c696a49b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 18:51:37 +0000 Subject: [PATCH 0815/1514] fix svn tag git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@910 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/utf8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyp/utf8.c b/src/polyp/utf8.c index bb8621e23..300a54caf 100644 --- a/src/polyp/utf8.c +++ b/src/polyp/utf8.c @@ -1,4 +1,4 @@ -/* $Id */ +/* $Id$ */ /* This file is based on the GLIB utf8 validation functions. The * original license text follows. */ From ee35a063b2c10564d43a611fcf6ada398851b1d6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 18:52:34 +0000 Subject: [PATCH 0816/1514] add new channel map argument to pa_simple_new() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@911 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/simple.c | 4 +++- src/polyp/simple.h | 9 ++++++--- src/tests/pacat-simple.c | 2 +- src/tests/parec-simple.c | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/polyp/simple.c b/src/polyp/simple.c index b56406c91..84c46bf1c 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -140,6 +140,7 @@ pa_simple* pa_simple_new( const char *dev, const char *stream_name, const pa_sample_spec *ss, + const pa_channel_map *map, const pa_buffer_attr *attr, int *rerror) { @@ -150,6 +151,7 @@ pa_simple* pa_simple_new( CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL); CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL); CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL); + CHECK_VALIDITY_RETURN_ANY(rerror, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID, NULL) p = pa_xnew(pa_simple, 1); p->context = NULL; @@ -184,7 +186,7 @@ pa_simple* pa_simple_new( goto unlock_and_fail; } - if (!(p->stream = pa_stream_new(p->context, stream_name, ss, NULL))) { + if (!(p->stream = pa_stream_new(p->context, stream_name, ss, map))) { error = pa_context_errno(p->context); goto unlock_and_fail; } diff --git a/src/polyp/simple.h b/src/polyp/simple.h index 9066826ba..bf3cc330a 100644 --- a/src/polyp/simple.h +++ b/src/polyp/simple.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -57,6 +58,7 @@ * NULL, // Use the default device. * "Music", // Description of our stream. * &ss, // Our sample format. + * NULL, // Use default channel map * NULL, // Use default buffering attributes. * NULL, // Ignore error code. * ); @@ -112,11 +114,12 @@ typedef struct pa_simple pa_simple; pa_simple* pa_simple_new( const char *server, /**< Server name, or NULL for default */ const char *name, /**< A descriptive name for this client (application name, ...) */ - pa_stream_direction_t dir, /**< Open this stream for recording or playback? */ + pa_stream_direction_t dir, /**< Open this stream for recording or playback? */ const char *dev, /**< Sink (resp. source) name, or NULL for default */ const char *stream_name, /**< A descriptive name for this client (application name, song title, ...) */ - const pa_sample_spec *ss, /**< The sample type to use */ - const pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */ + const pa_sample_spec *ss, /**< The sample type to use */ + const pa_channel_map *map, /**< The channel map to use, or NULL for default */ + const pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */ int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */ ); diff --git a/src/tests/pacat-simple.c b/src/tests/pacat-simple.c index 6a75c7903..544c31e38 100644 --- a/src/tests/pacat-simple.c +++ b/src/tests/pacat-simple.c @@ -66,7 +66,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { } /* Create a new playback stream */ - if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, &error))) { + if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &error))) { fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); goto finish; } diff --git a/src/tests/parec-simple.c b/src/tests/parec-simple.c index fc2314acc..4463d5493 100644 --- a/src/tests/parec-simple.c +++ b/src/tests/parec-simple.c @@ -67,7 +67,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { int error; /* Create the recording stream */ - if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, &error))) { + if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) { fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); goto finish; } From 6e9f2d70937e9b8dc09a753e3d678fe11a5754ca Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 19:06:42 +0000 Subject: [PATCH 0817/1514] add utf8.h and xmalloc.h to doxygen docs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@912 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doxygen/doxygen.conf.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 471c21dcd..97040377c 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h ../src/polyp/thread-mainloop.h +INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h ../src/polyp/thread-mainloop.h ../src/polyp/xmalloc.h ../src/polyp/utf8.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp From 56d8e56431e988716ef5580f95ab4361b7a2ebe1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 19:07:30 +0000 Subject: [PATCH 0818/1514] * make pa_xfree() a real function * update doxygen docs for xmalloc.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@913 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/xmalloc.c | 6 ++++++ src/polyp/xmalloc.h | 23 +++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/polyp/xmalloc.c b/src/polyp/xmalloc.c index 4c8689a6c..1deeebd80 100644 --- a/src/polyp/xmalloc.c +++ b/src/polyp/xmalloc.c @@ -121,3 +121,9 @@ char *pa_xstrndup(const char *s, size_t l) { } } +void pa_xfree(void *p) { + if (!p) + return; + + free(p); +} diff --git a/src/polyp/xmalloc.h b/src/polyp/xmalloc.h index 2946011af..9d91d8dc4 100644 --- a/src/polyp/xmalloc.h +++ b/src/polyp/xmalloc.h @@ -27,14 +27,29 @@ #include #include -void* pa_xmalloc(size_t l); -void *pa_xmalloc0(size_t l); -void *pa_xrealloc(void *ptr, size_t size); -#define pa_xfree free +/** \file + * Memory allocation functions. + */ +/** Allocate the specified number of bytes, just like malloc() does. However, in case of OOM, terminate */ +void* pa_xmalloc(size_t l); + +/** Same as pa_xmalloc(), but initialize allocated memory to 0 */ +void *pa_xmalloc0(size_t l); + +/** The combination of pa_xmalloc() and realloc() */ +void *pa_xrealloc(void *ptr, size_t size); + +/** Free allocated memory */ +void pa_xfree(void *p); + +/** Duplicate the specified string, allocating memory with pa_xmalloc() */ char *pa_xstrdup(const char *s); + +/** Duplicate the specified string, but truncate after l characters */ char *pa_xstrndup(const char *s, size_t l); +/** Duplicate the specified memory block */ void* pa_xmemdup(const void *p, size_t l); /** Internal helper for pa_xnew() */ From 41badddbb9d47fbc82a8473c24bac6e8044642d5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 19:07:53 +0000 Subject: [PATCH 0819/1514] add doxygen docs for utf8.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@914 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/utf8.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/polyp/utf8.h b/src/polyp/utf8.h index 6d1e4a7df..e9a515330 100644 --- a/src/polyp/utf8.h +++ b/src/polyp/utf8.h @@ -22,7 +22,14 @@ USA. ***/ +/** \file + * UTF8 Validation functions + */ + +/** Test if the specified strings qualifies as valid UTF8. Return the string if so, otherwise NULL */ const char *pa_utf8_valid(const char *str); + +/** Filter all invalid UTF8 characters from the specified string, returning a new fully UTF8 valid string. Don't forget to free the returned string with pa_xfree() */ char *pa_utf8_filter(const char *str); #endif From 43813dcce8119d6d988db7eb47ba587e953a5f21 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 19:26:14 +0000 Subject: [PATCH 0820/1514] include more files in polypaudio.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@915 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/polypaudio.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/polyp/polypaudio.h b/src/polyp/polypaudio.h index 1830dea86..fe25fe300 100644 --- a/src/polyp/polypaudio.h +++ b/src/polyp/polypaudio.h @@ -35,13 +35,19 @@ #include #include #include +#include +#include +#include +#include +#include /** \file - * Include all polyplib header file at once. The following + * Include all polyplib header files at once. The following * files are included: \ref mainloop-api.h, \ref sample.h, \ref def.h, * \ref context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h, * \ref scache.h, \ref version.h, \ref error.h, \ref channelmap.h, - * \ref operation.h and \ref volume.h at once */ + * \ref operation.h,\ref volume.h, \ref xmalloc.h, \ref utf8.h, \ref + * thread-mainloop.h, \ref mainloop.h and \ref mainloop-signal.h at once */ /** \mainpage * From fbdb06351385eb210c50ba6a1fc2b8c14575513e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 19:26:54 +0000 Subject: [PATCH 0821/1514] replace memory allocation function calls with pa_xXXXX() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@916 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 46 +++++++++++++++++++++------------------------- src/utils/pactl.c | 35 ++++++++++++++++------------------- src/utils/paplay.c | 36 +++++++++++++++++------------------- 3 files changed, 54 insertions(+), 63 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 529cebae0..51b3a48ed 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -34,8 +34,6 @@ #include #include -#include -#include #include #define TIME_EVENT_USEC 50000 @@ -97,7 +95,7 @@ static void do_stream_write(size_t length) { buffer_index += l; if (!buffer_length) { - free(buffer); + pa_xfree(buffer); buffer = NULL; buffer_index = buffer_length = 0; } @@ -141,8 +139,7 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { return; } - buffer = malloc(buffer_length = length); - assert(buffer); + buffer = pa_xmalloc(buffer_length = length); memcpy(buffer, data, length); buffer_index = 0; pa_stream_drop(s); @@ -273,8 +270,8 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream))) l = 4096; - buffer = malloc(l); - assert(buffer); + buffer = pa_xmalloc(l); + if ((r = read(fd, buffer, l)) <= 0) { if (r == 0) { pa_operation *o; @@ -331,7 +328,7 @@ static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_eve buffer_index += r; if (!buffer_length) { - free(buffer); + pa_xfree(buffer); buffer = NULL; buffer_length = buffer_index = 0; } @@ -342,7 +339,6 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, if (verbose) fprintf(stderr, "Got signal, exiting.\n"); quit(0); - } /* Show the current latency */ @@ -479,23 +475,23 @@ int main(int argc, char *argv[]) { break; case 'd': - free(device); - device = strdup(optarg); + pa_xfree(device); + device = pa_xstrdup(optarg); break; case 's': - free(server); - server = strdup(optarg); + pa_xfree(server); + server = pa_xstrdup(optarg); break; case 'n': - free(client_name); - client_name = strdup(optarg); + pa_xfree(client_name); + client_name = pa_xstrdup(optarg); break; case ARG_STREAM_NAME: - free(stream_name); - stream_name = strdup(optarg); + pa_xfree(stream_name); + stream_name = pa_xstrdup(optarg); break; case 'v': @@ -567,7 +563,7 @@ int main(int argc, char *argv[]) { close(fd); if (!stream_name) - stream_name = strdup(argv[optind]); + stream_name = pa_xstrdup(argv[optind]); } else { fprintf(stderr, "Too many arguments.\n"); @@ -576,10 +572,10 @@ int main(int argc, char *argv[]) { } if (!client_name) - client_name = strdup(bn); + client_name = pa_xstrdup(bn); if (!stream_name) - stream_name = strdup(client_name); + stream_name = pa_xstrdup(client_name); /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { @@ -659,12 +655,12 @@ quit: pa_mainloop_free(m); } - free(buffer); + pa_xfree(buffer); - free(server); - free(device); - free(client_name); - free(stream_name); + pa_xfree(server); + pa_xfree(device); + pa_xfree(client_name); + pa_xfree(stream_name); return ret; } diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 7a3d37372..cc59e4595 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -36,8 +36,6 @@ #include #include -#include -#include #if PA_API_VERSION != 9 #error Invalid Polypaudio API version @@ -511,19 +509,18 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { float *d; assert(s && length && sndfile); - d = malloc(length); - assert(d); + d = pa_xmalloc(length); assert(sample_length >= length); l = length/pa_frame_size(&sample_spec); if ((sf_readf_float(sndfile, d, l)) != l) { - free(d); + pa_xfree(d); fprintf(stderr, "Premature end of file\n"); quit(1); } - pa_stream_write(s, d, length, free, 0, PA_SEEK_RELATIVE); + pa_stream_write(s, d, length, pa_xfree, 0, PA_SEEK_RELATIVE); sample_length -= length; @@ -652,13 +649,13 @@ int main(int argc, char *argv[]) { goto quit; case 's': - free(server); - server = strdup(optarg); + pa_xfree(server); + server = pa_xstrdup(optarg); break; case 'n': - free(client_name); - client_name = strdup(optarg); + pa_xfree(client_name); + client_name = pa_xstrdup(optarg); break; default: @@ -667,7 +664,7 @@ int main(int argc, char *argv[]) { } if (!client_name) - client_name = strdup(bn); + client_name = pa_xstrdup(bn); if (optind < argc) { if (!strcmp(argv[optind], "stat")) @@ -686,7 +683,7 @@ int main(int argc, char *argv[]) { } if (optind+2 < argc) - sample_name = strdup(argv[optind+2]); + sample_name = pa_xstrdup(argv[optind+2]); else { char *f = strrchr(argv[optind+1], '/'); size_t n; @@ -698,7 +695,7 @@ int main(int argc, char *argv[]) { n = strcspn(f, "."); strncpy(tmp, f, n); tmp[n] = 0; - sample_name = strdup(tmp); + sample_name = pa_xstrdup(tmp); } memset(&sfinfo, 0, sizeof(sfinfo)); @@ -719,10 +716,10 @@ int main(int argc, char *argv[]) { goto quit; } - sample_name = strdup(argv[optind+1]); + sample_name = pa_xstrdup(argv[optind+1]); if (optind+2 < argc) - device = strdup(argv[optind+2]); + device = pa_xstrdup(argv[optind+2]); } else if (!strcmp(argv[optind], "remove-sample")) { action = REMOVE_SAMPLE; @@ -731,7 +728,7 @@ int main(int argc, char *argv[]) { goto quit; } - sample_name = strdup(argv[optind+1]); + sample_name = pa_xstrdup(argv[optind+1]); } } @@ -782,9 +779,9 @@ quit: if (sndfile) sf_close(sndfile); - free(server); - free(device); - free(sample_name); + pa_xfree(server); + pa_xfree(device); + pa_xfree(sample_name); return ret; } diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 5f2036157..b66c13da5 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -35,8 +35,6 @@ #include #include -#include -#include #if PA_API_VERSION != 9 #error Invalid Polypaudio API version @@ -105,7 +103,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { if (!sndfile) return; - data = malloc(length); + data = pa_xmalloc(length); if (readf_function) { size_t k = pa_frame_size(&sample_spec); @@ -117,9 +115,9 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { bytes = sf_read_raw(sndfile, data, length); if (bytes > 0) - pa_stream_write(s, data, bytes, free, 0, PA_SEEK_RELATIVE); + pa_stream_write(s, data, bytes, pa_xfree, 0, PA_SEEK_RELATIVE); else - free(data); + pa_xfree(data); if (bytes < length) { sf_close(sndfile); @@ -257,23 +255,23 @@ int main(int argc, char *argv[]) { goto quit; case 'd': - free(device); - device = strdup(optarg); + pa_xfree(device); + device = pa_xstrdup(optarg); break; case 's': - free(server); - server = strdup(optarg); + pa_xfree(server); + server = pa_xstrdup(optarg); break; case 'n': - free(client_name); - client_name = strdup(optarg); + pa_xfree(client_name); + client_name = pa_xstrdup(optarg); break; case ARG_STREAM_NAME: - free(stream_name); - stream_name = strdup(optarg); + pa_xfree(stream_name); + stream_name = pa_xstrdup(optarg); break; case 'v': @@ -351,11 +349,11 @@ int main(int argc, char *argv[]) { } if (!client_name) - client_name = strdup(bn); + client_name = pa_xstrdup(bn); if (!stream_name) { const char *n = sf_get_string(sndfile, SF_STR_TITLE); - stream_name = strdup(n ? n : filename); + stream_name = pa_xstrdup(n ? n : filename); } if (verbose) { @@ -408,10 +406,10 @@ quit: pa_mainloop_free(m); } - free(server); - free(device); - free(client_name); - free(stream_name); + pa_xfree(server); + pa_xfree(device); + pa_xfree(client_name); + pa_xfree(stream_name); if (sndfile) sf_close(sndfile); From c47e937011f00eebab7230cedb58fd59f16487b4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 20:09:57 +0000 Subject: [PATCH 0822/1514] split polypcore/util.[ch] into polypcore/core-util.[ch] and polyp/util.[ch] git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@917 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 31 +- src/modules/module-alsa-sink.c | 2 +- src/modules/module-alsa-source.c | 2 +- src/modules/module-combine.c | 2 +- src/modules/module-detect.c | 2 +- src/modules/module-esound-compat-spawnfd.c | 2 +- src/modules/module-esound-compat-spawnpid.c | 2 +- src/modules/module-esound-sink.c | 2 +- src/modules/module-jack-sink.c | 2 +- src/modules/module-jack-source.c | 2 +- src/modules/module-match.c | 4 +- src/modules/module-mmkbd-evdev.c | 2 +- src/modules/module-null-sink.c | 2 +- src/modules/module-oss-mmap.c | 2 +- src/modules/module-oss.c | 2 +- src/modules/module-pipe-sink.c | 2 +- src/modules/module-pipe-source.c | 2 +- src/modules/module-protocol-stub.c | 2 +- src/modules/module-solaris.c | 2 +- src/modules/module-tunnel.c | 2 +- src/modules/module-volume-restore.c | 4 +- src/modules/module-waveout.c | 2 +- src/modules/module-x11-publish.c | 2 +- src/modules/module-zeroconf-publish.c | 2 +- src/modules/oss-util.c | 2 +- src/polyp/util.c | 350 ++++++++++++++++++++ src/polyp/util.h | 48 +++ src/polypcore/authkey.c | 2 +- src/polypcore/cli-command.c | 2 +- src/polypcore/conf-parser.c | 2 +- src/polypcore/core-scache.c | 2 +- src/polypcore/{util.c => core-util.c} | 291 +--------------- src/polypcore/{util.h => core-util.h} | 22 +- src/polypcore/core.c | 2 +- src/polypcore/iochannel.c | 2 +- src/polypcore/log.c | 2 +- src/polypcore/modargs.c | 2 +- src/polypcore/modinfo.c | 2 +- src/polypcore/module.c | 2 +- src/polypcore/namereg.c | 2 +- src/polypcore/parseaddr.c | 2 +- src/polypcore/pdispatch.c | 2 +- src/polypcore/pid.c | 2 +- src/polypcore/poll.c | 2 +- src/polypcore/protocol-esound.c | 2 +- src/polypcore/protocol-native.c | 2 +- src/polypcore/random.c | 2 +- src/polypcore/sink.c | 2 +- src/polypcore/socket-client.c | 2 +- src/polypcore/socket-server.c | 2 +- src/polypcore/socket-util.c | 2 +- src/polypcore/strlist.c | 2 +- src/utils/pabrowse.c | 4 +- 53 files changed, 469 insertions(+), 375 deletions(-) create mode 100644 src/polyp/util.c create mode 100644 src/polyp/util.h rename src/polypcore/{util.c => core-util.c} (77%) rename src/polypcore/{util.h => core-util.h} (79%) diff --git a/src/Makefile.am b/src/Makefile.am index 72db5f80e..e7ad2fd4a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -271,17 +271,9 @@ mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MA mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12.la mainloop_test_glib12_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -memblockq_test_SOURCES = \ - tests/memblockq-test.c \ - polyp/xmalloc.c \ - polypcore/memblockq.c \ - polypcore/log.c \ - polypcore/memblock.c \ - polypcore/util.c \ - polypcore/mcalign.c \ - polypcore/memchunk.c +memblockq_test_SOURCES = tests/memblockq-test.c memblockq_test_CFLAGS = $(AM_CFLAGS) -memblockq_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) +memblockq_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la memblockq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) sync_playback_SOURCES = tests/sync-playback.c @@ -315,7 +307,8 @@ polypinclude_HEADERS = \ polyp/sample.h \ polyp/utf8.h \ polyp/volume.h \ - polyp/xmalloc.h + polyp/xmalloc.h \ + polyp/util.h if HAVE_HOWL polypinclude_HEADERS += \ @@ -364,8 +357,7 @@ libpolyp_la_SOURCES = \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ polyp/thread-mainloop.c polyp/thread-mainloop.h \ polyp/xmalloc.c polyp/xmalloc.h \ - polypcore/pipe.c polypcore/pipe.h \ - polypcore/poll.c polypcore/poll.h + polyp/util.c polyp/util.h # Internal stuff that is shared with libpolypcore libpolyp_la_SOURCES += \ @@ -394,9 +386,11 @@ libpolyp_la_SOURCES += \ polypcore/strbuf.c polypcore/strbuf.h \ polypcore/strlist.c polypcore/strlist.h \ polypcore/tagstruct.c polypcore/tagstruct.h \ - polypcore/util.c polypcore/util.h \ + polypcore/core-util.c polypcore/core-util.h \ polypcore/winsock.h \ - polypcore/llist.h + polypcore/llist.h \ + polypcore/pipe.c polypcore/pipe.h \ + polypcore/poll.c polypcore/poll.h if OS_IS_WIN32 libpolyp_la_SOURCES += \ @@ -487,7 +481,7 @@ polypcoreinclude_HEADERS = \ polypcore/source-output.h \ polypcore/strbuf.h \ polypcore/tokenizer.h \ - polypcore/util.h + polypcore/core-util.h lib_LTLIBRARIES += libpolypcore.la @@ -500,7 +494,8 @@ libpolypcore_la_SOURCES = \ polyp/sample.c polyp/sample.h \ polyp/volume.c polyp/volume.h \ polyp/utf8.c polyp/utf8.h \ - polyp/xmalloc.c polyp/xmalloc.h + polyp/xmalloc.c polyp/xmalloc.h \ + polyp/util.c polyp/util.h # Pure core stuff (some are shared in libpolyp though). libpolypcore_la_SOURCES += \ @@ -547,7 +542,7 @@ libpolypcore_la_SOURCES += \ polypcore/source-output.c polypcore/source-output.h \ polypcore/strbuf.c polypcore/strbuf.h \ polypcore/tokenizer.c polypcore/tokenizer.h \ - polypcore/util.c polypcore/util.h \ + polypcore/core-util.c polypcore/core-util.h \ polypcore/winsock.h if OS_IS_WIN32 diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 94de771c1..e768e16a6 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index b9d1ff87c..654f3e493 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index b31fe56ea..5047fc306 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index ea14e68fb..2edbea5ea 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "module-detect-symdef.h" diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index 9b72448fa..bf89ca70f 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include "module-esound-compat-spawnfd-symdef.h" diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index f8c07d316..895abec32 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 1d61e01b1..cf3ce8073 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 1aa734950..96db837a4 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 29c46d853..3d7831458 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 1692b5d82..c7ca12a5e 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -35,12 +35,12 @@ #include #include -#include +#include #include #include #include #include -#include +#include #include "module-match-symdef.h" diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index 654fbaa4b..55f0b2c86 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include "module-mmkbd-evdev-symdef.h" diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 2cc490630..78850011c 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 82e7d66dd..a1b40389a 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 46d100f15..9233420d1 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index b59808fcb..6492ba6ad 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index 4f3f9a6c9..9f7554401 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 79a59cd5f..cfe661a38 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -47,7 +47,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index d82e33620..77eb4e49d 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index a2a1e33de..81c322879 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index ea40d8622..e74567bc7 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -35,12 +35,12 @@ #include #include -#include +#include #include #include #include #include -#include +#include #include #include "module-volume-restore-symdef.h" diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 3d1f1b01a..ce9ea84d8 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include "module-waveout-symdef.h" diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index e974487d8..eddcb3b80 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index e5dce7559..5c5db2862 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 2c573b2f5..a84276f11 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include "oss-util.h" diff --git a/src/polyp/util.c b/src/polyp/util.c new file mode 100644 index 000000000..dd5973220 --- /dev/null +++ b/src/polyp/util.c @@ -0,0 +1,350 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_NETDB_H +#include +#endif + +#ifdef HAVE_PWD_H +#include +#endif + +#ifdef HAVE_GRP_H +#include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif + +#include +#include +#include + +#include "util.h" + +#ifndef OS_IS_WIN32 +#define PATH_SEP '/' +#else +#define PATH_SEP '\\' +#endif + +/* Return the current username in the specified string buffer. */ +char *pa_get_user_name(char *s, size_t l) { + char *p; + char buf[1024]; + +#ifdef HAVE_PWD_H + struct passwd pw, *r; +#endif + + assert(s && l > 0); + + if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) { +#ifdef HAVE_PWD_H + +#ifdef HAVE_GETPWUID_R + if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { +#else + /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) + * that do not support getpwuid_r. */ + if ((r = getpwuid(getuid())) == NULL) { +#endif + snprintf(s, l, "%lu", (unsigned long) getuid()); + return s; + } + + p = r->pw_name; + +#elif defined(OS_IS_WIN32) /* HAVE_PWD_H */ + DWORD size = sizeof(buf); + + if (!GetUserName(buf, &size)) + return NULL; + + p = buf; + +#else /* HAVE_PWD_H */ + return NULL; +#endif /* HAVE_PWD_H */ + } + + return pa_strlcpy(s, p, l); +} + +/* Return the current hostname in the specified buffer. */ +char *pa_get_host_name(char *s, size_t l) { + assert(s && l > 0); + if (gethostname(s, l) < 0) { + pa_log(__FILE__": gethostname(): %s", strerror(errno)); + return NULL; + } + s[l-1] = 0; + return s; +} + +/* Return the home directory of the current user */ +char *pa_get_home_dir(char *s, size_t l) { + char *e; + +#ifdef HAVE_PWD_H + char buf[1024]; + struct passwd pw, *r; +#endif + + assert(s && l); + + if ((e = getenv("HOME"))) + return pa_strlcpy(s, e, l); + + if ((e = getenv("USERPROFILE"))) + return pa_strlcpy(s, e, l); + +#ifdef HAVE_PWD_H +#ifdef HAVE_GETPWUID_R + if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { + pa_log(__FILE__": getpwuid_r() failed"); +#else + /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) + * that do not support getpwuid_r. */ + if ((r = getpwuid(getuid())) == NULL) { + pa_log(__FILE__": getpwuid_r() failed"); +#endif + return NULL; + } + + return pa_strlcpy(s, r->pw_dir, l); +#else /* HAVE_PWD_H */ + return NULL; +#endif +} + +struct timeval *pa_gettimeofday(struct timeval *tv) { +#ifdef HAVE_GETTIMEOFDAY + assert(tv); + + return gettimeofday(tv, NULL) < 0 ? NULL : tv; +#elif defined(OS_IS_WIN32) + /* + * Copied from implementation by Steven Edwards (LGPL). + * Found on wine mailing list. + */ + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define EPOCHFILETIME (116444736000000000i64) +#else +#define EPOCHFILETIME (116444736000000000LL) +#endif + + FILETIME ft; + LARGE_INTEGER li; + __int64 t; + + assert(tv); + + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + t = li.QuadPart; /* In 100-nanosecond intervals */ + t -= EPOCHFILETIME; /* Offset to the Epoch time */ + t /= 10; /* In microseconds */ + tv->tv_sec = (long)(t / 1000000); + tv->tv_usec = (long)(t % 1000000); + + return tv; +#else +#error "Platform lacks gettimeofday() or equivalent function." +#endif +} + +/* Calculate the difference between the two specfified timeval + * timestamsps. */ +pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { + pa_usec_t r; + assert(a && b); + + /* Check which whan is the earlier time and swap the two arguments if reuqired. */ + if (pa_timeval_cmp(a, b) < 0) { + const struct timeval *c; + c = a; + a = b; + b = c; + } + + /* Calculate the second difference*/ + r = ((pa_usec_t) a->tv_sec - b->tv_sec)* 1000000; + + /* Calculate the microsecond difference */ + if (a->tv_usec > b->tv_usec) + r += ((pa_usec_t) a->tv_usec - b->tv_usec); + else if (a->tv_usec < b->tv_usec) + r -= ((pa_usec_t) b->tv_usec - a->tv_usec); + + return r; +} + +/* Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */ +int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { + assert(a && b); + + if (a->tv_sec < b->tv_sec) + return -1; + + if (a->tv_sec > b->tv_sec) + return 1; + + if (a->tv_usec < b->tv_usec) + return -1; + + if (a->tv_usec > b->tv_usec) + return 1; + + return 0; +} + +/* Return the time difference between now and the specified timestamp */ +pa_usec_t pa_timeval_age(const struct timeval *tv) { + struct timeval now; + assert(tv); + + return pa_timeval_diff(pa_gettimeofday(&now), tv); +} + +/* Add the specified time inmicroseconds to the specified timeval structure */ +void pa_timeval_add(struct timeval *tv, pa_usec_t v) { + unsigned long secs; + assert(tv); + + secs = (v/1000000); + tv->tv_sec += (unsigned long) secs; + v -= secs*1000000; + + tv->tv_usec += v; + + /* Normalize */ + while (tv->tv_usec >= 1000000) { + tv->tv_sec++; + tv->tv_usec -= 1000000; + } +} + +/* Return the binary file name of the current process. Works on Linux + * only. This shoul be used for eyecandy only, don't rely on return + * non-NULL! */ +char *pa_get_binary_name(char *s, size_t l) { + +#ifdef HAVE_READLINK + char path[PATH_MAX]; + int i; + assert(s && l); + + /* This works on Linux only */ + + snprintf(path, sizeof(path), "/proc/%u/exe", (unsigned) getpid()); + if ((i = readlink(path, s, l-1)) < 0) + return NULL; + + s[i] = 0; + return s; +#elif defined(OS_IS_WIN32) + char path[PATH_MAX]; + if (!GetModuleFileName(NULL, path, PATH_MAX)) + return NULL; + pa_strlcpy(s, pa_path_get_filename(path), l); + return s; +#else + return NULL; +#endif +} + +/* Return a pointer to the filename inside a path (which is the last + * component). */ +const char *pa_path_get_filename(const char *p) { + char *fn; + + if ((fn = strrchr(p, PATH_SEP))) + return fn+1; + + return (const char*) p; +} + +/* Return the fully qualified domain name in *s */ +char *pa_get_fqdn(char *s, size_t l) { + char hn[256]; +#ifdef HAVE_GETADDRINFO + struct addrinfo *a, hints; +#endif + + if (!pa_get_host_name(hn, sizeof(hn))) + return NULL; + +#ifdef HAVE_GETADDRINFO + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_CANONNAME; + + if (getaddrinfo(hn, NULL, &hints, &a) < 0 || !a || !a->ai_canonname || !*a->ai_canonname) + return pa_strlcpy(s, hn, l); + + pa_strlcpy(s, a->ai_canonname, l); + freeaddrinfo(a); + return s; +#else + return pa_strlcpy(s, hn, l); +#endif +} + +/* Wait t milliseconds */ +int pa_msleep(unsigned long t) { +#ifdef OS_IS_WIN32 + Sleep(t); + return 0; +#elif defined(HAVE_NANOSLEEP) + struct timespec ts; + + ts.tv_sec = t/1000; + ts.tv_nsec = (t % 1000) * 1000000; + + return nanosleep(&ts, NULL); +#else +#error "Platform lacks a sleep function." +#endif +} diff --git a/src/polyp/util.h b/src/polyp/util.h new file mode 100644 index 000000000..37232d9f4 --- /dev/null +++ b/src/polyp/util.h @@ -0,0 +1,48 @@ +#ifndef fooutilhfoo +#define fooutilhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +#include + +struct timeval; + +char *pa_get_user_name(char *s, size_t l); +char *pa_get_host_name(char *s, size_t l); +char *pa_get_fqdn(char *s, size_t l); +char *pa_get_home_dir(char *s, size_t l); + +char *pa_get_binary_name(char *s, size_t l); +const char *pa_path_get_filename(const char *p); + +struct timeval *pa_gettimeofday(struct timeval *tv); +pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); +int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); +pa_usec_t pa_timeval_age(const struct timeval *tv); +void pa_timeval_add(struct timeval *tv, pa_usec_t v); + +int pa_msleep(unsigned long t); + +#endif diff --git a/src/polypcore/authkey.c b/src/polypcore/authkey.c index 6eafb6720..1231c7a2b 100644 --- a/src/polypcore/authkey.c +++ b/src/polypcore/authkey.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include diff --git a/src/polypcore/cli-command.c b/src/polypcore/cli-command.c index 5556bcb34..3adc9a217 100644 --- a/src/polypcore/cli-command.c +++ b/src/polypcore/cli-command.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include "cli-command.h" diff --git a/src/polypcore/conf-parser.c b/src/polypcore/conf-parser.c index 64e66c2e1..bc99b8710 100644 --- a/src/polypcore/conf-parser.c +++ b/src/polypcore/conf-parser.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include "conf-parser.h" diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 8080fcd69..068f2361d 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -52,7 +52,7 @@ #include #include #include -#include +#include #include #include "core-scache.h" diff --git a/src/polypcore/util.c b/src/polypcore/core-util.c similarity index 77% rename from src/polypcore/util.c rename to src/polypcore/core-util.c index 9783b7461..36044c810 100644 --- a/src/polypcore/util.c +++ b/src/polypcore/core-util.c @@ -59,22 +59,23 @@ #include #endif -#include - #ifdef HAVE_PWD_H #include #endif + #ifdef HAVE_GRP_H #include #endif -#include "winsock.h" +#include #include +#include +#include #include -#include "util.h" +#include "core-util.h" #ifndef OS_IS_WIN32 #define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-" @@ -377,96 +378,6 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) { } } -/* Return the current username in the specified string buffer. */ -char *pa_get_user_name(char *s, size_t l) { - char *p; - char buf[1024]; - -#ifdef HAVE_PWD_H - struct passwd pw, *r; -#endif - - assert(s && l > 0); - - if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) { -#ifdef HAVE_PWD_H - -#ifdef HAVE_GETPWUID_R - if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { -#else - /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) - * that do not support getpwuid_r. */ - if ((r = getpwuid(getuid())) == NULL) { -#endif - snprintf(s, l, "%lu", (unsigned long) getuid()); - return s; - } - - p = r->pw_name; - -#elif defined(OS_IS_WIN32) /* HAVE_PWD_H */ - DWORD size = sizeof(buf); - - if (!GetUserName(buf, &size)) - return NULL; - - p = buf; - -#else /* HAVE_PWD_H */ - return NULL; -#endif /* HAVE_PWD_H */ - } - - return pa_strlcpy(s, p, l); -} - -/* Return the current hostname in the specified buffer. */ -char *pa_get_host_name(char *s, size_t l) { - assert(s && l > 0); - if (gethostname(s, l) < 0) { - pa_log(__FILE__": gethostname(): %s", strerror(errno)); - return NULL; - } - s[l-1] = 0; - return s; -} - -/* Return the home directory of the current user */ -char *pa_get_home_dir(char *s, size_t l) { - char *e; - -#ifdef HAVE_PWD_H - char buf[1024]; - struct passwd pw, *r; -#endif - - assert(s && l); - - if ((e = getenv("HOME"))) - return pa_strlcpy(s, e, l); - - if ((e = getenv("USERPROFILE"))) - return pa_strlcpy(s, e, l); - -#ifdef HAVE_PWD_H -#ifdef HAVE_GETPWUID_R - if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { - pa_log(__FILE__": getpwuid_r() failed"); -#else - /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) - * that do not support getpwuid_r. */ - if ((r = getpwuid(getuid())) == NULL) { - pa_log(__FILE__": getpwuid_r() failed"); -#endif - return NULL; - } - - return pa_strlcpy(s, r->pw_dir, l); -#else /* HAVE_PWD_H */ - return NULL; -#endif -} - /* Similar to OpenBSD's strlcpy() function */ char *pa_strlcpy(char *b, const char *s, size_t l) { assert(b && s && l > 0); @@ -476,115 +387,6 @@ char *pa_strlcpy(char *b, const char *s, size_t l) { return b; } -struct timeval *pa_gettimeofday(struct timeval *tv) { -#ifdef HAVE_GETTIMEOFDAY - assert(tv); - - return gettimeofday(tv, NULL) < 0 ? NULL : tv; -#elif defined(OS_IS_WIN32) - /* - * Copied from implementation by Steven Edwards (LGPL). - * Found on wine mailing list. - */ - -#if defined(_MSC_VER) || defined(__BORLANDC__) -#define EPOCHFILETIME (116444736000000000i64) -#else -#define EPOCHFILETIME (116444736000000000LL) -#endif - - FILETIME ft; - LARGE_INTEGER li; - __int64 t; - - assert(tv); - - GetSystemTimeAsFileTime(&ft); - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - t = li.QuadPart; /* In 100-nanosecond intervals */ - t -= EPOCHFILETIME; /* Offset to the Epoch time */ - t /= 10; /* In microseconds */ - tv->tv_sec = (long)(t / 1000000); - tv->tv_usec = (long)(t % 1000000); - - return tv; -#else -#error "Platform lacks gettimeofday() or equivalent function." -#endif -} - -/* Calculate the difference between the two specfified timeval - * timestamsps. */ -pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { - pa_usec_t r; - assert(a && b); - - /* Check which whan is the earlier time and swap the two arguments if reuqired. */ - if (pa_timeval_cmp(a, b) < 0) { - const struct timeval *c; - c = a; - a = b; - b = c; - } - - /* Calculate the second difference*/ - r = ((pa_usec_t) a->tv_sec - b->tv_sec)* 1000000; - - /* Calculate the microsecond difference */ - if (a->tv_usec > b->tv_usec) - r += ((pa_usec_t) a->tv_usec - b->tv_usec); - else if (a->tv_usec < b->tv_usec) - r -= ((pa_usec_t) b->tv_usec - a->tv_usec); - - return r; -} - -/* Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */ -int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { - assert(a && b); - - if (a->tv_sec < b->tv_sec) - return -1; - - if (a->tv_sec > b->tv_sec) - return 1; - - if (a->tv_usec < b->tv_usec) - return -1; - - if (a->tv_usec > b->tv_usec) - return 1; - - return 0; -} - -/* Return the time difference between now and the specified timestamp */ -pa_usec_t pa_timeval_age(const struct timeval *tv) { - struct timeval now; - assert(tv); - - return pa_timeval_diff(pa_gettimeofday(&now), tv); -} - -/* Add the specified time inmicroseconds to the specified timeval structure */ -void pa_timeval_add(struct timeval *tv, pa_usec_t v) { - unsigned long secs; - assert(tv); - - secs = (v/1000000); - tv->tv_sec += (unsigned long) secs; - v -= secs*1000000; - - tv->tv_usec += v; - - /* Normalize */ - while (tv->tv_usec >= 1000000) { - tv->tv_sec++; - tv->tv_usec -= 1000000; - } -} - #define NICE_LEVEL (-15) /* Raise the priority of the current process as much as possible and @@ -665,46 +467,6 @@ int pa_fd_set_cloexec(int fd, int b) { return 0; } -/* Return the binary file name of the current process. Works on Linux - * only. This shoul be used for eyecandy only, don't rely on return - * non-NULL! */ -char *pa_get_binary_name(char *s, size_t l) { - -#ifdef HAVE_READLINK - char path[PATH_MAX]; - int i; - assert(s && l); - - /* This works on Linux only */ - - snprintf(path, sizeof(path), "/proc/%u/exe", (unsigned) getpid()); - if ((i = readlink(path, s, l-1)) < 0) - return NULL; - - s[i] = 0; - return s; -#elif defined(OS_IS_WIN32) - char path[PATH_MAX]; - if (!GetModuleFileName(NULL, path, PATH_MAX)) - return NULL; - pa_strlcpy(s, pa_path_get_filename(path), l); - return s; -#else - return NULL; -#endif -} - -/* Return a pointer to the filename inside a path (which is the last - * component). */ -const char *pa_path_get_filename(const char *p) { - char *fn; - - if ((fn = strrchr(p, PATH_SEP))) - return fn+1; - - return (const char*) p; -} - /* Try to parse a boolean string value.*/ int pa_parse_boolean(const char *v) { @@ -1163,32 +925,6 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) { return j; } -/* Return the fully qualified domain name in *s */ -char *pa_get_fqdn(char *s, size_t l) { - char hn[256]; -#ifdef HAVE_GETADDRINFO - struct addrinfo *a, hints; -#endif - - if (!pa_get_host_name(hn, sizeof(hn))) - return NULL; - -#ifdef HAVE_GETADDRINFO - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_CANONNAME; - - if (getaddrinfo(hn, NULL, &hints, &a) < 0 || !a || !a->ai_canonname || !*a->ai_canonname) - return pa_strlcpy(s, hn, l); - - pa_strlcpy(s, a->ai_canonname, l); - freeaddrinfo(a); - return s; -#else - return pa_strlcpy(s, hn, l); -#endif -} - /* Returns nonzero when *s starts with *pfx */ int pa_startswith(const char *s, const char *pfx) { size_t l; @@ -1243,23 +979,6 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) { return s; } -/* Wait t milliseconds */ -int pa_msleep(unsigned long t) { -#ifdef OS_IS_WIN32 - Sleep(t); - return 0; -#elif defined(HAVE_NANOSLEEP) - struct timespec ts; - - ts.tv_sec = t/1000; - ts.tv_nsec = (t % 1000) * 1000000; - - return nanosleep(&ts, NULL); -#else -#error "Platform lacks a sleep function." -#endif -} - /* Convert the string s to a signed integer in *ret_i */ int pa_atoi(const char *s, int32_t *ret_i) { char *x = NULL; diff --git a/src/polypcore/util.h b/src/polypcore/core-util.h similarity index 79% rename from src/polypcore/util.h rename to src/polypcore/core-util.h index df71672f4..d3db756fe 100644 --- a/src/polypcore/util.h +++ b/src/polypcore/core-util.h @@ -1,5 +1,5 @@ -#ifndef fooutilhfoo -#define fooutilhfoo +#ifndef foocoreutilhfoo +#define foocoreutilhfoo /* $Id$ */ @@ -27,8 +27,8 @@ #include #include -#include #include +#include struct timeval; @@ -49,22 +49,8 @@ char *pa_vsprintf_malloc(const char *format, va_list ap); char *pa_strlcpy(char *b, const char *s, size_t l); -char *pa_get_user_name(char *s, size_t l); -char *pa_get_host_name(char *s, size_t l); -char *pa_get_fqdn(char *s, size_t l); -char *pa_get_binary_name(char *s, size_t l); -char *pa_get_home_dir(char *s, size_t l); - -const char *pa_path_get_filename(const char *p); - char *pa_parent_dir(const char *fn); -struct timeval *pa_gettimeofday(struct timeval *tv); -pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); -int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); -pa_usec_t pa_timeval_age(const struct timeval *tv); -void pa_timeval_add(struct timeval *tv, pa_usec_t v); - void pa_raise_priority(void); void pa_reset_priority(void); @@ -97,8 +83,6 @@ int pa_endswith(const char *s, const char *sfx); char *pa_runtime_path(const char *fn, char *s, size_t l); -int pa_msleep(unsigned long t); - int pa_atoi(const char *s, int32_t *ret_i); int pa_atou(const char *s, uint32_t *ret_u); diff --git a/src/polypcore/core.c b/src/polypcore/core.c index ff8ec0810..43f7015e0 100644 --- a/src/polypcore/core.c +++ b/src/polypcore/core.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index a1ad5dea2..b953a1d08 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -40,7 +40,7 @@ #include -#include +#include #include #include diff --git a/src/polypcore/log.c b/src/polypcore/log.c index 9908d168c..3f5dfa086 100644 --- a/src/polypcore/log.c +++ b/src/polypcore/log.c @@ -35,7 +35,7 @@ #include -#include +#include #include "log.h" diff --git a/src/polypcore/modargs.c b/src/polypcore/modargs.c index 63cc779dd..5d046d269 100644 --- a/src/polypcore/modargs.c +++ b/src/polypcore/modargs.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include "modargs.h" diff --git a/src/polypcore/modinfo.c b/src/polypcore/modinfo.c index 241076c66..4a9be0f04 100644 --- a/src/polypcore/modinfo.c +++ b/src/polypcore/modinfo.c @@ -28,7 +28,7 @@ #include -#include +#include #include #include "modinfo.h" diff --git a/src/polypcore/module.c b/src/polypcore/module.c index fe177a5bf..52cde9c39 100644 --- a/src/polypcore/module.c +++ b/src/polypcore/module.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include "module.h" diff --git a/src/polypcore/namereg.c b/src/polypcore/namereg.c index cf11f5a4d..17d751465 100644 --- a/src/polypcore/namereg.c +++ b/src/polypcore/namereg.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include "namereg.h" diff --git a/src/polypcore/parseaddr.c b/src/polypcore/parseaddr.c index 7e518a5d4..b2c7d1c7d 100644 --- a/src/polypcore/parseaddr.c +++ b/src/polypcore/parseaddr.c @@ -29,7 +29,7 @@ #include -#include +#include #include "parseaddr.h" diff --git a/src/polypcore/pdispatch.c b/src/polypcore/pdispatch.c index 21e3644e0..4b0d1bb27 100644 --- a/src/polypcore/pdispatch.c +++ b/src/polypcore/pdispatch.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include "pdispatch.h" diff --git a/src/polypcore/pid.c b/src/polypcore/pid.c index 53b8ad0a2..e98dc97bb 100644 --- a/src/polypcore/pid.c +++ b/src/polypcore/pid.c @@ -41,7 +41,7 @@ #include -#include +#include #include #include "pid.h" diff --git a/src/polypcore/poll.c b/src/polypcore/poll.c index 6a29a9530..7b1ed4382 100644 --- a/src/polypcore/poll.c +++ b/src/polypcore/poll.c @@ -42,7 +42,7 @@ #ifndef HAVE_SYS_POLL_H -#include +#include #include "poll.h" diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 8f53694e7..98738728a 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include "endianmacros.h" diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 338db0020..f0e50ec54 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/polypcore/random.c b/src/polypcore/random.c index 1221206fd..4bfce975d 100644 --- a/src/polypcore/random.c +++ b/src/polypcore/random.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include "random.h" diff --git a/src/polypcore/sink.c b/src/polypcore/sink.c index 6931d396d..dc27ca2e5 100644 --- a/src/polypcore/sink.c +++ b/src/polypcore/sink.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index a61cf582f..4fb0a5d89 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -57,7 +57,7 @@ #include #include -#include +#include #include #include diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index 959173f26..96f8e0733 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -65,7 +65,7 @@ #include #include -#include +#include #include #include "socket-server.h" diff --git a/src/polypcore/socket-util.c b/src/polypcore/socket-util.c index 0961db210..acbb7c1ff 100644 --- a/src/polypcore/socket-util.c +++ b/src/polypcore/socket-util.c @@ -61,7 +61,7 @@ #include -#include +#include #include #include "socket-util.h" diff --git a/src/polypcore/strlist.c b/src/polypcore/strlist.c index 4d70e9e99..b94207496 100644 --- a/src/polypcore/strlist.c +++ b/src/polypcore/strlist.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include "strlist.h" diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index c1bab6b1c..8063a28ba 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -27,8 +27,7 @@ #include #include -#include -#include +#include #include static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { @@ -108,7 +107,6 @@ static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_brows } } - int main(int argc, char *argv[]) { pa_mainloop *mainloop = NULL; pa_browser *browser = NULL; From 813868e1cb98390b32f6ec3fbf3019a7d15f7ab9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 20:42:11 +0000 Subject: [PATCH 0823/1514] include util.h in polypaudio.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@918 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/polypaudio.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/polyp/polypaudio.h b/src/polyp/polypaudio.h index fe25fe300..51e3f9703 100644 --- a/src/polyp/polypaudio.h +++ b/src/polyp/polypaudio.h @@ -40,6 +40,7 @@ #include #include #include +#include /** \file * Include all polyplib header files at once. The following @@ -47,7 +48,7 @@ * \ref context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h, * \ref scache.h, \ref version.h, \ref error.h, \ref channelmap.h, * \ref operation.h,\ref volume.h, \ref xmalloc.h, \ref utf8.h, \ref - * thread-mainloop.h, \ref mainloop.h and \ref mainloop-signal.h at once */ + * thread-mainloop.h, \ref mainloop.h, \ref util.h and \ref mainloop-signal.h at once */ /** \mainpage * From 6766a3ba21632ed7ffa869800a7ac28f839a63a3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 20:42:27 +0000 Subject: [PATCH 0824/1514] add util.h to doxygen git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@919 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doxygen/doxygen.conf.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 97040377c..3d7ad3222 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h ../src/polyp/thread-mainloop.h ../src/polyp/xmalloc.h ../src/polyp/utf8.h +INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h ../src/polyp/thread-mainloop.h ../src/polyp/xmalloc.h ../src/polyp/utf8.h ../src/polyp/util.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp From dc9151d35517d82769028c7dd81e0d7cc527a270 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 20:43:19 +0000 Subject: [PATCH 0825/1514] * add doxygen docs to header file * add C++ macros to header file git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@920 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/util.c | 21 ++++----------------- src/polyp/util.h | 39 +++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/polyp/util.c b/src/polyp/util.c index dd5973220..76b5c9b97 100644 --- a/src/polyp/util.c +++ b/src/polyp/util.c @@ -57,7 +57,7 @@ #include #include -#include +#include #include "util.h" @@ -67,7 +67,6 @@ #define PATH_SEP '\\' #endif -/* Return the current username in the specified string buffer. */ char *pa_get_user_name(char *s, size_t l) { char *p; char buf[1024]; @@ -110,7 +109,6 @@ char *pa_get_user_name(char *s, size_t l) { return pa_strlcpy(s, p, l); } -/* Return the current hostname in the specified buffer. */ char *pa_get_host_name(char *s, size_t l) { assert(s && l > 0); if (gethostname(s, l) < 0) { @@ -121,7 +119,6 @@ char *pa_get_host_name(char *s, size_t l) { return s; } -/* Return the home directory of the current user */ char *pa_get_home_dir(char *s, size_t l) { char *e; @@ -195,8 +192,6 @@ struct timeval *pa_gettimeofday(struct timeval *tv) { #endif } -/* Calculate the difference between the two specfified timeval - * timestamsps. */ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { pa_usec_t r; assert(a && b); @@ -221,7 +216,6 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { return r; } -/* Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { assert(a && b); @@ -240,7 +234,6 @@ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { return 0; } -/* Return the time difference between now and the specified timestamp */ pa_usec_t pa_timeval_age(const struct timeval *tv) { struct timeval now; assert(tv); @@ -248,8 +241,7 @@ pa_usec_t pa_timeval_age(const struct timeval *tv) { return pa_timeval_diff(pa_gettimeofday(&now), tv); } -/* Add the specified time inmicroseconds to the specified timeval structure */ -void pa_timeval_add(struct timeval *tv, pa_usec_t v) { +struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) { unsigned long secs; assert(tv); @@ -264,11 +256,10 @@ void pa_timeval_add(struct timeval *tv, pa_usec_t v) { tv->tv_sec++; tv->tv_usec -= 1000000; } + + return tv; } -/* Return the binary file name of the current process. Works on Linux - * only. This shoul be used for eyecandy only, don't rely on return - * non-NULL! */ char *pa_get_binary_name(char *s, size_t l) { #ifdef HAVE_READLINK @@ -295,8 +286,6 @@ char *pa_get_binary_name(char *s, size_t l) { #endif } -/* Return a pointer to the filename inside a path (which is the last - * component). */ const char *pa_path_get_filename(const char *p) { char *fn; @@ -306,7 +295,6 @@ const char *pa_path_get_filename(const char *p) { return (const char*) p; } -/* Return the fully qualified domain name in *s */ char *pa_get_fqdn(char *s, size_t l) { char hn[256]; #ifdef HAVE_GETADDRINFO @@ -332,7 +320,6 @@ char *pa_get_fqdn(char *s, size_t l) { #endif } -/* Wait t milliseconds */ int pa_msleep(unsigned long t) { #ifdef OS_IS_WIN32 Sleep(t); diff --git a/src/polyp/util.h b/src/polyp/util.h index 37232d9f4..8bd03f98a 100644 --- a/src/polyp/util.h +++ b/src/polyp/util.h @@ -26,23 +26,54 @@ #include #include +#include + +/** \file + * Assorted utility functions */ + +PA_C_DECL_BEGIN struct timeval; +/** Return the current username in the specified string buffer. */ char *pa_get_user_name(char *s, size_t l); + +/** Return the current hostname in the specified buffer. */ char *pa_get_host_name(char *s, size_t l); + +/** Return the fully qualified domain name in s */ char *pa_get_fqdn(char *s, size_t l); + +/** Return the home directory of the current user */ char *pa_get_home_dir(char *s, size_t l); +/** Return the binary file name of the current process. This is not + * supported on all architectures, in which case NULL is returned. */ char *pa_get_binary_name(char *s, size_t l); + +/** Return a pointer to the filename inside a path (which is the last + * component). */ const char *pa_path_get_filename(const char *p); +/** Return the current timestamp, just like UNIX gettimeofday() */ struct timeval *pa_gettimeofday(struct timeval *tv); -pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); -int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); -pa_usec_t pa_timeval_age(const struct timeval *tv); -void pa_timeval_add(struct timeval *tv, pa_usec_t v); +/** Calculate the difference between the two specified timeval + * structs. */ +pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); + +/** Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */ +int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); + +/** Return the time difference between now and the specified timestamp */ +pa_usec_t pa_timeval_age(const struct timeval *tv); + +/** Add the specified time inmicroseconds to the specified timeval structure */ +struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v); + +/** Wait t milliseconds */ int pa_msleep(unsigned long t); +PA_C_DECL_END + #endif From ee4d6b064fe9c872e008a37b5b8daf60752a27ae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 20:43:49 +0000 Subject: [PATCH 0826/1514] add C++ macros to xmalloc.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@921 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/xmalloc.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/polyp/xmalloc.h b/src/polyp/xmalloc.h index 9d91d8dc4..49b6d7bca 100644 --- a/src/polyp/xmalloc.h +++ b/src/polyp/xmalloc.h @@ -26,11 +26,14 @@ #include #include #include +#include /** \file * Memory allocation functions. */ +PA_C_DECL_BEGIN + /** Allocate the specified number of bytes, just like malloc() does. However, in case of OOM, terminate */ void* pa_xmalloc(size_t l); @@ -70,4 +73,6 @@ static inline void* pa_xnew0_internal(unsigned n, size_t k) { /** Same as pa_xnew() but set the memory to zero */ #define pa_xnew0(type, n) ((type*) pa_xnew0_internal((n), sizeof(type))) +PA_C_DECL_END + #endif From 40feedb8bf53fe656946f376c044dbe4a1741082 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 20:44:19 +0000 Subject: [PATCH 0827/1514] add C++ macros to utf8.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@922 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/utf8.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/polyp/utf8.h b/src/polyp/utf8.h index e9a515330..3cc3a7d08 100644 --- a/src/polyp/utf8.h +++ b/src/polyp/utf8.h @@ -22,14 +22,20 @@ USA. ***/ +#include + /** \file * UTF8 Validation functions */ +PA_C_DECL_BEGIN + /** Test if the specified strings qualifies as valid UTF8. Return the string if so, otherwise NULL */ const char *pa_utf8_valid(const char *str); /** Filter all invalid UTF8 characters from the specified string, returning a new fully UTF8 valid string. Don't forget to free the returned string with pa_xfree() */ char *pa_utf8_filter(const char *str); +PA_C_DECL_END + #endif From 53a285e75616281bcdd8b1dcf0e3b7ba59257516 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 20:44:55 +0000 Subject: [PATCH 0828/1514] fix include line for "core-util.h" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@923 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/cmdline.c | 2 +- src/daemon/cpulimit.c | 2 +- src/daemon/daemon-conf.c | 2 +- src/daemon/dumpmodules.c | 2 +- src/daemon/main.c | 2 +- src/modules/rtp/module-rtp-recv.c | 2 +- src/modules/rtp/module-rtp-send.c | 2 +- src/modules/rtp/sap.c | 2 +- src/modules/rtp/sdp.c | 2 +- src/polyp/browser.c | 2 +- src/polyp/channelmap.c | 3 +-- src/polyp/client-conf-x11.c | 2 +- src/polyp/client-conf.c | 2 +- src/polyp/context.c | 2 +- src/polyp/glib-mainloop.c | 2 +- src/polyp/glib12-mainloop.c | 2 +- src/polyp/mainloop-signal.c | 2 +- src/polyp/mainloop.c | 2 +- src/polyp/stream.c | 2 +- src/polyp/xmalloc.c | 2 +- src/polypcore/ioline.h | 2 +- src/tests/mainloop-test.c | 2 +- src/tests/mcalign-test.c | 2 +- src/tests/thread-mainloop-test.c | 2 +- src/utils/pacat.c | 1 - src/utils/pacmd.c | 2 +- src/utils/pax11publish.c | 2 +- 27 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index 1ed16a692..21fd5a257 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -32,7 +32,7 @@ #include -#include +#include #include #include "cmdline.h" diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index 54f111da8..699733847 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -23,7 +23,7 @@ #include #endif -#include +#include #include #include "cpulimit.h" diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index f82d3d24f..0f4fcb976 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -31,7 +31,7 @@ #include -#include +#include #include #include #include diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c index c541c1681..b6a3bb7cf 100644 --- a/src/daemon/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include "dumpmodules.h" diff --git a/src/daemon/main.c b/src/daemon/main.c index a7144eba0..9b9ea1800 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -58,7 +58,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 89aa89830..a1196a2d3 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 8fc1d7fee..a88ea76af 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index e579b5c57..5b8f31fba 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -40,7 +40,7 @@ #include -#include +#include #include #include "sap.h" diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index 3cece7110..5ec5090d6 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -33,7 +33,7 @@ #include -#include +#include #include #include "sdp.h" diff --git a/src/polyp/browser.c b/src/polyp/browser.c index 5442fd4c0..69760d8d0 100644 --- a/src/polyp/browser.c +++ b/src/polyp/browser.c @@ -25,7 +25,7 @@ #include #include -#include +#include #include "browser.h" diff --git a/src/polyp/channelmap.c b/src/polyp/channelmap.c index ddd7b3ce7..653331ba1 100644 --- a/src/polyp/channelmap.c +++ b/src/polyp/channelmap.c @@ -29,8 +29,7 @@ #include #include - -#include +#include #include "channelmap.h" diff --git a/src/polyp/client-conf-x11.c b/src/polyp/client-conf-x11.c index 17ee2d6ae..fb67df2f0 100644 --- a/src/polyp/client-conf-x11.c +++ b/src/polyp/client-conf-x11.c @@ -33,7 +33,7 @@ #include #include -#include +#include #include "client-conf-x11.h" diff --git a/src/polyp/client-conf.c b/src/polyp/client-conf.c index 567d2ae4c..1ebcff437 100644 --- a/src/polyp/client-conf.c +++ b/src/polyp/client-conf.c @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include "client-conf.h" diff --git a/src/polyp/context.c b/src/polyp/context.c index 3c46e2e87..a3b49d4b5 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -56,7 +56,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/polyp/glib-mainloop.c b/src/polyp/glib-mainloop.c index bc5df3a9b..51d437d22 100644 --- a/src/polyp/glib-mainloop.c +++ b/src/polyp/glib-mainloop.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include "glib.h" #include "glib-mainloop.h" diff --git a/src/polyp/glib12-mainloop.c b/src/polyp/glib12-mainloop.c index 7af21210f..f7459f192 100644 --- a/src/polyp/glib12-mainloop.c +++ b/src/polyp/glib12-mainloop.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include "glib-mainloop.h" diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index a225f78be..c57437b6e 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -38,7 +38,7 @@ #include -#include +#include #include #include diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 82e789c54..8f44c180c 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -46,7 +46,7 @@ #include -#include +#include #include #include diff --git a/src/polyp/stream.c b/src/polyp/stream.c index f188e7885..ad6c9e43c 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include diff --git a/src/polyp/xmalloc.c b/src/polyp/xmalloc.c index 1deeebd80..ffc7f7c81 100644 --- a/src/polyp/xmalloc.c +++ b/src/polyp/xmalloc.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include "xmalloc.h" diff --git a/src/polypcore/ioline.h b/src/polypcore/ioline.h index e2dadf557..77bf87616 100644 --- a/src/polypcore/ioline.h +++ b/src/polypcore/ioline.h @@ -23,7 +23,7 @@ ***/ #include -#include +#include /* An ioline wraps an iochannel for line based communication. A * callback function is called whenever a new line has been recieved diff --git a/src/tests/mainloop-test.c b/src/tests/mainloop-test.c index f62c96939..300884839 100644 --- a/src/tests/mainloop-test.c +++ b/src/tests/mainloop-test.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include #ifdef GLIB_MAIN_LOOP diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index 2728def22..765dcf943 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c index 8ca3f92fa..676b8d37e 100644 --- a/src/tests/thread-mainloop-test.c +++ b/src/tests/thread-mainloop-test.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 51b3a48ed..b1f5bf59a 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -34,7 +34,6 @@ #include #include -#include #define TIME_EVENT_USEC 50000 diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index e640ddaf0..fefe76349 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index e43588949..ee0cb8452 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include #include From 38cb1381156c7913118b76c5ddf3ae0e70f39163 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 21:07:46 +0000 Subject: [PATCH 0829/1514] modify lirc module to use pa_sink_mute() for muting and unmuting git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@924 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-lirc.c | 56 ++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index 918177a30..009c2e466 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -88,7 +88,14 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_xfree(c); while (lirc_code2char(u->config, code, &name) == 0 && name) { - enum { INVALID, UP, DOWN, MUTE, RESET, MUTE_TOGGLE } volchange = INVALID; + enum { + INVALID, + UP, + DOWN, + MUTE, + RESET, + MUTE_TOGGLE + } volchange = INVALID; pa_log_info(__FILE__": translated IR code '%s'", name); @@ -111,51 +118,56 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) pa_log(__FILE__": failed to get sink '%s'", u->sink_name); else { - pa_volume_t v = pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE)); - pa_cvolume cv; + int i; + pa_cvolume cv = *pa_sink_get_volume(s, PA_MIXER_HARDWARE); + #define DELTA (PA_VOLUME_NORM/20) switch (volchange) { case UP: - v += PA_VOLUME_NORM/20; + for (i = 0; i < cv.channels; i++) { + cv.values[i] += DELTA; + + if (cv.values[i] > PA_VOLUME_NORM) + cv.values[i] = PA_VOLUME_NORM; + } + + pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); break; case DOWN: - if (v > DELTA) - v -= DELTA; - else - v = PA_VOLUME_MUTED; + for (i = 0; i < cv.channels; i++) { + if (cv.values[i] >= DELTA) + cv.values[i] -= DELTA; + else + cv.values[i] = PA_VOLUME_MUTED; + } + pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); break; case MUTE: - v = PA_VOLUME_MUTED; + pa_sink_set_mute(s, PA_MIXER_HARDWARE, 0); break; case RESET: - v = PA_VOLUME_NORM; + pa_sink_set_mute(s, PA_MIXER_HARDWARE, 1); break; - case MUTE_TOGGLE: { + case MUTE_TOGGLE: - if (v > 0) { - u->mute_toggle_save = v; - v = PA_VOLUME_MUTED; - } else - v = u->mute_toggle_save; - } - default: + pa_sink_set_mute(s, PA_MIXER_HARDWARE, !pa_sink_get_mute(s, PA_MIXER_HARDWARE)); + break; + + case INVALID: ; } - - pa_cvolume_set(&cv, PA_CHANNELS_MAX, v); - pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); } } } } - free(code); + pa_xfree(code); return; From 5f458db84f38c52170af26be93156c24ac7831fc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 21:39:35 +0000 Subject: [PATCH 0830/1514] update README for 0.9.0 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@925 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index 5c6e49a76..62a23b71a 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -43,6 +43,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    News

    +
    Fri Apr 28 2006:

    Version 0.9.0 +released; changes include: new module module-volume-restore; +require valid UTF8 strings everywhere; properly support ALSA channel +maps for surround sound; increase maximum number of channels per +stream to 32; add new threaded main loop API for synchronous programs; +introduce real shared object versioning; a few API additions; many, +many bugfixes

    +
    Fri Apr 28 2006:

    Version 0.8.1 released; changes include: support for specifying the channel map on @@ -157,6 +166,7 @@ Sound Architecture (ALSA) sinks and sources

  • module-http-protocol-tcp: Spawns a small HTTP server which can be used to introspect the Polypaudio server with a web browser.
  • module-tunnel-sink, module-tunnel-source: make sinks/sources from other hosts available locally.
  • module-match: adjust volume automatically for newly created playback streams based on a regular expression matching table.
  • +
  • module-volume-restore: much like module-match, but create rules fully automatically based on the client name.
  • module-null-sink: a clocked sink similar to /dev/null.
  • module-esound-sink: a sink for forwarding audio data to an ESOUND server.
  • module-detect: a module which automatically detects what sound hardware is available locally and which loads the required driver modules.
  • @@ -167,15 +177,13 @@ Sound Architecture (ALSA) sinks and sources
  • module-jack-sink, module-jack-source: connect to a JACK Audio Connection Kit server. (A sound server for professional audio production)
  • -

    polypaudio is the successor of my previous, ill-fated -attempt to write a sound server, asd.

    -

    A GTK GUI manager application for polypaudio is the Polypaudio -Manager. Another GTK GUI tool for Polypaudio is the . Other GTK GUI tool for Polypaudio are the Polypaudio Volume -Meter.

    +Meter and the Polypaudio Volume +Control .

    There are output plugins for XMMS,

    Version @PACKAGE_VERSION@ is quite usable. It matches and supersedes ESOUND's feature set in nearly all areas.

    -

    Warning: polypaudio's client API and protocol are not stable -yet. The client interface is still a moving target and changes from -release to release. The client API's library version number is currently fixed to 0.0.0.

    -

    Documentation

    There is some preliminary documentation available: for the client API. (Run make doxygen to generate thi

    There are several reasons for writing loadable modules for polypaudio:

      -
    • Device driver support in addition to ALSA/OSS
    • +
    • Extended device driver support
    • Protocol support beyond ESOUND's protocol and the native protocol. (such as NAS or a subset of aRts)
    • New programming interfaces such as XMLRPC or DBUS for controlling the daemon.
    • Hooking audio event sources directly into polypaudio (similar to module-x11-bell)
    • @@ -326,7 +330,7 @@ compilation and make install (as root) for installation of

      Please report bugs to our Trac ticket system.


      -
      Lennart Poettering <@PACKAGE_BUGREPORT@>, April 2006
      +
      Lennart Poettering <@PACKAGE_BUGREPORT@>, May 2006
      $Id$
      From 0796ead0db250f6a46a7531c9db471592ed6e129 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 06:45:43 +0000 Subject: [PATCH 0831/1514] Move timeval calculation functions into their own file. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@926 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doxygen/doxygen.conf.in | 2 +- src/Makefile.am | 6 +- src/modules/module-combine.c | 1 + src/modules/module-null-sink.c | 1 + src/modules/module-tunnel.c | 1 + src/modules/rtp/module-rtp-recv.c | 1 + src/modules/rtp/module-rtp-send.c | 1 + src/polyp/glib12-mainloop.c | 1 + src/polyp/mainloop.c | 1 + src/polyp/polypaudio.h | 4 +- src/polyp/timeval.c | 142 ++++++++++++++++++++++++++++++ src/polyp/timeval.h | 53 +++++++++++ src/polyp/util.c | 136 +++------------------------- src/polyp/util.h | 22 +---- src/polypcore/core-scache.c | 1 + src/polypcore/core.c | 1 + src/polypcore/module.c | 1 + src/polypcore/pdispatch.c | 1 + src/polypcore/protocol-esound.c | 1 + src/polypcore/protocol-native.c | 1 + src/polypcore/socket-client.c | 1 + src/tests/mainloop-test.c | 2 + src/tests/thread-mainloop-test.c | 2 + 23 files changed, 234 insertions(+), 149 deletions(-) create mode 100644 src/polyp/timeval.c create mode 100644 src/polyp/timeval.h diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 3d7ad3222..f466c9d47 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h ../src/polyp/thread-mainloop.h ../src/polyp/xmalloc.h ../src/polyp/utf8.h ../src/polyp/util.h +INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h ../src/polyp/thread-mainloop.h ../src/polyp/xmalloc.h ../src/polyp/utf8.h ../src/polyp/util.h ../src/polyp/timeval.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/src/Makefile.am b/src/Makefile.am index e7ad2fd4a..b0401e650 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -351,6 +351,7 @@ libpolyp_la_SOURCES = \ polyp/stream.c polyp/stream.h \ polyp/subscribe.c polyp/subscribe.h \ polyp/sample.c polyp/sample.h \ + polyp/timeval.c polyp/timeval.h \ polyp/volume.c polyp/volume.h \ polyp/utf8.c polyp/utf8.h \ polyp/mainloop.c polyp/mainloop.h \ @@ -493,9 +494,10 @@ libpolypcore_la_SOURCES = \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ polyp/sample.c polyp/sample.h \ polyp/volume.c polyp/volume.h \ + polyp/timeval.c polyp/timeval.h \ polyp/utf8.c polyp/utf8.h \ - polyp/xmalloc.c polyp/xmalloc.h \ - polyp/util.c polyp/util.h + polyp/util.c polyp/util.h \ + polyp/xmalloc.c polyp/xmalloc.h # Pure core stuff (some are shared in libpolyp though). libpolypcore_la_SOURCES += \ diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 5047fc306..037cbaf71 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -26,6 +26,7 @@ #include #include +#include #include #include diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 78850011c..a1555e672 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -33,6 +33,7 @@ #include #include +#include #include #include diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 81c322879..758d1bd6e 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -31,6 +31,7 @@ #include #include +#include #include #include diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index a1196a2d3..56fc91ef1 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -31,6 +31,7 @@ #include #include +#include #include #include diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index a88ea76af..4ca2b1e62 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -32,6 +32,7 @@ #include #include +#include #include #include diff --git a/src/polyp/glib12-mainloop.c b/src/polyp/glib12-mainloop.c index f7459f192..dfd6ff2f1 100644 --- a/src/polyp/glib12-mainloop.c +++ b/src/polyp/glib12-mainloop.c @@ -25,6 +25,7 @@ #include +#include #include #include diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 8f44c180c..6b5b3b252 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -44,6 +44,7 @@ #include "../polypcore/pipe.h" #endif +#include #include #include diff --git a/src/polyp/polypaudio.h b/src/polyp/polypaudio.h index 51e3f9703..c172315b2 100644 --- a/src/polyp/polypaudio.h +++ b/src/polyp/polypaudio.h @@ -41,6 +41,7 @@ #include #include #include +#include /** \file * Include all polyplib header files at once. The following @@ -48,7 +49,8 @@ * \ref context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h, * \ref scache.h, \ref version.h, \ref error.h, \ref channelmap.h, * \ref operation.h,\ref volume.h, \ref xmalloc.h, \ref utf8.h, \ref - * thread-mainloop.h, \ref mainloop.h, \ref util.h and \ref mainloop-signal.h at once */ + * thread-mainloop.h, \ref mainloop.h, \ref util.h, \ref timeval.h and + * \ref mainloop-signal.h at once */ /** \mainpage * diff --git a/src/polyp/timeval.c b/src/polyp/timeval.c new file mode 100644 index 000000000..6043d7fd2 --- /dev/null +++ b/src/polyp/timeval.c @@ -0,0 +1,142 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#ifdef HAVE_WINDOWS_H +#include +#endif + +#include "../polypcore/winsock.h" + +#include "timeval.h" + +struct timeval *pa_gettimeofday(struct timeval *tv) { +#ifdef HAVE_GETTIMEOFDAY + assert(tv); + + return gettimeofday(tv, NULL) < 0 ? NULL : tv; +#elif defined(OS_IS_WIN32) + /* + * Copied from implementation by Steven Edwards (LGPL). + * Found on wine mailing list. + */ + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define EPOCHFILETIME (116444736000000000i64) +#else +#define EPOCHFILETIME (116444736000000000LL) +#endif + + FILETIME ft; + LARGE_INTEGER li; + __int64 t; + + assert(tv); + + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + t = li.QuadPart; /* In 100-nanosecond intervals */ + t -= EPOCHFILETIME; /* Offset to the Epoch time */ + t /= 10; /* In microseconds */ + tv->tv_sec = (long)(t / 1000000); + tv->tv_usec = (long)(t % 1000000); + + return tv; +#else +#error "Platform lacks gettimeofday() or equivalent function." +#endif +} + +pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { + pa_usec_t r; + assert(a && b); + + /* Check which whan is the earlier time and swap the two arguments if reuqired. */ + if (pa_timeval_cmp(a, b) < 0) { + const struct timeval *c; + c = a; + a = b; + b = c; + } + + /* Calculate the second difference*/ + r = ((pa_usec_t) a->tv_sec - b->tv_sec)* 1000000; + + /* Calculate the microsecond difference */ + if (a->tv_usec > b->tv_usec) + r += ((pa_usec_t) a->tv_usec - b->tv_usec); + else if (a->tv_usec < b->tv_usec) + r -= ((pa_usec_t) b->tv_usec - a->tv_usec); + + return r; +} + +int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { + assert(a && b); + + if (a->tv_sec < b->tv_sec) + return -1; + + if (a->tv_sec > b->tv_sec) + return 1; + + if (a->tv_usec < b->tv_usec) + return -1; + + if (a->tv_usec > b->tv_usec) + return 1; + + return 0; +} + +pa_usec_t pa_timeval_age(const struct timeval *tv) { + struct timeval now; + assert(tv); + + return pa_timeval_diff(pa_gettimeofday(&now), tv); +} + +struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) { + unsigned long secs; + assert(tv); + + secs = (v/1000000); + tv->tv_sec += (unsigned long) secs; + v -= secs*1000000; + + tv->tv_usec += v; + + /* Normalize */ + while (tv->tv_usec >= 1000000) { + tv->tv_sec++; + tv->tv_usec -= 1000000; + } + + return tv; +} diff --git a/src/polyp/timeval.h b/src/polyp/timeval.h new file mode 100644 index 000000000..9990d4cae --- /dev/null +++ b/src/polyp/timeval.h @@ -0,0 +1,53 @@ +#ifndef footimevalhfoo +#define footimevalhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +/** \file + * Utility functions for handling timeval calculations */ + +PA_C_DECL_BEGIN + +struct timeval; + +/** Return the current timestamp, just like UNIX gettimeofday() */ +struct timeval *pa_gettimeofday(struct timeval *tv); + +/** Calculate the difference between the two specified timeval + * structs. */ +pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); + +/** Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */ +int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); + +/** Return the time difference between now and the specified timestamp */ +pa_usec_t pa_timeval_age(const struct timeval *tv); + +/** Add the specified time inmicroseconds to the specified timeval structure */ +struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v); + +PA_C_DECL_END + +#endif diff --git a/src/polyp/util.c b/src/polyp/util.c index 76b5c9b97..dcebff595 100644 --- a/src/polyp/util.c +++ b/src/polyp/util.c @@ -23,39 +23,33 @@ #include #endif -#include -#include -#include -#include #include -#include +#include #include -#include -#include -#include +#include +#include #include -#include +#include #include -#include -#include - -#ifdef HAVE_NETDB_H -#include -#endif #ifdef HAVE_PWD_H #include #endif -#ifdef HAVE_GRP_H -#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETDB_H +#include #endif #ifdef HAVE_WINDOWS_H #include #endif -#include +#include "../polypcore/winsock.h" + #include #include @@ -154,112 +148,6 @@ char *pa_get_home_dir(char *s, size_t l) { #endif } -struct timeval *pa_gettimeofday(struct timeval *tv) { -#ifdef HAVE_GETTIMEOFDAY - assert(tv); - - return gettimeofday(tv, NULL) < 0 ? NULL : tv; -#elif defined(OS_IS_WIN32) - /* - * Copied from implementation by Steven Edwards (LGPL). - * Found on wine mailing list. - */ - -#if defined(_MSC_VER) || defined(__BORLANDC__) -#define EPOCHFILETIME (116444736000000000i64) -#else -#define EPOCHFILETIME (116444736000000000LL) -#endif - - FILETIME ft; - LARGE_INTEGER li; - __int64 t; - - assert(tv); - - GetSystemTimeAsFileTime(&ft); - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - t = li.QuadPart; /* In 100-nanosecond intervals */ - t -= EPOCHFILETIME; /* Offset to the Epoch time */ - t /= 10; /* In microseconds */ - tv->tv_sec = (long)(t / 1000000); - tv->tv_usec = (long)(t % 1000000); - - return tv; -#else -#error "Platform lacks gettimeofday() or equivalent function." -#endif -} - -pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { - pa_usec_t r; - assert(a && b); - - /* Check which whan is the earlier time and swap the two arguments if reuqired. */ - if (pa_timeval_cmp(a, b) < 0) { - const struct timeval *c; - c = a; - a = b; - b = c; - } - - /* Calculate the second difference*/ - r = ((pa_usec_t) a->tv_sec - b->tv_sec)* 1000000; - - /* Calculate the microsecond difference */ - if (a->tv_usec > b->tv_usec) - r += ((pa_usec_t) a->tv_usec - b->tv_usec); - else if (a->tv_usec < b->tv_usec) - r -= ((pa_usec_t) b->tv_usec - a->tv_usec); - - return r; -} - -int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { - assert(a && b); - - if (a->tv_sec < b->tv_sec) - return -1; - - if (a->tv_sec > b->tv_sec) - return 1; - - if (a->tv_usec < b->tv_usec) - return -1; - - if (a->tv_usec > b->tv_usec) - return 1; - - return 0; -} - -pa_usec_t pa_timeval_age(const struct timeval *tv) { - struct timeval now; - assert(tv); - - return pa_timeval_diff(pa_gettimeofday(&now), tv); -} - -struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) { - unsigned long secs; - assert(tv); - - secs = (v/1000000); - tv->tv_sec += (unsigned long) secs; - v -= secs*1000000; - - tv->tv_usec += v; - - /* Normalize */ - while (tv->tv_usec >= 1000000) { - tv->tv_sec++; - tv->tv_usec -= 1000000; - } - - return tv; -} - char *pa_get_binary_name(char *s, size_t l) { #ifdef HAVE_READLINK diff --git a/src/polyp/util.h b/src/polyp/util.h index 8bd03f98a..cd8aab0bd 100644 --- a/src/polyp/util.h +++ b/src/polyp/util.h @@ -22,10 +22,8 @@ USA. ***/ -#include -#include +#include -#include #include /** \file @@ -33,8 +31,6 @@ PA_C_DECL_BEGIN -struct timeval; - /** Return the current username in the specified string buffer. */ char *pa_get_user_name(char *s, size_t l); @@ -55,22 +51,6 @@ char *pa_get_binary_name(char *s, size_t l); * component). */ const char *pa_path_get_filename(const char *p); -/** Return the current timestamp, just like UNIX gettimeofday() */ -struct timeval *pa_gettimeofday(struct timeval *tv); - -/** Calculate the difference between the two specified timeval - * structs. */ -pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); - -/** Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */ -int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); - -/** Return the time difference between now and the specified timestamp */ -pa_usec_t pa_timeval_age(const struct timeval *tv); - -/** Add the specified time inmicroseconds to the specified timeval structure */ -struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v); - /** Wait t milliseconds */ int pa_msleep(unsigned long t); diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 068f2361d..1ee3361f8 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -43,6 +43,7 @@ #include #include +#include #include #include diff --git a/src/polypcore/core.c b/src/polypcore/core.c index 43f7015e0..09d023dce 100644 --- a/src/polypcore/core.c +++ b/src/polypcore/core.c @@ -28,6 +28,7 @@ #include #include +#include #include #include diff --git a/src/polypcore/module.c b/src/polypcore/module.c index 52cde9c39..0286bba85 100644 --- a/src/polypcore/module.c +++ b/src/polypcore/module.c @@ -30,6 +30,7 @@ #include #include +#include #include #include diff --git a/src/polypcore/pdispatch.c b/src/polypcore/pdispatch.c index 4b0d1bb27..c6f90bac4 100644 --- a/src/polypcore/pdispatch.c +++ b/src/polypcore/pdispatch.c @@ -27,6 +27,7 @@ #include #include +#include #include #include diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 98738728a..c11bdb21c 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -31,6 +31,7 @@ #include #include +#include #include #include diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index f0e50ec54..0a408c6d6 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index 4fb0a5d89..ec2f9a9e3 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -54,6 +54,7 @@ #include "winsock.h" +#include #include #include diff --git a/src/tests/mainloop-test.c b/src/tests/mainloop-test.c index 300884839..2936420c3 100644 --- a/src/tests/mainloop-test.c +++ b/src/tests/mainloop-test.c @@ -28,6 +28,8 @@ #include #include +#include + #include #include diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c index 676b8d37e..701444312 100644 --- a/src/tests/thread-mainloop-test.c +++ b/src/tests/thread-mainloop-test.c @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include From 9ec9d2873eaf2ffcfa4214858eaad814a297b502 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 06:46:27 +0000 Subject: [PATCH 0832/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@927 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 79b1894a4..98db8194e 100644 --- a/doc/todo +++ b/doc/todo @@ -25,6 +25,7 @@ Post 0.8: - iconv stuff sent from utils to server (UTF-8) - iconv stuff leaving the server (e.g. syslog). Sample loading probably needs help as well. +- Document utf8.h, timeval.h and util.h Long term: - pass meta info for hearing impaired From 3ee205141280ff4246f9fe40521f666b6d598fc5 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 06:53:54 +0000 Subject: [PATCH 0833/1514] PATH_MAX needs limits.h. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@928 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/polyp/util.c b/src/polyp/util.c index dcebff595..ed59a5c63 100644 --- a/src/polyp/util.c +++ b/src/polyp/util.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include From 24a781992bad4d66bb7bc3a2d1deeba7e959dbb1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 07:04:41 +0000 Subject: [PATCH 0834/1514] Don't include util.h from core-util.h as it is not needed by many users. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@929 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/dumpmodules.c | 3 ++- src/modules/module-tunnel.c | 1 + src/modules/rtp/module-rtp-send.c | 1 + src/polypcore/authkey.c | 1 + src/polypcore/core-scache.c | 1 + src/polypcore/core-util.h | 1 - src/polypcore/parseaddr.c | 1 + src/polypcore/protocol-native.c | 2 +- src/polypcore/socket-server.c | 1 + src/tests/thread-mainloop-test.c | 2 +- src/utils/pacmd.c | 2 ++ 11 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c index b6a3bb7cf..d56bb7980 100644 --- a/src/daemon/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -29,8 +29,9 @@ #include #include +#include + #include -#include #include "dumpmodules.h" diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 758d1bd6e..bf1fafb3d 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -32,6 +32,7 @@ #include #include +#include #include #include diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 4ca2b1e62..1372414cb 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -33,6 +33,7 @@ #include #include +#include #include #include diff --git a/src/polypcore/authkey.c b/src/polypcore/authkey.c index 1231c7a2b..aee54fd4b 100644 --- a/src/polypcore/authkey.c +++ b/src/polypcore/authkey.c @@ -35,6 +35,7 @@ #include #include +#include #include #include #include diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 1ee3361f8..5cb38beef 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include diff --git a/src/polypcore/core-util.h b/src/polypcore/core-util.h index d3db756fe..989f8c16a 100644 --- a/src/polypcore/core-util.h +++ b/src/polypcore/core-util.h @@ -28,7 +28,6 @@ #include #include -#include struct timeval; diff --git a/src/polypcore/parseaddr.c b/src/polypcore/parseaddr.c index b2c7d1c7d..d0687b05e 100644 --- a/src/polypcore/parseaddr.c +++ b/src/polypcore/parseaddr.c @@ -29,6 +29,7 @@ #include +#include #include #include "parseaddr.h" diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 0a408c6d6..a300c45df 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -46,7 +47,6 @@ #include #include #include -#include #include #include #include diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index 96f8e0733..592b6a630 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -63,6 +63,7 @@ #include "winsock.h" #include +#include #include #include diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c index 701444312..aef3aff05 100644 --- a/src/tests/thread-mainloop-test.c +++ b/src/tests/thread-mainloop-test.c @@ -29,9 +29,9 @@ #include #include +#include #include -#include #include static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index fefe76349..539d205e2 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -32,6 +32,8 @@ #include #include +#include + #include #include #include From 40d9f5d00d99d55d3dbb20801c4842ae8d0d95ac Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 07:07:27 +0000 Subject: [PATCH 0835/1514] Missing include of util.h. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@930 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-http.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/polypcore/protocol-http.c b/src/polypcore/protocol-http.c index 68864237e..86ea3b155 100644 --- a/src/polypcore/protocol-http.c +++ b/src/polypcore/protocol-http.c @@ -28,6 +28,7 @@ #include #include +#include #include #include From 4981092a797c18c1be8f2d5e0864c8b30f4130a0 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 08:19:07 +0000 Subject: [PATCH 0836/1514] And functions for convertion to and from current locale and UTF-8. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@931 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- src/polyp/utf8.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ src/polyp/utf8.h | 6 ++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 18332405f..9974c29c5 100644 --- a/configure.ac +++ b/configure.ac @@ -156,7 +156,7 @@ AM_CONDITIONAL(OS_IS_WIN32, test "x$os_is_win32" = "x1") AC_HEADER_STDC # POSIX -AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \ +AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h iconv.h netdb.h netinet/in.h \ netinet/in_systm.h netinet/ip.h netinet/tcp.h pwd.h sched.h \ sys/resource.h sys/select.h sys/socket.h sys/wait.h \ syslog.h]) diff --git a/src/polyp/utf8.c b/src/polyp/utf8.c index 300a54caf..931328e50 100644 --- a/src/polyp/utf8.c +++ b/src/polyp/utf8.c @@ -29,10 +29,15 @@ #endif #include +#include #include #include #include +#ifdef HAVE_ICONV_H +#include +#endif + #include "utf8.h" #include "xmalloc.h" @@ -162,3 +167,70 @@ char* pa_utf8_filter (const char *str) { return utf8_validate(str, new_str); } + +#ifdef HAVE_ICONV_H + +static char* iconv_simple(const char *str, const char *to, const char *from) { + char *new_str; + size_t len, inlen; + + iconv_t cd; + char *inbuf, *outbuf; + size_t res, inbytes, outbytes; + + cd = iconv_open(to, from); + if (cd == (iconv_t)-1) + return NULL; + + inlen = len = strlen(str) + 1; + new_str = pa_xmalloc(len); + assert(new_str); + + while (1) { + inbuf = (char*)str; /* Brain dead prototype for iconv() */ + inbytes = inlen; + outbuf = new_str; + outbytes = len; + + res = iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes); + + if (res != (size_t)-1) + break; + + if (errno != E2BIG) { + pa_xfree(new_str); + new_str = NULL; + break; + } + + assert(inbytes != 0); + + len += inbytes; + new_str = pa_xrealloc(new_str, len); + assert(new_str); + } + + iconv_close(cd); + + return new_str; +} + +char* pa_utf8_to_locale (const char *str) { + return iconv_simple(str, "", "UTF-8"); +} + +char* pa_locale_to_utf8 (const char *str) { + return iconv_simple(str, "UTF-8", ""); +} + +#else + +char* pa_utf8_to_locale (const char *str) { + return NULL; +} + +char* pa_locale_to_utf8 (const char *str) { + return NULL; +} + +#endif diff --git a/src/polyp/utf8.h b/src/polyp/utf8.h index 3cc3a7d08..55b8d2e49 100644 --- a/src/polyp/utf8.h +++ b/src/polyp/utf8.h @@ -36,6 +36,12 @@ const char *pa_utf8_valid(const char *str); /** Filter all invalid UTF8 characters from the specified string, returning a new fully UTF8 valid string. Don't forget to free the returned string with pa_xfree() */ char *pa_utf8_filter(const char *str); +/** Convert a UTF-8 string to the current locale. Free the string using pa_xfree(). */ +char* pa_utf8_to_locale (const char *str); + +/** Convert a string in the current locale to UTF-8. Free the string using pa_xfree(). */ +char* pa_locale_to_utf8 (const char *str); + PA_C_DECL_END #endif From 83591883d8bcec475e74881b3f9cbcb84900c7ec Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 08:21:41 +0000 Subject: [PATCH 0837/1514] Make paplay convert names to UTF-8 before sending to the server. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@932 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/paplay.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/utils/paplay.c b/src/utils/paplay.c index b66c13da5..effc2a111 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -236,6 +237,8 @@ int main(int argc, char *argv[]) { {NULL, 0, NULL, 0} }; + setlocale(LC_ALL, ""); + if (!(bn = strrchr(argv[0], '/'))) bn = argv[0]; else @@ -348,12 +351,23 @@ int main(int argc, char *argv[]) { goto quit; } - if (!client_name) - client_name = pa_xstrdup(bn); + if (!client_name) { + client_name = pa_locale_to_utf8(bn); + if (!client_name) + client_name = pa_utf8_filter(bn); + } if (!stream_name) { - const char *n = sf_get_string(sndfile, SF_STR_TITLE); - stream_name = pa_xstrdup(n ? n : filename); + const char *n; + + n = sf_get_string(sndfile, SF_STR_TITLE); + + if (!n) + n = filename; + + stream_name = pa_locale_to_utf8(n); + if (!stream_name) + stream_name = pa_utf8_filter(n); } if (verbose) { From 13798312efde92a618a024064b1b2f2f69dfddaa Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 10:36:36 +0000 Subject: [PATCH 0838/1514] Convert log text to current locale before passing it on to stderr or syslog. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@933 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 3 +++ src/polypcore/log.c | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 9b9ea1800..b4bc4e009 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -161,6 +162,8 @@ int main(int argc, char *argv[]) { struct timeval tv; #endif + setlocale(LC_ALL, ""); + pa_limit_caps(); #ifdef HAVE_GETUID diff --git a/src/polypcore/log.c b/src/polypcore/log.c index 3f5dfa086..ce9df1a97 100644 --- a/src/polypcore/log.c +++ b/src/polypcore/log.c @@ -33,6 +33,7 @@ #include #endif +#include #include #include @@ -41,7 +42,7 @@ #define ENV_LOGLEVEL "POLYP_LOG" -static char *log_ident = NULL; +static char *log_ident = NULL, *log_ident_local = NULL; static pa_log_target_t log_target = PA_LOG_STDERR; static void (*user_log_func)(pa_log_level_t l, const char *s) = NULL; static pa_log_level_t maximal_level = PA_LOG_NOTICE; @@ -59,8 +60,13 @@ static const int level_to_syslog[] = { void pa_log_set_ident(const char *p) { if (log_ident) pa_xfree(log_ident); + if (log_ident_local) + pa_xfree(log_ident_local); log_ident = pa_xstrdup(p); + log_ident_local = pa_utf8_to_locale(log_ident); + if (!log_ident_local) + log_ident_local = pa_xstrdup(log_ident); } void pa_log_set_maximal_level(pa_log_level_t l) { @@ -100,6 +106,7 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { switch (log_target) { case PA_LOG_STDERR: { const char *prefix = "", *suffix = ""; + char *local_t; #ifndef OS_IS_WIN32 /* Yes indeed. Useless, but fun! */ @@ -114,16 +121,34 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { } #endif - fprintf(stderr, "%s%s%s\n", prefix, t, suffix); + local_t = pa_utf8_to_locale(t); + if (!local_t) + fprintf(stderr, "%s%s%s\n", prefix, t, suffix); + else { + fprintf(stderr, "%s%s%s\n", prefix, local_t, suffix); + pa_xfree(local_t); + } + break; } #ifdef HAVE_SYSLOG_H - case PA_LOG_SYSLOG: - openlog(log_ident ? log_ident : "???", LOG_PID, LOG_USER); - syslog(level_to_syslog[level], "%s", t); + case PA_LOG_SYSLOG: { + char *local_t; + + openlog(log_ident_local ? log_ident_local : "???", LOG_PID, LOG_USER); + + local_t = pa_utf8_to_locale(t); + if (!local_t) + syslog(level_to_syslog[level], "%s", t); + else { + syslog(level_to_syslog[level], "%s", local_t); + pa_xfree(local_t); + } + closelog(); break; + } #endif case PA_LOG_USER: From 1dfe8f83408d30837e8af7a1bc005c04dde2cc76 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 18 May 2006 10:36:50 +0000 Subject: [PATCH 0839/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@934 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/todo b/doc/todo index 98db8194e..80658d23e 100644 --- a/doc/todo +++ b/doc/todo @@ -26,6 +26,8 @@ Post 0.8: - iconv stuff leaving the server (e.g. syslog). Sample loading probably needs help as well. - Document utf8.h, timeval.h and util.h +- strerror() needs to be wrapped as it returns stuff in the current locale + and we tend to pass it to functions that require UTF-8. Long term: - pass meta info for hearing impaired From c811351d2823f1bad06050ef019930685c0d0c28 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 19 May 2006 07:29:34 +0000 Subject: [PATCH 0840/1514] Sort source files. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@935 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 58 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index b0401e650..5d7fde18d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -288,27 +288,27 @@ sync_playback_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) polypinclude_HEADERS = \ polyp/cdecl.h \ polyp/channelmap.h \ - polyp/glib-mainloop.h \ - polyp/mainloop.h \ - polyp/mainloop-api.h \ - polyp/mainloop-signal.h \ - polyp/thread-mainloop.h \ - polyp/polypaudio.h \ polyp/context.h \ polyp/def.h \ polyp/error.h \ + polyp/glib-mainloop.h \ polyp/introspect.h \ + polyp/mainloop.h \ + polyp/mainloop-api.h \ + polyp/mainloop-signal.h \ polyp/operation.h \ + polyp/polypaudio.h \ + polyp/sample.h \ polyp/scache.h \ polyp/simple.h \ polyp/stream.h \ polyp/subscribe.h \ - polyp/version.h \ - polyp/sample.h \ + polyp/thread-mainloop.h \ polyp/utf8.h \ + polyp/util.h \ + polyp/version.h \ polyp/volume.h \ - polyp/xmalloc.h \ - polyp/util.h + polyp/xmalloc.h if HAVE_HOWL polypinclude_HEADERS += \ @@ -339,36 +339,38 @@ libpolyp_la_SOURCES = \ polyp/cdecl.h \ polyp/channelmap.c polyp/channelmap.h \ polyp/client-conf.c polyp/client-conf.h \ - polyp/mainloop-api.c polyp/mainloop-api.h \ - polyp/polypaudio.h \ polyp/context.c polyp/context.h \ polyp/def.h \ polyp/error.c polyp/error.h \ polyp/internal.h \ polyp/introspect.c polyp/introspect.h \ + polyp/mainloop.c polyp/mainloop.h \ + polyp/mainloop-api.c polyp/mainloop-api.h \ + polyp/mainloop-signal.c polyp/mainloop-signal.h \ polyp/operation.c polyp/operation.h \ + polyp/polypaudio.h \ + polyp/sample.c polyp/sample.h \ polyp/scache.c polyp/scache.h \ polyp/stream.c polyp/stream.h \ polyp/subscribe.c polyp/subscribe.h \ - polyp/sample.c polyp/sample.h \ - polyp/timeval.c polyp/timeval.h \ - polyp/volume.c polyp/volume.h \ - polyp/utf8.c polyp/utf8.h \ - polyp/mainloop.c polyp/mainloop.h \ - polyp/mainloop-signal.c polyp/mainloop-signal.h \ polyp/thread-mainloop.c polyp/thread-mainloop.h \ - polyp/xmalloc.c polyp/xmalloc.h \ - polyp/util.c polyp/util.h + polyp/timeval.c polyp/timeval.h \ + polyp/utf8.c polyp/utf8.h \ + polyp/util.c polyp/util.h \ + polyp/volume.c polyp/volume.h \ + polyp/xmalloc.c polyp/xmalloc.h # Internal stuff that is shared with libpolypcore libpolyp_la_SOURCES += \ polypcore/authkey.c polypcore/authkey.h \ polypcore/conf-parser.c polypcore/conf-parser.h \ + polypcore/core-util.c polypcore/core-util.h \ polypcore/dynarray.c polypcore/dynarray.h \ polypcore/gccmacro.h \ polypcore/hashmap.c polypcore/hashmap.h \ polypcore/idxset.c polypcore/idxset.h \ polypcore/iochannel.c polypcore/iochannel.h \ + polypcore/llist.h \ polypcore/log.c polypcore/log.h \ polypcore/mcalign.c polypcore/mcalign.h \ polypcore/memblock.c polypcore/memblock.h \ @@ -378,6 +380,8 @@ libpolyp_la_SOURCES += \ polypcore/packet.c polypcore/packet.h \ polypcore/parseaddr.c polypcore/parseaddr.h \ polypcore/pdispatch.c polypcore/pdispatch.h \ + polypcore/pipe.c polypcore/pipe.h \ + polypcore/poll.c polypcore/poll.h \ polypcore/pstream.c polypcore/pstream.h \ polypcore/pstream-util.c polypcore/pstream-util.h \ polypcore/queue.c polypcore/queue.h \ @@ -387,11 +391,7 @@ libpolyp_la_SOURCES += \ polypcore/strbuf.c polypcore/strbuf.h \ polypcore/strlist.c polypcore/strlist.h \ polypcore/tagstruct.c polypcore/tagstruct.h \ - polypcore/core-util.c polypcore/core-util.h \ - polypcore/winsock.h \ - polypcore/llist.h \ - polypcore/pipe.c polypcore/pipe.h \ - polypcore/poll.c polypcore/poll.h + polypcore/winsock.h if OS_IS_WIN32 libpolyp_la_SOURCES += \ @@ -452,6 +452,7 @@ polypcoreinclude_HEADERS = \ polypcore/core-scache.h \ polypcore/core-subscribe.h \ polypcore/conf-parser.h \ + polypcore/core-util.h \ polypcore/dynarray.h \ polypcore/g711.h \ polypcore/hashmap.h \ @@ -481,8 +482,7 @@ polypcoreinclude_HEADERS = \ polypcore/source.h \ polypcore/source-output.h \ polypcore/strbuf.h \ - polypcore/tokenizer.h \ - polypcore/core-util.h + polypcore/tokenizer.h lib_LTLIBRARIES += libpolypcore.la @@ -493,10 +493,10 @@ libpolypcore_la_SOURCES = \ polyp/mainloop-api.c polyp/mainloop-api.h \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ polyp/sample.c polyp/sample.h \ - polyp/volume.c polyp/volume.h \ polyp/timeval.c polyp/timeval.h \ polyp/utf8.c polyp/utf8.h \ polyp/util.c polyp/util.h \ + polyp/volume.c polyp/volume.h \ polyp/xmalloc.c polyp/xmalloc.h # Pure core stuff (some are shared in libpolyp though). @@ -509,6 +509,7 @@ libpolypcore_la_SOURCES += \ polypcore/core.c polypcore/core.h \ polypcore/core-scache.c polypcore/core-scache.h \ polypcore/core-subscribe.c polypcore/core-subscribe.h \ + polypcore/core-util.c polypcore/core-util.h \ polypcore/dynarray.c polypcore/dynarray.h \ polypcore/endianmacros.h \ polypcore/g711.c polypcore/g711.h \ @@ -544,7 +545,6 @@ libpolypcore_la_SOURCES += \ polypcore/source-output.c polypcore/source-output.h \ polypcore/strbuf.c polypcore/strbuf.h \ polypcore/tokenizer.c polypcore/tokenizer.h \ - polypcore/core-util.c polypcore/core-util.h \ polypcore/winsock.h if OS_IS_WIN32 From a034b61eb5a9bd897349be425b28c42b87f63d65 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 19 May 2006 07:38:35 +0000 Subject: [PATCH 0841/1514] Fix which headers get installed for libpolyp. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@936 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 5d7fde18d..e93210aaf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -291,7 +291,6 @@ polypinclude_HEADERS = \ polyp/context.h \ polyp/def.h \ polyp/error.h \ - polyp/glib-mainloop.h \ polyp/introspect.h \ polyp/mainloop.h \ polyp/mainloop-api.h \ @@ -304,6 +303,7 @@ polypinclude_HEADERS = \ polyp/stream.h \ polyp/subscribe.h \ polyp/thread-mainloop.h \ + polyp/timeval.h \ polyp/utf8.h \ polyp/util.h \ polyp/version.h \ @@ -315,6 +315,16 @@ polypinclude_HEADERS += \ polyp/browser.h endif +if HAVE_GLIB20 +polypinclude_HEADERS += \ + polyp/glib-mainloop.h +else +if HAVE_GLIB12 +polypinclude_HEADERS += \ + polyp/glib-mainloop.h +endif +endif + lib_LTLIBRARIES = \ libpolyp.la \ libpolyp-simple.la From a3fe39ac4168d9521dc12c8e27eb8040ff078f5e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 19 May 2006 11:32:32 +0000 Subject: [PATCH 0842/1514] Fix some missing headers. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@937 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-x11-publish.c | 1 + src/polyp/stream.c | 2 +- src/utils/pax11publish.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index eddcb3b80..70d750384 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -32,6 +32,7 @@ #include #include +#include #include #include diff --git a/src/polyp/stream.c b/src/polyp/stream.c index ad6c9e43c..2e1680452 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -29,10 +29,10 @@ #include #include +#include #include #include -#include #include #include diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index ee0cb8452..668361c6f 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -31,6 +31,8 @@ #include #include +#include + #include #include #include From acc655235663f223f10bd26c6e6d1ebc6331d9bd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 May 2006 17:40:44 +0000 Subject: [PATCH 0843/1514] generate PA_MAJORMINOR properly - only from major and minor, not from micro git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@938 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 9974c29c5..445e26be3 100644 --- a/configure.ac +++ b/configure.ac @@ -20,12 +20,17 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) -AC_INIT([polypaudio],[0.9.0],[mzcbylcnhqvb (at) 0pointer (dot) de]) + +m4_define(PA_MAJOR, [0]) +m4_define(PA_MINOR, [9]) +m4_define(PA_MICRO, [0]) + +AC_INIT([polypaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) -AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION") +AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) AC_SUBST(PA_API_VERSION, 9) From cc61b57a325ee688b74ca2cbd5e281e7f76b71c0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 20 May 2006 14:59:02 +0000 Subject: [PATCH 0844/1514] rename pa_simple_get_playback_latency() to pa_simple_get_latency() and allow its usage on capture streams git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@939 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/simple.c | 4 +--- src/polyp/simple.h | 2 +- src/tests/pacat-simple.c | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/polyp/simple.c b/src/polyp/simple.c index 84c46bf1c..9c2c908c9 100644 --- a/src/polyp/simple.c +++ b/src/polyp/simple.c @@ -423,14 +423,12 @@ unlock_and_fail: return -1; } -pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) { +pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) { pa_usec_t t; int negative; assert(p); - CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, (pa_usec_t) -1); - pa_threaded_mainloop_lock(p->mainloop); for (;;) { diff --git a/src/polyp/simple.h b/src/polyp/simple.h index bf3cc330a..b97e844b0 100644 --- a/src/polyp/simple.h +++ b/src/polyp/simple.h @@ -136,7 +136,7 @@ int pa_simple_drain(pa_simple *s, int *error); int pa_simple_read(pa_simple *s, void*data, size_t length, int *error); /** Return the playback latency. \since 0.5 */ -pa_usec_t pa_simple_get_playback_latency(pa_simple *s, int *error); +pa_usec_t pa_simple_get_latency(pa_simple *s, int *error); /** Flush the playback buffer. \since 0.5 */ int pa_simple_flush(pa_simple *s, int *error); diff --git a/src/tests/pacat-simple.c b/src/tests/pacat-simple.c index 544c31e38..9d8cc9215 100644 --- a/src/tests/pacat-simple.c +++ b/src/tests/pacat-simple.c @@ -78,8 +78,8 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { #if 0 pa_usec_t latency; - if ((latency = pa_simple_get_playback_latency(s, &error)) == (pa_usec_t) -1) { - fprintf(stderr, __FILE__": pa_simple_get_playback_latency() failed: %s\n", pa_strerror(error)); + if ((latency = pa_simple_get_latency(s, &error)) == (pa_usec_t) -1) { + fprintf(stderr, __FILE__": pa_simple_get_latency() failed: %s\n", pa_strerror(error)); goto finish; } From 13329d36dfb5950c5917ab4b6d0939e7ae1100a0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 20 May 2006 15:00:16 +0000 Subject: [PATCH 0845/1514] fix long-standing buf that could cause polypaudio to eat 100% CPU: fix handling of event bits for pa_iochannel git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@940 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/iochannel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index b953a1d08..10997d623 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -69,17 +69,17 @@ static void enable_mainloop_sources(pa_iochannel *io) { pa_io_event_flags_t f = PA_IO_EVENT_NULL; assert(io->input_event); - if (!pa_iochannel_is_readable(io)) + if (!io->readable) f |= PA_IO_EVENT_INPUT; - if (!pa_iochannel_is_writable(io)) + if (!io->writable) f |= PA_IO_EVENT_OUTPUT; io->mainloop->io_enable(io->input_event, f); } else { if (io->input_event) - io->mainloop->io_enable(io->input_event, pa_iochannel_is_readable(io) ? PA_IO_EVENT_NULL : PA_IO_EVENT_INPUT); + io->mainloop->io_enable(io->input_event, io->readable ? PA_IO_EVENT_NULL : PA_IO_EVENT_INPUT); if (io->output_event) - io->mainloop->io_enable(io->output_event, pa_iochannel_is_writable(io) ? PA_IO_EVENT_NULL : PA_IO_EVENT_OUTPUT); + io->mainloop->io_enable(io->output_event, io->writable ? PA_IO_EVENT_NULL : PA_IO_EVENT_OUTPUT); } } From bc87137a8f26152a0589e94e0bc8ffc936566ed6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 20 May 2006 19:27:47 +0000 Subject: [PATCH 0846/1514] doc update git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@941 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index 80658d23e..c2d20a05c 100644 --- a/doc/todo +++ b/doc/todo @@ -28,6 +28,7 @@ Post 0.8: - Document utf8.h, timeval.h and util.h - strerror() needs to be wrapped as it returns stuff in the current locale and we tend to pass it to functions that require UTF-8. +- fix clock of the NULL sink Long term: - pass meta info for hearing impaired From 651e575575c307be75e050ed9600d35a43b7819c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 May 2006 14:06:33 +0000 Subject: [PATCH 0847/1514] add new function pa_usec_to_bytes() as inverse of pa_bytes_to_usec() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@942 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/sample.c | 6 ++++++ src/polyp/sample.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/polyp/sample.c b/src/polyp/sample.c index 668a485ed..320e31a05 100644 --- a/src/polyp/sample.c +++ b/src/polyp/sample.c @@ -66,6 +66,12 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) { return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate); } +size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) { + assert(spec); + + return ((double) t * spec->rate / 1000000)*pa_frame_size(spec); +} + int pa_sample_spec_valid(const pa_sample_spec *spec) { assert(spec); diff --git a/src/polyp/sample.h b/src/polyp/sample.h index 09b12fd79..2a9a72fef 100644 --- a/src/polyp/sample.h +++ b/src/polyp/sample.h @@ -160,6 +160,9 @@ size_t pa_sample_size(const pa_sample_spec *spec); /** Calculate the time the specified bytes take to play with the specified sample type */ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec); +/** Calculates the number of bytes that are required for the specified time. \since 0.9 */ +size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec); + /** Return non-zero when the sample type specification is valid */ int pa_sample_spec_valid(const pa_sample_spec *spec); From cc84fc9e942daabe940dff20c7b46bfb132a2d22 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 May 2006 14:06:51 +0000 Subject: [PATCH 0848/1514] add missing #include git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@943 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/glib-mainloop.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/polyp/glib-mainloop.c b/src/polyp/glib-mainloop.c index 51d437d22..d5fce7671 100644 --- a/src/polyp/glib-mainloop.c +++ b/src/polyp/glib-mainloop.c @@ -26,6 +26,7 @@ #include #include +#include #include #include From bf09399d0e84c43fbae3d24b5c71dc8d85b62fe7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 22 May 2006 15:19:50 +0000 Subject: [PATCH 0849/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@944 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index c2d20a05c..bf3365aba 100644 --- a/doc/todo +++ b/doc/todo @@ -29,6 +29,7 @@ Post 0.8: - strerror() needs to be wrapped as it returns stuff in the current locale and we tend to pass it to functions that require UTF-8. - fix clock of the NULL sink +- gettextify polypaudio Long term: - pass meta info for hearing impaired From 4e3dc7ce68561c16254712d713b2ccd472b8afe7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 22 May 2006 15:20:46 +0000 Subject: [PATCH 0850/1514] Wrap strerror() in a function that makes it thread safe and converts the output to UTF-8. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@945 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 3 + src/Makefile.am | 1 + src/daemon/caps.c | 4 +- src/daemon/cpulimit.c | 4 +- src/daemon/daemon-conf.c | 3 +- src/daemon/main.c | 5 +- src/modules/module-alsa-source.c | 3 +- src/modules/module-detect.c | 7 +- src/modules/module-esound-compat-spawnfd.c | 4 +- src/modules/module-esound-compat-spawnpid.c | 4 +- src/modules/module-esound-sink.c | 11 +-- src/modules/module-jack-sink.c | 3 +- src/modules/module-jack-source.c | 3 +- src/modules/module-match.c | 3 +- src/modules/module-mmkbd-evdev.c | 13 +-- src/modules/module-oss-mmap.c | 29 +++---- src/modules/module-oss.c | 17 ++-- src/modules/module-pipe-sink.c | 7 +- src/modules/module-pipe-source.c | 7 +- src/modules/module-protocol-stub.c | 5 +- src/modules/module-solaris.c | 15 ++-- src/modules/module-volume-restore.c | 5 +- src/modules/oss-util.c | 20 ++--- src/modules/rtp/module-rtp-recv.c | 9 ++- src/modules/rtp/module-rtp-send.c | 11 +-- src/modules/rtp/rtp.c | 8 +- src/modules/rtp/sap.c | 9 ++- src/polyp/client-conf.c | 3 +- src/polyp/context.c | 7 +- src/polyp/error.c | 90 +++++++++++++++++++++ src/polyp/error.h | 6 ++ src/polyp/mainloop-signal.c | 5 +- src/polyp/mainloop.c | 3 +- src/polyp/util.c | 4 +- src/polypcore/authkey.c | 13 +-- src/polypcore/cli-command.c | 3 +- src/polypcore/conf-parser.c | 7 +- src/polypcore/core-scache.c | 5 +- src/polypcore/core-util.c | 31 ++++--- src/polypcore/iochannel.c | 3 +- src/polypcore/ioline.c | 5 +- src/polypcore/log.c | 3 + src/polypcore/pid.c | 25 ++++-- src/polypcore/protocol-esound.c | 13 +-- src/polypcore/protocol-simple.c | 5 +- src/polypcore/socket-client.c | 9 ++- src/polypcore/socket-server.c | 35 ++++---- src/polypcore/socket-util.c | 3 +- src/utils/pacmd.c | 15 ++-- 49 files changed, 337 insertions(+), 169 deletions(-) diff --git a/configure.ac b/configure.ac index 445e26be3..fadc02198 100644 --- a/configure.ac +++ b/configure.ac @@ -242,6 +242,9 @@ AC_CHECK_FUNCS([readlink]) # SUSv2 AC_CHECK_FUNCS([ctime_r usleep]) +# SUSv3 +AC_CHECK_FUNCS([strerror_r]) + # BSD AC_CHECK_FUNCS([lstat]) diff --git a/src/Makefile.am b/src/Makefile.am index e93210aaf..30e735129 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -499,6 +499,7 @@ lib_LTLIBRARIES += libpolypcore.la # Some public stuff is used even in the core. libpolypcore_la_SOURCES = \ polyp/channelmap.c polyp/channelmap.h \ + polyp/error.c polyp/error.h \ polyp/mainloop.c polyp/mainloop.h \ polyp/mainloop-api.c polyp/mainloop-api.h \ polyp/mainloop-signal.c polyp/mainloop-signal.h \ diff --git a/src/daemon/caps.c b/src/daemon/caps.c index 8740b7e8d..4942868c1 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -32,6 +32,8 @@ #include #endif +#include + #include #include "caps.h" @@ -110,7 +112,7 @@ int pa_drop_caps(void) { cap_clear(caps); if (cap_set_proc(caps) < 0) { - pa_log(__FILE__": failed to drop capabilities: %s", strerror(errno)); + pa_log(__FILE__": failed to drop capabilities: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index 699733847..2cc37be62 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -23,6 +23,8 @@ #include #endif +#include + #include #include @@ -169,7 +171,7 @@ int pa_cpu_limit_init(pa_mainloop_api *m) { /* Prepare the main loop pipe */ if (pipe(the_pipe) < 0) { - pa_log(__FILE__": pipe() failed: %s", strerror(errno)); + pa_log(__FILE__": pipe() failed: %s", pa_cstrerror(errno)); return -1; } diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 0f4fcb976..809769f8e 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -237,7 +238,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file, "r"); if (!f && errno != ENOENT) { - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, strerror(errno)); + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } diff --git a/src/daemon/main.c b/src/daemon/main.c index b4bc4e009..2fadd496c 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -50,6 +50,7 @@ #include "../polypcore/winsock.h" +#include #include #include #include @@ -286,7 +287,7 @@ int main(int argc, char *argv[]) { } if ((child = fork()) < 0) { - pa_log(__FILE__": fork() failed: %s", strerror(errno)); + pa_log(__FILE__": fork() failed: %s", pa_cstrerror(errno)); goto finish; } @@ -297,7 +298,7 @@ int main(int argc, char *argv[]) { daemon_pipe[1] = -1; if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval)) != sizeof(retval)) { - pa_log(__FILE__": read() failed: %s", strerror(errno)); + pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno)); retval = 1; } diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 654f3e493..c72b03224 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -34,6 +34,7 @@ #include +#include #include #include @@ -134,7 +135,7 @@ static void do_read(struct userdata *u) { continue; } - pa_log(__FILE__": snd_pcm_readi() failed: %s", strerror(-frames)); + pa_log(__FILE__": snd_pcm_readi() failed: %s", pa_cstrerror(-frames)); return; } diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 2edbea5ea..e4f2e3f97 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -56,7 +57,7 @@ static int detect_alsa(pa_core *c, int just_one) { if (!(f = fopen("/proc/asound/devices", "r"))) { if (errno != ENOENT) - pa_log_error(__FILE__": open(\"/proc/asound/devices\") failed: %s", strerror(errno)); + pa_log_error(__FILE__": open(\"/proc/asound/devices\") failed: %s", pa_cstrerror(errno)); return -1; } @@ -119,7 +120,7 @@ static int detect_oss(pa_core *c, int just_one) { !(f = fopen("/proc/asound/oss/sndstat", "r"))) { if (errno != ENOENT) - pa_log_error(__FILE__": failed to open OSS sndstat device: %s", strerror(errno)); + pa_log_error(__FILE__": failed to open OSS sndstat device: %s", pa_cstrerror(errno)); return -1; } @@ -175,7 +176,7 @@ static int detect_solaris(pa_core *c, int just_one) { if (stat(dev, &s) < 0) { if (errno != ENOENT) - pa_log_error(__FILE__": failed to open device %s: %s", dev, strerror(errno)); + pa_log_error(__FILE__": failed to open device %s: %s", dev, pa_cstrerror(errno)); return -1; } diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index bf89ca70f..f59e9e218 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -59,7 +61,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (pa_loop_write(fd, &x, sizeof(x)) != sizeof(x)) - pa_log(__FILE__": WARNING: write(%u, 1, 1) failed: %s", fd, strerror(errno)); + pa_log(__FILE__": WARNING: write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno)); close(fd); diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index 895abec32..c14ce12a6 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -59,7 +61,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (kill(pid, SIGUSR1) < 0) - pa_log(__FILE__": WARNING: kill(%u) failed: %s", pid, strerror(errno)); + pa_log(__FILE__": WARNING: kill(%u) failed: %s", pid, pa_cstrerror(errno)); pa_module_unload_request(m); diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index cf3ce8073..72298679e 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -128,7 +129,7 @@ static int do_write(struct userdata *u) { assert(u->write_index < u->write_length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) <= 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); return -1; } @@ -150,7 +151,7 @@ static int do_write(struct userdata *u) { assert(u->memchunk.memblock && u->memchunk.length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); return -1; } @@ -175,7 +176,7 @@ static int handle_response(struct userdata *u) { /* Process auth data */ if (!*(int32_t*) u->read_data) { - pa_log(__FILE__": Authentication failed: %s", strerror(errno)); + pa_log(__FILE__": Authentication failed: %s", pa_cstrerror(errno)); return -1; } @@ -245,7 +246,7 @@ static int do_read(struct userdata *u) { assert(u->read_index < u->read_length); if ((r = pa_iochannel_read(u->io, (uint8_t*) u->read_data + u->read_index, u->read_length - u->read_index)) <= 0) { - pa_log(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF"); + pa_log(__FILE__": read() failed: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); cancel(u); return -1; } @@ -305,7 +306,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, vo u->client = NULL; if (!io) { - pa_log(__FILE__": connection failed: %s", strerror(errno)); + pa_log(__FILE__": connection failed: %s", pa_cstrerror(errno)); cancel(u); return; } diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 96db837a4..db2ba0303 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -36,6 +36,7 @@ #include +#include #include #include @@ -272,7 +273,7 @@ int pa__init(pa_core *c, pa_module*m) { pthread_cond_init(&u->cond, NULL); if (pipe(u->pipe_fds) < 0) { - pa_log(__FILE__": pipe() failed: %s", strerror(errno)); + pa_log(__FILE__": pipe() failed: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 3d7831458..8816fb8ac 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -36,6 +36,7 @@ #include +#include #include #include @@ -270,7 +271,7 @@ int pa__init(pa_core *c, pa_module*m) { pthread_cond_init(&u->cond, NULL); if (pipe(u->pipe_fds) < 0) { - pa_log(__FILE__": pipe() failed: %s", strerror(errno)); + pa_log(__FILE__": pipe() failed: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/modules/module-match.c b/src/modules/module-match.c index c7ca12a5e..f68f0c615 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -86,7 +87,7 @@ static int load_rules(struct userdata *u, const char *filename) { pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn, "r"); if (!f) { - pa_log(__FILE__": failed to open file '%s': %s", fn, strerror(errno)); + pa_log(__FILE__": failed to open file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index 55f0b2c86..d6c91e2e5 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -33,6 +33,7 @@ #include +#include #include #include @@ -89,7 +90,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC struct input_event ev; if (pa_loop_read(u->fd, &ev, sizeof(ev)) <= 0) { - pa_log(__FILE__": failed to read from event device: %s", strerror(errno)); + pa_log(__FILE__": failed to read from event device: %s", pa_cstrerror(errno)); goto fail; } @@ -183,19 +184,19 @@ int pa__init(pa_core *c, pa_module*m) { u->fd = -1; if ((u->fd = open(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY)) < 0) { - pa_log(__FILE__": failed to open evdev device: %s", strerror(errno)); + pa_log(__FILE__": failed to open evdev device: %s", pa_cstrerror(errno)); goto fail; } if (ioctl(u->fd, EVIOCGVERSION, &version) < 0) { - pa_log(__FILE__": EVIOCGVERSION failed: %s", strerror(errno)); + pa_log(__FILE__": EVIOCGVERSION failed: %s", pa_cstrerror(errno)); goto fail; } pa_log_info(__FILE__": evdev driver version %i.%i.%i", version >> 16, (version >> 8) & 0xff, version & 0xff); if(ioctl(u->fd, EVIOCGID, &input_id)) { - pa_log(__FILE__": EVIOCGID failed: %s", strerror(errno)); + pa_log(__FILE__": EVIOCGID failed: %s", pa_cstrerror(errno)); goto fail; } @@ -204,7 +205,7 @@ int pa__init(pa_core *c, pa_module*m) { memset(name, 0, sizeof(name)); if(ioctl(u->fd, EVIOCGNAME(sizeof(name)), name) < 0) { - pa_log(__FILE__": EVIOCGNAME failed: %s", strerror(errno)); + pa_log(__FILE__": EVIOCGNAME failed: %s", pa_cstrerror(errno)); goto fail; } @@ -212,7 +213,7 @@ int pa__init(pa_core *c, pa_module*m) { memset(evtype_bitmask, 0, sizeof(evtype_bitmask)); if (ioctl(u->fd, EVIOCGBIT(0, EV_MAX), evtype_bitmask) < 0) { - pa_log(__FILE__": EVIOCGBIT failed: %s", strerror(errno)); + pa_log(__FILE__": EVIOCGBIT failed: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index a1b40389a..dac7d7f33 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -36,6 +36,7 @@ #include #include +#include #include #include @@ -152,7 +153,7 @@ static void do_write(struct userdata *u) { update_usage(u); if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); return; } @@ -215,7 +216,7 @@ static void do_read(struct userdata *u) { update_usage(u); if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); return; } @@ -246,7 +247,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { assert(s && u); if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); return 0; } @@ -272,7 +273,7 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { assert(s && u); if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); return 0; } @@ -295,7 +296,7 @@ static int sink_get_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); + pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); s->get_hw_volume = NULL; return -1; } @@ -307,7 +308,7 @@ static int sink_set_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); + pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); s->set_hw_volume = NULL; return -1; } @@ -319,7 +320,7 @@ static int source_get_hw_volume(pa_source *s) { struct userdata *u = s->userdata; if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); + pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); s->get_hw_volume = NULL; return -1; } @@ -331,7 +332,7 @@ static int source_set_hw_volume(pa_source *s) { struct userdata *u = s->userdata; if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); + pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); s->set_hw_volume = NULL; return -1; } @@ -413,7 +414,7 @@ int pa__init(pa_core *c, pa_module*m) { if (mode != O_WRONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETISPACE: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno)); goto fail; } @@ -425,7 +426,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log(__FILE__": mmap failed for input. Changing to O_WRONLY mode."); mode = O_WRONLY; } else { - pa_log(__FILE__": mmap(): %s", strerror(errno)); + pa_log(__FILE__": mmap(): %s", pa_cstrerror(errno)); goto fail; } } else { @@ -452,7 +453,7 @@ int pa__init(pa_core *c, pa_module*m) { if (mode != O_RDONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETOSPACE: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno)); goto fail; } @@ -464,7 +465,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log(__FILE__": mmap filed for output. Changing to O_RDONLY mode."); mode = O_RDONLY; } else { - pa_log(__FILE__": mmap(): %s", strerror(errno)); + pa_log(__FILE__": mmap(): %s", pa_cstrerror(errno)); goto fail; } } else { @@ -492,12 +493,12 @@ int pa__init(pa_core *c, pa_module*m) { zero = 0; if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); goto fail; } if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 9233420d1..8e2178555 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -146,7 +147,7 @@ static void do_write(struct userdata *u) { assert(memchunk->length); if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); break; } @@ -199,7 +200,7 @@ static void do_read(struct userdata *u) { if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) - pa_log(__FILE__": read() failed: %s", strerror(errno)); + pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno)); break; } @@ -234,7 +235,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { assert(s && u && u->sink); if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) { - pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY: %s", strerror(errno)); + pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno)); s->get_latency = NULL; return 0; } @@ -270,7 +271,7 @@ static int sink_get_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); + pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); s->get_hw_volume = NULL; return -1; } @@ -282,7 +283,7 @@ static int sink_set_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); + pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); s->set_hw_volume = NULL; return -1; } @@ -294,7 +295,7 @@ static int source_get_hw_volume(pa_source *s) { struct userdata *u = s->userdata; if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", strerror(errno)); + pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); s->get_hw_volume = NULL; return -1; } @@ -306,7 +307,7 @@ static int source_set_hw_volume(pa_source *s) { struct userdata *u = s->userdata; if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", strerror(errno)); + pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); s->set_hw_volume = NULL; return -1; } @@ -380,7 +381,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETBLKSIZE: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno)); goto fail; } assert(frag_size); diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 6492ba6ad..f0569ce99 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -99,7 +100,7 @@ static void do_write(struct userdata *u) { assert(u->memchunk.memblock && u->memchunk.length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); return; } @@ -163,14 +164,14 @@ int pa__init(pa_core *c, pa_module*m) { mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); if ((fd = open(p, O_RDWR)) < 0) { - pa_log(__FILE__": open('%s'): %s", p, strerror(errno)); + pa_log(__FILE__": open('%s'): %s", p, pa_cstrerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); if (fstat(fd, &st) < 0) { - pa_log(__FILE__": fstat('%s'): %s", p, strerror(errno)); + pa_log(__FILE__": fstat('%s'): %s", p, pa_cstrerror(errno)); goto fail; } diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index 9f7554401..77212ce59 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -96,7 +97,7 @@ static void do_read(struct userdata *u) { assert(u->chunk.memblock && u->chunk.memblock->length > u->chunk.index); if ((r = pa_iochannel_read(u->io, (uint8_t*) u->chunk.memblock->data + u->chunk.index, u->chunk.memblock->length - u->chunk.index)) <= 0) { - pa_log(__FILE__": read() failed: %s", strerror(errno)); + pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); return; } @@ -141,14 +142,14 @@ int pa__init(pa_core *c, pa_module*m) { mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); if ((fd = open(p, O_RDWR)) < 0) { - pa_log(__FILE__": open('%s'): %s", p, strerror(errno)); + pa_log(__FILE__": open('%s'): %s", p, pa_cstrerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); if (fstat(fd, &st) < 0) { - pa_log(__FILE__": fstat('%s'): %s", p, strerror(errno)); + pa_log(__FILE__": fstat('%s'): %s", p, pa_cstrerror(errno)); goto fail; } diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index cfe661a38..8eba352b6 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -42,6 +42,7 @@ #include "../polypcore/winsock.h" +#include #include #include @@ -250,7 +251,7 @@ int pa__init(pa_core *c, pa_module*m) { } if ((r = pa_unix_socket_remove_stale(tmp)) < 0) { - pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s", tmp, strerror(errno)); + pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s", tmp, pa_cstrerror(errno)); goto fail; } @@ -328,7 +329,7 @@ void pa__done(pa_core *c, pa_module*m) { if ((p = pa_parent_dir(u->socket_path))) { if (rmdir(p) < 0 && errno != ENOENT && errno != ENOTEMPTY) - pa_log(__FILE__": Failed to remove %s: %s.", u->socket_path, strerror(errno)); + pa_log(__FILE__": Failed to remove %s: %s.", u->socket_path, pa_cstrerror(errno)); pa_xfree(p); } diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 77eb4e49d..8670bb354 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -168,7 +169,7 @@ static void do_write(struct userdata *u) { } if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); return; } @@ -206,7 +207,7 @@ static void do_read(struct userdata *u) { if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) - pa_log(__FILE__": read() failed: %s", strerror(errno)); + pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno)); return; } @@ -334,7 +335,7 @@ static int sink_set_hw_volume_cb(pa_sink *s) { if (errno == EINVAL) pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -363,7 +364,7 @@ static int sink_set_hw_mute_cb(pa_sink *s) { info.output_muted = !!s->hw_muted; if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { - pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -397,7 +398,7 @@ static int source_set_hw_volume_cb(pa_source *s) { if (errno == EINVAL) pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -463,7 +464,7 @@ static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { if (errno == EINVAL) pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -481,7 +482,7 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { if (errno == EINVAL) pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", strerror(errno)); + pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index e74567bc7..796e43a36 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -124,7 +125,7 @@ static int load_rules(struct userdata *u) { pa_log_info(__FILE__": starting with empty ruleset."); ret = 0; } else - pa_log(__FILE__": failed to open file '%s': %s", u->table_file, strerror(errno)); + pa_log(__FILE__": failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); goto finish; } @@ -198,7 +199,7 @@ static int save_rules(struct userdata *u) { pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w"); if (!f) { - pa_log(__FILE__": failed to open file '%s': %s", u->table_file, strerror(errno)); + pa_log(__FILE__": failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); goto finish; } diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index a84276f11..027921c56 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -34,6 +34,8 @@ #include #include +#include + #include #include @@ -51,7 +53,7 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { tcaps = pcaps ? pcaps : &dcaps; if (ioctl(fd, SNDCTL_DSP_GETCAPS, tcaps) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); goto fail; } @@ -65,13 +67,13 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) { if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY)) < 0) { - pa_log(__FILE__": open('%s'): %s", device, strerror(errno)); + pa_log(__FILE__": open('%s'): %s", device, pa_cstrerror(errno)); goto fail; } } } else { if ((fd = open(device, *mode|O_NDELAY)) < 0) { - pa_log(__FILE__": open('%s'): %s", device, strerror(errno)); + pa_log(__FILE__": open('%s'): %s", device, pa_cstrerror(errno)); goto fail; } } @@ -80,7 +82,7 @@ success: if (pcaps) { if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); goto fail; } } @@ -118,7 +120,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != f) { format = AFMT_U8; if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_U8) { - pa_log(__FILE__": SNDCTL_DSP_SETFMT: %s", format != AFMT_U8 ? "No supported sample format" : strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETFMT: %s", format != AFMT_U8 ? "No supported sample format" : pa_cstrerror(errno)); return -1; } else ss->format = PA_SAMPLE_U8; @@ -130,7 +132,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { channels = ss->channels; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { - pa_log(__FILE__": SNDCTL_DSP_CHANNELS: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_CHANNELS: %s", pa_cstrerror(errno)); return -1; } assert(channels); @@ -138,7 +140,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { speed = ss->rate; if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SPEED: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SPEED: %s", pa_cstrerror(errno)); return -1; } assert(speed); @@ -164,7 +166,7 @@ int pa_oss_set_fragments(int fd, int nfrags, int frag_size) { arg = ((int) nfrags << 16) | simple_log2(frag_size); if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &arg) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SETFRAGMENT: %s", strerror(errno)); + pa_log(__FILE__": SNDCTL_DSP_SETFRAGMENT: %s", pa_cstrerror(errno)); return -1; } @@ -253,7 +255,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { !(f = fopen("/proc/asound/oss/sndstat", "r"))) { if (errno != ENOENT) - pa_log_warn(__FILE__": failed to open OSS sndstat device: %s", strerror(errno)); + pa_log_warn(__FILE__": failed to open OSS sndstat device: %s", pa_cstrerror(errno)); return -1; } diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 56fc91ef1..8d9b33c2a 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -216,13 +217,13 @@ static int mcast_socket(const struct sockaddr* sa, socklen_t salen) { af = sa->sa_family; if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) { - pa_log(__FILE__": Failed to create socket: %s", strerror(errno)); + pa_log(__FILE__": Failed to create socket: %s", pa_cstrerror(errno)); goto fail; } one = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) { - pa_log(__FILE__": SO_REUSEADDR failed: %s", strerror(errno)); + pa_log(__FILE__": SO_REUSEADDR failed: %s", pa_cstrerror(errno)); goto fail; } @@ -239,12 +240,12 @@ static int mcast_socket(const struct sockaddr* sa, socklen_t salen) { } if (r < 0) { - pa_log_info(__FILE__": Joining mcast group failed: %s", strerror(errno)); + pa_log_info(__FILE__": Joining mcast group failed: %s", pa_cstrerror(errno)); goto fail; } if (bind(fd, sa, salen) < 0) { - pa_log(__FILE__": bind() failed: %s", strerror(errno)); + pa_log(__FILE__": bind() failed: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 1372414cb..c8b3899a2 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -238,28 +239,28 @@ int pa__init(pa_core *c, pa_module*m) { } if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) { - pa_log(__FILE__": socket() failed: %s", strerror(errno)); + pa_log(__FILE__": socket() failed: %s", pa_cstrerror(errno)); goto fail; } if (connect(fd, af == AF_INET ? (struct sockaddr*) &sa4 : (struct sockaddr*) &sa6, af == AF_INET ? sizeof(sa4) : sizeof(sa6)) < 0) { - pa_log(__FILE__": connect() failed: %s", strerror(errno)); + pa_log(__FILE__": connect() failed: %s", pa_cstrerror(errno)); goto fail; } if ((sap_fd = socket(af, SOCK_DGRAM, 0)) < 0) { - pa_log(__FILE__": socket() failed: %s", strerror(errno)); + pa_log(__FILE__": socket() failed: %s", pa_cstrerror(errno)); goto fail; } if (connect(sap_fd, af == AF_INET ? (struct sockaddr*) &sap_sa4 : (struct sockaddr*) &sap_sa6, af == AF_INET ? sizeof(sap_sa4) : sizeof(sap_sa6)) < 0) { - pa_log(__FILE__": connect() failed: %s", strerror(errno)); + pa_log(__FILE__": connect() failed: %s", pa_cstrerror(errno)); goto fail; } if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0 || setsockopt(sap_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) { - pa_log(__FILE__": IP_MULTICAST_LOOP failed: %s", strerror(errno)); + pa_log(__FILE__": IP_MULTICAST_LOOP failed: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index 23e84eb3e..012d65785 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -36,6 +36,8 @@ #include #endif +#include + #include #include "rtp.h" @@ -124,7 +126,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { if (k < 0) { if (errno != EAGAIN) /* If the queue is full, just ignore it */ - pa_log(__FILE__": sendmsg() failed: %s", strerror(errno)); + pa_log(__FILE__": sendmsg() failed: %s", pa_cstrerror(errno)); return -1; } @@ -162,7 +164,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_memblock_stat *st) { chunk->memblock = NULL; if (ioctl(c->fd, FIONREAD, &size) < 0) { - pa_log(__FILE__": FIONREAD failed: %s", strerror(errno)); + pa_log(__FILE__": FIONREAD failed: %s", pa_cstrerror(errno)); goto fail; } @@ -183,7 +185,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_memblock_stat *st) { m.msg_flags = 0; if ((r = recvmsg(c->fd, &m, 0)) != size) { - pa_log(__FILE__": recvmsg() failed: %s", r < 0 ? strerror(errno) : "size mismatch"); + pa_log(__FILE__": recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); goto fail; } diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index 5b8f31fba..238ee4200 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -38,6 +38,7 @@ #include #endif +#include #include #include @@ -77,7 +78,7 @@ int pa_sap_send(pa_sap_context *c, int goodbye) { int k; if (getsockname(c->fd, sa, &salen) < 0) { - pa_log("getsockname() failed: %s\n", strerror(errno)); + pa_log("getsockname() failed: %s\n", pa_cstrerror(errno)); return -1; } @@ -109,7 +110,7 @@ int pa_sap_send(pa_sap_context *c, int goodbye) { m.msg_flags = 0; if ((k = sendmsg(c->fd, &m, MSG_DONTWAIT)) < 0) - pa_log("sendmsg() failed: %s\n", strerror(errno)); + pa_log("sendmsg() failed: %s\n", pa_cstrerror(errno)); return k; } @@ -136,7 +137,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { assert(goodbye); if (ioctl(c->fd, FIONREAD, &size) < 0) { - pa_log(__FILE__": FIONREAD failed: %s", strerror(errno)); + pa_log(__FILE__": FIONREAD failed: %s", pa_cstrerror(errno)); goto fail; } @@ -158,7 +159,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { m.msg_flags = 0; if ((r = recvmsg(c->fd, &m, 0)) != size) { - pa_log(__FILE__": recvmsg() failed: %s", r < 0 ? strerror(errno) : "size mismatch"); + pa_log(__FILE__": recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); goto fail; } diff --git a/src/polyp/client-conf.c b/src/polyp/client-conf.c index 1ebcff437..0b3154c84 100644 --- a/src/polyp/client-conf.c +++ b/src/polyp/client-conf.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -123,7 +124,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn, "r"); if (!f && errno != EINTR) { - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, strerror(errno)); + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } diff --git a/src/polyp/context.c b/src/polyp/context.c index a3b49d4b5..eb5638197 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -47,6 +47,7 @@ #include "../polypcore/winsock.h" +#include #include #include @@ -440,7 +441,7 @@ static int context_connect_spawn(pa_context *c) { pa_context_ref(c); if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - pa_log(__FILE__": socketpair() failed: %s", strerror(errno)); + pa_log(__FILE__": socketpair(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } @@ -454,7 +455,7 @@ static int context_connect_spawn(pa_context *c) { c->spawn_api.prefork(); if ((pid = fork()) < 0) { - pa_log(__FILE__": fork() failed: %s", strerror(errno)); + pa_log(__FILE__": fork(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); if (c->spawn_api.postfork) @@ -510,7 +511,7 @@ static int context_connect_spawn(pa_context *c) { c->spawn_api.postfork(); if (r < 0) { - pa_log(__FILE__": waitpid() failed: %s", strerror(errno)); + pa_log(__FILE__": waitpid(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { diff --git a/src/polyp/error.c b/src/polyp/error.c index e78d072e8..062b6f36d 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -23,9 +23,23 @@ #include #endif +#include #include #include +#include +#ifdef HAVE_PTHREAD +#include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif + +#include +#include + +#include #include #include "error.h" @@ -58,3 +72,79 @@ const char*pa_strerror(int error) { return errortab[error]; } + +#ifdef HAVE_PTHREAD + +static pthread_once_t cstrerror_once = PTHREAD_ONCE_INIT; +static pthread_key_t tlsstr_key; + +static void inittls(void) { + int ret; + + ret = pthread_key_create(&tlsstr_key, pa_xfree); + if (ret) { + fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", errno); + exit(-1); + } +} + +#elif HAVE_WINDOWS_H + +static __declspec(thread) char *tlsstr; + +#else + +/* Unsafe, but we have no choice */ +static char *tlsstr; + +#endif + +char* pa_cstrerror(int errnum) { + const char *origbuf; + +#ifdef HAVE_STRERROR_R + char errbuf[128]; +#endif + +#ifdef HAVE_PTHREAD + char *tlsstr; + + pthread_once(&cstrerror_once, inittls); + + tlsstr = pthread_getspecific(tlsstr_key); +#endif + + if (tlsstr) + pa_xfree(tlsstr); + +#ifdef HAVE_STRERROR_R + +#ifdef __GLIBC__ + origbuf = strerror_r(errnum, errbuf, sizeof(errbuf)); + if (origbuf == NULL) + origbuf = ""; +#else + if (strerror_r(errnum, errbuf, sizeof(errbuf)) == 0) { + origbuf = errbuf; + errbuf[sizeof(errbuf) - 1] = '\0'; + } else + origbuf = ""; +#endif + +#else + /* This might not be thread safe, but we hope for the best */ + origbuf = strerror(errnum); +#endif + + tlsstr = pa_locale_to_utf8(origbuf); + if (!tlsstr) { + fprintf(stderr, "Unable to convert, filtering\n"); + tlsstr = pa_utf8_filter(origbuf); + } + +#ifdef HAVE_PTHREAD + pthread_setspecific(tlsstr_key, tlsstr); +#endif + + return tlsstr; +} diff --git a/src/polyp/error.h b/src/polyp/error.h index 9856c1af3..33507bfd4 100644 --- a/src/polyp/error.h +++ b/src/polyp/error.h @@ -33,6 +33,12 @@ PA_C_DECL_BEGIN /** Return a human readable error message for the specified numeric error code */ const char* pa_strerror(int error); +/** A wrapper around the standard strerror() function that converts the + * string to UTF-8. The function is thread safe but the returned string is + * only guaranteed to exist until the thread exits or pa_cstrerror() is + * called again from the same thread. */ +char* pa_cstrerror(int errnum); + PA_C_DECL_END #endif diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index c57437b6e..c6ad431a1 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -36,6 +36,7 @@ #include #endif +#include #include #include @@ -89,7 +90,7 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags if (errno == EAGAIN) return; - pa_log(__FILE__": read(): %s", strerror(errno)); + pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); return; } @@ -106,7 +107,7 @@ int pa_signal_init(pa_mainloop_api *a) { assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event); if (pipe(signal_pipe) < 0) { - pa_log(__FILE__": pipe() failed: %s", strerror(errno)); + pa_log(__FILE__": pipe(): %s", pa_cstrerror(errno)); return -1; } diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 6b5b3b252..6088fa4b3 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -44,6 +44,7 @@ #include "../polypcore/pipe.h" #endif +#include #include #include @@ -689,7 +690,7 @@ int pa_mainloop_poll(pa_mainloop *m) { if (errno == EINTR) r = 0; else - pa_log(__FILE__": poll(): %s", strerror(errno)); + pa_log(__FILE__": poll(): %s", pa_cstrerror(errno)); } } diff --git a/src/polyp/util.c b/src/polyp/util.c index ed59a5c63..910544834 100644 --- a/src/polyp/util.c +++ b/src/polyp/util.c @@ -51,6 +51,8 @@ #include "../polypcore/winsock.h" +#include + #include #include @@ -107,7 +109,7 @@ char *pa_get_user_name(char *s, size_t l) { char *pa_get_host_name(char *s, size_t l) { assert(s && l > 0); if (gethostname(s, l) < 0) { - pa_log(__FILE__": gethostname(): %s", strerror(errno)); + pa_log(__FILE__": gethostname(): %s", pa_cstrerror(errno)); return NULL; } s[l-1] = 0; diff --git a/src/polypcore/authkey.c b/src/polypcore/authkey.c index aee54fd4b..6b462a23b 100644 --- a/src/polypcore/authkey.c +++ b/src/polypcore/authkey.c @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -53,7 +54,7 @@ static int generate(int fd, void *ret_data, size_t length) { ftruncate(fd, 0); if ((r = pa_loop_write(fd, ret_data, length)) < 0 || (size_t) r != length) { - pa_log(__FILE__": failed to write cookie file: %s", strerror(errno)); + pa_log(__FILE__": failed to write cookie file: %s", pa_cstrerror(errno)); return -1; } @@ -75,7 +76,7 @@ static int load(const char *fn, void *data, size_t length) { if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR)) < 0) { if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY)) < 0) { - pa_log(__FILE__": failed to open cookie file '%s': %s", fn, strerror(errno)); + pa_log(__FILE__": failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } else writable = 0; @@ -84,7 +85,7 @@ static int load(const char *fn, void *data, size_t length) { unlock = pa_lock_fd(fd, 1) >= 0; if ((r = pa_loop_read(fd, data, length)) < 0) { - pa_log(__FILE__": failed to read cookie file '%s': %s", fn, strerror(errno)); + pa_log(__FILE__": failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } @@ -125,7 +126,7 @@ int pa_authkey_load(const char *path, void *data, size_t length) { if (ret < 0) pa_log(__FILE__": Failed to load authorization key '%s': %s", path, - (ret == -1) ? strerror(errno) : "file corrupt"); + (ret == -1) ? pa_cstrerror(errno) : "file corrupt"); return ret; } @@ -181,14 +182,14 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) { return -2; if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": failed to open cookie file '%s': %s", fn, strerror(errno)); + pa_log(__FILE__": failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } unlock = pa_lock_fd(fd, 1) >= 0; if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) { - pa_log(__FILE__": failed to read cookie file '%s': %s", fn, strerror(errno)); + pa_log(__FILE__": failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } diff --git a/src/polypcore/cli-command.c b/src/polypcore/cli-command.c index 3adc9a217..039aa9579 100644 --- a/src/polypcore/cli-command.c +++ b/src/polypcore/cli-command.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -900,7 +901,7 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int assert(c && fn && buf); if (!(f = fopen(fn, "r"))) { - pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, strerror(errno)); + pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno)); if (!*fail) ret = 0; goto fail; diff --git a/src/polypcore/conf-parser.c b/src/polypcore/conf-parser.c index bc99b8710..4bcb83ddb 100644 --- a/src/polypcore/conf-parser.c +++ b/src/polypcore/conf-parser.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -112,7 +113,8 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void goto finish; } - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to open configuration file '%s': %s", + filename, pa_cstrerror(errno)); goto finish; } @@ -122,7 +124,8 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void if (feof(f)) break; - pa_log(__FILE__": WARNING: failed to read configuration file '%s': %s", filename, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to read configuration file '%s': %s", + filename, pa_cstrerror(errno)); goto finish; } diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 5cb38beef..1d60a910d 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -41,6 +41,7 @@ #include #endif +#include #include #include #include @@ -359,7 +360,7 @@ static void add_file(pa_core *c, const char *pathname) { e = pa_path_get_filename(pathname); if (stat(pathname, &st) < 0) { - pa_log(__FILE__": stat('%s') failed: %s", pathname, strerror(errno)); + pa_log(__FILE__": stat('%s'): %s", pathname, pa_cstrerror(errno)); return; } @@ -381,7 +382,7 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) { /* If that fails, try to open it as shell glob */ if (glob(pathname, GLOB_ERR|GLOB_NOSORT, NULL, &p) < 0) { - pa_log(__FILE__": Failed to open directory: %s", strerror(errno)); + pa_log(__FILE__": failed to open directory '%s': %s", pathname, pa_cstrerror(errno)); return -1; } diff --git a/src/polypcore/core-util.c b/src/polypcore/core-util.c index 36044c810..0e7f77a4e 100644 --- a/src/polypcore/core-util.c +++ b/src/polypcore/core-util.c @@ -69,6 +69,7 @@ #include +#include #include #include @@ -301,7 +302,7 @@ void pa_check_signal_is_blocked(int sig) { if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) { #endif if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) { - pa_log(__FILE__": sigprocmask() failed: %s", strerror(errno)); + pa_log(__FILE__": sigprocmask(): %s", pa_cstrerror(errno)); return; } #ifdef HAVE_PTHREAD @@ -314,7 +315,7 @@ void pa_check_signal_is_blocked(int sig) { /* Check whether the signal is trapped */ if (sigaction(sig, NULL, &sa) < 0) { - pa_log(__FILE__": sigaction() failed: %s", strerror(errno)); + pa_log(__FILE__": sigaction(): %s", pa_cstrerror(errno)); return; } @@ -396,7 +397,7 @@ void pa_raise_priority(void) { #ifdef HAVE_SYS_RESOURCE_H if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) - pa_log_warn(__FILE__": setpriority() failed: %s", strerror(errno)); + pa_log_warn(__FILE__": setpriority(): %s", pa_cstrerror(errno)); else pa_log_info(__FILE__": Successfully gained nice level %i.", NICE_LEVEL); #endif @@ -406,13 +407,13 @@ void pa_raise_priority(void) { struct sched_param sp; if (sched_getparam(0, &sp) < 0) { - pa_log(__FILE__": sched_getparam() failed: %s", strerror(errno)); + pa_log(__FILE__": sched_getparam(): %s", pa_cstrerror(errno)); return; } sp.sched_priority = 1; if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) { - pa_log_warn(__FILE__": sched_setscheduler() failed: %s", strerror(errno)); + pa_log_warn(__FILE__": sched_setscheduler(): %s", pa_cstrerror(errno)); return; } @@ -563,7 +564,7 @@ static int is_group(gid_t gid, const char *name) { data = pa_xmalloc(n); if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) { - pa_log(__FILE__ ": getgrgid_r(%u) failed: %s", gid, strerror(errno)); + pa_log(__FILE__": getgrgid_r(%u): %s", gid, pa_cstrerror(errno)); goto finish; } @@ -575,8 +576,8 @@ finish: /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not * support getgrgid_r. */ if ((result = getgrgid(gid)) == NULL) { - pa_log(__FILE__ ": getgrgid(%u) failed: %s", gid, strerror(errno)); - goto finish; + pa_log(__FILE__": getgrgid(%u): %s", gid, pa_cstrerror(errno)); + goto finish; } r = strcmp(name, result->gr_name) == 0; @@ -598,7 +599,7 @@ int pa_own_uid_in_group(const char *name, gid_t *gid) { gids = pa_xmalloc(sizeof(GETGROUPS_T)*n); if ((n = getgroups(n, gids)) < 0) { - pa_log(__FILE__": getgroups() failed: %s", strerror(errno)); + pa_log(__FILE__": getgroups(): %s", pa_cstrerror(errno)); goto finish; } @@ -696,7 +697,8 @@ int pa_lock_fd(int fd, int b) { return 0; } - pa_log(__FILE__": %slock failed: %s", !b ? "un" : "", strerror(errno)); + pa_log(__FILE__": %slock: %s", !b? "un" : "", + pa_cstrerror(errno)); #endif #ifdef OS_IS_WIN32 @@ -730,7 +732,8 @@ int pa_lock_lockfile(const char *fn) { struct stat st; if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": failed to create lock file '%s': %s", fn, strerror(errno)); + pa_log(__FILE__": failed to create lock file '%s': %s", fn, + pa_cstrerror(errno)); goto fail; } @@ -777,7 +780,8 @@ int pa_unlock_lockfile(const char *fn, int fd) { assert(fn && fd >= 0); if (unlink(fn) < 0) { - pa_log_warn(__FILE__": WARNING: unable to remove lock file '%s': %s", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: unable to remove lock file '%s': %s", + fn, pa_cstrerror(errno)); r = -1; } @@ -787,7 +791,8 @@ int pa_unlock_lockfile(const char *fn, int fd) { } if (close(fd) < 0) { - pa_log_warn(__FILE__": WARNING: failed to close lock file '%s': %s", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to close lock file '%s': %s", + fn, pa_cstrerror(errno)); r = -1; } diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index 10997d623..8af6a36bf 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -38,6 +38,7 @@ #include "winsock.h" +#include #include #include @@ -253,7 +254,7 @@ int pa_iochannel_creds_enable(pa_iochannel *io) { assert(io->ifd >= 0); if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) { - pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", strerror(errno)); + pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", pa_cstrerror(errno)); return -1; } diff --git a/src/polypcore/ioline.c b/src/polypcore/ioline.c index 9bb610fe9..2e0a3e1af 100644 --- a/src/polypcore/ioline.c +++ b/src/polypcore/ioline.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -275,7 +276,7 @@ static int do_read(pa_ioline *l) { pa_ioline_puts(l, "\nExiting.\n"); do_write(l); } else if (r < 0) { - pa_log(__FILE__": read() failed: %s", strerror(errno)); + pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); failure(l); return -1; } @@ -297,7 +298,7 @@ static int do_write(pa_ioline *l) { while (!l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length) { if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) { - pa_log(__FILE__": write() failed: %s", r < 0 ? strerror(errno) : "EOF"); + pa_log(__FILE__": write(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); failure(l); return -1; } diff --git a/src/polypcore/log.c b/src/polypcore/log.c index ce9df1a97..6cdffa51d 100644 --- a/src/polypcore/log.c +++ b/src/polypcore/log.c @@ -94,6 +94,9 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { text = pa_vsprintf_malloc(format, ap); + if (!pa_utf8_valid(text)) + pa_log_level(level, __FILE__": invalid UTF-8 string following below:"); + for (t = text; t; t = n) { if ((n = strchr(t, '\n'))) { *n = 0; diff --git a/src/polypcore/pid.c b/src/polypcore/pid.c index e98dc97bb..b8f53955d 100644 --- a/src/polypcore/pid.c +++ b/src/polypcore/pid.c @@ -39,6 +39,7 @@ #include #endif +#include #include #include @@ -56,7 +57,8 @@ static pid_t read_pid(const char *fn, int fd) { assert(fn && fd >= 0); if ((r = pa_loop_read(fd, t, sizeof(t)-1)) < 0) { - pa_log(__FILE__": WARNING: failed to read PID file '%s': %s", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to read PID file '%s': %s", + fn, pa_cstrerror(errno)); return (pid_t) -1; } @@ -86,7 +88,8 @@ static int open_pid_file(const char *fn, int mode) { if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) { if (mode != O_RDONLY || errno != ENOENT) - pa_log(__FILE__": WARNING: failed to open PID file '%s': %s", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to open PID file '%s': %s", + fn, pa_cstrerror(errno)); goto fail; } @@ -95,7 +98,8 @@ static int open_pid_file(const char *fn, int mode) { goto fail; if (fstat(fd, &st) < 0) { - pa_log(__FILE__": Failed to fstat() PID file '%s': %s", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to fstat() PID file '%s': %s", + fn, pa_cstrerror(errno)); goto fail; } @@ -107,7 +111,8 @@ static int open_pid_file(const char *fn, int mode) { goto fail; if (close(fd) < 0) { - pa_log(__FILE__": Failed to close file '%s': %s", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to close file '%s': %s", + fn, pa_cstrerror(errno)); goto fail; } @@ -164,7 +169,8 @@ int pa_pid_file_create(void) { /* Overwrite the current PID file */ if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) { - pa_log(__FILE__": failed to truncate PID fil: %s.", strerror(errno)); + pa_log(__FILE__": failed to truncate PID file '%s': %s", + fn, pa_cstrerror(errno)); goto fail; } @@ -198,7 +204,8 @@ int pa_pid_file_remove(void) { pa_runtime_path("pid", fn, sizeof(fn)); if ((fd = open_pid_file(fn, O_RDWR)) < 0) { - pa_log(__FILE__": WARNING: failed to open PID file '%s': %s", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to open PID file '%s': %s", + fn, pa_cstrerror(errno)); goto fail; } @@ -211,7 +218,8 @@ int pa_pid_file_remove(void) { } if (ftruncate(fd, 0) < 0) { - pa_log(__FILE__": failed to truncate PID file '%s': %s", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to truncate PID file '%s': %s", + fn, pa_cstrerror(errno)); goto fail; } @@ -222,7 +230,8 @@ int pa_pid_file_remove(void) { #endif if (unlink(fn) < 0) { - pa_log(__FILE__": failed to remove PID file '%s': %s", fn, strerror(errno)); + pa_log_warn(__FILE__": WARNING: failed to remove PID file '%s': %s", + fn, pa_cstrerror(errno)); goto fail; } diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index c11bdb21c..01a72e849 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -812,7 +813,7 @@ static int do_read(struct connection *c) { assert(c->read_data_length < sizeof(c->request)); if ((r = pa_iochannel_read(c->io, ((uint8_t*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { - pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF"); + pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } @@ -860,7 +861,7 @@ static int do_read(struct connection *c) { assert(c->read_data && c->read_data_length < handler->data_length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { - pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF"); + pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } @@ -880,7 +881,7 @@ static int do_read(struct connection *c) { assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { - pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF"); + pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } @@ -935,7 +936,7 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF"); + pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } @@ -965,7 +966,7 @@ static int do_write(struct connection *c) { assert(c->write_data_index < c->write_data_length); if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); return -1; } @@ -984,7 +985,7 @@ static int do_write(struct connection *c) { if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); - pa_log(__FILE__": write(): %s", strerror(errno)); + pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); return -1; } diff --git a/src/polypcore/protocol-simple.c b/src/polypcore/protocol-simple.c index caffd5c9f..f15f882ab 100644 --- a/src/polypcore/protocol-simple.c +++ b/src/polypcore/protocol-simple.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -133,7 +134,7 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - pa_log_debug(__FILE__": read() failed: %s", r == 0 ? "EOF" : strerror(errno)); + pa_log_debug(__FILE__": read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno)); return -1; } @@ -167,7 +168,7 @@ static int do_write(struct connection *c) { if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); - pa_log(__FILE__": write(): %s", strerror(errno)); + pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); return -1; } diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index ec2f9a9e3..aa885759e 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -54,6 +54,7 @@ #include "winsock.h" +#include #include #include @@ -139,7 +140,7 @@ static void do_call(pa_socket_client *c) { lerror = sizeof(error); if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) { - pa_log(__FILE__": getsockopt(): %s", strerror(errno)); + pa_log(__FILE__": getsockopt(): %s", pa_cstrerror(errno)); goto finish; } @@ -149,7 +150,7 @@ static void do_call(pa_socket_client *c) { } if (error != 0) { - pa_log_debug(__FILE__": connect(): %s", strerror(error)); + pa_log_debug(__FILE__": connect(): %s", pa_cstrerror(errno)); errno = error; goto finish; } @@ -194,7 +195,7 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t pa_log_debug(__FILE__": connect(): %d", WSAGetLastError()); #else if (errno != EINPROGRESS) { - pa_log_debug(__FILE__": connect(): %s (%d)", strerror(errno), errno); + pa_log_debug(__FILE__": connect(): %s (%d)", pa_cstrerror(errno), errno); #endif return -1; } @@ -266,7 +267,7 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size } if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s", strerror(errno)); + pa_log(__FILE__": socket(): %s", pa_cstrerror(errno)); return -1; } diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index 592b6a630..871fac115 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -64,6 +64,7 @@ #include #include +#include #include #include @@ -94,7 +95,7 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U pa_socket_server_ref(s); if ((nfd = accept(fd, NULL, NULL)) < 0) { - pa_log(__FILE__": accept(): %s", strerror(errno)); + pa_log(__FILE__": accept(): %s", pa_cstrerror(errno)); goto finish; } @@ -173,7 +174,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file assert(m && filename); if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s", strerror(errno)); + pa_log(__FILE__": socket(): %s", pa_cstrerror(errno)); goto fail; } @@ -186,12 +187,12 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file pa_socket_low_delay(fd); if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { - pa_log(__FILE__": bind(): %s", strerror(errno)); + pa_log(__FILE__": bind(): %s", pa_cstrerror(errno)); goto fail; } if (listen(fd, 5) < 0) { - pa_log(__FILE__": listen(): %s", strerror(errno)); + pa_log(__FILE__": listen(): %s", pa_cstrerror(errno)); goto fail; } @@ -227,7 +228,7 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address assert(m && port); if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_INET): %s", strerror(errno)); + pa_log(__FILE__": socket(PF_INET): %s", pa_cstrerror(errno)); goto fail; } @@ -235,7 +236,7 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address #ifdef SO_REUSEADDR if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) - pa_log(__FILE__": setsockopt(): %s", strerror(errno)); + pa_log(__FILE__": setsockopt(): %s", pa_cstrerror(errno)); #endif pa_socket_tcp_low_delay(fd); @@ -246,12 +247,12 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address sa.sin_addr.s_addr = htonl(address); if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { - pa_log(__FILE__": bind(): %s", strerror(errno)); + pa_log(__FILE__": bind(): %s", pa_cstrerror(errno)); goto fail; } if (listen(fd, 5) < 0) { - pa_log(__FILE__": listen(): %s", strerror(errno)); + pa_log(__FILE__": listen(): %s", pa_cstrerror(errno)); goto fail; } @@ -278,7 +279,7 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad assert(m && port); if ((fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_INET6): %s", strerror(errno)); + pa_log(__FILE__": socket(PF_INET6): %s", pa_cstrerror(errno)); goto fail; } @@ -286,12 +287,12 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad #ifdef IPV6_V6ONLY if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) - pa_log(__FILE__": setsockopt(IPPROTO_IPV6, IPV6_V6ONLY): %s", strerror(errno)); + pa_log(__FILE__": setsockopt(IPPROTO_IPV6, IPV6_V6ONLY): %s", pa_cstrerror(errno)); #endif #ifdef SO_REUSEADDR if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) - pa_log(__FILE__": setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", strerror(errno)); + pa_log(__FILE__": setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", pa_cstrerror(errno)); #endif pa_socket_tcp_low_delay(fd); @@ -302,12 +303,12 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad memcpy(sa.sin6_addr.s6_addr, address, 16); if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { - pa_log(__FILE__": bind(): %s", strerror(errno)); + pa_log(__FILE__": bind(): %s", pa_cstrerror(errno)); goto fail; } if (listen(fd, 5) < 0) { - pa_log(__FILE__": listen(): %s", strerror(errno)); + pa_log(__FILE__": listen(): %s", pa_cstrerror(errno)); goto fail; } @@ -418,7 +419,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { socklen_t sa_len = sizeof(sa); if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) { - pa_log(__FILE__": getsockname() failed: %s", strerror(errno)); + pa_log(__FILE__": getsockname(): %s", pa_cstrerror(errno)); return NULL; } @@ -439,7 +440,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { char ip[INET6_ADDRSTRLEN]; if (!inet_ntop(AF_INET6, &sa.sin6_addr, ip, sizeof(ip))) { - pa_log(__FILE__": inet_ntop() failed: %s", strerror(errno)); + pa_log(__FILE__": inet_ntop(): %s", pa_cstrerror(errno)); return NULL; } @@ -454,7 +455,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { socklen_t sa_len = sizeof(sa); if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) { - pa_log(__FILE__": getsockname() failed: %s", strerror(errno)); + pa_log(__FILE__": getsockname(): %s", pa_cstrerror(errno)); return NULL; } @@ -474,7 +475,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { char ip[INET_ADDRSTRLEN]; if (!inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip))) { - pa_log(__FILE__": inet_ntop() failed: %s", strerror(errno)); + pa_log(__FILE__": inet_ntop(): %s", pa_cstrerror(errno)); return NULL; } diff --git a/src/polypcore/socket-util.c b/src/polypcore/socket-util.c index acbb7c1ff..06cdc6253 100644 --- a/src/polypcore/socket-util.c +++ b/src/polypcore/socket-util.c @@ -59,6 +59,7 @@ #include "winsock.h" +#include #include #include @@ -198,7 +199,7 @@ int pa_unix_socket_is_stale(const char *fn) { int fd = -1, ret = -1; if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s", strerror(errno)); + pa_log(__FILE__": socket(): %s", pa_cstrerror(errno)); goto finish; } diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 539d205e2..351d79da7 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -53,7 +54,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { } if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); + pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", pa_cstrerror(errno)); goto fail; } @@ -65,7 +66,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { int r; if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { - pa_log(__FILE__": connect() failed: %s", strerror(errno)); + pa_log(__FILE__": connect(): %s", pa_cstrerror(errno)); goto fail; } @@ -96,7 +97,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { for (;;) { if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { - pa_log(__FILE__": select() failed: %s", strerror(errno)); + pa_log(__FILE__": select(): %s", pa_cstrerror(errno)); goto fail; } @@ -108,7 +109,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read() failed: %s", strerror(errno)); + pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); goto fail; } @@ -124,7 +125,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read() failed: %s", strerror(errno)); + pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); goto fail; } @@ -137,7 +138,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(obuf_length); if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); goto fail; } @@ -151,7 +152,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(ibuf_length); if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { - pa_log(__FILE__": write() failed: %s", strerror(errno)); + pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); goto fail; } From 97ec77c66060abac88305a0acd1c86312b8ae6f2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 May 2006 15:56:28 +0000 Subject: [PATCH 0851/1514] add missing #include git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@946 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-zeroconf-publish.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 5c5db2862..bd4a2d974 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -30,6 +30,7 @@ #include #include +#include #include #include From d71dc9b022209480c2ddecdc8b1356ee02c69a55 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 22 May 2006 16:47:26 +0000 Subject: [PATCH 0852/1514] Fix TLS on Win32 to something a bit more safe and portable (compiler-wise). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@947 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/error.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/src/polyp/error.c b/src/polyp/error.c index 062b6f36d..ee9ce51b1 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -90,7 +90,78 @@ static void inittls(void) { #elif HAVE_WINDOWS_H -static __declspec(thread) char *tlsstr; +static DWORD tlsstr_key = TLS_OUT_OF_INDEXES; +static DWORD monitor_key = TLS_OUT_OF_INDEXES; + +static void inittls(void) { + HANDLE mutex; + char name[64]; + + sprintf(name, "polypaudio%d", (int)GetCurrentProcessId()); + + mutex = CreateMutex(NULL, FALSE, name); + if (!mutex) { + fprintf(stderr, __FILE__ ": CRITICAL: Unable to create named mutex (%d)\n", (int)GetLastError()); + exit(-1); + } + + WaitForSingleObject(mutex, INFINITE); + + if (tlsstr_key == TLS_OUT_OF_INDEXES) { + tlsstr_key = TlsAlloc(); + monitor_key = TlsAlloc(); + if ((tlsstr_key == TLS_OUT_OF_INDEXES) || (monitor_key == TLS_OUT_OF_INDEXES)) { + fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", (int)GetLastError()); + exit(-1); + } + } + + ReleaseMutex(mutex); + + CloseHandle(mutex); +} + +/* + * This is incredibly brain dead, but this is necessary when dealing with + * the hell that is Win32. + */ +struct monitor_data { + HANDLE thread; + void *data; +}; + +static DWORD WINAPI monitor_thread(LPVOID param) { + struct monitor_data *data; + + data = (struct monitor_data*)param; + assert(data); + + WaitForSingleObject(data->thread, INFINITE); + + CloseHandle(data->thread); + pa_xfree(data->data); + pa_xfree(data); + + return 0; +} + +static void start_monitor(void) { + HANDLE thread; + struct monitor_data *data; + + data = pa_xnew(struct monitor_data, 1); + assert(data); + + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &data->thread, 0, FALSE, DUPLICATE_SAME_ACCESS); + + thread = CreateThread(NULL, 0, monitor_thread, data, 0, NULL); + assert(thread); + + TlsSetValue(monitor_key, data); + + CloseHandle(thread); +} #else @@ -112,6 +183,16 @@ char* pa_cstrerror(int errnum) { pthread_once(&cstrerror_once, inittls); tlsstr = pthread_getspecific(tlsstr_key); +#elif defined(HAVE_WINDOWS_H) + char *tlsstr; + struct monitor_data *data; + + inittls(); + + tlsstr = TlsGetValue(tlsstr_key); + if (!tlsstr) + start_monitor(); + data = TlsGetValue(monitor_key); #endif if (tlsstr) @@ -144,6 +225,9 @@ char* pa_cstrerror(int errnum) { #ifdef HAVE_PTHREAD pthread_setspecific(tlsstr_key, tlsstr); +#elif defined(HAVE_WINDOWS_H) + TlsSetValue(tlsstr_key, tlsstr); + data->data = tlsstr; #endif return tlsstr; From 1b72d026344866f59ee2caaa66250d5932faea78 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 23 May 2006 07:33:33 +0000 Subject: [PATCH 0853/1514] Fix some warnings. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@948 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/sample.c | 1 + src/polypcore/core-util.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/polyp/sample.c b/src/polyp/sample.c index 320e31a05..9c3b9f917 100644 --- a/src/polyp/sample.c +++ b/src/polyp/sample.c @@ -46,6 +46,7 @@ size_t pa_sample_size(const pa_sample_spec *spec) { return 4; default: assert(0); + return 0; } } diff --git a/src/polypcore/core-util.c b/src/polypcore/core-util.c index 0e7f77a4e..bb6a3d85f 100644 --- a/src/polypcore/core-util.c +++ b/src/polypcore/core-util.c @@ -564,7 +564,7 @@ static int is_group(gid_t gid, const char *name) { data = pa_xmalloc(n); if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) { - pa_log(__FILE__": getgrgid_r(%u): %s", gid, pa_cstrerror(errno)); + pa_log(__FILE__": getgrgid_r(%u): %s", (unsigned)gid, pa_cstrerror(errno)); goto finish; } From 8f111b0adde21ef75cdfb7d6cf30169219256b22 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 May 2006 14:39:15 +0000 Subject: [PATCH 0854/1514] change return type of pa_cstrerror() to "const char*" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@949 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/error.c | 2 +- src/polyp/error.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/polyp/error.c b/src/polyp/error.c index ee9ce51b1..0e3b506f1 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -170,7 +170,7 @@ static char *tlsstr; #endif -char* pa_cstrerror(int errnum) { +const char* pa_cstrerror(int errnum) { const char *origbuf; #ifdef HAVE_STRERROR_R diff --git a/src/polyp/error.h b/src/polyp/error.h index 33507bfd4..1d7b2ca64 100644 --- a/src/polyp/error.h +++ b/src/polyp/error.h @@ -37,7 +37,7 @@ const char* pa_strerror(int error); * string to UTF-8. The function is thread safe but the returned string is * only guaranteed to exist until the thread exits or pa_cstrerror() is * called again from the same thread. */ -char* pa_cstrerror(int errnum); +const char* pa_cstrerror(int errnum); PA_C_DECL_END From 103154940d09855b102ab823f032e854f5327ba1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 May 2006 14:42:23 +0000 Subject: [PATCH 0855/1514] add new padsp utility: a $LD_PRELOAD wrapper for using the OSS API with polypaudio git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@950 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 23 +- src/utils/padsp.c | 1284 ++++++++++++++++++++++++++++++++++++++++++++ src/utils/padsp.in | 30 ++ 3 files changed, 1335 insertions(+), 2 deletions(-) create mode 100644 src/utils/padsp.c create mode 100644 src/utils/padsp.in diff --git a/src/Makefile.am b/src/Makefile.am index 30e735129..6327d5500 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -78,6 +78,7 @@ EXTRA_DIST = \ daemon/default.pa.in \ depmod.py \ daemon/esdcompat.sh.in \ + utils/padsp.in \ modules/module-defs.h.m4 polypconf_DATA = \ @@ -173,6 +174,24 @@ pabrowse_LDADD = $(AM_LDADD) libpolyp.la libpolyp-browse.la pabrowse_CFLAGS = $(AM_CFLAGS) pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +lib_LTLIBRARIES = +CLEANFILES= + +if HAVE_OSS +lib_LTLIBRARIES += libpolypdsp.la +libpolypdsp_la_SOURCES = utils/padsp.c +libpolypdsp_la_CFLAGS = $(AM_CFLAGS) +libpolypdsp_la_LIBADD = $(AM_LIBADD) libpolyp.la +libpolypdsp_la_LDFLAGS = -avoid-version + +CLEANFILES+=padsp +bin_SCRIPTS += padsp + +padsp: utils/padsp.in Makefile + sed -e 's,@LIBPOLYPDSP\@,$(libdir)/libpolypdsp.so,g' < $< > $@ + +endif + ################################### # Test programs # ################################### @@ -325,7 +344,7 @@ polypinclude_HEADERS += \ endif endif -lib_LTLIBRARIES = \ +lib_LTLIBRARIES += \ libpolyp.la \ libpolyp-simple.la @@ -1141,7 +1160,7 @@ suid: polypaudio chown root $< chmod u+s $< -CLEANFILES=esdcompat.sh client.conf default.pa daemon.conf +CLEANFILES+=esdcompat.sh client.conf default.pa daemon.conf esdcompat.sh: daemon/esdcompat.sh.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ diff --git a/src/utils/padsp.c b/src/utils/padsp.c new file mode 100644 index 000000000..06bdd575d --- /dev/null +++ b/src/utils/padsp.c @@ -0,0 +1,1284 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef _FILE_OFFSET_BITS +#undef _FILE_OFFSET_BITS +#endif + +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +typedef enum { + FD_INFO_MIXER, + FD_INFO_PLAYBACK +} fd_info_type_t; + +typedef struct fd_info fd_info; + +struct fd_info { + pthread_mutex_t mutex; + int ref; + + fd_info_type_t type; + int app_fd, thread_fd; + + pa_sample_spec sample_spec; + size_t fragment_size; + unsigned n_fragments; + + pa_threaded_mainloop *mainloop; + pa_context *context; + pa_stream *stream; + + pa_io_event *io_event; + + void *buf; + + int operation_success; + + PA_LLIST_FIELDS(fd_info); +}; + +static int dsp_drain(fd_info *i); + +static pthread_mutex_t fd_infos_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t func_mutex = PTHREAD_MUTEX_INITIALIZER; + +static PA_LLIST_HEAD(fd_info, fd_infos) = NULL; + +static int (*_ioctl)(int, int, void*) = NULL; +static int (*_close)(int) = NULL; +static int (*_open)(const char *, int, mode_t) = NULL; +static FILE* (*_fopen)(const char *path, const char *mode) = NULL; +static int (*_open64)(const char *, int, mode_t) = NULL; +static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; +static int (*_fclose)(FILE *f) = NULL; + +#define LOAD_IOCTL_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_ioctl) \ + _ioctl = (int (*)(int, int, void*)) dlsym(RTLD_NEXT, "ioctl"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_OPEN_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_open) \ + _open = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_OPEN64_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_open64) \ + _open64 = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open64"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_CLOSE_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_close) \ + _close = (int (*)(int)) dlsym(RTLD_NEXT, "close"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_FOPEN_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_fopen) \ + _fopen = (FILE* (*)(const char *, const char*)) dlsym(RTLD_NEXT, "fopen"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_FOPEN64_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_fopen64) \ + _fopen64 = (FILE* (*)(const char *, const char*)) dlsym(RTLD_NEXT, "fopen64"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_FCLOSE_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_fclose) \ + _fclose = (int (*)(FILE *)) dlsym(RTLD_NEXT, "fclose"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +static void debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); + +static void debug(const char *format, ...) { + va_list ap; + if (getenv("PADSP_DEBUG")) { + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + } +} + +static pthread_key_t recursion_key; + +static void recursion_key_alloc(void) { + pthread_key_create(&recursion_key, NULL); +} + +static int function_enter(void) { + /* Avoid recursive calls */ + static pthread_once_t recursion_key_once = PTHREAD_ONCE_INIT; + pthread_once(&recursion_key_once, recursion_key_alloc); + + if (pthread_getspecific(recursion_key)) + return 0; + + pthread_setspecific(recursion_key, (void*) 1); + return 1; +} + +static void function_exit(void) { + pthread_setspecific(recursion_key, NULL); +} + +static void fd_info_free(fd_info *i) { + assert(i); + + debug(__FILE__": freeing fd info (fd=%i)\n", i->app_fd); + + dsp_drain(i); + + if (i->mainloop) + pa_threaded_mainloop_stop(i->mainloop); + + if (i->stream) { + pa_stream_disconnect(i->stream); + pa_stream_unref(i->stream); + } + + if (i->context) { + pa_context_disconnect(i->context); + pa_context_unref(i->context); + } + + if (i->mainloop) + pa_threaded_mainloop_free(i->mainloop); + + if (i->app_fd >= 0) { + LOAD_CLOSE_FUNC(); + _close(i->app_fd); + } + + if (i->thread_fd >= 0) { + LOAD_CLOSE_FUNC(); + _close(i->thread_fd); + } + + free(i->buf); + + pthread_mutex_destroy(&i->mutex); + free(i); +} + +static fd_info *fd_info_ref(fd_info *i) { + assert(i); + + pthread_mutex_lock(&i->mutex); + assert(i->ref >= 1); + i->ref++; + +/* debug(__FILE__": ref++, now %i\n", i->ref); */ + pthread_mutex_unlock(&i->mutex); + + return i; +} + +static void fd_info_unref(fd_info *i) { + int r; + pthread_mutex_lock(&i->mutex); + assert(i->ref >= 1); + r = --i->ref; +/* debug(__FILE__": ref--, now %i\n", i->ref); */ + pthread_mutex_unlock(&i->mutex); + + if (r <= 0) + fd_info_free(i); +} + +static void context_state_cb(pa_context *c, void *userdata) { + fd_info *i = userdata; + assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: + pa_threaded_mainloop_signal(i->mainloop, 0); + break; + + case PA_CONTEXT_UNCONNECTED: + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + } +} + +static void reset_params(fd_info *i) { + assert(i); + + i->sample_spec.format = PA_SAMPLE_ULAW; + i->sample_spec.channels = 1; + i->sample_spec.rate = 8000; + i->fragment_size = 1024; + i->n_fragments = 0; +} + +static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { + fd_info *i; + int sfds[2] = { -1, -1 }; + + debug(__FILE__": fd_info_new()\n"); + + signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */ + + if (!(i = malloc(sizeof(fd_info)))) { + *_errno = ENOMEM; + goto fail; + } + + i->app_fd = i->thread_fd = -1; + i->type = type; + + i->mainloop = NULL; + i->context = NULL; + i->stream = NULL; + i->io_event = NULL; + pthread_mutex_init(&i->mutex, NULL); + i->ref = 1; + i->buf = NULL; + PA_LLIST_INIT(fd_info, i); + + reset_params(i); + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfds) < 0) { + *_errno = errno; + debug(__FILE__": socket() failed: %s\n", strerror(errno)); + goto fail; + } + + i->app_fd = sfds[0]; + i->thread_fd = sfds[1]; + + if (!(i->mainloop = pa_threaded_mainloop_new())) { + *_errno = EIO; + debug(__FILE__": pa_threaded_mainloop_new() failed\n"); + goto fail; + } + + if (!(i->context = pa_context_new(pa_threaded_mainloop_get_api(i->mainloop), "oss"))) { + *_errno = EIO; + debug(__FILE__": pa_context_new() failed\n"); + goto fail; + } + + pa_context_set_state_callback(i->context, context_state_cb, i); + + if (pa_context_connect(i->context, NULL, 0, NULL) < 0) { + *_errno = ECONNREFUSED; + debug(__FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + pa_threaded_mainloop_lock(i->mainloop); + + if (pa_threaded_mainloop_start(i->mainloop) < 0) { + *_errno = EIO; + debug(__FILE__": pa_threaded_mainloop_start() failed\n"); + goto unlock_and_fail; + } + + /* Wait until the context is ready */ + pa_threaded_mainloop_wait(i->mainloop); + + if (pa_context_get_state(i->context) != PA_CONTEXT_READY) { + *_errno = ECONNREFUSED; + debug(__FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto unlock_and_fail; + } + + pa_threaded_mainloop_unlock(i->mainloop); + return i; + +unlock_and_fail: + + pa_threaded_mainloop_unlock(i->mainloop); + +fail: + + if (i) + fd_info_unref(i); + + return NULL; +} + +static void fd_info_add_to_list(fd_info *i) { + assert(i); + + pthread_mutex_lock(&fd_infos_mutex); + PA_LLIST_PREPEND(fd_info, fd_infos, i); + pthread_mutex_unlock(&fd_infos_mutex); + + fd_info_ref(i); +} + +static void fd_info_remove_from_list(fd_info *i) { + assert(i); + + pthread_mutex_lock(&fd_infos_mutex); + PA_LLIST_REMOVE(fd_info, fd_infos, i); + pthread_mutex_unlock(&fd_infos_mutex); + + fd_info_unref(i); +} + +static fd_info* fd_info_find(int fd) { + fd_info *i; + + pthread_mutex_lock(&fd_infos_mutex); + + for (i = fd_infos; i; i = i->next) + if (i->app_fd == fd) { + fd_info_ref(i); + break; + } + + pthread_mutex_unlock(&fd_infos_mutex); + + return i; +} + +static void fix_metrics(fd_info *i) { + size_t fs; + char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; + + fs = pa_frame_size(&i->sample_spec); + i->fragment_size = (i->fragment_size/fs)*fs; + + if (i->n_fragments < 2) + i->n_fragments = 12; + + if (i->fragment_size <= 0) + if ((i->fragment_size = pa_bytes_per_second(&i->sample_spec) / 2 / i->n_fragments) <= 0) + i->fragment_size = 1024; + + debug(__FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); + debug(__FILE__": fixated metrics to %i fragments, %i bytes each.\n", i->n_fragments, i->fragment_size); +} + +static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { + fd_info *i = userdata; + assert(s); + + if (i->io_event) { + pa_mainloop_api *api; + api = pa_threaded_mainloop_get_api(i->mainloop); + api->io_enable(i->io_event, PA_IO_EVENT_INPUT); + } +} + +static void stream_latency_update_cb(pa_stream *s, void *userdata) { + fd_info *i = userdata; + assert(s); + + pa_threaded_mainloop_signal(i->mainloop, 0); +} + +static void fd_info_shutdown(fd_info *i) { + assert(i); + + if (i->io_event) { + pa_mainloop_api *api; + api = pa_threaded_mainloop_get_api(i->mainloop); + api->io_free(i->io_event); + i->io_event = NULL; + } + + if (i->thread_fd >= 0) { + close(i->thread_fd); + i->thread_fd = -1; + } +} + +static int fd_info_copy_data(fd_info *i, int force) { + size_t n; + + if (!i->stream) + return -1; + + if ((n = pa_stream_writable_size(i->stream)) == (size_t) -1) { + debug(__FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + return -1; + } + + while (n >= i->fragment_size || force) { + ssize_t r; + + if (!i->buf) { + if (!(i->buf = malloc(i->fragment_size))) { + debug(__FILE__": malloc() failed.\n"); + return -1; + } + } + + if ((r = read(i->thread_fd, i->buf, i->fragment_size)) <= 0) { + + if (errno == EAGAIN) + break; + + debug(__FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno)); + return -1; + } + + if (pa_stream_write(i->stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) { + debug(__FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); + return -1; + } + + i->buf = NULL; + + assert(n >= (size_t) r); + n -= r; + } + + if (i->io_event) { + pa_mainloop_api *api; + api = pa_threaded_mainloop_get_api(i->mainloop); + api->io_enable(i->io_event, n >= i->fragment_size ? PA_IO_EVENT_INPUT : 0); + } + + return 0; +} + +static void stream_state_cb(pa_stream *s, void * userdata) { + fd_info *i = userdata; + assert(s); + + switch (pa_stream_get_state(s)) { + + case PA_STREAM_READY: + debug(__FILE__": stream established.\n"); + break; + + case PA_STREAM_FAILED: + debug(__FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + fd_info_shutdown(i); + break; + + case PA_STREAM_TERMINATED: + case PA_STREAM_UNCONNECTED: + case PA_STREAM_CREATING: + break; + } +} + +static int create_stream(fd_info *i) { + pa_buffer_attr attr; + int n; + + assert(i); + + fix_metrics(i); + + if (!(i->stream = pa_stream_new(i->context, "audio stream", &i->sample_spec, NULL))) { + debug(__FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + pa_stream_set_state_callback(i->stream, stream_state_cb, i); + pa_stream_set_write_callback(i->stream, stream_request_cb, i); + pa_stream_set_latency_update_callback(i->stream, stream_latency_update_cb, i); + + memset(&attr, 0, sizeof(attr)); + attr.maxlength = i->fragment_size * (i->n_fragments+1); + attr.tlength = i->fragment_size * i->n_fragments; + attr.prebuf = i->fragment_size; + attr.minreq = i->fragment_size; + + if (pa_stream_connect_playback(i->stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { + debug(__FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + n = i->fragment_size; + setsockopt(i->app_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)); + n = i->fragment_size; + setsockopt(i->thread_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); + + return 0; + +fail: + return -1; +} + +static void free_stream(fd_info *i) { + assert(i); + + if (i->stream) { + pa_stream_disconnect(i->stream); + pa_stream_unref(i->stream); + i->stream = NULL; + } +} + +static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { + fd_info *i = userdata; + + pa_threaded_mainloop_signal(i->mainloop, 0); + + if (flags & PA_IO_EVENT_INPUT) { + + if (!i->stream) { + api->io_enable(e, 0); + + if (create_stream(i) < 0) + goto fail; + + } else { + if (fd_info_copy_data(i, 0) < 0) + goto fail; + } + + } else if (flags & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) + goto fail; + + return; + +fail: + /* We can't do anything better than removing the event source */ + fd_info_shutdown(i); +} + +static int dsp_open(int flags, int *_errno) { + fd_info *i; + pa_mainloop_api *api; + int ret; + int f; + + if ((flags != O_WRONLY) && (flags != (O_WRONLY|O_NONBLOCK))) { + *_errno = EACCES; + return -1; + } + + if (!(i = fd_info_new(FD_INFO_PLAYBACK, _errno))) + return -1; + + shutdown(i->thread_fd, SHUT_WR); + shutdown(i->app_fd, SHUT_RD); + + if ((flags & O_NONBLOCK) == O_NONBLOCK) { + if ((f = fcntl(i->app_fd, F_GETFL)) >= 0) + fcntl(i->app_fd, F_SETFL, f|O_NONBLOCK); + } + if ((f = fcntl(i->thread_fd, F_GETFL)) >= 0) + fcntl(i->thread_fd, F_SETFL, f|O_NONBLOCK); + + fcntl(i->app_fd, F_SETFD, FD_CLOEXEC); + fcntl(i->thread_fd, F_SETFD, FD_CLOEXEC); + + pa_threaded_mainloop_lock(i->mainloop); + api = pa_threaded_mainloop_get_api(i->mainloop); + if (!(i->io_event = api->io_new(api, i->thread_fd, PA_IO_EVENT_INPUT, io_event_cb, i))) + goto fail; + + pa_threaded_mainloop_unlock(i->mainloop); + + debug(__FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd); + + fd_info_add_to_list(i); + ret = i->app_fd; + fd_info_unref(i); + + return ret; + +fail: + pa_threaded_mainloop_unlock(i->mainloop); + + if (i) + fd_info_unref(i); + + *_errno = EIO; + + debug(__FILE__": dsp_open() failed\n"); + + return -1; +} + +static int mixer_open(int flags, int *_errno) { +/* fd_info *i; */ + + *_errno = ENOSYS; + return -1; + +/* if (!(i = fd_info_new(FD_INFO_MIXER))) */ +/* return -1; */ + +} + +int open(const char *filename, int flags, ...) { + va_list args; + mode_t mode = 0; + int r, _errno = 0; + + va_start(args, flags); + if (flags & O_CREAT) + mode = va_arg(args, mode_t); + va_end(args); + + if (!function_enter()) { + LOAD_OPEN_FUNC(); + return _open(filename, flags, mode); + } + + debug(__FILE__": open()\n"); + + if (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0) { + r = dsp_open(flags, &_errno); + } else if (strcmp(filename, "/dev/mixer") == 0) { + r = mixer_open(flags, &_errno); + } else { + function_exit(); + LOAD_OPEN_FUNC(); + return _open(filename, flags, mode); + } + + function_exit(); + + if (_errno) + errno = _errno; + + return r; +} + +static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { + *_errno = ENOSYS; + return -1; +} + +static int map_format(int *fmt, pa_sample_spec *ss) { + + switch (*fmt) { + case AFMT_MU_LAW: + ss->format = PA_SAMPLE_ULAW; + break; + + case AFMT_A_LAW: + ss->format = PA_SAMPLE_ALAW; + break; + + case AFMT_S8: + *fmt = AFMT_U8; + /* fall through */ + case AFMT_U8: + ss->format = PA_SAMPLE_U8; + break; + + case AFMT_U16_BE: + *fmt = AFMT_S16_BE; + /* fall through */ + case AFMT_S16_BE: + ss->format = PA_SAMPLE_S16BE; + break; + + case AFMT_U16_LE: + *fmt = AFMT_S16_LE; + /* fall through */ + case AFMT_S16_LE: + ss->format = PA_SAMPLE_S16LE; + break; + + default: + ss->format = PA_SAMPLE_S16NE; + *fmt = AFMT_S16_NE; + break; + } + + return 0; +} + +static int map_format_back(pa_sample_format_t format) { + switch (format) { + case PA_SAMPLE_S16LE: return AFMT_S16_LE; + case PA_SAMPLE_S16BE: return AFMT_S16_BE; + case PA_SAMPLE_ULAW: return AFMT_MU_LAW; + case PA_SAMPLE_ALAW: return AFMT_A_LAW; + case PA_SAMPLE_U8: return AFMT_U8; + default: + abort(); + } +} + +static void success_cb(pa_stream *s, int success, void *userdata) { + fd_info *i = userdata; + + assert(s); + assert(i); + + i->operation_success = success; + pa_threaded_mainloop_signal(i->mainloop, 0); +} + +static int dsp_empty_socket(fd_info *i) { + int ret = -1; + + /* Empty the socket */ + for (;;) { + int l; + + if (i->thread_fd < 0) + break; + + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { + debug(__FILE__": SIOCINQ: %s\n", strerror(errno)); + break; + } + + if (!l) + break; + + pa_threaded_mainloop_wait(i->mainloop); + } + + return ret; +} + +static int dsp_drain(fd_info *i) { + pa_operation *o = NULL; + int r = -1; + + if (!i->mainloop) + return 0; + + debug(__FILE__": Draining.\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + if (dsp_empty_socket(i) < 0) + goto fail; + + if (!i->stream) + goto fail; + + debug(__FILE__": Really draining.\n"); + + if (!(o = pa_stream_drain(i->stream, success_cb, i))) { + debug(__FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + i->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) + goto fail; + + pa_threaded_mainloop_wait(i->mainloop); + } + + if (!i->operation_success) { + debug(__FILE__": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + r = 0; + +fail: + + if (o) + pa_operation_unref(o); + + pa_threaded_mainloop_unlock(i->mainloop); + + return 0; +} + +static int dsp_trigger(fd_info *i) { + pa_operation *o = NULL; + int r = -1; + + fd_info_copy_data(i, 1); + + if (!i->stream) + return 0; + + pa_threaded_mainloop_lock(i->mainloop); + + if (dsp_empty_socket(i) < 0) + goto fail; + + debug(__FILE__": Triggering.\n"); + + if (!(o = pa_stream_trigger(i->stream, success_cb, i))) { + debug(__FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + i->operation_success = 0; + while (!pa_operation_get_state(o) != PA_OPERATION_DONE) { + if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) + goto fail; + + pa_threaded_mainloop_wait(i->mainloop); + } + + if (!i->operation_success) { + debug(__FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + r = 0; + +fail: + + if (o) + pa_operation_unref(o); + + pa_threaded_mainloop_unlock(i->mainloop); + + return 0; +} + +static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { + int ret = -1; + + switch (request) { + case SNDCTL_DSP_SETFMT: { + debug(__FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp); + + pa_threaded_mainloop_lock(i->mainloop); + + if (*(int*) argp == AFMT_QUERY) + *(int*) argp = map_format_back(i->sample_spec.format); + else { + map_format((int*) argp, &i->sample_spec); + free_stream(i); + } + + pa_threaded_mainloop_unlock(i->mainloop); + break; + } + + case SNDCTL_DSP_SPEED: { + pa_sample_spec ss; + int valid; + + debug(__FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp); + + pa_threaded_mainloop_lock(i->mainloop); + + ss = i->sample_spec; + ss.rate = *(int*) argp; + + if ((valid = pa_sample_spec_valid(&ss))) { + i->sample_spec = ss; + free_stream(i); + } + + pa_threaded_mainloop_unlock(i->mainloop); + + if (!valid) { + *_errno = EINVAL; + goto fail; + } + + break; + } + + case SNDCTL_DSP_STEREO: + debug(__FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp); + + pa_threaded_mainloop_lock(i->mainloop); + + i->sample_spec.channels = *(int*) argp ? 2 : 1; + free_stream(i); + + pa_threaded_mainloop_unlock(i->mainloop); + return 0; + + case SNDCTL_DSP_CHANNELS: { + pa_sample_spec ss; + int valid; + + debug(__FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp); + + pa_threaded_mainloop_lock(i->mainloop); + + ss = i->sample_spec; + ss.channels = *(int*) argp; + + if ((valid = pa_sample_spec_valid(&ss))) { + i->sample_spec = ss; + free_stream(i); + } + + pa_threaded_mainloop_unlock(i->mainloop); + + if (!valid) { + *_errno = EINVAL; + goto fail; + } + + break; + } + + case SNDCTL_DSP_GETBLKSIZE: + debug(__FILE__": SNDCTL_DSP_GETBLKSIZE\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + fix_metrics(i); + *(int*) argp = i->fragment_size; + + pa_threaded_mainloop_unlock(i->mainloop); + + break; + + case SNDCTL_DSP_SETFRAGMENT: + debug(__FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%8x\n", *(int*) argp); + + pa_threaded_mainloop_lock(i->mainloop); + + i->fragment_size = 1 << (*(int*) argp); + i->n_fragments = (*(int*) argp) >> 16; + + free_stream(i); + + pa_threaded_mainloop_unlock(i->mainloop); + + break; + + case SNDCTL_DSP_GETCAPS: + debug(__FILE__": SNDCTL_DSP_CAPS\n"); + + *(int*) argp = DSP_CAP_MULTI; + break; + + case SNDCTL_DSP_GETODELAY: { + int l; + + debug(__FILE__": SNDCTL_DSP_GETODELAY\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + *(int*) argp = 0; + + for (;;) { + pa_usec_t usec; + if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) + break; + + if (pa_stream_get_latency(i->stream, &usec, NULL) >= 0) { + *(int*) argp = pa_usec_to_bytes(usec, &i->sample_spec); + break; + } + + if (pa_context_errno(i->context) != PA_ERR_NODATA) { + debug(__FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context))); + break; + } + + pa_threaded_mainloop_wait(i->mainloop); + } + + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) + debug(__FILE__": SIOCINQ failed: %s\n", strerror(errno)); + else + *(int*) argp += l; + + pa_threaded_mainloop_unlock(i->mainloop); + + debug(__FILE__": ODELAY: %i\n", *(int*) argp); + + break; + } + + case SNDCTL_DSP_RESET: { + debug(__FILE__": SNDCTL_DSP_RESET\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + free_stream(i); + reset_params(i); + + pa_threaded_mainloop_unlock(i->mainloop); + break; + } + + case SNDCTL_DSP_GETFMTS: { + debug(__FILE__": SNDCTL_DSP_GETFMTS\n"); + + *(int*) argp = AFMT_MU_LAW|AFMT_A_LAW|AFMT_U8|AFMT_S16_LE|AFMT_S16_BE; + break; + } + + case SNDCTL_DSP_POST: + debug(__FILE__": SNDCTL_DSP_POST\n"); + + if (dsp_trigger(i) < 0) + *_errno = EIO; + break; + + case SNDCTL_DSP_SYNC: + debug(__FILE__": SNDCTL_DSP_SYNC\n"); + + if (dsp_drain(i) < 0) + *_errno = EIO; + + break; + + case SNDCTL_DSP_GETOSPACE: { + audio_buf_info *bi = (audio_buf_info*) argp; + int l; + size_t k = 0; + + debug(__FILE__": SNDCTL_DSP_GETOSPACE\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + fix_metrics(i); + + if (i->stream) { + if ((k = pa_stream_writable_size(i->stream)) == (size_t) -1) + debug(__FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + } else + k = i->fragment_size * i->n_fragments; + + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { + debug(__FILE__": SIOCINQ failed: %s\n", strerror(errno)); + l = 0; + } + + bi->fragsize = i->fragment_size; + bi->fragstotal = i->n_fragments; + bi->bytes = k > (size_t) l ? k - l : 0; + bi->fragments = bi->bytes / bi->fragsize; + + pa_threaded_mainloop_unlock(i->mainloop); + + debug(__FILE__": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi->fragsize, bi->fragstotal, bi->bytes, bi->fragments); + + break; + } + + default: + debug(__FILE__": unknwon ioctl 0x%08lx\n", request); + + *_errno = EINVAL; + goto fail; + } + + ret = 0; + +fail: + + return ret; +} + +int ioctl(int fd, unsigned long request, ...) { + fd_info *i; + va_list args; + void *argp; + int r, _errno = 0; + + debug(__FILE__": ioctl()\n"); + + va_start(args, request); + argp = va_arg(args, void *); + va_end(args); + + if (!function_enter()) { + LOAD_IOCTL_FUNC(); + return _ioctl(fd, request, argp); + } + + if (!(i = fd_info_find(fd))) { + function_exit(); + LOAD_IOCTL_FUNC(); + return _ioctl(fd, request, argp); + } + + if (i->type == FD_INFO_MIXER) + r = mixer_ioctl(i, request, argp, &_errno); + else + r = dsp_ioctl(i, request, argp, &_errno); + + fd_info_unref(i); + + if (_errno) + errno = _errno; + + function_exit(); + + return r; +} + +int close(int fd) { + fd_info *i; + + debug(__FILE__": close()\n"); + + if (!function_enter()) { + LOAD_CLOSE_FUNC(); + return _close(fd); + } + + if (!(i = fd_info_find(fd))) { + function_exit(); + LOAD_CLOSE_FUNC(); + return _close(fd); + } + + fd_info_remove_from_list(i); + fd_info_unref(i); + + function_exit(); + + return 0; +} + +int open64(const char *filename, int flags, ...) { + va_list args; + mode_t mode = 0; + + debug(__FILE__": open64()\n"); + + va_start(args, flags); + if (flags & O_CREAT) + mode = va_arg(args, mode_t); + va_end(args); + + if (strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/mixer") != 0) { + LOAD_OPEN64_FUNC(); + return _open64(filename, flags, mode); + } + + return open(filename, flags, mode); +} + +FILE* fopen(const char *filename, const char *mode) { + FILE *f = NULL; + int fd; + + debug(__FILE__": fopen()\n"); + + if (strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/mixer") != 0) { + LOAD_FOPEN_FUNC(); + return _fopen(filename, mode); + } + + if (strcmp(mode, "wb") != 0) { + errno = EACCES; + return NULL; + } + + if ((fd = open(filename, O_WRONLY)) < 0) + return NULL; + + if (!(f = fdopen(fd, "wb"))) { + close(fd); + return NULL; + } + + return f; +} + +FILE *fopen64(const char *filename, const char *mode) { + + debug(__FILE__": fopen64()\n"); + + if (strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/mixer") != 0) { + LOAD_FOPEN64_FUNC(); + return _fopen64(filename, mode); + } + + return fopen(filename, mode); +} + +int fclose(FILE *f) { + fd_info *i; + + debug(__FILE__": fclose()\n"); + + if (!function_enter()) { + LOAD_FCLOSE_FUNC(); + return _fclose(f); + } + + if (!(i = fd_info_find(fileno(f)))) { + function_exit(); + LOAD_FCLOSE_FUNC(); + return _fclose(f); + } + + fd_info_remove_from_list(i); + + /* Dirty trick to avoid that the fd is not freed twice, once by us + * and once by the real fclose() */ + i->app_fd = -1; + + fd_info_unref(i); + + function_exit(); + + LOAD_FCLOSE_FUNC(); + return _fclose(f); +} diff --git a/src/utils/padsp.in b/src/utils/padsp.in new file mode 100644 index 000000000..d82e92fe9 --- /dev/null +++ b/src/utils/padsp.in @@ -0,0 +1,30 @@ +#!/bin/sh + +# $Id$ +# +# This file is part of polypaudio. +# +# polypaudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# polypaudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with polypaudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +if [ x"$LD_PRELOAD" = x ] ; then + LD_PRELOAD="@LIBPOLYPDSP@" +else + LD_PRELOAD="$LD_PRELOAD @LIBPOLYPDSP@" +fi + +export LD_PRELOAD + +exec "$@" From 7906985d2af27a187eac7260f641a07c39bb705e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 23 May 2006 15:24:29 +0000 Subject: [PATCH 0856/1514] Cast size_t to long to be more compatible with 64-bit systems. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@951 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 06bdd575d..63f79eb1e 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -417,7 +417,7 @@ static void fix_metrics(fd_info *i) { i->fragment_size = 1024; debug(__FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); - debug(__FILE__": fixated metrics to %i fragments, %i bytes each.\n", i->n_fragments, i->fragment_size); + debug(__FILE__": fixated metrics to %i fragments, %li bytes each.\n", i->n_fragments, (long)i->fragment_size); } static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { From e99afdae388018f119c16c3a331e01898ab9a90a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 May 2006 16:37:33 +0000 Subject: [PATCH 0857/1514] pass the binary name as client name to polypaudio git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@952 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 63f79eb1e..ec073a288 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -278,9 +278,21 @@ static void reset_params(fd_info *i) { i->n_fragments = 0; } +static char *client_name(char *buf, size_t n) { + char p[PATH_MAX]; + + if (pa_get_binary_name(p, sizeof(p))) + snprintf(buf, n, "oss[%s]", pa_path_get_filename(p)); + else + snprintf(buf, n, "oss"); + + return buf; +} + static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { fd_info *i; int sfds[2] = { -1, -1 }; + char name[64]; debug(__FILE__": fd_info_new()\n"); @@ -320,7 +332,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { goto fail; } - if (!(i->context = pa_context_new(pa_threaded_mainloop_get_api(i->mainloop), "oss"))) { + if (!(i->context = pa_context_new(pa_threaded_mainloop_get_api(i->mainloop), client_name(name, sizeof(name))))) { *_errno = EIO; debug(__FILE__": pa_context_new() failed\n"); goto fail; From 23b123d361959553fc9e467dd4b605adee00f07e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 May 2006 23:06:28 +0000 Subject: [PATCH 0858/1514] - use pthread_atfork() to disable open sound streams in the child after a fork. Obviusly sound won't work in child process but at least we don't leak fds from the parent. Now any operation on the device fd in the child will result in an EBADF error, which seems somewhat clean to me. - flush our unix socket properly on RESET ioctl git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@953 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 128 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 122 insertions(+), 6 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index ec073a288..a69676ab2 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -60,6 +60,7 @@ typedef struct fd_info fd_info; struct fd_info { pthread_mutex_t mutex; int ref; + int unusable; fd_info_type_t type; int app_fd, thread_fd; @@ -82,6 +83,7 @@ struct fd_info { }; static int dsp_drain(fd_info *i); +static void fd_info_remove_from_list(fd_info *i); static pthread_mutex_t fd_infos_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t func_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -289,14 +291,101 @@ static char *client_name(char *buf, size_t n) { return buf; } +static void atfork_prepare(void) { + fd_info *i; + + debug(__FILE__": atfork_prepare() enter\n"); + + function_enter(); + + pthread_mutex_lock(&fd_infos_mutex); + + for (i = fd_infos; i; i = i->next) { + pthread_mutex_lock(&i->mutex); + pa_threaded_mainloop_lock(i->mainloop); + } + + pthread_mutex_lock(&func_mutex); + + + debug(__FILE__": atfork_prepare() exit\n"); +} + +static void atfork_parent(void) { + fd_info *i; + + debug(__FILE__": atfork_parent() enter\n"); + + pthread_mutex_unlock(&func_mutex); + + for (i = fd_infos; i; i = i->next) { + pa_threaded_mainloop_unlock(i->mainloop); + pthread_mutex_unlock(&i->mutex); + } + + pthread_mutex_unlock(&fd_infos_mutex); + + function_exit(); + + debug(__FILE__": atfork_parent() exit\n"); +} + +static void atfork_child(void) { + fd_info *i; + + debug(__FILE__": atfork_child() enter\n"); + + /* We do only the bare minimum to get all fds closed */ + pthread_mutex_init(&func_mutex, NULL); + pthread_mutex_init(&fd_infos_mutex, NULL); + + for (i = fd_infos; i; i = i->next) { + pthread_mutex_init(&i->mutex, NULL); + + if (i->context) { + pa_context_disconnect(i->context); + pa_context_unref(i->context); + i->context = NULL; + } + + if (i->stream) { + pa_stream_unref(i->stream); + i->stream = NULL; + } + + if (i->app_fd >= 0) { + close(i->app_fd); + i->app_fd = -1; + } + + if (i->thread_fd >= 0) { + close(i->thread_fd); + i->thread_fd = -1; + } + + i->unusable = 1; + } + + function_exit(); + + debug(__FILE__": atfork_child() exit\n"); +} + +static void install_atfork(void) { + pthread_atfork(atfork_prepare, atfork_parent, atfork_child); +} + static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { fd_info *i; int sfds[2] = { -1, -1 }; char name[64]; + static pthread_once_t install_atfork_once = PTHREAD_ONCE_INIT; debug(__FILE__": fd_info_new()\n"); signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */ + + pthread_once(&install_atfork_once, install_atfork); if (!(i = malloc(sizeof(fd_info)))) { *_errno = ENOMEM; @@ -313,6 +402,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { pthread_mutex_init(&i->mutex, NULL); i->ref = 1; i->buf = NULL; + i->unusable = 0; PA_LLIST_INIT(fd_info, i); reset_params(i); @@ -404,7 +494,7 @@ static fd_info* fd_info_find(int fd) { pthread_mutex_lock(&fd_infos_mutex); for (i = fd_infos; i; i = i->next) - if (i->app_fd == fd) { + if (i->app_fd == fd && !i->unusable) { fd_info_ref(i); break; } @@ -546,7 +636,7 @@ static int create_stream(fd_info *i) { fix_metrics(i); - if (!(i->stream = pa_stream_new(i->context, "audio stream", &i->sample_spec, NULL))) { + if (!(i->stream = pa_stream_new(i->context, "Audio Stream", &i->sample_spec, NULL))) { debug(__FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -784,6 +874,30 @@ static void success_cb(pa_stream *s, int success, void *userdata) { pa_threaded_mainloop_signal(i->mainloop, 0); } +static int dsp_flush_socket(fd_info *i) { + int l; + + if (i->thread_fd < 0) + return -1; + + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { + debug(__FILE__": SIOCINQ: %s\n", strerror(errno)); + return -1; + } + + while (l > 0) { + char buf[1024]; + size_t k; + + k = (size_t) l > sizeof(buf) ? sizeof(buf) : (size_t) l; + if (read(i->thread_fd, buf, k) < 0) + debug(__FILE__": read(): %s\n", strerror(errno)); + l -= k; + } + + return 0; +} + static int dsp_empty_socket(fd_info *i) { int ret = -1; @@ -791,7 +905,7 @@ static int dsp_empty_socket(fd_info *i) { for (;;) { int l; - if (i->thread_fd < 0) + if (i->thread_fd < 0 || !i->stream) break; if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { @@ -861,8 +975,6 @@ static int dsp_trigger(fd_info *i) { pa_operation *o = NULL; int r = -1; - fd_info_copy_data(i, 1); - if (!i->stream) return 0; @@ -926,6 +1038,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_SPEED: { pa_sample_spec ss; int valid; + char t[256]; debug(__FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp); @@ -939,13 +1052,15 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) free_stream(i); } + debug(__FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); + pa_threaded_mainloop_unlock(i->mainloop); if (!valid) { *_errno = EINVAL; goto fail; } - + break; } @@ -1063,6 +1178,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_lock(i->mainloop); free_stream(i); + dsp_flush_socket(i); reset_params(i); pa_threaded_mainloop_unlock(i->mainloop); From 46fee4641864df8972beb95f9d9af5670198add9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 May 2006 23:57:50 +0000 Subject: [PATCH 0859/1514] implement emulation of /dev/sndstat git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@954 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 117 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 15 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index a69676ab2..ed34ac8ab 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -771,11 +771,83 @@ static int mixer_open(int flags, int *_errno) { } +static int sndstat_open(int flags, int *_errno) { + static const char sndstat[] = + "Sound Driver:3.8.1a-980706 (Polypaudio Virtual OSS)\n" + "Kernel: POSIX\n" + "Config options: 0\n" + "\n" + "Installed drivers:\n" + "Type 255: Polypaudio Virtual OSS\n" + "\n" + "Card config:\n" + "Polypaudio Virtual OSS\n" + "\n" + "Audio devices:\n" + "0: Polypaudio Virtual OSS\n" + "\n" + "Synth devices: NOT ENABLED IN CONFIG\n" + "\n" + "Midi devices:\n" + "\n" + "Timers:\n" + "\n" + "\Mixers:\n" + "0: Polypaudio Virtual OSS\n"; + + char fn[] = "/tmp/padsp-sndstat-XXXXXX"; + mode_t u; + int fd = -1; + int e; + + debug(__FILE__": sndstat_open()\n"); + + if (flags != O_RDONLY && flags != (O_RDONLY|O_LARGEFILE)) { + *_errno = EACCES; + debug(__FILE__": bad access!\n"); + goto fail; + } + + u = umask(0077); + fd = mkstemp(fn); + e = errno; + umask(u); + + if (fd < 0) { + *_errno = e; + debug(__FILE__": mkstemp() failed: %s\n", strerror(errno)); + goto fail; + } + + unlink(fn); + + if (write(fd, sndstat, sizeof(sndstat) -1) != sizeof(sndstat)-1) { + *_errno = errno; + debug(__FILE__": write() failed: %s\n", strerror(errno)); + goto fail; + } + + if (lseek(fd, SEEK_SET, 0) < 0) { + *_errno = errno; + debug(__FILE__": lseek() failed: %s\n", strerror(errno)); + goto fail; + } + + return fd; + +fail: + if (fd >= 0) + close(fd); + return -1; +} + int open(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; int r, _errno = 0; + debug(__FILE__": open(%s)\n", filename); + va_start(args, flags); if (flags & O_CREAT) mode = va_arg(args, mode_t); @@ -786,12 +858,12 @@ int open(const char *filename, int flags, ...) { return _open(filename, flags, mode); } - debug(__FILE__": open()\n"); - if (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0) { r = dsp_open(flags, &_errno); } else if (strcmp(filename, "/dev/mixer") == 0) { r = mixer_open(flags, &_errno); + } else if (strcmp(filename, "/dev/sndstat") == 0) { + r = sndstat_open(flags, &_errno); } else { function_exit(); LOAD_OPEN_FUNC(); @@ -1321,7 +1393,7 @@ int open64(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; - debug(__FILE__": open64()\n"); + debug(__FILE__": open64(%s)\n", filename); va_start(args, flags); if (flags & O_CREAT) @@ -1330,6 +1402,7 @@ int open64(const char *filename, int flags, ...) { if (strcmp(filename, "/dev/dsp") != 0 && strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/sndstat") != 0 && strcmp(filename, "/dev/mixer") != 0) { LOAD_OPEN64_FUNC(); return _open64(filename, flags, mode); @@ -1341,25 +1414,38 @@ int open64(const char *filename, int flags, ...) { FILE* fopen(const char *filename, const char *mode) { FILE *f = NULL; int fd; + mode_t m; + + debug(__FILE__": fopen(%s)\n", filename); - debug(__FILE__": fopen()\n"); + if (strcmp(filename, "/dev/dsp") == 0 || + strcmp(filename, "/dev/adsp") == 0) { - if (strcmp(filename, "/dev/dsp") != 0 && - strcmp(filename, "/dev/adsp") != 0 && - strcmp(filename, "/dev/mixer") != 0) { + if (strcmp(mode, "wb") != 0) { + errno = EACCES; + return NULL; + } + + m = O_WRONLY; + } else if (strcmp(filename, "/dev/sndstat") == 0) { + + if (strcmp(mode, "r") != 0) { + errno = EACCES; + return NULL; + } + + m = O_RDONLY; + } else if (strcmp(filename, "/dev/mixer") != 0) + m = O_RDWR; + else { LOAD_FOPEN_FUNC(); return _fopen(filename, mode); } - if (strcmp(mode, "wb") != 0) { - errno = EACCES; - return NULL; - } - - if ((fd = open(filename, O_WRONLY)) < 0) + if ((fd = open(filename, m)) < 0) return NULL; - if (!(f = fdopen(fd, "wb"))) { + if (!(f = fdopen(fd, mode))) { close(fd); return NULL; } @@ -1369,10 +1455,11 @@ FILE* fopen(const char *filename, const char *mode) { FILE *fopen64(const char *filename, const char *mode) { - debug(__FILE__": fopen64()\n"); + debug(__FILE__": fopen64(%s)\n", filename); if (strcmp(filename, "/dev/dsp") != 0 && strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/sndstat") != 0 && strcmp(filename, "/dev/mixer") != 0) { LOAD_FOPEN64_FUNC(); return _fopen64(filename, mode); From 440b901a4d445de6695e3fa41853a694d677516e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 May 2006 00:42:30 +0000 Subject: [PATCH 0860/1514] fix playback of small sound files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@955 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index ed34ac8ab..d9325df48 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -977,7 +977,7 @@ static int dsp_empty_socket(fd_info *i) { for (;;) { int l; - if (i->thread_fd < 0 || !i->stream) + if (i->thread_fd < 0) break; if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { @@ -985,8 +985,10 @@ static int dsp_empty_socket(fd_info *i) { break; } - if (!l) + if (!l) { + ret = 0; break; + } pa_threaded_mainloop_wait(i->mainloop); } From ca08e57470d0a6ce1bcbfb853288aa7d3a08efe1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 May 2006 02:13:29 +0000 Subject: [PATCH 0861/1514] implement a /dev/mixer interface git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@956 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 288 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 262 insertions(+), 26 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index d9325df48..b85d9c4d9 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -79,6 +79,10 @@ struct fd_info { int operation_success; + pa_cvolume volume; + uint32_t sink_index; + int volume_modify_count; + PA_LLIST_FIELDS(fd_info); }; @@ -154,6 +158,21 @@ do { \ pthread_mutex_unlock(&func_mutex); \ } while(0) +#define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \ +if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ + debug(__FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + goto label; \ +} \ +} while(0); + +#define STREAM_CHECK_DEAD_GOTO(i, label) do { \ +if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ + !(i)->stream || pa_stream_get_state((i)->stream) != PA_STREAM_READY) { \ + debug(__FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + goto label; \ +} \ +} while(0); + static void debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); static void debug(const char *format, ...) { @@ -375,6 +394,26 @@ static void install_atfork(void) { pthread_atfork(atfork_prepare, atfork_parent, atfork_child); } +static void stream_success_cb(pa_stream *s, int success, void *userdata) { + fd_info *i = userdata; + + assert(s); + assert(i); + + i->operation_success = success; + pa_threaded_mainloop_signal(i->mainloop, 0); +} + +static void context_success_cb(pa_context *c, int success, void *userdata) { + fd_info *i = userdata; + + assert(c); + assert(i); + + i->operation_success = success; + pa_threaded_mainloop_signal(i->mainloop, 0); +} + static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { fd_info *i; int sfds[2] = { -1, -1 }; @@ -403,6 +442,9 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { i->ref = 1; i->buf = NULL; i->unusable = 0; + pa_cvolume_reset(&i->volume, 2); + i->volume_modify_count = 0; + i->sink_index = (uint32_t) -1; PA_LLIST_INIT(fd_info, i); reset_params(i); @@ -760,15 +802,118 @@ fail: return -1; } +static void sink_info_cb(pa_context *context, const pa_sink_info *si, int eol, void *userdata) { + fd_info *i = userdata; + + if (!si && eol < 0) { + i->operation_success = 0; + pa_threaded_mainloop_signal(i->mainloop, 0); + return; + } + + if (eol) + return; + + if (!pa_cvolume_equal(&i->volume, &si->volume)) + i->volume_modify_count++; + + i->volume = si->volume; + i->sink_index = si->index; + + i->operation_success = 1; + pa_threaded_mainloop_signal(i->mainloop, 0); +} + +static void subscribe_cb(pa_context *context, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + fd_info *i = userdata; + pa_operation *o = NULL; + + if (i->sink_index != idx) + return; + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) + return; + + if (!(o = pa_context_get_sink_info_by_index(i->context, i->sink_index, sink_info_cb, i))) { + debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + return; + } + + pa_operation_unref(o); +} + static int mixer_open(int flags, int *_errno) { -/* fd_info *i; */ + fd_info *i; + pa_operation *o; + int ret; + + if (!(i = fd_info_new(FD_INFO_MIXER, _errno))) + return -1; + + pa_threaded_mainloop_lock(i->mainloop); + + pa_context_set_subscribe_callback(i->context, subscribe_cb, i); + + if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK, context_success_cb, i))) { + debug(__FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + + i->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(i->mainloop); + CONTEXT_CHECK_DEAD_GOTO(i, fail); + } + + if (!i->operation_success) { + debug(__FILE__":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + + /* Get sink info */ + + pa_operation_unref(o); + if (!(o = pa_context_get_sink_info_by_name(i->context, NULL, sink_info_cb, i))) { + debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + + i->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(i->mainloop); + CONTEXT_CHECK_DEAD_GOTO(i, fail); + } + + if (!i->operation_success) { + debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + + pa_threaded_mainloop_unlock(i->mainloop); + + debug(__FILE__": mixer_open() succeeded, fd=%i\n", i->app_fd); + + fd_info_add_to_list(i); + ret = i->app_fd; + fd_info_unref(i); + + return ret; + +fail: + pa_threaded_mainloop_unlock(i->mainloop); + + if (i) + fd_info_unref(i); + + *_errno = EIO; + + debug(__FILE__": mixer_open() failed\n"); - *_errno = ENOSYS; return -1; - -/* if (!(i = fd_info_new(FD_INFO_MIXER))) */ -/* return -1; */ - } static int sndstat_open(int flags, int *_errno) { @@ -879,8 +1024,109 @@ int open(const char *filename, int flags, ...) { } static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { - *_errno = ENOSYS; - return -1; + int ret = -1; + + switch (request) { + case SOUND_MIXER_READ_DEVMASK : + debug(__FILE__": SOUND_MIXER_READ_DEVMASK\n"); + + *(int*) argp = SOUND_MASK_PCM; + break; + + case SOUND_MIXER_READ_RECMASK : + debug(__FILE__": SOUND_MIXER_READ_RECMASK\n"); + + *(int*) argp = 0; + break; + + case SOUND_MIXER_READ_STEREODEVS: + debug(__FILE__": SOUND_MIXER_READ_STEREODEVS\n"); + + pa_threaded_mainloop_lock(i->mainloop); + *(int*) argp = i->volume.channels > 1 ? SOUND_MASK_PCM : 0; + pa_threaded_mainloop_unlock(i->mainloop); + + break; + + case SOUND_MIXER_READ_RECSRC: + debug(__FILE__": SOUND_MIXER_READ_RECSRC\n"); + + *(int*) argp = 0; + break; + + case SOUND_MIXER_CAPS: + debug(__FILE__": SOUND_MIXER_CAPS\n"); + + *(int*) argp = 0; + break; + + case SOUND_MIXER_READ_PCM: + + debug(__FILE__": SOUND_MIXER_READ_PCM\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + *(int*) argp = + ((i->volume.values[0]*100/PA_VOLUME_NORM) << 8) | + ((i->volume.values[i->volume.channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM)); + + pa_threaded_mainloop_unlock(i->mainloop); + + break; + + case SOUND_MIXER_WRITE_PCM: { + pa_cvolume v; + + debug(__FILE__": SOUND_MIXER_WRITE_PCM\n"); + + pa_threaded_mainloop_lock(i->mainloop); + + v = i->volume; + + i->volume.values[0] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100; + i->volume.values[1] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100; + + if (!pa_cvolume_equal(&i->volume, &v)) { + pa_operation *o; + + if (!(o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, &i->volume, NULL, NULL))) + debug(__FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); + else + pa_operation_unref(o); + + /* We don't wait for completion here */ + i->volume_modify_count++; + } + + pa_threaded_mainloop_unlock(i->mainloop); + + break; + } + + case SOUND_MIXER_INFO: { + mixer_info *mi = argp; + + memset(mi, 0, sizeof(mixer_info)); + strncpy(mi->id, "POLYPAUDIO", sizeof(mi->id)); + strncpy(mi->name, "Polypaudio Virtual OSS", sizeof(mi->name)); + pa_threaded_mainloop_lock(i->mainloop); + mi->modify_counter = i->volume_modify_count; + pa_threaded_mainloop_unlock(i->mainloop); + break; + } + + default: + debug(__FILE__": unknwon ioctl 0x%08lx\n", request); + + *_errno = EINVAL; + goto fail; + } + + ret = 0; + +fail: + + return ret; } static int map_format(int *fmt, pa_sample_spec *ss) { @@ -936,16 +1182,6 @@ static int map_format_back(pa_sample_format_t format) { } } -static void success_cb(pa_stream *s, int success, void *userdata) { - fd_info *i = userdata; - - assert(s); - assert(i); - - i->operation_success = success; - pa_threaded_mainloop_signal(i->mainloop, 0); -} - static int dsp_flush_socket(fd_info *i) { int l; @@ -1015,15 +1251,14 @@ static int dsp_drain(fd_info *i) { debug(__FILE__": Really draining.\n"); - if (!(o = pa_stream_drain(i->stream, success_cb, i))) { + if (!(o = pa_stream_drain(i->stream, stream_success_cb, i))) { debug(__FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } i->operation_success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { - if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) - goto fail; + STREAM_CHECK_DEAD_GOTO(i, fail); pa_threaded_mainloop_wait(i->mainloop); } @@ -1059,15 +1294,14 @@ static int dsp_trigger(fd_info *i) { debug(__FILE__": Triggering.\n"); - if (!(o = pa_stream_trigger(i->stream, success_cb, i))) { + if (!(o = pa_stream_trigger(i->stream, stream_success_cb, i))) { debug(__FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } i->operation_success = 0; while (!pa_operation_get_state(o) != PA_OPERATION_DONE) { - if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) - goto fail; + STREAM_CHECK_DEAD_GOTO(i, fail); pa_threaded_mainloop_wait(i->mainloop); } @@ -1218,8 +1452,8 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) for (;;) { pa_usec_t usec; - if (!i->stream || pa_stream_get_state(i->stream) != PA_STREAM_READY) - break; + + STREAM_CHECK_DEAD_GOTO(i, exit_loop); if (pa_stream_get_latency(i->stream, &usec, NULL) >= 0) { *(int*) argp = pa_usec_to_bytes(usec, &i->sample_spec); @@ -1234,6 +1468,8 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_wait(i->mainloop); } + exit_loop: + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) debug(__FILE__": SIOCINQ failed: %s\n", strerror(errno)); else From c4328cdfddb16cf43ae4037b087cf2c58d7c531d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 24 May 2006 08:14:19 +0000 Subject: [PATCH 0862/1514] Fix stray \ git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@957 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b85d9c4d9..10b08eaef 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -937,7 +937,7 @@ static int sndstat_open(int flags, int *_errno) { "\n" "Timers:\n" "\n" - "\Mixers:\n" + "Mixers:\n" "0: Polypaudio Virtual OSS\n"; char fn[] = "/tmp/padsp-sndstat-XXXXXX"; From 2843b1a318aa1a01da465031d713ca2238b39d4c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 24 May 2006 13:22:16 +0000 Subject: [PATCH 0863/1514] Remove the exceedingly anal warnings. It's impossible to write a non-trivial C program and not trigger these. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@958 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index fadc02198..18dba96d5 100644 --- a/configure.ac +++ b/configure.ac @@ -87,7 +87,7 @@ if test "x$GCC" = "xyes" ; then # We use gnu99 instead of c99 because many have interpreted the standard # in a way that int64_t isn't defined on non-64 bit platforms. - DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter" + DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter" for flag in $DESIRED_FLAGS ; do AC_MSG_CHECKING([whether $CC accepts $flag]) From 3fa19ab457ff71d148a6dff5eb7362582e82ce61 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 24 May 2006 13:23:15 +0000 Subject: [PATCH 0864/1514] Fix warnings. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@959 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/stream.c | 2 +- src/polypcore/modinfo.c | 15 +++++++++++---- src/polypcore/module.c | 11 +++++++++-- src/polypcore/pipe.h | 4 ++++ src/polypcore/protocol-esound.c | 2 -- src/polypcore/random.c | 2 +- src/polypcore/x11wrap.c | 3 ++- src/utils/padsp.c | 21 ++++++++++++++------- 8 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 2e1680452..e41c588e5 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -872,7 +872,7 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t pa_operation *o; pa_tagstruct *t; struct timeval now; - int cidx; + int cidx = 0; assert(s); assert(s->ref >= 1); diff --git a/src/polypcore/modinfo.c b/src/polypcore/modinfo.c index 4a9be0f04..a2fffb01f 100644 --- a/src/polypcore/modinfo.c +++ b/src/polypcore/modinfo.c @@ -38,6 +38,13 @@ #define PA_SYMBOL_USAGE "pa__get_usage" #define PA_SYMBOL_VERSION "pa__get_version" +/* lt_dlsym() violates ISO C, so confide the breakage into this function to + * avoid warnings. */ +typedef void (*fnptr)(void); +static inline fnptr lt_dlsym_fn(lt_dlhandle handle, const char *symbol) { + return (fnptr) (long) lt_dlsym(handle, symbol); +} + pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) { pa_modinfo *i; const char* (*func)(void); @@ -45,16 +52,16 @@ pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) { i = pa_xnew0(pa_modinfo, 1); - if ((func = (const char* (*)(void)) lt_dlsym(dl, PA_SYMBOL_AUTHOR))) + if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_AUTHOR))) i->author = pa_xstrdup(func()); - if ((func = (const char* (*)(void)) lt_dlsym(dl, PA_SYMBOL_DESCRIPTION))) + if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_DESCRIPTION))) i->description = pa_xstrdup(func()); - if ((func = (const char* (*)(void)) lt_dlsym(dl, PA_SYMBOL_USAGE))) + if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_USAGE))) i->usage = pa_xstrdup(func()); - if ((func = (const char* (*)(void)) lt_dlsym(dl, PA_SYMBOL_VERSION))) + if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_VERSION))) i->version = pa_xstrdup(func()); return i; diff --git a/src/polypcore/module.c b/src/polypcore/module.c index 0286bba85..b938750c8 100644 --- a/src/polypcore/module.c +++ b/src/polypcore/module.c @@ -44,6 +44,13 @@ #define UNLOAD_POLL_TIME 2 +/* lt_dlsym() violates ISO C, so confide the breakage into this function to + * avoid warnings. */ +typedef void (*fnptr)(void); +static inline fnptr lt_dlsym_fn(lt_dlhandle handle, const char *symbol) { + return (fnptr) (long) lt_dlsym(handle, symbol); +} + static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { pa_core *c = userdata; struct timeval ntv; @@ -75,12 +82,12 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { goto fail; } - if (!(m->init = (int (*)(pa_core *_c, pa_module*_m)) lt_dlsym(m->dl, PA_SYMBOL_INIT))) { + if (!(m->init = (int (*)(pa_core *_c, pa_module*_m)) lt_dlsym_fn(m->dl, PA_SYMBOL_INIT))) { pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name); goto fail; } - if (!(m->done = (void (*)(pa_core *_c, pa_module*_m)) lt_dlsym(m->dl, PA_SYMBOL_DONE))) { + if (!(m->done = (void (*)(pa_core *_c, pa_module*_m)) lt_dlsym_fn(m->dl, PA_SYMBOL_DONE))) { pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.", name); goto fail; } diff --git a/src/polypcore/pipe.h b/src/polypcore/pipe.h index e91677829..276b072d2 100644 --- a/src/polypcore/pipe.h +++ b/src/polypcore/pipe.h @@ -22,6 +22,10 @@ USA. ***/ +#ifndef HAVE_PIPE + int pipe(int filedes[2]); #endif + +#endif diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 01a72e849..d7c9475a5 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -515,7 +515,6 @@ static int esd_proto_server_info(struct connection *c, PA_GCC_UNUSED esd_proto_t } static int esd_proto_all_info(struct connection *c, esd_proto_t request, const void *data, size_t length) { - uint8_t *response; size_t t, k, s; struct connection *conn; uint32_t idx = PA_IDXSET_INVALID; @@ -585,7 +584,6 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v } assert(t == s*(nsamples+1)+k); - response += k; t -= k; connection_write(c, terminator, k); diff --git a/src/polypcore/random.c b/src/polypcore/random.c index 4bfce975d..d7a37b0b0 100644 --- a/src/polypcore/random.c +++ b/src/polypcore/random.c @@ -48,7 +48,7 @@ static int random_proper(void *ret_data, size_t length) { #else /* OS_IS_WIN32 */ - int fd, ret; + int fd, ret = -1; ssize_t r = 0; const char **device; diff --git a/src/polypcore/x11wrap.c b/src/polypcore/x11wrap.c index 41a407645..b53a43b60 100644 --- a/src/polypcore/x11wrap.c +++ b/src/polypcore/x11wrap.c @@ -107,9 +107,10 @@ static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC /* Add a new IO source for the specified X11 internal connection */ static pa_x11_internal* x11_internal_add(pa_x11_wrapper *w, int fd) { pa_x11_internal *i; - assert(i && fd >= 0); + assert(fd >= 0); i = pa_xmalloc(sizeof(pa_x11_internal)); + assert(i); i->wrapper = w; i->io_event = w->core->mainloop->io_new(w->core->mainloop, fd, PA_IO_EVENT_INPUT, internal_io_event, w); i->fd = fd; diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 10b08eaef..87d0b2572 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -102,11 +102,18 @@ static int (*_open64)(const char *, int, mode_t) = NULL; static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; static int (*_fclose)(FILE *f) = NULL; +/* dlsym() violates ISO C, so confide the breakage into this function to + * avoid warnings. */ +typedef void (*fnptr)(void); +static inline fnptr dlsym_fn(void *handle, const char *symbol) { + return (fnptr) (long) dlsym(handle, symbol); +} + #define LOAD_IOCTL_FUNC() \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_ioctl) \ - _ioctl = (int (*)(int, int, void*)) dlsym(RTLD_NEXT, "ioctl"); \ + _ioctl = (int (*)(int, int, void*)) dlsym_fn(RTLD_NEXT, "ioctl"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -114,7 +121,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_open) \ - _open = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open"); \ + _open = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -122,7 +129,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_open64) \ - _open64 = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open64"); \ + _open64 = (int (*)(const char *, int, mode_t)) dlsym_fn(RTLD_NEXT, "open64"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -130,7 +137,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_close) \ - _close = (int (*)(int)) dlsym(RTLD_NEXT, "close"); \ + _close = (int (*)(int)) dlsym_fn(RTLD_NEXT, "close"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -138,7 +145,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_fopen) \ - _fopen = (FILE* (*)(const char *, const char*)) dlsym(RTLD_NEXT, "fopen"); \ + _fopen = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -146,7 +153,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_fopen64) \ - _fopen64 = (FILE* (*)(const char *, const char*)) dlsym(RTLD_NEXT, "fopen64"); \ + _fopen64 = (FILE* (*)(const char *, const char*)) dlsym_fn(RTLD_NEXT, "fopen64"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) @@ -154,7 +161,7 @@ do { \ do { \ pthread_mutex_lock(&func_mutex); \ if (!_fclose) \ - _fclose = (int (*)(FILE *)) dlsym(RTLD_NEXT, "fclose"); \ + _fclose = (int (*)(FILE *)) dlsym_fn(RTLD_NEXT, "fclose"); \ pthread_mutex_unlock(&func_mutex); \ } while(0) From 6a7172e91c942abcd999ed19074d1664aea6fec2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 24 May 2006 15:38:11 +0000 Subject: [PATCH 0865/1514] padsp needs dlsym & co so make sure we get that lib included. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@960 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 18dba96d5..004053c2a 100644 --- a/configure.ac +++ b/configure.ac @@ -214,6 +214,7 @@ AC_SEARCH_LIBS([pow], [m]) # POSIX AC_SEARCH_LIBS([sched_setscheduler], [rt]) +AC_SEARCH_LIBS([dlopen], [dl]) # BSD AC_SEARCH_LIBS([connect], [socket]) From 0fb63e7b0a0328319c4200074d3e54ef74e5948e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 00:12:06 +0000 Subject: [PATCH 0866/1514] update TODO git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@961 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/todo b/doc/todo index bf3365aba..b2c3577e4 100644 --- a/doc/todo +++ b/doc/todo @@ -30,6 +30,8 @@ Post 0.8: and we tend to pass it to functions that require UTF-8. - fix clock of the NULL sink - gettextify polypaudio +- add API to query the bufferattrs after stream creation +- move libpadsp.so to /usr/lib/polypaudio/ or something, and move the modules to /usr/lib/polypaudio/modules/0.9.0/ Long term: - pass meta info for hearing impaired From 59d00e2f49f709630cd3c55b28e752fa5d7919fb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 00:25:03 +0000 Subject: [PATCH 0867/1514] * issue volume updates syncrhonously * correct channel order of OSS volumes (swap left,right) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@962 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 87d0b2572..d372b6976 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1074,8 +1074,8 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = - ((i->volume.values[0]*100/PA_VOLUME_NORM) << 8) | - ((i->volume.values[i->volume.channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM)); + ((i->volume.values[0]*100/PA_VOLUME_NORM)) | + ((i->volume.values[i->volume.channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM) << 8); pa_threaded_mainloop_unlock(i->mainloop); @@ -1090,16 +1090,29 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno v = i->volume; - i->volume.values[0] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100; - i->volume.values[1] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100; + i->volume.values[0] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100; + i->volume.values[1] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100; if (!pa_cvolume_equal(&i->volume, &v)) { pa_operation *o; if (!(o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, &i->volume, NULL, NULL))) debug(__FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); - else + else { + + i->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + CONTEXT_CHECK_DEAD_GOTO(i, exit_loop); + + pa_threaded_mainloop_wait(i->mainloop); + } + exit_loop: + + if (!i->operation_success) + debug(__FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context))); + pa_operation_unref(o); + } /* We don't wait for completion here */ i->volume_modify_count++; From 2bb05ea6678ff27f37ac082d01dcb9fd14889613 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 00:40:04 +0000 Subject: [PATCH 0868/1514] fix evil, evil typo that cause all gtk2 based apps to crash git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@963 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index d372b6976..746965d7d 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1693,7 +1693,7 @@ FILE* fopen(const char *filename, const char *mode) { } m = O_RDONLY; - } else if (strcmp(filename, "/dev/mixer") != 0) + } else if (strcmp(filename, "/dev/mixer") == 0) m = O_RDWR; else { LOAD_FOPEN_FUNC(); From 2bbd7bac63a48361d3d848ba1d3838a0ef5eb2bd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 01:14:06 +0000 Subject: [PATCH 0869/1514] add support to disable emulation of /dev/dsp,/dev/mixer,/dev/sndstat selectively by either passing an environment variable or by defining a symbol __padsp_disable__ in the process git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@964 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 61 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 746965d7d..2f0f72603 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -191,6 +191,61 @@ static void debug(const char *format, ...) { } } +static int padsp_disabled(void) { + static int *sym; + static int sym_resolved = 0; + + /* If the current process has a symbol __padsp_disabled__ we use + * it to detect whether we should enable our stuff or not. A + * program needs to be compiled with -rdynamic for this to work! + * The symbol must be an int containing a three bit bitmask: bit 1 + * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat + * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value + * 7 disables padsp entirely. */ + + pthread_mutex_lock(&func_mutex); + if (!sym_resolved) { + sym = (int*) dlsym_fn(RTLD_DEFAULT, "__padsp_disabled__"); + sym_resolved = 1; + + } + pthread_mutex_unlock(&func_mutex); + + if (!sym) + return 0; + + return *sym; +} + +static int dsp_cloak_enable(void) { + if (padsp_disabled() & 1) + return 0; + + if (getenv("PADSP_NO_DSP")) + return 0; + + return 1; +} + +static int sndstat_cloak_enable(void) { + if (padsp_disabled() & 2) + return 0; + + if (getenv("PADSP_NO_SNDSTAT")) + return 0; + + return 1; +} + +static int mixer_cloak_enable(void) { + if (padsp_disabled() & 4) + return 0; + + if (getenv("PADSP_NO_MIXER")) + return 0; + + return 1; +} static pthread_key_t recursion_key; static void recursion_key_alloc(void) { @@ -1010,11 +1065,11 @@ int open(const char *filename, int flags, ...) { return _open(filename, flags, mode); } - if (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0) { + if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) { r = dsp_open(flags, &_errno); - } else if (strcmp(filename, "/dev/mixer") == 0) { + } else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) { r = mixer_open(flags, &_errno); - } else if (strcmp(filename, "/dev/sndstat") == 0) { + } else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) { r = sndstat_open(flags, &_errno); } else { function_exit(); From ae80ab396e9aa764b16b436b7b7c66011dce513c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 01:19:56 +0000 Subject: [PATCH 0870/1514] read stream and client name from $PADSP_STREAM_NAME resp. $PADSP_CLIENT_NAME, if available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@965 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 2f0f72603..5987ec5fa 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -201,7 +201,7 @@ static int padsp_disabled(void) { * The symbol must be an int containing a three bit bitmask: bit 1 * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value - * 7 disables padsp entirely. */ + * of 7 disables padsp entirely. */ pthread_mutex_lock(&func_mutex); if (!sym_resolved) { @@ -363,15 +363,28 @@ static void reset_params(fd_info *i) { static char *client_name(char *buf, size_t n) { char p[PATH_MAX]; + const char *e; + + if ((e = getenv("PADSP_CLIENT_NAME"))) + return e; if (pa_get_binary_name(p, sizeof(p))) - snprintf(buf, n, "oss[%s]", pa_path_get_filename(p)); + snprintf(buf, n, "OSS Emulation[%s]", pa_path_get_filename(p)); else - snprintf(buf, n, "oss"); + snprintf(buf, n, "OSS"); return buf; } +static char *stream_name(void) { + const char *e; + + if ((e = getenv("PADSP_STREAM_NAME"))) + return e; + + return "Audio Stream"; +} + static void atfork_prepare(void) { fd_info *i; @@ -740,7 +753,7 @@ static int create_stream(fd_info *i) { fix_metrics(i); - if (!(i->stream = pa_stream_new(i->context, "Audio Stream", &i->sample_spec, NULL))) { + if (!(i->stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) { debug(__FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } From e07b2620f3838d178cdc42c7ba6225277287f46e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 01:26:10 +0000 Subject: [PATCH 0871/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@966 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/todo b/doc/todo index b2c3577e4..8d73f25b2 100644 --- a/doc/todo +++ b/doc/todo @@ -1,6 +1,11 @@ *** $Id$ *** -Post 0.8: +Pre 0.9.0 +- add API to query the bufferattrs after stream creation +- move libpadsp.so to /usr/lib/polypaudio/ or something, and move the modules to /usr/lib/polypaudio/modules/0.9.0/ +- add proper padsp script that makes $PADSP_xxx env vars from the command line arguments, just like esddsp does + +Post 0.9.0: - alsa mmap driver - dbus/hal - polish for starting polypaudio as root/system-wide instance @@ -30,8 +35,6 @@ Post 0.8: and we tend to pass it to functions that require UTF-8. - fix clock of the NULL sink - gettextify polypaudio -- add API to query the bufferattrs after stream creation -- move libpadsp.so to /usr/lib/polypaudio/ or something, and move the modules to /usr/lib/polypaudio/modules/0.9.0/ Long term: - pass meta info for hearing impaired @@ -40,4 +43,4 @@ Long term: Backends for: - portaudio (semi-done) - sdl -- OSS (esddsp style) +- xine (needs update) From fc8a2c4a3616a9a97eeb60e22065615f5c13e888 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 13:29:36 +0000 Subject: [PATCH 0872/1514] add item about moving pa_cstrerror() to TODO git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@967 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/todo b/doc/todo index 8d73f25b2..58b2fa6c9 100644 --- a/doc/todo +++ b/doc/todo @@ -2,8 +2,9 @@ Pre 0.9.0 - add API to query the bufferattrs after stream creation -- move libpadsp.so to /usr/lib/polypaudio/ or something, and move the modules to /usr/lib/polypaudio/modules/0.9.0/ +- move the modules to /usr/lib/polypaudio-0.9.0/modules - add proper padsp script that makes $PADSP_xxx env vars from the command line arguments, just like esddsp does +- move pa_cstrerror() to polypcore/core-error.h Post 0.9.0: - alsa mmap driver From 1799b7ac332e0309437c41c676358078cc1f659c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 May 2006 13:31:28 +0000 Subject: [PATCH 0873/1514] Move libpolypdsp in the makefile to avoid the libtool bug where it must come after any things it depends on. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@968 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 6327d5500..a298397b6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -174,24 +174,6 @@ pabrowse_LDADD = $(AM_LDADD) libpolyp.la libpolyp-browse.la pabrowse_CFLAGS = $(AM_CFLAGS) pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -lib_LTLIBRARIES = -CLEANFILES= - -if HAVE_OSS -lib_LTLIBRARIES += libpolypdsp.la -libpolypdsp_la_SOURCES = utils/padsp.c -libpolypdsp_la_CFLAGS = $(AM_CFLAGS) -libpolypdsp_la_LIBADD = $(AM_LIBADD) libpolyp.la -libpolypdsp_la_LDFLAGS = -avoid-version - -CLEANFILES+=padsp -bin_SCRIPTS += padsp - -padsp: utils/padsp.in Makefile - sed -e 's,@LIBPOLYPDSP\@,$(libdir)/libpolypdsp.so,g' < $< > $@ - -endif - ################################### # Test programs # ################################### @@ -344,7 +326,7 @@ polypinclude_HEADERS += \ endif endif -lib_LTLIBRARIES += \ +lib_LTLIBRARIES = \ libpolyp.la \ libpolyp-simple.la @@ -467,6 +449,29 @@ libpolyp_mainloop_glib12_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) libpolyp_mainloop_glib12_la_LIBADD = $(AM_LIBADD) libpolyp.la $(GLIB12_LIBS) libpolyp_mainloop_glib12_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO) +################################### +# OSS emulation # +################################### + +CLEANFILES= + +if HAVE_OSS + +lib_LTLIBRARIES += libpolypdsp.la + +CLEANFILES += padsp +bin_SCRIPTS += padsp + +endif + +libpolypdsp_la_SOURCES = utils/padsp.c +libpolypdsp_la_CFLAGS = $(AM_CFLAGS) +libpolypdsp_la_LIBADD = $(AM_LIBADD) libpolyp.la +libpolypdsp_la_LDFLAGS = -avoid-version + +padsp: utils/padsp.in Makefile + sed -e 's,@LIBPOLYPDSP\@,$(libdir)/libpolypdsp.so,g' < $< > $@ + ################################### # Daemon core library # ################################### From 0387b30994185a44e6df737c529ddda24325c671 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 May 2006 13:56:14 +0000 Subject: [PATCH 0874/1514] Use only the basename of libpolypdsp.so so that it will work on multi-arch systems. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@969 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 12 +++--------- src/utils/{padsp.in => padsp} | 4 ++-- 2 files changed, 5 insertions(+), 11 deletions(-) rename src/utils/{padsp.in => padsp} (91%) diff --git a/src/Makefile.am b/src/Makefile.am index a298397b6..16b5e9e31 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -78,7 +78,7 @@ EXTRA_DIST = \ daemon/default.pa.in \ depmod.py \ daemon/esdcompat.sh.in \ - utils/padsp.in \ + utils/padsp \ modules/module-defs.h.m4 polypconf_DATA = \ @@ -453,14 +453,11 @@ libpolyp_mainloop_glib12_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VER # OSS emulation # ################################### -CLEANFILES= - if HAVE_OSS lib_LTLIBRARIES += libpolypdsp.la -CLEANFILES += padsp -bin_SCRIPTS += padsp +bin_SCRIPTS += utils/padsp endif @@ -469,9 +466,6 @@ libpolypdsp_la_CFLAGS = $(AM_CFLAGS) libpolypdsp_la_LIBADD = $(AM_LIBADD) libpolyp.la libpolypdsp_la_LDFLAGS = -avoid-version -padsp: utils/padsp.in Makefile - sed -e 's,@LIBPOLYPDSP\@,$(libdir)/libpolypdsp.so,g' < $< > $@ - ################################### # Daemon core library # ################################### @@ -1165,7 +1159,7 @@ suid: polypaudio chown root $< chmod u+s $< -CLEANFILES+=esdcompat.sh client.conf default.pa daemon.conf +CLEANFILES = esdcompat.sh client.conf default.pa daemon.conf esdcompat.sh: daemon/esdcompat.sh.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ diff --git a/src/utils/padsp.in b/src/utils/padsp similarity index 91% rename from src/utils/padsp.in rename to src/utils/padsp index d82e92fe9..9f38cf3d2 100644 --- a/src/utils/padsp.in +++ b/src/utils/padsp @@ -20,9 +20,9 @@ # USA. if [ x"$LD_PRELOAD" = x ] ; then - LD_PRELOAD="@LIBPOLYPDSP@" + LD_PRELOAD="libpolypdsp.so" else - LD_PRELOAD="$LD_PRELOAD @LIBPOLYPDSP@" + LD_PRELOAD="$LD_PRELOAD libpolypdsp.so" fi export LD_PRELOAD From ea7995b764ed716bbe17576ebdba3a435de095d3 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 May 2006 15:44:24 +0000 Subject: [PATCH 0875/1514] Fix padsp script so that it accepts parameters, setting relevant environment variables as needed. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@970 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/utils/padsp b/src/utils/padsp index 9f38cf3d2..dc89bfb73 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -19,6 +19,57 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. +while getopts 'hs:n:m:MSDd' param ; do + case $param in + s) + POLYP_SERVER="$OPTARG" + export POLYP_SERVER + ;; + n) + PA_CLIENT_NAME="$OPTARG" + export PA_CLIENT_NAME + ;; + m) + PA_STREAM_NAME="$OPTARG" + export PA_STREAM_NAME + ;; + M) + PA_NO_MIXER=1 + export PA_NO_MIXER + ;; + S) + PA_NO_SNDSTAT=1 + export PA_NO_SNDSTAT + ;; + D) + PA_NO_DSP=1 + export PA_NO_DSP + ;; + d) + PADSP_DEBUG=1 + export PADSP_DEBUG + ;; + *) + echo "$0 - redirect OSS audio devices to Polypaudio" + echo " " + echo "$0 [options] application [arguments]" + echo " " + echo "options:" + echo " -h show brief help" + echo " -s [:] contact a specific Polypaudio server" + echo " -n client name to report to the server" + echo " -m stream name to report to the server" + echo " -M disable /dev/mixer emulation" + echo " -S disable /dev/sndstat emulation" + echo " -D disable /dev/dsp emulation" + echo " -d enable debug output" + exit 0 + ;; + esac +done + +shift $(( $OPTIND - 1 )) + if [ x"$LD_PRELOAD" = x ] ; then LD_PRELOAD="libpolypdsp.so" else From f8aa55c5ac1f21fec9e1a5f0351328fb33366f2a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 16:05:11 +0000 Subject: [PATCH 0876/1514] move modules to ${libdir}/polypaudio-${PA_MAJORMINOR}/modules/ git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@971 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 ++-- doc/todo | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 004053c2a..157c01a4b 100644 --- a/configure.ac +++ b/configure.ac @@ -437,8 +437,8 @@ fi AC_ARG_WITH( [module-dir], - AC_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${libdir}/polypaudio-${PA_MAJORMINOR}]), - [modlibexecdir=$withval], [modlibexecdir="${libdir}/polypaudio-${PA_MAJORMINOR}"]) + AC_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${libdir}/polypaudio-${PA_MAJORMINOR}/modules/]), + [modlibexecdir=$withval], [modlibexecdir="${libdir}/polypaudio-${PA_MAJORMINOR}/modules/"]) AC_SUBST(modlibexecdir) diff --git a/doc/todo b/doc/todo index 58b2fa6c9..1d17d3cc8 100644 --- a/doc/todo +++ b/doc/todo @@ -2,7 +2,6 @@ Pre 0.9.0 - add API to query the bufferattrs after stream creation -- move the modules to /usr/lib/polypaudio-0.9.0/modules - add proper padsp script that makes $PADSP_xxx env vars from the command line arguments, just like esddsp does - move pa_cstrerror() to polypcore/core-error.h From 4413b89d7a45587b545a31463ad2196767f45563 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 17:16:55 +0000 Subject: [PATCH 0877/1514] * split pa_cstrerror() into its own file polypcore/core-error.[ch] * fix building of padsp * remove a warning when compiling padsp.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@972 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 - src/Makefile.am | 6 +- src/daemon/caps.c | 2 +- src/daemon/daemon-conf.c | 2 +- src/daemon/main.c | 2 +- src/modules/module-alsa-source.c | 2 +- src/modules/module-detect.c | 2 +- src/modules/module-esound-compat-spawnfd.c | 3 +- src/modules/module-esound-compat-spawnpid.c | 3 +- src/modules/module-esound-sink.c | 2 +- src/modules/module-jack-sink.c | 2 +- src/modules/module-jack-source.c | 2 +- src/modules/module-match.c | 2 +- src/modules/module-mmkbd-evdev.c | 2 +- src/modules/module-oss-mmap.c | 2 +- src/modules/module-oss.c | 2 +- src/modules/module-pipe-sink.c | 2 +- src/modules/module-pipe-source.c | 2 +- src/modules/module-protocol-stub.c | 2 +- src/modules/module-volume-restore.c | 2 +- src/modules/oss-util.c | 3 +- src/modules/rtp/module-rtp-recv.c | 2 +- src/modules/rtp/module-rtp-send.c | 2 +- src/modules/rtp/rtp.c | 3 +- src/modules/rtp/sap.c | 2 +- src/polyp/client-conf.c | 2 +- src/polyp/context.c | 2 +- src/polyp/error.c | 214 +++----------------- src/polyp/error.h | 6 - src/polyp/mainloop-signal.c | 2 +- src/polyp/mainloop.c | 2 +- src/polyp/util.c | 3 +- src/polypcore/authkey.c | 2 +- src/polypcore/cli-command.c | 2 +- src/polypcore/conf-parser.c | 2 +- src/polypcore/core-error.c | 205 +++++++++++++++++++ src/polypcore/core-error.h | 41 ++++ src/polypcore/core-scache.c | 2 +- src/polypcore/core-util.c | 2 +- src/polypcore/iochannel.c | 2 +- src/polypcore/ioline.c | 2 +- src/polypcore/pid.c | 2 +- src/polypcore/protocol-esound.c | 2 +- src/polypcore/protocol-simple.c | 2 +- src/polypcore/socket-client.c | 2 +- src/polypcore/socket-server.c | 2 +- src/polypcore/socket-util.c | 2 +- src/utils/pacmd.c | 14 +- src/utils/padsp.c | 4 +- 49 files changed, 324 insertions(+), 255 deletions(-) create mode 100644 src/polypcore/core-error.c create mode 100644 src/polypcore/core-error.h diff --git a/doc/todo b/doc/todo index 1d17d3cc8..0b78ee935 100644 --- a/doc/todo +++ b/doc/todo @@ -2,8 +2,6 @@ Pre 0.9.0 - add API to query the bufferattrs after stream creation -- add proper padsp script that makes $PADSP_xxx env vars from the command line arguments, just like esddsp does -- move pa_cstrerror() to polypcore/core-error.h Post 0.9.0: - alsa mmap driver diff --git a/src/Makefile.am b/src/Makefile.am index 16b5e9e31..3a8c9bba7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -402,6 +402,7 @@ libpolyp_la_SOURCES += \ polypcore/strbuf.c polypcore/strbuf.h \ polypcore/strlist.c polypcore/strlist.h \ polypcore/tagstruct.c polypcore/tagstruct.h \ + polypcore/core-error.c polypcore/core-error.h \ polypcore/winsock.h if OS_IS_WIN32 @@ -574,7 +575,8 @@ libpolypcore_la_SOURCES += \ polypcore/source-output.c polypcore/source-output.h \ polypcore/strbuf.c polypcore/strbuf.h \ polypcore/tokenizer.c polypcore/tokenizer.h \ - polypcore/winsock.h + polypcore/winsock.h \ + polypcore/core-error.c polypcore/core-error.h if OS_IS_WIN32 libpolypcore_la_SOURCES += \ @@ -1186,3 +1188,5 @@ install-exec-hook: chmod u+s $(DESTDIR)$(bindir)/polypaudio ln -sf pacat $(DESTDIR)$(bindir)/parec rm -f $(DESTDIR)$(modlibexecdir)/*.a + +.PHONY: utils/padsp diff --git a/src/daemon/caps.c b/src/daemon/caps.c index 4942868c1..5e24da821 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -32,7 +32,7 @@ #include #endif -#include +#include #include diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 809769f8e..2d8d9558c 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -29,9 +29,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/daemon/main.c b/src/daemon/main.c index 2fadd496c..b88f932c3 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -50,11 +50,11 @@ #include "../polypcore/winsock.h" -#include #include #include #include +#include #include #include #include diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index c72b03224..414efda88 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -34,9 +34,9 @@ #include -#include #include +#include #include #include #include diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index e4f2e3f97..d0a377330 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -33,9 +33,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index f59e9e218..861e25709 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -28,8 +28,7 @@ #include #include -#include - +#include #include #include #include diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index c14ce12a6..7b47bb0ac 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -28,8 +28,7 @@ #include #include -#include - +#include #include #include #include diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 72298679e..53a9411a4 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -33,9 +33,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index db2ba0303..fc2bfc452 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -36,9 +36,9 @@ #include -#include #include +#include #include #include #include diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 8816fb8ac..ca9560a68 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -36,9 +36,9 @@ #include -#include #include +#include #include #include #include diff --git a/src/modules/module-match.c b/src/modules/module-match.c index f68f0c615..02d75e7ef 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -32,9 +32,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index d6c91e2e5..ee2c6bffd 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -33,9 +33,9 @@ #include -#include #include +#include #include #include #include diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index dac7d7f33..5cf6228f2 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -36,9 +36,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 8e2178555..887246733 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -35,9 +35,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index f0569ce99..01598e388 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -33,9 +33,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index 77212ce59..be2a28d51 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -33,9 +33,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 8eba352b6..2b4f303b1 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -42,9 +42,9 @@ #include "../polypcore/winsock.h" -#include #include +#include #include #include #include diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 796e43a36..435f0c965 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -32,9 +32,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 027921c56..ff337a5ce 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -34,8 +34,7 @@ #include #include -#include - +#include #include #include diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 8d9b33c2a..c448502ee 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -31,10 +31,10 @@ #include #include -#include #include #include +#include #include #include #include diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index c8b3899a2..4359d00d4 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -32,11 +32,11 @@ #include #include -#include #include #include #include +#include #include #include #include diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index 012d65785..52a1819c6 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -36,8 +36,7 @@ #include #endif -#include - +#include #include #include "rtp.h" diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index 238ee4200..134bab095 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -38,9 +38,9 @@ #include #endif -#include #include +#include #include #include diff --git a/src/polyp/client-conf.c b/src/polyp/client-conf.c index 0b3154c84..e1934ce14 100644 --- a/src/polyp/client-conf.c +++ b/src/polyp/client-conf.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include diff --git a/src/polyp/context.c b/src/polyp/context.c index eb5638197..68fb4bf3e 100644 --- a/src/polyp/context.c +++ b/src/polyp/context.c @@ -47,7 +47,7 @@ #include "../polypcore/winsock.h" -#include +#include #include #include diff --git a/src/polyp/error.c b/src/polyp/error.c index 0e3b506f1..27da7eae9 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -28,15 +28,6 @@ #include #include -#ifdef HAVE_PTHREAD -#include -#endif - -#ifdef HAVE_WINDOWS_H -#include -#endif - -#include #include #include @@ -44,191 +35,32 @@ #include "error.h" -static const char* const errortab[PA_ERR_MAX] = { - [PA_OK] = "OK", - [PA_ERR_ACCESS] = "Access denied", - [PA_ERR_COMMAND] = "Unknown command", - [PA_ERR_INVALID] = "Invalid argument", - [PA_ERR_EXIST] = "Entity exists", - [PA_ERR_NOENTITY] = "No such entity", - [PA_ERR_CONNECTIONREFUSED] = "Connection refused", - [PA_ERR_PROTOCOL] = "Protocol error", - [PA_ERR_TIMEOUT] = "Timeout", - [PA_ERR_AUTHKEY] = "No authorization key", - [PA_ERR_INTERNAL] = "Internal error", - [PA_ERR_CONNECTIONTERMINATED] = "Connection terminated", - [PA_ERR_KILLED] = "Entity killed", - [PA_ERR_INVALIDSERVER] = "Invalid server", - [PA_ERR_MODINITFAILED] = "Module initalization failed", - [PA_ERR_BADSTATE] = "Bad state", - [PA_ERR_NODATA] = "No data", - [PA_ERR_VERSION] = "Incompatible protocol version", - [PA_ERR_TOOLARGE] = "Too large" -}; - const char*pa_strerror(int error) { + + static const char* const errortab[PA_ERR_MAX] = { + [PA_OK] = "OK", + [PA_ERR_ACCESS] = "Access denied", + [PA_ERR_COMMAND] = "Unknown command", + [PA_ERR_INVALID] = "Invalid argument", + [PA_ERR_EXIST] = "Entity exists", + [PA_ERR_NOENTITY] = "No such entity", + [PA_ERR_CONNECTIONREFUSED] = "Connection refused", + [PA_ERR_PROTOCOL] = "Protocol error", + [PA_ERR_TIMEOUT] = "Timeout", + [PA_ERR_AUTHKEY] = "No authorization key", + [PA_ERR_INTERNAL] = "Internal error", + [PA_ERR_CONNECTIONTERMINATED] = "Connection terminated", + [PA_ERR_KILLED] = "Entity killed", + [PA_ERR_INVALIDSERVER] = "Invalid server", + [PA_ERR_MODINITFAILED] = "Module initalization failed", + [PA_ERR_BADSTATE] = "Bad state", + [PA_ERR_NODATA] = "No data", + [PA_ERR_VERSION] = "Incompatible protocol version", + [PA_ERR_TOOLARGE] = "Too large" + }; + if (error < 0 || error >= PA_ERR_MAX) return NULL; return errortab[error]; } - -#ifdef HAVE_PTHREAD - -static pthread_once_t cstrerror_once = PTHREAD_ONCE_INIT; -static pthread_key_t tlsstr_key; - -static void inittls(void) { - int ret; - - ret = pthread_key_create(&tlsstr_key, pa_xfree); - if (ret) { - fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", errno); - exit(-1); - } -} - -#elif HAVE_WINDOWS_H - -static DWORD tlsstr_key = TLS_OUT_OF_INDEXES; -static DWORD monitor_key = TLS_OUT_OF_INDEXES; - -static void inittls(void) { - HANDLE mutex; - char name[64]; - - sprintf(name, "polypaudio%d", (int)GetCurrentProcessId()); - - mutex = CreateMutex(NULL, FALSE, name); - if (!mutex) { - fprintf(stderr, __FILE__ ": CRITICAL: Unable to create named mutex (%d)\n", (int)GetLastError()); - exit(-1); - } - - WaitForSingleObject(mutex, INFINITE); - - if (tlsstr_key == TLS_OUT_OF_INDEXES) { - tlsstr_key = TlsAlloc(); - monitor_key = TlsAlloc(); - if ((tlsstr_key == TLS_OUT_OF_INDEXES) || (monitor_key == TLS_OUT_OF_INDEXES)) { - fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", (int)GetLastError()); - exit(-1); - } - } - - ReleaseMutex(mutex); - - CloseHandle(mutex); -} - -/* - * This is incredibly brain dead, but this is necessary when dealing with - * the hell that is Win32. - */ -struct monitor_data { - HANDLE thread; - void *data; -}; - -static DWORD WINAPI monitor_thread(LPVOID param) { - struct monitor_data *data; - - data = (struct monitor_data*)param; - assert(data); - - WaitForSingleObject(data->thread, INFINITE); - - CloseHandle(data->thread); - pa_xfree(data->data); - pa_xfree(data); - - return 0; -} - -static void start_monitor(void) { - HANDLE thread; - struct monitor_data *data; - - data = pa_xnew(struct monitor_data, 1); - assert(data); - - DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &data->thread, 0, FALSE, DUPLICATE_SAME_ACCESS); - - thread = CreateThread(NULL, 0, monitor_thread, data, 0, NULL); - assert(thread); - - TlsSetValue(monitor_key, data); - - CloseHandle(thread); -} - -#else - -/* Unsafe, but we have no choice */ -static char *tlsstr; - -#endif - -const char* pa_cstrerror(int errnum) { - const char *origbuf; - -#ifdef HAVE_STRERROR_R - char errbuf[128]; -#endif - -#ifdef HAVE_PTHREAD - char *tlsstr; - - pthread_once(&cstrerror_once, inittls); - - tlsstr = pthread_getspecific(tlsstr_key); -#elif defined(HAVE_WINDOWS_H) - char *tlsstr; - struct monitor_data *data; - - inittls(); - - tlsstr = TlsGetValue(tlsstr_key); - if (!tlsstr) - start_monitor(); - data = TlsGetValue(monitor_key); -#endif - - if (tlsstr) - pa_xfree(tlsstr); - -#ifdef HAVE_STRERROR_R - -#ifdef __GLIBC__ - origbuf = strerror_r(errnum, errbuf, sizeof(errbuf)); - if (origbuf == NULL) - origbuf = ""; -#else - if (strerror_r(errnum, errbuf, sizeof(errbuf)) == 0) { - origbuf = errbuf; - errbuf[sizeof(errbuf) - 1] = '\0'; - } else - origbuf = ""; -#endif - -#else - /* This might not be thread safe, but we hope for the best */ - origbuf = strerror(errnum); -#endif - - tlsstr = pa_locale_to_utf8(origbuf); - if (!tlsstr) { - fprintf(stderr, "Unable to convert, filtering\n"); - tlsstr = pa_utf8_filter(origbuf); - } - -#ifdef HAVE_PTHREAD - pthread_setspecific(tlsstr_key, tlsstr); -#elif defined(HAVE_WINDOWS_H) - TlsSetValue(tlsstr_key, tlsstr); - data->data = tlsstr; -#endif - - return tlsstr; -} diff --git a/src/polyp/error.h b/src/polyp/error.h index 1d7b2ca64..9856c1af3 100644 --- a/src/polyp/error.h +++ b/src/polyp/error.h @@ -33,12 +33,6 @@ PA_C_DECL_BEGIN /** Return a human readable error message for the specified numeric error code */ const char* pa_strerror(int error); -/** A wrapper around the standard strerror() function that converts the - * string to UTF-8. The function is thread safe but the returned string is - * only guaranteed to exist until the thread exits or pa_cstrerror() is - * called again from the same thread. */ -const char* pa_cstrerror(int errnum); - PA_C_DECL_END #endif diff --git a/src/polyp/mainloop-signal.c b/src/polyp/mainloop-signal.c index c6ad431a1..927028143 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/polyp/mainloop-signal.c @@ -36,7 +36,7 @@ #include #endif -#include +#include #include #include diff --git a/src/polyp/mainloop.c b/src/polyp/mainloop.c index 6088fa4b3..61d8b4881 100644 --- a/src/polyp/mainloop.c +++ b/src/polyp/mainloop.c @@ -44,7 +44,7 @@ #include "../polypcore/pipe.h" #endif -#include +#include #include #include diff --git a/src/polyp/util.c b/src/polyp/util.c index 910544834..842b9e7f8 100644 --- a/src/polyp/util.c +++ b/src/polyp/util.c @@ -51,8 +51,7 @@ #include "../polypcore/winsock.h" -#include - +#include #include #include diff --git a/src/polypcore/authkey.c b/src/polypcore/authkey.c index 6b462a23b..54f4dd868 100644 --- a/src/polypcore/authkey.c +++ b/src/polypcore/authkey.c @@ -35,8 +35,8 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/polypcore/cli-command.c b/src/polypcore/cli-command.c index 039aa9579..e25e464ce 100644 --- a/src/polypcore/cli-command.c +++ b/src/polypcore/cli-command.c @@ -29,7 +29,6 @@ #include #include -#include #include #include @@ -50,6 +49,7 @@ #include #include #include +#include #include "cli-command.h" diff --git a/src/polypcore/conf-parser.c b/src/polypcore/conf-parser.c index 4bcb83ddb..d59bc5556 100644 --- a/src/polypcore/conf-parser.c +++ b/src/polypcore/conf-parser.c @@ -28,9 +28,9 @@ #include #include -#include #include +#include #include #include diff --git a/src/polypcore/core-error.c b/src/polypcore/core-error.c new file mode 100644 index 000000000..f2240a9fe --- /dev/null +++ b/src/polypcore/core-error.c @@ -0,0 +1,205 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#ifdef HAVE_PTHREAD +#include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif + +#include +#include + +#include +#include + +#include "core-error.h" + +#ifdef HAVE_PTHREAD + +static pthread_once_t cstrerror_once = PTHREAD_ONCE_INIT; +static pthread_key_t tlsstr_key; + +static void inittls(void) { + int ret; + + ret = pthread_key_create(&tlsstr_key, pa_xfree); + if (ret) { + fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", errno); + exit(-1); + } +} + +#elif HAVE_WINDOWS_H + +static DWORD tlsstr_key = TLS_OUT_OF_INDEXES; +static DWORD monitor_key = TLS_OUT_OF_INDEXES; + +static void inittls(void) { + HANDLE mutex; + char name[64]; + + sprintf(name, "polypaudio%d", (int)GetCurrentProcessId()); + + mutex = CreateMutex(NULL, FALSE, name); + if (!mutex) { + fprintf(stderr, __FILE__ ": CRITICAL: Unable to create named mutex (%d)\n", (int)GetLastError()); + exit(-1); + } + + WaitForSingleObject(mutex, INFINITE); + + if (tlsstr_key == TLS_OUT_OF_INDEXES) { + tlsstr_key = TlsAlloc(); + monitor_key = TlsAlloc(); + if ((tlsstr_key == TLS_OUT_OF_INDEXES) || (monitor_key == TLS_OUT_OF_INDEXES)) { + fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", (int)GetLastError()); + exit(-1); + } + } + + ReleaseMutex(mutex); + + CloseHandle(mutex); +} + +/* + * This is incredibly brain dead, but this is necessary when dealing with + * the hell that is Win32. + */ +struct monitor_data { + HANDLE thread; + void *data; +}; + +static DWORD WINAPI monitor_thread(LPVOID param) { + struct monitor_data *data; + + data = (struct monitor_data*)param; + assert(data); + + WaitForSingleObject(data->thread, INFINITE); + + CloseHandle(data->thread); + pa_xfree(data->data); + pa_xfree(data); + + return 0; +} + +static void start_monitor(void) { + HANDLE thread; + struct monitor_data *data; + + data = pa_xnew(struct monitor_data, 1); + assert(data); + + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &data->thread, 0, FALSE, DUPLICATE_SAME_ACCESS); + + thread = CreateThread(NULL, 0, monitor_thread, data, 0, NULL); + assert(thread); + + TlsSetValue(monitor_key, data); + + CloseHandle(thread); +} + +#else + +/* Unsafe, but we have no choice */ +static char *tlsstr; + +#endif + +const char* pa_cstrerror(int errnum) { + const char *origbuf; + +#ifdef HAVE_STRERROR_R + char errbuf[128]; +#endif + +#ifdef HAVE_PTHREAD + char *tlsstr; + + pthread_once(&cstrerror_once, inittls); + + tlsstr = pthread_getspecific(tlsstr_key); +#elif defined(HAVE_WINDOWS_H) + char *tlsstr; + struct monitor_data *data; + + inittls(); + + tlsstr = TlsGetValue(tlsstr_key); + if (!tlsstr) + start_monitor(); + data = TlsGetValue(monitor_key); +#endif + + if (tlsstr) + pa_xfree(tlsstr); + +#ifdef HAVE_STRERROR_R + +#ifdef __GLIBC__ + origbuf = strerror_r(errnum, errbuf, sizeof(errbuf)); + if (origbuf == NULL) + origbuf = ""; +#else + if (strerror_r(errnum, errbuf, sizeof(errbuf)) == 0) { + origbuf = errbuf; + errbuf[sizeof(errbuf) - 1] = '\0'; + } else + origbuf = ""; +#endif + +#else + /* This might not be thread safe, but we hope for the best */ + origbuf = strerror(errnum); +#endif + + tlsstr = pa_locale_to_utf8(origbuf); + if (!tlsstr) { + fprintf(stderr, "Unable to convert, filtering\n"); + tlsstr = pa_utf8_filter(origbuf); + } + +#ifdef HAVE_PTHREAD + pthread_setspecific(tlsstr_key, tlsstr); +#elif defined(HAVE_WINDOWS_H) + TlsSetValue(tlsstr_key, tlsstr); + data->data = tlsstr; +#endif + + return tlsstr; +} diff --git a/src/polypcore/core-error.h b/src/polypcore/core-error.h new file mode 100644 index 000000000..17595c98c --- /dev/null +++ b/src/polypcore/core-error.h @@ -0,0 +1,41 @@ +#ifndef foocoreerrorhfoo +#define foocoreerrorhfoo + +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +/** \file + * Error management */ + +PA_C_DECL_BEGIN + +/** A wrapper around the standard strerror() function that converts the + * string to UTF-8. The function is thread safe but the returned string is + * only guaranteed to exist until the thread exits or pa_cstrerror() is + * called again from the same thread. */ +const char* pa_cstrerror(int errnum); + +PA_C_DECL_END + +#endif diff --git a/src/polypcore/core-scache.c b/src/polypcore/core-scache.c index 1d60a910d..b44a7e198 100644 --- a/src/polypcore/core-scache.c +++ b/src/polypcore/core-scache.c @@ -41,7 +41,6 @@ #include #endif -#include #include #include #include @@ -57,6 +56,7 @@ #include #include #include +#include #include "core-scache.h" diff --git a/src/polypcore/core-util.c b/src/polypcore/core-util.c index bb6a3d85f..6cf281c5f 100644 --- a/src/polypcore/core-util.c +++ b/src/polypcore/core-util.c @@ -69,10 +69,10 @@ #include -#include #include #include +#include #include #include diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c index 8af6a36bf..106c413ec 100644 --- a/src/polypcore/iochannel.c +++ b/src/polypcore/iochannel.c @@ -38,9 +38,9 @@ #include "winsock.h" -#include #include +#include #include #include #include diff --git a/src/polypcore/ioline.c b/src/polypcore/ioline.c index 2e0a3e1af..6a2ef3389 100644 --- a/src/polypcore/ioline.c +++ b/src/polypcore/ioline.c @@ -29,9 +29,9 @@ #include #include -#include #include +#include #include #include "ioline.h" diff --git a/src/polypcore/pid.c b/src/polypcore/pid.c index b8f53955d..a5c0ef0b1 100644 --- a/src/polypcore/pid.c +++ b/src/polypcore/pid.c @@ -39,9 +39,9 @@ #include #endif -#include #include +#include #include #include diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index d7c9475a5..02e140b95 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -49,6 +48,7 @@ #include #include #include +#include #include "endianmacros.h" diff --git a/src/polypcore/protocol-simple.c b/src/polypcore/protocol-simple.c index f15f882ab..8b319d70f 100644 --- a/src/polypcore/protocol-simple.c +++ b/src/polypcore/protocol-simple.c @@ -30,7 +30,6 @@ #include #include -#include #include #include @@ -39,6 +38,7 @@ #include #include #include +#include #include "protocol-simple.h" diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index aa885759e..fd840ab5b 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -54,10 +54,10 @@ #include "winsock.h" -#include #include #include +#include #include #include #include diff --git a/src/polypcore/socket-server.c b/src/polypcore/socket-server.c index 871fac115..17071ec27 100644 --- a/src/polypcore/socket-server.c +++ b/src/polypcore/socket-server.c @@ -64,11 +64,11 @@ #include #include -#include #include #include #include +#include #include "socket-server.h" diff --git a/src/polypcore/socket-util.c b/src/polypcore/socket-util.c index 06cdc6253..aefcb5eff 100644 --- a/src/polypcore/socket-util.c +++ b/src/polypcore/socket-util.c @@ -59,9 +59,9 @@ #include "winsock.h" -#include #include +#include #include #include diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 351d79da7..ad50c77c7 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -54,7 +54,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { } if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", pa_cstrerror(errno)); + pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); goto fail; } @@ -66,7 +66,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { int r; if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { - pa_log(__FILE__": connect(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": connect(): %s", strerror(errno)); goto fail; } @@ -97,7 +97,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { for (;;) { if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { - pa_log(__FILE__": select(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": select(): %s", strerror(errno)); goto fail; } @@ -109,7 +109,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": read(): %s", strerror(errno)); goto fail; } @@ -125,7 +125,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": read(): %s", strerror(errno)); goto fail; } @@ -138,7 +138,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(obuf_length); if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { - pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": write(): %s", strerror(errno)); goto fail; } @@ -152,7 +152,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(ibuf_length); if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { - pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); + pa_log(__FILE__": write(): %s", strerror(errno)); goto fail; } diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 5987ec5fa..c1cc9c92c 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -361,7 +361,7 @@ static void reset_params(fd_info *i) { i->n_fragments = 0; } -static char *client_name(char *buf, size_t n) { +static const char *client_name(char *buf, size_t n) { char p[PATH_MAX]; const char *e; @@ -376,7 +376,7 @@ static char *client_name(char *buf, size_t n) { return buf; } -static char *stream_name(void) { +static const char *stream_name(void) { const char *e; if ((e = getenv("PADSP_STREAM_NAME"))) From f3b72593b545c66eeb5c7858958f0b2c44fd730e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 17:18:42 +0000 Subject: [PATCH 0878/1514] really fix a superfluous warning when building padsp.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@973 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index c1cc9c92c..5f3f91581 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -205,7 +205,7 @@ static int padsp_disabled(void) { pthread_mutex_lock(&func_mutex); if (!sym_resolved) { - sym = (int*) dlsym_fn(RTLD_DEFAULT, "__padsp_disabled__"); + sym = (int*) dlsym(RTLD_DEFAULT, "__padsp_disabled__"); sym_resolved = 1; } From d39740fb6b5c1bf5f70f655451878ee5fb4edf5e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 May 2006 17:26:02 +0000 Subject: [PATCH 0879/1514] We only need the so for libpolypdsp. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@974 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 3a8c9bba7..569b65613 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1188,5 +1188,7 @@ install-exec-hook: chmod u+s $(DESTDIR)$(bindir)/polypaudio ln -sf pacat $(DESTDIR)$(bindir)/parec rm -f $(DESTDIR)$(modlibexecdir)/*.a + rm -f $(DESTDIR)$(libdir)/libpolypdsp.a + rm -f $(DESTDIR)$(libdir)/libpolypdsp.la .PHONY: utils/padsp From b754d5095e8c1bbf41e7c0147dfb2328145a2c83 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 May 2006 17:27:06 +0000 Subject: [PATCH 0880/1514] Wrong prefix used in the padsp script. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@975 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/utils/padsp b/src/utils/padsp index dc89bfb73..b43535b63 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -26,24 +26,24 @@ while getopts 'hs:n:m:MSDd' param ; do export POLYP_SERVER ;; n) - PA_CLIENT_NAME="$OPTARG" - export PA_CLIENT_NAME + PADSP_CLIENT_NAME="$OPTARG" + export PADSP_CLIENT_NAME ;; m) - PA_STREAM_NAME="$OPTARG" - export PA_STREAM_NAME + PADSP_STREAM_NAME="$OPTARG" + export PADSP_STREAM_NAME ;; M) - PA_NO_MIXER=1 - export PA_NO_MIXER + PADSP_NO_MIXER=1 + export PADSP_NO_MIXER ;; S) - PA_NO_SNDSTAT=1 - export PA_NO_SNDSTAT + PADSP_NO_SNDSTAT=1 + export PADSP_NO_SNDSTAT ;; D) - PA_NO_DSP=1 - export PA_NO_DSP + PADSP_NO_DSP=1 + export PADSP_NO_DSP ;; d) PADSP_DEBUG=1 From 7d975345a555fc20e5019307c7dc01545552e42d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 23:20:28 +0000 Subject: [PATCH 0881/1514] * add new API function pa_stream_get_buffer_attr(). * modify pacat.c to make use of that new API * extend protocol to allow transfer of the necessary information * update protocol version accordingly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@976 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- src/polyp/internal.h | 1 + src/polyp/stream.c | 47 +++++++++++++++++++++++++++++++-- src/polyp/stream.h | 5 ++++ src/polypcore/memblockq.c | 12 +++++++++ src/polypcore/memblockq.h | 6 +++++ src/polypcore/protocol-native.c | 21 ++++++++++++++- src/utils/pacat.c | 20 +++++++++++++- 8 files changed, 109 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 157c01a4b..7859d33fa 100644 --- a/configure.ac +++ b/configure.ac @@ -34,7 +34,7 @@ AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) AC_SUBST(PA_API_VERSION, 9) -AC_SUBST(PA_PROTOCOL_VERSION, 8) +AC_SUBST(PA_PROTOCOL_VERSION, 9) AC_SUBST(LIBPOLYP_VERSION_INFO, [0:0:0]) AC_SUBST(LIBPOLYPCORE_VERSION_INFO, [0:0:0]) diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 80c286164..d88a1e5b4 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -100,6 +100,7 @@ struct pa_stream { char *name; pa_buffer_attr buffer_attr; + int buffer_attr_from_server; pa_sample_spec sample_spec; pa_channel_map channel_map; pa_stream_flags_t flags; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index e41c588e5..17884ed34 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -84,6 +84,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->requested_bytes = 0; s->state = PA_STREAM_UNCONNECTED; memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + s->buffer_attr_from_server = 0; s->peek_memchunk.index = 0; s->peek_memchunk.length = 0; @@ -401,12 +402,43 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED if (pa_tagstruct_getu32(t, &s->channel) < 0 || ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || - ((s->direction != PA_STREAM_RECORD) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0) || - !pa_tagstruct_eof(t)) { + ((s->direction != PA_STREAM_RECORD) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0)) { pa_context_fail(s->context, PA_ERR_PROTOCOL); goto finish; } + if (!pa_tagstruct_eof(t)) { + + if (s->direction == PA_STREAM_PLAYBACK) { + + /* This is a server 0.9.0 or later */ + if (pa_tagstruct_getu32(t, &s->buffer_attr.maxlength) < 0 || + pa_tagstruct_getu32(t, &s->buffer_attr.tlength) < 0 || + pa_tagstruct_getu32(t, &s->buffer_attr.prebuf) < 0 || + pa_tagstruct_getu32(t, &s->buffer_attr.minreq) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(s->context, PA_ERR_PROTOCOL); + goto finish; + } + + s->buffer_attr_from_server = 1; + } else if (s->direction == PA_STREAM_RECORD) { + + /* This is a server 0.9.0 or later */ + if (pa_tagstruct_getu32(t, &s->buffer_attr.maxlength) < 0 || + pa_tagstruct_getu32(t, &s->buffer_attr.fragsize) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(s->context, PA_ERR_PROTOCOL); + goto finish; + } + + s->buffer_attr_from_server = 1; + } else { + pa_context_fail(s->context, PA_ERR_PROTOCOL); + goto finish; + } + } + if (s->direction == PA_STREAM_RECORD) { assert(!s->record_memblockq); @@ -1336,3 +1368,14 @@ const pa_channel_map* pa_stream_get_channel_map(pa_stream *s) { return &s->channel_map; } + +const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s) { + assert(s); + assert(s->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr_from_server, PA_ERR_NODATA); + + return &s->buffer_attr; +} diff --git a/src/polyp/stream.h b/src/polyp/stream.h index ad77d9383..d1f558aea 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -439,6 +439,11 @@ const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s); /** Return a pointer to the stream's channel map. \since 0.8 */ const pa_channel_map* pa_stream_get_channel_map(pa_stream *s); +/** Return the buffer metrics of the stream. Only valid after the + * stream has been connected successfuly and if the server is at least + * Polypaudio 0.9. \since 0.9.0 */ +const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s); + PA_C_DECL_END #endif diff --git a/src/polypcore/memblockq.c b/src/polypcore/memblockq.c index caacd96f0..8ed358fa4 100644 --- a/src/polypcore/memblockq.c +++ b/src/polypcore/memblockq.c @@ -622,3 +622,15 @@ void pa_memblockq_prebuf_force(pa_memblockq *bq) { if (bq->state == RUNNING && bq->prebuf > 0) bq->state = PREBUF; } + +size_t pa_memblockq_get_maxlength(pa_memblockq *bq) { + assert(bq); + + return bq->maxlength; +} + +size_t pa_memblockq_get_prebuf(pa_memblockq *bq) { + assert(bq); + + return bq->prebuf; +} diff --git a/src/polypcore/memblockq.h b/src/polypcore/memblockq.h index 302a53668..74fb00eed 100644 --- a/src/polypcore/memblockq.h +++ b/src/polypcore/memblockq.h @@ -131,4 +131,10 @@ void pa_memblockq_prebuf_disable(pa_memblockq *bq); /* Force prebuf */ void pa_memblockq_prebuf_force(pa_memblockq *bq); +/* Return the maximum length of the queue in bytes */ +size_t pa_memblockq_get_maxlength(pa_memblockq *bq); + +/* Return the prebuffer length in bytes */ +size_t pa_memblockq_get_prebuf(pa_memblockq *bq); + #endif diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index a300c45df..7ab112093 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -755,6 +755,16 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC assert(s->sink_input); pa_tagstruct_putu32(reply, s->sink_input->index); pa_tagstruct_putu32(reply, s->requested_bytes = pa_memblockq_missing(s->memblockq)); + + if (c->version >= 9) { + /* Since 0.9 we support sending the buffer metrics back to the client */ + + pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq)); + pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_tlength(s->memblockq)); + pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_prebuf(s->memblockq)); + pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_minreq(s->memblockq)); + } + pa_pstream_send_tagstruct(c->pstream, reply); request_bytes(s); } @@ -852,6 +862,14 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct_putu32(reply, s->index); assert(s->source_output); pa_tagstruct_putu32(reply, s->source_output->index); + + if (c->version >= 9) { + /* Since 0.9 we support sending the buffer metrics back to the client */ + + pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq)); + pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size); + } + pa_pstream_send_tagstruct(c->pstream, reply); } @@ -2215,7 +2233,8 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c); } else c->auth_timeout_event = NULL; - + + c->version = 8; c->protocol = p; assert(p->core); c->client = pa_client_new(p->core, __FILE__, "Client"); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index b1f5bf59a..83c3d3cab 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -154,8 +154,26 @@ static void stream_state_callback(pa_stream *s, void *userdata) { break; case PA_STREAM_READY: - if (verbose) + if (verbose) { + pa_buffer_attr *a; + fprintf(stderr, "Stream successfully created.\n"); + + if (!(a = pa_stream_get_buffer_attr(s))) + fprintf(stderr, "pa_stream_get_buffer_attr() failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); + else { + + if (mode == PLAYBACK) + fprintf(stderr, "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n", a->maxlength, a->tlength, a->prebuf, a->minreq); + else { + assert(mode == RECORD); + fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize); + } + + } + + } + break; case PA_STREAM_FAILED: From 099304a0d4604712261e66bffd32f0c5042329a0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 23:40:25 +0000 Subject: [PATCH 0882/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@977 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/todo b/doc/todo index 0b78ee935..6301cc19c 100644 --- a/doc/todo +++ b/doc/todo @@ -1,8 +1,5 @@ *** $Id$ *** -Pre 0.9.0 -- add API to query the bufferattrs after stream creation - Post 0.9.0: - alsa mmap driver - dbus/hal From d142408f5c83d2fcdac802cfa9a5eeec14d88df1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 May 2006 07:24:25 +0000 Subject: [PATCH 0883/1514] Explicitly check version number when determining which fields are in a stream create response. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@978 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/internal.h | 1 - src/polyp/stream.c | 29 ++++++++++------------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/polyp/internal.h b/src/polyp/internal.h index d88a1e5b4..80c286164 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -100,7 +100,6 @@ struct pa_stream { char *name; pa_buffer_attr buffer_attr; - int buffer_attr_from_server; pa_sample_spec sample_spec; pa_channel_map channel_map; pa_stream_flags_t flags; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index 17884ed34..e3f40a3f3 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -84,7 +84,6 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->requested_bytes = 0; s->state = PA_STREAM_UNCONNECTED; memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); - s->buffer_attr_from_server = 0; s->peek_memchunk.index = 0; s->peek_memchunk.length = 0; @@ -407,38 +406,29 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED goto finish; } - if (!pa_tagstruct_eof(t)) { - + if (pa_context_get_server_protocol_version(s->context) >= 9) { if (s->direction == PA_STREAM_PLAYBACK) { - - /* This is a server 0.9.0 or later */ if (pa_tagstruct_getu32(t, &s->buffer_attr.maxlength) < 0 || pa_tagstruct_getu32(t, &s->buffer_attr.tlength) < 0 || pa_tagstruct_getu32(t, &s->buffer_attr.prebuf) < 0 || - pa_tagstruct_getu32(t, &s->buffer_attr.minreq) < 0 || - !pa_tagstruct_eof(t)) { + pa_tagstruct_getu32(t, &s->buffer_attr.minreq) < 0) { pa_context_fail(s->context, PA_ERR_PROTOCOL); goto finish; } - - s->buffer_attr_from_server = 1; } else if (s->direction == PA_STREAM_RECORD) { - - /* This is a server 0.9.0 or later */ if (pa_tagstruct_getu32(t, &s->buffer_attr.maxlength) < 0 || - pa_tagstruct_getu32(t, &s->buffer_attr.fragsize) < 0 || - !pa_tagstruct_eof(t)) { + pa_tagstruct_getu32(t, &s->buffer_attr.fragsize) < 0) { pa_context_fail(s->context, PA_ERR_PROTOCOL); goto finish; } - - s->buffer_attr_from_server = 1; - } else { - pa_context_fail(s->context, PA_ERR_PROTOCOL); - goto finish; } } + if (!pa_tagstruct_eof(t)) { + pa_context_fail(s->context, PA_ERR_PROTOCOL); + goto finish; + } + if (s->direction == PA_STREAM_RECORD) { assert(!s->record_memblockq); @@ -1375,7 +1365,8 @@ const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s) { PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr_from_server, PA_ERR_NODATA); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, + pa_context_get_server_protocol_version(s->context) >= 9, PA_ERR_NODATA); return &s->buffer_attr; } From 6aeaaf94a8af3c3b0607bc4a9f57923c569d71de Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 May 2006 07:24:47 +0000 Subject: [PATCH 0884/1514] Returned buffer attr is const. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@979 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 83c3d3cab..99e54e641 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -155,7 +155,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_READY: if (verbose) { - pa_buffer_attr *a; + const pa_buffer_attr *a; fprintf(stderr, "Stream successfully created.\n"); From 7d90e3a32d52a5d94b536c0286d3e87f4df01fd0 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 May 2006 09:21:03 +0000 Subject: [PATCH 0885/1514] Fix typos. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@980 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 5f3f91581..b3e443d33 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1129,8 +1129,8 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno *(int*) argp = 0; break; - case SOUND_MIXER_CAPS: - debug(__FILE__": SOUND_MIXER_CAPS\n"); + case SOUND_MIXER_READ_CAPS: + debug(__FILE__": SOUND_MIXER_READ_CAPS\n"); *(int*) argp = 0; break; @@ -1204,7 +1204,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno } default: - debug(__FILE__": unknwon ioctl 0x%08lx\n", request); + debug(__FILE__": unknown ioctl 0x%08lx\n", request); *_errno = EINVAL; goto fail; From 12dc4c21ac4e31becf687513ac9852a3ae6893e5 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 May 2006 12:18:07 +0000 Subject: [PATCH 0886/1514] Fix the fix_metrics() function so that we don't get a tiny buffer by default. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@981 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b3e443d33..8bad126bf 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -357,7 +357,7 @@ static void reset_params(fd_info *i) { i->sample_spec.format = PA_SAMPLE_ULAW; i->sample_spec.channels = 1; i->sample_spec.rate = 8000; - i->fragment_size = 1024; + i->fragment_size = 0; i->n_fragments = 0; } @@ -627,13 +627,23 @@ static void fix_metrics(fd_info *i) { fs = pa_frame_size(&i->sample_spec); i->fragment_size = (i->fragment_size/fs)*fs; - - if (i->n_fragments < 2) - i->n_fragments = 12; - if (i->fragment_size <= 0) - if ((i->fragment_size = pa_bytes_per_second(&i->sample_spec) / 2 / i->n_fragments) <= 0) + /* Number of fragments set? */ + if (i->n_fragments < 2) { + if (i->fragment_size > 0) { + i->n_fragments = pa_bytes_per_second(&i->sample_spec) / 2 / i->fragment_size; + if (i->n_fragments < 2) + i->n_fragments = 2; + } else + i->n_fragments = 12; + } + + /* Fragment size set? */ + if (i->fragment_size <= 0) { + i->fragment_size = pa_bytes_per_second(&i->sample_spec) / 2 / i->n_fragments; + if (i->fragment_size < 1024) i->fragment_size = 1024; + } debug(__FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); debug(__FILE__": fixated metrics to %i fragments, %li bytes each.\n", i->n_fragments, (long)i->fragment_size); From c8e9fa36c5038b88adc684b578d8ec4c52381197 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 May 2006 12:24:37 +0000 Subject: [PATCH 0887/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@982 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/todo b/doc/todo index 6301cc19c..f03c43a9b 100644 --- a/doc/todo +++ b/doc/todo @@ -23,11 +23,8 @@ Post 0.9.0: - Fix a way for the threading API to handle state and subscription callbacks in a nice way. - iconv stuff sent from utils to server (UTF-8) -- iconv stuff leaving the server (e.g. syslog). Sample loading probably needs - help as well. +- iconv sample loading in server - Document utf8.h, timeval.h and util.h -- strerror() needs to be wrapped as it returns stuff in the current locale - and we tend to pass it to functions that require UTF-8. - fix clock of the NULL sink - gettextify polypaudio From f5a888504fe70c0106c791e2d97caa3cd5675aef Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 May 2006 17:59:39 +0000 Subject: [PATCH 0888/1514] disable padsp for the polypaudio daemon itself by defining the __padsp_disabled__ symbol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@983 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/daemon/main.c b/src/daemon/main.c index b88f932c3..16cc0f5ed 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -79,6 +79,13 @@ int allow_severity = LOG_INFO; int deny_severity = LOG_WARNING; #endif +#ifdef HAVE_OSS +/* padsp looks for this symbol in the running process and disables + * itself if it finds it and it is set to 7 (which is actually a bit + * mask). For details see padsp. */ +int __padsp_disabled__ = 7; +#endif + #ifdef OS_IS_WIN32 static void message_cb(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { From 3a868be9abdf3fdd4abc9017d2776474ac46e8a9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 May 2006 18:00:02 +0000 Subject: [PATCH 0889/1514] update README for 0.9.0 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@984 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index 62a23b71a..f02c657d8 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -43,14 +43,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

      News

      -
      Fri Apr 28 2006:

      Fri May 26 2006:

      Version 0.9.0 released; changes include: new module module-volume-restore; -require valid UTF8 strings everywhere; properly support ALSA channel -maps for surround sound; increase maximum number of channels per -stream to 32; add new threaded main loop API for synchronous programs; -introduce real shared object versioning; a few API additions; many, -many bugfixes

      +new OSS API emulation tool padsp; require valid UTF8 strings +everywhere; properly support ALSA channel maps for surround sound; +increase maximum number of channels per stream to 32; add new threaded +main loop API for synchronous programs; introduce real shared object +versioning; a few API additions; many, many bugfixes

      Fri Apr 28 2006:

      Version 0.8.1 From 632f5b44f5149477462a9b59c832c59fe6eaa7ae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 May 2006 12:59:10 +0000 Subject: [PATCH 0890/1514] drop the .sh suffix from esdcompat git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@986 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 8 ++++---- src/daemon/{esdcompat.sh.in => esdcompat.in} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename src/daemon/{esdcompat.sh.in => esdcompat.in} (100%) diff --git a/src/Makefile.am b/src/Makefile.am index 569b65613..ef9d825bd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,7 +77,7 @@ EXTRA_DIST = \ daemon/daemon.conf.in \ daemon/default.pa.in \ depmod.py \ - daemon/esdcompat.sh.in \ + daemon/esdcompat.in \ utils/padsp \ modules/module-defs.h.m4 @@ -142,7 +142,7 @@ if HAVE_HOWL bin_PROGRAMS += pabrowse endif -bin_SCRIPTS = esdcompat.sh +bin_SCRIPTS = esdcompat pacat_SOURCES = utils/pacat.c pacat_LDADD = $(AM_LDADD) libpolyp.la @@ -1161,9 +1161,9 @@ suid: polypaudio chown root $< chmod u+s $< -CLEANFILES = esdcompat.sh client.conf default.pa daemon.conf +CLEANFILES = esdcompat client.conf default.pa daemon.conf -esdcompat.sh: daemon/esdcompat.sh.in Makefile +esdcompat: daemon/esdcompat.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ diff --git a/src/daemon/esdcompat.sh.in b/src/daemon/esdcompat.in similarity index 100% rename from src/daemon/esdcompat.sh.in rename to src/daemon/esdcompat.in From ce04f0b3f534b5129b3d4e904d6da5948ff41f1f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 May 2006 13:01:08 +0000 Subject: [PATCH 0891/1514] update svn:ignore to reflect the esdcompat name change git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@987 fefdeb5f-60dc-0310-8127-8f9354f1896f From 21cb51b3a1898e5fa89fb8cb0b9323a491986d85 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 May 2006 14:06:08 +0000 Subject: [PATCH 0892/1514] merge patch from Igor Zubkov, fixing linking of the HOWL modules git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@988 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index ef9d825bd..de0c18dff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1089,12 +1089,12 @@ module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la libhowl_wrap_la_SOURCES = modules/howl-wrap.c modules/howl-wrap.h libhowl_wrap_la_LDFLAGS = -avoid-version -libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) +libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libpolypcore.la libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) module_zeroconf_publish_la_SOURCES = modules/module-zeroconf-publish.c module_zeroconf_publish_la_LDFLAGS = -module -avoid-version -module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la +module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la libpolypcore.la module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) # LIRC From 6140619e61884afc85e64d834745fa59d61e93d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 May 2006 00:25:51 +0000 Subject: [PATCH 0893/1514] fix amd64 portability issues git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@989 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/protocol-native.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index 7ab112093..f663dc356 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -696,8 +696,7 @@ static pa_tagstruct *reply_new(uint32_t tag) { static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; struct playback_stream *s; - size_t maxlength, tlength, prebuf, minreq; - uint32_t sink_index, syncid; + uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid; const char *name, *sink_name; pa_sample_spec ss; pa_channel_map map; @@ -736,7 +735,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, maxlength > 0 && maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); if (sink_index != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); From 73eedcbaaec8ff6bbdde2b55eec3a83092044527 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 May 2006 12:23:37 +0000 Subject: [PATCH 0894/1514] load alsa modules with device string hw:0 instead of hw:0,0 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@990 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-detect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index d0a377330..3512e31c9 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -92,7 +92,7 @@ static int detect_alsa(pa_core *c, int just_one) { if (subdevice != 0) continue; - snprintf(args, sizeof(args), "device=hw:%u,0", device); + snprintf(args, sizeof(args), "device=hw:%u", device); if (!pa_module_load(c, is_sink ? "module-alsa-sink" : "module-alsa-source", args)) continue; From 821a49b96708986cbfb45de416f806ee5efed943 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 May 2006 15:28:46 +0000 Subject: [PATCH 0895/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@991 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/todo b/doc/todo index f03c43a9b..19e4f1a97 100644 --- a/doc/todo +++ b/doc/todo @@ -27,6 +27,7 @@ Post 0.9.0: - Document utf8.h, timeval.h and util.h - fix clock of the NULL sink - gettextify polypaudio +- use send() with MSG_NOSIGNAL instead of write() wherever possible, and than drop that SIGPIPE warning Long term: - pass meta info for hearing impaired From bb820db4b5b9e928b4d7fe58bbab2f56b1897f64 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 May 2006 22:05:07 +0000 Subject: [PATCH 0896/1514] * if an ALSA device doesn't support the channel count requested, use what ALSA suggests instead * if an ALSA device doesn't support the sampling freq requested, use what ALSA suggests and resample if this deviates more than 10% from what we requested * fix segfault freeing an unitialized mixer_fdl field git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@992 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 17 ++++++++++++++--- src/modules/alsa-util.h | 2 +- src/modules/module-alsa-sink.c | 13 ++++++++++--- src/modules/module-alsa-source.c | 15 +++++++++++---- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 122f4419b..22e623f6b 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -249,11 +249,12 @@ int pa_alsa_fdlist_init_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_han /* Set the hardware parameters of the given ALSA device. Returns the * selected fragment settings in *period and *period_size */ -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { int ret = -1; snd_pcm_uframes_t buffer_size; snd_pcm_hw_params_t *hwparams = NULL; unsigned int r = ss->rate; + unsigned int c = ss->channels; static const snd_pcm_format_t format_trans[] = { [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8, @@ -273,14 +274,24 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint3 (ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0 || (ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[ss->format])) < 0 || (ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0 || - (ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss->channels)) < 0 || + (ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0 || (*period_size > 0 && (ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL)) < 0) || (*periods > 0 && (ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0) || (ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) goto finish; - if (ss->rate != r) + if (ss->rate != r) { pa_log_info(__FILE__": device doesn't support %u Hz, changed to %u Hz.", ss->rate, r); + + /* If the sample rate deviates too much, we need to resample */ + if (r < ss->rate*.9 || r > ss->rate*1.1) + ss->rate = r; + } + + if (ss->channels != c) { + pa_log_info(__FILE__": device doesn't support %u channels, changed to %u.", ss->channels, c); + ss->channels = c; + } if ((ret = snd_pcm_prepare(pcm_handle)) < 0) goto finish; diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 69d4eddc2..4bee86258 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -37,7 +37,7 @@ void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl); int pa_alsa_fdlist_init_pcm(struct pa_alsa_fdlist *fdl, snd_pcm_t *pcm_handle, pa_mainloop_api* m, void (*cb)(void *userdata), void *userdata); int pa_alsa_fdlist_init_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m); -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev); snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name); diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index e768e16a6..a0b6dc08d 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -363,6 +363,10 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + if (ss.channels != map.channels) + /* Seems ALSA didn't like the channel number, so let's fix the channel map */ + pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); + if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) { pa_log(__FILE__": Error opening mixer: %s", snd_strerror(err)); goto fail; @@ -374,8 +378,10 @@ int pa__init(pa_core *c, pa_module*m) { u->mixer_handle = NULL; } - u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map); - assert(u->sink); + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { + pa_log(__FILE__": Failed to create sink object"); + goto fail; + } u->sink->get_latency = sink_get_latency_cb; if (u->mixer_handle) { @@ -420,7 +426,8 @@ int pa__init(pa_core *c, pa_module*m) { } snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback); snd_mixer_elem_set_callback_private(u->mixer_elem, u); - } + } else + u->mixer_fdl = NULL; u->frame_size = frame_size; u->fragment_size = period_size * frame_size; diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 414efda88..10b98f75b 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -335,7 +335,7 @@ int pa__init(pa_core *c, pa_module*m) { } period_size = fragsize/frame_size; - u = pa_xmalloc0(sizeof(struct userdata)); + u = pa_xnew(struct userdata, 1); m->userdata = u; u->module = m; @@ -356,6 +356,10 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + if (ss.channels != map.channels) + /* Seems ALSA didn't like the channel number, so let's fix the channel map */ + pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); + if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) { pa_log(__FILE__": Error opening mixer: %s", snd_strerror(err)); goto fail; @@ -367,8 +371,10 @@ int pa__init(pa_core *c, pa_module*m) { u->mixer_handle = NULL; } - u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map); - assert(u->source); + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { + pa_log(__FILE__": Failed to create source object"); + goto fail; + } u->source->userdata = u; u->source->get_latency = source_get_latency_cb; @@ -413,7 +419,8 @@ int pa__init(pa_core *c, pa_module*m) { } snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback); snd_mixer_elem_set_callback_private(u->mixer_elem, u); - } + } else + u->mixer_fdl = NULL; u->frame_size = frame_size; u->fragment_size = period_size * frame_size; From 64fa5b882f53b24d78fd3c84191150000e79b391 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 May 2006 22:48:17 +0000 Subject: [PATCH 0897/1514] * alsa-sink: if "PCM" is not found as mixer track name, fallback to "Master" * alsa-source: if "Capture" is not found as mixer track name, fallback to "Mic" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@993 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 23 +++++++++++++++++------ src/modules/alsa-util.h | 2 +- src/modules/module-alsa-sink.c | 2 +- src/modules/module-alsa-source.c | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 22e623f6b..be0fc0649 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -337,18 +337,29 @@ int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) { return 0; } -snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name) { +snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback) { snd_mixer_elem_t *elem; - snd_mixer_selem_id_t *sid; + snd_mixer_selem_id_t *sid = NULL; snd_mixer_selem_id_alloca(&sid); - assert(mixer && name); + assert(mixer); + assert(name); snd_mixer_selem_id_set_name(sid, name); - elem = snd_mixer_find_selem(mixer, sid); - if (!elem) - pa_log_warn(__FILE__": Cannot find mixer control %s", snd_mixer_selem_id_get_name(sid)); + if (!(elem = snd_mixer_find_selem(mixer, sid))) { + pa_log_warn(__FILE__": Cannot find mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); + + if (fallback) { + snd_mixer_selem_id_set_name(sid, fallback); + + if (!(elem = snd_mixer_find_selem(mixer, sid))) + pa_log_warn(__FILE__": Cannot find fallback mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); + } + } + + if (elem) + pa_log_warn(__FILE__": Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); return elem; } diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 4bee86258..83d1481f2 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -40,6 +40,6 @@ int pa_alsa_fdlist_init_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_han int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev); -snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name); +snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback); #endif diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index a0b6dc08d..620047b77 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -373,7 +373,7 @@ int pa__init(pa_core *c, pa_module*m) { } if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || - !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "PCM"))) { + !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "PCM", "Master"))) { snd_mixer_close(u->mixer_handle); u->mixer_handle = NULL; } diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 10b98f75b..0999c65fc 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -366,7 +366,7 @@ int pa__init(pa_core *c, pa_module*m) { } if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || - !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture"))) { + !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", "Mic"))) { snd_mixer_close(u->mixer_handle); u->mixer_handle = NULL; } From 9f2026da05582c154b2cd833fce8e877fb9d5375 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 May 2006 22:57:41 +0000 Subject: [PATCH 0898/1514] downgrade a log message git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@994 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index be0fc0649..99c1cfa32 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -359,7 +359,7 @@ snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const } if (elem) - pa_log_warn(__FILE__": Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); + pa_log_info(__FILE__": Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); return elem; } From 79b6c31f2303e34f016363ced6dad3bc3ff35c54 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 31 May 2006 00:05:38 +0000 Subject: [PATCH 0899/1514] decrease maximum allowed sample frequency for ALSA devices to 5%, since 48000 would otherwise match with 44100 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@995 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 99c1cfa32..5b6d72e77 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -284,7 +284,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p pa_log_info(__FILE__": device doesn't support %u Hz, changed to %u Hz.", ss->rate, r); /* If the sample rate deviates too much, we need to resample */ - if (r < ss->rate*.9 || r > ss->rate*1.1) + if (r < ss->rate*.95 || r > ss->rate*1.05) ss->rate = r; } From ac7213d7337bf878dc687c9d0dcbfc545a539ac1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 31 May 2006 15:07:37 +0000 Subject: [PATCH 0900/1514] update TODO git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@996 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/todo b/doc/todo index 19e4f1a97..de23c4935 100644 --- a/doc/todo +++ b/doc/todo @@ -28,6 +28,9 @@ Post 0.9.0: - fix clock of the NULL sink - gettextify polypaudio - use send() with MSG_NOSIGNAL instead of write() wherever possible, and than drop that SIGPIPE warning +- drop dependency of libpolyp on libX11, instead use an external mini binary +- "hot" moving of streams between sinks +- check if using prctl(PR_GET_NAME) makes sense in pa_get_binary_name() Long term: - pass meta info for hearing impaired From 8ca956892ef71cf93e97c8f94c4c64d979f9a128 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 31 May 2006 19:17:32 +0000 Subject: [PATCH 0901/1514] remove superfluous prefixes from service names git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@997 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-zeroconf-publish.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index bd4a2d974..c07c95f39 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -140,7 +140,7 @@ static int publish_service(struct userdata *u, struct service *s) { s->published = 0; } - snprintf(t, sizeof(t), "Networked Audio Device %s on %s", s->name, pa_get_host_name(hn, sizeof(hn))); + snprintf(t, sizeof(t), "%s on %s", s->name, pa_get_host_name(hn, sizeof(hn))); if (sw_text_record_init(&txt) != SW_OKAY) { pa_log(__FILE__": sw_text_record_init() failed"); @@ -432,7 +432,7 @@ int pa__init(pa_core *c, pa_module*m) { if (publish_autoload(u, autoload) < 0) goto fail; - snprintf(t, sizeof(t), "Networked Audio Server on %s", pa_get_host_name(hn, sizeof(hn))); + snprintf(t, sizeof(t), "%s", pa_get_host_name(hn, sizeof(hn))); if (sw_text_record_init(&txt) != SW_OKAY) { pa_log(__FILE__": sw_text_record_init() failed"); From 7a52eab5968ff6974c3585659acadd0c0d04715e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 1 Jun 2006 13:49:10 +0000 Subject: [PATCH 0902/1514] Try the ltdl mangled name ourselves so that .la files for modules are optional. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@998 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/module.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/polypcore/module.c b/src/polypcore/module.c index b938750c8..47a878fba 100644 --- a/src/polypcore/module.c +++ b/src/polypcore/module.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,39 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED m->time_restart(e, &ntv); } +static inline fnptr load_sym(lt_dlhandle handle, const char *module, const char *symbol) { + char *buffer, *ch; + size_t buflen; + fnptr res; + + res = lt_dlsym_fn(handle, symbol); + if (res) + return res; + + /* As the .la files might have been cleansed from the system, we should + * try with the ltdl prefix as well. */ + + buflen = strlen(symbol) + strlen(module) + strlen("_LTX_") + 1; + buffer = pa_xmalloc(buflen); + assert(buffer); + + strcpy(buffer, module); + + for (ch = buffer;*ch != '\0';ch++) { + if (!isalnum(*ch)) + *ch = '_'; + } + + strcat(buffer, "_LTX_"); + strcat(buffer, symbol); + + res = lt_dlsym_fn(handle, buffer); + + pa_xfree(buffer); + + return res; +} + pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { pa_module *m = NULL; int r; @@ -82,12 +116,12 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { goto fail; } - if (!(m->init = (int (*)(pa_core *_c, pa_module*_m)) lt_dlsym_fn(m->dl, PA_SYMBOL_INIT))) { + if (!(m->init = (int (*)(pa_core *_c, pa_module*_m)) load_sym(m->dl, name, PA_SYMBOL_INIT))) { pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name); goto fail; } - if (!(m->done = (void (*)(pa_core *_c, pa_module*_m)) lt_dlsym_fn(m->dl, PA_SYMBOL_DONE))) { + if (!(m->done = (void (*)(pa_core *_c, pa_module*_m)) load_sym(m->dl, name, PA_SYMBOL_DONE))) { pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.", name); goto fail; } From 02bfa3c4492e7a9469948ba7d7c58e033b35dbe2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 1 Jun 2006 13:49:17 +0000 Subject: [PATCH 0903/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@999 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/todo b/doc/todo index de23c4935..0569924c2 100644 --- a/doc/todo +++ b/doc/todo @@ -12,6 +12,8 @@ Post 0.9.0: - rtp module ported to Win32 (sendmsg/recvmsg emulation) - CODECs to reduce bandwidth usage (plug-in based) - Remove symdef files and use macros (like most other projects) +- Use own name mangling scheme instead of ltdl's, which will eliminate the + need for .la files or extra trickery. - use software volume when hardware doesn't support all channels (alsa done) - paplay needs to set a channel map. our default is only correct for AIFF. (we need help from libsndfile for this) From 7b961bd982dfcefecc25901d253e985c6a6eeea0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 2 Jun 2006 15:30:04 +0000 Subject: [PATCH 0904/1514] Add new configure options to disable/enable specific modules at configure time. Original patch by ed@catmur.co.uk. (Closes #16) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1000 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 114 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 90 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index 7859d33fa..cf4bb0eb5 100644 --- a/configure.ac +++ b/configure.ac @@ -107,13 +107,17 @@ AC_ARG_ENABLE(lynx, yes) lynx=yes ;; no) lynx=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-lynx) ;; -esac],[lynx=yes]) +esac],[lynx=auto]) -if test x$lynx = xyes ; then +if test x$lynx != xno ; then AC_CHECK_PROG(have_lynx, lynx, yes, no) if test x$have_lynx = xno ; then - AC_MSG_WARN([*** lynx not found, plain text README will not be built ***]) + if test x$lynx = xyes ; then + AC_MSG_ERROR([*** lynx not found]) + else + AC_MSG_WARN([*** lynx not found, plain text README will not be built ***]) + fi fi fi @@ -291,8 +295,14 @@ AC_ARG_WITH( AC_HELP_STRING([--without-caps],[Omit support for POSIX capabilities.])) if test "x${with_caps}" != "xno"; then - AC_SEARCH_LIBS([cap_init], [cap]) - AC_CHECK_HEADERS([sys/capability.h]) + AC_SEARCH_LIBS([cap_init], [cap], [], [ + if test "x${with_caps}" = "xyes" ; then + AC_MSG_ERROR([*** POSIX caps libraries not found]) + fi]) + AC_CHECK_HEADERS([sys/capability.h], [], [ + if test "x${with_caps}" = "xyes" ; then + AC_MSG_ERROR([*** POSIX caps headers not found]) + fi]) fi #### pkg-config #### @@ -321,20 +331,30 @@ AC_SUBST(LIBSNDFILE_LIBS) #### OSS support (optional) #### -AC_CHECK_HEADERS([sys/soundcard.h], [ -HAVE_OSS=1 -AC_DEFINE([HAVE_OSS], 1, [Have OSS?]) -], [HAVE_OSS=0]) +AC_ARG_ENABLE([oss], + AC_HELP_STRING([--disable-oss], [Disable optional OSS support]), + [case "${enableval}" in yes) oss=yes ;; no) oss=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-oss) ;; esac],[oss=auto]) +if test "x${oss}" != xno ; then + AC_CHECK_HEADERS([sys/soundcard.h], [ + HAVE_OSS=1 + AC_DEFINE([HAVE_OSS], 1, [Have OSS?]) + ], [HAVE_OSS=0 ; if test "x$oss" = xyes ; then AC_MSG_ERROR([*** OSS support not found]) ; fi]) +else HAVE_OSS=0; fi AC_SUBST(HAVE_OSS) AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1]) #### ALSA support (optional) #### -PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [ -HAVE_ALSA=1 -AC_DEFINE([HAVE_ALSA], 1, [Have ALSA?]) -], [HAVE_ALSA=0]) +AC_ARG_ENABLE([alsa], + AC_HELP_STRING([--disable-alsa], [Disable optional ALSA support]), + [case "${enableval}" in yes) alsa=yes ;; no) alsa=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-alsa) ;; esac],[alsa=auto]) +if test "x${alsa}" != xno ; then + PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [ + HAVE_ALSA=1 + AC_DEFINE([HAVE_ALSA], 1, [Have ALSA?]) + ], [HAVE_ALSA=0 ; if test "x$alsa" = xyes ; then AC_MSG_ERROR([*** ALSA support not found]) ; fi]) +else HAVE_ALSA=0 ; fi AC_SUBST(ASOUNDLIB_CFLAGS) AC_SUBST(ASOUNDLIB_LIBS) AC_SUBST(HAVE_ALSA) @@ -342,16 +362,26 @@ AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1]) #### Solaris audio support (optional) #### -AC_CHECK_HEADERS([sys/audio.h], [ -HAVE_SOLARIS=1 -AC_DEFINE([HAVE_SOLARIS], 1, [Have Solaris audio?]) -], [HAVE_SOLARIS=0]) +AC_ARG_ENABLE([solaris], + AC_HELP_STRING([--disable-solaris], [Disable optional Solaris audio support]), + [case "${enableval}" in yes) solaris=yes ;; no) solaris=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-solaris) ;; esac],[solaris=auto]) +if test "x${solaris}" != xno ; then + AC_CHECK_HEADERS([sys/audio.h], [ + HAVE_SOLARIS=1 + AC_DEFINE([HAVE_SOLARIS], 1, [Have Solaris audio?]) + ], [HAVE_SOLARIS=0 ; if test "x$solaris" = xyes ; then AC_MSG_ERROR([*** Solaris audio support not found]) ; fi]) +else HAVE_SOLARIS=0 ; fi AC_SUBST(HAVE_SOLARIS) AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1]) #### GLib 2 support (optional) #### -PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], HAVE_GLIB20=1, HAVE_GLIB20=0) +AC_ARG_ENABLE([glib2], + AC_HELP_STRING([--disable-glib2], [Disable optional GLib 2 support]), + [case "${enableval}" in yes) glib2=yes ;; no) glib2=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-glib2) ;; esac],[glib2=auto]) +if test "x${glib2}" != xno ; then + PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], HAVE_GLIB20=1, [HAVE_GLIB20=0 ; if test "x$glib2" = xyes ; then AC_MSG_ERROR([*** GLib 2 support not found]) ; fi]) +else HAVE_GLIB20=0 ; fi AC_SUBST(GLIB20_CFLAGS) AC_SUBST(GLIB20_LIBS) AC_SUBST(HAVE_GLIB20) @@ -359,7 +389,12 @@ AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1]) #### GLib 1 support (optional) #### -PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], HAVE_GLIB12=1, HAVE_GLIB12=0) +AC_ARG_ENABLE([glib1], + AC_HELP_STRING([--disable-glib1], [Disable optional GLib 1 support]), + [case "${enableval}" in yes) glib1=yes ;; no) glib1=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-glib1) ;; esac],[glib1=auto]) +if test "x${glib1}" != xno ; then + PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], HAVE_GLIB12=1, [HAVE_GLIB12=0 ; if test "x$glib1" = xyes ; then AC_MSG_ERROR([*** GLib 1 support not found]) ; fi]) +else HAVE_GLIB12=0 ; fi AC_SUBST(GLIB12_CFLAGS) AC_SUBST(GLIB12_LIBS) AC_SUBST(HAVE_GLIB12) @@ -367,7 +402,12 @@ AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) #### Howl support (optional) #### -PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], HAVE_HOWL=1, HAVE_HOWL=0) +AC_ARG_ENABLE([howl], + AC_HELP_STRING([--disable-howl], [Disable optional Howl support]), + [case "${enableval}" in yes) howl=yes ;; no) howl=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-howl) ;; esac],[howl=auto]) +if test "x${howl}" != xno ; then + PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], HAVE_HOWL=1, PKG_CHECK_MODULES(HOWL, [ avahi-compat-howl >= 0.9.8 ], HAVE_HOWL=1, [HAVE_HOWL=0 ; if test "x$howl" = xyes ; then AC_MSG_ERROR([*** Howl support not found]) ; fi])) +else HAVE_HOWL=0 ; fi AC_SUBST(HOWL_CFLAGS) AC_SUBST(HOWL_LIBS) AC_SUBST(HAVE_HOWL) @@ -381,7 +421,12 @@ AC_SUBST(LIBOIL_LIBS) ### JACK (optional) #### -PKG_CHECK_MODULES(JACK, [ jack >= 0.100 ], HAVE_JACK=1, HAVE_JACK=0) +AC_ARG_ENABLE([jack], + AC_HELP_STRING([--disable-jack], [Disable optional JACK support]), + [case "${enableval}" in yes) jack=yes ;; no) jack=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-jack) ;; esac],[jack=auto]) +if test "x${jack}" != xno ; then + PKG_CHECK_MODULES(JACK, [ jack >= 0.100 ], HAVE_JACK=1, [HAVE_JACK=0 ; if test "x$jack" = xyes ; then AC_MSG_ERROR([*** JACK support not found]) ; fi]) +else HAVE_JACK=0 ; fi AC_SUBST(JACK_CFLAGS) AC_SUBST(JACK_LIBS) AC_SUBST(HAVE_JACK) @@ -389,7 +434,12 @@ AM_CONDITIONAL([HAVE_JACK], [test "x$HAVE_JACK" = x1]) #### Async DNS support (optional) #### -PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, HAVE_LIBASYNCNS=0) +AC_ARG_ENABLE([asyncns], + AC_HELP_STRING([--disable-asyncns], [Disable optional Async DNS support]), + [case "${enableval}" in yes) asyncns=yes ;; no) asyncns=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-asyncns) ;; esac],[asyncns=auto]) +if test "x${asyncns}" != xno ; then + PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, [HAVE_LIBASYNCNS=0 ; if test "x$asyncns" = xyes ; then AC_MSG_ERROR([*** Async DNS support not found]) ; fi]) +else HAVE_LIBASYNCNS=0 ; fi AC_SUBST(LIBASYNCNS_CFLAGS) AC_SUBST(LIBASYNCNS_LIBS) AC_SUBST(HAVE_LIBASYNCNS) @@ -401,12 +451,28 @@ fi #### TCP wrappers (optional) #### -ACX_LIBWRAP +AC_ARG_ENABLE([tcpwrap], + AC_HELP_STRING([--disable-tcpwrap], [Disable optional TCP wrappers support]), + [case "${enableval}" in yes) tcpwrap=yes ;; no) tcpwrap=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-tcpwrap) ;; esac],[tcpwrap=auto]) +if test "x${tcpwrap}" != xno ; then + ACX_LIBWRAP + if test "x${LIBWRAP_LIBS}" = x && test "x$tcpwrap" = xyes ; then + AC_MSG_ERROR([*** TCP wrappers support not found]) + fi +else LIBWRAP_LIBS= ; fi AC_SUBST(LIBWRAP_LIBS) #### LIRC support (optional) #### -ACX_LIRC +AC_ARG_ENABLE([lirc], + AC_HELP_STRING([--disable-lirc], [Disable optional LIRC support]), + [case "${enableval}" in yes) lirc=yes ;; no) lirc=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-lirc) ;; esac],[lirc=auto]) +if test "x${lirc}" != xno ; then + ACX_LIRC + if test "x${HAVE_LIRC}" = x0 && test "x$lirc" = xyes ; then + AC_MSG_ERROR([*** LIRC support not found]) + fi +else HAVE_LIRC=0 ; fi AC_SUBST(LIRC_CFLAGS) AC_SUBST(LIRC_LIBS) AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) From e09233664e9db152567c56ff047899c951c769fd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 2 Jun 2006 19:28:47 +0000 Subject: [PATCH 0905/1514] bump version and soname git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1001 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index cf4bb0eb5..c389dd238 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_PREREQ(2.57) m4_define(PA_MAJOR, [0]) m4_define(PA_MINOR, [9]) -m4_define(PA_MICRO, [0]) +m4_define(PA_MICRO, [1]) AC_INIT([polypaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) @@ -37,7 +37,7 @@ AC_SUBST(PA_API_VERSION, 9) AC_SUBST(PA_PROTOCOL_VERSION, 9) AC_SUBST(LIBPOLYP_VERSION_INFO, [0:0:0]) -AC_SUBST(LIBPOLYPCORE_VERSION_INFO, [0:0:0]) +AC_SUBST(LIBPOLYPCORE_VERSION_INFO, [0:1:0]) AC_SUBST(LIBPOLYP_SIMPLE_VERSION_INFO, [0:0:0]) AC_SUBST(LIBPOLYP_BROWSE_VERSION_INFO, [0:0:0]) AC_SUBST(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO, [0:0:0]) From 8b0e6f6f66a6991ce42aa0ad743ac47dcf1e6f42 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 2 Jun 2006 19:49:05 +0000 Subject: [PATCH 0906/1514] update docs for 0.9.1 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1002 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/README.html.in b/doc/README.html.in index f02c657d8..f35b2da96 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -43,6 +43,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

      News

      +
      Fri Jun 2 2006:

      Version 0.9.1 +released; changes include: load modules even when libtool .la +files are missing; generate better ALSA device names from +module-detect; if an ALSA device doesn't support the +requested number of channels or the frequency, accept what ALSA +suggests instead; amd64 portability; drop .sh suffix of +esdcompat.sh; build system fixes; No API or ABI changes were made

      +
      Fri May 26 2006:

      Version 0.9.0 released; changes include: new module module-volume-restore; @@ -330,7 +339,7 @@ compilation and make install (as root) for installation of

      Please report bugs to our Trac ticket system.


      -
      Lennart Poettering <@PACKAGE_BUGREPORT@>, May 2006
      +
      Lennart Poettering <@PACKAGE_BUGREPORT@>, June 2006
      $Id$
      From 441362a50b8c7e190b98066198555832a95ef064 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 2 Jun 2006 21:06:38 +0000 Subject: [PATCH 0907/1514] fix ugly access-after-free bug when doing asyncronous NS lookups git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1004 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/socket-client.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/polypcore/socket-client.c b/src/polypcore/socket-client.c index fd840ab5b..efb6de9a9 100644 --- a/src/polypcore/socket-client.c +++ b/src/polypcore/socket-client.c @@ -376,16 +376,18 @@ static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED asyncns_freeaddrinfo(res); - goto finish; - -fail: - errno = EHOSTUNREACH; - do_call(c); - -finish: - m->io_free(c->asyncns_io_event); c->asyncns_io_event = NULL; + return; + +fail: + m->io_free(c->asyncns_io_event); + c->asyncns_io_event = NULL; + + errno = EHOSTUNREACH; + do_call(c); + return; + } #endif From 16a275a9fddcf9216941cae4a002f0902ae5df88 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 2 Jun 2006 22:56:20 +0000 Subject: [PATCH 0908/1514] actually build cpulimit support if SIGXCPU is available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1005 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 5 ++++- src/daemon/cpulimit.c | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index c389dd238..7a2fdbf03 100644 --- a/configure.ac +++ b/configure.ac @@ -204,7 +204,10 @@ AC_TYPE_OFF_T AC_TYPE_SIGNAL AC_TYPE_UID_T -AC_CHECK_DEFINE([SIGXCPU], [signal.h], [HAVE_SIGXCPU=1], [HAVE_SIGXCPU=0]) +AC_CHECK_DEFINE([SIGXCPU], [signal.h], [ +HAVE_SIGXCPU=1 +AC_DEFINE([HAVE_SIGXCPU], 1, [Have SIGXCPU?]) +], [HAVE_SIGXCPU=0]) AM_CONDITIONAL(HAVE_SIGXCPU, test "x$HAVE_SIGXCPU" = "x1") # Solaris lacks this diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index 2cc37be62..d537b9db0 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -26,6 +26,7 @@ #include #include +#include #include #include "cpulimit.h" @@ -62,8 +63,8 @@ /* Check every 10s */ #define CPUTIME_INTERVAL_SOFT (10) -/* Recheck after 2s */ -#define CPUTIME_INTERVAL_HARD (2) +/* Recheck after 5s */ +#define CPUTIME_INTERVAL_HARD (5) /* Time of the last CPU load check */ static time_t last_time = 0; @@ -155,7 +156,7 @@ static void signal_handler(int sig) { } /* Callback for IO events on the FIFO */ -static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags f, void *userdata) { +static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata) { char c; assert(m && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == the_pipe[0]); read(the_pipe[0], &c, sizeof(c)); From 2fa08ba9aac87f75751bc57bf153a2905699584d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 3 Jun 2006 00:59:24 +0000 Subject: [PATCH 0909/1514] fix pa_xstrndup() implementation to not access potentially uninitialized memory git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1006 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/xmalloc.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/polyp/xmalloc.c b/src/polyp/xmalloc.c index ffc7f7c81..7f71a5edf 100644 --- a/src/polyp/xmalloc.c +++ b/src/polyp/xmalloc.c @@ -106,19 +106,18 @@ char *pa_xstrdup(const char *s) { } char *pa_xstrndup(const char *s, size_t l) { + char *e, *r; + if (!s) return NULL; - else { - char *r; - size_t t = strlen(s); - if (t > l) - t = l; - - r = pa_xmemdup(s, t+1); - r[t] = 0; - return r; - } + if ((e = memchr(s, 0, l))) + return pa_xmemdup(s, e-s+1); + + r = pa_xmalloc(l+1); + memcpy(r, s, l); + r[l] = 0; + return r; } void pa_xfree(void *p) { From d8dafa0d5f4f52ad39f586572994eaf6d8005846 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 3 Jun 2006 01:15:21 +0000 Subject: [PATCH 0910/1514] rework ioline EOF handling to actually work properly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1007 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/ioline.c | 89 ++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/src/polypcore/ioline.c b/src/polypcore/ioline.c index 6a2ef3389..b908f967d 100644 --- a/src/polypcore/ioline.c +++ b/src/polypcore/ioline.c @@ -65,7 +65,7 @@ pa_ioline* pa_ioline_new(pa_iochannel *io) { pa_ioline *l; assert(io); - l = pa_xmalloc(sizeof(pa_ioline)); + l = pa_xnew(pa_ioline, 1); l->io = io; l->dead = 0; @@ -106,23 +106,27 @@ static void ioline_free(pa_ioline *l) { } void pa_ioline_unref(pa_ioline *l) { - assert(l && l->ref >= 1); + assert(l); + assert(l->ref >= 1); if ((--l->ref) <= 0) ioline_free(l); } pa_ioline* pa_ioline_ref(pa_ioline *l) { - assert(l && l->ref >= 1); + assert(l); + assert(l->ref >= 1); l->ref++; return l; } void pa_ioline_close(pa_ioline *l) { - assert(l && l->ref >= 1); + assert(l); + assert(l->ref >= 1); l->dead = 1; + if (l->io) { pa_iochannel_free(l->io); l->io = NULL; @@ -132,13 +136,20 @@ void pa_ioline_close(pa_ioline *l) { l->mainloop->defer_free(l->defer_event); l->defer_event = NULL; } + + if (l->callback) + l->callback = NULL; } void pa_ioline_puts(pa_ioline *l, const char *c) { size_t len; - assert(l && c && l->ref >= 1 && !l->dead); + + assert(l); + assert(l->ref >= 1); + assert(c); - pa_ioline_ref(l); + if (l->dead) + return; len = strlen(c); if (len > BUFFER_LIMIT - l->wbuf_valid_length) @@ -173,25 +184,37 @@ void pa_ioline_puts(pa_ioline *l, const char *c) { l->mainloop->defer_enable(l->defer_event, 1); } - - pa_ioline_unref(l); } void pa_ioline_set_callback(pa_ioline*l, void (*callback)(pa_ioline*io, const char *s, void *userdata), void *userdata) { - assert(l && l->ref >= 1); + assert(l); + assert(l->ref >= 1); + l->callback = callback; l->userdata = userdata; } -static void failure(pa_ioline *l) { - assert(l && l->ref >= 1 && !l->dead); +static void failure(pa_ioline *l, int process_leftover) { + assert(l); + assert(l->ref >= 1); + assert(!l->dead); - pa_ioline_close(l); + if (process_leftover && l->rbuf_valid_length > 0) { + /* Pass the last missing bit to the client */ + + if (l->callback) { + char *p = pa_xstrndup(l->rbuf+l->rbuf_index, l->rbuf_valid_length); + l->callback(l, p, l->userdata); + pa_xfree(p); + } + } if (l->callback) { l->callback(l, NULL, l->userdata); l->callback = NULL; } + + pa_ioline_close(l); } static void scan_for_lines(pa_ioline *l, size_t skip) { @@ -267,17 +290,13 @@ static int do_read(pa_ioline *l) { assert(len >= READ_SIZE); /* Read some data */ - r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len); - if (r == 0) { - /* Got an EOF, so fake an exit command. */ - l->rbuf_index = 0; - snprintf (l->rbuf, l->rbuf_length, "exit\n"); - r = 5; - pa_ioline_puts(l, "\nExiting.\n"); - do_write(l); - } else if (r < 0) { - pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); - failure(l); + if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) { + if (r < 0) { + pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); + failure(l, 0); + } else + failure(l, 1); + return -1; } @@ -299,7 +318,7 @@ static int do_write(pa_ioline *l) { if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) { pa_log(__FILE__": write(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); - failure(l); + failure(l, 0); return -1; } @@ -316,20 +335,21 @@ static int do_write(pa_ioline *l) { /* Try to flush read/write data */ static void do_work(pa_ioline *l) { - assert(l && l->ref >= 1); + assert(l); + assert(l->ref >= 1); pa_ioline_ref(l); l->mainloop->defer_enable(l->defer_event, 0); - if (!l->dead) - do_write(l); - if (!l->dead) do_read(l); + if (!l->dead) + do_write(l); + if (l->defer_close && !l->wbuf_valid_length) - failure(l); + failure(l, 1); pa_ioline_unref(l); } @@ -350,22 +370,25 @@ static void defer_callback(pa_mainloop_api*m, pa_defer_event*e, void *userdata) void pa_ioline_defer_close(pa_ioline *l) { assert(l); - + assert(l->ref >= 1); + l->defer_close = 1; if (!l->wbuf_valid_length) l->mainloop->defer_enable(l->defer_event, 1); } -void pa_ioline_printf(pa_ioline *s, const char *format, ...) { +void pa_ioline_printf(pa_ioline *l, const char *format, ...) { char *t; va_list ap; - + assert(l); + assert(l->ref >= 1); + va_start(ap, format); t = pa_vsprintf_malloc(format, ap); va_end(ap); - pa_ioline_puts(s, t); + pa_ioline_puts(l, t); pa_xfree(t); } From 75ac45b0de4cb03fa6eeea14081824c3cb6c8f67 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 11 Jun 2006 01:34:12 +0000 Subject: [PATCH 0911/1514] Add all the preopen libs to the polypaudio binary's dependency list as they aren't automatically detected. (Closes #17) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1008 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index de0c18dff..2e68ed94f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -108,6 +108,8 @@ polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) polypaudio_CPPFLAGS = $(AM_CPPFLAGS) polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \ $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) +# This is needed because automake doesn't properly expand the foreach below +polypaudio_DEPENDENCIES = libpolypcore.la $(PREOPEN_LIBS) if PREOPEN_MODS PREOPEN_LIBS = $(PREOPEN_MODS) From 15a0b28ee64760d1199a9a28d627dc9780250bb9 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 12 Jun 2006 12:19:24 +0000 Subject: [PATCH 0912/1514] Properly escape the m4 macros and make the code a bit more readable. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1009 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 244 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 207 insertions(+), 37 deletions(-) diff --git a/configure.ac b/configure.ac index 7a2fdbf03..a6a8aa2c9 100644 --- a/configure.ac +++ b/configure.ac @@ -336,13 +336,31 @@ AC_SUBST(LIBSNDFILE_LIBS) AC_ARG_ENABLE([oss], AC_HELP_STRING([--disable-oss], [Disable optional OSS support]), - [case "${enableval}" in yes) oss=yes ;; no) oss=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-oss) ;; esac],[oss=auto]) + [ + case "${enableval}" in + yes) oss=yes ;; + no) oss=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-oss) ;; + esac + ], + [oss=auto]) + if test "x${oss}" != xno ; then - AC_CHECK_HEADERS([sys/soundcard.h], [ - HAVE_OSS=1 - AC_DEFINE([HAVE_OSS], 1, [Have OSS?]) - ], [HAVE_OSS=0 ; if test "x$oss" = xyes ; then AC_MSG_ERROR([*** OSS support not found]) ; fi]) -else HAVE_OSS=0; fi + AC_CHECK_HEADERS([sys/soundcard.h], + [ + HAVE_OSS=1 + AC_DEFINE([HAVE_OSS], 1, [Have OSS?]) + ], + [ + HAVE_OSS=0 + if test "x$oss" = xyes ; then + AC_MSG_ERROR([*** OSS support not found]) + fi + ]) +else + HAVE_OSS=0 +fi + AC_SUBST(HAVE_OSS) AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1]) @@ -351,13 +369,31 @@ AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1]) AC_ARG_ENABLE([alsa], AC_HELP_STRING([--disable-alsa], [Disable optional ALSA support]), - [case "${enableval}" in yes) alsa=yes ;; no) alsa=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-alsa) ;; esac],[alsa=auto]) + [ + case "${enableval}" in + yes) alsa=yes ;; + no) alsa=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-alsa) ;; + esac + ], + [alsa=auto]) + if test "x${alsa}" != xno ; then - PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [ - HAVE_ALSA=1 - AC_DEFINE([HAVE_ALSA], 1, [Have ALSA?]) - ], [HAVE_ALSA=0 ; if test "x$alsa" = xyes ; then AC_MSG_ERROR([*** ALSA support not found]) ; fi]) -else HAVE_ALSA=0 ; fi + PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], + [ + HAVE_ALSA=1 + AC_DEFINE([HAVE_ALSA], 1, [Have ALSA?]) + ], + [ + HAVE_ALSA=0 + if test "x$alsa" = xyes ; then + AC_MSG_ERROR([*** ALSA support not found]) + fi + ]) +else + HAVE_ALSA=0 +fi + AC_SUBST(ASOUNDLIB_CFLAGS) AC_SUBST(ASOUNDLIB_LIBS) AC_SUBST(HAVE_ALSA) @@ -367,13 +403,31 @@ AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1]) AC_ARG_ENABLE([solaris], AC_HELP_STRING([--disable-solaris], [Disable optional Solaris audio support]), - [case "${enableval}" in yes) solaris=yes ;; no) solaris=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-solaris) ;; esac],[solaris=auto]) + [ + case "${enableval}" in + yes) solaris=yes ;; + no) solaris=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-solaris) ;; + esac + ], + [solaris=auto]) + if test "x${solaris}" != xno ; then - AC_CHECK_HEADERS([sys/audio.h], [ - HAVE_SOLARIS=1 - AC_DEFINE([HAVE_SOLARIS], 1, [Have Solaris audio?]) - ], [HAVE_SOLARIS=0 ; if test "x$solaris" = xyes ; then AC_MSG_ERROR([*** Solaris audio support not found]) ; fi]) -else HAVE_SOLARIS=0 ; fi + AC_CHECK_HEADERS([sys/audio.h], + [ + HAVE_SOLARIS=1 + AC_DEFINE([HAVE_SOLARIS], 1, [Have Solaris audio?]) + ], + [ + HAVE_SOLARIS=0 + if test "x$solaris" = xyes ; then + AC_MSG_ERROR([*** Solaris audio support not found]) + fi + ]) +else + HAVE_SOLARIS=0 +fi + AC_SUBST(HAVE_SOLARIS) AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1]) @@ -381,10 +435,28 @@ AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1]) AC_ARG_ENABLE([glib2], AC_HELP_STRING([--disable-glib2], [Disable optional GLib 2 support]), - [case "${enableval}" in yes) glib2=yes ;; no) glib2=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-glib2) ;; esac],[glib2=auto]) + [ + case "${enableval}" in + yes) glib2=yes ;; + no) glib2=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-glib2) ;; + esac + ], + [glib2=auto]) + if test "x${glib2}" != xno ; then - PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], HAVE_GLIB20=1, [HAVE_GLIB20=0 ; if test "x$glib2" = xyes ; then AC_MSG_ERROR([*** GLib 2 support not found]) ; fi]) -else HAVE_GLIB20=0 ; fi + PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], + HAVE_GLIB20=1, + [ + HAVE_GLIB20=0 + if test "x$glib2" = xyes ; then + AC_MSG_ERROR([*** GLib 2 support not found]) + fi + ]) +else + HAVE_GLIB20=0 +fi + AC_SUBST(GLIB20_CFLAGS) AC_SUBST(GLIB20_LIBS) AC_SUBST(HAVE_GLIB20) @@ -394,10 +466,28 @@ AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1]) AC_ARG_ENABLE([glib1], AC_HELP_STRING([--disable-glib1], [Disable optional GLib 1 support]), - [case "${enableval}" in yes) glib1=yes ;; no) glib1=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-glib1) ;; esac],[glib1=auto]) + [ + case "${enableval}" in + yes) glib1=yes ;; + no) glib1=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-glib1) ;; + esac + ], + [glib1=auto]) + if test "x${glib1}" != xno ; then - PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], HAVE_GLIB12=1, [HAVE_GLIB12=0 ; if test "x$glib1" = xyes ; then AC_MSG_ERROR([*** GLib 1 support not found]) ; fi]) -else HAVE_GLIB12=0 ; fi + PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], + HAVE_GLIB12=1, + [ + HAVE_GLIB12=0 + if test "x$glib1" = xyes ; then + AC_MSG_ERROR([*** GLib 1 support not found]) + fi + ]) +else + HAVE_GLIB12=0 +fi + AC_SUBST(GLIB12_CFLAGS) AC_SUBST(GLIB12_LIBS) AC_SUBST(HAVE_GLIB12) @@ -407,10 +497,32 @@ AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) AC_ARG_ENABLE([howl], AC_HELP_STRING([--disable-howl], [Disable optional Howl support]), - [case "${enableval}" in yes) howl=yes ;; no) howl=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-howl) ;; esac],[howl=auto]) + [ + case "${enableval}" in + yes) howl=yes ;; + no) howl=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-howl) ;; + esac + ], + [howl=auto]) + if test "x${howl}" != xno ; then - PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], HAVE_HOWL=1, PKG_CHECK_MODULES(HOWL, [ avahi-compat-howl >= 0.9.8 ], HAVE_HOWL=1, [HAVE_HOWL=0 ; if test "x$howl" = xyes ; then AC_MSG_ERROR([*** Howl support not found]) ; fi])) -else HAVE_HOWL=0 ; fi + PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], + HAVE_HOWL=1, + [ + PKG_CHECK_MODULES(HOWL, [ avahi-compat-howl >= 0.9.8 ], + HAVE_HOWL=1, + [ + HAVE_HOWL=0 + if test "x$howl" = xyes ; then + AC_MSG_ERROR([*** Howl support not found]) + fi + ]) + ]) +else + HAVE_HOWL=0 +fi + AC_SUBST(HOWL_CFLAGS) AC_SUBST(HOWL_LIBS) AC_SUBST(HAVE_HOWL) @@ -426,10 +538,28 @@ AC_SUBST(LIBOIL_LIBS) AC_ARG_ENABLE([jack], AC_HELP_STRING([--disable-jack], [Disable optional JACK support]), - [case "${enableval}" in yes) jack=yes ;; no) jack=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-jack) ;; esac],[jack=auto]) + [ + case "${enableval}" in + yes) jack=yes ;; + no) jack=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-jack) ;; + esac + ], + [jack=auto]) + if test "x${jack}" != xno ; then - PKG_CHECK_MODULES(JACK, [ jack >= 0.100 ], HAVE_JACK=1, [HAVE_JACK=0 ; if test "x$jack" = xyes ; then AC_MSG_ERROR([*** JACK support not found]) ; fi]) -else HAVE_JACK=0 ; fi + PKG_CHECK_MODULES(JACK, [ jack >= 0.100 ], + HAVE_JACK=1, + [ + HAVE_JACK=0 + if test "x$jack" = xyes ; then + AC_MSG_ERROR([*** JACK support not found]) + fi + ]) +else + HAVE_JACK=0 +fi + AC_SUBST(JACK_CFLAGS) AC_SUBST(JACK_LIBS) AC_SUBST(HAVE_JACK) @@ -439,10 +569,28 @@ AM_CONDITIONAL([HAVE_JACK], [test "x$HAVE_JACK" = x1]) AC_ARG_ENABLE([asyncns], AC_HELP_STRING([--disable-asyncns], [Disable optional Async DNS support]), - [case "${enableval}" in yes) asyncns=yes ;; no) asyncns=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-asyncns) ;; esac],[asyncns=auto]) + [ + case "${enableval}" in + yes) asyncns=yes ;; + no) asyncns=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-asyncns) ;; + esac + ], + [asyncns=auto]) + if test "x${asyncns}" != xno ; then - PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, [HAVE_LIBASYNCNS=0 ; if test "x$asyncns" = xyes ; then AC_MSG_ERROR([*** Async DNS support not found]) ; fi]) -else HAVE_LIBASYNCNS=0 ; fi + PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], + HAVE_LIBASYNCNS=1, + [ + HAVE_LIBASYNCNS=0 + if test "x$asyncns" = xyes ; then + AC_MSG_ERROR([*** Async DNS support not found]) + fi + ]) +else + HAVE_LIBASYNCNS=0 +fi + AC_SUBST(LIBASYNCNS_CFLAGS) AC_SUBST(LIBASYNCNS_LIBS) AC_SUBST(HAVE_LIBASYNCNS) @@ -456,26 +604,48 @@ fi AC_ARG_ENABLE([tcpwrap], AC_HELP_STRING([--disable-tcpwrap], [Disable optional TCP wrappers support]), - [case "${enableval}" in yes) tcpwrap=yes ;; no) tcpwrap=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-tcpwrap) ;; esac],[tcpwrap=auto]) + [ + case "${enableval}" in + yes) tcpwrap=yes ;; + no) tcpwrap=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-tcpwrap) ;; + esac + ], + [tcpwrap=auto]) + if test "x${tcpwrap}" != xno ; then ACX_LIBWRAP if test "x${LIBWRAP_LIBS}" = x && test "x$tcpwrap" = xyes ; then AC_MSG_ERROR([*** TCP wrappers support not found]) fi -else LIBWRAP_LIBS= ; fi +else + LIBWRAP_LIBS= +fi + AC_SUBST(LIBWRAP_LIBS) #### LIRC support (optional) #### AC_ARG_ENABLE([lirc], AC_HELP_STRING([--disable-lirc], [Disable optional LIRC support]), - [case "${enableval}" in yes) lirc=yes ;; no) lirc=no ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-lirc) ;; esac],[lirc=auto]) + [ + case "${enableval}" in + yes) lirc=yes ;; + no) lirc=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-lirc) ;; + esac + ], + [lirc=auto]) + if test "x${lirc}" != xno ; then ACX_LIRC if test "x${HAVE_LIRC}" = x0 && test "x$lirc" = xyes ; then AC_MSG_ERROR([*** LIRC support not found]) fi -else HAVE_LIRC=0 ; fi +else + HAVE_LIRC=0 +fi + AC_SUBST(LIRC_CFLAGS) AC_SUBST(LIRC_LIBS) AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) From 7c770e22e453347e0d995f0b3c1c6c8986118a45 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 12 Jun 2006 12:52:37 +0000 Subject: [PATCH 0913/1514] Also look in winsock2.h for INADDR_NONE. (solves #18) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1010 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index a6a8aa2c9..34ba78c6c 100644 --- a/configure.ac +++ b/configure.ac @@ -212,7 +212,8 @@ AM_CONDITIONAL(HAVE_SIGXCPU, test "x$HAVE_SIGXCPU" = "x1") # Solaris lacks this AC_CHECK_DEFINE([INADDR_NONE], [netinet/in.h], [], - [AC_DEFINE([INADDR_NONE], [0xffffffff], [Define INADDR_NONE if not found in ])]) + [AC_CHECK_DEFINE([INADDR_NONE], [winsock2.h], [], + [AC_DEFINE([INADDR_NONE], [0xffffffff], [Define INADDR_NONE if not found in ])])]) #### Check for libs #### From c32176b0ad0f94adc820de1b57aff8c89bd53d9f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 12 Jun 2006 13:56:30 +0000 Subject: [PATCH 0914/1514] Fix AC_CHECK_DEFINE so that we can look in different files for the same define. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1011 fefdeb5f-60dc-0310-8127-8f9354f1896f --- acinclude.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 02f271b43..edd803445 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -199,8 +199,8 @@ AC_LANG_RESTORE ])dnl ACX_PTHREAD AC_DEFUN([AC_CHECK_DEFINE],[ -AS_VAR_PUSHDEF([ac_var],[ac_cv_defined_$1])dnl -AC_CACHE_CHECK([for $1 defined], ac_var, +AS_VAR_PUSHDEF([ac_var],[ac_cv_defined_$1_$2])dnl +AC_CACHE_CHECK([for $1 in $2], ac_var, AC_TRY_COMPILE([#include <$2>],[ #ifdef $1 int ok; From 519aa9b2ef4ec1fdbbc746f753240113423e1b21 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 12 Jun 2006 14:18:19 +0000 Subject: [PATCH 0915/1514] Use AM_ICONV to determine what needs to be done for iconv support. (closes #19) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1012 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 6 +++++- src/Makefile.am | 4 ++-- src/polyp/utf8.c | 9 +++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 34ba78c6c..0ccbe4f31 100644 --- a/configure.ac +++ b/configure.ac @@ -165,7 +165,7 @@ AM_CONDITIONAL(OS_IS_WIN32, test "x$os_is_win32" = "x1") AC_HEADER_STDC # POSIX -AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h iconv.h netdb.h netinet/in.h \ +AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \ netinet/in_systm.h netinet/ip.h netinet/tcp.h pwd.h sched.h \ sys/resource.h sys/select.h sys/socket.h sys/wait.h \ syslog.h]) @@ -270,6 +270,10 @@ ACX_PTHREAD AC_SYS_LARGEFILE +#### [lib]iconv #### + +AM_ICONV + ################################### # External libraries # ################################### diff --git a/src/Makefile.am b/src/Makefile.am index 2e68ed94f..a98ea6970 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -420,7 +420,7 @@ endif libpolyp_la_CFLAGS = $(AM_CFLAGS) libpolyp_la_LDFLAGS = -version-info $(LIBPOLYP_VERSION_INFO) -libpolyp_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) +libpolyp_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LIBICONV) if HAVE_X11 libpolyp_la_CFLAGS += $(X_CFLAGS) @@ -587,7 +587,7 @@ endif libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) libpolypcore_la_LDFLAGS = -version-info $(LIBPOLYPCORE_VERSION_INFO) -libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) +libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV) ################################### # Plug-in support libraries # diff --git a/src/polyp/utf8.c b/src/polyp/utf8.c index 931328e50..33fa7214e 100644 --- a/src/polyp/utf8.c +++ b/src/polyp/utf8.c @@ -34,7 +34,7 @@ #include #include -#ifdef HAVE_ICONV_H +#ifdef HAVE_ICONV #include #endif @@ -168,14 +168,15 @@ char* pa_utf8_filter (const char *str) { return utf8_validate(str, new_str); } -#ifdef HAVE_ICONV_H +#ifdef HAVE_ICONV static char* iconv_simple(const char *str, const char *to, const char *from) { char *new_str; size_t len, inlen; iconv_t cd; - char *inbuf, *outbuf; + ICONV_CONST char *inbuf; + char *outbuf; size_t res, inbytes, outbytes; cd = iconv_open(to, from); @@ -187,7 +188,7 @@ static char* iconv_simple(const char *str, const char *to, const char *from) { assert(new_str); while (1) { - inbuf = (char*)str; /* Brain dead prototype for iconv() */ + inbuf = (ICONV_CONST char*)str; /* Brain dead prototype for iconv() */ inbytes = inlen; outbuf = new_str; outbytes = len; From 7582f7493b4103dcc1442c511d856cb616409078 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Jun 2006 09:33:04 +0000 Subject: [PATCH 0916/1514] Handle pretty printing of IPv6 socket names. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1013 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/socket-util.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/polypcore/socket-util.c b/src/polypcore/socket-util.c index aefcb5eff..3cd205db0 100644 --- a/src/polypcore/socket-util.c +++ b/src/polypcore/socket-util.c @@ -56,6 +56,13 @@ #ifdef HAVE_NETDB_H #include #endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifndef HAVE_INET_NTOP +#include "inet_ntop.h" +#endif #include "winsock.h" @@ -85,6 +92,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { union { struct sockaddr sa; struct sockaddr_in in; + struct sockaddr_in6 in6; #ifdef HAVE_SYS_UN_H struct sockaddr_un un; #endif @@ -103,6 +111,15 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { ip & 0xFF, ntohs(sa.in.sin_port)); return; + } else if (sa.sa.sa_family == AF_INET6) { + char buf[INET6_ADDRSTRLEN]; + const char *res; + + res = inet_ntop(AF_INET6, &sa.in6.sin6_addr, buf, sizeof(buf)); + if (res) { + snprintf(c, l, "TCP/IP client from [%s]:%u", buf, ntohs(sa.in6.sin6_port)); + return; + } #ifdef HAVE_SYS_UN_H } else if (sa.sa.sa_family == AF_UNIX) { snprintf(c, l, "UNIX socket client"); From 928847933891f1d47b87b66299d5d2b241107c48 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Jun 2006 09:33:55 +0000 Subject: [PATCH 0917/1514] Tweak the printing of client connections a bit so that it's more apparent what and who it is that's connecting. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1014 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/client.c | 3 +++ src/polypcore/protocol-esound.c | 5 +++-- src/polypcore/protocol-native.c | 5 ++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/polypcore/client.c b/src/polypcore/client.c index b5ed2fd0b..4ece07a8b 100644 --- a/src/polypcore/client.c +++ b/src/polypcore/client.c @@ -86,6 +86,9 @@ void pa_client_kill(pa_client *c) { void pa_client_set_name(pa_client *c, const char *name) { assert(c); + + pa_log_info(__FILE__": client %u changed name from \"%s\" to \"%s\"", c->index, c->name, name); + pa_xfree(c->name); c->name = pa_xstrdup(name); diff --git a/src/polypcore/protocol-esound.c b/src/polypcore/protocol-esound.c index 02e140b95..c9bc504d6 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/polypcore/protocol-esound.c @@ -1139,7 +1139,7 @@ static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timev static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) { struct connection *c; pa_protocol_esound *p = userdata; - char cname[256]; + char cname[256], pname[128]; assert(s && io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { @@ -1153,7 +1153,8 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->io = io; pa_iochannel_set_callback(c->io, io_callback, c); - pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); + pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname)); + snprintf(cname, sizeof(cname), "EsounD client (%s)", pname); assert(p->core); c->client = pa_client_new(p->core, __FILE__, cname); assert(c->client); diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index f663dc356..221601a69 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -2213,6 +2213,7 @@ static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timev static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, void *userdata) { pa_protocol_native *p = userdata; struct connection *c; + char cname[256], pname[128]; assert(io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { @@ -2235,8 +2236,10 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo c->version = 8; c->protocol = p; + pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname)); + snprintf(cname, sizeof(cname), "Native client (%s)", pname); assert(p->core); - c->client = pa_client_new(p->core, __FILE__, "Client"); + c->client = pa_client_new(p->core, __FILE__, cname); assert(c->client); c->client->kill = client_kill_cb; c->client->userdata = c; From b5a8815ec96708426f3a2c81629355660cea376a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Jun 2006 10:53:49 +0000 Subject: [PATCH 0918/1514] Make sure our inet_ntop() implementation gets linked into the new users. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1015 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index a98ea6970..2dc2c6639 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -382,6 +382,7 @@ libpolyp_la_SOURCES += \ polypcore/gccmacro.h \ polypcore/hashmap.c polypcore/hashmap.h \ polypcore/idxset.c polypcore/idxset.h \ + polypcore/inet_ntop.c polypcore/inet_ntop.h \ polypcore/iochannel.c polypcore/iochannel.h \ polypcore/llist.h \ polypcore/log.c polypcore/log.h \ @@ -741,7 +742,9 @@ libauthkey_prop_la_SOURCES = polypcore/authkey-prop.c polypcore/authkey-prop.h libauthkey_prop_la_LDFLAGS = -avoid-version libauthkey_prop_la_LIBADD = $(AM_LIBADD) libpolypcore.la -libsocket_util_la_SOURCES = polypcore/socket-util.c polypcore/socket-util.h +libsocket_util_la_SOURCES = \ + polypcore/inet_ntop.c polypcor/inet_ntop.h \ + polypcore/socket-util.c polypcore/socket-util.h libsocket_util_la_LDFLAGS = -avoid-version libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) libpolypcore.la From 0f13c43797dd291b02a6b0fa1c9933a35da95c01 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Jun 2006 13:21:14 +0000 Subject: [PATCH 0919/1514] Catch the access() system call as some applications do this to test if they can open /dev/dsp. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1016 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 8bad126bf..da8f6786b 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -101,6 +101,7 @@ static FILE* (*_fopen)(const char *path, const char *mode) = NULL; static int (*_open64)(const char *, int, mode_t) = NULL; static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; static int (*_fclose)(FILE *f) = NULL; +static int (*_access)(const char *, int) = NULL; /* dlsym() violates ISO C, so confide the breakage into this function to * avoid warnings. */ @@ -141,6 +142,14 @@ do { \ pthread_mutex_unlock(&func_mutex); \ } while(0) +#define LOAD_ACCESS_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_access) \ + _access = (int (*)(const char*, int)) dlsym_fn(RTLD_NEXT, "access"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + #define LOAD_FOPEN_FUNC() \ do { \ pthread_mutex_lock(&func_mutex); \ @@ -1725,6 +1734,25 @@ int close(int fd) { return 0; } +int access(const char *pathname, int mode) { + debug(__FILE__": access()\n"); + + if (strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0) { + LOAD_ACCESS_FUNC(); + return _access(pathname, mode); + } + + if (mode & (W_OK | X_OK)) { + errno = EACCES; + return -1; + } + + return 0; +} + int open64(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; From dd0f80e3e28f2c4a0195d763f861594a9265ef1f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Jun 2006 15:54:11 +0000 Subject: [PATCH 0920/1514] Make a copy of the va_list as vsnprintf() is free to change it. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1017 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/core-util.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/polypcore/core-util.c b/src/polypcore/core-util.c index 6cf281c5f..dfa41f57f 100644 --- a/src/polypcore/core-util.c +++ b/src/polypcore/core-util.c @@ -366,8 +366,14 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) { for(;;) { int r; + va_list aq; + + va_copy(aq, ap); + c = pa_xrealloc(c, size); - r = vsnprintf(c, size, format, ap); + r = vsnprintf(c, size, format, aq); + + va_end(aq); if (r > -1 && r < size) return c; From 3fa491dc905edb8f54b10bff0b896e8ad7f733c6 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 15 Jun 2006 14:47:14 +0000 Subject: [PATCH 0921/1514] Make debug output in padsp a bit less verbose. Specifying -d twice will give original output. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1018 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp | 6 +- src/utils/padsp.c | 260 +++++++++++++++++++++++++--------------------- 2 files changed, 147 insertions(+), 119 deletions(-) diff --git a/src/utils/padsp b/src/utils/padsp index b43535b63..27f99336b 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -46,7 +46,11 @@ while getopts 'hs:n:m:MSDd' param ; do export PADSP_NO_DSP ;; d) - PADSP_DEBUG=1 + if [ x"$PADSP_DEBUG" = x ]; then + PADSP_DEBUG=1 + else + PADSP_DEBUG=$(( $PADSP_DEBUG + 1 )) + fi export PADSP_DEBUG ;; *) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index da8f6786b..4fe8205ee 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -176,7 +176,7 @@ do { \ #define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ - debug(__FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ } while(0); @@ -184,20 +184,34 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ #define STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ !(i)->stream || pa_stream_get_state((i)->stream) != PA_STREAM_READY) { \ - debug(__FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ } while(0); -static void debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); +static void debug(int level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); -static void debug(const char *format, ...) { +#define DEBUG_LEVEL_ALWAYS 0 +#define DEBUG_LEVEL_NORMAL 1 +#define DEBUG_LEVEL_VERBOSE 2 + +static void debug(int level, const char *format, ...) { va_list ap; - if (getenv("PADSP_DEBUG")) { - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); - } + const char *dlevel_s; + int dlevel; + + dlevel_s = getenv("PADSP_DEBUG"); + if (!dlevel_s) + return; + + dlevel = atoi(dlevel_s); + + if (dlevel < level) + return; + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); } static int padsp_disabled(void) { @@ -280,7 +294,7 @@ static void function_exit(void) { static void fd_info_free(fd_info *i) { assert(i); - debug(__FILE__": freeing fd info (fd=%i)\n", i->app_fd); + debug(DEBUG_LEVEL_NORMAL, __FILE__": freeing fd info (fd=%i)\n", i->app_fd); dsp_drain(i); @@ -323,7 +337,7 @@ static fd_info *fd_info_ref(fd_info *i) { assert(i->ref >= 1); i->ref++; -/* debug(__FILE__": ref++, now %i\n", i->ref); */ + debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref++, now %i\n", i->ref); pthread_mutex_unlock(&i->mutex); return i; @@ -334,7 +348,7 @@ static void fd_info_unref(fd_info *i) { pthread_mutex_lock(&i->mutex); assert(i->ref >= 1); r = --i->ref; -/* debug(__FILE__": ref--, now %i\n", i->ref); */ + debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref); pthread_mutex_unlock(&i->mutex); if (r <= 0) @@ -397,7 +411,7 @@ static const char *stream_name(void) { static void atfork_prepare(void) { fd_info *i; - debug(__FILE__": atfork_prepare() enter\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() enter\n"); function_enter(); @@ -411,13 +425,13 @@ static void atfork_prepare(void) { pthread_mutex_lock(&func_mutex); - debug(__FILE__": atfork_prepare() exit\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() exit\n"); } static void atfork_parent(void) { fd_info *i; - debug(__FILE__": atfork_parent() enter\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() enter\n"); pthread_mutex_unlock(&func_mutex); @@ -430,13 +444,13 @@ static void atfork_parent(void) { function_exit(); - debug(__FILE__": atfork_parent() exit\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() exit\n"); } static void atfork_child(void) { fd_info *i; - debug(__FILE__": atfork_child() enter\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() enter\n"); /* We do only the bare minimum to get all fds closed */ pthread_mutex_init(&func_mutex, NULL); @@ -471,7 +485,7 @@ static void atfork_child(void) { function_exit(); - debug(__FILE__": atfork_child() exit\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() exit\n"); } static void install_atfork(void) { @@ -504,7 +518,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { char name[64]; static pthread_once_t install_atfork_once = PTHREAD_ONCE_INIT; - debug(__FILE__": fd_info_new()\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": fd_info_new()\n"); signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */ @@ -535,7 +549,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfds) < 0) { *_errno = errno; - debug(__FILE__": socket() failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": socket() failed: %s\n", strerror(errno)); goto fail; } @@ -544,13 +558,13 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { if (!(i->mainloop = pa_threaded_mainloop_new())) { *_errno = EIO; - debug(__FILE__": pa_threaded_mainloop_new() failed\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_threaded_mainloop_new() failed\n"); goto fail; } if (!(i->context = pa_context_new(pa_threaded_mainloop_get_api(i->mainloop), client_name(name, sizeof(name))))) { *_errno = EIO; - debug(__FILE__": pa_context_new() failed\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_new() failed\n"); goto fail; } @@ -558,7 +572,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { if (pa_context_connect(i->context, NULL, 0, NULL) < 0) { *_errno = ECONNREFUSED; - debug(__FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -566,7 +580,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { if (pa_threaded_mainloop_start(i->mainloop) < 0) { *_errno = EIO; - debug(__FILE__": pa_threaded_mainloop_start() failed\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_threaded_mainloop_start() failed\n"); goto unlock_and_fail; } @@ -575,7 +589,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { if (pa_context_get_state(i->context) != PA_CONTEXT_READY) { *_errno = ECONNREFUSED; - debug(__FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto unlock_and_fail; } @@ -654,8 +668,8 @@ static void fix_metrics(fd_info *i) { i->fragment_size = 1024; } - debug(__FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); - debug(__FILE__": fixated metrics to %i fragments, %li bytes each.\n", i->n_fragments, (long)i->fragment_size); + debug(DEBUG_LEVEL_NORMAL, __FILE__": sample spec: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": fixated metrics to %i fragments, %li bytes each.\n", i->n_fragments, (long)i->fragment_size); } static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { @@ -699,7 +713,7 @@ static int fd_info_copy_data(fd_info *i, int force) { return -1; if ((n = pa_stream_writable_size(i->stream)) == (size_t) -1) { - debug(__FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); return -1; } @@ -708,7 +722,7 @@ static int fd_info_copy_data(fd_info *i, int force) { if (!i->buf) { if (!(i->buf = malloc(i->fragment_size))) { - debug(__FILE__": malloc() failed.\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": malloc() failed.\n"); return -1; } } @@ -718,12 +732,12 @@ static int fd_info_copy_data(fd_info *i, int force) { if (errno == EAGAIN) break; - debug(__FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } if (pa_stream_write(i->stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) { - debug(__FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); return -1; } @@ -749,11 +763,11 @@ static void stream_state_cb(pa_stream *s, void * userdata) { switch (pa_stream_get_state(s)) { case PA_STREAM_READY: - debug(__FILE__": stream established.\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": stream established.\n"); break; case PA_STREAM_FAILED: - debug(__FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); fd_info_shutdown(i); break; @@ -773,7 +787,7 @@ static int create_stream(fd_info *i) { fix_metrics(i); if (!(i->stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) { - debug(__FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -788,7 +802,7 @@ static int create_stream(fd_info *i) { attr.minreq = i->fragment_size; if (pa_stream_connect_playback(i->stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { - debug(__FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -847,7 +861,10 @@ static int dsp_open(int flags, int *_errno) { int ret; int f; + debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open()\n"); + if ((flags != O_WRONLY) && (flags != (O_WRONLY|O_NONBLOCK))) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": bad access flags: %x\n", flags); *_errno = EACCES; return -1; } @@ -875,7 +892,7 @@ static int dsp_open(int flags, int *_errno) { pa_threaded_mainloop_unlock(i->mainloop); - debug(__FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd); + debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd); fd_info_add_to_list(i); ret = i->app_fd; @@ -891,7 +908,7 @@ fail: *_errno = EIO; - debug(__FILE__": dsp_open() failed\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() failed\n"); return -1; } @@ -929,7 +946,7 @@ static void subscribe_cb(pa_context *context, pa_subscription_event_type_t t, ui return; if (!(o = pa_context_get_sink_info_by_index(i->context, i->sink_index, sink_info_cb, i))) { - debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); return; } @@ -941,6 +958,8 @@ static int mixer_open(int flags, int *_errno) { pa_operation *o; int ret; + debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open()\n"); + if (!(i = fd_info_new(FD_INFO_MIXER, _errno))) return -1; @@ -949,7 +968,7 @@ static int mixer_open(int flags, int *_errno) { pa_context_set_subscribe_callback(i->context, subscribe_cb, i); if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK, context_success_cb, i))) { - debug(__FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; } @@ -961,7 +980,7 @@ static int mixer_open(int flags, int *_errno) { } if (!i->operation_success) { - debug(__FILE__":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; } @@ -970,7 +989,7 @@ static int mixer_open(int flags, int *_errno) { pa_operation_unref(o); if (!(o = pa_context_get_sink_info_by_name(i->context, NULL, sink_info_cb, i))) { - debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; } @@ -982,14 +1001,14 @@ static int mixer_open(int flags, int *_errno) { } if (!i->operation_success) { - debug(__FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; } pa_threaded_mainloop_unlock(i->mainloop); - debug(__FILE__": mixer_open() succeeded, fd=%i\n", i->app_fd); + debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() succeeded, fd=%i\n", i->app_fd); fd_info_add_to_list(i); ret = i->app_fd; @@ -1005,7 +1024,7 @@ fail: *_errno = EIO; - debug(__FILE__": mixer_open() failed\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() failed\n"); return -1; } @@ -1039,11 +1058,11 @@ static int sndstat_open(int flags, int *_errno) { int fd = -1; int e; - debug(__FILE__": sndstat_open()\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": sndstat_open()\n"); if (flags != O_RDONLY && flags != (O_RDONLY|O_LARGEFILE)) { *_errno = EACCES; - debug(__FILE__": bad access!\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": bad access!\n"); goto fail; } @@ -1054,7 +1073,7 @@ static int sndstat_open(int flags, int *_errno) { if (fd < 0) { *_errno = e; - debug(__FILE__": mkstemp() failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": mkstemp() failed: %s\n", strerror(errno)); goto fail; } @@ -1062,13 +1081,13 @@ static int sndstat_open(int flags, int *_errno) { if (write(fd, sndstat, sizeof(sndstat) -1) != sizeof(sndstat)-1) { *_errno = errno; - debug(__FILE__": write() failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": write() failed: %s\n", strerror(errno)); goto fail; } if (lseek(fd, SEEK_SET, 0) < 0) { *_errno = errno; - debug(__FILE__": lseek() failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": lseek() failed: %s\n", strerror(errno)); goto fail; } @@ -1085,7 +1104,7 @@ int open(const char *filename, int flags, ...) { mode_t mode = 0; int r, _errno = 0; - debug(__FILE__": open(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename); va_start(args, flags); if (flags & O_CREAT) @@ -1122,19 +1141,19 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno switch (request) { case SOUND_MIXER_READ_DEVMASK : - debug(__FILE__": SOUND_MIXER_READ_DEVMASK\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_DEVMASK\n"); *(int*) argp = SOUND_MASK_PCM; break; case SOUND_MIXER_READ_RECMASK : - debug(__FILE__": SOUND_MIXER_READ_RECMASK\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECMASK\n"); *(int*) argp = 0; break; case SOUND_MIXER_READ_STEREODEVS: - debug(__FILE__": SOUND_MIXER_READ_STEREODEVS\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_STEREODEVS\n"); pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = i->volume.channels > 1 ? SOUND_MASK_PCM : 0; @@ -1143,20 +1162,20 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno break; case SOUND_MIXER_READ_RECSRC: - debug(__FILE__": SOUND_MIXER_READ_RECSRC\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECSRC\n"); *(int*) argp = 0; break; case SOUND_MIXER_READ_CAPS: - debug(__FILE__": SOUND_MIXER_READ_CAPS\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_CAPS\n"); *(int*) argp = 0; break; case SOUND_MIXER_READ_PCM: - debug(__FILE__": SOUND_MIXER_READ_PCM\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_PCM\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1171,7 +1190,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno case SOUND_MIXER_WRITE_PCM: { pa_cvolume v; - debug(__FILE__": SOUND_MIXER_WRITE_PCM\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_PCM\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1184,7 +1203,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno pa_operation *o; if (!(o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, &i->volume, NULL, NULL))) - debug(__FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); else { i->operation_success = 0; @@ -1196,7 +1215,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno exit_loop: if (!i->operation_success) - debug(__FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context))); pa_operation_unref(o); } @@ -1213,6 +1232,8 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno case SOUND_MIXER_INFO: { mixer_info *mi = argp; + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_INFO\n"); + memset(mi, 0, sizeof(mixer_info)); strncpy(mi->id, "POLYPAUDIO", sizeof(mi->id)); strncpy(mi->name, "Polypaudio Virtual OSS", sizeof(mi->name)); @@ -1223,7 +1244,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno } default: - debug(__FILE__": unknown ioctl 0x%08lx\n", request); + debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); *_errno = EINVAL; goto fail; @@ -1296,7 +1317,7 @@ static int dsp_flush_socket(fd_info *i) { return -1; if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { - debug(__FILE__": SIOCINQ: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno)); return -1; } @@ -1306,7 +1327,7 @@ static int dsp_flush_socket(fd_info *i) { k = (size_t) l > sizeof(buf) ? sizeof(buf) : (size_t) l; if (read(i->thread_fd, buf, k) < 0) - debug(__FILE__": read(): %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", strerror(errno)); l -= k; } @@ -1324,7 +1345,7 @@ static int dsp_empty_socket(fd_info *i) { break; if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { - debug(__FILE__": SIOCINQ: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno)); break; } @@ -1346,7 +1367,7 @@ static int dsp_drain(fd_info *i) { if (!i->mainloop) return 0; - debug(__FILE__": Draining.\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Draining.\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1356,10 +1377,10 @@ static int dsp_drain(fd_info *i) { if (!i->stream) goto fail; - debug(__FILE__": Really draining.\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Really draining.\n"); if (!(o = pa_stream_drain(i->stream, stream_success_cb, i))) { - debug(__FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -1371,7 +1392,7 @@ static int dsp_drain(fd_info *i) { } if (!i->operation_success) { - debug(__FILE__": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain() 2: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -1399,10 +1420,10 @@ static int dsp_trigger(fd_info *i) { if (dsp_empty_socket(i) < 0) goto fail; - debug(__FILE__": Triggering.\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": Triggering.\n"); if (!(o = pa_stream_trigger(i->stream, stream_success_cb, i))) { - debug(__FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -1414,7 +1435,7 @@ static int dsp_trigger(fd_info *i) { } if (!i->operation_success) { - debug(__FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -1435,7 +1456,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) switch (request) { case SNDCTL_DSP_SETFMT: { - debug(__FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1455,7 +1476,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) int valid; char t[256]; - debug(__FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1467,7 +1488,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) free_stream(i); } - debug(__FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); pa_threaded_mainloop_unlock(i->mainloop); @@ -1480,7 +1501,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } case SNDCTL_DSP_STEREO: - debug(__FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1494,7 +1515,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_sample_spec ss; int valid; - debug(__FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1517,7 +1538,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } case SNDCTL_DSP_GETBLKSIZE: - debug(__FILE__": SNDCTL_DSP_GETBLKSIZE\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETBLKSIZE\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1529,7 +1550,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; case SNDCTL_DSP_SETFRAGMENT: - debug(__FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%8x\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%8x\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1543,7 +1564,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; case SNDCTL_DSP_GETCAPS: - debug(__FILE__": SNDCTL_DSP_CAPS\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n"); *(int*) argp = DSP_CAP_MULTI; break; @@ -1551,7 +1572,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETODELAY: { int l; - debug(__FILE__": SNDCTL_DSP_GETODELAY\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1568,7 +1589,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } if (pa_context_errno(i->context) != PA_ERR_NODATA) { - debug(__FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context))); break; } @@ -1578,19 +1599,19 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) exit_loop: if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) - debug(__FILE__": SIOCINQ failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); else *(int*) argp += l; pa_threaded_mainloop_unlock(i->mainloop); - debug(__FILE__": ODELAY: %i\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": ODELAY: %i\n", *(int*) argp); break; } case SNDCTL_DSP_RESET: { - debug(__FILE__": SNDCTL_DSP_RESET\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_RESET\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1603,21 +1624,21 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } case SNDCTL_DSP_GETFMTS: { - debug(__FILE__": SNDCTL_DSP_GETFMTS\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETFMTS\n"); *(int*) argp = AFMT_MU_LAW|AFMT_A_LAW|AFMT_U8|AFMT_S16_LE|AFMT_S16_BE; break; } case SNDCTL_DSP_POST: - debug(__FILE__": SNDCTL_DSP_POST\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_POST\n"); if (dsp_trigger(i) < 0) *_errno = EIO; break; case SNDCTL_DSP_SYNC: - debug(__FILE__": SNDCTL_DSP_SYNC\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SYNC\n"); if (dsp_drain(i) < 0) *_errno = EIO; @@ -1629,7 +1650,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) int l; size_t k = 0; - debug(__FILE__": SNDCTL_DSP_GETOSPACE\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOSPACE\n"); pa_threaded_mainloop_lock(i->mainloop); @@ -1637,12 +1658,12 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) if (i->stream) { if ((k = pa_stream_writable_size(i->stream)) == (size_t) -1) - debug(__FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); } else k = i->fragment_size * i->n_fragments; if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { - debug(__FILE__": SIOCINQ failed: %s\n", strerror(errno)); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); l = 0; } @@ -1653,13 +1674,13 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_unlock(i->mainloop); - debug(__FILE__": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi->fragsize, bi->fragstotal, bi->bytes, bi->fragments); + debug(DEBUG_LEVEL_NORMAL, __FILE__": fragsize=%i, fragstotal=%i, bytes=%i, fragments=%i\n", bi->fragsize, bi->fragstotal, bi->bytes, bi->fragments); break; } default: - debug(__FILE__": unknwon ioctl 0x%08lx\n", request); + debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); *_errno = EINVAL; goto fail; @@ -1678,7 +1699,7 @@ int ioctl(int fd, unsigned long request, ...) { void *argp; int r, _errno = 0; - debug(__FILE__": ioctl()\n"); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": ioctl()\n"); va_start(args, request); argp = va_arg(args, void *); @@ -1713,7 +1734,7 @@ int ioctl(int fd, unsigned long request, ...) { int close(int fd) { fd_info *i; - debug(__FILE__": close()\n"); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": close()\n"); if (!function_enter()) { LOAD_CLOSE_FUNC(); @@ -1735,7 +1756,7 @@ int close(int fd) { } int access(const char *pathname, int mode) { - debug(__FILE__": access()\n"); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname); if (strcmp(pathname, "/dev/dsp") != 0 && strcmp(pathname, "/dev/adsp") != 0 && @@ -1746,10 +1767,13 @@ int access(const char *pathname, int mode) { } if (mode & (W_OK | X_OK)) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": access(%s, %x) = EACCESS\n", pathname, mode); errno = EACCES; return -1; } + debug(DEBUG_LEVEL_NORMAL, __FILE__": access(%s, %x) = OK\n", pathname, mode); + return 0; } @@ -1757,7 +1781,7 @@ int open64(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; - debug(__FILE__": open64(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename); va_start(args, flags); if (flags & O_CREAT) @@ -1780,32 +1804,32 @@ FILE* fopen(const char *filename, const char *mode) { int fd; mode_t m; - debug(__FILE__": fopen(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename); - if (strcmp(filename, "/dev/dsp") == 0 || - strcmp(filename, "/dev/adsp") == 0) { - - if (strcmp(mode, "wb") != 0) { - errno = EACCES; - return NULL; - } - - m = O_WRONLY; - } else if (strcmp(filename, "/dev/sndstat") == 0) { - - if (strcmp(mode, "r") != 0) { - errno = EACCES; - return NULL; - } - - m = O_RDONLY; - } else if (strcmp(filename, "/dev/mixer") == 0) - m = O_RDWR; - else { + if (strcmp(filename, "/dev/dsp") != 0 && + strcmp(filename, "/dev/adsp") != 0 && + strcmp(filename, "/dev/sndstat") != 0 && + strcmp(filename, "/dev/mixer") != 0) { LOAD_FOPEN_FUNC(); return _fopen(filename, mode); } + switch (mode[0]) { + case 'r': + m = O_RDONLY; + break; + case 'w': + case 'a': + m = O_WRONLY; + break; + default: + errno = EINVAL; + return NULL; + } + + if ((((mode[1] == 'b') || (mode[1] == 't')) && (mode[2] == '+')) || (mode[1] == '+')) + m = O_RDWR; + if ((fd = open(filename, m)) < 0) return NULL; @@ -1819,7 +1843,7 @@ FILE* fopen(const char *filename, const char *mode) { FILE *fopen64(const char *filename, const char *mode) { - debug(__FILE__": fopen64(%s)\n", filename); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename); if (strcmp(filename, "/dev/dsp") != 0 && strcmp(filename, "/dev/adsp") != 0 && @@ -1835,7 +1859,7 @@ FILE *fopen64(const char *filename, const char *mode) { int fclose(FILE *f) { fd_info *i; - debug(__FILE__": fclose()\n"); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": fclose()\n"); if (!function_enter()) { LOAD_FCLOSE_FUNC(); From 8e37d68ae3206abb306b7cf00f0189e99edb4aa8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Jun 2006 17:34:27 +0000 Subject: [PATCH 0922/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1019 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/todo b/doc/todo index 0569924c2..7b83ea984 100644 --- a/doc/todo +++ b/doc/todo @@ -33,6 +33,9 @@ Post 0.9.0: - drop dependency of libpolyp on libX11, instead use an external mini binary - "hot" moving of streams between sinks - check if using prctl(PR_GET_NAME) makes sense in pa_get_binary_name() +- gconf module + frontend +- hooks for creating sink inputs +- module-cli argument exit-on-eof Long term: - pass meta info for hearing impaired From a529b281ebe32ee07f80f77aa13e24d65ee15eba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Jun 2006 19:33:05 +0000 Subject: [PATCH 0923/1514] if S16NE is not supported, fall back to S16RE. If FLOAT32NE is not supported, fall back to FLOAT32NE. If still nothing is supported, try everything else in order git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1020 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 84 ++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 14 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 5b6d72e77..2ead58c83 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -247,15 +247,8 @@ int pa_alsa_fdlist_init_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_han return 0; } -/* Set the hardware parameters of the given ALSA device. Returns the - * selected fragment settings in *period and *period_size */ -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { - int ret = -1; - snd_pcm_uframes_t buffer_size; - snd_pcm_hw_params_t *hwparams = NULL; - unsigned int r = ss->rate; - unsigned int c = ss->channels; - +static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) { + static const snd_pcm_format_t format_trans[] = { [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8, [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW, @@ -265,15 +258,73 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE, [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE, }; - assert(pcm_handle && ss && periods && period_size); + + static const pa_sample_format_t try_order[] = { + PA_SAMPLE_S16NE, + PA_SAMPLE_S16RE, + PA_SAMPLE_FLOAT32NE, + PA_SAMPLE_FLOAT32RE, + PA_SAMPLE_ULAW, + PA_SAMPLE_ALAW, + PA_SAMPLE_U8, + PA_SAMPLE_INVALID + }; + + int i, ret; + + assert(pcm_handle); + assert(f); + + if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0) + return ret; + + if (*f == PA_SAMPLE_FLOAT32BE) + *f = PA_SAMPLE_FLOAT32LE; + else if (*f == PA_SAMPLE_FLOAT32LE) + *f = PA_SAMPLE_FLOAT32BE; + else if (*f == PA_SAMPLE_S16BE) + *f = PA_SAMPLE_S16LE; + else if (*f == PA_SAMPLE_S16LE) + *f = PA_SAMPLE_S16BE; + else + goto try_auto; + + if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0) + return ret; + +try_auto: + + for (i = 0; try_order[i] != PA_SAMPLE_INVALID; i++) { + *f = try_order[i]; + + if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0) + return ret; + } + + return -1; +} + +/* Set the hardware parameters of the given ALSA device. Returns the + * selected fragment settings in *period and *period_size */ +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { + int ret = -1; + snd_pcm_uframes_t buffer_size; + unsigned int r = ss->rate; + unsigned int c = ss->channels; + pa_sample_format_t f = ss->format; + snd_pcm_hw_params_t *hwparams; + + assert(pcm_handle); + assert(ss); + assert(periods); + assert(period_size); buffer_size = *periods * *period_size; if ((ret = snd_pcm_hw_params_malloc(&hwparams)) < 0 || (ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 || (ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0 || - (ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[ss->format])) < 0 || - (ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0 || + (ret = set_format(pcm_handle, hwparams, &f)) < 0 || (ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0 || (*period_size > 0 && (ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL)) < 0) || (*periods > 0 && (ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0) || @@ -281,7 +332,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p goto finish; if (ss->rate != r) { - pa_log_info(__FILE__": device doesn't support %u Hz, changed to %u Hz.", ss->rate, r); + pa_log_warn(__FILE__": device doesn't support %u Hz, changed to %u Hz.", ss->rate, r); /* If the sample rate deviates too much, we need to resample */ if (r < ss->rate*.95 || r > ss->rate*1.05) @@ -289,9 +340,14 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p } if (ss->channels != c) { - pa_log_info(__FILE__": device doesn't support %u channels, changed to %u.", ss->channels, c); + pa_log_warn(__FILE__": device doesn't support %u channels, changed to %u.", ss->channels, c); ss->channels = c; } + + if (ss->format != f) { + pa_log_warn(__FILE__": device doesn't support sample format %s, changed to %s.", pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f)); + ss->format = f; + } if ((ret = snd_pcm_prepare(pcm_handle)) < 0) goto finish; From 6684264b69a17ec907c903c6f9ca9b99dbd29be2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 16 Jun 2006 21:07:32 +0000 Subject: [PATCH 0924/1514] Record support. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1021 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 575 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 439 insertions(+), 136 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 4fe8205ee..b0e763272 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -52,7 +52,7 @@ typedef enum { FD_INFO_MIXER, - FD_INFO_PLAYBACK + FD_INFO_STREAM, } fd_info_type_t; typedef struct fd_info fd_info; @@ -71,16 +71,18 @@ struct fd_info { pa_threaded_mainloop *mainloop; pa_context *context; - pa_stream *stream; + pa_stream *play_stream; + pa_stream *rec_stream; pa_io_event *io_event; void *buf; + size_t rec_offset; int operation_success; - pa_cvolume volume; - uint32_t sink_index; + pa_cvolume sink_volume, source_volume; + uint32_t sink_index, source_index; int volume_modify_count; PA_LLIST_FIELDS(fd_info); @@ -181,9 +183,17 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ } \ } while(0); -#define STREAM_CHECK_DEAD_GOTO(i, label) do { \ +#define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ - !(i)->stream || pa_stream_get_state((i)->stream) != PA_STREAM_READY) { \ + !(i)->play_stream || pa_stream_get_state((i)->play_stream) != PA_STREAM_READY) { \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + goto label; \ +} \ +} while(0); + +#define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \ +if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ + !(i)->rec_stream || pa_stream_get_state((i)->rec_stream) != PA_STREAM_READY) { \ debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ @@ -301,9 +311,14 @@ static void fd_info_free(fd_info *i) { if (i->mainloop) pa_threaded_mainloop_stop(i->mainloop); - if (i->stream) { - pa_stream_disconnect(i->stream); - pa_stream_unref(i->stream); + if (i->play_stream) { + pa_stream_disconnect(i->play_stream); + pa_stream_unref(i->play_stream); + } + + if (i->rec_stream) { + pa_stream_disconnect(i->rec_stream); + pa_stream_unref(i->rec_stream); } if (i->context) { @@ -465,9 +480,14 @@ static void atfork_child(void) { i->context = NULL; } - if (i->stream) { - pa_stream_unref(i->stream); - i->stream = NULL; + if (i->play_stream) { + pa_stream_unref(i->play_stream); + i->play_stream = NULL; + } + + if (i->rec_stream) { + pa_stream_unref(i->rec_stream); + i->rec_stream = NULL; } if (i->app_fd >= 0) { @@ -534,15 +554,19 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { i->mainloop = NULL; i->context = NULL; - i->stream = NULL; + i->play_stream = NULL; + i->rec_stream = NULL; i->io_event = NULL; pthread_mutex_init(&i->mutex, NULL); i->ref = 1; i->buf = NULL; + i->rec_offset = 0; i->unusable = 0; - pa_cvolume_reset(&i->volume, 2); + pa_cvolume_reset(&i->sink_volume, 2); + pa_cvolume_reset(&i->source_volume, 2); i->volume_modify_count = 0; i->sink_index = (uint32_t) -1; + i->source_index = (uint32_t) -1; PA_LLIST_INIT(fd_info, i); reset_params(i); @@ -678,8 +702,36 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { if (i->io_event) { pa_mainloop_api *api; + pa_io_event_flags_t flags; + size_t n; + api = pa_threaded_mainloop_get_api(i->mainloop); - api->io_enable(i->io_event, PA_IO_EVENT_INPUT); + + flags = 0; + + if (s == i->play_stream) { + n = pa_stream_writable_size(i->play_stream); + if (n == (size_t)-1) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", + pa_strerror(pa_context_errno(i->context))); + } + + if (n >= i->fragment_size) + flags |= PA_IO_EVENT_INPUT; + } + + if (s == i->rec_stream) { + n = pa_stream_readable_size(i->rec_stream); + if (n == (size_t)-1) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n", + pa_strerror(pa_context_errno(i->context))); + } + + if (n >= i->fragment_size) + flags |= PA_IO_EVENT_OUTPUT; + } + + api->io_enable(i->io_event, flags); } } @@ -708,49 +760,114 @@ static void fd_info_shutdown(fd_info *i) { static int fd_info_copy_data(fd_info *i, int force) { size_t n; + pa_io_event_flags_t flags; - if (!i->stream) + if (!i->play_stream && !i->rec_stream) return -1; - if ((n = pa_stream_writable_size(i->stream)) == (size_t) -1) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); - return -1; - } - - while (n >= i->fragment_size || force) { - ssize_t r; - - if (!i->buf) { - if (!(i->buf = malloc(i->fragment_size))) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": malloc() failed.\n"); + flags = 0; + + if (i->play_stream) { + n = pa_stream_writable_size(i->play_stream); + + if (n == (size_t)-1) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", + pa_strerror(pa_context_errno(i->context))); + return -1; + } + + while (n >= i->fragment_size || force) { + ssize_t r; + + if (!i->buf) { + if (!(i->buf = malloc(i->fragment_size))) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": malloc() failed.\n"); + return -1; + } + } + + if ((r = read(i->thread_fd, i->buf, i->fragment_size)) <= 0) { + + if (errno == EAGAIN) + break; + + debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno)); return -1; } - } - - if ((r = read(i->thread_fd, i->buf, i->fragment_size)) <= 0) { - if (errno == EAGAIN) + if (pa_stream_write(i->play_stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); + return -1; + } + + i->buf = NULL; + + assert(n >= (size_t) r); + n -= r; + } + + if (n >= i->fragment_size) + flags |= PA_IO_EVENT_INPUT; + } + + if (i->rec_stream) { + n = pa_stream_readable_size(i->rec_stream); + + if (n == (size_t)-1) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n", + pa_strerror(pa_context_errno(i->context))); + return -1; + } + + while (n >= i->fragment_size || force) { + ssize_t r; + const void *data; + const char *buf; + size_t len; + + if (pa_stream_peek(i->rec_stream, &data, &len) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_peek(): %s\n", pa_strerror(pa_context_errno(i->context))); + return -1; + } + + if (!data) break; - - debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", r == 0 ? "EOF" : strerror(errno)); - return -1; - } - - if (pa_stream_write(i->stream, i->buf, r, free, 0, PA_SEEK_RELATIVE) < 0) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_write(): %s\n", pa_strerror(pa_context_errno(i->context))); - return -1; + + buf = (const char*)data + i->rec_offset; + + if ((r = write(i->thread_fd, buf, len - i->rec_offset)) <= 0) { + + if (errno == EAGAIN) + break; + + debug(DEBUG_LEVEL_NORMAL, __FILE__": write(): %s\n", strerror(errno)); + return -1; + } + + assert((size_t)r <= len - i->rec_offset); + i->rec_offset += r; + + if (i->rec_offset == len) { + if (pa_stream_drop(i->rec_stream) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drop(): %s\n", pa_strerror(pa_context_errno(i->context))); + return -1; + } + i->rec_offset = 0; + } + + assert(n >= (size_t) r); + n -= r; } - i->buf = NULL; - - assert(n >= (size_t) r); - n -= r; + if (n >= i->fragment_size) + flags |= PA_IO_EVENT_OUTPUT; } if (i->io_event) { pa_mainloop_api *api; + api = pa_threaded_mainloop_get_api(i->mainloop); - api->io_enable(i->io_event, n >= i->fragment_size ? PA_IO_EVENT_INPUT : 0); + api->io_enable(i->io_event, flags); } return 0; @@ -778,7 +895,7 @@ static void stream_state_cb(pa_stream *s, void * userdata) { } } -static int create_stream(fd_info *i) { +static int create_playback_stream(fd_info *i) { pa_buffer_attr attr; int n; @@ -786,14 +903,14 @@ static int create_stream(fd_info *i) { fix_metrics(i); - if (!(i->stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) { + if (!(i->play_stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } - pa_stream_set_state_callback(i->stream, stream_state_cb, i); - pa_stream_set_write_callback(i->stream, stream_request_cb, i); - pa_stream_set_latency_update_callback(i->stream, stream_latency_update_cb, i); + pa_stream_set_state_callback(i->play_stream, stream_state_cb, i); + pa_stream_set_write_callback(i->play_stream, stream_request_cb, i); + pa_stream_set_latency_update_callback(i->play_stream, stream_latency_update_cb, i); memset(&attr, 0, sizeof(attr)); attr.maxlength = i->fragment_size * (i->n_fragments+1); @@ -801,7 +918,7 @@ static int create_stream(fd_info *i) { attr.prebuf = i->fragment_size; attr.minreq = i->fragment_size; - if (pa_stream_connect_playback(i->stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { + if (pa_stream_connect_playback(i->play_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -817,13 +934,56 @@ fail: return -1; } -static void free_stream(fd_info *i) { +static int create_record_stream(fd_info *i) { + pa_buffer_attr attr; + int n; + assert(i); - if (i->stream) { - pa_stream_disconnect(i->stream); - pa_stream_unref(i->stream); - i->stream = NULL; + fix_metrics(i); + + if (!(i->rec_stream = pa_stream_new(i->context, stream_name(), &i->sample_spec, NULL))) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + pa_stream_set_state_callback(i->rec_stream, stream_state_cb, i); + pa_stream_set_read_callback(i->rec_stream, stream_request_cb, i); + pa_stream_set_latency_update_callback(i->rec_stream, stream_latency_update_cb, i); + + memset(&attr, 0, sizeof(attr)); + attr.maxlength = i->fragment_size * (i->n_fragments+1); + attr.fragsize = i->fragment_size; + + if (pa_stream_connect_record(i->rec_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + n = i->fragment_size; + setsockopt(i->app_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); + n = i->fragment_size; + setsockopt(i->thread_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)); + + return 0; + +fail: + return -1; +} + +static void free_streams(fd_info *i) { + assert(i); + + if (i->play_stream) { + pa_stream_disconnect(i->play_stream); + pa_stream_unref(i->play_stream); + i->play_stream = NULL; + } + + if (i->rec_stream) { + pa_stream_disconnect(i->rec_stream); + pa_stream_unref(i->rec_stream); + i->rec_stream = NULL; } } @@ -834,17 +994,24 @@ static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_even if (flags & PA_IO_EVENT_INPUT) { - if (!i->stream) { - api->io_enable(e, 0); - - if (create_stream(i) < 0) + if (!i->play_stream) { + if (create_playback_stream(i) < 0) goto fail; - } else { if (fd_info_copy_data(i, 0) < 0) goto fail; } + } else if (flags & PA_IO_EVENT_OUTPUT) { + + if (!i->rec_stream) { + if (create_record_stream(i) < 0) + goto fail; + } else { + if (fd_info_copy_data(i, 0) < 0) + goto fail; + } + } else if (flags & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) goto fail; @@ -860,20 +1027,12 @@ static int dsp_open(int flags, int *_errno) { pa_mainloop_api *api; int ret; int f; + pa_io_event_flags_t ioflags; debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open()\n"); - if ((flags != O_WRONLY) && (flags != (O_WRONLY|O_NONBLOCK))) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": bad access flags: %x\n", flags); - *_errno = EACCES; + if (!(i = fd_info_new(FD_INFO_STREAM, _errno))) return -1; - } - - if (!(i = fd_info_new(FD_INFO_PLAYBACK, _errno))) - return -1; - - shutdown(i->thread_fd, SHUT_WR); - shutdown(i->app_fd, SHUT_RD); if ((flags & O_NONBLOCK) == O_NONBLOCK) { if ((f = fcntl(i->app_fd, F_GETFL)) >= 0) @@ -887,7 +1046,26 @@ static int dsp_open(int flags, int *_errno) { pa_threaded_mainloop_lock(i->mainloop); api = pa_threaded_mainloop_get_api(i->mainloop); - if (!(i->io_event = api->io_new(api, i->thread_fd, PA_IO_EVENT_INPUT, io_event_cb, i))) + + switch (flags & O_ACCMODE) { + case O_RDONLY: + ioflags = PA_IO_EVENT_OUTPUT; + shutdown(i->thread_fd, SHUT_RD); + shutdown(i->app_fd, SHUT_WR); + break; + case O_WRONLY: + ioflags = PA_IO_EVENT_INPUT; + shutdown(i->thread_fd, SHUT_WR); + shutdown(i->app_fd, SHUT_RD); + break; + case O_RDWR: + ioflags = PA_IO_EVENT_INPUT | PA_IO_EVENT_OUTPUT; + break; + default: + return -1; + } + + if (!(i->io_event = api->io_new(api, i->thread_fd, ioflags, io_event_cb, i))) goto fail; pa_threaded_mainloop_unlock(i->mainloop); @@ -925,16 +1103,38 @@ static void sink_info_cb(pa_context *context, const pa_sink_info *si, int eol, v if (eol) return; - if (!pa_cvolume_equal(&i->volume, &si->volume)) + if (!pa_cvolume_equal(&i->sink_volume, &si->volume)) i->volume_modify_count++; - i->volume = si->volume; + i->sink_volume = si->volume; i->sink_index = si->index; i->operation_success = 1; pa_threaded_mainloop_signal(i->mainloop, 0); } +static void source_info_cb(pa_context *context, const pa_source_info *si, int eol, void *userdata) { + fd_info *i = userdata; + + if (!si && eol < 0) { + i->operation_success = 0; + pa_threaded_mainloop_signal(i->mainloop, 0); + return; + } + + if (eol) + return; + + if (!pa_cvolume_equal(&i->source_volume, &si->volume)) + i->volume_modify_count++; + + i->source_volume = si->volume; + i->source_index = si->index; + + i->operation_success = 1; + pa_threaded_mainloop_signal(i->mainloop, 0); +} + static void subscribe_cb(pa_context *context, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { fd_info *i = userdata; pa_operation *o = NULL; @@ -955,7 +1155,7 @@ static void subscribe_cb(pa_context *context, pa_subscription_event_type_t t, ui static int mixer_open(int flags, int *_errno) { fd_info *i; - pa_operation *o; + pa_operation *o = NULL; int ret; debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open()\n"); @@ -967,7 +1167,7 @@ static int mixer_open(int flags, int *_errno) { pa_context_set_subscribe_callback(i->context, subscribe_cb, i); - if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK, context_success_cb, i))) { + if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, context_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; @@ -979,6 +1179,9 @@ static int mixer_open(int flags, int *_errno) { CONTEXT_CHECK_DEAD_GOTO(i, fail); } + pa_operation_unref(o); + o = NULL; + if (!i->operation_success) { debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; @@ -987,7 +1190,6 @@ static int mixer_open(int flags, int *_errno) { /* Get sink info */ - pa_operation_unref(o); if (!(o = pa_context_get_sink_info_by_name(i->context, NULL, sink_info_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; @@ -1000,12 +1202,38 @@ static int mixer_open(int flags, int *_errno) { CONTEXT_CHECK_DEAD_GOTO(i, fail); } + pa_operation_unref(o); + o = NULL; + if (!i->operation_success) { debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get sink info: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; goto fail; } + /* Get source info */ + + if (!(o = pa_context_get_source_info_by_name(i->context, NULL, source_info_cb, i))) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get source info: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + + i->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(i->mainloop); + CONTEXT_CHECK_DEAD_GOTO(i, fail); + } + + pa_operation_unref(o); + o = NULL; + + if (!i->operation_success) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to get source info: %s", pa_strerror(pa_context_errno(i->context))); + *_errno = EIO; + goto fail; + } + pa_threaded_mainloop_unlock(i->mainloop); debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() succeeded, fd=%i\n", i->app_fd); @@ -1017,6 +1245,9 @@ static int mixer_open(int flags, int *_errno) { return ret; fail: + if (o) + pa_operation_unref(o); + pa_threaded_mainloop_unlock(i->mainloop); if (i) @@ -1143,20 +1374,24 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno case SOUND_MIXER_READ_DEVMASK : debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_DEVMASK\n"); - *(int*) argp = SOUND_MASK_PCM; + *(int*) argp = SOUND_MASK_PCM | SOUND_MASK_IGAIN; break; case SOUND_MIXER_READ_RECMASK : debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECMASK\n"); - *(int*) argp = 0; + *(int*) argp = SOUND_MASK_IGAIN; break; case SOUND_MIXER_READ_STEREODEVS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_STEREODEVS\n"); pa_threaded_mainloop_lock(i->mainloop); - *(int*) argp = i->volume.channels > 1 ? SOUND_MASK_PCM : 0; + *(int*) argp = 0; + if (i->sink_volume.channels > 1) + *(int*) argp |= SOUND_MASK_PCM; + if (i->source_volume.channels > 1) + *(int*) argp |= SOUND_MASK_IGAIN; pa_threaded_mainloop_unlock(i->mainloop); break; @@ -1164,9 +1399,13 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno case SOUND_MIXER_READ_RECSRC: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_RECSRC\n"); - *(int*) argp = 0; + *(int*) argp = SOUND_MASK_IGAIN; break; - + + case SOUND_MIXER_WRITE_RECSRC: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_RECSRC\n"); + break; + case SOUND_MIXER_READ_CAPS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_CAPS\n"); @@ -1174,35 +1413,61 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno break; case SOUND_MIXER_READ_PCM: - - debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_PCM\n"); - + case SOUND_MIXER_READ_IGAIN: { + pa_cvolume *v; + + if (request == SOUND_MIXER_READ_PCM) + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_PCM\n"); + else + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_IGAIN\n"); + pa_threaded_mainloop_lock(i->mainloop); + if (request == SOUND_MIXER_READ_PCM) + v = &i->sink_volume; + else + v = &i->source_volume; + *(int*) argp = - ((i->volume.values[0]*100/PA_VOLUME_NORM)) | - ((i->volume.values[i->volume.channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM) << 8); - - pa_threaded_mainloop_unlock(i->mainloop); - - break; + ((v->values[0]*100/PA_VOLUME_NORM)) | + ((v->values[v->channels > 1 ? 1 : 0]*100/PA_VOLUME_NORM) << 8); + + pa_threaded_mainloop_unlock(i->mainloop); + + break; + } + + case SOUND_MIXER_WRITE_PCM: + case SOUND_MIXER_WRITE_IGAIN: { + pa_cvolume v, *pv; + + if (request == SOUND_MIXER_READ_PCM) + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_PCM\n"); + else + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_IGAIN\n"); - case SOUND_MIXER_WRITE_PCM: { - pa_cvolume v; - - debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_PCM\n"); - pa_threaded_mainloop_lock(i->mainloop); - v = i->volume; - - i->volume.values[0] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100; - i->volume.values[1] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100; + if (request == SOUND_MIXER_READ_PCM) { + v = i->sink_volume; + pv = &i->sink_volume; + } else { + v = i->source_volume; + pv = &i->source_volume; + } - if (!pa_cvolume_equal(&i->volume, &v)) { + pv->values[0] = ((*(int*) argp & 0xFF)*PA_VOLUME_NORM)/100; + pv->values[1] = ((*(int*) argp >> 8)*PA_VOLUME_NORM)/100; + + if (!pa_cvolume_equal(pv, &v)) { pa_operation *o; - - if (!(o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, &i->volume, NULL, NULL))) + + if (request == SOUND_MIXER_READ_PCM) + o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, pv, NULL, NULL); + else + o = pa_context_set_source_volume_by_index(i->context, i->source_index, pv, NULL, NULL); + + if (!o) debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); else { @@ -1310,13 +1575,10 @@ static int map_format_back(pa_sample_format_t format) { } } -static int dsp_flush_socket(fd_info *i) { +static int dsp_flush_fd(int fd) { int l; - - if (i->thread_fd < 0) - return -1; - if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { + if (ioctl(fd, SIOCINQ, &l) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno)); return -1; } @@ -1326,7 +1588,7 @@ static int dsp_flush_socket(fd_info *i) { size_t k; k = (size_t) l > sizeof(buf) ? sizeof(buf) : (size_t) l; - if (read(i->thread_fd, buf, k) < 0) + if (read(fd, buf, k) < 0) debug(DEBUG_LEVEL_NORMAL, __FILE__": read(): %s\n", strerror(errno)); l -= k; } @@ -1334,6 +1596,27 @@ static int dsp_flush_socket(fd_info *i) { return 0; } +static int dsp_flush_socket(fd_info *i) { + int res = 0; + + if ((i->thread_fd < 0) && (i->app_fd < 0)) + return -1; + + if (i->thread_fd >= 0) + res = dsp_flush_fd(i->thread_fd); + + if (res < 0) + return res; + + if (i->app_fd >= 0) + res = dsp_flush_fd(i->app_fd); + + if (res < 0) + return res; + + return 0; +} + static int dsp_empty_socket(fd_info *i) { int ret = -1; @@ -1374,19 +1657,19 @@ static int dsp_drain(fd_info *i) { if (dsp_empty_socket(i) < 0) goto fail; - if (!i->stream) + if (!i->play_stream) goto fail; debug(DEBUG_LEVEL_NORMAL, __FILE__": Really draining.\n"); - if (!(o = pa_stream_drain(i->stream, stream_success_cb, i))) { + if (!(o = pa_stream_drain(i->play_stream, stream_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } i->operation_success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { - STREAM_CHECK_DEAD_GOTO(i, fail); + PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail); pa_threaded_mainloop_wait(i->mainloop); } @@ -1412,7 +1695,7 @@ static int dsp_trigger(fd_info *i) { pa_operation *o = NULL; int r = -1; - if (!i->stream) + if (!i->play_stream) return 0; pa_threaded_mainloop_lock(i->mainloop); @@ -1422,14 +1705,14 @@ static int dsp_trigger(fd_info *i) { debug(DEBUG_LEVEL_NORMAL, __FILE__": Triggering.\n"); - if (!(o = pa_stream_trigger(i->stream, stream_success_cb, i))) { + if (!(o = pa_stream_trigger(i->play_stream, stream_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } i->operation_success = 0; while (!pa_operation_get_state(o) != PA_OPERATION_DONE) { - STREAM_CHECK_DEAD_GOTO(i, fail); + PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail); pa_threaded_mainloop_wait(i->mainloop); } @@ -1464,7 +1747,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) *(int*) argp = map_format_back(i->sample_spec.format); else { map_format((int*) argp, &i->sample_spec); - free_stream(i); + free_streams(i); } pa_threaded_mainloop_unlock(i->mainloop); @@ -1485,7 +1768,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) if ((valid = pa_sample_spec_valid(&ss))) { i->sample_spec = ss; - free_stream(i); + free_streams(i); } debug(DEBUG_LEVEL_NORMAL, __FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); @@ -1506,7 +1789,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_lock(i->mainloop); i->sample_spec.channels = *(int*) argp ? 2 : 1; - free_stream(i); + free_streams(i); pa_threaded_mainloop_unlock(i->mainloop); return 0; @@ -1524,7 +1807,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) if ((valid = pa_sample_spec_valid(&ss))) { i->sample_spec = ss; - free_stream(i); + free_streams(i); } pa_threaded_mainloop_unlock(i->mainloop); @@ -1557,7 +1840,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) i->fragment_size = 1 << (*(int*) argp); i->n_fragments = (*(int*) argp) >> 16; - free_stream(i); + free_streams(i); pa_threaded_mainloop_unlock(i->mainloop); @@ -1566,7 +1849,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETCAPS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n"); - *(int*) argp = DSP_CAP_MULTI; + *(int*) argp = DSP_CAP_DUPLEX | DSP_CAP_MULTI; break; case SNDCTL_DSP_GETODELAY: { @@ -1581,9 +1864,9 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) for (;;) { pa_usec_t usec; - STREAM_CHECK_DEAD_GOTO(i, exit_loop); + PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, exit_loop); - if (pa_stream_get_latency(i->stream, &usec, NULL) >= 0) { + if (pa_stream_get_latency(i->play_stream, &usec, NULL) >= 0) { *(int*) argp = pa_usec_to_bytes(usec, &i->sample_spec); break; } @@ -1615,7 +1898,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_lock(i->mainloop); - free_stream(i); + free_streams(i); dsp_flush_socket(i); reset_params(i); @@ -1645,31 +1928,51 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; - case SNDCTL_DSP_GETOSPACE: { + case SNDCTL_DSP_GETOSPACE: + case SNDCTL_DSP_GETISPACE: { audio_buf_info *bi = (audio_buf_info*) argp; int l; size_t k = 0; - debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOSPACE\n"); + if (request == SNDCTL_DSP_GETOSPACE) + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOSPACE\n"); + else + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETISPACE\n"); pa_threaded_mainloop_lock(i->mainloop); fix_metrics(i); - - if (i->stream) { - if ((k = pa_stream_writable_size(i->stream)) == (size_t) -1) - debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); - } else - k = i->fragment_size * i->n_fragments; - - if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); - l = 0; + + if (request == SNDCTL_DSP_GETOSPACE) { + if (i->play_stream) { + if ((k = pa_stream_writable_size(i->play_stream)) == (size_t) -1) + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_writable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + } else + k = i->fragment_size * i->n_fragments; + + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); + l = 0; + } + + bi->bytes = k > (size_t) l ? k - l : 0; + } else { + if (i->rec_stream) { + if ((k = pa_stream_readable_size(i->rec_stream)) == (size_t) -1) + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_readable_size(): %s\n", pa_strerror(pa_context_errno(i->context))); + } else + k = 0; + + if (ioctl(i->app_fd, SIOCINQ, &l) < 0) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); + l = 0; + } + + bi->bytes = k + l; } bi->fragsize = i->fragment_size; bi->fragstotal = i->n_fragments; - bi->bytes = k > (size_t) l ? k - l : 0; bi->fragments = bi->bytes / bi->fragsize; pa_threaded_mainloop_unlock(i->mainloop); From e66b0e6d3f235a65913c17a549bed74fd414445a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 16 Jun 2006 21:08:35 +0000 Subject: [PATCH 0925/1514] Creating a stream might take some time, so check that it's in the right state before transferring data. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1022 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b0e763272..be935060e 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -767,7 +767,7 @@ static int fd_info_copy_data(fd_info *i, int force) { flags = 0; - if (i->play_stream) { + if ((i->play_stream) && (pa_stream_get_state(i->play_stream) == PA_STREAM_READY)) { n = pa_stream_writable_size(i->play_stream); if (n == (size_t)-1) { @@ -810,7 +810,7 @@ static int fd_info_copy_data(fd_info *i, int force) { flags |= PA_IO_EVENT_INPUT; } - if (i->rec_stream) { + if ((i->rec_stream) && (pa_stream_get_state(i->rec_stream) == PA_STREAM_READY)) { n = pa_stream_readable_size(i->rec_stream); if (n == (size_t)-1) { From 8485a477053f7ea9549a1ca588c32b5379ba2d36 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 16 Jun 2006 21:11:45 +0000 Subject: [PATCH 0926/1514] /dev/dsp should default to U8, not mulaw. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1023 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index be935060e..e25fdfd86 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -392,7 +392,7 @@ static void context_state_cb(pa_context *c, void *userdata) { static void reset_params(fd_info *i) { assert(i); - i->sample_spec.format = PA_SAMPLE_ULAW; + i->sample_spec.format = PA_SAMPLE_U8; i->sample_spec.channels = 1; i->sample_spec.rate = 8000; i->fragment_size = 0; From e26bd47282e679b384568f4dd916f13277b271fa Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jun 2006 23:36:03 +0000 Subject: [PATCH 0927/1514] * make hw param settings easier to debug by splitting up long if * actually set the sample rate * disable resampling done by ALSA git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1024 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 2ead58c83..fafcac489 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -323,12 +323,24 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p if ((ret = snd_pcm_hw_params_malloc(&hwparams)) < 0 || (ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 || - (ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0 || - (ret = set_format(pcm_handle, hwparams, &f)) < 0 || - (ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0 || - (*period_size > 0 && (ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL)) < 0) || - (*periods > 0 && (ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0) || - (ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) + (ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0 || + (ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) + goto finish; + + if ((ret = set_format(pcm_handle, hwparams, &f)) < 0) + goto finish; + + if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0) + goto finish; + + if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) + goto finish; + + if ((*period_size > 0 && (ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL)) < 0) || + (*periods > 0 && (ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)) + goto finish; + + if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) goto finish; if (ss->rate != r) { From 5e1127a2346857b93d66be15a29339ef3c572f7d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 17 Jun 2006 23:37:07 +0000 Subject: [PATCH 0928/1514] * implement volume adjusting and mixing for S16RE * some optimizations git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1025 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polypcore/sample-util.c | 86 +++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/src/polypcore/sample-util.c b/src/polypcore/sample-util.c index d06fa95fa..7a75ce1cf 100644 --- a/src/polypcore/sample-util.c +++ b/src/polypcore/sample-util.c @@ -33,6 +33,7 @@ #include #include "sample-util.h" +#include "endianmacros.h" pa_memblock *pa_silence_memblock_new(const pa_sample_spec *spec, size_t length, pa_memblock_stat*s) { assert(spec); @@ -138,6 +139,54 @@ size_t pa_mix( channel = 0; } } + + case PA_SAMPLE_S16RE:{ + size_t d; + unsigned channel = 0; + + for (d = 0;; d += sizeof(int16_t)) { + int32_t sum = 0; + + if (d >= length) + return d; + + if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { + unsigned i; + + for (i = 0; i < nstreams; i++) { + int32_t v; + pa_volume_t cvolume = streams[i].volume.values[channel]; + + if (d >= streams[i].chunk.length) + return d; + + if (cvolume == PA_VOLUME_MUTED) + v = 0; + else { + v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d))); + + if (cvolume != PA_VOLUME_NORM) + v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); + } + + sum += v; + } + + if (volume->values[channel] != PA_VOLUME_NORM) + sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); + + if (sum < -0x8000) sum = -0x8000; + if (sum > 0x7FFF) sum = 0x7FFF; + + } + + *((int16_t*) data) = INT16_SWAP(sum); + data = (uint8_t*) data + sizeof(int16_t); + + if (++channel >= spec->channels) + channel = 0; + } + } case PA_SAMPLE_U8: { size_t d; @@ -232,6 +281,7 @@ size_t pa_mix( } default: + pa_log_error(__FILE__": ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); abort(); } } @@ -253,12 +303,16 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol case PA_SAMPLE_S16NE: { int16_t *d; size_t n; - unsigned channel = 0; + unsigned channel; + double linear[PA_CHANNELS_MAX]; + + for (channel = 0; channel < spec->channels; channel++) + linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); - for (d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t = (int32_t)(*d); - t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel])); + t = (int32_t) (t * linear[channel]); if (t < -0x8000) t = -0x8000; if (t > 0x7FFF) t = 0x7FFF; @@ -270,6 +324,32 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol } break; } + + case PA_SAMPLE_S16RE: { + int16_t *d; + size_t n; + unsigned channel; + double linear[PA_CHANNELS_MAX]; + + for (channel = 0; channel < spec->channels; channel++) + linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); + + for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + int32_t t = (int32_t)(INT16_SWAP(*d)); + + t = (int32_t) (t * linear[channel]); + + if (t < -0x8000) t = -0x8000; + if (t > 0x7FFF) t = 0x7FFF; + + *d = INT16_SWAP((int16_t) t); + + if (++channel >= spec->channels) + channel = 0; + } + + break; + } case PA_SAMPLE_U8: { uint8_t *d; From bd432f0590bdda2c42887f1d6da07ff0bb571013 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 18 Jun 2006 11:10:45 +0000 Subject: [PATCH 0929/1514] * add new argument 'exit_on_eof' to module-cli and make use of it if "-C" is passed to the daemon git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1026 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/modules.html.in | 4 ++- doc/todo | 1 - src/daemon/cmdline.c | 2 +- src/modules/module-cli.c | 58 ++++++++++++++++++++++++++++++++-------- 4 files changed, 51 insertions(+), 14 deletions(-) diff --git a/doc/modules.html.in b/doc/modules.html.in index af6b6de61..85479523f 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -193,7 +193,9 @@ once.

      For an explanation of the simple command line language used by this module see cli.html. -

      This module doesn't accept any arguments.

      + + +
      exit_on_eof=Accepts a binary numerical argument specifying whether the daemon shuld exit after an EOF was recieved from STDIN (default: 0)
      diff --git a/doc/todo b/doc/todo index 7b83ea984..1ea40d3e1 100644 --- a/doc/todo +++ b/doc/todo @@ -35,7 +35,6 @@ Post 0.9.0: - check if using prctl(PR_GET_NAME) makes sense in pa_get_binary_name() - gconf module + frontend - hooks for creating sink inputs -- module-cli argument exit-on-eof Long term: - pass meta info for hearing impaired diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index 21fd5a257..b71be2e67 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -186,7 +186,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d break; case 'C': - pa_strbuf_puts(buf, "load-module module-cli\n"); + pa_strbuf_puts(buf, "load-module module-cli exit_on_eof=1\n"); break; case ARG_DAEMONIZE: diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c index 41e33c7f0..ce50a46bb 100644 --- a/src/modules/module-cli.c +++ b/src/modules/module-cli.c @@ -32,38 +32,64 @@ #include #include #include +#include #include "module-cli-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("Command line interface") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("No arguments") +PA_MODULE_USAGE("exit_on_eof=") -static void eof_cb(pa_cli*c, void *userdata) { +static const char* const valid_modargs[] = { + "exit_on_eof", + NULL +}; + +static void eof_and_unload_cb(pa_cli*c, void *userdata) { pa_module *m = userdata; - assert(c && m); + + assert(c); + assert(m); pa_module_unload_request(m); } +static void eof_and_exit_cb(pa_cli*c, void *userdata) { + pa_module *m = userdata; + + assert(c); + assert(m); + + m->core->mainloop->quit(m->core->mainloop, 0); +} + int pa__init(pa_core *c, pa_module*m) { pa_iochannel *io; - assert(c && m); + pa_modargs *ma; + int exit_on_eof = 0; + + assert(c); + assert(m); if (c->running_as_daemon) { - pa_log_info(__FILE__": Running as daemon so won't load this module."); + pa_log_info(__FILE__": Running as daemon, refusing to load this module."); return 0; } - if (m->argument) { - pa_log(__FILE__": module doesn't accept arguments."); - return -1; + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": failed to parse module arguments."); + goto fail; } + if (pa_modargs_get_value_boolean(ma, "exit_on_eof", &exit_on_eof) < 0) { + pa_log(__FILE__": exit_on_eof= expects boolean argument."); + goto fail; + } + if (pa_stdio_acquire() < 0) { pa_log(__FILE__": STDIN/STDUSE already in use."); - return -1; + goto fail; } io = pa_iochannel_new(c->mainloop, STDIN_FILENO, STDOUT_FILENO); @@ -73,13 +99,23 @@ int pa__init(pa_core *c, pa_module*m) { m->userdata = pa_cli_new(c, io, m); assert(m->userdata); - pa_cli_set_eof_callback(m->userdata, eof_cb, m); + pa_cli_set_eof_callback(m->userdata, exit_on_eof ? eof_and_exit_cb : eof_and_unload_cb, m); + + pa_modargs_free(ma); return 0; + +fail: + + if (ma) + pa_modargs_free(ma); + + return -1; } void pa__done(pa_core *c, pa_module*m) { - assert(c && m); + assert(c); + assert(m); if (c->running_as_daemon == 0) { pa_cli_free(m->userdata); From 9f59b4e1cd516dbbc8a4978146bc94f2a1ce75eb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 11:27:00 +0000 Subject: [PATCH 0930/1514] add new test "interpol-test" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1027 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 ++ src/tests/interpol-test.c | 168 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 src/tests/interpol-test.c diff --git a/src/Makefile.am b/src/Makefile.am index 2dc2c6639..6a2decb3d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -189,6 +189,7 @@ noinst_PROGRAMS = \ voltest \ memblockq-test \ sync-playback \ + interpol-test \ channelmap-test \ thread-mainloop-test \ utf8-test @@ -284,6 +285,11 @@ sync_playback_LDADD = $(AM_LDADD) libpolyp.la sync_playback_CFLAGS = $(AM_CFLAGS) sync_playback_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +interpol_test_SOURCES = tests/interpol-test.c +interpol_test_LDADD = $(AM_LDADD) libpolyp.la +interpol_test_CFLAGS = $(AM_CFLAGS) +interpol_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + ################################### # Client library # ################################### diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c new file mode 100644 index 000000000..26a92dbf0 --- /dev/null +++ b/src/tests/interpol-test.c @@ -0,0 +1,168 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static pa_context *context = NULL; +static pa_stream *stream = NULL; +static pa_mainloop_api *mainloop_api = NULL; + +static void stream_write_cb(pa_stream *p, size_t length, void *userdata) { + + /* Just some silence */ + pa_stream_write(p, pa_xmalloc0(length), length, pa_xfree, 0, PA_SEEK_RELATIVE); +} + +/* This is called whenever the context status changes */ +static void context_state_callback(pa_context *c, void *userdata) { + assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: { + + static const pa_sample_spec ss = { + .format = PA_SAMPLE_S16LE, + .rate = 44100, + .channels = 1 + }; + + fprintf(stderr, "Connection established.\n"); + + stream = pa_stream_new(c, "interpol-test", &ss, NULL); + assert(stream); + + pa_stream_connect_playback(stream, NULL, NULL, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL); + pa_stream_set_write_callback(stream, stream_write_cb, NULL); + + break; + } + + case PA_CONTEXT_TERMINATED: + break; + + case PA_CONTEXT_FAILED: + default: + fprintf(stderr, "Context error: %s\n", pa_strerror(pa_context_errno(c))); + abort(); + } +} + +int main(int argc, char *argv[]) { + pa_threaded_mainloop* m = NULL; + int k, r; + struct timeval start, last_info = { 0, 0 }; + pa_usec_t old_t = 0, old_rtc = 0; + + /* Set up a new main loop */ + m = pa_threaded_mainloop_new(); + assert(m); + + mainloop_api = pa_threaded_mainloop_get_api(m); + + context = pa_context_new(mainloop_api, argv[0]); + assert(context); + + pa_context_set_state_callback(context, context_state_callback, NULL); + + r = pa_context_connect(context, NULL, 0, NULL); + assert(r >= 0); + + pa_gettimeofday(&start); + + pa_threaded_mainloop_start(m); + + for (k = 0; k < 5000; k++) { + int success = 0, changed = 0; + pa_usec_t t, rtc; + struct timeval now, tv; + + pa_threaded_mainloop_lock(m); + + if (stream) { + const pa_timing_info *info; + + if (pa_stream_get_time(stream, &t) >= 0) + success = 1; + + if ((info = pa_stream_get_timing_info(stream))) + if (last_info.tv_usec != info->timestamp.tv_usec || last_info.tv_sec != info->timestamp.tv_sec) { + changed = 1; + last_info = info->timestamp; + } + } + + pa_threaded_mainloop_unlock(m); + + if (success) { + pa_gettimeofday(&now); + + rtc = pa_timeval_diff(&now, &start); + printf("%i\t%llu\t%llu\t%llu\t%llu\t%u\n", k, rtc, t, rtc-old_rtc, t-old_t, changed*2000000); + old_t = t; + old_rtc = rtc; + } + + /* Spin loop, eerks but normal usleep is just to badly grained */ + + tv = now; + while (pa_timeval_diff(pa_gettimeofday(&now), &tv) < 1000) + pthread_yield(); + } + + if (m) + pa_threaded_mainloop_stop(m); + + if (stream) { + pa_stream_disconnect(stream); + pa_stream_unref(stream); + } + + if (context) { + pa_context_disconnect(context); + pa_context_unref(context); + } + + if (m) + pa_threaded_mainloop_free(m); + + return 0; +} From 6eabab6e2b093933bf489e6c94b13433d03584d2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 12:20:10 +0000 Subject: [PATCH 0931/1514] minor cleanups git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1028 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/interpol-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c index 26a92dbf0..fa5fae7d8 100644 --- a/src/tests/interpol-test.c +++ b/src/tests/interpol-test.c @@ -136,12 +136,12 @@ int main(int argc, char *argv[]) { pa_gettimeofday(&now); rtc = pa_timeval_diff(&now, &start); - printf("%i\t%llu\t%llu\t%llu\t%llu\t%u\n", k, rtc, t, rtc-old_rtc, t-old_t, changed*2000000); + printf("%i\t%llu\t%llu\t%llu\t%llu\t%u\n", k, rtc, t, rtc-old_rtc, t-old_t, changed); old_t = t; old_rtc = rtc; } - /* Spin loop, eerks but normal usleep is just to badly grained */ + /* Spin loop, ugly but normal usleep() is just too badly grained */ tv = now; while (pa_timeval_diff(pa_gettimeofday(&now), &tv) < 1000) From 40494c3bc1f109b0d0d2e9e04cda814e9856ff1f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 12:37:43 +0000 Subject: [PATCH 0932/1514] * rework latency interpolation to make it smoother * increase latency update interval to 100ms git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1029 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/internal.h | 5 ++--- src/polyp/stream.c | 26 ++++++++++---------------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 80c286164..e659553d8 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -136,9 +136,8 @@ struct pa_stream { pa_time_event *auto_timing_update_event; int auto_timing_update_requested; - pa_usec_t ipol_usec; - int ipol_usec_valid; - struct timeval ipol_timestamp; + pa_usec_t cached_time; + int cached_time_valid; /* Callbacks */ pa_stream_notify_cb_t state_callback; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index e3f40a3f3..8927805ed 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -38,7 +38,7 @@ #include "internal.h" -#define LATENCY_IPOL_INTERVAL_USEC (10000L) +#define LATENCY_IPOL_INTERVAL_USEC (100000L) pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) { pa_stream *s; @@ -102,9 +102,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->corked = 0; - s->ipol_usec_valid = 0; - s->ipol_timestamp.tv_sec = 0; - s->ipol_timestamp.tv_usec = 0; + s->cached_time_valid = 0; s->auto_timing_update_event = NULL; s->auto_timing_update_requested = 0; @@ -367,7 +365,7 @@ static void invalidate_indexes(pa_stream *s, int r, int w) { if ((s->direction == PA_STREAM_PLAYBACK && r) || (s->direction == PA_STREAM_RECORD && w)) - s->ipol_usec_valid = 0; + s->cached_time_valid = 0; request_auto_timing_update(s, 1); } @@ -855,8 +853,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, i->read_index -= pa_memblockq_get_length(o->stream->record_memblockq); } - o->stream->ipol_timestamp = now; - o->stream->ipol_usec_valid = 0; + o->stream->cached_time_valid = 0; } o->stream->auto_timing_update_requested = 0; @@ -1203,8 +1200,9 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->timing_info.read_index_corrupt, PA_ERR_NODATA); PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_RECORD || !s->timing_info.write_index_corrupt, PA_ERR_NODATA); - if (s->flags & PA_STREAM_INTERPOLATE_TIMING && s->ipol_usec_valid) - usec = s->ipol_usec; + if (s->cached_time_valid) + /* We alredy calculated the time value for this timing info, so let's reuse it */ + usec = s->cached_time; else { if (s->direction == PA_STREAM_PLAYBACK) { /* The last byte that was written into the output device @@ -1247,10 +1245,8 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { } } - if (s->flags & PA_STREAM_INTERPOLATE_TIMING) { - s->ipol_usec = usec; - s->ipol_usec_valid = 1; - } + s->cached_time = usec; + s->cached_time_valid = 1; } /* Interpolate if requested */ @@ -1260,9 +1256,7 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { * current */ if (!s->corked) { struct timeval now; - - usec += pa_timeval_diff(pa_gettimeofday(&now), &s->ipol_timestamp); - s->ipol_timestamp = now; + usec += pa_timeval_diff(pa_gettimeofday(&now), &s->timing_info.timestamp); } } From c6d4cc0af9497a4376fa1dcb33a28c9a54264109 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 19 Jun 2006 16:39:28 +0000 Subject: [PATCH 0933/1514] Handle clients that just want to set fragment size (and not count). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1030 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index e25fdfd86..56acbb28e 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1839,7 +1839,11 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) i->fragment_size = 1 << (*(int*) argp); i->n_fragments = (*(int*) argp) >> 16; - + + /* 0x7FFF means that we can set whatever we like */ + if (i->n_fragments == 0x7FFF) + i->n_fragments = 12; + free_streams(i); pa_threaded_mainloop_unlock(i->mainloop); From f6d1154c4f69d6290872e5f4c5ad26a22328c116 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 20:58:26 +0000 Subject: [PATCH 0934/1514] hide interpol-test git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1031 fefdeb5f-60dc-0310-8127-8f9354f1896f From dd21f11deda64e65a6f75817496534c2c9dda1a8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 21:00:45 +0000 Subject: [PATCH 0935/1514] unhide padsp git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1032 fefdeb5f-60dc-0310-8127-8f9354f1896f From f44ba092651aa75055e109e04b4164ea92ae7fdc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 21:53:48 +0000 Subject: [PATCH 0936/1514] big s/polyp/pulse/g git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1033 fefdeb5f-60dc-0310-8127-8f9354f1896f --- LICENSE | 8 +- Makefile.am | 29 +- bootstrap.sh | 8 +- configure.ac | 28 +- doc/FAQ.html.in | 52 +- doc/Makefile.am | 8 +- doc/README.html.in | 108 +-- doc/cli.html.in | 6 +- doc/daemon.html.in | 8 +- doc/modules.html.in | 28 +- doc/style.css | 8 +- doxygen/Makefile.am | 8 +- doxygen/doxygen.conf.in | 4 +- ...plib-browse.pc.in => libpulse-browse.pc.in | 8 +- ...loop.pc.in => libpulse-glib-mainloop.pc.in | 8 +- ...op.pc.in => libpulse-glib12-mainloop.pc.in | 8 +- ...plib-simple.pc.in => libpulse-simple.pc.in | 8 +- polyplib.pc.in => libpulse.pc.in | 6 +- src/Makefile.am | 790 +++++++++--------- src/daemon/Makefile | 2 +- src/daemon/caps.c | 12 +- src/daemon/caps.h | 8 +- src/daemon/cmdline.c | 14 +- src/daemon/cmdline.h | 8 +- src/daemon/cpulimit.c | 16 +- src/daemon/cpulimit.h | 12 +- src/daemon/daemon-conf.c | 26 +- src/daemon/daemon-conf.h | 10 +- src/daemon/daemon.conf.in | 16 +- src/daemon/default.pa.in | 8 +- src/daemon/default.pa.win32 | 8 +- src/daemon/dumpmodules.c | 12 +- src/daemon/dumpmodules.h | 8 +- src/daemon/esdcompat.in | 8 +- src/daemon/main.c | 42 +- src/depmod.py | 8 +- src/modules/Makefile | 2 +- src/modules/alsa-util.c | 14 +- src/modules/alsa-util.h | 14 +- src/modules/howl-wrap.c | 14 +- src/modules/howl-wrap.h | 10 +- src/modules/module-alsa-sink.c | 26 +- src/modules/module-alsa-source.c | 28 +- src/modules/module-cli.c | 20 +- src/modules/module-combine.c | 30 +- src/modules/module-defs.h.m4 | 4 +- src/modules/module-detect.c | 20 +- src/modules/module-esound-compat-spawnfd.c | 18 +- src/modules/module-esound-compat-spawnpid.c | 18 +- src/modules/module-esound-sink.c | 30 +- src/modules/module-jack-sink.c | 28 +- src/modules/module-jack-source.c | 28 +- src/modules/module-lirc.c | 22 +- src/modules/module-match.c | 30 +- src/modules/module-mmkbd-evdev.c | 24 +- src/modules/module-native-protocol-fd.c | 18 +- src/modules/module-null-sink.c | 24 +- src/modules/module-oss-mmap.c | 28 +- src/modules/module-oss.c | 28 +- src/modules/module-pipe-sink.c | 24 +- src/modules/module-pipe-source.c | 24 +- src/modules/module-protocol-stub.c | 48 +- src/modules/module-sine.c | 20 +- src/modules/module-solaris.c | 30 +- src/modules/module-tunnel.c | 42 +- src/modules/module-volume-restore.c | 30 +- src/modules/module-waveout.c | 26 +- src/modules/module-x11-bell.c | 24 +- src/modules/module-x11-publish.c | 40 +- src/modules/module-zeroconf-publish.c | 38 +- src/modules/oss-util.c | 14 +- src/modules/oss-util.h | 12 +- src/modules/rtp/module-rtp-recv.c | 34 +- src/modules/rtp/module-rtp-send.c | 34 +- src/modules/rtp/rtp.c | 12 +- src/modules/rtp/rtp.h | 12 +- src/modules/rtp/sap.c | 16 +- src/modules/rtp/sap.h | 12 +- src/modules/rtp/sdp.c | 14 +- src/modules/rtp/sdp.h | 10 +- src/polypcore/Makefile | 1 - src/{polyp => pulse}/Makefile | 0 src/{polyp => pulse}/browser.c | 20 +- src/{polyp => pulse}/browser.h | 16 +- src/{polyp => pulse}/cdecl.h | 8 +- src/{polyp => pulse}/channelmap.c | 12 +- src/{polyp => pulse}/channelmap.h | 12 +- src/{polyp => pulse}/client-conf-x11.c | 16 +- src/{polyp => pulse}/client-conf-x11.h | 8 +- src/{polyp => pulse}/client-conf.c | 24 +- src/{polyp => pulse}/client-conf.h | 12 +- src/{polyp => pulse}/client.conf.in | 14 +- src/{polyp => pulse}/context.c | 34 +- src/{polyp => pulse}/context.h | 30 +- src/{polyp => pulse}/def.h | 14 +- src/{polyp => pulse}/error.c | 14 +- src/{polyp => pulse}/error.h | 10 +- src/{polyp => pulse}/glib-mainloop.c | 16 +- src/{polyp => pulse}/glib-mainloop.h | 12 +- src/{polyp => pulse}/glib12-mainloop.c | 16 +- src/{polyp => pulse}/internal.h | 38 +- src/{polyp => pulse}/introspect.c | 14 +- src/{polyp => pulse}/introspect.h | 22 +- src/{polyp => pulse}/mainloop-api.c | 12 +- src/{polyp => pulse}/mainloop-api.h | 18 +- src/{polyp => pulse}/mainloop-signal.c | 18 +- src/{polyp => pulse}/mainloop-signal.h | 12 +- src/{polyp => pulse}/mainloop.c | 26 +- src/{polyp => pulse}/mainloop.h | 12 +- src/{polyp => pulse}/operation.c | 10 +- src/{polyp => pulse}/operation.h | 12 +- src/{polyp => pulse}/polypaudio.h | 70 +- src/{polyp => pulse}/sample.c | 8 +- src/{polyp => pulse}/sample.h | 10 +- src/{polyp => pulse}/scache.c | 10 +- src/{polyp => pulse}/scache.h | 14 +- src/{polyp => pulse}/simple.c | 18 +- src/{polyp => pulse}/simple.h | 16 +- src/{polyp => pulse}/stream.c | 20 +- src/{polyp => pulse}/stream.h | 20 +- src/{polyp => pulse}/subscribe.c | 12 +- src/{polyp => pulse}/subscribe.h | 14 +- src/{polyp => pulse}/thread-mainloop.c | 16 +- src/{polyp => pulse}/thread-mainloop.h | 12 +- src/{polyp => pulse}/timeval.c | 10 +- src/{polyp => pulse}/timeval.h | 12 +- src/{polyp => pulse}/utf8.c | 0 src/{polyp => pulse}/utf8.h | 10 +- src/{polyp => pulse}/util.c | 16 +- src/{polyp => pulse}/util.h | 10 +- src/{polyp => pulse}/version.h.in | 14 +- src/{polyp => pulse}/volume.c | 8 +- src/{polyp => pulse}/volume.h | 12 +- src/{polyp => pulse}/xmalloc.c | 12 +- src/{polyp => pulse}/xmalloc.h | 10 +- src/pulsecore/Makefile | 1 + src/{polypcore => pulsecore}/authkey-prop.c | 14 +- src/{polypcore => pulsecore}/authkey-prop.h | 10 +- src/{polypcore => pulsecore}/authkey.c | 18 +- src/{polypcore => pulsecore}/authkey.h | 8 +- src/{polypcore => pulsecore}/autoload.c | 22 +- src/{polypcore => pulsecore}/autoload.h | 10 +- src/{polypcore => pulsecore}/cli-command.c | 48 +- src/{polypcore => pulsecore}/cli-command.h | 12 +- src/{polypcore => pulsecore}/cli-text.c | 32 +- src/{polypcore => pulsecore}/cli-text.h | 10 +- src/{polypcore => pulsecore}/cli.c | 38 +- src/{polypcore => pulsecore}/cli.h | 14 +- src/{polypcore => pulsecore}/client.c | 14 +- src/{polypcore => pulsecore}/client.h | 12 +- src/{polypcore => pulsecore}/conf-parser.c | 16 +- src/{polypcore => pulsecore}/conf-parser.h | 8 +- src/{polypcore => pulsecore}/core-def.h | 8 +- src/{polypcore => pulsecore}/core-error.c | 18 +- src/{polypcore => pulsecore}/core-error.h | 10 +- src/{polypcore => pulsecore}/core-scache.c | 38 +- src/{polypcore => pulsecore}/core-scache.h | 14 +- src/{polypcore => pulsecore}/core-subscribe.c | 14 +- src/{polypcore => pulsecore}/core-subscribe.h | 12 +- src/{polypcore => pulsecore}/core-util.c | 24 +- src/{polypcore => pulsecore}/core-util.h | 10 +- src/{polypcore => pulsecore}/core.c | 32 +- src/{polypcore => pulsecore}/core.h | 28 +- src/{polypcore => pulsecore}/dllmain.c | 8 +- src/{polypcore => pulsecore}/dynarray.c | 10 +- src/{polypcore => pulsecore}/dynarray.h | 8 +- src/{polypcore => pulsecore}/endianmacros.h | 8 +- src/{polypcore => pulsecore}/esound.h | 8 +- src/{polypcore => pulsecore}/g711.c | 0 src/{polypcore => pulsecore}/g711.h | 0 src/{polypcore => pulsecore}/gccmacro.h | 8 +- src/{polypcore => pulsecore}/hashmap.c | 14 +- src/{polypcore => pulsecore}/hashmap.h | 8 +- src/{polypcore => pulsecore}/idxset.c | 10 +- src/{polypcore => pulsecore}/idxset.h | 8 +- src/{polypcore => pulsecore}/inet_ntop.c | 8 +- src/{polypcore => pulsecore}/inet_ntop.h | 0 src/{polypcore => pulsecore}/inet_pton.c | 8 +- src/{polypcore => pulsecore}/inet_pton.h | 0 src/{polypcore => pulsecore}/iochannel.c | 18 +- src/{polypcore => pulsecore}/iochannel.h | 10 +- src/{polypcore => pulsecore}/ioline.c | 14 +- src/{polypcore => pulsecore}/ioline.h | 12 +- src/{polypcore => pulsecore}/llist.h | 8 +- src/{polypcore => pulsecore}/log.c | 14 +- src/{polypcore => pulsecore}/log.h | 10 +- src/{polypcore => pulsecore}/mcalign.c | 10 +- src/{polypcore => pulsecore}/mcalign.h | 12 +- src/{polypcore => pulsecore}/memblock.c | 10 +- src/{polypcore => pulsecore}/memblock.h | 8 +- src/{polypcore => pulsecore}/memblockq.c | 14 +- src/{polypcore => pulsecore}/memblockq.h | 14 +- src/{polypcore => pulsecore}/memchunk.c | 10 +- src/{polypcore => pulsecore}/memchunk.h | 10 +- src/{polypcore => pulsecore}/modargs.c | 24 +- src/{polypcore => pulsecore}/modargs.h | 14 +- src/{polypcore => pulsecore}/modinfo.c | 14 +- src/{polypcore => pulsecore}/modinfo.h | 8 +- src/{polypcore => pulsecore}/module.c | 18 +- src/{polypcore => pulsecore}/module.h | 12 +- src/{polypcore => pulsecore}/namereg.c | 20 +- src/{polypcore => pulsecore}/namereg.h | 10 +- src/{polypcore => pulsecore}/native-common.h | 14 +- src/{polypcore => pulsecore}/packet.c | 10 +- src/{polypcore => pulsecore}/packet.h | 8 +- src/{polypcore => pulsecore}/parseaddr.c | 14 +- src/{polypcore => pulsecore}/parseaddr.h | 8 +- src/{polypcore => pulsecore}/pdispatch.c | 20 +- src/{polypcore => pulsecore}/pdispatch.h | 16 +- src/{polypcore => pulsecore}/pid.c | 16 +- src/{polypcore => pulsecore}/pid.h | 8 +- src/{polypcore => pulsecore}/pipe.c | 8 +- src/{polypcore => pulsecore}/pipe.h | 8 +- src/{polypcore => pulsecore}/play-memchunk.c | 14 +- src/{polypcore => pulsecore}/play-memchunk.h | 12 +- src/{polypcore => pulsecore}/poll.c | 10 +- src/{polypcore => pulsecore}/poll.h | 8 +- src/{polypcore => pulsecore}/props.c | 12 +- src/{polypcore => pulsecore}/props.h | 12 +- src/{polypcore => pulsecore}/protocol-cli.c | 14 +- src/{polypcore => pulsecore}/protocol-cli.h | 16 +- .../protocol-esound.c | 44 +- .../protocol-esound.h | 16 +- src/{polypcore => pulsecore}/protocol-http.c | 20 +- src/{polypcore => pulsecore}/protocol-http.h | 16 +- .../protocol-native.c | 58 +- .../protocol-native.h | 16 +- .../protocol-simple.c | 24 +- .../protocol-simple.h | 16 +- src/{polypcore => pulsecore}/pstream-util.c | 10 +- src/{polypcore => pulsecore}/pstream-util.h | 12 +- src/{polypcore => pulsecore}/pstream.c | 16 +- src/{polypcore => pulsecore}/pstream.h | 20 +- src/{polypcore => pulsecore}/queue.c | 10 +- src/{polypcore => pulsecore}/queue.h | 8 +- src/{polypcore => pulsecore}/random.c | 12 +- src/{polypcore => pulsecore}/random.h | 8 +- src/{polypcore => pulsecore}/resampler.c | 14 +- src/{polypcore => pulsecore}/resampler.h | 16 +- src/{polypcore => pulsecore}/sample-util.c | 10 +- src/{polypcore => pulsecore}/sample-util.h | 16 +- src/{polypcore => pulsecore}/sconv-s16be.c | 8 +- src/{polypcore => pulsecore}/sconv-s16be.h | 8 +- src/{polypcore => pulsecore}/sconv-s16le.c | 12 +- src/{polypcore => pulsecore}/sconv-s16le.h | 8 +- src/{polypcore => pulsecore}/sconv.c | 10 +- src/{polypcore => pulsecore}/sconv.h | 10 +- src/{polypcore => pulsecore}/sink-input.c | 18 +- src/{polypcore => pulsecore}/sink-input.h | 20 +- src/{polypcore => pulsecore}/sink.c | 26 +- src/{polypcore => pulsecore}/sink.h | 24 +- src/{polypcore => pulsecore}/sioman.c | 8 +- src/{polypcore => pulsecore}/sioman.h | 8 +- src/{polypcore => pulsecore}/socket-client.c | 22 +- src/{polypcore => pulsecore}/socket-client.h | 12 +- src/{polypcore => pulsecore}/socket-server.c | 20 +- src/{polypcore => pulsecore}/socket-server.h | 12 +- src/{polypcore => pulsecore}/socket-util.c | 16 +- src/{polypcore => pulsecore}/socket-util.h | 8 +- .../sound-file-stream.c | 14 +- .../sound-file-stream.h | 10 +- src/{polypcore => pulsecore}/sound-file.c | 12 +- src/{polypcore => pulsecore}/sound-file.h | 14 +- src/{polypcore => pulsecore}/source-output.c | 16 +- src/{polypcore => pulsecore}/source-output.h | 20 +- src/{polypcore => pulsecore}/source.c | 22 +- src/{polypcore => pulsecore}/source.h | 28 +- src/{polypcore => pulsecore}/strbuf.c | 10 +- src/{polypcore => pulsecore}/strbuf.h | 10 +- src/{polypcore => pulsecore}/strlist.c | 14 +- src/{polypcore => pulsecore}/strlist.h | 8 +- src/{polypcore => pulsecore}/tagstruct.c | 10 +- src/{polypcore => pulsecore}/tagstruct.h | 14 +- src/{polypcore => pulsecore}/tokenizer.c | 14 +- src/{polypcore => pulsecore}/tokenizer.h | 8 +- src/{polypcore => pulsecore}/winsock.h | 0 src/{polypcore => pulsecore}/x11prop.c | 8 +- src/{polypcore => pulsecore}/x11prop.h | 8 +- src/{polypcore => pulsecore}/x11wrap.c | 16 +- src/{polypcore => pulsecore}/x11wrap.h | 10 +- src/tests/Makefile | 2 +- src/tests/channelmap-test.c | 4 +- src/tests/cpulimit-test.c | 14 +- src/tests/interpol-test.c | 12 +- src/tests/mainloop-test.c | 18 +- src/tests/mcalign-test.c | 14 +- src/tests/memblockq-test.c | 12 +- src/tests/pacat-simple.c | 14 +- src/tests/parec-simple.c | 14 +- src/tests/strlist-test.c | 6 +- src/tests/sync-playback.c | 12 +- src/tests/thread-mainloop-test.c | 16 +- src/tests/utf8-test.c | 4 +- src/tests/voltest.c | 4 +- src/utils/Makefile | 2 +- src/utils/pabrowse.c | 12 +- src/utils/pacat.c | 12 +- src/utils/pacmd.c | 18 +- src/utils/pactl.c | 12 +- src/utils/padsp | 12 +- src/utils/padsp.c | 14 +- src/utils/paplay.c | 12 +- src/utils/pax11publish.c | 22 +- 303 files changed, 2724 insertions(+), 2719 deletions(-) rename polyplib-browse.pc.in => libpulse-browse.pc.in (57%) rename polyplib-glib-mainloop.pc.in => libpulse-glib-mainloop.pc.in (50%) rename polyplib-glib12-mainloop.pc.in => libpulse-glib12-mainloop.pc.in (50%) rename polyplib-simple.pc.in => libpulse-simple.pc.in (53%) rename polyplib.pc.in => libpulse.pc.in (66%) delete mode 120000 src/polypcore/Makefile rename src/{polyp => pulse}/Makefile (100%) rename src/{polyp => pulse}/browser.c (94%) rename src/{polyp => pulse}/browser.h (83%) rename src/{polyp => pulse}/cdecl.h (82%) rename src/{polyp => pulse}/channelmap.c (97%) rename src/{polyp => pulse}/channelmap.h (96%) rename src/{polyp => pulse}/client-conf-x11.c (85%) rename src/{polyp => pulse}/client-conf-x11.h (78%) rename src/{polyp => pulse}/client-conf.c (90%) rename src/{polyp => pulse}/client-conf.h (82%) rename src/{polyp => pulse}/client.conf.in (69%) rename src/{polyp => pulse}/context.c (97%) rename src/{polyp => pulse}/context.h (92%) rename src/{polyp => pulse}/def.h (98%) rename src/{polyp => pulse}/error.c (84%) rename src/{polyp => pulse}/error.h (76%) rename src/{polyp => pulse}/glib-mainloop.c (97%) rename src/{polyp => pulse}/glib-mainloop.h (85%) rename src/{polyp => pulse}/glib12-mainloop.c (97%) rename src/{polyp => pulse}/internal.h (89%) rename src/{polyp => pulse}/introspect.c (99%) rename src/{polyp => pulse}/introspect.h (98%) rename src/{polyp => pulse}/mainloop-api.c (84%) rename src/{polyp => pulse}/mainloop-api.h (89%) rename src/{polyp => pulse}/mainloop-signal.c (92%) rename src/{polyp => pulse}/mainloop-signal.h (87%) rename src/{polyp => pulse}/mainloop.c (97%) rename src/{polyp => pulse}/mainloop.h (94%) rename src/{polyp => pulse}/operation.c (90%) rename src/{polyp => pulse}/operation.h (81%) rename src/{polyp => pulse}/polypaudio.h (67%) rename src/{polyp => pulse}/sample.c (95%) rename src/{polyp => pulse}/sample.h (96%) rename src/{polyp => pulse}/scache.c (93%) rename src/{polyp => pulse}/scache.h (91%) rename src/{polyp => pulse}/simple.c (96%) rename src/{polyp => pulse}/simple.h (93%) rename src/{polyp => pulse}/stream.c (99%) rename src/{polyp => pulse}/stream.h (98%) rename src/{polyp => pulse}/subscribe.c (88%) rename src/{polyp => pulse}/subscribe.h (85%) rename src/{polyp => pulse}/thread-mainloop.c (96%) rename src/{polyp => pulse}/thread-mainloop.h (97%) rename src/{polyp => pulse}/timeval.c (92%) rename src/{polyp => pulse}/timeval.h (83%) rename src/{polyp => pulse}/utf8.c (100%) rename src/{polyp => pulse}/utf8.h (83%) rename src/{polyp => pulse}/util.c (92%) rename src/{polyp => pulse}/util.h (85%) rename src/{polyp => pulse}/version.h.in (77%) rename src/{polyp => pulse}/volume.c (94%) rename src/{polyp => pulse}/volume.h (95%) rename src/{polyp => pulse}/xmalloc.c (89%) rename src/{polyp => pulse}/xmalloc.h (89%) create mode 120000 src/pulsecore/Makefile rename src/{polypcore => pulsecore}/authkey-prop.c (85%) rename src/{polypcore => pulsecore}/authkey-prop.h (84%) rename src/{polypcore => pulsecore}/authkey.c (93%) rename src/{polypcore => pulsecore}/authkey.h (78%) rename src/{polypcore => pulsecore}/autoload.c (91%) rename src/{polypcore => pulsecore}/autoload.h (88%) rename src/{polypcore => pulsecore}/cli-command.c (97%) rename src/{polypcore => pulsecore}/cli-command.h (81%) rename src/{polypcore => pulsecore}/cli-text.c (95%) rename src/{polypcore => pulsecore}/cli-text.h (81%) rename src/{polypcore => pulsecore}/cli.c (81%) rename src/{polypcore => pulsecore}/cli.h (76%) rename src/{polypcore => pulsecore}/client.c (87%) rename src/{polypcore => pulsecore}/client.h (83%) rename src/{polypcore => pulsecore}/conf-parser.c (92%) rename src/{polypcore => pulsecore}/conf-parser.h (89%) rename src/{polypcore => pulsecore}/core-def.h (75%) rename src/{polypcore => pulsecore}/core-error.c (91%) rename src/{polypcore => pulsecore}/core-error.h (79%) rename src/{polypcore => pulsecore}/core-scache.c (93%) rename src/{polypcore => pulsecore}/core-scache.h (84%) rename src/{polypcore => pulsecore}/core-subscribe.c (95%) rename src/{polypcore => pulsecore}/core-subscribe.h (79%) rename src/{polypcore => pulsecore}/core-util.c (97%) rename src/{polypcore => pulsecore}/core-util.h (90%) rename src/{polypcore => pulsecore}/core.c (86%) rename src/{polypcore => pulsecore}/core.h (76%) rename src/{polypcore => pulsecore}/dllmain.c (83%) rename src/{polypcore => pulsecore}/dynarray.c (89%) rename src/{polypcore => pulsecore}/dynarray.h (86%) rename src/{polypcore => pulsecore}/endianmacros.h (91%) rename src/{polypcore => pulsecore}/esound.h (97%) rename src/{polypcore => pulsecore}/g711.c (100%) rename src/{polypcore => pulsecore}/g711.h (100%) rename src/{polypcore => pulsecore}/gccmacro.h (85%) rename src/{polypcore => pulsecore}/hashmap.c (93%) rename src/{polypcore => pulsecore}/hashmap.h (89%) rename src/{polypcore => pulsecore}/idxset.c (97%) rename src/{polypcore => pulsecore}/idxset.h (94%) rename src/{polypcore => pulsecore}/inet_ntop.c (90%) rename src/{polypcore => pulsecore}/inet_ntop.h (100%) rename src/{polypcore => pulsecore}/inet_pton.c (84%) rename src/{polypcore => pulsecore}/inet_pton.h (100%) rename src/{polypcore => pulsecore}/iochannel.c (96%) rename src/{polypcore => pulsecore}/iochannel.h (92%) rename src/{polypcore => pulsecore}/ioline.c (96%) rename src/{polypcore => pulsecore}/ioline.h (83%) rename src/{polypcore => pulsecore}/llist.h (92%) rename src/{polypcore => pulsecore}/log.c (94%) rename src/{polypcore => pulsecore}/log.h (89%) rename src/{polypcore => pulsecore}/mcalign.c (95%) rename src/{polypcore => pulsecore}/mcalign.h (87%) rename src/{polypcore => pulsecore}/memblock.c (93%) rename src/{polypcore => pulsecore}/memblock.h (93%) rename src/{polypcore => pulsecore}/memblockq.c (98%) rename src/{polypcore => pulsecore}/memblockq.h (93%) rename src/{polypcore => pulsecore}/memchunk.c (84%) rename src/{polypcore => pulsecore}/memchunk.h (83%) rename src/{polypcore => pulsecore}/modargs.c (94%) rename src/{polypcore => pulsecore}/modargs.h (87%) rename src/{polypcore => pulsecore}/modinfo.c (87%) rename src/{polypcore => pulsecore}/modinfo.h (82%) rename src/{polypcore => pulsecore}/module.c (95%) rename src/{polypcore => pulsecore}/module.h (85%) rename src/{polypcore => pulsecore}/namereg.c (92%) rename src/{polypcore => pulsecore}/namereg.h (82%) rename src/{polypcore => pulsecore}/native-common.h (91%) rename src/{polypcore => pulsecore}/packet.c (85%) rename src/{polypcore => pulsecore}/packet.h (81%) rename src/{polypcore => pulsecore}/parseaddr.c (90%) rename src/{polypcore => pulsecore}/parseaddr.h (81%) rename src/{polypcore => pulsecore}/pdispatch.c (95%) rename src/{polypcore => pulsecore}/pdispatch.h (82%) rename src/{polypcore => pulsecore}/pid.c (95%) rename src/{polypcore => pulsecore}/pid.h (76%) rename src/{polypcore => pulsecore}/pipe.c (93%) rename src/{polypcore => pulsecore}/pipe.h (74%) rename src/{polypcore => pulsecore}/play-memchunk.c (88%) rename src/{polypcore => pulsecore}/play-memchunk.h (73%) rename src/{polypcore => pulsecore}/poll.c (95%) rename src/{polypcore => pulsecore}/poll.h (91%) rename src/{polypcore => pulsecore}/props.c (90%) rename src/{polypcore => pulsecore}/props.h (86%) rename src/{polypcore => pulsecore}/protocol-cli.c (88%) rename src/{polypcore => pulsecore}/protocol-cli.h (69%) rename src/{polypcore => pulsecore}/protocol-esound.c (98%) rename src/{polypcore => pulsecore}/protocol-esound.h (70%) rename src/{polypcore => pulsecore}/protocol-http.c (95%) rename src/{polypcore => pulsecore}/protocol-http.h (70%) rename src/{polypcore => pulsecore}/protocol-native.c (98%) rename src/{polypcore => pulsecore}/protocol-native.h (73%) rename src/{polypcore => pulsecore}/protocol-simple.c (96%) rename src/{polypcore => pulsecore}/protocol-simple.h (70%) rename src/{polypcore => pulsecore}/pstream-util.c (85%) rename src/{polypcore => pulsecore}/pstream-util.h (77%) rename src/{polypcore => pulsecore}/pstream.c (97%) rename src/{polypcore => pulsecore}/pstream.h (81%) rename src/{polypcore => pulsecore}/queue.c (88%) rename src/{polypcore => pulsecore}/queue.h (83%) rename src/{polypcore => pulsecore}/random.c (88%) rename src/{polypcore => pulsecore}/random.h (75%) rename src/{polypcore => pulsecore}/resampler.c (98%) rename src/{polypcore => pulsecore}/resampler.h (86%) rename src/{polypcore => pulsecore}/sample-util.c (98%) rename src/{polypcore => pulsecore}/sample-util.h (79%) rename src/{polypcore => pulsecore}/sconv-s16be.c (80%) rename src/{polypcore => pulsecore}/sconv-s16be.h (77%) rename src/{polypcore => pulsecore}/sconv-s16le.c (86%) rename src/{polypcore => pulsecore}/sconv-s16le.h (77%) rename src/{polypcore => pulsecore}/sconv.c (93%) rename src/{polypcore => pulsecore}/sconv.h (79%) rename src/{polypcore => pulsecore}/sink-input.c (96%) rename src/{polypcore => pulsecore}/sink-input.h (86%) rename src/{polypcore => pulsecore}/sink.c (95%) rename src/{polypcore => pulsecore}/sink.h (83%) rename src/{polypcore => pulsecore}/sioman.c (79%) rename src/{polypcore => pulsecore}/sioman.h (74%) rename src/{polypcore => pulsecore}/socket-client.c (96%) rename src/{polypcore => pulsecore}/socket-client.h (83%) rename src/{polypcore => pulsecore}/socket-server.c (97%) rename src/{polypcore => pulsecore}/socket-server.h (88%) rename src/{polypcore => pulsecore}/socket-util.c (94%) rename src/{polypcore => pulsecore}/socket-util.h (80%) rename src/{polypcore => pulsecore}/sound-file-stream.c (93%) rename src/{polypcore => pulsecore}/sound-file-stream.h (73%) rename src/{polypcore => pulsecore}/sound-file.c (93%) rename src/{polypcore => pulsecore}/sound-file.h (71%) rename src/{polypcore => pulsecore}/source-output.c (94%) rename src/{polypcore => pulsecore}/source-output.h (84%) rename src/{polypcore => pulsecore}/source.c (94%) rename src/{polypcore => pulsecore}/source.h (81%) rename src/{polypcore => pulsecore}/strbuf.c (93%) rename src/{polypcore => pulsecore}/strbuf.h (79%) rename src/{polypcore => pulsecore}/strlist.c (89%) rename src/{polypcore => pulsecore}/strlist.h (86%) rename src/{polypcore => pulsecore}/tagstruct.c (98%) rename src/{polypcore => pulsecore}/tagstruct.h (90%) rename src/{polypcore => pulsecore}/tokenizer.c (85%) rename src/{polypcore => pulsecore}/tokenizer.h (78%) rename src/{polypcore => pulsecore}/winsock.h (100%) rename src/{polypcore => pulsecore}/x11prop.c (88%) rename src/{polypcore => pulsecore}/x11prop.h (78%) rename src/{polypcore => pulsecore}/x11wrap.c (94%) rename src/{polypcore => pulsecore}/x11wrap.h (85%) diff --git a/LICENSE b/LICENSE index 0ef095127..bc633bd14 100644 --- a/LICENSE +++ b/LICENSE @@ -1,13 +1,13 @@ -All Polypaudio source files are licensed under the GNU Lesser General Public +All PulseAudio source files are licensed under the GNU Lesser General Public License. (see file LGPL for details) However, the server side links to the GPL-only library 'libsamplerate' which practically downgrades the license of the server part to GPL (see file GPL for details), exercising section 3 of the LGPL. -Hence you should treat the client library ('libpolyp') of Polypaudio as being -LGPL licensed and the server part ('libpolypcore') as being GPL licensed. Since -the Polypaudio daemon and the modules link to 'libpolypcore' they are of course +Hence you should treat the client library ('libpulse') of Polypaudio as being +LGPL licensed and the server part ('libpulsecore') as being GPL licensed. Since +the PulseAudio daemon and the modules link to 'libpulsecore' they are of course also GPL licensed. -- Lennart Poettering, April 20th, 2006. diff --git a/Makefile.am b/Makefile.am index c7ea54f35..4174a39b1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,19 +1,19 @@ # $Id$ # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify +# PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software +# along with PulseAudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. @@ -24,16 +24,21 @@ MAINTAINERCLEANFILES = noinst_DATA = pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-browse.pc +pkgconfig_DATA = libpulse.pc libpulse-simple.pc + +if HAVE_HOWL +pkgconfig_DATA += \ + libpulse-browse.pc +endif if HAVE_GLIB20 pkgconfig_DATA += \ - polyplib-glib-mainloop.pc + libpulse-glib-mainloop.pc endif if HAVE_GLIB12 pkgconfig_DATA += \ - polyplib-glib12-mainloop.pc + libpulse-glib12-mainloop.pc endif if USE_LYNX @@ -49,11 +54,11 @@ endif homepage: all dist doxygen test -d $$HOME/homepage/private - mkdir -p $$HOME/homepage/private/projects/polypaudio $$HOME/homepage/private/projects/polypaudio/doxygen - cp polypaudio-@PACKAGE_VERSION@.tar.gz $$HOME/homepage/private/projects/polypaudio - cp doc/README.html doc/FAQ.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/polypaudio - cp -a doxygen/html/* $$HOME/homepage/private/projects/polypaudio/doxygen - ln -sf $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html + mkdir -p $$HOME/homepage/private/projects/pulseaudio $$HOME/homepage/private/projects/pulseaudio/doxygen + cp pulseaudio-@PACKAGE_VERSION@.tar.gz $$HOME/homepage/private/projects/pulseaudio + cp doc/README.html doc/FAQ.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/pulseaudio + cp -a doxygen/html/* $$HOME/homepage/private/projects/pulseaudio/doxygen + ln -sf $$HOME/homepage/private/projects/pulseaudio/README.html $$HOME/homepage/private/projects/pulseaudio/index.html #distcleancheck: # @: diff --git a/bootstrap.sh b/bootstrap.sh index ea6758a42..1f8b29d0b 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,20 +1,20 @@ #!/bin/bash # $Id$ -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify it +# PulseAudio is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software Foundation, +# along with PulseAudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. VERSION=1.9 diff --git a/configure.ac b/configure.ac index 0ccbe4f31..4f530347f 100644 --- a/configure.ac +++ b/configure.ac @@ -3,20 +3,20 @@ # $Id$ -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify it +# PulseAudio is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software Foundation, +# along with PulseAudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. AC_PREREQ(2.57) @@ -25,13 +25,13 @@ m4_define(PA_MAJOR, [0]) m4_define(PA_MINOR, [9]) m4_define(PA_MICRO, [1]) -AC_INIT([polypaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR") -AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/]) +AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/]) AC_SUBST(PA_API_VERSION, 9) AC_SUBST(PA_PROTOCOL_VERSION, 9) @@ -681,8 +681,8 @@ fi AC_ARG_WITH( [module-dir], - AC_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${libdir}/polypaudio-${PA_MAJORMINOR}/modules/]), - [modlibexecdir=$withval], [modlibexecdir="${libdir}/polypaudio-${PA_MAJORMINOR}/modules/"]) + AC_HELP_STRING([--with-module-dir],[Directory where to install the modules to (defaults to ${libdir}/pulse-${PA_MAJORMINOR}/modules/]), + [modlibexecdir=$withval], [modlibexecdir="${libdir}/pulse-${PA_MAJORMINOR}/modules/"]) AC_SUBST(modlibexecdir) @@ -695,11 +695,11 @@ AM_CONDITIONAL([FORCE_PREOPEN], [test "x$FORCE_PREOPEN" = "x1"]) AC_CONFIG_FILES([ Makefile src/Makefile -polyplib.pc -polyplib-simple.pc -polyplib-browse.pc -polyplib-glib-mainloop.pc -polyplib-glib12-mainloop.pc +libpulse.pc +libpulse-simple.pc +libpulse-browse.pc +libpulse-glib-mainloop.pc +libpulse-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html @@ -707,7 +707,7 @@ doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf -src/polyp/version.h +src/pulse/version.h doc/FAQ.html ]) AC_OUTPUT diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in index a042dd7b2..d9550e95c 100644 --- a/doc/FAQ.html.in +++ b/doc/FAQ.html.in @@ -2,7 +2,7 @@ -polypaudio: FAQ +pulseaudio: FAQ @@ -57,64 +57,64 @@ reimplement very much code for Polypaudio. It should be easy to implement limited support for libartsc based applications. Noone has done this yet. It is probably a better idea to - run arts on top of Polypaudio (through a polypaudio driver + run arts on top of Polypaudio (through a pulseaudio driver for aRts, which nobody has written yet). Another solution would be to embed Polypaudio in the aRts process.

    • I often hear noises when playing back with Polypaudio, what can I do?

      -

      There are to possible solutions: run polypaudio with argument +

      There are to possible solutions: run pulseaudio with argument --high-priority=1 and make yourself member of the group realtime, or increase the fragment sizes of the audio drivers. The former will allow Polypaudio to activate SCHED_FIFO high priority scheduling (root rights are dropped immediately after this). Keep in mind that this is a potential security hole!

    • -
    • The polypaudio executable is installed SUID root by default. Why this? Isn't this a potential security hole?

      +
    • The pulseaudio executable is installed SUID root by default. Why this? Isn't this a potential security hole?

      Polypaudio activates SCHED_FIFO scheduling if the user passes --high-priority=1. This will only succeed when executed as root, therefore the binary is marked SUID root by -default. Yes, this is a potential security hole. However, polypaudio +default. Yes, this is a potential security hole. However, pulseaudio tries its best to minimize the security threat: immediately after -startup polypaudio drops all capabilities except +startup pulseaudio drops all capabilities except CAP_SYS_NICE (At least on systems that support it, like Linux; see man 7 capabilities for more information). If the calling user is not a member of the group realtime (which is required to have a GID < 1000), root rights are dropped immediately. This means, you can -install polypaudio SUID root, but only a subset of your users (the +install pulseaudio SUID root, but only a subset of your users (the members of the group realtime) may make use of realtime scheduling. Keep in mind that these users might load their own binary -modules into the polypaudio daemon which may freeze the machine. The +modules into the pulseaudio daemon which may freeze the machine. The daemon has a minimal protection against CPU hogging (the daemon is killed after hogging more than 70% CPU for 5 seconds), but this may be circumvented easily by evildoers.

    • -
    • I want to run polypaudio only when it is needed, how do I do this?

      +
    • I want to run pulseaudio only when it is needed, how do I do this?

      Set autospawn = yes in client.conf. That -configuration file may be found either in /etc/polypaudio/ or -in ~/.polypaudio/.

    • +configuration file may be found either in /etc/pulseaudio/ or +in ~/.pulseaudio/.

      -
    • How do I list all polypaudio modules installed?

      +
    • How do I list all pulseaudio modules installed?

      -

      polypaudio --dump-modules

      +

      pulseaudio --dump-modules

      Add -v for terse usage instructions.

      -
    • How do I use polypaudio over the network?

      +
    • How do I use pulseaudio over the network?

      -

      Just set $POLYP_SERVER to the host name of the polypaudio +

      Just set $POLYP_SERVER to the host name of the pulseaudio server. For authentication you need the same auth cookies on all sides. For -that copy ~./polypaudio-cookie to all clients that shall +that copy ~./pulseaudio-cookie to all clients that shall be allowed to connect.

      Alternatively the authorization cookies can be stored in the X11 server.

    • -
    • Is polypaudio capable of providing synchronized audio playback over the network for movie players like mplayer?

      +
    • Is pulseaudio capable of providing synchronized audio playback over the network for movie players like mplayer?

      Yes! Unless your network is congested in some way (i.e. transfer latencies vary strongly) it works perfectly. Drop me an email for experimental patches for MPlayer.

      -
    • What environment variables does polypaudio care about?

      +
    • What environment variables does pulseaudio care about?

      The client honors: POLYP_SINK (default sink to connect to), POLYP_SOURCE (default source to connect to), POLYP_SERVER (default server to connect to, like ESPEAKER), POLYP_BINARY (the binary to start when autospawning a daemon), POLYP_CLIENTCONFIG (path to the client configuration file).

      @@ -126,31 +126,31 @@ be allowed to connect.

      A brilliant guy named Lennart Poettering once wrote a nifty tool for that purpose: bidilink. To -connect to a running polypaudio daemon try using the following commands:

      +connect to a running pulseaudio daemon try using the following commands:

      -
      killall -USR2 polypaudio
      -bidilink unix-client:/tmp/polypaudio/cli
      +
      killall -USR2 pulseaudio
      +bidilink unix-client:/tmp/pulseaudio/cli

      BTW: Someone should package this great tool for Debian!

      New: There's now a tool pacmd that automates sending SIGUSR2 to the daemon and running a bidilink like tool for you.

    • -
    • How do the polypaudio libraries decide where to connect to?

      +
    • How do the pulseaudio libraries decide where to connect to?

      The following rule applies:

      1. If the the application using the library specifies a server to connect to it is used. If the connection fails, the library fails too.
      2. If the environment variable POLYP_SERVER is defined the library connects to that server. If the connection fails, the library fails too.
      3. If $DISPLAY is set, the library tries to connect to that server and looks for the root window property POYLP_SERVER for the host to connect to. If POLYP_COOKIE is set it is used as authentication cookie.
      4. -
      5. If the client configuration file (~/.polypaudio/client.conf or /etc/polypaudio/client.conf) sets the server address, the library connects to that server. If the connection fails, the library fails too.
      6. -
      7. The library tries to connect to the default local UNIX socket for polypaudio servers. If the connection fails, it proceeds with the next item.
      8. -
      9. The library tries to connect to the default local TCP socket for polypaudio servers. If the connection fails, it proceeds with the next item.
      10. +
      11. If the client configuration file (~/.pulseaudio/client.conf or /etc/pulseaudio/client.conf) sets the server address, the library connects to that server. If the connection fails, the library fails too.
      12. +
      13. The library tries to connect to the default local UNIX socket for pulseaudio servers. If the connection fails, it proceeds with the next item.
      14. +
      15. The library tries to connect to the default local TCP socket for pulseaudio servers. If the connection fails, it proceeds with the next item.
      16. If $DISPLAY is set, the library tries to connect to the default TCP port of that host. If the connection fails, it proceeds with the next item.
      17. The connection fails.
    • -
    • Why the heck does libpolyp link against libX11?

      +
    • Why the heck does libpulse link against libX11?

      The Polypaudio client libraries look for some X11 root window properties for the credentials of the Polypaudio server to access. You may compile Polypaudio without X11 for disabling this feature.

    • diff --git a/doc/Makefile.am b/doc/Makefile.am index a5884abda..a58911add 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,19 +1,19 @@ # $Id$ -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify it +# PulseAudio is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software Foundation, +# along with PulseAudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. noinst_DATA = README.html cli.html modules.html daemon.html FAQ.html diff --git a/doc/README.html.in b/doc/README.html.in index f35b2da96..2f6ad4489 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -3,12 +3,12 @@ -polypaudio @PACKAGE_VERSION@ +pulseaudio @PACKAGE_VERSION@ -

      polypaudio @PACKAGE_VERSION@

      +

      pulseaudio @PACKAGE_VERSION@

      Copyright 2004-2006 Lennart Poettering <@PACKAGE_BUGREPORT@> and Pierre Ossman

      @@ -44,7 +44,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

      News

      Fri Jun 2 2006:

      Version 0.9.1 +href="@PACKAGE_URL@pulseaudio-0.9.1.tar.gz">Version 0.9.1 released; changes include: load modules even when libtool .la files are missing; generate better ALSA device names from module-detect; if an ALSA device doesn't support the @@ -53,7 +53,7 @@ suggests instead; amd64 portability; drop .sh suffix of esdcompat.sh; build system fixes; No API or ABI changes were made

      Fri May 26 2006:

      Version 0.9.0 +href="@PACKAGE_URL@pulseaudio-0.9.0.tar.gz">Version 0.9.0 released; changes include: new module module-volume-restore; new OSS API emulation tool padsp; require valid UTF8 strings everywhere; properly support ALSA channel maps for surround sound; @@ -62,7 +62,7 @@ main loop API for synchronous programs; introduce real shared object versioning; a few API additions; many, many bugfixes

      Fri Apr 28 2006:

      Version 0.8.1 +href="@PACKAGE_URL@pulseaudio-0.8.1.tar.gz">Version 0.8.1 released; changes include: support for specifying the channel map on the command lines of paplay and pacat and as arguments to the driver modules; ALSA hardware mixer compatibility; @@ -70,16 +70,16 @@ fix linking; properly remove PF_UNIX sockets when unloading protocol modules; fix sample cache; many other fixes

      Thu Apr 13 2006:

      Version 0.8 released; -changes include: too many to count - consider reading this blog entry for more information; many, many minor fixes.

      +href="@PACKAGE_URL@pulseaudio-0.8.tar.gz">Version 0.8 released; +changes include: too many to count - consider reading this blog entry for more information; many, many minor fixes.

      Sun Nov 21 2004:

      Version 0.7 released; +href="@PACKAGE_URL@pulseaudio-0.7.tar.gz">Version 0.7 released; changes include: IPv6 support; PID file support; publish credentials in X11 root window (module-x11-publish; new tool pacmd; ESOUND backend; new command load-sample-dir-lazy; many, many minor fixes.

      Thu Oct 28 2004:

      Version 0.6 released; +href="@PACKAGE_URL@pulseaudio-0.6.tar.gz">Version 0.6 released; changes include: TCP wrappers support; don't load the complete sound file into memory when playing back using pa_play_file(); autoload API change; don't load all sound files as FLOAT32; shorten @@ -91,14 +91,14 @@ generation; correctly lock daemon autospawning; print daemon layout to STDERR on SIGHUP; new options for pacat: allow sample type specification.

      Mon Sep 24 2004:

      Version 0.5.1 released; +href="@PACKAGE_URL@pulseaudio-0.5.1.tar.gz">Version 0.5.1 released; changes include: improve esound protocol compatibility; fix autospawning via libesd; make use of POSIX capabilities; allow SCHED_FIFO scheduling only for users in group realtime; minor build system fix.

      Mon Sep 20 2004:

      Version 0.5 released; +href="@PACKAGE_URL@pulseaudio-0.5.tar.gz">Version 0.5 released; changes include: extensive API improvements, new module module-combine for combining multiple sound cards into one, gcc 2.95 compatibility, configuration files, add "lazy" samples, @@ -106,29 +106,29 @@ support for source and network latency measurements, add module-pipe-source, many other fixes and improvements.

      Wed Sep 8 2004:

      Version 0.4 released; +href="@PACKAGE_URL@pulseaudio-0.4.tar.gz">Version 0.4 released; changes include: daemon auto spawning, support for SCHED_FIFO scheduling, three new modules, proper logging, CPU load watchdog, many fixes.

      Fri Aug 27 2004:

      Version 0.3 released; +href="@PACKAGE_URL@pulseaudio-0.3.tar.gz">Version 0.3 released; changes include: support for both glib 2.0 and glib 1.2, future cancellation, API updates, many fixes, relicense client library to LGPL.

      Fri Aug 20 2004:

      Version 0.2 released; +href="@PACKAGE_URL@pulseaudio-0.2.tar.gz">Version 0.2 released; changes include: added sample cache, introspection API, client API documentation, module autoloading, glib support, a module for intercepting X11 bell events, and much more.

      Sat Jul 17 2004:

      Version 0.1 released

      +href="@PACKAGE_URL@pulseaudio-0.1.tar.gz">Version 0.1 released

      Overview

      -

      polypaudio is a networked sound server for Linux and other +

      pulseaudio is a networked sound server for Linux and other Unix like operating systems and Microsoft Windows. It is intended to be an improved drop-in replacement for the Enlightened Sound Daemon (ESOUND). In addition to the features ESOUND provides -polypaudio has:

      +pulseaudio has:

      • Extensible plugin architecture (by loading dynamic loadable modules with dlopen())
      • @@ -150,8 +150,8 @@ Daemon (ESOUND). In addition to the features ESOUND provides use of a simple main loop abstraction layer. This allows easy integration with asynchronous applications using the glib/gtk mainloop. Since the asynchronous API -available through polyplib is quite difficult to use there is -a simplified synchronous API wrapper polyplib-simple +available through pulselib is quite difficult to use there is +a simplified synchronous API wrapper pulselib-simple available. A simple main loop implementation is available as well.

        The following modules are currently available:

        @@ -169,9 +169,9 @@ Sound Architecture (ALSA) sinks and sources
      • module-x11-bell: play a sample from the sample cache on every X11 bell event.
      • module-x11-publish: store Polypaudio credentials in the X11 root window.
      • module-esound-protocol-tcp, module-esound-protocol-unix: ESOUND compatibility modules (for TCP/IP resp. UNIX domain sockets)
      • -
      • module-native-protocol-tcp, module-native-protocol-unix: Native polypaudio protocol (for TCP/IP resp. UNIX domain sockets)
      • +
      • module-native-protocol-tcp, module-native-protocol-unix: Native pulseaudio protocol (for TCP/IP resp. UNIX domain sockets)
      • module-simple-protocol-tcp, module-simple-protocol-unix: Simplistic protocol for playback/capture for usage with tools like netcat (for TCP/IP resp. UNIX domain sockets)
      • -
      • module-cli-protocol-tcp, module-cli-protocol-unix, module-cli: Expose polypaudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
      • +
      • module-cli-protocol-tcp, module-cli-protocol-unix, module-cli: Expose pulseaudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
      • module-http-protocol-tcp: Spawns a small HTTP server which can be used to introspect the Polypaudio server with a web browser.
      • module-tunnel-sink, module-tunnel-source: make sinks/sources from other hosts available locally.
      • module-match: adjust volume automatically for newly created playback streams based on a regular expression matching table.
      • @@ -186,7 +186,7 @@ Sound Architecture (ALSA) sinks and sources
      • module-jack-sink, module-jack-source: connect to a JACK Audio Connection Kit server. (A sound server for professional audio production)
      -

      A GTK GUI manager application for polypaudio is the A GTK GUI manager application for pulseaudio is the Polypaudio Manager. Other GTK GUI tool for Polypaudio are the Polypaudio Volume @@ -195,10 +195,10 @@ href="http://0pointer.de/lennart/projects/pavucontrol">Polypaudio Volume Control .

      There are output plugins for XMMS, libao +href="http://0pointer.de/lennart/projects/xmms-pulse/">XMMS, libao (merged in libao SVN) and gstreamer +href="http://0pointer.de/lennart/projects/gst-pulse/">gstreamer (merged in gstreamer-plugins CVS), MPlayer (merged in MPlayer CVS) and Xine (merged in Xine CVS). Drivers for @@ -216,68 +216,68 @@ href="modules.html">modules.html, cli.html, daemon.html and FAQ.html.

      -

      There is a Trac based Wiki for Polypaudio available.

      +

      There is a Trac based Wiki for Polypaudio available.

      First Steps

      -

      Simply start the polypaudio daemon with the argument -nC

      +

      Simply start the pulseaudio daemon with the argument -nC

      -
      polypaudio -nC
      +
      pulseaudio -nC

      This will present you a screen like this:

      -
      Welcome to polypaudio! Use "help" for usage information.
      +
      Welcome to pulseaudio! Use "help" for usage information.
       >>> 

      Now you can issue CLI commands as described in cli.html. Another way to start -polypaudio is by specifying a configuration script like that one included in the distribution on the +pulseaudio is by specifying a configuration script like that one included in the distribution on the command line :

      -
      polypaudio -nF polypaudio.pa
      +
      pulseaudio -nF pulseaudio.pa

      This will load some drivers and protocols automatically.

      -

      The best idea is to configure your daemon in /etc/polypaudio/daemon.conf and /etc/polypaudio/default.pa and to run polypaudio without any arguments.

      +

      The best idea is to configure your daemon in /etc/pulseaudio/daemon.conf and /etc/pulseaudio/default.pa and to run pulseaudio without any arguments.

      Beware! Unless you pass the option --sysconfdir=/etc to -configure, the directory /etc/polypaudio/ is really -/usr/local/etc/polypaudio/.

      +configure, the directory /etc/pulseaudio/ is really +/usr/local/etc/pulseaudio/.

      -

      Developing polypaudio Clients

      +

      Developing pulseaudio Clients

      You may browse the Doxygen generated programing +href="http://0pointer.de/lennart/projects/pulseaudio/doxygen/">programing documentation for the client API. (Run make doxygen to generate this documentation from the source tree)

      -

      Developing polypaudio Modules

      +

      Developing pulseaudio Modules

      -

      There are several reasons for writing loadable modules for polypaudio:

      +

      There are several reasons for writing loadable modules for pulseaudio:

      • Extended device driver support
      • Protocol support beyond ESOUND's protocol and the native protocol. (such as NAS or a subset of aRts)
      • New programming interfaces such as XMLRPC or DBUS for controlling the daemon.
      • -
      • Hooking audio event sources directly into polypaudio (similar to module-x11-bell)
      • -
      • For low latency applications such as VOIP: load the VOIP core directly into polypaudio and have a slim GUI frontend to control it.
      • +
      • Hooking audio event sources directly into pulseaudio (similar to module-x11-bell)
      • +
      • For low latency applications such as VOIP: load the VOIP core directly into pulseaudio and have a slim GUI frontend to control it.

      There is currently no documentation how to write loadable modules -for polypaudio. Read the source, Luke! If you are interested in +for pulseaudio. Read the source, Luke! If you are interested in writing new modules feel free to contact the author in case you have any questions.

      Requirements

      -

      Currently, polypaudio is tested on Linux, FreeBSD, Solaris and Microsoft Windows. It requires an OSS, ALSA, Win32 or Solaris compatible soundcard.

      +

      Currently, pulseaudio is tested on Linux, FreeBSD, Solaris and Microsoft Windows. It requires an OSS, ALSA, Win32 or Solaris compatible soundcard.

      -

      polypaudio was developed and tested on Debian GNU/Linux +

      pulseaudio was developed and tested on Debian GNU/Linux "testing" from November 2004, it should work on most other Linux distributions (and maybe Unix versions) since it uses GNU autoconf and GNU libtool for source code configuration and shared library management.

      -

      polypaudio needs pulseaudio needs Secret Rabbit Code (aka libsamplerate), libsndfile, ./configure inside the distribution directory for configuring the source tree. After that you should run make for compilation and make install (as root) for installation of -polypaudio.

      +pulseaudio.

      Acknowledgements

      @@ -318,25 +318,25 @@ compilation and make install (as root) for installation of

      The newest release is always available from @PACKAGE_URL@

      -

      The current release is @PACKAGE_VERSION@

      +

      The current release is @PACKAGE_VERSION@

      -

      Get polypaudio's development sources from the Subversion repository (viewcvs):

      +

      Get pulseaudio's development sources from the Subversion repository (viewcvs):

      -
      svn checkout svn://0pointer.de/polypaudio/trunk polypaudio
      +
      svn checkout svn://0pointer.de/pulseaudio/trunk pulseaudio

      Community

      -

      If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

      +

      If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

      -

      There is a general discussion mailing list for polypaudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

      +

      There is a general discussion mailing list for pulseaudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

      -

      Polypaudio is being tracked at CIA.

      +

      Polypaudio is being tracked at CIA.

      -

      There's a chance to meet the Polypaudio developers on our IRC channel #polypaudio on irc.freenode.org.

      +

      There's a chance to meet the Polypaudio developers on our IRC channel #pulseaudio on irc.freenode.org.

      -

      There is a Trac based Wiki for Polypaudio available.

      +

      There is a Trac based Wiki for Polypaudio available.

      -

      Please report bugs to our Trac ticket system.

      +

      Please report bugs to our Trac ticket system.


      Lennart Poettering <@PACKAGE_BUGREPORT@>, June 2006
      diff --git a/doc/cli.html.in b/doc/cli.html.in index 0db96c366..511f5964c 100644 --- a/doc/cli.html.in +++ b/doc/cli.html.in @@ -2,14 +2,14 @@ -polypaudio: Simple Command Line Language +pulseaudio: Simple Command Line Language

      Simple Command Line Language

      -

      polypaudio provides a simple command line language used by +

      pulseaudio provides a simple command line language used by configuration scripts as well as the modules module-cli and module-cli-protocol-{unix,tcp}. Empty lines and lines beginning with a hashmark (#) are silently ignored. Several @@ -181,7 +181,7 @@ on the interactive command line.

      Example Configuration Script

      -

      Mark the following script as executable (chmod +x) and run it for a sensible polypaudio configuration.

      +

      Mark the following script as executable (chmod +x) and run it for a sensible pulseaudio configuration.

       #!/usr/bin/polaudio -nF
      diff --git a/doc/daemon.html.in b/doc/daemon.html.in
      index a4db0bd7a..0d91e534c 100644
      --- a/doc/daemon.html.in
      +++ b/doc/daemon.html.in
      @@ -2,7 +2,7 @@
       
       
       
      -polypaudio: Daemon
      +pulseaudio: Daemon
       
       
       
      @@ -11,7 +11,7 @@
       
       

      Command Line Arguments

      -The polypaudio daemon accepts several command line arguments: +The pulseaudio daemon accepts several command line arguments:
       COMMANDS:
      @@ -58,9 +58,9 @@ STARTUP SCRIPT:
       
       

      It is a good idea to run the daemon like this:

      -
      polypaudio -D
      +
      pulseaudio -D
      -

      This will run /etc/polypaudio/default.pa after startup. This should be a script written in the CLI language described in cli.html.

      +

      This will run /etc/pulseaudio/default.pa after startup. This should be a script written in the CLI language described in cli.html.

      Signals

      diff --git a/doc/modules.html.in b/doc/modules.html.in index 85479523f..f004f0841 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -2,7 +2,7 @@ -polypaudio: Loadable Modules +pulseaudio: Loadable Modules @@ -10,7 +10,7 @@

      Loadable Modules

      -

      The following loadable modules are provided with the polypaudio distribution:

      +

      The following loadable modules are provided with the pulseaudio distribution:

      Device Drivers

      @@ -157,7 +157,7 @@ will decrease output quality however. (defaults to

      module-tunnel-{sink,source}

      Tunnel a remote sink/source to a local "ghost" -sink/source. Requires a running polypaudio daemon on the remote server +sink/source. Requires a running pulseaudio daemon on the remote server with module-native-protocol-tcp loaded. It's probably a better idea to connect to the remote sink/source directly since some buffer control is lost through this tunneling.

      @@ -204,7 +204,7 @@ module see cli.html.

      module-cli-protocol-{unix,tcp}

      An implemenation of a simple command line based protocol for -controlling the polypaudio daemon. If loaded, the user may +controlling the pulseaudio daemon. If loaded, the user may connect with tools like netcat, telnet or bidilink to the listening sockets and execute commands the same way as with module-cli.

      @@ -225,7 +225,7 @@ transparent TCP/IP socket. (Both IPv6 and IPv4 - if available)

      a numerical binary value. If 1 the socket is bound to the loopback device, i.e. not publicly accessible. (defaults to 1) listen=(only for -tcp) The IP address to listen on. If specified, supersedes the value specified in loopback= - socket=(only for -unix) The UNIX socket name (defaults to /tmp/polypaudio/cli) + socket=(only for -unix) The UNIX socket name (defaults to /tmp/pulseaudio/cli)

      module-simple-protocol-{unix,tcp}

      @@ -254,7 +254,7 @@ about the two possible suffixes of this module.

      An implemenation of a protocol compatible with the Enlightened Sound Daemon (ESOUND, esd). When you load this module you may -access the polypaudio daemon with tools like esdcat, +access the pulseaudio daemon with tools like esdcat, esdrec or even esdctl. Many applications, such as XMMS, include support for this protocol.

      @@ -273,7 +273,7 @@ about the two possible suffixes of this module.

      module-native-protocol-{unix,tcp}

      -

      The native protocol of polypaudio.

      +

      The native protocol of pulseaudio.

      See module-cli-protocol-{unix,tcp} for more information about the two possible suffixes of this module.

      @@ -293,7 +293,7 @@ about the two possible suffixes of this module.

      module-http-protocol-tcp

      A proof-of-concept HTTP module, which can be used to introspect -the current status of the polypaudio daemon using HTTP. Just load this +the current status of the pulseaudio daemon using HTTP. Just load this module and point your browser to http://localhost:4714/. This module takes the same arguments as module-cli-protocol-tcp.

      @@ -347,7 +347,7 @@ already loaded protocol module is used. - +
      config=The LIRC configuration file
      appname=The application name to pass to LIRC (defaults to polypaudio)
      appname=The application name to pass to LIRC (defaults to pulseaudio)
      sink=The sink to control
      @@ -430,7 +430,7 @@ created in the JACK server.

      - +
      sink_name=The name for the Polypaudio sink. If ommited defaults to jack_out.
      server_name=The JACK server to connect to. If ommited defaults to the default server.
      client_name=The client name to tell the JACK server. If ommited defaults to polypaudio.
      client_name=The client name to tell the JACK server. If ommited defaults to pulseaudio.
      channels=Number of channels to register. If ommited defaults to the number of physical playback ports of the JACK server.
      connect=Takes a boolean value. If enabled (the default) Polypaudio will try to connect its ports to the physicial playback ports of the JACK server
      @@ -455,18 +455,18 @@ which is replaced by source_name (with a default of jack_in) f

      module-esound-compat-spawnfd

      -

      This is a compatibility module for libesd based autospawning of polypaudio. Don't use it directly.

      +

      This is a compatibility module for libesd based autospawning of pulseaudio. Don't use it directly.

      module-esound-compat-spawnpid

      -

      This is a compatibility module for libesd based autospawning of polypaudio. Don't use it directly.

      +

      This is a compatibility module for libesd based autospawning of pulseaudio. Don't use it directly.

      module-match

      Adjust the volume of a playback stream automatically based on its name.

      - +
      table=The regular expression matching table file to use (defaults to ~/.polypaudio/match.table)
      table=The regular expression matching table file to use (defaults to ~/.pulseaudio/match.table)

      The table file should contain a regexp and volume on each line, seperated by spaces. An example:

      @@ -482,7 +482,7 @@ which is replaced by source_name (with a default of jack_in) f

      Adjust the volume of a playback stream automatically based on its name.

      - +
      table=The table file to use (defaults to ~/.polypaudio/volume.table)
      table=The table file to use (defaults to ~/.pulseaudio/volume.table)

      In contrast to module-match this module needs no explicit diff --git a/doc/style.css b/doc/style.css index a606c08ef..c5af0055b 100644 --- a/doc/style.css +++ b/doc/style.css @@ -1,20 +1,20 @@ /* $Id$ */ /*** - * This file is part of polypaudio. + * This file is part of PulseAudio. * - * polypaudio is free software; you can redistribute it and/or modify it + * PulseAudio is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * polypaudio is distributed in the hope that it will be useful, but + * PulseAudio is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with polypaudio; if not, write to the Free Software Foundation, + * along with PulseAudio; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/doxygen/Makefile.am b/doxygen/Makefile.am index 8feec7339..c4f66d831 100644 --- a/doxygen/Makefile.am +++ b/doxygen/Makefile.am @@ -1,19 +1,19 @@ # $Id$ # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify +# PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software +# along with PulseAudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index f466c9d47..8ccf667ae 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -17,7 +17,7 @@ # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. -PROJECT_NAME = @PACKAGE_NAME@ +PROJECT_NAME = PulseAudio # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../src/polyp/context.h ../src/polyp/stream.h ../src/polyp/polypaudio.h ../src/polyp/sample.h ../src/polyp/def.h ../src/polyp/subscribe.h ../src/polyp/introspect.h ../src/polyp/scache.h ../src/polyp/mainloop-api.h ../src/polyp/glib-mainloop.h ../src/polyp/mainloop.h ../src/polyp/mainloop-signal.h ../src/polyp/error.h ../src/polyp/operation.h ../src/polyp/simple.h ../src/polyp/version.h ../src/polyp/volume.h ../src/polyp/channelmap.h ../src/polyp/thread-mainloop.h ../src/polyp/xmalloc.h ../src/polyp/utf8.h ../src/polyp/util.h ../src/polyp/timeval.h +INPUT = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/polyplib-browse.pc.in b/libpulse-browse.pc.in similarity index 57% rename from polyplib-browse.pc.in rename to libpulse-browse.pc.in index 952e28c10..7bdedf2e1 100644 --- a/polyplib-browse.pc.in +++ b/libpulse-browse.pc.in @@ -3,9 +3,9 @@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include -Name: polyplib-browse -Description: Polypaudio network browsing API +Name: libpuls-browse +Description: PulseAudio Network Browsing API Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-browse +Libs: -L${libdir} -lpulse-browse Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib +Requires: libpulse diff --git a/polyplib-glib-mainloop.pc.in b/libpulse-glib-mainloop.pc.in similarity index 50% rename from polyplib-glib-mainloop.pc.in rename to libpulse-glib-mainloop.pc.in index 03338c55b..169910ba1 100644 --- a/polyplib-glib-mainloop.pc.in +++ b/libpulse-glib-mainloop.pc.in @@ -3,9 +3,9 @@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include -Name: polyplib-glib-mainloop -Description: GLIB main loop wrapper for polypaudio +Name: libpulse-glib-mainloop +Description: GLIB 2.0 Main Loop Wrapper for PulseAudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-mainloop-glib +Libs: -L${libdir} -lpulse-mainloop-glib Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib glib-2.0 +Requires: libpulse glib-2.0 diff --git a/polyplib-glib12-mainloop.pc.in b/libpulse-glib12-mainloop.pc.in similarity index 50% rename from polyplib-glib12-mainloop.pc.in rename to libpulse-glib12-mainloop.pc.in index c12a838b3..f525c370d 100644 --- a/polyplib-glib12-mainloop.pc.in +++ b/libpulse-glib12-mainloop.pc.in @@ -3,9 +3,9 @@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include -Name: polyplib-glib12-mainloop -Description: GLIB main loop wrapper for polypaudio +Name: libpulse-glib12-mainloop +Description: GLIB 1.2 Main Loop Wrapper for PulseAudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-mainloop-glib12 +Libs: -L${libdir} -lpulse-mainloop-glib12 Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib glib +Requires: libpulse glib diff --git a/polyplib-simple.pc.in b/libpulse-simple.pc.in similarity index 53% rename from polyplib-simple.pc.in rename to libpulse-simple.pc.in index fa0ca0b95..c35e83fa5 100644 --- a/polyplib-simple.pc.in +++ b/libpulse-simple.pc.in @@ -3,9 +3,9 @@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include -Name: polyplib-simple -Description: Simplified synchronous client interface to polypaudio +Name: libpulse-simple +Description: Simplified Synchronous Client Interface to PulseAudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp-simple +Libs: -L${libdir} -lpulse-simple Cflags: -D_REENTRANT -I${includedir} -Requires: polyplib +Requires: libpulse diff --git a/polyplib.pc.in b/libpulse.pc.in similarity index 66% rename from polyplib.pc.in rename to libpulse.pc.in index 2d073a93d..8d0ffb85f 100644 --- a/polyplib.pc.in +++ b/libpulse.pc.in @@ -3,9 +3,9 @@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include -Name: polyplib -Description: Client interface to polypaudio +Name: libpulse +Description: Client Interface to PulseAudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpolyp +Libs: -L${libdir} -lpulse Cflags: -D_REENTRANT -I${includedir} Requires: diff --git a/src/Makefile.am b/src/Makefile.am index 6a2decb3d..746f85ecf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,19 +1,19 @@ # $Id$ # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify +# PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software +# along with PulseAudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. @@ -22,19 +22,19 @@ # Extra directories # ################################### -polypincludedir=$(includedir)/polyp -polypcoreincludedir=$(includedir)/polypcore -polypconfdir=$(sysconfdir)/polypaudio +pulseincludedir=$(includedir)/pulse +pulsecoreincludedir=$(includedir)/pulsecore +pulseconfdir=$(sysconfdir)/pulse ################################### # Defines # ################################### -POLYPAUDIO_BINARY=$(bindir)/polypaudio$(EXEEXT) +POLYPAUDIO_BINARY=$(bindir)/pulseaudio$(EXEEXT) if OS_IS_WIN32 DEFAULT_CONFIG_DIR=%POLYP_ROOT% else -DEFAULT_CONFIG_DIR=$(polypconfdir) +DEFAULT_CONFIG_DIR=$(pulseconfdir) endif ################################### @@ -73,7 +73,7 @@ endif ################################### EXTRA_DIST = \ - polyp/client.conf.in \ + pulse/client.conf.in \ daemon/daemon.conf.in \ daemon/default.pa.in \ depmod.py \ @@ -81,35 +81,35 @@ EXTRA_DIST = \ utils/padsp \ modules/module-defs.h.m4 -polypconf_DATA = \ +pulseconf_DATA = \ default.pa \ daemon.conf \ client.conf BUILT_SOURCES = \ - polyp/version.h + pulse/version.h ################################### # Main daemon # ################################### -bin_PROGRAMS = polypaudio +bin_PROGRAMS = pulseaudio -polypaudio_SOURCES = \ +pulseaudio_SOURCES = \ daemon/caps.h daemon/caps.c \ daemon/cmdline.c daemon/cmdline.h \ daemon/cpulimit.c daemon/cpulimit.h \ daemon/daemon-conf.c daemon/daemon-conf.h \ daemon/dumpmodules.c daemon/dumpmodules.h \ daemon/main.c \ - polypcore/gccmacro.h + pulsecore/gccmacro.h -polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) -polypaudio_CPPFLAGS = $(AM_CPPFLAGS) -polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \ +pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) +pulseaudio_CPPFLAGS = $(AM_CPPFLAGS) +pulseaudio_LDADD = $(AM_LDADD) libpulsecore.la $(LIBLTDL) \ $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) # This is needed because automake doesn't properly expand the foreach below -polypaudio_DEPENDENCIES = libpolypcore.la $(PREOPEN_LIBS) +pulseaudio_DEPENDENCIES = libpulsecore.la $(PREOPEN_LIBS) if PREOPEN_MODS PREOPEN_LIBS = $(PREOPEN_MODS) @@ -118,9 +118,9 @@ PREOPEN_LIBS = $(modlibexec_LTLIBRARIES) endif if FORCE_PREOPEN -polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlpreopen force $(foreach f,$(PREOPEN_LIBS),-dlpreopen $(f)) +pulseaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlpreopen force $(foreach f,$(PREOPEN_LIBS),-dlpreopen $(f)) else -polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f)) +pulseaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f)) endif ################################### @@ -147,32 +147,32 @@ endif bin_SCRIPTS = esdcompat pacat_SOURCES = utils/pacat.c -pacat_LDADD = $(AM_LDADD) libpolyp.la +pacat_LDADD = $(AM_LDADD) libpulse.la pacat_CFLAGS = $(AM_CFLAGS) pacat_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) paplay_SOURCES = utils/paplay.c -paplay_LDADD = $(AM_LDADD) libpolyp.la $(LIBSNDFILE_LIBS) +paplay_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS) paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) paplay_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pactl_SOURCES = utils/pactl.c -pactl_LDADD = $(AM_LDADD) libpolyp.la $(LIBSNDFILE_LIBS) +pactl_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS) pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pacmd_SOURCES = utils/pacmd.c polypcore/pid.c polypcore/pid.h +pacmd_SOURCES = utils/pacmd.c pulsecore/pid.c pulsecore/pid.h pacmd_CFLAGS = $(AM_CFLAGS) -pacmd_LDADD = $(AM_LDADD) libpolyp.la +pacmd_LDADD = $(AM_LDADD) libpulse.la pacmd_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pax11publish_SOURCES = utils/pax11publish.c pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -pax11publish_LDADD = $(AM_LDADD) libpolyp.la $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +pax11publish_LDADD = $(AM_LDADD) libpulse.la $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pabrowse_SOURCES = utils/pabrowse.c -pabrowse_LDADD = $(AM_LDADD) libpolyp.la libpolyp-browse.la +pabrowse_LDADD = $(AM_LDADD) libpulse.la libpulse-browse.la pabrowse_CFLAGS = $(AM_CFLAGS) pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -212,81 +212,81 @@ endif mainloop_test_SOURCES = tests/mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) -mainloop_test_LDADD = $(AM_LDADD) libpolyp.la +mainloop_test_LDADD = $(AM_LDADD) libpulse.la mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) thread_mainloop_test_SOURCES = tests/thread-mainloop-test.c thread_mainloop_test_CFLAGS = $(AM_CFLAGS) -thread_mainloop_test_LDADD = $(AM_LDADD) libpolyp.la +thread_mainloop_test_LDADD = $(AM_LDADD) libpulse.la thread_mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) utf8_test_SOURCES = tests/utf8-test.c utf8_test_CFLAGS = $(AM_CFLAGS) -utf8_test_LDADD = $(AM_LDADD) libpolypcore.la +utf8_test_LDADD = $(AM_LDADD) libpulsecore.la utf8_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) -mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la +mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la mcalign_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) pacat_simple_SOURCES = tests/pacat-simple.c -pacat_simple_LDADD = $(AM_LDADD) libpolyp.la libpolyp-simple.la +pacat_simple_LDADD = $(AM_LDADD) libpulse.la libpulse-simple.la pacat_simple_CFLAGS = $(AM_CFLAGS) pacat_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) parec_simple_SOURCES = tests/parec-simple.c -parec_simple_LDADD = $(AM_LDADD) libpolyp.la libpolyp-simple.la +parec_simple_LDADD = $(AM_LDADD) libpulse.la libpulse-simple.la parec_simple_CFLAGS = $(AM_CFLAGS) parec_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) strlist_test_SOURCES = tests/strlist-test.c strlist_test_CFLAGS = $(AM_CFLAGS) -strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la libstrlist.la +strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la libstrlist.la strlist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) voltest_SOURCES = tests/voltest.c voltest_CFLAGS = $(AM_CFLAGS) -voltest_LDADD = $(AM_LDADD) libpolyp.la +voltest_LDADD = $(AM_LDADD) libpulse.la voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) channelmap_test_SOURCES = tests/channelmap-test.c channelmap_test_CFLAGS = $(AM_CFLAGS) -channelmap_test_LDADD = $(AM_LDADD) libpolyp.la +channelmap_test_LDADD = $(AM_LDADD) libpulse.la channelmap_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) cpulimit_test_SOURCES = tests/cpulimit-test.c daemon/cpulimit.c daemon/cpulimit.h cpulimit_test_CFLAGS = $(AM_CFLAGS) -cpulimit_test_LDADD = $(AM_LDADD) libpolypcore.la +cpulimit_test_LDADD = $(AM_LDADD) libpulsecore.la cpulimit_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) cpulimit_test2_SOURCES = tests/cpulimit-test.c daemon/cpulimit.c daemon/cpulimit.h cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2 -cpulimit_test2_LDADD = $(AM_LDADD) libpolypcore.la +cpulimit_test2_LDADD = $(AM_LDADD) libpulsecore.la cpulimit_test2_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES) mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib.la +mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpulse-mainloop-glib.la mainloop_test_glib_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12.la +mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpulse-mainloop-glib12.la mainloop_test_glib12_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) memblockq_test_SOURCES = tests/memblockq-test.c memblockq_test_CFLAGS = $(AM_CFLAGS) -memblockq_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpolypcore.la +memblockq_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la memblockq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) sync_playback_SOURCES = tests/sync-playback.c -sync_playback_LDADD = $(AM_LDADD) libpolyp.la +sync_playback_LDADD = $(AM_LDADD) libpulse.la sync_playback_CFLAGS = $(AM_CFLAGS) sync_playback_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) interpol_test_SOURCES = tests/interpol-test.c -interpol_test_LDADD = $(AM_LDADD) libpolyp.la +interpol_test_LDADD = $(AM_LDADD) libpulse.la interpol_test_CFLAGS = $(AM_CFLAGS) interpol_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -294,170 +294,170 @@ interpol_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) # Client library # ################################### -polypinclude_HEADERS = \ - polyp/cdecl.h \ - polyp/channelmap.h \ - polyp/context.h \ - polyp/def.h \ - polyp/error.h \ - polyp/introspect.h \ - polyp/mainloop.h \ - polyp/mainloop-api.h \ - polyp/mainloop-signal.h \ - polyp/operation.h \ - polyp/polypaudio.h \ - polyp/sample.h \ - polyp/scache.h \ - polyp/simple.h \ - polyp/stream.h \ - polyp/subscribe.h \ - polyp/thread-mainloop.h \ - polyp/timeval.h \ - polyp/utf8.h \ - polyp/util.h \ - polyp/version.h \ - polyp/volume.h \ - polyp/xmalloc.h +pulseinclude_HEADERS = \ + pulse/cdecl.h \ + pulse/channelmap.h \ + pulse/context.h \ + pulse/def.h \ + pulse/error.h \ + pulse/introspect.h \ + pulse/mainloop.h \ + pulse/mainloop-api.h \ + pulse/mainloop-signal.h \ + pulse/operation.h \ + pulse/pulseaudio.h \ + pulse/sample.h \ + pulse/scache.h \ + pulse/simple.h \ + pulse/stream.h \ + pulse/subscribe.h \ + pulse/thread-mainloop.h \ + pulse/timeval.h \ + pulse/utf8.h \ + pulse/util.h \ + pulse/version.h \ + pulse/volume.h \ + pulse/xmalloc.h if HAVE_HOWL -polypinclude_HEADERS += \ - polyp/browser.h +pulseinclude_HEADERS += \ + pulse/browser.h endif if HAVE_GLIB20 -polypinclude_HEADERS += \ - polyp/glib-mainloop.h +pulseinclude_HEADERS += \ + pulse/glib-mainloop.h else if HAVE_GLIB12 -polypinclude_HEADERS += \ - polyp/glib-mainloop.h +pulseinclude_HEADERS += \ + pulse/glib-mainloop.h endif endif lib_LTLIBRARIES = \ - libpolyp.la \ - libpolyp-simple.la + libpulse.la \ + libpulse-simple.la if HAVE_HOWL lib_LTLIBRARIES += \ - libpolyp-browse.la + libpulse-browse.la endif if HAVE_GLIB20 lib_LTLIBRARIES += \ - libpolyp-mainloop-glib.la + libpulse-mainloop-glib.la endif if HAVE_GLIB12 lib_LTLIBRARIES += \ - libpolyp-mainloop-glib12.la + libpulse-mainloop-glib12.la endif # Public interface -libpolyp_la_SOURCES = \ - polyp/cdecl.h \ - polyp/channelmap.c polyp/channelmap.h \ - polyp/client-conf.c polyp/client-conf.h \ - polyp/context.c polyp/context.h \ - polyp/def.h \ - polyp/error.c polyp/error.h \ - polyp/internal.h \ - polyp/introspect.c polyp/introspect.h \ - polyp/mainloop.c polyp/mainloop.h \ - polyp/mainloop-api.c polyp/mainloop-api.h \ - polyp/mainloop-signal.c polyp/mainloop-signal.h \ - polyp/operation.c polyp/operation.h \ - polyp/polypaudio.h \ - polyp/sample.c polyp/sample.h \ - polyp/scache.c polyp/scache.h \ - polyp/stream.c polyp/stream.h \ - polyp/subscribe.c polyp/subscribe.h \ - polyp/thread-mainloop.c polyp/thread-mainloop.h \ - polyp/timeval.c polyp/timeval.h \ - polyp/utf8.c polyp/utf8.h \ - polyp/util.c polyp/util.h \ - polyp/volume.c polyp/volume.h \ - polyp/xmalloc.c polyp/xmalloc.h +libpulse_la_SOURCES = \ + pulse/cdecl.h \ + pulse/channelmap.c pulse/channelmap.h \ + pulse/client-conf.c pulse/client-conf.h \ + pulse/context.c pulse/context.h \ + pulse/def.h \ + pulse/error.c pulse/error.h \ + pulse/internal.h \ + pulse/introspect.c pulse/introspect.h \ + pulse/mainloop.c pulse/mainloop.h \ + pulse/mainloop-api.c pulse/mainloop-api.h \ + pulse/mainloop-signal.c pulse/mainloop-signal.h \ + pulse/operation.c pulse/operation.h \ + pulse/pulseaudio.h \ + pulse/sample.c pulse/sample.h \ + pulse/scache.c pulse/scache.h \ + pulse/stream.c pulse/stream.h \ + pulse/subscribe.c pulse/subscribe.h \ + pulse/thread-mainloop.c pulse/thread-mainloop.h \ + pulse/timeval.c pulse/timeval.h \ + pulse/utf8.c pulse/utf8.h \ + pulse/util.c pulse/util.h \ + pulse/volume.c pulse/volume.h \ + pulse/xmalloc.c pulse/xmalloc.h -# Internal stuff that is shared with libpolypcore -libpolyp_la_SOURCES += \ - polypcore/authkey.c polypcore/authkey.h \ - polypcore/conf-parser.c polypcore/conf-parser.h \ - polypcore/core-util.c polypcore/core-util.h \ - polypcore/dynarray.c polypcore/dynarray.h \ - polypcore/gccmacro.h \ - polypcore/hashmap.c polypcore/hashmap.h \ - polypcore/idxset.c polypcore/idxset.h \ - polypcore/inet_ntop.c polypcore/inet_ntop.h \ - polypcore/iochannel.c polypcore/iochannel.h \ - polypcore/llist.h \ - polypcore/log.c polypcore/log.h \ - polypcore/mcalign.c polypcore/mcalign.h \ - polypcore/memblock.c polypcore/memblock.h \ - polypcore/memblockq.c polypcore/memblockq.h \ - polypcore/memchunk.c polypcore/memchunk.h \ - polypcore/native-common.h \ - polypcore/packet.c polypcore/packet.h \ - polypcore/parseaddr.c polypcore/parseaddr.h \ - polypcore/pdispatch.c polypcore/pdispatch.h \ - polypcore/pipe.c polypcore/pipe.h \ - polypcore/poll.c polypcore/poll.h \ - polypcore/pstream.c polypcore/pstream.h \ - polypcore/pstream-util.c polypcore/pstream-util.h \ - polypcore/queue.c polypcore/queue.h \ - polypcore/random.c polypcore/random.h \ - polypcore/socket-client.c polypcore/socket-client.h \ - polypcore/socket-util.c polypcore/socket-util.h \ - polypcore/strbuf.c polypcore/strbuf.h \ - polypcore/strlist.c polypcore/strlist.h \ - polypcore/tagstruct.c polypcore/tagstruct.h \ - polypcore/core-error.c polypcore/core-error.h \ - polypcore/winsock.h +# Internal stuff that is shared with libpulsecore +libpulse_la_SOURCES += \ + pulsecore/authkey.c pulsecore/authkey.h \ + pulsecore/conf-parser.c pulsecore/conf-parser.h \ + pulsecore/core-util.c pulsecore/core-util.h \ + pulsecore/dynarray.c pulsecore/dynarray.h \ + pulsecore/gccmacro.h \ + pulsecore/hashmap.c pulsecore/hashmap.h \ + pulsecore/idxset.c pulsecore/idxset.h \ + pulsecore/inet_ntop.c pulsecore/inet_ntop.h \ + pulsecore/iochannel.c pulsecore/iochannel.h \ + pulsecore/llist.h \ + pulsecore/log.c pulsecore/log.h \ + pulsecore/mcalign.c pulsecore/mcalign.h \ + pulsecore/memblock.c pulsecore/memblock.h \ + pulsecore/memblockq.c pulsecore/memblockq.h \ + pulsecore/memchunk.c pulsecore/memchunk.h \ + pulsecore/native-common.h \ + pulsecore/packet.c pulsecore/packet.h \ + pulsecore/parseaddr.c pulsecore/parseaddr.h \ + pulsecore/pdispatch.c pulsecore/pdispatch.h \ + pulsecore/pipe.c pulsecore/pipe.h \ + pulsecore/poll.c pulsecore/poll.h \ + pulsecore/pstream.c pulsecore/pstream.h \ + pulsecore/pstream-util.c pulsecore/pstream-util.h \ + pulsecore/queue.c pulsecore/queue.h \ + pulsecore/random.c pulsecore/random.h \ + pulsecore/socket-client.c pulsecore/socket-client.h \ + pulsecore/socket-util.c pulsecore/socket-util.h \ + pulsecore/strbuf.c pulsecore/strbuf.h \ + pulsecore/strlist.c pulsecore/strlist.h \ + pulsecore/tagstruct.c pulsecore/tagstruct.h \ + pulsecore/core-error.c pulsecore/core-error.h \ + pulsecore/winsock.h if OS_IS_WIN32 -libpolyp_la_SOURCES += \ - polypcore/dllmain.c +libpulse_la_SOURCES += \ + pulsecore/dllmain.c endif if HAVE_X11 -libpolyp_la_SOURCES += \ - polyp/client-conf-x11.c polyp/client-conf-x11.h \ - polypcore/x11prop.c polypcore/x11prop.h +libpulse_la_SOURCES += \ + pulse/client-conf-x11.c pulse/client-conf-x11.h \ + pulsecore/x11prop.c pulsecore/x11prop.h endif -libpolyp_la_CFLAGS = $(AM_CFLAGS) -libpolyp_la_LDFLAGS = -version-info $(LIBPOLYP_VERSION_INFO) -libpolyp_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LIBICONV) +libpulse_la_CFLAGS = $(AM_CFLAGS) +libpulse_la_LDFLAGS = -version-info $(LIBPOLYP_VERSION_INFO) +libpulse_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LIBICONV) if HAVE_X11 -libpolyp_la_CFLAGS += $(X_CFLAGS) -libpolyp_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +libpulse_la_CFLAGS += $(X_CFLAGS) +libpulse_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) endif if HAVE_LIBASYNCNS -libpolyp_la_CFLAGS += $(LIBASYNCNS_CFLAGS) -libpolyp_la_LIBADD += $(LIBASYNCNS_LIBS) +libpulse_la_CFLAGS += $(LIBASYNCNS_CFLAGS) +libpulse_la_LIBADD += $(LIBASYNCNS_LIBS) endif -libpolyp_simple_la_SOURCES = polyp/simple.c polyp/simple.h -libpolyp_simple_la_CFLAGS = $(AM_CFLAGS) -libpolyp_simple_la_LIBADD = $(AM_LIBADD) libpolyp.la -libpolyp_simple_la_LDFLAGS = -version-info $(LIBPOLYP_SIMPLE_VERSION_INFO) +libpulse_simple_la_SOURCES = pulse/simple.c pulse/simple.h +libpulse_simple_la_CFLAGS = $(AM_CFLAGS) +libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la +libpulse_simple_la_LDFLAGS = -version-info $(LIBPOLYP_SIMPLE_VERSION_INFO) -libpolyp_browse_la_SOURCES = polyp/browser.c polyp/browser.h -libpolyp_browse_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) -libpolyp_browse_la_LIBADD = $(AM_LIBADD) libpolyp.la $(HOWL_LIBS) -libpolyp_browse_la_LDFLAGS = -version-info $(LIBPOLYP_BROWSE_VERSION_INFO) +libpulse_browse_la_SOURCES = pulse/browser.c pulse/browser.h +libpulse_browse_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) +libpulse_browse_la_LIBADD = $(AM_LIBADD) libpulse.la $(HOWL_LIBS) +libpulse_browse_la_LDFLAGS = -version-info $(LIBPOLYP_BROWSE_VERSION_INFO) -libpolyp_mainloop_glib_la_SOURCES = polyp/glib-mainloop.h polyp/glib-mainloop.c -libpolyp_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) -libpolyp_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpolyp.la $(GLIB20_LIBS) -libpolyp_mainloop_glib_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO) +libpulse_mainloop_glib_la_SOURCES = pulse/glib-mainloop.h pulse/glib-mainloop.c +libpulse_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) +libpulse_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpulse.la $(GLIB20_LIBS) +libpulse_mainloop_glib_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO) -libpolyp_mainloop_glib12_la_SOURCES = polyp/glib-mainloop.h polyp/glib12-mainloop.c -libpolyp_mainloop_glib12_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) -libpolyp_mainloop_glib12_la_LIBADD = $(AM_LIBADD) libpolyp.la $(GLIB12_LIBS) -libpolyp_mainloop_glib12_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO) +libpulse_mainloop_glib12_la_SOURCES = pulse/glib-mainloop.h pulse/glib12-mainloop.c +libpulse_mainloop_glib12_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) +libpulse_mainloop_glib12_la_LIBADD = $(AM_LIBADD) libpulse.la $(GLIB12_LIBS) +libpulse_mainloop_glib12_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO) ################################### # OSS emulation # @@ -465,164 +465,164 @@ libpolyp_mainloop_glib12_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VER if HAVE_OSS -lib_LTLIBRARIES += libpolypdsp.la +lib_LTLIBRARIES += libpulsedsp.la bin_SCRIPTS += utils/padsp endif -libpolypdsp_la_SOURCES = utils/padsp.c -libpolypdsp_la_CFLAGS = $(AM_CFLAGS) -libpolypdsp_la_LIBADD = $(AM_LIBADD) libpolyp.la -libpolypdsp_la_LDFLAGS = -avoid-version +libpulsedsp_la_SOURCES = utils/padsp.c +libpulsedsp_la_CFLAGS = $(AM_CFLAGS) +libpulsedsp_la_LIBADD = $(AM_LIBADD) libpulse.la +libpulsedsp_la_LDFLAGS = -avoid-version ################################### # Daemon core library # ################################### -polypcoreinclude_HEADERS = \ - polypcore/autoload.h \ - polypcore/cli-command.h \ - polypcore/cli-text.h \ - polypcore/client.h \ - polypcore/core.h \ - polypcore/core-def.h \ - polypcore/core-scache.h \ - polypcore/core-subscribe.h \ - polypcore/conf-parser.h \ - polypcore/core-util.h \ - polypcore/dynarray.h \ - polypcore/g711.h \ - polypcore/hashmap.h \ - polypcore/idxset.h \ - polypcore/log.h \ - polypcore/mcalign.h \ - polypcore/memblock.h \ - polypcore/memblockq.h \ - polypcore/memchunk.h \ - polypcore/modargs.h \ - polypcore/modinfo.h \ - polypcore/module.h \ - polypcore/namereg.h \ - polypcore/pid.h \ - polypcore/play-memchunk.h \ - polypcore/props.h \ - polypcore/queue.h \ - polypcore/random.h \ - polypcore/resampler.h \ - polypcore/sample-util.h \ - polypcore/sconv.h \ - polypcore/sink.h \ - polypcore/sink-input.h \ - polypcore/sioman.h \ - polypcore/sound-file.h \ - polypcore/sound-file-stream.h \ - polypcore/source.h \ - polypcore/source-output.h \ - polypcore/strbuf.h \ - polypcore/tokenizer.h +pulsecoreinclude_HEADERS = \ + pulsecore/autoload.h \ + pulsecore/cli-command.h \ + pulsecore/cli-text.h \ + pulsecore/client.h \ + pulsecore/core.h \ + pulsecore/core-def.h \ + pulsecore/core-scache.h \ + pulsecore/core-subscribe.h \ + pulsecore/conf-parser.h \ + pulsecore/core-util.h \ + pulsecore/dynarray.h \ + pulsecore/g711.h \ + pulsecore/hashmap.h \ + pulsecore/idxset.h \ + pulsecore/log.h \ + pulsecore/mcalign.h \ + pulsecore/memblock.h \ + pulsecore/memblockq.h \ + pulsecore/memchunk.h \ + pulsecore/modargs.h \ + pulsecore/modinfo.h \ + pulsecore/module.h \ + pulsecore/namereg.h \ + pulsecore/pid.h \ + pulsecore/play-memchunk.h \ + pulsecore/props.h \ + pulsecore/queue.h \ + pulsecore/random.h \ + pulsecore/resampler.h \ + pulsecore/sample-util.h \ + pulsecore/sconv.h \ + pulsecore/sink.h \ + pulsecore/sink-input.h \ + pulsecore/sioman.h \ + pulsecore/sound-file.h \ + pulsecore/sound-file-stream.h \ + pulsecore/source.h \ + pulsecore/source-output.h \ + pulsecore/strbuf.h \ + pulsecore/tokenizer.h -lib_LTLIBRARIES += libpolypcore.la +lib_LTLIBRARIES += libpulsecore.la # Some public stuff is used even in the core. -libpolypcore_la_SOURCES = \ - polyp/channelmap.c polyp/channelmap.h \ - polyp/error.c polyp/error.h \ - polyp/mainloop.c polyp/mainloop.h \ - polyp/mainloop-api.c polyp/mainloop-api.h \ - polyp/mainloop-signal.c polyp/mainloop-signal.h \ - polyp/sample.c polyp/sample.h \ - polyp/timeval.c polyp/timeval.h \ - polyp/utf8.c polyp/utf8.h \ - polyp/util.c polyp/util.h \ - polyp/volume.c polyp/volume.h \ - polyp/xmalloc.c polyp/xmalloc.h +libpulsecore_la_SOURCES = \ + pulse/channelmap.c pulse/channelmap.h \ + pulse/error.c pulse/error.h \ + pulse/mainloop.c pulse/mainloop.h \ + pulse/mainloop-api.c pulse/mainloop-api.h \ + pulse/mainloop-signal.c pulse/mainloop-signal.h \ + pulse/sample.c pulse/sample.h \ + pulse/timeval.c pulse/timeval.h \ + pulse/utf8.c pulse/utf8.h \ + pulse/util.c pulse/util.h \ + pulse/volume.c pulse/volume.h \ + pulse/xmalloc.c pulse/xmalloc.h -# Pure core stuff (some are shared in libpolyp though). -libpolypcore_la_SOURCES += \ - polypcore/autoload.c polypcore/autoload.h \ - polypcore/cli-command.c polypcore/cli-command.h \ - polypcore/cli-text.c polypcore/cli-text.h \ - polypcore/client.c polypcore/client.h \ - polypcore/conf-parser.c polypcore/conf-parser.h \ - polypcore/core.c polypcore/core.h \ - polypcore/core-scache.c polypcore/core-scache.h \ - polypcore/core-subscribe.c polypcore/core-subscribe.h \ - polypcore/core-util.c polypcore/core-util.h \ - polypcore/dynarray.c polypcore/dynarray.h \ - polypcore/endianmacros.h \ - polypcore/g711.c polypcore/g711.h \ - polypcore/hashmap.c polypcore/hashmap.h \ - polypcore/idxset.c polypcore/idxset.h \ - polypcore/log.c polypcore/log.h \ - polypcore/mcalign.c polypcore/mcalign.h \ - polypcore/memblock.c polypcore/memblock.h \ - polypcore/memblockq.c polypcore/memblockq.h \ - polypcore/memchunk.c polypcore/memchunk.h \ - polypcore/modargs.c polypcore/modargs.h \ - polypcore/modinfo.c polypcore/modinfo.h \ - polypcore/module.c polypcore/module.h \ - polypcore/namereg.c polypcore/namereg.h \ - polypcore/pid.c polypcore/pid.h \ - polypcore/pipe.c polypcore/pipe.h \ - polypcore/play-memchunk.c polypcore/play-memchunk.h \ - polypcore/poll.c polypcore/poll.h \ - polypcore/props.c polypcore/props.h \ - polypcore/queue.c polypcore/queue.h \ - polypcore/random.c polypcore/random.h \ - polypcore/resampler.c polypcore/resampler.h \ - polypcore/sample-util.c polypcore/sample-util.h \ - polypcore/sconv.c polypcore/sconv.h \ - polypcore/sconv-s16be.c polypcore/sconv-s16be.h \ - polypcore/sconv-s16le.c polypcore/sconv-s16le.h \ - polypcore/sink.c polypcore/sink.h \ - polypcore/sink-input.c polypcore/sink-input.h \ - polypcore/sioman.c polypcore/sioman.h \ - polypcore/sound-file.c polypcore/sound-file.h \ - polypcore/sound-file-stream.c polypcore/sound-file-stream.h \ - polypcore/source.c polypcore/source.h \ - polypcore/source-output.c polypcore/source-output.h \ - polypcore/strbuf.c polypcore/strbuf.h \ - polypcore/tokenizer.c polypcore/tokenizer.h \ - polypcore/winsock.h \ - polypcore/core-error.c polypcore/core-error.h +# Pure core stuff (some are shared in libpulse though). +libpulsecore_la_SOURCES += \ + pulsecore/autoload.c pulsecore/autoload.h \ + pulsecore/cli-command.c pulsecore/cli-command.h \ + pulsecore/cli-text.c pulsecore/cli-text.h \ + pulsecore/client.c pulsecore/client.h \ + pulsecore/conf-parser.c pulsecore/conf-parser.h \ + pulsecore/core.c pulsecore/core.h \ + pulsecore/core-scache.c pulsecore/core-scache.h \ + pulsecore/core-subscribe.c pulsecore/core-subscribe.h \ + pulsecore/core-util.c pulsecore/core-util.h \ + pulsecore/dynarray.c pulsecore/dynarray.h \ + pulsecore/endianmacros.h \ + pulsecore/g711.c pulsecore/g711.h \ + pulsecore/hashmap.c pulsecore/hashmap.h \ + pulsecore/idxset.c pulsecore/idxset.h \ + pulsecore/log.c pulsecore/log.h \ + pulsecore/mcalign.c pulsecore/mcalign.h \ + pulsecore/memblock.c pulsecore/memblock.h \ + pulsecore/memblockq.c pulsecore/memblockq.h \ + pulsecore/memchunk.c pulsecore/memchunk.h \ + pulsecore/modargs.c pulsecore/modargs.h \ + pulsecore/modinfo.c pulsecore/modinfo.h \ + pulsecore/module.c pulsecore/module.h \ + pulsecore/namereg.c pulsecore/namereg.h \ + pulsecore/pid.c pulsecore/pid.h \ + pulsecore/pipe.c pulsecore/pipe.h \ + pulsecore/play-memchunk.c pulsecore/play-memchunk.h \ + pulsecore/poll.c pulsecore/poll.h \ + pulsecore/props.c pulsecore/props.h \ + pulsecore/queue.c pulsecore/queue.h \ + pulsecore/random.c pulsecore/random.h \ + pulsecore/resampler.c pulsecore/resampler.h \ + pulsecore/sample-util.c pulsecore/sample-util.h \ + pulsecore/sconv.c pulsecore/sconv.h \ + pulsecore/sconv-s16be.c pulsecore/sconv-s16be.h \ + pulsecore/sconv-s16le.c pulsecore/sconv-s16le.h \ + pulsecore/sink.c pulsecore/sink.h \ + pulsecore/sink-input.c pulsecore/sink-input.h \ + pulsecore/sioman.c pulsecore/sioman.h \ + pulsecore/sound-file.c pulsecore/sound-file.h \ + pulsecore/sound-file-stream.c pulsecore/sound-file-stream.h \ + pulsecore/source.c pulsecore/source.h \ + pulsecore/source-output.c pulsecore/source-output.h \ + pulsecore/strbuf.c pulsecore/strbuf.h \ + pulsecore/tokenizer.c pulsecore/tokenizer.h \ + pulsecore/winsock.h \ + pulsecore/core-error.c pulsecore/core-error.h if OS_IS_WIN32 -libpolypcore_la_SOURCES += \ - polypcore/dllmain.c +libpulsecore_la_SOURCES += \ + pulsecore/dllmain.c endif -libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) -libpolypcore_la_LDFLAGS = -version-info $(LIBPOLYPCORE_VERSION_INFO) -libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV) +libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) +libpulsecore_la_LDFLAGS = -version-info $(LIBPOLYPCORE_VERSION_INFO) +libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV) ################################### # Plug-in support libraries # ################################### -polypcoreinclude_HEADERS += \ - polypcore/socket-util.h \ - polypcore/iochannel.h \ - polypcore/socket-server.h \ - polypcore/socket-client.h \ - polypcore/parseaddr.h \ - polypcore/packet.h \ - polypcore/pstream.h \ - polypcore/ioline.h \ - polypcore/cli.h \ - polypcore/protocol-cli.h \ - polypcore/tagstruct.h \ - polypcore/pstream-util.h \ - polypcore/pdispatch.h \ - polypcore/authkey.h \ - polypcore/authkey-prop.h \ - polypcore/strlist.h \ - polypcore/protocol-simple.h \ - polypcore/esound.h \ - polypcore/protocol-esound.h \ - polypcore/native-common.h \ - polypcore/protocol-native.h \ - polypcore/protocol-http.h +pulsecoreinclude_HEADERS += \ + pulsecore/socket-util.h \ + pulsecore/iochannel.h \ + pulsecore/socket-server.h \ + pulsecore/socket-client.h \ + pulsecore/parseaddr.h \ + pulsecore/packet.h \ + pulsecore/pstream.h \ + pulsecore/ioline.h \ + pulsecore/cli.h \ + pulsecore/protocol-cli.h \ + pulsecore/tagstruct.h \ + pulsecore/pstream-util.h \ + pulsecore/pdispatch.h \ + pulsecore/authkey.h \ + pulsecore/authkey-prop.h \ + pulsecore/strlist.h \ + pulsecore/protocol-simple.h \ + pulsecore/esound.h \ + pulsecore/protocol-esound.h \ + pulsecore/native-common.h \ + pulsecore/protocol-native.h \ + pulsecore/protocol-http.h ### Warning! Due to an obscure bug in libtool/automake it is required ### that the libraries in modlibexec_LTLIBRARIES are specified in-order, @@ -658,114 +658,114 @@ modlibexec_LTLIBRARIES += \ endif if HAVE_X11 -polypcoreinclude_HEADERS += \ - polypcore/x11wrap.h \ - polypcore/x11prop.h +pulsecoreinclude_HEADERS += \ + pulsecore/x11wrap.h \ + pulsecore/x11prop.h modlibexec_LTLIBRARIES += \ libx11wrap.la \ libx11prop.la endif -libprotocol_simple_la_SOURCES = polypcore/protocol-simple.c polypcore/protocol-simple.h +libprotocol_simple_la_SOURCES = pulsecore/protocol-simple.c pulsecore/protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version -libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-server.la libiochannel.la +libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-server.la libiochannel.la libsocket_server_la_SOURCES = \ - polypcore/inet_ntop.c polypcore/inet_ntop.h \ - polypcore/inet_pton.c polypcore/inet_pton.h \ - polypcore/socket-server.c polypcore/socket-server.h + pulsecore/inet_ntop.c pulsecore/inet_ntop.h \ + pulsecore/inet_pton.c pulsecore/inet_pton.h \ + pulsecore/socket-server.c pulsecore/socket-server.h libsocket_server_la_LDFLAGS = -avoid-version -libsocket_server_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS) +libsocket_server_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS) -libsocket_client_la_SOURCES = polypcore/socket-client.c polypcore/socket-client.h +libsocket_client_la_SOURCES = pulsecore/socket-client.c pulsecore/socket-client.h libsocket_client_la_LDFLAGS = -avoid-version -libsocket_client_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS) $(WINSOCK_LIBS) +libsocket_client_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS) $(WINSOCK_LIBS) libsocket_client_la_CFLAGS = $(AM_CFLAGS) $(LIBASYNCNS_CFLAGS) -libparseaddr_la_SOURCES = polypcore/parseaddr.c polypcore/parseaddr.h +libparseaddr_la_SOURCES = pulsecore/parseaddr.c pulsecore/parseaddr.h libparseaddr_la_LDFLAGS = -avoid-version -libparseaddr_la_LIBADD = $(AM_LIBADD) libpolypcore.la +libparseaddr_la_LIBADD = $(AM_LIBADD) libpulsecore.la -libpstream_la_SOURCES = polypcore/pstream.c polypcore/pstream.h +libpstream_la_SOURCES = pulsecore/pstream.c pulsecore/pstream.h libpstream_la_LDFLAGS = -avoid-version -libpstream_la_LIBADD = $(AM_LIBADD) libpolypcore.la libpacket.la libiochannel.la $(WINSOCK_LIBS) +libpstream_la_LIBADD = $(AM_LIBADD) libpulsecore.la libpacket.la libiochannel.la $(WINSOCK_LIBS) -libpstream_util_la_SOURCES = polypcore/pstream-util.c polypcore/pstream-util.h +libpstream_util_la_SOURCES = pulsecore/pstream-util.c pulsecore/pstream-util.h libpstream_util_la_LDFLAGS = -avoid-version libpstream_util_la_LIBADD = $(AM_LIBADD) libpacket.la libpstream.la libtagstruct.la -libpdispatch_la_SOURCES = polypcore/pdispatch.c polypcore/pdispatch.h +libpdispatch_la_SOURCES = pulsecore/pdispatch.c pulsecore/pdispatch.h libpdispatch_la_LDFLAGS = -avoid-version -libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la libpolypcore.la +libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la libpulsecore.la -libiochannel_la_SOURCES = polypcore/iochannel.c polypcore/iochannel.h +libiochannel_la_SOURCES = pulsecore/iochannel.c pulsecore/iochannel.h libiochannel_la_LDFLAGS = -avoid-version -libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpolypcore.la $(WINSOCK_LIBS) +libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpulsecore.la $(WINSOCK_LIBS) -libpacket_la_SOURCES = polypcore/packet.c polypcore/packet.h +libpacket_la_SOURCES = pulsecore/packet.c pulsecore/packet.h libpacket_la_LDFLAGS = -avoid-version -libpacket_la_LIBADD = $(AM_LIBADD) libpolypcore.la +libpacket_la_LIBADD = $(AM_LIBADD) libpulsecore.la -libioline_la_SOURCES = polypcore/ioline.c polypcore/ioline.h +libioline_la_SOURCES = pulsecore/ioline.c pulsecore/ioline.h libioline_la_LDFLAGS = -avoid-version -libioline_la_LIBADD = $(AM_LIBADD) libiochannel.la libpolypcore.la +libioline_la_LIBADD = $(AM_LIBADD) libiochannel.la libpulsecore.la -libcli_la_SOURCES = polypcore/cli.c polypcore/cli.h +libcli_la_SOURCES = pulsecore/cli.c pulsecore/cli.h libcli_la_CPPFLAGS = $(AM_CPPFLAGS) libcli_la_LDFLAGS = -avoid-version -libcli_la_LIBADD = $(AM_LIBADD) libiochannel.la libioline.la libpolypcore.la +libcli_la_LIBADD = $(AM_LIBADD) libiochannel.la libioline.la libpulsecore.la -libstrlist_la_SOURCES = polypcore/strlist.c polypcore/strlist.h +libstrlist_la_SOURCES = pulsecore/strlist.c pulsecore/strlist.h libstrlist_la_LDFLAGS = -avoid-version -libstrlist_la_LIBADD = $(AM_LIBADD) libpolypcore.la +libstrlist_la_LIBADD = $(AM_LIBADD) libpulsecore.la -libprotocol_cli_la_SOURCES = polypcore/protocol-cli.c polypcore/protocol-cli.h +libprotocol_cli_la_SOURCES = pulsecore/protocol-cli.c pulsecore/protocol-cli.h libprotocol_cli_la_LDFLAGS = -avoid-version -libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la libpolypcore.la +libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la libpulsecore.la -libprotocol_http_la_SOURCES = polypcore/protocol-http.c polypcore/protocol-http.h +libprotocol_http_la_SOURCES = pulsecore/protocol-http.c pulsecore/protocol-http.h libprotocol_http_la_LDFLAGS = -avoid-version -libprotocol_http_la_LIBADD = $(AM_LIBADD) libsocket-server.la libioline.la libpolypcore.la libiochannel.la +libprotocol_http_la_LIBADD = $(AM_LIBADD) libsocket-server.la libioline.la libpulsecore.la libiochannel.la -libprotocol_native_la_SOURCES = polypcore/protocol-native.c polypcore/protocol-native.h polypcore/native-common.h +libprotocol_native_la_SOURCES = pulsecore/protocol-native.c pulsecore/protocol-native.h pulsecore/native-common.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la libpolypcore.la libiochannel.la +libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la libpulsecore.la libiochannel.la -libtagstruct_la_SOURCES = polypcore/tagstruct.c polypcore/tagstruct.h +libtagstruct_la_SOURCES = pulsecore/tagstruct.c pulsecore/tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version -libtagstruct_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(WINSOCK_LIBS) +libtagstruct_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(WINSOCK_LIBS) -libprotocol_esound_la_SOURCES = polypcore/protocol-esound.c polypcore/protocol-esound.h polypcore/esound.h +libprotocol_esound_la_SOURCES = pulsecore/protocol-esound.c pulsecore/protocol-esound.h pulsecore/esound.h libprotocol_esound_la_LDFLAGS = -avoid-version -libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la libpolypcore.la +libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la libpulsecore.la -libauthkey_la_SOURCES = polypcore/authkey.c polypcore/authkey.h +libauthkey_la_SOURCES = pulsecore/authkey.c pulsecore/authkey.h libauthkey_la_LDFLAGS = -avoid-version -libauthkey_la_LIBADD = $(AM_LIBADD) libpolypcore.la +libauthkey_la_LIBADD = $(AM_LIBADD) libpulsecore.la -libauthkey_prop_la_SOURCES = polypcore/authkey-prop.c polypcore/authkey-prop.h +libauthkey_prop_la_SOURCES = pulsecore/authkey-prop.c pulsecore/authkey-prop.h libauthkey_prop_la_LDFLAGS = -avoid-version -libauthkey_prop_la_LIBADD = $(AM_LIBADD) libpolypcore.la +libauthkey_prop_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket_util_la_SOURCES = \ - polypcore/inet_ntop.c polypcor/inet_ntop.h \ - polypcore/socket-util.c polypcore/socket-util.h + pulsecore/inet_ntop.c pulsecor/inet_ntop.h \ + pulsecore/socket-util.c pulsecore/socket-util.h libsocket_util_la_LDFLAGS = -avoid-version -libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) libpolypcore.la +libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) libpulsecore.la librtp_la_SOURCES = modules/rtp/rtp.c modules/rtp/rtp.h modules/rtp/sdp.c modules/rtp/sdp.h modules/rtp/sap.c modules/rtp/sap.h librtp_la_LDFLAGS = -avoid-version -librtp_la_LIBADD = $(AM_LIBADD) libpolypcore.la +librtp_la_LIBADD = $(AM_LIBADD) libpulsecore.la # X11 -libx11wrap_la_SOURCES = polypcore/x11wrap.c polypcore/x11wrap.h +libx11wrap_la_SOURCES = pulsecore/x11wrap.c pulsecore/x11wrap.h libx11wrap_la_LDFLAGS = -avoid-version libx11wrap_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) -libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libpolypcore.la +libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libpulsecore.la -libx11prop_la_SOURCES = polypcore/x11prop.c polypcore/x11prop.h +libx11prop_la_SOURCES = pulsecore/x11prop.c pulsecore/x11prop.h libx11prop_la_LDFLAGS = -avoid-version libx11prop_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) @@ -932,127 +932,127 @@ $(SYMDEF_FILES): modules/module-defs.h.m4 module_simple_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la +module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-simple.la libsocket-server.la module_simple_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version -module_simple_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la libsocket-util.la +module_simple_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-simple.la libsocket-server.la libsocket-util.la # CLI protocol module_cli_la_SOURCES = modules/module-cli.c module_cli_la_LDFLAGS = -module -avoid-version -module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la libpolypcore.la +module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la libpulsecore.la module_cli_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la +module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-cli.la libsocket-server.la module_cli_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version -module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la libsocket-util.la +module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-cli.la libsocket-server.la libsocket-util.la # HTTP protocol module_http_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_http_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) module_http_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la +module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-http.la libsocket-server.la module_http_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) module_http_protocol_unix_la_LDFLAGS = -module -avoid-version -module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la libsocket-util.la +module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-http.la libsocket-server.la libsocket-util.la # Native protocol module_native_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la +module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la module_native_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) module_native_protocol_unix_la_LDFLAGS = -module -avoid-version -module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la libsocket-util.la +module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la module_native_protocol_fd_la_SOURCES = modules/module-native-protocol-fd.c module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS) module_native_protocol_fd_la_LDFLAGS = -module -avoid-version -module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la libsocket-util.la libiochannel.la +module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la libiochannel.la # EsounD protocol module_esound_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version -module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la +module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la module_esound_protocol_unix_la_SOURCES = modules/module-protocol-stub.c module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version -module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la libsocket-util.la +module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la libsocket-util.la module_esound_compat_spawnfd_la_SOURCES = modules/module-esound-compat-spawnfd.c module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version -module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_esound_compat_spawnpid_la_SOURCES = modules/module-esound-compat-spawnpid.c module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version -module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_esound_sink_la_SOURCES = modules/module-esound-sink.c module_esound_sink_la_LDFLAGS = -module -avoid-version -module_esound_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-client.la libauthkey.la +module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-client.la libauthkey.la # Pipes module_pipe_sink_la_SOURCES = modules/module-pipe-sink.c module_pipe_sink_la_LDFLAGS = -module -avoid-version -module_pipe_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la +module_pipe_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la module_pipe_source_la_SOURCES = modules/module-pipe-source.c module_pipe_source_la_LDFLAGS = -module -avoid-version -module_pipe_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la +module_pipe_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la # Fake sources/sinks module_sine_la_SOURCES = modules/module-sine.c module_sine_la_LDFLAGS = -module -avoid-version -module_sine_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_sine_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_null_sink_la_SOURCES = modules/module-null-sink.c module_null_sink_la_LDFLAGS = -module -avoid-version -module_null_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_null_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la # Couplings module_combine_la_SOURCES = modules/module-combine.c module_combine_la_LDFLAGS = -module -avoid-version -module_combine_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_combine_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_match_la_SOURCES = modules/module-match.c module_match_la_LDFLAGS = -module -avoid-version -module_match_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_match_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_tunnel_sink_la_SOURCES = modules/module-tunnel.c module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) module_tunnel_sink_la_LDFLAGS = -module -avoid-version -module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la +module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la module_tunnel_source_la_SOURCES = modules/module-tunnel.c module_tunnel_source_la_LDFLAGS = -module -avoid-version -module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la +module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la # X11 module_x11_bell_la_SOURCES = modules/module-x11-bell.c module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_bell_la_LDFLAGS = -module -avoid-version -module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libpolypcore.la +module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libpulsecore.la module_x11_publish_la_SOURCES = modules/module-x11-publish.c module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) @@ -1063,7 +1063,7 @@ module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EX liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h liboss_util_la_LDFLAGS = -avoid-version -liboss_util_la_LIBADD = libpolypcore.la +liboss_util_la_LIBADD = libpulsecore.la module_oss_la_SOURCES = modules/module-oss.c module_oss_la_LDFLAGS = -module -avoid-version @@ -1071,23 +1071,23 @@ module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la module_oss_mmap_la_SOURCES = modules/module-oss-mmap.c module_oss_mmap_la_LDFLAGS = -module -avoid-version -module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la libpolypcore.la +module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la libpulsecore.la # ALSA libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h libalsa_util_la_LDFLAGS = -avoid-version -libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libpolypcore.la +libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libpulsecore.la libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) module_alsa_sink_la_SOURCES = modules/module-alsa-sink.c module_alsa_sink_la_LDFLAGS = -module -avoid-version -module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpolypcore.la +module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) module_alsa_source_la_SOURCES = modules/module-alsa-source.c module_alsa_source_la_LDFLAGS = -module -avoid-version -module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpolypcore.la +module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) # Solaris @@ -1100,75 +1100,75 @@ module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la libhowl_wrap_la_SOURCES = modules/howl-wrap.c modules/howl-wrap.h libhowl_wrap_la_LDFLAGS = -avoid-version -libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libpolypcore.la +libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libpulsecore.la libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) module_zeroconf_publish_la_SOURCES = modules/module-zeroconf-publish.c module_zeroconf_publish_la_LDFLAGS = -module -avoid-version -module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la libpolypcore.la +module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la libpulsecore.la module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) # LIRC module_lirc_la_SOURCES = modules/module-lirc.c module_lirc_la_LDFLAGS = -module -avoid-version -module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) libpolypcore.la +module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) libpulsecore.la module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS) # Linux evdev module_mmkbd_evdev_la_SOURCES = modules/module-mmkbd-evdev.c module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version -module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS) # Windows waveout module_waveout_la_SOURCES = modules/module-waveout.c module_waveout_la_LDFLAGS = -module -avoid-version -module_waveout_la_LIBADD = $(AM_LIBADD) libpolypcore.la -lwinmm +module_waveout_la_LIBADD = $(AM_LIBADD) libpulsecore.la -lwinmm module_waveout_la_CFLAGS = $(AM_CFLAGS) # Hardware autodetection module module_detect_la_SOURCES = modules/module-detect.c module_detect_la_LDFLAGS = -module -avoid-version -module_detect_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_detect_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_detect_la_CFLAGS = $(AM_CFLAGS) # Volume restore module module_volume_restore_la_SOURCES = modules/module-volume-restore.c module_volume_restore_la_LDFLAGS = -module -avoid-version -module_volume_restore_la_LIBADD = $(AM_LIBADD) libpolypcore.la +module_volume_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_volume_restore_la_CFLAGS = $(AM_CFLAGS) # RTP modules module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c module_rtp_send_la_LDFLAGS = -module -avoid-version -module_rtp_send_la_LIBADD = $(AM_LIBADD) libpolypcore.la librtp.la +module_rtp_send_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la module_rtp_send_la_CFLAGS = $(AM_CFLAGS) module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c module_rtp_recv_la_LDFLAGS = -module -avoid-version -module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpolypcore.la librtp.la +module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) # JACK module_jack_sink_la_SOURCES = modules/module-jack-sink.c module_jack_sink_la_LDFLAGS = -module -avoid-version -module_jack_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(JACK_LIBS) +module_jack_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS) module_jack_sink_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS) module_jack_source_la_SOURCES = modules/module-jack-source.c module_jack_source_la_LDFLAGS = -module -avoid-version -module_jack_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(JACK_LIBS) +module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS) module_jack_source_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS) ################################### # Some minor stuff # ################################### -suid: polypaudio +suid: pulse chown root $< chmod u+s $< @@ -1179,7 +1179,7 @@ esdcompat: daemon/esdcompat.in Makefile -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ -client.conf: polyp/client.conf.in Makefile +client.conf: pulse/client.conf.in Makefile sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ if OS_IS_WIN32 @@ -1195,11 +1195,11 @@ daemon.conf: daemon/daemon.conf.in Makefile -e 's,@DEFAULT_CONFIG_FILE\@,$(DEFAULT_CONFIG_DIR),g' < $< > $@ install-exec-hook: - chown root $(DESTDIR)$(bindir)/polypaudio ; true - chmod u+s $(DESTDIR)$(bindir)/polypaudio + chown root $(DESTDIR)$(bindir)/pulseaudio ; true + chmod u+s $(DESTDIR)$(bindir)/pulseaudio ln -sf pacat $(DESTDIR)$(bindir)/parec rm -f $(DESTDIR)$(modlibexecdir)/*.a - rm -f $(DESTDIR)$(libdir)/libpolypdsp.a - rm -f $(DESTDIR)$(libdir)/libpolypdsp.la + rm -f $(DESTDIR)$(libdir)/libpulsedsp.a + rm -f $(DESTDIR)$(libdir)/libpulsedsp.la .PHONY: utils/padsp diff --git a/src/daemon/Makefile b/src/daemon/Makefile index cd2a5c9a6..c110232d3 120000 --- a/src/daemon/Makefile +++ b/src/daemon/Makefile @@ -1 +1 @@ -../polyp/Makefile \ No newline at end of file +../pulse/Makefile \ No newline at end of file diff --git a/src/daemon/caps.c b/src/daemon/caps.c index 5e24da821..dc74bc7d0 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -32,9 +32,9 @@ #include #endif -#include +#include -#include +#include #include "caps.h" diff --git a/src/daemon/caps.h b/src/daemon/caps.h index 3bb861d1d..8a618286f 100644 --- a/src/daemon/caps.h +++ b/src/daemon/caps.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index b71be2e67..a106dc090 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,10 +30,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "cmdline.h" diff --git a/src/daemon/cmdline.h b/src/daemon/cmdline.h index e2eaf0d2f..25453e558 100644 --- a/src/daemon/cmdline.h +++ b/src/daemon/cmdline.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index d537b9db0..a8c9d3f5a 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -23,11 +23,11 @@ #include #endif -#include +#include -#include -#include -#include +#include +#include +#include #include "cpulimit.h" diff --git a/src/daemon/cpulimit.h b/src/daemon/cpulimit.h index f3c5534d1..21bdd17ba 100644 --- a/src/daemon/cpulimit.h +++ b/src/daemon/cpulimit.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include -/* This kills the polypaudio process if it eats more than 70% of the +/* This kills the pulseaudio process if it eats more than 70% of the * CPU time. This is build around setrlimit() and SIGXCPU. It is handy * in case of using SCHED_FIFO which may freeze the whole machine */ diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 2d8d9558c..fd83f28f2 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,19 +29,19 @@ #include #include -#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "daemon-conf.h" #ifndef DEFAULT_CONFIG_DIR # ifndef OS_IS_WIN32 -# define DEFAULT_CONFIG_DIR "/etc/polypaudio" +# define DEFAULT_CONFIG_DIR "/etc/pulseaudio" # else # define DEFAULT_CONFIG_DIR "%POLYP_ROOT%" # endif @@ -54,9 +54,9 @@ #endif #define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR PATH_SEP "default.pa" -#define DEFAULT_SCRIPT_FILE_USER ".polypaudio" PATH_SEP "default.pa" +#define DEFAULT_SCRIPT_FILE_USER ".pulseaudio" PATH_SEP "default.pa" #define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" -#define DEFAULT_CONFIG_FILE_USER ".polypaudio" PATH_SEP "daemon.conf" +#define DEFAULT_CONFIG_FILE_USER ".pulseaudio" PATH_SEP "daemon.conf" #define ENV_SCRIPT_FILE "POLYP_SCRIPT" #define ENV_CONFIG_FILE "POLYP_CONFIG" diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index d51314197..dd5d7fb84 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -4,25 +4,25 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include /* The actual command to execute */ typedef enum pa_daemon_conf_cmd { diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index d5373018d..30bf3ca16 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -1,23 +1,23 @@ # $Id$ # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify +# PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software +# along with PulseAudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -## Configuration file for the polypaudio daemon. Default values are +## Configuration file for the pulseaudio daemon. Default values are ## commented out. Use either ; or # for commenting # Extra verbositiy @@ -69,9 +69,9 @@ ## hand it has the worst quality of all. ; resample-method = sinc-fastest -## Create a PID file in /tmp/polypaudio-$USER/pid. Of this is enabled -## you may use commands like "polypaudio --kill" or "polypaudio -## --check". If you are planning to start more than one polypaudio +## Create a PID file in /tmp/pulseaudio-$USER/pid. Of this is enabled +## you may use commands like "pulseaudio --kill" or "pulseaudio +## --check". If you are planning to start more than one pulseaudio ## process per user, you better disable this option since it ## effectively disables multiple instances. ; use-pid-file = 1 diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index cba0172fc..623cd1148 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -1,20 +1,20 @@ #!@POLYPAUDIO_BINARY@ -nF # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify it +# PulseAudio is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software Foundation, +# along with PulseAudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/src/daemon/default.pa.win32 b/src/daemon/default.pa.win32 index 3478adab1..d5a1e183d 100644 --- a/src/daemon/default.pa.win32 +++ b/src/daemon/default.pa.win32 @@ -1,18 +1,18 @@ # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify it +# PulseAudio is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software Foundation, +# along with PulseAudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c index d56bb7980..06734ea63 100644 --- a/src/daemon/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,9 +29,9 @@ #include #include -#include +#include -#include +#include #include "dumpmodules.h" diff --git a/src/daemon/dumpmodules.h b/src/daemon/dumpmodules.h index 968d2de95..05cd86e02 100644 --- a/src/daemon/dumpmodules.h +++ b/src/daemon/dumpmodules.h @@ -4,20 +4,20 @@ /* $Id*/ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/daemon/esdcompat.in b/src/daemon/esdcompat.in index 76023f52a..673f8c8ac 100755 --- a/src/daemon/esdcompat.in +++ b/src/daemon/esdcompat.in @@ -2,20 +2,20 @@ # $Id$ # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify +# PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software +# along with PulseAudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. diff --git a/src/daemon/main.c b/src/daemon/main.c index 16cc0f5ed..5e7330a56 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -48,24 +48,24 @@ #include #endif -#include "../polypcore/winsock.h" +#include "../pulsecore/winsock.h" -#include -#include -#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "cmdline.h" #include "cpulimit.h" @@ -199,7 +199,7 @@ int main(int argc, char *argv[]) { pa_random_seed(); - pa_log_set_ident("polypaudio"); + pa_log_set_ident("pulseaudio"); conf = pa_daemon_conf_new(); diff --git a/src/depmod.py b/src/depmod.py index 7bb223b19..a20bc7c05 100755 --- a/src/depmod.py +++ b/src/depmod.py @@ -1,20 +1,20 @@ #!/usr/bin/python # $Id$ # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify +# PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software +# along with PulseAudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. diff --git a/src/modules/Makefile b/src/modules/Makefile index cd2a5c9a6..c110232d3 120000 --- a/src/modules/Makefile +++ b/src/modules/Makefile @@ -1 +1 @@ -../polyp/Makefile \ No newline at end of file +../pulse/Makefile \ No newline at end of file diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index fafcac489..04a2d849f 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,10 +26,10 @@ #include #include -#include -#include +#include +#include -#include +#include #include "alsa-util.h" diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 83d1481f2..215844b40 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -4,30 +4,30 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include +#include +#include -#include +#include struct pa_alsa_fdlist; diff --git a/src/modules/howl-wrap.c b/src/modules/howl-wrap.c index 467ab9e24..e56fca3e7 100644 --- a/src/modules/howl-wrap.c +++ b/src/modules/howl-wrap.c @@ -1,30 +1,30 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include +#include -#include -#include +#include +#include #include "howl-wrap.h" diff --git a/src/modules/howl-wrap.h b/src/modules/howl-wrap.h index a4b26490d..506c0b68d 100644 --- a/src/modules/howl-wrap.h +++ b/src/modules/howl-wrap.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include +#include typedef struct pa_howl_wrapper pa_howl_wrapper; diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 620047b77..d49b34076 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -34,16 +34,16 @@ #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include "alsa-util.h" #include "module-alsa-sink-symdef.h" diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 0999c65fc..c4e8689ce 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -34,17 +34,17 @@ #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "alsa-util.h" #include "module-alsa-source-symdef.h" diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c index ce50a46bb..2eef5c46d 100644 --- a/src/modules/module-cli.c +++ b/src/modules/module-cli.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,12 +27,12 @@ #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include "module-cli-symdef.h" diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 037cbaf71..4e3dd555e 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,18 +26,18 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-combine-symdef.h" diff --git a/src/modules/module-defs.h.m4 b/src/modules/module-defs.h.m4 index 8f10d6599..c961412d8 100644 --- a/src/modules/module-defs.h.m4 +++ b/src/modules/module-defs.h.m4 @@ -8,8 +8,8 @@ define(`gen_symbol', `#define $1 'module_name`_LTX_$1')dnl #ifndef incmacro #define incmacro -#include -#include +#include +#include gen_symbol(pa__init) gen_symbol(pa__done) diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 3512e31c9..3e4d2bf63 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -33,13 +33,13 @@ #include #include -#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "module-detect-symdef.h" diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index 861e25709..c4bc342a6 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,11 +28,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "module-esound-compat-spawnfd-symdef.h" diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index 7b47bb0ac..3108baf7f 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -1,19 +1,19 @@ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,11 +28,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "module-esound-compat-spawnpid-symdef.h" diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 53a9411a4..75a47b04e 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -33,18 +33,18 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-esound-sink-symdef.h" diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index fc2bfc452..c6a161ff6 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -36,16 +36,16 @@ #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-jack-sink-symdef.h" @@ -261,7 +261,7 @@ int pa__init(pa_core *c, pa_module*m) { } server_name = pa_modargs_get_value(ma, "server_name", NULL); - client_name = pa_modargs_get_value(ma, "client_name", "polypaudio"); + client_name = pa_modargs_get_value(ma, "client_name", "pulseaudio"); u = pa_xnew0(struct userdata, 1); m->userdata = u; diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index ca9560a68..6f31f6c3a 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -36,16 +36,16 @@ #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-jack-source-symdef.h" @@ -259,7 +259,7 @@ int pa__init(pa_core *c, pa_module*m) { } server_name = pa_modargs_get_value(ma, "server_name", NULL); - client_name = pa_modargs_get_value(ma, "client_name", "polypaudio"); + client_name = pa_modargs_get_value(ma, "client_name", "pulseaudio"); u = pa_xnew0(struct userdata, 1); m->userdata = u; diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index 009c2e466..a93a3b927 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,13 +30,13 @@ #include #include -#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "module-lirc-symdef.h" @@ -203,7 +203,7 @@ int pa__init(pa_core *c, pa_module*m) { u->lirc_fd = -1; u->mute_toggle_save = 0; - if ((u->lirc_fd = lirc_init((char*) pa_modargs_get_value(ma, "appname", "polypaudio"), 1)) < 0) { + if ((u->lirc_fd = lirc_init((char*) pa_modargs_get_value(ma, "appname", "pulseaudio"), 1)) < 0) { pa_log(__FILE__": lirc_init() failed."); goto fail; } diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 02d75e7ef..ddeda7347 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -32,16 +32,16 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-match-symdef.h" @@ -53,11 +53,11 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" #ifndef DEFAULT_CONFIG_DIR -#define DEFAULT_CONFIG_DIR "/etc/polypaudio" +#define DEFAULT_CONFIG_DIR "/etc/pulseaudio" #endif #define DEFAULT_MATCH_TABLE_FILE DEFAULT_CONFIG_DIR"/match.table" -#define DEFAULT_MATCH_TABLE_FILE_USER ".polypaudio/match.table" +#define DEFAULT_MATCH_TABLE_FILE_USER ".pulseaudio/match.table" static const char* const valid_modargs[] = { "table", diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index ee2c6bffd..ddbf16d25 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -33,15 +33,15 @@ #include -#include +#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "module-mmkbd-evdev-symdef.h" diff --git a/src/modules/module-native-protocol-fd.c b/src/modules/module-native-protocol-fd.c index e3caf55a0..9e1cac096 100644 --- a/src/modules/module-native-protocol-fd.c +++ b/src/modules/module-native-protocol-fd.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,11 +27,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "module-native-protocol-fd-symdef.h" diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index a1555e672..8cfce8fec 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -33,15 +33,15 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include "module-null-sink-symdef.h" diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 5cf6228f2..fcc89c845 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -36,17 +36,17 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "oss-util.h" #include "module-oss-mmap-symdef.h" diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 887246733..5a80661ec 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -35,17 +35,17 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "oss-util.h" #include "module-oss-symdef.h" diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 01598e388..4878a1a10 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -33,15 +33,15 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "module-pipe-sink-symdef.h" diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index be2a28d51..f2f214c7b 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -33,15 +33,15 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "module-pipe-source-symdef.h" diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 2b4f303b1..207287661 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -40,18 +40,18 @@ #include #endif -#include "../polypcore/winsock.h" +#include "../pulsecore/winsock.h" -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" @@ -62,10 +62,10 @@ #endif #if defined(USE_PROTOCOL_SIMPLE) - #include + #include #define protocol_new pa_protocol_simple_new #define protocol_free pa_protocol_simple_free - #define TCPWRAP_SERVICE "polypaudio-simple" + #define TCPWRAP_SERVICE "pulseaudio-simple" #define IPV4_PORT 4711 #define UNIX_SOCKET "simple" #define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record", @@ -77,10 +77,10 @@ PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("rate= format= channels= sink= source= playback= record= "SOCKET_USAGE) #elif defined(USE_PROTOCOL_CLI) - #include + #include #define protocol_new pa_protocol_cli_new #define protocol_free pa_protocol_cli_free - #define TCPWRAP_SERVICE "polypaudio-cli" + #define TCPWRAP_SERVICE "pulseaudio-cli" #define IPV4_PORT 4712 #define UNIX_SOCKET "cli" #define MODULE_ARGUMENTS @@ -92,10 +92,10 @@ PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE(SOCKET_USAGE) #elif defined(USE_PROTOCOL_HTTP) - #include + #include #define protocol_new pa_protocol_http_new #define protocol_free pa_protocol_http_free - #define TCPWRAP_SERVICE "polypaudio-http" + #define TCPWRAP_SERVICE "pulseaudio-http" #define IPV4_PORT 4714 #define UNIX_SOCKET "http" #define MODULE_ARGUMENTS @@ -107,10 +107,10 @@ PA_MODULE_DESCRIPTION("HTTP "SOCKET_DESCRIPTION) PA_MODULE_USAGE(SOCKET_USAGE) #elif defined(USE_PROTOCOL_NATIVE) - #include + #include #define protocol_new pa_protocol_native_new #define protocol_free pa_protocol_native_free - #define TCPWRAP_SERVICE "polypaudio-native" + #define TCPWRAP_SERVICE "pulseaudio-native" #define IPV4_PORT PA_NATIVE_DEFAULT_PORT #define UNIX_SOCKET PA_NATIVE_DEFAULT_UNIX_SOCKET #define MODULE_ARGUMENTS_COMMON "cookie", "auth-anonymous", @@ -131,8 +131,8 @@ PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("auth-anonymous= cookie= "AUTH_USAGE SOCKET_USAGE) #elif defined(USE_PROTOCOL_ESOUND) - #include - #include + #include + #include #define protocol_new pa_protocol_esound_new #define protocol_free pa_protocol_esound_free #define TCPWRAP_SERVICE "esound" diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index 15b6c8a94..f4392b9a0 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,13 +27,13 @@ #include #include -#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "module-sine-symdef.h" diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 8670bb354..12c4a3ffd 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -40,18 +40,18 @@ #include #include -#include -#include -#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-solaris-symdef.h" diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index bf1fafb3d..bf2627a7e 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -31,24 +31,24 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef TUNNEL_SINK #include "module-tunnel-sink-symdef.h" diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 435f0c965..ede2fcf28 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -32,17 +32,17 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-volume-restore-symdef.h" @@ -53,7 +53,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#define DEFAULT_VOLUME_TABLE_FILE ".polypaudio/volume.table" +#define DEFAULT_VOLUME_TABLE_FILE ".pulseaudio/volume.table" static const char* const valid_modargs[] = { "table", diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index ce9ea84d8..2bd4905ac 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,17 +27,17 @@ #include #include -#include +#include -#include +#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "module-waveout-symdef.h" diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index 2b891bc12..7ac5f558b 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -31,15 +31,15 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "module-x11-bell-symdef.h" diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index 70d750384..991630354 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -32,23 +32,23 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-x11-publish-symdef.h" diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index c07c95f39..14cbef46a 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,20 +29,20 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "../polypcore/endianmacros.h" +#include "../pulsecore/endianmacros.h" #include "howl-wrap.h" @@ -53,9 +53,9 @@ PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("port=") -#define SERVICE_NAME_SINK "_polypaudio-sink._tcp" -#define SERVICE_NAME_SOURCE "_polypaudio-source._tcp" -#define SERVICE_NAME_SERVER "_polypaudio-server._tcp" +#define SERVICE_NAME_SINK "_pulseaudio-sink._tcp" +#define SERVICE_NAME_SOURCE "_pulseaudio-source._tcp" +#define SERVICE_NAME_SERVER "_pulseaudio-server._tcp" static const char* const valid_modargs[] = { "port", diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index ff337a5ce..f4cc45de3 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -34,9 +34,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include "oss-util.h" diff --git a/src/modules/oss-util.h b/src/modules/oss-util.h index c652d2a10..12855f4e2 100644 --- a/src/modules/oss-util.h +++ b/src/modules/oss-util.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include int pa_oss_open(const char *device, int *mode, int* pcaps); int pa_oss_auto_format(int fd, pa_sample_spec *ss); diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index c448502ee..932da8493 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -1,19 +1,19 @@ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -31,20 +31,20 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-rtp-recv-symdef.h" diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 4359d00d4..00da64d54 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -32,20 +32,20 @@ #include #include -#include -#include -#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-rtp-send-symdef.h" diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index 52a1819c6..ee037d421 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -36,8 +36,8 @@ #include #endif -#include -#include +#include +#include #include "rtp.h" diff --git a/src/modules/rtp/rtp.h b/src/modules/rtp/rtp.h index 49da155b6..35fbbd357 100644 --- a/src/modules/rtp/rtp.h +++ b/src/modules/rtp/rtp.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,8 +25,8 @@ #include #include #include -#include -#include +#include +#include typedef struct pa_rtp_context { int fd; diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index 134bab095..3814a1c3d 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -38,11 +38,11 @@ #include #endif -#include +#include -#include -#include -#include +#include +#include +#include #include "sap.h" #include "sdp.h" diff --git a/src/modules/rtp/sap.h b/src/modules/rtp/sap.h index b11b1dd7b..987403e37 100644 --- a/src/modules/rtp/sap.h +++ b/src/modules/rtp/sap.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,8 +25,8 @@ #include #include #include -#include -#include +#include +#include typedef struct pa_sap_context { int fd; diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index 5ec5090d6..cada636a4 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -31,10 +31,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "sdp.h" #include "rtp.h" diff --git a/src/modules/rtp/sdp.h b/src/modules/rtp/sdp.h index 2aa18056e..b95ca633e 100644 --- a/src/modules/rtp/sdp.h +++ b/src/modules/rtp/sdp.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,7 +26,7 @@ #include #include -#include +#include #define PA_SDP_HEADER "v=0\n" diff --git a/src/polypcore/Makefile b/src/polypcore/Makefile deleted file mode 120000 index cd2a5c9a6..000000000 --- a/src/polypcore/Makefile +++ /dev/null @@ -1 +0,0 @@ -../polyp/Makefile \ No newline at end of file diff --git a/src/polyp/Makefile b/src/pulse/Makefile similarity index 100% rename from src/polyp/Makefile rename to src/pulse/Makefile diff --git a/src/polyp/browser.c b/src/pulse/browser.c similarity index 94% rename from src/polyp/browser.c rename to src/pulse/browser.c index 69760d8d0..d063465dc 100644 --- a/src/polyp/browser.c +++ b/src/pulse/browser.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -22,16 +22,16 @@ #include #include -#include +#include -#include -#include +#include +#include #include "browser.h" -#define SERVICE_NAME_SINK "_polypaudio-sink._tcp." -#define SERVICE_NAME_SOURCE "_polypaudio-source._tcp." -#define SERVICE_NAME_SERVER "_polypaudio-server._tcp." +#define SERVICE_NAME_SINK "_pulseaudio-sink._tcp." +#define SERVICE_NAME_SOURCE "_pulseaudio-source._tcp." +#define SERVICE_NAME_SERVER "_pulseaudio-server._tcp." struct pa_browser { int ref; diff --git a/src/polyp/browser.h b/src/pulse/browser.h similarity index 83% rename from src/polyp/browser.h rename to src/pulse/browser.h index 1ff58d8c7..2d20c6c0a 100644 --- a/src/polyp/browser.h +++ b/src/pulse/browser.h @@ -4,28 +4,28 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include -#include +#include +#include +#include +#include PA_C_DECL_BEGIN diff --git a/src/polyp/cdecl.h b/src/pulse/cdecl.h similarity index 82% rename from src/polyp/cdecl.h rename to src/pulse/cdecl.h index d51ae0266..6ac96687a 100644 --- a/src/polyp/cdecl.h +++ b/src/pulse/cdecl.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polyp/channelmap.c b/src/pulse/channelmap.c similarity index 97% rename from src/polyp/channelmap.c rename to src/pulse/channelmap.c index 653331ba1..a4f133723 100644 --- a/src/polyp/channelmap.c +++ b/src/pulse/channelmap.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,8 +28,8 @@ #include #include -#include -#include +#include +#include #include "channelmap.h" diff --git a/src/polyp/channelmap.h b/src/pulse/channelmap.h similarity index 96% rename from src/polyp/channelmap.h rename to src/pulse/channelmap.h index 645a8a388..8a39ade85 100644 --- a/src/polyp/channelmap.h +++ b/src/pulse/channelmap.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include /** \page channelmap Channel Maps * diff --git a/src/polyp/client-conf-x11.c b/src/pulse/client-conf-x11.c similarity index 85% rename from src/polyp/client-conf-x11.c rename to src/pulse/client-conf-x11.c index fb67df2f0..7eea5ae37 100644 --- a/src/polyp/client-conf-x11.c +++ b/src/pulse/client-conf-x11.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-13071 USA. ***/ @@ -29,11 +29,11 @@ #include #include -#include +#include -#include -#include -#include +#include +#include +#include #include "client-conf-x11.h" diff --git a/src/polyp/client-conf-x11.h b/src/pulse/client-conf-x11.h similarity index 78% rename from src/polyp/client-conf-x11.h rename to src/pulse/client-conf-x11.h index 64459224f..02e808be9 100644 --- a/src/polyp/client-conf-x11.h +++ b/src/pulse/client-conf-x11.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polyp/client-conf.c b/src/pulse/client-conf.c similarity index 90% rename from src/polyp/client-conf.c rename to src/pulse/client-conf.c index e1934ce14..752d0134a 100644 --- a/src/polyp/client-conf.c +++ b/src/pulse/client-conf.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,19 +29,19 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include +#include +#include +#include +#include #include "client-conf.h" #ifndef DEFAULT_CONFIG_DIR # ifndef OS_IS_WIN32 -# define DEFAULT_CONFIG_DIR "/etc/polypaudio" +# define DEFAULT_CONFIG_DIR "/etc/pulseaudio" # else # define DEFAULT_CONFIG_DIR "%POLYP_ROOT%" # endif @@ -54,7 +54,7 @@ #endif #define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "client.conf" -#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio" PATH_SEP "client.conf" +#define DEFAULT_CLIENT_CONFIG_FILE_USER ".pulseaudio" PATH_SEP "client.conf" #define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG" #define ENV_DEFAULT_SINK "POLYP_SINK" diff --git a/src/polyp/client-conf.h b/src/pulse/client-conf.h similarity index 82% rename from src/polyp/client-conf.h rename to src/pulse/client-conf.h index de3efae70..9d45af478 100644 --- a/src/polyp/client-conf.h +++ b/src/pulse/client-conf.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include -/* A structure containing configuration data for polypaudio clients. */ +/* A structure containing configuration data for pulseaudio clients. */ typedef struct pa_client_conf { char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; diff --git a/src/polyp/client.conf.in b/src/pulse/client.conf.in similarity index 69% rename from src/polyp/client.conf.in rename to src/pulse/client.conf.in index fbf645a49..d881c44e8 100644 --- a/src/polyp/client.conf.in +++ b/src/pulse/client.conf.in @@ -1,29 +1,29 @@ # $Id$ # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify +# PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software +# along with PulseAudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -## Configuration file for polypaudio clients. Default values are +## Configuration file for pulseaudio clients. Default values are ## commented out. Use either ; or # for commenting -## Path to the polypaudio daemon to run when autospawning. +## Path to the pulseaudio daemon to run when autospawning. ; daemon-binary = @POLYPAUDIO_BINARY@ -## Extra arguments to pass to the polypaudio daemon +## Extra arguments to pass to the pulseaudio daemon ; extra-arguments = --log-target=syslog --exit-idle-time=5 ## The default sink to connect to diff --git a/src/polyp/context.c b/src/pulse/context.c similarity index 97% rename from src/polyp/context.c rename to src/pulse/context.c index 68fb4bf3e..648024c38 100644 --- a/src/polyp/context.c +++ b/src/pulse/context.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -45,21 +45,21 @@ #include #endif -#include "../polypcore/winsock.h" +#include "../pulsecore/winsock.h" -#include -#include -#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "internal.h" diff --git a/src/polyp/context.h b/src/pulse/context.h similarity index 92% rename from src/polyp/context.h rename to src/pulse/context.h index 04e2af4dc..65d70e8b1 100644 --- a/src/polyp/context.h +++ b/src/pulse/context.h @@ -4,35 +4,35 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include /** \page async Asynchronous API * * \section overv_sec Overview * - * The asynchronous API is the native interface to the polypaudio library. + * The asynchronous API is the native interface to the pulseaudio library. * It allows full access to all available functions. This also means that * it is rather complex and can take some time to fully master. * @@ -52,10 +52,10 @@ * * To actually be able to use these functions, an implementation needs to * be coupled to the abstraction. There are three of these shipped with - * polypaudio, but any other can be used with a minimal ammount of work, + * pulseaudio, but any other can be used with a minimal ammount of work, * provided it supports the three basic events listed above. * - * The implementations shipped with polypaudio are: + * The implementations shipped with pulseaudio are: * * \li \subpage mainloop - A minimal but fast implementation based on poll(). * \li \subpage threaded_mainloop - A special version of the previous @@ -71,7 +71,7 @@ * * \section refcnt_sec Reference Counting * - * Almost all objects in polypaudio are reference counted. What that means + * Almost all objects in pulseaudio are reference counted. What that means * is that you rarely malloc() or free() any objects. Instead you increase * and decrease their reference counts. Whenever an object's reference * count reaches zero, that object gets destroy and any resources it uses @@ -89,7 +89,7 @@ * * \section context_sec Context * - * A context is the basic object for a connection to a polypaudio server. + * A context is the basic object for a connection to a pulseaudio server. * It multiplexes commands, data streams and events through a single * channel. * @@ -142,7 +142,7 @@ /** \file * Connection contexts for asynchrononous communication with a - * server. A pa_context object wraps a connection to a polypaudio + * server. A pa_context object wraps a connection to a pulseaudio * server using its native protocol. */ /** \example pacat.c diff --git a/src/polyp/def.h b/src/pulse/def.h similarity index 98% rename from src/polyp/def.h rename to src/pulse/def.h index 579971633..3a17f43bf 100644 --- a/src/polyp/def.h +++ b/src/pulse/def.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,8 +26,8 @@ #include #include -#include -#include +#include +#include /** \file * Global definitions */ @@ -66,7 +66,7 @@ typedef enum pa_operation_state { /** Some special flags for contexts. \since 0.8 */ typedef enum pa_context_flags { - PA_CONTEXT_NOAUTOSPAWN = 1 /**< Disabled autospawning of the polypaudio daemon if required */ + PA_CONTEXT_NOAUTOSPAWN = 1 /**< Disabled autospawning of the pulseaudio daemon if required */ } pa_context_flags_t; /** The direction of a pa_stream object */ diff --git a/src/polyp/error.c b/src/pulse/error.c similarity index 84% rename from src/polyp/error.c rename to src/pulse/error.c index 27da7eae9..7bd31ead9 100644 --- a/src/polyp/error.c +++ b/src/pulse/error.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,10 +28,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "error.h" diff --git a/src/polyp/error.h b/src/pulse/error.h similarity index 76% rename from src/polyp/error.h rename to src/pulse/error.h index 9856c1af3..bfce023ca 100644 --- a/src/polyp/error.h +++ b/src/pulse/error.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include +#include /** \file * Error management */ diff --git a/src/polyp/glib-mainloop.c b/src/pulse/glib-mainloop.c similarity index 97% rename from src/polyp/glib-mainloop.c rename to src/pulse/glib-mainloop.c index d5fce7671..25848ece3 100644 --- a/src/polyp/glib-mainloop.c +++ b/src/pulse/glib-mainloop.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,11 +25,11 @@ #include -#include -#include +#include +#include -#include -#include +#include +#include #include "glib.h" #include "glib-mainloop.h" diff --git a/src/polyp/glib-mainloop.h b/src/pulse/glib-mainloop.h similarity index 85% rename from src/polyp/glib-mainloop.h rename to src/pulse/glib-mainloop.h index ce885e135..75de1cc77 100644 --- a/src/polyp/glib-mainloop.h +++ b/src/pulse/glib-mainloop.h @@ -4,28 +4,28 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include +#include +#include /** \page glib-mainloop GLIB Main Loop Bindings * diff --git a/src/polyp/glib12-mainloop.c b/src/pulse/glib12-mainloop.c similarity index 97% rename from src/polyp/glib12-mainloop.c rename to src/pulse/glib12-mainloop.c index dfd6ff2f1..ebaf87fc5 100644 --- a/src/polyp/glib12-mainloop.c +++ b/src/pulse/glib12-mainloop.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,11 +25,11 @@ #include -#include -#include +#include +#include -#include -#include +#include +#include #include "glib-mainloop.h" diff --git a/src/polyp/internal.h b/src/pulse/internal.h similarity index 89% rename from src/polyp/internal.h rename to src/pulse/internal.h index e659553d8..96028d832 100644 --- a/src/polyp/internal.h +++ b/src/pulse/internal.h @@ -4,40 +4,40 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "client-conf.h" diff --git a/src/polyp/introspect.c b/src/pulse/introspect.c similarity index 99% rename from src/polyp/introspect.c rename to src/pulse/introspect.c index 9d0026695..ed40c53de 100644 --- a/src/polyp/introspect.c +++ b/src/pulse/introspect.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,10 +25,10 @@ #include -#include +#include -#include -#include +#include +#include #include "internal.h" diff --git a/src/polyp/introspect.h b/src/pulse/introspect.h similarity index 98% rename from src/polyp/introspect.h rename to src/pulse/introspect.h index 9a0edb795..8fe218bcd 100644 --- a/src/polyp/introspect.h +++ b/src/pulse/introspect.h @@ -4,31 +4,31 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include /** \page introspect Server Query and Control * @@ -266,11 +266,11 @@ typedef struct pa_server_info { const char *user_name; /**< User name of the daemon process */ const char *host_name; /**< Host name the daemon is running on */ const char *server_version; /**< Version string of the daemon */ - const char *server_name; /**< Server package name (usually "polypaudio") */ + const char *server_name; /**< Server package name (usually "pulseaudio") */ pa_sample_spec sample_spec; /**< Default sample specification */ const char *default_sink_name; /**< Name of default sink. \since 0.4 */ const char *default_source_name; /**< Name of default sink. \since 0.4*/ - uint32_t cookie; /**< A random cookie for identifying this instance of polypaudio. \since 0.8 */ + uint32_t cookie; /**< A random cookie for identifying this instance of pulseaudio. \since 0.8 */ } pa_server_info; /** Callback prototype for pa_context_get_server_info() */ diff --git a/src/polyp/mainloop-api.c b/src/pulse/mainloop-api.c similarity index 84% rename from src/polyp/mainloop-api.c rename to src/pulse/mainloop-api.c index f29598dc4..2e20b446a 100644 --- a/src/polyp/mainloop-api.c +++ b/src/pulse/mainloop-api.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,9 +26,9 @@ #include #include -#include +#include -#include +#include #include "mainloop-api.h" diff --git a/src/polyp/mainloop-api.h b/src/pulse/mainloop-api.h similarity index 89% rename from src/polyp/mainloop-api.h rename to src/pulse/mainloop-api.h index 12d74aa16..a732b215e 100644 --- a/src/polyp/mainloop-api.h +++ b/src/pulse/mainloop-api.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,17 +25,17 @@ #include #include -#include +#include /** \file * - * Main loop abstraction layer. Both the polypaudio core and the - * polypaudio client library use a main loop abstraction layer. Due to - * this it is possible to embed polypaudio into other + * Main loop abstraction layer. Both the pulseaudio core and the + * pulseaudio client library use a main loop abstraction layer. Due to + * this it is possible to embed pulseaudio into other * applications easily. Two main loop implemenations are * currently available: * \li A minimal implementation based on the C library's poll() function (See \ref mainloop.h) - * \li A wrapper around the GLIB main loop. Use this to embed polypaudio into your GLIB/GTK+/GNOME programs (See \ref glib-mainloop.h) + * \li A wrapper around the GLIB main loop. Use this to embed pulseaudio into your GLIB/GTK+/GNOME programs (See \ref glib-mainloop.h) * * The structure pa_mainloop_api is used as vtable for the main loop abstraction. * diff --git a/src/polyp/mainloop-signal.c b/src/pulse/mainloop-signal.c similarity index 92% rename from src/polyp/mainloop-signal.c rename to src/pulse/mainloop-signal.c index 927028143..c3cf362d8 100644 --- a/src/polyp/mainloop-signal.c +++ b/src/pulse/mainloop-signal.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -36,12 +36,12 @@ #include #endif -#include -#include +#include +#include -#include -#include -#include +#include +#include +#include #include "mainloop-signal.h" diff --git a/src/polyp/mainloop-signal.h b/src/pulse/mainloop-signal.h similarity index 87% rename from src/polyp/mainloop-signal.h rename to src/pulse/mainloop-signal.h index 20e97988f..0721c1f5d 100644 --- a/src/polyp/mainloop-signal.h +++ b/src/pulse/mainloop-signal.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include PA_C_DECL_BEGIN diff --git a/src/polyp/mainloop.c b/src/pulse/mainloop.c similarity index 97% rename from src/polyp/mainloop.c rename to src/pulse/mainloop.c index 61d8b4881..32f1a845d 100644 --- a/src/polyp/mainloop.c +++ b/src/pulse/mainloop.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -35,22 +35,22 @@ #ifdef HAVE_SYS_POLL_H #include #else -#include "../polypcore/poll.h" +#include "../pulsecore/poll.h" #endif -#include "../polypcore/winsock.h" +#include "../pulsecore/winsock.h" #ifndef HAVE_PIPE -#include "../polypcore/pipe.h" +#include "../pulsecore/pipe.h" #endif -#include -#include -#include +#include +#include +#include -#include -#include -#include +#include +#include +#include #include "mainloop.h" diff --git a/src/polyp/mainloop.h b/src/pulse/mainloop.h similarity index 94% rename from src/polyp/mainloop.h rename to src/pulse/mainloop.h index 4681912bb..8abd8fe47 100644 --- a/src/polyp/mainloop.h +++ b/src/pulse/mainloop.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include PA_C_DECL_BEGIN diff --git a/src/polyp/operation.c b/src/pulse/operation.c similarity index 90% rename from src/polyp/operation.c rename to src/pulse/operation.c index 5af9ec0b8..24ddf69ff 100644 --- a/src/polyp/operation.c +++ b/src/pulse/operation.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,7 +25,7 @@ #include -#include +#include #include "internal.h" #include "operation.h" diff --git a/src/polyp/operation.h b/src/pulse/operation.h similarity index 81% rename from src/polyp/operation.h rename to src/pulse/operation.h index 2fbac2e27..b544e08ec 100644 --- a/src/polyp/operation.h +++ b/src/pulse/operation.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include /** \file * Asynchronous operations */ diff --git a/src/polyp/polypaudio.h b/src/pulse/polypaudio.h similarity index 67% rename from src/polyp/polypaudio.h rename to src/pulse/polypaudio.h index c172315b2..5bbd4cc52 100644 --- a/src/polyp/polypaudio.h +++ b/src/pulse/polypaudio.h @@ -1,50 +1,50 @@ -#ifndef foopolypaudiohfoo -#define foopolypaudiohfoo +#ifndef foopulseaudiohfoo +#define foopulseaudiohfoo /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /** \file - * Include all polyplib header files at once. The following + * Include all pulselib header files at once. The following * files are included: \ref mainloop-api.h, \ref sample.h, \ref def.h, * \ref context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h, * \ref scache.h, \ref version.h, \ref error.h, \ref channelmap.h, @@ -56,7 +56,7 @@ * * \section intro_sec Introduction * - * This document describes the client API for the polypaudio sound + * This document describes the client API for the pulseaudio sound * server. The API comes in two flavours to accomodate different styles * of applications and different needs in complexity: * @@ -78,7 +78,7 @@ * * Use this if you develop your programs in asynchronous, event loop * based style or if you want to use the advanced features of the - * polypaudio API. A guide can be found in \subpage async. + * pulseaudio API. A guide can be found in \subpage async. * * By using the built-in threaded main loop, it is possible to acheive a * pseudo-synchronous API, which can be useful in synchronous applications @@ -87,7 +87,7 @@ * * \section thread_sec Threads * - * The polypaudio client libraries are not designed to be used in a + * The pulseaudio client libraries are not designed to be used in a * heavily threaded environment. They are however designed to be reentrant * safe. * @@ -102,14 +102,14 @@ * * \section pkgconfig pkg-config * - * The polypaudio libraries provide pkg-config snippets for the different + * The pulseaudio libraries provide pkg-config snippets for the different * modules: * - * \li polyplib - The asynchronous API and the internal main loop + * \li pulselib - The asynchronous API and the internal main loop * implementation. - * \li polyplib-glib12-mainloop - GLIB 1.2 main loop bindings. - * \li polyplib-glib-mainloop - GLIB 2.x main loop bindings. - * \li polyplib-simple - The simple polypaudio API. + * \li pulselib-glib12-mainloop - GLIB 1.2 main loop bindings. + * \li pulselib-glib-mainloop - GLIB 2.x main loop bindings. + * \li pulselib-simple - The simple pulseaudio API. */ #endif diff --git a/src/polyp/sample.c b/src/pulse/sample.c similarity index 95% rename from src/polyp/sample.c rename to src/pulse/sample.c index 9c3b9f917..2e055bf1b 100644 --- a/src/polyp/sample.c +++ b/src/pulse/sample.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polyp/sample.h b/src/pulse/sample.h similarity index 96% rename from src/polyp/sample.h rename to src/pulse/sample.h index 2a9a72fef..848fd16dc 100644 --- a/src/polyp/sample.h +++ b/src/pulse/sample.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,7 +26,7 @@ #include #include -#include +#include /** \page sample Sample Format Specifications * diff --git a/src/polyp/scache.c b/src/pulse/scache.c similarity index 93% rename from src/polyp/scache.c rename to src/pulse/scache.c index 22d8a5454..5d29c5b32 100644 --- a/src/polyp/scache.c +++ b/src/pulse/scache.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,7 +28,7 @@ #include #include -#include +#include #include "internal.h" diff --git a/src/polyp/scache.h b/src/pulse/scache.h similarity index 91% rename from src/polyp/scache.h rename to src/pulse/scache.h index 91890673f..e32703d44 100644 --- a/src/polyp/scache.h +++ b/src/pulse/scache.h @@ -4,29 +4,29 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include -#include +#include +#include +#include /** \page scache Sample Cache * diff --git a/src/polyp/simple.c b/src/pulse/simple.c similarity index 96% rename from src/polyp/simple.c rename to src/pulse/simple.c index 9c2c908c9..a41881bb6 100644 --- a/src/polyp/simple.c +++ b/src/pulse/simple.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,12 +28,12 @@ #include #include -#include -#include -#include +#include +#include +#include -#include -#include +#include +#include #include "simple.h" diff --git a/src/polyp/simple.h b/src/pulse/simple.h similarity index 93% rename from src/polyp/simple.h rename to src/pulse/simple.h index b97e844b0..0438d3199 100644 --- a/src/polyp/simple.h +++ b/src/pulse/simple.h @@ -4,30 +4,30 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include -#include -#include +#include +#include +#include +#include /** \page simple Simple API * diff --git a/src/polyp/stream.c b/src/pulse/stream.c similarity index 99% rename from src/polyp/stream.c rename to src/pulse/stream.c index 8927805ed..c8fc09d29 100644 --- a/src/polyp/stream.c +++ b/src/pulse/stream.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,13 +28,13 @@ #include #include -#include -#include -#include +#include +#include +#include -#include -#include -#include +#include +#include +#include #include "internal.h" diff --git a/src/polyp/stream.h b/src/pulse/stream.h similarity index 98% rename from src/polyp/stream.h rename to src/pulse/stream.h index d1f558aea..d117ce4a3 100644 --- a/src/polyp/stream.h +++ b/src/pulse/stream.h @@ -4,32 +4,32 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include /** \page streams Audio Streams * diff --git a/src/polyp/subscribe.c b/src/pulse/subscribe.c similarity index 88% rename from src/polyp/subscribe.c rename to src/pulse/subscribe.c index 21f5f7a57..c1d889122 100644 --- a/src/polyp/subscribe.c +++ b/src/pulse/subscribe.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,8 +26,8 @@ #include #include -#include -#include +#include +#include #include "internal.h" diff --git a/src/polyp/subscribe.h b/src/pulse/subscribe.h similarity index 85% rename from src/polyp/subscribe.h rename to src/pulse/subscribe.h index d8326e1ce..adbea6809 100644 --- a/src/polyp/subscribe.h +++ b/src/pulse/subscribe.h @@ -4,29 +4,29 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include -#include +#include +#include +#include /** \page subscribe Event Subscription * diff --git a/src/polyp/thread-mainloop.c b/src/pulse/thread-mainloop.c similarity index 96% rename from src/polyp/thread-mainloop.c rename to src/pulse/thread-mainloop.c index d036a2327..34f0f2503 100644 --- a/src/polyp/thread-mainloop.c +++ b/src/pulse/thread-mainloop.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,7 +30,7 @@ #ifdef HAVE_SYS_POLL_H #include #else -#include "../polypcore/poll.h" +#include "../pulsecore/poll.h" #endif #ifdef HAVE_PTHREAD @@ -41,10 +41,10 @@ #include #endif -#include +#include -#include -#include +#include +#include #include "mainloop.h" #include "thread-mainloop.h" diff --git a/src/polyp/thread-mainloop.h b/src/pulse/thread-mainloop.h similarity index 97% rename from src/polyp/thread-mainloop.h rename to src/pulse/thread-mainloop.h index 81e8d6746..fb216c5ab 100644 --- a/src/polyp/thread-mainloop.h +++ b/src/pulse/thread-mainloop.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include PA_C_DECL_BEGIN diff --git a/src/polyp/timeval.c b/src/pulse/timeval.c similarity index 92% rename from src/polyp/timeval.c rename to src/pulse/timeval.c index 6043d7fd2..112852302 100644 --- a/src/polyp/timeval.c +++ b/src/pulse/timeval.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -31,7 +31,7 @@ #include #endif -#include "../polypcore/winsock.h" +#include "../pulsecore/winsock.h" #include "timeval.h" diff --git a/src/polyp/timeval.h b/src/pulse/timeval.h similarity index 83% rename from src/polyp/timeval.h rename to src/pulse/timeval.h index 9990d4cae..e2dbbadb2 100644 --- a/src/polyp/timeval.h +++ b/src/pulse/timeval.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include /** \file * Utility functions for handling timeval calculations */ diff --git a/src/polyp/utf8.c b/src/pulse/utf8.c similarity index 100% rename from src/polyp/utf8.c rename to src/pulse/utf8.c diff --git a/src/polyp/utf8.h b/src/pulse/utf8.h similarity index 83% rename from src/polyp/utf8.h rename to src/pulse/utf8.h index 55b8d2e49..2eac724db 100644 --- a/src/polyp/utf8.h +++ b/src/pulse/utf8.h @@ -4,25 +4,25 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include /** \file * UTF8 Validation functions diff --git a/src/polyp/util.c b/src/pulse/util.c similarity index 92% rename from src/polyp/util.c rename to src/pulse/util.c index 842b9e7f8..338607c41 100644 --- a/src/polyp/util.c +++ b/src/pulse/util.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -49,11 +49,11 @@ #include #endif -#include "../polypcore/winsock.h" +#include "../pulsecore/winsock.h" -#include -#include -#include +#include +#include +#include #include "util.h" diff --git a/src/polyp/util.h b/src/pulse/util.h similarity index 85% rename from src/polyp/util.h rename to src/pulse/util.h index cd8aab0bd..5c03b0a94 100644 --- a/src/polyp/util.h +++ b/src/pulse/util.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include +#include /** \file * Assorted utility functions */ diff --git a/src/polyp/version.h.in b/src/pulse/version.h.in similarity index 77% rename from src/polyp/version.h.in rename to src/pulse/version.h.in index de7b9c1c0..6c5492e8d 100644 --- a/src/polyp/version.h.in +++ b/src/pulse/version.h.in @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ /* WARNING: Make sure to edit the real source file version.h.in! */ -#include +#include /** \file * Define header version */ @@ -39,12 +39,12 @@ it. */ /** Return the version of the library the current application is linked to. */ const char* pa_get_library_version(void); -/** The current API version. Version 6 relates to polypaudio +/** The current API version. Version 6 relates to pulseaudio * 0.6. Prior versions (i.e. Polypaudio 0.5.1 and older) have * PA_API_VERSION undefined. */ #define PA_API_VERSION @PA_API_VERSION@ -/** The current protocol version. Version 8 relates to polypaudio 0.8. +/** The current protocol version. Version 8 relates to pulseaudio 0.8. * \since 0.8 */ #define PA_PROTOCOL_VERSION @PA_PROTOCOL_VERSION@ diff --git a/src/polyp/volume.c b/src/pulse/volume.c similarity index 94% rename from src/polyp/volume.c rename to src/pulse/volume.c index f10463c3c..530814e0f 100644 --- a/src/polyp/volume.c +++ b/src/pulse/volume.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polyp/volume.h b/src/pulse/volume.h similarity index 95% rename from src/polyp/volume.h rename to src/pulse/volume.h index 0da5f54fe..d403a09e3 100644 --- a/src/polyp/volume.h +++ b/src/pulse/volume.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include +#include +#include /** \page volume Volume Control * diff --git a/src/polyp/xmalloc.c b/src/pulse/xmalloc.c similarity index 89% rename from src/polyp/xmalloc.c rename to src/pulse/xmalloc.c index 7f71a5edf..46871aeb6 100644 --- a/src/polyp/xmalloc.c +++ b/src/pulse/xmalloc.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,8 +29,8 @@ #include #include -#include -#include +#include +#include #include "xmalloc.h" diff --git a/src/polyp/xmalloc.h b/src/pulse/xmalloc.h similarity index 89% rename from src/polyp/xmalloc.h rename to src/pulse/xmalloc.h index 49b6d7bca..126c495ca 100644 --- a/src/polyp/xmalloc.h +++ b/src/pulse/xmalloc.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,7 +26,7 @@ #include #include #include -#include +#include /** \file * Memory allocation functions. diff --git a/src/pulsecore/Makefile b/src/pulsecore/Makefile new file mode 120000 index 000000000..c110232d3 --- /dev/null +++ b/src/pulsecore/Makefile @@ -0,0 +1 @@ +../pulse/Makefile \ No newline at end of file diff --git a/src/polypcore/authkey-prop.c b/src/pulsecore/authkey-prop.c similarity index 85% rename from src/polypcore/authkey-prop.c rename to src/pulsecore/authkey-prop.c index 6172d4320..7eda1e496 100644 --- a/src/polypcore/authkey-prop.c +++ b/src/pulsecore/authkey-prop.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -22,10 +22,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "authkey-prop.h" diff --git a/src/polypcore/authkey-prop.h b/src/pulsecore/authkey-prop.h similarity index 84% rename from src/polypcore/authkey-prop.h rename to src/pulsecore/authkey-prop.h index 63fde5d8d..b1da28bea 100644 --- a/src/polypcore/authkey-prop.h +++ b/src/pulsecore/authkey-prop.h @@ -4,25 +4,25 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include /* The authkey-prop uses a central property to store a previously * loaded cookie in memory. Useful for sharing the same cookie between diff --git a/src/polypcore/authkey.c b/src/pulsecore/authkey.c similarity index 93% rename from src/polypcore/authkey.c rename to src/pulsecore/authkey.c index 54f4dd868..064209d9a 100644 --- a/src/polypcore/authkey.c +++ b/src/pulsecore/authkey.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -35,11 +35,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "authkey.h" diff --git a/src/polypcore/authkey.h b/src/pulsecore/authkey.h similarity index 78% rename from src/polypcore/authkey.h rename to src/pulsecore/authkey.h index 81b1a578e..cc8a565cf 100644 --- a/src/polypcore/authkey.h +++ b/src/pulsecore/authkey.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/autoload.c b/src/pulsecore/autoload.c similarity index 91% rename from src/polypcore/autoload.c rename to src/pulsecore/autoload.c index 386de2192..f6869097a 100644 --- a/src/polypcore/autoload.c +++ b/src/pulsecore/autoload.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,14 +27,14 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include "autoload.h" diff --git a/src/polypcore/autoload.h b/src/pulsecore/autoload.h similarity index 88% rename from src/polypcore/autoload.h rename to src/pulsecore/autoload.h index a8931fc7e..65bdd6da6 100644 --- a/src/polypcore/autoload.h +++ b/src/pulsecore/autoload.h @@ -4,25 +4,25 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include /* Using the autoloading facility, modules by be loaded on-demand and * synchronously. The user may register a "ghost sink" or "ghost diff --git a/src/polypcore/cli-command.c b/src/pulsecore/cli-command.c similarity index 97% rename from src/polypcore/cli-command.c rename to src/pulsecore/cli-command.c index e25e464ce..4ba3e0af3 100644 --- a/src/polypcore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,27 +29,27 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "cli-command.h" diff --git a/src/polypcore/cli-command.h b/src/pulsecore/cli-command.h similarity index 81% rename from src/polypcore/cli-command.h rename to src/pulsecore/cli-command.h index e7c70ecfe..c56c3ca00 100644 --- a/src/polypcore/cli-command.h +++ b/src/pulsecore/cli-command.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include /* Execute a single CLI command. Write the results to the string * buffer *buf. If *fail is non-zero the function will return -1 when diff --git a/src/polypcore/cli-text.c b/src/pulsecore/cli-text.c similarity index 95% rename from src/polypcore/cli-text.c rename to src/pulsecore/cli-text.c index 09ccaa00d..eecf68fff 100644 --- a/src/polypcore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,19 +26,19 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "cli-text.h" diff --git a/src/polypcore/cli-text.h b/src/pulsecore/cli-text.h similarity index 81% rename from src/polypcore/cli-text.h rename to src/pulsecore/cli-text.h index a8f400035..cd3acdee7 100644 --- a/src/polypcore/cli-text.h +++ b/src/pulsecore/cli-text.h @@ -4,25 +4,25 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include /* Some functions to generate pretty formatted listings of * entities. The returned strings have to be freed manually. */ diff --git a/src/polypcore/cli.c b/src/pulsecore/cli.c similarity index 81% rename from src/polypcore/cli.c rename to src/pulsecore/cli.c index 683d29ec9..fbfa5009b 100644 --- a/src/polypcore/cli.c +++ b/src/pulsecore/cli.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,21 +28,21 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "cli.h" @@ -84,7 +84,7 @@ pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) { c->client->owner = m; pa_ioline_set_callback(c->line, line_callback, c); - pa_ioline_puts(c->line, "Welcome to polypaudio! Use \"help\" for usage information.\n"PROMPT); + pa_ioline_puts(c->line, "Welcome to pulseaudio! Use \"help\" for usage information.\n"PROMPT); c->fail = c->kill_requested = c->defer_kill = 0; diff --git a/src/polypcore/cli.h b/src/pulsecore/cli.h similarity index 76% rename from src/polypcore/cli.h rename to src/pulsecore/cli.h index 12ffd848f..639fa9525 100644 --- a/src/polypcore/cli.h +++ b/src/pulsecore/cli.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include +#include +#include +#include typedef struct pa_cli pa_cli; diff --git a/src/polypcore/client.c b/src/pulsecore/client.c similarity index 87% rename from src/polypcore/client.c rename to src/pulsecore/client.c index 4ece07a8b..bf2b13df7 100644 --- a/src/polypcore/client.c +++ b/src/pulsecore/client.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,10 +28,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "client.h" diff --git a/src/polypcore/client.h b/src/pulsecore/client.h similarity index 83% rename from src/polypcore/client.h rename to src/pulsecore/client.h index f6ff935db..1e72baf77 100644 --- a/src/polypcore/client.h +++ b/src/pulsecore/client.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include /* Every connection to the server should have a pa_client * attached. That way the user may generate a listing of all connected diff --git a/src/polypcore/conf-parser.c b/src/pulsecore/conf-parser.c similarity index 92% rename from src/polypcore/conf-parser.c rename to src/pulsecore/conf-parser.c index d59bc5556..cc471ff92 100644 --- a/src/polypcore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,11 +28,11 @@ #include #include -#include +#include -#include -#include -#include +#include +#include +#include #include "conf-parser.h" diff --git a/src/polypcore/conf-parser.h b/src/pulsecore/conf-parser.h similarity index 89% rename from src/polypcore/conf-parser.h rename to src/pulsecore/conf-parser.h index 2dca3bceb..9c1a697a6 100644 --- a/src/polypcore/conf-parser.h +++ b/src/pulsecore/conf-parser.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/core-def.h b/src/pulsecore/core-def.h similarity index 75% rename from src/polypcore/core-def.h rename to src/pulsecore/core-def.h index 89cc47f1e..718499d12 100644 --- a/src/polypcore/core-def.h +++ b/src/pulsecore/core-def.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/core-error.c b/src/pulsecore/core-error.c similarity index 91% rename from src/polypcore/core-error.c rename to src/pulsecore/core-error.c index f2240a9fe..e42070d17 100644 --- a/src/polypcore/core-error.c +++ b/src/pulsecore/core-error.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -36,11 +36,11 @@ #include #endif -#include -#include +#include +#include -#include -#include +#include +#include #include "core-error.h" @@ -68,7 +68,7 @@ static void inittls(void) { HANDLE mutex; char name[64]; - sprintf(name, "polypaudio%d", (int)GetCurrentProcessId()); + sprintf(name, "pulseaudio%d", (int)GetCurrentProcessId()); mutex = CreateMutex(NULL, FALSE, name); if (!mutex) { diff --git a/src/polypcore/core-error.h b/src/pulsecore/core-error.h similarity index 79% rename from src/polypcore/core-error.h rename to src/pulsecore/core-error.h index 17595c98c..32da8bf2b 100644 --- a/src/polypcore/core-error.h +++ b/src/pulsecore/core-error.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include +#include /** \file * Error management */ diff --git a/src/polypcore/core-scache.c b/src/pulsecore/core-scache.c similarity index 93% rename from src/polypcore/core-scache.c rename to src/pulsecore/core-scache.c index b44a7e198..377dd569f 100644 --- a/src/polypcore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -41,22 +41,22 @@ #include #endif -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "core-scache.h" diff --git a/src/polypcore/core-scache.h b/src/pulsecore/core-scache.h similarity index 84% rename from src/polypcore/core-scache.h rename to src/pulsecore/core-scache.h index 9ca05f8f6..d01aae9b1 100644 --- a/src/polypcore/core-scache.h +++ b/src/pulsecore/core-scache.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include +#include +#include +#include #define PA_SCACHE_ENTRY_SIZE_MAX (1024*1024*2) diff --git a/src/polypcore/core-subscribe.c b/src/pulsecore/core-subscribe.c similarity index 95% rename from src/polypcore/core-subscribe.c rename to src/pulsecore/core-subscribe.c index 52babb7a3..e865256aa 100644 --- a/src/polypcore/core-subscribe.c +++ b/src/pulsecore/core-subscribe.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,10 +26,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "core-subscribe.h" diff --git a/src/polypcore/core-subscribe.h b/src/pulsecore/core-subscribe.h similarity index 79% rename from src/polypcore/core-subscribe.h rename to src/pulsecore/core-subscribe.h index 7c8569542..c24670336 100644 --- a/src/polypcore/core-subscribe.h +++ b/src/pulsecore/core-subscribe.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,8 +25,8 @@ typedef struct pa_subscription pa_subscription; typedef struct pa_subscription_event pa_subscription_event; -#include -#include +#include +#include pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata); void pa_subscription_free(pa_subscription*s); diff --git a/src/polypcore/core-util.c b/src/pulsecore/core-util.c similarity index 97% rename from src/polypcore/core-util.c rename to src/pulsecore/core-util.c index dfa41f57f..8e3587ebe 100644 --- a/src/polypcore/core-util.c +++ b/src/pulsecore/core-util.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -69,20 +69,20 @@ #include -#include -#include +#include +#include -#include -#include -#include +#include +#include +#include #include "core-util.h" #ifndef OS_IS_WIN32 -#define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-" +#define PA_RUNTIME_PATH_PREFIX "/tmp/pulseaudio-" #define PATH_SEP '/' #else -#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\polypaudio-" +#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\pulseaudio-" #define PATH_SEP '\\' #endif @@ -961,7 +961,7 @@ int pa_endswith(const char *s, const char *sfx) { return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0; } -/* if fn is null return the polypaudio run time path in s (/tmp/polypaudio) +/* if fn is null return the pulseaudio run time path in s (/tmp/pulseaudio) * if fn is non-null and starts with / return fn in s * otherwise append fn to the run time path and return it in s */ char *pa_runtime_path(const char *fn, char *s, size_t l) { diff --git a/src/polypcore/core-util.h b/src/pulsecore/core-util.h similarity index 90% rename from src/polypcore/core-util.h rename to src/pulsecore/core-util.h index 989f8c16a..0012afc64 100644 --- a/src/polypcore/core-util.h +++ b/src/pulsecore/core-util.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,7 +27,7 @@ #include #include -#include +#include struct timeval; diff --git a/src/polypcore/core.c b/src/pulsecore/core.c similarity index 86% rename from src/polypcore/core.c rename to src/pulsecore/core.c index 09d023dce..7c780ea8e 100644 --- a/src/polypcore/core.c +++ b/src/pulsecore/core.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,19 +28,19 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "core.h" diff --git a/src/polypcore/core.h b/src/pulsecore/core.h similarity index 76% rename from src/polypcore/core.h rename to src/pulsecore/core.h index a323ae8e1..627d42396 100644 --- a/src/polypcore/core.h +++ b/src/pulsecore/core.h @@ -4,42 +4,42 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ typedef struct pa_core pa_core; -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include -/* The core structure of polypaudio. Every polypaudio daemon contains +/* The core structure of pulseaudio. Every pulseaudio daemon contains * exactly one of these. It is used for storing kind of global * variables for the daemon. */ struct pa_core { /* A random value which may be used to identify this instance of - * polypaudio. Not cryptographically secure in any way. */ + * pulseaudio. Not cryptographically secure in any way. */ uint32_t cookie; pa_mainloop_api *mainloop; diff --git a/src/polypcore/dllmain.c b/src/pulsecore/dllmain.c similarity index 83% rename from src/polypcore/dllmain.c rename to src/pulsecore/dllmain.c index 95473b068..b86bf04f0 100644 --- a/src/polypcore/dllmain.c +++ b/src/pulsecore/dllmain.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/dynarray.c b/src/pulsecore/dynarray.c similarity index 89% rename from src/polypcore/dynarray.c rename to src/pulsecore/dynarray.c index 234c2c03f..d1ab11610 100644 --- a/src/polypcore/dynarray.c +++ b/src/pulsecore/dynarray.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,7 +27,7 @@ #include #include -#include +#include #include "dynarray.h" diff --git a/src/polypcore/dynarray.h b/src/pulsecore/dynarray.h similarity index 86% rename from src/polypcore/dynarray.h rename to src/pulsecore/dynarray.h index 9b1601bab..4ddb526ca 100644 --- a/src/polypcore/dynarray.h +++ b/src/pulsecore/dynarray.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/endianmacros.h b/src/pulsecore/endianmacros.h similarity index 91% rename from src/polypcore/endianmacros.h rename to src/pulsecore/endianmacros.h index 3ab1826a5..65db3feb3 100644 --- a/src/polypcore/endianmacros.h +++ b/src/pulsecore/endianmacros.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/esound.h b/src/pulsecore/esound.h similarity index 97% rename from src/polypcore/esound.h rename to src/pulsecore/esound.h index 9c507ef9c..9d44f65c7 100644 --- a/src/polypcore/esound.h +++ b/src/pulsecore/esound.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/g711.c b/src/pulsecore/g711.c similarity index 100% rename from src/polypcore/g711.c rename to src/pulsecore/g711.c diff --git a/src/polypcore/g711.h b/src/pulsecore/g711.h similarity index 100% rename from src/polypcore/g711.h rename to src/pulsecore/g711.h diff --git a/src/polypcore/gccmacro.h b/src/pulsecore/gccmacro.h similarity index 85% rename from src/polypcore/gccmacro.h rename to src/pulsecore/gccmacro.h index 9e212f2e2..2ab999d90 100644 --- a/src/polypcore/gccmacro.h +++ b/src/pulsecore/gccmacro.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/hashmap.c b/src/pulsecore/hashmap.c similarity index 93% rename from src/polypcore/hashmap.c rename to src/pulsecore/hashmap.c index adc322f04..2cddba1d5 100644 --- a/src/polypcore/hashmap.c +++ b/src/pulsecore/hashmap.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,10 +27,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "hashmap.h" diff --git a/src/polypcore/hashmap.h b/src/pulsecore/hashmap.h similarity index 89% rename from src/polypcore/hashmap.h rename to src/pulsecore/hashmap.h index 14f827059..3f62adb11 100644 --- a/src/polypcore/hashmap.h +++ b/src/pulsecore/hashmap.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/idxset.c b/src/pulsecore/idxset.c similarity index 97% rename from src/polypcore/idxset.c rename to src/pulsecore/idxset.c index bde5c2791..ddce623a2 100644 --- a/src/polypcore/idxset.c +++ b/src/pulsecore/idxset.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,7 +28,7 @@ #include #include -#include +#include #include "idxset.h" diff --git a/src/polypcore/idxset.h b/src/pulsecore/idxset.h similarity index 94% rename from src/polypcore/idxset.h rename to src/pulsecore/idxset.h index 17ae16cba..3d0bc75f8 100644 --- a/src/polypcore/idxset.h +++ b/src/pulsecore/idxset.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/inet_ntop.c b/src/pulsecore/inet_ntop.c similarity index 90% rename from src/polypcore/inet_ntop.c rename to src/pulsecore/inet_ntop.c index a25c3c951..483c3e262 100644 --- a/src/polypcore/inet_ntop.c +++ b/src/pulsecore/inet_ntop.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/inet_ntop.h b/src/pulsecore/inet_ntop.h similarity index 100% rename from src/polypcore/inet_ntop.h rename to src/pulsecore/inet_ntop.h diff --git a/src/polypcore/inet_pton.c b/src/pulsecore/inet_pton.c similarity index 84% rename from src/polypcore/inet_pton.c rename to src/pulsecore/inet_pton.c index 17860f6d2..7b6bbc31d 100644 --- a/src/polypcore/inet_pton.c +++ b/src/pulsecore/inet_pton.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/inet_pton.h b/src/pulsecore/inet_pton.h similarity index 100% rename from src/polypcore/inet_pton.h rename to src/pulsecore/inet_pton.h diff --git a/src/polypcore/iochannel.c b/src/pulsecore/iochannel.c similarity index 96% rename from src/polypcore/iochannel.c rename to src/pulsecore/iochannel.c index 106c413ec..8a19094af 100644 --- a/src/polypcore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -38,12 +38,12 @@ #include "winsock.h" -#include +#include -#include -#include -#include -#include +#include +#include +#include +#include #include "iochannel.h" diff --git a/src/polypcore/iochannel.h b/src/pulsecore/iochannel.h similarity index 92% rename from src/polypcore/iochannel.h rename to src/pulsecore/iochannel.h index fe7cc0cea..64cf331ec 100644 --- a/src/polypcore/iochannel.h +++ b/src/pulsecore/iochannel.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include +#include /* A wrapper around UNIX file descriptors for attaching them to the a main event loop. Everytime new data may be read or be written to diff --git a/src/polypcore/ioline.c b/src/pulsecore/ioline.c similarity index 96% rename from src/polypcore/ioline.c rename to src/pulsecore/ioline.c index b908f967d..9c9900f8b 100644 --- a/src/polypcore/ioline.c +++ b/src/pulsecore/ioline.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,10 +29,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "ioline.h" diff --git a/src/polypcore/ioline.h b/src/pulsecore/ioline.h similarity index 83% rename from src/polypcore/ioline.h rename to src/pulsecore/ioline.h index 77bf87616..e736e2b3b 100644 --- a/src/polypcore/ioline.h +++ b/src/pulsecore/ioline.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include /* An ioline wraps an iochannel for line based communication. A * callback function is called whenever a new line has been recieved diff --git a/src/polypcore/llist.h b/src/pulsecore/llist.h similarity index 92% rename from src/polypcore/llist.h rename to src/pulsecore/llist.h index c54742d32..bf3c150ae 100644 --- a/src/polypcore/llist.h +++ b/src/pulsecore/llist.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/log.c b/src/pulsecore/log.c similarity index 94% rename from src/polypcore/log.c rename to src/pulsecore/log.c index 6cdffa51d..df5b140ac 100644 --- a/src/polypcore/log.c +++ b/src/pulsecore/log.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -33,10 +33,10 @@ #include #endif -#include -#include +#include +#include -#include +#include #include "log.h" diff --git a/src/polypcore/log.h b/src/pulsecore/log.h similarity index 89% rename from src/polypcore/log.h rename to src/pulsecore/log.h index c306acaff..7bf4e4076 100644 --- a/src/polypcore/log.h +++ b/src/pulsecore/log.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include +#include /* A simple logging subsystem */ diff --git a/src/polypcore/mcalign.c b/src/pulsecore/mcalign.c similarity index 95% rename from src/polypcore/mcalign.c rename to src/pulsecore/mcalign.c index d9267f99d..8283a7a0b 100644 --- a/src/polypcore/mcalign.c +++ b/src/pulsecore/mcalign.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,7 +28,7 @@ #include #include -#include +#include #include "mcalign.h" diff --git a/src/polypcore/mcalign.h b/src/pulsecore/mcalign.h similarity index 87% rename from src/polypcore/mcalign.h rename to src/pulsecore/mcalign.h index 580194629..80e374996 100644 --- a/src/polypcore/mcalign.h +++ b/src/pulsecore/mcalign.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include /* An alignment object, used for aligning memchunks to multiples of * the frame size. */ diff --git a/src/polypcore/memblock.c b/src/pulsecore/memblock.c similarity index 93% rename from src/polypcore/memblock.c rename to src/pulsecore/memblock.c index a0e5135b3..36de17fb3 100644 --- a/src/polypcore/memblock.c +++ b/src/pulsecore/memblock.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,7 +28,7 @@ #include #include -#include +#include #include "memblock.h" diff --git a/src/polypcore/memblock.h b/src/pulsecore/memblock.h similarity index 93% rename from src/polypcore/memblock.h rename to src/pulsecore/memblock.h index 9471278ad..f85458366 100644 --- a/src/polypcore/memblock.h +++ b/src/pulsecore/memblock.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/memblockq.c b/src/pulsecore/memblockq.c similarity index 98% rename from src/polypcore/memblockq.c rename to src/pulsecore/memblockq.c index 8ed358fa4..ff199f1bd 100644 --- a/src/polypcore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,10 +30,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "memblockq.h" diff --git a/src/polypcore/memblockq.h b/src/pulsecore/memblockq.h similarity index 93% rename from src/polypcore/memblockq.h rename to src/pulsecore/memblockq.h index 74fb00eed..c35b62ddd 100644 --- a/src/polypcore/memblockq.h +++ b/src/pulsecore/memblockq.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,9 +25,9 @@ #include #include -#include -#include -#include +#include +#include +#include /* A memblockq is a queue of pa_memchunks (yepp, the name is not * perfect). It is similar to the ring buffers used by most other diff --git a/src/polypcore/memchunk.c b/src/pulsecore/memchunk.c similarity index 84% rename from src/polypcore/memchunk.c rename to src/pulsecore/memchunk.c index 918b3f0f0..abfc2cab7 100644 --- a/src/polypcore/memchunk.c +++ b/src/pulsecore/memchunk.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,7 +28,7 @@ #include #include -#include +#include #include "memchunk.h" diff --git a/src/polypcore/memchunk.h b/src/pulsecore/memchunk.h similarity index 83% rename from src/polypcore/memchunk.h rename to src/pulsecore/memchunk.h index 3ddb28eeb..1b26c2e64 100644 --- a/src/polypcore/memchunk.h +++ b/src/pulsecore/memchunk.h @@ -4,25 +4,25 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include /* A memchunk describes a part of a memblock. In contrast to the memblock, a * memchunk is not allocated dynamically or reference counted, instead diff --git a/src/polypcore/modargs.c b/src/pulsecore/modargs.c similarity index 94% rename from src/polypcore/modargs.c rename to src/pulsecore/modargs.c index 5d046d269..13a48785b 100644 --- a/src/polypcore/modargs.c +++ b/src/pulsecore/modargs.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,15 +28,15 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "modargs.h" diff --git a/src/polypcore/modargs.h b/src/pulsecore/modargs.h similarity index 87% rename from src/polypcore/modargs.h rename to src/pulsecore/modargs.h index b6977d370..730cf3968 100644 --- a/src/polypcore/modargs.h +++ b/src/pulsecore/modargs.h @@ -4,28 +4,28 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include -#include +#include +#include +#include typedef struct pa_modargs pa_modargs; diff --git a/src/polypcore/modinfo.c b/src/pulsecore/modinfo.c similarity index 87% rename from src/polypcore/modinfo.c rename to src/pulsecore/modinfo.c index a2fffb01f..adefdb46f 100644 --- a/src/polypcore/modinfo.c +++ b/src/pulsecore/modinfo.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,10 +26,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "modinfo.h" diff --git a/src/polypcore/modinfo.h b/src/pulsecore/modinfo.h similarity index 82% rename from src/polypcore/modinfo.h rename to src/pulsecore/modinfo.h index 531761475..f39cee3bb 100644 --- a/src/polypcore/modinfo.h +++ b/src/pulsecore/modinfo.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/module.c b/src/pulsecore/module.c similarity index 95% rename from src/polypcore/module.c rename to src/pulsecore/module.c index 47a878fba..e7dca78d5 100644 --- a/src/polypcore/module.c +++ b/src/pulsecore/module.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -31,12 +31,12 @@ #include #include -#include -#include +#include +#include -#include -#include -#include +#include +#include +#include #include "module.h" diff --git a/src/polypcore/module.h b/src/pulsecore/module.h similarity index 85% rename from src/polypcore/module.h rename to src/pulsecore/module.h index 03b9bc877..9bc5cb5d2 100644 --- a/src/polypcore/module.h +++ b/src/pulsecore/module.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,8 +25,8 @@ #include #include -#include -#include +#include +#include typedef struct pa_module pa_module; diff --git a/src/polypcore/namereg.c b/src/pulsecore/namereg.c similarity index 92% rename from src/polypcore/namereg.c rename to src/pulsecore/namereg.c index 17d751465..0f35ed1c5 100644 --- a/src/polypcore/namereg.c +++ b/src/pulsecore/namereg.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,13 +29,13 @@ #include #include -#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "namereg.h" diff --git a/src/polypcore/namereg.h b/src/pulsecore/namereg.h similarity index 82% rename from src/polypcore/namereg.h rename to src/pulsecore/namereg.h index a98295ff9..e1aef8bb8 100644 --- a/src/polypcore/namereg.h +++ b/src/pulsecore/namereg.h @@ -4,25 +4,25 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include typedef enum pa_namereg_type { PA_NAMEREG_SINK, diff --git a/src/polypcore/native-common.h b/src/pulsecore/native-common.h similarity index 91% rename from src/polypcore/native-common.h rename to src/pulsecore/native-common.h index 1107da552..b35931d00 100644 --- a/src/polypcore/native-common.h +++ b/src/pulsecore/native-common.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include PA_C_DECL_BEGIN @@ -112,7 +112,7 @@ enum { }; #define PA_NATIVE_COOKIE_LENGTH 256 -#define PA_NATIVE_COOKIE_FILE ".polypaudio-cookie" +#define PA_NATIVE_COOKIE_FILE ".pulseaudio-cookie" #define PA_NATIVE_DEFAULT_PORT 4713 diff --git a/src/polypcore/packet.c b/src/pulsecore/packet.c similarity index 85% rename from src/polypcore/packet.c rename to src/pulsecore/packet.c index 646b59e0e..8b010f012 100644 --- a/src/polypcore/packet.c +++ b/src/pulsecore/packet.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,7 +26,7 @@ #include #include -#include +#include #include "packet.h" diff --git a/src/polypcore/packet.h b/src/pulsecore/packet.h similarity index 81% rename from src/polypcore/packet.h rename to src/pulsecore/packet.h index fbc582325..7842857a6 100644 --- a/src/polypcore/packet.h +++ b/src/pulsecore/packet.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/parseaddr.c b/src/pulsecore/parseaddr.c similarity index 90% rename from src/polypcore/parseaddr.c rename to src/pulsecore/parseaddr.c index d0687b05e..da1647af7 100644 --- a/src/polypcore/parseaddr.c +++ b/src/pulsecore/parseaddr.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,10 +27,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "parseaddr.h" diff --git a/src/polypcore/parseaddr.h b/src/pulsecore/parseaddr.h similarity index 81% rename from src/polypcore/parseaddr.h rename to src/pulsecore/parseaddr.h index eff9dd3bd..0393f6657 100644 --- a/src/polypcore/parseaddr.h +++ b/src/pulsecore/parseaddr.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/pdispatch.c b/src/pulsecore/pdispatch.c similarity index 95% rename from src/polypcore/pdispatch.c rename to src/pulsecore/pdispatch.c index c6f90bac4..5b76b432c 100644 --- a/src/polypcore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,13 +27,13 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include +#include +#include +#include +#include #include "pdispatch.h" diff --git a/src/polypcore/pdispatch.h b/src/pulsecore/pdispatch.h similarity index 82% rename from src/polypcore/pdispatch.h rename to src/pulsecore/pdispatch.h index 0074e8b36..07620e5ae 100644 --- a/src/polypcore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -4,29 +4,29 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include -#include -#include +#include +#include +#include +#include typedef struct pa_pdispatch pa_pdispatch; diff --git a/src/polypcore/pid.c b/src/pulsecore/pid.c similarity index 95% rename from src/polypcore/pid.c rename to src/pulsecore/pid.c index a5c0ef0b1..b89728666 100644 --- a/src/polypcore/pid.c +++ b/src/pulsecore/pid.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -39,11 +39,11 @@ #include #endif -#include +#include -#include -#include -#include +#include +#include +#include #include "pid.h" diff --git a/src/polypcore/pid.h b/src/pulsecore/pid.h similarity index 76% rename from src/polypcore/pid.h rename to src/pulsecore/pid.h index 906ab6da8..bd476b292 100644 --- a/src/polypcore/pid.h +++ b/src/pulsecore/pid.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/pipe.c b/src/pulsecore/pipe.c similarity index 93% rename from src/polypcore/pipe.c rename to src/pulsecore/pipe.c index eef6d5335..6933e180d 100644 --- a/src/polypcore/pipe.c +++ b/src/pulsecore/pipe.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify it + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public - License along with polypaudio; If not, write to the Free Software + License along with PulseAudio; If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***/ diff --git a/src/polypcore/pipe.h b/src/pulsecore/pipe.h similarity index 74% rename from src/polypcore/pipe.h rename to src/pulsecore/pipe.h index 276b072d2..a25147603 100644 --- a/src/polypcore/pipe.h +++ b/src/pulsecore/pipe.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify it + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public - License along with polypaudio; If not, write to the Free Software + License along with PulseAudio; If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***/ diff --git a/src/polypcore/play-memchunk.c b/src/pulsecore/play-memchunk.c similarity index 88% rename from src/polypcore/play-memchunk.c rename to src/pulsecore/play-memchunk.c index 982cedc7b..7ac579e9d 100644 --- a/src/polypcore/play-memchunk.c +++ b/src/pulsecore/play-memchunk.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,10 +28,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "play-memchunk.h" diff --git a/src/polypcore/play-memchunk.h b/src/pulsecore/play-memchunk.h similarity index 73% rename from src/polypcore/play-memchunk.h rename to src/pulsecore/play-memchunk.h index 72aeda955..3d5b8cc69 100644 --- a/src/polypcore/play-memchunk.h +++ b/src/pulsecore/play-memchunk.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include int pa_play_memchunk( pa_sink *sink, diff --git a/src/polypcore/poll.c b/src/pulsecore/poll.c similarity index 95% rename from src/polypcore/poll.c rename to src/pulsecore/poll.c index 7b1ed4382..3f9ace7c0 100644 --- a/src/polypcore/poll.c +++ b/src/pulsecore/poll.c @@ -3,21 +3,21 @@ /*** Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. Copyright (C) 2005, Cendio AB. - This file is part of polypaudio. + This file is part of PulseAudio. Based on work for the GNU C Library. - polypaudio is free software; you can redistribute it and/or modify it + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public - License along with polypaudio; If not, write to the Free Software + License along with PulseAudio; If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***/ @@ -42,7 +42,7 @@ #ifndef HAVE_SYS_POLL_H -#include +#include #include "poll.h" diff --git a/src/polypcore/poll.h b/src/pulsecore/poll.h similarity index 91% rename from src/polypcore/poll.h rename to src/pulsecore/poll.h index c201014eb..bed772c78 100644 --- a/src/polypcore/poll.h +++ b/src/pulsecore/poll.h @@ -4,21 +4,21 @@ Compatibility definitions for System V `poll' interface. Copyright (C) 1994,96,97,98,99,2000,2001,2004 Free Software Foundation, Inc. Copyright (C) 2005, Cendio AB. - This file is part of polypaudio. + This file is part of PulseAudio. Based on work for the GNU C Library. - polypaudio is free software; you can redistribute it and/or modify it + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public - License along with polypaudio; If not, write to the Free Software + License along with PulseAudio; If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***/ diff --git a/src/polypcore/props.c b/src/pulsecore/props.c similarity index 90% rename from src/polypcore/props.c rename to src/pulsecore/props.c index 1db44ee75..8879b7aa0 100644 --- a/src/polypcore/props.c +++ b/src/pulsecore/props.c @@ -1,29 +1,29 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include +#include -#include +#include #include "props.h" diff --git a/src/polypcore/props.h b/src/pulsecore/props.h similarity index 86% rename from src/polypcore/props.h rename to src/pulsecore/props.h index 9430db5eb..39b7ca683 100644 --- a/src/polypcore/props.h +++ b/src/pulsecore/props.h @@ -4,26 +4,26 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include +#include +#include /* The property subsystem is to be used to share data between * modules. Consider them to be kind of "global" variables for a diff --git a/src/polypcore/protocol-cli.c b/src/pulsecore/protocol-cli.c similarity index 88% rename from src/polypcore/protocol-cli.c rename to src/pulsecore/protocol-cli.c index 076411cf3..c5854f1e0 100644 --- a/src/polypcore/protocol-cli.c +++ b/src/pulsecore/protocol-cli.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,10 +26,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "protocol-cli.h" diff --git a/src/polypcore/protocol-cli.h b/src/pulsecore/protocol-cli.h similarity index 69% rename from src/polypcore/protocol-cli.h rename to src/pulsecore/protocol-cli.h index c47b14d61..84101e14d 100644 --- a/src/polypcore/protocol-cli.h +++ b/src/pulsecore/protocol-cli.h @@ -4,28 +4,28 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include -#include +#include +#include +#include +#include typedef struct pa_protocol_cli pa_protocol_cli; diff --git a/src/polypcore/protocol-esound.c b/src/pulsecore/protocol-esound.c similarity index 98% rename from src/polypcore/protocol-esound.c rename to src/pulsecore/protocol-esound.c index c9bc504d6..6b9112bf4 100644 --- a/src/polypcore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,25 +30,25 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "endianmacros.h" diff --git a/src/polypcore/protocol-esound.h b/src/pulsecore/protocol-esound.h similarity index 70% rename from src/polypcore/protocol-esound.h rename to src/pulsecore/protocol-esound.h index a94d1c724..79b5acf0b 100644 --- a/src/polypcore/protocol-esound.h +++ b/src/pulsecore/protocol-esound.h @@ -4,28 +4,28 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include -#include +#include +#include +#include +#include typedef struct pa_protocol_esound pa_protocol_esound; diff --git a/src/polypcore/protocol-http.c b/src/pulsecore/protocol-http.c similarity index 95% rename from src/polypcore/protocol-http.c rename to src/pulsecore/protocol-http.c index 86ea3b155..d0d92629c 100644 --- a/src/polypcore/protocol-http.c +++ b/src/pulsecore/protocol-http.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,13 +28,13 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include +#include +#include +#include +#include #include "protocol-http.h" diff --git a/src/polypcore/protocol-http.h b/src/pulsecore/protocol-http.h similarity index 70% rename from src/polypcore/protocol-http.h rename to src/pulsecore/protocol-http.h index 10dd656b6..5d5dba313 100644 --- a/src/polypcore/protocol-http.h +++ b/src/pulsecore/protocol-http.h @@ -4,28 +4,28 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include -#include +#include +#include +#include +#include typedef struct pa_protocol_http pa_protocol_http; diff --git a/src/polypcore/protocol-native.c b/src/pulsecore/protocol-native.c similarity index 98% rename from src/polypcore/protocol-native.c rename to src/pulsecore/protocol-native.c index 221601a69..1f936e753 100644 --- a/src/polypcore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,32 +29,32 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "protocol-native.h" diff --git a/src/polypcore/protocol-native.h b/src/pulsecore/protocol-native.h similarity index 73% rename from src/polypcore/protocol-native.h rename to src/pulsecore/protocol-native.h index 88aa8494f..5b0910144 100644 --- a/src/polypcore/protocol-native.h +++ b/src/pulsecore/protocol-native.h @@ -4,28 +4,28 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include -#include +#include +#include +#include +#include typedef struct pa_protocol_native pa_protocol_native; diff --git a/src/polypcore/protocol-simple.c b/src/pulsecore/protocol-simple.c similarity index 96% rename from src/polypcore/protocol-simple.c rename to src/pulsecore/protocol-simple.c index 8b319d70f..4d73bd24d 100644 --- a/src/polypcore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,15 +30,15 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "protocol-simple.h" diff --git a/src/polypcore/protocol-simple.h b/src/pulsecore/protocol-simple.h similarity index 70% rename from src/polypcore/protocol-simple.h rename to src/pulsecore/protocol-simple.h index f11c77592..8dfaee349 100644 --- a/src/polypcore/protocol-simple.h +++ b/src/pulsecore/protocol-simple.h @@ -4,28 +4,28 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include -#include +#include +#include +#include +#include typedef struct pa_protocol_simple pa_protocol_simple; diff --git a/src/polypcore/pstream-util.c b/src/pulsecore/pstream-util.c similarity index 85% rename from src/polypcore/pstream-util.c rename to src/pulsecore/pstream-util.c index bd1d1a87f..3a995324d 100644 --- a/src/polypcore/pstream-util.c +++ b/src/pulsecore/pstream-util.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -25,7 +25,7 @@ #include -#include +#include #include "pstream-util.h" diff --git a/src/polypcore/pstream-util.h b/src/pulsecore/pstream-util.h similarity index 77% rename from src/polypcore/pstream-util.h rename to src/pulsecore/pstream-util.h index f2677a440..fc6d18c05 100644 --- a/src/polypcore/pstream-util.h +++ b/src/pulsecore/pstream-util.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include +#include +#include /* The tagstruct is freed!*/ void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, int creds); diff --git a/src/polypcore/pstream.c b/src/pulsecore/pstream.c similarity index 97% rename from src/polypcore/pstream.c rename to src/pulsecore/pstream.c index 074cab916..60c059381 100644 --- a/src/polypcore/pstream.c +++ b/src/pulsecore/pstream.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -34,11 +34,11 @@ #include "winsock.h" -#include +#include -#include -#include -#include +#include +#include +#include #include "pstream.h" diff --git a/src/polypcore/pstream.h b/src/pulsecore/pstream.h similarity index 81% rename from src/polypcore/pstream.h rename to src/pulsecore/pstream.h index feb1b1517..1a2932d4f 100644 --- a/src/polypcore/pstream.h +++ b/src/pulsecore/pstream.h @@ -4,32 +4,32 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include typedef struct pa_pstream pa_pstream; diff --git a/src/polypcore/queue.c b/src/pulsecore/queue.c similarity index 88% rename from src/polypcore/queue.c rename to src/pulsecore/queue.c index 01f957d9b..93b119ebc 100644 --- a/src/polypcore/queue.c +++ b/src/pulsecore/queue.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,7 +26,7 @@ #include #include -#include +#include #include "queue.h" diff --git a/src/polypcore/queue.h b/src/pulsecore/queue.h similarity index 83% rename from src/polypcore/queue.h rename to src/pulsecore/queue.h index 3edcfb635..3fb9dea45 100644 --- a/src/polypcore/queue.h +++ b/src/pulsecore/queue.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/random.c b/src/pulsecore/random.c similarity index 88% rename from src/polypcore/random.c rename to src/pulsecore/random.c index d7a37b0b0..3d3357a5e 100644 --- a/src/polypcore/random.c +++ b/src/pulsecore/random.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -31,8 +31,8 @@ #include #include -#include -#include +#include +#include #include "random.h" diff --git a/src/polypcore/random.h b/src/pulsecore/random.h similarity index 75% rename from src/polypcore/random.h rename to src/pulsecore/random.h index 1f152dc73..f809afec4 100644 --- a/src/polypcore/random.h +++ b/src/pulsecore/random.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/resampler.c b/src/pulsecore/resampler.c similarity index 98% rename from src/polypcore/resampler.c rename to src/pulsecore/resampler.c index 33e8c2959..23cdf3811 100644 --- a/src/polypcore/resampler.c +++ b/src/pulsecore/resampler.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,10 +30,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "resampler.h" diff --git a/src/polypcore/resampler.h b/src/pulsecore/resampler.h similarity index 86% rename from src/polypcore/resampler.h rename to src/pulsecore/resampler.h index 2f4d3cbe8..c1199e5ce 100644 --- a/src/polypcore/resampler.h +++ b/src/pulsecore/resampler.h @@ -4,30 +4,30 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include -#include -#include +#include +#include +#include +#include typedef struct pa_resampler pa_resampler; diff --git a/src/polypcore/sample-util.c b/src/pulsecore/sample-util.c similarity index 98% rename from src/polypcore/sample-util.c rename to src/pulsecore/sample-util.c index 7a75ce1cf..638f80670 100644 --- a/src/polypcore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,7 +30,7 @@ #include -#include +#include #include "sample-util.h" #include "endianmacros.h" diff --git a/src/polypcore/sample-util.h b/src/pulsecore/sample-util.h similarity index 79% rename from src/polypcore/sample-util.h rename to src/pulsecore/sample-util.h index da7f56e15..3ebb7e2ea 100644 --- a/src/polypcore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -4,28 +4,28 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include -#include +#include +#include +#include +#include pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec); pa_memblock *pa_silence_memblock_new(const pa_sample_spec *spec, size_t length, pa_memblock_stat*s); diff --git a/src/polypcore/sconv-s16be.c b/src/pulsecore/sconv-s16be.c similarity index 80% rename from src/polypcore/sconv-s16be.c rename to src/pulsecore/sconv-s16be.c index 8b076f06f..5ac96320e 100644 --- a/src/polypcore/sconv-s16be.c +++ b/src/pulsecore/sconv-s16be.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/sconv-s16be.h b/src/pulsecore/sconv-s16be.h similarity index 77% rename from src/polypcore/sconv-s16be.h rename to src/pulsecore/sconv-s16be.h index b2b6a8c74..bd3fd3454 100644 --- a/src/polypcore/sconv-s16be.h +++ b/src/pulsecore/sconv-s16be.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c similarity index 86% rename from src/polypcore/sconv-s16le.c rename to src/pulsecore/sconv-s16le.c index 0814c35b5..d8b93cbda 100644 --- a/src/polypcore/sconv-s16le.c +++ b/src/pulsecore/sconv-s16le.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,8 +28,8 @@ #include -#include -#include +#include +#include #include "endianmacros.h" diff --git a/src/polypcore/sconv-s16le.h b/src/pulsecore/sconv-s16le.h similarity index 77% rename from src/polypcore/sconv-s16le.h rename to src/pulsecore/sconv-s16le.h index ef5e31e8a..ae6e22d21 100644 --- a/src/polypcore/sconv-s16le.h +++ b/src/pulsecore/sconv-s16le.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/sconv.c b/src/pulsecore/sconv.c similarity index 93% rename from src/polypcore/sconv.c rename to src/pulsecore/sconv.c index c557be67b..ff2a0110c 100644 --- a/src/polypcore/sconv.c +++ b/src/pulsecore/sconv.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,7 +30,7 @@ #include #include -#include +#include #include "endianmacros.h" #include "sconv-s16le.h" diff --git a/src/polypcore/sconv.h b/src/pulsecore/sconv.h similarity index 79% rename from src/polypcore/sconv.h rename to src/pulsecore/sconv.h index a0c15c24f..4aba06944 100644 --- a/src/polypcore/sconv.h +++ b/src/pulsecore/sconv.h @@ -4,25 +4,25 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, float *b); typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b); diff --git a/src/polypcore/sink-input.c b/src/pulsecore/sink-input.c similarity index 96% rename from src/polypcore/sink-input.c rename to src/pulsecore/sink-input.c index bd2a1dcd1..8590a0b1d 100644 --- a/src/polypcore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,12 +28,12 @@ #include #include -#include -#include +#include +#include -#include -#include -#include +#include +#include +#include #include "sink-input.h" diff --git a/src/polypcore/sink-input.h b/src/pulsecore/sink-input.h similarity index 86% rename from src/polypcore/sink-input.h rename to src/pulsecore/sink-input.h index 4cf4460a4..69a7e50a1 100644 --- a/src/polypcore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,12 +26,12 @@ typedef struct pa_sink_input pa_sink_input; -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include typedef enum pa_sink_input_state { PA_SINK_INPUT_RUNNING, diff --git a/src/polypcore/sink.c b/src/pulsecore/sink.c similarity index 95% rename from src/polypcore/sink.c rename to src/pulsecore/sink.c index dc27ca2e5..ee6850f08 100644 --- a/src/polypcore/sink.c +++ b/src/pulsecore/sink.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,16 +28,16 @@ #include #include -#include -#include -#include +#include +#include +#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include "sink.h" diff --git a/src/polypcore/sink.h b/src/pulsecore/sink.h similarity index 83% rename from src/polypcore/sink.h rename to src/pulsecore/sink.h index 59d455972..fdff0522d 100644 --- a/src/polypcore/sink.h +++ b/src/pulsecore/sink.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,14 +26,14 @@ typedef struct pa_sink pa_sink; -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #define PA_MAX_INPUTS_PER_SINK 32 diff --git a/src/polypcore/sioman.c b/src/pulsecore/sioman.c similarity index 79% rename from src/polypcore/sioman.c rename to src/pulsecore/sioman.c index b389eceef..d84010ee9 100644 --- a/src/polypcore/sioman.c +++ b/src/pulsecore/sioman.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/sioman.h b/src/pulsecore/sioman.h similarity index 74% rename from src/polypcore/sioman.h rename to src/pulsecore/sioman.h index 840d93f23..cd04d140e 100644 --- a/src/polypcore/sioman.h +++ b/src/pulsecore/sioman.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/socket-client.c b/src/pulsecore/socket-client.c similarity index 96% rename from src/polypcore/socket-client.c rename to src/pulsecore/socket-client.c index efb6de9a9..8e547614d 100644 --- a/src/polypcore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -54,14 +54,14 @@ #include "winsock.h" -#include -#include +#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "socket-client.h" diff --git a/src/polypcore/socket-client.h b/src/pulsecore/socket-client.h similarity index 83% rename from src/polypcore/socket-client.h rename to src/pulsecore/socket-client.h index d00053310..47e7cd5a9 100644 --- a/src/polypcore/socket-client.h +++ b/src/pulsecore/socket-client.h @@ -4,28 +4,28 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include +#include +#include struct sockaddr; diff --git a/src/polypcore/socket-server.c b/src/pulsecore/socket-server.c similarity index 97% rename from src/polypcore/socket-server.c rename to src/pulsecore/socket-server.c index 17071ec27..77ea13e70 100644 --- a/src/polypcore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -62,13 +62,13 @@ #include "winsock.h" -#include -#include +#include +#include -#include -#include -#include -#include +#include +#include +#include +#include #include "socket-server.h" diff --git a/src/polypcore/socket-server.h b/src/pulsecore/socket-server.h similarity index 88% rename from src/polypcore/socket-server.h rename to src/pulsecore/socket-server.h index cd3276ad8..d90c8194e 100644 --- a/src/polypcore/socket-server.h +++ b/src/pulsecore/socket-server.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include -#include +#include +#include /* It is safe to destroy the calling socket_server object from the callback */ diff --git a/src/polypcore/socket-util.c b/src/pulsecore/socket-util.c similarity index 94% rename from src/polypcore/socket-util.c rename to src/pulsecore/socket-util.c index 3cd205db0..8705560d9 100644 --- a/src/polypcore/socket-util.c +++ b/src/pulsecore/socket-util.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -66,11 +66,11 @@ #include "winsock.h" -#include +#include -#include -#include -#include +#include +#include +#include #include "socket-util.h" diff --git a/src/polypcore/socket-util.h b/src/pulsecore/socket-util.h similarity index 80% rename from src/polypcore/socket-util.h rename to src/pulsecore/socket-util.h index ae16fb164..f8248ae72 100644 --- a/src/polypcore/socket-util.h +++ b/src/pulsecore/socket-util.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c similarity index 93% rename from src/polypcore/sound-file-stream.c rename to src/pulsecore/sound-file-stream.c index 68fd8a89c..386f5bd01 100644 --- a/src/polypcore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,10 +30,10 @@ #include -#include +#include -#include -#include +#include +#include #include "sound-file-stream.h" diff --git a/src/polypcore/sound-file-stream.h b/src/pulsecore/sound-file-stream.h similarity index 73% rename from src/polypcore/sound-file-stream.h rename to src/pulsecore/sound-file-stream.h index 5effc7f03..28e6a8ba9 100644 --- a/src/polypcore/sound-file-stream.h +++ b/src/pulsecore/sound-file-stream.h @@ -4,25 +4,25 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume); diff --git a/src/polypcore/sound-file.c b/src/pulsecore/sound-file.c similarity index 93% rename from src/polypcore/sound-file.c rename to src/pulsecore/sound-file.c index bd0cf5961..d11d4b9d9 100644 --- a/src/polypcore/sound-file.c +++ b/src/pulsecore/sound-file.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,8 +28,8 @@ #include -#include -#include +#include +#include #include "sound-file.h" #include "core-scache.h" diff --git a/src/polypcore/sound-file.h b/src/pulsecore/sound-file.h similarity index 71% rename from src/polypcore/sound-file.h rename to src/pulsecore/sound-file.h index 9d687f90e..0b81d97e1 100644 --- a/src/polypcore/sound-file.h +++ b/src/pulsecore/sound-file.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include -#include -#include +#include +#include +#include int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk, pa_memblock_stat *s); diff --git a/src/polypcore/source-output.c b/src/pulsecore/source-output.c similarity index 94% rename from src/polypcore/source-output.c rename to src/pulsecore/source-output.c index 8ac3a33d4..230b416d8 100644 --- a/src/polypcore/source-output.c +++ b/src/pulsecore/source-output.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,11 +28,11 @@ #include #include -#include -#include +#include +#include -#include -#include +#include +#include #include "source-output.h" diff --git a/src/polypcore/source-output.h b/src/pulsecore/source-output.h similarity index 84% rename from src/polypcore/source-output.h rename to src/pulsecore/source-output.h index 1c6120522..ef398dd1a 100644 --- a/src/polypcore/source-output.h +++ b/src/pulsecore/source-output.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,12 +26,12 @@ typedef struct pa_source_output pa_source_output; -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include typedef enum { PA_SOURCE_OUTPUT_RUNNING, diff --git a/src/polypcore/source.c b/src/pulsecore/source.c similarity index 94% rename from src/polypcore/source.c rename to src/pulsecore/source.c index c53bf079f..84151a929 100644 --- a/src/polypcore/source.c +++ b/src/pulsecore/source.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,14 +28,14 @@ #include #include -#include -#include +#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "source.h" diff --git a/src/polypcore/source.h b/src/pulsecore/source.h similarity index 81% rename from src/polypcore/source.h rename to src/pulsecore/source.h index 63b77624b..6255c1156 100644 --- a/src/polypcore/source.h +++ b/src/pulsecore/source.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,16 +26,16 @@ typedef struct pa_source pa_source; #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define PA_MAX_OUTPUTS_PER_SOURCE 16 diff --git a/src/polypcore/strbuf.c b/src/pulsecore/strbuf.c similarity index 93% rename from src/polypcore/strbuf.c rename to src/pulsecore/strbuf.c index d1517a11e..ef8160dc5 100644 --- a/src/polypcore/strbuf.c +++ b/src/pulsecore/strbuf.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -30,7 +30,7 @@ #include #include -#include +#include #include "strbuf.h" diff --git a/src/polypcore/strbuf.h b/src/pulsecore/strbuf.h similarity index 79% rename from src/polypcore/strbuf.h rename to src/pulsecore/strbuf.h index 4b06a7e60..c45fb15f6 100644 --- a/src/polypcore/strbuf.h +++ b/src/pulsecore/strbuf.h @@ -4,25 +4,25 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#include +#include typedef struct pa_strbuf pa_strbuf; diff --git a/src/polypcore/strlist.c b/src/pulsecore/strlist.c similarity index 89% rename from src/polypcore/strlist.c rename to src/pulsecore/strlist.c index b94207496..df3a02751 100644 --- a/src/polypcore/strlist.c +++ b/src/pulsecore/strlist.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -26,10 +26,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "strlist.h" diff --git a/src/polypcore/strlist.h b/src/pulsecore/strlist.h similarity index 86% rename from src/polypcore/strlist.h rename to src/pulsecore/strlist.h index 2c54dc748..87925d5ec 100644 --- a/src/polypcore/strlist.h +++ b/src/pulsecore/strlist.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/tagstruct.c b/src/pulsecore/tagstruct.c similarity index 98% rename from src/polypcore/tagstruct.c rename to src/pulsecore/tagstruct.c index 27582cae1..60b05a3fa 100644 --- a/src/polypcore/tagstruct.c +++ b/src/pulsecore/tagstruct.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -36,7 +36,7 @@ #include "winsock.h" -#include +#include #include "tagstruct.h" diff --git a/src/polypcore/tagstruct.h b/src/pulsecore/tagstruct.h similarity index 90% rename from src/polypcore/tagstruct.h rename to src/pulsecore/tagstruct.h index d5e6050b6..4c56f3281 100644 --- a/src/polypcore/tagstruct.h +++ b/src/pulsecore/tagstruct.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,9 +27,9 @@ #include #include -#include -#include -#include +#include +#include +#include typedef struct pa_tagstruct pa_tagstruct; diff --git a/src/polypcore/tokenizer.c b/src/pulsecore/tokenizer.c similarity index 85% rename from src/polypcore/tokenizer.c rename to src/pulsecore/tokenizer.c index 667643fe6..e799c1e64 100644 --- a/src/polypcore/tokenizer.c +++ b/src/pulsecore/tokenizer.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,10 +27,10 @@ #include #include -#include +#include -#include -#include +#include +#include #include "tokenizer.h" diff --git a/src/polypcore/tokenizer.h b/src/pulsecore/tokenizer.h similarity index 78% rename from src/polypcore/tokenizer.h rename to src/pulsecore/tokenizer.h index bedacb8a9..b9a5c55b9 100644 --- a/src/polypcore/tokenizer.h +++ b/src/pulsecore/tokenizer.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/winsock.h b/src/pulsecore/winsock.h similarity index 100% rename from src/polypcore/winsock.h rename to src/pulsecore/winsock.h diff --git a/src/polypcore/x11prop.c b/src/pulsecore/x11prop.c similarity index 88% rename from src/polypcore/x11prop.c rename to src/pulsecore/x11prop.c index e57fc136e..dd4ff99eb 100644 --- a/src/polypcore/x11prop.c +++ b/src/pulsecore/x11prop.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/x11prop.h b/src/pulsecore/x11prop.h similarity index 78% rename from src/polypcore/x11prop.h rename to src/pulsecore/x11prop.h index 5531c6403..bd24951a1 100644 --- a/src/polypcore/x11prop.h +++ b/src/pulsecore/x11prop.h @@ -4,20 +4,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ diff --git a/src/polypcore/x11wrap.c b/src/pulsecore/x11wrap.c similarity index 94% rename from src/polypcore/x11wrap.c rename to src/pulsecore/x11wrap.c index b53a43b60..2ba0a87fb 100644 --- a/src/polypcore/x11wrap.c +++ b/src/pulsecore/x11wrap.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -22,11 +22,11 @@ #include #include -#include +#include -#include -#include -#include +#include +#include +#include #include "x11wrap.h" diff --git a/src/polypcore/x11wrap.h b/src/pulsecore/x11wrap.h similarity index 85% rename from src/polypcore/x11wrap.h rename to src/pulsecore/x11wrap.h index 15969869d..fcdd9f6c8 100644 --- a/src/polypcore/x11wrap.h +++ b/src/pulsecore/x11wrap.h @@ -4,27 +4,27 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include -#include +#include typedef struct pa_x11_wrapper pa_x11_wrapper; diff --git a/src/tests/Makefile b/src/tests/Makefile index cd2a5c9a6..c110232d3 120000 --- a/src/tests/Makefile +++ b/src/tests/Makefile @@ -1 +1 @@ -../polyp/Makefile \ No newline at end of file +../pulse/Makefile \ No newline at end of file diff --git a/src/tests/channelmap-test.c b/src/tests/channelmap-test.c index c6644229b..124ce5768 100644 --- a/src/tests/channelmap-test.c +++ b/src/tests/channelmap-test.c @@ -3,8 +3,8 @@ #include #include -#include -#include +#include +#include int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; diff --git a/src/tests/cpulimit-test.c b/src/tests/cpulimit-test.c index b51014c85..2302a26d5 100644 --- a/src/tests/cpulimit-test.c +++ b/src/tests/cpulimit-test.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,11 +29,11 @@ #include #include -#include -#include +#include +#include #ifdef TEST2 -#include +#include #endif #include "../daemon/cpulimit.h" diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c index fa5fae7d8..7cabc1c9c 100644 --- a/src/tests/interpol-test.c +++ b/src/tests/interpol-test.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -34,8 +34,8 @@ #include #include -#include -#include +#include +#include static pa_context *context = NULL; static pa_stream *stream = NULL; diff --git a/src/tests/mainloop-test.c b/src/tests/mainloop-test.c index 2936420c3..671adeff2 100644 --- a/src/tests/mainloop-test.c +++ b/src/tests/mainloop-test.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,15 +28,15 @@ #include #include -#include +#include -#include -#include +#include +#include #ifdef GLIB_MAIN_LOOP #include -#include +#include static GMainLoop* glib_main_loop = NULL; @@ -48,7 +48,7 @@ static GMainLoop* glib_main_loop = NULL; #else /* GLIB_MAIN_LOOP */ -#include +#include #endif /* GLIB_MAIN_LOOP */ static pa_defer_event *de; diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index 765dcf943..ccb0613e8 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with polypaudio; if not, write to the Free Software + License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -31,9 +31,9 @@ #include #include -#include -#include -#include +#include +#include +#include /* A simple program for testing pa_mcalign */ diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c index e9764627c..af43d06f1 100644 --- a/src/tests/memblockq-test.c +++ b/src/tests/memblockq-test.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,8 +27,8 @@ #include #include -#include -#include +#include +#include int main(int argc, char *argv[]) { int ret; diff --git a/src/tests/pacat-simple.c b/src/tests/pacat-simple.c index 9d8cc9215..364e1ad61 100644 --- a/src/tests/pacat-simple.c +++ b/src/tests/pacat-simple.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -29,9 +29,9 @@ #include #include -#include -#include -#include +#include +#include +#include #define BUFSIZE 1024 diff --git a/src/tests/parec-simple.c b/src/tests/parec-simple.c index 4463d5493..45a522888 100644 --- a/src/tests/parec-simple.c +++ b/src/tests/parec-simple.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,9 +28,9 @@ #include #include -#include -#include -#include +#include +#include +#include #define BUFSIZE 1024 diff --git a/src/tests/strlist-test.c b/src/tests/strlist-test.c index 415c94e6a..4262a0015 100644 --- a/src/tests/strlist-test.c +++ b/src/tests/strlist-test.c @@ -1,8 +1,8 @@ #include -#include -#include -#include +#include +#include +#include int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) { char *t, *u; diff --git a/src/tests/sync-playback.c b/src/tests/sync-playback.c index d675e01cc..39c6aac46 100644 --- a/src/tests/sync-playback.c +++ b/src/tests/sync-playback.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -33,8 +33,8 @@ #include #include -#include -#include +#include +#include #define NSTREAMS 4 #define SINE_HZ 440 diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c index aef3aff05..bf3d4cd2c 100644 --- a/src/tests/thread-mainloop-test.c +++ b/src/tests/thread-mainloop-test.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -28,11 +28,11 @@ #include #include -#include -#include +#include +#include -#include -#include +#include +#include static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { fprintf(stderr, "TIME EVENT START\n"); diff --git a/src/tests/utf8-test.c b/src/tests/utf8-test.c index 2c21613e9..2e9f128a7 100644 --- a/src/tests/utf8-test.c +++ b/src/tests/utf8-test.c @@ -3,8 +3,8 @@ #include #include -#include -#include +#include +#include int main(int argc, char *argv[]) { char *c; diff --git a/src/tests/voltest.c b/src/tests/voltest.c index 4db8ef285..3de884aff 100644 --- a/src/tests/voltest.c +++ b/src/tests/voltest.c @@ -2,8 +2,8 @@ #include -#include -#include +#include +#include int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { pa_volume_t v; diff --git a/src/utils/Makefile b/src/utils/Makefile index cd2a5c9a6..c110232d3 120000 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -1 +1 @@ -../polyp/Makefile \ No newline at end of file +../pulse/Makefile \ No newline at end of file diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 8063a28ba..954e4e6c2 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -27,8 +27,8 @@ #include #include -#include -#include +#include +#include static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { fprintf(stderr, "Got signal, exiting\n"); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 99e54e641..5e4596d15 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -33,7 +33,7 @@ #include #include -#include +#include #define TIME_EVENT_USEC 50000 @@ -479,7 +479,7 @@ int main(int argc, char *argv[]) { goto quit; case ARG_VERSION: - printf("pacat "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + printf("pacat "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; goto quit; diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index ad50c77c7..e4a0970d2 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -32,12 +32,12 @@ #include #include -#include -#include +#include +#include -#include -#include -#include +#include +#include +#include int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { pid_t pid ; diff --git a/src/utils/pactl.c b/src/utils/pactl.c index cc59e4595..6e40f3fec 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -35,7 +35,7 @@ #include -#include +#include #if PA_API_VERSION != 9 #error Invalid Polypaudio API version @@ -644,7 +644,7 @@ int main(int argc, char *argv[]) { goto quit; case ARG_VERSION: - printf("pactl "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + printf("pactl "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; goto quit; diff --git a/src/utils/padsp b/src/utils/padsp index 27f99336b..6e7e9f06c 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -2,20 +2,20 @@ # $Id$ # -# This file is part of polypaudio. +# This file is part of PulseAudio. # -# polypaudio is free software; you can redistribute it and/or modify +# PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # -# polypaudio is distributed in the hope that it will be useful, but +# PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License -# along with polypaudio; if not, write to the Free Software +# along with PulseAudio; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. @@ -75,9 +75,9 @@ done shift $(( $OPTIND - 1 )) if [ x"$LD_PRELOAD" = x ] ; then - LD_PRELOAD="libpolypdsp.so" + LD_PRELOAD="libpulsedsp.so" else - LD_PRELOAD="$LD_PRELOAD libpolypdsp.so" + LD_PRELOAD="$LD_PRELOAD libpulsedsp.so" fi export LD_PRELOAD diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 56acbb28e..13f571e1e 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -46,9 +46,9 @@ #include -#include -#include -#include +#include +#include +#include typedef enum { FD_INFO_MIXER, diff --git a/src/utils/paplay.c b/src/utils/paplay.c index effc2a111..4b4a1ea6c 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -35,7 +35,7 @@ #include -#include +#include #if PA_API_VERSION != 9 #error Invalid Polypaudio API version @@ -253,7 +253,7 @@ int main(int argc, char *argv[]) { goto quit; case ARG_VERSION: - printf("paplay "PACKAGE_VERSION"\nCompiled with libpolyp %s\nLinked with libpolyp %s\n", pa_get_headers_version(), pa_get_library_version()); + printf("paplay "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; goto quit; diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 668361c6f..770455b99 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -31,15 +31,15 @@ #include #include -#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include "../polyp/client-conf.h" +#include "../pulse/client-conf.h" int main(int argc, char *argv[]) { const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE; From 25f79693b150eb157a92d48036b904d3f7132a08 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 21:55:07 +0000 Subject: [PATCH 0937/1514] rename polypaudio.h to pulseaudio.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1034 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/{polypaudio.h => pulseaudio.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/pulse/{polypaudio.h => pulseaudio.h} (100%) diff --git a/src/pulse/polypaudio.h b/src/pulse/pulseaudio.h similarity index 100% rename from src/pulse/polypaudio.h rename to src/pulse/pulseaudio.h From 955e33db6076a6266d4decfbeb64d89a9b8d516c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 22:03:39 +0000 Subject: [PATCH 0938/1514] hide pulseadudio binary from SVN git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1035 fefdeb5f-60dc-0310-8127-8f9354f1896f --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index bc633bd14..612c23415 100644 --- a/LICENSE +++ b/LICENSE @@ -5,7 +5,7 @@ However, the server side links to the GPL-only library 'libsamplerate' which practically downgrades the license of the server part to GPL (see file GPL for details), exercising section 3 of the LGPL. -Hence you should treat the client library ('libpulse') of Polypaudio as being +Hence you should treat the client library ('libpulse') of PulseAudio as being LGPL licensed and the server part ('libpulsecore') as being GPL licensed. Since the PulseAudio daemon and the modules link to 'libpulsecore' they are of course also GPL licensed. From 10b5e997d7a8a4e955ce49cc816fdcd36225ff6e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 22:11:49 +0000 Subject: [PATCH 0939/1514] replace a few remaining uppercase "Polypaudio" occurences with "PulseAudio" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1036 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.h | 2 +- src/modules/module-esound-sink.c | 2 +- src/modules/module-x11-publish.c | 2 +- src/pulse/context.h | 2 +- src/pulse/introspect.h | 6 +++--- src/pulse/pulseaudio.h | 2 +- src/pulse/sample.h | 10 +++++----- src/pulse/stream.h | 16 ++++++++-------- src/pulse/thread-mainloop.h | 14 +++++++------- src/pulse/version.h.in | 4 ++-- src/pulse/volume.h | 8 ++++---- src/pulsecore/memblock.h | 2 +- src/pulsecore/modinfo.h | 2 +- src/utils/pacat.c | 2 +- src/utils/pacmd.c | 4 ++-- src/utils/pactl.c | 2 +- src/utils/padsp | 4 ++-- src/utils/padsp.c | 12 ++++++------ src/utils/paplay.c | 2 +- src/utils/pax11publish.c | 8 ++++---- 20 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index dd5d7fb84..c325495c2 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -35,7 +35,7 @@ typedef enum pa_daemon_conf_cmd { PA_CMD_CHECK } pa_daemon_conf_cmd_t; -/* A structure containing configuration data for the Polypaudio server . */ +/* A structure containing configuration data for the PulseAudio server . */ typedef struct pa_daemon_conf { pa_daemon_conf_cmd_t cmd; int daemonize, diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 75a47b04e..86ffaf788 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -211,7 +211,7 @@ static int handle_response(struct userdata *u) { *(p++) = ESD_PROTO_STREAM_PLAY; *(p++) = u->format; *(p++) = u->rate; - pa_strlcpy((char*) p, "Polypaudio Tunnel", ESD_NAME_MAX); + pa_strlcpy((char*) p, "PulseAudio Tunnel", ESD_NAME_MAX); u->write_index = 0; u->state = STATE_RUNNING; diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index 991630354..05f0d86a5 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -168,7 +168,7 @@ void pa__done(pa_core *c, pa_module*m) { /* Yes, here is a race condition */ if (!pa_x11_get_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_ID", t, sizeof(t)) || strcmp(t, u->id)) - pa_log_warn(__FILE__": Polypaudio information vanished from X11!"); + pa_log_warn(__FILE__": PulseAudio information vanished from X11!"); else { pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_ID"); pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SERVER"); diff --git a/src/pulse/context.h b/src/pulse/context.h index 65d70e8b1..ad8c9f3fa 100644 --- a/src/pulse/context.h +++ b/src/pulse/context.h @@ -59,7 +59,7 @@ * * \li \subpage mainloop - A minimal but fast implementation based on poll(). * \li \subpage threaded_mainloop - A special version of the previous - * implementation where all of Polypaudio's + * implementation where all of PulseAudio's * internal handling runs in a separate * thread. * \li \subpage glib-mainloop - A wrapper around GLIB's main loop. Available diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h index 8fe218bcd..23d736c65 100644 --- a/src/pulse/introspect.h +++ b/src/pulse/introspect.h @@ -35,7 +35,7 @@ * \section overv_sec Overview * * Sometimes it is necessary to query and modify global settings in the - * server. For this, Polypaudio has the introspection API. It can list sinks, + * server. For this, PulseAudio has the introspection API. It can list sinks, * sources, samples and other aspects of the server. It can also modify the * attributes of the server that will affect operations on a global level, * and not just the application's context. @@ -121,7 +121,7 @@ * * \subsection module_subsec Driver Modules * - * Polypaudio driver modules are identified by index and are retrieved using either + * PulseAudio driver modules are identified by index and are retrieved using either * pa_context_get_module_info() or pa_context_get_module_info_list(). The * information structure is called pa_module_info. * @@ -137,7 +137,7 @@ * * \subsection client_subsec Clients * - * Polypaudio clients are also identified by index and are retrieved using + * PulseAudio clients are also identified by index and are retrieved using * either pa_context_get_client_info() or pa_context_get_client_info_list(). * The information structure is called pa_client_info. * diff --git a/src/pulse/pulseaudio.h b/src/pulse/pulseaudio.h index 5bbd4cc52..5c526dc70 100644 --- a/src/pulse/pulseaudio.h +++ b/src/pulse/pulseaudio.h @@ -63,7 +63,7 @@ * \li The complete but somewhat complicated to use asynchronous API * \li The simplified, easy to use, but limited synchronous API * - * All strings in Polypaudio are in the UTF-8 encoding, regardless of current + * All strings in PulseAudio are in the UTF-8 encoding, regardless of current * locale. Some functions will filter invalid sequences from the string, some * will simply fail. To ensure reliable behaviour, make sure everything you * pass to the API is already in UTF-8. diff --git a/src/pulse/sample.h b/src/pulse/sample.h index 848fd16dc..03965a99d 100644 --- a/src/pulse/sample.h +++ b/src/pulse/sample.h @@ -32,12 +32,12 @@ * * \section overv_sec Overview * - * Polypaudio is capable of handling a multitude of sample formats, rates + * PulseAudio is capable of handling a multitude of sample formats, rates * and channels, transparently converting and mixing them as needed. * * \section format_sec Sample Format * - * Polypaudio supports the following sample formats: + * PulseAudio supports the following sample formats: * * \li PA_SAMPLE_U8 - Unsigned 8 bit PCM. * \li PA_SAMPLE_S16LE - Signed 16 bit PCM, little endian. @@ -54,20 +54,20 @@ * * \section rate_sec Sample Rates * - * Polypaudio supports any sample rate between 1 Hz and 4 GHz. There is no + * PulseAudio supports any sample rate between 1 Hz and 4 GHz. There is no * point trying to exceed the sample rate of the output device though as the * signal will only get downsampled, consuming CPU on the machine running the * server. * * \section chan_sec Channels * - * Polypaudio supports up to 16 individiual channels. The order of the + * PulseAudio supports up to 16 individiual channels. The order of the * channels is up to the application, but they must be continous. To map * channels to speakers, see \ref channelmap. * * \section calc_sec Calculations * - * The Polypaudio library contains a number of convenience functions to do + * The PulseAudio library contains a number of convenience functions to do * calculations on sample formats: * * \li pa_bytes_per_second() - The number of bytes one second of audio will diff --git a/src/pulse/stream.h b/src/pulse/stream.h index d117ce4a3..ad15125ab 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -107,7 +107,7 @@ * wrap. The current read/write index may be queried using * pa_stream_get_timing_info() (see below for more information). In * case of a buffer underrun the read index is equal or larger than - * the write index. Unless the prebuf value is 0, Polypaudio will + * the write index. Unless the prebuf value is 0, PulseAudio will * temporarily pause playback in such a case, and wait until the * buffer is filled up to prebuf bytes again. If prebuf is 0, the * read index may be larger than the write index, in which case @@ -169,7 +169,7 @@ * \section latency_sec Latency * * A major problem with networked audio is the increased latency caused by - * the network. To remedy this, Polypaudio supports an advanced system of + * the network. To remedy this, PulseAudio supports an advanced system of * monitoring the current latency. * * To get the raw data needed to calculate latencies, call @@ -183,14 +183,14 @@ * pa_stream_update_timing_info() operation is executed. (i.e. before * the first call to this function the timing information structure is * not available!) Since it is a lot of work to keep this structure - * up-to-date manually, Polypaudio can do that automatically for you: + * up-to-date manually, PulseAudio can do that automatically for you: * if PA_STREAM_AUTO_TIMING_UPDATE is passed when connecting the - * stream Polypaudio will automatically update the structure every + * stream PulseAudio will automatically update the structure every * 100ms and every time a function is called that might invalidate the * previously known timing data (such as pa_stream_write() or * pa_stream_flush()). Please note however, that there always is a * short time window when the data in the timing information structure - * is out-of-date. Polypaudio tries to mark these situations by + * is out-of-date. PulseAudio tries to mark these situations by * setting the write_index_corrupt and read_index_corrupt fields * accordingly. * @@ -208,7 +208,7 @@ * * Since updating the timing info structure usually requires a full * network round trip and some applications monitor the timing very - * often Polypaudio offers a timing interpolation system. If + * often PulseAudio offers a timing interpolation system. If * PA_STREAM_INTERPOLATE_TIMING is passed when connecting the stream, * pa_stream_get_time() and pa_stream_get_latency() will try to * interpolate the current playback time/latency by estimating the @@ -228,7 +228,7 @@ * * \section sync_streams Sychronizing Multiple Playback Streams * - * Polypaudio allows applications to fully synchronize multiple + * PulseAudio allows applications to fully synchronize multiple * playback streams that are connected to the same output device. That * means the streams will always be played back sample-by-sample * synchronously. If stream operations like pa_stream_cork() are @@ -441,7 +441,7 @@ const pa_channel_map* pa_stream_get_channel_map(pa_stream *s); /** Return the buffer metrics of the stream. Only valid after the * stream has been connected successfuly and if the server is at least - * Polypaudio 0.9. \since 0.9.0 */ + * PulseAudio 0.9. \since 0.9.0 */ const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s); PA_C_DECL_END diff --git a/src/pulse/thread-mainloop.h b/src/pulse/thread-mainloop.h index fb216c5ab..44eff5a34 100644 --- a/src/pulse/thread-mainloop.h +++ b/src/pulse/thread-mainloop.h @@ -37,7 +37,7 @@ PA_C_DECL_BEGIN * * The added feature in the threaded main loop is that it spawns a new thread * that runs the real main loop. This allows a synchronous application to use - * the asynchronous API without risking to stall the Polypaudio library. + * the asynchronous API without risking to stall the PulseAudio library. * * \section creat_sec Creation * @@ -48,7 +48,7 @@ PA_C_DECL_BEGIN * * \section destr_sec Destruction * - * When the Polypaudio connection has been terminated, the thread must be + * When the PulseAudio connection has been terminated, the thread must be * stopped and the resources freed. Stopping the thread is done using * pa_threaded_mainloop_stop(), which must be called without the lock (see * below) held. When that function returns, the thread is stopped and the @@ -56,7 +56,7 @@ PA_C_DECL_BEGIN * * \section lock_sec Locking * - * Since the Polypaudio API doesn't allow concurrent accesses to objects, + * Since the PulseAudio API doesn't allow concurrent accesses to objects, * a locking scheme must be used to guarantee safe usage. The threaded main * loop API provides such a scheme through the functions * pa_threaded_mainloop_lock() and pa_threaded_mainloop_unlock(). @@ -65,7 +65,7 @@ PA_C_DECL_BEGIN * thread. Just make sure you call pa_threaded_mainloop_unlock() the same * number of times you called pa_threaded_mainloop_lock(). * - * The lock needs to be held whenever you call any Polypaudio function that + * The lock needs to be held whenever you call any PulseAudio function that * uses an object associated with this main loop. Make sure you do not hold * on to the lock more than necessary though, as the threaded main loop stops * while the lock is held. @@ -91,12 +91,12 @@ PA_C_DECL_BEGIN * * \section cb_sec Callbacks * - * Callbacks in Polypaudio are asynchronous, so they require extra care when + * Callbacks in PulseAudio are asynchronous, so they require extra care when * using them together with a threaded main loop. * * The easiest way to turn the callback based operations into synchronous * ones, is to simply wait for the callback to be called and continue from - * there. This is the approach chosen in Polypaudio's threaded API. + * there. This is the approach chosen in PulseAudio's threaded API. * * \subsection basic_subsec Basic callbacks * @@ -216,7 +216,7 @@ PA_C_DECL_BEGIN * * \subsection async_subsec Asynchronous callbacks * - * Polypaudio also has callbacks that are completely asynchronous, meaning + * PulseAudio also has callbacks that are completely asynchronous, meaning * that they can be called at any time. The threading main loop API provides * the locking mechanism to handle concurrent accesses, but nothing else. * Applications will have to handle communication from the callback to the diff --git a/src/pulse/version.h.in b/src/pulse/version.h.in index 6c5492e8d..748541a11 100644 --- a/src/pulse/version.h.in +++ b/src/pulse/version.h.in @@ -39,12 +39,12 @@ it. */ /** Return the version of the library the current application is linked to. */ const char* pa_get_library_version(void); -/** The current API version. Version 6 relates to pulseaudio +/** The current API version. Version 6 relates to Polypaudio * 0.6. Prior versions (i.e. Polypaudio 0.5.1 and older) have * PA_API_VERSION undefined. */ #define PA_API_VERSION @PA_API_VERSION@ -/** The current protocol version. Version 8 relates to pulseaudio 0.8. +/** The current protocol version. Version 8 relates to Polypaudio 0.8/PulseAudio 0.9. * \since 0.8 */ #define PA_PROTOCOL_VERSION @PA_PROTOCOL_VERSION@ diff --git a/src/pulse/volume.h b/src/pulse/volume.h index d403a09e3..6c60223ac 100644 --- a/src/pulse/volume.h +++ b/src/pulse/volume.h @@ -31,10 +31,10 @@ * \section overv_sec Overview * * Sinks, sources, sink inputs and samples can all have their own volumes. - * To deal with these, The Polypaudio libray contains a number of functions + * To deal with these, The PulseAudio libray contains a number of functions * that ease handling. * - * The basic volume type in Polypaudio is the \ref pa_volume_t type. Most of + * The basic volume type in PulseAudio is the \ref pa_volume_t type. Most of * the time, applications will use the aggregated pa_cvolume structure that * can store the volume of all channels at once. * @@ -43,7 +43,7 @@ * * \section calc_sec Calculations * - * The volumes in Polypaudio are logarithmic in nature and applications + * The volumes in PulseAudio are logarithmic in nature and applications * shouldn't perform calculations with them directly. Instead, they should * be converted to and from either dB or a linear scale: * @@ -64,7 +64,7 @@ * * \section conv_sec Convenience Functions * - * To handle the pa_cvolume structure, the Polypaudio library provides a + * To handle the pa_cvolume structure, the PulseAudio library provides a * number of convenienc functions: * * \li pa_cvolume_valid() - Tests if a pa_cvolume structure is valid. diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index f85458366..04a0b55b1 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -25,7 +25,7 @@ #include #include -/* A pa_memblock is a reference counted memory block. Polypaudio +/* A pa_memblock is a reference counted memory block. PulseAudio * passed references to pa_memblocks around instead of copying * data. See pa_memchunk for a structure that describes parts of * memory blocks. */ diff --git a/src/pulsecore/modinfo.h b/src/pulsecore/modinfo.h index f39cee3bb..90404504f 100644 --- a/src/pulsecore/modinfo.h +++ b/src/pulsecore/modinfo.h @@ -22,7 +22,7 @@ USA. ***/ -/* Some functions for reading module meta data from Polypaudio modules */ +/* Some functions for reading module meta data from PulseAudio modules */ typedef struct pa_modinfo { char *author; diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 5e4596d15..10edd71d7 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -38,7 +38,7 @@ #define TIME_EVENT_USEC 50000 #if PA_API_VERSION != 9 -#error Invalid Polypaudio API version +#error Invalid PulseAudio API version #endif static enum { RECORD, PLAYBACK } mode = PLAYBACK; diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index e4a0970d2..fe8038e00 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -49,7 +49,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { fd_set ifds, ofds; if (pa_pid_file_check_running(&pid) < 0) { - pa_log(__FILE__": no Polypaudio daemon running"); + pa_log(__FILE__": no PulseAudio daemon running"); goto fail; } @@ -74,7 +74,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { break; if (pa_pid_file_kill(SIGUSR2, NULL) < 0) { - pa_log(__FILE__": failed to kill Polypaudio daemon."); + pa_log(__FILE__": failed to kill PulseAudio daemon."); goto fail; } diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 6e40f3fec..94d22f987 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -38,7 +38,7 @@ #include #if PA_API_VERSION != 9 -#error Invalid Polypaudio API version +#error Invalid PulseAudio API version #endif #define BUFSIZE 1024 diff --git a/src/utils/padsp b/src/utils/padsp index 6e7e9f06c..d9ebcbc57 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -54,13 +54,13 @@ while getopts 'hs:n:m:MSDd' param ; do export PADSP_DEBUG ;; *) - echo "$0 - redirect OSS audio devices to Polypaudio" + echo "$0 - redirect OSS audio devices to PulseAudio" echo " " echo "$0 [options] application [arguments]" echo " " echo "options:" echo " -h show brief help" - echo " -s [:] contact a specific Polypaudio server" + echo " -s [:] contact a specific PulseAudio server" echo " -n client name to report to the server" echo " -m stream name to report to the server" echo " -M disable /dev/mixer emulation" diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 13f571e1e..d9dcc7645 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1262,18 +1262,18 @@ fail: static int sndstat_open(int flags, int *_errno) { static const char sndstat[] = - "Sound Driver:3.8.1a-980706 (Polypaudio Virtual OSS)\n" + "Sound Driver:3.8.1a-980706 (PulseAudio Virtual OSS)\n" "Kernel: POSIX\n" "Config options: 0\n" "\n" "Installed drivers:\n" - "Type 255: Polypaudio Virtual OSS\n" + "Type 255: PulseAudio Virtual OSS\n" "\n" "Card config:\n" - "Polypaudio Virtual OSS\n" + "PulseAudio Virtual OSS\n" "\n" "Audio devices:\n" - "0: Polypaudio Virtual OSS\n" + "0: PulseAudio Virtual OSS\n" "\n" "Synth devices: NOT ENABLED IN CONFIG\n" "\n" @@ -1282,7 +1282,7 @@ static int sndstat_open(int flags, int *_errno) { "Timers:\n" "\n" "Mixers:\n" - "0: Polypaudio Virtual OSS\n"; + "0: PulseAudio Virtual OSS\n"; char fn[] = "/tmp/padsp-sndstat-XXXXXX"; mode_t u; @@ -1501,7 +1501,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno memset(mi, 0, sizeof(mixer_info)); strncpy(mi->id, "POLYPAUDIO", sizeof(mi->id)); - strncpy(mi->name, "Polypaudio Virtual OSS", sizeof(mi->name)); + strncpy(mi->name, "PulseAudio Virtual OSS", sizeof(mi->name)); pa_threaded_mainloop_lock(i->mainloop); mi->modify_counter = i->volume_modify_count; pa_threaded_mainloop_unlock(i->mainloop); diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 4b4a1ea6c..7b34016c5 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -38,7 +38,7 @@ #include #if PA_API_VERSION != 9 -#error Invalid Polypaudio API version +#error Invalid PulseAudio API version #endif static pa_context *context = NULL; diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 770455b99..d2ed6c930 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -54,10 +54,10 @@ int main(int argc, char *argv[]) { break; case 'h': printf("%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n\n" - " -d Show current Polypaudio data attached to X11 display (default)\n" - " -e Export local Polypaudio data to X11 display\n" - " -i Import Polypaudio data from X11 display to local environment variables and cookie file.\n" - " -r Remove Polypaudio data from X11 display\n", + " -d Show current PulseAudio data attached to X11 display (default)\n" + " -e Export local PulseAudio data to X11 display\n" + " -i Import PulseAudio data from X11 display to local environment variables and cookie file.\n" + " -r Remove PulseAudio data from X11 display\n", pa_path_get_filename(argv[0])); ret = 0; goto finish; From 0d97ac6d2b8616073a3b047bfe22416a452950a5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 23:00:21 +0000 Subject: [PATCH 0940/1514] name the pkg-config files after the library names git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1037 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 4 ++-- configure.ac | 4 ++-- ...loop.pc.in => libpulse-mainloop-glib.pc.in | 2 +- ...op.pc.in => libpulse-mainloop-glib12.pc.in | 2 +- src/pulse/pulseaudio.h | 19 +++++++++---------- 5 files changed, 15 insertions(+), 16 deletions(-) rename libpulse-glib-mainloop.pc.in => libpulse-mainloop-glib.pc.in (90%) rename libpulse-glib12-mainloop.pc.in => libpulse-mainloop-glib12.pc.in (90%) diff --git a/Makefile.am b/Makefile.am index 4174a39b1..8a0eaf497 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,12 +33,12 @@ endif if HAVE_GLIB20 pkgconfig_DATA += \ - libpulse-glib-mainloop.pc + libpulse-mainloop-glib.pc endif if HAVE_GLIB12 pkgconfig_DATA += \ - libpulse-glib12-mainloop.pc + libpulse-mainloop-glib12.pc endif if USE_LYNX diff --git a/configure.ac b/configure.ac index 4f530347f..bb72ee373 100644 --- a/configure.ac +++ b/configure.ac @@ -698,8 +698,8 @@ src/Makefile libpulse.pc libpulse-simple.pc libpulse-browse.pc -libpulse-glib-mainloop.pc -libpulse-glib12-mainloop.pc +libpulse-mainloop-glib.pc +libpulse-mainloop-glib12.pc doc/Makefile doc/README.html doc/cli.html diff --git a/libpulse-glib-mainloop.pc.in b/libpulse-mainloop-glib.pc.in similarity index 90% rename from libpulse-glib-mainloop.pc.in rename to libpulse-mainloop-glib.pc.in index 169910ba1..a9a51cf7e 100644 --- a/libpulse-glib-mainloop.pc.in +++ b/libpulse-mainloop-glib.pc.in @@ -3,7 +3,7 @@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include -Name: libpulse-glib-mainloop +Name: libpulse-mainloop-glib Description: GLIB 2.0 Main Loop Wrapper for PulseAudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpulse-mainloop-glib diff --git a/libpulse-glib12-mainloop.pc.in b/libpulse-mainloop-glib12.pc.in similarity index 90% rename from libpulse-glib12-mainloop.pc.in rename to libpulse-mainloop-glib12.pc.in index f525c370d..7a0388260 100644 --- a/libpulse-glib12-mainloop.pc.in +++ b/libpulse-mainloop-glib12.pc.in @@ -3,7 +3,7 @@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include -Name: libpulse-glib12-mainloop +Name: libpulse-mainloop-glib12 Description: GLIB 1.2 Main Loop Wrapper for PulseAudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpulse-mainloop-glib12 diff --git a/src/pulse/pulseaudio.h b/src/pulse/pulseaudio.h index 5c526dc70..71262eaa8 100644 --- a/src/pulse/pulseaudio.h +++ b/src/pulse/pulseaudio.h @@ -44,7 +44,7 @@ #include /** \file - * Include all pulselib header files at once. The following + * Include all libpulse header files at once. The following * files are included: \ref mainloop-api.h, \ref sample.h, \ref def.h, * \ref context.h, \ref stream.h, \ref introspect.h, \ref subscribe.h, * \ref scache.h, \ref version.h, \ref error.h, \ref channelmap.h, @@ -56,7 +56,7 @@ * * \section intro_sec Introduction * - * This document describes the client API for the pulseaudio sound + * This document describes the client API for the PulseAudio sound * server. The API comes in two flavours to accomodate different styles * of applications and different needs in complexity: * @@ -78,7 +78,7 @@ * * Use this if you develop your programs in asynchronous, event loop * based style or if you want to use the advanced features of the - * pulseaudio API. A guide can be found in \subpage async. + * PulseAudio API. A guide can be found in \subpage async. * * By using the built-in threaded main loop, it is possible to acheive a * pseudo-synchronous API, which can be useful in synchronous applications @@ -87,7 +87,7 @@ * * \section thread_sec Threads * - * The pulseaudio client libraries are not designed to be used in a + * The PulseAudio client libraries are not designed to be used in a * heavily threaded environment. They are however designed to be reentrant * safe. * @@ -102,14 +102,13 @@ * * \section pkgconfig pkg-config * - * The pulseaudio libraries provide pkg-config snippets for the different + * The PulseAudio libraries provide pkg-config snippets for the different * modules: * - * \li pulselib - The asynchronous API and the internal main loop - * implementation. - * \li pulselib-glib12-mainloop - GLIB 1.2 main loop bindings. - * \li pulselib-glib-mainloop - GLIB 2.x main loop bindings. - * \li pulselib-simple - The simple pulseaudio API. + * \li pulselib - The asynchronous API and the internal main loop implementation. + * \li pulselib-mainloop-glib12 - GLIB 1.2 main loop bindings. + * \li pulselib-mainloop-glib - GLIB 2.x main loop bindings. + * \li pulselib-simple - The simple PulseAudio API. */ #endif From fe1dadbadd9f694d533dc2191451d2a020d99c2f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 23:06:50 +0000 Subject: [PATCH 0941/1514] update references to the pkg-config files in the docs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1038 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/pulseaudio.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pulse/pulseaudio.h b/src/pulse/pulseaudio.h index 71262eaa8..88cc326b8 100644 --- a/src/pulse/pulseaudio.h +++ b/src/pulse/pulseaudio.h @@ -105,10 +105,10 @@ * The PulseAudio libraries provide pkg-config snippets for the different * modules: * - * \li pulselib - The asynchronous API and the internal main loop implementation. - * \li pulselib-mainloop-glib12 - GLIB 1.2 main loop bindings. - * \li pulselib-mainloop-glib - GLIB 2.x main loop bindings. - * \li pulselib-simple - The simple PulseAudio API. + * \li libpulse - The asynchronous API and the internal main loop implementation. + * \li libpulse-mainloop-glib12 - GLIB 1.2 main loop bindings. + * \li libpulse-mainloop-glib - GLIB 2.x main loop bindings. + * \li libpulse-simple - The simple PulseAudio API. */ #endif From 3cf16214334b4a1c51e56b0536abd8223d6813dd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 23:51:58 +0000 Subject: [PATCH 0942/1514] * more s/pulseaudio/PulseAudio/ replacements * name the per-user dir ~/.pulse (instead of .pulseaudio), just like /etc/pulse/ git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1039 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 6 +++--- src/modules/module-jack-sink.c | 2 +- src/modules/module-jack-source.c | 2 +- src/modules/module-match.c | 4 ++-- src/modules/module-volume-restore.c | 2 +- src/modules/module-zeroconf-publish.c | 6 +++--- src/pulse/browser.c | 6 +++--- src/pulse/client-conf.c | 4 ++-- src/pulse/client-conf.h | 2 +- src/pulse/context.h | 12 ++++++------ src/pulse/def.h | 2 +- src/pulse/introspect.h | 2 +- src/pulse/mainloop-api.h | 8 ++++---- src/pulsecore/cli.c | 2 +- src/pulsecore/core-error.c | 2 +- src/pulsecore/core-util.c | 6 +++--- src/pulsecore/core.h | 4 ++-- src/pulsecore/native-common.h | 2 +- 18 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index fd83f28f2..4d458a5c0 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -41,7 +41,7 @@ #ifndef DEFAULT_CONFIG_DIR # ifndef OS_IS_WIN32 -# define DEFAULT_CONFIG_DIR "/etc/pulseaudio" +# define DEFAULT_CONFIG_DIR "/etc/pulse" # else # define DEFAULT_CONFIG_DIR "%POLYP_ROOT%" # endif @@ -54,9 +54,9 @@ #endif #define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR PATH_SEP "default.pa" -#define DEFAULT_SCRIPT_FILE_USER ".pulseaudio" PATH_SEP "default.pa" +#define DEFAULT_SCRIPT_FILE_USER ".pulse" PATH_SEP "default.pa" #define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" -#define DEFAULT_CONFIG_FILE_USER ".pulseaudio" PATH_SEP "daemon.conf" +#define DEFAULT_CONFIG_FILE_USER ".pulse" PATH_SEP "daemon.conf" #define ENV_SCRIPT_FILE "POLYP_SCRIPT" #define ENV_CONFIG_FILE "POLYP_CONFIG" diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index c6a161ff6..74f25d536 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -261,7 +261,7 @@ int pa__init(pa_core *c, pa_module*m) { } server_name = pa_modargs_get_value(ma, "server_name", NULL); - client_name = pa_modargs_get_value(ma, "client_name", "pulseaudio"); + client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio"); u = pa_xnew0(struct userdata, 1); m->userdata = u; diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 6f31f6c3a..9c7f449f3 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -259,7 +259,7 @@ int pa__init(pa_core *c, pa_module*m) { } server_name = pa_modargs_get_value(ma, "server_name", NULL); - client_name = pa_modargs_get_value(ma, "client_name", "pulseaudio"); + client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio"); u = pa_xnew0(struct userdata, 1); m->userdata = u; diff --git a/src/modules/module-match.c b/src/modules/module-match.c index ddeda7347..28d6a08be 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -53,11 +53,11 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" #ifndef DEFAULT_CONFIG_DIR -#define DEFAULT_CONFIG_DIR "/etc/pulseaudio" +#define DEFAULT_CONFIG_DIR "/etc/pulse" #endif #define DEFAULT_MATCH_TABLE_FILE DEFAULT_CONFIG_DIR"/match.table" -#define DEFAULT_MATCH_TABLE_FILE_USER ".pulseaudio/match.table" +#define DEFAULT_MATCH_TABLE_FILE_USER ".pulse/match.table" static const char* const valid_modargs[] = { "table", diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index ede2fcf28..2f45082b3 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -53,7 +53,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#define DEFAULT_VOLUME_TABLE_FILE ".pulseaudio/volume.table" +#define DEFAULT_VOLUME_TABLE_FILE ".pulse/volume.table" static const char* const valid_modargs[] = { "table", diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 14cbef46a..32fb1f41b 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -53,9 +53,9 @@ PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("port=") -#define SERVICE_NAME_SINK "_pulseaudio-sink._tcp" -#define SERVICE_NAME_SOURCE "_pulseaudio-source._tcp" -#define SERVICE_NAME_SERVER "_pulseaudio-server._tcp" +#define SERVICE_NAME_SINK "_pulse-sink._tcp" +#define SERVICE_NAME_SOURCE "_pulse-source._tcp" +#define SERVICE_NAME_SERVER "_pulse-server._tcp" static const char* const valid_modargs[] = { "port", diff --git a/src/pulse/browser.c b/src/pulse/browser.c index d063465dc..966258692 100644 --- a/src/pulse/browser.c +++ b/src/pulse/browser.c @@ -29,9 +29,9 @@ #include "browser.h" -#define SERVICE_NAME_SINK "_pulseaudio-sink._tcp." -#define SERVICE_NAME_SOURCE "_pulseaudio-source._tcp." -#define SERVICE_NAME_SERVER "_pulseaudio-server._tcp." +#define SERVICE_NAME_SINK "_pulse-sink._tcp." +#define SERVICE_NAME_SOURCE "_pulse-source._tcp." +#define SERVICE_NAME_SERVER "_pulse-server._tcp." struct pa_browser { int ref; diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 752d0134a..9f5cf53da 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -41,7 +41,7 @@ #ifndef DEFAULT_CONFIG_DIR # ifndef OS_IS_WIN32 -# define DEFAULT_CONFIG_DIR "/etc/pulseaudio" +# define DEFAULT_CONFIG_DIR "/etc/pulse" # else # define DEFAULT_CONFIG_DIR "%POLYP_ROOT%" # endif @@ -54,7 +54,7 @@ #endif #define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "client.conf" -#define DEFAULT_CLIENT_CONFIG_FILE_USER ".pulseaudio" PATH_SEP "client.conf" +#define DEFAULT_CLIENT_CONFIG_FILE_USER ".pulse" PATH_SEP "client.conf" #define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG" #define ENV_DEFAULT_SINK "POLYP_SINK" diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index 9d45af478..a532f0dfe 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -24,7 +24,7 @@ #include -/* A structure containing configuration data for pulseaudio clients. */ +/* A structure containing configuration data for PulseAudio clients. */ typedef struct pa_client_conf { char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; diff --git a/src/pulse/context.h b/src/pulse/context.h index ad8c9f3fa..661ff6170 100644 --- a/src/pulse/context.h +++ b/src/pulse/context.h @@ -32,7 +32,7 @@ * * \section overv_sec Overview * - * The asynchronous API is the native interface to the pulseaudio library. + * The asynchronous API is the native interface to the PulseAudio library. * It allows full access to all available functions. This also means that * it is rather complex and can take some time to fully master. * @@ -52,10 +52,10 @@ * * To actually be able to use these functions, an implementation needs to * be coupled to the abstraction. There are three of these shipped with - * pulseaudio, but any other can be used with a minimal ammount of work, + * PulseAudio, but any other can be used with a minimal ammount of work, * provided it supports the three basic events listed above. * - * The implementations shipped with pulseaudio are: + * The implementations shipped with PulseAudio are: * * \li \subpage mainloop - A minimal but fast implementation based on poll(). * \li \subpage threaded_mainloop - A special version of the previous @@ -71,7 +71,7 @@ * * \section refcnt_sec Reference Counting * - * Almost all objects in pulseaudio are reference counted. What that means + * Almost all objects in PulseAudio are reference counted. What that means * is that you rarely malloc() or free() any objects. Instead you increase * and decrease their reference counts. Whenever an object's reference * count reaches zero, that object gets destroy and any resources it uses @@ -89,7 +89,7 @@ * * \section context_sec Context * - * A context is the basic object for a connection to a pulseaudio server. + * A context is the basic object for a connection to a PulseAudio server. * It multiplexes commands, data streams and events through a single * channel. * @@ -142,7 +142,7 @@ /** \file * Connection contexts for asynchrononous communication with a - * server. A pa_context object wraps a connection to a pulseaudio + * server. A pa_context object wraps a connection to a PulseAudio * server using its native protocol. */ /** \example pacat.c diff --git a/src/pulse/def.h b/src/pulse/def.h index 3a17f43bf..b98337d29 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -66,7 +66,7 @@ typedef enum pa_operation_state { /** Some special flags for contexts. \since 0.8 */ typedef enum pa_context_flags { - PA_CONTEXT_NOAUTOSPAWN = 1 /**< Disabled autospawning of the pulseaudio daemon if required */ + PA_CONTEXT_NOAUTOSPAWN = 1 /**< Disabled autospawning of the PulseAudio daemon if required */ } pa_context_flags_t; /** The direction of a pa_stream object */ diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h index 23d736c65..e9a144908 100644 --- a/src/pulse/introspect.h +++ b/src/pulse/introspect.h @@ -270,7 +270,7 @@ typedef struct pa_server_info { pa_sample_spec sample_spec; /**< Default sample specification */ const char *default_sink_name; /**< Name of default sink. \since 0.4 */ const char *default_source_name; /**< Name of default sink. \since 0.4*/ - uint32_t cookie; /**< A random cookie for identifying this instance of pulseaudio. \since 0.8 */ + uint32_t cookie; /**< A random cookie for identifying this instance of PulseAudio. \since 0.8 */ } pa_server_info; /** Callback prototype for pa_context_get_server_info() */ diff --git a/src/pulse/mainloop-api.h b/src/pulse/mainloop-api.h index a732b215e..4aaeccf58 100644 --- a/src/pulse/mainloop-api.h +++ b/src/pulse/mainloop-api.h @@ -29,13 +29,13 @@ /** \file * - * Main loop abstraction layer. Both the pulseaudio core and the - * pulseaudio client library use a main loop abstraction layer. Due to - * this it is possible to embed pulseaudio into other + * Main loop abstraction layer. Both the PulseAudio core and the + * PulseAudio client library use a main loop abstraction layer. Due to + * this it is possible to embed PulseAudio into other * applications easily. Two main loop implemenations are * currently available: * \li A minimal implementation based on the C library's poll() function (See \ref mainloop.h) - * \li A wrapper around the GLIB main loop. Use this to embed pulseaudio into your GLIB/GTK+/GNOME programs (See \ref glib-mainloop.h) + * \li A wrapper around the GLIB main loop. Use this to embed PulseAudio into your GLIB/GTK+/GNOME programs (See \ref glib-mainloop.h) * * The structure pa_mainloop_api is used as vtable for the main loop abstraction. * diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c index fbfa5009b..7c2840668 100644 --- a/src/pulsecore/cli.c +++ b/src/pulsecore/cli.c @@ -84,7 +84,7 @@ pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) { c->client->owner = m; pa_ioline_set_callback(c->line, line_callback, c); - pa_ioline_puts(c->line, "Welcome to pulseaudio! Use \"help\" for usage information.\n"PROMPT); + pa_ioline_puts(c->line, "Welcome to PulseAudio! Use \"help\" for usage information.\n"PROMPT); c->fail = c->kill_requested = c->defer_kill = 0; diff --git a/src/pulsecore/core-error.c b/src/pulsecore/core-error.c index e42070d17..61878c9ed 100644 --- a/src/pulsecore/core-error.c +++ b/src/pulsecore/core-error.c @@ -68,7 +68,7 @@ static void inittls(void) { HANDLE mutex; char name[64]; - sprintf(name, "pulseaudio%d", (int)GetCurrentProcessId()); + sprintf(name, "pulse%d", (int)GetCurrentProcessId()); mutex = CreateMutex(NULL, FALSE, name); if (!mutex) { diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 8e3587ebe..d4b140ded 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -79,10 +79,10 @@ #include "core-util.h" #ifndef OS_IS_WIN32 -#define PA_RUNTIME_PATH_PREFIX "/tmp/pulseaudio-" +#define PA_RUNTIME_PATH_PREFIX "/tmp/pulse-" #define PATH_SEP '/' #else -#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\pulseaudio-" +#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-" #define PATH_SEP '\\' #endif @@ -961,7 +961,7 @@ int pa_endswith(const char *s, const char *sfx) { return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0; } -/* if fn is null return the pulseaudio run time path in s (/tmp/pulseaudio) +/* if fn is null return the PulseAudio run time path in s (/tmp/pulse) * if fn is non-null and starts with / return fn in s * otherwise append fn to the run time path and return it in s */ char *pa_runtime_path(const char *fn, char *s, size_t l) { diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 627d42396..261c5f752 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -33,13 +33,13 @@ typedef struct pa_core pa_core; #include #include -/* The core structure of pulseaudio. Every pulseaudio daemon contains +/* The core structure of PulseAudio. Every PulseAudio daemon contains * exactly one of these. It is used for storing kind of global * variables for the daemon. */ struct pa_core { /* A random value which may be used to identify this instance of - * pulseaudio. Not cryptographically secure in any way. */ + * PulseAudio. Not cryptographically secure in any way. */ uint32_t cookie; pa_mainloop_api *mainloop; diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h index b35931d00..5fdb6f427 100644 --- a/src/pulsecore/native-common.h +++ b/src/pulsecore/native-common.h @@ -112,7 +112,7 @@ enum { }; #define PA_NATIVE_COOKIE_LENGTH 256 -#define PA_NATIVE_COOKIE_FILE ".pulseaudio-cookie" +#define PA_NATIVE_COOKIE_FILE ".pulse-cookie" #define PA_NATIVE_DEFAULT_PORT 4713 From 6654e987c17bc1026944248cfb01876311807bd7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 23:52:16 +0000 Subject: [PATCH 0943/1514] update docs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1040 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/FAQ.html.in | 110 +++++++++++++++++++++++--------------------- doc/README.html.in | 108 ++++++++++++++++++++++--------------------- doc/cli.html.in | 8 ++-- doc/daemon.html.in | 8 ++-- doc/modules.html.in | 26 +++++------ 5 files changed, 133 insertions(+), 127 deletions(-) diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in index d9550e95c..6b83cf77c 100644 --- a/doc/FAQ.html.in +++ b/doc/FAQ.html.in @@ -2,7 +2,7 @@ -pulseaudio: FAQ +PulseAudio: FAQ @@ -12,39 +12,39 @@

      Frequently Asked Questions

        -
      1. How does Polypaudio compare with ESOUND/aRts/NAS?

        +
      2. How does PulseAudio compare with ESOUND/aRts/NAS?

        -

        Polypaudio is sound daemon similar to ESOUND and NAS, but much more +

        PulseAudio is sound daemon similar to ESOUND and NAS, but much more powerful. aRts is a realtime-synthesizer-cum-sound-server, i.e. it - does much more than Polypaudio. However, I believe that Polypaudio + does much more than PulseAudio. However, I believe that PulseAudio does what it does much better than any other free sound server.

      3. What about ESOUND compatibility?

        -

        Polypaudio is a drop in replacement for ESOUND. That means: you can +

        PulseAudio is a drop in replacement for ESOUND. That means: you can load a esound compatibility module which implements an ESOUND compatible protocol which allows you to use most of the classic ESOUND compatible programs (including the command line programs like esdcat).

      4. -
      5. Is Polypaudio a GNOME program?

        -

        No, Polypaudio has no dependency on GNOME/GTK/GLIB. All it requires +

      6. Is PulseAudio a GNOME program?

        +

        No, PulseAudio has no dependency on GNOME/GTK/GLIB. All it requires is a UNIX-like operating system and very few dependency - libraries. However, the accompanying GUI tools are writen with + libraries. However, the accompanying GUI tools are written with gtkmm, i.e. require both GLIB and GTK.

      7. -
      8. Can I integrate Polypaudio in my GLIB/GTK/GNOME application?

        -

        Yes! Polypaudio comes with a GLIB main loop adapter. You can embed +

      9. Can I integrate PulseAudio in my GLIB/GTK/GNOME application?

        +

        Yes! PulseAudio comes with a GLIB main loop adapter. You can embed both the client library and the daemon (!) into your GLIB based application.

      10. -
      11. Can I integrate Polypaudio in my Qt/KDE application?

        -

        Yes! Polypaudio uses a main loop abstraction layer that allows you - to integrate Polypaudio in any program that supports main +

      12. Can I integrate PulseAudio in my Qt/KDE application?

        +

        Yes! PulseAudio uses a main loop abstraction layer that allows you + to integrate PulseAudio in any program that supports main loops. Unfortunately there is no adapter for Qt publicly available yet.

      13. -
      14. I want to write a new driver for Polypaudio, are there any docs?

        +
      15. I want to write a new driver for PulseAudio, are there any docs?

        Currently, only the client API is documented with doxygen. Read the source and base your work on a simple module like module-pipe-sink.

      16. @@ -54,67 +54,67 @@
      17. What about compatibility with aRts?

        Is not available. Since aRts is as synthesizer application you'd have to - reimplement very much code for Polypaudio. It should be easy to + reimplement very much code for PulseAudio. It should be easy to implement limited support for libartsc based applications. Noone has done this yet. It is probably a better idea to - run arts on top of Polypaudio (through a pulseaudio driver + run arts on top of PulseAudio (through a PulseAudio driver for aRts, which nobody has written yet). Another solution would be to - embed Polypaudio in the aRts process.

      18. + embed PulseAudio in the aRts process.

        -
      19. I often hear noises when playing back with Polypaudio, what can I do?

        -

        There are to possible solutions: run pulseaudio with argument +

      20. I often hear noises when playing back with PulseAudio, what can I do?

        +

        There are to possible solutions: run PulseAudio with argument --high-priority=1 and make yourself member of the group realtime, or increase the fragment sizes of the audio - drivers. The former will allow Polypaudio to activate + drivers. The former will allow PulseAudio to activate SCHED_FIFO high priority scheduling (root rights are dropped immediately after this). Keep in mind that this is a potential security hole!

      21. The pulseaudio executable is installed SUID root by default. Why this? Isn't this a potential security hole?

        -

        Polypaudio activates SCHED_FIFO scheduling if the user +

        PulseAudio activates SCHED_FIFO scheduling if the user passes --high-priority=1. This will only succeed when executed as root, therefore the binary is marked SUID root by -default. Yes, this is a potential security hole. However, pulseaudio +default. Yes, this is a potential security hole. However, PulseAudio tries its best to minimize the security threat: immediately after -startup pulseaudio drops all capabilities except +startup PulseAudio drops all capabilities except CAP_SYS_NICE (At least on systems that support it, like Linux; see man 7 capabilities for more information). If the calling user is not a member of the group realtime (which is required to have a GID < 1000), root rights are dropped immediately. This means, you can -install pulseaudio SUID root, but only a subset of your users (the +install pulseaudio SUID root, but only a subset of your users (the members of the group realtime) may make use of realtime scheduling. Keep in mind that these users might load their own binary -modules into the pulseaudio daemon which may freeze the machine. The +modules into the PulseAudio daemon which may freeze the machine. The daemon has a minimal protection against CPU hogging (the daemon is killed after hogging more than 70% CPU for 5 seconds), but this may be circumvented easily by evildoers.

      22. -
      23. I want to run pulseaudio only when it is needed, how do I do this?

        +
      24. I want to run PulseAudio only when it is needed, how do I do this?

        Set autospawn = yes in client.conf. That -configuration file may be found either in /etc/pulseaudio/ or -in ~/.pulseaudio/.

      25. +configuration file may be found either in /etc/pulse/ or +in ~/.pulse/.

        -
      26. How do I list all pulseaudio modules installed?

        +
      27. How do I list all PulseAudio modules installed?

        pulseaudio --dump-modules

        Add -v for terse usage instructions.

        -
      28. How do I use pulseaudio over the network?

        +
      29. How do I use PulseAudio over the network?

        -

        Just set $POLYP_SERVER to the host name of the pulseaudio +

        Just set $POLYP_SERVER to the host name of the PulseAudio server. For authentication you need the same auth cookies on all sides. For -that copy ~./pulseaudio-cookie to all clients that shall +that copy ~./pulse-cookie to all clients that shall be allowed to connect.

        Alternatively the authorization cookies can be stored in the X11 server.

      30. -
      31. Is pulseaudio capable of providing synchronized audio playback over the network for movie players like mplayer?

        +
      32. Is PulseAudio capable of providing synchronized audio playback over the network for movie players like mplayer?

        Yes! Unless your network is congested in some way (i.e. transfer latencies vary strongly) it works perfectly. Drop me an email for experimental patches for MPlayer.

        -
      33. What environment variables does pulseaudio care about?

        +
      34. What environment variables does PulseAudio care about?

        The client honors: POLYP_SINK (default sink to connect to), POLYP_SOURCE (default source to connect to), POLYP_SERVER (default server to connect to, like ESPEAKER), POLYP_BINARY (the binary to start when autospawning a daemon), POLYP_CLIENTCONFIG (path to the client configuration file).

        @@ -126,36 +126,36 @@ be allowed to connect.

        A brilliant guy named Lennart Poettering once wrote a nifty tool for that purpose: bidilink. To -connect to a running pulseaudio daemon try using the following commands:

        +connect to a running PulseAudio daemon try using the following commands:

        killall -USR2 pulseaudio
        -bidilink unix-client:/tmp/pulseaudio/cli
        +bidilink unix-client:/tmp/pulse-$USER/cli

      BTW: Someone should package this great tool for Debian!

      New: There's now a tool pacmd that automates sending SIGUSR2 to the daemon and running a bidilink like tool for you.

      -
    • How do the pulseaudio libraries decide where to connect to?

      +
    • How do the PulseAudio libraries decide where to connect to?

      The following rule applies:

      1. If the the application using the library specifies a server to connect to it is used. If the connection fails, the library fails too.
      2. If the environment variable POLYP_SERVER is defined the library connects to that server. If the connection fails, the library fails too.
      3. If $DISPLAY is set, the library tries to connect to that server and looks for the root window property POYLP_SERVER for the host to connect to. If POLYP_COOKIE is set it is used as authentication cookie.
      4. -
      5. If the client configuration file (~/.pulseaudio/client.conf or /etc/pulseaudio/client.conf) sets the server address, the library connects to that server. If the connection fails, the library fails too.
      6. -
      7. The library tries to connect to the default local UNIX socket for pulseaudio servers. If the connection fails, it proceeds with the next item.
      8. -
      9. The library tries to connect to the default local TCP socket for pulseaudio servers. If the connection fails, it proceeds with the next item.
      10. +
      11. If the client configuration file (~/.pulse/client.conf or /etc/pulse/client.conf) sets the server address, the library connects to that server. If the connection fails, the library fails too.
      12. +
      13. The library tries to connect to the default local UNIX socket for PulseAudio servers. If the connection fails, it proceeds with the next item.
      14. +
      15. The library tries to connect to the default local TCP socket for PulseAudio servers. If the connection fails, it proceeds with the next item.
      16. If $DISPLAY is set, the library tries to connect to the default TCP port of that host. If the connection fails, it proceeds with the next item.
      17. The connection fails.
    • Why the heck does libpulse link against libX11?

      -

      The Polypaudio client libraries look for some X11 root window -properties for the credentials of the Polypaudio server to access. You -may compile Polypaudio without X11 for disabling this feature.

    • +

      The PulseAudio client libraries look for some X11 root window +properties for the credentials of the PulseAudio server to access. You +may compile PulseAudio without X11 for disabling this feature.

      -
    • How can I use Polypaudio as an RTP based N:N multicast +

    • How can I use PulseAudio as an RTP based N:N multicast conferencing solution for the LAN?

      After loading all the necessary audio drivers for recording and playback, just load the RTP reciever and sender modules with default parameters:

      @@ -165,7 +165,7 @@ load-module module-rtp-send load-module module-rtp-recv
    • -

      As long as the Polypaudio daemon runs, the microphone data will be +

      As long as the PulseAudio daemon runs, the microphone data will be streamed to the network and the data from other hosts is played back locally. Please note that this may cause quite a lot of traffic. Hence consider passing rate=8000 format=ulaw channels=1 to the @@ -182,11 +182,11 @@ announce RTP sessions that are described with SDP. (Modern SIP based VoIP phones

      All three protocols are defined in IETF RFCs (RFC3550, RFC3551, RFC2327, RFC2327). They can be used in both multicast and unicast -fashions. Polypaudio exclusively uses multicast RTP/SDP/SAP containing audio data.

      +fashions. PulseAudio exclusively uses multicast RTP/SDP/SAP containing audio data.

      -

      For more information about using these technologies with Polypaudio have a look on the respective module's documentation. +

      For more information about using these technologies with PulseAudio have a look on the respective module's documentation. -

    • How can I use Polypaudio to stream music from my main PC to my LAN with multiple PCs with speakers?

      +
    • How can I use PulseAudio to stream music from my main PC to my LAN with multiple PCs with speakers?

      On the sender side create an RTP sink:

      @@ -208,7 +208,7 @@ load-module module-rtp-recv

      BTW: You can have more than one sender machine set up like this. The audio data will be mixed on the client side.

    • -
    • How can I use Polypaudio to share a single LINE-IN/MIC jack on the entire LAN?

      +
    • How can I use PulseAudio to share a single LINE-IN/MIC jack on the entire LAN?

      On the sender side simply load the RTP sender module:

      @@ -238,7 +238,7 @@ modules to select them. Choose your group addresses from the range 225.0.0.x to make sure the audio data never leaves the LAN.

    • -
    • Can I use Polypaudio to playback music on two sound cards simultaneously?

      +
    • Can I use PulseAudio to playback music on two sound cards simultaneously?

      Yes! Use module-combine for that.

      @@ -251,13 +251,13 @@ set-sink-default combined

      This will combine the two sinks output0 and output1 into a new sink combined. Every sample -written to the latter will be forwarded to the former two. Polypaudio +written to the latter will be forwarded to the former two. PulseAudio will make sure to adjust the sample rate of the slave device in case it deviates from the master device. You can have more than one slave sink attached to the combined sink, and hence combine even three and more sound cards.

    • -
    • Can I use Polypaudio to combine two stereo soundcards into a virtual surround sound card?

      +
    • Can I use PulseAudio to combine two stereo soundcards into a virtual surround sound card?

      Yes! You can use use module-combine for that.

      @@ -271,7 +271,7 @@ load-module module-combine sink_name=combined master=output0 slaves=output1 chan time we manually specify the channel mappings for the sinks to make sure everything is routed correctly.

      -

      Please keep in mind that Polypaudio will constantly adjust the +

      Please keep in mind that PulseAudio will constantly adjust the sample rate to compensate for the deviating quartzes of the sound devices. This is not perfect, however. Deviations in a range of 1/44100s (or 1/48000s depending on the sampling frequency) can not be @@ -281,7 +281,11 @@ you hear.

    • +
    • Why did you rename Polypaudio to PulseAudio?

      +

      Please read this blog story for an explanation.

      + +
    • diff --git a/doc/README.html.in b/doc/README.html.in index 2f6ad4489..e4eea7866 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -3,12 +3,12 @@ -pulseaudio @PACKAGE_VERSION@ +PulseAudio @PACKAGE_VERSION@ -

      pulseaudio @PACKAGE_VERSION@

      +

      PulseAudio @PACKAGE_VERSION@

      Copyright 2004-2006 Lennart Poettering <@PACKAGE_BUGREPORT@> and Pierre Ossman

      @@ -44,7 +44,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

      News

      Fri Jun 2 2006:

      Version 0.9.1 +href="@PACKAGE_URL@polypaudio-0.9.1.tar.gz">Version 0.9.1 released; changes include: load modules even when libtool .la files are missing; generate better ALSA device names from module-detect; if an ALSA device doesn't support the @@ -53,7 +53,7 @@ suggests instead; amd64 portability; drop .sh suffix of esdcompat.sh; build system fixes; No API or ABI changes were made

      Fri May 26 2006:

      Version 0.9.0 +href="@PACKAGE_URL@polypaudio-0.9.0.tar.gz">Version 0.9.0 released; changes include: new module module-volume-restore; new OSS API emulation tool padsp; require valid UTF8 strings everywhere; properly support ALSA channel maps for surround sound; @@ -62,7 +62,7 @@ main loop API for synchronous programs; introduce real shared object versioning; a few API additions; many, many bugfixes

      Fri Apr 28 2006:

      Version 0.8.1 +href="@PACKAGE_URL@polypaudio-0.8.1.tar.gz">Version 0.8.1 released; changes include: support for specifying the channel map on the command lines of paplay and pacat and as arguments to the driver modules; ALSA hardware mixer compatibility; @@ -70,16 +70,16 @@ fix linking; properly remove PF_UNIX sockets when unloading protocol modules; fix sample cache; many other fixes

      Thu Apr 13 2006:

      Version 0.8 released; -changes include: too many to count - consider reading this blog entry for more information; many, many minor fixes.

      +href="@PACKAGE_URL@polypaudio-0.8.tar.gz">Version 0.8 released; +changes include: too many to count - consider reading this blog entry for more information; many, many minor fixes.

      Sun Nov 21 2004:

      Version 0.7 released; +href="@PACKAGE_URL@polypaudio-0.7.tar.gz">Version 0.7 released; changes include: IPv6 support; PID file support; publish credentials in X11 root window (module-x11-publish; new tool pacmd; ESOUND backend; new command load-sample-dir-lazy; many, many minor fixes.

      Thu Oct 28 2004:

      Version 0.6 released; +href="@PACKAGE_URL@polypaudio-0.6.tar.gz">Version 0.6 released; changes include: TCP wrappers support; don't load the complete sound file into memory when playing back using pa_play_file(); autoload API change; don't load all sound files as FLOAT32; shorten @@ -91,14 +91,14 @@ generation; correctly lock daemon autospawning; print daemon layout to STDERR on SIGHUP; new options for pacat: allow sample type specification.

      Mon Sep 24 2004:

      Version 0.5.1 released; +href="@PACKAGE_URL@polypaudio-0.5.1.tar.gz">Version 0.5.1 released; changes include: improve esound protocol compatibility; fix autospawning via libesd; make use of POSIX capabilities; allow SCHED_FIFO scheduling only for users in group realtime; minor build system fix.

      Mon Sep 20 2004:

      Version 0.5 released; +href="@PACKAGE_URL@polypaudio-0.5.tar.gz">Version 0.5 released; changes include: extensive API improvements, new module module-combine for combining multiple sound cards into one, gcc 2.95 compatibility, configuration files, add "lazy" samples, @@ -106,29 +106,29 @@ support for source and network latency measurements, add module-pipe-source, many other fixes and improvements.

      Wed Sep 8 2004:

      Version 0.4 released; +href="@PACKAGE_URL@polypaudio-0.4.tar.gz">Version 0.4 released; changes include: daemon auto spawning, support for SCHED_FIFO scheduling, three new modules, proper logging, CPU load watchdog, many fixes.

      Fri Aug 27 2004:

      Version 0.3 released; +href="@PACKAGE_URL@polypaudio-0.3.tar.gz">Version 0.3 released; changes include: support for both glib 2.0 and glib 1.2, future cancellation, API updates, many fixes, relicense client library to LGPL.

      Fri Aug 20 2004:

      Version 0.2 released; +href="@PACKAGE_URL@polypaudio-0.2.tar.gz">Version 0.2 released; changes include: added sample cache, introspection API, client API documentation, module autoloading, glib support, a module for intercepting X11 bell events, and much more.

      Sat Jul 17 2004:

      Version 0.1 released

      +href="@PACKAGE_URL@polypaudio-0.1.tar.gz">Version 0.1 released

      Overview

      -

      pulseaudio is a networked sound server for Linux and other +

      PulseAudio is a networked sound server for Linux and other Unix like operating systems and Microsoft Windows. It is intended to be an improved drop-in replacement for the Enlightened Sound Daemon (ESOUND). In addition to the features ESOUND provides -pulseaudio has:

      +PulseAudio has:

      • Extensible plugin architecture (by loading dynamic loadable modules with dlopen())
      • @@ -150,8 +150,8 @@ Daemon (ESOUND). In addition to the features ESOUND provides use of a simple main loop abstraction layer. This allows easy integration with asynchronous applications using the glib/gtk mainloop. Since the asynchronous API -available through pulselib is quite difficult to use there is -a simplified synchronous API wrapper pulselib-simple +available through libpulse is quite difficult to use there is +a simplified synchronous API wrapper libpulse-simple available. A simple main loop implementation is available as well.

        The following modules are currently available:

        @@ -167,12 +167,12 @@ Sound Architecture (ALSA) sinks and sources
      • module-combine: combine multiple sinks into one, adjusting the sample rate if the their clocks deviate.
      • module-sine: a sine generate sink input.
      • module-x11-bell: play a sample from the sample cache on every X11 bell event.
      • -
      • module-x11-publish: store Polypaudio credentials in the X11 root window.
      • +
      • module-x11-publish: store PulseAudio credentials in the X11 root window.
      • module-esound-protocol-tcp, module-esound-protocol-unix: ESOUND compatibility modules (for TCP/IP resp. UNIX domain sockets)
      • -
      • module-native-protocol-tcp, module-native-protocol-unix: Native pulseaudio protocol (for TCP/IP resp. UNIX domain sockets)
      • +
      • module-native-protocol-tcp, module-native-protocol-unix: Native PulseAudio protocol (for TCP/IP resp. UNIX domain sockets)
      • module-simple-protocol-tcp, module-simple-protocol-unix: Simplistic protocol for playback/capture for usage with tools like netcat (for TCP/IP resp. UNIX domain sockets)
      • -
      • module-cli-protocol-tcp, module-cli-protocol-unix, module-cli: Expose pulseaudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
      • -
      • module-http-protocol-tcp: Spawns a small HTTP server which can be used to introspect the Polypaudio server with a web browser.
      • +
      • module-cli-protocol-tcp, module-cli-protocol-unix, module-cli: Expose PulseAudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
      • +
      • module-http-protocol-tcp: Spawns a small HTTP server which can be used to introspect the PulseAudio server with a web browser.
      • module-tunnel-sink, module-tunnel-source: make sinks/sources from other hosts available locally.
      • module-match: adjust volume automatically for newly created playback streams based on a regular expression matching table.
      • module-volume-restore: much like module-match, but create rules fully automatically based on the client name.
      • @@ -186,12 +186,12 @@ Sound Architecture (ALSA) sinks and sources
      • module-jack-sink, module-jack-source: connect to a JACK Audio Connection Kit server. (A sound server for professional audio production)
      -

      A GTK GUI manager application for pulseaudio is the Polypaudio -Manager. Other GTK GUI tool for Polypaudio are the Polypaudio Volume +

      A GTK GUI manager application for PulseAudio is the PulseAudio +Manager. Other GTK GUI tool for PulseAudio are the PulseAudio Volume Meter and the Polypaudio Volume +href="http://0pointer.de/lennart/projects/pavucontrol">PulseAudio Volume Control .

      There are output plugins for Xine (merged in Xine CVS). Drivers for PortAudio will be released shortly.

      +

      PulseAudio was formerly known as Polypaudio.

      +

      Current Status

      Version @PACKAGE_VERSION@ is quite usable. It matches and supersedes ESOUND's feature set in nearly all areas.

      @@ -216,68 +218,68 @@ href="modules.html">modules.html, cli.html, daemon.html and FAQ.html.

      -

      There is a Trac based Wiki for Polypaudio available.

      +

      There is a Trac based Wiki for PulseAudio available.

      First Steps

      -

      Simply start the pulseaudio daemon with the argument -nC

      +

      Simply start the PulseAudio daemon with the argument -nC

      pulseaudio -nC

      This will present you a screen like this:

      -
      Welcome to pulseaudio! Use "help" for usage information.
      +
      Welcome to PulseAudio! Use "help" for usage information.
       >>> 

      Now you can issue CLI commands as described in cli.html. Another way to start -pulseaudio is by specifying a configuration script like that one included in the distribution on the +PulseAudio is by specifying a configuration script like that one included in the distribution on the command line :

      pulseaudio -nF pulseaudio.pa

      This will load some drivers and protocols automatically.

      -

      The best idea is to configure your daemon in /etc/pulseaudio/daemon.conf and /etc/pulseaudio/default.pa and to run pulseaudio without any arguments.

      +

      The best idea is to configure your daemon in /etc/pulse/daemon.conf and /etc/pulse/default.pa and to run PulseAudio without any arguments.

      Beware! Unless you pass the option --sysconfdir=/etc to -configure, the directory /etc/pulseaudio/ is really -/usr/local/etc/pulseaudio/.

      +configure, the directory /etc/pulse/ is really +/usr/local/etc/pulse/.

      -

      Developing pulseaudio Clients

      +

      Developing PulseAudio Clients

      You may browse the Doxygen generated programing documentation for the client API. (Run make doxygen to generate this documentation from the source tree)

      -

      Developing pulseaudio Modules

      +

      Developing PulseAudio Modules

      -

      There are several reasons for writing loadable modules for pulseaudio:

      +

      There are several reasons for writing loadable modules for PulseAudio:

      • Extended device driver support
      • Protocol support beyond ESOUND's protocol and the native protocol. (such as NAS or a subset of aRts)
      • New programming interfaces such as XMLRPC or DBUS for controlling the daemon.
      • -
      • Hooking audio event sources directly into pulseaudio (similar to module-x11-bell)
      • -
      • For low latency applications such as VOIP: load the VOIP core directly into pulseaudio and have a slim GUI frontend to control it.
      • +
      • Hooking audio event sources directly into PulseAudio (similar to module-x11-bell)
      • +
      • For low latency applications such as VOIP: load the VOIP core directly into PulseAudio and have a slim GUI frontend to control it.

      There is currently no documentation how to write loadable modules -for pulseaudio. Read the source, Luke! If you are interested in +for PulseAudio. Read the source, Luke! If you are interested in writing new modules feel free to contact the author in case you have any questions.

      Requirements

      -

      Currently, pulseaudio is tested on Linux, FreeBSD, Solaris and Microsoft Windows. It requires an OSS, ALSA, Win32 or Solaris compatible soundcard.

      +

      Currently, PulseAudio> is tested on Linux, FreeBSD, Solaris and Microsoft Windows. It requires an OSS, ALSA, Win32 or Solaris compatible soundcard.

      -

      pulseaudio was developed and tested on Debian GNU/Linux +

      PulseAudio was developed and tested on Debian GNU/Linux "testing" from November 2004, it should work on most other Linux distributions (and maybe Unix versions) since it uses GNU autoconf and GNU libtool for source code configuration and shared library management.

      -

      pulseaudio needs Pulseaudio needs Secret Rabbit Code (aka libsamplerate), libsndfile, ./configure inside the distribution directory for configuring the source tree. After that you should run make for compilation and make install (as root) for installation of -pulseaudio.

      +PulseAudio.

      Acknowledgements

      @@ -304,11 +306,11 @@ compilation and make install (as root) for installation of

      Jeff Waugh for creating Ubuntu packages (and hopefully soon Debian)

      -

      Miguel Freitas for writing a Polypaudio driver for Xine

      +

      Miguel Freitas for writing a PulseAudio driver for Xine

      -

      Joe Marcus Clarke for porting Polypaudio to FreeBSD

      +

      Joe Marcus Clarke for porting PulseAudio to FreeBSD

      -

      Cendio AB for paying for Pierre's work on Polypaudio

      +

      Cendio AB for paying for Pierre's work on PulseAudio

      Sebastien ESTIENNE for testing

      @@ -320,7 +322,7 @@ compilation and make install (as root) for installation of

      The current release is @PACKAGE_VERSION@

      -

      Get pulseaudio's development sources from the Subversion repository (viewcvs):

      +

      Get PulseAudio's development sources from the Subversion repository (viewcvs):

      svn checkout svn://0pointer.de/pulseaudio/trunk pulseaudio
      @@ -328,13 +330,13 @@ compilation and make install (as root) for installation of

      If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

      -

      There is a general discussion mailing list for pulseaudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

      +

      There is a general discussion mailing list for PulseAudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

      -

      Polypaudio is being tracked at CIA.

      +

      PulseAudio is being tracked at CIA.

      -

      There's a chance to meet the Polypaudio developers on our IRC channel #pulseaudio on irc.freenode.org.

      +

      There's a chance to meet the PulseAudio developers on our IRC channel #pulseaudio on irc.freenode.org.

      -

      There is a Trac based Wiki for Polypaudio available.

      +

      There is a Trac based Wiki for PulseAudio available.

      Please report bugs to our Trac ticket system.

      diff --git a/doc/cli.html.in b/doc/cli.html.in index 511f5964c..3a256732d 100644 --- a/doc/cli.html.in +++ b/doc/cli.html.in @@ -2,14 +2,14 @@ -pulseaudio: Simple Command Line Language +PulseAudio: Simple Command Line Language

      Simple Command Line Language

      -

      pulseaudio provides a simple command line language used by +

      PulseAudio provides a simple command line language used by configuration scripts as well as the modules module-cli and module-cli-protocol-{unix,tcp}. Empty lines and lines beginning with a hashmark (#) are silently ignored. Several @@ -181,7 +181,7 @@ on the interactive command line.

      Example Configuration Script

      -

      Mark the following script as executable (chmod +x) and run it for a sensible pulseaudio configuration.

      +

      Mark the following script as executable (chmod +x) and run it for a sensible PulseAudio configuration.

       #!/usr/bin/polaudio -nF
      @@ -215,6 +215,6 @@ play-file /usr/share/sounds/startup3.wav combined
       

      -
      Lennart Poettering <@PACKAGE_BUGREPORT@>, April 2006
      +
      Lennart Poettering <@PACKAGE_BUGREPORT@>, June 2006
      $Id$
      diff --git a/doc/daemon.html.in b/doc/daemon.html.in index 0d91e534c..d90caa2a8 100644 --- a/doc/daemon.html.in +++ b/doc/daemon.html.in @@ -2,7 +2,7 @@ -pulseaudio: Daemon +PulseAudio: Daemon @@ -11,7 +11,7 @@

      Command Line Arguments

      -The pulseaudio daemon accepts several command line arguments: +The PulseAudio daemon accepts several command line arguments:
       COMMANDS:
      @@ -60,7 +60,7 @@ STARTUP SCRIPT:
       
       
      pulseaudio -D
      -

      This will run /etc/pulseaudio/default.pa after startup. This should be a script written in the CLI language described in cli.html.

      +

      This will run /etc/pulse/default.pa after startup. This should be a script written in the CLI language described in cli.html.

      Signals

      @@ -83,6 +83,6 @@ STARTUP SCRIPT:

      The daemon logs the current server layout.


      -
      Lennart Poettering <@PACKAGE_BUGREPORT@>, November 2004
      +
      Lennart Poettering <@PACKAGE_BUGREPORT@>, June 2006
      $Id$
      diff --git a/doc/modules.html.in b/doc/modules.html.in index f004f0841..dbad8d635 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -2,7 +2,7 @@ -pulseaudio: Loadable Modules +PulseAudio: Loadable Modules @@ -10,7 +10,7 @@

      Loadable Modules

      -

      The following loadable modules are provided with the pulseaudio distribution:

      +

      The following loadable modules are provided with the PulseAudio distribution:

      Device Drivers

      @@ -157,7 +157,7 @@ will decrease output quality however. (defaults to

      module-tunnel-{sink,source}

      Tunnel a remote sink/source to a local "ghost" -sink/source. Requires a running pulseaudio daemon on the remote server +sink/source. Requires a running PulseAudio daemon on the remote server with module-native-protocol-tcp loaded. It's probably a better idea to connect to the remote sink/source directly since some buffer control is lost through this tunneling.

      @@ -204,7 +204,7 @@ module see cli.html.

      module-cli-protocol-{unix,tcp}

      An implemenation of a simple command line based protocol for -controlling the pulseaudio daemon. If loaded, the user may +controlling the PulseAudio daemon. If loaded, the user may connect with tools like netcat, telnet or bidilink to the listening sockets and execute commands the same way as with module-cli.

      @@ -225,7 +225,7 @@ transparent TCP/IP socket. (Both IPv6 and IPv4 - if available)

      a numerical binary value. If 1 the socket is bound to the loopback device, i.e. not publicly accessible. (defaults to 1) listen=(only for -tcp) The IP address to listen on. If specified, supersedes the value specified in loopback= - socket=(only for -unix) The UNIX socket name (defaults to /tmp/pulseaudio/cli) + socket=(only for -unix) The UNIX socket name (defaults to /tmp/pulse/cli)

      module-simple-protocol-{unix,tcp}

      @@ -254,7 +254,7 @@ about the two possible suffixes of this module.

      An implemenation of a protocol compatible with the Enlightened Sound Daemon (ESOUND, esd). When you load this module you may -access the pulseaudio daemon with tools like esdcat, +access the PulseAudio daemon with tools like esdcat, esdrec or even esdctl. Many applications, such as XMMS, include support for this protocol.

      @@ -273,7 +273,7 @@ about the two possible suffixes of this module.

      module-native-protocol-{unix,tcp}

      -

      The native protocol of pulseaudio.

      +

      The native protocol of PulseAudio.

      See module-cli-protocol-{unix,tcp} for more information about the two possible suffixes of this module.

      @@ -293,7 +293,7 @@ about the two possible suffixes of this module.

      module-http-protocol-tcp

      A proof-of-concept HTTP module, which can be used to introspect -the current status of the pulseaudio daemon using HTTP. Just load this +the current status of the PulseAudio daemon using HTTP. Just load this module and point your browser to http://localhost:4714/. This module takes the same arguments as module-cli-protocol-tcp.

      @@ -430,7 +430,7 @@ created in the JACK server.

      - +
      sink_name=The name for the Polypaudio sink. If ommited defaults to jack_out.
      server_name=The JACK server to connect to. If ommited defaults to the default server.
      client_name=The client name to tell the JACK server. If ommited defaults to pulseaudio.
      client_name=The client name to tell the JACK server. If ommited defaults to PulseAudio.
      channels=Number of channels to register. If ommited defaults to the number of physical playback ports of the JACK server.
      connect=Takes a boolean value. If enabled (the default) Polypaudio will try to connect its ports to the physicial playback ports of the JACK server
      @@ -455,18 +455,18 @@ which is replaced by source_name (with a default of jack_in) f

      module-esound-compat-spawnfd

      -

      This is a compatibility module for libesd based autospawning of pulseaudio. Don't use it directly.

      +

      This is a compatibility module for libesd based autospawning of PulseAudio. Don't use it directly.

      module-esound-compat-spawnpid

      -

      This is a compatibility module for libesd based autospawning of pulseaudio. Don't use it directly.

      +

      This is a compatibility module for libesd based autospawning of PulseAudio. Don't use it directly.

      module-match

      Adjust the volume of a playback stream automatically based on its name.

      - +
      table=The regular expression matching table file to use (defaults to ~/.pulseaudio/match.table)
      table=The regular expression matching table file to use (defaults to ~/.pulse/match.table)

      The table file should contain a regexp and volume on each line, seperated by spaces. An example:

      @@ -482,7 +482,7 @@ which is replaced by source_name (with a default of jack_in) f

      Adjust the volume of a playback stream automatically based on its name.

      - +
      table=The table file to use (defaults to ~/.pulseaudio/volume.table)
      table=The table file to use (defaults to ~/.pulse/volume.table)

      In contrast to module-match this module needs no explicit From 230f97a4a4dc22510a19add8b2df0533a359846c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 23:56:54 +0000 Subject: [PATCH 0944/1514] s/POLYP/PULSE/g git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1041 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 10 +++--- doc/FAQ.html.in | 10 +++--- doc/modules.html.in | 4 +-- src/Makefile.am | 24 ++++++------- src/daemon/daemon-conf.c | 8 ++--- src/modules/module-x11-publish.c | 22 ++++++------ src/pulse/client-conf-x11.c | 8 ++--- src/pulse/client-conf.c | 16 ++++----- src/pulsecore/core-util.c | 10 +++--- src/pulsecore/log.c | 2 +- src/utils/padsp.c | 2 +- src/utils/pax11publish.c | 58 ++++++++++++++++---------------- 12 files changed, 87 insertions(+), 87 deletions(-) diff --git a/configure.ac b/configure.ac index bb72ee373..e2c8ed6c2 100644 --- a/configure.ac +++ b/configure.ac @@ -36,11 +36,11 @@ AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/]) AC_SUBST(PA_API_VERSION, 9) AC_SUBST(PA_PROTOCOL_VERSION, 9) -AC_SUBST(LIBPOLYP_VERSION_INFO, [0:0:0]) -AC_SUBST(LIBPOLYPCORE_VERSION_INFO, [0:1:0]) -AC_SUBST(LIBPOLYP_SIMPLE_VERSION_INFO, [0:0:0]) -AC_SUBST(LIBPOLYP_BROWSE_VERSION_INFO, [0:0:0]) -AC_SUBST(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO, [0:0:0]) +AC_SUBST(LIBPULSE_VERSION_INFO, [0:0:0]) +AC_SUBST(LIBPULSECORE_VERSION_INFO, [0:1:0]) +AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:0:0]) +AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [0:0:0]) +AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:0:0]) if type -p stow > /dev/null && test -d /usr/local/stow ; then AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in index 6b83cf77c..39b7390ab 100644 --- a/doc/FAQ.html.in +++ b/doc/FAQ.html.in @@ -103,7 +103,7 @@ in ~/.pulse/.

    • How do I use PulseAudio over the network?

      -

      Just set $POLYP_SERVER to the host name of the PulseAudio +

      Just set $PULSE_SERVER to the host name of the PulseAudio server. For authentication you need the same auth cookies on all sides. For that copy ~./pulse-cookie to all clients that shall be allowed to connect.

      @@ -116,9 +116,9 @@ be allowed to connect.

    • What environment variables does PulseAudio care about?

      -

      The client honors: POLYP_SINK (default sink to connect to), POLYP_SOURCE (default source to connect to), POLYP_SERVER (default server to connect to, like ESPEAKER), POLYP_BINARY (the binary to start when autospawning a daemon), POLYP_CLIENTCONFIG (path to the client configuration file).

      +

      The client honors: PULSE_SINK (default sink to connect to), PULSE_SOURCE (default source to connect to), PULSE_SERVER (default server to connect to, like ESPEAKER), PULSE_BINARY (the binary to start when autospawning a daemon), PULSE_CLIENTCONFIG (path to the client configuration file).

      -

      The daemon honors: POLYP_SCRIPT (default CLI script file run after startup), POLYP_CONFIG (default daemon configuration file), POLYP_DLPATH (colon separated list of paths where to look for modules)

    • +

      The daemon honors: PULSE_SCRIPT (default CLI script file run after startup), PULSE_CONFIG (default daemon configuration file), PULSE_DLPATH (colon separated list of paths where to look for modules)

    • I saw that SIGUSR2 provokes loading of the module module-cli-protocol-unix. But how do I make use of that?

      @@ -140,8 +140,8 @@ bidilink unix-client:/tmp/pulse-$USER/cli
    • The following rule applies:

      1. If the the application using the library specifies a server to connect to it is used. If the connection fails, the library fails too.
      2. -
      3. If the environment variable POLYP_SERVER is defined the library connects to that server. If the connection fails, the library fails too.
      4. -
      5. If $DISPLAY is set, the library tries to connect to that server and looks for the root window property POYLP_SERVER for the host to connect to. If POLYP_COOKIE is set it is used as authentication cookie.
      6. +
      7. If the environment variable PULSE_SERVER is defined the library connects to that server. If the connection fails, the library fails too.
      8. +
      9. If $DISPLAY is set, the library tries to connect to that server and looks for the root window property POYLP_SERVER for the host to connect to. If PULSE_COOKIE is set it is used as authentication cookie.
      10. If the client configuration file (~/.pulse/client.conf or /etc/pulse/client.conf) sets the server address, the library connects to that server. If the connection fails, the library fails too.
      11. The library tries to connect to the default local UNIX socket for PulseAudio servers. If the connection fails, it proceeds with the next item.
      12. The library tries to connect to the default local TCP socket for PulseAudio servers. If the connection fails, it proceeds with the next item.
      13. diff --git a/doc/modules.html.in b/doc/modules.html.in index dbad8d635..23ece9547 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -314,8 +314,8 @@ as module-cli-protocol-tcp.

        Publishes the access credentials to the Polypaudio server in the X11 root window. The following properties are used: -POLYP_SERVER, POYLP_SINK, POLYP_SOURCE, -POLYP_COOKIE. This is very useful when using SSH or any other +PULSE_SERVER, POYLP_SINK, PULSE_SOURCE, +PULSE_COOKIE. This is very useful when using SSH or any other remote login tool for logging into other machines and getting audio playback to your local speakers. The Polypaudio client libraries make use of this data automatically. Instead of using this module you may diff --git a/src/Makefile.am b/src/Makefile.am index 746f85ecf..12621d6a3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,9 +30,9 @@ pulseconfdir=$(sysconfdir)/pulse # Defines # ################################### -POLYPAUDIO_BINARY=$(bindir)/pulseaudio$(EXEEXT) +PULSEAUDIO_BINARY=$(bindir)/pulseaudio$(EXEEXT) if OS_IS_WIN32 -DEFAULT_CONFIG_DIR=%POLYP_ROOT% +DEFAULT_CONFIG_DIR=%PULSE_ROOT% else DEFAULT_CONFIG_DIR=$(pulseconfdir) endif @@ -48,7 +48,7 @@ AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibexecdir)\" #AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" -AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\" +AM_CFLAGS += -DPULSEAUDIO_BINARY=\"$(PULSEAUDIO_BINARY)\" # This cool debug trap works on i386/gcc only AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")' @@ -426,7 +426,7 @@ libpulse_la_SOURCES += \ endif libpulse_la_CFLAGS = $(AM_CFLAGS) -libpulse_la_LDFLAGS = -version-info $(LIBPOLYP_VERSION_INFO) +libpulse_la_LDFLAGS = -version-info $(LIBPULSE_VERSION_INFO) libpulse_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LIBICONV) if HAVE_X11 @@ -442,22 +442,22 @@ endif libpulse_simple_la_SOURCES = pulse/simple.c pulse/simple.h libpulse_simple_la_CFLAGS = $(AM_CFLAGS) libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la -libpulse_simple_la_LDFLAGS = -version-info $(LIBPOLYP_SIMPLE_VERSION_INFO) +libpulse_simple_la_LDFLAGS = -version-info $(LIBPULSE_SIMPLE_VERSION_INFO) libpulse_browse_la_SOURCES = pulse/browser.c pulse/browser.h libpulse_browse_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) libpulse_browse_la_LIBADD = $(AM_LIBADD) libpulse.la $(HOWL_LIBS) -libpulse_browse_la_LDFLAGS = -version-info $(LIBPOLYP_BROWSE_VERSION_INFO) +libpulse_browse_la_LDFLAGS = -version-info $(LIBPULSE_BROWSE_VERSION_INFO) libpulse_mainloop_glib_la_SOURCES = pulse/glib-mainloop.h pulse/glib-mainloop.c libpulse_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) libpulse_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpulse.la $(GLIB20_LIBS) -libpulse_mainloop_glib_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO) +libpulse_mainloop_glib_la_LDFLAGS = -version-info $(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO) libpulse_mainloop_glib12_la_SOURCES = pulse/glib-mainloop.h pulse/glib12-mainloop.c libpulse_mainloop_glib12_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) libpulse_mainloop_glib12_la_LIBADD = $(AM_LIBADD) libpulse.la $(GLIB12_LIBS) -libpulse_mainloop_glib12_la_LDFLAGS = -version-info $(LIBPOLYP_MAINLOOP_GLIB_VERSION_INFO) +libpulse_mainloop_glib12_la_LDFLAGS = -version-info $(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO) ################################### # OSS emulation # @@ -593,7 +593,7 @@ libpulsecore_la_SOURCES += \ endif libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) -libpulsecore_la_LDFLAGS = -version-info $(LIBPOLYPCORE_VERSION_INFO) +libpulsecore_la_LDFLAGS = -version-info $(LIBPULSECORE_VERSION_INFO) libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV) ################################### @@ -1177,17 +1177,17 @@ CLEANFILES = esdcompat client.conf default.pa daemon.conf esdcompat: daemon/esdcompat.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ - -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ + -e 's,@PULSEAUDIO_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ client.conf: pulse/client.conf.in Makefile - sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ + sed -e 's,@PULSEAUDIO_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ if OS_IS_WIN32 default.pa: daemon/default.pa.win32 cp $< $@ else default.pa: daemon/default.pa.in Makefile - sed -e 's,@POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@ + sed -e 's,@PULSEAUDIO_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ endif daemon.conf: daemon/daemon.conf.in Makefile diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 4d458a5c0..64e8d2356 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -43,7 +43,7 @@ # ifndef OS_IS_WIN32 # define DEFAULT_CONFIG_DIR "/etc/pulse" # else -# define DEFAULT_CONFIG_DIR "%POLYP_ROOT%" +# define DEFAULT_CONFIG_DIR "%PULSE_ROOT%" # endif #endif @@ -58,9 +58,9 @@ #define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" #define DEFAULT_CONFIG_FILE_USER ".pulse" PATH_SEP "daemon.conf" -#define ENV_SCRIPT_FILE "POLYP_SCRIPT" -#define ENV_CONFIG_FILE "POLYP_CONFIG" -#define ENV_DL_SEARCH_PATH "POLYP_DLPATH" +#define ENV_SCRIPT_FILE "PULSE_SCRIPT" +#define ENV_CONFIG_FILE "PULSE_CONFIG" +#define ENV_DL_SEARCH_PATH "PULSE_DLPATH" static const pa_daemon_conf default_conf = { .cmd = PA_CMD_DAEMON, diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index 05f0d86a5..0ee453cca 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -128,22 +128,22 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; s = pa_strlist_tostring(l); - pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SERVER", s); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER", s); pa_xfree(s); if (!pa_get_fqdn(hn, sizeof(hn)) || !pa_get_user_name(un, sizeof(un))) goto fail; u->id = pa_sprintf_malloc("%s@%s/%u", un, hn, (unsigned) getpid()); - pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_ID", u->id); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID", u->id); if ((t = pa_modargs_get_value(ma, "source", NULL))) - pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SOURCE", t); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SOURCE", t); if ((t = pa_modargs_get_value(ma, "sink", NULL))) - pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SINK", t); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SINK", t); - pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), hx, sizeof(hx))); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), hx, sizeof(hx))); pa_modargs_free(ma); return 0; @@ -167,14 +167,14 @@ void pa__done(pa_core *c, pa_module*m) { char t[256]; /* Yes, here is a race condition */ - if (!pa_x11_get_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_ID", t, sizeof(t)) || strcmp(t, u->id)) + if (!pa_x11_get_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID", t, sizeof(t)) || strcmp(t, u->id)) pa_log_warn(__FILE__": PulseAudio information vanished from X11!"); else { - pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_ID"); - pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SERVER"); - pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SINK"); - pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_SOURCE"); - pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "POLYP_COOKIE"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SINK"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SOURCE"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_COOKIE"); XSync(pa_x11_wrapper_get_display(u->x11_wrapper), False); } } diff --git a/src/pulse/client-conf-x11.c b/src/pulse/client-conf-x11.c index 7eea5ae37..e4a900177 100644 --- a/src/pulse/client-conf-x11.c +++ b/src/pulse/client-conf-x11.c @@ -50,22 +50,22 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { goto finish; } - if (pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) { + if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) { pa_xfree(c->default_server); c->default_server = pa_xstrdup(t); } - if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) { + if (pa_x11_get_prop(d, "PULSE_SINK", t, sizeof(t))) { pa_xfree(c->default_sink); c->default_sink = pa_xstrdup(t); } - if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) { + if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t))) { pa_xfree(c->default_source); c->default_source = pa_xstrdup(t); } - if (pa_x11_get_prop(d, "POLYP_COOKIE", t, sizeof(t))) { + if (pa_x11_get_prop(d, "PULSE_COOKIE", t, sizeof(t))) { uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; if (pa_parsehex(t, cookie, sizeof(cookie)) != sizeof(cookie)) { diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 9f5cf53da..e150a9cc0 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -43,7 +43,7 @@ # ifndef OS_IS_WIN32 # define DEFAULT_CONFIG_DIR "/etc/pulse" # else -# define DEFAULT_CONFIG_DIR "%POLYP_ROOT%" +# define DEFAULT_CONFIG_DIR "%PULSE_ROOT%" # endif #endif @@ -56,12 +56,12 @@ #define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "client.conf" #define DEFAULT_CLIENT_CONFIG_FILE_USER ".pulse" PATH_SEP "client.conf" -#define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG" -#define ENV_DEFAULT_SINK "POLYP_SINK" -#define ENV_DEFAULT_SOURCE "POLYP_SOURCE" -#define ENV_DEFAULT_SERVER "POLYP_SERVER" -#define ENV_DAEMON_BINARY "POLYP_BINARY" -#define ENV_COOKIE_FILE "POLYP_COOKIE" +#define ENV_CLIENT_CONFIG_FILE "PULSE_CLIENTCONFIG" +#define ENV_DEFAULT_SINK "PULSE_SINK" +#define ENV_DEFAULT_SOURCE "PULSE_SOURCE" +#define ENV_DEFAULT_SERVER "PULSE_SERVER" +#define ENV_DAEMON_BINARY "PULSE_BINARY" +#define ENV_COOKIE_FILE "PULSE_COOKIE" static const pa_client_conf default_conf = { .daemon_binary = NULL, @@ -77,7 +77,7 @@ static const pa_client_conf default_conf = { pa_client_conf *pa_client_conf_new(void) { pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); - c->daemon_binary = pa_xstrdup(POLYPAUDIO_BINARY); + c->daemon_binary = pa_xstrdup(PULSEAUDIO_BINARY); c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5"); c->cookie_file = pa_xstrdup(PA_NATIVE_COOKIE_FILE); diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index d4b140ded..9d694da5f 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -88,14 +88,14 @@ #ifdef OS_IS_WIN32 -#define POLYP_ROOTENV "POLYP_ROOT" +#define PULSE_ROOTENV "PULSE_ROOT" int pa_set_root(HANDLE handle) { - char library_path[MAX_PATH + sizeof(POLYP_ROOTENV) + 1], *sep; + char library_path[MAX_PATH + sizeof(PULSE_ROOTENV) + 1], *sep; - strcpy(library_path, POLYP_ROOTENV "="); + strcpy(library_path, PULSE_ROOTENV "="); - if (!GetModuleFileName(handle, library_path + sizeof(POLYP_ROOTENV), MAX_PATH)) + if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH)) return 0; sep = strrchr(library_path, '\\'); @@ -818,7 +818,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env #ifdef OS_IS_WIN32 char buf[PATH_MAX]; - if (!getenv(POLYP_ROOTENV)) + if (!getenv(PULSE_ROOTENV)) pa_set_root(NULL); #endif diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index df5b140ac..06e95b285 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -40,7 +40,7 @@ #include "log.h" -#define ENV_LOGLEVEL "POLYP_LOG" +#define ENV_LOGLEVEL "PULSE_LOG" static char *log_ident = NULL, *log_ident_local = NULL; static pa_log_target_t log_target = PA_LOG_STDERR; diff --git a/src/utils/padsp.c b/src/utils/padsp.c index d9dcc7645..af89f8fb7 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1500,7 +1500,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_INFO\n"); memset(mi, 0, sizeof(mixer_info)); - strncpy(mi->id, "POLYPAUDIO", sizeof(mi->id)); + strncpy(mi->id, "PULSEAUDIO", sizeof(mi->id)); strncpy(mi->name, "PulseAudio Virtual OSS", sizeof(mi->name)); pa_threaded_mainloop_lock(i->mainloop); mi->modify_counter = i->volume_modify_count; diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index d2ed6c930..2a0d21d68 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -99,13 +99,13 @@ int main(int argc, char *argv[]) { switch (mode) { case DUMP: { char t[1024]; - if (pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) printf("Server: %s\n", t); - if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t))) printf("Source: %s\n", t); - if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_SINK", t, sizeof(t))) printf("Sink: %s\n", t); - if (pa_x11_get_prop(d, "POLYP_COOKIE", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_COOKIE", t, sizeof(t))) printf("Cookie: %s\n", t); break; @@ -113,14 +113,14 @@ int main(int argc, char *argv[]) { case IMPORT: { char t[1024]; - if (pa_x11_get_prop(d, "POLYP_SERVER", t, sizeof(t))) - printf("POLYP_SERVER='%s'\nexport POLYP_SERVER\n", t); - if (pa_x11_get_prop(d, "POLYP_SOURCE", t, sizeof(t))) - printf("POLYP_SOURCE='%s'\nexport POLYP_SOURCE\n", t); - if (pa_x11_get_prop(d, "POLYP_SINK", t, sizeof(t))) - printf("POLYP_SINK='%s'\nexport POLYP_SINK\n", t); + if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) + printf("PULSE_SERVER='%s'\nexport PULSE_SERVER\n", t); + if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t))) + printf("PULSE_SOURCE='%s'\nexport PULSE_SOURCE\n", t); + if (pa_x11_get_prop(d, "PULSE_SINK", t, sizeof(t))) + printf("PULSE_SINK='%s'\nexport PULSE_SINK\n", t); - if (pa_x11_get_prop(d, "POLYP_COOKIE", t, sizeof(t))) { + if (pa_x11_get_prop(d, "PULSE_COOKIE", t, sizeof(t))) { uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; size_t l; if ((l = pa_parsehex(t, cookie, sizeof(cookie))) != sizeof(cookie)) { @@ -153,16 +153,16 @@ int main(int argc, char *argv[]) { goto finish; } - pa_x11_del_prop(d, "POLYP_SERVER"); - pa_x11_del_prop(d, "POLYP_SINK"); - pa_x11_del_prop(d, "POLYP_SOURCE"); - pa_x11_del_prop(d, "POLYP_ID"); - pa_x11_del_prop(d, "POLYP_COOKIE"); + pa_x11_del_prop(d, "PULSE_SERVER"); + pa_x11_del_prop(d, "PULSE_SINK"); + pa_x11_del_prop(d, "PULSE_SOURCE"); + pa_x11_del_prop(d, "PULSE_ID"); + pa_x11_del_prop(d, "PULSE_COOKIE"); if (server) - pa_x11_set_prop(d, "POLYP_SERVER", server); + pa_x11_set_prop(d, "PULSE_SERVER", server); else if (conf->default_server) - pa_x11_set_prop(d, "POLYP_SERVER", conf->default_server); + pa_x11_set_prop(d, "PULSE_SERVER", conf->default_server); else { char hn[256]; if (!pa_get_fqdn(hn, sizeof(hn))) { @@ -170,18 +170,18 @@ int main(int argc, char *argv[]) { goto finish; } - pa_x11_set_prop(d, "POLYP_SERVER", hn); + pa_x11_set_prop(d, "PULSE_SERVER", hn); } if (sink) - pa_x11_set_prop(d, "POLYP_SINK", sink); + pa_x11_set_prop(d, "PULSE_SINK", sink); else if (conf->default_sink) - pa_x11_set_prop(d, "POLYP_SINK", conf->default_sink); + pa_x11_set_prop(d, "PULSE_SINK", conf->default_sink); if (source) - pa_x11_set_prop(d, "POLYP_SOURCE", source); + pa_x11_set_prop(d, "PULSE_SOURCE", source); if (conf->default_source) - pa_x11_set_prop(d, "POLYP_SOURCE", conf->default_source); + pa_x11_set_prop(d, "PULSE_SOURCE", conf->default_source); pa_client_conf_free(conf); @@ -190,16 +190,16 @@ int main(int argc, char *argv[]) { goto finish; } - pa_x11_set_prop(d, "POLYP_COOKIE", pa_hexstr(cookie, sizeof(cookie), hx, sizeof(hx))); + pa_x11_set_prop(d, "PULSE_COOKIE", pa_hexstr(cookie, sizeof(cookie), hx, sizeof(hx))); break; } case REMOVE: - pa_x11_del_prop(d, "POLYP_SERVER"); - pa_x11_del_prop(d, "POLYP_SINK"); - pa_x11_del_prop(d, "POLYP_SOURCE"); - pa_x11_del_prop(d, "POLYP_ID"); - pa_x11_del_prop(d, "POLYP_COOKIE"); + pa_x11_del_prop(d, "PULSE_SERVER"); + pa_x11_del_prop(d, "PULSE_SINK"); + pa_x11_del_prop(d, "PULSE_SOURCE"); + pa_x11_del_prop(d, "PULSE_ID"); + pa_x11_del_prop(d, "PULSE_COOKIE"); break; default: From 3ff68bd7a57186c6c6def975be3fc7e826c8bbcd Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 13:02:34 +0000 Subject: [PATCH 0945/1514] Fix the final few occurences of polyp. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1042 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/modules.html.in | 20 ++++++++++---------- src/daemon/default.pa.in | 2 +- src/daemon/esdcompat.in | 2 +- src/modules/rtp/module-rtp-send.c | 2 +- src/pulse/client.conf.in | 2 +- src/utils/padsp | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/doc/modules.html.in b/doc/modules.html.in index 23ece9547..7f12d9a94 100644 --- a/doc/modules.html.in +++ b/doc/modules.html.in @@ -312,12 +312,12 @@ as module-cli-protocol-tcp.

        module-x11-publish

        -

        Publishes the access credentials to the Polypaudio server in the +

        Publishes the access credentials to the PulseAudio server in the X11 root window. The following properties are used: PULSE_SERVER, POYLP_SINK, PULSE_SOURCE, PULSE_COOKIE. This is very useful when using SSH or any other remote login tool for logging into other machines and getting audio -playback to your local speakers. The Polypaudio client libraries make +playback to your local speakers. The PulseAudio client libraries make use of this data automatically. Instead of using this module you may use the tool pax11publish which may be used to access, modify and import credential data from/to the X11 display.

        @@ -354,7 +354,7 @@ already loaded protocol module is used.

        RTP/SDP/SAP Transport

        -

        Polypaudio can stream audio data to an IP multicast group via the +

        PulseAudio can stream audio data to an IP multicast group via the standard protocols RTP, -

        Polypaudio implements both a sender and a reciever for RTP +

        PulseAudio implements both a sender and a reciever for RTP traffic. The sender announces itself via SAP/SDP on the same multicast group as it sends the RTP data to. The reciever picks up the SAP/SDP announcements and creates a playback stream for each @@ -418,26 +418,26 @@ module to create an RTP source.

        JACK Connectivity

        -

        Polypaudio can be hooked up to a PulseAudio can be hooked up to a JACK Audio Connection Kit server which is a specialized sound server used for professional audio production on Unix/Linux. Both a -Polypaudio sink and a source are available. For each channel a port is +PulseAudio sink and a source are available. For each channel a port is created in the JACK server.

        module-jack-sink

        -

        This module implements a Polypaudio sink that connects to JACK and registers as many output ports as requested.

        +

        This module implements a PulseAudio sink that connects to JACK and registers as many output ports as requested.

        - + - +
        sink_name=The name for the Polypaudio sink. If ommited defaults to jack_out.
        sink_name=The name for the PulseAudio sink. If ommited defaults to jack_out.
        server_name=The JACK server to connect to. If ommited defaults to the default server.
        client_name=The client name to tell the JACK server. If ommited defaults to PulseAudio.
        channels=Number of channels to register. If ommited defaults to the number of physical playback ports of the JACK server.
        connect=Takes a boolean value. If enabled (the default) Polypaudio will try to connect its ports to the physicial playback ports of the JACK server
        connect=Takes a boolean value. If enabled (the default) PulseAudio will try to connect its ports to the physicial playback ports of the JACK server

        module-jack-source

        -

        This module implements a Polypaudio source that connects to JACK +

        This module implements a PulseAudio source that connects to JACK and registers as many input ports as requested. Takes the same arguments as module-jack-sink, except for sink_name which is replaced by source_name (with a default of jack_in) for obvious reasons.

        diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index 623cd1148..6beeb90f6 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -1,4 +1,4 @@ -#!@POLYPAUDIO_BINARY@ -nF +#!@PULSEAUDIO_BINARY@ -nF # # This file is part of PulseAudio. diff --git a/src/daemon/esdcompat.in b/src/daemon/esdcompat.in index 673f8c8ac..edae8615d 100755 --- a/src/daemon/esdcompat.in +++ b/src/daemon/esdcompat.in @@ -95,4 +95,4 @@ EOF shift done -eval "exec '@POLYPAUDIO_BINARY@'$ARGS" +eval "exec '@PULSEAUDIO_BINARY@'$ARGS" diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 00da64d54..5c47047fd 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -298,7 +298,7 @@ int pa__init(pa_core *c, pa_module*m) { r = getsockname(fd, (struct sockaddr*) &sa_dst, &k); assert(r >= 0); - n = pa_sprintf_malloc("Polypaudio RTP Stream on %s", pa_get_fqdn(hn, sizeof(hn))); + n = pa_sprintf_malloc("PulseAudio RTP Stream on %s", pa_get_fqdn(hn, sizeof(hn))); p = pa_sdp_build(af, af == AF_INET ? (void*) &((struct sockaddr_in*) &sa_dst)->sin_addr : (void*) &((struct sockaddr_in6*) &sa_dst)->sin6_addr, diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in index d881c44e8..21786ebf4 100644 --- a/src/pulse/client.conf.in +++ b/src/pulse/client.conf.in @@ -21,7 +21,7 @@ ## commented out. Use either ; or # for commenting ## Path to the pulseaudio daemon to run when autospawning. -; daemon-binary = @POLYPAUDIO_BINARY@ +; daemon-binary = @PULSEAUDIO_BINARY@ ## Extra arguments to pass to the pulseaudio daemon ; extra-arguments = --log-target=syslog --exit-idle-time=5 diff --git a/src/utils/padsp b/src/utils/padsp index d9ebcbc57..bae5a7289 100644 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -22,8 +22,8 @@ while getopts 'hs:n:m:MSDd' param ; do case $param in s) - POLYP_SERVER="$OPTARG" - export POLYP_SERVER + PULSE_SERVER="$OPTARG" + export PULSE_SERVER ;; n) PADSP_CLIENT_NAME="$OPTARG" From 6ca46f4d7a9fa57b949e2286d3af1b6e78dce8f5 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 13:49:30 +0000 Subject: [PATCH 0946/1514] Make interpol-test build on Win32 and non-pthread systems. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1043 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/interpol-test.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c index 7cabc1c9c..bf7f582c9 100644 --- a/src/tests/interpol-test.c +++ b/src/tests/interpol-test.c @@ -32,7 +32,10 @@ #include #include #include + +#ifdef HAVE_PTHREAD #include +#endif #include #include @@ -145,7 +148,13 @@ int main(int argc, char *argv[]) { tv = now; while (pa_timeval_diff(pa_gettimeofday(&now), &tv) < 1000) +#ifdef HAVE_PTHREAD pthread_yield(); +#elif defined(OS_IS_WIN32) + Sleep(0); +#else + ; +#endif } if (m) From 3b2835843e61e41cdcef1bf0e5cd3687d20767b9 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 14:22:34 +0000 Subject: [PATCH 0947/1514] Check for pthread_yield() as not all platforms have that. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1044 fefdeb5f-60dc-0310-8127-8f9354f1896f --- acinclude.m4 | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/acinclude.m4 b/acinclude.m4 index edd803445..f3a4ac520 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -174,6 +174,17 @@ if test "x$acx_pthread_ok" = xyes; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi + AC_MSG_CHECKING([if pthread_yield is available]) + flag=no + AC_TRY_LINK([#include ], + [pthread_yield();], + [flag=yes]) + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + AC_DEFINE(HAVE_PTHREAD_YIELD, 1, + [Define to 1 if you have the 'pthread_yield' function.]) + fi + LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" From 1342999b5197adeb76ee9feb41f38dba26a20dbe Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 14:26:52 +0000 Subject: [PATCH 0948/1514] Make sure we do not use pthread_yield() on platforms that do not have them. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1045 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/interpol-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c index bf7f582c9..2df65a455 100644 --- a/src/tests/interpol-test.c +++ b/src/tests/interpol-test.c @@ -148,7 +148,7 @@ int main(int argc, char *argv[]) { tv = now; while (pa_timeval_diff(pa_gettimeofday(&now), &tv) < 1000) -#ifdef HAVE_PTHREAD +#ifdef HAVE_PTHREAD_YIELD pthread_yield(); #elif defined(OS_IS_WIN32) Sleep(0); From 07edf591771e719a5616ca11319f644fbf66f576 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 15:36:28 +0000 Subject: [PATCH 0949/1514] Make fix_metrics() exit early so that it doesn't spam the output needlessly. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1046 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index af89f8fb7..3b8ecbf19 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -673,6 +673,13 @@ static void fix_metrics(fd_info *i) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; fs = pa_frame_size(&i->sample_spec); + + /* Don't fix things more than necessary */ + if ((i->fragment_size % fs) == 0 && + i->n_fragments >= 2 && + i->fragment_size > 0) + return; + i->fragment_size = (i->fragment_size/fs)*fs; /* Number of fragments set? */ From 1040b69cf2fc6175a1069226a93ec66f1a092ad0 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 15:45:10 +0000 Subject: [PATCH 0950/1514] Warn when applications use SNDCTL_DSP_GET[IO]PTR even when they shouldn't. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1047 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 3b8ecbf19..3b2294f7e 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1992,10 +1992,19 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; } - + + case SNDCTL_DSP_GETIPTR: + debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETIPTR\n"); + goto inval; + + case SNDCTL_DSP_GETOPTR: + debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETOPTR\n"); + goto inval; + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); +inval: *_errno = EINVAL; goto fail; } From 320bedb58032d33a2bd31978c95b8f17d07c9872 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 20 Jun 2006 16:43:46 +0000 Subject: [PATCH 0951/1514] Fix handling of the io flags in duplex mode. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1048 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 3b2294f7e..f493f7e5a 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -75,6 +75,7 @@ struct fd_info { pa_stream *rec_stream; pa_io_event *io_event; + pa_io_event_flags_t io_flags; void *buf; size_t rec_offset; @@ -557,6 +558,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { i->play_stream = NULL; i->rec_stream = NULL; i->io_event = NULL; + i->io_flags = 0; pthread_mutex_init(&i->mutex, NULL); i->ref = 1; i->buf = NULL; @@ -709,13 +711,10 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { if (i->io_event) { pa_mainloop_api *api; - pa_io_event_flags_t flags; size_t n; api = pa_threaded_mainloop_get_api(i->mainloop); - flags = 0; - if (s == i->play_stream) { n = pa_stream_writable_size(i->play_stream); if (n == (size_t)-1) { @@ -724,7 +723,9 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { } if (n >= i->fragment_size) - flags |= PA_IO_EVENT_INPUT; + i->io_flags |= PA_IO_EVENT_INPUT; + else + i->io_flags &= ~PA_IO_EVENT_INPUT; } if (s == i->rec_stream) { @@ -735,10 +736,12 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { } if (n >= i->fragment_size) - flags |= PA_IO_EVENT_OUTPUT; + i->io_flags |= PA_IO_EVENT_OUTPUT; + else + i->io_flags &= ~PA_IO_EVENT_OUTPUT; } - api->io_enable(i->io_event, flags); + api->io_enable(i->io_event, i->io_flags); } } @@ -757,6 +760,7 @@ static void fd_info_shutdown(fd_info *i) { api = pa_threaded_mainloop_get_api(i->mainloop); api->io_free(i->io_event); i->io_event = NULL; + i->io_flags = 0; } if (i->thread_fd >= 0) { @@ -767,13 +771,10 @@ static void fd_info_shutdown(fd_info *i) { static int fd_info_copy_data(fd_info *i, int force) { size_t n; - pa_io_event_flags_t flags; if (!i->play_stream && !i->rec_stream) return -1; - flags = 0; - if ((i->play_stream) && (pa_stream_get_state(i->play_stream) == PA_STREAM_READY)) { n = pa_stream_writable_size(i->play_stream); @@ -814,7 +815,9 @@ static int fd_info_copy_data(fd_info *i, int force) { } if (n >= i->fragment_size) - flags |= PA_IO_EVENT_INPUT; + i->io_flags |= PA_IO_EVENT_INPUT; + else + i->io_flags &= ~PA_IO_EVENT_INPUT; } if ((i->rec_stream) && (pa_stream_get_state(i->rec_stream) == PA_STREAM_READY)) { @@ -867,14 +870,16 @@ static int fd_info_copy_data(fd_info *i, int force) { } if (n >= i->fragment_size) - flags |= PA_IO_EVENT_OUTPUT; + i->io_flags |= PA_IO_EVENT_OUTPUT; + else + i->io_flags &= ~PA_IO_EVENT_OUTPUT; } if (i->io_event) { pa_mainloop_api *api; api = pa_threaded_mainloop_get_api(i->mainloop); - api->io_enable(i->io_event, flags); + api->io_enable(i->io_event, i->io_flags); } return 0; @@ -1034,7 +1039,6 @@ static int dsp_open(int flags, int *_errno) { pa_mainloop_api *api; int ret; int f; - pa_io_event_flags_t ioflags; debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open()\n"); @@ -1056,23 +1060,23 @@ static int dsp_open(int flags, int *_errno) { switch (flags & O_ACCMODE) { case O_RDONLY: - ioflags = PA_IO_EVENT_OUTPUT; + i->io_flags = PA_IO_EVENT_OUTPUT; shutdown(i->thread_fd, SHUT_RD); shutdown(i->app_fd, SHUT_WR); break; case O_WRONLY: - ioflags = PA_IO_EVENT_INPUT; + i->io_flags = PA_IO_EVENT_INPUT; shutdown(i->thread_fd, SHUT_WR); shutdown(i->app_fd, SHUT_RD); break; case O_RDWR: - ioflags = PA_IO_EVENT_INPUT | PA_IO_EVENT_OUTPUT; + i->io_flags = PA_IO_EVENT_INPUT | PA_IO_EVENT_OUTPUT; break; default: return -1; } - if (!(i->io_event = api->io_new(api, i->thread_fd, ioflags, io_event_cb, i))) + if (!(i->io_event = api->io_new(api, i->thread_fd, i->io_flags, io_event_cb, i))) goto fail; pa_threaded_mainloop_unlock(i->mainloop); From 84907e6716b83a340c0d5717148d6262fc0f7121 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 20 Jun 2006 21:23:10 +0000 Subject: [PATCH 0952/1514] fix segfault when module-alsa-source fails to load git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1049 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 2 +- src/modules/module-alsa-source.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index d49b34076..9238072b5 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -342,7 +342,7 @@ int pa__init(pa_core *c, pa_module*m) { } period_size = fragsize/frame_size; - u = pa_xmalloc0(sizeof(struct userdata)); + u = pa_xnew0(struct userdata, 1); m->userdata = u; u->module = m; diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index c4e8689ce..68c61be97 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -335,7 +335,7 @@ int pa__init(pa_core *c, pa_module*m) { } period_size = fragsize/frame_size; - u = pa_xnew(struct userdata, 1); + u = pa_xnew0(struct userdata, 1); m->userdata = u; u->module = m; From 74e958c008c743ec157edf4f08edf5cb94413194 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 20 Jun 2006 22:27:35 +0000 Subject: [PATCH 0953/1514] bump version number git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1050 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- doc/README.html.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e2c8ed6c2..3b02df5a8 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_PREREQ(2.57) m4_define(PA_MAJOR, [0]) m4_define(PA_MINOR, [9]) -m4_define(PA_MICRO, [1]) +m4_define(PA_MICRO, [2]) AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) diff --git a/doc/README.html.in b/doc/README.html.in index e4eea7866..31cd929dc 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -328,7 +328,7 @@ PulseAudio.

        Community

        -

        If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

        +

        If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

        There is a general discussion mailing list for PulseAudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

        From 1710041eaffc917d45eaeb6143db24a9773842b3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Jun 2006 00:18:43 +0000 Subject: [PATCH 0954/1514] only interpolate when the last timing info told us the stream is indeed playing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1051 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulse/stream.c b/src/pulse/stream.c index c8fc09d29..677df009d 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -1254,7 +1254,7 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { /* We just add the time that passed since the latency info was * current */ - if (!s->corked) { + if (!s->corked && s->timing_info.playing) { struct timeval now; usec += pa_timeval_diff(pa_gettimeofday(&now), &s->timing_info.timestamp); } From 045b05cd91aa313d9a3cb496f8a0e664d8bceea3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Jun 2006 14:05:15 +0000 Subject: [PATCH 0955/1514] include config.h in browser.c (closes #20) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1052 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/browser.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pulse/browser.c b/src/pulse/browser.c index 966258692..60c71090b 100644 --- a/src/pulse/browser.c +++ b/src/pulse/browser.c @@ -19,6 +19,10 @@ USA. ***/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include From 18b8b84b7e3885165ef14cd7c25fa34f1ce36b61 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Jun 2006 16:36:58 +0000 Subject: [PATCH 0956/1514] increase the maxium number of concurrent esd and native connections git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1053 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-esound.c | 2 +- src/pulsecore/protocol-native.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 6b9112bf4..5daa32fef 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -55,7 +55,7 @@ #include "protocol-esound.h" /* Don't accept more connection than this */ -#define MAX_CONNECTIONS 10 +#define MAX_CONNECTIONS 64 /* Kick a client if it doesn't authenticate within this time */ #define AUTH_TIMEOUT 5 diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 1f936e753..f77c9c24f 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -62,7 +62,7 @@ #define AUTH_TIMEOUT 60 /* Don't accept more connection than this */ -#define MAX_CONNECTIONS 10 +#define MAX_CONNECTIONS 64 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */ From 8b0d1346022d0eb3f3b4bf3eb956f9757ff57156 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 30 Jun 2006 08:16:14 +0000 Subject: [PATCH 0957/1514] Make sure we print the file name we actually use. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1054 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 2 +- src/pulse/client-conf.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 64e8d2356..d1afed7b1 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -238,7 +238,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file, "r"); if (!f && errno != ENOENT) { - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno)); goto finish; } diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index e150a9cc0..5cebcf460 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -124,7 +124,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn, "r"); if (!f && errno != EINTR) { - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); + pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } From 9e45991b112680c9ae64454811577c7c0d790501 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Jul 2006 12:45:24 +0000 Subject: [PATCH 0958/1514] update readme for 0.9.2 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1055 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index 31cd929dc..0a49e1ed0 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -43,6 +43,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

        News

        +
        Fri Jul 7 2006:

        Version 0.9.2 +released; changes include: rename project to PulseAudio (see this blog +article for an explanation); increase maximum number of concurrent +connections; fix latency interpolation; add support for reverse endian +sound cards; add support for recording in padsp; reenable CPU +load limiter; other bugfixes

        +
        Fri Jun 2 2006:

        Version 0.9.1 released; changes include: load modules even when libtool .la @@ -123,7 +132,7 @@ href="@PACKAGE_URL@polypaudio-0.1.tar.gz">Version 0.1 released

        Overview

        -

        PulseAudio is a networked sound server for Linux and other +

        PulseAudio is a networked sound server for Linux and other Unix like operating systems and Microsoft Windows. It is intended to be an improved drop-in replacement for the Enlightened Sound @@ -190,7 +199,8 @@ Sound Architecture (ALSA) sinks and sources href="http://0pointer.de/lennart/projects/paman/">PulseAudio Manager. Other GTK GUI tool for PulseAudio are the PulseAudio Volume -Meter and the , PulseAudio Device Chooser and the PulseAudio Volume Control .

        @@ -199,11 +209,7 @@ href="http://0pointer.de/lennart/projects/xmms-pulse/">XMMS, libao (merged in libao SVN) and gstreamer -(merged in gstreamer-plugins CVS), MPlayer (merged in MPlayer CVS) and Xine (merged in Xine CVS). Drivers for -PortAudio will be released -shortly.

        +(merged in gstreamer-plugins CVS).

        PulseAudio was formerly known as Polypaudio.

        @@ -316,19 +322,21 @@ PulseAudio.

        Igor Zubkov for some portability patches

        +

        Jan Schmidt for some latency interpolation love

        +

        Download

        The newest release is always available from @PACKAGE_URL@

        The current release is @PACKAGE_VERSION@

        -

        Get PulseAudio's development sources from the Subversion repository (viewcvs):

        +

        Get PulseAudio's development sources from the Subversion repository (ViewCVS, Trac):

        svn checkout svn://0pointer.de/pulseaudio/trunk pulseaudio

        Community

        -

        If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

        +

        If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

        There is a general discussion mailing list for PulseAudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

        @@ -336,12 +344,12 @@ PulseAudio.

        There's a chance to meet the PulseAudio developers on our IRC channel #pulseaudio on irc.freenode.org.

        -

        There is a Trac based Wiki for PulseAudio available.

        +

        The main project homepage is http://avahi.org/.

        -

        Please report bugs to our Trac ticket system.

        +

        Please report bugs to our Trac ticket system.


        -
        Lennart Poettering <@PACKAGE_BUGREPORT@>, June 2006
        +
        Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2006
        $Id$
        From 81eb4a2d76e145406bbe1f78f7765b6c63521031 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Jul 2006 12:53:19 +0000 Subject: [PATCH 0959/1514] fix mailman URL git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1056 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README.html.in b/doc/README.html.in index 0a49e1ed0..84d69466c 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -338,7 +338,7 @@ PulseAudio.

        If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

        -

        There is a general discussion mailing list for PulseAudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

        +

        There is a general discussion mailing list for PulseAudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

        PulseAudio is being tracked at CIA.

        From 7fe5e5f0204626d8fcfaf62b21cab895b340cce4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Jul 2006 12:59:13 +0000 Subject: [PATCH 0960/1514] replace remaining ML refs to polyp git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1057 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README.html.in b/doc/README.html.in index 84d69466c..9076758e8 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -338,7 +338,7 @@ PulseAudio.

        If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

        -

        There is a general discussion mailing list for PulseAudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

        +

        There is a general discussion mailing list for PulseAudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

        PulseAudio is being tracked at CIA.

        From 9a778bddfe3bb8e5124805456d23bafdf7b8dbec Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Jul 2006 14:36:39 +0000 Subject: [PATCH 0961/1514] s/avahi/pulseuaiod/ git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1058 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/README.html.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/README.html.in b/doc/README.html.in index 9076758e8..4937deb3d 100644 --- a/doc/README.html.in +++ b/doc/README.html.in @@ -344,9 +344,9 @@ PulseAudio.

        There's a chance to meet the PulseAudio developers on our IRC channel #pulseaudio on irc.freenode.org.

        -

        The main project homepage is http://avahi.org/.

        +

        The main project homepage is http://pulseaudio.org/.

        -

        Please report bugs to our Trac ticket system.

        +

        Please report bugs to our Trac ticket system.


        Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2006
        From e16cdb50bd1a38403cd7aac7922461bc23fe918c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Jul 2006 16:05:20 +0000 Subject: [PATCH 0962/1514] remove all docs from tarball since they are now available on pulseaudio.org git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1059 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 18 +- README | 1 + configure.ac | 28 --- doc/FAQ.html.in | 295 ------------------------- doc/Makefile.am | 23 +- doc/README.html.in | 356 ------------------------------- doc/cli.html.in | 220 ------------------- doc/daemon.html.in | 88 -------- doc/modules.html.in | 510 -------------------------------------------- doc/style.css | 27 --- 10 files changed, 3 insertions(+), 1563 deletions(-) create mode 100644 README delete mode 100644 doc/FAQ.html.in delete mode 100644 doc/README.html.in delete mode 100644 doc/cli.html.in delete mode 100644 doc/daemon.html.in delete mode 100644 doc/modules.html.in delete mode 100644 doc/style.css diff --git a/Makefile.am b/Makefile.am index 8a0eaf497..0884476d4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,7 +17,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4 +EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4 README SUBDIRS=libltdl src doc doxygen MAINTAINERCLEANFILES = @@ -41,27 +41,11 @@ pkgconfig_DATA += \ libpulse-mainloop-glib12.pc endif -if USE_LYNX -EXTRA_DIST += README -MAINTAINERCLEANFILES += README -noinst_DATA += README - -README: - rm -f README - $(MAKE) -C doc README - cd $(srcdir) && ln -s doc/README README -endif - homepage: all dist doxygen test -d $$HOME/homepage/private mkdir -p $$HOME/homepage/private/projects/pulseaudio $$HOME/homepage/private/projects/pulseaudio/doxygen cp pulseaudio-@PACKAGE_VERSION@.tar.gz $$HOME/homepage/private/projects/pulseaudio - cp doc/README.html doc/FAQ.html doc/cli.html doc/daemon.html doc/modules.html doc/style.css $$HOME/homepage/private/projects/pulseaudio cp -a doxygen/html/* $$HOME/homepage/private/projects/pulseaudio/doxygen - ln -sf $$HOME/homepage/private/projects/pulseaudio/README.html $$HOME/homepage/private/projects/pulseaudio/index.html - -#distcleancheck: -# @: doxygen: $(MAKE) -C doxygen doxygen diff --git a/README b/README new file mode 100644 index 000000000..005ddf4a2 --- /dev/null +++ b/README @@ -0,0 +1 @@ +For more information see http://pulseaudio.org/ diff --git a/configure.ac b/configure.ac index 3b02df5a8..6b82effdb 100644 --- a/configure.ac +++ b/configure.ac @@ -100,29 +100,6 @@ if test "x$GCC" = "xyes" ; then done fi -# LYNX documentation generation -AC_ARG_ENABLE(lynx, - AC_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation), -[case "${enableval}" in - yes) lynx=yes ;; - no) lynx=no ;; - *) AC_MSG_ERROR(bad value ${enableval} for --disable-lynx) ;; -esac],[lynx=auto]) - -if test x$lynx != xno ; then - AC_CHECK_PROG(have_lynx, lynx, yes, no) - - if test x$have_lynx = xno ; then - if test x$lynx = xyes ; then - AC_MSG_ERROR([*** lynx not found]) - else - AC_MSG_WARN([*** lynx not found, plain text README will not be built ***]) - fi - fi -fi - -AM_CONDITIONAL([USE_LYNX], [test "x$have_lynx" = xyes]) - #### libtool stuff #### AC_LTDL_ENABLE_INSTALL @@ -701,13 +678,8 @@ libpulse-browse.pc libpulse-mainloop-glib.pc libpulse-mainloop-glib12.pc doc/Makefile -doc/README.html -doc/cli.html -doc/daemon.html -doc/modules.html doxygen/Makefile doxygen/doxygen.conf src/pulse/version.h -doc/FAQ.html ]) AC_OUTPUT diff --git a/doc/FAQ.html.in b/doc/FAQ.html.in deleted file mode 100644 index 39b7390ab..000000000 --- a/doc/FAQ.html.in +++ /dev/null @@ -1,295 +0,0 @@ - - - - -PulseAudio: FAQ - - - - - - -

        Frequently Asked Questions

        - -
          -
        1. How does PulseAudio compare with ESOUND/aRts/NAS?

          - -

          PulseAudio is sound daemon similar to ESOUND and NAS, but much more - powerful. aRts is a realtime-synthesizer-cum-sound-server, i.e. it - does much more than PulseAudio. However, I believe that PulseAudio - does what it does much better than any other free sound server.

          -
        2. - -
        3. What about ESOUND compatibility?

          -

          PulseAudio is a drop in replacement for ESOUND. That means: you can - load a esound compatibility module which implements an ESOUND - compatible protocol which allows you to use most of the classic ESOUND - compatible programs (including the command line programs like - esdcat).

          -
        4. - -
        5. Is PulseAudio a GNOME program?

          -

          No, PulseAudio has no dependency on GNOME/GTK/GLIB. All it requires - is a UNIX-like operating system and very few dependency - libraries. However, the accompanying GUI tools are written with - gtkmm, i.e. require both GLIB and GTK.

        6. - -
        7. Can I integrate PulseAudio in my GLIB/GTK/GNOME application?

          -

          Yes! PulseAudio comes with a GLIB main loop adapter. You can embed - both the client library and the daemon (!) into your GLIB based - application.

        8. - -
        9. Can I integrate PulseAudio in my Qt/KDE application?

          -

          Yes! PulseAudio uses a main loop abstraction layer that allows you - to integrate PulseAudio in any program that supports main - loops. Unfortunately there is no adapter for Qt publicly available yet.

        10. - -
        11. I want to write a new driver for PulseAudio, are there any docs?

          -

          Currently, only the client API is documented with doxygen. Read - the source and base your work on a simple module like - module-pipe-sink.

        12. - -
        13. What about compatibility with NAS?

          -

          Is not available (yet?). It is doable, but noone has implemented it yet.

        14. - -
        15. What about compatibility with aRts?

          -

          Is not available. Since aRts is as synthesizer application you'd have to - reimplement very much code for PulseAudio. It should be easy to - implement limited support for libartsc based - applications. Noone has done this yet. It is probably a better idea to - run arts on top of PulseAudio (through a PulseAudio driver - for aRts, which nobody has written yet). Another solution would be to - embed PulseAudio in the aRts process.

        16. - -
        17. I often hear noises when playing back with PulseAudio, what can I do?

          -

          There are to possible solutions: run PulseAudio with argument ---high-priority=1 and make yourself member of the group -realtime, or increase the fragment sizes of the audio - drivers. The former will allow PulseAudio to activate - SCHED_FIFO high priority scheduling (root rights are dropped - immediately after this). Keep in mind that this is a potential security hole!

        18. - -
        19. The pulseaudio executable is installed SUID root by default. Why this? Isn't this a potential security hole?

          - -

          PulseAudio activates SCHED_FIFO scheduling if the user -passes --high-priority=1. This will only succeed when -executed as root, therefore the binary is marked SUID root by -default. Yes, this is a potential security hole. However, PulseAudio -tries its best to minimize the security threat: immediately after -startup PulseAudio drops all capabilities except -CAP_SYS_NICE (At least on systems that support it, like Linux; see man 7 -capabilities for more information). If the calling user is not a -member of the group realtime (which is required to have a GID -< 1000), root rights are dropped immediately. This means, you can -install pulseaudio SUID root, but only a subset of your users (the -members of the group realtime) may make use of realtime -scheduling. Keep in mind that these users might load their own binary -modules into the PulseAudio daemon which may freeze the machine. The -daemon has a minimal protection against CPU hogging (the daemon is -killed after hogging more than 70% CPU for 5 seconds), but this may -be circumvented easily by evildoers.

        20. - -
        21. I want to run PulseAudio only when it is needed, how do I do this?

          - -

          Set autospawn = yes in client.conf. That -configuration file may be found either in /etc/pulse/ or -in ~/.pulse/.

        22. - -
        23. How do I list all PulseAudio modules installed?

          - -

          pulseaudio --dump-modules

          - -

          Add -v for terse usage instructions.

          - -
        24. How do I use PulseAudio over the network?

          - -

          Just set $PULSE_SERVER to the host name of the PulseAudio -server. For authentication you need the same auth cookies on all sides. For -that copy ~./pulse-cookie to all clients that shall -be allowed to connect.

          - -

          Alternatively the authorization cookies can be stored in the X11 server.

        25. - -
        26. Is PulseAudio capable of providing synchronized audio playback over the network for movie players like mplayer?

          - -

          Yes! Unless your network is congested in some way (i.e. transfer latencies vary strongly) it works perfectly. Drop me an email for experimental patches for MPlayer.

          - -
        27. What environment variables does PulseAudio care about?

          - -

          The client honors: PULSE_SINK (default sink to connect to), PULSE_SOURCE (default source to connect to), PULSE_SERVER (default server to connect to, like ESPEAKER), PULSE_BINARY (the binary to start when autospawning a daemon), PULSE_CLIENTCONFIG (path to the client configuration file).

          - -

          The daemon honors: PULSE_SCRIPT (default CLI script file run after startup), PULSE_CONFIG (default daemon configuration file), PULSE_DLPATH (colon separated list of paths where to look for modules)

        28. - - -
        29. I saw that SIGUSR2 provokes loading of the module module-cli-protocol-unix. But how do I make use of that?

          - -

          A brilliant guy named Lennart Poettering once wrote a nifty tool -for that purpose: bidilink. To -connect to a running PulseAudio daemon try using the following commands:

          - -
          killall -USR2 pulseaudio
          -bidilink unix-client:/tmp/pulse-$USER/cli
          - -

          BTW: Someone should package this great tool for Debian!

          - -

          New: There's now a tool pacmd that automates sending SIGUSR2 to the daemon and running a bidilink like tool for you.

          -
        30. - -
        31. How do the PulseAudio libraries decide where to connect to?

          -

          The following rule applies:

          -
            -
          1. If the the application using the library specifies a server to connect to it is used. If the connection fails, the library fails too.
          2. -
          3. If the environment variable PULSE_SERVER is defined the library connects to that server. If the connection fails, the library fails too.
          4. -
          5. If $DISPLAY is set, the library tries to connect to that server and looks for the root window property POYLP_SERVER for the host to connect to. If PULSE_COOKIE is set it is used as authentication cookie.
          6. -
          7. If the client configuration file (~/.pulse/client.conf or /etc/pulse/client.conf) sets the server address, the library connects to that server. If the connection fails, the library fails too.
          8. -
          9. The library tries to connect to the default local UNIX socket for PulseAudio servers. If the connection fails, it proceeds with the next item.
          10. -
          11. The library tries to connect to the default local TCP socket for PulseAudio servers. If the connection fails, it proceeds with the next item.
          12. -
          13. If $DISPLAY is set, the library tries to connect to the default TCP port of that host. If the connection fails, it proceeds with the next item.
          14. -
          15. The connection fails.
          16. -
          -
        32. - -
        33. Why the heck does libpulse link against libX11?

          -

          The PulseAudio client libraries look for some X11 root window -properties for the credentials of the PulseAudio server to access. You -may compile PulseAudio without X11 for disabling this feature.

        34. - -
        35. How can I use PulseAudio as an RTP based N:N multicast -conferencing solution for the LAN?

          After loading all the -necessary audio drivers for recording and playback, just load the RTP -reciever and sender modules with default parameters:

          - -
          -load-module module-rtp-send
          -load-module module-rtp-recv
          -
          - -

          As long as the PulseAudio daemon runs, the microphone data will be -streamed to the network and the data from other hosts is played back -locally. Please note that this may cause quite a lot of traffic. Hence -consider passing rate=8000 format=ulaw channels=1 to the -sender module to save bandwith while still maintaining good quality -for speech transmission.

        36. - -
        37. What is this RTP/SDP/SAP thing all about?

          - -

          RTP is the Realtime Transfer Protocol. It is a well-known -protocol for transferring audio and video data over IP. SDP is the Session -Description Protocol and can be used to describe RTP sessions. SAP -is the Session Announcement Protocol and can be used to -announce RTP sessions that are described with SDP. (Modern SIP based VoIP phones use RTP/SDP for their sessions, too)

          - -

          All three protocols are defined in IETF RFCs (RFC3550, RFC3551, -RFC2327, RFC2327). They can be used in both multicast and unicast -fashions. PulseAudio exclusively uses multicast RTP/SDP/SAP containing audio data.

          - -

          For more information about using these technologies with PulseAudio have a look on the respective module's documentation. - -

        38. How can I use PulseAudio to stream music from my main PC to my LAN with multiple PCs with speakers?

          - -

          On the sender side create an RTP sink:

          - -
          -load-module module-null-sink sink_name=rtp
          -load-module module-rtp-send source=rtp_monitor
          -set-default-sink rtp
          -
          - -

          This will make rtp the default sink, i.e. all applications will write to this virtual RTP device by default.

          - -

          On the client sides just load the reciever module:

          -
          -load-module module-rtp-recv
          -
          - -

          Now you can play your favourite music on the sender side and all clients will output it simultaneously.

          - - -

          BTW: You can have more than one sender machine set up like this. The audio data will be mixed on the client side.

        39. - -
        40. How can I use PulseAudio to share a single LINE-IN/MIC jack on the entire LAN?

          - -

          On the sender side simply load the RTP sender module:

          - -
          -load-module module-rtp-send
          -
          - -

          On the reciever sides, create an RTP source:

          - -
          -load-module module-null-sink sink_name=rtp
          -load-module module-rtp-recv sink=rtp
          -set-default-source rtp_monitor
          -
          - -

          Now the audio data will be available from the default source rtp_monitor.

        41. - -
        42. When sending multicast RTP traffic it is recieved on the entire LAN but not by the sender machine itself!

          - -

          Pass loop=1 to the sender module!

        43. - -
        44. Can I have more than one multicast RTP group?

          - -

          Yes! Simply use a new multicast group address. Use -the destination/sap_address arguments of the RTP -modules to select them. Choose your group addresses from the range -225.0.0.x to make sure the audio data never leaves the LAN.

        45. - - -
        46. Can I use PulseAudio to playback music on two sound cards simultaneously?

          - -

          Yes! Use module-combine for that.

          - -
          -load-module module-oss-mmap device="/dev/dsp" sink_name=output0
          -load-module module-oss-mmap device="/dev/dsp1" sink_name=output1
          -load-module module-combine sink_name=combined master=output0 slaves=output1
          -set-sink-default combined
          -
          - -

          This will combine the two sinks output0 and -output1 into a new sink combined. Every sample -written to the latter will be forwarded to the former two. PulseAudio -will make sure to adjust the sample rate of the slave device in case -it deviates from the master device. You can have more than one slave -sink attached to the combined sink, and hence combine even three and -more sound cards.

        47. - -
        48. Can I use PulseAudio to combine two stereo soundcards into a virtual surround sound card?

          - -

          Yes! You can use use module-combine for that.

          - -
          -load-module module-oss-mmap device="/dev/dsp" sink_name=output0 channel_map=left,right channels=2
          -load-module module-oss-mmap device="/dev/dsp1" sink_name=output1 channel_map=rear-left,rear-right channels=2
          -load-module module-combine sink_name=combined master=output0 slaves=output1 channel_map=left,right,rear-left,rear-right channels=4
          -
          - -

          This is mostly identical to the previous example. However, this -time we manually specify the channel mappings for the sinks to make -sure everything is routed correctly.

          - -

          Please keep in mind that PulseAudio will constantly adjust the -sample rate to compensate for the deviating quartzes of the sound -devices. This is not perfect, however. Deviations in a range of -1/44100s (or 1/48000s depending on the sampling frequency) can not be -compensated. The human ear will decode these deviations as minor -movements (less than 1cm) of the positions of the sound sources -you hear.

          - -
        49. - -
        50. Why did you rename Polypaudio to PulseAudio?

          - -

          Please read this blog story for an explanation.

          - -
        51. - -
        - -
        -
        Lennart Poettering <@PACKAGE_BUGREPORT@>, April 2006
        -
        $Id$
        - diff --git a/doc/Makefile.am b/doc/Makefile.am index a58911add..1e9fe2449 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -16,26 +16,5 @@ # along with PulseAudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -noinst_DATA = README.html cli.html modules.html daemon.html FAQ.html -EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in todo FAQ.html.in - -MAINTAINERCLEANFILES = README.html cli.html modules.html daemon.html FAQ.html -CLEANFILES = - -if USE_LYNX -README: README.html - lynx --dump $^ | sed 's,file://localhost/.*/doc/README.html,README,' > $@ - -noinst_DATA += README -CLEANFILES += README -endif - -tidy: README.html cli.html modules.html daemon.html - tidy -qe < README.html ; true - tidy -qe < cli.html ; true - tidy -qe < daemon.html ; true - tidy -qe < modules.html ; true - tidy -qe < FAQ.html ; true - -.PHONY: tidy +EXTRA_DIST = todo diff --git a/doc/README.html.in b/doc/README.html.in deleted file mode 100644 index 4937deb3d..000000000 --- a/doc/README.html.in +++ /dev/null @@ -1,356 +0,0 @@ - - - - - -PulseAudio @PACKAGE_VERSION@ - - - - -

        PulseAudio @PACKAGE_VERSION@

        - -

        Copyright 2004-2006 Lennart Poettering <@PACKAGE_BUGREPORT@> and Pierre Ossman

        - - - -

        License

        - -

        This program is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version.

        - -

        This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details.

        - -

        You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

        - -

        News

        - -
        Fri Jul 7 2006:

        Version 0.9.2 -released; changes include: rename project to PulseAudio (see this blog -article for an explanation); increase maximum number of concurrent -connections; fix latency interpolation; add support for reverse endian -sound cards; add support for recording in padsp; reenable CPU -load limiter; other bugfixes

        - -
        Fri Jun 2 2006:

        Version 0.9.1 -released; changes include: load modules even when libtool .la -files are missing; generate better ALSA device names from -module-detect; if an ALSA device doesn't support the -requested number of channels or the frequency, accept what ALSA -suggests instead; amd64 portability; drop .sh suffix of -esdcompat.sh; build system fixes; No API or ABI changes were made

        - -
        Fri May 26 2006:

        Version 0.9.0 -released; changes include: new module module-volume-restore; -new OSS API emulation tool padsp; require valid UTF8 strings -everywhere; properly support ALSA channel maps for surround sound; -increase maximum number of channels per stream to 32; add new threaded -main loop API for synchronous programs; introduce real shared object -versioning; a few API additions; many, many bugfixes

        - -
        Fri Apr 28 2006:

        Version 0.8.1 -released; changes include: support for specifying the channel map on -the command lines of paplay and pacat and as -arguments to the driver modules; ALSA hardware mixer compatibility; -fix linking; properly remove PF_UNIX sockets when unloading -protocol modules; fix sample cache; many other fixes

        - -
        Thu Apr 13 2006:

        Version 0.8 released; -changes include: too many to count - consider reading this blog entry for more information; many, many minor fixes.

        - -
        Sun Nov 21 2004:

        Version 0.7 released; -changes include: IPv6 support; PID file support; publish credentials -in X11 root window (module-x11-publish; new tool pacmd; ESOUND backend; new command load-sample-dir-lazy; many, many minor fixes.

        - -
        Thu Oct 28 2004:

        Version 0.6 released; -changes include: TCP wrappers support; don't load the complete sound -file into memory when playing back using pa_play_file(); -autoload API change; don't load all sound files as FLOAT32; shorten -default buffers; client-side latency interpolation; add new user -volume metrics; add module-tunnel, module-null-sink, -module-match and new tool paplay; new API version -macros; many client API improvements; correctly lock cookie file -generation; correctly lock daemon autospawning; print daemon layout to -STDERR on SIGHUP; new options for pacat: allow sample type specification.

        - -
        Mon Sep 24 2004:

        Version 0.5.1 released; -changes include: improve esound protocol compatibility; fix -autospawning via libesd; make use of POSIX capabilities; -allow SCHED_FIFO scheduling only for users in group -realtime; minor build system fix.

        - -
        Mon Sep 20 2004:

        Version 0.5 released; -changes include: extensive API improvements, new module -module-combine for combining multiple sound cards into one, -gcc 2.95 compatibility, configuration files, add "lazy" samples, -support for source and network latency measurements, add -module-pipe-source, many other fixes and improvements.

        - -
        Wed Sep 8 2004:

        Version 0.4 released; -changes include: daemon auto spawning, support for SCHED_FIFO scheduling, three new modules, proper logging, CPU load watchdog, many fixes.

        - -
        Fri Aug 27 2004:

        Version 0.3 released; -changes include: support for both glib 2.0 and glib 1.2, future cancellation, API updates, many fixes, relicense client library to LGPL.

        - -
        Fri Aug 20 2004:

        Version 0.2 released; -changes include: added sample cache, introspection API, client API -documentation, module autoloading, glib support, a module for intercepting X11 bell events, and much more.

        - -
        Sat Jul 17 2004:

        Version 0.1 released

        - -

        Overview

        - -

        PulseAudio is a networked sound server for Linux and other -Unix like operating systems and Microsoft Windows. It is intended to be an improved drop-in -replacement for the Enlightened Sound -Daemon (ESOUND). In addition to the features ESOUND provides -PulseAudio has:

        - -
          -
        • Extensible plugin architecture (by loading dynamic loadable modules with dlopen())
        • -
        • Support for more than one sink/source
        • -
        • Better low latency behaviour
        • -
        • Embedabble into other software (the core is available as C library)
        • -
        • Completely asynchronous C API
        • -
        • Simple command line interface for reconfiguring the daemon while running
        • -
        • Flexible, implicit sample type conversion and resampling
        • -
        • "Zero-Copy" architecture
        • -
        • Module autoloading
        • -
        • Very accurate latency measurement for playback and recording.
        • -
        • May be used to combine multiple sound cards to one (with sample rate adjustment)
        • -
        • Client side latency interpolation
        • -
        • Ability to fully synchronize multiple playback streams
        • -
        - -

        Both the core and the client API are completely asynchronous making -use of a simple main loop abstraction layer. This allows easy -integration with asynchronous applications using the -glib/gtk mainloop. Since the asynchronous API -available through libpulse is quite difficult to use there is -a simplified synchronous API wrapper libpulse-simple -available. A simple main loop implementation is available as well.

        - -

        The following modules are currently available:

        - -
          -
        • module-oss: driver for Open Sound System (OSS) audio sinks and sources.
        • -
        • module-oss-mmap: same as above, but uses mmap() access to the audio buffer. Not as compatible bot more accurate in latency calculations
        • -
        • module-alsa-sink, module-alsa-source: drivers for Advanced Linux -Sound Architecture (ALSA) sinks and sources
        • -
        • module-solaris: drivers for Solaris audio sinks and sources
        • -
        • module-waveout: drivers for Microsoft Windows audio sinks and sources
        • -
        • module-pipe-sink, module-pipe-source: demonstration module providing UNIX FIFOs backed sinks/sources
        • -
        • module-combine: combine multiple sinks into one, adjusting the sample rate if the their clocks deviate.
        • -
        • module-sine: a sine generate sink input.
        • -
        • module-x11-bell: play a sample from the sample cache on every X11 bell event.
        • -
        • module-x11-publish: store PulseAudio credentials in the X11 root window.
        • -
        • module-esound-protocol-tcp, module-esound-protocol-unix: ESOUND compatibility modules (for TCP/IP resp. UNIX domain sockets)
        • -
        • module-native-protocol-tcp, module-native-protocol-unix: Native PulseAudio protocol (for TCP/IP resp. UNIX domain sockets)
        • -
        • module-simple-protocol-tcp, module-simple-protocol-unix: Simplistic protocol for playback/capture for usage with tools like netcat (for TCP/IP resp. UNIX domain sockets)
        • -
        • module-cli-protocol-tcp, module-cli-protocol-unix, module-cli: Expose PulseAudio's internals whith a simple command line interface. (for TCP/IP resp. UNIX domain sockets resp. STDIN/STDOUT)
        • -
        • module-http-protocol-tcp: Spawns a small HTTP server which can be used to introspect the PulseAudio server with a web browser.
        • -
        • module-tunnel-sink, module-tunnel-source: make sinks/sources from other hosts available locally.
        • -
        • module-match: adjust volume automatically for newly created playback streams based on a regular expression matching table.
        • -
        • module-volume-restore: much like module-match, but create rules fully automatically based on the client name.
        • -
        • module-null-sink: a clocked sink similar to /dev/null.
        • -
        • module-esound-sink: a sink for forwarding audio data to an ESOUND server.
        • -
        • module-detect: a module which automatically detects what sound hardware is available locally and which loads the required driver modules.
        • -
        • module-lirc: a module to control the volume of a sink with infrared remote controls supported by LIRC.
        • -
        • module-mmkbd-evdev: a module to control the volume of a sink with the special volume keys of a multimeda keyboard.
        • -
        • module-zeroconf-publish: a module to publish local sources/sinks using mDNS zeroconf.
        • -
        • module-rtp-send, module-rtp-recv: modules to implement RTP/SAP/SDP based audio streaming.
        • -
        • module-jack-sink, module-jack-source: connect to a JACK Audio Connection Kit server. (A sound server for professional audio production)
        • -
        - -

        A GTK GUI manager application for PulseAudio is the PulseAudio -Manager. Other GTK GUI tool for PulseAudio are the PulseAudio Volume -Meter, PulseAudio Device Chooser and the PulseAudio Volume -Control .

        - -

        There are output plugins for XMMS, libao -(merged in libao SVN) and gstreamer -(merged in gstreamer-plugins CVS).

        - -

        PulseAudio was formerly known as Polypaudio.

        - -

        Current Status

        - -

        Version @PACKAGE_VERSION@ is quite usable. It matches and supersedes ESOUND's feature set in nearly all areas.

        - -

        Documentation

        - -

        There is some preliminary documentation available: modules.html, cli.html, daemon.html and FAQ.html.

        - -

        There is a Trac based Wiki for PulseAudio available.

        - -

        First Steps

        - -

        Simply start the PulseAudio daemon with the argument -nC

        - -
        pulseaudio -nC
        - -

        This will present you a screen like this:

        - -
        Welcome to PulseAudio! Use "help" for usage information.
        ->>> 
        - -

        Now you can issue CLI commands as described in cli.html. Another way to start -PulseAudio is by specifying a configuration script like that one included in the distribution on the -command line :

        - -
        pulseaudio -nF pulseaudio.pa
        - -

        This will load some drivers and protocols automatically.

        - -

        The best idea is to configure your daemon in /etc/pulse/daemon.conf and /etc/pulse/default.pa and to run PulseAudio without any arguments.

        - -

        Beware! Unless you pass the option --sysconfdir=/etc to -configure, the directory /etc/pulse/ is really -/usr/local/etc/pulse/.

        - -

        Developing PulseAudio Clients

        - -

        You may browse the Doxygen generated programing -documentation for the client API. (Run make doxygen to generate this documentation from the source tree)

        - -

        Developing PulseAudio Modules

        - -

        There are several reasons for writing loadable modules for PulseAudio:

        - -
          -
        • Extended device driver support
        • -
        • Protocol support beyond ESOUND's protocol and the native protocol. (such as NAS or a subset of aRts)
        • -
        • New programming interfaces such as XMLRPC or DBUS for controlling the daemon.
        • -
        • Hooking audio event sources directly into PulseAudio (similar to module-x11-bell)
        • -
        • For low latency applications such as VOIP: load the VOIP core directly into PulseAudio and have a slim GUI frontend to control it.
        • -
        - -

        There is currently no documentation how to write loadable modules -for PulseAudio. Read the source, Luke! If you are interested in -writing new modules feel free to contact the author in case you have any -questions.

        - -

        Requirements

        - -

        Currently, PulseAudio> is tested on Linux, FreeBSD, Solaris and Microsoft Windows. It requires an OSS, ALSA, Win32 or Solaris compatible soundcard.

        - -

        PulseAudio was developed and tested on Debian GNU/Linux -"testing" from November 2004, it should work on most other Linux -distributions (and maybe Unix versions) since it uses GNU autoconf and -GNU libtool for source code configuration and shared library -management.

        - -

        Pulseaudio needs Secret Rabbit Code (aka -libsamplerate), libsndfile, liboil.

        - -

        Optionally it can make use of libwrap, alsa-lib, libasyncns, -lirc, HOWL (or preferably the compatibility layer included in its superior replacement Avahi) and GLIB. (The latter is required for -building the GLIB main loop integration module only.)

        - -

        Installation

        - -

        As this package is made with the GNU autotools you should run -./configure inside the distribution directory for configuring -the source tree. After that you should run make for -compilation and make install (as root) for installation of -PulseAudio.

        - -

        Acknowledgements

        - -

        Eric B. Mitchell for writing ESOUND

        - -

        Jeff Waugh for creating Ubuntu packages (and hopefully soon Debian)

        - -

        Miguel Freitas for writing a PulseAudio driver for Xine

        - -

        Joe Marcus Clarke for porting PulseAudio to FreeBSD

        - -

        Cendio AB for paying for Pierre's work on PulseAudio

        - -

        Sebastien ESTIENNE for testing

        - -

        Igor Zubkov for some portability patches

        - -

        Jan Schmidt for some latency interpolation love

        - -

        Download

        - -

        The newest release is always available from @PACKAGE_URL@

        - -

        The current release is @PACKAGE_VERSION@

        - -

        Get PulseAudio's development sources from the Subversion repository (ViewCVS, Trac):

        - -
        svn checkout svn://0pointer.de/pulseaudio/trunk pulseaudio
        - -

        Community

        - -

        If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.

        - -

        There is a general discussion mailing list for PulseAudio available. In addition, you can subscribe to SVN changes and Trac Tickets.

        - -

        PulseAudio is being tracked at CIA.

        - -

        There's a chance to meet the PulseAudio developers on our IRC channel #pulseaudio on irc.freenode.org.

        - -

        The main project homepage is http://pulseaudio.org/.

        - -

        Please report bugs to our Trac ticket system.

        - -
        -
        Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2006
        -
        $Id$
        - - - diff --git a/doc/cli.html.in b/doc/cli.html.in deleted file mode 100644 index 3a256732d..000000000 --- a/doc/cli.html.in +++ /dev/null @@ -1,220 +0,0 @@ - - - - -PulseAudio: Simple Command Line Language - - - - -

        Simple Command Line Language

        - -

        PulseAudio provides a simple command line language used by -configuration scripts as well as the modules module-cli -and module-cli-protocol-{unix,tcp}. Empty lines and lines -beginning with a hashmark (#) are silently ignored. Several -commands are supported:

        - -

        Miscellaneous Commands

        - -

        help

        - -

        Show a quick help on the commands available.

        - -

        exit

        - -

        Terminate the daemon. If you want to terminate a CLI connection -("log out") you might want to use C-d.

        - -

        Status Commands

        - -

        list-modules

        - -

        Show all currently loaded modules with their arguments.

        - -

        list-sinks/list-sources

        - -

        Show all currently registered sinks (resp. sources).

        - -

        list-clients

        - -

        Show all currently active clients.

        - -

        list-sink-inputs/list-sink-outputs

        - -

        Show all currently active inputs to sinks (resp. outputs of sources).

        - -

        stat

        - -

        Show some simple statistics about the allocated memory blocks and -the space used by them.

        - -

        info

        - -

        A combination of all status commands described above. ls -and list are synonyms for info.

        - -

        Module Management

        - -

        load-module

        - -

        Load a module specified by its name and arguments. For most modules -it is OK to be loaded more than once.

        - -

        unload-module

        - -

        Unload a module specified by its index in the module list as -returned by modules.

        - -

        Configuration Commands

        - -

        set-sink-volume/set-source-volume

        - -

        Set the volume of the specified sink or source. You may specify the sink/source either -by its index in the sink/source list or by its name. The volume should be an -integer value greater or equal than 0 (= muted). Volume 65536 -(0x10000) is normal volume, values greater than this amplify -the audio signal (with clipping).

        - -

        set-sink-mute/set-source-mute

        - -

        Mute or unmute the specified sink our source. You may specify the -sink/source either by its index or by its name. The mute value is -either 0 or 1.

        - -

        set-sink-input-volume

        - -

        Set the volume of a sink input specified by its index the the sink -input list. The same volume rules apply as with sink_volume.

        - -

        set-default-sink/set-default-source

        - -

        Make a sink (resp. source) the default. You may specify the sink -(resp. ssource) by its index in the sink (resp. source) list or by its -name.

        - -

        Sample Cache

        - -

        list-samples

        - -

        Lists the contents of the sample cache.

        - -

        play-sample

        - -

        Play a sample cache entry to a sink. Expects the sample name and the sink name as arguments.

        - -

        remove-sample

        - -

        Remove an entry from the sample cache. Expects the sample name as argument.

        - -

        load-sample

        - -

        Load an audio file to the sample cache. Expects the file name to load and the desired sample name as arguments.

        - -

        load-sample-lazy

        - -

        Create a new entry in the sample cache, but don't load the sample -immediately. The sample is loaded only when it is first used. After a -certain idle time it is freed again. Expects the the desired sample -name and file name to load as arguments.

        - -

        load-sample-dir-lazy

        - -

        Load all entries in the specified directory into the sample cache -as lazy entries. A shell globbing expression (e.g. *.wav) may -be appended to the path of the directory to add.

        - -

        Module Autoloading

        - -

        list-autoload

        - -

        Lists all currently defined autoloading entries.

        - -

        add-autoload-sink/add-autoload-source

        - -

        Adds an autoloading entry for a sink (resp. source). Expects the sink name (resp. source name), the module name and the module arguments as arguments.

        - -

        remove-autoload-sink/remove-autoload-source

        - -

        Remove an autoloading entry. Expects the sink name (resp. source name) as argument.

        - -

        Miscellaneous Commands

        - -

        play-file

        - -

        Play an audio file to a sink. Expects the file name and the sink name as argumens.

        - -

        dump

        - -

        Dump the daemon's current configuration in CLI commands.

        - -

        Killing Clients/Streams

        - -

        kill-client

        - -

        Remove a client forcibly from the server. There is no protection that -the client reconnects immediately.

        - -

        kill-sink-input/kill-source-output

        - -

        Remove a sink input (resp. source output) forcibly from the -server. This will not remove the owning client or any other streams -opened by the client from the server.

        - -

        Meta Commands

        - -

        In addition the the commands described above there a few meta -directives supported by the command line interpreter:

        - -

        .include

        - -

        Executes the commands from the specified script file.

        - -

        .fail/.nofail

        - -

        Enable (resp. disable) that following failing commands will cancel -the execution of the current script file. This is a ignored when used -on the interactive command line.

        - -

        .verbose/.noverbose

        -

        Enable (resp. disable) extra verbosity.

        - -

        Example Configuration Script

        - -

        Mark the following script as executable (chmod +x) and run it for a sensible PulseAudio configuration.

        - -
        -#!/usr/bin/polaudio -nF
        -
        -# Create autoload entries for the device drivers
        -add-autoload-sink output module-alsa-sink device=plughw:0,0 rate=48000 sink_name=output
        -add-autoload-sink output2 module-oss device=/dev/dsp1 record=0 sink_name=output2
        -add-autoload-sink combined module-combine master=output slaves=output2 sink_name=combined
        -
        -add-autoload-source input module-alsa-source device=hw:1,0 source_name=input
        -
        -# Load several protocols
        -load-module module-esound-protocol-unix
        -load-module module-simple-protocol-tcp
        -load-module module-native-protocol-unix
        -load-module module-cli-protocol-unix
        -
        -# Make some devices default
        -set-default-sink combined
        -set-default-source input
        -
        -# Don't fail if the audio files referred to below don't exist
        -.nofail
        -
        -# Load an audio to the sample cache for usage with module-x11-bell
        -load-sample-lazy  /usr/share/sounds/KDE_Notify.wav x11-bell
        -load-module module-x11-bell sample=x11-bell
        -
        -# Play a welcome sound
        -play-file /usr/share/sounds/startup3.wav combined
        -
        - -
        -
        Lennart Poettering <@PACKAGE_BUGREPORT@>, June 2006
        -
        $Id$
        - diff --git a/doc/daemon.html.in b/doc/daemon.html.in deleted file mode 100644 index d90caa2a8..000000000 --- a/doc/daemon.html.in +++ /dev/null @@ -1,88 +0,0 @@ - - - - -PulseAudio: Daemon - - - - -

        Daemon

        - -

        Command Line Arguments

        - -The PulseAudio daemon accepts several command line arguments: - -
        -COMMANDS:
        -  -h, --help                            Show this help
        -      --version                         Show version
        -      --dump-conf                       Dump default configuration
        -      --dump-modules                    Dump list of available modules
        -  -k  --kill                            Kill a running daemon
        -      --check                           Check for a running daemon
        -
        -OPTIONS:
        -  -D, --daemonize[=BOOL]                Daemonize after startup
        -      --fail[=BOOL]                     Quit when startup fails
        -      --verbose[=BOOL]                  Be slightly more verbose
        -      --high-priority[=BOOL]            Try to set high process priority
        -                                        (only available as root)
        -      --disallow-module-loading[=BOOL]  Disallow module loading after startup
        -      --exit-idle-time=SECS             Terminate the daemon when idle and this
        -                                        time passed
        -      --module-idle-time=SECS           Unload autoloaded modules when idle and
        -                                        this time passed
        -      --scache-idle-time=SECS           Unload autoloaded samples when idle and
        -                                        this time passed
        -      --log-target={auto,syslog,stderr} Specify the log target
        -  -p, --dl-search-path=PATH             Set the search path for dynamic shared
        -                                        objects (plugins)
        -      --resample-method=[METHOD]        Use the specified resampling method
        -                                        (one of src-sinc-medium-quality,
        -                                        src-sinc-best-quality,src-sinc-fastest
        -                                        src-zero-order-hold,src-linear,trivial)
        -      --use-pid-file[=BOOL]             Create a PID file
        -
        -STARTUP SCRIPT:
        -  -L, --load="MODULE ARGUMENTS"         Load the specified plugin module with
        -                                        the specified argument
        -  -F, --file=FILENAME                   Run the specified script
        -  -C                                    Open a command line on the running TTY
        -                                        after startup
        -
        -  -n                                    Don't load default script file
        -
        - -

        Example

        - -

        It is a good idea to run the daemon like this:

        - -
        pulseaudio -D
        - -

        This will run /etc/pulse/default.pa after startup. This should be a script written in the CLI language described in cli.html.

        - -

        Signals

        - -

        The following signals are trapped specially:

        - -

        SIGINT

        - -

        The daemon is shut down cleanly.

        - -

        SIGUSR1

        - -

        The daemon tries to load the module module-cli, effectively providing a command line interface on the calling TTY.

        - -

        SIGUSR2

        - -

        The daemon tries to load the module module-cli-protocol-unix, effectively providing a command line interface on a special UNIX domain socket.

        - -

        SIGHUP

        - -

        The daemon logs the current server layout.

        - -
        -
        Lennart Poettering <@PACKAGE_BUGREPORT@>, June 2006
        -
        $Id$
        - diff --git a/doc/modules.html.in b/doc/modules.html.in deleted file mode 100644 index 7f12d9a94..000000000 --- a/doc/modules.html.in +++ /dev/null @@ -1,510 +0,0 @@ - - - - -PulseAudio: Loadable Modules - - - - - -

        Loadable Modules

        - -

        The following loadable modules are provided with the PulseAudio distribution:

        - -

        Device Drivers

        - -

        All device driver modules support the following parameters:

        - - - - - -
        format=The sample format (one of u8, s16, s16le, s16le, float32, float32be, float32le, alaw, ulaw) (defaults to s16)
        rate=The sample rate (defaults to 44100)
        channels=Audio channels (defaults to 2)
        sink_name=, source_name=Name for the sink (resp. source)
        channel_map=Channel map. A list of -comma-seperated channel names. The currently defined channel names -are: left, right, mono, center, -front-left, front-right, front-center, -rear-center, rear-left, rear-right, -lfe, subwoofer, front-left-of-center, -front-right-of-center, side-left, -side-right, aux0, aux1 to aux15, -top-center, top-front-left, -top-front-right, top-front-center, -top-rear-left, top-rear-right, -top-rear-center, (Default depends on the number of channels -and the driver)
        - -

        module-pipe-sink

        - -

        Provides a simple test sink that writes the audio data to a FIFO -special file in the file system. The sink name defaults to pipe_output.

        - -

        The following option is supported:

        - - - -
        file=The name of the FIFO special file to use. (defaults to: /tmp/music.output)
        - -

        module-pipe-source

        - -

        Provides a simple test source that reads the audio data from a FIFO -special file in the file system. The source name defaults to pipe_input.

        - -

        The following option is supported:

        - - - -
        file=The name of the FIFO special file to use. (defaults to: /tmp/music.input)
        - - -

        module-null-sink

        - -

        Provides a simple null sink. All data written to this sink is silently dropped. This sink is clocked using the system time.

        - -

        This module doesn't support any special parameters

        - - - -

        module-alsa-sink

        - -

        Provides a playback sink for devices supported by the Advanced Linux -Sound Architecture (ALSA). The sink name defaults to alsa_output.

        - -

        In addition to the general device driver options described above this module supports:

        - - - - - -
        device=The ALSA device to use. (defaults to "plughw:0,0")
        fragments=The desired fragments when opening the device. (defaults to 12)
        fragment_size=The desired fragment size in bytes when opening the device (defaults to 1024)
        - -

        module-alsa-source

        - -

        Provides a recording source for devices supported by the Advanced -Linux Sound Architecture (ALSA). The source name defaults to alsa_input.

        - -

        This module supports device=, fragments= and fragment_size= arguments the same way as module-alsa-sink.

        - - - -

        module-oss

        - -

        Provides both a sink and a source for playback, resp. recording on -Open Sound System (OSS) compatible devices.

        - -

        This module supports device= (which defaults to /dev/dsp), fragments= and fragment_size= arguments the same way as module-alsa-sink.

        - -

        In addition this module supports the following options:

        - - - - -
        record=Accepts a binary numerical value for enabling (resp. disabling) the recording on this device. (defaults: to 1)
        playback=Accepts a binary numerical value for enabling (resp. disabling) the playback on this device. (defaults: to 1)
        - -

        The sink name (resp. source name) defaults to oss_output (resp. oss_input).

        - -

        module-oss-mmap

        - -

        Similar to module-oss but uses memory mapped -(mmap()) access to the input/output buffers of the audio -device. This provides better latency behaviour but is not as -compatible as module-oss.

        - -

        This module accepts exactly the same arguments as module-oss.

        - -

        module-solaris

        - -

        Provides a sink and source for the Solaris audio device.

        - -

        In addition to the general device driver options described above this module supports:

        - - - - - -
        record=Accepts a binary numerical value for enabling (resp. disabling) the recording on this device. (defaults: to 1)
        playback=Accepts a binary numerical value for enabling (resp. disabling) the playback on this device. (defaults: to 1)
        buffer_size=Record buffer size
        - -

        module-waveout

        - -

        Provides a sink and source for the Win32 audio device.

        - -

        This module supports all arguments thet module-oss supports except device=.

        - - -

        module-combine

        - -

        This combines two or more sinks into one. A new virtual sink is -allocated. All data written to it is forwarded to all connected -sinks. In aequidistant intervals the sample rates of the output sinks -is recalculated: i.e. even when the sinks' crystals deviate (which is -normally the case) output appears synchronously to the human ear. The -resampling required for this may be very CPU intensive.

        - - - - - - -
        sink_name=The name for the combined sink. (defaults to combined)
        master=The name of the first sink to link into the combined think. The sample rate/type is taken from this sink.
        slaves=Name of additional sinks to link into the combined think, seperated by commas.
        adjust_time=Time in seconds when to readjust the sample rate of all sinks. (defaults to 20)
        resample_method=Resampling algorithm to -use. See libsamplerate's documentation for more -information. Use one of sinc-best-quality, -sinc-medium-quality, sinc-fastest, -zero-order-hold, linear. If the default happens to -be to slow on your machine try using zero-order-hold. This -will decrease output quality however. (defaults to -sinc-fastest)
        - -

        module-tunnel-{sink,source}

        - -

        Tunnel a remote sink/source to a local "ghost" -sink/source. Requires a running PulseAudio daemon on the remote server -with module-native-protocol-tcp loaded. It's probably a -better idea to connect to the remote sink/source directly since some -buffer control is lost through this tunneling.

        - - - - - - -
        server=The server to connect to
        source=The source on the remote server. Only available for module-tunnel-source.
        sink=The sink on the remote server. Only available for module-tunnel-sink.
        cookie=The authentication cookie file to use.
        - -

        module-esound-sink

        - -

        Create a playback sink using an ESOUND server as backend. Whenever you can, try to omit this -module since it has many disadvantages including bad latency -and even worse latency measurement.

        - - - - -
        server=The server to connect to
        cookie=The authentication cookie file to use.
        - -

        Protocols

        - - - -

        module-cli

        - -

        Provides the user with a simple command line interface on the -controlling TTY of the daemon. This module may not be loaded more than -once.

        - -

        For an explanation of the simple command line language used by this -module see cli.html. - - - -
        exit_on_eof=Accepts a binary numerical argument specifying whether the daemon shuld exit after an EOF was recieved from STDIN (default: 0)
        - - - - - -

        module-cli-protocol-{unix,tcp}

        - -

        An implemenation of a simple command line based protocol for -controlling the PulseAudio daemon. If loaded, the user may -connect with tools like netcat, telnet or -bidilink to the listening sockets and execute commands the -same way as with module-cli.

        - -

        Beware! Users are not authenticated when connecting to this -service.

        - -

        This module exists in two versions: with the suffix -unix -the service will listen on an UNIX domain socket in the local file -system. With the suffix -tcp it will listen on a network -transparent TCP/IP socket. (Both IPv6 and IPv4 - if available)

        - -

        This module supports the following options:

        - - - - - - -
        port=(only for -tcp) The port number to listen on (defaults to 4712)
        loopback=(only for -tcp) Accepts -a numerical binary value. If 1 the socket is bound to the loopback -device, i.e. not publicly accessible. (defaults to 1)
        listen=(only for -tcp) The IP address to listen on. If specified, supersedes the value specified in loopback=
        socket=(only for -unix) The UNIX socket name (defaults to /tmp/pulse/cli)
        - -

        module-simple-protocol-{unix,tcp}

        - -

        An implementation of a simple protocol which allows playback by using -simple tools like netcat. Just connect to the listening -socket of this module and write the audio data to it, or read it from -it for playback, resp. recording.

        - -

        Beware! Users are not authenticated when connecting to this -service.

        - -

        See module-cli-protocol-{unix,tcp} for more information -about the two possible suffixes of this module.

        - -

        In addition to the options supported by module-cli-protocol-*, this module supports:

        - - - - - -
        rate=, format=, channels=Sample format for streams connecting to this service.
        playback=, record=Enable/disable playback/recording
        sink=, source=Specify the sink/source this service connects to
        - -

        module-esound-protocol-{unix,tcp}

        - -

        An implemenation of a protocol compatible with the Enlightened Sound -Daemon (ESOUND, esd). When you load this module you may -access the PulseAudio daemon with tools like esdcat, -esdrec or even esdctl. Many applications, such as -XMMS, include support for this protocol.

        - -

        See module-cli-protocol-{unix,tcp} for more information -about the two possible suffixes of this module.

        - -

        In addition to the options supported by module-cli-protocol-*, this module supports:

        - - - - - -
        sink=, source=Specify the sink/source this service connects to
        auth-anonymous=If set to 1 no authentication is required to connect to the service
        cookie=Name of the cookie file for authentication purposes
        - -

        This implementation misses some features the original ESOUND has: e.g. there is no sample cache yet. However: XMMS works fine.

        - -

        module-native-protocol-{unix,tcp}

        - -

        The native protocol of PulseAudio.

        - -

        See module-cli-protocol-{unix,tcp} for more information -about the two possible suffixes of this module.

        - -

        In addition to the options supported by module-cli-protocol-*, this module supports:

        - - - - - -
        auth-anonymous=If set to 1 no authentication is required to connect to the service
        auth-group=(only for -unix): members of the specified unix group may access the server without further auhentication.
        cookie=Name of the cookie file for authentication purposes
        - -

        module-native-protocol-fd

        - -

        This is used internally when auto spawning a new daemon. Don't use it directly.

        - -

        module-http-protocol-tcp

        - -

        A proof-of-concept HTTP module, which can be used to introspect -the current status of the PulseAudio daemon using HTTP. Just load this -module and point your browser to http://localhost:4714/. This module takes the same arguments -as module-cli-protocol-tcp.

        - -

        X Window System

        - -

        module-x11-bell

        - -

        Intercepts X11 bell events and plays a sample from the sample cache on each occurence.

        - - - - - -
        display=X11 display to connect to. If ommited defaults to the value of $DISPLAY
        sample=The sample to play. If ommited defaults to x11-bell.
        sink=Name of the sink to play the sample on. If ommited defaults to the default sink.
        - -

        module-x11-publish

        - -

        Publishes the access credentials to the PulseAudio server in the -X11 root window. The following properties are used: -PULSE_SERVER, POYLP_SINK, PULSE_SOURCE, -PULSE_COOKIE. This is very useful when using SSH or any other -remote login tool for logging into other machines and getting audio -playback to your local speakers. The PulseAudio client libraries make -use of this data automatically. Instead of using this module you may -use the tool pax11publish which may be used to access, modify -and import credential data from/to the X11 display.

        - - - - - -
        display=X11 display to connect to. If ommited defaults to the value of $DISPLAY
        sink=Name of the default sink. If ommited this property isn't stored in the X11 display.
        source=Name of the default source. If ommited this property isn't stored in the X11 display.
        cookie=Name of the cookie file of the -cookie to store in the X11 display. If ommited the cookie of an -already loaded protocol module is used.
        - -

        Volume Control

        - -

        module-mmkbd-evdev

        - -

        Adjust the volume of a sink when the special multimedia buttons of modern keyboards are pressed.

        - - - - -
        device=Linux input device ("evdev", defaults to /dev/input/event0)
        sink=The sink to control
        - -

        module-lirc

        - -

        Adjust the volume of a sink when the volume buttons of an infrared remote control are pressed (through LIRC).

        - - - - - -
        config=The LIRC configuration file
        appname=The application name to pass to LIRC (defaults to pulseaudio)
        sink=The sink to control
        - - -

        RTP/SDP/SAP Transport

        - -

        PulseAudio can stream audio data to an IP multicast group via the -standard protocols RTP, -SAP -and SDP -(RFC3550, RFC3551, RFC2327, RFC2327). This can be used for multiple -different purposes: for sharing a single microphone on multiple -computers on the local LAN, for streaming music from a single -controlling PC to multiple PCs with speakers or to implement a simple -"always-on" teleconferencing solution.

        - -

        The current implementation is designed to be used exlusively in -local area networks, though Internet multicasting is theoretically -supported. Only uncompressed audio is supported, hence you won't be -able to multicast more than a few streams at the same time over a -standard LAN.

        - -

        PulseAudio implements both a sender and a reciever for RTP -traffic. The sender announces itself via SAP/SDP on the same multicast -group as it sends the RTP data to. The reciever picks up the SAP/SDP -announcements and creates a playback stream for each -session. Alternatively you can use any RTP capable client to -recieve and play back the RTP data (such as mplayer).

        - -

        module-rtp-send

        - -

        This is the sender side of the RTP/SDP/SAP implementation. It reads -audio data from an existing source and forwards it to the network -encapsulated in RTP. In addition it sends SAP packets with an SDP -session description.

        - -

        In combination with the monitor source of module-null-sink -you can use this module to create an RTP sink.

        - - - - - - - - -
        source=The source to read the audio data from. If ommited defaults to the default source.
        format=, rate=, channels=Sample format to use, defaults to the source's.
        destination=Destination multicast group for both RTP and SAP packets, defaults to 224.0.0.56
        port=Destination port number of the RTP -traffic. If ommited defaults to a randomly chosen even port -number. Please keep in mind that the RFC suggests to use only even -port numbers for RTP traffic.
        mtu=Maximum payload size for RTP packets. If ommited defaults to 1280
        loop=Takes a boolean value, specifying whether locally generated RTP traffic should be looped back to the local host. Disabled by default.
        - -

        module-rtp-recv

        - -

        This is the reciever side of the RTP/SDP/SAP implementation. It -picks up SAP session announcements and creates an RTP playback stream -for each.

        - -

        In combination with module-null-sink you can use this -module to create an RTP source.

        - - - - -
        sink=The sink to connect to. If ommited defaults to the default sink.
        sap_address=The multicast group to join for SAP announcements, defaults to 224.0.0.56.
        - -

        JACK Connectivity

        - -

        PulseAudio can be hooked up to a JACK Audio Connection Kit server which is a specialized sound server used for professional audio production on Unix/Linux. Both a -PulseAudio sink and a source are available. For each channel a port is -created in the JACK server.

        - -

        module-jack-sink

        - -

        This module implements a PulseAudio sink that connects to JACK and registers as many output ports as requested.

        - - - - - - - -
        sink_name=The name for the PulseAudio sink. If ommited defaults to jack_out.
        server_name=The JACK server to connect to. If ommited defaults to the default server.
        client_name=The client name to tell the JACK server. If ommited defaults to PulseAudio.
        channels=Number of channels to register. If ommited defaults to the number of physical playback ports of the JACK server.
        connect=Takes a boolean value. If enabled (the default) PulseAudio will try to connect its ports to the physicial playback ports of the JACK server
        - -

        module-jack-source

        - -

        This module implements a PulseAudio source that connects to JACK -and registers as many input ports as requested. Takes the same -arguments as module-jack-sink, except for sink_name -which is replaced by source_name (with a default of jack_in) for obvious reasons.

        - -

        Miscellaneous

        - -

        module-sine

        - -

        Creates a sink input and generates a sine waveform stream.

        - - - - -
        sink=The sink to connect to. If ommited defaults to the default sink.
        frequency=The frequency to generate in Hertz. Defaults to 440.
        - -

        module-esound-compat-spawnfd

        - -

        This is a compatibility module for libesd based autospawning of PulseAudio. Don't use it directly.

        - -

        module-esound-compat-spawnpid

        - -

        This is a compatibility module for libesd based autospawning of PulseAudio. Don't use it directly.

        - -

        module-match

        - -

        Adjust the volume of a playback stream automatically based on its name.

        - - - -
        table=The regular expression matching table file to use (defaults to ~/.pulse/match.table)
        - -

        The table file should contain a regexp and volume on each line, seperated by spaces. An example:

        - -
        -^sample: 32000
        -
        - -

        The volumes of all streams with titles starting with sample: are automatically set to 32000. (FYI: All sample cache streams start with sample:)

        - -

        module-volume-restore

        - -

        Adjust the volume of a playback stream automatically based on its name.

        - - - -
        table=The table file to use (defaults to ~/.pulse/volume.table)
        - -

        In contrast to module-match this module needs no explicit -configuration. Instead the volumes are saved and restored in a fully -automatical fashion depending on the client name to identify -streams. The volume for a stream is automatically saved every time it is -changed and than restored when a new stream is created.

        - -

        module-detect

        - -

        Automatically detect the available sound hardware and load modules for it. Supports OSS, ALSA, Solaris and Win32 output drivers. - - - -
        just-one=If set to 1 the module will only try to load a single sink/source and than stop.
        - -

        module-zeroconf-publish

        - -

        Publish all local sinks/sources using mDNS Zeroconf.

        - - -
        -
        Lennart Poettering <@PACKAGE_BUGREPORT@>, April 2006
        -
        $Id$
        - diff --git a/doc/style.css b/doc/style.css deleted file mode 100644 index c5af0055b..000000000 --- a/doc/style.css +++ /dev/null @@ -1,27 +0,0 @@ -/* $Id$ */ - -/*** - * This file is part of PulseAudio. - * - * PulseAudio is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * PulseAudio is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with PulseAudio; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - ***/ - -body { color: black; background-color: white; } -a:link, a:visited { color: #900000; } -div.news-date { font-size: 80%; font-style: italic; } -pre { background-color: #f0f0f0; padding: 0.4cm; } -.grey { color: #8f8f8f; font-size: 80%; } -table { margin-left: 1cm; border:1px solid lightgrey; padding: 0.2cm; } -td { padding-left:10px; padding-right:10px; } From f87f3c805470c5a0aab50a19387f1583fb487720 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Jul 2006 10:40:15 +0000 Subject: [PATCH 0963/1514] unhide a few files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1060 fefdeb5f-60dc-0310-8127-8f9354f1896f From eb4abb2cceb2f178cdabcea31c99c6d75dae7d1c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 8 Jul 2006 10:51:46 +0000 Subject: [PATCH 0964/1514] Fix typo. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1061 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 12621d6a3..2bd3b871d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -749,7 +749,7 @@ libauthkey_prop_la_LDFLAGS = -avoid-version libauthkey_prop_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket_util_la_SOURCES = \ - pulsecore/inet_ntop.c pulsecor/inet_ntop.h \ + pulsecore/inet_ntop.c pulsecore/inet_ntop.h \ pulsecore/socket-util.c pulsecore/socket-util.h libsocket_util_la_LDFLAGS = -avoid-version libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) libpulsecore.la From e12ead7c5948c8ff7265fda5dc433de031ebbcda Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sat, 8 Jul 2006 11:29:14 +0000 Subject: [PATCH 0965/1514] Remove some unused m4 files. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1062 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- libtool.m4 | 5951 --------------------------------------------------- ltdl.m4 | 431 ---- 3 files changed, 1 insertion(+), 6383 deletions(-) delete mode 100644 libtool.m4 delete mode 100644 ltdl.m4 diff --git a/Makefile.am b/Makefile.am index 0884476d4..d5d9b52fa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,7 +17,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4 README +EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in README SUBDIRS=libltdl src doc doxygen MAINTAINERCLEANFILES = diff --git a/libtool.m4 b/libtool.m4 deleted file mode 100644 index 4f5ac795c..000000000 --- a/libtool.m4 +++ /dev/null @@ -1,5951 +0,0 @@ -# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -## Copyright 1996, 1997, 1998, 1999, 2000, 2001 -## Free Software Foundation, Inc. -## Originally by Gordon Matzigkeit , 1996 -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -## -## As a special exception to the GNU General Public License, if you -## distribute this file as part of a program that contains a -## configuration script generated by Autoconf, you may include it under -## the same distribution terms that you use for the rest of that program. - -# serial 47 AC_PROG_LIBTOOL -# Debian $Rev: 214 $ - - -# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) -# ----------------------------------------------------------- -# If this macro is not defined by Autoconf, define it here. -m4_ifdef([AC_PROVIDE_IFELSE], - [], - [m4_define([AC_PROVIDE_IFELSE], - [m4_ifdef([AC_PROVIDE_$1], - [$2], [$3])])]) - - -# AC_PROG_LIBTOOL -# --------------- -AC_DEFUN([AC_PROG_LIBTOOL], -[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl -dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX -dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. - AC_PROVIDE_IFELSE([AC_PROG_CXX], - [AC_LIBTOOL_CXX], - [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX - ])]) -dnl And a similar setup for Fortran 77 support - AC_PROVIDE_IFELSE([AC_PROG_F77], - [AC_LIBTOOL_F77], - [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 -])]) - -dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. -dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run -dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. - AC_PROVIDE_IFELSE([AC_PROG_GCJ], - [AC_LIBTOOL_GCJ], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], - [AC_LIBTOOL_GCJ], - [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], - [AC_LIBTOOL_GCJ], - [ifdef([AC_PROG_GCJ], - [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) - ifdef([A][M_PROG_GCJ], - [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) - ifdef([LT_AC_PROG_GCJ], - [define([LT_AC_PROG_GCJ], - defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) -])])# AC_PROG_LIBTOOL - - -# _AC_PROG_LIBTOOL -# ---------------- -AC_DEFUN([_AC_PROG_LIBTOOL], -[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl -AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl -AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl -AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' -AC_SUBST(LIBTOOL)dnl - -# Prevent multiple expansion -define([AC_PROG_LIBTOOL], []) -])# _AC_PROG_LIBTOOL - - -# AC_LIBTOOL_SETUP -# ---------------- -AC_DEFUN([AC_LIBTOOL_SETUP], -[AC_PREREQ(2.50)dnl -AC_REQUIRE([AC_ENABLE_SHARED])dnl -AC_REQUIRE([AC_ENABLE_STATIC])dnl -AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_LD])dnl -AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl -AC_REQUIRE([AC_PROG_NM])dnl - -AC_REQUIRE([AC_PROG_LN_S])dnl -AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl -# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! -AC_REQUIRE([AC_OBJEXT])dnl -AC_REQUIRE([AC_EXEEXT])dnl -dnl - -AC_LIBTOOL_SYS_MAX_CMD_LEN -AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE -AC_LIBTOOL_OBJDIR - -AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl -_LT_AC_PROG_ECHO_BACKSLASH - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e s/^X//' -[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] - -# Same as above, but do not quote variable references. -[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -# Constants: -rm="rm -f" - -# Global variables: -default_ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except M$VC, -# which needs '.lib'). -libext=a -ltmain="$ac_aux_dir/ltmain.sh" -ofile="$default_ofile" -with_gnu_ld="$lt_cv_prog_gnu_ld" - -AC_CHECK_TOOL(AR, ar, false) -AC_CHECK_TOOL(RANLIB, ranlib, :) -AC_CHECK_TOOL(STRIP, strip, :) - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru -test -z "$AS" && AS=as -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$DLLTOOL" && DLLTOOL=dlltool -test -z "$LD" && LD=ld -test -z "$LN_S" && LN_S="ln -s" -test -z "$MAGIC_CMD" && MAGIC_CMD=file -test -z "$NM" && NM=nm -test -z "$SED" && SED=sed -test -z "$OBJDUMP" && OBJDUMP=objdump -test -z "$RANLIB" && RANLIB=: -test -z "$STRIP" && STRIP=: -test -z "$ac_objext" && ac_objext=o - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" - ;; - *) - old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" -fi - -# Only perform the check for file, if the check method requires it -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - AC_PATH_MAGIC - fi - ;; -esac - -AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) -AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], -enable_win32_dll=yes, enable_win32_dll=no) - -AC_ARG_ENABLE([libtool-lock], - [AC_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -AC_ARG_WITH([pic], - [AC_HELP_STRING([--with-pic], - [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], - [pic_mode="$withval"], - [pic_mode=default]) -test -z "$pic_mode" && pic_mode=default - -# Use C for the default configuration in the libtool script -tagname= -AC_LIBTOOL_LANG_C_CONFIG -_LT_AC_TAGCONFIG -])# AC_LIBTOOL_SETUP - - -# _LT_AC_SYS_COMPILER -# ------------------- -AC_DEFUN([_LT_AC_SYS_COMPILER], -[AC_REQUIRE([AC_PROG_CC])dnl - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# Allow CC to be a program name with arguments. -compiler=$CC -])# _LT_AC_SYS_COMPILER - - -# _LT_AC_SYS_LIBPATH_AIX -# ---------------------- -# Links a minimal program and checks the executable -# for the system default hardcoded library path. In most cases, -# this is /usr/lib:/lib, but when the MPI compilers are used -# the location of the communication and MPI libs are included too. -# If we don't find anything, use the default library path according -# to the aix ld manual. -AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], -[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi],[]) -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi -])# _LT_AC_SYS_LIBPATH_AIX - - -# _LT_AC_SHELL_INIT(ARG) -# ---------------------- -AC_DEFUN([_LT_AC_SHELL_INIT], -[ifdef([AC_DIVERSION_NOTICE], - [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], - [AC_DIVERT_PUSH(NOTICE)]) -$1 -AC_DIVERT_POP -])# _LT_AC_SHELL_INIT - - -# _LT_AC_PROG_ECHO_BACKSLASH -# -------------------------- -# Add some code to the start of the generated configure script which -# will find an echo command which doesn't interpret backslashes. -AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], -[_LT_AC_SHELL_INIT([ -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` - ;; -esac - -echo=${ECHO-echo} -if test "X[$]1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X[$]1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then - # Yippee, $echo works! - : -else - # Restart under the correct shell. - exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} -fi - -if test "X[$]1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null && - echo_test_string="`eval $cmd`" && - (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null - then - break - fi - done -fi - -if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : -else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$echo" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - echo='print -r' - elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} - else - # Try using printf. - echo='printf %s\n' - if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - echo="$CONFIG_SHELL [$]0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$CONFIG_SHELL [$]0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do - if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "[$]0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} - else - # Oops. We lost completely, so just stick with echo. - echo=echo - fi - fi - fi - fi -fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -ECHO=$echo -if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then - ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" -fi - -AC_SUBST(ECHO) -])])# _LT_AC_PROG_ECHO_BACKSLASH - - -# _LT_AC_LOCK -# ----------- -AC_DEFUN([_LT_AC_LOCK], -[AC_ARG_ENABLE([libtool-lock], - [AC_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '[#]line __oline__ "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case "`/usr/bin/file conftest.o`" in - *32-bit*) - case $host in - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, - [AC_LANG_PUSH(C) - AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) - AC_LANG_POP]) - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; -AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], -[*-*-cygwin* | *-*-mingw* | *-*-pw32*) - AC_CHECK_TOOL(DLLTOOL, dlltool, false) - AC_CHECK_TOOL(AS, as, false) - AC_CHECK_TOOL(OBJDUMP, objdump, false) - ;; - ]) -esac - -need_locks="$enable_libtool_lock" - -])# _LT_AC_LOCK - - -# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------------------- -# Check whether the given compiler option works -AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], -[AC_REQUIRE([LT_AC_PROG_SED]) -AC_CACHE_CHECK([$1], [$2], - [$2=no - ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then - $2=yes - fi - fi - $rm conftest* -]) - -if test x"[$]$2" = xyes; then - ifelse([$5], , :, [$5]) -else - ifelse([$6], , :, [$6]) -fi -])# AC_LIBTOOL_COMPILER_OPTION - - -# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [ACTION-SUCCESS], [ACTION-FAILURE]) -# ------------------------------------------------------------ -# Check whether the given compiler option works -AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], -[AC_CACHE_CHECK([$1], [$2], - [$2=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $3" - printf "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&AS_MESSAGE_LOG_FD - else - $2=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" -]) - -if test x"[$]$2" = xyes; then - ifelse([$4], , :, [$4]) -else - ifelse([$5], , :, [$5]) -fi -])# AC_LIBTOOL_LINKER_OPTION - - -# AC_LIBTOOL_SYS_MAX_CMD_LEN -# -------------------------- -AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], -[# find the maximum length of command line arguments -AC_MSG_CHECKING([the maximum length of command line arguments]) -AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl - i=0 - teststring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - *) - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ - = "XX$teststring") >/dev/null 2>&1 && - new_result=`expr "X$teststring" : ".*" 2>&1` && - lt_cv_sys_max_cmd_len=$new_result && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - teststring= - # Add a significant safety factor because C++ compilers can tack on massive - # amounts of additional arguments before passing them to the linker. - # It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - ;; - esac -]) -if test -n $lt_cv_sys_max_cmd_len ; then - AC_MSG_RESULT($lt_cv_sys_max_cmd_len) -else - AC_MSG_RESULT(none) -fi -])# AC_LIBTOOL_SYS_MAX_CMD_LEN - - -# _LT_AC_CHECK_DLFCN -# -------------------- -AC_DEFUN([_LT_AC_CHECK_DLFCN], -[AC_CHECK_HEADERS(dlfcn.h)dnl -])# _LT_AC_CHECK_DLFCN - - -# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, -# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) -# ------------------------------------------------------------------ -AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], -[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl -if test "$cross_compiling" = yes; then : - [$4] -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -}] -EOF - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) $1 ;; - x$lt_dlneed_uscore) $2 ;; - x$lt_unknown|x*) $3 ;; - esac - else : - # compilation failed - $3 - fi -fi -rm -fr conftest* -])# _LT_AC_TRY_DLOPEN_SELF - - -# AC_LIBTOOL_DLOPEN_SELF -# ------------------- -AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], -[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ]) - ;; - - *) - AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen="shl_load"], - [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], - [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen="dlopen"], - [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], - [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], - [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) - ]) - ]) - ]) - ]) - ]) - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - AC_CACHE_CHECK([whether a program can dlopen itself], - lt_cv_dlopen_self, [dnl - _LT_AC_TRY_DLOPEN_SELF( - lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, - lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) - ]) - - if test "x$lt_cv_dlopen_self" = xyes; then - LDFLAGS="$LDFLAGS $link_static_flag" - AC_CACHE_CHECK([whether a statically linked program can dlopen itself], - lt_cv_dlopen_self_static, [dnl - _LT_AC_TRY_DLOPEN_SELF( - lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, - lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) - ]) - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi -])# AC_LIBTOOL_DLOPEN_SELF - - -# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) -# --------------------------------- -# Check to see if options -c and -o are simultaneously supported by compiler -AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], -[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl -AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], - [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], - [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s out/conftest.err; then - _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - fi - fi - chmod u+w . - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* -]) -])# AC_LIBTOOL_PROG_CC_C_O - - -# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) -# ----------------------------------------- -# Check to see if we can do hard links to lock some files if needed -AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], -[AC_REQUIRE([_LT_AC_LOCK])dnl - -hard_links="nottested" -if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - AC_MSG_CHECKING([if we can lock with hard links]) - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - AC_MSG_RESULT([$hard_links]) - if test "$hard_links" = no; then - AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) - need_locks=warn - fi -else - need_locks=no -fi -])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS - - -# AC_LIBTOOL_OBJDIR -# ----------------- -AC_DEFUN([AC_LIBTOOL_OBJDIR], -[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], -[rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null]) -objdir=$lt_cv_objdir -])# AC_LIBTOOL_OBJDIR - - -# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) -# ---------------------------------------------- -# Check hardcoding attributes. -AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], -[AC_MSG_CHECKING([how to hardcode library paths into programs]) -_LT_AC_TAGVAR(hardcode_action, $1)= -if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ - test -n "$_LT_AC_TAGVAR(runpath_var $1)" || \ - test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)"="Xyes" ; then - - # We can hardcode non-existant directories. - if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && - test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then - # Linking always hardcodes the temporary library directory. - _LT_AC_TAGVAR(hardcode_action, $1)=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - _LT_AC_TAGVAR(hardcode_action, $1)=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - _LT_AC_TAGVAR(hardcode_action, $1)=unsupported -fi -AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) - -if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi -])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH - - -# AC_LIBTOOL_SYS_LIB_STRIP -# ------------------------ -AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], -[striplib= -old_striplib= -AC_MSG_CHECKING([whether stripping libraries is possible]) -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - AC_MSG_RESULT([yes]) -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) -fi - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac -fi -])# AC_LIBTOOL_SYS_LIB_STRIP - - -# AC_LIBTOOL_SYS_DYNAMIC_LINKER -# ----------------------------- -# PORTME Fill in your ld.so characteristics -AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], -[AC_MSG_CHECKING([dynamic linker characteristics]) -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[[01]] | aix4.[[01]].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi4*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - *) # from 3.2 on - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case "$host_cpu" in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`$SED -e 's/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g' /etc/ld.so.conf | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - need_lib_prefix=no - need_version=yes - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[[89]] | openbsd2.[[89]].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -AC_MSG_RESULT([$dynamic_linker]) -test "$dynamic_linker" = no && can_build_shared=no -])# AC_LIBTOOL_SYS_DYNAMIC_LINKER - - -# _LT_AC_TAGCONFIG -# ---------------- -AC_DEFUN([_LT_AC_TAGCONFIG], -[AC_ARG_WITH([tags], - [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], - [include additional configurations @<:@automatic@:>@])], - [tagnames="$withval"]) - -if test -f "$ltmain" && test -n "$tagnames"; then - if test ! -f "${ofile}"; then - AC_MSG_WARN([output file `$ofile' does not exist]) - fi - - if test -z "$LTCC"; then - eval "`$SHELL ${ofile} --config | grep '^LTCC='`" - if test -z "$LTCC"; then - AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) - else - AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) - fi - fi - - # Extract list of available tagged configurations in $ofile. - # Note that this assumes the entire list is on one line. - available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` - - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for tagname in $tagnames; do - IFS="$lt_save_ifs" - # Check whether tagname contains only valid characters - case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in - "") ;; - *) AC_MSG_ERROR([invalid tag name: $tagname]) - ;; - esac - - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null - then - AC_MSG_ERROR([tag name \"$tagname\" already exists]) - fi - - # Update the list of available tags. - if test -n "$tagname"; then - echo appending configuration tag \"$tagname\" to $ofile - - case $tagname in - CXX) - if test -n "$CXX" && test "X$CXX" != "Xno"; then - AC_LIBTOOL_LANG_CXX_CONFIG - else - tagname="" - fi - ;; - - F77) - if test -n "$F77" && test "X$F77" != "Xno"; then - AC_LIBTOOL_LANG_F77_CONFIG - else - tagname="" - fi - ;; - - GCJ) - if test -n "$GCJ" && test "X$GCJ" != "Xno"; then - AC_LIBTOOL_LANG_GCJ_CONFIG - else - tagname="" - fi - ;; - - RC) - AC_LIBTOOL_LANG_RC_CONFIG - ;; - - *) - AC_MSG_ERROR([Unsupported tag name: $tagname]) - ;; - esac - - # Append the new tag name to the list of available tags. - if test -n "$tagname" ; then - available_tags="$available_tags $tagname" - fi - fi - done - IFS="$lt_save_ifs" - - # Now substitute the updated list of available tags. - if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then - mv "${ofile}T" "$ofile" - chmod +x "$ofile" - else - rm -f "${ofile}T" - AC_MSG_ERROR([unable to update list of available tagged configurations.]) - fi -fi -])# _LT_AC_TAGCONFIG - - -# AC_LIBTOOL_DLOPEN -# ----------------- -# enable checks for dlopen support -AC_DEFUN([AC_LIBTOOL_DLOPEN], - [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) -])# AC_LIBTOOL_DLOPEN - - -# AC_LIBTOOL_WIN32_DLL -# -------------------- -# declare package support for building win32 dll's -AC_DEFUN([AC_LIBTOOL_WIN32_DLL], -[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) -])# AC_LIBTOOL_WIN32_DLL - - -# AC_ENABLE_SHARED([DEFAULT]) -# --------------------------- -# implement the --enable-shared flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -AC_DEFUN([AC_ENABLE_SHARED], -[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE([shared], - [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], - [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_shared=]AC_ENABLE_SHARED_DEFAULT) -])# AC_ENABLE_SHARED - - -# AC_DISABLE_SHARED -# ----------------- -#- set the default shared flag to --disable-shared -AC_DEFUN([AC_DISABLE_SHARED], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_SHARED(no) -])# AC_DISABLE_SHARED - - -# AC_ENABLE_STATIC([DEFAULT]) -# --------------------------- -# implement the --enable-static flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -AC_DEFUN([AC_ENABLE_STATIC], -[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE([static], - [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], - [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_static=]AC_ENABLE_STATIC_DEFAULT) -])# AC_ENABLE_STATIC - - -# AC_DISABLE_STATIC -# ----------------- -# set the default static flag to --disable-static -AC_DEFUN([AC_DISABLE_STATIC], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_STATIC(no) -])# AC_DISABLE_STATIC - - -# AC_ENABLE_FAST_INSTALL([DEFAULT]) -# --------------------------------- -# implement the --enable-fast-install flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -AC_DEFUN([AC_ENABLE_FAST_INSTALL], -[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE([fast-install], - [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], - [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) -])# AC_ENABLE_FAST_INSTALL - - -# AC_DISABLE_FAST_INSTALL -# ----------------------- -# set the default to --disable-fast-install -AC_DEFUN([AC_DISABLE_FAST_INSTALL], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_FAST_INSTALL(no) -])# AC_DISABLE_FAST_INSTALL - - -# AC_LIBTOOL_PICMODE([MODE]) -# -------------------------- -# implement the --with-pic flag -# MODE is either `yes' or `no'. If omitted, it defaults to `both'. -AC_DEFUN([AC_LIBTOOL_PICMODE], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -pic_mode=ifelse($#,1,$1,default) -])# AC_LIBTOOL_PICMODE - - -# AC_PROG_EGREP -# ------------- -# This is predefined starting with Autoconf 2.54, so this conditional -# definition can be removed once we require Autoconf 2.54 or later. -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], -[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], - [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' - fi]) - EGREP=$ac_cv_prog_egrep - AC_SUBST([EGREP]) -])]) - - -# AC_PATH_TOOL_PREFIX -# ------------------- -# find a file program which can recognise shared library -AC_DEFUN([AC_PATH_TOOL_PREFIX], -[AC_REQUIRE([AC_PROG_EGREP])dnl -AC_MSG_CHECKING([for $1]) -AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, -[case $MAGIC_CMD in -[[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR -dnl $ac_dummy forces splitting on constant user-supplied paths. -dnl POSIX.2 word splitting is done only on the output of word expansions, -dnl not every word. This closes a longstanding sh security hole. - ac_dummy="ifelse([$2], , $PATH, [$2])" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$1; then - lt_cv_path_MAGIC_CMD="$ac_dir/$1" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac]) -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - AC_MSG_RESULT($MAGIC_CMD) -else - AC_MSG_RESULT(no) -fi -])# AC_PATH_TOOL_PREFIX - - -# AC_PATH_MAGIC -# ------------- -# find a file program which can recognise a shared library -AC_DEFUN([AC_PATH_MAGIC], -[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) - else - MAGIC_CMD=: - fi -fi -])# AC_PATH_MAGIC - - -# AC_PROG_LD -# ---------- -# find the pathname to the GNU or non-GNU linker -AC_DEFUN([AC_PROG_LD], -[AC_ARG_WITH([gnu-ld], - [AC_HELP_STRING([--with-gnu-ld], - [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test "$withval" = no || with_gnu_ld=yes], - [with_gnu_ld=no]) -AC_REQUIRE([LT_AC_PROG_SED])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by $CC]) - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [[\\/]]* | ?:[[\\/]]*) - re_direlt='/[[^/]][[^/]]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(lt_cv_path_LD, -[if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case "$host_cpu" in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be Linux ELF. -linux*) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | netbsdelf*-gnu | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -nto-qnx*) - lt_cv_deplibs_check_method=unknown - ;; - -openbsd*) - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' - else - lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -sco3.2v5*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; -esac -]) -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown -])# AC_DEPLIBS_CHECK_METHOD - - -# AC_PROG_NM -# ---------- -# find the pathname to a BSD-compatible name lister -AC_DEFUN([AC_PROG_NM], -[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, -[if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/${ac_tool_prefix}nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - esac - fi - done - IFS="$lt_save_ifs" - test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm -fi]) -NM="$lt_cv_path_NM" -])# AC_PROG_NM - - -# AC_CHECK_LIBM -# ------------- -# check for math library -AC_DEFUN([AC_CHECK_LIBM], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -LIBM= -case $host in -*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) - # These system don't have libm, or don't need it - ;; -*-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") - AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") - ;; -*) - AC_CHECK_LIB(m, cos, LIBM="-lm") - ;; -esac -])# AC_CHECK_LIBM - - -# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) -# ----------------------------------- -# sets LIBLTDL to the link flags for the libltdl convenience library and -# LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL -# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If -# DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will -# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with -# '${top_srcdir}/' (note the single quotes!). If your package is not -# flat and you're not using automake, define top_builddir and -# top_srcdir appropriately in the Makefiles. -AC_DEFUN([AC_LIBLTDL_CONVENIENCE], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl - case $enable_ltdl_convenience in - no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; - "") enable_ltdl_convenience=yes - ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; - esac - LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la - LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) - # For backwards non-gettext consistent compatibility... - INCLTDL="$LTDLINCL" -])# AC_LIBLTDL_CONVENIENCE - - -# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) -# ----------------------------------- -# sets LIBLTDL to the link flags for the libltdl installable library and -# LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-install to the configure arguments. Note that LIBLTDL -# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If -# DIRECTORY is not provided and an installed libltdl is not found, it is -# assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/' -# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single -# quotes!). If your package is not flat and you're not using automake, -# define top_builddir and top_srcdir appropriately in the Makefiles. -# In the future, this macro may have to be called after AC_PROG_LIBTOOL. -AC_DEFUN([AC_LIBLTDL_INSTALLABLE], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl - AC_CHECK_LIB(ltdl, lt_dlinit, - [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], - [if test x"$enable_ltdl_install" = xno; then - AC_MSG_WARN([libltdl not installed, but installation disabled]) - else - enable_ltdl_install=yes - fi - ]) - if test x"$enable_ltdl_install" = x"yes"; then - ac_configure_args="$ac_configure_args --enable-ltdl-install" - LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la - LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) - else - ac_configure_args="$ac_configure_args --enable-ltdl-install=no" - LIBLTDL="-lltdl" - LTDLINCL= - fi - # For backwards non-gettext consistent compatibility... - INCLTDL="$LTDLINCL" -])# AC_LIBLTDL_INSTALLABLE - - -# AC_LIBTOOL_CXX -# -------------- -# enable support for C++ libraries -AC_DEFUN([AC_LIBTOOL_CXX], -[AC_REQUIRE([_LT_AC_LANG_CXX]) -])# AC_LIBTOOL_CXX - - -# _LT_AC_LANG_CXX -# --------------- -AC_DEFUN([_LT_AC_LANG_CXX], -[AC_REQUIRE([AC_PROG_CXX]) -AC_REQUIRE([AC_PROG_CXXCPP]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) -])# _LT_AC_LANG_CXX - - -# AC_LIBTOOL_F77 -# -------------- -# enable support for Fortran 77 libraries -AC_DEFUN([AC_LIBTOOL_F77], -[AC_REQUIRE([_LT_AC_LANG_F77]) -])# AC_LIBTOOL_F77 - - -# _LT_AC_LANG_F77 -# --------------- -AC_DEFUN([_LT_AC_LANG_F77], -[AC_REQUIRE([AC_PROG_F77]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) -])# _LT_AC_LANG_F77 - - -# AC_LIBTOOL_GCJ -# -------------- -# enable support for GCJ libraries -AC_DEFUN([AC_LIBTOOL_GCJ], -[AC_REQUIRE([_LT_AC_LANG_GCJ]) -])# AC_LIBTOOL_GCJ - - -# _LT_AC_LANG_GCJ -# --------------- -AC_DEFUN([_LT_AC_LANG_GCJ], -[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], - [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], - [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], - [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], - [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) -])# _LT_AC_LANG_GCJ - - -# AC_LIBTOOL_RC -# -------------- -# enable support for Windows resource files -AC_DEFUN([AC_LIBTOOL_RC], -[AC_REQUIRE([LT_AC_PROG_RC]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) -])# AC_LIBTOOL_RC - - -# AC_LIBTOOL_LANG_C_CONFIG -# ------------------------ -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. -AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) -AC_DEFUN([_LT_AC_LANG_C_CONFIG], -[lt_save_CC="$CC" -AC_LANG_PUSH(C) - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -_LT_AC_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}\n' - -_LT_AC_SYS_COMPILER - -# -# Check for any special shared library compilation flags. -# -_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= -if test "$GCC" = no; then - case $host_os in - sco3.2v5*) - _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' - ;; - esac -fi -if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then - AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) - if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[ ]]" >/dev/null; then : - else - AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) - _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no - fi -fi - - -# -# Check to make sure the static flag actually works. -# -AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], - _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), - $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), - [], - [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) - - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) -AC_LIBTOOL_PROG_COMPILER_PIC($1) -AC_LIBTOOL_PROG_CC_C_O($1) -AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) -AC_LIBTOOL_PROG_LD_SHLIBS($1) -AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) -AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) -AC_LIBTOOL_SYS_LIB_STRIP -AC_LIBTOOL_DLOPEN_SELF($1) - -# Report which librarie types wil actually be built -AC_MSG_CHECKING([if libtool supports shared libraries]) -AC_MSG_RESULT([$can_build_shared]) - -AC_MSG_CHECKING([whether to build shared libraries]) -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case "$host_os" in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - -aix4* | aix5*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - darwin* | rhapsody*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case "$host_os" in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - output_verbose_link_cmd='echo' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' - _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_automatic, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; -esac -AC_MSG_RESULT([$enable_shared]) - -AC_MSG_CHECKING([whether to build static libraries]) -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes -AC_MSG_RESULT([$enable_static]) - -AC_LIBTOOL_CONFIG($1) - -AC_LANG_POP -CC="$lt_save_CC" -])# AC_LIBTOOL_LANG_C_CONFIG - - -# AC_LIBTOOL_LANG_CXX_CONFIG -# -------------------------- -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. -AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) -AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], -[AC_LANG_PUSH(C++) -AC_REQUIRE([AC_PROG_CXX]) -AC_REQUIRE([AC_PROG_CXXCPP]) - -_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_AC_TAGVAR(allow_undefined_flag, $1)= -_LT_AC_TAGVAR(always_export_symbols, $1)=no -_LT_AC_TAGVAR(archive_expsym_cmds, $1)= -_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_AC_TAGVAR(hardcode_direct, $1)=no -_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= -_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= -_LT_AC_TAGVAR(hardcode_minus_L, $1)=no -_LT_AC_TAGVAR(hardcode_automatic, $1)=no -_LT_AC_TAGVAR(module_cmds, $1)= -_LT_AC_TAGVAR(module_expsym_cmds, $1)= -_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown -_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_AC_TAGVAR(no_undefined_flag, $1)= -_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= -_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Dependencies to place before and after the object being linked: -_LT_AC_TAGVAR(predep_objects, $1)= -_LT_AC_TAGVAR(postdep_objects, $1)= -_LT_AC_TAGVAR(predeps, $1)= -_LT_AC_TAGVAR(postdeps, $1)= -_LT_AC_TAGVAR(compiler_lib_search_path, $1)= - -# Source file extension for C++ test sources. -ac_ext=cc - -# Object file extension for compiled C++ test sources. -objext=o -_LT_AC_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_AC_SYS_COMPILER - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_LD=$LD -lt_save_GCC=$GCC -GCC=$GXX -lt_save_with_gnu_ld=$with_gnu_ld -lt_save_path_LD=$lt_cv_path_LD -if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx -else - unset lt_cv_prog_gnu_ld -fi -if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX -else - unset lt_cv_path_LD -fi -test -z "${LDCXX+set}" || LD=$LDCXX -CC=${CXX-"c++"} -compiler=$CC -_LT_AC_TAGVAR(compiler, $1)=$CC -cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` - -# We don't want -fno-exception wen compiling C++ code, so set the -# no_builtin_flag separately -if test "$GXX" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' -else - _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= -fi - -if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - AC_PROG_LD - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ - grep 'no-whole-archive' > /dev/null; then - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - -else - GXX=no - with_gnu_ld=no - wlarc= -fi - -# PORTME: fill in a description of your system's C++ link characteristics -AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -_LT_AC_TAGVAR(ld_shlibs, $1)=yes -case $host_os in - aix3*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_AC_TAGVAR(archive_cmds, $1)='' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - if test "$GXX" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - else - # We have old collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= - fi - esac - shared_flag='-shared' - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - # Exported symbols can be pulled into shared objects from archives - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds it's shared libraries. - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(always_export_symbols, $1)=no - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - darwin* | rhapsody*) - if test "$GXX" = yes; then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case "$host_os" in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_automatic, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - dgux*) - case $cc_basename in - ec++) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - ghcx) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - freebsd[12]*) - # C++ shared libraries reported to be fairly broken before switch to ELF - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - freebsd-elf*) - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - ;; - freebsd* | kfreebsd*-gnu) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - _LT_AC_TAGVAR(ld_shlibs, $1)=yes - ;; - gnu*) - ;; - hpux9*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - aCC) - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - case "$host_cpu" in - hppa*64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - ia64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - ;; - *) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - esac - fi - case "$host_cpu" in - hppa*64*) - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - ia64*) - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - *) - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - aCC) - case "$host_cpu" in - hppa*64*|ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case "$host_cpu" in - ia64*|hppa*64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - irix5* | irix6*) - case $cc_basename in - CC) - # SGI C++ - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' - fi - fi - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - ;; - esac - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - linux*) - case $cc_basename in - KCC) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc) - # Intel C++ - with_gnu_ld=yes - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - cxx) - # Compaq C++ - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - esac - ;; - lynxos*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - m88k*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - mvs*) - case $cc_basename in - cxx) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - netbsd* | netbsdelf*-gnu | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - osf3*) - case $cc_basename in - KCC) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - - ;; - RCC) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - cxx) - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - osf4* | osf5*) - case $cc_basename in - KCC) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' - ;; - RCC) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - cxx) - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ - $rm $lib.exp' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - psos*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - sco*) - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - lcc) - # Lucid - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - solaris*) - case $cc_basename in - CC) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The C++ compiler is used as linker so we must use $wl - # flag to pass the commands to the underlying system - # linker. - # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - ;; - esac - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - gcx) - # Green Hills C++ Compiler - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' - if $CC --version | grep -v '^2\.7' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - fi - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' - fi - ;; - esac - ;; - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - ;; - tandem*) - case $cc_basename in - NCC) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - vxworks*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; -esac -AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) -test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - -_LT_AC_TAGVAR(GCC, $1)="$GXX" -_LT_AC_TAGVAR(LD, $1)="$LD" - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -AC_LIBTOOL_POSTDEP_PREDEP($1) -AC_LIBTOOL_PROG_COMPILER_PIC($1) -AC_LIBTOOL_PROG_CC_C_O($1) -AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) -AC_LIBTOOL_PROG_LD_SHLIBS($1) -AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) -AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) -AC_LIBTOOL_SYS_LIB_STRIP -AC_LIBTOOL_DLOPEN_SELF($1) - -AC_LIBTOOL_CONFIG($1) - -AC_LANG_POP -CC=$lt_save_CC -LDCXX=$LD -LD=$lt_save_LD -GCC=$lt_save_GCC -with_gnu_ldcxx=$with_gnu_ld -with_gnu_ld=$lt_save_with_gnu_ld -lt_cv_path_LDCXX=$lt_cv_path_LD -lt_cv_path_LD=$lt_save_path_LD -lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld -lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -])# AC_LIBTOOL_LANG_CXX_CONFIG - -# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) -# ------------------------ -# Figure out "hidden" library dependencies from verbose -# compiler output when linking a shared library. -# Parse the compiler output and extract the necessary -# objects, libraries and library flags. -AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ -dnl we can't use the lt_simple_compile_test_code here, -dnl because it contains code intended for an executable, -dnl not a library. It's possible we should let each -dnl tag define a new lt_????_link_test_code variable, -dnl but it's only used here... -ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" -ifelse([$1], [], -[#! $SHELL - -# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. -# -# This file is part of GNU Libtool: -# Originally by Gordon Matzigkeit , 1996 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# A sed program that does not truncate output. -SED=$lt_SED - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="$SED -e s/^X//" - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi - -# The names of the tagged configurations supported by this script. -available_tags= - -# ### BEGIN LIBTOOL CONFIG], -[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# A language-specific compiler. -CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) - -# Is the compiler the GNU C compiler? -with_gcc=$_LT_AC_TAGVAR(GCC, $1) - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_[]_LT_AC_TAGVAR(LD, $1) - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) - -# Must we lock files when doing compilation ? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) - -# Commands used to build and install a shared archive. -archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) -archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) -module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" - -# Set to yes if exported symbols are required. -always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) - -# The commands to list exported symbols. -export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) - -# Symbols that must always be exported. -include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) - -ifelse([$1],[], -[# ### END LIBTOOL CONFIG], -[# ### END LIBTOOL TAG CONFIG: $tagname]) - -__EOF__ - -ifelse([$1],[], [ - case $host_os in - aix3*) - cat <<\EOF >> "$cfgfile" - -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -EOF - ;; - esac - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || \ - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" -]) -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi -])# AC_LIBTOOL_CONFIG - - -# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) -# ------------------------------------------- -AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], -[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl - -_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - -if test "$GCC" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' - - AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], - lt_cv_prog_compiler_rtti_exceptions, - [-fno-rtti -fno-exceptions], [], - [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) -fi -])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI - - -# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE -# --------------------------------- -AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], -[AC_REQUIRE([AC_CANONICAL_HOST]) -AC_REQUIRE([AC_PROG_NM]) -AC_REQUIRE([AC_OBJEXT]) -# Check for command to grab the raw symbol name followed by C symbol from nm. -AC_MSG_CHECKING([command to parse $NM output from $compiler object]) -AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], -[ -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[[BCDEGRST]]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' - -# Transform the above into a raw symbol and a C symbol. -symxfrm='\1 \2\3 \3' - -# Transform an extracted symbol line into a proper C declaration -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[[BCDT]]' - ;; -cygwin* | mingw* | pw32*) - symcode='[[ABCDGISTW]]' - ;; -hpux*) # Its linker distinguishes data from code symbols - if test "$host_cpu" = ia64; then - symcode='[[ABCDEGRST]]' - fi - lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - ;; -irix* | nonstopux*) - symcode='[[BCDEGRST]]' - ;; -osf*) - symcode='[[BCDEGQRST]]' - ;; -solaris* | sysv5*) - symcode='[[BDRT]]' - ;; -sysv4) - symcode='[[DFNSTU]]' - ;; -esac - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[[ABCDGIRSTW]]' ;; -esac - -# Try without a prefix undercore, then with it. -for ac_symprfx in "" "_"; do - - # Write the raw and C identifiers. - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if grep ' nm_test_var$' "$nlist" >/dev/null; then - if grep ' nm_test_func$' "$nlist" >/dev/null; then - cat < conftest.$ac_ext -#ifdef __cplusplus -extern "C" { -#endif - -EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' - - cat <> conftest.$ac_ext -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[[]] = -{ -EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext - cat <<\EOF >> conftest.$ac_ext - {0, (lt_ptr_t) 0} -}; - -#ifdef __cplusplus -} -#endif -EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" - else - echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD - fi - else - echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD - cat conftest.$ac_ext >&5 - fi - rm -f conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done -]) -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - AC_MSG_RESULT(failed) -else - AC_MSG_RESULT(ok) -fi -]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE - - -# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) -# --------------------------------------- -AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], -[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= -_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= -_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= - -AC_MSG_CHECKING([for $compiler option to produce PIC]) - ifelse([$1],[CXX],[ - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | os2* | pw32*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - sysv4*MP*) - if test -d /usr/nec; then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - case $host_os in - aix4* | aix5*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68) - # Green Hills C++ Compiler - # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - dgux*) - case $cc_basename in - ec++) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - ghcx) - # Green Hills C++ Compiler - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | kfreebsd*-gnu) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" - if test "$host_cpu" != ia64; then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - fi - ;; - aCC) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux*) - case $cc_basename in - KCC) - # KAI C++ Compiler - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - icpc) - # Intel C++ - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - cxx) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd* | netbsdelf*-gnu | knetbsd*-gnu) - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - ;; - RCC) - # Rational C++ 2.4.1 - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - cxx) - # Digital/Compaq C++ - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - sco*) - case $cc_basename in - CC) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - *) - ;; - esac - ;; - solaris*) - case $cc_basename in - CC) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - gcx) - # Green Hills C++ Compiler - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC) - # Sun C++ 4.x - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - lcc) - # Lucid - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC) - # NonStop-UX NCC 3.20 - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - *) - ;; - esac - ;; - unixware*) - ;; - vxworks*) - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -], -[ - if test "$GCC" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case "$host_cpu" in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC (with -KPIC) is the default. - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - newsos6) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - linux*) - case $CC in - icc* | ecc*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - ccc*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All Alpha code is PIC. - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - esac - ;; - - osf3* | osf4* | osf5*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All OSF/1 code is PIC. - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - sco3.2v5*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' - ;; - - solaris*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sunos4*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - uts4*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *) - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -]) -AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then - AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], - _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), - [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], - [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in - "" | " "*) ;; - *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; - esac], - [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) -fi -case "$host_os" in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" - ;; -esac -]) - - -# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) -# ------------------------------------ -# See if the linker supports building shared libraries. -AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], -[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -ifelse([$1],[CXX],[ - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - case $host_os in - aix4* | aix5*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - else - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" - ;; - cygwin* | mingw*) - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' - ;; - linux*) - _LT_AC_TAGVAR(link_all_deplibs, $1)=no - ;; - *) - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac -],[ - runpath_var= - _LT_AC_TAGVAR(allow_undefined_flag, $1)= - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no - _LT_AC_TAGVAR(archive_cmds, $1)= - _LT_AC_TAGVAR(archive_expsym_cmds, $1)= - _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= - _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_minus_L, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown - _LT_AC_TAGVAR(hardcode_automatic, $1)=no - _LT_AC_TAGVAR(module_cmds, $1)= - _LT_AC_TAGVAR(module_expsym_cmds, $1)= - _LT_AC_TAGVAR(always_export_symbols, $1)=no - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - _LT_AC_TAGVAR(include_expsyms, $1)= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - _LT_AC_TAGVAR(ld_shlibs, $1)=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - _LT_AC_TAGVAR(ld_shlibs, $1)=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(always_export_symbols, $1)=no - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' - else - ld_shlibs=no - fi - ;; - - netbsd* | netbsdelf*-gnu | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris* | sysv5*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - _LT_AC_TAGVAR(ld_shlibs, $1)=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - sunos4*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - linux*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds" - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - if test $supports_anon_versioning = yes; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ -cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ -$echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds" - fi - _LT_AC_TAGVAR(link_all_deplibs, $1)=no - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - - if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then - runpath_var=LD_RUN_PATH - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - fi - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - if test "$GCC" = yes && test -z "$link_static_flag"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - else - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_AC_TAGVAR(archive_cmds, $1)='' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - else - # We have old collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= - fi - esac - shared_flag='-shared' - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - # Exported symbols can be pulled into shared objects from archives - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds it's shared libraries. - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - # see comment about different semantics on the GNU ld section - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - - bsdi4*) - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' - # FIXME: Should let the user specify the lib program. - _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - darwin* | rhapsody*) - if test "$GXX" = yes ; then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case "$host_os" in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_automatic, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - dgux*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - freebsd1*) - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - hpux9*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - - hpux10* | hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*|ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case "$host_cpu" in - hppa*64*|ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - ia64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - ;; - *) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - ;; - - netbsd* | netbsdelf*-gnu | knetbsd*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - newsos6) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - openbsd*) - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - else - case $host_os in - openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - ;; - esac - fi - ;; - - os2*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - else - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - fi - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - sco3.2v5*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - - solaris*) - _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; - esac - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4) - case $host_vendor in - sni) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - ;; - motorola) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4.3*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - _LT_AC_TAGVAR(ld_shlibs, $1)=yes - fi - ;; - - sysv4.2uw2*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; - - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) - _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - runpath_var='LD_RUN_PATH' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv5*) - _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - ;; - - uts4*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - fi -]) -AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) -test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -# -# Do we need to explicitly link libc? -# -case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in -x|xyes) - # Assume -lc should be added - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $_LT_AC_TAGVAR(archive_cmds, $1) in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - AC_MSG_CHECKING([whether -lc should be explicitly linked in]) - $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - if AC_TRY_EVAL(ac_compile) 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) - _LT_AC_TAGVAR(allow_undefined_flag, $1)= - if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) - then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - else - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - fi - _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) - ;; - esac - fi - ;; -esac -])# AC_LIBTOOL_PROG_LD_SHLIBS - - -# _LT_AC_FILE_LTDLL_C -# ------------------- -# Be careful that the start marker always follows a newline. -AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ -# /* ltdll.c starts here */ -# #define WIN32_LEAN_AND_MEAN -# #include -# #undef WIN32_LEAN_AND_MEAN -# #include -# -# #ifndef __CYGWIN__ -# # ifdef __CYGWIN32__ -# # define __CYGWIN__ __CYGWIN32__ -# # endif -# #endif -# -# #ifdef __cplusplus -# extern "C" { -# #endif -# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); -# #ifdef __cplusplus -# } -# #endif -# -# #ifdef __CYGWIN__ -# #include -# DECLARE_CYGWIN_DLL( DllMain ); -# #endif -# HINSTANCE __hDllInstance_base; -# -# BOOL APIENTRY -# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) -# { -# __hDllInstance_base = hInst; -# return TRUE; -# } -# /* ltdll.c ends here */ -])# _LT_AC_FILE_LTDLL_C - - -# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) -# --------------------------------- -AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) - - -# old names -AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) -AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) -AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) -AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) -AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) -AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) -AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) - -# This is just to silence aclocal about the macro not being used -ifelse([AC_DISABLE_FAST_INSTALL]) - -AC_DEFUN([LT_AC_PROG_GCJ], -[AC_CHECK_TOOL(GCJ, gcj, no) - test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" - AC_SUBST(GCJFLAGS) -]) - -AC_DEFUN([LT_AC_PROG_RC], -[AC_CHECK_TOOL(RC, windres, no) -]) - -############################################################ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_SED. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # -############################################################ -# LT_AC_PROG_SED -# -------------- -# Check for a fully-functional sed program, that truncates -# as few characters as possible. Prefer GNU sed if found. -AC_DEFUN([LT_AC_PROG_SED], -[AC_MSG_CHECKING([for a sed that does not truncate output]) -AC_CACHE_VAL(lt_cv_path_SED, -[# Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && break - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break - lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done -SED=$lt_cv_path_SED -]) -AC_MSG_RESULT([$SED]) -]) diff --git a/ltdl.m4 b/ltdl.m4 deleted file mode 100644 index aa6a0d134..000000000 --- a/ltdl.m4 +++ /dev/null @@ -1,431 +0,0 @@ -## ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- -## Copyright (C) 1999-2000 Free Software Foundation, Inc. -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -## -## As a special exception to the GNU General Public License, if you -## distribute this file as part of a program that contains a -## configuration script generated by Autoconf, you may include it under -## the same distribution terms that you use for the rest of that program. - -# serial 6 AC_LIB_LTDL -# Debian $Rev: 214 $ - -# AC_WITH_LTDL -# ------------ -# Clients of libltdl can use this macro to allow the installer to -# choose between a shipped copy of the ltdl sources or a preinstalled -# version of the library. -AC_DEFUN([AC_WITH_LTDL], -[AC_REQUIRE([AC_LIB_LTDL]) -AC_SUBST([LIBLTDL]) -AC_SUBST([INCLTDL]) - -# Unless the user asks us to check, assume no installed ltdl exists. -use_installed_libltdl=no - -AC_ARG_WITH([included_ltdl], - [ --with-included-ltdl use the GNU ltdl sources included here]) - -if test "x$with_included_ltdl" != xyes; then - # We are not being forced to use the included libltdl sources, so - # decide whether there is a useful installed version we can use. - AC_CHECK_HEADER([ltdl.h], - [AC_CHECK_LIB([ltdl], [lt_dlcaller_register], - [with_included_ltdl=no], - [with_included_ltdl=yes]) - ]) -fi - -if test "x$enable_ltdl_install" != xyes; then - # If the user did not specify an installable libltdl, then default - # to a convenience lib. - AC_LIBLTDL_CONVENIENCE -fi - -if test "x$with_included_ltdl" = xno; then - # If the included ltdl is not to be used. then Use the - # preinstalled libltdl we found. - AC_DEFINE([HAVE_LTDL], 1, - [Define this if a modern libltdl is already installed]) - LIBLTDL=-lltdl -fi - -# Report our decision... -AC_MSG_CHECKING([whether to use included libltdl]) -AC_MSG_RESULT([$with_included_ltdl]) - -AC_CONFIG_SUBDIRS([libltdl]) -])# AC_WITH_LTDL - - -# AC_LIB_LTDL -# ----------- -# Perform all the checks necessary for compilation of the ltdl objects -# -- including compiler checks and header checks. -AC_DEFUN([AC_LIB_LTDL], -[AC_PREREQ(2.50) -AC_REQUIRE([AC_PROG_CC]) -AC_REQUIRE([AC_C_CONST]) -AC_REQUIRE([AC_HEADER_STDC]) -AC_REQUIRE([AC_HEADER_DIRENT]) -AC_REQUIRE([_LT_AC_CHECK_DLFCN]) -AC_REQUIRE([AC_LTDL_ENABLE_INSTALL]) -AC_REQUIRE([AC_LTDL_SHLIBEXT]) -AC_REQUIRE([AC_LTDL_SHLIBPATH]) -AC_REQUIRE([AC_LTDL_SYSSEARCHPATH]) -AC_REQUIRE([AC_LTDL_OBJDIR]) -AC_REQUIRE([AC_LTDL_DLPREOPEN]) -AC_REQUIRE([AC_LTDL_DLLIB]) -AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) -AC_REQUIRE([AC_LTDL_DLSYM_USCORE]) -AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS]) -AC_REQUIRE([AC_LTDL_FUNC_ARGZ]) - -AC_CHECK_HEADERS([assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ - stdio.h unistd.h]) -AC_CHECK_HEADERS([dl.h sys/dl.h dld.h mach-o/dyld.h]) -AC_CHECK_HEADERS([string.h strings.h], [break]) - -AC_CHECK_FUNCS([strchr index], [break]) -AC_CHECK_FUNCS([strrchr rindex], [break]) -AC_CHECK_FUNCS([memcpy bcopy], [break]) -AC_CHECK_FUNCS([memmove strcmp]) -AC_CHECK_FUNCS([closedir opendir readdir]) -])# AC_LIB_LTDL - - -# AC_LTDL_ENABLE_INSTALL -# ---------------------- -AC_DEFUN([AC_LTDL_ENABLE_INSTALL], -[AC_ARG_ENABLE([ltdl-install], - [AC_HELP_STRING([--enable-ltdl-install], [install libltdl])]) - -AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) -AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno) -])])# AC_LTDL_ENABLE_INSTALL - - -# AC_LTDL_SYS_DLOPEN_DEPLIBS -# -------------------------- -AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], -[AC_REQUIRE([AC_CANONICAL_HOST]) -AC_CACHE_CHECK([whether deplibs are loaded by dlopen], - [libltdl_cv_sys_dlopen_deplibs], - [# PORTME does your system automatically load deplibs for dlopen? - # or its logical equivalent (e.g. shl_load for HP-UX < 11) - # For now, we just catch OSes we know something about -- in the - # future, we'll try test this programmatically. - libltdl_cv_sys_dlopen_deplibs=unknown - case "$host_os" in - aix3*|aix4.1.*|aix4.2.*) - # Unknown whether this is true for these versions of AIX, but - # we want this `case' here to explicitly catch those versions. - libltdl_cv_sys_dlopen_deplibs=unknown - ;; - aix[[45]]*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - darwin*) - # Assuming the user has installed a libdl from somewhere, this is true - # If you are looking for one http://www.opendarwin.org/projects/dlcompat - libltdl_cv_sys_dlopen_deplibs=yes - ;; - gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) - # GNU and its variants, using gnu ld.so (Glibc) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - hpux10*|hpux11*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - irix[[12345]]*|irix6.[[01]]*) - # Catch all versions of IRIX before 6.2, and indicate that we don't - # know how it worked for any of those versions. - libltdl_cv_sys_dlopen_deplibs=unknown - ;; - irix*) - # The case above catches anything before 6.2, and it's known that - # at 6.2 and later dlopen does load deplibs. - libltdl_cv_sys_dlopen_deplibs=yes - ;; - netbsd* | netbsdelf*-gnu) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - openbsd*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - osf[[1234]]*) - # dlopen did load deplibs (at least at 4.x), but until the 5.x series, - # it did *not* use an RPATH in a shared library to find objects the - # library depends on, so we explictly say `no'. - libltdl_cv_sys_dlopen_deplibs=no - ;; - osf5.0|osf5.0a|osf5.1) - # dlopen *does* load deplibs and with the right loader patch applied - # it even uses RPATH in a shared library to search for shared objects - # that the library depends on, but there's no easy way to know if that - # patch is installed. Since this is the case, all we can really - # say is unknown -- it depends on the patch being installed. If - # it is, this changes to `yes'. Without it, it would be `no'. - libltdl_cv_sys_dlopen_deplibs=unknown - ;; - osf*) - # the two cases above should catch all versions of osf <= 5.1. Read - # the comments above for what we know about them. - # At > 5.1, deplibs are loaded *and* any RPATH in a shared library - # is used to find them so we can finally say `yes'. - libltdl_cv_sys_dlopen_deplibs=yes - ;; - solaris*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - esac - ]) -if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then - AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], - [Define if the OS needs help to load dependent libraries for dlopen().]) -fi -])# AC_LTDL_SYS_DLOPEN_DEPLIBS - - -# AC_LTDL_SHLIBEXT -# ---------------- -AC_DEFUN([AC_LTDL_SHLIBEXT], -[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) -AC_CACHE_CHECK([which extension is used for loadable modules], - [libltdl_cv_shlibext], -[ -module=yes -eval libltdl_cv_shlibext=$shrext_cmds - ]) -if test -n "$libltdl_cv_shlibext"; then - AC_DEFINE_UNQUOTED(LTDL_SHLIB_EXT, "$libltdl_cv_shlibext", - [Define to the extension used for shared libraries, say, ".so".]) -fi -])# AC_LTDL_SHLIBEXT - - -# AC_LTDL_SHLIBPATH -# ----------------- -AC_DEFUN([AC_LTDL_SHLIBPATH], -[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) -AC_CACHE_CHECK([which variable specifies run-time library path], - [libltdl_cv_shlibpath_var], [libltdl_cv_shlibpath_var="$shlibpath_var"]) -if test -n "$libltdl_cv_shlibpath_var"; then - AC_DEFINE_UNQUOTED(LTDL_SHLIBPATH_VAR, "$libltdl_cv_shlibpath_var", - [Define to the name of the environment variable that determines the dynamic library search path.]) -fi -])# AC_LTDL_SHLIBPATH - - -# AC_LTDL_SYSSEARCHPATH -# --------------------- -AC_DEFUN([AC_LTDL_SYSSEARCHPATH], -[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) -AC_CACHE_CHECK([for the default library search path], - [libltdl_cv_sys_search_path], - [libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"]) -if test -n "$libltdl_cv_sys_search_path"; then - sys_search_path= - for dir in $libltdl_cv_sys_search_path; do - if test -z "$sys_search_path"; then - sys_search_path="$dir" - else - sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" - fi - done - AC_DEFINE_UNQUOTED(LTDL_SYSSEARCHPATH, "$sys_search_path", - [Define to the system default library search path.]) -fi -])# AC_LTDL_SYSSEARCHPATH - - -# AC_LTDL_OBJDIR -# -------------- -AC_DEFUN([AC_LTDL_OBJDIR], -[AC_CACHE_CHECK([for objdir], - [libltdl_cv_objdir], - [libltdl_cv_objdir="$objdir" - if test -n "$objdir"; then - : - else - rm -f .libs 2>/dev/null - mkdir .libs 2>/dev/null - if test -d .libs; then - libltdl_cv_objdir=.libs - else - # MS-DOS does not allow filenames that begin with a dot. - libltdl_cv_objdir=_libs - fi - rmdir .libs 2>/dev/null - fi - ]) -AC_DEFINE_UNQUOTED(LTDL_OBJDIR, "$libltdl_cv_objdir/", - [Define to the sub-directory in which libtool stores uninstalled libraries.]) -])# AC_LTDL_OBJDIR - - -# AC_LTDL_DLPREOPEN -# ----------------- -AC_DEFUN([AC_LTDL_DLPREOPEN], -[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) -AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], - [libltdl_cv_preloaded_symbols], - [if test -n "$lt_cv_sys_global_symbol_pipe"; then - libltdl_cv_preloaded_symbols=yes - else - libltdl_cv_preloaded_symbols=no - fi - ]) -if test x"$libltdl_cv_preloaded_symbols" = xyes; then - AC_DEFINE(HAVE_PRELOADED_SYMBOLS, 1, - [Define if libtool can extract symbol lists from object files.]) -fi -])# AC_LTDL_DLPREOPEN - - -# AC_LTDL_DLLIB -# ------------- -AC_DEFUN([AC_LTDL_DLLIB], -[LIBADD_DL= -AC_SUBST(LIBADD_DL) -AC_LANG_PUSH([C]) - -AC_CHECK_FUNC([shl_load], - [AC_DEFINE([HAVE_SHL_LOAD], [1], - [Define if you have the shl_load function.])], - [AC_CHECK_LIB([dld], [shl_load], - [AC_DEFINE([HAVE_SHL_LOAD], [1], - [Define if you have the shl_load function.]) - LIBADD_DL="$LIBADD_DL -ldld"], - [AC_CHECK_LIB([dl], [dlopen], - [AC_DEFINE([HAVE_LIBDL], [1], - [Define if you have the libdl library or equivalent.]) - LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"], - [AC_TRY_LINK([#if HAVE_DLFCN_H -# include -#endif - ], - [dlopen(0, 0);], - [AC_DEFINE([HAVE_LIBDL], [1], - [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"], - [AC_CHECK_LIB([svld], [dlopen], - [AC_DEFINE([HAVE_LIBDL], [1], - [Define if you have the libdl library or equivalent.]) - LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"], - [AC_CHECK_LIB([dld], [dld_link], - [AC_DEFINE([HAVE_DLD], [1], - [Define if you have the GNU dld library.]) - LIBADD_DL="$LIBADD_DL -ldld"], - [AC_CHECK_FUNC([_dyld_func_lookup], - [AC_DEFINE([HAVE_DYLD], [1], - [Define if you have the _dyld_func_lookup function.])]) - ]) - ]) - ]) - ]) - ]) -]) - -if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes -then - lt_save_LIBS="$LIBS" - LIBS="$LIBS $LIBADD_DL" - AC_CHECK_FUNCS([dlerror]) - LIBS="$lt_save_LIBS" -fi -AC_LANG_POP -])# AC_LTDL_DLLIB - - -# AC_LTDL_SYMBOL_USCORE -# --------------------- -# does the compiler prefix global symbols with an underscore? -AC_DEFUN([AC_LTDL_SYMBOL_USCORE], -[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) -AC_CACHE_CHECK([for _ prefix in compiled symbols], - [ac_cv_sys_symbol_underscore], - [ac_cv_sys_symbol_underscore=no - cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then - # See whether the symbols have a leading underscore. - if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then - ac_cv_sys_symbol_underscore=yes - else - if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then - : - else - echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC - fi - fi - else - echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC - fi - else - echo "configure: failed program was:" >&AC_FD_CC - cat conftest.c >&AC_FD_CC - fi - rm -rf conftest* - ]) -])# AC_LTDL_SYMBOL_USCORE - - -# AC_LTDL_DLSYM_USCORE -# -------------------- -AC_DEFUN([AC_LTDL_DLSYM_USCORE], -[AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) -if test x"$ac_cv_sys_symbol_underscore" = xyes; then - if test x"$libltdl_cv_func_dlopen" = xyes || - test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then - AC_CACHE_CHECK([whether we have to add an underscore for dlsym], - [libltdl_cv_need_uscore], - [libltdl_cv_need_uscore=unknown - save_LIBS="$LIBS" - LIBS="$LIBS $LIBADD_DL" - _LT_AC_TRY_DLOPEN_SELF( - [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], - [], [libltdl_cv_need_uscore=cross]) - LIBS="$save_LIBS" - ]) - fi -fi - -if test x"$libltdl_cv_need_uscore" = xyes; then - AC_DEFINE(NEED_USCORE, 1, - [Define if dlsym() requires a leading underscore in symbol names.]) -fi -])# AC_LTDL_DLSYM_USCORE - -# AC_LTDL_FUNC_ARGZ -# ----------------- -AC_DEFUN([AC_LTDL_FUNC_ARGZ], -[AC_CHECK_HEADERS([argz.h]) - -AC_CHECK_TYPES([error_t], - [], - [AC_DEFINE([error_t], [int], - [Define to a type to use for `error_t' if it is not otherwise available.])], - [#if HAVE_ARGZ_H -# include -#endif]) - -AC_CHECK_FUNCS([argz_append argz_create_sep argz_insert argz_next argz_stringify]) -])# AC_LTDL_FUNC_ARGZ From 9c96bdcf01798b9146d232019825ca5cc927648a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Jul 2006 13:25:35 +0000 Subject: [PATCH 0966/1514] * remove doc/ directory * move doc/todo to root dir git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1063 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 4 ++-- configure.ac | 1 - doc/Makefile.am | 20 -------------------- doc/todo => todo | 0 4 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 doc/Makefile.am rename doc/todo => todo (100%) diff --git a/Makefile.am b/Makefile.am index d5d9b52fa..566cec684 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,8 +17,8 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in README -SUBDIRS=libltdl src doc doxygen +EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in README todo +SUBDIRS=libltdl src doxygen MAINTAINERCLEANFILES = noinst_DATA = diff --git a/configure.ac b/configure.ac index 6b82effdb..300201f7c 100644 --- a/configure.ac +++ b/configure.ac @@ -677,7 +677,6 @@ libpulse-simple.pc libpulse-browse.pc libpulse-mainloop-glib.pc libpulse-mainloop-glib12.pc -doc/Makefile doxygen/Makefile doxygen/doxygen.conf src/pulse/version.h diff --git a/doc/Makefile.am b/doc/Makefile.am deleted file mode 100644 index 1e9fe2449..000000000 --- a/doc/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -# $Id$ - -# This file is part of PulseAudio. -# -# PulseAudio is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# PulseAudio is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with PulseAudio; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - -EXTRA_DIST = todo - diff --git a/doc/todo b/todo similarity index 100% rename from doc/todo rename to todo From 3428f0384def9f1b39889d6a06c3780820d8ec5c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Jul 2006 17:56:05 +0000 Subject: [PATCH 0967/1514] mark HAL for shams king git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1065 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/todo b/todo index 1ea40d3e1..978331f45 100644 --- a/todo +++ b/todo @@ -2,7 +2,7 @@ Post 0.9.0: - alsa mmap driver -- dbus/hal +- dbus/hal (Shams King is working on this one) - polish for starting polypaudio as root/system-wide instance - chroot() - module-tunnel: improve latency calculation From 81621641b77cfa897cb136e670b9defaa4642fff Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 15:51:49 +0000 Subject: [PATCH 0968/1514] check for avahi in configure.ac git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1066 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/configure.ac b/configure.ac index 300201f7c..eb6fa2d37 100644 --- a/configure.ac +++ b/configure.ac @@ -510,6 +510,37 @@ AC_SUBST(HOWL_LIBS) AC_SUBST(HAVE_HOWL) AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1]) +#### Avahi support (optional) #### + +AC_ARG_ENABLE([avahi], + AC_HELP_STRING([--disable-avahi], [Disable optional Avahi support]), + [ + case "${enableval}" in + yes) avahi=yes ;; + no) avahi=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-avahi) ;; + esac + ], + [avahi=auto]) + +if test "x${avahi}" != xno ; then + PKG_CHECK_MODULES(AVAHI, [ avahi-client >= 0.6.0 ], + HAVE_AVAHI=1, + [ + HAVE_AVAHI=0 + if test "x$avahi" = xyes ; then + AC_MSG_ERROR([*** Avahi support not found]) + fi + ]) +else + HAVE_AVAHI=0 +fi + +AC_SUBST(AVAHI_CFLAGS) +AC_SUBST(AVAHI_LIBS) +AC_SUBST(HAVE_AVAHI) +AM_CONDITIONAL([HAVE_AVAHI], [test "x$HAVE_AVAHI" = x1]) + ### LIBOIL #### PKG_CHECK_MODULES(LIBOIL, [ liboil-0.3 >= 0.3.0 ]) From 10f7a6457545320595574ad249a3e9e1dd56c481 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 15:52:34 +0000 Subject: [PATCH 0969/1514] make sure gccmacro.h and cdecl.h may be included at the same time as those headers from the avahi project git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1067 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/cdecl.h | 4 ++-- src/pulsecore/gccmacro.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pulse/cdecl.h b/src/pulse/cdecl.h index 6ac96687a..a3ec231cc 100644 --- a/src/pulse/cdecl.h +++ b/src/pulse/cdecl.h @@ -1,5 +1,5 @@ -#ifndef foocdeclhfoo -#define foocdeclhfoo +#ifndef foopulsecdeclhfoo +#define foopulsecdeclhfoo /* $Id$ */ diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h index 2ab999d90..8825700ad 100644 --- a/src/pulsecore/gccmacro.h +++ b/src/pulsecore/gccmacro.h @@ -1,5 +1,5 @@ -#ifndef foogccmacrohfoo -#define foogccmacrohfoo +#ifndef foopulsegccmacrohfoo +#define foopulsegccmacrohfoo /* $Id$ */ From 3a816205ffde85bcf06c9ff55febc1ba69ce8de9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 15:54:13 +0000 Subject: [PATCH 0970/1514] update module-zeroconf-publish to make use of the native AVAHI API, instead of HOWL git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1068 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 19 +- src/modules/module-zeroconf-publish.c | 430 ++++++++++++++++++-------- src/pulsecore/avahi-wrap.c | 188 +++++++++++ src/pulsecore/avahi-wrap.h | 33 ++ 4 files changed, 539 insertions(+), 131 deletions(-) create mode 100644 src/pulsecore/avahi-wrap.c create mode 100644 src/pulsecore/avahi-wrap.h diff --git a/src/Makefile.am b/src/Makefile.am index 2bd3b871d..8c8168d53 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -667,6 +667,14 @@ modlibexec_LTLIBRARIES += \ libx11prop.la endif +if HAVE_AVAHI +pulsecoreinclude_HEADERS += \ + pulsecore/avahi-wrap.h + +modlibexec_LTLIBRARIES += \ + libavahi-wrap.la +endif + libprotocol_simple_la_SOURCES = pulsecore/protocol-simple.c pulsecore/protocol-simple.h libprotocol_simple_la_LDFLAGS = -avoid-version libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-server.la libiochannel.la @@ -770,6 +778,13 @@ libx11prop_la_LDFLAGS = -avoid-version libx11prop_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) +# Avahi + +libavahi_wrap_la_SOURCES = pulsecore/avahi-wrap.c pulsecore/avahi-wrap.h +libavahi_wrap_la_LDFLAGS = -avoid-version +libavahi_wrap_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) +libavahi_wrap_la_LIBADD = $(AM_LIBADD) $(AVAHI_CFLAGS) libpulsecore.la + ################################### # Plug-in libraries # ################################### @@ -1105,8 +1120,8 @@ libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) module_zeroconf_publish_la_SOURCES = modules/module-zeroconf-publish.c module_zeroconf_publish_la_LDFLAGS = -module -avoid-version -module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la libpulsecore.la -module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) +module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(AVAHI_LIBS) libavahi-wrap.la libpulsecore.la +module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) # LIRC diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 32fb1f41b..23a188b3e 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -29,6 +29,11 @@ #include #include +#include +#include +#include +#include + #include #include @@ -41,10 +46,8 @@ #include #include #include - -#include "../pulsecore/endianmacros.h" - -#include "howl-wrap.h" +#include +#include #include "module-zeroconf-publish-symdef.h" @@ -53,9 +56,9 @@ PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("port=") -#define SERVICE_NAME_SINK "_pulse-sink._tcp" -#define SERVICE_NAME_SOURCE "_pulse-source._tcp" -#define SERVICE_NAME_SERVER "_pulse-server._tcp" +#define SERVICE_TYPE_SINK "_pulse-sink._tcp" +#define SERVICE_TYPE_SOURCE "_pulse-source._tcp" +#define SERVICE_TYPE_SERVER "_pulse-server._tcp" static const char* const valid_modargs[] = { "port", @@ -63,9 +66,11 @@ static const char* const valid_modargs[] = { }; struct service { - sw_discovery_oid oid; + struct userdata *userdata; + AvahiEntryGroup *entry_group; + char *service_name; char *name; - int published; /* 0 -> not yet registered, 1 -> registered with data from real device, 2 -> registered with data from autoload device */ + enum { UNPUBLISHED, PUBLISHED_REAL, PUBLISHED_AUTOLOAD } published ; struct { int valid; @@ -82,19 +87,18 @@ struct service { struct userdata { pa_core *core; - pa_howl_wrapper *howl_wrapper; + AvahiPoll *avahi_poll; + AvahiClient *client; pa_hashmap *services; pa_dynarray *sink_dynarray, *source_dynarray, *autoload_dynarray; pa_subscription *subscription; + char *service_name; + + AvahiEntryGroup *main_entry_group; uint16_t port; - sw_discovery_oid server_oid; }; -static sw_result publish_reply(sw_discovery discovery, sw_discovery_publish_status status, sw_discovery_oid oid, sw_opaque extra) { - return SW_OKAY; -} - static void get_service_data(struct userdata *u, struct service *s, pa_sample_spec *ret_ss, char **ret_description) { assert(u && s && s->loaded.valid && ret_ss && ret_description); @@ -112,109 +116,144 @@ static void get_service_data(struct userdata *u, struct service *s, pa_sample_sp assert(0); } -static void txt_record_server_data(pa_core *c, sw_text_record t) { - char s[256]; +static AvahiStringList* txt_record_server_data(pa_core *c, AvahiStringList *l) { + char s[128]; assert(c); - sw_text_record_add_key_and_string_value(t, "server-version", PACKAGE_NAME" "PACKAGE_VERSION); - sw_text_record_add_key_and_string_value(t, "user-name", pa_get_user_name(s, sizeof(s))); - sw_text_record_add_key_and_string_value(t, "fqdn", pa_get_fqdn(s, sizeof(s))); - snprintf(s, sizeof(s), "0x%08x", c->cookie); - sw_text_record_add_key_and_string_value(t, "cookie", s); + l = avahi_string_list_add_pair(l, "server-version", PACKAGE_NAME" "PACKAGE_VERSION); + l = avahi_string_list_add_pair(l, "user-name", pa_get_user_name(s, sizeof(s))); + l = avahi_string_list_add_pair(l, "fqdn", pa_get_fqdn(s, sizeof(s))); + l = avahi_string_list_add_printf(l, "cookie=0x%08x", c->cookie); + + return l; +} + +static int publish_service(struct userdata *u, struct service *s); + +static void service_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) { + struct service *s = userdata; + + if (state == AVAHI_ENTRY_GROUP_COLLISION) { + char *t; + + t = avahi_alternative_service_name(s->service_name); + pa_xfree(s->service_name); + s->service_name = t; + + publish_service(s->userdata, s); + } } static int publish_service(struct userdata *u, struct service *s) { - char t[256]; - char hn[256]; int r = -1; - sw_text_record txt; - int free_txt = 0; - assert(u && s); - - if ((s->published == 1 && s->loaded.valid) || - (s->published == 2 && s->autoload.valid && !s->loaded.valid)) + AvahiStringList *txt = NULL; + + assert(u); + assert(s); + + if (!u->client || avahi_client_get_state(u->client) != AVAHI_CLIENT_S_RUNNING) + return 0; + + if ((s->published == PUBLISHED_REAL && s->loaded.valid) || + (s->published == PUBLISHED_AUTOLOAD && s->autoload.valid && !s->loaded.valid)) return 0; - if (s->published) { - sw_discovery_cancel(pa_howl_wrapper_get_discovery(u->howl_wrapper), s->oid); - s->published = 0; - } - - snprintf(t, sizeof(t), "%s on %s", s->name, pa_get_host_name(hn, sizeof(hn))); - - if (sw_text_record_init(&txt) != SW_OKAY) { - pa_log(__FILE__": sw_text_record_init() failed"); - goto finish; - } - free_txt = 1; - - sw_text_record_add_key_and_string_value(txt, "device", s->name); - - txt_record_server_data(u->core, txt); + if (s->published != UNPUBLISHED) { + avahi_entry_group_reset(s->entry_group); + s->published = UNPUBLISHED; + } - if (s->loaded.valid) { - char z[64], *description; - pa_sample_spec ss; + if (s->loaded.valid || s->autoload.valid) { + pa_namereg_type_t type; - get_service_data(u, s, &ss, &description); + if (!s->entry_group) { + if (!(s->entry_group = avahi_entry_group_new(u->client, service_entry_group_callback, s))) { + pa_log("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(u->client))); + goto finish; + } + } + + txt = avahi_string_list_add_pair(txt, "device", s->name); + txt = txt_record_server_data(u->core, txt); + + if (s->loaded.valid) { + char *description; + pa_sample_spec ss; - snprintf(z, sizeof(z), "%u", ss.rate); - sw_text_record_add_key_and_string_value(txt, "rate", z); - snprintf(z, sizeof(z), "%u", ss.channels); - sw_text_record_add_key_and_string_value(txt, "channels", z); - sw_text_record_add_key_and_string_value(txt, "format", pa_sample_format_to_string(ss.format)); - - sw_text_record_add_key_and_string_value(txt, "description", description); - - if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t, - s->loaded.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE, - NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt), - publish_reply, s, &s->oid) != SW_OKAY) { - pa_log(__FILE__": failed to register sink on zeroconf."); + get_service_data(u, s, &ss, &description); + + txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate); + txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels); + txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format)); + txt = avahi_string_list_add_pair(txt, "description", description); + + type = s->loaded.type; + } else if (s->autoload.valid) + type = s->autoload.type; + + if (avahi_entry_group_add_service_strlst( + s->entry_group, + AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + 0, + s->service_name, + type == PA_NAMEREG_SINK ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE, + NULL, + NULL, + u->port, + txt) < 0) { + + pa_log(__FILE__": avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(u->client))); goto finish; } - - s->published = 1; - } else if (s->autoload.valid) { - - if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t, - s->autoload.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE, - NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt), - publish_reply, s, &s->oid) != SW_OKAY) { - pa_log(__FILE__": failed to register sink on zeroconf."); + + if (avahi_entry_group_commit(s->entry_group) < 0) { + pa_log(__FILE__": avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(u->client))); goto finish; } - - s->published = 2; + + if (s->loaded.valid) + s->published = PUBLISHED_REAL; + else if (s->autoload.valid) + s->published = PUBLISHED_AUTOLOAD; } - + r = 0; finish: - if (!s->published) { + if (s->published == UNPUBLISHED) { /* Remove this service */ + + if (s->entry_group) { + avahi_entry_group_free(s->entry_group); + } + pa_hashmap_remove(u->services, s->name); pa_xfree(s->name); + pa_xfree(s->service_name); pa_xfree(s); } - if (free_txt) - sw_text_record_fina(txt); + if (txt) + avahi_string_list_free(txt); return r; } static struct service *get_service(struct userdata *u, const char *name) { struct service *s; + char hn[64]; if ((s = pa_hashmap_get(u->services, name))) return s; - s = pa_xmalloc(sizeof(struct service)); - s->published = 0; + s = pa_xnew(struct service, 1); + s->userdata = u; + s->entry_group = NULL; + s->published = UNPUBLISHED; s->name = pa_xstrdup(name); s->loaded.valid = s->autoload.valid = 0; + s->service_name = pa_sprintf_malloc("%s on %s", s->name, pa_get_host_name(hn, sizeof(hn))); pa_hashmap_put(u->services, s->name, s); @@ -227,7 +266,7 @@ static int publish_sink(struct userdata *u, pa_sink *s) { svc = get_service(u, s->name); if (svc->loaded.valid) - return 0; + return publish_service(u, svc); svc->loaded.valid = 1; svc->loaded.type = PA_NAMEREG_SINK; @@ -244,7 +283,7 @@ static int publish_source(struct userdata *u, pa_source *s) { svc = get_service(u, s->name); if (svc->loaded.valid) - return 0; + return publish_service(u, svc); svc->loaded.valid = 1; svc->loaded.type = PA_NAMEREG_SOURCE; @@ -261,7 +300,7 @@ static int publish_autoload(struct userdata *u, pa_autoload_entry *s) { svc = get_service(u, s->name); if (svc->autoload.valid) - return 0; + return publish_service(u, svc); svc->autoload.valid = 1; svc->autoload.type = s->type; @@ -381,16 +420,164 @@ fail: } } -int pa__init(pa_core *c, pa_module*m) { - struct userdata *u; - uint32_t idx, port = PA_NATIVE_DEFAULT_PORT; +static int publish_main_service(struct userdata *u); + +static void main_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) { + struct userdata *u = userdata; + assert(u); + + if (state == AVAHI_ENTRY_GROUP_COLLISION) { + char *t; + + t = avahi_alternative_service_name(u->service_name); + pa_xfree(u->service_name); + u->service_name = t; + + publish_main_service(u); + } +} + +static int publish_main_service(struct userdata *u) { + AvahiStringList *txt = NULL; + int r = -1; + + if (!u->main_entry_group) { + if (!(u->main_entry_group = avahi_entry_group_new(u->client, main_entry_group_callback, u))) { + pa_log(__FILE__": avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); + goto fail; + } + } else + avahi_entry_group_reset(u->main_entry_group); + + txt = txt_record_server_data(u->core, NULL); + + if (avahi_entry_group_add_service_strlst( + u->main_entry_group, + AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + 0, + u->service_name, + SERVICE_TYPE_SERVER, + NULL, + NULL, + u->port, + txt) < 0) { + + pa_log(__FILE__": avahi_entry_group_add_service_strlst() failed: %s", avahi_strerror(avahi_client_errno(u->client))); + goto fail; + } + + if (avahi_entry_group_commit(u->main_entry_group) < 0) { + pa_log(__FILE__": avahi_entry_group_commit() failed: %s", avahi_strerror(avahi_client_errno(u->client))); + goto fail; + } + + r = 0; + +fail: + avahi_string_list_free(txt); + + return r; +} + +static int publish_all_services(struct userdata *u) { pa_sink *sink; pa_source *source; pa_autoload_entry *autoload; + int r = -1; + uint32_t idx; + + assert(u); + + pa_log_debug(__FILE__": Publishing services in Zeroconf"); + + for (sink = pa_idxset_first(u->core->sinks, &idx); sink; sink = pa_idxset_next(u->core->sinks, &idx)) + if (publish_sink(u, sink) < 0) + goto fail; + + for (source = pa_idxset_first(u->core->sources, &idx); source; source = pa_idxset_next(u->core->sources, &idx)) + if (publish_source(u, source) < 0) + goto fail; + + if (u->core->autoload_idxset) + for (autoload = pa_idxset_first(u->core->autoload_idxset, &idx); autoload; autoload = pa_idxset_next(u->core->autoload_idxset, &idx)) + if (publish_autoload(u, autoload) < 0) + goto fail; + + if (publish_main_service(u) < 0) + goto fail; + + r = 0; + +fail: + return r; +} + +static void unpublish_all_services(struct userdata *u, int rem) { + void *state = NULL; + struct service *s; + + assert(u); + + pa_log_debug(__FILE__": Unpublishing services in Zeroconf"); + + while ((s = pa_hashmap_iterate(u->services, &state, NULL))) { + if (s->entry_group) { + if (rem) { + avahi_entry_group_free(s->entry_group); + s->entry_group = NULL; + } else + avahi_entry_group_reset(s->entry_group); + } + + s->published = UNPUBLISHED; + } + + if (u->main_entry_group) { + if (rem) { + avahi_entry_group_free(u->main_entry_group); + u->main_entry_group = NULL; + } else + avahi_entry_group_reset(u->main_entry_group); + } +} + +static void client_callback(AvahiClient *c, AvahiClientState state, void *userdata) { + struct userdata *u = userdata; + assert(c); + + u->client = c; + + switch (state) { + case AVAHI_CLIENT_S_RUNNING: + publish_all_services(u); + break; + + case AVAHI_CLIENT_S_COLLISION: + unpublish_all_services(u, 0); + break; + + case AVAHI_CLIENT_FAILURE: + if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) { + int error; + unpublish_all_services(u, 1); + avahi_client_free(u->client); + + if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) + pa_log(__FILE__": pa_avahi_client_new() failed: %s", avahi_strerror(error)); + } + + break; + + default: ; + } +} + +int pa__init(pa_core *c, pa_module*m) { + struct userdata *u; + uint32_t port = PA_NATIVE_DEFAULT_PORT; pa_modargs *ma = NULL; - char t[256], hn[256]; - int free_txt = 0; - sw_text_record txt; + char hn[256]; + int error; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments."); @@ -402,55 +589,31 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - m->userdata = u = pa_xmalloc(sizeof(struct userdata)); + m->userdata = u = pa_xnew(struct userdata, 1); u->core = c; u->port = (uint16_t) port; - if (!(u->howl_wrapper = pa_howl_wrapper_get(c))) - goto fail; - + u->avahi_poll = pa_avahi_poll_new(c->mainloop); + u->services = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); u->sink_dynarray = pa_dynarray_new(); u->source_dynarray = pa_dynarray_new(); u->autoload_dynarray = pa_dynarray_new(); - + u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK| PA_SUBSCRIPTION_MASK_SOURCE| PA_SUBSCRIPTION_MASK_AUTOLOAD, subscribe_callback, u); - for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) - if (publish_sink(u, sink) < 0) - goto fail; + u->main_entry_group = NULL; - for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) - if (publish_source(u, source) < 0) - goto fail; + u->service_name = pa_xstrdup(pa_get_host_name(hn, sizeof(hn))); - if (c->autoload_idxset) - for (autoload = pa_idxset_first(c->autoload_idxset, &idx); autoload; autoload = pa_idxset_next(c->autoload_idxset, &idx)) - if (publish_autoload(u, autoload) < 0) - goto fail; - - snprintf(t, sizeof(t), "%s", pa_get_host_name(hn, sizeof(hn))); - - if (sw_text_record_init(&txt) != SW_OKAY) { - pa_log(__FILE__": sw_text_record_init() failed"); + if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { + pa_log(__FILE__": pa_avahi_client_new() failed: %s", avahi_strerror(error)); goto fail; } - free_txt = 1; - txt_record_server_data(u->core, txt); - - if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t, - SERVICE_NAME_SERVER, - NULL, NULL, u->port, sw_text_record_bytes(txt), sw_text_record_len(txt), - publish_reply, u, &u->server_oid) != SW_OKAY) { - pa_log(__FILE__": failed to register server on zeroconf."); - goto fail; - } - - sw_text_record_fina(txt); pa_modargs_free(ma); return 0; @@ -460,9 +623,6 @@ fail: if (ma) pa_modargs_free(ma); - - if (free_txt) - sw_text_record_fina(txt); return -1; } @@ -470,8 +630,14 @@ fail: static void service_free(void *p, void *userdata) { struct service *s = p; struct userdata *u = userdata; - assert(s && u); - sw_discovery_cancel(pa_howl_wrapper_get_discovery(u->howl_wrapper), s->oid); + + assert(s); + assert(u); + + if (s->entry_group) + avahi_entry_group_free(s->entry_group); + + pa_xfree(s->service_name); pa_xfree(s->name); pa_xfree(s); } @@ -495,11 +661,17 @@ void pa__done(pa_core *c, pa_module*m) { if (u->subscription) pa_subscription_free(u->subscription); - - if (u->howl_wrapper) - pa_howl_wrapper_unref(u->howl_wrapper); + if (u->main_entry_group) + avahi_entry_group_free(u->main_entry_group); + if (u->client) + avahi_client_free(u->client); + + if (u->avahi_poll) + pa_avahi_poll_free(u->avahi_poll); + + pa_xfree(u->service_name); pa_xfree(u); } diff --git a/src/pulsecore/avahi-wrap.c b/src/pulsecore/avahi-wrap.c new file mode 100644 index 000000000..9da765589 --- /dev/null +++ b/src/pulsecore/avahi-wrap.c @@ -0,0 +1,188 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include + +#include + +#include "avahi-wrap.h" + +typedef struct { + AvahiPoll api; + pa_mainloop_api *mainloop; +} pa_avahi_poll; + +struct AvahiWatch { + pa_io_event *io_event; + pa_avahi_poll *avahi_poll; + AvahiWatchEvent current_event; + AvahiWatchCallback callback; + void *userdata; +}; + +static AvahiWatchEvent translate_io_flags_back(pa_io_event_flags_t e) { + return + (e & PA_IO_EVENT_INPUT ? AVAHI_WATCH_IN : 0) | + (e & PA_IO_EVENT_OUTPUT ? AVAHI_WATCH_OUT : 0) | + (e & PA_IO_EVENT_ERROR ? AVAHI_WATCH_ERR : 0) | + (e & PA_IO_EVENT_HANGUP ? AVAHI_WATCH_HUP : 0); +} + +static pa_io_event_flags_t translate_io_flags(AvahiWatchEvent e) { + return + (e & AVAHI_WATCH_IN ? PA_IO_EVENT_INPUT : 0) | + (e & AVAHI_WATCH_OUT ? PA_IO_EVENT_OUTPUT : 0) | + (e & AVAHI_WATCH_ERR ? PA_IO_EVENT_ERROR : 0) | + (e & AVAHI_WATCH_HUP ? PA_IO_EVENT_HANGUP : 0); +} + +static void watch_callback(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) { + AvahiWatch *w = userdata; + + assert(a); + assert(e); + assert(w); + + w->current_event = translate_io_flags_back(events); + w->callback(w, fd, w->current_event, w->userdata); + w->current_event = 0; +} + +static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) { + pa_avahi_poll *p; + AvahiWatch *w; + + assert(api); + assert(fd >= 0); + assert(callback); + + p = api->userdata; + assert(p); + + w = pa_xnew(AvahiWatch, 1); + w->avahi_poll = p; + w->current_event = 0; + w->callback = callback; + w->userdata = userdata; + w->io_event = p->mainloop->io_new(p->mainloop, fd, translate_io_flags(event), watch_callback, w); + + return w; +} + +static void watch_update(AvahiWatch *w, AvahiWatchEvent event) { + assert(w); + + w->avahi_poll->mainloop->io_enable(w->io_event, translate_io_flags(event)); +} + +static AvahiWatchEvent watch_get_events(AvahiWatch *w) { + assert(w); + + return w->current_event; +} + +static void watch_free(AvahiWatch *w) { + assert(w); + + w->avahi_poll->mainloop->io_free(w->io_event); + pa_xfree(w); +} + +struct AvahiTimeout { + pa_time_event *time_event; + pa_avahi_poll *avahi_poll; + AvahiTimeoutCallback callback; + void *userdata; +}; + +static void timeout_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) { + AvahiTimeout *t = userdata; + + assert(a); + assert(e); + assert(t); + + t->callback(t, t->userdata); +} + +static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata) { + pa_avahi_poll *p; + AvahiTimeout *t; + + assert(api); + assert(callback); + + p = api->userdata; + assert(p); + + t = pa_xnew(AvahiTimeout, 1); + t->avahi_poll = p; + t->callback = callback; + t->userdata = userdata; + t->time_event = p->mainloop->time_new(p->mainloop, tv, timeout_callback, t); + + return t; +} + +static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { + assert(t); + + t->avahi_poll->mainloop->time_restart(t->time_event, tv); +} + +static void timeout_free(AvahiTimeout *t) { + assert(t); + + t->avahi_poll->mainloop->time_free(t->time_event); + pa_xfree(t); +} + +AvahiPoll* pa_avahi_poll_new(pa_mainloop_api *m) { + pa_avahi_poll *p; + + assert(m); + + p = pa_xnew(pa_avahi_poll, 1); + + p->api.userdata = p; + p->api.watch_new = watch_new; + p->api.watch_update = watch_update; + p->api.watch_get_events = watch_get_events; + p->api.watch_free = watch_free; + p->api.timeout_new = timeout_new; + p->api.timeout_update = timeout_update; + p->api.timeout_free = timeout_free; + p->mainloop = m; + + return &p->api; +} + +void pa_avahi_poll_free(AvahiPoll *api) { + pa_avahi_poll *p; + assert(api); + p = api->userdata; + assert(p); + + pa_xfree(p); +} + diff --git a/src/pulsecore/avahi-wrap.h b/src/pulsecore/avahi-wrap.h new file mode 100644 index 000000000..97da11eb9 --- /dev/null +++ b/src/pulsecore/avahi-wrap.h @@ -0,0 +1,33 @@ +#ifndef fooavahiwrapperhfoo +#define fooavahiwrapperhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include + +AvahiPoll* pa_avahi_poll_new(pa_mainloop_api *api); +void pa_avahi_poll_free(AvahiPoll *p); + + +#endif From 76f93a07f9d683c3484ff3a71857fe30bedcfd46 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 17:33:44 +0000 Subject: [PATCH 0971/1514] * port libpulse-browse to use the native avahi API instead of the HOWL cruft * add new function pa_browser_set_error_callback() * add doxygen docs to browser.h git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1069 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 22 +- src/pulse/browser.c | 449 ++++++++++++++++++++++--------------- src/pulse/browser.h | 62 +++-- src/pulsecore/avahi-wrap.h | 1 - 4 files changed, 328 insertions(+), 206 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 8c8168d53..fad01e08d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -140,7 +140,7 @@ if HAVE_X11 bin_PROGRAMS += pax11publish endif -if HAVE_HOWL +if HAVE_AVAHI bin_PROGRAMS += pabrowse endif @@ -319,7 +319,7 @@ pulseinclude_HEADERS = \ pulse/volume.h \ pulse/xmalloc.h -if HAVE_HOWL +if HAVE_AVAHI pulseinclude_HEADERS += \ pulse/browser.h endif @@ -338,7 +338,7 @@ lib_LTLIBRARIES = \ libpulse.la \ libpulse-simple.la -if HAVE_HOWL +if HAVE_AVAHI lib_LTLIBRARIES += \ libpulse-browse.la endif @@ -444,9 +444,9 @@ libpulse_simple_la_CFLAGS = $(AM_CFLAGS) libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la libpulse_simple_la_LDFLAGS = -version-info $(LIBPULSE_SIMPLE_VERSION_INFO) -libpulse_browse_la_SOURCES = pulse/browser.c pulse/browser.h -libpulse_browse_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) -libpulse_browse_la_LIBADD = $(AM_LIBADD) libpulse.la $(HOWL_LIBS) +libpulse_browse_la_SOURCES = pulse/browser.c pulse/browser.h pulsecore/avahi-wrap.c pulsecore/avahi-wrap.h +libpulse_browse_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) +libpulse_browse_la_LIBADD = $(AM_LIBADD) libpulse.la $(AVAHI_LIBS) libpulse_browse_la_LDFLAGS = -version-info $(LIBPULSE_BROWSE_VERSION_INFO) libpulse_mainloop_glib_la_SOURCES = pulse/glib-mainloop.h pulse/glib-mainloop.c @@ -864,9 +864,8 @@ modlibexec_LTLIBRARIES += \ module-solaris.la endif -if HAVE_HOWL +if HAVE_AVAHI modlibexec_LTLIBRARIES += \ - libhowl-wrap.la \ module-zeroconf-publish.la endif @@ -1111,12 +1110,7 @@ module_solaris_la_SOURCES = modules/module-solaris.c module_solaris_la_LDFLAGS = -module -avoid-version module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la -# HOWL - -libhowl_wrap_la_SOURCES = modules/howl-wrap.c modules/howl-wrap.h -libhowl_wrap_la_LDFLAGS = -avoid-version -libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libpulsecore.la -libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS) +# Avahi module_zeroconf_publish_la_SOURCES = modules/module-zeroconf-publish.c module_zeroconf_publish_la_LDFLAGS = -module -avoid-version diff --git a/src/pulse/browser.c b/src/pulse/browser.c index 60c71090b..dae8e3d51 100644 --- a/src/pulse/browser.c +++ b/src/pulse/browser.c @@ -24,85 +24,68 @@ #endif #include -#include +#include + +#include +#include +#include #include #include #include +#include + #include "browser.h" -#define SERVICE_NAME_SINK "_pulse-sink._tcp." -#define SERVICE_NAME_SOURCE "_pulse-source._tcp." -#define SERVICE_NAME_SERVER "_pulse-server._tcp." +#define SERVICE_TYPE_SINK "_pulse-sink._tcp." +#define SERVICE_TYPE_SOURCE "_pulse-source._tcp." +#define SERVICE_TYPE_SERVER "_pulse-server._tcp." struct pa_browser { int ref; pa_mainloop_api *mainloop; + AvahiPoll* avahi_poll; pa_browse_cb_t callback; void *userdata; + + pa_browser_error_cb_t error_callback; + void *error_userdata; + + AvahiClient *client; + AvahiServiceBrowser *server_browser, *sink_browser, *source_browser; - sw_discovery discovery; - pa_io_event *io_event; }; -static void io_callback(pa_mainloop_api*a, PA_GCC_UNUSED pa_io_event*e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void *userdata) { - pa_browser *b = userdata; - assert(a && b && b->mainloop == a); - - if (events != PA_IO_EVENT_INPUT || sw_discovery_read_socket(b->discovery) != SW_OKAY) { - pa_log(__FILE__": connection to HOWL daemon failed."); - b->mainloop->io_free(b->io_event); - b->io_event = NULL; - return; - } -} - -static int type_equal(const char *a, const char *b) { - size_t la, lb; - - if (strcasecmp(a, b) == 0) - return 1; - - la = strlen(a); - lb = strlen(b); - - if (la > 0 && a[la-1] == '.' && la == lb+1 && strncasecmp(a, b, la-1) == 0) - return 1; - - if (lb > 0 && b[lb-1] == '.' && lb == la+1 && strncasecmp(a, b, lb-1) == 0) - return 1; - - return 0; -} - static int map_to_opcode(const char *type, int new) { - if (type_equal(type, SERVICE_NAME_SINK)) + if (avahi_domain_equal(type, SERVICE_TYPE_SINK)) return new ? PA_BROWSE_NEW_SINK : PA_BROWSE_REMOVE_SINK; - else if (type_equal(type, SERVICE_NAME_SOURCE)) + else if (avahi_domain_equal(type, SERVICE_TYPE_SOURCE)) return new ? PA_BROWSE_NEW_SOURCE : PA_BROWSE_REMOVE_SOURCE; - else if (type_equal(type, SERVICE_NAME_SERVER)) + else if (avahi_domain_equal(type, SERVICE_TYPE_SERVER)) return new ? PA_BROWSE_NEW_SERVER : PA_BROWSE_REMOVE_SERVER; return -1; } -static sw_result resolve_reply( - sw_discovery discovery, - sw_discovery_oid oid, - sw_uint32 interface_index, - sw_const_string name, - sw_const_string type, - sw_const_string domain, - sw_ipv4_address address, - sw_port port, - sw_octets text_record, - sw_ulong text_record_len, - sw_opaque extra) { +static void resolve_callback( + AvahiServiceResolver *r, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiResolverEvent event, + const char *name, + const char *type, + const char *domain, + const char *host_name, + const AvahiAddress *aa, + uint16_t port, + AvahiStringList *txt, + AvahiLookupResultFlags flags, + void *userdata) { - pa_browser *b = extra; + pa_browser *b = userdata; pa_browse_info i; char ip[256], a[256]; int opcode; @@ -110,100 +93,96 @@ static sw_result resolve_reply( uint32_t cookie; pa_sample_spec ss; int ss_valid = 0; - sw_text_record_iterator iterator; - int free_iterator = 0; - char *c = NULL; + char *key = NULL, *value = NULL; assert(b); - sw_discovery_cancel(discovery, oid); - memset(&i, 0, sizeof(i)); i.name = name; - + + if (event != AVAHI_RESOLVER_FOUND) + goto fail; + if (!b->callback) goto fail; opcode = map_to_opcode(type, 1); assert(opcode >= 0); - - snprintf(a, sizeof(a), "tcp:%s:%u", sw_ipv4_address_name(address, ip, sizeof(ip)), port); + + if (aa->proto == AVAHI_PROTO_INET) + snprintf(a, sizeof(a), "tcp:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port); + else { + assert(aa->proto == AVAHI_PROTO_INET6); + snprintf(a, sizeof(a), "tcp6:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port); + } i.server = a; - - if (text_record && text_record_len) { - char key[SW_TEXT_RECORD_MAX_LEN]; - uint8_t val[SW_TEXT_RECORD_MAX_LEN]; - uint32_t val_len; + + + while (txt) { + + if (avahi_string_list_get_pair(txt, &key, &value, NULL) < 0) + break; - if (sw_text_record_iterator_init(&iterator, text_record, text_record_len) != SW_OKAY) { - pa_log_error(__FILE__": sw_text_record_string_iterator_init() failed."); - goto fail; - } - - free_iterator = 1; - - while (sw_text_record_iterator_next(iterator, key, val, &val_len) == SW_OKAY) { - c = pa_xstrndup((char*) val, val_len); + if (!strcmp(key, "device")) { + device_found = 1; + pa_xfree((char*) i.device); + i.device = value; + value = NULL; + } else if (!strcmp(key, "server-version")) { + pa_xfree((char*) i.server_version); + i.server_version = value; + value = NULL; + } else if (!strcmp(key, "user-name")) { + pa_xfree((char*) i.user_name); + i.user_name = value; + value = NULL; + } else if (!strcmp(key, "fqdn")) { + size_t l; - if (!strcmp(key, "device")) { - device_found = 1; - pa_xfree((char*) i.device); - i.device = c; - c = NULL; - } else if (!strcmp(key, "server-version")) { - pa_xfree((char*) i.server_version); - i.server_version = c; - c = NULL; - } else if (!strcmp(key, "user-name")) { - pa_xfree((char*) i.user_name); - i.user_name = c; - c = NULL; - } else if (!strcmp(key, "fqdn")) { - size_t l; + pa_xfree((char*) i.fqdn); + i.fqdn = value; + value = NULL; - pa_xfree((char*) i.fqdn); - i.fqdn = c; - c = NULL; - - l = strlen(a); - assert(l+1 <= sizeof(a)); - strncat(a, " ", sizeof(a)-l-1); - strncat(a, i.fqdn, sizeof(a)-l-2); - } else if (!strcmp(key, "cookie")) { + l = strlen(a); + assert(l+1 <= sizeof(a)); + strncat(a, " ", sizeof(a)-l-1); + strncat(a, i.fqdn, sizeof(a)-l-2); + } else if (!strcmp(key, "cookie")) { - if (pa_atou(c, &cookie) < 0) - goto fail; - - i.cookie = &cookie; - } else if (!strcmp(key, "description")) { - pa_xfree((char*) i.description); - i.description = c; - c = NULL; - } else if (!strcmp(key, "channels")) { - uint32_t ch; - - if (pa_atou(c, &ch) < 0 || ch <= 0 || ch > 255) - goto fail; + if (pa_atou(value, &cookie) < 0) + goto fail; + + i.cookie = &cookie; + } else if (!strcmp(key, "description")) { + pa_xfree((char*) i.description); + i.description = value; + value = NULL; + } else if (!strcmp(key, "channels")) { + uint32_t ch; + + if (pa_atou(value, &ch) < 0 || ch <= 0 || ch > 255) + goto fail; + + ss.channels = (uint8_t) ch; + ss_valid |= 1; + + } else if (!strcmp(key, "rate")) { + if (pa_atou(value, &ss.rate) < 0) + goto fail; + ss_valid |= 2; + } else if (!strcmp(key, "format")) { - ss.channels = (uint8_t) ch; - ss_valid |= 1; - - } else if (!strcmp(key, "rate")) { - if (pa_atou(c, &ss.rate) < 0) - goto fail; - ss_valid |= 2; - } else if (!strcmp(key, "format")) { - - if ((ss.format = pa_parse_sample_format(c)) == PA_SAMPLE_INVALID) - goto fail; - - ss_valid |= 4; - } - - pa_xfree(c); - c = NULL; + if ((ss.format = pa_parse_sample_format(value)) == PA_SAMPLE_INVALID) + goto fail; + + ss_valid |= 4; } - + + pa_xfree(key); + pa_xfree(value); + key = value = NULL; + + txt = avahi_string_list_get_next(txt); } /* No device txt record was sent for a sink or source service */ @@ -212,7 +191,6 @@ static sw_result resolve_reply( if (ss_valid == 7) i.sample_spec = &ss; - b->callback(b, opcode, &i, b->userdata); @@ -222,39 +200,72 @@ fail: pa_xfree((void*) i.server_version); pa_xfree((void*) i.user_name); pa_xfree((void*) i.description); - pa_xfree(c); - - if (free_iterator) - sw_text_record_iterator_fina(iterator); + pa_xfree(key); + pa_xfree(value); - return SW_OKAY; + avahi_service_resolver_free(r); } -static sw_result browse_reply( - sw_discovery discovery, - sw_discovery_oid id, - sw_discovery_browse_status status, - sw_uint32 interface_index, - sw_const_string name, - sw_const_string type, - sw_const_string domain, - sw_opaque extra) { - - pa_browser *b = extra; +static void handle_failure(pa_browser *b) { + const char *e = NULL; assert(b); - switch (status) { - case SW_DISCOVERY_BROWSE_ADD_SERVICE: { - sw_discovery_oid oid; + if (b->sink_browser) + avahi_service_browser_free(b->sink_browser); + if (b->source_browser) + avahi_service_browser_free(b->source_browser); + if (b->server_browser) + avahi_service_browser_free(b->server_browser); - if (sw_discovery_resolve(b->discovery, 0, name, type, domain, resolve_reply, b, &oid) != SW_OKAY) - pa_log_error(__FILE__": sw_discovery_resolve() failed"); + b->sink_browser = b->source_browser = b->server_browser = NULL; + + if (b->client) { + e = avahi_strerror(avahi_client_errno(b->client)); + avahi_client_free(b->client); + } + + b->client = NULL; + + if (b->error_callback) + b->error_callback(b, e, b->error_userdata); +} + +static void browse_callback( + AvahiServiceBrowser *sb, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiBrowserEvent event, + const char *name, + const char *type, + const char *domain, + AvahiLookupResultFlags flags, + void *userdata) { + + pa_browser *b = userdata; + assert(b); + + switch (event) { + case AVAHI_BROWSER_NEW: { + + if (!avahi_service_resolver_new( + b->client, + interface, + protocol, + name, + type, + domain, + AVAHI_PROTO_UNSPEC, + 0, + resolve_callback, + b)) + handle_failure(b); break; } - case SW_DISCOVERY_BROWSE_REMOVE_SERVICE: + case AVAHI_BROWSER_REMOVE: { + if (b->callback) { pa_browse_info i; int opcode; @@ -268,63 +279,144 @@ static sw_result browse_reply( b->callback(b, opcode, &i, b->userdata); } break; + } + case AVAHI_BROWSER_FAILURE: { + handle_failure(b); + break; + } + default: ; } - - return SW_OKAY; } -pa_browser *pa_browser_new(pa_mainloop_api *mainloop) { - pa_browser *b; - sw_discovery_oid oid; +static void client_callback(AvahiClient *s, AvahiClientState state, void *userdata) { + pa_browser *b = userdata; + assert(s); + if (state == AVAHI_CLIENT_FAILURE) + handle_failure(b); +} + +static void browser_free(pa_browser *b); + +pa_browser *pa_browser_new(pa_mainloop_api *mainloop) { + return pa_browser_new_full(mainloop, PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, NULL); +} + +pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t flags, const char **error_string) { + pa_browser *b; + int error; + + assert(mainloop); + + if (flags & ~(PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES) || flags == 0) + return NULL; + b = pa_xnew(pa_browser, 1); b->mainloop = mainloop; b->ref = 1; b->callback = NULL; b->userdata = NULL; + b->error_callback = NULL; + b->error_userdata = NULL; + b->sink_browser = b->source_browser = b->server_browser = NULL; - if (sw_discovery_init(&b->discovery) != SW_OKAY) { - pa_log_error(__FILE__": sw_discovery_init() failed."); - pa_xfree(b); - return NULL; + b->avahi_poll = pa_avahi_poll_new(mainloop); + + if (!(b->client = avahi_client_new(b->avahi_poll, 0, client_callback, b, &error))) { + if (error_string) + *error_string = avahi_strerror(error); + goto fail; + } + + if ((flags & PA_BROWSE_FOR_SERVERS) && + !(b->server_browser = avahi_service_browser_new( + b->client, + AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, + SERVICE_TYPE_SERVER, + NULL, + 0, + browse_callback, + b))) { + + if (error_string) + *error_string = avahi_strerror(avahi_client_errno(b->client)); + goto fail; } - if (sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SERVER, NULL, browse_reply, b, &oid) != SW_OKAY || - sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SINK, NULL, browse_reply, b, &oid) != SW_OKAY || - sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SOURCE, NULL, browse_reply, b, &oid) != SW_OKAY) { + if ((flags & PA_BROWSE_FOR_SINKS) && + !(b->sink_browser = avahi_service_browser_new( + b->client, + AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, + SERVICE_TYPE_SINK, + NULL, + 0, + browse_callback, + b))) { - pa_log_error(__FILE__": sw_discovery_browse() failed."); - - sw_discovery_fina(b->discovery); - pa_xfree(b); - return NULL; + if (error_string) + *error_string = avahi_strerror(avahi_client_errno(b->client)); + goto fail; + } + + if ((flags & PA_BROWSE_FOR_SOURCES) && + !(b->source_browser = avahi_service_browser_new( + b->client, + AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, + SERVICE_TYPE_SOURCE, + NULL, + 0, + browse_callback, + b))) { + + if (error_string) + *error_string = avahi_strerror(avahi_client_errno(b->client)); + goto fail; } - b->io_event = mainloop->io_new(mainloop, sw_discovery_socket(b->discovery), PA_IO_EVENT_INPUT, io_callback, b); return b; + +fail: + if (b) + browser_free(b); + + return NULL; } static void browser_free(pa_browser *b) { assert(b && b->mainloop); - if (b->io_event) - b->mainloop->io_free(b->io_event); + if (b->sink_browser) + avahi_service_browser_free(b->sink_browser); + if (b->source_browser) + avahi_service_browser_free(b->source_browser); + if (b->server_browser) + avahi_service_browser_free(b->server_browser); + + if (b->client) + avahi_client_free(b->client); + + if (b->avahi_poll) + pa_avahi_poll_free(b->avahi_poll); - sw_discovery_fina(b->discovery); pa_xfree(b); } pa_browser *pa_browser_ref(pa_browser *b) { - assert(b && b->ref >= 1); + assert(b); + assert(b->ref >= 1); b->ref++; return b; } void pa_browser_unref(pa_browser *b) { - assert(b && b->ref >= 1); + assert(b); + assert(b->ref >= 1); if ((-- (b->ref)) <= 0) browser_free(b); @@ -336,3 +428,10 @@ void pa_browser_set_callback(pa_browser *b, pa_browse_cb_t cb, void *userdata) { b->callback = cb; b->userdata = userdata; } + +void pa_browser_set_error_callback(pa_browser *b, pa_browser_error_cb_t cb, void *userdata) { + assert(b); + + b->error_callback = cb; + b->error_userdata = userdata; +} diff --git a/src/pulse/browser.h b/src/pulse/browser.h index 2d20c6c0a..fc57a4d50 100644 --- a/src/pulse/browser.h +++ b/src/pulse/browser.h @@ -27,42 +27,72 @@ #include #include +/** \file + * An abstract interface for Zeroconf browsing of PulseAudio servers */ + PA_C_DECL_BEGIN +/** An opaque Zeroconf service browser object */ typedef struct pa_browser pa_browser; +/** Opcodes for pa_browser_cb_t callbacks */ typedef enum pa_browse_opcode { - PA_BROWSE_NEW_SERVER = 0, - PA_BROWSE_NEW_SINK, - PA_BROWSE_NEW_SOURCE, - PA_BROWSE_REMOVE_SERVER, - PA_BROWSE_REMOVE_SINK, - PA_BROWSE_REMOVE_SOURCE + PA_BROWSE_NEW_SERVER = 0, /**< New server found */ + PA_BROWSE_NEW_SINK, /**< New sink found */ + PA_BROWSE_NEW_SOURCE, /**< New source found */ + PA_BROWSE_REMOVE_SERVER, /**< Server disappeared */ + PA_BROWSE_REMOVE_SINK, /**< Sink disappeared */ + PA_BROWSE_REMOVE_SOURCE /**< Source disappeared */ } pa_browse_opcode_t; +typedef enum pa_browse_flags { + PA_BROWSE_FOR_SERVERS = 1, /**< Browse for servers */ + PA_BROWSE_FOR_SINKS = 2, /**< Browse for sinks */ + PA_BROWSE_FOR_SOURCES = 4 /** Browse for sources */ +} pa_browse_flags_t; + +/** Create a new browser object on the specified main loop */ pa_browser *pa_browser_new(pa_mainloop_api *mainloop); + +/** Same pa_browser_new, but pass additional flags parameter. */ +pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t flags, const char **error_string); + +/** Increase reference counter of the specified browser object */ pa_browser *pa_browser_ref(pa_browser *z); + +/** Decrease reference counter of the specified browser object */ void pa_browser_unref(pa_browser *z); +/** Information about a sink/source/server found with Zeroconf */ typedef struct pa_browse_info { - /* Unique service name */ - const char *name; /* always available */ + const char *name; /**< Unique service name; always available */ - /* Server info */ - const char *server; /* always available */ - const char *server_version, *user_name, *fqdn; /* optional */ - const uint32_t *cookie; /* optional */ + const char *server; /**< Server name; always available */ + const char *server_version; /**< Server version string; optional */ + const char *user_name; /**< User name of the server process; optional */ + const char *fqdn; /* Server version; optional */ + const uint32_t *cookie; /* Server cookie; optional */ - /* Device info */ - const char *device; /* always available when this information is of a sink/source */ - const char *description; /* optional */ - const pa_sample_spec *sample_spec; /* optional */ + const char *device; /* Device name; always available when this information is of a sink/source */ + const char *description; /* Device description; optional */ + const pa_sample_spec *sample_spec; /* Sample specification of the device; optional */ } pa_browse_info; +/** Callback prototype */ typedef void (*pa_browse_cb_t)(pa_browser *z, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata); +/** Set the callback pointer for the browser object */ void pa_browser_set_callback(pa_browser *z, pa_browse_cb_t cb, void *userdata); +/** Callback prototype for errors */ +typedef void (*pa_browser_error_cb_t)(pa_browser *z, const char *error_string, void *userdata); + +/** Set a callback function that is called whenever the browser object + * becomes invalid due to an error. After this function has been + * called the browser object has become invalid and should be + * freed. */ +void pa_browser_set_error_callback(pa_browser *z, pa_browser_error_cb_t, void *userdata); + PA_C_DECL_END #endif diff --git a/src/pulsecore/avahi-wrap.h b/src/pulsecore/avahi-wrap.h index 97da11eb9..d868fed49 100644 --- a/src/pulsecore/avahi-wrap.h +++ b/src/pulsecore/avahi-wrap.h @@ -29,5 +29,4 @@ AvahiPoll* pa_avahi_poll_new(pa_mainloop_api *api); void pa_avahi_poll_free(AvahiPoll *p); - #endif From d989c692ac2178f0724bd34d5ac0bc2c12176efb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 17:34:08 +0000 Subject: [PATCH 0972/1514] add browser.h to doxygen docs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1070 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doxygen/doxygen.conf.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index 8ccf667ae..81923a9fd 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h +INPUT = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h ../src/pulse/browser.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp From 1fd18d6b5fce487faea673d093019395ec783fbc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 17:35:10 +0000 Subject: [PATCH 0973/1514] * add proper error handling to pabrowse.c * properly destroy pa_browser object on exit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1071 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pabrowse.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 954e4e6c2..450182f5f 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -107,10 +107,18 @@ static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_brows } } +static void error_callback(pa_browser *b, const char *s, void *userdata) { + pa_mainloop_api*m = userdata; + + fprintf(stderr, "Failure: %s\n", s); + m->quit(m, 1); +} + int main(int argc, char *argv[]) { pa_mainloop *mainloop = NULL; pa_browser *browser = NULL; int ret = 1, r; + const char *s; if (!(mainloop = pa_mainloop_new())) goto finish; @@ -121,15 +129,22 @@ int main(int argc, char *argv[]) { pa_signal_new(SIGTERM, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - if (!(browser = pa_browser_new(pa_mainloop_get_api(mainloop)))) + if (!(browser = pa_browser_new_full(pa_mainloop_get_api(mainloop), PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, &s))) { + fprintf(stderr, "pa_browse_new_full(): %s\n", s); goto finish; + } pa_browser_set_callback(browser, browser_callback, NULL); + pa_browser_set_error_callback(browser, error_callback, pa_mainloop_get_api(mainloop)); ret = 0; pa_mainloop_run(mainloop, &ret); finish: + + if (browser) + pa_browser_unref(browser); + if (mainloop) { pa_signal_done(); pa_mainloop_free(mainloop); From 6f24a9d32c8132fdd842035f473750bbd313305d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 17:44:18 +0000 Subject: [PATCH 0974/1514] remove HOWL snippet from configure script git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1072 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- configure.ac | 35 ----------------------------------- 2 files changed, 1 insertion(+), 36 deletions(-) diff --git a/Makefile.am b/Makefile.am index 566cec684..8aa609f6c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,7 @@ noinst_DATA = pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libpulse.pc libpulse-simple.pc -if HAVE_HOWL +if HAVE_AVAHI pkgconfig_DATA += \ libpulse-browse.pc endif diff --git a/configure.ac b/configure.ac index eb6fa2d37..83cb2e1a2 100644 --- a/configure.ac +++ b/configure.ac @@ -475,41 +475,6 @@ AC_SUBST(GLIB12_LIBS) AC_SUBST(HAVE_GLIB12) AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) -#### Howl support (optional) #### - -AC_ARG_ENABLE([howl], - AC_HELP_STRING([--disable-howl], [Disable optional Howl support]), - [ - case "${enableval}" in - yes) howl=yes ;; - no) howl=no ;; - *) AC_MSG_ERROR(bad value ${enableval} for --disable-howl) ;; - esac - ], - [howl=auto]) - -if test "x${howl}" != xno ; then - PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], - HAVE_HOWL=1, - [ - PKG_CHECK_MODULES(HOWL, [ avahi-compat-howl >= 0.9.8 ], - HAVE_HOWL=1, - [ - HAVE_HOWL=0 - if test "x$howl" = xyes ; then - AC_MSG_ERROR([*** Howl support not found]) - fi - ]) - ]) -else - HAVE_HOWL=0 -fi - -AC_SUBST(HOWL_CFLAGS) -AC_SUBST(HOWL_LIBS) -AC_SUBST(HAVE_HOWL) -AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1]) - #### Avahi support (optional) #### AC_ARG_ENABLE([avahi], From 3f0f4f57d29e868c03f2e164c44faa715f2572d7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 17:44:54 +0000 Subject: [PATCH 0975/1514] remove howl-wrap.[ch] git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1073 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/howl-wrap.c | 117 ---------------------------------------- src/modules/howl-wrap.h | 37 ------------- 2 files changed, 154 deletions(-) delete mode 100644 src/modules/howl-wrap.c delete mode 100644 src/modules/howl-wrap.h diff --git a/src/modules/howl-wrap.c b/src/modules/howl-wrap.c deleted file mode 100644 index e56fca3e7..000000000 --- a/src/modules/howl-wrap.c +++ /dev/null @@ -1,117 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of PulseAudio. - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -#include - -#include -#include - -#include "howl-wrap.h" - -#define HOWL_PROPERTY "howl" - -struct pa_howl_wrapper { - pa_core *core; - int ref; - - pa_io_event *io_event; - sw_discovery discovery; -}; - -static void howl_io_event(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { - pa_howl_wrapper *w = userdata; - assert(m && e && fd >= 0 && w && w->ref >= 1); - - if (f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) - goto fail; - - if (sw_discovery_read_socket(w->discovery) != SW_OKAY) - goto fail; - - return; - -fail: - pa_log_error(__FILE__": howl connection died."); - w->core->mainloop->io_free(w->io_event); - w->io_event = NULL; -} - -static pa_howl_wrapper* howl_wrapper_new(pa_core *c) { - pa_howl_wrapper *h; - sw_discovery session; - assert(c); - - if (sw_discovery_init(&session) != SW_OKAY) { - pa_log_error(__FILE__": sw_discovery_init() failed."); - return NULL; - } - - h = pa_xmalloc(sizeof(pa_howl_wrapper)); - h->core = c; - h->ref = 1; - h->discovery = session; - - h->io_event = c->mainloop->io_new(c->mainloop, sw_discovery_socket(session), PA_IO_EVENT_INPUT, howl_io_event, h); - - return h; -} - -static void howl_wrapper_free(pa_howl_wrapper *h) { - assert(h); - - sw_discovery_fina(h->discovery); - - if (h->io_event) - h->core->mainloop->io_free(h->io_event); - - pa_xfree(h); -} - -pa_howl_wrapper* pa_howl_wrapper_get(pa_core *c) { - pa_howl_wrapper *h; - assert(c); - - if ((h = pa_property_get(c, HOWL_PROPERTY))) - return pa_howl_wrapper_ref(h); - - return howl_wrapper_new(c); -} - -pa_howl_wrapper* pa_howl_wrapper_ref(pa_howl_wrapper *h) { - assert(h && h->ref >= 1); - h->ref++; - return h; -} - -void pa_howl_wrapper_unref(pa_howl_wrapper *h) { - assert(h && h->ref >= 1); - if (!(--h->ref)) - howl_wrapper_free(h); -} - -sw_discovery pa_howl_wrapper_get_discovery(pa_howl_wrapper *h) { - assert(h && h->ref >= 1); - - return h->discovery; -} - diff --git a/src/modules/howl-wrap.h b/src/modules/howl-wrap.h deleted file mode 100644 index 506c0b68d..000000000 --- a/src/modules/howl-wrap.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef foohowlwrapperhfoo -#define foohowlwrapperhfoo - -/* $Id$ */ - -/*** - This file is part of PulseAudio. - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -#include - -typedef struct pa_howl_wrapper pa_howl_wrapper; - -pa_howl_wrapper* pa_howl_wrapper_get(pa_core *c); -pa_howl_wrapper* pa_howl_wrapper_ref(pa_howl_wrapper *h); -void pa_howl_wrapper_unref(pa_howl_wrapper *h); - -sw_discovery pa_howl_wrapper_get_discovery(pa_howl_wrapper *h); - -#endif From ceb1b6f3d18f1485849f96009aadf53520faede2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 18:23:57 +0000 Subject: [PATCH 0976/1514] remove avahi/howl item from todo list git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1074 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index 978331f45..e23335578 100644 --- a/todo +++ b/todo @@ -6,7 +6,6 @@ Post 0.9.0: - polish for starting polypaudio as root/system-wide instance - chroot() - module-tunnel: improve latency calculation -- port from howl to avahi - multiline configuration statements - use scatter/gather io for sockets - rtp module ported to Win32 (sendmsg/recvmsg emulation) From 7484b62e1e00e551cd4b1a19507b98da698d4f7e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 23:10:48 +0000 Subject: [PATCH 0977/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1075 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/todo b/todo index e23335578..cae27b2af 100644 --- a/todo +++ b/todo @@ -34,6 +34,8 @@ Post 0.9.0: - check if using prctl(PR_GET_NAME) makes sense in pa_get_binary_name() - gconf module + frontend - hooks for creating sink inputs +- insert the low-level device name in the default sink/source name, to make them recognizable:q! + Long term: - pass meta info for hearing impaired From 55296041473306ca4aa346197b60545814dfebe8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Jul 2006 23:12:50 +0000 Subject: [PATCH 0978/1514] support time events with NULL timevals which are OK in avahi, but not in PA. This makes padevchooser actually work on top of the new avahi browsing stuff git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1076 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/avahi-wrap.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/pulsecore/avahi-wrap.c b/src/pulsecore/avahi-wrap.c index 9da765589..80256a124 100644 --- a/src/pulsecore/avahi-wrap.c +++ b/src/pulsecore/avahi-wrap.c @@ -139,7 +139,8 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, t->avahi_poll = p; t->callback = callback; t->userdata = userdata; - t->time_event = p->mainloop->time_new(p->mainloop, tv, timeout_callback, t); + + t->time_event = tv ? p->mainloop->time_new(p->mainloop, tv, timeout_callback, t) : NULL; return t; } @@ -147,13 +148,21 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { assert(t); - t->avahi_poll->mainloop->time_restart(t->time_event, tv); + if (t->time_event && tv) + t->avahi_poll->mainloop->time_restart(t->time_event, tv); + else if (!t->time_event && tv) + t->time_event = t->avahi_poll->mainloop->time_new(t->avahi_poll->mainloop, tv, timeout_callback, t); + else if (t->time_event && !tv) { + t->avahi_poll->mainloop->time_free(t->time_event); + t->time_event = NULL; + } } static void timeout_free(AvahiTimeout *t) { assert(t); - t->avahi_poll->mainloop->time_free(t->time_event); + if (t->time_event) + t->avahi_poll->mainloop->time_free(t->time_event); pa_xfree(t); } From 881d4ddd397a829930b6800f1ecc438439cdc766 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 00:17:31 +0000 Subject: [PATCH 0979/1514] * fall back to prctl(PR_GET_NAME) in pa_get_binary_name() if readlink() fails * call pa_path_get_filename() in all cases before returning in pa_get_binary_name(). We already did so on Win32, but didn't on Linux. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1077 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 ++ src/pulse/util.c | 67 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/configure.ac b/configure.ac index 83cb2e1a2..a36ee5a04 100644 --- a/configure.ac +++ b/configure.ac @@ -160,6 +160,8 @@ AC_CHECK_HEADERS([linux/input.h], [HAVE_EVDEV=1], [HAVE_EVDEV=0]) AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = "x1"]) +AC_CHECK_HEADERS([sys/prctl.h]) + # Solaris AC_CHECK_HEADERS([sys/filio.h]) diff --git a/src/pulse/util.c b/src/pulse/util.c index 338607c41..b041fec80 100644 --- a/src/pulse/util.c +++ b/src/pulse/util.c @@ -49,6 +49,10 @@ #include #endif +#ifdef HAVE_SYS_PRCTL_H +#include +#endif + #include "../pulsecore/winsock.h" #include @@ -152,28 +156,51 @@ char *pa_get_home_dir(char *s, size_t l) { char *pa_get_binary_name(char *s, size_t l) { -#ifdef HAVE_READLINK - char path[PATH_MAX]; - int i; - assert(s && l); + assert(s); + assert(l); - /* This works on Linux only */ - - snprintf(path, sizeof(path), "/proc/%u/exe", (unsigned) getpid()); - if ((i = readlink(path, s, l-1)) < 0) - return NULL; - - s[i] = 0; - return s; -#elif defined(OS_IS_WIN32) - char path[PATH_MAX]; - if (!GetModuleFileName(NULL, path, PATH_MAX)) - return NULL; - pa_strlcpy(s, pa_path_get_filename(path), l); - return s; -#else - return NULL; +#if defined(OS_IS_WIN32) + { + char path[PATH_MAX]; + + if (GetModuleFileName(NULL, path, PATH_MAX)) + return pa_strlcpy(s, pa_path_get_filename(path), l); + } #endif + +#ifdef HAVE_READLINK + { + int i; + char path[PATH_MAX]; + /* This works on Linux only */ + + if ((i = readlink("/proc/self/exe", path, sizeof(path)-1)) >= 0) { + path[i] = 0; + return pa_strlcpy(s, pa_path_get_filename(path), l); + } + } + +#endif + +#if defined(HAVE_SYS_PRCTL_H) && defined(PR_GET_NAME) + { + + #ifndef TASK_COMM_LEN + /* Actually defined in linux/sched.h */ + #define TASK_COMM_LEN 16 + #endif + + char tcomm[TASK_COMM_LEN+1]; + memset(tcomm, 0, sizeof(tcomm)); + + /* This works on Linux only */ + if (prctl(PR_GET_NAME, (unsigned long) tcomm, 0, 0, 0) == 0) + return pa_strlcpy(s, tcomm, l); + + } +#endif + + return NULL; } const char *pa_path_get_filename(const char *p) { From a87c43d61e950b60b44e7e786116dd1e2fad4dc6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 00:18:21 +0000 Subject: [PATCH 0980/1514] Don't call pa_path_get_filename() anymore since it is implicitly called by pa_get_binary_name() anyway git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1078 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index f493f7e5a..b1636754b 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -408,7 +408,7 @@ static const char *client_name(char *buf, size_t n) { return e; if (pa_get_binary_name(p, sizeof(p))) - snprintf(buf, n, "OSS Emulation[%s]", pa_path_get_filename(p)); + snprintf(buf, n, "OSS Emulation[%s]", p); else snprintf(buf, n, "OSS"); From 883ce83f92c408c77bf1a50952893ee5af3f0acc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 00:19:09 +0000 Subject: [PATCH 0981/1514] add new test get-binary-name-test for testing pa_get_binary_name() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1079 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 8 ++++++- src/tests/get-binary-name-test.c | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/tests/get-binary-name-test.c diff --git a/src/Makefile.am b/src/Makefile.am index fad01e08d..0db8a8f25 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -192,7 +192,8 @@ noinst_PROGRAMS = \ interpol-test \ channelmap-test \ thread-mainloop-test \ - utf8-test + utf8-test \ + get-binary-name-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -225,6 +226,11 @@ utf8_test_CFLAGS = $(AM_CFLAGS) utf8_test_LDADD = $(AM_LDADD) libpulsecore.la utf8_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +get_binary_name_test_SOURCES = tests/get-binary-name-test.c +get_binary_name_test_CFLAGS = $(AM_CFLAGS) +get_binary_name_test_LDADD = $(AM_LDADD) libpulse.la +get_binary_name_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la diff --git a/src/tests/get-binary-name-test.c b/src/tests/get-binary-name-test.c new file mode 100644 index 000000000..0cea2b6d4 --- /dev/null +++ b/src/tests/get-binary-name-test.c @@ -0,0 +1,36 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +int main(int argc, char *argv[]) { + char exename[PATH_MAX]; + + printf("%s\n", pa_get_binary_name(exename, sizeof(exename))); + return 0; +} From 82e680c31ca9df51c599ce9634343b28233a27fa Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 14 Jul 2006 10:08:53 +0000 Subject: [PATCH 0982/1514] Make sure the win32 default conf gets shipped. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1080 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index 0db8a8f25..8da51aac3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -76,6 +76,7 @@ EXTRA_DIST = \ pulse/client.conf.in \ daemon/daemon.conf.in \ daemon/default.pa.in \ + daemon/default.pa.win32 \ depmod.py \ daemon/esdcompat.in \ utils/padsp \ From dfd864a00e45c3fef8a5be51718b022843de7a30 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 10:19:46 +0000 Subject: [PATCH 0983/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1081 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 2 -- 1 file changed, 2 deletions(-) diff --git a/todo b/todo index cae27b2af..6a805813e 100644 --- a/todo +++ b/todo @@ -31,12 +31,10 @@ Post 0.9.0: - use send() with MSG_NOSIGNAL instead of write() wherever possible, and than drop that SIGPIPE warning - drop dependency of libpolyp on libX11, instead use an external mini binary - "hot" moving of streams between sinks -- check if using prctl(PR_GET_NAME) makes sense in pa_get_binary_name() - gconf module + frontend - hooks for creating sink inputs - insert the low-level device name in the default sink/source name, to make them recognizable:q! - Long term: - pass meta info for hearing impaired - X11: support for the X11 synchronization extension From 350a253dc559956b63ced4e602b1040ccba66f98 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 10:20:57 +0000 Subject: [PATCH 0984/1514] remove vi'ism git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1082 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/todo b/todo index 6a805813e..f30122810 100644 --- a/todo +++ b/todo @@ -33,7 +33,7 @@ Post 0.9.0: - "hot" moving of streams between sinks - gconf module + frontend - hooks for creating sink inputs -- insert the low-level device name in the default sink/source name, to make them recognizable:q! +- insert the low-level device name in the default sink/source name, to make them recognizable Long term: - pass meta info for hearing impaired From 860be2e70b33ff5eeb9130f80c4b1c096a2a8f27 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 22:42:01 +0000 Subject: [PATCH 0985/1514] try to use send(,,MSG_NOSIGNAL) instead of write() wherever possible (which will allow us to drop the SIGPIPE check). Cache the results of the last write()/send() to make sure that we do not issue more than necessary system calls. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1083 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/cpulimit.c | 4 +- src/daemon/main.c | 10 +-- src/modules/module-esound-compat-spawnfd.c | 2 +- src/modules/module-jack-sink.c | 6 +- src/modules/module-jack-source.c | 6 +- src/modules/module-mmkbd-evdev.c | 5 +- src/modules/module-oss.c | 2 +- src/pulse/mainloop-signal.c | 4 +- src/pulse/mainloop.c | 6 +- src/pulse/xmalloc.c | 2 +- src/pulsecore/authkey.c | 6 +- src/pulsecore/core-util.c | 83 +++++++++++++++------- src/pulsecore/core-util.h | 8 +-- src/pulsecore/iochannel.c | 6 +- src/pulsecore/pid.c | 4 +- src/pulsecore/random.c | 2 +- src/tests/mcalign-test.c | 2 +- 17 files changed, 100 insertions(+), 58 deletions(-) diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index a8c9d3f5a..b8740ea0f 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -111,7 +111,7 @@ static void reset_cpu_time(int t) { /* A simple, thread-safe puts() work-alike */ static void write_err(const char *p) { - pa_loop_write(2, p, strlen(p)); + pa_loop_write(2, p, strlen(p), NULL); } /* The signal handler, called on every SIGXCPU */ @@ -159,7 +159,7 @@ static void signal_handler(int sig) { static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata) { char c; assert(m && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == the_pipe[0]); - read(the_pipe[0], &c, sizeof(c)); + pa_read(the_pipe[0], &c, sizeof(c), NULL); m->quit(m, 1); /* Quit the main loop */ } diff --git a/src/daemon/main.c b/src/daemon/main.c index 5e7330a56..c41c69df6 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -304,7 +304,7 @@ int main(int argc, char *argv[]) { close(daemon_pipe[1]); daemon_pipe[1] = -1; - if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval)) != sizeof(retval)) { + if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL) != sizeof(retval)) { pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno)); retval = 1; } @@ -368,7 +368,7 @@ int main(int argc, char *argv[]) { pa_log(__FILE__": pa_pid_file_create() failed."); #ifdef HAVE_FORK if (conf->daemonize) - pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); #endif goto finish; } @@ -428,20 +428,20 @@ int main(int argc, char *argv[]) { pa_log(__FILE__": failed to initialize daemon."); #ifdef HAVE_FORK if (conf->daemonize) - pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); #endif } else if (!c->modules || pa_idxset_size(c->modules) == 0) { pa_log(__FILE__": daemon startup without any loaded modules, refusing to work."); #ifdef HAVE_FORK if (conf->daemonize) - pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); #endif } else { retval = 0; #ifdef HAVE_FORK if (conf->daemonize) - pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); #endif c->disallow_module_loading = conf->disallow_module_loading; diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index c4bc342a6..54e090e4c 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -59,7 +59,7 @@ int pa__init(pa_core *c, pa_module*m) { goto finish; } - if (pa_loop_write(fd, &x, sizeof(x)) != sizeof(x)) + if (pa_loop_write(fd, &x, sizeof(x), NULL) != sizeof(x)) pa_log(__FILE__": WARNING: write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno)); close(fd); diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 74f25d536..d761c1f7c 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -80,6 +80,7 @@ struct userdata { jack_nframes_t frames_requested; int quit_requested; + int pipe_fd_type; int pipe_fds[2]; pa_io_event *io_event; @@ -120,7 +121,7 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_ assert(u); assert(u->pipe_fds[0] == fd); - read(fd, &x, 1); + pa_read(fd, &x, 1, &u->pipe_fd_type); if (u->quit_requested) { stop_sink(u); @@ -165,7 +166,7 @@ static void request_render(struct userdata *u) { assert(u); assert(u->pipe_fds[1] >= 0); - write(u->pipe_fds[1], &c, 1); + pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type); } static void jack_shutdown(void *arg) { @@ -268,6 +269,7 @@ int pa__init(pa_core *c, pa_module*m) { u->core = c; u->module = m; u->pipe_fds[0] = u->pipe_fds[1] = -1; + u->pipe_fd_type = 0; pthread_mutex_init(&u->mutex, NULL); pthread_cond_init(&u->cond, NULL); diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 9c7f449f3..649a8f98d 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -81,6 +81,7 @@ struct userdata { int quit_requested; int pipe_fds[2]; + int pipe_fd_type; pa_io_event *io_event; jack_nframes_t frames_in_buffer; @@ -119,7 +120,7 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_ assert(u); assert(u->pipe_fds[0] == fd); - read(fd, &x, 1); + pa_read(fd, &x, 1, &u->pipe_fd_type); if (u->quit_requested) { stop_source(u); @@ -166,7 +167,7 @@ static void request_post(struct userdata *u) { assert(u); assert(u->pipe_fds[1] >= 0); - write(u->pipe_fds[1], &c, 1); + pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type); } static void jack_shutdown(void *arg) { @@ -266,6 +267,7 @@ int pa__init(pa_core *c, pa_module*m) { u->core = c; u->module = m; u->pipe_fds[0] = u->pipe_fds[1] = -1; + u->pipe_fd_type = 0; pthread_mutex_init(&u->mutex, NULL); pthread_cond_init(&u->cond, NULL); diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index ddbf16d25..c3d07396e 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -70,7 +70,7 @@ static const char* const valid_modargs[] = { }; struct userdata { - int fd; + int fd, fd_type; pa_io_event *io; char *sink_name; pa_module *module; @@ -89,7 +89,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC if (events & PA_IO_EVENT_INPUT) { struct input_event ev; - if (pa_loop_read(u->fd, &ev, sizeof(ev)) <= 0) { + if (pa_loop_read(u->fd, &ev, sizeof(ev), &u->fd_type) <= 0) { pa_log(__FILE__": failed to read from event device: %s", pa_cstrerror(errno)); goto fail; } @@ -182,6 +182,7 @@ int pa__init(pa_core *c, pa_module*m) { u->io = NULL; u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); u->fd = -1; + u->fd_type = 0; if ((u->fd = open(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY)) < 0) { pa_log(__FILE__": failed to open evdev device: %s", pa_cstrerror(errno)); diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 5a80661ec..a3ea2c1f5 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -467,7 +467,7 @@ int pa__init(pa_core *c, pa_module*m) { */ if (u->source) { char *buf = pa_xnew(char, u->sample_size); - read(u->fd, buf, u->sample_size); + pa_read(u->fd, buf, u->sample_size, NULL); pa_xfree(buf); } diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c index c3cf362d8..11a27cd50 100644 --- a/src/pulse/mainloop-signal.c +++ b/src/pulse/mainloop-signal.c @@ -67,7 +67,7 @@ static void signal_handler(int sig) { #ifndef HAVE_SIGACTION signal(sig, signal_handler); #endif - pa_write(signal_pipe[1], &sig, sizeof(sig)); + pa_write(signal_pipe[1], &sig, sizeof(sig), NULL); } static void dispatch(pa_mainloop_api*a, int sig) { @@ -86,7 +86,7 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags int sig; assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); - if ((r = pa_read(signal_pipe[0], &sig, sizeof(sig))) < 0) { + if ((r = pa_read(signal_pipe[0], &sig, sizeof(sig), NULL)) < 0) { if (errno == EAGAIN) return; diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 32f1a845d..dfbc337b8 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -100,6 +100,7 @@ struct pa_mainloop { int deferred_pending; int wakeup_pipe[2]; + int wakeup_pipe_type; enum { STATE_PASSIVE, @@ -337,6 +338,7 @@ pa_mainloop *pa_mainloop_new(void) { m = pa_xmalloc(sizeof(pa_mainloop)); + m->wakeup_pipe_type = 0; if (pipe(m->wakeup_pipe) < 0) { pa_log_error(__FILE__": ERROR: cannot create wakeup pipe"); pa_xfree(m); @@ -625,7 +627,7 @@ void pa_mainloop_wakeup(pa_mainloop *m) { assert(m); if (m->wakeup_pipe[1] >= 0) - pa_write(m->wakeup_pipe[1], &c, sizeof(c)); + pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type); } static void clear_wakeup(pa_mainloop *m) { @@ -636,7 +638,7 @@ static void clear_wakeup(pa_mainloop *m) { if (m->wakeup_pipe[0] < 0) return; - while (pa_read(m->wakeup_pipe[0], &c, sizeof(c)) == sizeof(c)); + while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c)); } int pa_mainloop_prepare(pa_mainloop *m, int timeout) { diff --git a/src/pulse/xmalloc.c b/src/pulse/xmalloc.c index 46871aeb6..367551665 100644 --- a/src/pulse/xmalloc.c +++ b/src/pulse/xmalloc.c @@ -49,7 +49,7 @@ static void oom(void) PA_GCC_NORETURN; * exits */ static void oom(void) { static const char e[] = "Not enough memory\n"; - pa_loop_write(STDERR_FILENO, e, sizeof(e)-1); + pa_loop_write(STDERR_FILENO, e, sizeof(e)-1, NULL); #ifdef SIGQUIT raise(SIGQUIT); #endif diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c index 064209d9a..a5df3ed1d 100644 --- a/src/pulsecore/authkey.c +++ b/src/pulsecore/authkey.c @@ -53,7 +53,7 @@ static int generate(int fd, void *ret_data, size_t length) { lseek(fd, 0, SEEK_SET); ftruncate(fd, 0); - if ((r = pa_loop_write(fd, ret_data, length)) < 0 || (size_t) r != length) { + if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) { pa_log(__FILE__": failed to write cookie file: %s", pa_cstrerror(errno)); return -1; } @@ -84,7 +84,7 @@ static int load(const char *fn, void *data, size_t length) { unlock = pa_lock_fd(fd, 1) >= 0; - if ((r = pa_loop_read(fd, data, length)) < 0) { + if ((r = pa_loop_read(fd, data, length, NULL)) < 0) { pa_log(__FILE__": failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } @@ -188,7 +188,7 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) { unlock = pa_lock_fd(fd, 1) >= 0; - if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) { + if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) { pa_log(__FILE__": failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 9d694da5f..16c3631f6 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -201,57 +201,81 @@ finish: return ret; } -/** Platform independent read function. Necessary since not all systems - * treat all file descriptors equal. */ -ssize_t pa_read(int fd, void *buf, size_t count) { - ssize_t r; +/** Platform independent read function. Necessary since not all + * systems treat all file descriptors equal. If type is + * non-NULL it is used to cache the type of the fd. This is + * useful for making sure that only a single syscall is executed per + * function call. The variable pointed to should be initialized to 0 + * by the caller. */ +ssize_t pa_read(int fd, void *buf, size_t count, int *type) { #ifdef OS_IS_WIN32 - r = recv(fd, buf, count, 0); - if (r < 0) { + + if (!type || *type == 0) { + ssize_t r; + + if ((r = recv(fd, buf, count, 0)) >= 0) + return r; + if (WSAGetLastError() != WSAENOTSOCK) { errno = WSAGetLastError(); return r; } + + if (type) + *type = 1; } - if (r < 0) #endif - r = read(fd, buf, count); - - return r; + + return read(fd, buf, count); } /** Similar to pa_read(), but handles writes */ -ssize_t pa_write(int fd, const void *buf, size_t count) { - ssize_t r; +ssize_t pa_write(int fd, const void *buf, size_t count, int *type) { + if (!type || *type == 0) { + ssize_t r; + + if ((r = send(fd, buf, count, MSG_NOSIGNAL)) >= 0) + return r; + #ifdef OS_IS_WIN32 - r = send(fd, buf, count, 0); - if (r < 0) { if (WSAGetLastError() != WSAENOTSOCK) { errno = WSAGetLastError(); return r; } +#else + if (errno != ENOTSOCK) + return r; +#endif + + if (type) + *type = 1; } - if (r < 0) -#endif - r = write(fd, buf, count); - - return r; + return write(fd, buf, count); } /** Calls read() in a loop. Makes sure that as much as 'size' bytes, * unless EOF is reached or an error occured */ -ssize_t pa_loop_read(int fd, void*data, size_t size) { +ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) { ssize_t ret = 0; - assert(fd >= 0 && data && size); + int _type; + + assert(fd >= 0); + assert(data); + assert(size); + + if (!type) { + _type = 0; + type = &_type; + } while (size > 0) { ssize_t r; - if ((r = pa_read(fd, data, size)) < 0) + if ((r = pa_read(fd, data, size, type)) < 0) return r; if (r == 0) @@ -266,14 +290,23 @@ ssize_t pa_loop_read(int fd, void*data, size_t size) { } /** Similar to pa_loop_read(), but wraps write() */ -ssize_t pa_loop_write(int fd, const void*data, size_t size) { +ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) { ssize_t ret = 0; - assert(fd >= 0 && data && size); + int _type; + + assert(fd >= 0); + assert(data); + assert(size); + + if (!type) { + _type = 0; + type = &_type; + } while (size > 0) { ssize_t r; - if ((r = pa_write(fd, data, size)) < 0) + if ((r = pa_write(fd, data, size, type)) < 0) return r; if (r == 0) diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 0012afc64..864a96ecc 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -36,10 +36,10 @@ void pa_make_nonblock_fd(int fd); int pa_make_secure_dir(const char* dir); int pa_make_secure_parent_dir(const char *fn); -ssize_t pa_read(int fd, void *buf, size_t count); -ssize_t pa_write(int fd, const void *buf, size_t count); -ssize_t pa_loop_read(int fd, void*data, size_t size); -ssize_t pa_loop_write(int fd, const void*data, size_t size); +ssize_t pa_read(int fd, void *buf, size_t count, int *type); +ssize_t pa_write(int fd, const void *buf, size_t count, int *type); +ssize_t pa_loop_read(int fd, void*data, size_t size, int *type); +ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type); void pa_check_signal_is_blocked(int sig); diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 8a19094af..842c0e6a9 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -49,6 +49,7 @@ struct pa_iochannel { int ifd, ofd; + int ifd_type, ofd_type; pa_mainloop_api* mainloop; pa_iochannel_cb_t callback; @@ -127,6 +128,7 @@ pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) { io = pa_xnew(pa_iochannel, 1); io->ifd = ifd; io->ofd = ofd; + io->ifd_type = io->ofd_type = 0; io->mainloop = m; io->userdata = NULL; @@ -204,7 +206,7 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) { assert(l); assert(io->ofd >= 0); - r = pa_write(io->ofd, data, l); + r = pa_write(io->ofd, data, l, &io->ofd_type); if (r >= 0) { io->writable = 0; enable_mainloop_sources(io); @@ -220,7 +222,7 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { assert(data); assert(io->ifd >= 0); - r = pa_read(io->ifd, data, l); + r = pa_read(io->ifd, data, l, &io->ifd_type); if (r >= 0) { io->readable = 0; enable_mainloop_sources(io); diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index b89728666..0ad76a6e2 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -56,7 +56,7 @@ static pid_t read_pid(const char *fn, int fd) { assert(fn && fd >= 0); - if ((r = pa_loop_read(fd, t, sizeof(t)-1)) < 0) { + if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) { pa_log_warn(__FILE__": WARNING: failed to read PID file '%s': %s", fn, pa_cstrerror(errno)); return (pid_t) -1; @@ -177,7 +177,7 @@ int pa_pid_file_create(void) { snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid()); l = strlen(t); - if (pa_loop_write(fd, t, l) != (ssize_t) l) { + if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) { pa_log(__FILE__": failed to write PID file."); goto fail; } diff --git a/src/pulsecore/random.c b/src/pulsecore/random.c index 3d3357a5e..684ead715 100644 --- a/src/pulsecore/random.c +++ b/src/pulsecore/random.c @@ -61,7 +61,7 @@ static int random_proper(void *ret_data, size_t length) { if ((fd = open(*device, O_RDONLY)) >= 0) { - if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length) + if ((r = pa_loop_read(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) ret = -1; close(fd); diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index ccb0613e8..7a68e6de0 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -82,7 +82,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { if (pa_mcalign_pop(a, &t) < 0) break; - pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length); + pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length, NULL); fprintf(stderr, "Wrote %lu bytes.\n", (unsigned long) t.length); pa_memblock_unref(t.memblock); From 3eeecdc79095748eb8ac046edee6bf4fe7268060 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 23:00:20 +0000 Subject: [PATCH 0986/1514] don't set MSG_NOSIGNAL for recvmsg(), since it doesn't make sense there git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1084 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/iochannel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 842c0e6a9..15aa8e35c 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -336,7 +336,7 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struc mh.msg_controllen = sizeof(cmsg_data); mh.msg_flags = 0; - if ((r = recvmsg(io->ifd, &mh, MSG_NOSIGNAL)) >= 0) { + if ((r = recvmsg(io->ifd, &mh, 0)) >= 0) { struct cmsghdr *cmsg; *creds_valid = 0; From fc544a63de7496ab6ea23cce65599c086d730256 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 23:00:57 +0000 Subject: [PATCH 0987/1514] don't send SCM_CREDENTIALS on every sendmsg(), instead do it only on handshake git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1085 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pstream.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 60c059381..e9b6f4c80 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -291,6 +291,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa i->channel = channel; i->offset = offset; i->seek_mode = seek_mode; + i->with_creds = 0; pa_memblock_ref(i->chunk.memblock); @@ -317,9 +318,6 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = 0; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = 0; -#ifdef SCM_CREDENTIALS - p->send_creds_now = 1; -#endif } else { assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK && p->write.current->chunk.memblock); @@ -329,11 +327,12 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl((uint32_t) (((uint64_t) p->write.current->offset) >> 32)); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = htonl((uint32_t) ((uint64_t) p->write.current->offset)); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = htonl(p->write.current->seek_mode); + } #ifdef SCM_CREDENTIALS - p->send_creds_now = 1; + p->send_creds_now = p->write.current->with_creds; #endif - } + } static int do_write(pa_pstream *p) { From b8f9ae00f341c936eb27dd51d307f99682a09685 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 23:06:44 +0000 Subject: [PATCH 0988/1514] remove checking for SIGPIPE blocking from client code. Because we use send(,,MSG_NOSIGNAL) for most socket writes now the reason for SIGPIPE blocking is no longer give. We keep this check for the server side however, because pipes create SIGPIPE too but cannot be used with MSG_NOSIGNAL. Some modules use pipes for internal and external communication. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1086 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index 648024c38..5724765be 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -132,10 +132,6 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { memset(&c->spawn_api, 0, sizeof(c->spawn_api)); c->do_autospawn = 0; -#ifdef SIGPIPE - pa_check_signal_is_blocked(SIGPIPE); -#endif - c->conf = pa_client_conf_new(); pa_client_conf_load(c->conf, NULL); #ifdef HAVE_X11 From d43bcb31bb355f1cddc037b017e1c65ef7725633 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 23:08:14 +0000 Subject: [PATCH 0989/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1087 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index f30122810..9b28ce1d5 100644 --- a/todo +++ b/todo @@ -28,7 +28,6 @@ Post 0.9.0: - Document utf8.h, timeval.h and util.h - fix clock of the NULL sink - gettextify polypaudio -- use send() with MSG_NOSIGNAL instead of write() wherever possible, and than drop that SIGPIPE warning - drop dependency of libpolyp on libX11, instead use an external mini binary - "hot" moving of streams between sinks - gconf module + frontend From 55a8db8efe50a85abe690224c13c8501dd56be47 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 23:59:42 +0000 Subject: [PATCH 0990/1514] improve latency calculation of NULL sink git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1088 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-null-sink.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 8cfce8fec..470be6bca 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -63,6 +63,9 @@ struct userdata { pa_sink *sink; pa_time_event *time_event; size_t block_size; + + uint64_t n_bytes; + struct timeval start_time; }; static const char* const valid_modargs[] = { @@ -90,6 +93,19 @@ static void time_callback(pa_mainloop_api *m, pa_time_event*e, const struct time pa_timeval_add(&ntv, pa_bytes_to_usec(l, &u->sink->sample_spec)); m->time_restart(e, &ntv); + + u->n_bytes += l; +} + +static pa_usec_t get_latency(pa_sink *s) { + struct userdata *u = s->userdata; + pa_usec_t a, b; + struct timeval now; + + a = pa_timeval_diff(pa_gettimeofday(&now), &u->start_time); + b = pa_bytes_to_usec(u->n_bytes, &s->sample_spec); + + return b > a ? b - a : 0; } int pa__init(pa_core *c, pa_module*m) { @@ -97,8 +113,9 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; - struct timeval tv; - assert(c && m); + + assert(c); + assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments."); @@ -111,7 +128,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - u = pa_xmalloc0(sizeof(struct userdata)); + u = pa_xnew0(struct userdata, 1); u->core = c; u->module = m; m->userdata = u; @@ -120,13 +137,16 @@ int pa__init(pa_core *c, pa_module*m) { pa_log(__FILE__": failed to create sink."); goto fail; } - + + u->sink->get_latency = get_latency; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("NULL sink"); + u->sink->description = pa_xstrdup("NULL sink"); - pa_gettimeofday(&tv); - u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u); + u->n_bytes = 0; + pa_gettimeofday(&u->start_time); + + u->time_event = c->mainloop->time_new(c->mainloop, &u->start_time, time_callback, u); u->block_size = pa_bytes_per_second(&ss) / 10; From a537b01cba05ff3d5b8bb3035413d2aebf4e00f0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 15 Jul 2006 12:40:27 +0000 Subject: [PATCH 0991/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1089 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/todo b/todo index 9b28ce1d5..2c98c4eda 100644 --- a/todo +++ b/todo @@ -26,13 +26,13 @@ Post 0.9.0: - iconv stuff sent from utils to server (UTF-8) - iconv sample loading in server - Document utf8.h, timeval.h and util.h -- fix clock of the NULL sink - gettextify polypaudio - drop dependency of libpolyp on libX11, instead use an external mini binary - "hot" moving of streams between sinks - gconf module + frontend - hooks for creating sink inputs - insert the low-level device name in the default sink/source name, to make them recognizable +- add new flag for distuinguishing hw sinks/sources from virtual sink/sources Long term: - pass meta info for hearing impaired From 6e38949039cca052ee0d167b92f895e4d95ee30d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Jul 2006 17:26:55 +0000 Subject: [PATCH 0992/1514] add a new boolean variable is_hardware to pa_sink/pa_source to denote wether the specific device is a hardware device or virtual/software git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1090 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sink.c | 2 ++ src/pulsecore/sink.h | 2 ++ src/pulsecore/source.c | 2 ++ src/pulsecore/source.h | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index ee6850f08..8acb77156 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -102,6 +102,8 @@ pa_sink* pa_sink_new( s->sw_muted = 0; s->hw_muted = 0; + s->is_hardware = 0; + s->get_latency = NULL; s->notify = NULL; s->set_hw_volume = NULL; diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index fdff0522d..1a6bc9886 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -60,6 +60,8 @@ struct pa_sink { pa_cvolume hw_volume, sw_volume; int hw_muted, sw_muted; + int is_hardware; + void (*notify)(pa_sink*sink); pa_usec_t (*get_latency)(pa_sink *s); int (*set_hw_volume)(pa_sink *s); diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 84151a929..48b6daea1 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -98,6 +98,8 @@ pa_source* pa_source_new( s->sw_muted = 0; s->hw_muted = 0; + s->is_hardware = 0; + s->get_latency = NULL; s->notify = NULL; s->set_hw_volume = NULL; diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index 6255c1156..878ae34d7 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -61,6 +61,8 @@ struct pa_source { pa_cvolume hw_volume, sw_volume; int hw_muted, sw_muted; + + int is_hardware; void (*notify)(pa_source*source); pa_usec_t (*get_latency)(pa_source *s); From 494fa68327fb52276d68437e8467886ce81de297 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Jul 2006 17:28:10 +0000 Subject: [PATCH 0993/1514] add new PA_SOURCE_HARDWARE/PA_SINK_HARDWARE flag git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1091 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/def.h | 6 ++++-- src/pulsecore/protocol-native.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/pulse/def.h b/src/pulse/def.h index b98337d29..06d4c7c2b 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -295,13 +295,15 @@ typedef enum pa_seek_mode { /** Special sink flags. \since 0.8 */ typedef enum pa_sink_flags { PA_SINK_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ - PA_SINK_LATENCY = 2 /**< Supports latency querying */ + PA_SINK_LATENCY = 2, /**< Supports latency querying */ + PA_SINK_HARDWARE = 4 /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks */ } pa_sink_flags_t; /** Special source flags. \since 0.8 */ typedef enum pa_source_flags { PA_SOURCE_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ - PA_SOURCE_LATENCY = 2 /**< Supports latency querying */ + PA_SOURCE_LATENCY = 2, /**< Supports latency querying */ + PA_SOURCE_HARDWARE = 4 /**< Is a hardware source of some kind, in contrast to "virtual"/software source */ } pa_source_flags_t; /** A generic free() like callback prototype */ diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index f77c9c24f..784610bd8 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1265,7 +1265,10 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { PA_TAG_STRING, sink->monitor_source->name, PA_TAG_USEC, pa_sink_get_latency(sink), PA_TAG_STRING, sink->driver, - PA_TAG_U32, (sink->get_hw_volume ? PA_SINK_HW_VOLUME_CTRL : 0) | (sink->get_latency ? PA_SINK_LATENCY : 0), + PA_TAG_U32, + (sink->get_hw_volume ? PA_SINK_HW_VOLUME_CTRL : 0) | + (sink->get_latency ? PA_SINK_LATENCY : 0) | + (sink->is_hardware ? PA_SINK_HARDWARE : 0), PA_TAG_INVALID); } @@ -1285,7 +1288,10 @@ static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL, PA_TAG_USEC, pa_source_get_latency(source), PA_TAG_STRING, source->driver, - PA_TAG_U32, (source->get_hw_volume ? PA_SOURCE_HW_VOLUME_CTRL : 0) | (source->get_latency ? PA_SOURCE_LATENCY : 0), + PA_TAG_U32, + (source->get_hw_volume ? PA_SOURCE_HW_VOLUME_CTRL : 0) | + (source->get_latency ? PA_SOURCE_LATENCY : 0) | + (source->is_hardware ? PA_SOURCE_HARDWARE : 0), PA_TAG_INVALID); } From b91dd2381bffeb0a4b5450ef4ce1f0031909f79a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Jul 2006 17:28:41 +0000 Subject: [PATCH 0994/1514] set is_hardware flag for a few hw plugins git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1092 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 1 + src/modules/module-alsa-source.c | 1 + src/modules/module-oss-mmap.c | 2 ++ src/modules/module-oss.c | 2 ++ src/modules/module-solaris.c | 2 ++ src/modules/module-waveout.c | 2 ++ 6 files changed, 10 insertions(+) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 9238072b5..d5abdc286 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -383,6 +383,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + u->sink->is_hardware = 1; u->sink->get_latency = sink_get_latency_cb; if (u->mixer_handle) { assert(u->mixer_elem); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 68c61be97..ca4ac9d0f 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -376,6 +376,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + u->source->is_hardware = 1; u->source->userdata = u; u->source->get_latency = source_get_latency_cb; if (u->mixer_handle) { diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index fcc89c845..d6f376339 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -444,6 +444,7 @@ int pa__init(pa_core *c, pa_module*m) { hwdesc[0] ? " (" : "", hwdesc[0] ? hwdesc : "", hwdesc[0] ? ")" : ""); + u->source->is_hardware = 1; u->in_memblocks = pa_xnew0(pa_memblock*, u->in_fragments); @@ -485,6 +486,7 @@ int pa__init(pa_core *c, pa_module*m) { hwdesc[0] ? hwdesc : "", hwdesc[0] ? ")" : ""); + u->sink->is_hardware = 1; u->out_memblocks = pa_xmalloc0(sizeof(struct memblock *)*u->out_fragments); enable_bits |= PCM_ENABLE_OUTPUT; diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index a3ea2c1f5..cde7f3119 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -418,6 +418,7 @@ int pa__init(pa_core *c, pa_module*m) { hwdesc[0] ? " (" : "", hwdesc[0] ? hwdesc : "", hwdesc[0] ? ")" : ""); + u->source->is_hardware = 1; } else u->source = NULL; @@ -435,6 +436,7 @@ int pa__init(pa_core *c, pa_module*m) { hwdesc[0] ? " (" : "", hwdesc[0] ? hwdesc : "", hwdesc[0] ? ")" : ""); + u->sink->is_hardware = 1; } else u->sink = NULL; diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 12c4a3ffd..02ef4bc4a 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -555,6 +555,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source->set_hw_volume = source_set_hw_volume_cb; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + u->source->is_hardware = 1; } else u->source = NULL; @@ -569,6 +570,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + u->sink->is_hardware = 1; } else u->sink = NULL; diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 2bd4905ac..8fd60b6ac 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -504,6 +504,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source->get_latency = source_get_latency_cb; pa_source_set_owner(u->source, m); u->source->description = pa_sprintf_malloc("Windows waveIn PCM"); + u->source->is_hardware = 1; } else u->source = NULL; @@ -517,6 +518,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->userdata = u; pa_sink_set_owner(u->sink, m); u->sink->description = pa_sprintf_malloc("Windows waveOut PCM"); + u->sink->is_hardware = 1; } else u->sink = NULL; From 3b2843d5a8d50d6f9c3f5bedd63e3cc429c7ea13 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Jul 2006 17:29:09 +0000 Subject: [PATCH 0995/1514] show value of PA_SINK_HARDWARE/PA_SOURCE_HARDWARE in pactl git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1093 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 94d22f987..25ef324d3 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -174,7 +174,7 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ "Volume: %s\n" "Monitor Source: %u\n" "Latency: %0.0f usec\n" - "Flags: %s%s\n", + "Flags: %s%s%s\n", i->index, i->name, i->driver, @@ -186,7 +186,8 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ i->monitor_source, (double) i->latency, i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", - i->flags & PA_SINK_LATENCY ? "LATENCY" : ""); + i->flags & PA_SINK_LATENCY ? "LATENCY " : "", + i->flags & PA_SINK_HARDWARE ? "HARDWARE" : ""); } @@ -222,7 +223,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int "Volume: %s\n" "Monitor of Sink: %s\n" "Latency: %0.0f usec\n" - "Flags: %s%s\n", + "Flags: %s%s%s\n", i->index, i->driver, i->name, @@ -234,7 +235,8 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int i->monitor_of_sink != PA_INVALID_INDEX ? t : "no", (double) i->latency, i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", - i->flags & PA_SOURCE_LATENCY ? "LATENCY" : ""); + i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", + i->flags & PA_SOURCE_HARDWARE ? "HARDWARE" : ""); } From 9ced7f62a7a453242eee9b56a0c5158753712ef4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Jul 2006 17:38:45 +0000 Subject: [PATCH 0996/1514] show summary after "configure" has run (closes: #22) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1094 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/configure.ac b/configure.ac index a36ee5a04..10f511c6e 100644 --- a/configure.ac +++ b/configure.ac @@ -680,3 +680,80 @@ doxygen/doxygen.conf src/pulse/version.h ]) AC_OUTPUT + +# ========================================================================== +ENABLE_X11=no +if test "x$HAVE_X11" = "x1" ; then + ENABLE_X11=yes +fi + +ENABLE_OSS=no +if test "x$HAVE_OSS" = "x1" ; then + ENABLE_OSS=yes +fi + +ENABLE_ALSA=no +if test "x$HAVE_ALSA" = "x1" ; then + ENABLE_ALSA=yes +fi + +ENABLE_SOLARIS=no +if test "x$HAVE_SOLARIS" = "x1" ; then + ENABLE_SOLARIS=yes +fi + +ENABLE_GLIB20=no +if test "x$HAVE_GLIB20" = "x1" ; then + ENABLE_GLIB20=yes +fi + +ENABLE_GLIB12=no +if test "x$HAVE_GLIB12" = "x1" ; then + ENABLE_GLIB12=yes +fi + +ENABLE_AVAHI=no +if test "x$HAVE_AVAHI" = "x1" ; then + ENABLE_AVAHI=yes +fi + +ENABLE_JACK=no +if test "x$HAVE_JACK" = "x1" ; then + ENABLE_JACK=yes +fi + +ENABLE_LIBASYNCNS=no +if test "x$HAVE_LIBASYNCNS" = "x1" ; then + ENABLE_LIBASYNCNS=yes +fi + +ENABLE_LIRC=no +if test "x$HAVE_LIRC" = "x1" ; then + ENABLE_LIRC=yes +fi + +ENABLE_TCPWRAP=no +if test "x${LIBWRAP_LIBS}" != x ; then + ENABLE_TCPWRAP=yes +fi + +echo " + ---{ $PACKAGE_NAME $VERSION }--- + + prefix: ${prefix} + sysconfdir: ${sysconfdir} + localstatedir: ${localstatedir} + compiler: ${CC} + cflags: ${CFLAGS} + Have X11: ${ENABLE_X11} + Enable OSS: ${ENABLE_OSS} + Enable Alsa: ${ENABLE_ALSA} + Enable Solaris: ${ENABLE_SOLARIS} + Enable Glib 2.0: ${ENABLE_GLIB20} + Enable Glib 1.2: ${ENABLE_GLIB12} + Enable Avahi: ${ENABLE_AVAHI} + Enable Jack: ${ENABLE_JACK} + Enable Async DNS: ${ENABLE_LIBASYNCNS} + Enable LIRC: ${ENABLE_LIRC} + Enable TCP Wrappers: ${ENABLE_TCPWRAP} +" From e45b1dceaf290b9a49893b5237127717773518d3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Jul 2006 17:42:29 +0000 Subject: [PATCH 0997/1514] todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1095 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index 2c98c4eda..07d022b71 100644 --- a/todo +++ b/todo @@ -32,7 +32,6 @@ Post 0.9.0: - gconf module + frontend - hooks for creating sink inputs - insert the low-level device name in the default sink/source name, to make them recognizable -- add new flag for distuinguishing hw sinks/sources from virtual sink/sources Long term: - pass meta info for hearing impaired From ba31adcf3ebb542931fb6d66f2e1fc7689dfc712 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Jul 2006 23:20:27 +0000 Subject: [PATCH 0998/1514] make pulseaudio compile again on FreeBSD (patch from Diego "Flameeyes" Petteno) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1096 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 3 ++ src/modules/rtp/module-rtp-recv.c | 2 +- src/modules/rtp/sap.c | 1 + src/modules/rtp/sdp.c | 1 + src/utils/padsp.c | 58 +++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 10f511c6e..80473415c 100644 --- a/configure.ac +++ b/configure.ac @@ -249,6 +249,9 @@ ACX_PTHREAD AC_SYS_LARGEFILE +# Check for open64 to know if the current system does have open64() and similar functions +AC_CHECK_FUNCS([open64]) + #### [lib]iconv #### AM_ICONV diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 932da8493..0359a43bf 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -236,7 +236,7 @@ static int mcast_socket(const struct sockaddr* sa, socklen_t salen) { struct ipv6_mreq mr6; memset(&mr6, 0, sizeof(mr6)); mr6.ipv6mr_multiaddr = ((const struct sockaddr_in6*) sa)->sin6_addr; - r = setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr6, sizeof(mr6)); + r = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr6, sizeof(mr6)); } if (r < 0) { diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index 3814a1c3d..615b8e4eb 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index cada636a4..e707e4bb5 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b1636754b..32cb5f9a3 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,9 @@ #include #include +#ifdef __linux__ #include +#endif #include #include @@ -101,8 +104,10 @@ static int (*_ioctl)(int, int, void*) = NULL; static int (*_close)(int) = NULL; static int (*_open)(const char *, int, mode_t) = NULL; static FILE* (*_fopen)(const char *path, const char *mode) = NULL; +#ifdef HAVE_OPEN64 static int (*_open64)(const char *, int, mode_t) = NULL; static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; +#endif static int (*_fclose)(FILE *f) = NULL; static int (*_access)(const char *, int) = NULL; @@ -1302,7 +1307,11 @@ static int sndstat_open(int flags, int *_errno) { debug(DEBUG_LEVEL_NORMAL, __FILE__": sndstat_open()\n"); - if (flags != O_RDONLY && flags != (O_RDONLY|O_LARGEFILE)) { + if (flags != O_RDONLY +#ifdef O_LARGEFILE + && flags != (O_RDONLY|O_LARGEFILE) +#endif + ) { *_errno = EACCES; debug(DEBUG_LEVEL_NORMAL, __FILE__": bad access!\n"); goto fail; @@ -1349,8 +1358,12 @@ int open(const char *filename, int flags, ...) { debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename); va_start(args, flags); - if (flags & O_CREAT) + if (flags & O_CREAT) { + if (sizeof(mode_t) < sizeof(int)) + mode = va_arg(args, int); + else mode = va_arg(args, mode_t); + } va_end(args); if (!function_enter()) { @@ -1587,6 +1600,7 @@ static int map_format_back(pa_sample_format_t format) { } static int dsp_flush_fd(int fd) { +#ifdef SIOCINQ int l; if (ioctl(fd, SIOCINQ, &l) < 0) { @@ -1605,6 +1619,10 @@ static int dsp_flush_fd(int fd) { } return 0; +#else +# warning "Your platform does not support SIOCINQ, something might not work as intended." + return 0; +#endif } static int dsp_flush_socket(fd_info *i) { @@ -1629,6 +1647,7 @@ static int dsp_flush_socket(fd_info *i) { } static int dsp_empty_socket(fd_info *i) { +#ifdef SIOCINQ int ret = -1; /* Empty the socket */ @@ -1652,6 +1671,10 @@ static int dsp_empty_socket(fd_info *i) { } return ret; +#else +# warning "Your platform does not support SIOCINQ, something might not work as intended." + return 0; +#endif } static int dsp_drain(fd_info *i) { @@ -1864,7 +1887,11 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETCAPS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n"); - *(int*) argp = DSP_CAP_DUPLEX | DSP_CAP_MULTI; + *(int*) argp = DSP_CAP_DUPLEX +#ifdef DSP_CAP_MULTI + | DSP_CAP_MULTI +#endif + ; break; case SNDCTL_DSP_GETODELAY: { @@ -1895,11 +1922,15 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } exit_loop: - + +#ifdef SIOCINQ if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); else *(int*) argp += l; +#else +# warning "Your platform does not support SIOCINQ, something might not work as intended." +#endif pa_threaded_mainloop_unlock(i->mainloop); @@ -1946,7 +1977,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETOSPACE: case SNDCTL_DSP_GETISPACE: { audio_buf_info *bi = (audio_buf_info*) argp; - int l; + int l = 0; size_t k = 0; if (request == SNDCTL_DSP_GETOSPACE) @@ -1965,10 +1996,14 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } else k = i->fragment_size * i->n_fragments; +#ifdef SIOCINQ if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); l = 0; } +#else +# warning "Your platform does not dsp_flush_fd, something might not work as intended." +#endif bi->bytes = k > (size_t) l ? k - l : 0; } else { @@ -1978,11 +2013,14 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) } else k = 0; +#ifdef SIOCINQ if (ioctl(i->app_fd, SIOCINQ, &l) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); l = 0; } - +#else +# warning "Your platform does not dsp_flush_fd, something might not work as intended." +#endif bi->bytes = k + l; } @@ -2104,6 +2142,8 @@ int access(const char *pathname, int mode) { return 0; } +#ifdef HAVE_OPEN64 + int open64(const char *filename, int flags, ...) { va_list args; mode_t mode = 0; @@ -2126,6 +2166,8 @@ int open64(const char *filename, int flags, ...) { return open(filename, flags, mode); } +#endif + FILE* fopen(const char *filename, const char *mode) { FILE *f = NULL; int fd; @@ -2168,6 +2210,8 @@ FILE* fopen(const char *filename, const char *mode) { return f; } +#ifdef HAVE_OPEN64 + FILE *fopen64(const char *filename, const char *mode) { debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename); @@ -2183,6 +2227,8 @@ FILE *fopen64(const char *filename, const char *mode) { return fopen(filename, mode); } +#endif + int fclose(FILE *f) { fd_info *i; From 4b352e5fac5ff546315139f7b791074261544f66 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 17 Jul 2006 11:26:29 +0000 Subject: [PATCH 0999/1514] Restore SIGPIPE warning when the platform doesn't have MSG_NOSIGNAL. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1097 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 6 ++++++ src/pulsecore/core-util.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/pulse/context.c b/src/pulse/context.c index 5724765be..228053bcf 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -132,6 +132,12 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { memset(&c->spawn_api, 0, sizeof(c->spawn_api)); c->do_autospawn = 0; +#ifndef MSG_NOSIGNAL +#ifdef SIGPIPE + pa_check_signal_is_blocked(SIGPIPE); +#endif +#endif + c->conf = pa_client_conf_new(); pa_client_conf_load(c->conf, NULL); #ifdef HAVE_X11 diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 16c3631f6..7cb85209c 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -78,6 +78,11 @@ #include "core-util.h" +/* Not all platforms have this */ +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + #ifndef OS_IS_WIN32 #define PA_RUNTIME_PATH_PREFIX "/tmp/pulse-" #define PATH_SEP '/' From f5afb7b6d06d78e63e714cbf3617b1bd372b2e7d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 17 Jul 2006 11:42:25 +0000 Subject: [PATCH 1000/1514] Forgot to protect one access to with_creds with an ifdef. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1098 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pstream.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index e9b6f4c80..7992ccb66 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -291,7 +291,9 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa i->channel = channel; i->offset = offset; i->seek_mode = seek_mode; +#ifdef SCM_CREDENTIALS i->with_creds = 0; +#endif pa_memblock_ref(i->chunk.memblock); From 64d87ac36329d76d220c437bf56c665f1f839ea5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 17 Jul 2006 21:20:31 +0000 Subject: [PATCH 1001/1514] change licensing blurb form "Library GPL" to "Lesser GPL" on request of Loic Minier. Effectively this means using the same license blurb like in all other source files. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1099 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pipe.c | 32 ++++++++++++++++---------------- src/pulsecore/pipe.h | 32 ++++++++++++++++---------------- src/pulsecore/poll.c | 32 ++++++++++++++++++-------------- src/pulsecore/poll.h | 32 ++++++++++++++++++-------------- 4 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/pulsecore/pipe.c b/src/pulsecore/pipe.c index 6933e180d..41ffb693b 100644 --- a/src/pulsecore/pipe.c +++ b/src/pulsecore/pipe.c @@ -1,22 +1,22 @@ /* $Id$ */ /*** - This file is part of PulseAudio. - - PulseAudio is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with PulseAudio; If not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. ***/ #ifdef HAVE_CONFIG_H diff --git a/src/pulsecore/pipe.h b/src/pulsecore/pipe.h index a25147603..21049e17f 100644 --- a/src/pulsecore/pipe.h +++ b/src/pulsecore/pipe.h @@ -4,22 +4,22 @@ /* $Id$ */ /*** - This file is part of PulseAudio. - - PulseAudio is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with PulseAudio; If not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. ***/ #ifndef HAVE_PIPE diff --git a/src/pulsecore/poll.c b/src/pulsecore/poll.c index 3f9ace7c0..289e0cdf2 100644 --- a/src/pulsecore/poll.c +++ b/src/pulsecore/poll.c @@ -5,21 +5,25 @@ Copyright (C) 2005, Cendio AB. This file is part of PulseAudio. Based on work for the GNU C Library. +***/ - PulseAudio is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with PulseAudio; If not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. ***/ /* Poll the file descriptors described by the NFDS structures starting at diff --git a/src/pulsecore/poll.h b/src/pulsecore/poll.h index bed772c78..c3d486e14 100644 --- a/src/pulsecore/poll.h +++ b/src/pulsecore/poll.h @@ -6,21 +6,25 @@ Copyright (C) 2005, Cendio AB. This file is part of PulseAudio. Based on work for the GNU C Library. +***/ - PulseAudio is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with PulseAudio; If not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. ***/ /* Event types that can be polled for. These bits may be set in `events' From ddd5acf5535b3a97af56987bb26ce152bdd772a3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Jul 2006 18:51:35 +0000 Subject: [PATCH 1002/1514] define proper typdefs for callback prototypes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1100 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/mainloop-api.h | 43 +++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/pulse/mainloop-api.h b/src/pulse/mainloop-api.h index 4aaeccf58..7b7075ae2 100644 --- a/src/pulse/mainloop-api.h +++ b/src/pulse/mainloop-api.h @@ -44,6 +44,9 @@ PA_C_DECL_BEGIN +/** An abstract mainloop API vtable */ +typedef struct pa_mainloop_api pa_mainloop_api; + /** A bitmask for IO events */ typedef enum pa_io_event_flags { PA_IO_EVENT_NULL = 0, /**< No event */ @@ -55,15 +58,24 @@ typedef enum pa_io_event_flags { /** An opaque IO event source object */ typedef struct pa_io_event pa_io_event; - -/** An opaque deferred event source object. Events of this type are triggered once in every main loop iteration */ -typedef struct pa_defer_event pa_defer_event; +/** An IO event callback protoype \since 0.9.3 */ +typedef void (*pa_io_event_cb_t)(pa_mainloop_api*ea, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata); +/** A IO event destroy callback prototype \ since 0.9.3 */ +typedef void (*pa_io_event_destroy_cb_t)(pa_mainloop_api*a, pa_io_event *e, void *userdata); /** An opaque timer event source object */ typedef struct pa_time_event pa_time_event; +/** A time event callback prototype \since 0.9.3 */ +typedef void (*pa_time_event_cb_t)(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata); +/** A time event destroy callback prototype \ since 0.9.3 */ +typedef void (*pa_time_event_destroy_cb_t)(pa_mainloop_api*a, pa_time_event *e, void *userdata); -/** An abstract mainloop API vtable */ -typedef struct pa_mainloop_api pa_mainloop_api; +/** An opaque deferred event source object. Events of this type are triggered once in every main loop iteration */ +typedef struct pa_defer_event pa_defer_event; +/** A defer event callback protoype \since 0.9.3 */ +typedef void (*pa_defer_event_cb_t)(pa_mainloop_api*a, pa_defer_event* e, void *userdata); +/** A defer event destroy callback prototype \ since 0.9.3 */ +typedef void (*pa_defer_event_destroy_cb_t)(pa_mainloop_api*a, pa_defer_event *e, void *userdata); /** An abstract mainloop API vtable */ struct pa_mainloop_api { @@ -71,40 +83,31 @@ struct pa_mainloop_api { void *userdata; /** Create a new IO event source object */ - pa_io_event* (*io_new)(pa_mainloop_api*a, int fd, pa_io_event_flags_t events, void (*callback) (pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata); - + pa_io_event* (*io_new)(pa_mainloop_api*a, int fd, pa_io_event_flags_t events, pa_io_event_cb_t cb, void *userdata); /** Enable or disable IO events on this object */ void (*io_enable)(pa_io_event* e, pa_io_event_flags_t events); - /** Free a IO event source object */ void (*io_free)(pa_io_event* e); - /** Set a function that is called when the IO event source is destroyed. Use this to free the userdata argument if required */ - void (*io_set_destroy)(pa_io_event *e, void (*callback) (pa_mainloop_api*a, pa_io_event *e, void *userdata)); + void (*io_set_destroy)(pa_io_event *e, pa_io_event_destroy_cb_t cb); /** Create a new timer event source object for the specified Unix time */ - pa_time_event* (*time_new)(pa_mainloop_api*a, const struct timeval *tv, void (*callback) (pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata), void *userdata); - + pa_time_event* (*time_new)(pa_mainloop_api*a, const struct timeval *tv, pa_time_event_cb_t cb, void *userdata); /** Restart a running or expired timer event source with a new Unix time */ void (*time_restart)(pa_time_event* e, const struct timeval *tv); - /** Free a deferred timer event source object */ void (*time_free)(pa_time_event* e); - /** Set a function that is called when the timer event source is destroyed. Use this to free the userdata argument if required */ - void (*time_set_destroy)(pa_time_event *e, void (*callback) (pa_mainloop_api*a, pa_time_event *e, void *userdata)); + void (*time_set_destroy)(pa_time_event *e, pa_time_event_destroy_cb_t cb); /** Create a new deferred event source object */ - pa_defer_event* (*defer_new)(pa_mainloop_api*a, void (*callback) (pa_mainloop_api*a, pa_defer_event* e, void *userdata), void *userdata); - + pa_defer_event* (*defer_new)(pa_mainloop_api*a, pa_defer_event_cb_t cb, void *userdata); /** Enable or disable a deferred event source temporarily */ void (*defer_enable)(pa_defer_event* e, int b); - /** Free a deferred event source object */ void (*defer_free)(pa_defer_event* e); - /** Set a function that is called when the deferred event source is destroyed. Use this to free the userdata argument if required */ - void (*defer_set_destroy)(pa_defer_event *e, void (*callback) (pa_mainloop_api*a, pa_defer_event *e, void *userdata)); + void (*defer_set_destroy)(pa_defer_event *e, pa_defer_event_destroy_cb_t cb); /** Exit the main loop and return the specfied retval*/ void (*quit)(pa_mainloop_api*a, int retval); From 2c2abbb1698c6fa0607d4db2a20efce141a0f8c5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Jul 2006 18:52:13 +0000 Subject: [PATCH 1003/1514] turn the glib adapter into a single GSource instead of creating a bunch of seperate GSources for each event git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1101 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/glib-mainloop.c | 800 +++++++++++++++++++++----------------- 1 file changed, 450 insertions(+), 350 deletions(-) diff --git a/src/pulse/glib-mainloop.c b/src/pulse/glib-mainloop.c index 25848ece3..cdaecdf83 100644 --- a/src/pulse/glib-mainloop.c +++ b/src/pulse/glib-mainloop.c @@ -30,365 +30,546 @@ #include #include +#include +#include -#include "glib.h" +#include #include "glib-mainloop.h" struct pa_io_event { pa_glib_mainloop *mainloop; int dead; - GIOChannel *io_channel; - GSource *source; - GIOCondition io_condition; - int fd; - void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata); + + GPollFD poll_fd; + int poll_fd_added; + + pa_io_event_cb_t callback; void *userdata; - void (*destroy_callback) (pa_mainloop_api *m, pa_io_event *e, void *userdata); - pa_io_event *next, *prev; + pa_io_event_destroy_cb_t destroy_callback; + + PA_LLIST_FIELDS(pa_io_event); }; struct pa_time_event { pa_glib_mainloop *mainloop; int dead; - GSource *source; + + int enabled; struct timeval timeval; - void (*callback) (pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata); + + pa_time_event_cb_t callback; void *userdata; - void (*destroy_callback) (pa_mainloop_api *m, pa_time_event*e, void *userdata); - pa_time_event *next, *prev; + pa_time_event_destroy_cb_t destroy_callback; + + PA_LLIST_FIELDS(pa_time_event); }; struct pa_defer_event { pa_glib_mainloop *mainloop; int dead; - GSource *source; - void (*callback) (pa_mainloop_api*m, pa_defer_event *e, void *userdata); + + int enabled; + + pa_defer_event_cb_t callback; void *userdata; - void (*destroy_callback) (pa_mainloop_api *m, pa_defer_event*e, void *userdata); - pa_defer_event *next, *prev; + pa_defer_event_destroy_cb_t destroy_callback; + + PA_LLIST_FIELDS(pa_defer_event); }; struct pa_glib_mainloop { - GMainContext *glib_main_context; + GSource source; + pa_mainloop_api api; - GSource *cleanup_source; - pa_io_event *io_events, *dead_io_events; - pa_time_event *time_events, *dead_time_events; - pa_defer_event *defer_events, *dead_defer_events; + GMainContext *context; + + PA_LLIST_HEAD(pa_io_event, io_events); + PA_LLIST_HEAD(pa_time_event, time_events); + PA_LLIST_HEAD(pa_defer_event, defer_events); + + int n_enabled_defer_events, n_enabled_time_events; + int io_events_please_scan, time_events_please_scan, defer_events_please_scan; + + pa_time_event *cached_next_time_event; }; -static void schedule_free_dead_events(pa_glib_mainloop *g); +static void cleanup_io_events(pa_glib_mainloop *g, int force) { + pa_io_event *e; -static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f); + e = g->io_events; + while (e) { + pa_io_event *n = e->next; -static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags_t f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata), void *userdata) { + if (!force && g->io_events_please_scan <= 0) + break; + + if (force || e->dead) { + PA_LLIST_REMOVE(pa_io_event, g->io_events, e); + + if (e->dead) + g->io_events_please_scan--; + + if (e->poll_fd_added) + g_source_remove_poll(&g->source, &e->poll_fd); + + if (e->destroy_callback) + e->destroy_callback(&g->api, e, e->userdata); + + pa_xfree(e); + } + + e = n; + } + + assert(g->io_events_please_scan == 0); +} + +static void cleanup_time_events(pa_glib_mainloop *g, int force) { + pa_time_event *e; + + e = g->time_events; + while (e) { + pa_time_event *n = e->next; + + if (!force && g->time_events_please_scan <= 0) + break; + + if (force || e->dead) { + PA_LLIST_REMOVE(pa_time_event, g->time_events, e); + + if (e->dead) + g->time_events_please_scan--; + + if (!e->dead && e->enabled) + g->n_enabled_time_events--; + + if (e->destroy_callback) + e->destroy_callback(&g->api, e, e->userdata); + + pa_xfree(e); + } + + e = n; + } + + assert(g->time_events_please_scan == 0); +} + +static void cleanup_defer_events(pa_glib_mainloop *g, int force) { + pa_defer_event *e; + + e = g->defer_events; + while (e) { + pa_defer_event *n = e->next; + + if (!force && g->defer_events_please_scan <= 0) + break; + + if (force || e->dead) { + PA_LLIST_REMOVE(pa_defer_event, g->defer_events, e); + + if (e->dead) + g->defer_events_please_scan--; + + if (!e->dead && e->enabled) + g->n_enabled_defer_events--; + + if (e->destroy_callback) + e->destroy_callback(&g->api, e, e->userdata); + + pa_xfree(e); + } + + e = n; + } + + assert(g->defer_events_please_scan == 0); +} + +static gushort map_flags_to_glib(pa_io_event_flags_t flags) { + return + (flags & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | + (flags & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) | + (flags & PA_IO_EVENT_ERROR ? G_IO_ERR : 0) | + (flags & PA_IO_EVENT_HANGUP ? G_IO_HUP : 0); +} + +static pa_io_event_flags_t map_flags_from_glib(gushort flags) { + return + (flags & G_IO_IN ? PA_IO_EVENT_INPUT : 0) | + (flags & G_IO_OUT ? PA_IO_EVENT_OUTPUT : 0) | + (flags & G_IO_ERR ? PA_IO_EVENT_ERROR : 0) | + (flags & G_IO_HUP ? PA_IO_EVENT_HANGUP : 0); +} + +static pa_io_event* glib_io_new( + pa_mainloop_api*m, + int fd, + pa_io_event_flags_t f, + pa_io_event_cb_t cb, + void *userdata) { + pa_io_event *e; pa_glib_mainloop *g; - assert(m && m->userdata && fd >= 0 && callback); + assert(m); + assert(m->userdata); + assert(fd >= 0); + assert(cb); + g = m->userdata; - e = pa_xmalloc(sizeof(pa_io_event)); - e->mainloop = m->userdata; + e = pa_xnew(pa_io_event, 1); + e->mainloop = g; e->dead = 0; - e->fd = fd; - e->callback = callback; + + e->poll_fd.fd = fd; + e->poll_fd.events = map_flags_to_glib(f); + e->poll_fd.revents = 0; + + e->callback = cb; e->userdata = userdata; e->destroy_callback = NULL; - e->io_channel = g_io_channel_unix_new(e->fd); - assert(e->io_channel); - e->source = NULL; - e->io_condition = 0; + PA_LLIST_PREPEND(pa_io_event, g->io_events, e); - glib_io_enable(e, f); - - e->next = g->io_events; - if (e->next) e->next->prev = e; - g->io_events = e; - e->prev = NULL; + g_source_add_poll(&g->source, &e->poll_fd); + e->poll_fd_added = 1; return e; } -/* The callback GLIB calls whenever an IO condition is met */ -static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) { - pa_io_event *e = data; - pa_io_event_flags_t f; - assert(source && e && e->io_channel == source); - - f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) | - (condition & G_IO_OUT ? PA_IO_EVENT_OUTPUT : 0) | - (condition & G_IO_ERR ? PA_IO_EVENT_ERROR : 0) | - (condition & G_IO_HUP ? PA_IO_EVENT_HANGUP : 0); - - e->callback(&e->mainloop->api, e, e->fd, f, e->userdata); - return TRUE; -} - static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) { - GIOCondition c; - assert(e && !e->dead); + assert(e); + assert(!e->dead); - c = (f & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | (f & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0); - - if (c == e->io_condition) - return; - - if (e->source) { - g_source_destroy(e->source); - g_source_unref(e->source); - } - - e->source = g_io_create_watch(e->io_channel, c | G_IO_ERR | G_IO_HUP); - assert(e->source); - - g_source_set_callback(e->source, (GSourceFunc) io_cb, e, NULL); - g_source_attach(e->source, e->mainloop->glib_main_context); - g_source_set_priority(e->source, G_PRIORITY_DEFAULT); - - e->io_condition = c; + e->poll_fd.events = map_flags_to_glib(f); } static void glib_io_free(pa_io_event*e) { - assert(e && !e->dead); - - if (e->source) { - g_source_destroy(e->source); - g_source_unref(e->source); - e->source = NULL; - } - - if (e->prev) - e->prev->next = e->next; - else - e->mainloop->io_events = e->next; - - if (e->next) - e->next->prev = e->prev; - - if ((e->next = e->mainloop->dead_io_events)) - e->next->prev = e; - - e->mainloop->dead_io_events = e; - e->prev = NULL; + assert(e); + assert(!e->dead); e->dead = 1; - schedule_free_dead_events(e->mainloop); + e->mainloop->io_events_please_scan++; + + if (e->poll_fd_added) { + g_source_remove_poll(&e->mainloop->source, &e->poll_fd); + e->poll_fd_added = 0; + } } -static void glib_io_set_destroy(pa_io_event*e, void (*callback)(pa_mainloop_api*m, pa_io_event *e, void *userdata)) { +static void glib_io_set_destroy(pa_io_event*e, pa_io_event_destroy_cb_t cb) { assert(e); - e->destroy_callback = callback; + assert(!e->dead); + + e->destroy_callback = cb; } /* Time sources */ -static void glib_time_restart(pa_time_event*e, const struct timeval *tv); - -static pa_time_event* glib_time_new(pa_mainloop_api*m, const struct timeval *tv, void (*callback) (pa_mainloop_api*m, pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { +static pa_time_event* glib_time_new( + pa_mainloop_api*m, + const struct timeval *tv, + pa_time_event_cb_t cb, + void *userdata) { + pa_glib_mainloop *g; pa_time_event *e; - assert(m && m->userdata && tv && callback); + assert(m); + assert(m->userdata); + assert(cb); + g = m->userdata; - e = pa_xmalloc(sizeof(pa_time_event)); + e = pa_xnew(pa_time_event, 1); e->mainloop = g; e->dead = 0; - e->callback = callback; + + if ((e->enabled = !!tv)) { + e->timeval = *tv; + g->n_enabled_time_events++; + + if (g->cached_next_time_event) { + g_assert(g->cached_next_time_event->enabled); + + if (pa_timeval_cmp(tv, &g->cached_next_time_event->timeval) < 0) + g->cached_next_time_event = e; + } + } + + e->callback = cb; e->userdata = userdata; e->destroy_callback = NULL; - e->source = NULL; - glib_time_restart(e, tv); - - e->next = g->time_events; - if (e->next) e->next->prev = e; - g->time_events = e; - e->prev = NULL; + PA_LLIST_PREPEND(pa_time_event, g->time_events, e); return e; } -static guint msec_diff(const struct timeval *a, const struct timeval *b) { - guint r; - assert(a && b); - - if (a->tv_sec < b->tv_sec) - return 0; - - if (a->tv_sec == b->tv_sec && a->tv_sec <= b->tv_sec) - return 0; - - r = (a->tv_sec-b->tv_sec)*1000; - - if (a->tv_usec >= b->tv_usec) - r += (a->tv_usec - b->tv_usec) / 1000; - else - r -= (b->tv_usec - a->tv_usec) / 1000; - - return r; -} - -static gboolean time_cb(gpointer data) { - pa_time_event* e = data; - assert(e && e->mainloop && e->source); - - g_source_unref(e->source); - e->source = NULL; - - e->callback(&e->mainloop->api, e, &e->timeval, e->userdata); - return FALSE; -} - static void glib_time_restart(pa_time_event*e, const struct timeval *tv) { - struct timeval now; - assert(e && e->mainloop && !e->dead); + assert(e); + assert(!e->dead); - pa_gettimeofday(&now); - if (e->source) { - g_source_destroy(e->source); - g_source_unref(e->source); - } + if (e->enabled && !!tv) + e->mainloop->n_enabled_time_events--; + else if (!e->enabled && tv) + e->mainloop->n_enabled_time_events++; - if (tv) { + if ((e->enabled = !!tv)) e->timeval = *tv; - e->source = g_timeout_source_new(msec_diff(tv, &now)); - assert(e->source); - g_source_set_callback(e->source, time_cb, e, NULL); - g_source_set_priority(e->source, G_PRIORITY_DEFAULT); - g_source_attach(e->source, e->mainloop->glib_main_context); - } else - e->source = NULL; + + if (e->mainloop->cached_next_time_event && e->enabled) { + g_assert(e->mainloop->cached_next_time_event->enabled); + + if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0) + e->mainloop->cached_next_time_event = e; + } else if (e->mainloop->cached_next_time_event == e) + e->mainloop->cached_next_time_event = NULL; } static void glib_time_free(pa_time_event *e) { - assert(e && e->mainloop && !e->dead); - - if (e->source) { - g_source_destroy(e->source); - g_source_unref(e->source); - e->source = NULL; - } - - if (e->prev) - e->prev->next = e->next; - else - e->mainloop->time_events = e->next; - - if (e->next) - e->next->prev = e->prev; - - if ((e->next = e->mainloop->dead_time_events)) - e->next->prev = e; - - e->mainloop->dead_time_events = e; - e->prev = NULL; + assert(e); + assert(!e->dead); e->dead = 1; - schedule_free_dead_events(e->mainloop); + e->mainloop->time_events_please_scan++; + + if (e->enabled) + e->mainloop->n_enabled_time_events--; + + if (e->mainloop->cached_next_time_event == e) + e->mainloop->cached_next_time_event = NULL; } -static void glib_time_set_destroy(pa_time_event *e, void (*callback)(pa_mainloop_api*m, pa_time_event*e, void *userdata)) { +static void glib_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb) { assert(e); - e->destroy_callback = callback; + assert(!e->dead); + + e->destroy_callback = cb; } /* Deferred sources */ -static void glib_defer_enable(pa_defer_event *e, int b); - -static pa_defer_event* glib_defer_new(pa_mainloop_api*m, void (*callback) (pa_mainloop_api*m, pa_defer_event *e, void *userdata), void *userdata) { +static pa_defer_event* glib_defer_new( + pa_mainloop_api*m, + pa_defer_event_cb_t cb, + void *userdata) { + pa_defer_event *e; pa_glib_mainloop *g; - assert(m && m->userdata && callback); + assert(m); + assert(m->userdata); + assert(cb); + g = m->userdata; - e = pa_xmalloc(sizeof(pa_defer_event)); + e = pa_xnew(pa_defer_event, 1); e->mainloop = g; e->dead = 0; - e->callback = callback; + + e->enabled = 1; + g->n_enabled_defer_events++; + + e->callback = cb; e->userdata = userdata; e->destroy_callback = NULL; - e->source = NULL; - - glib_defer_enable(e, 1); - - e->next = g->defer_events; - if (e->next) e->next->prev = e; - g->defer_events = e; - e->prev = NULL; + + PA_LLIST_PREPEND(pa_defer_event, g->defer_events, e); return e; } -static gboolean idle_cb(gpointer data) { - pa_defer_event* e = data; - assert(e && e->mainloop && e->source); - - e->callback(&e->mainloop->api, e, e->userdata); - return TRUE; -} - static void glib_defer_enable(pa_defer_event *e, int b) { - assert(e && e->mainloop); + assert(e); + assert(!e->dead); - if (e->source && !b) { - g_source_destroy(e->source); - g_source_unref(e->source); - e->source = NULL; - } else if (!e->source && b) { - e->source = g_idle_source_new(); - assert(e->source); - g_source_set_callback(e->source, idle_cb, e, NULL); - g_source_attach(e->source, e->mainloop->glib_main_context); - g_source_set_priority(e->source, G_PRIORITY_HIGH); - } + if (e->enabled && !b) + e->mainloop->n_enabled_defer_events--; + else if (!e->enabled && b) + e->mainloop->n_enabled_defer_events++; + + e->enabled = b; } static void glib_defer_free(pa_defer_event *e) { - assert(e && e->mainloop && !e->dead); - - if (e->source) { - g_source_destroy(e->source); - g_source_unref(e->source); - e->source = NULL; - } - - if (e->prev) - e->prev->next = e->next; - else - e->mainloop->defer_events = e->next; - - if (e->next) - e->next->prev = e->prev; - - if ((e->next = e->mainloop->dead_defer_events)) - e->next->prev = e; - - e->mainloop->dead_defer_events = e; - e->prev = NULL; + assert(e); + assert(!e->dead); e->dead = 1; - schedule_free_dead_events(e->mainloop); + e->mainloop->defer_events_please_scan++; + + if (e->enabled) + e->mainloop->n_enabled_defer_events--; } -static void glib_defer_set_destroy(pa_defer_event *e, void (*callback)(pa_mainloop_api *m, pa_defer_event *e, void *userdata)) { +static void glib_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t cb) { assert(e); - e->destroy_callback = callback; + assert(!e->dead); + + e->destroy_callback = cb; } /* quit() */ static void glib_quit(pa_mainloop_api*a, PA_GCC_UNUSED int retval) { - pa_glib_mainloop *g; - assert(a && a->userdata); - g = a->userdata; + g_warning("quit() ignored"); + /* NOOP */ } +static pa_time_event* find_next_time_event(pa_glib_mainloop *g) { + pa_time_event *t, *n = NULL; + assert(g); + + if (g->cached_next_time_event) + return g->cached_next_time_event; + + for (t = g->time_events; t; t = t->next) { + + if (t->dead || !t->enabled) + continue; + + if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) { + n = t; + + /* Shortcut for tv = { 0, 0 } */ + if (n->timeval.tv_sec <= 0) + break; + } + } + + g->cached_next_time_event = n; + return n; +} + +static gboolean prepare_func(GSource *source, gint *timeout) { + pa_glib_mainloop *g = (pa_glib_mainloop*) source; + + g_assert(g); + g_assert(timeout); + + if (g->io_events_please_scan) + cleanup_io_events(g, 0); + + if (g->time_events_please_scan) + cleanup_time_events(g, 0); + + if (g->defer_events_please_scan) + cleanup_defer_events(g, 0); + + if (g->n_enabled_defer_events) { + *timeout = 0; + return TRUE; + } else if (g->n_enabled_time_events) { + pa_time_event *t; + GTimeVal now; + struct timeval tvnow; + pa_usec_t usec; + + t = find_next_time_event(g); + g_assert(t); + + g_source_get_current_time(source, &now); + tvnow.tv_sec = now.tv_sec; + tvnow.tv_usec = now.tv_usec; + + usec = pa_timeval_diff(&t->timeval, &tvnow); + + if (usec <= 0) { + *timeout = 0; + return TRUE; + } + + *timeout = (gint) (usec / 1000); + } else + *timeout = -1; + + return FALSE; +} +static gboolean check_func(GSource *source) { + pa_glib_mainloop *g = (pa_glib_mainloop*) source; + pa_io_event *e; + + g_assert(g); + + if (g->n_enabled_defer_events) + return TRUE; + else if (g->n_enabled_time_events) { + pa_time_event *t; + GTimeVal now; + struct timeval tvnow; + + t = find_next_time_event(g); + g_assert(t); + + g_source_get_current_time(source, &now); + tvnow.tv_sec = now.tv_sec; + tvnow.tv_usec = now.tv_usec; + + if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) + return TRUE; + } + + for (e = g->io_events; e; e = e->next) + if (!e->dead && e->poll_fd.revents != 0) + return TRUE; + + return FALSE; +} + +static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callback, PA_GCC_UNUSED gpointer userdata) { + pa_glib_mainloop *g = (pa_glib_mainloop*) source; + pa_io_event *e; + + g_assert(g); + + if (g->n_enabled_defer_events) { + pa_defer_event *d; + + for (d = g->defer_events; d; d = d->next) { + if (d->dead || !d->enabled) + continue; + + break; + } + + assert(d); + + d->callback(&g->api, d, d->userdata); + return TRUE; + } + + if (g->n_enabled_time_events) { + GTimeVal now; + struct timeval tvnow; + pa_time_event *t; + + t = find_next_time_event(g); + g_assert(t); + + g_source_get_current_time(source, &now); + tvnow.tv_sec = now.tv_sec; + tvnow.tv_usec = now.tv_usec; + + if (pa_timeval_cmp(&t->timeval, &tvnow) < 0) { + t->callback(&g->api, t, &t->timeval, t->userdata); + return TRUE; + } + } + + for (e = g->io_events; e; e = e->next) + if (!e->dead && e->poll_fd.revents != 0) { + e->callback(&g->api, e, e->poll_fd.fd, map_flags_from_glib(e->poll_fd.revents), e->userdata); + e->poll_fd.revents = 0; + return TRUE; + } + + return FALSE; +} + static const pa_mainloop_api vtable = { .userdata = NULL, @@ -412,130 +593,49 @@ static const pa_mainloop_api vtable = { pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { pa_glib_mainloop *g; + + static GSourceFuncs source_funcs = { + prepare_func, + check_func, + dispatch_func, + NULL, + NULL, + NULL + }; - g = pa_xmalloc(sizeof(pa_glib_mainloop)); - if (c) { - g->glib_main_context = c; - g_main_context_ref(c); - } else - g->glib_main_context = g_main_context_default(); + g = (pa_glib_mainloop*) g_source_new(&source_funcs, sizeof(pa_glib_mainloop)); + g_main_context_ref(g->context = c ? c : g_main_context_default()); g->api = vtable; g->api.userdata = g; - g->io_events = g->dead_io_events = NULL; - g->time_events = g->dead_time_events = NULL; - g->defer_events = g->dead_defer_events = NULL; + PA_LLIST_HEAD_INIT(pa_io_event, g->io_events); + PA_LLIST_HEAD_INIT(pa_time_event, g->time_events); + PA_LLIST_HEAD_INIT(pa_defer_event, g->defer_events); - g->cleanup_source = NULL; + g->n_enabled_defer_events = g->n_enabled_time_events = 0; + g->io_events_please_scan = g->time_events_please_scan = g->defer_events_please_scan = 0; + + g_source_attach(&g->source, g->context); + g_source_set_can_recurse(&g->source, FALSE); + return g; } -static void free_io_events(pa_io_event *e) { - while (e) { - pa_io_event *r = e; - e = r->next; - - if (r->source) { - g_source_destroy(r->source); - g_source_unref(r->source); - } - - if (r->io_channel) - g_io_channel_unref(r->io_channel); - - if (r->destroy_callback) - r->destroy_callback(&r->mainloop->api, r, r->userdata); - - pa_xfree(r); - } -} - -static void free_time_events(pa_time_event *e) { - while (e) { - pa_time_event *r = e; - e = r->next; - - if (r->source) { - g_source_destroy(r->source); - g_source_unref(r->source); - } - - if (r->destroy_callback) - r->destroy_callback(&r->mainloop->api, r, r->userdata); - - pa_xfree(r); - } -} - -static void free_defer_events(pa_defer_event *e) { - while (e) { - pa_defer_event *r = e; - e = r->next; - - if (r->source) { - g_source_destroy(r->source); - g_source_unref(r->source); - } - - if (r->destroy_callback) - r->destroy_callback(&r->mainloop->api, r, r->userdata); - - pa_xfree(r); - } -} - void pa_glib_mainloop_free(pa_glib_mainloop* g) { assert(g); - free_io_events(g->io_events); - free_io_events(g->dead_io_events); - free_defer_events(g->defer_events); - free_defer_events(g->dead_defer_events); - free_time_events(g->time_events); - free_time_events(g->dead_time_events); + cleanup_io_events(g, 1); + cleanup_defer_events(g, 1); + cleanup_time_events(g, 1); - if (g->cleanup_source) { - g_source_destroy(g->cleanup_source); - g_source_unref(g->cleanup_source); - } - - g_main_context_unref(g->glib_main_context); - pa_xfree(g); + g_main_context_unref(g->context); + g_source_destroy(&g->source); + g_source_unref(&g->source); } pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) { assert(g); + return &g->api; } - -static gboolean free_dead_events(gpointer p) { - pa_glib_mainloop *g = p; - assert(g); - - free_io_events(g->dead_io_events); - free_defer_events(g->dead_defer_events); - free_time_events(g->dead_time_events); - - g->dead_io_events = NULL; - g->dead_defer_events = NULL; - g->dead_time_events = NULL; - - g_source_destroy(g->cleanup_source); - g_source_unref(g->cleanup_source); - g->cleanup_source = NULL; - - return FALSE; -} - -static void schedule_free_dead_events(pa_glib_mainloop *g) { - assert(g && g->glib_main_context); - - if (g->cleanup_source) - return; - - g->cleanup_source = g_idle_source_new(); - assert(g->cleanup_source); - g_source_set_callback(g->cleanup_source, free_dead_events, g, NULL); - g_source_attach(g->cleanup_source, g->glib_main_context); -} From f4ec7d47fd15465b86056266983f8d15ce5b8d68 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Jul 2006 19:19:52 +0000 Subject: [PATCH 1004/1514] =?UTF-8?q?fix=20module-detect=20on=20FreeBSD=20?= =?UTF-8?q?(patch=20from=20Diego=20"Flameeyes"=20Petten=C3=B3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1102 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-detect.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 3e4d2bf63..ebafa10df 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -135,23 +135,29 @@ static int detect_oss(pa_core *c, int just_one) { line[strcspn(line, "\r\n")] = 0; if (!b) { - b = strcmp(line, "Audio devices:") == 0; + b = strcmp(line, "Audio devices:") == 0 || strcmp(line, "Installed devices:") == 0; continue; } if (line[0] == 0) break; - if (sscanf(line, "%u: ", &device) != 1) - continue; - - if (device == 0) - snprintf(args, sizeof(args), "device=/dev/dsp"); - else - snprintf(args, sizeof(args), "device=/dev/dsp%u", device); - - if (!pa_module_load(c, "module-oss", args)) - continue; + if (sscanf(line, "%u: ", &device) == 1) { + if (device == 0) + snprintf(args, sizeof(args), "device=/dev/dsp"); + else + snprintf(args, sizeof(args), "device=/dev/dsp%u", device); + + if (!pa_module_load(c, "module-oss", args)) + continue; + + } else if (sscanf(line, "pcm%u: ", &device) == 1) { + /* FreeBSD support, the devices are named /dev/dsp0.0, dsp0.1 and so on */ + snprintf(args, sizeof(args), "device=/dev/dsp%u.0", device); + + if (!pa_module_load(c, "module-oss", args)) + continue; + } n++; From d7cdaf22a199e4b6710e6912b0378f0c919ff4d1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Jul 2006 19:50:09 +0000 Subject: [PATCH 1005/1514] add two more \since git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1103 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/def.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pulse/def.h b/src/pulse/def.h index 06d4c7c2b..01ed0f6d0 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -296,14 +296,14 @@ typedef enum pa_seek_mode { typedef enum pa_sink_flags { PA_SINK_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ PA_SINK_LATENCY = 2, /**< Supports latency querying */ - PA_SINK_HARDWARE = 4 /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks */ + PA_SINK_HARDWARE = 4 /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */ } pa_sink_flags_t; /** Special source flags. \since 0.8 */ typedef enum pa_source_flags { PA_SOURCE_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ PA_SOURCE_LATENCY = 2, /**< Supports latency querying */ - PA_SOURCE_HARDWARE = 4 /**< Is a hardware source of some kind, in contrast to "virtual"/software source */ + PA_SOURCE_HARDWARE = 4 /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */ } pa_source_flags_t; /** A generic free() like callback prototype */ From 9db70682d68cc4fef9314677b6427582e5d5c8f2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Jul 2006 19:53:29 +0000 Subject: [PATCH 1006/1514] remove glib 1.2 adapter. It started to bitrot and wasn't used by anything anyway. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1104 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 5 - configure.ac | 56 +--- libpulse-mainloop-glib12.pc.in | 11 - src/Makefile.am | 25 -- src/pulse/glib-mainloop.h | 6 +- src/pulse/glib12-mainloop.c | 503 --------------------------------- src/tests/mainloop-test.c | 26 +- 7 files changed, 12 insertions(+), 620 deletions(-) delete mode 100644 libpulse-mainloop-glib12.pc.in delete mode 100644 src/pulse/glib12-mainloop.c diff --git a/Makefile.am b/Makefile.am index 8aa609f6c..1b77187de 100644 --- a/Makefile.am +++ b/Makefile.am @@ -36,11 +36,6 @@ pkgconfig_DATA += \ libpulse-mainloop-glib.pc endif -if HAVE_GLIB12 -pkgconfig_DATA += \ - libpulse-mainloop-glib12.pc -endif - homepage: all dist doxygen test -d $$HOME/homepage/private mkdir -p $$HOME/homepage/private/projects/pulseaudio $$HOME/homepage/private/projects/pulseaudio/doxygen diff --git a/configure.ac b/configure.ac index 80473415c..cf7b5534c 100644 --- a/configure.ac +++ b/configure.ac @@ -449,37 +449,6 @@ AC_SUBST(GLIB20_LIBS) AC_SUBST(HAVE_GLIB20) AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1]) -#### GLib 1 support (optional) #### - -AC_ARG_ENABLE([glib1], - AC_HELP_STRING([--disable-glib1], [Disable optional GLib 1 support]), - [ - case "${enableval}" in - yes) glib1=yes ;; - no) glib1=no ;; - *) AC_MSG_ERROR(bad value ${enableval} for --disable-glib1) ;; - esac - ], - [glib1=auto]) - -if test "x${glib1}" != xno ; then - PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], - HAVE_GLIB12=1, - [ - HAVE_GLIB12=0 - if test "x$glib1" = xyes ; then - AC_MSG_ERROR([*** GLib 1 support not found]) - fi - ]) -else - HAVE_GLIB12=0 -fi - -AC_SUBST(GLIB12_CFLAGS) -AC_SUBST(GLIB12_LIBS) -AC_SUBST(HAVE_GLIB12) -AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1]) - #### Avahi support (optional) #### AC_ARG_ENABLE([avahi], @@ -677,7 +646,6 @@ libpulse.pc libpulse-simple.pc libpulse-browse.pc libpulse-mainloop-glib.pc -libpulse-mainloop-glib12.pc doxygen/Makefile doxygen/doxygen.conf src/pulse/version.h @@ -710,11 +678,6 @@ if test "x$HAVE_GLIB20" = "x1" ; then ENABLE_GLIB20=yes fi -ENABLE_GLIB12=no -if test "x$HAVE_GLIB12" = "x1" ; then - ENABLE_GLIB12=yes -fi - ENABLE_AVAHI=no if test "x$HAVE_AVAHI" = "x1" ; then ENABLE_AVAHI=yes @@ -748,15 +711,14 @@ echo " localstatedir: ${localstatedir} compiler: ${CC} cflags: ${CFLAGS} - Have X11: ${ENABLE_X11} - Enable OSS: ${ENABLE_OSS} - Enable Alsa: ${ENABLE_ALSA} - Enable Solaris: ${ENABLE_SOLARIS} - Enable Glib 2.0: ${ENABLE_GLIB20} - Enable Glib 1.2: ${ENABLE_GLIB12} - Enable Avahi: ${ENABLE_AVAHI} - Enable Jack: ${ENABLE_JACK} - Enable Async DNS: ${ENABLE_LIBASYNCNS} - Enable LIRC: ${ENABLE_LIRC} + Have X11: ${ENABLE_X11} + Enable OSS: ${ENABLE_OSS} + Enable Alsa: ${ENABLE_ALSA} + Enable Solaris: ${ENABLE_SOLARIS} + Enable Glib 2.0: ${ENABLE_GLIB20} + Enable Avahi: ${ENABLE_AVAHI} + Enable Jack: ${ENABLE_JACK} + Enable Async DNS: ${ENABLE_LIBASYNCNS} + Enable LIRC: ${ENABLE_LIRC} Enable TCP Wrappers: ${ENABLE_TCPWRAP} " diff --git a/libpulse-mainloop-glib12.pc.in b/libpulse-mainloop-glib12.pc.in deleted file mode 100644 index 7a0388260..000000000 --- a/libpulse-mainloop-glib12.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include - -Name: libpulse-mainloop-glib12 -Description: GLIB 1.2 Main Loop Wrapper for PulseAudio -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpulse-mainloop-glib12 -Cflags: -D_REENTRANT -I${includedir} -Requires: libpulse glib diff --git a/src/Makefile.am b/src/Makefile.am index 8da51aac3..0235741bb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -207,11 +207,6 @@ noinst_PROGRAMS += \ mainloop-test-glib endif -if HAVE_GLIB12 -noinst_PROGRAMS += \ - mainloop-test-glib12 -endif - mainloop_test_SOURCES = tests/mainloop-test.c mainloop_test_CFLAGS = $(AM_CFLAGS) mainloop_test_LDADD = $(AM_LDADD) libpulse.la @@ -277,11 +272,6 @@ mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpulse-mainloop-glib.la mainloop_test_glib_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES) -mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP -mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpulse-mainloop-glib12.la -mainloop_test_glib12_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) - memblockq_test_SOURCES = tests/memblockq-test.c memblockq_test_CFLAGS = $(AM_CFLAGS) memblockq_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la @@ -334,11 +324,6 @@ endif if HAVE_GLIB20 pulseinclude_HEADERS += \ pulse/glib-mainloop.h -else -if HAVE_GLIB12 -pulseinclude_HEADERS += \ - pulse/glib-mainloop.h -endif endif lib_LTLIBRARIES = \ @@ -355,11 +340,6 @@ lib_LTLIBRARIES += \ libpulse-mainloop-glib.la endif -if HAVE_GLIB12 -lib_LTLIBRARIES += \ - libpulse-mainloop-glib12.la -endif - # Public interface libpulse_la_SOURCES = \ pulse/cdecl.h \ @@ -461,11 +441,6 @@ libpulse_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) libpulse_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpulse.la $(GLIB20_LIBS) libpulse_mainloop_glib_la_LDFLAGS = -version-info $(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO) -libpulse_mainloop_glib12_la_SOURCES = pulse/glib-mainloop.h pulse/glib12-mainloop.c -libpulse_mainloop_glib12_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS) -libpulse_mainloop_glib12_la_LIBADD = $(AM_LIBADD) libpulse.la $(GLIB12_LIBS) -libpulse_mainloop_glib12_la_LDFLAGS = -version-info $(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO) - ################################### # OSS emulation # ################################### diff --git a/src/pulse/glib-mainloop.h b/src/pulse/glib-mainloop.h index 75de1cc77..af7cc0e90 100644 --- a/src/pulse/glib-mainloop.h +++ b/src/pulse/glib-mainloop.h @@ -47,13 +47,9 @@ PA_C_DECL_BEGIN typedef struct pa_glib_mainloop pa_glib_mainloop; /** Create a new GLIB main loop object for the specified GLIB main - * loop context. The GLIB 2.0 version takes an argument c for the + * loop context. Takes an argument c for the * GMainContext to use. If c is NULL the default context is used. */ -#if GLIB_MAJOR_VERSION >= 2 pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c); -#else -pa_glib_mainloop *pa_glib_mainloop_new(void); -#endif /** Free the GLIB main loop object */ void pa_glib_mainloop_free(pa_glib_mainloop* g); diff --git a/src/pulse/glib12-mainloop.c b/src/pulse/glib12-mainloop.c deleted file mode 100644 index ebaf87fc5..000000000 --- a/src/pulse/glib12-mainloop.c +++ /dev/null @@ -1,503 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of PulseAudio. - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include - -#include -#include - -#include "glib-mainloop.h" - -/* A mainloop implementation based on GLIB 1.2 */ - -struct pa_io_event { - pa_glib_mainloop *mainloop; - int dead; - GIOChannel *io_channel; - guint source; - GIOCondition io_condition; - int fd; - void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata); - void *userdata; - void (*destroy_callback) (pa_mainloop_api *m, pa_io_event*e, void *userdata); - pa_io_event *next, *prev; -}; - -struct pa_time_event { - pa_glib_mainloop *mainloop; - int dead; - guint source; - struct timeval timeval; - void (*callback) (pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata); - void *userdata; - void (*destroy_callback) (pa_mainloop_api *m, pa_time_event*e, void *userdata); - pa_time_event *next, *prev; -}; - -struct pa_defer_event { - pa_glib_mainloop *mainloop; - int dead; - guint source; - void (*callback) (pa_mainloop_api*m, pa_defer_event *e, void *userdata); - void *userdata; - void (*destroy_callback) (pa_mainloop_api *m, pa_defer_event*e, void *userdata); - pa_defer_event *next, *prev; -}; - -struct pa_glib_mainloop { - pa_mainloop_api api; - guint cleanup_source; - pa_io_event *io_events, *dead_io_events; - pa_time_event *time_events, *dead_time_events; - pa_defer_event *defer_events, *dead_defer_events; -}; - -static void schedule_free_dead_events(pa_glib_mainloop *g); - -static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f); - -static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags_t f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata), void *userdata) { - pa_io_event *e; - pa_glib_mainloop *g; - - assert(m && m->userdata && fd >= 0 && callback); - g = m->userdata; - - e = pa_xmalloc(sizeof(pa_io_event)); - e->mainloop = m->userdata; - e->dead = 0; - e->fd = fd; - e->callback = callback; - e->userdata = userdata; - e->destroy_callback = NULL; - - e->io_channel = g_io_channel_unix_new(e->fd); - assert(e->io_channel); - e->source = (guint) -1; - e->io_condition = 0; - - glib_io_enable(e, f); - - e->next = g->io_events; - if (e->next) e->next->prev = e; - g->io_events = e; - e->prev = NULL; - - return e; -} - -static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) { - pa_io_event *e = data; - pa_io_event_flags_t f; - assert(source && e && e->io_channel == source); - - f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) | - (condition & G_IO_OUT ? PA_IO_EVENT_OUTPUT : 0) | - (condition & G_IO_ERR ? PA_IO_EVENT_ERROR : 0) | - (condition & G_IO_HUP ? PA_IO_EVENT_HANGUP : 0); - - e->callback(&e->mainloop->api, e, e->fd, f, e->userdata); - return TRUE; -} - -static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) { - GIOCondition c; - assert(e && !e->dead); - - c = (f & PA_IO_EVENT_INPUT ? G_IO_IN : 0) | (f & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0); - - if (c == e->io_condition) - return; - - if (e->source != (guint) -1) - g_source_remove(e->source); - - e->source = g_io_add_watch_full(e->io_channel, G_PRIORITY_DEFAULT, c | G_IO_ERR | G_IO_HUP, io_cb, e, NULL); - assert(e->source != (guint) -1); - e->io_condition = c; -} - -static void glib_io_free(pa_io_event*e) { - assert(e && !e->dead); - - if (e->source != (guint) -1) { - g_source_remove(e->source); - e->source = (guint) -1; - } - - if (e->prev) - e->prev->next = e->next; - else - e->mainloop->io_events = e->next; - - if (e->next) - e->next->prev = e->prev; - - if ((e->next = e->mainloop->dead_io_events)) - e->next->prev = e; - - e->mainloop->dead_io_events = e; - e->prev = NULL; - - e->dead = 1; - schedule_free_dead_events(e->mainloop); -} - -static void glib_io_set_destroy(pa_io_event*e, void (*callback)(pa_mainloop_api*m, pa_io_event *e, void *userdata)) { - assert(e); - e->destroy_callback = callback; -} - -/* Time sources */ - -static void glib_time_restart(pa_time_event*e, const struct timeval *tv); - -static pa_time_event* glib_time_new(pa_mainloop_api*m, const struct timeval *tv, void (*callback) (pa_mainloop_api*m, pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { - pa_glib_mainloop *g; - pa_time_event *e; - - assert(m && m->userdata && tv && callback); - g = m->userdata; - - e = pa_xmalloc(sizeof(pa_time_event)); - e->mainloop = g; - e->dead = 0; - e->callback = callback; - e->userdata = userdata; - e->destroy_callback = NULL; - e->source = (guint) -1; - - glib_time_restart(e, tv); - - e->next = g->time_events; - if (e->next) e->next->prev = e; - g->time_events = e; - e->prev = NULL; - - return e; -} - -static guint msec_diff(const struct timeval *a, const struct timeval *b) { - guint r; - assert(a && b); - - if (a->tv_sec < b->tv_sec) - return 0; - - if (a->tv_sec == b->tv_sec && a->tv_sec <= b->tv_sec) - return 0; - - r = (a->tv_sec-b->tv_sec)*1000; - - if (a->tv_usec >= b->tv_usec) - r += (a->tv_usec - b->tv_usec) / 1000; - else - r -= (b->tv_usec - a->tv_usec) / 1000; - - return r; -} - -static gboolean time_cb(gpointer data) { - pa_time_event* e = data; - assert(e && e->mainloop && e->source != (guint) -1); - - g_source_remove(e->source); - e->source = (guint) -1; - - e->callback(&e->mainloop->api, e, &e->timeval, e->userdata); - return FALSE; -} - -static void glib_time_restart(pa_time_event*e, const struct timeval *tv) { - struct timeval now; - assert(e && e->mainloop && !e->dead); - - pa_gettimeofday(&now); - if (e->source != (guint) -1) - g_source_remove(e->source); - - if (tv) { - e->timeval = *tv; - e->source = g_timeout_add_full(G_PRIORITY_DEFAULT, msec_diff(tv, &now), time_cb, e, NULL); - assert(e->source != (guint) -1); - } else - e->source = (guint) -1; - } - -static void glib_time_free(pa_time_event *e) { - assert(e && e->mainloop && !e->dead); - - if (e->source != (guint) -1) { - g_source_remove(e->source); - e->source = (guint) -1; - } - - if (e->prev) - e->prev->next = e->next; - else - e->mainloop->time_events = e->next; - - if (e->next) - e->next->prev = e->prev; - - if ((e->next = e->mainloop->dead_time_events)) - e->next->prev = e; - - e->mainloop->dead_time_events = e; - e->prev = NULL; - - e->dead = 1; - schedule_free_dead_events(e->mainloop); -} - -static void glib_time_set_destroy(pa_time_event *e, void (*callback)(pa_mainloop_api*m, pa_time_event*e, void *userdata)) { - assert(e); - e->destroy_callback = callback; -} - -/* Deferred sources */ - -static void glib_defer_enable(pa_defer_event *e, int b); - -static pa_defer_event* glib_defer_new(pa_mainloop_api*m, void (*callback) (pa_mainloop_api*m, pa_defer_event *e, void *userdata), void *userdata) { - pa_defer_event *e; - pa_glib_mainloop *g; - - assert(m && m->userdata && callback); - g = m->userdata; - - e = pa_xmalloc(sizeof(pa_defer_event)); - e->mainloop = g; - e->dead = 0; - e->callback = callback; - e->userdata = userdata; - e->destroy_callback = NULL; - e->source = (guint) -1; - - glib_defer_enable(e, 1); - - e->next = g->defer_events; - if (e->next) e->next->prev = e; - g->defer_events = e; - e->prev = NULL; - return e; -} - -static gboolean idle_cb(gpointer data) { - pa_defer_event* e = data; - assert(e && e->mainloop && e->source != (guint) -1); - - e->callback(&e->mainloop->api, e, e->userdata); - return TRUE; -} - -static void glib_defer_enable(pa_defer_event *e, int b) { - assert(e && e->mainloop); - - if (e->source != (guint) -1 && !b) { - g_source_remove(e->source); - e->source = (guint) -1; - } else if (e->source == (guint) -1 && b) { - e->source = g_idle_add_full(G_PRIORITY_HIGH, idle_cb, e, NULL); - assert(e->source != (guint) -1); - } -} - -static void glib_defer_free(pa_defer_event *e) { - assert(e && e->mainloop && !e->dead); - - if (e->source != (guint) -1) { - g_source_remove(e->source); - e->source = (guint) -1; - } - - if (e->prev) - e->prev->next = e->next; - else - e->mainloop->defer_events = e->next; - - if (e->next) - e->next->prev = e->prev; - - if ((e->next = e->mainloop->dead_defer_events)) - e->next->prev = e; - - e->mainloop->dead_defer_events = e; - e->prev = NULL; - - e->dead = 1; - schedule_free_dead_events(e->mainloop); -} - -static void glib_defer_set_destroy(pa_defer_event *e, void (*callback)(pa_mainloop_api *m, pa_defer_event *e, void *userdata)) { - assert(e); - e->destroy_callback = callback; -} - -/* quit() */ - -static void glib_quit(pa_mainloop_api*a, PA_GCC_UNUSED int retval) { - pa_glib_mainloop *g; - assert(a && a->userdata); - g = a->userdata; - - /* NOOP */ -} - -static const pa_mainloop_api vtable = { - .userdata = NULL, - - .io_new = glib_io_new, - .io_enable = glib_io_enable, - .io_free = glib_io_free, - .io_set_destroy= glib_io_set_destroy, - - .time_new = glib_time_new, - .time_restart = glib_time_restart, - .time_free = glib_time_free, - .time_set_destroy = glib_time_set_destroy, - - .defer_new = glib_defer_new, - .defer_enable = glib_defer_enable, - .defer_free = glib_defer_free, - .defer_set_destroy = glib_defer_set_destroy, - - .quit = glib_quit, -}; - -pa_glib_mainloop *pa_glib_mainloop_new(void) { - pa_glib_mainloop *g; - - g = pa_xmalloc(sizeof(pa_glib_mainloop)); - - g->api = vtable; - g->api.userdata = g; - - g->io_events = g->dead_io_events = NULL; - g->time_events = g->dead_time_events = NULL; - g->defer_events = g->dead_defer_events = NULL; - - g->cleanup_source = (guint) -1; - return g; -} - -static void free_io_events(pa_io_event *e) { - while (e) { - pa_io_event *r = e; - e = r->next; - - if (r->source != (guint) -1) - g_source_remove(r->source); - - if (r->io_channel) - g_io_channel_unref(r->io_channel); - - if (r->destroy_callback) - r->destroy_callback(&r->mainloop->api, r, r->userdata); - - pa_xfree(r); - } -} - -static void free_time_events(pa_time_event *e) { - while (e) { - pa_time_event *r = e; - e = r->next; - - if (r->source != (guint) -1) - g_source_remove(r->source); - - if (r->destroy_callback) - r->destroy_callback(&r->mainloop->api, r, r->userdata); - - pa_xfree(r); - } -} - -static void free_defer_events(pa_defer_event *e) { - while (e) { - pa_defer_event *r = e; - e = r->next; - - if (r->source != (guint) -1) - g_source_remove(r->source); - - if (r->destroy_callback) - r->destroy_callback(&r->mainloop->api, r, r->userdata); - - pa_xfree(r); - } -} - -void pa_glib_mainloop_free(pa_glib_mainloop* g) { - assert(g); - - free_io_events(g->io_events); - free_io_events(g->dead_io_events); - free_defer_events(g->defer_events); - free_defer_events(g->dead_defer_events); - free_time_events(g->time_events); - free_time_events(g->dead_time_events); - - if (g->cleanup_source != (guint) -1) - g_source_remove(g->cleanup_source); - - pa_xfree(g); -} - -pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) { - assert(g); - return &g->api; -} - -static gboolean free_dead_events(gpointer p) { - pa_glib_mainloop *g = p; - assert(g); - - free_io_events(g->dead_io_events); - free_defer_events(g->dead_defer_events); - free_time_events(g->dead_time_events); - - g->dead_io_events = NULL; - g->dead_defer_events = NULL; - g->dead_time_events = NULL; - - g_source_remove(g->cleanup_source); - g->cleanup_source = (guint) -1; - - return FALSE; -} - -static void schedule_free_dead_events(pa_glib_mainloop *g) { - assert(g); - - if (g->cleanup_source != (guint) -1) - return; - - g->cleanup_source = g_idle_add_full(G_PRIORITY_HIGH, free_dead_events, g, NULL); -} diff --git a/src/tests/mainloop-test.c b/src/tests/mainloop-test.c index 671adeff2..b06d0ed1d 100644 --- a/src/tests/mainloop-test.c +++ b/src/tests/mainloop-test.c @@ -40,13 +40,6 @@ static GMainLoop* glib_main_loop = NULL; -#if GLIB_MAJOR_VERSION >= 2 -#define GLIB20 -#else -#undef GLIB20 -#endif - - #else /* GLIB_MAIN_LOOP */ #include #endif /* GLIB_MAIN_LOOP */ @@ -68,10 +61,8 @@ static void dcb(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { fprintf(stderr, "TIME EVENT\n"); -#if defined(GLIB_MAIN_LOOP) && defined(GLIB20) +#if defined(GLIB_MAIN_LOOP) g_main_loop_quit(glib_main_loop); -#elif defined(GLIB_MAIN_LOOP) - g_main_quit(glib_main_loop); #else a->quit(a, 0); #endif @@ -86,17 +77,10 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { #ifdef GLIB_MAIN_LOOP pa_glib_mainloop *g; -#ifdef GLIB20 glib_main_loop = g_main_loop_new(NULL, FALSE); assert(glib_main_loop); g = pa_glib_mainloop_new(NULL); -#else /* GLIB20 */ - glib_main_loop = g_main_new(FALSE); - assert(glib_main_loop); - - g = pa_glib_mainloop_new(); -#endif /* GLIB20 */ assert(g); a = pa_glib_mainloop_get_api(g); @@ -121,10 +105,8 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { tv.tv_sec += 10; te = a->time_new(a, &tv, tcb, NULL); -#if defined(GLIB_MAIN_LOOP) && defined(GLIB20) +#if defined(GLIB_MAIN_LOOP) g_main_loop_run(glib_main_loop); -#elif defined(GLIB_MAIN_LOOP) - g_main_run(glib_main_loop); #else pa_mainloop_run(m, NULL); #endif @@ -135,11 +117,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { #ifdef GLIB_MAIN_LOOP pa_glib_mainloop_free(g); -#ifdef GLIB20 g_main_loop_unref(glib_main_loop); -#else - g_main_destroy(glib_main_loop); -#endif #else pa_mainloop_free(m); #endif From 9c87a65ce91c38b60c19ae108a51a2e8ce46a85c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 17:44:19 +0000 Subject: [PATCH 1007/1514] * add new --system command line parameter to the daemon for running PulseAudio as system-wide instance * add PA_ prefixes to all global #defines * modify auth-by-creds: define a new group "pulse-access" which is used for authentication * add proper privilige dropping when running in --system mode * create runtime directory once on startup and not by each module seperately git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1105 fefdeb5f-60dc-0310-8127-8f9354f1896f --- bootstrap.sh | 2 +- configure.ac | 55 +++++++++++- src/Makefile.am | 14 ++-- src/daemon/cmdline.c | 12 ++- src/daemon/daemon-conf.c | 22 ++--- src/daemon/daemon-conf.h | 3 +- src/daemon/daemon.conf.in | 6 ++ src/daemon/main.c | 129 +++++++++++++++++++++++++++-- src/modules/module-match.c | 6 +- src/modules/module-protocol-stub.c | 55 +++++++----- src/modules/module-tunnel.c | 2 +- src/pulse/client-conf.c | 19 ++--- src/pulse/client-conf.h | 2 +- src/pulse/context.c | 24 +++++- src/pulsecore/core-util.c | 86 ++++++++++++++----- src/pulsecore/core-util.h | 5 +- src/pulsecore/core.c | 5 +- src/pulsecore/core.h | 2 + src/pulsecore/iochannel.c | 17 ++-- src/pulsecore/iochannel.h | 2 +- src/pulsecore/pdispatch.c | 4 +- src/pulsecore/pdispatch.h | 6 +- src/pulsecore/pid.c | 15 +--- src/pulsecore/protocol-native.c | 2 +- src/pulsecore/pstream-util.c | 2 +- src/pulsecore/pstream-util.h | 4 +- src/pulsecore/pstream.c | 31 ++++--- src/pulsecore/pstream.h | 6 +- 28 files changed, 403 insertions(+), 135 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 1f8b29d0b..b85f025eb 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -57,7 +57,7 @@ else run_versioned automake "$VERSION" -a -c --foreign if test "x$NOCONFIGURE" = "x"; then - CFLAGS="-g -O0" ./configure --sysconfdir=/etc --enable-force-preopen "$@" + CFLAGS="-g -O0" ./configure --sysconfdir=/etc --localstatedir=/var --enable-force-preopen "$@" make clean fi fi diff --git a/configure.ac b/configure.ac index cf7b5534c..a7f85ea0e 100644 --- a/configure.ac +++ b/configure.ac @@ -239,7 +239,11 @@ AC_CHECK_FUNCS([lstat]) # Non-standard AC_CHECK_FUNCS(setresuid) +AC_CHECK_FUNCS(setresgid) AC_CHECK_FUNCS(setreuid) +AC_CHECK_FUNCS(setregid) +AC_CHECK_FUNCS(seteuid) +AC_CHECK_FUNCS(setegid) #### POSIX threads #### @@ -602,6 +606,48 @@ AC_SUBST(LIRC_CFLAGS) AC_SUBST(LIRC_LIBS) AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) +#### PulseAudio system group & user ##### + +AC_ARG_WITH(system_user, AS_HELP_STRING([--with-system-user=],[User for running the PulseAudio daemon as a system-wide instance (pulse)])) +if test -z "$with_system_user" ; then + PA_SYSTEM_USER=pulse +else + PA_SYSTEM_USER=$with_system_user +fi +AC_SUBST(PA_SYSTEM_USER) +AC_DEFINE_UNQUOTED(PA_SYSTEM_USER,"$PA_SYSTEM_USER", [User for running the PulseAudio system daemon]) + +AC_ARG_WITH(system_group,AS_HELP_STRING([--with-system-group=],[Group for running the PulseAudio daemon as a system-wide instance (pulse)])) +if test -z "$with_system_group" ; then + PA_SYSTEM_GROUP=pulse +else + PA_SYSTEM_GROUP=$with_system_group +fi +AC_SUBST(PA_SYSTEM_GROUP) +AC_DEFINE_UNQUOTED(PA_SYSTEM_GROUP,"$PA_SYSTEM_GROUP", [Group for the PulseAudio system daemon]) + +AC_ARG_WITH(realtime_group,AS_HELP_STRING([--with-realtime-group=],[Group for users that are allowed to start the PulseAudio daemon with realtime scheduling (realtime)])) +if test -z "$with_realtime_group" ; then + PA_REALTIME_GROUP=realtime +else + PA_REALTIME_GROUP=$with_realtime_group +fi +AC_SUBST(PA_REALTIME_GROUP) +AC_DEFINE_UNQUOTED(PA_REALTIME_GROUP,"$PA_REALTIME_GROUP", [Realtime group]) + +AC_ARG_WITH(access_group,AS_HELP_STRING([--with-access-group=],[Group which is allowed access to a system-wide PulseAudio daemon (pulse-access)])) +if test -z "$with_access_group" ; then + PA_ACCESS_GROUP=pulse-access +else + PA_ACCESS_GROUP=$with_access_group +fi +AC_SUBST(PA_ACCESS_GROUP) +AC_DEFINE_UNQUOTED(PA_ACCESS_GROUP,"$PA_ACCESS_GROUP", [Access group]) + +#### PulseAudio system runtime dir #### +PA_SYSTEM_RUNTIME_PATH="${localstatedir}/run/pulse" +AC_SUBST(PA_SYSTEM_RUNTIME_PATH) + ################################### # Output # ################################### @@ -709,8 +755,9 @@ echo " prefix: ${prefix} sysconfdir: ${sysconfdir} localstatedir: ${localstatedir} - compiler: ${CC} - cflags: ${CFLAGS} + System Runtime Path: ${PA_SYSTEM_RUNTIME_PATH} + Compiler: ${CC} + CFLAGS: ${CFLAGS} Have X11: ${ENABLE_X11} Enable OSS: ${ENABLE_OSS} Enable Alsa: ${ENABLE_ALSA} @@ -721,4 +768,8 @@ echo " Enable Async DNS: ${ENABLE_LIBASYNCNS} Enable LIRC: ${ENABLE_LIRC} Enable TCP Wrappers: ${ENABLE_TCPWRAP} + System User: ${PA_SYSTEM_USER} + System Group: ${PA_SYSTEM_GROUP} + Realtime Group: ${PA_REALTIME_GROUP} + Access Group: ${PA_ACCESS_GROUP} " diff --git a/src/Makefile.am b/src/Makefile.am index 0235741bb..1a4bcb04d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,11 +30,11 @@ pulseconfdir=$(sysconfdir)/pulse # Defines # ################################### -PULSEAUDIO_BINARY=$(bindir)/pulseaudio$(EXEEXT) +PA_BINARY=$(bindir)/pulseaudio$(EXEEXT) if OS_IS_WIN32 -DEFAULT_CONFIG_DIR=%PULSE_ROOT% +PA_DEFAULT_CONFIG_DIR=%PULSE_ROOT% else -DEFAULT_CONFIG_DIR=$(pulseconfdir) +PA_DEFAULT_CONFIG_DIR=$(pulseconfdir) endif ################################### @@ -45,10 +45,10 @@ AM_CFLAGS = -I$(top_srcdir)/src AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) -AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibexecdir)\" -#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\" -AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\" -AM_CFLAGS += -DPULSEAUDIO_BINARY=\"$(PULSEAUDIO_BINARY)\" +AM_CFLAGS += -DPA_DLSEARCHPATH=\"$(modlibexecdir)\" +AM_CFLAGS += -DPA_DEFAULT_CONFIG_DIR=\"$(PA_DEFAULT_CONFIG_DIR)\" +AM_CFLAGS += -DPA_BINARY=\"$(PA_BINARY)\" +AM_CFLAGS += -DPA_SYSTEM_RUNTIME_PATH=\"$(PA_SYSTEM_RUNTIME_PATH)\" # This cool debug trap works on i386/gcc only AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")' diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index a106dc090..ab876edf2 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -58,7 +58,8 @@ enum { ARG_RESAMPLE_METHOD, ARG_KILL, ARG_USE_PID_FILE, - ARG_CHECK + ARG_CHECK, + ARG_SYSTEM }; /* Tabel for getopt_long() */ @@ -84,6 +85,7 @@ static struct option long_options[] = { {"kill", 0, 0, ARG_KILL}, {"use-pid-file", 2, 0, ARG_USE_PID_FILE}, {"check", 0, 0, ARG_CHECK}, + {"system", 2, 0, ARG_SYSTEM}, {NULL, 0, 0, 0} }; @@ -105,6 +107,7 @@ void pa_cmdline_help(const char *argv0) { " --check Check for a running daemon\n\n" "OPTIONS:\n" + " --system[=BOOL] Run as system-wide instance\n" " -D, --daemonize[=BOOL] Daemonize after startup\n" " --fail[=BOOL] Quit when startup fails\n" " --high-priority[=BOOL] Try to set high process priority\n" @@ -276,6 +279,13 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d goto fail; } break; + + case ARG_SYSTEM: + if ((conf->system_instance = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log(__FILE__": --system expects boolean argument"); + goto fail; + } + break; default: goto fail; diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index d1afed7b1..a5a62567a 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -39,23 +39,15 @@ #include "daemon-conf.h" -#ifndef DEFAULT_CONFIG_DIR -# ifndef OS_IS_WIN32 -# define DEFAULT_CONFIG_DIR "/etc/pulse" -# else -# define DEFAULT_CONFIG_DIR "%PULSE_ROOT%" -# endif -#endif - #ifndef OS_IS_WIN32 # define PATH_SEP "/" #else # define PATH_SEP "\\" #endif -#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR PATH_SEP "default.pa" +#define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "default.pa" #define DEFAULT_SCRIPT_FILE_USER ".pulse" PATH_SEP "default.pa" -#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" +#define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" #define DEFAULT_CONFIG_FILE_USER ".pulse" PATH_SEP "daemon.conf" #define ENV_SCRIPT_FILE "PULSE_SCRIPT" @@ -79,7 +71,8 @@ static const pa_daemon_conf default_conf = { .log_level = PA_LOG_NOTICE, .resample_method = PA_RESAMPLER_SRC_SINC_FASTEST, .config_file = NULL, - .use_pid_file = 1 + .use_pid_file = 1, + .system_instance = 0 }; pa_daemon_conf* pa_daemon_conf_new(void) { @@ -89,9 +82,7 @@ pa_daemon_conf* pa_daemon_conf_new(void) { if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file, "r"))) fclose(f); -#ifdef DLSEARCHPATH - c->dl_search_path = pa_xstrdup(DLSEARCHPATH); -#endif + c->dl_search_path = pa_xstrdup(PA_DLSEARCHPATH); return c; } @@ -212,6 +203,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "verbose", parse_log_level, NULL }, { "resample-method", parse_resample_method, NULL }, { "use-pid-file", pa_config_parse_bool, NULL }, + { "system-instance", pa_config_parse_bool, NULL }, { NULL, NULL, NULL }, }; @@ -229,6 +221,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[11].data = c; table[12].data = c; table[13].data = &c->use_pid_file; + table[14].data = &c->system_instance; pa_xfree(c->config_file); c->config_file = NULL; @@ -295,6 +288,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file); + pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance); return pa_strbuf_tostring_free(s); } diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index c325495c2..bfea73583 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -46,7 +46,8 @@ typedef struct pa_daemon_conf { module_idle_time, scache_idle_time, auto_log_target, - use_pid_file; + use_pid_file, + system_instance; char *script_commands, *dl_search_path, *default_script_file; pa_log_target_t log_target; pa_log_level_t log_level; diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 30bf3ca16..6e55c0ee6 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -46,6 +46,9 @@ ## Unload autoloaded modules after being idle for this time ; module-idle-time = 20 +## Unload autoloaded sample cache entries after being idle for this time +; scache-idle-time = 20 + ## The path were to look for dynamic shared objects (DSOs aka ## plugins). You may specify more than one path seperated by ## colons. @@ -75,3 +78,6 @@ ## process per user, you better disable this option since it ## effectively disables multiple instances. ; use-pid-file = 1 + +## Run the daemon as system-wide instance, requires root priviliges +; system-instance = 0 diff --git a/src/daemon/main.c b/src/daemon/main.c index c41c69df6..4961f0ca3 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -37,6 +37,9 @@ #include #include #include +#include +#include + #include #ifdef HAVE_SYS_IOCTL_H @@ -149,6 +152,104 @@ static void close_pipe(int p[2]) { p[0] = p[1] = -1; } +#define set_env(key, value) putenv(pa_sprintf_malloc("%s=%s", (key), (value))) + +static int change_user(void) { + struct passwd *pw; + struct group * gr; + int r; + + if (!(pw = getpwnam(PA_SYSTEM_USER))) { + pa_log(__FILE__": Failed to find user '%s'.", PA_SYSTEM_USER); + return -1; + } + + if (!(gr = getgrnam(PA_SYSTEM_GROUP))) { + pa_log(__FILE__": Failed to find group '%s'.", PA_SYSTEM_GROUP); + return -1; + } + + pa_log_info(__FILE__": Found user '%s' (UID %lu) and group '%s' (GID %lu).", + PA_SYSTEM_USER, (unsigned long) pw->pw_uid, + PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid); + + if (pw->pw_gid != gr->gr_gid) { + pa_log(__FILE__": GID of user '%s' and of group '%s' don't match.", PA_SYSTEM_USER, PA_SYSTEM_GROUP); + return -1; + } + + if (strcmp(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH) != 0) + pa_log_warn(__FILE__": Warning: home directory of user '%s' is not '%s', ignoring.", PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH); + + if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid) < 0) { + pa_log(__FILE__": Failed to create '%s': %s", PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno)); + return -1; + } + + if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) { + pa_log(__FILE__": Failed to change group list: %s", pa_cstrerror(errno)); + return -1; + } + +#if defined(HAVE_SETRESGID) + r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid); +#elif defined(HAVE_SETEGID) + if ((r = setgid(gr->gr_gid)) >= 0) + r = setegid(gr->gr_gid); +#elif defined(HAVE_SETREGID) + r = setregid(gr->gr_gid, gr->gr_gid); +#else +#error "No API to drop priviliges" +#endif + + if (r < 0) { + pa_log(__FILE__": Failed to change GID: %s", pa_cstrerror(errno)); + return -1; + } + +#if defined(HAVE_SETRESUID) + r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid); +#elif defined(HAVE_SETEUID) + if ((r = setuid(pw->pw_uid)) >= 0) + r = seteuid(pw->pw_uid); +#elif defined(HAVE_SETREUID) + r = setreuid(pw->pw_uid, pw->pw_uid); +#else +#error "No API to drop priviliges" +#endif + + if (r < 0) { + pa_log(__FILE__": Failed to change UID: %s", pa_cstrerror(errno)); + return -1; + } + + set_env("USER", PA_SYSTEM_USER); + set_env("LOGNAME", PA_SYSTEM_GROUP); + set_env("HOME", PA_SYSTEM_RUNTIME_PATH); + + /* Relevant for pa_runtime_path() */ + set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH); + + pa_log_info(__FILE__": Successfully dropped root privileges."); + + return 0; +} + +static int create_runtime_dir(void) { + char fn[PATH_MAX]; + + pa_runtime_path(NULL, fn, sizeof(fn)); + + if (pa_make_secure_dir(fn, 0700, getuid(), getgid()) < 0) { + pa_log(__FILE__": Failed to create '%s': %s", fn, pa_cstrerror(errno)); + return -1; + } + + /* Relevant for pa_runtime_path() later on */ + set_env("PULSE_RUNTIME_PATH", fn); + return 0; +} + int main(int argc, char *argv[]) { pa_core *c; pa_strbuf *buf = NULL; @@ -172,13 +273,14 @@ int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); - pa_limit_caps(); + if (getuid() != 0) + pa_limit_caps(); #ifdef HAVE_GETUID suid_root = getuid() != 0 && geteuid() == 0; - if (suid_root && (pa_own_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) { - pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'."); + if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) { + pa_log_warn(__FILE__": WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'."); pa_drop_root(); } #else @@ -220,7 +322,8 @@ int main(int argc, char *argv[]) { if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) pa_raise_priority(); - pa_drop_caps(); + if (getuid() != 0) + pa_drop_caps(); if (suid_root) pa_drop_root(); @@ -278,6 +381,14 @@ int main(int argc, char *argv[]) { assert(conf->cmd == PA_CMD_DAEMON); } + if (getuid() == 0 && !conf->system_instance) { + pa_log(__FILE__": This program is not intended to be run as root (unless --system is specified)."); + goto finish; + } else if (getuid() != 0 && conf->system_instance) { + pa_log(__FILE__": Root priviliges required."); + goto finish; + } + if (conf->daemonize) { pid_t child; int tty_fd; @@ -362,6 +473,13 @@ int main(int argc, char *argv[]) { } chdir("/"); + umask(0022); + + if (conf->system_instance) { + if (change_user() < 0) + goto finish; + } else if (create_runtime_dir() < 0) + goto finish; if (conf->use_pid_file) { if (pa_pid_file_create() < 0) { @@ -379,12 +497,13 @@ int main(int argc, char *argv[]) { #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif - + mainloop = pa_mainloop_new(); assert(mainloop); c = pa_core_new(pa_mainloop_get_api(mainloop)); assert(c); + c->is_system_instance = !!conf->system_instance; r = pa_signal_init(pa_mainloop_get_api(mainloop)); assert(r == 0); diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 28d6a08be..cd58a8388 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -52,11 +52,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#ifndef DEFAULT_CONFIG_DIR -#define DEFAULT_CONFIG_DIR "/etc/pulse" -#endif - -#define DEFAULT_MATCH_TABLE_FILE DEFAULT_CONFIG_DIR"/match.table" +#define DEFAULT_MATCH_TABLE_FILE PA_DEFAULT_CONFIG_DIR"/match.table" #define DEFAULT_MATCH_TABLE_FILE_USER ".pulse/match.table" static const char* const valid_modargs[] = { diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 207287661..fa21b737e 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -75,7 +75,14 @@ #include "module-simple-protocol-unix-symdef.h" #endif PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION) - PA_MODULE_USAGE("rate= format= channels= sink= source= playback= record= "SOCKET_USAGE) + PA_MODULE_USAGE("rate= " + "format= " + "channels= " + "sink= " + "source= " + "playback= " + "record= " + SOCKET_USAGE) #elif defined(USE_PROTOCOL_CLI) #include #define protocol_new pa_protocol_cli_new @@ -129,7 +136,10 @@ #endif PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) - PA_MODULE_USAGE("auth-anonymous= cookie= "AUTH_USAGE SOCKET_USAGE) + PA_MODULE_USAGE("auth-anonymous= " + "cookie= " + AUTH_USAGE + SOCKET_USAGE) #elif defined(USE_PROTOCOL_ESOUND) #include #include @@ -145,7 +155,11 @@ #include "module-esound-protocol-unix-symdef.h" #endif PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION) - PA_MODULE_USAGE("sink= source= auth-anonymous= cookie= "SOCKET_USAGE) + PA_MODULE_USAGE("sink= " + "source= " + "auth-anonymous= " + "cookie= " + SOCKET_USAGE) #else #error "Broken build system" #endif @@ -189,7 +203,6 @@ int pa__init(pa_core *c, pa_module*m) { #else pa_socket_server *s; int r; - const char *v; char tmp[PATH_MAX]; #endif @@ -241,15 +254,21 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; #else - v = pa_modargs_get_value(ma, "socket", UNIX_SOCKET); - pa_runtime_path(v, tmp, sizeof(tmp)); + + pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET), tmp, sizeof(tmp)); u->socket_path = pa_xstrdup(tmp); - if (pa_make_secure_parent_dir(tmp) < 0) { - pa_log(__FILE__": Failed to create secure socket directory."); +#if defined(USE_PROTOCOL_ESOUND) + + /* This socket doesn't reside in our own runtime dir but in + * /tmp/.esd/, hence we have to create the dir first */ + + if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, getuid(), getgid()) < 0) { + pa_log(__FILE__": Failed to create socket directory: %s\n", pa_cstrerror(errno)); goto fail; } - +#endif + if ((r = pa_unix_socket_remove_stale(tmp)) < 0) { pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s", tmp, pa_cstrerror(errno)); goto fail; @@ -324,19 +343,17 @@ void pa__done(pa_core *c, pa_module*m) { if (u->protocol_unix) protocol_free(u->protocol_unix); +#if defined(USE_PROTOCOL_ESOUND) if (u->socket_path) { - char *p; - - if ((p = pa_parent_dir(u->socket_path))) { - if (rmdir(p) < 0 && errno != ENOENT && errno != ENOTEMPTY) - pa_log(__FILE__": Failed to remove %s: %s.", u->socket_path, pa_cstrerror(errno)); - - pa_xfree(p); - } - - pa_xfree(u->socket_path); + char *p = pa_parent_dir(u->socket_path); + rmdir(p); + pa_xfree(p); } #endif + + + pa_xfree(u->socket_path); +#endif pa_xfree(u); } diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index bf2627a7e..c018c5205 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -611,7 +611,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void*creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { struct userdata *u = userdata; assert(p && packet && u); diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 5cebcf460..28b4f2d19 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -39,21 +39,13 @@ #include "client-conf.h" -#ifndef DEFAULT_CONFIG_DIR -# ifndef OS_IS_WIN32 -# define DEFAULT_CONFIG_DIR "/etc/pulse" -# else -# define DEFAULT_CONFIG_DIR "%PULSE_ROOT%" -# endif -#endif - #ifndef OS_IS_WIN32 # define PATH_SEP "/" #else # define PATH_SEP "\\" #endif -#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "client.conf" +#define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "client.conf" #define DEFAULT_CLIENT_CONFIG_FILE_USER ".pulse" PATH_SEP "client.conf" #define ENV_CLIENT_CONFIG_FILE "PULSE_CLIENTCONFIG" @@ -71,15 +63,17 @@ static const pa_client_conf default_conf = { .default_server = NULL, .autospawn = 0, .cookie_file = NULL, - .cookie_valid = 0 + .cookie_valid = 0, + .access_group = NULL }; pa_client_conf *pa_client_conf_new(void) { pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); - c->daemon_binary = pa_xstrdup(PULSEAUDIO_BINARY); + c->daemon_binary = pa_xstrdup(PA_BINARY); c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5"); c->cookie_file = pa_xstrdup(PA_NATIVE_COOKIE_FILE); + c->access_group = pa_xstrdup(PA_ACCESS_GROUP); return c; } @@ -92,6 +86,7 @@ void pa_client_conf_free(pa_client_conf *c) { pa_xfree(c->default_source); pa_xfree(c->default_server); pa_xfree(c->cookie_file); + pa_xfree(c->access_group); pa_xfree(c); } int pa_client_conf_load(pa_client_conf *c, const char *filename) { @@ -108,6 +103,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { { "default-server", pa_config_parse_string, NULL }, { "autospawn", pa_config_parse_bool, NULL }, { "cookie-file", pa_config_parse_string, NULL }, + { "access-group", pa_config_parse_string, NULL }, { NULL, NULL, NULL }, }; @@ -118,6 +114,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { table[4].data = &c->default_server; table[5].data = &c->autospawn; table[6].data = &c->cookie_file; + table[7].data = &c->access_group; f = filename ? fopen((fn = pa_xstrdup(filename)), "r") : diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index a532f0dfe..dfb1148dc 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -27,7 +27,7 @@ /* A structure containing configuration data for PulseAudio clients. */ typedef struct pa_client_conf { - char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; + char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file, *access_group; int autospawn; uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; int cookie_valid; /* non-zero, when cookie is valid */ diff --git a/src/pulse/context.c b/src/pulse/context.c index 228053bcf..a25e2f78e 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #ifdef HAVE_SYS_WAIT_H #include @@ -270,7 +272,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { pa_context *c = userdata; assert(p); @@ -420,7 +422,23 @@ static void setup_context(pa_context *c, pa_iochannel *io) { t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); - pa_pstream_send_tagstruct_with_creds(c->pstream, t, 1); + +#ifdef SCM_CREDENTIALS +{ + struct ucred ucred; + + ucred.pid = getpid(); + ucred.uid = getuid(); + + if ((ucred.gid = pa_get_gid_of_group(PA_ACCESS_GROUP)) == (gid_t) -1) + ucred.gid = getgid(); + + pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); +} +#else + pa_pstream_send_tagstruct_with_creds(c->pstream, t, NULL); +#endif + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); @@ -680,7 +698,7 @@ int pa_context_connect( char lf[PATH_MAX]; pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); - pa_make_secure_parent_dir(lf); + pa_make_secure_parent_dir(lf, 0700, getuid(), getgid()); assert(c->autospawn_lock_fd <= 0); c->autospawn_lock_fd = pa_lock_lockfile(lf); diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 7cb85209c..6375e5ef5 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -84,10 +84,10 @@ #endif #ifndef OS_IS_WIN32 -#define PA_RUNTIME_PATH_PREFIX "/tmp/pulse-" +#define PA_USER_RUNTIME_PATH_PREFIX "/tmp/pulse-" #define PATH_SEP '/' #else -#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-" +#define PA_USER_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-" #define PATH_SEP '\\' #endif @@ -136,23 +136,32 @@ void pa_make_nonblock_fd(int fd) { } /** Creates a directory securely */ -int pa_make_secure_dir(const char* dir) { +int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { struct stat st; + int r; + assert(dir); #ifdef OS_IS_WIN32 - if (mkdir(dir) < 0) + r = mkdir(dir); #else - if (mkdir(dir, 0700) < 0) + { + mode_t u; + u = umask(~m); + r = mkdir(dir, m); + umask(u); + } #endif - if (errno != EEXIST) - return -1; + + if (r < 0 && errno != EEXIST) + return -1; #ifdef HAVE_CHOWN - chown(dir, getuid(), getgid()); + chown(dir, uid, gid); #endif + #ifdef HAVE_CHMOD - chmod(dir, 0700); + chmod(dir, m); #endif #ifdef HAVE_LSTAT @@ -163,8 +172,13 @@ int pa_make_secure_dir(const char* dir) { goto fail; #ifndef OS_IS_WIN32 - if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700)) + if (!S_ISDIR(st.st_mode) || + (st.st_uid != uid) || + (st.st_gid != gid) || + ((st.st_mode & 0777) != m)) { + errno = EACCES; goto fail; + } #else fprintf(stderr, "FIXME: pa_make_secure_dir()\n"); #endif @@ -180,23 +194,24 @@ fail: char *pa_parent_dir(const char *fn) { char *slash, *dir = pa_xstrdup(fn); - slash = (char*) pa_path_get_filename(dir); - if (slash == fn) + if ((slash = (char*) pa_path_get_filename(dir)) == dir) { + pa_xfree(dir); return NULL; + } *(slash-1) = 0; return dir; } /* Creates a the parent directory of the specified path securely */ -int pa_make_secure_parent_dir(const char *fn) { +int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) { int ret = -1; char *dir; if (!(dir = pa_parent_dir(fn))) goto finish; - if (pa_make_secure_dir(dir) < 0) + if (pa_make_secure_dir(dir, m, uid, gid) < 0) goto finish; ret = 0; @@ -669,6 +684,7 @@ finish: return r; } +/* Check whether the specifc user id is a member of the specified group */ int pa_uid_in_group(uid_t uid, const char *name) { char *g_buf, *p_buf; long g_n, p_n; @@ -705,6 +721,26 @@ finish: return r; } +/* Get the GID of a gfiven group, return (gid_t) -1 on failure. */ +gid_t pa_get_gid_of_group(const char *name) { + gid_t ret = (gid_t) -1; + char *g_buf; + long g_n; + struct group grbuf, *gr; + + g_n = sysconf(_SC_GETGR_R_SIZE_MAX); + g_buf = pa_xmalloc(g_n); + + if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) + goto finish; + + ret = gr->gr_gid; + +finish: + pa_xfree(g_buf); + return ret; +} + #else /* HAVE_GRP_H */ int pa_own_uid_in_group(const char *name, gid_t *gid) { @@ -1003,7 +1039,7 @@ int pa_endswith(const char *s, const char *sfx) { * if fn is non-null and starts with / return fn in s * otherwise append fn to the run time path and return it in s */ char *pa_runtime_path(const char *fn, char *s, size_t l) { - char u[256]; + const char *e; #ifndef OS_IS_WIN32 if (fn && *fn == '/') @@ -1012,10 +1048,22 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) { #endif return pa_strlcpy(s, fn, l); - if (fn) - snprintf(s, l, "%s%s%c%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn); - else - snprintf(s, l, "%s%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u))); + if ((e = getenv("PULSE_RUNTIME_PATH"))) { + + if (fn) + snprintf(s, l, "%s%c%s", e, PATH_SEP, fn); + else + snprintf(s, l, "%s", e); + + } else { + char u[256]; + + if (fn) + snprintf(s, l, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn); + else + snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u))); + } + #ifdef OS_IS_WIN32 { diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 864a96ecc..db764de10 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -33,8 +33,8 @@ struct timeval; void pa_make_nonblock_fd(int fd); -int pa_make_secure_dir(const char* dir); -int pa_make_secure_parent_dir(const char *fn); +int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid); +int pa_make_secure_parent_dir(const char *fn, mode_t, uid_t uid, gid_t gid); ssize_t pa_read(int fd, void *buf, size_t count, int *type); ssize_t pa_write(int fd, const void *buf, size_t count, int *type); @@ -66,6 +66,7 @@ const char *pa_strsignal(int sig); int pa_own_uid_in_group(const char *name, gid_t *gid); int pa_uid_in_group(uid_t uid, const char *name); +gid_t pa_get_gid_of_group(const char *name); int pa_lock_fd(int fd, int b); diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 7c780ea8e..d6af3ca91 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -46,7 +46,8 @@ pa_core* pa_core_new(pa_mainloop_api *m) { pa_core* c; - c = pa_xmalloc(sizeof(pa_core)); + + c = pa_xnew(pa_core, 1); c->mainloop = m; c->clients = pa_idxset_new(NULL, NULL); @@ -88,6 +89,8 @@ pa_core* pa_core_new(pa_mainloop_api *m) { c->resample_method = PA_RESAMPLER_SRC_SINC_FASTEST; + c->is_system_instance = 0; + pa_property_init(c); pa_random(&c->cookie, sizeof(c->cookie)); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 261c5f752..61f174321 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -71,6 +71,8 @@ struct pa_core { pa_time_event *scache_auto_unload_event; pa_resample_method_t resample_method; + + int is_system_instance; }; pa_core* pa_core_new(pa_mainloop_api *m); diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 15aa8e35c..852e960ea 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -263,12 +263,12 @@ int pa_iochannel_creds_enable(pa_iochannel *io) { return 0; } -ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l) { +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const struct ucred *ucred) { ssize_t r; struct msghdr mh; struct iovec iov; uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))]; - struct ucred *ucred; + struct ucred *u; struct cmsghdr *cmsg; assert(io); @@ -286,10 +286,15 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_CREDENTIALS; - ucred = (struct ucred*) CMSG_DATA(cmsg); - ucred->pid = getpid(); - ucred->uid = getuid(); - ucred->gid = getgid(); + u = (struct ucred*) CMSG_DATA(cmsg); + + if (ucred) + *u = *ucred; + else { + u->pid = getpid(); + u->uid = getuid(); + u->gid = getgid(); + } memset(&mh, 0, sizeof(mh)); mh.msg_name = NULL; diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h index 64cf331ec..3b5cba1c2 100644 --- a/src/pulsecore/iochannel.h +++ b/src/pulsecore/iochannel.h @@ -54,7 +54,7 @@ int pa_iochannel_creds_enable(pa_iochannel *io); struct ucred; -ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l); +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const struct ucred *ucred); ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid); int pa_iochannel_is_readable(pa_iochannel*io); diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 5b76b432c..9bc20da47 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -180,7 +180,7 @@ static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command, pa_pdispatch_unref(pd); } -int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const void *creds, void *userdata) { +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const struct ucred *creds, void *userdata) { uint32_t tag, command; pa_tagstruct *ts = NULL; int ret = -1; @@ -310,7 +310,7 @@ pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd) { return pd; } -const void * pa_pdispatch_creds(pa_pdispatch *pd) { +const struct ucred * pa_pdispatch_creds(pa_pdispatch *pd) { assert(pd); assert(pd->ref >= 1); diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h index 07620e5ae..18073502f 100644 --- a/src/pulsecore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -28,6 +28,8 @@ #include #include +struct ucred; + typedef struct pa_pdispatch pa_pdispatch; typedef void (*pa_pdispatch_cb_t)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); @@ -37,7 +39,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_cb_t*table void pa_pdispatch_unref(pa_pdispatch *pd); pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); -int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const void*creds, void *userdata); +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const struct ucred*creds, void *userdata); void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t callback, void *userdata, pa_free_cb_t free_cb); @@ -48,6 +50,6 @@ void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, pa_pdispatch_drain_callba /* Remove all reply slots with the give userdata parameter */ void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata); -const void * pa_pdispatch_creds(pa_pdispatch *pd); +const struct ucred * pa_pdispatch_creds(pa_pdispatch *pd); #endif diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index 0ad76a6e2..044d223d2 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -79,13 +79,10 @@ static pid_t read_pid(const char *fn, int fd) { static int open_pid_file(const char *fn, int mode) { int fd = -1; - int lock = -1; for (;;) { struct stat st; - pa_make_secure_parent_dir(fn); - if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) { if (mode != O_RDONLY || errno != ENOENT) pa_log_warn(__FILE__": WARNING: failed to open PID file '%s': %s", @@ -123,10 +120,8 @@ static int open_pid_file(const char *fn, int mode) { fail: - if (fd < 0) { - if (lock >= 0) - pa_lock_fd(fd, 0); - + if (fd >= 0) { + pa_lock_fd(fd, 0); close(fd); } @@ -199,7 +194,6 @@ int pa_pid_file_remove(void) { char fn[PATH_MAX]; int ret = -1; pid_t pid; - char *p; pa_runtime_path("pid", fn, sizeof(fn)); @@ -235,11 +229,6 @@ int pa_pid_file_remove(void) { goto fail; } - if ((p = pa_parent_dir(fn))) { - rmdir(p); - pa_xfree(p); - } - ret = 0; fail: diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 784610bd8..14f880d7f 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2100,7 +2100,7 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC /*** pstream callbacks ***/ -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { struct connection *c = userdata; assert(p && packet && packet->data && c); diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c index 3a995324d..09d6f2fa8 100644 --- a/src/pulsecore/pstream-util.c +++ b/src/pulsecore/pstream-util.c @@ -29,7 +29,7 @@ #include "pstream-util.h" -void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, int creds) { +void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const struct ucred *creds) { size_t length; uint8_t *data; pa_packet *packet; diff --git a/src/pulsecore/pstream-util.h b/src/pulsecore/pstream-util.h index fc6d18c05..c60000a8b 100644 --- a/src/pulsecore/pstream-util.h +++ b/src/pulsecore/pstream-util.h @@ -26,8 +26,10 @@ #include #include +struct ucred; + /* The tagstruct is freed!*/ -void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, int creds); +void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const struct ucred *creds); #define pa_pstream_send_tagstruct(p, t) pa_pstream_send_tagstruct_with_creds((p), (t), 0) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 7992ccb66..7ef493051 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #ifdef HAVE_NETINET_IN_H #include @@ -69,6 +71,7 @@ struct item_info { pa_packet *packet; #ifdef SCM_CREDENTIALS int with_creds; + struct ucred creds; #endif }; @@ -112,9 +115,8 @@ struct pa_pstream { pa_memblock_stat *memblock_stat; #ifdef SCM_CREDENTIALS - int send_creds_now; - struct ucred ucred; - int creds_valid; + struct ucred read_creds, write_creds; + int read_creds_valid, send_creds_now; #endif }; @@ -216,7 +218,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta #ifdef SCM_CREDENTIALS p->send_creds_now = 0; - p->creds_valid = 0; + p->read_creds_valid = 0; #endif return p; } @@ -256,7 +258,7 @@ static void pstream_free(pa_pstream *p) { pa_xfree(p); } -void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, int with_creds) { +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred *creds) { struct item_info *i; assert(p && packet && p->ref >= 1); @@ -269,7 +271,8 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, int with_creds) { i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); #ifdef SCM_CREDENTIALS - i->with_creds = with_creds; + if ((i->with_creds = !!creds)) + i->creds = *creds; #endif pa_queue_push(p->send_queue, i); @@ -332,7 +335,9 @@ static void prepare_next_write_item(pa_pstream *p) { } #ifdef SCM_CREDENTIALS - p->send_creds_now = p->write.current->with_creds; + if ((p->send_creds_now = p->write.current->with_creds)) + p->write_creds = p->write.current->creds; + #endif } @@ -362,7 +367,7 @@ static int do_write(pa_pstream *p) { #ifdef SCM_CREDENTIALS if (p->send_creds_now) { - if ((r = pa_iochannel_write_with_creds(p->io, d, l)) < 0) + if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0) return -1; p->send_creds_now = 0; @@ -403,12 +408,12 @@ static int do_read(pa_pstream *p) { #ifdef SCM_CREDENTIALS { - int b; + int b = 0; - if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->ucred, &b)) <= 0) + if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->read_creds, &b)) <= 0) return -1; - p->creds_valid = p->creds_valid || b; + p->read_creds_valid = p->read_creds_valid || b; } #else if ((r = pa_iochannel_read(p->io, d, l)) <= 0) @@ -491,7 +496,7 @@ static int do_read(pa_pstream *p) { if (p->recieve_packet_callback) #ifdef SCM_CREDENTIALS - p->recieve_packet_callback(p, p->read.packet, p->creds_valid ? &p->ucred : NULL, p->recieve_packet_callback_userdata); + p->recieve_packet_callback(p, p->read.packet, p->read_creds_valid ? &p->read_creds : NULL, p->recieve_packet_callback_userdata); #else p->recieve_packet_callback(p, p->read.packet, NULL, p->recieve_packet_callback_userdata); #endif @@ -502,7 +507,7 @@ static int do_read(pa_pstream *p) { p->read.index = 0; #ifdef SCM_CREDENTIALS - p->creds_valid = 0; + p->read_creds_valid = 0; #endif } } diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h index 1a2932d4f..39cb75919 100644 --- a/src/pulsecore/pstream.h +++ b/src/pulsecore/pstream.h @@ -31,9 +31,11 @@ #include #include +struct ucred; + typedef struct pa_pstream pa_pstream; -typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata); +typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata); typedef void (*pa_pstream_memblock_cb_t)(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata); typedef void (*pa_pstream_notify_cb_t)(pa_pstream *p, void *userdata); @@ -41,7 +43,7 @@ pa_pstream* pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta void pa_pstream_unref(pa_pstream*p); pa_pstream* pa_pstream_ref(pa_pstream*p); -void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, int with_creds); +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred *creds); void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk); void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata); From 45a9a8bcb5572188ca9121e4f11bfeb5c932411f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 18:08:29 +0000 Subject: [PATCH 1008/1514] fix sed scripts according to #define renames git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1106 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 1a4bcb04d..d4fbe5288 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1168,22 +1168,22 @@ CLEANFILES = esdcompat client.conf default.pa daemon.conf esdcompat: daemon/esdcompat.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ - -e 's,@PULSEAUDIO_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ + -e 's,@PA_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ client.conf: pulse/client.conf.in Makefile - sed -e 's,@PULSEAUDIO_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ + sed -e 's,@PA_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ if OS_IS_WIN32 default.pa: daemon/default.pa.win32 cp $< $@ else default.pa: daemon/default.pa.in Makefile - sed -e 's,@PULSEAUDIO_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ + sed -e 's,@PA_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ endif daemon.conf: daemon/daemon.conf.in Makefile - sed -e 's,@DLSEARCHPATH\@,$(modlibexecdir),g' \ - -e 's,@DEFAULT_CONFIG_FILE\@,$(DEFAULT_CONFIG_DIR),g' < $< > $@ + sed -e 's,@PA_DLSEARCHPATH\@,$(modlibexecdir),g' \ + -e 's,@PA_DEFAULT_CONFIG_FILE\@,$(DEFAULT_CONFIG_DIR),g' < $< > $@ install-exec-hook: chown root $(DESTDIR)$(bindir)/pulseaudio ; true From 2b31a900d67506592aecd9c0d59ad997d7977deb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 18:11:12 +0000 Subject: [PATCH 1009/1514] update @@ tokens according to recent Makefile.am change git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1107 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon.conf.in | 4 ++-- src/daemon/esdcompat.in | 2 +- src/pulse/client.conf.in | 8 +++++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 6e55c0ee6..30628969e 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -52,11 +52,11 @@ ## The path were to look for dynamic shared objects (DSOs aka ## plugins). You may specify more than one path seperated by ## colons. -; dl-search-path = @DLSEARCHPATH@ +; dl-search-path = @PA_DLSEARCHPATH@ ## The default script file to load. Specify an empty string for not ## loading a default script file. The -; default-script-file = @DEFAULT_CONFIG_FILE@ +; default-script-file = @PA_DEFAULT_CONFIG_FILE@ ## The default log target. Use either "stderr", "syslog" or ## "auto". The latter is equivalent to "sylog" in case daemonize is diff --git a/src/daemon/esdcompat.in b/src/daemon/esdcompat.in index edae8615d..ece1f4f92 100755 --- a/src/daemon/esdcompat.in +++ b/src/daemon/esdcompat.in @@ -95,4 +95,4 @@ EOF shift done -eval "exec '@PULSEAUDIO_BINARY@'$ARGS" +eval "exec '@PA_BINARY@'$ARGS" diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in index 21786ebf4..3e0087661 100644 --- a/src/pulse/client.conf.in +++ b/src/pulse/client.conf.in @@ -21,7 +21,7 @@ ## commented out. Use either ; or # for commenting ## Path to the pulseaudio daemon to run when autospawning. -; daemon-binary = @PULSEAUDIO_BINARY@ +; daemon-binary = @PA_BINARY@ ## Extra arguments to pass to the pulseaudio daemon ; extra-arguments = --log-target=syslog --exit-idle-time=5 @@ -37,3 +37,9 @@ ## Autospawn daemons? ; autospawn = 0 + +### Cookie file +; cookie-file = + +### Access group +; access-group = From 340803b30c154ead29795454416592ff9d0e0df2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 18:14:14 +0000 Subject: [PATCH 1010/1514] use access group dedclared in ~/.pulse/client.conf instead of PA_ACCESS_GROUP git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1108 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/default.pa.in | 2 +- src/pulse/context.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index 6beeb90f6..ac10c0ca3 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -1,4 +1,4 @@ -#!@PULSEAUDIO_BINARY@ -nF +#!@PA_BINARY@ -nF # # This file is part of PulseAudio. diff --git a/src/pulse/context.c b/src/pulse/context.c index a25e2f78e..f6452d4ed 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -430,7 +430,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) { ucred.pid = getpid(); ucred.uid = getuid(); - if ((ucred.gid = pa_get_gid_of_group(PA_ACCESS_GROUP)) == (gid_t) -1) + if ((ucred.gid = pa_get_gid_of_group(c->conf->access_group)) == (gid_t) -1) ucred.gid = getgid(); pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); From a382492204ad3588c0c837e120e5bc31578df72a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 21:48:35 +0000 Subject: [PATCH 1011/1514] * add new function pa_check_in_group() * abstract credential APis a little bit by introducing HAVE_CREDS and a structure pa_creds * rework credential authentication * fix module-volume-restore and friends for usage in system-wide instance * remove loopback= argument from moulde-*-protocol-tcp since it is a superset of listen= and usually a bad idea anyway since the user shouldn't load the TCP module at all if he doesn't want remote access * rename a few variables in the jack modules to make sure they don't conflict with symbols defined in the system headers * add server address for system-wide daemons to the default server list for the the client libs * update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1109 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 4 +- src/daemon/main.c | 3 +- src/modules/module-jack-sink.c | 6 +-- src/modules/module-jack-source.c | 6 +-- src/modules/module-match.c | 2 +- src/modules/module-protocol-stub.c | 19 +++------ src/modules/module-tunnel.c | 2 +- src/modules/module-volume-restore.c | 2 +- src/pulse/client-conf.c | 2 +- src/pulse/context.c | 22 ++++++---- src/pulsecore/core-util.c | 63 ++++++++++++++++++++--------- src/pulsecore/core-util.h | 1 + src/pulsecore/creds.h | 44 ++++++++++++++++++++ src/pulsecore/iochannel.c | 44 +++++++------------- src/pulsecore/iochannel.h | 9 +++-- src/pulsecore/pdispatch.c | 6 +-- src/pulsecore/pdispatch.h | 9 +++-- src/pulsecore/protocol-native.c | 55 ++++++++++++++++--------- src/pulsecore/pstream-util.c | 2 +- src/pulsecore/pstream-util.h | 5 +-- src/pulsecore/pstream.c | 27 +++++++------ src/pulsecore/pstream.h | 8 ++-- src/pulsecore/socket-server.c | 9 ++++- todo | 6 ++- 24 files changed, 222 insertions(+), 134 deletions(-) create mode 100644 src/pulsecore/creds.h diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index a5a62567a..2577578cc 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -46,9 +46,9 @@ #endif #define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "default.pa" -#define DEFAULT_SCRIPT_FILE_USER ".pulse" PATH_SEP "default.pa" +#define DEFAULT_SCRIPT_FILE_USER PATH_SEP "default.pa" #define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" -#define DEFAULT_CONFIG_FILE_USER ".pulse" PATH_SEP "daemon.conf" +#define DEFAULT_CONFIG_FILE_USER PATH_SEP "daemon.conf" #define ENV_SCRIPT_FILE "PULSE_SCRIPT" #define ENV_CONFIG_FILE "PULSE_CONFIG" diff --git a/src/daemon/main.c b/src/daemon/main.c index 4961f0ca3..0449cb943 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -229,6 +229,7 @@ static int change_user(void) { /* Relevant for pa_runtime_path() */ set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH); + set_env("PULSE_CONFIG_PATH", PA_SYSTEM_RUNTIME_PATH); pa_log_info(__FILE__": Successfully dropped root privileges."); @@ -245,8 +246,6 @@ static int create_runtime_dir(void) { return -1; } - /* Relevant for pa_runtime_path() later on */ - set_env("PULSE_RUNTIME_PATH", fn); return 0; } diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index d761c1f7c..c645caa99 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -242,7 +242,7 @@ int pa__init(pa_core *c, pa_module*m) { jack_status_t status; const char *server_name, *client_name; uint32_t channels = 0; - int connect = 1; + int do_connect = 1; unsigned i; const char **ports = NULL, **p; @@ -256,7 +256,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (pa_modargs_get_value_boolean(ma, "connect", &connect) < 0) { + if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { pa_log(__FILE__": failed to parse connect= argument."); goto fail; } @@ -339,7 +339,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (connect) { + if (do_connect) { for (i = 0, p = ports; i < ss.channels; i++, p++) { if (!*p) { diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 649a8f98d..2a4929292 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -240,7 +240,7 @@ int pa__init(pa_core *c, pa_module*m) { jack_status_t status; const char *server_name, *client_name; uint32_t channels = 0; - int connect = 1; + int do_connect = 1; unsigned i; const char **ports = NULL, **p; @@ -254,7 +254,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (pa_modargs_get_value_boolean(ma, "connect", &connect) < 0) { + if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { pa_log(__FILE__": failed to parse connect= argument."); goto fail; } @@ -337,7 +337,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (connect) { + if (do_connect) { for (i = 0, p = ports; i < ss.channels; i++, p++) { if (!*p) { diff --git a/src/modules/module-match.c b/src/modules/module-match.c index cd58a8388..ab94b02d7 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -53,7 +53,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" #define DEFAULT_MATCH_TABLE_FILE PA_DEFAULT_CONFIG_DIR"/match.table" -#define DEFAULT_MATCH_TABLE_FILE_USER ".pulse/match.table" +#define DEFAULT_MATCH_TABLE_FILE_USER "match.table" static const char* const valid_modargs[] = { "table", diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index fa21b737e..ecbc5676c 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -52,10 +52,11 @@ #include #include #include +#include #ifdef USE_TCP_SOCKETS #define SOCKET_DESCRIPTION "(TCP sockets)" -#define SOCKET_USAGE "port= loopback= listen=
        " +#define SOCKET_USAGE "port= listen=
        " #else #define SOCKET_DESCRIPTION "(UNIX sockets)" #define SOCKET_USAGE "socket=" @@ -127,9 +128,9 @@ #include "module-native-protocol-unix-symdef.h" #endif - #if defined(SCM_CREDENTIALS) && !defined(USE_TCP_SOCKETS) - #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", - #define AUTH_USAGE "auth-group=" + #if defined(HAVE_CREDS) && !defined(USE_TCP_SOCKETS) + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable=" + #define AUTH_USAGE "auth-group= auth-group-enable= " #else #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON #define AUTH_USAGE @@ -171,7 +172,6 @@ static const char* const valid_modargs[] = { MODULE_ARGUMENTS #if defined(USE_TCP_SOCKETS) "port", - "loopback", "listen", #else "socket", @@ -197,7 +197,6 @@ int pa__init(pa_core *c, pa_module*m) { #if defined(USE_TCP_SOCKETS) pa_socket_server *s_ipv4 = NULL, *s_ipv6 = NULL; - int loopback = 1; uint32_t port = IPV4_PORT; const char *listen_on; #else @@ -216,11 +215,6 @@ int pa__init(pa_core *c, pa_module*m) { u = pa_xnew0(struct userdata, 1); #if defined(USE_TCP_SOCKETS) - if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) { - pa_log(__FILE__": loopback= expects a boolean argument."); - goto fail; - } - if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { pa_log(__FILE__": port= expects a numerical argument between 1 and 65535."); goto fail; @@ -231,9 +225,6 @@ int pa__init(pa_core *c, pa_module*m) { if (listen_on) { s_ipv6 = pa_socket_server_new_ipv6_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); s_ipv4 = pa_socket_server_new_ipv4_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); - } else if (loopback) { - s_ipv6 = pa_socket_server_new_ipv6_loopback(c->mainloop, port, TCPWRAP_SERVICE); - s_ipv4 = pa_socket_server_new_ipv4_loopback(c->mainloop, port, TCPWRAP_SERVICE); } else { s_ipv6 = pa_socket_server_new_ipv6_any(c->mainloop, port, TCPWRAP_SERVICE); s_ipv4 = pa_socket_server_new_ipv4_any(c->mainloop, port, TCPWRAP_SERVICE); diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index c018c5205..2fb34d12b 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -611,7 +611,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { struct userdata *u = userdata; assert(p && packet && u); diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 2f45082b3..d09565097 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -53,7 +53,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#define DEFAULT_VOLUME_TABLE_FILE ".pulse/volume.table" +#define DEFAULT_VOLUME_TABLE_FILE "volume.table" static const char* const valid_modargs[] = { "table", diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 28b4f2d19..219175973 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -46,7 +46,7 @@ #endif #define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "client.conf" -#define DEFAULT_CLIENT_CONFIG_FILE_USER ".pulse" PATH_SEP "client.conf" +#define DEFAULT_CLIENT_CONFIG_FILE_USER "client.conf" #define ENV_CLIENT_CONFIG_FILE "PULSE_CLIENTCONFIG" #define ENV_DEFAULT_SINK "PULSE_SINK" diff --git a/src/pulse/context.c b/src/pulse/context.c index f6452d4ed..0150204cb 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -62,6 +62,7 @@ #include #include #include +#include #include "internal.h" @@ -272,7 +273,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { pa_context *c = userdata; assert(p); @@ -423,15 +424,17 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS { - struct ucred ucred; + pa_creds ucred; + gid_t g; - ucred.pid = getpid(); ucred.uid = getuid(); + ucred.gid = getgid(); - if ((ucred.gid = pa_get_gid_of_group(c->conf->access_group)) == (gid_t) -1) - ucred.gid = getgid(); + if ((g = pa_get_gid_of_group(c->conf->access_group)) != (gid_t) -1) + if (pa_check_in_group(g) > 0) + ucred.gid = g; pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } @@ -690,7 +693,12 @@ int pa_context_connect( } c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost"); - c->server_list = pa_strlist_prepend(c->server_list, "localhost"); + c->server_list = pa_strlist_prepend(c->server_list, "tcp4:localhost"); + + /* The system wide instance */ + c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH "/" PA_NATIVE_DEFAULT_UNIX_SOCKET); + + /* The per-user instance */ c->server_list = pa_strlist_prepend(c->server_list, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET, ufn, sizeof(ufn))); /* Wrap the connection attempts in a single transaction for sane autospawn locking */ diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 6375e5ef5..0e6501b8f 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -741,6 +741,20 @@ finish: return ret; } +int pa_check_in_group(gid_t g) { + gid_t gids[NGROUPS_MAX]; + int r; + + if ((r = getgroups(NGROUPS_MAX, gids)) < 0) + return -1; + + for (; r > 0; r--) + if (gids[r-1] == g) + return 1; + + return 0; +} + #else /* HAVE_GRP_H */ int pa_own_uid_in_group(const char *name, gid_t *gid) { @@ -752,6 +766,14 @@ int pa_uid_in_group(uid_t uid, const char *name) { return -1; } +gid_t pa_get_gid_of_group(const char *name) { + return (gid_t) -1; +} + +int pa_check_in_group(gid_t g) { + return -1; +} + #endif /* Lock or unlock a file entirely. @@ -909,28 +931,33 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env return fopen(fn, mode); } - if (local && pa_get_home_dir(h, sizeof(h))) { - FILE *f; - char *lfn; - - fn = lfn = pa_sprintf_malloc("%s/%s", h, local); + if (local) { + const char *e; + char *lfn = NULL; + if ((e = getenv("PULSE_CONFIG_PATH"))) + fn = lfn = pa_sprintf_malloc("%s/%s", e, local); + else if (pa_get_home_dir(h, sizeof(h))) + fn = lfn = pa_sprintf_malloc("%s/.pulse/%s", h, local); + + if (lfn) { + FILE *f; + #ifdef OS_IS_WIN32 - if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) - return NULL; - fn = buf; + if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) + return NULL; + fn = buf; #endif - - f = fopen(fn, mode); - - if (f || errno != ENOENT) { - if (result) - *result = pa_xstrdup(fn); - pa_xfree(lfn); - return f; - } + + if ((f = fopen(fn, mode)) || errno != ENOENT) { + if (result) + *result = pa_xstrdup(fn); + pa_xfree(lfn); + return f; + } - pa_xfree(lfn); + pa_xfree(lfn); + } } if (!global) { diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index db764de10..ba3259686 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -67,6 +67,7 @@ const char *pa_strsignal(int sig); int pa_own_uid_in_group(const char *name, gid_t *gid); int pa_uid_in_group(uid_t uid, const char *name); gid_t pa_get_gid_of_group(const char *name); +int pa_check_in_group(gid_t g); int pa_lock_fd(int fd, int b); diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h new file mode 100644 index 000000000..a95f4480f --- /dev/null +++ b/src/pulsecore/creds.h @@ -0,0 +1,44 @@ +#ifndef foocredshfoo +#define foocredshfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include + +typedef struct pa_creds pa_creds; + +#if defined(SCM_CREDENTIALS) + +#define HAVE_CREDS 1 + +struct pa_creds { + gid_t gid; + uid_t uid; +}; + +#else +#undef HAVE_CREDS +#endif + +#endif diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 852e960ea..b50293bff 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -231,7 +231,7 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { return r; } -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS int pa_iochannel_creds_supported(pa_iochannel *io) { struct sockaddr_un sa; @@ -263,7 +263,7 @@ int pa_iochannel_creds_enable(pa_iochannel *io) { return 0; } -ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const struct ucred *ucred) { +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const pa_creds *ucred) { ssize_t r; struct msghdr mh; struct iovec iov; @@ -288,10 +288,11 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l u = (struct ucred*) CMSG_DATA(cmsg); - if (ucred) - *u = *ucred; - else { - u->pid = getpid(); + u->pid = getpid(); + if (ucred) { + u->uid = ucred->uid; + u->gid = ucred->gid; + } else { u->uid = getuid(); u->gid = getgid(); } @@ -313,7 +314,7 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l return r; } -ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid) { +ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *creds, int *creds_valid) { ssize_t r; struct msghdr mh; struct iovec iov; @@ -323,7 +324,7 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struc assert(data); assert(l); assert(io->ifd >= 0); - assert(ucred); + assert(creds); assert(creds_valid); memset(&iov, 0, sizeof(iov)); @@ -349,8 +350,12 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struc for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { + struct ucred u; assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))); - memcpy(ucred, CMSG_DATA(cmsg), sizeof(struct ucred)); + memcpy(&u, CMSG_DATA(cmsg), sizeof(struct ucred)); + + creds->gid = u.gid; + creds->uid = u.uid; *creds_valid = 1; break; } @@ -362,27 +367,8 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struc return r; } -#else /* SCM_CREDENTIALS */ -int pa_iochannel_creds_supported(pa_iochannel *io) { - return 0; -} - -int pa_iochannel_creds_enable(pa_iochannel *io) { - return -1; -} - -ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l) { - pa_log_error("pa_iochannel_write_with_creds() not supported."); - return -1; -} - -ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid) { - pa_log_error("pa_iochannel_read_with_creds() not supported."); - return -1; -} - -#endif /* SCM_CREDENTIALS */ +#endif /* HAVE_CREDS */ void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) { assert(io); diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h index 3b5cba1c2..1f9ab0d44 100644 --- a/src/pulsecore/iochannel.h +++ b/src/pulsecore/iochannel.h @@ -25,6 +25,7 @@ #include #include +#include /* A wrapper around UNIX file descriptors for attaching them to the a main event loop. Everytime new data may be read or be written to @@ -49,13 +50,13 @@ void pa_iochannel_free(pa_iochannel*io); ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l); ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l); +#ifdef HAVE_CREDS int pa_iochannel_creds_supported(pa_iochannel *io); int pa_iochannel_creds_enable(pa_iochannel *io); -struct ucred; - -ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const struct ucred *ucred); -ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid); +ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const pa_creds *ucred); +ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *ucred, int *creds_valid); +#endif int pa_iochannel_is_readable(pa_iochannel*io); int pa_iochannel_is_writable(pa_iochannel*io); diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 9bc20da47..db54b2a31 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -112,7 +112,7 @@ struct pa_pdispatch { PA_LLIST_HEAD(struct reply_info, replies); pa_pdispatch_drain_callback drain_callback; void *drain_userdata; - const void *creds; + const pa_creds *creds; }; static void reply_info_free(struct reply_info *r) { @@ -180,7 +180,7 @@ static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command, pa_pdispatch_unref(pd); } -int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const struct ucred *creds, void *userdata) { +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, void *userdata) { uint32_t tag, command; pa_tagstruct *ts = NULL; int ret = -1; @@ -310,7 +310,7 @@ pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd) { return pd; } -const struct ucred * pa_pdispatch_creds(pa_pdispatch *pd) { +const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd) { assert(pd); assert(pd->ref >= 1); diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h index 18073502f..479eb6b44 100644 --- a/src/pulsecore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -23,12 +23,13 @@ ***/ #include + #include #include + #include #include - -struct ucred; +#include typedef struct pa_pdispatch pa_pdispatch; @@ -39,7 +40,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, const pa_pdispatch_cb_t*table void pa_pdispatch_unref(pa_pdispatch *pd); pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd); -int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const struct ucred*creds, void *userdata); +int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const pa_creds *creds, void *userdata); void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t callback, void *userdata, pa_free_cb_t free_cb); @@ -50,6 +51,6 @@ void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, pa_pdispatch_drain_callba /* Remove all reply slots with the give userdata parameter */ void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata); -const struct ucred * pa_pdispatch_creds(pa_pdispatch *pd); +const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd); #endif diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 14f880d7f..2775d7745 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -55,6 +55,8 @@ #include #include #include +#include +#include #include "protocol-native.h" @@ -134,7 +136,7 @@ struct pa_protocol_native { pa_idxset *connections; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; int auth_cookie_in_property; -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS char *auth_group; #endif }; @@ -910,25 +912,32 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t if (!c->authorized) { int success = 0; -#ifdef SCM_CREDENTIALS - const struct ucred *ucred = pa_pdispatch_creds(pd); +#ifdef HAVE_CREDS + const pa_creds *creds; - if (ucred) { - if (ucred->uid == getuid()) + if ((creds = pa_pdispatch_creds(pd))) { + if (creds->uid == getuid()) success = 1; else if (c->protocol->auth_group) { int r; - - if ((r = pa_uid_in_group(ucred->uid, c->protocol->auth_group)) < 0) - pa_log_warn(__FILE__": failed to check group membership."); - else if (r > 0) + gid_t gid; + + if ((gid = pa_get_gid_of_group(c->protocol->auth_group)) == (gid_t) -1) + pa_log_warn(__FILE__": failed to get GID of group '%s'", c->protocol->auth_group); + else if (gid == creds->gid) success = 1; + + if (!success) { + if ((r = pa_uid_in_group(creds->uid, c->protocol->auth_group)) < 0) + pa_log_warn(__FILE__": failed to check group membership."); + else if (r > 0) + success = 1; + } } - pa_log_info(__FILE__": Got credentials: pid=%lu uid=%lu gid=%lu auth=%i", - (unsigned long) ucred->pid, - (unsigned long) ucred->uid, - (unsigned long) ucred->gid, + pa_log_info(__FILE__": Got credentials: uid=%lu gid=%lu success=%i", + (unsigned long) creds->uid, + (unsigned long) creds->gid, success); } #endif @@ -2100,7 +2109,7 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC /*** pstream callbacks ***/ -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { struct connection *c = userdata; assert(p && packet && packet->data && c); @@ -2272,7 +2281,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo pa_idxset_put(p->connections, c, NULL); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS if (pa_iochannel_creds_supported(io)) pa_iochannel_creds_enable(io); @@ -2323,8 +2332,18 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo p->public = public; p->server = NULL; -#ifdef SCM_CREDENTIALS - p->auth_group = pa_xstrdup(pa_modargs_get_value(ma, "auth-group", NULL)); +#ifdef HAVE_CREDS + { + int a = 1; + if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &a) < 0) { + pa_log(__FILE__": auth-group-enabled= expects a boolean argument."); + return NULL; + } + p->auth_group = a ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", c->is_system_instance ? PA_ACCESS_GROUP : NULL)) : NULL; + + if (p->auth_group) + pa_log_info(__FILE__": Allowing access to group '%s'.", p->auth_group); + } #endif if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0) { @@ -2386,7 +2405,7 @@ void pa_protocol_native_free(pa_protocol_native *p) { if (p->auth_cookie_in_property) pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS pa_xfree(p->auth_group); #endif pa_xfree(p); diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c index 09d6f2fa8..d7c1b31b8 100644 --- a/src/pulsecore/pstream-util.c +++ b/src/pulsecore/pstream-util.c @@ -29,7 +29,7 @@ #include "pstream-util.h" -void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const struct ucred *creds) { +void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const pa_creds *creds) { size_t length; uint8_t *data; pa_packet *packet; diff --git a/src/pulsecore/pstream-util.h b/src/pulsecore/pstream-util.h index c60000a8b..f384d8895 100644 --- a/src/pulsecore/pstream-util.h +++ b/src/pulsecore/pstream-util.h @@ -25,11 +25,10 @@ #include #include #include - -struct ucred; +#include /* The tagstruct is freed!*/ -void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const struct ucred *creds); +void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const pa_creds *creds); #define pa_pstream_send_tagstruct(p, t) pa_pstream_send_tagstruct_with_creds((p), (t), 0) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 7ef493051..de5fa43e6 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "pstream.h" @@ -69,9 +70,9 @@ struct item_info { /* packet info */ pa_packet *packet; -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS int with_creds; - struct ucred creds; + pa_creds creds; #endif }; @@ -114,8 +115,8 @@ struct pa_pstream { pa_memblock_stat *memblock_stat; -#ifdef SCM_CREDENTIALS - struct ucred read_creds, write_creds; +#ifdef HAVE_CREDS + pa_creds read_creds, write_creds; int read_creds_valid, send_creds_now; #endif }; @@ -216,7 +217,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta pa_iochannel_socket_set_rcvbuf(io, 1024*8); pa_iochannel_socket_set_sndbuf(io, 1024*8); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS p->send_creds_now = 0; p->read_creds_valid = 0; #endif @@ -258,7 +259,7 @@ static void pstream_free(pa_pstream *p) { pa_xfree(p); } -void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred *creds) { +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds) { struct item_info *i; assert(p && packet && p->ref >= 1); @@ -270,7 +271,7 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS if ((i->with_creds = !!creds)) i->creds = *creds; #endif @@ -294,7 +295,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa i->channel = channel; i->offset = offset; i->seek_mode = seek_mode; -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS i->with_creds = 0; #endif @@ -334,7 +335,7 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = htonl(p->write.current->seek_mode); } -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS if ((p->send_creds_now = p->write.current->with_creds)) p->write_creds = p->write.current->creds; @@ -364,7 +365,7 @@ static int do_write(pa_pstream *p) { l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS if (p->send_creds_now) { if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0) @@ -406,7 +407,7 @@ static int do_read(pa_pstream *p) { l = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE); } -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS { int b = 0; @@ -495,7 +496,7 @@ static int do_read(pa_pstream *p) { assert(p->read.packet); if (p->recieve_packet_callback) -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS p->recieve_packet_callback(p, p->read.packet, p->read_creds_valid ? &p->read_creds : NULL, p->recieve_packet_callback_userdata); #else p->recieve_packet_callback(p, p->read.packet, NULL, p->recieve_packet_callback_userdata); @@ -506,7 +507,7 @@ static int do_read(pa_pstream *p) { } p->read.index = 0; -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS p->read_creds_valid = 0; #endif } diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h index 39cb75919..789e40bc2 100644 --- a/src/pulsecore/pstream.h +++ b/src/pulsecore/pstream.h @@ -26,16 +26,16 @@ #include #include + #include #include #include #include - -struct ucred; +#include typedef struct pa_pstream pa_pstream; -typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata); +typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata); typedef void (*pa_pstream_memblock_cb_t)(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata); typedef void (*pa_pstream_notify_cb_t)(pa_pstream *p, void *userdata); @@ -43,7 +43,7 @@ pa_pstream* pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta void pa_pstream_unref(pa_pstream*p); pa_pstream* pa_pstream_ref(pa_pstream*p); -void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const struct ucred *creds); +void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds); void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk); void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata); diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c index 77ea13e70..254835922 100644 --- a/src/pulsecore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef HAVE_SYS_SOCKET_H #include @@ -185,12 +186,18 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file sa.sun_path[sizeof(sa.sun_path) - 1] = 0; pa_socket_low_delay(fd); - + if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { pa_log(__FILE__": bind(): %s", pa_cstrerror(errno)); goto fail; } + /* Allow access from all clients. Sockets like this one should + * always be put inside a directory with proper access rights, + * because not all OS check the access rights on the socket + * inodes. */ + chmod(filename, 0777); + if (listen(fd, 5) < 0) { pa_log(__FILE__": listen(): %s", pa_cstrerror(errno)); goto fail; diff --git a/todo b/todo index 07d022b71..0173ccd92 100644 --- a/todo +++ b/todo @@ -3,7 +3,6 @@ Post 0.9.0: - alsa mmap driver - dbus/hal (Shams King is working on this one) -- polish for starting polypaudio as root/system-wide instance - chroot() - module-tunnel: improve latency calculation - multiline configuration statements @@ -32,6 +31,11 @@ Post 0.9.0: - gconf module + frontend - hooks for creating sink inputs - insert the low-level device name in the default sink/source name, to make them recognizable +- ssl +- key rings for auth +- challenge response auth +- sasl auth +- setrlimit Long term: - pass meta info for hearing impaired From 703bb49c91a53d03ec55a704d895f59bfbafd8b0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 23:16:02 +0000 Subject: [PATCH 1012/1514] add a few comments git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1110 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 0449cb943..cf655ee0b 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -158,6 +158,10 @@ static int change_user(void) { struct passwd *pw; struct group * gr; int r; + + /* This function is called only in system-wide mode. It creates a + * runtime dir in /var/run/ with proper UID/GID and drops privs + * afterwards. */ if (!(pw = getpwnam(PA_SYSTEM_USER))) { pa_log(__FILE__": Failed to find user '%s'.", PA_SYSTEM_USER); @@ -238,8 +242,12 @@ static int change_user(void) { static int create_runtime_dir(void) { char fn[PATH_MAX]; - + pa_runtime_path(NULL, fn, sizeof(fn)); + + /* This function is called only when the daemon is started in + * per-user mode. We create the runtime directory somewhere in + * /tmp/ with the current UID/GID */ if (pa_make_secure_dir(fn, 0700, getuid(), getgid()) < 0) { pa_log(__FILE__": Failed to create '%s': %s", fn, pa_cstrerror(errno)); From 2ad69389d4a584a1058474341ee959c6cfc070a2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 00:12:52 +0000 Subject: [PATCH 1013/1514] Remove unneeded headers. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1111 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/creds.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h index a95f4480f..a2acae04b 100644 --- a/src/pulsecore/creds.h +++ b/src/pulsecore/creds.h @@ -23,8 +23,6 @@ ***/ #include -#include -#include typedef struct pa_creds pa_creds; From 7ba93ebae21742522bfe430e229a859370a888d1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 00:13:12 +0000 Subject: [PATCH 1014/1514] Protect platform dependent headers with ifdefs. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1112 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 5 +++-- src/pulsecore/pstream.c | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index 0150204cb..efc1685bf 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -33,8 +33,6 @@ #include #include #include -#include -#include #ifdef HAVE_SYS_WAIT_H #include @@ -43,6 +41,9 @@ #ifdef HAVE_SYS_SOCKET_H #include #endif +#ifdef HAVE_SYS_UN_H +#include +#endif #ifdef HAVE_NETDB_H #include #endif diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index de5fa43e6..7096d65af 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -27,9 +27,13 @@ #include #include #include -#include -#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_UN_H +#include +#endif #ifdef HAVE_NETINET_IN_H #include #endif From a3e7595ac179ca32bc5c876b25a4e80171c3d917 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 00:21:50 +0000 Subject: [PATCH 1015/1514] Make -1 mean "current group/user" so that some platform dependent calls can be centralised. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1113 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 2 +- src/modules/module-protocol-stub.c | 2 +- src/pulse/context.c | 2 +- src/pulsecore/core-util.c | 4 ++++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index cf655ee0b..948b20551 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -249,7 +249,7 @@ static int create_runtime_dir(void) { * per-user mode. We create the runtime directory somewhere in * /tmp/ with the current UID/GID */ - if (pa_make_secure_dir(fn, 0700, getuid(), getgid()) < 0) { + if (pa_make_secure_dir(fn, 0700, (uid_t)-1, (gid_t)-1) < 0) { pa_log(__FILE__": Failed to create '%s': %s", fn, pa_cstrerror(errno)); return -1; } diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index ecbc5676c..36d7db895 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -254,7 +254,7 @@ int pa__init(pa_core *c, pa_module*m) { /* This socket doesn't reside in our own runtime dir but in * /tmp/.esd/, hence we have to create the dir first */ - if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, getuid(), getgid()) < 0) { + if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) { pa_log(__FILE__": Failed to create socket directory: %s\n", pa_cstrerror(errno)); goto fail; } diff --git a/src/pulse/context.c b/src/pulse/context.c index efc1685bf..30a257fe6 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -707,7 +707,7 @@ int pa_context_connect( char lf[PATH_MAX]; pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); - pa_make_secure_parent_dir(lf, 0700, getuid(), getgid()); + pa_make_secure_parent_dir(lf, 0700, (uid_t)-1, (gid_t)-1); assert(c->autospawn_lock_fd <= 0); c->autospawn_lock_fd = pa_lock_lockfile(lf); diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 0e6501b8f..595ef939f 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -157,6 +157,10 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { return -1; #ifdef HAVE_CHOWN + if (uid == (uid_t)-1) + uid = getuid(); + if (gid == (gid_t)-1) + gid = getgid(); chown(dir, uid, gid); #endif From 246e30aec74c76fd7db53f4c537a4c90b87d5ea4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 00:28:18 +0000 Subject: [PATCH 1016/1514] Add missing header. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1114 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/daemon/main.c b/src/daemon/main.c index 948b20551..63452f6f5 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -55,6 +55,7 @@ #include #include +#include #include #include From 0ff247db7303d7c452d62bcfc1291075f297dcbd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 00:52:44 +0000 Subject: [PATCH 1017/1514] undo r1111 in some way: include sys/socket.h and sys/un.h but wrap it in #ifdef HAVE_xxx_H. This should be safe because config.h should be the first included header in all .c files and creds.h is never included by any external tools git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1115 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/creds.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h index a2acae04b..d92ce5989 100644 --- a/src/pulsecore/creds.h +++ b/src/pulsecore/creds.h @@ -24,6 +24,16 @@ #include +/* config.h must be included before this file */ + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_SYS_UN_H +#include +#endif + typedef struct pa_creds pa_creds; #if defined(SCM_CREDENTIALS) From 2409f1a80b708ead6c48ebbb568bd2b7d6d3af31 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 01:25:37 +0000 Subject: [PATCH 1018/1514] add support to set resource limits for the daemon and set some of them to some sane values git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1116 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 84 +++++++++++++++++++++++++++++++++++++++ src/daemon/daemon-conf.h | 22 ++++++++++ src/daemon/daemon.conf.in | 10 +++++ src/daemon/main.c | 37 ++++++++++++++++- todo | 2 +- 5 files changed, 153 insertions(+), 2 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 2577578cc..12ee08001 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -73,6 +73,20 @@ static const pa_daemon_conf default_conf = { .config_file = NULL, .use_pid_file = 1, .system_instance = 0 +#ifdef HAVE_SYS_RESOURCE_H + , .rlimit_as = { .value = 0, .is_set = 0 }, + .rlimit_core = { .value = 0, .is_set = 0 }, + .rlimit_data = { .value = 0, .is_set = 0 }, + .rlimit_fsize = { .value = 0, .is_set = 0 }, + .rlimit_nofile = { .value = 25, .is_set = 1 }, + .rlimit_stack = { .value = 0, .is_set = 0 } +#ifdef RLIMIT_NPROC + , .rlimit_nproc = { .value = 0, .is_set = 0 } +#endif +#ifdef RLIMIT_MEMLOCK + , .rlimit_memlock = { .value = 0, .is_set = 1 } +#endif +#endif }; pa_daemon_conf* pa_daemon_conf_new(void) { @@ -184,6 +198,30 @@ static int parse_resample_method(const char *filename, unsigned line, const char return 0; } +static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_rlimit *r = data; + assert(filename); + assert(lvalue); + assert(rvalue); + assert(r); + + if (rvalue[strspn(rvalue, "\t ")] == 0) { + /* Empty string */ + r->is_set = 0; + r->value = 0; + } else { + int32_t k; + if (pa_atoi(rvalue, &k) < 0) { + pa_log(__FILE__": [%s:%u] Inavalid rlimit '%s'.", filename, line, rvalue); + return -1; + } + r->is_set = k >= 0; + r->value = k >= 0 ? (rlim_t) k : 0; + } + + return 0; +} + int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { int r = -1; FILE *f = NULL; @@ -204,6 +242,20 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "resample-method", parse_resample_method, NULL }, { "use-pid-file", pa_config_parse_bool, NULL }, { "system-instance", pa_config_parse_bool, NULL }, +#ifdef HAVE_SYS_RESOURCE_H + { "rlimit-as", parse_rlimit, NULL }, + { "rlimit-core", parse_rlimit, NULL }, + { "rlimit-data", parse_rlimit, NULL }, + { "rlimit-fsize", parse_rlimit, NULL }, + { "rlimit-nofile", parse_rlimit, NULL }, + { "rlimit-stack", parse_rlimit, NULL }, +#ifdef RLIMIT_NPROC + { "rlimit-nproc", parse_rlimit, NULL }, +#endif +#ifdef RLIMIT_MEMLOCK + { "rlimit-memlock", parse_rlimit, NULL }, +#endif +#endif { NULL, NULL, NULL }, }; @@ -222,6 +274,24 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[12].data = c; table[13].data = &c->use_pid_file; table[14].data = &c->system_instance; +#ifdef HAVE_SYS_RESOURCE_H + table[15].data = &c->rlimit_as; + table[16].data = &c->rlimit_core; + table[17].data = &c->rlimit_data; + table[18].data = &c->rlimit_fsize; + table[19].data = &c->rlimit_nofile; + table[20].data = &c->rlimit_stack; +#ifdef RLIMIT_NPROC + table[21].data = &c->rlimit_nproc; +#endif +#ifdef RLIMIT_MEMLOCK +#ifndef RLIMIT_NPROC +#error "Houston, we have a numbering problem!" +#endif + table[22].data = &c->rlimit_memlock; +#endif +#endif + pa_xfree(c->config_file); c->config_file = NULL; @@ -289,6 +359,20 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file); pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance); +#ifdef HAVE_SYS_RESOURCE_H + pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1); + pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1); + pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1); + pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1); + pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1); + pa_strbuf_printf(s, "rlimit-stack = %li\n", c->rlimit_stack.is_set ? (long int) c->rlimit_stack.value : -1); +#ifdef RLIMIT_NPROC + pa_strbuf_printf(s, "rlimit-nproc = %li\n", c->rlimit_nproc.is_set ? (long int) c->rlimit_nproc.value : -1); +#endif +#ifdef RLIMIT_MEMLOCK + pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1); +#endif +#endif return pa_strbuf_tostring_free(s); } diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index bfea73583..a09773f14 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -24,6 +24,10 @@ #include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + /* The actual command to execute */ typedef enum pa_daemon_conf_cmd { PA_CMD_DAEMON, /* the default */ @@ -35,6 +39,13 @@ typedef enum pa_daemon_conf_cmd { PA_CMD_CHECK } pa_daemon_conf_cmd_t; +#ifdef HAVE_SYS_RESOURCE_H +typedef struct pa_rlimit { + rlim_t value; + int is_set; +} pa_rlimit; +#endif + /* A structure containing configuration data for the PulseAudio server . */ typedef struct pa_daemon_conf { pa_daemon_conf_cmd_t cmd; @@ -53,6 +64,17 @@ typedef struct pa_daemon_conf { pa_log_level_t log_level; int resample_method; char *config_file; + +#ifdef HAVE_SYS_RESOURCE_H + pa_rlimit rlimit_as, rlimit_core, rlimit_data, rlimit_fsize, rlimit_nofile, rlimit_stack; +#ifdef RLIMIT_NPROC + pa_rlimit rlimit_nproc; +#endif +#ifdef RLIMIT_MEMLOCK + pa_rlimit rlimit_memlock; +#endif +#endif + } pa_daemon_conf; /* Allocate a new structure and fill it with sane defaults */ diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 30628969e..787405f8f 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -81,3 +81,13 @@ ## Run the daemon as system-wide instance, requires root priviliges ; system-instance = 0 + +## Resource limits, see getrlimit(2) for more information +; rlimit-as = -1 +; rlimit-core = -1 +; rlimit-data = -1 +; rlimit-fsize = -1 +; rlimit-nofile = 25 +; rlimit-stack = -1 +; rlimit-nproc = -1 +; rlimit-memlock = 25 diff --git a/src/daemon/main.c b/src/daemon/main.c index 63452f6f5..517d99845 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -258,6 +258,37 @@ static int create_runtime_dir(void) { return 0; } +#ifdef HAVE_SYS_RESOURCE_H + +static void set_one_rlimit(const pa_rlimit *r, int resource, const char *name) { + struct rlimit rl; + assert(r); + + if (!r->is_set) + return; + + rl.rlim_cur = rl.rlim_max = r->value; + + if (setrlimit(resource, &rl) < 0) + pa_log_warn(__FILE__": setrlimit(%s, (%u, %u)) failed: %s", name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno)); +} + +static void set_all_rlimits(const pa_daemon_conf *conf) { + set_one_rlimit(&conf->rlimit_as, RLIMIT_AS, "RLIMIT_AS"); + set_one_rlimit(&conf->rlimit_core, RLIMIT_CORE, "RLIMIT_CORE"); + set_one_rlimit(&conf->rlimit_data, RLIMIT_DATA, "RLIMIT_DATA"); + set_one_rlimit(&conf->rlimit_fsize, RLIMIT_FSIZE, "RLIMIT_FSIZE"); + set_one_rlimit(&conf->rlimit_nofile, RLIMIT_NOFILE, "RLIMIT_NOFILE"); + set_one_rlimit(&conf->rlimit_stack, RLIMIT_STACK, "RLIMIT_STACK"); +#ifdef RLIMIT_NPROC + set_one_rlimit(&conf->rlimit_nproc, RLIMIT_NPROC, "RLIMIT_NPROC"); +#endif +#ifdef RLIMIT_MEMLOCK + set_one_rlimit(&conf->rlimit_memlock, RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK"); +#endif +} +#endif + int main(int argc, char *argv[]) { pa_core *c; pa_strbuf *buf = NULL; @@ -335,7 +366,7 @@ int main(int argc, char *argv[]) { if (suid_root) pa_drop_root(); - + if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); @@ -502,6 +533,10 @@ int main(int argc, char *argv[]) { valid_pid_file = 1; } +#ifdef HAVE_SYS_RESOURCE_H + set_all_rlimits(conf); +#endif + #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif diff --git a/todo b/todo index 0173ccd92..cdc973733 100644 --- a/todo +++ b/todo @@ -35,7 +35,7 @@ Post 0.9.0: - key rings for auth - challenge response auth - sasl auth -- setrlimit +- IP ACLs Long term: - pass meta info for hearing impaired From b12f29d04ba9fcaa6930d52b13880086693c0faa Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 13:07:01 +0000 Subject: [PATCH 1019/1514] Make sure parse_rlimit is only used when rlimits are supported. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1117 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 12ee08001..7184b2e60 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -199,7 +199,8 @@ static int parse_resample_method(const char *filename, unsigned line, const char } static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { - pa_rlimit *r = data; +#ifdef HAVE_SYS_RESOURCE_H + struct pa_rlimit *r = data; assert(filename); assert(lvalue); assert(rvalue); @@ -218,6 +219,9 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, r->is_set = k >= 0; r->value = k >= 0 ? (rlim_t) k : 0; } +#else + pa_log_warning(__FILE__": [%s:%u] rlimit not supported on this platform.", filename, line); +#endif return 0; } From 8d2dc9c4d14fd879aac3e4137b1dfc2c32a338cb Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 13:16:23 +0000 Subject: [PATCH 1020/1514] Handle user switch in a more platform independent manner. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1118 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 517d99845..8b905b310 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -37,8 +37,6 @@ #include #include #include -#include -#include #include @@ -46,6 +44,13 @@ #include #endif +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif + #ifdef HAVE_LIBWRAP #include #include @@ -155,6 +160,8 @@ static void close_pipe(int p[2]) { #define set_env(key, value) putenv(pa_sprintf_malloc("%s=%s", (key), (value))) +#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H) + static int change_user(void) { struct passwd *pw; struct group * gr; @@ -241,6 +248,15 @@ static int change_user(void) { return 0; } +#else /* HAVE_PWD_H && HAVE_GRP_H */ + +static int change_user(void) { + pa_log(__FILE__": System wide mode unsupported on this platform."); + return -1; +} + +#endif /* HAVE_PWD_H && HAVE_GRP_H */ + static int create_runtime_dir(void) { char fn[PATH_MAX]; From 57d8a315ea3c3e4e19e19fe1d293ca941d6229d5 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 13:19:16 +0000 Subject: [PATCH 1021/1514] Move check for SUID into the caps functions. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1119 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/caps.c | 9 +++++++++ src/daemon/main.c | 6 ++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/daemon/caps.c b/src/daemon/caps.c index dc74bc7d0..957824d98 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -27,6 +27,7 @@ #include #include #include +#include #ifdef HAVE_SYS_CAPABILITY_H #include @@ -80,6 +81,10 @@ int pa_limit_caps(void) { cap_t caps; cap_value_t nice_cap = CAP_SYS_NICE; + /* Only drop caps when called SUID */ + if (getuid() != 0) + return 0; + caps = cap_init(); assert(caps); @@ -106,6 +111,10 @@ int pa_drop_caps(void) { cap_t caps; int r = -1; + /* Only drop caps when called SUID */ + if (getuid() != 0) + return 0; + caps = cap_init(); assert(caps); diff --git a/src/daemon/main.c b/src/daemon/main.c index 8b905b310..3f4899815 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -328,8 +328,7 @@ int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); - if (getuid() != 0) - pa_limit_caps(); + pa_limit_caps(); #ifdef HAVE_GETUID suid_root = getuid() != 0 && geteuid() == 0; @@ -377,8 +376,7 @@ int main(int argc, char *argv[]) { if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) pa_raise_priority(); - if (getuid() != 0) - pa_drop_caps(); + pa_drop_caps(); if (suid_root) pa_drop_root(); From f3d49244731498c009b5c1991cb7242a8e9914ae Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 13:24:04 +0000 Subject: [PATCH 1022/1514] Centralise check if we're running as root. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1120 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 3f4899815..14c16ab22 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -314,7 +314,7 @@ int main(int argc, char *argv[]) { char *s; int r, retval = 1, d = 0; int daemon_pipe[2] = { -1, -1 }; - int suid_root; + int suid_root, real_root; int valid_pid_file = 0; #ifdef HAVE_GETUID @@ -331,13 +331,15 @@ int main(int argc, char *argv[]) { pa_limit_caps(); #ifdef HAVE_GETUID - suid_root = getuid() != 0 && geteuid() == 0; + real_root = getuid() == 0; + suid_root = !real_root && geteuid() == 0; if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) { pa_log_warn(__FILE__": WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'."); pa_drop_root(); } #else + real_root = 0; suid_root = 0; #endif @@ -434,10 +436,10 @@ int main(int argc, char *argv[]) { assert(conf->cmd == PA_CMD_DAEMON); } - if (getuid() == 0 && !conf->system_instance) { + if (real_root && !conf->system_instance) { pa_log(__FILE__": This program is not intended to be run as root (unless --system is specified)."); goto finish; - } else if (getuid() != 0 && conf->system_instance) { + } else if (!real_root && conf->system_instance) { pa_log(__FILE__": Root priviliges required."); goto finish; } From 0762af2aeed6f590bf5833128185adf902eac0cf Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 13:24:57 +0000 Subject: [PATCH 1023/1514] Only warn when running as root and not --system. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1121 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 14c16ab22..d578f508b 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -437,8 +437,7 @@ int main(int argc, char *argv[]) { } if (real_root && !conf->system_instance) { - pa_log(__FILE__": This program is not intended to be run as root (unless --system is specified)."); - goto finish; + pa_log_warning(__FILE__": This program is not intended to be run as root (unless --system is specified)."); } else if (!real_root && conf->system_instance) { pa_log(__FILE__": Root priviliges required."); goto finish; From 4a59581a4c95c94d97abc7844a097a356c937f0e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 13:28:50 +0000 Subject: [PATCH 1024/1514] Fix incorrect call to nonexistant pa_log_warning(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1122 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 2 +- src/daemon/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 7184b2e60..894c0434b 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -220,7 +220,7 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, r->value = k >= 0 ? (rlim_t) k : 0; } #else - pa_log_warning(__FILE__": [%s:%u] rlimit not supported on this platform.", filename, line); + pa_log_warn(__FILE__": [%s:%u] rlimit not supported on this platform.", filename, line); #endif return 0; diff --git a/src/daemon/main.c b/src/daemon/main.c index d578f508b..3ced3bf6d 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -437,7 +437,7 @@ int main(int argc, char *argv[]) { } if (real_root && !conf->system_instance) { - pa_log_warning(__FILE__": This program is not intended to be run as root (unless --system is specified)."); + pa_log_warn(__FILE__": This program is not intended to be run as root (unless --system is specified)."); } else if (!real_root && conf->system_instance) { pa_log(__FILE__": Root priviliges required."); goto finish; From 30ada90fd2bce05097a85da86a10ffb52c2ffd35 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 16:48:26 +0000 Subject: [PATCH 1025/1514] add IP address ACL subsystem git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1123 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 14 ++- src/pulsecore/ipacl.c | 216 +++++++++++++++++++++++++++++++++++++++++ src/pulsecore/ipacl.h | 31 ++++++ src/tests/ipacl-test.c | 117 ++++++++++++++++++++++ 4 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 src/pulsecore/ipacl.c create mode 100644 src/pulsecore/ipacl.h create mode 100644 src/tests/ipacl-test.c diff --git a/src/Makefile.am b/src/Makefile.am index d4fbe5288..431bedbd2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -194,7 +194,8 @@ noinst_PROGRAMS = \ channelmap-test \ thread-mainloop-test \ utf8-test \ - get-binary-name-test + get-binary-name-test \ + ipacl-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -227,6 +228,11 @@ get_binary_name_test_CFLAGS = $(AM_CFLAGS) get_binary_name_test_LDADD = $(AM_LDADD) libpulse.la get_binary_name_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +ipacl_test_SOURCES = tests/ipacl-test.c pulsecore/ipacl.c pulsecore/ipacl.h +ipacl_test_CFLAGS = $(AM_CFLAGS) +ipacl_test_LDADD = $(AM_LDADD) libpulsecore.la +ipacl_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la @@ -586,6 +592,7 @@ pulsecoreinclude_HEADERS += \ pulsecore/socket-util.h \ pulsecore/iochannel.h \ pulsecore/socket-server.h \ + pulsecore/ipacl.h \ pulsecore/socket-client.h \ pulsecore/parseaddr.h \ pulsecore/packet.h \ @@ -615,6 +622,7 @@ modlibexec_LTLIBRARIES = \ libsocket-util.la \ libiochannel.la \ libsocket-server.la \ + libipacl.la \ libparseaddr.la \ libsocket-client.la \ libpacket.la \ @@ -668,6 +676,10 @@ libsocket_server_la_SOURCES = \ libsocket_server_la_LDFLAGS = -avoid-version libsocket_server_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS) +libipacl_la_SOURCES = pulsecore/ipacl.h pulsecore/ipacl.c +libipacl_la_LDFLAGS = -avoid-version +libipacl_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(WINSOCK_LIBS) + libsocket_client_la_SOURCES = pulsecore/socket-client.c pulsecore/socket-client.h libsocket_client_la_LDFLAGS = -avoid-version libsocket_client_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS) $(WINSOCK_LIBS) diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c new file mode 100644 index 000000000..06be0a287 --- /dev/null +++ b/src/pulsecore/ipacl.c @@ -0,0 +1,216 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ipacl.h" + +struct acl_entry { + PA_LLIST_FIELDS(struct acl_entry); + int family; + struct in_addr address_ipv4; + struct in6_addr address_ipv6; + int bits; +}; + +struct pa_ip_acl { + PA_LLIST_HEAD(struct acl_entry, entries); +}; + +pa_ip_acl* pa_ip_acl_new(const char *s) { + const char *state = NULL; + char *a; + pa_ip_acl *acl; + + assert(s); + + acl = pa_xnew(pa_ip_acl, 1); + PA_LLIST_HEAD_INIT(struct acl_entry, acl->entries); + + while ((a = pa_split(s, ";", &state))) { + char *slash; + struct acl_entry e, *n; + uint32_t bits; + + if ((slash = strchr(a, '/'))) { + *slash = 0; + slash++; + if (pa_atou(slash, &bits) < 0) { + pa_log(__FILE__": failed to parse number of bits: %s", slash); + goto fail; + } + } else + bits = (uint32_t) -1; + + if (inet_pton(AF_INET, a, &e.address_ipv4) > 0) { + + e.bits = bits == (uint32_t) -1 ? 32 : (int) bits; + + if (e.bits > 32) { + pa_log(__FILE__": number of bits out of range: %i", e.bits); + goto fail; + } + + e.family = AF_INET; + + if (e.bits < 32 && (uint32_t) (ntohl(e.address_ipv4.s_addr) << e.bits) != 0) + pa_log_warn(__FILE__": WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); + + } else if (inet_pton(AF_INET6, a, &e.address_ipv6) > 0) { + + e.bits = bits == (uint32_t) -1 ? 128 : (int) bits; + + if (e.bits > 128) { + pa_log(__FILE__": number of bits out of range: %i", e.bits); + goto fail; + } + e.family = AF_INET6; + + if (e.bits < 128) { + int t = 0, i; + + for (i = 0, bits = e.bits; i < 16; i++) { + + if (bits >= 8) + bits -= 8; + else { + if ((uint8_t) ((e.address_ipv6.s6_addr[i]) << bits) != 0) { + t = 1; + break; + } + bits = 0; + } + } + + if (t) + pa_log_warn(__FILE__": WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); + } + + } else { + pa_log(__FILE__": failed to parse address: %s", a); + goto fail; + } + + n = pa_xmemdup(&e, sizeof(struct acl_entry)); + PA_LLIST_PREPEND(struct acl_entry, acl->entries, n); + + pa_xfree(a); + } + + return acl; + +fail: + pa_xfree(a); + pa_ip_acl_free(acl); + + return NULL; +} + +void pa_ip_acl_free(pa_ip_acl *acl) { + assert(acl); + + while (acl->entries) { + struct acl_entry *e = acl->entries; + PA_LLIST_REMOVE(struct acl_entry, acl->entries, e); + pa_xfree(e); + } + + pa_xfree(acl); +} + +int pa_ip_acl_check(pa_ip_acl *acl, int fd) { + struct sockaddr_storage sa; + struct acl_entry *e; + socklen_t salen; + + assert(acl); + assert(fd >= 0); + + salen = sizeof(sa); + if (getpeername(fd, (struct sockaddr*) &sa, &salen) < 0) + return -1; + + if (sa.ss_family != AF_INET && sa.ss_family != AF_INET6) + return -1; + + if (sa.ss_family == AF_INET && salen != sizeof(struct sockaddr_in)) + return -1; + + if (sa.ss_family == AF_INET6 && salen != sizeof(struct sockaddr_in6)) + return -1; + + for (e = acl->entries; e; e = e->next) { + + if (e->family != sa.ss_family) + continue; + + if (e->family == AF_INET) { + struct sockaddr_in *sai = (struct sockaddr_in*) &sa; + + if (e->bits == 0 || /* this needs special handling because >> takes the right-hand side modulo 32 */ + (ntohl(sai->sin_addr.s_addr ^ e->address_ipv4.s_addr) >> (32 - e->bits)) == 0) + return 1; + } else if (e->family == AF_INET6) { + int i, bits ; + struct sockaddr_in6 *sai = (struct sockaddr_in6*) &sa; + + if (e->bits == 128) + return memcmp(&sai->sin6_addr, &e->address_ipv6, 16) == 0; + + if (e->bits == 0) + return 1; + + for (i = 0, bits = e->bits; i < 16; i++) { + + if (bits >= 8) { + if (sai->sin6_addr.s6_addr[i] != e->address_ipv6.s6_addr[i]) + break; + + bits -= 8; + } else { + if ((sai->sin6_addr.s6_addr[i] ^ e->address_ipv6.s6_addr[i]) >> (8 - bits) != 0) + break; + + bits = 0; + } + + if (bits == 0) + return 1; + } + } + } + + return 0; +} diff --git a/src/pulsecore/ipacl.h b/src/pulsecore/ipacl.h new file mode 100644 index 000000000..7a4540ce9 --- /dev/null +++ b/src/pulsecore/ipacl.h @@ -0,0 +1,31 @@ +#ifndef fooparseaddrhfoo +#define fooparseaddrhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +typedef struct pa_ip_acl pa_ip_acl; + +pa_ip_acl* pa_ip_acl_new(const char *s); +void pa_ip_acl_free(pa_ip_acl *acl); +int pa_ip_acl_check(pa_ip_acl *acl, int fd); + +#endif diff --git a/src/tests/ipacl-test.c b/src/tests/ipacl-test.c new file mode 100644 index 000000000..b98151eea --- /dev/null +++ b/src/tests/ipacl-test.c @@ -0,0 +1,117 @@ +/* $Id$ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int main(int argc, char *argv[]) { + struct sockaddr_in sa; + struct sockaddr_in6 sa6; + int fd; + int r; + pa_ip_acl *acl; + + fd = socket(PF_INET, SOCK_STREAM, 0); + assert(fd >= 0); + + sa.sin_family = AF_INET; + sa.sin_port = htons(22); + sa.sin_addr.s_addr = inet_addr("127.0.0.1"); + + r = connect(fd, (struct sockaddr*) &sa, sizeof(sa)); + assert(r >= 0); + + acl = pa_ip_acl_new("127.0.0.1"); + assert(acl); + printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("127.0.0.2/0"); + assert(acl); + printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("127.0.0.1/32"); + assert(acl); + printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("127.0.0.1/7"); + assert(acl); + printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("127.0.0.2"); + assert(acl); + printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("127.0.0.0/8;0.0.0.0/32"); + assert(acl); + printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("128.0.0.2/9"); + assert(acl); + printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("::1/9"); + assert(acl); + printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + close(fd); + + fd = socket(PF_INET6, SOCK_STREAM, 0); + assert(fd >= 0); + + memset(&sa6, 0, sizeof(sa6)); + sa6.sin6_family = AF_INET6; + sa6.sin6_port = htons(22); + inet_pton(AF_INET6, "::1", &sa6.sin6_addr); + + r = connect(fd, (struct sockaddr*) &sa6, sizeof(sa6)); + assert(r >= 0); + + acl = pa_ip_acl_new("::1"); + assert(acl); + printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("::1/9"); + assert(acl); + printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("::/0"); + assert(acl); + printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("::2/128"); + assert(acl); + printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("::2/127"); + assert(acl); + printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + acl = pa_ip_acl_new("::2/126"); + assert(acl); + printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd)); + pa_ip_acl_free(acl); + + close(fd); + + return 0; +} From db75f68854b03a4fb8884616d085f48b9fc4d001 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 16:56:06 +0000 Subject: [PATCH 1026/1514] actually ship src/pulsecore/creds.h in the tarballs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1124 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 431bedbd2..ec1678c72 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -405,7 +405,7 @@ libpulse_la_SOURCES += \ pulsecore/strlist.c pulsecore/strlist.h \ pulsecore/tagstruct.c pulsecore/tagstruct.h \ pulsecore/core-error.c pulsecore/core-error.h \ - pulsecore/winsock.h + pulsecore/winsock.h pulsecore/creds.h if OS_IS_WIN32 libpulse_la_SOURCES += \ @@ -508,7 +508,8 @@ pulsecoreinclude_HEADERS = \ pulsecore/source.h \ pulsecore/source-output.h \ pulsecore/strbuf.h \ - pulsecore/tokenizer.h + pulsecore/tokenizer.h \ + pulsecore/creds.h lib_LTLIBRARIES += libpulsecore.la From 44beeaa648a1d434692721dd65a04ecb3f75dace Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 18:43:20 +0000 Subject: [PATCH 1027/1514] implement "auth-ip-acl=" in the native and esound protocols git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1125 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 ++-- src/modules/module-protocol-stub.c | 17 ++++++++++-- src/pulsecore/iochannel.c | 6 ++++ src/pulsecore/iochannel.h | 2 ++ src/pulsecore/protocol-esound.c | 41 +++++++++++++++++++++++----- src/pulsecore/protocol-native.c | 44 ++++++++++++++++++++++++------ 6 files changed, 96 insertions(+), 20 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index ec1678c72..428e45210 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -513,7 +513,7 @@ pulsecoreinclude_HEADERS = \ lib_LTLIBRARIES += libpulsecore.la -# Some public stuff is used even in the core. +# Some public stuff is used even in the core libpulsecore_la_SOURCES = \ pulse/channelmap.c pulse/channelmap.h \ pulse/error.c pulse/error.h \ @@ -733,7 +733,7 @@ libprotocol_http_la_LIBADD = $(AM_LIBADD) libsocket-server.la libioline.la libpu libprotocol_native_la_SOURCES = pulsecore/protocol-native.c pulsecore/protocol-native.h pulsecore/native-common.h libprotocol_native_la_LDFLAGS = -avoid-version -libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la libpulsecore.la libiochannel.la +libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la libpulsecore.la libiochannel.la libipacl.la libtagstruct_la_SOURCES = pulsecore/tagstruct.c pulsecore/tagstruct.h libtagstruct_la_LDFLAGS = -avoid-version @@ -741,7 +741,7 @@ libtagstruct_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(WINSOCK_LIBS) libprotocol_esound_la_SOURCES = pulsecore/protocol-esound.c pulsecore/protocol-esound.h pulsecore/esound.h libprotocol_esound_la_LDFLAGS = -avoid-version -libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la libpulsecore.la +libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la libpulsecore.la libipacl.la libauthkey_la_SOURCES = pulsecore/authkey.c pulsecore/authkey.h libauthkey_la_LDFLAGS = -avoid-version diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 36d7db895..d1f5fa158 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -129,8 +129,11 @@ #endif #if defined(HAVE_CREDS) && !defined(USE_TCP_SOCKETS) - #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable=" + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable", #define AUTH_USAGE "auth-group= auth-group-enable= " + #elif defined(USE_TCP_SOCKETS) + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl", + #define AUTH_USAGE "auth-ip-acl= " #else #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON #define AUTH_USAGE @@ -149,17 +152,27 @@ #define TCPWRAP_SERVICE "esound" #define IPV4_PORT ESD_DEFAULT_PORT #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME - #define MODULE_ARGUMENTS "sink", "source", "auth-anonymous", "cookie", + #define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", #ifdef USE_TCP_SOCKETS #include "module-esound-protocol-tcp-symdef.h" #else #include "module-esound-protocol-unix-symdef.h" #endif + + #if defined(USE_TCP_SOCKETS) + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl", + #define AUTH_USAGE "auth-ip-acl= " + #else + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON + #define AUTH_USAGE + #endif + PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("sink= " "source= " "auth-anonymous= " "cookie= " + AUTH_USAGE SOCKET_USAGE) #else #error "Broken build system" diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index b50293bff..af732c26c 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -408,3 +408,9 @@ pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io) { return io->mainloop; } + +int pa_iochannel_get_recv_fd(pa_iochannel *io) { + assert(io); + + return io->ifd; +} diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h index 1f9ab0d44..0e6d6d3af 100644 --- a/src/pulsecore/iochannel.h +++ b/src/pulsecore/iochannel.h @@ -79,4 +79,6 @@ int pa_iochannel_socket_set_sndbuf(pa_iochannel*io, size_t l); pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io); +int pa_iochannel_get_recv_fd(pa_iochannel *io); + #endif diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 5daa32fef..0fa2c7f1f 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "endianmacros.h" @@ -116,6 +117,7 @@ struct pa_protocol_esound { char *sink_name, *source_name; unsigned n_player; uint8_t esd_key[ESD_KEY_LEN]; + pa_ip_acl *auth_ip_acl; }; typedef struct proto_handler { @@ -1162,7 +1164,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->client->kill = client_kill_cb; c->client->userdata = c; - c->authorized = p->public; + c->authorized = !!p->public; c->swap_byte_order = 0; c->dead = 0; @@ -1191,6 +1193,11 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->original_name = NULL; + if (!c->authorized && p->auth_ip_acl && pa_ip_acl_check(p->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) { + pa_log_info(__FILE__": Client authenticated by IP ACL."); + c->authorized = 1; + } + if (!c->authorized) { struct timeval tv; pa_gettimeofday(&tv); @@ -1211,20 +1218,32 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *server, pa_module *m, pa_modargs *ma) { pa_protocol_esound *p; int public = 0; - assert(core && server && ma); + const char *acl; + + assert(core); + assert(server); + assert(m); + assert(ma); p = pa_xnew(pa_protocol_esound, 1); if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) { pa_log(__FILE__": auth-anonymous= expects a boolean argument."); - return NULL; + goto fail; } - if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", DEFAULT_COOKIE_FILE), p->esd_key, sizeof(p->esd_key)) < 0) { - pa_xfree(p); - return NULL; - } + if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", DEFAULT_COOKIE_FILE), p->esd_key, sizeof(p->esd_key)) < 0) + goto fail; + if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) { + + if (!(p->auth_ip_acl = pa_ip_acl_new(acl))) { + pa_log(__FILE__": Failed to parse IP ACL '%s'", acl); + goto fail; + } + } else + p->auth_ip_acl = NULL; + p->module = m; p->public = public; p->server = server; @@ -1238,6 +1257,10 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve p->n_player = 0; return p; + +fail: + pa_xfree(p); + return NULL; } void pa_protocol_esound_free(pa_protocol_esound *p) { @@ -1249,5 +1272,9 @@ void pa_protocol_esound_free(pa_protocol_esound *p) { pa_idxset_free(p->connections, NULL, NULL); pa_socket_server_unref(p->server); + + if (p->auth_ip_acl) + pa_ip_acl_free(p->auth_ip_acl); + pa_xfree(p); } diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 2775d7745..f1959dd76 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -57,6 +57,7 @@ #include #include #include +#include #include "protocol-native.h" @@ -139,6 +140,7 @@ struct pa_protocol_native { #ifdef HAVE_CREDS char *auth_group; #endif + pa_ip_acl *auth_ip_acl; }; static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk); @@ -942,7 +944,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t } #endif - if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) == 0) + if (!success && memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) == 0) success = 1; if (!success) { @@ -2239,8 +2241,13 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo c = pa_xmalloc(sizeof(struct connection)); - c->authorized =!! p->public; + c->authorized = !!p->public; + if (!c->authorized && p->auth_ip_acl && pa_ip_acl_check(p->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) { + pa_log_info(__FILE__": Client authenticated by IP ACL."); + c->authorized = 1; + } + if (!c->authorized) { struct timeval tv; pa_gettimeofday(&tv); @@ -2319,7 +2326,10 @@ static int load_key(pa_protocol_native*p, const char*fn) { static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_modargs *ma) { pa_protocol_native *p; int public = 0; - assert(c && ma); + const char *acl; + + assert(c); + assert(ma); if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) { pa_log(__FILE__": auth-anonymous= expects a boolean argument."); @@ -2331,7 +2341,8 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo p->module = m; p->public = public; p->server = NULL; - + p->auth_ip_acl = NULL; + #ifdef HAVE_CREDS { int a = 1; @@ -2345,16 +2356,30 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo pa_log_info(__FILE__": Allowing access to group '%s'.", p->auth_group); } #endif - - if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0) { - pa_xfree(p); - return NULL; + + + if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) { + + if (!(p->auth_ip_acl = pa_ip_acl_new(acl))) { + pa_log(__FILE__": Failed to parse IP ACL '%s'", acl); + goto fail; + } } + if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0) + goto fail; + p->connections = pa_idxset_new(NULL, NULL); assert(p->connections); return p; + +fail: + pa_xfree(p->auth_group); + if (p->auth_ip_acl) + pa_ip_acl_free(p->auth_ip_acl); + pa_xfree(p); + return NULL; } pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) { @@ -2405,6 +2430,9 @@ void pa_protocol_native_free(pa_protocol_native *p) { if (p->auth_cookie_in_property) pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); + if (p->auth_ip_acl) + pa_ip_acl_free(p->auth_ip_acl); + #ifdef HAVE_CREDS pa_xfree(p->auth_group); #endif From dd5fd8d7036074480fd6ea28eb39644adc8531a2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 18:43:38 +0000 Subject: [PATCH 1028/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1126 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index cdc973733..9ea67dda3 100644 --- a/todo +++ b/todo @@ -35,7 +35,6 @@ Post 0.9.0: - key rings for auth - challenge response auth - sasl auth -- IP ACLs Long term: - pass meta info for hearing impaired From da1ec271bbc1907c32811cd61f41390a7d3ac1e8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 21:28:44 +0000 Subject: [PATCH 1029/1514] remove configurable client access group, since can never work on Linux anway, since SCM_CREDENTAILS doesn't allow sending supplementary GIDs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1127 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/client-conf.c | 5 ----- src/pulse/client-conf.h | 2 +- src/pulse/context.c | 5 ----- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 219175973..c3f58ec24 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -64,7 +64,6 @@ static const pa_client_conf default_conf = { .autospawn = 0, .cookie_file = NULL, .cookie_valid = 0, - .access_group = NULL }; pa_client_conf *pa_client_conf_new(void) { @@ -73,7 +72,6 @@ pa_client_conf *pa_client_conf_new(void) { c->daemon_binary = pa_xstrdup(PA_BINARY); c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5"); c->cookie_file = pa_xstrdup(PA_NATIVE_COOKIE_FILE); - c->access_group = pa_xstrdup(PA_ACCESS_GROUP); return c; } @@ -86,7 +84,6 @@ void pa_client_conf_free(pa_client_conf *c) { pa_xfree(c->default_source); pa_xfree(c->default_server); pa_xfree(c->cookie_file); - pa_xfree(c->access_group); pa_xfree(c); } int pa_client_conf_load(pa_client_conf *c, const char *filename) { @@ -103,7 +100,6 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { { "default-server", pa_config_parse_string, NULL }, { "autospawn", pa_config_parse_bool, NULL }, { "cookie-file", pa_config_parse_string, NULL }, - { "access-group", pa_config_parse_string, NULL }, { NULL, NULL, NULL }, }; @@ -114,7 +110,6 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { table[4].data = &c->default_server; table[5].data = &c->autospawn; table[6].data = &c->cookie_file; - table[7].data = &c->access_group; f = filename ? fopen((fn = pa_xstrdup(filename)), "r") : diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index dfb1148dc..a532f0dfe 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -27,7 +27,7 @@ /* A structure containing configuration data for PulseAudio clients. */ typedef struct pa_client_conf { - char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file, *access_group; + char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; int autospawn; uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; int cookie_valid; /* non-zero, when cookie is valid */ diff --git a/src/pulse/context.c b/src/pulse/context.c index 30a257fe6..34f517f0b 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -428,14 +428,9 @@ static void setup_context(pa_context *c, pa_iochannel *io) { #ifdef HAVE_CREDS { pa_creds ucred; - gid_t g; ucred.uid = getuid(); ucred.gid = getgid(); - - if ((g = pa_get_gid_of_group(c->conf->access_group)) != (gid_t) -1) - if (pa_check_in_group(g) > 0) - ucred.gid = g; pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } From b3d3d16bbeeee1067a27593908004f30b2e1b20e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 21:48:49 +0000 Subject: [PATCH 1030/1514] bump release and sonames git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1128 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index a7f85ea0e..746da4799 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_PREREQ(2.57) m4_define(PA_MAJOR, [0]) m4_define(PA_MINOR, [9]) -m4_define(PA_MICRO, [2]) +m4_define(PA_MICRO, [3]) AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) @@ -36,11 +36,11 @@ AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/]) AC_SUBST(PA_API_VERSION, 9) AC_SUBST(PA_PROTOCOL_VERSION, 9) -AC_SUBST(LIBPULSE_VERSION_INFO, [0:0:0]) -AC_SUBST(LIBPULSECORE_VERSION_INFO, [0:1:0]) +AC_SUBST(LIBPULSE_VERSION_INFO, [0:1:0]) +AC_SUBST(LIBPULSECORE_VERSION_INFO, [1:0:0]) AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:0:0]) -AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [0:0:0]) -AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:0:0]) +AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:0:1]) +AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:1:0]) if type -p stow > /dev/null && test -d /usr/local/stow ; then AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) From 2683f25b97420ceba7be99b9de03bc8f2eb4d3a9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 22:44:38 +0000 Subject: [PATCH 1031/1514] some more FreeBSD compat from Flameeyes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1129 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/ipacl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c index 06be0a287..ed5044ef2 100644 --- a/src/pulsecore/ipacl.c +++ b/src/pulsecore/ipacl.c @@ -23,8 +23,10 @@ #include #endif +#include #include #include +#include #include #include #include From 90b521d73e2a51f7b5df0bce1ee19d30bd0b087e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 22:46:41 +0000 Subject: [PATCH 1032/1514] add missing #ifdef HAVE_CREDS (thanks, Flameeyes) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1130 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-native.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index f1959dd76..9023adde2 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2375,7 +2375,9 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo return p; fail: +#ifdef HAVE_CREDS pa_xfree(p->auth_group); +#endif if (p->auth_ip_acl) pa_ip_acl_free(p->auth_ip_acl); pa_xfree(p); From 6ad1f33c3fdad0c9cbf78f722223b29fe3160ec6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 22:58:37 +0000 Subject: [PATCH 1033/1514] even more FreeBSD portability (thanks Flameeyes, again!) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1131 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/ipacl-test.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tests/ipacl-test.c b/src/tests/ipacl-test.c index b98151eea..8819a6a0f 100644 --- a/src/tests/ipacl-test.c +++ b/src/tests/ipacl-test.c @@ -1,7 +1,9 @@ /* $Id$ */ +#include #include #include +#include #include #include #include From 55e97b84c40f32506b1fcd0a96bac84b0ee134a6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 23:04:59 +0000 Subject: [PATCH 1034/1514] fix a few @@ replacments git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1132 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 428e45210..4669fbbe0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1181,17 +1181,17 @@ CLEANFILES = esdcompat client.conf default.pa daemon.conf esdcompat: daemon/esdcompat.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ - -e 's,@PA_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ + -e 's,@PA_BINARY\@,$(PA_BINARY),g' < $< > $@ client.conf: pulse/client.conf.in Makefile - sed -e 's,@PA_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ + sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' < $< > $@ if OS_IS_WIN32 default.pa: daemon/default.pa.win32 cp $< $@ else default.pa: daemon/default.pa.in Makefile - sed -e 's,@PA_BINARY\@,$(PULSEAUDIO_BINARY),g' < $< > $@ + sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' < $< > $@ endif daemon.conf: daemon/daemon.conf.in Makefile From 40b408990ae4d52df33a88508b02954a67b6841b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 23:12:18 +0000 Subject: [PATCH 1035/1514] remove access group setting from default client.conf git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1133 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/client.conf.in | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in index 3e0087661..c970be56f 100644 --- a/src/pulse/client.conf.in +++ b/src/pulse/client.conf.in @@ -40,6 +40,3 @@ ### Cookie file ; cookie-file = - -### Access group -; access-group = From 09e01afa1fa27b5148fa8eb7dc35bfd04cc3de68 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 23:21:57 +0000 Subject: [PATCH 1036/1514] Get ACL:s to work on Win32. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1134 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 7 +++++-- src/pulsecore/ipacl.c | 30 ++++++++++++++++++++++++------ src/tests/ipacl-test.c | 27 ++++++++++++++++++++++----- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 4669fbbe0..9eb957d57 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -228,7 +228,9 @@ get_binary_name_test_CFLAGS = $(AM_CFLAGS) get_binary_name_test_LDADD = $(AM_LDADD) libpulse.la get_binary_name_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -ipacl_test_SOURCES = tests/ipacl-test.c pulsecore/ipacl.c pulsecore/ipacl.h +ipacl_test_SOURCES = tests/ipacl-test.c \ + pulsecore/ipacl.c pulsecore/ipacl.h \ + pulsecore/inet_pton.c pulsecore/inet_pton.h ipacl_test_CFLAGS = $(AM_CFLAGS) ipacl_test_LDADD = $(AM_LDADD) libpulsecore.la ipacl_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -677,7 +679,8 @@ libsocket_server_la_SOURCES = \ libsocket_server_la_LDFLAGS = -avoid-version libsocket_server_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS) -libipacl_la_SOURCES = pulsecore/ipacl.h pulsecore/ipacl.c +libipacl_la_SOURCES = pulsecore/ipacl.h pulsecore/ipacl.c \ + pulsecore/inet_pton.c pulsecore/inet_pton.h libipacl_la_LDFLAGS = -avoid-version libipacl_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(WINSOCK_LIBS) diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c index ed5044ef2..15b6b3f9a 100644 --- a/src/pulsecore/ipacl.c +++ b/src/pulsecore/ipacl.c @@ -24,18 +24,36 @@ #endif #include -#include -#include -#include -#include #include -#include #include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif +#ifdef HAVE_NETINET_IP_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "winsock.h" + +#include + #include #include #include -#include + +#ifndef HAVE_INET_PTON +#include "inet_pton.h" +#endif #include "ipacl.h" diff --git a/src/tests/ipacl-test.c b/src/tests/ipacl-test.c index 8819a6a0f..2566b038e 100644 --- a/src/tests/ipacl-test.c +++ b/src/tests/ipacl-test.c @@ -1,16 +1,33 @@ /* $Id$ */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include -#include -#include -#include -#include #include #include -#include #include #include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif +#ifdef HAVE_NETINET_IP_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include "../pulsecore/winsock.h" + #include int main(int argc, char *argv[]) { From a84a2f91384060720dc1e1a97963faadc526c299 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Jul 2006 19:59:52 +0000 Subject: [PATCH 1037/1514] raise the default value for RLIMIT_NOFILE to 200 since 25 is apparently too small if every single GNOME apps thinks it needs to create its own server connection! git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1136 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 2 +- src/daemon/daemon.conf.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 894c0434b..0426989c1 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -78,7 +78,7 @@ static const pa_daemon_conf default_conf = { .rlimit_core = { .value = 0, .is_set = 0 }, .rlimit_data = { .value = 0, .is_set = 0 }, .rlimit_fsize = { .value = 0, .is_set = 0 }, - .rlimit_nofile = { .value = 25, .is_set = 1 }, + .rlimit_nofile = { .value = 200, .is_set = 1 }, .rlimit_stack = { .value = 0, .is_set = 0 } #ifdef RLIMIT_NPROC , .rlimit_nproc = { .value = 0, .is_set = 0 } diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 787405f8f..696b25a97 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -87,7 +87,7 @@ ; rlimit-core = -1 ; rlimit-data = -1 ; rlimit-fsize = -1 -; rlimit-nofile = 25 +; rlimit-nofile = 200 ; rlimit-stack = -1 ; rlimit-nproc = -1 ; rlimit-memlock = 25 From b345af2273cdeee77785514974e5c5b28ebb5fe3 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 21 Jul 2006 21:19:11 +0000 Subject: [PATCH 1038/1514] Use proper @libdir@ in pc.in files to handle x86_64 machines. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1137 fefdeb5f-60dc-0310-8127-8f9354f1896f --- libpulse-browse.pc.in | 4 ++-- libpulse-mainloop-glib.pc.in | 2 +- libpulse-simple.pc.in | 2 +- libpulse.pc.in | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libpulse-browse.pc.in b/libpulse-browse.pc.in index 7bdedf2e1..7b9a59f41 100644 --- a/libpulse-browse.pc.in +++ b/libpulse-browse.pc.in @@ -1,9 +1,9 @@ prefix=@prefix@ exec_prefix=${prefix} -libdir=${exec_prefix}/lib +libdir=@libdir@ includedir=${prefix}/include -Name: libpuls-browse +Name: libpulse-browse Description: PulseAudio Network Browsing API Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpulse-browse diff --git a/libpulse-mainloop-glib.pc.in b/libpulse-mainloop-glib.pc.in index a9a51cf7e..0977f185d 100644 --- a/libpulse-mainloop-glib.pc.in +++ b/libpulse-mainloop-glib.pc.in @@ -1,6 +1,6 @@ prefix=@prefix@ exec_prefix=${prefix} -libdir=${exec_prefix}/lib +libdir=@libdir@ includedir=${prefix}/include Name: libpulse-mainloop-glib diff --git a/libpulse-simple.pc.in b/libpulse-simple.pc.in index c35e83fa5..4ccc3d582 100644 --- a/libpulse-simple.pc.in +++ b/libpulse-simple.pc.in @@ -1,6 +1,6 @@ prefix=@prefix@ exec_prefix=${prefix} -libdir=${exec_prefix}/lib +libdir=@libdir@ includedir=${prefix}/include Name: libpulse-simple diff --git a/libpulse.pc.in b/libpulse.pc.in index 8d0ffb85f..45fec220d 100644 --- a/libpulse.pc.in +++ b/libpulse.pc.in @@ -1,6 +1,6 @@ prefix=@prefix@ exec_prefix=${prefix} -libdir=${exec_prefix}/lib +libdir=@libdir@ includedir=${prefix}/include Name: libpulse From 07a1c45cc1bd647d9a9c579a0c2bffd4c3d5fc1b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 22 Jul 2006 00:54:23 +0000 Subject: [PATCH 1039/1514] fix horribly broken glib timeout event handling git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1138 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/glib-mainloop.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/pulse/glib-mainloop.c b/src/pulse/glib-mainloop.c index cdaecdf83..77f934501 100644 --- a/src/pulse/glib-mainloop.c +++ b/src/pulse/glib-mainloop.c @@ -312,7 +312,7 @@ static void glib_time_restart(pa_time_event*e, const struct timeval *tv) { assert(e); assert(!e->dead); - if (e->enabled && !!tv) + if (e->enabled && !tv) e->mainloop->n_enabled_time_events--; else if (!e->enabled && tv) e->mainloop->n_enabled_time_events++; @@ -476,13 +476,11 @@ static gboolean prepare_func(GSource *source, gint *timeout) { tvnow.tv_sec = now.tv_sec; tvnow.tv_usec = now.tv_usec; - usec = pa_timeval_diff(&t->timeval, &tvnow); - - if (usec <= 0) { + if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) { *timeout = 0; return TRUE; - } - + } + usec = pa_timeval_diff(&t->timeval, &tvnow); *timeout = (gint) (usec / 1000); } else *timeout = -1; @@ -554,7 +552,7 @@ static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callbac tvnow.tv_sec = now.tv_sec; tvnow.tv_usec = now.tv_usec; - if (pa_timeval_cmp(&t->timeval, &tvnow) < 0) { + if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) { t->callback(&g->api, t, &t->timeval, t->userdata); return TRUE; } From 95eee87380dfbb648243da456dfb204cd5009441 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Jul 2006 19:23:12 +0000 Subject: [PATCH 1040/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1139 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 + 1 file changed, 1 insertion(+) diff --git a/todo b/todo index 9ea67dda3..d453b4d85 100644 --- a/todo +++ b/todo @@ -2,6 +2,7 @@ Post 0.9.0: - alsa mmap driver +- alsa driver with hw mixing - dbus/hal (Shams King is working on this one) - chroot() - module-tunnel: improve latency calculation From c85351ba054045fd4fad1d8825c3d8c6e036c93b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Jul 2006 22:35:30 +0000 Subject: [PATCH 1041/1514] as a result of memory profiling with valgrind/massif: decrease default hash table size from 1024 to 127. the hashtables are sparsely filled most of the time, so there is no point in allocating to much memory by default. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1140 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/hashmap.c | 2 +- src/pulsecore/idxset.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c index 2cddba1d5..6e0e6b028 100644 --- a/src/pulsecore/hashmap.c +++ b/src/pulsecore/hashmap.c @@ -34,7 +34,7 @@ #include "hashmap.h" -#define BUCKETS 1023 +#define BUCKETS 127 struct hashmap_entry { struct hashmap_entry *next, *previous, *bucket_next, *bucket_previous; diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c index ddce623a2..d3aec2dea 100644 --- a/src/pulsecore/idxset.c +++ b/src/pulsecore/idxset.c @@ -78,7 +78,7 @@ pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_fu s = pa_xnew(pa_idxset, 1); s->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; s->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; - s->hash_table_size = 1023; + s->hash_table_size = 127; s->hash_table = pa_xmalloc0(sizeof(idxset_entry*)*s->hash_table_size); s->array = NULL; s->array_size = 0; From 3aac89331bfaf7858fcb8672da4c9a0ced1de911 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 23 Jul 2006 22:36:08 +0000 Subject: [PATCH 1042/1514] add massif target to Makefile git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1141 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 9eb957d57..e0add7031 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1209,4 +1209,7 @@ install-exec-hook: rm -f $(DESTDIR)$(libdir)/libpulsedsp.a rm -f $(DESTDIR)$(libdir)/libpulsedsp.la +massif: pulseaudio + libtool --mode=execute valgrind --tool=massif --depth=6 --alloc-fn=pa_xmalloc --alloc-fn=pa_xmalloc0 --alloc-fn=pa_xrealloc --alloc-fn=dbus_realloc --alloc-fn=pa_xnew0_internal --alloc-fn=pa_xnew_internal ./pulseaudio + .PHONY: utils/padsp From 0f8f5bce6c3b94e2638bcbcbad4310b49e4010cd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Jul 2006 17:48:33 +0000 Subject: [PATCH 1043/1514] bump version and sonames git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1142 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 746da4799..6cfbcf183 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_PREREQ(2.57) m4_define(PA_MAJOR, [0]) m4_define(PA_MINOR, [9]) -m4_define(PA_MICRO, [3]) +m4_define(PA_MICRO, [4]) AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) @@ -36,8 +36,8 @@ AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/]) AC_SUBST(PA_API_VERSION, 9) AC_SUBST(PA_PROTOCOL_VERSION, 9) -AC_SUBST(LIBPULSE_VERSION_INFO, [0:1:0]) -AC_SUBST(LIBPULSECORE_VERSION_INFO, [1:0:0]) +AC_SUBST(LIBPULSE_VERSION_INFO, [0:2:0]) +AC_SUBST(LIBPULSECORE_VERSION_INFO, [1:1:0]) AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:0:0]) AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:0:1]) AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:1:0]) From 675bf2f51a0e37e8f0d4fd4d733255ca92efc923 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Jul 2006 20:03:27 +0000 Subject: [PATCH 1044/1514] add autogen.sh for jhbuild (for you, elmarco!) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1144 fefdeb5f-60dc-0310-8127-8f9354f1896f --- autogen.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100755 autogen.sh diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 000000000..16c573865 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# $Id$ + +# This file is part of PulseAudio. +# +# PulseAudio is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# PulseAudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with PulseAudio; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +# Only there to make jhbuild happy + +NOCONFIGURE=1 ./bootstrap.sh + +exec ./configure "$@" From c41d7498d3edc66c05297874cd106adb3961e8a4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Jul 2006 20:09:22 +0000 Subject: [PATCH 1045/1514] add a few more g_assert()s and change all assert()s to g_assert()s git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1145 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/glib-mainloop.c | 125 ++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 52 deletions(-) diff --git a/src/pulse/glib-mainloop.c b/src/pulse/glib-mainloop.c index 77f934501..767675526 100644 --- a/src/pulse/glib-mainloop.c +++ b/src/pulse/glib-mainloop.c @@ -106,8 +106,10 @@ static void cleanup_io_events(pa_glib_mainloop *g, int force) { if (force || e->dead) { PA_LLIST_REMOVE(pa_io_event, g->io_events, e); - if (e->dead) + if (e->dead) { + g_assert(g->io_events_please_scan > 0); g->io_events_please_scan--; + } if (e->poll_fd_added) g_source_remove_poll(&g->source, &e->poll_fd); @@ -121,7 +123,7 @@ static void cleanup_io_events(pa_glib_mainloop *g, int force) { e = n; } - assert(g->io_events_please_scan == 0); + g_assert(g->io_events_please_scan == 0); } static void cleanup_time_events(pa_glib_mainloop *g, int force) { @@ -137,11 +139,15 @@ static void cleanup_time_events(pa_glib_mainloop *g, int force) { if (force || e->dead) { PA_LLIST_REMOVE(pa_time_event, g->time_events, e); - if (e->dead) + if (e->dead) { + g_assert(g->time_events_please_scan > 0); g->time_events_please_scan--; + } - if (!e->dead && e->enabled) + if (!e->dead && e->enabled) { + g_assert(g->n_enabled_time_events > 0); g->n_enabled_time_events--; + } if (e->destroy_callback) e->destroy_callback(&g->api, e, e->userdata); @@ -152,7 +158,7 @@ static void cleanup_time_events(pa_glib_mainloop *g, int force) { e = n; } - assert(g->time_events_please_scan == 0); + g_assert(g->time_events_please_scan == 0); } static void cleanup_defer_events(pa_glib_mainloop *g, int force) { @@ -168,11 +174,15 @@ static void cleanup_defer_events(pa_glib_mainloop *g, int force) { if (force || e->dead) { PA_LLIST_REMOVE(pa_defer_event, g->defer_events, e); - if (e->dead) + if (e->dead) { + g_assert(g->defer_events_please_scan > 0); g->defer_events_please_scan--; + } - if (!e->dead && e->enabled) + if (!e->dead && e->enabled) { + g_assert(g->n_enabled_defer_events > 0); g->n_enabled_defer_events--; + } if (e->destroy_callback) e->destroy_callback(&g->api, e, e->userdata); @@ -183,7 +193,7 @@ static void cleanup_defer_events(pa_glib_mainloop *g, int force) { e = n; } - assert(g->defer_events_please_scan == 0); + g_assert(g->defer_events_please_scan == 0); } static gushort map_flags_to_glib(pa_io_event_flags_t flags) { @@ -212,10 +222,10 @@ static pa_io_event* glib_io_new( pa_io_event *e; pa_glib_mainloop *g; - assert(m); - assert(m->userdata); - assert(fd >= 0); - assert(cb); + g_assert(m); + g_assert(m->userdata); + g_assert(fd >= 0); + g_assert(cb); g = m->userdata; @@ -240,15 +250,15 @@ static pa_io_event* glib_io_new( } static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->poll_fd.events = map_flags_to_glib(f); } static void glib_io_free(pa_io_event*e) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->dead = 1; e->mainloop->io_events_please_scan++; @@ -260,8 +270,8 @@ static void glib_io_free(pa_io_event*e) { } static void glib_io_set_destroy(pa_io_event*e, pa_io_event_destroy_cb_t cb) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->destroy_callback = cb; } @@ -277,9 +287,9 @@ static pa_time_event* glib_time_new( pa_glib_mainloop *g; pa_time_event *e; - assert(m); - assert(m->userdata); - assert(cb); + g_assert(m); + g_assert(m->userdata); + g_assert(cb); g = m->userdata; @@ -309,20 +319,21 @@ static pa_time_event* glib_time_new( } static void glib_time_restart(pa_time_event*e, const struct timeval *tv) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); - if (e->enabled && !tv) + if (e->enabled && !tv) { + g_assert(e->mainloop->n_enabled_time_events > 0); e->mainloop->n_enabled_time_events--; - else if (!e->enabled && tv) + } else if (!e->enabled && tv) e->mainloop->n_enabled_time_events++; - if ((e->enabled = !!tv)) + if ((e->enabled = !!tv)) e->timeval = *tv; if (e->mainloop->cached_next_time_event && e->enabled) { g_assert(e->mainloop->cached_next_time_event->enabled); - + if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0) e->mainloop->cached_next_time_event = e; } else if (e->mainloop->cached_next_time_event == e) @@ -330,8 +341,8 @@ static void glib_time_restart(pa_time_event*e, const struct timeval *tv) { } static void glib_time_free(pa_time_event *e) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->dead = 1; e->mainloop->time_events_please_scan++; @@ -344,8 +355,8 @@ static void glib_time_free(pa_time_event *e) { } static void glib_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->destroy_callback = cb; } @@ -360,9 +371,9 @@ static pa_defer_event* glib_defer_new( pa_defer_event *e; pa_glib_mainloop *g; - assert(m); - assert(m->userdata); - assert(cb); + g_assert(m); + g_assert(m->userdata); + g_assert(cb); g = m->userdata; @@ -382,31 +393,34 @@ static pa_defer_event* glib_defer_new( } static void glib_defer_enable(pa_defer_event *e, int b) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); - if (e->enabled && !b) + if (e->enabled && !b) { + g_assert(e->mainloop->n_enabled_defer_events > 0); e->mainloop->n_enabled_defer_events--; - else if (!e->enabled && b) + } else if (!e->enabled && b) e->mainloop->n_enabled_defer_events++; e->enabled = b; } static void glib_defer_free(pa_defer_event *e) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->dead = 1; e->mainloop->defer_events_please_scan++; - if (e->enabled) + if (e->enabled) { + g_assert(e->mainloop->n_enabled_defer_events > 0); e->mainloop->n_enabled_defer_events--; + } } static void glib_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t cb) { - assert(e); - assert(!e->dead); + g_assert(e); + g_assert(!e->dead); e->destroy_callback = cb; } @@ -422,7 +436,7 @@ static void glib_quit(pa_mainloop_api*a, PA_GCC_UNUSED int retval) { static pa_time_event* find_next_time_event(pa_glib_mainloop *g) { pa_time_event *t, *n = NULL; - assert(g); + g_assert(g); if (g->cached_next_time_event) return g->cached_next_time_event; @@ -445,12 +459,9 @@ static pa_time_event* find_next_time_event(pa_glib_mainloop *g) { return n; } -static gboolean prepare_func(GSource *source, gint *timeout) { - pa_glib_mainloop *g = (pa_glib_mainloop*) source; - +static void scan_dead(pa_glib_mainloop *g) { g_assert(g); - g_assert(timeout); - + if (g->io_events_please_scan) cleanup_io_events(g, 0); @@ -459,6 +470,15 @@ static gboolean prepare_func(GSource *source, gint *timeout) { if (g->defer_events_please_scan) cleanup_defer_events(g, 0); +} + +static gboolean prepare_func(GSource *source, gint *timeout) { + pa_glib_mainloop *g = (pa_glib_mainloop*) source; + + g_assert(g); + g_assert(timeout); + + scan_dead(g); if (g->n_enabled_defer_events) { *timeout = 0; @@ -534,7 +554,7 @@ static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callbac break; } - assert(d); + g_assert(d); d->callback(&g->api, d, d->userdata); return TRUE; @@ -553,6 +573,7 @@ static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callbac tvnow.tv_usec = now.tv_usec; if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) { + t->enabled = 0; t->callback(&g->api, t, &t->timeval, t->userdata); return TRUE; } @@ -621,7 +642,7 @@ pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { } void pa_glib_mainloop_free(pa_glib_mainloop* g) { - assert(g); + g_assert(g); cleanup_io_events(g, 1); cleanup_defer_events(g, 1); @@ -633,7 +654,7 @@ void pa_glib_mainloop_free(pa_glib_mainloop* g) { } pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) { - assert(g); + g_assert(g); return &g->api; } From 32444f0df3c5a28a812b37a6665f8f39201d80d7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Jul 2006 20:10:30 +0000 Subject: [PATCH 1046/1514] split a few assert()s git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1146 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/idxset.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c index d3aec2dea..5c79767df 100644 --- a/src/pulsecore/idxset.c +++ b/src/pulsecore/idxset.c @@ -151,13 +151,15 @@ static idxset_entry** array_index(pa_idxset*s, uint32_t idx) { if (idx < s->start_index) return NULL; - return s->array + (idx - s->start_index); + return s->array + idx - s->start_index; } int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { unsigned h; idxset_entry *e, **a; - assert(s && p); + + assert(s); + assert(p); assert(s->hash_func); h = s->hash_func(p) % s->hash_table_size; @@ -341,7 +343,8 @@ void* pa_idxset_first(pa_idxset *s, uint32_t *idx) { void *pa_idxset_next(pa_idxset *s, uint32_t *idx) { idxset_entry **a, *e = NULL; - assert(s && idx); + assert(s); + assert(idx); if ((a = array_index(s, *idx)) && *a) e = (*a)->iterate_next; @@ -355,7 +358,6 @@ void *pa_idxset_next(pa_idxset *s, uint32_t *idx) { } } - int pa_idxset_foreach(pa_idxset*s, int (*func)(void *p, uint32_t idx, int *del, void*userdata), void *userdata) { idxset_entry *e; assert(s && func); From 216bdd48594f6b6be7c09f8b4c7094ec070cdaf1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Jul 2006 20:10:47 +0000 Subject: [PATCH 1047/1514] split a few asserts git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1147 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/tagstruct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c index 60b05a3fa..11e85c19c 100644 --- a/src/pulsecore/tagstruct.c +++ b/src/pulsecore/tagstruct.c @@ -79,7 +79,8 @@ uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l) { } static void extend(pa_tagstruct*t, size_t l) { - assert(t && t->dynamic); + assert(t); + assert(t->dynamic); if (t->length+l <= t->allocated) return; @@ -87,7 +88,6 @@ static void extend(pa_tagstruct*t, size_t l) { t->data = pa_xrealloc(t->data, t->allocated = t->length+l+100); } - void pa_tagstruct_puts(pa_tagstruct*t, const char *s) { size_t l; assert(t); From 563fab983f065fdad14696ce3f13d3df6a2b0370 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Jul 2006 20:39:34 +0000 Subject: [PATCH 1048/1514] Results of profiling PulseAudio with valgrind's callgrind module: rework the default event loop implementation to use PA_LLIST_xxx instead of pa_idxset; don't generate weakeup events if we aren't in STATE_POLLING; minimize dispatching of io events; cache next time event instead of traversing the list of time events on every event loop iteration; other optimizations git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1148 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/mainloop.c | 551 ++++++++++++++++++++++++++++--------------- 1 file changed, 355 insertions(+), 196 deletions(-) diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index dfbc337b8..682b2ccd7 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -49,7 +49,7 @@ #include #include -#include +#include #include #include "mainloop.h" @@ -57,50 +57,66 @@ struct pa_io_event { pa_mainloop *mainloop; int dead; + int fd; pa_io_event_flags_t events; - void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata); struct pollfd *pollfd; + + pa_io_event_cb_t callback; void *userdata; - void (*destroy_callback) (pa_mainloop_api*a, pa_io_event *e, void *userdata); + pa_io_event_destroy_cb_t destroy_callback; + + PA_LLIST_FIELDS(pa_io_event); }; struct pa_time_event { pa_mainloop *mainloop; int dead; + int enabled; struct timeval timeval; - void (*callback)(pa_mainloop_api*a, pa_time_event *e, const struct timeval*tv, void *userdata); + + pa_time_event_cb_t callback; void *userdata; - void (*destroy_callback) (pa_mainloop_api*a, pa_time_event *e, void *userdata); + pa_time_event_destroy_cb_t destroy_callback; + + PA_LLIST_FIELDS(pa_time_event); }; struct pa_defer_event { pa_mainloop *mainloop; int dead; + int enabled; - void (*callback)(pa_mainloop_api*a, pa_defer_event*e, void *userdata); + + pa_defer_event_cb_t callback; void *userdata; - void (*destroy_callback) (pa_mainloop_api*a, pa_defer_event *e, void *userdata); + pa_defer_event_destroy_cb_t destroy_callback; + + PA_LLIST_FIELDS(pa_defer_event); }; struct pa_mainloop { - pa_idxset *io_events, *time_events, *defer_events; - int io_events_scan_dead, defer_events_scan_dead, time_events_scan_dead; + PA_LLIST_HEAD(pa_io_event, io_events); + PA_LLIST_HEAD(pa_time_event, time_events); + PA_LLIST_HEAD(pa_defer_event, defer_events); + + int n_enabled_defer_events, n_enabled_time_events, n_io_events; + int io_events_please_scan, time_events_please_scan, defer_events_please_scan; struct pollfd *pollfds; unsigned max_pollfds, n_pollfds; int rebuild_pollfds; int prepared_timeout; + pa_time_event *cached_next_time_event; int quit, retval; pa_mainloop_api api; - int deferred_pending; - int wakeup_pipe[2]; int wakeup_pipe_type; + int wakeup_requested; enum { STATE_PASSIVE, @@ -112,33 +128,55 @@ struct pa_mainloop { pa_poll_func poll_func; void *poll_func_userdata; + int poll_func_ret; }; +static short map_flags_to_libc(pa_io_event_flags_t flags) { + return + (flags & PA_IO_EVENT_INPUT ? POLLIN : 0) | + (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | + (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) | + (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0); +} + +static pa_io_event_flags_t map_flags_from_libc(short flags) { + return + (flags & POLLIN ? PA_IO_EVENT_INPUT : 0) | + (flags & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) | + (flags & POLLERR ? PA_IO_EVENT_ERROR : 0) | + (flags & POLLHUP ? PA_IO_EVENT_HANGUP : 0); +} + /* IO events */ static pa_io_event* mainloop_io_new( - pa_mainloop_api*a, - int fd, - pa_io_event_flags_t events, - void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), - void *userdata) { + pa_mainloop_api*a, + int fd, + pa_io_event_flags_t events, + pa_io_event_cb_t callback, + void *userdata) { pa_mainloop *m; pa_io_event *e; - assert(a && a->userdata && fd >= 0 && callback); + assert(a); + assert(a->userdata); + assert(fd >= 0); + assert(callback); + m = a->userdata; assert(a == &m->api); - e = pa_xmalloc(sizeof(pa_io_event)); + e = pa_xnew(pa_io_event, 1); e->mainloop = m; e->dead = 0; e->fd = fd; e->events = events; + e->pollfd = NULL; + e->callback = callback; e->userdata = userdata; e->destroy_callback = NULL; - e->pollfd = NULL; #ifdef OS_IS_WIN32 { @@ -160,8 +198,9 @@ static pa_io_event* mainloop_io_new( } #endif - pa_idxset_put(m->io_events, e, NULL); + PA_LLIST_PREPEND(pa_io_event, m->io_events, e); m->rebuild_pollfds = 1; + m->n_io_events ++; pa_mainloop_wakeup(m); @@ -169,48 +208,69 @@ static pa_io_event* mainloop_io_new( } static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { - assert(e && e->mainloop); + assert(e); + assert(!e->dead); + if (e->events == events) + return; + e->events = events; - e->mainloop->rebuild_pollfds = 1; + + if (e->pollfd) + e->pollfd->events = map_flags_to_libc(events); + else + e->mainloop->rebuild_pollfds = 1; pa_mainloop_wakeup(e->mainloop); } static void mainloop_io_free(pa_io_event *e) { - assert(e && e->mainloop); + assert(e); + assert(!e->dead); - e->dead = e->mainloop->io_events_scan_dead = e->mainloop->rebuild_pollfds = 1; + e->dead = 1; + e->mainloop->io_events_please_scan ++; + + e->mainloop->n_io_events --; + e->mainloop->rebuild_pollfds = 1; pa_mainloop_wakeup(e->mainloop); } -static void mainloop_io_set_destroy(pa_io_event *e, void (*callback)(pa_mainloop_api*a, pa_io_event *e, void *userdata)) { +static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) { assert(e); + e->destroy_callback = callback; } /* Defer events */ -static pa_defer_event* mainloop_defer_new(pa_mainloop_api*a, void (*callback) (pa_mainloop_api*a, pa_defer_event *e, void *userdata), void *userdata) { +static pa_defer_event* mainloop_defer_new( + pa_mainloop_api*a, + pa_defer_event_cb_t callback, + void *userdata) { + pa_mainloop *m; pa_defer_event *e; - assert(a && a->userdata && callback); + assert(a); + assert(a->userdata); + assert(callback); + m = a->userdata; assert(a == &m->api); - e = pa_xmalloc(sizeof(pa_defer_event)); + e = pa_xnew(pa_defer_event, 1); e->mainloop = m; e->dead = 0; e->enabled = 1; + m->n_enabled_defer_events++; + e->callback = callback; e->userdata = userdata; e->destroy_callback = NULL; - pa_idxset_put(m->defer_events, e, NULL); - - m->deferred_pending++; + PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e); pa_mainloop_wakeup(e->mainloop); @@ -219,12 +279,13 @@ static pa_defer_event* mainloop_defer_new(pa_mainloop_api*a, void (*callback) (p static void mainloop_defer_enable(pa_defer_event *e, int b) { assert(e); + assert(!e->dead); if (e->enabled && !b) { - assert(e->mainloop->deferred_pending > 0); - e->mainloop->deferred_pending--; + assert(e->mainloop->n_enabled_defer_events > 0); + e->mainloop->n_enabled_defer_events--; } else if (!e->enabled && b) { - e->mainloop->deferred_pending++; + e->mainloop->n_enabled_defer_events++; pa_mainloop_wakeup(e->mainloop); } @@ -233,42 +294,63 @@ static void mainloop_defer_enable(pa_defer_event *e, int b) { static void mainloop_defer_free(pa_defer_event *e) { assert(e); - e->dead = e->mainloop->defer_events_scan_dead = 1; + assert(!e->dead); + + e->dead = 1; + e->mainloop->defer_events_please_scan ++; if (e->enabled) { - e->enabled = 0; - assert(e->mainloop->deferred_pending > 0); - e->mainloop->deferred_pending--; + assert(e->mainloop->n_enabled_defer_events > 0); + e->mainloop->n_enabled_defer_events--; } } -static void mainloop_defer_set_destroy(pa_defer_event *e, void (*callback)(pa_mainloop_api*a, pa_defer_event *e, void *userdata)) { +static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t callback) { assert(e); + assert(!e->dead); + e->destroy_callback = callback; } /* Time events */ -static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval *tv, void (*callback) (pa_mainloop_api*a, pa_time_event*e, const struct timeval *tv, void *userdata), void *userdata) { +static pa_time_event* mainloop_time_new( + pa_mainloop_api*a, + const struct timeval *tv, + pa_time_event_cb_t callback, + void *userdata) { + pa_mainloop *m; pa_time_event *e; - assert(a && a->userdata && callback); + assert(a); + assert(a->userdata); + assert(callback); + m = a->userdata; assert(a == &m->api); - e = pa_xmalloc(sizeof(pa_time_event)); + e = pa_xnew(pa_time_event, 1); e->mainloop = m; e->dead = 0; - e->enabled = !!tv; - if (tv) + if ((e->enabled = !!tv)) { e->timeval = *tv; + m->n_enabled_time_events++; + + if (m->cached_next_time_event) { + assert(m->cached_next_time_event->enabled); + + if (pa_timeval_cmp(tv, &m->cached_next_time_event->timeval) < 0) + m->cached_next_time_event = e; + } + } + e->callback = callback; e->userdata = userdata; e->destroy_callback = NULL; - pa_idxset_put(m->time_events, e, NULL); + PA_LLIST_PREPEND(pa_time_event, m->time_events, e); if (e->enabled) pa_mainloop_wakeup(m); @@ -278,26 +360,50 @@ static pa_time_event* mainloop_time_new(pa_mainloop_api*a, const struct timeval static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { assert(e); + assert(!e->dead); - if (tv) { - e->enabled = 1; + if (e->enabled && !tv) { + assert(e->mainloop->n_enabled_time_events > 0); + e->mainloop->n_enabled_time_events--; + } else if (!e->enabled && tv) + e->mainloop->n_enabled_time_events++; + + if ((e->enabled = !!tv)) { e->timeval = *tv; - pa_mainloop_wakeup(e->mainloop); - } else - e->enabled = 0; + } + + if (e->mainloop->cached_next_time_event && e->enabled) { + assert(e->mainloop->cached_next_time_event->enabled); + + if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0) + e->mainloop->cached_next_time_event = e; + } else if (e->mainloop->cached_next_time_event == e) + e->mainloop->cached_next_time_event = NULL; } static void mainloop_time_free(pa_time_event *e) { assert(e); + assert(!e->dead); - e->dead = e->mainloop->time_events_scan_dead = 1; + e->dead = 1; + e->mainloop->time_events_please_scan ++; + if (e->enabled) { + assert(e->mainloop->n_enabled_time_events > 0); + e->mainloop->n_enabled_time_events--; + } + + if (e->mainloop->cached_next_time_event == e) + e->mainloop->cached_next_time_event = NULL; + /* no wakeup needed here. Think about it! */ } -static void mainloop_time_set_destroy(pa_time_event *e, void (*callback)(pa_mainloop_api*a, pa_time_event *e, void *userdata)) { +static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t callback) { assert(e); + assert(!e->dead); + e->destroy_callback = callback; } @@ -305,7 +411,9 @@ static void mainloop_time_set_destroy(pa_time_event *e, void (*callback)(pa_main static void mainloop_quit(pa_mainloop_api*a, int retval) { pa_mainloop *m; - assert(a && a->userdata); + + assert(a); + assert(a->userdata); m = a->userdata; assert(a == &m->api); @@ -336,7 +444,7 @@ static const pa_mainloop_api vtable = { pa_mainloop *pa_mainloop_new(void) { pa_mainloop *m; - m = pa_xmalloc(sizeof(pa_mainloop)); + m = pa_xnew(pa_mainloop, 1); m->wakeup_pipe_type = 0; if (pipe(m->wakeup_pipe) < 0) { @@ -347,14 +455,17 @@ pa_mainloop *pa_mainloop_new(void) { pa_make_nonblock_fd(m->wakeup_pipe[0]); pa_make_nonblock_fd(m->wakeup_pipe[1]); + m->wakeup_requested = 0; - m->io_events = pa_idxset_new(NULL, NULL); - m->defer_events = pa_idxset_new(NULL, NULL); - m->time_events = pa_idxset_new(NULL, NULL); + PA_LLIST_HEAD_INIT(pa_io_event, m->io_events); + PA_LLIST_HEAD_INIT(pa_time_event, m->time_events); + PA_LLIST_HEAD_INIT(pa_defer_event, m->defer_events); - assert(m->io_events && m->defer_events && m->time_events); + m->n_enabled_defer_events = m->n_enabled_time_events = m->n_io_events = 0; + m->io_events_please_scan = m->time_events_please_scan = m->defer_events_please_scan = 0; - m->io_events_scan_dead = m->defer_events_scan_dead = m->time_events_scan_dead = 0; + m->cached_next_time_event = NULL; + m->prepared_timeout = 0; m->pollfds = NULL; m->max_pollfds = m->n_pollfds = 0; @@ -365,74 +476,124 @@ pa_mainloop *pa_mainloop_new(void) { m->api = vtable; m->api.userdata = m; - m->deferred_pending = 0; - m->state = STATE_PASSIVE; m->poll_func = NULL; m->poll_func_userdata = NULL; - - m->retval = -1; + m->poll_func_ret = -1; return m; } -static int io_foreach(void *p, uint32_t PA_GCC_UNUSED idx, int *del, void*userdata) { - pa_io_event *e = p; - int *all = userdata; - assert(e && del && all); +static void cleanup_io_events(pa_mainloop *m, int force) { + pa_io_event *e; - if (!*all && !e->dead) - return 0; - - if (e->destroy_callback) - e->destroy_callback(&e->mainloop->api, e, e->userdata); - pa_xfree(e); - *del = 1; - return 0; + e = m->io_events; + while (e) { + pa_io_event *n = e->next; + + if (!force && m->io_events_please_scan <= 0) + break; + + if (force || e->dead) { + PA_LLIST_REMOVE(pa_io_event, m->io_events, e); + + if (e->dead) { + assert(m->io_events_please_scan > 0); + m->io_events_please_scan--; + } + + if (e->destroy_callback) + e->destroy_callback(&m->api, e, e->userdata); + + pa_xfree(e); + + m->rebuild_pollfds = 1; + } + + e = n; + } + + assert(m->io_events_please_scan == 0); } -static int time_foreach(void *p, uint32_t PA_GCC_UNUSED idx, int *del, void*userdata) { - pa_time_event *e = p; - int *all = userdata; - assert(e && del && all); +static void cleanup_time_events(pa_mainloop *m, int force) { + pa_time_event *e; - if (!*all && !e->dead) - return 0; - - if (e->destroy_callback) - e->destroy_callback(&e->mainloop->api, e, e->userdata); - pa_xfree(e); - *del = 1; - return 0; + e = m->time_events; + while (e) { + pa_time_event *n = e->next; + + if (!force && m->time_events_please_scan <= 0) + break; + + if (force || e->dead) { + PA_LLIST_REMOVE(pa_time_event, m->time_events, e); + + if (e->dead) { + assert(m->time_events_please_scan > 0); + m->time_events_please_scan--; + } + + if (!e->dead && e->enabled) { + assert(m->n_enabled_time_events > 0); + m->n_enabled_time_events--; + } + + if (e->destroy_callback) + e->destroy_callback(&m->api, e, e->userdata); + + pa_xfree(e); + } + + e = n; + } + + assert(m->time_events_please_scan == 0); } -static int defer_foreach(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void*userdata) { - pa_defer_event *e = p; - int *all = userdata; - assert(e && del && all); +static void cleanup_defer_events(pa_mainloop *m, int force) { + pa_defer_event *e; - if (!*all && !e->dead) - return 0; - - if (e->destroy_callback) - e->destroy_callback(&e->mainloop->api, e, e->userdata); - pa_xfree(e); - *del = 1; - return 0; + e = m->defer_events; + while (e) { + pa_defer_event *n = e->next; + + if (!force && m->defer_events_please_scan <= 0) + break; + + if (force || e->dead) { + PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e); + + if (e->dead) { + assert(m->defer_events_please_scan > 0); + m->defer_events_please_scan--; + } + + if (!e->dead && e->enabled) { + assert(m->n_enabled_defer_events > 0); + m->n_enabled_defer_events--; + } + + if (e->destroy_callback) + e->destroy_callback(&m->api, e, e->userdata); + + pa_xfree(e); + } + + e = n; + } + + assert(m->defer_events_please_scan == 0); } + void pa_mainloop_free(pa_mainloop* m) { - int all = 1; assert(m); - pa_idxset_foreach(m->io_events, io_foreach, &all); - pa_idxset_foreach(m->time_events, time_foreach, &all); - pa_idxset_foreach(m->defer_events, defer_foreach, &all); - - pa_idxset_free(m->io_events, NULL, NULL); - pa_idxset_free(m->time_events, NULL, NULL); - pa_idxset_free(m->defer_events, NULL, NULL); + cleanup_io_events(m, 1); + cleanup_defer_events(m, 1); + cleanup_time_events(m, 1); pa_xfree(m->pollfds); @@ -445,27 +606,26 @@ void pa_mainloop_free(pa_mainloop* m) { } static void scan_dead(pa_mainloop *m) { - int all = 0; assert(m); - if (m->io_events_scan_dead) - pa_idxset_foreach(m->io_events, io_foreach, &all); - if (m->time_events_scan_dead) - pa_idxset_foreach(m->time_events, time_foreach, &all); - if (m->defer_events_scan_dead) - pa_idxset_foreach(m->defer_events, defer_foreach, &all); + if (m->io_events_please_scan) + cleanup_io_events(m, 0); - m->io_events_scan_dead = m->time_events_scan_dead = m->defer_events_scan_dead = 0; + if (m->time_events_please_scan) + cleanup_time_events(m, 0); + + if (m->defer_events_please_scan) + cleanup_defer_events(m, 0); } static void rebuild_pollfds(pa_mainloop *m) { pa_io_event*e; struct pollfd *p; - uint32_t idx = PA_IDXSET_INVALID; unsigned l; - l = pa_idxset_size(m->io_events) + 1; + l = m->n_io_events + 1; if (m->max_pollfds < l) { + l *= 2; m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l); m->max_pollfds = l; } @@ -481,7 +641,7 @@ static void rebuild_pollfds(pa_mainloop *m) { m->n_pollfds++; } - for (e = pa_idxset_first(m->io_events, &idx); e; e = pa_idxset_next(m->io_events, &idx)) { + for (e = m->io_events; e; e = e->next) { if (e->dead) { e->pollfd = NULL; continue; @@ -489,11 +649,7 @@ static void rebuild_pollfds(pa_mainloop *m) { e->pollfd = p; p->fd = e->fd; - p->events = - ((e->events & PA_IO_EVENT_INPUT) ? POLLIN : 0) | - ((e->events & PA_IO_EVENT_OUTPUT) ? POLLOUT : 0) | - POLLHUP | - POLLERR; + p->events = map_flags_to_libc(e->events); p->revents = 0; p++; @@ -504,37 +660,34 @@ static void rebuild_pollfds(pa_mainloop *m) { } static int dispatch_pollfds(pa_mainloop *m) { - uint32_t idx = PA_IDXSET_INVALID; pa_io_event *e; - int r = 0; + int r = 0, k; - for (e = pa_idxset_first(m->io_events, &idx); e && !m->quit; e = pa_idxset_next(m->io_events, &idx)) { + assert(m->poll_func_ret > 0); + + for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) { if (e->dead || !e->pollfd || !e->pollfd->revents) continue; assert(e->pollfd->fd == e->fd && e->callback); - e->callback(&m->api, e, e->fd, - (e->pollfd->revents & POLLHUP ? PA_IO_EVENT_HANGUP : 0) | - (e->pollfd->revents & POLLIN ? PA_IO_EVENT_INPUT : 0) | - (e->pollfd->revents & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) | - (e->pollfd->revents & POLLERR ? PA_IO_EVENT_ERROR : 0), - e->userdata); + e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata); e->pollfd->revents = 0; r++; + + k--; } return r; } static int dispatch_defer(pa_mainloop *m) { - uint32_t idx; pa_defer_event *e; int r = 0; - if (!m->deferred_pending) + if (m->n_enabled_defer_events <= 0) return 0; - for (e = pa_idxset_first(m->defer_events, &idx); e && !m->quit; e = pa_idxset_next(m->defer_events, &idx)) { + for (e = m->defer_events; e && !m->quit; e = e->next) { if (e->dead || !e->enabled) continue; @@ -546,70 +699,71 @@ static int dispatch_defer(pa_mainloop *m) { return r; } -static int calc_next_timeout(pa_mainloop *m) { - uint32_t idx; - pa_time_event *e; - struct timeval now; - int t = -1; - int got_time = 0; +static pa_time_event* find_next_time_event(pa_mainloop *m) { + pa_time_event *t, *n = NULL; + assert(m); - if (pa_idxset_isempty(m->time_events)) - return -1; + if (m->cached_next_time_event) + return m->cached_next_time_event; + + for (t = m->time_events; t; t = t->next) { - for (e = pa_idxset_first(m->time_events, &idx); e; e = pa_idxset_next(m->time_events, &idx)) { - int tmp; - - if (e->dead || !e->enabled) + if (t->dead || !t->enabled) continue; - /* Let's save a system call */ - if (!got_time) { - pa_gettimeofday(&now); - got_time = 1; + if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) { + n = t; + + /* Shortcut for tv = { 0, 0 } */ + if (n->timeval.tv_sec <= 0) + break; } - - if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) - return 0; - - tmp = (e->timeval.tv_sec - now.tv_sec)*1000; - - if (e->timeval.tv_usec > now.tv_usec) - tmp += (e->timeval.tv_usec - now.tv_usec)/1000; - else - tmp -= (now.tv_usec - e->timeval.tv_usec)/1000; - - if (tmp == 0) - return 0; - else if (t == -1 || tmp < t) - t = tmp; } - return t; + m->cached_next_time_event = n; + return n; +} + +static int calc_next_timeout(pa_mainloop *m) { + pa_time_event *t; + struct timeval now; + pa_usec_t usec; + + if (!m->n_enabled_time_events) + return -1; + + t = find_next_time_event(m); + assert(t); + + if (t->timeval.tv_sec <= 0) + return 0; + + pa_gettimeofday(&now); + + if (pa_timeval_cmp(&t->timeval, &now) <= 0) + return 0; + + usec = pa_timeval_diff(&t->timeval, &now); + return (int) (usec / 1000); } static int dispatch_timeout(pa_mainloop *m) { - uint32_t idx; pa_time_event *e; struct timeval now; - int got_time = 0; int r = 0; assert(m); - if (pa_idxset_isempty(m->time_events)) + if (m->n_enabled_time_events <= 0) return 0; - for (e = pa_idxset_first(m->time_events, &idx); e && !m->quit; e = pa_idxset_next(m->time_events, &idx)) { + pa_gettimeofday(&now); + + for (e = m->time_events; e && !m->quit; e = e->next) { if (e->dead || !e->enabled) continue; - /* Let's save a system call */ - if (!got_time) { - pa_gettimeofday(&now); - got_time = 1; - } - - if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) { + if (pa_timeval_cmp(&e->timeval, &now) <= 0) { assert(e->callback); e->enabled = 0; @@ -626,8 +780,10 @@ void pa_mainloop_wakeup(pa_mainloop *m) { char c = 'W'; assert(m); - if (m->wakeup_pipe[1] >= 0) + if (m->wakeup_pipe[1] >= 0 && m->state == STATE_POLLING) { pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type); + m->wakeup_requested++; + } } static void clear_wakeup(pa_mainloop *m) { @@ -638,7 +794,10 @@ static void clear_wakeup(pa_mainloop *m) { if (m->wakeup_pipe[0] < 0) return; - while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c)); + if (m->wakeup_requested) { + while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c)); + m->wakeup_requested = 0; + } } int pa_mainloop_prepare(pa_mainloop *m, int timeout) { @@ -651,8 +810,7 @@ int pa_mainloop_prepare(pa_mainloop *m, int timeout) { if (m->quit) goto quit; - if (!m->deferred_pending) { - + if (m->n_enabled_defer_events <= 0) { if (m->rebuild_pollfds) rebuild_pollfds(m); @@ -670,8 +828,6 @@ quit: } int pa_mainloop_poll(pa_mainloop *m) { - int r; - assert(m); assert(m->state == STATE_PREPARED); @@ -680,24 +836,26 @@ int pa_mainloop_poll(pa_mainloop *m) { m->state = STATE_POLLING; - if (m->deferred_pending) - r = 0; + if (m->n_enabled_defer_events ) + m->poll_func_ret = 0; else { + assert(!m->rebuild_pollfds); + if (m->poll_func) - r = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata); + m->poll_func_ret = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata); else - r = poll(m->pollfds, m->n_pollfds, m->prepared_timeout); + m->poll_func_ret = poll(m->pollfds, m->n_pollfds, m->prepared_timeout); - if (r < 0) { + if (m->poll_func_ret < 0) { if (errno == EINTR) - r = 0; + m->poll_func_ret = 0; else pa_log(__FILE__": poll(): %s", pa_cstrerror(errno)); } } - m->state = r < 0 ? STATE_PASSIVE : STATE_POLLED; - return r; + m->state = m->poll_func_ret < 0 ? STATE_PASSIVE : STATE_POLLED; + return m->poll_func_ret; quit: m->state = STATE_QUIT; @@ -713,16 +871,17 @@ int pa_mainloop_dispatch(pa_mainloop *m) { if (m->quit) goto quit; - if (m->deferred_pending) + if (m->n_enabled_defer_events) dispatched += dispatch_defer(m); else { - dispatched += dispatch_timeout(m); + if (m->n_enabled_time_events) + dispatched += dispatch_timeout(m); if (m->quit) goto quit; - - dispatched += dispatch_pollfds(m); + if (m->poll_func_ret > 0) + dispatched += dispatch_pollfds(m); } if (m->quit) From 61ce8bb0024764fa059aa5f5f1f5c2a0189c40bc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Jul 2006 20:51:15 +0000 Subject: [PATCH 1049/1514] add new command line option --no-cpu-limit. This is useful when running PulseAudio in valgrind's massif or callgrind tools git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1149 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/cmdline.c | 14 +++++++++++++- src/daemon/daemon-conf.c | 22 +++++++++++++--------- src/daemon/daemon-conf.h | 3 ++- src/daemon/daemon.conf.in | 5 +++++ src/daemon/main.c | 14 +++++++++----- 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index ab876edf2..e00f290e0 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -59,6 +59,7 @@ enum { ARG_KILL, ARG_USE_PID_FILE, ARG_CHECK, + ARG_NO_CPU_LIMIT, ARG_SYSTEM }; @@ -86,6 +87,7 @@ static struct option long_options[] = { {"use-pid-file", 2, 0, ARG_USE_PID_FILE}, {"check", 0, 0, ARG_CHECK}, {"system", 2, 0, ARG_SYSTEM}, + {"no-cpu-limit", 2, 0, ARG_NO_CPU_LIMIT}, {NULL, 0, 0, 0} }; @@ -128,7 +130,9 @@ void pa_cmdline_help(const char *argv0) { " (one of src-sinc-medium-quality,\n" " src-sinc-best-quality,src-sinc-fastest\n" " src-zero-order-hold,src-linear,trivial)\n" - " --use-pid-file[=BOOL] Create a PID file\n\n" + " --use-pid-file[=BOOL] Create a PID file\n" + " --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n" + " platforms that support it.\n\n" "STARTUP SCRIPT:\n" " -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with\n" @@ -286,6 +290,14 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d goto fail; } break; + + case ARG_NO_CPU_LIMIT: + if ((conf->no_cpu_limit = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log(__FILE__": --no-cpu-limit expects boolean argument"); + goto fail; + } + break; + default: goto fail; diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 0426989c1..3e585d90d 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -72,7 +72,8 @@ static const pa_daemon_conf default_conf = { .resample_method = PA_RESAMPLER_SRC_SINC_FASTEST, .config_file = NULL, .use_pid_file = 1, - .system_instance = 0 + .system_instance = 0, + .no_cpu_limit = 0 #ifdef HAVE_SYS_RESOURCE_H , .rlimit_as = { .value = 0, .is_set = 0 }, .rlimit_core = { .value = 0, .is_set = 0 }, @@ -246,6 +247,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "resample-method", parse_resample_method, NULL }, { "use-pid-file", pa_config_parse_bool, NULL }, { "system-instance", pa_config_parse_bool, NULL }, + { "no-cpu-limit", pa_config_parse_bool, NULL }, #ifdef HAVE_SYS_RESOURCE_H { "rlimit-as", parse_rlimit, NULL }, { "rlimit-core", parse_rlimit, NULL }, @@ -278,21 +280,22 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[12].data = c; table[13].data = &c->use_pid_file; table[14].data = &c->system_instance; + table[15].data = &c->no_cpu_limit; #ifdef HAVE_SYS_RESOURCE_H - table[15].data = &c->rlimit_as; - table[16].data = &c->rlimit_core; - table[17].data = &c->rlimit_data; - table[18].data = &c->rlimit_fsize; - table[19].data = &c->rlimit_nofile; - table[20].data = &c->rlimit_stack; + table[16].data = &c->rlimit_as; + table[17].data = &c->rlimit_core; + table[18].data = &c->rlimit_data; + table[19].data = &c->rlimit_fsize; + table[20].data = &c->rlimit_nofile; + table[21].data = &c->rlimit_stack; #ifdef RLIMIT_NPROC - table[21].data = &c->rlimit_nproc; + table[22].data = &c->rlimit_nproc; #endif #ifdef RLIMIT_MEMLOCK #ifndef RLIMIT_NPROC #error "Houston, we have a numbering problem!" #endif - table[22].data = &c->rlimit_memlock; + table[23].data = &c->rlimit_memlock; #endif #endif @@ -363,6 +366,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file); pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance); + pa_strbuf_printf(s, "no-cpu-limit = %i\n", !!c->no_cpu_limit); #ifdef HAVE_SYS_RESOURCE_H pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1); pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index a09773f14..84208336a 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -58,7 +58,8 @@ typedef struct pa_daemon_conf { scache_idle_time, auto_log_target, use_pid_file, - system_instance; + system_instance, + no_cpu_limit; char *script_commands, *dl_search_path, *default_script_file; pa_log_target_t log_target; pa_log_level_t log_level; diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 696b25a97..0204b9e32 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -79,6 +79,11 @@ ## effectively disables multiple instances. ; use-pid-file = 1 +## Do not install the CPU load limit, even on platforms where it is +## supported. This option is useful when debugging/profiling +## PulseAudio to disable disturbing SIGXCPU signals. +; no-cpu-limit = 0 + ## Run the daemon as system-wide instance, requires root priviliges ; system-instance = 0 diff --git a/src/daemon/main.c b/src/daemon/main.c index 3ced3bf6d..38d465f80 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -588,10 +588,12 @@ int main(int argc, char *argv[]) { c->running_as_daemon = 1; oil_init(); - - r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop)); - assert(r == 0); - + + if (!conf->no_cpu_limit) { + r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop)); + assert(r == 0); + } + buf = pa_strbuf_new(); if (conf->default_script_file) r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail); @@ -645,7 +647,9 @@ int main(int argc, char *argv[]) { pa_core_free(c); - pa_cpu_limit_done(); + if (!conf->no_cpu_limit) + pa_cpu_limit_done(); + pa_signal_done(); pa_mainloop_free(mainloop); From cc1d8213d6a58b0022017f8d231a346387aab507 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Jul 2006 17:36:14 +0000 Subject: [PATCH 1050/1514] add new module "module-gconf" which reads configuration information from gconf. this will be used in my upcoming paconf module git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1150 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 24 +- src/modules/gconf/Makefile | 13 ++ src/modules/gconf/gconf-helper.c | 123 ++++++++++ src/modules/gconf/module-gconf.c | 386 +++++++++++++++++++++++++++++++ 4 files changed, 544 insertions(+), 2 deletions(-) create mode 100644 src/modules/gconf/Makefile create mode 100644 src/modules/gconf/gconf-helper.c create mode 100644 src/modules/gconf/module-gconf.c diff --git a/src/Makefile.am b/src/Makefile.am index e0add7031..bb08ed785 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,6 +25,7 @@ pulseincludedir=$(includedir)/pulse pulsecoreincludedir=$(includedir)/pulsecore pulseconfdir=$(sysconfdir)/pulse +pulselibexecdir=$(libexecdir)/pulse ################################### # Defines # @@ -883,6 +884,14 @@ modlibexec_LTLIBRARIES += \ module-jack-source.la endif +if HAVE_GCONF +modlibexec_LTLIBRARIES += \ + module-gconf.la + +pulselibexec_PROGRAMS = \ + gconf-helper +endif + if OS_IS_WIN32 modlibexec_LTLIBRARIES += \ module-waveout.la @@ -930,8 +939,8 @@ SYMDEF_FILES = \ modules/rtp/module-rtp-recv-symdef.h \ modules/module-jack-sink-symdef.h \ modules/module-jack-source-symdef.h \ - modules/module-volume-restore-symdef.h - + modules/module-volume-restore-symdef.h \ + modules/gconf/module-gconf-symdef.h EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) @@ -1171,6 +1180,17 @@ module_jack_source_la_LDFLAGS = -module -avoid-version module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS) module_jack_source_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS) +# GConf support +module_gconf_la_SOURCES = modules/gconf/module-gconf.c +module_gconf_la_LDFLAGS = -module -avoid-version +module_gconf_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_gconf_la_CFLAGS = $(AM_CFLAGS) -DPA_GCONF_HELPER=\"$(pulselibexecdir)/gconf-helper\" + +gconf_helper_SOURCES = modules/gconf/gconf-helper.c +gconf_helper_LDADD = $(AM_LDADD) $(GCONF_LIBS) +gconf_helper_CFLAGS = $(AM_CFLAGS) $(GCONF_CFLAGS) +gconf_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + ################################### # Some minor stuff # ################################### diff --git a/src/modules/gconf/Makefile b/src/modules/gconf/Makefile new file mode 100644 index 000000000..316beb72d --- /dev/null +++ b/src/modules/gconf/Makefile @@ -0,0 +1,13 @@ +# This is a dirty trick just to ease compilation with emacs +# +# This file is not intended to be distributed or anything +# +# So: don't touch it, even better ignore it! + +all: + $(MAKE) -C ../.. + +clean: + $(MAKE) -C ../.. clean + +.PHONY: all clean diff --git a/src/modules/gconf/gconf-helper.c b/src/modules/gconf/gconf-helper.c new file mode 100644 index 000000000..c8b9b1445 --- /dev/null +++ b/src/modules/gconf/gconf-helper.c @@ -0,0 +1,123 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#define PA_GCONF_ROOT "/system/pulseaudio" +#define PA_GCONF_PATH_MODULES PA_GCONF_ROOT"/modules" + +static void handle_module(GConfClient *client, const char *name) { + gchar p[1024]; + gboolean enabled; + int i; + + snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/enabled", name); + enabled = gconf_client_get_bool(client, p, FALSE); + + printf("%c%s%c", enabled ? '+' : '-', name, 0); + + if (enabled) { + + for (i = 0; i < 10; i++) { + gchar *n, *a; + + snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/name%i", name, i); + if (!(n = gconf_client_get_string(client, p, NULL)) || !*n) + break; + + snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/args%i", name, i); + a = gconf_client_get_string(client, p, NULL); + + printf("%s%c%s%c", n, 0, a ? a : "", 0); + + g_free(n); + g_free(a); + } + + printf("%c", 0); + } + + fflush(stdout); +} + +static void modules_callback( + GConfClient* client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data) { + + const char *n; + char buf[128]; + + g_assert(strncmp(entry->key, PA_GCONF_PATH_MODULES"/", sizeof(PA_GCONF_PATH_MODULES)) == 0); + + n = entry->key + sizeof(PA_GCONF_PATH_MODULES); + + g_strlcpy(buf, n, sizeof(buf)); + buf[strcspn(buf, "/")] = 0; + + handle_module(client, buf); +} + +int main(int argc, char *argv[]) { + GMainLoop *g; + GConfClient *client; + GSList *modules, *m; + + if (!(client = gconf_client_get_default())) + goto fail; + + gconf_client_add_dir(client, PA_GCONF_ROOT, GCONF_CLIENT_PRELOAD_RECURSIVE, NULL); + gconf_client_notify_add(client, PA_GCONF_PATH_MODULES, modules_callback, NULL, NULL, NULL); + + modules = gconf_client_all_dirs(client, PA_GCONF_PATH_MODULES, NULL); + + for (m = modules; m; m = m->next) { + char *e = strrchr(m->data, '/'); + handle_module(client, e ? e+1 : m->data); + } + + g_slist_free(modules); + + /* Signal the parent that we are now initialized */ + printf("!"); + fflush(stdout); + + g = g_main_loop_new(NULL, FALSE); + g_main_loop_run(g); + g_main_loop_unref(g); + + g_object_unref(G_OBJECT(client)); + + return 0; + +fail: + return 1; +} diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c new file mode 100644 index 000000000..30e6292e6 --- /dev/null +++ b/src/modules/gconf/module-gconf.c @@ -0,0 +1,386 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-gconf-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("GConf Adapter") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("") + +#define MAX_MODULES 10 +#define BUF_MAX 2048 + +#undef PA_GCONF_HELPER +#define PA_GCONF_HELPER "/home/lennart/projects/pulseaudio/src/gconf-helper" + +struct module_info { + char *name; + + unsigned n_indexes; + uint32_t indexes[MAX_MODULES]; +}; + +struct userdata { + pa_core *core; + pa_module *module; + + pa_hashmap *module_infos; + + pid_t pid; + + int fd; + int fd_type; + pa_io_event *io_event; + + char buf[BUF_MAX]; + size_t buf_fill; +}; + +static int fill_buf(struct userdata *u) { + ssize_t r; + assert(u); + + if (u->buf_fill >= BUF_MAX) { + pa_log(__FILE__": read buffer overflow"); + return -1; + } + + if ((r = pa_read(u->fd, u->buf + u->buf_fill, BUF_MAX - u->buf_fill, &u->fd_type)) <= 0) + return -1; + + u->buf_fill += r; + return 0; +} + +static int read_byte(struct userdata *u) { + int ret; + assert(u); + + if (u->buf_fill < 1) + if (fill_buf(u) < 0) + return -1; + + ret = u->buf[0]; + assert(u->buf_fill > 0); + u->buf_fill--; + memmove(u->buf, u->buf+1, u->buf_fill); + return ret; +} + +static char *read_string(struct userdata *u) { + assert(u); + + for (;;) { + char *e; + + if ((e = memchr(u->buf, 0, u->buf_fill))) { + char *ret = pa_xstrdup(u->buf); + u->buf_fill -= e - u->buf +1; + memmove(u->buf, e+1, u->buf_fill); + return ret; + } + + if (fill_buf(u) < 0) + return NULL; + } +} + +static void unload_modules(struct userdata *u, struct module_info*m) { + unsigned i; + + assert(u); + assert(m); + + for (i = 0; i < m->n_indexes; i++) { + pa_log_debug(__FILE__": Unloading module #%i", m->indexes[i]); + pa_module_unload_by_index(u->core, m->indexes[i]); + } + + m->n_indexes = 0; +} + +static void load_module( + struct userdata *u, + struct module_info *m, + const char *module, + const char *args) { + + pa_module *mod; + + assert(u); + assert(m); + assert(module); + + assert(m->n_indexes < MAX_MODULES); + + pa_log_debug(__FILE__": Loading module '%s' with args '%s' due to GConf configuration.", module, args); + + if (!(mod = pa_module_load(u->core, module, args))) { + pa_log(__FILE__": pa_module_load() failed"); + return; + } + + m->indexes[m->n_indexes++] = mod->index; +} + +static void module_info_free(void *p, void *userdata) { + struct module_info *m = p; + struct userdata *u = userdata; + + assert(m); + assert(u); + + unload_modules(u, m); + pa_xfree(m->name); + pa_xfree(m); +} + +static int handle_event(struct userdata *u) { + int opcode; + int ret = 0; + + do { + if ((opcode = read_byte(u)) < 0) + goto fail; + + switch (opcode) { + case '!': + /* The helper tool is now initialized */ + ret = 1; + break; + + case '+': { + char *name; + struct module_info *m; + + if (!(name = read_string(u))) + goto fail; + + if ((m = pa_hashmap_get(u->module_infos, name))) { + unload_modules(u, m); + } else { + m = pa_xnew(struct module_info, 1); + m->name = pa_xstrdup(name); + m->n_indexes = 0; + pa_hashmap_put(u->module_infos, m->name, m); + } + + while (m->n_indexes < MAX_MODULES) { + char *module, *args; + + if (!(module = read_string(u))) { + pa_xfree(name); + goto fail; + } + + if (!*module) { + pa_xfree(module); + break; + } + + if (!(args = read_string(u))) { + pa_xfree(name); + pa_xfree(module); + goto fail; + } + + load_module(u, m, module, args); + + pa_xfree(module); + pa_xfree(args); + } + + pa_xfree(name); + + break; + } + + case '-': { + char *name; + struct module_info *m; + + if (!(name = read_string(u))) + goto fail; + + if ((m = pa_hashmap_get(u->module_infos, name))) { + pa_hashmap_remove(u->module_infos, name); + module_info_free(m, u); + } + + pa_xfree(name); + + break; + } + } + } while (u->buf_fill > 0 && ret == 0); + + return ret; + +fail: + pa_log(__FILE__": Unable to read or parse data from client."); + return -1; +} + +static void io_event_cb( + pa_mainloop_api*a, + pa_io_event* e, + int fd, + pa_io_event_flags_t events, + void *userdata) { + + struct userdata *u = userdata; + + handle_event(u); +} + +static int start_client(const char *n, pid_t *pid) { + pid_t child; + int pipe_fds[2] = { -1, -1 }; + + if (pipe(pipe_fds) < 0) { + pa_log(__FILE__": pipe() failed: %s", pa_cstrerror(errno)); + goto fail; + } + + if ((child = fork()) == (pid_t) -1) { + pa_log(__FILE__": fork() failed: %s", pa_cstrerror(errno)); + goto fail; + } else if (child != 0) { + + /* Parent */ + close(pipe_fds[1]); + + if (pid) + *pid = child; + + return pipe_fds[0]; + } else { + + /* child */ + + close(pipe_fds[0]); + dup2(pipe_fds[1], 1); + + if (pipe_fds[1] != 1) + close(pipe_fds[1]); + + execl(n, n, NULL); + _exit(1); + } + +fail: + if (pipe_fds[0] >= 0) + close(pipe_fds[0]); + + if (pipe_fds[1] >= 0) + close(pipe_fds[1]); + + return -1; +} + +int pa__init(pa_core *c, pa_module*m) { + struct userdata *u; + int r; + + u = pa_xnew(struct userdata, 1); + u->core = c; + u->module = m; + u->module_infos = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + u->pid = (pid_t) -1; + u->fd = -1; + u->fd_type = 0; + u->io_event = NULL; + u->buf_fill = 0; + + if ((u->fd = start_client(PA_GCONF_HELPER, &u->pid)) < 0) + goto fail; + + u->io_event = c->mainloop->io_new( + c->mainloop, + u->fd, + PA_IO_EVENT_INPUT, + io_event_cb, + u); + + do { + if ((r = handle_event(u)) < 0) + goto fail; + + /* Read until the client signalled us that it is ready with + * initialization */ + } while (r != 1); + + return 0; + +fail: + pa__done(c, m); + return -1; +} + +void pa__done(pa_core *c, pa_module*m) { + struct userdata *u; + + assert(c); + assert(m); + + if (!(u = m->userdata)) + return; + + if (u->io_event) + c->mainloop->io_free(u->io_event); + + if (u->fd >= 0) + close(u->fd); + + if (u->pid != (pid_t) -1) { + kill(u->pid, SIGTERM); + waitpid(u->pid, NULL, 0); + } + + if (u->module_infos) + pa_hashmap_free(u->module_infos, module_info_free, u); + + pa_xfree(u); +} + From f5d29acdeb1e6412af3d2c9f761f329be36366d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Jul 2006 17:46:51 +0000 Subject: [PATCH 1051/1514] add missing configure.ac checks for module-gconf git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1151 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6cfbcf183..e6b09c539 100644 --- a/configure.ac +++ b/configure.ac @@ -453,6 +453,37 @@ AC_SUBST(GLIB20_LIBS) AC_SUBST(HAVE_GLIB20) AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1]) +#### GConf support (optional) #### + +AC_ARG_ENABLE([gconf], + AC_HELP_STRING([--disable-gconf], [Disable optional GConf support]), + [ + case "${enableval}" in + yes) gconf=yes ;; + no) gconf=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-gconf) ;; + esac + ], + [glib=auto]) + +if test "x${gconf}" != xno ; then + PKG_CHECK_MODULES(GCONF, [ gconf-2.0 >= 2.4.0 ], + HAVE_GCONF=1, + [ + HAVE_GCONF=0 + if test "x$gconf" = xyes ; then + AC_MSG_ERROR([*** GConf support not found]) + fi + ]) +else + HAVE_GCONF=0 +fi + +AC_SUBST(GCONF_CFLAGS) +AC_SUBST(GCONF_LIBS) +AC_SUBST(HAVE_GCONF) +AM_CONDITIONAL([HAVE_GCONF], [test "x$HAVE_GCONF" = x1]) + #### Avahi support (optional) #### AC_ARG_ENABLE([avahi], @@ -724,6 +755,11 @@ if test "x$HAVE_GLIB20" = "x1" ; then ENABLE_GLIB20=yes fi +ENABLE_GCONF=no +if test "x$HAVE_GCONF" = "x1" ; then + ENABLE_GCONF=yes +fi + ENABLE_AVAHI=no if test "x$HAVE_AVAHI" = "x1" ; then ENABLE_AVAHI=yes @@ -762,7 +798,8 @@ echo " Enable OSS: ${ENABLE_OSS} Enable Alsa: ${ENABLE_ALSA} Enable Solaris: ${ENABLE_SOLARIS} - Enable Glib 2.0: ${ENABLE_GLIB20} + Enable GLib 2.0: ${ENABLE_GLIB20} + Enable GConf: ${ENABLE_GCONF} Enable Avahi: ${ENABLE_AVAHI} Enable Jack: ${ENABLE_JACK} Enable Async DNS: ${ENABLE_LIBASYNCNS} From b2ad9a9753d9d5e69192a620b714f7e32a31e574 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Jul 2006 18:28:31 +0000 Subject: [PATCH 1052/1514] add some protection that the gconf helper process will be killed when the daemon process dies. make sure the gconf helper process doesn't keep open file descriptors belonging to the daemon; if gconf helper path git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1152 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 58 +++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index 30e6292e6..c6f83f6d5 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -31,6 +31,14 @@ #include #include #include +#include + +#ifdef HAVE_SYS_PRCTL_H +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif #include #include @@ -51,8 +59,8 @@ PA_MODULE_USAGE("") #define MAX_MODULES 10 #define BUF_MAX 2048 -#undef PA_GCONF_HELPER -#define PA_GCONF_HELPER "/home/lennart/projects/pulseaudio/src/gconf-helper" +/* #undef PA_GCONF_HELPER */ +/* #define PA_GCONF_HELPER "/home/lennart/projects/pulseaudio/src/gconf-helper" */ struct module_info { char *name; @@ -271,7 +279,15 @@ static void io_event_cb( struct userdata *u = userdata; - handle_event(u); + if (handle_event(u) < 0) { + + if (u->io_event) { + u->core->mainloop->io_free(u->io_event); + u->io_event = NULL; + } + + pa_module_unload_request(u->module); + } } static int start_client(const char *n, pid_t *pid) { @@ -296,7 +312,8 @@ static int start_client(const char *n, pid_t *pid) { return pipe_fds[0]; } else { - + int max_fd, i; + /* child */ close(pipe_fds[0]); @@ -305,6 +322,39 @@ static int start_client(const char *n, pid_t *pid) { if (pipe_fds[1] != 1) close(pipe_fds[1]); + close(0); + open("/dev/null", O_RDONLY); + + close(2); + open("/dev/null", O_WRONLY); + + max_fd = 1024; + +#ifdef HAVE_SYS_RESOURCE_H + { + struct rlimit r; + if (getrlimit(RLIMIT_NOFILE, &r) == 0) + max_fd = r.rlim_max; + } +#endif + + for (i = 3; i < max_fd; i++) + close(i); + +#ifdef PR_SET_PDEATHSIG + /* On Linux we can use PR_SET_PDEATHSIG to have the helper + process killed when the daemon dies abnormally. On non-Linux + machines the client will die as soon as it writes data to + stdout again (SIGPIPE) */ + + prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); +#endif + +#ifdef SIGPIPE + /* Make sure that SIGPIPE kills the child process */ + signal(SIGPIPE, SIG_DFL); +#endif + execl(n, n, NULL); _exit(1); } From 0d7be3148e872d0d2a68ecd740a596a3bcf4db5a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Jul 2006 22:39:06 +0000 Subject: [PATCH 1053/1514] mainloop fixes: when disabling time events when dispatching them, make sure to adjust the cache time event and enabled time event counters git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1153 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/glib-mainloop.c | 7 ++++++- src/pulse/mainloop.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/pulse/glib-mainloop.c b/src/pulse/glib-mainloop.c index 767675526..201b6e236 100644 --- a/src/pulse/glib-mainloop.c +++ b/src/pulse/glib-mainloop.c @@ -573,7 +573,10 @@ static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callbac tvnow.tv_usec = now.tv_usec; if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) { - t->enabled = 0; + + /* Disable time event */ + glib_time_restart(t, NULL); + t->callback(&g->api, t, &t->timeval, t->userdata); return TRUE; } @@ -634,6 +637,8 @@ pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { g->n_enabled_defer_events = g->n_enabled_time_events = 0; g->io_events_please_scan = g->time_events_please_scan = g->defer_events_please_scan = 0; + + g->cached_next_time_event = NULL; g_source_attach(&g->source, g->context); g_source_set_can_recurse(&g->source, FALSE); diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 682b2ccd7..699c0ee76 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -766,7 +766,12 @@ static int dispatch_timeout(pa_mainloop *m) { if (pa_timeval_cmp(&e->timeval, &now) <= 0) { assert(e->callback); - e->enabled = 0; + /* Disable time event */ + mainloop_time_restart(e, NULL); + + if (m->cached_next_time_event == e) + m->cached_next_time_event = NULL; + e->callback(&m->api, e, &e->timeval, e->userdata); r++; From 358e577403f081efa1e838df58617a86c1eaacb7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Jul 2006 22:39:56 +0000 Subject: [PATCH 1054/1514] remove two superfluous lines git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1154 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/mainloop.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 699c0ee76..5aa727063 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -769,9 +769,6 @@ static int dispatch_timeout(pa_mainloop *m) { /* Disable time event */ mainloop_time_restart(e, NULL); - if (m->cached_next_time_event == e) - m->cached_next_time_event = NULL; - e->callback(&m->api, e, &e->timeval, e->userdata); r++; From 6afb61efdc53be232b345b293ac0cd8943966beb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Jul 2006 16:49:44 +0000 Subject: [PATCH 1055/1514] remove superfluous code git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1155 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/mainloop.c | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 5aa727063..5ebb9bc86 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -957,46 +957,3 @@ void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *use m->poll_func = poll_func; m->poll_func_userdata = userdata; } - - -#if 0 -void pa_mainloop_dump(pa_mainloop *m) { - assert(m); - - pa_log(__FILE__": Dumping mainloop sources START"); - - { - uint32_t idx = PA_IDXSET_INVALID; - pa_io_event *e; - for (e = pa_idxset_first(m->io_events, &idx); e; e = pa_idxset_next(m->io_events, &idx)) { - if (e->dead) - continue; - - pa_log(__FILE__": kind=io fd=%i events=%i callback=%p userdata=%p", e->fd, (int) e->events, (void*) e->callback, (void*) e->userdata); - } - } - { - uint32_t idx = PA_IDXSET_INVALID; - pa_defer_event *e; - for (e = pa_idxset_first(m->defer_events, &idx); e; e = pa_idxset_next(m->defer_events, &idx)) { - if (e->dead) - continue; - - pa_log(__FILE__": kind=defer enabled=%i callback=%p userdata=%p", e->enabled, (void*) e->callback, (void*) e->userdata); - } - } - { - uint32_t idx = PA_IDXSET_INVALID; - pa_time_event *e; - for (e = pa_idxset_first(m->time_events, &idx); e; e = pa_idxset_next(m->time_events, &idx)) { - if (e->dead) - continue; - - pa_log(__FILE__": kind=time enabled=%i time=%lu.%lu callback=%p userdata=%p", e->enabled, (unsigned long) e->timeval.tv_sec, (unsigned long) e->timeval.tv_usec, (void*) e->callback, (void*) e->userdata); - } - } - - pa_log(__FILE__": Dumping mainloop sources STOP"); - -} -#endif From 87d4f0bd93f7c1c9d31409b526505c3c21aa5a19 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Jul 2006 16:50:26 +0000 Subject: [PATCH 1056/1514] because gconf doesn't provide real transactions we emulate our own with a "locked" gconf key git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1156 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/gconf-helper.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/modules/gconf/gconf-helper.c b/src/modules/gconf/gconf-helper.c index c8b9b1445..724548175 100644 --- a/src/modules/gconf/gconf-helper.c +++ b/src/modules/gconf/gconf-helper.c @@ -35,12 +35,18 @@ static void handle_module(GConfClient *client, const char *name) { gchar p[1024]; - gboolean enabled; + gboolean enabled, locked; int i; + snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/locked", name); + locked = gconf_client_get_bool(client, p, FALSE); + + if (locked) + return; + snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/enabled", name); enabled = gconf_client_get_bool(client, p, FALSE); - + printf("%c%s%c", enabled ? '+' : '-', name, 0); if (enabled) { From fec7e9bec70364996a857b5f4e2cee01299ea59c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Jul 2006 16:51:20 +0000 Subject: [PATCH 1057/1514] if possible do not unload already loaded modules when the gconf settings change. instead try to reuse already loaded modules as much as possible git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1157 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 100 ++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 29 deletions(-) diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index c6f83f6d5..d524346c7 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -62,11 +62,17 @@ PA_MODULE_USAGE("") /* #undef PA_GCONF_HELPER */ /* #define PA_GCONF_HELPER "/home/lennart/projects/pulseaudio/src/gconf-helper" */ +struct module_item { + char *name; + char *args; + uint32_t index; +}; + struct module_info { char *name; - - unsigned n_indexes; - uint32_t indexes[MAX_MODULES]; + + struct module_item items[MAX_MODULES]; + unsigned n_items; }; struct userdata { @@ -134,42 +140,70 @@ static char *read_string(struct userdata *u) { } } -static void unload_modules(struct userdata *u, struct module_info*m) { +static void unload_one_module(struct userdata *u, struct module_info*m, unsigned i) { + assert(u); + assert(m); + assert(i < m->n_items); + + if (m->items[i].index == PA_INVALID_INDEX) + return; + + pa_log_debug(__FILE__": Unloading module #%i", m->items[i].index); + pa_module_unload_by_index(u->core, m->items[i].index); + m->items[i].index = PA_INVALID_INDEX; + pa_xfree(m->items[i].name); + pa_xfree(m->items[i].args); + m->items[i].name = m->items[i].args = NULL; +} + +static void unload_all_modules(struct userdata *u, struct module_info*m) { unsigned i; assert(u); assert(m); - for (i = 0; i < m->n_indexes; i++) { - pa_log_debug(__FILE__": Unloading module #%i", m->indexes[i]); - pa_module_unload_by_index(u->core, m->indexes[i]); - } + for (i = 0; i < m->n_items; i++) + unload_one_module(u, m, i); - m->n_indexes = 0; + m->n_items = 0; } static void load_module( struct userdata *u, struct module_info *m, - const char *module, - const char *args) { + int i, + const char *name, + const char *args, + int is_new) { pa_module *mod; assert(u); assert(m); - assert(module); + assert(name); + assert(args); - assert(m->n_indexes < MAX_MODULES); + if (!is_new) { + if (m->items[i].index != PA_INVALID_INDEX && + strcmp(m->items[i].name, name) == 0 && + strcmp(m->items[i].args, args) == 0) + return; - pa_log_debug(__FILE__": Loading module '%s' with args '%s' due to GConf configuration.", module, args); + unload_one_module(u, m, i); + } - if (!(mod = pa_module_load(u->core, module, args))) { + pa_log_debug(__FILE__": Loading module '%s' with args '%s' due to GConf configuration.", name, args); + + m->items[i].name = pa_xstrdup(name); + m->items[i].args = pa_xstrdup(args); + m->items[i].index = PA_INVALID_INDEX; + + if (!(mod = pa_module_load(u->core, name, args))) { pa_log(__FILE__": pa_module_load() failed"); return; } - m->indexes[m->n_indexes++] = mod->index; + m->items[i].index = mod->index; } static void module_info_free(void *p, void *userdata) { @@ -179,7 +213,7 @@ static void module_info_free(void *p, void *userdata) { assert(m); assert(u); - unload_modules(u, m); + unload_all_modules(u, m); pa_xfree(m->name); pa_xfree(m); } @@ -201,24 +235,25 @@ static int handle_event(struct userdata *u) { case '+': { char *name; struct module_info *m; + unsigned i, j; if (!(name = read_string(u))) goto fail; - if ((m = pa_hashmap_get(u->module_infos, name))) { - unload_modules(u, m); - } else { + if (!(m = pa_hashmap_get(u->module_infos, name))) { m = pa_xnew(struct module_info, 1); - m->name = pa_xstrdup(name); - m->n_indexes = 0; + m->name = name; + m->n_items = 0; pa_hashmap_put(u->module_infos, m->name, m); - } - - while (m->n_indexes < MAX_MODULES) { + } else + pa_xfree(name); + + i = 0; + while (i < MAX_MODULES) { char *module, *args; if (!(module = read_string(u))) { - pa_xfree(name); + if (i > m->n_items) m->n_items = i; goto fail; } @@ -228,18 +263,25 @@ static int handle_event(struct userdata *u) { } if (!(args = read_string(u))) { - pa_xfree(name); pa_xfree(module); + + if (i > m->n_items) m->n_items = i; goto fail; } - load_module(u, m, module, args); + load_module(u, m, i, module, args, i >= m->n_items); + + i++; pa_xfree(module); pa_xfree(args); } - pa_xfree(name); + /* Unload all removed modules */ + for (j = i; j < m->n_items; j++) + unload_one_module(u, m, j); + + m->n_items = i; break; } From 0dea2237ed0a75d5696de228e66cc492a4db2fe4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Jul 2006 18:02:59 +0000 Subject: [PATCH 1058/1514] introduce three virtual sink/source names: @DEFAULT_SINK@, @DEFAULT_SOURCE@, @DEFAULT_MONITOR@. Especially the latter is useful for connecting to the monitor source of the default sink. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1158 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/namereg.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index 0f35ed1c5..11c36c3a2 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -58,7 +58,13 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t char *n = NULL; int r; - assert(c && name && data); + assert(c); + assert(name); + assert(data); + + /* Don't allow registration of special names */ + if (*name == '@') + return NULL; if (!c->namereg) { c->namereg = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); @@ -118,11 +124,29 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int a assert(c); if (!name) { + if (type == PA_NAMEREG_SOURCE) name = pa_namereg_get_default_source_name(c); else if (type == PA_NAMEREG_SINK) name = pa_namereg_get_default_sink_name(c); - } + + } else if (strcmp(name, "@DEFAULT_SINK@") == 0) { + if (type == PA_NAMEREG_SINK) + name = pa_namereg_get_default_sink_name(c); + + } else if (strcmp(name, "@DEFAULT_SOURCE@") == 0) { + if (type == PA_NAMEREG_SOURCE) + name = pa_namereg_get_default_source_name(c); + + } else if (strcmp(name, "@DEFAULT_MONITOR@") == 0) { + if (type == PA_NAMEREG_SOURCE) { + pa_sink *k; + + if ((k = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, autoload))) + return k->monitor_source; + } + } else if (*name == '@') + name = NULL; if (!name) return NULL; From c21f88cb9020caca5a45a6c899d9d0a66b0d3200 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Jul 2006 18:35:17 +0000 Subject: [PATCH 1059/1514] load module-gconf in default install git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1159 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/default.pa.in | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index ac10c0ca3..ef6048d6a 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -39,9 +39,11 @@ load-module module-detect ### Load several protocols load-module module-esound-protocol-unix -#load-module module-esound-protocol-tcp load-module module-native-protocol-unix + +#load-module module-esound-protocol-tcp #load-module module-native-protocol-tcp +#load-module module-zeroconf-publish ### Load the RTP reciever module #load-module module-rtp-recv @@ -69,3 +71,7 @@ load-module module-x11-bell sample=x11-bell ### Publish connection data in the X11 root window load-module module-x11-publish +### Load additional modules from GConf settings. This can be configured with the paprefs tool. +### Please keep in mind that the modules configured by paprefs might conflict with manually +### loaded modules. +load-module module-gconf From ecd4655b873c6f103b151c3b53e94dfc9237b714 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Jul 2006 18:40:01 +0000 Subject: [PATCH 1060/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1160 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index d453b4d85..8d0105f59 100644 --- a/todo +++ b/todo @@ -29,7 +29,6 @@ Post 0.9.0: - gettextify polypaudio - drop dependency of libpolyp on libX11, instead use an external mini binary - "hot" moving of streams between sinks -- gconf module + frontend - hooks for creating sink inputs - insert the low-level device name in the default sink/source name, to make them recognizable - ssl From 12aa8421747fa3448fb4dce6adafa198181cb4ac Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 28 Jul 2006 22:52:28 +0000 Subject: [PATCH 1061/1514] introduce pa_play_memblockq() which creates a playback stream and passes the data from the memblockq to it. after that is done, frees the memblockq git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1161 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 + src/pulsecore/play-memblockq.c | 113 +++++++++++++++++++++++++++++++++ src/pulsecore/play-memblockq.h | 36 +++++++++++ 3 files changed, 151 insertions(+) create mode 100644 src/pulsecore/play-memblockq.c create mode 100644 src/pulsecore/play-memblockq.h diff --git a/src/Makefile.am b/src/Makefile.am index bb08ed785..48211e1f9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -497,6 +497,7 @@ pulsecoreinclude_HEADERS = \ pulsecore/namereg.h \ pulsecore/pid.h \ pulsecore/play-memchunk.h \ + pulsecore/play-memblockq.h \ pulsecore/props.h \ pulsecore/queue.h \ pulsecore/random.h \ @@ -558,6 +559,7 @@ libpulsecore_la_SOURCES += \ pulsecore/pid.c pulsecore/pid.h \ pulsecore/pipe.c pulsecore/pipe.h \ pulsecore/play-memchunk.c pulsecore/play-memchunk.h \ + pulsecore/play-memblockq.c pulsecore/play-memblockq.h \ pulsecore/poll.c pulsecore/poll.h \ pulsecore/props.c pulsecore/props.h \ pulsecore/queue.c pulsecore/queue.h \ diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c new file mode 100644 index 000000000..2df3b9523 --- /dev/null +++ b/src/pulsecore/play-memblockq.c @@ -0,0 +1,113 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include +#include + +#include "play-memblockq.h" + +static void sink_input_kill(pa_sink_input *i) { + pa_memblockq *q; + assert(i); + assert(i->userdata); + + q = i->userdata; + + pa_sink_input_disconnect(i); + pa_sink_input_unref(i); + + pa_memblockq_free(q); +} + +static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { + pa_memblockq *q; + assert(i); + assert(chunk); + assert(i->userdata); + + q = i->userdata; + + return pa_memblockq_peek(q, chunk); +} + +static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) { + sink_input_kill(i); +} + +static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) { + pa_memblockq *q; + + assert(i); + assert(length > 0); + assert( i->userdata); + + q = i->userdata; + + pa_memblockq_drop(q, chunk, length); + + if (pa_memblockq_get_length(q) <= 0) + pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); +} + +int pa_play_memblockq( + pa_sink *sink, + const char *name, + const pa_sample_spec *ss, + const pa_channel_map *map, + pa_memblockq *q, + pa_cvolume *cvolume) { + + pa_sink_input *si; + + assert(sink); + assert(ss); + assert(q); + + if (pa_memblockq_get_length(q) <= 0) + return 0; + + if (cvolume && pa_cvolume_is_muted(cvolume)) + return 0; + + if (!(si = pa_sink_input_new(sink, name, __FILE__, ss, map, cvolume, 0, PA_RESAMPLER_INVALID))) + return -1; + + si->peek = sink_input_peek; + si->drop = sink_input_drop; + si->kill = sink_input_kill; + + si->userdata = q; + + pa_sink_notify(sink); + + return 0; +} diff --git a/src/pulsecore/play-memblockq.h b/src/pulsecore/play-memblockq.h new file mode 100644 index 000000000..9b96efe36 --- /dev/null +++ b/src/pulsecore/play-memblockq.h @@ -0,0 +1,36 @@ +#ifndef fooplaymemblockqhfoo +#define fooplaymemblockqhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +int pa_play_memblockq( + pa_sink *sink, + const char *name, + const pa_sample_spec *ss, + const pa_channel_map *map, + pa_memblockq *q, + pa_cvolume *cvolume); + +#endif From f1c46113ae4b0eedd291907d187f5ed39f29104d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 28 Jul 2006 23:27:16 +0000 Subject: [PATCH 1062/1514] fold the seperate variable pa_sink_input::playing into pa_sink_input::state as state PA_SINK_INPUT_DRAINED. The following mappings hold: old PA_SINK_RUNNING + playing set = new PA_SINK_RUNNING old PA_SINK_RUNNING + playing not set = new PA_SINK_DRAINED git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1162 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sink-input.c | 24 ++++++++++++++---------- src/pulsecore/sink-input.h | 9 ++++----- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 8590a0b1d..5613b15e1 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -94,7 +94,7 @@ pa_sink_input* pa_sink_input_new( i = pa_xnew(pa_sink_input, 1); i->ref = 1; - i->state = PA_SINK_INPUT_RUNNING; + i->state = PA_SINK_INPUT_DRAINED; i->name = pa_xstrdup(name); i->driver = pa_xstrdup(driver); i->owner = NULL; @@ -112,8 +112,6 @@ pa_sink_input* pa_sink_input_new( i->underrun = NULL; i->userdata = NULL; - i->playing = 0; - pa_memchunk_reset(&i->resampled_chunk); i->resampler = resampler; @@ -149,7 +147,6 @@ void pa_sink_input_disconnect(pa_sink_input *i) { i->get_latency = NULL; i->underrun = NULL; - i->playing = 0; i->state = PA_SINK_INPUT_DISCONNECTED; } @@ -225,6 +222,8 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) if (!i->peek || !i->drop || i->state == PA_SINK_INPUT_CORKED) goto finish; + assert(i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED); + if (!i->resampler) { do_volume_adj_here = 0; ret = i->peek(i, chunk); @@ -270,10 +269,13 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) finish: - if (ret < 0 && i->playing && i->underrun) + if (ret < 0 && i->state == PA_SINK_INPUT_RUNNING && i->underrun) i->underrun(i); - i->playing = ret >= 0; + if (ret >= 0) + i->state = PA_SINK_INPUT_RUNNING; + else if (ret < 0 && i->state == PA_SINK_INPUT_RUNNING) + i->state = PA_SINK_INPUT_DRAINED; if (ret >= 0) { /* Let's see if we had to apply the volume adjustment @@ -342,12 +344,14 @@ void pa_sink_input_cork(pa_sink_input *i, int b) { assert(i); assert(i->ref >= 1); - if (i->state == PA_SINK_INPUT_DISCONNECTED) - return; + assert(i->state != PA_SINK_INPUT_DISCONNECTED); n = i->state == PA_SINK_INPUT_CORKED && !b; - - i->state = b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING; + + if (b) + i->state = PA_SINK_INPUT_CORKED; + else if (i->state == PA_SINK_INPUT_CORKED) + i->state = PA_SINK_INPUT_DRAINED; if (n) pa_sink_notify(i->sink); diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 69a7e50a1..60105d31a 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -34,9 +34,10 @@ typedef struct pa_sink_input pa_sink_input; #include typedef enum pa_sink_input_state { - PA_SINK_INPUT_RUNNING, - PA_SINK_INPUT_CORKED, - PA_SINK_INPUT_DISCONNECTED + PA_SINK_INPUT_RUNNING, /*< The stream is alive and kicking */ + PA_SINK_INPUT_DRAINED, /*< The stream stopped playing because there was no data to play */ + PA_SINK_INPUT_CORKED, /*< The stream was corked on user request */ + PA_SINK_INPUT_DISCONNECTED /*< The stream is dead */ } pa_sink_input_state_t; struct pa_sink_input { @@ -63,8 +64,6 @@ struct pa_sink_input { void *userdata; - int playing; - pa_memchunk resampled_chunk; pa_resampler *resampler; }; From d1db0375771636a2f43e5c016afe181da5cb8008 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 28 Jul 2006 23:29:37 +0000 Subject: [PATCH 1063/1514] for the playing field of pa_timing_info use pa_sink_input::state == PA_SINK_INPUT_RUNNING. This means that this variable will now refer to the current state and not to the expected future state, which is probably more what clients expect. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1163 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-native.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 9023adde2..d2268a5a6 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1101,7 +1101,7 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct_put_usec(reply, latency); pa_tagstruct_put_usec(reply, 0); - pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq)); + pa_tagstruct_put_boolean(reply, s->sink_input->state == PA_SINK_INPUT_RUNNING); pa_tagstruct_put_timeval(reply, &tv); pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now)); pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq)); From b325e07c7337a533792aac2d19ac6ff364c92fb6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 15:02:24 +0000 Subject: [PATCH 1064/1514] handle EOF correctly if it is read before the stream was created git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1164 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacat.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 10edd71d7..dda5c1929 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -291,18 +291,22 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even if ((r = read(fd, buffer, l)) <= 0) { if (r == 0) { - pa_operation *o; - if (verbose) fprintf(stderr, "Got EOF.\n"); - - if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { - fprintf(stderr, "pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(context))); - quit(1); - return; - } - pa_operation_unref(o); + if (stream) { + pa_operation *o; + + if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { + fprintf(stderr, "pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(context))); + quit(1); + return; + } + + pa_operation_unref(o); + } else + quit(0); + } else { fprintf(stderr, "read() failed: %s\n", strerror(errno)); quit(1); From 9310a2e3b88286fdb60f52c4b8a8c51848ffca53 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 15:02:53 +0000 Subject: [PATCH 1065/1514] fix calculation of pa_usec_to_bytes, to make sure that it never returns fractions of a frame size git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1165 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/sample.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulse/sample.c b/src/pulse/sample.c index 2e055bf1b..87b2d7a06 100644 --- a/src/pulse/sample.c +++ b/src/pulse/sample.c @@ -70,7 +70,7 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) { size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) { assert(spec); - return ((double) t * spec->rate / 1000000)*pa_frame_size(spec); + return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec); } int pa_sample_spec_valid(const pa_sample_spec *spec) { From f15b4c7c704292ee88ae05919adc88a2765684cf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 15:03:26 +0000 Subject: [PATCH 1066/1514] if the memblockq is empty, return -1 in all cases git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1166 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/memblockq.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index ff199f1bd..822bd66cd 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -368,6 +368,12 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { chunk->length = length; } else { + + /* If the memblockq is empty, return -1, otherwise return + * the time to sleep */ + if (!bq->blocks) + return -1; + chunk->memblock = NULL; chunk->length = length; } From 4dd3b31825aa3feeea4d1cf6cfeee2b48a945f7c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 15:04:17 +0000 Subject: [PATCH 1067/1514] free the memblockq if we decide not to play it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1167 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/play-memblockq.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c index 2df3b9523..7b796a8d8 100644 --- a/src/pulsecore/play-memblockq.c +++ b/src/pulsecore/play-memblockq.c @@ -92,11 +92,15 @@ int pa_play_memblockq( assert(ss); assert(q); - if (pa_memblockq_get_length(q) <= 0) + if (pa_memblockq_get_length(q) <= 0) { + pa_memblockq_free(q); return 0; + } - if (cvolume && pa_cvolume_is_muted(cvolume)) + if (cvolume && pa_cvolume_is_muted(cvolume)) { + pa_memblockq_free(q); return 0; + } if (!(si = pa_sink_input_new(sink, name, __FILE__, ss, map, cvolume, 0, PA_RESAMPLER_INVALID))) return -1; From 5e9295037f073fc768c1011253685ef35dba6331 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 15:06:49 +0000 Subject: [PATCH 1068/1514] * implement "hot" moving of playback streams between sinks (pa_sink_input_move_to()). * optimize the adjusting of the volume in pa_sink_input_peek() a little git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1168 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sink-input.c | 231 ++++++++++++++++++++++++++++++++++++- src/pulsecore/sink-input.h | 14 ++- 2 files changed, 239 insertions(+), 6 deletions(-) diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 5613b15e1..8280d0bf3 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -34,10 +34,13 @@ #include #include #include +#include #include "sink-input.h" #define CONVERT_BUFFER_LENGTH 4096 +#define MOVE_BUFFER_LENGTH (1024*1024) +#define SILENCE_BUFFER_LENGTH (64*1024) #define CHECK_VALIDITY_RETURN_NULL(condition) \ do {\ @@ -89,9 +92,11 @@ pa_sink_input* pa_sink_input_new( resample_method = s->core->resample_method; if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec) || !pa_channel_map_equal(map, &s->channel_map)) - if (!(resampler = pa_resampler_new(spec, map, &s->sample_spec, &s->channel_map, s->core->memblock_stat, resample_method))) + if (!(resampler = pa_resampler_new(spec, map, &s->sample_spec, &s->channel_map, s->core->memblock_stat, resample_method))) { + pa_log_warn(__FILE__": Unsupported resampling operation."); return NULL; - + } + i = pa_xnew(pa_sink_input, 1); i->ref = 1; i->state = PA_SINK_INPUT_DRAINED; @@ -111,9 +116,14 @@ pa_sink_input* pa_sink_input_new( i->get_latency = NULL; i->underrun = NULL; i->userdata = NULL; + i->move_silence = 0; pa_memchunk_reset(&i->resampled_chunk); i->resampler = resampler; + i->resample_method = resample_method; + i->variable_rate = variable_rate; + + i->silence_memblock = NULL; assert(s->core); r = pa_idxset_put(s->core->sink_inputs, i, &i->index); @@ -125,7 +135,8 @@ pa_sink_input* pa_sink_input_new( pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"", i->index, i->name, s->index, st); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); - + pa_sink_notify(i->sink); + return i; } @@ -164,6 +175,9 @@ static void sink_input_free(pa_sink_input* i) { if (i->resampler) pa_resampler_free(i->resampler); + if (i->silence_memblock) + pa_memblock_unref(i->silence_memblock); + pa_xfree(i->name); pa_xfree(i->driver); pa_xfree(i); @@ -203,7 +217,10 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) { r += i->get_latency(i); if (i->resampled_chunk.memblock) - r += pa_bytes_to_usec(i->resampled_chunk.length, &i->sample_spec); + r += pa_bytes_to_usec(i->resampled_chunk.length, &i->sink->sample_spec); + + if (i->move_silence) + r += pa_bytes_to_usec(i->move_silence, &i->sink->sample_spec); return r; } @@ -211,6 +228,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) { int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) { int ret = -1; int do_volume_adj_here; + int volume_is_norm; assert(i); assert(i->ref >= 1); @@ -223,6 +241,23 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) goto finish; assert(i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED); + + if (i->move_silence > 0) { + + /* We have just been moved and shall play some silence for a + * while until the old sink has drained its playback buffer */ + + if (!i->silence_memblock) + i->silence_memblock = pa_silence_memblock_new(&i->sink->sample_spec, SILENCE_BUFFER_LENGTH, i->sink->core->memblock_stat); + + chunk->memblock = pa_memblock_ref(i->silence_memblock); + chunk->index = 0; + chunk->length = i->move_silence < chunk->memblock->length ? i->move_silence : chunk->memblock->length; + + ret = 0; + do_volume_adj_here = 1; + goto finish; + } if (!i->resampler) { do_volume_adj_here = 0; @@ -231,6 +266,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) } do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map); + volume_is_norm = pa_cvolume_is_norm(&i->volume); while (!i->resampled_chunk.memblock) { pa_memchunk tchunk; @@ -250,7 +286,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) tchunk.length = l; /* It might be necessary to adjust the volume here */ - if (do_volume_adj_here) { + if (do_volume_adj_here && !volume_is_norm) { pa_memchunk_make_writable(&tchunk, i->sink->core->memblock_stat, 0); pa_volume_memchunk(&tchunk, &i->sample_spec, &i->volume); } @@ -299,6 +335,30 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt assert(i->ref >= 1); assert(length > 0); + if (i->move_silence > 0) { + + if (chunk) { + + if (chunk->memblock != i->silence_memblock || + chunk->index != 0 || + (chunk->memblock && (chunk->length != (i->silence_memblock->length < i->move_silence ? i->silence_memblock->length : i->move_silence)))) + return; + + } + + assert(i->move_silence >= length); + + i->move_silence -= length; + + if (i->move_silence <= 0) { + assert(i->silence_memblock); + pa_memblock_unref(i->silence_memblock); + i->silence_memblock = NULL; + } + + return; + } + if (!i->resampler) { if (i->drop) i->drop(i, chunk, length); @@ -367,6 +427,8 @@ void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) { i->sample_spec.rate = rate; pa_resampler_set_input_rate(i->resampler, rate); + + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); } void pa_sink_input_set_name(pa_sink_input *i, const char *name) { @@ -388,3 +450,162 @@ pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) { return pa_resampler_get_method(i->resampler); } + +int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { + pa_resampler *new_resampler = NULL; + pa_memblockq *buffer = NULL; + pa_sink *origin; + + assert(i); + assert(dest); + + origin = i->sink; + + if (dest == origin) + return 0; + + if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) { + pa_log_warn(__FILE__": Failed to move sink input: too many inputs per sink."); + return -1; + } + + if (i->resampler && + pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) && + pa_channel_map_equal(&origin->channel_map, &dest->channel_map)) + + /* Try to reuse the old resampler if possible */ + new_resampler = i->resampler; + + else if (i->variable_rate || + !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) || + !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) { + + /* Okey, we need a new resampler for the new sink */ + + if (!(new_resampler = pa_resampler_new( + &i->sample_spec, &i->channel_map, + &dest->sample_spec, &dest->channel_map, + dest->core->memblock_stat, + i->resample_method))) { + pa_log_warn(__FILE__": Unsupported resampling operation."); + return -1; + } + } + + if (!immediately) { + pa_usec_t old_latency, new_latency; + pa_usec_t silence_usec = 0; + + buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL, NULL); + + /* Let's do a little bit of Voodoo for compensating latency + * differences */ + + old_latency = pa_sink_get_latency(origin); + new_latency = pa_sink_get_latency(dest); + + /* The already resampled data should go to the old sink */ + + if (old_latency >= new_latency) { + + /* The latency of the old sink is larger than the latency + * of the new sink. Therefore to compensate for the + * difference we to play silence on the new one for a + * while */ + + silence_usec = old_latency - new_latency; + + } else { + size_t l; + int volume_is_norm; + + /* The latency of new sink is larger than the latency of + * the old sink. Therefore we have to precompute a little + * and make sure that this is still played on the old + * sink, until we can play the first sample on the new + * sink.*/ + + l = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec); + + volume_is_norm = pa_cvolume_is_norm(&i->volume); + + while (l > 0) { + pa_memchunk chunk; + pa_cvolume volume; + size_t n; + + if (pa_sink_input_peek(i, &chunk, &volume) < 0) + break; + + n = chunk.length > l ? l : chunk.length; + pa_sink_input_drop(i, &chunk, n); + chunk.length = n; + + if (!volume_is_norm) { + pa_memchunk_make_writable(&chunk, origin->core->memblock_stat, 0); + pa_volume_memchunk(&chunk, &origin->sample_spec, &volume); + } + + if (pa_memblockq_push(buffer, &chunk) < 0) { + pa_memblock_unref(chunk.memblock); + break; + } + + pa_memblock_unref(chunk.memblock); + l -= n; + } + } + + if (i->resampled_chunk.memblock) { + + /* There is still some data left in the already resampled + * memory block. Hence, let's output it on the old sink + * and sleep so long on the new sink */ + + pa_memblockq_push(buffer, &i->resampled_chunk); + silence_usec += pa_bytes_to_usec(i->resampled_chunk.length, &origin->sample_spec); + } + + /* Calculate the new sleeping time */ + i->move_silence = pa_usec_to_bytes( + pa_bytes_to_usec(i->move_silence, &i->sample_spec) + + silence_usec, + &i->sample_spec); + } + + /* Okey, let's move it */ + pa_idxset_remove_by_data(i->sink->inputs, i, NULL); + i->sink = dest; + pa_idxset_put(i->sink->inputs, i, NULL); + + /* Replace resampler */ + if (new_resampler != i->resampler) { + if (i->resampler) + pa_resampler_free(i->resampler); + i->resampler = new_resampler; + + /* if the resampler changed, the silence memblock is + * probably invalid now, too */ + if (i->silence_memblock) { + pa_memblock_unref(i->silence_memblock); + i->silence_memblock = NULL; + } + } + + /* Dump already resampled data */ + if (i->resampled_chunk.memblock) { + pa_memblock_unref(i->resampled_chunk.memblock); + i->resampled_chunk.memblock = NULL; + i->resampled_chunk.index = i->resampled_chunk.length = 0; + } + + /* Notify everyone */ + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); + pa_sink_notify(i->sink); + + /* Ok, no let's feed the precomputed buffer to the old sink */ + if (buffer) + pa_play_memblockq(origin, "Ghost Stream", &origin->sample_spec, &origin->channel_map, buffer, NULL); + + return 0; +} diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 60105d31a..b1971d0a9 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -55,6 +55,11 @@ struct pa_sink_input { pa_channel_map channel_map; pa_cvolume volume; + + /* Some silence to play before the actual data. This is used to + * compensate for latency differences when moving a sink input + * "hot" between sinks. */ + size_t move_silence; int (*peek) (pa_sink_input *i, pa_memchunk *chunk); void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length); @@ -66,6 +71,11 @@ struct pa_sink_input { pa_memchunk resampled_chunk; pa_resampler *resampler; + + int variable_rate; + pa_resample_method_t resample_method; + + pa_memblock *silence_memblock; }; pa_sink_input* pa_sink_input_new( @@ -76,7 +86,7 @@ pa_sink_input* pa_sink_input_new( const pa_channel_map *map, const pa_cvolume *volume, int variable_rate, - int resample_method); + pa_resample_method_t resample_method); void pa_sink_input_unref(pa_sink_input* i); pa_sink_input* pa_sink_input_ref(pa_sink_input* i); @@ -103,4 +113,6 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name); pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i); +int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately); + #endif From a1e8b0968b9637e9813c320e0d1ca63e5fedf8ba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 15:07:15 +0000 Subject: [PATCH 1069/1514] add new CLI function "move-sink-input" as wrapper around pa_sink_input_move_to() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1169 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/cli-command.c | 42 +++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 4ba3e0af3..f04c710bb 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -98,7 +98,7 @@ static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *b static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); - +static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); /* A method table for all available commands */ @@ -141,6 +141,7 @@ static const struct command commands[] = { { "remove-autoload-source", pa_cli_command_autoload_remove, "Remove autoload entry for a source (args: name)", 2}, { "dump", pa_cli_command_dump, "Dump daemon configuration", 1}, { "list-props", pa_cli_command_list_props, NULL, 1}, + { "move-sink-input", pa_cli_command_move_sink_input, "Move Sink input to another sink (args: index, sink)", 3}, { NULL, NULL, NULL, 0 } }; @@ -728,6 +729,44 @@ static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf return 0; } +static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { + const char *n, *k; + pa_sink_input *si; + pa_sink *sink; + uint32_t idx; + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n"); + return -1; + } + + if ((idx = parse_index(n)) == PA_IDXSET_INVALID) { + pa_strbuf_puts(buf, "Failed to parse index.\n"); + return -1; + } + + if (!(k = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a sink.\n"); + return -1; + } + + if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) { + pa_strbuf_puts(buf, "No sink input found with this index.\n"); + return -1; + } + + if (!(sink = pa_namereg_get(c, k, PA_NAMEREG_SINK, 1))) { + pa_strbuf_puts(buf, "No sink found by this name or index.\n"); + return -1; + } + + if (pa_sink_input_move_to(si, sink, 0) < 0) { + pa_strbuf_puts(buf, "Moved failed.\n"); + return -1; + } + return 0; +} + static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { pa_module *m; pa_sink *sink; @@ -835,7 +874,6 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G return 0; } - int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int *fail) { const char *cs; From a7cf5e0f2de5474b4a1131a4254a56229436b7f7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 15:34:36 +0000 Subject: [PATCH 1070/1514] fix two typos (pierre, have you been sleeping? next time please the comments wrong but the code right, not the other way round! ;-)) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1170 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/caps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/daemon/caps.c b/src/daemon/caps.c index 957824d98..8ae43fb2a 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -82,7 +82,7 @@ int pa_limit_caps(void) { cap_value_t nice_cap = CAP_SYS_NICE; /* Only drop caps when called SUID */ - if (getuid() != 0) + if (getuid() == 0) return 0; caps = cap_init(); @@ -112,7 +112,7 @@ int pa_drop_caps(void) { int r = -1; /* Only drop caps when called SUID */ - if (getuid() != 0) + if (getuid() == 0) return 0; caps = cap_init(); From 646deeaee69b2a3e5b3dedbf6bf4cccdd9255957 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 17:20:08 +0000 Subject: [PATCH 1071/1514] don't hit an assetr if there are operations outstanding when the pa_context is destroyed git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1171 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/operation.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pulse/operation.c b/src/pulse/operation.c index 24ddf69ff..8d896d7d9 100644 --- a/src/pulse/operation.c +++ b/src/pulse/operation.c @@ -76,6 +76,8 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) { if (st == o->state) return; + pa_operation_ref(o); + o->state = st; if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) { @@ -92,6 +94,8 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) { o->callback = NULL; o->userdata = NULL; } + + pa_operation_unref(o); } void pa_operation_cancel(pa_operation *o) { From d7ee1bcf758241d744002e3aea982295ce9e9247 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 29 Jul 2006 17:42:25 +0000 Subject: [PATCH 1072/1514] fix module-gconf initialization git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1172 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index d524346c7..a61295e06 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -418,6 +418,7 @@ int pa__init(pa_core *c, pa_module*m) { u = pa_xnew(struct userdata, 1); u->core = c; u->module = m; + m->userdata = u; u->module_infos = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); u->pid = (pid_t) -1; u->fd = -1; From e2e94ca47c5fc8b52ec28d9811a6da199a2c7262 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 31 Jul 2006 21:53:21 +0000 Subject: [PATCH 1073/1514] fix bad memory access if a non-existing entry shall be removed from a pa_idxset by index git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1173 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/idxset.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c index 5c79767df..23fe0b5a7 100644 --- a/src/pulsecore/idxset.c +++ b/src/pulsecore/idxset.c @@ -286,6 +286,9 @@ void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) { if (!(a = array_index(s, idx))) return NULL; + if (!*a) + return NULL; + data = (*a)->data; remove_entry(s, *a); From ccf67d2988521a8caf14ef1d650dcab4764462e4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 31 Jul 2006 21:53:48 +0000 Subject: [PATCH 1074/1514] deal properly with recursive module unloading git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1174 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/module.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index e7dca78d5..3568059e6 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -224,10 +224,14 @@ static void free_callback(void *p, PA_GCC_UNUSED void *userdata) { void pa_module_unload_all(pa_core *c) { assert(c); + pa_module *m; if (!c->modules) return; + while ((m = pa_idxset_first(c->modules, NULL))) + pa_module_unload(c, m); + pa_idxset_free(c->modules, free_callback, NULL); c->modules = NULL; From 304fcbb8435949fa6e94280040cbbea2c4fc43c0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 31 Jul 2006 21:54:20 +0000 Subject: [PATCH 1075/1514] add new commands opcode for moving sink inputs and source outputs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1175 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/native-common.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h index 5fdb6f427..785289eb1 100644 --- a/src/pulsecore/native-common.h +++ b/src/pulsecore/native-common.h @@ -108,6 +108,10 @@ enum { PA_COMMAND_RECORD_STREAM_KILLED, PA_COMMAND_SUBSCRIBE_EVENT, + /* A few more client->server commands */ + PA_COMMAND_MOVE_SINK_INPUT, + PA_COMMAND_MOVE_SOURCE_OUTPUT, + PA_COMMAND_MAX }; From 785477ba937e6850dff35d65e46e2b8a56bcc592 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 31 Jul 2006 21:54:46 +0000 Subject: [PATCH 1076/1514] add new native protocol function for moving sink inputs between sinks git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1176 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-native.c | 45 ++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index d2268a5a6..f14aa8730 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -189,6 +189,7 @@ static void command_get_autoload_info(pa_pdispatch *pd, uint32_t command, uint32 static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = NULL, @@ -257,7 +258,10 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_GET_AUTOLOAD_INFO] = command_get_autoload_info, [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = command_get_autoload_info_list, [PA_COMMAND_ADD_AUTOLOAD] = command_add_autoload, - [PA_COMMAND_REMOVE_AUTOLOAD] = command_remove_autoload + [PA_COMMAND_REMOVE_AUTOLOAD] = command_remove_autoload, + + [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream, + [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream }; /* structure management */ @@ -2109,6 +2113,45 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC pa_pstream_send_tagstruct(c->pstream, reply); } +static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + struct connection *c = userdata; + uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX; + pa_sink_input *si = NULL; + pa_sink *sink = NULL; + const char *name = NULL; + + assert(c); + assert(t); + + if (pa_tagstruct_getu32(t, &idx) < 0 || + pa_tagstruct_getu32(t, &idx_device) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); + + si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); + + if (idx_device != PA_INVALID_INDEX) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device); + else + sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); + + CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY); + + if (pa_sink_input_move_to(si, sink, 0) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); + return; + } + + pa_pstream_send_simple_ack(c->pstream, tag); +} + /*** pstream callbacks ***/ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { From bb9b08758e0eb1447f9891adccabda5334923b7b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 31 Jul 2006 21:55:09 +0000 Subject: [PATCH 1077/1514] wrap PA_COMMAND_MOVE_SINK_INPUT for libpulse git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1177 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/introspect.c | 48 ++++++++++++++++++++++++++++++++++++++++++ src/pulse/introspect.h | 5 +++++ 2 files changed, 53 insertions(+) diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c index ed40c53de..8aaf8b3f1 100644 --- a/src/pulse/introspect.c +++ b/src/pulse/introspect.c @@ -1238,3 +1238,51 @@ pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, p return o; } + +pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, char *sink_name, pa_context_success_cb_t cb, void* userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, sink_name && *sink_name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SINK_INPUT, &tag); + pa_tagstruct_putu32(t, idx); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, sink_name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, uint32_t sink_idx, pa_context_success_cb_t cb, void* userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, sink_idx != PA_INVALID_INDEX, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SINK_INPUT, &tag); + pa_tagstruct_putu32(t, idx); + pa_tagstruct_putu32(t, sink_idx); + pa_tagstruct_puts(t, NULL); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h index e9a144908..529945fda 100644 --- a/src/pulse/introspect.h +++ b/src/pulse/introspect.h @@ -484,6 +484,11 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name /** Remove an autoload entry. \since 0.6 */ pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata); +/** Move the specified sink input to a different sink. \since 0.9.5 */ +pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, char *sink_name, pa_context_success_cb_t cb, void* userdata); + +/** Move the specified sink input to a different sink. \since 0.9.5 */ +pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, uint32_t sink_idx, pa_context_success_cb_t cb, void* userdata); PA_C_DECL_END From bc30e2d9346edad2c8a755656e9aec803227bde1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 31 Jul 2006 21:55:42 +0000 Subject: [PATCH 1078/1514] add new "move-sink-input" command to pactl git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1178 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 25ef324d3..3674f950f 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -46,7 +46,8 @@ static pa_context *context = NULL; static pa_mainloop_api *mainloop_api = NULL; -static char *device = NULL, *sample_name = NULL; +static char *device = NULL, *sample_name = NULL, *sink_name = NULL; +static uint32_t sink_input_idx = PA_INVALID_INDEX; static SNDFILE *sndfile = NULL; static pa_stream *sample_stream = NULL; @@ -64,7 +65,8 @@ static enum { UPLOAD_SAMPLE, PLAY_SAMPLE, REMOVE_SAMPLE, - LIST + LIST, + MOVE_SINK_INPUT } action = NONE; static void quit(int ret) { @@ -581,6 +583,10 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_operation_unref(pa_context_get_autoload_info_list(c, get_autoload_info_callback, NULL)); break; + case MOVE_SINK_INPUT: + pa_operation_unref(pa_context_move_sink_input_by_name(c, sink_input_idx, sink_name, simple_callback, NULL)); + break; + default: assert(0); } @@ -609,12 +615,13 @@ static void help(const char *argv0) { "%s [options] exit\n" "%s [options] upload-sample FILENAME [NAME]\n" "%s [options] play-sample NAME [SINK]\n" + "%s [options] move-sink-input NAME [SINK]\n" "%s [options] remove-sample NAME\n\n" " -h, --help Show this help\n" " --version Show version\n\n" " -s, --server=SERVER The name of the server to connect to\n" " -n, --client-name=NAME How to call this client on the server\n", - argv0, argv0, argv0, argv0, argv0, argv0); + argv0, argv0, argv0, argv0, argv0, argv0, argv0); } enum { ARG_VERSION = 256 }; @@ -731,6 +738,15 @@ int main(int argc, char *argv[]) { } sample_name = pa_xstrdup(argv[optind+1]); + } else if (!strcmp(argv[optind], "move-sink-input")) { + action = MOVE_SINK_INPUT; + if (optind+2 >= argc) { + fprintf(stderr, "You have to specify a sink input index and a sink\n"); + goto quit; + } + + sink_input_idx = atoi(argv[optind+1]); + sink_name = pa_xstrdup(argv[optind+2]); } } @@ -784,6 +800,7 @@ quit: pa_xfree(server); pa_xfree(device); pa_xfree(sample_name); + pa_xfree(sink_name); return ret; } From 7f93d08d4014cc68965611068c47834c1e5547ef Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 1 Aug 2006 21:04:43 +0000 Subject: [PATCH 1079/1514] bump API and protocol version. Return PA_ERR_NOTSUPPORTED if pa_context_move_sink_input_by_*()is called for servers that don't support it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1179 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 ++-- src/pulse/def.h | 1 + src/pulse/introspect.c | 2 ++ src/utils/pacat.c | 2 +- src/utils/pactl.c | 2 +- src/utils/paplay.c | 2 +- todo | 2 +- 7 files changed, 9 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index e6b09c539..26fd860cb 100644 --- a/configure.ac +++ b/configure.ac @@ -33,8 +33,8 @@ AM_INIT_AUTOMAKE([foreign -Wall]) AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR") AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/]) -AC_SUBST(PA_API_VERSION, 9) -AC_SUBST(PA_PROTOCOL_VERSION, 9) +AC_SUBST(PA_API_VERSION, 10) +AC_SUBST(PA_PROTOCOL_VERSION, 10) AC_SUBST(LIBPULSE_VERSION_INFO, [0:2:0]) AC_SUBST(LIBPULSECORE_VERSION_INFO, [1:1:0]) diff --git a/src/pulse/def.h b/src/pulse/def.h index 01ed0f6d0..a22e3c190 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -161,6 +161,7 @@ enum { PA_ERR_NODATA, /**< No data */ PA_ERR_VERSION, /**< Incompatible protocol version \since 0.8 */ PA_ERR_TOOLARGE, /**< Data too large \since 0.8.1 */ + PA_ERR_NOTSUPPORTED, /**< Operation not supported \since 0.9.5 */ PA_ERR_MAX /**< Not really an error but the first invalid error code */ }; diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c index 8aaf8b3f1..d750bbdea 100644 --- a/src/pulse/introspect.c +++ b/src/pulse/introspect.c @@ -1248,6 +1248,7 @@ pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, ch assert(c->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); PA_CHECK_VALIDITY_RETURN_NULL(c, sink_name && *sink_name, PA_ERR_INVALID); @@ -1272,6 +1273,7 @@ pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, u assert(c->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); PA_CHECK_VALIDITY_RETURN_NULL(c, sink_idx != PA_INVALID_INDEX, PA_ERR_INVALID); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index dda5c1929..1c581f4d9 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -37,7 +37,7 @@ #define TIME_EVENT_USEC 50000 -#if PA_API_VERSION != 9 +#if PA_API_VERSION < 9 #error Invalid PulseAudio API version #endif diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 3674f950f..0fde33eb5 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -37,7 +37,7 @@ #include -#if PA_API_VERSION != 9 +#if PA_API_VERSION < 10 #error Invalid PulseAudio API version #endif diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 7b34016c5..0386c9df8 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -37,7 +37,7 @@ #include -#if PA_API_VERSION != 9 +#if PA_API_VERSION < 9 #error Invalid PulseAudio API version #endif diff --git a/todo b/todo index 8d0105f59..cdd8b8721 100644 --- a/todo +++ b/todo @@ -28,7 +28,7 @@ Post 0.9.0: - Document utf8.h, timeval.h and util.h - gettextify polypaudio - drop dependency of libpolyp on libX11, instead use an external mini binary -- "hot" moving of streams between sinks +- "hot" moving of recording streams between sources - hooks for creating sink inputs - insert the low-level device name in the default sink/source name, to make them recognizable - ssl From ddc69fccb5eec6ed546b1d2fe1771c383eeb5413 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Aug 2006 22:29:55 +0000 Subject: [PATCH 1080/1514] - don't call pa_sink_notify in pa_sink_input_new() because the virtual methods are not yet initialized at this time - some minor cleanups git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1180 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sink-input.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 8280d0bf3..b89210f4b 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -135,8 +135,10 @@ pa_sink_input* pa_sink_input_new( pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"", i->index, i->name, s->index, st); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); - pa_sink_notify(i->sink); + /* We do not call pa_sink_notify() here, because the virtual + * functions have not yet been initialized */ + return i; } @@ -446,7 +448,7 @@ pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) { assert(i->ref >= 1); if (!i->resampler) - return PA_RESAMPLER_INVALID; + return i->resample_method; return pa_resampler_get_method(i->resampler); } @@ -574,9 +576,9 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { } /* Okey, let's move it */ - pa_idxset_remove_by_data(i->sink->inputs, i, NULL); + pa_idxset_remove_by_data(origin->inputs, i, NULL); + pa_idxset_put(dest->inputs, i, NULL); i->sink = dest; - pa_idxset_put(i->sink->inputs, i, NULL); /* Replace resampler */ if (new_resampler != i->resampler) { From 2d00de58513fa069d4a8aabca0aa0be33eb37ce9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Aug 2006 22:30:45 +0000 Subject: [PATCH 1081/1514] Implement pa_source_input_move_to() for moving record streams between sources git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1181 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/source-output.c | 77 +++++++++++++++++++++++++++++++++-- src/pulsecore/source-output.h | 3 ++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 230b416d8..1ffaedae9 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -79,8 +79,10 @@ pa_source_output* pa_source_output_new( resample_method = s->core->resample_method; if (!pa_sample_spec_equal(&s->sample_spec, spec) || !pa_channel_map_equal(&s->channel_map, map)) - if (!(resampler = pa_resampler_new(&s->sample_spec, &s->channel_map, spec, map, s->core->memblock_stat, resample_method))) + if (!(resampler = pa_resampler_new(&s->sample_spec, &s->channel_map, spec, map, s->core->memblock_stat, resample_method))) { + pa_log_warn(__FILE__": Unsupported resampling operation."); return NULL; + } o = pa_xnew(pa_source_output, 1); o->ref = 1; @@ -100,6 +102,7 @@ pa_source_output* pa_source_output_new( o->userdata = NULL; o->resampler = resampler; + o->resample_method = resample_method; assert(s->core); r = pa_idxset_put(s->core->source_outputs, o, &o->index); @@ -111,6 +114,9 @@ pa_source_output* pa_source_output_new( pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"", o->index, o->name, s->index, st); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index); + + /* We do not call pa_source_notify() here, because the virtual + * functions have not yet been initialized */ return o; } @@ -166,7 +172,6 @@ pa_source_output* pa_source_output_ref(pa_source_output *o) { return o; } - void pa_source_output_kill(pa_source_output*o) { assert(o); assert(o->ref >= 1); @@ -221,13 +226,20 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) { } void pa_source_output_cork(pa_source_output *o, int b) { + int n; + assert(o); assert(o->ref >= 1); if (o->state == PA_SOURCE_OUTPUT_DISCONNECTED) return; + + n = o->state == PA_SOURCE_OUTPUT_CORKED && !b; o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING; + + if (n) + pa_source_notify(o->source); } pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) { @@ -235,7 +247,66 @@ pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) { assert(o->ref >= 1); if (!o->resampler) - return PA_RESAMPLER_INVALID; + return o->resample_method; return pa_resampler_get_method(o->resampler); } + +int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { + pa_source *origin; + pa_resampler *new_resampler; + + assert(o); + assert(o->ref >= 1); + assert(dest); + + origin = o->source; + + if (dest == origin) + return 0; + + if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { + pa_log_warn(__FILE__": Failed to move source output: too many outputs per source."); + return -1; + } + + if (o->resampler && + pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) && + pa_channel_map_equal(&origin->channel_map, &dest->channel_map)) + + /* Try to reuse the old resampler if possible */ + new_resampler = o->resampler; + + else if (!pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) || + !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) { + + /* Okey, we need a new resampler for the new sink */ + + if (!(new_resampler = pa_resampler_new( + &dest->sample_spec, &dest->channel_map, + &o->sample_spec, &o->channel_map, + dest->core->memblock_stat, + o->resample_method))) { + pa_log_warn(__FILE__": Unsupported resampling operation."); + return -1; + } + } + + /* Okey, let's move it */ + pa_idxset_remove_by_data(origin->outputs, o, NULL); + pa_idxset_put(dest->outputs, o, NULL); + o->source = dest; + + /* Replace resampler */ + if (new_resampler != o->resampler) { + if (o->resampler) + pa_resampler_free(o->resampler); + o->resampler = new_resampler; + } + + /* Notify everyone */ + pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); + pa_source_notify(o->source); + + return 0; +} diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index ef398dd1a..9a8ea92b5 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -58,6 +58,7 @@ struct pa_source_output { pa_usec_t (*get_latency) (pa_source_output *o); pa_resampler* resampler; + pa_resample_method_t resample_method; void *userdata; }; @@ -89,4 +90,6 @@ void pa_source_output_cork(pa_source_output *i, int b); pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o); +int pa_source_output_move_to(pa_source_output *o, pa_source *dest); + #endif From 1c45061fe1291e65620967d47cf7fc5258669d21 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Aug 2006 22:31:35 +0000 Subject: [PATCH 1082/1514] add new CLI command move-source-output as wrapper around pa_source_output_move_to() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1182 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/cli-command.c | 42 ++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index f04c710bb..f74258d3c 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -99,6 +99,7 @@ static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); /* A method table for all available commands */ @@ -141,7 +142,8 @@ static const struct command commands[] = { { "remove-autoload-source", pa_cli_command_autoload_remove, "Remove autoload entry for a source (args: name)", 2}, { "dump", pa_cli_command_dump, "Dump daemon configuration", 1}, { "list-props", pa_cli_command_list_props, NULL, 1}, - { "move-sink-input", pa_cli_command_move_sink_input, "Move Sink input to another sink (args: index, sink)", 3}, + { "move-sink-input", pa_cli_command_move_sink_input, "Move sink input to another sink (args: index, sink)", 3}, + { "move-source-output", pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3}, { NULL, NULL, NULL, 0 } }; @@ -767,6 +769,44 @@ static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } +static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { + const char *n, *k; + pa_source_output *so; + pa_source *source; + uint32_t idx; + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a source output by its index.\n"); + return -1; + } + + if ((idx = parse_index(n)) == PA_IDXSET_INVALID) { + pa_strbuf_puts(buf, "Failed to parse index.\n"); + return -1; + } + + if (!(k = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a source.\n"); + return -1; + } + + if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) { + pa_strbuf_puts(buf, "No source output found with this index.\n"); + return -1; + } + + if (!(source = pa_namereg_get(c, k, PA_NAMEREG_SOURCE, 1))) { + pa_strbuf_puts(buf, "No source found by this name or index.\n"); + return -1; + } + + if (pa_source_output_move_to(so, source) < 0) { + pa_strbuf_puts(buf, "Moved failed.\n"); + return -1; + } + return 0; +} + static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { pa_module *m; pa_sink *sink; From 5fdc39dc26c2691a8315de271d3f00fa257beff1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Aug 2006 22:32:23 +0000 Subject: [PATCH 1083/1514] wrap pa_source_output_move_to() in the native protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1183 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-native.c | 49 +++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index f14aa8730..d5a4cf459 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2116,8 +2116,6 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX; - pa_sink_input *si = NULL; - pa_sink *sink = NULL; const char *name = NULL; assert(c); @@ -2135,21 +2133,44 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); - si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); - - if (idx_device != PA_INVALID_INDEX) - sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device); - else - sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); - - CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY); + if (command == PA_COMMAND_MOVE_SINK_INPUT) { + pa_sink_input *si = NULL; + pa_sink *sink = NULL; - if (pa_sink_input_move_to(si, sink, 0) < 0) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); - return; + si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); + + if (idx_device != PA_INVALID_INDEX) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device); + else + sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); + + CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY); + + if (pa_sink_input_move_to(si, sink, 0) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); + return; + } + } else { + pa_source_output *so = NULL; + pa_source *source; + + so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx); + + if (idx_device != PA_INVALID_INDEX) + source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device); + else + source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); + + CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY); + + if (pa_source_output_move_to(so, source) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); + return; + } } - + pa_pstream_send_simple_ack(c->pstream, tag); + } /*** pstream callbacks ***/ From e52436b6c4ff50906b4fbf2e9e5cdb8fb2eb683b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Aug 2006 22:33:11 +0000 Subject: [PATCH 1084/1514] implement pa_context_move_source_output_by_{name,index}() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1184 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/introspect.c | 50 ++++++++++++++++++++++++++++++++++++++++++ src/pulse/introspect.h | 6 +++++ 2 files changed, 56 insertions(+) diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c index d750bbdea..b926e4e4d 100644 --- a/src/pulse/introspect.c +++ b/src/pulse/introspect.c @@ -1288,3 +1288,53 @@ pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, u return o; } + +pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, char *source_name, pa_context_success_cb_t cb, void* userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, source_name && *source_name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SOURCE_OUTPUT, &tag); + pa_tagstruct_putu32(t, idx); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, source_name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, source_idx != PA_INVALID_INDEX, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SOURCE_OUTPUT, &tag); + pa_tagstruct_putu32(t, idx); + pa_tagstruct_putu32(t, source_idx); + pa_tagstruct_puts(t, NULL); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h index 529945fda..28d22cd7e 100644 --- a/src/pulse/introspect.h +++ b/src/pulse/introspect.h @@ -490,6 +490,12 @@ pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, ch /** Move the specified sink input to a different sink. \since 0.9.5 */ pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, uint32_t sink_idx, pa_context_success_cb_t cb, void* userdata); +/** Move the specified source output to a different source. \since 0.9.5 */ +pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, char *source_name, pa_context_success_cb_t cb, void* userdata); + +/** Move the specified source output to a different source. \since 0.9.5 */ +pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata); + PA_C_DECL_END #endif From ad95c96a7278ac2e7d213e9575c2db1503d422fd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Aug 2006 22:33:54 +0000 Subject: [PATCH 1085/1514] implement "pactl move-source-output" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1185 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 0fde33eb5..f6f754986 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -46,8 +46,8 @@ static pa_context *context = NULL; static pa_mainloop_api *mainloop_api = NULL; -static char *device = NULL, *sample_name = NULL, *sink_name = NULL; -static uint32_t sink_input_idx = PA_INVALID_INDEX; +static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL; +static uint32_t sink_input_idx = PA_INVALID_INDEX, source_output_idx = PA_INVALID_INDEX; static SNDFILE *sndfile = NULL; static pa_stream *sample_stream = NULL; @@ -66,7 +66,8 @@ static enum { PLAY_SAMPLE, REMOVE_SAMPLE, LIST, - MOVE_SINK_INPUT + MOVE_SINK_INPUT, + MOVE_SOURCE_OUTPUT } action = NONE; static void quit(int ret) { @@ -587,6 +588,10 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_operation_unref(pa_context_move_sink_input_by_name(c, sink_input_idx, sink_name, simple_callback, NULL)); break; + case MOVE_SOURCE_OUTPUT: + pa_operation_unref(pa_context_move_source_output_by_name(c, source_output_idx, source_name, simple_callback, NULL)); + break; + default: assert(0); } @@ -615,7 +620,8 @@ static void help(const char *argv0) { "%s [options] exit\n" "%s [options] upload-sample FILENAME [NAME]\n" "%s [options] play-sample NAME [SINK]\n" - "%s [options] move-sink-input NAME [SINK]\n" + "%s [options] move-sink-input ID SINK\n" + "%s [options] move-source-output ID SOURCE\n" "%s [options] remove-sample NAME\n\n" " -h, --help Show this help\n" " --version Show version\n\n" @@ -747,6 +753,15 @@ int main(int argc, char *argv[]) { sink_input_idx = atoi(argv[optind+1]); sink_name = pa_xstrdup(argv[optind+2]); + } else if (!strcmp(argv[optind], "move-source-output")) { + action = MOVE_SOURCE_OUTPUT; + if (optind+2 >= argc) { + fprintf(stderr, "You have to specify a source output index and a source\n"); + goto quit; + } + + source_output_idx = atoi(argv[optind+1]); + source_name = pa_xstrdup(argv[optind+2]); } } @@ -801,6 +816,7 @@ quit: pa_xfree(device); pa_xfree(sample_name); pa_xfree(sink_name); + pa_xfree(source_name); return ret; } From f74e5ef8845b7b7e5ee39b1e0dae8ca7f6113eb8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Aug 2006 22:34:22 +0000 Subject: [PATCH 1086/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1186 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index cdd8b8721..5c2edf759 100644 --- a/todo +++ b/todo @@ -28,7 +28,6 @@ Post 0.9.0: - Document utf8.h, timeval.h and util.h - gettextify polypaudio - drop dependency of libpolyp on libX11, instead use an external mini binary -- "hot" moving of recording streams between sources - hooks for creating sink inputs - insert the low-level device name in the default sink/source name, to make them recognizable - ssl From 050b73912ca0e81a5740b65745d4ba1d450a66ab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 6 Aug 2006 16:16:50 +0000 Subject: [PATCH 1087/1514] merge HAL support from Shams E. King git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1187 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 37 +++ src/Makefile.am | 18 ++ src/modules/dbus-util.c | 354 +++++++++++++++++++++++ src/modules/dbus-util.h | 36 +++ src/modules/module-hal-detect.c | 495 ++++++++++++++++++++++++++++++++ 5 files changed, 940 insertions(+) create mode 100644 src/modules/dbus-util.c create mode 100644 src/modules/dbus-util.h create mode 100644 src/modules/module-hal-detect.c diff --git a/configure.ac b/configure.ac index 26fd860cb..bf7425c01 100644 --- a/configure.ac +++ b/configure.ac @@ -637,6 +637,37 @@ AC_SUBST(LIRC_CFLAGS) AC_SUBST(LIRC_LIBS) AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) +#### HAL support (optional) #### + +AC_ARG_ENABLE([hal], + AC_HELP_STRING([--disable-hal], [Disable optional HAL support]), + [ + case "${enableval}" in + yes) hal=yes ;; + no) hal=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-hal) ;; + esac + ], + [hal=auto]) + +if test "x${hal}" != xno ; then + PKG_CHECK_MODULES(HAL, [ hal >= 0.5.7 ], + HAVE_HAL=1, + [ + HAVE_HAL=0 + if test "x$hal" = xyes ; then + AC_MSG_ERROR([*** HAL support not found]) + fi + ]) +else + HAVE_HAL=0 +fi + +AC_SUBST(HAL_CFLAGS) +AC_SUBST(HAL_LIBS) +AC_SUBST(HAVE_HAL) +AM_CONDITIONAL([HAVE_HAL], [test "x$HAVE_HAL" = x1]) + #### PulseAudio system group & user ##### AC_ARG_WITH(system_user, AS_HELP_STRING([--with-system-user=],[User for running the PulseAudio daemon as a system-wide instance (pulse)])) @@ -780,6 +811,11 @@ if test "x$HAVE_LIRC" = "x1" ; then ENABLE_LIRC=yes fi +ENABLE_HAL=no +if test "x$HAVE_HAL" = "x1" ; then + ENABLE_HAL=yes +fi + ENABLE_TCPWRAP=no if test "x${LIBWRAP_LIBS}" != x ; then ENABLE_TCPWRAP=yes @@ -804,6 +840,7 @@ echo " Enable Jack: ${ENABLE_JACK} Enable Async DNS: ${ENABLE_LIBASYNCNS} Enable LIRC: ${ENABLE_LIRC} + Enable HAL: ${ENABLE_HAL} Enable TCP Wrappers: ${ENABLE_TCPWRAP} System User: ${PA_SYSTEM_USER} System Group: ${PA_SYSTEM_GROUP} diff --git a/src/Makefile.am b/src/Makefile.am index 48211e1f9..e0fae996e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -899,6 +899,12 @@ modlibexec_LTLIBRARIES += \ module-waveout.la endif +if HAVE_HAL +modlibexec_LTLIBRARIES += \ + libdbus-util.la \ + module-hal-detect.la +endif + # These are generated by a M4 script SYMDEF_FILES = \ @@ -942,6 +948,7 @@ SYMDEF_FILES = \ modules/module-jack-sink-symdef.h \ modules/module-jack-source-symdef.h \ modules/module-volume-restore-symdef.h \ + modules/module-hal-detect-symdef.h \ modules/gconf/module-gconf-symdef.h EXTRA_DIST += $(SYMDEF_FILES) @@ -1182,6 +1189,17 @@ module_jack_source_la_LDFLAGS = -module -avoid-version module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS) module_jack_source_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS) +# HAL +libdbus_util_la_SOURCES = modules/dbus-util.c modules/dbus-util.h +libdbus_util_la_LDFLAGS = -avoid-version +libdbus_util_la_LIBADD = $(AM_LIBADD) $(HAL_LIBS) libpulsecore.la +libdbus_util_la_CFLAGS = $(AM_CFLAGS) $(HAL_CFLAGS) + +module_hal_detect_la_SOURCES = modules/module-hal-detect.c +module_hal_detect_la_LDFLAGS = -module -avoid-version +module_hal_detect_la_LIBADD = $(AM_LIBADD) $(HAL_LIBS) libpulsecore.la libdbus-util.la +module_hal_detect_la_CFLAGS = $(AM_CFLAGS) $(HAL_CFLAGS) + # GConf support module_gconf_la_SOURCES = modules/gconf/module-gconf.c module_gconf_la_LDFLAGS = -module -avoid-version diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c new file mode 100644 index 000000000..0c9978e70 --- /dev/null +++ b/src/modules/dbus-util.c @@ -0,0 +1,354 @@ +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "dbus-util.h" + +struct pa_dbus_connection { + int refcount; + pa_core *core; + DBusConnection *connection; + const char *property_name; + pa_defer_event* dispatch_event; +}; + +static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata) +{ + DBusConnection *conn = (DBusConnection *) userdata; + if (dbus_connection_dispatch(conn) == DBUS_DISPATCH_COMPLETE) { + /* no more data to process, disable the deferred */ + ea->defer_enable(ev, 0); + } +} + +/* DBusDispatchStatusFunction callback for the pa mainloop */ +static void dispatch_status(DBusConnection *conn, DBusDispatchStatus status, + void *userdata) +{ + pa_dbus_connection *c = (pa_dbus_connection*) userdata; + switch(status) { + case DBUS_DISPATCH_COMPLETE: + c->core->mainloop->defer_enable(c->dispatch_event, 0); + break; + case DBUS_DISPATCH_DATA_REMAINS: + case DBUS_DISPATCH_NEED_MEMORY: + default: + c->core->mainloop->defer_enable(c->dispatch_event, 1); + break; + } +} + +static pa_io_event_flags_t +get_watch_flags(DBusWatch *watch) +{ + unsigned int flags = dbus_watch_get_flags(watch); + pa_io_event_flags_t events = PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR; + + /* no watch flags for disabled watches */ + if (!dbus_watch_get_enabled(watch)) + return PA_IO_EVENT_NULL; + + if (flags & DBUS_WATCH_READABLE) + events |= PA_IO_EVENT_INPUT; + if (flags & DBUS_WATCH_WRITABLE) + events |= PA_IO_EVENT_OUTPUT; + + return events; +} + +static void timeval_next(struct timeval *tv, int millint) +{ + /* number of seconds in the milli-second interval */ + tv->tv_sec += (millint / 1000); + /* milliseconds minus the seconds portion, converted to microseconds */ + tv->tv_usec += (millint - tv->tv_sec * 1000) * 1000; +} + +/* pa_io_event_cb_t IO event handler */ +static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, + int fd, pa_io_event_flags_t events, void *userdata) +{ + unsigned int flags = 0; + DBusWatch *watch = (DBusWatch*) userdata; + + assert(fd == dbus_watch_get_fd(watch)); + + if (!dbus_watch_get_enabled(watch)) { + pa_log_warn(__FILE__": Asked to handle disabled watch: %p %i", + (void *) watch, fd); + return; + } + + if (events & PA_IO_EVENT_INPUT) + flags |= DBUS_WATCH_READABLE; + if (events & PA_IO_EVENT_OUTPUT) + flags |= DBUS_WATCH_WRITABLE; + if (events & PA_IO_EVENT_HANGUP) + flags |= DBUS_WATCH_HANGUP; + if (events & PA_IO_EVENT_ERROR) + flags |= DBUS_WATCH_ERROR; + + dbus_watch_handle(watch, flags); +} + +/* pa_time_event_cb_t timer event handler */ +static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, + const struct timeval *tv, void *userdata) +{ + DBusTimeout *timeout = (DBusTimeout*) userdata; + + if (dbus_timeout_get_enabled(timeout)) { + struct timeval next = *tv; + dbus_timeout_handle(timeout); + + /* restart it for the next scheduled time */ + timeval_next(&next, dbus_timeout_get_interval(timeout)); + ea->time_restart(e, &next); + } +} + +/* DBusAddWatchFunction callback for pa mainloop */ +static dbus_bool_t add_watch(DBusWatch *watch, void *data) +{ + pa_io_event *ev; + pa_core *c = (pa_core*) data; + + ev = c->mainloop->io_new(c->mainloop, dbus_watch_get_fd(watch), + get_watch_flags(watch), + handle_io_event, (void*) watch); + if (NULL == ev) + return FALSE; + + /* dbus_watch_set_data(watch, (void*) ev, c->mainloop->io_free); */ + dbus_watch_set_data(watch, (void*) ev, NULL); + + return TRUE; +} + +/* DBusRemoveWatchFunction callback for pa mainloop */ +static void remove_watch(DBusWatch *watch, void *data) +{ + pa_core *c = (pa_core*) data; + pa_io_event *ev = (pa_io_event*) dbus_watch_get_data(watch); + + /* free the event */ + if (NULL != ev) + c->mainloop->io_free(ev); +} + +/* DBusWatchToggledFunction callback for pa mainloop */ +static void toggle_watch(DBusWatch *watch, void *data) +{ + pa_core *c = (pa_core*) data; + pa_io_event *ev = (pa_io_event*) dbus_watch_get_data(watch); + + /* get_watch_flags() checks if the watch is enabled */ + c->mainloop->io_enable(ev, get_watch_flags(watch)); +} + +/* DBusAddTimeoutFunction callback for pa mainloop */ +static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) +{ + struct timeval tv; + pa_time_event *ev; + pa_core *c = (pa_core*) data; + + if (!dbus_timeout_get_enabled(timeout)) + return FALSE; + + if (gettimeofday(&tv, NULL) < 0) + return -1; + + timeval_next(&tv, dbus_timeout_get_interval(timeout)); + + ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, + (void*) timeout); + if (NULL == ev) + return FALSE; + + /* dbus_timeout_set_data(timeout, (void*) ev, c->mainloop->time_free); */ + dbus_timeout_set_data(timeout, (void*) ev, NULL); + + return TRUE; +} + +/* DBusRemoveTimeoutFunction callback for pa mainloop */ +static void remove_timeout(DBusTimeout *timeout, void *data) +{ + pa_core *c = (pa_core*) data; + pa_time_event *ev = (pa_time_event*) dbus_timeout_get_data(timeout); + + /* free the event */ + if (NULL != ev) + c->mainloop->time_free(ev); +} + +/* DBusTimeoutToggledFunction callback for pa mainloop */ +static void toggle_timeout(DBusTimeout *timeout, void *data) +{ + struct timeval tv; + pa_core *c = (pa_core*) data; + pa_time_event *ev = (pa_time_event*) dbus_timeout_get_data(timeout); + + gettimeofday(&tv, NULL); + if (dbus_timeout_get_enabled(timeout)) { + timeval_next(&tv, dbus_timeout_get_interval(timeout)); + c->mainloop->time_restart(ev, &tv); + } else { + /* set it to expire one second ago */ + tv.tv_sec -= 1; + c->mainloop->time_restart(ev, &tv); + } +} + +static void +pa_dbus_connection_free(pa_dbus_connection *c) +{ + assert(c); + assert(!dbus_connection_get_is_connected(c->connection)); + + /* already disconnected, just free */ + pa_property_remove(c->core, c->property_name); + c->core->mainloop->defer_free(c->dispatch_event); + dbus_connection_unref(c->connection); + pa_xfree(c); +} + +static void +wakeup_main(void *userdata) +{ + pa_dbus_connection *c = (pa_dbus_connection*) userdata; + /* this will wakeup the mainloop and dispatch events, although + * it may not be the cleanest way of accomplishing it */ + c->core->mainloop->defer_enable(c->dispatch_event, 1); +} + +static pa_dbus_connection* pa_dbus_connection_new(pa_core* c, DBusConnection *conn, const char* name) +{ + pa_dbus_connection *pconn = pa_xmalloc(sizeof(pa_dbus_connection)); + + pconn->refcount = 1; + pconn->core = c; + pconn->property_name = name; + pconn->connection = conn; + pconn->dispatch_event = c->mainloop->defer_new(c->mainloop, dispatch_cb, + (void*) conn); + + pa_property_set(c, name, pconn); + + return pconn; +} + +DBusConnection* pa_dbus_connection_get(pa_dbus_connection *c) +{ + assert(c && c->connection); + return c->connection; +} + +void pa_dbus_connection_unref(pa_dbus_connection *c) +{ + assert(c); + + /* non-zero refcount, still outstanding refs */ + if (--(c->refcount)) + return; + + /* refcount is zero */ + if (dbus_connection_get_is_connected(c->connection)) { + /* disconnect as we have no more internal references */ + dbus_connection_close(c->connection); + /* must process remaining messages, bit of a kludge to + * handle both unload and shutdown */ + while(dbus_connection_read_write_dispatch(c->connection, -1)); + } + pa_dbus_connection_free(c); +} + +pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c) +{ + assert(c); + + ++(c->refcount); + + return c; +} + +pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, + DBusError *error) +{ + const char* name; + DBusConnection *conn; + pa_dbus_connection *pconn; + static const char sysname[] = "dbus-connection-system"; + static const char sessname[] = "dbus-connection-session"; + static const char startname[] = "dbus-connection-starter"; + + switch (type) { + case DBUS_BUS_SYSTEM: + name = sysname; + break; + case DBUS_BUS_SESSION: + name = sessname; + break; + case DBUS_BUS_STARTER: + name = startname; + break; + default: + assert(0); /* never reached */ + break; + } + + if ((pconn = pa_property_get(c, name))) + return pa_dbus_connection_ref(pconn); + + /* else */ + conn = dbus_bus_get_private(type, error); + if (conn == NULL || dbus_error_is_set(error)) { + return NULL; + } + + pconn = pa_dbus_connection_new(c, conn, name); + + /* don't exit on disconnect */ + dbus_connection_set_exit_on_disconnect(conn, FALSE); + /* set up the DBUS call backs */ + dbus_connection_set_dispatch_status_function(conn, dispatch_status, + (void*) pconn, NULL); + dbus_connection_set_watch_functions(conn, + add_watch, + remove_watch, + toggle_watch, + (void*) c, NULL); + dbus_connection_set_timeout_functions(conn, + add_timeout, + remove_timeout, + toggle_timeout, + (void*) c, NULL); + dbus_connection_set_wakeup_main_function(conn, wakeup_main, pconn, NULL); + + return pconn; +} diff --git a/src/modules/dbus-util.h b/src/modules/dbus-util.h new file mode 100644 index 000000000..d5d5b36af --- /dev/null +++ b/src/modules/dbus-util.h @@ -0,0 +1,36 @@ +#ifndef foodbusutilhfoo +#define foodbusutilhfoo + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +typedef struct pa_dbus_connection pa_dbus_connection; + +/* return the DBusConnection of the specified type for the given core, + * like dbus_bus_get(), but integrates the connection with the pa_core */ +pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error); + +DBusConnection* pa_dbus_connection_get(pa_dbus_connection *conn); + +pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *conn); +void pa_dbus_connection_unref(pa_dbus_connection *conn); + +#endif diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c new file mode 100644 index 000000000..1c15a2d1b --- /dev/null +++ b/src/modules/module-hal-detect.c @@ -0,0 +1,495 @@ +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dbus-util.h" +#include "module-hal-detect-symdef.h" + +PA_MODULE_AUTHOR("Shahms King") +PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") +PA_MODULE_VERSION(PACKAGE_VERSION) + +static const char* capabilities[] = { "alsa", "oss" }; + +typedef enum { + CAP_ALSA, + CAP_OSS, + CAP_MAX +} capability_t; + +typedef enum { + ALSA_TYPE_SINK, + ALSA_TYPE_SOURCE, + ALSA_TYPE_OTHER, + ALSA_TYPE_MAX +} alsa_type_t; + +struct device { + char *udi; + pa_module *module; +}; + +struct userdata { + pa_core *core; + pa_subscription *sub; + LibHalContext *ctx; + capability_t capability; + pa_dbus_connection *conn; + pa_hashmap *by_udi; + pa_hashmap *by_module; +}; + +struct timerdata { + struct userdata *u; + char *udi; +}; + +static alsa_type_t hal_device_get_alsa_type(LibHalContext *ctx, const char *udi, + DBusError *error) +{ + char *type; + alsa_type_t t; + + type = libhal_device_get_property_string(ctx, udi, "alsa.type", error); + if (!type || dbus_error_is_set(error)) + return FALSE; + + if (!strcmp(type, "playback")) { + t = ALSA_TYPE_SINK; + } else if (!strcmp(type, "capture")) { + t = ALSA_TYPE_SOURCE; + } else { + t = ALSA_TYPE_OTHER; + } + libhal_free_string(type); + + return t; +} + +static int hal_device_get_alsa_card(LibHalContext *ctx, const char *udi, + DBusError *error) +{ + return libhal_device_get_property_int(ctx, udi, "alsa.card", error); +} + +static int hal_device_get_alsa_device(LibHalContext *ctx, const char *udi, + DBusError *error) +{ + return libhal_device_get_property_int(ctx, udi, "alsa.device", error); +} + +static void hal_device_free(struct device* d) { + pa_xfree(d->udi); + pa_xfree(d); +} + +static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { + hal_device_free((struct device*) d); +} + +static dbus_bool_t hal_device_add_alsa(struct userdata *u, const char *udi, + DBusError *error) +{ + char args[64]; + alsa_type_t type; + int device, card; + pa_module *m; + struct device *d; + const char *module_name; + + type = hal_device_get_alsa_type(u->ctx, udi, error); + if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER) { + return FALSE; + } + + device = hal_device_get_alsa_device(u->ctx, udi, error); + if (dbus_error_is_set(error) || device != 0) + return FALSE; + + card = hal_device_get_alsa_card(u->ctx, udi, error); + if (dbus_error_is_set(error)) + return FALSE; + + module_name = (type == ALSA_TYPE_SINK) ? "module-alsa-sink" + : "module-alsa-source"; + snprintf(args, sizeof(args), "device=hw:%u", card); + if (!(m = pa_module_load(u->core, module_name, args))) + return FALSE; + + d = pa_xmalloc(sizeof(struct device)); + d->udi = pa_xstrdup(udi); + d->module = m; + + pa_hashmap_put(u->by_module, m, d); + pa_hashmap_put(u->by_udi, udi, d); + + return TRUE; +} + +static int hal_device_add_all(struct userdata *u, capability_t capability) +{ + DBusError error; + int i,n,count; + dbus_bool_t r; + char** udis; + const char* cap = capabilities[capability]; + + assert(capability < CAP_MAX); + + pa_log_info(__FILE__": Trying capability %u (%s)", capability, cap); + dbus_error_init(&error); + udis = libhal_find_device_by_capability(u->ctx, cap, &n, &error); + if (dbus_error_is_set(&error)) { + pa_log_error(__FILE__": Error finding devices: %s: %s", error.name, + error.message); + dbus_error_free(&error); + return -1; + } + count = 0; + for (i = 0; i < n; ++i) { + switch(capability) { + case CAP_ALSA: + r = hal_device_add_alsa(u, udis[i], &error); + break; + case CAP_OSS: + /* r = hal_device_add_oss(u, udis[i], &error) + * break; */ + case CAP_MAX: + default: + assert(FALSE); + break; + } + + if (dbus_error_is_set(&error)) { + pa_log_error(__FILE__": Error adding device: %s: %s", error.name, + error.message); + dbus_error_free(&error); + count = -1; + break; + } + if (r) + ++count; + } + + libhal_free_string_array(udis); + u->capability = capability; + return count; +} + +static dbus_bool_t device_has_capability(LibHalContext *ctx, const char *udi, + const char* cap, DBusError *error) +{ + dbus_bool_t has_prop; + has_prop = libhal_device_property_exists(ctx, udi, "info.capabilities", + error); + if (!has_prop || dbus_error_is_set(error)) + return FALSE; + + return libhal_device_query_capability(ctx, udi, cap, error); +} + +static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, + const struct timeval *tv, void *userdata) +{ + DBusError error; + struct timerdata *td = (struct timerdata*) userdata; + + dbus_error_init(&error); + if (!libhal_device_exists(td->u->ctx, td->udi, &error)) + goto exit; + + switch(td->u->capability) { + case CAP_ALSA: + hal_device_add_alsa(td->u, td->udi, &error); + break; + case CAP_OSS: + /* hal_device_add_oss(td->u, td->udi, &error); + * break; */ + case CAP_MAX: + default: + /* not reached */ + assert(FALSE); + break; + } + +exit: + if (dbus_error_is_set(&error)) { + pa_log_error(__FILE__": Error adding device: %s: %s", error.name, + error.message); + dbus_error_free(&error); + } + + pa_xfree(td->udi); + pa_xfree(td); + ea->time_free(ev); +} + +static void device_added_cb(LibHalContext *ctx, const char *udi) +{ + DBusError error; + struct timeval tv; + dbus_bool_t has_cap; + struct timerdata *t; + struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); + const char* cap = capabilities[u->capability]; + + pa_log_debug(__FILE__": HAL Device added: %s", udi); + + dbus_error_init(&error); + has_cap = device_has_capability(ctx, udi, cap, &error); + if (dbus_error_is_set(&error)) { + pa_log_error(__FILE__": Error getting capability: %s: %s", error.name, + error.message); + dbus_error_free(&error); + return; + } + + /* skip it */ + if (!has_cap) + return; + + /* actually add the device one second later */ + t = pa_xmalloc(sizeof(struct timerdata)); + t->u = u; + t->udi = pa_xstrdup(udi); + + gettimeofday(&tv, NULL); + tv.tv_sec += 1; + u->core->mainloop->time_new(u->core->mainloop, &tv, + device_added_time_cb, t); +} + +static void device_removed_cb(LibHalContext* ctx, const char *udi) +{ + struct device *d; + struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); + + pa_log_debug(__FILE__": Device removed: %s", udi); + if ((d = pa_hashmap_remove(u->by_udi, udi))) { + d = pa_hashmap_remove(u->by_module, d->module); + pa_log_debug(__FILE__": Unloading: %s <%s>", d->module->name, d->module->argument); + pa_module_unload_request(d->module); + hal_device_free(d); + } +} + +#if 0 +static void new_capability_cb(LibHalContext *ctx, const char *udi, + const char* capability) +{ +} + +static void lost_capability_cb(LibHalContext *ctx, const char *udi, + const char* capability) +{ +} + +static void property_modified_cb(LibHalContext *ctx, const char *udi, + const char* key, + dbus_bool_t is_removed, + dbus_bool_t is_added) +{ +} +#endif + +static void subscribe_notify_cb(pa_core *c, pa_subscription_event_type_t type, + uint32_t idx, void *userdata) +{ + pa_module *m; + struct device *d; + struct userdata *u = (struct userdata*) userdata; + + /* only listen for module remove events */ + if (type != (PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE)) + return; + + if (!(m = pa_idxset_get_by_index(c->modules, idx))) + return; + + /* we found the module, see if it's one we care about */ + if ((d = pa_hashmap_remove(u->by_module, m))) { + pa_log_debug(__FILE__": Removing module #%u %s: %s", + m->index, m->name, d->udi); + d = pa_hashmap_remove(u->by_udi, d->udi); + hal_device_free(d); + } +} + + +static void pa_hal_context_free(LibHalContext* hal_ctx) +{ + DBusError error; + + dbus_error_init(&error); + libhal_ctx_shutdown(hal_ctx, &error); + libhal_ctx_free(hal_ctx); + + if (dbus_error_is_set(&error)) { + dbus_error_free(&error); + } +} + +static void userdata_free(struct userdata *u) { + pa_hal_context_free(u->ctx); + pa_subscription_free(u->sub); + /* free the hashmap */ + pa_hashmap_free(u->by_module, NULL, NULL); + /* free the devices with the hashmap */ + pa_hashmap_free(u->by_udi, hal_device_free_cb, NULL); + pa_dbus_connection_unref(u->conn); + pa_xfree(u); +} + +static LibHalContext* pa_hal_context_new(pa_core* c, DBusConnection *conn) +{ + DBusError error; + LibHalContext *hal_ctx = NULL; + + dbus_error_init(&error); + if (!(hal_ctx = libhal_ctx_new())) { + pa_log_error(__FILE__": libhal_ctx_new() failed"); + goto fail; + } + + if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) { + pa_log_error(__FILE__": Error establishing DBUS connection: %s: %s", + error.name, error.message); + goto fail; + } + + if (!libhal_ctx_init(hal_ctx, &error)) { + pa_log_error(__FILE__": Couldn't connect to hald: %s: %s", + error.name, error.message); + goto fail; + } + + return hal_ctx; + +fail: + if (hal_ctx) + pa_hal_context_free(hal_ctx); + + if (dbus_error_is_set(&error)) + dbus_error_free(&error); + + return NULL; +} + +int pa__init(pa_core *c, pa_module*m) { + int n; + DBusError error; + pa_dbus_connection *conn; + struct userdata *u = NULL; + LibHalContext *hal_ctx = NULL; + + assert(c); + assert(m); + + dbus_error_init(&error); + if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error))) { + pa_log_error(__FILE__": Unable to contact DBUS system bus: %s: %s", + error.name, error.message); + dbus_error_free(&error); + return -1; + } + + if (!(hal_ctx = pa_hal_context_new(c, pa_dbus_connection_get(conn)))) { + /* pa_hal_context_new() logs appropriate errors */ + return -1; + } + + u = pa_xmalloc(sizeof(struct userdata)); + u->core = c; + u->ctx = hal_ctx; + u->conn = conn; + u->by_module = pa_hashmap_new(NULL, NULL); + u->by_udi = pa_hashmap_new(pa_idxset_string_hash_func, + pa_idxset_string_compare_func); + u->sub = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_MODULE, + subscribe_notify_cb, (void*) u); + m->userdata = (void*) u; + +#if HAVE_ALSA + if ((n = hal_device_add_all(u, CAP_ALSA)) <= 0) +#endif +#if HAVE_OSS + if ((n = hal_device_add_all(u, CAP_OSS)) <= 0) +#endif + { + pa_log_warn(__FILE__": failed to detect any sound hardware."); + userdata_free(u); + return -1; + } + + libhal_ctx_set_user_data(hal_ctx, (void*) u); + libhal_ctx_set_device_added(hal_ctx, device_added_cb); + libhal_ctx_set_device_removed(hal_ctx, device_removed_cb); + + dbus_error_init(&error); + if (!libhal_device_property_watch_all(hal_ctx, &error)) { + pa_log_error(__FILE__": error monitoring device list: %s: %s", + error.name, error.message); + dbus_error_free(&error); + userdata_free(u); + return -1; + } + + /* + libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); + libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability_cb); + libhal_ctx_set_device_property_modified(hal_ctx, property_modified_cb); + */ + + pa_log_info(__FILE__": loaded %i modules.", n); + + return 0; +} + + +void pa__done(PA_GCC_UNUSED pa_core *c, pa_module *m) { + assert (c && m); + + /* free the user data */ + userdata_free(m->userdata); +} From d953870564c13bc4742634a17300c58abbf1eadf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 6 Aug 2006 19:14:07 +0000 Subject: [PATCH 1088/1514] * add SVN $Id$ tags * add a const git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1188 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/dbus-util.c | 2 ++ src/modules/dbus-util.h | 2 ++ src/modules/module-hal-detect.c | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c index 0c9978e70..b5c613372 100644 --- a/src/modules/dbus-util.c +++ b/src/modules/dbus-util.c @@ -1,3 +1,5 @@ +/* $Id$ */ + /*** This file is part of PulseAudio. diff --git a/src/modules/dbus-util.h b/src/modules/dbus-util.h index d5d5b36af..7a9871a47 100644 --- a/src/modules/dbus-util.h +++ b/src/modules/dbus-util.h @@ -1,6 +1,8 @@ #ifndef foodbusutilhfoo #define foodbusutilhfoo +/* $Id$ */ + /*** This file is part of PulseAudio. diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 1c15a2d1b..adcb866ce 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -1,3 +1,5 @@ +/* $Id$ */ + /*** This file is part of PulseAudio. @@ -50,7 +52,7 @@ PA_MODULE_AUTHOR("Shahms King") PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") PA_MODULE_VERSION(PACKAGE_VERSION) -static const char* capabilities[] = { "alsa", "oss" }; +static const char*const capabilities[] = { "alsa", "oss" }; typedef enum { CAP_ALSA, From 5d8ccfd83984c6b0559857e6a0bf13037818ca95 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 7 Aug 2006 16:50:15 +0000 Subject: [PATCH 1089/1514] try to reduce volume updates in the ALSA sinks/sources: only touch the shadowed hw volme if necessary git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1189 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 32 +++++++++++++++++++------------- src/modules/module-alsa-source.c | 22 +++++++++++++--------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index d5abdc286..0a0717df1 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -212,20 +212,25 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { static int sink_get_hw_volume_cb(pa_sink *s) { struct userdata *u = s->userdata; - long vol; int err; int i; - assert(u && u->mixer_elem); + assert(u); + assert(u->mixer_elem); + + for (i = 0; i < s->hw_volume.channels; i++) { + long set_vol, vol; - for (i = 0;i < s->hw_volume.channels;i++) { assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); - err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol); - if (err < 0) + if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol)) < 0) goto fail; - s->hw_volume.values[i] = - (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min); + + set_vol = (long) roundf(((float) s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; + + /* Try to avoid superfluous volume changes */ + if (set_vol != vol) + s->hw_volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); } return 0; @@ -243,9 +248,12 @@ static int sink_set_hw_volume_cb(pa_sink *s) { int i; pa_volume_t vol; - assert(u && u->mixer_elem); + assert(u); + assert(u->mixer_elem); - for (i = 0;i < s->hw_volume.channels;i++) { + for (i = 0; i < s->hw_volume.channels; i++) { + long alsa_vol; + assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); vol = s->hw_volume.values[i]; @@ -253,11 +261,9 @@ static int sink_set_hw_volume_cb(pa_sink *s) { if (vol > PA_VOLUME_NORM) vol = PA_VOLUME_NORM; - vol = (vol * (u->hw_volume_max - u->hw_volume_min)) / - PA_VOLUME_NORM + u->hw_volume_min; + alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; - err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, vol); - if (err < 0) + if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, alsa_vol)) < 0) goto fail; } diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index ca4ac9d0f..3952a3850 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -213,13 +213,18 @@ static int source_get_hw_volume_cb(pa_source *s) { assert(u && u->mixer_elem); for (i = 0;i < s->hw_volume.channels;i++) { + long set_vol; + assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i)); - - err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol); - if (err < 0) + + if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol)) < 0) goto fail; - s->hw_volume.values[i] = - (vol - u->hw_volume_min) * PA_VOLUME_NORM / (u->hw_volume_max - u->hw_volume_min); + + set_vol = (long) roundf(((float) s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; + + /* Try to avoid superfluous volume changes */ + if (set_vol != vol) + s->hw_volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); } return 0; @@ -247,10 +252,9 @@ static int source_set_hw_volume_cb(pa_source *s) { if (vol > PA_VOLUME_NORM) vol = PA_VOLUME_NORM; - vol = vol * (u->hw_volume_max - u->hw_volume_min) / - PA_VOLUME_NORM + u->hw_volume_min; - err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, vol); - if (err < 0) + vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; + + if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, vol)) < 0) goto fail; } From b382df5868db14628bed2d7445706dab5a4bdf58 Mon Sep 17 00:00:00 2001 From: "Shahms E. King" Date: Mon, 7 Aug 2006 20:29:31 +0000 Subject: [PATCH 1090/1514] clean up hal patch to use pa_xnew and timeval compatibility wrappers git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1190 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/dbus-util.c | 35 ++++++----------- src/modules/module-hal-detect.c | 67 ++++++++------------------------- 2 files changed, 28 insertions(+), 74 deletions(-) diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c index b5c613372..c9cdf114d 100644 --- a/src/modules/dbus-util.c +++ b/src/modules/dbus-util.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "dbus-util.h" @@ -82,14 +83,6 @@ get_watch_flags(DBusWatch *watch) return events; } -static void timeval_next(struct timeval *tv, int millint) -{ - /* number of seconds in the milli-second interval */ - tv->tv_sec += (millint / 1000); - /* milliseconds minus the seconds portion, converted to microseconds */ - tv->tv_usec += (millint - tv->tv_sec * 1000) * 1000; -} - /* pa_io_event_cb_t IO event handler */ static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) @@ -128,7 +121,7 @@ static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, dbus_timeout_handle(timeout); /* restart it for the next scheduled time */ - timeval_next(&next, dbus_timeout_get_interval(timeout)); + pa_timeval_add(&next, dbus_timeout_get_interval(timeout) * 1000); ea->time_restart(e, &next); } } @@ -182,10 +175,10 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) if (!dbus_timeout_get_enabled(timeout)) return FALSE; - if (gettimeofday(&tv, NULL) < 0) + if (pa_gettimeofday(&tv) < 0) return -1; - timeval_next(&tv, dbus_timeout_get_interval(timeout)); + pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000); ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, (void*) timeout); @@ -216,14 +209,13 @@ static void toggle_timeout(DBusTimeout *timeout, void *data) pa_core *c = (pa_core*) data; pa_time_event *ev = (pa_time_event*) dbus_timeout_get_data(timeout); - gettimeofday(&tv, NULL); if (dbus_timeout_get_enabled(timeout)) { - timeval_next(&tv, dbus_timeout_get_interval(timeout)); + pa_gettimeofday(&tv); + pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000); c->mainloop->time_restart(ev, &tv); } else { - /* set it to expire one second ago */ - tv.tv_sec -= 1; - c->mainloop->time_restart(ev, &tv); + /* disable the timeout */ + c->mainloop->time_restart(ev, NULL); } } @@ -251,7 +243,7 @@ wakeup_main(void *userdata) static pa_dbus_connection* pa_dbus_connection_new(pa_core* c, DBusConnection *conn, const char* name) { - pa_dbus_connection *pconn = pa_xmalloc(sizeof(pa_dbus_connection)); + pa_dbus_connection *pconn = pa_xnew(pa_dbus_connection, 1); pconn->refcount = 1; pconn->core = c; @@ -305,19 +297,16 @@ pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, const char* name; DBusConnection *conn; pa_dbus_connection *pconn; - static const char sysname[] = "dbus-connection-system"; - static const char sessname[] = "dbus-connection-session"; - static const char startname[] = "dbus-connection-starter"; switch (type) { case DBUS_BUS_SYSTEM: - name = sysname; + name = "dbus-connection-system"; break; case DBUS_BUS_SESSION: - name = sessname; + name = "dbus-connection-session"; break; case DBUS_BUS_STARTER: - name = startname; + name = "dbus-connection-starter"; break; default: assert(0); /* never reached */ diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index adcb866ce..a35144b00 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -34,11 +34,11 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -68,18 +68,16 @@ typedef enum { } alsa_type_t; struct device { + uint32_t index; char *udi; - pa_module *module; }; struct userdata { pa_core *core; - pa_subscription *sub; LibHalContext *ctx; capability_t capability; pa_dbus_connection *conn; - pa_hashmap *by_udi; - pa_hashmap *by_module; + pa_hashmap *devices; }; struct timerdata { @@ -159,12 +157,11 @@ static dbus_bool_t hal_device_add_alsa(struct userdata *u, const char *udi, if (!(m = pa_module_load(u->core, module_name, args))) return FALSE; - d = pa_xmalloc(sizeof(struct device)); + d = pa_xnew(struct device, 1); d->udi = pa_xstrdup(udi); - d->module = m; + d->index = m->index; - pa_hashmap_put(u->by_module, m, d); - pa_hashmap_put(u->by_udi, udi, d); + pa_hashmap_put(u->devices, udi, d); return TRUE; } @@ -291,13 +288,13 @@ static void device_added_cb(LibHalContext *ctx, const char *udi) if (!has_cap) return; - /* actually add the device one second later */ - t = pa_xmalloc(sizeof(struct timerdata)); + /* actually add the device 1/2 second later */ + t = pa_xnew(struct timerdata, 1); t->u = u; t->udi = pa_xstrdup(udi); - gettimeofday(&tv, NULL); - tv.tv_sec += 1; + pa_gettimeofday(&tv); + pa_timeval_add(&tv, 500000); u->core->mainloop->time_new(u->core->mainloop, &tv, device_added_time_cb, t); } @@ -308,10 +305,8 @@ static void device_removed_cb(LibHalContext* ctx, const char *udi) struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); pa_log_debug(__FILE__": Device removed: %s", udi); - if ((d = pa_hashmap_remove(u->by_udi, udi))) { - d = pa_hashmap_remove(u->by_module, d->module); - pa_log_debug(__FILE__": Unloading: %s <%s>", d->module->name, d->module->argument); - pa_module_unload_request(d->module); + if ((d = pa_hashmap_remove(u->devices, udi))) { + pa_module_unload_by_index(u->core, d->index); hal_device_free(d); } } @@ -335,30 +330,6 @@ static void property_modified_cb(LibHalContext *ctx, const char *udi, } #endif -static void subscribe_notify_cb(pa_core *c, pa_subscription_event_type_t type, - uint32_t idx, void *userdata) -{ - pa_module *m; - struct device *d; - struct userdata *u = (struct userdata*) userdata; - - /* only listen for module remove events */ - if (type != (PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE)) - return; - - if (!(m = pa_idxset_get_by_index(c->modules, idx))) - return; - - /* we found the module, see if it's one we care about */ - if ((d = pa_hashmap_remove(u->by_module, m))) { - pa_log_debug(__FILE__": Removing module #%u %s: %s", - m->index, m->name, d->udi); - d = pa_hashmap_remove(u->by_udi, d->udi); - hal_device_free(d); - } -} - - static void pa_hal_context_free(LibHalContext* hal_ctx) { DBusError error; @@ -374,11 +345,8 @@ static void pa_hal_context_free(LibHalContext* hal_ctx) static void userdata_free(struct userdata *u) { pa_hal_context_free(u->ctx); - pa_subscription_free(u->sub); - /* free the hashmap */ - pa_hashmap_free(u->by_module, NULL, NULL); /* free the devices with the hashmap */ - pa_hashmap_free(u->by_udi, hal_device_free_cb, NULL); + pa_hashmap_free(u->devices, hal_device_free_cb, NULL); pa_dbus_connection_unref(u->conn); pa_xfree(u); } @@ -441,15 +409,12 @@ int pa__init(pa_core *c, pa_module*m) { return -1; } - u = pa_xmalloc(sizeof(struct userdata)); + u = pa_xnew(struct userdata, 1); u->core = c; u->ctx = hal_ctx; u->conn = conn; - u->by_module = pa_hashmap_new(NULL, NULL); - u->by_udi = pa_hashmap_new(pa_idxset_string_hash_func, - pa_idxset_string_compare_func); - u->sub = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_MODULE, - subscribe_notify_cb, (void*) u); + u->devices = pa_hashmap_new(pa_idxset_string_hash_func, + pa_idxset_string_compare_func); m->userdata = (void*) u; #if HAVE_ALSA From 7ee7a23408a1dae0ce1655067b26ed49e8e2e11f Mon Sep 17 00:00:00 2001 From: "Shahms E. King" Date: Tue, 8 Aug 2006 19:26:06 +0000 Subject: [PATCH 1091/1514] add HAL support for OSS devices and capability changes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1191 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 175 +++++++++++++++++++++----------- 1 file changed, 115 insertions(+), 60 deletions(-) diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index a35144b00..27c392210 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -85,6 +85,21 @@ struct timerdata { char *udi; }; +static const char* get_capability_name(capability_t cap) { + if (cap >= CAP_MAX) + return NULL; + return capabilities[cap]; +} + +static void hal_device_free(struct device* d) { + pa_xfree(d->udi); + pa_xfree(d); +} + +static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { + hal_device_free((struct device*) d); +} + static alsa_type_t hal_device_get_alsa_type(LibHalContext *ctx, const char *udi, DBusError *error) { @@ -119,42 +134,98 @@ static int hal_device_get_alsa_device(LibHalContext *ctx, const char *udi, return libhal_device_get_property_int(ctx, udi, "alsa.device", error); } -static void hal_device_free(struct device* d) { - pa_xfree(d->udi); - pa_xfree(d); -} - -static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { - hal_device_free((struct device*) d); -} - -static dbus_bool_t hal_device_add_alsa(struct userdata *u, const char *udi, +static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, DBusError *error) { char args[64]; alsa_type_t type; int device, card; - pa_module *m; - struct device *d; const char *module_name; type = hal_device_get_alsa_type(u->ctx, udi, error); - if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER) { - return FALSE; - } + if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER) + return NULL; device = hal_device_get_alsa_device(u->ctx, udi, error); if (dbus_error_is_set(error) || device != 0) - return FALSE; + return NULL; card = hal_device_get_alsa_card(u->ctx, udi, error); if (dbus_error_is_set(error)) - return FALSE; + return NULL; module_name = (type == ALSA_TYPE_SINK) ? "module-alsa-sink" : "module-alsa-source"; snprintf(args, sizeof(args), "device=hw:%u", card); - if (!(m = pa_module_load(u->core, module_name, args))) + return pa_module_load(u->core, module_name, args); +} + +static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi, + DBusError *error) +{ + dbus_bool_t rv = FALSE; + char* device; + char* type; + + type = libhal_device_get_property_string(ctx, udi, "oss.type", error); + if (!type || dbus_error_is_set(error)) + return FALSE; + + if (!strcmp(type, "pcm")) { + device = libhal_device_get_property_string(ctx, udi, "oss.device_file", + error); + if (!device || dbus_error_is_set(error)) + goto exit; + + /* hack to ignore /dev/audio style devices */ + if ((device = strrchr(device, '/'))) + rv = (pa_startswith(device + 1, "audio")) ? FALSE : TRUE; + } + +exit: + libhal_free_string(type); + return rv; +} + +static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, + DBusError *error) +{ + char args[128]; + char* device; + + if (!hal_device_is_oss_pcm(u->ctx, udi, error) || dbus_error_is_set(error)) + return NULL; + + device = libhal_device_get_property_string(u->ctx, udi, "oss.device_file", + error); + if (!device || dbus_error_is_set(error)) + return NULL; + + snprintf(args, sizeof(args), "device=%s", device); + libhal_free_string(device); + + return pa_module_load(u->core, "module-oss", args); +} + +static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, + DBusError *error) +{ + pa_module* m; + struct device *d; + + switch(u->capability) { + case CAP_ALSA: + m = hal_device_load_alsa(u, udi, error); + break; + case CAP_OSS: + m = hal_device_load_oss(u, udi, error); + break; + default: + assert(FALSE); /* never reached */ + break; + } + + if (!m || dbus_error_is_set(error)) return FALSE; d = pa_xnew(struct device, 1); @@ -172,7 +243,7 @@ static int hal_device_add_all(struct userdata *u, capability_t capability) int i,n,count; dbus_bool_t r; char** udis; - const char* cap = capabilities[capability]; + const char* cap = get_capability_name(capability); assert(capability < CAP_MAX); @@ -186,20 +257,9 @@ static int hal_device_add_all(struct userdata *u, capability_t capability) return -1; } count = 0; + u->capability = capability; for (i = 0; i < n; ++i) { - switch(capability) { - case CAP_ALSA: - r = hal_device_add_alsa(u, udis[i], &error); - break; - case CAP_OSS: - /* r = hal_device_add_oss(u, udis[i], &error) - * break; */ - case CAP_MAX: - default: - assert(FALSE); - break; - } - + r = hal_device_add(u, udis[i], &error); if (dbus_error_is_set(&error)) { pa_log_error(__FILE__": Error adding device: %s: %s", error.name, error.message); @@ -212,7 +272,6 @@ static int hal_device_add_all(struct userdata *u, capability_t capability) } libhal_free_string_array(udis); - u->capability = capability; return count; } @@ -221,7 +280,7 @@ static dbus_bool_t device_has_capability(LibHalContext *ctx, const char *udi, { dbus_bool_t has_prop; has_prop = libhal_device_property_exists(ctx, udi, "info.capabilities", - error); + error); if (!has_prop || dbus_error_is_set(error)) return FALSE; @@ -235,24 +294,9 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, struct timerdata *td = (struct timerdata*) userdata; dbus_error_init(&error); - if (!libhal_device_exists(td->u->ctx, td->udi, &error)) - goto exit; + if (libhal_device_exists(td->u->ctx, td->udi, &error)) + hal_device_add(td->u, td->udi, &error); - switch(td->u->capability) { - case CAP_ALSA: - hal_device_add_alsa(td->u, td->udi, &error); - break; - case CAP_OSS: - /* hal_device_add_oss(td->u, td->udi, &error); - * break; */ - case CAP_MAX: - default: - /* not reached */ - assert(FALSE); - break; - } - -exit: if (dbus_error_is_set(&error)) { pa_log_error(__FILE__": Error adding device: %s: %s", error.name, error.message); @@ -271,7 +315,7 @@ static void device_added_cb(LibHalContext *ctx, const char *udi) dbus_bool_t has_cap; struct timerdata *t; struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); - const char* cap = capabilities[u->capability]; + const char* cap = get_capability_name(u->capability); pa_log_debug(__FILE__": HAL Device added: %s", udi); @@ -311,17 +355,31 @@ static void device_removed_cb(LibHalContext* ctx, const char *udi) } } -#if 0 static void new_capability_cb(LibHalContext *ctx, const char *udi, - const char* capability) + const char* capability) { + struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); + const char* capname = get_capability_name(u->capability); + + if (capname && !strcmp(capname, capability)) { + /* capability we care about, pretend it's a new device */ + device_added_cb(ctx, udi); + } } static void lost_capability_cb(LibHalContext *ctx, const char *udi, const char* capability) { + struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); + const char* capname = get_capability_name(u->capability); + + if (capname && !strcmp(capname, capability)) { + /* capability we care about, pretend it was removed */ + device_removed_cb(ctx, udi); + } } +#if 0 static void property_modified_cb(LibHalContext *ctx, const char *udi, const char* key, dbus_bool_t is_removed, @@ -432,6 +490,9 @@ int pa__init(pa_core *c, pa_module*m) { libhal_ctx_set_user_data(hal_ctx, (void*) u); libhal_ctx_set_device_added(hal_ctx, device_added_cb); libhal_ctx_set_device_removed(hal_ctx, device_removed_cb); + libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); + libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability_cb); + /*libhal_ctx_set_device_property_modified(hal_ctx, property_modified_cb);*/ dbus_error_init(&error); if (!libhal_device_property_watch_all(hal_ctx, &error)) { @@ -442,12 +503,6 @@ int pa__init(pa_core *c, pa_module*m) { return -1; } - /* - libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); - libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability_cb); - libhal_ctx_set_device_property_modified(hal_ctx, property_modified_cb); - */ - pa_log_info(__FILE__": loaded %i modules.", n); return 0; From 59f1a67cb5f55f57b743667a3a15547fb1fb7cbc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 15:05:02 +0000 Subject: [PATCH 1092/1514] use the copied udi string as hash key for the device table, because the temporary one is freed when the function exits git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1192 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 27c392210..dd30045e5 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -232,7 +232,7 @@ static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, d->udi = pa_xstrdup(udi); d->index = m->index; - pa_hashmap_put(u->devices, udi, d); + pa_hashmap_put(u->devices, d->udi, d); return TRUE; } From b0b968df0048a66c9beb76a0c0f42e3264753d4d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 15:06:03 +0000 Subject: [PATCH 1093/1514] change order of the ALSA event dispatch code to make sure that the code survives if the event dispatcher frees the ALSA client git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1193 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 04a2d849f..969a3da16 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -93,14 +93,14 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io return; } + a->defer_enable(fdl->defer, 1); + if (revents) { if (fdl->pcm) fdl->cb(fdl->userdata); else snd_mixer_handle_events(fdl->mixer); } - - a->defer_enable(fdl->defer, 1); } static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *userdata) { From 7a4e1c9a0ea6143553d6f63ad4b2f96f3c7bb9be Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 15:08:09 +0000 Subject: [PATCH 1094/1514] ALSA: handle write()/read() errors properly by unloading the driver module. This should fix problems when removing USB audio device while pulseaudio is running. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1194 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 78 +++++++++++++++++++++----------- src/modules/module-alsa-source.c | 76 +++++++++++++++++++++---------- 2 files changed, 104 insertions(+), 50 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 0a0717df1..d47e8c3b6 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -96,13 +96,49 @@ static void update_usage(struct userdata *u) { (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0)); } -static void xrun_recovery(struct userdata *u) { +static void clear_up(struct userdata *u) { + assert(u); + + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + u->sink = NULL; + } + + if (u->pcm_fdl) + pa_alsa_fdlist_free(u->pcm_fdl); + if (u->mixer_fdl) + pa_alsa_fdlist_free(u->mixer_fdl); + + u->pcm_fdl = u->mixer_fdl = NULL; + + if (u->mixer_handle) { + snd_mixer_close(u->mixer_handle); + u->mixer_handle = NULL; + } + + if (u->pcm_handle) { + snd_pcm_drop(u->pcm_handle); + snd_pcm_close(u->pcm_handle); + u->pcm_handle = NULL; + } +} + +static int xrun_recovery(struct userdata *u) { + int ret; assert(u); - pa_log(__FILE__": *** ALSA-XRUN (playback) ***"); + pa_log_info(__FILE__": *** ALSA-XRUN (playback) ***"); - if (snd_pcm_prepare(u->pcm_handle) < 0) - pa_log(__FILE__": snd_pcm_prepare() failed"); + if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) { + pa_log(__FILE__": snd_pcm_prepare() failed: %s", snd_strerror(-ret)); + + clear_up(u); + pa_module_unload_request(u->module); + return -1; + } + + return ret; } static void do_write(struct userdata *u) { @@ -130,11 +166,16 @@ static void do_write(struct userdata *u) { return; if (frames == -EPIPE) { - xrun_recovery(u); + if (xrun_recovery(u) < 0) + return; + continue; } - pa_log(__FILE__": snd_pcm_writei() failed: %s", snd_strerror(frames)); + pa_log(__FILE__": snd_pcm_writei() failed: %s", snd_strerror(-frames)); + + clear_up(u); + pa_module_unload_request(u->module); return; } @@ -159,7 +200,8 @@ static void fdl_callback(void *userdata) { assert(u); if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) - xrun_recovery(u); + if (xrun_recovery(u) < 0) + return; do_write(u); } @@ -480,25 +522,9 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; - - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - } - - if (u->pcm_fdl) - pa_alsa_fdlist_free(u->pcm_fdl); - if (u->mixer_fdl) - pa_alsa_fdlist_free(u->mixer_fdl); - - if (u->mixer_handle) - snd_mixer_close(u->mixer_handle); - - if (u->pcm_handle) { - snd_pcm_drop(u->pcm_handle); - snd_pcm_close(u->pcm_handle); - } - + + clear_up(u); + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); if (u->silence.memblock) diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 3952a3850..b5cf9c705 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -96,13 +96,50 @@ static void update_usage(struct userdata *u) { (u->source ? pa_idxset_size(u->source->outputs) : 0)); } -static void xrun_recovery(struct userdata *u) { +static void clear_up(struct userdata *u) { + assert(u); + + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + u->source = NULL; + } + + if (u->pcm_fdl) + pa_alsa_fdlist_free(u->pcm_fdl); + if (u->mixer_fdl) + pa_alsa_fdlist_free(u->mixer_fdl); + + u->pcm_fdl = u->mixer_fdl = NULL; + + if (u->mixer_handle) { + snd_mixer_close(u->mixer_handle); + u->mixer_handle = NULL; + } + + if (u->pcm_handle) { + snd_pcm_drop(u->pcm_handle); + snd_pcm_close(u->pcm_handle); + u->pcm_handle = NULL; + } +} + +static int xrun_recovery(struct userdata *u) { + int ret; assert(u); - pa_log(__FILE__": *** ALSA-XRUN (capture) ***"); + pa_log_info(__FILE__": *** ALSA-XRUN (capture) ***"); - if (snd_pcm_prepare(u->pcm_handle) < 0) - pa_log(__FILE__": snd_pcm_prepare() failed"); + if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) { + pa_log(__FILE__": snd_pcm_prepare() failed: %s", snd_strerror(-ret)); + + clear_up(u); + pa_module_unload_request(u->module); + + return -1; + } + + return 0; } static void do_read(struct userdata *u) { @@ -131,11 +168,16 @@ static void do_read(struct userdata *u) { return; if (frames == -EPIPE) { - xrun_recovery(u); + if (xrun_recovery(u) < 0) + return; + continue; } - pa_log(__FILE__": snd_pcm_readi() failed: %s", pa_cstrerror(-frames)); + pa_log(__FILE__": snd_pcm_readi() failed: %s", snd_strerror(-frames)); + + clear_up(u); + pa_module_unload_request(u->module); return; } @@ -164,7 +206,8 @@ static void fdl_callback(void *userdata) { assert(u); if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) - xrun_recovery(u); + if (xrun_recovery(u) < 0) + return; do_read(u); } @@ -182,6 +225,7 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { u->source->get_hw_volume(u->source); if (u->source->get_hw_mute) u->source->get_hw_mute(u->source); + pa_subscription_post(u->source->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, u->source->index); @@ -468,24 +512,8 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; - - if (u->source) { - pa_source_disconnect(u->source); - pa_source_unref(u->source); - } - - if (u->pcm_fdl) - pa_alsa_fdlist_free(u->pcm_fdl); - if (u->mixer_fdl) - pa_alsa_fdlist_free(u->mixer_fdl); - if (u->mixer_handle) - snd_mixer_close(u->mixer_handle); - - if (u->pcm_handle) { - snd_pcm_drop(u->pcm_handle); - snd_pcm_close(u->pcm_handle); - } + clear_up(u); if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); From dcd3acc0b887dcf3f94569a1984e0217a1ddf581 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 16:29:46 +0000 Subject: [PATCH 1095/1514] remove OSS specific code from module-hal-detect if HAVE_OSS is not set. Same for ALSA git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1195 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 40 ++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index dd30045e5..6a430a83b 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -52,20 +52,24 @@ PA_MODULE_AUTHOR("Shahms King") PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") PA_MODULE_VERSION(PACKAGE_VERSION) -static const char*const capabilities[] = { "alsa", "oss" }; - typedef enum { +#ifdef HAVE_ALSA CAP_ALSA, +#endif +#ifdef HAVE_OSS CAP_OSS, +#endif CAP_MAX } capability_t; -typedef enum { - ALSA_TYPE_SINK, - ALSA_TYPE_SOURCE, - ALSA_TYPE_OTHER, - ALSA_TYPE_MAX -} alsa_type_t; +static const char* const capabilities[CAP_MAX] = { +#ifdef HAVE_ALSA + [CAP_ALSA] = "alsa", +#endif +#ifdef HAVE_OSS + [CAP_OSS] = "oss", +#endif +}; struct device { uint32_t index; @@ -100,6 +104,14 @@ static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { hal_device_free((struct device*) d); } +#ifdef HAVE_ALSA +typedef enum { + ALSA_TYPE_SINK, + ALSA_TYPE_SOURCE, + ALSA_TYPE_OTHER, + ALSA_TYPE_MAX +} alsa_type_t; + static alsa_type_t hal_device_get_alsa_type(LibHalContext *ctx, const char *udi, DBusError *error) { @@ -160,6 +172,9 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, return pa_module_load(u->core, module_name, args); } +#endif + +#ifdef HAVE_OSS static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi, DBusError *error) { @@ -206,6 +221,7 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, return pa_module_load(u->core, "module-oss", args); } +#endif static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, DBusError *error) @@ -214,12 +230,16 @@ static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, struct device *d; switch(u->capability) { +#ifdef HAVE_ALSA case CAP_ALSA: m = hal_device_load_alsa(u, udi, error); break; +#endif +#ifdef HAVE_OSS case CAP_OSS: m = hal_device_load_oss(u, udi, error); break; +#endif default: assert(FALSE); /* never reached */ break; @@ -475,10 +495,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_idxset_string_compare_func); m->userdata = (void*) u; -#if HAVE_ALSA +#ifdef HAVE_ALSA if ((n = hal_device_add_all(u, CAP_ALSA)) <= 0) #endif -#if HAVE_OSS +#ifdef HAVE_OSS if ((n = hal_device_add_all(u, CAP_OSS)) <= 0) #endif { From bf854c445ab83a298b8a364c08b0aca9938471f0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 16:38:05 +0000 Subject: [PATCH 1096/1514] Build HAL support only when either OSS or ALSA is available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1196 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index bf7425c01..68d9d5d52 100644 --- a/configure.ac +++ b/configure.ac @@ -650,7 +650,7 @@ AC_ARG_ENABLE([hal], ], [hal=auto]) -if test "x${hal}" != xno ; then +if test "x${hal}" != xno -a \( "x$HAVE_OSS" = "x1" -o "x$HAVE_ALSA" = "x1" \) ; then PKG_CHECK_MODULES(HAL, [ hal >= 0.5.7 ], HAVE_HAL=1, [ From 576c4dd96a3780716e603363c0dfa83f20e85937 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 16:38:51 +0000 Subject: [PATCH 1097/1514] rework name register a litle to only allow "valid" names. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1197 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/namereg.c | 130 +++++++++++++++++++++++++++++----------- src/pulsecore/namereg.h | 8 ++- 2 files changed, 103 insertions(+), 35 deletions(-) diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index 11c36c3a2..bb5eb7bea 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -45,10 +45,54 @@ struct namereg_entry { void *data; }; +static int is_valid_char(char c) { + return + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '.' || + c == '_'; +} + +int pa_namereg_is_valid_name(const char *name) { + const char *c; + + if (*name == 0) + return 0; + + for (c = name; *c && (c-name < PA_NAME_MAX); c++) + if (!is_valid_char(*c)) + return 0; + + if (*c) + return 0; + + return 1; +} + +char* pa_namereg_cleanup_name(const char *name) { + const char *a; + char *b, *n; + + if (*name == 0) + return NULL; + + n = pa_xnew(char, strlen(name)+1); + + for (a = name, b = n; *a && (a-name < PA_NAME_MAX); a++, b++) + *b = is_valid_char(*a) ? *a : '_'; + + *b = 0; + + return n; +} + void pa_namereg_free(pa_core *c) { assert(c); + if (!c->namereg) return; + assert(pa_hashmap_size(c->namereg) == 0); pa_hashmap_free(c->namereg, NULL, NULL); } @@ -62,54 +106,71 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t assert(name); assert(data); - /* Don't allow registration of special names */ - if (*name == '@') + if (!*name) return NULL; + + if (!pa_namereg_is_valid_name(name)) { + + if (fail) + return NULL; - if (!c->namereg) { - c->namereg = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - assert(c->namereg); + if (!(name = n = pa_namereg_cleanup_name(name))) + return NULL; } - if ((e = pa_hashmap_get(c->namereg, name)) && fail) - return NULL; + if (!c->namereg) + c->namereg = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - if (!e) - n = pa_xstrdup(name); - else { + if ((e = pa_hashmap_get(c->namereg, name)) && fail) { + pa_xfree(n); + return NULL; + } + + if (e) { unsigned i; size_t l = strlen(name); - n = pa_xmalloc(l+3); - - for (i = 1; i <= 99; i++) { - snprintf(n, l+2, "%s%u", name, i); + char *k; - if (!(e = pa_hashmap_get(c->namereg, n))) + if (l+4 > PA_NAME_MAX) { + pa_xfree(n); + return NULL; + } + + k = pa_xnew(char, l+4); + + for (i = 2; i <= 99; i++) { + snprintf(k, l+4, "%s.%u", name, i); + + if (!(e = pa_hashmap_get(c->namereg, k))) break; } if (e) { pa_xfree(n); + pa_xfree(k); return NULL; } + + pa_xfree(n); + n = k; } - assert(n); - e = pa_xmalloc(sizeof(struct namereg_entry)); + e = pa_xnew(struct namereg_entry, 1); e->type = type; - e->name = n; + e->name = n ? n : pa_xstrdup(name); e->data = data; r = pa_hashmap_put(c->namereg, e->name, e); assert (r >= 0); return e->name; - } void pa_namereg_unregister(pa_core *c, const char *name) { struct namereg_entry *e; - assert(c && name); + + assert(c); + assert(name); e = pa_hashmap_remove(c->namereg, name); assert(e); @@ -178,26 +239,33 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int a return NULL; } -void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) { +int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) { char **s; - assert(c && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); + + assert(c); + assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE); s = type == PA_NAMEREG_SINK ? &c->default_sink_name : &c->default_source_name; - assert(s); if (!name && !*s) - return; - + return 0; + if (name && *s && !strcmp(name, *s)) - return; + return 0; + + if (!pa_namereg_is_valid_name(name)) + return -1; pa_xfree(*s); *s = pa_xstrdup(name); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX); + + return 0; } const char *pa_namereg_get_default_sink_name(pa_core *c) { pa_sink *s; + assert(c); if (c->default_sink_name) @@ -206,10 +274,7 @@ const char *pa_namereg_get_default_sink_name(pa_core *c) { if ((s = pa_idxset_first(c->sinks, NULL))) pa_namereg_set_default(c, s->name, PA_NAMEREG_SINK); - if (c->default_sink_name) - return c->default_sink_name; - - return NULL; + return c->default_sink_name; } const char *pa_namereg_get_default_source_name(pa_core *c) { @@ -231,8 +296,5 @@ const char *pa_namereg_get_default_source_name(pa_core *c) { if ((s = pa_idxset_first(c->sources, NULL))) pa_namereg_set_default(c, s->name, PA_NAMEREG_SOURCE); - if (c->default_source_name) - return c->default_source_name; - - return NULL; + return c->default_source_name; } diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index e1aef8bb8..0f8466ad1 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -24,6 +24,8 @@ #include +#define PA_NAME_MAX 64 + typedef enum pa_namereg_type { PA_NAMEREG_SINK, PA_NAMEREG_SOURCE, @@ -32,10 +34,14 @@ typedef enum pa_namereg_type { void pa_namereg_free(pa_core *c); +int pa_namereg_is_valid_name(const char *name); + +char* pa_namereg_cleanup_name(const char *name); + const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail); void pa_namereg_unregister(pa_core *c, const char *name); void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload); -void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type); +int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type); const char *pa_namereg_get_default_sink_name(pa_core *c); const char *pa_namereg_get_default_source_name(pa_core *c); From e1316f572828257ea788c87aabf4e298101fbaa1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 16:56:47 +0000 Subject: [PATCH 1098/1514] fix bad memory access and a leak when detructing ALSA fd lists git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1198 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 969a3da16..39ddbfe95 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -178,7 +178,6 @@ struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) { struct pa_alsa_fdlist *fdl; fdl = pa_xmalloc(sizeof(struct pa_alsa_fdlist)); - assert(fdl); fdl->num_fds = 0; fdl->fds = NULL; @@ -208,7 +207,7 @@ void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) { int i; assert(fdl->m); for (i = 0;i < fdl->num_fds;i++) - fdl->m->io_free(fdl->ios[0]); + fdl->m->io_free(fdl->ios[i]); pa_xfree(fdl->ios); } From 539612a5c27a9b786ba76fb632110d9fa9178a39 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 16:58:21 +0000 Subject: [PATCH 1099/1514] do not export name validity checking routes and apply them only to sink/source names, not sample names git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1199 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/namereg.c | 11 ++++++----- src/pulsecore/namereg.h | 4 ---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index bb5eb7bea..fcd271bf6 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -54,7 +54,7 @@ static int is_valid_char(char c) { c == '_'; } -int pa_namereg_is_valid_name(const char *name) { +static int is_valid_name(const char *name) { const char *c; if (*name == 0) @@ -70,7 +70,7 @@ int pa_namereg_is_valid_name(const char *name) { return 1; } -char* pa_namereg_cleanup_name(const char *name) { +static char* cleanup_name(const char *name) { const char *a; char *b, *n; @@ -109,12 +109,13 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t if (!*name) return NULL; - if (!pa_namereg_is_valid_name(name)) { + if ((type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE) && + !is_valid_name(name) ) { if (fail) return NULL; - if (!(name = n = pa_namereg_cleanup_name(name))) + if (!(name = n = cleanup_name(name))) return NULL; } @@ -253,7 +254,7 @@ int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) if (name && *s && !strcmp(name, *s)) return 0; - if (!pa_namereg_is_valid_name(name)) + if (!is_valid_name(name)) return -1; pa_xfree(*s); diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index 0f8466ad1..53295b846 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -34,10 +34,6 @@ typedef enum pa_namereg_type { void pa_namereg_free(pa_core *c); -int pa_namereg_is_valid_name(const char *name); - -char* pa_namereg_cleanup_name(const char *name); - const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail); void pa_namereg_unregister(pa_core *c, const char *name); void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload); From 1d7b8e1ba761314a85908dd172b75a02526ff649 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 17:12:54 +0000 Subject: [PATCH 1100/1514] use the HAL UDI for naming input/output devices git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1200 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 6a430a83b..0063fdbd3 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -104,6 +104,14 @@ static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { hal_device_free((struct device*) d); } +static const char *strip_udi(const char *udi) { + const char *slash; + if ((slash = strrchr(udi, '/'))) + return slash+1; + + return udi; +} + #ifdef HAVE_ALSA typedef enum { ALSA_TYPE_SINK, @@ -166,9 +174,14 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, if (dbus_error_is_set(error)) return NULL; - module_name = (type == ALSA_TYPE_SINK) ? "module-alsa-sink" - : "module-alsa-source"; - snprintf(args, sizeof(args), "device=hw:%u", card); + if (type == ALSA_TYPE_SINK) { + module_name = "module-alsa-sink"; + snprintf(args, sizeof(args), "device=hw:%u sink_name=alsa_output.%s", card, strip_udi(udi)); + } else { + module_name = "module-alsa-source"; + snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi)); + } + return pa_module_load(u->core, module_name, args); } @@ -216,7 +229,7 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, if (!device || dbus_error_is_set(error)) return NULL; - snprintf(args, sizeof(args), "device=%s", device); + snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi)); libhal_free_string(device); return pa_module_load(u->core, "module-oss", args); From bfff23db10db9fe6370f8bfbc8498d2057030a0d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 17:14:35 +0000 Subject: [PATCH 1101/1514] shorten sink/source device descriptions a little git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1201 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 2 +- src/modules/module-alsa-source.c | 2 +- src/modules/module-oss-mmap.c | 4 ++-- src/modules/module-oss.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index d47e8c3b6..649fe99cf 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -457,7 +457,7 @@ int pa__init(pa_core *c, pa_module*m) { } u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s' (%s)", dev, snd_pcm_info_get_name(pcm_info)); + u->sink->description = pa_sprintf_malloc("ALSA PCM on %s (%s)", dev, snd_pcm_info_get_name(pcm_info)); u->pcm_fdl = pa_alsa_fdlist_new(); assert(u->pcm_fdl); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index b5cf9c705..63369e479 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -450,7 +450,7 @@ int pa__init(pa_core *c, pa_module*m) { } } pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s' (%s)", dev, snd_pcm_info_get_name(pcm_info)); + u->source->description = pa_sprintf_malloc("ALSA PCM on %s (%s)", dev, snd_pcm_info_get_name(pcm_info)); u->pcm_fdl = pa_alsa_fdlist_new(); assert(u->pcm_fdl); diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index d6f376339..4212febe5 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -439,7 +439,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source->get_hw_volume = source_get_hw_volume; u->source->set_hw_volume = source_set_hw_volume; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'%s%s%s", + u->source->description = pa_sprintf_malloc("OSS PCM/mmap() on %s%s%s%s", p, hwdesc[0] ? " (" : "", hwdesc[0] ? hwdesc : "", @@ -480,7 +480,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->set_hw_volume = sink_set_hw_volume; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Open Sound System PCM/mmap() on '%s'%s%s%s", + u->sink->description = pa_sprintf_malloc("OSS PCM/mmap() on %s%s%s%s", p, hwdesc[0] ? " (" : "", hwdesc[0] ? hwdesc : "", diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index cde7f3119..c9fce7a72 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -413,7 +413,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source->get_hw_volume = source_get_hw_volume; u->source->set_hw_volume = source_set_hw_volume; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Open Sound System PCM on '%s'%s%s%s", + u->source->description = pa_sprintf_malloc("OSS PCM on %s%s%s%s", p, hwdesc[0] ? " (" : "", hwdesc[0] ? hwdesc : "", @@ -431,7 +431,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->set_hw_volume = sink_set_hw_volume; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Open Sound System PCM on '%s'%s%s%s", + u->sink->description = pa_sprintf_malloc("OSS PCM on %s%s%s%s", p, hwdesc[0] ? " (" : "", hwdesc[0] ? hwdesc : "", From 0aebc03d1ad0820dac76057a0474a4bd7c025c76 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 17:15:41 +0000 Subject: [PATCH 1102/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1202 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/todo b/todo index 5c2edf759..89239db05 100644 --- a/todo +++ b/todo @@ -3,7 +3,7 @@ Post 0.9.0: - alsa mmap driver - alsa driver with hw mixing -- dbus/hal (Shams King is working on this one) +- merge module-oss-mmap into module-oss - chroot() - module-tunnel: improve latency calculation - multiline configuration statements @@ -34,6 +34,8 @@ Post 0.9.0: - key rings for auth - challenge response auth - sasl auth +- fix OSS hot-remove +- use better sink/source names, generated from the device file names Long term: - pass meta info for hearing impaired From c90dd53268bec8516be3b37e8af1989290f022a2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 17:53:34 +0000 Subject: [PATCH 1103/1514] * introduce new functions pa_sink_set_description() and pa_source_set_description() for changing the description of a sink/source * allow sinks without monitor sources attached git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1203 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sink.c | 58 ++++++++++++++++++++++++++++++++++-------- src/pulsecore/sink.h | 2 ++ src/pulsecore/source.c | 16 ++++++++++++ src/pulsecore/source.h | 3 +++ 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 8acb77156..eecf89cce 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -118,12 +118,19 @@ pa_sink* pa_sink_new( pa_sample_spec_snprint(st, sizeof(st), spec); pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); - n = pa_sprintf_malloc("%s_monitor", name); - s->monitor_source = pa_source_new(core, driver, n, 0, spec, map); - assert(s->monitor_source); + n = pa_sprintf_malloc("%s.monitor", name); + + if (!(s->monitor_source = pa_source_new(core, driver, n, 0, spec, map))) + pa_log_warn(__FILE__": failed to create monitor source."); + else { + char *d; + s->monitor_source->monitor_of = s; + d = pa_sprintf_malloc("Monitor Source of %s", s->name); + pa_source_set_description(s->monitor_source, d); + pa_xfree(d); + } + pa_xfree(n); - s->monitor_source->monitor_of = s; - s->monitor_source->description = pa_sprintf_malloc("Monitor source of sink '%s'", s->name); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); @@ -144,7 +151,8 @@ void pa_sink_disconnect(pa_sink* s) { j = i; } - pa_source_disconnect(s->monitor_source); + if (s->monitor_source) + pa_source_disconnect(s->monitor_source); pa_idxset_remove_by_data(s->core->sinks, s, NULL); @@ -168,8 +176,10 @@ static void sink_free(pa_sink *s) { pa_log_info(__FILE__": freed %u \"%s\"", s->index, s->name); - pa_source_unref(s->monitor_source); - s->monitor_source = NULL; + if (s->monitor_source) { + pa_source_unref(s->monitor_source); + s->monitor_source = NULL; + } pa_idxset_free(s->inputs, NULL, NULL); @@ -304,7 +314,9 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { } inputs_drop(s, info, n, result->length); - pa_source_post(s->monitor_source, result); + + if (s->monitor_source) + pa_source_post(s->monitor_source, result); r = 0; @@ -358,7 +370,9 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { s->sw_muted); inputs_drop(s, info, n, target->length); - pa_source_post(s->monitor_source, target); + + if (s->monitor_source) + pa_source_post(s->monitor_source, target); r = 0; @@ -513,3 +527,27 @@ int pa_sink_get_mute(pa_sink *s, pa_mixer_t m) { } else return s->sw_muted; } + +void pa_sink_set_description(pa_sink *s, const char *description) { + assert(s); + assert(s->ref >= 1); + + if (!description && !s->description) + return; + + if (description && s->description && !strcmp(description, s->description)) + return; + + pa_xfree(s->description); + s->description = pa_xstrdup(description); + + if (s->monitor_source) { + char *n; + + n = pa_sprintf_malloc("Monitor Source of %s", s->description? s->description : s->name); + pa_source_set_description(s->monitor_source, n); + pa_xfree(n); + } + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); +} diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 1a6bc9886..5a80a0133 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -100,4 +100,6 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_mixer_t m); void pa_sink_set_mute(pa_sink *sink, pa_mixer_t m, int mute); int pa_sink_get_mute(pa_sink *sink, pa_mixer_t m); +void pa_sink_set_description(pa_sink *s, const char *description); + #endif diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 48b6daea1..f9c0703d8 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -313,3 +313,19 @@ int pa_source_get_mute(pa_source *s, pa_mixer_t m) { } else return s->sw_muted; } + +void pa_source_set_description(pa_source *s, const char *description) { + assert(s); + assert(s->ref >= 1); + + if (!description && !s->description) + return; + + if (description && s->description && !strcmp(description, s->description)) + return; + + pa_xfree(s->description); + s->description = pa_xstrdup(description); + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); +} diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index 878ae34d7..0643a108b 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -100,4 +100,7 @@ const pa_cvolume *pa_source_get_volume(pa_source *source, pa_mixer_t m); void pa_source_set_mute(pa_source *source, pa_mixer_t m, int mute); int pa_source_get_mute(pa_source *source, pa_mixer_t m); +void pa_source_set_description(pa_source *s, const char *description); + + #endif From af1b0317f653a3da092b45de3b27643359b9a85e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 23:31:59 +0000 Subject: [PATCH 1104/1514] comment which values in pa_{sink,source,sink_input,source_output} structures may be NULL git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1204 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sink-input.h | 16 ++++++++-------- src/pulsecore/sink.h | 23 ++++++++++++----------- src/pulsecore/source-output.h | 12 ++++++------ src/pulsecore/source.h | 20 +++++++++++--------- 4 files changed, 37 insertions(+), 34 deletions(-) diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index b1971d0a9..d33f382b9 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -45,11 +45,11 @@ struct pa_sink_input { uint32_t index; pa_sink_input_state_t state; - char *name, *driver; - pa_module *owner; + char *name, *driver; /* may be NULL */ + pa_module *owner; /* may be NULL */ pa_sink *sink; - pa_client *client; + pa_client *client; /* may be NULL */ pa_sample_spec sample_spec; pa_channel_map channel_map; @@ -63,19 +63,19 @@ struct pa_sink_input { int (*peek) (pa_sink_input *i, pa_memchunk *chunk); void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length); - void (*kill) (pa_sink_input *i); - pa_usec_t (*get_latency) (pa_sink_input *i); - void (*underrun) (pa_sink_input *i); + void (*kill) (pa_sink_input *i); /* may be NULL */ + pa_usec_t (*get_latency) (pa_sink_input *i); /* may be NULL */ + void (*underrun) (pa_sink_input *i); /* may be NULL */ void *userdata; pa_memchunk resampled_chunk; - pa_resampler *resampler; + pa_resampler *resampler; /* may be NULL */ int variable_rate; pa_resample_method_t resample_method; - pa_memblock *silence_memblock; + pa_memblock *silence_memblock; /* may be NULL */ }; pa_sink_input* pa_sink_input_new( diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 5a80a0133..fb0912cac 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -48,26 +48,27 @@ struct pa_sink { pa_core *core; pa_sink_state_t state; - char *name, *description, *driver; - pa_module *owner; + char *name; + char *description, *driver; /* may be NULL */ + int is_hardware; + + pa_module *owner; /* may be NULL */ pa_sample_spec sample_spec; pa_channel_map channel_map; pa_idxset *inputs; - pa_source *monitor_source; + pa_source *monitor_source; /* may be NULL */ pa_cvolume hw_volume, sw_volume; int hw_muted, sw_muted; - int is_hardware; - - void (*notify)(pa_sink*sink); - pa_usec_t (*get_latency)(pa_sink *s); - int (*set_hw_volume)(pa_sink *s); - int (*get_hw_volume)(pa_sink *s); - int (*set_hw_mute)(pa_sink *s); - int (*get_hw_mute)(pa_sink *s); + void (*notify)(pa_sink*sink); /* may be NULL */ + pa_usec_t (*get_latency)(pa_sink *s); /* dito */ + int (*set_hw_volume)(pa_sink *s); /* dito */ + int (*get_hw_volume)(pa_sink *s); /* dito */ + int (*set_hw_mute)(pa_sink *s); /* dito */ + int (*get_hw_mute)(pa_sink *s); /* dito */ void *userdata; }; diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index 9a8ea92b5..acf53bd1f 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -44,20 +44,20 @@ struct pa_source_output { uint32_t index; pa_source_output_state_t state; - char *name, *driver; - pa_module *owner; + char *name, *driver; /* may be NULL */ + pa_module *owner; /* may be NULL */ pa_source *source; - pa_client *client; + pa_client *client; /* may be NULL */ pa_sample_spec sample_spec; pa_channel_map channel_map; void (*push)(pa_source_output *o, const pa_memchunk *chunk); - void (*kill)(pa_source_output* o); - pa_usec_t (*get_latency) (pa_source_output *o); + void (*kill)(pa_source_output* o); /* may be NULL */ + pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */ - pa_resampler* resampler; + pa_resampler* resampler; /* may be NULL */ pa_resample_method_t resample_method; void *userdata; diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index 0643a108b..be0c969dc 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -50,26 +50,28 @@ struct pa_source { pa_core *core; pa_source_state_t state; - char *name, *description, *driver; - pa_module *owner; + char *name; + char *description, *driver; /* may be NULL */ + + pa_module *owner; /* may be NULL */ pa_sample_spec sample_spec; pa_channel_map channel_map; pa_idxset *outputs; - pa_sink *monitor_of; + pa_sink *monitor_of; /* may be NULL */ pa_cvolume hw_volume, sw_volume; int hw_muted, sw_muted; int is_hardware; - void (*notify)(pa_source*source); - pa_usec_t (*get_latency)(pa_source *s); - int (*set_hw_volume)(pa_source *s); - int (*get_hw_volume)(pa_source *s); - int (*set_hw_mute)(pa_source *s); - int (*get_hw_mute)(pa_source *s); + void (*notify)(pa_source*source); /* may be NULL */ + pa_usec_t (*get_latency)(pa_source *s); /* dito */ + int (*set_hw_volume)(pa_source *s); /* dito */ + int (*get_hw_volume)(pa_source *s); /* dito */ + int (*set_hw_mute)(pa_source *s); /* dito */ + int (*get_hw_mute)(pa_source *s); /* dito */ void *userdata; }; From bfa6604b1ddc5e2c0f1aaa15330363724856359b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 23:58:55 +0000 Subject: [PATCH 1105/1514] don't set the sink/source descriptions manually, use the new functions pa_{sink,source}_set_description() instead git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1205 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 6 ++++-- src/modules/module-alsa-source.c | 4 +++- src/modules/module-combine.c | 2 +- src/modules/module-esound-sink.c | 5 ++++- src/modules/module-jack-sink.c | 4 +++- src/modules/module-jack-source.c | 4 +++- src/modules/module-null-sink.c | 2 +- src/modules/module-oss-mmap.c | 24 +++++++++++++----------- src/modules/module-oss.c | 24 +++++++++++++----------- src/modules/module-pipe-sink.c | 6 ++++-- src/modules/module-pipe-source.c | 6 ++++-- src/modules/module-solaris.c | 7 +++++-- src/modules/module-tunnel.c | 9 +++++++-- src/modules/module-waveout.c | 4 ++-- src/modules/module-zeroconf-publish.c | 3 ++- 15 files changed, 69 insertions(+), 41 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 649fe99cf..efecfc21e 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -366,7 +366,8 @@ int pa__init(pa_core *c, pa_module*m) { size_t frame_size; snd_pcm_info_t *pcm_info = NULL; int err; - + char *t; + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments"); goto fail; @@ -457,7 +458,8 @@ int pa__init(pa_core *c, pa_module*m) { } u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("ALSA PCM on %s (%s)", dev, snd_pcm_info_get_name(pcm_info)); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("ALSA PCM on %s (%s)", dev, snd_pcm_info_get_name(pcm_info))); + pa_xfree(t); u->pcm_fdl = pa_alsa_fdlist_new(); assert(u->pcm_fdl); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 63369e479..6149224ad 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -359,6 +359,7 @@ int pa__init(pa_core *c, pa_module*m) { size_t frame_size; snd_pcm_info_t *pcm_info = NULL; int err; + char *t; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments"); @@ -450,7 +451,8 @@ int pa__init(pa_core *c, pa_module*m) { } } pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("ALSA PCM on %s (%s)", dev, snd_pcm_info_get_name(pcm_info)); + pa_source_set_description(u->source, t = pa_sprintf_malloc("ALSA PCM on %s (%s)", dev, snd_pcm_info_get_name(pcm_info))); + pa_xfree(t); u->pcm_fdl = pa_alsa_fdlist_new(); assert(u->pcm_fdl); diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 4e3dd555e..0a5bd4720 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -381,7 +381,7 @@ int pa__init(pa_core *c, pa_module*m) { } pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Combined sink"); + pa_sink_set_description(u->sink, "Combined sink"); u->sink->get_latency = sink_get_latency_cb; u->sink->userdata = u; diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 86ffaf788..9f0c2c5b0 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -320,6 +320,8 @@ int pa__init(pa_core *c, pa_module*m) { const char *p; pa_sample_spec ss; pa_modargs *ma = NULL; + char *t; + assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -381,7 +383,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_latency = get_latency_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Esound sink '%s'", p); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Esound sink '%s'", p)); + pa_xfree(t); u->memchunk.memblock = NULL; u->memchunk.length = 0; diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index c645caa99..286f6f579 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -245,6 +245,7 @@ int pa__init(pa_core *c, pa_module*m) { int do_connect = 1; unsigned i; const char **ports = NULL, **p; + char *t; assert(c); assert(m); @@ -328,7 +329,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Jack sink (%s)", jack_get_client_name(u->client)); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Jack sink (%s)", jack_get_client_name(u->client))); + pa_xfree(t); u->sink->get_latency = sink_get_latency_cb; jack_set_process_callback(u->client, jack_process, u); diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 2a4929292..583f3b8e9 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -243,6 +243,7 @@ int pa__init(pa_core *c, pa_module*m) { int do_connect = 1; unsigned i; const char **ports = NULL, **p; + char *t; assert(c); assert(m); @@ -326,7 +327,8 @@ int pa__init(pa_core *c, pa_module*m) { u->source->userdata = u; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Jack source (%s)", jack_get_client_name(u->client)); + pa_source_set_description(u->source, t = pa_sprintf_malloc("Jack source (%s)", jack_get_client_name(u->client))); + pa_xfree(t); u->source->get_latency = source_get_latency_cb; jack_set_process_callback(u->client, jack_process, u); diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 470be6bca..73cacc723 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -141,7 +141,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_latency = get_latency; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_xstrdup("NULL sink"); + pa_sink_set_description(u->sink, "NULL sink"); u->n_bytes = 0; pa_gettimeofday(&u->start_time); diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 4212febe5..cc408f903 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -349,7 +349,7 @@ int pa__init(pa_core *c, pa_module*m) { int enable_bits = 0, zero = 0; int playback = 1, record = 1; pa_modargs *ma = NULL; - char hwdesc[64]; + char hwdesc[64], *t; pa_channel_map map; assert(c); @@ -439,11 +439,12 @@ int pa__init(pa_core *c, pa_module*m) { u->source->get_hw_volume = source_get_hw_volume; u->source->set_hw_volume = source_set_hw_volume; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("OSS PCM/mmap() on %s%s%s%s", - p, - hwdesc[0] ? " (" : "", - hwdesc[0] ? hwdesc : "", - hwdesc[0] ? ")" : ""); + pa_source_set_description(u->source, t = pa_sprintf_malloc("OSS PCM/mmap() on %s%s%s%s", + p, + hwdesc[0] ? " (" : "", + hwdesc[0] ? hwdesc : "", + hwdesc[0] ? ")" : "")); + pa_xfree(t); u->source->is_hardware = 1; u->in_memblocks = pa_xnew0(pa_memblock*, u->in_fragments); @@ -480,11 +481,12 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->set_hw_volume = sink_set_hw_volume; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("OSS PCM/mmap() on %s%s%s%s", - p, - hwdesc[0] ? " (" : "", - hwdesc[0] ? hwdesc : "", - hwdesc[0] ? ")" : ""); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("OSS PCM/mmap() on %s%s%s%s", + p, + hwdesc[0] ? " (" : "", + hwdesc[0] ? hwdesc : "", + hwdesc[0] ? ")" : "")); + pa_xfree(t); u->sink->is_hardware = 1; u->out_memblocks = pa_xmalloc0(sizeof(struct memblock *)*u->out_fragments); diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index c9fce7a72..085ae5da3 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -326,7 +326,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; - char hwdesc[64]; + char hwdesc[64], *t; assert(c); assert(m); @@ -413,11 +413,12 @@ int pa__init(pa_core *c, pa_module*m) { u->source->get_hw_volume = source_get_hw_volume; u->source->set_hw_volume = source_set_hw_volume; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("OSS PCM on %s%s%s%s", - p, - hwdesc[0] ? " (" : "", - hwdesc[0] ? hwdesc : "", - hwdesc[0] ? ")" : ""); + pa_source_set_description(u->source, t = pa_sprintf_malloc("OSS PCM on %s%s%s%s", + p, + hwdesc[0] ? " (" : "", + hwdesc[0] ? hwdesc : "", + hwdesc[0] ? ")" : "")); + pa_xfree(t); u->source->is_hardware = 1; } else u->source = NULL; @@ -431,11 +432,12 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->set_hw_volume = sink_set_hw_volume; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("OSS PCM on %s%s%s%s", - p, - hwdesc[0] ? " (" : "", - hwdesc[0] ? hwdesc : "", - hwdesc[0] ? ")" : ""); + pa_sink_set_description(u->sink, pa_sprintf_malloc("OSS PCM on %s%s%s%s", + p, + hwdesc[0] ? " (" : "", + hwdesc[0] ? hwdesc : "", + hwdesc[0] ? ")" : "")); + pa_xfree(t); u->sink->is_hardware = 1; } else u->sink = NULL; diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 4878a1a10..cc5276d48 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -148,6 +148,8 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; + char *t; + assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -194,8 +196,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_latency = get_latency_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Unix FIFO sink '%s'", p); - assert(u->sink->description); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", p)); + pa_xfree(t); u->io = pa_iochannel_new(c->mainloop, -1, fd); assert(u->io); diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index f2f214c7b..5caa60a3e 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -126,6 +126,8 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; + char *t; + assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -169,8 +171,8 @@ int pa__init(pa_core *c, pa_module*m) { } u->source->userdata = u; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Unix FIFO source '%s'", p); - assert(u->source->description); + pa_source_set_description(u->source, t = pa_sprintf_malloc("Unix FIFO source '%s'", p)); + pa_xfree(t); u->io = pa_iochannel_new(c->mainloop, fd, -1); assert(u->io); diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 02ef4bc4a..21a72b38a 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -500,6 +500,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_channel_map map; pa_modargs *ma = NULL; struct timeval tv; + char *t; assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -554,7 +555,8 @@ int pa__init(pa_core *c, pa_module*m) { u->source->get_hw_volume = source_get_hw_volume_cb; u->source->set_hw_volume = source_set_hw_volume_cb; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + pa_source_set_description(u->source, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); + pa_xfree(t); u->source->is_hardware = 1; } else u->source = NULL; @@ -569,7 +571,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->set_hw_mute = sink_set_hw_mute_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); + pa_xfree(t); u->sink->is_hardware = 1; } else u->sink = NULL; diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 2fb34d12b..9bb11c094 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -859,6 +859,8 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_channel_map map; struct timeval ntv; + char *t; + assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -925,7 +927,8 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_hw_mute = sink_get_hw_mute; u->sink->set_hw_mute = sink_set_hw_mute; u->sink->userdata = u; - u->sink->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->sink_name ? u->sink_name : "", u->sink_name ? "@" : "", u->server_name); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->sink_name ? u->sink_name : "", u->sink_name ? "@" : "", u->server_name)); + pa_xfree(t); pa_sink_set_owner(u->sink, m); #else @@ -940,7 +943,9 @@ int pa__init(pa_core *c, pa_module*m) { u->source->get_hw_mute = source_get_hw_mute; u->source->set_hw_mute = source_set_hw_mute; u->source->userdata = u; - u->source->description = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->source_name ? u->source_name : "", u->source_name ? "@" : "", u->server_name); + + pa_source_set_description(u->source, t = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->source_name ? u->source_name : "", u->source_name ? "@" : "", u->server_name)); + pa_xfree(t); pa_source_set_owner(u->source, m); #endif diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 8fd60b6ac..27e8de580 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -503,7 +503,7 @@ int pa__init(pa_core *c, pa_module*m) { u->source->notify = notify_source_cb; u->source->get_latency = source_get_latency_cb; pa_source_set_owner(u->source, m); - u->source->description = pa_sprintf_malloc("Windows waveIn PCM"); + pa_source_set_description(u->source, "Windows waveIn PCM"); u->source->is_hardware = 1; } else u->source = NULL; @@ -517,7 +517,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->set_hw_volume = sink_set_hw_volume_cb; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - u->sink->description = pa_sprintf_malloc("Windows waveOut PCM"); + pa_sink_set_description(u->sink, "Windows waveOut PCM"); u->sink->is_hardware = 1; } else u->sink = NULL; diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 23a188b3e..16315d350 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -185,7 +185,8 @@ static int publish_service(struct userdata *u, struct service *s) { txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate); txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels); txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format)); - txt = avahi_string_list_add_pair(txt, "description", description); + if (description) + txt = avahi_string_list_add_pair(txt, "description", description); type = s->loaded.type; } else if (s->autoload.valid) From 8da9b94af667b066b6ab2bb86553bedae330e27b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 00:25:52 +0000 Subject: [PATCH 1106/1514] allow setting the null sink description by a module parameter git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1206 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-null-sink.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 73cacc723..4d5ebb084 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -53,7 +53,8 @@ PA_MODULE_USAGE( "channels= " "rate= " "sink_name=" - "channel_map=") + "channel_map=" + "description=") #define DEFAULT_SINK_NAME "null" @@ -73,7 +74,8 @@ static const char* const valid_modargs[] = { "format", "channels", "sink_name", - "channel_map", + "channel_map", + "description", NULL }; @@ -141,7 +143,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_latency = get_latency; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, "NULL sink"); + pa_sink_set_description(u->sink, pa_modargs_get_value(ma, "description", "NULL sink")); u->n_bytes = 0; pa_gettimeofday(&u->start_time); From 1e12c75ba1a236bd5a8304c4c6c4aae28e9e6179 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 00:26:17 +0000 Subject: [PATCH 1107/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1207 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/todo b/todo index 89239db05..c9c9a86e5 100644 --- a/todo +++ b/todo @@ -36,6 +36,8 @@ Post 0.9.0: - sasl auth - fix OSS hot-remove - use better sink/source names, generated from the device file names +- subscription: filter out superfluous events +- make sure that everyone knows how to deal with sinks without a monitor source Long term: - pass meta info for hearing impaired From bb961569eb562b4c92617098627f8092098955d0 Mon Sep 17 00:00:00 2001 From: "Shahms E. King" Date: Sat, 12 Aug 2006 01:17:19 +0000 Subject: [PATCH 1108/1514] increase module argument buffer size to prevent truncating names git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1208 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 0063fdbd3..54d139ecb 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -157,7 +157,7 @@ static int hal_device_get_alsa_device(LibHalContext *ctx, const char *udi, static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, DBusError *error) { - char args[64]; + char args[128]; alsa_type_t type; int device, card; const char *module_name; @@ -218,7 +218,7 @@ exit: static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, DBusError *error) { - char args[128]; + char args[256]; char* device; if (!hal_device_is_oss_pcm(u->ctx, udi, error) || dbus_error_is_set(error)) From e9d9356d110945bf9bc8c3ca0e1cb0b1d42a67a1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 02:16:12 +0000 Subject: [PATCH 1109/1514] add new macro PA_LLIST_INSERT_AFTER git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1209 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/llist.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/llist.h b/src/pulsecore/llist.h index bf3c150ae..9ce24e74a 100644 --- a/src/pulsecore/llist.h +++ b/src/pulsecore/llist.h @@ -73,7 +73,24 @@ do { \ assert(_head); \ while ((*_head)->prev) \ *_head = (*_head)->prev; \ -} while (0) \ +} while (0) +#define PA_LLIST_INSERT_AFTER(t,head,a,b) \ +do { \ + t **_head = &(head), *_a = (a), *_b = (b); \ + assert(_b); \ + if (!_a) { \ + if ((_b->next = *_head)) \ + _b->next->prev = _b; \ + _b->prev = NULL; \ + *_head = _b; \ + } else { \ + if ((_b->next = _a->next)) \ + _b->next->prev = _b; \ + _b->prev = _a; \ + _a->next = _b; \ + } \ +} while (0) + #endif From f8e5f47e233fc401eec5e2c7fdeab46c7314a6b2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 02:16:47 +0000 Subject: [PATCH 1110/1514] fix a compiler warning git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1210 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index 3568059e6..cdf95adac 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -223,8 +223,8 @@ static void free_callback(void *p, PA_GCC_UNUSED void *userdata) { } void pa_module_unload_all(pa_core *c) { - assert(c); pa_module *m; + assert(c); if (!c->modules) return; From 47d009afd69612aa97fd368fd481734f1c52909a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 02:18:24 +0000 Subject: [PATCH 1111/1514] rework subscription code: try to drop redundant queued events git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1211 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-subscribe.c | 203 +++++++++++++++++++-------------- src/pulsecore/core-subscribe.h | 4 +- src/pulsecore/core.c | 5 +- src/pulsecore/core.h | 10 +- 4 files changed, 127 insertions(+), 95 deletions(-) diff --git a/src/pulsecore/core-subscribe.c b/src/pulsecore/core-subscribe.c index e865256aa..2c6256329 100644 --- a/src/pulsecore/core-subscribe.c +++ b/src/pulsecore/core-subscribe.c @@ -43,75 +43,81 @@ struct pa_subscription { pa_core *core; int dead; - void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata); + + pa_subscription_cb_t callback; void *userdata; pa_subscription_mask_t mask; - pa_subscription *prev, *next; + PA_LLIST_FIELDS(pa_subscription); }; struct pa_subscription_event { + pa_core *core; + pa_subscription_event_type_t type; uint32_t index; + + PA_LLIST_FIELDS(pa_subscription_event); }; static void sched_event(pa_core *c); /* Allocate a new subscription object for the given subscription mask. Use the specified callback function and user data */ -pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata) { +pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_subscription_cb_t callback, void *userdata) { pa_subscription *s; + assert(c); + assert(m); + assert(callback); - s = pa_xmalloc(sizeof(pa_subscription)); + s = pa_xnew(pa_subscription, 1); s->core = c; s->dead = 0; s->callback = callback; s->userdata = userdata; s->mask = m; - if ((s->next = c->subscriptions)) - s->next->prev = s; - s->prev = NULL; - c->subscriptions = s; + PA_LLIST_PREPEND(pa_subscription, c->subscriptions, s); return s; } /* Free a subscription object, effectively marking it for deletion */ void pa_subscription_free(pa_subscription*s) { - assert(s && !s->dead); + assert(s); + assert(!s->dead); + s->dead = 1; sched_event(s->core); } -static void free_item(pa_subscription *s) { - assert(s && s->core); +static void free_subscription(pa_subscription *s) { + assert(s); + assert(s->core); - if (s->prev) - s->prev->next = s->next; - else - s->core->subscriptions = s->next; - - if (s->next) - s->next->prev = s->prev; + PA_LLIST_REMOVE(pa_subscription, s->core->subscriptions, s); + pa_xfree(s); +} + +static void free_event(pa_subscription_event *s) { + assert(s); + assert(s->core); + + if (!s->next) + s->core->subscription_event_last = s->prev; + PA_LLIST_REMOVE(pa_subscription_event, s->core->subscription_event_queue, s); pa_xfree(s); } /* Free all subscription objects */ void pa_subscription_free_all(pa_core *c) { - pa_subscription_event *e; assert(c); while (c->subscriptions) - free_item(c->subscriptions); + free_subscription(c->subscriptions); - if (c->subscription_event_queue) { - while ((e = pa_queue_pop(c->subscription_event_queue))) - pa_xfree(e); - - pa_queue_free(c->subscription_event_queue, NULL, NULL); - c->subscription_event_queue = NULL; - } + while (c->subscription_event_queue) + free_event(c->subscription_event_queue); if (c->subscription_defer_event) { c->mainloop->defer_free(c->subscription_defer_event); @@ -119,48 +125,31 @@ void pa_subscription_free_all(pa_core *c) { } } -#if 0 -static void dump_event(pa_subscription_event*e) { - switch (e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { - case PA_SUBSCRIPTION_EVENT_SINK: - pa_log(__FILE__": SINK_EVENT"); - break; - case PA_SUBSCRIPTION_EVENT_SOURCE: - pa_log(__FILE__": SOURCE_EVENT"); - break; - case PA_SUBSCRIPTION_EVENT_SINK_INPUT: - pa_log(__FILE__": SINK_INPUT_EVENT"); - break; - case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: - pa_log(__FILE__": SOURCE_OUTPUT_EVENT"); - break; - case PA_SUBSCRIPTION_EVENT_MODULE: - pa_log(__FILE__": MODULE_EVENT"); - break; - case PA_SUBSCRIPTION_EVENT_CLIENT: - pa_log(__FILE__": CLIENT_EVENT"); - break; - default: - pa_log(__FILE__": OTHER"); - break; - } +#ifdef DEBUG +static void dump_event(const char * prefix, pa_subscription_event*e) { + const char * const fac_table[] = { + [PA_SUBSCRIPTION_EVENT_SINK] = "SINK", + [PA_SUBSCRIPTION_EVENT_SOURCE] = "SOURCE", + [PA_SUBSCRIPTION_EVENT_SINK_INPUT] = "SINK_INPUT", + [PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT] = "SOURCE_OUTPUT", + [PA_SUBSCRIPTION_EVENT_MODULE] = "MODULE", + [PA_SUBSCRIPTION_EVENT_CLIENT] = "CLIENT", + [PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE] = "SAMPLE_CACHE", + [PA_SUBSCRIPTION_EVENT_SERVER] = "SERVER", + [PA_SUBSCRIPTION_EVENT_AUTOLOAD] = "AUTOLOAD" + }; - switch (e->type & PA_SUBSCRIPTION_EVENT_TYPE_MASK) { - case PA_SUBSCRIPTION_EVENT_NEW: - pa_log(__FILE__": NEW"); - break; - case PA_SUBSCRIPTION_EVENT_CHANGE: - pa_log(__FILE__": CHANGE"); - break; - case PA_SUBSCRIPTION_EVENT_REMOVE: - pa_log(__FILE__": REMOVE"); - break; - default: - pa_log(__FILE__": OTHER"); - break; - } + const char * const type_table[] = { + [PA_SUBSCRIPTION_EVENT_NEW] = "NEW", + [PA_SUBSCRIPTION_EVENT_CHANGE] = "CHANGE", + [PA_SUBSCRIPTION_EVENT_REMOVE] = "REMOVE" + }; - pa_log(__FILE__": %u", e->index); + pa_log(__FILE__": %s event (%s|%s|%u)", + prefix, + fac_table[e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK], + type_table[e->type & PA_SUBSCRIPTION_EVENT_TYPE_MASK], + e->index); } #endif @@ -168,25 +157,28 @@ static void dump_event(pa_subscription_event*e) { static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) { pa_core *c = userdata; pa_subscription *s; - assert(c && c->subscription_defer_event == de && c->mainloop == m); + + assert(c->mainloop == m); + assert(c); + assert(c->subscription_defer_event == de); c->mainloop->defer_enable(c->subscription_defer_event, 0); /* Dispatch queued events */ - - if (c->subscription_event_queue) { - pa_subscription_event *e; - - while ((e = pa_queue_pop(c->subscription_event_queue))) { - for (s = c->subscriptions; s; s = s->next) { + while (c->subscription_event_queue) { + pa_subscription_event *e = c->subscription_event_queue; - if (!s->dead && pa_subscription_match_flags(s->mask, e->type)) - s->callback(c, e->type, e->index, s->userdata); - } + for (s = c->subscriptions; s; s = s->next) { - pa_xfree(e); + if (!s->dead && pa_subscription_match_flags(s->mask, e->type)) + s->callback(c, e->type, e->index, s->userdata); } + +#ifdef DEBUG + dump_event("Dispatched", e); +#endif + free_event(e); } /* Remove dead subscriptions */ @@ -195,7 +187,7 @@ static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) { while (s) { pa_subscription *n = s->next; if (s->dead) - free_item(s); + free_subscription(s); s = n; } } @@ -217,17 +209,52 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i pa_subscription_event *e; assert(c); - e = pa_xmalloc(sizeof(pa_subscription_event)); + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_NEW) { + pa_subscription_event *i, *n; + + /* Check for duplicates */ + for (i = c->subscription_event_last; i; i = n) { + n = i->prev; + + /* not the same object type */ + if (((t ^ i->type) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)) + continue; + + /* not the same object */ + if (i->index != index) + continue; + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + /* This object is being removed, hence there is no + * point in keeping the old events regarding this + * entry in the queue. */ + + free_event(i); + pa_log_debug(__FILE__": dropped redundant event."); + continue; + } + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE) { + /* This object has changed. If a "new" or "change" event for + * this object is still in the queue we can exit. */ + + pa_log_debug(__FILE__": dropped redundant event."); + return; + } + } + } + + e = pa_xnew(pa_subscription_event, 1); + e->core = c; e->type = t; e->index = index; - if (!c->subscription_event_queue) { - c->subscription_event_queue = pa_queue_new(); - assert(c->subscription_event_queue); - } - - pa_queue_push(c->subscription_event_queue, e); + PA_LLIST_INSERT_AFTER(pa_subscription_event, c->subscription_event_queue, c->subscription_event_last, e); + c->subscription_event_last = e; + +#ifdef DEBUG + dump_event("Queued", e); +#endif + sched_event(c); } - - diff --git a/src/pulsecore/core-subscribe.h b/src/pulsecore/core-subscribe.h index c24670336..6e3b646eb 100644 --- a/src/pulsecore/core-subscribe.h +++ b/src/pulsecore/core-subscribe.h @@ -28,7 +28,9 @@ typedef struct pa_subscription_event pa_subscription_event; #include #include -pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, void (*callback)(pa_core *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata); +typedef void (*pa_subscription_cb_t)(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata); + +pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_subscription_cb_t cb, void *userdata); void pa_subscription_free(pa_subscription*s); void pa_subscription_free_all(pa_core *c); diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index d6af3ca91..710e00ad6 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -74,8 +74,9 @@ pa_core* pa_core_new(pa_mainloop_api *m) { c->scache_auto_unload_event = NULL; c->subscription_defer_event = NULL; - c->subscription_event_queue = NULL; - c->subscriptions = NULL; + PA_LLIST_HEAD_INIT(pa_subscription, c->subscriptions); + PA_LLIST_HEAD_INIT(pa_subscription_event, c->subscription_event_queue); + c->subscription_event_last = NULL; c->memblock_stat = pa_memblock_stat_new(); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 61f174321..391ba9b86 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -24,14 +24,15 @@ typedef struct pa_core pa_core; -#include -#include #include #include +#include +#include #include #include #include #include +#include /* The core structure of PulseAudio. Every PulseAudio daemon contains * exactly one of these. It is used for storing kind of global @@ -58,8 +59,9 @@ struct pa_core { pa_defer_event *module_defer_unload_event; pa_defer_event *subscription_defer_event; - pa_queue *subscription_event_queue; - pa_subscription *subscriptions; + PA_LLIST_HEAD(pa_subscription, subscriptions); + PA_LLIST_HEAD(pa_subscription_event, subscription_event_queue); + pa_subscription_event *subscription_event_last; pa_memblock_stat *memblock_stat; From 3aba099fc3e515db5c4b1f2990c48fdb4160ff52 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 02:19:36 +0000 Subject: [PATCH 1112/1514] clean up event generation a little: suppress unnecessary events and generate new ones on owner change git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1212 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sink-input.c | 6 ++++++ src/pulsecore/sink.c | 7 ++++++- src/pulsecore/source-output.c | 6 ++++++ src/pulsecore/source.c | 4 ++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index b89210f4b..701d7f6cc 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -437,6 +437,12 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name) { assert(i); assert(i->ref >= 1); + if (!i->name && !name) + return; + + if (i->name && name && !strcmp(i->name, name)) + return; + pa_xfree(i->name); i->name = pa_xstrdup(name); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index eecf89cce..d1d9785af 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -446,11 +446,16 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) { void pa_sink_set_owner(pa_sink *s, pa_module *m) { assert(s); assert(s->ref >= 1); - + + if (s->owner == m) + return; + s->owner = m; if (s->monitor_source) pa_source_set_owner(s->monitor_source, m); + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } void pa_sink_set_volume(pa_sink *s, pa_mixer_t m, const pa_cvolume *volume) { diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 1ffaedae9..36ea420ca 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -208,6 +208,12 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { void pa_source_output_set_name(pa_source_output *o, const char *name) { assert(o); assert(o->ref >= 1); + + if (!o->name && !name) + return; + + if (o->name && name && !strcmp(o->name, name)) + return; pa_xfree(o->name); o->name = pa_xstrdup(name); diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index f9c0703d8..903de88b3 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -225,8 +225,12 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) { void pa_source_set_owner(pa_source *s, pa_module *m) { assert(s); assert(s->ref >= 1); + + if (m == s->owner) + return; s->owner = m; + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } pa_usec_t pa_source_get_latency(pa_source *s) { From 365ceec6d61524b157b95e5b0cca11080f63ab49 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 02:20:05 +0000 Subject: [PATCH 1113/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1213 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index c9c9a86e5..c5ad29f8d 100644 --- a/todo +++ b/todo @@ -36,7 +36,6 @@ Post 0.9.0: - sasl auth - fix OSS hot-remove - use better sink/source names, generated from the device file names -- subscription: filter out superfluous events - make sure that everyone knows how to deal with sinks without a monitor source Long term: From adfa76c43388c6b6895ea7cdd3c307c90933cd91 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 12:03:30 +0000 Subject: [PATCH 1114/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1214 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/todo b/todo index c5ad29f8d..2029ce6bb 100644 --- a/todo +++ b/todo @@ -35,8 +35,8 @@ Post 0.9.0: - challenge response auth - sasl auth - fix OSS hot-remove -- use better sink/source names, generated from the device file names - make sure that everyone knows how to deal with sinks without a monitor source +- allow passing data with shared memory between local clients and the server Long term: - pass meta info for hearing impaired From 2d702715f7f1b2158a50d5c838b0bad0487b42fd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 12:07:22 +0000 Subject: [PATCH 1115/1514] fix pa_gettimeofday() return value testing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1215 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/dbus-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c index c9cdf114d..e4bd2c3ec 100644 --- a/src/modules/dbus-util.c +++ b/src/modules/dbus-util.c @@ -175,7 +175,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) if (!dbus_timeout_get_enabled(timeout)) return FALSE; - if (pa_gettimeofday(&tv) < 0) + if (!pa_gettimeofday(&tv)) return -1; pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000); From 7fa074480687dff06723b7078c8146aae5eec61a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 13:17:33 +0000 Subject: [PATCH 1116/1514] fix a segfault in module-oss git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1216 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 085ae5da3..5ce741510 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -432,7 +432,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->set_hw_volume = sink_set_hw_volume; u->sink->userdata = u; pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, pa_sprintf_malloc("OSS PCM on %s%s%s%s", + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("OSS PCM on %s%s%s%s", p, hwdesc[0] ? " (" : "", hwdesc[0] ? hwdesc : "", From c86890d5e794aa5b4b3e39796c705b5922877dfe Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 13:18:34 +0000 Subject: [PATCH 1117/1514] * only load an OSS driver for the first device of a sound card, similar to what is done for ALSA. * fix a mem leak git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1217 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 54d139ecb..825fa96ce 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -192,26 +192,33 @@ static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi, DBusError *error) { dbus_bool_t rv = FALSE; - char* device; - char* type; + char* type, *device_file = NULL; + int device; type = libhal_device_get_property_string(ctx, udi, "oss.type", error); if (!type || dbus_error_is_set(error)) return FALSE; - + if (!strcmp(type, "pcm")) { - device = libhal_device_get_property_string(ctx, udi, "oss.device_file", + char *e; + + device = libhal_device_get_property_int(ctx, udi, "oss.device", error); + if (dbus_error_is_set(error) || device != 0) + goto exit; + + device_file = libhal_device_get_property_string(ctx, udi, "oss.device_file", error); - if (!device || dbus_error_is_set(error)) + if (!device_file || dbus_error_is_set(error)) goto exit; /* hack to ignore /dev/audio style devices */ - if ((device = strrchr(device, '/'))) - rv = (pa_startswith(device + 1, "audio")) ? FALSE : TRUE; + if ((e = strrchr(device_file, '/'))) + rv = !pa_startswith(e + 1, "audio"); } exit: libhal_free_string(type); + libhal_free_string(device_file); return rv; } From 0547b0fd4a9a8df1f7c6836a6e1e04697769d4b8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 15:08:53 +0000 Subject: [PATCH 1118/1514] there's no need to queue subscription events if noone is listening, hence don't do it! git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1218 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-subscribe.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pulsecore/core-subscribe.c b/src/pulsecore/core-subscribe.c index 2c6256329..37673da57 100644 --- a/src/pulsecore/core-subscribe.c +++ b/src/pulsecore/core-subscribe.c @@ -209,6 +209,10 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i pa_subscription_event *e; assert(c); + /* No need for queuing subscriptions of noone is listening */ + if (!c->subscriptions) + return; + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_NEW) { pa_subscription_event *i, *n; From fbeeb8b70d754cf16af87330f3a5fe748a27078f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 15:09:49 +0000 Subject: [PATCH 1119/1514] when the requested sample format is not available for OSS devices, print a nice warning and take what we can get instead git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1219 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/oss-util.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index f4cc45de3..feb1aadf5 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -98,6 +98,8 @@ fail: int pa_oss_auto_format(int fd, pa_sample_spec *ss) { int format, channels, speed, reqformat; + pa_sample_format_t orig_format; + static const int format_trans[PA_SAMPLE_MAX] = { [PA_SAMPLE_U8] = AFMT_U8, [PA_SAMPLE_ALAW] = AFMT_A_LAW, @@ -110,6 +112,8 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { assert(fd >= 0 && ss); + orig_format = ss->format; + reqformat = format = format_trans[ss->format]; if (reqformat == AFMT_QUERY || ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != reqformat) { format = AFMT_S16_NE; @@ -128,22 +132,38 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { } else ss->format = PA_SAMPLE_S16NE; } - + + if (orig_format != ss->format) + pa_log_warn(__FILE__": device doesn't support sample format %s, changed to %s.", + pa_sample_format_to_string(orig_format), + pa_sample_format_to_string(ss->format)); + channels = ss->channels; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { pa_log(__FILE__": SNDCTL_DSP_CHANNELS: %s", pa_cstrerror(errno)); return -1; } - assert(channels); - ss->channels = channels; + assert(channels > 0); + + if (ss->channels != channels) { + pa_log_warn(__FILE__": device doesn't support %i channels, using %i channels.", ss->channels, channels); + ss->channels = channels; + } speed = ss->rate; if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { pa_log(__FILE__": SNDCTL_DSP_SPEED: %s", pa_cstrerror(errno)); return -1; } - assert(speed); - ss->rate = speed; + assert(speed > 0); + + if (ss->rate != (unsigned) speed) { + pa_log_warn(__FILE__": device doesn't support %i Hz, changed to %i Hz.", ss->rate, speed); + + /* If the sample rate deviates too much, we need to resample */ + if (speed < ss->rate*.95 || speed > ss->rate*1.05) + ss->rate = speed; + } return 0; } From 3cfed301d91ebf773ace89a02fea6db817426221 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 16:01:40 +0000 Subject: [PATCH 1120/1514] print the device capabilities after opening the device git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1220 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/oss-util.c | 55 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index feb1aadf5..177322be9 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -42,8 +42,13 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { int fd = -1; + int caps; + assert(device && mode && (*mode == O_RDWR || *mode == O_RDONLY || *mode == O_WRONLY)); + if(!pcaps) + pcaps = ∩︀ + if (*mode == O_RDWR) { if ((fd = open(device, O_RDWR|O_NDELAY)) >= 0) { int dcaps, *tcaps; @@ -79,12 +84,52 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { success: - if (pcaps) { - if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); - goto fail; - } + *pcaps = 0; + + if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { + pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); + goto fail; } + + pa_log_debug(__FILE__": capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + *pcaps & DSP_CAP_BATCH ? " BATCH" : "", + *pcaps & DSP_CAP_BIND ? " BIND" : "", + *pcaps & DSP_CAP_COPROC ? " COPROC" : "", + *pcaps & DSP_CAP_DUPLEX ? " DUPLEX" : "", +#ifdef DSP_CAP_FREERATE + *pcaps & DSP_CAP_FREERATE ? " FREERATE" : "", +#else + "", +#endif +#ifdef DSP_CAP_INPUT + *pcaps & DSP_CAP_INPUT ? " INPUT" : "", +#else + "", +#endif + *pcaps & DSP_CAP_MMAP ? " MMAP" : "", +#ifdef DSP_CAP_MODEM + *pcaps & DSP_CAP_MODEM ? " MODEM" : "", +#else + "", +#endif + *pcaps & DSP_CAP_MULTI ? " MULTI" : "", +#ifdef DSP_CAP_OUTPUT + *pcaps & DSP_CAP_OUTPUT ? " OUTPUT" : "", +#else + "", +#endif + *pcaps & DSP_CAP_REALTIME ? " REALTIME" : "", +#ifdef DSP_CAP_SHADOW + *pcaps & DSP_CAP_SHADOW ? " SHADOW" : "", +#else + "", +#endif +#ifdef DSP_CAP_VIRTUAL + *pcaps & DSP_CAP_VIRTUAL ? " VIRTUAL" : "", +#else + "", +#endif + *pcaps & DSP_CAP_TRIGGER ? " TRIGGER" : ""); pa_fd_set_cloexec(fd, 1); From 4c9c4269bb70aad6c7a62ed7f73867087f4af217 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 16:02:26 +0000 Subject: [PATCH 1121/1514] handle hot-remeving of OSS devices properly git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1221 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss-mmap.c | 74 ++++++++++++++++++++++++----------- src/modules/module-oss.c | 42 ++++++++++++++------ 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index cc408f903..08cf1a8d7 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -117,6 +117,42 @@ static void update_usage(struct userdata *u) { (u->source ? pa_idxset_size(u->source->outputs) : 0)); } +static void clear_up(struct userdata *u) { + assert(u); + + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + u->sink = NULL; + } + + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + u->source = NULL; + } + + if (u->in_mmap && u->in_mmap != MAP_FAILED) { + munmap(u->in_mmap, u->in_mmap_length); + u->in_mmap = NULL; + } + + if (u->out_mmap && u->out_mmap != MAP_FAILED) { + munmap(u->out_mmap, u->out_mmap_length); + u->out_mmap = NULL; + } + + if (u->io_event) { + u->core->mainloop->io_free(u->io_event); + u->io_event = NULL; + } + + if (u->fd >= 0) { + close(u->fd); + u->fd = -1; + } +} + static void out_fill_memblocks(struct userdata *u, unsigned n) { assert(u && u->out_memblocks); @@ -154,6 +190,9 @@ static void do_write(struct userdata *u) { if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); + + clear_up(u); + pa_module_unload_request(u->module); return; } @@ -217,6 +256,9 @@ static void do_read(struct userdata *u) { if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); + + clear_up(u); + pa_module_unload_request(u->module); return; } @@ -234,6 +276,12 @@ static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd struct userdata *u = userdata; assert (u && u->core->mainloop == m && u->io_event == e); + if (f & PA_IO_EVENT_ERROR) { + clear_up(u); + pa_module_unload_request(u->module); + return; + } + if (f & PA_IO_EVENT_INPUT) do_read(u); if (f & PA_IO_EVENT_OUTPUT) @@ -393,7 +441,7 @@ int pa__init(pa_core *c, pa_module*m) { if ((u->fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0) goto fail; - if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_REALTIME) || !(caps & DSP_CAP_TRIGGER)) { + if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER)) { pa_log(__FILE__": OSS device not mmap capable."); goto fail; } @@ -539,6 +587,8 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; + clear_up(u); + if (u->out_memblocks) { unsigned i; for (i = 0; i < u->out_fragments; i++) @@ -555,27 +605,5 @@ void pa__done(pa_core *c, pa_module*m) { pa_xfree(u->in_memblocks); } - if (u->in_mmap && u->in_mmap != MAP_FAILED) - munmap(u->in_mmap, u->in_mmap_length); - - if (u->out_mmap && u->out_mmap != MAP_FAILED) - munmap(u->out_mmap, u->out_mmap_length); - - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - } - - if (u->source) { - pa_source_disconnect(u->source); - pa_source_unref(u->source); - } - - if (u->io_event) - u->core->mainloop->io_free(u->io_event); - - if (u->fd >= 0) - close(u->fd); - pa_xfree(u); } diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 5ce741510..c39726809 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -107,6 +107,27 @@ static void update_usage(struct userdata *u) { (u->source ? pa_idxset_size(u->source->outputs) : 0)); } +static void clear_up(struct userdata *u) { + assert(u); + + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + u->sink = NULL; + } + + if (u->source) { + pa_source_disconnect(u->source); + pa_source_unref(u->source); + u->source = NULL; + } + + if (u->io) { + pa_iochannel_free(u->io); + u->io = NULL; + } +} + static void do_write(struct userdata *u) { pa_memchunk *memchunk; ssize_t r; @@ -148,6 +169,9 @@ static void do_write(struct userdata *u) { if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); + + clear_up(u); + pa_module_unload_request(u->module); break; } @@ -199,8 +223,11 @@ static void do_read(struct userdata *u) { assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); - if (errno != EAGAIN) + if (errno != EAGAIN) { pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno)); + clear_up(u); + pa_module_unload_request(u->module); + } break; } @@ -501,22 +528,13 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; + + clear_up(u); if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); if (u->silence.memblock) pa_memblock_unref(u->silence.memblock); - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - } - - if (u->source) { - pa_source_disconnect(u->source); - pa_source_unref(u->source); - } - - pa_iochannel_free(u->io); pa_xfree(u); } From 005017647b4d883fd4d3fe376f3373f71b5f7b53 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 16:02:52 +0000 Subject: [PATCH 1122/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1222 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index 2029ce6bb..568ff30a3 100644 --- a/todo +++ b/todo @@ -34,7 +34,6 @@ Post 0.9.0: - key rings for auth - challenge response auth - sasl auth -- fix OSS hot-remove - make sure that everyone knows how to deal with sinks without a monitor source - allow passing data with shared memory between local clients and the server From bf79e9759112abfa7be5d01de807b24a68038d26 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 16:26:59 +0000 Subject: [PATCH 1123/1514] generate default sink/source names from the device files they belong to git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1223 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 16 ++++++++++++++-- src/modules/module-alsa-source.c | 17 ++++++++++++++--- src/modules/module-oss.c | 32 ++++++++++++++++++++++++++++---- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index efecfc21e..e14cc5c81 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -87,7 +87,6 @@ static const char* const valid_modargs[] = { NULL }; -#define DEFAULT_SINK_NAME "alsa_output" #define DEFAULT_DEVICE "default" static void update_usage(struct userdata *u) { @@ -367,6 +366,9 @@ int pa__init(pa_core *c, pa_module*m) { snd_pcm_info_t *pcm_info = NULL; int err; char *t; + const char *name; + char *name_buf = NULL; + int namereg_fail; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments"); @@ -427,7 +429,14 @@ int pa__init(pa_core *c, pa_module*m) { u->mixer_handle = NULL; } - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { + if ((name = pa_modargs_get_value(ma, "sink_name", NULL))) + namereg_fail = 1; + else { + name = name_buf = pa_sprintf_malloc("alsa_output.%s", dev); + namereg_fail = 0; + } + + if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map))) { pa_log(__FILE__": Failed to create sink object"); goto fail; } @@ -502,6 +511,9 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_hw_mute(u->sink); finish: + + pa_xfree(name_buf); + if (ma) pa_modargs_free(ma); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 6149224ad..b4ef09d99 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -88,7 +88,6 @@ static const char* const valid_modargs[] = { NULL }; -#define DEFAULT_SOURCE_NAME "alsa_input" #define DEFAULT_DEVICE "default" static void update_usage(struct userdata *u) { @@ -360,6 +359,9 @@ int pa__init(pa_core *c, pa_module*m) { snd_pcm_info_t *pcm_info = NULL; int err; char *t; + const char *name; + char *name_buf = NULL; + int namereg_fail; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": failed to parse module arguments"); @@ -420,7 +422,14 @@ int pa__init(pa_core *c, pa_module*m) { u->mixer_handle = NULL; } - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { + if ((name = pa_modargs_get_value(ma, "source_name", NULL))) + namereg_fail = 1; + else { + name = name_buf = pa_sprintf_malloc("alsa_input.%s", dev); + namereg_fail = 0; + } + + if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map))) { pa_log(__FILE__": Failed to create source object"); goto fail; } @@ -492,7 +501,9 @@ int pa__init(pa_core *c, pa_module*m) { u->source->get_hw_mute(u->source); finish: - if (ma) + pa_xfree(name_buf); + + if (ma) pa_modargs_free(ma); if (pcm_info) diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index c39726809..89a8152bc 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -36,6 +36,7 @@ #include #include +#include #include #include @@ -96,8 +97,6 @@ static const char* const valid_modargs[] = { NULL }; -#define DEFAULT_SINK_NAME "oss_output" -#define DEFAULT_SOURCE_NAME "oss_input" #define DEFAULT_DEVICE "/dev/dsp" static void update_usage(struct userdata *u) { @@ -354,6 +353,9 @@ int pa__init(pa_core *c, pa_module*m) { pa_channel_map map; pa_modargs *ma = NULL; char hwdesc[64], *t; + const char *name; + char *name_buf = NULL; + int namereg_fail; assert(c); assert(m); @@ -431,7 +433,14 @@ int pa__init(pa_core *c, pa_module*m) { } if (mode != O_WRONLY) { - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) + if ((name = pa_modargs_get_value(ma, "source_name", NULL))) + namereg_fail = 1; + else { + name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(p)); + namereg_fail = 0; + } + + if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map))) goto fail; u->source->userdata = u; @@ -450,8 +459,18 @@ int pa__init(pa_core *c, pa_module*m) { } else u->source = NULL; + pa_xfree(name_buf); + name_buf = NULL; + if (mode != O_RDONLY) { - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) + if ((name = pa_modargs_get_value(ma, "sink_name", NULL))) + namereg_fail = 1; + else { + name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p)); + namereg_fail = 0; + } + + if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map))) goto fail; u->sink->get_latency = sink_get_latency_cb; @@ -469,6 +488,9 @@ int pa__init(pa_core *c, pa_module*m) { } else u->sink = NULL; + pa_xfree(name_buf); + name_buf = NULL; + assert(u->source || u->sink); u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : -1); @@ -516,6 +538,8 @@ fail: if (ma) pa_modargs_free(ma); + + pa_xfree(name_buf); return -1; } From 28f86ea698c12218383e302236cd687a20987bec Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 16:33:31 +0000 Subject: [PATCH 1124/1514] name the sink/source after the device file, just like we already do for the non-mmaped driver git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1224 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss-mmap.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 08cf1a8d7..21a23d75a 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -104,8 +105,6 @@ static const char* const valid_modargs[] = { NULL }; -#define DEFAULT_SINK_NAME "oss_output" -#define DEFAULT_SOURCE_NAME "oss_input" #define DEFAULT_DEVICE "/dev/dsp" #define DEFAULT_NFRAGS 12 #define DEFAULT_FRAGSIZE 1024 @@ -399,6 +398,9 @@ int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; char hwdesc[64], *t; pa_channel_map map; + const char *name; + char *name_buf = NULL; + int namereg_fail; assert(c); assert(m); @@ -478,8 +480,14 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } } else { - - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec, &map))) + if ((name = pa_modargs_get_value(ma, "source_name", NULL))) + namereg_fail = 1; + else { + name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(p)); + namereg_fail = 0; + } + + if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &u->sample_spec, &map))) goto fail; u->source->userdata = u; @@ -501,6 +509,9 @@ int pa__init(pa_core *c, pa_module*m) { } } + pa_xfree(name_buf); + name_buf = NULL; + if (mode != O_RDONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { pa_log(__FILE__": SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno)); @@ -520,8 +531,15 @@ int pa__init(pa_core *c, pa_module*m) { } } else { pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); + + if ((name = pa_modargs_get_value(ma, "sink_name", NULL))) + namereg_fail = 1; + else { + name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p)); + namereg_fail = 0; + } - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec, &map))) + if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &u->sample_spec, &map))) goto fail; u->sink->get_latency = sink_get_latency_cb; @@ -543,6 +561,9 @@ int pa__init(pa_core *c, pa_module*m) { } } + pa_xfree(name_buf); + name_buf = NULL; + zero = 0; if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero) < 0) { pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); @@ -574,6 +595,8 @@ fail: if (ma) pa_modargs_free(ma); + + pa_xfree(name_buf); return -1; } From b45c39269fe3f59694056b2ae6bae2ac9eada9dc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 16:40:59 +0000 Subject: [PATCH 1125/1514] categorize todo file git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1225 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 55 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/todo b/todo index 568ff30a3..f386e94a7 100644 --- a/todo +++ b/todo @@ -1,41 +1,50 @@ *** $Id$ *** -Post 0.9.0: -- alsa mmap driver -- alsa driver with hw mixing -- merge module-oss-mmap into module-oss -- chroot() -- module-tunnel: improve latency calculation -- multiline configuration statements -- use scatter/gather io for sockets -- rtp module ported to Win32 (sendmsg/recvmsg emulation) -- CODECs to reduce bandwidth usage (plug-in based) +Build System: - Remove symdef files and use macros (like most other projects) - Use own name mangling scheme instead of ltdl's, which will eliminate the need for .la files or extra trickery. -- use software volume when hardware doesn't support all channels (alsa done) -- paplay needs to set a channel map. our default is only correct for AIFF. - (we need help from libsndfile for this) -- silence generation should be moved into the core to avoid races and code - duplication in the backends -- examine if it is possible to mimic esd's handling of half duplex cards - (switch to capture when a recording client connects and drop playback during - that time) -- Fix a way for the threading API to handle state and subscription callbacks - in a nice way. + +Porting: +- rtp module ported to Win32 (sendmsg/recvmsg emulation) + +I18N: - iconv stuff sent from utils to server (UTF-8) - iconv sample loading in server - Document utf8.h, timeval.h and util.h - gettextify polypaudio + +Cleanups: - drop dependency of libpolyp on libX11, instead use an external mini binary -- hooks for creating sink inputs -- insert the low-level device name in the default sink/source name, to make them recognizable +- merge module-oss-mmap into module-oss +- module-tunnel: improve latency calculation +- use software volume when hardware doesn't support all channels (alsa done) +- silence generation should be moved into the core to avoid races and code + duplication in the backends +- make sure that everyone knows how to deal with sinks without a monitor source + +Auth/Crypto: - ssl - key rings for auth - challenge response auth - sasl auth -- make sure that everyone knows how to deal with sinks without a monitor source + +Features: +- alsa mmap driver +- alsa driver with hw mixing - allow passing data with shared memory between local clients and the server +- hooks for creating sink inputs/window manager for sound +- chroot() +- use scatter/gather io for sockets +- CODECs to reduce bandwidth usage (plug-in based) +- multiline configuration statements +- paplay needs to set a channel map. our default is only correct for AIFF. + (we need help from libsndfile for this) +- Fix a way for the threading API to handle state and subscription callbacks + in a nice way. +- examine if it is possible to mimic esd's handling of half duplex cards + (switch to capture when a recording client connects and drop playback during + that time) Long term: - pass meta info for hearing impaired From b5207fc9cac954d49132ff4e6760a60e4e6f2b51 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 16:50:58 +0000 Subject: [PATCH 1126/1514] add pa_sink_used_by()/pa_source_used_by() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1226 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sink.c | 14 ++++++++++++++ src/pulsecore/sink.h | 2 ++ src/pulsecore/source.c | 7 +++++++ src/pulsecore/source.h | 2 +- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index d1d9785af..e770950cf 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -556,3 +556,17 @@ void pa_sink_set_description(pa_sink *s, const char *description) { pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } + +unsigned pa_sink_used_by(pa_sink *s) { + unsigned ret; + + assert(s); + assert(s->ref >= 1); + + ret = pa_idxset_size(s->inputs); + + if (s->monitor_source) + ret += pa_source_used_by(s->monitor_source); + + return ret; +} diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index fb0912cac..1d870620e 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -103,4 +103,6 @@ int pa_sink_get_mute(pa_sink *sink, pa_mixer_t m); void pa_sink_set_description(pa_sink *s, const char *description); +unsigned pa_sink_used_by(pa_sink *s); + #endif diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 903de88b3..ae72f040d 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -333,3 +333,10 @@ void pa_source_set_description(pa_source *s, const char *description) { pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } + +unsigned pa_source_used_by(pa_source *s) { + assert(s); + assert(s->ref >= 1); + + return pa_idxset_size(s->outputs); +} diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index be0c969dc..4dbe4e01d 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -104,5 +104,5 @@ int pa_source_get_mute(pa_source *source, pa_mixer_t m); void pa_source_set_description(pa_source *s, const char *description); - +unsigned pa_source_used_by(pa_source *s); #endif From dbe6bdd2bcd035b0b07d70811593be719c5cc7c0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 17:06:05 +0000 Subject: [PATCH 1127/1514] make use of pa_sink_used_by()/pa_source_used_by() wherever applicable git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1227 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 4 +--- src/modules/module-alsa-source.c | 3 +-- src/modules/module-combine.c | 5 +---- src/modules/module-esound-sink.c | 2 +- src/modules/module-oss-mmap.c | 7 +++---- src/modules/module-oss.c | 7 +++---- src/modules/module-pipe-sink.c | 2 +- src/modules/module-solaris.c | 5 ++--- src/modules/module-waveout.c | 5 ++--- 9 files changed, 15 insertions(+), 25 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index e14cc5c81..8da3d2360 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -90,9 +90,7 @@ static const char* const valid_modargs[] = { #define DEFAULT_DEVICE "default" static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, - (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0)); + pa_module_set_used(u->module, u->sink ? pa_sink_used_by(u->sink) : 0); } static void clear_up(struct userdata *u) { diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index b4ef09d99..4a8678c9c 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -91,8 +91,7 @@ static const char* const valid_modargs[] = { #define DEFAULT_DEVICE "default" static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, - (u->source ? pa_idxset_size(u->source->outputs) : 0)); + pa_module_set_used(u->module, u->source ? pa_source_used_by(u->source) : 0); } static void clear_up(struct userdata *u) { diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 0a5bd4720..9368aed86 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -99,12 +99,9 @@ static void output_free(struct output *o); static void clear_up(struct userdata *u); static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, - (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0)); + pa_module_set_used(u->module, u->sink ? pa_sink_used_by(u->sink) : 0); } - static void adjust_rates(struct userdata *u) { struct output *o; pa_usec_t max_sink_latency = 0, min_total_latency = (pa_usec_t) -1, target_latency; diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 9f0c2c5b0..c774d8c1b 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -142,7 +142,7 @@ static int do_write(struct userdata *u) { u->write_index = u->write_length = 0; } } else if (u->state == STATE_RUNNING) { - pa_module_set_used(u->module, pa_idxset_size(u->sink->inputs) + pa_idxset_size(u->sink->monitor_source->outputs)); + pa_module_set_used(u->module, pa_sink_used_by(u->sink)); if (!u->memchunk.length) if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0) diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 21a23d75a..c783a2f1f 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -110,10 +110,9 @@ static const char* const valid_modargs[] = { #define DEFAULT_FRAGSIZE 1024 static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, - (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) + - (u->source ? pa_idxset_size(u->source->outputs) : 0)); + pa_module_set_used(u->module, + (u->sink ? pa_sink_used_by(u->sink) : 0) + + (u->source ? pa_source_used_by(u->source) : 0)); } static void clear_up(struct userdata *u) { diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 89a8152bc..ce11ee025 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -100,10 +100,9 @@ static const char* const valid_modargs[] = { #define DEFAULT_DEVICE "/dev/dsp" static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, - (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) + - (u->source ? pa_idxset_size(u->source->outputs) : 0)); + pa_module_set_used(u->module, + (u->sink ? pa_sink_used_by(u->sink) : 0) + + (u->source ? pa_source_used_by(u->source) : 0)); } static void clear_up(struct userdata *u) { diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index cc5276d48..c90039fd7 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -91,7 +91,7 @@ static void do_write(struct userdata *u) { if (!pa_iochannel_is_writable(u->io)) return; - pa_module_set_used(u->module, pa_idxset_size(u->sink->inputs) + pa_idxset_size(u->sink->monitor_source->outputs)); + pa_module_set_used(u->module, pa_sink_used_by(u->sink)); if (!u->memchunk.length) if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 21a72b38a..53c73af79 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -110,9 +110,8 @@ static const char* const valid_modargs[] = { static void update_usage(struct userdata *u) { pa_module_set_used(u->module, - (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) + - (u->source ? pa_idxset_size(u->source->outputs) : 0)); + (u->sink ? pa_sink_used_by(u->sink) : 0) + + (u->source ? pa_source_used_by(u->source) : 0)); } static void do_write(struct userdata *u) { diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 27e8de580..5f55c2027 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -103,9 +103,8 @@ static const char* const valid_modargs[] = { static void update_usage(struct userdata *u) { pa_module_set_used(u->module, - (u->sink ? pa_idxset_size(u->sink->inputs) : 0) + - (u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0) + - (u->source ? pa_idxset_size(u->source->outputs) : 0)); + (u->sink ? pa_sink_used_by(u->sink) : 0) + + (u->source ? pa_source_used_by(u->source) : 0)); } static void do_write(struct userdata *u) From 02e083cbc4956e6c8990ea0e2a888efb912d90c3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 17:06:39 +0000 Subject: [PATCH 1128/1514] test if sink->monitor_source is set before making use of it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1228 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/cli-text.c | 2 +- src/pulsecore/protocol-native.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index eecf68fff..a1a2e5647 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -109,7 +109,7 @@ char *pa_sink_list_to_string(pa_core *c) { sink->driver, pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, PA_MIXER_HARDWARE)), (double) pa_sink_get_latency(sink), - sink->monitor_source->index, + sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX, pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &sink->channel_map)); diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index d5a4cf459..982129228 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1276,8 +1276,8 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { PA_TAG_U32, sink->owner ? sink->owner->index : PA_INVALID_INDEX, PA_TAG_CVOLUME, pa_sink_get_volume(sink, PA_MIXER_HARDWARE), PA_TAG_BOOLEAN, pa_sink_get_mute(sink, PA_MIXER_HARDWARE), - PA_TAG_U32, sink->monitor_source->index, - PA_TAG_STRING, sink->monitor_source->name, + PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX, + PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL, PA_TAG_USEC, pa_sink_get_latency(sink), PA_TAG_STRING, sink->driver, PA_TAG_U32, From 17964dda374210579b887ea849ba35dbb438ef0a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 17:07:49 +0000 Subject: [PATCH 1129/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1229 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index f386e94a7..7fbf01a86 100644 --- a/todo +++ b/todo @@ -21,7 +21,6 @@ Cleanups: - use software volume when hardware doesn't support all channels (alsa done) - silence generation should be moved into the core to avoid races and code duplication in the backends -- make sure that everyone knows how to deal with sinks without a monitor source Auth/Crypto: - ssl From 7f70ca31a148edd2bbe82d1424d02fa50892d9bc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 17:59:10 +0000 Subject: [PATCH 1130/1514] extend maximum sink/source name length, because HAL UDIs can get ridiculously long git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1230 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/namereg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index 53295b846..53fb66184 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -24,7 +24,7 @@ #include -#define PA_NAME_MAX 64 +#define PA_NAME_MAX 128 typedef enum pa_namereg_type { PA_NAMEREG_SINK, From 80d73dd21b0af1970ec3cedfe1490acc39f7c221 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 23:35:44 +0000 Subject: [PATCH 1131/1514] implement typeafe hook chain git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1231 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 8 +++++++- src/pulsecore/llist.h | 2 ++ src/tests/hook-list-test.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/tests/hook-list-test.c diff --git a/src/Makefile.am b/src/Makefile.am index e0fae996e..82175e42f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -196,7 +196,8 @@ noinst_PROGRAMS = \ thread-mainloop-test \ utf8-test \ get-binary-name-test \ - ipacl-test + ipacl-test \ + hook-list-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -236,6 +237,11 @@ ipacl_test_CFLAGS = $(AM_CFLAGS) ipacl_test_LDADD = $(AM_LDADD) libpulsecore.la ipacl_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +hook_list_test_SOURCES = tests/hook-list-test.c +hook_list_test_CFLAGS = $(AM_CFLAGS) +hook_list_test_LDADD = $(AM_LDADD) libpulsecore.la +hook_list_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la diff --git a/src/pulsecore/llist.h b/src/pulsecore/llist.h index 9ce24e74a..c50b8a78e 100644 --- a/src/pulsecore/llist.h +++ b/src/pulsecore/llist.h @@ -22,6 +22,8 @@ USA. ***/ +#include + /* Some macros for maintaining doubly linked lists */ /* The head of the linked list. Use this in the structure that shall diff --git a/src/tests/hook-list-test.c b/src/tests/hook-list-test.c new file mode 100644 index 000000000..ee0b54f90 --- /dev/null +++ b/src/tests/hook-list-test.c @@ -0,0 +1,38 @@ +/* $Id$ */ + +#include +#include + +PA_HOOK_DECLARE(test, const char *, const char*); +PA_HOOK_IMPLEMENT(test, const char *, const char *); + +static pa_hook_result_t func1(const char*a, const char*b, void *userdata) { + pa_log("#1 a=%s b=%s userdata=%s", a, b, (char*) userdata); + return PA_HOOK_OK; +} + +static pa_hook_result_t func2(const char*a, const char*b, void *userdata) { + pa_log("#2 a=%s b=%s userdata=%s", a, b, (char*) userdata); + return PA_HOOK_OK; +} + +int main(int argc, char *argv[]) { + void *u; + + PA_HOOK_HEAD(test, test); + + PA_HOOK_HEAD_INIT(test, test); + + PA_HOOK_APPEND(test, test, func1, (void*) "1-1"); + PA_HOOK_APPEND(test, test, func2, u = (void*) "2"); + PA_HOOK_APPEND(test, test, func1, (void*) "1-2"); + + + PA_HOOK_EXECUTE(test, test, "arg1", "arg2"); + + PA_HOOK_REMOVE(test, test, func2, u); + + PA_HOOK_FREE(test, test); + + return 0; +} From 82a913d73e6a319b040510a172e3c6fb46602624 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 23:55:22 +0000 Subject: [PATCH 1132/1514] reall add type safe hook list git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1232 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/hook-list.h | 117 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 src/pulsecore/hook-list.h diff --git a/src/pulsecore/hook-list.h b/src/pulsecore/hook-list.h new file mode 100644 index 000000000..6bfe9cb57 --- /dev/null +++ b/src/pulsecore/hook-list.h @@ -0,0 +1,117 @@ +#ifndef foohooklistfoo +#define foohooklistfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* Some macro voodoo to implement a type safe hook list */ + +#include +#include +#include + +typedef enum pa_hook_result { + PA_HOOK_OK = 0, + PA_HOOK_STOP = 1, + PA_HOOK_CANCEL = -1 +} pa_hook_result_t; + +#define PA_HOOK_DECLARE(name, arg1, arg2) \ +typedef pa_hook_result_t (*pa_hook__##name##__func_t)(arg1 a, arg2 b, void *userdata); \ +\ +typedef struct pa_hook__##name##__func_info pa_hook__##name##__func_info; \ +struct pa_hook__##name##__func_info { \ + int dead; \ + pa_hook__##name##__func_t func; \ + void *userdata; \ + PA_LLIST_FIELDS(pa_hook__##name##__func_info); \ +}; \ +PA_GCC_UNUSED static void pa_hook__##name##__free_one( \ + pa_hook__##name##__func_info **head, \ + pa_hook__##name##__func_info *i) { \ + PA_LLIST_REMOVE(pa_hook__##name##__func_info, *head, i); \ + pa_xfree(i); \ +} \ +PA_GCC_UNUSED static void pa_hook__##name##__free_all( \ + pa_hook__##name##__func_info **head) { \ + while (*head) \ + pa_hook__##name##__free_one(head, *head); \ +} \ +PA_GCC_UNUSED static void pa_hook__##name##__mark_dead( \ + pa_hook__##name##__func_info *i, \ + pa_hook__##name##__func_t func, \ + void *userdata) { \ + for (; i; i = i->next) { \ + if (i->func != func || i->userdata != userdata) \ + continue; \ + i->dead = 1; \ + break; \ + } \ +} \ +PA_GCC_UNUSED static void pa_hook__##name##__append( \ + pa_hook__##name##__func_info **head, \ + pa_hook__##name##__func_t func, \ + void *userdata) { \ + pa_hook__##name##__func_info *i = pa_xnew(pa_hook__##name##__func_info, 1); \ + i->dead = 0; \ + i->func = func; \ + i->userdata = userdata; \ + PA_LLIST_PREPEND(pa_hook__##name##__func_info, *head, i); \ +} \ +PA_GCC_UNUSED static pa_hook_result_t pa_hook__##name##__execute ( \ + pa_hook__##name##__func_info **head, \ + arg1 a, \ + arg2 b) { \ + pa_hook__##name##__func_info *i, *n; \ + pa_hook_result_t ret = PA_HOOK_OK; \ + for (i = *head; i; i = i->next) { \ + if ((ret = i->func(a, b, i->userdata)) != PA_HOOK_OK) \ + break; \ + } \ + for (i = *head; i; i = n) { \ + n = i->next; \ + if (i->dead) \ + pa_hook__##name##__free_one(head, i); \ + } \ + return ret; \ +}\ +void pa_hook__##name##__nowarn(void) + + +#define PA_HOOK_HEAD(name, head) \ +pa_hook__##name##__func_info *head; + +#define PA_HOOK_HEAD_INIT(name, head) \ +(head) = NULL + +#define PA_HOOK_EXECUTE(name, head, arg1, arg2) \ +pa_hook__##name##__execute(&(head), arg1, arg2) + +#define PA_HOOK_APPEND(name, head, func, userdata) \ +pa_hook__##name##__append(&(head), func, userdata) + +#define PA_HOOK_REMOVE(name, head, func, userdata) \ +pa_hook__##name##__mark_dead(head, func, userdata) + +#define PA_HOOK_FREE(name, head) \ +pa_hook__##name##__free_all(&(head)) + +#endif From 2622b0ca9eae2ffb18caed2b54b4e25325bed702 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 23:55:48 +0000 Subject: [PATCH 1133/1514] update hook list test git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1233 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/hook-list-test.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tests/hook-list-test.c b/src/tests/hook-list-test.c index ee0b54f90..b0ea59974 100644 --- a/src/tests/hook-list-test.c +++ b/src/tests/hook-list-test.c @@ -4,7 +4,6 @@ #include PA_HOOK_DECLARE(test, const char *, const char*); -PA_HOOK_IMPLEMENT(test, const char *, const char *); static pa_hook_result_t func1(const char*a, const char*b, void *userdata) { pa_log("#1 a=%s b=%s userdata=%s", a, b, (char*) userdata); @@ -27,7 +26,6 @@ int main(int argc, char *argv[]) { PA_HOOK_APPEND(test, test, func2, u = (void*) "2"); PA_HOOK_APPEND(test, test, func1, (void*) "1-2"); - PA_HOOK_EXECUTE(test, test, "arg1", "arg2"); PA_HOOK_REMOVE(test, test, func2, u); From 281125c72767713d6294ac7094f3bf7bde47a1e3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 01:43:34 +0000 Subject: [PATCH 1134/1514] rework hook list stuff again, and replace macros with real functins. We loose type safety but things are much cleaner now git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1234 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 3 +- src/pulsecore/hook-list.c | 111 +++++++++++++++++++++++++++++++++++++ src/pulsecore/hook-list.h | 99 ++++++++------------------------- src/tests/hook-list-test.c | 34 +++++------- 4 files changed, 150 insertions(+), 97 deletions(-) create mode 100644 src/pulsecore/hook-list.c diff --git a/src/Makefile.am b/src/Makefile.am index 82175e42f..3cf3168c4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -585,7 +585,8 @@ libpulsecore_la_SOURCES += \ pulsecore/strbuf.c pulsecore/strbuf.h \ pulsecore/tokenizer.c pulsecore/tokenizer.h \ pulsecore/winsock.h \ - pulsecore/core-error.c pulsecore/core-error.h + pulsecore/core-error.c pulsecore/core-error.h \ + pulsecore/hook-list.c pulsecore/hook-list.h if OS_IS_WIN32 libpulsecore_la_SOURCES += \ diff --git a/src/pulsecore/hook-list.c b/src/pulsecore/hook-list.c new file mode 100644 index 000000000..14ab8e898 --- /dev/null +++ b/src/pulsecore/hook-list.c @@ -0,0 +1,111 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +void pa_hook_init(pa_hook *hook) { + assert(hook); + + PA_LLIST_HEAD_INIT(pa_hook_slots, hook->slots); + hook->last = NULL; + hook->n_dead = hook->firing = 0; +} + +static void slot_free(pa_hook *hook, pa_hook_slot *slot) { + assert(hook); + assert(slot); + + if (hook->last == slot) + hook->last = slot->prev; + + PA_LLIST_REMOVE(pa_hook_slot, hook->slots, slot); + + pa_xfree(slot); +} + +void pa_hook_free(pa_hook *hook) { + assert(hook); + assert(!hook->firing); + + while (hook->slots) + slot_free(hook, hook->slots); + + pa_hook_init(hook); +} + +pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *userdata) { + pa_hook_slot *slot; + + assert(cb); + + slot = pa_xnew(pa_hook_slot, 1); + slot->hook = hook; + slot->dead = 0; + slot->callback = cb; + slot->userdata = userdata; + + PA_LLIST_INSERT_AFTER(pa_hook_slot, hook->slots, hook->last, slot); + hook->last = slot; + + return slot; +} + +void pa_hook_slot_free(pa_hook_slot *slot) { + assert(slot); + assert(!slot->dead); + + if (slot->hook->firing > 0) { + slot->dead = 1; + slot->hook->n_dead++; + } else + slot_free(slot->hook, slot); +} + +pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) { + pa_hook_slot *slot, *next; + pa_hook_result_t result = PA_HOOK_OK; + + assert(hook); + + hook->firing ++; + + for (slot = hook->slots; slot; slot = slot->next) { + if (slot->dead) + continue; + + if ((result = slot->callback(data, slot->userdata)) != PA_HOOK_OK) + break; + } + + hook->firing --; + + for (slot = hook->slots; hook->n_dead > 0 && slot; slot = next) { + next = slot->next; + + if (slot->dead) { + slot_free(hook, slot); + hook->n_dead--; + } + } + + return result; +} + diff --git a/src/pulsecore/hook-list.h b/src/pulsecore/hook-list.h index 6bfe9cb57..e016ff0ce 100644 --- a/src/pulsecore/hook-list.h +++ b/src/pulsecore/hook-list.h @@ -22,11 +22,12 @@ USA. ***/ -/* Some macro voodoo to implement a type safe hook list */ - #include #include -#include +#include + +typedef struct pa_hook_slot pa_hook_slot; +typedef struct pa_hook pa_hook; typedef enum pa_hook_result { PA_HOOK_OK = 0, @@ -34,84 +35,28 @@ typedef enum pa_hook_result { PA_HOOK_CANCEL = -1 } pa_hook_result_t; -#define PA_HOOK_DECLARE(name, arg1, arg2) \ -typedef pa_hook_result_t (*pa_hook__##name##__func_t)(arg1 a, arg2 b, void *userdata); \ -\ -typedef struct pa_hook__##name##__func_info pa_hook__##name##__func_info; \ -struct pa_hook__##name##__func_info { \ - int dead; \ - pa_hook__##name##__func_t func; \ - void *userdata; \ - PA_LLIST_FIELDS(pa_hook__##name##__func_info); \ -}; \ -PA_GCC_UNUSED static void pa_hook__##name##__free_one( \ - pa_hook__##name##__func_info **head, \ - pa_hook__##name##__func_info *i) { \ - PA_LLIST_REMOVE(pa_hook__##name##__func_info, *head, i); \ - pa_xfree(i); \ -} \ -PA_GCC_UNUSED static void pa_hook__##name##__free_all( \ - pa_hook__##name##__func_info **head) { \ - while (*head) \ - pa_hook__##name##__free_one(head, *head); \ -} \ -PA_GCC_UNUSED static void pa_hook__##name##__mark_dead( \ - pa_hook__##name##__func_info *i, \ - pa_hook__##name##__func_t func, \ - void *userdata) { \ - for (; i; i = i->next) { \ - if (i->func != func || i->userdata != userdata) \ - continue; \ - i->dead = 1; \ - break; \ - } \ -} \ -PA_GCC_UNUSED static void pa_hook__##name##__append( \ - pa_hook__##name##__func_info **head, \ - pa_hook__##name##__func_t func, \ - void *userdata) { \ - pa_hook__##name##__func_info *i = pa_xnew(pa_hook__##name##__func_info, 1); \ - i->dead = 0; \ - i->func = func; \ - i->userdata = userdata; \ - PA_LLIST_PREPEND(pa_hook__##name##__func_info, *head, i); \ -} \ -PA_GCC_UNUSED static pa_hook_result_t pa_hook__##name##__execute ( \ - pa_hook__##name##__func_info **head, \ - arg1 a, \ - arg2 b) { \ - pa_hook__##name##__func_info *i, *n; \ - pa_hook_result_t ret = PA_HOOK_OK; \ - for (i = *head; i; i = i->next) { \ - if ((ret = i->func(a, b, i->userdata)) != PA_HOOK_OK) \ - break; \ - } \ - for (i = *head; i; i = n) { \ - n = i->next; \ - if (i->dead) \ - pa_hook__##name##__free_one(head, i); \ - } \ - return ret; \ -}\ -void pa_hook__##name##__nowarn(void) +typedef pa_hook_result_t (*pa_hook_cb_t)(void *data, void *userdata); +struct pa_hook_slot { + int dead; + pa_hook *hook; + pa_hook_cb_t callback; + void *userdata; + PA_LLIST_FIELDS(pa_hook_slot); +}; -#define PA_HOOK_HEAD(name, head) \ -pa_hook__##name##__func_info *head; +struct pa_hook { + PA_LLIST_HEAD(pa_hook_slot, slots); + pa_hook_slot *last; + int firing, n_dead; +}; -#define PA_HOOK_HEAD_INIT(name, head) \ -(head) = NULL +void pa_hook_init(pa_hook *hook); +void pa_hook_free(pa_hook *hook); -#define PA_HOOK_EXECUTE(name, head, arg1, arg2) \ -pa_hook__##name##__execute(&(head), arg1, arg2) +pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t, void *userdata); +void pa_hook_slot_free(pa_hook_slot *slot); -#define PA_HOOK_APPEND(name, head, func, userdata) \ -pa_hook__##name##__append(&(head), func, userdata) - -#define PA_HOOK_REMOVE(name, head, func, userdata) \ -pa_hook__##name##__mark_dead(head, func, userdata) - -#define PA_HOOK_FREE(name, head) \ -pa_hook__##name##__free_all(&(head)) +pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data); #endif diff --git a/src/tests/hook-list-test.c b/src/tests/hook-list-test.c index b0ea59974..0d811a1ea 100644 --- a/src/tests/hook-list-test.c +++ b/src/tests/hook-list-test.c @@ -3,34 +3,30 @@ #include #include -PA_HOOK_DECLARE(test, const char *, const char*); - -static pa_hook_result_t func1(const char*a, const char*b, void *userdata) { - pa_log("#1 a=%s b=%s userdata=%s", a, b, (char*) userdata); +static pa_hook_result_t func1(const char*a, void *userdata) { + pa_log("#1 arg=%s userdata=%s", a, (char*) userdata); return PA_HOOK_OK; } -static pa_hook_result_t func2(const char*a, const char*b, void *userdata) { - pa_log("#2 a=%s b=%s userdata=%s", a, b, (char*) userdata); +static pa_hook_result_t func2(const char*a, void *userdata) { + pa_log("#2 arg=%s userdata=%s", a, (char*) userdata); return PA_HOOK_OK; } int main(int argc, char *argv[]) { - void *u; + pa_hook hook; + pa_hook_slot *slot; + + pa_hook_init(&hook); + + pa_hook_connect(&hook, (pa_hook_cb_t) func1, (void*) "1-1"); + slot = pa_hook_connect(&hook, (pa_hook_cb_t) func2, (void*) "2-1"); + pa_hook_connect(&hook, (pa_hook_cb_t) func1, (void*) "1-2"); - PA_HOOK_HEAD(test, test); + pa_hook_fire(&hook, (void*) "arg2"); - PA_HOOK_HEAD_INIT(test, test); - - PA_HOOK_APPEND(test, test, func1, (void*) "1-1"); - PA_HOOK_APPEND(test, test, func2, u = (void*) "2"); - PA_HOOK_APPEND(test, test, func1, (void*) "1-2"); - - PA_HOOK_EXECUTE(test, test, "arg1", "arg2"); - - PA_HOOK_REMOVE(test, test, func2, u); - - PA_HOOK_FREE(test, test); + pa_hook_slot_free(slot); + pa_hook_free(&hook); return 0; } From db3f561ec4d6fe7b6deedff45802a5efd3ba4013 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 16:13:36 +0000 Subject: [PATCH 1135/1514] rework hook list stuff once again: change the callback prototype to recieve three data pointers: one to the data for the hook, once for the slot and once for the call git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1235 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/hook-list.c | 11 ++++++----- src/pulsecore/hook-list.h | 13 +++++++++---- src/tests/hook-list-test.c | 21 ++++++++++++--------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/pulsecore/hook-list.c b/src/pulsecore/hook-list.c index 14ab8e898..72b206b2c 100644 --- a/src/pulsecore/hook-list.c +++ b/src/pulsecore/hook-list.c @@ -21,12 +21,13 @@ #include -void pa_hook_init(pa_hook *hook) { +void pa_hook_init(pa_hook *hook, void *data) { assert(hook); PA_LLIST_HEAD_INIT(pa_hook_slots, hook->slots); hook->last = NULL; hook->n_dead = hook->firing = 0; + hook->data = data; } static void slot_free(pa_hook *hook, pa_hook_slot *slot) { @@ -48,10 +49,10 @@ void pa_hook_free(pa_hook *hook) { while (hook->slots) slot_free(hook, hook->slots); - pa_hook_init(hook); + pa_hook_init(hook, NULL); } -pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *userdata) { +pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *data) { pa_hook_slot *slot; assert(cb); @@ -60,7 +61,7 @@ pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *userdata) { slot->hook = hook; slot->dead = 0; slot->callback = cb; - slot->userdata = userdata; + slot->data = data; PA_LLIST_INSERT_AFTER(pa_hook_slot, hook->slots, hook->last, slot); hook->last = slot; @@ -91,7 +92,7 @@ pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) { if (slot->dead) continue; - if ((result = slot->callback(data, slot->userdata)) != PA_HOOK_OK) + if ((result = slot->callback(hook->data, data, slot->data)) != PA_HOOK_OK) break; } diff --git a/src/pulsecore/hook-list.h b/src/pulsecore/hook-list.h index e016ff0ce..67e5d1ae2 100644 --- a/src/pulsecore/hook-list.h +++ b/src/pulsecore/hook-list.h @@ -35,13 +35,16 @@ typedef enum pa_hook_result { PA_HOOK_CANCEL = -1 } pa_hook_result_t; -typedef pa_hook_result_t (*pa_hook_cb_t)(void *data, void *userdata); +typedef pa_hook_result_t (*pa_hook_cb_t)( + void *hook_data, + void *call_data, + void *slot_data); struct pa_hook_slot { int dead; pa_hook *hook; pa_hook_cb_t callback; - void *userdata; + void *data; PA_LLIST_FIELDS(pa_hook_slot); }; @@ -49,12 +52,14 @@ struct pa_hook { PA_LLIST_HEAD(pa_hook_slot, slots); pa_hook_slot *last; int firing, n_dead; + + void *data; }; -void pa_hook_init(pa_hook *hook); +void pa_hook_init(pa_hook *hook, void *data); void pa_hook_free(pa_hook *hook); -pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t, void *userdata); +pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t, void *data); void pa_hook_slot_free(pa_hook_slot *slot); pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data); diff --git a/src/tests/hook-list-test.c b/src/tests/hook-list-test.c index 0d811a1ea..d68d1b7d1 100644 --- a/src/tests/hook-list-test.c +++ b/src/tests/hook-list-test.c @@ -3,13 +3,13 @@ #include #include -static pa_hook_result_t func1(const char*a, void *userdata) { - pa_log("#1 arg=%s userdata=%s", a, (char*) userdata); +static pa_hook_result_t func1(const char*hook_data, const char*call_data, const char*slot_data) { + pa_log("(func1) hook=%s call=%s slot=%s", hook_data, call_data, slot_data); return PA_HOOK_OK; } -static pa_hook_result_t func2(const char*a, void *userdata) { - pa_log("#2 arg=%s userdata=%s", a, (char*) userdata); +static pa_hook_result_t func2(const char*hook_data, const char*call_data, const char*slot_data) { + pa_log("(func2) hook=%s call=%s slot=%s", hook_data, call_data, slot_data); return PA_HOOK_OK; } @@ -17,15 +17,18 @@ int main(int argc, char *argv[]) { pa_hook hook; pa_hook_slot *slot; - pa_hook_init(&hook); + pa_hook_init(&hook, (void*) "hook"); - pa_hook_connect(&hook, (pa_hook_cb_t) func1, (void*) "1-1"); - slot = pa_hook_connect(&hook, (pa_hook_cb_t) func2, (void*) "2-1"); - pa_hook_connect(&hook, (pa_hook_cb_t) func1, (void*) "1-2"); + pa_hook_connect(&hook, (pa_hook_cb_t) func1, (void*) "slot1"); + slot = pa_hook_connect(&hook, (pa_hook_cb_t) func2, (void*) "slot2"); + pa_hook_connect(&hook, (pa_hook_cb_t) func1, (void*) "slot3"); - pa_hook_fire(&hook, (void*) "arg2"); + pa_hook_fire(&hook, (void*) "call1"); pa_hook_slot_free(slot); + + pa_hook_fire(&hook, (void*) "call2"); + pa_hook_free(&hook); return 0; From b5cbea940ea70b8ed92fa3be6b742e8a14897337 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 16:14:06 +0000 Subject: [PATCH 1136/1514] fix bad printf() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1236 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/pactl.c b/src/utils/pactl.c index f6f754986..028f71c8a 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -627,7 +627,7 @@ static void help(const char *argv0) { " --version Show version\n\n" " -s, --server=SERVER The name of the server to connect to\n" " -n, --client-name=NAME How to call this client on the server\n", - argv0, argv0, argv0, argv0, argv0, argv0, argv0); + argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0); } enum { ARG_VERSION = 256 }; From a621d9028548723d13df64df06a4f4538504e7a3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 16:19:56 +0000 Subject: [PATCH 1137/1514] allow hooking into the process of creating playback streams. To implement this I modified the pa_sink_input_new() signature to take a pa_sink_input_new_data structure instead of direct arguments. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1237 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-combine.c | 14 ++- src/modules/module-sine.c | 12 ++- src/modules/rtp/module-rtp-recv.c | 11 ++- src/pulsecore/cli-text.c | 4 +- src/pulsecore/client.h | 10 +- src/pulsecore/core.c | 6 ++ src/pulsecore/core.h | 13 ++- src/pulsecore/module.h | 4 +- src/pulsecore/play-memblockq.c | 27 ++++-- src/pulsecore/play-memchunk.c | 27 ++++-- src/pulsecore/protocol-esound.c | 15 ++- src/pulsecore/protocol-native.c | 41 ++++---- src/pulsecore/protocol-simple.c | 19 ++-- src/pulsecore/sink-input.c | 150 ++++++++++++++++++++---------- src/pulsecore/sink-input.h | 47 +++++++--- src/pulsecore/sound-file-stream.c | 24 ++++- 16 files changed, 291 insertions(+), 133 deletions(-) diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 9368aed86..008fe6e74 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -220,6 +220,8 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { static struct output *output_new(struct userdata *u, pa_sink *sink, int resample_method) { struct output *o = NULL; char t[256]; + pa_sink_input_new_data data; + assert(u && sink && u->sink); o = pa_xmalloc(sizeof(struct output)); @@ -237,7 +239,16 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample sink->core->memblock_stat); snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1); - if (!(o->sink_input = pa_sink_input_new(sink, __FILE__, t, &u->sink->sample_spec, &u->sink->channel_map, NULL, 1, resample_method))) + + pa_sink_input_new_data_init(&data); + data.sink = sink; + data.driver = __FILE__; + data.name = t; + pa_sink_input_new_data_set_sample_spec(&data, &u->sink->sample_spec); + pa_sink_input_new_data_set_channel_map(&data, &u->sink->channel_map); + data.module = u->module; + + if (!(o->sink_input = pa_sink_input_new(u->core, &data, PA_SINK_INPUT_VARIABLE_RATE))) goto fail; o->sink_input->get_latency = sink_input_get_latency_cb; @@ -245,7 +256,6 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample o->sink_input->drop = sink_input_drop_cb; o->sink_input->kill = sink_input_kill_cb; o->sink_input->userdata = o; - o->sink_input->owner = u->module; PA_LLIST_PREPEND(struct output, u->outputs, o); u->n_outputs++; diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index f4392b9a0..5ceddce08 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -109,6 +109,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; uint32_t frequency; char t[256]; + pa_sink_input_new_data data; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log(__FILE__": Failed to parse module arguments"); @@ -142,14 +143,21 @@ int pa__init(pa_core *c, pa_module*m) { calc_sine(u->memblock->data, u->memblock->length, frequency); snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); - if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, t, &ss, NULL, NULL, 0, -1))) + + pa_sink_input_new_data_init(&data); + data.sink = sink; + data.driver = __FILE__; + data.name = t; + pa_sink_input_new_data_set_sample_spec(&data, &ss); + data.module = m; + + if (!(u->sink_input = pa_sink_input_new(c, &data, 0))) goto fail; u->sink_input->peek = sink_input_peek; u->sink_input->drop = sink_input_drop; u->sink_input->kill = sink_input_kill; u->sink_input->userdata = u; - u->sink_input->owner = m; u->peek_index = 0; diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 0359a43bf..df6f8c118 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -265,6 +265,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_sink *sink; int fd = -1; pa_memblock *silence; + pa_sink_input_new_data data; if (u->n_sessions >= MAX_SESSIONS) { pa_log(__FILE__": session limit reached."); @@ -289,7 +290,14 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in sdp_info->session_name ? sdp_info->session_name : "", sdp_info->session_name ? ")" : ""); - s->sink_input = pa_sink_input_new(sink, __FILE__, c, &sdp_info->sample_spec, NULL, NULL, 0, PA_RESAMPLER_INVALID); + pa_sink_input_new_data_init(&data); + data.sink = sink; + data.driver = __FILE__; + data.name = c; + data.module = u->module; + pa_sink_input_new_data_set_sample_spec(&data, &sdp_info->sample_spec); + + s->sink_input = pa_sink_input_new(u->core, &data, 0); pa_xfree(c); if (!s->sink_input) { @@ -298,7 +306,6 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in } s->sink_input->userdata = s; - s->sink_input->owner = u->module; s->sink_input->peek = sink_input_peek; s->sink_input->drop = sink_input_drop; diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index a1a2e5647..ff083dc31 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -257,8 +257,8 @@ char *pa_sink_input_list_to_string(pa_core *c) { pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), pa_resample_method_to_string(pa_sink_input_get_resample_method(i))); - if (i->owner) - pa_strbuf_printf(s, "\towner module: <%u>\n", i->owner->index); + if (i->module) + pa_strbuf_printf(s, "\towner module: <%u>\n", i->module->index); if (i->client) pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", i->client->index, i->client->name); } diff --git a/src/pulsecore/client.h b/src/pulsecore/client.h index 1e72baf77..b28065e5d 100644 --- a/src/pulsecore/client.h +++ b/src/pulsecore/client.h @@ -1,5 +1,5 @@ -#ifndef fooclienthfoo -#define fooclienthfoo +#ifndef foopulseclienthfoo +#define foopulseclienthfoo /* $Id$ */ @@ -22,6 +22,10 @@ USA. ***/ +#include + +typedef struct pa_client pa_client; + #include #include @@ -29,8 +33,6 @@ * attached. That way the user may generate a listing of all connected * clients easily and kill them if he wants.*/ -typedef struct pa_client pa_client; - struct pa_client { uint32_t index; diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 710e00ad6..24f835f79 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -92,6 +92,9 @@ pa_core* pa_core_new(pa_mainloop_api *m) { c->is_system_instance = 0; + pa_hook_init(&c->hook_sink_input_new, c); + pa_hook_init(&c->hook_sink_input_disconnect, c); + pa_property_init(c); pa_random(&c->cookie, sizeof(c->cookie)); @@ -137,6 +140,9 @@ void pa_core_free(pa_core *c) { pa_memblock_stat_unref(c->memblock_stat); pa_property_cleanup(c); + + pa_hook_free(&c->hook_sink_input_new); + pa_hook_free(&c->hook_sink_input_disconnect); pa_xfree(c); } diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 391ba9b86..fd92de61f 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -22,17 +22,21 @@ USA. ***/ -typedef struct pa_core pa_core; - #include #include + #include #include #include #include #include -#include #include +#include + +typedef struct pa_core pa_core; + +#include +#include /* The core structure of PulseAudio. Every PulseAudio daemon contains * exactly one of these. It is used for storing kind of global @@ -75,6 +79,9 @@ struct pa_core { pa_resample_method_t resample_method; int is_system_instance; + + /* hooks */ + pa_hook hook_sink_input_new, hook_sink_input_disconnect; }; pa_core* pa_core_new(pa_mainloop_api *m); diff --git a/src/pulsecore/module.h b/src/pulsecore/module.h index 9bc5cb5d2..8c320be88 100644 --- a/src/pulsecore/module.h +++ b/src/pulsecore/module.h @@ -25,11 +25,11 @@ #include #include +typedef struct pa_module pa_module; + #include #include -typedef struct pa_module pa_module; - struct pa_module { pa_core *core; char *name, *argument; diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c index 7b796a8d8..f459142ae 100644 --- a/src/pulsecore/play-memblockq.c +++ b/src/pulsecore/play-memblockq.c @@ -79,14 +79,15 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t le } int pa_play_memblockq( - pa_sink *sink, - const char *name, - const pa_sample_spec *ss, - const pa_channel_map *map, - pa_memblockq *q, - pa_cvolume *cvolume) { + pa_sink *sink, + const char *name, + const pa_sample_spec *ss, + const pa_channel_map *map, + pa_memblockq *q, + pa_cvolume *volume) { pa_sink_input *si; + pa_sink_input_new_data data; assert(sink); assert(ss); @@ -97,12 +98,20 @@ int pa_play_memblockq( return 0; } - if (cvolume && pa_cvolume_is_muted(cvolume)) { + if (volume && pa_cvolume_is_muted(volume)) { pa_memblockq_free(q); return 0; } - if (!(si = pa_sink_input_new(sink, name, __FILE__, ss, map, cvolume, 0, PA_RESAMPLER_INVALID))) + pa_sink_input_new_data_init(&data); + data.sink = sink; + data.name = name; + data.driver = __FILE__; + pa_sink_input_new_data_set_channel_map(&data, map); + pa_sink_input_new_data_set_sample_spec(&data, ss); + pa_sink_input_new_data_set_volume(&data, volume); + + if (!(si = pa_sink_input_new(sink->core, &data, 0))) return -1; si->peek = sink_input_peek; @@ -111,7 +120,7 @@ int pa_play_memblockq( si->userdata = q; - pa_sink_notify(sink); + pa_sink_notify(si->sink); return 0; } diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c index 7ac579e9d..cde6a9ee4 100644 --- a/src/pulsecore/play-memchunk.c +++ b/src/pulsecore/play-memchunk.c @@ -82,24 +82,33 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t le } int pa_play_memchunk( - pa_sink *sink, - const char *name, - const pa_sample_spec *ss, - const pa_channel_map *map, - const pa_memchunk *chunk, - pa_cvolume *cvolume) { + pa_sink *sink, + const char *name, + const pa_sample_spec *ss, + const pa_channel_map *map, + const pa_memchunk *chunk, + pa_cvolume *volume) { pa_sink_input *si; pa_memchunk *nchunk; + pa_sink_input_new_data data; assert(sink); assert(ss); assert(chunk); - if (cvolume && pa_cvolume_is_muted(cvolume)) + if (volume && pa_cvolume_is_muted(volume)) return 0; - if (!(si = pa_sink_input_new(sink, name, __FILE__, ss, map, cvolume, 0, PA_RESAMPLER_INVALID))) + pa_sink_input_new_data_init(&data); + data.sink = sink; + data.name = name; + data.driver = __FILE__; + pa_sink_input_new_data_set_sample_spec(&data, ss); + pa_sink_input_new_data_set_channel_map(&data, map); + pa_sink_input_new_data_set_volume(&data, volume); + + if (!(si = pa_sink_input_new(sink->core, &data, 0))) return -1; si->peek = sink_input_peek; @@ -111,7 +120,7 @@ int pa_play_memchunk( pa_memblock_ref(chunk->memblock); - pa_sink_notify(sink); + pa_sink_notify(si->sink); return 0; } diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 0fa2c7f1f..724dccbc9 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -325,9 +325,10 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { char name[ESD_NAME_MAX], *utf8_name; int32_t format, rate; - pa_sink *sink; pa_sample_spec ss; size_t l; + pa_sink *sink; + pa_sink_input_new_data sdata; assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX)); @@ -355,7 +356,15 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t assert(!c->sink_input && !c->input_memblockq); - c->sink_input = pa_sink_input_new(sink, __FILE__, utf8_name, &ss, NULL, NULL, 0, -1); + pa_sink_input_new_data_init(&sdata); + sdata.sink = sink; + sdata.driver = __FILE__; + sdata.name = utf8_name; + pa_sink_input_new_data_set_sample_spec(&sdata, &ss); + sdata.module = c->protocol->module; + sdata.client = c->client; + + c->sink_input = pa_sink_input_new(c->protocol->core, &sdata, 0); pa_xfree(utf8_name); @@ -374,8 +383,6 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2); c->playback.fragment_size = l/10; - c->sink_input->owner = c->protocol->module; - c->sink_input->client = c->client; c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; c->sink_input->kill = sink_input_kill_cb; diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 982129228..f922fb556 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -362,23 +362,24 @@ static void record_stream_free(struct record_stream* r) { } static struct playback_stream* playback_stream_new( - struct connection *c, - pa_sink *sink, - const pa_sample_spec *ss, - const pa_channel_map *map, - const char *name, - size_t maxlength, - size_t tlength, - size_t prebuf, - size_t minreq, - pa_cvolume *volume, - uint32_t syncid) { + struct connection *c, + pa_sink *sink, + const pa_sample_spec *ss, + const pa_channel_map *map, + const char *name, + size_t maxlength, + size_t tlength, + size_t prebuf, + size_t minreq, + pa_cvolume *volume, + uint32_t syncid) { struct playback_stream *s, *ssync; pa_sink_input *sink_input; pa_memblock *silence; uint32_t idx; int64_t start_index; + pa_sink_input_new_data data; assert(c && sink && ss && name && maxlength); @@ -395,8 +396,18 @@ static struct playback_stream* playback_stream_new( /* Synced streams must connect to the same sink */ if (ssync && ssync->sink_input->sink != sink) return NULL; - - if (!(sink_input = pa_sink_input_new(sink, __FILE__, name, ss, map, volume, 0, -1))) + + pa_sink_input_new_data_init(&data); + data.sink = sink; + data.driver = __FILE__; + data.name = name; + pa_sink_input_new_data_set_sample_spec(&data, ss); + pa_sink_input_new_data_set_channel_map(&data, map); + pa_sink_input_new_data_set_volume(&data, volume); + data.module = c->protocol->module; + data.client = c->client; + + if (!(sink_input = pa_sink_input_new(sink->core, &data, 0))) return NULL; s = pa_xnew(struct playback_stream, 1); @@ -411,8 +422,6 @@ static struct playback_stream* playback_stream_new( s->sink_input->kill = sink_input_kill_cb; s->sink_input->get_latency = sink_input_get_latency_cb; s->sink_input->userdata = s; - s->sink_input->owner = c->protocol->module; - s->sink_input->client = c->client; if (ssync) { /* Sync id found, now find head of list */ @@ -1331,7 +1340,7 @@ static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) { assert(t && s); pa_tagstruct_putu32(t, s->index); pa_tagstruct_puts(t, s->name); - pa_tagstruct_putu32(t, s->owner ? s->owner->index : PA_INVALID_INDEX); + pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX); pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX); pa_tagstruct_putu32(t, s->sink->index); pa_tagstruct_put_sample_spec(t, &s->sample_spec); diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 4d73bd24d..5071191a0 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -340,22 +340,21 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->client->userdata = c; if (p->mode & PLAYBACK) { - pa_sink *sink; + pa_sink_input_new_data data; size_t l; - if (!(sink = pa_namereg_get(p->core, p->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": Failed to get sink."); - goto fail; - } + pa_sink_input_new_data_init(&data); + data.driver = __FILE__; + data.name = c->client->name; + pa_sink_input_new_data_set_sample_spec(&data, &p->sample_spec); + data.module = p->module; + data.client = c->client; - if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, c->client->name, &p->sample_spec, NULL, NULL, 0, -1))) { + if (!(c->sink_input = pa_sink_input_new(p->core, &data, 0))) { pa_log(__FILE__": Failed to create sink input."); goto fail; } - c->sink_input->owner = p->module; - c->sink_input->client = c->client; - c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; c->sink_input->kill = sink_input_kill_cb; @@ -375,6 +374,8 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) assert(c->input_memblockq); pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5); c->playback.fragment_size = l/10; + + pa_sink_notify(c->sink_input->sink); } if (p->mode & RECORD) { diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 701d7f6cc..ff5213e19 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "sink-input.h" @@ -48,51 +49,96 @@ if (!(condition)) \ return NULL; \ } while (0) +pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) { + assert(data); + + memset(data, 0, sizeof(*data)); + data->resample_method = PA_RESAMPLER_INVALID; + return data; +} + +void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map) { + assert(data); + + if ((data->channel_map_is_set = !!map)) + data->channel_map = *map; +} + +void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) { + assert(data); + + if ((data->volume_is_set = !!volume)) + data->volume = *volume; +} + +void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec) { + assert(data); + + if ((data->sample_spec_is_set = !!spec)) + data->sample_spec = *spec; +} + pa_sink_input* pa_sink_input_new( - pa_sink *s, - const char *driver, - const char *name, - const pa_sample_spec *spec, - const pa_channel_map *map, - const pa_cvolume *volume, - int variable_rate, - int resample_method) { + pa_core *core, + pa_sink_input_new_data *data, + pa_sink_input_flags_t flags) { pa_sink_input *i; pa_resampler *resampler = NULL; int r; - char st[256]; - pa_channel_map tmap; - pa_cvolume tvol; + char st[PA_SAMPLE_SPEC_SNPRINT_MAX]; - assert(s); - assert(spec); - assert(s->state == PA_SINK_RUNNING); + assert(core); + assert(data); - CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + if (!(flags & PA_SINK_INPUT_NO_HOOKS)) + if (pa_hook_fire(&core->hook_sink_input_new, data) < 0) + return NULL; - if (!map) - map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); - if (!volume) - volume = pa_cvolume_reset(&tvol, spec->channels); + CHECK_VALIDITY_RETURN_NULL(!data->driver || pa_utf8_valid(data->driver)); + CHECK_VALIDITY_RETURN_NULL(!data->name || pa_utf8_valid(data->name)); - CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); - CHECK_VALIDITY_RETURN_NULL(volume && pa_cvolume_valid(volume)); - CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); - CHECK_VALIDITY_RETURN_NULL(volume->channels == spec->channels); - CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); - CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name)); - - if (pa_idxset_size(s->inputs) >= PA_MAX_INPUTS_PER_SINK) { + if (!data->sink) + data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK, 1); + + CHECK_VALIDITY_RETURN_NULL(data->sink && data->sink->state == PA_SINK_RUNNING); + + if (!data->sample_spec_is_set) + data->sample_spec = data->sink->sample_spec; + + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(&data->sample_spec)); + + if (!data->channel_map_is_set) + pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); + + CHECK_VALIDITY_RETURN_NULL(pa_channel_map_valid(&data->channel_map)); + CHECK_VALIDITY_RETURN_NULL(data->channel_map.channels == data->sample_spec.channels); + + if (!data->volume_is_set) + pa_cvolume_reset(&data->volume, data->sample_spec.channels); + + CHECK_VALIDITY_RETURN_NULL(pa_cvolume_valid(&data->volume)); + CHECK_VALIDITY_RETURN_NULL(data->volume.channels == data->sample_spec.channels); + + if (data->resample_method == PA_RESAMPLER_INVALID) + data->resample_method = core->resample_method; + + CHECK_VALIDITY_RETURN_NULL(data->resample_method < PA_RESAMPLER_MAX); + + if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) { pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink."); return NULL; } - if (resample_method == PA_RESAMPLER_INVALID) - resample_method = s->core->resample_method; - - if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec) || !pa_channel_map_equal(map, &s->channel_map)) - if (!(resampler = pa_resampler_new(spec, map, &s->sample_spec, &s->channel_map, s->core->memblock_stat, resample_method))) { + if ((flags & PA_SINK_INPUT_VARIABLE_RATE) || + !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) || + !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) + + if (!(resampler = pa_resampler_new( + &data->sample_spec, &data->channel_map, + &data->sink->sample_spec, &data->sink->channel_map, + core->memblock_stat, + data->resample_method))) { pa_log_warn(__FILE__": Unsupported resampling operation."); return NULL; } @@ -100,15 +146,16 @@ pa_sink_input* pa_sink_input_new( i = pa_xnew(pa_sink_input, 1); i->ref = 1; i->state = PA_SINK_INPUT_DRAINED; - i->name = pa_xstrdup(name); - i->driver = pa_xstrdup(driver); - i->owner = NULL; - i->sink = s; - i->client = NULL; + i->flags = flags; + i->name = pa_xstrdup(data->name); + i->driver = pa_xstrdup(data->driver); + i->module = data->module; + i->sink = data->sink; + i->client = data->client; - i->sample_spec = *spec; - i->channel_map = *map; - i->volume = *volume; + i->sample_spec = data->sample_spec; + i->channel_map = data->channel_map; + i->volume = data->volume; i->peek = NULL; i->drop = NULL; @@ -116,25 +163,26 @@ pa_sink_input* pa_sink_input_new( i->get_latency = NULL; i->underrun = NULL; i->userdata = NULL; + i->move_silence = 0; pa_memchunk_reset(&i->resampled_chunk); i->resampler = resampler; - i->resample_method = resample_method; - i->variable_rate = variable_rate; - + i->resample_method = data->resample_method; i->silence_memblock = NULL; - assert(s->core); - r = pa_idxset_put(s->core->sink_inputs, i, &i->index); - assert(r == 0 && i->index != PA_IDXSET_INVALID); - r = pa_idxset_put(s->inputs, i, NULL); + r = pa_idxset_put(core->sink_inputs, i, &i->index); + assert(r == 0); + r = pa_idxset_put(i->sink->inputs, i, NULL); assert(r == 0); - pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"", i->index, i->name, s->index, st); - - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); + pa_log_info(__FILE__": created %u \"%s\" on %s with sample spec %s", + i->index, + i->name, + i->sink->name, + pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec)); + + pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); /* We do not call pa_sink_notify() here, because the virtual * functions have not yet been initialized */ diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index d33f382b9..243978fe9 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -27,11 +27,13 @@ typedef struct pa_sink_input pa_sink_input; #include -#include +#include #include #include #include #include +#include +#include typedef enum pa_sink_input_state { PA_SINK_INPUT_RUNNING, /*< The stream is alive and kicking */ @@ -40,20 +42,25 @@ typedef enum pa_sink_input_state { PA_SINK_INPUT_DISCONNECTED /*< The stream is dead */ } pa_sink_input_state_t; +typedef enum pa_sink_input_flags { + PA_SINK_INPUT_VARIABLE_RATE = 1, + PA_SINK_INPUT_NO_HOOKS = 2 +} pa_sink_input_flags_t; + struct pa_sink_input { int ref; uint32_t index; pa_sink_input_state_t state; + pa_sink_input_flags_t flags; char *name, *driver; /* may be NULL */ - pa_module *owner; /* may be NULL */ + pa_module *module; /* may be NULL */ + pa_client *client; /* may be NULL */ pa_sink *sink; - pa_client *client; /* may be NULL */ pa_sample_spec sample_spec; pa_channel_map channel_map; - pa_cvolume volume; /* Some silence to play before the actual data. This is used to @@ -78,15 +85,29 @@ struct pa_sink_input { pa_memblock *silence_memblock; /* may be NULL */ }; -pa_sink_input* pa_sink_input_new( - pa_sink *s, - const char *driver, - const char *name, - const pa_sample_spec *spec, - const pa_channel_map *map, - const pa_cvolume *volume, - int variable_rate, - pa_resample_method_t resample_method); +typedef struct pa_sink_input_new_data { + const char *name, *driver; + pa_module *module; + pa_client *client; + + pa_sink *sink; + + pa_sample_spec sample_spec; + int sample_spec_is_set; + pa_channel_map channel_map; + int channel_map_is_set; + pa_cvolume volume; + int volume_is_set; + + pa_resample_method_t resample_method; +} pa_sink_input_new_data; + +pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data); +void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec); +void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map); +void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume); + +pa_sink_input* pa_sink_input_new(pa_core *core, pa_sink_input_new_data *data, pa_sink_input_flags_t flags); void pa_sink_input_unref(pa_sink_input* i); pa_sink_input* pa_sink_input_ref(pa_sink_input* i); diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index 386f5bd01..6063b93e3 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -120,13 +120,20 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t le } } -int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume) { +int pa_play_file( + pa_sink *sink, + const char *fname, + const pa_cvolume *volume) { + struct userdata *u = NULL; SF_INFO sfinfo; pa_sample_spec ss; - assert(sink && fname); + pa_sink_input_new_data data; + + assert(sink); + assert(fname); - u = pa_xmalloc(sizeof(struct userdata)); + u = pa_xnew(struct userdata, 1); u->sink_input = NULL; u->memchunk.memblock = NULL; u->memchunk.index = u->memchunk.length = 0; @@ -171,8 +178,15 @@ int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume) { pa_log(__FILE__": Unsupported sample format in file %s", fname); goto fail; } + + pa_sink_input_new_data_init(&data); + data.sink = sink; + data.driver = __FILE__; + data.name = fname; + pa_sink_input_new_data_set_sample_spec(&data, &ss); + pa_sink_input_new_data_set_volume(&data, volume); - if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, fname, &ss, NULL, volume, 0, -1))) + if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0))) goto fail; u->sink_input->peek = sink_input_peek; @@ -180,7 +194,7 @@ int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume) { u->sink_input->kill = sink_input_kill; u->sink_input->userdata = u; - pa_sink_notify(sink); + pa_sink_notify(u->sink_input->sink); return 0; From b37ad1ffd37b2e590191c3dced2b92bb72071dd2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 16:21:20 +0000 Subject: [PATCH 1138/1514] modify module-volume-restore to change the initial volume of a sink input from a hook instead of an asyncronous subscription event. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1238 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 35 +++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index d09565097..d49cceb02 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -68,6 +68,7 @@ struct rule { struct userdata { pa_hashmap *hashmap; pa_subscription *subscription; + pa_hook_slot *hook_slot; int modified; char *table_file; }; @@ -255,7 +256,7 @@ static char* client_name(pa_client *c) { return t; } -static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { +static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = userdata; pa_sink_input *si; struct rule *r; @@ -277,15 +278,11 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v if ((r = pa_hashmap_get(u->hashmap, name))) { pa_xfree(name); - if (((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) && si->sample_spec.channels == r->volume.channels) { - pa_log_info(__FILE__": Restoring volume for <%s>", r->name); - pa_sink_input_set_volume(si, &r->volume); - } else if (!pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { + if (!pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { pa_log_info(__FILE__": Saving volume for <%s>", r->name); r->volume = *pa_sink_input_get_volume(si); u->modified = 1; } - } else { pa_log_info(__FILE__": Creating new entry for <%s>", name); @@ -298,6 +295,26 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v } } +static pa_hook_result_t hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { + struct rule *r; + char *name; + + assert(data); + + if (!data->client || !(name = client_name(data->client))) + return PA_HOOK_OK; + + if ((r = pa_hashmap_get(u->hashmap, name))) { + + if (data->sample_spec_is_set && data->sample_spec.channels == r->volume.channels) { + pa_log_info(__FILE__": Restoring volume for <%s>", r->name); + pa_sink_input_new_data_set_volume(data, &r->volume); + } + } + + return PA_HOOK_OK; +} + int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; @@ -321,7 +338,8 @@ int pa__init(pa_core *c, pa_module*m) { if (load_rules(u) < 0) goto fail; - u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); + u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, subscribe_callback, u); + u->hook_slot = pa_hook_connect(&c->hook_sink_input_new, (pa_hook_cb_t) hook_callback, u); pa_modargs_free(ma); return 0; @@ -355,6 +373,9 @@ void pa__done(pa_core *c, pa_module*m) { if (u->subscription) pa_subscription_free(u->subscription); + if (u->hook_slot) + pa_hook_slot_free(u->hook_slot); + if (u->hashmap) { if (u->modified) From 3beef50639ff340635eca154d1d9c90fcf002fed Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 16:22:20 +0000 Subject: [PATCH 1139/1514] hide hook-list-test git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1239 fefdeb5f-60dc-0310-8127-8f9354f1896f From 72cf2118df6a3cb0515bcb426e2dc57c781fa2b1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 17:30:51 +0000 Subject: [PATCH 1140/1514] remove pa_sink_input::variable_rate field since it has been folded into pa_sink_input::flags git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1240 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sink-input.c | 2 +- src/pulsecore/sink-input.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index ff5213e19..21050d224 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -532,7 +532,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { /* Try to reuse the old resampler if possible */ new_resampler = i->resampler; - else if (i->variable_rate || + else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) || !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) || !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) { diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 243978fe9..da0c26620 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -79,7 +79,6 @@ struct pa_sink_input { pa_memchunk resampled_chunk; pa_resampler *resampler; /* may be NULL */ - int variable_rate; pa_resample_method_t resample_method; pa_memblock *silence_memblock; /* may be NULL */ From abbabd848a3ece49d58f59c88edc379d73bbd77e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 17:31:58 +0000 Subject: [PATCH 1141/1514] ignore if we recieved a memory block for an invalid stream, since this might happen unwillingly due to the asychnronous nature of the protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1241 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-native.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index f922fb556..e53444485 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2201,7 +2201,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) { pa_log(__FILE__": client sent block for invalid stream."); - connection_free(c); + /* Ignoring */ return; } From 87e64d58454f73bfa1e979b0fedfea7e0827d845 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 17:32:35 +0000 Subject: [PATCH 1142/1514] Clean up module description a little git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1242 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index d49cceb02..bdead0f62 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -47,7 +47,7 @@ #include "module-volume-restore-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Playback stream automatic volume restore module") +PA_MODULE_DESCRIPTION("Automatically restore volume of playback streams") PA_MODULE_USAGE("table=") PA_MODULE_VERSION(PACKAGE_VERSION) From 818083289882e8739bbfaefd1edb252ed5629771 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 17:33:32 +0000 Subject: [PATCH 1143/1514] properly implement a pa_sink_disconnect() hook git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1243 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core.c | 4 ++-- src/pulsecore/core.h | 3 ++- src/pulsecore/sink.c | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 24f835f79..50d79fbfb 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -93,7 +93,7 @@ pa_core* pa_core_new(pa_mainloop_api *m) { c->is_system_instance = 0; pa_hook_init(&c->hook_sink_input_new, c); - pa_hook_init(&c->hook_sink_input_disconnect, c); + pa_hook_init(&c->hook_sink_disconnect, c); pa_property_init(c); @@ -142,7 +142,7 @@ void pa_core_free(pa_core *c) { pa_property_cleanup(c); pa_hook_free(&c->hook_sink_input_new); - pa_hook_free(&c->hook_sink_input_disconnect); + pa_hook_free(&c->hook_sink_disconnect); pa_xfree(c); } diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index fd92de61f..22dec50c4 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -81,7 +81,8 @@ struct pa_core { int is_system_instance; /* hooks */ - pa_hook hook_sink_input_new, hook_sink_input_disconnect; + pa_hook hook_sink_input_new, + hook_sink_disconnect; }; pa_core* pa_core_new(pa_mainloop_api *m); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index e770950cf..557d5efcb 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -143,7 +143,10 @@ void pa_sink_disconnect(pa_sink* s) { assert(s); assert(s->state == PA_SINK_RUNNING); + s->state = PA_SINK_DISCONNECTED; pa_namereg_unregister(s->core, s->name); + + pa_hook_fire(&s->core->hook_sink_disconnect, s); while ((i = pa_idxset_first(s->inputs, NULL))) { assert(i != j); @@ -163,7 +166,6 @@ void pa_sink_disconnect(pa_sink* s) { s->set_hw_mute = NULL; s->get_hw_mute = NULL; - s->state = PA_SINK_DISCONNECTED; pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); } From dd8706115378193c8f8889526c108a2b49653619 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 17:34:36 +0000 Subject: [PATCH 1144/1514] implement new module "module-rescue-streams" which moves sink inputs away when their sink is removed. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1244 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 10 ++- src/modules/module-rescue-streams.c | 98 +++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/modules/module-rescue-streams.c diff --git a/src/Makefile.am b/src/Makefile.am index 3cf3168c4..0ab0436b4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -812,7 +812,8 @@ modlibexec_LTLIBRARIES += \ module-esound-sink.la \ module-http-protocol-tcp.la \ module-detect.la \ - module-volume-restore.la + module-volume-restore.la \ + module-rescue-streams.la # See comment at librtp.la above if !OS_IS_WIN32 @@ -955,6 +956,7 @@ SYMDEF_FILES = \ modules/module-jack-sink-symdef.h \ modules/module-jack-source-symdef.h \ modules/module-volume-restore-symdef.h \ + modules/module-rescue-streams-symdef.h \ modules/module-hal-detect-symdef.h \ modules/gconf/module-gconf-symdef.h @@ -1173,6 +1175,12 @@ module_volume_restore_la_LDFLAGS = -module -avoid-version module_volume_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_volume_restore_la_CFLAGS = $(AM_CFLAGS) +# Rescue streams module +module_rescue_streams_la_SOURCES = modules/module-rescue-streams.c +module_rescue_streams_la_LDFLAGS = -module -avoid-version +module_rescue_streams_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_rescue_streams_la_CFLAGS = $(AM_CFLAGS) + # RTP modules module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c module_rtp_send_la_LDFLAGS = -module -avoid-version diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c new file mode 100644 index 000000000..0e3946b1f --- /dev/null +++ b/src/modules/module-rescue-streams.c @@ -0,0 +1,98 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include + +#include "module-rescue-streams-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("When a sink/source is removed, try to move their streams to the default sink/source") +PA_MODULE_VERSION(PACKAGE_VERSION) + +static const char* const valid_modargs[] = { + NULL, +}; + +static pa_hook_result_t hook_callback(pa_core *c, pa_sink *sink, void* userdata) { + pa_sink_input *i; + pa_sink *target; + + assert(c); + assert(sink); + + if (!pa_idxset_size(sink->inputs)) { + pa_log_debug(__FILE__": No sink inputs to move away."); + return PA_HOOK_OK; + } + + if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, 0))) { + pa_log_info(__FILE__": No evacuation sink found."); + return PA_HOOK_OK; + } + + assert(target != sink); + + while ((i = pa_idxset_first(sink->inputs, NULL))) { + if (pa_sink_input_move_to(i, target, 1) < 0) { + pa_log_warn(__FILE__": Failed to move sink input %u \"%s\" to %s.", i->index, i->name, target->name); + return PA_HOOK_OK; + } + + pa_log_info(__FILE__": Sucessfully moved sink input %u \"%s\" to %s.", i->index, i->name, target->name); + } + + + return PA_HOOK_OK; +} + +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; + + assert(c); + assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": Failed to parse module arguments"); + return -1; + } + + m->userdata = pa_hook_connect(&c->hook_sink_disconnect, (pa_hook_cb_t) hook_callback, NULL); + + pa_modargs_free(ma); + return 0; +} + +void pa__done(pa_core *c, pa_module*m) { + assert(c); + assert(m); + + if (m->userdata) + pa_hook_slot_free((pa_hook_slot*) m->userdata); +} From a7b9a7d599d461b36d225849bdbf2d5c6ad73008 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 17:35:46 +0000 Subject: [PATCH 1145/1514] Load module-rescue-streams by default git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1245 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/default.pa.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index ef6048d6a..74148cd19 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -55,6 +55,9 @@ load-module module-native-protocol-unix ### Automatically restore the volume of playback streams load-module module-volume-restore +### Automatically move streams to the default sink if the sink they are connected to dies +load-module module-rescue-streams + ### Make some devices default #set-default-sink output #set-default-source input From a09a49e41b086721ed644a0c9573e701e945287d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 17:39:19 +0000 Subject: [PATCH 1146/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1246 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/todo b/todo index 7fbf01a86..573fc2a1d 100644 --- a/todo +++ b/todo @@ -4,6 +4,7 @@ Build System: - Remove symdef files and use macros (like most other projects) - Use own name mangling scheme instead of ltdl's, which will eliminate the need for .la files or extra trickery. +- build pulsecore only statically by default, it's not a public API yet Porting: - rtp module ported to Win32 (sendmsg/recvmsg emulation) @@ -32,7 +33,8 @@ Features: - alsa mmap driver - alsa driver with hw mixing - allow passing data with shared memory between local clients and the server -- hooks for creating sink inputs/window manager for sound +- "window manager for sound" +- hooks for pa_source_output_new, pa_source_disconnect() - chroot() - use scatter/gather io for sockets - CODECs to reduce bandwidth usage (plug-in based) From 8f91b1f4c4b47997ce4bfd70dc4e0f7fffe58a35 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 19:52:43 +0000 Subject: [PATCH 1147/1514] define new hooks: hook_source_output_new, hook_source_disconnect git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1247 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core.c | 4 ++++ src/pulsecore/core.h | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 50d79fbfb..7f2f0f60d 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -94,6 +94,8 @@ pa_core* pa_core_new(pa_mainloop_api *m) { pa_hook_init(&c->hook_sink_input_new, c); pa_hook_init(&c->hook_sink_disconnect, c); + pa_hook_init(&c->hook_source_output_new, c); + pa_hook_init(&c->hook_source_disconnect, c); pa_property_init(c); @@ -143,6 +145,8 @@ void pa_core_free(pa_core *c) { pa_hook_free(&c->hook_sink_input_new); pa_hook_free(&c->hook_sink_disconnect); + pa_hook_free(&c->hook_source_output_new); + pa_hook_free(&c->hook_source_disconnect); pa_xfree(c); } diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 22dec50c4..f9fa386e8 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -81,8 +81,11 @@ struct pa_core { int is_system_instance; /* hooks */ - pa_hook hook_sink_input_new, - hook_sink_disconnect; + pa_hook + hook_sink_input_new, + hook_sink_disconnect, + hook_source_output_new, + hook_source_disconnect; }; pa_core* pa_core_new(pa_mainloop_api *m); From 79cb80c5740dd00fae89464e7d03f1a7ade6ccdd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 19:53:18 +0000 Subject: [PATCH 1148/1514] implement hook_source_disconnect git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1248 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/source.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index ae72f040d..0d55da448 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -125,7 +125,10 @@ void pa_source_disconnect(pa_source *s) { assert(s); assert(s->state == PA_SOURCE_RUNNING); + s->state = PA_SOURCE_DISCONNECTED; pa_namereg_unregister(s->core, s->name); + + pa_hook_fire(&s->core->hook_source_disconnect, s); while ((o = pa_idxset_first(s->outputs, NULL))) { assert(o != j); @@ -142,7 +145,6 @@ void pa_source_disconnect(pa_source *s) { s->set_hw_mute = NULL; s->get_hw_mute = NULL; - s->state = PA_SOURCE_DISCONNECTED; pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); } From e0f7e8614ce06f2b0a4bd5a38189cf97b07c0d30 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 19:53:35 +0000 Subject: [PATCH 1149/1514] split a validity check into two git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1249 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sink-input.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 21050d224..b3fabad3a 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -101,7 +101,8 @@ pa_sink_input* pa_sink_input_new( if (!data->sink) data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK, 1); - CHECK_VALIDITY_RETURN_NULL(data->sink && data->sink->state == PA_SINK_RUNNING); + CHECK_VALIDITY_RETURN_NULL(data->sink); + CHECK_VALIDITY_RETURN_NULL(data->sink->state == PA_SINK_RUNNING); if (!data->sample_spec_is_set) data->sample_spec = data->sink->sample_spec; From a75e1ed9ef483c4c08f0fc963c0ea1a980f0c0e9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 19:55:17 +0000 Subject: [PATCH 1150/1514] implement hook_source_ouput_new. For this I modified the pa_source_output_new constructor to take a struct similar to what I already did for pa_sink_input_new() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1250 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-send.c | 11 ++- src/pulsecore/cli-text.c | 4 +- src/pulsecore/protocol-esound.c | 26 ++++--- src/pulsecore/protocol-native.c | 17 ++++- src/pulsecore/protocol-simple.c | 19 +++-- src/pulsecore/sink-input.h | 5 +- src/pulsecore/source-output.c | 119 ++++++++++++++++++++---------- src/pulsecore/source-output.h | 35 +++++++-- 8 files changed, 160 insertions(+), 76 deletions(-) diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 5c47047fd..52cd4052b 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -168,6 +168,7 @@ int pa__init(pa_core *c, pa_module*m) { struct timeval tv; char hn[128], *n; int loop = 0; + pa_source_output_new_data data; assert(c); assert(m); @@ -263,8 +264,15 @@ int pa__init(pa_core *c, pa_module*m) { pa_log(__FILE__": IP_MULTICAST_LOOP failed: %s", pa_cstrerror(errno)); goto fail; } + + pa_source_output_new_data_init(&data); + data.name = "RTP Monitor Stream"; + data.driver = __FILE__; + data.module = m; + pa_source_output_new_data_set_sample_spec(&data, &ss); + pa_source_output_new_data_set_channel_map(&data, &cm); - if (!(o = pa_source_output_new(s, __FILE__, "RTP Monitor Stream", &ss, &cm, PA_RESAMPLER_INVALID))) { + if (!(o = pa_source_output_new(c, &data, 0))) { pa_log(__FILE__": failed to create source output."); goto fail; } @@ -272,7 +280,6 @@ int pa__init(pa_core *c, pa_module*m) { o->push = source_output_push; o->kill = source_output_kill; o->get_latency = source_output_get_latency; - o->owner = m; u = pa_xnew(struct userdata, 1); m->userdata = u; diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index ff083dc31..49934c07d 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -204,8 +204,8 @@ char *pa_source_output_list_to_string(pa_core *c) { pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map), pa_resample_method_to_string(pa_source_output_get_resample_method(o))); - if (o->owner) - pa_strbuf_printf(s, "\towner module: <%u>\n", o->owner->index); + if (o->module) + pa_strbuf_printf(s, "\towner module: <%u>\n", o->module->index); if (o->client) pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", o->client->index, o->client->name); } diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 724dccbc9..f1a827bce 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -349,9 +349,11 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t strncpy(name, data, sizeof(name)); name[sizeof(name)-1] = 0; + utf8_name = pa_utf8_filter(name); - pa_client_set_name(c->client, utf8_name); + pa_xfree(utf8_name); + c->original_name = pa_xstrdup(name); assert(!c->sink_input && !c->input_memblockq); @@ -359,15 +361,12 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t pa_sink_input_new_data_init(&sdata); sdata.sink = sink; sdata.driver = __FILE__; - sdata.name = utf8_name; + sdata.name = c->client->name; pa_sink_input_new_data_set_sample_spec(&sdata, &ss); sdata.module = c->protocol->module; sdata.client = c->client; c->sink_input = pa_sink_input_new(c->protocol->core, &sdata, 0); - - pa_xfree(utf8_name); - CHECK_VALIDITY(c->sink_input, "Failed to create sink input."); l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); @@ -402,6 +401,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co pa_source *source; pa_sample_spec ss; size_t l; + pa_source_output_new_data sdata; assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX)); @@ -450,10 +450,16 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co assert(!c->output_memblockq && !c->source_output); - if (!(c->source_output = pa_source_output_new(source, __FILE__, c->client->name, &ss, NULL, -1))) { - pa_log(__FILE__": failed to create source output"); - return -1; - } + pa_source_output_new_data_init(&sdata); + sdata.source = source; + sdata.driver = __FILE__; + sdata.name = c->client->name; + pa_source_output_new_data_set_sample_spec(&sdata, &ss); + sdata.module = c->protocol->module; + sdata.client = c->client; + + c->source_output = pa_source_output_new(c->protocol->core, &sdata, 9); + CHECK_VALIDITY(c->sink_input, "Failed to create source_output."); l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS); c->output_memblockq = pa_memblockq_new( @@ -467,8 +473,6 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co c->protocol->core->memblock_stat); pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2); - c->source_output->owner = c->protocol->module; - c->source_output->client = c->client; c->source_output->push = source_output_push_cb; c->source_output->kill = source_output_kill_cb; c->source_output->get_latency = source_output_get_latency_cb; diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index e53444485..0b79892c5 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -317,9 +317,20 @@ static struct record_stream* record_stream_new( struct record_stream *s; pa_source_output *source_output; size_t base; + pa_source_output_new_data data; + assert(c && source && ss && name && maxlength); - if (!(source_output = pa_source_output_new(source, __FILE__, name, ss, map, -1))) + pa_source_output_new_data_init(&data); + data.source = source; + data.driver = __FILE__; + data.name = name; + pa_source_output_new_data_set_sample_spec(&data, ss); + pa_source_output_new_data_set_channel_map(&data, map); + data.module = c->protocol->module; + data.client = c->client; + + if (!(source_output = pa_source_output_new(source->core, &data, 0))) return NULL; s = pa_xnew(struct record_stream, 1); @@ -329,8 +340,6 @@ static struct record_stream* record_stream_new( s->source_output->kill = source_output_kill_cb; s->source_output->get_latency = source_output_get_latency_cb; s->source_output->userdata = s; - s->source_output->owner = c->protocol->module; - s->source_output->client = c->client; s->memblockq = pa_memblockq_new( 0, @@ -1356,7 +1365,7 @@ static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) { assert(t && s); pa_tagstruct_putu32(t, s->index); pa_tagstruct_puts(t, s->name); - pa_tagstruct_putu32(t, s->owner ? s->owner->index : PA_INVALID_INDEX); + pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX); pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX); pa_tagstruct_putu32(t, s->source->index); pa_tagstruct_put_sample_spec(t, &s->sample_spec); diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 5071191a0..3705986d5 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -379,22 +379,20 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) } if (p->mode & RECORD) { - pa_source *source; + pa_source_output_new_data data; size_t l; - if (!(source = pa_namereg_get(p->core, p->source_name, PA_NAMEREG_SOURCE, 1))) { - pa_log(__FILE__": Failed to get source."); - goto fail; - } + pa_source_output_new_data_init(&data); + data.driver = __FILE__; + data.name = c->client->name; + pa_source_output_new_data_set_sample_spec(&data, &p->sample_spec); + data.module = p->module; + data.client = c->client; - c->source_output = pa_source_output_new(source, __FILE__, c->client->name, &p->sample_spec, NULL, -1); - if (!c->source_output) { + if (!(c->source_output = pa_source_output_new(p->core, &data, 0))) { pa_log(__FILE__": Failed to create source output."); goto fail; } - c->source_output->owner = p->module; - c->source_output->client = c->client; - c->source_output->push = source_output_push_cb; c->source_output->kill = source_output_kill_cb; c->source_output->get_latency = source_output_get_latency_cb; @@ -411,6 +409,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) NULL, p->core->memblock_stat); pa_iochannel_socket_set_sndbuf(io, l/RECORD_BUFFER_FRAGMENTS*2); + pa_source_notify(c->source_output->source); } pa_iochannel_set_callback(c->io, io_callback, c); diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index da0c26620..2943dfaef 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -106,7 +106,10 @@ void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map); void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume); -pa_sink_input* pa_sink_input_new(pa_core *core, pa_sink_input_new_data *data, pa_sink_input_flags_t flags); +pa_sink_input* pa_sink_input_new( + pa_core *core, + pa_sink_input_new_data *data, + pa_sink_input_flags_t flags); void pa_sink_input_unref(pa_sink_input* i); pa_sink_input* pa_sink_input_ref(pa_sink_input* i); diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 36ea420ca..7371474f1 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -33,6 +33,7 @@ #include #include +#include #include "source-output.h" @@ -42,44 +43,82 @@ if (!(condition)) \ return NULL; \ } while (0) +pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data) { + assert(data); + + memset(data, 0, sizeof(*data)); + data->resample_method = PA_RESAMPLER_INVALID; + return data; +} + +void pa_source_output_new_data_set_channel_map(pa_source_output_new_data *data, const pa_channel_map *map) { + assert(data); + + if ((data->channel_map_is_set = !!map)) + data->channel_map = *map; +} + +void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data, const pa_sample_spec *spec) { + assert(data); + + if ((data->sample_spec_is_set = !!spec)) + data->sample_spec = *spec; +} + pa_source_output* pa_source_output_new( - pa_source *s, - const char *driver, - const char *name, - const pa_sample_spec *spec, - const pa_channel_map *map, - int resample_method) { + pa_core *core, + pa_source_output_new_data *data, + pa_source_output_flags_t flags) { pa_source_output *o; pa_resampler *resampler = NULL; int r; - char st[256]; - pa_channel_map tmap; + char st[PA_SAMPLE_SPEC_SNPRINT_MAX]; - assert(s); - assert(spec); - assert(s->state == PA_SOURCE_RUNNING); + assert(core); + assert(data); - CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + if (!(flags & PA_SOURCE_OUTPUT_NO_HOOKS)) + if (pa_hook_fire(&core->hook_source_output_new, data) < 0) + return NULL; - if (!map) - map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); + CHECK_VALIDITY_RETURN_NULL(!data->driver || pa_utf8_valid(data->driver)); + CHECK_VALIDITY_RETURN_NULL(!data->name || pa_utf8_valid(data->name)); + + if (!data->source) + data->source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE, 1); + + CHECK_VALIDITY_RETURN_NULL(data->source); + CHECK_VALIDITY_RETURN_NULL(data->source->state == PA_SOURCE_RUNNING); - CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); - CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); - CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); - CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name)); + if (!data->sample_spec_is_set) + data->sample_spec = data->source->sample_spec; + + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(&data->sample_spec)); - if (pa_idxset_size(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { + if (!data->channel_map_is_set) + pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); + + CHECK_VALIDITY_RETURN_NULL(pa_channel_map_valid(&data->channel_map)); + CHECK_VALIDITY_RETURN_NULL(data->channel_map.channels == data->sample_spec.channels); + + if (data->resample_method == PA_RESAMPLER_INVALID) + data->resample_method = core->resample_method; + + CHECK_VALIDITY_RETURN_NULL(data->resample_method < PA_RESAMPLER_MAX); + + if (pa_idxset_size(data->source->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { pa_log(__FILE__": Failed to create source output: too many outputs per source."); return NULL; } - if (resample_method == PA_RESAMPLER_INVALID) - resample_method = s->core->resample_method; - - if (!pa_sample_spec_equal(&s->sample_spec, spec) || !pa_channel_map_equal(&s->channel_map, map)) - if (!(resampler = pa_resampler_new(&s->sample_spec, &s->channel_map, spec, map, s->core->memblock_stat, resample_method))) { + if (!pa_sample_spec_equal(&data->sample_spec, &data->source->sample_spec) || + !pa_channel_map_equal(&data->channel_map, &data->source->channel_map)) + if (!(resampler = pa_resampler_new( + &data->source->sample_spec, &data->source->channel_map, + &data->sample_spec, &data->channel_map, + core->memblock_stat, + data->resample_method))) { pa_log_warn(__FILE__": Unsupported resampling operation."); return NULL; } @@ -87,14 +126,14 @@ pa_source_output* pa_source_output_new( o = pa_xnew(pa_source_output, 1); o->ref = 1; o->state = PA_SOURCE_OUTPUT_RUNNING; - o->name = pa_xstrdup(name); - o->driver = pa_xstrdup(driver); - o->owner = NULL; - o->source = s; - o->client = NULL; + o->name = pa_xstrdup(data->name); + o->driver = pa_xstrdup(data->driver); + o->module = data->module; + o->source = data->source; + o->client = data->client; - o->sample_spec = *spec; - o->channel_map = *map; + o->sample_spec = data->sample_spec; + o->channel_map = data->channel_map; o->push = NULL; o->kill = NULL; @@ -102,18 +141,20 @@ pa_source_output* pa_source_output_new( o->userdata = NULL; o->resampler = resampler; - o->resample_method = resample_method; + o->resample_method = data->resample_method; - assert(s->core); - r = pa_idxset_put(s->core->source_outputs, o, &o->index); - assert(r == 0 && o->index != PA_IDXSET_INVALID); - r = pa_idxset_put(s->outputs, o, NULL); + r = pa_idxset_put(core->source_outputs, o, &o->index); + assert(r == 0); + r = pa_idxset_put(o->source->outputs, o, NULL); assert(r == 0); - pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info(__FILE__": created %u \"%s\" on %u with sample spec \"%s\"", o->index, o->name, s->index, st); + pa_log_info(__FILE__": created %u \"%s\" on %s with sample spec %s", + o->index, + o->name, + o->source->name, + pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec)); - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index); + pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index); /* We do not call pa_source_notify() here, because the virtual * functions have not yet been initialized */ diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index acf53bd1f..f7396a195 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -39,13 +39,17 @@ typedef enum { PA_SOURCE_OUTPUT_DISCONNECTED } pa_source_output_state_t; +typedef enum pa_source_output_flags { + PA_SOURCE_OUTPUT_NO_HOOKS = 1 +} pa_source_output_flags_t; + struct pa_source_output { int ref; uint32_t index; pa_source_output_state_t state; char *name, *driver; /* may be NULL */ - pa_module *owner; /* may be NULL */ + pa_module *module; /* may be NULL */ pa_source *source; pa_client *client; /* may be NULL */ @@ -63,13 +67,30 @@ struct pa_source_output { void *userdata; }; +typedef struct pa_source_output_new_data { + const char *name, *driver; + pa_module *module; + pa_client *client; + + pa_source *source; + + pa_sample_spec sample_spec; + int sample_spec_is_set; + pa_channel_map channel_map; + int channel_map_is_set; + + pa_resample_method_t resample_method; +} pa_source_output_new_data; + +pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data); +void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data, const pa_sample_spec *spec); +void pa_source_output_new_data_set_channel_map(pa_source_output_new_data *data, const pa_channel_map *map); +void pa_source_output_new_data_set_volume(pa_source_output_new_data *data, const pa_cvolume *volume); + pa_source_output* pa_source_output_new( - pa_source *s, - const char *driver, - const char *name, - const pa_sample_spec *spec, - const pa_channel_map *map, - int resample_method); + pa_core *core, + pa_source_output_new_data *data, + pa_source_output_flags_t flags); void pa_source_output_unref(pa_source_output* o); pa_source_output* pa_source_output_ref(pa_source_output *o); From d182a0b1cb2eede12a7e3f902d9f2d374a2a6838 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 20:43:22 +0000 Subject: [PATCH 1151/1514] minor optimization git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1251 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/dynarray.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/dynarray.c b/src/pulsecore/dynarray.c index d1ab11610..cd1fcb0fd 100644 --- a/src/pulsecore/dynarray.c +++ b/src/pulsecore/dynarray.c @@ -90,7 +90,7 @@ unsigned pa_dynarray_append(pa_dynarray*a, void *p) { void *pa_dynarray_get(pa_dynarray*a, unsigned i) { assert(a); - if (i >= a->n_allocated) + if (i >= a->n_entries) return NULL; assert(a->data); From cdb173f6aba3e514d5d5c0abbd07e2722dd4d205 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 20:44:00 +0000 Subject: [PATCH 1152/1514] create rtp source output on correct source git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1252 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-send.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 52cd4052b..759aa8197 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -269,6 +269,7 @@ int pa__init(pa_core *c, pa_module*m) { data.name = "RTP Monitor Stream"; data.driver = __FILE__; data.module = m; + data.source = s; pa_source_output_new_data_set_sample_spec(&data, &ss); pa_source_output_new_data_set_channel_map(&data, &cm); From 3334814ebb3c955b696c413ac5246ddb09efefe2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 20:44:32 +0000 Subject: [PATCH 1153/1514] fix a segfault when registering a service with avahi fails git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1253 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-zeroconf-publish.c | 31 +++++++++++++++++++-------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 16315d350..24e324f8b 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -225,9 +225,8 @@ finish: if (s->published == UNPUBLISHED) { /* Remove this service */ - if (s->entry_group) { + if (s->entry_group) avahi_entry_group_free(s->entry_group); - } pa_hashmap_remove(u->services, s->name); pa_xfree(s->name); @@ -263,6 +262,7 @@ static struct service *get_service(struct userdata *u, const char *name) { static int publish_sink(struct userdata *u, pa_sink *s) { struct service *svc; + int ret; assert(u && s); svc = get_service(u, s->name); @@ -273,13 +273,17 @@ static int publish_sink(struct userdata *u, pa_sink *s) { svc->loaded.type = PA_NAMEREG_SINK; svc->loaded.index = s->index; - pa_dynarray_put(u->sink_dynarray, s->index, svc); + if ((ret = publish_service(u, svc)) < 0) + return ret; - return publish_service(u, svc); + pa_dynarray_put(u->sink_dynarray, s->index, svc); + return ret; } static int publish_source(struct userdata *u, pa_source *s) { struct service *svc; + int ret; + assert(u && s); svc = get_service(u, s->name); @@ -292,11 +296,17 @@ static int publish_source(struct userdata *u, pa_source *s) { pa_dynarray_put(u->source_dynarray, s->index, svc); - return publish_service(u, svc); + if ((ret = publish_service(u, svc)) < 0) + return ret; + + pa_dynarray_put(u->sink_dynarray, s->index, svc); + return ret; } static int publish_autoload(struct userdata *u, pa_autoload_entry *s) { struct service *svc; + int ret; + assert(u && s); svc = get_service(u, s->name); @@ -307,9 +317,11 @@ static int publish_autoload(struct userdata *u, pa_autoload_entry *s) { svc->autoload.type = s->type; svc->autoload.index = s->index; - pa_dynarray_put(u->autoload_dynarray, s->index, svc); + if ((ret = publish_service(u, svc)) < 0) + return ret; - return publish_service(u, svc); + pa_dynarray_put(u->autoload_dynarray, s->index, svc); + return ret; } static int remove_sink(struct userdata *u, uint32_t idx) { @@ -653,6 +665,9 @@ void pa__done(pa_core *c, pa_module*m) { if (u->services) pa_hashmap_free(u->services, service_free, u); + if (u->subscription) + pa_subscription_free(u->subscription); + if (u->sink_dynarray) pa_dynarray_free(u->sink_dynarray, NULL, NULL); if (u->source_dynarray) @@ -660,8 +675,6 @@ void pa__done(pa_core *c, pa_module*m) { if (u->autoload_dynarray) pa_dynarray_free(u->autoload_dynarray, NULL, NULL); - if (u->subscription) - pa_subscription_free(u->subscription); if (u->main_entry_group) avahi_entry_group_free(u->main_entry_group); From 2bf46537136a73220771c899e86a52b1ee9b22d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 20:45:19 +0000 Subject: [PATCH 1154/1514] extend module-rescue-streams to move also source outputs when a source dies git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1254 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-rescue-streams.c | 59 +++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c index 0e3946b1f..5700ef438 100644 --- a/src/modules/module-rescue-streams.c +++ b/src/modules/module-rescue-streams.c @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include #include @@ -40,7 +42,11 @@ static const char* const valid_modargs[] = { NULL, }; -static pa_hook_result_t hook_callback(pa_core *c, pa_sink *sink, void* userdata) { +struct userdata { + pa_hook_slot *sink_slot, *source_slot; +}; + +static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* userdata) { pa_sink_input *i; pa_sink *target; @@ -72,8 +78,41 @@ static pa_hook_result_t hook_callback(pa_core *c, pa_sink *sink, void* userdata) return PA_HOOK_OK; } +static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void* userdata) { + pa_source_output *o; + pa_source *target; + + assert(c); + assert(source); + + if (!pa_idxset_size(source->outputs)) { + pa_log_debug(__FILE__": No source outputs to move away."); + return PA_HOOK_OK; + } + + if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SOURCE, 0))) { + pa_log_info(__FILE__": No evacuation source found."); + return PA_HOOK_OK; + } + + assert(target != source); + + while ((o = pa_idxset_first(source->outputs, NULL))) { + if (pa_source_output_move_to(o, target) < 0) { + pa_log_warn(__FILE__": Failed to move source output %u \"%s\" to %s.", o->index, o->name, target->name); + return PA_HOOK_OK; + } + + pa_log_info(__FILE__": Sucessfully moved source output %u \"%s\" to %s.", o->index, o->name, target->name); + } + + + return PA_HOOK_OK; +} + int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; + struct userdata *u; assert(c); assert(m); @@ -83,16 +122,28 @@ int pa__init(pa_core *c, pa_module*m) { return -1; } - m->userdata = pa_hook_connect(&c->hook_sink_disconnect, (pa_hook_cb_t) hook_callback, NULL); + m->userdata = u = pa_xnew(struct userdata, 1); + u->sink_slot = pa_hook_connect(&c->hook_sink_disconnect, (pa_hook_cb_t) sink_hook_callback, NULL); + u->source_slot = pa_hook_connect(&c->hook_source_disconnect, (pa_hook_cb_t) source_hook_callback, NULL); pa_modargs_free(ma); return 0; } void pa__done(pa_core *c, pa_module*m) { + struct userdata *u; + assert(c); assert(m); - if (m->userdata) - pa_hook_slot_free((pa_hook_slot*) m->userdata); + if (!m->userdata) + return; + + u = m->userdata; + if (u->sink_slot) + pa_hook_slot_free(u->sink_slot); + if (u->source_slot) + pa_hook_slot_free(u->source_slot); + + pa_xfree(u); } From 5d8d9164747c0cded726e86b4fc84505305e87dd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 20:45:54 +0000 Subject: [PATCH 1155/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1255 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index 573fc2a1d..d4165481e 100644 --- a/todo +++ b/todo @@ -34,7 +34,6 @@ Features: - alsa driver with hw mixing - allow passing data with shared memory between local clients and the server - "window manager for sound" -- hooks for pa_source_output_new, pa_source_disconnect() - chroot() - use scatter/gather io for sockets - CODECs to reduce bandwidth usage (plug-in based) From 6c39af7ad368743463540e85982c63b9d351e7a2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 14 Aug 2006 08:38:07 +0000 Subject: [PATCH 1156/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1256 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 + 1 file changed, 1 insertion(+) diff --git a/todo b/todo index d4165481e..2c67f6d5e 100644 --- a/todo +++ b/todo @@ -45,6 +45,7 @@ Features: - examine if it is possible to mimic esd's handling of half duplex cards (switch to capture when a recording client connects and drop playback during that time) +- Support for device selection in waveout driver Long term: - pass meta info for hearing impaired From 1c3bfc44dcbd760687ea841d893c35db510804af Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 15 Aug 2006 18:15:00 +0000 Subject: [PATCH 1157/1514] use the description field of sinks/sources to name the zeroconf services, instead of the logical name git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1257 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-zeroconf-publish.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 24e324f8b..651a95b7a 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -240,7 +240,7 @@ finish: return r; } -static struct service *get_service(struct userdata *u, const char *name) { +static struct service *get_service(struct userdata *u, const char *name, const char *description) { struct service *s; char hn[64]; @@ -253,7 +253,7 @@ static struct service *get_service(struct userdata *u, const char *name) { s->published = UNPUBLISHED; s->name = pa_xstrdup(name); s->loaded.valid = s->autoload.valid = 0; - s->service_name = pa_sprintf_malloc("%s on %s", s->name, pa_get_host_name(hn, sizeof(hn))); + s->service_name = pa_sprintf_malloc("%s on %s", description ? description : s->name, pa_get_host_name(hn, sizeof(hn))); pa_hashmap_put(u->services, s->name, s); @@ -265,7 +265,7 @@ static int publish_sink(struct userdata *u, pa_sink *s) { int ret; assert(u && s); - svc = get_service(u, s->name); + svc = get_service(u, s->name, s->description); if (svc->loaded.valid) return publish_service(u, svc); @@ -286,7 +286,7 @@ static int publish_source(struct userdata *u, pa_source *s) { assert(u && s); - svc = get_service(u, s->name); + svc = get_service(u, s->name, s->description); if (svc->loaded.valid) return publish_service(u, svc); @@ -309,7 +309,7 @@ static int publish_autoload(struct userdata *u, pa_autoload_entry *s) { assert(u && s); - svc = get_service(u, s->name); + svc = get_service(u, s->name, NULL); if (svc->autoload.valid) return publish_service(u, svc); From 99db0672c7866f6d622a3e342ad8a7b308e1f4dd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 17 Aug 2006 20:01:04 +0000 Subject: [PATCH 1158/1514] make PA_LLIST_HEAD_INIT thread safe git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1258 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/llist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/llist.h b/src/pulsecore/llist.h index c50b8a78e..312794312 100644 --- a/src/pulsecore/llist.h +++ b/src/pulsecore/llist.h @@ -34,7 +34,7 @@ #define PA_LLIST_FIELDS(t) t *next, *prev /* Initialize the list's head */ -#define PA_LLIST_HEAD_INIT(t,item) do { (item) = NULL; } while(0) +#define PA_LLIST_HEAD_INIT(t,item) do { (item) = (t*) NULL; } while(0) /* Initialize a list item */ #define PA_LLIST_INIT(t,item) do { \ From d89066036ba2b6d62a728540baff3c1269515c22 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 17 Aug 2006 20:02:46 +0000 Subject: [PATCH 1159/1514] modify pa_bytes_snprint() to return the string we just wrote to. This should be binary compat with older versions which returned void git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1259 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/sample.c | 4 +++- src/pulse/sample.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pulse/sample.c b/src/pulse/sample.c index 87b2d7a06..7ca418e10 100644 --- a/src/pulse/sample.c +++ b/src/pulse/sample.c @@ -120,7 +120,7 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) { return s; } -void pa_bytes_snprint(char *s, size_t l, unsigned v) { +char* pa_bytes_snprint(char *s, size_t l, unsigned v) { if (v >= ((unsigned) 1024)*1024*1024) snprintf(s, l, "%0.1f GiB", ((double) v)/1024/1024/1024); else if (v >= ((unsigned) 1024)*1024) @@ -129,6 +129,8 @@ void pa_bytes_snprint(char *s, size_t l, unsigned v) { snprintf(s, l, "%0.1f KiB", ((double) v)/1024); else snprintf(s, l, "%u B", (unsigned) v); + + return s; } pa_sample_format_t pa_parse_sample_format(const char *format) { diff --git a/src/pulse/sample.h b/src/pulse/sample.h index 03965a99d..da32fdf0f 100644 --- a/src/pulse/sample.h +++ b/src/pulse/sample.h @@ -182,7 +182,7 @@ pa_sample_format_t pa_parse_sample_format(const char *format); char* pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec); /** Pretty print a byte size value. (i.e. "2.5 MiB") */ -void pa_bytes_snprint(char *s, size_t l, unsigned v); +char* pa_bytes_snprint(char *s, size_t l, unsigned v); PA_C_DECL_END From a847f74ed0fcc268a4dd23ac5b310db6026982a5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 17 Aug 2006 20:03:09 +0000 Subject: [PATCH 1160/1514] add missing #include git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1260 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/random.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pulsecore/random.h b/src/pulsecore/random.h index f809afec4..b2bb39347 100644 --- a/src/pulsecore/random.h +++ b/src/pulsecore/random.h @@ -22,6 +22,8 @@ USA. ***/ +#include + void pa_random_seed(void); void pa_random(void *ret_data, size_t length); From c3df1ceb3827e3ffaef6c6182270ce0c7d325518 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 17 Aug 2006 20:03:38 +0000 Subject: [PATCH 1161/1514] fix a PA_LLIST_HEAD_INIT invocation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1261 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/hook-list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/hook-list.c b/src/pulsecore/hook-list.c index 72b206b2c..91c2598b7 100644 --- a/src/pulsecore/hook-list.c +++ b/src/pulsecore/hook-list.c @@ -24,7 +24,7 @@ void pa_hook_init(pa_hook *hook, void *data) { assert(hook); - PA_LLIST_HEAD_INIT(pa_hook_slots, hook->slots); + PA_LLIST_HEAD_INIT(pa_hook_slot, hook->slots); hook->last = NULL; hook->n_dead = hook->firing = 0; hook->data = data; From 8be0cf60079da8f75933fa128f91efefbd73d5c5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 19:42:14 +0000 Subject: [PATCH 1162/1514] cleanup idxset.[ch] a little: define proper types for the hash/compare funcs, do ptr->int/int->ptr conversions with clean macros git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1262 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/idxset.c | 10 +++++----- src/pulsecore/idxset.h | 10 +++++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c index 23fe0b5a7..ee0137a3d 100644 --- a/src/pulsecore/idxset.c +++ b/src/pulsecore/idxset.c @@ -42,8 +42,8 @@ typedef struct idxset_entry { } idxset_entry; struct pa_idxset { - unsigned (*hash_func) (const void *p); - int (*compare_func)(const void *a, const void *b); + pa_hash_func_t hash_func; + pa_compare_func_t compare_func; unsigned hash_table_size, n_entries; idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail; @@ -65,21 +65,21 @@ int pa_idxset_string_compare_func(const void *a, const void *b) { } unsigned pa_idxset_trivial_hash_func(const void *p) { - return (unsigned) (long) p; + return PA_PTR_TO_UINT(p); } int pa_idxset_trivial_compare_func(const void *a, const void *b) { return a != b; } -pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { +pa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) { pa_idxset *s; s = pa_xnew(pa_idxset, 1); s->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; s->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; s->hash_table_size = 127; - s->hash_table = pa_xmalloc0(sizeof(idxset_entry*)*s->hash_table_size); + s->hash_table = pa_xnew0(idxset_entry*, s->hash_table_size); s->array = NULL; s->array_size = 0; s->index = 0; diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h index 3d0bc75f8..1765e843c 100644 --- a/src/pulsecore/idxset.h +++ b/src/pulsecore/idxset.h @@ -41,10 +41,18 @@ int pa_idxset_trivial_compare_func(const void *a, const void *b); unsigned pa_idxset_string_hash_func(const void *p); int pa_idxset_string_compare_func(const void *a, const void *b); +#define PA_PTR_TO_UINT(p) ((unsigned int) (unsigned long) (p)) +#define PA_UINT_TO_PTR(u) ((void*) (unsigned long) (u)) +#define PA_PTR_TO_UINT32(p) ((uint32_t) PA_PTR_TO_UINT(p)) +#define PA_UINT32_TO_PTR(u) PA_UINT_TO_PTR(u) + +typedef unsigned (*pa_hash_func_t)(const void *p); +typedef int (*pa_compare_func_t)(const void *a, const void *b); + typedef struct pa_idxset pa_idxset; /* Instantiate a new idxset with the specified hash and comparison functions */ -pa_idxset* pa_idxset_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); +pa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func); /* Free the idxset. When the idxset is not empty the specified function is called for every entry contained */ void pa_idxset_free(pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata); From dfa17b9f36f5741be05e144c15a8e89fceae9415 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 19:43:46 +0000 Subject: [PATCH 1163/1514] cleanup hashmap.[ch] a little: use hash/compare func prototypes defined in idxset.h, add pa_hashmpa_{get,steal}_first git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1263 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/hashmap.c | 49 ++++++++++++++++++++++++++++++++--------- src/pulsecore/hashmap.h | 8 ++++++- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c index 6e0e6b028..81a160a69 100644 --- a/src/pulsecore/hashmap.c +++ b/src/pulsecore/hashmap.c @@ -49,22 +49,25 @@ struct pa_hashmap { struct hashmap_entry *first_entry; unsigned n_entries; - unsigned (*hash_func) (const void *p); - int (*compare_func) (const void*a, const void*b); + pa_hash_func_t hash_func; + pa_compare_func_t compare_func; }; -pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)) { +pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) { pa_hashmap *h; - h = pa_xmalloc(sizeof(pa_hashmap)); - h->data = pa_xmalloc0(sizeof(struct hashmap_entry*)*(h->size = BUCKETS)); + + h = pa_xnew(pa_hashmap, 1); + h->data = pa_xnew0(struct hashmap_entry*, h->size = BUCKETS); h->first_entry = NULL; h->n_entries = 0; h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; h->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; + return h; } static void remove(pa_hashmap *h, struct hashmap_entry *e) { + assert(h); assert(e); if (e->next) @@ -102,7 +105,8 @@ void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), v static struct hashmap_entry *get(pa_hashmap *h, unsigned hash, const void *key) { struct hashmap_entry *e; - assert(h && hash < h->size); + assert(h); + assert(hash < h->size); for (e = h->data[hash]; e; e = e->bucket_next) if (h->compare_func(e->key, key) == 0) @@ -121,7 +125,7 @@ int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) { if ((e = get(h, hash, key))) return -1; - e = pa_xmalloc(sizeof(struct hashmap_entry)); + e = pa_xnew(struct hashmap_entry, 1); e->hash = hash; e->key = key; e->value = value; @@ -145,7 +149,8 @@ int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) { void* pa_hashmap_get(pa_hashmap *h, const void *key) { unsigned hash; struct hashmap_entry *e; - assert(h && key); + + assert(h); hash = h->hash_func(key) % h->size; @@ -159,7 +164,8 @@ void* pa_hashmap_remove(pa_hashmap *h, const void *key) { struct hashmap_entry *e; unsigned hash; void *data; - assert(h && key); + + assert(h); hash = h->hash_func(key) % h->size; @@ -176,7 +182,8 @@ unsigned pa_hashmap_size(pa_hashmap *h) { } void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) { - assert(h && state); + assert(h); + assert(state); if (!*state) *state = h->first_entry; @@ -194,3 +201,25 @@ void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) { return ((struct hashmap_entry*) *state)->value; } + +void* pa_hashmap_steal_first(pa_hashmap *h) { + void *data; + + assert(h); + + if (!h->first_entry) + return NULL; + + data = h->first_entry->value; + remove(h, h->first_entry); + return data; +} + +void *pa_hashmap_get_first(pa_hashmap *h) { + assert(h); + + if (!h->first_entry) + return NULL; + + return h->first_entry->value; +} diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h index 3f62adb11..b8a358ec6 100644 --- a/src/pulsecore/hashmap.h +++ b/src/pulsecore/hashmap.h @@ -22,6 +22,8 @@ USA. ***/ +#include + /* Simple Implementation of a hash table. Memory management is the * user's job. It's a good idea to have the key pointer point to a * string in the value data. */ @@ -29,7 +31,7 @@ typedef struct pa_hashmap pa_hashmap; /* Create a new hashmap. Use the specified functions for hashing and comparing objects in the map */ -pa_hashmap *pa_hashmap_new(unsigned (*hash_func) (const void *p), int (*compare_func) (const void*a, const void*b)); +pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func); /* Free the hash table. Calls the specified function for every value in the table. The function may be NULL */ void pa_hashmap_free(pa_hashmap*, void (*free_func)(void *p, void *userdata), void *userdata); @@ -50,4 +52,8 @@ unsigned pa_hashmap_size(pa_hashmap *h); is returned. */ void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void**key); +void *pa_hashmap_steal_first(pa_hashmap *h); + +void *pa_hashmap_get_first(pa_hashmap *h); + #endif From 20d0823e35e62165cc4bf277020814521117a632 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 19:45:19 +0000 Subject: [PATCH 1164/1514] fix a bad type cast git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1264 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pdispatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index db54b2a31..e1653d64b 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -137,7 +137,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_ pd->mainloop = mainloop; pd->callback_table = table; pd->n_commands = entries; - PA_LLIST_HEAD_INIT(pa_reply_info, pd->replies); + PA_LLIST_HEAD_INIT(struct reply_info, pd->replies); pd->drain_callback = NULL; pd->drain_userdata = NULL; pd->creds = NULL; From ff48681aaef919cd2c85e4572928e936397a615c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 19:46:20 +0000 Subject: [PATCH 1165/1514] add abstracted shared memory API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1265 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/shm.c | 224 ++++++++++++++++++++++++++++++++++++++++++++ src/pulsecore/shm.h | 42 +++++++++ 2 files changed, 266 insertions(+) create mode 100644 src/pulsecore/shm.c create mode 100644 src/pulsecore/shm.h diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c new file mode 100644 index 000000000..ad9dc46a4 --- /dev/null +++ b/src/pulsecore/shm.c @@ -0,0 +1,224 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "shm.h" + +#if defined(__linux__) && !defined(MADV_REMOVE) +#define MADV_REMOVE 9 +#endif + +#define MAX_SHM_SIZE (1024*1024*20) + +static char *segment_name(char *fn, size_t l, unsigned id) { + snprintf(fn, l, "/pulse-shm-%u", id); + return fn; +} + +int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { + char fn[32]; + int fd = -1; + + assert(m); + assert(size > 0); + assert(size < MAX_SHM_SIZE); + assert(mode >= 0600); + + if (!shared) { + m->id = 0; + m->size = size; + +#ifdef MAP_ANONYMOUS + if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS, fd, 0)) == MAP_FAILED) { + pa_log(__FILE__": mmap() failed: %s", pa_cstrerror(errno)); + goto fail; + } +#else + m->ptr = pa_xmalloc(m->size); +#endif + + m->do_unlink = 0; + + } else { + pa_random(&m->id, sizeof(m->id)); + segment_name(fn, sizeof(fn), m->id); + + if ((fd = shm_open(fn, O_RDWR|O_CREAT|O_EXCL, mode & 0444)) < 0) { + pa_log(__FILE__": shm_open() failed: %s", pa_cstrerror(errno)); + goto fail; + } + + if (ftruncate(fd, m->size = size) < 0) { + pa_log(__FILE__": ftruncate() failed: %s", pa_cstrerror(errno)); + goto fail; + } + + if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { + pa_log(__FILE__": mmap() failed: %s", pa_cstrerror(errno)); + goto fail; + } + + close(fd); + m->do_unlink = 1; + } + + m->shared = shared; + + return 0; + +fail: + + if (fd >= 0) { + shm_unlink(fn); + close(fd); + } + + return -1; +} + +void pa_shm_free(pa_shm *m) { + char fn[32]; + + assert(m); + assert(m->ptr && m->ptr != MAP_FAILED); + assert(m->size > 0); + +#ifndef MAP_ANONYMOUS + if (!m->shared) + pa_xfree(m->ptr); + else +#endif + + if (munmap(m->ptr, m->size) < 0) + pa_log(__FILE__": munmap() failed: %s", pa_cstrerror(errno)); + + if (m->do_unlink) { + segment_name(fn, sizeof(fn), m->id); + + if (shm_unlink(fn) < 0) + pa_log(__FILE__":shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno)); + } + + memset(m, 0, sizeof(*m)); +} + +void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { + void *ptr; + + assert(m); + assert(m->ptr && m->ptr != MAP_FAILED); + assert(m->size > 0); + assert(m->do_unlink); + assert(offset < m->size); + assert(offset+size < m->size); + + /* You're welcome to implement this as NOOP on systems that don't + * support it */ + + ptr = (uint8_t*) m->ptr + offset; + +#ifdef __linux__ +{ + /* On Linux ptr must be page aligned */ + long psz = sysconf(_SC_PAGESIZE); + unsigned o; + + o = ((unsigned long) ptr) - ((((unsigned long) ptr)/psz) * psz); + + if (o > 0) { + ptr = (uint8_t*) ptr + (psz - o); + size -= psz - o; + } +} +#endif + +#ifdef MADV_REMOVE + if (madvise(ptr, size, MADV_REMOVE) >= 0) + return; +#endif + +#ifdef MADV_FREE + if (madvise(ptr, size, MADV_FREE) >= 0) + return; +#endif + +#ifdef MADV_DONTNEED + madvise(ptr, size, MADV_DONTNEED); +#endif +} + +int pa_shm_attach_ro(pa_shm *m, unsigned id) { + char fn[32]; + int fd = -1; + struct stat st; + + assert(m); + + segment_name(fn, sizeof(fn), m->id = id); + + if ((fd = shm_open(fn, O_RDONLY, 0)) < 0) { + pa_log(__FILE__": shm_open() failed: %s", pa_cstrerror(errno)); + goto fail; + } + + if (fstat(fd, &st) < 0) { + pa_log(__FILE__": fstat() failed: %s", pa_cstrerror(errno)); + goto fail; + } + + if (st.st_size <= 0 || st.st_size > MAX_SHM_SIZE) { + pa_log(__FILE__": Invalid shared memory segment size"); + goto fail; + } + + m->size = st.st_size; + + if ((m->ptr = mmap(NULL, m->size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + pa_log(__FILE__": mmap() failed: %s", pa_cstrerror(errno)); + goto fail; + } + + m->do_unlink = 0; + m->shared = 1; + + close(fd); + + return 0; + +fail: + if (fd >= 0) + close(fd); + + return -1; +} diff --git a/src/pulsecore/shm.h b/src/pulsecore/shm.h new file mode 100644 index 000000000..ea72403a2 --- /dev/null +++ b/src/pulsecore/shm.h @@ -0,0 +1,42 @@ +#ifndef foopulseshmhfoo +#define foopulseshmhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +typedef struct pa_shm { + unsigned id; + void *ptr; + size_t size; + int do_unlink; + int shared; +} pa_shm; + +int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode); +int pa_shm_attach_ro(pa_shm *m, unsigned id); + +void pa_shm_punch(pa_shm *m, size_t offset, size_t size); + +void pa_shm_free(pa_shm *m); + +#endif From 0e436a6926af56f37a74a03bb5e143e078ca0d55 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 19:55:18 +0000 Subject: [PATCH 1166/1514] Rework memory management to allow shared memory data transfer. The central idea is to allocate all audio memory blocks from a per-process memory pool which is available as read-only SHM segment to other local processes. Then, instead of writing the actual audio data to the socket just write references to this shared memory pool. To work optimally all memory blocks should now be of type PA_MEMBLOCK_POOL or PA_MEMBLOCK_POOL_EXTERNAL. The function pa_memblock_new() now generates memory blocks of this type by default. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1266 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 2 +- src/modules/module-alsa-sink.c | 2 +- src/modules/module-alsa-source.c | 2 +- src/modules/module-combine.c | 3 +- src/modules/module-jack-source.c | 2 +- src/modules/module-oss-mmap.c | 6 +- src/modules/module-oss.c | 4 +- src/modules/module-pipe-source.c | 2 +- src/modules/module-sine.c | 2 +- src/modules/module-tunnel.c | 2 +- src/modules/rtp/module-rtp-recv.c | 11 +- src/modules/rtp/module-rtp-send.c | 3 +- src/modules/rtp/rtp.c | 4 +- src/modules/rtp/rtp.h | 2 +- src/pulse/context.c | 8 +- src/pulse/internal.h | 2 +- src/pulse/stream.c | 7 +- src/pulsecore/cli-command.c | 40 +- src/pulsecore/core-scache.c | 4 +- src/pulsecore/core.c | 6 +- src/pulsecore/core.h | 4 +- src/pulsecore/mcalign.c | 6 +- src/pulsecore/mcalign.h | 2 +- src/pulsecore/memblock.c | 771 ++++++++++++++++++++++++++---- src/pulsecore/memblock.h | 106 ++-- src/pulsecore/memblockq.c | 7 +- src/pulsecore/memblockq.h | 3 +- src/pulsecore/memchunk.c | 9 +- src/pulsecore/memchunk.h | 2 +- src/pulsecore/protocol-esound.c | 10 +- src/pulsecore/protocol-native.c | 25 +- src/pulsecore/protocol-simple.c | 8 +- src/pulsecore/pstream.c | 402 +++++++++++++--- src/pulsecore/pstream.h | 4 +- src/pulsecore/resampler.c | 21 +- src/pulsecore/resampler.h | 12 +- src/pulsecore/sample-util.c | 7 +- src/pulsecore/sample-util.h | 2 +- src/pulsecore/sink-input.c | 12 +- src/pulsecore/sink.c | 6 +- src/pulsecore/sound-file-stream.c | 2 +- src/pulsecore/sound-file.c | 4 +- src/pulsecore/sound-file.h | 2 +- src/pulsecore/source-output.c | 4 +- src/pulsecore/source.c | 2 +- 45 files changed, 1235 insertions(+), 312 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 38d465f80..aada0ad79 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -559,7 +559,7 @@ int main(int argc, char *argv[]) { mainloop = pa_mainloop_new(); assert(mainloop); - c = pa_core_new(pa_mainloop_get_api(mainloop)); + c = pa_core_new(pa_mainloop_get_api(mainloop), 1); assert(c); c->is_system_instance = !!conf->system_instance; diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 8da3d2360..0cebd50f1 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -492,7 +492,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log_info(__FILE__": using %u fragments of size %lu bytes.", periods, (long unsigned)u->fragment_size); - u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size, c->memblock_stat); + u->silence.memblock = pa_memblock_new(c->mempool, u->silence.length = u->fragment_size); assert(u->silence.memblock); pa_silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 4a8678c9c..c3979df17 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -151,7 +151,7 @@ static void do_read(struct userdata *u) { size_t l; if (!u->memchunk.memblock) { - u->memchunk.memblock = pa_memblock_new(u->memchunk.length = u->fragment_size, u->source->core->memblock_stat); + u->memchunk.memblock = pa_memblock_new(u->source->core->mempool, u->memchunk.length = u->fragment_size); u->memchunk.index = 0; } diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 008fe6e74..5243975b5 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -235,8 +235,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample pa_frame_size(&u->sink->sample_spec), 1, 0, - NULL, - sink->core->memblock_stat); + NULL); snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1); diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 583f3b8e9..8e659198d 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -137,7 +137,7 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_ fs = pa_frame_size(&u->source->sample_spec); - chunk.memblock = pa_memblock_new(chunk.length = u->frames_posted * fs, u->core->memblock_stat); + chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length = u->frames_posted * fs); chunk.index = 0; for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) { diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index c783a2f1f..75ab9a9e9 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -162,10 +162,10 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed( + u->core->mempool, (uint8_t*) u->out_mmap+u->out_fragment_size*u->out_current, u->out_fragment_size, - 1, - u->core->memblock_stat); + 1); assert(chunk.memblock); chunk.length = chunk.memblock->length; chunk.index = 0; @@ -210,7 +210,7 @@ static void in_post_memblocks(struct userdata *u, unsigned n) { pa_memchunk chunk; if (!u->in_memblocks[u->in_current]) { - chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed((uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, 1, u->core->memblock_stat); + chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->core->mempool, (uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, 1); chunk.length = chunk.memblock->length; chunk.index = 0; diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index ce11ee025..b9b80e725 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -217,7 +217,7 @@ static void do_read(struct userdata *u) { } do { - memchunk.memblock = pa_memblock_new(l, u->core->memblock_stat); + memchunk.memblock = pa_memblock_new(u->core->mempool, l); assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); @@ -503,7 +503,7 @@ int pa__init(pa_core *c, pa_module*m) { u->out_fragment_size = out_frag_size; u->in_fragment_size = in_frag_size; - u->silence.memblock = pa_memblock_new(u->silence.length = u->out_fragment_size, u->core->memblock_stat); + u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length = u->out_fragment_size); assert(u->silence.memblock); pa_silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index 5caa60a3e..43a8dab55 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -91,7 +91,7 @@ static void do_read(struct userdata *u) { pa_module_set_used(u->module, pa_idxset_size(u->source->outputs)); if (!u->chunk.memblock) { - u->chunk.memblock = pa_memblock_new(1024, u->core->memblock_stat); + u->chunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF); u->chunk.index = chunk.length = 0; } diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index 5ceddce08..89c3c6093 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -139,7 +139,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - u->memblock = pa_memblock_new(pa_bytes_per_second(&ss), c->memblock_stat); + u->memblock = pa_memblock_new(c->mempool, pa_bytes_per_second(&ss)); calc_sine(u->memblock->data, u->memblock->length, frequency); snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 9bb11c094..53bffd3b1 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -651,7 +651,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata return; } - u->pstream = pa_pstream_new(u->core->mainloop, io, u->core->memblock_stat); + u->pstream = pa_pstream_new(u->core->mainloop, io, u->core->mempool); u->pdispatch = pa_pdispatch_new(u->core->mainloop, command_table, PA_COMMAND_MAX); pa_pstream_set_die_callback(u->pstream, pstream_die_callback, u); diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index df6f8c118..5d3f3e279 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -150,7 +150,7 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event assert(fd == s->rtp_context.fd); assert(flags == PA_IO_EVENT_INPUT); - if (pa_rtp_recv(&s->rtp_context, &chunk, s->userdata->core->memblock_stat) < 0) + if (pa_rtp_recv(&s->rtp_context, &chunk, s->userdata->core->mempool) < 0) return; if (s->sdp_info.payload != s->rtp_context.payload) { @@ -312,10 +312,10 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in s->sink_input->kill = sink_input_kill; s->sink_input->get_latency = sink_input_get_latency; - silence = pa_silence_memblock_new(&s->sink_input->sample_spec, + silence = pa_silence_memblock_new(s->userdata->core->mempool, + &s->sink_input->sample_spec, (pa_bytes_per_second(&s->sink_input->sample_spec)/128/pa_frame_size(&s->sink_input->sample_spec))* - pa_frame_size(&s->sink_input->sample_spec), - s->userdata->core->memblock_stat); + pa_frame_size(&s->sink_input->sample_spec)); s->memblockq = pa_memblockq_new( 0, @@ -324,8 +324,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_frame_size(&s->sink_input->sample_spec), pa_bytes_per_second(&s->sink_input->sample_spec)/10+1, 0, - silence, - u->core->memblock_stat); + silence); pa_memblock_unref(silence); diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 759aa8197..1b85c840b 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -297,8 +297,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_frame_size(&ss), 1, 0, - NULL, - c->memblock_stat); + NULL); u->mtu = mtu; diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index ee037d421..8e77c60a6 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -149,7 +149,7 @@ pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame return c; } -int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_memblock_stat *st) { +int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { int size; struct msghdr m; struct iovec iov; @@ -170,7 +170,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_memblock_stat *st) { if (!size) return 0; - chunk->memblock = pa_memblock_new(size, st); + chunk->memblock = pa_memblock_new(pool, size); iov.iov_base = chunk->memblock->data; iov.iov_len = size; diff --git a/src/modules/rtp/rtp.h b/src/modules/rtp/rtp.h index 35fbbd357..123602b23 100644 --- a/src/modules/rtp/rtp.h +++ b/src/modules/rtp/rtp.h @@ -41,7 +41,7 @@ pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssr int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q); pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size); -int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_memblock_stat *st); +int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool); void pa_rtp_context_destroy(pa_rtp_context *c); diff --git a/src/pulse/context.c b/src/pulse/context.c index 34f517f0b..b35305424 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -128,7 +128,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { c->subscribe_callback = NULL; c->subscribe_userdata = NULL; - c->memblock_stat = pa_memblock_stat_new(); + c->mempool = pa_mempool_new(1); c->local = -1; c->server_list = NULL; c->server = NULL; @@ -177,7 +177,7 @@ static void context_free(pa_context *c) { if (c->playback_streams) pa_dynarray_free(c->playback_streams, NULL, NULL); - pa_memblock_stat_unref(c->memblock_stat); + pa_mempool_free(c->mempool); if (c->conf) pa_client_conf_free(c->conf); @@ -407,7 +407,9 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_context_ref(c); assert(!c->pstream); - c->pstream = pa_pstream_new(c->mainloop, io, c->memblock_stat); + c->pstream = pa_pstream_new(c->mainloop, io, c->mempool); + + pa_pstream_use_shm(c->pstream, 1); pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 96028d832..afcfaeff5 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -69,7 +69,7 @@ struct pa_context { pa_context_subscribe_cb_t subscribe_callback; void *subscribe_userdata; - pa_memblock_stat *memblock_stat; + pa_mempool *mempool; int local; int do_autospawn; diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 677df009d..180cd096d 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -437,8 +437,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED pa_frame_size(&s->sample_spec), 1, 0, - NULL, - s->context->memblock_stat); + NULL); } s->channel_valid = 1; @@ -604,9 +603,9 @@ int pa_stream_write( return 0; if (free_cb) - chunk.memblock = pa_memblock_new_user((void*) data, length, free_cb, 1, s->context->memblock_stat); + chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) data, length, free_cb, 1); else { - chunk.memblock = pa_memblock_new(length, s->context->memblock_stat); + chunk.memblock = pa_memblock_new(s->context->mempool, length); memcpy(chunk.memblock->data, data, length); } diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index f74258d3c..811b96d2a 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -100,6 +100,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); /* A method table for all available commands */ @@ -144,6 +145,7 @@ static const struct command commands[] = { { "list-props", pa_cli_command_list_props, NULL, 1}, { "move-sink-input", pa_cli_command_move_sink_input, "Move sink input to another sink (args: index, sink)", 3}, { "move-source-output", pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3}, + { "vacuum", pa_cli_command_vacuum, NULL, 1}, { NULL, NULL, NULL, 0 } }; @@ -239,23 +241,32 @@ static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char s[256]; + const pa_mempool_stat *stat; assert(c && t); - pa_bytes_snprint(s, sizeof(s), c->memblock_stat->total_size); + stat = pa_mempool_get_stat(c->mempool); + pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n", - c->memblock_stat->total, - s); + stat->n_allocated, + pa_bytes_snprint(s, sizeof(s), stat->allocated_size)); - pa_bytes_snprint(s, sizeof(s), c->memblock_stat->allocated_size); pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n", - c->memblock_stat->allocated, - s); + stat->n_accumulated, + pa_bytes_snprint(s, sizeof(s), stat->accumulated_size)); - pa_bytes_snprint(s, sizeof(s), pa_scache_total_size(c)); - pa_strbuf_printf(buf, "Total sample cache size: %s.\n", s); + pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n", + stat->n_imported, + pa_bytes_snprint(s, sizeof(s), stat->imported_size)); - pa_sample_spec_snprint(s, sizeof(s), &c->default_sample_spec); - pa_strbuf_printf(buf, "Default sample spec: %s\n", s); + pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n", + stat->n_exported, + pa_bytes_snprint(s, sizeof(s), stat->exported_size)); + + pa_strbuf_printf(buf, "Total sample cache size: %s.\n", + pa_bytes_snprint(s, sizeof(s), pa_scache_total_size(c))); + + pa_strbuf_printf(buf, "Default sample spec: %s\n", + pa_sample_spec_snprint(s, sizeof(s), &c->default_sample_spec)); pa_strbuf_printf(buf, "Default sink name: %s\n" "Default source name: %s\n", @@ -731,6 +742,15 @@ static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf return 0; } +static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { + assert(c); + assert(t); + + pa_mempool_vacuum(c->mempool); + + return 0; +} + static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n, *k; pa_sink_input *si; diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c index 377dd569f..ca2408fe7 100644 --- a/src/pulsecore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -176,7 +176,7 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3 filename = buf; #endif - if (pa_sound_file_load(filename, &ss, &map, &chunk, c->memblock_stat) < 0) + if (pa_sound_file_load(c->mempool, filename, &ss, &map, &chunk) < 0) return -1; r = pa_scache_add_item(c, name, &ss, &map, &chunk, idx); @@ -261,7 +261,7 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t return -1; if (e->lazy && !e->memchunk.memblock) { - if (pa_sound_file_load(e->filename, &e->sample_spec, &e->channel_map, &e->memchunk, c->memblock_stat) < 0) + if (pa_sound_file_load(c->mempool, e->filename, &e->sample_spec, &e->channel_map, &e->memchunk) < 0) return -1; pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 7f2f0f60d..5fdeab569 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -44,7 +44,7 @@ #include "core.h" -pa_core* pa_core_new(pa_mainloop_api *m) { +pa_core* pa_core_new(pa_mainloop_api *m, int shared) { pa_core* c; c = pa_xnew(pa_core, 1); @@ -78,7 +78,7 @@ pa_core* pa_core_new(pa_mainloop_api *m) { PA_LLIST_HEAD_INIT(pa_subscription_event, c->subscription_event_queue); c->subscription_event_last = NULL; - c->memblock_stat = pa_memblock_stat_new(); + c->mempool = pa_mempool_new(shared); c->disallow_module_loading = 0; @@ -139,7 +139,7 @@ void pa_core_free(pa_core *c) { pa_xfree(c->default_source_name); pa_xfree(c->default_sink_name); - pa_memblock_stat_unref(c->memblock_stat); + pa_mempool_free(c->mempool); pa_property_cleanup(c); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index f9fa386e8..3a34d297a 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -67,7 +67,7 @@ struct pa_core { PA_LLIST_HEAD(pa_subscription_event, subscription_event_queue); pa_subscription_event *subscription_event_last; - pa_memblock_stat *memblock_stat; + pa_mempool *mempool; int disallow_module_loading, running_as_daemon; int exit_idle_time, module_idle_time, scache_idle_time; @@ -88,7 +88,7 @@ struct pa_core { hook_source_disconnect; }; -pa_core* pa_core_new(pa_mainloop_api *m); +pa_core* pa_core_new(pa_mainloop_api *m, int shared); void pa_core_free(pa_core*c); /* Check whether noone is connected to this core */ diff --git a/src/pulsecore/mcalign.c b/src/pulsecore/mcalign.c index 8283a7a0b..9ede610d7 100644 --- a/src/pulsecore/mcalign.c +++ b/src/pulsecore/mcalign.c @@ -35,10 +35,9 @@ struct pa_mcalign { size_t base; pa_memchunk leftover, current; - pa_memblock_stat *memblock_stat; }; -pa_mcalign *pa_mcalign_new(size_t base, pa_memblock_stat *s) { +pa_mcalign *pa_mcalign_new(size_t base) { pa_mcalign *m; assert(base); @@ -47,7 +46,6 @@ pa_mcalign *pa_mcalign_new(size_t base, pa_memblock_stat *s) { m->base = base; pa_memchunk_reset(&m->leftover); pa_memchunk_reset(&m->current); - m->memblock_stat = s; return m; } @@ -100,7 +98,7 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { l = c->length; /* Can we use the current block? */ - pa_memchunk_make_writable(&m->leftover, m->memblock_stat, m->base); + pa_memchunk_make_writable(&m->leftover, m->base); memcpy((uint8_t*) m->leftover.memblock->data + m->leftover.index + m->leftover.length, (uint8_t*) c->memblock->data + c->index, l); m->leftover.length += l; diff --git a/src/pulsecore/mcalign.h b/src/pulsecore/mcalign.h index 80e374996..94e99e212 100644 --- a/src/pulsecore/mcalign.h +++ b/src/pulsecore/mcalign.h @@ -63,7 +63,7 @@ typedef struct pa_mcalign pa_mcalign; -pa_mcalign *pa_mcalign_new(size_t base, pa_memblock_stat *s); +pa_mcalign *pa_mcalign_new(size_t base); void pa_mcalign_free(pa_mcalign *m); /* Push a new memchunk into the aligner. The caller of this routine diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 36de17fb3..4ce1b7c1a 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -27,86 +27,271 @@ #include #include #include +#include #include +#include +#include +#include + #include "memblock.h" -static void stat_add(pa_memblock*m, pa_memblock_stat *s) { - assert(m); +#define PA_MEMPOOL_SLOTS_MAX 128 +#define PA_MEMPOOL_SLOT_SIZE (16*1024) - if (!s) { - m->stat = NULL; - return; +#define PA_MEMEXPORT_SLOTS_MAX 128 + +#define PA_MEMIMPORT_SLOTS_MAX 128 +#define PA_MEMIMPORT_SEGMENTS_MAX 16 + +struct pa_memimport_segment { + pa_memimport *import; + pa_shm memory; + unsigned n_blocks; +}; + +struct pa_memimport { + pa_mempool *pool; + pa_hashmap *segments; + pa_hashmap *blocks; + + /* Called whenever an imported memory block is no longer + * needed. */ + pa_memimport_release_cb_t release_cb; + void *userdata; + + PA_LLIST_FIELDS(pa_memimport); +}; + +struct memexport_slot { + PA_LLIST_FIELDS(struct memexport_slot); + pa_memblock *block; +}; + +struct pa_memexport { + pa_mempool *pool; + + struct memexport_slot slots[PA_MEMEXPORT_SLOTS_MAX]; + PA_LLIST_HEAD(struct memexport_slot, free_slots); + PA_LLIST_HEAD(struct memexport_slot, used_slots); + unsigned n_init; + + /* Called whenever a client from which we imported a memory block + which we in turn exported to another client dies and we need to + revoke the memory block accordingly */ + pa_memexport_revoke_cb_t revoke_cb; + void *userdata; + + PA_LLIST_FIELDS(pa_memexport); +}; + +struct mempool_slot { + PA_LLIST_FIELDS(struct mempool_slot); + /* the actual data follows immediately hereafter */ +}; + +struct pa_mempool { + pa_shm memory; + size_t block_size; + unsigned n_blocks, n_init; + + PA_LLIST_HEAD(pa_memimport, imports); + PA_LLIST_HEAD(pa_memexport, exports); + + /* A list of free slots that may be reused */ + PA_LLIST_HEAD(struct mempool_slot, free_slots); + PA_LLIST_HEAD(struct mempool_slot, used_slots); + + pa_mempool_stat stat; +}; + +static void segment_detach(pa_memimport_segment *seg); + +static void stat_add(pa_memblock*b) { + assert(b); + assert(b->pool); + + b->pool->stat.n_allocated ++; + b->pool->stat.n_accumulated ++; + b->pool->stat.allocated_size += b->length; + b->pool->stat.accumulated_size += b->length; + + if (b->type == PA_MEMBLOCK_IMPORTED) { + b->pool->stat.n_imported++; + b->pool->stat.imported_size += b->length; + } +} + +static void stat_remove(pa_memblock *b) { + assert(b); + assert(b->pool); + + assert(b->pool->stat.n_allocated > 0); + assert(b->pool->stat.allocated_size >= b->length); + + b->pool->stat.n_allocated --; + b->pool->stat.allocated_size -= b->length; + + if (b->type == PA_MEMBLOCK_IMPORTED) { + assert(b->pool->stat.n_imported > 0); + assert(b->pool->stat.imported_size >= b->length); + + b->pool->stat.n_imported --; + b->pool->stat.imported_size -= b->length; + } +} + +static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length); + +pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) { + pa_memblock *b; + + assert(p); + assert(length > 0); + + if (!(b = pa_memblock_new_pool(p, length))) + b = memblock_new_appended(p, length); + + return b; +} + +static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) { + pa_memblock *b; + + assert(p); + assert(length > 0); + + b = pa_xmalloc(sizeof(pa_memblock) + length); + b->type = PA_MEMBLOCK_APPENDED; + b->read_only = 0; + b->ref = 1; + b->length = length; + b->data = (uint8_t*) b + sizeof(pa_memblock); + b->pool = p; + + stat_add(b); + return b; +} + +static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { + struct mempool_slot *slot; + assert(p); + + if (p->free_slots) { + slot = p->free_slots; + PA_LLIST_REMOVE(struct mempool_slot, p->free_slots, slot); + } else if (p->n_init < p->n_blocks) + slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * p->n_init++)); + else { + pa_log_debug(__FILE__": Pool full"); + p->stat.n_pool_full++; + return NULL; } - m->stat = pa_memblock_stat_ref(s); - s->total++; - s->allocated++; - s->total_size += m->length; - s->allocated_size += m->length; + PA_LLIST_PREPEND(struct mempool_slot, p->used_slots, slot); + return slot; } -static void stat_remove(pa_memblock *m) { - assert(m); +static void* mempool_slot_data(struct mempool_slot *slot) { + assert(slot); - if (!m->stat) - return; - - m->stat->total--; - m->stat->total_size -= m->length; - - pa_memblock_stat_unref(m->stat); - m->stat = NULL; + return (uint8_t*) slot + sizeof(struct mempool_slot); } -pa_memblock *pa_memblock_new(size_t length, pa_memblock_stat*s) { - pa_memblock *b = pa_xmalloc(sizeof(pa_memblock)+length); - b->type = PA_MEMBLOCK_APPENDED; - b->ref = 1; +static unsigned mempool_slot_idx(pa_mempool *p, void *ptr) { + assert(p); + assert((uint8_t*) ptr >= (uint8_t*) p->memory.ptr); + assert((uint8_t*) ptr < (uint8_t*) p->memory.ptr + p->memory.size); + + return ((uint8_t*) ptr - (uint8_t*) p->memory.ptr) / p->block_size; +} + +static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) { + unsigned idx; + + if ((idx = mempool_slot_idx(p, ptr)) == (unsigned) -1) + return NULL; + + return (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (idx * p->block_size)); +} + +pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { + pa_memblock *b = NULL; + struct mempool_slot *slot; + + assert(p); + assert(length > 0); + + if (p->block_size - sizeof(struct mempool_slot) >= sizeof(pa_memblock) + length) { + + if (!(slot = mempool_allocate_slot(p))) + return NULL; + + b = mempool_slot_data(slot); + b->type = PA_MEMBLOCK_POOL; + b->data = (uint8_t*) b + sizeof(pa_memblock); + + } else if (p->block_size - sizeof(struct mempool_slot) >= length) { + + if (!(slot = mempool_allocate_slot(p))) + return NULL; + + b = pa_xnew(pa_memblock, 1); + b->type = PA_MEMBLOCK_POOL_EXTERNAL; + b->data = mempool_slot_data(slot); + } else { + pa_log_debug(__FILE__": Memory block to large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot)); + p->stat.n_too_large_for_pool++; + return NULL; + } + b->length = length; - b->data = b+1; - b->free_cb = NULL; b->read_only = 0; - stat_add(b, s); - return b; -} - -pa_memblock *pa_memblock_new_dynamic(void *d, size_t length, pa_memblock_stat*s) { - pa_memblock *b = pa_xmalloc(sizeof(pa_memblock)); - b->type = PA_MEMBLOCK_DYNAMIC; b->ref = 1; - b->length = length; - b->data = d; - b->free_cb = NULL; - b->read_only = 0; - stat_add(b, s); + b->pool = p; + + stat_add(b); return b; } -pa_memblock *pa_memblock_new_fixed(void *d, size_t length, int read_only, pa_memblock_stat*s) { - pa_memblock *b = pa_xmalloc(sizeof(pa_memblock)); - b->type = PA_MEMBLOCK_FIXED; - b->ref = 1; - b->length = length; - b->data = d; - b->free_cb = NULL; - b->read_only = read_only; - stat_add(b, s); - return b; -} - -pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p), int read_only, pa_memblock_stat*s) { +pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int read_only) { pa_memblock *b; - assert(d && length && free_cb); - b = pa_xmalloc(sizeof(pa_memblock)); - b->type = PA_MEMBLOCK_USER; + + assert(p); + assert(d); + assert(length > 0); + + b = pa_xnew(pa_memblock, 1); + b->type = PA_MEMBLOCK_FIXED; + b->read_only = read_only; b->ref = 1; b->length = length; b->data = d; - b->free_cb = free_cb; + b->pool = p; + + stat_add(b); + return b; +} + +pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (*free_cb)(void *p), int read_only) { + pa_memblock *b; + + assert(p); + assert(d); + assert(length > 0); + assert(free_cb); + + b = pa_xnew(pa_memblock, 1); + b->type = PA_MEMBLOCK_USER; b->read_only = read_only; - stat_add(b, s); + b->ref = 1; + b->length = length; + b->data = d; + b->per_type.user.free_cb = free_cb; + b->pool = p; + + stat_add(b); return b; } @@ -122,52 +307,458 @@ void pa_memblock_unref(pa_memblock*b) { assert(b); assert(b->ref >= 1); - if ((--(b->ref)) == 0) { - stat_remove(b); + if ((--(b->ref)) > 0) + return; + + stat_remove(b); - if (b->type == PA_MEMBLOCK_USER) { - assert(b->free_cb); - b->free_cb(b->data); - } else if (b->type == PA_MEMBLOCK_DYNAMIC) - pa_xfree(b->data); + switch (b->type) { + case PA_MEMBLOCK_USER : + assert(b->per_type.user.free_cb); + b->per_type.user.free_cb(b->data); - pa_xfree(b); + /* Fall through */ + + case PA_MEMBLOCK_FIXED: + case PA_MEMBLOCK_APPENDED : + pa_xfree(b); + break; + + case PA_MEMBLOCK_IMPORTED : { + pa_memimport_segment *segment; + + segment = b->per_type.imported.segment; + assert(segment); + assert(segment->import); + + pa_hashmap_remove(segment->import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); + segment->import->release_cb(segment->import, b->per_type.imported.id, segment->import->userdata); + + if (-- segment->n_blocks <= 0) + segment_detach(segment); + + pa_xfree(b); + break; + } + + case PA_MEMBLOCK_POOL_EXTERNAL: + case PA_MEMBLOCK_POOL: { + struct mempool_slot *slot; + + slot = mempool_slot_by_ptr(b->pool, b->data); + assert(slot); + + PA_LLIST_REMOVE(struct mempool_slot, b->pool->used_slots, slot); + PA_LLIST_PREPEND(struct mempool_slot, b->pool->free_slots, slot); + + if (b->type == PA_MEMBLOCK_POOL_EXTERNAL) + pa_xfree(b); + } } } +static void memblock_make_local(pa_memblock *b) { + assert(b); + + if (b->length <= b->pool->block_size - sizeof(struct mempool_slot)) { + struct mempool_slot *slot; + + if ((slot = mempool_allocate_slot(b->pool))) { + void *new_data; + /* We can move it into a local pool, perfect! */ + + b->type = PA_MEMBLOCK_POOL_EXTERNAL; + b->read_only = 0; + + new_data = mempool_slot_data(slot); + memcpy(new_data, b->data, b->length); + b->data = new_data; + return; + } + } + + /* Humm, not enough space in the pool, so lets allocate the memory with malloc() */ + b->type = PA_MEMBLOCK_USER; + b->per_type.user.free_cb = pa_xfree; + b->read_only = 0; + b->data = pa_xmemdup(b->data, b->length); +} + void pa_memblock_unref_fixed(pa_memblock *b) { - assert(b && b->ref >= 1 && b->type == PA_MEMBLOCK_FIXED); + assert(b); + assert(b->ref >= 1); + assert(b->type == PA_MEMBLOCK_FIXED); - if (b->ref == 1) + if (b->ref > 1) + memblock_make_local(b); + + pa_memblock_unref(b); +} + +static void memblock_replace_import(pa_memblock *b) { + pa_memimport_segment *seg; + + assert(b); + assert(b->type == PA_MEMBLOCK_IMPORTED); + + assert(b->pool->stat.n_imported > 0); + assert(b->pool->stat.imported_size >= b->length); + b->pool->stat.n_imported --; + b->pool->stat.imported_size -= b->length; + + seg = b->per_type.imported.segment; + assert(seg); + assert(seg->import); + + pa_hashmap_remove( + seg->import->blocks, + PA_UINT32_TO_PTR(b->per_type.imported.id)); + + memblock_make_local(b); + + if (-- seg->n_blocks <= 0) + segment_detach(seg); +} + +pa_mempool* pa_mempool_new(int shared) { + size_t ps; + pa_mempool *p; + + p = pa_xnew(pa_mempool, 1); + + ps = (size_t) sysconf(_SC_PAGESIZE); + + p->block_size = (PA_MEMPOOL_SLOT_SIZE/ps)*ps; + + if (p->block_size < ps) + p->block_size = ps; + + p->n_blocks = PA_MEMPOOL_SLOTS_MAX; + + assert(p->block_size > sizeof(struct mempool_slot)); + + if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) { + pa_xfree(p); + return NULL; + } + + p->n_init = 0; + + PA_LLIST_HEAD_INIT(pa_memimport, p->imports); + PA_LLIST_HEAD_INIT(pa_memexport, p->exports); + PA_LLIST_HEAD_INIT(struct mempool_slot, p->free_slots); + PA_LLIST_HEAD_INIT(struct mempool_slot, p->used_slots); + + memset(&p->stat, 0, sizeof(p->stat)); + + return p; +} + +void pa_mempool_free(pa_mempool *p) { + assert(p); + + while (p->imports) + pa_memimport_free(p->imports); + + while (p->exports) + pa_memexport_free(p->exports); + + if (p->stat.n_allocated > 0) + pa_log_warn(__FILE__": WARNING! Memory pool destroyed but not all memory blocks freed!"); + + pa_shm_free(&p->memory); + pa_xfree(p); +} + +const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p) { + assert(p); + + return &p->stat; +} + +void pa_mempool_vacuum(pa_mempool *p) { + struct mempool_slot *slot; + + assert(p); + + for (slot = p->free_slots; slot; slot = slot->next) { + pa_shm_punch(&p->memory, (uint8_t*) slot + sizeof(struct mempool_slot) - (uint8_t*) p->memory.ptr, p->block_size - sizeof(struct mempool_slot)); + } +} + +int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) { + assert(p); + + if (!p->memory.shared) + return -1; + + *id = p->memory.id; + + return 0; +} + +/* For recieving blocks from other nodes */ +pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void *userdata) { + pa_memimport *i; + + assert(p); + assert(cb); + + i = pa_xnew(pa_memimport, 1); + i->pool = p; + i->segments = pa_hashmap_new(NULL, NULL); + i->blocks = pa_hashmap_new(NULL, NULL); + i->release_cb = cb; + i->userdata = userdata; + + PA_LLIST_PREPEND(pa_memimport, p->imports, i); + return i; +} + +static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i); + +static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) { + pa_memimport_segment* seg; + + if (pa_hashmap_size(i->segments) >= PA_MEMIMPORT_SEGMENTS_MAX) + return NULL; + + seg = pa_xnew(pa_memimport_segment, 1); + + if (pa_shm_attach_ro(&seg->memory, shm_id) < 0) { + pa_xfree(seg); + return NULL; + } + + seg->import = i; + seg->n_blocks = 0; + + pa_hashmap_put(i->segments, PA_UINT32_TO_PTR(shm_id), seg); + return seg; +} + +static void segment_detach(pa_memimport_segment *seg) { + assert(seg); + + pa_hashmap_remove(seg->import->segments, PA_UINT32_TO_PTR(seg->memory.id)); + pa_shm_free(&seg->memory); + pa_xfree(seg); +} + +void pa_memimport_free(pa_memimport *i) { + pa_memexport *e; + pa_memblock *b; + + assert(i); + + /* If we've exported this block further we need to revoke that export */ + for (e = i->pool->exports; e; e = e->next) + memexport_revoke_blocks(e, i); + + while ((b = pa_hashmap_get_first(i->blocks))) + memblock_replace_import(b); + + assert(pa_hashmap_size(i->segments) == 0); + + pa_hashmap_free(i->blocks, NULL, NULL); + pa_hashmap_free(i->segments, NULL, NULL); + + PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i); + pa_xfree(i); +} + +pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_id, size_t offset, size_t size) { + pa_memblock *b; + pa_memimport_segment *seg; + + assert(i); + + if (pa_hashmap_size(i->blocks) >= PA_MEMIMPORT_SLOTS_MAX) + return NULL; + + if (!(seg = pa_hashmap_get(i->segments, PA_UINT32_TO_PTR(shm_id)))) + if (!(seg = segment_attach(i, shm_id))) + return NULL; + + if (offset+size > seg->memory.size) + return NULL; + + b = pa_xnew(pa_memblock, 1); + b->type = PA_MEMBLOCK_IMPORTED; + b->read_only = 1; + b->ref = 1; + b->length = size; + b->data = (uint8_t*) seg->memory.ptr + offset; + b->pool = i->pool; + b->per_type.imported.id = block_id; + b->per_type.imported.segment = seg; + + pa_hashmap_put(i->blocks, PA_UINT32_TO_PTR(block_id), b); + + seg->n_blocks++; + + stat_add(b); + + return b; +} + +int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) { + pa_memblock *b; + assert(i); + + if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id)))) + return -1; + + memblock_replace_import(b); + return 0; +} + +/* For sending blocks to other nodes */ +pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void *userdata) { + pa_memexport *e; + + assert(p); + assert(cb); + + if (!p->memory.shared) + return NULL; + + e = pa_xnew(pa_memexport, 1); + e->pool = p; + PA_LLIST_HEAD_INIT(struct memexport_slot, e->free_slots); + PA_LLIST_HEAD_INIT(struct memexport_slot, e->used_slots); + e->n_init = 0; + e->revoke_cb = cb; + e->userdata = userdata; + + PA_LLIST_PREPEND(pa_memexport, p->exports, e); + return e; +} + +void pa_memexport_free(pa_memexport *e) { + assert(e); + + while (e->used_slots) + pa_memexport_process_release(e, e->used_slots - e->slots); + + PA_LLIST_REMOVE(pa_memexport, e->pool->exports, e); + pa_xfree(e); +} + +int pa_memexport_process_release(pa_memexport *e, uint32_t id) { + assert(e); + + if (id >= e->n_init) + return -1; + + if (!e->slots[id].block) + return -1; + +/* pa_log("Processing release for %u", id); */ + + assert(e->pool->stat.n_exported > 0); + assert(e->pool->stat.exported_size >= e->slots[id].block->length); + + e->pool->stat.n_exported --; + e->pool->stat.exported_size -= e->slots[id].block->length; + + pa_memblock_unref(e->slots[id].block); + e->slots[id].block = NULL; + + PA_LLIST_REMOVE(struct memexport_slot, e->used_slots, &e->slots[id]); + PA_LLIST_PREPEND(struct memexport_slot, e->free_slots, &e->slots[id]); + + return 0; +} + +static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) { + struct memexport_slot *slot, *next; + assert(e); + assert(i); + + for (slot = e->used_slots; slot; slot = next) { + uint32_t idx; + next = slot->next; + + if (slot->block->type != PA_MEMBLOCK_IMPORTED || + slot->block->per_type.imported.segment->import != i) + continue; + + idx = slot - e->slots; + e->revoke_cb(e, idx, e->userdata); + pa_memexport_process_release(e, idx); + } +} + +static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *b) { + pa_memblock *n; + + assert(p); + assert(b); + + if (b->type == PA_MEMBLOCK_IMPORTED || + b->type == PA_MEMBLOCK_POOL || + b->type == PA_MEMBLOCK_POOL_EXTERNAL) { + assert(b->pool == p); + return pa_memblock_ref(b); + } + + if (!(n = pa_memblock_new_pool(p, b->length))) + return NULL; + + memcpy(n->data, b->data, b->length); + return n; +} + +int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32_t *shm_id, size_t *offset, size_t * size) { + pa_shm *memory; + struct memexport_slot *slot; + + assert(e); + assert(b); + assert(block_id); + assert(shm_id); + assert(offset); + assert(size); + assert(b->pool == e->pool); + + if (!(b = memblock_shared_copy(e->pool, b))) + return -1; + + if (e->free_slots) { + slot = e->free_slots; + PA_LLIST_REMOVE(struct memexport_slot, e->free_slots, slot); + } else if (e->n_init < PA_MEMEXPORT_SLOTS_MAX) { + slot = &e->slots[e->n_init++]; + } else { pa_memblock_unref(b); - else { - b->data = pa_xmemdup(b->data, b->length); - b->type = PA_MEMBLOCK_DYNAMIC; - b->ref--; + return -1; } -} -pa_memblock_stat* pa_memblock_stat_new(void) { - pa_memblock_stat *s; + PA_LLIST_PREPEND(struct memexport_slot, e->used_slots, slot); + slot->block = b; + *block_id = slot - e->slots; - s = pa_xmalloc(sizeof(pa_memblock_stat)); - s->ref = 1; - s->total = s->total_size = s->allocated = s->allocated_size = 0; +/* pa_log("Got block id %u", *block_id); */ - return s; -} - -void pa_memblock_stat_unref(pa_memblock_stat *s) { - assert(s && s->ref >= 1); - - if (!(--(s->ref))) { - assert(!s->total); - pa_xfree(s); + if (b->type == PA_MEMBLOCK_IMPORTED) { + assert(b->per_type.imported.segment); + memory = &b->per_type.imported.segment->memory; + } else { + assert(b->type == PA_MEMBLOCK_POOL || b->type == PA_MEMBLOCK_POOL_EXTERNAL); + assert(b->pool); + memory = &b->pool->memory; } -} + + assert(b->data >= memory->ptr); + assert((uint8_t*) b->data + b->length <= (uint8_t*) memory->ptr + memory->size); + + *shm_id = memory->id; + *offset = (uint8_t*) b->data - (uint8_t*) memory->ptr; + *size = b->length; -pa_memblock_stat * pa_memblock_stat_ref(pa_memblock_stat *s) { - assert(s); - s->ref++; - return s; + e->pool->stat.n_exported ++; + e->pool->stat.exported_size += b->length; + + return 0; } diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index 04a0b55b1..e63e1e0fe 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -1,5 +1,5 @@ -#ifndef foomemblockhfoo -#define foomemblockhfoo +#ifndef foopulsememblockhfoo +#define foopulsememblockhfoo /* $Id$ */ @@ -25,6 +25,8 @@ #include #include +#include + /* A pa_memblock is a reference counted memory block. PulseAudio * passed references to pa_memblocks around instead of copying * data. See pa_memchunk for a structure that describes parts of @@ -32,43 +34,72 @@ /* The type of memory this block points to */ typedef enum pa_memblock_type { - PA_MEMBLOCK_FIXED, /* data is a pointer to fixed memory that needs not to be freed */ - PA_MEMBLOCK_APPENDED, /* The most common kind: the data is appended to the memory block */ - PA_MEMBLOCK_DYNAMIC, /* data is a pointer to some memory allocated with pa_xmalloc() */ - PA_MEMBLOCK_USER /* User supplied memory, to be freed with free_cb */ + PA_MEMBLOCK_POOL, /* Memory is part of the memory pool */ + PA_MEMBLOCK_POOL_EXTERNAL, /* Data memory is part of the memory pool but the pa_memblock structure itself not */ + PA_MEMBLOCK_APPENDED, /* the data is appended to the memory block */ + PA_MEMBLOCK_USER, /* User supplied memory, to be freed with free_cb */ + PA_MEMBLOCK_FIXED, /* data is a pointer to fixed memory that needs not to be freed */ + PA_MEMBLOCK_IMPORTED, /* Memory is imported from another process via shm */ } pa_memblock_type_t; -/* A structure of keeping memory block statistics */ -/* Maintains statistics about memory blocks */ -typedef struct pa_memblock_stat { - int ref; - unsigned total; - unsigned total_size; - unsigned allocated; - unsigned allocated_size; -} pa_memblock_stat; +typedef struct pa_memblock pa_memblock; +typedef struct pa_mempool pa_mempool; +typedef struct pa_mempool_stat pa_mempool_stat; +typedef struct pa_memimport_segment pa_memimport_segment; +typedef struct pa_memimport pa_memimport; +typedef struct pa_memexport pa_memexport; -typedef struct pa_memblock { +typedef void (*pa_memimport_release_cb_t)(pa_memimport *i, uint32_t block_id, void *userdata); +typedef void (*pa_memexport_revoke_cb_t)(pa_memexport *e, uint32_t block_id, void *userdata); + +struct pa_memblock { pa_memblock_type_t type; - unsigned ref; /* the reference counter */ int read_only; /* boolean */ + unsigned ref; /* the reference counter */ size_t length; void *data; - void (*free_cb)(void *p); /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ - pa_memblock_stat *stat; -} pa_memblock; + pa_mempool *pool; -/* Allocate a new memory block of type PA_MEMBLOCK_APPENDED */ -pa_memblock *pa_memblock_new(size_t length, pa_memblock_stat*s); + union { + struct { + void (*free_cb)(void *p); /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ + } user; + + struct { + uint32_t id; + pa_memimport_segment *segment; + } imported; + } per_type; +}; -/* Allocate a new memory block of type PA_MEMBLOCK_DYNAMIC. The pointer data is to be maintained be the memory block */ -pa_memblock *pa_memblock_new_dynamic(void *data, size_t length, pa_memblock_stat*s); +struct pa_mempool_stat { + unsigned n_allocated; + unsigned n_accumulated; + unsigned n_imported; + unsigned n_exported; + size_t allocated_size; + size_t accumulated_size; + size_t imported_size; + size_t exported_size; -/* Allocate a new memory block of type PA_MEMBLOCK_FIXED */ -pa_memblock *pa_memblock_new_fixed(void *data, size_t length, int read_only, pa_memblock_stat*s); + unsigned n_too_large_for_pool; + unsigned n_pool_full; +}; + +/* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL or PA_MEMBLOCK_APPENDED, depending on the size */ +pa_memblock *pa_memblock_new(pa_mempool *, size_t length); + +/* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL. If the requested size is too large, return NULL */ +pa_memblock *pa_memblock_new_pool(pa_mempool *, size_t length); /* Allocate a new memory block of type PA_MEMBLOCK_USER */ -pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p), int read_only, pa_memblock_stat*s); +pa_memblock *pa_memblock_new_user(pa_mempool *, void *data, size_t length, void (*free_cb)(void *p), int read_only); + +/* A special case of pa_memblock_new_user: take a memory buffer previously allocated with pa_xmalloc() */ +#define pa_memblock_new_malloced(p,data,length) pa_memblock_new_user(p, data, length, pa_xfree, 0) + +/* Allocate a new memory block of type PA_MEMBLOCK_FIXED */ +pa_memblock *pa_memblock_new_fixed(pa_mempool *, void *data, size_t length, int read_only); void pa_memblock_unref(pa_memblock*b); pa_memblock* pa_memblock_ref(pa_memblock*b); @@ -79,8 +110,23 @@ references to the memory. This causes the memory to be copied and converted into a PA_MEMBLOCK_DYNAMIC type memory block */ void pa_memblock_unref_fixed(pa_memblock*b); -pa_memblock_stat* pa_memblock_stat_new(void); -void pa_memblock_stat_unref(pa_memblock_stat *s); -pa_memblock_stat * pa_memblock_stat_ref(pa_memblock_stat *s); +/* The memory block manager */ +pa_mempool* pa_mempool_new(int shared); +void pa_mempool_free(pa_mempool *p); +const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p); +void pa_mempool_vacuum(pa_mempool *p); +int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id); + +/* For recieving blocks from other nodes */ +pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void *userdata); +void pa_memimport_free(pa_memimport *i); +pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_id, size_t offset, size_t size); +int pa_memimport_process_revoke(pa_memimport *i, uint32_t block_id); + +/* For sending blocks to other nodes */ +pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void *userdata); +void pa_memexport_free(pa_memexport *e); +int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32_t *shm_id, size_t *offset, size_t *size); +int pa_memexport_process_release(pa_memexport *e, uint32_t id); #endif diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index 822bd66cd..2fd38850e 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -49,7 +49,6 @@ struct pa_memblockq { size_t maxlength, tlength, base, prebuf, minreq; int64_t read_index, write_index; enum { PREBUF, RUNNING } state; - pa_memblock_stat *memblock_stat; pa_memblock *silence; pa_mcalign *mcalign; }; @@ -61,8 +60,7 @@ pa_memblockq* pa_memblockq_new( size_t base, size_t prebuf, size_t minreq, - pa_memblock *silence, - pa_memblock_stat *s) { + pa_memblock *silence) { pa_memblockq* bq; @@ -75,7 +73,6 @@ pa_memblockq* pa_memblockq_new( bq->base = base; bq->read_index = bq->write_index = idx; - bq->memblock_stat = s; pa_log_debug(__FILE__": memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", (unsigned long)maxlength, (unsigned long)tlength, (unsigned long)base, (unsigned long)prebuf, (unsigned long)minreq); @@ -586,7 +583,7 @@ int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk) { return pa_memblockq_push(bq, chunk); if (!bq->mcalign) - bq->mcalign = pa_mcalign_new(bq->base, bq->memblock_stat); + bq->mcalign = pa_mcalign_new(bq->base); if (!can_push(bq, pa_mcalign_csize(bq->mcalign, chunk->length))) return -1; diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h index c35b62ddd..4d701a80e 100644 --- a/src/pulsecore/memblockq.h +++ b/src/pulsecore/memblockq.h @@ -69,8 +69,7 @@ pa_memblockq* pa_memblockq_new( size_t base, size_t prebuf, size_t minreq, - pa_memblock *silence, - pa_memblock_stat *s); + pa_memblock *silence); void pa_memblockq_free(pa_memblockq*bq); diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c index abfc2cab7..bcf0ce043 100644 --- a/src/pulsecore/memchunk.c +++ b/src/pulsecore/memchunk.c @@ -32,10 +32,13 @@ #include "memchunk.h" -void pa_memchunk_make_writable(pa_memchunk *c, pa_memblock_stat *s, size_t min) { +void pa_memchunk_make_writable(pa_memchunk *c, size_t min) { pa_memblock *n; size_t l; - assert(c && c->memblock && c->memblock->ref >= 1); + + assert(c); + assert(c->memblock); + assert(c->memblock->ref >= 1); if (c->memblock->ref == 1 && !c->memblock->read_only && c->memblock->length >= c->index+min) return; @@ -44,7 +47,7 @@ void pa_memchunk_make_writable(pa_memchunk *c, pa_memblock_stat *s, size_t min) if (l < min) l = min; - n = pa_memblock_new(l, s); + n = pa_memblock_new(c->memblock->pool, l); memcpy(n->data, (uint8_t*) c->memblock->data + c->index, c->length); pa_memblock_unref(c->memblock); c->memblock = n; diff --git a/src/pulsecore/memchunk.h b/src/pulsecore/memchunk.h index 1b26c2e64..b8ce62495 100644 --- a/src/pulsecore/memchunk.h +++ b/src/pulsecore/memchunk.h @@ -36,7 +36,7 @@ typedef struct pa_memchunk { /* Make a memchunk writable, i.e. make sure that the caller may have * exclusive access to the memblock and it is not read_only. If needed * the memblock in the structure is replaced by a copy. */ -void pa_memchunk_make_writable(pa_memchunk *c, pa_memblock_stat *s, size_t min); +void pa_memchunk_make_writable(pa_memchunk *c, size_t min); /* Invalidate a memchunk. This does not free the cotaining memblock, * but sets all members to zero. */ diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index f1a827bce..2fadeca30 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -377,8 +377,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t pa_frame_size(&ss), (size_t) -1, l/PLAYBACK_BUFFER_FRAGMENTS, - NULL, - c->protocol->core->memblock_stat); + NULL); pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2); c->playback.fragment_size = l/10; @@ -469,8 +468,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co pa_frame_size(&ss), 1, 0, - NULL, - c->protocol->core->memblock_stat); + NULL); pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2); c->source_output->push = source_output_push_cb; @@ -722,7 +720,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name."); assert(!c->scache.memchunk.memblock); - c->scache.memchunk.memblock = pa_memblock_new(sc_length, c->protocol->core->memblock_stat); + c->scache.memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, sc_length); c->scache.memchunk.index = 0; c->scache.memchunk.length = sc_length; c->scache.sample_spec = ss; @@ -941,7 +939,7 @@ static int do_read(struct connection *c) { } if (!c->playback.current_memblock) { - c->playback.current_memblock = pa_memblock_new(c->playback.fragment_size*2, c->protocol->core->memblock_stat); + c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2); assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); c->playback.memblock_index = 0; } diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 0b79892c5..2c9b3566c 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -348,8 +348,7 @@ static struct record_stream* record_stream_new( base = pa_frame_size(ss), 1, 0, - NULL, - c->protocol->core->memblock_stat); + NULL); assert(s->memblockq); s->fragment_size = (fragment_size/base)*base; @@ -448,7 +447,7 @@ static struct playback_stream* playback_stream_new( start_index = 0; } - silence = pa_silence_memblock_new(ss, 0, c->protocol->core->memblock_stat); + silence = pa_silence_memblock_new(c->protocol->core->mempool, ss, 0); s->memblockq = pa_memblockq_new( start_index, @@ -457,8 +456,7 @@ static struct playback_stream* playback_stream_new( pa_frame_size(ss), prebuf, minreq, - silence, - c->protocol->core->memblock_stat); + silence); pa_memblock_unref(silence); @@ -1076,6 +1074,7 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; pa_tagstruct *reply; + const pa_mempool_stat *stat; assert(c && t); if (!pa_tagstruct_eof(t)) { @@ -1085,11 +1084,13 @@ static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + stat = pa_mempool_get_stat(c->protocol->core->mempool); + reply = reply_new(tag); - pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total); - pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total_size); - pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated); - pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated_size); + pa_tagstruct_putu32(reply, stat->n_allocated); + pa_tagstruct_putu32(reply, stat->allocated_size); + pa_tagstruct_putu32(reply, stat->n_accumulated); + pa_tagstruct_putu32(reply, stat->accumulated_size); pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core)); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -2256,7 +2257,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o pa_memblock_ref(u->memchunk.memblock); u->length = 0; } else { - u->memchunk.memblock = pa_memblock_new(u->length, c->protocol->core->memblock_stat); + u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length); u->memchunk.index = u->memchunk.length = 0; } } @@ -2349,9 +2350,11 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo c->client->userdata = c; c->client->owner = p->module; - c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->memblock_stat); + c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool); assert(c->pstream); + pa_pstream_use_shm(c->pstream, 1); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 3705986d5..924ee29ec 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -128,7 +128,7 @@ static int do_read(struct connection *c) { } if (!c->playback.current_memblock) { - c->playback.current_memblock = pa_memblock_new(c->playback.fragment_size*2, c->protocol->core->memblock_stat); + c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2); assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); c->playback.memblock_index = 0; } @@ -369,8 +369,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) pa_frame_size(&p->sample_spec), (size_t) -1, l/PLAYBACK_BUFFER_FRAGMENTS, - NULL, - p->core->memblock_stat); + NULL); assert(c->input_memblockq); pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5); c->playback.fragment_size = l/10; @@ -406,8 +405,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) pa_frame_size(&p->sample_spec), 1, 0, - NULL, - p->core->memblock_stat); + NULL); pa_iochannel_socket_set_sndbuf(io, l/RECORD_BUFFER_FRAGMENTS*2); pa_source_notify(c->source_output->source); } diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 7096d65af..421f5de9c 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -49,28 +49,45 @@ #include "pstream.h" +/* We piggyback information if audio data blocks are stored in SHM on the seek mode */ +#define PA_FLAG_SHMDATA 0x80000000LU +#define PA_FLAG_SHMRELEASE 0x40000000LU +#define PA_FLAG_SHMREVOKE 0xC0000000LU +#define PA_FLAG_SHMMASK 0xFF000000LU +#define PA_FLAG_SEEKMASK 0x000000FFLU + +/* The sequence descriptor header consists of 5 32bit integers: */ enum { PA_PSTREAM_DESCRIPTOR_LENGTH, PA_PSTREAM_DESCRIPTOR_CHANNEL, PA_PSTREAM_DESCRIPTOR_OFFSET_HI, PA_PSTREAM_DESCRIPTOR_OFFSET_LO, - PA_PSTREAM_DESCRIPTOR_SEEK, + PA_PSTREAM_DESCRIPTOR_FLAGS, PA_PSTREAM_DESCRIPTOR_MAX }; +/* If we have an SHM block, this info follows the descriptor */ +enum { + PA_PSTREAM_SHM_BLOCKID, + PA_PSTREAM_SHM_SHMID, + PA_PSTREAM_SHM_INDEX, + PA_PSTREAM_SHM_LENGTH, + PA_PSTREAM_SHM_MAX +}; + typedef uint32_t pa_pstream_descriptor[PA_PSTREAM_DESCRIPTOR_MAX]; #define PA_PSTREAM_DESCRIPTOR_SIZE (PA_PSTREAM_DESCRIPTOR_MAX*sizeof(uint32_t)) #define FRAME_SIZE_MAX PA_SCACHE_ENTRY_SIZE_MAX /* allow uploading a single sample in one frame at max */ struct item_info { - enum { PA_PSTREAM_ITEM_PACKET, PA_PSTREAM_ITEM_MEMBLOCK } type; + enum { + PA_PSTREAM_ITEM_PACKET, + PA_PSTREAM_ITEM_MEMBLOCK, + PA_PSTREAM_ITEM_SHMRELEASE, + PA_PSTREAM_ITEM_SHMREVOKE + } type; - /* memblock info */ - pa_memchunk chunk; - uint32_t channel; - int64_t offset; - pa_seek_mode_t seek_mode; /* packet info */ pa_packet *packet; @@ -78,6 +95,15 @@ struct item_info { int with_creds; pa_creds creds; #endif + + /* memblock info */ + pa_memchunk chunk; + uint32_t channel; + int64_t offset; + pa_seek_mode_t seek_mode; + + /* release/revoke info */ + uint32_t block_id; }; struct pa_pstream { @@ -91,20 +117,26 @@ struct pa_pstream { int dead; struct { - struct item_info* current; pa_pstream_descriptor descriptor; + struct item_info* current; + uint32_t shm_info[PA_PSTREAM_SHM_MAX]; void *data; size_t index; } write; struct { + pa_pstream_descriptor descriptor; pa_memblock *memblock; pa_packet *packet; - pa_pstream_descriptor descriptor; + uint32_t shm_info[PA_PSTREAM_SHM_MAX]; void *data; size_t index; } read; + int use_shm; + pa_memimport *import; + pa_memexport *export; + pa_pstream_packet_cb_t recieve_packet_callback; void *recieve_packet_callback_userdata; @@ -117,7 +149,7 @@ struct pa_pstream { pa_pstream_notify_cb_t die_callback; void *die_callback_userdata; - pa_memblock_stat *memblock_stat; + pa_mempool *mempool; #ifdef HAVE_CREDS pa_creds read_creds, write_creds; @@ -178,16 +210,19 @@ static void defer_callback(pa_mainloop_api *m, pa_defer_event *e, void*userdata) do_something(p); } -pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_stat *s) { +static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata); + +pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *pool) { pa_pstream *p; + + assert(m); assert(io); + assert(pool); p = pa_xnew(pa_pstream, 1); - p->ref = 1; p->io = io; pa_iochannel_set_callback(io, io_callback, p); - p->dead = 0; p->mainloop = m; @@ -199,24 +234,24 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_sta p->write.current = NULL; p->write.index = 0; - p->read.memblock = NULL; p->read.packet = NULL; p->read.index = 0; p->recieve_packet_callback = NULL; p->recieve_packet_callback_userdata = NULL; - p->recieve_memblock_callback = NULL; p->recieve_memblock_callback_userdata = NULL; - p->drain_callback = NULL; p->drain_callback_userdata = NULL; - p->die_callback = NULL; p->die_callback_userdata = NULL; - p->memblock_stat = s; + p->mempool = pool; + + p->use_shm = 0; + p->export = NULL; + p->import = NULL; pa_iochannel_socket_set_rcvbuf(io, 1024*8); pa_iochannel_socket_set_sndbuf(io, 1024*8); @@ -235,8 +270,7 @@ static void item_free(void *item, PA_GCC_UNUSED void *p) { if (i->type == PA_PSTREAM_ITEM_MEMBLOCK) { assert(i->chunk.memblock); pa_memblock_unref(i->chunk.memblock); - } else { - assert(i->type == PA_PSTREAM_ITEM_PACKET); + } else if (i->type == PA_PSTREAM_ITEM_PACKET) { assert(i->packet); pa_packet_unref(i->packet); } @@ -265,16 +299,18 @@ static void pstream_free(pa_pstream *p) { void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds) { struct item_info *i; - assert(p && packet && p->ref >= 1); + + assert(p); + assert(p->ref >= 1); + assert(packet); if (p->dead) return; -/* pa_log(__FILE__": push-packet %p", packet); */ - i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); + #ifdef HAVE_CREDS if ((i->with_creds = !!creds)) i->creds = *creds; @@ -286,13 +322,15 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) { struct item_info *i; - assert(p && channel != (uint32_t) -1 && chunk && p->ref >= 1); + + assert(p); + assert(p->ref >= 1); + assert(channel != (uint32_t) -1); + assert(chunk); if (p->dead) return; - -/* pa_log(__FILE__": push-memblock %p", chunk); */ - + i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_MEMBLOCK; i->chunk = *chunk; @@ -309,6 +347,52 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa p->mainloop->defer_enable(p->defer_event, 1); } +static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata) { + struct item_info *item; + pa_pstream *p = userdata; + + assert(p); + assert(p->ref >= 1); + + if (p->dead) + return; + +/* pa_log(__FILE__": Releasing block %u", block_id); */ + + item = pa_xnew(struct item_info, 1); + item->type = PA_PSTREAM_ITEM_SHMRELEASE; + item->block_id = block_id; +#ifdef HAVE_CREDS + item->with_creds = 0; +#endif + + pa_queue_push(p->send_queue, item); + p->mainloop->defer_enable(p->defer_event, 1); +} + +static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) { + struct item_info *item; + pa_pstream *p = userdata; + + assert(p); + assert(p->ref >= 1); + + if (p->dead) + return; + +/* pa_log(__FILE__": Revoking block %u", block_id); */ + + item = pa_xnew(struct item_info, 1); + item->type = PA_PSTREAM_ITEM_SHMREVOKE; + item->block_id = block_id; +#ifdef HAVE_CREDS + item->with_creds = 0; +#endif + + pa_queue_push(p->send_queue, item); + p->mainloop->defer_enable(p->defer_event, 1); +} + static void prepare_next_write_item(pa_pstream *p) { assert(p); @@ -316,27 +400,77 @@ static void prepare_next_write_item(pa_pstream *p) { return; p->write.index = 0; + p->write.data = NULL; + + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = 0; + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = 0; + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = 0; + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = 0; if (p->write.current->type == PA_PSTREAM_ITEM_PACKET) { - /*pa_log(__FILE__": pop-packet %p", p->write.current->packet);*/ assert(p->write.current->packet); p->write.data = p->write.current->packet->data; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length); - p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1); - p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = 0; - p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = 0; - p->write.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = 0; + } else if (p->write.current->type == PA_PSTREAM_ITEM_SHMRELEASE) { + + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(PA_FLAG_SHMRELEASE); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl(p->write.current->block_id); + + } else if (p->write.current->type == PA_PSTREAM_ITEM_SHMREVOKE) { + + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(PA_FLAG_SHMREVOKE); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl(p->write.current->block_id); } else { - assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK && p->write.current->chunk.memblock); - p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index; - p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); + uint32_t flags; + int send_payload = 1; + + assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK); + assert(p->write.current->chunk.memblock); + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl(p->write.current->channel); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl((uint32_t) (((uint64_t) p->write.current->offset) >> 32)); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = htonl((uint32_t) ((uint64_t) p->write.current->offset)); - p->write.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = htonl(p->write.current->seek_mode); + + flags = p->write.current->seek_mode & PA_FLAG_SEEKMASK; + + if (p->use_shm) { + uint32_t block_id, shm_id; + size_t offset, length; + + assert(p->export); + + if (pa_memexport_put(p->export, + p->write.current->chunk.memblock, + &block_id, + &shm_id, + &offset, + &length) >= 0) { + + flags |= PA_FLAG_SHMDATA; + send_payload = 0; + + p->write.shm_info[PA_PSTREAM_SHM_BLOCKID] = htonl(block_id); + p->write.shm_info[PA_PSTREAM_SHM_SHMID] = htonl(shm_id); + p->write.shm_info[PA_PSTREAM_SHM_INDEX] = htonl((uint32_t) (offset + p->write.current->chunk.index)); + p->write.shm_info[PA_PSTREAM_SHM_LENGTH] = htonl((uint32_t) p->write.current->chunk.length); + + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(sizeof(p->write.shm_info)); + p->write.data = p->write.shm_info; + } +/* else */ +/* pa_log_warn(__FILE__": Failed to export memory block."); */ + } + + if (send_payload) { + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); + p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index; + } + + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(flags); } #ifdef HAVE_CREDS @@ -344,7 +478,6 @@ static void prepare_next_write_item(pa_pstream *p) { p->write_creds = p->write.current->creds; #endif - } static int do_write(pa_pstream *p) { @@ -359,16 +492,18 @@ static int do_write(pa_pstream *p) { if (!p->write.current) return 0; - assert(p->write.data); - if (p->write.index < PA_PSTREAM_DESCRIPTOR_SIZE) { d = (uint8_t*) p->write.descriptor + p->write.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->write.index; } else { + assert(p->write.data); + d = (uint8_t*) p->write.data + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } + assert(l > 0); + #ifdef HAVE_CREDS if (p->send_creds_now) { @@ -384,7 +519,7 @@ static int do_write(pa_pstream *p) { p->write.index += r; - if (p->write.index >= PA_PSTREAM_DESCRIPTOR_SIZE+ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])) { + if (p->write.index >= PA_PSTREAM_DESCRIPTOR_SIZE + ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])) { assert(p->write.current); item_free(p->write.current, (void *) 1); p->write.current = NULL; @@ -428,27 +563,87 @@ static int do_read(pa_pstream *p) { p->read.index += r; if (p->read.index == PA_PSTREAM_DESCRIPTOR_SIZE) { + uint32_t flags, length, channel; /* Reading of frame descriptor complete */ - /* Frame size too large */ - if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) > FRAME_SIZE_MAX) { - pa_log_warn(__FILE__": Frame size too large: %lu > %lu", (unsigned long) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]), (unsigned long) FRAME_SIZE_MAX); + flags = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]); + + if (!p->use_shm && (flags & PA_FLAG_SHMMASK) != 0) { + pa_log_warn(__FILE__": Recieved SHM frame on a socket where SHM is disabled."); + return -1; + } + + if (flags == PA_FLAG_SHMRELEASE) { + + /* This is a SHM memblock release frame with no payload */ + +/* pa_log(__FILE__": Got release frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */ + + assert(p->export); + pa_memexport_process_release(p->export, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); + + goto frame_done; + + } else if (flags == PA_FLAG_SHMREVOKE) { + + /* This is a SHM memblock revoke frame with no payload */ + +/* pa_log(__FILE__": Got revoke frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */ + + assert(p->import); + pa_memimport_process_revoke(p->import, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); + + goto frame_done; + } + + length = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]); + + if (length > FRAME_SIZE_MAX) { + pa_log_warn(__FILE__": Recieved invalid frame size : %lu", (unsigned long) length); return -1; } assert(!p->read.packet && !p->read.memblock); - if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]) == (uint32_t) -1) { - /* Frame is a packet frame */ - p->read.packet = pa_packet_new(ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])); - p->read.data = p->read.packet->data; - } else { - /* Frame is a memblock frame */ - p->read.memblock = pa_memblock_new(ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]), p->memblock_stat); - p->read.data = p->read.memblock->data; + channel = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]); + + if (channel == (uint32_t) -1) { - if (ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK]) > PA_SEEK_RELATIVE_END) { - pa_log_warn(__FILE__": Invalid seek mode"); + if (flags != 0) { + pa_log_warn(__FILE__": Received packet frame with invalid flags value."); + return -1; + } + + /* Frame is a packet frame */ + p->read.packet = pa_packet_new(length); + p->read.data = p->read.packet->data; + + } else { + + if ((flags & PA_FLAG_SEEKMASK) > PA_SEEK_RELATIVE_END) { + pa_log_warn(__FILE__": Received memblock frame with invalid seek mode."); + return -1; + } + + if ((flags & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA) { + + if (length != sizeof(p->read.shm_info)) { + pa_log_warn(__FILE__": Recieved SHM memblock frame with Invalid frame length."); + return -1; + } + + /* Frame is a memblock frame referencing an SHM memblock */ + p->read.data = p->read.shm_info; + + } else if ((flags & PA_FLAG_SHMMASK) == 0) { + + /* Frame is a memblock frame */ + + p->read.memblock = pa_memblock_new(p->mempool, length); + p->read.data = p->read.memblock->data; + } else { + + pa_log_warn(__FILE__": Recieved memblock frame with invalid flags value."); return -1; } } @@ -456,7 +651,9 @@ static int do_read(pa_pstream *p) { } else if (p->read.index > PA_PSTREAM_DESCRIPTOR_SIZE) { /* Frame payload available */ - if (p->read.memblock && p->recieve_memblock_callback) { /* Is this memblock data? Than pass it to the user */ + if (p->read.memblock && p->recieve_memblock_callback) { + + /* Is this memblock data? Than pass it to the user */ l = (p->read.index - r) < PA_PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE : (size_t) r; if (l > 0) { @@ -477,13 +674,13 @@ static int do_read(pa_pstream *p) { p, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]), offset, - ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK]), + ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SEEKMASK, &chunk, p->recieve_memblock_callback_userdata); } /* Drop seek info for following callbacks */ - p->read.descriptor[PA_PSTREAM_DESCRIPTOR_SEEK] = + p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = 0; } @@ -491,13 +688,13 @@ static int do_read(pa_pstream *p) { /* Frame complete */ if (p->read.index >= ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) + PA_PSTREAM_DESCRIPTOR_SIZE) { + if (p->read.memblock) { - assert(!p->read.packet); - + + /* This was a memblock frame. We can unref the memblock now */ pa_memblock_unref(p->read.memblock); - p->read.memblock = NULL; - } else { - assert(p->read.packet); + + } else if (p->read.packet) { if (p->recieve_packet_callback) #ifdef HAVE_CREDS @@ -507,17 +704,63 @@ static int do_read(pa_pstream *p) { #endif pa_packet_unref(p->read.packet); - p->read.packet = NULL; + } else { + pa_memblock *b; + + assert((ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA); + + assert(p->import); + + if (!(b = pa_memimport_get(p->import, + ntohl(p->read.shm_info[PA_PSTREAM_SHM_BLOCKID]), + ntohl(p->read.shm_info[PA_PSTREAM_SHM_SHMID]), + ntohl(p->read.shm_info[PA_PSTREAM_SHM_INDEX]), + ntohl(p->read.shm_info[PA_PSTREAM_SHM_LENGTH])))) { + + pa_log_warn(__FILE__": Failed to import memory block."); + return -1; + } + + if (p->recieve_memblock_callback) { + int64_t offset; + pa_memchunk chunk; + + chunk.memblock = b; + chunk.index = 0; + chunk.length = b->length; + + offset = (int64_t) ( + (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) | + (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO])))); + + p->recieve_memblock_callback( + p, + ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]), + offset, + ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SEEKMASK, + &chunk, + p->recieve_memblock_callback_userdata); + } + + pa_memblock_unref(b); } - p->read.index = 0; -#ifdef HAVE_CREDS - p->read_creds_valid = 0; -#endif + goto frame_done; } } - return 0; + return 0; + +frame_done: + p->read.memblock = NULL; + p->read.packet = NULL; + p->read.index = 0; + +#ifdef HAVE_CREDS + p->read_creds_valid = 0; +#endif + + return 0; } void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { @@ -583,6 +826,16 @@ void pa_pstream_close(pa_pstream *p) { p->dead = 1; + if (p->import) { + pa_memimport_free(p->import); + p->import = NULL; + } + + if (p->export) { + pa_memexport_free(p->export); + p->export = NULL; + } + if (p->io) { pa_iochannel_free(p->io); p->io = NULL; @@ -597,4 +850,19 @@ void pa_pstream_close(pa_pstream *p) { p->drain_callback = NULL; p->recieve_packet_callback = NULL; p->recieve_memblock_callback = NULL; + + +} + +void pa_pstream_use_shm(pa_pstream *p, int enable) { + assert(p); + assert(p->ref >= 1); + + p->use_shm = enable; + + if (!p->import) + p->import = pa_memimport_new(p->mempool, memimport_release_cb, p); + + if (!p->export) + p->export = pa_memexport_new(p->mempool, memexport_revoke_cb, p); } diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h index 789e40bc2..26bb7699c 100644 --- a/src/pulsecore/pstream.h +++ b/src/pulsecore/pstream.h @@ -39,7 +39,7 @@ typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const p typedef void (*pa_pstream_memblock_cb_t)(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata); typedef void (*pa_pstream_notify_cb_t)(pa_pstream *p, void *userdata); -pa_pstream* pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_memblock_stat *s); +pa_pstream* pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *p); void pa_pstream_unref(pa_pstream*p); pa_pstream* pa_pstream_ref(pa_pstream*p); @@ -54,6 +54,8 @@ void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void int pa_pstream_is_pending(pa_pstream *p); +void pa_pstream_use_shm(pa_pstream *p, int enable); + void pa_pstream_close(pa_pstream *p); #endif diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index 23cdf3811..742267146 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -42,7 +42,7 @@ struct pa_resampler { pa_sample_spec i_ss, o_ss; pa_channel_map i_cm, o_cm; size_t i_fz, o_fz; - pa_memblock_stat *memblock_stat; + pa_mempool *mempool; void (*impl_free)(pa_resampler *r); void (*impl_update_input_rate)(pa_resampler *r, uint32_t rate); @@ -71,15 +71,16 @@ static int libsamplerate_init(pa_resampler*r); static int trivial_init(pa_resampler*r); pa_resampler* pa_resampler_new( - const pa_sample_spec *a, - const pa_channel_map *am, - const pa_sample_spec *b, - const pa_channel_map *bm, - pa_memblock_stat *s, - pa_resample_method_t resample_method) { + pa_mempool *pool, + const pa_sample_spec *a, + const pa_channel_map *am, + const pa_sample_spec *b, + const pa_channel_map *bm, + pa_resample_method_t resample_method) { pa_resampler *r = NULL; + assert(pool); assert(a); assert(b); assert(pa_sample_spec_valid(a)); @@ -88,7 +89,7 @@ pa_resampler* pa_resampler_new( r = pa_xnew(pa_resampler, 1); r->impl_data = NULL; - r->memblock_stat = s; + r->mempool = pool; r->resample_method = resample_method; r->impl_free = NULL; @@ -450,7 +451,7 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun assert(p); /* Take the existing buffer and make it a memblock */ - out->memblock = pa_memblock_new_dynamic(*p, out->length, r->memblock_stat); + out->memblock = pa_memblock_new_malloced(r->mempool, *p, out->length); *p = NULL; } } else { @@ -549,7 +550,7 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz; out->index = 0; - out->memblock = pa_memblock_new(l, r->memblock_stat); + out->memblock = pa_memblock_new(r->mempool, l); for (o_index = 0;; o_index++, u->o_counter++) { unsigned j; diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h index c1199e5ce..327e24a29 100644 --- a/src/pulsecore/resampler.h +++ b/src/pulsecore/resampler.h @@ -43,12 +43,12 @@ typedef enum pa_resample_method { } pa_resample_method_t; pa_resampler* pa_resampler_new( - const pa_sample_spec *a, - const pa_channel_map *am, - const pa_sample_spec *b, - const pa_channel_map *bm, - pa_memblock_stat *s, - pa_resample_method_t resample_method); + pa_mempool *pool, + const pa_sample_spec *a, + const pa_channel_map *am, + const pa_sample_spec *b, + const pa_channel_map *bm, + pa_resample_method_t resample_method); void pa_resampler_free(pa_resampler *r); diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index 638f80670..7f5d8a020 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -35,13 +35,14 @@ #include "sample-util.h" #include "endianmacros.h" -pa_memblock *pa_silence_memblock_new(const pa_sample_spec *spec, size_t length, pa_memblock_stat*s) { +pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spec, size_t length) { + assert(pool); assert(spec); if (length == 0) - length = pa_bytes_per_second(spec)/10; /* 100 ms */ + length = pa_bytes_per_second(spec)/20; /* 50 ms */ - return pa_silence_memblock(pa_memblock_new(length, s), spec); + return pa_silence_memblock(pa_memblock_new(pool, length), spec); } pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h index 3ebb7e2ea..6b7707925 100644 --- a/src/pulsecore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -28,7 +28,7 @@ #include pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec); -pa_memblock *pa_silence_memblock_new(const pa_sample_spec *spec, size_t length, pa_memblock_stat*s); +pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spec, size_t length); void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec); void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec); diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index b3fabad3a..b5ba9df19 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -136,9 +136,9 @@ pa_sink_input* pa_sink_input_new( !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) if (!(resampler = pa_resampler_new( + core->mempool, &data->sample_spec, &data->channel_map, &data->sink->sample_spec, &data->sink->channel_map, - core->memblock_stat, data->resample_method))) { pa_log_warn(__FILE__": Unsupported resampling operation."); return NULL; @@ -299,7 +299,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) * while until the old sink has drained its playback buffer */ if (!i->silence_memblock) - i->silence_memblock = pa_silence_memblock_new(&i->sink->sample_spec, SILENCE_BUFFER_LENGTH, i->sink->core->memblock_stat); + i->silence_memblock = pa_silence_memblock_new(i->sink->core->mempool, &i->sink->sample_spec, SILENCE_BUFFER_LENGTH); chunk->memblock = pa_memblock_ref(i->silence_memblock); chunk->index = 0; @@ -338,7 +338,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) /* It might be necessary to adjust the volume here */ if (do_volume_adj_here && !volume_is_norm) { - pa_memchunk_make_writable(&tchunk, i->sink->core->memblock_stat, 0); + pa_memchunk_make_writable(&tchunk, 0); pa_volume_memchunk(&tchunk, &i->sample_spec, &i->volume); } @@ -540,9 +540,9 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { /* Okey, we need a new resampler for the new sink */ if (!(new_resampler = pa_resampler_new( + dest->core->mempool, &i->sample_spec, &i->channel_map, &dest->sample_spec, &dest->channel_map, - dest->core->memblock_stat, i->resample_method))) { pa_log_warn(__FILE__": Unsupported resampling operation."); return -1; @@ -553,7 +553,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { pa_usec_t old_latency, new_latency; pa_usec_t silence_usec = 0; - buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL, NULL); + buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL); /* Let's do a little bit of Voodoo for compensating latency * differences */ @@ -599,7 +599,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { chunk.length = n; if (!volume_is_norm) { - pa_memchunk_make_writable(&chunk, origin->core->memblock_stat, 0); + pa_memchunk_make_writable(&chunk, 0); pa_volume_memchunk(&chunk, &origin->sample_spec, &volume); } diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 557d5efcb..aacb89fd5 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -298,14 +298,14 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); if (s->sw_muted || !pa_cvolume_is_norm(&volume)) { - pa_memchunk_make_writable(result, s->core->memblock_stat, 0); + pa_memchunk_make_writable(result, 0); if (s->sw_muted) pa_silence_memchunk(result, &s->sample_spec); else pa_volume_memchunk(result, &s->sample_spec, &volume); } } else { - result->memblock = pa_memblock_new(length, s->core->memblock_stat); + result->memblock = pa_memblock_new(s->core->mempool, length); assert(result->memblock); /* pa_log("mixing %i", n); */ @@ -429,7 +429,7 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { /*** This needs optimization ***/ - result->memblock = pa_memblock_new(result->length = length, s->core->memblock_stat); + result->memblock = pa_memblock_new(s->core->mempool, result->length = length); result->index = 0; pa_sink_render_into_full(s, result); diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index 6063b93e3..6782f50eb 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -75,7 +75,7 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { uint32_t fs = pa_frame_size(&i->sample_spec); sf_count_t n; - u->memchunk.memblock = pa_memblock_new(BUF_SIZE, i->sink->core->memblock_stat); + u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, BUF_SIZE); u->memchunk.index = 0; if (u->readf_function) { diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c index d11d4b9d9..256cce434 100644 --- a/src/pulsecore/sound-file.c +++ b/src/pulsecore/sound-file.c @@ -34,7 +34,7 @@ #include "sound-file.h" #include "core-scache.h" -int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk, pa_memblock_stat *s) { +int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk) { SNDFILE*sf = NULL; SF_INFO sfinfo; int ret = -1; @@ -92,7 +92,7 @@ int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *ma goto finish; } - chunk->memblock = pa_memblock_new(l, s); + chunk->memblock = pa_memblock_new(pool, l); assert(chunk->memblock); chunk->index = 0; chunk->length = l; diff --git a/src/pulsecore/sound-file.h b/src/pulsecore/sound-file.h index 0b81d97e1..7e3c82eab 100644 --- a/src/pulsecore/sound-file.h +++ b/src/pulsecore/sound-file.h @@ -26,7 +26,7 @@ #include #include -int pa_sound_file_load(const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk, pa_memblock_stat *s); +int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk); int pa_sound_file_too_big_to_cache(const char *fname); diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 7371474f1..f9d66f6d1 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -115,9 +115,9 @@ pa_source_output* pa_source_output_new( if (!pa_sample_spec_equal(&data->sample_spec, &data->source->sample_spec) || !pa_channel_map_equal(&data->channel_map, &data->source->channel_map)) if (!(resampler = pa_resampler_new( + core->mempool, &data->source->sample_spec, &data->source->channel_map, &data->sample_spec, &data->channel_map, - core->memblock_stat, data->resample_method))) { pa_log_warn(__FILE__": Unsupported resampling operation."); return NULL; @@ -330,9 +330,9 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { /* Okey, we need a new resampler for the new sink */ if (!(new_resampler = pa_resampler_new( + dest->core->mempool, &dest->sample_spec, &dest->channel_map, &o->sample_spec, &o->channel_map, - dest->core->memblock_stat, o->resample_method))) { pa_log_warn(__FILE__": Unsupported resampling operation."); return -1; diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 0d55da448..cb5b10302 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -211,7 +211,7 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) { pa_memchunk vchunk = *chunk; pa_memblock_ref(vchunk.memblock); - pa_memchunk_make_writable(&vchunk, s->core->memblock_stat, 0); + pa_memchunk_make_writable(&vchunk, 0); if (s->sw_muted) pa_silence_memchunk(&vchunk, &s->sample_spec); else From c3fc2eaa7e44c1d71f53e4f61c874f551a65de3e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 19:56:11 +0000 Subject: [PATCH 1167/1514] update tests for new memory manager git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1267 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/mcalign-test.c | 11 +++++++++-- src/tests/memblockq-test.c | 16 ++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index 7a68e6de0..356916984 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -38,9 +38,14 @@ /* A simple program for testing pa_mcalign */ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { - pa_mcalign *a = pa_mcalign_new(11, NULL); + pa_mempool *p; + pa_mcalign *a; pa_memchunk c; + p = pa_mempool_new(0); + + a = pa_mcalign_new(11); + pa_memchunk_reset(&c); srand(time(NULL)); @@ -50,7 +55,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { size_t l; if (!c.memblock) { - c.memblock = pa_memblock_new(2048, NULL); + c.memblock = pa_memblock_new(p, 2048); c.index = c.length = 0; } @@ -94,5 +99,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { if (c.memblock) pa_memblock_unref(c.memblock); + pa_mempool_free(p); + return 0; } diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c index af43d06f1..1ac4577b5 100644 --- a/src/tests/memblockq-test.c +++ b/src/tests/memblockq-test.c @@ -32,34 +32,38 @@ int main(int argc, char *argv[]) { int ret; + + pa_mempool *p; pa_memblockq *bq; pa_memchunk chunk1, chunk2, chunk3, chunk4; pa_memblock *silence; pa_log_set_maximal_level(PA_LOG_DEBUG); + + p = pa_mempool_new(0); - silence = pa_memblock_new_fixed((char*) "__", 2, 1, NULL); + silence = pa_memblock_new_fixed(p, (char*) "__", 2, 1); assert(silence); - bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, silence, NULL); + bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, silence); assert(bq); - chunk1.memblock = pa_memblock_new_fixed((char*) "AA", 2, 1, NULL); + chunk1.memblock = pa_memblock_new_fixed(p, (char*) "AA", 2, 1); chunk1.index = 0; chunk1.length = 2; assert(chunk1.memblock); - chunk2.memblock = pa_memblock_new_fixed((char*) "TTBB", 4, 1, NULL); + chunk2.memblock = pa_memblock_new_fixed(p, (char*) "TTBB", 4, 1); chunk2.index = 2; chunk2.length = 2; assert(chunk2.memblock); - chunk3.memblock = pa_memblock_new_fixed((char*) "ZZZZ", 4, 1, NULL); + chunk3.memblock = pa_memblock_new_fixed(p, (char*) "ZZZZ", 4, 1); chunk3.index = 0; chunk3.length = 4; assert(chunk3.memblock); - chunk4.memblock = pa_memblock_new_fixed((char*) "KKKKKKKK", 8, 1, NULL); + chunk4.memblock = pa_memblock_new_fixed(p, (char*) "KKKKKKKK", 8, 1); chunk4.index = 0; chunk4.length = 8; assert(chunk4.memblock); From 35caf0c4eaedbf8553c1fe59e7d3e3438e59a7d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 19:56:51 +0000 Subject: [PATCH 1168/1514] add new test memblock-test for testing SHM import/export git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1268 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 17 +++- src/tests/memblock-test.c | 164 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+), 4 deletions(-) create mode 100644 src/tests/memblock-test.c diff --git a/src/Makefile.am b/src/Makefile.am index 0ab0436b4..c4988d8e8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -197,7 +197,8 @@ noinst_PROGRAMS = \ utf8-test \ get-binary-name-test \ ipacl-test \ - hook-list-test + hook-list-test \ + memblock-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -242,6 +243,11 @@ hook_list_test_CFLAGS = $(AM_CFLAGS) hook_list_test_LDADD = $(AM_LDADD) libpulsecore.la hook_list_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +memblock_test_SOURCES = tests/memblock-test.c +memblock_test_CFLAGS = $(AM_CFLAGS) +memblock_test_LDADD = $(AM_LDADD) libpulsecore.la +memblock_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la @@ -414,7 +420,8 @@ libpulse_la_SOURCES += \ pulsecore/strlist.c pulsecore/strlist.h \ pulsecore/tagstruct.c pulsecore/tagstruct.h \ pulsecore/core-error.c pulsecore/core-error.h \ - pulsecore/winsock.h pulsecore/creds.h + pulsecore/winsock.h pulsecore/creds.h \ + pulsecore/shm.c pulsecore/shm.h if OS_IS_WIN32 libpulse_la_SOURCES += \ @@ -519,7 +526,8 @@ pulsecoreinclude_HEADERS = \ pulsecore/source-output.h \ pulsecore/strbuf.h \ pulsecore/tokenizer.h \ - pulsecore/creds.h + pulsecore/creds.h \ + pulsecore/shm.h lib_LTLIBRARIES += libpulsecore.la @@ -586,7 +594,8 @@ libpulsecore_la_SOURCES += \ pulsecore/tokenizer.c pulsecore/tokenizer.h \ pulsecore/winsock.h \ pulsecore/core-error.c pulsecore/core-error.h \ - pulsecore/hook-list.c pulsecore/hook-list.h + pulsecore/hook-list.c pulsecore/hook-list.h \ + pulsecore/shm.c pulsecore/shm.h if OS_IS_WIN32 libpulsecore_la_SOURCES += \ diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c new file mode 100644 index 000000000..11198ae6b --- /dev/null +++ b/src/tests/memblock-test.c @@ -0,0 +1,164 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +static void release_cb(pa_memimport *i, uint32_t block_id, void *userdata) { + printf("%s: Imported block %u is released.\n", (char*) userdata, block_id); +} + +static void revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) { + printf("%s: Exported block %u is revoked.\n", (char*) userdata, block_id); +} + +static void print_stats(pa_mempool *p, const char *text) { + const pa_mempool_stat*s = pa_mempool_get_stat(p); + + printf("%s = {\n" + "n_allocated = %u\n" + "n_accumulated = %u\n" + "n_imported = %u\n" + "n_exported = %u\n" + "allocated_size = %lu\n" + "accumulated_size = %lu\n" + "imported_size = %lu\n" + "exported_size = %lu\n" + "n_too_large_for_pool = %u\n" + "n_pool_full = %u\n" + "}\n", + text, + s->n_allocated, + s->n_accumulated, + s->n_imported, + s->n_exported, + (unsigned long) s->allocated_size, + (unsigned long) s->accumulated_size, + (unsigned long) s->imported_size, + (unsigned long) s->exported_size, + s->n_too_large_for_pool, + s->n_pool_full); +} + +int main(int argc, char *argv[]) { + pa_mempool *pool_a, *pool_b, *pool_c; + unsigned id_a, id_b, id_c; + pa_memexport *export_a, *export_b; + pa_memimport *import_b, *import_c; + pa_memblock *mb_a, *mb_b, *mb_c; + int r, i; + pa_memblock* blocks[5]; + uint32_t id, shm_id; + size_t offset, size; + + const char txt[] = "This is a test!"; + + pool_a = pa_mempool_new(1); + pool_b = pa_mempool_new(1); + pool_c = pa_mempool_new(1); + + pa_mempool_get_shm_id(pool_a, &id_a); + pa_mempool_get_shm_id(pool_b, &id_b); + pa_mempool_get_shm_id(pool_c, &id_c); + + assert(pool_a && pool_b && pool_c); + + blocks[0] = pa_memblock_new_fixed(pool_a, (void*) txt, sizeof(txt), 1); + blocks[1] = pa_memblock_new(pool_a, sizeof(txt)); + snprintf(blocks[1]->data, blocks[1]->length, "%s", txt); + blocks[2] = pa_memblock_new_pool(pool_a, sizeof(txt)); + snprintf(blocks[2]->data, blocks[2]->length, "%s", txt); + blocks[3] = pa_memblock_new_malloced(pool_a, pa_xstrdup(txt), sizeof(txt)); + blocks[4] = NULL; + + for (i = 0; blocks[i]; i++) { + printf("Memory block %u\n", i); + + mb_a = blocks[i]; + assert(mb_a); + + export_a = pa_memexport_new(pool_a, revoke_cb, (void*) "A"); + export_b = pa_memexport_new(pool_b, revoke_cb, (void*) "B"); + + assert(export_a && export_b); + + import_b = pa_memimport_new(pool_b, release_cb, (void*) "B"); + import_c = pa_memimport_new(pool_c, release_cb, (void*) "C"); + + assert(import_b && import_c); + + r = pa_memexport_put(export_a, mb_a, &id, &shm_id, &offset, &size); + assert(r >= 0); + assert(shm_id == id_a); + + printf("A: Memory block exported as %u\n", id); + + mb_b = pa_memimport_get(import_b, id, shm_id, offset, size); + assert(mb_b); + r = pa_memexport_put(export_b, mb_b, &id, &shm_id, &offset, &size); + assert(r >= 0); + assert(shm_id == id_a || shm_id == id_b); + pa_memblock_unref(mb_b); + + printf("B: Memory block exported as %u\n", id); + + mb_c = pa_memimport_get(import_c, id, shm_id, offset, size); + assert(mb_c); + printf("1 data=%s\n", (char*) mb_c->data); + + print_stats(pool_a, "A"); + print_stats(pool_b, "B"); + print_stats(pool_c, "C"); + + pa_memexport_free(export_b); + printf("2 data=%s\n", (char*) mb_c->data); + pa_memblock_unref(mb_c); + + pa_memimport_free(import_b); + + pa_memblock_unref(mb_a); + + pa_memimport_free(import_c); + pa_memexport_free(export_a); + } + + printf("vaccuuming...\n"); + + pa_mempool_vacuum(pool_a); + pa_mempool_vacuum(pool_b); + pa_mempool_vacuum(pool_c); + + printf("vaccuuming done...\n"); + + pa_mempool_free(pool_a); + pa_mempool_free(pool_b); + pa_mempool_free(pool_c); + + return 0; +} From 8ebef4d00f1868fd968218d594c7993c1c4254b1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 19:57:19 +0000 Subject: [PATCH 1169/1514] look for shm_open in -lrt git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1269 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 68d9d5d52..07b2cfa12 100644 --- a/configure.ac +++ b/configure.ac @@ -206,6 +206,8 @@ AC_SEARCH_LIBS([dlopen], [dl]) # BSD AC_SEARCH_LIBS([connect], [socket]) +AC_SEARCH_LIBS([shm_open], [rt]) + # Non-standard # This magic is needed so we do not needlessly add static libs to the win32 From 666eca38b9db862629c22c858767a14962cbd262 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 19:57:53 +0000 Subject: [PATCH 1170/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1270 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 2 ++ 1 file changed, 2 insertions(+) diff --git a/todo b/todo index 2c67f6d5e..c4bb9b0d3 100644 --- a/todo +++ b/todo @@ -22,6 +22,8 @@ Cleanups: - use software volume when hardware doesn't support all channels (alsa done) - silence generation should be moved into the core to avoid races and code duplication in the backends +- rework resampler to not use pa_xrealloc. Use pa_memblock_new instead. +- allow disabling shm in both client and server Auth/Crypto: - ssl From 1bc62d5ec671bf3edab5263fdc8015c0a701ce81 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 21:26:01 +0000 Subject: [PATCH 1171/1514] rework logging subsystem, to implicitly include __FILE__ in pa_log() calls. In addition we now record the line numbers and function names of pa_log calls. However, those are only shown If $PULSE_LOG_META is set. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1271 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/log.c | 91 +++++++++++++++++++++++---------------------- src/pulsecore/log.h | 49 ++++++++++++++++++++---- 2 files changed, 89 insertions(+), 51 deletions(-) diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 06e95b285..8bc673e59 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -35,12 +35,14 @@ #include #include +#include #include #include "log.h" #define ENV_LOGLEVEL "PULSE_LOG" +#define ENV_LOGMETA "PULSE_LOG_META" static char *log_ident = NULL, *log_ident_local = NULL; static pa_log_target_t log_target = PA_LOG_STDERR; @@ -80,11 +82,19 @@ void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t l, const c user_log_func = func; } -void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { +void pa_log_levelv_meta( + pa_log_level_t level, + const char*file, + int line, + const char *func, + const char *format, + va_list ap) { + const char *e; - char *text, *t, *n; + char *text, *t, *n, *location = pa_xstrdup(""); assert(level < PA_LOG_LEVEL_MAX); + assert(format); if ((e = getenv(ENV_LOGLEVEL))) maximal_level = atoi(e); @@ -94,6 +104,11 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { text = pa_vsprintf_malloc(format, ap); + if (getenv(ENV_LOGMETA) && file && line > 0 && func) + location = pa_sprintf_malloc("[%s:%i %s()] ", file, line, func); + else if (file) + location = pa_sprintf_malloc("%s: ", pa_path_get_filename(file)); + if (!pa_utf8_valid(text)) pa_log_level(level, __FILE__": invalid UTF-8 string following below:"); @@ -126,9 +141,9 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { local_t = pa_utf8_to_locale(t); if (!local_t) - fprintf(stderr, "%s%s%s\n", prefix, t, suffix); + fprintf(stderr, "%s%s%s%s\n", location, prefix, t, suffix); else { - fprintf(stderr, "%s%s%s\n", prefix, local_t, suffix); + fprintf(stderr, "%s%s%s%s\n", location, prefix, local_t, suffix); pa_xfree(local_t); } @@ -143,9 +158,9 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { local_t = pa_utf8_to_locale(t); if (!local_t) - syslog(level_to_syslog[level], "%s", t); + syslog(level_to_syslog[level], "%s%s", location, t); else { - syslog(level_to_syslog[level], "%s", local_t); + syslog(level_to_syslog[level], "%s%s", location, local_t); pa_xfree(local_t); } @@ -154,9 +169,15 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { } #endif - case PA_LOG_USER: - user_log_func(level, t); + case PA_LOG_USER: { + char *x; + + x = pa_sprintf_malloc("%s%s", location, t); + user_log_func(level, x); + pa_xfree(x); + break; + } case PA_LOG_NULL: default: @@ -165,47 +186,29 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { } pa_xfree(text); + pa_xfree(location); +} +void pa_log_level_meta( + pa_log_level_t level, + const char*file, + int line, + const char *func, + const char *format, ...) { + + va_list ap; + va_start(ap, format); + pa_log_levelv_meta(level, file, line, func, format, ap); + va_end(ap); +} + +void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { + pa_log_levelv_meta(level, NULL, 0, NULL, format, ap); } void pa_log_level(pa_log_level_t level, const char *format, ...) { va_list ap; va_start(ap, format); - pa_log_levelv(level, format, ap); - va_end(ap); -} - -void pa_log_debug(const char *format, ...) { - va_list ap; - va_start(ap, format); - pa_log_levelv(PA_LOG_DEBUG, format, ap); - va_end(ap); -} - -void pa_log_info(const char *format, ...) { - va_list ap; - va_start(ap, format); - pa_log_levelv(PA_LOG_INFO, format, ap); - va_end(ap); -} - -void pa_log_notice(const char *format, ...) { - va_list ap; - va_start(ap, format); - pa_log_levelv(PA_LOG_INFO, format, ap); - va_end(ap); -} - -void pa_log_warn(const char *format, ...) { - va_list ap; - va_start(ap, format); - pa_log_levelv(PA_LOG_WARN, format, ap); - va_end(ap); -} - -void pa_log_error(const char *format, ...) { - va_list ap; - va_start(ap, format); - pa_log_levelv(PA_LOG_ERROR, format, ap); + pa_log_levelv_meta(level, NULL, 0, NULL, format, ap); va_end(ap); } diff --git a/src/pulsecore/log.h b/src/pulsecore/log.h index 7bf4e4076..bf0e75f51 100644 --- a/src/pulsecore/log.h +++ b/src/pulsecore/log.h @@ -23,6 +23,7 @@ ***/ #include +#include #include /* A simple logging subsystem */ @@ -53,17 +54,51 @@ void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t t, const c /* Minimal log level */ void pa_log_set_maximal_level(pa_log_level_t l); -/* Do a log line */ -void pa_log_debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); -void pa_log_info(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); -void pa_log_notice(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); -void pa_log_warn(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); -void pa_log_error(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); +void pa_log_level_meta( + pa_log_level_t level, + const char*file, + int line, + const char *func, + const char *format, ...) PA_GCC_PRINTF_ATTR(5,6); +void pa_log_levelv_meta( + pa_log_level_t level, + const char*file, + int line, + const char *func, + const char *format, + va_list ap); void pa_log_level(pa_log_level_t level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); - void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap); +#if __STDC_VERSION__ >= 199901L + +/* ISO varargs available */ + +#define pa_log_debug(...) pa_log_level_meta(PA_LOG_DEBUG, __FILE__, __LINE__, __func__, __VA_ARGS__) +#define pa_log_info(...) pa_log_level_meta(PA_LOG_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__) +#define pa_log_notice(...) pa_log_level_meta(PA_LOG_NOTICE, __FILE__, __LINE__, __func__, __VA_ARGS__) +#define pa_log_warn(...) pa_log_level_meta(PA_LOG_WARN, __FILE__, __LINE__, __func__, __VA_ARGS__) +#define pa_log_error(...) pa_log_level_meta(PA_LOG_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__) + +#else + +#define LOG_FUNC(suffix, level) \ +PA_GCC_UNUSED static void pa_log_##suffix(const char *format, ...) { \ + va_list ap; \ + va_start(ap, format); \ + pa_log_levelv_meta(level, NULL, 0, NULL, format, ap); \ + va_end(ap); \ +} + +LOG_FUNC(debug, PA_LOG_DEBUG) +LOG_FUNC(info, PA_LOG_INFO) +LOG_FUNC(notice, PA_LOG_NOTICE) +LOG_FUNC(warn, PA_LOG_WARN) +LOG_FUNC(error, PA_LOG_ERROR) + +#endif + #define pa_log pa_log_error #endif From e385d93e5aad6a6fce754c00c804ff1d6a6746d4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 21:38:40 +0000 Subject: [PATCH 1172/1514] remove all occurences of pa_logXXX(__FILE__": and replace them by pa_logXXX(" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1272 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/caps.c | 6 +- src/daemon/cmdline.c | 20 +++--- src/daemon/cpulimit.c | 2 +- src/daemon/daemon-conf.c | 12 ++-- src/daemon/main.c | 68 ++++++++++----------- src/modules/alsa-util.c | 22 +++---- src/modules/dbus-util.c | 2 +- src/modules/gconf/module-gconf.c | 14 ++--- src/modules/module-alsa-sink.c | 38 ++++++------ src/modules/module-alsa-source.c | 38 ++++++------ src/modules/module-cli.c | 8 +-- src/modules/module-combine.c | 32 +++++----- src/modules/module-detect.c | 14 ++--- src/modules/module-esound-compat-spawnfd.c | 4 +- src/modules/module-esound-compat-spawnpid.c | 4 +- src/modules/module-esound-sink.c | 24 ++++---- src/modules/module-hal-detect.c | 28 ++++----- src/modules/module-jack-sink.c | 28 ++++----- src/modules/module-jack-source.c | 28 ++++----- src/modules/module-lirc.c | 20 +++--- src/modules/module-match.c | 10 +-- src/modules/module-mmkbd-evdev.c | 28 ++++----- src/modules/module-native-protocol-fd.c | 4 +- src/modules/module-null-sink.c | 6 +- src/modules/module-oss-mmap.c | 52 ++++++++-------- src/modules/module-oss.c | 34 +++++------ src/modules/module-pipe-sink.c | 14 ++--- src/modules/module-pipe-source.c | 14 ++--- src/modules/module-protocol-stub.c | 10 +-- src/modules/module-rescue-streams.c | 18 +++--- src/modules/module-sine.c | 6 +- src/modules/module-solaris.c | 36 +++++------ src/modules/module-tunnel.c | 58 +++++++++--------- src/modules/module-volume-restore.c | 20 +++--- src/modules/module-waveout.c | 24 ++++---- src/modules/module-x11-bell.c | 10 +-- src/modules/module-x11-publish.c | 8 +-- src/modules/module-zeroconf-publish.c | 22 +++---- src/modules/oss-util.c | 32 +++++----- src/modules/rtp/module-rtp-recv.c | 24 ++++---- src/modules/rtp/module-rtp-send.c | 36 +++++------ src/modules/rtp/rtp.c | 18 +++--- src/modules/rtp/sap.c | 16 ++--- src/modules/rtp/sdp.c | 16 ++--- src/pulse/client-conf-x11.c | 4 +- src/pulse/client-conf.c | 2 +- src/pulse/context.c | 8 +-- src/pulse/mainloop-signal.c | 6 +- src/pulse/mainloop.c | 6 +- src/pulse/thread-mainloop.c | 2 +- src/pulse/util.c | 6 +- src/pulsecore/authkey.c | 16 ++--- src/pulsecore/cli.c | 4 +- src/pulsecore/client.c | 8 +-- src/pulsecore/conf-parser.c | 12 ++-- src/pulsecore/core-scache.c | 4 +- src/pulsecore/core-subscribe.c | 6 +- src/pulsecore/core-util.c | 52 ++++++++-------- src/pulsecore/ioline.c | 4 +- src/pulsecore/ipacl.c | 12 ++-- src/pulsecore/memblock.c | 6 +- src/pulsecore/memblockq.c | 4 +- src/pulsecore/modinfo.c | 2 +- src/pulsecore/module.c | 14 ++--- src/pulsecore/pdispatch.c | 4 +- src/pulsecore/pid.c | 28 ++++----- src/pulsecore/protocol-cli.c | 2 +- src/pulsecore/protocol-esound.c | 36 +++++------ src/pulsecore/protocol-http.c | 4 +- src/pulsecore/protocol-native.c | 48 +++++++-------- src/pulsecore/protocol-simple.c | 18 +++--- src/pulsecore/pstream.c | 24 ++++---- src/pulsecore/random.c | 4 +- src/pulsecore/sample-util.c | 4 +- src/pulsecore/shm.c | 18 +++--- src/pulsecore/sink-input.c | 12 ++-- src/pulsecore/sink.c | 6 +- src/pulsecore/socket-client.c | 14 ++--- src/pulsecore/socket-server.c | 38 ++++++------ src/pulsecore/socket-util.c | 6 +- src/pulsecore/sound-file-stream.c | 4 +- src/pulsecore/sound-file.c | 12 ++-- src/pulsecore/source-output.c | 12 ++-- src/pulsecore/source.c | 4 +- src/pulsecore/x11wrap.c | 2 +- src/utils/pacmd.c | 20 +++--- src/utils/pax11publish.c | 2 +- 87 files changed, 714 insertions(+), 714 deletions(-) diff --git a/src/daemon/caps.c b/src/daemon/caps.c index 8ae43fb2a..cebdaebcc 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -54,7 +54,7 @@ void pa_drop_root(void) { if (uid == 0 || geteuid() != 0) return; - pa_log_info(__FILE__": dropping root rights."); + pa_log_info("dropping root rights."); #if defined(HAVE_SETRESUID) setresuid(uid, uid, uid); @@ -96,7 +96,7 @@ int pa_limit_caps(void) { if (cap_set_proc(caps) < 0) goto fail; - pa_log_info(__FILE__": dropped capabilities successfully."); + pa_log_info("dropped capabilities successfully."); r = 0; @@ -121,7 +121,7 @@ int pa_drop_caps(void) { cap_clear(caps); if (cap_set_proc(caps) < 0) { - pa_log(__FILE__": failed to drop capabilities: %s", pa_cstrerror(errno)); + pa_log("failed to drop capabilities: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index e00f290e0..d3fe8e655 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -199,14 +199,14 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_DAEMONIZE: case 'D': if ((conf->daemonize = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --daemonize expects boolean argument"); + pa_log("--daemonize expects boolean argument"); goto fail; } break; case ARG_FAIL: if ((conf->fail = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --fail expects boolean argument"); + pa_log("--fail expects boolean argument"); goto fail; } break; @@ -216,7 +216,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d if (optarg) { if (pa_daemon_conf_set_log_level(conf, optarg) < 0) { - pa_log(__FILE__": --log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."); + pa_log("--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."); goto fail; } } else { @@ -228,21 +228,21 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_HIGH_PRIORITY: if ((conf->high_priority = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --high-priority expects boolean argument"); + pa_log("--high-priority expects boolean argument"); goto fail; } break; case ARG_DISALLOW_MODULE_LOADING: if ((conf->disallow_module_loading = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --disallow-module-loading expects boolean argument"); + pa_log("--disallow-module-loading expects boolean argument"); goto fail; } break; case ARG_USE_PID_FILE: if ((conf->use_pid_file = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --use-pid-file expects boolean argument"); + pa_log("--use-pid-file expects boolean argument"); goto fail; } break; @@ -260,7 +260,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_LOG_TARGET: if (pa_daemon_conf_set_log_target(conf, optarg) < 0) { - pa_log(__FILE__": Invalid log target: use either 'syslog', 'stderr' or 'auto'."); + pa_log("Invalid log target: use either 'syslog', 'stderr' or 'auto'."); goto fail; } break; @@ -279,21 +279,21 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_RESAMPLE_METHOD: if (pa_daemon_conf_set_resample_method(conf, optarg) < 0) { - pa_log(__FILE__": Invalid resample method '%s'.", optarg); + pa_log("Invalid resample method '%s'.", optarg); goto fail; } break; case ARG_SYSTEM: if ((conf->system_instance = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --system expects boolean argument"); + pa_log("--system expects boolean argument"); goto fail; } break; case ARG_NO_CPU_LIMIT: if ((conf->no_cpu_limit = optarg ? pa_parse_boolean(optarg) : 1) < 0) { - pa_log(__FILE__": --no-cpu-limit expects boolean argument"); + pa_log("--no-cpu-limit expects boolean argument"); goto fail; } break; diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index b8740ea0f..d7466b06e 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -172,7 +172,7 @@ int pa_cpu_limit_init(pa_mainloop_api *m) { /* Prepare the main loop pipe */ if (pipe(the_pipe) < 0) { - pa_log(__FILE__": pipe() failed: %s", pa_cstrerror(errno)); + pa_log("pipe() failed: %s", pa_cstrerror(errno)); return -1; } diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 3e585d90d..2cb066971 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -168,7 +168,7 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva assert(filename && lvalue && rvalue && data); if (pa_daemon_conf_set_log_target(c, rvalue) < 0) { - pa_log(__FILE__": [%s:%u] Invalid log target '%s'.", filename, line, rvalue); + pa_log("[%s:%u] Invalid log target '%s'.", filename, line, rvalue); return -1; } @@ -180,7 +180,7 @@ static int parse_log_level(const char *filename, unsigned line, const char *lval assert(filename && lvalue && rvalue && data); if (pa_daemon_conf_set_log_level(c, rvalue) < 0) { - pa_log(__FILE__": [%s:%u] Invalid log level '%s'.", filename, line, rvalue); + pa_log("[%s:%u] Invalid log level '%s'.", filename, line, rvalue); return -1; } @@ -192,7 +192,7 @@ static int parse_resample_method(const char *filename, unsigned line, const char assert(filename && lvalue && rvalue && data); if (pa_daemon_conf_set_resample_method(c, rvalue) < 0) { - pa_log(__FILE__": [%s:%u] Inavalid resample method '%s'.", filename, line, rvalue); + pa_log("[%s:%u] Inavalid resample method '%s'.", filename, line, rvalue); return -1; } @@ -214,14 +214,14 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, } else { int32_t k; if (pa_atoi(rvalue, &k) < 0) { - pa_log(__FILE__": [%s:%u] Inavalid rlimit '%s'.", filename, line, rvalue); + pa_log("[%s:%u] Inavalid rlimit '%s'.", filename, line, rvalue); return -1; } r->is_set = k >= 0; r->value = k >= 0 ? (rlim_t) k : 0; } #else - pa_log_warn(__FILE__": [%s:%u] rlimit not supported on this platform.", filename, line); + pa_log_warn("[%s:%u] rlimit not supported on this platform.", filename, line); #endif return 0; @@ -308,7 +308,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file, "r"); if (!f && errno != ENOENT) { - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno)); + pa_log("WARNING: failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno)); goto finish; } diff --git a/src/daemon/main.c b/src/daemon/main.c index aada0ad79..95ba6dd50 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -117,7 +117,7 @@ static void message_cb(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const s #endif static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, int sig, void *userdata) { - pa_log_info(__FILE__": Got signal %s.", pa_strsignal(sig)); + pa_log_info("Got signal %s.", pa_strsignal(sig)); switch (sig) { #ifdef SIGUSR1 @@ -144,7 +144,7 @@ static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, case SIGINT: case SIGTERM: default: - pa_log_info(__FILE__": Exiting."); + pa_log_info("Exiting."); m->quit(m, 1); break; } @@ -172,34 +172,34 @@ static int change_user(void) { * afterwards. */ if (!(pw = getpwnam(PA_SYSTEM_USER))) { - pa_log(__FILE__": Failed to find user '%s'.", PA_SYSTEM_USER); + pa_log("Failed to find user '%s'.", PA_SYSTEM_USER); return -1; } if (!(gr = getgrnam(PA_SYSTEM_GROUP))) { - pa_log(__FILE__": Failed to find group '%s'.", PA_SYSTEM_GROUP); + pa_log("Failed to find group '%s'.", PA_SYSTEM_GROUP); return -1; } - pa_log_info(__FILE__": Found user '%s' (UID %lu) and group '%s' (GID %lu).", + pa_log_info("Found user '%s' (UID %lu) and group '%s' (GID %lu).", PA_SYSTEM_USER, (unsigned long) pw->pw_uid, PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid); if (pw->pw_gid != gr->gr_gid) { - pa_log(__FILE__": GID of user '%s' and of group '%s' don't match.", PA_SYSTEM_USER, PA_SYSTEM_GROUP); + pa_log("GID of user '%s' and of group '%s' don't match.", PA_SYSTEM_USER, PA_SYSTEM_GROUP); return -1; } if (strcmp(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH) != 0) - pa_log_warn(__FILE__": Warning: home directory of user '%s' is not '%s', ignoring.", PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH); + pa_log_warn("Warning: home directory of user '%s' is not '%s', ignoring.", PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH); if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid) < 0) { - pa_log(__FILE__": Failed to create '%s': %s", PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno)); + pa_log("Failed to create '%s': %s", PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno)); return -1; } if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) { - pa_log(__FILE__": Failed to change group list: %s", pa_cstrerror(errno)); + pa_log("Failed to change group list: %s", pa_cstrerror(errno)); return -1; } @@ -215,7 +215,7 @@ static int change_user(void) { #endif if (r < 0) { - pa_log(__FILE__": Failed to change GID: %s", pa_cstrerror(errno)); + pa_log("Failed to change GID: %s", pa_cstrerror(errno)); return -1; } @@ -231,7 +231,7 @@ static int change_user(void) { #endif if (r < 0) { - pa_log(__FILE__": Failed to change UID: %s", pa_cstrerror(errno)); + pa_log("Failed to change UID: %s", pa_cstrerror(errno)); return -1; } @@ -243,7 +243,7 @@ static int change_user(void) { set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH); set_env("PULSE_CONFIG_PATH", PA_SYSTEM_RUNTIME_PATH); - pa_log_info(__FILE__": Successfully dropped root privileges."); + pa_log_info("Successfully dropped root privileges."); return 0; } @@ -251,7 +251,7 @@ static int change_user(void) { #else /* HAVE_PWD_H && HAVE_GRP_H */ static int change_user(void) { - pa_log(__FILE__": System wide mode unsupported on this platform."); + pa_log("System wide mode unsupported on this platform."); return -1; } @@ -267,7 +267,7 @@ static int create_runtime_dir(void) { * /tmp/ with the current UID/GID */ if (pa_make_secure_dir(fn, 0700, (uid_t)-1, (gid_t)-1) < 0) { - pa_log(__FILE__": Failed to create '%s': %s", fn, pa_cstrerror(errno)); + pa_log("Failed to create '%s': %s", fn, pa_cstrerror(errno)); return -1; } @@ -286,7 +286,7 @@ static void set_one_rlimit(const pa_rlimit *r, int resource, const char *name) { rl.rlim_cur = rl.rlim_max = r->value; if (setrlimit(resource, &rl) < 0) - pa_log_warn(__FILE__": setrlimit(%s, (%u, %u)) failed: %s", name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno)); + pa_log_warn("setrlimit(%s, (%u, %u)) failed: %s", name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno)); } static void set_all_rlimits(const pa_daemon_conf *conf) { @@ -335,7 +335,7 @@ int main(int argc, char *argv[]) { suid_root = !real_root && geteuid() == 0; if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) { - pa_log_warn(__FILE__": WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'."); + pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'."); pa_drop_root(); } #else @@ -368,7 +368,7 @@ int main(int argc, char *argv[]) { goto finish; if (pa_cmdline_parse(conf, argc, argv, &d) < 0) { - pa_log(__FILE__": failed to parse command line."); + pa_log("failed to parse command line."); goto finish; } @@ -414,9 +414,9 @@ int main(int argc, char *argv[]) { pid_t pid; if (pa_pid_file_check_running(&pid) < 0) { - pa_log_info(__FILE__": daemon not running"); + pa_log_info("daemon not running"); } else { - pa_log_info(__FILE__": daemon running as PID %u", pid); + pa_log_info("daemon running as PID %u", pid); retval = 0; } @@ -426,7 +426,7 @@ int main(int argc, char *argv[]) { case PA_CMD_KILL: if (pa_pid_file_kill(SIGINT, NULL) < 0) - pa_log(__FILE__": failed to kill daemon."); + pa_log("failed to kill daemon."); else retval = 0; @@ -437,9 +437,9 @@ int main(int argc, char *argv[]) { } if (real_root && !conf->system_instance) { - pa_log_warn(__FILE__": This program is not intended to be run as root (unless --system is specified)."); + pa_log_warn("This program is not intended to be run as root (unless --system is specified)."); } else if (!real_root && conf->system_instance) { - pa_log(__FILE__": Root priviliges required."); + pa_log("Root priviliges required."); goto finish; } @@ -448,18 +448,18 @@ int main(int argc, char *argv[]) { int tty_fd; if (pa_stdio_acquire() < 0) { - pa_log(__FILE__": failed to acquire stdio."); + pa_log("failed to acquire stdio."); goto finish; } #ifdef HAVE_FORK if (pipe(daemon_pipe) < 0) { - pa_log(__FILE__": failed to create pipe."); + pa_log("failed to create pipe."); goto finish; } if ((child = fork()) < 0) { - pa_log(__FILE__": fork() failed: %s", pa_cstrerror(errno)); + pa_log("fork() failed: %s", pa_cstrerror(errno)); goto finish; } @@ -470,14 +470,14 @@ int main(int argc, char *argv[]) { daemon_pipe[1] = -1; if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL) != sizeof(retval)) { - pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno)); + pa_log("read() failed: %s", pa_cstrerror(errno)); retval = 1; } if (retval) - pa_log(__FILE__": daemon startup failed."); + pa_log("daemon startup failed."); else - pa_log_info(__FILE__": daemon startup successful."); + pa_log_info("daemon startup successful."); goto finish; } @@ -537,7 +537,7 @@ int main(int argc, char *argv[]) { if (conf->use_pid_file) { if (pa_pid_file_create() < 0) { - pa_log(__FILE__": pa_pid_file_create() failed."); + pa_log("pa_pid_file_create() failed."); #ifdef HAVE_FORK if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); @@ -604,13 +604,13 @@ int main(int argc, char *argv[]) { pa_xfree(s); if (r < 0 && conf->fail) { - pa_log(__FILE__": failed to initialize daemon."); + pa_log("failed to initialize daemon."); #ifdef HAVE_FORK if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); #endif } else if (!c->modules || pa_idxset_size(c->modules) == 0) { - pa_log(__FILE__": daemon startup without any loaded modules, refusing to work."); + pa_log("daemon startup without any loaded modules, refusing to work."); #ifdef HAVE_FORK if (conf->daemonize) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); @@ -634,10 +634,10 @@ int main(int argc, char *argv[]) { pa_log_error("%s : Fatal error. Default sink name (%s) does not exist in name register.", __FILE__, c->default_sink_name); retval = 1; } else { - pa_log_info(__FILE__": Daemon startup complete."); + pa_log_info("Daemon startup complete."); if (pa_mainloop_run(mainloop, &retval) < 0) retval = 1; - pa_log_info(__FILE__": Daemon shutdown initiated."); + pa_log_info("Daemon shutdown initiated."); } } @@ -653,7 +653,7 @@ int main(int argc, char *argv[]) { pa_signal_done(); pa_mainloop_free(mainloop); - pa_log_info(__FILE__": Daemon terminated."); + pa_log_info("Daemon terminated."); finish: diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 39ddbfe95..d8b6c5ccc 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -88,7 +88,7 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io err = snd_mixer_poll_descriptors_revents(fdl->mixer, fdl->work_fds, fdl->num_fds, &revents); if (err < 0) { - pa_log_error(__FILE__": Unable to get poll revent: %s", + pa_log_error("Unable to get poll revent: %s", snd_strerror(err)); return; } @@ -135,7 +135,7 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u err = snd_mixer_poll_descriptors(fdl->mixer, fdl->work_fds, num_fds); if (err < 0) { - pa_log_error(__FILE__": Unable to get poll descriptors: %s", + pa_log_error("Unable to get poll descriptors: %s", snd_strerror(err)); return; } @@ -343,7 +343,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p goto finish; if (ss->rate != r) { - pa_log_warn(__FILE__": device doesn't support %u Hz, changed to %u Hz.", ss->rate, r); + pa_log_warn("device doesn't support %u Hz, changed to %u Hz.", ss->rate, r); /* If the sample rate deviates too much, we need to resample */ if (r < ss->rate*.95 || r > ss->rate*1.05) @@ -351,12 +351,12 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p } if (ss->channels != c) { - pa_log_warn(__FILE__": device doesn't support %u channels, changed to %u.", ss->channels, c); + pa_log_warn("device doesn't support %u channels, changed to %u.", ss->channels, c); ss->channels = c; } if (ss->format != f) { - pa_log_warn(__FILE__": device doesn't support sample format %s, changed to %s.", pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f)); + pa_log_warn("device doesn't support sample format %s, changed to %s.", pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f)); ss->format = f; } @@ -387,17 +387,17 @@ int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) { assert(mixer && dev); if ((err = snd_mixer_attach(mixer, dev)) < 0) { - pa_log_warn(__FILE__": Unable to attach to mixer %s: %s", dev, snd_strerror(err)); + pa_log_warn("Unable to attach to mixer %s: %s", dev, snd_strerror(err)); return -1; } if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) { - pa_log_warn(__FILE__": Unable to register mixer: %s", snd_strerror(err)); + pa_log_warn("Unable to register mixer: %s", snd_strerror(err)); return -1; } if ((err = snd_mixer_load(mixer)) < 0) { - pa_log_warn(__FILE__": Unable to load mixer: %s", snd_strerror(err)); + pa_log_warn("Unable to load mixer: %s", snd_strerror(err)); return -1; } @@ -415,18 +415,18 @@ snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const snd_mixer_selem_id_set_name(sid, name); if (!(elem = snd_mixer_find_selem(mixer, sid))) { - pa_log_warn(__FILE__": Cannot find mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); + pa_log_warn("Cannot find mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); if (fallback) { snd_mixer_selem_id_set_name(sid, fallback); if (!(elem = snd_mixer_find_selem(mixer, sid))) - pa_log_warn(__FILE__": Cannot find fallback mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); + pa_log_warn("Cannot find fallback mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); } } if (elem) - pa_log_info(__FILE__": Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); + pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); return elem; } diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c index e4bd2c3ec..165ccff6a 100644 --- a/src/modules/dbus-util.c +++ b/src/modules/dbus-util.c @@ -93,7 +93,7 @@ static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, assert(fd == dbus_watch_get_fd(watch)); if (!dbus_watch_get_enabled(watch)) { - pa_log_warn(__FILE__": Asked to handle disabled watch: %p %i", + pa_log_warn("Asked to handle disabled watch: %p %i", (void *) watch, fd); return; } diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index a61295e06..d9f649fd1 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -96,7 +96,7 @@ static int fill_buf(struct userdata *u) { assert(u); if (u->buf_fill >= BUF_MAX) { - pa_log(__FILE__": read buffer overflow"); + pa_log("read buffer overflow"); return -1; } @@ -148,7 +148,7 @@ static void unload_one_module(struct userdata *u, struct module_info*m, unsigned if (m->items[i].index == PA_INVALID_INDEX) return; - pa_log_debug(__FILE__": Unloading module #%i", m->items[i].index); + pa_log_debug("Unloading module #%i", m->items[i].index); pa_module_unload_by_index(u->core, m->items[i].index); m->items[i].index = PA_INVALID_INDEX; pa_xfree(m->items[i].name); @@ -192,14 +192,14 @@ static void load_module( unload_one_module(u, m, i); } - pa_log_debug(__FILE__": Loading module '%s' with args '%s' due to GConf configuration.", name, args); + pa_log_debug("Loading module '%s' with args '%s' due to GConf configuration.", name, args); m->items[i].name = pa_xstrdup(name); m->items[i].args = pa_xstrdup(args); m->items[i].index = PA_INVALID_INDEX; if (!(mod = pa_module_load(u->core, name, args))) { - pa_log(__FILE__": pa_module_load() failed"); + pa_log("pa_module_load() failed"); return; } @@ -308,7 +308,7 @@ static int handle_event(struct userdata *u) { return ret; fail: - pa_log(__FILE__": Unable to read or parse data from client."); + pa_log("Unable to read or parse data from client."); return -1; } @@ -337,12 +337,12 @@ static int start_client(const char *n, pid_t *pid) { int pipe_fds[2] = { -1, -1 }; if (pipe(pipe_fds) < 0) { - pa_log(__FILE__": pipe() failed: %s", pa_cstrerror(errno)); + pa_log("pipe() failed: %s", pa_cstrerror(errno)); goto fail; } if ((child = fork()) == (pid_t) -1) { - pa_log(__FILE__": fork() failed: %s", pa_cstrerror(errno)); + pa_log("fork() failed: %s", pa_cstrerror(errno)); goto fail; } else if (child != 0) { diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 0cebd50f1..6ff9a6e49 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -125,10 +125,10 @@ static int xrun_recovery(struct userdata *u) { int ret; assert(u); - pa_log_info(__FILE__": *** ALSA-XRUN (playback) ***"); + pa_log_info("*** ALSA-XRUN (playback) ***"); if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) { - pa_log(__FILE__": snd_pcm_prepare() failed: %s", snd_strerror(-ret)); + pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); clear_up(u); pa_module_unload_request(u->module); @@ -169,7 +169,7 @@ static void do_write(struct userdata *u) { continue; } - pa_log(__FILE__": snd_pcm_writei() failed: %s", snd_strerror(-frames)); + pa_log("snd_pcm_writei() failed: %s", snd_strerror(-frames)); clear_up(u); pa_module_unload_request(u->module); @@ -233,7 +233,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { assert(s && u && u->sink); if ((err = snd_pcm_delay(u->pcm_handle, &frames)) < 0) { - pa_log(__FILE__": failed to get delay: %s", snd_strerror(err)); + pa_log("failed to get delay: %s", snd_strerror(err)); s->get_latency = NULL; return 0; } @@ -275,7 +275,7 @@ static int sink_get_hw_volume_cb(pa_sink *s) { return 0; fail: - pa_log_error(__FILE__": Unable to read volume: %s", snd_strerror(err)); + pa_log_error("Unable to read volume: %s", snd_strerror(err)); s->get_hw_volume = NULL; s->set_hw_volume = NULL; return -1; @@ -309,7 +309,7 @@ static int sink_set_hw_volume_cb(pa_sink *s) { return 0; fail: - pa_log_error(__FILE__": Unable to set volume: %s", snd_strerror(err)); + pa_log_error("Unable to set volume: %s", snd_strerror(err)); s->get_hw_volume = NULL; s->set_hw_volume = NULL; return -1; @@ -323,7 +323,7 @@ static int sink_get_hw_mute_cb(pa_sink *s) { err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw); if (err) { - pa_log_error(__FILE__": Unable to get switch: %s", snd_strerror(err)); + pa_log_error("Unable to get switch: %s", snd_strerror(err)); s->get_hw_mute = NULL; s->set_hw_mute = NULL; return -1; @@ -342,7 +342,7 @@ static int sink_set_hw_mute_cb(pa_sink *s) { err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->hw_muted); if (err) { - pa_log_error(__FILE__": Unable to set switch: %s", snd_strerror(err)); + pa_log_error("Unable to set switch: %s", snd_strerror(err)); s->get_hw_mute = NULL; s->set_hw_mute = NULL; return -1; @@ -369,13 +369,13 @@ int pa__init(pa_core *c, pa_module*m) { int namereg_fail; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { - pa_log(__FILE__": failed to parse sample specification and channel map"); + pa_log("failed to parse sample specification and channel map"); goto fail; } @@ -386,7 +386,7 @@ int pa__init(pa_core *c, pa_module*m) { fragsize = pa_bytes_per_second(&ss)/128; if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { - pa_log(__FILE__": failed to parse buffer metrics"); + pa_log("failed to parse buffer metrics"); goto fail; } period_size = fragsize/frame_size; @@ -397,18 +397,18 @@ int pa__init(pa_core *c, pa_module*m) { snd_config_update_free_global(); if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { - pa_log(__FILE__": Error opening PCM device %s: %s", dev, snd_strerror(err)); + pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); goto fail; } if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 || (err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) { - pa_log(__FILE__": Error fetching PCM info: %s", snd_strerror(err)); + pa_log("Error fetching PCM info: %s", snd_strerror(err)); goto fail; } if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) { - pa_log(__FILE__": Failed to set hardware parameters: %s", snd_strerror(err)); + pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); goto fail; } @@ -417,7 +417,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) { - pa_log(__FILE__": Error opening mixer: %s", snd_strerror(err)); + pa_log("Error opening mixer: %s", snd_strerror(err)); goto fail; } @@ -435,7 +435,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map))) { - pa_log(__FILE__": Failed to create sink object"); + pa_log("Failed to create sink object"); goto fail; } @@ -471,7 +471,7 @@ int pa__init(pa_core *c, pa_module*m) { u->pcm_fdl = pa_alsa_fdlist_new(); assert(u->pcm_fdl); if (pa_alsa_fdlist_init_pcm(u->pcm_fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) { - pa_log(__FILE__": failed to initialise file descriptor monitoring"); + pa_log("failed to initialise file descriptor monitoring"); goto fail; } @@ -479,7 +479,7 @@ int pa__init(pa_core *c, pa_module*m) { u->mixer_fdl = pa_alsa_fdlist_new(); assert(u->mixer_fdl); if (pa_alsa_fdlist_init_mixer(u->mixer_fdl, u->mixer_handle, c->mainloop) < 0) { - pa_log(__FILE__": failed to initialise file descriptor monitoring"); + pa_log("failed to initialise file descriptor monitoring"); goto fail; } snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback); @@ -490,7 +490,7 @@ int pa__init(pa_core *c, pa_module*m) { u->frame_size = frame_size; u->fragment_size = period_size * frame_size; - pa_log_info(__FILE__": using %u fragments of size %lu bytes.", periods, (long unsigned)u->fragment_size); + pa_log_info("using %u fragments of size %lu bytes.", periods, (long unsigned)u->fragment_size); u->silence.memblock = pa_memblock_new(c->mempool, u->silence.length = u->fragment_size); assert(u->silence.memblock); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index c3979df17..aa0666f10 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -126,10 +126,10 @@ static int xrun_recovery(struct userdata *u) { int ret; assert(u); - pa_log_info(__FILE__": *** ALSA-XRUN (capture) ***"); + pa_log_info("*** ALSA-XRUN (capture) ***"); if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) { - pa_log(__FILE__": snd_pcm_prepare() failed: %s", snd_strerror(-ret)); + pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); clear_up(u); pa_module_unload_request(u->module); @@ -172,7 +172,7 @@ static void do_read(struct userdata *u) { continue; } - pa_log(__FILE__": snd_pcm_readi() failed: %s", snd_strerror(-frames)); + pa_log("snd_pcm_readi() failed: %s", snd_strerror(-frames)); clear_up(u); pa_module_unload_request(u->module); @@ -238,7 +238,7 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { assert(s && u && u->source); if (snd_pcm_delay(u->pcm_handle, &frames) < 0) { - pa_log(__FILE__": failed to get delay"); + pa_log("failed to get delay"); s->get_latency = NULL; return 0; } @@ -272,7 +272,7 @@ static int source_get_hw_volume_cb(pa_source *s) { return 0; fail: - pa_log_error(__FILE__": Unable to read volume: %s", snd_strerror(err)); + pa_log_error("Unable to read volume: %s", snd_strerror(err)); s->get_hw_volume = NULL; s->set_hw_volume = NULL; return -1; @@ -303,7 +303,7 @@ static int source_set_hw_volume_cb(pa_source *s) { return 0; fail: - pa_log_error(__FILE__": Unable to set volume: %s", snd_strerror(err)); + pa_log_error("Unable to set volume: %s", snd_strerror(err)); s->get_hw_volume = NULL; s->set_hw_volume = NULL; return -1; @@ -317,7 +317,7 @@ static int source_get_hw_mute_cb(pa_source *s) { err = snd_mixer_selem_get_capture_switch(u->mixer_elem, 0, &sw); if (err) { - pa_log_error(__FILE__": Unable to get switch: %s", snd_strerror(err)); + pa_log_error("Unable to get switch: %s", snd_strerror(err)); s->get_hw_mute = NULL; s->set_hw_mute = NULL; return -1; @@ -336,7 +336,7 @@ static int source_set_hw_mute_cb(pa_source *s) { err = snd_mixer_selem_set_capture_switch_all(u->mixer_elem, !s->hw_muted); if (err) { - pa_log_error(__FILE__": Unable to set switch: %s", snd_strerror(err)); + pa_log_error("Unable to set switch: %s", snd_strerror(err)); s->get_hw_mute = NULL; s->set_hw_mute = NULL; return -1; @@ -363,13 +363,13 @@ int pa__init(pa_core *c, pa_module*m) { int namereg_fail; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { - pa_log(__FILE__": failed to parse sample specification"); + pa_log("failed to parse sample specification"); goto fail; } @@ -380,7 +380,7 @@ int pa__init(pa_core *c, pa_module*m) { fragsize = pa_bytes_per_second(&ss)/128; if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { - pa_log(__FILE__": failed to parse buffer metrics"); + pa_log("failed to parse buffer metrics"); goto fail; } period_size = fragsize/frame_size; @@ -391,18 +391,18 @@ int pa__init(pa_core *c, pa_module*m) { snd_config_update_free_global(); if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { - pa_log(__FILE__": Error opening PCM device %s: %s", dev, snd_strerror(err)); + pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); goto fail; } if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 || (err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) { - pa_log(__FILE__": Error fetching PCM info: %s", snd_strerror(err)); + pa_log("Error fetching PCM info: %s", snd_strerror(err)); goto fail; } if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) { - pa_log(__FILE__": Failed to set hardware parameters: %s", snd_strerror(err)); + pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); goto fail; } @@ -411,7 +411,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) { - pa_log(__FILE__": Error opening mixer: %s", snd_strerror(err)); + pa_log("Error opening mixer: %s", snd_strerror(err)); goto fail; } @@ -429,7 +429,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map))) { - pa_log(__FILE__": Failed to create source object"); + pa_log("Failed to create source object"); goto fail; } @@ -465,7 +465,7 @@ int pa__init(pa_core *c, pa_module*m) { u->pcm_fdl = pa_alsa_fdlist_new(); assert(u->pcm_fdl); if (pa_alsa_fdlist_init_pcm(u->pcm_fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) { - pa_log(__FILE__": failed to initialise file descriptor monitoring"); + pa_log("failed to initialise file descriptor monitoring"); goto fail; } @@ -473,7 +473,7 @@ int pa__init(pa_core *c, pa_module*m) { u->mixer_fdl = pa_alsa_fdlist_new(); assert(u->mixer_fdl); if (pa_alsa_fdlist_init_mixer(u->mixer_fdl, u->mixer_handle, c->mainloop) < 0) { - pa_log(__FILE__": failed to initialise file descriptor monitoring"); + pa_log("failed to initialise file descriptor monitoring"); goto fail; } snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback); @@ -484,7 +484,7 @@ int pa__init(pa_core *c, pa_module*m) { u->frame_size = frame_size; u->fragment_size = period_size * frame_size; - pa_log_info(__FILE__": using %u fragments of size %lu bytes.", periods, (long unsigned) u->fragment_size); + pa_log_info("using %u fragments of size %lu bytes.", periods, (long unsigned) u->fragment_size); u->memchunk.memblock = NULL; u->memchunk.index = u->memchunk.length = 0; diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c index 2eef5c46d..d5374838b 100644 --- a/src/modules/module-cli.c +++ b/src/modules/module-cli.c @@ -73,22 +73,22 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (c->running_as_daemon) { - pa_log_info(__FILE__": Running as daemon, refusing to load this module."); + pa_log_info("Running as daemon, refusing to load this module."); return 0; } if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "exit_on_eof", &exit_on_eof) < 0) { - pa_log(__FILE__": exit_on_eof= expects boolean argument."); + pa_log("exit_on_eof= expects boolean argument."); goto fail; } if (pa_stdio_acquire() < 0) { - pa_log(__FILE__": STDIN/STDUSE already in use."); + pa_log("STDIN/STDUSE already in use."); goto fail; } diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 5243975b5..217fdae62 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -124,7 +124,7 @@ static void adjust_rates(struct userdata *u) { target_latency = max_sink_latency > min_total_latency ? max_sink_latency : min_total_latency; - pa_log_info(__FILE__": [%s] target latency is %0.0f usec.", u->sink->name, (float) target_latency); + pa_log_info("[%s] target latency is %0.0f usec.", u->sink->name, (float) target_latency); base_rate = u->sink->sample_spec.rate; @@ -137,9 +137,9 @@ static void adjust_rates(struct userdata *u) { r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/ 1000000); if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) - pa_log_warn(__FILE__": [%s] sample rates too different, not adjusting (%u vs. %u).", o->sink_input->name, base_rate, r); + pa_log_warn("[%s] sample rates too different, not adjusting (%u vs. %u).", o->sink_input->name, base_rate, r); else { - pa_log_info(__FILE__": [%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.", o->sink_input->name, r, (double) r / base_rate, (float) o->total_latency); + pa_log_info("[%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.", o->sink_input->name, r, (double) r / base_rate, (float) o->total_latency); pa_sink_input_set_rate(o->sink_input, r); } } @@ -323,13 +323,13 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } if ((rm = pa_modargs_get_value(ma, "resample_method", NULL))) { if ((resample_method = pa_parse_resample_method(rm)) < 0) { - pa_log(__FILE__": invalid resample method '%s'", rm); + pa_log("invalid resample method '%s'", rm); goto fail; } } @@ -346,23 +346,23 @@ int pa__init(pa_core *c, pa_module*m) { PA_LLIST_HEAD_INIT(struct output, u->outputs); if (pa_modargs_get_value_u32(ma, "adjust_time", &u->adjust_time) < 0) { - pa_log(__FILE__": failed to parse adjust_time value"); + pa_log("failed to parse adjust_time value"); goto fail; } if (!(master_name = pa_modargs_get_value(ma, "master", NULL)) || !(slaves = pa_modargs_get_value(ma, "slaves", NULL))) { - pa_log(__FILE__": no master or slave sinks specified"); + pa_log("no master or slave sinks specified"); goto fail; } if (!(master_sink = pa_namereg_get(c, master_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": invalid master sink '%s'", master_name); + pa_log("invalid master sink '%s'", master_name); goto fail; } ss = master_sink->sample_spec; if ((pa_modargs_get_sample_spec(ma, &ss) < 0)) { - pa_log(__FILE__": invalid sample specification."); + pa_log("invalid sample specification."); goto fail; } @@ -372,17 +372,17 @@ int pa__init(pa_core *c, pa_module*m) { pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_DEFAULT); if ((pa_modargs_get_channel_map(ma, &map) < 0)) { - pa_log(__FILE__": invalid channel map."); + pa_log("invalid channel map."); goto fail; } if (ss.channels != map.channels) { - pa_log(__FILE__": channel map and sample specification don't match."); + pa_log("channel map and sample specification don't match."); goto fail; } if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { - pa_log(__FILE__": failed to create sink"); + pa_log("failed to create sink"); goto fail; } @@ -392,7 +392,7 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->userdata = u; if (!(u->master = output_new(u, master_sink, resample_method))) { - pa_log(__FILE__": failed to create master sink input on sink '%s'.", u->sink->name); + pa_log("failed to create master sink input on sink '%s'.", u->sink->name); goto fail; } @@ -401,20 +401,20 @@ int pa__init(pa_core *c, pa_module*m) { pa_sink *slave_sink; if (!(slave_sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": invalid slave sink '%s'", n); + pa_log("invalid slave sink '%s'", n); goto fail; } pa_xfree(n); if (!output_new(u, slave_sink, resample_method)) { - pa_log(__FILE__": failed to create slave sink input on sink '%s'.", slave_sink->name); + pa_log("failed to create slave sink input on sink '%s'.", slave_sink->name); goto fail; } } if (u->n_outputs <= 1) - pa_log_warn(__FILE__": WARNING: no slave sinks specified."); + pa_log_warn("WARNING: no slave sinks specified."); if (u->adjust_time > 0) { pa_gettimeofday(&tv); diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index ebafa10df..84ccd14cb 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -57,7 +57,7 @@ static int detect_alsa(pa_core *c, int just_one) { if (!(f = fopen("/proc/asound/devices", "r"))) { if (errno != ENOENT) - pa_log_error(__FILE__": open(\"/proc/asound/devices\") failed: %s", pa_cstrerror(errno)); + pa_log_error("open(\"/proc/asound/devices\") failed: %s", pa_cstrerror(errno)); return -1; } @@ -120,7 +120,7 @@ static int detect_oss(pa_core *c, int just_one) { !(f = fopen("/proc/asound/oss/sndstat", "r"))) { if (errno != ENOENT) - pa_log_error(__FILE__": failed to open OSS sndstat device: %s", pa_cstrerror(errno)); + pa_log_error("failed to open OSS sndstat device: %s", pa_cstrerror(errno)); return -1; } @@ -182,7 +182,7 @@ static int detect_solaris(pa_core *c, int just_one) { if (stat(dev, &s) < 0) { if (errno != ENOENT) - pa_log_error(__FILE__": failed to open device %s: %s", dev, pa_cstrerror(errno)); + pa_log_error("failed to open device %s: %s", dev, pa_cstrerror(errno)); return -1; } @@ -224,12 +224,12 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } if (pa_modargs_get_value_boolean(ma, "just-one", &just_one) < 0) { - pa_log(__FILE__": just_one= expects a boolean argument."); + pa_log("just_one= expects a boolean argument."); goto fail; } @@ -246,11 +246,11 @@ int pa__init(pa_core *c, pa_module*m) { if ((n = detect_waveout(c, just_one)) <= 0) #endif { - pa_log_warn(__FILE__": failed to detect any sound hardware."); + pa_log_warn("failed to detect any sound hardware."); goto fail; } - pa_log_info(__FILE__": loaded %i modules.", n); + pa_log_info("loaded %i modules.", n); /* We were successful and can unload ourselves now. */ pa_module_unload_request(m); diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index 54e090e4c..263e81f93 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -55,12 +55,12 @@ int pa__init(pa_core *c, pa_module*m) { if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || pa_modargs_get_value_s32(ma, "fd", &fd) < 0 || fd < 0) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto finish; } if (pa_loop_write(fd, &x, sizeof(x), NULL) != sizeof(x)) - pa_log(__FILE__": WARNING: write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno)); + pa_log("WARNING: write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno)); close(fd); diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index 3108baf7f..7a662c2df 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -55,12 +55,12 @@ int pa__init(pa_core *c, pa_module*m) { if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || pa_modargs_get_value_u32(ma, "pid", &pid) < 0 || !pid) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto finish; } if (kill(pid, SIGUSR1) < 0) - pa_log(__FILE__": WARNING: kill(%u) failed: %s", pid, pa_cstrerror(errno)); + pa_log("WARNING: kill(%u) failed: %s", pid, pa_cstrerror(errno)); pa_module_unload_request(m); diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index c774d8c1b..6d4a84891 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -129,7 +129,7 @@ static int do_write(struct userdata *u) { assert(u->write_index < u->write_length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) <= 0) { - pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); + pa_log("write() failed: %s", pa_cstrerror(errno)); return -1; } @@ -151,7 +151,7 @@ static int do_write(struct userdata *u) { assert(u->memchunk.memblock && u->memchunk.length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { - pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); + pa_log("write() failed: %s", pa_cstrerror(errno)); return -1; } @@ -176,7 +176,7 @@ static int handle_response(struct userdata *u) { /* Process auth data */ if (!*(int32_t*) u->read_data) { - pa_log(__FILE__": Authentication failed: %s", pa_cstrerror(errno)); + pa_log("Authentication failed: %s", pa_cstrerror(errno)); return -1; } @@ -201,7 +201,7 @@ static int handle_response(struct userdata *u) { /* Process latency info */ u->latency = (pa_usec_t) ((double) (*(int32_t*) u->read_data) * 1000000 / 44100); if (u->latency > 10000000) { - pa_log(__FILE__": WARNING! Invalid latency information received from server"); + pa_log("WARNING! Invalid latency information received from server"); u->latency = 0; } @@ -246,7 +246,7 @@ static int do_read(struct userdata *u) { assert(u->read_index < u->read_length); if ((r = pa_iochannel_read(u->io, (uint8_t*) u->read_data + u->read_index, u->read_length - u->read_index)) <= 0) { - pa_log(__FILE__": read() failed: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); + pa_log("read() failed: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); cancel(u); return -1; } @@ -306,7 +306,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, vo u->client = NULL; if (!io) { - pa_log(__FILE__": connection failed: %s", pa_cstrerror(errno)); + pa_log("connection failed: %s", pa_cstrerror(errno)); cancel(u); return; } @@ -325,19 +325,19 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": invalid sample format specification"); + pa_log("invalid sample format specification"); goto fail; } if ((ss.format != PA_SAMPLE_U8 && ss.format != PA_SAMPLE_S16NE) || (ss.channels > 2)) { - pa_log(__FILE__": esound sample type support is limited to mono/stereo and U8 or S16NE sample data"); + pa_log("esound sample type support is limited to mono/stereo and U8 or S16NE sample data"); goto fail; } @@ -358,12 +358,12 @@ int pa__init(pa_core *c, pa_module*m) { u->latency = 0; if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { - pa_log(__FILE__": failed to create sink."); + pa_log("failed to create sink."); goto fail; } if (!(u->client = pa_socket_client_new_string(u->core->mainloop, p = pa_modargs_get_value(ma, "server", ESD_UNIX_SOCKET_NAME), ESD_DEFAULT_PORT))) { - pa_log(__FILE__": failed to connect to server."); + pa_log("failed to connect to server."); goto fail; } pa_socket_client_set_callback(u->client, on_connection, u); @@ -371,7 +371,7 @@ int pa__init(pa_core *c, pa_module*m) { /* Prepare the initial request */ u->write_data = pa_xmalloc(u->write_length = ESD_KEY_LEN + sizeof(int32_t)); if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", ".esd_auth"), u->write_data, ESD_KEY_LEN) < 0) { - pa_log(__FILE__": failed to load cookie"); + pa_log("failed to load cookie"); goto fail; } *(int32_t*) ((uint8_t*) u->write_data + ESD_KEY_LEN) = ESD_ENDIAN_KEY; diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 825fa96ce..8232cd383 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -287,11 +287,11 @@ static int hal_device_add_all(struct userdata *u, capability_t capability) assert(capability < CAP_MAX); - pa_log_info(__FILE__": Trying capability %u (%s)", capability, cap); + pa_log_info("Trying capability %u (%s)", capability, cap); dbus_error_init(&error); udis = libhal_find_device_by_capability(u->ctx, cap, &n, &error); if (dbus_error_is_set(&error)) { - pa_log_error(__FILE__": Error finding devices: %s: %s", error.name, + pa_log_error("Error finding devices: %s: %s", error.name, error.message); dbus_error_free(&error); return -1; @@ -301,7 +301,7 @@ static int hal_device_add_all(struct userdata *u, capability_t capability) for (i = 0; i < n; ++i) { r = hal_device_add(u, udis[i], &error); if (dbus_error_is_set(&error)) { - pa_log_error(__FILE__": Error adding device: %s: %s", error.name, + pa_log_error("Error adding device: %s: %s", error.name, error.message); dbus_error_free(&error); count = -1; @@ -338,7 +338,7 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, hal_device_add(td->u, td->udi, &error); if (dbus_error_is_set(&error)) { - pa_log_error(__FILE__": Error adding device: %s: %s", error.name, + pa_log_error("Error adding device: %s: %s", error.name, error.message); dbus_error_free(&error); } @@ -357,12 +357,12 @@ static void device_added_cb(LibHalContext *ctx, const char *udi) struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); const char* cap = get_capability_name(u->capability); - pa_log_debug(__FILE__": HAL Device added: %s", udi); + pa_log_debug("HAL Device added: %s", udi); dbus_error_init(&error); has_cap = device_has_capability(ctx, udi, cap, &error); if (dbus_error_is_set(&error)) { - pa_log_error(__FILE__": Error getting capability: %s: %s", error.name, + pa_log_error("Error getting capability: %s: %s", error.name, error.message); dbus_error_free(&error); return; @@ -388,7 +388,7 @@ static void device_removed_cb(LibHalContext* ctx, const char *udi) struct device *d; struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); - pa_log_debug(__FILE__": Device removed: %s", udi); + pa_log_debug("Device removed: %s", udi); if ((d = pa_hashmap_remove(u->devices, udi))) { pa_module_unload_by_index(u->core, d->index); hal_device_free(d); @@ -456,18 +456,18 @@ static LibHalContext* pa_hal_context_new(pa_core* c, DBusConnection *conn) dbus_error_init(&error); if (!(hal_ctx = libhal_ctx_new())) { - pa_log_error(__FILE__": libhal_ctx_new() failed"); + pa_log_error("libhal_ctx_new() failed"); goto fail; } if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) { - pa_log_error(__FILE__": Error establishing DBUS connection: %s: %s", + pa_log_error("Error establishing DBUS connection: %s: %s", error.name, error.message); goto fail; } if (!libhal_ctx_init(hal_ctx, &error)) { - pa_log_error(__FILE__": Couldn't connect to hald: %s: %s", + pa_log_error("Couldn't connect to hald: %s: %s", error.name, error.message); goto fail; } @@ -496,7 +496,7 @@ int pa__init(pa_core *c, pa_module*m) { dbus_error_init(&error); if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error))) { - pa_log_error(__FILE__": Unable to contact DBUS system bus: %s: %s", + pa_log_error("Unable to contact DBUS system bus: %s: %s", error.name, error.message); dbus_error_free(&error); return -1; @@ -522,7 +522,7 @@ int pa__init(pa_core *c, pa_module*m) { if ((n = hal_device_add_all(u, CAP_OSS)) <= 0) #endif { - pa_log_warn(__FILE__": failed to detect any sound hardware."); + pa_log_warn("failed to detect any sound hardware."); userdata_free(u); return -1; } @@ -536,14 +536,14 @@ int pa__init(pa_core *c, pa_module*m) { dbus_error_init(&error); if (!libhal_device_property_watch_all(hal_ctx, &error)) { - pa_log_error(__FILE__": error monitoring device list: %s: %s", + pa_log_error("error monitoring device list: %s: %s", error.name, error.message); dbus_error_free(&error); userdata_free(u); return -1; } - pa_log_info(__FILE__": loaded %i modules.", n); + pa_log_info("loaded %i modules.", n); return 0; } diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 286f6f579..47f77bab3 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -231,7 +231,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { } static void jack_error_func(const char*t) { - pa_log_warn(__FILE__": JACK error >%s<", t); + pa_log_warn("JACK error >%s<", t); } int pa__init(pa_core *c, pa_module*m) { @@ -253,12 +253,12 @@ int pa__init(pa_core *c, pa_module*m) { jack_set_error_function(jack_error_func); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { - pa_log(__FILE__": failed to parse connect= argument."); + pa_log("failed to parse connect= argument."); goto fail; } @@ -276,14 +276,14 @@ int pa__init(pa_core *c, pa_module*m) { pthread_cond_init(&u->cond, NULL); if (pipe(u->pipe_fds) < 0) { - pa_log(__FILE__": pipe() failed: %s", pa_cstrerror(errno)); + pa_log("pipe() failed: %s", pa_cstrerror(errno)); goto fail; } pa_make_nonblock_fd(u->pipe_fds[1]); if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { - pa_log(__FILE__": jack_client_open() failed."); + pa_log("jack_client_open() failed."); goto fail; } @@ -297,17 +297,17 @@ int pa__init(pa_core *c, pa_module*m) { channels = c->default_sample_spec.channels; if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { - pa_log(__FILE__": failed to parse channels= argument."); + pa_log("failed to parse channels= argument."); goto fail; } pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA); if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) { - pa_log(__FILE__": failed to parse channel_map= argument."); + pa_log("failed to parse channel_map= argument."); goto fail; } - pa_log_info(__FILE__": Successfully connected as '%s'", jack_get_client_name(u->client)); + pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client)); ss.channels = u->channels = channels; ss.rate = jack_get_sample_rate(u->client); @@ -317,13 +317,13 @@ int pa__init(pa_core *c, pa_module*m) { for (i = 0; i < ss.channels; i++) { if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(map.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0))) { - pa_log(__FILE__": jack_port_register() failed."); + pa_log("jack_port_register() failed."); goto fail; } } if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { - pa_log(__FILE__": failed to create sink."); + pa_log("failed to create sink."); goto fail; } @@ -337,7 +337,7 @@ int pa__init(pa_core *c, pa_module*m) { jack_on_shutdown(u->client, jack_shutdown, u); if (jack_activate(u->client)) { - pa_log(__FILE__": jack_activate() failed"); + pa_log("jack_activate() failed"); goto fail; } @@ -345,14 +345,14 @@ int pa__init(pa_core *c, pa_module*m) { for (i = 0, p = ports; i < ss.channels; i++, p++) { if (!*p) { - pa_log(__FILE__": not enough physical output ports, leaving unconnected."); + pa_log("not enough physical output ports, leaving unconnected."); break; } - pa_log_info(__FILE__": connecting %s to %s", jack_port_name(u->port[i]), *p); + pa_log_info("connecting %s to %s", jack_port_name(u->port[i]), *p); if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) { - pa_log(__FILE__": failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); + pa_log("failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); break; } } diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 8e659198d..62a991087 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -229,7 +229,7 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { } static void jack_error_func(const char*t) { - pa_log_warn(__FILE__": JACK error >%s<", t); + pa_log_warn("JACK error >%s<", t); } int pa__init(pa_core *c, pa_module*m) { @@ -251,12 +251,12 @@ int pa__init(pa_core *c, pa_module*m) { jack_set_error_function(jack_error_func); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { - pa_log(__FILE__": failed to parse connect= argument."); + pa_log("failed to parse connect= argument."); goto fail; } @@ -274,14 +274,14 @@ int pa__init(pa_core *c, pa_module*m) { pthread_cond_init(&u->cond, NULL); if (pipe(u->pipe_fds) < 0) { - pa_log(__FILE__": pipe() failed: %s", pa_cstrerror(errno)); + pa_log("pipe() failed: %s", pa_cstrerror(errno)); goto fail; } pa_make_nonblock_fd(u->pipe_fds[1]); if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { - pa_log(__FILE__": jack_client_open() failed."); + pa_log("jack_client_open() failed."); goto fail; } @@ -295,17 +295,17 @@ int pa__init(pa_core *c, pa_module*m) { channels = c->default_sample_spec.channels; if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { - pa_log(__FILE__": failed to parse channels= argument."); + pa_log("failed to parse channels= argument."); goto fail; } pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA); if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) { - pa_log(__FILE__": failed to parse channel_map= argument."); + pa_log("failed to parse channel_map= argument."); goto fail; } - pa_log_info(__FILE__": Successfully connected as '%s'", jack_get_client_name(u->client)); + pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client)); ss.channels = u->channels = channels; ss.rate = jack_get_sample_rate(u->client); @@ -315,13 +315,13 @@ int pa__init(pa_core *c, pa_module*m) { for (i = 0; i < ss.channels; i++) { if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(map.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput|JackPortIsTerminal, 0))) { - pa_log(__FILE__": jack_port_register() failed."); + pa_log("jack_port_register() failed."); goto fail; } } if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { - pa_log(__FILE__": failed to create source."); + pa_log("failed to create source."); goto fail; } @@ -335,7 +335,7 @@ int pa__init(pa_core *c, pa_module*m) { jack_on_shutdown(u->client, jack_shutdown, u); if (jack_activate(u->client)) { - pa_log(__FILE__": jack_activate() failed"); + pa_log("jack_activate() failed"); goto fail; } @@ -343,14 +343,14 @@ int pa__init(pa_core *c, pa_module*m) { for (i = 0, p = ports; i < ss.channels; i++, p++) { if (!*p) { - pa_log(__FILE__": not enough physical output ports, leaving unconnected."); + pa_log("not enough physical output ports, leaving unconnected."); break; } - pa_log_info(__FILE__": connecting %s to %s", jack_port_name(u->port[i]), *p); + pa_log_info("connecting %s to %s", jack_port_name(u->port[i]), *p); if (jack_connect(u->client, *p, jack_port_name(u->port[i]))) { - pa_log(__FILE__": failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); + pa_log("failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); break; } } diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index a93a3b927..18b2ddf1f 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -70,7 +70,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC assert(u); if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { - pa_log(__FILE__": lost connection to LIRC daemon."); + pa_log("lost connection to LIRC daemon."); goto fail; } @@ -78,13 +78,13 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC char *c; if (lirc_nextcode(&code) != 0 || !code) { - pa_log(__FILE__": lirc_nextcode() failed."); + pa_log("lirc_nextcode() failed."); goto fail; } c = pa_xstrdup(code); c[strcspn(c, "\n\r")] = 0; - pa_log_debug(__FILE__": raw IR code '%s'", c); + pa_log_debug("raw IR code '%s'", c); pa_xfree(c); while (lirc_code2char(u->config, code, &name) == 0 && name) { @@ -97,7 +97,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC MUTE_TOGGLE } volchange = INVALID; - pa_log_info(__FILE__": translated IR code '%s'", name); + pa_log_info("translated IR code '%s'", name); if (strcasecmp(name, "volume-up") == 0) volchange = UP; @@ -111,12 +111,12 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC volchange = RESET; if (volchange == INVALID) - pa_log_warn(__FILE__": recieved unknown IR code '%s'", name); + pa_log_warn("recieved unknown IR code '%s'", name); else { pa_sink *s; if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) - pa_log(__FILE__": failed to get sink '%s'", u->sink_name); + pa_log("failed to get sink '%s'", u->sink_name); else { int i; pa_cvolume cv = *pa_sink_get_volume(s, PA_MIXER_HARDWARE); @@ -186,12 +186,12 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (lirc_in_use) { - pa_log(__FILE__": module-lirc may no be loaded twice."); + pa_log("module-lirc may no be loaded twice."); return -1; } if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } @@ -204,12 +204,12 @@ int pa__init(pa_core *c, pa_module*m) { u->mute_toggle_save = 0; if ((u->lirc_fd = lirc_init((char*) pa_modargs_get_value(ma, "appname", "pulseaudio"), 1)) < 0) { - pa_log(__FILE__": lirc_init() failed."); + pa_log("lirc_init() failed."); goto fail; } if (lirc_readconfig((char*) pa_modargs_get_value(ma, "config", NULL), &u->config, NULL) < 0) { - pa_log(__FILE__": lirc_readconfig() failed."); + pa_log("lirc_readconfig() failed."); goto fail; } diff --git a/src/modules/module-match.c b/src/modules/module-match.c index ab94b02d7..eb5de64eb 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -83,7 +83,7 @@ static int load_rules(struct userdata *u, const char *filename) { pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn, "r"); if (!f) { - pa_log(__FILE__": failed to open file '%s': %s", fn, pa_cstrerror(errno)); + pa_log("failed to open file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } @@ -118,7 +118,7 @@ static int load_rules(struct userdata *u, const char *filename) { *d = 0; if (pa_atou(v, &k) < 0) { - pa_log(__FILE__": [%s:%u] failed to parse volume", filename, n); + pa_log("[%s:%u] failed to parse volume", filename, n); goto finish; } @@ -126,7 +126,7 @@ static int load_rules(struct userdata *u, const char *filename) { if (regcomp(®ex, ln, REG_EXTENDED|REG_NOSUB) != 0) { - pa_log(__FILE__": [%s:%u] invalid regular expression", filename, n); + pa_log("[%s:%u] invalid regular expression", filename, n); goto finish; } @@ -176,7 +176,7 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v for (r = u->rules; r; r = r->next) { if (!regexec(&r->regex, si->name, 0, NULL, 0)) { pa_cvolume cv; - pa_log_debug(__FILE__": changing volume of sink input '%s' to 0x%03x", si->name, r->volume); + pa_log_debug("changing volume of sink input '%s' to 0x%03x", si->name, r->volume); pa_cvolume_set(&cv, r->volume, si->sample_spec.channels); pa_sink_input_set_volume(si, &cv); } @@ -189,7 +189,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index c3d07396e..37234d925 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -82,7 +82,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC assert(u); if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { - pa_log(__FILE__": lost connection to evdev device."); + pa_log("lost connection to evdev device."); goto fail; } @@ -90,14 +90,14 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC struct input_event ev; if (pa_loop_read(u->fd, &ev, sizeof(ev), &u->fd_type) <= 0) { - pa_log(__FILE__": failed to read from event device: %s", pa_cstrerror(errno)); + pa_log("failed to read from event device: %s", pa_cstrerror(errno)); goto fail; } if (ev.type == EV_KEY && (ev.value == 1 || ev.value == 2)) { enum { INVALID, UP, DOWN, MUTE_TOGGLE } volchange = INVALID; - pa_log_debug(__FILE__": key code=%u, value=%u", ev.code, ev.value); + pa_log_debug("key code=%u, value=%u", ev.code, ev.value); switch (ev.code) { case KEY_VOLUMEDOWN: volchange = DOWN; break; @@ -109,7 +109,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_sink *s; if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) - pa_log(__FILE__": failed to get sink '%s'", u->sink_name); + pa_log("failed to get sink '%s'", u->sink_name); else { int i; pa_cvolume cv = *pa_sink_get_volume(s, PA_MIXER_HARDWARE); @@ -173,7 +173,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } @@ -185,41 +185,41 @@ int pa__init(pa_core *c, pa_module*m) { u->fd_type = 0; if ((u->fd = open(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY)) < 0) { - pa_log(__FILE__": failed to open evdev device: %s", pa_cstrerror(errno)); + pa_log("failed to open evdev device: %s", pa_cstrerror(errno)); goto fail; } if (ioctl(u->fd, EVIOCGVERSION, &version) < 0) { - pa_log(__FILE__": EVIOCGVERSION failed: %s", pa_cstrerror(errno)); + pa_log("EVIOCGVERSION failed: %s", pa_cstrerror(errno)); goto fail; } - pa_log_info(__FILE__": evdev driver version %i.%i.%i", version >> 16, (version >> 8) & 0xff, version & 0xff); + pa_log_info("evdev driver version %i.%i.%i", version >> 16, (version >> 8) & 0xff, version & 0xff); if(ioctl(u->fd, EVIOCGID, &input_id)) { - pa_log(__FILE__": EVIOCGID failed: %s", pa_cstrerror(errno)); + pa_log("EVIOCGID failed: %s", pa_cstrerror(errno)); goto fail; } - pa_log_info(__FILE__": evdev vendor 0x%04hx product 0x%04hx version 0x%04hx bustype %u", + pa_log_info("evdev vendor 0x%04hx product 0x%04hx version 0x%04hx bustype %u", input_id.vendor, input_id.product, input_id.version, input_id.bustype); memset(name, 0, sizeof(name)); if(ioctl(u->fd, EVIOCGNAME(sizeof(name)), name) < 0) { - pa_log(__FILE__": EVIOCGNAME failed: %s", pa_cstrerror(errno)); + pa_log("EVIOCGNAME failed: %s", pa_cstrerror(errno)); goto fail; } - pa_log_info(__FILE__": evdev device name: %s", name); + pa_log_info("evdev device name: %s", name); memset(evtype_bitmask, 0, sizeof(evtype_bitmask)); if (ioctl(u->fd, EVIOCGBIT(0, EV_MAX), evtype_bitmask) < 0) { - pa_log(__FILE__": EVIOCGBIT failed: %s", pa_cstrerror(errno)); + pa_log("EVIOCGBIT failed: %s", pa_cstrerror(errno)); goto fail; } if (!test_bit(EV_KEY, evtype_bitmask)) { - pa_log(__FILE__": device has no keys."); + pa_log("device has no keys."); goto fail; } diff --git a/src/modules/module-native-protocol-fd.c b/src/modules/module-native-protocol-fd.c index 9e1cac096..dd3b4abe8 100644 --- a/src/modules/module-native-protocol-fd.c +++ b/src/modules/module-native-protocol-fd.c @@ -53,12 +53,12 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto finish; } if (pa_modargs_get_value_s32(ma, "fd", &fd) < 0) { - pa_log(__FILE__": invalid file descriptor."); + pa_log("invalid file descriptor."); goto finish; } diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 4d5ebb084..50e58853a 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -120,13 +120,13 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { - pa_log(__FILE__": invalid sample format specification or channel map."); + pa_log("invalid sample format specification or channel map."); goto fail; } @@ -136,7 +136,7 @@ int pa__init(pa_core *c, pa_module*m) { m->userdata = u; if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { - pa_log(__FILE__": failed to create sink."); + pa_log("failed to create sink."); goto fail; } diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 75ab9a9e9..0be6bbe22 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -187,7 +187,7 @@ static void do_write(struct userdata *u) { update_usage(u); if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); clear_up(u); pa_module_unload_request(u->module); @@ -253,7 +253,7 @@ static void do_read(struct userdata *u) { update_usage(u); if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); clear_up(u); pa_module_unload_request(u->module); @@ -293,7 +293,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { assert(s && u); if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); return 0; } @@ -319,7 +319,7 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { assert(s && u); if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); return 0; } @@ -342,7 +342,7 @@ static int sink_get_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); + pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); s->get_hw_volume = NULL; return -1; } @@ -354,7 +354,7 @@ static int sink_set_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); + pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); s->set_hw_volume = NULL; return -1; } @@ -366,7 +366,7 @@ static int source_get_hw_volume(pa_source *s) { struct userdata *u = s->userdata; if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); + pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); s->get_hw_volume = NULL; return -1; } @@ -378,7 +378,7 @@ static int source_set_hw_volume(pa_source *s) { struct userdata *u = s->userdata; if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); + pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); s->set_hw_volume = NULL; return -1; } @@ -410,17 +410,17 @@ int pa__init(pa_core *c, pa_module*m) { u->core = c; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log(__FILE__": record= and playback= expect numeric arguments."); + pa_log("record= and playback= expect numeric arguments."); goto fail; } if (!playback && !record) { - pa_log(__FILE__": neither playback nor record enabled for device."); + pa_log("neither playback nor record enabled for device."); goto fail; } @@ -429,13 +429,13 @@ int pa__init(pa_core *c, pa_module*m) { nfrags = DEFAULT_NFRAGS; frag_size = DEFAULT_FRAGSIZE; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { - pa_log(__FILE__": failed to parse fragments arguments"); + pa_log("failed to parse fragments arguments"); goto fail; } u->sample_spec = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->sample_spec, &map, PA_CHANNEL_MAP_OSS) < 0) { - pa_log(__FILE__": failed to parse sample specification or channel map"); + pa_log("failed to parse sample specification or channel map"); goto fail; } @@ -443,14 +443,14 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER)) { - pa_log(__FILE__": OSS device not mmap capable."); + pa_log("OSS device not mmap capable."); goto fail; } - pa_log_info(__FILE__": device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0) - pa_log_info(__FILE__": hardware name is '%s'.", hwdesc); + pa_log_info("hardware name is '%s'.", hwdesc); else hwdesc[0] = 0; @@ -463,19 +463,19 @@ int pa__init(pa_core *c, pa_module*m) { if (mode != O_WRONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno)); goto fail; } - pa_log_info(__FILE__": input -- %u fragments of size %u.", info.fragstotal, info.fragsize); + pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize); u->in_mmap_length = (u->in_fragment_size = info.fragsize) * (u->in_fragments = info.fragstotal); if ((u->in_mmap = mmap(NULL, u->in_mmap_length, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { if (mode == O_RDWR) { - pa_log(__FILE__": mmap failed for input. Changing to O_WRONLY mode."); + pa_log("mmap failed for input. Changing to O_WRONLY mode."); mode = O_WRONLY; } else { - pa_log(__FILE__": mmap(): %s", pa_cstrerror(errno)); + pa_log("mmap(): %s", pa_cstrerror(errno)); goto fail; } } else { @@ -513,19 +513,19 @@ int pa__init(pa_core *c, pa_module*m) { if (mode != O_RDONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno)); goto fail; } - pa_log_info(__FILE__": output -- %u fragments of size %u.", info.fragstotal, info.fragsize); + pa_log_info("output -- %u fragments of size %u.", info.fragstotal, info.fragsize); u->out_mmap_length = (u->out_fragment_size = info.fragsize) * (u->out_fragments = info.fragstotal); if ((u->out_mmap = mmap(NULL, u->out_mmap_length, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { if (mode == O_RDWR) { - pa_log(__FILE__": mmap filed for output. Changing to O_RDONLY mode."); + pa_log("mmap filed for output. Changing to O_RDONLY mode."); mode = O_RDONLY; } else { - pa_log(__FILE__": mmap(): %s", pa_cstrerror(errno)); + pa_log("mmap(): %s", pa_cstrerror(errno)); goto fail; } } else { @@ -565,12 +565,12 @@ int pa__init(pa_core *c, pa_module*m) { zero = 0; if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); goto fail; } if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index b9b80e725..b71581d9a 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -166,7 +166,7 @@ static void do_write(struct userdata *u) { assert(memchunk->length); if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { - pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); + pa_log("write() failed: %s", pa_cstrerror(errno)); clear_up(u); pa_module_unload_request(u->module); @@ -222,7 +222,7 @@ static void do_read(struct userdata *u) { if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) { - pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno)); + pa_log("read() failed: %s", pa_cstrerror(errno)); clear_up(u); pa_module_unload_request(u->module); } @@ -260,7 +260,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { assert(s && u && u->sink); if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) { - pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno)); + pa_log_info("device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno)); s->get_latency = NULL; return 0; } @@ -296,7 +296,7 @@ static int sink_get_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); + pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); s->get_hw_volume = NULL; return -1; } @@ -308,7 +308,7 @@ static int sink_set_hw_volume(pa_sink *s) { struct userdata *u = s->userdata; if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); + pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); s->set_hw_volume = NULL; return -1; } @@ -320,7 +320,7 @@ static int source_get_hw_volume(pa_source *s) { struct userdata *u = s->userdata; if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); + pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); s->get_hw_volume = NULL; return -1; } @@ -332,7 +332,7 @@ static int source_set_hw_volume(pa_source *s) { struct userdata *u = s->userdata; if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info(__FILE__": device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); + pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); s->set_hw_volume = NULL; return -1; } @@ -360,17 +360,17 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log(__FILE__": record= and playback= expect numeric argument."); + pa_log("record= and playback= expect numeric argument."); goto fail; } if (!playback && !record) { - pa_log(__FILE__": neither playback nor record enabled for device."); + pa_log("neither playback nor record enabled for device."); goto fail; } @@ -378,7 +378,7 @@ int pa__init(pa_core *c, pa_module*m) { ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_OSS) < 0) { - pa_log(__FILE__": failed to parse sample specification or channel map"); + pa_log("failed to parse sample specification or channel map"); goto fail; } @@ -387,7 +387,7 @@ int pa__init(pa_core *c, pa_module*m) { frag_size = pa_bytes_per_second(&ss)/128; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { - pa_log(__FILE__": failed to parse fragments arguments"); + pa_log("failed to parse fragments arguments"); goto fail; } @@ -395,11 +395,11 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0) - pa_log_info(__FILE__": hardware name is '%s'.", hwdesc); + pa_log_info("hardware name is '%s'.", hwdesc); else hwdesc[0] = 0; - pa_log_info(__FILE__": device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (nfrags >= 2 && frag_size >= 1) if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) @@ -409,7 +409,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno)); goto fail; } assert(frag_size); @@ -420,13 +420,13 @@ int pa__init(pa_core *c, pa_module*m) { u->use_getospace = u->use_getispace = 0; if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { - pa_log_info(__FILE__": input -- %u fragments of size %u.", info.fragstotal, info.fragsize); + pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize); in_frag_size = info.fragsize; u->use_getispace = 1; } if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { - pa_log_info(__FILE__": output -- %u fragments of size %u.", info.fragstotal, info.fragsize); + pa_log_info("output -- %u fragments of size %u.", info.fragstotal, info.fragsize); out_frag_size = info.fragsize; u->use_getospace = 1; } diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index c90039fd7..4aee849bb 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -100,7 +100,7 @@ static void do_write(struct userdata *u) { assert(u->memchunk.memblock && u->memchunk.length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { - pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); + pa_log("write(): %s", pa_cstrerror(errno)); return; } @@ -153,32 +153,32 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { - pa_log(__FILE__": invalid sample format specification"); + pa_log("invalid sample format specification"); goto fail; } mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); if ((fd = open(p, O_RDWR)) < 0) { - pa_log(__FILE__": open('%s'): %s", p, pa_cstrerror(errno)); + pa_log("open('%s'): %s", p, pa_cstrerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); if (fstat(fd, &st) < 0) { - pa_log(__FILE__": fstat('%s'): %s", p, pa_cstrerror(errno)); + pa_log("fstat('%s'): %s", p, pa_cstrerror(errno)); goto fail; } if (!S_ISFIFO(st.st_mode)) { - pa_log(__FILE__": '%s' is not a FIFO.", p); + pa_log("'%s' is not a FIFO.", p); goto fail; } @@ -189,7 +189,7 @@ int pa__init(pa_core *c, pa_module*m) { m->userdata = u; if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { - pa_log(__FILE__": failed to create sink."); + pa_log("failed to create sink."); goto fail; } u->sink->notify = notify_cb; diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index 43a8dab55..c251f7ac3 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -97,7 +97,7 @@ static void do_read(struct userdata *u) { assert(u->chunk.memblock && u->chunk.memblock->length > u->chunk.index); if ((r = pa_iochannel_read(u->io, (uint8_t*) u->chunk.memblock->data + u->chunk.index, u->chunk.memblock->length - u->chunk.index)) <= 0) { - pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); + pa_log("read(): %s", pa_cstrerror(errno)); return; } @@ -131,32 +131,32 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { - pa_log(__FILE__": invalid sample format specification or channel map"); + pa_log("invalid sample format specification or channel map"); goto fail; } mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); if ((fd = open(p, O_RDWR)) < 0) { - pa_log(__FILE__": open('%s'): %s", p, pa_cstrerror(errno)); + pa_log("open('%s'): %s", p, pa_cstrerror(errno)); goto fail; } pa_fd_set_cloexec(fd, 1); if (fstat(fd, &st) < 0) { - pa_log(__FILE__": fstat('%s'): %s", p, pa_cstrerror(errno)); + pa_log("fstat('%s'): %s", p, pa_cstrerror(errno)); goto fail; } if (!S_ISFIFO(st.st_mode)) { - pa_log(__FILE__": '%s' is not a FIFO.", p); + pa_log("'%s' is not a FIFO.", p); goto fail; } @@ -166,7 +166,7 @@ int pa__init(pa_core *c, pa_module*m) { u->core = c; if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { - pa_log(__FILE__": failed to create source."); + pa_log("failed to create source."); goto fail; } u->source->userdata = u; diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index d1f5fa158..df58958a9 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -221,7 +221,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto finish; } @@ -229,7 +229,7 @@ int pa__init(pa_core *c, pa_module*m) { #if defined(USE_TCP_SOCKETS) if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { - pa_log(__FILE__": port= expects a numerical argument between 1 and 65535."); + pa_log("port= expects a numerical argument between 1 and 65535."); goto fail; } @@ -268,18 +268,18 @@ int pa__init(pa_core *c, pa_module*m) { * /tmp/.esd/, hence we have to create the dir first */ if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) { - pa_log(__FILE__": Failed to create socket directory: %s\n", pa_cstrerror(errno)); + pa_log("Failed to create socket directory: %s\n", pa_cstrerror(errno)); goto fail; } #endif if ((r = pa_unix_socket_remove_stale(tmp)) < 0) { - pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s", tmp, pa_cstrerror(errno)); + pa_log("Failed to remove stale UNIX socket '%s': %s", tmp, pa_cstrerror(errno)); goto fail; } if (r) - pa_log(__FILE__": Removed stale UNIX socket '%s'.", tmp); + pa_log("Removed stale UNIX socket '%s'.", tmp); if (!(s = pa_socket_server_new_unix(c->mainloop, tmp))) goto fail; diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c index 5700ef438..7aa205bd4 100644 --- a/src/modules/module-rescue-streams.c +++ b/src/modules/module-rescue-streams.c @@ -54,12 +54,12 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user assert(sink); if (!pa_idxset_size(sink->inputs)) { - pa_log_debug(__FILE__": No sink inputs to move away."); + pa_log_debug("No sink inputs to move away."); return PA_HOOK_OK; } if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, 0))) { - pa_log_info(__FILE__": No evacuation sink found."); + pa_log_info("No evacuation sink found."); return PA_HOOK_OK; } @@ -67,11 +67,11 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user while ((i = pa_idxset_first(sink->inputs, NULL))) { if (pa_sink_input_move_to(i, target, 1) < 0) { - pa_log_warn(__FILE__": Failed to move sink input %u \"%s\" to %s.", i->index, i->name, target->name); + pa_log_warn("Failed to move sink input %u \"%s\" to %s.", i->index, i->name, target->name); return PA_HOOK_OK; } - pa_log_info(__FILE__": Sucessfully moved sink input %u \"%s\" to %s.", i->index, i->name, target->name); + pa_log_info("Sucessfully moved sink input %u \"%s\" to %s.", i->index, i->name, target->name); } @@ -86,12 +86,12 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void assert(source); if (!pa_idxset_size(source->outputs)) { - pa_log_debug(__FILE__": No source outputs to move away."); + pa_log_debug("No source outputs to move away."); return PA_HOOK_OK; } if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SOURCE, 0))) { - pa_log_info(__FILE__": No evacuation source found."); + pa_log_info("No evacuation source found."); return PA_HOOK_OK; } @@ -99,11 +99,11 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void while ((o = pa_idxset_first(source->outputs, NULL))) { if (pa_source_output_move_to(o, target) < 0) { - pa_log_warn(__FILE__": Failed to move source output %u \"%s\" to %s.", o->index, o->name, target->name); + pa_log_warn("Failed to move source output %u \"%s\" to %s.", o->index, o->name, target->name); return PA_HOOK_OK; } - pa_log_info(__FILE__": Sucessfully moved source output %u \"%s\" to %s.", o->index, o->name, target->name); + pa_log_info("Sucessfully moved source output %u \"%s\" to %s.", o->index, o->name, target->name); } @@ -118,7 +118,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); return -1; } diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index 89c3c6093..fa29ba160 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -112,7 +112,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_sink_input_new_data data; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } @@ -125,7 +125,7 @@ int pa__init(pa_core *c, pa_module*m) { sink_name = pa_modargs_get_value(ma, "sink", NULL); if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": No such sink."); + pa_log("No such sink."); goto fail; } @@ -135,7 +135,7 @@ int pa__init(pa_core *c, pa_module*m) { frequency = 440; if (pa_modargs_get_value_u32(ma, "frequency", &frequency) < 0 || frequency < 1 || frequency > ss.rate/2) { - pa_log(__FILE__": Invalid frequency specification"); + pa_log("Invalid frequency specification"); goto fail; } diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 53c73af79..e13254e93 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -144,7 +144,7 @@ static void do_write(struct userdata *u) { len = 0; if (len == u->buffer_size) - pa_log_debug(__FILE__": Solaris buffer underflow!"); + pa_log_debug("Solaris buffer underflow!"); len -= len % u->frame_size; @@ -168,7 +168,7 @@ static void do_write(struct userdata *u) { } if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { - pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno)); + pa_log("write() failed: %s", pa_cstrerror(errno)); return; } @@ -206,7 +206,7 @@ static void do_read(struct userdata *u) { if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) - pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno)); + pa_log("read() failed: %s", pa_cstrerror(errno)); return; } @@ -332,9 +332,9 @@ static int sink_set_hw_volume_cb(pa_sink *s) { if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); + pa_log("AUDIO_SETINFO: Unsupported volume."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -363,7 +363,7 @@ static int sink_set_hw_mute_cb(pa_sink *s) { info.output_muted = !!s->hw_muted; if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { - pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -395,9 +395,9 @@ static int source_set_hw_volume_cb(pa_source *s) { if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported volume."); + pa_log("AUDIO_SETINFO: Unsupported volume."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -461,9 +461,9 @@ static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format."); + pa_log("AUDIO_SETINFO: Unsupported sample format."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -479,9 +479,9 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { if (errno == EINVAL) - pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size."); + pa_log("AUDIO_SETINFO: Unsupported buffer size."); else - pa_log(__FILE__": AUDIO_SETINFO: %s", pa_cstrerror(errno)); + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); return -1; } @@ -503,17 +503,17 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log(__FILE__": record= and playback= expect numeric argument."); + pa_log("record= and playback= expect numeric argument."); goto fail; } if (!playback && !record) { - pa_log(__FILE__": neither playback nor record enabled for device."); + pa_log("neither playback nor record enabled for device."); goto fail; } @@ -521,20 +521,20 @@ int pa__init(pa_core *c, pa_module*m) { buffer_size = 16384; if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) { - pa_log(__FILE__": failed to parse buffer size argument"); + pa_log("failed to parse buffer size argument"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { - pa_log(__FILE__": failed to parse sample specification"); + pa_log("failed to parse sample specification"); goto fail; } if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode | O_NONBLOCK)) < 0) goto fail; - pa_log_info(__FILE__": device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (pa_solaris_auto_format(fd, mode, &ss) < 0) goto fail; diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 53bffd3b1..de1a12c90 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -206,7 +206,7 @@ static void command_stream_killed(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t comma struct userdata *u = userdata; assert(pd && t && u && u->pdispatch == pd); - pa_log(__FILE__": stream killed"); + pa_log("stream killed"); die(u); } @@ -223,7 +223,7 @@ static void command_subscribe_event(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t com if (pa_tagstruct_getu32(t, &e) < 0 || pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid protocol reply"); + pa_log("invalid protocol reply"); die(u); return; } @@ -284,13 +284,13 @@ static void command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED ui if (pa_tagstruct_getu32(t, &channel) < 0 || pa_tagstruct_getu32(t, &bytes) < 0 || !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid protocol reply"); + pa_log("invalid protocol reply"); die(u); return; } if (channel != u->channel) { - pa_log(__FILE__": recieved data for invalid channel"); + pa_log("recieved data for invalid channel"); die(u); return; } @@ -311,9 +311,9 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G if (command != PA_COMMAND_REPLY) { if (command == PA_COMMAND_ERROR) - pa_log(__FILE__": failed to get latency."); + pa_log("failed to get latency."); else - pa_log(__FILE__": protocol error."); + pa_log("protocol error."); die(u); return; } @@ -326,7 +326,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G pa_tagstruct_gets64(t, &write_index) < 0 || pa_tagstruct_gets64(t, &read_index) < 0 || !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid reply. (latency)"); + pa_log("invalid reply. (latency)"); die(u); return; } @@ -353,7 +353,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G u->host_latency = 0; #endif -/* pa_log(__FILE__": estimated host latency: %0.0f usec", (double) u->host_latency); */ +/* pa_log("estimated host latency: %0.0f usec", (double) u->host_latency); */ } static void request_latency(struct userdata *u) { @@ -392,9 +392,9 @@ static void stream_get_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_ if (command != PA_COMMAND_REPLY) { if (command == PA_COMMAND_ERROR) - pa_log(__FILE__": failed to get info."); + pa_log("failed to get info."); else - pa_log(__FILE__": protocol error."); + pa_log("protocol error."); die(u); return; } @@ -413,7 +413,7 @@ static void stream_get_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_ pa_tagstruct_gets(t, &driver) < 0 || pa_tagstruct_getu32(t, &flags) < 0 || !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid reply. (get_info)"); + pa_log("invalid reply. (get_info)"); die(u); return; } @@ -495,9 +495,9 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN if (command != PA_COMMAND_REPLY) { if (command == PA_COMMAND_ERROR) - pa_log(__FILE__": failed to create stream."); + pa_log("failed to create stream."); else - pa_log(__FILE__": protocol error."); + pa_log("protocol error."); die(u); return; } @@ -508,7 +508,7 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN pa_tagstruct_getu32(t, &u->requested_bytes) < 0 || #endif !pa_tagstruct_eof(t)) { - pa_log(__FILE__": invalid reply. (create stream)"); + pa_log("invalid reply. (create stream)"); die(u); return; } @@ -535,16 +535,16 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct_getu32(t, &u->version) < 0 || !pa_tagstruct_eof(t)) { if (command == PA_COMMAND_ERROR) - pa_log(__FILE__": failed to authenticate"); + pa_log("failed to authenticate"); else - pa_log(__FILE__": protocol error."); + pa_log("protocol error."); die(u); return; } /* Minimum supported protocol version */ if (u->version < 8) { - pa_log(__FILE__": incompatible protocol version"); + pa_log("incompatible protocol version"); die(u); return; } @@ -606,7 +606,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { struct userdata *u = userdata; assert(p && u); - pa_log(__FILE__": stream died."); + pa_log("stream died."); die(u); } @@ -616,7 +616,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_c assert(p && packet && u); if (pa_pdispatch_run(u->pdispatch, packet, creds, u) < 0) { - pa_log(__FILE__": invalid packet"); + pa_log("invalid packet"); die(u); } } @@ -627,7 +627,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, PA_GCC_UN assert(p && chunk && u); if (channel != u->channel) { - pa_log(__FILE__": recieved memory block on bad channel."); + pa_log("recieved memory block on bad channel."); die(u); return; } @@ -646,7 +646,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata u->client = NULL; if (!io) { - pa_log(__FILE__": connection failed."); + pa_log("connection failed."); pa_module_unload_request(u->module); return; } @@ -833,7 +833,7 @@ static int load_key(struct userdata *u, const char*fn) { u->auth_cookie_in_property = 0; if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { - pa_log_debug(__FILE__": using already loaded auth cookie."); + pa_log_debug("using already loaded auth cookie."); pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); u->auth_cookie_in_property = 1; return 0; @@ -845,7 +845,7 @@ static int load_key(struct userdata *u, const char*fn) { if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) return -1; - pa_log_debug(__FILE__": loading cookie from disk."); + pa_log_debug("loading cookie from disk."); if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) u->auth_cookie_in_property = 1; @@ -864,7 +864,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } @@ -894,18 +894,18 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) { - pa_log(__FILE__": no server specified."); + pa_log("no server specified."); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { - pa_log(__FILE__": invalid sample format specification"); + pa_log("invalid sample format specification"); goto fail; } if (!(u->client = pa_socket_client_new_string(c->mainloop, u->server_name, PA_NATIVE_DEFAULT_PORT))) { - pa_log(__FILE__": failed to connect to server '%s'", u->server_name); + pa_log("failed to connect to server '%s'", u->server_name); goto fail; } @@ -916,7 +916,7 @@ int pa__init(pa_core *c, pa_module*m) { #ifdef TUNNEL_SINK if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { - pa_log(__FILE__": failed to create sink."); + pa_log("failed to create sink."); goto fail; } @@ -933,7 +933,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_sink_set_owner(u->sink, m); #else if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { - pa_log(__FILE__": failed to create source."); + pa_log("failed to create source."); goto fail; } diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index bdead0f62..0e4f278c2 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -123,10 +123,10 @@ static int load_rules(struct userdata *u) { if (!f) { if (errno == ENOENT) { - pa_log_info(__FILE__": starting with empty ruleset."); + pa_log_info("starting with empty ruleset."); ret = 0; } else - pa_log(__FILE__": failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); + pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); goto finish; } @@ -155,14 +155,14 @@ static int load_rules(struct userdata *u) { assert(ln == buf_volume); if (!parse_volume(buf_volume, &v)) { - pa_log(__FILE__": parse failure in %s:%u, stopping parsing", u->table_file, n); + pa_log("parse failure in %s:%u, stopping parsing", u->table_file, n); goto finish; } ln = buf_name; if (pa_hashmap_get(u->hashmap, buf_name)) { - pa_log(__FILE__": double entry in %s:%u, ignoring", u->table_file, n); + pa_log("double entry in %s:%u, ignoring", u->table_file, n); goto finish; } @@ -174,7 +174,7 @@ static int load_rules(struct userdata *u) { } if (ln == buf_volume) { - pa_log(__FILE__": invalid number of lines in %s.", u->table_file); + pa_log("invalid number of lines in %s.", u->table_file); goto finish; } @@ -200,7 +200,7 @@ static int save_rules(struct userdata *u) { pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w"); if (!f) { - pa_log(__FILE__": failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); + pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); goto finish; } @@ -279,12 +279,12 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 pa_xfree(name); if (!pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { - pa_log_info(__FILE__": Saving volume for <%s>", r->name); + pa_log_info("Saving volume for <%s>", r->name); r->volume = *pa_sink_input_get_volume(si); u->modified = 1; } } else { - pa_log_info(__FILE__": Creating new entry for <%s>", name); + pa_log_info("Creating new entry for <%s>", name); r = pa_xnew(struct rule, 1); r->name = name; @@ -307,7 +307,7 @@ static pa_hook_result_t hook_callback(pa_core *c, pa_sink_input_new_data *data, if ((r = pa_hashmap_get(u->hashmap, name))) { if (data->sample_spec_is_set && data->sample_spec.channels == r->volume.channels) { - pa_log_info(__FILE__": Restoring volume for <%s>", r->name); + pa_log_info("Restoring volume for <%s>", r->name); pa_sink_input_new_data_set_volume(data, &r->volume); } } @@ -323,7 +323,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 5f55c2027..2cc665b42 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -125,7 +125,7 @@ static void do_write(struct userdata *u) LeaveCriticalSection(&u->crit); if (free_frags == u->fragments) - pa_log_debug(__FILE__": WaveOut underflow!"); + pa_log_debug("WaveOut underflow!"); while (free_frags) { hdr = &u->ohdrs[u->cur_ohdr]; @@ -209,7 +209,7 @@ static void do_read(struct userdata *u) LeaveCriticalSection(&u->crit); if (free_frags == u->fragments) - pa_log_debug(__FILE__": WaveIn overflow!"); + pa_log_debug("WaveIn overflow!"); while (free_frags) { hdr = &u->ihdrs[u->cur_ihdr]; @@ -395,7 +395,7 @@ static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) { wf->wFormatTag = WAVE_FORMAT_PCM; if (ss->channels > 2) { - pa_log_error(__FILE__": ERROR: More than two channels not supported."); + pa_log_error("ERROR: More than two channels not supported."); return -1; } @@ -408,7 +408,7 @@ static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) { case 44100: break; default: - pa_log_error(__FILE__": ERROR: Unsupported sample rate."); + pa_log_error("ERROR: Unsupported sample rate."); return -1; } @@ -419,7 +419,7 @@ static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) { else if (ss->format == PA_SAMPLE_S16NE) wf->wBitsPerSample = 16; else { - pa_log_error(__FILE__": ERROR: Unsupported sample format."); + pa_log_error("ERROR: Unsupported sample format."); return -1; } @@ -447,30 +447,30 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log(__FILE__": record= and playback= expect boolean argument."); + pa_log("record= and playback= expect boolean argument."); goto fail; } if (!playback && !record) { - pa_log(__FILE__": neither playback nor record enabled for device."); + pa_log("neither playback nor record enabled for device."); goto fail; } nfrags = 5; frag_size = 8192; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { - pa_log(__FILE__": failed to parse fragments arguments"); + pa_log("failed to parse fragments arguments"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_WAVEEX) < 0) { - pa_log(__FILE__": failed to parse sample specification"); + pa_log("failed to parse sample specification"); goto fail; } @@ -484,13 +484,13 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; if (waveInStart(hwi) != MMSYSERR_NOERROR) goto fail; - pa_log_debug(__FILE__": Opened waveIn subsystem."); + pa_log_debug("Opened waveIn subsystem."); } if (playback) { if (waveOutOpen(&hwo, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) goto fail; - pa_log_debug(__FILE__": Opened waveOut subsystem."); + pa_log_debug("Opened waveOut subsystem."); } InitializeCriticalSection(&u->crit); diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index 7ac5f558b..48e95c8ce 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -70,7 +70,7 @@ static int ring_bell(struct userdata *u, int percent) { assert(u); if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": Invalid sink: %s", u->sink_name); + pa_log("Invalid sink: %s", u->sink_name); return -1; } @@ -89,7 +89,7 @@ static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) { bne = (XkbBellNotifyEvent*) e; if (ring_bell(u, bne->percent) < 0) { - pa_log_info(__FILE__": Ringing bell failed, reverting to X11 device bell."); + pa_log_info("Ringing bell failed, reverting to X11 device bell."); XkbForceDeviceBell(pa_x11_wrapper_get_display(w), bne->device, bne->bell_class, bne->bell_id, bne->percent); } @@ -104,7 +104,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } @@ -121,7 +121,7 @@ int pa__init(pa_core *c, pa_module*m) { minor = XkbMinorVersion; if (!XkbLibraryVersion(&major, &minor)) { - pa_log(__FILE__": XkbLibraryVersion() failed"); + pa_log("XkbLibraryVersion() failed"); goto fail; } @@ -130,7 +130,7 @@ int pa__init(pa_core *c, pa_module*m) { if (!XkbQueryExtension(pa_x11_wrapper_get_display(u->x11_wrapper), NULL, &u->xkb_event_base, NULL, &major, &minor)) { - pa_log(__FILE__": XkbQueryExtension() failed"); + pa_log("XkbQueryExtension() failed"); goto fail; } diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index 0ee453cca..f2cace149 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -79,7 +79,7 @@ static int load_key(struct userdata *u, const char*fn) { u->auth_cookie_in_property = 0; if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { - pa_log_debug(__FILE__": using already loaded auth cookie."); + pa_log_debug("using already loaded auth cookie."); pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); u->auth_cookie_in_property = 1; return 0; @@ -91,7 +91,7 @@ static int load_key(struct userdata *u, const char*fn) { if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) return -1; - pa_log_debug(__FILE__": loading cookie from disk."); + pa_log_debug("loading cookie from disk."); if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) u->auth_cookie_in_property = 1; @@ -109,7 +109,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_strlist *l; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } @@ -168,7 +168,7 @@ void pa__done(pa_core *c, pa_module*m) { /* Yes, here is a race condition */ if (!pa_x11_get_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID", t, sizeof(t)) || strcmp(t, u->id)) - pa_log_warn(__FILE__": PulseAudio information vanished from X11!"); + pa_log_warn("PulseAudio information vanished from X11!"); else { pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID"); pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER"); diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 651a95b7a..696d8afeb 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -203,12 +203,12 @@ static int publish_service(struct userdata *u, struct service *s) { u->port, txt) < 0) { - pa_log(__FILE__": avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(u->client))); + pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(u->client))); goto finish; } if (avahi_entry_group_commit(s->entry_group) < 0) { - pa_log(__FILE__": avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(u->client))); + pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(u->client))); goto finish; } @@ -456,7 +456,7 @@ static int publish_main_service(struct userdata *u) { if (!u->main_entry_group) { if (!(u->main_entry_group = avahi_entry_group_new(u->client, main_entry_group_callback, u))) { - pa_log(__FILE__": avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); + pa_log("avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); goto fail; } } else @@ -475,12 +475,12 @@ static int publish_main_service(struct userdata *u) { u->port, txt) < 0) { - pa_log(__FILE__": avahi_entry_group_add_service_strlst() failed: %s", avahi_strerror(avahi_client_errno(u->client))); + pa_log("avahi_entry_group_add_service_strlst() failed: %s", avahi_strerror(avahi_client_errno(u->client))); goto fail; } if (avahi_entry_group_commit(u->main_entry_group) < 0) { - pa_log(__FILE__": avahi_entry_group_commit() failed: %s", avahi_strerror(avahi_client_errno(u->client))); + pa_log("avahi_entry_group_commit() failed: %s", avahi_strerror(avahi_client_errno(u->client))); goto fail; } @@ -501,7 +501,7 @@ static int publish_all_services(struct userdata *u) { assert(u); - pa_log_debug(__FILE__": Publishing services in Zeroconf"); + pa_log_debug("Publishing services in Zeroconf"); for (sink = pa_idxset_first(u->core->sinks, &idx); sink; sink = pa_idxset_next(u->core->sinks, &idx)) if (publish_sink(u, sink) < 0) @@ -531,7 +531,7 @@ static void unpublish_all_services(struct userdata *u, int rem) { assert(u); - pa_log_debug(__FILE__": Unpublishing services in Zeroconf"); + pa_log_debug("Unpublishing services in Zeroconf"); while ((s = pa_hashmap_iterate(u->services, &state, NULL))) { if (s->entry_group) { @@ -576,7 +576,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda avahi_client_free(u->client); if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) - pa_log(__FILE__": pa_avahi_client_new() failed: %s", avahi_strerror(error)); + pa_log("pa_avahi_client_new() failed: %s", avahi_strerror(error)); } break; @@ -593,12 +593,12 @@ int pa__init(pa_core *c, pa_module*m) { int error; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments."); + pa_log("failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port == 0 || port >= 0xFFFF) { - pa_log(__FILE__": invalid port specified."); + pa_log("invalid port specified."); goto fail; } @@ -623,7 +623,7 @@ int pa__init(pa_core *c, pa_module*m) { u->service_name = pa_xstrdup(pa_get_host_name(hn, sizeof(hn))); if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { - pa_log(__FILE__": pa_avahi_client_new() failed: %s", avahi_strerror(error)); + pa_log("pa_avahi_client_new() failed: %s", avahi_strerror(error)); goto fail; } diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 177322be9..d1c623b4c 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -57,27 +57,27 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { tcaps = pcaps ? pcaps : &dcaps; if (ioctl(fd, SNDCTL_DSP_GETCAPS, tcaps) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); goto fail; } if (*tcaps & DSP_CAP_DUPLEX) goto success; - pa_log_warn(__FILE__": '%s' doesn't support full duplex", device); + pa_log_warn("'%s' doesn't support full duplex", device); close(fd); } if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) { if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY)) < 0) { - pa_log(__FILE__": open('%s'): %s", device, pa_cstrerror(errno)); + pa_log("open('%s'): %s", device, pa_cstrerror(errno)); goto fail; } } } else { if ((fd = open(device, *mode|O_NDELAY)) < 0) { - pa_log(__FILE__": open('%s'): %s", device, pa_cstrerror(errno)); + pa_log("open('%s'): %s", device, pa_cstrerror(errno)); goto fail; } } @@ -87,11 +87,11 @@ success: *pcaps = 0; if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { - pa_log(__FILE__": SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); goto fail; } - pa_log_debug(__FILE__": capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + pa_log_debug("capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s%s", *pcaps & DSP_CAP_BATCH ? " BATCH" : "", *pcaps & DSP_CAP_BIND ? " BIND" : "", *pcaps & DSP_CAP_COPROC ? " COPROC" : "", @@ -168,7 +168,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != f) { format = AFMT_U8; if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != AFMT_U8) { - pa_log(__FILE__": SNDCTL_DSP_SETFMT: %s", format != AFMT_U8 ? "No supported sample format" : pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_SETFMT: %s", format != AFMT_U8 ? "No supported sample format" : pa_cstrerror(errno)); return -1; } else ss->format = PA_SAMPLE_U8; @@ -179,31 +179,31 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { } if (orig_format != ss->format) - pa_log_warn(__FILE__": device doesn't support sample format %s, changed to %s.", + pa_log_warn("device doesn't support sample format %s, changed to %s.", pa_sample_format_to_string(orig_format), pa_sample_format_to_string(ss->format)); channels = ss->channels; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { - pa_log(__FILE__": SNDCTL_DSP_CHANNELS: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_CHANNELS: %s", pa_cstrerror(errno)); return -1; } assert(channels > 0); if (ss->channels != channels) { - pa_log_warn(__FILE__": device doesn't support %i channels, using %i channels.", ss->channels, channels); + pa_log_warn("device doesn't support %i channels, using %i channels.", ss->channels, channels); ss->channels = channels; } speed = ss->rate; if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SPEED: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_SPEED: %s", pa_cstrerror(errno)); return -1; } assert(speed > 0); if (ss->rate != (unsigned) speed) { - pa_log_warn(__FILE__": device doesn't support %i Hz, changed to %i Hz.", ss->rate, speed); + pa_log_warn("device doesn't support %i Hz, changed to %i Hz.", ss->rate, speed); /* If the sample rate deviates too much, we need to resample */ if (speed < ss->rate*.95 || speed > ss->rate*1.05) @@ -230,7 +230,7 @@ int pa_oss_set_fragments(int fd, int nfrags, int frag_size) { arg = ((int) nfrags << 16) | simple_log2(frag_size); if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &arg) < 0) { - pa_log(__FILE__": SNDCTL_DSP_SETFRAGMENT: %s", pa_cstrerror(errno)); + pa_log("SNDCTL_DSP_SETFRAGMENT: %s", pa_cstrerror(errno)); return -1; } @@ -253,7 +253,7 @@ static int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvo if ((volume->channels = ss->channels) >= 2) volume->values[1] = (((vol >> 8) & 0xFF) * PA_VOLUME_NORM) / 100; - pa_log_debug(__FILE__": Read mixer settings: %s", pa_cvolume_snprint(cv, sizeof(cv), volume)); + pa_log_debug("Read mixer settings: %s", pa_cvolume_snprint(cv, sizeof(cv), volume)); return 0; } @@ -274,7 +274,7 @@ static int pa_oss_set_volume(int fd, int mixer, const pa_sample_spec *ss, const if (ioctl(fd, mixer, &vol) < 0) return -1; - pa_log_debug(__FILE__": Wrote mixer settings: %s", pa_cvolume_snprint(cv, sizeof(cv), volume)); + pa_log_debug("Wrote mixer settings: %s", pa_cvolume_snprint(cv, sizeof(cv), volume)); return 0; } @@ -319,7 +319,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { !(f = fopen("/proc/asound/oss/sndstat", "r"))) { if (errno != ENOENT) - pa_log_warn(__FILE__": failed to open OSS sndstat device: %s", pa_cstrerror(errno)); + pa_log_warn("failed to open OSS sndstat device: %s", pa_cstrerror(errno)); return -1; } diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 5d3f3e279..338d57cfa 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -165,7 +165,7 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event s->offset = s->rtp_context.timestamp; if (s->ssrc == s->userdata->core->cookie) - pa_log_warn(__FILE__": WARNING! Detected RTP packet loop!"); + pa_log_warn("WARNING! Detected RTP packet loop!"); } else { if (s->ssrc != s->rtp_context.ssrc) { pa_memblock_unref(chunk.memblock); @@ -217,13 +217,13 @@ static int mcast_socket(const struct sockaddr* sa, socklen_t salen) { af = sa->sa_family; if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) { - pa_log(__FILE__": Failed to create socket: %s", pa_cstrerror(errno)); + pa_log("Failed to create socket: %s", pa_cstrerror(errno)); goto fail; } one = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) { - pa_log(__FILE__": SO_REUSEADDR failed: %s", pa_cstrerror(errno)); + pa_log("SO_REUSEADDR failed: %s", pa_cstrerror(errno)); goto fail; } @@ -240,12 +240,12 @@ static int mcast_socket(const struct sockaddr* sa, socklen_t salen) { } if (r < 0) { - pa_log_info(__FILE__": Joining mcast group failed: %s", pa_cstrerror(errno)); + pa_log_info("Joining mcast group failed: %s", pa_cstrerror(errno)); goto fail; } if (bind(fd, sa, salen) < 0) { - pa_log(__FILE__": bind() failed: %s", pa_cstrerror(errno)); + pa_log("bind() failed: %s", pa_cstrerror(errno)); goto fail; } @@ -268,12 +268,12 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_sink_input_new_data data; if (u->n_sessions >= MAX_SESSIONS) { - pa_log(__FILE__": session limit reached."); + pa_log("session limit reached."); goto fail; } if (!(sink = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": sink does not exist."); + pa_log("sink does not exist."); goto fail; } @@ -301,7 +301,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_xfree(c); if (!s->sink_input) { - pa_log(__FILE__": failed to create sink input."); + pa_log("failed to create sink input."); goto fail; } @@ -338,7 +338,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_rtp_context_init_recv(&s->rtp_context, fd, pa_frame_size(&s->sdp_info.sample_spec)); - pa_log_info(__FILE__": Found new session '%s'", s->sdp_info.session_name); + pa_log_info("Found new session '%s'", s->sdp_info.session_name); u->n_sessions++; @@ -358,7 +358,7 @@ fail: static void session_free(struct session *s, int from_hash) { assert(s); - pa_log_info(__FILE__": Freeing session '%s'", s->sdp_info.session_name); + pa_log_info("Freeing session '%s'", s->sdp_info.session_name); s->userdata->core->mainloop->time_free(s->death_event); s->userdata->core->mainloop->io_free(s->rtp_event); @@ -435,7 +435,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } @@ -452,7 +452,7 @@ int pa__init(pa_core *c, pa_module*m) { sa = (struct sockaddr*) &sa4; salen = sizeof(sa4); } else { - pa_log(__FILE__": invalid SAP address '%s'", sap_address); + pa_log("invalid SAP address '%s'", sap_address); goto fail; } diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 1b85c840b..61dd00472 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -105,7 +105,7 @@ static void source_output_push(pa_source_output *o, const pa_memchunk *chunk) { u = o->userdata; if (pa_memblockq_push(u->memblockq, chunk) < 0) { - pa_log(__FILE__": Failed to push chunk into memblockq."); + pa_log("Failed to push chunk into memblockq."); return; } @@ -174,17 +174,17 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": failed to parse module arguments"); + pa_log("failed to parse module arguments"); goto fail; } if (!(s = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source", NULL), PA_NAMEREG_SOURCE, 1))) { - pa_log(__FILE__": source does not exist."); + pa_log("source does not exist."); goto fail; } if (pa_modargs_get_value_boolean(ma, "loop", &loop) < 0) { - pa_log(__FILE__": failed to parse \"loop\" parameter."); + pa_log("failed to parse \"loop\" parameter."); goto fail; } @@ -192,12 +192,12 @@ int pa__init(pa_core *c, pa_module*m) { pa_rtp_sample_spec_fixup(&ss); cm = s->channel_map; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log(__FILE__": failed to parse sample specification"); + pa_log("failed to parse sample specification"); goto fail; } if (!pa_rtp_sample_spec_valid(&ss)) { - pa_log(__FILE__": specified sample type not compatible with RTP"); + pa_log("specified sample type not compatible with RTP"); goto fail; } @@ -209,18 +209,18 @@ int pa__init(pa_core *c, pa_module*m) { mtu = (DEFAULT_MTU/pa_frame_size(&ss))*pa_frame_size(&ss); if (pa_modargs_get_value_u32(ma, "mtu", &mtu) < 0 || mtu < 1 || mtu % pa_frame_size(&ss) != 0) { - pa_log(__FILE__": invalid mtu."); + pa_log("invalid mtu."); goto fail; } port = DEFAULT_PORT + ((rand() % 512) << 1); if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { - pa_log(__FILE__": port= expects a numerical argument between 1 and 65535."); + pa_log("port= expects a numerical argument between 1 and 65535."); goto fail; } if (port & 1) - pa_log_warn(__FILE__": WARNING: port number not even as suggested in RFC3550!"); + pa_log_warn("WARNING: port number not even as suggested in RFC3550!"); dest = pa_modargs_get_value(ma, "destination", DEFAULT_DESTINATION); @@ -235,33 +235,33 @@ int pa__init(pa_core *c, pa_module*m) { sap_sa4 = sa4; sap_sa4.sin_port = htons(SAP_PORT); } else { - pa_log(__FILE__": invalid destination '%s'", dest); + pa_log("invalid destination '%s'", dest); goto fail; } if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) { - pa_log(__FILE__": socket() failed: %s", pa_cstrerror(errno)); + pa_log("socket() failed: %s", pa_cstrerror(errno)); goto fail; } if (connect(fd, af == AF_INET ? (struct sockaddr*) &sa4 : (struct sockaddr*) &sa6, af == AF_INET ? sizeof(sa4) : sizeof(sa6)) < 0) { - pa_log(__FILE__": connect() failed: %s", pa_cstrerror(errno)); + pa_log("connect() failed: %s", pa_cstrerror(errno)); goto fail; } if ((sap_fd = socket(af, SOCK_DGRAM, 0)) < 0) { - pa_log(__FILE__": socket() failed: %s", pa_cstrerror(errno)); + pa_log("socket() failed: %s", pa_cstrerror(errno)); goto fail; } if (connect(sap_fd, af == AF_INET ? (struct sockaddr*) &sap_sa4 : (struct sockaddr*) &sap_sa6, af == AF_INET ? sizeof(sap_sa4) : sizeof(sap_sa6)) < 0) { - pa_log(__FILE__": connect() failed: %s", pa_cstrerror(errno)); + pa_log("connect() failed: %s", pa_cstrerror(errno)); goto fail; } if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0 || setsockopt(sap_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) { - pa_log(__FILE__": IP_MULTICAST_LOOP failed: %s", pa_cstrerror(errno)); + pa_log("IP_MULTICAST_LOOP failed: %s", pa_cstrerror(errno)); goto fail; } @@ -274,7 +274,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_source_output_new_data_set_channel_map(&data, &cm); if (!(o = pa_source_output_new(c, &data, 0))) { - pa_log(__FILE__": failed to create source output."); + pa_log("failed to create source output."); goto fail; } @@ -317,8 +317,8 @@ int pa__init(pa_core *c, pa_module*m) { pa_rtp_context_init_send(&u->rtp_context, fd, c->cookie, payload, pa_frame_size(&ss)); pa_sap_context_init_send(&u->sap_context, sap_fd, p); - pa_log_info(__FILE__": RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence); - pa_log_info(__FILE__": SDP-Data:\n%s\n"__FILE__": EOF", p); + pa_log_info("RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence); + pa_log_info("SDP-Data:\n%s\n"__FILE__": EOF", p); pa_sap_send(&u->sap_context, 0); diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index 8e77c60a6..3bb0ea473 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -125,7 +125,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { if (k < 0) { if (errno != EAGAIN) /* If the queue is full, just ignore it */ - pa_log(__FILE__": sendmsg() failed: %s", pa_cstrerror(errno)); + pa_log("sendmsg() failed: %s", pa_cstrerror(errno)); return -1; } @@ -163,7 +163,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { chunk->memblock = NULL; if (ioctl(c->fd, FIONREAD, &size) < 0) { - pa_log(__FILE__": FIONREAD failed: %s", pa_cstrerror(errno)); + pa_log("FIONREAD failed: %s", pa_cstrerror(errno)); goto fail; } @@ -184,12 +184,12 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { m.msg_flags = 0; if ((r = recvmsg(c->fd, &m, 0)) != size) { - pa_log(__FILE__": recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); + pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); goto fail; } if (size < 12) { - pa_log(__FILE__": RTP packet too short."); + pa_log("RTP packet too short."); goto fail; } @@ -202,17 +202,17 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { c->ssrc = ntohl(c->ssrc); if ((header >> 30) != 2) { - pa_log(__FILE__": Unsupported RTP version."); + pa_log("Unsupported RTP version."); goto fail; } if ((header >> 29) & 1) { - pa_log(__FILE__": RTP padding not supported."); + pa_log("RTP padding not supported."); goto fail; } if ((header >> 28) & 1) { - pa_log(__FILE__": RTP header extensions not supported."); + pa_log("RTP header extensions not supported."); goto fail; } @@ -221,7 +221,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { c->sequence = header & 0xFFFF; if (12 + cc*4 > size) { - pa_log(__FILE__": RTP packet too short. (CSRC)"); + pa_log("RTP packet too short. (CSRC)"); goto fail; } @@ -229,7 +229,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { chunk->length = size - chunk->index; if (chunk->length % c->frame_size != 0) { - pa_log(__FILE__": Vad RTP packet size."); + pa_log("Vad RTP packet size."); goto fail; } diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index 615b8e4eb..022c7fa33 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -138,7 +138,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { assert(goodbye); if (ioctl(c->fd, FIONREAD, &size) < 0) { - pa_log(__FILE__": FIONREAD failed: %s", pa_cstrerror(errno)); + pa_log("FIONREAD failed: %s", pa_cstrerror(errno)); goto fail; } @@ -160,12 +160,12 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { m.msg_flags = 0; if ((r = recvmsg(c->fd, &m, 0)) != size) { - pa_log(__FILE__": recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); + pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); goto fail; } if (size < 4) { - pa_log(__FILE__": SAP packet too short."); + pa_log("SAP packet too short."); goto fail; } @@ -173,17 +173,17 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { header = ntohl(header); if (header >> 29 != 1) { - pa_log(__FILE__": Unsupported SAP version."); + pa_log("Unsupported SAP version."); goto fail; } if ((header >> 25) & 1) { - pa_log(__FILE__": Encrypted SAP not supported."); + pa_log("Encrypted SAP not supported."); goto fail; } if ((header >> 24) & 1) { - pa_log(__FILE__": Compressed SAP not supported."); + pa_log("Compressed SAP not supported."); goto fail; } @@ -192,7 +192,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { k = 4 + (six ? 16 : 4) + ac*4; if (size < k) { - pa_log(__FILE__": SAP packet too short (AD)."); + pa_log("SAP packet too short (AD)."); goto fail; } @@ -203,7 +203,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { e += sizeof(MIME_TYPE); size -= sizeof(MIME_TYPE); } else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)) { - pa_log(__FILE__": Invalid SDP header."); + pa_log("Invalid SDP header."); goto fail; } diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index e707e4bb5..1b71a9a01 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -129,7 +129,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { i->payload = 255; if (!pa_startswith(t, PA_SDP_HEADER)) { - pa_log(__FILE__": Failed to parse SDP data: invalid header."); + pa_log("Failed to parse SDP data: invalid header."); goto fail; } @@ -141,7 +141,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { l = strcspn(t, "\n"); if (l <= 2) { - pa_log(__FILE__": Failed to parse SDP data: line too short: >%s<.", t); + pa_log("Failed to parse SDP data: line too short: >%s<.", t); goto fail; } @@ -159,7 +159,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { a[strcspn(a, "/")] = 0; if (inet_pton(AF_INET, a, &((struct sockaddr_in*) &i->sa)->sin_addr) <= 0) { - pa_log(__FILE__": Failed to parse SDP data: bad address: >%s<.", a); + pa_log("Failed to parse SDP data: bad address: >%s<.", a); goto fail; } @@ -176,7 +176,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { a[strcspn(a, "/")] = 0; if (inet_pton(AF_INET6, a, &((struct sockaddr_in6*) &i->sa)->sin6_addr) <= 0) { - pa_log(__FILE__": Failed to parse SDP data: bad address: >%s<.", a); + pa_log("Failed to parse SDP data: bad address: >%s<.", a); goto fail; } @@ -191,12 +191,12 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { if (sscanf(t+8, "%i RTP/AVP %i", &_port, &_payload) == 2) { if (_port <= 0 || _port > 0xFFFF) { - pa_log(__FILE__": Failed to parse SDP data: invalid port %i.", _port); + pa_log("Failed to parse SDP data: invalid port %i.", _port); goto fail; } if (_payload < 0 || _payload > 127) { - pa_log(__FILE__": Failed to parse SDP data: invalid payload %i.", _payload); + pa_log("Failed to parse SDP data: invalid payload %i.", _payload); goto fail; } @@ -216,7 +216,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { if (sscanf(t+9, "%i %64c", &_payload, c) == 2) { if (_payload < 0 || _payload > 127) { - pa_log(__FILE__": Failed to parse SDP data: invalid payload %i.", _payload); + pa_log("Failed to parse SDP data: invalid payload %i.", _payload); goto fail; } if (_payload == i->payload) { @@ -237,7 +237,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { } if (!i->origin || (!is_goodbye && (!i->salen || i->payload > 127 || !ss_valid || port == 0))) { - pa_log(__FILE__": Failed to parse SDP data: missing data."); + pa_log("Failed to parse SDP data: missing data."); goto fail; } diff --git a/src/pulse/client-conf-x11.c b/src/pulse/client-conf-x11.c index e4a900177..8cedc48b9 100644 --- a/src/pulse/client-conf-x11.c +++ b/src/pulse/client-conf-x11.c @@ -46,7 +46,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { goto finish; if (!(d = XOpenDisplay(dname))) { - pa_log(__FILE__": XOpenDisplay() failed"); + pa_log("XOpenDisplay() failed"); goto finish; } @@ -69,7 +69,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; if (pa_parsehex(t, cookie, sizeof(cookie)) != sizeof(cookie)) { - pa_log(__FILE__": failed to parse cookie data"); + pa_log("failed to parse cookie data"); goto finish; } diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index c3f58ec24..619b11c3b 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -116,7 +116,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn, "r"); if (!f && errno != EINTR) { - pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s", fn, pa_cstrerror(errno)); + pa_log("WARNING: failed to open configuration file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } diff --git a/src/pulse/context.c b/src/pulse/context.c index b35305424..df627ee67 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -462,7 +462,7 @@ static int context_connect_spawn(pa_context *c) { pa_context_ref(c); if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - pa_log(__FILE__": socketpair(): %s", pa_cstrerror(errno)); + pa_log("socketpair(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } @@ -476,7 +476,7 @@ static int context_connect_spawn(pa_context *c) { c->spawn_api.prefork(); if ((pid = fork()) < 0) { - pa_log(__FILE__": fork(): %s", pa_cstrerror(errno)); + pa_log("fork(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); if (c->spawn_api.postfork) @@ -532,7 +532,7 @@ static int context_connect_spawn(pa_context *c) { c->spawn_api.postfork(); if (r < 0) { - pa_log(__FILE__": waitpid(): %s", pa_cstrerror(errno)); + pa_log("waitpid(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { @@ -594,7 +594,7 @@ static int try_next_connection(pa_context *c) { goto finish; } - pa_log_debug(__FILE__": Trying to connect to %s...", u); + pa_log_debug("Trying to connect to %s...", u); pa_xfree(c->server); c->server = pa_xstrdup(u); diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c index 11a27cd50..d651462b0 100644 --- a/src/pulse/mainloop-signal.c +++ b/src/pulse/mainloop-signal.c @@ -90,12 +90,12 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags if (errno == EAGAIN) return; - pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); + pa_log("read(): %s", pa_cstrerror(errno)); return; } if (r != sizeof(sig)) { - pa_log(__FILE__": short read()"); + pa_log("short read()"); return; } @@ -107,7 +107,7 @@ int pa_signal_init(pa_mainloop_api *a) { assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event); if (pipe(signal_pipe) < 0) { - pa_log(__FILE__": pipe(): %s", pa_cstrerror(errno)); + pa_log("pipe(): %s", pa_cstrerror(errno)); return -1; } diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 5ebb9bc86..f7b155373 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -192,7 +192,7 @@ static pa_io_event* mainloop_io_new( if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset, SELECT_TYPE_ARG5 &tv) == -1) && (WSAGetLastError() == WSAENOTSOCK)) { - pa_log_warn(__FILE__": WARNING: cannot monitor non-socket file descriptors."); + pa_log_warn("WARNING: cannot monitor non-socket file descriptors."); e->dead = 1; } } @@ -448,7 +448,7 @@ pa_mainloop *pa_mainloop_new(void) { m->wakeup_pipe_type = 0; if (pipe(m->wakeup_pipe) < 0) { - pa_log_error(__FILE__": ERROR: cannot create wakeup pipe"); + pa_log_error("ERROR: cannot create wakeup pipe"); pa_xfree(m); return NULL; } @@ -852,7 +852,7 @@ int pa_mainloop_poll(pa_mainloop *m) { if (errno == EINTR) m->poll_func_ret = 0; else - pa_log(__FILE__": poll(): %s", pa_cstrerror(errno)); + pa_log("poll(): %s", pa_cstrerror(errno)); } } diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c index 34f0f2503..b1b180a08 100644 --- a/src/pulse/thread-mainloop.c +++ b/src/pulse/thread-mainloop.c @@ -421,7 +421,7 @@ pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) { #else /* defined(OS_IS_WIN32) || defined(HAVE_PTHREAD) */ pa_threaded_mainloop *pa_threaded_mainloop_new(void) { - pa_log_error(__FILE__": Threaded main loop not supported on this platform"); + pa_log_error("Threaded main loop not supported on this platform"); return NULL; } diff --git a/src/pulse/util.c b/src/pulse/util.c index b041fec80..c13951da4 100644 --- a/src/pulse/util.c +++ b/src/pulse/util.c @@ -112,7 +112,7 @@ char *pa_get_user_name(char *s, size_t l) { char *pa_get_host_name(char *s, size_t l) { assert(s && l > 0); if (gethostname(s, l) < 0) { - pa_log(__FILE__": gethostname(): %s", pa_cstrerror(errno)); + pa_log("gethostname(): %s", pa_cstrerror(errno)); return NULL; } s[l-1] = 0; @@ -138,12 +138,12 @@ char *pa_get_home_dir(char *s, size_t l) { #ifdef HAVE_PWD_H #ifdef HAVE_GETPWUID_R if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { - pa_log(__FILE__": getpwuid_r() failed"); + pa_log("getpwuid_r() failed"); #else /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) * that do not support getpwuid_r. */ if ((r = getpwuid(getuid())) == NULL) { - pa_log(__FILE__": getpwuid_r() failed"); + pa_log("getpwuid_r() failed"); #endif return NULL; } diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c index a5df3ed1d..87631ca53 100644 --- a/src/pulsecore/authkey.c +++ b/src/pulsecore/authkey.c @@ -54,7 +54,7 @@ static int generate(int fd, void *ret_data, size_t length) { ftruncate(fd, 0); if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) { - pa_log(__FILE__": failed to write cookie file: %s", pa_cstrerror(errno)); + pa_log("failed to write cookie file: %s", pa_cstrerror(errno)); return -1; } @@ -76,7 +76,7 @@ static int load(const char *fn, void *data, size_t length) { if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR)) < 0) { if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY)) < 0) { - pa_log(__FILE__": failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_log("failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } else writable = 0; @@ -85,15 +85,15 @@ static int load(const char *fn, void *data, size_t length) { unlock = pa_lock_fd(fd, 1) >= 0; if ((r = pa_loop_read(fd, data, length, NULL)) < 0) { - pa_log(__FILE__": failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_log("failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } if ((size_t) r != length) { - pa_log_debug(__FILE__": got %d bytes from cookie file '%s', expected %d", (int)r, fn, (int)length); + pa_log_debug("got %d bytes from cookie file '%s', expected %d", (int)r, fn, (int)length); if (!writable) { - pa_log(__FILE__": unable to write cookie to read only file"); + pa_log("unable to write cookie to read only file"); goto finish; } @@ -125,7 +125,7 @@ int pa_authkey_load(const char *path, void *data, size_t length) { ret = load(path, data, length); if (ret < 0) - pa_log(__FILE__": Failed to load authorization key '%s': %s", path, + pa_log("Failed to load authorization key '%s': %s", path, (ret == -1) ? pa_cstrerror(errno) : "file corrupt"); return ret; @@ -182,14 +182,14 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) { return -2; if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_log("failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } unlock = pa_lock_fd(fd, 1) >= 0; if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) { - pa_log(__FILE__": failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_log("failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c index 7c2840668..e3fc2e4cd 100644 --- a/src/pulsecore/cli.c +++ b/src/pulsecore/cli.c @@ -104,7 +104,7 @@ static void client_kill(pa_client *client) { assert(client && client->userdata); c = client->userdata; - pa_log_debug(__FILE__": CLI client killed."); + pa_log_debug("CLI client killed."); if (c->defer_kill) c->kill_requested = 1; else { @@ -120,7 +120,7 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { assert(line && c); if (!s) { - pa_log_debug(__FILE__": CLI got EOF from user."); + pa_log_debug("CLI got EOF from user."); if (c->eof_callback) c->eof_callback(c, c->userdata); diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c index bf2b13df7..c34bf1490 100644 --- a/src/pulsecore/client.c +++ b/src/pulsecore/client.c @@ -52,7 +52,7 @@ pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) { r = pa_idxset_put(core->clients, c, &c->index); assert(c->index != PA_IDXSET_INVALID && r >= 0); - pa_log_info(__FILE__": created %u \"%s\"", c->index, c->name); + pa_log_info("created %u \"%s\"", c->index, c->name); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); pa_core_check_quit(core); @@ -67,7 +67,7 @@ void pa_client_free(pa_client *c) { pa_core_check_quit(c->core); - pa_log_info(__FILE__": freed %u \"%s\"", c->index, c->name); + pa_log_info("freed %u \"%s\"", c->index, c->name); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_xfree(c->name); pa_xfree(c->driver); @@ -77,7 +77,7 @@ void pa_client_free(pa_client *c) { void pa_client_kill(pa_client *c) { assert(c); if (!c->kill) { - pa_log_warn(__FILE__": kill() operation not implemented for client %u", c->index); + pa_log_warn("kill() operation not implemented for client %u", c->index); return; } @@ -87,7 +87,7 @@ void pa_client_kill(pa_client *c) { void pa_client_set_name(pa_client *c, const char *name) { assert(c); - pa_log_info(__FILE__": client %u changed name from \"%s\" to \"%s\"", c->index, c->name, name); + pa_log_info("client %u changed name from \"%s\" to \"%s\"", c->index, c->name, name); pa_xfree(c->name); c->name = pa_xstrdup(name); diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index cc471ff92..db1e37192 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -47,7 +47,7 @@ static int next_assignment(const char *filename, unsigned line, const pa_config_ if (!strcmp(lvalue, t->lvalue)) return t->parse(filename, line, lvalue, rvalue, t->data, userdata); - pa_log(__FILE__": [%s:%u] Unknown lvalue '%s'.", filename, line, lvalue); + pa_log("[%s:%u] Unknown lvalue '%s'.", filename, line, lvalue); return -1; } @@ -90,7 +90,7 @@ static int parse_line(const char *filename, unsigned line, const pa_config_item return 0; if (!(e = strchr(b, '='))) { - pa_log(__FILE__": [%s:%u] Missing '='.", filename, line); + pa_log("[%s:%u] Missing '='.", filename, line); return -1; } @@ -113,7 +113,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void goto finish; } - pa_log_warn(__FILE__": WARNING: failed to open configuration file '%s': %s", + pa_log_warn("WARNING: failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } @@ -124,7 +124,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void if (feof(f)) break; - pa_log_warn(__FILE__": WARNING: failed to read configuration file '%s': %s", + pa_log_warn("WARNING: failed to read configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } @@ -149,7 +149,7 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, assert(filename && lvalue && rvalue && data); if (pa_atoi(rvalue, &k) < 0) { - pa_log(__FILE__": [%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); + pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); return -1; } @@ -162,7 +162,7 @@ int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue assert(filename && lvalue && rvalue && data); if ((k = pa_parse_boolean(rvalue)) < 0) { - pa_log(__FILE__": [%s:%u] Failed to parse boolean value: %s", filename, line, rvalue); + pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue); return -1; } diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c index ca2408fe7..e3bf3ca21 100644 --- a/src/pulsecore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -360,7 +360,7 @@ static void add_file(pa_core *c, const char *pathname) { e = pa_path_get_filename(pathname); if (stat(pathname, &st) < 0) { - pa_log(__FILE__": stat('%s'): %s", pathname, pa_cstrerror(errno)); + pa_log("stat('%s'): %s", pathname, pa_cstrerror(errno)); return; } @@ -382,7 +382,7 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) { /* If that fails, try to open it as shell glob */ if (glob(pathname, GLOB_ERR|GLOB_NOSORT, NULL, &p) < 0) { - pa_log(__FILE__": failed to open directory '%s': %s", pathname, pa_cstrerror(errno)); + pa_log("failed to open directory '%s': %s", pathname, pa_cstrerror(errno)); return -1; } diff --git a/src/pulsecore/core-subscribe.c b/src/pulsecore/core-subscribe.c index 37673da57..4df1d5112 100644 --- a/src/pulsecore/core-subscribe.c +++ b/src/pulsecore/core-subscribe.c @@ -145,7 +145,7 @@ static void dump_event(const char * prefix, pa_subscription_event*e) { [PA_SUBSCRIPTION_EVENT_REMOVE] = "REMOVE" }; - pa_log(__FILE__": %s event (%s|%s|%u)", + pa_log("%s event (%s|%s|%u)", prefix, fac_table[e->type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK], type_table[e->type & PA_SUBSCRIPTION_EVENT_TYPE_MASK], @@ -234,7 +234,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i * entry in the queue. */ free_event(i); - pa_log_debug(__FILE__": dropped redundant event."); + pa_log_debug("dropped redundant event."); continue; } @@ -242,7 +242,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i /* This object has changed. If a "new" or "change" event for * this object is still in the queue we can exit. */ - pa_log_debug(__FILE__": dropped redundant event."); + pa_log_debug("dropped redundant event."); return; } } diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 595ef939f..b504b6d34 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -128,10 +128,10 @@ void pa_make_nonblock_fd(int fd) { u_long arg = 1; if (ioctlsocket(fd, FIONBIO, &arg) < 0) { if (WSAGetLastError() == WSAENOTSOCK) - pa_log_warn(__FILE__": WARNING: Only sockets can be made non-blocking!"); + pa_log_warn("WARNING: Only sockets can be made non-blocking!"); } #else - pa_log_warn(__FILE__": WARNING: Non-blocking I/O not supported.!"); + pa_log_warn("WARNING: Non-blocking I/O not supported.!"); #endif } @@ -359,7 +359,7 @@ void pa_check_signal_is_blocked(int sig) { if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) { #endif if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) { - pa_log(__FILE__": sigprocmask(): %s", pa_cstrerror(errno)); + pa_log("sigprocmask(): %s", pa_cstrerror(errno)); return; } #ifdef HAVE_PTHREAD @@ -372,16 +372,16 @@ void pa_check_signal_is_blocked(int sig) { /* Check whether the signal is trapped */ if (sigaction(sig, NULL, &sa) < 0) { - pa_log(__FILE__": sigaction(): %s", pa_cstrerror(errno)); + pa_log("sigaction(): %s", pa_cstrerror(errno)); return; } if (sa.sa_handler != SIG_DFL) return; - pa_log(__FILE__": WARNING: %s is not trapped. This might cause malfunction!", pa_strsignal(sig)); + pa_log("WARNING: %s is not trapped. This might cause malfunction!", pa_strsignal(sig)); #else /* HAVE_SIGACTION */ - pa_log(__FILE__": WARNING: %s might not be trapped. This might cause malfunction!", pa_strsignal(sig)); + pa_log("WARNING: %s might not be trapped. This might cause malfunction!", pa_strsignal(sig)); #endif } @@ -460,9 +460,9 @@ void pa_raise_priority(void) { #ifdef HAVE_SYS_RESOURCE_H if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) - pa_log_warn(__FILE__": setpriority(): %s", pa_cstrerror(errno)); + pa_log_warn("setpriority(): %s", pa_cstrerror(errno)); else - pa_log_info(__FILE__": Successfully gained nice level %i.", NICE_LEVEL); + pa_log_info("Successfully gained nice level %i.", NICE_LEVEL); #endif #ifdef _POSIX_PRIORITY_SCHEDULING @@ -470,25 +470,25 @@ void pa_raise_priority(void) { struct sched_param sp; if (sched_getparam(0, &sp) < 0) { - pa_log(__FILE__": sched_getparam(): %s", pa_cstrerror(errno)); + pa_log("sched_getparam(): %s", pa_cstrerror(errno)); return; } sp.sched_priority = 1; if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) { - pa_log_warn(__FILE__": sched_setscheduler(): %s", pa_cstrerror(errno)); + pa_log_warn("sched_setscheduler(): %s", pa_cstrerror(errno)); return; } - pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling."); + pa_log_info("Successfully enabled SCHED_FIFO scheduling."); } #endif #ifdef OS_IS_WIN32 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) - pa_log_warn(__FILE__": SetPriorityClass() failed: 0x%08X", GetLastError()); + pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError()); else - pa_log_info(__FILE__": Successfully gained high priority class."); + pa_log_info("Successfully gained high priority class."); #endif } @@ -627,7 +627,7 @@ static int is_group(gid_t gid, const char *name) { data = pa_xmalloc(n); if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) { - pa_log(__FILE__": getgrgid_r(%u): %s", (unsigned)gid, pa_cstrerror(errno)); + pa_log("getgrgid_r(%u): %s", (unsigned)gid, pa_cstrerror(errno)); goto finish; } @@ -639,7 +639,7 @@ finish: /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not * support getgrgid_r. */ if ((result = getgrgid(gid)) == NULL) { - pa_log(__FILE__": getgrgid(%u): %s", gid, pa_cstrerror(errno)); + pa_log("getgrgid(%u): %s", gid, pa_cstrerror(errno)); goto finish; } @@ -662,7 +662,7 @@ int pa_own_uid_in_group(const char *name, gid_t *gid) { gids = pa_xmalloc(sizeof(GETGROUPS_T)*n); if ((n = getgroups(n, gids)) < 0) { - pa_log(__FILE__": getgroups(): %s", pa_cstrerror(errno)); + pa_log("getgroups(): %s", pa_cstrerror(errno)); goto finish; } @@ -803,7 +803,7 @@ int pa_lock_fd(int fd, int b) { return 0; } - pa_log(__FILE__": %slock: %s", !b? "un" : "", + pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno)); #endif @@ -815,7 +815,7 @@ int pa_lock_fd(int fd, int b) { if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF)) return 0; - pa_log(__FILE__": %slock failed: 0x%08X", !b ? "un" : "", GetLastError()); + pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError()); #endif return -1; @@ -838,18 +838,18 @@ int pa_lock_lockfile(const char *fn) { struct stat st; if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": failed to create lock file '%s': %s", fn, + pa_log("failed to create lock file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } if (pa_lock_fd(fd, 1) < 0) { - pa_log(__FILE__": failed to lock file '%s'.", fn); + pa_log("failed to lock file '%s'.", fn); goto fail; } if (fstat(fd, &st) < 0) { - pa_log(__FILE__": failed to fstat() file '%s'.", fn); + pa_log("failed to fstat() file '%s'.", fn); goto fail; } @@ -858,12 +858,12 @@ int pa_lock_lockfile(const char *fn) { break; if (pa_lock_fd(fd, 0) < 0) { - pa_log(__FILE__": failed to unlock file '%s'.", fn); + pa_log("failed to unlock file '%s'.", fn); goto fail; } if (close(fd) < 0) { - pa_log(__FILE__": failed to close file '%s'.", fn); + pa_log("failed to close file '%s'.", fn); goto fail; } @@ -886,18 +886,18 @@ int pa_unlock_lockfile(const char *fn, int fd) { assert(fn && fd >= 0); if (unlink(fn) < 0) { - pa_log_warn(__FILE__": WARNING: unable to remove lock file '%s': %s", + pa_log_warn("WARNING: unable to remove lock file '%s': %s", fn, pa_cstrerror(errno)); r = -1; } if (pa_lock_fd(fd, 0) < 0) { - pa_log_warn(__FILE__": WARNING: failed to unlock file '%s'.", fn); + pa_log_warn("WARNING: failed to unlock file '%s'.", fn); r = -1; } if (close(fd) < 0) { - pa_log_warn(__FILE__": WARNING: failed to close lock file '%s': %s", + pa_log_warn("WARNING: failed to close lock file '%s': %s", fn, pa_cstrerror(errno)); r = -1; } diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c index 9c9900f8b..a3bca22f9 100644 --- a/src/pulsecore/ioline.c +++ b/src/pulsecore/ioline.c @@ -292,7 +292,7 @@ static int do_read(pa_ioline *l) { /* Read some data */ if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) { if (r < 0) { - pa_log(__FILE__": read(): %s", pa_cstrerror(errno)); + pa_log("read(): %s", pa_cstrerror(errno)); failure(l, 0); } else failure(l, 1); @@ -317,7 +317,7 @@ static int do_write(pa_ioline *l) { while (!l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length) { if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) { - pa_log(__FILE__": write(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); + pa_log("write(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); failure(l, 0); return -1; } diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c index 15b6b3f9a..36159fabf 100644 --- a/src/pulsecore/ipacl.c +++ b/src/pulsecore/ipacl.c @@ -88,7 +88,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { *slash = 0; slash++; if (pa_atou(slash, &bits) < 0) { - pa_log(__FILE__": failed to parse number of bits: %s", slash); + pa_log("failed to parse number of bits: %s", slash); goto fail; } } else @@ -99,21 +99,21 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { e.bits = bits == (uint32_t) -1 ? 32 : (int) bits; if (e.bits > 32) { - pa_log(__FILE__": number of bits out of range: %i", e.bits); + pa_log("number of bits out of range: %i", e.bits); goto fail; } e.family = AF_INET; if (e.bits < 32 && (uint32_t) (ntohl(e.address_ipv4.s_addr) << e.bits) != 0) - pa_log_warn(__FILE__": WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); + pa_log_warn("WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); } else if (inet_pton(AF_INET6, a, &e.address_ipv6) > 0) { e.bits = bits == (uint32_t) -1 ? 128 : (int) bits; if (e.bits > 128) { - pa_log(__FILE__": number of bits out of range: %i", e.bits); + pa_log("number of bits out of range: %i", e.bits); goto fail; } e.family = AF_INET6; @@ -135,11 +135,11 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { } if (t) - pa_log_warn(__FILE__": WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); + pa_log_warn("WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); } } else { - pa_log(__FILE__": failed to parse address: %s", a); + pa_log("failed to parse address: %s", a); goto fail; } diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 4ce1b7c1a..2109d83ce 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -184,7 +184,7 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { } else if (p->n_init < p->n_blocks) slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * p->n_init++)); else { - pa_log_debug(__FILE__": Pool full"); + pa_log_debug("Pool full"); p->stat.n_pool_full++; return NULL; } @@ -241,7 +241,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { b->type = PA_MEMBLOCK_POOL_EXTERNAL; b->data = mempool_slot_data(slot); } else { - pa_log_debug(__FILE__": Memory block to large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot)); + pa_log_debug("Memory block to large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot)); p->stat.n_too_large_for_pool++; return NULL; } @@ -464,7 +464,7 @@ void pa_mempool_free(pa_mempool *p) { pa_memexport_free(p->exports); if (p->stat.n_allocated > 0) - pa_log_warn(__FILE__": WARNING! Memory pool destroyed but not all memory blocks freed!"); + pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!"); pa_shm_free(&p->memory); pa_xfree(p); diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index 2fd38850e..e6b73fc55 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -74,7 +74,7 @@ pa_memblockq* pa_memblockq_new( bq->base = base; bq->read_index = bq->write_index = idx; - pa_log_debug(__FILE__": memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", + pa_log_debug("memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", (unsigned long)maxlength, (unsigned long)tlength, (unsigned long)base, (unsigned long)prebuf, (unsigned long)minreq); bq->maxlength = ((maxlength+base-1)/base)*base; @@ -97,7 +97,7 @@ pa_memblockq* pa_memblockq_new( if (!bq->minreq) bq->minreq = 1; - pa_log_debug(__FILE__": memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", + pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", (unsigned long)bq->maxlength, (unsigned long)bq->tlength, (unsigned long)bq->base, (unsigned long)bq->prebuf, (unsigned long)bq->minreq); bq->state = bq->prebuf ? PREBUF : RUNNING; diff --git a/src/pulsecore/modinfo.c b/src/pulsecore/modinfo.c index adefdb46f..00720113a 100644 --- a/src/pulsecore/modinfo.c +++ b/src/pulsecore/modinfo.c @@ -73,7 +73,7 @@ pa_modinfo *pa_modinfo_get_by_name(const char *name) { assert(name); if (!(dl = lt_dlopenext(name))) { - pa_log(__FILE__": Failed to open module \"%s\": %s", name, lt_dlerror()); + pa_log("Failed to open module \"%s\": %s", name, lt_dlerror()); return NULL; } diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index cdf95adac..ea3d726ed 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -112,17 +112,17 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { m->argument = pa_xstrdup(argument); if (!(m->dl = lt_dlopenext(name))) { - pa_log(__FILE__": Failed to open module \"%s\": %s", name, lt_dlerror()); + pa_log("Failed to open module \"%s\": %s", name, lt_dlerror()); goto fail; } if (!(m->init = (int (*)(pa_core *_c, pa_module*_m)) load_sym(m->dl, name, PA_SYMBOL_INIT))) { - pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name); + pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name); goto fail; } if (!(m->done = (void (*)(pa_core *_c, pa_module*_m)) load_sym(m->dl, name, PA_SYMBOL_DONE))) { - pa_log(__FILE__": Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.", name); + pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.", name); goto fail; } @@ -134,7 +134,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { assert(m->init); if (m->init(c, m) < 0) { - pa_log_error(__FILE__": Failed to load module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : ""); + pa_log_error("Failed to load module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : ""); goto fail; } @@ -153,7 +153,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { r = pa_idxset_put(c->modules, m, &m->index); assert(r >= 0 && m->index != PA_IDXSET_INVALID); - pa_log_info(__FILE__": Loaded \"%s\" (index: #%u; argument: \"%s\").", m->name, m->index, m->argument ? m->argument : ""); + pa_log_info("Loaded \"%s\" (index: #%u; argument: \"%s\").", m->name, m->index, m->argument ? m->argument : ""); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_NEW, m->index); @@ -180,13 +180,13 @@ static void pa_module_free(pa_module *m) { if (m->core->disallow_module_loading) return; - pa_log_info(__FILE__": Unloading \"%s\" (index: #%u).", m->name, m->index); + pa_log_info("Unloading \"%s\" (index: #%u).", m->name, m->index); m->done(m->core, m); lt_dlclose(m->dl); - pa_log_info(__FILE__": Unloaded \"%s\" (index: #%u).", m->name, m->index); + pa_log_info("Unloaded \"%s\" (index: #%u).", m->name, m->index); pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE, m->index); diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index e1653d64b..6ecf710a7 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -205,7 +205,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, if (!(p = command_names[command])) snprintf((char*) (p = t), sizeof(t), "%u", command); - pa_log(__FILE__": Recieved opcode <%s>", p); + pa_log("Recieved opcode <%s>", p); } #endif @@ -226,7 +226,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, (*c)(pd, command, tag, ts, userdata); } else { - pa_log(__FILE__": Recieved unsupported command %u", command); + pa_log("Recieved unsupported command %u", command); goto finish; } diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index 044d223d2..6e0c085ee 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -57,7 +57,7 @@ static pid_t read_pid(const char *fn, int fd) { assert(fn && fd >= 0); if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) { - pa_log_warn(__FILE__": WARNING: failed to read PID file '%s': %s", + pa_log_warn("WARNING: failed to read PID file '%s': %s", fn, pa_cstrerror(errno)); return (pid_t) -1; } @@ -70,7 +70,7 @@ static pid_t read_pid(const char *fn, int fd) { *e = 0; if (pa_atou(t, &pid) < 0) { - pa_log(__FILE__": WARNING: failed to parse PID file '%s'", fn); + pa_log("WARNING: failed to parse PID file '%s'", fn); return (pid_t) -1; } @@ -85,7 +85,7 @@ static int open_pid_file(const char *fn, int mode) { if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) { if (mode != O_RDONLY || errno != ENOENT) - pa_log_warn(__FILE__": WARNING: failed to open PID file '%s': %s", + pa_log_warn("WARNING: failed to open PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -95,7 +95,7 @@ static int open_pid_file(const char *fn, int mode) { goto fail; if (fstat(fd, &st) < 0) { - pa_log_warn(__FILE__": WARNING: failed to fstat() PID file '%s': %s", + pa_log_warn("WARNING: failed to fstat() PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -108,7 +108,7 @@ static int open_pid_file(const char *fn, int mode) { goto fail; if (close(fd) < 0) { - pa_log_warn(__FILE__": WARNING: failed to close file '%s': %s", + pa_log_warn("WARNING: failed to close file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -147,7 +147,7 @@ int pa_pid_file_create(void) { goto fail; if ((pid = read_pid(fn, fd)) == (pid_t) -1) - pa_log(__FILE__": corrupt PID file, overwriting."); + pa_log("corrupt PID file, overwriting."); else if (pid > 0) { #ifdef OS_IS_WIN32 if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) { @@ -155,16 +155,16 @@ int pa_pid_file_create(void) { #else if (kill(pid, 0) >= 0 || errno != ESRCH) { #endif - pa_log(__FILE__": daemon already running."); + pa_log("daemon already running."); goto fail; } - pa_log(__FILE__": stale PID file, overwriting."); + pa_log("stale PID file, overwriting."); } /* Overwrite the current PID file */ if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) { - pa_log(__FILE__": failed to truncate PID file '%s': %s", + pa_log("failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -173,7 +173,7 @@ int pa_pid_file_create(void) { l = strlen(t); if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) { - pa_log(__FILE__": failed to write PID file."); + pa_log("failed to write PID file."); goto fail; } @@ -198,7 +198,7 @@ int pa_pid_file_remove(void) { pa_runtime_path("pid", fn, sizeof(fn)); if ((fd = open_pid_file(fn, O_RDWR)) < 0) { - pa_log_warn(__FILE__": WARNING: failed to open PID file '%s': %s", + pa_log_warn("WARNING: failed to open PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -207,12 +207,12 @@ int pa_pid_file_remove(void) { goto fail; if (pid != getpid()) { - pa_log(__FILE__": WARNING: PID file '%s' not mine!", fn); + pa_log("WARNING: PID file '%s' not mine!", fn); goto fail; } if (ftruncate(fd, 0) < 0) { - pa_log_warn(__FILE__": WARNING: failed to truncate PID file '%s': %s", + pa_log_warn("WARNING: failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -224,7 +224,7 @@ int pa_pid_file_remove(void) { #endif if (unlink(fn) < 0) { - pa_log_warn(__FILE__": WARNING: failed to remove PID file '%s': %s", + pa_log_warn("WARNING: failed to remove PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } diff --git a/src/pulsecore/protocol-cli.c b/src/pulsecore/protocol-cli.c index c5854f1e0..81ce5e8fb 100644 --- a/src/pulsecore/protocol-cli.c +++ b/src/pulsecore/protocol-cli.c @@ -56,7 +56,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) assert(s && io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { - pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); + pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); pa_iochannel_free(io); return; } diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 2fadeca30..c96a98b9a 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -294,7 +294,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req if (!c->authorized) { if (memcmp(data, c->protocol->esd_key, ESD_KEY_LEN) != 0) { - pa_log(__FILE__": kicked client with invalid authorization key."); + pa_log("kicked client with invalid authorization key."); return -1; } @@ -313,7 +313,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req else if (ekey == ESD_SWAP_ENDIAN_KEY) c->swap_byte_order = 1; else { - pa_log(__FILE__": client sent invalid endian key"); + pa_log("client sent invalid endian key"); return -1; } @@ -421,19 +421,19 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co pa_sink* sink; if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log(__FILE__": no such sink."); + pa_log("no such sink."); return -1; } if (!(source = sink->monitor_source)) { - pa_log(__FILE__": no such monitor source."); + pa_log("no such monitor source."); return -1; } } else { assert(request == ESD_PROTO_STREAM_REC); if (!(source = pa_namereg_get(c->protocol->core, c->protocol->source_name, PA_NAMEREG_SOURCE, 1))) { - pa_log(__FILE__": no such source."); + pa_log("no such source."); return -1; } } @@ -822,7 +822,7 @@ static int do_read(struct connection *c) { assert(c->read_data_length < sizeof(c->request)); if ((r = pa_iochannel_read(c->io, ((uint8_t*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { - pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); + pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } @@ -832,16 +832,16 @@ static int do_read(struct connection *c) { c->request = MAYBE_INT32_SWAP(c->swap_byte_order, c->request); if (c->request < ESD_PROTO_CONNECT || c->request > ESD_PROTO_MAX) { - pa_log(__FILE__": recieved invalid request."); + pa_log("recieved invalid request."); return -1; } handler = proto_map+c->request; -/* pa_log(__FILE__": executing request #%u", c->request); */ +/* pa_log("executing request #%u", c->request); */ if (!handler->proc) { - pa_log(__FILE__": recieved unimplemented request #%u.", c->request); + pa_log("recieved unimplemented request #%u.", c->request); return -1; } @@ -870,7 +870,7 @@ static int do_read(struct connection *c) { assert(c->read_data && c->read_data_length < handler->data_length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { - pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); + pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } @@ -890,7 +890,7 @@ static int do_read(struct connection *c) { assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { - pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); + pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } @@ -945,7 +945,7 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); + pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } @@ -975,7 +975,7 @@ static int do_write(struct connection *c) { assert(c->write_data_index < c->write_data_length); if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { - pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); + pa_log("write(): %s", pa_cstrerror(errno)); return -1; } @@ -994,7 +994,7 @@ static int do_write(struct connection *c) { if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); - pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); + pa_log("write(): %s", pa_cstrerror(errno)); return -1; } @@ -1154,7 +1154,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) assert(s && io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { - pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); + pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); pa_iochannel_free(io); return; } @@ -1203,7 +1203,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->original_name = NULL; if (!c->authorized && p->auth_ip_acl && pa_ip_acl_check(p->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) { - pa_log_info(__FILE__": Client authenticated by IP ACL."); + pa_log_info("Client authenticated by IP ACL."); c->authorized = 1; } @@ -1237,7 +1237,7 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve p = pa_xnew(pa_protocol_esound, 1); if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) { - pa_log(__FILE__": auth-anonymous= expects a boolean argument."); + pa_log("auth-anonymous= expects a boolean argument."); goto fail; } @@ -1247,7 +1247,7 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) { if (!(p->auth_ip_acl = pa_ip_acl_new(acl))) { - pa_log(__FILE__": Failed to parse IP ACL '%s'", acl); + pa_log("Failed to parse IP ACL '%s'", acl); goto fail; } } else diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c index d0d92629c..3b1207f62 100644 --- a/src/pulsecore/protocol-http.c +++ b/src/pulsecore/protocol-http.c @@ -145,7 +145,7 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { /* We're done */ c->state = DATA; - pa_log_info(__FILE__": request for %s", c->url); + pa_log_info("request for %s", c->url); if (!strcmp(c->url, URL_ROOT)) { char txt[256]; @@ -224,7 +224,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) assert(s && io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { - pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); + pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); pa_iochannel_free(io); return; } diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 2c9b3566c..506442f50 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -542,7 +542,7 @@ static void request_bytes(struct playback_stream *s) { pa_tagstruct_putu32(t, l); pa_pstream_send_tagstruct(s->connection->pstream, t); -/* pa_log(__FILE__": Requesting %u bytes", l); */ +/* pa_log("Requesting %u bytes", l); */ } static void send_memblock(struct connection *c) { @@ -620,11 +620,11 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { } if (pa_memblockq_peek(s->memblockq, chunk) < 0) { -/* pa_log(__FILE__": peek: failure"); */ +/* pa_log("peek: failure"); */ return -1; } -/* pa_log(__FILE__": peek: %u", chunk->length); */ +/* pa_log("peek: %u", chunk->length); */ return 0; } @@ -643,7 +643,7 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_ s->drain_request = 0; } -/* pa_log(__FILE__": after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */ +/* pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */ } static void sink_input_kill_cb(pa_sink_input *i) { @@ -657,7 +657,7 @@ static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { assert(i && i->userdata); s = i->userdata; - /*pa_log(__FILE__": get_latency: %u", pa_memblockq_get_length(s->memblockq));*/ + /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/ return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); } @@ -670,7 +670,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) s = o->userdata; if (pa_memblockq_push_align(s->memblockq, chunk) < 0) { - pa_log_warn(__FILE__": Failed to push data into output queue."); + pa_log_warn("Failed to push data into output queue."); return; } @@ -689,7 +689,7 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { assert(o && o->userdata); s = o->userdata; - /*pa_log(__FILE__": get_latency: %u", pa_memblockq_get_length(s->memblockq));*/ + /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/ return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec); } @@ -697,7 +697,7 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { /*** pdispatch callbacks ***/ static void protocol_error(struct connection *c) { - pa_log(__FILE__": protocol error, kicking client"); + pa_log("protocol error, kicking client"); connection_free(c); } @@ -945,19 +945,19 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t gid_t gid; if ((gid = pa_get_gid_of_group(c->protocol->auth_group)) == (gid_t) -1) - pa_log_warn(__FILE__": failed to get GID of group '%s'", c->protocol->auth_group); + pa_log_warn("failed to get GID of group '%s'", c->protocol->auth_group); else if (gid == creds->gid) success = 1; if (!success) { if ((r = pa_uid_in_group(creds->uid, c->protocol->auth_group)) < 0) - pa_log_warn(__FILE__": failed to check group membership."); + pa_log_warn("failed to check group membership."); else if (r > 0) success = 1; } } - pa_log_info(__FILE__": Got credentials: uid=%lu gid=%lu success=%i", + pa_log_info("Got credentials: uid=%lu gid=%lu success=%i", (unsigned long) creds->uid, (unsigned long) creds->gid, success); @@ -968,7 +968,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t success = 1; if (!success) { - pa_log_warn(__FILE__": Denied access to client with invalid authorization data."); + pa_log_warn("Denied access to client with invalid authorization data."); pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } @@ -2199,7 +2199,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_c assert(p && packet && packet->data && c); if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) { - pa_log(__FILE__": invalid packet."); + pa_log("invalid packet."); connection_free(c); } } @@ -2210,7 +2210,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o assert(p && chunk && userdata); if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) { - pa_log(__FILE__": client sent block for invalid stream."); + pa_log("client sent block for invalid stream."); /* Ignoring */ return; } @@ -2227,7 +2227,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o if (pa_memblockq_push_align(ps->memblockq, chunk) < 0) { pa_tagstruct *t; - pa_log_warn(__FILE__": failed to push data into queue"); + pa_log_warn("failed to push data into queue"); /* Pushing this block into the queue failed, so we simulate * it by skipping ahead */ @@ -2282,7 +2282,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { assert(p && c); connection_free(c); -/* pa_log(__FILE__": connection died.");*/ +/* pa_log("connection died.");*/ } @@ -2317,7 +2317,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo assert(io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { - pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); + pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); pa_iochannel_free(io); return; } @@ -2327,7 +2327,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo c->authorized = !!p->public; if (!c->authorized && p->auth_ip_acl && pa_ip_acl_check(p->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) { - pa_log_info(__FILE__": Client authenticated by IP ACL."); + pa_log_info("Client authenticated by IP ACL."); c->authorized = 1; } @@ -2388,7 +2388,7 @@ static int load_key(pa_protocol_native*p, const char*fn) { p->auth_cookie_in_property = 0; if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) { - pa_log_info(__FILE__": using already loaded auth cookie."); + pa_log_info("using already loaded auth cookie."); pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); p->auth_cookie_in_property = 1; return 0; @@ -2400,7 +2400,7 @@ static int load_key(pa_protocol_native*p, const char*fn) { if (pa_authkey_load_auto(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0) return -1; - pa_log_info(__FILE__": loading cookie from disk."); + pa_log_info("loading cookie from disk."); if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) p->auth_cookie_in_property = 1; @@ -2417,7 +2417,7 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo assert(ma); if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) { - pa_log(__FILE__": auth-anonymous= expects a boolean argument."); + pa_log("auth-anonymous= expects a boolean argument."); return NULL; } @@ -2432,13 +2432,13 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo { int a = 1; if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &a) < 0) { - pa_log(__FILE__": auth-group-enabled= expects a boolean argument."); + pa_log("auth-group-enabled= expects a boolean argument."); return NULL; } p->auth_group = a ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", c->is_system_instance ? PA_ACCESS_GROUP : NULL)) : NULL; if (p->auth_group) - pa_log_info(__FILE__": Allowing access to group '%s'.", p->auth_group); + pa_log_info("Allowing access to group '%s'.", p->auth_group); } #endif @@ -2446,7 +2446,7 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) { if (!(p->auth_ip_acl = pa_ip_acl_new(acl))) { - pa_log(__FILE__": Failed to parse IP ACL '%s'", acl); + pa_log("Failed to parse IP ACL '%s'", acl); goto fail; } } diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 924ee29ec..6bfba875e 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -134,7 +134,7 @@ static int do_read(struct connection *c) { } if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { - pa_log_debug(__FILE__": read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno)); + pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno)); return -1; } @@ -168,7 +168,7 @@ static int do_write(struct connection *c) { if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); - pa_log(__FILE__": write(): %s", pa_cstrerror(errno)); + pa_log("write(): %s", pa_cstrerror(errno)); return -1; } @@ -315,7 +315,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) assert(s && io && p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { - pa_log(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); + pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); pa_iochannel_free(io); return; } @@ -351,7 +351,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) data.client = c->client; if (!(c->sink_input = pa_sink_input_new(p->core, &data, 0))) { - pa_log(__FILE__": Failed to create sink input."); + pa_log("Failed to create sink input."); goto fail; } @@ -389,7 +389,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) data.client = c->client; if (!(c->source_output = pa_source_output_new(p->core, &data, 0))) { - pa_log(__FILE__": Failed to create source output."); + pa_log("Failed to create source output."); goto fail; } c->source_output->push = source_output_push_cb; @@ -437,7 +437,7 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv p->sample_spec = core->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &p->sample_spec) < 0) { - pa_log(__FILE__": Failed to parse sample type specification."); + pa_log("Failed to parse sample type specification."); goto fail; } @@ -446,20 +446,20 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv enable = 0; if (pa_modargs_get_value_boolean(ma, "record", &enable) < 0) { - pa_log(__FILE__": record= expects a numeric argument."); + pa_log("record= expects a numeric argument."); goto fail; } p->mode = enable ? RECORD : 0; enable = 1; if (pa_modargs_get_value_boolean(ma, "playback", &enable) < 0) { - pa_log(__FILE__": playback= expects a numeric argument."); + pa_log("playback= expects a numeric argument."); goto fail; } p->mode |= enable ? PLAYBACK : 0; if ((p->mode & (RECORD|PLAYBACK)) == 0) { - pa_log(__FILE__": neither playback nor recording enabled for protocol."); + pa_log("neither playback nor recording enabled for protocol."); goto fail; } diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 421f5de9c..ca8137a4a 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -357,7 +357,7 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd if (p->dead) return; -/* pa_log(__FILE__": Releasing block %u", block_id); */ +/* pa_log("Releasing block %u", block_id); */ item = pa_xnew(struct item_info, 1); item->type = PA_PSTREAM_ITEM_SHMRELEASE; @@ -380,7 +380,7 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda if (p->dead) return; -/* pa_log(__FILE__": Revoking block %u", block_id); */ +/* pa_log("Revoking block %u", block_id); */ item = pa_xnew(struct item_info, 1); item->type = PA_PSTREAM_ITEM_SHMREVOKE; @@ -462,7 +462,7 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.data = p->write.shm_info; } /* else */ -/* pa_log_warn(__FILE__": Failed to export memory block."); */ +/* pa_log_warn("Failed to export memory block."); */ } if (send_payload) { @@ -569,7 +569,7 @@ static int do_read(pa_pstream *p) { flags = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]); if (!p->use_shm && (flags & PA_FLAG_SHMMASK) != 0) { - pa_log_warn(__FILE__": Recieved SHM frame on a socket where SHM is disabled."); + pa_log_warn("Recieved SHM frame on a socket where SHM is disabled."); return -1; } @@ -577,7 +577,7 @@ static int do_read(pa_pstream *p) { /* This is a SHM memblock release frame with no payload */ -/* pa_log(__FILE__": Got release frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */ +/* pa_log("Got release frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */ assert(p->export); pa_memexport_process_release(p->export, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); @@ -588,7 +588,7 @@ static int do_read(pa_pstream *p) { /* This is a SHM memblock revoke frame with no payload */ -/* pa_log(__FILE__": Got revoke frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */ +/* pa_log("Got revoke frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */ assert(p->import); pa_memimport_process_revoke(p->import, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); @@ -599,7 +599,7 @@ static int do_read(pa_pstream *p) { length = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]); if (length > FRAME_SIZE_MAX) { - pa_log_warn(__FILE__": Recieved invalid frame size : %lu", (unsigned long) length); + pa_log_warn("Recieved invalid frame size : %lu", (unsigned long) length); return -1; } @@ -610,7 +610,7 @@ static int do_read(pa_pstream *p) { if (channel == (uint32_t) -1) { if (flags != 0) { - pa_log_warn(__FILE__": Received packet frame with invalid flags value."); + pa_log_warn("Received packet frame with invalid flags value."); return -1; } @@ -621,14 +621,14 @@ static int do_read(pa_pstream *p) { } else { if ((flags & PA_FLAG_SEEKMASK) > PA_SEEK_RELATIVE_END) { - pa_log_warn(__FILE__": Received memblock frame with invalid seek mode."); + pa_log_warn("Received memblock frame with invalid seek mode."); return -1; } if ((flags & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA) { if (length != sizeof(p->read.shm_info)) { - pa_log_warn(__FILE__": Recieved SHM memblock frame with Invalid frame length."); + pa_log_warn("Recieved SHM memblock frame with Invalid frame length."); return -1; } @@ -643,7 +643,7 @@ static int do_read(pa_pstream *p) { p->read.data = p->read.memblock->data; } else { - pa_log_warn(__FILE__": Recieved memblock frame with invalid flags value."); + pa_log_warn("Recieved memblock frame with invalid flags value."); return -1; } } @@ -717,7 +717,7 @@ static int do_read(pa_pstream *p) { ntohl(p->read.shm_info[PA_PSTREAM_SHM_INDEX]), ntohl(p->read.shm_info[PA_PSTREAM_SHM_LENGTH])))) { - pa_log_warn(__FILE__": Failed to import memory block."); + pa_log_warn("Failed to import memory block."); return -1; } diff --git a/src/pulsecore/random.c b/src/pulsecore/random.c index 684ead715..7908e87d8 100644 --- a/src/pulsecore/random.c +++ b/src/pulsecore/random.c @@ -81,7 +81,7 @@ void pa_random_seed(void) { if (random_proper(&seed, sizeof(unsigned int)) < 0) { if (!has_whined) - pa_log_warn(__FILE__": failed to get proper entropy. Falling back to seeding with current time."); + pa_log_warn("failed to get proper entropy. Falling back to seeding with current time."); has_whined = 1; seed = (unsigned int) time(NULL); @@ -100,7 +100,7 @@ void pa_random(void *ret_data, size_t length) { return; if (!has_whined) - pa_log_warn(__FILE__": failed to get proper entropy. Falling back to unsecure pseudo RNG."); + pa_log_warn("failed to get proper entropy. Falling back to unsecure pseudo RNG."); has_whined = 1; for (p = ret_data, l = length; l > 0; p++, l--) diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index 7f5d8a020..d902b4b55 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -282,7 +282,7 @@ size_t pa_mix( } default: - pa_log_error(__FILE__": ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); + pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); abort(); } } @@ -398,7 +398,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol } default: - pa_log_error(__FILE__": ERROR: Unable to change volume of format %s.", + pa_log_error("ERROR: Unable to change volume of format %s.", pa_sample_format_to_string(spec->format)); abort(); } diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index ad9dc46a4..bf0071d6b 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -61,7 +61,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { #ifdef MAP_ANONYMOUS if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS, fd, 0)) == MAP_FAILED) { - pa_log(__FILE__": mmap() failed: %s", pa_cstrerror(errno)); + pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } #else @@ -75,17 +75,17 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { segment_name(fn, sizeof(fn), m->id); if ((fd = shm_open(fn, O_RDWR|O_CREAT|O_EXCL, mode & 0444)) < 0) { - pa_log(__FILE__": shm_open() failed: %s", pa_cstrerror(errno)); + pa_log("shm_open() failed: %s", pa_cstrerror(errno)); goto fail; } if (ftruncate(fd, m->size = size) < 0) { - pa_log(__FILE__": ftruncate() failed: %s", pa_cstrerror(errno)); + pa_log("ftruncate() failed: %s", pa_cstrerror(errno)); goto fail; } if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { - pa_log(__FILE__": mmap() failed: %s", pa_cstrerror(errno)); + pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } @@ -121,7 +121,7 @@ void pa_shm_free(pa_shm *m) { #endif if (munmap(m->ptr, m->size) < 0) - pa_log(__FILE__": munmap() failed: %s", pa_cstrerror(errno)); + pa_log("munmap() failed: %s", pa_cstrerror(errno)); if (m->do_unlink) { segment_name(fn, sizeof(fn), m->id); @@ -188,24 +188,24 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) { segment_name(fn, sizeof(fn), m->id = id); if ((fd = shm_open(fn, O_RDONLY, 0)) < 0) { - pa_log(__FILE__": shm_open() failed: %s", pa_cstrerror(errno)); + pa_log("shm_open() failed: %s", pa_cstrerror(errno)); goto fail; } if (fstat(fd, &st) < 0) { - pa_log(__FILE__": fstat() failed: %s", pa_cstrerror(errno)); + pa_log("fstat() failed: %s", pa_cstrerror(errno)); goto fail; } if (st.st_size <= 0 || st.st_size > MAX_SHM_SIZE) { - pa_log(__FILE__": Invalid shared memory segment size"); + pa_log("Invalid shared memory segment size"); goto fail; } m->size = st.st_size; if ((m->ptr = mmap(NULL, m->size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { - pa_log(__FILE__": mmap() failed: %s", pa_cstrerror(errno)); + pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index b5ba9df19..d948f0a4c 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -127,7 +127,7 @@ pa_sink_input* pa_sink_input_new( CHECK_VALIDITY_RETURN_NULL(data->resample_method < PA_RESAMPLER_MAX); if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) { - pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink."); + pa_log_warn("Failed to create sink input: too many inputs per sink."); return NULL; } @@ -140,7 +140,7 @@ pa_sink_input* pa_sink_input_new( &data->sample_spec, &data->channel_map, &data->sink->sample_spec, &data->sink->channel_map, data->resample_method))) { - pa_log_warn(__FILE__": Unsupported resampling operation."); + pa_log_warn("Unsupported resampling operation."); return NULL; } @@ -177,7 +177,7 @@ pa_sink_input* pa_sink_input_new( r = pa_idxset_put(i->sink->inputs, i, NULL); assert(r == 0); - pa_log_info(__FILE__": created %u \"%s\" on %s with sample spec %s", + pa_log_info("created %u \"%s\" on %s with sample spec %s", i->index, i->name, i->sink->name, @@ -218,7 +218,7 @@ static void sink_input_free(pa_sink_input* i) { if (i->state != PA_SINK_INPUT_DISCONNECTED) pa_sink_input_disconnect(i); - pa_log_info(__FILE__": freed %u \"%s\"", i->index, i->name); + pa_log_info("freed %u \"%s\"", i->index, i->name); if (i->resampled_chunk.memblock) pa_memblock_unref(i->resampled_chunk.memblock); @@ -522,7 +522,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { return 0; if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) { - pa_log_warn(__FILE__": Failed to move sink input: too many inputs per sink."); + pa_log_warn("Failed to move sink input: too many inputs per sink."); return -1; } @@ -544,7 +544,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { &i->sample_spec, &i->channel_map, &dest->sample_spec, &dest->channel_map, i->resample_method))) { - pa_log_warn(__FILE__": Unsupported resampling operation."); + pa_log_warn("Unsupported resampling operation."); return -1; } } diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index aacb89fd5..056952546 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -116,12 +116,12 @@ pa_sink* pa_sink_new( assert(s->index != PA_IDXSET_INVALID && r >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); + pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); n = pa_sprintf_malloc("%s.monitor", name); if (!(s->monitor_source = pa_source_new(core, driver, n, 0, spec, map))) - pa_log_warn(__FILE__": failed to create monitor source."); + pa_log_warn("failed to create monitor source."); else { char *d; s->monitor_source->monitor_of = s; @@ -176,7 +176,7 @@ static void sink_free(pa_sink *s) { if (s->state != PA_SINK_DISCONNECTED) pa_sink_disconnect(s); - pa_log_info(__FILE__": freed %u \"%s\"", s->index, s->name); + pa_log_info("freed %u \"%s\"", s->index, s->name); if (s->monitor_source) { pa_source_unref(s->monitor_source); diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c index 8e547614d..2ceaf5c3c 100644 --- a/src/pulsecore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -140,17 +140,17 @@ static void do_call(pa_socket_client *c) { lerror = sizeof(error); if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) { - pa_log(__FILE__": getsockopt(): %s", pa_cstrerror(errno)); + pa_log("getsockopt(): %s", pa_cstrerror(errno)); goto finish; } if (lerror != sizeof(error)) { - pa_log(__FILE__": getsockopt() returned invalid size."); + pa_log("getsockopt() returned invalid size."); goto finish; } if (error != 0) { - pa_log_debug(__FILE__": connect(): %s", pa_cstrerror(errno)); + pa_log_debug("connect(): %s", pa_cstrerror(errno)); errno = error; goto finish; } @@ -192,10 +192,10 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t if ((r = connect(c->fd, sa, len)) < 0) { #ifdef OS_IS_WIN32 if (WSAGetLastError() != EWOULDBLOCK) { - pa_log_debug(__FILE__": connect(): %d", WSAGetLastError()); + pa_log_debug("connect(): %d", WSAGetLastError()); #else if (errno != EINPROGRESS) { - pa_log_debug(__FILE__": connect(): %s (%d)", pa_cstrerror(errno), errno); + pa_log_debug("connect(): %s (%d)", pa_cstrerror(errno), errno); #endif return -1; } @@ -267,7 +267,7 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size } if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s", pa_cstrerror(errno)); + pa_log("socket(): %s", pa_cstrerror(errno)); return -1; } @@ -485,7 +485,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam /* FIXME: PF_INET6 support */ if (hints.ai_family == PF_INET6) { - pa_log_error(__FILE__": IPv6 is not supported on Windows"); + pa_log_error("IPv6 is not supported on Windows"); goto finish; } diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c index 254835922..4d69b8a47 100644 --- a/src/pulsecore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -96,7 +96,7 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U pa_socket_server_ref(s); if ((nfd = accept(fd, NULL, NULL)) < 0) { - pa_log(__FILE__": accept(): %s", pa_cstrerror(errno)); + pa_log("accept(): %s", pa_cstrerror(errno)); goto finish; } @@ -115,12 +115,12 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U request_init(&req, RQ_DAEMON, s->tcpwrap_service, RQ_FILE, nfd, NULL); fromhost(&req); if (!hosts_access(&req)) { - pa_log_warn(__FILE__": TCP connection refused by tcpwrap."); + pa_log_warn("TCP connection refused by tcpwrap."); close(nfd); goto finish; } - pa_log_info(__FILE__": TCP connection accepted by tcpwrap."); + pa_log_info("TCP connection accepted by tcpwrap."); } #endif @@ -175,7 +175,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file assert(m && filename); if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s", pa_cstrerror(errno)); + pa_log("socket(): %s", pa_cstrerror(errno)); goto fail; } @@ -188,7 +188,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file pa_socket_low_delay(fd); if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { - pa_log(__FILE__": bind(): %s", pa_cstrerror(errno)); + pa_log("bind(): %s", pa_cstrerror(errno)); goto fail; } @@ -199,7 +199,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file chmod(filename, 0777); if (listen(fd, 5) < 0) { - pa_log(__FILE__": listen(): %s", pa_cstrerror(errno)); + pa_log("listen(): %s", pa_cstrerror(errno)); goto fail; } @@ -235,7 +235,7 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address assert(m && port); if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_INET): %s", pa_cstrerror(errno)); + pa_log("socket(PF_INET): %s", pa_cstrerror(errno)); goto fail; } @@ -243,7 +243,7 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address #ifdef SO_REUSEADDR if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) - pa_log(__FILE__": setsockopt(): %s", pa_cstrerror(errno)); + pa_log("setsockopt(): %s", pa_cstrerror(errno)); #endif pa_socket_tcp_low_delay(fd); @@ -254,12 +254,12 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address sa.sin_addr.s_addr = htonl(address); if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { - pa_log(__FILE__": bind(): %s", pa_cstrerror(errno)); + pa_log("bind(): %s", pa_cstrerror(errno)); goto fail; } if (listen(fd, 5) < 0) { - pa_log(__FILE__": listen(): %s", pa_cstrerror(errno)); + pa_log("listen(): %s", pa_cstrerror(errno)); goto fail; } @@ -286,7 +286,7 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad assert(m && port); if ((fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_INET6): %s", pa_cstrerror(errno)); + pa_log("socket(PF_INET6): %s", pa_cstrerror(errno)); goto fail; } @@ -294,12 +294,12 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad #ifdef IPV6_V6ONLY if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) - pa_log(__FILE__": setsockopt(IPPROTO_IPV6, IPV6_V6ONLY): %s", pa_cstrerror(errno)); + pa_log("setsockopt(IPPROTO_IPV6, IPV6_V6ONLY): %s", pa_cstrerror(errno)); #endif #ifdef SO_REUSEADDR if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) - pa_log(__FILE__": setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", pa_cstrerror(errno)); + pa_log("setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", pa_cstrerror(errno)); #endif pa_socket_tcp_low_delay(fd); @@ -310,12 +310,12 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad memcpy(sa.sin6_addr.s6_addr, address, 16); if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { - pa_log(__FILE__": bind(): %s", pa_cstrerror(errno)); + pa_log("bind(): %s", pa_cstrerror(errno)); goto fail; } if (listen(fd, 5) < 0) { - pa_log(__FILE__": listen(): %s", pa_cstrerror(errno)); + pa_log("listen(): %s", pa_cstrerror(errno)); goto fail; } @@ -426,7 +426,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { socklen_t sa_len = sizeof(sa); if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) { - pa_log(__FILE__": getsockname(): %s", pa_cstrerror(errno)); + pa_log("getsockname(): %s", pa_cstrerror(errno)); return NULL; } @@ -447,7 +447,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { char ip[INET6_ADDRSTRLEN]; if (!inet_ntop(AF_INET6, &sa.sin6_addr, ip, sizeof(ip))) { - pa_log(__FILE__": inet_ntop(): %s", pa_cstrerror(errno)); + pa_log("inet_ntop(): %s", pa_cstrerror(errno)); return NULL; } @@ -462,7 +462,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { socklen_t sa_len = sizeof(sa); if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) { - pa_log(__FILE__": getsockname(): %s", pa_cstrerror(errno)); + pa_log("getsockname(): %s", pa_cstrerror(errno)); return NULL; } @@ -482,7 +482,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { char ip[INET_ADDRSTRLEN]; if (!inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip))) { - pa_log(__FILE__": inet_ntop(): %s", pa_cstrerror(errno)); + pa_log("inet_ntop(): %s", pa_cstrerror(errno)); return NULL; } diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c index 8705560d9..856c28e8a 100644 --- a/src/pulsecore/socket-util.c +++ b/src/pulsecore/socket-util.c @@ -191,7 +191,7 @@ int pa_socket_set_rcvbuf(int fd, size_t l) { assert(fd >= 0); /* if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&l, sizeof(l)) < 0) { */ -/* pa_log(__FILE__": SO_RCVBUF: %s", strerror(errno)); */ +/* pa_log("SO_RCVBUF: %s", strerror(errno)); */ /* return -1; */ /* } */ @@ -202,7 +202,7 @@ int pa_socket_set_sndbuf(int fd, size_t l) { assert(fd >= 0); /* if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&l, sizeof(l)) < 0) { */ -/* pa_log(__FILE__": SO_SNDBUF: %s", strerror(errno)); */ +/* pa_log("SO_SNDBUF: %s", strerror(errno)); */ /* return -1; */ /* } */ @@ -216,7 +216,7 @@ int pa_unix_socket_is_stale(const char *fn) { int fd = -1, ret = -1; if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(): %s", pa_cstrerror(errno)); + pa_log("socket(): %s", pa_cstrerror(errno)); goto finish; } diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index 6782f50eb..e6f24a795 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -142,7 +142,7 @@ int pa_play_file( memset(&sfinfo, 0, sizeof(sfinfo)); if (!(u->sndfile = sf_open(fname, SFM_READ, &sfinfo))) { - pa_log(__FILE__": Failed to open file %s", fname); + pa_log("Failed to open file %s", fname); goto fail; } @@ -175,7 +175,7 @@ int pa_play_file( ss.channels = sfinfo.channels; if (!pa_sample_spec_valid(&ss)) { - pa_log(__FILE__": Unsupported sample format in file %s", fname); + pa_log("Unsupported sample format in file %s", fname); goto fail; } diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c index 256cce434..1bf650e22 100644 --- a/src/pulsecore/sound-file.c +++ b/src/pulsecore/sound-file.c @@ -48,7 +48,7 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, memset(&sfinfo, 0, sizeof(sfinfo)); if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { - pa_log(__FILE__": Failed to open file %s", fname); + pa_log("Failed to open file %s", fname); goto finish; } @@ -80,7 +80,7 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, ss->channels = sfinfo.channels; if (!pa_sample_spec_valid(ss)) { - pa_log(__FILE__": Unsupported sample format in file %s", fname); + pa_log("Unsupported sample format in file %s", fname); goto finish; } @@ -88,7 +88,7 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT); if ((l = pa_frame_size(ss)*sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { - pa_log(__FILE__": File too large"); + pa_log("File too large"); goto finish; } @@ -99,7 +99,7 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, if ((readf_function && readf_function(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) || (!readf_function && sf_read_raw(sf, chunk->memblock->data, l) != l)) { - pa_log(__FILE__": Premature file end"); + pa_log("Premature file end"); goto finish; } @@ -123,7 +123,7 @@ int pa_sound_file_too_big_to_cache(const char *fname) { pa_sample_spec ss; if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { - pa_log(__FILE__": Failed to open file %s", fname); + pa_log("Failed to open file %s", fname); return 0; } @@ -155,7 +155,7 @@ int pa_sound_file_too_big_to_cache(const char *fname) { ss.channels = sfinfo.channels; if ((pa_frame_size(&ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { - pa_log(__FILE__": File too large %s", fname); + pa_log("File too large %s", fname); return 1; } diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index f9d66f6d1..a2fc8519b 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -108,7 +108,7 @@ pa_source_output* pa_source_output_new( CHECK_VALIDITY_RETURN_NULL(data->resample_method < PA_RESAMPLER_MAX); if (pa_idxset_size(data->source->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { - pa_log(__FILE__": Failed to create source output: too many outputs per source."); + pa_log("Failed to create source output: too many outputs per source."); return NULL; } @@ -119,7 +119,7 @@ pa_source_output* pa_source_output_new( &data->source->sample_spec, &data->source->channel_map, &data->sample_spec, &data->channel_map, data->resample_method))) { - pa_log_warn(__FILE__": Unsupported resampling operation."); + pa_log_warn("Unsupported resampling operation."); return NULL; } @@ -148,7 +148,7 @@ pa_source_output* pa_source_output_new( r = pa_idxset_put(o->source->outputs, o, NULL); assert(r == 0); - pa_log_info(__FILE__": created %u \"%s\" on %s with sample spec %s", + pa_log_info("created %u \"%s\" on %s with sample spec %s", o->index, o->name, o->source->name, @@ -187,7 +187,7 @@ static void source_output_free(pa_source_output* o) { if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED) pa_source_output_disconnect(o); - pa_log_info(__FILE__": freed %u \"%s\"", o->index, o->name); + pa_log_info("freed %u \"%s\"", o->index, o->name); if (o->resampler) pa_resampler_free(o->resampler); @@ -313,7 +313,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { return 0; if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { - pa_log_warn(__FILE__": Failed to move source output: too many outputs per source."); + pa_log_warn("Failed to move source output: too many outputs per source."); return -1; } @@ -334,7 +334,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { &dest->sample_spec, &dest->channel_map, &o->sample_spec, &o->channel_map, o->resample_method))) { - pa_log_warn(__FILE__": Unsupported resampling operation."); + pa_log_warn("Unsupported resampling operation."); return -1; } } diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index cb5b10302..c48d6aaae 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -112,7 +112,7 @@ pa_source* pa_source_new( assert(s->index != PA_IDXSET_INVALID && r >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); + pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); @@ -155,7 +155,7 @@ static void source_free(pa_source *s) { if (s->state != PA_SOURCE_DISCONNECTED) pa_source_disconnect(s); - pa_log_info(__FILE__": freed %u \"%s\"", s->index, s->name); + pa_log_info("freed %u \"%s\"", s->index, s->name); pa_idxset_free(s->outputs, NULL, NULL); diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c index 2ba0a87fb..cc993e78d 100644 --- a/src/pulsecore/x11wrap.c +++ b/src/pulsecore/x11wrap.c @@ -145,7 +145,7 @@ static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char int r; if (!(d = XOpenDisplay(name))) { - pa_log(__FILE__": XOpenDisplay() failed"); + pa_log("XOpenDisplay() failed"); return NULL; } diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index fe8038e00..b99127016 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -49,12 +49,12 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { fd_set ifds, ofds; if (pa_pid_file_check_running(&pid) < 0) { - pa_log(__FILE__": no PulseAudio daemon running"); + pa_log("no PulseAudio daemon running"); goto fail; } if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - pa_log(__FILE__": socket(PF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); + pa_log("socket(PF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); goto fail; } @@ -66,7 +66,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { int r; if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { - pa_log(__FILE__": connect(): %s", strerror(errno)); + pa_log("connect(): %s", strerror(errno)); goto fail; } @@ -74,7 +74,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { break; if (pa_pid_file_kill(SIGUSR2, NULL) < 0) { - pa_log(__FILE__": failed to kill PulseAudio daemon."); + pa_log("failed to kill PulseAudio daemon."); goto fail; } @@ -82,7 +82,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { } if (i >= 5) { - pa_log(__FILE__": daemon not responding."); + pa_log("daemon not responding."); goto fail; } @@ -97,7 +97,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { for (;;) { if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { - pa_log(__FILE__": select(): %s", strerror(errno)); + pa_log("select(): %s", strerror(errno)); goto fail; } @@ -109,7 +109,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read(): %s", strerror(errno)); + pa_log("read(): %s", strerror(errno)); goto fail; } @@ -125,7 +125,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r == 0) break; - pa_log(__FILE__": read(): %s", strerror(errno)); + pa_log("read(): %s", strerror(errno)); goto fail; } @@ -138,7 +138,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(obuf_length); if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { - pa_log(__FILE__": write(): %s", strerror(errno)); + pa_log("write(): %s", strerror(errno)); goto fail; } @@ -152,7 +152,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { assert(ibuf_length); if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { - pa_log(__FILE__": write(): %s", strerror(errno)); + pa_log("write(): %s", strerror(errno)); goto fail; } diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 2a0d21d68..6a3c6dbce 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) { } if (!(d = XOpenDisplay(dname))) { - pa_log(__FILE__": XOpenDisplay() failed"); + pa_log("XOpenDisplay() failed"); goto finish; } From 7e01b1c5bd74b305c9f14f0711642ab88e3592ac Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 21:39:32 +0000 Subject: [PATCH 1173/1514] hide memblock-test git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1273 fefdeb5f-60dc-0310-8127-8f9354f1896f From fd3fe96ce52a1737bb253939f36264908b353b26 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 23:40:48 +0000 Subject: [PATCH 1174/1514] add new function pa_mempool_is_shared() to test whether a memory pool is suitable for SHM data transfers git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1274 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/memblock.c | 6 ++++++ src/pulsecore/memblock.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 2109d83ce..90494fb6f 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -497,6 +497,12 @@ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) { return 0; } +int pa_mempool_is_shared(pa_mempool *p) { + assert(p); + + return !!p->memory.shared; +} + /* For recieving blocks from other nodes */ pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void *userdata) { pa_memimport *i; diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index e63e1e0fe..70cd1b9e8 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -116,6 +116,7 @@ void pa_mempool_free(pa_mempool *p); const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p); void pa_mempool_vacuum(pa_mempool *p); int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id); +int pa_mempool_is_shared(pa_mempool *p); /* For recieving blocks from other nodes */ pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void *userdata); From 7ac79098a623e33ffc9d7ca4bbce215ba5f10700 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 23:42:14 +0000 Subject: [PATCH 1175/1514] remove export/import objects when SHM is disable for a pa_pstream object git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1275 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pstream.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index ca8137a4a..e2cfcb633 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -476,7 +476,6 @@ static void prepare_next_write_item(pa_pstream *p) { #ifdef HAVE_CREDS if ((p->send_creds_now = p->write.current->with_creds)) p->write_creds = p->write.current->creds; - #endif } @@ -860,9 +859,25 @@ void pa_pstream_use_shm(pa_pstream *p, int enable) { p->use_shm = enable; - if (!p->import) - p->import = pa_memimport_new(p->mempool, memimport_release_cb, p); + if (enable) { + + if (!p->import) + p->import = pa_memimport_new(p->mempool, memimport_release_cb, p); + + if (!p->export) + p->export = pa_memexport_new(p->mempool, memexport_revoke_cb, p); - if (!p->export) - p->export = pa_memexport_new(p->mempool, memexport_revoke_cb, p); + } else { + + if (p->import) { + pa_memimport_free(p->import); + p->import = NULL; + } + + if (p->export) { + pa_memexport_free(p->export); + p->export = NULL; + } + + } } From c313b23d5f5a8ee1a5510d1cc79b8ba54c217df6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 23:43:27 +0000 Subject: [PATCH 1176/1514] one s/0/NULL/ git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1276 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pstream-util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/pstream-util.h b/src/pulsecore/pstream-util.h index f384d8895..c6d76a7c2 100644 --- a/src/pulsecore/pstream-util.h +++ b/src/pulsecore/pstream-util.h @@ -30,7 +30,7 @@ /* The tagstruct is freed!*/ void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const pa_creds *creds); -#define pa_pstream_send_tagstruct(p, t) pa_pstream_send_tagstruct_with_creds((p), (t), 0) +#define pa_pstream_send_tagstruct(p, t) pa_pstream_send_tagstruct_with_creds((p), (t), NULL) void pa_pstream_send_error(pa_pstream *p, uint32_t tag, uint32_t error); void pa_pstream_send_simple_ack(pa_pstream *p, uint32_t tag); From e33abc30894dab740ca2fb2f864161266792ea08 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 23:44:35 +0000 Subject: [PATCH 1177/1514] activate SHM support on the server side only when new client supports it and when client and server have the same UID. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1277 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-native.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 506442f50..40a839739 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -961,6 +961,15 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t (unsigned long) creds->uid, (unsigned long) creds->gid, success); + + if (c->version >= 10 && + pa_mempool_is_shared(c->protocol->core->mempool) && + creds->uid == getuid()) { + + pa_pstream_use_shm(c->pstream, 1); + pa_log_info("Enabled SHM for new connection"); + } + } #endif @@ -982,7 +991,21 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t reply = reply_new(tag); pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION); + +#ifdef HAVE_CREDS +{ + /* SHM support is only enabled after both sides made sure they are the same user. */ + + pa_creds ucred; + + ucred.uid = getuid(); + ucred.gid = getgid(); + + pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred); +} +#else pa_pstream_send_tagstruct(c->pstream, reply); +#endif } static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -2353,8 +2376,6 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool); assert(c->pstream); - pa_pstream_use_shm(c->pstream, 1); - pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); From 40875d6d05d00eb54265907be36b76ed7fc590ea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 23:45:23 +0000 Subject: [PATCH 1178/1514] enable SHM support on the client side only if both the client and the server run as the same user and the server supports it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1278 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 30 +++++++++++++++++++++++------- src/pulse/internal.h | 2 +- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index df627ee67..55b49a793 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -129,7 +129,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { c->subscribe_userdata = NULL; c->mempool = pa_mempool_new(1); - c->local = -1; + c->is_local = -1; c->server_list = NULL; c->server = NULL; c->autospawn_lock_fd = -1; @@ -376,6 +376,21 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t goto finish; } + /* Enable shared memory support if possible */ + if (c->version >= 10 && + pa_mempool_is_shared(c->mempool) && + c->is_local) { + + /* Only enable SHM if both sides are owned by the same + * user. This is a security measure because otherwise + * data private to the user might leak. */ + + const pa_creds *creds; + if ((creds = pa_pdispatch_creds(pd))) + if (getuid() == creds->uid) + pa_pstream_use_shm(c->pstream, 1); + } + reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); pa_tagstruct_puts(reply, c->name); pa_pstream_send_tagstruct(c->pstream, reply); @@ -409,8 +424,6 @@ static void setup_context(pa_context *c, pa_iochannel *io) { assert(!c->pstream); c->pstream = pa_pstream_new(c->mainloop, io, c->mempool); - pa_pstream_use_shm(c->pstream, 1); - pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); @@ -431,13 +444,16 @@ static void setup_context(pa_context *c, pa_iochannel *io) { { pa_creds ucred; + if (pa_iochannel_creds_supported(io)) + pa_iochannel_creds_enable(io); + ucred.uid = getuid(); ucred.gid = getgid(); pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } #else - pa_pstream_send_tagstruct_with_creds(c->pstream, t, NULL); + pa_pstream_send_tagstruct(c->pstream, t, NULL); #endif pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); @@ -542,7 +558,7 @@ static int context_connect_spawn(pa_context *c) { close(fds[1]); - c->local = 1; + c->is_local = 1; io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); @@ -602,7 +618,7 @@ static int try_next_connection(pa_context *c) { if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT))) continue; - c->local = pa_socket_client_is_local(c->client); + c->is_local = pa_socket_client_is_local(c->client); pa_socket_client_set_callback(c->client, on_connection, c); break; } @@ -938,7 +954,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ int pa_context_is_local(pa_context *c) { assert(c); - return c->local; + return c->is_local; } pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { diff --git a/src/pulse/internal.h b/src/pulse/internal.h index afcfaeff5..fa7d5bbd4 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -71,7 +71,7 @@ struct pa_context { pa_mempool *mempool; - int local; + int is_local; int do_autospawn; int autospawn_lock_fd; pa_spawn_api spawn_api; From c979b87feab8fc444c2402fe6614a18f18c8b1b6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 23:45:57 +0000 Subject: [PATCH 1179/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1279 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index c4bb9b0d3..35d8fffad 100644 --- a/todo +++ b/todo @@ -34,7 +34,6 @@ Auth/Crypto: Features: - alsa mmap driver - alsa driver with hw mixing -- allow passing data with shared memory between local clients and the server - "window manager for sound" - chroot() - use scatter/gather io for sockets From c2db5f88646b2899400479b36ce7eeea44fa00f4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:14:59 +0000 Subject: [PATCH 1180/1514] fix a memory leak git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1280 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/log.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 8bc673e59..ce0932211 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -91,7 +91,7 @@ void pa_log_levelv_meta( va_list ap) { const char *e; - char *text, *t, *n, *location = pa_xstrdup(""); + char *text, *t, *n, *location; assert(level < PA_LOG_LEVEL_MAX); assert(format); @@ -108,6 +108,8 @@ void pa_log_levelv_meta( location = pa_sprintf_malloc("[%s:%i %s()] ", file, line, func); else if (file) location = pa_sprintf_malloc("%s: ", pa_path_get_filename(file)); + else + location = pa_xstrdup(""); if (!pa_utf8_valid(text)) pa_log_level(level, __FILE__": invalid UTF-8 string following below:"); From 8c9bdb838c35c12505a63cab6f0da6912a6bbf49 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:15:22 +0000 Subject: [PATCH 1181/1514] fix allocation of anonymous memory git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1281 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/shm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index bf0071d6b..52867d2a9 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -60,7 +60,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { m->size = size; #ifdef MAP_ANONYMOUS - if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS, fd, 0)) == MAP_FAILED) { + if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } From 046bdd9b30d10a18d21890f7975a8ca268cdfeeb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:15:48 +0000 Subject: [PATCH 1182/1514] deal properly with pa_mempool_new() failing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1282 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 5fdeab569..c36a35bd9 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -46,7 +46,11 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { pa_core* c; - + pa_mempool *pool; + + if (!(pool = pa_mempool_new(shared))) + return NULL; + c = pa_xnew(pa_core, 1); c->mainloop = m; @@ -78,7 +82,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { PA_LLIST_HEAD_INIT(pa_subscription_event, c->subscription_event_queue); c->subscription_event_last = NULL; - c->mempool = pa_mempool_new(shared); + c->mempool = pool; c->disallow_module_loading = 0; From 206ac6f3ee4e849a80d3449b9e0f7e3d794cac27 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:16:38 +0000 Subject: [PATCH 1183/1514] allow importing of external shm data blocks unconditionally, even when local SHM support is disabled git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1283 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pstream.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index e2cfcb633..fa5b27884 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -251,7 +251,9 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo p->use_shm = 0; p->export = NULL; - p->import = NULL; + + /* We do importing unconditionally */ + p->import = pa_memimport_new(p->mempool, memimport_release_cb, p); pa_iochannel_socket_set_rcvbuf(io, 1024*8); pa_iochannel_socket_set_sndbuf(io, 1024*8); @@ -567,7 +569,7 @@ static int do_read(pa_pstream *p) { flags = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]); - if (!p->use_shm && (flags & PA_FLAG_SHMMASK) != 0) { + if (!p->import && (flags & PA_FLAG_SHMMASK) != 0) { pa_log_warn("Recieved SHM frame on a socket where SHM is disabled."); return -1; } @@ -861,19 +863,11 @@ void pa_pstream_use_shm(pa_pstream *p, int enable) { if (enable) { - if (!p->import) - p->import = pa_memimport_new(p->mempool, memimport_release_cb, p); - if (!p->export) p->export = pa_memexport_new(p->mempool, memexport_revoke_cb, p); } else { - if (p->import) { - pa_memimport_free(p->import); - p->import = NULL; - } - if (p->export) { pa_memexport_free(p->export); p->export = NULL; From d785b8fa877b829d9d38082968b35117f7c9d9ec Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:18:30 +0000 Subject: [PATCH 1184/1514] add new "disable-shm" option to client.conf git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1284 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/client-conf.c | 3 +++ src/pulse/client-conf.h | 2 +- src/pulse/context.c | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 619b11c3b..5cd7e3ed5 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -62,6 +62,7 @@ static const pa_client_conf default_conf = { .default_source = NULL, .default_server = NULL, .autospawn = 0, + .disable_shm = 0, .cookie_file = NULL, .cookie_valid = 0, }; @@ -100,6 +101,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { { "default-server", pa_config_parse_string, NULL }, { "autospawn", pa_config_parse_bool, NULL }, { "cookie-file", pa_config_parse_string, NULL }, + { "disable-shm", pa_config_parse_bool, NULL }, { NULL, NULL, NULL }, }; @@ -110,6 +112,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { table[4].data = &c->default_server; table[5].data = &c->autospawn; table[6].data = &c->cookie_file; + table[7].data = &c->disable_shm; f = filename ? fopen((fn = pa_xstrdup(filename)), "r") : diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index a532f0dfe..35728aeb5 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -28,7 +28,7 @@ typedef struct pa_client_conf { char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; - int autospawn; + int autospawn, disable_shm; uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; int cookie_valid; /* non-zero, when cookie is valid */ } pa_client_conf; diff --git a/src/pulse/context.c b/src/pulse/context.c index 55b49a793..b46415907 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -128,7 +128,6 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { c->subscribe_callback = NULL; c->subscribe_userdata = NULL; - c->mempool = pa_mempool_new(1); c->is_local = -1; c->server_list = NULL; c->server = NULL; @@ -149,6 +148,8 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { #endif pa_client_conf_env(c->conf); + c->mempool = pa_mempool_new(!c->conf->disable_shm); + return c; } From c9b6d55090a22256443b0a0f4b24acfa94bf4422 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:18:57 +0000 Subject: [PATCH 1185/1514] add default "disable-shm" option to client.conf git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1285 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/client.conf.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in index c970be56f..3cfd97604 100644 --- a/src/pulse/client.conf.in +++ b/src/pulse/client.conf.in @@ -40,3 +40,6 @@ ### Cookie file ; cookie-file = + +### Disable shared memory data transfer +; disable-shm = 0 From dbc658df4129eec260619f3fd31680ad7977f46c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:20:13 +0000 Subject: [PATCH 1186/1514] add new "disable-shm" server config option git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1286 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 22 +++++++++++++--------- src/daemon/daemon-conf.h | 3 ++- src/daemon/main.c | 15 +++++++++------ 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 2cb066971..dd478126c 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -73,7 +73,8 @@ static const pa_daemon_conf default_conf = { .config_file = NULL, .use_pid_file = 1, .system_instance = 0, - .no_cpu_limit = 0 + .no_cpu_limit = 0, + .disable_shm = 0 #ifdef HAVE_SYS_RESOURCE_H , .rlimit_as = { .value = 0, .is_set = 0 }, .rlimit_core = { .value = 0, .is_set = 0 }, @@ -248,6 +249,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "use-pid-file", pa_config_parse_bool, NULL }, { "system-instance", pa_config_parse_bool, NULL }, { "no-cpu-limit", pa_config_parse_bool, NULL }, + { "disable-shm", pa_config_parse_bool, NULL }, #ifdef HAVE_SYS_RESOURCE_H { "rlimit-as", parse_rlimit, NULL }, { "rlimit-core", parse_rlimit, NULL }, @@ -281,21 +283,22 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[13].data = &c->use_pid_file; table[14].data = &c->system_instance; table[15].data = &c->no_cpu_limit; + table[16].data = &c->disable_shm; #ifdef HAVE_SYS_RESOURCE_H - table[16].data = &c->rlimit_as; - table[17].data = &c->rlimit_core; - table[18].data = &c->rlimit_data; - table[19].data = &c->rlimit_fsize; - table[20].data = &c->rlimit_nofile; - table[21].data = &c->rlimit_stack; + table[17].data = &c->rlimit_as; + table[18].data = &c->rlimit_core; + table[19].data = &c->rlimit_data; + table[20].data = &c->rlimit_fsize; + table[21].data = &c->rlimit_nofile; + table[22].data = &c->rlimit_stack; #ifdef RLIMIT_NPROC - table[22].data = &c->rlimit_nproc; + table[23].data = &c->rlimit_nproc; #endif #ifdef RLIMIT_MEMLOCK #ifndef RLIMIT_NPROC #error "Houston, we have a numbering problem!" #endif - table[23].data = &c->rlimit_memlock; + table[24].data = &c->rlimit_memlock; #endif #endif @@ -367,6 +370,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file); pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance); pa_strbuf_printf(s, "no-cpu-limit = %i\n", !!c->no_cpu_limit); + pa_strbuf_printf(s, "disable_shm = %i\n", !!c->disable_shm); #ifdef HAVE_SYS_RESOURCE_H pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1); pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index 84208336a..b4b833ad4 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -59,7 +59,8 @@ typedef struct pa_daemon_conf { auto_log_target, use_pid_file, system_instance, - no_cpu_limit; + no_cpu_limit, + disable_shm; char *script_commands, *dl_search_path, *default_script_file; pa_log_target_t log_target; pa_log_level_t log_level; diff --git a/src/daemon/main.c b/src/daemon/main.c index 95ba6dd50..8b816b9a5 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -306,10 +306,10 @@ static void set_all_rlimits(const pa_daemon_conf *conf) { #endif int main(int argc, char *argv[]) { - pa_core *c; + pa_core *c = NULL; pa_strbuf *buf = NULL; - pa_daemon_conf *conf; - pa_mainloop *mainloop; + pa_daemon_conf *conf = NULL; + pa_mainloop *mainloop = NULL; char *s; int r, retval = 1, d = 0; @@ -559,8 +559,9 @@ int main(int argc, char *argv[]) { mainloop = pa_mainloop_new(); assert(mainloop); - c = pa_core_new(pa_mainloop_get_api(mainloop), 1); - assert(c); + if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) + goto finish; + c->is_system_instance = !!conf->system_instance; r = pa_signal_init(pa_mainloop_get_api(mainloop)); @@ -651,12 +652,14 @@ int main(int argc, char *argv[]) { pa_cpu_limit_done(); pa_signal_done(); - pa_mainloop_free(mainloop); pa_log_info("Daemon terminated."); finish: + if (mainloop) + pa_mainloop_free(mainloop); + if (conf) pa_daemon_conf_free(conf); From a8519d56677f79e9ef6ee65439531a8d6b955d43 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:20:40 +0000 Subject: [PATCH 1187/1514] add "disable-shm=" to default daemon configuration file git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1287 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon.conf.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 0204b9e32..29b22a42c 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -96,3 +96,6 @@ ; rlimit-stack = -1 ; rlimit-nproc = -1 ; rlimit-memlock = 25 + +## Disable shared memory data transfer +; disable-shm = 0 From 47c7a14b828a35ade80b49ec6bed75b2801af7bb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:21:22 +0000 Subject: [PATCH 1188/1514] add --disable-shm command line option to the daemon git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1288 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/cmdline.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index d3fe8e655..d368b644f 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -60,6 +60,7 @@ enum { ARG_USE_PID_FILE, ARG_CHECK, ARG_NO_CPU_LIMIT, + ARG_DISABLE_SHM, ARG_SYSTEM }; @@ -88,6 +89,7 @@ static struct option long_options[] = { {"check", 0, 0, ARG_CHECK}, {"system", 2, 0, ARG_SYSTEM}, {"no-cpu-limit", 2, 0, ARG_NO_CPU_LIMIT}, + {"disable-shm", 2, 0, ARG_DISABLE_SHM}, {NULL, 0, 0, 0} }; @@ -132,7 +134,8 @@ void pa_cmdline_help(const char *argv0) { " src-zero-order-hold,src-linear,trivial)\n" " --use-pid-file[=BOOL] Create a PID file\n" " --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n" - " platforms that support it.\n\n" + " platforms that support it.\n" + " --disable-shm[=BOOL] Disable shared memory support.\n\n" "STARTUP SCRIPT:\n" " -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with\n" @@ -297,7 +300,13 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d goto fail; } break; - + + case ARG_DISABLE_SHM: + if ((conf->disable_shm = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + pa_log("--disable-shm expects boolean argument"); + goto fail; + } + break; default: goto fail; From 1b7fff323853cee6944a47316dd882785f365f77 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:23:09 +0000 Subject: [PATCH 1189/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1289 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index 35d8fffad..7597cb319 100644 --- a/todo +++ b/todo @@ -23,7 +23,6 @@ Cleanups: - silence generation should be moved into the core to avoid races and code duplication in the backends - rework resampler to not use pa_xrealloc. Use pa_memblock_new instead. -- allow disabling shm in both client and server Auth/Crypto: - ssl From 521d15babb5be8f3ce47d2e73b1b3470c71159ba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 02:23:11 +0000 Subject: [PATCH 1190/1514] fix a memory leak git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1290 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 0e4f278c2..59c47743d 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -237,8 +237,10 @@ static char* client_name(pa_client *c) { t = pa_sprintf_malloc("%s$%s", c->driver, c->name); t[strcspn(t, "\n\r#")] = 0; - if (!*t) + if (!*t) { + pa_xfree(t); return NULL; + } if ((e = strrchr(t, '('))) { char *k = e + 1 + strspn(e + 1, "0123456789-"); From af87c7d21bad55d91daa7a60028df5d0ee66cd8d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 02:23:52 +0000 Subject: [PATCH 1191/1514] rework the resample to allocate temporary memory with pa_memblock_new() instead of pa_xrealloc() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1291 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/resampler.c | 83 +++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index 742267146..b01420491 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -51,6 +51,7 @@ struct pa_resampler { }; struct impl_libsamplerate { + pa_memblock *buf1_block, *buf2_block, *buf3_block, *buf4_block; float* buf1, *buf2, *buf3, *buf4; unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples; @@ -223,10 +224,14 @@ static void libsamplerate_free(pa_resampler *r) { if (u->src_state) src_delete(u->src_state); - pa_xfree(u->buf1); - pa_xfree(u->buf2); - pa_xfree(u->buf3); - pa_xfree(u->buf4); + if (u->buf1_block) + pa_memblock_unref(u->buf1_block); + if (u->buf2_block) + pa_memblock_unref(u->buf2_block); + if (u->buf3_block) + pa_memblock_unref(u->buf3_block); + if (u->buf4_block) + pa_memblock_unref(u->buf4_block); pa_xfree(u); } @@ -281,8 +286,14 @@ static float * convert_to_float(pa_resampler *r, void *input, unsigned n_frames) n_samples = n_frames * r->i_ss.channels; - if (u->buf1_samples < n_samples) - u->buf1 = pa_xrealloc(u->buf1, sizeof(float) * (u->buf1_samples = n_samples)); + if (u->buf1_samples < n_samples) { + if (u->buf1_block) + pa_memblock_unref(u->buf1_block); + + u->buf1_samples = n_samples; + u->buf1_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); + u->buf1 = u->buf1_block->data; + } u->to_float32ne_func(n_samples, input, u->buf1); @@ -307,8 +318,14 @@ static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) { n_samples = n_frames * r->o_ss.channels; - if (u->buf2_samples < n_samples) - u->buf2 = pa_xrealloc(u->buf2, sizeof(float) * (u->buf2_samples = n_samples)); + if (u->buf2_samples < n_samples) { + if (u->buf2_block) + pa_memblock_unref(u->buf2_block); + + u->buf2_samples = n_samples; + u->buf2_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); + u->buf2 = u->buf2_block->data; + } memset(u->buf2, 0, n_samples * sizeof(float)); @@ -351,8 +368,14 @@ static float *resample(pa_resampler *r, float *input, unsigned *n_frames) { out_n_frames = (*n_frames*r->o_ss.rate/r->i_ss.rate)+1024; out_n_samples = out_n_frames * r->o_ss.channels; - if (u->buf3_samples < out_n_samples) - u->buf3 = pa_xrealloc(u->buf3, sizeof(float) * (u->buf3_samples = out_n_samples)); + if (u->buf3_samples < out_n_samples) { + if (u->buf3_block) + pa_memblock_unref(u->buf3_block); + + u->buf3_samples = out_n_samples; + u->buf3_block = pa_memblock_new(r->mempool, sizeof(float) * out_n_samples); + u->buf3 = u->buf3_block->data; + } data.data_in = input; data.input_frames = *n_frames; @@ -388,9 +411,15 @@ static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames n_samples = n_frames * r->o_ss.channels; - if (u->buf4_samples < n_samples) - u->buf4 = pa_xrealloc(u->buf4, sizeof(float) * (u->buf4_samples = n_samples)); - + if (u->buf4_samples < n_samples) { + if (u->buf4_block) + pa_memblock_unref(u->buf4_block); + + u->buf4_samples = n_samples; + u->buf4_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); + u->buf4 = u->buf4_block->data; + } + u->from_float32ne_func(n_samples, input, u->buf4); return u->buf4; @@ -429,30 +458,33 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun out->index = in->index; out->length = in->length; } else { - float **p = NULL; - out->length = n_frames * r->o_fz; out->index = 0; - + out->memblock = NULL; + if (output == u->buf1) { - p = &u->buf1; + u->buf1 = NULL; u->buf1_samples = 0; + out->memblock = u->buf1_block; + u->buf1_block = NULL; } else if (output == u->buf2) { - p = &u->buf2; + u->buf2 = NULL; u->buf2_samples = 0; + out->memblock = u->buf2_block; + u->buf2_block = NULL; } else if (output == u->buf3) { - p = &u->buf3; + u->buf3 = NULL; u->buf3_samples = 0; + out->memblock = u->buf3_block; + u->buf3_block = NULL; } else if (output == u->buf4) { - p = &u->buf4; + u->buf4 = NULL; u->buf4_samples = 0; + out->memblock = u->buf4_block; + u->buf4_block = NULL; } - assert(p); - - /* Take the existing buffer and make it a memblock */ - out->memblock = pa_memblock_new_malloced(r->mempool, *p, out->length); - *p = NULL; + assert(out->memblock); } } else { out->memblock = NULL; @@ -485,6 +517,7 @@ static int libsamplerate_init(pa_resampler *r) { r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1); u->buf1 = u->buf2 = u->buf3 = u->buf4 = NULL; + u->buf1_block = u->buf2_block = u->buf3_block = u->buf4_block = NULL; u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0; if (r->i_ss.format == PA_SAMPLE_FLOAT32NE) From 16ff83f5c0acbd606f23090ebd4cba9ecaf502a7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 02:24:59 +0000 Subject: [PATCH 1192/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1292 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/todo b/todo index 7597cb319..a47caa7c6 100644 --- a/todo +++ b/todo @@ -22,7 +22,9 @@ Cleanups: - use software volume when hardware doesn't support all channels (alsa done) - silence generation should be moved into the core to avoid races and code duplication in the backends -- rework resampler to not use pa_xrealloc. Use pa_memblock_new instead. +- pdispatch: split large memory blocks when sending +- sysv shm +- posix_memalign Auth/Crypto: - ssl From 57f0b08cc1c6be0afc4f563d41cacae7c5d820a9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 16:25:15 +0000 Subject: [PATCH 1193/1514] generate per-type memory block statistics git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1293 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/memblock.c | 19 ++++++++++++++++++- src/pulsecore/memblock.h | 4 ++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 90494fb6f..c34ddee55 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -121,6 +121,9 @@ static void stat_add(pa_memblock*b) { b->pool->stat.n_imported++; b->pool->stat.imported_size += b->length; } + + b->pool->stat.n_allocated_by_type[b->type]++; + b->pool->stat.n_accumulated_by_type[b->type]++; } static void stat_remove(pa_memblock *b) { @@ -140,6 +143,8 @@ static void stat_remove(pa_memblock *b) { b->pool->stat.n_imported --; b->pool->stat.imported_size -= b->length; } + + b->pool->stat.n_allocated_by_type[b->type]--; } static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length); @@ -353,13 +358,21 @@ void pa_memblock_unref(pa_memblock*b) { if (b->type == PA_MEMBLOCK_POOL_EXTERNAL) pa_xfree(b); + + break; } + + case PA_MEMBLOCK_TYPE_MAX: + default: + abort(); } } static void memblock_make_local(pa_memblock *b) { assert(b); + b->pool->stat.n_allocated_by_type[b->type]--; + if (b->length <= b->pool->block_size - sizeof(struct mempool_slot)) { struct mempool_slot *slot; @@ -373,7 +386,7 @@ static void memblock_make_local(pa_memblock *b) { new_data = mempool_slot_data(slot); memcpy(new_data, b->data, b->length); b->data = new_data; - return; + goto finish; } } @@ -382,6 +395,10 @@ static void memblock_make_local(pa_memblock *b) { b->per_type.user.free_cb = pa_xfree; b->read_only = 0; b->data = pa_xmemdup(b->data, b->length); + +finish: + b->pool->stat.n_allocated_by_type[b->type]++; + b->pool->stat.n_accumulated_by_type[b->type]++; } void pa_memblock_unref_fixed(pa_memblock *b) { diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index 70cd1b9e8..620bf7263 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -40,6 +40,7 @@ typedef enum pa_memblock_type { PA_MEMBLOCK_USER, /* User supplied memory, to be freed with free_cb */ PA_MEMBLOCK_FIXED, /* data is a pointer to fixed memory that needs not to be freed */ PA_MEMBLOCK_IMPORTED, /* Memory is imported from another process via shm */ + PA_MEMBLOCK_TYPE_MAX } pa_memblock_type_t; typedef struct pa_memblock pa_memblock; @@ -84,6 +85,9 @@ struct pa_mempool_stat { unsigned n_too_large_for_pool; unsigned n_pool_full; + + unsigned n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; + unsigned n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; }; /* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL or PA_MEMBLOCK_APPENDED, depending on the size */ From c6ca9a85c375a0ecc3b205b05b7867b251676162 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 16:25:41 +0000 Subject: [PATCH 1194/1514] print per-type memory block statistics on "stat" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1294 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/cli-command.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 811b96d2a..8ea9262bd 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -242,7 +242,19 @@ static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { char s[256]; const pa_mempool_stat *stat; - assert(c && t); + unsigned k; + + static const char* const type_table[PA_MEMBLOCK_TYPE_MAX] = { + [PA_MEMBLOCK_POOL] = "POOL", + [PA_MEMBLOCK_POOL_EXTERNAL] = "POOL_EXTERNAL", + [PA_MEMBLOCK_APPENDED] = "APPENDED", + [PA_MEMBLOCK_USER] = "USER", + [PA_MEMBLOCK_FIXED] = "FIXED", + [PA_MEMBLOCK_IMPORTED] = "IMPORTED", + }; + + assert(c); + assert(t); stat = pa_mempool_get_stat(c->mempool); @@ -273,6 +285,13 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_namereg_get_default_sink_name(c), pa_namereg_get_default_source_name(c)); + for (k = 0; k < PA_MEMBLOCK_TYPE_MAX; k++) + pa_strbuf_printf(buf, + "Memory blocks of type %s: %u allocated/%u accumulated.\n", + type_table[k], + stat->n_allocated_by_type[k], + stat->n_accumulated_by_type[k]); + return 0; } From d50c56a8f31515e1678b5d56b34a00b58b735539 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 16:26:08 +0000 Subject: [PATCH 1195/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1295 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 + 1 file changed, 1 insertion(+) diff --git a/todo b/todo index a47caa7c6..4100ee2de 100644 --- a/todo +++ b/todo @@ -25,6 +25,7 @@ Cleanups: - pdispatch: split large memory blocks when sending - sysv shm - posix_memalign +- test sample upload Auth/Crypto: - ssl From 3e0f00f93deed28e68b60f29fc42838575241b0e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 17:27:27 +0000 Subject: [PATCH 1196/1514] if MAP_ANONYMOUS is not supported use posix_memalign if possible to allocate the memory pool git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1296 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/shm.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index 52867d2a9..02528126c 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -19,6 +19,10 @@ USA. ***/ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -32,6 +36,7 @@ #include #include #include +#include #include "shm.h" @@ -64,6 +69,15 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } +#elif defined(HAVE_POSIX_MEMALIGN) + { + int r; + + if ((r = posix_memalign(&m->ptr, sysconf(_SC_PAGESIZE), size)) < 0) { + pa_log("posix_memalign() failed: %s", pa_cstrerror(r)); + goto fail; + } + } #else m->ptr = pa_xmalloc(m->size); #endif @@ -114,7 +128,11 @@ void pa_shm_free(pa_shm *m) { assert(m->ptr && m->ptr != MAP_FAILED); assert(m->size > 0); -#ifndef MAP_ANONYMOUS +#if !defined(MAP_ANONYMOUS) && defined(HAVE_POSIX_MEMALIGN) + if (!m->shared) + free(m->ptr); + else +#elif !defined(MAP_ANONYMOUS) if (!m->shared) pa_xfree(m->ptr); else @@ -139,7 +157,6 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { assert(m); assert(m->ptr && m->ptr != MAP_FAILED); assert(m->size > 0); - assert(m->do_unlink); assert(offset < m->size); assert(offset+size < m->size); From b642325d1090b699e14bf8f218b61227a9d1b2ab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 17:30:30 +0000 Subject: [PATCH 1197/1514] check for posix_memalign and friends git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1297 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 07b2cfa12..b6b5f495c 100644 --- a/configure.ac +++ b/configure.ac @@ -240,12 +240,11 @@ AC_CHECK_FUNCS([lstat]) # Non-standard -AC_CHECK_FUNCS(setresuid) -AC_CHECK_FUNCS(setresgid) -AC_CHECK_FUNCS(setreuid) -AC_CHECK_FUNCS(setregid) -AC_CHECK_FUNCS(seteuid) -AC_CHECK_FUNCS(setegid) +AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid]) + +# Memory mangement + +AC_CHECK_FUNCS([mmap posix_memalign madvise]) #### POSIX threads #### From 84d1d3eff293e9d30b65d2656a7e5abdad893075 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 17:34:08 +0000 Subject: [PATCH 1198/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1298 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/todo b/todo index 4100ee2de..7719190ce 100644 --- a/todo +++ b/todo @@ -23,9 +23,12 @@ Cleanups: - silence generation should be moved into the core to avoid races and code duplication in the backends - pdispatch: split large memory blocks when sending -- sysv shm -- posix_memalign -- test sample upload +- don't read/write audio data from/to ALSA devices if noone is listening + +Test: +- autoload +- sample upload + SHM +- SHM revoke stuff Auth/Crypto: - ssl From 79b26280cc11cbb0d12185ba8226eeb5e7652467 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 18:28:04 +0000 Subject: [PATCH 1199/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1299 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/todo b/todo index 7719190ce..4b52e7f03 100644 --- a/todo +++ b/todo @@ -27,8 +27,6 @@ Cleanups: Test: - autoload -- sample upload + SHM -- SHM revoke stuff Auth/Crypto: - ssl @@ -52,6 +50,8 @@ Features: (switch to capture when a recording client connects and drop playback during that time) - Support for device selection in waveout driver +- beefup module-volume-restore to restore the device a stream was connected to, too +- add an API to libpulse for allocating memory from the pa_context memory pool Long term: - pass meta info for hearing impaired From c0b3e8b34605e902f2aed311b0ed393aadd9592d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 18:57:33 +0000 Subject: [PATCH 1200/1514] when transferring large memory chunks of a pa_pstream, split them up git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1300 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pstream.c | 42 ++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index fa5b27884..511972d98 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -78,7 +78,8 @@ enum { typedef uint32_t pa_pstream_descriptor[PA_PSTREAM_DESCRIPTOR_MAX]; #define PA_PSTREAM_DESCRIPTOR_SIZE (PA_PSTREAM_DESCRIPTOR_MAX*sizeof(uint32_t)) -#define FRAME_SIZE_MAX PA_SCACHE_ENTRY_SIZE_MAX /* allow uploading a single sample in one frame at max */ +#define FRAME_SIZE_MAX_ALLOW PA_SCACHE_ENTRY_SIZE_MAX /* allow uploading a single sample in one frame at max */ +#define FRAME_SIZE_MAX_USE (1024*64) struct item_info { enum { @@ -323,7 +324,7 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre } void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) { - struct item_info *i; + size_t length, idx; assert(p); assert(p->ref >= 1); @@ -333,19 +334,34 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa if (p->dead) return; - i = pa_xnew(struct item_info, 1); - i->type = PA_PSTREAM_ITEM_MEMBLOCK; - i->chunk = *chunk; - i->channel = channel; - i->offset = offset; - i->seek_mode = seek_mode; + length = chunk->length; + idx = 0; + + while (length > 0) { + struct item_info *i; + size_t n; + + i = pa_xnew(struct item_info, 1); + i->type = PA_PSTREAM_ITEM_MEMBLOCK; + + n = length < FRAME_SIZE_MAX_USE ? length : FRAME_SIZE_MAX_USE; + i->chunk.index = chunk->index + idx; + i->chunk.length = n; + i->chunk.memblock = pa_memblock_ref(chunk->memblock); + + i->channel = channel; + i->offset = offset; + i->seek_mode = seek_mode; #ifdef HAVE_CREDS - i->with_creds = 0; + i->with_creds = 0; #endif + + pa_queue_push(p->send_queue, i); - pa_memblock_ref(i->chunk.memblock); - - pa_queue_push(p->send_queue, i); + idx += n; + length -= n; + } + p->mainloop->defer_enable(p->defer_event, 1); } @@ -599,7 +615,7 @@ static int do_read(pa_pstream *p) { length = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]); - if (length > FRAME_SIZE_MAX) { + if (length > FRAME_SIZE_MAX_ALLOW) { pa_log_warn("Recieved invalid frame size : %lu", (unsigned long) length); return -1; } From ce11b1f23098e07742f71c878b7a174791ccee22 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 18:58:17 +0000 Subject: [PATCH 1201/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1301 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index 4b52e7f03..4f2a8f3a1 100644 --- a/todo +++ b/todo @@ -22,7 +22,6 @@ Cleanups: - use software volume when hardware doesn't support all channels (alsa done) - silence generation should be moved into the core to avoid races and code duplication in the backends -- pdispatch: split large memory blocks when sending - don't read/write audio data from/to ALSA devices if noone is listening Test: From bf62e77f71733cd458df6fc02c6d9eda82a8e0c4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 23:04:04 +0000 Subject: [PATCH 1202/1514] fix a bad memory access git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1302 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/source-output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index a2fc8519b..352fce142 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -301,7 +301,7 @@ pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) { int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { pa_source *origin; - pa_resampler *new_resampler; + pa_resampler *new_resampler = NULL; assert(o); assert(o->ref >= 1); From bffde5da05806ed1801b29b0440e9f542b3a6017 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 23:06:45 +0000 Subject: [PATCH 1203/1514] If a client leaves the sink/source for a stream unspecified by passing NULL as sink/source name sink/source we should pass NULL to pa_sink_input_new()/pa_source_output_new() as too. This allows hooks to change the sink/source device only if it is left unspecified by the client git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1303 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-esound.c | 21 ++++++++++++-------- src/pulsecore/protocol-native.c | 34 +++++++++++++++++---------------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index c96a98b9a..80aeb27b1 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -327,7 +327,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t int32_t format, rate; pa_sample_spec ss; size_t l; - pa_sink *sink; + pa_sink *sink = NULL; pa_sink_input_new_data sdata; assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX)); @@ -344,8 +344,11 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t format_esd2native(format, c->swap_byte_order, &ss); CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification"); - sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1); - CHECK_VALIDITY(sink, "No such sink"); + + if (c->protocol->sink_name) { + sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1); + CHECK_VALIDITY(sink, "No such sink"); + } strncpy(name, data, sizeof(name)); name[sizeof(name)-1] = 0; @@ -397,7 +400,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length) { char name[ESD_NAME_MAX], *utf8_name; int32_t format, rate; - pa_source *source; + pa_source *source = NULL; pa_sample_spec ss; size_t l; pa_source_output_new_data sdata; @@ -431,10 +434,12 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co } } else { assert(request == ESD_PROTO_STREAM_REC); - - if (!(source = pa_namereg_get(c->protocol->core, c->protocol->source_name, PA_NAMEREG_SOURCE, 1))) { - pa_log("no such source."); - return -1; + + if (c->protocol->source_name) { + if (!(source = pa_namereg_get(c->protocol->core, c->protocol->source_name, PA_NAMEREG_SOURCE, 1))) { + pa_log("no such source."); + return -1; + } } } diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 40a839739..0f0150718 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -319,7 +319,7 @@ static struct record_stream* record_stream_new( size_t base; pa_source_output_new_data data; - assert(c && source && ss && name && maxlength); + assert(c && ss && name && maxlength); pa_source_output_new_data_init(&data); data.source = source; @@ -330,7 +330,7 @@ static struct record_stream* record_stream_new( data.module = c->protocol->module; data.client = c->client; - if (!(source_output = pa_source_output_new(source->core, &data, 0))) + if (!(source_output = pa_source_output_new(c->protocol->core, &data, 0))) return NULL; s = pa_xnew(struct record_stream, 1); @@ -389,7 +389,7 @@ static struct playback_stream* playback_stream_new( int64_t start_index; pa_sink_input_new_data data; - assert(c && sink && ss && name && maxlength); + assert(c && ss && name && maxlength); /* Find syncid group */ for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) { @@ -402,8 +402,8 @@ static struct playback_stream* playback_stream_new( } /* Synced streams must connect to the same sink */ - if (ssync && ssync->sink_input->sink != sink) - return NULL; + if (ssync) + sink = ssync->sink_input->sink; pa_sink_input_new_data_init(&data); data.sink = sink; @@ -415,7 +415,7 @@ static struct playback_stream* playback_stream_new( data.module = c->protocol->module; data.client = c->client; - if (!(sink_input = pa_sink_input_new(sink->core, &data, 0))) + if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, 0))) return NULL; s = pa_xnew(struct playback_stream, 1); @@ -725,7 +725,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC pa_sample_spec ss; pa_channel_map map; pa_tagstruct *reply; - pa_sink *sink; + pa_sink *sink = NULL; pa_cvolume volume; int corked; @@ -761,12 +761,13 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, maxlength > 0 && maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); - if (sink_index != PA_INVALID_INDEX) + if (sink_index != PA_INVALID_INDEX) { sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); - else + CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); + } else if (sink_name) { sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1); - - CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); + } s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume, syncid); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); @@ -844,7 +845,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_sample_spec ss; pa_channel_map map; pa_tagstruct *reply; - pa_source *source; + pa_source *source = NULL; int corked; assert(c && t && c->protocol && c->protocol->core); @@ -869,12 +870,13 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); - if (source_index != PA_INVALID_INDEX) + if (source_index != PA_INVALID_INDEX) { source = pa_idxset_get_by_index(c->protocol->core->sources, source_index); - else + CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY); + } else if (source_name) { source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1); - - CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY); + } s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); From 3dbc4ae973070760bcc2d525fdb9dcbaecfd1835 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 23:08:50 +0000 Subject: [PATCH 1204/1514] restore the sink/source for a client in addition to the playback volume. This changes the file format of the table file. To avoid parse errors ~/.pulse/volume.table has been renamed to ~/.pulse/volume-restore.table git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1304 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 178 ++++++++++++++++++++++------ 1 file changed, 141 insertions(+), 37 deletions(-) diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 59c47743d..efa59f406 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -41,19 +41,21 @@ #include #include #include +#include #include +#include #include #include "module-volume-restore-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Automatically restore volume of playback streams") +PA_MODULE_DESCRIPTION("Automatically restore the volume and the devices of streams") PA_MODULE_USAGE("table=") PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#define DEFAULT_VOLUME_TABLE_FILE "volume.table" +#define DEFAULT_VOLUME_TABLE_FILE "volume-restore.table" static const char* const valid_modargs[] = { "table", @@ -62,13 +64,16 @@ static const char* const valid_modargs[] = { struct rule { char* name; + int volume_is_set; pa_cvolume volume; + char *sink; + char *source; }; struct userdata { pa_hashmap *hashmap; pa_subscription *subscription; - pa_hook_slot *hook_slot; + pa_hook_slot *sink_input_hook_slot, *source_output_hook_slot; int modified; char *table_file; }; @@ -114,7 +119,7 @@ static int load_rules(struct userdata *u) { FILE *f; int n = 0; int ret = -1; - char buf_name[256], buf_volume[256]; + char buf_name[256], buf_volume[256], buf_sink[256], buf_source[256]; char *ln = buf_name; f = u->table_file ? @@ -136,6 +141,7 @@ static int load_rules(struct userdata *u) { while (!feof(f)) { struct rule *rule; pa_cvolume v; + int v_is_set; if (!fgets(ln, sizeof(buf_name), f)) break; @@ -144,7 +150,7 @@ static int load_rules(struct userdata *u) { pa_strip_nl(ln); - if (ln[0] == '#' || !*ln ) + if (ln[0] == '#') continue; if (ln == buf_name) { @@ -152,28 +158,46 @@ static int load_rules(struct userdata *u) { continue; } - assert(ln == buf_volume); - - if (!parse_volume(buf_volume, &v)) { - pa_log("parse failure in %s:%u, stopping parsing", u->table_file, n); - goto finish; + if (ln == buf_volume) { + ln = buf_sink; + continue; } + if (ln == buf_sink) { + ln = buf_source; + continue; + } + + assert(ln == buf_source); + + if (buf_volume[0]) { + if (!parse_volume(buf_volume, &v)) { + pa_log("parse failure in %s:%u, stopping parsing", u->table_file, n); + goto finish; + } + + v_is_set = 1; + } else + v_is_set = 0; + ln = buf_name; if (pa_hashmap_get(u->hashmap, buf_name)) { pa_log("double entry in %s:%u, ignoring", u->table_file, n); - goto finish; + continue; } rule = pa_xnew(struct rule, 1); rule->name = pa_xstrdup(buf_name); - rule->volume = v; + if ((rule->volume_is_set = v_is_set)) + rule->volume = v; + rule->sink = buf_sink[0] ? pa_xstrdup(buf_sink) : NULL; + rule->source = buf_source[0] ? pa_xstrdup(buf_source) : NULL; pa_hashmap_put(u->hashmap, rule->name, rule); } - if (ln == buf_volume) { + if (ln != buf_name) { pa_log("invalid number of lines in %s.", u->table_file); goto finish; } @@ -209,12 +233,18 @@ static int save_rules(struct userdata *u) { while ((rule = pa_hashmap_iterate(u->hashmap, &state, NULL))) { unsigned i; - fprintf(f, "%s\n%u", rule->name, rule->volume.channels); - - for (i = 0; i < rule->volume.channels; i++) - fprintf(f, " %u", rule->volume.values[i]); + fprintf(f, "%s\n", rule->name); - fprintf(f, "\n"); + if (rule->volume_is_set) { + fprintf(f, "%u", rule->volume.channels); + + for (i = 0; i < rule->volume.channels; i++) + fprintf(f, " %u", rule->volume.values[i]); + } + + fprintf(f, "\n%s\n%s\n", + rule->sink ? rule->sink : "", + rule->source ? rule->source : ""); } ret = 0; @@ -260,7 +290,8 @@ static char* client_name(pa_client *c) { static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = userdata; - pa_sink_input *si; + pa_sink_input *si = NULL; + pa_source_output *so = NULL; struct rule *r; char *name; @@ -268,36 +299,80 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 assert(u); if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) && - t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE)) + t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) && + t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) && + t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE)) return; + + if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) { + if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) + return; - if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) - return; - - if (!si->client || !(name = client_name(si->client))) - return; + if (!si->client || !(name = client_name(si->client))) + return; + } else { + assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT); + + if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) + return; + + if (!so->client || !(name = client_name(so->client))) + return; + } if ((r = pa_hashmap_get(u->hashmap, name))) { pa_xfree(name); - if (!pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { - pa_log_info("Saving volume for <%s>", r->name); - r->volume = *pa_sink_input_get_volume(si); - u->modified = 1; + if (si) { + + if (!r->volume_is_set || !pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { + pa_log_info("Saving volume for <%s>", r->name); + r->volume = *pa_sink_input_get_volume(si); + r->volume_is_set = 1; + u->modified = 1; + } + + if (!r->sink || strcmp(si->sink->name, r->sink) != 0) { + pa_log_info("Saving sink for <%s>", r->name); + pa_xfree(r->sink); + r->sink = pa_xstrdup(si->sink->name); + u->modified = 1; + } + } else { + assert(so); + + if (!r->source || strcmp(so->source->name, r->source) != 0) { + pa_log_info("Saving source for <%s>", r->name); + pa_xfree(r->source); + r->source = pa_xstrdup(so->source->name); + u->modified = 1; + } } + } else { pa_log_info("Creating new entry for <%s>", name); r = pa_xnew(struct rule, 1); r->name = name; - r->volume = *pa_sink_input_get_volume(si); - pa_hashmap_put(u->hashmap, r->name, r); + if (si) { + r->volume = *pa_sink_input_get_volume(si); + r->volume_is_set = 1; + r->sink = pa_xstrdup(si->sink->name); + r->source = NULL; + } else { + assert(so); + r->volume_is_set = 0; + r->sink = NULL; + r->source = pa_xstrdup(so->source->name); + } + + pa_hashmap_put(u->hashmap, r->name, r); u->modified = 1; } } -static pa_hook_result_t hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { +static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { struct rule *r; char *name; @@ -308,10 +383,34 @@ static pa_hook_result_t hook_callback(pa_core *c, pa_sink_input_new_data *data, if ((r = pa_hashmap_get(u->hashmap, name))) { - if (data->sample_spec_is_set && data->sample_spec.channels == r->volume.channels) { + if (r->volume_is_set && data->sample_spec.channels == r->volume.channels) { pa_log_info("Restoring volume for <%s>", r->name); pa_sink_input_new_data_set_volume(data, &r->volume); } + + if (!data->sink && r->sink) { + if ((data->sink = pa_namereg_get(c, r->sink, PA_NAMEREG_SINK, 1))) + pa_log_info("Restoring sink for <%s>", r->name); + } + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output_new_data *data, struct userdata *u) { + struct rule *r; + char *name; + + assert(data); + + if (!data->client || !(name = client_name(data->client))) + return PA_HOOK_OK; + + if ((r = pa_hashmap_get(u->hashmap, name))) { + if (!data->source && r->source) { + if ((data->source = pa_namereg_get(c, r->source, PA_NAMEREG_SOURCE, 1))) + pa_log_info("Restoring source for <%s>", r->name); + } } return PA_HOOK_OK; @@ -340,8 +439,9 @@ int pa__init(pa_core *c, pa_module*m) { if (load_rules(u) < 0) goto fail; - u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, subscribe_callback, u); - u->hook_slot = pa_hook_connect(&c->hook_sink_input_new, (pa_hook_cb_t) hook_callback, u); + u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u); + u->sink_input_hook_slot = pa_hook_connect(&c->hook_sink_input_new, (pa_hook_cb_t) sink_input_hook_callback, u); + u->source_output_hook_slot = pa_hook_connect(&c->hook_source_output_new, (pa_hook_cb_t) source_output_hook_callback, u); pa_modargs_free(ma); return 0; @@ -360,6 +460,8 @@ static void free_func(void *p, void *userdata) { assert(r); pa_xfree(r->name); + pa_xfree(r->sink); + pa_xfree(r->source); pa_xfree(r); } @@ -375,8 +477,10 @@ void pa__done(pa_core *c, pa_module*m) { if (u->subscription) pa_subscription_free(u->subscription); - if (u->hook_slot) - pa_hook_slot_free(u->hook_slot); + if (u->sink_input_hook_slot) + pa_hook_slot_free(u->sink_input_hook_slot); + if (u->source_output_hook_slot) + pa_hook_slot_free(u->source_output_hook_slot); if (u->hashmap) { From 3d32b96771ece395eb25988f2a644d97903ce513 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 23:09:23 +0000 Subject: [PATCH 1205/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1305 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 - 1 file changed, 1 deletion(-) diff --git a/todo b/todo index 4f2a8f3a1..befa5ee95 100644 --- a/todo +++ b/todo @@ -49,7 +49,6 @@ Features: (switch to capture when a recording client connects and drop playback during that time) - Support for device selection in waveout driver -- beefup module-volume-restore to restore the device a stream was connected to, too - add an API to libpulse for allocating memory from the pa_context memory pool Long term: From 26201b27ec3233bb0f28539d63e49bb00d285d2a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 21 Aug 2006 22:37:09 +0000 Subject: [PATCH 1206/1514] fix pactl output (sink drivers and names where switched) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1306 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 028f71c8a..110585f79 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -228,8 +228,8 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int "Latency: %0.0f usec\n" "Flags: %s%s%s\n", i->index, - i->driver, i->name, + i->driver, i->description, pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), From 25c0640ac2206872f76df70368180c74153581e3 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:12:50 +0000 Subject: [PATCH 1207/1514] Add an ifdef for when we do not have creds. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1307 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index b46415907..f2af4727b 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -385,11 +385,13 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t /* Only enable SHM if both sides are owned by the same * user. This is a security measure because otherwise * data private to the user might leak. */ - + +#ifdef HAVE_CREDS const pa_creds *creds; if ((creds = pa_pdispatch_creds(pd))) if (getuid() == creds->uid) pa_pstream_use_shm(c->pstream, 1); +#endif } reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); From 8a16c731514a7d25e37ea70080e4c3d42fb5e5d4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:18:07 +0000 Subject: [PATCH 1208/1514] Fix call to pa_pstream_send_tagstruct(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1308 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index f2af4727b..2f9106a5c 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -456,7 +456,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } #else - pa_pstream_send_tagstruct(c->pstream, t, NULL); + pa_pstream_send_tagstruct(c->pstream, t); #endif pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); From 6e3d8af52078db439f9cacece690dfe96d353c42 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:21:41 +0000 Subject: [PATCH 1209/1514] Add header for pa_cstrerror(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1309 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index e13254e93..06de7d369 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -52,6 +52,7 @@ #include #include #include +#include #include "module-solaris-symdef.h" From 1c320fe0b76995c50cfc4b54bfe90e859accdfc4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:23:47 +0000 Subject: [PATCH 1210/1514] Fix calls to pa_memblock_new(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1310 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 06de7d369..d198ee611 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -202,7 +202,7 @@ static void do_read(struct userdata *u) { err = ioctl(u->fd, I_NREAD, &l); assert(err >= 0); - memchunk.memblock = pa_memblock_new(l, u->core->memblock_stat); + memchunk.memblock = pa_memblock_new(u->core->mempool, l); assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); @@ -589,7 +589,7 @@ int pa__init(pa_core *c, pa_module*m) { u->frame_size = pa_frame_size(&ss); u->buffer_size = buffer_size; - u->silence.memblock = pa_memblock_new(u->silence.length = CHUNK_SIZE, u->core->memblock_stat); + u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length = CHUNK_SIZE); assert(u->silence.memblock); pa_silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; From 7bc71103fb51609edfb0d7893344871a00f1221d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:25:45 +0000 Subject: [PATCH 1211/1514] Fix missing header for timeval helpers. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1311 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index d198ee611..8eaf6758e 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include From d964459a649ff8c8d73388bc810a2ea629abe5c9 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:41:23 +0000 Subject: [PATCH 1212/1514] Fix detection of page size for non-POSIX systems. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1312 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 3 ++- src/pulsecore/memblock.c | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index b6b5f495c..4aba536d4 100644 --- a/configure.ac +++ b/configure.ac @@ -221,7 +221,8 @@ AC_FUNC_FORK AC_FUNC_GETGROUPS AC_FUNC_SELECT_ARGTYPES AC_CHECK_FUNCS([chmod chown getaddrinfo getgrgid_r getpwuid_r gettimeofday \ - getuid inet_ntop inet_pton nanosleep pipe setpgid setsid sigaction sleep]) + getuid inet_ntop inet_pton nanosleep pipe setpgid setsid sigaction sleep \ + sysconf]) AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0]) AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1") diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index c34ddee55..9e5c5b81d 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -443,8 +443,14 @@ pa_mempool* pa_mempool_new(int shared) { p = pa_xnew(pa_mempool, 1); +#ifdef HAVE_SYSCONF ps = (size_t) sysconf(_SC_PAGESIZE); - +#elif defined(PAGE_SIZE) + ps = (size_t) PAGE_SIZE; +#else + ps = 4096; /* Let's hope it's like x86. */ +#endif + p->block_size = (PA_MEMPOOL_SLOT_SIZE/ps)*ps; if (p->block_size < ps) From b5ef414ec89f827b741e2656f3236db7b4195dbf Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 11:37:53 +0000 Subject: [PATCH 1213/1514] Fix call to pa_memblock_new(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1313 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 2cc665b42..7965d0152 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -217,7 +217,7 @@ static void do_read(struct userdata *u) waveInUnprepareHeader(u->hwi, hdr, sizeof(WAVEHDR)); if (hdr->dwBytesRecorded) { - memchunk.memblock = pa_memblock_new(hdr->dwBytesRecorded, u->core->memblock_stat); + memchunk.memblock = pa_memblock_new(u->core->mempool, hdr->dwBytesRecorded); assert(memchunk.memblock); memcpy((char*)memchunk.memblock->data, hdr->lpData, hdr->dwBytesRecorded); @@ -564,7 +564,7 @@ int pa__init(pa_core *c, pa_module*m) { } u->silence.length = u->fragment_size; - u->silence.memblock = pa_memblock_new(u->silence.length, u->core->memblock_stat); + u->silence.memblock = pa_memblock_new(u->core->mem, u->silence.length); assert(u->silence.memblock); pa_silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; From eeabf636732f784969bded89a215b3a0b263852f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 11:38:46 +0000 Subject: [PATCH 1214/1514] Add missing header. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1314 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 7965d0152..d4fa121b8 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -30,6 +30,7 @@ #include #include +#include #include #include From 568c8ea7158d3f94793f27768afbd639558a932f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 11:39:19 +0000 Subject: [PATCH 1215/1514] Fix typo. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1315 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index d4fa121b8..1222d4af5 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -565,7 +565,7 @@ int pa__init(pa_core *c, pa_module*m) { } u->silence.length = u->fragment_size; - u->silence.memblock = pa_memblock_new(u->core->mem, u->silence.length); + u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length); assert(u->silence.memblock); pa_silence_memblock(u->silence.memblock, &ss); u->silence.index = 0; From 10bbc4b7c9e6aed6e0b281eaf23b8192e53233d7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 11:41:14 +0000 Subject: [PATCH 1216/1514] Fix detection of shared memory support and proper fallback. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1316 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 13 ++++--------- src/modules/module-oss-mmap.c | 3 +++ src/pulsecore/shm.c | 25 ++++++++++++++++++++++++- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 4aba536d4..cb9ca2efd 100644 --- a/configure.ac +++ b/configure.ac @@ -144,7 +144,7 @@ AC_HEADER_STDC # POSIX AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \ netinet/in_systm.h netinet/ip.h netinet/tcp.h pwd.h sched.h \ - sys/resource.h sys/select.h sys/socket.h sys/wait.h \ + sys/mman.h sys/resource.h sys/select.h sys/socket.h sys/wait.h \ syslog.h]) AC_CHECK_HEADERS([regex.h], [HAVE_REGEX=1], [HAVE_REGEX=0]) AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0]) @@ -202,12 +202,11 @@ AC_SEARCH_LIBS([pow], [m]) # POSIX AC_SEARCH_LIBS([sched_setscheduler], [rt]) AC_SEARCH_LIBS([dlopen], [dl]) +AC_SEARCH_LIBS([shm_open], [rt]) # BSD AC_SEARCH_LIBS([connect], [socket]) -AC_SEARCH_LIBS([shm_open], [rt]) - # Non-standard # This magic is needed so we do not needlessly add static libs to the win32 @@ -221,8 +220,8 @@ AC_FUNC_FORK AC_FUNC_GETGROUPS AC_FUNC_SELECT_ARGTYPES AC_CHECK_FUNCS([chmod chown getaddrinfo getgrgid_r getpwuid_r gettimeofday \ - getuid inet_ntop inet_pton nanosleep pipe setpgid setsid sigaction sleep \ - sysconf]) + getuid inet_ntop inet_pton nanosleep pipe posix_memalignsetpgid setsid \ + shm_open sigaction sleep sysconf]) AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0]) AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1") @@ -243,10 +242,6 @@ AC_CHECK_FUNCS([lstat]) AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid]) -# Memory mangement - -AC_CHECK_FUNCS([mmap posix_memalign madvise]) - #### POSIX threads #### ACX_PTHREAD diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 0be6bbe22..5ab082878 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -34,7 +34,10 @@ #include #include #include + +#ifdef HAVE_SYS_MMAN_H #include +#endif #include #include diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index 02528126c..7c10bd0af 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -27,12 +27,15 @@ #include #include #include -#include #include #include #include #include +#ifdef HAVE_SYS_MMAN_H +#include +#endif + #include #include #include @@ -51,6 +54,8 @@ static char *segment_name(char *fn, size_t l, unsigned id) { return fn; } +#ifdef HAVE_SHM_OPEN + int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { char fn[32]; int fd = -1; @@ -239,3 +244,21 @@ fail: return -1; } + +#else /* HAVE_SHM_OPEN */ + +int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { + return -1; +} + +void pa_shm_free(pa_shm *m) { +} + +void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { +} + +int pa_shm_attach_ro(pa_shm *m, unsigned id) { + return -1; +} + +#endif /* HAVE_SHM_OPEN */ From 22d8e0e75e05f8c414df17e4dedfb310397483ea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 Aug 2006 12:04:55 +0000 Subject: [PATCH 1217/1514] fix typo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1317 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cb9ca2efd..c337930b3 100644 --- a/configure.ac +++ b/configure.ac @@ -220,7 +220,7 @@ AC_FUNC_FORK AC_FUNC_GETGROUPS AC_FUNC_SELECT_ARGTYPES AC_CHECK_FUNCS([chmod chown getaddrinfo getgrgid_r getpwuid_r gettimeofday \ - getuid inet_ntop inet_pton nanosleep pipe posix_memalignsetpgid setsid \ + getuid inet_ntop inet_pton nanosleep pipe posix_memalign setpgid setsid \ shm_open sigaction sleep sysconf]) AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0]) From fef4a2059915dc30711be1f6d514ef3cce61bcc4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 Aug 2006 12:29:41 +0000 Subject: [PATCH 1218/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1318 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 + 1 file changed, 1 insertion(+) diff --git a/todo b/todo index befa5ee95..6d263c2b6 100644 --- a/todo +++ b/todo @@ -50,6 +50,7 @@ Features: that time) - Support for device selection in waveout driver - add an API to libpulse for allocating memory from the pa_context memory pool +- allow buffer metric changes during runtime Long term: - pass meta info for hearing impaired From cf7b401ac61f7dd3b30adba2660a3ea4059f4677 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 12:45:43 +0000 Subject: [PATCH 1219/1514] Fix up portability of memory pool handling a bit. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1319 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/shm.c | 80 +++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index 7c10bd0af..806a0320b 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -54,8 +54,6 @@ static char *segment_name(char *fn, size_t l, unsigned id) { return fn; } -#ifdef HAVE_SHM_OPEN - int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { char fn[32]; int fd = -1; @@ -90,9 +88,10 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { m->do_unlink = 0; } else { +#ifdef HAVE_SHM_OPEN pa_random(&m->id, sizeof(m->id)); segment_name(fn, sizeof(fn), m->id); - + if ((fd = shm_open(fn, O_RDWR|O_CREAT|O_EXCL, mode & 0444)) < 0) { pa_log("shm_open() failed: %s", pa_cstrerror(errno)); goto fail; @@ -110,6 +109,9 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { close(fd); m->do_unlink = 1; +#else + return -1; +#endif } m->shared = shared; @@ -118,40 +120,52 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { fail: +#ifdef HAVE_SHM_OPEN if (fd >= 0) { shm_unlink(fn); close(fd); } +#endif return -1; } void pa_shm_free(pa_shm *m) { - char fn[32]; - assert(m); - assert(m->ptr && m->ptr != MAP_FAILED); + assert(m->ptr); assert(m->size > 0); -#if !defined(MAP_ANONYMOUS) && defined(HAVE_POSIX_MEMALIGN) - if (!m->shared) - free(m->ptr); - else -#elif !defined(MAP_ANONYMOUS) - if (!m->shared) - pa_xfree(m->ptr); - else -#endif - - if (munmap(m->ptr, m->size) < 0) - pa_log("munmap() failed: %s", pa_cstrerror(errno)); +#ifdef MAP_FAILED + assert(m->ptr != MAP_FAILED); +#endif - if (m->do_unlink) { - segment_name(fn, sizeof(fn), m->id); - - if (shm_unlink(fn) < 0) - pa_log(__FILE__":shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno)); - } + if (!m->shared) { +#ifdef MAP_ANONYMOUS + if (munmap(m->ptr, m->size) < 0) + pa_log("munmap() failed: %s", pa_cstrerror(errno)); +#elif defined(HAVE_POSIX_MEMALIGN) + free(m->ptr); +#else + pa_xfree(m->ptr); +#endif + } else { +#ifdef HAVE_SHM_OPEN + if (munmap(m->ptr, m->size) < 0) + pa_log("munmap() failed: %s", pa_cstrerror(errno)); + + if (m->do_unlink) { + char fn[32]; + + segment_name(fn, sizeof(fn), m->id); + + if (shm_unlink(fn) < 0) + pa_log(__FILE__":shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno)); + } +#else + /* We shouldn't be here without shm support */ + assert(0); +#endif + } memset(m, 0, sizeof(*m)); } @@ -160,11 +174,15 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { void *ptr; assert(m); - assert(m->ptr && m->ptr != MAP_FAILED); + assert(m->ptr); assert(m->size > 0); assert(offset < m->size); assert(offset+size < m->size); +#ifdef MAP_FAILED + assert(m->ptr != MAP_FAILED); +#endif + /* You're welcome to implement this as NOOP on systems that don't * support it */ @@ -200,6 +218,8 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { #endif } +#ifdef HAVE_SHM_OPEN + int pa_shm_attach_ro(pa_shm *m, unsigned id) { char fn[32]; int fd = -1; @@ -247,16 +267,6 @@ fail: #else /* HAVE_SHM_OPEN */ -int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { - return -1; -} - -void pa_shm_free(pa_shm *m) { -} - -void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { -} - int pa_shm_attach_ro(pa_shm *m, unsigned id) { return -1; } From 26bfce6281f475d04f122dee6a711c7c00496614 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 12:46:05 +0000 Subject: [PATCH 1220/1514] Improve error messages a bit. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1320 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 4 +++- src/pulsecore/core-util.c | 2 +- src/pulsecore/core.c | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 8b816b9a5..5d77282c7 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -559,8 +559,10 @@ int main(int argc, char *argv[]) { mainloop = pa_mainloop_new(); assert(mainloop); - if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) + if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) { + pa_log("pa_core_new() failed."); goto finish; + } c->is_system_instance = !!conf->system_instance; diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index b504b6d34..5f72b3428 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -184,7 +184,7 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { goto fail; } #else - fprintf(stderr, "FIXME: pa_make_secure_dir()\n"); + pa_log_warn("secure directory creation not supported on Win32."); #endif return 0; diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index c36a35bd9..1a7382e50 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "core.h" @@ -48,8 +49,10 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { pa_core* c; pa_mempool *pool; - if (!(pool = pa_mempool_new(shared))) + if (!(pool = pa_mempool_new(shared))) { + pa_log("pa_mempool_new() failed."); return NULL; + } c = pa_xnew(pa_core, 1); From 7bf25407789a99eec9d77ec8b9f9ece8abe49589 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 12:51:29 +0000 Subject: [PATCH 1221/1514] Fall back to creating a "normal" memory pool if unable to get a shared one. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1321 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 1a7382e50..3b6434d77 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -49,11 +49,20 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { pa_core* c; pa_mempool *pool; - if (!(pool = pa_mempool_new(shared))) { - pa_log("pa_mempool_new() failed."); - return NULL; + if (shared) { + if (!(pool = pa_mempool_new(shared))) { + pa_log_warn("failed to allocate shared memory pool. Falling back to a normal memory pool."); + shared = 0; + } + } + + if (!shared) { + if (!(pool = pa_mempool_new(shared))) { + pa_log("pa_mempool_new() failed."); + return NULL; + } } - + c = pa_xnew(pa_core, 1); c->mainloop = m; From 0249651c8e46f2133f159baae1eac52e8b5a5e2f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 15:20:57 +0000 Subject: [PATCH 1222/1514] Log when there is a problem opening the waveOut/waveIn device. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1322 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 1222d4af5..9c867fdb8 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -481,16 +481,22 @@ int pa__init(pa_core *c, pa_module*m) { u = pa_xmalloc(sizeof(struct userdata)); if (record) { - if (waveInOpen(&hwi, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_ready_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) + if (waveInOpen(&hwi, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_ready_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { + pa_log("failed to open waveIn"); goto fail; - if (waveInStart(hwi) != MMSYSERR_NOERROR) + } + if (waveInStart(hwi) != MMSYSERR_NOERROR) { + pa_log("failed to start waveIn"); goto fail; + } pa_log_debug("Opened waveIn subsystem."); } if (playback) { - if (waveOutOpen(&hwo, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) + if (waveOutOpen(&hwo, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { + pa_log("failed to open waveOut"); goto fail; + } pa_log_debug("Opened waveOut subsystem."); } From 306aea78d35486596627bcbbcb566d5f19bb9e21 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 15:24:11 +0000 Subject: [PATCH 1223/1514] Fix memory leak in waveout module. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1323 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 9c867fdb8..f1861466e 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -611,6 +611,9 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; + + if (u->silence.memblock) + pa_memblock_unref(u->silence.memblock); if (u->event) c->mainloop->time_free(u->event); From 095f35725d644e0284c4b2d99b6fab71290eaeaa Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 15:36:37 +0000 Subject: [PATCH 1224/1514] Proceed with connect even when no cookie is loaded. Allows you to connect to server which do not require a cookie under all circumstances. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1324 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index 2f9106a5c..b700657b4 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -434,10 +434,8 @@ static void setup_context(pa_context *c, pa_iochannel *io) { assert(!c->pdispatch); c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); - if (!c->conf->cookie_valid) { - pa_context_fail(c, PA_ERR_AUTHKEY); - goto finish; - } + if (!c->conf->cookie_valid) + pa_log_warn("No cookie loaded. Attempting to connect without."); t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); @@ -463,8 +461,6 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); -finish: - pa_context_unref(c); } From d194604402648fbab61bde3d1106fecb1b82dc83 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 16:15:47 +0000 Subject: [PATCH 1225/1514] Remove silence generation in waveout module. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1325 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 85 +++++++++++++++--------------------- 1 file changed, 34 insertions(+), 51 deletions(-) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index f1861466e..4043c1364 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -75,11 +75,10 @@ struct userdata { uint32_t free_ofrags, free_ifrags; DWORD written_bytes; + int sink_underflow; int cur_ohdr, cur_ihdr; - unsigned int oremain; WAVEHDR *ohdrs, *ihdrs; - pa_memchunk silence; HWAVEOUT hwo; HWAVEIN hwi; @@ -110,8 +109,8 @@ static void update_usage(struct userdata *u) { static void do_write(struct userdata *u) { - uint32_t free_frags, remain; - pa_memchunk memchunk, *cur_chunk; + uint32_t free_frags; + pa_memchunk memchunk; WAVEHDR *hdr; MMRESULT res; @@ -119,13 +118,10 @@ static void do_write(struct userdata *u) return; EnterCriticalSection(&u->crit); - free_frags = u->free_ofrags; - u->free_ofrags = 0; - LeaveCriticalSection(&u->crit); - if (free_frags == u->fragments) + if (!u->sink_underflow && (free_frags == u->fragments)) pa_log_debug("WaveOut underflow!"); while (free_frags) { @@ -133,45 +129,39 @@ static void do_write(struct userdata *u) if (hdr->dwFlags & WHDR_PREPARED) waveOutUnprepareHeader(u->hwo, hdr, sizeof(WAVEHDR)); - remain = u->oremain; - while (remain) { - cur_chunk = &memchunk; + hdr->dwBufferLength = 0; + while (hdr->dwBufferLength < u->fragment_size) { + size_t len; - if (pa_sink_render(u->sink, remain, cur_chunk) < 0) { - /* - * Don't fill with silence unless we're getting close to - * underflowing. - */ - if (free_frags > u->fragments/2) - cur_chunk = &u->silence; - else { - EnterCriticalSection(&u->crit); + len = u->fragment_size - hdr->dwBufferLength; - u->free_ofrags += free_frags; + if (pa_sink_render(u->sink, len, &memchunk) < 0) + break; - LeaveCriticalSection(&u->crit); + assert(memchunk.memblock); + assert(memchunk.memblock->data); + assert(memchunk.length); - u->oremain = remain; - return; - } - } + if (memchunk.length < len) + len = memchunk.length; - assert(cur_chunk->memblock); - assert(cur_chunk->memblock->data); - assert(cur_chunk->length); + memcpy(hdr->lpData + hdr->dwBufferLength, + (char*)memchunk.memblock->data + memchunk.index, len); - memcpy(hdr->lpData + u->fragment_size - remain, - (char*)cur_chunk->memblock->data + cur_chunk->index, - (cur_chunk->length < remain)?cur_chunk->length:remain); + hdr->dwBufferLength += len; - remain -= (cur_chunk->length < remain)?cur_chunk->length:remain; - - if (cur_chunk != &u->silence) { - pa_memblock_unref(cur_chunk->memblock); - cur_chunk->memblock = NULL; - } + pa_memblock_unref(memchunk.memblock); + memchunk.memblock = NULL; } + /* Insufficient data in sink buffer? */ + if (hdr->dwBufferLength == 0) { + u->sink_underflow = 1; + break; + } + + u->sink_underflow = 0; + res = waveOutPrepareHeader(u->hwo, hdr, sizeof(WAVEHDR)); if (res != MMSYSERR_NOERROR) { pa_log_error(__FILE__ ": ERROR: Unable to prepare waveOut block: %d", @@ -183,12 +173,15 @@ static void do_write(struct userdata *u) res); } - u->written_bytes += u->fragment_size; + u->written_bytes += hdr->dwBufferLength; + + EnterCriticalSection(&u->crit); + u->free_ofrags--; + LeaveCriticalSection(&u->crit); free_frags--; u->cur_ohdr++; u->cur_ohdr %= u->fragments; - u->oremain = u->fragment_size; } } @@ -540,8 +533,7 @@ int pa__init(pa_core *c, pa_module*m) { u->fragment_size = frag_size - (frag_size % pa_frame_size(&ss)); u->written_bytes = 0; - - u->oremain = u->fragment_size; + u->sink_underflow = 1; u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 10, &ss); @@ -570,12 +562,6 @@ int pa__init(pa_core *c, pa_module*m) { assert(u->ohdrs); } - u->silence.length = u->fragment_size; - u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length); - assert(u->silence.memblock); - pa_silence_memblock(u->silence.memblock, &ss); - u->silence.index = 0; - u->module = m; m->userdata = u; @@ -611,9 +597,6 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; - - if (u->silence.memblock) - pa_memblock_unref(u->silence.memblock); if (u->event) c->mainloop->time_free(u->event); From b27ffbec8c815d0efa936063482b9bf0bc312103 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 16:25:47 +0000 Subject: [PATCH 1226/1514] Remove silence generation in solaris module. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1326 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 57 +++++++++++++++++------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 8eaf6758e..90cf010bf 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -80,11 +80,12 @@ struct userdata { pa_usec_t poll_timeout; pa_signal_event *sig; - pa_memchunk memchunk, silence; + pa_memchunk memchunk; uint32_t frame_size; uint32_t buffer_size; unsigned int written_bytes, read_bytes; + int sink_underflow; int fd; pa_module *module; @@ -119,7 +120,6 @@ static void update_usage(struct userdata *u) { static void do_write(struct userdata *u) { audio_info_t info; int err; - pa_memchunk *memchunk; size_t len; ssize_t r; @@ -145,7 +145,7 @@ static void do_write(struct userdata *u) { if (len > u->buffer_size) len = 0; - if (len == u->buffer_size) + if (!u->sink_underflow && (len == u->buffer_size)) pa_log_debug("Solaris buffer underflow!"); len -= len % u->frame_size; @@ -153,37 +153,39 @@ static void do_write(struct userdata *u) { if (len == 0) return; - memchunk = &u->memchunk; - - if (!memchunk->length) - if (pa_sink_render(u->sink, len, memchunk) < 0) - memchunk = &u->silence; - - assert(memchunk->memblock); - assert(memchunk->memblock->data); - assert(memchunk->length); + if (!u->memchunk.length) { + if (pa_sink_render(u->sink, len, &u->memchunk) < 0) { + u->sink_underflow = 1; + return; + } + } - if (memchunk->length < len) { - len = memchunk->length; + u->sink_underflow = 0; + + assert(u->memchunk.memblock); + assert(u->memchunk.memblock->data); + assert(u->memchunk.length); + + if (u->memchunk.length < len) { + len = u->memchunk.length; len -= len % u->frame_size; assert(len); } - if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, len)) < 0) { + if ((r = pa_iochannel_write(u->io, + (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, len)) < 0) { pa_log("write() failed: %s", pa_cstrerror(errno)); return; } assert(r % u->frame_size == 0); - if (memchunk != &u->silence) { - u->memchunk.index += r; - u->memchunk.length -= r; - - if (u->memchunk.length <= 0) { - pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; - } + u->memchunk.index += r; + u->memchunk.length -= r; + + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; } u->written_bytes += r; @@ -590,14 +592,11 @@ int pa__init(pa_core *c, pa_module*m) { u->frame_size = pa_frame_size(&ss); u->buffer_size = buffer_size; - u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length = CHUNK_SIZE); - assert(u->silence.memblock); - pa_silence_memblock(u->silence.memblock, &ss); - u->silence.index = 0; - u->written_bytes = 0; u->read_bytes = 0; + u->sink_underflow = 1; + u->module = m; m->userdata = u; @@ -649,8 +648,6 @@ void pa__done(pa_core *c, pa_module*m) { if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); - if (u->silence.memblock) - pa_memblock_unref(u->silence.memblock); if (u->sink) { pa_sink_disconnect(u->sink); From 79c4a6842c7e67a9e39d951d8ac2beab98100ae4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 23 Aug 2006 07:57:43 +0000 Subject: [PATCH 1227/1514] Make the recording a bit more chunky so that we can fit in the pool and have efficient blocks. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1327 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-solaris.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 90cf010bf..66968cb1a 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -82,6 +82,8 @@ struct userdata { pa_memchunk memchunk; + unsigned int page_size; + uint32_t frame_size; uint32_t buffer_size; unsigned int written_bytes, read_bytes; @@ -193,7 +195,8 @@ static void do_write(struct userdata *u) { static void do_read(struct userdata *u) { pa_memchunk memchunk; - int err, l; + int err; + size_t l; ssize_t r; assert(u); @@ -205,6 +208,11 @@ static void do_read(struct userdata *u) { err = ioctl(u->fd, I_NREAD, &l); assert(err >= 0); + /* This is to make sure it fits in the memory pool. Also, a page + should be the most efficient transfer size. */ + if (l > u->page_size) + l = u->page_size; + memchunk.memblock = pa_memblock_new(u->core->mempool, l); assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { @@ -589,6 +597,10 @@ int pa__init(pa_core *c, pa_module*m) { u->memchunk.memblock = NULL; u->memchunk.length = 0; + + /* We use this to get a reasonable chunk size */ + u->page_size = sysconf(_SC_PAGESIZE); + u->frame_size = pa_frame_size(&ss); u->buffer_size = buffer_size; From 2575b446372b249fddb2cc792c089985901de7f2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 23 Aug 2006 07:58:07 +0000 Subject: [PATCH 1228/1514] fix typo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1328 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/memblock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 9e5c5b81d..286f7b5a4 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -246,7 +246,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { b->type = PA_MEMBLOCK_POOL_EXTERNAL; b->data = mempool_slot_data(slot); } else { - pa_log_debug("Memory block to large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot)); + pa_log_debug("Memory block too large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot)); p->stat.n_too_large_for_pool++; return NULL; } From 8f5b86b77d75b9e4287942c30d3b5d4c42b8afb2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 Aug 2006 22:28:53 +0000 Subject: [PATCH 1229/1514] fix handling of "mtu" module argument (patch by "theBear") git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1329 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/module-rtp-send.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 61dd00472..7bbfabee7 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -81,6 +81,7 @@ static const char* const valid_modargs[] = { "rate", "destination", "port", + "mtu" , "loop", NULL }; From aec3888ef2deb1dba51922fcf149115acea6476b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 24 Aug 2006 08:57:35 +0000 Subject: [PATCH 1230/1514] Add missing header. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1330 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/interpol-test.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c index 2df65a455..3ec8a18f7 100644 --- a/src/tests/interpol-test.c +++ b/src/tests/interpol-test.c @@ -37,6 +37,10 @@ #include #endif +#ifdef HAVE_WINDOWS_H +#include +#endif + #include #include From 8ead68fcb3fb7da981a42f4b502bdeabf96a62fb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 25 Aug 2006 12:12:13 +0000 Subject: [PATCH 1231/1514] activate HAL in the default config git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1331 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/default.pa.in | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index 74148cd19..031226693 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -27,7 +27,11 @@ #load-module module-pipe-sink ### Automatically load driver modules depending on the hardware available -load-module module-detect +load-module module-hal-detect + +### Alternatively use the static hardware detection module (for systems that +### lack HAL support +#load-module module-detect ### Load audio drivers automatically on access #add-autoload-sink output module-oss device="/dev/dsp" sink_name=output source_name=input @@ -41,21 +45,24 @@ load-module module-detect load-module module-esound-protocol-unix load-module module-native-protocol-unix +### Network access (may be configured with paprefs, so leave this commented +### here if you plan to use paprefs) #load-module module-esound-protocol-tcp #load-module module-native-protocol-tcp #load-module module-zeroconf-publish -### Load the RTP reciever module +### Load the RTP reciever module (also configured via paprefs, see above) #load-module module-rtp-recv -### Load the RTP sender module -#load-module module-null-sink sink_name=rtp -#load-module module-rtp-send source=rtp_monitor +### Load the RTP sender module (also configured via paprefs, see above) +#load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 description="RTP Multicast Sink" +#load-module module-rtp-send source=rtp.monitor ### Automatically restore the volume of playback streams load-module module-volume-restore -### Automatically move streams to the default sink if the sink they are connected to dies +### Automatically move streams to the default sink if the sink they are +### connected to dies, similar for sources load-module module-rescue-streams ### Make some devices default From 93e005ad3767eb08cb9542b4bc50f8fab81f5c07 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 25 Aug 2006 22:52:59 +0000 Subject: [PATCH 1232/1514] update module-tunnel to latest protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1332 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 67 ++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index de1a12c90..18c289a83 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -79,9 +79,6 @@ PA_MODULE_USAGE( PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_VERSION(PACKAGE_VERSION) -#define DEFAULT_SINK_NAME "tunnel" -#define DEFAULT_SOURCE_NAME "tunnel" - #define DEFAULT_TLENGTH (44100*2*2/10) //(10240*8) #define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) #define DEFAULT_MINREQ 512 @@ -503,15 +500,33 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN } if (pa_tagstruct_getu32(t, &u->channel) < 0 || - pa_tagstruct_getu32(t, &u->device_index) < 0 || + pa_tagstruct_getu32(t, &u->device_index) < 0 #ifdef TUNNEL_SINK - pa_tagstruct_getu32(t, &u->requested_bytes) < 0 || + || pa_tagstruct_getu32(t, &u->requested_bytes) < 0 #endif - !pa_tagstruct_eof(t)) { - pa_log("invalid reply. (create stream)"); - die(u); - return; + ) + goto parse_error; + + if (u->version >= 9) { +#ifdef TUNNEL_SINK + uint32_t maxlength, tlength, prebuf, minreq; + + if (pa_tagstruct_getu32(t, &maxlength) < 0 || + pa_tagstruct_getu32(t, &tlength) < 0 || + pa_tagstruct_getu32(t, &prebuf) < 0 || + pa_tagstruct_getu32(t, &minreq) < 0) + goto parse_error; +#else + uint32_t maxlength, fragsize; + + if (pa_tagstruct_getu32(t, &maxlength) < 0 || + pa_tagstruct_getu32(t, &fragsize) < 0) + goto parse_error; +#endif } + + if (!pa_tagstruct_eof(t)) + goto parse_error; start_subscribe(u); request_info(u); @@ -520,6 +535,12 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN #ifdef TUNNEL_SINK send_bytes(u); #endif + + return; + +parse_error: + pa_log("invalid reply. (create stream)"); + die(u); } static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -550,12 +571,12 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t } #ifdef TUNNEL_SINK - snprintf(name, sizeof(name), "Tunnel from host '%s', user '%s', sink '%s'", + snprintf(name, sizeof(name), "Tunnel from host %s, user %s, sink %s", pa_get_host_name(hn, sizeof(hn)), pa_get_user_name(un, sizeof(un)), u->sink->name); #else - snprintf(name, sizeof(name), "Tunnel from host '%s', user '%s', source '%s'", + snprintf(name, sizeof(name), "Tunnel from host %s, user %s, source %s", pa_get_host_name(hn, sizeof(hn)), pa_get_user_name(un, sizeof(un)), u->source->name); @@ -859,7 +880,8 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_channel_map map; struct timeval ntv; - char *t; + char *t, *dn = NULL; + assert(c && m); @@ -915,7 +937,11 @@ int pa__init(pa_core *c, pa_module*m) { pa_socket_client_set_callback(u->client, on_connection, u); #ifdef TUNNEL_SINK - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { + + if (!(dn = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL)))) + dn = pa_sprintf_malloc("tunnel.%s", u->server_name); + + if (!(u->sink = pa_sink_new(c, __FILE__, dn, 0, &ss, &map))) { pa_log("failed to create sink."); goto fail; } @@ -927,12 +953,16 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_hw_mute = sink_get_hw_mute; u->sink->set_hw_mute = sink_set_hw_mute; u->sink->userdata = u; - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->sink_name ? u->sink_name : "", u->sink_name ? "@" : "", u->server_name)); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Tunnel to %s%s%s", u->sink_name ? u->sink_name : "", u->sink_name ? " on " : "", u->server_name)); pa_xfree(t); pa_sink_set_owner(u->sink, m); #else - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { + + if (!(dn = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL)))) + dn = pa_sprintf_malloc("tunnel.%s", u->server_name); + + if (!(u->source = pa_source_new(c, __FILE__, dn, 0, &ss, &map))) { pa_log("failed to create source."); goto fail; } @@ -944,12 +974,14 @@ int pa__init(pa_core *c, pa_module*m) { u->source->set_hw_mute = source_set_hw_mute; u->source->userdata = u; - pa_source_set_description(u->source, t = pa_sprintf_malloc("Tunnel to '%s%s%s'", u->source_name ? u->source_name : "", u->source_name ? "@" : "", u->server_name)); + pa_source_set_description(u->source, t = pa_sprintf_malloc("Tunnel to %s%s%s", u->source_name ? u->source_name : "", u->source_name ? " on " : "", u->server_name)); pa_xfree(t); pa_source_set_owner(u->source, m); #endif + pa_xfree(dn); + pa_gettimeofday(&ntv); ntv.tv_sec += LATENCY_INTERVAL; u->time_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, u); @@ -963,6 +995,9 @@ fail: if (ma) pa_modargs_free(ma); + + pa_xfree(dn); + return -1; } From b8ea488b7654f447fff49811129001334b2db3fa Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 26 Aug 2006 19:00:22 +0000 Subject: [PATCH 1233/1514] fix module-combine when used on top of a tunnel sink git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1333 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-combine.c | 17 +++++++++++++++-- src/modules/module-tunnel.c | 10 +++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 217fdae62..f3bb3fd3a 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -217,6 +217,18 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { pa_sink_get_latency(u->master->sink_input->sink); } +static void sink_notify(pa_sink *s) { + struct userdata *u; + struct output *o; + + assert(s); + u = s->userdata; + assert(u); + + for (o = u->outputs; o; o = o->next) + pa_sink_notify(o->sink_input->sink); +} + static struct output *output_new(struct userdata *u, pa_sink *sink, int resample_method) { struct output *o = NULL; char t[256]; @@ -237,7 +249,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample 0, NULL); - snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1); + snprintf(t, sizeof(t), "Output stream #%u of sink %s", u->n_outputs+1, u->sink->name); pa_sink_input_new_data_init(&data); data.sink = sink; @@ -387,8 +399,9 @@ int pa__init(pa_core *c, pa_module*m) { } pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, "Combined sink"); + pa_sink_set_description(u->sink, "Combined Sink"); u->sink->get_latency = sink_get_latency_cb; + u->sink->notify = sink_notify; u->sink->userdata = u; if (!(u->master = output_new(u, master_sink, resample_method))) { diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 18c289a83..18e1d97db 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -266,6 +266,8 @@ static void send_bytes(struct userdata *u) { pa_pstream_send_memblock(u->pstream, u->channel, 0, PA_SEEK_RELATIVE, &chunk); pa_memblock_unref(chunk.memblock); +/* pa_log("sent %lu", (unsigned long) chunk.length); */ + if (chunk.length > u->requested_bytes) u->requested_bytes = 0; else @@ -330,6 +332,8 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G pa_gettimeofday(&now); + /* FIXME! This could use some serious love. */ + if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) { /* local and remote seem to have synchronized clocks */ #ifdef TUNNEL_SINK @@ -350,7 +354,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G u->host_latency = 0; #endif -/* pa_log("estimated host latency: %0.0f usec", (double) u->host_latency); */ +/* pa_log("estimated host latency: %0.0f usec", (double) u->host_latency); */ } static void request_latency(struct userdata *u) { @@ -631,7 +635,6 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { die(u); } - static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { struct userdata *u = userdata; assert(p && packet && u); @@ -772,6 +775,7 @@ static int sink_set_hw_mute(pa_sink *sink) { return 0; } + #else static pa_usec_t source_get_latency(pa_source *source) { struct userdata *u; @@ -946,12 +950,12 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - u->sink->notify = sink_notify; u->sink->get_latency = sink_get_latency; u->sink->get_hw_volume = sink_get_hw_volume; u->sink->set_hw_volume = sink_set_hw_volume; u->sink->get_hw_mute = sink_get_hw_mute; u->sink->set_hw_mute = sink_set_hw_mute; + u->sink->notify = sink_notify; u->sink->userdata = u; pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Tunnel to %s%s%s", u->sink_name ? u->sink_name : "", u->sink_name ? " on " : "", u->server_name)); pa_xfree(t); From bc87a5869dc80ea2faed9c0ebc9f97a2e40ce2dd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 26 Aug 2006 19:22:14 +0000 Subject: [PATCH 1234/1514] bump version and sonames git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1334 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index c337930b3..33b305e7d 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_PREREQ(2.57) m4_define(PA_MAJOR, [0]) m4_define(PA_MINOR, [9]) -m4_define(PA_MICRO, [4]) +m4_define(PA_MICRO, [5]) AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) @@ -36,11 +36,11 @@ AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/]) AC_SUBST(PA_API_VERSION, 10) AC_SUBST(PA_PROTOCOL_VERSION, 10) -AC_SUBST(LIBPULSE_VERSION_INFO, [0:2:0]) -AC_SUBST(LIBPULSECORE_VERSION_INFO, [1:1:0]) +AC_SUBST(LIBPULSE_VERSION_INFO, [1:0:1]) +AC_SUBST(LIBPULSECORE_VERSION_INFO, [2:0:0]) AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:0:0]) AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:0:1]) -AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:1:0]) +AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:2:0]) if type -p stow > /dev/null && test -d /usr/local/stow ; then AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) From 1ed33478e531eba112dd421cbcaa42202d314135 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 27 Aug 2006 13:04:56 +0000 Subject: [PATCH 1235/1514] increase operation timeout git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1336 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulse/internal.h b/src/pulse/internal.h index fa7d5bbd4..4eef4b4ad 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -41,7 +41,7 @@ #include "client-conf.h" -#define DEFAULT_TIMEOUT (10) +#define DEFAULT_TIMEOUT (30) struct pa_context { int ref; From cd4767305cc73a019564754430af470da3882553 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 28 Aug 2006 05:15:46 +0000 Subject: [PATCH 1236/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1337 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 + 1 file changed, 1 insertion(+) diff --git a/todo b/todo index 6d263c2b6..34935c6f8 100644 --- a/todo +++ b/todo @@ -51,6 +51,7 @@ Features: - Support for device selection in waveout driver - add an API to libpulse for allocating memory from the pa_context memory pool - allow buffer metric changes during runtime +- "include" command in configuration files. should have glob support. Long term: - pass meta info for hearing impaired From 5ecbd9edeead63b7ac694b728bb8dda5811438f8 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 28 Aug 2006 06:25:41 +0000 Subject: [PATCH 1237/1514] Add PulseAudio logo to tree. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1338 fefdeb5f-60dc-0310-8127-8f9354f1896f --- pulseaudio.svg | 287 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 pulseaudio.svg diff --git a/pulseaudio.svg b/pulseaudio.svg new file mode 100644 index 000000000..a79e03daf --- /dev/null +++ b/pulseaudio.svg @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + PulseAudio logotype + 2006-08-28 + + + Pierre Ossman <ossman@cendio.se> for Cendio AB + + + + + + + + + + Rafael Jannone (basic idea) + + + + + + + + + + + + + + + + + + + + + + + + + + + + From a6339448202d01a922934dd85d0efa851f81dd3d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 28 Aug 2006 19:16:00 +0000 Subject: [PATCH 1238/1514] fix an misdesigned assert() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1339 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/shm.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index 806a0320b..19731b5f3 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -156,10 +156,10 @@ void pa_shm_free(pa_shm *m) { if (m->do_unlink) { char fn[32]; - segment_name(fn, sizeof(fn), m->id); - - if (shm_unlink(fn) < 0) - pa_log(__FILE__":shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno)); + segment_name(fn, sizeof(fn), m->id); + + if (shm_unlink(fn) < 0) + pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno)); } #else /* We shouldn't be here without shm support */ @@ -176,8 +176,7 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { assert(m); assert(m->ptr); assert(m->size > 0); - assert(offset < m->size); - assert(offset+size < m->size); + assert(offset+size <= m->size); #ifdef MAP_FAILED assert(m->ptr != MAP_FAILED); From 91d802582362e0d81f291cd4955b278a85528e51 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Aug 2006 01:15:09 +0000 Subject: [PATCH 1239/1514] add libatomic-ops to hard dependencies git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1340 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/configure.ac b/configure.ac index 33b305e7d..42bee9a85 100644 --- a/configure.ac +++ b/configure.ac @@ -320,6 +320,18 @@ PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ]) AC_SUBST(LIBSNDFILE_CFLAGS) AC_SUBST(LIBSNDFILE_LIBS) +#### atomic-ops ### + +AC_CHECK_HEADERS([atomic_ops.h], [], [ +AC_MSG_ERROR([*** libatomic-ops headers not found]) +]) + +AC_SEARCH_LIBS([AO_spin], [atomic_ops], [], [ +AC_MSG_ERROR([*** libatomic-ops library file not found]) +]) + + + #### OSS support (optional) #### AC_ARG_ENABLE([oss], From 9948cb09a3e1b976ad1705df06ef24216a61bf85 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Aug 2006 01:15:51 +0000 Subject: [PATCH 1240/1514] add lock-free reference counting macros, based on libatomic-ops git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1341 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 +++- src/pulsecore/refcnt.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/pulsecore/refcnt.h diff --git a/src/Makefile.am b/src/Makefile.am index c4988d8e8..c9942cffd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -527,7 +527,9 @@ pulsecoreinclude_HEADERS = \ pulsecore/strbuf.h \ pulsecore/tokenizer.h \ pulsecore/creds.h \ - pulsecore/shm.h + pulsecore/shm.h \ + pulsecore/llist.h \ + pulsecore/refcnt.h lib_LTLIBRARIES += libpulsecore.la diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h new file mode 100644 index 000000000..fade9aa47 --- /dev/null +++ b/src/pulsecore/refcnt.h @@ -0,0 +1,41 @@ +#ifndef foopulserefcntfoo +#define foopulserefcntfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#define PA_REFCNT_DECLARE volatile AO_t _ref + +#define PA_REFCNT_INIT(p) \ + AO_store_release_write(&(p)->_ref, 1) + +#define PA_REFCNT_INC(p) \ + AO_fetch_and_add1_release_write(&(p)->_ref) + +#define PA_REFCNT_DEC(p) \ + (AO_fetch_and_sub1_release_write(&(p)->_ref)-1) + +#define PA_REFCNT_VALUE(p) \ + AO_load_acquire_read(&(p)->_ref) + +#endif From 327e0cd8e1e81999dd855e38d3cb3b414aeadc7a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Aug 2006 01:16:47 +0000 Subject: [PATCH 1241/1514] modify memory block reference counting to use the new reference counting API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1342 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/memblock.c | 24 ++++++++++++------------ src/pulsecore/memblock.h | 3 ++- src/pulsecore/memchunk.c | 6 ++++-- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 286f7b5a4..516ade133 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -170,7 +170,7 @@ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) { b = pa_xmalloc(sizeof(pa_memblock) + length); b->type = PA_MEMBLOCK_APPENDED; b->read_only = 0; - b->ref = 1; + PA_REFCNT_INIT(b); b->length = length; b->data = (uint8_t*) b + sizeof(pa_memblock); b->pool = p; @@ -253,7 +253,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { b->length = length; b->read_only = 0; - b->ref = 1; + PA_REFCNT_INIT(b); b->pool = p; stat_add(b); @@ -270,7 +270,7 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int re b = pa_xnew(pa_memblock, 1); b->type = PA_MEMBLOCK_FIXED; b->read_only = read_only; - b->ref = 1; + PA_REFCNT_INIT(b); b->length = length; b->data = d; b->pool = p; @@ -290,7 +290,7 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (* b = pa_xnew(pa_memblock, 1); b->type = PA_MEMBLOCK_USER; b->read_only = read_only; - b->ref = 1; + PA_REFCNT_INIT(b); b->length = length; b->data = d; b->per_type.user.free_cb = free_cb; @@ -302,17 +302,17 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (* pa_memblock* pa_memblock_ref(pa_memblock*b) { assert(b); - assert(b->ref >= 1); - - b->ref++; + assert(PA_REFCNT_VALUE(b) > 0); + + PA_REFCNT_INC(b); return b; } void pa_memblock_unref(pa_memblock*b) { assert(b); - assert(b->ref >= 1); + assert(PA_REFCNT_VALUE(b) > 0); - if ((--(b->ref)) > 0) + if (PA_REFCNT_DEC(b) > 0) return; stat_remove(b); @@ -403,10 +403,10 @@ finish: void pa_memblock_unref_fixed(pa_memblock *b) { assert(b); - assert(b->ref >= 1); + assert(PA_REFCNT_VALUE(b) > 0); assert(b->type == PA_MEMBLOCK_FIXED); - if (b->ref > 1) + if (PA_REFCNT_VALUE(b) > 1) memblock_make_local(b); pa_memblock_unref(b); @@ -615,7 +615,7 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i b = pa_xnew(pa_memblock, 1); b->type = PA_MEMBLOCK_IMPORTED; b->read_only = 1; - b->ref = 1; + PA_REFCNT_INIT(b); b->length = size; b->data = (uint8_t*) seg->memory.ptr + offset; b->pool = i->pool; diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index 620bf7263..60a0c900c 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -26,6 +26,7 @@ #include #include +#include /* A pa_memblock is a reference counted memory block. PulseAudio * passed references to pa_memblocks around instead of copying @@ -56,7 +57,7 @@ typedef void (*pa_memexport_revoke_cb_t)(pa_memexport *e, uint32_t block_id, voi struct pa_memblock { pa_memblock_type_t type; int read_only; /* boolean */ - unsigned ref; /* the reference counter */ + PA_REFCNT_DECLARE; /* the reference counter */ size_t length; void *data; pa_mempool *pool; diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c index bcf0ce043..1dbad2b90 100644 --- a/src/pulsecore/memchunk.c +++ b/src/pulsecore/memchunk.c @@ -38,9 +38,11 @@ void pa_memchunk_make_writable(pa_memchunk *c, size_t min) { assert(c); assert(c->memblock); - assert(c->memblock->ref >= 1); + assert(PA_REFCNT_VALUE(c->memblock) > 0); - if (c->memblock->ref == 1 && !c->memblock->read_only && c->memblock->length >= c->index+min) + if (PA_REFCNT_VALUE(c->memblock) == 1 && + !c->memblock->read_only && + c->memblock->length >= c->index+min) return; l = c->length; From 5264d235d25f04d3cd5796e751a66cb92453be73 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Aug 2006 02:01:39 +0000 Subject: [PATCH 1242/1514] make pa_mempool_stat thread-safe/lock-free git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1343 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/cli-command.c | 20 +++++----- src/pulsecore/memblock.c | 67 +++++++++++++++++---------------- src/pulsecore/memblock.h | 28 ++++++++------ src/pulsecore/protocol-native.c | 8 ++-- src/tests/memblock-test.c | 20 +++++----- 5 files changed, 74 insertions(+), 69 deletions(-) diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 8ea9262bd..ae475c3a0 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -259,20 +259,20 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G stat = pa_mempool_get_stat(c->mempool); pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n", - stat->n_allocated, - pa_bytes_snprint(s, sizeof(s), stat->allocated_size)); + (unsigned) AO_load_acquire_read((AO_t*) &stat->n_allocated), + pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->allocated_size))); pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n", - stat->n_accumulated, - pa_bytes_snprint(s, sizeof(s), stat->accumulated_size)); + (unsigned) AO_load_acquire_read((AO_t*) &stat->n_accumulated), + pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->accumulated_size))); pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n", - stat->n_imported, - pa_bytes_snprint(s, sizeof(s), stat->imported_size)); + (unsigned) AO_load_acquire_read((AO_t*) &stat->n_imported), + pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->imported_size))); pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n", - stat->n_exported, - pa_bytes_snprint(s, sizeof(s), stat->exported_size)); + (unsigned) AO_load_acquire_read((AO_t*) &stat->n_exported), + pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->exported_size))); pa_strbuf_printf(buf, "Total sample cache size: %s.\n", pa_bytes_snprint(s, sizeof(s), pa_scache_total_size(c))); @@ -289,8 +289,8 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_strbuf_printf(buf, "Memory blocks of type %s: %u allocated/%u accumulated.\n", type_table[k], - stat->n_allocated_by_type[k], - stat->n_accumulated_by_type[k]); + (unsigned) AO_load_acquire_read(&stat->n_allocated_by_type[k]), + (unsigned) AO_load_acquire_read(&stat->n_accumulated_by_type[k])); return 0; } diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 516ade133..70bcf677d 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -112,39 +112,40 @@ static void stat_add(pa_memblock*b) { assert(b); assert(b->pool); - b->pool->stat.n_allocated ++; - b->pool->stat.n_accumulated ++; - b->pool->stat.allocated_size += b->length; - b->pool->stat.accumulated_size += b->length; + AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated); + AO_fetch_and_add_release_write(&b->pool->stat.allocated_size, (AO_t) b->length); + + AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated); + AO_fetch_and_add_release_write(&b->pool->stat.accumulated_size, (AO_t) b->length); if (b->type == PA_MEMBLOCK_IMPORTED) { - b->pool->stat.n_imported++; - b->pool->stat.imported_size += b->length; + AO_fetch_and_add1_release_write(&b->pool->stat.n_imported); + AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) b->length); } - b->pool->stat.n_allocated_by_type[b->type]++; - b->pool->stat.n_accumulated_by_type[b->type]++; + AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); + AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated_by_type[b->type]); } static void stat_remove(pa_memblock *b) { assert(b); assert(b->pool); - assert(b->pool->stat.n_allocated > 0); - assert(b->pool->stat.allocated_size >= b->length); + assert(AO_load_acquire_read(&b->pool->stat.n_allocated) > 0); + assert(AO_load_acquire_read(&b->pool->stat.allocated_size) >= (AO_t) b->length); - b->pool->stat.n_allocated --; - b->pool->stat.allocated_size -= b->length; + AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated); + AO_fetch_and_add_release_write(&b->pool->stat.allocated_size, (AO_t) (-b->length)); if (b->type == PA_MEMBLOCK_IMPORTED) { - assert(b->pool->stat.n_imported > 0); - assert(b->pool->stat.imported_size >= b->length); + assert(AO_load_acquire_read(&b->pool->stat.n_imported) > 0); + assert(AO_load_acquire_read(&b->pool->stat.imported_size) >= (AO_t) b->length); - b->pool->stat.n_imported --; - b->pool->stat.imported_size -= b->length; + AO_fetch_and_sub1_release_write(&b->pool->stat.n_imported); + AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) (-b->length)); } - b->pool->stat.n_allocated_by_type[b->type]--; + AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); } static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length); @@ -190,7 +191,7 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * p->n_init++)); else { pa_log_debug("Pool full"); - p->stat.n_pool_full++; + AO_fetch_and_add1_release_write(&p->stat.n_pool_full); return NULL; } @@ -247,7 +248,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { b->data = mempool_slot_data(slot); } else { pa_log_debug("Memory block too large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot)); - p->stat.n_too_large_for_pool++; + AO_fetch_and_add1_release_write(&p->stat.n_too_large_for_pool); return NULL; } @@ -371,7 +372,7 @@ void pa_memblock_unref(pa_memblock*b) { static void memblock_make_local(pa_memblock *b) { assert(b); - b->pool->stat.n_allocated_by_type[b->type]--; + AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); if (b->length <= b->pool->block_size - sizeof(struct mempool_slot)) { struct mempool_slot *slot; @@ -397,8 +398,8 @@ static void memblock_make_local(pa_memblock *b) { b->data = pa_xmemdup(b->data, b->length); finish: - b->pool->stat.n_allocated_by_type[b->type]++; - b->pool->stat.n_accumulated_by_type[b->type]++; + AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); + AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated_by_type[b->type]); } void pa_memblock_unref_fixed(pa_memblock *b) { @@ -418,10 +419,10 @@ static void memblock_replace_import(pa_memblock *b) { assert(b); assert(b->type == PA_MEMBLOCK_IMPORTED); - assert(b->pool->stat.n_imported > 0); - assert(b->pool->stat.imported_size >= b->length); - b->pool->stat.n_imported --; - b->pool->stat.imported_size -= b->length; + assert(AO_load_acquire_read(&b->pool->stat.n_imported) > 0); + assert(AO_load_acquire_read(&b->pool->stat.imported_size) >= (AO_t) b->length); + AO_fetch_and_sub1_release_write(&b->pool->stat.n_imported); + AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) - b->length); seg = b->per_type.imported.segment; assert(seg); @@ -486,7 +487,7 @@ void pa_mempool_free(pa_mempool *p) { while (p->exports) pa_memexport_free(p->exports); - if (p->stat.n_allocated > 0) + if (AO_load_acquire_read(&p->stat.n_allocated) > 0) pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!"); pa_shm_free(&p->memory); @@ -685,11 +686,11 @@ int pa_memexport_process_release(pa_memexport *e, uint32_t id) { /* pa_log("Processing release for %u", id); */ - assert(e->pool->stat.n_exported > 0); - assert(e->pool->stat.exported_size >= e->slots[id].block->length); + assert(AO_load_acquire_read(&e->pool->stat.n_exported) > 0); + assert(AO_load_acquire_read(&e->pool->stat.exported_size) >= (AO_t) e->slots[id].block->length); - e->pool->stat.n_exported --; - e->pool->stat.exported_size -= e->slots[id].block->length; + AO_fetch_and_sub1_release_write(&e->pool->stat.n_exported); + AO_fetch_and_add_release_write(&e->pool->stat.exported_size, (AO_t) -e->slots[id].block->length); pa_memblock_unref(e->slots[id].block); e->slots[id].block = NULL; @@ -786,8 +787,8 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 *offset = (uint8_t*) b->data - (uint8_t*) memory->ptr; *size = b->length; - e->pool->stat.n_exported ++; - e->pool->stat.exported_size += b->length; + AO_fetch_and_add1_release_write(&e->pool->stat.n_exported); + AO_fetch_and_add_release_write(&e->pool->stat.exported_size, (AO_t) b->length); return 0; } diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index 60a0c900c..d4f2b7aaf 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -74,21 +74,25 @@ struct pa_memblock { } per_type; }; +/* Please note that updates to this structure are not locked, + * i.e. n_allocated might be updated at a point in time where + * n_accumulated is not yet. Take these values with a grain of salt, + * threy are here for purely statistical reasons.*/ struct pa_mempool_stat { - unsigned n_allocated; - unsigned n_accumulated; - unsigned n_imported; - unsigned n_exported; - size_t allocated_size; - size_t accumulated_size; - size_t imported_size; - size_t exported_size; + AO_t n_allocated; + AO_t n_accumulated; + AO_t n_imported; + AO_t n_exported; + AO_t allocated_size; + AO_t accumulated_size; + AO_t imported_size; + AO_t exported_size; - unsigned n_too_large_for_pool; - unsigned n_pool_full; + AO_t n_too_large_for_pool; + AO_t n_pool_full; - unsigned n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; - unsigned n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; + AO_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; + AO_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; }; /* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL or PA_MEMBLOCK_APPENDED, depending on the size */ diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 0f0150718..38c024b7b 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1112,10 +1112,10 @@ static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t stat = pa_mempool_get_stat(c->protocol->core->mempool); reply = reply_new(tag); - pa_tagstruct_putu32(reply, stat->n_allocated); - pa_tagstruct_putu32(reply, stat->allocated_size); - pa_tagstruct_putu32(reply, stat->n_accumulated); - pa_tagstruct_putu32(reply, stat->accumulated_size); + pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->n_allocated)); + pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->allocated_size)); + pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->n_accumulated)); + pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->accumulated_size)); pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core)); pa_pstream_send_tagstruct(c->pstream, reply); } diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c index 11198ae6b..ef2e0ad71 100644 --- a/src/tests/memblock-test.c +++ b/src/tests/memblock-test.c @@ -54,16 +54,16 @@ static void print_stats(pa_mempool *p, const char *text) { "n_pool_full = %u\n" "}\n", text, - s->n_allocated, - s->n_accumulated, - s->n_imported, - s->n_exported, - (unsigned long) s->allocated_size, - (unsigned long) s->accumulated_size, - (unsigned long) s->imported_size, - (unsigned long) s->exported_size, - s->n_too_large_for_pool, - s->n_pool_full); + (unsigned) AO_load_acquire_read((AO_t*) &s->n_allocated), + (unsigned) AO_load_acquire_read((AO_t*) &s->n_accumulated), + (unsigned) AO_load_acquire_read((AO_t*) &s->n_imported), + (unsigned) AO_load_acquire_read((AO_t*) &s->n_exported), + (unsigned long) AO_load_acquire_read((AO_t*) &s->allocated_size), + (unsigned long) AO_load_acquire_read((AO_t*) &s->accumulated_size), + (unsigned long) AO_load_acquire_read((AO_t*) &s->imported_size), + (unsigned long) AO_load_acquire_read((AO_t*) &s->exported_size), + (unsigned) AO_load_acquire_read((AO_t*) &s->n_too_large_for_pool), + (unsigned) AO_load_acquire_read((AO_t*) &s->n_pool_full)); } int main(int argc, char *argv[]) { From b2c341f935bd54eb1b7f80a297e72bf0e6c6dc83 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Aug 2006 19:51:14 +0000 Subject: [PATCH 1243/1514] add a threading primitive API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1344 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 16 +++- src/pulsecore/mutex-posix.c | 121 +++++++++++++++++++++++++++++ src/pulsecore/mutex.h | 39 ++++++++++ src/pulsecore/thread-posix.c | 146 +++++++++++++++++++++++++++++++++++ src/pulsecore/thread.h | 44 +++++++++++ src/tests/thread-test.c | 135 ++++++++++++++++++++++++++++++++ 6 files changed, 498 insertions(+), 3 deletions(-) create mode 100644 src/pulsecore/mutex-posix.c create mode 100644 src/pulsecore/mutex.h create mode 100644 src/pulsecore/thread-posix.c create mode 100644 src/pulsecore/thread.h create mode 100644 src/tests/thread-test.c diff --git a/src/Makefile.am b/src/Makefile.am index c9942cffd..bbdc46120 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -198,7 +198,8 @@ noinst_PROGRAMS = \ get-binary-name-test \ ipacl-test \ hook-list-test \ - memblock-test + memblock-test \ + thread-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -248,6 +249,11 @@ memblock_test_CFLAGS = $(AM_CFLAGS) memblock_test_LDADD = $(AM_LDADD) libpulsecore.la memblock_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +thread_test_SOURCES = tests/thread-test.c +thread_test_CFLAGS = $(AM_CFLAGS) +thread_test_LDADD = $(AM_LDADD) libpulsecore.la +thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la @@ -529,7 +535,9 @@ pulsecoreinclude_HEADERS = \ pulsecore/creds.h \ pulsecore/shm.h \ pulsecore/llist.h \ - pulsecore/refcnt.h + pulsecore/refcnt.h \ + pulsecore/mutex.h \ + pulsecore/thread.h lib_LTLIBRARIES += libpulsecore.la @@ -597,7 +605,9 @@ libpulsecore_la_SOURCES += \ pulsecore/winsock.h \ pulsecore/core-error.c pulsecore/core-error.h \ pulsecore/hook-list.c pulsecore/hook-list.h \ - pulsecore/shm.c pulsecore/shm.h + pulsecore/shm.c pulsecore/shm.h \ + pulsecore/mutex-posix.c pulsecore/mutex.h \ + pulsecore/thread-posix.c pulsecore/thread.h if OS_IS_WIN32 libpulsecore_la_SOURCES += \ diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c new file mode 100644 index 000000000..d0156dbf1 --- /dev/null +++ b/src/pulsecore/mutex-posix.c @@ -0,0 +1,121 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "mutex.h" + +#define ASSERT_SUCCESS(x) do { \ + int _r = (x); \ + assert(_r == 0); \ +} while(0) + +struct pa_mutex { + pthread_mutex_t mutex; +}; + +struct pa_cond { + pthread_cond_t cond; +}; + +pa_mutex* pa_mutex_new(int recursive) { + pa_mutex *m; + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + + if (recursive) + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) < 0) + return NULL; + + m = pa_xnew(pa_mutex, 1); + + if (pthread_mutex_init(&m->mutex, &attr) < 0) { + pa_xfree(m); + return NULL; + } + + return m; +} + +void pa_mutex_free(pa_mutex *m) { + assert(m); + + ASSERT_SUCCESS(pthread_mutex_destroy(&m->mutex)); + pa_xfree(m); +} + +void pa_mutex_lock(pa_mutex *m) { + assert(m); + + ASSERT_SUCCESS(pthread_mutex_lock(&m->mutex)); +} + +void pa_mutex_unlock(pa_mutex *m) { + assert(m); + + ASSERT_SUCCESS(pthread_mutex_unlock(&m->mutex)); +} + + +pa_cond *pa_cond_new(void) { + pa_cond *c; + + c = pa_xnew(pa_cond, 1); + + if (pthread_cond_init(&c->cond, NULL) < 0) { + pa_xfree(c); + return NULL; + } + + return c; +} + +void pa_cond_free(pa_cond *c) { + assert(c); + + ASSERT_SUCCESS(pthread_cond_destroy(&c->cond)); + pa_xfree(c); +} + +void pa_cond_signal(pa_cond *c, int broadcast) { + assert(c); + + if (broadcast) + ASSERT_SUCCESS(pthread_cond_broadcast(&c->cond)); + else + ASSERT_SUCCESS(pthread_cond_signal(&c->cond)); +} + +int pa_cond_wait(pa_cond *c, pa_mutex *m) { + assert(c); + assert(m); + + return pthread_cond_wait(&c->cond, &m->mutex); +} diff --git a/src/pulsecore/mutex.h b/src/pulsecore/mutex.h new file mode 100644 index 000000000..b3b9c5c6a --- /dev/null +++ b/src/pulsecore/mutex.h @@ -0,0 +1,39 @@ +#ifndef foopulsemutexhfoo +#define foopulsemutexhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +typedef struct pa_mutex pa_mutex; + +pa_mutex* pa_mutex_new(int recursive); +void pa_mutex_free(pa_mutex *m); +void pa_mutex_lock(pa_mutex *m); +void pa_mutex_unlock(pa_mutex *m); + +typedef struct pa_cond pa_cond; + +pa_cond *pa_cond_new(void); +void pa_cond_free(pa_cond *c); +void pa_cond_signal(pa_cond *c, int broadcast); +int pa_cond_wait(pa_cond *c, pa_mutex *m); + +#endif diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c new file mode 100644 index 000000000..15ade2909 --- /dev/null +++ b/src/pulsecore/thread-posix.c @@ -0,0 +1,146 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "thread.h" + +#define ASSERT_SUCCESS(x) do { \ + int _r = (x); \ + assert(_r == 0); \ +} while(0) + +struct pa_thread { + pthread_t id; + pa_thread_func_t thread_func; + void *userdata; + AO_t running; +}; + +struct pa_tls { + pthread_key_t key; +}; + +static pa_tls *thread_tls; +static pthread_once_t thread_tls_once = PTHREAD_ONCE_INIT; + +static void thread_tls_once_func(void) { + thread_tls = pa_tls_new(NULL); + assert(thread_tls); +} + +static void* internal_thread_func(void *userdata) { + pa_thread *t = userdata; + assert(t); + + t->id = pthread_self(); + + ASSERT_SUCCESS(pthread_once(&thread_tls_once, thread_tls_once_func)); + pa_tls_set(thread_tls, t); + + AO_store_release_write(&t->running, 1); + t->thread_func(t->userdata); + AO_store_release_write(&t->running, 0); + + return NULL; +} + +pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { + pa_thread *t; + + t = pa_xnew(pa_thread, 1); + t->thread_func = thread_func; + t->userdata = userdata; + + if (pthread_create(&t->id, NULL, internal_thread_func, t) < 0) { + pa_xfree(t); + return NULL; + } + + return t; +} + +int pa_thread_is_running(pa_thread *t) { + assert(t); + + return !!AO_load_acquire_read(&t->running); +} + +void pa_thread_free(pa_thread *t) { + assert(t); + + pa_thread_join(t); + pa_xfree(t); +} + +int pa_thread_join(pa_thread *t) { + assert(t); + + return pthread_join(t->id, NULL); +} + +pa_thread* pa_thread_self(void) { + ASSERT_SUCCESS(pthread_once(&thread_tls_once, thread_tls_once_func)); + return pa_tls_get(thread_tls); +} + +pa_tls* pa_tls_new(pa_free_cb_t free_cb) { + pa_tls *t; + + t = pa_xnew(pa_tls, 1); + + if (pthread_key_create(&t->key, free_cb) < 0) { + pa_xfree(t); + return NULL; + } + + return t; +} + +void pa_tls_free(pa_tls *t) { + assert(t); + + ASSERT_SUCCESS(pthread_key_delete(t->key)); + pa_xfree(t); +} + +void *pa_tls_get(pa_tls *t) { + assert(t); + + return pthread_getspecific(t->key); +} + +void *pa_tls_set(pa_tls *t, void *userdata) { + void *r; + + r = pthread_getspecific(t->key); + ASSERT_SUCCESS(pthread_setspecific(t->key, userdata)); + return r; +} + diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h new file mode 100644 index 000000000..978e99276 --- /dev/null +++ b/src/pulsecore/thread.h @@ -0,0 +1,44 @@ +#ifndef foopulsethreadhfoo +#define foopulsethreadhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +typedef struct pa_thread pa_thread; + +typedef void (*pa_thread_func_t) (void *userdata); + +pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata); +void pa_thread_free(pa_thread *t); +int pa_thread_join(pa_thread *t); +int pa_thread_is_running(pa_thread *t); +pa_thread *pa_thread_self(void); + +typedef struct pa_tls pa_tls; + +pa_tls* pa_tls_new(pa_free_cb_t free_cb); +void pa_tls_free(pa_tls *t); +void * pa_tls_get(pa_tls *t); +void *pa_tls_set(pa_tls *t, void *userdata); + +#endif diff --git a/src/tests/thread-test.c b/src/tests/thread-test.c new file mode 100644 index 000000000..a93ac1e4a --- /dev/null +++ b/src/tests/thread-test.c @@ -0,0 +1,135 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include + +static pa_mutex *mutex = NULL; +static pa_cond *cond1 = NULL, *cond2 = NULL; +static pa_tls *tls = NULL; + +static int magic_number = 0; + +#define THREADS_MAX 20 + +static void thread_func(void *data) { + pa_tls_set(tls, data); + + pa_log("thread_func() for %s starting...", (char*) pa_tls_get(tls)); + + pa_mutex_lock(mutex); + + for (;;) { + int k, n; + + pa_log("%s waiting ...", (char*) pa_tls_get(tls)); + + for (;;) { + + if (magic_number < 0) + goto quit; + + if (magic_number != 0) + break; + + pa_cond_wait(cond1, mutex); + } + + k = magic_number; + magic_number = 0; + + pa_mutex_unlock(mutex); + + pa_cond_signal(cond2, 0); + + pa_log("%s got number %i", (char*) pa_tls_get(tls), k); + + /* Spin! */ + for (n = 0; n < k; n++) + sched_yield(); + + pa_mutex_lock(mutex); + } + +quit: + + pa_mutex_unlock(mutex); + + pa_log("thread_func() for %s done...", (char*) pa_tls_get(tls)); +} + +int main(int argc, char *argv[]) { + int i, k; + pa_thread* t[THREADS_MAX]; + + mutex = pa_mutex_new(0); + cond1 = pa_cond_new(); + cond2 = pa_cond_new(); + tls = pa_tls_new(pa_xfree); + + for (i = 0; i < THREADS_MAX; i++) { + t[i] = pa_thread_new(thread_func, pa_sprintf_malloc("Thread #%i", i+1)); + assert(t[i]); + } + + pa_mutex_lock(mutex); + + pa_log("loop-init"); + + for (k = 0; k < 100; k++) { + assert(magic_number == 0); + + + magic_number = (int) rand() % 0x10000; + + pa_log("iteration %i (%i)", k, magic_number); + + pa_cond_signal(cond1, 0); + + pa_cond_wait(cond2, mutex); + } + + pa_log("loop-exit"); + + magic_number = -1; + pa_cond_signal(cond1, 1); + + pa_mutex_unlock(mutex); + + for (i = 0; i < THREADS_MAX; i++) + pa_thread_free(t[i]); + + pa_mutex_free(mutex); + pa_cond_free(cond1); + pa_cond_free(cond2); + pa_tls_free(tls); + + return 0; +} From 078420a9d2b2532062f30263d067e76735a30349 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 30 Aug 2006 13:02:29 +0000 Subject: [PATCH 1244/1514] We need to have a callback when changing volume or we might deadlock. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1345 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 32cb5f9a3..c765b6935 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1487,9 +1487,9 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno pa_operation *o; if (request == SOUND_MIXER_READ_PCM) - o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, pv, NULL, NULL); + o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, pv, context_success_cb, i); else - o = pa_context_set_source_volume_by_index(i->context, i->source_index, pv, NULL, NULL); + o = pa_context_set_source_volume_by_index(i->context, i->source_index, pv, context_success_cb, i); if (!o) debug(DEBUG_LEVEL_NORMAL, __FILE__":Failed set volume: %s", pa_strerror(pa_context_errno(i->context))); From c4e47c63b7dbba208cb8c78bb5d15a0d1310854e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 30 Aug 2006 14:44:15 +0000 Subject: [PATCH 1245/1514] Remove check for libatomic_ops library as some systems have no (zero, nada) symbols in it. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1346 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 6 ------ 1 file changed, 6 deletions(-) diff --git a/configure.ac b/configure.ac index 42bee9a85..2bb208092 100644 --- a/configure.ac +++ b/configure.ac @@ -326,12 +326,6 @@ AC_CHECK_HEADERS([atomic_ops.h], [], [ AC_MSG_ERROR([*** libatomic-ops headers not found]) ]) -AC_SEARCH_LIBS([AO_spin], [atomic_ops], [], [ -AC_MSG_ERROR([*** libatomic-ops library file not found]) -]) - - - #### OSS support (optional) #### AC_ARG_ENABLE([oss], From a6b99d5196cf66aa276d9e7c9483f1b9e2fba491 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 30 Aug 2006 16:55:37 +0000 Subject: [PATCH 1246/1514] Make sure the libatomic_ops lib is included. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1347 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 2bb208092..c08c1d029 100644 --- a/configure.ac +++ b/configure.ac @@ -326,6 +326,8 @@ AC_CHECK_HEADERS([atomic_ops.h], [], [ AC_MSG_ERROR([*** libatomic-ops headers not found]) ]) +LIBS="$LIBS -latomic_ops" + #### OSS support (optional) #### AC_ARG_ENABLE([oss], From ad0535beef4cd0d4e96fa194d54796a0945ed3c6 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 30 Aug 2006 17:01:10 +0000 Subject: [PATCH 1247/1514] Add AO_REQUIRE_CAS as we do. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1348 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/mutex-posix.c | 2 ++ src/pulsecore/refcnt.h | 1 + src/pulsecore/thread-posix.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c index d0156dbf1..08baa3860 100644 --- a/src/pulsecore/mutex-posix.c +++ b/src/pulsecore/mutex-posix.c @@ -25,6 +25,8 @@ #include #include + +#define AO_REQUIRE_CAS #include #include diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h index fade9aa47..ff0a99238 100644 --- a/src/pulsecore/refcnt.h +++ b/src/pulsecore/refcnt.h @@ -22,6 +22,7 @@ USA. ***/ +#define AO_REQUIRE_CAS #include #define PA_REFCNT_DECLARE volatile AO_t _ref diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index 15ade2909..54f21b75a 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -25,6 +25,8 @@ #include #include + +#define AO_REQUIRE_CAS #include #include From 2f6cc4f8fa8d806ef6120887cd3aed62b1b072c0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 30 Aug 2006 17:12:35 +0000 Subject: [PATCH 1248/1514] fix handling of "running" variable git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1349 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/thread-posix.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index 54f21b75a..b634a6f6b 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -66,9 +66,9 @@ static void* internal_thread_func(void *userdata) { ASSERT_SUCCESS(pthread_once(&thread_tls_once, thread_tls_once_func)); pa_tls_set(thread_tls, t); - AO_store_release_write(&t->running, 1); + AO_fetch_and_add1_full(&t->running); t->thread_func(t->userdata); - AO_store_release_write(&t->running, 0); + AO_fetch_and_add_full(&t->running, (AO_t) -2); return NULL; } @@ -79,19 +79,24 @@ pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { t = pa_xnew(pa_thread, 1); t->thread_func = thread_func; t->userdata = userdata; + AO_store_full(&t->running, 0); if (pthread_create(&t->id, NULL, internal_thread_func, t) < 0) { pa_xfree(t); return NULL; } + AO_fetch_and_add1_full(&t->running); + return t; } int pa_thread_is_running(pa_thread *t) { + AO_t r; assert(t); - return !!AO_load_acquire_read(&t->running); + r = AO_load_full(&t->running); + return r == 1 || r == 2; } void pa_thread_free(pa_thread *t) { From 7ce39d35c680d2a51e14c0776f3b3a17bdc598f0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 31 Aug 2006 15:17:40 +0000 Subject: [PATCH 1249/1514] update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1350 fefdeb5f-60dc-0310-8127-8f9354f1896f --- todo | 1 + 1 file changed, 1 insertion(+) diff --git a/todo b/todo index 34935c6f8..7b4ce7864 100644 --- a/todo +++ b/todo @@ -23,6 +23,7 @@ Cleanups: - silence generation should be moved into the core to avoid races and code duplication in the backends - don't read/write audio data from/to ALSA devices if noone is listening +- using POSIX monotonous clocks wherever possible instead of gettimeofday() Test: - autoload From aee4a3738eaa5026a5ade1e865f67860c9bc004f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 31 Aug 2006 15:20:43 +0000 Subject: [PATCH 1250/1514] define AO_REQUIRE_CAS in the Makefile instead of each source file, effectively reversing r1348 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1351 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 1 + src/pulsecore/mutex-posix.c | 1 - src/pulsecore/refcnt.h | 1 - src/pulsecore/thread-posix.c | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index bbdc46120..3b79acade 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,6 +50,7 @@ AM_CFLAGS += -DPA_DLSEARCHPATH=\"$(modlibexecdir)\" AM_CFLAGS += -DPA_DEFAULT_CONFIG_DIR=\"$(PA_DEFAULT_CONFIG_DIR)\" AM_CFLAGS += -DPA_BINARY=\"$(PA_BINARY)\" AM_CFLAGS += -DPA_SYSTEM_RUNTIME_PATH=\"$(PA_SYSTEM_RUNTIME_PATH)\" +AM_CFLAGS += -DAO_REQUIRE_CAS # This cool debug trap works on i386/gcc only AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")' diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c index 08baa3860..6f0e73365 100644 --- a/src/pulsecore/mutex-posix.c +++ b/src/pulsecore/mutex-posix.c @@ -26,7 +26,6 @@ #include #include -#define AO_REQUIRE_CAS #include #include diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h index ff0a99238..fade9aa47 100644 --- a/src/pulsecore/refcnt.h +++ b/src/pulsecore/refcnt.h @@ -22,7 +22,6 @@ USA. ***/ -#define AO_REQUIRE_CAS #include #define PA_REFCNT_DECLARE volatile AO_t _ref diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index b634a6f6b..6ca46d705 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -26,7 +26,6 @@ #include #include -#define AO_REQUIRE_CAS #include #include From 0f6098bf6428b17bbff2b2d6f4e8ead0d43d7f3a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 31 Aug 2006 15:31:33 +0000 Subject: [PATCH 1251/1514] work around bug in firefox which apparently misuses access() as NULL pointer test. Original patch by "alon". (Closes #27) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1352 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index c765b6935..ddb732f03 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2121,6 +2121,13 @@ int close(int fd) { } int access(const char *pathname, int mode) { + + if (!pathname) { + /* Firefox needs this. See #27 */ + errno = EFAULT; + return -1; + } + debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname); if (strcmp(pathname, "/dev/dsp") != 0 && From 6e9706bcbcc0c5743d21ed48bd6e6485e4ee5203 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 31 Aug 2006 16:13:07 +0000 Subject: [PATCH 1252/1514] Also wrap yield functionality so that it can be platform independent. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1353 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/thread-posix.c | 9 +++++++++ src/pulsecore/thread.h | 1 + src/tests/thread-test.c | 4 +--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index 6ca46d705..4c12ec93b 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -25,6 +25,7 @@ #include #include +#include #include @@ -116,6 +117,14 @@ pa_thread* pa_thread_self(void) { return pa_tls_get(thread_tls); } +void pa_thread_yield(void) { +#ifdef HAVE_PTHREAD_YIELD + pthread_yield(); +#else + sched_yield(); +#endif +} + pa_tls* pa_tls_new(pa_free_cb_t free_cb) { pa_tls *t; diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h index 978e99276..9b99c8c24 100644 --- a/src/pulsecore/thread.h +++ b/src/pulsecore/thread.h @@ -33,6 +33,7 @@ void pa_thread_free(pa_thread *t); int pa_thread_join(pa_thread *t); int pa_thread_is_running(pa_thread *t); pa_thread *pa_thread_self(void); +void pa_thread_yield(void); typedef struct pa_tls pa_tls; diff --git a/src/tests/thread-test.c b/src/tests/thread-test.c index a93ac1e4a..120d25542 100644 --- a/src/tests/thread-test.c +++ b/src/tests/thread-test.c @@ -23,8 +23,6 @@ #include #endif -#include - #include #include #include @@ -73,7 +71,7 @@ static void thread_func(void *data) { /* Spin! */ for (n = 0; n < k; n++) - sched_yield(); + pa_thread_yield(); pa_mutex_lock(mutex); } From 6e3de3dbe5e70839c70c1180a08fa720946ee247 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 31 Aug 2006 16:39:53 +0000 Subject: [PATCH 1253/1514] Make sure libatomic_ops.a isn't included in win32 builds as libtool doesn't like static libs in dlls. Everything is in the headers anyway, so we do not need it. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1354 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c08c1d029..7d85b32ae 100644 --- a/configure.ac +++ b/configure.ac @@ -326,7 +326,10 @@ AC_CHECK_HEADERS([atomic_ops.h], [], [ AC_MSG_ERROR([*** libatomic-ops headers not found]) ]) -LIBS="$LIBS -latomic_ops" +# Win32 does not need the lib and breaks horribly if we try to include it +if test "x$os_is_win32" != "x1" ; then + LIBS="$LIBS -latomic_ops" +fi #### OSS support (optional) #### From 97202d1b2d1638df147a369f4476060f608b568f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 1 Sep 2006 00:24:32 +0000 Subject: [PATCH 1254/1514] fix a race condition with stream connection vs. latency measuremtn (found by theBear) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1355 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 18e1d97db..a110c57e2 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -490,8 +490,21 @@ static void start_subscribe(struct userdata *u) { pa_pstream_send_tagstruct(u->pstream, t); } +static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + struct timeval ntv; + assert(m && e && u); + + request_latency(u); + + pa_gettimeofday(&ntv); + ntv.tv_sec += LATENCY_INTERVAL; + m->time_restart(e, &ntv); +} + static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; + struct timeval ntv; assert(pd && u && u->pdispatch == pd); if (command != PA_COMMAND_REPLY) { @@ -535,6 +548,11 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN start_subscribe(u); request_info(u); + assert(!u->time_event); + pa_gettimeofday(&ntv); + ntv.tv_sec += LATENCY_INTERVAL; + u->time_event = u->core->mainloop->time_new(u->core->mainloop, &ntv, timeout_callback, u); + request_latency(u); #ifdef TUNNEL_SINK send_bytes(u); @@ -840,18 +858,6 @@ static int source_set_hw_mute(pa_source *source) { } #endif -static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { - struct userdata *u = userdata; - struct timeval ntv; - assert(m && e && u); - - request_latency(u); - - pa_gettimeofday(&ntv); - ntv.tv_sec += LATENCY_INTERVAL; - m->time_restart(e, &ntv); -} - static int load_key(struct userdata *u, const char*fn) { assert(u); @@ -883,10 +889,8 @@ int pa__init(pa_core *c, pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; pa_channel_map map; - struct timeval ntv; char *t, *dn = NULL; - assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -986,9 +990,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_xfree(dn); - pa_gettimeofday(&ntv); - ntv.tv_sec += LATENCY_INTERVAL; - u->time_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, u); + u->time_event = NULL; pa_modargs_free(ma); From 3571bf1699d1fa42b5d24fcf62eea867f0fe9903 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 1 Sep 2006 18:16:55 +0000 Subject: [PATCH 1255/1514] Thread implementation for Win32. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1356 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 16 ++- src/pulsecore/mutex-win32.c | 133 +++++++++++++++++++ src/pulsecore/thread-win32.c | 246 +++++++++++++++++++++++++++++++++++ 3 files changed, 392 insertions(+), 3 deletions(-) create mode 100644 src/pulsecore/mutex-win32.c create mode 100644 src/pulsecore/thread-win32.c diff --git a/src/Makefile.am b/src/Makefile.am index 3b79acade..5043197c4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -580,6 +580,7 @@ libpulsecore_la_SOURCES += \ pulsecore/modargs.c pulsecore/modargs.h \ pulsecore/modinfo.c pulsecore/modinfo.h \ pulsecore/module.c pulsecore/module.h \ + pulsecore/mutex.h \ pulsecore/namereg.c pulsecore/namereg.h \ pulsecore/pid.c pulsecore/pid.h \ pulsecore/pipe.c pulsecore/pipe.h \ @@ -602,19 +603,28 @@ libpulsecore_la_SOURCES += \ pulsecore/source.c pulsecore/source.h \ pulsecore/source-output.c pulsecore/source-output.h \ pulsecore/strbuf.c pulsecore/strbuf.h \ + pulsecore/thread.h \ pulsecore/tokenizer.c pulsecore/tokenizer.h \ pulsecore/winsock.h \ pulsecore/core-error.c pulsecore/core-error.h \ pulsecore/hook-list.c pulsecore/hook-list.h \ - pulsecore/shm.c pulsecore/shm.h \ - pulsecore/mutex-posix.c pulsecore/mutex.h \ - pulsecore/thread-posix.c pulsecore/thread.h + pulsecore/shm.c pulsecore/shm.h if OS_IS_WIN32 libpulsecore_la_SOURCES += \ pulsecore/dllmain.c endif +if OS_IS_WIN32 +libpulsecore_la_SOURCES += \ + pulsecore/mutex-win32.c \ + pulsecore/thread-win32.c +else +libpulsecore_la_SOURCES += \ + pulsecore/mutex-posix.c \ + pulsecore/thread-posix.c +endif + libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) libpulsecore_la_LDFLAGS = -version-info $(LIBPULSECORE_VERSION_INFO) libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV) diff --git a/src/pulsecore/mutex-win32.c b/src/pulsecore/mutex-win32.c new file mode 100644 index 000000000..3710d914d --- /dev/null +++ b/src/pulsecore/mutex-win32.c @@ -0,0 +1,133 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "mutex.h" + +struct pa_mutex { + CRITICAL_SECTION mutex; +}; + +struct pa_cond { + pa_hashmap *wait_events; +}; + +pa_mutex* pa_mutex_new(int recursive) { + pa_mutex *m; + + m = pa_xnew(pa_mutex, 1); + + InitializeCriticalSection(&m->mutex); + + return m; +} + +void pa_mutex_free(pa_mutex *m) { + assert(m); + + DeleteCriticalSection(&m->mutex); + pa_xfree(m); +} + +void pa_mutex_lock(pa_mutex *m) { + assert(m); + + EnterCriticalSection(&m->mutex); +} + +void pa_mutex_unlock(pa_mutex *m) { + assert(m); + + LeaveCriticalSection(&m->mutex); +} + +pa_cond *pa_cond_new(void) { + pa_cond *c; + + c = pa_xnew(pa_cond, 1); + c->wait_events = pa_hashmap_new(NULL, NULL); + assert(c->wait_events); + + return c; +} + +void pa_cond_free(pa_cond *c) { + assert(c); + + pa_hashmap_free(c->wait_events, NULL, NULL); + pa_xfree(c); +} + +void pa_cond_signal(pa_cond *c, int broadcast) { + assert(c); + + if (pa_hashmap_size(c->wait_events) == 0) + return; + + if (broadcast) + SetEvent(pa_hashmap_get_first(c->wait_events)); + else { + void *iter; + const void *key; + HANDLE event; + + iter = NULL; + while (1) { + pa_hashmap_iterate(c->wait_events, &iter, &key); + if (key == NULL) + break; + event = (HANDLE)pa_hashmap_get(c->wait_events, key); + SetEvent(event); + } + } +} + +int pa_cond_wait(pa_cond *c, pa_mutex *m) { + HANDLE event; + + assert(c); + assert(m); + + event = CreateEvent(NULL, FALSE, FALSE, NULL); + assert(event); + + pa_hashmap_put(c->wait_events, event, event); + + pa_mutex_unlock(m); + + WaitForSingleObject(event, INFINITE); + + pa_mutex_lock(m); + + pa_hashmap_remove(c->wait_events, event); + + CloseHandle(event); + + return 0; +} diff --git a/src/pulsecore/thread-win32.c b/src/pulsecore/thread-win32.c new file mode 100644 index 000000000..bdcc5b2c5 --- /dev/null +++ b/src/pulsecore/thread-win32.c @@ -0,0 +1,246 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include +#include + +#include "thread.h" + +struct pa_thread { + HANDLE thread; + pa_thread_func_t thread_func; + void *userdata; +}; + +struct pa_tls { + DWORD index; + pa_free_cb_t free_func; +}; + +struct pa_tls_monitor { + HANDLE thread; + pa_free_cb_t free_func; + void *data; +}; + +static pa_tls *thread_tls = NULL; +static pa_tls *monitor_tls = NULL; + +static void thread_tls_once_func(void) { + HANDLE mutex; + char name[64]; + + sprintf(name, "pulse%d", (int)GetCurrentProcessId()); + + mutex = CreateMutex(NULL, FALSE, name); + assert(mutex); + + WaitForSingleObject(mutex, INFINITE); + + if (thread_tls == NULL) { + thread_tls = pa_tls_new(NULL); + assert(thread_tls); + } + + ReleaseMutex(mutex); + + CloseHandle(mutex); +} + +static DWORD WINAPI internal_thread_func(LPVOID param) { + pa_thread *t = param; + assert(t); + + thread_tls_once_func(); + pa_tls_set(thread_tls, t); + + t->thread_func(t->userdata); + + return 0; +} + +pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { + pa_thread *t; + + assert(thread_func); + + t = pa_xnew(pa_thread, 1); + t->thread_func = thread_func; + t->userdata = userdata; + + t->thread = CreateThread(NULL, 0, internal_thread_func, t, 0, NULL); + + if (!t->thread) { + pa_xfree(t); + return NULL; + } + + return t; +} + +int pa_thread_is_running(pa_thread *t) { + DWORD code; + + assert(t); + + if (!GetExitCodeThread(t->thread, &code)) + return 0; + + return code == STILL_ACTIVE; +} + +void pa_thread_free(pa_thread *t) { + assert(t); + + pa_thread_join(t); + CloseHandle(t->thread); + pa_xfree(t); +} + +int pa_thread_join(pa_thread *t) { + assert(t); + + if (WaitForSingleObject(t->thread, INFINITE) == WAIT_FAILED) + return -1; + + return 0; +} + +pa_thread* pa_thread_self(void) { + thread_tls_once_func(); + return pa_tls_get(thread_tls); +} + +void pa_thread_yield(void) { + Sleep(0); +} + +static void monitor_tls_once_func(void) { + HANDLE mutex; + char name[64]; + + sprintf(name, "pulse%d", (int)GetCurrentProcessId()); + + mutex = CreateMutex(NULL, FALSE, name); + assert(mutex); + + WaitForSingleObject(mutex, INFINITE); + + if (monitor_tls == NULL) { + monitor_tls = pa_tls_new(NULL); + assert(monitor_tls); + pa_tls_set(monitor_tls, NULL); + } + + ReleaseMutex(mutex); + + CloseHandle(mutex); +} + +static DWORD WINAPI monitor_thread_func(LPVOID param) { + struct pa_tls_monitor *m = param; + assert(m); + + WaitForSingleObject(m->thread, INFINITE); + + CloseHandle(m->thread); + + m->free_func(m->data); + + pa_xfree(m); + + return 0; +} + +pa_tls* pa_tls_new(pa_free_cb_t free_cb) { + pa_tls *t; + + t = pa_xnew(pa_tls, 1); + t->index = TlsAlloc(); + t->free_func = free_cb; + + if (t->index == TLS_OUT_OF_INDEXES) { + pa_xfree(t); + return NULL; + } + + return t; +} + +void pa_tls_free(pa_tls *t) { + assert(t); + + TlsFree(t->index); + pa_xfree(t); +} + +void *pa_tls_get(pa_tls *t) { + assert(t); + + return TlsGetValue(t->index); +} + +void *pa_tls_set(pa_tls *t, void *userdata) { + void *r; + + assert(t); + + r = TlsGetValue(t->index); + + TlsSetValue(t->index, userdata); + + if (t->free_func) { + struct pa_tls_monitor *m; + + monitor_tls_once_func(); + + m = pa_tls_get(monitor_tls); + if (!m) { + HANDLE thread; + + m = pa_xnew(struct pa_tls_monitor, 1); + + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &m->thread, 0, FALSE, + DUPLICATE_SAME_ACCESS); + + m->free_func = t->free_func; + + pa_tls_set(monitor_tls, m); + + thread = CreateThread(NULL, 0, monitor_thread_func, m, 0, NULL); + assert(thread); + CloseHandle(thread); + } + + m->data = userdata; + } + + return r; +} From f84c65ed86ae59aae6e9a48e62aca31eaa30e2e3 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 1 Sep 2006 18:39:55 +0000 Subject: [PATCH 1256/1514] Add pthread_once() equivalent support. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1357 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/thread-posix.c | 25 ++++++++++++++++ src/pulsecore/thread-win32.c | 56 ++++++++++++++++-------------------- src/pulsecore/thread.h | 5 ++++ 3 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index 4c12ec93b..bc71ea473 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -30,6 +30,7 @@ #include #include +#include #include "thread.h" @@ -52,6 +53,9 @@ struct pa_tls { static pa_tls *thread_tls; static pthread_once_t thread_tls_once = PTHREAD_ONCE_INIT; +static pa_mutex *once_mutex; +static pthread_once_t thread_once_once = PTHREAD_ONCE_INIT; + static void thread_tls_once_func(void) { thread_tls = pa_tls_new(NULL); assert(thread_tls); @@ -125,6 +129,27 @@ void pa_thread_yield(void) { #endif } +static void thread_once_once_func(void) { + once_mutex = pa_mutex_new(); + assert(once_mutex); +} + +void pa_thread_once(pa_thread_once_t *control, pa_thread_once_func_t once_func) { + assert(control); + assert(once_func); + + ASSERT_SUCCESS(pthread_once(&thread_once_once, thread_once_once_func)); + + pa_mutex_lock(once_mutex); + + if (*control == PA_THREAD_ONCE_INIT) { + *control = ~PA_THREAD_ONCE_INIT; + pa_mutex_unlock(once_mutex); + once_func(); + } else + pa_mutex_unlock(once_mutex); +} + pa_tls* pa_tls_new(pa_free_cb_t free_cb) { pa_tls *t; diff --git a/src/pulsecore/thread-win32.c b/src/pulsecore/thread-win32.c index bdcc5b2c5..ee61d85aa 100644 --- a/src/pulsecore/thread-win32.c +++ b/src/pulsecore/thread-win32.c @@ -49,35 +49,21 @@ struct pa_tls_monitor { void *data; }; -static pa_tls *thread_tls = NULL; -static pa_tls *monitor_tls = NULL; +static pa_tls *thread_tls; +static pa_thread_once_t thread_tls_once = PA_THREAD_ONCE_INIT; +static pa_tls *monitor_tls; +static pa_thread_once_t monitor_tls_once = PA_THREAD_ONCE_INIT; static void thread_tls_once_func(void) { - HANDLE mutex; - char name[64]; - - sprintf(name, "pulse%d", (int)GetCurrentProcessId()); - - mutex = CreateMutex(NULL, FALSE, name); - assert(mutex); - - WaitForSingleObject(mutex, INFINITE); - - if (thread_tls == NULL) { - thread_tls = pa_tls_new(NULL); - assert(thread_tls); - } - - ReleaseMutex(mutex); - - CloseHandle(mutex); + thread_tls = pa_tls_new(NULL); + assert(thread_tls); } static DWORD WINAPI internal_thread_func(LPVOID param) { pa_thread *t = param; assert(t); - thread_tls_once_func(); + pa_thread_once(&thread_tls_once, thread_tls_once_func); pa_tls_set(thread_tls, t); t->thread_func(t->userdata); @@ -133,7 +119,7 @@ int pa_thread_join(pa_thread *t) { } pa_thread* pa_thread_self(void) { - thread_tls_once_func(); + pa_thread_once(&thread_tls_once, thread_tls_once_func); return pa_tls_get(thread_tls); } @@ -141,10 +127,13 @@ void pa_thread_yield(void) { Sleep(0); } -static void monitor_tls_once_func(void) { +void pa_thread_once(pa_thread_once_t *control, pa_thread_once_func_t once_func) { HANDLE mutex; char name[64]; + assert(control); + assert(once_func); + sprintf(name, "pulse%d", (int)GetCurrentProcessId()); mutex = CreateMutex(NULL, FALSE, name); @@ -152,17 +141,22 @@ static void monitor_tls_once_func(void) { WaitForSingleObject(mutex, INFINITE); - if (monitor_tls == NULL) { - monitor_tls = pa_tls_new(NULL); - assert(monitor_tls); - pa_tls_set(monitor_tls, NULL); - } - - ReleaseMutex(mutex); + if (*control == PA_THREAD_ONCE_INIT) { + *control = ~PA_THREAD_ONCE_INIT; + ReleaseMutex(mutex); + once_func(); + } else + ReleaseMutex(mutex); CloseHandle(mutex); } +static void monitor_tls_once_func(void) { + monitor_tls = pa_tls_new(NULL); + assert(monitor_tls); + pa_tls_set(monitor_tls, NULL); +} + static DWORD WINAPI monitor_thread_func(LPVOID param) { struct pa_tls_monitor *m = param; assert(m); @@ -218,7 +212,7 @@ void *pa_tls_set(pa_tls *t, void *userdata) { if (t->free_func) { struct pa_tls_monitor *m; - monitor_tls_once_func(); + pa_thread_once(&monitor_tls_once, monitor_tls_once_func); m = pa_tls_get(monitor_tls); if (!m) { diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h index 9b99c8c24..8aabecfa1 100644 --- a/src/pulsecore/thread.h +++ b/src/pulsecore/thread.h @@ -24,9 +24,13 @@ #include +#define PA_THREAD_ONCE_INIT 0 + typedef struct pa_thread pa_thread; typedef void (*pa_thread_func_t) (void *userdata); +typedef void (*pa_thread_once_func_t) (void); +typedef unsigned int pa_thread_once_t; pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata); void pa_thread_free(pa_thread *t); @@ -34,6 +38,7 @@ int pa_thread_join(pa_thread *t); int pa_thread_is_running(pa_thread *t); pa_thread *pa_thread_self(void); void pa_thread_yield(void); +void pa_thread_once(pa_thread_once_t *control, pa_thread_once_func_t once_func); typedef struct pa_tls pa_tls; From 647ef180c3dac933963fdfeca53772bd3be894ae Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 1 Sep 2006 19:06:44 +0000 Subject: [PATCH 1257/1514] Fix call to pa_mutex_new(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1358 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/thread-posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index bc71ea473..2e8d6b68a 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -130,7 +130,7 @@ void pa_thread_yield(void) { } static void thread_once_once_func(void) { - once_mutex = pa_mutex_new(); + once_mutex = pa_mutex_new(0); assert(once_mutex); } From 5fa9cdb6b4be9f5998af462a858124a528914bf3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 2 Sep 2006 12:03:18 +0000 Subject: [PATCH 1258/1514] Merge FreeBSD compatibility patch (from Flameeyes) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1359 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/oss-util.c | 8 ++++++++ src/utils/padsp.c | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index d1c623b4c..0aaf6971d 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -93,7 +93,11 @@ success: pa_log_debug("capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s%s", *pcaps & DSP_CAP_BATCH ? " BATCH" : "", +#ifdef DSP_CAP_BIND *pcaps & DSP_CAP_BIND ? " BIND" : "", +#else + "", +#endif *pcaps & DSP_CAP_COPROC ? " COPROC" : "", *pcaps & DSP_CAP_DUPLEX ? " DUPLEX" : "", #ifdef DSP_CAP_FREERATE @@ -112,7 +116,11 @@ success: #else "", #endif +#ifdef DSP_CAP_MULTI *pcaps & DSP_CAP_MULTI ? " MULTI" : "", +#else + "", +#endif #ifdef DSP_CAP_OUTPUT *pcaps & DSP_CAP_OUTPUT ? " OUTPUT" : "", #else diff --git a/src/utils/padsp.c b/src/utils/padsp.c index ddb732f03..dfef3f3ab 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -53,6 +53,11 @@ #include #include +/* On some systems SIOCINQ isn't defined, but FIONREAD is just an alias */ +#if !defined(SIOCINQ) && defined(FIONREAD) +# define SIOCINQ FIONREAD +#endif + typedef enum { FD_INFO_MIXER, FD_INFO_STREAM, From 161c2c0c45bb10e8be1d58771297d4df672bfaa2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 2 Sep 2006 12:28:17 +0000 Subject: [PATCH 1259/1514] make esdcompat executable git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1360 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index 5043197c4..487b7ff7e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1272,6 +1272,7 @@ esdcompat: daemon/esdcompat.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@PACKAGE_NAME\@,$(PACKAGE_NAME),g' \ -e 's,@PA_BINARY\@,$(PA_BINARY),g' < $< > $@ + chmod +x esdcompat client.conf: pulse/client.conf.in Makefile sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' < $< > $@ From 11b6c451b88099d2094183de5f4237ec578f4cfe Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 2 Sep 2006 12:28:40 +0000 Subject: [PATCH 1260/1514] fix esdcompat for non-gnu systems git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1361 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/esdcompat.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/daemon/esdcompat.in b/src/daemon/esdcompat.in index ece1f4f92..942389d2d 100755 --- a/src/daemon/esdcompat.in +++ b/src/daemon/esdcompat.in @@ -28,7 +28,7 @@ fail() { ARGS=" --log-target=syslog" -for N in $(seq $#) ; do +while [ "$#" -gt "0" ]; do case "$1" in "") From a00c3cb9afc3848fc3369b16a3187354176d3b99 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 2 Sep 2006 12:45:53 +0000 Subject: [PATCH 1261/1514] fix a few autoconf warnings (patch by Flameeyes) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1362 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 7d85b32ae..48b86cd31 100644 --- a/configure.ac +++ b/configure.ac @@ -143,9 +143,18 @@ AC_HEADER_STDC # POSIX AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \ - netinet/in_systm.h netinet/ip.h netinet/tcp.h pwd.h sched.h \ + netinet/in_systm.h netinet/tcp.h pwd.h sched.h \ sys/mman.h sys/resource.h sys/select.h sys/socket.h sys/wait.h \ syslog.h]) +AC_CHECK_HEADERS([netinet/ip.h], [], [], + [#include + #if HAVE_NETINET_IN_H + # include + #endif + #if HAVE_NETINET_IN_SYSTM_H + # include + #endif + ]) AC_CHECK_HEADERS([regex.h], [HAVE_REGEX=1], [HAVE_REGEX=0]) AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0]) From 6528b6b19efeacc72bcb93b1eb78547eac8bd98c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 2 Sep 2006 12:51:44 +0000 Subject: [PATCH 1262/1514] allow building when srcdir != builddir (patch from Flameeyes) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1363 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 487b7ff7e..22e0a5c9a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -995,7 +995,12 @@ SYMDEF_FILES = \ EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) -$(SYMDEF_FILES): modules/module-defs.h.m4 +modulesdirs: + $(mkdir_p) modules + $(mkdir_p) modules/gconf + $(mkdir_p) modules/rtp + +$(SYMDEF_FILES): modules/module-defs.h.m4 modulesdirs $(M4) -Dfname="$@" $< > $@ # Simple protocol From b01fabff657656ad29c3dcce80048cdac959f0fc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 2 Sep 2006 14:56:41 +0000 Subject: [PATCH 1263/1514] update acx_pthread.m4 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1364 fefdeb5f-60dc-0310-8127-8f9354f1896f --- acinclude.m4 | 217 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 177 insertions(+), 40 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index f3a4ac520..723eb87e4 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,6 +1,55 @@ -dnl Available from the GNU Autoconf Macro Archive at: -dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html +dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) dnl +dnl @summary figure out how to build C programs using POSIX threads +dnl +dnl This macro figures out how to build C programs using POSIX threads. +dnl It sets the PTHREAD_LIBS output variable to the threads library and +dnl linker flags, and the PTHREAD_CFLAGS output variable to any special +dnl C compiler flags that are needed. (The user can also force certain +dnl compiler flags/libs to be tested by setting these environment +dnl variables.) +dnl +dnl Also sets PTHREAD_CC to any special C compiler that is needed for +dnl multi-threaded programs (defaults to the value of CC otherwise). +dnl (This is necessary on AIX to use the special cc_r compiler alias.) +dnl +dnl NOTE: You are assumed to not only compile your program with these +dnl flags, but also link it with them as well. e.g. you should link +dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS +dnl $LIBS +dnl +dnl If you are only building threads programs, you may wish to use +dnl these variables in your default LIBS, CFLAGS, and CC: +dnl +dnl LIBS="$PTHREAD_LIBS $LIBS" +dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +dnl CC="$PTHREAD_CC" +dnl +dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute +dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to +dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +dnl +dnl ACTION-IF-FOUND is a list of shell commands to run if a threads +dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to +dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the +dnl default action will define HAVE_PTHREAD. +dnl +dnl Please let the authors know if this macro fails on any platform, or +dnl if you have any other suggestions or comments. This macro was based +dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with +dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros +dnl posted by Alejandro Forero Cuervo to the autoconf macro repository. +dnl We are also grateful for the helpful feedback of numerous users. +dnl +dnl @category InstalledPackages +dnl @author Steven G. Johnson +dnl @version 2006-05-29 +dnl @license GPLWithACException +dnl +dnl Checks for GCC shared/pthread inconsistency based on work by +dnl Marcin Owsiany + + AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE @@ -57,6 +106,7 @@ acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -m # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) @@ -66,13 +116,13 @@ case "${host_cpu}-${host_os}" in # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthread or + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: - acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" + acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" ;; esac @@ -142,54 +192,142 @@ if test "x$acx_pthread_ok" = xyes; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - # Detect AIX lossage: threads are created detached by default - # and the JOINABLE attribute has a nonstandard name (UNDETACHED). - AC_MSG_CHECKING([for joinable pthread attribute]) - AC_TRY_LINK([#include ], - [int attr=PTHREAD_CREATE_JOINABLE;], - ok=PTHREAD_CREATE_JOINABLE, ok=unknown) - if test x"$ok" = xunknown; then - AC_TRY_LINK([#include ], - [int attr=PTHREAD_CREATE_UNDETACHED;], - ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) - fi - if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then - AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, - [Define to the necessary symbol if this constant - uses a non-standard name on your system.]) - fi - AC_MSG_RESULT(${ok}) - if test x"$ok" = xunknown; then - AC_MSG_WARN([we do not know how to create joinable pthreads]) + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_TRY_LINK([#include ], [int attr=$attr; return attr;], + [attr_name=$attr; break]) + done + AC_MSG_RESULT($attr_name) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in - *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; - *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi - - AC_MSG_CHECKING([if pthread_yield is available]) - flag=no - AC_TRY_LINK([#include ], - [pthread_yield();], - [flag=yes]) - AC_MSG_RESULT(${flag}) - if test "x$flag" != xno; then - AC_DEFINE(HAVE_PTHREAD_YIELD, 1, - [Define to 1 if you have the 'pthread_yield' function.]) + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" + # More AIX lossage: must compile with xlc_r or cc_r + if test x"$GCC" != xyes; then + AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) + else + PTHREAD_CC=$CC + fi - # More AIX lossage: must compile with cc_r - AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) + # The next part tries to detect GCC inconsistency with -shared on some + # architectures and systems. The problem is that in certain + # configurations, when -shared is specified, GCC "forgets" to + # internally use various flags which are still necessary. + + AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies]) + check_inconsistencies=yes + case "${host_cpu}-${host_os}" in + *-darwin*) check_inconsistencies=no ;; + esac + if test x"$GCC" != xyes -o "x$check_inconsistencies" != xyes ; then + AC_MSG_RESULT([no]) + else + AC_MSG_RESULT([yes]) + + # In order not to create several levels of indentation, we test + # the value of "$ok" until we find out the cure or run out of + # ideas. + ok="no" + + # + # Prepare the flags + # + save_CFLAGS="$CFLAGS" + save_LIBS="$LIBS" + save_CC="$CC" + # Try with the flags determined by the earlier checks. + # + # -Wl,-z,defs forces link-time symbol resolution, so that the + # linking checks with -shared actually have any value + # + # FIXME: -fPIC is required for -shared on many architectures, + # so we specify it here, but the right way would probably be to + # properly detect whether it is actually required. + CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CC="$PTHREAD_CC" + + AC_MSG_CHECKING([whether -pthread is sufficient with -shared]) + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [ok=yes]) + + if test "x$ok" = xyes; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + + # + # Linux gcc on some architectures such as mips/mipsel forgets + # about -lpthread + # + if test x"$ok" = xno; then + AC_MSG_CHECKING([whether -lpthread fixes that]) + LIBS="-lpthread $PTHREAD_LIBS $save_LIBS" + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [ok=yes]) + + if test "x$ok" = xyes; then + AC_MSG_RESULT([yes]) + PTHREAD_LIBS="-lpthread $PTHREAD_LIBS" + else + AC_MSG_RESULT([no]) + fi + fi + # + # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc + # + if test x"$ok" = xno; then + AC_MSG_CHECKING([whether -lc_r fixes that]) + LIBS="-lc_r $PTHREAD_LIBS $save_LIBS" + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [ok=yes]) + + if test "x$ok" = xyes; then + AC_MSG_RESULT([yes]) + PTHREAD_LIBS="-lc_r $PTHREAD_LIBS" + else + AC_MSG_RESULT([no]) + fi + fi + if test x"$ok" = xno; then + # OK, we have run out of ideas + AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries]) + + # so it's not safe to assume that we may use pthreads + acx_pthread_ok=no + fi + + CFLAGS="$save_CFLAGS" + LIBS="$save_LIBS" + CC="$save_CC" + fi else PTHREAD_CC="$CC" fi @@ -208,7 +346,6 @@ else fi AC_LANG_RESTORE ])dnl ACX_PTHREAD - AC_DEFUN([AC_CHECK_DEFINE],[ AS_VAR_PUSHDEF([ac_var],[ac_cv_defined_$1_$2])dnl AC_CACHE_CHECK([for $1 in $2], ac_var, From e504e807ce43df0a7bc0bad1158e06aca31368c3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 2 Sep 2006 14:57:50 +0000 Subject: [PATCH 1264/1514] include PTRHEAD_LIBS in pkg-config file (patch from Flameeyes) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1365 fefdeb5f-60dc-0310-8127-8f9354f1896f --- libpulse.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libpulse.pc.in b/libpulse.pc.in index 45fec220d..0f01799b1 100644 --- a/libpulse.pc.in +++ b/libpulse.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: libpulse Description: Client Interface to PulseAudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpulse +Libs: -L${libdir} -lpulse @PTHREAD_LIBS@ Cflags: -D_REENTRANT -I${includedir} Requires: From 2536ba9279f681eb97ba51bdc3b5cadad7c5c5fc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 2 Sep 2006 14:59:12 +0000 Subject: [PATCH 1265/1514] rework handling of srcdir != builddir (patch from Flameeyes) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1366 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 22e0a5c9a..3dec5c1c6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,7 +42,7 @@ endif # Compiler/linker flags # ################################### -AM_CFLAGS = -I$(top_srcdir)/src +AM_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src/modules -I$(top_builddir)/src/modules/rtp -I$(top_builddir)/src/modules/gconf AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS AM_CFLAGS += $(LTDLINCL) AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) @@ -995,12 +995,8 @@ SYMDEF_FILES = \ EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) -modulesdirs: - $(mkdir_p) modules - $(mkdir_p) modules/gconf - $(mkdir_p) modules/rtp - -$(SYMDEF_FILES): modules/module-defs.h.m4 modulesdirs +$(SYMDEF_FILES): modules/module-defs.h.m4 + $(mkdir_p) modules/gconf modules/rtp $(M4) -Dfname="$@" $< > $@ # Simple protocol From 6db6c835ec450e4e70197f01e2fcf1b9c9d3e222 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 2 Sep 2006 15:18:56 +0000 Subject: [PATCH 1266/1514] add missing g_type_init() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1367 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/gconf-helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/gconf/gconf-helper.c b/src/modules/gconf/gconf-helper.c index 724548175..40724f4e6 100644 --- a/src/modules/gconf/gconf-helper.c +++ b/src/modules/gconf/gconf-helper.c @@ -97,6 +97,8 @@ int main(int argc, char *argv[]) { GConfClient *client; GSList *modules, *m; + g_type_init(); + if (!(client = gconf_client_get_default())) goto fail; From 8e7c2a3b0c2fd67802222b3f216bc67bb2c1fe70 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 4 Sep 2006 21:28:34 +0000 Subject: [PATCH 1267/1514] make pa_thread_self() return a sensible pointer on foreign threads git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1368 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/thread-posix.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index 2e8d6b68a..43ad2d52a 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -117,15 +117,32 @@ int pa_thread_join(pa_thread *t) { } pa_thread* pa_thread_self(void) { + pa_thread *t; + ASSERT_SUCCESS(pthread_once(&thread_tls_once, thread_tls_once_func)); - return pa_tls_get(thread_tls); + + if ((t = pa_tls_get(thread_tls))) + return t; + + /* This is a foreign thread, let's create a pthread structure to + * make sure that we can always return a sensible pointer */ + + t = pa_xnew(pa_thread, 1); + t->id = pthread_self(); + t->thread_func = NULL; + t->userdata = NULL; + AO_store_full(&t->running, 1); + + pa_tls_set(thread_tls, t); + + return t; } void pa_thread_yield(void) { #ifdef HAVE_PTHREAD_YIELD pthread_yield(); #else - sched_yield(); + ASSERT_SUCCESS(sched_yield()); #endif } From 813e95f3b88a8345f82a205126d94bbffeda57b9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 4 Sep 2006 21:29:17 +0000 Subject: [PATCH 1268/1514] port the threaded mainloop to our new abstract mutex/thread API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1369 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 + src/pulse/thread-mainloop.c | 329 +++++------------------------------- 2 files changed, 48 insertions(+), 287 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 3dec5c1c6..69c6ac341 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -619,10 +619,16 @@ if OS_IS_WIN32 libpulsecore_la_SOURCES += \ pulsecore/mutex-win32.c \ pulsecore/thread-win32.c +libpulse_la_SOURCES += \ + pulsecore/mutex-win32.c \ + pulsecore/thread-win32.c else libpulsecore_la_SOURCES += \ pulsecore/mutex-posix.c \ pulsecore/thread-posix.c +libpulse_la_SOURCES += \ + pulsecore/mutex-posix.c \ + pulsecore/thread-posix.c endif libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c index b1b180a08..060782b57 100644 --- a/src/pulse/thread-mainloop.c +++ b/src/pulse/thread-mainloop.c @@ -33,57 +33,31 @@ #include "../pulsecore/poll.h" #endif -#ifdef HAVE_PTHREAD -#include -#endif - -#ifdef HAVE_WINDOWS_H -#include -#endif - #include #include #include +#include +#include #include "mainloop.h" #include "thread-mainloop.h" -#if defined(HAVE_PTHREAD) || defined(OS_IS_WIN32) - struct pa_threaded_mainloop { pa_mainloop *real_mainloop; int n_waiting; - int thread_running; -#ifdef OS_IS_WIN32 - DWORD thread_id; - HANDLE thread; - CRITICAL_SECTION mutex; - pa_hashmap *cond_events; - HANDLE accept_cond; -#else - pthread_t thread_id; - pthread_mutex_t mutex; - pthread_cond_t cond, accept_cond; -#endif + pa_thread* thread; + pa_mutex* mutex; + pa_cond* cond, *accept_cond; }; static inline int in_worker(pa_threaded_mainloop *m) { -#ifdef OS_IS_WIN32 - return GetCurrentThreadId() == m->thread_id; -#else - return pthread_equal(pthread_self(), m->thread_id); -#endif + return pa_thread_self() == m->thread; } static int poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata) { -#ifdef OS_IS_WIN32 - CRITICAL_SECTION *mutex = userdata; -#else - pthread_mutex_t *mutex = userdata; -#endif - + pa_mutex *mutex = userdata; int r; assert(mutex); @@ -91,28 +65,14 @@ static int poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void /* Before entering poll() we unlock the mutex, so that * avahi_simple_poll_quit() can succeed from another thread. */ -#ifdef OS_IS_WIN32 - LeaveCriticalSection(mutex); -#else - pthread_mutex_unlock(mutex); -#endif - + pa_mutex_unlock(mutex); r = poll(ufds, nfds, timeout); - -#ifdef OS_IS_WIN32 - EnterCriticalSection(mutex); -#else - pthread_mutex_lock(mutex); -#endif + pa_mutex_lock(mutex); return r; } -#ifdef OS_IS_WIN32 -static DWORD WINAPI thread(void *userdata) { -#else -static void* thread(void *userdata) { -#endif +static void thread(void *userdata) { pa_threaded_mainloop *m = userdata; #ifndef OS_IS_WIN32 @@ -123,32 +83,15 @@ static void* thread(void *userdata) { pthread_sigmask(SIG_BLOCK, &mask, NULL); #endif -#ifdef OS_IS_WIN32 - EnterCriticalSection(&m->mutex); -#else - pthread_mutex_lock(&m->mutex); -#endif + pa_mutex_lock(m->mutex); pa_mainloop_run(m->real_mainloop, NULL); -#ifdef OS_IS_WIN32 - LeaveCriticalSection(&m->mutex); -#else - pthread_mutex_unlock(&m->mutex); -#endif - -#ifdef OS_IS_WIN32 - return 0; -#else - return NULL; -#endif + pa_mutex_unlock(m->mutex); } pa_threaded_mainloop *pa_threaded_mainloop_new(void) { pa_threaded_mainloop *m; -#ifndef OS_IS_WIN32 - pthread_mutexattr_t a; -#endif m = pa_xnew(pa_threaded_mainloop, 1); @@ -157,26 +100,13 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) { return NULL; } - pa_mainloop_set_poll_func(m->real_mainloop, poll_func, &m->mutex); + m->mutex = pa_mutex_new(1); + m->cond = pa_cond_new(); + m->accept_cond = pa_cond_new(); + m->thread = NULL; -#ifdef OS_IS_WIN32 - InitializeCriticalSection(&m->mutex); + pa_mainloop_set_poll_func(m->real_mainloop, poll_func, m->mutex); - m->cond_events = pa_hashmap_new(NULL, NULL); - assert(m->cond_events); - m->accept_cond = CreateEvent(NULL, FALSE, FALSE, NULL); - assert(m->accept_cond); -#else - pthread_mutexattr_init(&a); - pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&m->mutex, &a); - pthread_mutexattr_destroy(&a); - - pthread_cond_init(&m->cond, NULL); - pthread_cond_init(&m->accept_cond, NULL); -#endif - - m->thread_running = 0; m->n_waiting = 0; return m; @@ -186,22 +116,17 @@ void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread_running || !in_worker(m)); + assert((m->thread && !pa_thread_is_running(m->thread)) || !in_worker(m)); - if (m->thread_running) - pa_threaded_mainloop_stop(m); + pa_threaded_mainloop_stop(m); - if (m->real_mainloop) - pa_mainloop_free(m->real_mainloop); + pa_thread_free(m->thread); -#ifdef OS_IS_WIN32 - pa_hashmap_free(m->cond_events, NULL, NULL); - CloseHandle(m->accept_cond); -#else - pthread_mutex_destroy(&m->mutex); - pthread_cond_destroy(&m->cond); - pthread_cond_destroy(&m->accept_cond); -#endif + pa_mainloop_free(m->real_mainloop); + + pa_mutex_free(m->mutex); + pa_cond_free(m->cond); + pa_cond_free(m->accept_cond); pa_xfree(m); } @@ -209,36 +134,10 @@ void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { int pa_threaded_mainloop_start(pa_threaded_mainloop *m) { assert(m); - assert(!m->thread_running); + assert(!m->thread || !pa_thread_is_running(m->thread)); -#ifdef OS_IS_WIN32 - - EnterCriticalSection(&m->mutex); - - m->thread = CreateThread(NULL, 0, thread, m, 0, &m->thread_id); - if (!m->thread) { - LeaveCriticalSection(&m->mutex); + if (!(m->thread = pa_thread_new(thread, m))) return -1; - } - -#else - - pthread_mutex_lock(&m->mutex); - - if (pthread_create(&m->thread_id, NULL, thread, m) < 0) { - pthread_mutex_unlock(&m->mutex); - return -1; - } - -#endif - - m->thread_running = 1; - -#ifdef OS_IS_WIN32 - LeaveCriticalSection(&m->mutex); -#else - pthread_mutex_unlock(&m->mutex); -#endif return 0; } @@ -246,148 +145,55 @@ int pa_threaded_mainloop_start(pa_threaded_mainloop *m) { void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) { assert(m); - if (!m->thread_running) + if (!m->thread || !pa_thread_is_running(m->thread)) return; /* Make sure that this function is not called from the helper thread */ assert(!in_worker(m)); -#ifdef OS_IS_WIN32 - EnterCriticalSection(&m->mutex); -#else - pthread_mutex_lock(&m->mutex); -#endif - + pa_mutex_lock(m->mutex); pa_mainloop_quit(m->real_mainloop, 0); + pa_mutex_unlock(m->mutex); -#ifdef OS_IS_WIN32 - LeaveCriticalSection(&m->mutex); -#else - pthread_mutex_unlock(&m->mutex); -#endif - -#ifdef OS_IS_WIN32 - WaitForSingleObject(m->thread, INFINITE); - CloseHandle(m->thread); -#else - pthread_join(m->thread_id, NULL); -#endif - - m->thread_running = 0; - - return; + pa_thread_join(m->thread); } void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) { assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread_running || !in_worker(m)); + assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); -#ifdef OS_IS_WIN32 - EnterCriticalSection(&m->mutex); -#else - pthread_mutex_lock(&m->mutex); -#endif + pa_mutex_lock(m->mutex); } void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) { assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread_running || !in_worker(m)); + assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); -#ifdef OS_IS_WIN32 - LeaveCriticalSection(&m->mutex); -#else - pthread_mutex_unlock(&m->mutex); -#endif + pa_mutex_unlock(m->mutex); } void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) { -#ifdef OS_IS_WIN32 - void *iter; - const void *key; - HANDLE event; -#endif - assert(m); -#ifdef OS_IS_WIN32 + pa_cond_signal(m->cond, 1); - iter = NULL; - while (1) { - pa_hashmap_iterate(m->cond_events, &iter, &key); - if (key == NULL) - break; - event = (HANDLE)pa_hashmap_get(m->cond_events, key); - SetEvent(event); - } - -#else - - pthread_cond_broadcast(&m->cond); - -#endif - - if (wait_for_accept && m->n_waiting > 0) { - -#ifdef OS_IS_WIN32 - - /* This is just to make sure it's unsignaled */ - WaitForSingleObject(m->accept_cond, 0); - - LeaveCriticalSection(&m->mutex); - - WaitForSingleObject(m->accept_cond, INFINITE); - - EnterCriticalSection(&m->mutex); - -#else - - pthread_cond_wait(&m->accept_cond, &m->mutex); - -#endif - - } + if (wait_for_accept && m->n_waiting > 0) + pa_cond_wait(m->accept_cond, m->mutex); } void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { -#ifdef OS_IS_WIN32 - HANDLE event; - DWORD result; -#endif - assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread_running || !in_worker(m)); + assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); m->n_waiting ++; -#ifdef OS_IS_WIN32 - - event = CreateEvent(NULL, FALSE, FALSE, NULL); - assert(event); - - pa_hashmap_put(m->cond_events, event, event); - - LeaveCriticalSection(&m->mutex); - - result = WaitForSingleObject(event, INFINITE); - assert(result == WAIT_OBJECT_0); - - EnterCriticalSection(&m->mutex); - - pa_hashmap_remove(m->cond_events, event); - - CloseHandle(event); - -#else - - pthread_cond_wait(&m->cond, &m->mutex); - -#endif + pa_cond_wait(m->cond, m->mutex); assert(m->n_waiting > 0); m->n_waiting --; @@ -397,13 +203,9 @@ void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) { assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread_running || !in_worker(m)); + assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); -#ifdef OS_IS_WIN32 - SetEvent(m->accept_cond); -#else - pthread_cond_signal(&m->accept_cond); -#endif + pa_cond_signal(m->accept_cond, 0); } int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) { @@ -417,50 +219,3 @@ pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) { return pa_mainloop_get_api(m->real_mainloop); } - -#else /* defined(OS_IS_WIN32) || defined(HAVE_PTHREAD) */ - -pa_threaded_mainloop *pa_threaded_mainloop_new(void) { - pa_log_error("Threaded main loop not supported on this platform"); - return NULL; -} - -void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { - assert(0); -} - -int pa_threaded_mainloop_start(pa_threaded_mainloop *m) { - assert(0); - return -1; -} - -void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) { - assert(0); -} - -void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) { - assert(0); -} - -void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) { - assert(0); -} - -void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { - assert(0); -} - -void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_release) { - assert(0); -} - -int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) { - assert(0); -} - -pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) { - assert(0); - return NULL; -} - -#endif /* defined(OS_IS_WIN32) || defined(HAVE_PTHREAD) */ From 3be920d9aec656e7e34672558e85ba025a4059d0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 4 Sep 2006 22:04:33 +0000 Subject: [PATCH 1269/1514] fix pa_thread_is_running() for foreign threads; fix a memory leak for foreign threads git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1370 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/thread-posix.c | 26 +++++++++++++++++++++++++- src/tests/thread-test.c | 2 ++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index 43ad2d52a..1b9a94a3f 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -56,8 +57,18 @@ static pthread_once_t thread_tls_once = PTHREAD_ONCE_INIT; static pa_mutex *once_mutex; static pthread_once_t thread_once_once = PTHREAD_ONCE_INIT; +static void tls_free_cb(void *p) { + pa_thread *t = p; + + assert(t); + + if (!t->thread_func) + /* This is a foreign thread, we need to free the struct */ + pa_xfree(t); +} + static void thread_tls_once_func(void) { - thread_tls = pa_tls_new(NULL); + thread_tls = pa_tls_new(tls_free_cb); assert(thread_tls); } @@ -80,6 +91,8 @@ static void* internal_thread_func(void *userdata) { pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { pa_thread *t; + assert(thread_func); + t = pa_xnew(pa_thread, 1); t->thread_func = thread_func; t->userdata = userdata; @@ -99,6 +112,17 @@ int pa_thread_is_running(pa_thread *t) { AO_t r; assert(t); + if (!t->thread_func) { + /* Mhmm, this is a foreign thread, t->running is not + * necessarily valid. We misuse pthread_getschedparam() to + * check if the thread is valid. This might not be portable. */ + + int policy; + struct sched_param param; + + return pthread_getschedparam(t->id, &policy, ¶m) >= 0 || errno != ESRCH; + } + r = AO_load_full(&t->running); return r == 1 || r == 2; } diff --git a/src/tests/thread-test.c b/src/tests/thread-test.c index 120d25542..9e8afd9bb 100644 --- a/src/tests/thread-test.c +++ b/src/tests/thread-test.c @@ -87,6 +87,8 @@ int main(int argc, char *argv[]) { int i, k; pa_thread* t[THREADS_MAX]; + assert(pa_thread_is_running(pa_thread_self())); + mutex = pa_mutex_new(0); cond1 = pa_cond_new(); cond2 = pa_cond_new(); From 6bbfb43f2ac597c2d1ba95b0c4b7c9619dcb9a35 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 4 Sep 2006 22:15:15 +0000 Subject: [PATCH 1270/1514] add accessor functions for the userdata attached to a pa_thread object git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1371 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/thread-posix.c | 12 ++++++++++++ src/pulsecore/thread.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index 1b9a94a3f..a2cb9b56c 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -162,6 +162,18 @@ pa_thread* pa_thread_self(void) { return t; } +void* pa_thread_get_data(pa_thread *t) { + assert(t); + + return t->userdata; +} + +void pa_thread_set_data(pa_thread *t, void *userdata) { + assert(t); + + t->userdata = userdata; +} + void pa_thread_yield(void) { #ifdef HAVE_PTHREAD_YIELD pthread_yield(); diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h index 8aabecfa1..e50a707f3 100644 --- a/src/pulsecore/thread.h +++ b/src/pulsecore/thread.h @@ -40,6 +40,9 @@ pa_thread *pa_thread_self(void); void pa_thread_yield(void); void pa_thread_once(pa_thread_once_t *control, pa_thread_once_func_t once_func); +void* pa_thread_get_data(pa_thread *t); +void pa_thread_set_data(pa_thread *t, void *userdata); + typedef struct pa_tls pa_tls; pa_tls* pa_tls_new(pa_free_cb_t free_cb); From e00ba020cb712aee50c591fc66c6bc2ab3659deb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 4 Sep 2006 22:38:41 +0000 Subject: [PATCH 1271/1514] remove yet another occurence of pthread_yield() by pa_thread_yield() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1372 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/interpol-test.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c index 3ec8a18f7..54bdd7750 100644 --- a/src/tests/interpol-test.c +++ b/src/tests/interpol-test.c @@ -33,17 +33,11 @@ #include #include -#ifdef HAVE_PTHREAD -#include -#endif - -#ifdef HAVE_WINDOWS_H -#include -#endif - #include #include +#include + static pa_context *context = NULL; static pa_stream *stream = NULL; static pa_mainloop_api *mainloop_api = NULL; @@ -152,13 +146,7 @@ int main(int argc, char *argv[]) { tv = now; while (pa_timeval_diff(pa_gettimeofday(&now), &tv) < 1000) -#ifdef HAVE_PTHREAD_YIELD - pthread_yield(); -#elif defined(OS_IS_WIN32) - Sleep(0); -#else - ; -#endif + pa_thread_yield(); } if (m) From 65691997782da950f1e2f38700321e635cc5f37c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Sep 2006 19:47:53 +0000 Subject: [PATCH 1272/1514] implement a few more ioctl()s, including a subset of SNDCTL_DSP_GETOPTR. Just enough to make JavaSound work. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1373 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp | 0 src/utils/padsp.c | 77 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 5 deletions(-) mode change 100644 => 100755 src/utils/padsp diff --git a/src/utils/padsp b/src/utils/padsp old mode 100644 new mode 100755 diff --git a/src/utils/padsp.c b/src/utils/padsp.c index dfef3f3ab..b20f0d064 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -93,6 +93,8 @@ struct fd_info { pa_cvolume sink_volume, source_volume; uint32_t sink_index, source_index; int volume_modify_count; + + int optr_n_blocks; PA_LLIST_FIELDS(fd_info); }; @@ -579,6 +581,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { i->volume_modify_count = 0; i->sink_index = (uint32_t) -1; i->source_index = (uint32_t) -1; + i->optr_n_blocks = 0; PA_LLIST_INIT(fd_info, i); reset_params(i); @@ -1952,6 +1955,8 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) free_streams(i); dsp_flush_socket(i); reset_params(i); + + i->optr_n_blocks = 0; pa_threaded_mainloop_unlock(i->mainloop); break; @@ -2040,14 +2045,76 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; } + case SOUND_PCM_READ_RATE: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_RATE\n"); + + pa_threaded_mainloop_lock(i->mainloop); + *(int*) argp = i->sample_spec.rate; + pa_threaded_mainloop_unlock(i->mainloop); + break; + + case SOUND_PCM_READ_CHANNELS: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_CHANNELS\n"); + + pa_threaded_mainloop_lock(i->mainloop); + *(int*) argp = i->sample_spec.channels; + pa_threaded_mainloop_unlock(i->mainloop); + break; + + case SOUND_PCM_READ_BITS: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_BITS\n"); + + pa_threaded_mainloop_lock(i->mainloop); + *(int*) argp = pa_sample_size(&i->sample_spec)*8; + pa_threaded_mainloop_unlock(i->mainloop); + break; + + case SNDCTL_DSP_GETOPTR: { + count_info *info; + + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n"); + + info = (count_info*) argp; + memset(info, 0, sizeof(*info)); + + pa_threaded_mainloop_lock(i->mainloop); + + for (;;) { + pa_usec_t usec; + + PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, exit_loop); + + if (pa_stream_get_time(i->play_stream, &usec) >= 0) { + size_t k = pa_usec_to_bytes(usec, &i->sample_spec); + int m; + + info->bytes = (int) k; + m = k / i->fragment_size; + info->blocks = m - i->optr_n_blocks; + i->optr_n_blocks = m; + + break; + } + + if (pa_context_errno(i->context) != PA_ERR_NODATA) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_get_latency(): %s\n", pa_strerror(pa_context_errno(i->context))); + break; + } + + pa_threaded_mainloop_wait(i->mainloop); + } + + pa_threaded_mainloop_unlock(i->mainloop); + + debug(DEBUG_LEVEL_NORMAL, __FILE__": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info->bytes, info->blocks, info->ptr); + + break; + } + case SNDCTL_DSP_GETIPTR: debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETIPTR\n"); goto inval; - - case SNDCTL_DSP_GETOPTR: - debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETOPTR\n"); - goto inval; - + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); From 66ec460845d2e3df08a447b3ba93ee1006b04846 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Sep 2006 21:37:09 +0000 Subject: [PATCH 1273/1514] fix a bogus debug line git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1374 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b20f0d064..883ffbd94 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2072,7 +2072,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETOPTR: { count_info *info; - debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n"); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOPTR\n"); info = (count_info*) argp; memset(info, 0, sizeof(*info)); From ead67cda48f58ad8d1f53ce2c32e3b500dfc5a19 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Sep 2006 22:19:11 +0000 Subject: [PATCH 1274/1514] fix indentation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1375 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 3b6434d77..63ee60ca8 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -58,10 +58,10 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { if (!shared) { if (!(pool = pa_mempool_new(shared))) { - pa_log("pa_mempool_new() failed."); + pa_log("pa_mempool_new() failed."); return NULL; } - } + } c = pa_xnew(pa_core, 1); From 40ecf869d0f77a3af2ce59bc060c4bccd2baec25 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Sep 2006 22:19:54 +0000 Subject: [PATCH 1275/1514] don't hit an assert in the client if posix shm is not available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1376 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index b700657b4..a458c6b10 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -98,6 +98,8 @@ static void unlock_autospawn_lock_file(pa_context *c) { } } +static void context_free(pa_context *c); + pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { pa_context *c; @@ -148,7 +150,16 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { #endif pa_client_conf_env(c->conf); - c->mempool = pa_mempool_new(!c->conf->disable_shm); + if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm))) { + + if (!c->conf->disable_shm) + c->mempool = pa_mempool_new(0); + + if (!c->mempool) { + context_free(c); + return NULL; + } + } return c; } @@ -178,7 +189,8 @@ static void context_free(pa_context *c) { if (c->playback_streams) pa_dynarray_free(c->playback_streams, NULL, NULL); - pa_mempool_free(c->mempool); + if (c->mempool) + pa_mempool_free(c->mempool); if (c->conf) pa_client_conf_free(c->conf); From 40f18d97f6e84e56e8792212f6078519609dec47 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 7 Sep 2006 13:29:59 +0000 Subject: [PATCH 1276/1514] fix alsa-sink example git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1377 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/default.pa.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index 031226693..a495f8907 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -20,7 +20,7 @@ ### Load audio drivers statically #load-module module-alsa-sink -#load-module module-alsa-source device=plughw:1,0 +#load-module module-alsa-source device=hw:1,0 #load-module module-oss device="/dev/dsp" sink_name=output source_name=input #load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #load-module module-null-sink From 0669c99fb6fedcd43af43466b7967b30b5af4f1d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 7 Sep 2006 13:31:53 +0000 Subject: [PATCH 1277/1514] add missing channel names (fixes a segfault when parsing invalid channel maps) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1378 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/channelmap.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c index a4f133723..69b09089c 100644 --- a/src/pulse/channelmap.c +++ b/src/pulse/channelmap.c @@ -68,6 +68,22 @@ const char *const table[] = { [PA_CHANNEL_POSITION_AUX13] = "aux13", [PA_CHANNEL_POSITION_AUX14] = "aux14", [PA_CHANNEL_POSITION_AUX15] = "aux15", + [PA_CHANNEL_POSITION_AUX16] = "aux16", + [PA_CHANNEL_POSITION_AUX17] = "aux17", + [PA_CHANNEL_POSITION_AUX18] = "aux18", + [PA_CHANNEL_POSITION_AUX19] = "aux19", + [PA_CHANNEL_POSITION_AUX20] = "aux20", + [PA_CHANNEL_POSITION_AUX21] = "aux21", + [PA_CHANNEL_POSITION_AUX22] = "aux22", + [PA_CHANNEL_POSITION_AUX23] = "aux23", + [PA_CHANNEL_POSITION_AUX24] = "aux24", + [PA_CHANNEL_POSITION_AUX25] = "aux25", + [PA_CHANNEL_POSITION_AUX26] = "aux26", + [PA_CHANNEL_POSITION_AUX27] = "aux27", + [PA_CHANNEL_POSITION_AUX28] = "aux28", + [PA_CHANNEL_POSITION_AUX29] = "aux29", + [PA_CHANNEL_POSITION_AUX30] = "aux30", + [PA_CHANNEL_POSITION_AUX31] = "aux31", [PA_CHANNEL_POSITION_TOP_CENTER] = "top-center", From 1728e3ac982146c0ff2d5e46571aadda6937e4fc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 7 Sep 2006 19:08:19 +0000 Subject: [PATCH 1278/1514] make pa_stream thread-safe: use new refcounting system, protect access using mutexes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1379 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pstream.c | 121 ++++++++++++++++++++++++++++++---------- 1 file changed, 93 insertions(+), 28 deletions(-) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 511972d98..566fb060a 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include "pstream.h" @@ -108,12 +110,13 @@ struct item_info { }; struct pa_pstream { - int ref; + PA_REFCNT_DECLARE; pa_mainloop_api *mainloop; pa_defer_event *defer_event; pa_iochannel *io; pa_queue *send_queue; + pa_mutex *mutex; int dead; @@ -163,11 +166,14 @@ static int do_read(pa_pstream *p); static void do_something(pa_pstream *p) { assert(p); - - p->mainloop->defer_enable(p->defer_event, 0); + assert(PA_REFCNT_VALUE(p) > 0); pa_pstream_ref(p); + pa_mutex_lock(p->mutex); + + p->mainloop->defer_enable(p->defer_event, 0); + if (!p->dead && pa_iochannel_is_readable(p->io)) { if (do_read(p) < 0) goto fail; @@ -179,6 +185,8 @@ static void do_something(pa_pstream *p) { goto fail; } + pa_mutex_unlock(p->mutex); + pa_pstream_unref(p); return; @@ -189,6 +197,8 @@ fail: if (p->die_callback) p->die_callback(p, p->die_callback_userdata); + pa_mutex_unlock(p->mutex); + pa_pstream_unref(p); } @@ -221,11 +231,13 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo assert(pool); p = pa_xnew(pa_pstream, 1); - p->ref = 1; + PA_REFCNT_INIT(p); p->io = io; pa_iochannel_set_callback(io, io_callback, p); p->dead = 0; + p->mutex = pa_mutex_new(1); + p->mainloop = m; p->defer_event = m->defer_new(m, defer_callback, p); m->defer_enable(p->defer_event, 0); @@ -297,6 +309,9 @@ static void pstream_free(pa_pstream *p) { if (p->read.packet) pa_packet_unref(p->read.packet); + if (p->mutex) + pa_mutex_free(p->mutex); + pa_xfree(p); } @@ -304,11 +319,13 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre struct item_info *i; assert(p); - assert(p->ref >= 1); + assert(PA_REFCNT_VALUE(p) > 0); assert(packet); + pa_mutex_lock(p->mutex); + if (p->dead) - return; + goto finish; i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; @@ -321,18 +338,24 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre pa_queue_push(p->send_queue, i); p->mainloop->defer_enable(p->defer_event, 1); + +finish: + + pa_mutex_unlock(p->mutex); } void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) { size_t length, idx; assert(p); - assert(p->ref >= 1); + assert(PA_REFCNT_VALUE(p) > 0); assert(channel != (uint32_t) -1); assert(chunk); + pa_mutex_lock(p->mutex); + if (p->dead) - return; + goto finish; length = chunk->length; idx = 0; @@ -363,6 +386,10 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa } p->mainloop->defer_enable(p->defer_event, 1); + +finish: + + pa_mutex_unlock(p->mutex); } static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata) { @@ -370,10 +397,12 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd pa_pstream *p = userdata; assert(p); - assert(p->ref >= 1); + assert(PA_REFCNT_VALUE(p) > 0); + + pa_mutex_lock(p->mutex); if (p->dead) - return; + goto finish; /* pa_log("Releasing block %u", block_id); */ @@ -386,6 +415,10 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd pa_queue_push(p->send_queue, item); p->mainloop->defer_enable(p->defer_event, 1); + +finish: + + pa_mutex_unlock(p->mutex); } static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) { @@ -393,10 +426,12 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda pa_pstream *p = userdata; assert(p); - assert(p->ref >= 1); + assert(PA_REFCNT_VALUE(p) > 0); + + pa_mutex_lock(p->mutex); if (p->dead) - return; + goto finish; /* pa_log("Revoking block %u", block_id); */ @@ -409,10 +444,15 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda pa_queue_push(p->send_queue, item); p->mainloop->defer_enable(p->defer_event, 1); + +finish: + + pa_mutex_unlock(p->mutex); } static void prepare_next_write_item(pa_pstream *p) { assert(p); + assert(PA_REFCNT_VALUE(p) > 0); if (!(p->write.current = pa_queue_pop(p->send_queue))) return; @@ -501,7 +541,9 @@ static int do_write(pa_pstream *p) { void *d; size_t l; ssize_t r; + assert(p); + assert(PA_REFCNT_VALUE(p) > 0); if (!p->write.current) prepare_next_write_item(p); @@ -552,8 +594,10 @@ static int do_read(pa_pstream *p) { void *d; size_t l; ssize_t r; + assert(p); - + assert(PA_REFCNT_VALUE(p) > 0); + if (p->read.index < PA_PSTREAM_DESCRIPTOR_SIZE) { d = (uint8_t*) p->read.descriptor + p->read.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->read.index; @@ -782,65 +826,83 @@ frame_done: void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { assert(p); - assert(p->ref >= 1); - + assert(PA_REFCNT_VALUE(p) > 0); + + pa_mutex_lock(p->mutex); p->die_callback = cb; p->die_callback_userdata = userdata; + pa_mutex_unlock(p->mutex); } - void pa_pstream_set_drain_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { assert(p); - assert(p->ref >= 1); + assert(PA_REFCNT_VALUE(p) > 0); + pa_mutex_lock(p->mutex); p->drain_callback = cb; p->drain_callback_userdata = userdata; + pa_mutex_unlock(p->mutex); } void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata) { assert(p); - assert(p->ref >= 1); + assert(PA_REFCNT_VALUE(p) > 0); + pa_mutex_lock(p->mutex); p->recieve_packet_callback = cb; p->recieve_packet_callback_userdata = userdata; + pa_mutex_unlock(p->mutex); } void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock_cb_t cb, void *userdata) { assert(p); - assert(p->ref >= 1); + assert(PA_REFCNT_VALUE(p) > 0); + pa_mutex_lock(p->mutex); p->recieve_memblock_callback = cb; p->recieve_memblock_callback_userdata = userdata; + pa_mutex_unlock(p->mutex); } int pa_pstream_is_pending(pa_pstream *p) { + int b; + assert(p); + assert(PA_REFCNT_VALUE(p) > 0); + + pa_mutex_lock(p->mutex); if (p->dead) - return 0; + b = 0; + else + b = p->write.current || !pa_queue_is_empty(p->send_queue); - return p->write.current || !pa_queue_is_empty(p->send_queue); + pa_mutex_unlock(p->mutex); + + return b; } void pa_pstream_unref(pa_pstream*p) { assert(p); - assert(p->ref >= 1); + assert(PA_REFCNT_VALUE(p) > 0); - if (--p->ref == 0) + if (PA_REFCNT_DEC(p) <= 0) pstream_free(p); } pa_pstream* pa_pstream_ref(pa_pstream*p) { assert(p); - assert(p->ref >= 1); + assert(PA_REFCNT_VALUE(p) > 0); - p->ref++; + PA_REFCNT_INC(p); return p; } void pa_pstream_close(pa_pstream *p) { assert(p); + pa_mutex_lock(p->mutex); + p->dead = 1; if (p->import) { @@ -868,12 +930,14 @@ void pa_pstream_close(pa_pstream *p) { p->recieve_packet_callback = NULL; p->recieve_memblock_callback = NULL; - + pa_mutex_unlock(p->mutex); } void pa_pstream_use_shm(pa_pstream *p, int enable) { assert(p); - assert(p->ref >= 1); + assert(PA_REFCNT_VALUE(p) > 0); + + pa_mutex_lock(p->mutex); p->use_shm = enable; @@ -888,6 +952,7 @@ void pa_pstream_use_shm(pa_pstream *p, int enable) { pa_memexport_free(p->export); p->export = NULL; } - } + + pa_mutex_unlock(p->mutex); } From 791bbd8e0e8b0a2350ee20321578f34ca026cd0e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 7 Sep 2006 20:17:25 +0000 Subject: [PATCH 1279/1514] don't maintain a list of allocated mempool slots, we don't use it anyway git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1380 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/memblock.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 70bcf677d..9cfd79b5e 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -101,7 +101,6 @@ struct pa_mempool { /* A list of free slots that may be reused */ PA_LLIST_HEAD(struct mempool_slot, free_slots); - PA_LLIST_HEAD(struct mempool_slot, used_slots); pa_mempool_stat stat; }; @@ -195,7 +194,6 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { return NULL; } - PA_LLIST_PREPEND(struct mempool_slot, p->used_slots, slot); return slot; } @@ -354,7 +352,6 @@ void pa_memblock_unref(pa_memblock*b) { slot = mempool_slot_by_ptr(b->pool, b->data); assert(slot); - PA_LLIST_REMOVE(struct mempool_slot, b->pool->used_slots, slot); PA_LLIST_PREPEND(struct mempool_slot, b->pool->free_slots, slot); if (b->type == PA_MEMBLOCK_POOL_EXTERNAL) @@ -471,7 +468,6 @@ pa_mempool* pa_mempool_new(int shared) { PA_LLIST_HEAD_INIT(pa_memimport, p->imports); PA_LLIST_HEAD_INIT(pa_memexport, p->exports); PA_LLIST_HEAD_INIT(struct mempool_slot, p->free_slots); - PA_LLIST_HEAD_INIT(struct mempool_slot, p->used_slots); memset(&p->stat, 0, sizeof(p->stat)); @@ -505,9 +501,8 @@ void pa_mempool_vacuum(pa_mempool *p) { assert(p); - for (slot = p->free_slots; slot; slot = slot->next) { + for (slot = p->free_slots; slot; slot = slot->next) pa_shm_punch(&p->memory, (uint8_t*) slot + sizeof(struct mempool_slot) - (uint8_t*) p->memory.ptr, p->block_size - sizeof(struct mempool_slot)); - } } int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) { From bfaa3584581c0d9f3acc7208a0d7ab13845124ab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Sep 2006 15:43:44 +0000 Subject: [PATCH 1280/1514] add a tiny wrapper around libatomic_ops: pa_atomic_int_t and pa_atomit_ptr_t. Reasoning: This wrapper fixes a few API issues I found with atomic_ops: * AO_t is an int, which can be written to with "=". pa_tomic_int_t however is a struct which due to type-safety enforces proper access with pa_atomic_xx(). (Inspired by the way the Linux kernel handles this) * AO_load()'s parameter is lacking a "const" * Explicitly choosing the proper memory barrier for each call is very difficult and especially hard to debug because most CPUs support only two different barrier types which the eight types defined by atomic_ops are mapped to. Most other software (i.e. glib, Linux kernel) which provides atomic variable access usually do a full barrier in all cases and so should we. Eventually we might choose to add additional memory barrier calls, in which case we can add special versions of the current function with special suffixes. * The function names are unnecesarily long * Atomic pointer accesses are only supported with manual casts. The new pa_atomic_xxx interface borrows heavily from the GLib and Linux kernel atomicity API, though it is different from both of them. In addition this abstract API makes it easy to port PA to different atomicty APIs, if libatomic_ops should ever become out-of-fashion or if the system OS supports atomic primitives anyway. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1381 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/atomic.h | 80 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/pulsecore/atomic.h diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h new file mode 100644 index 000000000..f789142d6 --- /dev/null +++ b/src/pulsecore/atomic.h @@ -0,0 +1,80 @@ +#ifndef foopulseatomichfoo +#define foopulseatomichfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +/* atomic_ops guarantees us that sizeof(AO_t) == sizeof(void*). + * + * It is not guaranteed however, that sizeof(AO_t) == sizeof(size_t). + * however very likely. */ + +typedef struct pa_atomic_int { + volatile AO_t value; +} pa_atomic_int_t; + +/* For now we do only full memory barriers. Eventually we might want + * to support more elaborate memory barriers, in which case we will add + * suffixes to the function names */ + +static inline int pa_atomic_load(const pa_atomic_int_t *a) { + return (int) AO_load_full((AO_t*) &a->value); +} + +static inline void pa_atomic_store(pa_atomic_int_t *a, int i) { + AO_store_full(&a->value, (AO_t) i); +} + +static inline int pa_atomic_add(pa_atomic_int_t *a, int i) { + return AO_fetch_and_add_full(&a->value, (AO_t) i); +} + +static inline int pa_atomic_inc(pa_atomic_int_t *a) { + return AO_fetch_and_add1_full(&a->value); +} + +static inline int pa_atomic_dec(pa_atomic_int_t *a) { + return AO_fetch_and_sub1_full(&a->value); +} + +static inline int pa_atomic_cmpxchg(pa_atomic_int_t *a, int old_i, int new_i) { + return AO_compare_and_swap_full(&a->value, old_i, new_i); +} + +typedef struct pa_atomic_ptr { + volatile AO_t value; +} pa_atomic_ptr_t; + +static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { + return (void*) AO_load_full((AO_t*) &a->value); +} + +static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { + AO_store_full(&a->value, (AO_t) p); +} + +static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { + return AO_compare_and_swap_full(&a->value, (AO_t) old_p, (AO_t) new_p); +} + +#endif From ee40a3439f33186f2c14237cbd1dab4a88bd1b10 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 21:05:31 +0000 Subject: [PATCH 1281/1514] implement a simple lock-free free list git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1382 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/flist.c | 226 ++++++++++++++++++++++++++++++++++++++++++ src/pulsecore/flist.h | 39 ++++++++ 2 files changed, 265 insertions(+) create mode 100644 src/pulsecore/flist.c create mode 100644 src/pulsecore/flist.h diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c new file mode 100644 index 000000000..cfeeac22f --- /dev/null +++ b/src/pulsecore/flist.c @@ -0,0 +1,226 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include + +#include "flist.h" + +/* Algorithm is not perfect, in a few corner cases it will fail to pop + * from the flist although it isn't empty, and fail to push into the + * flist, although it isn't full. + * + * We keep a fixed size array of entries, each item is either marked + * UNUSED, USED or BUSY and contains a user data pointer. When pushing + * into the queue we look for an UNUSED cell and mark it BUSY with a + * CAS operation. If successful we use it and mark it USED, otherwise + * we go on and look for the next UNUSED cell. The algorithm for + * popping an item from the queue is practically inverse: look for a + * USED cell and and mark it BUSY with a CAS operation, after reading + * from it mark it UNUSED again. + * + * To accelerate finding of used/unused cells we maintain a read and a + * write index which is used like a ring buffer. After each push we + * increase the write index and after each pop we increase the read + * index. + * + * The indexes are incremented atomically and are never truncated to + * the buffer size. Instead we assume that the buffer size is a power + * of two and that the truncation can thus be done by applying a + * simple AND on read. + * + * To make sure that we do not look for empty cells indefinitely we + * maintain a length value which stores the number of used cells. From + * this value the number of unused cells is easily calculated. Please + * note that the length value is not updated atomically with the read + * and write index and might thus be a few cells off the real + * value. To deal with this we always look for N_EXTRA_SCAN extra + * cells when pushing/popping entries. + * + * It might make sense to replace this implementation with a link list + * stack or queue, which however requires DCAS to be simple. Patches + * welcome. + * + * Please note that this algorithm is home grown.*/ + +#define FLIST_SIZE 128 +#define N_EXTRA_SCAN 2 + +/* For debugging purposes we can define _Y to put and extra thread + * yield between each operation. */ + +#ifdef PROFILE +#define _Y pa_thread_yield() +#else +#define _Y do { } while(0) +#endif + +enum { + STATE_UNUSED, + STATE_USED, + STATE_BUSY +}; + +struct cell { + pa_atomic_int_t state; + void *data; +}; + +struct pa_flist { + struct cell *cells; + unsigned size; + pa_atomic_int_t length; + pa_atomic_int_t read_idx; + pa_atomic_int_t write_idx; +}; + +static int is_power_of_two(unsigned size) { + return !(size & (size - 1)); +} + +pa_flist *pa_flist_new(unsigned size) { + pa_flist *l; + + if (!size) + size = FLIST_SIZE; + + assert(is_power_of_two(size)); + + l = pa_xnew(pa_flist, 1); + + l->size = size; + l->cells = pa_xnew0(struct cell, size); + + pa_atomic_store(&l->read_idx, 0); + pa_atomic_store(&l->write_idx, 0); + pa_atomic_store(&l->length, 0); + + return l; +} + +static int reduce(pa_flist *l, int value) { + return value & (unsigned) (l->size - 1); +} + +void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) { + assert(l); + + if (free_cb) { + int len, idx; + + idx = reduce(l, pa_atomic_load(&l->read_idx)); + len = pa_atomic_load(&l->length); + + for (; len > 0; len--) { + + if (pa_atomic_load(&l->cells[idx].state) == STATE_USED) + free_cb(l->cells[idx].data); + + idx = reduce(l, idx + 1); + } + } + + pa_xfree(l->cells); + pa_xfree(l); +} + +int pa_flist_push(pa_flist*l, void *p) { + int idx, len, n; + + assert(l); + assert(p); + + n = len = (int) l->size - pa_atomic_load(&l->length) + N_EXTRA_SCAN; + _Y; + idx = reduce(l, pa_atomic_load(&l->write_idx)); + + for (; n > 0 ; n--) { + _Y; + + if (pa_atomic_cmpxchg(&l->cells[idx].state, STATE_UNUSED, STATE_BUSY)) { + _Y; + pa_atomic_inc(&l->write_idx); + _Y; + l->cells[idx].data = p; + _Y; + pa_atomic_store(&l->cells[idx].state, STATE_USED); + _Y; + pa_atomic_inc(&l->length); + return 0; + } + + _Y; + idx = reduce(l, idx + 1); + } + +#ifdef PROFILE + if (len > N_EXTRA_SCAN) + pa_log("WARNING: Didn't find free cell after %u iterations.", len); +#endif + + return -1; +} + +void* pa_flist_pop(pa_flist*l) { + int idx, len, n; + + assert(l); + + n = len = pa_atomic_load(&l->length) + N_EXTRA_SCAN; + _Y; + idx = reduce(l, pa_atomic_load(&l->read_idx)); + + for (; n > 0 ; n--) { + _Y; + + if (pa_atomic_cmpxchg(&l->cells[idx].state, STATE_USED, STATE_BUSY)) { + void *p; + _Y; + pa_atomic_inc(&l->read_idx); + _Y; + p = l->cells[idx].data; + _Y; + pa_atomic_store(&l->cells[idx].state, STATE_UNUSED); + _Y; + + pa_atomic_dec(&l->length); + return p; + } + + _Y; + idx = reduce(l, idx+1); + } + +#ifdef PROFILE + if (len > N_EXTRA_SCAN) + pa_log("WARNING: Didn't find used cell after %u iterations.", len); +#endif + + return NULL; +} diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h new file mode 100644 index 000000000..57c9598b2 --- /dev/null +++ b/src/pulsecore/flist.h @@ -0,0 +1,39 @@ +#ifndef foopulseflisthfoo +#define foopulseflisthfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +/* A multiple-reader multipler-write lock-free free list implementation */ + +typedef struct pa_flist pa_flist; + +/* Size is required to be a power of two, or 0 for the default size */ +pa_flist * pa_flist_new(unsigned size); +void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb); + +/* Please note that this routine might fail! */ +int pa_flist_push(pa_flist*l, void *p); +void* pa_flist_pop(pa_flist*l); + +#endif From b93fedd49c95675ed8ce089b94b2b3bcfd903565 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 21:09:55 +0000 Subject: [PATCH 1282/1514] add a test program for the free list git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1383 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/flist-test.c | 104 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/tests/flist-test.c diff --git a/src/tests/flist-test.c b/src/tests/flist-test.c new file mode 100644 index 000000000..b0404449c --- /dev/null +++ b/src/tests/flist-test.c @@ -0,0 +1,104 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define THREADS_MAX 20 + +static pa_flist *flist; +static int quit = 0; + +static void spin(void) { + int k; + + /* Spin a little */ + k = rand() % 10000; + for (; k > 0; k--) + pa_thread_yield(); +} + +static void thread_func(void *data) { + char *s = data; + int n = 0; + int b = 1; + + while (!quit) { + char *text, *t; + + /* Allocate some memory, if possible take it from the flist */ + if (b && (text = pa_flist_pop(flist))) + pa_log("%s: popped '%s'", s, text); + else { + text = pa_sprintf_malloc("Block %i, allocated by %s", n++, s); + pa_log("%s: allocated '%s'", s, text); + } + + b = !b; + + spin(); + + /* Give it back to the flist if possible */ + if (pa_flist_push(flist, text) < 0) { + pa_log("%s: failed to push back '%s'", s, text); + pa_xfree(text); + } else + pa_log("%s: pushed", s); + + spin(); + } + + if (pa_flist_push(flist, s) < 0) + pa_xfree(s); +} + +int main(int argc, char* argv[]) { + pa_thread *threads[THREADS_MAX]; + int i; + + flist = pa_flist_new(0); + + for (i = 0; i < THREADS_MAX; i++) { + threads[i] = pa_thread_new(thread_func, pa_sprintf_malloc("Thread #%i", i+1)); + assert(threads[i]); + } + + sleep(60); + quit = 1; + + for (i = 0; i < THREADS_MAX; i++) + pa_thread_free(threads[i]); + + pa_flist_free(flist, pa_xfree); + + return 0; +} From c89cb6a00f6ab862a047db1124486492e5e59f83 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 22:54:11 +0000 Subject: [PATCH 1283/1514] add static initializer PA_ATOMIC_INIT() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1384 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/atomic.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index f789142d6..8d608b5b6 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -33,6 +33,8 @@ typedef struct pa_atomic_int { volatile AO_t value; } pa_atomic_int_t; +#define PA_ATOMIC_INIT(v) { .value = (v) } + /* For now we do only full memory barriers. Eventually we might want * to support more elaborate memory barriers, in which case we will add * suffixes to the function names */ From 3426a399ccbaa60c03bf38f9fb788a6f12b888b0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 22:55:51 +0000 Subject: [PATCH 1284/1514] implement trival pa_once API based on atomic operations git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1385 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/once.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/pulsecore/once.h diff --git a/src/pulsecore/once.h b/src/pulsecore/once.h new file mode 100644 index 000000000..a82a3c860 --- /dev/null +++ b/src/pulsecore/once.h @@ -0,0 +1,42 @@ +#ifndef foopulseoncehfoo +#define foopulseoncehfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +typedef struct pa_once { + pa_atomic_int_t atomic; +} pa_once_t; + +#define PA_ONCE_INIT { PA_ATOMIC_INIT(0) } + +#define pa_once_test(o) (pa_atomic_cmpxchg(&(o)->atomic, 0, 1)) + +typedef void (*pa_once_func_t) (void); + +static inline void pa_once(pa_once_t *o, pa_once_func_t f) { + if (pa_once_test(o)) + f(); +} + +#endif From 6d532029eaac08a3b60a28752f23f0586f895168 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 22:59:17 +0000 Subject: [PATCH 1285/1514] update for newer APIs: replace direct usage of libatomic_ops by usage of our own atomic.h; remove pa_once implementation; always use our pa_once implementation instead of the POSIX version git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1386 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/thread-posix.c | 51 +++++++++--------------------------- src/pulsecore/thread.h | 5 ---- 2 files changed, 13 insertions(+), 43 deletions(-) diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index a2cb9b56c..d69790a53 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -28,10 +28,10 @@ #include #include -#include - #include #include +#include +#include #include "thread.h" @@ -44,7 +44,7 @@ struct pa_thread { pthread_t id; pa_thread_func_t thread_func; void *userdata; - AO_t running; + pa_atomic_int_t running; }; struct pa_tls { @@ -52,10 +52,7 @@ struct pa_tls { }; static pa_tls *thread_tls; -static pthread_once_t thread_tls_once = PTHREAD_ONCE_INIT; - -static pa_mutex *once_mutex; -static pthread_once_t thread_once_once = PTHREAD_ONCE_INIT; +static pa_once_t thread_tls_once = PA_ONCE_INIT; static void tls_free_cb(void *p) { pa_thread *t = p; @@ -78,12 +75,13 @@ static void* internal_thread_func(void *userdata) { t->id = pthread_self(); - ASSERT_SUCCESS(pthread_once(&thread_tls_once, thread_tls_once_func)); + pa_once(&thread_tls_once, thread_tls_once_func); + pa_tls_set(thread_tls, t); - AO_fetch_and_add1_full(&t->running); + pa_atomic_inc(&t->running); t->thread_func(t->userdata); - AO_fetch_and_add_full(&t->running, (AO_t) -2); + pa_atomic_add(&t->running, -2); return NULL; } @@ -96,20 +94,19 @@ pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { t = pa_xnew(pa_thread, 1); t->thread_func = thread_func; t->userdata = userdata; - AO_store_full(&t->running, 0); + pa_atomic_store(&t->running, 0); if (pthread_create(&t->id, NULL, internal_thread_func, t) < 0) { pa_xfree(t); return NULL; } - AO_fetch_and_add1_full(&t->running); + pa_atomic_inc(&t->running); return t; } int pa_thread_is_running(pa_thread *t) { - AO_t r; assert(t); if (!t->thread_func) { @@ -123,8 +120,7 @@ int pa_thread_is_running(pa_thread *t) { return pthread_getschedparam(t->id, &policy, ¶m) >= 0 || errno != ESRCH; } - r = AO_load_full(&t->running); - return r == 1 || r == 2; + return pa_atomic_load(&t->running) > 0; } void pa_thread_free(pa_thread *t) { @@ -143,7 +139,7 @@ int pa_thread_join(pa_thread *t) { pa_thread* pa_thread_self(void) { pa_thread *t; - ASSERT_SUCCESS(pthread_once(&thread_tls_once, thread_tls_once_func)); + pa_once(&thread_tls_once, thread_tls_once_func); if ((t = pa_tls_get(thread_tls))) return t; @@ -155,7 +151,7 @@ pa_thread* pa_thread_self(void) { t->id = pthread_self(); t->thread_func = NULL; t->userdata = NULL; - AO_store_full(&t->running, 1); + pa_atomic_store(&t->running, 2); pa_tls_set(thread_tls, t); @@ -182,27 +178,6 @@ void pa_thread_yield(void) { #endif } -static void thread_once_once_func(void) { - once_mutex = pa_mutex_new(0); - assert(once_mutex); -} - -void pa_thread_once(pa_thread_once_t *control, pa_thread_once_func_t once_func) { - assert(control); - assert(once_func); - - ASSERT_SUCCESS(pthread_once(&thread_once_once, thread_once_once_func)); - - pa_mutex_lock(once_mutex); - - if (*control == PA_THREAD_ONCE_INIT) { - *control = ~PA_THREAD_ONCE_INIT; - pa_mutex_unlock(once_mutex); - once_func(); - } else - pa_mutex_unlock(once_mutex); -} - pa_tls* pa_tls_new(pa_free_cb_t free_cb) { pa_tls *t; diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h index e50a707f3..d08990a20 100644 --- a/src/pulsecore/thread.h +++ b/src/pulsecore/thread.h @@ -24,13 +24,9 @@ #include -#define PA_THREAD_ONCE_INIT 0 - typedef struct pa_thread pa_thread; typedef void (*pa_thread_func_t) (void *userdata); -typedef void (*pa_thread_once_func_t) (void); -typedef unsigned int pa_thread_once_t; pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata); void pa_thread_free(pa_thread *t); @@ -38,7 +34,6 @@ int pa_thread_join(pa_thread *t); int pa_thread_is_running(pa_thread *t); pa_thread *pa_thread_self(void); void pa_thread_yield(void); -void pa_thread_once(pa_thread_once_t *control, pa_thread_once_func_t once_func); void* pa_thread_get_data(pa_thread *t); void pa_thread_set_data(pa_thread *t, void *userdata); From d0dcde060bb3e5fd04512d16afdd1ed71e780e08 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 23:54:19 +0000 Subject: [PATCH 1286/1514] rework pa_once once again, because the once function needs to have terminated before pa_once returns, regardless whether the local call executes it or another thread does. With the previous code it might happen that an long-running initializing in a once function is not terminated yet when another thread thinks it already is. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1387 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/once-posix.c | 69 ++++++++++++++++++++++++++++++++++++++ src/pulsecore/once.h | 14 +++----- 2 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 src/pulsecore/once-posix.c diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c new file mode 100644 index 000000000..865997df3 --- /dev/null +++ b/src/pulsecore/once-posix.c @@ -0,0 +1,69 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +#include "once.h" + +#define ASSERT_SUCCESS(x) do { \ + int _r = (x); \ + assert(_r == 0); \ +} while(0) + +static pa_mutex *global_mutex; +static pthread_once_t global_mutex_once = PTHREAD_ONCE_INIT; + +static void global_mutex_once_func(void) { + global_mutex = pa_mutex_new(0); +} + +void pa_once(pa_once_t *control, pa_once_func_t func) { + assert(control); + assert(func); + + /* Create the global mutex */ + ASSERT_SUCCESS(pthread_once(&global_mutex_once, global_mutex_once_func)); + + /* Create the local mutex */ + pa_mutex_lock(global_mutex); + if (!control->mutex) + control->mutex = pa_mutex_new(1); + pa_mutex_unlock(global_mutex); + + /* Execute function */ + pa_mutex_lock(control->mutex); + if (!control->once_value) { + control->once_value = 1; + func(); + } + pa_mutex_unlock(control->mutex); + + /* Caveat: We have to make sure that the once func has completed + * before returning, even if the once func is not actually + * executed by us. Hence the awkward locking. */ +} diff --git a/src/pulsecore/once.h b/src/pulsecore/once.h index a82a3c860..0aabb3f29 100644 --- a/src/pulsecore/once.h +++ b/src/pulsecore/once.h @@ -22,21 +22,17 @@ USA. ***/ -#include +#include typedef struct pa_once { - pa_atomic_int_t atomic; + unsigned int once_value; + pa_mutex *mutex; } pa_once_t; -#define PA_ONCE_INIT { PA_ATOMIC_INIT(0) } - -#define pa_once_test(o) (pa_atomic_cmpxchg(&(o)->atomic, 0, 1)) +#define PA_ONCE_INIT { .once_value = 0, .mutex = NULL } typedef void (*pa_once_func_t) (void); -static inline void pa_once(pa_once_t *o, pa_once_func_t f) { - if (pa_once_test(o)) - f(); -} +void pa_once(pa_once_t *o, pa_once_func_t f); #endif From 3ae98db1aa01cfe68ed55f303fecf9c9bbcb4438 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 23:54:56 +0000 Subject: [PATCH 1287/1514] add pa_once testing code git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1388 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/thread-test.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tests/thread-test.c b/src/tests/thread-test.c index 9e8afd9bb..9559cdbbb 100644 --- a/src/tests/thread-test.c +++ b/src/tests/thread-test.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -37,6 +38,12 @@ static int magic_number = 0; #define THREADS_MAX 20 +static void once_func(void) { + pa_log("once!"); +} + +static pa_once_t once = PA_ONCE_INIT; + static void thread_func(void *data) { pa_tls_set(tls, data); @@ -65,6 +72,8 @@ static void thread_func(void *data) { pa_mutex_unlock(mutex); + pa_once(&once, once_func); + pa_cond_signal(cond2, 0); pa_log("%s got number %i", (char*) pa_tls_get(tls), k); From 0e96d8b7bc8be2621867fbd38a455ca1a3724abc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 23:55:58 +0000 Subject: [PATCH 1288/1514] make pa_mutex_new() and pa_cond_new() succeed in all cases. Similar behaviour to pa_xmalloc(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1389 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/mutex-posix.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c index 6f0e73365..094d637d9 100644 --- a/src/pulsecore/mutex-posix.c +++ b/src/pulsecore/mutex-posix.c @@ -52,16 +52,11 @@ pa_mutex* pa_mutex_new(int recursive) { pthread_mutexattr_init(&attr); if (recursive) - if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) < 0) - return NULL; + ASSERT_SUCCESS(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)); m = pa_xnew(pa_mutex, 1); - if (pthread_mutex_init(&m->mutex, &attr) < 0) { - pa_xfree(m); - return NULL; - } - + ASSERT_SUCCESS(pthread_mutex_init(&m->mutex, &attr)); return m; } @@ -84,17 +79,12 @@ void pa_mutex_unlock(pa_mutex *m) { ASSERT_SUCCESS(pthread_mutex_unlock(&m->mutex)); } - pa_cond *pa_cond_new(void) { pa_cond *c; c = pa_xnew(pa_cond, 1); - if (pthread_cond_init(&c->cond, NULL) < 0) { - pa_xfree(c); - return NULL; - } - + ASSERT_SUCCESS(pthread_cond_init(&c->cond, NULL)); return c; } From 9358d28c21c5ea9bf8c288bd10d61eae4e3cc278 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 23:56:58 +0000 Subject: [PATCH 1289/1514] update Makefile git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1390 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 69c6ac341..aad6e26d3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -200,7 +200,8 @@ noinst_PROGRAMS = \ ipacl-test \ hook-list-test \ memblock-test \ - thread-test + thread-test \ + flist-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -250,11 +251,16 @@ memblock_test_CFLAGS = $(AM_CFLAGS) memblock_test_LDADD = $(AM_LDADD) libpulsecore.la memblock_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -thread_test_SOURCES = tests/thread-test.c +thread_test_SOURCES = tests/thread-test.c pulse/xmalloc.c pulsecore/flist.c pulsecore/thread-posix.c pulsecore/mutex-posix.c pulsecore/log.c pulsecore/core-util.c pulse/util.c pulse/utf8.c pulsecore/core-error.c pulsecore/once-posix.c thread_test_CFLAGS = $(AM_CFLAGS) -thread_test_LDADD = $(AM_LDADD) libpulsecore.la +thread_test_LDADD = $(AM_LDADD) thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +flist_test_SOURCES = tests/flist-test.c pulse/xmalloc.c pulsecore/flist.c pulsecore/thread-posix.c pulsecore/mutex-posix.c pulsecore/log.c pulsecore/core-util.c pulse/util.c pulse/utf8.c pulsecore/core-error.c pulsecore/once-posix.c +flist_test_CFLAGS = $(AM_CFLAGS) +flist_test_LDADD = $(AM_LDADD) +flist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la @@ -625,10 +631,12 @@ libpulse_la_SOURCES += \ else libpulsecore_la_SOURCES += \ pulsecore/mutex-posix.c \ - pulsecore/thread-posix.c + pulsecore/thread-posix.c \ + pulsecore/once-posix.c libpulse_la_SOURCES += \ pulsecore/mutex-posix.c \ - pulsecore/thread-posix.c + pulsecore/thread-posix.c \ + pulecore/once-posix.c endif libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) From 6b1794dfba3c7b20e27d48636a802f5be3671b4b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 23:58:03 +0000 Subject: [PATCH 1290/1514] ignore flist-test git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1391 fefdeb5f-60dc-0310-8127-8f9354f1896f From fc08db23918286a6a985b6e7c9921915a006d652 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Sep 2006 23:59:26 +0000 Subject: [PATCH 1291/1514] ignore flist-test in the correct dir git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1392 fefdeb5f-60dc-0310-8127-8f9354f1896f From 7c6088d98a6399171c9abf108084c46de133f132 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 11 Sep 2006 07:14:39 +0000 Subject: [PATCH 1292/1514] Fix typo. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1393 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index aad6e26d3..7db0f8c70 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -636,7 +636,7 @@ libpulsecore_la_SOURCES += \ libpulse_la_SOURCES += \ pulsecore/mutex-posix.c \ pulsecore/thread-posix.c \ - pulecore/once-posix.c + pulsecore/once-posix.c endif libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) From a85b3e2dd49adc5addab25e5ceeb8eb56e283e48 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 11 Sep 2006 07:54:41 +0000 Subject: [PATCH 1293/1514] Use platform independent sleep. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1394 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/flist-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tests/flist-test.c b/src/tests/flist-test.c index b0404449c..abc0659d9 100644 --- a/src/tests/flist-test.c +++ b/src/tests/flist-test.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -92,7 +93,7 @@ int main(int argc, char* argv[]) { assert(threads[i]); } - sleep(60); + pa_msleep(60000); quit = 1; for (i = 0; i < THREADS_MAX; i++) From 772645922a450f5d366bd6e077a44582e7a7b79f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 11 Sep 2006 07:56:03 +0000 Subject: [PATCH 1294/1514] Fix up build structure for platform dependent modules. Also add implementation on Win32 for pa_once(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1395 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 50 +++++++++++++-------------- src/pulsecore/once-win32.c | 67 ++++++++++++++++++++++++++++++++++++ src/pulsecore/thread-win32.c | 35 ++++--------------- 3 files changed, 96 insertions(+), 56 deletions(-) create mode 100644 src/pulsecore/once-win32.c diff --git a/src/Makefile.am b/src/Makefile.am index 7db0f8c70..c04507dcd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -70,6 +70,18 @@ AM_LDFLAGS+=-Wl,--export-all-symbols WINSOCK_LIBS=-lwsock32 -lws2_32 -lwininet endif +if OS_IS_WIN32 +PA_THREAD_OBJS = \ + pulsecore/once-win32.c pulsecore/once.h \ + pulsecore/mutex-win32.c pulsecore/mutex.h \ + pulsecore/thread-win32.c pulsecore/thread.h +else +PA_THREAD_OBJS = \ + pulsecore/once-posix.c pulsecore/once.h \ + pulsecore/mutex-posix.c pulsecore/mutex.h \ + pulsecore/thread-posix.c pulsecore/thread.h +endif + ################################### # Extra files # ################################### @@ -251,14 +263,15 @@ memblock_test_CFLAGS = $(AM_CFLAGS) memblock_test_LDADD = $(AM_LDADD) libpulsecore.la memblock_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -thread_test_SOURCES = tests/thread-test.c pulse/xmalloc.c pulsecore/flist.c pulsecore/thread-posix.c pulsecore/mutex-posix.c pulsecore/log.c pulsecore/core-util.c pulse/util.c pulse/utf8.c pulsecore/core-error.c pulsecore/once-posix.c +thread_test_SOURCES = tests/thread-test.c thread_test_CFLAGS = $(AM_CFLAGS) -thread_test_LDADD = $(AM_LDADD) +thread_test_LDADD = $(AM_LDADD) libpulsecore.la thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -flist_test_SOURCES = tests/flist-test.c pulse/xmalloc.c pulsecore/flist.c pulsecore/thread-posix.c pulsecore/mutex-posix.c pulsecore/log.c pulsecore/core-util.c pulse/util.c pulse/utf8.c pulsecore/core-error.c pulsecore/once-posix.c +flist_test_SOURCES = tests/flist-test.c \ + pulsecore/flist.c pulsecore/flist.h flist_test_CFLAGS = $(AM_CFLAGS) -flist_test_LDADD = $(AM_LDADD) +flist_test_LDADD = $(AM_LDADD) libpulsecore.la flist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mcalign_test_SOURCES = tests/mcalign-test.c @@ -434,7 +447,8 @@ libpulse_la_SOURCES += \ pulsecore/tagstruct.c pulsecore/tagstruct.h \ pulsecore/core-error.c pulsecore/core-error.h \ pulsecore/winsock.h pulsecore/creds.h \ - pulsecore/shm.c pulsecore/shm.h + pulsecore/shm.c pulsecore/shm.h \ + $(PA_THREAD_OBJS) if OS_IS_WIN32 libpulse_la_SOURCES += \ @@ -544,7 +558,8 @@ pulsecoreinclude_HEADERS = \ pulsecore/llist.h \ pulsecore/refcnt.h \ pulsecore/mutex.h \ - pulsecore/thread.h + pulsecore/thread.h \ + pulsecore/once.h lib_LTLIBRARIES += libpulsecore.la @@ -586,7 +601,6 @@ libpulsecore_la_SOURCES += \ pulsecore/modargs.c pulsecore/modargs.h \ pulsecore/modinfo.c pulsecore/modinfo.h \ pulsecore/module.c pulsecore/module.h \ - pulsecore/mutex.h \ pulsecore/namereg.c pulsecore/namereg.h \ pulsecore/pid.c pulsecore/pid.h \ pulsecore/pipe.c pulsecore/pipe.h \ @@ -609,36 +623,18 @@ libpulsecore_la_SOURCES += \ pulsecore/source.c pulsecore/source.h \ pulsecore/source-output.c pulsecore/source-output.h \ pulsecore/strbuf.c pulsecore/strbuf.h \ - pulsecore/thread.h \ pulsecore/tokenizer.c pulsecore/tokenizer.h \ pulsecore/winsock.h \ pulsecore/core-error.c pulsecore/core-error.h \ pulsecore/hook-list.c pulsecore/hook-list.h \ - pulsecore/shm.c pulsecore/shm.h + pulsecore/shm.c pulsecore/shm.h \ + $(PA_THREAD_OBJS) if OS_IS_WIN32 libpulsecore_la_SOURCES += \ pulsecore/dllmain.c endif -if OS_IS_WIN32 -libpulsecore_la_SOURCES += \ - pulsecore/mutex-win32.c \ - pulsecore/thread-win32.c -libpulse_la_SOURCES += \ - pulsecore/mutex-win32.c \ - pulsecore/thread-win32.c -else -libpulsecore_la_SOURCES += \ - pulsecore/mutex-posix.c \ - pulsecore/thread-posix.c \ - pulsecore/once-posix.c -libpulse_la_SOURCES += \ - pulsecore/mutex-posix.c \ - pulsecore/thread-posix.c \ - pulsecore/once-posix.c -endif - libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) libpulsecore_la_LDFLAGS = -version-info $(LIBPULSECORE_VERSION_INFO) libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV) diff --git a/src/pulsecore/once-win32.c b/src/pulsecore/once-win32.c new file mode 100644 index 000000000..8b9282f42 --- /dev/null +++ b/src/pulsecore/once-win32.c @@ -0,0 +1,67 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +#include + +#include "once.h" + +void pa_once(pa_once_t *control, pa_once_func_t func) { + HANDLE mutex; + char name[64]; + + assert(control); + assert(func); + + /* Create the global mutex */ + sprintf(name, "pulse%d", (int)GetCurrentProcessId()); + + mutex = CreateMutex(NULL, FALSE, name); + assert(mutex); + + /* Create the local mutex */ + WaitForSingleObject(mutex, INFINITE); + if (!control->mutex) + control->mutex = pa_mutex_new(1); + ReleaseMutex(mutex); + + CloseHandle(mutex); + + /* Execute function */ + pa_mutex_lock(control->mutex); + if (!control->once_value) { + control->once_value = 1; + func(); + } + pa_mutex_unlock(control->mutex); + + /* Caveat: We have to make sure that the once func has completed + * before returning, even if the once func is not actually + * executed by us. Hence the awkward locking. */ +} diff --git a/src/pulsecore/thread-win32.c b/src/pulsecore/thread-win32.c index ee61d85aa..98ea06912 100644 --- a/src/pulsecore/thread-win32.c +++ b/src/pulsecore/thread-win32.c @@ -29,6 +29,7 @@ #include #include +#include #include "thread.h" @@ -50,9 +51,9 @@ struct pa_tls_monitor { }; static pa_tls *thread_tls; -static pa_thread_once_t thread_tls_once = PA_THREAD_ONCE_INIT; +static pa_once_t thread_tls_once = PA_ONCE_INIT; static pa_tls *monitor_tls; -static pa_thread_once_t monitor_tls_once = PA_THREAD_ONCE_INIT; +static pa_once_t monitor_tls_once = PA_ONCE_INIT; static void thread_tls_once_func(void) { thread_tls = pa_tls_new(NULL); @@ -63,7 +64,7 @@ static DWORD WINAPI internal_thread_func(LPVOID param) { pa_thread *t = param; assert(t); - pa_thread_once(&thread_tls_once, thread_tls_once_func); + pa_once(&thread_tls_once, thread_tls_once_func); pa_tls_set(thread_tls, t); t->thread_func(t->userdata); @@ -119,7 +120,7 @@ int pa_thread_join(pa_thread *t) { } pa_thread* pa_thread_self(void) { - pa_thread_once(&thread_tls_once, thread_tls_once_func); + pa_once(&thread_tls_once, thread_tls_once_func); return pa_tls_get(thread_tls); } @@ -127,30 +128,6 @@ void pa_thread_yield(void) { Sleep(0); } -void pa_thread_once(pa_thread_once_t *control, pa_thread_once_func_t once_func) { - HANDLE mutex; - char name[64]; - - assert(control); - assert(once_func); - - sprintf(name, "pulse%d", (int)GetCurrentProcessId()); - - mutex = CreateMutex(NULL, FALSE, name); - assert(mutex); - - WaitForSingleObject(mutex, INFINITE); - - if (*control == PA_THREAD_ONCE_INIT) { - *control = ~PA_THREAD_ONCE_INIT; - ReleaseMutex(mutex); - once_func(); - } else - ReleaseMutex(mutex); - - CloseHandle(mutex); -} - static void monitor_tls_once_func(void) { monitor_tls = pa_tls_new(NULL); assert(monitor_tls); @@ -212,7 +189,7 @@ void *pa_tls_set(pa_tls *t, void *userdata) { if (t->free_func) { struct pa_tls_monitor *m; - pa_thread_once(&monitor_tls_once, monitor_tls_once_func); + pa_once(&monitor_tls_once, monitor_tls_once_func); m = pa_tls_get(monitor_tls); if (!m) { From 5f828c2c3df6a788b5f8be3422bd355b91104791 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 14 Sep 2006 14:56:31 +0000 Subject: [PATCH 1295/1514] Fix debug output for SNDCTL_DSP_SETFRAGMENT. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1396 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 883ffbd94..d947f6977 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1875,7 +1875,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; case SNDCTL_DSP_SETFRAGMENT: - debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%8x\n", *(int*) argp); + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%08x\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); From 29ab939570ee739570a6bfaa6569bd6f6135df56 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 14 Sep 2006 16:00:57 +0000 Subject: [PATCH 1296/1514] Stop using x86-isms and use ISO C (oversized shifts are undefined). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1397 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index d947f6977..c7bfe5abd 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1879,7 +1879,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_lock(i->mainloop); - i->fragment_size = 1 << (*(int*) argp); + i->fragment_size = 1 << ((*(int*) argp) & 31); i->n_fragments = (*(int*) argp) >> 16; /* 0x7FFF means that we can set whatever we like */ From 534eeb181e264945968c841ba08f918efb473930 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 19 Sep 2006 07:49:39 +0000 Subject: [PATCH 1297/1514] No need to create these dirs as they're part of the source tree. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1398 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index c04507dcd..f7026c5fc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1006,7 +1006,6 @@ EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) $(SYMDEF_FILES): modules/module-defs.h.m4 - $(mkdir_p) modules/gconf modules/rtp $(M4) -Dfname="$@" $< > $@ # Simple protocol From 71a6ceb29bb7714389576d274216e1a275fa08aa Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 19 Sep 2006 07:54:53 +0000 Subject: [PATCH 1298/1514] Revert r1398 as it broke the srcdir != builddir patch. New fix that doesn't use the $(mkdir_p) define as it isn't present on many systems. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1399 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index f7026c5fc..dfe358513 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1006,6 +1006,9 @@ EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) $(SYMDEF_FILES): modules/module-defs.h.m4 + mkdir modules + mkdir modules/gconf + mkdir modules/rtp $(M4) -Dfname="$@" $< > $@ # Simple protocol From bf83a961d5b246b6aed1d52d27f37e4b745bf264 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 20 Sep 2006 19:01:59 +0000 Subject: [PATCH 1299/1514] rename default realtime group from "realtime" to "pulse-rt", since it is pulseaudio specific. you may still pass --with-realtime-group=realtime to configure to get the old behaviour git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1400 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 48b86cd31..2f09279c9 100644 --- a/configure.ac +++ b/configure.ac @@ -707,7 +707,7 @@ AC_DEFINE_UNQUOTED(PA_SYSTEM_GROUP,"$PA_SYSTEM_GROUP", [Group for the PulseAudio AC_ARG_WITH(realtime_group,AS_HELP_STRING([--with-realtime-group=],[Group for users that are allowed to start the PulseAudio daemon with realtime scheduling (realtime)])) if test -z "$with_realtime_group" ; then - PA_REALTIME_GROUP=realtime + PA_REALTIME_GROUP=pulse-rt else PA_REALTIME_GROUP=$with_realtime_group fi From f1021b9e0ba9727ff08009295dea28cc247b9d4f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 20 Sep 2006 19:02:45 +0000 Subject: [PATCH 1300/1514] enable module-hal-detect in the default configuration file only if HAL support is enabled (closes #30) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1401 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 +++- src/daemon/default.pa.in | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index dfe358513..64df8614d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1295,7 +1295,9 @@ default.pa: daemon/default.pa.win32 cp $< $@ else default.pa: daemon/default.pa.in Makefile - sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' < $< > $@ + sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' \ + -e 's,@HAVE_HAL_TRUE\@,@HAVE_HAL_TRUE@,g' \ + -e 's,@HAVE_HAL_FALSE\@,@HAVE_HAL_FALSE@,g' < $< > $@ endif daemon.conf: daemon/daemon.conf.in Makefile diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index a495f8907..af2a67893 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -27,11 +27,11 @@ #load-module module-pipe-sink ### Automatically load driver modules depending on the hardware available -load-module module-hal-detect +@HAVE_HAL_TRUE@load-module module-hal-detect ### Alternatively use the static hardware detection module (for systems that ### lack HAL support -#load-module module-detect +@HAVE_HAL_FALSE@load-module module-detect ### Load audio drivers automatically on access #add-autoload-sink output module-oss device="/dev/dsp" sink_name=output source_name=input From 736de36f6822d7ff85bb604ab749af88f8e19e12 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 26 Sep 2006 23:41:20 +0000 Subject: [PATCH 1301/1514] add asynchronous inter-thread notification API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1402 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/anotify.c | 143 ++++++++++++++++++++++++++++++++++++++++ src/pulsecore/anotify.h | 38 +++++++++++ 2 files changed, 181 insertions(+) create mode 100644 src/pulsecore/anotify.c create mode 100644 src/pulsecore/anotify.h diff --git a/src/pulsecore/anotify.c b/src/pulsecore/anotify.c new file mode 100644 index 000000000..a61f84426 --- /dev/null +++ b/src/pulsecore/anotify.c @@ -0,0 +1,143 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "anotify.h" + +#define EVENTS_MAX 16 + +struct pa_anotify { + pa_mainloop_api *api; + pa_anotify_cb_t callback; + void *userdata; + int fds[2]; + pa_io_event *io_event; + pa_defer_event *defer_event; + + uint8_t queued_events[EVENTS_MAX]; + unsigned n_queued_events, queue_index; +}; + +static void dispatch_event(pa_anotify *a) { + assert(a); + assert(a->queue_index < a->n_queued_events); + + a->callback(a->queued_events[a->queue_index++], a->userdata); + + if (a->queue_index >= a->n_queued_events) { + a->n_queued_events = 0; + a->queue_index = 0; + + a->api->io_enable(a->io_event, PA_IO_EVENT_INPUT); + a->api->defer_enable(a->defer_event, 0); + } else { + a->api->io_enable(a->io_event, 0); + a->api->defer_enable(a->defer_event, 1); + } +} + +static void io_callback( + pa_mainloop_api *api, + pa_io_event *e, + int fd, + pa_io_event_flags_t events, + void *userdata) { + + pa_anotify *a = userdata; + ssize_t r; + + assert(a); + assert(events == PA_IO_EVENT_INPUT); + assert(a->n_queued_events == 0); + + r = read(fd, a->queued_events, sizeof(a->queued_events)); + assert(r > 0); + + a->n_queued_events = (unsigned) r; + a->queue_index = 0; + + /* Only dispatch a single event */ + dispatch_event(a); +} + +static void defer_callback(pa_mainloop_api *api, pa_defer_event *e, void *userdata) { + pa_anotify *a = userdata; + assert(a); + + dispatch_event(a); +} + +pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userdata) { + pa_anotify *a; + + assert(api); + assert(cb); + + a = pa_xnew(pa_anotify, 1); + + if (pipe(a->fds) < 0) { + pa_xfree(a); + return NULL; + } + + a->api = api; + a->callback = cb; + a->userdata = userdata; + + a->io_event = api->io_new(api, a->fds[0], PA_IO_EVENT_INPUT, io_callback, a); + a->defer_event = api->defer_new(api, defer_callback, a); + a->api->defer_enable(a->defer_event, 0); + + a->n_queued_events = 0; + + return a; +} + +void pa_anotify_free(pa_anotify *a) { + assert(a); + + a->api->io_free(a->io_event); + a->api->defer_free(a->defer_event); + + if (a->fds[0] >= 0) + close(a->fds[0]); + if (a->fds[1] >= 0) + close(a->fds[1]); + + pa_xfree(a); +} + +int pa_anotify_signal(pa_anotify *a, uint8_t event) { + ssize_t r; + assert(a); + + r = write(a->fds[1], &event, 1); + return r != 1 ? -1 : 0; +} diff --git a/src/pulsecore/anotify.h b/src/pulsecore/anotify.h new file mode 100644 index 000000000..44e942f75 --- /dev/null +++ b/src/pulsecore/anotify.h @@ -0,0 +1,38 @@ +#ifndef foopulseanotifyhfoo +#define foopulseanotifyhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* Asynchronous thread-safe notification of mainloops */ + + +#include +#include + +typedef struct pa_anotify pa_anotify; +typedef void (*pa_anotify_cb_t)(uint8_t event, void *userdata); + +pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userdata); +void pa_anotify_free(pa_anotify *a); +int pa_anotify_signal(pa_anotify *a, uint8_t event); + +#endif From 5ad143b3aba3e5bd0d528feb3143dd9cd2f1e845 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 26 Sep 2006 23:42:08 +0000 Subject: [PATCH 1302/1514] upgrade refcnt.h to make use of our new pa_atomic_xxx() API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1403 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/refcnt.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h index fade9aa47..6eb5ee3f9 100644 --- a/src/pulsecore/refcnt.h +++ b/src/pulsecore/refcnt.h @@ -1,5 +1,5 @@ -#ifndef foopulserefcntfoo -#define foopulserefcntfoo +#ifndef foopulserefcnthfoo +#define foopulserefcnthfoo /* $Id$ */ @@ -22,20 +22,21 @@ USA. ***/ -#include +#include -#define PA_REFCNT_DECLARE volatile AO_t _ref +#define PA_REFCNT_DECLARE \ + pa_atomic_int_t _ref #define PA_REFCNT_INIT(p) \ - AO_store_release_write(&(p)->_ref, 1) + pa_atomic_store(&p->_ref, 1) #define PA_REFCNT_INC(p) \ - AO_fetch_and_add1_release_write(&(p)->_ref) + pa_atomic_inc(&p->_ref) #define PA_REFCNT_DEC(p) \ - (AO_fetch_and_sub1_release_write(&(p)->_ref)-1) + (pa_atomic_dec(&p->_ref)-1) #define PA_REFCNT_VALUE(p) \ - AO_load_acquire_read(&(p)->_ref) + pa_atomic_load(&p->_ref) #endif From d210ebbb09daddb2c8c8e8e77243e088b0b19c4d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 26 Sep 2006 23:50:56 +0000 Subject: [PATCH 1303/1514] rework memory block management to be thread-safe and mostly lock-free. pa_memblock is now an opaque structure. Access to its fields is now done through various accessor functions in a thread-safe manner. pa_memblock_acquire() and pa_memblock_release() are now used to access the attached audio data. Why? To allow safe manipulation of the memory pointer maintained by the memory block. Internally _acquire() and _release() maintain a reference counter. Please do not confuse this reference counter whith the one maintained by pa_memblock_ref()/_unref()! As a side effect this patch removes all direct usages of AO_t and replaces it with pa_atomic_xxx based code. This stuff needs some serious testing love. Especially if threads are actively used. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1404 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 7 +- src/modules/module-alsa-sink.c | 14 +- src/modules/module-alsa-source.c | 10 +- src/modules/module-esound-sink.c | 11 +- src/modules/module-jack-sink.c | 5 +- src/modules/module-jack-source.c | 7 +- src/modules/module-oss-mmap.c | 4 +- src/modules/module-oss.c | 22 +- src/modules/module-pipe-sink.c | 11 +- src/modules/module-pipe-source.c | 13 +- src/modules/module-sine.c | 14 +- src/modules/rtp/rtp.c | 18 +- src/pulse/internal.h | 1 + src/pulse/stream.c | 20 +- src/pulsecore/cli-command.c | 20 +- src/pulsecore/mcalign.c | 10 +- src/pulsecore/memblock.c | 507 +++++++++++++++++++++++------- src/pulsecore/memblock.h | 57 ++-- src/pulsecore/memblockq.c | 10 +- src/pulsecore/memchunk.c | 15 +- src/pulsecore/play-memchunk.c | 2 +- src/pulsecore/protocol-esound.c | 38 ++- src/pulsecore/protocol-native.c | 14 +- src/pulsecore/protocol-simple.c | 22 +- src/pulsecore/pstream.c | 169 +++++----- src/pulsecore/resampler.c | 245 ++++++++------- src/pulsecore/sample-util.c | 118 ++++--- src/pulsecore/sample-util.h | 3 +- src/pulsecore/sink-input.c | 9 +- src/pulsecore/sink.c | 26 +- src/pulsecore/sound-file-stream.c | 9 +- src/pulsecore/sound-file.c | 15 +- src/tests/flist-test.c | 2 +- src/tests/mcalign-test.c | 19 +- src/tests/memblock-test.c | 20 +- src/tests/memblockq-test.c | 4 +- 36 files changed, 991 insertions(+), 500 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 64df8614d..0ce805ec0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -268,8 +268,7 @@ thread_test_CFLAGS = $(AM_CFLAGS) thread_test_LDADD = $(AM_LDADD) libpulsecore.la thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -flist_test_SOURCES = tests/flist-test.c \ - pulsecore/flist.c pulsecore/flist.h +flist_test_SOURCES = tests/flist-test.c flist_test_CFLAGS = $(AM_CFLAGS) flist_test_LDADD = $(AM_LDADD) libpulsecore.la flist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -448,6 +447,8 @@ libpulse_la_SOURCES += \ pulsecore/core-error.c pulsecore/core-error.h \ pulsecore/winsock.h pulsecore/creds.h \ pulsecore/shm.c pulsecore/shm.h \ + pulsecore/flist.c pulsecore/flist.h \ + pulsecore/anotify.c pulsecore/anotify.h \ $(PA_THREAD_OBJS) if OS_IS_WIN32 @@ -628,6 +629,8 @@ libpulsecore_la_SOURCES += \ pulsecore/core-error.c pulsecore/core-error.h \ pulsecore/hook-list.c pulsecore/hook-list.h \ pulsecore/shm.c pulsecore/shm.h \ + pulsecore/flist.c pulsecore/flist.h \ + pulsecore/anotify.c pulsecore/anotify.h \ $(PA_THREAD_OBJS) if OS_IS_WIN32 diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 6ff9a6e49..7bbd7de2f 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -144,6 +144,7 @@ static void do_write(struct userdata *u) { update_usage(u); for (;;) { + void *p; pa_memchunk *memchunk = NULL; snd_pcm_sframes_t frames; @@ -156,9 +157,15 @@ static void do_write(struct userdata *u) { memchunk = &u->memchunk; } - assert(memchunk->memblock && memchunk->memblock->data && memchunk->length && memchunk->memblock->length && (memchunk->length % u->frame_size) == 0); + assert(memchunk->memblock); + assert(memchunk->length); + assert((memchunk->length % u->frame_size) == 0); - if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) { + p = pa_memblock_acquire(memchunk->memblock); + + if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) p + memchunk->index, memchunk->length / u->frame_size)) < 0) { + pa_memblock_release(memchunk->memblock); + if (frames == -EAGAIN) return; @@ -176,6 +183,9 @@ static void do_write(struct userdata *u) { return; } + pa_memblock_release(memchunk->memblock); + + if (memchunk == &u->memchunk) { size_t l = frames * u->frame_size; memchunk->index += l; diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index aa0666f10..9bde46dab 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -149,6 +149,7 @@ static void do_read(struct userdata *u) { pa_memchunk post_memchunk; snd_pcm_sframes_t frames; size_t l; + void *p; if (!u->memchunk.memblock) { u->memchunk.memblock = pa_memblock_new(u->source->core->mempool, u->memchunk.length = u->fragment_size); @@ -157,11 +158,13 @@ static void do_read(struct userdata *u) { assert(u->memchunk.memblock); assert(u->memchunk.length); - assert(u->memchunk.memblock->data); - assert(u->memchunk.memblock->length); assert(u->memchunk.length % u->frame_size == 0); - if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) { + p = pa_memblock_acquire(u->memchunk.memblock); + + if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) { + pa_memblock_release(u->memchunk.memblock); + if (frames == -EAGAIN) return; @@ -178,6 +181,7 @@ static void do_read(struct userdata *u) { pa_module_unload_request(u->module); return; } + pa_memblock_release(u->memchunk.memblock); l = frames * u->frame_size; diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 6d4a84891..ca1f16ced 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -142,18 +142,25 @@ static int do_write(struct userdata *u) { u->write_index = u->write_length = 0; } } else if (u->state == STATE_RUNNING) { + void *p; + pa_module_set_used(u->module, pa_sink_used_by(u->sink)); if (!u->memchunk.length) if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0) return 0; - assert(u->memchunk.memblock && u->memchunk.length); + assert(u->memchunk.memblock); + assert(u->memchunk.length); + + p = pa_memblock_acquire(u->memchunk.memblock); - if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { + if ((r = pa_iochannel_write(u->io, (uint8_t*) p + u->memchunk.index, u->memchunk.length)) < 0) { + pa_memblock_release(u->memchunk.memblock); pa_log("write() failed: %s", pa_cstrerror(errno)); return -1; } + pa_memblock_release(u->memchunk.memblock); u->memchunk.index += r; u->memchunk.length -= r; diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 47f77bab3..66ded27ff 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -135,22 +135,25 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_ unsigned fs; jack_nframes_t frame_idx; pa_memchunk chunk; + void *p; fs = pa_frame_size(&u->sink->sample_spec); pa_sink_render_full(u->sink, u->frames_requested * fs, &chunk); + p = pa_memblock_acquire(chunk.memblock); for (frame_idx = 0; frame_idx < u->frames_requested; frame_idx ++) { unsigned c; for (c = 0; c < u->channels; c++) { - float *s = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c; + float *s = ((float*) ((uint8_t*) p + chunk.index)) + (frame_idx * u->channels) + c; float *d = ((float*) u->buffer[c]) + frame_idx; *d = *s; } } + pa_memblock_release(chunk.memblock); pa_memblock_unref(chunk.memblock); u->frames_requested = 0; diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 62a991087..5270b2410 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -134,23 +134,28 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_ unsigned fs; jack_nframes_t frame_idx; pa_memchunk chunk; + void *p; fs = pa_frame_size(&u->source->sample_spec); chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length = u->frames_posted * fs); chunk.index = 0; + + p = pa_memblock_acquire(chunk.memblock); for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) { unsigned c; for (c = 0; c < u->channels; c++) { float *s = ((float*) u->buffer[c]) + frame_idx; - float *d = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c; + float *d = ((float*) ((uint8_t*) p + chunk.index)) + (frame_idx * u->channels) + c; *d = *s; } } + pa_memblock_release(chunk.memblock); + pa_source_post(u->source, &chunk); pa_memblock_unref(chunk.memblock); diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 5ab082878..39a8511f0 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -170,7 +170,7 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { u->out_fragment_size, 1); assert(chunk.memblock); - chunk.length = chunk.memblock->length; + chunk.length = pa_memblock_get_length(chunk.memblock); chunk.index = 0; pa_sink_render_into_full(u->sink, &chunk); @@ -214,7 +214,7 @@ static void in_post_memblocks(struct userdata *u, unsigned n) { if (!u->in_memblocks[u->in_current]) { chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->core->mempool, (uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, 1); - chunk.length = chunk.memblock->length; + chunk.length = pa_memblock_get_length(chunk.memblock); chunk.index = 0; pa_source_post(u->source, &chunk); diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index b71581d9a..73f0d57ef 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -155,6 +155,7 @@ static void do_write(struct userdata *u) { } do { + void *p; memchunk = &u->memchunk; if (!memchunk->length) @@ -162,16 +163,18 @@ static void do_write(struct userdata *u) { memchunk = &u->silence; assert(memchunk->memblock); - assert(memchunk->memblock->data); assert(memchunk->length); - - if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { + + p = pa_memblock_acquire(memchunk->memblock); + if ((r = pa_iochannel_write(u->io, (uint8_t*) p + memchunk->index, memchunk->length)) < 0) { + pa_memblock_release(memchunk->memblock); pa_log("write() failed: %s", pa_cstrerror(errno)); clear_up(u); pa_module_unload_request(u->module); break; } + pa_memblock_release(memchunk->memblock); if (memchunk == &u->silence) assert(r % u->sample_size == 0); @@ -217,9 +220,13 @@ static void do_read(struct userdata *u) { } do { + void *p; memchunk.memblock = pa_memblock_new(u->core->mempool, l); - assert(memchunk.memblock); - if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { + + p = pa_memblock_acquire(memchunk.memblock); + + if ((r = pa_iochannel_read(u->io, p, pa_memblock_get_length(memchunk.memblock))) < 0) { + pa_memblock_release(memchunk.memblock); pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) { pa_log("read() failed: %s", pa_cstrerror(errno)); @@ -228,9 +235,10 @@ static void do_read(struct userdata *u) { } break; } + pa_memblock_release(memchunk.memblock); - assert(r <= (ssize_t) memchunk.memblock->length); - memchunk.length = memchunk.memblock->length = r; + assert(r <= (ssize_t) pa_memblock_get_length(memchunk.memblock)); + memchunk.length = r; memchunk.index = 0; pa_source_post(u->source, &memchunk); diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 4aee849bb..59d91aa4b 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -84,6 +84,8 @@ static const char* const valid_modargs[] = { static void do_write(struct userdata *u) { ssize_t r; + void *p; + assert(u); u->core->mainloop->defer_enable(u->defer_event, 0); @@ -97,12 +99,17 @@ static void do_write(struct userdata *u) { if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) return; - assert(u->memchunk.memblock && u->memchunk.length); + assert(u->memchunk.memblock); + assert(u->memchunk.length); + + p = pa_memblock_acquire(u->memchunk.memblock); - if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { + if ((r = pa_iochannel_write(u->io, (uint8_t*) p + u->memchunk.index, u->memchunk.length)) < 0) { + pa_memblock_release(u->memchunk.memblock); pa_log("write(): %s", pa_cstrerror(errno)); return; } + pa_memblock_release(u->memchunk.memblock); u->memchunk.index += r; u->memchunk.length -= r; diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index c251f7ac3..99f4f3b97 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -82,7 +82,9 @@ static const char* const valid_modargs[] = { static void do_read(struct userdata *u) { ssize_t r; + void *p; pa_memchunk chunk; + assert(u); if (!pa_iochannel_is_readable(u->io)) @@ -95,17 +97,22 @@ static void do_read(struct userdata *u) { u->chunk.index = chunk.length = 0; } - assert(u->chunk.memblock && u->chunk.memblock->length > u->chunk.index); - if ((r = pa_iochannel_read(u->io, (uint8_t*) u->chunk.memblock->data + u->chunk.index, u->chunk.memblock->length - u->chunk.index)) <= 0) { + assert(u->chunk.memblock); + assert(pa_memblock_get_length(u->chunk.memblock) > u->chunk.index); + + p = pa_memblock_acquire(u->chunk.memblock); + if ((r = pa_iochannel_read(u->io, (uint8_t*) p + u->chunk.index, pa_memblock_get_length(u->chunk.memblock) - u->chunk.index)) <= 0) { + pa_memblock_release(u->chunk.memblock); pa_log("read(): %s", pa_cstrerror(errno)); return; } + pa_memblock_release(u->chunk.memblock); u->chunk.length = r; pa_source_post(u->source, &u->chunk); u->chunk.index += r; - if (u->chunk.index >= u->chunk.memblock->length) { + if (u->chunk.index >= pa_memblock_get_length(u->chunk.memblock)) { u->chunk.index = u->chunk.length = 0; pa_memblock_unref(u->chunk.memblock); u->chunk.memblock = NULL; diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index fa29ba160..f65b1f3a6 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -63,7 +63,7 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { chunk->memblock = pa_memblock_ref(u->memblock); chunk->index = u->peek_index; - chunk->length = u->memblock->length - u->peek_index; + chunk->length = pa_memblock_get_length(u->memblock) - u->peek_index; return 0; } @@ -72,11 +72,12 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t l assert(i && chunk && length && i->userdata); u = i->userdata; - assert(chunk->memblock == u->memblock && length <= u->memblock->length-u->peek_index); + assert(chunk->memblock == u->memblock); + assert(length <= pa_memblock_get_length(u->memblock)-u->peek_index); u->peek_index += length; - if (u->peek_index >= u->memblock->length) + if (u->peek_index >= pa_memblock_get_length(u->memblock)) u->peek_index = 0; } @@ -109,6 +110,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; uint32_t frequency; char t[256]; + void *p; pa_sink_input_new_data data; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -140,8 +142,10 @@ int pa__init(pa_core *c, pa_module*m) { } u->memblock = pa_memblock_new(c->mempool, pa_bytes_per_second(&ss)); - calc_sine(u->memblock->data, u->memblock->length, frequency); - + p = pa_memblock_acquire(u->memblock); + calc_sine(p, pa_memblock_get_length(u->memblock), frequency); + pa_memblock_release(u->memblock); + snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); pa_sink_input_new_data_init(&data); diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index 3bb0ea473..a4362f84d 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -79,7 +79,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { size_t k = n + chunk.length > size ? size - n : chunk.length; if (chunk.memblock) { - iov[iov_idx].iov_base = (void*)((uint8_t*) chunk.memblock->data + chunk.index); + iov[iov_idx].iov_base = (void*)((uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index); iov[iov_idx].iov_len = k; mb[iov_idx] = chunk.memblock; iov_idx ++; @@ -114,8 +114,10 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { k = sendmsg(c->fd, &m, MSG_DONTWAIT); - for (i = 1; i < iov_idx; i++) + for (i = 1; i < iov_idx; i++) { + pa_memblock_release(mb[i]); pa_memblock_unref(mb[i]); + } c->sequence++; } else @@ -172,7 +174,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { chunk->memblock = pa_memblock_new(pool, size); - iov.iov_base = chunk->memblock->data; + iov.iov_base = pa_memblock_acquire(chunk->memblock); iov.iov_len = size; m.msg_name = NULL; @@ -193,9 +195,9 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { goto fail; } - memcpy(&header, chunk->memblock->data, sizeof(uint32_t)); - memcpy(&c->timestamp, (uint8_t*) chunk->memblock->data + 4, sizeof(uint32_t)); - memcpy(&c->ssrc, (uint8_t*) chunk->memblock->data + 8, sizeof(uint32_t)); + memcpy(&header, iov.iov_base, sizeof(uint32_t)); + memcpy(&c->timestamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t)); + memcpy(&c->ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t)); header = ntohl(header); c->timestamp = ntohl(c->timestamp); @@ -236,8 +238,10 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { return 0; fail: - if (chunk->memblock) + if (chunk->memblock) { + pa_memblock_release(chunk->memblock); pa_memblock_unref(chunk->memblock); + } return -1; } diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 4eef4b4ad..76d80d836 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -113,6 +113,7 @@ struct pa_stream { uint32_t requested_bytes; pa_memchunk peek_memchunk; + void *peek_data; pa_memblockq *record_memblockq; int corked; diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 180cd096d..d31127d88 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -88,6 +88,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->peek_memchunk.index = 0; s->peek_memchunk.length = 0; s->peek_memchunk.memblock = NULL; + s->peek_data = NULL; s->record_memblockq = NULL; @@ -122,8 +123,11 @@ static void stream_free(pa_stream *s) { s->mainloop->time_free(s->auto_timing_update_event); } - if (s->peek_memchunk.memblock) + if (s->peek_memchunk.memblock) { + if (s->peek_data) + pa_memblock_release(s->peek_memchunk.memblock); pa_memblock_unref(s->peek_memchunk.memblock); + } if (s->record_memblockq) pa_memblockq_free(s->record_memblockq); @@ -605,8 +609,11 @@ int pa_stream_write( if (free_cb) chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) data, length, free_cb, 1); else { + void *tdata; chunk.memblock = pa_memblock_new(s->context->mempool, length); - memcpy(chunk.memblock->data, data, length); + tdata = pa_memblock_acquire(chunk.memblock); + memcpy(tdata, data, length); + pa_memblock_release(chunk.memblock); } chunk.index = 0; @@ -672,9 +679,12 @@ int pa_stream_peek(pa_stream *s, const void **data, size_t *length) { *length = 0; return 0; } + + s->peek_data = pa_memblock_acquire(s->peek_memchunk.memblock); } - *data = (const char*) s->peek_memchunk.memblock->data + s->peek_memchunk.index; + assert(s->peek_data); + *data = (uint8_t*) s->peek_data + s->peek_memchunk.index; *length = s->peek_memchunk.length; return 0; } @@ -692,7 +702,9 @@ int pa_stream_drop(pa_stream *s) { /* Fix the simulated local read index */ if (s->timing_info_valid && !s->timing_info.read_index_corrupt) s->timing_info.read_index += s->peek_memchunk.length; - + + assert(s->peek_data); + pa_memblock_release(s->peek_memchunk.memblock); pa_memblock_unref(s->peek_memchunk.memblock); s->peek_memchunk.length = 0; s->peek_memchunk.index = 0; diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index ae475c3a0..d7e4a75c7 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -259,20 +259,20 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G stat = pa_mempool_get_stat(c->mempool); pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n", - (unsigned) AO_load_acquire_read((AO_t*) &stat->n_allocated), - pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->allocated_size))); + (unsigned) pa_atomic_load(&stat->n_allocated), + pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->allocated_size))); pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n", - (unsigned) AO_load_acquire_read((AO_t*) &stat->n_accumulated), - pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->accumulated_size))); + (unsigned) pa_atomic_load(&stat->n_accumulated), + pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->accumulated_size))); pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n", - (unsigned) AO_load_acquire_read((AO_t*) &stat->n_imported), - pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->imported_size))); + (unsigned) pa_atomic_load(&stat->n_imported), + pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->imported_size))); pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n", - (unsigned) AO_load_acquire_read((AO_t*) &stat->n_exported), - pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->exported_size))); + (unsigned) pa_atomic_load(&stat->n_exported), + pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->exported_size))); pa_strbuf_printf(buf, "Total sample cache size: %s.\n", pa_bytes_snprint(s, sizeof(s), pa_scache_total_size(c))); @@ -289,8 +289,8 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_strbuf_printf(buf, "Memory blocks of type %s: %u allocated/%u accumulated.\n", type_table[k], - (unsigned) AO_load_acquire_read(&stat->n_allocated_by_type[k]), - (unsigned) AO_load_acquire_read(&stat->n_accumulated_by_type[k])); + (unsigned) pa_atomic_load(&stat->n_allocated_by_type[k]), + (unsigned) pa_atomic_load(&stat->n_accumulated_by_type[k])); return 0; } diff --git a/src/pulsecore/mcalign.c b/src/pulsecore/mcalign.c index 9ede610d7..aa2eae469 100644 --- a/src/pulsecore/mcalign.c +++ b/src/pulsecore/mcalign.c @@ -89,6 +89,7 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { } else { size_t l; + void *lo_data, *m_data; /* We have to copy */ assert(m->leftover.length < m->base); @@ -100,10 +101,15 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { /* Can we use the current block? */ pa_memchunk_make_writable(&m->leftover, m->base); - memcpy((uint8_t*) m->leftover.memblock->data + m->leftover.index + m->leftover.length, (uint8_t*) c->memblock->data + c->index, l); + lo_data = pa_memblock_acquire(m->leftover.memblock); + m_data = pa_memblock_acquire(c->memblock); + memcpy((uint8_t*) lo_data + m->leftover.index + m->leftover.length, (uint8_t*) m_data + c->index, l); + pa_memblock_release(m->leftover.memblock); + pa_memblock_release(c->memblock); m->leftover.length += l; - assert(m->leftover.length <= m->base && m->leftover.length <= m->leftover.memblock->length); + assert(m->leftover.length <= m->base); + assert(m->leftover.length <= pa_memblock_get_length(m->leftover.memblock)); if (c->length > l) { /* Save the remainder of the memory block */ diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 9cfd79b5e..f11a71745 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -30,10 +30,13 @@ #include #include +#include #include #include #include +#include +#include #include "memblock.h" @@ -45,6 +48,32 @@ #define PA_MEMIMPORT_SLOTS_MAX 128 #define PA_MEMIMPORT_SEGMENTS_MAX 16 +struct pa_memblock { + PA_REFCNT_DECLARE; /* the reference counter */ + pa_mempool *pool; + + pa_memblock_type_t type; + int read_only; /* boolean */ + + pa_atomic_ptr_t data; + size_t length; + + pa_atomic_int_t n_acquired; + pa_atomic_int_t please_signal; + + union { + struct { + /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ + pa_free_cb_t free_cb; + } user; + + struct { + uint32_t id; + pa_memimport_segment *segment; + } imported; + } per_type; +}; + struct pa_memimport_segment { pa_memimport *import; pa_shm memory; @@ -52,6 +81,8 @@ struct pa_memimport_segment { }; struct pa_memimport { + pa_mutex *mutex; + pa_mempool *pool; pa_hashmap *segments; pa_hashmap *blocks; @@ -70,9 +101,11 @@ struct memexport_slot { }; struct pa_memexport { + pa_mutex *mutex; pa_mempool *pool; struct memexport_slot slots[PA_MEMEXPORT_SLOTS_MAX]; + PA_LLIST_HEAD(struct memexport_slot, free_slots); PA_LLIST_HEAD(struct memexport_slot, used_slots); unsigned n_init; @@ -92,63 +125,71 @@ struct mempool_slot { }; struct pa_mempool { + pa_mutex *mutex; + pa_cond *cond; + pa_shm memory; size_t block_size; - unsigned n_blocks, n_init; + unsigned n_blocks; + + pa_atomic_int_t n_init; PA_LLIST_HEAD(pa_memimport, imports); PA_LLIST_HEAD(pa_memexport, exports); /* A list of free slots that may be reused */ - PA_LLIST_HEAD(struct mempool_slot, free_slots); + pa_flist *free_slots; pa_mempool_stat stat; }; static void segment_detach(pa_memimport_segment *seg); +/* No lock necessary */ static void stat_add(pa_memblock*b) { assert(b); assert(b->pool); - AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated); - AO_fetch_and_add_release_write(&b->pool->stat.allocated_size, (AO_t) b->length); + pa_atomic_inc(&b->pool->stat.n_allocated); + pa_atomic_add(&b->pool->stat.allocated_size, (int) b->length); - AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated); - AO_fetch_and_add_release_write(&b->pool->stat.accumulated_size, (AO_t) b->length); + pa_atomic_inc(&b->pool->stat.n_accumulated); + pa_atomic_add(&b->pool->stat.accumulated_size, (int) b->length); if (b->type == PA_MEMBLOCK_IMPORTED) { - AO_fetch_and_add1_release_write(&b->pool->stat.n_imported); - AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) b->length); + pa_atomic_inc(&b->pool->stat.n_imported); + pa_atomic_add(&b->pool->stat.imported_size, (int) b->length); } - AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); - AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated_by_type[b->type]); + pa_atomic_inc(&b->pool->stat.n_allocated_by_type[b->type]); + pa_atomic_inc(&b->pool->stat.n_accumulated_by_type[b->type]); } +/* No lock necessary */ static void stat_remove(pa_memblock *b) { assert(b); assert(b->pool); - assert(AO_load_acquire_read(&b->pool->stat.n_allocated) > 0); - assert(AO_load_acquire_read(&b->pool->stat.allocated_size) >= (AO_t) b->length); + assert(pa_atomic_load(&b->pool->stat.n_allocated) > 0); + assert(pa_atomic_load(&b->pool->stat.allocated_size) >= (int) b->length); - AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated); - AO_fetch_and_add_release_write(&b->pool->stat.allocated_size, (AO_t) (-b->length)); + pa_atomic_dec(&b->pool->stat.n_allocated); + pa_atomic_add(&b->pool->stat.allocated_size, - (int) b->length); if (b->type == PA_MEMBLOCK_IMPORTED) { - assert(AO_load_acquire_read(&b->pool->stat.n_imported) > 0); - assert(AO_load_acquire_read(&b->pool->stat.imported_size) >= (AO_t) b->length); + assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); + assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); - AO_fetch_and_sub1_release_write(&b->pool->stat.n_imported); - AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) (-b->length)); + pa_atomic_dec(&b->pool->stat.n_imported); + pa_atomic_add(&b->pool->stat.imported_size, - (int) b->length); } - AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); + pa_atomic_dec(&b->pool->stat.n_allocated_by_type[b->type]); } static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length); +/* No lock necessary */ pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) { pa_memblock *b; @@ -161,6 +202,7 @@ pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) { return b; } +/* No lock necessary */ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) { pa_memblock *b; @@ -168,49 +210,61 @@ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) { assert(length > 0); b = pa_xmalloc(sizeof(pa_memblock) + length); + PA_REFCNT_INIT(b); + b->pool = p; b->type = PA_MEMBLOCK_APPENDED; b->read_only = 0; - PA_REFCNT_INIT(b); + pa_atomic_ptr_store(&b->data, (uint8_t*)b + sizeof(pa_memblock)); b->length = length; - b->data = (uint8_t*) b + sizeof(pa_memblock); - b->pool = p; - + pa_atomic_store(&b->n_acquired, 0); + pa_atomic_store(&b->please_signal, 0); + stat_add(b); return b; } +/* No lock necessary */ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { struct mempool_slot *slot; assert(p); - if (p->free_slots) { - slot = p->free_slots; - PA_LLIST_REMOVE(struct mempool_slot, p->free_slots, slot); - } else if (p->n_init < p->n_blocks) - slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * p->n_init++)); - else { - pa_log_debug("Pool full"); - AO_fetch_and_add1_release_write(&p->stat.n_pool_full); - return NULL; + if (!(slot = pa_flist_pop(p->free_slots))) { + int idx; + + /* The free list was empty, we have to allocate a new entry */ + + if ((unsigned) (idx = pa_atomic_inc(&p->n_init)) >= p->n_blocks) + pa_atomic_dec(&p->n_init); + else + slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * idx)); + + if (!slot) { + pa_log_debug("Pool full"); + pa_atomic_inc(&p->stat.n_pool_full); + } } return slot; } +/* No lock necessary */ static void* mempool_slot_data(struct mempool_slot *slot) { assert(slot); return (uint8_t*) slot + sizeof(struct mempool_slot); } +/* No lock necessary */ static unsigned mempool_slot_idx(pa_mempool *p, void *ptr) { assert(p); + assert((uint8_t*) ptr >= (uint8_t*) p->memory.ptr); assert((uint8_t*) ptr < (uint8_t*) p->memory.ptr + p->memory.size); return ((uint8_t*) ptr - (uint8_t*) p->memory.ptr) / p->block_size; } +/* No lock necessary */ static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) { unsigned idx; @@ -220,6 +274,7 @@ static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) { return (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (idx * p->block_size)); } +/* No lock necessary */ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { pa_memblock *b = NULL; struct mempool_slot *slot; @@ -234,7 +289,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { b = mempool_slot_data(slot); b->type = PA_MEMBLOCK_POOL; - b->data = (uint8_t*) b + sizeof(pa_memblock); + pa_atomic_ptr_store(&b->data, (uint8_t*) b + sizeof(pa_memblock)); } else if (p->block_size - sizeof(struct mempool_slot) >= length) { @@ -243,22 +298,26 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { b = pa_xnew(pa_memblock, 1); b->type = PA_MEMBLOCK_POOL_EXTERNAL; - b->data = mempool_slot_data(slot); + pa_atomic_ptr_store(&b->data, mempool_slot_data(slot)); + } else { pa_log_debug("Memory block too large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot)); - AO_fetch_and_add1_release_write(&p->stat.n_too_large_for_pool); + pa_atomic_inc(&p->stat.n_too_large_for_pool); return NULL; } - b->length = length; - b->read_only = 0; PA_REFCNT_INIT(b); b->pool = p; + b->read_only = 0; + b->length = length; + pa_atomic_store(&b->n_acquired, 0); + pa_atomic_store(&b->please_signal, 0); stat_add(b); return b; } +/* No lock necessary */ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int read_only) { pa_memblock *b; @@ -267,17 +326,20 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int re assert(length > 0); b = pa_xnew(pa_memblock, 1); + PA_REFCNT_INIT(b); + b->pool = p; b->type = PA_MEMBLOCK_FIXED; b->read_only = read_only; - PA_REFCNT_INIT(b); + pa_atomic_ptr_store(&b->data, d); b->length = length; - b->data = d; - b->pool = p; + pa_atomic_store(&b->n_acquired, 0); + pa_atomic_store(&b->please_signal, 0); stat_add(b); return b; } +/* No lock necessary */ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (*free_cb)(void *p), int read_only) { pa_memblock *b; @@ -287,18 +349,72 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (* assert(free_cb); b = pa_xnew(pa_memblock, 1); + PA_REFCNT_INIT(b); + b->pool = p; b->type = PA_MEMBLOCK_USER; b->read_only = read_only; - PA_REFCNT_INIT(b); + pa_atomic_ptr_store(&b->data, d); b->length = length; - b->data = d; + pa_atomic_store(&b->n_acquired, 0); + pa_atomic_store(&b->please_signal, 0); + b->per_type.user.free_cb = free_cb; - b->pool = p; stat_add(b); return b; } +/* No lock necessary */ +int pa_memblock_is_read_only(pa_memblock *b) { + assert(b); + assert(PA_REFCNT_VALUE(b) > 0); + + return b->read_only && PA_REFCNT_VALUE(b) == 1; +} + +/* No lock necessary */ +void* pa_memblock_acquire(pa_memblock *b) { + assert(b); + assert(PA_REFCNT_VALUE(b) > 0); + + pa_atomic_inc(&b->n_acquired); + + return pa_atomic_ptr_load(&b->data); +} + +/* No lock necessary, in corner cases locks by its own */ +void pa_memblock_release(pa_memblock *b) { + int r; + assert(b); + assert(PA_REFCNT_VALUE(b) > 0); + + r = pa_atomic_dec(&b->n_acquired); + assert(r >= 1); + + if (r == 1 && pa_atomic_load(&b->please_signal)) { + pa_mempool *p = b->pool; + /* Signal a waiting thread that this memblock is no longer used */ + pa_mutex_lock(p->mutex); + pa_cond_signal(p->cond, 1); + pa_mutex_unlock(p->mutex); + } +} + +size_t pa_memblock_get_length(pa_memblock *b) { + assert(b); + assert(PA_REFCNT_VALUE(b) > 0); + + return b->length; +} + +pa_mempool* pa_memblock_get_pool(pa_memblock *b) { + assert(b); + assert(PA_REFCNT_VALUE(b) > 0); + + return b->pool; +} + +/* No lock necessary */ pa_memblock* pa_memblock_ref(pa_memblock*b) { assert(b); assert(PA_REFCNT_VALUE(b) > 0); @@ -307,19 +423,17 @@ pa_memblock* pa_memblock_ref(pa_memblock*b) { return b; } -void pa_memblock_unref(pa_memblock*b) { +static void memblock_free(pa_memblock *b) { assert(b); - assert(PA_REFCNT_VALUE(b) > 0); - - if (PA_REFCNT_DEC(b) > 0) - return; + assert(pa_atomic_load(&b->n_acquired) == 0); + stat_remove(b); switch (b->type) { case PA_MEMBLOCK_USER : assert(b->per_type.user.free_cb); - b->per_type.user.free_cb(b->data); + b->per_type.user.free_cb(pa_atomic_ptr_load(&b->data)); /* Fall through */ @@ -330,17 +444,23 @@ void pa_memblock_unref(pa_memblock*b) { case PA_MEMBLOCK_IMPORTED : { pa_memimport_segment *segment; - + pa_memimport *import; + + /* FIXME! This should be implemented lock-free */ + segment = b->per_type.imported.segment; assert(segment); - assert(segment->import); + import = segment->import; + assert(import); - pa_hashmap_remove(segment->import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); - segment->import->release_cb(segment->import, b->per_type.imported.id, segment->import->userdata); - + pa_mutex_lock(import->mutex); + pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); if (-- segment->n_blocks <= 0) segment_detach(segment); - + pa_mutex_unlock(import->mutex); + + import->release_cb(import, b->per_type.imported.id, import->userdata); + pa_xfree(b); break; } @@ -348,13 +468,20 @@ void pa_memblock_unref(pa_memblock*b) { case PA_MEMBLOCK_POOL_EXTERNAL: case PA_MEMBLOCK_POOL: { struct mempool_slot *slot; + int call_free; - slot = mempool_slot_by_ptr(b->pool, b->data); + slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data)); assert(slot); + + call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL; + + /* The free list dimensions should easily allow all slots + * to fit in, hence try harder if pushing this slot into + * the free list fails */ + while (pa_flist_push(b->pool->free_slots, slot) < 0) + ; - PA_LLIST_PREPEND(struct mempool_slot, b->pool->free_slots, slot); - - if (b->type == PA_MEMBLOCK_POOL_EXTERNAL) + if (call_free) pa_xfree(b); break; @@ -366,10 +493,42 @@ void pa_memblock_unref(pa_memblock*b) { } } +/* No lock necessary */ +void pa_memblock_unref(pa_memblock*b) { + assert(b); + assert(PA_REFCNT_VALUE(b) > 0); + + if (PA_REFCNT_DEC(b) > 0) + return; + + memblock_free(b); +} + +/* Self locked */ +static void memblock_wait(pa_memblock *b) { + assert(b); + + if (pa_atomic_load(&b->n_acquired) > 0) { + /* We need to wait until all threads gave up access to the + * memory block before we can go on. Unfortunately this means + * that we have to lock and wait here. Sniff! */ + + pa_atomic_inc(&b->please_signal); + + pa_mutex_lock(b->pool->mutex); + while (pa_atomic_load(&b->n_acquired) > 0) + pa_cond_wait(b->pool->cond, b->pool->mutex); + pa_mutex_unlock(b->pool->mutex); + + pa_atomic_dec(&b->please_signal); + } +} + +/* No lock necessary. This function is not multiple caller safe! */ static void memblock_make_local(pa_memblock *b) { assert(b); - AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); + pa_atomic_dec(&b->pool->stat.n_allocated_by_type[b->type]); if (b->length <= b->pool->block_size - sizeof(struct mempool_slot)) { struct mempool_slot *slot; @@ -378,53 +537,61 @@ static void memblock_make_local(pa_memblock *b) { void *new_data; /* We can move it into a local pool, perfect! */ + new_data = mempool_slot_data(slot); + memcpy(new_data, pa_atomic_ptr_load(&b->data), b->length); + pa_atomic_ptr_store(&b->data, new_data); + b->type = PA_MEMBLOCK_POOL_EXTERNAL; b->read_only = 0; - new_data = mempool_slot_data(slot); - memcpy(new_data, b->data, b->length); - b->data = new_data; goto finish; } } /* Humm, not enough space in the pool, so lets allocate the memory with malloc() */ - b->type = PA_MEMBLOCK_USER; b->per_type.user.free_cb = pa_xfree; + pa_atomic_ptr_store(&b->data, pa_xmemdup(pa_atomic_ptr_load(&b->data), b->length)); + + b->type = PA_MEMBLOCK_USER; b->read_only = 0; - b->data = pa_xmemdup(b->data, b->length); finish: - AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); - AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated_by_type[b->type]); + pa_atomic_inc(&b->pool->stat.n_allocated_by_type[b->type]); + pa_atomic_inc(&b->pool->stat.n_accumulated_by_type[b->type]); + + memblock_wait(b); } +/* No lock necessary. This function is not multiple caller safe*/ void pa_memblock_unref_fixed(pa_memblock *b) { assert(b); assert(PA_REFCNT_VALUE(b) > 0); assert(b->type == PA_MEMBLOCK_FIXED); - if (PA_REFCNT_VALUE(b) > 1) + if (PA_REFCNT_DEC(b) > 0) memblock_make_local(b); - - pa_memblock_unref(b); + else + memblock_free(b); } +/* Self-locked. This function is not multiple-caller safe */ static void memblock_replace_import(pa_memblock *b) { pa_memimport_segment *seg; assert(b); assert(b->type == PA_MEMBLOCK_IMPORTED); - assert(AO_load_acquire_read(&b->pool->stat.n_imported) > 0); - assert(AO_load_acquire_read(&b->pool->stat.imported_size) >= (AO_t) b->length); - AO_fetch_and_sub1_release_write(&b->pool->stat.n_imported); - AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) - b->length); + assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); + assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); + pa_atomic_dec(&b->pool->stat.n_imported); + pa_atomic_add(&b->pool->stat.imported_size, (int) - b->length); seg = b->per_type.imported.segment; assert(seg); assert(seg->import); + pa_mutex_lock(seg->import->mutex); + pa_hashmap_remove( seg->import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); @@ -433,6 +600,8 @@ static void memblock_replace_import(pa_memblock *b) { if (-- seg->n_blocks <= 0) segment_detach(seg); + + pa_mutex_unlock(seg->import->mutex); } pa_mempool* pa_mempool_new(int shared) { @@ -441,12 +610,15 @@ pa_mempool* pa_mempool_new(int shared) { p = pa_xnew(pa_mempool, 1); + p->mutex = pa_mutex_new(1); + p->cond = pa_cond_new(); + #ifdef HAVE_SYSCONF ps = (size_t) sysconf(_SC_PAGESIZE); #elif defined(PAGE_SIZE) - ps = (size_t) PAGE_SIZE; + ps = (size_t) PAGE_SIZE; #else - ps = 4096; /* Let's hope it's like x86. */ + ps = 4096; /* Let's hope it's like x86. */ #endif p->block_size = (PA_MEMPOOL_SLOT_SIZE/ps)*ps; @@ -463,13 +635,13 @@ pa_mempool* pa_mempool_new(int shared) { return NULL; } - p->n_init = 0; + memset(&p->stat, 0, sizeof(p->stat)); + pa_atomic_store(&p->n_init, 0); PA_LLIST_HEAD_INIT(pa_memimport, p->imports); PA_LLIST_HEAD_INIT(pa_memexport, p->exports); - PA_LLIST_HEAD_INIT(struct mempool_slot, p->free_slots); - memset(&p->stat, 0, sizeof(p->stat)); + p->free_slots = pa_flist_new(p->n_blocks*2); return p; } @@ -477,34 +649,62 @@ pa_mempool* pa_mempool_new(int shared) { void pa_mempool_free(pa_mempool *p) { assert(p); + pa_mutex_lock(p->mutex); + while (p->imports) pa_memimport_free(p->imports); while (p->exports) pa_memexport_free(p->exports); - if (AO_load_acquire_read(&p->stat.n_allocated) > 0) + pa_mutex_unlock(p->mutex); + + if (pa_atomic_load(&p->stat.n_allocated) > 0) pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!"); + + pa_flist_free(p->free_slots, NULL); pa_shm_free(&p->memory); + + pa_mutex_free(p->mutex); + pa_cond_free(p->cond); + pa_xfree(p); } +/* No lock necessary */ const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p) { assert(p); return &p->stat; } +/* No lock necessary */ void pa_mempool_vacuum(pa_mempool *p) { struct mempool_slot *slot; + pa_flist *list; assert(p); - for (slot = p->free_slots; slot; slot = slot->next) - pa_shm_punch(&p->memory, (uint8_t*) slot + sizeof(struct mempool_slot) - (uint8_t*) p->memory.ptr, p->block_size - sizeof(struct mempool_slot)); + list = pa_flist_new(p->n_blocks*2); + + while ((slot = pa_flist_pop(p->free_slots))) + while (pa_flist_push(list, slot) < 0) + ; + + while ((slot = pa_flist_pop(list))) { + pa_shm_punch(&p->memory, + (uint8_t*) slot - (uint8_t*) p->memory.ptr + sizeof(struct mempool_slot), + p->block_size - sizeof(struct mempool_slot)); + + while (pa_flist_push(p->free_slots, slot)) + ; + } + + pa_flist_free(list, NULL); } +/* No lock necessary */ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) { assert(p); @@ -516,6 +716,7 @@ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) { return 0; } +/* No lock necessary */ int pa_mempool_is_shared(pa_mempool *p) { assert(p); @@ -530,18 +731,23 @@ pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void assert(cb); i = pa_xnew(pa_memimport, 1); + i->mutex = pa_mutex_new(0); i->pool = p; i->segments = pa_hashmap_new(NULL, NULL); i->blocks = pa_hashmap_new(NULL, NULL); i->release_cb = cb; i->userdata = userdata; - + + pa_mutex_lock(p->mutex); PA_LLIST_PREPEND(pa_memimport, p->imports, i); + pa_mutex_unlock(p->mutex); + return i; } static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i); +/* Should be called locked */ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) { pa_memimport_segment* seg; @@ -562,6 +768,7 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) { return seg; } +/* Should be called locked */ static void segment_detach(pa_memimport_segment *seg) { assert(seg); @@ -570,51 +777,68 @@ static void segment_detach(pa_memimport_segment *seg) { pa_xfree(seg); } +/* Self-locked. Not multiple-caller safe */ void pa_memimport_free(pa_memimport *i) { pa_memexport *e; pa_memblock *b; assert(i); - /* If we've exported this block further we need to revoke that export */ - for (e = i->pool->exports; e; e = e->next) - memexport_revoke_blocks(e, i); + pa_mutex_lock(i->mutex); while ((b = pa_hashmap_get_first(i->blocks))) memblock_replace_import(b); assert(pa_hashmap_size(i->segments) == 0); + + pa_mutex_unlock(i->mutex); + pa_mutex_lock(i->pool->mutex); + + /* If we've exported this block further we need to revoke that export */ + for (e = i->pool->exports; e; e = e->next) + memexport_revoke_blocks(e, i); + + PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i); + + pa_mutex_unlock(i->pool->mutex); + pa_hashmap_free(i->blocks, NULL, NULL); pa_hashmap_free(i->segments, NULL, NULL); + + pa_mutex_free(i->mutex); - PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i); pa_xfree(i); } +/* Self-locked */ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_id, size_t offset, size_t size) { - pa_memblock *b; + pa_memblock *b = NULL; pa_memimport_segment *seg; assert(i); + pa_mutex_lock(i->mutex); + if (pa_hashmap_size(i->blocks) >= PA_MEMIMPORT_SLOTS_MAX) - return NULL; + goto finish; if (!(seg = pa_hashmap_get(i->segments, PA_UINT32_TO_PTR(shm_id)))) if (!(seg = segment_attach(i, shm_id))) - return NULL; + goto finish; if (offset+size > seg->memory.size) - return NULL; - + goto finish; + b = pa_xnew(pa_memblock, 1); + PA_REFCNT_INIT(b); + b->pool = i->pool; b->type = PA_MEMBLOCK_IMPORTED; b->read_only = 1; - PA_REFCNT_INIT(b); + pa_atomic_ptr_store(&b->data, (uint8_t*) seg->memory.ptr + offset); b->length = size; - b->data = (uint8_t*) seg->memory.ptr + offset; - b->pool = i->pool; + pa_atomic_store(&b->n_acquired, 0); + pa_atomic_store(&b->please_signal, 0); b->per_type.imported.id = block_id; b->per_type.imported.segment = seg; @@ -622,7 +846,11 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i seg->n_blocks++; - stat_add(b); +finish: + pa_mutex_unlock(i->mutex); + + if (b) + stat_add(b); return b; } @@ -631,10 +859,15 @@ int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) { pa_memblock *b; assert(i); + pa_mutex_lock(i->mutex); + if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id)))) return -1; memblock_replace_import(b); + + pa_mutex_unlock(i->mutex); + return 0; } @@ -649,58 +882,84 @@ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void return NULL; e = pa_xnew(pa_memexport, 1); + e->mutex = pa_mutex_new(1); e->pool = p; PA_LLIST_HEAD_INIT(struct memexport_slot, e->free_slots); PA_LLIST_HEAD_INIT(struct memexport_slot, e->used_slots); e->n_init = 0; e->revoke_cb = cb; e->userdata = userdata; - + + pa_mutex_lock(p->mutex); PA_LLIST_PREPEND(pa_memexport, p->exports, e); + pa_mutex_unlock(p->mutex); + return e; } void pa_memexport_free(pa_memexport *e) { assert(e); + pa_mutex_lock(e->mutex); while (e->used_slots) pa_memexport_process_release(e, e->used_slots - e->slots); + pa_mutex_unlock(e->mutex); + pa_mutex_lock(e->pool->mutex); PA_LLIST_REMOVE(pa_memexport, e->pool->exports, e); + pa_mutex_unlock(e->pool->mutex); + pa_xfree(e); } +/* Self-locked */ int pa_memexport_process_release(pa_memexport *e, uint32_t id) { + pa_memblock *b; + assert(e); + pa_mutex_lock(e->mutex); + if (id >= e->n_init) - return -1; + goto fail; if (!e->slots[id].block) - return -1; + goto fail; -/* pa_log("Processing release for %u", id); */ - - assert(AO_load_acquire_read(&e->pool->stat.n_exported) > 0); - assert(AO_load_acquire_read(&e->pool->stat.exported_size) >= (AO_t) e->slots[id].block->length); - - AO_fetch_and_sub1_release_write(&e->pool->stat.n_exported); - AO_fetch_and_add_release_write(&e->pool->stat.exported_size, (AO_t) -e->slots[id].block->length); - - pa_memblock_unref(e->slots[id].block); + b = e->slots[id].block; e->slots[id].block = NULL; PA_LLIST_REMOVE(struct memexport_slot, e->used_slots, &e->slots[id]); PA_LLIST_PREPEND(struct memexport_slot, e->free_slots, &e->slots[id]); + pa_mutex_unlock(e->mutex); + +/* pa_log("Processing release for %u", id); */ + + assert(pa_atomic_load(&e->pool->stat.n_exported) > 0); + assert(pa_atomic_load(&e->pool->stat.exported_size) >= (int) b->length); + + pa_atomic_dec(&e->pool->stat.n_exported); + pa_atomic_add(&e->pool->stat.exported_size, (int) -b->length); + + pa_memblock_unref(b); + return 0; + +fail: + pa_mutex_unlock(e->mutex); + + return -1; } +/* Self-locked */ static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) { struct memexport_slot *slot, *next; assert(e); assert(i); + pa_mutex_lock(e->mutex); + for (slot = e->used_slots; slot; slot = next) { uint32_t idx; next = slot->next; @@ -713,8 +972,11 @@ static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) { e->revoke_cb(e, idx, e->userdata); pa_memexport_process_release(e, idx); } + + pa_mutex_unlock(e->mutex); } +/* No lock necessary */ static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *b) { pa_memblock *n; @@ -731,13 +993,16 @@ static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *b) { if (!(n = pa_memblock_new_pool(p, b->length))) return NULL; - memcpy(n->data, b->data, b->length); + memcpy(pa_atomic_ptr_load(&n->data), pa_atomic_ptr_load(&b->data), b->length); return n; } +/* Self-locked */ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32_t *shm_id, size_t *offset, size_t * size) { pa_shm *memory; struct memexport_slot *slot; + void *data; + size_t length; assert(e); assert(b); @@ -750,12 +1015,15 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 if (!(b = memblock_shared_copy(e->pool, b))) return -1; + pa_mutex_lock(e->mutex); + if (e->free_slots) { slot = e->free_slots; PA_LLIST_REMOVE(struct memexport_slot, e->free_slots, slot); - } else if (e->n_init < PA_MEMEXPORT_SLOTS_MAX) { + } else if (e->n_init < PA_MEMEXPORT_SLOTS_MAX) slot = &e->slots[e->n_init++]; - } else { + else { + pa_mutex_unlock(e->mutex); pa_memblock_unref(b); return -1; } @@ -764,8 +1032,11 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 slot->block = b; *block_id = slot - e->slots; + pa_mutex_unlock(e->mutex); /* pa_log("Got block id %u", *block_id); */ + data = pa_memblock_acquire(b); + if (b->type == PA_MEMBLOCK_IMPORTED) { assert(b->per_type.imported.segment); memory = &b->per_type.imported.segment->memory; @@ -775,15 +1046,17 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 memory = &b->pool->memory; } - assert(b->data >= memory->ptr); - assert((uint8_t*) b->data + b->length <= (uint8_t*) memory->ptr + memory->size); + assert(data >= memory->ptr); + assert((uint8_t*) data + length <= (uint8_t*) memory->ptr + memory->size); *shm_id = memory->id; - *offset = (uint8_t*) b->data - (uint8_t*) memory->ptr; - *size = b->length; + *offset = (uint8_t*) data - (uint8_t*) memory->ptr; + *size = length; - AO_fetch_and_add1_release_write(&e->pool->stat.n_exported); - AO_fetch_and_add_release_write(&e->pool->stat.exported_size, (AO_t) b->length); + pa_memblock_release(b); + + pa_atomic_inc(&e->pool->stat.n_exported); + pa_atomic_add(&e->pool->stat.exported_size, (int) length); return 0; } diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index d4f2b7aaf..9937818f6 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -54,45 +55,25 @@ typedef struct pa_memexport pa_memexport; typedef void (*pa_memimport_release_cb_t)(pa_memimport *i, uint32_t block_id, void *userdata); typedef void (*pa_memexport_revoke_cb_t)(pa_memexport *e, uint32_t block_id, void *userdata); -struct pa_memblock { - pa_memblock_type_t type; - int read_only; /* boolean */ - PA_REFCNT_DECLARE; /* the reference counter */ - size_t length; - void *data; - pa_mempool *pool; - - union { - struct { - void (*free_cb)(void *p); /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ - } user; - - struct { - uint32_t id; - pa_memimport_segment *segment; - } imported; - } per_type; -}; - /* Please note that updates to this structure are not locked, * i.e. n_allocated might be updated at a point in time where * n_accumulated is not yet. Take these values with a grain of salt, - * threy are here for purely statistical reasons.*/ + * they are here for purely statistical reasons.*/ struct pa_mempool_stat { - AO_t n_allocated; - AO_t n_accumulated; - AO_t n_imported; - AO_t n_exported; - AO_t allocated_size; - AO_t accumulated_size; - AO_t imported_size; - AO_t exported_size; + pa_atomic_int_t n_allocated; + pa_atomic_int_t n_accumulated; + pa_atomic_int_t n_imported; + pa_atomic_int_t n_exported; + pa_atomic_int_t allocated_size; + pa_atomic_int_t accumulated_size; + pa_atomic_int_t imported_size; + pa_atomic_int_t exported_size; - AO_t n_too_large_for_pool; - AO_t n_pool_full; + pa_atomic_int_t n_too_large_for_pool; + pa_atomic_int_t n_pool_full; - AO_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; - AO_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; + pa_atomic_int_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; + pa_atomic_int_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; }; /* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL or PA_MEMBLOCK_APPENDED, depending on the size */ @@ -116,9 +97,17 @@ pa_memblock* pa_memblock_ref(pa_memblock*b); /* This special unref function has to be called by the owner of the memory of a static memory block when he wants to release all references to the memory. This causes the memory to be copied and -converted into a PA_MEMBLOCK_DYNAMIC type memory block */ +converted into a pool or malloc'ed memory block. Please note that this +function is not multiple caller safe, i.e. needs to be locked +manually if called from more than one thread at the same time. */ void pa_memblock_unref_fixed(pa_memblock*b); +int pa_memblock_is_read_only(pa_memblock *b); +void* pa_memblock_acquire(pa_memblock *b); +void pa_memblock_release(pa_memblock *b); +size_t pa_memblock_get_length(pa_memblock *b); +pa_mempool * pa_memblock_get_pool(pa_memblock *b); + /* The memory block manager */ pa_mempool* pa_mempool_new(int shared); void pa_mempool_free(pa_mempool *p); diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index e6b73fc55..dab44dc39 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -176,7 +176,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { assert(uchunk); assert(uchunk->memblock); assert(uchunk->length > 0); - assert(uchunk->index + uchunk->length <= uchunk->memblock->length); + assert(uchunk->index + uchunk->length <= pa_memblock_get_length(uchunk->memblock)); if (uchunk->length % bq->base) return -1; @@ -360,8 +360,8 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { if (bq->silence) { chunk->memblock = pa_memblock_ref(bq->silence); - if (!length || length > chunk->memblock->length) - length = chunk->memblock->length; + if (!length || length > pa_memblock_get_length(chunk->memblock)) + length = pa_memblock_get_length(chunk->memblock); chunk->length = length; } else { @@ -413,8 +413,8 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length if (bq->silence) { - if (!l || l > bq->silence->length) - l = bq->silence->length; + if (!l || l > pa_memblock_get_length(bq->silence)) + l = pa_memblock_get_length(bq->silence); } diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c index 1dbad2b90..55c4bfa7d 100644 --- a/src/pulsecore/memchunk.c +++ b/src/pulsecore/memchunk.c @@ -35,22 +35,25 @@ void pa_memchunk_make_writable(pa_memchunk *c, size_t min) { pa_memblock *n; size_t l; + void *tdata, *sdata; assert(c); assert(c->memblock); - assert(PA_REFCNT_VALUE(c->memblock) > 0); - if (PA_REFCNT_VALUE(c->memblock) == 1 && - !c->memblock->read_only && - c->memblock->length >= c->index+min) + if (pa_memblock_is_read_only(c->memblock) && + pa_memblock_get_length(c->memblock) >= c->index+min) return; l = c->length; if (l < min) l = min; - n = pa_memblock_new(c->memblock->pool, l); - memcpy(n->data, (uint8_t*) c->memblock->data + c->index, c->length); + n = pa_memblock_new(pa_memblock_get_pool(c->memblock), l); + tdata = pa_memblock_acquire(n); + sdata = pa_memblock_acquire(c->memblock); + memcpy(tdata, (uint8_t*) sdata + c->index, c->length); + pa_memblock_release(n); + pa_memblock_release(c->memblock); pa_memblock_unref(c->memblock); c->memblock = n; c->index = 0; diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c index cde6a9ee4..b711c98cd 100644 --- a/src/pulsecore/play-memchunk.c +++ b/src/pulsecore/play-memchunk.c @@ -55,7 +55,7 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { if (c->length <= 0) return -1; - assert(c->memblock && c->memblock->length); + assert(c->memblock); *chunk = *c; pa_memblock_ref(c->memblock); diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 80aeb27b1..65b93eb45 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -891,14 +891,22 @@ static int do_read(struct connection *c) { } } else if (c->state == ESD_CACHING_SAMPLE) { ssize_t r; + void *p; - assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length); + assert(c->scache.memchunk.memblock); + assert(c->scache.name); + assert(c->scache.memchunk.index < c->scache.memchunk.length); + + p = pa_memblock_acquire(c->scache.memchunk.memblock); - if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { + if ((r = pa_iochannel_read(c->io, (uint8_t*) p+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { + pa_memblock_release(c->scache.memchunk.memblock); pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } + pa_memblock_release(c->scache.memchunk.memblock); + c->scache.memchunk.index += r; assert(c->scache.memchunk.index <= c->scache.memchunk.length); @@ -925,6 +933,7 @@ static int do_read(struct connection *c) { pa_memchunk chunk; ssize_t r; size_t l; + void *p; assert(c->input_memblockq); @@ -937,7 +946,7 @@ static int do_read(struct connection *c) { l = c->playback.fragment_size; if (c->playback.current_memblock) - if (c->playback.current_memblock->length - c->playback.memblock_index < l) { + if (pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index < l) { pa_memblock_unref(c->playback.current_memblock); c->playback.current_memblock = NULL; c->playback.memblock_index = 0; @@ -945,15 +954,21 @@ static int do_read(struct connection *c) { if (!c->playback.current_memblock) { c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2); - assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); + assert(c->playback.current_memblock); + assert(pa_memblock_get_length(c->playback.current_memblock) >= l); c->playback.memblock_index = 0; } - if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { + p = pa_memblock_acquire(c->playback.current_memblock); + + if ((r = pa_iochannel_read(c->io, (uint8_t*) p+c->playback.memblock_index, l)) <= 0) { + pa_memblock_release(c->playback.current_memblock); pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } - + + pa_memblock_release(c->playback.current_memblock); + chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; chunk.length = r; @@ -990,19 +1005,26 @@ static int do_write(struct connection *c) { } else if (c->state == ESD_STREAMING_DATA && c->source_output) { pa_memchunk chunk; ssize_t r; + void *p; assert(c->output_memblockq); if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) return 0; - assert(chunk.memblock && chunk.length); + assert(chunk.memblock); + assert(chunk.length); + + p = pa_memblock_acquire(chunk.memblock); - if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { + if ((r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length)) < 0) { + pa_memblock_release(chunk.memblock); pa_memblock_unref(chunk.memblock); pa_log("write(): %s", pa_cstrerror(errno)); return -1; } + pa_memblock_release(chunk.memblock); + pa_memblockq_drop(c->output_memblockq, &chunk, r); pa_memblock_unref(chunk.memblock); diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 38c024b7b..fba611d7d 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2274,6 +2274,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o } else { struct upload_stream *u = (struct upload_stream*) stream; size_t l; + assert(u->type == UPLOAD_STREAM); if (!u->memchunk.memblock) { @@ -2293,9 +2294,18 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o if (l > chunk->length) l = chunk->length; + if (l > 0) { - memcpy((uint8_t*) u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length, - (uint8_t*) chunk->memblock->data+chunk->index, l); + void *src, *dst; + dst = pa_memblock_acquire(u->memchunk.memblock); + src = pa_memblock_acquire(chunk->memblock); + + memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length, + (uint8_t*) src+chunk->index, l); + + pa_memblock_release(u->memchunk.memblock); + pa_memblock_release(chunk->memblock); + u->memchunk.length += l; u->length -= l; } diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 6bfba875e..bf203e423 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -113,6 +113,7 @@ static int do_read(struct connection *c) { pa_memchunk chunk; ssize_t r; size_t l; + void *p; if (!c->sink_input || !(l = pa_memblockq_missing(c->input_memblockq))) return 0; @@ -121,7 +122,7 @@ static int do_read(struct connection *c) { l = c->playback.fragment_size; if (c->playback.current_memblock) - if (c->playback.current_memblock->length - c->playback.memblock_index < l) { + if (pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index < l) { pa_memblock_unref(c->playback.current_memblock); c->playback.current_memblock = NULL; c->playback.memblock_index = 0; @@ -129,15 +130,20 @@ static int do_read(struct connection *c) { if (!c->playback.current_memblock) { c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2); - assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); + assert(c->playback.current_memblock); + assert(pa_memblock_get_length(c->playback.current_memblock) >= l); c->playback.memblock_index = 0; } + + p = pa_memblock_acquire(c->playback.current_memblock); - if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { + if ((r = pa_iochannel_read(c->io, (uint8_t*) p + c->playback.memblock_index, l)) <= 0) { + pa_memblock_release(c->playback.current_memblock); pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno)); return -1; } + pa_memblock_release(c->playback.current_memblock); chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; chunk.length = r; @@ -156,7 +162,8 @@ static int do_read(struct connection *c) { static int do_write(struct connection *c) { pa_memchunk chunk; ssize_t r; - + void *p; + if (!c->source_output) return 0; @@ -165,12 +172,17 @@ static int do_write(struct connection *c) { return 0; assert(chunk.memblock && chunk.length); + + p = pa_memblock_acquire(chunk.memblock); - if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { + if ((r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length)) < 0) { + pa_memblock_release(chunk.memblock); pa_memblock_unref(chunk.memblock); pa_log("write(): %s", pa_cstrerror(errno)); return -1; } + + pa_memblock_release(chunk.memblock); pa_memblockq_drop(c->output_memblockq, &chunk, r); pa_memblock_unref(chunk.memblock); diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 566fb060a..339637967 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "pstream.h" @@ -113,10 +114,11 @@ struct pa_pstream { PA_REFCNT_DECLARE; pa_mainloop_api *mainloop; - pa_defer_event *defer_event; pa_iochannel *io; + pa_queue *send_queue; - pa_mutex *mutex; + pa_mutex *mutex; /* only for access to the queue */ + pa_anotify *anotify; int dead; @@ -126,6 +128,7 @@ struct pa_pstream { uint32_t shm_info[PA_PSTREAM_SHM_MAX]; void *data; size_t index; + pa_memchunk memchunk; } write; struct { @@ -170,10 +173,6 @@ static void do_something(pa_pstream *p) { pa_pstream_ref(p); - pa_mutex_lock(p->mutex); - - p->mainloop->defer_enable(p->defer_event, 0); - if (!p->dead && pa_iochannel_is_readable(p->io)) { if (do_read(p) < 0) goto fail; @@ -185,8 +184,6 @@ static void do_something(pa_pstream *p) { goto fail; } - pa_mutex_unlock(p->mutex); - pa_pstream_unref(p); return; @@ -197,8 +194,6 @@ fail: if (p->die_callback) p->die_callback(p, p->die_callback_userdata); - pa_mutex_unlock(p->mutex); - pa_pstream_unref(p); } @@ -211,13 +206,10 @@ static void io_callback(pa_iochannel*io, void *userdata) { do_something(p); } -static void defer_callback(pa_mainloop_api *m, pa_defer_event *e, void*userdata) { +static void anotify_callback(uint8_t event, void *userdata) { pa_pstream *p = userdata; assert(p); - assert(p->defer_event == e); - assert(p->mainloop == m); - do_something(p); } @@ -237,16 +229,16 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo p->dead = 0; p->mutex = pa_mutex_new(1); + p->anotify = pa_anotify_new(m, anotify_callback, p); p->mainloop = m; - p->defer_event = m->defer_new(m, defer_callback, p); - m->defer_enable(p->defer_event, 0); p->send_queue = pa_queue_new(); assert(p->send_queue); p->write.current = NULL; p->write.index = 0; + pa_memchunk_reset(&p->write.memchunk); p->read.memblock = NULL; p->read.packet = NULL; p->read.index = 0; @@ -309,9 +301,15 @@ static void pstream_free(pa_pstream *p) { if (p->read.packet) pa_packet_unref(p->read.packet); + if (p->write.memchunk.memblock) + pa_memblock_unref(p->write.memchunk.memblock); + if (p->mutex) pa_mutex_free(p->mutex); + if (p->anotify) + pa_anotify_free(p->anotify); + pa_xfree(p); } @@ -322,11 +320,6 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre assert(PA_REFCNT_VALUE(p) > 0); assert(packet); - pa_mutex_lock(p->mutex); - - if (p->dead) - goto finish; - i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); @@ -336,12 +329,11 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre i->creds = *creds; #endif + pa_mutex_lock(p->mutex); pa_queue_push(p->send_queue, i); - p->mainloop->defer_enable(p->defer_event, 1); - -finish: - pa_mutex_unlock(p->mutex); + + pa_anotify_signal(p->anotify, 0); } void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) { @@ -352,12 +344,6 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa assert(channel != (uint32_t) -1); assert(chunk); - pa_mutex_lock(p->mutex); - - if (p->dead) - goto finish; - - length = chunk->length; idx = 0; while (length > 0) { @@ -379,17 +365,15 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa i->with_creds = 0; #endif + pa_mutex_lock(p->mutex); pa_queue_push(p->send_queue, i); + pa_mutex_unlock(p->mutex); idx += n; length -= n; } - - p->mainloop->defer_enable(p->defer_event, 1); -finish: - - pa_mutex_unlock(p->mutex); + pa_anotify_signal(p->anotify, 0); } static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata) { @@ -399,11 +383,6 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd assert(p); assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); - - if (p->dead) - goto finish; - /* pa_log("Releasing block %u", block_id); */ item = pa_xnew(struct item_info, 1); @@ -413,12 +392,11 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd item->with_creds = 0; #endif + pa_mutex_lock(p->mutex); pa_queue_push(p->send_queue, item); - p->mainloop->defer_enable(p->defer_event, 1); - -finish: - pa_mutex_unlock(p->mutex); + + pa_anotify_signal(p->anotify, 0); } static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) { @@ -428,11 +406,6 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda assert(p); assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); - - if (p->dead) - goto finish; - /* pa_log("Revoking block %u", block_id); */ item = pa_xnew(struct item_info, 1); @@ -442,23 +415,27 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda item->with_creds = 0; #endif + pa_mutex_lock(p->mutex); pa_queue_push(p->send_queue, item); - p->mainloop->defer_enable(p->defer_event, 1); - -finish: - pa_mutex_unlock(p->mutex); + + pa_anotify_signal(p->anotify, 0); } static void prepare_next_write_item(pa_pstream *p) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); - if (!(p->write.current = pa_queue_pop(p->send_queue))) + pa_mutex_lock(p->mutex); + p->write.current = pa_queue_pop(p->send_queue); + pa_mutex_unlock(p->mutex); + + if (!p->write.current) return; p->write.index = 0; p->write.data = NULL; + pa_memchunk_reset(&p->write.memchunk); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = 0; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1); @@ -525,7 +502,9 @@ static void prepare_next_write_item(pa_pstream *p) { if (send_payload) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); - p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index; + p->write.memchunk = p->write.current->chunk; + pa_memblock_ref(p->write.memchunk.memblock); + p->write.data = NULL; } p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(flags); @@ -541,6 +520,7 @@ static int do_write(pa_pstream *p) { void *d; size_t l; ssize_t r; + pa_memblock *release_memblock = NULL; assert(p); assert(PA_REFCNT_VALUE(p) > 0); @@ -555,9 +535,16 @@ static int do_write(pa_pstream *p) { d = (uint8_t*) p->write.descriptor + p->write.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->write.index; } else { - assert(p->write.data); + assert(p->write.data || p->write.memchunk.memblock); + + if (p->write.data) + d = p->write.data; + else { + d = (uint8_t*) pa_memblock_acquire(p->write.memchunk.memblock) + p->write.memchunk.index; + release_memblock = p->write.memchunk.memblock; + } - d = (uint8_t*) p->write.data + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; + d = (uint8_t*) d + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } @@ -567,14 +554,17 @@ static int do_write(pa_pstream *p) { if (p->send_creds_now) { if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0) - return -1; + goto fail; p->send_creds_now = 0; } else #endif if ((r = pa_iochannel_write(p->io, d, l)) < 0) - return -1; + goto fail; + + if (release_memblock) + pa_memblock_release(release_memblock); p->write.index += r; @@ -588,12 +578,20 @@ static int do_write(pa_pstream *p) { } return 0; + +fail: + + if (release_memblock) + pa_memblock_release(release_memblock); + + return -1; } static int do_read(pa_pstream *p) { void *d; size_t l; ssize_t r; + pa_memblock *release_memblock = NULL; assert(p); assert(PA_REFCNT_VALUE(p) > 0); @@ -602,8 +600,16 @@ static int do_read(pa_pstream *p) { d = (uint8_t*) p->read.descriptor + p->read.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->read.index; } else { - assert(p->read.data); - d = (uint8_t*) p->read.data + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE; + assert(p->read.data || p->read.memblock); + + if (p->read.data) + d = p->read.data; + else { + d = pa_memblock_acquire(p->read.memblock); + release_memblock = p->read.memblock; + } + + d = (uint8_t*) d + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE; l = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE); } @@ -612,14 +618,17 @@ static int do_read(pa_pstream *p) { int b = 0; if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->read_creds, &b)) <= 0) - return -1; + goto fail; p->read_creds_valid = p->read_creds_valid || b; } #else if ((r = pa_iochannel_read(p->io, d, l)) <= 0) - return -1; + goto fail; #endif + + if (release_memblock) + pa_memblock_release(release_memblock); p->read.index += r; @@ -701,7 +710,7 @@ static int do_read(pa_pstream *p) { /* Frame is a memblock frame */ p->read.memblock = pa_memblock_new(p->mempool, length); - p->read.data = p->read.memblock->data; + p->read.data = NULL; } else { pa_log_warn("Recieved memblock frame with invalid flags value."); @@ -788,7 +797,7 @@ static int do_read(pa_pstream *p) { chunk.memblock = b; chunk.index = 0; - chunk.length = b->length; + chunk.length = pa_memblock_get_length(b); offset = (int64_t) ( (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) | @@ -816,52 +825,51 @@ frame_done: p->read.memblock = NULL; p->read.packet = NULL; p->read.index = 0; + p->read.data = NULL; #ifdef HAVE_CREDS p->read_creds_valid = 0; #endif return 0; + +fail: + if (release_memblock) + pa_memblock_release(release_memblock); + + return -1; } void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); p->die_callback = cb; p->die_callback_userdata = userdata; - pa_mutex_unlock(p->mutex); } void pa_pstream_set_drain_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); p->drain_callback = cb; p->drain_callback_userdata = userdata; - pa_mutex_unlock(p->mutex); } void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); p->recieve_packet_callback = cb; p->recieve_packet_callback_userdata = userdata; - pa_mutex_unlock(p->mutex); } void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock_cb_t cb, void *userdata) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); p->recieve_memblock_callback = cb; p->recieve_memblock_callback_userdata = userdata; - pa_mutex_unlock(p->mutex); } int pa_pstream_is_pending(pa_pstream *p) { @@ -901,8 +909,6 @@ pa_pstream* pa_pstream_ref(pa_pstream*p) { void pa_pstream_close(pa_pstream *p) { assert(p); - pa_mutex_lock(p->mutex); - p->dead = 1; if (p->import) { @@ -920,25 +926,16 @@ void pa_pstream_close(pa_pstream *p) { p->io = NULL; } - if (p->defer_event) { - p->mainloop->defer_free(p->defer_event); - p->defer_event = NULL; - } - p->die_callback = NULL; p->drain_callback = NULL; p->recieve_packet_callback = NULL; p->recieve_memblock_callback = NULL; - - pa_mutex_unlock(p->mutex); } void pa_pstream_use_shm(pa_pstream *p, int enable) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); - p->use_shm = enable; if (enable) { @@ -953,6 +950,4 @@ void pa_pstream_use_shm(pa_pstream *p, int enable) { p->export = NULL; } } - - pa_mutex_unlock(p->mutex); } diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index b01420491..c28c2fb31 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -51,8 +51,7 @@ struct pa_resampler { }; struct impl_libsamplerate { - pa_memblock *buf1_block, *buf2_block, *buf3_block, *buf4_block; - float* buf1, *buf2, *buf3, *buf4; + pa_memchunk buf1, buf2, buf3, buf4; unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples; pa_convert_to_float32ne_func_t to_float32ne_func; @@ -224,14 +223,14 @@ static void libsamplerate_free(pa_resampler *r) { if (u->src_state) src_delete(u->src_state); - if (u->buf1_block) - pa_memblock_unref(u->buf1_block); - if (u->buf2_block) - pa_memblock_unref(u->buf2_block); - if (u->buf3_block) - pa_memblock_unref(u->buf3_block); - if (u->buf4_block) - pa_memblock_unref(u->buf4_block); + if (u->buf1.memblock) + pa_memblock_unref(u->buf1.memblock); + if (u->buf2.memblock) + pa_memblock_unref(u->buf2.memblock); + if (u->buf3.memblock) + pa_memblock_unref(u->buf3.memblock); + if (u->buf4.memblock) + pa_memblock_unref(u->buf4.memblock); pa_xfree(u); } @@ -270,64 +269,80 @@ static void calc_map_table(pa_resampler *r) { } } -static float * convert_to_float(pa_resampler *r, void *input, unsigned n_frames) { +static pa_memchunk* convert_to_float(pa_resampler *r, pa_memchunk *input) { struct impl_libsamplerate *u; unsigned n_samples; + void *src, *dst; assert(r); assert(input); + assert(input->memblock); + assert(r->impl_data); u = r->impl_data; /* Convert the incoming sample into floats and place them in buf1 */ - if (!u->to_float32ne_func) + if (!u->to_float32ne_func || !input->length) return input; - n_samples = n_frames * r->i_ss.channels; + n_samples = (input->length / r->i_fz) * r->i_ss.channels; - if (u->buf1_samples < n_samples) { - if (u->buf1_block) - pa_memblock_unref(u->buf1_block); + if (!u->buf1.memblock || u->buf1_samples < n_samples) { + if (u->buf1.memblock) + pa_memblock_unref(u->buf1.memblock); u->buf1_samples = n_samples; - u->buf1_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); - u->buf1 = u->buf1_block->data; + u->buf1.memblock = pa_memblock_new(r->mempool, u->buf1.length = sizeof(float) * n_samples); + u->buf1.index = 0; } - - u->to_float32ne_func(n_samples, input, u->buf1); - return u->buf1; + src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index; + dst = (uint8_t*) pa_memblock_acquire(u->buf1.memblock); + u->to_float32ne_func(n_samples, src, dst); + pa_memblock_release(input->memblock); + pa_memblock_release(u->buf1.memblock); + + u->buf1.length = sizeof(float) * n_samples; + + return &u->buf1; } -static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) { +static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { struct impl_libsamplerate *u; - unsigned n_samples; + unsigned n_samples, n_frames; int i_skip, o_skip; unsigned oc; + float *src, *dst; assert(r); assert(input); + assert(input->memblock); + assert(r->impl_data); u = r->impl_data; /* Remap channels and place the result int buf2 */ - if (!u->map_required) + if (!u->map_required || !input->length) return input; - n_samples = n_frames * r->o_ss.channels; + n_samples = input->length / sizeof(float); + n_frames = n_samples / r->o_ss.channels; - if (u->buf2_samples < n_samples) { - if (u->buf2_block) - pa_memblock_unref(u->buf2_block); + if (!u->buf2.memblock || u->buf2_samples < n_samples) { + if (u->buf2.memblock) + pa_memblock_unref(u->buf2.memblock); u->buf2_samples = n_samples; - u->buf2_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); - u->buf2 = u->buf2_block->data; + u->buf2.memblock = pa_memblock_new(r->mempool, u->buf2.length = sizeof(float) * n_samples); + u->buf2.index = 0; } - memset(u->buf2, 0, n_samples * sizeof(float)); + src = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); + dst = (float*) pa_memblock_acquire(u->buf2.memblock); + + memset(dst, 0, n_samples * sizeof(float)); o_skip = sizeof(float) * r->o_ss.channels; i_skip = sizeof(float) * r->i_ss.channels; @@ -338,49 +353,57 @@ static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) { for (i = 0; i < PA_CHANNELS_MAX && u->map_table[oc][i] >= 0; i++) oil_vectoradd_f32( - u->buf2 + oc, o_skip, - u->buf2 + oc, o_skip, - input + u->map_table[oc][i], i_skip, + dst + oc, o_skip, + dst + oc, o_skip, + src + u->map_table[oc][i], i_skip, n_frames, &one, &one); } - return u->buf2; + pa_memblock_release(input->memblock); + pa_memblock_release(u->buf2.memblock); + + u->buf2.length = n_frames * sizeof(float) * r->o_ss.channels; + + return &u->buf2; } -static float *resample(pa_resampler *r, float *input, unsigned *n_frames) { +static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) { struct impl_libsamplerate *u; SRC_DATA data; + unsigned in_n_frames, in_n_samples; unsigned out_n_frames, out_n_samples; int ret; assert(r); assert(input); - assert(n_frames); assert(r->impl_data); u = r->impl_data; /* Resample the data and place the result in buf3 */ - if (!u->src_state) + if (!u->src_state || !input->length) return input; - out_n_frames = (*n_frames*r->o_ss.rate/r->i_ss.rate)+1024; + in_n_samples = input->length / sizeof(float); + in_n_frames = in_n_samples * r->o_ss.channels; + + out_n_frames = (in_n_frames*r->o_ss.rate/r->i_ss.rate)+1024; out_n_samples = out_n_frames * r->o_ss.channels; - if (u->buf3_samples < out_n_samples) { - if (u->buf3_block) - pa_memblock_unref(u->buf3_block); + if (!u->buf3.memblock || u->buf3_samples < out_n_samples) { + if (u->buf3.memblock) + pa_memblock_unref(u->buf3.memblock); u->buf3_samples = out_n_samples; - u->buf3_block = pa_memblock_new(r->mempool, sizeof(float) * out_n_samples); - u->buf3 = u->buf3_block->data; + u->buf3.memblock = pa_memblock_new(r->mempool, u->buf3.length = sizeof(float) * out_n_samples); + u->buf3.index = 0; } - data.data_in = input; - data.input_frames = *n_frames; + data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); + data.input_frames = in_n_frames; - data.data_out = u->buf3; + data.data_out = (float*) pa_memblock_acquire(u->buf3.memblock); data.output_frames = out_n_frames; data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; @@ -388,16 +411,20 @@ static float *resample(pa_resampler *r, float *input, unsigned *n_frames) { ret = src_process(u->src_state, &data); assert(ret == 0); - assert((unsigned) data.input_frames_used == *n_frames); + assert((unsigned) data.input_frames_used == in_n_frames); - *n_frames = data.output_frames_gen; + pa_memblock_release(input->memblock); + pa_memblock_release(u->buf3.memblock); + + u->buf3.length = data.output_frames_gen * sizeof(float) * r->o_ss.channels; - return u->buf3; + return &u->buf3; } -static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) { +static pa_memchunk *convert_from_float(pa_resampler *r, pa_memchunk *input) { struct impl_libsamplerate *u; - unsigned n_samples; + unsigned n_samples, n_frames; + void *src, *dst; assert(r); assert(input); @@ -406,30 +433,35 @@ static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames /* Convert the data into the correct sample type and place the result in buf4 */ - if (!u->from_float32ne_func) + if (!u->from_float32ne_func || !input->length) return input; - + + n_frames = input->length / sizeof(float) / r->o_ss.channels; n_samples = n_frames * r->o_ss.channels; if (u->buf4_samples < n_samples) { - if (u->buf4_block) - pa_memblock_unref(u->buf4_block); + if (u->buf4.memblock) + pa_memblock_unref(u->buf4.memblock); u->buf4_samples = n_samples; - u->buf4_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); - u->buf4 = u->buf4_block->data; + u->buf4.memblock = pa_memblock_new(r->mempool, u->buf4.length = r->o_fz * n_frames); + u->buf4.index = 0; } - - u->from_float32ne_func(n_samples, input, u->buf4); - return u->buf4; + src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->length; + dst = pa_memblock_acquire(u->buf4.memblock); + u->from_float32ne_func(n_samples, src, dst); + pa_memblock_release(input->memblock); + pa_memblock_release(u->buf4.memblock); + + u->buf4.length = r->o_fz * n_frames; + + return &u->buf4; } static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { struct impl_libsamplerate *u; - float *buf; - void *input, *output; - unsigned n_frames; + pa_memchunk *buf; assert(r); assert(in); @@ -441,55 +473,23 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun u = r->impl_data; - input = ((uint8_t*) in->memblock->data + in->index); - n_frames = in->length / r->i_fz; - assert(n_frames > 0); + buf = convert_to_float(r, (pa_memchunk*) in); + buf = remap_channels(r, buf); + buf = resample(r, buf); + + if (buf->length) { + buf = convert_from_float(r, buf); + *out = *buf; + + if (buf == in) + pa_memblock_ref(buf->memblock); + else + pa_memchunk_reset(buf); + } else + pa_memchunk_reset(out); + + pa_memblock_release(in->memblock); - buf = convert_to_float(r, input, n_frames); - buf = remap_channels(r, buf, n_frames); - buf = resample(r, buf, &n_frames); - - if (n_frames) { - output = convert_from_float(r, buf, n_frames); - - if (output == input) { - /* Mm, no adjustment has been necessary, so let's return the original block */ - out->memblock = pa_memblock_ref(in->memblock); - out->index = in->index; - out->length = in->length; - } else { - out->length = n_frames * r->o_fz; - out->index = 0; - out->memblock = NULL; - - if (output == u->buf1) { - u->buf1 = NULL; - u->buf1_samples = 0; - out->memblock = u->buf1_block; - u->buf1_block = NULL; - } else if (output == u->buf2) { - u->buf2 = NULL; - u->buf2_samples = 0; - out->memblock = u->buf2_block; - u->buf2_block = NULL; - } else if (output == u->buf3) { - u->buf3 = NULL; - u->buf3_samples = 0; - out->memblock = u->buf3_block; - u->buf3_block = NULL; - } else if (output == u->buf4) { - u->buf4 = NULL; - u->buf4_samples = 0; - out->memblock = u->buf4_block; - u->buf4_block = NULL; - } - - assert(out->memblock); - } - } else { - out->memblock = NULL; - out->index = out->length = 0; - } } static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) { @@ -516,8 +516,10 @@ static int libsamplerate_init(pa_resampler *r) { r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1); - u->buf1 = u->buf2 = u->buf3 = u->buf4 = NULL; - u->buf1_block = u->buf2_block = u->buf3_block = u->buf4_block = NULL; + pa_memchunk_reset(&u->buf1); + pa_memchunk_reset(&u->buf2); + pa_memchunk_reset(&u->buf3); + pa_memchunk_reset(&u->buf4); u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0; if (r->i_ss.format == PA_SAMPLE_FLOAT32NE) @@ -578,12 +580,16 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out /* Do real resampling */ size_t l; unsigned o_index; + void *src, *dst; /* The length of the new memory block rounded up */ l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz; out->index = 0; out->memblock = pa_memblock_new(r->mempool, l); + + src = (uint8_t*) pa_memblock_acquire(in->memblock) + in->index; + dst = pa_memblock_acquire(out->memblock); for (o_index = 0;; o_index++, u->o_counter++) { unsigned j; @@ -594,13 +600,16 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out if (j >= n_frames) break; - assert(o_index*fz < out->memblock->length); + assert(o_index*fz < pa_memblock_get_length(out->memblock)); - memcpy((uint8_t*) out->memblock->data + fz*o_index, - (uint8_t*) in->memblock->data + in->index + fz*j, fz); + memcpy((uint8_t*) dst + fz*o_index, + (uint8_t*) src + fz*j, fz); } - + + pa_memblock_release(in->memblock); + pa_memblock_release(out->memblock); + out->length = o_index*fz; } diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index d902b4b55..52023d311 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -46,15 +46,27 @@ pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spe } pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { - assert(b && b->data && spec); - pa_silence_memory(b->data, b->length, spec); + void *data; + + assert(b); + assert(spec); + + data = pa_memblock_acquire(b); + pa_silence_memory(data, pa_memblock_get_length(b), spec); + pa_memblock_release(b); return b; } void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) { - assert(c && c->memblock && c->memblock->data && spec && c->length); + void *data; + + assert(c); + assert(c->memblock); + assert(spec); - pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec); + data = pa_memblock_acquire(c->memblock); + pa_silence_memory((uint8_t*) data+c->index, c->length, spec); + pa_memblock_release(c->memblock); } void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { @@ -82,26 +94,38 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { } size_t pa_mix( - const pa_mix_info streams[], - unsigned nstreams, - void *data, - size_t length, - const pa_sample_spec *spec, - const pa_cvolume *volume, - int mute) { - - assert(streams && data && length && spec); + pa_mix_info streams[], + unsigned nstreams, + void *data, + size_t length, + const pa_sample_spec *spec, + const pa_cvolume *volume, + int mute) { + pa_cvolume full_volume; + size_t d = 0; + unsigned k; + + assert(streams); + assert(data); + assert(length); + assert(spec); + + if (!volume) + volume = pa_cvolume_reset(&full_volume, spec->channels); + + for (k = 0; k < nstreams; k++) + streams[k].internal = pa_memblock_acquire(streams[k].chunk.memblock); + switch (spec->format) { case PA_SAMPLE_S16NE:{ - size_t d; unsigned channel = 0; for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; if (d >= length) - return d; + goto finish; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -111,12 +135,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - return d; + goto finish; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); + v = *((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d)); if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); @@ -139,17 +163,18 @@ size_t pa_mix( if (++channel >= spec->channels) channel = 0; } + + break; } case PA_SAMPLE_S16RE:{ - size_t d; unsigned channel = 0; for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; if (d >= length) - return d; + goto finish; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -159,12 +184,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - return d; + goto finish; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d))); + v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d))); if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); @@ -187,17 +212,18 @@ size_t pa_mix( if (++channel >= spec->channels) channel = 0; } + + break; } case PA_SAMPLE_U8: { - size_t d; unsigned channel = 0; for (d = 0;; d ++) { int32_t sum = 0; if (d >= length) - return d; + goto finish; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -207,12 +233,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - return d; + goto finish; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80; + v = (int32_t) *((uint8_t*) streams[i].internal + streams[i].chunk.index + d) - 0x80; if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); @@ -235,17 +261,18 @@ size_t pa_mix( if (++channel >= spec->channels) channel = 0; } + + break; } case PA_SAMPLE_FLOAT32NE: { - size_t d; unsigned channel = 0; for (d = 0;; d += sizeof(float)) { float sum = 0; if (d >= length) - return d; + goto finish; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -255,12 +282,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - return d; + goto finish; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); + v = *((float*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d)); if (cvolume != PA_VOLUME_NORM) v *= pa_sw_volume_to_linear(cvolume); @@ -279,17 +306,34 @@ size_t pa_mix( if (++channel >= spec->channels) channel = 0; } + + break; } default: pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); abort(); } + +finish: + + for (k = 0; k < nstreams; k++) + pa_memblock_release(streams[k].chunk.memblock); + + return d; } -void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvolume *volume) { - assert(c && spec && (c->length % pa_frame_size(spec) == 0)); +void pa_volume_memchunk( + pa_memchunk*c, + const pa_sample_spec *spec, + const pa_cvolume *volume) { + + void *ptr; + + assert(c); + assert(spec); + assert(c->length % pa_frame_size(spec) == 0); assert(volume); if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM)) @@ -300,6 +344,8 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol return; } + ptr = pa_memblock_acquire(c->memblock); + switch (spec->format) { case PA_SAMPLE_S16NE: { int16_t *d; @@ -310,7 +356,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol for (channel = 0; channel < spec->channels; channel++) linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); - for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t = (int32_t)(*d); t = (int32_t) (t * linear[channel]); @@ -335,7 +381,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol for (channel = 0; channel < spec->channels; channel++) linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); - for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t = (int32_t)(INT16_SWAP(*d)); t = (int32_t) (t * linear[channel]); @@ -357,7 +403,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol size_t n; unsigned channel = 0; - for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) { + for (d = (uint8_t*) ptr + c->index, n = c->length; n > 0; d++, n--) { int32_t t = (int32_t) *d - 0x80; t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel])); @@ -379,7 +425,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol unsigned n; unsigned channel; - d = (float*) ((uint8_t*) c->memblock->data + c->index); + d = (float*) ((uint8_t*) ptr + c->index); skip = spec->channels * sizeof(float); n = c->length/sizeof(float)/spec->channels; @@ -402,5 +448,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol pa_sample_format_to_string(spec->format)); abort(); } + + pa_memblock_release(c->memblock); } diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h index 6b7707925..04c2f6b12 100644 --- a/src/pulsecore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -36,10 +36,11 @@ typedef struct pa_mix_info { pa_memchunk chunk; pa_cvolume volume; void *userdata; + void *internal; /* Used internally by pa_mix(), should not be initialised when calling pa_mix() */ } pa_mix_info; size_t pa_mix( - const pa_mix_info channels[], + pa_mix_info channels[], unsigned nchannels, void *data, size_t length, diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index d948f0a4c..c3cd49525 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -294,6 +294,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) assert(i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED); if (i->move_silence > 0) { + size_t l; /* We have just been moved and shall play some silence for a * while until the old sink has drained its playback buffer */ @@ -303,7 +304,8 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) chunk->memblock = pa_memblock_ref(i->silence_memblock); chunk->index = 0; - chunk->length = i->move_silence < chunk->memblock->length ? i->move_silence : chunk->memblock->length; + l = pa_memblock_get_length(chunk->memblock); + chunk->length = i->move_silence < l ? i->move_silence : l; ret = 0; do_volume_adj_here = 1; @@ -389,10 +391,13 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt if (i->move_silence > 0) { if (chunk) { + size_t l; + l = pa_memblock_get_length(i->silence_memblock); + if (chunk->memblock != i->silence_memblock || chunk->index != 0 || - (chunk->memblock && (chunk->length != (i->silence_memblock->length < i->move_silence ? i->silence_memblock->length : i->move_silence)))) + (chunk->memblock && (chunk->length != (l < i->move_silence ? l : i->move_silence)))) return; } diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 056952546..04795e39b 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -237,7 +237,6 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) { info->userdata = i; assert(info->chunk.memblock); - assert(info->chunk.memblock->data); assert(info->chunk.length); info++; @@ -305,13 +304,16 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_volume_memchunk(result, &s->sample_spec, &volume); } } else { + void *ptr; result->memblock = pa_memblock_new(s->core->mempool, length); assert(result->memblock); /* pa_log("mixing %i", n); */ - result->length = pa_mix(info, n, result->memblock->data, length, - &s->sample_spec, &s->sw_volume, s->sw_muted); + ptr = pa_memblock_acquire(result->memblock); + result->length = pa_mix(info, n, ptr, length, &s->sample_spec, &s->sw_volume, s->sw_muted); + pa_memblock_release(result->memblock); + result->index = 0; } @@ -332,13 +334,13 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; int r = -1; + void *ptr; assert(s); assert(s->ref >= 1); assert(target); assert(target->memblock); assert(target->length); - assert(target->memblock->data); pa_sink_ref(s); @@ -347,16 +349,23 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { if (n <= 0) goto finish; + ptr = pa_memblock_acquire(target->memblock); + if (n == 1) { + void *src; pa_cvolume volume; if (target->length > info[0].chunk.length) target->length = info[0].chunk.length; + + src = pa_memblock_acquire(info[0].chunk.memblock); - memcpy((uint8_t*) target->memblock->data + target->index, - (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index, + memcpy((uint8_t*) ptr + target->index, + (uint8_t*) src + info[0].chunk.index, target->length); + pa_memblock_release(info[0].chunk.memblock); + pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); if (s->sw_muted) @@ -365,11 +374,13 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_volume_memchunk(target, &s->sample_spec, &volume); } else target->length = pa_mix(info, n, - (uint8_t*) target->memblock->data + target->index, + (uint8_t*) ptr + target->index, target->length, &s->sample_spec, &s->sw_volume, s->sw_muted); + + pa_memblock_release(target->memblock); inputs_drop(s, info, n, target->length); @@ -393,7 +404,6 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { assert(target); assert(target->memblock); assert(target->length); - assert(target->memblock->data); pa_sink_ref(s); diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index e6f24a795..d2ffeeeda 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -74,21 +74,26 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { if (!u->memchunk.memblock) { uint32_t fs = pa_frame_size(&i->sample_spec); sf_count_t n; + void *p; u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, BUF_SIZE); u->memchunk.index = 0; + p = pa_memblock_acquire(u->memchunk.memblock); + if (u->readf_function) { - if ((n = u->readf_function(u->sndfile, u->memchunk.memblock->data, BUF_SIZE/fs)) <= 0) + if ((n = u->readf_function(u->sndfile, p, BUF_SIZE/fs)) <= 0) n = 0; u->memchunk.length = n * fs; } else { - if ((n = sf_read_raw(u->sndfile, u->memchunk.memblock->data, BUF_SIZE)) <= 0) + if ((n = sf_read_raw(u->sndfile, p, BUF_SIZE)) <= 0) n = 0; u->memchunk.length = n; } + + pa_memblock_release(u->memchunk.memblock); if (!u->memchunk.length) { free_userdata(u); diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c index 1bf650e22..c74a1586f 100644 --- a/src/pulsecore/sound-file.c +++ b/src/pulsecore/sound-file.c @@ -40,7 +40,11 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, int ret = -1; size_t l; sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL; - assert(fname && ss && chunk); + void *ptr = NULL; + + assert(fname); + assert(ss); + assert(chunk); chunk->memblock = NULL; chunk->index = chunk->length = 0; @@ -97,8 +101,10 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, chunk->index = 0; chunk->length = l; - if ((readf_function && readf_function(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) || - (!readf_function && sf_read_raw(sf, chunk->memblock->data, l) != l)) { + ptr = pa_memblock_acquire(chunk->memblock); + + if ((readf_function && readf_function(sf, ptr, sfinfo.frames) != sfinfo.frames) || + (!readf_function && sf_read_raw(sf, ptr, l) != l)) { pa_log("Premature file end"); goto finish; } @@ -110,6 +116,9 @@ finish: if (sf) sf_close(sf); + if (ptr) + pa_memblock_release(chunk->memblock); + if (ret != 0 && chunk->memblock) pa_memblock_unref(chunk->memblock); diff --git a/src/tests/flist-test.c b/src/tests/flist-test.c index abc0659d9..06d683110 100644 --- a/src/tests/flist-test.c +++ b/src/tests/flist-test.c @@ -54,7 +54,7 @@ static void thread_func(void *data) { int b = 1; while (!quit) { - char *text, *t; + char *text; /* Allocate some memory, if possible take it from the flist */ if (b && (text = pa_flist_pop(flist))) diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index 356916984..1584256cb 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -59,24 +59,27 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { c.index = c.length = 0; } - assert(c.index < c.memblock->length); + assert(c.index < pa_memblock_get_length(c.memblock)); - l = c.memblock->length - c.index; + l = pa_memblock_get_length(c.memblock) - c.index; l = l <= 1 ? l : rand() % (l-1) +1 ; - - if ((r = read(STDIN_FILENO, (uint8_t*) c.memblock->data + c.index, l)) <= 0) { + + p = pa_memblock_acquire(c.memblock); + if ((r = read(STDIN_FILENO, (uint8_t*) p + c.index, l)) <= 0) { + pa_memblock_release(c.memblock); fprintf(stderr, "read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); break; } - + pa_memblock_release(c.memblock); + c.length = r; pa_mcalign_push(a, &c); fprintf(stderr, "Read %ld bytes\n", (long)r); c.index += r; - if (c.index >= c.memblock->length) { + if (c.index >= pa_memblock_get_length(c.memblock)) { pa_memblock_unref(c.memblock); pa_memchunk_reset(&c); } @@ -87,7 +90,9 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { if (pa_mcalign_pop(a, &t) < 0) break; - pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length, NULL); + p = pa_memblock_acquire(t.memblock); + pa_loop_write(STDOUT_FILENO, (uint8_t*) p + t.index, t.length, NULL); + pa_memblock_release(t.memblock); fprintf(stderr, "Wrote %lu bytes.\n", (unsigned long) t.length); pa_memblock_unref(t.memblock); diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c index ef2e0ad71..c2dd2efa5 100644 --- a/src/tests/memblock-test.c +++ b/src/tests/memblock-test.c @@ -76,6 +76,7 @@ int main(int argc, char *argv[]) { pa_memblock* blocks[5]; uint32_t id, shm_id; size_t offset, size; + char *x; const char txt[] = "This is a test!"; @@ -90,10 +91,17 @@ int main(int argc, char *argv[]) { assert(pool_a && pool_b && pool_c); blocks[0] = pa_memblock_new_fixed(pool_a, (void*) txt, sizeof(txt), 1); + blocks[1] = pa_memblock_new(pool_a, sizeof(txt)); - snprintf(blocks[1]->data, blocks[1]->length, "%s", txt); + x = pa_memblock_acquire(blocks[1]); + snprintf(x, pa_memblock_get_length(blocks[1]), "%s", txt); + pa_memblock_release(blocks[1]); + blocks[2] = pa_memblock_new_pool(pool_a, sizeof(txt)); - snprintf(blocks[2]->data, blocks[2]->length, "%s", txt); + x = pa_memblock_acquire(blocks[2]); + snprintf(x, pa_memblock_get_length(blocks[2]), "%s", txt); + pa_memblock_release(blocks[1]); + blocks[3] = pa_memblock_new_malloced(pool_a, pa_xstrdup(txt), sizeof(txt)); blocks[4] = NULL; @@ -130,14 +138,18 @@ int main(int argc, char *argv[]) { mb_c = pa_memimport_get(import_c, id, shm_id, offset, size); assert(mb_c); - printf("1 data=%s\n", (char*) mb_c->data); + x = pa_memblock_acquire(mb_c); + printf("1 data=%s\n", x); + pa_memblock_release(mb_c); print_stats(pool_a, "A"); print_stats(pool_b, "B"); print_stats(pool_c, "C"); pa_memexport_free(export_b); - printf("2 data=%s\n", (char*) mb_c->data); + x = pa_memblock_acquire(mb_c); + printf("2 data=%s\n", x); + pa_memblock_release(mb_c); pa_memblock_unref(mb_c); pa_memimport_free(import_b); diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c index 1ac4577b5..02848eb22 100644 --- a/src/tests/memblockq-test.c +++ b/src/tests/memblockq-test.c @@ -131,8 +131,10 @@ int main(int argc, char *argv[]) { if (pa_memblockq_peek(bq, &out) < 0) break; - for (e = (char*) out.memblock->data + out.index, n = 0; n < out.length; n++) + p = pa_memblock_acquire(out.memblock); + for (e = (char*) p + out.index, n = 0; n < out.length; n++) printf("%c", *e); + pa_memblock_release(out.memblock); pa_memblock_unref(out.memblock); pa_memblockq_drop(bq, &out, out.length); From 977659684855d30d48958910f92593e94dbb8da8 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 6 Nov 2006 10:14:16 +0000 Subject: [PATCH 1304/1514] Handle when threaded mainloop is freed before it is started. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1405 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/thread-mainloop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c index 060782b57..7e1ccfaa6 100644 --- a/src/pulse/thread-mainloop.c +++ b/src/pulse/thread-mainloop.c @@ -120,7 +120,8 @@ void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { pa_threaded_mainloop_stop(m); - pa_thread_free(m->thread); + if (m->thread) + pa_thread_free(m->thread); pa_mainloop_free(m->real_mainloop); From 6ca819354cabdaeda0b122535a50fa49924d8d2d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 6 Nov 2006 10:17:39 +0000 Subject: [PATCH 1305/1514] The OSS spec is unclear what should happen when a reset is requested. Let's have a nicer attitude and keep as much settings as possible. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1406 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index c7bfe5abd..5d96a984e 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1003,12 +1003,21 @@ static void free_streams(fd_info *i) { pa_stream_disconnect(i->play_stream); pa_stream_unref(i->play_stream); i->play_stream = NULL; + i->io_flags |= PA_IO_EVENT_INPUT; } if (i->rec_stream) { pa_stream_disconnect(i->rec_stream); pa_stream_unref(i->rec_stream); i->rec_stream = NULL; + i->io_flags |= PA_IO_EVENT_OUTPUT; + } + + if (i->io_event) { + pa_mainloop_api *api; + + api = pa_threaded_mainloop_get_api(i->mainloop); + api->io_enable(i->io_event, i->io_flags); } } @@ -1954,7 +1963,6 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) free_streams(i); dsp_flush_socket(i); - reset_params(i); i->optr_n_blocks = 0; From 8dc62142765249addf131b058c27f931ede1776b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 6 Nov 2006 13:06:01 +0000 Subject: [PATCH 1306/1514] Revert r1404 and keep it on a development branch until it is fully tested. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1409 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 7 +- src/modules/module-alsa-sink.c | 14 +- src/modules/module-alsa-source.c | 10 +- src/modules/module-esound-sink.c | 11 +- src/modules/module-jack-sink.c | 5 +- src/modules/module-jack-source.c | 7 +- src/modules/module-oss-mmap.c | 4 +- src/modules/module-oss.c | 22 +- src/modules/module-pipe-sink.c | 11 +- src/modules/module-pipe-source.c | 13 +- src/modules/module-sine.c | 14 +- src/modules/rtp/rtp.c | 18 +- src/pulse/internal.h | 1 - src/pulse/stream.c | 20 +- src/pulsecore/cli-command.c | 20 +- src/pulsecore/mcalign.c | 10 +- src/pulsecore/memblock.c | 507 +++++++----------------------- src/pulsecore/memblock.h | 57 ++-- src/pulsecore/memblockq.c | 10 +- src/pulsecore/memchunk.c | 15 +- src/pulsecore/play-memchunk.c | 2 +- src/pulsecore/protocol-esound.c | 38 +-- src/pulsecore/protocol-native.c | 14 +- src/pulsecore/protocol-simple.c | 22 +- src/pulsecore/pstream.c | 169 +++++----- src/pulsecore/resampler.c | 245 +++++++-------- src/pulsecore/sample-util.c | 116 ++----- src/pulsecore/sample-util.h | 3 +- src/pulsecore/sink-input.c | 9 +- src/pulsecore/sink.c | 26 +- src/pulsecore/sound-file-stream.c | 9 +- src/pulsecore/sound-file.c | 15 +- src/tests/flist-test.c | 2 +- src/tests/mcalign-test.c | 19 +- src/tests/memblock-test.c | 20 +- src/tests/memblockq-test.c | 4 +- 36 files changed, 499 insertions(+), 990 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 0ce805ec0..64df8614d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -268,7 +268,8 @@ thread_test_CFLAGS = $(AM_CFLAGS) thread_test_LDADD = $(AM_LDADD) libpulsecore.la thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -flist_test_SOURCES = tests/flist-test.c +flist_test_SOURCES = tests/flist-test.c \ + pulsecore/flist.c pulsecore/flist.h flist_test_CFLAGS = $(AM_CFLAGS) flist_test_LDADD = $(AM_LDADD) libpulsecore.la flist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -447,8 +448,6 @@ libpulse_la_SOURCES += \ pulsecore/core-error.c pulsecore/core-error.h \ pulsecore/winsock.h pulsecore/creds.h \ pulsecore/shm.c pulsecore/shm.h \ - pulsecore/flist.c pulsecore/flist.h \ - pulsecore/anotify.c pulsecore/anotify.h \ $(PA_THREAD_OBJS) if OS_IS_WIN32 @@ -629,8 +628,6 @@ libpulsecore_la_SOURCES += \ pulsecore/core-error.c pulsecore/core-error.h \ pulsecore/hook-list.c pulsecore/hook-list.h \ pulsecore/shm.c pulsecore/shm.h \ - pulsecore/flist.c pulsecore/flist.h \ - pulsecore/anotify.c pulsecore/anotify.h \ $(PA_THREAD_OBJS) if OS_IS_WIN32 diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 7bbd7de2f..6ff9a6e49 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -144,7 +144,6 @@ static void do_write(struct userdata *u) { update_usage(u); for (;;) { - void *p; pa_memchunk *memchunk = NULL; snd_pcm_sframes_t frames; @@ -157,15 +156,9 @@ static void do_write(struct userdata *u) { memchunk = &u->memchunk; } - assert(memchunk->memblock); - assert(memchunk->length); - assert((memchunk->length % u->frame_size) == 0); + assert(memchunk->memblock && memchunk->memblock->data && memchunk->length && memchunk->memblock->length && (memchunk->length % u->frame_size) == 0); - p = pa_memblock_acquire(memchunk->memblock); - - if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) p + memchunk->index, memchunk->length / u->frame_size)) < 0) { - pa_memblock_release(memchunk->memblock); - + if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) { if (frames == -EAGAIN) return; @@ -183,9 +176,6 @@ static void do_write(struct userdata *u) { return; } - pa_memblock_release(memchunk->memblock); - - if (memchunk == &u->memchunk) { size_t l = frames * u->frame_size; memchunk->index += l; diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 9bde46dab..aa0666f10 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -149,7 +149,6 @@ static void do_read(struct userdata *u) { pa_memchunk post_memchunk; snd_pcm_sframes_t frames; size_t l; - void *p; if (!u->memchunk.memblock) { u->memchunk.memblock = pa_memblock_new(u->source->core->mempool, u->memchunk.length = u->fragment_size); @@ -158,13 +157,11 @@ static void do_read(struct userdata *u) { assert(u->memchunk.memblock); assert(u->memchunk.length); + assert(u->memchunk.memblock->data); + assert(u->memchunk.memblock->length); assert(u->memchunk.length % u->frame_size == 0); - p = pa_memblock_acquire(u->memchunk.memblock); - - if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) { - pa_memblock_release(u->memchunk.memblock); - + if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) { if (frames == -EAGAIN) return; @@ -181,7 +178,6 @@ static void do_read(struct userdata *u) { pa_module_unload_request(u->module); return; } - pa_memblock_release(u->memchunk.memblock); l = frames * u->frame_size; diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index ca1f16ced..6d4a84891 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -142,25 +142,18 @@ static int do_write(struct userdata *u) { u->write_index = u->write_length = 0; } } else if (u->state == STATE_RUNNING) { - void *p; - pa_module_set_used(u->module, pa_sink_used_by(u->sink)); if (!u->memchunk.length) if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0) return 0; - assert(u->memchunk.memblock); - assert(u->memchunk.length); - - p = pa_memblock_acquire(u->memchunk.memblock); + assert(u->memchunk.memblock && u->memchunk.length); - if ((r = pa_iochannel_write(u->io, (uint8_t*) p + u->memchunk.index, u->memchunk.length)) < 0) { - pa_memblock_release(u->memchunk.memblock); + if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { pa_log("write() failed: %s", pa_cstrerror(errno)); return -1; } - pa_memblock_release(u->memchunk.memblock); u->memchunk.index += r; u->memchunk.length -= r; diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 66ded27ff..47f77bab3 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -135,25 +135,22 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_ unsigned fs; jack_nframes_t frame_idx; pa_memchunk chunk; - void *p; fs = pa_frame_size(&u->sink->sample_spec); pa_sink_render_full(u->sink, u->frames_requested * fs, &chunk); - p = pa_memblock_acquire(chunk.memblock); for (frame_idx = 0; frame_idx < u->frames_requested; frame_idx ++) { unsigned c; for (c = 0; c < u->channels; c++) { - float *s = ((float*) ((uint8_t*) p + chunk.index)) + (frame_idx * u->channels) + c; + float *s = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c; float *d = ((float*) u->buffer[c]) + frame_idx; *d = *s; } } - pa_memblock_release(chunk.memblock); pa_memblock_unref(chunk.memblock); u->frames_requested = 0; diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 5270b2410..62a991087 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -134,28 +134,23 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_ unsigned fs; jack_nframes_t frame_idx; pa_memchunk chunk; - void *p; fs = pa_frame_size(&u->source->sample_spec); chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length = u->frames_posted * fs); chunk.index = 0; - - p = pa_memblock_acquire(chunk.memblock); for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) { unsigned c; for (c = 0; c < u->channels; c++) { float *s = ((float*) u->buffer[c]) + frame_idx; - float *d = ((float*) ((uint8_t*) p + chunk.index)) + (frame_idx * u->channels) + c; + float *d = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c; *d = *s; } } - pa_memblock_release(chunk.memblock); - pa_source_post(u->source, &chunk); pa_memblock_unref(chunk.memblock); diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 39a8511f0..5ab082878 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -170,7 +170,7 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { u->out_fragment_size, 1); assert(chunk.memblock); - chunk.length = pa_memblock_get_length(chunk.memblock); + chunk.length = chunk.memblock->length; chunk.index = 0; pa_sink_render_into_full(u->sink, &chunk); @@ -214,7 +214,7 @@ static void in_post_memblocks(struct userdata *u, unsigned n) { if (!u->in_memblocks[u->in_current]) { chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->core->mempool, (uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, 1); - chunk.length = pa_memblock_get_length(chunk.memblock); + chunk.length = chunk.memblock->length; chunk.index = 0; pa_source_post(u->source, &chunk); diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 73f0d57ef..b71581d9a 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -155,7 +155,6 @@ static void do_write(struct userdata *u) { } do { - void *p; memchunk = &u->memchunk; if (!memchunk->length) @@ -163,18 +162,16 @@ static void do_write(struct userdata *u) { memchunk = &u->silence; assert(memchunk->memblock); + assert(memchunk->memblock->data); assert(memchunk->length); - - p = pa_memblock_acquire(memchunk->memblock); - if ((r = pa_iochannel_write(u->io, (uint8_t*) p + memchunk->index, memchunk->length)) < 0) { - pa_memblock_release(memchunk->memblock); + + if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { pa_log("write() failed: %s", pa_cstrerror(errno)); clear_up(u); pa_module_unload_request(u->module); break; } - pa_memblock_release(memchunk->memblock); if (memchunk == &u->silence) assert(r % u->sample_size == 0); @@ -220,13 +217,9 @@ static void do_read(struct userdata *u) { } do { - void *p; memchunk.memblock = pa_memblock_new(u->core->mempool, l); - - p = pa_memblock_acquire(memchunk.memblock); - - if ((r = pa_iochannel_read(u->io, p, pa_memblock_get_length(memchunk.memblock))) < 0) { - pa_memblock_release(memchunk.memblock); + assert(memchunk.memblock); + if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); if (errno != EAGAIN) { pa_log("read() failed: %s", pa_cstrerror(errno)); @@ -235,10 +228,9 @@ static void do_read(struct userdata *u) { } break; } - pa_memblock_release(memchunk.memblock); - assert(r <= (ssize_t) pa_memblock_get_length(memchunk.memblock)); - memchunk.length = r; + assert(r <= (ssize_t) memchunk.memblock->length); + memchunk.length = memchunk.memblock->length = r; memchunk.index = 0; pa_source_post(u->source, &memchunk); diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 59d91aa4b..4aee849bb 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -84,8 +84,6 @@ static const char* const valid_modargs[] = { static void do_write(struct userdata *u) { ssize_t r; - void *p; - assert(u); u->core->mainloop->defer_enable(u->defer_event, 0); @@ -99,17 +97,12 @@ static void do_write(struct userdata *u) { if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) return; - assert(u->memchunk.memblock); - assert(u->memchunk.length); - - p = pa_memblock_acquire(u->memchunk.memblock); + assert(u->memchunk.memblock && u->memchunk.length); - if ((r = pa_iochannel_write(u->io, (uint8_t*) p + u->memchunk.index, u->memchunk.length)) < 0) { - pa_memblock_release(u->memchunk.memblock); + if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { pa_log("write(): %s", pa_cstrerror(errno)); return; } - pa_memblock_release(u->memchunk.memblock); u->memchunk.index += r; u->memchunk.length -= r; diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index 99f4f3b97..c251f7ac3 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -82,9 +82,7 @@ static const char* const valid_modargs[] = { static void do_read(struct userdata *u) { ssize_t r; - void *p; pa_memchunk chunk; - assert(u); if (!pa_iochannel_is_readable(u->io)) @@ -97,22 +95,17 @@ static void do_read(struct userdata *u) { u->chunk.index = chunk.length = 0; } - assert(u->chunk.memblock); - assert(pa_memblock_get_length(u->chunk.memblock) > u->chunk.index); - - p = pa_memblock_acquire(u->chunk.memblock); - if ((r = pa_iochannel_read(u->io, (uint8_t*) p + u->chunk.index, pa_memblock_get_length(u->chunk.memblock) - u->chunk.index)) <= 0) { - pa_memblock_release(u->chunk.memblock); + assert(u->chunk.memblock && u->chunk.memblock->length > u->chunk.index); + if ((r = pa_iochannel_read(u->io, (uint8_t*) u->chunk.memblock->data + u->chunk.index, u->chunk.memblock->length - u->chunk.index)) <= 0) { pa_log("read(): %s", pa_cstrerror(errno)); return; } - pa_memblock_release(u->chunk.memblock); u->chunk.length = r; pa_source_post(u->source, &u->chunk); u->chunk.index += r; - if (u->chunk.index >= pa_memblock_get_length(u->chunk.memblock)) { + if (u->chunk.index >= u->chunk.memblock->length) { u->chunk.index = u->chunk.length = 0; pa_memblock_unref(u->chunk.memblock); u->chunk.memblock = NULL; diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index f65b1f3a6..fa29ba160 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -63,7 +63,7 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { chunk->memblock = pa_memblock_ref(u->memblock); chunk->index = u->peek_index; - chunk->length = pa_memblock_get_length(u->memblock) - u->peek_index; + chunk->length = u->memblock->length - u->peek_index; return 0; } @@ -72,12 +72,11 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t l assert(i && chunk && length && i->userdata); u = i->userdata; - assert(chunk->memblock == u->memblock); - assert(length <= pa_memblock_get_length(u->memblock)-u->peek_index); + assert(chunk->memblock == u->memblock && length <= u->memblock->length-u->peek_index); u->peek_index += length; - if (u->peek_index >= pa_memblock_get_length(u->memblock)) + if (u->peek_index >= u->memblock->length) u->peek_index = 0; } @@ -110,7 +109,6 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; uint32_t frequency; char t[256]; - void *p; pa_sink_input_new_data data; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -142,10 +140,8 @@ int pa__init(pa_core *c, pa_module*m) { } u->memblock = pa_memblock_new(c->mempool, pa_bytes_per_second(&ss)); - p = pa_memblock_acquire(u->memblock); - calc_sine(p, pa_memblock_get_length(u->memblock), frequency); - pa_memblock_release(u->memblock); - + calc_sine(u->memblock->data, u->memblock->length, frequency); + snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); pa_sink_input_new_data_init(&data); diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index a4362f84d..3bb0ea473 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -79,7 +79,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { size_t k = n + chunk.length > size ? size - n : chunk.length; if (chunk.memblock) { - iov[iov_idx].iov_base = (void*)((uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index); + iov[iov_idx].iov_base = (void*)((uint8_t*) chunk.memblock->data + chunk.index); iov[iov_idx].iov_len = k; mb[iov_idx] = chunk.memblock; iov_idx ++; @@ -114,10 +114,8 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { k = sendmsg(c->fd, &m, MSG_DONTWAIT); - for (i = 1; i < iov_idx; i++) { - pa_memblock_release(mb[i]); + for (i = 1; i < iov_idx; i++) pa_memblock_unref(mb[i]); - } c->sequence++; } else @@ -174,7 +172,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { chunk->memblock = pa_memblock_new(pool, size); - iov.iov_base = pa_memblock_acquire(chunk->memblock); + iov.iov_base = chunk->memblock->data; iov.iov_len = size; m.msg_name = NULL; @@ -195,9 +193,9 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { goto fail; } - memcpy(&header, iov.iov_base, sizeof(uint32_t)); - memcpy(&c->timestamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t)); - memcpy(&c->ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t)); + memcpy(&header, chunk->memblock->data, sizeof(uint32_t)); + memcpy(&c->timestamp, (uint8_t*) chunk->memblock->data + 4, sizeof(uint32_t)); + memcpy(&c->ssrc, (uint8_t*) chunk->memblock->data + 8, sizeof(uint32_t)); header = ntohl(header); c->timestamp = ntohl(c->timestamp); @@ -238,10 +236,8 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { return 0; fail: - if (chunk->memblock) { - pa_memblock_release(chunk->memblock); + if (chunk->memblock) pa_memblock_unref(chunk->memblock); - } return -1; } diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 76d80d836..4eef4b4ad 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -113,7 +113,6 @@ struct pa_stream { uint32_t requested_bytes; pa_memchunk peek_memchunk; - void *peek_data; pa_memblockq *record_memblockq; int corked; diff --git a/src/pulse/stream.c b/src/pulse/stream.c index d31127d88..180cd096d 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -88,7 +88,6 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->peek_memchunk.index = 0; s->peek_memchunk.length = 0; s->peek_memchunk.memblock = NULL; - s->peek_data = NULL; s->record_memblockq = NULL; @@ -123,11 +122,8 @@ static void stream_free(pa_stream *s) { s->mainloop->time_free(s->auto_timing_update_event); } - if (s->peek_memchunk.memblock) { - if (s->peek_data) - pa_memblock_release(s->peek_memchunk.memblock); + if (s->peek_memchunk.memblock) pa_memblock_unref(s->peek_memchunk.memblock); - } if (s->record_memblockq) pa_memblockq_free(s->record_memblockq); @@ -609,11 +605,8 @@ int pa_stream_write( if (free_cb) chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) data, length, free_cb, 1); else { - void *tdata; chunk.memblock = pa_memblock_new(s->context->mempool, length); - tdata = pa_memblock_acquire(chunk.memblock); - memcpy(tdata, data, length); - pa_memblock_release(chunk.memblock); + memcpy(chunk.memblock->data, data, length); } chunk.index = 0; @@ -679,12 +672,9 @@ int pa_stream_peek(pa_stream *s, const void **data, size_t *length) { *length = 0; return 0; } - - s->peek_data = pa_memblock_acquire(s->peek_memchunk.memblock); } - assert(s->peek_data); - *data = (uint8_t*) s->peek_data + s->peek_memchunk.index; + *data = (const char*) s->peek_memchunk.memblock->data + s->peek_memchunk.index; *length = s->peek_memchunk.length; return 0; } @@ -702,9 +692,7 @@ int pa_stream_drop(pa_stream *s) { /* Fix the simulated local read index */ if (s->timing_info_valid && !s->timing_info.read_index_corrupt) s->timing_info.read_index += s->peek_memchunk.length; - - assert(s->peek_data); - pa_memblock_release(s->peek_memchunk.memblock); + pa_memblock_unref(s->peek_memchunk.memblock); s->peek_memchunk.length = 0; s->peek_memchunk.index = 0; diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index d7e4a75c7..ae475c3a0 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -259,20 +259,20 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G stat = pa_mempool_get_stat(c->mempool); pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n", - (unsigned) pa_atomic_load(&stat->n_allocated), - pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->allocated_size))); + (unsigned) AO_load_acquire_read((AO_t*) &stat->n_allocated), + pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->allocated_size))); pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n", - (unsigned) pa_atomic_load(&stat->n_accumulated), - pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->accumulated_size))); + (unsigned) AO_load_acquire_read((AO_t*) &stat->n_accumulated), + pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->accumulated_size))); pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n", - (unsigned) pa_atomic_load(&stat->n_imported), - pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->imported_size))); + (unsigned) AO_load_acquire_read((AO_t*) &stat->n_imported), + pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->imported_size))); pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n", - (unsigned) pa_atomic_load(&stat->n_exported), - pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->exported_size))); + (unsigned) AO_load_acquire_read((AO_t*) &stat->n_exported), + pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->exported_size))); pa_strbuf_printf(buf, "Total sample cache size: %s.\n", pa_bytes_snprint(s, sizeof(s), pa_scache_total_size(c))); @@ -289,8 +289,8 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_strbuf_printf(buf, "Memory blocks of type %s: %u allocated/%u accumulated.\n", type_table[k], - (unsigned) pa_atomic_load(&stat->n_allocated_by_type[k]), - (unsigned) pa_atomic_load(&stat->n_accumulated_by_type[k])); + (unsigned) AO_load_acquire_read(&stat->n_allocated_by_type[k]), + (unsigned) AO_load_acquire_read(&stat->n_accumulated_by_type[k])); return 0; } diff --git a/src/pulsecore/mcalign.c b/src/pulsecore/mcalign.c index aa2eae469..9ede610d7 100644 --- a/src/pulsecore/mcalign.c +++ b/src/pulsecore/mcalign.c @@ -89,7 +89,6 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { } else { size_t l; - void *lo_data, *m_data; /* We have to copy */ assert(m->leftover.length < m->base); @@ -101,15 +100,10 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { /* Can we use the current block? */ pa_memchunk_make_writable(&m->leftover, m->base); - lo_data = pa_memblock_acquire(m->leftover.memblock); - m_data = pa_memblock_acquire(c->memblock); - memcpy((uint8_t*) lo_data + m->leftover.index + m->leftover.length, (uint8_t*) m_data + c->index, l); - pa_memblock_release(m->leftover.memblock); - pa_memblock_release(c->memblock); + memcpy((uint8_t*) m->leftover.memblock->data + m->leftover.index + m->leftover.length, (uint8_t*) c->memblock->data + c->index, l); m->leftover.length += l; - assert(m->leftover.length <= m->base); - assert(m->leftover.length <= pa_memblock_get_length(m->leftover.memblock)); + assert(m->leftover.length <= m->base && m->leftover.length <= m->leftover.memblock->length); if (c->length > l) { /* Save the remainder of the memory block */ diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index f11a71745..9cfd79b5e 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -30,13 +30,10 @@ #include #include -#include #include #include #include -#include -#include #include "memblock.h" @@ -48,32 +45,6 @@ #define PA_MEMIMPORT_SLOTS_MAX 128 #define PA_MEMIMPORT_SEGMENTS_MAX 16 -struct pa_memblock { - PA_REFCNT_DECLARE; /* the reference counter */ - pa_mempool *pool; - - pa_memblock_type_t type; - int read_only; /* boolean */ - - pa_atomic_ptr_t data; - size_t length; - - pa_atomic_int_t n_acquired; - pa_atomic_int_t please_signal; - - union { - struct { - /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ - pa_free_cb_t free_cb; - } user; - - struct { - uint32_t id; - pa_memimport_segment *segment; - } imported; - } per_type; -}; - struct pa_memimport_segment { pa_memimport *import; pa_shm memory; @@ -81,8 +52,6 @@ struct pa_memimport_segment { }; struct pa_memimport { - pa_mutex *mutex; - pa_mempool *pool; pa_hashmap *segments; pa_hashmap *blocks; @@ -101,11 +70,9 @@ struct memexport_slot { }; struct pa_memexport { - pa_mutex *mutex; pa_mempool *pool; struct memexport_slot slots[PA_MEMEXPORT_SLOTS_MAX]; - PA_LLIST_HEAD(struct memexport_slot, free_slots); PA_LLIST_HEAD(struct memexport_slot, used_slots); unsigned n_init; @@ -125,71 +92,63 @@ struct mempool_slot { }; struct pa_mempool { - pa_mutex *mutex; - pa_cond *cond; - pa_shm memory; size_t block_size; - unsigned n_blocks; - - pa_atomic_int_t n_init; + unsigned n_blocks, n_init; PA_LLIST_HEAD(pa_memimport, imports); PA_LLIST_HEAD(pa_memexport, exports); /* A list of free slots that may be reused */ - pa_flist *free_slots; + PA_LLIST_HEAD(struct mempool_slot, free_slots); pa_mempool_stat stat; }; static void segment_detach(pa_memimport_segment *seg); -/* No lock necessary */ static void stat_add(pa_memblock*b) { assert(b); assert(b->pool); - pa_atomic_inc(&b->pool->stat.n_allocated); - pa_atomic_add(&b->pool->stat.allocated_size, (int) b->length); + AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated); + AO_fetch_and_add_release_write(&b->pool->stat.allocated_size, (AO_t) b->length); - pa_atomic_inc(&b->pool->stat.n_accumulated); - pa_atomic_add(&b->pool->stat.accumulated_size, (int) b->length); + AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated); + AO_fetch_and_add_release_write(&b->pool->stat.accumulated_size, (AO_t) b->length); if (b->type == PA_MEMBLOCK_IMPORTED) { - pa_atomic_inc(&b->pool->stat.n_imported); - pa_atomic_add(&b->pool->stat.imported_size, (int) b->length); + AO_fetch_and_add1_release_write(&b->pool->stat.n_imported); + AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) b->length); } - pa_atomic_inc(&b->pool->stat.n_allocated_by_type[b->type]); - pa_atomic_inc(&b->pool->stat.n_accumulated_by_type[b->type]); + AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); + AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated_by_type[b->type]); } -/* No lock necessary */ static void stat_remove(pa_memblock *b) { assert(b); assert(b->pool); - assert(pa_atomic_load(&b->pool->stat.n_allocated) > 0); - assert(pa_atomic_load(&b->pool->stat.allocated_size) >= (int) b->length); + assert(AO_load_acquire_read(&b->pool->stat.n_allocated) > 0); + assert(AO_load_acquire_read(&b->pool->stat.allocated_size) >= (AO_t) b->length); - pa_atomic_dec(&b->pool->stat.n_allocated); - pa_atomic_add(&b->pool->stat.allocated_size, - (int) b->length); + AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated); + AO_fetch_and_add_release_write(&b->pool->stat.allocated_size, (AO_t) (-b->length)); if (b->type == PA_MEMBLOCK_IMPORTED) { - assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); - assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); + assert(AO_load_acquire_read(&b->pool->stat.n_imported) > 0); + assert(AO_load_acquire_read(&b->pool->stat.imported_size) >= (AO_t) b->length); - pa_atomic_dec(&b->pool->stat.n_imported); - pa_atomic_add(&b->pool->stat.imported_size, - (int) b->length); + AO_fetch_and_sub1_release_write(&b->pool->stat.n_imported); + AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) (-b->length)); } - pa_atomic_dec(&b->pool->stat.n_allocated_by_type[b->type]); + AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); } static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length); -/* No lock necessary */ pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) { pa_memblock *b; @@ -202,7 +161,6 @@ pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) { return b; } -/* No lock necessary */ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) { pa_memblock *b; @@ -210,61 +168,49 @@ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) { assert(length > 0); b = pa_xmalloc(sizeof(pa_memblock) + length); - PA_REFCNT_INIT(b); - b->pool = p; b->type = PA_MEMBLOCK_APPENDED; b->read_only = 0; - pa_atomic_ptr_store(&b->data, (uint8_t*)b + sizeof(pa_memblock)); + PA_REFCNT_INIT(b); b->length = length; - pa_atomic_store(&b->n_acquired, 0); - pa_atomic_store(&b->please_signal, 0); - + b->data = (uint8_t*) b + sizeof(pa_memblock); + b->pool = p; + stat_add(b); return b; } -/* No lock necessary */ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { struct mempool_slot *slot; assert(p); - if (!(slot = pa_flist_pop(p->free_slots))) { - int idx; - - /* The free list was empty, we have to allocate a new entry */ - - if ((unsigned) (idx = pa_atomic_inc(&p->n_init)) >= p->n_blocks) - pa_atomic_dec(&p->n_init); - else - slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * idx)); - - if (!slot) { - pa_log_debug("Pool full"); - pa_atomic_inc(&p->stat.n_pool_full); - } + if (p->free_slots) { + slot = p->free_slots; + PA_LLIST_REMOVE(struct mempool_slot, p->free_slots, slot); + } else if (p->n_init < p->n_blocks) + slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * p->n_init++)); + else { + pa_log_debug("Pool full"); + AO_fetch_and_add1_release_write(&p->stat.n_pool_full); + return NULL; } return slot; } -/* No lock necessary */ static void* mempool_slot_data(struct mempool_slot *slot) { assert(slot); return (uint8_t*) slot + sizeof(struct mempool_slot); } -/* No lock necessary */ static unsigned mempool_slot_idx(pa_mempool *p, void *ptr) { assert(p); - assert((uint8_t*) ptr >= (uint8_t*) p->memory.ptr); assert((uint8_t*) ptr < (uint8_t*) p->memory.ptr + p->memory.size); return ((uint8_t*) ptr - (uint8_t*) p->memory.ptr) / p->block_size; } -/* No lock necessary */ static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) { unsigned idx; @@ -274,7 +220,6 @@ static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) { return (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (idx * p->block_size)); } -/* No lock necessary */ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { pa_memblock *b = NULL; struct mempool_slot *slot; @@ -289,7 +234,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { b = mempool_slot_data(slot); b->type = PA_MEMBLOCK_POOL; - pa_atomic_ptr_store(&b->data, (uint8_t*) b + sizeof(pa_memblock)); + b->data = (uint8_t*) b + sizeof(pa_memblock); } else if (p->block_size - sizeof(struct mempool_slot) >= length) { @@ -298,26 +243,22 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { b = pa_xnew(pa_memblock, 1); b->type = PA_MEMBLOCK_POOL_EXTERNAL; - pa_atomic_ptr_store(&b->data, mempool_slot_data(slot)); - + b->data = mempool_slot_data(slot); } else { pa_log_debug("Memory block too large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot)); - pa_atomic_inc(&p->stat.n_too_large_for_pool); + AO_fetch_and_add1_release_write(&p->stat.n_too_large_for_pool); return NULL; } + b->length = length; + b->read_only = 0; PA_REFCNT_INIT(b); b->pool = p; - b->read_only = 0; - b->length = length; - pa_atomic_store(&b->n_acquired, 0); - pa_atomic_store(&b->please_signal, 0); stat_add(b); return b; } -/* No lock necessary */ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int read_only) { pa_memblock *b; @@ -326,20 +267,17 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int re assert(length > 0); b = pa_xnew(pa_memblock, 1); - PA_REFCNT_INIT(b); - b->pool = p; b->type = PA_MEMBLOCK_FIXED; b->read_only = read_only; - pa_atomic_ptr_store(&b->data, d); + PA_REFCNT_INIT(b); b->length = length; - pa_atomic_store(&b->n_acquired, 0); - pa_atomic_store(&b->please_signal, 0); + b->data = d; + b->pool = p; stat_add(b); return b; } -/* No lock necessary */ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (*free_cb)(void *p), int read_only) { pa_memblock *b; @@ -349,72 +287,18 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (* assert(free_cb); b = pa_xnew(pa_memblock, 1); - PA_REFCNT_INIT(b); - b->pool = p; b->type = PA_MEMBLOCK_USER; b->read_only = read_only; - pa_atomic_ptr_store(&b->data, d); + PA_REFCNT_INIT(b); b->length = length; - pa_atomic_store(&b->n_acquired, 0); - pa_atomic_store(&b->please_signal, 0); - + b->data = d; b->per_type.user.free_cb = free_cb; + b->pool = p; stat_add(b); return b; } -/* No lock necessary */ -int pa_memblock_is_read_only(pa_memblock *b) { - assert(b); - assert(PA_REFCNT_VALUE(b) > 0); - - return b->read_only && PA_REFCNT_VALUE(b) == 1; -} - -/* No lock necessary */ -void* pa_memblock_acquire(pa_memblock *b) { - assert(b); - assert(PA_REFCNT_VALUE(b) > 0); - - pa_atomic_inc(&b->n_acquired); - - return pa_atomic_ptr_load(&b->data); -} - -/* No lock necessary, in corner cases locks by its own */ -void pa_memblock_release(pa_memblock *b) { - int r; - assert(b); - assert(PA_REFCNT_VALUE(b) > 0); - - r = pa_atomic_dec(&b->n_acquired); - assert(r >= 1); - - if (r == 1 && pa_atomic_load(&b->please_signal)) { - pa_mempool *p = b->pool; - /* Signal a waiting thread that this memblock is no longer used */ - pa_mutex_lock(p->mutex); - pa_cond_signal(p->cond, 1); - pa_mutex_unlock(p->mutex); - } -} - -size_t pa_memblock_get_length(pa_memblock *b) { - assert(b); - assert(PA_REFCNT_VALUE(b) > 0); - - return b->length; -} - -pa_mempool* pa_memblock_get_pool(pa_memblock *b) { - assert(b); - assert(PA_REFCNT_VALUE(b) > 0); - - return b->pool; -} - -/* No lock necessary */ pa_memblock* pa_memblock_ref(pa_memblock*b) { assert(b); assert(PA_REFCNT_VALUE(b) > 0); @@ -423,17 +307,19 @@ pa_memblock* pa_memblock_ref(pa_memblock*b) { return b; } -static void memblock_free(pa_memblock *b) { +void pa_memblock_unref(pa_memblock*b) { assert(b); - - assert(pa_atomic_load(&b->n_acquired) == 0); + assert(PA_REFCNT_VALUE(b) > 0); + if (PA_REFCNT_DEC(b) > 0) + return; + stat_remove(b); switch (b->type) { case PA_MEMBLOCK_USER : assert(b->per_type.user.free_cb); - b->per_type.user.free_cb(pa_atomic_ptr_load(&b->data)); + b->per_type.user.free_cb(b->data); /* Fall through */ @@ -444,23 +330,17 @@ static void memblock_free(pa_memblock *b) { case PA_MEMBLOCK_IMPORTED : { pa_memimport_segment *segment; - pa_memimport *import; - - /* FIXME! This should be implemented lock-free */ - + segment = b->per_type.imported.segment; assert(segment); - import = segment->import; - assert(import); + assert(segment->import); - pa_mutex_lock(import->mutex); - pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); + pa_hashmap_remove(segment->import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); + segment->import->release_cb(segment->import, b->per_type.imported.id, segment->import->userdata); + if (-- segment->n_blocks <= 0) segment_detach(segment); - pa_mutex_unlock(import->mutex); - - import->release_cb(import, b->per_type.imported.id, import->userdata); - + pa_xfree(b); break; } @@ -468,20 +348,13 @@ static void memblock_free(pa_memblock *b) { case PA_MEMBLOCK_POOL_EXTERNAL: case PA_MEMBLOCK_POOL: { struct mempool_slot *slot; - int call_free; - slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data)); + slot = mempool_slot_by_ptr(b->pool, b->data); assert(slot); - - call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL; - - /* The free list dimensions should easily allow all slots - * to fit in, hence try harder if pushing this slot into - * the free list fails */ - while (pa_flist_push(b->pool->free_slots, slot) < 0) - ; - if (call_free) + PA_LLIST_PREPEND(struct mempool_slot, b->pool->free_slots, slot); + + if (b->type == PA_MEMBLOCK_POOL_EXTERNAL) pa_xfree(b); break; @@ -493,42 +366,10 @@ static void memblock_free(pa_memblock *b) { } } -/* No lock necessary */ -void pa_memblock_unref(pa_memblock*b) { - assert(b); - assert(PA_REFCNT_VALUE(b) > 0); - - if (PA_REFCNT_DEC(b) > 0) - return; - - memblock_free(b); -} - -/* Self locked */ -static void memblock_wait(pa_memblock *b) { - assert(b); - - if (pa_atomic_load(&b->n_acquired) > 0) { - /* We need to wait until all threads gave up access to the - * memory block before we can go on. Unfortunately this means - * that we have to lock and wait here. Sniff! */ - - pa_atomic_inc(&b->please_signal); - - pa_mutex_lock(b->pool->mutex); - while (pa_atomic_load(&b->n_acquired) > 0) - pa_cond_wait(b->pool->cond, b->pool->mutex); - pa_mutex_unlock(b->pool->mutex); - - pa_atomic_dec(&b->please_signal); - } -} - -/* No lock necessary. This function is not multiple caller safe! */ static void memblock_make_local(pa_memblock *b) { assert(b); - pa_atomic_dec(&b->pool->stat.n_allocated_by_type[b->type]); + AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); if (b->length <= b->pool->block_size - sizeof(struct mempool_slot)) { struct mempool_slot *slot; @@ -537,61 +378,53 @@ static void memblock_make_local(pa_memblock *b) { void *new_data; /* We can move it into a local pool, perfect! */ - new_data = mempool_slot_data(slot); - memcpy(new_data, pa_atomic_ptr_load(&b->data), b->length); - pa_atomic_ptr_store(&b->data, new_data); - b->type = PA_MEMBLOCK_POOL_EXTERNAL; b->read_only = 0; + new_data = mempool_slot_data(slot); + memcpy(new_data, b->data, b->length); + b->data = new_data; goto finish; } } /* Humm, not enough space in the pool, so lets allocate the memory with malloc() */ - b->per_type.user.free_cb = pa_xfree; - pa_atomic_ptr_store(&b->data, pa_xmemdup(pa_atomic_ptr_load(&b->data), b->length)); - b->type = PA_MEMBLOCK_USER; + b->per_type.user.free_cb = pa_xfree; b->read_only = 0; + b->data = pa_xmemdup(b->data, b->length); finish: - pa_atomic_inc(&b->pool->stat.n_allocated_by_type[b->type]); - pa_atomic_inc(&b->pool->stat.n_accumulated_by_type[b->type]); - - memblock_wait(b); + AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); + AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated_by_type[b->type]); } -/* No lock necessary. This function is not multiple caller safe*/ void pa_memblock_unref_fixed(pa_memblock *b) { assert(b); assert(PA_REFCNT_VALUE(b) > 0); assert(b->type == PA_MEMBLOCK_FIXED); - if (PA_REFCNT_DEC(b) > 0) + if (PA_REFCNT_VALUE(b) > 1) memblock_make_local(b); - else - memblock_free(b); + + pa_memblock_unref(b); } -/* Self-locked. This function is not multiple-caller safe */ static void memblock_replace_import(pa_memblock *b) { pa_memimport_segment *seg; assert(b); assert(b->type == PA_MEMBLOCK_IMPORTED); - assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); - assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); - pa_atomic_dec(&b->pool->stat.n_imported); - pa_atomic_add(&b->pool->stat.imported_size, (int) - b->length); + assert(AO_load_acquire_read(&b->pool->stat.n_imported) > 0); + assert(AO_load_acquire_read(&b->pool->stat.imported_size) >= (AO_t) b->length); + AO_fetch_and_sub1_release_write(&b->pool->stat.n_imported); + AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) - b->length); seg = b->per_type.imported.segment; assert(seg); assert(seg->import); - pa_mutex_lock(seg->import->mutex); - pa_hashmap_remove( seg->import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); @@ -600,8 +433,6 @@ static void memblock_replace_import(pa_memblock *b) { if (-- seg->n_blocks <= 0) segment_detach(seg); - - pa_mutex_unlock(seg->import->mutex); } pa_mempool* pa_mempool_new(int shared) { @@ -610,15 +441,12 @@ pa_mempool* pa_mempool_new(int shared) { p = pa_xnew(pa_mempool, 1); - p->mutex = pa_mutex_new(1); - p->cond = pa_cond_new(); - #ifdef HAVE_SYSCONF ps = (size_t) sysconf(_SC_PAGESIZE); #elif defined(PAGE_SIZE) - ps = (size_t) PAGE_SIZE; + ps = (size_t) PAGE_SIZE; #else - ps = 4096; /* Let's hope it's like x86. */ + ps = 4096; /* Let's hope it's like x86. */ #endif p->block_size = (PA_MEMPOOL_SLOT_SIZE/ps)*ps; @@ -635,13 +463,13 @@ pa_mempool* pa_mempool_new(int shared) { return NULL; } - memset(&p->stat, 0, sizeof(p->stat)); - pa_atomic_store(&p->n_init, 0); + p->n_init = 0; PA_LLIST_HEAD_INIT(pa_memimport, p->imports); PA_LLIST_HEAD_INIT(pa_memexport, p->exports); + PA_LLIST_HEAD_INIT(struct mempool_slot, p->free_slots); - p->free_slots = pa_flist_new(p->n_blocks*2); + memset(&p->stat, 0, sizeof(p->stat)); return p; } @@ -649,62 +477,34 @@ pa_mempool* pa_mempool_new(int shared) { void pa_mempool_free(pa_mempool *p) { assert(p); - pa_mutex_lock(p->mutex); - while (p->imports) pa_memimport_free(p->imports); while (p->exports) pa_memexport_free(p->exports); - pa_mutex_unlock(p->mutex); - - if (pa_atomic_load(&p->stat.n_allocated) > 0) + if (AO_load_acquire_read(&p->stat.n_allocated) > 0) pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!"); - - pa_flist_free(p->free_slots, NULL); pa_shm_free(&p->memory); - - pa_mutex_free(p->mutex); - pa_cond_free(p->cond); - pa_xfree(p); } -/* No lock necessary */ const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p) { assert(p); return &p->stat; } -/* No lock necessary */ void pa_mempool_vacuum(pa_mempool *p) { struct mempool_slot *slot; - pa_flist *list; assert(p); - list = pa_flist_new(p->n_blocks*2); - - while ((slot = pa_flist_pop(p->free_slots))) - while (pa_flist_push(list, slot) < 0) - ; - - while ((slot = pa_flist_pop(list))) { - pa_shm_punch(&p->memory, - (uint8_t*) slot - (uint8_t*) p->memory.ptr + sizeof(struct mempool_slot), - p->block_size - sizeof(struct mempool_slot)); - - while (pa_flist_push(p->free_slots, slot)) - ; - } - - pa_flist_free(list, NULL); + for (slot = p->free_slots; slot; slot = slot->next) + pa_shm_punch(&p->memory, (uint8_t*) slot + sizeof(struct mempool_slot) - (uint8_t*) p->memory.ptr, p->block_size - sizeof(struct mempool_slot)); } -/* No lock necessary */ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) { assert(p); @@ -716,7 +516,6 @@ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) { return 0; } -/* No lock necessary */ int pa_mempool_is_shared(pa_mempool *p) { assert(p); @@ -731,23 +530,18 @@ pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void assert(cb); i = pa_xnew(pa_memimport, 1); - i->mutex = pa_mutex_new(0); i->pool = p; i->segments = pa_hashmap_new(NULL, NULL); i->blocks = pa_hashmap_new(NULL, NULL); i->release_cb = cb; i->userdata = userdata; - - pa_mutex_lock(p->mutex); + PA_LLIST_PREPEND(pa_memimport, p->imports, i); - pa_mutex_unlock(p->mutex); - return i; } static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i); -/* Should be called locked */ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) { pa_memimport_segment* seg; @@ -768,7 +562,6 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) { return seg; } -/* Should be called locked */ static void segment_detach(pa_memimport_segment *seg) { assert(seg); @@ -777,68 +570,51 @@ static void segment_detach(pa_memimport_segment *seg) { pa_xfree(seg); } -/* Self-locked. Not multiple-caller safe */ void pa_memimport_free(pa_memimport *i) { pa_memexport *e; pa_memblock *b; assert(i); - pa_mutex_lock(i->mutex); + /* If we've exported this block further we need to revoke that export */ + for (e = i->pool->exports; e; e = e->next) + memexport_revoke_blocks(e, i); while ((b = pa_hashmap_get_first(i->blocks))) memblock_replace_import(b); assert(pa_hashmap_size(i->segments) == 0); - - pa_mutex_unlock(i->mutex); - pa_mutex_lock(i->pool->mutex); - - /* If we've exported this block further we need to revoke that export */ - for (e = i->pool->exports; e; e = e->next) - memexport_revoke_blocks(e, i); - - PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i); - - pa_mutex_unlock(i->pool->mutex); - pa_hashmap_free(i->blocks, NULL, NULL); pa_hashmap_free(i->segments, NULL, NULL); - - pa_mutex_free(i->mutex); + PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i); pa_xfree(i); } -/* Self-locked */ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_id, size_t offset, size_t size) { - pa_memblock *b = NULL; + pa_memblock *b; pa_memimport_segment *seg; assert(i); - pa_mutex_lock(i->mutex); - if (pa_hashmap_size(i->blocks) >= PA_MEMIMPORT_SLOTS_MAX) - goto finish; + return NULL; if (!(seg = pa_hashmap_get(i->segments, PA_UINT32_TO_PTR(shm_id)))) if (!(seg = segment_attach(i, shm_id))) - goto finish; + return NULL; if (offset+size > seg->memory.size) - goto finish; - + return NULL; + b = pa_xnew(pa_memblock, 1); - PA_REFCNT_INIT(b); - b->pool = i->pool; b->type = PA_MEMBLOCK_IMPORTED; b->read_only = 1; - pa_atomic_ptr_store(&b->data, (uint8_t*) seg->memory.ptr + offset); + PA_REFCNT_INIT(b); b->length = size; - pa_atomic_store(&b->n_acquired, 0); - pa_atomic_store(&b->please_signal, 0); + b->data = (uint8_t*) seg->memory.ptr + offset; + b->pool = i->pool; b->per_type.imported.id = block_id; b->per_type.imported.segment = seg; @@ -846,11 +622,7 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i seg->n_blocks++; -finish: - pa_mutex_unlock(i->mutex); - - if (b) - stat_add(b); + stat_add(b); return b; } @@ -859,15 +631,10 @@ int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) { pa_memblock *b; assert(i); - pa_mutex_lock(i->mutex); - if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id)))) return -1; memblock_replace_import(b); - - pa_mutex_unlock(i->mutex); - return 0; } @@ -882,84 +649,58 @@ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void return NULL; e = pa_xnew(pa_memexport, 1); - e->mutex = pa_mutex_new(1); e->pool = p; PA_LLIST_HEAD_INIT(struct memexport_slot, e->free_slots); PA_LLIST_HEAD_INIT(struct memexport_slot, e->used_slots); e->n_init = 0; e->revoke_cb = cb; e->userdata = userdata; - - pa_mutex_lock(p->mutex); - PA_LLIST_PREPEND(pa_memexport, p->exports, e); - pa_mutex_unlock(p->mutex); + PA_LLIST_PREPEND(pa_memexport, p->exports, e); return e; } void pa_memexport_free(pa_memexport *e) { assert(e); - pa_mutex_lock(e->mutex); while (e->used_slots) pa_memexport_process_release(e, e->used_slots - e->slots); - pa_mutex_unlock(e->mutex); - pa_mutex_lock(e->pool->mutex); PA_LLIST_REMOVE(pa_memexport, e->pool->exports, e); - pa_mutex_unlock(e->pool->mutex); - pa_xfree(e); } -/* Self-locked */ int pa_memexport_process_release(pa_memexport *e, uint32_t id) { - pa_memblock *b; - assert(e); - pa_mutex_lock(e->mutex); - if (id >= e->n_init) - goto fail; + return -1; if (!e->slots[id].block) - goto fail; + return -1; - b = e->slots[id].block; +/* pa_log("Processing release for %u", id); */ + + assert(AO_load_acquire_read(&e->pool->stat.n_exported) > 0); + assert(AO_load_acquire_read(&e->pool->stat.exported_size) >= (AO_t) e->slots[id].block->length); + + AO_fetch_and_sub1_release_write(&e->pool->stat.n_exported); + AO_fetch_and_add_release_write(&e->pool->stat.exported_size, (AO_t) -e->slots[id].block->length); + + pa_memblock_unref(e->slots[id].block); e->slots[id].block = NULL; PA_LLIST_REMOVE(struct memexport_slot, e->used_slots, &e->slots[id]); PA_LLIST_PREPEND(struct memexport_slot, e->free_slots, &e->slots[id]); - pa_mutex_unlock(e->mutex); - -/* pa_log("Processing release for %u", id); */ - - assert(pa_atomic_load(&e->pool->stat.n_exported) > 0); - assert(pa_atomic_load(&e->pool->stat.exported_size) >= (int) b->length); - - pa_atomic_dec(&e->pool->stat.n_exported); - pa_atomic_add(&e->pool->stat.exported_size, (int) -b->length); - - pa_memblock_unref(b); - return 0; - -fail: - pa_mutex_unlock(e->mutex); - - return -1; } -/* Self-locked */ static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) { struct memexport_slot *slot, *next; assert(e); assert(i); - pa_mutex_lock(e->mutex); - for (slot = e->used_slots; slot; slot = next) { uint32_t idx; next = slot->next; @@ -972,11 +713,8 @@ static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) { e->revoke_cb(e, idx, e->userdata); pa_memexport_process_release(e, idx); } - - pa_mutex_unlock(e->mutex); } -/* No lock necessary */ static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *b) { pa_memblock *n; @@ -993,16 +731,13 @@ static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *b) { if (!(n = pa_memblock_new_pool(p, b->length))) return NULL; - memcpy(pa_atomic_ptr_load(&n->data), pa_atomic_ptr_load(&b->data), b->length); + memcpy(n->data, b->data, b->length); return n; } -/* Self-locked */ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32_t *shm_id, size_t *offset, size_t * size) { pa_shm *memory; struct memexport_slot *slot; - void *data; - size_t length; assert(e); assert(b); @@ -1015,15 +750,12 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 if (!(b = memblock_shared_copy(e->pool, b))) return -1; - pa_mutex_lock(e->mutex); - if (e->free_slots) { slot = e->free_slots; PA_LLIST_REMOVE(struct memexport_slot, e->free_slots, slot); - } else if (e->n_init < PA_MEMEXPORT_SLOTS_MAX) + } else if (e->n_init < PA_MEMEXPORT_SLOTS_MAX) { slot = &e->slots[e->n_init++]; - else { - pa_mutex_unlock(e->mutex); + } else { pa_memblock_unref(b); return -1; } @@ -1032,11 +764,8 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 slot->block = b; *block_id = slot - e->slots; - pa_mutex_unlock(e->mutex); /* pa_log("Got block id %u", *block_id); */ - data = pa_memblock_acquire(b); - if (b->type == PA_MEMBLOCK_IMPORTED) { assert(b->per_type.imported.segment); memory = &b->per_type.imported.segment->memory; @@ -1046,17 +775,15 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 memory = &b->pool->memory; } - assert(data >= memory->ptr); - assert((uint8_t*) data + length <= (uint8_t*) memory->ptr + memory->size); + assert(b->data >= memory->ptr); + assert((uint8_t*) b->data + b->length <= (uint8_t*) memory->ptr + memory->size); *shm_id = memory->id; - *offset = (uint8_t*) data - (uint8_t*) memory->ptr; - *size = length; + *offset = (uint8_t*) b->data - (uint8_t*) memory->ptr; + *size = b->length; - pa_memblock_release(b); - - pa_atomic_inc(&e->pool->stat.n_exported); - pa_atomic_add(&e->pool->stat.exported_size, (int) length); + AO_fetch_and_add1_release_write(&e->pool->stat.n_exported); + AO_fetch_and_add_release_write(&e->pool->stat.exported_size, (AO_t) b->length); return 0; } diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index 9937818f6..d4f2b7aaf 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -55,25 +54,45 @@ typedef struct pa_memexport pa_memexport; typedef void (*pa_memimport_release_cb_t)(pa_memimport *i, uint32_t block_id, void *userdata); typedef void (*pa_memexport_revoke_cb_t)(pa_memexport *e, uint32_t block_id, void *userdata); +struct pa_memblock { + pa_memblock_type_t type; + int read_only; /* boolean */ + PA_REFCNT_DECLARE; /* the reference counter */ + size_t length; + void *data; + pa_mempool *pool; + + union { + struct { + void (*free_cb)(void *p); /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ + } user; + + struct { + uint32_t id; + pa_memimport_segment *segment; + } imported; + } per_type; +}; + /* Please note that updates to this structure are not locked, * i.e. n_allocated might be updated at a point in time where * n_accumulated is not yet. Take these values with a grain of salt, - * they are here for purely statistical reasons.*/ + * threy are here for purely statistical reasons.*/ struct pa_mempool_stat { - pa_atomic_int_t n_allocated; - pa_atomic_int_t n_accumulated; - pa_atomic_int_t n_imported; - pa_atomic_int_t n_exported; - pa_atomic_int_t allocated_size; - pa_atomic_int_t accumulated_size; - pa_atomic_int_t imported_size; - pa_atomic_int_t exported_size; + AO_t n_allocated; + AO_t n_accumulated; + AO_t n_imported; + AO_t n_exported; + AO_t allocated_size; + AO_t accumulated_size; + AO_t imported_size; + AO_t exported_size; - pa_atomic_int_t n_too_large_for_pool; - pa_atomic_int_t n_pool_full; + AO_t n_too_large_for_pool; + AO_t n_pool_full; - pa_atomic_int_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; - pa_atomic_int_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; + AO_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; + AO_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; }; /* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL or PA_MEMBLOCK_APPENDED, depending on the size */ @@ -97,17 +116,9 @@ pa_memblock* pa_memblock_ref(pa_memblock*b); /* This special unref function has to be called by the owner of the memory of a static memory block when he wants to release all references to the memory. This causes the memory to be copied and -converted into a pool or malloc'ed memory block. Please note that this -function is not multiple caller safe, i.e. needs to be locked -manually if called from more than one thread at the same time. */ +converted into a PA_MEMBLOCK_DYNAMIC type memory block */ void pa_memblock_unref_fixed(pa_memblock*b); -int pa_memblock_is_read_only(pa_memblock *b); -void* pa_memblock_acquire(pa_memblock *b); -void pa_memblock_release(pa_memblock *b); -size_t pa_memblock_get_length(pa_memblock *b); -pa_mempool * pa_memblock_get_pool(pa_memblock *b); - /* The memory block manager */ pa_mempool* pa_mempool_new(int shared); void pa_mempool_free(pa_mempool *p); diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index dab44dc39..e6b73fc55 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -176,7 +176,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { assert(uchunk); assert(uchunk->memblock); assert(uchunk->length > 0); - assert(uchunk->index + uchunk->length <= pa_memblock_get_length(uchunk->memblock)); + assert(uchunk->index + uchunk->length <= uchunk->memblock->length); if (uchunk->length % bq->base) return -1; @@ -360,8 +360,8 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { if (bq->silence) { chunk->memblock = pa_memblock_ref(bq->silence); - if (!length || length > pa_memblock_get_length(chunk->memblock)) - length = pa_memblock_get_length(chunk->memblock); + if (!length || length > chunk->memblock->length) + length = chunk->memblock->length; chunk->length = length; } else { @@ -413,8 +413,8 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length if (bq->silence) { - if (!l || l > pa_memblock_get_length(bq->silence)) - l = pa_memblock_get_length(bq->silence); + if (!l || l > bq->silence->length) + l = bq->silence->length; } diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c index 55c4bfa7d..1dbad2b90 100644 --- a/src/pulsecore/memchunk.c +++ b/src/pulsecore/memchunk.c @@ -35,25 +35,22 @@ void pa_memchunk_make_writable(pa_memchunk *c, size_t min) { pa_memblock *n; size_t l; - void *tdata, *sdata; assert(c); assert(c->memblock); + assert(PA_REFCNT_VALUE(c->memblock) > 0); - if (pa_memblock_is_read_only(c->memblock) && - pa_memblock_get_length(c->memblock) >= c->index+min) + if (PA_REFCNT_VALUE(c->memblock) == 1 && + !c->memblock->read_only && + c->memblock->length >= c->index+min) return; l = c->length; if (l < min) l = min; - n = pa_memblock_new(pa_memblock_get_pool(c->memblock), l); - tdata = pa_memblock_acquire(n); - sdata = pa_memblock_acquire(c->memblock); - memcpy(tdata, (uint8_t*) sdata + c->index, c->length); - pa_memblock_release(n); - pa_memblock_release(c->memblock); + n = pa_memblock_new(c->memblock->pool, l); + memcpy(n->data, (uint8_t*) c->memblock->data + c->index, c->length); pa_memblock_unref(c->memblock); c->memblock = n; c->index = 0; diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c index b711c98cd..cde6a9ee4 100644 --- a/src/pulsecore/play-memchunk.c +++ b/src/pulsecore/play-memchunk.c @@ -55,7 +55,7 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { if (c->length <= 0) return -1; - assert(c->memblock); + assert(c->memblock && c->memblock->length); *chunk = *c; pa_memblock_ref(c->memblock); diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 65b93eb45..80aeb27b1 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -891,22 +891,14 @@ static int do_read(struct connection *c) { } } else if (c->state == ESD_CACHING_SAMPLE) { ssize_t r; - void *p; - assert(c->scache.memchunk.memblock); - assert(c->scache.name); - assert(c->scache.memchunk.index < c->scache.memchunk.length); - - p = pa_memblock_acquire(c->scache.memchunk.memblock); + assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length); - if ((r = pa_iochannel_read(c->io, (uint8_t*) p+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { - pa_memblock_release(c->scache.memchunk.memblock); + if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } - pa_memblock_release(c->scache.memchunk.memblock); - c->scache.memchunk.index += r; assert(c->scache.memchunk.index <= c->scache.memchunk.length); @@ -933,7 +925,6 @@ static int do_read(struct connection *c) { pa_memchunk chunk; ssize_t r; size_t l; - void *p; assert(c->input_memblockq); @@ -946,7 +937,7 @@ static int do_read(struct connection *c) { l = c->playback.fragment_size; if (c->playback.current_memblock) - if (pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index < l) { + if (c->playback.current_memblock->length - c->playback.memblock_index < l) { pa_memblock_unref(c->playback.current_memblock); c->playback.current_memblock = NULL; c->playback.memblock_index = 0; @@ -954,21 +945,15 @@ static int do_read(struct connection *c) { if (!c->playback.current_memblock) { c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2); - assert(c->playback.current_memblock); - assert(pa_memblock_get_length(c->playback.current_memblock) >= l); + assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); c->playback.memblock_index = 0; } - p = pa_memblock_acquire(c->playback.current_memblock); - - if ((r = pa_iochannel_read(c->io, (uint8_t*) p+c->playback.memblock_index, l)) <= 0) { - pa_memblock_release(c->playback.current_memblock); + if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } - - pa_memblock_release(c->playback.current_memblock); - + chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; chunk.length = r; @@ -1005,26 +990,19 @@ static int do_write(struct connection *c) { } else if (c->state == ESD_STREAMING_DATA && c->source_output) { pa_memchunk chunk; ssize_t r; - void *p; assert(c->output_memblockq); if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) return 0; - assert(chunk.memblock); - assert(chunk.length); - - p = pa_memblock_acquire(chunk.memblock); + assert(chunk.memblock && chunk.length); - if ((r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length)) < 0) { - pa_memblock_release(chunk.memblock); + if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); pa_log("write(): %s", pa_cstrerror(errno)); return -1; } - pa_memblock_release(chunk.memblock); - pa_memblockq_drop(c->output_memblockq, &chunk, r); pa_memblock_unref(chunk.memblock); diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index fba611d7d..38c024b7b 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2274,7 +2274,6 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o } else { struct upload_stream *u = (struct upload_stream*) stream; size_t l; - assert(u->type == UPLOAD_STREAM); if (!u->memchunk.memblock) { @@ -2294,18 +2293,9 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o if (l > chunk->length) l = chunk->length; - if (l > 0) { - void *src, *dst; - dst = pa_memblock_acquire(u->memchunk.memblock); - src = pa_memblock_acquire(chunk->memblock); - - memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length, - (uint8_t*) src+chunk->index, l); - - pa_memblock_release(u->memchunk.memblock); - pa_memblock_release(chunk->memblock); - + memcpy((uint8_t*) u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length, + (uint8_t*) chunk->memblock->data+chunk->index, l); u->memchunk.length += l; u->length -= l; } diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index bf203e423..6bfba875e 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -113,7 +113,6 @@ static int do_read(struct connection *c) { pa_memchunk chunk; ssize_t r; size_t l; - void *p; if (!c->sink_input || !(l = pa_memblockq_missing(c->input_memblockq))) return 0; @@ -122,7 +121,7 @@ static int do_read(struct connection *c) { l = c->playback.fragment_size; if (c->playback.current_memblock) - if (pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index < l) { + if (c->playback.current_memblock->length - c->playback.memblock_index < l) { pa_memblock_unref(c->playback.current_memblock); c->playback.current_memblock = NULL; c->playback.memblock_index = 0; @@ -130,20 +129,15 @@ static int do_read(struct connection *c) { if (!c->playback.current_memblock) { c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2); - assert(c->playback.current_memblock); - assert(pa_memblock_get_length(c->playback.current_memblock) >= l); + assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); c->playback.memblock_index = 0; } - - p = pa_memblock_acquire(c->playback.current_memblock); - if ((r = pa_iochannel_read(c->io, (uint8_t*) p + c->playback.memblock_index, l)) <= 0) { - pa_memblock_release(c->playback.current_memblock); + if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno)); return -1; } - pa_memblock_release(c->playback.current_memblock); chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; chunk.length = r; @@ -162,8 +156,7 @@ static int do_read(struct connection *c) { static int do_write(struct connection *c) { pa_memchunk chunk; ssize_t r; - void *p; - + if (!c->source_output) return 0; @@ -172,17 +165,12 @@ static int do_write(struct connection *c) { return 0; assert(chunk.memblock && chunk.length); - - p = pa_memblock_acquire(chunk.memblock); - if ((r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length)) < 0) { - pa_memblock_release(chunk.memblock); + if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); pa_log("write(): %s", pa_cstrerror(errno)); return -1; } - - pa_memblock_release(chunk.memblock); pa_memblockq_drop(c->output_memblockq, &chunk, r); pa_memblock_unref(chunk.memblock); diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 339637967..566fb060a 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -48,7 +48,6 @@ #include #include #include -#include #include "pstream.h" @@ -114,11 +113,10 @@ struct pa_pstream { PA_REFCNT_DECLARE; pa_mainloop_api *mainloop; + pa_defer_event *defer_event; pa_iochannel *io; - pa_queue *send_queue; - pa_mutex *mutex; /* only for access to the queue */ - pa_anotify *anotify; + pa_mutex *mutex; int dead; @@ -128,7 +126,6 @@ struct pa_pstream { uint32_t shm_info[PA_PSTREAM_SHM_MAX]; void *data; size_t index; - pa_memchunk memchunk; } write; struct { @@ -173,6 +170,10 @@ static void do_something(pa_pstream *p) { pa_pstream_ref(p); + pa_mutex_lock(p->mutex); + + p->mainloop->defer_enable(p->defer_event, 0); + if (!p->dead && pa_iochannel_is_readable(p->io)) { if (do_read(p) < 0) goto fail; @@ -184,6 +185,8 @@ static void do_something(pa_pstream *p) { goto fail; } + pa_mutex_unlock(p->mutex); + pa_pstream_unref(p); return; @@ -194,6 +197,8 @@ fail: if (p->die_callback) p->die_callback(p, p->die_callback_userdata); + pa_mutex_unlock(p->mutex); + pa_pstream_unref(p); } @@ -206,10 +211,13 @@ static void io_callback(pa_iochannel*io, void *userdata) { do_something(p); } -static void anotify_callback(uint8_t event, void *userdata) { +static void defer_callback(pa_mainloop_api *m, pa_defer_event *e, void*userdata) { pa_pstream *p = userdata; assert(p); + assert(p->defer_event == e); + assert(p->mainloop == m); + do_something(p); } @@ -229,16 +237,16 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo p->dead = 0; p->mutex = pa_mutex_new(1); - p->anotify = pa_anotify_new(m, anotify_callback, p); p->mainloop = m; + p->defer_event = m->defer_new(m, defer_callback, p); + m->defer_enable(p->defer_event, 0); p->send_queue = pa_queue_new(); assert(p->send_queue); p->write.current = NULL; p->write.index = 0; - pa_memchunk_reset(&p->write.memchunk); p->read.memblock = NULL; p->read.packet = NULL; p->read.index = 0; @@ -301,15 +309,9 @@ static void pstream_free(pa_pstream *p) { if (p->read.packet) pa_packet_unref(p->read.packet); - if (p->write.memchunk.memblock) - pa_memblock_unref(p->write.memchunk.memblock); - if (p->mutex) pa_mutex_free(p->mutex); - if (p->anotify) - pa_anotify_free(p->anotify); - pa_xfree(p); } @@ -320,6 +322,11 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre assert(PA_REFCNT_VALUE(p) > 0); assert(packet); + pa_mutex_lock(p->mutex); + + if (p->dead) + goto finish; + i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); @@ -329,11 +336,12 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre i->creds = *creds; #endif - pa_mutex_lock(p->mutex); pa_queue_push(p->send_queue, i); + p->mainloop->defer_enable(p->defer_event, 1); + +finish: + pa_mutex_unlock(p->mutex); - - pa_anotify_signal(p->anotify, 0); } void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) { @@ -344,6 +352,12 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa assert(channel != (uint32_t) -1); assert(chunk); + pa_mutex_lock(p->mutex); + + if (p->dead) + goto finish; + + length = chunk->length; idx = 0; while (length > 0) { @@ -365,15 +379,17 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa i->with_creds = 0; #endif - pa_mutex_lock(p->mutex); pa_queue_push(p->send_queue, i); - pa_mutex_unlock(p->mutex); idx += n; length -= n; } + + p->mainloop->defer_enable(p->defer_event, 1); - pa_anotify_signal(p->anotify, 0); +finish: + + pa_mutex_unlock(p->mutex); } static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata) { @@ -383,6 +399,11 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd assert(p); assert(PA_REFCNT_VALUE(p) > 0); + pa_mutex_lock(p->mutex); + + if (p->dead) + goto finish; + /* pa_log("Releasing block %u", block_id); */ item = pa_xnew(struct item_info, 1); @@ -392,11 +413,12 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd item->with_creds = 0; #endif - pa_mutex_lock(p->mutex); pa_queue_push(p->send_queue, item); - pa_mutex_unlock(p->mutex); + p->mainloop->defer_enable(p->defer_event, 1); - pa_anotify_signal(p->anotify, 0); +finish: + + pa_mutex_unlock(p->mutex); } static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) { @@ -406,6 +428,11 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda assert(p); assert(PA_REFCNT_VALUE(p) > 0); + pa_mutex_lock(p->mutex); + + if (p->dead) + goto finish; + /* pa_log("Revoking block %u", block_id); */ item = pa_xnew(struct item_info, 1); @@ -415,27 +442,23 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda item->with_creds = 0; #endif - pa_mutex_lock(p->mutex); pa_queue_push(p->send_queue, item); - pa_mutex_unlock(p->mutex); + p->mainloop->defer_enable(p->defer_event, 1); - pa_anotify_signal(p->anotify, 0); +finish: + + pa_mutex_unlock(p->mutex); } static void prepare_next_write_item(pa_pstream *p) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); - p->write.current = pa_queue_pop(p->send_queue); - pa_mutex_unlock(p->mutex); - - if (!p->write.current) + if (!(p->write.current = pa_queue_pop(p->send_queue))) return; p->write.index = 0; p->write.data = NULL; - pa_memchunk_reset(&p->write.memchunk); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = 0; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1); @@ -502,9 +525,7 @@ static void prepare_next_write_item(pa_pstream *p) { if (send_payload) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); - p->write.memchunk = p->write.current->chunk; - pa_memblock_ref(p->write.memchunk.memblock); - p->write.data = NULL; + p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index; } p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(flags); @@ -520,7 +541,6 @@ static int do_write(pa_pstream *p) { void *d; size_t l; ssize_t r; - pa_memblock *release_memblock = NULL; assert(p); assert(PA_REFCNT_VALUE(p) > 0); @@ -535,16 +555,9 @@ static int do_write(pa_pstream *p) { d = (uint8_t*) p->write.descriptor + p->write.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->write.index; } else { - assert(p->write.data || p->write.memchunk.memblock); - - if (p->write.data) - d = p->write.data; - else { - d = (uint8_t*) pa_memblock_acquire(p->write.memchunk.memblock) + p->write.memchunk.index; - release_memblock = p->write.memchunk.memblock; - } + assert(p->write.data); - d = (uint8_t*) d + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; + d = (uint8_t*) p->write.data + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } @@ -554,17 +567,14 @@ static int do_write(pa_pstream *p) { if (p->send_creds_now) { if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0) - goto fail; + return -1; p->send_creds_now = 0; } else #endif if ((r = pa_iochannel_write(p->io, d, l)) < 0) - goto fail; - - if (release_memblock) - pa_memblock_release(release_memblock); + return -1; p->write.index += r; @@ -578,20 +588,12 @@ static int do_write(pa_pstream *p) { } return 0; - -fail: - - if (release_memblock) - pa_memblock_release(release_memblock); - - return -1; } static int do_read(pa_pstream *p) { void *d; size_t l; ssize_t r; - pa_memblock *release_memblock = NULL; assert(p); assert(PA_REFCNT_VALUE(p) > 0); @@ -600,16 +602,8 @@ static int do_read(pa_pstream *p) { d = (uint8_t*) p->read.descriptor + p->read.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->read.index; } else { - assert(p->read.data || p->read.memblock); - - if (p->read.data) - d = p->read.data; - else { - d = pa_memblock_acquire(p->read.memblock); - release_memblock = p->read.memblock; - } - - d = (uint8_t*) d + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE; + assert(p->read.data); + d = (uint8_t*) p->read.data + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE; l = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE); } @@ -618,17 +612,14 @@ static int do_read(pa_pstream *p) { int b = 0; if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->read_creds, &b)) <= 0) - goto fail; + return -1; p->read_creds_valid = p->read_creds_valid || b; } #else if ((r = pa_iochannel_read(p->io, d, l)) <= 0) - goto fail; + return -1; #endif - - if (release_memblock) - pa_memblock_release(release_memblock); p->read.index += r; @@ -710,7 +701,7 @@ static int do_read(pa_pstream *p) { /* Frame is a memblock frame */ p->read.memblock = pa_memblock_new(p->mempool, length); - p->read.data = NULL; + p->read.data = p->read.memblock->data; } else { pa_log_warn("Recieved memblock frame with invalid flags value."); @@ -797,7 +788,7 @@ static int do_read(pa_pstream *p) { chunk.memblock = b; chunk.index = 0; - chunk.length = pa_memblock_get_length(b); + chunk.length = b->length; offset = (int64_t) ( (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) | @@ -825,51 +816,52 @@ frame_done: p->read.memblock = NULL; p->read.packet = NULL; p->read.index = 0; - p->read.data = NULL; #ifdef HAVE_CREDS p->read_creds_valid = 0; #endif return 0; - -fail: - if (release_memblock) - pa_memblock_release(release_memblock); - - return -1; } void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); + pa_mutex_lock(p->mutex); p->die_callback = cb; p->die_callback_userdata = userdata; + pa_mutex_unlock(p->mutex); } void pa_pstream_set_drain_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); + pa_mutex_lock(p->mutex); p->drain_callback = cb; p->drain_callback_userdata = userdata; + pa_mutex_unlock(p->mutex); } void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); + pa_mutex_lock(p->mutex); p->recieve_packet_callback = cb; p->recieve_packet_callback_userdata = userdata; + pa_mutex_unlock(p->mutex); } void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock_cb_t cb, void *userdata) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); + pa_mutex_lock(p->mutex); p->recieve_memblock_callback = cb; p->recieve_memblock_callback_userdata = userdata; + pa_mutex_unlock(p->mutex); } int pa_pstream_is_pending(pa_pstream *p) { @@ -909,6 +901,8 @@ pa_pstream* pa_pstream_ref(pa_pstream*p) { void pa_pstream_close(pa_pstream *p) { assert(p); + pa_mutex_lock(p->mutex); + p->dead = 1; if (p->import) { @@ -926,16 +920,25 @@ void pa_pstream_close(pa_pstream *p) { p->io = NULL; } + if (p->defer_event) { + p->mainloop->defer_free(p->defer_event); + p->defer_event = NULL; + } + p->die_callback = NULL; p->drain_callback = NULL; p->recieve_packet_callback = NULL; p->recieve_memblock_callback = NULL; + + pa_mutex_unlock(p->mutex); } void pa_pstream_use_shm(pa_pstream *p, int enable) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); + pa_mutex_lock(p->mutex); + p->use_shm = enable; if (enable) { @@ -950,4 +953,6 @@ void pa_pstream_use_shm(pa_pstream *p, int enable) { p->export = NULL; } } + + pa_mutex_unlock(p->mutex); } diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index c28c2fb31..b01420491 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -51,7 +51,8 @@ struct pa_resampler { }; struct impl_libsamplerate { - pa_memchunk buf1, buf2, buf3, buf4; + pa_memblock *buf1_block, *buf2_block, *buf3_block, *buf4_block; + float* buf1, *buf2, *buf3, *buf4; unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples; pa_convert_to_float32ne_func_t to_float32ne_func; @@ -223,14 +224,14 @@ static void libsamplerate_free(pa_resampler *r) { if (u->src_state) src_delete(u->src_state); - if (u->buf1.memblock) - pa_memblock_unref(u->buf1.memblock); - if (u->buf2.memblock) - pa_memblock_unref(u->buf2.memblock); - if (u->buf3.memblock) - pa_memblock_unref(u->buf3.memblock); - if (u->buf4.memblock) - pa_memblock_unref(u->buf4.memblock); + if (u->buf1_block) + pa_memblock_unref(u->buf1_block); + if (u->buf2_block) + pa_memblock_unref(u->buf2_block); + if (u->buf3_block) + pa_memblock_unref(u->buf3_block); + if (u->buf4_block) + pa_memblock_unref(u->buf4_block); pa_xfree(u); } @@ -269,80 +270,64 @@ static void calc_map_table(pa_resampler *r) { } } -static pa_memchunk* convert_to_float(pa_resampler *r, pa_memchunk *input) { +static float * convert_to_float(pa_resampler *r, void *input, unsigned n_frames) { struct impl_libsamplerate *u; unsigned n_samples; - void *src, *dst; assert(r); assert(input); - assert(input->memblock); - assert(r->impl_data); u = r->impl_data; /* Convert the incoming sample into floats and place them in buf1 */ - if (!u->to_float32ne_func || !input->length) + if (!u->to_float32ne_func) return input; - n_samples = (input->length / r->i_fz) * r->i_ss.channels; + n_samples = n_frames * r->i_ss.channels; - if (!u->buf1.memblock || u->buf1_samples < n_samples) { - if (u->buf1.memblock) - pa_memblock_unref(u->buf1.memblock); + if (u->buf1_samples < n_samples) { + if (u->buf1_block) + pa_memblock_unref(u->buf1_block); u->buf1_samples = n_samples; - u->buf1.memblock = pa_memblock_new(r->mempool, u->buf1.length = sizeof(float) * n_samples); - u->buf1.index = 0; + u->buf1_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); + u->buf1 = u->buf1_block->data; } + + u->to_float32ne_func(n_samples, input, u->buf1); - src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index; - dst = (uint8_t*) pa_memblock_acquire(u->buf1.memblock); - u->to_float32ne_func(n_samples, src, dst); - pa_memblock_release(input->memblock); - pa_memblock_release(u->buf1.memblock); - - u->buf1.length = sizeof(float) * n_samples; - - return &u->buf1; + return u->buf1; } -static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { +static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) { struct impl_libsamplerate *u; - unsigned n_samples, n_frames; + unsigned n_samples; int i_skip, o_skip; unsigned oc; - float *src, *dst; assert(r); assert(input); - assert(input->memblock); - assert(r->impl_data); u = r->impl_data; /* Remap channels and place the result int buf2 */ - if (!u->map_required || !input->length) + if (!u->map_required) return input; - n_samples = input->length / sizeof(float); - n_frames = n_samples / r->o_ss.channels; + n_samples = n_frames * r->o_ss.channels; - if (!u->buf2.memblock || u->buf2_samples < n_samples) { - if (u->buf2.memblock) - pa_memblock_unref(u->buf2.memblock); + if (u->buf2_samples < n_samples) { + if (u->buf2_block) + pa_memblock_unref(u->buf2_block); u->buf2_samples = n_samples; - u->buf2.memblock = pa_memblock_new(r->mempool, u->buf2.length = sizeof(float) * n_samples); - u->buf2.index = 0; + u->buf2_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); + u->buf2 = u->buf2_block->data; } - src = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); - dst = (float*) pa_memblock_acquire(u->buf2.memblock); - - memset(dst, 0, n_samples * sizeof(float)); + memset(u->buf2, 0, n_samples * sizeof(float)); o_skip = sizeof(float) * r->o_ss.channels; i_skip = sizeof(float) * r->i_ss.channels; @@ -353,57 +338,49 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { for (i = 0; i < PA_CHANNELS_MAX && u->map_table[oc][i] >= 0; i++) oil_vectoradd_f32( - dst + oc, o_skip, - dst + oc, o_skip, - src + u->map_table[oc][i], i_skip, + u->buf2 + oc, o_skip, + u->buf2 + oc, o_skip, + input + u->map_table[oc][i], i_skip, n_frames, &one, &one); } - pa_memblock_release(input->memblock); - pa_memblock_release(u->buf2.memblock); - - u->buf2.length = n_frames * sizeof(float) * r->o_ss.channels; - - return &u->buf2; + return u->buf2; } -static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) { +static float *resample(pa_resampler *r, float *input, unsigned *n_frames) { struct impl_libsamplerate *u; SRC_DATA data; - unsigned in_n_frames, in_n_samples; unsigned out_n_frames, out_n_samples; int ret; assert(r); assert(input); + assert(n_frames); assert(r->impl_data); u = r->impl_data; /* Resample the data and place the result in buf3 */ - if (!u->src_state || !input->length) + if (!u->src_state) return input; - in_n_samples = input->length / sizeof(float); - in_n_frames = in_n_samples * r->o_ss.channels; - - out_n_frames = (in_n_frames*r->o_ss.rate/r->i_ss.rate)+1024; + out_n_frames = (*n_frames*r->o_ss.rate/r->i_ss.rate)+1024; out_n_samples = out_n_frames * r->o_ss.channels; - if (!u->buf3.memblock || u->buf3_samples < out_n_samples) { - if (u->buf3.memblock) - pa_memblock_unref(u->buf3.memblock); + if (u->buf3_samples < out_n_samples) { + if (u->buf3_block) + pa_memblock_unref(u->buf3_block); u->buf3_samples = out_n_samples; - u->buf3.memblock = pa_memblock_new(r->mempool, u->buf3.length = sizeof(float) * out_n_samples); - u->buf3.index = 0; + u->buf3_block = pa_memblock_new(r->mempool, sizeof(float) * out_n_samples); + u->buf3 = u->buf3_block->data; } - data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); - data.input_frames = in_n_frames; + data.data_in = input; + data.input_frames = *n_frames; - data.data_out = (float*) pa_memblock_acquire(u->buf3.memblock); + data.data_out = u->buf3; data.output_frames = out_n_frames; data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; @@ -411,20 +388,16 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) { ret = src_process(u->src_state, &data); assert(ret == 0); - assert((unsigned) data.input_frames_used == in_n_frames); + assert((unsigned) data.input_frames_used == *n_frames); - pa_memblock_release(input->memblock); - pa_memblock_release(u->buf3.memblock); - - u->buf3.length = data.output_frames_gen * sizeof(float) * r->o_ss.channels; + *n_frames = data.output_frames_gen; - return &u->buf3; + return u->buf3; } -static pa_memchunk *convert_from_float(pa_resampler *r, pa_memchunk *input) { +static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) { struct impl_libsamplerate *u; - unsigned n_samples, n_frames; - void *src, *dst; + unsigned n_samples; assert(r); assert(input); @@ -433,35 +406,30 @@ static pa_memchunk *convert_from_float(pa_resampler *r, pa_memchunk *input) { /* Convert the data into the correct sample type and place the result in buf4 */ - if (!u->from_float32ne_func || !input->length) + if (!u->from_float32ne_func) return input; - - n_frames = input->length / sizeof(float) / r->o_ss.channels; + n_samples = n_frames * r->o_ss.channels; if (u->buf4_samples < n_samples) { - if (u->buf4.memblock) - pa_memblock_unref(u->buf4.memblock); + if (u->buf4_block) + pa_memblock_unref(u->buf4_block); u->buf4_samples = n_samples; - u->buf4.memblock = pa_memblock_new(r->mempool, u->buf4.length = r->o_fz * n_frames); - u->buf4.index = 0; + u->buf4_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); + u->buf4 = u->buf4_block->data; } + + u->from_float32ne_func(n_samples, input, u->buf4); - src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->length; - dst = pa_memblock_acquire(u->buf4.memblock); - u->from_float32ne_func(n_samples, src, dst); - pa_memblock_release(input->memblock); - pa_memblock_release(u->buf4.memblock); - - u->buf4.length = r->o_fz * n_frames; - - return &u->buf4; + return u->buf4; } static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { struct impl_libsamplerate *u; - pa_memchunk *buf; + float *buf; + void *input, *output; + unsigned n_frames; assert(r); assert(in); @@ -473,23 +441,55 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun u = r->impl_data; - buf = convert_to_float(r, (pa_memchunk*) in); - buf = remap_channels(r, buf); - buf = resample(r, buf); - - if (buf->length) { - buf = convert_from_float(r, buf); - *out = *buf; - - if (buf == in) - pa_memblock_ref(buf->memblock); - else - pa_memchunk_reset(buf); - } else - pa_memchunk_reset(out); - - pa_memblock_release(in->memblock); + input = ((uint8_t*) in->memblock->data + in->index); + n_frames = in->length / r->i_fz; + assert(n_frames > 0); + buf = convert_to_float(r, input, n_frames); + buf = remap_channels(r, buf, n_frames); + buf = resample(r, buf, &n_frames); + + if (n_frames) { + output = convert_from_float(r, buf, n_frames); + + if (output == input) { + /* Mm, no adjustment has been necessary, so let's return the original block */ + out->memblock = pa_memblock_ref(in->memblock); + out->index = in->index; + out->length = in->length; + } else { + out->length = n_frames * r->o_fz; + out->index = 0; + out->memblock = NULL; + + if (output == u->buf1) { + u->buf1 = NULL; + u->buf1_samples = 0; + out->memblock = u->buf1_block; + u->buf1_block = NULL; + } else if (output == u->buf2) { + u->buf2 = NULL; + u->buf2_samples = 0; + out->memblock = u->buf2_block; + u->buf2_block = NULL; + } else if (output == u->buf3) { + u->buf3 = NULL; + u->buf3_samples = 0; + out->memblock = u->buf3_block; + u->buf3_block = NULL; + } else if (output == u->buf4) { + u->buf4 = NULL; + u->buf4_samples = 0; + out->memblock = u->buf4_block; + u->buf4_block = NULL; + } + + assert(out->memblock); + } + } else { + out->memblock = NULL; + out->index = out->length = 0; + } } static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) { @@ -516,10 +516,8 @@ static int libsamplerate_init(pa_resampler *r) { r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1); - pa_memchunk_reset(&u->buf1); - pa_memchunk_reset(&u->buf2); - pa_memchunk_reset(&u->buf3); - pa_memchunk_reset(&u->buf4); + u->buf1 = u->buf2 = u->buf3 = u->buf4 = NULL; + u->buf1_block = u->buf2_block = u->buf3_block = u->buf4_block = NULL; u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0; if (r->i_ss.format == PA_SAMPLE_FLOAT32NE) @@ -580,16 +578,12 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out /* Do real resampling */ size_t l; unsigned o_index; - void *src, *dst; /* The length of the new memory block rounded up */ l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz; out->index = 0; out->memblock = pa_memblock_new(r->mempool, l); - - src = (uint8_t*) pa_memblock_acquire(in->memblock) + in->index; - dst = pa_memblock_acquire(out->memblock); for (o_index = 0;; o_index++, u->o_counter++) { unsigned j; @@ -600,16 +594,13 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out if (j >= n_frames) break; - assert(o_index*fz < pa_memblock_get_length(out->memblock)); + assert(o_index*fz < out->memblock->length); - memcpy((uint8_t*) dst + fz*o_index, - (uint8_t*) src + fz*j, fz); + memcpy((uint8_t*) out->memblock->data + fz*o_index, + (uint8_t*) in->memblock->data + in->index + fz*j, fz); } - - pa_memblock_release(in->memblock); - pa_memblock_release(out->memblock); - + out->length = o_index*fz; } diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index 52023d311..d902b4b55 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -46,27 +46,15 @@ pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spe } pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { - void *data; - - assert(b); - assert(spec); - - data = pa_memblock_acquire(b); - pa_silence_memory(data, pa_memblock_get_length(b), spec); - pa_memblock_release(b); + assert(b && b->data && spec); + pa_silence_memory(b->data, b->length, spec); return b; } void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) { - void *data; - - assert(c); - assert(c->memblock); - assert(spec); + assert(c && c->memblock && c->memblock->data && spec && c->length); - data = pa_memblock_acquire(c->memblock); - pa_silence_memory((uint8_t*) data+c->index, c->length, spec); - pa_memblock_release(c->memblock); + pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec); } void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { @@ -94,38 +82,26 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { } size_t pa_mix( - pa_mix_info streams[], - unsigned nstreams, - void *data, - size_t length, - const pa_sample_spec *spec, - const pa_cvolume *volume, - int mute) { - - pa_cvolume full_volume; - size_t d = 0; - unsigned k; + const pa_mix_info streams[], + unsigned nstreams, + void *data, + size_t length, + const pa_sample_spec *spec, + const pa_cvolume *volume, + int mute) { - assert(streams); - assert(data); - assert(length); - assert(spec); + assert(streams && data && length && spec); - if (!volume) - volume = pa_cvolume_reset(&full_volume, spec->channels); - - for (k = 0; k < nstreams; k++) - streams[k].internal = pa_memblock_acquire(streams[k].chunk.memblock); - switch (spec->format) { case PA_SAMPLE_S16NE:{ + size_t d; unsigned channel = 0; for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; if (d >= length) - goto finish; + return d; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -135,12 +111,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - goto finish; + return d; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = *((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d)); + v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); @@ -163,18 +139,17 @@ size_t pa_mix( if (++channel >= spec->channels) channel = 0; } - - break; } case PA_SAMPLE_S16RE:{ + size_t d; unsigned channel = 0; for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; if (d >= length) - goto finish; + return d; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -184,12 +159,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - goto finish; + return d; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d))); + v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d))); if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); @@ -212,18 +187,17 @@ size_t pa_mix( if (++channel >= spec->channels) channel = 0; } - - break; } case PA_SAMPLE_U8: { + size_t d; unsigned channel = 0; for (d = 0;; d ++) { int32_t sum = 0; if (d >= length) - goto finish; + return d; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -233,12 +207,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - goto finish; + return d; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = (int32_t) *((uint8_t*) streams[i].internal + streams[i].chunk.index + d) - 0x80; + v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80; if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); @@ -261,18 +235,17 @@ size_t pa_mix( if (++channel >= spec->channels) channel = 0; } - - break; } case PA_SAMPLE_FLOAT32NE: { + size_t d; unsigned channel = 0; for (d = 0;; d += sizeof(float)) { float sum = 0; if (d >= length) - goto finish; + return d; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -282,12 +255,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - goto finish; + return d; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = *((float*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d)); + v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); if (cvolume != PA_VOLUME_NORM) v *= pa_sw_volume_to_linear(cvolume); @@ -306,34 +279,17 @@ size_t pa_mix( if (++channel >= spec->channels) channel = 0; } - - break; } default: pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); abort(); } - -finish: - - for (k = 0; k < nstreams; k++) - pa_memblock_release(streams[k].chunk.memblock); - - return d; } -void pa_volume_memchunk( - pa_memchunk*c, - const pa_sample_spec *spec, - const pa_cvolume *volume) { - - void *ptr; - - assert(c); - assert(spec); - assert(c->length % pa_frame_size(spec) == 0); +void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvolume *volume) { + assert(c && spec && (c->length % pa_frame_size(spec) == 0)); assert(volume); if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM)) @@ -344,8 +300,6 @@ void pa_volume_memchunk( return; } - ptr = pa_memblock_acquire(c->memblock); - switch (spec->format) { case PA_SAMPLE_S16NE: { int16_t *d; @@ -356,7 +310,7 @@ void pa_volume_memchunk( for (channel = 0; channel < spec->channels; channel++) linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); - for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t = (int32_t)(*d); t = (int32_t) (t * linear[channel]); @@ -381,7 +335,7 @@ void pa_volume_memchunk( for (channel = 0; channel < spec->channels; channel++) linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); - for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t = (int32_t)(INT16_SWAP(*d)); t = (int32_t) (t * linear[channel]); @@ -403,7 +357,7 @@ void pa_volume_memchunk( size_t n; unsigned channel = 0; - for (d = (uint8_t*) ptr + c->index, n = c->length; n > 0; d++, n--) { + for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) { int32_t t = (int32_t) *d - 0x80; t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel])); @@ -425,7 +379,7 @@ void pa_volume_memchunk( unsigned n; unsigned channel; - d = (float*) ((uint8_t*) ptr + c->index); + d = (float*) ((uint8_t*) c->memblock->data + c->index); skip = spec->channels * sizeof(float); n = c->length/sizeof(float)/spec->channels; @@ -448,7 +402,5 @@ void pa_volume_memchunk( pa_sample_format_to_string(spec->format)); abort(); } - - pa_memblock_release(c->memblock); } diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h index 04c2f6b12..6b7707925 100644 --- a/src/pulsecore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -36,11 +36,10 @@ typedef struct pa_mix_info { pa_memchunk chunk; pa_cvolume volume; void *userdata; - void *internal; /* Used internally by pa_mix(), should not be initialised when calling pa_mix() */ } pa_mix_info; size_t pa_mix( - pa_mix_info channels[], + const pa_mix_info channels[], unsigned nchannels, void *data, size_t length, diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index c3cd49525..d948f0a4c 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -294,7 +294,6 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) assert(i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED); if (i->move_silence > 0) { - size_t l; /* We have just been moved and shall play some silence for a * while until the old sink has drained its playback buffer */ @@ -304,8 +303,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) chunk->memblock = pa_memblock_ref(i->silence_memblock); chunk->index = 0; - l = pa_memblock_get_length(chunk->memblock); - chunk->length = i->move_silence < l ? i->move_silence : l; + chunk->length = i->move_silence < chunk->memblock->length ? i->move_silence : chunk->memblock->length; ret = 0; do_volume_adj_here = 1; @@ -391,13 +389,10 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt if (i->move_silence > 0) { if (chunk) { - size_t l; - l = pa_memblock_get_length(i->silence_memblock); - if (chunk->memblock != i->silence_memblock || chunk->index != 0 || - (chunk->memblock && (chunk->length != (l < i->move_silence ? l : i->move_silence)))) + (chunk->memblock && (chunk->length != (i->silence_memblock->length < i->move_silence ? i->silence_memblock->length : i->move_silence)))) return; } diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 04795e39b..056952546 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -237,6 +237,7 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) { info->userdata = i; assert(info->chunk.memblock); + assert(info->chunk.memblock->data); assert(info->chunk.length); info++; @@ -304,16 +305,13 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_volume_memchunk(result, &s->sample_spec, &volume); } } else { - void *ptr; result->memblock = pa_memblock_new(s->core->mempool, length); assert(result->memblock); /* pa_log("mixing %i", n); */ - ptr = pa_memblock_acquire(result->memblock); - result->length = pa_mix(info, n, ptr, length, &s->sample_spec, &s->sw_volume, s->sw_muted); - pa_memblock_release(result->memblock); - + result->length = pa_mix(info, n, result->memblock->data, length, + &s->sample_spec, &s->sw_volume, s->sw_muted); result->index = 0; } @@ -334,13 +332,13 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; int r = -1; - void *ptr; assert(s); assert(s->ref >= 1); assert(target); assert(target->memblock); assert(target->length); + assert(target->memblock->data); pa_sink_ref(s); @@ -349,23 +347,16 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { if (n <= 0) goto finish; - ptr = pa_memblock_acquire(target->memblock); - if (n == 1) { - void *src; pa_cvolume volume; if (target->length > info[0].chunk.length) target->length = info[0].chunk.length; - - src = pa_memblock_acquire(info[0].chunk.memblock); - memcpy((uint8_t*) ptr + target->index, - (uint8_t*) src + info[0].chunk.index, + memcpy((uint8_t*) target->memblock->data + target->index, + (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index, target->length); - pa_memblock_release(info[0].chunk.memblock); - pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); if (s->sw_muted) @@ -374,13 +365,11 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_volume_memchunk(target, &s->sample_spec, &volume); } else target->length = pa_mix(info, n, - (uint8_t*) ptr + target->index, + (uint8_t*) target->memblock->data + target->index, target->length, &s->sample_spec, &s->sw_volume, s->sw_muted); - - pa_memblock_release(target->memblock); inputs_drop(s, info, n, target->length); @@ -404,6 +393,7 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { assert(target); assert(target->memblock); assert(target->length); + assert(target->memblock->data); pa_sink_ref(s); diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index d2ffeeeda..e6f24a795 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -74,26 +74,21 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { if (!u->memchunk.memblock) { uint32_t fs = pa_frame_size(&i->sample_spec); sf_count_t n; - void *p; u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, BUF_SIZE); u->memchunk.index = 0; - p = pa_memblock_acquire(u->memchunk.memblock); - if (u->readf_function) { - if ((n = u->readf_function(u->sndfile, p, BUF_SIZE/fs)) <= 0) + if ((n = u->readf_function(u->sndfile, u->memchunk.memblock->data, BUF_SIZE/fs)) <= 0) n = 0; u->memchunk.length = n * fs; } else { - if ((n = sf_read_raw(u->sndfile, p, BUF_SIZE)) <= 0) + if ((n = sf_read_raw(u->sndfile, u->memchunk.memblock->data, BUF_SIZE)) <= 0) n = 0; u->memchunk.length = n; } - - pa_memblock_release(u->memchunk.memblock); if (!u->memchunk.length) { free_userdata(u); diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c index c74a1586f..1bf650e22 100644 --- a/src/pulsecore/sound-file.c +++ b/src/pulsecore/sound-file.c @@ -40,11 +40,7 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, int ret = -1; size_t l; sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL; - void *ptr = NULL; - - assert(fname); - assert(ss); - assert(chunk); + assert(fname && ss && chunk); chunk->memblock = NULL; chunk->index = chunk->length = 0; @@ -101,10 +97,8 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, chunk->index = 0; chunk->length = l; - ptr = pa_memblock_acquire(chunk->memblock); - - if ((readf_function && readf_function(sf, ptr, sfinfo.frames) != sfinfo.frames) || - (!readf_function && sf_read_raw(sf, ptr, l) != l)) { + if ((readf_function && readf_function(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) || + (!readf_function && sf_read_raw(sf, chunk->memblock->data, l) != l)) { pa_log("Premature file end"); goto finish; } @@ -116,9 +110,6 @@ finish: if (sf) sf_close(sf); - if (ptr) - pa_memblock_release(chunk->memblock); - if (ret != 0 && chunk->memblock) pa_memblock_unref(chunk->memblock); diff --git a/src/tests/flist-test.c b/src/tests/flist-test.c index 06d683110..abc0659d9 100644 --- a/src/tests/flist-test.c +++ b/src/tests/flist-test.c @@ -54,7 +54,7 @@ static void thread_func(void *data) { int b = 1; while (!quit) { - char *text; + char *text, *t; /* Allocate some memory, if possible take it from the flist */ if (b && (text = pa_flist_pop(flist))) diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index 1584256cb..356916984 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -59,27 +59,24 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { c.index = c.length = 0; } - assert(c.index < pa_memblock_get_length(c.memblock)); + assert(c.index < c.memblock->length); - l = pa_memblock_get_length(c.memblock) - c.index; + l = c.memblock->length - c.index; l = l <= 1 ? l : rand() % (l-1) +1 ; - - p = pa_memblock_acquire(c.memblock); - if ((r = read(STDIN_FILENO, (uint8_t*) p + c.index, l)) <= 0) { - pa_memblock_release(c.memblock); + + if ((r = read(STDIN_FILENO, (uint8_t*) c.memblock->data + c.index, l)) <= 0) { fprintf(stderr, "read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); break; } - pa_memblock_release(c.memblock); - + c.length = r; pa_mcalign_push(a, &c); fprintf(stderr, "Read %ld bytes\n", (long)r); c.index += r; - if (c.index >= pa_memblock_get_length(c.memblock)) { + if (c.index >= c.memblock->length) { pa_memblock_unref(c.memblock); pa_memchunk_reset(&c); } @@ -90,9 +87,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { if (pa_mcalign_pop(a, &t) < 0) break; - p = pa_memblock_acquire(t.memblock); - pa_loop_write(STDOUT_FILENO, (uint8_t*) p + t.index, t.length, NULL); - pa_memblock_release(t.memblock); + pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length, NULL); fprintf(stderr, "Wrote %lu bytes.\n", (unsigned long) t.length); pa_memblock_unref(t.memblock); diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c index c2dd2efa5..ef2e0ad71 100644 --- a/src/tests/memblock-test.c +++ b/src/tests/memblock-test.c @@ -76,7 +76,6 @@ int main(int argc, char *argv[]) { pa_memblock* blocks[5]; uint32_t id, shm_id; size_t offset, size; - char *x; const char txt[] = "This is a test!"; @@ -91,17 +90,10 @@ int main(int argc, char *argv[]) { assert(pool_a && pool_b && pool_c); blocks[0] = pa_memblock_new_fixed(pool_a, (void*) txt, sizeof(txt), 1); - blocks[1] = pa_memblock_new(pool_a, sizeof(txt)); - x = pa_memblock_acquire(blocks[1]); - snprintf(x, pa_memblock_get_length(blocks[1]), "%s", txt); - pa_memblock_release(blocks[1]); - + snprintf(blocks[1]->data, blocks[1]->length, "%s", txt); blocks[2] = pa_memblock_new_pool(pool_a, sizeof(txt)); - x = pa_memblock_acquire(blocks[2]); - snprintf(x, pa_memblock_get_length(blocks[2]), "%s", txt); - pa_memblock_release(blocks[1]); - + snprintf(blocks[2]->data, blocks[2]->length, "%s", txt); blocks[3] = pa_memblock_new_malloced(pool_a, pa_xstrdup(txt), sizeof(txt)); blocks[4] = NULL; @@ -138,18 +130,14 @@ int main(int argc, char *argv[]) { mb_c = pa_memimport_get(import_c, id, shm_id, offset, size); assert(mb_c); - x = pa_memblock_acquire(mb_c); - printf("1 data=%s\n", x); - pa_memblock_release(mb_c); + printf("1 data=%s\n", (char*) mb_c->data); print_stats(pool_a, "A"); print_stats(pool_b, "B"); print_stats(pool_c, "C"); pa_memexport_free(export_b); - x = pa_memblock_acquire(mb_c); - printf("2 data=%s\n", x); - pa_memblock_release(mb_c); + printf("2 data=%s\n", (char*) mb_c->data); pa_memblock_unref(mb_c); pa_memimport_free(import_b); diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c index 02848eb22..1ac4577b5 100644 --- a/src/tests/memblockq-test.c +++ b/src/tests/memblockq-test.c @@ -131,10 +131,8 @@ int main(int argc, char *argv[]) { if (pa_memblockq_peek(bq, &out) < 0) break; - p = pa_memblock_acquire(out.memblock); - for (e = (char*) p + out.index, n = 0; n < out.length; n++) + for (e = (char*) out.memblock->data + out.index, n = 0; n < out.length; n++) printf("%c", *e); - pa_memblock_release(out.memblock); pa_memblock_unref(out.memblock); pa_memblockq_drop(bq, &out, out.length); From d4ca81fc2e8f480ec3f244b5f23e9303b5816452 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 6 Nov 2006 13:16:15 +0000 Subject: [PATCH 1307/1514] Fix some missing line breaks. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1410 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 5d96a984e..a8ac8667e 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -191,7 +191,7 @@ do { \ #define CONTEXT_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ - debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ } while(0); @@ -199,7 +199,7 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ #define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ !(i)->play_stream || pa_stream_get_state((i)->play_stream) != PA_STREAM_READY) { \ - debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ } while(0); @@ -207,7 +207,7 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ #define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ !(i)->rec_stream || pa_stream_get_state((i)->rec_stream) != PA_STREAM_READY) { \ - debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ + debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ } while(0); From 55c25c657e907178de36e5b06b44cae66174d922 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 8 Nov 2006 12:56:26 +0000 Subject: [PATCH 1308/1514] Check correct variable for return value. Closes #37. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1411 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-esound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 80aeb27b1..c36f82017 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -463,7 +463,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co sdata.client = c->client; c->source_output = pa_source_output_new(c->protocol->core, &sdata, 9); - CHECK_VALIDITY(c->sink_input, "Failed to create source_output."); + CHECK_VALIDITY(c->source_output, "Failed to create source_output."); l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS); c->output_memblockq = pa_memblockq_new( From 0ef2d7eb778e25d252c78594fa6490a6cb654cb9 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 8 Nov 2006 13:03:35 +0000 Subject: [PATCH 1309/1514] Support reversed endian floats. (closes #28) (closes #35) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1412 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sample-util.c | 1 + src/pulsecore/sconv.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index d902b4b55..a7a5ed8f0 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -68,6 +68,7 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { case PA_SAMPLE_S16LE: case PA_SAMPLE_S16BE: case PA_SAMPLE_FLOAT32: + case PA_SAMPLE_FLOAT32RE: c = 0; break; case PA_SAMPLE_ALAW: diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index ff2a0110c..2e5e2dbef 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -72,6 +72,22 @@ static void float32ne_from_float32ne(unsigned n, const float *a, void *b) { oil_memcpy(b, a, sizeof(float) * n); } +static void float32re_to_float32ne(unsigned n, const void *a, float *b) { + assert(a); + assert(b); + + while (n-- > 0) + ((uint32_t *)b)[n] = UINT32_SWAP (((uint32_t *)a)[n]); +} + +static void float32re_from_float32ne(unsigned n, const float *a, void *b) { + assert(a); + assert(b); + + while (n-- > 0) + ((uint32_t *)b)[n] = UINT32_SWAP (((uint32_t *)a)[n]); +} + static void ulaw_to_float32ne(unsigned n, const void *a, float *b) { const uint8_t *ca = a; @@ -140,6 +156,8 @@ pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_fo return pa_sconv_s16be_to_float32ne; case PA_SAMPLE_FLOAT32NE: return float32ne_to_float32ne; + case PA_SAMPLE_FLOAT32RE: + return float32re_to_float32ne; case PA_SAMPLE_ALAW: return alaw_to_float32ne; case PA_SAMPLE_ULAW: @@ -159,6 +177,8 @@ pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sampl return pa_sconv_s16be_from_float32ne; case PA_SAMPLE_FLOAT32NE: return float32ne_from_float32ne; + case PA_SAMPLE_FLOAT32RE: + return float32re_from_float32ne; case PA_SAMPLE_ALAW: return alaw_from_float32ne; case PA_SAMPLE_ULAW: From 0a37ec28ff9e3b20a1c41170968de010cc0cb99f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 9 Nov 2006 15:23:30 +0000 Subject: [PATCH 1310/1514] Yet again try to fix the creation of necessary directories when srcdir != builddir. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1413 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 64df8614d..1a071ec43 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1006,9 +1006,9 @@ EXTRA_DIST += $(SYMDEF_FILES) BUILT_SOURCES += $(SYMDEF_FILES) $(SYMDEF_FILES): modules/module-defs.h.m4 - mkdir modules - mkdir modules/gconf - mkdir modules/rtp + -mkdir modules + -mkdir modules/gconf + -mkdir modules/rtp $(M4) -Dfname="$@" $< > $@ # Simple protocol From 86f4c2108f1bac17c32c68b9a4e8880a4577d533 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 10 Nov 2006 12:20:16 +0000 Subject: [PATCH 1311/1514] Make sure we package version.h.in. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1414 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index 1a071ec43..6adc06885 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,6 +88,7 @@ endif EXTRA_DIST = \ pulse/client.conf.in \ + pulse/version.h.in \ daemon/daemon.conf.in \ daemon/default.pa.in \ daemon/default.pa.win32 \ From 7933cbaf29c85e072ee3176dbb7a8baebb9263ca Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 10 Nov 2006 14:58:22 +0000 Subject: [PATCH 1312/1514] Add atomic.h as a dependency at relevant places. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1415 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 6adc06885..2f3bd8ab9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,6 +77,7 @@ PA_THREAD_OBJS = \ pulsecore/thread-win32.c pulsecore/thread.h else PA_THREAD_OBJS = \ + pulsecore/atomic.h \ pulsecore/once-posix.c pulsecore/once.h \ pulsecore/mutex-posix.c pulsecore/mutex.h \ pulsecore/thread-posix.c pulsecore/thread.h @@ -270,6 +271,7 @@ thread_test_LDADD = $(AM_LDADD) libpulsecore.la thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) flist_test_SOURCES = tests/flist-test.c \ + pulsecore/atomic.h \ pulsecore/flist.c pulsecore/flist.h flist_test_CFLAGS = $(AM_CFLAGS) flist_test_LDADD = $(AM_LDADD) libpulsecore.la @@ -514,6 +516,7 @@ libpulsedsp_la_LDFLAGS = -avoid-version pulsecoreinclude_HEADERS = \ pulsecore/autoload.h \ + pulsecore/atomic.h \ pulsecore/cli-command.h \ pulsecore/cli-text.h \ pulsecore/client.h \ From 68bcbd29139df99174e0e7757c540a91b577883f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 24 Nov 2006 09:29:10 +0000 Subject: [PATCH 1313/1514] Fix incorrect assert. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1416 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/autoload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/autoload.c b/src/pulsecore/autoload.c index f6869097a..8e57d343a 100644 --- a/src/pulsecore/autoload.c +++ b/src/pulsecore/autoload.c @@ -102,7 +102,7 @@ int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const c int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type) { pa_autoload_entry *e; - assert(c && name && type); + assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) return -1; From 1a460ee40ab19e354402f6c9346591b554471f03 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 4 Dec 2006 08:15:06 +0000 Subject: [PATCH 1314/1514] Fix silly copy-and-paste error. (closes #45) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1417 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/autoload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/autoload.c b/src/pulsecore/autoload.c index 8e57d343a..60304201f 100644 --- a/src/pulsecore/autoload.c +++ b/src/pulsecore/autoload.c @@ -102,7 +102,7 @@ int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const c int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type) { pa_autoload_entry *e; - assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); + assert(c && name && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) return -1; From 521daf6f0ac4fa6a2fbfb5d523c0c743342dca2b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 13:43:45 +0000 Subject: [PATCH 1315/1514] Huge trailing whitespace cleanup. Let's keep the tree pure from here on, mmmkay? git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1418 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/caps.c | 18 +- src/daemon/caps.h | 6 +- src/daemon/cmdline.c | 36 +-- src/daemon/cmdline.h | 6 +- src/daemon/cpulimit.c | 22 +- src/daemon/cpulimit.h | 6 +- src/daemon/daemon-conf.c | 16 +- src/daemon/daemon-conf.h | 4 +- src/daemon/dumpmodules.c | 22 +- src/daemon/main.c | 60 ++--- src/modules/alsa-util.c | 28 +- src/modules/alsa-util.h | 6 +- src/modules/dbus-util.c | 6 +- src/modules/dbus-util.h | 6 +- src/modules/module-alsa-sink.c | 54 ++-- src/modules/module-alsa-source.c | 58 ++-- src/modules/module-cli.c | 14 +- src/modules/module-combine.c | 70 ++--- src/modules/module-detect.c | 36 +-- src/modules/module-esound-compat-spawnfd.c | 6 +- src/modules/module-esound-compat-spawnpid.c | 6 +- src/modules/module-esound-sink.c | 58 ++-- src/modules/module-hal-detect.c | 12 +- src/modules/module-jack-sink.c | 70 ++--- src/modules/module-jack-source.c | 70 ++--- src/modules/module-lirc.c | 42 +-- src/modules/module-match.c | 26 +- src/modules/module-mmkbd-evdev.c | 26 +- src/modules/module-native-protocol-fd.c | 10 +- src/modules/module-null-sink.c | 24 +- src/modules/module-oss-mmap.c | 86 +++--- src/modules/module-oss.c | 70 ++--- src/modules/module-pipe-sink.c | 36 +-- src/modules/module-pipe-source.c | 30 +-- src/modules/module-protocol-stub.c | 36 +-- src/modules/module-rescue-streams.c | 22 +- src/modules/module-sine.c | 18 +- src/modules/module-solaris.c | 36 +-- src/modules/module-tunnel.c | 86 +++--- src/modules/module-volume-restore.c | 64 ++--- src/modules/module-waveout.c | 22 +- src/modules/module-x11-bell.c | 18 +- src/modules/module-x11-publish.c | 26 +- src/modules/module-zeroconf-publish.c | 108 ++++---- src/modules/oss-util.c | 44 ++-- src/modules/oss-util.h | 6 +- src/pulse/browser.c | 62 ++--- src/pulse/browser.h | 8 +- src/pulse/cdecl.h | 6 +- src/pulse/channelmap.c | 110 ++++---- src/pulse/channelmap.h | 20 +- src/pulse/client-conf-x11.c | 4 +- src/pulse/client-conf.c | 16 +- src/pulse/context.c | 156 +++++------ src/pulse/context.h | 10 +- src/pulse/def.h | 16 +- src/pulse/error.c | 6 +- src/pulse/error.h | 6 +- src/pulse/glib-mainloop.c | 98 +++---- src/pulse/glib-mainloop.h | 6 +- src/pulse/internal.h | 20 +- src/pulse/introspect.c | 118 ++++----- src/pulse/introspect.h | 24 +- src/pulse/mainloop-api.c | 6 +- src/pulse/mainloop-api.h | 8 +- src/pulse/mainloop-signal.c | 20 +- src/pulse/mainloop-signal.h | 6 +- src/pulse/mainloop.c | 96 +++---- src/pulse/mainloop.h | 8 +- src/pulse/operation.c | 20 +- src/pulse/operation.h | 6 +- src/pulse/pulseaudio.h | 12 +- src/pulse/sample.c | 12 +- src/pulse/sample.h | 6 +- src/pulse/scache.c | 24 +- src/pulse/scache.h | 6 +- src/pulse/simple.c | 68 ++--- src/pulse/simple.h | 6 +- src/pulse/stream.c | 238 ++++++++--------- src/pulse/stream.h | 20 +- src/pulse/subscribe.c | 10 +- src/pulse/subscribe.h | 6 +- src/pulse/thread-mainloop.c | 16 +- src/pulse/thread-mainloop.h | 10 +- src/pulse/timeval.c | 12 +- src/pulse/timeval.h | 6 +- src/pulse/utf8.c | 2 +- src/pulse/utf8.h | 6 +- src/pulse/util.c | 30 +-- src/pulse/util.h | 6 +- src/pulse/volume.c | 14 +- src/pulse/volume.h | 6 +- src/pulse/xmalloc.c | 20 +- src/pulse/xmalloc.h | 6 +- src/pulsecore/anotify.c | 18 +- src/pulsecore/anotify.h | 6 +- src/pulsecore/atomic.h | 6 +- src/pulsecore/authkey-prop.c | 10 +- src/pulsecore/authkey-prop.h | 6 +- src/pulsecore/authkey.c | 26 +- src/pulsecore/authkey.h | 6 +- src/pulsecore/autoload.c | 30 +-- src/pulsecore/autoload.h | 8 +- src/pulsecore/avahi-wrap.c | 34 +-- src/pulsecore/avahi-wrap.h | 6 +- src/pulsecore/cli-command.c | 48 ++-- src/pulsecore/cli-command.h | 6 +- src/pulsecore/cli-text.c | 46 ++-- src/pulsecore/cli-text.h | 6 +- src/pulsecore/cli.c | 14 +- src/pulsecore/cli.h | 6 +- src/pulsecore/client.c | 8 +- src/pulsecore/client.h | 6 +- src/pulsecore/conf-parser.c | 34 +-- src/pulsecore/core-def.h | 6 +- src/pulsecore/core-error.c | 6 +- src/pulsecore/core-error.h | 6 +- src/pulsecore/core-scache.c | 28 +- src/pulsecore/core-scache.h | 10 +- src/pulsecore/core-subscribe.c | 32 +-- src/pulsecore/core-subscribe.h | 6 +- src/pulsecore/core-util.c | 154 +++++------ src/pulsecore/core-util.h | 6 +- src/pulsecore/core.c | 18 +- src/pulsecore/core.h | 8 +- src/pulsecore/creds.h | 6 +- src/pulsecore/dynarray.c | 6 +- src/pulsecore/dynarray.h | 6 +- src/pulsecore/endianmacros.h | 6 +- src/pulsecore/esound.h | 6 +- src/pulsecore/flist.c | 22 +- src/pulsecore/flist.h | 6 +- src/pulsecore/g711.h | 2 +- src/pulsecore/gccmacro.h | 6 +- src/pulsecore/hashmap.c | 30 +-- src/pulsecore/hashmap.h | 6 +- src/pulsecore/hook-list.c | 30 +-- src/pulsecore/hook-list.h | 6 +- src/pulsecore/idxset.c | 50 ++-- src/pulsecore/idxset.h | 6 +- src/pulsecore/inet_ntop.c | 6 +- src/pulsecore/inet_pton.c | 6 +- src/pulsecore/iochannel.c | 66 ++--- src/pulsecore/iochannel.h | 6 +- src/pulsecore/ioline.c | 70 ++--- src/pulsecore/ioline.h | 6 +- src/pulsecore/ipacl.c | 36 +-- src/pulsecore/ipacl.h | 6 +- src/pulsecore/llist.h | 12 +- src/pulsecore/log.c | 30 +-- src/pulsecore/log.h | 6 +- src/pulsecore/mcalign.c | 34 +-- src/pulsecore/mcalign.h | 10 +- src/pulsecore/memblock.c | 94 +++---- src/pulsecore/memblock.h | 10 +- src/pulsecore/memblockq.c | 80 +++--- src/pulsecore/memblockq.h | 20 +- src/pulsecore/memchunk.c | 10 +- src/pulsecore/memchunk.h | 6 +- src/pulsecore/modargs.c | 22 +- src/pulsecore/modargs.h | 6 +- src/pulsecore/modinfo.c | 6 +- src/pulsecore/modinfo.h | 6 +- src/pulsecore/module.c | 38 +-- src/pulsecore/module.h | 8 +- src/pulsecore/mutex-posix.c | 6 +- src/pulsecore/mutex-win32.c | 6 +- src/pulsecore/mutex.h | 6 +- src/pulsecore/namereg.c | 60 ++--- src/pulsecore/namereg.h | 6 +- src/pulsecore/native-common.h | 18 +- src/pulsecore/once-posix.c | 30 +-- src/pulsecore/once-win32.c | 8 +- src/pulsecore/once.h | 6 +- src/pulsecore/packet.c | 14 +- src/pulsecore/packet.h | 6 +- src/pulsecore/parseaddr.c | 22 +- src/pulsecore/parseaddr.h | 6 +- src/pulsecore/pdispatch.c | 40 +-- src/pulsecore/pdispatch.h | 6 +- src/pulsecore/pid.c | 36 +-- src/pulsecore/pid.h | 6 +- src/pulsecore/pipe.c | 6 +- src/pulsecore/pipe.h | 6 +- src/pulsecore/play-memblockq.c | 18 +- src/pulsecore/play-memblockq.h | 6 +- src/pulsecore/play-memchunk.c | 18 +- src/pulsecore/play-memchunk.h | 6 +- src/pulsecore/poll.c | 6 +- src/pulsecore/poll.h | 6 +- src/pulsecore/props.c | 12 +- src/pulsecore/props.h | 6 +- src/pulsecore/protocol-cli.c | 10 +- src/pulsecore/protocol-cli.h | 6 +- src/pulsecore/protocol-esound.c | 152 +++++------ src/pulsecore/protocol-esound.h | 6 +- src/pulsecore/protocol-http.c | 28 +- src/pulsecore/protocol-http.h | 6 +- src/pulsecore/protocol-native.c | 274 +++++++++---------- src/pulsecore/protocol-native.h | 6 +- src/pulsecore/protocol-simple.c | 54 ++-- src/pulsecore/protocol-simple.h | 6 +- src/pulsecore/pstream-util.c | 6 +- src/pulsecore/pstream-util.h | 6 +- src/pulsecore/pstream.c | 146 +++++----- src/pulsecore/pstream.h | 6 +- src/pulsecore/queue.c | 8 +- src/pulsecore/queue.h | 6 +- src/pulsecore/random.c | 6 +- src/pulsecore/random.h | 8 +- src/pulsecore/refcnt.h | 6 +- src/pulsecore/resampler.c | 104 ++++---- src/pulsecore/resampler.h | 6 +- src/pulsecore/sample-util.c | 138 +++++----- src/pulsecore/sample-util.h | 6 +- src/pulsecore/sconv-s16be.c | 6 +- src/pulsecore/sconv-s16be.h | 6 +- src/pulsecore/sconv-s16le.c | 14 +- src/pulsecore/sconv-s16le.h | 6 +- src/pulsecore/sconv.c | 16 +- src/pulsecore/sconv.h | 6 +- src/pulsecore/shm.c | 46 ++-- src/pulsecore/shm.h | 6 +- src/pulsecore/sink-input.c | 100 +++---- src/pulsecore/sink-input.h | 22 +- src/pulsecore/sink.c | 98 +++---- src/pulsecore/sink.h | 12 +- src/pulsecore/sioman.c | 8 +- src/pulsecore/sioman.h | 6 +- src/pulsecore/socket-client.c | 68 ++--- src/pulsecore/socket-client.h | 6 +- src/pulsecore/socket-server.c | 66 ++--- src/pulsecore/socket-server.h | 6 +- src/pulsecore/socket-util.c | 20 +- src/pulsecore/socket-util.h | 6 +- src/pulsecore/sound-file-stream.c | 28 +- src/pulsecore/sound-file-stream.h | 6 +- src/pulsecore/sound-file.c | 18 +- src/pulsecore/sound-file.h | 6 +- src/pulsecore/source-output.c | 64 ++--- src/pulsecore/source-output.h | 12 +- src/pulsecore/source.c | 54 ++-- src/pulsecore/source.h | 16 +- src/pulsecore/strbuf.c | 18 +- src/pulsecore/strbuf.h | 6 +- src/pulsecore/strlist.c | 14 +- src/pulsecore/strlist.h | 6 +- src/pulsecore/tagstruct.c | 48 ++-- src/pulsecore/tagstruct.h | 6 +- src/pulsecore/thread-posix.c | 36 +-- src/pulsecore/thread-win32.c | 6 +- src/pulsecore/thread.h | 6 +- src/pulsecore/tokenizer.c | 8 +- src/pulsecore/tokenizer.h | 6 +- src/pulsecore/x11prop.c | 4 +- src/pulsecore/x11wrap.c | 26 +- src/pulsecore/x11wrap.h | 6 +- src/tests/channelmap-test.c | 10 +- src/tests/cpulimit-test.c | 14 +- src/tests/flist-test.c | 10 +- src/tests/get-binary-name-test.c | 6 +- src/tests/hook-list-test.c | 4 +- src/tests/interpol-test.c | 30 +-- src/tests/ipacl-test.c | 14 +- src/tests/mainloop-test.c | 8 +- src/tests/mcalign-test.c | 10 +- src/tests/memblock-test.c | 36 +-- src/tests/memblockq-test.c | 30 +-- src/tests/pacat-simple.c | 16 +- src/tests/parec-simple.c | 10 +- src/tests/strlist-test.c | 6 +- src/tests/sync-playback.c | 28 +- src/tests/thread-mainloop-test.c | 14 +- src/tests/thread-test.c | 32 +-- src/tests/utf8-test.c | 4 +- src/tests/voltest.c | 2 +- src/utils/pabrowse.c | 18 +- src/utils/pacat.c | 86 +++--- src/utils/pacmd.c | 40 +-- src/utils/pactl.c | 76 +++--- src/utils/padsp.c | 278 ++++++++++---------- src/utils/paplay.c | 48 ++-- src/utils/pax11publish.c | 24 +- 283 files changed, 3742 insertions(+), 3742 deletions(-) diff --git a/src/daemon/caps.c b/src/daemon/caps.c index cebdaebcc..db4bd9194 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -50,7 +50,7 @@ int setresuid(uid_t r, uid_t e, uid_t s); /* Drop root rights when called SUID root */ void pa_drop_root(void) { uid_t uid = getuid(); - + if (uid == 0 || geteuid() != 0) return; @@ -96,13 +96,13 @@ int pa_limit_caps(void) { if (cap_set_proc(caps) < 0) goto fail; - pa_log_info("dropped capabilities successfully."); - + pa_log_info("dropped capabilities successfully."); + r = 0; fail: cap_free (caps); - + return r; } @@ -124,12 +124,12 @@ int pa_drop_caps(void) { pa_log("failed to drop capabilities: %s", pa_cstrerror(errno)); goto fail; } - + r = 0; fail: cap_free (caps); - + return r; } diff --git a/src/daemon/caps.h b/src/daemon/caps.h index 8a618286f..34da1af68 100644 --- a/src/daemon/caps.h +++ b/src/daemon/caps.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index d368b644f..c3cb9209e 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -100,7 +100,7 @@ void pa_cmdline_help(const char *argv0) { e++; else e = argv0; - + printf("%s [options]\n\n" "COMMANDS:\n" " -h, --help Show this help\n" @@ -124,7 +124,7 @@ void pa_cmdline_help(const char *argv0) { " --scache-idle-time=SECS Unload autoloaded samples when idle and\n" " this time passed\n" " --log-level[=LEVEL] Increase or set verbosity level\n" - " -v Increase the verbosity level\n" + " -v Increase the verbosity level\n" " --log-target={auto,syslog,stderr} Specify the log target\n" " -p, --dl-search-path=PATH Set the search path for dynamic shared\n" " objects (plugins)\n" @@ -143,7 +143,7 @@ void pa_cmdline_help(const char *argv0) { " -F, --file=FILENAME Run the specified script\n" " -C Open a command line on the running TTY\n" " after startup\n\n" - + " -n Don't load default script file\n", e); } @@ -156,7 +156,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d if (conf->script_commands) pa_strbuf_puts(buf, conf->script_commands); - + while ((c = getopt_long(argc, argv, "L:F:ChDnp:kv", long_options, NULL)) != -1) { switch (c) { case ARG_HELP: @@ -184,21 +184,21 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_CHECK: conf->cmd = PA_CMD_CHECK; break; - + case ARG_LOAD: case 'L': pa_strbuf_printf(buf, "load-module %s\n", optarg); break; - + case ARG_FILE: case 'F': pa_strbuf_printf(buf, ".include %s\n", optarg); break; - + case 'C': pa_strbuf_puts(buf, "load-module module-cli exit_on_eof=1\n"); break; - + case ARG_DAEMONIZE: case 'D': if ((conf->daemonize = optarg ? pa_parse_boolean(optarg) : 1) < 0) { @@ -226,7 +226,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d if (conf->log_level < PA_LOG_LEVEL_MAX-1) conf->log_level++; } - + break; case ARG_HIGH_PRIORITY: @@ -249,13 +249,13 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d goto fail; } break; - + case 'p': case ARG_DL_SEARCH_PATH: pa_xfree(conf->dl_search_path); conf->dl_search_path = *optarg ? pa_xstrdup(optarg) : NULL; break; - + case 'n': pa_xfree(conf->default_script_file); conf->default_script_file = NULL; @@ -307,7 +307,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d goto fail; } break; - + default: goto fail; } @@ -322,12 +322,12 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d } *d = optind; - + return 0; - + fail: if (buf) pa_strbuf_free(buf); - + return -1; } diff --git a/src/daemon/cmdline.h b/src/daemon/cmdline.h index 25453e558..fdfbc0b69 100644 --- a/src/daemon/cmdline.h +++ b/src/daemon/cmdline.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index d7466b06e..808cb4d4a 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -80,7 +80,7 @@ static pa_io_event *io_event = NULL; static struct sigaction sigaction_prev; /* Nonzero after pa_cpu_limit_init() */ -static int installed = 0; +static int installed = 0; /* The current state of operation */ static enum { @@ -131,24 +131,24 @@ static void signal_handler(int sig) { snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100); write_err(t); #endif - + if (CPUTIME_INTERVAL_SOFT >= ((now-last_time)*(double)CPUTIME_PERCENT/100)) { static const char c = 'X'; write_err("Soft CPU time limit exhausted, terminating.\n"); - + /* Try a soft cleanup */ write(the_pipe[1], &c, sizeof(c)); phase = PHASE_SOFT; reset_cpu_time(CPUTIME_INTERVAL_HARD); - + } else { /* Everything's fine */ reset_cpu_time(CPUTIME_INTERVAL_SOFT); last_time = now; } - + } else if (phase == PHASE_SOFT) { write_err("Hard CPU time limit exhausted, terminating forcibly.\n"); _exit(1); /* Forced exit */ @@ -167,7 +167,7 @@ static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags int pa_cpu_limit_init(pa_mainloop_api *m) { struct sigaction sa; assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1 && !installed); - + time(&last_time); /* Prepare the main loop pipe */ @@ -191,7 +191,7 @@ int pa_cpu_limit_init(pa_mainloop_api *m) { sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - + if (sigaction(SIGXCPU, &sa, &sigaction_prev) < 0) { pa_cpu_limit_done(); return -1; @@ -200,7 +200,7 @@ int pa_cpu_limit_init(pa_mainloop_api *m) { installed = 1; reset_cpu_time(CPUTIME_INTERVAL_SOFT); - + return 0; } diff --git a/src/daemon/cpulimit.h b/src/daemon/cpulimit.h index 21bdd17ba..bb11f794e 100644 --- a/src/daemon/cpulimit.h +++ b/src/daemon/cpulimit.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index dd478126c..319cf0c7d 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -231,7 +231,7 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { int r = -1; FILE *f = NULL; - + pa_config_item table[] = { { "daemonize", pa_config_parse_bool, NULL }, { "fail", pa_config_parse_bool, NULL }, @@ -266,7 +266,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { #endif { NULL, NULL, NULL }, }; - + table[0].data = &c->daemonize; table[1].data = &c->fail; table[2].data = &c->high_priority; @@ -301,8 +301,8 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[24].data = &c->rlimit_memlock; #endif #endif - - + + pa_xfree(c->config_file); c->config_file = NULL; @@ -316,11 +316,11 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { } r = f ? pa_config_parse(c->config_file, f, table, NULL) : 0; - + finish: if (f) fclose(f); - + return r; } @@ -354,7 +354,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file); assert(c->log_level <= PA_LOG_LEVEL_MAX); - + pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize); pa_strbuf_printf(s, "fail = %i\n", !!c->fail); pa_strbuf_printf(s, "high-priority = %i\n", !!c->high_priority); @@ -385,6 +385,6 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1); #endif #endif - + return pa_strbuf_tostring_free(s); } diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index b4b833ad4..b7fcf23b7 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -66,7 +66,7 @@ typedef struct pa_daemon_conf { pa_log_level_t log_level; int resample_method; char *config_file; - + #ifdef HAVE_SYS_RESOURCE_H pa_rlimit rlimit_as, rlimit_core, rlimit_data, rlimit_fsize, rlimit_nofile, rlimit_stack; #ifdef RLIMIT_NPROC @@ -76,7 +76,7 @@ typedef struct pa_daemon_conf { pa_rlimit rlimit_memlock; #endif #endif - + } pa_daemon_conf; /* Allocate a new structure and fill it with sane defaults */ diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c index 06734ea63..8509924aa 100644 --- a/src/daemon/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -45,14 +45,14 @@ static void short_info(const char *name, PA_GCC_UNUSED const char *path, pa_modi static void long_info(const char *name, const char *path, pa_modinfo *i) { static int nl = 0; assert(name && i); - + if (nl) printf("\n"); nl = 1; printf("Name: %s\n", name); - + if (!i->description && !i->version && !i->author && !i->usage) printf("No module information available\n"); else { @@ -65,14 +65,14 @@ static void long_info(const char *name, const char *path, pa_modinfo *i) { if (i->usage) printf("Usage: %s\n", i->usage); } - + if (path) printf("Path: %s\n", path); } static void show_info(const char *name, const char *path, void (*info)(const char *name, const char *path, pa_modinfo*i)) { pa_modinfo *i; - + if ((i = pa_modinfo_get_by_name(path ? path : name))) { info(name, path, i); pa_modinfo_free(i); @@ -86,10 +86,10 @@ static int is_preloaded(const char *name) { for (l = lt_preloaded_symbols; l->name; l++) { char buf[64], *e; - + if (l->address) continue; - + snprintf(buf, sizeof(buf), "%s", l->name); if ((e = strrchr(buf, '.'))) *e = 0; @@ -112,7 +112,7 @@ static int callback(const char *path, lt_ptr data) { if (is_preloaded(e)) return 0; - + show_info(e, path, c->log_level >= PA_LOG_INFO ? long_info : short_info); return 0; } @@ -127,20 +127,20 @@ void pa_dump_modules(pa_daemon_conf *c, int argc, char * const argv[]) { for (l = lt_preloaded_symbols; l->name; l++) { char buf[64], *e; - + if (l->address) continue; if (strlen(l->name) <= sizeof(PREFIX)-1 || strncmp(l->name, PREFIX, sizeof(PREFIX)-1)) continue; - + snprintf(buf, sizeof(buf), "%s", l->name); if ((e = strrchr(buf, '.'))) *e = 0; - + show_info(buf, NULL, c->log_level >= PA_LOG_INFO ? long_info : short_info); } - + lt_dlforeachfile(NULL, callback, c); } } diff --git a/src/daemon/main.c b/src/daemon/main.c index 5d77282c7..b7266b7ea 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -125,7 +125,7 @@ static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, pa_module_load(userdata, "module-cli", NULL); break; #endif - + #ifdef SIGUSR2 case SIGUSR2: pa_module_load(userdata, "module-cli-protocol-unix", NULL); @@ -170,7 +170,7 @@ static int change_user(void) { /* This function is called only in system-wide mode. It creates a * runtime dir in /var/run/ with proper UID/GID and drops privs * afterwards. */ - + if (!(pw = getpwnam(PA_SYSTEM_USER))) { pa_log("Failed to find user '%s'.", PA_SYSTEM_USER); return -1; @@ -197,7 +197,7 @@ static int change_user(void) { pa_log("Failed to create '%s': %s", PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno)); return -1; } - + if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) { pa_log("Failed to change group list: %s", pa_cstrerror(errno)); return -1; @@ -265,7 +265,7 @@ static int create_runtime_dir(void) { /* This function is called only when the daemon is started in * per-user mode. We create the runtime directory somewhere in * /tmp/ with the current UID/GID */ - + if (pa_make_secure_dir(fn, 0700, (uid_t)-1, (gid_t)-1) < 0) { pa_log("Failed to create '%s': %s", fn, pa_cstrerror(errno)); return -1; @@ -311,7 +311,7 @@ int main(int argc, char *argv[]) { pa_daemon_conf *conf = NULL; pa_mainloop *mainloop = NULL; - char *s; + char *s; int r, retval = 1, d = 0; int daemon_pipe[2] = { -1, -1 }; int suid_root, real_root; @@ -333,7 +333,7 @@ int main(int argc, char *argv[]) { #ifdef HAVE_GETUID real_root = getuid() == 0; suid_root = !real_root && geteuid() == 0; - + if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) { pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'."); pa_drop_root(); @@ -342,9 +342,9 @@ int main(int argc, char *argv[]) { real_root = 0; suid_root = 0; #endif - + LTDL_SET_PRELOADED_SYMBOLS(); - + r = lt_dlinit(); assert(r == 0); @@ -356,11 +356,11 @@ int main(int argc, char *argv[]) { #endif pa_random_seed(); - + pa_log_set_ident("pulseaudio"); - + conf = pa_daemon_conf_new(); - + if (pa_daemon_conf_load(conf, NULL) < 0) goto finish; @@ -429,9 +429,9 @@ int main(int argc, char *argv[]) { pa_log("failed to kill daemon."); else retval = 0; - + goto finish; - + default: assert(conf->cmd == PA_CMD_DAEMON); } @@ -457,7 +457,7 @@ int main(int argc, char *argv[]) { pa_log("failed to create pipe."); goto finish; } - + if ((child = fork()) < 0) { pa_log("fork() failed: %s", pa_cstrerror(errno)); goto finish; @@ -478,7 +478,7 @@ int main(int argc, char *argv[]) { pa_log("daemon startup failed."); else pa_log_info("daemon startup successful."); - + goto finish; } @@ -517,7 +517,7 @@ int main(int argc, char *argv[]) { #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif - + #ifdef TIOCNOTTY if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) { ioctl(tty_fd, TIOCNOTTY, (char*) 0); @@ -528,13 +528,13 @@ int main(int argc, char *argv[]) { chdir("/"); umask(0022); - + if (conf->system_instance) { if (change_user() < 0) goto finish; } else if (create_runtime_dir() < 0) goto finish; - + if (conf->use_pid_file) { if (pa_pid_file_create() < 0) { pa_log("pa_pid_file_create() failed."); @@ -551,7 +551,7 @@ int main(int argc, char *argv[]) { #ifdef HAVE_SYS_RESOURCE_H set_all_rlimits(conf); #endif - + #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif @@ -580,7 +580,7 @@ int main(int argc, char *argv[]) { #ifdef SIGHUP pa_signal_new(SIGHUP, signal_callback, c); #endif - + #ifdef OS_IS_WIN32 timer = pa_mainloop_get_api(mainloop)->time_new( pa_mainloop_get_api(mainloop), pa_gettimeofday(&tv), message_cb, NULL); @@ -596,7 +596,7 @@ int main(int argc, char *argv[]) { r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop)); assert(r == 0); } - + buf = pa_strbuf_new(); if (conf->default_script_file) r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail); @@ -605,7 +605,7 @@ int main(int argc, char *argv[]) { r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); pa_xfree(s); - + if (r < 0 && conf->fail) { pa_log("failed to initialize daemon."); #ifdef HAVE_FORK @@ -652,11 +652,11 @@ int main(int argc, char *argv[]) { if (!conf->no_cpu_limit) pa_cpu_limit_done(); - + pa_signal_done(); - + pa_log_info("Daemon terminated."); - + finish: if (mainloop) @@ -667,7 +667,7 @@ finish: if (valid_pid_file) pa_pid_file_remove(); - + close_pipe(daemon_pipe); #ifdef OS_IS_WIN32 @@ -675,6 +675,6 @@ finish: #endif lt_dlexit(); - + return retval; } diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index d8b6c5ccc..8023d3add 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -270,7 +270,7 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s }; int i, ret; - + assert(pcm_handle); assert(f); @@ -290,12 +290,12 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0) return ret; - + try_auto: for (i = 0; try_order[i] != PA_SAMPLE_INVALID; i++) { *f = try_order[i]; - + if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0) return ret; } @@ -312,14 +312,14 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p unsigned int c = ss->channels; pa_sample_format_t f = ss->format; snd_pcm_hw_params_t *hwparams; - + assert(pcm_handle); assert(ss); assert(periods); assert(period_size); buffer_size = *periods * *period_size; - + if ((ret = snd_pcm_hw_params_malloc(&hwparams)) < 0 || (ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 || (ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0 || @@ -359,25 +359,25 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p pa_log_warn("device doesn't support sample format %s, changed to %s.", pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f)); ss->format = f; } - + if ((ret = snd_pcm_prepare(pcm_handle)) < 0) goto finish; if ((ret = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size)) < 0 || (ret = snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL)) < 0) goto finish; - + assert(buffer_size > 0); assert(*period_size > 0); *periods = buffer_size / *period_size; assert(*periods > 0); - + ret = 0; - + finish: if (hwparams) snd_pcm_hw_params_free(hwparams); - + return ret; } @@ -419,7 +419,7 @@ snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const if (fallback) { snd_mixer_selem_id_set_name(sid, fallback); - + if (!(elem = snd_mixer_find_selem(mixer, sid))) pa_log_warn("Cannot find fallback mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); } diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 215844b40..675856c6b 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c index 165ccff6a..ee9062d19 100644 --- a/src/modules/dbus-util.c +++ b/src/modules/dbus-util.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/modules/dbus-util.h b/src/modules/dbus-util.h index 7a9871a47..73501c29c 100644 --- a/src/modules/dbus-util.h +++ b/src/modules/dbus-util.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 6ff9a6e49..2fea58917 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -95,13 +95,13 @@ static void update_usage(struct userdata *u) { static void clear_up(struct userdata *u) { assert(u); - + if (u->sink) { pa_sink_disconnect(u->sink); pa_sink_unref(u->sink); u->sink = NULL; } - + if (u->pcm_fdl) pa_alsa_fdlist_free(u->pcm_fdl); if (u->mixer_fdl) @@ -113,7 +113,7 @@ static void clear_up(struct userdata *u) { snd_mixer_close(u->mixer_handle); u->mixer_handle = NULL; } - + if (u->pcm_handle) { snd_pcm_drop(u->pcm_handle); snd_pcm_close(u->pcm_handle); @@ -126,7 +126,7 @@ static int xrun_recovery(struct userdata *u) { assert(u); pa_log_info("*** ALSA-XRUN (playback) ***"); - + if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) { pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); @@ -142,11 +142,11 @@ static void do_write(struct userdata *u) { assert(u); update_usage(u); - + for (;;) { pa_memchunk *memchunk = NULL; snd_pcm_sframes_t frames; - + if (u->memchunk.memblock) memchunk = &u->memchunk; else { @@ -155,7 +155,7 @@ static void do_write(struct userdata *u) { else memchunk = &u->memchunk; } - + assert(memchunk->memblock && memchunk->memblock->data && memchunk->length && memchunk->memblock->length && (memchunk->length % u->frame_size) == 0); if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) { @@ -165,7 +165,7 @@ static void do_write(struct userdata *u) { if (frames == -EPIPE) { if (xrun_recovery(u) < 0) return; - + continue; } @@ -187,7 +187,7 @@ static void do_write(struct userdata *u) { memchunk->index = memchunk->length = 0; } } - + break; } } @@ -229,7 +229,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { struct userdata *u = s->userdata; snd_pcm_sframes_t frames; int err; - + assert(s && u && u->sink); if ((err = snd_pcm_delay(u->pcm_handle, &frames)) < 0) { @@ -292,14 +292,14 @@ static int sink_set_hw_volume_cb(pa_sink *s) { for (i = 0; i < s->hw_volume.channels; i++) { long alsa_vol; - + assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); vol = s->hw_volume.values[i]; if (vol > PA_VOLUME_NORM) vol = PA_VOLUME_NORM; - + alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, alsa_vol)) < 0) @@ -367,7 +367,7 @@ int pa__init(pa_core *c, pa_module*m) { const char *name; char *name_buf = NULL; int namereg_fail; - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments"); goto fail; @@ -380,7 +380,7 @@ int pa__init(pa_core *c, pa_module*m) { } frame_size = pa_frame_size(&ss); - + /* Fix latency to 100ms */ periods = 8; fragsize = pa_bytes_per_second(&ss)/128; @@ -390,11 +390,11 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } period_size = fragsize/frame_size; - + u = pa_xnew0(struct userdata, 1); m->userdata = u; u->module = m; - + snd_config_update_free_global(); if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); @@ -415,7 +415,7 @@ int pa__init(pa_core *c, pa_module*m) { if (ss.channels != map.channels) /* Seems ALSA didn't like the channel number, so let's fix the channel map */ pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); - + if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) { pa_log("Error opening mixer: %s", snd_strerror(err)); goto fail; @@ -486,7 +486,7 @@ int pa__init(pa_core *c, pa_module*m) { snd_mixer_elem_set_callback_private(u->mixer_elem, u); } else u->mixer_fdl = NULL; - + u->frame_size = frame_size; u->fragment_size = period_size * frame_size; @@ -499,7 +499,7 @@ int pa__init(pa_core *c, pa_module*m) { u->memchunk.memblock = NULL; u->memchunk.index = u->memchunk.length = 0; - + ret = 0; /* Get initial mixer settings */ @@ -507,21 +507,21 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_hw_volume(u->sink); if (u->sink->get_hw_mute) u->sink->get_hw_mute(u->sink); - + finish: pa_xfree(name_buf); - + if (ma) pa_modargs_free(ma); if (pcm_info) snd_pcm_info_free(pcm_info); - + return ret; fail: - + if (u) pa__done(c, m); @@ -541,7 +541,7 @@ void pa__done(pa_core *c, pa_module*m) { pa_memblock_unref(u->memchunk.memblock); if (u->silence.memblock) pa_memblock_unref(u->silence.memblock); - + pa_xfree(u); } diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index aa0666f10..596998d12 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -96,13 +96,13 @@ static void update_usage(struct userdata *u) { static void clear_up(struct userdata *u) { assert(u); - + if (u->source) { pa_source_disconnect(u->source); pa_source_unref(u->source); u->source = NULL; } - + if (u->pcm_fdl) pa_alsa_fdlist_free(u->pcm_fdl); if (u->mixer_fdl) @@ -114,7 +114,7 @@ static void clear_up(struct userdata *u) { snd_mixer_close(u->mixer_handle); u->mixer_handle = NULL; } - + if (u->pcm_handle) { snd_pcm_drop(u->pcm_handle); snd_pcm_close(u->pcm_handle); @@ -127,7 +127,7 @@ static int xrun_recovery(struct userdata *u) { assert(u); pa_log_info("*** ALSA-XRUN (capture) ***"); - + if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) { pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); @@ -144,17 +144,17 @@ static void do_read(struct userdata *u) { assert(u); update_usage(u); - + for (;;) { pa_memchunk post_memchunk; snd_pcm_sframes_t frames; size_t l; - + if (!u->memchunk.memblock) { u->memchunk.memblock = pa_memblock_new(u->source->core->mempool, u->memchunk.length = u->fragment_size); u->memchunk.index = 0; } - + assert(u->memchunk.memblock); assert(u->memchunk.length); assert(u->memchunk.memblock->data); @@ -164,11 +164,11 @@ static void do_read(struct userdata *u) { if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) { if (frames == -EAGAIN) return; - + if (frames == -EPIPE) { if (xrun_recovery(u) < 0) return; - + continue; } @@ -180,7 +180,7 @@ static void do_read(struct userdata *u) { } l = frames * u->frame_size; - + post_memchunk = u->memchunk; post_memchunk.length = l; @@ -188,13 +188,13 @@ static void do_read(struct userdata *u) { u->memchunk.index += l; u->memchunk.length -= l; - + if (u->memchunk.length == 0) { pa_memblock_unref(u->memchunk.memblock); u->memchunk.memblock = NULL; u->memchunk.index = u->memchunk.length = 0; } - + break; } } @@ -223,7 +223,7 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { u->source->get_hw_volume(u->source); if (u->source->get_hw_mute) u->source->get_hw_mute(u->source); - + pa_subscription_post(u->source->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, u->source->index); @@ -256,14 +256,14 @@ static int source_get_hw_volume_cb(pa_source *s) { for (i = 0;i < s->hw_volume.channels;i++) { long set_vol; - + assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i)); - + if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol)) < 0) goto fail; set_vol = (long) roundf(((float) s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; - + /* Try to avoid superfluous volume changes */ if (set_vol != vol) s->hw_volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); @@ -361,7 +361,7 @@ int pa__init(pa_core *c, pa_module*m) { const char *name; char *name_buf = NULL; int namereg_fail; - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments"); goto fail; @@ -378,17 +378,17 @@ int pa__init(pa_core *c, pa_module*m) { /* Fix latency to 100ms */ periods = 12; fragsize = pa_bytes_per_second(&ss)/128; - + if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { pa_log("failed to parse buffer metrics"); goto fail; } period_size = fragsize/frame_size; - + u = pa_xnew0(struct userdata, 1); m->userdata = u; u->module = m; - + snd_config_update_free_global(); if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); @@ -427,7 +427,7 @@ int pa__init(pa_core *c, pa_module*m) { name = name_buf = pa_sprintf_malloc("alsa_input.%s", dev); namereg_fail = 0; } - + if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map))) { pa_log("Failed to create source object"); goto fail; @@ -490,7 +490,7 @@ int pa__init(pa_core *c, pa_module*m) { u->memchunk.index = u->memchunk.length = 0; snd_pcm_start(u->pcm_handle); - + ret = 0; /* Get initial mixer settings */ @@ -507,11 +507,11 @@ finish: if (pcm_info) snd_pcm_info_free(pcm_info); - + return ret; fail: - + if (u) pa__done(c, m); @@ -526,10 +526,10 @@ void pa__done(pa_core *c, pa_module*m) { return; clear_up(u); - + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); - + pa_xfree(u); } diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c index d5374838b..b5c27299d 100644 --- a/src/modules/module-cli.c +++ b/src/modules/module-cli.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -48,7 +48,7 @@ static const char* const valid_modargs[] = { static void eof_and_unload_cb(pa_cli*c, void *userdata) { pa_module *m = userdata; - + assert(c); assert(m); @@ -68,7 +68,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_iochannel *io; pa_modargs *ma; int exit_on_eof = 0; - + assert(c); assert(m); @@ -81,7 +81,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse module arguments."); goto fail; } - + if (pa_modargs_get_value_boolean(ma, "exit_on_eof", &exit_on_eof) < 0) { pa_log("exit_on_eof= expects boolean argument."); goto fail; @@ -102,7 +102,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_cli_set_eof_callback(m->userdata, exit_on_eof ? eof_and_exit_cb : eof_and_unload_cb, m); pa_modargs_free(ma); - + return 0; fail: diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index f3bb3fd3a..6bc958aa9 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -91,7 +91,7 @@ struct userdata { struct output *master; pa_time_event *time_event; uint32_t adjust_time; - + PA_LLIST_HEAD(struct output, outputs); }; @@ -110,9 +110,9 @@ static void adjust_rates(struct userdata *u) { for (o = u->outputs; o; o = o->next) { uint32_t sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0; - + o->total_latency = sink_latency + pa_sink_input_get_latency(o->sink_input); - + if (sink_latency > max_sink_latency) max_sink_latency = sink_latency; @@ -123,14 +123,14 @@ static void adjust_rates(struct userdata *u) { assert(min_total_latency != (pa_usec_t) -1); target_latency = max_sink_latency > min_total_latency ? max_sink_latency : min_total_latency; - + pa_log_info("[%s] target latency is %0.0f usec.", u->sink->name, (float) target_latency); base_rate = u->sink->sample_spec.rate; for (o = u->outputs; o; o = o->next) { - uint32_t r = base_rate; - + uint32_t r = base_rate; + if (o->total_latency < target_latency) r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/ 1000000); else if (o->total_latency > target_latency) @@ -151,7 +151,7 @@ static void request_memblock(struct userdata *u) { assert(u && u->sink); update_usage(u); - + if (pa_sink_render(u->sink, RENDER_SIZE, &chunk) < 0) return; @@ -179,10 +179,10 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { if (pa_memblockq_peek(o->memblockq, chunk) >= 0) return 0; - + /* Try harder */ request_memblock(o->userdata); - + return pa_memblockq_peek(o->memblockq, chunk); } @@ -204,7 +204,7 @@ static void sink_input_kill_cb(pa_sink_input *i) { static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { struct output *o = i->userdata; assert(i && o && o->sink_input); - + return pa_bytes_to_usec(pa_memblockq_get_length(o->memblockq), &i->sample_spec); } @@ -220,11 +220,11 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { static void sink_notify(pa_sink *s) { struct userdata *u; struct output *o; - + assert(s); u = s->userdata; assert(u); - + for (o = u->outputs; o; o = o->next) pa_sink_notify(o->sink_input->sink); } @@ -233,12 +233,12 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample struct output *o = NULL; char t[256]; pa_sink_input_new_data data; - + assert(u && sink && u->sink); - + o = pa_xmalloc(sizeof(struct output)); o->userdata = u; - + o->counter = 0; o->memblockq = pa_memblockq_new( 0, @@ -258,7 +258,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample pa_sink_input_new_data_set_sample_spec(&data, &u->sink->sample_spec); pa_sink_input_new_data_set_channel_map(&data, &u->sink->channel_map); data.module = u->module; - + if (!(o->sink_input = pa_sink_input_new(u->core, &data, PA_SINK_INPUT_VARIABLE_RATE))) goto fail; @@ -267,7 +267,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample o->sink_input->drop = sink_input_drop_cb; o->sink_input->kill = sink_input_kill_cb; o->sink_input->userdata = o; - + PA_LLIST_PREPEND(struct output, u->outputs, o); u->n_outputs++; return o; @@ -282,7 +282,7 @@ fail: if (o->memblockq) pa_memblockq_free(o->memblockq); - + pa_xfree(o); } @@ -302,17 +302,17 @@ static void output_free(struct output *o) { static void clear_up(struct userdata *u) { struct output *o; assert(u); - + if (u->time_event) { u->core->mainloop->time_free(u->time_event); u->time_event = NULL; } - + while ((o = u->outputs)) output_free(o); u->master = NULL; - + if (u->sink) { pa_sink_disconnect(u->sink); pa_sink_unref(u->sink); @@ -331,7 +331,7 @@ int pa__init(pa_core *c, pa_module*m) { int resample_method = -1; pa_sample_spec ss; pa_channel_map map; - + assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -345,7 +345,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } } - + u = pa_xnew(struct userdata, 1); m->userdata = u; u->sink = NULL; @@ -361,7 +361,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse adjust_time value"); goto fail; } - + if (!(master_name = pa_modargs_get_value(ma, "master", NULL)) || !(slaves = pa_modargs_get_value(ma, "slaves", NULL))) { pa_log("no master or slave sinks specified"); goto fail; @@ -392,7 +392,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("channel map and sample specification don't match."); goto fail; } - + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { pa_log("failed to create sink"); goto fail; @@ -403,16 +403,16 @@ int pa__init(pa_core *c, pa_module*m) { u->sink->get_latency = sink_get_latency_cb; u->sink->notify = sink_notify; u->sink->userdata = u; - + if (!(u->master = output_new(u, master_sink, resample_method))) { pa_log("failed to create master sink input on sink '%s'.", u->sink->name); goto fail; } - + split_state = NULL; while ((n = pa_split(slaves, ",", &split_state))) { pa_sink *slave_sink; - + if (!(slave_sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) { pa_log("invalid slave sink '%s'", n); goto fail; @@ -425,7 +425,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } } - + if (u->n_outputs <= 1) pa_log_warn("WARNING: no slave sinks specified."); @@ -434,13 +434,13 @@ int pa__init(pa_core *c, pa_module*m) { tv.tv_sec += u->adjust_time; u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u); } - + pa_modargs_free(ma); - return 0; + return 0; fail: pa_xfree(n); - + if (ma) pa_modargs_free(ma); diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 84ccd14cb..3057f70db 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -58,7 +58,7 @@ static int detect_alsa(pa_core *c, int just_one) { if (errno != ENOENT) pa_log_error("open(\"/proc/asound/devices\") failed: %s", pa_cstrerror(errno)); - + return -1; } @@ -66,7 +66,7 @@ static int detect_alsa(pa_core *c, int just_one) { char line[64], args[64]; unsigned device, subdevice; int is_sink; - + if (!fgets(line, sizeof(line), f)) break; @@ -81,7 +81,7 @@ static int detect_alsa(pa_core *c, int just_one) { if (just_one && is_sink && n_sink >= 1) continue; - + if (just_one && !is_sink && n_source >= 1) continue; @@ -105,7 +105,7 @@ static int detect_alsa(pa_core *c, int just_one) { } fclose(f); - + return n; } #endif @@ -114,7 +114,7 @@ static int detect_alsa(pa_core *c, int just_one) { static int detect_oss(pa_core *c, int just_one) { FILE *f; int n = 0, b = 0; - + if (!(f = fopen("/dev/sndstat", "r")) && !(f = fopen("/proc/sndstat", "r")) && !(f = fopen("/proc/asound/oss/sndstat", "r"))) { @@ -128,7 +128,7 @@ static int detect_oss(pa_core *c, int just_one) { while (!feof(f)) { char line[64], args[64]; unsigned device; - + if (!fgets(line, sizeof(line), f)) break; @@ -141,20 +141,20 @@ static int detect_oss(pa_core *c, int just_one) { if (line[0] == 0) break; - + if (sscanf(line, "%u: ", &device) == 1) { if (device == 0) snprintf(args, sizeof(args), "device=/dev/dsp"); else snprintf(args, sizeof(args), "device=/dev/dsp%u", device); - + if (!pa_module_load(c, "module-oss", args)) continue; - + } else if (sscanf(line, "pcm%u: ", &device) == 1) { /* FreeBSD support, the devices are named /dev/dsp0.0, dsp0.1 and so on */ snprintf(args, sizeof(args), "device=/dev/dsp%u.0", device); - + if (!pa_module_load(c, "module-oss", args)) continue; } @@ -219,7 +219,7 @@ int pa__init(pa_core *c, pa_module*m) { "just-one", NULL }; - + assert(c); assert(m); @@ -227,14 +227,14 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("Failed to parse module arguments"); goto fail; } - + if (pa_modargs_get_value_boolean(ma, "just-one", &just_one) < 0) { pa_log("just_one= expects a boolean argument."); goto fail; } #if HAVE_ALSA - if ((n = detect_alsa(c, just_one)) <= 0) + if ((n = detect_alsa(c, just_one)) <= 0) #endif #if HAVE_OSS if ((n = detect_oss(c, just_one)) <= 0) @@ -251,7 +251,7 @@ int pa__init(pa_core *c, pa_module*m) { } pa_log_info("loaded %i modules.", n); - + /* We were successful and can unload ourselves now. */ pa_module_unload_request(m); @@ -262,7 +262,7 @@ int pa__init(pa_core *c, pa_module*m) { fail: if (ma) pa_modargs_free(ma); - + return -1; } diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index 263e81f93..fbb6bd6db 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index 7a662c2df..a7196313e 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -1,17 +1,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 6d4a84891..626006826 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -69,7 +69,7 @@ struct userdata { void *write_data; size_t write_length, write_index; - + void *read_data; size_t read_length, read_index; @@ -135,7 +135,7 @@ static int do_write(struct userdata *u) { u->write_index += r; assert(u->write_index <= u->write_length); - + if (u->write_index == u->write_length) { free(u->write_data); u->write_data = NULL; @@ -143,13 +143,13 @@ static int do_write(struct userdata *u) { } } else if (u->state == STATE_RUNNING) { pa_module_set_used(u->module, pa_sink_used_by(u->sink)); - + if (!u->memchunk.length) if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0) return 0; assert(u->memchunk.memblock && u->memchunk.length); - + if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { pa_log("write() failed: %s", pa_cstrerror(errno)); return -1; @@ -157,13 +157,13 @@ static int do_write(struct userdata *u) { u->memchunk.index += r; u->memchunk.length -= r; - + if (u->memchunk.length <= 0) { pa_memblock_unref(u->memchunk.memblock); u->memchunk.memblock = NULL; } } - + return 0; } @@ -191,7 +191,7 @@ static int handle_response(struct userdata *u) { assert(u->read_length >= sizeof(int32_t)); u->read_index = 0; u->read_length = sizeof(int32_t); - + break; case STATE_LATENCY: { @@ -220,10 +220,10 @@ static int handle_response(struct userdata *u) { pa_xfree(u->read_data); u->read_data = NULL; u->read_index = u->read_length = 0; - + break; } - + default: abort(); } @@ -233,18 +233,18 @@ static int handle_response(struct userdata *u) { static int do_read(struct userdata *u) { assert(u); - + if (!pa_iochannel_is_readable(u->io)) return 0; - + if (u->state == STATE_AUTH || u->state == STATE_LATENCY) { ssize_t r; - + if (!u->read_data) return 0; - + assert(u->read_index < u->read_length); - + if ((r = pa_iochannel_read(u->io, (uint8_t*) u->read_data + u->read_index, u->read_length - u->read_index)) <= 0) { pa_log("read() failed: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); cancel(u); @@ -265,7 +265,7 @@ static void do_work(struct userdata *u) { assert(u); u->core->mainloop->defer_enable(u->defer_event, 0); - + if (do_read(u) < 0 || do_write(u) < 0) cancel(u); } @@ -304,13 +304,13 @@ static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, vo pa_socket_client_unref(u->client); u->client = NULL; - + if (!io) { pa_log("connection failed: %s", pa_cstrerror(errno)); cancel(u); return; } - + u->io = io; pa_iochannel_set_callback(u->io, io_callback, u); } @@ -321,9 +321,9 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_modargs *ma = NULL; char *t; - + assert(c && m); - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments"); goto fail; @@ -340,7 +340,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("esound sample type support is limited to mono/stereo and U8 or S16NE sample data"); goto fail; } - + u = pa_xmalloc0(sizeof(struct userdata)); u->core = c; u->module = m; @@ -378,7 +378,7 @@ int pa__init(pa_core *c, pa_module*m) { /* Reserve space for the response */ u->read_data = pa_xmalloc(u->read_length = sizeof(int32_t)); - + u->sink->notify = notify_cb; u->sink->get_latency = get_latency_cb; u->sink->userdata = u; @@ -392,15 +392,15 @@ int pa__init(pa_core *c, pa_module*m) { u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u); c->mainloop->defer_enable(u->defer_event, 0); - + pa_modargs_free(ma); - + return 0; fail: if (ma) pa_modargs_free(ma); - + pa__done(c, m); return -1; @@ -415,13 +415,13 @@ void pa__done(pa_core *c, pa_module*m) { u->module = NULL; cancel(u); - + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); if (u->client) pa_socket_client_unref(u->client); - + pa_xfree(u->read_data); pa_xfree(u->write_data); diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 8232cd383..eb275ff02 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -58,7 +58,7 @@ typedef enum { #endif #ifdef HAVE_OSS CAP_OSS, -#endif +#endif CAP_MAX } capability_t; @@ -181,7 +181,7 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, module_name = "module-alsa-source"; snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi)); } - + return pa_module_load(u->core, module_name, args); } @@ -198,7 +198,7 @@ static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi, type = libhal_device_get_property_string(ctx, udi, "oss.type", error); if (!type || dbus_error_is_set(error)) return FALSE; - + if (!strcmp(type, "pcm")) { char *e; diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 47f77bab3..6175536c8 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -75,7 +75,7 @@ struct userdata { pthread_mutex_t mutex; pthread_cond_t cond; - + void * buffer[PA_CHANNELS_MAX]; jack_nframes_t frames_requested; int quit_requested; @@ -100,7 +100,7 @@ static const char* const valid_modargs[] = { static void stop_sink(struct userdata *u) { assert (u); - + jack_client_close(u->client); u->client = NULL; u->core->mainloop->io_free(u->io_event); @@ -114,7 +114,7 @@ static void stop_sink(struct userdata *u) { static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { struct userdata *u = userdata; char x; - + assert(m); assert(e); assert(flags == PA_IO_EVENT_INPUT); @@ -122,39 +122,39 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_ assert(u->pipe_fds[0] == fd); pa_read(fd, &x, 1, &u->pipe_fd_type); - + if (u->quit_requested) { stop_sink(u); u->quit_requested = 0; return; } - + pthread_mutex_lock(&u->mutex); if (u->frames_requested > 0) { unsigned fs; jack_nframes_t frame_idx; pa_memchunk chunk; - + fs = pa_frame_size(&u->sink->sample_spec); pa_sink_render_full(u->sink, u->frames_requested * fs, &chunk); for (frame_idx = 0; frame_idx < u->frames_requested; frame_idx ++) { unsigned c; - + for (c = 0; c < u->channels; c++) { float *s = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c; float *d = ((float*) u->buffer[c]) + frame_idx; - + *d = *s; } } - + pa_memblock_unref(chunk.memblock); u->frames_requested = 0; - + pthread_cond_signal(&u->cond); } @@ -183,36 +183,36 @@ static int jack_process(jack_nframes_t nframes, void *arg) { if (jack_transport_query(u->client, NULL) == JackTransportRolling) { unsigned c; - + pthread_mutex_lock(&u->mutex); - + u->frames_requested = nframes; - + for (c = 0; c < u->channels; c++) { u->buffer[c] = jack_port_get_buffer(u->port[c], nframes); assert(u->buffer[c]); } - + request_render(u); - + pthread_cond_wait(&u->cond, &u->mutex); u->frames_in_buffer = nframes; u->timestamp = jack_get_current_transport_frame(u->client); - + pthread_mutex_unlock(&u->mutex); } - + return 0; } static pa_usec_t sink_get_latency_cb(pa_sink *s) { struct userdata *u; jack_nframes_t n, l, d; - + assert(s); u = s->userdata; - + if (jack_transport_query(u->client, NULL) != JackTransportRolling) return 0; @@ -226,7 +226,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { if (d >= l) return 0; - + return pa_bytes_to_usec((l - d) * pa_frame_size(&s->sample_spec), &s->sample_spec); } @@ -246,12 +246,12 @@ int pa__init(pa_core *c, pa_module*m) { unsigned i; const char **ports = NULL, **p; char *t; - + assert(c); assert(m); jack_set_error_function(jack_error_func); - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments."); goto fail; @@ -261,7 +261,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse connect= argument."); goto fail; } - + server_name = pa_modargs_get_value(ma, "server_name", NULL); client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio"); @@ -274,28 +274,28 @@ int pa__init(pa_core *c, pa_module*m) { pthread_mutex_init(&u->mutex, NULL); pthread_cond_init(&u->cond, NULL); - + if (pipe(u->pipe_fds) < 0) { pa_log("pipe() failed: %s", pa_cstrerror(errno)); goto fail; } pa_make_nonblock_fd(u->pipe_fds[1]); - + if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { pa_log("jack_client_open() failed."); goto fail; } ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); - + channels = 0; for (p = ports; *p; p++) channels++; if (!channels) channels = c->default_sample_spec.channels; - + if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { pa_log("failed to parse channels= argument."); goto fail; @@ -306,7 +306,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse channel_map= argument."); goto fail; } - + pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client)); ss.channels = u->channels = channels; @@ -350,7 +350,7 @@ int pa__init(pa_core *c, pa_module*m) { } pa_log_info("connecting %s to %s", jack_port_name(u->port[i]), *p); - + if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) { pa_log("failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); break; @@ -360,10 +360,10 @@ int pa__init(pa_core *c, pa_module*m) { } u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u); - + free(ports); pa_modargs_free(ma); - + return 0; fail: @@ -371,7 +371,7 @@ fail: pa_modargs_free(ma); free(ports); - + pa__done(c, m); return -1; diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 62a991087..8d891ce64 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -75,7 +75,7 @@ struct userdata { pthread_mutex_t mutex; pthread_cond_t cond; - + void * buffer[PA_CHANNELS_MAX]; jack_nframes_t frames_posted; int quit_requested; @@ -100,7 +100,7 @@ static const char* const valid_modargs[] = { static void stop_source(struct userdata *u) { assert (u); - + jack_client_close(u->client); u->client = NULL; u->core->mainloop->io_free(u->io_event); @@ -114,39 +114,39 @@ static void stop_source(struct userdata *u) { static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { struct userdata *u = userdata; char x; - + assert(m); assert(flags == PA_IO_EVENT_INPUT); assert(u); assert(u->pipe_fds[0] == fd); pa_read(fd, &x, 1, &u->pipe_fd_type); - + if (u->quit_requested) { stop_source(u); u->quit_requested = 0; return; } - + pthread_mutex_lock(&u->mutex); if (u->frames_posted > 0) { unsigned fs; jack_nframes_t frame_idx; pa_memchunk chunk; - + fs = pa_frame_size(&u->source->sample_spec); chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length = u->frames_posted * fs); chunk.index = 0; - + for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) { unsigned c; - + for (c = 0; c < u->channels; c++) { float *s = ((float*) u->buffer[c]) + frame_idx; float *d = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c; - + *d = *s; } } @@ -155,7 +155,7 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_ pa_memblock_unref(chunk.memblock); u->frames_posted = 0; - + pthread_cond_signal(&u->cond); } @@ -184,36 +184,36 @@ static int jack_process(jack_nframes_t nframes, void *arg) { if (jack_transport_query(u->client, NULL) == JackTransportRolling) { unsigned c; - + pthread_mutex_lock(&u->mutex); - + u->frames_posted = nframes; - + for (c = 0; c < u->channels; c++) { u->buffer[c] = jack_port_get_buffer(u->port[c], nframes); assert(u->buffer[c]); } - + request_post(u); - + pthread_cond_wait(&u->cond, &u->mutex); u->frames_in_buffer = nframes; u->timestamp = jack_get_current_transport_frame(u->client); - + pthread_mutex_unlock(&u->mutex); } - + return 0; } static pa_usec_t source_get_latency_cb(pa_source *s) { struct userdata *u; jack_nframes_t n, l, d; - + assert(s); u = s->userdata; - + if (jack_transport_query(u->client, NULL) != JackTransportRolling) return 0; @@ -224,7 +224,7 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { d = n - u->timestamp; l = jack_port_get_total_latency(u->client, u->port[0]); - + return pa_bytes_to_usec((l + d) * pa_frame_size(&s->sample_spec), &s->sample_spec); } @@ -244,12 +244,12 @@ int pa__init(pa_core *c, pa_module*m) { unsigned i; const char **ports = NULL, **p; char *t; - + assert(c); assert(m); jack_set_error_function(jack_error_func); - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments."); goto fail; @@ -259,7 +259,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse connect= argument."); goto fail; } - + server_name = pa_modargs_get_value(ma, "server_name", NULL); client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio"); @@ -272,28 +272,28 @@ int pa__init(pa_core *c, pa_module*m) { pthread_mutex_init(&u->mutex, NULL); pthread_cond_init(&u->cond, NULL); - + if (pipe(u->pipe_fds) < 0) { pa_log("pipe() failed: %s", pa_cstrerror(errno)); goto fail; } pa_make_nonblock_fd(u->pipe_fds[1]); - + if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { pa_log("jack_client_open() failed."); goto fail; } ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput); - + channels = 0; for (p = ports; *p; p++) channels++; if (!channels) channels = c->default_sample_spec.channels; - + if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { pa_log("failed to parse channels= argument."); goto fail; @@ -304,7 +304,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse channel_map= argument."); goto fail; } - + pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client)); ss.channels = u->channels = channels; @@ -348,7 +348,7 @@ int pa__init(pa_core *c, pa_module*m) { } pa_log_info("connecting %s to %s", jack_port_name(u->port[i]), *p); - + if (jack_connect(u->client, *p, jack_port_name(u->port[i]))) { pa_log("failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); break; @@ -358,10 +358,10 @@ int pa__init(pa_core *c, pa_module*m) { } u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u); - + free(ports); pa_modargs_free(ma); - + return 0; fail: @@ -369,7 +369,7 @@ fail: pa_modargs_free(ma); free(ports); - + pa__done(c, m); return -1; diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index 18b2ddf1f..f32667ee6 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -73,20 +73,20 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_log("lost connection to LIRC daemon."); goto fail; } - + if (events & PA_IO_EVENT_INPUT) { char *c; - + if (lirc_nextcode(&code) != 0 || !code) { pa_log("lirc_nextcode() failed."); goto fail; } - + c = pa_xstrdup(code); c[strcspn(c, "\n\r")] = 0; pa_log_debug("raw IR code '%s'", c); pa_xfree(c); - + while (lirc_code2char(u->config, code, &name) == 0 && name) { enum { INVALID, @@ -96,9 +96,9 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC RESET, MUTE_TOGGLE } volchange = INVALID; - + pa_log_info("translated IR code '%s'", name); - + if (strcasecmp(name, "volume-up") == 0) volchange = UP; else if (strcasecmp(name, "volume-down") == 0) @@ -109,12 +109,12 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC volchange = MUTE_TOGGLE; else if (strcasecmp(name, "reset") == 0) volchange = RESET; - + if (volchange == INVALID) pa_log_warn("recieved unknown IR code '%s'", name); else { pa_sink *s; - + if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) pa_log("failed to get sink '%s'", u->sink_name); else { @@ -134,7 +134,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); break; - + case DOWN: for (i = 0; i < cv.channels; i++) { if (cv.values[i] >= DELTA) @@ -142,18 +142,18 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC else cv.values[i] = PA_VOLUME_MUTED; } - + pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); break; - + case MUTE: pa_sink_set_mute(s, PA_MIXER_HARDWARE, 0); break; - + case RESET: pa_sink_set_mute(s, PA_MIXER_HARDWARE, 1); break; - + case MUTE_TOGGLE: pa_sink_set_mute(s, PA_MIXER_HARDWARE, !pa_sink_get_mute(s, PA_MIXER_HARDWARE)); @@ -170,7 +170,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_xfree(code); return; - + fail: u->module->core->mainloop->io_free(u->io); u->io = NULL; @@ -179,7 +179,7 @@ fail: free(code); } - + int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; @@ -189,7 +189,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("module-lirc may no be loaded twice."); return -1; } - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; @@ -212,13 +212,13 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("lirc_readconfig() failed."); goto fail; } - + u->io = c->mainloop->io_new(c->mainloop, u->lirc_fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); lirc_in_use = 1; pa_modargs_free(ma); - + return 0; fail: diff --git a/src/modules/module-match.c b/src/modules/module-match.c index eb5de64eb..d0e82ba32 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -88,7 +88,7 @@ static int load_rules(struct userdata *u, const char *filename) { } pa_lock_fd(fileno(f), 1); - + while (!feof(f)) { char *d, *v; pa_volume_t volume; @@ -96,12 +96,12 @@ static int load_rules(struct userdata *u, const char *filename) { regex_t regex; char ln[256]; struct rule *rule; - + if (!fgets(ln, sizeof(ln), f)) break; n++; - + pa_strip_nl(ln); if (ln[0] == '#' || !*ln ) @@ -110,7 +110,7 @@ static int load_rules(struct userdata *u, const char *filename) { d = ln+strcspn(ln, WHITESPACE); v = d+strspn(d, WHITESPACE); - + if (!*v) { pa_log(__FILE__ ": [%s:%u] failed to parse line - too few words", filename, n); goto finish; @@ -124,7 +124,7 @@ static int load_rules(struct userdata *u, const char *filename) { volume = (pa_volume_t) k; - + if (regcomp(®ex, ln, REG_EXTENDED|REG_NOSUB) != 0) { pa_log("[%s:%u] invalid regular expression", filename, n); goto finish; @@ -140,12 +140,12 @@ static int load_rules(struct userdata *u, const char *filename) { else u->rules = rule; end = rule; - + *d = 0; } ret = 0; - + finish: if (f) { pa_lock_fd(fileno(f), 0); @@ -172,7 +172,7 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v if (!si->name) return; - + for (r = u->rules; r; r = r->next) { if (!regexec(&r->regex, si->name, 0, NULL, 0)) { pa_cvolume cv; @@ -197,7 +197,7 @@ int pa__init(pa_core *c, pa_module*m) { u->rules = NULL; u->subscription = NULL; m->userdata = u; - + if (load_rules(u, pa_modargs_get_value(ma, "table", NULL)) < 0) goto fail; @@ -224,7 +224,7 @@ void pa__done(pa_core *c, pa_module*m) { if (u->subscription) pa_subscription_free(u->subscription); - + for (r = u->rules; r; r = n) { n = r->next; diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index 37234d925..baf688f19 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -85,7 +85,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_log("lost connection to evdev device."); goto fail; } - + if (events & PA_IO_EVENT_INPUT) { struct input_event ev; @@ -107,15 +107,15 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC if (volchange != INVALID) { pa_sink *s; - + if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) pa_log("failed to get sink '%s'", u->sink_name); else { int i; pa_cvolume cv = *pa_sink_get_volume(s, PA_MIXER_HARDWARE); - + #define DELTA (PA_VOLUME_NORM/20) - + switch (volchange) { case UP: for (i = 0; i < cv.channels; i++) { @@ -127,7 +127,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); break; - + case DOWN: for (i = 0; i < cv.channels; i++) { if (cv.values[i] >= DELTA) @@ -135,10 +135,10 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC else cv.values[i] = PA_VOLUME_MUTED; } - + pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); break; - + case MUTE_TOGGLE: pa_sink_set_mute(s, PA_MIXER_HARDWARE, !pa_sink_get_mute(s, PA_MIXER_HARDWARE)); @@ -153,7 +153,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC } return; - + fail: u->module->core->mainloop->io_free(u->io); u->io = NULL; @@ -162,7 +162,7 @@ fail: } #define test_bit(bit, array) (array[bit/8] & (1<<(bit%8))) - + int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; @@ -226,7 +226,7 @@ int pa__init(pa_core *c, pa_module*m) { u->io = c->mainloop->io_new(c->mainloop, u->fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); pa_modargs_free(ma); - + return 0; fail: diff --git a/src/modules/module-native-protocol-fd.c b/src/modules/module-native-protocol-fd.c index dd3b4abe8..907aab273 100644 --- a/src/modules/module-native-protocol-fd.c +++ b/src/modules/module-native-protocol-fd.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -61,7 +61,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("invalid file descriptor."); goto finish; } - + io = pa_iochannel_new(c->mainloop, fd, fd); if (!(m->userdata = pa_protocol_native_new_iochannel(c, io, m, ma))) { @@ -74,7 +74,7 @@ int pa__init(pa_core *c, pa_module*m) { finish: if (ma) pa_modargs_free(ma); - + return r; } diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 50e58853a..fc9107a37 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -115,10 +115,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; - + assert(c); assert(m); - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments."); goto fail; @@ -129,12 +129,12 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("invalid sample format specification or channel map."); goto fail; } - + u = pa_xnew0(struct userdata, 1); u->core = c; u->module = m; m->userdata = u; - + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { pa_log("failed to create sink."); goto fail; @@ -147,19 +147,19 @@ int pa__init(pa_core *c, pa_module*m) { u->n_bytes = 0; pa_gettimeofday(&u->start_time); - + u->time_event = c->mainloop->time_new(c->mainloop, &u->start_time, time_callback, u); u->block_size = pa_bytes_per_second(&ss) / 10; - + pa_modargs_free(ma); - + return 0; fail: if (ma) pa_modargs_free(ma); - + pa__done(c, m); return -1; @@ -171,7 +171,7 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; - + pa_sink_disconnect(u->sink); pa_sink_unref(u->sink); diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 5ab082878..7bf6cbbdf 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -113,7 +113,7 @@ static const char* const valid_modargs[] = { #define DEFAULT_FRAGSIZE 1024 static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, + pa_module_set_used(u->module, (u->sink ? pa_sink_used_by(u->sink) : 0) + (u->source ? pa_source_used_by(u->source) : 0)); } @@ -126,7 +126,7 @@ static void clear_up(struct userdata *u) { pa_sink_unref(u->sink); u->sink = NULL; } - + if (u->source) { pa_source_disconnect(u->source); pa_source_unref(u->source); @@ -137,12 +137,12 @@ static void clear_up(struct userdata *u) { munmap(u->in_mmap, u->in_mmap_length); u->in_mmap = NULL; } - + if (u->out_mmap && u->out_mmap != MAP_FAILED) { munmap(u->out_mmap, u->out_mmap_length); u->out_mmap = NULL; } - + if (u->io_event) { u->core->mainloop->io_free(u->io_event); u->io_event = NULL; @@ -156,13 +156,13 @@ static void clear_up(struct userdata *u) { static void out_fill_memblocks(struct userdata *u, unsigned n) { assert(u && u->out_memblocks); - + while (n > 0) { pa_memchunk chunk; - + if (u->out_memblocks[u->out_current]) pa_memblock_unref_fixed(u->out_memblocks[u->out_current]); - + chunk.memblock = u->out_memblocks[u->out_current] = pa_memblock_new_fixed( u->core->mempool, @@ -172,13 +172,13 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) { assert(chunk.memblock); chunk.length = chunk.memblock->length; chunk.index = 0; - + pa_sink_render_into_full(u->sink, &chunk); - + u->out_current++; while (u->out_current >= u->out_fragments) u->out_current -= u->out_fragments; - + n--; } } @@ -188,7 +188,7 @@ static void do_write(struct userdata *u) { assert(u && u->sink); update_usage(u); - + if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); @@ -199,31 +199,31 @@ static void do_write(struct userdata *u) { info.blocks += u->out_blocks_saved; u->out_blocks_saved = 0; - + if (!info.blocks) return; - + out_fill_memblocks(u, info.blocks); } static void in_post_memblocks(struct userdata *u, unsigned n) { assert(u && u->in_memblocks); - + while (n > 0) { pa_memchunk chunk; - + if (!u->in_memblocks[u->in_current]) { chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->core->mempool, (uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, 1); chunk.length = chunk.memblock->length; chunk.index = 0; - + pa_source_post(u->source, &chunk); } u->in_current++; while (u->in_current >= u->in_fragments) u->in_current -= u->in_fragments; - + n--; } } @@ -234,7 +234,7 @@ static void in_clear_memblocks(struct userdata*u, unsigned n) { if (n > u->in_fragments) n = u->in_fragments; - + while (n > 0) { if (u->in_memblocks[i]) { pa_memblock_unref_fixed(u->in_memblocks[i]); @@ -254,7 +254,7 @@ static void do_read(struct userdata *u) { assert(u && u->source); update_usage(u); - + if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); @@ -265,10 +265,10 @@ static void do_read(struct userdata *u) { info.blocks += u->in_blocks_saved; u->in_blocks_saved = 0; - + if (!info.blocks) return; - + in_post_memblocks(u, info.blocks); in_clear_memblocks(u, u->in_fragments/2); } @@ -311,7 +311,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) { n = bpos - info.ptr; /* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->out_fragment_size, u->out_fragments); */ - + return pa_bytes_to_usec(n, &s->sample_spec); } @@ -337,7 +337,7 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { n = (u->in_fragments * u->in_fragment_size) - bpos + info.ptr; /* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->in_fragment_size, u->in_fragments); */ - + return pa_bytes_to_usec(n, &s->sample_spec); } @@ -416,7 +416,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse module arguments."); goto fail; } - + if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { pa_log("record= and playback= expect numeric arguments."); goto fail; @@ -460,7 +460,7 @@ int pa__init(pa_core *c, pa_module*m) { if (nfrags >= 2 && frag_size >= 1) if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0) goto fail; - + if (pa_oss_auto_format(u->fd, &u->sample_spec) < 0) goto fail; @@ -491,7 +491,7 @@ int pa__init(pa_core *c, pa_module*m) { if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &u->sample_spec, &map))) goto fail; - + u->source->userdata = u; u->source->get_latency = source_get_latency_cb; u->source->get_hw_volume = source_get_hw_volume; @@ -504,22 +504,22 @@ int pa__init(pa_core *c, pa_module*m) { hwdesc[0] ? ")" : "")); pa_xfree(t); u->source->is_hardware = 1; - + u->in_memblocks = pa_xnew0(pa_memblock*, u->in_fragments); - + enable_bits |= PCM_ENABLE_INPUT; } } pa_xfree(name_buf); name_buf = NULL; - + if (mode != O_RDONLY) { if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { pa_log("SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno)); goto fail; } - + pa_log_info("output -- %u fragments of size %u.", info.fragstotal, info.fragsize); u->out_mmap_length = (u->out_fragment_size = info.fragsize) * (u->out_fragments = info.fragstotal); @@ -540,7 +540,7 @@ int pa__init(pa_core *c, pa_module*m) { name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p)); namereg_fail = 0; } - + if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &u->sample_spec, &map))) goto fail; @@ -555,28 +555,28 @@ int pa__init(pa_core *c, pa_module*m) { hwdesc[0] ? hwdesc : "", hwdesc[0] ? ")" : "")); pa_xfree(t); - + u->sink->is_hardware = 1; u->out_memblocks = pa_xmalloc0(sizeof(struct memblock *)*u->out_fragments); - + enable_bits |= PCM_ENABLE_OUTPUT; } } pa_xfree(name_buf); name_buf = NULL; - + zero = 0; if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero) < 0) { pa_log("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); goto fail; } - + if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0) { pa_log("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); goto fail; } - + assert(u->source || u->sink); u->io_event = c->mainloop->io_new(c->mainloop, u->fd, (u->source ? PA_IO_EVENT_INPUT : 0) | (u->sink ? PA_IO_EVENT_OUTPUT : 0), io_callback, u); @@ -589,7 +589,7 @@ int pa__init(pa_core *c, pa_module*m) { source_get_hw_volume(u->source); if (u->sink) sink_get_hw_volume(u->sink); - + return 0; fail: @@ -599,13 +599,13 @@ fail: pa_modargs_free(ma); pa_xfree(name_buf); - + return -1; } void pa__done(pa_core *c, pa_module*m) { struct userdata *u; - + assert(c); assert(m); @@ -629,6 +629,6 @@ void pa__done(pa_core *c, pa_module*m) { pa_memblock_unref_fixed(u->in_memblocks[i]); pa_xfree(u->in_memblocks); } - + pa_xfree(u); } diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index b71581d9a..b8ced86fb 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -100,20 +100,20 @@ static const char* const valid_modargs[] = { #define DEFAULT_DEVICE "/dev/dsp" static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, + pa_module_set_used(u->module, (u->sink ? pa_sink_used_by(u->sink) : 0) + (u->source ? pa_source_used_by(u->source) : 0)); } static void clear_up(struct userdata *u) { assert(u); - + if (u->sink) { pa_sink_disconnect(u->sink); pa_sink_unref(u->sink); u->sink = NULL; } - + if (u->source) { pa_source_disconnect(u->source); pa_source_unref(u->source); @@ -131,7 +131,7 @@ static void do_write(struct userdata *u) { ssize_t r; size_t l; int loop = 0; - + assert(u); if (!u->sink || !pa_iochannel_is_writable(u->io)) @@ -140,10 +140,10 @@ static void do_write(struct userdata *u) { update_usage(u); l = u->out_fragment_size; - + if (u->use_getospace) { audio_buf_info info; - + if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) u->use_getospace = 0; else { @@ -156,15 +156,15 @@ static void do_write(struct userdata *u) { do { memchunk = &u->memchunk; - + if (!memchunk->length) if (pa_sink_render(u->sink, l, memchunk) < 0) memchunk = &u->silence; - + assert(memchunk->memblock); assert(memchunk->memblock->data); assert(memchunk->length); - + if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { pa_log("write() failed: %s", pa_cstrerror(errno)); @@ -172,13 +172,13 @@ static void do_write(struct userdata *u) { pa_module_unload_request(u->module); break; } - + if (memchunk == &u->silence) assert(r % u->sample_size == 0); else { u->memchunk.index += r; u->memchunk.length -= r; - + if (u->memchunk.length <= 0) { pa_memblock_unref(u->memchunk.memblock); u->memchunk.memblock = NULL; @@ -195,7 +195,7 @@ static void do_read(struct userdata *u) { size_t l; int loop = 0; assert(u); - + if (!u->source || !pa_iochannel_is_readable(u->io) || !pa_idxset_size(u->source->outputs)) return; @@ -205,7 +205,7 @@ static void do_read(struct userdata *u) { if (u->use_getispace) { audio_buf_info info; - + if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) u->use_getispace = 0; else { @@ -215,7 +215,7 @@ static void do_read(struct userdata *u) { } } } - + do { memchunk.memblock = pa_memblock_new(u->core->mempool, l); assert(memchunk.memblock); @@ -228,11 +228,11 @@ static void do_read(struct userdata *u) { } break; } - + assert(r <= (ssize_t) memchunk.memblock->length); memchunk.length = memchunk.memblock->length = r; memchunk.index = 0; - + pa_source_post(u->source, &memchunk); pa_memblock_unref(memchunk.memblock); @@ -280,12 +280,12 @@ static pa_usec_t source_get_latency_cb(pa_source *s) { if (!u->use_getispace) return 0; - + if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { u->use_getispace = 0; return 0; } - + if (info.bytes <= 0) return 0; @@ -355,7 +355,7 @@ int pa__init(pa_core *c, pa_module*m) { const char *name; char *name_buf = NULL; int namereg_fail; - + assert(c); assert(m); @@ -363,7 +363,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse module arguments."); goto fail; } - + if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { pa_log("record= and playback= expect numeric argument."); goto fail; @@ -381,11 +381,11 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse sample specification or channel map"); goto fail; } - + /* Fix latency to 100ms */ nfrags = 12; frag_size = pa_bytes_per_second(&ss)/128; - + if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { pa_log("failed to parse fragments arguments"); goto fail; @@ -398,12 +398,12 @@ int pa__init(pa_core *c, pa_module*m) { pa_log_info("hardware name is '%s'.", hwdesc); else hwdesc[0] = 0; - + pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (nfrags >= 2 && frag_size >= 1) - if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) - goto fail; + if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) + goto fail; if (pa_oss_auto_format(fd, &ss) < 0) goto fail; @@ -418,7 +418,7 @@ int pa__init(pa_core *c, pa_module*m) { u = pa_xmalloc(sizeof(struct userdata)); u->core = c; u->use_getospace = u->use_getispace = 0; - + if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize); in_frag_size = info.fragsize; @@ -438,7 +438,7 @@ int pa__init(pa_core *c, pa_module*m) { name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(p)); namereg_fail = 0; } - + if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map))) goto fail; @@ -468,7 +468,7 @@ int pa__init(pa_core *c, pa_module*m) { name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p)); namereg_fail = 0; } - + if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map))) goto fail; @@ -489,7 +489,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_xfree(name_buf); name_buf = NULL; - + assert(u->source || u->sink); u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : -1); @@ -539,13 +539,13 @@ fail: pa_modargs_free(ma); pa_xfree(name_buf); - + return -1; } void pa__done(pa_core *c, pa_module*m) { struct userdata *u; - + assert(c); assert(m); @@ -553,7 +553,7 @@ void pa__done(pa_core *c, pa_module*m) { return; clear_up(u); - + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); if (u->silence.memblock) diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 4aee849bb..724003130 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -63,7 +63,7 @@ struct userdata { pa_core *core; char *filename; - + pa_sink *sink; pa_iochannel *io; pa_defer_event *defer_event; @@ -87,18 +87,18 @@ static void do_write(struct userdata *u) { assert(u); u->core->mainloop->defer_enable(u->defer_event, 0); - + if (!pa_iochannel_is_writable(u->io)) return; pa_module_set_used(u->module, pa_sink_used_by(u->sink)); - + if (!u->memchunk.length) if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) return; assert(u->memchunk.memblock && u->memchunk.length); - + if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { pa_log("write(): %s", pa_cstrerror(errno)); return; @@ -106,7 +106,7 @@ static void do_write(struct userdata *u) { u->memchunk.index += r; u->memchunk.length -= r; - + if (u->memchunk.length <= 0) { pa_memblock_unref(u->memchunk.memblock); u->memchunk.memblock = NULL; @@ -149,9 +149,9 @@ int pa__init(pa_core *c, pa_module*m) { pa_channel_map map; pa_modargs *ma = NULL; char *t; - + assert(c && m); - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments"); goto fail; @@ -162,7 +162,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("invalid sample format specification"); goto fail; } - + mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); if ((fd = open(p, O_RDWR)) < 0) { @@ -171,7 +171,7 @@ int pa__init(pa_core *c, pa_module*m) { } pa_fd_set_cloexec(fd, 1); - + if (fstat(fd, &st) < 0) { pa_log("fstat('%s'): %s", p, pa_cstrerror(errno)); goto fail; @@ -187,7 +187,7 @@ int pa__init(pa_core *c, pa_module*m) { u->core = c; u->module = m; m->userdata = u; - + if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { pa_log("failed to create sink."); goto fail; @@ -211,13 +211,13 @@ int pa__init(pa_core *c, pa_module*m) { c->mainloop->defer_enable(u->defer_event, 0); pa_modargs_free(ma); - + return 0; fail: if (ma) pa_modargs_free(ma); - + if (fd >= 0) close(fd); @@ -232,10 +232,10 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; - + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); - + pa_sink_disconnect(u->sink); pa_sink_unref(u->sink); pa_iochannel_free(u->io); @@ -244,6 +244,6 @@ void pa__done(pa_core *c, pa_module*m) { assert(u->filename); unlink(u->filename); pa_xfree(u->filename); - + pa_xfree(u); } diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index c251f7ac3..f53f6a63b 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -63,7 +63,7 @@ struct userdata { pa_core *core; char *filename; - + pa_source *source; pa_iochannel *io; pa_module *module; @@ -127,9 +127,9 @@ int pa__init(pa_core *c, pa_module*m) { pa_channel_map map; pa_modargs *ma = NULL; char *t; - + assert(c && m); - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments"); goto fail; @@ -140,7 +140,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("invalid sample format specification or channel map"); goto fail; } - + mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); if ((fd = open(p, O_RDWR)) < 0) { @@ -149,7 +149,7 @@ int pa__init(pa_core *c, pa_module*m) { } pa_fd_set_cloexec(fd, 1); - + if (fstat(fd, &st) < 0) { pa_log("fstat('%s'): %s", p, pa_cstrerror(errno)); goto fail; @@ -164,7 +164,7 @@ int pa__init(pa_core *c, pa_module*m) { u->filename = pa_xstrdup(p); u->core = c; - + if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { pa_log("failed to create source."); goto fail; @@ -180,18 +180,18 @@ int pa__init(pa_core *c, pa_module*m) { u->chunk.memblock = NULL; u->chunk.index = u->chunk.length = 0; - + u->module = m; m->userdata = u; pa_modargs_free(ma); - + return 0; fail: if (ma) pa_modargs_free(ma); - + if (fd >= 0) close(fd); @@ -206,10 +206,10 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; - + if (u->chunk.memblock) pa_memblock_unref(u->chunk.memblock); - + pa_source_disconnect(u->source); pa_source_unref(u->source); pa_iochannel_free(u->io); @@ -217,6 +217,6 @@ void pa__done(pa_core *c, pa_module*m) { assert(u->filename); unlink(u->filename); pa_xfree(u->filename); - + pa_xfree(u); } diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index df58958a9..93fb2a366 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -85,13 +85,13 @@ "record= " SOCKET_USAGE) #elif defined(USE_PROTOCOL_CLI) - #include + #include #define protocol_new pa_protocol_cli_new #define protocol_free pa_protocol_cli_free #define TCPWRAP_SERVICE "pulseaudio-cli" #define IPV4_PORT 4712 #define UNIX_SOCKET "cli" - #define MODULE_ARGUMENTS + #define MODULE_ARGUMENTS #ifdef USE_TCP_SOCKETS #include "module-cli-protocol-tcp-symdef.h" #else @@ -106,7 +106,7 @@ #define TCPWRAP_SERVICE "pulseaudio-http" #define IPV4_PORT 4714 #define UNIX_SOCKET "http" - #define MODULE_ARGUMENTS + #define MODULE_ARGUMENTS #ifdef USE_TCP_SOCKETS #include "module-http-protocol-tcp-symdef.h" #else @@ -129,16 +129,16 @@ #endif #if defined(HAVE_CREDS) && !defined(USE_TCP_SOCKETS) - #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable", + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable", #define AUTH_USAGE "auth-group= auth-group-enable= " #elif defined(USE_TCP_SOCKETS) - #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl", + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl", #define AUTH_USAGE "auth-ip-acl= " #else #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON #define AUTH_USAGE #endif - + PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) PA_MODULE_USAGE("auth-anonymous= " "cookie= " @@ -160,7 +160,7 @@ #endif #if defined(USE_TCP_SOCKETS) - #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl", + #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl", #define AUTH_USAGE "auth-ip-acl= " #else #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON @@ -175,7 +175,7 @@ AUTH_USAGE SOCKET_USAGE) #else - #error "Broken build system" + #error "Broken build system" #endif PA_MODULE_AUTHOR("Lennart Poettering") @@ -266,21 +266,21 @@ int pa__init(pa_core *c, pa_module*m) { /* This socket doesn't reside in our own runtime dir but in * /tmp/.esd/, hence we have to create the dir first */ - + if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) { pa_log("Failed to create socket directory: %s\n", pa_cstrerror(errno)); goto fail; } #endif - + if ((r = pa_unix_socket_remove_stale(tmp)) < 0) { pa_log("Failed to remove stale UNIX socket '%s': %s", tmp, pa_cstrerror(errno)); goto fail; } - + if (r) pa_log("Removed stale UNIX socket '%s'.", tmp); - + if (!(s = pa_socket_server_new_unix(c->mainloop, tmp))) goto fail; @@ -332,7 +332,7 @@ fail: void pa__done(pa_core *c, pa_module*m) { struct userdata *u; - + assert(c); assert(m); @@ -354,8 +354,8 @@ void pa__done(pa_core *c, pa_module*m) { pa_xfree(p); } #endif - - + + pa_xfree(u->socket_path); #endif diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c index 7aa205bd4..2eea4f61d 100644 --- a/src/modules/module-rescue-streams.c +++ b/src/modules/module-rescue-streams.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -49,7 +49,7 @@ struct userdata { static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* userdata) { pa_sink_input *i; pa_sink *target; - + assert(c); assert(sink); @@ -57,7 +57,7 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user pa_log_debug("No sink inputs to move away."); return PA_HOOK_OK; } - + if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, 0))) { pa_log_info("No evacuation sink found."); return PA_HOOK_OK; @@ -74,14 +74,14 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user pa_log_info("Sucessfully moved sink input %u \"%s\" to %s.", i->index, i->name, target->name); } - + return PA_HOOK_OK; } static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void* userdata) { pa_source_output *o; pa_source *target; - + assert(c); assert(source); @@ -89,7 +89,7 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void pa_log_debug("No source outputs to move away."); return PA_HOOK_OK; } - + if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SOURCE, 0))) { pa_log_info("No evacuation source found."); return PA_HOOK_OK; @@ -106,14 +106,14 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void pa_log_info("Sucessfully moved source output %u \"%s\" to %s.", o->index, o->name, target->name); } - + return PA_HOOK_OK; } int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; - + assert(c); assert(m); @@ -132,7 +132,7 @@ int pa__init(pa_core *c, pa_module*m) { void pa__done(pa_core *c, pa_module*m) { struct userdata *u; - + assert(c); assert(m); diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index fa29ba160..871b702d3 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -96,7 +96,7 @@ static void calc_sine(float *f, size_t l, float freq) { size_t i; l /= sizeof(float); - + for (i = 0; i < l; i++) f[i] = (float) sin((double) i/l*M_PI*2*freq)/2; } @@ -115,7 +115,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("Failed to parse module arguments"); goto fail; } - + m->userdata = u = pa_xmalloc(sizeof(struct userdata)); u->core = c; u->module = m; @@ -138,7 +138,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("Invalid frequency specification"); goto fail; } - + u->memblock = pa_memblock_new(c->mempool, pa_bytes_per_second(&ss)); calc_sine(u->memblock->data, u->memblock->length, frequency); @@ -160,10 +160,10 @@ int pa__init(pa_core *c, pa_module*m) { u->sink_input->userdata = u; u->peek_index = 0; - + pa_modargs_free(ma); return 0; - + fail: if (ma) pa_modargs_free(ma); @@ -183,7 +183,7 @@ void pa__done(pa_core *c, pa_module*m) { pa_sink_input_disconnect(u->sink_input); pa_sink_input_unref(u->sink_input); } - + if (u->memblock) pa_memblock_unref(u->memblock); pa_xfree(u); diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 66968cb1a..1454d6398 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -124,7 +124,7 @@ static void do_write(struct userdata *u) { int err; size_t len; ssize_t r; - + assert(u); /* We cannot check pa_iochannel_is_writable() because of our buffer hack */ @@ -163,7 +163,7 @@ static void do_write(struct userdata *u) { } u->sink_underflow = 0; - + assert(u->memchunk.memblock); assert(u->memchunk.memblock->data); assert(u->memchunk.length); @@ -181,10 +181,10 @@ static void do_write(struct userdata *u) { } assert(r % u->frame_size == 0); - + u->memchunk.index += r; u->memchunk.length -= r; - + if (u->memchunk.length <= 0) { pa_memblock_unref(u->memchunk.memblock); u->memchunk.memblock = NULL; @@ -199,7 +199,7 @@ static void do_read(struct userdata *u) { size_t l; ssize_t r; assert(u); - + if (!u->source || !pa_iochannel_is_readable(u->io)) return; @@ -221,11 +221,11 @@ static void do_read(struct userdata *u) { pa_log("read() failed: %s", pa_cstrerror(errno)); return; } - + assert(r <= (ssize_t) memchunk.memblock->length); memchunk.length = memchunk.memblock->length = r; memchunk.index = 0; - + pa_source_post(u->source, &memchunk); pa_memblock_unref(memchunk.memblock); @@ -256,7 +256,7 @@ static void timer_cb(pa_mainloop_api*a, pa_time_event *e, const struct timeval * static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { struct userdata *u = userdata; pa_cvolume old_vol; - + assert(u); if (u->sink) { @@ -518,7 +518,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse module arguments."); goto fail; } - + if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { pa_log("record= and playback= expect numeric argument."); goto fail; @@ -531,7 +531,7 @@ int pa__init(pa_core *c, pa_module*m) { mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); - buffer_size = 16384; + buffer_size = 16384; if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) { pa_log("failed to parse buffer size argument"); goto fail; @@ -542,7 +542,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse sample specification"); goto fail; } - + if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode | O_NONBLOCK)) < 0) goto fail; @@ -642,7 +642,7 @@ fail: if (ma) pa_modargs_free(ma); - + return -1; } @@ -657,7 +657,7 @@ void pa__done(pa_core *c, pa_module*m) { c->mainloop->time_free(u->timer); ioctl(u->fd, I_SETSIG, 0); pa_signal_free(u->sig); - + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); @@ -665,12 +665,12 @@ void pa__done(pa_core *c, pa_module*m) { pa_sink_disconnect(u->sink); pa_sink_unref(u->sink); } - + if (u->source) { pa_source_disconnect(u->source); pa_source_unref(u->source); } - + pa_iochannel_free(u->io); pa_xfree(u); } diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index a110c57e2..f7420a67b 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -116,10 +116,10 @@ static void command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { #ifdef TUNNEL_SINK [PA_COMMAND_REQUEST] = command_request, -#endif +#endif [PA_COMMAND_PLAYBACK_STREAM_KILLED] = command_stream_killed, [PA_COMMAND_RECORD_STREAM_KILLED] = command_stream_killed, - [PA_COMMAND_SUBSCRIBE_EVENT] = command_subscribe_event, + [PA_COMMAND_SUBSCRIBE_EVENT] = command_subscribe_event, }; struct userdata { @@ -136,7 +136,7 @@ struct userdata { char *source_name; pa_source *source; #endif - + pa_module *module; pa_core *core; @@ -146,7 +146,7 @@ struct userdata { uint32_t ctag; uint32_t device_index; uint32_t channel; - + pa_usec_t host_latency; pa_time_event *time_event; @@ -156,7 +156,7 @@ struct userdata { static void close_stuff(struct userdata *u) { assert(u); - + if (u->pstream) { pa_pstream_close(u->pstream); pa_pstream_unref(u->pstream); @@ -256,10 +256,10 @@ static void send_bytes(struct userdata *u) { while (u->requested_bytes > 0) { pa_memchunk chunk; if (pa_sink_render(u->sink, u->requested_bytes, &chunk) < 0) { - - if (u->requested_bytes >= DEFAULT_TLENGTH-DEFAULT_PREBUF) + + if (u->requested_bytes >= DEFAULT_TLENGTH-DEFAULT_PREBUF) send_prebuf_request(u); - + return; } @@ -293,7 +293,7 @@ static void command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED ui die(u); return; } - + u->requested_bytes += bytes; send_bytes(u); } @@ -316,7 +316,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G die(u); return; } - + if (pa_tagstruct_get_usec(t, &sink_usec) < 0 || pa_tagstruct_get_usec(t, &source_usec) < 0 || pa_tagstruct_get_boolean(t, &playing) < 0 || @@ -333,14 +333,14 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G pa_gettimeofday(&now); /* FIXME! This could use some serious love. */ - + if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) { /* local and remote seem to have synchronized clocks */ #ifdef TUNNEL_SINK transport_usec = pa_timeval_diff(&remote, &local); #else transport_usec = pa_timeval_diff(&now, &remote); -#endif +#endif } else transport_usec = pa_timeval_diff(&now, &local)/2; @@ -364,7 +364,7 @@ static void request_latency(struct userdata *u) { assert(u); t = pa_tagstruct_new(NULL, 0); -#ifdef TUNNEL_SINK +#ifdef TUNNEL_SINK pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); #else pa_tagstruct_putu32(t, PA_COMMAND_GET_RECORD_LATENCY); @@ -374,7 +374,7 @@ static void request_latency(struct userdata *u) { pa_gettimeofday(&now); pa_tagstruct_put_timeval(t, &now); - + pa_pstream_send_tagstruct(u->pstream, t); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u, NULL); } @@ -496,7 +496,7 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED assert(m && e && u); request_latency(u); - + pa_gettimeofday(&ntv); ntv.tv_sec += LATENCY_INTERVAL; m->time_restart(e, &ntv); @@ -518,16 +518,16 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN if (pa_tagstruct_getu32(t, &u->channel) < 0 || pa_tagstruct_getu32(t, &u->device_index) < 0 -#ifdef TUNNEL_SINK +#ifdef TUNNEL_SINK || pa_tagstruct_getu32(t, &u->requested_bytes) < 0 -#endif +#endif ) goto parse_error; if (u->version >= 9) { #ifdef TUNNEL_SINK uint32_t maxlength, tlength, prebuf, minreq; - + if (pa_tagstruct_getu32(t, &maxlength) < 0 || pa_tagstruct_getu32(t, &tlength) < 0 || pa_tagstruct_getu32(t, &prebuf) < 0 || @@ -535,13 +535,13 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN goto parse_error; #else uint32_t maxlength, fragsize; - + if (pa_tagstruct_getu32(t, &maxlength) < 0 || - pa_tagstruct_getu32(t, &fragsize) < 0) + pa_tagstruct_getu32(t, &fragsize) < 0) goto parse_error; #endif } - + if (!pa_tagstruct_eof(t)) goto parse_error; @@ -559,7 +559,7 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN #endif return; - + parse_error: pa_log("invalid reply. (create stream)"); die(u); @@ -603,7 +603,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_get_user_name(un, sizeof(un)), u->source->name); #endif - + reply = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME); pa_tagstruct_putu32(reply, tag = u->ctag++); @@ -612,7 +612,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t /* We ignore the server's reply here */ reply = pa_tagstruct_new(NULL, 0); -#ifdef TUNNEL_SINK +#ifdef TUNNEL_SINK pa_tagstruct_putu32(reply, PA_COMMAND_CREATE_PLAYBACK_STREAM); pa_tagstruct_putu32(reply, tag = u->ctag++); pa_tagstruct_puts(reply, name); @@ -640,7 +640,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct_put_boolean(reply, 0); pa_tagstruct_putu32(reply, DEFAULT_FRAGSIZE); #endif - + pa_pstream_send_tagstruct(u->pstream, reply); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u, NULL); } @@ -673,7 +673,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, PA_GCC_UN die(u); return; } - + pa_source_post(u->source, chunk); } #endif @@ -686,7 +686,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata pa_socket_client_unref(u->client); u->client = NULL; - + if (!io) { pa_log("connection failed."); pa_module_unload_request(u->module); @@ -701,7 +701,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata #ifndef TUNNEL_SINK pa_pstream_set_recieve_memblock_callback(u->pstream, pstream_memblock_callback, u); #endif - + t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_AUTH); pa_tagstruct_putu32(t, tag = u->ctag++); @@ -709,7 +709,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata pa_tagstruct_put_arbitrary(t, u->auth_cookie, sizeof(u->auth_cookie)); pa_pstream_send_tagstruct(u->pstream, t); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, u, NULL); - + } #ifdef TUNNEL_SINK @@ -862,14 +862,14 @@ static int load_key(struct userdata *u, const char*fn) { assert(u); u->auth_cookie_in_property = 0; - + if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { pa_log_debug("using already loaded auth cookie."); pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); u->auth_cookie_in_property = 1; return 0; } - + if (!fn) fn = PA_NATIVE_COOKIE_FILE; @@ -877,7 +877,7 @@ static int load_key(struct userdata *u, const char*fn) { return -1; pa_log_debug("loading cookie from disk."); - + if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) u->auth_cookie_in_property = 1; @@ -890,7 +890,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_channel_map map; char *t, *dn = NULL; - + assert(c && m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -919,10 +919,10 @@ int pa__init(pa_core *c, pa_module*m) { u->host_latency = 0; u->auth_cookie_in_property = 0; u->time_event = NULL; - + if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0) goto fail; - + if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) { pa_log("no server specified."); goto fail; @@ -938,7 +938,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to connect to server '%s'", u->server_name); goto fail; } - + if (!u->client) goto fail; @@ -987,7 +987,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_source_set_owner(u->source, m); #endif - + pa_xfree(dn); u->time_event = NULL; @@ -995,7 +995,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_modargs_free(ma); return 0; - + fail: pa__done(c, m); @@ -1003,7 +1003,7 @@ fail: pa_modargs_free(ma); pa_xfree(dn); - + return -1; } @@ -1018,7 +1018,7 @@ void pa__done(pa_core *c, pa_module*m) { if (u->auth_cookie_in_property) pa_authkey_prop_unref(c, PA_NATIVE_COOKIE_PROPERTY_NAME); - + #ifdef TUNNEL_SINK pa_xfree(u->sink_name); #else diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index efa59f406..877d17c78 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -82,7 +82,7 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { char *p; long k; unsigned i; - + assert(s); assert(v); @@ -92,7 +92,7 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { k = strtol(s, &p, 0); if (k <= 0 || k > PA_CHANNELS_MAX) return NULL; - + v->channels = (unsigned) k; for (i = 0; i < v->channels; i++) { @@ -105,7 +105,7 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { if (k < PA_VOLUME_MUTED) return NULL; - + v->values[i] = (pa_volume_t) k; } @@ -132,22 +132,22 @@ static int load_rules(struct userdata *u) { ret = 0; } else pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); - + goto finish; } pa_lock_fd(fileno(f), 1); - + while (!feof(f)) { struct rule *rule; pa_cvolume v; int v_is_set; - + if (!fgets(ln, sizeof(buf_name), f)) break; n++; - + pa_strip_nl(ln); if (ln[0] == '#') @@ -181,12 +181,12 @@ static int load_rules(struct userdata *u) { v_is_set = 0; ln = buf_name; - + if (pa_hashmap_get(u->hashmap, buf_name)) { pa_log("double entry in %s:%u, ignoring", u->table_file, n); continue; } - + rule = pa_xnew(struct rule, 1); rule->name = pa_xstrdup(buf_name); if ((rule->volume_is_set = v_is_set)) @@ -203,7 +203,7 @@ static int load_rules(struct userdata *u) { } ret = 0; - + finish: if (f) { pa_lock_fd(fileno(f), 0); @@ -218,7 +218,7 @@ static int save_rules(struct userdata *u) { int ret = -1; void *state = NULL; struct rule *rule; - + f = u->table_file ? fopen(u->table_file, "w") : pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w"); @@ -232,7 +232,7 @@ static int save_rules(struct userdata *u) { while ((rule = pa_hashmap_iterate(u->hashmap, &state, NULL))) { unsigned i; - + fprintf(f, "%s\n", rule->name); if (rule->volume_is_set) { @@ -241,14 +241,14 @@ static int save_rules(struct userdata *u) { for (i = 0; i < rule->volume.channels; i++) fprintf(f, " %u", rule->volume.values[i]); } - + fprintf(f, "\n%s\n%s\n", rule->sink ? rule->sink : "", rule->source ? rule->source : ""); } - + ret = 0; - + finish: if (f) { pa_lock_fd(fileno(f), 0); @@ -260,7 +260,7 @@ finish: static char* client_name(pa_client *c) { char *t, *e; - + if (!c->name || !c->driver) return NULL; @@ -280,11 +280,11 @@ static char* client_name(pa_client *c) { * sessions of the same application, which is something we * explicitly don't want. Besides other stuff this makes xmms * with esound work properly for us. */ - + if (*k == ')' && *(k+1) == 0) *e = 0; } - + return t; } @@ -294,7 +294,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 pa_source_output *so = NULL; struct rule *r; char *name; - + assert(c); assert(u); @@ -307,7 +307,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) { if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) return; - + if (!si->client || !(name = client_name(si->client))) return; } else { @@ -315,7 +315,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) return; - + if (!so->client || !(name = client_name(so->client))) return; } @@ -348,7 +348,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 u->modified = 1; } } - + } else { pa_log_info("Creating new entry for <%s>", name); @@ -366,7 +366,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 r->sink = NULL; r->source = pa_xstrdup(so->source->name); } - + pa_hashmap_put(u->hashmap, r->name, r); u->modified = 1; } @@ -419,7 +419,7 @@ static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; - + assert(c); assert(m); @@ -433,9 +433,9 @@ int pa__init(pa_core *c, pa_module*m) { u->subscription = NULL; u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL)); u->modified = 0; - + m->userdata = u; - + if (load_rules(u) < 0) goto fail; @@ -451,7 +451,7 @@ fail: if (ma) pa_modargs_free(ma); - + return -1; } @@ -467,7 +467,7 @@ static void free_func(void *p, void *userdata) { void pa__done(pa_core *c, pa_module*m) { struct userdata* u; - + assert(c); assert(m); @@ -486,7 +486,7 @@ void pa__done(pa_core *c, pa_module*m) { if (u->modified) save_rules(u); - + pa_hashmap_free(u->hashmap, free_func, NULL); } diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 4043c1364..e245e1380 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -172,7 +172,7 @@ static void do_write(struct userdata *u) pa_log_error(__FILE__ ": ERROR: Unable to write waveOut block: %d", res); } - + u->written_bytes += hdr->dwBufferLength; EnterCriticalSection(&u->crit); @@ -233,7 +233,7 @@ static void do_read(struct userdata *u) pa_log_error(__FILE__ ": ERROR: Unable to add waveIn block: %d", res); } - + free_frags--; u->cur_ihdr++; u->cur_ihdr %= u->fragments; @@ -561,7 +561,7 @@ int pa__init(pa_core *c, pa_module*m) { u->ohdrs[i].lpData = pa_xmalloc(u->fragment_size); assert(u->ohdrs); } - + u->module = m; m->userdata = u; @@ -585,7 +585,7 @@ fail: if (ma) pa_modargs_free(ma); - + return -1; } @@ -597,7 +597,7 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; - + if (u->event) c->mainloop->time_free(u->event); @@ -608,12 +608,12 @@ void pa__done(pa_core *c, pa_module*m) { pa_sink_disconnect(u->sink); pa_sink_unref(u->sink); } - + if (u->source) { pa_source_disconnect(u->source); pa_source_unref(u->source); } - + if (u->hwi != INVALID_HANDLE_VALUE) { waveInReset(u->hwi); waveInClose(u->hwi); @@ -633,6 +633,6 @@ void pa__done(pa_core *c, pa_module*m) { pa_xfree(u->ohdrs); DeleteCriticalSection(&u->crit); - + pa_xfree(u); } diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index 48e95c8ce..5322a71f9 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -107,19 +107,19 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("failed to parse module arguments"); goto fail; } - + m->userdata = u = pa_xmalloc(sizeof(struct userdata)); u->core = c; u->scache_item = pa_xstrdup(pa_modargs_get_value(ma, "sample", "x11-bell")); u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); u->x11_client = NULL; - if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) + if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) goto fail; major = XkbMajorVersion; minor = XkbMinorVersion; - + if (!XkbLibraryVersion(&major, &minor)) { pa_log("XkbLibraryVersion() failed"); goto fail; @@ -140,11 +140,11 @@ int pa__init(pa_core *c, pa_module*m) { XkbChangeEnabledControls(pa_x11_wrapper_get_display(u->x11_wrapper), XkbUseCoreKbd, XkbAudibleBellMask, 0); u->x11_client = pa_x11_client_new(u->x11_wrapper, x11_event_callback, u); - + pa_modargs_free(ma); - + return 0; - + fail: if (ma) pa_modargs_free(ma); diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index f2cace149..b1c17a7c1 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -77,14 +77,14 @@ static int load_key(struct userdata *u, const char*fn) { assert(u); u->auth_cookie_in_property = 0; - + if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { pa_log_debug("using already loaded auth cookie."); pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); u->auth_cookie_in_property = 1; return 0; } - + if (!fn) fn = PA_NATIVE_COOKIE_FILE; @@ -92,7 +92,7 @@ static int load_key(struct userdata *u, const char*fn) { return -1; pa_log_debug("loading cookie from disk."); - + if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) u->auth_cookie_in_property = 1; @@ -121,7 +121,7 @@ int pa__init(pa_core *c, pa_module*m) { if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0) goto fail; - if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) + if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) goto fail; if (!(l = pa_property_get(c, PA_NATIVE_SERVER_PROPERTY_NAME))) @@ -130,10 +130,10 @@ int pa__init(pa_core *c, pa_module*m) { s = pa_strlist_tostring(l); pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER", s); pa_xfree(s); - + if (!pa_get_fqdn(hn, sizeof(hn)) || !pa_get_user_name(un, sizeof(un))) goto fail; - + u->id = pa_sprintf_malloc("%s@%s/%u", un, hn, (unsigned) getpid()); pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID", u->id); @@ -144,10 +144,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SINK", t); pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), hx, sizeof(hx))); - + pa_modargs_free(ma); return 0; - + fail: if (ma) pa_modargs_free(ma); @@ -162,7 +162,7 @@ void pa__done(pa_core *c, pa_module*m) { if (!(u = m->userdata)) return; - + if (u->x11_wrapper) { char t[256]; @@ -178,7 +178,7 @@ void pa__done(pa_core *c, pa_module*m) { XSync(pa_x11_wrapper_get_display(u->x11_wrapper), False); } } - + if (u->x11_wrapper) pa_x11_wrapper_unref(u->x11_wrapper); diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 696d8afeb..10643808b 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -153,7 +153,7 @@ static int publish_service(struct userdata *u, struct service *s) { if (!u->client || avahi_client_get_state(u->client) != AVAHI_CLIENT_S_RUNNING) return 0; - + if ((s->published == PUBLISHED_REAL && s->loaded.valid) || (s->published == PUBLISHED_AUTOLOAD && s->autoload.valid && !s->loaded.valid)) return 0; @@ -161,8 +161,8 @@ static int publish_service(struct userdata *u, struct service *s) { if (s->published != UNPUBLISHED) { avahi_entry_group_reset(s->entry_group); s->published = UNPUBLISHED; - } - + } + if (s->loaded.valid || s->autoload.valid) { pa_namereg_type_t type; @@ -172,26 +172,26 @@ static int publish_service(struct userdata *u, struct service *s) { goto finish; } } - + txt = avahi_string_list_add_pair(txt, "device", s->name); txt = txt_record_server_data(u->core, txt); - + if (s->loaded.valid) { char *description; pa_sample_spec ss; - + get_service_data(u, s, &ss, &description); - + txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate); txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels); txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format)); if (description) txt = avahi_string_list_add_pair(txt, "description", description); - + type = s->loaded.type; } else if (s->autoload.valid) type = s->autoload.type; - + if (avahi_entry_group_add_service_strlst( s->entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, @@ -202,24 +202,24 @@ static int publish_service(struct userdata *u, struct service *s) { NULL, u->port, txt) < 0) { - + pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(u->client))); goto finish; } - + if (avahi_entry_group_commit(s->entry_group) < 0) { pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(u->client))); goto finish; } - + if (s->loaded.valid) s->published = PUBLISHED_REAL; else if (s->autoload.valid) s->published = PUBLISHED_AUTOLOAD; } - + r = 0; - + finish: if (s->published == UNPUBLISHED) { @@ -227,7 +227,7 @@ finish: if (s->entry_group) avahi_entry_group_free(s->entry_group); - + pa_hashmap_remove(u->services, s->name); pa_xfree(s->name); pa_xfree(s->service_name); @@ -236,17 +236,17 @@ finish: if (txt) avahi_string_list_free(txt); - + return r; } static struct service *get_service(struct userdata *u, const char *name, const char *description) { struct service *s; char hn[64]; - + if ((s = pa_hashmap_get(u->services, name))) return s; - + s = pa_xnew(struct service, 1); s->userdata = u; s->entry_group = NULL; @@ -283,7 +283,7 @@ static int publish_sink(struct userdata *u, pa_sink *s) { static int publish_source(struct userdata *u, pa_source *s) { struct service *svc; int ret; - + assert(u && s); svc = get_service(u, s->name, s->description); @@ -295,7 +295,7 @@ static int publish_source(struct userdata *u, pa_source *s) { svc->loaded.index = s->index; pa_dynarray_put(u->source_dynarray, s->index, svc); - + if ((ret = publish_service(u, svc)) < 0) return ret; @@ -306,7 +306,7 @@ static int publish_source(struct userdata *u, pa_source *s) { static int publish_autoload(struct userdata *u, pa_autoload_entry *s) { struct service *svc; int ret; - + assert(u && s); svc = get_service(u, s->name, NULL); @@ -319,7 +319,7 @@ static int publish_autoload(struct userdata *u, pa_autoload_entry *s) { if ((ret = publish_service(u, svc)) < 0) return ret; - + pa_dynarray_put(u->autoload_dynarray, s->index, svc); return ret; } @@ -336,14 +336,14 @@ static int remove_sink(struct userdata *u, uint32_t idx) { svc->loaded.valid = 0; pa_dynarray_put(u->sink_dynarray, idx, NULL); - + return publish_service(u, svc); } static int remove_source(struct userdata *u, uint32_t idx) { struct service *svc; assert(u && idx != PA_INVALID_INDEX); - + if (!(svc = pa_dynarray_get(u->source_dynarray, idx))) return 0; @@ -359,7 +359,7 @@ static int remove_source(struct userdata *u, uint32_t idx) { static int remove_autoload(struct userdata *u, uint32_t idx) { struct service *svc; assert(u && idx != PA_INVALID_INDEX); - + if (!(svc = pa_dynarray_get(u->autoload_dynarray, idx))) return 0; @@ -389,14 +389,14 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (remove_sink(u, idx) < 0) goto fail; } - + break; case PA_SUBSCRIPTION_EVENT_SOURCE: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { pa_source *source; - + if ((source = pa_idxset_get_by_index(c->sources, idx))) { if (publish_source(u, source) < 0) goto fail; @@ -405,13 +405,13 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (remove_source(u, idx) < 0) goto fail; } - + break; case PA_SUBSCRIPTION_EVENT_AUTOLOAD: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { pa_autoload_entry *autoload; - + if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, idx))) { if (publish_autoload(u, autoload) < 0) goto fail; @@ -420,7 +420,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (remove_autoload(u, idx) < 0) goto fail; } - + break; } @@ -453,7 +453,7 @@ static void main_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState s static int publish_main_service(struct userdata *u) { AvahiStringList *txt = NULL; int r = -1; - + if (!u->main_entry_group) { if (!(u->main_entry_group = avahi_entry_group_new(u->client, main_entry_group_callback, u))) { pa_log("avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); @@ -461,7 +461,7 @@ static int publish_main_service(struct userdata *u) { } } else avahi_entry_group_reset(u->main_entry_group); - + txt = txt_record_server_data(u->core, NULL); if (avahi_entry_group_add_service_strlst( @@ -474,18 +474,18 @@ static int publish_main_service(struct userdata *u) { NULL, u->port, txt) < 0) { - + pa_log("avahi_entry_group_add_service_strlst() failed: %s", avahi_strerror(avahi_client_errno(u->client))); goto fail; } - + if (avahi_entry_group_commit(u->main_entry_group) < 0) { pa_log("avahi_entry_group_commit() failed: %s", avahi_strerror(avahi_client_errno(u->client))); goto fail; } r = 0; - + fail: avahi_string_list_free(txt); @@ -498,7 +498,7 @@ static int publish_all_services(struct userdata *u) { pa_autoload_entry *autoload; int r = -1; uint32_t idx; - + assert(u); pa_log_debug("Publishing services in Zeroconf"); @@ -518,9 +518,9 @@ static int publish_all_services(struct userdata *u) { if (publish_main_service(u) < 0) goto fail; - + r = 0; - + fail: return r; } @@ -528,7 +528,7 @@ fail: static void unpublish_all_services(struct userdata *u, int rem) { void *state = NULL; struct service *s; - + assert(u); pa_log_debug("Unpublishing services in Zeroconf"); @@ -538,7 +538,7 @@ static void unpublish_all_services(struct userdata *u, int rem) { if (rem) { avahi_entry_group_free(s->entry_group); s->entry_group = NULL; - } else + } else avahi_entry_group_reset(s->entry_group); } @@ -559,12 +559,12 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda assert(c); u->client = c; - + switch (state) { case AVAHI_CLIENT_S_RUNNING: publish_all_services(u); break; - + case AVAHI_CLIENT_S_COLLISION: unpublish_all_services(u, 0); break; @@ -578,7 +578,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) pa_log("pa_avahi_client_new() failed: %s", avahi_strerror(error)); } - + break; default: ; @@ -607,7 +607,7 @@ int pa__init(pa_core *c, pa_module*m) { u->port = (uint16_t) port; u->avahi_poll = pa_avahi_poll_new(c->mainloop); - + u->services = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); u->sink_dynarray = pa_dynarray_new(); u->source_dynarray = pa_dynarray_new(); @@ -628,15 +628,15 @@ int pa__init(pa_core *c, pa_module*m) { } pa_modargs_free(ma); - + return 0; - + fail: pa__done(c, m); if (ma) pa_modargs_free(ma); - + return -1; } @@ -649,7 +649,7 @@ static void service_free(void *p, void *userdata) { if (s->entry_group) avahi_entry_group_free(s->entry_group); - + pa_xfree(s->service_name); pa_xfree(s->name); pa_xfree(s); @@ -674,14 +674,14 @@ void pa__done(pa_core *c, pa_module*m) { pa_dynarray_free(u->source_dynarray, NULL, NULL); if (u->autoload_dynarray) pa_dynarray_free(u->autoload_dynarray, NULL, NULL); - + if (u->main_entry_group) avahi_entry_group_free(u->main_entry_group); - + if (u->client) avahi_client_free(u->client); - + if (u->avahi_poll) pa_avahi_poll_free(u->avahi_poll); diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 0aaf6971d..d26a0e813 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -48,14 +48,14 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { if(!pcaps) pcaps = ∩︀ - + if (*mode == O_RDWR) { if ((fd = open(device, O_RDWR|O_NDELAY)) >= 0) { int dcaps, *tcaps; ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); tcaps = pcaps ? pcaps : &dcaps; - + if (ioctl(fd, SNDCTL_DSP_GETCAPS, tcaps) < 0) { pa_log("SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); goto fail; @@ -68,7 +68,7 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { close(fd); } - + if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) { if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY)) < 0) { pa_log("open('%s'): %s", device, pa_cstrerror(errno)); @@ -80,17 +80,17 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { pa_log("open('%s'): %s", device, pa_cstrerror(errno)); goto fail; } - } + } success: *pcaps = 0; - + if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { pa_log("SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); goto fail; } - + pa_log_debug("capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s%s", *pcaps & DSP_CAP_BATCH ? " BATCH" : "", #ifdef DSP_CAP_BIND @@ -100,7 +100,7 @@ success: #endif *pcaps & DSP_CAP_COPROC ? " COPROC" : "", *pcaps & DSP_CAP_DUPLEX ? " DUPLEX" : "", -#ifdef DSP_CAP_FREERATE +#ifdef DSP_CAP_FREERATE *pcaps & DSP_CAP_FREERATE ? " FREERATE" : "", #else "", @@ -140,7 +140,7 @@ success: *pcaps & DSP_CAP_TRIGGER ? " TRIGGER" : ""); pa_fd_set_cloexec(fd, 1); - + return fd; fail: @@ -152,7 +152,7 @@ fail: int pa_oss_auto_format(int fd, pa_sample_spec *ss) { int format, channels, speed, reqformat; pa_sample_format_t orig_format; - + static const int format_trans[PA_SAMPLE_MAX] = { [PA_SAMPLE_U8] = AFMT_U8, [PA_SAMPLE_ALAW] = AFMT_A_LAW, @@ -166,7 +166,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { assert(fd >= 0 && ss); orig_format = ss->format; - + reqformat = format = format_trans[ss->format]; if (reqformat == AFMT_QUERY || ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != reqformat) { format = AFMT_S16_NE; @@ -190,7 +190,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { pa_log_warn("device doesn't support sample format %s, changed to %s.", pa_sample_format_to_string(orig_format), pa_sample_format_to_string(ss->format)); - + channels = ss->channels; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) { pa_log("SNDCTL_DSP_CHANNELS: %s", pa_cstrerror(errno)); @@ -229,14 +229,14 @@ static int simple_log2(int v) { if (!v) break; k++; } - + return k; } int pa_oss_set_fragments(int fd, int nfrags, int frag_size) { int arg; arg = ((int) nfrags << 16) | simple_log2(frag_size); - + if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &arg) < 0) { pa_log("SNDCTL_DSP_SETFRAGMENT: %s", pa_cstrerror(errno)); return -1; @@ -252,7 +252,7 @@ static int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvo assert(fd >= 0); assert(ss); assert(volume); - + if (ioctl(fd, mixer, &vol) < 0) return -1; @@ -278,7 +278,7 @@ static int pa_oss_set_volume(int fd, int mixer, const pa_sample_spec *ss, const r = volume->values[1] > PA_VOLUME_NORM ? PA_VOLUME_NORM : volume->values[1]; vol |= ((r*100)/PA_VOLUME_NORM) << 8; } - + if (ioctl(fd, mixer, &vol) < 0) return -1; @@ -321,7 +321,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { n = *e - '0'; else return -1; - + if (!(f = fopen("/dev/sndstat", "r")) && !(f = fopen("/proc/sndstat", "r")) && !(f = fopen("/proc/asound/oss/sndstat", "r"))) { @@ -335,7 +335,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { while (!feof(f)) { char line[64]; int device; - + if (!fgets(line, sizeof(line), f)) break; @@ -348,7 +348,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { if (line[0] == 0) break; - + if (sscanf(line, "%i: ", &device) != 1) continue; @@ -360,7 +360,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { if (pa_endswith(k, " (DUPLEX)")) k[strlen(k)-9] = 0; - + pa_strlcpy(name, k, l); r = 0; break; diff --git a/src/modules/oss-util.h b/src/modules/oss-util.h index 12855f4e2..6a8bf3d28 100644 --- a/src/modules/oss-util.h +++ b/src/modules/oss-util.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/browser.c b/src/pulse/browser.c index dae8e3d51..4b0de0294 100644 --- a/src/pulse/browser.c +++ b/src/pulse/browser.c @@ -2,26 +2,26 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include @@ -53,10 +53,10 @@ struct pa_browser { pa_browser_error_cb_t error_callback; void *error_userdata; - + AvahiClient *client; AvahiServiceBrowser *server_browser, *sink_browser, *source_browser; - + }; static int map_to_opcode(const char *type, int new) { @@ -84,7 +84,7 @@ static void resolve_callback( AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) { - + pa_browser *b = userdata; pa_browse_info i; char ip[256], a[256]; @@ -94,7 +94,7 @@ static void resolve_callback( pa_sample_spec ss; int ss_valid = 0; char *key = NULL, *value = NULL; - + assert(b); memset(&i, 0, sizeof(i)); @@ -102,7 +102,7 @@ static void resolve_callback( if (event != AVAHI_RESOLVER_FOUND) goto fail; - + if (!b->callback) goto fail; @@ -119,10 +119,10 @@ static void resolve_callback( while (txt) { - + if (avahi_string_list_get_pair(txt, &key, &value, NULL) < 0) break; - + if (!strcmp(key, "device")) { device_found = 1; pa_xfree((char*) i.device); @@ -138,11 +138,11 @@ static void resolve_callback( value = NULL; } else if (!strcmp(key, "fqdn")) { size_t l; - + pa_xfree((char*) i.fqdn); i.fqdn = value; value = NULL; - + l = strlen(a); assert(l+1 <= sizeof(a)); strncat(a, " ", sizeof(a)-l-1); @@ -151,7 +151,7 @@ static void resolve_callback( if (pa_atou(value, &cookie) < 0) goto fail; - + i.cookie = &cookie; } else if (!strcmp(key, "description")) { pa_xfree((char*) i.description); @@ -159,13 +159,13 @@ static void resolve_callback( value = NULL; } else if (!strcmp(key, "channels")) { uint32_t ch; - + if (pa_atou(value, &ch) < 0 || ch <= 0 || ch > 255) goto fail; - + ss.channels = (uint8_t) ch; ss_valid |= 1; - + } else if (!strcmp(key, "rate")) { if (pa_atou(value, &ss.rate) < 0) goto fail; @@ -174,7 +174,7 @@ static void resolve_callback( if ((ss.format = pa_parse_sample_format(value)) == PA_SAMPLE_INVALID) goto fail; - + ss_valid |= 4; } @@ -186,7 +186,7 @@ static void resolve_callback( } /* No device txt record was sent for a sink or source service */ - if (opcode != PA_BROWSE_NEW_SERVER && !device_found) + if (opcode != PA_BROWSE_NEW_SERVER && !device_found) goto fail; if (ss_valid == 7) @@ -203,7 +203,7 @@ fail: pa_xfree(key); pa_xfree(value); - + avahi_service_resolver_free(r); } @@ -263,19 +263,19 @@ static void browse_callback( break; } - + case AVAHI_BROWSER_REMOVE: { if (b->callback) { pa_browse_info i; int opcode; - + memset(&i, 0, sizeof(i)); i.name = name; opcode = map_to_opcode(type, 0); assert(opcode >= 0); - + b->callback(b, opcode, &i, b->userdata); } break; @@ -285,7 +285,7 @@ static void browse_callback( handle_failure(b); break; } - + default: ; } @@ -313,7 +313,7 @@ pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t fla if (flags & ~(PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES) || flags == 0) return NULL; - + b = pa_xnew(pa_browser, 1); b->mainloop = mainloop; b->ref = 1; @@ -346,7 +346,7 @@ pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t fla *error_string = avahi_strerror(avahi_client_errno(b->client)); goto fail; } - + if ((flags & PA_BROWSE_FOR_SINKS) && !(b->sink_browser = avahi_service_browser_new( b->client, @@ -378,13 +378,13 @@ pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t fla *error_string = avahi_strerror(avahi_client_errno(b->client)); goto fail; } - + return b; fail: if (b) browser_free(b); - + return NULL; } @@ -403,7 +403,7 @@ static void browser_free(pa_browser *b) { if (b->avahi_poll) pa_avahi_poll_free(b->avahi_poll); - + pa_xfree(b); } diff --git a/src/pulse/browser.h b/src/pulse/browser.h index fc57a4d50..7b9aae8d5 100644 --- a/src/pulse/browser.h +++ b/src/pulse/browser.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -41,7 +41,7 @@ typedef enum pa_browse_opcode { PA_BROWSE_NEW_SINK, /**< New sink found */ PA_BROWSE_NEW_SOURCE, /**< New source found */ PA_BROWSE_REMOVE_SERVER, /**< Server disappeared */ - PA_BROWSE_REMOVE_SINK, /**< Sink disappeared */ + PA_BROWSE_REMOVE_SINK, /**< Sink disappeared */ PA_BROWSE_REMOVE_SOURCE /**< Source disappeared */ } pa_browse_opcode_t; diff --git a/src/pulse/cdecl.h b/src/pulse/cdecl.h index a3ec231cc..09b9b84a5 100644 --- a/src/pulse/cdecl.h +++ b/src/pulse/cdecl.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c index 69b09089c..40655cf50 100644 --- a/src/pulse/channelmap.c +++ b/src/pulse/channelmap.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -35,23 +35,23 @@ const char *const table[] = { [PA_CHANNEL_POSITION_MONO] = "mono", - + [PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center", [PA_CHANNEL_POSITION_FRONT_LEFT] = "front-left", [PA_CHANNEL_POSITION_FRONT_RIGHT] = "front-right", - + [PA_CHANNEL_POSITION_REAR_CENTER] = "rear-center", [PA_CHANNEL_POSITION_REAR_LEFT] = "rear-left", [PA_CHANNEL_POSITION_REAR_RIGHT] = "rear-right", - + [PA_CHANNEL_POSITION_LFE] = "lfe", - + [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "front-left-of-center", [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "front-right-of-center", - + [PA_CHANNEL_POSITION_SIDE_LEFT] = "side-left", [PA_CHANNEL_POSITION_SIDE_RIGHT] = "side-right", - + [PA_CHANNEL_POSITION_AUX0] = "aux0", [PA_CHANNEL_POSITION_AUX1] = "aux1", [PA_CHANNEL_POSITION_AUX2] = "aux2", @@ -86,7 +86,7 @@ const char *const table[] = { [PA_CHANNEL_POSITION_AUX31] = "aux31", [PA_CHANNEL_POSITION_TOP_CENTER] = "top-center", - + [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "top-front-left", [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "top-front-right", [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center", @@ -140,14 +140,14 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p switch (def) { case PA_CHANNEL_MAP_AIFF: - + /* This is somewhat compatible with RFC3551 */ - + switch (channels) { case 1: m->map[0] = PA_CHANNEL_POSITION_MONO; return m; - + case 6: m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; m->map[1] = PA_CHANNEL_POSITION_SIDE_LEFT; @@ -156,31 +156,31 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p m->map[4] = PA_CHANNEL_POSITION_SIDE_RIGHT; m->map[5] = PA_CHANNEL_POSITION_LFE; return m; - + case 5: m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT; m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT; /* Fall through */ - + case 2: m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; return m; - + case 3: m->map[0] = PA_CHANNEL_POSITION_LEFT; m->map[1] = PA_CHANNEL_POSITION_RIGHT; m->map[2] = PA_CHANNEL_POSITION_CENTER; return m; - + case 4: m->map[0] = PA_CHANNEL_POSITION_LEFT; m->map[1] = PA_CHANNEL_POSITION_CENTER; m->map[2] = PA_CHANNEL_POSITION_RIGHT; m->map[3] = PA_CHANNEL_POSITION_LFE; return m; - + default: return NULL; } @@ -191,43 +191,43 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p case 1: m->map[0] = PA_CHANNEL_POSITION_MONO; return m; - + case 8: m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT; m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT; /* Fall through */ - + case 6: m->map[5] = PA_CHANNEL_POSITION_LFE; /* Fall through */ - + case 5: m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER; /* Fall through */ - + case 4: m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT; m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; /* Fall through */ - + case 2: m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; return m; - + default: return NULL; } case PA_CHANNEL_MAP_AUX: { unsigned i; - + if (channels >= PA_CHANNELS_MAX) return NULL; for (i = 0; i < channels; i++) m->map[i] = PA_CHANNEL_POSITION_AUX0 + i; - + return m; } @@ -237,55 +237,55 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p case 1: m->map[0] = PA_CHANNEL_POSITION_MONO; return m; - + case 18: m->map[15] = PA_CHANNEL_POSITION_TOP_REAR_LEFT; m->map[16] = PA_CHANNEL_POSITION_TOP_REAR_CENTER; m->map[17] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT; /* Fall through */ - + case 15: m->map[12] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT; m->map[13] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER; m->map[14] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT; /* Fall through */ - + case 12: m->map[11] = PA_CHANNEL_POSITION_TOP_CENTER; /* Fall through */ - + case 11: m->map[9] = PA_CHANNEL_POSITION_SIDE_LEFT; m->map[10] = PA_CHANNEL_POSITION_SIDE_RIGHT; /* Fall through */ - + case 9: m->map[8] = PA_CHANNEL_POSITION_REAR_CENTER; /* Fall through */ - + case 8: m->map[6] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER; m->map[7] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER; /* Fall through */ - + case 6: m->map[4] = PA_CHANNEL_POSITION_REAR_LEFT; m->map[5] = PA_CHANNEL_POSITION_REAR_RIGHT; /* Fall through */ - + case 4: m->map[3] = PA_CHANNEL_POSITION_LFE; /* Fall through */ - + case 3: m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; /* Fall through */ - + case 2: m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; return m; - + default: return NULL; } @@ -296,12 +296,12 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p case 1: m->map[0] = PA_CHANNEL_POSITION_MONO; return m; - + case 8: m->map[6] = PA_CHANNEL_POSITION_REAR_LEFT; m->map[7] = PA_CHANNEL_POSITION_REAR_RIGHT; /* Fall through */ - + case 6: m->map[4] = PA_CHANNEL_POSITION_SIDE_LEFT; m->map[5] = PA_CHANNEL_POSITION_SIDE_RIGHT; @@ -310,20 +310,20 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p case 4: m->map[3] = PA_CHANNEL_POSITION_LFE; /* Fall through */ - + case 3: m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; /* Fall through */ - + case 2: m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; return m; - + default: return NULL; } - + default: return NULL; @@ -341,13 +341,13 @@ const char* pa_channel_position_to_string(pa_channel_position_t pos) { int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) { unsigned c; - + assert(a); assert(b); if (a->channels != b->channels) return 0; - + for (c = 0; c < a->channels; c++) if (a->map[c] != b->map[c]) return 0; @@ -359,7 +359,7 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) { unsigned channel; int first = 1; char *e; - + assert(s); assert(l > 0); assert(map); @@ -382,7 +382,7 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) { const char *state; pa_channel_map map; char *p; - + assert(rmap); assert(s); @@ -397,14 +397,14 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) { state = NULL; map.channels = 0; - + while ((p = pa_split(s, ",", &state))) { if (map.channels >= PA_CHANNELS_MAX) { pa_xfree(p); return NULL; } - + /* Some special aliases */ if (strcmp(p, "left") == 0) map.map[map.channels++] = PA_CHANNEL_POSITION_LEFT; @@ -416,13 +416,13 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) { map.map[map.channels++] = PA_CHANNEL_POSITION_SUBWOOFER; else { pa_channel_position_t i; - + for (i = 0; i < PA_CHANNEL_POSITION_MAX; i++) if (strcmp(p, table[i]) == 0) { map.map[map.channels++] = i; break; } - + if (i >= PA_CHANNEL_POSITION_MAX) { pa_xfree(p); return NULL; @@ -433,24 +433,24 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) { } finish: - + if (!pa_channel_map_valid(&map)) return NULL; - + *rmap = map; return rmap; } int pa_channel_map_valid(const pa_channel_map *map) { unsigned c; - + assert(map); if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX) return 0; for (c = 0; c < map->channels; c++) { - + if (map->map[c] < 0 ||map->map[c] >= PA_CHANNEL_POSITION_MAX) return 0; diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h index 8a39ade85..203802510 100644 --- a/src/pulse/channelmap.h +++ b/src/pulse/channelmap.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -72,7 +72,7 @@ typedef enum pa_channel_position { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_CENTER, - + PA_CHANNEL_POSITION_FRONT_LEFT = PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT = PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_FRONT_CENTER = PA_CHANNEL_POSITION_CENTER, @@ -80,13 +80,13 @@ typedef enum pa_channel_position { PA_CHANNEL_POSITION_REAR_CENTER, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, - + PA_CHANNEL_POSITION_LFE, PA_CHANNEL_POSITION_SUBWOOFER = PA_CHANNEL_POSITION_LFE, - + PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, - + PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT, @@ -124,7 +124,7 @@ typedef enum pa_channel_position { PA_CHANNEL_POSITION_AUX31, PA_CHANNEL_POSITION_TOP_CENTER, - + PA_CHANNEL_POSITION_TOP_FRONT_LEFT, PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, PA_CHANNEL_POSITION_TOP_FRONT_CENTER, @@ -132,7 +132,7 @@ typedef enum pa_channel_position { PA_CHANNEL_POSITION_TOP_REAR_LEFT, PA_CHANNEL_POSITION_TOP_REAR_RIGHT, PA_CHANNEL_POSITION_TOP_REAR_CENTER, - + PA_CHANNEL_POSITION_MAX } pa_channel_position_t; @@ -143,7 +143,7 @@ typedef enum pa_channel_map_def { PA_CHANNEL_MAP_AUX, /**< Only aux channels */ PA_CHANNEL_MAP_WAVEEX, /**< Microsoft's WAVEFORMATEXTENSIBLE mapping */ PA_CHANNEL_MAP_OSS, /**< The default channel mapping used by OSS as defined in the OSS 4.0 API specs */ - + PA_CHANNEL_MAP_DEFAULT = PA_CHANNEL_MAP_AIFF /**< The default channel map */ } pa_channel_map_def_t; diff --git a/src/pulse/client-conf-x11.c b/src/pulse/client-conf-x11.c index 8cedc48b9..78e190e51 100644 --- a/src/pulse/client-conf-x11.c +++ b/src/pulse/client-conf-x11.c @@ -44,7 +44,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { if (!dname && !getenv("DISPLAY")) goto finish; - + if (!(d = XOpenDisplay(dname))) { pa_log("XOpenDisplay() failed"); goto finish; @@ -89,5 +89,5 @@ finish: XCloseDisplay(d); return ret; - + } diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 5cd7e3ed5..b652a25ba 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -69,11 +69,11 @@ static const pa_client_conf default_conf = { pa_client_conf *pa_client_conf_new(void) { pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); - + c->daemon_binary = pa_xstrdup(PA_BINARY); c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5"); c->cookie_file = pa_xstrdup(PA_NATIVE_COOKIE_FILE); - + return c; } @@ -122,25 +122,25 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { pa_log("WARNING: failed to open configuration file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } - + r = f ? pa_config_parse(fn, f, table, NULL) : 0; if (!r) r = pa_client_conf_load_cookie(c); - + finish: pa_xfree(fn); if (f) fclose(f); - + return r; } int pa_client_conf_env(pa_client_conf *c) { char *e; - + if ((e = getenv(ENV_DEFAULT_SINK))) { pa_xfree(c->default_sink); c->default_sink = pa_xstrdup(e); @@ -155,7 +155,7 @@ int pa_client_conf_env(pa_client_conf *c) { pa_xfree(c->default_server); c->default_server = pa_xstrdup(e); } - + if ((e = getenv(ENV_DAEMON_BINARY))) { pa_xfree(c->daemon_binary); c->daemon_binary = pa_xstrdup(e); @@ -167,7 +167,7 @@ int pa_client_conf_env(pa_client_conf *c) { return pa_client_conf_load_cookie(c); } - + return 0; } diff --git a/src/pulse/context.c b/src/pulse/context.c index a458c6b10..7ef43b306 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -88,11 +88,11 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { static void unlock_autospawn_lock_file(pa_context *c) { assert(c); - + if (c->autospawn_lock_fd >= 0) { char lf[PATH_MAX]; pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); - + pa_unlock_lockfile(lf, c->autospawn_lock_fd); c->autospawn_lock_fd = -1; } @@ -102,10 +102,10 @@ static void context_free(pa_context *c); pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { pa_context *c; - + assert(mainloop); assert(name); - + c = pa_xnew(pa_context, 1); c->ref = 1; c->name = pa_xstrdup(name); @@ -118,7 +118,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { PA_LLIST_HEAD_INIT(pa_stream, c->streams); PA_LLIST_HEAD_INIT(pa_operation, c->operations); - + c->error = PA_OK; c->state = PA_CONTEXT_UNCONNECTED; c->ctag = 0; @@ -138,7 +138,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { c->do_autospawn = 0; #ifndef MSG_NOSIGNAL -#ifdef SIGPIPE +#ifdef SIGPIPE pa_check_signal_is_blocked(SIGPIPE); #endif #endif @@ -183,7 +183,7 @@ static void context_free(pa_context *c) { pa_pstream_close(c->pstream); pa_pstream_unref(c->pstream); } - + if (c->record_streams) pa_dynarray_free(c->record_streams, NULL, NULL); if (c->playback_streams) @@ -196,7 +196,7 @@ static void context_free(pa_context *c) { pa_client_conf_free(c->conf); pa_strlist_free(c->server_list); - + pa_xfree(c->name); pa_xfree(c->server); pa_xfree(c); @@ -205,7 +205,7 @@ static void context_free(pa_context *c) { pa_context* pa_context_ref(pa_context *c) { assert(c); assert(c->ref >= 1); - + c->ref++; return c; } @@ -221,7 +221,7 @@ void pa_context_unref(pa_context *c) { void pa_context_set_state(pa_context *c, pa_context_state_t st) { assert(c); assert(c->ref >= 1); - + if (c->state == st) return; @@ -233,7 +233,7 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) { pa_stream *s; - + s = c->streams ? pa_stream_ref(c->streams) : NULL; while (s) { pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL; @@ -245,13 +245,13 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { if (c->pdispatch) pa_pdispatch_unref(c->pdispatch); c->pdispatch = NULL; - + if (c->pstream) { pa_pstream_close(c->pstream); pa_pstream_unref(c->pstream); } c->pstream = NULL; - + if (c->client) pa_socket_client_unref(c->client); c->client = NULL; @@ -263,7 +263,7 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { void pa_context_fail(pa_context *c, int error) { assert(c); assert(c->ref >= 1); - + pa_context_set_error(c, error); pa_context_set_state(c, PA_CONTEXT_FAILED); } @@ -283,19 +283,19 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { assert(p); assert(c); - + pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { pa_context *c = userdata; - + assert(p); assert(packet); assert(c); pa_context_ref(c); - + if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) pa_context_fail(c, PA_ERR_PROTOCOL); @@ -305,7 +305,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_c static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { pa_context *c = userdata; pa_stream *s; - + assert(p); assert(chunk); assert(chunk->memblock); @@ -321,7 +321,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o pa_memblockq_seek(s->record_memblockq, offset, seek); pa_memblockq_push_align(s->record_memblockq, chunk); - + if (s->read_callback) { size_t l; @@ -339,11 +339,11 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { if (command == PA_COMMAND_ERROR) { assert(t); - + if (pa_tagstruct_getu32(t, &c->error) < 0) { pa_context_fail(c, PA_ERR_PROTOCOL); return -1; - + } } else if (command == PA_COMMAND_TIMEOUT) c->error = PA_ERR_TIMEOUT; @@ -357,15 +357,15 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; - + assert(pd); assert(c); assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME); pa_context_ref(c); - + if (command != PA_COMMAND_REPLY) { - + if (pa_context_handle_error(c, command, t) < 0) pa_context_fail(c, PA_ERR_PROTOCOL); @@ -398,7 +398,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t * user. This is a security measure because otherwise * data private to the user might leak. */ -#ifdef HAVE_CREDS +#ifdef HAVE_CREDS const pa_creds *creds; if ((creds = pa_pdispatch_creds(pd))) if (getuid() == creds->uid) @@ -418,7 +418,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t case PA_CONTEXT_SETTING_NAME : pa_context_set_state(c, PA_CONTEXT_READY); break; - + default: assert(0); } @@ -430,12 +430,12 @@ finish: static void setup_context(pa_context *c, pa_iochannel *io) { pa_tagstruct *t; uint32_t tag; - + assert(c); assert(io); pa_context_ref(c); - + assert(!c->pstream); c->pstream = pa_pstream_new(c->mainloop, io, c->mempool); @@ -462,13 +462,13 @@ static void setup_context(pa_context *c, pa_iochannel *io) { ucred.uid = getuid(); ucred.gid = getgid(); - + pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } #else pa_pstream_send_tagstruct(c->pstream, t); #endif - + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); @@ -487,7 +487,7 @@ static int context_connect_spawn(pa_context *c) { pa_iochannel *io; pa_context_ref(c); - + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { pa_log("socketpair(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); @@ -495,7 +495,7 @@ static int context_connect_spawn(pa_context *c) { } pa_fd_set_cloexec(fds[0], 1); - + pa_socket_low_delay(fds[0]); pa_socket_low_delay(fds[1]); @@ -508,7 +508,7 @@ static int context_connect_spawn(pa_context *c) { if (c->spawn_api.postfork) c->spawn_api.postfork(); - + goto fail; } else if (!pid) { /* Child */ @@ -521,17 +521,17 @@ static int context_connect_spawn(pa_context *c) { /* Not required, since fds[0] has CLOEXEC enabled anyway */ close(fds[0]); - + if (c->spawn_api.atfork) c->spawn_api.atfork(); /* Setup argv */ n = 0; - + argv[n++] = c->conf->daemon_binary; argv[n++] = "--daemonize=yes"; - + snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); argv[n++] = strdup(t); @@ -540,7 +540,7 @@ static int context_connect_spawn(pa_context *c) { if (!(a = pa_split_spaces(c->conf->extra_arguments, &state))) break; - + argv[n++] = a; } @@ -549,7 +549,7 @@ static int context_connect_spawn(pa_context *c) { execv(argv[0], (char * const *) argv); _exit(1); #undef MAX_ARGS - } + } /* Parent */ @@ -557,7 +557,7 @@ static int context_connect_spawn(pa_context *c) { if (c->spawn_api.postfork) c->spawn_api.postfork(); - + if (r < 0) { pa_log("waitpid(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); @@ -570,7 +570,7 @@ static int context_connect_spawn(pa_context *c) { close(fds[1]); c->is_local = 1; - + io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); setup_context(c, io); @@ -598,16 +598,16 @@ fail: static int try_next_connection(pa_context *c) { char *u = NULL; int r = -1; - + assert(c); assert(!c->client); for (;;) { pa_xfree(u); u = NULL; - + c->server_list = pa_strlist_pop(c->server_list, &u); - + if (!u) { #ifndef OS_IS_WIN32 @@ -616,19 +616,19 @@ static int try_next_connection(pa_context *c) { goto finish; } #endif - + pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); goto finish; } - - pa_log_debug("Trying to connect to %s...", u); + + pa_log_debug("Trying to connect to %s...", u); pa_xfree(c->server); c->server = pa_xstrdup(u); if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT))) continue; - + c->is_local = pa_socket_client_is_local(c->client); pa_socket_client_set_callback(c->client, on_connection, c); break; @@ -638,13 +638,13 @@ static int try_next_connection(pa_context *c) { finish: pa_xfree(u); - + return r; } static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) { pa_context *c = userdata; - + assert(client); assert(c); assert(c->state == PA_CONTEXT_CONNECTING); @@ -677,9 +677,9 @@ int pa_context_connect( const char *server, pa_context_flags_t flags, const pa_spawn_api *api) { - + int r = -1; - + assert(c); assert(c->ref >= 1); @@ -693,7 +693,7 @@ int pa_context_connect( pa_context_ref(c); assert(!c->server_list); - + if (server) { if (!(c->server_list = pa_strlist_parse(server))) { pa_context_fail(c, PA_ERR_INVALIDSERVER); @@ -704,7 +704,7 @@ int pa_context_connect( char ufn[PATH_MAX]; /* Prepend in reverse order */ - + if ((d = getenv("DISPLAY"))) { char *e; d = pa_xstrdup(d); @@ -716,7 +716,7 @@ int pa_context_connect( pa_xfree(d); } - + c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost"); c->server_list = pa_strlist_prepend(c->server_list, "tcp4:localhost"); @@ -744,38 +744,38 @@ int pa_context_connect( pa_context_set_state(c, PA_CONTEXT_CONNECTING); r = try_next_connection(c); - + finish: pa_context_unref(c); - + return r; } void pa_context_disconnect(pa_context *c) { assert(c); assert(c->ref >= 1); - + pa_context_set_state(c, PA_CONTEXT_TERMINATED); } pa_context_state_t pa_context_get_state(pa_context *c) { assert(c); assert(c->ref >= 1); - + return c->state; } int pa_context_errno(pa_context *c) { assert(c); assert(c->ref >= 1); - + return c->error; } void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { assert(c); assert(c->ref >= 1); - + c->state_callback = cb; c->state_userdata = userdata; } @@ -807,7 +807,7 @@ static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata) static void set_dispatch_callbacks(pa_operation *o) { int done = 1; - + assert(o); assert(o->ref >= 1); assert(o->context); @@ -816,7 +816,7 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL); pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL); - + if (pa_pdispatch_is_pending(o->context->pdispatch)) { pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o); done = 0; @@ -832,7 +832,7 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_context_notify_cb_t cb = (pa_context_notify_cb_t) o->callback; cb(o->context, o->userdata); } - + pa_operation_done(o); pa_operation_unref(o); } @@ -840,13 +840,13 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { pa_operation *o; - + assert(c); assert(c->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); set_dispatch_callbacks(pa_operation_ref(o)); @@ -856,7 +856,7 @@ pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *u void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; - + assert(pd); assert(o); assert(o->ref >= 1); @@ -907,12 +907,12 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa pa_tagstruct *t; pa_operation *o; uint32_t tag; - + assert(c); assert(c->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); - + o = pa_operation_new(c, NULL, cb, userdata); t = pa_tagstruct_command(c, command, &tag); @@ -926,7 +926,7 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_co pa_tagstruct *t; pa_operation *o; uint32_t tag; - + assert(c); assert(c->ref >= 1); @@ -951,7 +951,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ assert(c->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag); @@ -964,7 +964,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ int pa_context_is_local(pa_context *c) { assert(c); - + return c->is_local; } @@ -978,7 +978,7 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su assert(name); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); @@ -999,12 +999,12 @@ const char* pa_context_get_server(pa_context *c) { if (!c->server) return NULL; - + if (*c->server == '{') { char *e = strchr(c->server+1, '}'); return e ? e+1 : c->server; } - + return c->server; } @@ -1024,7 +1024,7 @@ pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *ta assert(c); assert(tag); - + t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, command); pa_tagstruct_putu32(t, *tag = c->ctag++); diff --git a/src/pulse/context.h b/src/pulse/context.h index 661ff6170..048ed17f4 100644 --- a/src/pulse/context.h +++ b/src/pulse/context.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -50,7 +50,7 @@ * The abstraction is represented as a number of function pointers in the * pa_mainloop_api structure. * - * To actually be able to use these functions, an implementation needs to + * To actually be able to use these functions, an implementation needs to * be coupled to the abstraction. There are three of these shipped with * PulseAudio, but any other can be used with a minimal ammount of work, * provided it supports the three basic events listed above. @@ -76,7 +76,7 @@ * and decrease their reference counts. Whenever an object's reference * count reaches zero, that object gets destroy and any resources it uses * get freed. - * + * * The benefit of this design is that an application need not worry about * whether or not it needs to keep an object around in case the library is * using it internally. If it is, then it has made sure it has its own diff --git a/src/pulse/def.h b/src/pulse/def.h index a22e3c190..fb04de506 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -69,7 +69,7 @@ typedef enum pa_context_flags { PA_CONTEXT_NOAUTOSPAWN = 1 /**< Disabled autospawning of the PulseAudio daemon if required */ } pa_context_flags_t; -/** The direction of a pa_stream object */ +/** The direction of a pa_stream object */ typedef enum pa_stream_direction { PA_STREAM_NODIRECTION, /**< Invalid direction */ PA_STREAM_PLAYBACK, /**< Playback stream */ @@ -149,7 +149,7 @@ enum { PA_ERR_EXIST, /**< Entity exists */ PA_ERR_NOENTITY, /**< No such entity */ PA_ERR_CONNECTIONREFUSED, /**< Connection refused */ - PA_ERR_PROTOCOL, /**< Protocol error */ + PA_ERR_PROTOCOL, /**< Protocol error */ PA_ERR_TIMEOUT, /**< Timeout */ PA_ERR_AUTHKEY, /**< No authorization key */ PA_ERR_INTERNAL, /**< Internal error */ @@ -207,7 +207,7 @@ typedef enum pa_subscription_event_type { * total output latency a sample that is written with * pa_stream_write() takes to be played may be estimated by * sink_usec+buffer_usec+transport_usec. (where buffer_usec is defined - * as pa_bytes_to_usec(write_index-read_index)) The output buffer + * as pa_bytes_to_usec(write_index-read_index)) The output buffer * which buffer_usec relates to may be manipulated freely (with * pa_stream_write()'s seek argument, pa_stream_flush() and friends), * the buffers sink_usec and source_usec relate to are first-in @@ -256,7 +256,7 @@ typedef struct pa_timing_info { * flush request that corrupted it has * been issued in the time since this * latency info was current. \since 0.8 */ - + int64_t read_index; /**< Current read index into the * playback buffer in bytes. Think twice before * using this for seeking purposes: it @@ -288,7 +288,7 @@ typedef struct pa_spawn_api { /** Seek type for pa_stream_write(). \since 0.8*/ typedef enum pa_seek_mode { PA_SEEK_RELATIVE = 0, /**< Seek relatively to the write index */ - PA_SEEK_ABSOLUTE = 1, /**< Seek relatively to the start of the buffer queue */ + PA_SEEK_ABSOLUTE = 1, /**< Seek relatively to the start of the buffer queue */ PA_SEEK_RELATIVE_ON_READ = 2, /**< Seek relatively to the read index. */ PA_SEEK_RELATIVE_END = 3 /**< Seek relatively to the current end of the buffer queue. */ } pa_seek_mode_t; diff --git a/src/pulse/error.c b/src/pulse/error.c index 7bd31ead9..3b9a60a4c 100644 --- a/src/pulse/error.c +++ b/src/pulse/error.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/error.h b/src/pulse/error.h index bfce023ca..c96349a61 100644 --- a/src/pulse/error.h +++ b/src/pulse/error.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/glib-mainloop.c b/src/pulse/glib-mainloop.c index 201b6e236..1669acddb 100644 --- a/src/pulse/glib-mainloop.c +++ b/src/pulse/glib-mainloop.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -69,7 +69,7 @@ struct pa_defer_event { int dead; int enabled; - + pa_defer_event_cb_t callback; void *userdata; pa_defer_event_destroy_cb_t destroy_callback; @@ -79,7 +79,7 @@ struct pa_defer_event { struct pa_glib_mainloop { GSource source; - + pa_mainloop_api api; GMainContext *context; @@ -102,7 +102,7 @@ static void cleanup_io_events(pa_glib_mainloop *g, int force) { if (!force && g->io_events_please_scan <= 0) break; - + if (force || e->dead) { PA_LLIST_REMOVE(pa_io_event, g->io_events, e); @@ -110,13 +110,13 @@ static void cleanup_io_events(pa_glib_mainloop *g, int force) { g_assert(g->io_events_please_scan > 0); g->io_events_please_scan--; } - + if (e->poll_fd_added) g_source_remove_poll(&g->source, &e->poll_fd); - + if (e->destroy_callback) e->destroy_callback(&g->api, e, e->userdata); - + pa_xfree(e); } @@ -135,7 +135,7 @@ static void cleanup_time_events(pa_glib_mainloop *g, int force) { if (!force && g->time_events_please_scan <= 0) break; - + if (force || e->dead) { PA_LLIST_REMOVE(pa_time_event, g->time_events, e); @@ -148,10 +148,10 @@ static void cleanup_time_events(pa_glib_mainloop *g, int force) { g_assert(g->n_enabled_time_events > 0); g->n_enabled_time_events--; } - + if (e->destroy_callback) e->destroy_callback(&g->api, e, e->userdata); - + pa_xfree(e); } @@ -170,7 +170,7 @@ static void cleanup_defer_events(pa_glib_mainloop *g, int force) { if (!force && g->defer_events_please_scan <= 0) break; - + if (force || e->dead) { PA_LLIST_REMOVE(pa_defer_event, g->defer_events, e); @@ -183,10 +183,10 @@ static void cleanup_defer_events(pa_glib_mainloop *g, int force) { g_assert(g->n_enabled_defer_events > 0); g->n_enabled_defer_events--; } - + if (e->destroy_callback) e->destroy_callback(&g->api, e, e->userdata); - + pa_xfree(e); } @@ -218,7 +218,7 @@ static pa_io_event* glib_io_new( pa_io_event_flags_t f, pa_io_event_cb_t cb, void *userdata) { - + pa_io_event *e; pa_glib_mainloop *g; @@ -226,7 +226,7 @@ static pa_io_event* glib_io_new( g_assert(m->userdata); g_assert(fd >= 0); g_assert(cb); - + g = m->userdata; e = pa_xnew(pa_io_event, 1); @@ -236,7 +236,7 @@ static pa_io_event* glib_io_new( e->poll_fd.fd = fd; e->poll_fd.events = map_flags_to_glib(f); e->poll_fd.revents = 0; - + e->callback = cb; e->userdata = userdata; e->destroy_callback = NULL; @@ -245,7 +245,7 @@ static pa_io_event* glib_io_new( g_source_add_poll(&g->source, &e->poll_fd); e->poll_fd_added = 1; - + return e; } @@ -272,7 +272,7 @@ static void glib_io_free(pa_io_event*e) { static void glib_io_set_destroy(pa_io_event*e, pa_io_event_destroy_cb_t cb) { g_assert(e); g_assert(!e->dead); - + e->destroy_callback = cb; } @@ -283,14 +283,14 @@ static pa_time_event* glib_time_new( const struct timeval *tv, pa_time_event_cb_t cb, void *userdata) { - + pa_glib_mainloop *g; pa_time_event *e; - + g_assert(m); g_assert(m->userdata); g_assert(cb); - + g = m->userdata; e = pa_xnew(pa_time_event, 1); @@ -308,13 +308,13 @@ static pa_time_event* glib_time_new( g->cached_next_time_event = e; } } - + e->callback = cb; e->userdata = userdata; e->destroy_callback = NULL; PA_LLIST_PREPEND(pa_time_event, g->time_events, e); - + return e; } @@ -328,12 +328,12 @@ static void glib_time_restart(pa_time_event*e, const struct timeval *tv) { } else if (!e->enabled && tv) e->mainloop->n_enabled_time_events++; - if ((e->enabled = !!tv)) + if ((e->enabled = !!tv)) e->timeval = *tv; if (e->mainloop->cached_next_time_event && e->enabled) { g_assert(e->mainloop->cached_next_time_event->enabled); - + if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0) e->mainloop->cached_next_time_event = e; } else if (e->mainloop->cached_next_time_event == e) @@ -357,7 +357,7 @@ static void glib_time_free(pa_time_event *e) { static void glib_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb) { g_assert(e); g_assert(!e->dead); - + e->destroy_callback = cb; } @@ -367,27 +367,27 @@ static pa_defer_event* glib_defer_new( pa_mainloop_api*m, pa_defer_event_cb_t cb, void *userdata) { - + pa_defer_event *e; pa_glib_mainloop *g; g_assert(m); g_assert(m->userdata); g_assert(cb); - + g = m->userdata; - + e = pa_xnew(pa_defer_event, 1); e->mainloop = g; e->dead = 0; e->enabled = 1; g->n_enabled_defer_events++; - + e->callback = cb; e->userdata = userdata; e->destroy_callback = NULL; - + PA_LLIST_PREPEND(pa_defer_event, g->defer_events, e); return e; } @@ -430,7 +430,7 @@ static void glib_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_ static void glib_quit(pa_mainloop_api*a, PA_GCC_UNUSED int retval) { g_warning("quit() ignored"); - + /* NOOP */ } @@ -440,7 +440,7 @@ static pa_time_event* find_next_time_event(pa_glib_mainloop *g) { if (g->cached_next_time_event) return g->cached_next_time_event; - + for (t = g->time_events; t; t = t->next) { if (t->dead || !t->enabled) @@ -461,7 +461,7 @@ static pa_time_event* find_next_time_event(pa_glib_mainloop *g) { static void scan_dead(pa_glib_mainloop *g) { g_assert(g); - + if (g->io_events_please_scan) cleanup_io_events(g, 0); @@ -499,7 +499,7 @@ static gboolean prepare_func(GSource *source, gint *timeout) { if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) { *timeout = 0; return TRUE; - } + } usec = pa_timeval_diff(&t->timeval, &tvnow); *timeout = (gint) (usec / 1000); } else @@ -519,10 +519,10 @@ static gboolean check_func(GSource *source) { pa_time_event *t; GTimeVal now; struct timeval tvnow; - + t = find_next_time_event(g); g_assert(t); - + g_source_get_current_time(source, &now); tvnow.tv_sec = now.tv_sec; tvnow.tv_usec = now.tv_usec; @@ -555,7 +555,7 @@ static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callbac } g_assert(d); - + d->callback(&g->api, d, d->userdata); return TRUE; } @@ -567,7 +567,7 @@ static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callbac t = find_next_time_event(g); g_assert(t); - + g_source_get_current_time(source, &now); tvnow.tv_sec = now.tv_sec; tvnow.tv_usec = now.tv_usec; @@ -576,7 +576,7 @@ static gboolean dispatch_func(GSource *source, PA_GCC_UNUSED GSourceFunc callbac /* Disable time event */ glib_time_restart(t, NULL); - + t->callback(&g->api, t, &t->timeval, t->userdata); return TRUE; } @@ -604,12 +604,12 @@ static const pa_mainloop_api vtable = { .time_restart = glib_time_restart, .time_free = glib_time_free, .time_set_destroy = glib_time_set_destroy, - + .defer_new = glib_defer_new, .defer_enable = glib_defer_enable, .defer_free = glib_defer_free, .defer_set_destroy = glib_defer_set_destroy, - + .quit = glib_quit, }; @@ -624,10 +624,10 @@ pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { NULL, NULL }; - + g = (pa_glib_mainloop*) g_source_new(&source_funcs, sizeof(pa_glib_mainloop)); g_main_context_ref(g->context = c ? c : g_main_context_default()); - + g->api = vtable; g->api.userdata = g; @@ -639,10 +639,10 @@ pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) { g->io_events_please_scan = g->time_events_please_scan = g->defer_events_please_scan = 0; g->cached_next_time_event = NULL; - + g_source_attach(&g->source, g->context); g_source_set_can_recurse(&g->source, FALSE); - + return g; } @@ -660,6 +660,6 @@ void pa_glib_mainloop_free(pa_glib_mainloop* g) { pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) { g_assert(g); - + return &g->api; } diff --git a/src/pulse/glib-mainloop.h b/src/pulse/glib-mainloop.h index af7cc0e90..5f8093a1a 100644 --- a/src/pulse/glib-mainloop.h +++ b/src/pulse/glib-mainloop.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 4eef4b4ad..8cdbf84a1 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -45,7 +45,7 @@ struct pa_context { int ref; - + char *name; pa_mainloop_api* mainloop; @@ -75,7 +75,7 @@ struct pa_context { int do_autospawn; int autospawn_lock_fd; pa_spawn_api spawn_api; - + pa_strlist *server_list; char *server; @@ -109,7 +109,7 @@ struct pa_stream { uint32_t device_index; pa_stream_direction_t direction; pa_stream_state_t state; - + uint32_t requested_bytes; pa_memchunk peek_memchunk; @@ -120,10 +120,10 @@ struct pa_stream { /* Store latest latency info */ pa_timing_info timing_info; int timing_info_valid; - + /* Use to make sure that time advances monotonically */ pa_usec_t previous_time; - + /* time updates with tags older than these are invalid */ uint32_t write_index_not_before; uint32_t read_index_not_before; @@ -135,7 +135,7 @@ struct pa_stream { /* Latency interpolation stuff */ pa_time_event *auto_timing_update_event; int auto_timing_update_requested; - + pa_usec_t cached_time; int cached_time_valid; @@ -160,7 +160,7 @@ struct pa_operation { int ref; pa_context *context; pa_stream *stream; - + PA_LLIST_FIELDS(pa_operation); pa_operation_state_t state; diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c index b926e4e4d..5a2c8fb67 100644 --- a/src/pulse/introspect.c +++ b/src/pulse/introspect.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -39,7 +39,7 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; pa_stat_info i, *p = &i; - + assert(pd); assert(o); assert(o->ref >= 1); @@ -81,11 +81,11 @@ pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdat static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; pa_server_info i, *p = &i; - + assert(pd); assert(o); assert(o->ref >= 1); - + if (!o->context) goto finish; @@ -107,7 +107,7 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } - + if (o->callback) { pa_server_info_cb_t cb = (pa_server_info_cb_t) o->callback; cb(o->context, p, o->userdata); @@ -127,14 +127,14 @@ pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int eol = 1; - + assert(pd); assert(o); assert(o->ref >= 1); if (!o->context) goto finish; - + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; @@ -142,10 +142,10 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P eol = -1; } else { uint32_t flags; - + while (!pa_tagstruct_eof(t)) { pa_sink_info i; - + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_gets(t, &i.description) < 0 || @@ -159,7 +159,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P pa_tagstruct_get_usec(t, &i.latency) < 0 || pa_tagstruct_gets(t, &i.driver) < 0 || pa_tagstruct_getu32(t, &flags) < 0) { - + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -172,7 +172,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P } } } - + if (o->callback) { pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback; cb(o->context, NULL, eol, o->userdata); @@ -191,7 +191,7 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_ pa_tagstruct *t; pa_operation *o; uint32_t tag; - + assert(c); assert(c->ref >= 1); assert(cb); @@ -213,7 +213,7 @@ pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_tagstruct *t; pa_operation *o; uint32_t tag; - + assert(c); assert(c->ref >= 1); assert(cb); @@ -251,11 +251,11 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, eol = -1; } else { - + while (!pa_tagstruct_eof(t)) { pa_source_info i; uint32_t flags; - + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_gets(t, &i.description) < 0 || @@ -269,7 +269,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_get_usec(t, &i.latency) < 0 || pa_tagstruct_gets(t, &i.driver) < 0 || pa_tagstruct_getu32(t, &flags) < 0) { - + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -282,7 +282,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, } } } - + if (o->callback) { pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback; cb(o->context, NULL, eol, o->userdata); @@ -309,7 +309,7 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, p PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - + t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_INFO, &tag); pa_tagstruct_putu32(t, idx); pa_tagstruct_puts(t, NULL); @@ -361,10 +361,10 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, eol = -1; } else { - + while (!pa_tagstruct_eof(t)) { pa_client_info i; - + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || @@ -379,7 +379,7 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, } } } - + if (o->callback) { pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback; cb(o->context, NULL, eol, o->userdata); @@ -428,17 +428,17 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, if (!o->context) goto finish; - + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; eol = -1; } else { - + while (!pa_tagstruct_eof(t)) { pa_module_info i; - + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_gets(t, &i.argument) < 0 || @@ -454,7 +454,7 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, } } } - + if (o->callback) { pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback; cb(o->context, NULL, eol, o->userdata); @@ -476,7 +476,7 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_ PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_GET_MODULE_INFO, &tag); @@ -503,17 +503,17 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm if (!o->context) goto finish; - + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; eol = -1; } else { - + while (!pa_tagstruct_eof(t)) { pa_sink_input_info i; - + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || @@ -526,7 +526,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm pa_tagstruct_get_usec(t, &i.sink_usec) < 0 || pa_tagstruct_gets(t, &i.resample_method) < 0 || pa_tagstruct_gets(t, &i.driver) < 0) { - + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -537,7 +537,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm } } } - + if (o->callback) { pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback; cb(o->context, NULL, eol, o->userdata); @@ -559,7 +559,7 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sin PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INPUT_INFO, &tag); @@ -593,10 +593,10 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c eol = -1; } else { - + while (!pa_tagstruct_eof(t)) { pa_source_output_info i; - + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || @@ -608,7 +608,7 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c pa_tagstruct_get_usec(t, &i.source_usec) < 0 || pa_tagstruct_gets(t, &i.resample_method) < 0 || pa_tagstruct_gets(t, &i.driver) < 0) { - + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -619,7 +619,7 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c } } } - + if (o->callback) { pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback; cb(o->context, NULL, eol, o->userdata); @@ -641,7 +641,7 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_ PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO, &tag); @@ -695,7 +695,7 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_VOLUME, &tag); @@ -741,7 +741,7 @@ pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_MUTE, &tag); @@ -766,7 +766,7 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_VOLUME, &tag); @@ -815,7 +815,7 @@ pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *na PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_VOLUME, &tag); @@ -861,7 +861,7 @@ pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_MUTE, &tag); @@ -886,17 +886,17 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, if (!o->context) goto finish; - + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; eol = -1; } else { - + while (!pa_tagstruct_eof(t)) { pa_sample_info i; - + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_get_cvolume(t, &i.volume) < 0 || @@ -906,7 +906,7 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_getu32(t, &i.bytes) < 0 || pa_tagstruct_get_boolean(t, &i.lazy) < 0 || pa_tagstruct_gets(t, &i.filename) < 0) { - + pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -917,7 +917,7 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, } } } - + if (o->callback) { pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback; cb(o->context, NULL, eol, o->userdata); @@ -932,7 +932,7 @@ pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name pa_tagstruct *t; pa_operation *o; uint32_t tag; - + assert(c); assert(c->ref >= 1); assert(cb); @@ -1002,7 +1002,7 @@ static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) { return command_kill(c, PA_COMMAND_KILL_CLIENT, idx, cb, userdata); } - + pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) { return command_kill(c, PA_COMMAND_KILL_SINK_INPUT, idx, cb, userdata); } @@ -1021,7 +1021,7 @@ static void context_index_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN if (!o->context) goto finish; - + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; @@ -1048,7 +1048,7 @@ pa_operation* pa_context_load_module(pa_context *c, const char*name, const char pa_operation *o; pa_tagstruct *t; uint32_t tag; - + assert(c); assert(c->ref >= 1); @@ -1089,10 +1089,10 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman eol = -1; } else { - + while (!pa_tagstruct_eof(t)) { pa_autoload_info i; - + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.type) < 0 || @@ -1108,7 +1108,7 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman } } } - + if (o->callback) { pa_autoload_info_cb_t cb = (pa_autoload_info_cb_t) o->callback; cb(o->context, NULL, eol, o->userdata); @@ -1147,7 +1147,7 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_tagstruct *t; pa_operation *o; uint32_t tag; - + assert(c); assert(c->ref >= 1); assert(cb); @@ -1176,7 +1176,7 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo assert(c); assert(c->ref >= 1); - + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); PA_CHECK_VALIDITY_RETURN_NULL(c, type == PA_AUTOLOAD_SINK || type == PA_AUTOLOAD_SOURCE, PA_ERR_INVALID); @@ -1202,7 +1202,7 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name assert(c); assert(c->ref >= 1); - + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); PA_CHECK_VALIDITY_RETURN_NULL(c, type == PA_AUTOLOAD_SINK || type == PA_AUTOLOAD_SOURCE, PA_ERR_INVALID); diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h index 28d22cd7e..6de7bc714 100644 --- a/src/pulse/introspect.h +++ b/src/pulse/introspect.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -206,7 +206,7 @@ PA_C_DECL_BEGIN /** Stores information about sinks */ typedef struct pa_sink_info { const char *name; /**< Name of the sink */ - uint32_t index; /**< Index of the sink */ + uint32_t index; /**< Index of the sink */ const char *description; /**< Description of this sink */ pa_sample_spec sample_spec; /**< Sample spec of this sink */ pa_channel_map channel_map; /**< Channel map \since 0.8 */ @@ -233,7 +233,7 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t id, pa_s pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata); /** Stores information about sources */ -typedef struct pa_source_info { +typedef struct pa_source_info { const char *name ; /**< Name of the source */ uint32_t index; /**< Index of the source */ const char *description; /**< Description of this source */ @@ -316,7 +316,7 @@ pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t /** Stores information about sink inputs */ typedef struct pa_sink_input_info { - uint32_t index; /**< Index of the sink input */ + uint32_t index; /**< Index of the sink input */ const char *name; /**< Name of the sink input */ uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */ uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */ @@ -341,11 +341,11 @@ pa_operation* pa_context_get_sink_input_info_list(pa_context *c, pa_sink_input_i /** Stores information about source outputs */ typedef struct pa_source_output_info { - uint32_t index; /**< Index of the sink input */ + uint32_t index; /**< Index of the sink input */ const char *name; /**< Name of the sink input */ - uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */ - uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */ - uint32_t source; /**< Index of the connected source */ + uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */ + uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */ + uint32_t source; /**< Index of the connected source */ pa_sample_spec sample_spec; /**< The sample specification of the source output */ pa_channel_map channel_map; /**< Channel map */ pa_usec_t buffer_usec; /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */ @@ -396,7 +396,7 @@ typedef struct pa_stat_info { uint32_t memblock_total_size; /**< Currentl total size of allocated memory blocks */ uint32_t memblock_allocated; /**< Allocated memory blocks during the whole lifetime of the daemon */ uint32_t memblock_allocated_size; /**< Total size of all memory blocks allocated during the whole lifetime of the daemon */ - uint32_t scache_size; /**< Total size of all sample cache entries. \since 0.4 */ + uint32_t scache_size; /**< Total size of all sample cache entries. \since 0.4 */ } pa_stat_info; /** Callback prototype for pa_context_stat() */ @@ -432,7 +432,7 @@ pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t /** Kill a client. \since 0.5 */ pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata); - + /** Kill a sink input. \since 0.5 */ pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata); diff --git a/src/pulse/mainloop-api.c b/src/pulse/mainloop-api.c index 2e20b446a..bf3ef37ed 100644 --- a/src/pulse/mainloop-api.c +++ b/src/pulse/mainloop-api.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/mainloop-api.h b/src/pulse/mainloop-api.h index 7b7075ae2..b88bf125e 100644 --- a/src/pulse/mainloop-api.h +++ b/src/pulse/mainloop-api.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -28,7 +28,7 @@ #include /** \file - * + * * Main loop abstraction layer. Both the PulseAudio core and the * PulseAudio client library use a main loop abstraction layer. Due to * this it is possible to embed PulseAudio into other diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c index d651462b0..4dd427966 100644 --- a/src/pulse/mainloop-signal.c +++ b/src/pulse/mainloop-signal.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -73,7 +73,7 @@ static void signal_handler(int sig) { static void dispatch(pa_mainloop_api*a, int sig) { pa_signal_event*s; - for (s = signals; s; s = s->next) + for (s = signals; s; s = s->next) if (s->sig == sig) { assert(s->callback); s->callback(a, s, sig, s->userdata); @@ -93,7 +93,7 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags pa_log("read(): %s", pa_cstrerror(errno)); return; } - + if (r != sizeof(sig)) { pa_log("short read()"); return; @@ -129,7 +129,7 @@ void pa_signal_done(void) { while (signals) pa_signal_free(signals); - + api->io_free(io_event); io_event = NULL; @@ -148,11 +148,11 @@ pa_signal_event* pa_signal_new(int sig, void (*_callback) (pa_mainloop_api *api, #endif assert(sig > 0 && _callback); - + for (e = signals; e; e = e->next) if (e->sig == sig) goto fail; - + e = pa_xmalloc(sizeof(pa_signal_event)); e->sig = sig; e->callback = _callback; @@ -164,7 +164,7 @@ pa_signal_event* pa_signal_new(int sig, void (*_callback) (pa_mainloop_api *api, sa.sa_handler = signal_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - + if (sigaction(sig, &sa, &e->saved_sigaction) < 0) #else if ((e->saved_handler = signal(sig, signal_handler)) == SIG_ERR) @@ -200,7 +200,7 @@ void pa_signal_free(pa_signal_event *e) { if (e->destroy_callback) e->destroy_callback(api, e, e->userdata); - + pa_xfree(e); } diff --git a/src/pulse/mainloop-signal.h b/src/pulse/mainloop-signal.h index 0721c1f5d..e991cf1cf 100644 --- a/src/pulse/mainloop-signal.h +++ b/src/pulse/mainloop-signal.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index f7b155373..04461b307 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -57,11 +57,11 @@ struct pa_io_event { pa_mainloop *mainloop; int dead; - + int fd; pa_io_event_flags_t events; struct pollfd *pollfd; - + pa_io_event_cb_t callback; void *userdata; pa_io_event_destroy_cb_t destroy_callback; @@ -154,7 +154,7 @@ static pa_io_event* mainloop_io_new( pa_io_event_flags_t events, pa_io_event_cb_t callback, void *userdata) { - + pa_mainloop *m; pa_io_event *e; @@ -162,7 +162,7 @@ static pa_io_event* mainloop_io_new( assert(a->userdata); assert(fd >= 0); assert(callback); - + m = a->userdata; assert(a == &m->api); @@ -173,7 +173,7 @@ static pa_io_event* mainloop_io_new( e->fd = fd; e->events = events; e->pollfd = NULL; - + e->callback = callback; e->userdata = userdata; e->destroy_callback = NULL; @@ -213,7 +213,7 @@ static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { if (e->events == events) return; - + e->events = events; if (e->pollfd) @@ -239,7 +239,7 @@ static void mainloop_io_free(pa_io_event *e) { static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) { assert(e); - + e->destroy_callback = callback; } @@ -255,7 +255,7 @@ static pa_defer_event* mainloop_defer_new( assert(a); assert(a->userdata); assert(callback); - + m = a->userdata; assert(a == &m->api); @@ -265,7 +265,7 @@ static pa_defer_event* mainloop_defer_new( e->enabled = 1; m->n_enabled_defer_events++; - + e->callback = callback; e->userdata = userdata; e->destroy_callback = NULL; @@ -288,7 +288,7 @@ static void mainloop_defer_enable(pa_defer_event *e, int b) { e->mainloop->n_enabled_defer_events++; pa_mainloop_wakeup(e->mainloop); } - + e->enabled = b; } @@ -318,14 +318,14 @@ static pa_time_event* mainloop_time_new( const struct timeval *tv, pa_time_event_cb_t callback, void *userdata) { - + pa_mainloop *m; pa_time_event *e; assert(a); assert(a->userdata); assert(callback); - + m = a->userdata; assert(a == &m->api); @@ -354,7 +354,7 @@ static pa_time_event* mainloop_time_new( if (e->enabled) pa_mainloop_wakeup(m); - + return e; } @@ -375,7 +375,7 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { if (e->mainloop->cached_next_time_event && e->enabled) { assert(e->mainloop->cached_next_time_event->enabled); - + if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0) e->mainloop->cached_next_time_event = e; } else if (e->mainloop->cached_next_time_event == e) @@ -396,7 +396,7 @@ static void mainloop_time_free(pa_time_event *e) { if (e->mainloop->cached_next_time_event == e) e->mainloop->cached_next_time_event = NULL; - + /* no wakeup needed here. Think about it! */ } @@ -411,7 +411,7 @@ static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb static void mainloop_quit(pa_mainloop_api*a, int retval) { pa_mainloop *m; - + assert(a); assert(a->userdata); m = a->userdata; @@ -419,7 +419,7 @@ static void mainloop_quit(pa_mainloop_api*a, int retval) { pa_mainloop_quit(m, retval); } - + static const pa_mainloop_api vtable = { .userdata = NULL, @@ -432,12 +432,12 @@ static const pa_mainloop_api vtable = { .time_restart = mainloop_time_restart, .time_free = mainloop_time_free, .time_set_destroy = mainloop_time_set_destroy, - + .defer_new = mainloop_defer_new, .defer_enable = mainloop_defer_enable, .defer_free = mainloop_defer_free, .defer_set_destroy = mainloop_defer_set_destroy, - + .quit = mainloop_quit, }; @@ -466,7 +466,7 @@ pa_mainloop *pa_mainloop_new(void) { m->cached_next_time_event = NULL; m->prepared_timeout = 0; - + m->pollfds = NULL; m->max_pollfds = m->n_pollfds = 0; m->rebuild_pollfds = 1; @@ -481,7 +481,7 @@ pa_mainloop *pa_mainloop_new(void) { m->poll_func = NULL; m->poll_func_userdata = NULL; m->poll_func_ret = -1; - + return m; } @@ -494,7 +494,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) { if (!force && m->io_events_please_scan <= 0) break; - + if (force || e->dead) { PA_LLIST_REMOVE(pa_io_event, m->io_events, e); @@ -502,10 +502,10 @@ static void cleanup_io_events(pa_mainloop *m, int force) { assert(m->io_events_please_scan > 0); m->io_events_please_scan--; } - + if (e->destroy_callback) e->destroy_callback(&m->api, e, e->userdata); - + pa_xfree(e); m->rebuild_pollfds = 1; @@ -526,7 +526,7 @@ static void cleanup_time_events(pa_mainloop *m, int force) { if (!force && m->time_events_please_scan <= 0) break; - + if (force || e->dead) { PA_LLIST_REMOVE(pa_time_event, m->time_events, e); @@ -539,10 +539,10 @@ static void cleanup_time_events(pa_mainloop *m, int force) { assert(m->n_enabled_time_events > 0); m->n_enabled_time_events--; } - + if (e->destroy_callback) e->destroy_callback(&m->api, e, e->userdata); - + pa_xfree(e); } @@ -561,7 +561,7 @@ static void cleanup_defer_events(pa_mainloop *m, int force) { if (!force && m->defer_events_please_scan <= 0) break; - + if (force || e->dead) { PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e); @@ -574,10 +574,10 @@ static void cleanup_defer_events(pa_mainloop *m, int force) { assert(m->n_enabled_defer_events > 0); m->n_enabled_defer_events--; } - + if (e->destroy_callback) e->destroy_callback(&m->api, e, e->userdata); - + pa_xfree(e); } @@ -664,11 +664,11 @@ static int dispatch_pollfds(pa_mainloop *m) { int r = 0, k; assert(m->poll_func_ret > 0); - + for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) { if (e->dead || !e->pollfd || !e->pollfd->revents) continue; - + assert(e->pollfd->fd == e->fd && e->callback); e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata); e->pollfd->revents = 0; @@ -690,7 +690,7 @@ static int dispatch_defer(pa_mainloop *m) { for (e = m->defer_events; e && !m->quit; e = e->next) { if (e->dead || !e->enabled) continue; - + assert(e->callback); e->callback(&m->api, e, e->userdata); r++; @@ -705,7 +705,7 @@ static pa_time_event* find_next_time_event(pa_mainloop *m) { if (m->cached_next_time_event) return m->cached_next_time_event; - + for (t = m->time_events; t; t = t->next) { if (t->dead || !t->enabled) @@ -737,7 +737,7 @@ static int calc_next_timeout(pa_mainloop *m) { if (t->timeval.tv_sec <= 0) return 0; - + pa_gettimeofday(&now); if (pa_timeval_cmp(&t->timeval, &now) <= 0) @@ -759,7 +759,7 @@ static int dispatch_timeout(pa_mainloop *m) { pa_gettimeofday(&now); for (e = m->time_events; e && !m->quit; e = e->next) { - + if (e->dead || !e->enabled) continue; @@ -815,7 +815,7 @@ int pa_mainloop_prepare(pa_mainloop *m, int timeout) { if (m->n_enabled_defer_events <= 0) { if (m->rebuild_pollfds) rebuild_pollfds(m); - + m->prepared_timeout = calc_next_timeout(m); if (timeout >= 0 && (timeout < m->prepared_timeout || m->prepared_timeout < 0)) m->prepared_timeout = timeout; @@ -842,7 +842,7 @@ int pa_mainloop_poll(pa_mainloop *m) { m->poll_func_ret = 0; else { assert(!m->rebuild_pollfds); - + if (m->poll_func) m->poll_func_ret = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata); else @@ -872,23 +872,23 @@ int pa_mainloop_dispatch(pa_mainloop *m) { if (m->quit) goto quit; - + if (m->n_enabled_defer_events) dispatched += dispatch_defer(m); else { - if (m->n_enabled_time_events) + if (m->n_enabled_time_events) dispatched += dispatch_timeout(m); - + if (m->quit) goto quit; if (m->poll_func_ret > 0) dispatched += dispatch_pollfds(m); } - + if (m->quit) goto quit; - + m->state = STATE_PASSIVE; return dispatched; @@ -919,7 +919,7 @@ int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) { return r; quit: - + if ((r == -2) && retval) *retval = pa_mainloop_get_retval(m); return r; @@ -927,7 +927,7 @@ quit: int pa_mainloop_run(pa_mainloop *m, int *retval) { int r; - + while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0); if (r == -2) diff --git a/src/pulse/mainloop.h b/src/pulse/mainloop.h index 8abd8fe47..18be1f2ba 100644 --- a/src/pulse/mainloop.h +++ b/src/pulse/mainloop.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -65,7 +65,7 @@ struct pollfd; */ /** \file - * + * * A minimal main loop implementation based on the C library's poll() * function. Using the routines defined herein you may create a simple * main loop supporting the generic main loop abstraction layer as diff --git a/src/pulse/operation.c b/src/pulse/operation.c index 8d896d7d9..e039e8c9a 100644 --- a/src/pulse/operation.c +++ b/src/pulse/operation.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -46,14 +46,14 @@ pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb /* Refcounting is strictly one-way: from the "bigger" to the "smaller" object. */ PA_LLIST_PREPEND(pa_operation, c->operations, o); pa_operation_ref(o); - + return o; } pa_operation *pa_operation_ref(pa_operation *o) { assert(o); assert(o->ref >= 1); - + o->ref++; return o; } @@ -81,14 +81,14 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) { o->state = st; if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) { - + if (o->context) { assert(o->ref >= 2); - + PA_LLIST_REMOVE(pa_operation, o->context->operations, o); pa_operation_unref(o); } - + o->context = NULL; o->stream = NULL; o->callback = NULL; @@ -101,14 +101,14 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) { void pa_operation_cancel(pa_operation *o) { assert(o); assert(o->ref >= 1); - + operation_set_state(o, PA_OPERATION_CANCELED); } void pa_operation_done(pa_operation *o) { assert(o); assert(o->ref >= 1); - + operation_set_state(o, PA_OPERATION_DONE); } diff --git a/src/pulse/operation.h b/src/pulse/operation.h index b544e08ec..adfd5f2d0 100644 --- a/src/pulse/operation.h +++ b/src/pulse/operation.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/pulseaudio.h b/src/pulse/pulseaudio.h index 88cc326b8..5543d7cd6 100644 --- a/src/pulse/pulseaudio.h +++ b/src/pulse/pulseaudio.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -55,11 +55,11 @@ /** \mainpage * * \section intro_sec Introduction - * + * * This document describes the client API for the PulseAudio sound * server. The API comes in two flavours to accomodate different styles * of applications and different needs in complexity: - * + * * \li The complete but somewhat complicated to use asynchronous API * \li The simplified, easy to use, but limited synchronous API * @@ -67,7 +67,7 @@ * locale. Some functions will filter invalid sequences from the string, some * will simply fail. To ensure reliable behaviour, make sure everything you * pass to the API is already in UTF-8. - + * \section simple_sec Simple API * * Use this if you develop your program in synchronous style and just diff --git a/src/pulse/sample.c b/src/pulse/sample.c index 7ca418e10..dd68ac17b 100644 --- a/src/pulse/sample.c +++ b/src/pulse/sample.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -70,7 +70,7 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) { size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) { assert(spec); - return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec); + return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec); } int pa_sample_spec_valid(const pa_sample_spec *spec) { @@ -111,7 +111,7 @@ const char *pa_sample_format_to_string(pa_sample_format_t f) { char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) { assert(s && l && spec); - + if (!pa_sample_spec_valid(spec)) snprintf(s, l, "Invalid"); else @@ -134,7 +134,7 @@ char* pa_bytes_snprint(char *s, size_t l, unsigned v) { } pa_sample_format_t pa_parse_sample_format(const char *format) { - + if (strcasecmp(format, "s16le") == 0) return PA_SAMPLE_S16LE; else if (strcasecmp(format, "s16be") == 0) diff --git a/src/pulse/sample.h b/src/pulse/sample.h index da32fdf0f..b7c537e4c 100644 --- a/src/pulse/sample.h +++ b/src/pulse/sample.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/scache.c b/src/pulse/scache.c index 5d29c5b32..5abaf845f 100644 --- a/src/pulse/scache.c +++ b/src/pulse/scache.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -37,14 +37,14 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) { pa_tagstruct *t; uint32_t tag; - + assert(s); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, length > 0, PA_ERR_INVALID); - + pa_stream_ref(s); - + s->direction = PA_STREAM_UPLOAD; t = pa_tagstruct_command(s->context, PA_COMMAND_CREATE_UPLOAD_STREAM, &tag); @@ -56,7 +56,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) { pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL); pa_stream_set_state(s, PA_STREAM_CREATING); - + pa_stream_unref(s); return 0; } @@ -87,16 +87,16 @@ pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char assert(c); assert(c->ref >= 1); - + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); PA_CHECK_VALIDITY_RETURN_NULL(c, !dev || *dev, PA_ERR_INVALID); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); if (!dev) dev = c->conf->default_sink; - + t = pa_tagstruct_command(c, PA_COMMAND_PLAY_SAMPLE, &tag); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, dev); @@ -118,9 +118,9 @@ pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_conte PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - + t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_SAMPLE, &tag); pa_tagstruct_puts(t, name); pa_pstream_send_tagstruct(c->pstream, t); diff --git a/src/pulse/scache.h b/src/pulse/scache.h index e32703d44..2293dec4e 100644 --- a/src/pulse/scache.h +++ b/src/pulse/scache.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/simple.c b/src/pulse/simple.c index a41881bb6..1c632fa7f 100644 --- a/src/pulse/simple.c +++ b/src/pulse/simple.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -64,7 +64,7 @@ if (!(expression)) { \ goto label; \ } \ } while(0); - + #define CHECK_DEAD_GOTO(p, rerror, label) do { \ if (!(p)->context || pa_context_get_state((p)->context) != PA_CONTEXT_READY || \ !(p)->stream || pa_stream_get_state((p)->stream) != PA_STREAM_READY) { \ @@ -143,7 +143,7 @@ pa_simple* pa_simple_new( const pa_channel_map *map, const pa_buffer_attr *attr, int *rerror) { - + pa_simple *p; int error = PA_ERR_INTERNAL, r; @@ -162,12 +162,12 @@ pa_simple* pa_simple_new( if (!(p->mainloop = pa_threaded_mainloop_new())) goto fail; - + if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name))) goto fail; pa_context_set_state_callback(p->context, context_state_cb, p); - + if (pa_context_connect(p->context, server, 0, NULL) < 0) { error = pa_context_errno(p->context); goto fail; @@ -180,7 +180,7 @@ pa_simple* pa_simple_new( /* Wait until the context is ready */ pa_threaded_mainloop_wait(p->mainloop); - + if (pa_context_get_state(p->context) != PA_CONTEXT_READY) { error = pa_context_errno(p->context); goto unlock_and_fail; @@ -216,12 +216,12 @@ pa_simple* pa_simple_new( } pa_threaded_mainloop_unlock(p->mainloop); - + return p; unlock_and_fail: pa_threaded_mainloop_unlock(p->mainloop); - + fail: if (rerror) *rerror = error; @@ -234,10 +234,10 @@ void pa_simple_free(pa_simple *s) { if (s->mainloop) pa_threaded_mainloop_stop(s->mainloop); - + if (s->stream) pa_stream_unref(s->stream); - + if (s->context) pa_context_unref(s->context); @@ -249,38 +249,38 @@ void pa_simple_free(pa_simple *s) { int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) { assert(p); - + CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1); pa_threaded_mainloop_lock(p->mainloop); - + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); while (length > 0) { size_t l; int r; - + while (!(l = pa_stream_writable_size(p->stream))) { pa_threaded_mainloop_wait(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); } CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail); - + if (l > length) l = length; r = pa_stream_write(p->stream, data, l, NULL, 0, PA_SEEK_RELATIVE); CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail); - + data = (const uint8_t*) data + l; length -= l; } pa_threaded_mainloop_unlock(p->mainloop); return 0; - + unlock_and_fail: pa_threaded_mainloop_unlock(p->mainloop); return -1; @@ -293,15 +293,15 @@ int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1); pa_threaded_mainloop_lock(p->mainloop); - + CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); while (length > 0) { size_t l; - + while (!p->read_data) { int r; - + r = pa_stream_peek(p->stream, &p->read_data, &p->read_length); CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail); @@ -311,31 +311,31 @@ int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { } else p->read_index = 0; } - + l = p->read_length < length ? p->read_length : length; memcpy(data, (const uint8_t*) p->read_data+p->read_index, l); data = (uint8_t*) data + l; length -= l; - + p->read_index += l; p->read_length -= l; if (!p->read_length) { int r; - + r = pa_stream_drop(p->stream); p->read_data = NULL; p->read_length = 0; p->read_index = 0; - + CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail); } } pa_threaded_mainloop_unlock(p->mainloop); return 0; - + unlock_and_fail: pa_threaded_mainloop_unlock(p->mainloop); return -1; @@ -353,7 +353,7 @@ static void success_cb(pa_stream *s, int success, void *userdata) { int pa_simple_drain(pa_simple *p, int *rerror) { pa_operation *o = NULL; - + assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); @@ -370,7 +370,7 @@ int pa_simple_drain(pa_simple *p, int *rerror) { CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); } CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail); - + pa_operation_unref(o); pa_threaded_mainloop_unlock(p->mainloop); @@ -389,7 +389,7 @@ unlock_and_fail: int pa_simple_flush(pa_simple *p, int *rerror) { pa_operation *o = NULL; - + assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); @@ -399,7 +399,7 @@ int pa_simple_flush(pa_simple *p, int *rerror) { o = pa_stream_flush(p->stream, success_cb, p); CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail); - + p->operation_success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { pa_threaded_mainloop_wait(p->mainloop); @@ -426,14 +426,14 @@ unlock_and_fail: pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) { pa_usec_t t; int negative; - + assert(p); - + pa_threaded_mainloop_lock(p->mainloop); for (;;) { CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); - + if (pa_stream_get_latency(p->stream, &t, &negative) >= 0) break; @@ -442,7 +442,7 @@ pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) { /* Wait until latency data is available again */ pa_threaded_mainloop_wait(p->mainloop); } - + pa_threaded_mainloop_unlock(p->mainloop); return negative ? 0 : t; diff --git a/src/pulse/simple.h b/src/pulse/simple.h index 0438d3199..a97875f91 100644 --- a/src/pulse/simple.h +++ b/src/pulse/simple.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 180cd096d..009eb3cf6 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -43,7 +43,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) { pa_stream *s; int i; - + assert(c); PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID); @@ -76,7 +76,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->channel_map = *map; else pa_channel_map_init_auto(&s->channel_map, ss->channels, PA_CHANNEL_MAP_DEFAULT); - + s->channel = 0; s->channel_valid = 0; s->syncid = c->csyncid++; @@ -99,11 +99,11 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * for (i = 0; i < PA_MAX_WRITE_INDEX_CORRECTIONS; i++) s->write_index_corrections[i].valid = 0; s->current_write_index_correction = 0; - + s->corked = 0; s->cached_time_valid = 0; - + s->auto_timing_update_event = NULL; s->auto_timing_update_requested = 0; @@ -143,7 +143,7 @@ void pa_stream_unref(pa_stream *s) { pa_stream* pa_stream_ref(pa_stream *s) { assert(s); assert(s->ref >= 1); - + s->ref++; return s; } @@ -151,14 +151,14 @@ pa_stream* pa_stream_ref(pa_stream *s) { pa_stream_state_t pa_stream_get_state(pa_stream *s) { assert(s); assert(s->ref >= 1); - + return s->state; } pa_context* pa_stream_get_context(pa_stream *s) { assert(s); assert(s->ref >= 1); - + return s->context; } @@ -167,17 +167,17 @@ uint32_t pa_stream_get_index(pa_stream *s) { assert(s->ref >= 1); PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX); - + return s->device_index; } - + void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { assert(s); assert(s->ref >= 1); if (s->state == st) return; - + pa_stream_ref(s); s->state = st; @@ -192,24 +192,24 @@ void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { /* Unref all operatio object that point to us */ for (o = s->context->operations; o; o = n) { n = o->next; - + if (o->stream == s) pa_operation_cancel(o); } - + /* Drop all outstanding replies for this stream */ if (s->context->pdispatch) pa_pdispatch_unregister_reply(s->context->pdispatch, s); if (s->channel_valid) pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL); - + PA_LLIST_REMOVE(pa_stream, s->context->streams, s); pa_stream_unref(s); s->channel = 0; s->channel_valid = 0; - + s->context = NULL; } @@ -220,20 +220,20 @@ void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED pa_context *c = userdata; pa_stream *s; uint32_t channel; - + assert(pd); assert(command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED); assert(t); assert(c); pa_context_ref(c); - + if (pa_tagstruct_getu32(t, &channel) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(c, PA_ERR_PROTOCOL); goto finish; } - + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel))) goto finish; @@ -248,27 +248,27 @@ void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32 pa_stream *s; pa_context *c = userdata; uint32_t bytes, channel; - + assert(pd); assert(command == PA_COMMAND_REQUEST); assert(t); assert(c); pa_context_ref(c); - + if (pa_tagstruct_getu32(t, &channel) < 0 || pa_tagstruct_getu32(t, &bytes) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(c, PA_ERR_PROTOCOL); goto finish; } - + if (!(s = pa_dynarray_get(c->playback_streams, channel))) goto finish; if (s->state == PA_STREAM_READY) { s->requested_bytes += bytes; - + if (s->requested_bytes > 0 && s->write_callback) s->write_callback(s, s->requested_bytes, s->write_userdata); } @@ -288,13 +288,13 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC assert(c); pa_context_ref(c); - + if (pa_tagstruct_getu32(t, &channel) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(c, PA_ERR_PROTOCOL); goto finish; } - + if (!(s = pa_dynarray_get(c->playback_streams, channel))) goto finish; @@ -319,11 +319,11 @@ static void request_auto_timing_update(pa_stream *s, int force) { if (!(s->flags & PA_STREAM_AUTO_TIMING_UPDATE)) return; - + if (s->state == PA_STREAM_READY && (force || !s->auto_timing_update_requested)) { pa_operation *o; - + /* pa_log("automatically requesting new timing data"); */ if ((o = pa_stream_update_timing_info(s, NULL, NULL))) { @@ -341,32 +341,32 @@ static void invalidate_indexes(pa_stream *s, int r, int w) { assert(s); /* pa_log("invalidate r:%u w:%u tag:%u", r, w, s->context->ctag); */ - + if (s->state != PA_STREAM_READY) return; if (w) { s->write_index_not_before = s->context->ctag; - + if (s->timing_info_valid) s->timing_info.write_index_corrupt = 1; - + /* pa_log("write_index invalidated"); */ } - + if (r) { s->read_index_not_before = s->context->ctag; - + if (s->timing_info_valid) s->timing_info.read_index_corrupt = 1; - + /* pa_log("read_index invalidated"); */ } - + if ((s->direction == PA_STREAM_PLAYBACK && r) || (s->direction == PA_STREAM_RECORD && w)) s->cached_time_valid = 0; - + request_auto_timing_update(s, 1); } @@ -382,17 +382,17 @@ static void auto_timing_update_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s = userdata; - + assert(pd); assert(s); assert(s->state == PA_STREAM_CREATING); - + pa_stream_ref(s); - + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(s->context, command, t) < 0) goto finish; - + pa_stream_set_state(s, PA_STREAM_FAILED); goto finish; } @@ -429,9 +429,9 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED if (s->direction == PA_STREAM_RECORD) { assert(!s->record_memblockq); - + s->record_memblockq = pa_memblockq_new( - 0, + 0, s->buffer_attr.maxlength, 0, pa_frame_size(&s->sample_spec), @@ -444,7 +444,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); pa_stream_set_state(s, PA_STREAM_READY); - + if (s->direction != PA_STREAM_UPLOAD && s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { struct timeval tv; @@ -473,13 +473,13 @@ static int create_stream( pa_stream_flags_t flags, const pa_cvolume *volume, pa_stream *sync_stream) { - + pa_tagstruct *t; uint32_t tag; - + assert(s); assert(s->ref >= 1); - + PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, !(flags & ~((direction != PA_STREAM_UPLOAD ? PA_STREAM_START_CORKED| @@ -493,10 +493,10 @@ static int create_stream( s->direction = direction; s->flags = flags; - + if (sync_stream) s->syncid = sync_stream->syncid; - + if (attr) s->buffer_attr = *attr; else { @@ -515,7 +515,7 @@ static int create_stream( s->context, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM, &tag); - + pa_tagstruct_put( t, PA_TAG_STRING, s->name, @@ -526,7 +526,7 @@ static int create_stream( PA_TAG_U32, s->buffer_attr.maxlength, PA_TAG_BOOLEAN, !!(flags & PA_STREAM_START_CORKED), PA_TAG_INVALID); - + if (s->direction == PA_STREAM_PLAYBACK) { pa_cvolume cv; @@ -540,7 +540,7 @@ static int create_stream( if (!volume) volume = pa_cvolume_reset(&cv, s->sample_spec.channels); - + pa_tagstruct_put_cvolume(t, volume); } else pa_tagstruct_putu32(t, s->buffer_attr.fragsize); @@ -549,7 +549,7 @@ static int create_stream( pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL); pa_stream_set_state(s, PA_STREAM_CREATING); - + pa_stream_unref(s); return 0; } @@ -561,10 +561,10 @@ int pa_stream_connect_playback( pa_stream_flags_t flags, pa_cvolume *volume, pa_stream *sync_stream) { - + assert(s); assert(s->ref >= 1); - + return create_stream(PA_STREAM_PLAYBACK, s, dev, attr, flags, volume, sync_stream); } @@ -573,7 +573,7 @@ int pa_stream_connect_record( const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags) { - + assert(s); assert(s->ref >= 1); @@ -587,9 +587,9 @@ int pa_stream_write( void (*free_cb)(void *p), int64_t offset, pa_seek_mode_t seek) { - + pa_memchunk chunk; - + assert(s); assert(s->ref >= 1); assert(data); @@ -602,29 +602,29 @@ int pa_stream_write( if (length <= 0) return 0; - if (free_cb) + if (free_cb) chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) data, length, free_cb, 1); else { chunk.memblock = pa_memblock_new(s->context->mempool, length); memcpy(chunk.memblock->data, data, length); } - + chunk.index = 0; chunk.length = length; pa_pstream_send_memblock(s->context->pstream, s->channel, offset, seek, &chunk); pa_memblock_unref(chunk.memblock); - + if (length < s->requested_bytes) s->requested_bytes -= length; else s->requested_bytes = 0; if (s->direction == PA_STREAM_PLAYBACK) { - + /* Update latency request correction */ if (s->write_index_corrections[s->current_write_index_correction].valid) { - + if (seek == PA_SEEK_ABSOLUTE) { s->write_index_corrections[s->current_write_index_correction].corrupt = 0; s->write_index_corrections[s->current_write_index_correction].absolute = 1; @@ -635,10 +635,10 @@ int pa_stream_write( } else s->write_index_corrections[s->current_write_index_correction].corrupt = 1; } - + /* Update the write index in the already available latency data */ if (s->timing_info_valid) { - + if (seek == PA_SEEK_ABSOLUTE) { s->timing_info.write_index_corrupt = 0; s->timing_info.write_index = offset + length; @@ -652,7 +652,7 @@ int pa_stream_write( if (!s->timing_info_valid || s->timing_info.write_index_corrupt) request_auto_timing_update(s, 1); } - + return 0; } @@ -664,7 +664,7 @@ int pa_stream_peek(pa_stream *s, const void **data, size_t *length) { PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE); - + if (!s->peek_memchunk.memblock) { if (pa_memblockq_peek(s->record_memblockq, &s->peek_memchunk) < 0) { @@ -686,13 +686,13 @@ int pa_stream_drop(pa_stream *s) { PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->peek_memchunk.memblock, PA_ERR_BADSTATE); - + pa_memblockq_drop(s->record_memblockq, &s->peek_memchunk, s->peek_memchunk.length); /* Fix the simulated local read index */ if (s->timing_info_valid && !s->timing_info.read_index_corrupt) s->timing_info.read_index += s->peek_memchunk.length; - + pa_memblock_unref(s->peek_memchunk.memblock); s->peek_memchunk.length = 0; s->peek_memchunk.index = 0; @@ -707,7 +707,7 @@ size_t pa_stream_writable_size(pa_stream *s) { PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1); PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_RECORD, PA_ERR_BADSTATE, (size_t) -1); - + return s->requested_bytes; } @@ -725,7 +725,7 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us pa_operation *o; pa_tagstruct *t; uint32_t tag; - + assert(s); assert(s->ref >= 1); @@ -746,7 +746,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, pa_operation *o = userdata; struct timeval local, remote, now; pa_timing_info *i; - + assert(pd); assert(o); @@ -756,7 +756,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, i = &o->stream->timing_info; /* pa_log("pre corrupt w:%u r:%u\n", !o->stream->timing_info_valid || i->write_index_corrupt,!o->stream->timing_info_valid || i->read_index_corrupt); */ - + o->stream->timing_info_valid = 0; i->write_index_corrupt = 0; i->read_index_corrupt = 0; @@ -777,21 +777,21 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, !pa_tagstruct_eof(t)) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; - + } else { o->stream->timing_info_valid = 1; pa_gettimeofday(&now); - + /* Calculcate timestamps */ if (pa_timeval_cmp(&local, &remote) <= 0 && pa_timeval_cmp(&remote, &now) <= 0) { /* local and remote seem to have synchronized clocks */ - + if (o->stream->direction == PA_STREAM_PLAYBACK) i->transport_usec = pa_timeval_diff(&remote, &local); else i->transport_usec = pa_timeval_diff(&now, &remote); - + i->synchronized_clocks = 1; i->timestamp = remote; } else { @@ -816,7 +816,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t ctag = tag; /* Go through the saved correction values and add up the total correction.*/ - + for (n = 0, j = o->stream->current_write_index_correction+1; n < PA_MAX_WRITE_INDEX_CORRECTIONS; n++, j = (j + 1) % PA_MAX_WRITE_INDEX_CORRECTIONS) { @@ -851,21 +851,21 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, if (!i->read_index_corrupt) i->read_index -= pa_memblockq_get_length(o->stream->record_memblockq); } - + o->stream->cached_time_valid = 0; } o->stream->auto_timing_update_requested = 0; /* pa_log("post corrupt w:%u r:%u\n", i->write_index_corrupt || !o->stream->timing_info_valid, i->read_index_corrupt || !o->stream->timing_info_valid); */ - + /* Clear old correction entries */ if (o->stream->direction == PA_STREAM_PLAYBACK) { int n; - + for (n = 0; n < PA_MAX_WRITE_INDEX_CORRECTIONS; n++) { if (!o->stream->write_index_corrections[n].valid) continue; - + if (o->stream->write_index_corrections[n].tag <= tag) o->stream->write_index_corrections[n].valid = 0; } @@ -873,12 +873,12 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, if (o->stream->latency_update_callback) o->stream->latency_update_callback(o->stream, o->stream->latency_update_userdata); - + if (o->callback && o->stream && o->stream->state == PA_STREAM_READY) { pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback; cb(o->stream, o->stream->timing_info_valid, o->userdata); } - + finish: pa_operation_done(o); @@ -891,29 +891,29 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t pa_tagstruct *t; struct timeval now; int cidx = 0; - + assert(s); assert(s->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - + if (s->direction == PA_STREAM_PLAYBACK) { /* Find a place to store the write_index correction data for this entry */ cidx = (s->current_write_index_correction + 1) % PA_MAX_WRITE_INDEX_CORRECTIONS; - + /* Check if we could allocate a correction slot. If not, there are too many outstanding queries */ PA_CHECK_VALIDITY_RETURN_NULL(s->context, !s->write_index_corrections[cidx].valid, PA_ERR_INTERNAL); } o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); - + t = pa_tagstruct_command( s->context, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY, &tag); pa_tagstruct_putu32(t, s->channel); pa_tagstruct_put_timeval(t, pa_gettimeofday(&now)); - + pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_timing_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); @@ -926,15 +926,15 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t o->stream->write_index_corrections[cidx].value = 0; o->stream->write_index_corrections[cidx].corrupt = 0; } - + /* pa_log("requesting update %u\n", tag); */ - + return o; } void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s = userdata; - + assert(pd); assert(s); assert(s->ref >= 1); @@ -961,7 +961,7 @@ finish: int pa_stream_disconnect(pa_stream *s) { pa_tagstruct *t; uint32_t tag; - + assert(s); assert(s->ref >= 1); @@ -1010,7 +1010,7 @@ void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void * void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { assert(s); assert(s->ref >= 1); - + s->overflow_callback = cb; s->overflow_userdata = userdata; } @@ -1018,7 +1018,7 @@ void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, voi void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { assert(s); assert(s->ref >= 1); - + s->underflow_callback = cb; s->underflow_userdata = userdata; } @@ -1026,7 +1026,7 @@ void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, vo void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { assert(s); assert(s->ref >= 1); - + s->latency_update_callback = cb; s->latency_update_userdata = userdata; } @@ -1034,14 +1034,14 @@ void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t c void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; - + assert(pd); assert(o); assert(o->ref >= 1); if (!o->context) goto finish; - + if (command != PA_COMMAND_REPLY) { if (pa_context_handle_error(o->context, command, t) < 0) goto finish; @@ -1066,15 +1066,15 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi pa_operation *o; pa_tagstruct *t; uint32_t tag; - + assert(s); assert(s->ref >= 1); - + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); s->corked = b; - + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command( @@ -1096,12 +1096,12 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, pa_tagstruct *t; pa_operation *o; uint32_t tag; - + assert(s); assert(s->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); - + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(s->context, command, &tag); @@ -1114,26 +1114,26 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; - + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - + if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) { if (s->direction == PA_STREAM_PLAYBACK) { if (s->write_index_corrections[s->current_write_index_correction].valid) s->write_index_corrections[s->current_write_index_correction].corrupt = 1; - + if (s->timing_info_valid) s->timing_info.write_index_corrupt = 1; - if (s->buffer_attr.prebuf > 0) + if (s->buffer_attr.prebuf > 0) invalidate_indexes(s, 1, 0); else request_auto_timing_update(s, 1); } else invalidate_indexes(s, 0, 1); } - + return o; } @@ -1151,13 +1151,13 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; - + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE); if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata))) invalidate_indexes(s, 1, 0); - + return o; } @@ -1165,7 +1165,7 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe pa_operation *o; pa_tagstruct *t; uint32_t tag; - + assert(s); assert(s->ref >= 1); assert(name); @@ -1213,7 +1213,7 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { * to us, we assume that the real output time is actually * a little ahead */ usec += s->timing_info.transport_usec; - + /* However, the output device usually maintains a buffer too, hence the real sample currently played is a little back */ @@ -1222,7 +1222,7 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { else usec -= s->timing_info.sink_usec; } - + } else if (s->direction == PA_STREAM_RECORD) { /* The last byte written into the server side queue had * this time value associated */ @@ -1231,10 +1231,10 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { if (!s->corked) { /* Add transport latency */ usec += s->timing_info.transport_usec; - + /* Add latency of data in device buffer */ usec += s->timing_info.source_usec; - + /* If this is a monitor source, we need to correct the * time by the playback device buffer */ if (s->timing_info.sink_usec >= usec) @@ -1269,18 +1269,18 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { if (r_usec) *r_usec = usec; - + return 0; } static pa_usec_t time_counter_diff(pa_stream *s, pa_usec_t a, pa_usec_t b, int *negative) { assert(s); assert(s->ref >= 1); - + if (negative) *negative = 0; - if (a >= b) + if (a >= b) return a-b; else { if (negative && s->direction == PA_STREAM_RECORD) { @@ -1305,7 +1305,7 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) { PA_CHECK_VALIDITY(s->context, s->timing_info_valid, PA_ERR_NODATA); PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->timing_info.write_index_corrupt, PA_ERR_NODATA); PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_RECORD || !s->timing_info.read_index_corrupt, PA_ERR_NODATA); - + if ((r = pa_stream_get_time(s, &t)) < 0) return r; @@ -1316,7 +1316,7 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) { if (cindex < 0) cindex = 0; - + c = pa_bytes_to_usec(cindex, &s->sample_spec); if (s->direction == PA_STREAM_PLAYBACK) diff --git a/src/pulse/stream.h b/src/pulse/stream.h index ad15125ab..2ce534586 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -113,7 +113,7 @@ * read index may be larger than the write index, in which case * silence is played. If the application writes data to indexes lower * than the read index, the data is immediately lost. - * + * * \section transfer_sec Transferring Data * * Once the stream is up, data can start flowing between the client and the @@ -159,13 +159,13 @@ * \li PA_SEEK_ABSOLUTE - seek relative to the beginning of the playback buffer, (i.e. the first that was ever played in the stream) * \li PA_SEEK_RELATIVE_ON_READ - seek relative to the current read index. Use this to write data to the output buffer that should be played as soon as possible * \li PA_SEEK_RELATIVE_END - seek relative to the last byte ever written. - * + * * If an application just wants to append some data to the output * buffer, PA_SEEK_RELATIVE and an offset of 0 should be used. * * After a call to pa_stream_write() the write index will be left at * the position right after the last byte of the written data. - * + * * \section latency_sec Latency * * A major problem with networked audio is the increased latency caused by @@ -217,7 +217,7 @@ * this option with PA_STREAM_AUTO_TIMING_UPDATE, which will enable * you to monitor the current playback time/latency very precisely and * very frequently without requiring a network round trip every time. - * + * * \section flow_sec Overflow and underflow * * Even with the best precautions, buffers will sometime over - or @@ -275,7 +275,7 @@ typedef void (*pa_stream_notify_cb_t)(pa_stream *p, void *userdata); /** Create a new, unconnected stream with the specified name and sample type */ pa_stream* pa_stream_new( - pa_context *c /**< The context to create this stream in */, + pa_context *c /**< The context to create this stream in */, const char *name /**< A name for this stream */, const pa_sample_spec *ss /**< The desired sample format */, const pa_channel_map *map /**< The desired channel map, or NULL for default */); @@ -320,7 +320,7 @@ int pa_stream_disconnect(pa_stream *s); * is not copied. If NULL, the data is copied into an internal * buffer. The client my freely seek around in the output buffer. For * most applications passing 0 and PA_SEEK_RELATIVE as arguments for - * offset and seek should be useful.*/ + * offset and seek should be useful.*/ int pa_stream_write( pa_stream *p /**< The stream to use */, const void *data /**< The data to write */, @@ -333,7 +333,7 @@ int pa_stream_write( * data will point to the actual data and length will contain the size * of the data in bytes (which can be less than a complete framgnet). * Use pa_stream_drop() to actually remove the data from the - * buffer. If no data is available will return a NULL pointer \since 0.8 */ + * buffer. If no data is available will return a NULL pointer \since 0.8 */ int pa_stream_peek( pa_stream *p /**< The stream to use */, const void **data /**< Pointer to pointer that will point to data */, diff --git a/src/pulse/subscribe.c b/src/pulse/subscribe.c index c1d889122..d9abf6f80 100644 --- a/src/pulse/subscribe.c +++ b/src/pulse/subscribe.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -69,7 +69,7 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_c assert(c->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_SUBSCRIBE, &tag); @@ -83,7 +83,7 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_c void pa_context_set_subscribe_callback(pa_context *c, pa_context_subscribe_cb_t cb, void *userdata) { assert(c); assert(c->ref >= 1); - + c->subscribe_callback = cb; c->subscribe_userdata = userdata; } diff --git a/src/pulse/subscribe.h b/src/pulse/subscribe.h index adbea6809..35d5a31ce 100644 --- a/src/pulse/subscribe.h +++ b/src/pulse/subscribe.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c index 7e1ccfaa6..ad29f5ba8 100644 --- a/src/pulse/thread-mainloop.c +++ b/src/pulse/thread-mainloop.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -128,7 +128,7 @@ void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { pa_mutex_free(m->mutex); pa_cond_free(m->cond); pa_cond_free(m->accept_cond); - + pa_xfree(m); } @@ -161,7 +161,7 @@ void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) { void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) { assert(m); - + /* Make sure that this function is not called from the helper thread */ assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); @@ -170,7 +170,7 @@ void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) { void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) { assert(m); - + /* Make sure that this function is not called from the helper thread */ assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); @@ -188,7 +188,7 @@ void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) { void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { assert(m); - + /* Make sure that this function is not called from the helper thread */ assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); @@ -202,7 +202,7 @@ void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) { assert(m); - + /* Make sure that this function is not called from the helper thread */ assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); diff --git a/src/pulse/thread-mainloop.h b/src/pulse/thread-mainloop.h index 44eff5a34..48048b35c 100644 --- a/src/pulse/thread-mainloop.h +++ b/src/pulse/thread-mainloop.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -149,7 +149,7 @@ PA_C_DECL_BEGIN * deal with that. * * The functions will not dead lock because the wait function will release - * the lock before waiting and then regrab it once it has been signaled. + * the lock before waiting and then regrab it once it has been signaled. * For those of you familiar with threads, the behaviour is that of a * condition variable. * @@ -229,7 +229,7 @@ PA_C_DECL_BEGIN */ /** \file - * + * * A thread based event loop implementation based on pa_mainloop. The * event loop is run in a helper thread in the background. A few * synchronization primitives are available to access the objects diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c index 112852302..e5a86a632 100644 --- a/src/pulse/timeval.c +++ b/src/pulse/timeval.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -38,7 +38,7 @@ struct timeval *pa_gettimeofday(struct timeval *tv) { #ifdef HAVE_GETTIMEOFDAY assert(tv); - + return gettimeofday(tv, NULL) < 0 ? NULL : tv; #elif defined(OS_IS_WIN32) /* @@ -118,14 +118,14 @@ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { pa_usec_t pa_timeval_age(const struct timeval *tv) { struct timeval now; assert(tv); - + return pa_timeval_diff(pa_gettimeofday(&now), tv); } struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) { unsigned long secs; assert(tv); - + secs = (v/1000000); tv->tv_sec += (unsigned long) secs; v -= secs*1000000; diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h index e2dbbadb2..c10ec9f60 100644 --- a/src/pulse/timeval.h +++ b/src/pulse/timeval.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/utf8.c b/src/pulse/utf8.c index 33fa7214e..2708c5181 100644 --- a/src/pulse/utf8.c +++ b/src/pulse/utf8.c @@ -130,7 +130,7 @@ ONE_REMAINING: if (o) o++; - + continue; error: diff --git a/src/pulse/utf8.h b/src/pulse/utf8.h index 2eac724db..7225471f1 100644 --- a/src/pulse/utf8.h +++ b/src/pulse/utf8.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/util.c b/src/pulse/util.c index c13951da4..63f54e3bb 100644 --- a/src/pulse/util.c +++ b/src/pulse/util.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -79,7 +79,7 @@ char *pa_get_user_name(char *s, size_t l) { if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) { #ifdef HAVE_PWD_H - + #ifdef HAVE_GETPWUID_R if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) { #else @@ -90,7 +90,7 @@ char *pa_get_user_name(char *s, size_t l) { snprintf(s, l, "%lu", (unsigned long) getuid()); return s; } - + p = r->pw_name; #elif defined(OS_IS_WIN32) /* HAVE_PWD_H */ @@ -162,26 +162,26 @@ char *pa_get_binary_name(char *s, size_t l) { #if defined(OS_IS_WIN32) { char path[PATH_MAX]; - + if (GetModuleFileName(NULL, path, PATH_MAX)) return pa_strlcpy(s, pa_path_get_filename(path), l); } #endif - + #ifdef HAVE_READLINK { int i; char path[PATH_MAX]; /* This works on Linux only */ - + if ((i = readlink("/proc/self/exe", path, sizeof(path)-1)) >= 0) { path[i] = 0; return pa_strlcpy(s, pa_path_get_filename(path), l); } } - + #endif - + #if defined(HAVE_SYS_PRCTL_H) && defined(PR_GET_NAME) { @@ -192,14 +192,14 @@ char *pa_get_binary_name(char *s, size_t l) { char tcomm[TASK_COMM_LEN+1]; memset(tcomm, 0, sizeof(tcomm)); - + /* This works on Linux only */ if (prctl(PR_GET_NAME, (unsigned long) tcomm, 0, 0, 0) == 0) return pa_strlcpy(s, tcomm, l); - + } #endif - + return NULL; } @@ -214,7 +214,7 @@ const char *pa_path_get_filename(const char *p) { char *pa_get_fqdn(char *s, size_t l) { char hn[256]; -#ifdef HAVE_GETADDRINFO +#ifdef HAVE_GETADDRINFO struct addrinfo *a, hints; #endif @@ -225,7 +225,7 @@ char *pa_get_fqdn(char *s, size_t l) { memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_CANONNAME; - + if (getaddrinfo(hn, NULL, &hints, &a) < 0 || !a || !a->ai_canonname || !*a->ai_canonname) return pa_strlcpy(s, hn, l); diff --git a/src/pulse/util.h b/src/pulse/util.h index 5c03b0a94..0be169fb4 100644 --- a/src/pulse/util.h +++ b/src/pulse/util.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/volume.c b/src/pulse/volume.c index 530814e0f..aa7ddba29 100644 --- a/src/pulse/volume.c +++ b/src/pulse/volume.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -36,7 +36,7 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) { if (a->channels != b->channels) return 0; - + for (i = 0; i < a->channels; i++) if (a->values[i] != b->values[i]) return 0; @@ -46,7 +46,7 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) { pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) { int i; - + assert(a); assert(channels > 0); assert(channels <= PA_CHANNELS_MAX); @@ -115,7 +115,7 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) { unsigned channel; int first = 1; char *e; - + assert(s); assert(l > 0); assert(c); @@ -149,7 +149,7 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) { pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) { unsigned i; - + assert(dest); assert(a); assert(b); diff --git a/src/pulse/volume.h b/src/pulse/volume.h index 6c60223ac..62d2867aa 100644 --- a/src/pulse/volume.h +++ b/src/pulse/volume.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulse/xmalloc.c b/src/pulse/xmalloc.c index 367551665..dda42bdc3 100644 --- a/src/pulse/xmalloc.c +++ b/src/pulse/xmalloc.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -60,10 +60,10 @@ void* pa_xmalloc(size_t size) { void *p; assert(size > 0); assert(size < MAX_ALLOC_SIZE); - + if (!(p = malloc(size))) oom(); - + return p; } @@ -71,18 +71,18 @@ void* pa_xmalloc0(size_t size) { void *p; assert(size > 0); assert(size < MAX_ALLOC_SIZE); - + if (!(p = calloc(1, size))) oom(); - + return p; } - + void *pa_xrealloc(void *ptr, size_t size) { void *p; assert(size > 0); assert(size < MAX_ALLOC_SIZE); - + if (!(p = realloc(ptr, size))) oom(); return p; @@ -107,7 +107,7 @@ char *pa_xstrdup(const char *s) { char *pa_xstrndup(const char *s, size_t l) { char *e, *r; - + if (!s) return NULL; diff --git a/src/pulse/xmalloc.h b/src/pulse/xmalloc.h index 126c495ca..2fb1c5f0f 100644 --- a/src/pulse/xmalloc.h +++ b/src/pulse/xmalloc.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/anotify.c b/src/pulsecore/anotify.c index a61f84426..c89d4a15f 100644 --- a/src/pulsecore/anotify.c +++ b/src/pulsecore/anotify.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -48,7 +48,7 @@ struct pa_anotify { static void dispatch_event(pa_anotify *a) { assert(a); assert(a->queue_index < a->n_queued_events); - + a->callback(a->queued_events[a->queue_index++], a->userdata); if (a->queue_index >= a->n_queued_events) { @@ -69,14 +69,14 @@ static void io_callback( int fd, pa_io_event_flags_t events, void *userdata) { - + pa_anotify *a = userdata; ssize_t r; assert(a); assert(events == PA_IO_EVENT_INPUT); assert(a->n_queued_events == 0); - + r = read(fd, a->queued_events, sizeof(a->queued_events)); assert(r > 0); @@ -96,7 +96,7 @@ static void defer_callback(pa_mainloop_api *api, pa_defer_event *e, void *userda pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userdata) { pa_anotify *a; - + assert(api); assert(cb); @@ -106,7 +106,7 @@ pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userda pa_xfree(a); return NULL; } - + a->api = api; a->callback = cb; a->userdata = userdata; @@ -130,7 +130,7 @@ void pa_anotify_free(pa_anotify *a) { close(a->fds[0]); if (a->fds[1] >= 0) close(a->fds[1]); - + pa_xfree(a); } diff --git a/src/pulsecore/anotify.h b/src/pulsecore/anotify.h index 44e942f75..b91e6875b 100644 --- a/src/pulsecore/anotify.h +++ b/src/pulsecore/anotify.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index 8d608b5b6..e713e7a83 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/authkey-prop.c b/src/pulsecore/authkey-prop.c index 7eda1e496..f3a811798 100644 --- a/src/pulsecore/authkey-prop.c +++ b/src/pulsecore/authkey-prop.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -37,7 +37,7 @@ struct authkey_data { int pa_authkey_prop_get(pa_core *c, const char *name, void *data, size_t len) { struct authkey_data *a; assert(c && name && data && len > 0); - + if (!(a = pa_property_get(c, name))) return -1; @@ -59,7 +59,7 @@ int pa_authkey_prop_put(pa_core *c, const char *name, const void *data, size_t l memcpy(a+1, data, len); pa_property_set(c, name, a); - + return 0; } diff --git a/src/pulsecore/authkey-prop.h b/src/pulsecore/authkey-prop.h index b1da28bea..fb777f85f 100644 --- a/src/pulsecore/authkey-prop.h +++ b/src/pulsecore/authkey-prop.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c index 87631ca53..8ef53bd8e 100644 --- a/src/pulsecore/authkey.c +++ b/src/pulsecore/authkey.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -91,25 +91,25 @@ static int load(const char *fn, void *data, size_t length) { if ((size_t) r != length) { pa_log_debug("got %d bytes from cookie file '%s', expected %d", (int)r, fn, (int)length); - + if (!writable) { pa_log("unable to write cookie to read only file"); goto finish; } - + if (generate(fd, data, length) < 0) goto finish; } ret = 0; - + finish: if (fd >= 0) { - + if (unlock) pa_lock_fd(fd, 0); - + close(fd); } @@ -144,7 +144,7 @@ static const char *normalize_path(const char *fn, char *s, size_t l) { char homedir[PATH_MAX]; if (!pa_get_home_dir(homedir, sizeof(homedir))) return NULL; - + #ifndef OS_IS_WIN32 snprintf(s, l, "%s/%s", homedir, fn); #else @@ -165,7 +165,7 @@ int pa_authkey_load_auto(const char *fn, void *data, size_t length) { if (!(p = normalize_path(fn, path, sizeof(path)))) return -2; - + return pa_authkey_load(p, data, length); } @@ -194,14 +194,14 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) { } ret = 0; - + finish: if (fd >= 0) { - + if (unlock) pa_lock_fd(fd, 0); - + close(fd); } diff --git a/src/pulsecore/authkey.h b/src/pulsecore/authkey.h index cc8a565cf..bba0bc73c 100644 --- a/src/pulsecore/authkey.h +++ b/src/pulsecore/authkey.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/autoload.c b/src/pulsecore/autoload.c index 60304201f..b68eaac75 100644 --- a/src/pulsecore/autoload.c +++ b/src/pulsecore/autoload.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -58,20 +58,20 @@ static void entry_remove_and_free(pa_autoload_entry *e) { static pa_autoload_entry* entry_new(pa_core *c, const char *name) { pa_autoload_entry *e = NULL; assert(c && name); - + if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name))) return NULL; - + e = pa_xmalloc(sizeof(pa_autoload_entry)); e->core = c; e->name = pa_xstrdup(name); e->module = e->argument = NULL; e->in_action = 0; - + if (!c->autoload_hashmap) c->autoload_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); assert(c->autoload_hashmap); - + pa_hashmap_put(c->autoload_hashmap, e->name, e); if (!c->autoload_idxset) @@ -79,24 +79,24 @@ static pa_autoload_entry* entry_new(pa_core *c, const char *name) { pa_idxset_put(c->autoload_idxset, e, &e->index); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_NEW, e->index); - + return e; } int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const char*module, const char *argument, uint32_t *idx) { pa_autoload_entry *e = NULL; assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); - + if (!(e = entry_new(c, name))) return -1; - + e->module = pa_xstrdup(module); e->argument = pa_xstrdup(argument); e->type = type; if (idx) *idx = e->index; - + return 0; } @@ -139,7 +139,7 @@ void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type) { if ((m = pa_module_load(c, e->module, e->argument))) m->auto_unload = 1; } - + e->in_action = 0; } @@ -154,7 +154,7 @@ void pa_autoload_free(pa_core *c) { pa_hashmap_free(c->autoload_hashmap, free_func, NULL); c->autoload_hashmap = NULL; } - + if (c->autoload_idxset) { pa_idxset_free(c->autoload_idxset, NULL, NULL); c->autoload_idxset = NULL; @@ -164,7 +164,7 @@ void pa_autoload_free(pa_core *c) { const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type_t type) { pa_autoload_entry *e; assert(c && name); - + if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) return NULL; @@ -174,7 +174,7 @@ const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa const pa_autoload_entry* pa_autoload_get_by_index(pa_core *c, uint32_t idx) { pa_autoload_entry *e; assert(c && idx != PA_IDXSET_INVALID); - + if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, idx))) return NULL; diff --git a/src/pulsecore/autoload.h b/src/pulsecore/autoload.h index 65bdd6da6..f410e49cb 100644 --- a/src/pulsecore/autoload.h +++ b/src/pulsecore/autoload.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -36,7 +36,7 @@ typedef struct pa_autoload_entry { char *name; pa_namereg_type_t type; /* Type of the autoload entry */ int in_action; /* Currently loaded */ - char *module, *argument; + char *module, *argument; } pa_autoload_entry; /* Add a new autoload entry of the given time, with the speicified diff --git a/src/pulsecore/avahi-wrap.c b/src/pulsecore/avahi-wrap.c index 80256a124..bcda99546 100644 --- a/src/pulsecore/avahi-wrap.c +++ b/src/pulsecore/avahi-wrap.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -58,7 +58,7 @@ static pa_io_event_flags_t translate_io_flags(AvahiWatchEvent e) { static void watch_callback(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) { AvahiWatch *w = userdata; - + assert(a); assert(e); assert(w); @@ -75,7 +75,7 @@ static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event assert(api); assert(fd >= 0); assert(callback); - + p = api->userdata; assert(p); @@ -88,19 +88,19 @@ static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event return w; } - + static void watch_update(AvahiWatch *w, AvahiWatchEvent event) { assert(w); w->avahi_poll->mainloop->io_enable(w->io_event, translate_io_flags(event)); } - + static AvahiWatchEvent watch_get_events(AvahiWatch *w) { assert(w); return w->current_event; } - + static void watch_free(AvahiWatch *w) { assert(w); @@ -117,7 +117,7 @@ struct AvahiTimeout { static void timeout_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) { AvahiTimeout *t = userdata; - + assert(a); assert(e); assert(t); @@ -131,7 +131,7 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, assert(api); assert(callback); - + p = api->userdata; assert(p); @@ -139,12 +139,12 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, t->avahi_poll = p; t->callback = callback; t->userdata = userdata; - + t->time_event = tv ? p->mainloop->time_new(p->mainloop, tv, timeout_callback, t) : NULL; return t; } - + static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { assert(t); @@ -157,7 +157,7 @@ static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { t->time_event = NULL; } } - + static void timeout_free(AvahiTimeout *t) { assert(t); @@ -170,9 +170,9 @@ AvahiPoll* pa_avahi_poll_new(pa_mainloop_api *m) { pa_avahi_poll *p; assert(m); - + p = pa_xnew(pa_avahi_poll, 1); - + p->api.userdata = p; p->api.watch_new = watch_new; p->api.watch_update = watch_update; @@ -182,7 +182,7 @@ AvahiPoll* pa_avahi_poll_new(pa_mainloop_api *m) { p->api.timeout_update = timeout_update; p->api.timeout_free = timeout_free; p->mainloop = m; - + return &p->api; } @@ -191,7 +191,7 @@ void pa_avahi_poll_free(AvahiPoll *api) { assert(api); p = api->userdata; assert(p); - + pa_xfree(p); } diff --git a/src/pulsecore/avahi-wrap.h b/src/pulsecore/avahi-wrap.h index d868fed49..bb8f5716b 100644 --- a/src/pulsecore/avahi-wrap.h +++ b/src/pulsecore/avahi-wrap.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index ae475c3a0..cb438a224 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -172,7 +172,7 @@ static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G assert(c && t && buf); pa_strbuf_puts(buf, "Available commands:\n"); - + for (command = commands; command->name; command++) if (command->help) pa_strbuf_printf(buf, " %-25s %s\n", command->name, command->help); @@ -252,12 +252,12 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G [PA_MEMBLOCK_FIXED] = "FIXED", [PA_MEMBLOCK_IMPORTED] = "IMPORTED", }; - + assert(c); assert(t); stat = pa_mempool_get_stat(c->mempool); - + pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n", (unsigned) AO_load_acquire_read((AO_t*) &stat->n_allocated), pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->allocated_size))); @@ -291,7 +291,7 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G type_table[k], (unsigned) AO_load_acquire_read(&stat->n_allocated_by_type[k]), (unsigned) AO_load_acquire_read(&stat->n_accumulated_by_type[k])); - + return 0; } @@ -318,7 +318,7 @@ static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n"); return -1; } - + if (!(m = pa_module_load(c, name, pa_tokenizer_get(t, 2)))) { pa_strbuf_puts(buf, "Module load failed.\n"); return -1; @@ -724,14 +724,14 @@ static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *b } pa_autoload_add(c, a, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, b, pa_tokenizer_get(t, 3), NULL); - + return 0; } static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *name; assert(c && t && buf && fail); - + if (!(name = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a device name\n"); return -1; @@ -742,7 +742,7 @@ static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf return -1; } - return 0; + return 0; } static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { @@ -766,7 +766,7 @@ static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, in assert(t); pa_mempool_vacuum(c->mempool); - + return 0; } @@ -857,7 +857,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G time_t now; void *i; pa_autoload_entry *a; - + assert(c && t); time(&now); @@ -868,7 +868,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now)); #endif - + for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) { if (m->auto_unload) continue; @@ -912,7 +912,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G if (c->autoload_hashmap) { nl = 0; - + i = NULL; while ((a = pa_hashmap_iterate(c->autoload_hashmap, &i, NULL))) { @@ -920,18 +920,18 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_strbuf_puts(buf, "\n"); nl = 1; } - + pa_strbuf_printf(buf, "add-autoload-%s %s %s", a->type == PA_NAMEREG_SINK ? "sink" : "source", a->name, a->module); - + if (a->argument) pa_strbuf_printf(buf, " %s", a->argument); - + pa_strbuf_puts(buf, "\n"); } } nl = 0; - + if ((p = pa_namereg_get_default_sink_name(c))) { if (!nl) { pa_strbuf_puts(buf, "\n"); @@ -955,7 +955,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int *fail) { const char *cs; - + cs = s+strspn(s, whitespace); if (*cs == '#' || !*cs) @@ -983,10 +983,10 @@ int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int * const struct command*command; int unknown = 1; size_t l; - + l = strcspn(cs, whitespace); - for (command = commands; command->name; command++) + for (command = commands; command->name; command++) if (strlen(command->name) == l && !strncmp(cs, command->name, l)) { int ret; pa_tokenizer *t = pa_tokenizer_new(cs, command->args); @@ -997,7 +997,7 @@ int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int * if (ret < 0 && *fail) return -1; - + break; } @@ -1049,7 +1049,7 @@ int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail) while (*p) { size_t l = strcspn(p, linebreak); char *line = pa_xstrndup(p, l); - + if (pa_cli_command_execute_line(c, line, buf, fail) < 0&& *fail) { pa_xfree(line); return -1; diff --git a/src/pulsecore/cli-command.h b/src/pulsecore/cli-command.h index c56c3ca00..1594f4db4 100644 --- a/src/pulsecore/cli-command.h +++ b/src/pulsecore/cli-command.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index 49934c07d..ac74a287c 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -52,10 +52,10 @@ char *pa_module_list_to_string(pa_core *c) { assert(s); pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_size(c->modules)); - + for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\targument: <%s>\n\tused: %i\n\tauto unload: %s\n", m->index, m->name, m->argument, m->n_used, m->auto_unload ? "yes" : "no"); - + return pa_strbuf_tostring_free(s); } @@ -69,14 +69,14 @@ char *pa_client_list_to_string(pa_core *c) { assert(s); pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_size(c->clients)); - + for (client = pa_idxset_first(c->clients, &idx); client; client = pa_idxset_next(c->clients, &idx)) { pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tdriver: <%s>\n", client->index, client->name, client->driver); if (client->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index); } - + return pa_strbuf_tostring_free(s); } @@ -93,7 +93,7 @@ char *pa_sink_list_to_string(pa_core *c) { for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; - + pa_strbuf_printf( s, " %c index: %u\n" @@ -118,7 +118,7 @@ char *pa_sink_list_to_string(pa_core *c) { if (sink->description) pa_strbuf_printf(s, "\tdescription: <%s>\n", sink->description); } - + return pa_strbuf_tostring_free(s); } @@ -135,8 +135,8 @@ char *pa_source_list_to_string(pa_core *c) { for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; - - + + pa_strbuf_printf( s, " %c index: %u\n" @@ -153,14 +153,14 @@ char *pa_source_list_to_string(pa_core *c) { pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map)); - if (source->monitor_of) + if (source->monitor_of) pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index); if (source->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", source->owner->index); if (source->description) pa_strbuf_printf(s, "\tdescription: <%s>\n", source->description); } - + return pa_strbuf_tostring_free(s); } @@ -183,9 +183,9 @@ char *pa_source_output_list_to_string(pa_core *c) { for (o = pa_idxset_first(c->source_outputs, &idx); o; o = pa_idxset_next(c->source_outputs, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; - + assert(o->source); - + pa_strbuf_printf( s, " index: %u\n" @@ -209,7 +209,7 @@ char *pa_source_output_list_to_string(pa_core *c) { if (o->client) pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", o->client->index, o->client->name); } - + return pa_strbuf_tostring_free(s); } @@ -233,7 +233,7 @@ char *pa_sink_input_list_to_string(pa_core *c) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; assert(i->sink); - + pa_strbuf_printf( s, " index: %u\n" @@ -262,7 +262,7 @@ char *pa_sink_input_list_to_string(pa_core *c) { if (i->client) pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", i->client->index, i->client->name); } - + return pa_strbuf_tostring_free(s); } @@ -282,13 +282,13 @@ char *pa_scache_list_to_string(pa_core *c) { for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) { double l = 0; char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX] = "n/a"; - + if (e->memchunk.memblock) { pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec); pa_channel_map_snprint(cm, sizeof(cm), &e->channel_map); l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec); } - + pa_strbuf_printf( s, " name: <%s>\n" @@ -351,9 +351,9 @@ char *pa_full_status_string(pa_core *c) { for (i = 0; i < 8; i++) { char *t = NULL; - + switch (i) { - case 0: + case 0: t = pa_sink_list_to_string(c); break; case 1: @@ -365,7 +365,7 @@ char *pa_full_status_string(pa_core *c) { case 3: t = pa_source_output_list_to_string(c); break; - case 4: + case 4: t = pa_client_list_to_string(c); break; case 5: diff --git a/src/pulsecore/cli-text.h b/src/pulsecore/cli-text.h index cd3acdee7..b092fc8b7 100644 --- a/src/pulsecore/cli-text.h +++ b/src/pulsecore/cli-text.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c index e3fc2e4cd..0820fc8e7 100644 --- a/src/pulsecore/cli.c +++ b/src/pulsecore/cli.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -82,12 +82,12 @@ pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) { c->client->kill = client_kill; c->client->userdata = c; c->client->owner = m; - + pa_ioline_set_callback(c->line, line_callback, c); pa_ioline_puts(c->line, "Welcome to PulseAudio! Use \"help\" for usage information.\n"PROMPT); c->fail = c->kill_requested = c->defer_kill = 0; - + return c; } @@ -103,7 +103,7 @@ static void client_kill(pa_client *client) { pa_cli *c; assert(client && client->userdata); c = client->userdata; - + pa_log_debug("CLI client killed."); if (c->defer_kill) c->kill_requested = 1; @@ -138,7 +138,7 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { if (c->kill_requested) { if (c->eof_callback) c->eof_callback(c, c->userdata); - } else + } else pa_ioline_puts(line, PROMPT); } diff --git a/src/pulsecore/cli.h b/src/pulsecore/cli.h index 639fa9525..5cf0ebd21 100644 --- a/src/pulsecore/cli.h +++ b/src/pulsecore/cli.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c index c34bf1490..55697d2e3 100644 --- a/src/pulsecore/client.c +++ b/src/pulsecore/client.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -56,7 +56,7 @@ pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) { pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); pa_core_check_quit(core); - + return c; } diff --git a/src/pulsecore/client.h b/src/pulsecore/client.h index b28065e5d..e632da129 100644 --- a/src/pulsecore/client.h +++ b/src/pulsecore/client.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index db1e37192..6f55e2de4 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -42,24 +42,24 @@ /* Run the user supplied parser for an assignment */ static int next_assignment(const char *filename, unsigned line, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) { assert(filename && t && lvalue && rvalue); - + for (; t->parse; t++) if (!strcmp(lvalue, t->lvalue)) return t->parse(filename, line, lvalue, rvalue, t->data, userdata); pa_log("[%s:%u] Unknown lvalue '%s'.", filename, line, lvalue); - + return -1; } /* Returns non-zero when c is contained in s */ static int in_string(char c, const char *s) { assert(s); - + for (; *s; s++) if (*s == c) return 1; - + return 0; } @@ -85,7 +85,7 @@ static int parse_line(const char *filename, unsigned line, const pa_config_item if ((c = strpbrk(b, COMMENTS))) *c = 0; - + if (!*b) return 0; @@ -106,13 +106,13 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void unsigned line = 0; int do_close = !f; assert(filename && t); - + if (!f && !(f = fopen(filename, "r"))) { if (errno == ENOENT) { r = 0; goto finish; } - + pa_log_warn("WARNING: failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; @@ -123,23 +123,23 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void if (!fgets(l, sizeof(l), f)) { if (feof(f)) break; - + pa_log_warn("WARNING: failed to read configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } - + if (parse_line(filename, ++line, t, l, userdata) < 0) goto finish; } - + r = 0; - + finish: if (do_close && f) fclose(f); - + return r; } @@ -152,22 +152,22 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); return -1; } - + *i = (int) k; - return 0; + return 0; } int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { int *b = data, k; assert(filename && lvalue && rvalue && data); - + if ((k = pa_parse_boolean(rvalue)) < 0) { pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue); return -1; } - + *b = k; - + return 0; } diff --git a/src/pulsecore/core-def.h b/src/pulsecore/core-def.h index 718499d12..f849a6f64 100644 --- a/src/pulsecore/core-def.h +++ b/src/pulsecore/core-def.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/core-error.c b/src/pulsecore/core-error.c index 61878c9ed..2362068f1 100644 --- a/src/pulsecore/core-error.c +++ b/src/pulsecore/core-error.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/core-error.h b/src/pulsecore/core-error.h index 32da8bf2b..e43908339 100644 --- a/src/pulsecore/core-error.h +++ b/src/pulsecore/core-error.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c index e3bf3ca21..26c493ca5 100644 --- a/src/pulsecore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -94,7 +94,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { pa_memblock_unref(e->memchunk.memblock); pa_xfree(e->filename); - + assert(e->core == c); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); @@ -178,7 +178,7 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3 if (pa_sound_file_load(c->mempool, filename, &ss, &map, &chunk) < 0) return -1; - + r = pa_scache_add_item(c, name, &ss, &map, &chunk, idx); pa_memblock_unref(chunk.memblock); @@ -202,7 +202,7 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, e->lazy = 1; e->filename = pa_xstrdup(filename); - + if (!c->scache_auto_unload_event) { struct timeval ntv; pa_gettimeofday(&ntv); @@ -252,7 +252,7 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t pa_scache_entry *e; char *t; pa_cvolume r; - + assert(c); assert(name); assert(sink); @@ -269,7 +269,7 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t if (e->volume.channels > e->sample_spec.channels) e->volume.channels = e->sample_spec.channels; } - + if (!e->memchunk.memblock) return -1; @@ -287,7 +287,7 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t if (e->lazy) time(&e->last_used_time); - + return 0; } @@ -318,7 +318,7 @@ uint32_t pa_scache_total_size(pa_core *c) { if (!c->scache || !pa_idxset_size(c->scache)) return 0; - + for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) if (e->memchunk.memblock) sum += e->memchunk.length; @@ -334,7 +334,7 @@ void pa_scache_unload_unused(pa_core *c) { if (!c->scache || !pa_idxset_size(c->scache)) return; - + time(&now); for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) { @@ -344,7 +344,7 @@ void pa_scache_unload_unused(pa_core *c) { if (e->last_used_time + c->scache_idle_time > now) continue; - + pa_memblock_unref(e->memchunk.memblock); e->memchunk.memblock = NULL; e->memchunk.index = e->memchunk.length = 0; @@ -358,7 +358,7 @@ static void add_file(pa_core *c, const char *pathname) { const char *e; e = pa_path_get_filename(pathname); - + if (stat(pathname, &st) < 0) { pa_log("stat('%s'): %s", pathname, pa_cstrerror(errno)); return; @@ -388,7 +388,7 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) { for (i = 0; i < p.gl_pathc; i++) add_file(c, p.gl_pathv[i]); - + globfree(&p); #else return -1; diff --git a/src/pulsecore/core-scache.h b/src/pulsecore/core-scache.h index d01aae9b1..69baabbc6 100644 --- a/src/pulsecore/core-scache.h +++ b/src/pulsecore/core-scache.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -32,14 +32,14 @@ typedef struct pa_scache_entry { pa_core *core; uint32_t index; char *name; - + pa_cvolume volume; pa_sample_spec sample_spec; pa_channel_map channel_map; pa_memchunk memchunk; char *filename; - + int lazy; time_t last_used_time; } pa_scache_entry; diff --git a/src/pulsecore/core-subscribe.c b/src/pulsecore/core-subscribe.c index 4df1d5112..5a958b839 100644 --- a/src/pulsecore/core-subscribe.c +++ b/src/pulsecore/core-subscribe.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -65,7 +65,7 @@ static void sched_event(pa_core *c); /* Allocate a new subscription object for the given subscription mask. Use the specified callback function and user data */ pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_subscription_cb_t callback, void *userdata) { pa_subscription *s; - + assert(c); assert(m); assert(callback); @@ -85,7 +85,7 @@ pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_su void pa_subscription_free(pa_subscription*s) { assert(s); assert(!s->dead); - + s->dead = 1; sched_event(s->core); } @@ -104,7 +104,7 @@ static void free_event(pa_subscription_event *s) { if (!s->next) s->core->subscription_event_last = s->prev; - + PA_LLIST_REMOVE(pa_subscription_event, s->core->subscription_event_queue, s); pa_xfree(s); } @@ -112,7 +112,7 @@ static void free_event(pa_subscription_event *s) { /* Free all subscription objects */ void pa_subscription_free_all(pa_core *c) { assert(c); - + while (c->subscriptions) free_subscription(c->subscriptions); @@ -157,7 +157,7 @@ static void dump_event(const char * prefix, pa_subscription_event*e) { static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) { pa_core *c = userdata; pa_subscription *s; - + assert(c->mainloop == m); assert(c); assert(c->subscription_defer_event == de); @@ -170,7 +170,7 @@ static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) { pa_subscription_event *e = c->subscription_event_queue; for (s = c->subscriptions; s; s = s->next) { - + if (!s->dead && pa_subscription_match_flags(s->mask, e->type)) s->callback(c, e->type, e->index, s->userdata); } @@ -182,7 +182,7 @@ static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) { } /* Remove dead subscriptions */ - + s = c->subscriptions; while (s) { pa_subscription *n = s->next; @@ -200,7 +200,7 @@ static void sched_event(pa_core *c) { c->subscription_defer_event = c->mainloop->defer_new(c->mainloop, defer_cb, c); assert(c->subscription_defer_event); } - + c->mainloop->defer_enable(c->subscription_defer_event, 1); } @@ -212,18 +212,18 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i /* No need for queuing subscriptions of noone is listening */ if (!c->subscriptions) return; - + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_NEW) { pa_subscription_event *i, *n; - + /* Check for duplicates */ for (i = c->subscription_event_last; i; i = n) { n = i->prev; - + /* not the same object type */ if (((t ^ i->type) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)) continue; - + /* not the same object */ if (i->index != index) continue; @@ -253,7 +253,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i e->type = t; e->index = index; - PA_LLIST_INSERT_AFTER(pa_subscription_event, c->subscription_event_queue, c->subscription_event_last, e); + PA_LLIST_INSERT_AFTER(pa_subscription_event, c->subscription_event_queue, c->subscription_event_last, e); c->subscription_event_last = e; #ifdef DEBUG diff --git a/src/pulsecore/core-subscribe.h b/src/pulsecore/core-subscribe.h index 6e3b646eb..875cf331b 100644 --- a/src/pulsecore/core-subscribe.h +++ b/src/pulsecore/core-subscribe.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 5f72b3428..b42dc0caa 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -139,7 +139,7 @@ void pa_make_nonblock_fd(int fd) { int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { struct stat st; int r; - + assert(dir); #ifdef OS_IS_WIN32 @@ -152,7 +152,7 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { umask(u); } #endif - + if (r < 0 && errno != EEXIST) return -1; @@ -163,18 +163,18 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { gid = getgid(); chown(dir, uid, gid); #endif - + #ifdef HAVE_CHMOD chmod(dir, m); #endif - + #ifdef HAVE_LSTAT if (lstat(dir, &st) < 0) #else if (stat(dir, &st) < 0) #endif goto fail; - + #ifndef OS_IS_WIN32 if (!S_ISDIR(st.st_mode) || (st.st_uid != uid) || @@ -186,9 +186,9 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { #else pa_log_warn("secure directory creation not supported on Win32."); #endif - + return 0; - + fail: rmdir(dir); return -1; @@ -214,12 +214,12 @@ int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) { if (!(dir = pa_parent_dir(fn))) goto finish; - + if (pa_make_secure_dir(dir, m, uid, gid) < 0) goto finish; ret = 0; - + finish: pa_xfree(dir); return ret; @@ -237,7 +237,7 @@ ssize_t pa_read(int fd, void *buf, size_t count, int *type) { if (!type || *type == 0) { ssize_t r; - + if ((r = recv(fd, buf, count, 0)) >= 0) return r; @@ -251,7 +251,7 @@ ssize_t pa_read(int fd, void *buf, size_t count, int *type) { } #endif - + return read(fd, buf, count); } @@ -263,7 +263,7 @@ ssize_t pa_write(int fd, const void *buf, size_t count, int *type) { if ((r = send(fd, buf, count, MSG_NOSIGNAL)) >= 0) return r; - + #ifdef OS_IS_WIN32 if (WSAGetLastError() != WSAENOTSOCK) { errno = WSAGetLastError(); @@ -286,7 +286,7 @@ ssize_t pa_write(int fd, const void *buf, size_t count, int *type) { ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) { ssize_t ret = 0; int _type; - + assert(fd >= 0); assert(data); assert(size); @@ -304,7 +304,7 @@ ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) { if (r == 0) break; - + ret += r; data = (uint8_t*) data + r; size -= r; @@ -335,7 +335,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) { if (r == 0) break; - + ret += r; data = (const uint8_t*) data + r; size -= r; @@ -354,8 +354,8 @@ void pa_check_signal_is_blocked(int sig) { /* If POSIX threads are supported use thread-aware * pthread_sigmask() function, to check if the signal is * blocked. Otherwise fall back to sigprocmask() */ - -#ifdef HAVE_PTHREAD + +#ifdef HAVE_PTHREAD if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) { #endif if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) { @@ -370,15 +370,15 @@ void pa_check_signal_is_blocked(int sig) { return; /* Check whether the signal is trapped */ - + if (sigaction(sig, NULL, &sa) < 0) { pa_log("sigaction(): %s", pa_cstrerror(errno)); return; } - + if (sa.sa_handler != SIG_DFL) return; - + pa_log("WARNING: %s is not trapped. This might cause malfunction!", pa_strsignal(sig)); #else /* HAVE_SIGACTION */ pa_log("WARNING: %s might not be trapped. This might cause malfunction!", pa_strsignal(sig)); @@ -390,9 +390,9 @@ void pa_check_signal_is_blocked(int sig) { char *pa_sprintf_malloc(const char *format, ...) { int size = 100; char *c = NULL; - + assert(format); - + for(;;) { int r; va_list ap; @@ -402,12 +402,12 @@ char *pa_sprintf_malloc(const char *format, ...) { va_start(ap, format); r = vsnprintf(c, size, format, ap); va_end(ap); - + if (r > -1 && r < size) return c; if (r > -1) /* glibc 2.1 */ - size = r+1; + size = r+1; else /* glibc 2.0 */ size *= 2; } @@ -418,9 +418,9 @@ char *pa_sprintf_malloc(const char *format, ...) { char *pa_vsprintf_malloc(const char *format, va_list ap) { int size = 100; char *c = NULL; - + assert(format); - + for(;;) { int r; va_list aq; @@ -431,12 +431,12 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) { r = vsnprintf(c, size, format, aq); va_end(aq); - + if (r > -1 && r < size) return c; if (r > -1) /* glibc 2.1 */ - size = r+1; + size = r+1; else /* glibc 2.0 */ size *= 2; } @@ -461,10 +461,10 @@ void pa_raise_priority(void) { #ifdef HAVE_SYS_RESOURCE_H if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) pa_log_warn("setpriority(): %s", pa_cstrerror(errno)); - else - pa_log_info("Successfully gained nice level %i.", NICE_LEVEL); + else + pa_log_info("Successfully gained nice level %i.", NICE_LEVEL); #endif - + #ifdef _POSIX_PRIORITY_SCHEDULING { struct sched_param sp; @@ -473,14 +473,14 @@ void pa_raise_priority(void) { pa_log("sched_getparam(): %s", pa_cstrerror(errno)); return; } - + sp.sched_priority = 1; if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) { pa_log_warn("sched_setscheduler(): %s", pa_cstrerror(errno)); return; } - pa_log_info("Successfully enabled SCHED_FIFO scheduling."); + pa_log_info("Successfully enabled SCHED_FIFO scheduling."); } #endif @@ -488,7 +488,7 @@ void pa_raise_priority(void) { if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError()); else - pa_log_info("Successfully gained high priority class."); + pa_log_info("Successfully gained high priority class."); #endif } @@ -521,19 +521,19 @@ int pa_fd_set_cloexec(int fd, int b) { if ((v = fcntl(fd, F_GETFD, 0)) < 0) return -1; - + v = (v & ~FD_CLOEXEC) | (b ? FD_CLOEXEC : 0); - + if (fcntl(fd, F_SETFD, v) < 0) return -1; -#endif +#endif return 0; } /* Try to parse a boolean string value.*/ int pa_parse_boolean(const char *v) { - + if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on")) return 1; else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off")) @@ -552,7 +552,7 @@ char *pa_split(const char *c, const char *delimiter, const char**state) { if (!*current) return NULL; - + l = strcspn(current, delimiter); *state = current+l; @@ -632,7 +632,7 @@ static int is_group(gid_t gid, const char *name) { } r = strcmp(name, result->gr_name) == 0; - + finish: pa_xfree(data); #else @@ -647,7 +647,7 @@ finish: finish: #endif - + return r; } @@ -658,9 +658,9 @@ int pa_own_uid_in_group(const char *name, gid_t *gid) { int r = -1, i; assert(n > 0); - + gids = pa_xmalloc(sizeof(GETGROUPS_T)*n); - + if ((n = getgroups(n, gids)) < 0) { pa_log("getgroups(): %s", pa_cstrerror(errno)); goto finish; @@ -681,7 +681,7 @@ int pa_own_uid_in_group(const char *name, gid_t *gid) { } r = 0; - + finish: pa_xfree(gids); @@ -695,20 +695,20 @@ int pa_uid_in_group(uid_t uid, const char *name) { struct group grbuf, *gr; char **i; int r = -1; - + g_n = sysconf(_SC_GETGR_R_SIZE_MAX); g_buf = pa_xmalloc(g_n); p_n = sysconf(_SC_GETPW_R_SIZE_MAX); p_buf = pa_xmalloc(p_n); - + if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) goto finish; r = 0; for (i = gr->gr_mem; *i; i++) { struct passwd pwbuf, *pw; - + if (getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw) != 0 || !pw) continue; @@ -763,7 +763,7 @@ int pa_check_in_group(gid_t g) { int pa_own_uid_in_group(const char *name, gid_t *gid) { return -1; - + } int pa_uid_in_group(uid_t uid, const char *name) { @@ -787,7 +787,7 @@ int pa_lock_fd(int fd, int b) { struct flock flock; /* Try a R/W lock first */ - + flock.l_type = b ? F_WRLCK : F_UNLCK; flock.l_whence = SEEK_SET; flock.l_start = 0; @@ -802,7 +802,7 @@ int pa_lock_fd(int fd, int b) { if (fcntl(fd, F_SETLKW, &flock) >= 0) return 0; } - + pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno)); #endif @@ -836,18 +836,18 @@ int pa_lock_lockfile(const char *fn) { for (;;) { struct stat st; - + if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { pa_log("failed to create lock file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } - + if (pa_lock_fd(fd, 1) < 0) { pa_log("failed to lock file '%s'.", fn); goto fail; } - + if (fstat(fd, &st) < 0) { pa_log("failed to fstat() file '%s'.", fn); goto fail; @@ -856,12 +856,12 @@ int pa_lock_lockfile(const char *fn) { /* Check wheter the file has been removed meanwhile. When yes, restart this loop, otherwise, we're done */ if (st.st_nlink >= 1) break; - + if (pa_lock_fd(fd, 0) < 0) { pa_log("failed to unlock file '%s'.", fn); goto fail; } - + if (close(fd) < 0) { pa_log("failed to close file '%s'.", fn); goto fail; @@ -869,7 +869,7 @@ int pa_lock_lockfile(const char *fn) { fd = -1; } - + return fd; fail: @@ -890,7 +890,7 @@ int pa_unlock_lockfile(const char *fn, int fd) { fn, pa_cstrerror(errno)); r = -1; } - + if (pa_lock_fd(fd, 0) < 0) { pa_log_warn("WARNING: failed to unlock file '%s'.", fn); r = -1; @@ -946,20 +946,20 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env if (lfn) { FILE *f; - + #ifdef OS_IS_WIN32 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) return NULL; fn = buf; #endif - + if ((f = fopen(fn, mode)) || errno != ENOENT) { if (result) *result = pa_xstrdup(fn); pa_xfree(lfn); return f; } - + pa_xfree(lfn); } } @@ -979,10 +979,10 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env if (result) *result = pa_xstrdup(global); - + return fopen(global, mode); } - + /* Format the specified data as a hexademical string */ char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) { size_t i = 0, j = 0; @@ -1025,7 +1025,7 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) { if ((b = hexc(*(p++))) < 0) return (size_t) -1; - + d[j] = (uint8_t) (b << 4); if (!*p) @@ -1044,10 +1044,10 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) { /* Returns nonzero when *s starts with *pfx */ int pa_startswith(const char *s, const char *pfx) { size_t l; - + assert(s); assert(pfx); - + l = strlen(pfx); return strlen(s) >= l && strncmp(s, pfx, l) == 0; @@ -1056,10 +1056,10 @@ int pa_startswith(const char *s, const char *pfx) { /* Returns nonzero when *s ends with *sfx */ int pa_endswith(const char *s, const char *sfx) { size_t l1, l2; - + assert(s); assert(sfx); - + l1 = strlen(s); l2 = strlen(sfx); @@ -1081,20 +1081,20 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) { if ((e = getenv("PULSE_RUNTIME_PATH"))) { - if (fn) + if (fn) snprintf(s, l, "%s%c%s", e, PATH_SEP, fn); else snprintf(s, l, "%s", e); - + } else { char u[256]; - - if (fn) + + if (fn) snprintf(s, l, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn); else snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u))); } - + #ifdef OS_IS_WIN32 { @@ -1119,7 +1119,7 @@ int pa_atoi(const char *s, int32_t *ret_i) { return -1; *ret_i = (int32_t) l; - + return 0; } @@ -1135,6 +1135,6 @@ int pa_atou(const char *s, uint32_t *ret_u) { return -1; *ret_u = (uint32_t) l; - + return 0; } diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index ba3259686..b2608edd0 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 63ee60ca8..b19b1974b 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -116,7 +116,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { pa_property_init(c); pa_random(&c->cookie, sizeof(c->cookie)); - + #ifdef SIGPIPE pa_check_signal_is_blocked(SIGPIPE); #endif @@ -131,16 +131,16 @@ void pa_core_free(pa_core *c) { assert(pa_idxset_isempty(c->clients)); pa_idxset_free(c->clients, NULL, NULL); - + assert(pa_idxset_isempty(c->sinks)); pa_idxset_free(c->sinks, NULL, NULL); assert(pa_idxset_isempty(c->sources)); pa_idxset_free(c->sources, NULL, NULL); - + assert(pa_idxset_isempty(c->source_outputs)); pa_idxset_free(c->source_outputs, NULL, NULL); - + assert(pa_idxset_isempty(c->sink_inputs)); pa_idxset_free(c->sink_inputs, NULL, NULL); @@ -163,8 +163,8 @@ void pa_core_free(pa_core *c) { pa_hook_free(&c->hook_sink_disconnect); pa_hook_free(&c->hook_source_output_new); pa_hook_free(&c->hook_source_disconnect); - - pa_xfree(c); + + pa_xfree(c); } static void quit_callback(pa_mainloop_api*m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 3a34d297a..c1c6a19c2 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -46,7 +46,7 @@ struct pa_core { /* A random value which may be used to identify this instance of * PulseAudio. Not cryptographically secure in any way. */ uint32_t cookie; - + pa_mainloop_api *mainloop; /* idxset of all kinds of entities */ diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h index d92ce5989..5ad880a01 100644 --- a/src/pulsecore/creds.h +++ b/src/pulsecore/creds.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/dynarray.c b/src/pulsecore/dynarray.c index cd1fcb0fd..91a9d5e10 100644 --- a/src/pulsecore/dynarray.c +++ b/src/pulsecore/dynarray.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/dynarray.h b/src/pulsecore/dynarray.h index 4ddb526ca..216d87662 100644 --- a/src/pulsecore/dynarray.h +++ b/src/pulsecore/dynarray.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h index 65db3feb3..c01930140 100644 --- a/src/pulsecore/endianmacros.h +++ b/src/pulsecore/endianmacros.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/esound.h b/src/pulsecore/esound.h index 9d44f65c7..0ea201b62 100644 --- a/src/pulsecore/esound.h +++ b/src/pulsecore/esound.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c index cfeeac22f..5091bfd1e 100644 --- a/src/pulsecore/flist.c +++ b/src/pulsecore/flist.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -111,12 +111,12 @@ pa_flist *pa_flist_new(unsigned size) { size = FLIST_SIZE; assert(is_power_of_two(size)); - + l = pa_xnew(pa_flist, 1); l->size = size; l->cells = pa_xnew0(struct cell, size); - + pa_atomic_store(&l->read_idx, 0); pa_atomic_store(&l->write_idx, 0); pa_atomic_store(&l->length, 0); @@ -133,10 +133,10 @@ void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) { if (free_cb) { int len, idx; - + idx = reduce(l, pa_atomic_load(&l->read_idx)); len = pa_atomic_load(&l->length); - + for (; len > 0; len--) { if (pa_atomic_load(&l->cells[idx].state) == STATE_USED) @@ -152,7 +152,7 @@ void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) { int pa_flist_push(pa_flist*l, void *p) { int idx, len, n; - + assert(l); assert(p); @@ -183,13 +183,13 @@ int pa_flist_push(pa_flist*l, void *p) { if (len > N_EXTRA_SCAN) pa_log("WARNING: Didn't find free cell after %u iterations.", len); #endif - + return -1; } void* pa_flist_pop(pa_flist*l) { int idx, len, n; - + assert(l); n = len = pa_atomic_load(&l->length) + N_EXTRA_SCAN; @@ -221,6 +221,6 @@ void* pa_flist_pop(pa_flist*l) { if (len > N_EXTRA_SCAN) pa_log("WARNING: Didn't find used cell after %u iterations.", len); #endif - + return NULL; } diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h index 57c9598b2..9871f32d6 100644 --- a/src/pulsecore/flist.h +++ b/src/pulsecore/flist.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/g711.h b/src/pulsecore/g711.h index 97cedf814..b5c9e6a2c 100644 --- a/src/pulsecore/g711.h +++ b/src/pulsecore/g711.h @@ -33,7 +33,7 @@ extern int16_t _st_ulaw2linear16[256]; #define st_14linear2ulaw(sw) (_st_14linear2ulaw[(sw + 0x2000)]) #define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc]) #else -unsigned char st_14linear2ulaw(int16_t pcm_val); +unsigned char st_14linear2ulaw(int16_t pcm_val); int16_t st_ulaw2linear16(unsigned char); #endif diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h index 8825700ad..87f7eece5 100644 --- a/src/pulsecore/gccmacro.h +++ b/src/pulsecore/gccmacro.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c index 81a160a69..809eaeec3 100644 --- a/src/pulsecore/hashmap.c +++ b/src/pulsecore/hashmap.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -47,7 +47,7 @@ struct pa_hashmap { unsigned size; struct hashmap_entry **data; struct hashmap_entry *first_entry; - + unsigned n_entries; pa_hash_func_t hash_func; pa_compare_func_t compare_func; @@ -55,14 +55,14 @@ struct pa_hashmap { pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) { pa_hashmap *h; - + h = pa_xnew(pa_hashmap, 1); h->data = pa_xnew0(struct hashmap_entry*, h->size = BUCKETS); h->first_entry = NULL; h->n_entries = 0; h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; h->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; - + return h; } @@ -98,7 +98,7 @@ void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), v free_func(h->first_entry->value, userdata); remove(h, h->first_entry); } - + pa_xfree(h->data); pa_xfree(h); } @@ -124,24 +124,24 @@ int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) { if ((e = get(h, hash, key))) return -1; - + e = pa_xnew(struct hashmap_entry, 1); e->hash = hash; e->key = key; e->value = value; - + e->previous = NULL; e->next = h->first_entry; if (h->first_entry) h->first_entry->previous = e; h->first_entry = e; - + e->bucket_previous = NULL; e->bucket_next = h->data[hash]; if (h->data[hash]) h->data[hash]->bucket_previous = e; h->data[hash] = e; - + h->n_entries ++; return 0; } @@ -164,7 +164,7 @@ void* pa_hashmap_remove(pa_hashmap *h, const void *key) { struct hashmap_entry *e; unsigned hash; void *data; - + assert(h); hash = h->hash_func(key) % h->size; @@ -185,7 +185,7 @@ void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) { assert(h); assert(state); - if (!*state) + if (!*state) *state = h->first_entry; else *state = ((struct hashmap_entry*) *state)->next; @@ -198,13 +198,13 @@ void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) { if (key) *key = ((struct hashmap_entry*) *state)->key; - + return ((struct hashmap_entry*) *state)->value; } void* pa_hashmap_steal_first(pa_hashmap *h) { void *data; - + assert(h); if (!h->first_entry) diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h index b8a358ec6..18e41cf3f 100644 --- a/src/pulsecore/hashmap.h +++ b/src/pulsecore/hashmap.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/hook-list.c b/src/pulsecore/hook-list.c index 91c2598b7..40f6b4355 100644 --- a/src/pulsecore/hook-list.c +++ b/src/pulsecore/hook-list.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -36,9 +36,9 @@ static void slot_free(pa_hook *hook, pa_hook_slot *slot) { if (hook->last == slot) hook->last = slot->prev; - + PA_LLIST_REMOVE(pa_hook_slot, hook->slots, slot); - + pa_xfree(slot); } @@ -48,13 +48,13 @@ void pa_hook_free(pa_hook *hook) { while (hook->slots) slot_free(hook, hook->slots); - + pa_hook_init(hook, NULL); } pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *data) { pa_hook_slot *slot; - + assert(cb); slot = pa_xnew(pa_hook_slot, 1); @@ -62,17 +62,17 @@ pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *data) { slot->dead = 0; slot->callback = cb; slot->data = data; - + PA_LLIST_INSERT_AFTER(pa_hook_slot, hook->slots, hook->last, slot); hook->last = slot; - + return slot; } void pa_hook_slot_free(pa_hook_slot *slot) { assert(slot); assert(!slot->dead); - + if (slot->hook->firing > 0) { slot->dead = 1; slot->hook->n_dead++; @@ -83,7 +83,7 @@ void pa_hook_slot_free(pa_hook_slot *slot) { pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) { pa_hook_slot *slot, *next; pa_hook_result_t result = PA_HOOK_OK; - + assert(hook); hook->firing ++; @@ -91,16 +91,16 @@ pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) { for (slot = hook->slots; slot; slot = slot->next) { if (slot->dead) continue; - + if ((result = slot->callback(hook->data, data, slot->data)) != PA_HOOK_OK) break; } - + hook->firing --; - + for (slot = hook->slots; hook->n_dead > 0 && slot; slot = next) { next = slot->next; - + if (slot->dead) { slot_free(hook, slot); hook->n_dead--; diff --git a/src/pulsecore/hook-list.h b/src/pulsecore/hook-list.h index 67e5d1ae2..9a219a90b 100644 --- a/src/pulsecore/hook-list.h +++ b/src/pulsecore/hook-list.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c index ee0137a3d..dce51e210 100644 --- a/src/pulsecore/idxset.c +++ b/src/pulsecore/idxset.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -44,7 +44,7 @@ typedef struct idxset_entry { struct pa_idxset { pa_hash_func_t hash_func; pa_compare_func_t compare_func; - + unsigned hash_table_size, n_entries; idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail; uint32_t index, start_index, array_size; @@ -53,7 +53,7 @@ struct pa_idxset { unsigned pa_idxset_string_hash_func(const void *p) { unsigned hash = 0; const char *c; - + for (c = p; *c; c++) hash = 31 * hash + *c; @@ -97,7 +97,7 @@ void pa_idxset_free(pa_idxset *s, void (*free_func) (void *p, void *userdata), v while (s->iterate_list_head) { idxset_entry *e = s->iterate_list_head; s->iterate_list_head = s->iterate_list_head->iterate_next; - + if (free_func) free_func(e->data, userdata); pa_xfree(e); @@ -133,12 +133,12 @@ static void extend_array(pa_idxset *s, uint32_t idx) { l = idx - s->start_index - i + 100; n = pa_xnew0(idxset_entry*, l); - + for (j = 0; j < s->array_size-i; j++) n[j] = s->array[i+j]; pa_xfree(s->array); - + s->array = n; s->array_size = l; s->start_index += i; @@ -147,17 +147,17 @@ static void extend_array(pa_idxset *s, uint32_t idx) { static idxset_entry** array_index(pa_idxset*s, uint32_t idx) { if (idx >= s->start_index + s->array_size) return NULL; - + if (idx < s->start_index) return NULL; - + return s->array + idx - s->start_index; } int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { unsigned h; idxset_entry *e, **a; - + assert(s); assert(p); @@ -168,7 +168,7 @@ int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { if ((e = hash_scan(s, s->hash_table[h], p))) { if (idx) *idx = e->index; - + return -1; } @@ -201,10 +201,10 @@ int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { s->iterate_list_head = e; } s->iterate_list_tail = e; - + s->n_entries++; assert(s->n_entries >= 1); - + if (idx) *idx = e->index; @@ -214,7 +214,7 @@ int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { void* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx) { idxset_entry **a; assert(s); - + if (!(a = array_index(s, idx))) return NULL; @@ -228,7 +228,7 @@ void* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx) { unsigned h; idxset_entry *e; assert(s && p); - + assert(s->hash_func); h = s->hash_func(p) % s->hash_table_size; @@ -250,13 +250,13 @@ static void remove_entry(pa_idxset *s, idxset_entry *e) { a = array_index(s, e->index); assert(a && *a && *a == e); *a = NULL; - + /* Remove from linked list */ if (e->iterate_next) e->iterate_next->iterate_prev = e->iterate_prev; else s->iterate_list_tail = e->iterate_prev; - + if (e->iterate_prev) e->iterate_prev->iterate_next = e->iterate_next; else @@ -280,7 +280,7 @@ static void remove_entry(pa_idxset *s, idxset_entry *e) { void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) { idxset_entry **a; void *data; - + assert(s); if (!(a = array_index(s, idx))) @@ -291,15 +291,15 @@ void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) { data = (*a)->data; remove_entry(s, *a); - - return data; + + return data; } void* pa_idxset_remove_by_data(pa_idxset*s, const void *data, uint32_t *idx) { idxset_entry *e; unsigned h; void *r; - + assert(s->hash_func); h = s->hash_func(data) % s->hash_table_size; @@ -328,7 +328,7 @@ void* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx) { if (!e) return NULL; - + *idx = e->index; return e->data; } @@ -351,7 +351,7 @@ void *pa_idxset_next(pa_idxset *s, uint32_t *idx) { if ((a = array_index(s, *idx)) && *a) e = (*a)->iterate_next; - + if (e) { *idx = e->index; return e->data; @@ -380,7 +380,7 @@ int pa_idxset_foreach(pa_idxset*s, int (*func)(void *p, uint32_t idx, int *del, e = n; } - + return 0; } diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h index 1765e843c..0d751e079 100644 --- a/src/pulsecore/idxset.h +++ b/src/pulsecore/idxset.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/inet_ntop.c b/src/pulsecore/inet_ntop.c index 483c3e262..5d7a543ef 100644 --- a/src/pulsecore/inet_ntop.c +++ b/src/pulsecore/inet_ntop.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/inet_pton.c b/src/pulsecore/inet_pton.c index 7b6bbc31d..42bb53879 100644 --- a/src/pulsecore/inet_pton.c +++ b/src/pulsecore/inet_pton.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index af732c26c..b40f0aa10 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -54,11 +54,11 @@ struct pa_iochannel { pa_iochannel_cb_t callback; void*userdata; - + int readable; int writable; int hungup; - + int no_close; pa_io_event* input_event, *output_event; @@ -70,7 +70,7 @@ static void enable_mainloop_sources(pa_iochannel *io) { if (io->input_event == io->output_event && io->input_event) { pa_io_event_flags_t f = PA_IO_EVENT_NULL; assert(io->input_event); - + if (!io->readable) f |= PA_IO_EVENT_INPUT; if (!io->writable) @@ -88,7 +88,7 @@ static void enable_mainloop_sources(pa_iochannel *io) { static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { pa_iochannel *io = userdata; int changed = 0; - + assert(m); assert(e); assert(fd >= 0); @@ -104,7 +104,7 @@ static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_fla changed = 1; assert(e == io->input_event); } - + if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) { io->writable = 1; changed = 1; @@ -113,7 +113,7 @@ static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_fla if (changed) { enable_mainloop_sources(io); - + if (io->callback) io->callback(io, io->userdata); } @@ -121,7 +121,7 @@ static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_fla pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) { pa_iochannel *io; - + assert(m); assert(ifd >= 0 || ofd >= 0); @@ -165,42 +165,42 @@ void pa_iochannel_free(pa_iochannel*io) { if (io->input_event) io->mainloop->io_free(io->input_event); - + if (io->output_event && (io->output_event != io->input_event)) io->mainloop->io_free(io->output_event); if (!io->no_close) { if (io->ifd >= 0) - + close(io->ifd); if (io->ofd >= 0 && io->ofd != io->ifd) close(io->ofd); } - + pa_xfree(io); } int pa_iochannel_is_readable(pa_iochannel*io) { assert(io); - + return io->readable || io->hungup; } int pa_iochannel_is_writable(pa_iochannel*io) { assert(io); - + return io->writable && !io->hungup; } int pa_iochannel_is_hungup(pa_iochannel*io) { assert(io); - + return io->hungup; } ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) { ssize_t r; - + assert(io); assert(data); assert(l); @@ -217,7 +217,7 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) { ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { ssize_t r; - + assert(io); assert(data); assert(io->ifd >= 0); @@ -236,13 +236,13 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { int pa_iochannel_creds_supported(pa_iochannel *io) { struct sockaddr_un sa; socklen_t l; - + assert(io); assert(io->ifd >= 0); assert(io->ofd == io->ifd); l = sizeof(sa); - + if (getsockname(io->ifd, (struct sockaddr*) &sa, &l) < 0) return 0; @@ -254,7 +254,7 @@ int pa_iochannel_creds_enable(pa_iochannel *io) { assert(io); assert(io->ifd >= 0); - + if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) { pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", pa_cstrerror(errno)); return -1; @@ -270,7 +270,7 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))]; struct ucred *u; struct cmsghdr *cmsg; - + assert(io); assert(data); assert(l); @@ -296,7 +296,7 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l u->uid = getuid(); u->gid = getgid(); } - + memset(&mh, 0, sizeof(mh)); mh.msg_name = NULL; mh.msg_namelen = 0; @@ -319,7 +319,7 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr struct msghdr mh; struct iovec iov; uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))]; - + assert(io); assert(data); assert(l); @@ -346,9 +346,9 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr struct cmsghdr *cmsg; *creds_valid = 0; - + for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { - + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { struct ucred u; assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))); @@ -364,7 +364,7 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr io->readable = 0; enable_mainloop_sources(io); } - + return r; } @@ -372,14 +372,14 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) { assert(io); - + io->callback = _callback; io->userdata = userdata; } void pa_iochannel_set_noclose(pa_iochannel*io, int b) { assert(io); - + io->no_close = b; } @@ -387,25 +387,25 @@ void pa_iochannel_socket_peer_to_string(pa_iochannel*io, char*s, size_t l) { assert(io); assert(s); assert(l); - + pa_socket_peer_to_string(io->ifd, s, l); } int pa_iochannel_socket_set_rcvbuf(pa_iochannel *io, size_t l) { assert(io); - + return pa_socket_set_rcvbuf(io->ifd, l); } int pa_iochannel_socket_set_sndbuf(pa_iochannel *io, size_t l) { assert(io); - + return pa_socket_set_sndbuf(io->ofd, l); } pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io) { assert(io); - + return io->mainloop; } diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h index 0e6d6d3af..147e7276f 100644 --- a/src/pulsecore/iochannel.h +++ b/src/pulsecore/iochannel.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c index a3bca22f9..2fe5c88d4 100644 --- a/src/pulsecore/ioline.c +++ b/src/pulsecore/ioline.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -64,7 +64,7 @@ static void defer_callback(pa_mainloop_api*m, pa_defer_event*e, void *userdata); pa_ioline* pa_ioline_new(pa_iochannel *io) { pa_ioline *l; assert(io); - + l = pa_xnew(pa_ioline, 1); l->io = io; l->dead = 0; @@ -85,9 +85,9 @@ pa_ioline* pa_ioline_new(pa_iochannel *io) { l->mainloop->defer_enable(l->defer_event, 0); l->defer_close = 0; - + pa_iochannel_set_callback(io, io_callback, l); - + return l; } @@ -126,7 +126,7 @@ void pa_ioline_close(pa_ioline *l) { assert(l->ref >= 1); l->dead = 1; - + if (l->io) { pa_iochannel_free(l->io); l->io = NULL; @@ -143,21 +143,21 @@ void pa_ioline_close(pa_ioline *l) { void pa_ioline_puts(pa_ioline *l, const char *c) { size_t len; - + assert(l); assert(l->ref >= 1); assert(c); if (l->dead) return; - + len = strlen(c); if (len > BUFFER_LIMIT - l->wbuf_valid_length) len = BUFFER_LIMIT - l->wbuf_valid_length; if (len) { assert(l->wbuf_length >= l->wbuf_valid_length); - + /* In case the allocated buffer is too small, enlarge it. */ if (l->wbuf_valid_length + len > l->wbuf_length) { size_t n = l->wbuf_valid_length+len; @@ -170,14 +170,14 @@ void pa_ioline_puts(pa_ioline *l, const char *c) { l->wbuf_length = n; l->wbuf_index = 0; } else if (l->wbuf_index + l->wbuf_valid_length + len > l->wbuf_length) { - + /* In case the allocated buffer fits, but the current index is too far from the start, move it to the front. */ memmove(l->wbuf, l->wbuf+l->wbuf_index, l->wbuf_valid_length); l->wbuf_index = 0; } - + assert(l->wbuf_index + l->wbuf_valid_length + len <= l->wbuf_length); - + /* Append the new string */ memcpy(l->wbuf + l->wbuf_index + l->wbuf_valid_length, c, len); l->wbuf_valid_length += len; @@ -189,7 +189,7 @@ void pa_ioline_puts(pa_ioline *l, const char *c) { void pa_ioline_set_callback(pa_ioline*l, void (*callback)(pa_ioline*io, const char *s, void *userdata), void *userdata) { assert(l); assert(l->ref >= 1); - + l->callback = callback; l->userdata = userdata; } @@ -213,7 +213,7 @@ static void failure(pa_ioline *l, int process_leftover) { l->callback(l, NULL, l->userdata); l->callback = NULL; } - + pa_ioline_close(l); } @@ -223,12 +223,12 @@ static void scan_for_lines(pa_ioline *l, size_t skip) { while (!l->dead && l->rbuf_valid_length > skip) { char *e, *p; size_t m; - + if (!(e = memchr(l->rbuf + l->rbuf_index + skip, '\n', l->rbuf_valid_length - skip))) break; *e = 0; - + p = l->rbuf + l->rbuf_index; m = strlen(p); @@ -260,14 +260,14 @@ static int do_read(pa_ioline *l) { size_t len; len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; - + /* Check if we have to enlarge the read buffer */ if (len < READ_SIZE) { size_t n = l->rbuf_valid_length+READ_SIZE; - + if (n >= BUFFER_LIMIT) n = BUFFER_LIMIT; - + if (l->rbuf_length >= n) { /* The current buffer is large enough, let's just move the data to the front */ if (l->rbuf_valid_length) @@ -281,14 +281,14 @@ static int do_read(pa_ioline *l) { l->rbuf = new; l->rbuf_length = n; } - + l->rbuf_index = 0; } - + len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; - + assert(len >= READ_SIZE); - + /* Read some data */ if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) { if (r < 0) { @@ -296,16 +296,16 @@ static int do_read(pa_ioline *l) { failure(l, 0); } else failure(l, 1); - + return -1; } - + l->rbuf_valid_length += r; - + /* Look if a line has been terminated in the newly read data */ scan_for_lines(l, l->rbuf_valid_length - r); } - + return 0; } @@ -315,21 +315,21 @@ static int do_write(pa_ioline *l) { assert(l && l->ref >= 1); while (!l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length) { - + if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) { pa_log("write(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); failure(l, 0); return -1; } - + l->wbuf_index += r; l->wbuf_valid_length -= r; - + /* A shortcut for the next time */ if (l->wbuf_valid_length == 0) l->wbuf_index = 0; } - + return 0; } @@ -341,7 +341,7 @@ static void do_work(pa_ioline *l) { pa_ioline_ref(l); l->mainloop->defer_enable(l->defer_event, 0); - + if (!l->dead) do_read(l); @@ -371,7 +371,7 @@ static void defer_callback(pa_mainloop_api*m, pa_defer_event*e, void *userdata) void pa_ioline_defer_close(pa_ioline *l) { assert(l); assert(l->ref >= 1); - + l->defer_close = 1; if (!l->wbuf_valid_length) @@ -381,7 +381,7 @@ void pa_ioline_defer_close(pa_ioline *l) { void pa_ioline_printf(pa_ioline *l, const char *format, ...) { char *t; va_list ap; - + assert(l); assert(l->ref >= 1); diff --git a/src/pulsecore/ioline.h b/src/pulsecore/ioline.h index e736e2b3b..8d3fb5f80 100644 --- a/src/pulsecore/ioline.h +++ b/src/pulsecore/ioline.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c index 36159fabf..2848b1698 100644 --- a/src/pulsecore/ipacl.c +++ b/src/pulsecore/ipacl.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -59,7 +59,7 @@ struct acl_entry { PA_LLIST_FIELDS(struct acl_entry); - int family; + int family; struct in_addr address_ipv4; struct in6_addr address_ipv6; int bits; @@ -75,10 +75,10 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { pa_ip_acl *acl; assert(s); - + acl = pa_xnew(pa_ip_acl, 1); PA_LLIST_HEAD_INIT(struct acl_entry, acl->entries); - + while ((a = pa_split(s, ";", &state))) { char *slash; struct acl_entry e, *n; @@ -97,7 +97,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { if (inet_pton(AF_INET, a, &e.address_ipv4) > 0) { e.bits = bits == (uint32_t) -1 ? 32 : (int) bits; - + if (e.bits > 32) { pa_log("number of bits out of range: %i", e.bits); goto fail; @@ -107,7 +107,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { if (e.bits < 32 && (uint32_t) (ntohl(e.address_ipv4.s_addr) << e.bits) != 0) pa_log_warn("WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); - + } else if (inet_pton(AF_INET6, a, &e.address_ipv6) > 0) { e.bits = bits == (uint32_t) -1 ? 128 : (int) bits; @@ -123,7 +123,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { for (i = 0, bits = e.bits; i < 16; i++) { - if (bits >= 8) + if (bits >= 8) bits -= 8; else { if ((uint8_t) ((e.address_ipv6.s6_addr[i]) << bits) != 0) { @@ -137,7 +137,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { if (t) pa_log_warn("WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); } - + } else { pa_log("failed to parse address: %s", a); goto fail; @@ -145,16 +145,16 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { n = pa_xmemdup(&e, sizeof(struct acl_entry)); PA_LLIST_PREPEND(struct acl_entry, acl->entries, n); - + pa_xfree(a); } return acl; - + fail: pa_xfree(a); pa_ip_acl_free(acl); - + return NULL; } @@ -166,7 +166,7 @@ void pa_ip_acl_free(pa_ip_acl *acl) { PA_LLIST_REMOVE(struct acl_entry, acl->entries, e); pa_xfree(e); } - + pa_xfree(acl); } @@ -174,7 +174,7 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { struct sockaddr_storage sa; struct acl_entry *e; socklen_t salen; - + assert(acl); assert(fd >= 0); @@ -190,7 +190,7 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { if (sa.ss_family == AF_INET6 && salen != sizeof(struct sockaddr_in6)) return -1; - + for (e = acl->entries; e; e = e->next) { if (e->family != sa.ss_family) @@ -198,7 +198,7 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { if (e->family == AF_INET) { struct sockaddr_in *sai = (struct sockaddr_in*) &sa; - + if (e->bits == 0 || /* this needs special handling because >> takes the right-hand side modulo 32 */ (ntohl(sai->sin_addr.s_addr ^ e->address_ipv4.s_addr) >> (32 - e->bits)) == 0) return 1; @@ -211,7 +211,7 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { if (e->bits == 0) return 1; - + for (i = 0, bits = e->bits; i < 16; i++) { if (bits >= 8) { diff --git a/src/pulsecore/ipacl.h b/src/pulsecore/ipacl.h index 7a4540ce9..61bf99b01 100644 --- a/src/pulsecore/ipacl.h +++ b/src/pulsecore/ipacl.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/llist.h b/src/pulsecore/llist.h index 312794312..49d261664 100644 --- a/src/pulsecore/llist.h +++ b/src/pulsecore/llist.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -75,7 +75,7 @@ do { \ assert(_head); \ while ((*_head)->prev) \ *_head = (*_head)->prev; \ -} while (0) +} while (0) #define PA_LLIST_INSERT_AFTER(t,head,a,b) \ do { \ @@ -92,7 +92,7 @@ do { \ _b->prev = _a; \ _a->next = _b; \ } \ -} while (0) - +} while (0) + #endif diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index ce0932211..7ad90383c 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -89,16 +89,16 @@ void pa_log_levelv_meta( const char *func, const char *format, va_list ap) { - + const char *e; char *text, *t, *n, *location; - + assert(level < PA_LOG_LEVEL_MAX); assert(format); if ((e = getenv(ENV_LOGLEVEL))) maximal_level = atoi(e); - + if (level > maximal_level) return; @@ -122,13 +122,13 @@ void pa_log_levelv_meta( if (!*t) continue; - + switch (log_target) { case PA_LOG_STDERR: { const char *prefix = "", *suffix = ""; char *local_t; -#ifndef OS_IS_WIN32 +#ifndef OS_IS_WIN32 /* Yes indeed. Useless, but fun! */ if (isatty(STDERR_FILENO)) { if (level <= PA_LOG_ERROR) { @@ -151,8 +151,8 @@ void pa_log_levelv_meta( break; } - -#ifdef HAVE_SYSLOG_H + +#ifdef HAVE_SYSLOG_H case PA_LOG_SYSLOG: { char *local_t; @@ -167,20 +167,20 @@ void pa_log_levelv_meta( } closelog(); - break; + break; } #endif - + case PA_LOG_USER: { char *x; x = pa_sprintf_malloc("%s%s", location, t); user_log_func(level, x); pa_xfree(x); - + break; } - + case PA_LOG_NULL: default: break; @@ -197,7 +197,7 @@ void pa_log_level_meta( int line, const char *func, const char *format, ...) { - + va_list ap; va_start(ap, format); pa_log_levelv_meta(level, file, line, func, format, ap); diff --git a/src/pulsecore/log.h b/src/pulsecore/log.h index bf0e75f51..728c25013 100644 --- a/src/pulsecore/log.h +++ b/src/pulsecore/log.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/mcalign.c b/src/pulsecore/mcalign.c index 9ede610d7..baf367843 100644 --- a/src/pulsecore/mcalign.c +++ b/src/pulsecore/mcalign.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -42,11 +42,11 @@ pa_mcalign *pa_mcalign_new(size_t base) { assert(base); m = pa_xnew(pa_mcalign, 1); - + m->base = base; pa_memchunk_reset(&m->leftover); pa_memchunk_reset(&m->current); - + return m; } @@ -58,22 +58,22 @@ void pa_mcalign_free(pa_mcalign *m) { if (m->current.memblock) pa_memblock_unref(m->current.memblock); - + pa_xfree(m); } void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { assert(m); assert(c); - + assert(c->memblock); assert(c->length > 0); assert(!m->current.memblock); - + /* Append to the leftover memory block */ if (m->leftover.memblock) { - + /* Try to merge */ if (m->leftover.memblock == c->memblock && m->leftover.index + m->leftover.length == c->index) { @@ -85,7 +85,7 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { if (m->leftover.length >= m->base) { m->current = m->leftover; pa_memchunk_reset(&m->leftover); - } + } } else { size_t l; @@ -93,7 +93,7 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { /* We have to copy */ assert(m->leftover.length < m->base); l = m->base - m->leftover.length; - + if (l > c->length) l = c->length; @@ -115,7 +115,7 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { } } else { /* Nothing to merge or copy, just store it */ - + if (c->length >= m->base) m->current = *c; else @@ -146,7 +146,7 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) { m->leftover = m->current; pa_memchunk_reset(&m->current); } - + return 0; } @@ -182,13 +182,13 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) { } pa_memchunk_reset(&m->current); - + return 0; } /* There's simply nothing */ return -1; - + } size_t pa_mcalign_csize(pa_mcalign *m, size_t l) { @@ -196,9 +196,9 @@ size_t pa_mcalign_csize(pa_mcalign *m, size_t l) { assert(l > 0); assert(!m->current.memblock); - + if (m->leftover.memblock) l += m->leftover.length; - + return (l/m->base)*m->base; } diff --git a/src/pulsecore/mcalign.h b/src/pulsecore/mcalign.h index 94e99e212..751eacd3e 100644 --- a/src/pulsecore/mcalign.h +++ b/src/pulsecore/mcalign.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -41,11 +41,11 @@ * for (;;) { * pa_memchunk input; * - * ... fill input ... + * ... fill input ... * * pa_mcalign_push(m, &input); * pa_memblock_unref(input.memblock); - * + * * for (;;) { * pa_memchunk output; * diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 9cfd79b5e..73874cf1a 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -71,7 +71,7 @@ struct memexport_slot { struct pa_memexport { pa_mempool *pool; - + struct memexport_slot slots[PA_MEMEXPORT_SLOTS_MAX]; PA_LLIST_HEAD(struct memexport_slot, free_slots); PA_LLIST_HEAD(struct memexport_slot, used_slots); @@ -101,7 +101,7 @@ struct pa_mempool { /* A list of free slots that may be reused */ PA_LLIST_HEAD(struct mempool_slot, free_slots); - + pa_mempool_stat stat; }; @@ -132,14 +132,14 @@ static void stat_remove(pa_memblock *b) { assert(AO_load_acquire_read(&b->pool->stat.n_allocated) > 0); assert(AO_load_acquire_read(&b->pool->stat.allocated_size) >= (AO_t) b->length); - + AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated); AO_fetch_and_add_release_write(&b->pool->stat.allocated_size, (AO_t) (-b->length)); if (b->type == PA_MEMBLOCK_IMPORTED) { assert(AO_load_acquire_read(&b->pool->stat.n_imported) > 0); assert(AO_load_acquire_read(&b->pool->stat.imported_size) >= (AO_t) b->length); - + AO_fetch_and_sub1_release_write(&b->pool->stat.n_imported); AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) (-b->length)); } @@ -151,10 +151,10 @@ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length); pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) { pa_memblock *b; - + assert(p); assert(length > 0); - + if (!(b = pa_memblock_new_pool(p, length))) b = memblock_new_appended(p, length); @@ -231,16 +231,16 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { if (!(slot = mempool_allocate_slot(p))) return NULL; - + b = mempool_slot_data(slot); b->type = PA_MEMBLOCK_POOL; b->data = (uint8_t*) b + sizeof(pa_memblock); - + } else if (p->block_size - sizeof(struct mempool_slot) >= length) { if (!(slot = mempool_allocate_slot(p))) return NULL; - + b = pa_xnew(pa_memblock, 1); b->type = PA_MEMBLOCK_POOL_EXTERNAL; b->data = mempool_slot_data(slot); @@ -285,7 +285,7 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (* assert(d); assert(length > 0); assert(free_cb); - + b = pa_xnew(pa_memblock, 1); b->type = PA_MEMBLOCK_USER; b->read_only = read_only; @@ -313,7 +313,7 @@ void pa_memblock_unref(pa_memblock*b) { if (PA_REFCNT_DEC(b) > 0) return; - + stat_remove(b); switch (b->type) { @@ -334,13 +334,13 @@ void pa_memblock_unref(pa_memblock*b) { segment = b->per_type.imported.segment; assert(segment); assert(segment->import); - + pa_hashmap_remove(segment->import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); segment->import->release_cb(segment->import, b->per_type.imported.id, segment->import->userdata); if (-- segment->n_blocks <= 0) segment_detach(segment); - + pa_xfree(b); break; } @@ -351,9 +351,9 @@ void pa_memblock_unref(pa_memblock*b) { slot = mempool_slot_by_ptr(b->pool, b->data); assert(slot); - + PA_LLIST_PREPEND(struct mempool_slot, b->pool->free_slots, slot); - + if (b->type == PA_MEMBLOCK_POOL_EXTERNAL) pa_xfree(b); @@ -377,7 +377,7 @@ static void memblock_make_local(pa_memblock *b) { if ((slot = mempool_allocate_slot(b->pool))) { void *new_data; /* We can move it into a local pool, perfect! */ - + b->type = PA_MEMBLOCK_POOL_EXTERNAL; b->read_only = 0; @@ -412,7 +412,7 @@ void pa_memblock_unref_fixed(pa_memblock *b) { static void memblock_replace_import(pa_memblock *b) { pa_memimport_segment *seg; - + assert(b); assert(b->type == PA_MEMBLOCK_IMPORTED); @@ -453,7 +453,7 @@ pa_mempool* pa_mempool_new(int shared) { if (p->block_size < ps) p->block_size = ps; - + p->n_blocks = PA_MEMPOOL_SLOTS_MAX; assert(p->block_size > sizeof(struct mempool_slot)); @@ -464,7 +464,7 @@ pa_mempool* pa_mempool_new(int shared) { } p->n_init = 0; - + PA_LLIST_HEAD_INIT(pa_memimport, p->imports); PA_LLIST_HEAD_INIT(pa_memexport, p->exports); PA_LLIST_HEAD_INIT(struct mempool_slot, p->free_slots); @@ -485,7 +485,7 @@ void pa_mempool_free(pa_mempool *p) { if (AO_load_acquire_read(&p->stat.n_allocated) > 0) pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!"); - + pa_shm_free(&p->memory); pa_xfree(p); } @@ -498,7 +498,7 @@ const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p) { void pa_mempool_vacuum(pa_mempool *p) { struct mempool_slot *slot; - + assert(p); for (slot = p->free_slots; slot; slot = slot->next) @@ -512,7 +512,7 @@ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) { return -1; *id = p->memory.id; - + return 0; } @@ -528,14 +528,14 @@ pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void assert(p); assert(cb); - + i = pa_xnew(pa_memimport, 1); i->pool = p; i->segments = pa_hashmap_new(NULL, NULL); i->blocks = pa_hashmap_new(NULL, NULL); i->release_cb = cb; i->userdata = userdata; - + PA_LLIST_PREPEND(pa_memimport, p->imports, i); return i; } @@ -549,7 +549,7 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) { return NULL; seg = pa_xnew(pa_memimport_segment, 1); - + if (pa_shm_attach_ro(&seg->memory, shm_id) < 0) { pa_xfree(seg); return NULL; @@ -557,7 +557,7 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) { seg->import = i; seg->n_blocks = 0; - + pa_hashmap_put(i->segments, PA_UINT32_TO_PTR(shm_id), seg); return seg; } @@ -573,7 +573,7 @@ static void segment_detach(pa_memimport_segment *seg) { void pa_memimport_free(pa_memimport *i) { pa_memexport *e; pa_memblock *b; - + assert(i); /* If we've exported this block further we need to revoke that export */ @@ -587,7 +587,7 @@ void pa_memimport_free(pa_memimport *i) { pa_hashmap_free(i->blocks, NULL, NULL); pa_hashmap_free(i->segments, NULL, NULL); - + PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i); pa_xfree(i); } @@ -595,19 +595,19 @@ void pa_memimport_free(pa_memimport *i) { pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_id, size_t offset, size_t size) { pa_memblock *b; pa_memimport_segment *seg; - + assert(i); if (pa_hashmap_size(i->blocks) >= PA_MEMIMPORT_SLOTS_MAX) return NULL; - if (!(seg = pa_hashmap_get(i->segments, PA_UINT32_TO_PTR(shm_id)))) + if (!(seg = pa_hashmap_get(i->segments, PA_UINT32_TO_PTR(shm_id)))) if (!(seg = segment_attach(i, shm_id))) return NULL; if (offset+size > seg->memory.size) return NULL; - + b = pa_xnew(pa_memblock, 1); b->type = PA_MEMBLOCK_IMPORTED; b->read_only = 1; @@ -621,9 +621,9 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i pa_hashmap_put(i->blocks, PA_UINT32_TO_PTR(block_id), b); seg->n_blocks++; - + stat_add(b); - + return b; } @@ -633,7 +633,7 @@ int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) { if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id)))) return -1; - + memblock_replace_import(b); return 0; } @@ -641,13 +641,13 @@ int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) { /* For sending blocks to other nodes */ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void *userdata) { pa_memexport *e; - + assert(p); assert(cb); if (!p->memory.shared) return NULL; - + e = pa_xnew(pa_memexport, 1); e->pool = p; PA_LLIST_HEAD_INIT(struct memexport_slot, e->free_slots); @@ -655,7 +655,7 @@ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void e->n_init = 0; e->revoke_cb = cb; e->userdata = userdata; - + PA_LLIST_PREPEND(pa_memexport, p->exports, e); return e; } @@ -683,10 +683,10 @@ int pa_memexport_process_release(pa_memexport *e, uint32_t id) { assert(AO_load_acquire_read(&e->pool->stat.n_exported) > 0); assert(AO_load_acquire_read(&e->pool->stat.exported_size) >= (AO_t) e->slots[id].block->length); - + AO_fetch_and_sub1_release_write(&e->pool->stat.n_exported); AO_fetch_and_add_release_write(&e->pool->stat.exported_size, (AO_t) -e->slots[id].block->length); - + pa_memblock_unref(e->slots[id].block); e->slots[id].block = NULL; @@ -704,7 +704,7 @@ static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) { for (slot = e->used_slots; slot; slot = next) { uint32_t idx; next = slot->next; - + if (slot->block->type != PA_MEMBLOCK_IMPORTED || slot->block->per_type.imported.segment->import != i) continue; @@ -720,7 +720,7 @@ static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *b) { assert(p); assert(b); - + if (b->type == PA_MEMBLOCK_IMPORTED || b->type == PA_MEMBLOCK_POOL || b->type == PA_MEMBLOCK_POOL_EXTERNAL) { @@ -738,7 +738,7 @@ static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *b) { int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32_t *shm_id, size_t *offset, size_t * size) { pa_shm *memory; struct memexport_slot *slot; - + assert(e); assert(b); assert(block_id); @@ -774,10 +774,10 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 assert(b->pool); memory = &b->pool->memory; } - + assert(b->data >= memory->ptr); assert((uint8_t*) b->data + b->length <= (uint8_t*) memory->ptr + memory->size); - + *shm_id = memory->id; *offset = (uint8_t*) b->data - (uint8_t*) memory->ptr; *size = b->length; diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index d4f2b7aaf..eeecf7562 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -37,7 +37,7 @@ typedef enum pa_memblock_type { PA_MEMBLOCK_POOL, /* Memory is part of the memory pool */ PA_MEMBLOCK_POOL_EXTERNAL, /* Data memory is part of the memory pool but the pa_memblock structure itself not */ - PA_MEMBLOCK_APPENDED, /* the data is appended to the memory block */ + PA_MEMBLOCK_APPENDED, /* the data is appended to the memory block */ PA_MEMBLOCK_USER, /* User supplied memory, to be freed with free_cb */ PA_MEMBLOCK_FIXED, /* data is a pointer to fixed memory that needs not to be freed */ PA_MEMBLOCK_IMPORTED, /* Memory is imported from another process via shm */ @@ -66,7 +66,7 @@ struct pa_memblock { struct { void (*free_cb)(void *p); /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ } user; - + struct { uint32_t id; pa_memimport_segment *segment; diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index e6b73fc55..4a845a53b 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -61,12 +61,12 @@ pa_memblockq* pa_memblockq_new( size_t prebuf, size_t minreq, pa_memblock *silence) { - + pa_memblockq* bq; - + assert(base > 0); assert(maxlength >= base); - + bq = pa_xnew(pa_memblockq, 1); bq->blocks = bq->blocks_tail = NULL; bq->n_blocks = 0; @@ -90,20 +90,20 @@ pa_memblockq* pa_memblockq_new( bq->prebuf = bq->maxlength; bq->minreq = (minreq/base)*base; - + if (bq->minreq > bq->tlength - bq->prebuf) bq->minreq = bq->tlength - bq->prebuf; if (!bq->minreq) bq->minreq = 1; - + pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", (unsigned long)bq->maxlength, (unsigned long)bq->tlength, (unsigned long)bq->base, (unsigned long)bq->prebuf, (unsigned long)bq->minreq); bq->state = bq->prebuf ? PREBUF : RUNNING; bq->silence = silence ? pa_memblock_ref(silence) : NULL; bq->mcalign = NULL; - + return bq; } @@ -117,7 +117,7 @@ void pa_memblockq_free(pa_memblockq* bq) { if (bq->mcalign) pa_mcalign_free(bq->mcalign); - + pa_xfree(bq); } @@ -126,12 +126,12 @@ static void drop_block(pa_memblockq *bq, struct memblock_list *q) { assert(q); assert(bq->n_blocks >= 1); - + if (q->prev) q->prev->next = q->next; else bq->blocks = q->next; - + if (q->next) q->next->prev = q->prev; else @@ -168,10 +168,10 @@ static int can_push(pa_memblockq *bq, size_t l) { } int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { - + struct memblock_list *q, *n; pa_memchunk chunk; - + assert(bq); assert(uchunk); assert(uchunk->memblock); @@ -185,7 +185,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { return -1; chunk = *uchunk; - + if (bq->read_index > bq->write_index) { /* We currently have a buffer underflow, we need to drop some @@ -203,7 +203,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { return 0; } } - + /* We go from back to front to look for the right place to add * this new entry. Drop data we will overwrite on the way */ @@ -275,29 +275,29 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { assert(bq->write_index + (int64_t)chunk.length > q->index && bq->write_index + (int64_t)chunk.length < q->index + (int64_t)q->chunk.length && bq->write_index < q->index); - + /* The job overwrites the current entry at the end, so let's drop the beginning of this entry */ d = bq->write_index + chunk.length - q->index; q->index += d; q->chunk.index += d; q->chunk.length -= d; - + q = q->prev; } - + } if (q) { assert(bq->write_index >= q->index + (int64_t)q->chunk.length); assert(!q->next || (bq->write_index + (int64_t)chunk.length <= q->next->index)); - + /* Try to merge memory blocks */ - + if (q->chunk.memblock == chunk.memblock && q->chunk.index + (int64_t)q->chunk.length == chunk.index && bq->write_index == q->index + (int64_t)q->chunk.length) { - + q->chunk.length += chunk.length; bq->write_index += chunk.length; return 0; @@ -324,7 +324,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { n->prev->next = n; else bq->blocks = n; - + bq->n_blocks++; return 0; } @@ -347,7 +347,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { bq->state = PREBUF; return -1; } - + /* Do we need to spit out silence? */ if (!bq->blocks || bq->blocks->index > bq->read_index) { @@ -362,7 +362,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { if (!length || length > chunk->memblock->length) length = chunk->memblock->length; - + chunk->length = length; } else { @@ -370,7 +370,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { * the time to sleep */ if (!bq->blocks) return -1; - + chunk->memblock = NULL; chunk->length = length; } @@ -381,7 +381,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { /* Ok, let's pass real data to the caller */ assert(bq->blocks->index == bq->read_index); - + *chunk = bq->blocks->chunk; pa_memblock_ref(chunk->memblock); @@ -432,14 +432,14 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length assert(bq->blocks->index >= bq->read_index); d = (size_t) (bq->blocks->index - bq->read_index); - + if (d >= length) { /* The first block is too far in the future */ - + bq->read_index += length; break; } else { - + length -= d; bq->read_index += d; } @@ -462,7 +462,7 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length bq->read_index += length; break; } - + } else { /* The list is empty, there's nothing we could drop */ @@ -477,7 +477,7 @@ int pa_memblockq_is_readable(pa_memblockq *bq) { if (bq->prebuf > 0) { size_t l = pa_memblockq_get_length(bq); - + if (bq->state == PREBUF && l < bq->prebuf) return 0; @@ -493,7 +493,7 @@ int pa_memblockq_is_writable(pa_memblockq *bq, size_t length) { if (length % bq->base) return 0; - + return pa_memblockq_get_length(bq) + length <= bq->tlength; } @@ -502,7 +502,7 @@ size_t pa_memblockq_get_length(pa_memblockq *bq) { if (bq->write_index <= bq->read_index) return 0; - + return (size_t) (bq->write_index - bq->read_index); } @@ -546,7 +546,7 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) { void pa_memblockq_flush(pa_memblockq *bq) { assert(bq); - + while (bq->blocks) drop_block(bq, bq->blocks); @@ -559,7 +559,7 @@ void pa_memblockq_flush(pa_memblockq *bq) { size_t pa_memblockq_get_tlength(pa_memblockq *bq) { assert(bq); - + return bq->tlength; } @@ -578,18 +578,18 @@ int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk) { assert(bq); assert(chunk && bq->base); - + if (bq->base == 1) return pa_memblockq_push(bq, chunk); - + if (!bq->mcalign) bq->mcalign = pa_mcalign_new(bq->base); if (!can_push(bq, pa_mcalign_csize(bq->mcalign, chunk->length))) return -1; - + pa_mcalign_push(bq->mcalign, chunk); - + while (pa_mcalign_pop(bq->mcalign, &rchunk) >= 0) { int r; r = pa_memblockq_push(bq, &rchunk); diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h index 4d701a80e..3485a6693 100644 --- a/src/pulsecore/memblockq.h +++ b/src/pulsecore/memblockq.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -39,27 +39,27 @@ typedef struct pa_memblockq pa_memblockq; /* Parameters: - + - idx: start value for both read and write index - maxlength: maximum length of queue. If more data is pushed into the queue, the operation will fail. Must not be 0. - + - tlength: the target length of the queue. Pass 0 for the default. - + - base: a base value for all metrics. Only multiples of this value are popped from the queue or should be pushed into it. Must not be 0. - + - prebuf: If the queue runs empty wait until this many bytes are in queue again before passing the first byte out. If set to 0 pa_memblockq_pop() will return a silence memblock if no data is in the queue and will never fail. Pass (size_t) -1 for the default. - + - minreq: pa_memblockq_missing() will only return values greater than this value. Pass 0 for the default. - + - silence: return this memblock whzen reading unitialized data */ pa_memblockq* pa_memblockq_new( @@ -67,7 +67,7 @@ pa_memblockq* pa_memblockq_new( size_t maxlength, size_t tlength, size_t base, - size_t prebuf, + size_t prebuf, size_t minreq, pa_memblock *silence); diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c index 1dbad2b90..2ab6d3581 100644 --- a/src/pulsecore/memchunk.c +++ b/src/pulsecore/memchunk.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -35,7 +35,7 @@ void pa_memchunk_make_writable(pa_memchunk *c, size_t min) { pa_memblock *n; size_t l; - + assert(c); assert(c->memblock); assert(PA_REFCNT_VALUE(c->memblock) > 0); @@ -48,7 +48,7 @@ void pa_memchunk_make_writable(pa_memchunk *c, size_t min) { l = c->length; if (l < min) l = min; - + n = pa_memblock_new(c->memblock->pool, l); memcpy(n->data, (uint8_t*) c->memblock->data + c->index, c->length); pa_memblock_unref(c->memblock); diff --git a/src/pulsecore/memchunk.h b/src/pulsecore/memchunk.h index b8ce62495..2e2f936bb 100644 --- a/src/pulsecore/memchunk.h +++ b/src/pulsecore/memchunk.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c index 13a48785b..243ea0196 100644 --- a/src/pulsecore/modargs.c +++ b/src/pulsecore/modargs.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -60,7 +60,7 @@ static int add_key_value(pa_hashmap *map, char *key, char *value, const char* co return -1; } } - + e = pa_xmalloc(sizeof(struct entry)); e->key = key; e->value = value; @@ -78,7 +78,7 @@ pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) { enum { WHITESPACE, KEY, VALUE_START, VALUE_SIMPLE, VALUE_DOUBLE_QUOTES, VALUE_TICKS } state; const char *p, *key, *value; size_t key_len = 0, value_len = 0; - + key = value = NULL; state = WHITESPACE; for (p = args; *p; p++) { @@ -160,7 +160,7 @@ fail: if (map) pa_modargs_free((pa_modargs*) map); - + return NULL; } @@ -210,7 +210,7 @@ int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value) { if (pa_atoi(v, value) < 0) return -1; - + return 0; } @@ -239,7 +239,7 @@ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) { assert(ma && rss); /* DEBUG_TRAP;*/ - + ss = *rss; if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0) return -1; @@ -257,14 +257,14 @@ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) { return -1; *rss = ss; - + return 0; } int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *rmap) { pa_channel_map map; const char *cm; - + assert(ma); assert(rmap); @@ -284,7 +284,7 @@ int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *rmap) { int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *rss, pa_channel_map *rmap, pa_channel_map_def_t def) { pa_sample_spec ss; pa_channel_map map; - + assert(ma); assert(rss); assert(rmap); diff --git a/src/pulsecore/modargs.h b/src/pulsecore/modargs.h index 730cf3968..5cccee903 100644 --- a/src/pulsecore/modargs.h +++ b/src/pulsecore/modargs.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/modinfo.c b/src/pulsecore/modinfo.c index 00720113a..46e66c50f 100644 --- a/src/pulsecore/modinfo.c +++ b/src/pulsecore/modinfo.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/modinfo.h b/src/pulsecore/modinfo.h index 90404504f..e8d3103fa 100644 --- a/src/pulsecore/modinfo.h +++ b/src/pulsecore/modinfo.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index ea3d726ed..94410b396 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -100,17 +100,17 @@ static inline fnptr load_sym(lt_dlhandle handle, const char *module, const char pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { pa_module *m = NULL; int r; - + assert(c && name); if (c->disallow_module_loading) goto fail; - + m = pa_xmalloc(sizeof(pa_module)); m->name = pa_xstrdup(name); m->argument = pa_xstrdup(argument); - + if (!(m->dl = lt_dlopenext(name))) { pa_log("Failed to open module \"%s\": %s", name, lt_dlerror()); goto fail; @@ -125,7 +125,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.", name); goto fail; } - + m->userdata = NULL; m->core = c; m->n_used = -1; @@ -148,23 +148,23 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } assert(c->module_auto_unload_event); - + assert(c->modules); r = pa_idxset_put(c->modules, m, &m->index); assert(r >= 0 && m->index != PA_IDXSET_INVALID); - pa_log_info("Loaded \"%s\" (index: #%u; argument: \"%s\").", m->name, m->index, m->argument ? m->argument : ""); + pa_log_info("Loaded \"%s\" (index: #%u; argument: \"%s\").", m->name, m->index, m->argument ? m->argument : ""); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_NEW, m->index); - + return m; - + fail: if (m) { pa_xfree(m->argument); pa_xfree(m->name); - + if (m->dl) lt_dlclose(m->dl); @@ -180,16 +180,16 @@ static void pa_module_free(pa_module *m) { if (m->core->disallow_module_loading) return; - pa_log_info("Unloading \"%s\" (index: #%u).", m->name, m->index); + pa_log_info("Unloading \"%s\" (index: #%u).", m->name, m->index); m->done(m->core, m); lt_dlclose(m->dl); - - pa_log_info("Unloaded \"%s\" (index: #%u).", m->name, m->index); + + pa_log_info("Unloaded \"%s\" (index: #%u).", m->name, m->index); pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE, m->index); - + pa_xfree(m->name); pa_xfree(m->argument); pa_xfree(m); @@ -250,7 +250,7 @@ static int unused_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void * pa_module *m = p; time_t *now = userdata; assert(p && del && now); - + if (m->n_used == 0 && m->auto_unload && m->last_used_time+m->core->module_idle_time <= *now) { pa_module_free(m); *del = 1; @@ -265,7 +265,7 @@ void pa_module_unload_unused(pa_core *c) { if (!c->modules) return; - + time(&now); pa_idxset_foreach(c->modules, unused_callback, &now); } @@ -309,7 +309,7 @@ void pa_module_set_used(pa_module*m, int used) { if (m->n_used != used) pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_CHANGE, m->index); - + if (m->n_used != used && used == 0) time(&m->last_used_time); diff --git a/src/pulsecore/module.h b/src/pulsecore/module.h index 8c320be88..5f1075076 100644 --- a/src/pulsecore/module.h +++ b/src/pulsecore/module.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -36,7 +36,7 @@ struct pa_module { uint32_t index; lt_dlhandle dl; - + int (*init)(pa_core *c, pa_module*m); void (*done)(pa_core *c, pa_module*m); diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c index 094d637d9..896913ce1 100644 --- a/src/pulsecore/mutex-posix.c +++ b/src/pulsecore/mutex-posix.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/mutex-win32.c b/src/pulsecore/mutex-win32.c index 3710d914d..124b17c61 100644 --- a/src/pulsecore/mutex-win32.c +++ b/src/pulsecore/mutex-win32.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/mutex.h b/src/pulsecore/mutex.h index b3b9c5c6a..11a20733b 100644 --- a/src/pulsecore/mutex.h +++ b/src/pulsecore/mutex.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index fcd271bf6..faf7f1444 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -59,14 +59,14 @@ static int is_valid_name(const char *name) { if (*name == 0) return 0; - + for (c = name; *c && (c-name < PA_NAME_MAX); c++) if (!is_valid_char(*c)) return 0; if (*c) return 0; - + return 1; } @@ -78,7 +78,7 @@ static char* cleanup_name(const char *name) { return NULL; n = pa_xnew(char, strlen(name)+1); - + for (a = name, b = n; *a && (a-name < PA_NAME_MAX); a++, b++) *b = is_valid_char(*a) ? *a : '_'; @@ -89,10 +89,10 @@ static char* cleanup_name(const char *name) { void pa_namereg_free(pa_core *c) { assert(c); - + if (!c->namereg) return; - + assert(pa_hashmap_size(c->namereg) == 0); pa_hashmap_free(c->namereg, NULL, NULL); } @@ -101,17 +101,17 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t struct namereg_entry *e; char *n = NULL; int r; - + assert(c); assert(name); assert(data); if (!*name) return NULL; - + if ((type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE) && !is_valid_name(name) ) { - + if (fail) return NULL; @@ -136,9 +136,9 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t pa_xfree(n); return NULL; } - + k = pa_xnew(char, l+4); - + for (i = 2; i <= 99; i++) { snprintf(k, l+4, "%s.%u", name, i); @@ -151,11 +151,11 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t pa_xfree(k); return NULL; } - + pa_xfree(n); n = k; } - + e = pa_xnew(struct namereg_entry, 1); e->type = type; e->name = n ? n : pa_xstrdup(name); @@ -169,7 +169,7 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t void pa_namereg_unregister(pa_core *c, const char *name) { struct namereg_entry *e; - + assert(c); assert(name); @@ -184,26 +184,26 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int a struct namereg_entry *e; uint32_t idx; assert(c); - + if (!name) { - + if (type == PA_NAMEREG_SOURCE) name = pa_namereg_get_default_source_name(c); else if (type == PA_NAMEREG_SINK) name = pa_namereg_get_default_sink_name(c); - + } else if (strcmp(name, "@DEFAULT_SINK@") == 0) { if (type == PA_NAMEREG_SINK) name = pa_namereg_get_default_sink_name(c); - + } else if (strcmp(name, "@DEFAULT_SOURCE@") == 0) { if (type == PA_NAMEREG_SOURCE) name = pa_namereg_get_default_source_name(c); - + } else if (strcmp(name, "@DEFAULT_MONITOR@") == 0) { if (type == PA_NAMEREG_SOURCE) { pa_sink *k; - + if ((k = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, autoload))) return k->monitor_source; } @@ -212,7 +212,7 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int a if (!name) return NULL; - + if (c->namereg && (e = pa_hashmap_get(c->namereg, name))) if (e->type == type) return e->data; @@ -221,12 +221,12 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int a if (autoload) { pa_autoload_request(c, name, type); - + if (c->namereg && (e = pa_hashmap_get(c->namereg, name))) if (e->type == type) return e->data; } - + return NULL; } @@ -242,7 +242,7 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int a int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) { char **s; - + assert(c); assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE); @@ -256,7 +256,7 @@ int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) if (!is_valid_name(name)) return -1; - + pa_xfree(*s); *s = pa_xstrdup(name); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX); @@ -266,12 +266,12 @@ int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) const char *pa_namereg_get_default_sink_name(pa_core *c) { pa_sink *s; - + assert(c); if (c->default_sink_name) return c->default_sink_name; - + if ((s = pa_idxset_first(c->sinks, NULL))) pa_namereg_set_default(c, s->name, PA_NAMEREG_SINK); @@ -281,7 +281,7 @@ const char *pa_namereg_get_default_sink_name(pa_core *c) { const char *pa_namereg_get_default_source_name(pa_core *c) { pa_source *s; uint32_t idx; - + assert(c); if (c->default_source_name) diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index 53fb66184..efadb06eb 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h index 785289eb1..df7654ffa 100644 --- a/src/pulsecore/native-common.h +++ b/src/pulsecore/native-common.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -51,7 +51,7 @@ enum { PA_COMMAND_FINISH_UPLOAD_STREAM, PA_COMMAND_PLAY_SAMPLE, PA_COMMAND_REMOVE_SAMPLE, - + PA_COMMAND_GET_SERVER_INFO, PA_COMMAND_GET_SINK_INFO, PA_COMMAND_GET_SINK_INFO_LIST, @@ -68,24 +68,24 @@ enum { PA_COMMAND_GET_SAMPLE_INFO, PA_COMMAND_GET_SAMPLE_INFO_LIST, PA_COMMAND_SUBSCRIBE, - + PA_COMMAND_SET_SINK_VOLUME, PA_COMMAND_SET_SINK_INPUT_VOLUME, PA_COMMAND_SET_SOURCE_VOLUME, PA_COMMAND_SET_SINK_MUTE, PA_COMMAND_SET_SOURCE_MUTE, - + PA_COMMAND_CORK_PLAYBACK_STREAM, PA_COMMAND_FLUSH_PLAYBACK_STREAM, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, - + PA_COMMAND_SET_DEFAULT_SINK, PA_COMMAND_SET_DEFAULT_SOURCE, - + PA_COMMAND_SET_PLAYBACK_STREAM_NAME, PA_COMMAND_SET_RECORD_STREAM_NAME, - + PA_COMMAND_KILL_CLIENT, PA_COMMAND_KILL_SINK_INPUT, PA_COMMAND_KILL_SOURCE_OUTPUT, diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c index 865997df3..bb2ca7930 100644 --- a/src/pulsecore/once-posix.c +++ b/src/pulsecore/once-posix.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -35,22 +35,22 @@ assert(_r == 0); \ } while(0) -static pa_mutex *global_mutex; +static pa_mutex *global_mutex; static pthread_once_t global_mutex_once = PTHREAD_ONCE_INIT; -static void global_mutex_once_func(void) { - global_mutex = pa_mutex_new(0); -} +static void global_mutex_once_func(void) { + global_mutex = pa_mutex_new(0); +} + +void pa_once(pa_once_t *control, pa_once_func_t func) { + assert(control); + assert(func); -void pa_once(pa_once_t *control, pa_once_func_t func) { - assert(control); - assert(func); - /* Create the global mutex */ - ASSERT_SUCCESS(pthread_once(&global_mutex_once, global_mutex_once_func)); + ASSERT_SUCCESS(pthread_once(&global_mutex_once, global_mutex_once_func)); /* Create the local mutex */ - pa_mutex_lock(global_mutex); + pa_mutex_lock(global_mutex); if (!control->mutex) control->mutex = pa_mutex_new(1); pa_mutex_unlock(global_mutex); @@ -61,9 +61,9 @@ void pa_once(pa_once_t *control, pa_once_func_t func) { control->once_value = 1; func(); } - pa_mutex_unlock(control->mutex); + pa_mutex_unlock(control->mutex); /* Caveat: We have to make sure that the once func has completed * before returning, even if the once func is not actually * executed by us. Hence the awkward locking. */ -} +} diff --git a/src/pulsecore/once-win32.c b/src/pulsecore/once-win32.c index 8b9282f42..07f68f383 100644 --- a/src/pulsecore/once-win32.c +++ b/src/pulsecore/once-win32.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -59,7 +59,7 @@ void pa_once(pa_once_t *control, pa_once_func_t func) { control->once_value = 1; func(); } - pa_mutex_unlock(control->mutex); + pa_mutex_unlock(control->mutex); /* Caveat: We have to make sure that the once func has completed * before returning, even if the once func is not actually diff --git a/src/pulsecore/once.h b/src/pulsecore/once.h index 0aabb3f29..3c475a1d0 100644 --- a/src/pulsecore/once.h +++ b/src/pulsecore/once.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/packet.c b/src/pulsecore/packet.c index 8b010f012..b3a4b6f4c 100644 --- a/src/pulsecore/packet.c +++ b/src/pulsecore/packet.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -40,7 +40,7 @@ pa_packet* pa_packet_new(size_t length) { p->length = length; p->data = (uint8_t*) (p+1); p->type = PA_PACKET_APPENDED; - + return p; } @@ -55,14 +55,14 @@ pa_packet* pa_packet_new_dynamic(void* data, size_t length) { p->length = length; p->data = data; p->type = PA_PACKET_DYNAMIC; - + return p; } pa_packet* pa_packet_ref(pa_packet *p) { assert(p); assert(p->ref >= 1); - + p->ref++; return p; } @@ -70,7 +70,7 @@ pa_packet* pa_packet_ref(pa_packet *p) { void pa_packet_unref(pa_packet *p) { assert(p); assert(p->ref >= 1); - + if (--p->ref == 0) { if (p->type == PA_PACKET_DYNAMIC) pa_xfree(p->data); diff --git a/src/pulsecore/packet.h b/src/pulsecore/packet.h index 7842857a6..89759c5ab 100644 --- a/src/pulsecore/packet.h +++ b/src/pulsecore/packet.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/parseaddr.c b/src/pulsecore/parseaddr.c index da1647af7..3a5bc2e80 100644 --- a/src/pulsecore/parseaddr.c +++ b/src/pulsecore/parseaddr.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -53,11 +53,11 @@ static char *parse_host(const char *s, uint16_t *ret_port) { *ret_port = atoi(e+2); else if (e[1] != 0) return NULL; - + return pa_xstrndup(s+1, e-s-1); } else { char *e; - + if (!(e = strrchr(s, ':'))) return pa_xstrdup(s); @@ -75,22 +75,22 @@ int pa_parse_address(const char *name, pa_parsed_address *ret_p) { if (*name == '{') { char hn[256], *pfx; /* The URL starts with a host specification for detecting local connections */ - + if (!pa_get_host_name(hn, sizeof(hn))) return -1; - + pfx = pa_sprintf_malloc("{%s}", hn); if (!pa_startswith(name, pfx)) { pa_xfree(pfx); /* Not local */ return -1; } - + p = name + strlen(pfx); pa_xfree(pfx); } else p = name; - + if (*p == '/') ret_p->type = PA_PARSED_ADDRESS_UNIX; else if (pa_startswith(p, "unix:")) { @@ -109,7 +109,7 @@ int pa_parse_address(const char *name, pa_parsed_address *ret_p) { else if (!(ret_p->path_or_host = parse_host(p, &ret_p->port))) return -1; - - + + return 0; } diff --git a/src/pulsecore/parseaddr.h b/src/pulsecore/parseaddr.h index 0393f6657..bbbb8989b 100644 --- a/src/pulsecore/parseaddr.h +++ b/src/pulsecore/parseaddr.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 6ecf710a7..c474ccd1c 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -120,9 +120,9 @@ static void reply_info_free(struct reply_info *r) { if (r->time_event) r->pdispatch->mainloop->time_free(r->time_event); - + PA_LLIST_REMOVE(struct reply_info, r->pdispatch->replies, r); - + pa_xfree(r); } @@ -131,7 +131,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_ assert(mainloop); assert((entries && table) || (!entries && !table)); - + pd = pa_xmalloc(sizeof(pa_pdispatch)); pd->ref = 1; pd->mainloop = mainloop; @@ -141,7 +141,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_ pd->drain_callback = NULL; pd->drain_userdata = NULL; pd->creds = NULL; - + return pd; } @@ -154,7 +154,7 @@ static void pdispatch_free(pa_pdispatch *pd) { reply_info_free(pd->replies); } - + pa_xfree(pd); } @@ -165,13 +165,13 @@ static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command, assert(r); pa_pdispatch_ref(pd); - + callback = r->callback; userdata = r->userdata; tag = r->tag; - + reply_info_free(r); - + callback(pd, command, tag, ts, userdata); if (pd->drain_callback && !pa_pdispatch_is_pending(pd)) @@ -187,24 +187,24 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, assert(pd && packet && packet->data); pa_pdispatch_ref(pd); - + if (packet->length <= 8) goto finish; ts = pa_tagstruct_new(packet->data, packet->length); assert(ts); - + if (pa_tagstruct_getu32(ts, &command) < 0 || pa_tagstruct_getu32(ts, &tag) < 0) goto finish; - + #ifdef DEBUG_OPCODES { char t[256]; char const *p; if (!(p = command_names[command])) snprintf((char*) (p = t), sizeof(t), "%u", command); - + pa_log("Recieved opcode <%s>", p); } #endif @@ -231,10 +231,10 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, } ret = 0; - + finish: pd->creds = NULL; - + if (ts) pa_tagstruct_free(ts); @@ -261,7 +261,7 @@ void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa r->userdata = userdata; r->free_cb = free_cb; r->tag = tag; - + pa_gettimeofday(&tv); tv.tv_sec += timeout; @@ -292,7 +292,7 @@ void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata) { for (r = pd->replies; r; r = n) { n = r->next; - if (r->userdata == userdata) + if (r->userdata == userdata) reply_info_free(r); } } @@ -313,6 +313,6 @@ pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd) { const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd) { assert(pd); assert(pd->ref >= 1); - + return pd->creds; } diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h index 479eb6b44..28bc29d94 100644 --- a/src/pulsecore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index 6e0c085ee..40cc82489 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -64,7 +64,7 @@ static pid_t read_pid(const char *fn, int fd) { if (r == 0) return (pid_t) 0; - + t[r] = 0; if ((e = strchr(t, '\n'))) *e = 0; @@ -79,10 +79,10 @@ static pid_t read_pid(const char *fn, int fd) { static int open_pid_file(const char *fn, int mode) { int fd = -1; - + for (;;) { struct stat st; - + if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) { if (mode != O_RDONLY || errno != ENOENT) pa_log_warn("WARNING: failed to open PID file '%s': %s", @@ -93,7 +93,7 @@ static int open_pid_file(const char *fn, int mode) { /* Try to lock the file. If that fails, go without */ if (pa_lock_fd(fd, 1) < 0) goto fail; - + if (fstat(fd, &st) < 0) { pa_log_warn("WARNING: failed to fstat() PID file '%s': %s", fn, pa_cstrerror(errno)); @@ -168,23 +168,23 @@ int pa_pid_file_create(void) { fn, pa_cstrerror(errno)); goto fail; } - + snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid()); l = strlen(t); - + if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) { pa_log("failed to write PID file."); goto fail; } ret = 0; - + fail: if (fd >= 0) { pa_lock_fd(fd, 0); close(fd); } - + return ret; } @@ -230,7 +230,7 @@ int pa_pid_file_remove(void) { } ret = 0; - + fail: if (fd >= 0) { @@ -262,26 +262,26 @@ int pa_pid_file_kill(int sig, pid_t *pid) { if (!pid) pid = &_pid; - + pa_runtime_path("pid", fn, sizeof(fn)); - + if ((fd = open_pid_file(fn, O_RDONLY)) < 0) goto fail; - + if ((*pid = read_pid(fn, fd)) == (pid_t) -1) goto fail; ret = kill(*pid, sig); - + fail: - + if (fd >= 0) { pa_lock_fd(fd, 0); close(fd); } return ret; - + } #else /* OS_IS_WIN32 */ diff --git a/src/pulsecore/pid.h b/src/pulsecore/pid.h index bd476b292..31d6f0bb4 100644 --- a/src/pulsecore/pid.h +++ b/src/pulsecore/pid.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/pipe.c b/src/pulsecore/pipe.c index 41ffb693b..a0c46fa3a 100644 --- a/src/pulsecore/pipe.c +++ b/src/pulsecore/pipe.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/pipe.h b/src/pulsecore/pipe.h index 21049e17f..86a198d36 100644 --- a/src/pulsecore/pipe.h +++ b/src/pulsecore/pipe.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c index f459142ae..ae7cd616e 100644 --- a/src/pulsecore/play-memblockq.c +++ b/src/pulsecore/play-memblockq.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -65,11 +65,11 @@ static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) { static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) { pa_memblockq *q; - + assert(i); assert(length > 0); assert( i->userdata); - + q = i->userdata; pa_memblockq_drop(q, chunk, length); @@ -85,7 +85,7 @@ int pa_play_memblockq( const pa_channel_map *map, pa_memblockq *q, pa_cvolume *volume) { - + pa_sink_input *si; pa_sink_input_new_data data; @@ -110,17 +110,17 @@ int pa_play_memblockq( pa_sink_input_new_data_set_channel_map(&data, map); pa_sink_input_new_data_set_sample_spec(&data, ss); pa_sink_input_new_data_set_volume(&data, volume); - + if (!(si = pa_sink_input_new(sink->core, &data, 0))) return -1; si->peek = sink_input_peek; si->drop = sink_input_drop; si->kill = sink_input_kill; - + si->userdata = q; pa_sink_notify(si->sink); - + return 0; } diff --git a/src/pulsecore/play-memblockq.h b/src/pulsecore/play-memblockq.h index 9b96efe36..68d0f8e3c 100644 --- a/src/pulsecore/play-memblockq.h +++ b/src/pulsecore/play-memblockq.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c index cde6a9ee4..c5dcc8cec 100644 --- a/src/pulsecore/play-memchunk.c +++ b/src/pulsecore/play-memchunk.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -54,7 +54,7 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { if (c->length <= 0) return -1; - + assert(c->memblock && c->memblock->length); *chunk = *c; pa_memblock_ref(c->memblock); @@ -88,7 +88,7 @@ int pa_play_memchunk( const pa_channel_map *map, const pa_memchunk *chunk, pa_cvolume *volume) { - + pa_sink_input *si; pa_memchunk *nchunk; pa_sink_input_new_data data; @@ -107,20 +107,20 @@ int pa_play_memchunk( pa_sink_input_new_data_set_sample_spec(&data, ss); pa_sink_input_new_data_set_channel_map(&data, map); pa_sink_input_new_data_set_volume(&data, volume); - + if (!(si = pa_sink_input_new(sink->core, &data, 0))) return -1; si->peek = sink_input_peek; si->drop = sink_input_drop; si->kill = sink_input_kill; - + si->userdata = nchunk = pa_xnew(pa_memchunk, 1); *nchunk = *chunk; - + pa_memblock_ref(chunk->memblock); pa_sink_notify(si->sink); - + return 0; } diff --git a/src/pulsecore/play-memchunk.h b/src/pulsecore/play-memchunk.h index 3d5b8cc69..3e087baa2 100644 --- a/src/pulsecore/play-memchunk.h +++ b/src/pulsecore/play-memchunk.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/poll.c b/src/pulsecore/poll.c index 289e0cdf2..82af4c057 100644 --- a/src/pulsecore/poll.c +++ b/src/pulsecore/poll.c @@ -9,17 +9,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/poll.h b/src/pulsecore/poll.h index c3d486e14..9c29789d5 100644 --- a/src/pulsecore/poll.h +++ b/src/pulsecore/poll.h @@ -10,17 +10,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/props.c b/src/pulsecore/props.c index 8879b7aa0..b8f920905 100644 --- a/src/pulsecore/props.c +++ b/src/pulsecore/props.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -36,7 +36,7 @@ typedef struct pa_property { static pa_property* property_new(const char *name, void *data) { pa_property* p; assert(name && data); - + p = pa_xmalloc(sizeof(pa_property)); p->name = pa_xstrdup(name); p->data = data; @@ -80,7 +80,7 @@ int pa_property_remove(pa_core *c, const char *name) { if (!(p = pa_hashmap_remove(c->properties, name))) return -1; - + property_free(p); return 0; } @@ -101,7 +101,7 @@ void pa_property_cleanup(pa_core *c) { pa_hashmap_free(c->properties, NULL, NULL); c->properties = NULL; - + } void pa_property_dump(pa_core *c, pa_strbuf *s) { diff --git a/src/pulsecore/props.h b/src/pulsecore/props.h index 39b7ca683..2b881b67e 100644 --- a/src/pulsecore/props.h +++ b/src/pulsecore/props.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/protocol-cli.c b/src/pulsecore/protocol-cli.c index 81ce5e8fb..9cca39eb1 100644 --- a/src/pulsecore/protocol-cli.c +++ b/src/pulsecore/protocol-cli.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -60,7 +60,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) pa_iochannel_free(io); return; } - + c = pa_cli_new(p->core, io, p->module); assert(c); pa_cli_set_eof_callback(c, cli_eof_cb, p); @@ -79,7 +79,7 @@ pa_protocol_cli* pa_protocol_cli_new(pa_core *core, pa_socket_server *server, pa p->connections = pa_idxset_new(NULL, NULL); pa_socket_server_set_callback(p->server, on_connection, p); - + return p; } diff --git a/src/pulsecore/protocol-cli.h b/src/pulsecore/protocol-cli.h index 84101e14d..6acd62cfe 100644 --- a/src/pulsecore/protocol-cli.h +++ b/src/pulsecore/protocol-cli.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index c36f82017..2984676d8 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -93,7 +93,7 @@ struct connection { pa_defer_event *defer_event; char *original_name; - + struct { pa_memblock *current_memblock; size_t memblock_index, fragment_size; @@ -177,7 +177,7 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { 3 * sizeof(int), esd_proto_stream_pan, "stream pan"}, { 3 * sizeof(int), NULL, "sample pan" }, - + { sizeof(int), NULL, "standby mode" }, { 0, esd_proto_get_latency, "get latency" } }; @@ -188,19 +188,19 @@ static void connection_free(struct connection *c) { if (c->state == ESD_STREAMING_DATA) c->protocol->n_player--; - + pa_client_free(c->client); if (c->sink_input) { pa_sink_input_disconnect(c->sink_input); pa_sink_input_unref(c->sink_input); } - + if (c->source_output) { pa_source_output_disconnect(c->source_output); pa_source_output_unref(c->source_output); } - + if (c->input_memblockq) pa_memblockq_free(c->input_memblockq); if (c->output_memblockq) @@ -208,13 +208,13 @@ static void connection_free(struct connection *c) { if (c->playback.current_memblock) pa_memblock_unref(c->playback.current_memblock); - + pa_xfree(c->read_data); pa_xfree(c->write_data); if (c->io) pa_iochannel_free(c->io); - + if (c->defer_event) c->protocol->core->mainloop->defer_free(c->defer_event); @@ -254,7 +254,7 @@ static void connection_write(struct connection *c, const void *data, size_t leng i = c->write_data_length; c->write_data_length += length; - + memcpy((char*)c->write_data + i, data, length); } @@ -270,7 +270,7 @@ static void format_esd2native(int format, int swap_bytes, pa_sample_spec *ss) { static int format_native2esd(pa_sample_spec *ss) { int format = 0; - + format = (ss->format == PA_SAMPLE_U8) ? ESD_BITS8 : ESD_BITS16; format |= (ss->channels >= 2) ? ESD_STEREO : ESD_MONO; @@ -331,7 +331,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t pa_sink_input_new_data sdata; assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX)); - + memcpy(&format, data, sizeof(int32_t)); format = MAYBE_INT32_SWAP(c->swap_byte_order, format); data = (const char*)data + sizeof(int32_t); @@ -356,7 +356,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t utf8_name = pa_utf8_filter(name); pa_client_set_name(c->client, utf8_name); pa_xfree(utf8_name); - + c->original_name = pa_xstrdup(name); assert(!c->sink_input && !c->input_memblockq); @@ -368,11 +368,11 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t pa_sink_input_new_data_set_sample_spec(&sdata, &ss); sdata.module = c->protocol->module; sdata.client = c->client; - + c->sink_input = pa_sink_input_new(c->protocol->core, &sdata, 0); CHECK_VALIDITY(c->sink_input, "Failed to create sink input."); - l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); + l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS); c->input_memblockq = pa_memblockq_new( 0, l, @@ -393,7 +393,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t c->state = ESD_STREAMING_DATA; c->protocol->n_player++; - + return 0; } @@ -406,7 +406,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co pa_source_output_new_data sdata; assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX)); - + memcpy(&format, data, sizeof(int32_t)); format = MAYBE_INT32_SWAP(c->swap_byte_order, format); data = (const char*)data + sizeof(int32_t); @@ -442,14 +442,14 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co } } } - + strncpy(name, data, sizeof(name)); name[sizeof(name)-1] = 0; utf8_name = pa_utf8_filter(name); pa_client_set_name(c->client, utf8_name); pa_xfree(utf8_name); - + c->original_name = pa_xstrdup(name); assert(!c->output_memblockq && !c->source_output); @@ -461,11 +461,11 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co pa_source_output_new_data_set_sample_spec(&sdata, &ss); sdata.module = c->protocol->module; sdata.client = c->client; - + c->source_output = pa_source_output_new(c->protocol->core, &sdata, 9); CHECK_VALIDITY(c->source_output, "Failed to create source_output."); - l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS); + l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS); c->output_memblockq = pa_memblockq_new( 0, l, @@ -475,7 +475,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co 0, NULL); pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2); - + c->source_output->push = source_output_push_cb; c->source_output->kill = source_output_kill_cb; c->source_output->get_latency = source_output_get_latency_cb; @@ -484,7 +484,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co c->state = ESD_STREAMING_DATA; c->protocol->n_player++; - + return 0; } @@ -500,7 +500,7 @@ static int esd_proto_get_latency(struct connection *c, PA_GCC_UNUSED esd_proto_t double usec = pa_sink_get_latency(sink); latency = (int) ((usec*44100)/1000000); } - + latency = MAYBE_INT32_SWAP(c->swap_byte_order, latency); connection_write(c, &latency, sizeof(int32_t)); return 0; @@ -538,7 +538,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v char terminator[sizeof(int32_t)*6+ESD_NAME_MAX]; assert(c && data && length == sizeof(int32_t)); - + if (esd_proto_server_info(c, request, data, length) < 0) return -1; @@ -559,7 +559,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v continue; assert(t >= k*2+s); - + if (conn->sink_input) { pa_cvolume volume = *pa_sink_input_get_volume(conn->sink_input); rate = conn->sink_input->sample_spec.rate; @@ -567,7 +567,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v rvolume = (volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM; format = format_native2esd(&conn->sink_input->sample_spec); } - + /* id */ id = MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) (conn->index+1)); connection_write(c, &id, sizeof(int32_t)); @@ -606,7 +606,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v if (nsamples) { pa_scache_entry *ce; - + idx = PA_IDXSET_INVALID; for (ce = pa_idxset_first(c->protocol->core->scache, &idx); ce; ce = pa_idxset_next(c->protocol->core->scache, &idx)) { int32_t id, rate, lvolume, rvolume, format, len; @@ -617,7 +617,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v /* id */ id = MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1)); connection_write(c, &id, sizeof(int32_t)); - + /* name */ memset(name, 0, ESD_NAME_MAX); /* don't leak old data */ if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0) @@ -625,19 +625,19 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v else snprintf(name, ESD_NAME_MAX, "native.%s", ce->name); connection_write(c, name, ESD_NAME_MAX); - + /* rate */ rate = MAYBE_UINT32_SWAP(c->swap_byte_order, ce->sample_spec.rate); connection_write(c, &rate, sizeof(int32_t)); - + /* left */ lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); connection_write(c, &lvolume, sizeof(int32_t)); - + /*right*/ rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); connection_write(c, &rvolume, sizeof(int32_t)); - + /*format*/ format = MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ce->sample_spec)); connection_write(c, &format, sizeof(int32_t)); @@ -663,7 +663,7 @@ static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t struct connection *conn; assert(c && data && length == sizeof(int32_t)*3); - + memcpy(&idx, data, sizeof(uint32_t)); idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1; data = (const char*)data + sizeof(uint32_t); @@ -687,7 +687,7 @@ static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t ok = 0; connection_write(c, &ok, sizeof(int32_t)); - + return 0; } @@ -706,7 +706,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ memcpy(&rate, data, sizeof(int32_t)); rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); data = (const char*)data + sizeof(int32_t); - + ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -723,7 +723,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ name[sizeof(name)-1] = 0; CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name."); - + assert(!c->scache.memchunk.memblock); c->scache.memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, sc_length); c->scache.memchunk.index = 0; @@ -731,14 +731,14 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ c->scache.sample_spec = ss; assert(!c->scache.name); c->scache.name = pa_xstrdup(name); - + c->state = ESD_CACHING_SAMPLE; pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, &idx); idx += 1; connection_write(c, &idx, sizeof(uint32_t)); - + return 0; } @@ -775,11 +775,11 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1; ok = 0; - + if ((name = pa_scache_get_name_by_id(c->protocol->core, idx))) { if (request == ESD_PROTO_SAMPLE_PLAY) { pa_sink *sink; - + if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0) ok = idx + 1; @@ -790,7 +790,7 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque ok = idx + 1; } } - + connection_write(c, &ok, sizeof(int32_t)); return 0; @@ -821,7 +821,7 @@ static int do_read(struct connection *c) { assert(c && c->io); /* pa_log("READ"); */ - + if (c->state == ESD_NEXT_REQUEST) { ssize_t r; assert(c->read_data_length < sizeof(c->request)); @@ -833,7 +833,7 @@ static int do_read(struct connection *c) { if ((c->read_data_length+= r) >= sizeof(c->request)) { struct proto_handler *handler; - + c->request = MAYBE_INT32_SWAP(c->swap_byte_order, c->request); if (c->request < ESD_PROTO_CONNECT || c->request > ESD_PROTO_MAX) { @@ -849,18 +849,18 @@ static int do_read(struct connection *c) { pa_log("recieved unimplemented request #%u.", c->request); return -1; } - + if (handler->data_length == 0) { c->read_data_length = 0; if (handler->proc(c, c->request, NULL, 0) < 0) return -1; - + } else { if (c->read_data_alloc < handler->data_length) c->read_data = pa_xrealloc(c->read_data, c->read_data_alloc = handler->data_length); assert(c->read_data); - + c->state = ESD_NEEDS_REQDATA; c->read_data_length = 0; } @@ -871,7 +871,7 @@ static int do_read(struct connection *c) { struct proto_handler *handler = proto_map+c->request; assert(handler->proc); - + assert(c->read_data && c->read_data_length < handler->data_length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { @@ -885,7 +885,7 @@ static int do_read(struct connection *c) { c->state = ESD_NEXT_REQUEST; c->read_data_length = 0; - + if (handler->proc(c, c->request, c->read_data, l) < 0) return -1; } @@ -893,7 +893,7 @@ static int do_read(struct connection *c) { ssize_t r; assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length); - + if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; @@ -901,10 +901,10 @@ static int do_read(struct connection *c) { c->scache.memchunk.index += r; assert(c->scache.memchunk.index <= c->scache.memchunk.length); - + if (c->scache.memchunk.index == c->scache.memchunk.length) { uint32_t idx; - + c->scache.memchunk.index = 0; pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, &idx); @@ -920,7 +920,7 @@ static int do_read(struct connection *c) { idx += 1; connection_write(c, &idx, sizeof(uint32_t)); } - + } else if (c->state == ESD_STREAMING_DATA && c->sink_input) { pa_memchunk chunk; ssize_t r; @@ -936,13 +936,13 @@ static int do_read(struct connection *c) { if (l > c->playback.fragment_size) l = c->playback.fragment_size; - if (c->playback.current_memblock) + if (c->playback.current_memblock) if (c->playback.current_memblock->length - c->playback.memblock_index < l) { pa_memblock_unref(c->playback.current_memblock); c->playback.current_memblock = NULL; c->playback.memblock_index = 0; } - + if (!c->playback.current_memblock) { c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2); assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); @@ -953,20 +953,20 @@ static int do_read(struct connection *c) { pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } - + chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; chunk.length = r; assert(chunk.memblock); c->playback.memblock_index += r; - + assert(c->input_memblockq); pa_memblockq_push_align(c->input_memblockq, &chunk); assert(c->sink_input); pa_sink_notify(c->sink_input->sink); } - + return 0; } @@ -974,19 +974,19 @@ static int do_write(struct connection *c) { assert(c && c->io); /* pa_log("WRITE"); */ - + if (c->write_data_length) { ssize_t r; - + assert(c->write_data_index < c->write_data_length); if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { pa_log("write(): %s", pa_cstrerror(errno)); return -1; } - + if ((c->write_data_index +=r) >= c->write_data_length) c->write_data_length = c->write_data_index = 0; - + } else if (c->state == ESD_STREAMING_DATA && c->source_output) { pa_memchunk chunk; ssize_t r; @@ -994,9 +994,9 @@ static int do_write(struct connection *c) { assert(c->output_memblockq); if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) return 0; - + assert(chunk.memblock && chunk.length); - + if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); pa_log("write(): %s", pa_cstrerror(errno)); @@ -1008,7 +1008,7 @@ static int do_write(struct connection *c) { pa_source_notify(c->source_output->source); } - + return 0; } @@ -1035,7 +1035,7 @@ static void do_work(struct connection *c) { if (pa_iochannel_is_writable(c->io)) if (do_write(c) < 0) goto fail; - + return; fail: @@ -1066,7 +1066,7 @@ static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) assert(a && c && c->defer_event == e); /* pa_log("DEFER"); */ - + do_work(c); } @@ -1076,12 +1076,12 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { struct connection*c; assert(i && i->userdata && chunk); c = i->userdata; - + if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) { if (c->dead) connection_free(c); - + return -1; } @@ -1093,7 +1093,7 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_ assert(i && c && length); /* pa_log("DROP"); */ - + pa_memblockq_drop(c->input_memblockq, chunk, length); /* do something */ @@ -1163,7 +1163,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) pa_iochannel_free(io); return; } - + c = pa_xnew(struct connection, 1); c->protocol = p; c->io = io; @@ -1177,7 +1177,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->client->owner = p->module; c->client->kill = client_kill_cb; c->client->userdata = c; - + c->authorized = !!p->public; c->swap_byte_order = 0; c->dead = 0; @@ -1219,7 +1219,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c); } else c->auth_timeout_event = NULL; - + c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c); assert(c->defer_event); p->core->mainloop->defer_enable(c->defer_event, 0); @@ -1233,7 +1233,7 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve pa_protocol_esound *p; int public = 0; const char *acl; - + assert(core); assert(server); assert(m); @@ -1257,7 +1257,7 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve } } else p->auth_ip_acl = NULL; - + p->module = m; p->public = public; p->server = server; diff --git a/src/pulsecore/protocol-esound.h b/src/pulsecore/protocol-esound.h index 79b5acf0b..265f9e2cd 100644 --- a/src/pulsecore/protocol-esound.h +++ b/src/pulsecore/protocol-esound.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c index 3b1207f62..22ecba824 100644 --- a/src/pulsecore/protocol-http.c +++ b/src/pulsecore/protocol-http.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -67,7 +67,7 @@ static void http_response(struct connection *c, int code, const char *msg, const assert(msg); assert(mime); - snprintf(s, sizeof(s), + snprintf(s, sizeof(s), "HTTP/1.0 %i %s\n" "Connection: close\n" "Content-Type: %s\n" @@ -137,16 +137,16 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { } case MIME_HEADER: { - + /* Ignore MIME headers */ if (strcspn(s, " \r\n") != 0) break; - + /* We're done */ c->state = DATA; pa_log_info("request for %s", c->url); - + if (!strcmp(c->url, URL_ROOT)) { char txt[256]; http_response(c, 200, "OK", "text/html"); @@ -168,18 +168,18 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { PRINTF_FIELD("Default Sample Specification:", pa_sample_spec_snprint(txt, sizeof(txt), &c->protocol->core->default_sample_spec)); PRINTF_FIELD("Default Sink:", pa_namereg_get_default_sink_name(c->protocol->core)); PRINTF_FIELD("Default Source:", pa_namereg_get_default_source_name(c->protocol->core)); - + pa_ioline_puts(c->line, ""); pa_ioline_puts(c->line, "

        Click here for an extensive server status report.

        "); - + pa_ioline_puts(c->line, "\n"); - - pa_ioline_defer_close(c->line); + + pa_ioline_defer_close(c->line); } else if (!strcmp(c->url, URL_CSS)) { http_response(c, 200, "OK", "text/css"); - pa_ioline_puts(c->line, + pa_ioline_puts(c->line, "body { color: black; background-color: white; margin: 0.5cm; }\n" "a:link, a:visited { color: #900000; }\n" "p { margin-left: 0.5cm; margin-right: 0.5cm; }\n" @@ -207,13 +207,13 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { break; } - + default: ; } return; - + fail: internal_server_error(c); } diff --git a/src/pulsecore/protocol-http.h b/src/pulsecore/protocol-http.h index 5d5dba313..bf1562e69 100644 --- a/src/pulsecore/protocol-http.h +++ b/src/pulsecore/protocol-http.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 38c024b7b..a882d701c 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -234,7 +234,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume, [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume, [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume, - + [PA_COMMAND_SET_SINK_MUTE] = command_set_mute, [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute, @@ -242,13 +242,13 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_playback_stream, [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream, [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream, - + [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream, [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream, - + [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source, [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source, - [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name, + [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name, [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name, [PA_COMMAND_KILL_CLIENT] = command_kill, [PA_COMMAND_KILL_SINK_INPUT] = command_kill, @@ -271,10 +271,10 @@ static struct upload_stream* upload_stream_new( const pa_sample_spec *ss, const pa_channel_map *map, const char *name, size_t length) { - + struct upload_stream *s; assert(c && ss && name && length); - + s = pa_xnew(struct upload_stream, 1); s->type = UPLOAD_STREAM; s->connection = c; @@ -287,7 +287,7 @@ static struct upload_stream* upload_stream_new( s->memchunk.length = 0; s->length = length; - + pa_idxset_put(c->output_streams, s, &s->index); return s; } @@ -298,10 +298,10 @@ static void upload_stream_free(struct upload_stream *o) { pa_idxset_remove_by_data(o->connection->output_streams, o, NULL); pa_xfree(o->name); - + if (o->memchunk.memblock) pa_memblock_unref(o->memchunk.memblock); - + pa_xfree(o); } @@ -313,12 +313,12 @@ static struct record_stream* record_stream_new( const char *name, size_t maxlength, size_t fragment_size) { - + struct record_stream *s; pa_source_output *source_output; size_t base; pa_source_output_new_data data; - + assert(c && ss && name && maxlength); pa_source_output_new_data_init(&data); @@ -329,7 +329,7 @@ static struct record_stream* record_stream_new( pa_source_output_new_data_set_channel_map(&data, map); data.module = c->protocol->module; data.client = c->client; - + if (!(source_output = pa_source_output_new(c->protocol->core, &data, 0))) return NULL; @@ -381,19 +381,19 @@ static struct playback_stream* playback_stream_new( size_t minreq, pa_cvolume *volume, uint32_t syncid) { - + struct playback_stream *s, *ssync; pa_sink_input *sink_input; pa_memblock *silence; uint32_t idx; int64_t start_index; pa_sink_input_new_data data; - + assert(c && ss && name && maxlength); /* Find syncid group */ for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) { - + if (ssync->type != PLAYBACK_STREAM) continue; @@ -417,14 +417,14 @@ static struct playback_stream* playback_stream_new( if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, 0))) return NULL; - + s = pa_xnew(struct playback_stream, 1); s->type = PLAYBACK_STREAM; s->connection = c; s->syncid = syncid; s->sink_input = sink_input; s->underrun = 1; - + s->sink_input->peek = sink_input_peek_cb; s->sink_input->drop = sink_input_drop_cb; s->sink_input->kill = sink_input_kill_cb; @@ -446,9 +446,9 @@ static struct playback_stream* playback_stream_new( PA_LLIST_INIT(struct playback_stream, s); start_index = 0; } - + silence = pa_silence_memblock_new(c->protocol->core->mempool, ss, 0); - + s->memblockq = pa_memblockq_new( start_index, maxlength, @@ -459,10 +459,10 @@ static struct playback_stream* playback_stream_new( silence); pa_memblock_unref(silence); - + s->requested_bytes = 0; s->drain_request = 0; - + pa_idxset_put(c->output_streams, s, &s->index); return s; @@ -512,7 +512,7 @@ static void connection_free(struct connection *c) { if (c->auth_timeout_event) c->protocol->core->mainloop->time_free(c->auth_timeout_event); - + pa_xfree(c); } @@ -523,7 +523,7 @@ static void request_bytes(struct playback_stream *s) { if (!(l = pa_memblockq_missing(s->memblockq))) return; - + if (l <= s->requested_bytes) return; @@ -531,7 +531,7 @@ static void request_bytes(struct playback_stream *s) { if (l < pa_memblockq_get_minreq(s->memblockq)) return; - + s->requested_bytes += l; t = pa_tagstruct_new(NULL, 0); @@ -552,7 +552,7 @@ static void send_memblock(struct connection *c) { start = PA_IDXSET_INVALID; for (;;) { pa_memchunk chunk; - + if (!(r = pa_idxset_rrobin(c->record_streams, &c->rrobin_index))) return; @@ -563,14 +563,14 @@ static void send_memblock(struct connection *c) { if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) { pa_memchunk schunk = chunk; - + if (schunk.length > r->fragment_size) schunk.length = r->fragment_size; pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk); pa_memblockq_drop(r->memblockq, &chunk, schunk.length); pa_memblock_unref(schunk.memblock); - + return; } } @@ -618,14 +618,14 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { s->underrun = 1; } - + if (pa_memblockq_peek(s->memblockq, chunk) < 0) { /* pa_log("peek: failure"); */ return -1; } /* pa_log("peek: %u", chunk->length); */ - + return 0; } @@ -658,7 +658,7 @@ static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { s = i->userdata; /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/ - + return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); } @@ -668,12 +668,12 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) struct record_stream *s; assert(o && o->userdata && chunk); s = o->userdata; - + if (pa_memblockq_push_align(s->memblockq, chunk) < 0) { pa_log_warn("Failed to push data into output queue."); return; - } - + } + if (!pa_pstream_is_pending(s->connection->pstream)) send_memblock(s->connection); } @@ -690,7 +690,7 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { s = o->userdata; /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/ - + return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec); } @@ -710,7 +710,7 @@ if (!(expression)) { \ static pa_tagstruct *reply_new(uint32_t tag) { pa_tagstruct *reply; - + reply = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); pa_tagstruct_putu32(reply, tag); @@ -728,9 +728,9 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC pa_sink *sink = NULL; pa_cvolume volume; int corked; - + assert(c && t && c->protocol && c->protocol->core); - + if (pa_tagstruct_get( t, PA_TAG_STRING, &name, @@ -773,7 +773,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); pa_sink_input_cork(s->sink_input, corked); - + reply = reply_new(tag); pa_tagstruct_putu32(reply, s->index); assert(s->sink_input); @@ -788,7 +788,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_prebuf(s->memblockq)); pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_minreq(s->memblockq)); } - + pa_pstream_send_tagstruct(c->pstream, reply); request_bytes(s); } @@ -797,7 +797,7 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma struct connection *c = userdata; uint32_t channel; assert(c && t); - + if (pa_tagstruct_getu32(t, &channel) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -832,7 +832,7 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma upload_stream_free(s); } - + pa_pstream_send_simple_ack(c->pstream, tag); } @@ -848,7 +848,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_source *source = NULL; int corked; assert(c && t && c->protocol && c->protocol->core); - + if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_get_sample_spec(t, &ss) < 0 || pa_tagstruct_get_channel_map(t, &map) < 0 || @@ -876,13 +876,13 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } else if (source_name) { source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1); CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY); - } - + } + s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); - + pa_source_output_cork(s->source_output, corked); - + reply = reply_new(tag); pa_tagstruct_putu32(reply, s->index); assert(s->source_output); @@ -894,21 +894,21 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq)); pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size); } - + pa_pstream_send_tagstruct(c->pstream, reply); } static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; assert(c && t); - + if (!pa_tagstruct_eof(t)) { protocol_error(c); return; } CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - + assert(c->protocol && c->protocol->core && c->protocol->core->mainloop); c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0); pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */ @@ -935,7 +935,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t if (!c->authorized) { int success = 0; - + #ifdef HAVE_CREDS const pa_creds *creds; @@ -950,7 +950,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t pa_log_warn("failed to get GID of group '%s'", c->protocol->auth_group); else if (gid == creds->gid) success = 1; - + if (!success) { if ((r = pa_uid_in_group(creds->uid, c->protocol->auth_group)) < 0) pa_log_warn("failed to check group membership."); @@ -958,7 +958,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t success = 1; } } - + pa_log_info("Got credentials: uid=%lu gid=%lu success=%i", (unsigned long) creds->uid, (unsigned long) creds->gid, @@ -971,7 +971,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t pa_pstream_use_shm(c->pstream, 1); pa_log_info("Enabled SHM for new connection"); } - + } #endif @@ -983,7 +983,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS); return; } - + c->authorized = 1; if (c->auth_timeout_event) { c->protocol->core->mainloop->time_free(c->auth_timeout_event); @@ -997,12 +997,12 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t #ifdef HAVE_CREDS { /* SHM support is only enabled after both sides made sure they are the same user. */ - + pa_creds ucred; ucred.uid = getuid(); ucred.gid = getgid(); - + pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred); } #else @@ -1022,7 +1022,7 @@ static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE } CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID); - + pa_client_set_name(c->client, name); pa_pstream_send_simple_ack(c->pstream, tag); } @@ -1079,11 +1079,11 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC s = pa_idxset_get_by_index(c->output_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); - + s->drain_request = 0; pa_memblockq_prebuf_disable(s->memblockq); - + if (!pa_memblockq_is_readable(s->memblockq)) { /* pa_log("immediate drain: %u", pa_memblockq_get_length(s->memblockq)); */ pa_pstream_send_simple_ack(c->pstream, tag); @@ -1094,7 +1094,7 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC pa_sink_notify(s->sink_input->sink); } -} +} static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; @@ -1110,7 +1110,7 @@ static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); stat = pa_mempool_get_stat(c->protocol->core->mempool); - + reply = reply_new(tag); pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->n_allocated)); pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->allocated_size)); @@ -1128,7 +1128,7 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ uint32_t idx; pa_usec_t latency; assert(c && t); - + if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_timeval(t, &tv) < 0 || !pa_tagstruct_eof(t)) { @@ -1147,7 +1147,7 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ if (s->sink_input->resampled_chunk.memblock) latency += pa_bytes_to_usec(s->sink_input->resampled_chunk.length, &s->sink_input->sample_spec); pa_tagstruct_put_usec(reply, latency); - + pa_tagstruct_put_usec(reply, 0); pa_tagstruct_put_boolean(reply, s->sink_input->state == PA_SINK_INPUT_RUNNING); pa_tagstruct_put_timeval(reply, &tv); @@ -1196,8 +1196,8 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_channel_map map; pa_tagstruct *reply; assert(c && t && c->protocol && c->protocol->core); - - if (pa_tagstruct_gets(t, &name) < 0 || + + if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_get_sample_spec(t, &ss) < 0 || pa_tagstruct_get_channel_map(t, &map) < 0 || pa_tagstruct_getu32(t, &length) < 0 || @@ -1213,10 +1213,10 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE); CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); - + s = upload_stream_new(c, &ss, &map, name, length); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); - + reply = reply_new(tag); pa_tagstruct_putu32(reply, s->index); pa_tagstruct_putu32(reply, length); @@ -1229,7 +1229,7 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ struct upload_stream *s; uint32_t idx; assert(c && t); - + if (pa_tagstruct_getu32(t, &channel) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1246,7 +1246,7 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL); else pa_pstream_send_simple_ack(c->pstream, tag); - + upload_stream_free(s); } @@ -1266,7 +1266,7 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui protocol_error(c); return; } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); @@ -1455,7 +1455,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); } else if (command == PA_COMMAND_GET_CLIENT_INFO) client = pa_idxset_get_by_index(c->protocol->core->clients, idx); - else if (command == PA_COMMAND_GET_MODULE_INFO) + else if (command == PA_COMMAND_GET_MODULE_INFO) module = pa_idxset_get_by_index(c->protocol->core->modules, idx); else if (command == PA_COMMAND_GET_SINK_INPUT_INFO) si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); @@ -1468,7 +1468,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u else sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0); } - + if (!sink && !source && !client && !module && !si && !so && !sce) { pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); return; @@ -1538,7 +1538,7 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma module_fill_tagstruct(reply, p); else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST) sink_input_fill_tagstruct(reply, p); - else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST) + else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST) source_output_fill_tagstruct(reply, p); else { assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); @@ -1546,7 +1546,7 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma } } } - + pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1561,7 +1561,7 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE protocol_error(c); return; } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); reply = reply_new(tag); @@ -1577,7 +1577,7 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE pa_tagstruct_puts(reply, n); pa_tagstruct_putu32(reply, c->protocol->core->cookie); - + pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1607,7 +1607,7 @@ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID); - + if (c->subscription) pa_subscription_free(c->subscription); @@ -1626,7 +1626,7 @@ static void command_set_volume( uint32_t tag, pa_tagstruct *t, void *userdata) { - + struct connection *c = userdata; uint32_t idx; pa_cvolume volume; @@ -1644,7 +1644,7 @@ static void command_set_volume( protocol_error(c); return; } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); @@ -1682,7 +1682,7 @@ static void command_set_mute( uint32_t tag, pa_tagstruct *t, void *userdata) { - + struct connection *c = userdata; uint32_t idx; int mute; @@ -1698,7 +1698,7 @@ static void command_set_mute( protocol_error(c); return; } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); @@ -1758,9 +1758,9 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_sink_input_cork(ssync->sink_input, b); pa_memblockq_prebuf_force(ssync->memblockq); } - + pa_pstream_send_simple_ack(c->pstream, tag); -} +} static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { struct connection *c = userdata; @@ -1782,7 +1782,7 @@ static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC pa_memblockq_flush(s->memblockq); s->underrun = 0; - + /* Do the same for all other members in the sync group */ for (ssync = s->prev; ssync; ssync = ssync->prev) { pa_memblockq_flush(ssync->memblockq); @@ -1793,11 +1793,11 @@ static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC pa_memblockq_flush(ssync->memblockq); ssync->underrun = 0; } - + pa_pstream_send_simple_ack(c->pstream, tag); pa_sink_notify(s->sink_input->sink); request_bytes(s); - + for (ssync = s->prev; ssync; ssync = ssync->prev) request_bytes(ssync); @@ -1827,11 +1827,11 @@ static void command_trigger_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch case PA_COMMAND_PREBUF_PLAYBACK_STREAM: pa_memblockq_prebuf_force(s->memblockq); break; - + case PA_COMMAND_TRIGGER_PLAYBACK_STREAM: pa_memblockq_prebuf_disable(s->memblockq); break; - + default: abort(); } @@ -1914,22 +1914,22 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com protocol_error(c); return; } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID); if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) { struct playback_stream *s; - + s = pa_idxset_get_by_index(c->output_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); pa_sink_input_set_name(s->sink_input, name); - + } else { struct record_stream *s; - + s = pa_idxset_get_by_index(c->record_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); @@ -1954,14 +1954,14 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 if (command == PA_COMMAND_KILL_CLIENT) { pa_client *client; - + client = pa_idxset_get_by_index(c->protocol->core->clients, idx); CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY); pa_client_kill(client); - + } else if (command == PA_COMMAND_KILL_SINK_INPUT) { pa_sink_input *s; - + s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); @@ -1970,7 +1970,7 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 pa_source_output *s; assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT); - + s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); @@ -1997,7 +1997,7 @@ static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID); - + if (!(m = pa_module_load(c->protocol->core, name, argument))) { pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED); return; @@ -2019,7 +2019,7 @@ static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED protocol_error(c); return; } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); m = pa_idxset_get_by_index(c->protocol->core->modules, idx); CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY); @@ -2036,15 +2036,15 @@ static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED u pa_tagstruct *reply; assert(c && t); - if (pa_tagstruct_gets(t, &name) < 0 || - pa_tagstruct_getu32(t, &type) < 0 || - pa_tagstruct_gets(t, &module) < 0 || + if (pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_getu32(t, &type) < 0 || + pa_tagstruct_gets(t, &module) < 0 || pa_tagstruct_gets(t, &argument) < 0 || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, type == 0 || type == 1, tag, PA_ERR_INVALID); @@ -2075,12 +2075,12 @@ static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE protocol_error(c); return; } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, !name || (*name && pa_utf8_valid(name) && (type == 0 || type == 1)), tag, PA_ERR_INVALID); - if (name) + if (name) r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE); else r = pa_autoload_remove_by_index(c->protocol->core, idx); @@ -2141,7 +2141,7 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC protocol_error(c); return; } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); reply = reply_new(tag); @@ -2153,7 +2153,7 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state, NULL))) autoload_fill_tagstruct(reply, a); } - + pa_pstream_send_tagstruct(c->pstream, reply); } @@ -2161,7 +2161,7 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag struct connection *c = userdata; uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX; const char *name = NULL; - + assert(c); assert(t); @@ -2172,7 +2172,7 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag protocol_error(c); return; } - + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); @@ -2182,7 +2182,7 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag pa_sink *sink = NULL; si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); - + if (idx_device != PA_INVALID_INDEX) sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device); else @@ -2199,7 +2199,7 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag pa_source *source; so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx); - + if (idx_device != PA_INVALID_INDEX) source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device); else @@ -2212,9 +2212,9 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag return; } } - + pa_pstream_send_simple_ack(c->pstream, tag); - + } /*** pstream callbacks ***/ @@ -2233,7 +2233,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o struct connection *c = userdata; struct output_stream *stream; assert(p && chunk && userdata); - + if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) { pa_log("client sent block for invalid stream."); /* Ignoring */ @@ -2251,12 +2251,12 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o if (pa_memblockq_push_align(ps->memblockq, chunk) < 0) { pa_tagstruct *t; - + pa_log_warn("failed to push data into queue"); /* Pushing this block into the queue failed, so we simulate * it by skipping ahead */ - + pa_memblockq_seek(ps->memblockq, chunk->length, PA_SEEK_RELATIVE); /* Notify the user */ @@ -2268,7 +2268,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o } ps->underrun = 0; - + pa_sink_notify(ps->sink_input->sink); } else { @@ -2286,10 +2286,10 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o u->memchunk.index = u->memchunk.length = 0; } } - + assert(u->memchunk.memblock); - - l = u->length; + + l = u->length; if (l > chunk->length) l = chunk->length; @@ -2355,7 +2355,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo pa_log_info("Client authenticated by IP ACL."); c->authorized = 1; } - + if (!c->authorized) { struct timeval tv; pa_gettimeofday(&tv); @@ -2374,7 +2374,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo c->client->kill = client_kill_cb; c->client->userdata = c; c->client->owner = p->module; - + c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool); assert(c->pstream); @@ -2399,7 +2399,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo #ifdef HAVE_CREDS if (pa_iochannel_creds_supported(io)) pa_iochannel_creds_enable(io); - + #endif } @@ -2409,14 +2409,14 @@ static int load_key(pa_protocol_native*p, const char*fn) { assert(p); p->auth_cookie_in_property = 0; - + if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) { pa_log_info("using already loaded auth cookie."); pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME); p->auth_cookie_in_property = 1; return 0; } - + if (!fn) fn = PA_NATIVE_COOKIE_FILE; @@ -2427,7 +2427,7 @@ static int load_key(pa_protocol_native*p, const char*fn) { if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) p->auth_cookie_in_property = 1; - + return 0; } @@ -2435,7 +2435,7 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo pa_protocol_native *p; int public = 0; const char *acl; - + assert(c); assert(ma); @@ -2443,14 +2443,14 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo pa_log("auth-anonymous= expects a boolean argument."); return NULL; } - + p = pa_xnew(pa_protocol_native, 1); p->core = c; p->module = m; p->public = public; p->server = NULL; p->auth_ip_acl = NULL; - + #ifdef HAVE_CREDS { int a = 1; @@ -2498,7 +2498,7 @@ pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *serv if (!(p = protocol_new_internal(core, m, ma))) return NULL; - + p->server = server; pa_socket_server_set_callback(p->server, on_connection, p); @@ -2508,7 +2508,7 @@ pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *serv l = pa_strlist_prepend(l, t); pa_property_replace(core, PA_NATIVE_SERVER_PROPERTY_NAME, l); } - + return p; } @@ -2522,7 +2522,7 @@ void pa_protocol_native_free(pa_protocol_native *p) { if (p->server) { char t[256]; - + if (pa_socket_server_get_address(p->server, t, sizeof(t))) { pa_strlist *l; l = pa_property_get(p->core, PA_NATIVE_SERVER_PROPERTY_NAME); @@ -2533,7 +2533,7 @@ void pa_protocol_native_free(pa_protocol_native *p) { else pa_property_remove(p->core, PA_NATIVE_SERVER_PROPERTY_NAME); } - + pa_socket_server_unref(p->server); } @@ -2542,7 +2542,7 @@ void pa_protocol_native_free(pa_protocol_native *p) { if (p->auth_ip_acl) pa_ip_acl_free(p->auth_ip_acl); - + #ifdef HAVE_CREDS pa_xfree(p->auth_group); #endif @@ -2556,6 +2556,6 @@ pa_protocol_native* pa_protocol_native_new_iochannel(pa_core*core, pa_iochannel return NULL; on_connection(NULL, io, p); - + return p; } diff --git a/src/pulsecore/protocol-native.h b/src/pulsecore/protocol-native.h index 5b0910144..fcd4cb37a 100644 --- a/src/pulsecore/protocol-native.h +++ b/src/pulsecore/protocol-native.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 6bfba875e..0a7a7acbf 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -55,7 +55,7 @@ struct connection { pa_defer_event *defer_event; int dead; - + struct { pa_memblock *current_memblock; size_t memblock_index, fragment_size; @@ -120,7 +120,7 @@ static int do_read(struct connection *c) { if (l > c->playback.fragment_size) l = c->playback.fragment_size; - if (c->playback.current_memblock) + if (c->playback.current_memblock) if (c->playback.current_memblock->length - c->playback.memblock_index < l) { pa_memblock_unref(c->playback.current_memblock); c->playback.current_memblock = NULL; @@ -132,7 +132,7 @@ static int do_read(struct connection *c) { assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); c->playback.memblock_index = 0; } - + if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno)); return -1; @@ -144,12 +144,12 @@ static int do_read(struct connection *c) { assert(chunk.memblock); c->playback.memblock_index += r; - + assert(c->input_memblockq); pa_memblockq_push_align(c->input_memblockq, &chunk); assert(c->sink_input); pa_sink_notify(c->sink_input->sink); - + return 0; } @@ -158,25 +158,25 @@ static int do_write(struct connection *c) { ssize_t r; if (!c->source_output) - return 0; + return 0; assert(c->output_memblockq); if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) return 0; - + assert(chunk.memblock && chunk.length); - + if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { pa_memblock_unref(chunk.memblock); pa_log("write(): %s", pa_cstrerror(errno)); return -1; } - + pa_memblockq_drop(c->output_memblockq, &chunk, r); pa_memblock_unref(chunk.memblock); pa_source_notify(c->source_output->source); - + return 0; } @@ -188,7 +188,7 @@ static void do_work(struct connection *c) { if (c->dead) return; - + if (pa_iochannel_is_readable(c->io)) { if (do_read(c) < 0) goto fail; @@ -198,7 +198,7 @@ static void do_work(struct connection *c) { if (pa_iochannel_is_writable(c->io)) { if (do_write(c) < 0) goto fail; - } + } return; @@ -206,7 +206,7 @@ fail: if (c->sink_input) { c->dead = 1; - + pa_iochannel_free(c->io); c->io = NULL; @@ -222,12 +222,12 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { struct connection*c; assert(i && i->userdata && chunk); c = i->userdata; - + if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) { - + if (c->dead) connection_free(c); - + return -1; } @@ -331,7 +331,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->playback.memblock_index = 0; c->playback.fragment_size = 0; c->dead = 0; - + pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); c->client = pa_client_new(p->core, __FILE__, cname); assert(c->client); @@ -354,7 +354,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) pa_log("Failed to create sink input."); goto fail; } - + c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; c->sink_input->kill = sink_input_kill_cb; @@ -416,9 +416,9 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c); assert(c->defer_event); p->core->mainloop->defer_enable(c->defer_event, 0); - + return; - + fail: if (c) connection_free(c); @@ -443,7 +443,7 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv p->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL)); p->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); - + enable = 0; if (pa_modargs_get_value_boolean(ma, "record", &enable) < 0) { pa_log("record= expects a numeric argument."); @@ -462,9 +462,9 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv pa_log("neither playback nor recording enabled for protocol."); goto fail; } - + pa_socket_server_set_callback(p->server, on_connection, p); - + return p; fail: @@ -481,7 +481,7 @@ void pa_protocol_simple_free(pa_protocol_simple *p) { if (p->connections) { while((c = pa_idxset_first(p->connections, NULL))) connection_free(c); - + pa_idxset_free(p->connections, NULL, NULL); } diff --git a/src/pulsecore/protocol-simple.h b/src/pulsecore/protocol-simple.h index 8dfaee349..183f3acc3 100644 --- a/src/pulsecore/protocol-simple.h +++ b/src/pulsecore/protocol-simple.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c index d7c1b31b8..6ebb28630 100644 --- a/src/pulsecore/pstream-util.c +++ b/src/pulsecore/pstream-util.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/pstream-util.h b/src/pulsecore/pstream-util.h index c6d76a7c2..5f1bbd607 100644 --- a/src/pulsecore/pstream-util.h +++ b/src/pulsecore/pstream-util.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 566fb060a..7e1e5f57f 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -111,7 +111,7 @@ struct item_info { struct pa_pstream { PA_REFCNT_DECLARE; - + pa_mainloop_api *mainloop; pa_defer_event *defer_event; pa_iochannel *io; @@ -171,7 +171,7 @@ static void do_something(pa_pstream *p) { pa_pstream_ref(p); pa_mutex_lock(p->mutex); - + p->mainloop->defer_enable(p->defer_event, 0); if (!p->dead && pa_iochannel_is_readable(p->io)) { @@ -193,21 +193,21 @@ static void do_something(pa_pstream *p) { fail: p->dead = 1; - + if (p->die_callback) p->die_callback(p, p->die_callback_userdata); - + pa_mutex_unlock(p->mutex); - + pa_pstream_unref(p); } static void io_callback(pa_iochannel*io, void *userdata) { pa_pstream *p = userdata; - + assert(p); assert(p->io == io); - + do_something(p); } @@ -217,7 +217,7 @@ static void defer_callback(pa_mainloop_api *m, pa_defer_event *e, void*userdata) assert(p); assert(p->defer_event == e); assert(p->mainloop == m); - + do_something(p); } @@ -225,7 +225,7 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *pool) { pa_pstream *p; - + assert(m); assert(io); assert(pool); @@ -241,7 +241,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo p->mainloop = m; p->defer_event = m->defer_new(m, defer_callback, p); m->defer_enable(p->defer_event, 0); - + p->send_queue = pa_queue_new(); assert(p->send_queue); @@ -268,7 +268,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo /* We do importing unconditionally */ p->import = pa_memimport_new(p->mempool, memimport_release_cb, p); - pa_iochannel_socket_set_rcvbuf(io, 1024*8); + pa_iochannel_socket_set_rcvbuf(io, 1024*8); pa_iochannel_socket_set_sndbuf(io, 1024*8); #ifdef HAVE_CREDS @@ -297,7 +297,7 @@ static void pstream_free(pa_pstream *p) { assert(p); pa_pstream_close(p); - + pa_queue_free(p->send_queue, item_free, NULL); if (p->write.current) @@ -305,7 +305,7 @@ static void pstream_free(pa_pstream *p) { if (p->read.memblock) pa_memblock_unref(p->read.memblock); - + if (p->read.packet) pa_packet_unref(p->read.packet); @@ -323,14 +323,14 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre assert(packet); pa_mutex_lock(p->mutex); - + if (p->dead) goto finish; - + i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); - + #ifdef HAVE_CREDS if ((i->with_creds = !!creds)) i->creds = *creds; @@ -346,14 +346,14 @@ finish: void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) { size_t length, idx; - + assert(p); assert(PA_REFCNT_VALUE(p) > 0); assert(channel != (uint32_t) -1); assert(chunk); pa_mutex_lock(p->mutex); - + if (p->dead) goto finish; @@ -363,7 +363,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa while (length > 0) { struct item_info *i; size_t n; - + i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_MEMBLOCK; @@ -371,24 +371,24 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa i->chunk.index = chunk->index + idx; i->chunk.length = n; i->chunk.memblock = pa_memblock_ref(chunk->memblock); - + i->channel = channel; i->offset = offset; i->seek_mode = seek_mode; #ifdef HAVE_CREDS i->with_creds = 0; #endif - + pa_queue_push(p->send_queue, i); idx += n; length -= n; } - + p->mainloop->defer_enable(p->defer_event, 1); finish: - + pa_mutex_unlock(p->mutex); } @@ -400,7 +400,7 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd assert(PA_REFCNT_VALUE(p) > 0); pa_mutex_lock(p->mutex); - + if (p->dead) goto finish; @@ -429,12 +429,12 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda assert(PA_REFCNT_VALUE(p) > 0); pa_mutex_lock(p->mutex); - + if (p->dead) goto finish; /* pa_log("Revoking block %u", block_id); */ - + item = pa_xnew(struct item_info, 1); item->type = PA_PSTREAM_ITEM_SHMREVOKE; item->block_id = block_id; @@ -456,7 +456,7 @@ static void prepare_next_write_item(pa_pstream *p) { if (!(p->write.current = pa_queue_pop(p->send_queue))) return; - + p->write.index = 0; p->write.data = NULL; @@ -465,9 +465,9 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = 0; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = 0; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = 0; - + if (p->write.current->type == PA_PSTREAM_ITEM_PACKET) { - + assert(p->write.current->packet); p->write.data = p->write.current->packet->data; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length); @@ -481,14 +481,14 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(PA_FLAG_SHMREVOKE); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl(p->write.current->block_id); - + } else { uint32_t flags; int send_payload = 1; - + assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK); assert(p->write.current->chunk.memblock); - + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl(p->write.current->channel); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl((uint32_t) (((uint64_t) p->write.current->offset) >> 32)); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = htonl((uint32_t) ((uint64_t) p->write.current->offset)); @@ -507,15 +507,15 @@ static void prepare_next_write_item(pa_pstream *p) { &shm_id, &offset, &length) >= 0) { - + flags |= PA_FLAG_SHMDATA; send_payload = 0; - + p->write.shm_info[PA_PSTREAM_SHM_BLOCKID] = htonl(block_id); p->write.shm_info[PA_PSTREAM_SHM_SHMID] = htonl(shm_id); p->write.shm_info[PA_PSTREAM_SHM_INDEX] = htonl((uint32_t) (offset + p->write.current->chunk.index)); p->write.shm_info[PA_PSTREAM_SHM_LENGTH] = htonl((uint32_t) p->write.current->chunk.length); - + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(sizeof(p->write.shm_info)); p->write.data = p->write.shm_info; } @@ -527,7 +527,7 @@ static void prepare_next_write_item(pa_pstream *p) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index; } - + p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(flags); } @@ -541,7 +541,7 @@ static int do_write(pa_pstream *p) { void *d; size_t l; ssize_t r; - + assert(p); assert(PA_REFCNT_VALUE(p) > 0); @@ -556,13 +556,13 @@ static int do_write(pa_pstream *p) { l = PA_PSTREAM_DESCRIPTOR_SIZE - p->write.index; } else { assert(p->write.data); - + d = (uint8_t*) p->write.data + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } assert(l > 0); - + #ifdef HAVE_CREDS if (p->send_creds_now) { @@ -592,12 +592,12 @@ static int do_write(pa_pstream *p) { static int do_read(pa_pstream *p) { void *d; - size_t l; + size_t l; ssize_t r; - + assert(p); assert(PA_REFCNT_VALUE(p) > 0); - + if (p->read.index < PA_PSTREAM_DESCRIPTOR_SIZE) { d = (uint8_t*) p->read.descriptor + p->read.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->read.index; @@ -610,7 +610,7 @@ static int do_read(pa_pstream *p) { #ifdef HAVE_CREDS { int b = 0; - + if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->read_creds, &b)) <= 0) return -1; @@ -620,7 +620,7 @@ static int do_read(pa_pstream *p) { if ((r = pa_iochannel_read(p->io, d, l)) <= 0) return -1; #endif - + p->read.index += r; if (p->read.index == PA_PSTREAM_DESCRIPTOR_SIZE) { @@ -633,18 +633,18 @@ static int do_read(pa_pstream *p) { pa_log_warn("Recieved SHM frame on a socket where SHM is disabled."); return -1; } - + if (flags == PA_FLAG_SHMRELEASE) { /* This is a SHM memblock release frame with no payload */ /* pa_log("Got release frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */ - + assert(p->export); pa_memexport_process_release(p->export, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); goto frame_done; - + } else if (flags == PA_FLAG_SHMREVOKE) { /* This is a SHM memblock revoke frame with no payload */ @@ -658,68 +658,68 @@ static int do_read(pa_pstream *p) { } length = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]); - + if (length > FRAME_SIZE_MAX_ALLOW) { pa_log_warn("Recieved invalid frame size : %lu", (unsigned long) length); return -1; } - + assert(!p->read.packet && !p->read.memblock); channel = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]); - + if (channel == (uint32_t) -1) { if (flags != 0) { pa_log_warn("Received packet frame with invalid flags value."); return -1; } - + /* Frame is a packet frame */ p->read.packet = pa_packet_new(length); p->read.data = p->read.packet->data; - + } else { if ((flags & PA_FLAG_SEEKMASK) > PA_SEEK_RELATIVE_END) { pa_log_warn("Received memblock frame with invalid seek mode."); return -1; } - + if ((flags & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA) { if (length != sizeof(p->read.shm_info)) { pa_log_warn("Recieved SHM memblock frame with Invalid frame length."); return -1; } - + /* Frame is a memblock frame referencing an SHM memblock */ p->read.data = p->read.shm_info; } else if ((flags & PA_FLAG_SHMMASK) == 0) { /* Frame is a memblock frame */ - + p->read.memblock = pa_memblock_new(p->mempool, length); p->read.data = p->read.memblock->data; } else { - + pa_log_warn("Recieved memblock frame with invalid flags value."); return -1; } } - + } else if (p->read.index > PA_PSTREAM_DESCRIPTOR_SIZE) { /* Frame payload available */ - + if (p->read.memblock && p->recieve_memblock_callback) { /* Is this memblock data? Than pass it to the user */ l = (p->read.index - r) < PA_PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE : (size_t) r; - + if (l > 0) { pa_memchunk chunk; - + chunk.memblock = p->read.memblock; chunk.index = p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE - l; chunk.length = l; @@ -730,7 +730,7 @@ static int do_read(pa_pstream *p) { offset = (int64_t) ( (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) | (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO])))); - + p->recieve_memblock_callback( p, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]), @@ -749,14 +749,14 @@ static int do_read(pa_pstream *p) { /* Frame complete */ if (p->read.index >= ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) + PA_PSTREAM_DESCRIPTOR_SIZE) { - + if (p->read.memblock) { /* This was a memblock frame. We can unref the memblock now */ pa_memblock_unref(p->read.memblock); } else if (p->read.packet) { - + if (p->recieve_packet_callback) #ifdef HAVE_CREDS p->recieve_packet_callback(p, p->read.packet, p->read_creds_valid ? &p->read_creds : NULL, p->recieve_packet_callback_userdata); @@ -767,7 +767,7 @@ static int do_read(pa_pstream *p) { pa_packet_unref(p->read.packet); } else { pa_memblock *b; - + assert((ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA); assert(p->import); @@ -785,7 +785,7 @@ static int do_read(pa_pstream *p) { if (p->recieve_memblock_callback) { int64_t offset; pa_memchunk chunk; - + chunk.memblock = b; chunk.index = 0; chunk.length = b->length; @@ -793,7 +793,7 @@ static int do_read(pa_pstream *p) { offset = (int64_t) ( (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) | (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO])))); - + p->recieve_memblock_callback( p, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]), @@ -827,7 +827,7 @@ frame_done: void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); - + pa_mutex_lock(p->mutex); p->die_callback = cb; p->die_callback_userdata = userdata; @@ -893,7 +893,7 @@ void pa_pstream_unref(pa_pstream*p) { pa_pstream* pa_pstream_ref(pa_pstream*p) { assert(p); assert(PA_REFCNT_VALUE(p) > 0); - + PA_REFCNT_INC(p); return p; } @@ -902,7 +902,7 @@ void pa_pstream_close(pa_pstream *p) { assert(p); pa_mutex_lock(p->mutex); - + p->dead = 1; if (p->import) { @@ -942,7 +942,7 @@ void pa_pstream_use_shm(pa_pstream *p, int enable) { p->use_shm = enable; if (enable) { - + if (!p->export) p->export = pa_memexport_new(p->mempool, memexport_revoke_cb, p); diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h index 26bb7699c..0ab16720a 100644 --- a/src/pulsecore/pstream.h +++ b/src/pulsecore/pstream.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/queue.c b/src/pulsecore/queue.c index 93b119ebc..3132c5c5b 100644 --- a/src/pulsecore/queue.c +++ b/src/pulsecore/queue.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -99,7 +99,7 @@ void* pa_queue_pop(pa_queue *q) { pa_xfree(e); q->length--; - + return p; } diff --git a/src/pulsecore/queue.h b/src/pulsecore/queue.h index 3fb9dea45..cebe4cdf6 100644 --- a/src/pulsecore/queue.h +++ b/src/pulsecore/queue.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/random.c b/src/pulsecore/random.c index 7908e87d8..c3184c78d 100644 --- a/src/pulsecore/random.c +++ b/src/pulsecore/random.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/random.h b/src/pulsecore/random.h index b2bb39347..cdac9ac6e 100644 --- a/src/pulsecore/random.h +++ b/src/pulsecore/random.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -26,5 +26,5 @@ void pa_random_seed(void); void pa_random(void *ret_data, size_t length); - + #endif diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h index 6eb5ee3f9..f3918213a 100644 --- a/src/pulsecore/refcnt.h +++ b/src/pulsecore/refcnt.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index b01420491..e61864dd5 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -54,7 +54,7 @@ struct impl_libsamplerate { pa_memblock *buf1_block, *buf2_block, *buf3_block, *buf4_block; float* buf1, *buf2, *buf3, *buf4; unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples; - + pa_convert_to_float32ne_func_t to_float32ne_func; pa_convert_from_float32ne_func_t from_float32ne_func; SRC_STATE *src_state; @@ -78,7 +78,7 @@ pa_resampler* pa_resampler_new( const pa_sample_spec *b, const pa_channel_map *bm, pa_resample_method_t resample_method) { - + pa_resampler *r = NULL; assert(pool); @@ -110,7 +110,7 @@ pa_resampler* pa_resampler_new( r->o_cm = *bm; else pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels, PA_CHANNEL_MAP_DEFAULT); - + r->i_fz = pa_frame_size(a); r->o_fz = pa_frame_size(b); @@ -126,19 +126,19 @@ pa_resampler* pa_resampler_new( if (libsamplerate_init(r) < 0) goto fail; - + } else { /* Use our own simple non-fp resampler for the trivial cases and when the user selects it */ if (trivial_init(r) < 0) goto fail; } - + return r; - + fail: if (r) pa_xfree(r); - + return NULL; } @@ -147,7 +147,7 @@ void pa_resampler_free(pa_resampler *r) { if (r->impl_free) r->impl_free(r); - + pa_xfree(r); } @@ -157,9 +157,9 @@ void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) { if (r->i_ss.rate == rate) return; - + r->i_ss.rate = rate; - + if (r->impl_update_input_rate) r->impl_update_input_rate(r, rate); } @@ -172,7 +172,7 @@ void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) size_t pa_resampler_request(pa_resampler *r, size_t out_length) { assert(r); - + return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz; } @@ -200,7 +200,7 @@ const char *pa_resample_method_to_string(pa_resample_method_t m) { pa_resample_method_t pa_parse_resample_method(const char *string) { pa_resample_method_t m; - + assert(string); for (m = 0; m < PA_RESAMPLER_MAX; m++) @@ -218,9 +218,9 @@ static void libsamplerate_free(pa_resampler *r) { assert(r); assert(r->impl_data); - + u = r->impl_data; - + if (u->src_state) src_delete(u->src_state); @@ -251,16 +251,16 @@ static void calc_map_table(pa_resampler *r) { for (ic = 0; ic < r->i_ss.channels; ic++) { pa_channel_position_t a, b; - + a = r->i_cm.map[ic]; b = r->o_cm.map[oc]; - + if (a == b || (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_LEFT) || (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_RIGHT) || (a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) || (a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO)) - + u->map_table[oc][i++] = ic; } @@ -278,12 +278,12 @@ static float * convert_to_float(pa_resampler *r, void *input, unsigned n_frames) assert(input); assert(r->impl_data); u = r->impl_data; - + /* Convert the incoming sample into floats and place them in buf1 */ if (!u->to_float32ne_func) return input; - + n_samples = n_frames * r->i_ss.channels; if (u->buf1_samples < n_samples) { @@ -294,7 +294,7 @@ static float * convert_to_float(pa_resampler *r, void *input, unsigned n_frames) u->buf1_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); u->buf1 = u->buf1_block->data; } - + u->to_float32ne_func(n_samples, input, u->buf1); return u->buf1; @@ -305,14 +305,14 @@ static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) { unsigned n_samples; int i_skip, o_skip; unsigned oc; - + assert(r); assert(input); assert(r->impl_data); u = r->impl_data; /* Remap channels and place the result int buf2 */ - + if (!u->map_required) return input; @@ -331,7 +331,7 @@ static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) { o_skip = sizeof(float) * r->o_ss.channels; i_skip = sizeof(float) * r->i_ss.channels; - + for (oc = 0; oc < r->o_ss.channels; oc++) { unsigned i; static const float one = 1.0; @@ -361,7 +361,7 @@ static float *resample(pa_resampler *r, float *input, unsigned *n_frames) { u = r->impl_data; /* Resample the data and place the result in buf3 */ - + if (!u->src_state) return input; @@ -376,16 +376,16 @@ static float *resample(pa_resampler *r, float *input, unsigned *n_frames) { u->buf3_block = pa_memblock_new(r->mempool, sizeof(float) * out_n_samples); u->buf3 = u->buf3_block->data; } - + data.data_in = input; data.input_frames = *n_frames; data.data_out = u->buf3; data.output_frames = out_n_frames; - + data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; data.end_of_input = 0; - + ret = src_process(u->src_state, &data); assert(ret == 0); assert((unsigned) data.input_frames_used == *n_frames); @@ -398,17 +398,17 @@ static float *resample(pa_resampler *r, float *input, unsigned *n_frames) { static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) { struct impl_libsamplerate *u; unsigned n_samples; - + assert(r); assert(input); assert(r->impl_data); u = r->impl_data; - + /* Convert the data into the correct sample type and place the result in buf4 */ if (!u->from_float32ne_func) return input; - + n_samples = n_frames * r->o_ss.channels; if (u->buf4_samples < n_samples) { @@ -419,7 +419,7 @@ static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames u->buf4_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); u->buf4 = u->buf4_block->data; } - + u->from_float32ne_func(n_samples, input, u->buf4); return u->buf4; @@ -438,13 +438,13 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun assert(in->memblock); assert(in->length % r->i_fz == 0); assert(r->impl_data); - + u = r->impl_data; input = ((uint8_t*) in->memblock->data + in->index); n_frames = in->length / r->i_fz; assert(n_frames > 0); - + buf = convert_to_float(r, input, n_frames); buf = remap_channels(r, buf, n_frames); buf = resample(r, buf, &n_frames); @@ -461,7 +461,7 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun out->length = n_frames * r->o_fz; out->index = 0; out->memblock = NULL; - + if (output == u->buf1) { u->buf1 = NULL; u->buf1_samples = 0; @@ -494,7 +494,7 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) { struct impl_libsamplerate *u; - + assert(r); assert(rate > 0); assert(r->impl_data); @@ -540,7 +540,7 @@ static int libsamplerate_init(pa_resampler *r) { r->impl_run = libsamplerate_run; calc_map_table(r); - + return 0; fail: @@ -559,7 +559,7 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out assert(in); assert(out); assert(r->impl_data); - + u = r->impl_data; fz = r->i_fz; @@ -578,34 +578,34 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out /* Do real resampling */ size_t l; unsigned o_index; - + /* The length of the new memory block rounded up */ l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz; - + out->index = 0; out->memblock = pa_memblock_new(r->mempool, l); - + for (o_index = 0;; o_index++, u->o_counter++) { unsigned j; - + j = (u->o_counter * r->i_ss.rate / r->o_ss.rate); j = j > u->i_counter ? j - u->i_counter : 0; - + if (j >= n_frames) break; assert(o_index*fz < out->memblock->length); - + memcpy((uint8_t*) out->memblock->data + fz*o_index, (uint8_t*) in->memblock->data + in->index + fz*j, fz); - + } - + out->length = o_index*fz; } u->i_counter += n_frames; - + /* Normalize counters */ while (u->i_counter >= r->i_ss.rate) { u->i_counter -= r->i_ss.rate; @@ -616,7 +616,7 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out static void trivial_free(pa_resampler *r) { assert(r); - + pa_xfree(r->impl_data); } @@ -634,7 +634,7 @@ static void trivial_update_input_rate(pa_resampler *r, uint32_t rate) { static int trivial_init(pa_resampler*r) { struct impl_trivial *u; - + assert(r); assert(r->i_ss.format == r->o_ss.format); assert(r->i_ss.channels == r->o_ss.channels); @@ -645,7 +645,7 @@ static int trivial_init(pa_resampler*r) { r->impl_run = trivial_run; r->impl_free = trivial_free; r->impl_update_input_rate = trivial_update_input_rate; - + return 0; } diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h index 327e24a29..7a781364d 100644 --- a/src/pulsecore/resampler.h +++ b/src/pulsecore/resampler.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index a7a5ed8f0..ddf729202 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -78,7 +78,7 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { default: assert(0); } - + memset(p, c, length); } @@ -90,42 +90,42 @@ size_t pa_mix( const pa_sample_spec *spec, const pa_cvolume *volume, int mute) { - + assert(streams && data && length && spec); switch (spec->format) { case PA_SAMPLE_S16NE:{ size_t d; unsigned channel = 0; - + for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; - + if (d >= length) return d; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; - + for (i = 0; i < nstreams; i++) { int32_t v; pa_volume_t cvolume = streams[i].volume.values[channel]; - + if (d >= streams[i].chunk.length) return d; - + if (cvolume == PA_VOLUME_MUTED) v = 0; else { v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); - + if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); } - + sum += v; } - + if (volume->values[channel] != PA_VOLUME_NORM) sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); @@ -133,10 +133,10 @@ size_t pa_mix( if (sum > 0x7FFF) sum = 0x7FFF; } - + *((int16_t*) data) = sum; data = (uint8_t*) data + sizeof(int16_t); - + if (++channel >= spec->channels) channel = 0; } @@ -145,35 +145,35 @@ size_t pa_mix( case PA_SAMPLE_S16RE:{ size_t d; unsigned channel = 0; - + for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; - + if (d >= length) return d; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; - + for (i = 0; i < nstreams; i++) { int32_t v; pa_volume_t cvolume = streams[i].volume.values[channel]; - + if (d >= streams[i].chunk.length) return d; - + if (cvolume == PA_VOLUME_MUTED) v = 0; else { v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d))); - + if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); } - + sum += v; } - + if (volume->values[channel] != PA_VOLUME_NORM) sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); @@ -181,40 +181,40 @@ size_t pa_mix( if (sum > 0x7FFF) sum = 0x7FFF; } - + *((int16_t*) data) = INT16_SWAP(sum); data = (uint8_t*) data + sizeof(int16_t); - + if (++channel >= spec->channels) channel = 0; } } - + case PA_SAMPLE_U8: { size_t d; unsigned channel = 0; - + for (d = 0;; d ++) { int32_t sum = 0; - + if (d >= length) return d; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; - + for (i = 0; i < nstreams; i++) { int32_t v; pa_volume_t cvolume = streams[i].volume.values[channel]; - + if (d >= streams[i].chunk.length) return d; - + if (cvolume == PA_VOLUME_MUTED) v = 0; else { v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80; - + if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); } @@ -229,51 +229,51 @@ size_t pa_mix( if (sum > 0x7F) sum = 0x7F; } - + *((uint8_t*) data) = (uint8_t) (sum + 0x80); data = (uint8_t*) data + 1; - + if (++channel >= spec->channels) channel = 0; } } - + case PA_SAMPLE_FLOAT32NE: { size_t d; unsigned channel = 0; - + for (d = 0;; d += sizeof(float)) { float sum = 0; - + if (d >= length) return d; - + if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; - + for (i = 0; i < nstreams; i++) { float v; pa_volume_t cvolume = streams[i].volume.values[channel]; - + if (d >= streams[i].chunk.length) return d; - + if (cvolume == PA_VOLUME_MUTED) v = 0; else { v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); - + if (cvolume != PA_VOLUME_NORM) v *= pa_sw_volume_to_linear(cvolume); } - + sum += v; } - + if (volume->values[channel] != PA_VOLUME_NORM) sum *= pa_sw_volume_to_linear(volume->values[channel]); } - + *((float*) data) = sum; data = (uint8_t*) data + sizeof(float); @@ -281,7 +281,7 @@ size_t pa_mix( channel = 0; } } - + default: pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); abort(); @@ -310,17 +310,17 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol for (channel = 0; channel < spec->channels; channel++) linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); - + for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t = (int32_t)(*d); - + t = (int32_t) (t * linear[channel]); - + if (t < -0x8000) t = -0x8000; if (t > 0x7FFF) t = 0x7FFF; - + *d = (int16_t) t; - + if (++channel >= spec->channels) channel = 0; } @@ -332,66 +332,66 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol size_t n; unsigned channel; double linear[PA_CHANNELS_MAX]; - + for (channel = 0; channel < spec->channels; channel++) linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); - + for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t = (int32_t)(INT16_SWAP(*d)); - + t = (int32_t) (t * linear[channel]); - + if (t < -0x8000) t = -0x8000; if (t > 0x7FFF) t = 0x7FFF; - + *d = INT16_SWAP((int16_t) t); - + if (++channel >= spec->channels) channel = 0; } break; } - + case PA_SAMPLE_U8: { uint8_t *d; size_t n; unsigned channel = 0; - + for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) { int32_t t = (int32_t) *d - 0x80; - + t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel])); - + if (t < -0x80) t = -0x80; if (t > 0x7F) t = 0x7F; - + *d = (uint8_t) (t + 0x80); - + if (++channel >= spec->channels) channel = 0; } break; } - + case PA_SAMPLE_FLOAT32NE: { float *d; int skip; unsigned n; unsigned channel; - + d = (float*) ((uint8_t*) c->memblock->data + c->index); skip = spec->channels * sizeof(float); n = c->length/sizeof(float)/spec->channels; - + for (channel = 0; channel < spec->channels ; channel ++) { float v, *t; - + if (volume->values[channel] == PA_VOLUME_NORM) continue; - + v = (float) pa_sw_volume_to_linear(volume->values[channel]); - + t = d + channel; oil_scalarmult_f32(t, skip, t, skip, &v, n); } diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h index 6b7707925..1883b2cc5 100644 --- a/src/pulsecore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/sconv-s16be.c b/src/pulsecore/sconv-s16be.c index 5ac96320e..3af167dfd 100644 --- a/src/pulsecore/sconv-s16be.c +++ b/src/pulsecore/sconv-s16be.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/sconv-s16be.h b/src/pulsecore/sconv-s16be.h index bd3fd3454..b96f59ab6 100644 --- a/src/pulsecore/sconv-s16be.h +++ b/src/pulsecore/sconv-s16be.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c index d8b93cbda..1743d61ff 100644 --- a/src/pulsecore/sconv-s16le.c +++ b/src/pulsecore/sconv-s16le.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -58,7 +58,7 @@ void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b) { assert(b); #if SWAP_WORDS == 1 - + for (; n > 0; n--) { int16_t s = *(ca++); *(b++) = ((float) INT16_FROM(s))/0x7FFF; @@ -74,19 +74,19 @@ void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b) { void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) { int16_t *cb = b; - + assert(a); assert(b); #if SWAP_WORDS == 1 - + for (; n > 0; n--) { int16_t s; float v = *(a++); if (v > 1) v = 1; - + if (v < -1) v = -1; diff --git a/src/pulsecore/sconv-s16le.h b/src/pulsecore/sconv-s16le.h index ae6e22d21..37e85e2fe 100644 --- a/src/pulsecore/sconv-s16le.h +++ b/src/pulsecore/sconv-s16le.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index 2e5e2dbef..6bea06083 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -41,12 +41,12 @@ static void u8_to_float32ne(unsigned n, const void *a, float *b) { const uint8_t *ca = a; static const double add = -128.0/127.0, factor = 1.0/127.0; - + assert(a); assert(b); oil_scaleconv_f32_u8(b, ca, n, &add, &factor); -} +} static void u8_from_float32ne(unsigned n, const float *a, void *b) { uint8_t *cb = b; @@ -93,7 +93,7 @@ static void ulaw_to_float32ne(unsigned n, const void *a, float *b) { assert(a); assert(b); - + for (; n > 0; n--) *(b++) = st_ulaw2linear16(*(ca++)) * 1.0F / 0x7FFF; } @@ -103,7 +103,7 @@ static void ulaw_from_float32ne(unsigned n, const float *a, void *b) { assert(a); assert(b); - + for (; n > 0; n--) { float v = *(a++); @@ -132,7 +132,7 @@ static void alaw_from_float32ne(unsigned n, const float *a, void *b) { assert(a); assert(b); - + for (; n > 0; n--) { float v = *(a++); diff --git a/src/pulsecore/sconv.h b/src/pulsecore/sconv.h index 4aba06944..52240fd39 100644 --- a/src/pulsecore/sconv.h +++ b/src/pulsecore/sconv.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index 19731b5f3..6188b16c7 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -45,7 +45,7 @@ #if defined(__linux__) && !defined(MADV_REMOVE) #define MADV_REMOVE 9 -#endif +#endif #define MAX_SHM_SIZE (1024*1024*20) @@ -57,7 +57,7 @@ static char *segment_name(char *fn, size_t l, unsigned id) { int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { char fn[32]; int fd = -1; - + assert(m); assert(size > 0); assert(size < MAX_SHM_SIZE); @@ -75,7 +75,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { #elif defined(HAVE_POSIX_MEMALIGN) { int r; - + if ((r = posix_memalign(&m->ptr, sysconf(_SC_PAGESIZE), size)) < 0) { pa_log("posix_memalign() failed: %s", pa_cstrerror(r)); goto fail; @@ -84,9 +84,9 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { #else m->ptr = pa_xmalloc(m->size); #endif - + m->do_unlink = 0; - + } else { #ifdef HAVE_SHM_OPEN pa_random(&m->id, sizeof(m->id)); @@ -96,12 +96,12 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { pa_log("shm_open() failed: %s", pa_cstrerror(errno)); goto fail; } - + if (ftruncate(fd, m->size = size) < 0) { pa_log("ftruncate() failed: %s", pa_cstrerror(errno)); goto fail; } - + if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; @@ -115,9 +115,9 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { } m->shared = shared; - + return 0; - + fail: #ifdef HAVE_SHM_OPEN @@ -157,7 +157,7 @@ void pa_shm_free(pa_shm *m) { char fn[32]; segment_name(fn, sizeof(fn), m->id); - + if (shm_unlink(fn) < 0) pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno)); } @@ -172,7 +172,7 @@ void pa_shm_free(pa_shm *m) { void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { void *ptr; - + assert(m); assert(m->ptr); assert(m->size > 0); @@ -186,7 +186,7 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { * support it */ ptr = (uint8_t*) m->ptr + offset; - + #ifdef __linux__ { /* On Linux ptr must be page aligned */ @@ -194,14 +194,14 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { unsigned o; o = ((unsigned long) ptr) - ((((unsigned long) ptr)/psz) * psz); - + if (o > 0) { ptr = (uint8_t*) ptr + (psz - o); size -= psz - o; } } #endif - + #ifdef MADV_REMOVE if (madvise(ptr, size, MADV_REMOVE) >= 0) return; @@ -210,8 +210,8 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { #ifdef MADV_FREE if (madvise(ptr, size, MADV_FREE) >= 0) return; -#endif - +#endif + #ifdef MADV_DONTNEED madvise(ptr, size, MADV_DONTNEED); #endif @@ -244,7 +244,7 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) { } m->size = st.st_size; - + if ((m->ptr = mmap(NULL, m->size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; @@ -252,11 +252,11 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) { m->do_unlink = 0; m->shared = 1; - + close(fd); - + return 0; - + fail: if (fd >= 0) close(fd); diff --git a/src/pulsecore/shm.h b/src/pulsecore/shm.h index ea72403a2..f621474cb 100644 --- a/src/pulsecore/shm.h +++ b/src/pulsecore/shm.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index d948f0a4c..58fe37d55 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -51,7 +51,7 @@ if (!(condition)) \ pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) { assert(data); - + memset(data, 0, sizeof(*data)); data->resample_method = PA_RESAMPLER_INVALID; return data; @@ -82,7 +82,7 @@ pa_sink_input* pa_sink_input_new( pa_core *core, pa_sink_input_new_data *data, pa_sink_input_flags_t flags) { - + pa_sink_input *i; pa_resampler *resampler = NULL; int r; @@ -100,21 +100,21 @@ pa_sink_input* pa_sink_input_new( if (!data->sink) data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK, 1); - + CHECK_VALIDITY_RETURN_NULL(data->sink); CHECK_VALIDITY_RETURN_NULL(data->sink->state == PA_SINK_RUNNING); if (!data->sample_spec_is_set) data->sample_spec = data->sink->sample_spec; - + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(&data->sample_spec)); - + if (!data->channel_map_is_set) pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); - + CHECK_VALIDITY_RETURN_NULL(pa_channel_map_valid(&data->channel_map)); CHECK_VALIDITY_RETURN_NULL(data->channel_map.channels == data->sample_spec.channels); - + if (!data->volume_is_set) pa_cvolume_reset(&data->volume, data->sample_spec.channels); @@ -134,9 +134,9 @@ pa_sink_input* pa_sink_input_new( if ((flags & PA_SINK_INPUT_VARIABLE_RATE) || !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) || !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) - + if (!(resampler = pa_resampler_new( - core->mempool, + core->mempool, &data->sample_spec, &data->channel_map, &data->sink->sample_spec, &data->sink->channel_map, data->resample_method))) { @@ -157,21 +157,21 @@ pa_sink_input* pa_sink_input_new( i->sample_spec = data->sample_spec; i->channel_map = data->channel_map; i->volume = data->volume; - + i->peek = NULL; i->drop = NULL; i->kill = NULL; i->get_latency = NULL; i->underrun = NULL; i->userdata = NULL; - + i->move_silence = 0; pa_memchunk_reset(&i->resampled_chunk); i->resampler = resampler; i->resample_method = data->resample_method; i->silence_memblock = NULL; - + r = pa_idxset_put(core->sink_inputs, i, &i->index); assert(r == 0); r = pa_idxset_put(i->sink->inputs, i, NULL); @@ -182,13 +182,13 @@ pa_sink_input* pa_sink_input_new( i->name, i->sink->name, pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec)); - + pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); /* We do not call pa_sink_notify() here, because the virtual * functions have not yet been initialized */ - - return i; + + return i; } void pa_sink_input_disconnect(pa_sink_input *i) { @@ -218,17 +218,17 @@ static void sink_input_free(pa_sink_input* i) { if (i->state != PA_SINK_INPUT_DISCONNECTED) pa_sink_input_disconnect(i); - pa_log_info("freed %u \"%s\"", i->index, i->name); - + pa_log_info("freed %u \"%s\"", i->index, i->name); + if (i->resampled_chunk.memblock) pa_memblock_unref(i->resampled_chunk.memblock); - + if (i->resampler) pa_resampler_free(i->resampler); if (i->silence_memblock) pa_memblock_unref(i->silence_memblock); - + pa_xfree(i->name); pa_xfree(i->driver); pa_xfree(i); @@ -245,7 +245,7 @@ void pa_sink_input_unref(pa_sink_input *i) { pa_sink_input* pa_sink_input_ref(pa_sink_input *i) { assert(i); assert(i->ref >= 1); - + i->ref++; return i; } @@ -260,10 +260,10 @@ void pa_sink_input_kill(pa_sink_input*i) { pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) { pa_usec_t r = 0; - + assert(i); assert(i->ref >= 1); - + if (i->get_latency) r += i->get_latency(i); @@ -280,7 +280,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) int ret = -1; int do_volume_adj_here; int volume_is_norm; - + assert(i); assert(i->ref >= 1); assert(chunk); @@ -297,7 +297,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) /* We have just been moved and shall play some silence for a * while until the old sink has drained its playback buffer */ - + if (!i->silence_memblock) i->silence_memblock = pa_silence_memblock_new(i->sink->core->mempool, &i->sink->sample_spec, SILENCE_BUFFER_LENGTH); @@ -309,7 +309,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) do_volume_adj_here = 1; goto finish; } - + if (!i->resampler) { do_volume_adj_here = 0; ret = i->peek(i, chunk); @@ -318,16 +318,16 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map); volume_is_norm = pa_cvolume_is_norm(&i->volume); - + while (!i->resampled_chunk.memblock) { pa_memchunk tchunk; size_t l; - + if ((ret = i->peek(i, &tchunk)) < 0) goto finish; assert(tchunk.length); - + l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); if (l > tchunk.length) @@ -348,7 +348,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) assert(i->resampled_chunk.memblock); assert(i->resampled_chunk.length); - + *chunk = i->resampled_chunk; pa_memblock_ref(i->resampled_chunk.memblock); @@ -375,9 +375,9 @@ finish: /* We've both the same channel map, so let's have the sink do the adjustment for us*/ *volume = i->volume; } - + pa_sink_input_unref(i); - + return ret; } @@ -392,13 +392,13 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt if (chunk->memblock != i->silence_memblock || chunk->index != 0 || - (chunk->memblock && (chunk->length != (i->silence_memblock->length < i->move_silence ? i->silence_memblock->length : i->move_silence)))) + (chunk->memblock && (chunk->length != (i->silence_memblock->length < i->move_silence ? i->silence_memblock->length : i->move_silence)))) return; - + } assert(i->move_silence >= length); - + i->move_silence -= length; if (i->move_silence <= 0) { @@ -415,7 +415,7 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt i->drop(i, chunk, length); return; } - + assert(i->resampled_chunk.memblock); assert(i->resampled_chunk.length >= length); @@ -437,7 +437,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) { if (pa_cvolume_equal(&i->volume, volume)) return; - + i->volume = *volume; pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); } @@ -451,7 +451,7 @@ const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i) { void pa_sink_input_cork(pa_sink_input *i, int b) { int n; - + assert(i); assert(i->ref >= 1); @@ -491,7 +491,7 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name) { if (i->name && name && !strcmp(i->name, name)) return; - + pa_xfree(i->name); i->name = pa_xstrdup(name); @@ -512,7 +512,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { pa_resampler *new_resampler = NULL; pa_memblockq *buffer = NULL; pa_sink *origin; - + assert(i); assert(dest); @@ -532,13 +532,13 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { /* Try to reuse the old resampler if possible */ new_resampler = i->resampler; - + else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) || !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) || !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) { /* Okey, we need a new resampler for the new sink */ - + if (!(new_resampler = pa_resampler_new( dest->core->mempool, &i->sample_spec, &i->channel_map, @@ -554,13 +554,13 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { pa_usec_t silence_usec = 0; buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL); - + /* Let's do a little bit of Voodoo for compensating latency * differences */ old_latency = pa_sink_get_latency(origin); new_latency = pa_sink_get_latency(dest); - + /* The already resampled data should go to the old sink */ if (old_latency >= new_latency) { @@ -571,17 +571,17 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { * while */ silence_usec = old_latency - new_latency; - + } else { size_t l; int volume_is_norm; - + /* The latency of new sink is larger than the latency of * the old sink. Therefore we have to precompute a little * and make sure that this is still played on the old * sink, until we can play the first sample on the new * sink.*/ - + l = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec); volume_is_norm = pa_cvolume_is_norm(&i->volume); @@ -655,7 +655,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { i->resampled_chunk.memblock = NULL; i->resampled_chunk.index = i->resampled_chunk.length = 0; } - + /* Notify everyone */ pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); pa_sink_notify(i->sink); diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 2943dfaef..9d7487f7d 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -52,13 +52,13 @@ struct pa_sink_input { uint32_t index; pa_sink_input_state_t state; pa_sink_input_flags_t flags; - + char *name, *driver; /* may be NULL */ - pa_module *module; /* may be NULL */ - pa_client *client; /* may be NULL */ + pa_module *module; /* may be NULL */ + pa_client *client; /* may be NULL */ pa_sink *sink; - + pa_sample_spec sample_spec; pa_channel_map channel_map; pa_cvolume volume; @@ -67,7 +67,7 @@ struct pa_sink_input { * compensate for latency differences when moving a sink input * "hot" between sinks. */ size_t move_silence; - + int (*peek) (pa_sink_input *i, pa_memchunk *chunk); void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length); void (*kill) (pa_sink_input *i); /* may be NULL */ @@ -88,16 +88,16 @@ typedef struct pa_sink_input_new_data { const char *name, *driver; pa_module *module; pa_client *client; - + pa_sink *sink; - + pa_sample_spec sample_spec; int sample_spec_is_set; pa_channel_map channel_map; int channel_map_is_set; pa_cvolume volume; int volume_is_set; - + pa_resample_method_t resample_method; } pa_sink_input_new_data; diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 056952546..cb0e54c18 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -56,7 +56,7 @@ pa_sink* pa_sink_new( int fail, const pa_sample_spec *spec, const pa_channel_map *map) { - + pa_sink *s; char *n = NULL; char st[256]; @@ -68,7 +68,7 @@ pa_sink* pa_sink_new( assert(spec); CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); - + if (!map) map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); @@ -76,7 +76,7 @@ pa_sink* pa_sink_new( CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name) && *name); - + s = pa_xnew(pa_sink, 1); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) { @@ -94,7 +94,7 @@ pa_sink* pa_sink_new( s->sample_spec = *spec; s->channel_map = *map; - + s->inputs = pa_idxset_new(NULL, NULL); pa_cvolume_reset(&s->sw_volume, spec->channels); @@ -103,7 +103,7 @@ pa_sink* pa_sink_new( s->hw_muted = 0; s->is_hardware = 0; - + s->get_latency = NULL; s->notify = NULL; s->set_hw_volume = NULL; @@ -114,12 +114,12 @@ pa_sink* pa_sink_new( r = pa_idxset_put(core->sinks, s, &s->index); assert(s->index != PA_IDXSET_INVALID && r >= 0); - + pa_sample_spec_snprint(st, sizeof(st), spec); pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); n = pa_sprintf_malloc("%s.monitor", name); - + if (!(s->monitor_source = pa_source_new(core, driver, n, 0, spec, map))) pa_log_warn("failed to create monitor source."); else { @@ -131,15 +131,15 @@ pa_sink* pa_sink_new( } pa_xfree(n); - + pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); - + return s; } void pa_sink_disconnect(pa_sink* s) { pa_sink_input *i, *j = NULL; - + assert(s); assert(s->state == PA_SINK_RUNNING); @@ -147,7 +147,7 @@ void pa_sink_disconnect(pa_sink* s) { pa_namereg_unregister(s->core, s->name); pa_hook_fire(&s->core->hook_sink_disconnect, s); - + while ((i = pa_idxset_first(s->inputs, NULL))) { assert(i != j); pa_sink_input_kill(i); @@ -165,24 +165,24 @@ void pa_sink_disconnect(pa_sink* s) { s->set_hw_volume = NULL; s->set_hw_mute = NULL; s->get_hw_mute = NULL; - + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); } static void sink_free(pa_sink *s) { assert(s); assert(!s->ref); - + if (s->state != PA_SINK_DISCONNECTED) pa_sink_disconnect(s); - pa_log_info("freed %u \"%s\"", s->index, s->name); + pa_log_info("freed %u \"%s\"", s->index, s->name); if (s->monitor_source) { pa_source_unref(s->monitor_source); s->monitor_source = NULL; } - + pa_idxset_free(s->inputs, NULL, NULL); pa_xfree(s->name); @@ -202,7 +202,7 @@ void pa_sink_unref(pa_sink*s) { pa_sink* pa_sink_ref(pa_sink *s) { assert(s); assert(s->ref >= 1); - + s->ref++; return s; } @@ -219,7 +219,7 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) { uint32_t idx = PA_IDXSET_INVALID; pa_sink_input *i; unsigned n = 0; - + assert(s); assert(s->ref >= 1); assert(info); @@ -235,11 +235,11 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) { } info->userdata = i; - + assert(info->chunk.memblock); assert(info->chunk.memblock->data); assert(info->chunk.length); - + info++; maxinfo--; n++; @@ -255,7 +255,7 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t for (; maxinfo > 0; maxinfo--, info++) { pa_sink_input *i = info->userdata; - + assert(i); assert(info->chunk.memblock); @@ -268,19 +268,19 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t info->userdata = NULL; } } - + int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; int r = -1; - + assert(s); assert(s->ref >= 1); assert(length); assert(result); pa_sink_ref(s); - + n = fill_mix_info(s, info, MAX_MIX_CHANNELS); if (n <= 0) @@ -296,7 +296,7 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { result->length = length; pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); - + if (s->sw_muted || !pa_cvolume_is_norm(&volume)) { pa_memchunk_make_writable(result, 0); if (s->sw_muted) @@ -332,7 +332,7 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; int r = -1; - + assert(s); assert(s->ref >= 1); assert(target); @@ -341,7 +341,7 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { assert(target->memblock->data); pa_sink_ref(s); - + n = fill_mix_info(s, info, MAX_MIX_CHANNELS); if (n <= 0) @@ -352,7 +352,7 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { if (target->length > info[0].chunk.length) target->length = info[0].chunk.length; - + memcpy((uint8_t*) target->memblock->data + target->index, (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index, target->length); @@ -360,7 +360,7 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); if (s->sw_muted) - pa_silence_memchunk(target, &s->sample_spec); + pa_silence_memchunk(target, &s->sample_spec); else if (!pa_cvolume_is_norm(&volume)) pa_volume_memchunk(target, &s->sample_spec, &volume); } else @@ -370,7 +370,7 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { &s->sample_spec, &s->sw_volume, s->sw_muted); - + inputs_drop(s, info, n, target->length); if (s->monitor_source) @@ -380,14 +380,14 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { finish: pa_sink_unref(s); - + return r; } void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { pa_memchunk chunk; size_t l, d; - + assert(s); assert(s->ref >= 1); assert(target); @@ -396,14 +396,14 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { assert(target->memblock->data); pa_sink_ref(s); - + l = target->length; d = 0; while (l > 0) { chunk = *target; chunk.index += d; chunk.length -= d; - + if (pa_sink_render_into(s, &chunk) < 0) break; @@ -428,7 +428,7 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { assert(result); /*** This needs optimization ***/ - + result->memblock = pa_memblock_new(s->core->mempool, result->length = length); result->index = 0; @@ -451,7 +451,7 @@ void pa_sink_set_owner(pa_sink *s, pa_module *m) { if (s->owner == m) return; - + s->owner = m; if (s->monitor_source) @@ -462,19 +462,19 @@ void pa_sink_set_owner(pa_sink *s, pa_module *m) { void pa_sink_set_volume(pa_sink *s, pa_mixer_t m, const pa_cvolume *volume) { pa_cvolume *v; - + assert(s); assert(s->ref >= 1); assert(volume); - if (m == PA_MIXER_HARDWARE && s->set_hw_volume) + if (m == PA_MIXER_HARDWARE && s->set_hw_volume) v = &s->hw_volume; else v = &s->sw_volume; if (pa_cvolume_equal(v, volume)) return; - + *v = *volume; if (v == &s->hw_volume) @@ -492,7 +492,7 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_mixer_t m) { if (s->get_hw_volume) s->get_hw_volume(s); - + return &s->hw_volume; } else return &s->sw_volume; @@ -500,18 +500,18 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_mixer_t m) { void pa_sink_set_mute(pa_sink *s, pa_mixer_t m, int mute) { int *t; - + assert(s); assert(s->ref >= 1); - if (m == PA_MIXER_HARDWARE && s->set_hw_mute) + if (m == PA_MIXER_HARDWARE && s->set_hw_mute) t = &s->hw_muted; else t = &s->sw_muted; if (!!*t == !!mute) return; - + *t = !!mute; if (t == &s->hw_muted) @@ -529,7 +529,7 @@ int pa_sink_get_mute(pa_sink *s, pa_mixer_t m) { if (s->get_hw_mute) s->get_hw_mute(s); - + return s->hw_muted; } else return s->sw_muted; @@ -544,18 +544,18 @@ void pa_sink_set_description(pa_sink *s, const char *description) { if (description && s->description && !strcmp(description, s->description)) return; - + pa_xfree(s->description); s->description = pa_xstrdup(description); if (s->monitor_source) { char *n; - + n = pa_sprintf_malloc("Monitor Source of %s", s->description? s->description : s->name); pa_source_set_description(s->monitor_source, n); pa_xfree(n); } - + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 1d870620e..7cfc9e268 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -59,7 +59,7 @@ struct pa_sink { pa_idxset *inputs; pa_source *monitor_source; /* may be NULL */ - + pa_cvolume hw_volume, sw_volume; int hw_muted, sw_muted; @@ -69,7 +69,7 @@ struct pa_sink { int (*get_hw_volume)(pa_sink *s); /* dito */ int (*set_hw_mute)(pa_sink *s); /* dito */ int (*get_hw_mute)(pa_sink *s); /* dito */ - + void *userdata; }; @@ -89,7 +89,7 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result); void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result); int pa_sink_render_into(pa_sink*s, pa_memchunk *target); void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target); - + pa_usec_t pa_sink_get_latency(pa_sink *s); void pa_sink_notify(pa_sink*s); diff --git a/src/pulsecore/sioman.c b/src/pulsecore/sioman.c index d84010ee9..4d5d5562d 100644 --- a/src/pulsecore/sioman.c +++ b/src/pulsecore/sioman.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -40,4 +40,4 @@ int pa_stdio_acquire(void) { void pa_stdio_release(void) { assert(stdio_inuse); stdio_inuse = 0; -} +} diff --git a/src/pulsecore/sioman.h b/src/pulsecore/sioman.h index cd04d140e..bbd521108 100644 --- a/src/pulsecore/sioman.h +++ b/src/pulsecore/sioman.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c index 2ceaf5c3c..b08ba010d 100644 --- a/src/pulsecore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -110,17 +110,17 @@ static pa_socket_client*pa_socket_client_new(pa_mainloop_api *m) { static void free_events(pa_socket_client *c) { assert(c); - + if (c->io_event) { c->mainloop->io_free(c->io_event); c->io_event = NULL; } - + if (c->defer_event) { c->mainloop->defer_free(c->defer_event); c->defer_event = NULL; } - + if (c->timeout_event) { c->mainloop->time_free(c->timeout_event); c->timeout_event = NULL; @@ -137,7 +137,7 @@ static void do_call(pa_socket_client *c) { if (c->fd < 0) goto finish; - + lerror = sizeof(error); if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) { pa_log("getsockopt(): %s", pa_cstrerror(errno)); @@ -157,17 +157,17 @@ static void do_call(pa_socket_client *c) { io = pa_iochannel_new(c->mainloop, c->fd, c->fd); assert(io); - + finish: if (!io && c->fd >= 0) close(c->fd); c->fd = -1; free_events(c); - + assert(c->callback); c->callback(c, io, c->userdata); - + pa_socket_client_unref(c); } @@ -186,9 +186,9 @@ static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUS static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) { int r; assert(c && sa && len); - + pa_make_nonblock_fd(c->fd); - + if ((r = connect(c->fd, sa, len)) < 0) { #ifdef OS_IS_WIN32 if (WSAGetLastError() != EWOULDBLOCK) { @@ -227,7 +227,7 @@ pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) { struct sockaddr_un sa; assert(m && filename); - + memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); @@ -248,24 +248,24 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size assert(c); assert(sa); assert(salen); - + switch (sa->sa_family) { case AF_UNIX: c->local = 1; break; - + case AF_INET: c->local = ((const struct sockaddr_in*) sa)->sin_addr.s_addr == INADDR_LOOPBACK; break; - + case AF_INET6: c->local = memcmp(&((const struct sockaddr_in6*) sa)->sin6_addr, &in6addr_loopback, sizeof(struct in6_addr)) == 0; break; - + default: c->local = 0; } - + if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) { pa_log("socket(): %s", pa_cstrerror(errno)); return -1; @@ -291,13 +291,13 @@ pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct if (sockaddr_prepare(c, sa, salen) < 0) goto fail; - + return c; fail: pa_socket_client_unref(c); return NULL; - + } static void socket_client_free(pa_socket_client *c) { @@ -305,7 +305,7 @@ static void socket_client_free(pa_socket_client *c) { free_events(c); - + if (c->fd >= 0) close(c->fd); @@ -317,7 +317,7 @@ static void socket_client_free(pa_socket_client *c) { if (c->asyncns_io_event) c->mainloop->io_free(c->asyncns_io_event); #endif - + pa_xfree(c); } @@ -342,7 +342,7 @@ void pa_socket_client_set_callback(pa_socket_client *c, void (*on_connection)(pa pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) { struct sockaddr_in6 sa; - + memset(&sa, 0, sizeof(sa)); sa.sin6_family = AF_INET6; sa.sin6_port = htons(port); @@ -370,24 +370,24 @@ static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED if (ret != 0 || !res) goto fail; - + if (res->ai_addr) sockaddr_prepare(c, res->ai_addr, res->ai_addrlen); - + asyncns_freeaddrinfo(res); m->io_free(c->asyncns_io_event); c->asyncns_io_event = NULL; return; - + fail: m->io_free(c->asyncns_io_event); c->asyncns_io_event = NULL; - + errno = EHOSTUNREACH; do_call(c); return; - + } #endif @@ -428,7 +428,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam if (!a.port) a.port = default_port; - + switch (a.type) { case PA_PARSED_ADDRESS_UNIX: if ((c = pa_socket_client_new_unix(m, a.path_or_host))) @@ -447,11 +447,11 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam memset(&hints, 0, sizeof(hints)); hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? PF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? PF_INET6 : PF_UNSPEC); hints.ai_socktype = SOCK_STREAM; - + #ifdef HAVE_LIBASYNCNS { asyncns_t *asyncns; - + if (!(asyncns = asyncns_new(1))) goto finish; @@ -469,7 +469,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam struct addrinfo *res = NULL; ret = getaddrinfo(a.path_or_host, port, &hints, &res); - + if (ret < 0 || !res) goto finish; @@ -477,7 +477,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen))) start_timeout(c); } - + freeaddrinfo(res); #else /* HAVE_GETADDRINFO */ struct hostent *host = NULL; @@ -514,7 +514,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam finish: pa_xfree(a.path_or_host); return c; - + } /* Return non-zero when the target sockaddr is considered diff --git a/src/pulsecore/socket-client.h b/src/pulsecore/socket-client.h index 47e7cd5a9..146ebda87 100644 --- a/src/pulsecore/socket-client.h +++ b/src/pulsecore/socket-client.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c index 4d69b8a47..c878ab1ab 100644 --- a/src/pulsecore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -94,14 +94,14 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U assert(s && s->mainloop == mainloop && s->io_event == e && e && fd >= 0 && fd == s->fd); pa_socket_server_ref(s); - + if ((nfd = accept(fd, NULL, NULL)) < 0) { pa_log("accept(): %s", pa_cstrerror(errno)); goto finish; } pa_fd_set_cloexec(nfd, 1); - + if (!s->on_connection) { close(nfd); goto finish; @@ -123,13 +123,13 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U pa_log_info("TCP connection accepted by tcpwrap."); } #endif - + /* There should be a check for socket type here */ - if (s->type == SOCKET_SERVER_IPV4) + if (s->type == SOCKET_SERVER_IPV4) pa_socket_tcp_low_delay(fd); else pa_socket_low_delay(fd); - + io = pa_iochannel_new(s->mainloop, nfd, nfd); assert(io); s->on_connection(s, io, s->userdata); @@ -141,7 +141,7 @@ finish: pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) { pa_socket_server *s; assert(m && fd >= 0); - + s = pa_xmalloc(sizeof(pa_socket_server)); s->ref = 1; s->fd = fd; @@ -155,7 +155,7 @@ pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) { assert(s->io_event); s->type = SOCKET_SERVER_GENERIC; - + return s; } @@ -171,7 +171,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file int fd = -1; struct sockaddr_un sa; pa_socket_server *s; - + assert(m && filename); if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { @@ -197,7 +197,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file * because not all OS check the access rights on the socket * inodes. */ chmod(filename, 0777); - + if (listen(fd, 5) < 0) { pa_log("listen(): %s", pa_cstrerror(errno)); goto fail; @@ -208,9 +208,9 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file s->filename = pa_xstrdup(filename); s->type = SOCKET_SERVER_UNIX; - + return s; - + fail: if (fd >= 0) close(fd); @@ -247,7 +247,7 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address #endif pa_socket_tcp_low_delay(fd); - + memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(port); @@ -269,7 +269,7 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address } return ss; - + fail: if (fd >= 0) close(fd); @@ -323,9 +323,9 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad ss->type = SOCKET_SERVER_IPV6; ss->tcpwrap_service = pa_xstrdup(tcpwrap_service); } - + return ss; - + fail: if (fd >= 0) close(fd); @@ -350,20 +350,20 @@ pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_ pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { assert(m); assert(port > 0); - + return pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service); } pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { assert(m); assert(port > 0); - + return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service); } pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { struct in_addr ipv4; - + assert(m); assert(name); assert(port > 0); @@ -376,7 +376,7 @@ pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const cha pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { struct in6_addr ipv6; - + assert(m); assert(name); assert(port > 0); @@ -419,7 +419,7 @@ void pa_socket_server_set_callback(pa_socket_server*s, void (*on_connection)(pa_ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { assert(s && c && l > 0); - + switch (s->type) { case SOCKET_SERVER_IPV6: { struct sockaddr_in6 sa; @@ -434,23 +434,23 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { char fqdn[256]; if (!pa_get_fqdn(fqdn, sizeof(fqdn))) return NULL; - + snprintf(c, l, "tcp6:%s:%u", fqdn, (unsigned) ntohs(sa.sin6_port)); - + } else if (memcmp(&in6addr_loopback, &sa.sin6_addr, sizeof(in6addr_loopback)) == 0) { char hn[256]; if (!pa_get_host_name(hn, sizeof(hn))) return NULL; - + snprintf(c, l, "{%s}tcp6:localhost:%u", hn, (unsigned) ntohs(sa.sin6_port)); } else { char ip[INET6_ADDRSTRLEN]; - + if (!inet_ntop(AF_INET6, &sa.sin6_addr, ip, sizeof(ip))) { pa_log("inet_ntop(): %s", pa_cstrerror(errno)); return NULL; } - + snprintf(c, l, "tcp6:[%s]:%u", ip, (unsigned) ntohs(sa.sin6_port)); } @@ -470,13 +470,13 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { char fqdn[256]; if (!pa_get_fqdn(fqdn, sizeof(fqdn))) return NULL; - + snprintf(c, l, "tcp:%s:%u", fqdn, (unsigned) ntohs(sa.sin_port)); } else if (sa.sin_addr.s_addr == INADDR_LOOPBACK) { char hn[256]; if (!pa_get_host_name(hn, sizeof(hn))) return NULL; - + snprintf(c, l, "{%s}tcp:localhost:%u", hn, (unsigned) ntohs(sa.sin_port)); } else { char ip[INET_ADDRSTRLEN]; @@ -485,11 +485,11 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { pa_log("inet_ntop(): %s", pa_cstrerror(errno)); return NULL; } - + snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port)); } - + return c; } @@ -498,7 +498,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { if (!s->filename) return NULL; - + if (!pa_get_host_name(hn, sizeof(hn))) return NULL; diff --git a/src/pulsecore/socket-server.h b/src/pulsecore/socket-server.h index d90c8194e..489878cb9 100644 --- a/src/pulsecore/socket-server.h +++ b/src/pulsecore/socket-server.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c index 856c28e8a..e16f89795 100644 --- a/src/pulsecore/socket-util.c +++ b/src/pulsecore/socket-util.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -78,7 +78,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { struct stat st; assert(c && l && fd >= 0); - + #ifndef OS_IS_WIN32 if (fstat(fd, &st) < 0) { snprintf(c, l, "Invalid client fd"); @@ -88,7 +88,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { #ifndef OS_IS_WIN32 if (S_ISSOCK(st.st_mode)) { -#endif +#endif union { struct sockaddr sa; struct sockaddr_in in; @@ -98,12 +98,12 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { #endif } sa; socklen_t sa_len = sizeof(sa); - + if (getpeername(fd, &sa.sa, &sa_len) >= 0) { if (sa.sa.sa_family == AF_INET) { uint32_t ip = ntohl(sa.in.sin_addr.s_addr); - + snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u", ip >> 24, (ip >> 16) & 0xFF, @@ -159,7 +159,7 @@ int pa_socket_tcp_low_delay(int fd) { assert(fd >= 0); ret = pa_socket_low_delay(fd); - + on = 1; tos = 0; @@ -239,13 +239,13 @@ finish: int pa_unix_socket_remove_stale(const char *fn) { int r; - + if ((r = pa_unix_socket_is_stale(fn)) < 0) return errno != ENOENT ? -1 : 0; if (!r) return 0; - + /* Yes, here is a race condition. But who cares? */ if (unlink(fn) < 0) return -1; diff --git a/src/pulsecore/socket-util.h b/src/pulsecore/socket-util.h index f8248ae72..59b4980db 100644 --- a/src/pulsecore/socket-util.h +++ b/src/pulsecore/socket-util.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index e6f24a795..a277f1f0c 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -52,7 +52,7 @@ static void free_userdata(struct userdata *u) { pa_sink_input_disconnect(u->sink_input); pa_sink_input_unref(u->sink_input); } - + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); if (u->sndfile) @@ -86,10 +86,10 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { } else { if ((n = sf_read_raw(u->sndfile, u->memchunk.memblock->data, BUF_SIZE)) <= 0) n = 0; - + u->memchunk.length = n; } - + if (!u->memchunk.length) { free_userdata(u); return -1; @@ -124,12 +124,12 @@ int pa_play_file( pa_sink *sink, const char *fname, const pa_cvolume *volume) { - + struct userdata *u = NULL; SF_INFO sfinfo; pa_sample_spec ss; pa_sink_input_new_data data; - + assert(sink); assert(fname); @@ -147,7 +147,7 @@ int pa_play_file( } u->readf_function = NULL; - + switch (sfinfo.format & 0xFF) { case SF_FORMAT_PCM_16: case SF_FORMAT_PCM_U8: @@ -159,7 +159,7 @@ int pa_play_file( case SF_FORMAT_ULAW: ss.format = PA_SAMPLE_ULAW; break; - + case SF_FORMAT_ALAW: ss.format = PA_SAMPLE_ALAW; break; @@ -170,7 +170,7 @@ int pa_play_file( u->readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float; break; } - + ss.rate = sfinfo.samplerate; ss.channels = sfinfo.channels; @@ -185,7 +185,7 @@ int pa_play_file( data.name = fname; pa_sink_input_new_data_set_sample_spec(&data, &ss); pa_sink_input_new_data_set_volume(&data, volume); - + if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0))) goto fail; @@ -193,7 +193,7 @@ int pa_play_file( u->sink_input->drop = sink_input_drop; u->sink_input->kill = sink_input_kill; u->sink_input->userdata = u; - + pa_sink_notify(u->sink_input->sink); return 0; @@ -201,6 +201,6 @@ int pa_play_file( fail: if (u) free_userdata(u); - + return -1; } diff --git a/src/pulsecore/sound-file-stream.h b/src/pulsecore/sound-file-stream.h index 28e6a8ba9..0798b4233 100644 --- a/src/pulsecore/sound-file-stream.h +++ b/src/pulsecore/sound-file-stream.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c index 1bf650e22..284bbdda0 100644 --- a/src/pulsecore/sound-file.c +++ b/src/pulsecore/sound-file.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -63,7 +63,7 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, case SF_FORMAT_ULAW: ss->format = PA_SAMPLE_ULAW; break; - + case SF_FORMAT_ALAW: ss->format = PA_SAMPLE_ALAW; break; @@ -86,7 +86,7 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, if (map) pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT); - + if ((l = pa_frame_size(ss)*sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { pa_log("File too large"); goto finish; @@ -102,7 +102,7 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, pa_log("Premature file end"); goto finish; } - + ret = 0; finish: @@ -112,9 +112,9 @@ finish: if (ret != 0 && chunk->memblock) pa_memblock_unref(chunk->memblock); - + return ret; - + } int pa_sound_file_too_big_to_cache(const char *fname) { @@ -139,7 +139,7 @@ int pa_sound_file_too_big_to_cache(const char *fname) { case SF_FORMAT_ULAW: ss.format = PA_SAMPLE_ULAW; break; - + case SF_FORMAT_ALAW: ss.format = PA_SAMPLE_ALAW; break; diff --git a/src/pulsecore/sound-file.h b/src/pulsecore/sound-file.h index 7e3c82eab..cf8168d00 100644 --- a/src/pulsecore/sound-file.h +++ b/src/pulsecore/sound-file.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 352fce142..5783b44a4 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -45,7 +45,7 @@ if (!(condition)) \ pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data) { assert(data); - + memset(data, 0, sizeof(*data)); data->resample_method = PA_RESAMPLER_INVALID; return data; @@ -69,7 +69,7 @@ pa_source_output* pa_source_output_new( pa_core *core, pa_source_output_new_data *data, pa_source_output_flags_t flags) { - + pa_source_output *o; pa_resampler *resampler = NULL; int r; @@ -90,15 +90,15 @@ pa_source_output* pa_source_output_new( CHECK_VALIDITY_RETURN_NULL(data->source); CHECK_VALIDITY_RETURN_NULL(data->source->state == PA_SOURCE_RUNNING); - + if (!data->sample_spec_is_set) data->sample_spec = data->source->sample_spec; - + CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(&data->sample_spec)); if (!data->channel_map_is_set) pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); - + CHECK_VALIDITY_RETURN_NULL(pa_channel_map_valid(&data->channel_map)); CHECK_VALIDITY_RETURN_NULL(data->channel_map.channels == data->sample_spec.channels); @@ -106,7 +106,7 @@ pa_source_output* pa_source_output_new( data->resample_method = core->resample_method; CHECK_VALIDITY_RETURN_NULL(data->resample_method < PA_RESAMPLER_MAX); - + if (pa_idxset_size(data->source->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { pa_log("Failed to create source output: too many outputs per source."); return NULL; @@ -122,7 +122,7 @@ pa_source_output* pa_source_output_new( pa_log_warn("Unsupported resampling operation."); return NULL; } - + o = pa_xnew(pa_source_output, 1); o->ref = 1; o->state = PA_SOURCE_OUTPUT_RUNNING; @@ -131,7 +131,7 @@ pa_source_output* pa_source_output_new( o->module = data->module; o->source = data->source; o->client = data->client; - + o->sample_spec = data->sample_spec; o->channel_map = data->channel_map; @@ -139,10 +139,10 @@ pa_source_output* pa_source_output_new( o->kill = NULL; o->get_latency = NULL; o->userdata = NULL; - + o->resampler = resampler; o->resample_method = data->resample_method; - + r = pa_idxset_put(core->source_outputs, o, &o->index); assert(r == 0); r = pa_idxset_put(o->source->outputs, o, NULL); @@ -153,13 +153,13 @@ pa_source_output* pa_source_output_new( o->name, o->source->name, pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec)); - + pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index); /* We do not call pa_source_notify() here, because the virtual * functions have not yet been initialized */ - - return o; + + return o; } void pa_source_output_disconnect(pa_source_output*o) { @@ -167,7 +167,7 @@ void pa_source_output_disconnect(pa_source_output*o) { assert(o->state != PA_SOURCE_OUTPUT_DISCONNECTED); assert(o->source); assert(o->source->core); - + pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL); pa_idxset_remove_by_data(o->source->outputs, o, NULL); @@ -177,7 +177,7 @@ void pa_source_output_disconnect(pa_source_output*o) { o->push = NULL; o->kill = NULL; o->get_latency = NULL; - + o->state = PA_SOURCE_OUTPUT_DISCONNECTED; } @@ -187,8 +187,8 @@ static void source_output_free(pa_source_output* o) { if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED) pa_source_output_disconnect(o); - pa_log_info("freed %u \"%s\"", o->index, o->name); - + pa_log_info("freed %u \"%s\"", o->index, o->name); + if (o->resampler) pa_resampler_free(o->resampler); @@ -208,7 +208,7 @@ void pa_source_output_unref(pa_source_output* o) { pa_source_output* pa_source_output_ref(pa_source_output *o) { assert(o); assert(o->ref >= 1); - + o->ref++; return o; } @@ -223,7 +223,7 @@ void pa_source_output_kill(pa_source_output*o) { void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { pa_memchunk rchunk; - + assert(o); assert(chunk); assert(chunk->length); @@ -231,7 +231,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { if (o->state == PA_SOURCE_OUTPUT_CORKED) return; - + if (!o->resampler) { o->push(o, chunk); return; @@ -240,7 +240,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { pa_resampler_run(o->resampler, chunk, &rchunk); if (!rchunk.length) return; - + assert(rchunk.memblock); o->push(o, &rchunk); pa_memblock_unref(rchunk.memblock); @@ -255,7 +255,7 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) { if (o->name && name && !strcmp(o->name, name)) return; - + pa_xfree(o->name); o->name = pa_xstrdup(name); @@ -265,7 +265,7 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) { pa_usec_t pa_source_output_get_latency(pa_source_output *o) { assert(o); assert(o->ref >= 1); - + if (o->get_latency) return o->get_latency(o); @@ -274,7 +274,7 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) { void pa_source_output_cork(pa_source_output *o, int b) { int n; - + assert(o); assert(o->ref >= 1); @@ -282,9 +282,9 @@ void pa_source_output_cork(pa_source_output *o, int b) { return; n = o->state == PA_SOURCE_OUTPUT_CORKED && !b; - + o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING; - + if (n) pa_source_notify(o->source); } @@ -292,7 +292,7 @@ void pa_source_output_cork(pa_source_output *o, int b) { pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) { assert(o); assert(o->ref >= 1); - + if (!o->resampler) return o->resample_method; @@ -323,12 +323,12 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { /* Try to reuse the old resampler if possible */ new_resampler = o->resampler; - + else if (!pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) || !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) { /* Okey, we need a new resampler for the new sink */ - + if (!(new_resampler = pa_resampler_new( dest->core->mempool, &dest->sample_spec, &dest->channel_map, diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index f7396a195..827b68eef 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -47,7 +47,7 @@ struct pa_source_output { int ref; uint32_t index; pa_source_output_state_t state; - + char *name, *driver; /* may be NULL */ pa_module *module; /* may be NULL */ @@ -56,14 +56,14 @@ struct pa_source_output { pa_sample_spec sample_spec; pa_channel_map channel_map; - + void (*push)(pa_source_output *o, const pa_memchunk *chunk); void (*kill)(pa_source_output* o); /* may be NULL */ pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */ pa_resampler* resampler; /* may be NULL */ pa_resample_method_t resample_method; - + void *userdata; }; diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index c48d6aaae..702dbeffb 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -52,12 +52,12 @@ pa_source* pa_source_new( int fail, const pa_sample_spec *spec, const pa_channel_map *map) { - + pa_source *s; char st[256]; int r; pa_channel_map tmap; - + assert(core); assert(name); assert(spec); @@ -86,7 +86,7 @@ pa_source* pa_source_new( s->description = NULL; s->driver = pa_xstrdup(driver); s->owner = NULL; - + s->sample_spec = *spec; s->channel_map = *map; @@ -112,16 +112,16 @@ pa_source* pa_source_new( assert(s->index != PA_IDXSET_INVALID && r >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); + pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); - + return s; } void pa_source_disconnect(pa_source *s) { pa_source_output *o, *j = NULL; - + assert(s); assert(s->state == PA_SOURCE_RUNNING); @@ -129,7 +129,7 @@ void pa_source_disconnect(pa_source *s) { pa_namereg_unregister(s->core, s->name); pa_hook_fire(&s->core->hook_source_disconnect, s); - + while ((o = pa_idxset_first(s->outputs, NULL))) { assert(o != j); pa_source_output_kill(o); @@ -144,18 +144,18 @@ void pa_source_disconnect(pa_source *s) { s->set_hw_volume = NULL; s->set_hw_mute = NULL; s->get_hw_mute = NULL; - + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); } static void source_free(pa_source *s) { assert(s); assert(!s->ref); - + if (s->state != PA_SOURCE_DISCONNECTED) pa_source_disconnect(s); - - pa_log_info("freed %u \"%s\"", s->index, s->name); + + pa_log_info("freed %u \"%s\"", s->index, s->name); pa_idxset_free(s->outputs, NULL, NULL); @@ -176,7 +176,7 @@ void pa_source_unref(pa_source *s) { pa_source* pa_source_ref(pa_source *s) { assert(s); assert(s->ref >= 1); - + s->ref++; return s; } @@ -192,7 +192,7 @@ void pa_source_notify(pa_source*s) { static int do_post(void *p, PA_GCC_UNUSED uint32_t idx, PA_GCC_UNUSED int *del, void*userdata) { pa_source_output *o = p; const pa_memchunk *chunk = userdata; - + assert(o); assert(chunk); @@ -209,7 +209,7 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) { if (s->sw_muted || !pa_cvolume_is_norm(&s->sw_volume)) { pa_memchunk vchunk = *chunk; - + pa_memblock_ref(vchunk.memblock); pa_memchunk_make_writable(&vchunk, 0); if (s->sw_muted) @@ -230,7 +230,7 @@ void pa_source_set_owner(pa_source *s, pa_module *m) { if (m == s->owner) return; - + s->owner = m; pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } @@ -247,19 +247,19 @@ pa_usec_t pa_source_get_latency(pa_source *s) { void pa_source_set_volume(pa_source *s, pa_mixer_t m, const pa_cvolume *volume) { pa_cvolume *v; - + assert(s); assert(s->ref >= 1); assert(volume); - if (m == PA_MIXER_HARDWARE && s->set_hw_volume) + if (m == PA_MIXER_HARDWARE && s->set_hw_volume) v = &s->hw_volume; else v = &s->sw_volume; if (pa_cvolume_equal(v, volume)) return; - + *v = *volume; if (v == &s->hw_volume) @@ -277,7 +277,7 @@ const pa_cvolume *pa_source_get_volume(pa_source *s, pa_mixer_t m) { if (s->get_hw_volume) s->get_hw_volume(s); - + return &s->hw_volume; } else return &s->sw_volume; @@ -285,18 +285,18 @@ const pa_cvolume *pa_source_get_volume(pa_source *s, pa_mixer_t m) { void pa_source_set_mute(pa_source *s, pa_mixer_t m, int mute) { int *t; - + assert(s); assert(s->ref >= 1); - if (m == PA_MIXER_HARDWARE && s->set_hw_mute) + if (m == PA_MIXER_HARDWARE && s->set_hw_mute) t = &s->hw_muted; else t = &s->sw_muted; if (!!*t == !!mute) return; - + *t = !!mute; if (t == &s->hw_muted) @@ -314,7 +314,7 @@ int pa_source_get_mute(pa_source *s, pa_mixer_t m) { if (s->get_hw_mute) s->get_hw_mute(s); - + return s->hw_muted; } else return s->sw_muted; @@ -329,7 +329,7 @@ void pa_source_set_description(pa_source *s, const char *description) { if (description && s->description && !strcmp(description, s->description)) return; - + pa_xfree(s->description); s->description = pa_xstrdup(description); diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index 4dbe4e01d..462bc6ff4 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -49,10 +49,10 @@ struct pa_source { uint32_t index; pa_core *core; pa_source_state_t state; - + char *name; char *description, *driver; /* may be NULL */ - + pa_module *owner; /* may be NULL */ pa_sample_spec sample_spec; @@ -65,14 +65,14 @@ struct pa_source { int hw_muted, sw_muted; int is_hardware; - + void (*notify)(pa_source*source); /* may be NULL */ pa_usec_t (*get_latency)(pa_source *s); /* dito */ int (*set_hw_volume)(pa_source *s); /* dito */ - int (*get_hw_volume)(pa_source *s); /* dito */ + int (*get_hw_volume)(pa_source *s); /* dito */ int (*set_hw_mute)(pa_source *s); /* dito */ int (*get_hw_mute)(pa_source *s); /* dito */ - + void *userdata; }; diff --git a/src/pulsecore/strbuf.c b/src/pulsecore/strbuf.c index ef8160dc5..59d572601 100644 --- a/src/pulsecore/strbuf.c +++ b/src/pulsecore/strbuf.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -84,7 +84,7 @@ char *pa_strbuf_tostring(pa_strbuf *sb) { *e = 0; assert(e == t+sb->length); - + return t; } @@ -124,10 +124,10 @@ static void append(pa_strbuf *sb, struct chunk *c) { void pa_strbuf_putsn(pa_strbuf *sb, const char *t, size_t l) { struct chunk *c; assert(sb && t); - + if (!l) return; - + c = pa_xmalloc(sizeof(struct chunk)+l); c->length = l; memcpy(CHUNK_TO_TEXT(c), t, l); @@ -142,7 +142,7 @@ int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) { struct chunk *c = NULL; assert(sb); - + for(;;) { va_list ap; int r; @@ -152,7 +152,7 @@ int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) { va_start(ap, format); r = vsnprintf(CHUNK_TO_TEXT(c), size, format, ap); va_end(ap); - + if (r > -1 && r < size) { c->length = r; append(sb, c); @@ -160,7 +160,7 @@ int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) { } if (r > -1) /* glibc 2.1 */ - size = r+1; + size = r+1; else /* glibc 2.0 */ size *= 2; } diff --git a/src/pulsecore/strbuf.h b/src/pulsecore/strbuf.h index c45fb15f6..04109197e 100644 --- a/src/pulsecore/strbuf.h +++ b/src/pulsecore/strbuf.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/strlist.c b/src/pulsecore/strlist.c index df3a02751..23547bbac 100644 --- a/src/pulsecore/strlist.c +++ b/src/pulsecore/strlist.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -69,7 +69,7 @@ pa_strlist* pa_strlist_remove(pa_strlist *l, const char *s) { while (l) { if (!strcmp(l->str, s)) { pa_strlist *n = l->next; - + if (!prev) { assert(ret == l); ret = n; @@ -80,7 +80,7 @@ pa_strlist* pa_strlist_remove(pa_strlist *l, const char *s) { pa_xfree(l); l = n; - + } else { prev = l; l = l->next; @@ -103,12 +103,12 @@ void pa_strlist_free(pa_strlist *l) { pa_strlist* pa_strlist_pop(pa_strlist *l, char **s) { pa_strlist *r; assert(s); - + if (!l) { *s = NULL; return NULL; } - + *s = l->str; r = l->next; pa_xfree(l); diff --git a/src/pulsecore/strlist.h b/src/pulsecore/strlist.h index 87925d5ec..07d04677e 100644 --- a/src/pulsecore/strlist.h +++ b/src/pulsecore/strlist.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c index 11e85c19c..3a0915cf6 100644 --- a/src/pulsecore/tagstruct.c +++ b/src/pulsecore/tagstruct.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -53,7 +53,7 @@ pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) { pa_tagstruct*t; assert(!data || (data && length)); - + t = pa_xmalloc(sizeof(pa_tagstruct)); t->data = (uint8_t*) data; t->allocated = t->length = data ? length : 0; @@ -61,7 +61,7 @@ pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) { t->dynamic = !data; return t; } - + void pa_tagstruct_free(pa_tagstruct*t) { assert(t); if (t->dynamic) @@ -203,13 +203,13 @@ void pa_tagstruct_puts64(pa_tagstruct*t, int64_t u) { void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) { unsigned i; - + assert(t); extend(t, 2 + map->channels); t->data[t->length++] = PA_TAG_CHANNEL_MAP; t->data[t->length++] = map->channels; - + for (i = 0; i < map->channels; i ++) t->data[t->length++] = (uint8_t) map->map[i]; } @@ -217,13 +217,13 @@ void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) { void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) { unsigned i; pa_volume_t vol; - + assert(t); extend(t, 2 + cvolume->channels * sizeof(pa_volume_t)); t->data[t->length++] = PA_TAG_CVOLUME; t->data[t->length++] = cvolume->channels; - + for (i = 0; i < cvolume->channels; i ++) { vol = htonl(cvolume->values[i]); memcpy(t->data + t->length, &vol, sizeof(pa_volume_t)); @@ -245,10 +245,10 @@ int pa_tagstruct_gets(pa_tagstruct*t, const char **s) { *s = NULL; return 0; } - + if (t->rindex+2 > t->length) return -1; - + if (t->data[t->rindex] != PA_TAG_STRING) return -1; @@ -305,7 +305,7 @@ int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) { if (t->data[t->rindex] != PA_TAG_SAMPLE_SPEC) return -1; - + ss->format = t->data[t->rindex+1]; ss->channels = t->data[t->rindex+2]; memcpy(&ss->rate, t->data+t->rindex+3, 4); @@ -318,7 +318,7 @@ int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) { int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) { uint32_t len; assert(t && p); - + if (t->rindex+5+length > t->length) return -1; @@ -357,7 +357,7 @@ int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) { *b = 0; else return -1; - + t->rindex +=1; return 0; } @@ -434,7 +434,7 @@ int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *u) { int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) { unsigned i; - + assert(t); assert(map); @@ -449,7 +449,7 @@ int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) { if (t->rindex+2+map->channels > t->length) return -1; - + for (i = 0; i < map->channels; i ++) map->map[i] = (int8_t) t->data[t->rindex + 2 + i]; @@ -460,7 +460,7 @@ int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) { int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { unsigned i; pa_volume_t vol; - + assert(t); assert(cvolume); @@ -475,7 +475,7 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { if (t->rindex+2+cvolume->channels*sizeof(pa_volume_t) > t->length) return -1; - + for (i = 0; i < cvolume->channels; i ++) { memcpy(&vol, t->data + t->rindex + 2 + i * sizeof(pa_volume_t), sizeof(pa_volume_t)); cvolume->values[i] = (pa_volume_t) ntohl(vol); @@ -488,7 +488,7 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { void pa_tagstruct_put(pa_tagstruct *t, ...) { va_list va; assert(t); - + va_start(va, t); for (;;) { @@ -551,16 +551,16 @@ void pa_tagstruct_put(pa_tagstruct *t, ...) { abort(); } } - + va_end(va); } int pa_tagstruct_get(pa_tagstruct *t, ...) { va_list va; int ret = 0; - + assert(t); - + va_start(va, t); while (ret == 0) { int tag = va_arg(va, int); @@ -618,11 +618,11 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) { ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *)); break; - + default: abort(); } - + } va_end(va); diff --git a/src/pulsecore/tagstruct.h b/src/pulsecore/tagstruct.h index 4c56f3281..0177ff9d6 100644 --- a/src/pulsecore/tagstruct.h +++ b/src/pulsecore/tagstruct.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index d69790a53..dcd45ea73 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -58,8 +58,8 @@ static void tls_free_cb(void *p) { pa_thread *t = p; assert(t); - - if (!t->thread_func) + + if (!t->thread_func) /* This is a foreign thread, we need to free the struct */ pa_xfree(t); } @@ -76,13 +76,13 @@ static void* internal_thread_func(void *userdata) { t->id = pthread_self(); pa_once(&thread_tls_once, thread_tls_once_func); - + pa_tls_set(thread_tls, t); - + pa_atomic_inc(&t->running); t->thread_func(t->userdata); pa_atomic_add(&t->running, -2); - + return NULL; } @@ -90,7 +90,7 @@ pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { pa_thread *t; assert(thread_func); - + t = pa_xnew(pa_thread, 1); t->thread_func = thread_func; t->userdata = userdata; @@ -116,7 +116,7 @@ int pa_thread_is_running(pa_thread *t) { int policy; struct sched_param param; - + return pthread_getschedparam(t->id, &policy, ¶m) >= 0 || errno != ESRCH; } @@ -125,20 +125,20 @@ int pa_thread_is_running(pa_thread *t) { void pa_thread_free(pa_thread *t) { assert(t); - + pa_thread_join(t); pa_xfree(t); } int pa_thread_join(pa_thread *t) { assert(t); - + return pthread_join(t->id, NULL); } pa_thread* pa_thread_self(void) { pa_thread *t; - + pa_once(&thread_tls_once, thread_tls_once_func); if ((t = pa_tls_get(thread_tls))) @@ -146,7 +146,7 @@ pa_thread* pa_thread_self(void) { /* This is a foreign thread, let's create a pthread structure to * make sure that we can always return a sensible pointer */ - + t = pa_xnew(pa_thread, 1); t->id = pthread_self(); t->thread_func = NULL; @@ -154,7 +154,7 @@ pa_thread* pa_thread_self(void) { pa_atomic_store(&t->running, 2); pa_tls_set(thread_tls, t); - + return t; } @@ -187,7 +187,7 @@ pa_tls* pa_tls_new(pa_free_cb_t free_cb) { pa_xfree(t); return NULL; } - + return t; } @@ -200,13 +200,13 @@ void pa_tls_free(pa_tls *t) { void *pa_tls_get(pa_tls *t) { assert(t); - + return pthread_getspecific(t->key); } void *pa_tls_set(pa_tls *t, void *userdata) { void *r; - + r = pthread_getspecific(t->key); ASSERT_SUCCESS(pthread_setspecific(t->key, userdata)); return r; diff --git a/src/pulsecore/thread-win32.c b/src/pulsecore/thread-win32.c index 98ea06912..38dd4dd65 100644 --- a/src/pulsecore/thread-win32.c +++ b/src/pulsecore/thread-win32.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h index d08990a20..b383bb49b 100644 --- a/src/pulsecore/thread.h +++ b/src/pulsecore/thread.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/tokenizer.c b/src/pulsecore/tokenizer.c index e799c1e64..0bc1c0954 100644 --- a/src/pulsecore/tokenizer.c +++ b/src/pulsecore/tokenizer.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -69,7 +69,7 @@ static void parse(pa_dynarray*a, const char *s, unsigned args) { pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args) { pa_tokenizer *t; - + t = pa_xmalloc(sizeof(pa_tokenizer)); t->dynarray = pa_dynarray_new(); assert(t->dynarray); diff --git a/src/pulsecore/tokenizer.h b/src/pulsecore/tokenizer.h index b9a5c55b9..82cd6db18 100644 --- a/src/pulsecore/tokenizer.h +++ b/src/pulsecore/tokenizer.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/x11prop.c b/src/pulsecore/x11prop.c index dd4ff99eb..03d7990e4 100644 --- a/src/pulsecore/x11prop.c +++ b/src/pulsecore/x11prop.c @@ -48,7 +48,7 @@ char* pa_x11_get_prop(Display *d, const char *name, char *p, size_t l) { unsigned long nbytes_after; unsigned char *prop = NULL; char *ret = NULL; - + Atom a = XInternAtom(d, name, False); if (XGetWindowProperty(d, RootWindow(d, 0), a, 0, (l+2)/4, False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop) != Success) goto finish; @@ -65,6 +65,6 @@ finish: if (prop) XFree(prop); - + return ret; } diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c index cc993e78d..e4b048baa 100644 --- a/src/pulsecore/x11wrap.c +++ b/src/pulsecore/x11wrap.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -42,7 +42,7 @@ struct pa_x11_internal { struct pa_x11_wrapper { pa_core *core; int ref; - + char *property_name; Display *display; @@ -63,7 +63,7 @@ struct pa_x11_client { /* Dispatch all pending X11 events */ static void work(pa_x11_wrapper *w) { assert(w && w->ref >= 1); - + while (XPending(w->display)) { pa_x11_client *c; XEvent e; @@ -90,7 +90,7 @@ static void defer_event(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { assert(m && e && w && w->ref >= 1); m->defer_enable(e, 0); - + work(w); } @@ -154,7 +154,7 @@ static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char w->ref = 1; w->property_name = pa_xstrdup(t); w->display = d; - + PA_LLIST_HEAD_INIT(pa_x11_client, w->clients); PA_LLIST_HEAD_INIT(pa_x11_internal, w->internals); @@ -162,10 +162,10 @@ static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char w->io_event = c->mainloop->io_new(c->mainloop, ConnectionNumber(d), PA_IO_EVENT_INPUT, display_io_event, w); XAddConnectionWatch(d, x11_watch, (XPointer) w); - + r = pa_property_set(c, w->property_name, w); assert(r >= 0); - + return w; } @@ -180,13 +180,13 @@ static void x11_wrapper_free(pa_x11_wrapper*w) { XRemoveConnectionWatch(w->display, x11_watch, (XPointer) w); XCloseDisplay(w->display); - + w->core->mainloop->io_free(w->io_event); w->core->mainloop->defer_free(w->defer_event); while (w->internals) x11_internal_remove(w, w->internals); - + pa_xfree(w->property_name); pa_xfree(w); } @@ -195,7 +195,7 @@ pa_x11_wrapper* pa_x11_wrapper_get(pa_core *c, const char *name) { char t[256]; pa_x11_wrapper *w; assert(c); - + snprintf(t, sizeof(t), "x11-wrapper%s%s", name ? "-" : "", name ? name : ""); if ((w = pa_property_get(c, t))) return pa_x11_wrapper_ref(w); @@ -221,7 +221,7 @@ Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w) { /* Somebody is using us, schedule a output buffer flush */ w->core->mainloop->defer_enable(w->defer_event, 1); - + return w->display; } diff --git a/src/pulsecore/x11wrap.h b/src/pulsecore/x11wrap.h index fcdd9f6c8..b2e8e5349 100644 --- a/src/pulsecore/x11wrap.h +++ b/src/pulsecore/x11wrap.h @@ -5,17 +5,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/tests/channelmap-test.c b/src/tests/channelmap-test.c index 124ce5768..98f36b617 100644 --- a/src/tests/channelmap-test.c +++ b/src/tests/channelmap-test.c @@ -11,23 +11,23 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { pa_channel_map map, map2; pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_AIFF); - + fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map)); pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_AUX); - + fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map)); pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_ALSA); - + fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map)); - + pa_channel_map_parse(&map2, cm); assert(pa_channel_map_equal(&map, &map2)); pa_channel_map_parse(&map2, "left,test"); - + return 0; } diff --git a/src/tests/cpulimit-test.c b/src/tests/cpulimit-test.c index 2302a26d5..d582e9c58 100644 --- a/src/tests/cpulimit-test.c +++ b/src/tests/cpulimit-test.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -47,7 +47,7 @@ static time_t start; static void func(pa_mainloop_api *m, PA_GCC_UNUSED pa_signal_event *e, PA_GCC_UNUSED int sig, PA_GCC_UNUSED void *userdata) { time_t now; time(&now); - + if ((now - start) >= 30) { m->quit(m, 1); fprintf(stderr, "Test failed\n"); @@ -59,7 +59,7 @@ static void func(pa_mainloop_api *m, PA_GCC_UNUSED pa_signal_event *e, PA_GCC_UN int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { pa_mainloop *m; - + m = pa_mainloop_new(); assert(m); @@ -77,7 +77,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { for (;;) { time_t now; time(&now); - + if ((now - start) >= 30) { fprintf(stderr, "Test failed\n"); break; @@ -86,7 +86,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { #endif pa_cpu_limit_done(); - + pa_mainloop_free(m); return 0; diff --git a/src/tests/flist-test.c b/src/tests/flist-test.c index abc0659d9..17ba55c17 100644 --- a/src/tests/flist-test.c +++ b/src/tests/flist-test.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -41,7 +41,7 @@ static int quit = 0; static void spin(void) { int k; - + /* Spin a little */ k = rand() % 10000; for (; k > 0; k--) @@ -100,6 +100,6 @@ int main(int argc, char* argv[]) { pa_thread_free(threads[i]); pa_flist_free(flist, pa_xfree); - + return 0; } diff --git a/src/tests/get-binary-name-test.c b/src/tests/get-binary-name-test.c index 0cea2b6d4..29ebbe223 100644 --- a/src/tests/get-binary-name-test.c +++ b/src/tests/get-binary-name-test.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/tests/hook-list-test.c b/src/tests/hook-list-test.c index d68d1b7d1..6879eae53 100644 --- a/src/tests/hook-list-test.c +++ b/src/tests/hook-list-test.c @@ -22,7 +22,7 @@ int main(int argc, char *argv[]) { pa_hook_connect(&hook, (pa_hook_cb_t) func1, (void*) "slot1"); slot = pa_hook_connect(&hook, (pa_hook_cb_t) func2, (void*) "slot2"); pa_hook_connect(&hook, (pa_hook_cb_t) func1, (void*) "slot3"); - + pa_hook_fire(&hook, (void*) "call1"); pa_hook_slot_free(slot); @@ -30,6 +30,6 @@ int main(int argc, char *argv[]) { pa_hook_fire(&hook, (void*) "call2"); pa_hook_free(&hook); - + return 0; } diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c index 54bdd7750..3953043fb 100644 --- a/src/tests/interpol-test.c +++ b/src/tests/interpol-test.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -57,7 +57,7 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: break; - + case PA_CONTEXT_READY: { static const pa_sample_spec ss = { @@ -65,18 +65,18 @@ static void context_state_callback(pa_context *c, void *userdata) { .rate = 44100, .channels = 1 }; - + fprintf(stderr, "Connection established.\n"); stream = pa_stream_new(c, "interpol-test", &ss, NULL); assert(stream); - + pa_stream_connect_playback(stream, NULL, NULL, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL); pa_stream_set_write_callback(stream, stream_write_cb, NULL); - + break; } - + case PA_CONTEXT_TERMINATED: break; @@ -108,19 +108,19 @@ int main(int argc, char *argv[]) { assert(r >= 0); pa_gettimeofday(&start); - + pa_threaded_mainloop_start(m); for (k = 0; k < 5000; k++) { int success = 0, changed = 0; pa_usec_t t, rtc; struct timeval now, tv; - + pa_threaded_mainloop_lock(m); if (stream) { const pa_timing_info *info; - + if (pa_stream_get_time(stream, &t) >= 0) success = 1; @@ -130,9 +130,9 @@ int main(int argc, char *argv[]) { last_info = info->timestamp; } } - + pa_threaded_mainloop_unlock(m); - + if (success) { pa_gettimeofday(&now); @@ -156,7 +156,7 @@ int main(int argc, char *argv[]) { pa_stream_disconnect(stream); pa_stream_unref(stream); } - + if (context) { pa_context_disconnect(context); pa_context_unref(context); @@ -164,6 +164,6 @@ int main(int argc, char *argv[]) { if (m) pa_threaded_mainloop_free(m); - + return 0; } diff --git a/src/tests/ipacl-test.c b/src/tests/ipacl-test.c index 2566b038e..d1bcb3e3c 100644 --- a/src/tests/ipacl-test.c +++ b/src/tests/ipacl-test.c @@ -37,13 +37,13 @@ int main(int argc, char *argv[]) { int r; pa_ip_acl *acl; - fd = socket(PF_INET, SOCK_STREAM, 0); + fd = socket(PF_INET, SOCK_STREAM, 0); assert(fd >= 0); - + sa.sin_family = AF_INET; sa.sin_port = htons(22); sa.sin_addr.s_addr = inet_addr("127.0.0.1"); - + r = connect(fd, (struct sockaddr*) &sa, sizeof(sa)); assert(r >= 0); @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) { assert(acl); printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd)); pa_ip_acl_free(acl); - + acl = pa_ip_acl_new("127.0.0.2"); assert(acl); printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd)); @@ -86,7 +86,7 @@ int main(int argc, char *argv[]) { assert(acl); printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd)); pa_ip_acl_free(acl); - + close(fd); fd = socket(PF_INET6, SOCK_STREAM, 0); @@ -96,7 +96,7 @@ int main(int argc, char *argv[]) { sa6.sin6_family = AF_INET6; sa6.sin6_port = htons(22); inet_pton(AF_INET6, "::1", &sa6.sin6_addr); - + r = connect(fd, (struct sockaddr*) &sa6, sizeof(sa6)); assert(r >= 0); @@ -131,6 +131,6 @@ int main(int argc, char *argv[]) { pa_ip_acl_free(acl); close(fd); - + return 0; } diff --git a/src/tests/mainloop-test.c b/src/tests/mainloop-test.c index b06d0ed1d..c386251c9 100644 --- a/src/tests/mainloop-test.c +++ b/src/tests/mainloop-test.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -121,6 +121,6 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { #else pa_mainloop_free(m); #endif - + return 0; } diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index 356916984..db76712b4 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -45,7 +45,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { p = pa_mempool_new(0); a = pa_mcalign_new(11); - + pa_memchunk_reset(&c); srand(time(NULL)); @@ -64,7 +64,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { l = c.memblock->length - c.index; l = l <= 1 ? l : rand() % (l-1) +1 ; - + if ((r = read(STDIN_FILENO, (uint8_t*) c.memblock->data + c.index, l)) <= 0) { fprintf(stderr, "read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); break; diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c index ef2e0ad71..13bfdf0d4 100644 --- a/src/tests/memblock-test.c +++ b/src/tests/memblock-test.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -78,7 +78,7 @@ int main(int argc, char *argv[]) { size_t offset, size; const char txt[] = "This is a test!"; - + pool_a = pa_mempool_new(1); pool_b = pa_mempool_new(1); pool_c = pa_mempool_new(1); @@ -86,9 +86,9 @@ int main(int argc, char *argv[]) { pa_mempool_get_shm_id(pool_a, &id_a); pa_mempool_get_shm_id(pool_b, &id_b); pa_mempool_get_shm_id(pool_c, &id_c); - + assert(pool_a && pool_b && pool_c); - + blocks[0] = pa_memblock_new_fixed(pool_a, (void*) txt, sizeof(txt), 1); blocks[1] = pa_memblock_new(pool_a, sizeof(txt)); snprintf(blocks[1]->data, blocks[1]->length, "%s", txt); @@ -102,23 +102,23 @@ int main(int argc, char *argv[]) { mb_a = blocks[i]; assert(mb_a); - + export_a = pa_memexport_new(pool_a, revoke_cb, (void*) "A"); export_b = pa_memexport_new(pool_b, revoke_cb, (void*) "B"); - + assert(export_a && export_b); - + import_b = pa_memimport_new(pool_b, release_cb, (void*) "B"); import_c = pa_memimport_new(pool_c, release_cb, (void*) "C"); - + assert(import_b && import_c); - + r = pa_memexport_put(export_a, mb_a, &id, &shm_id, &offset, &size); assert(r >= 0); assert(shm_id == id_a); printf("A: Memory block exported as %u\n", id); - + mb_b = pa_memimport_get(import_b, id, shm_id, offset, size); assert(mb_b); r = pa_memexport_put(export_b, mb_b, &id, &shm_id, &offset, &size); @@ -127,7 +127,7 @@ int main(int argc, char *argv[]) { pa_memblock_unref(mb_b); printf("B: Memory block exported as %u\n", id); - + mb_c = pa_memimport_get(import_c, id, shm_id, offset, size); assert(mb_c); printf("1 data=%s\n", (char*) mb_c->data); @@ -135,21 +135,21 @@ int main(int argc, char *argv[]) { print_stats(pool_a, "A"); print_stats(pool_b, "B"); print_stats(pool_c, "C"); - + pa_memexport_free(export_b); printf("2 data=%s\n", (char*) mb_c->data); pa_memblock_unref(mb_c); - + pa_memimport_free(import_b); - + pa_memblock_unref(mb_a); - + pa_memimport_free(import_c); pa_memexport_free(export_a); } printf("vaccuuming...\n"); - + pa_mempool_vacuum(pool_a); pa_mempool_vacuum(pool_b); pa_mempool_vacuum(pool_c); diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c index 1ac4577b5..1c0b7fed3 100644 --- a/src/tests/memblockq-test.c +++ b/src/tests/memblockq-test.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) { pa_log_set_maximal_level(PA_LOG_DEBUG); p = pa_mempool_new(0); - + silence = pa_memblock_new_fixed(p, (char*) "__", 2, 1); assert(silence); @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) { chunk1.index = 0; chunk1.length = 2; assert(chunk1.memblock); - + chunk2.memblock = pa_memblock_new_fixed(p, (char*) "TTBB", 4, 1); chunk2.index = 2; chunk2.length = 2; @@ -70,13 +70,13 @@ int main(int argc, char *argv[]) { ret = pa_memblockq_push(bq, &chunk1); assert(ret == 0); - + ret = pa_memblockq_push(bq, &chunk1); assert(ret == 0); - + ret = pa_memblockq_push(bq, &chunk2); assert(ret == 0); - + ret = pa_memblockq_push(bq, &chunk2); assert(ret == 0); @@ -115,19 +115,19 @@ int main(int argc, char *argv[]) { chunk3.index += 2; chunk3.length -= 2; - + ret = pa_memblockq_push(bq, &chunk3); assert(ret == 0); - + printf(">"); pa_memblockq_shorten(bq, 6); - + for (;;) { pa_memchunk out; char *e; size_t n; - + if (pa_memblockq_peek(bq, &out) < 0) break; @@ -137,15 +137,15 @@ int main(int argc, char *argv[]) { pa_memblock_unref(out.memblock); pa_memblockq_drop(bq, &out, out.length); } - + printf("<\n"); - + pa_memblockq_free(bq); pa_memblock_unref(silence); pa_memblock_unref(chunk1.memblock); pa_memblock_unref(chunk2.memblock); pa_memblock_unref(chunk3.memblock); pa_memblock_unref(chunk4.memblock); - + return 0; } diff --git a/src/tests/pacat-simple.c b/src/tests/pacat-simple.c index 364e1ad61..2da67c1a5 100644 --- a/src/tests/pacat-simple.c +++ b/src/tests/pacat-simple.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -43,7 +43,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { .rate = 44100, .channels = 2 }; - + pa_simple *s = NULL; int ret = 1; int error; @@ -61,10 +61,10 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { fprintf(stderr, __FILE__": dup2() failed: %s\n", strerror(errno)); goto finish; } - + close(fd); } - + /* Create a new playback stream */ if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &error))) { fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); @@ -90,7 +90,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) { if ((r = read(STDIN_FILENO, buf, sizeof(buf))) <= 0) { if (r == 0) /* EOF */ break; - + fprintf(stderr, __FILE__": read() failed: %s\n", strerror(errno)); goto finish; } @@ -114,6 +114,6 @@ finish: if (s) pa_simple_free(s); - + return ret; } diff --git a/src/tests/parec-simple.c b/src/tests/parec-simple.c index 45a522888..d7d883607 100644 --- a/src/tests/parec-simple.c +++ b/src/tests/parec-simple.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -46,7 +46,7 @@ static ssize_t loop_write(int fd, const void*data, size_t size) { if (r == 0) break; - + ret += r; data = (const uint8_t*) data + r; size -= r; @@ -95,6 +95,6 @@ finish: if (s) pa_simple_free(s); - + return ret; } diff --git a/src/tests/strlist-test.c b/src/tests/strlist-test.c index 4262a0015..47770b5d9 100644 --- a/src/tests/strlist-test.c +++ b/src/tests/strlist-test.c @@ -16,7 +16,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) { t = pa_strlist_tostring(l); pa_strlist_free(l); - + fprintf(stderr, "1: %s\n", t); l = pa_strlist_parse(t); @@ -29,9 +29,9 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) { l = pa_strlist_pop(l, &u); fprintf(stderr, "3: %s\n", u); pa_xfree(u); - + l = pa_strlist_remove(l, "c"); - + t = pa_strlist_tostring(l); fprintf(stderr, "4: %s\n", t); pa_xfree(t); diff --git a/src/tests/sync-playback.c b/src/tests/sync-playback.c index 39c6aac46..63510eb6b 100644 --- a/src/tests/sync-playback.c +++ b/src/tests/sync-playback.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -67,7 +67,7 @@ static void underflow_cb(struct pa_stream *s, void *userdata) { int i = (int) (long) userdata; fprintf(stderr, "Stream %i finished\n", i); - + if (++n_streams_ready >= 2*NSTREAMS) { fprintf(stderr, "We're done\n"); mainloop_api->quit(mainloop_api, 0); @@ -89,19 +89,19 @@ static void stream_state_callback(pa_stream *s, void *userdata) { int r, i = (int) (long) userdata; fprintf(stderr, "Writing data to stream %i.\n", i); - + r = pa_stream_write(s, data, sizeof(data), nop_free_cb, sizeof(data) * i, PA_SEEK_ABSOLUTE); assert(r == 0); /* Be notified when this stream is drained */ pa_stream_set_underflow_callback(s, underflow_cb, userdata); - + /* All streams have been set up, let's go! */ if (++n_streams_ready >= NSTREAMS) { fprintf(stderr, "Uncorking\n"); pa_operation_unref(pa_stream_cork(s, 0, NULL, NULL)); } - + break; } @@ -121,7 +121,7 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: break; - + case PA_CONTEXT_READY: { int i; @@ -131,18 +131,18 @@ static void context_state_callback(pa_context *c, void *userdata) { char name[64]; fprintf(stderr, "Creating stream %i\n", i); - + snprintf(name, sizeof(name), "stream #%i", i); - + streams[i] = pa_stream_new(c, name, &sample_spec, NULL); assert(streams[i]); pa_stream_set_state_callback(streams[i], stream_state_callback, (void*) (long) i); pa_stream_connect_playback(streams[i], NULL, &buffer_attr, PA_STREAM_START_CORKED, NULL, i == 0 ? NULL : streams[0]); } - + break; } - + case PA_CONTEXT_TERMINATED: mainloop_api->quit(mainloop_api, 0); break; @@ -163,7 +163,7 @@ int main(int argc, char *argv[]) { for (i = 0; i < NSTREAMS; i++) streams[i] = NULL; - + /* Set up a new main loop */ m = pa_mainloop_new(); assert(m); @@ -187,6 +187,6 @@ int main(int argc, char *argv[]) { pa_stream_unref(streams[i]); pa_mainloop_free(m); - + return ret; } diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c index bf3d4cd2c..9d0e5de16 100644 --- a/src/tests/thread-mainloop-test.c +++ b/src/tests/thread-mainloop-test.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -53,19 +53,19 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { pa_threaded_mainloop_start(m); pa_threaded_mainloop_lock(m); - + pa_gettimeofday(&tv); tv.tv_sec += 5; a->time_new(a, &tv, tcb, m); - + fprintf(stderr, "waiting 5s (signal)\n"); pa_threaded_mainloop_wait(m); fprintf(stderr, "wait completed\n"); pa_threaded_mainloop_accept(m); fprintf(stderr, "signal accepted\n"); - + pa_threaded_mainloop_unlock(m); - + fprintf(stderr, "waiting 5s (sleep)\n"); pa_msleep(5000); diff --git a/src/tests/thread-test.c b/src/tests/thread-test.c index 9559cdbbb..2153c9854 100644 --- a/src/tests/thread-test.c +++ b/src/tests/thread-test.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -48,7 +48,7 @@ static void thread_func(void *data) { pa_tls_set(tls, data); pa_log("thread_func() for %s starting...", (char*) pa_tls_get(tls)); - + pa_mutex_lock(mutex); for (;;) { @@ -57,13 +57,13 @@ static void thread_func(void *data) { pa_log("%s waiting ...", (char*) pa_tls_get(tls)); for (;;) { - + if (magic_number < 0) goto quit; if (magic_number != 0) break; - + pa_cond_wait(cond1, mutex); } @@ -75,18 +75,18 @@ static void thread_func(void *data) { pa_once(&once, once_func); pa_cond_signal(cond2, 0); - + pa_log("%s got number %i", (char*) pa_tls_get(tls), k); - + /* Spin! */ for (n = 0; n < k; n++) pa_thread_yield(); - + pa_mutex_lock(mutex); } quit: - + pa_mutex_unlock(mutex); pa_log("thread_func() for %s done...", (char*) pa_tls_get(tls)); @@ -97,25 +97,25 @@ int main(int argc, char *argv[]) { pa_thread* t[THREADS_MAX]; assert(pa_thread_is_running(pa_thread_self())); - + mutex = pa_mutex_new(0); cond1 = pa_cond_new(); cond2 = pa_cond_new(); tls = pa_tls_new(pa_xfree); - + for (i = 0; i < THREADS_MAX; i++) { t[i] = pa_thread_new(thread_func, pa_sprintf_malloc("Thread #%i", i+1)); assert(t[i]); } pa_mutex_lock(mutex); - + pa_log("loop-init"); for (k = 0; k < 100; k++) { assert(magic_number == 0); - + magic_number = (int) rand() % 0x10000; pa_log("iteration %i (%i)", k, magic_number); @@ -126,10 +126,10 @@ int main(int argc, char *argv[]) { } pa_log("loop-exit"); - + magic_number = -1; pa_cond_signal(cond1, 1); - + pa_mutex_unlock(mutex); for (i = 0; i < THREADS_MAX; i++) diff --git a/src/tests/utf8-test.c b/src/tests/utf8-test.c index 2e9f128a7..b9594dcc8 100644 --- a/src/tests/utf8-test.c +++ b/src/tests/utf8-test.c @@ -8,13 +8,13 @@ int main(int argc, char *argv[]) { char *c; - + assert(pa_utf8_valid("hallo")); assert(pa_utf8_valid("hallo\n")); assert(!pa_utf8_valid("hüpfburg\n")); assert(pa_utf8_valid("hallo\n")); assert(pa_utf8_valid("hüpfburg\n")); - + printf("LATIN1: %s\n", c = pa_utf8_filter("hüpfburg")); pa_xfree(c); printf("UTF8: %sx\n", c = pa_utf8_filter("hüpfburg")); diff --git a/src/tests/voltest.c b/src/tests/voltest.c index 3de884aff..dcc1ec51b 100644 --- a/src/tests/voltest.c +++ b/src/tests/voltest.c @@ -12,7 +12,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { double dB = pa_sw_volume_to_dB(v); double f = pa_sw_volume_to_linear(v); - + printf("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i\n", v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f)); diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 450182f5f..f756ac011 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -40,7 +40,7 @@ static void dump_server(const pa_browse_info *i) { if (i->cookie) snprintf(t, sizeof(t), "0x%08x", *i->cookie); - + printf("server: %s\n" "server-version: %s\n" "user-name: %s\n" @@ -65,7 +65,7 @@ static void dump_device(const pa_browse_info *i) { i->device, i->description ? i->description : "n/a", i->sample_spec ? ss : "n/a"); - + } static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata) { @@ -89,7 +89,7 @@ static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_brows dump_server(i); dump_device(i); break; - + case PA_BROWSE_REMOVE_SERVER: printf("\n=> removed server <%s>\n", i->name); break; @@ -109,7 +109,7 @@ static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_brows static void error_callback(pa_browser *b, const char *s, void *userdata) { pa_mainloop_api*m = userdata; - + fprintf(stderr, "Failure: %s\n", s); m->quit(m, 1); } @@ -128,7 +128,7 @@ int main(int argc, char *argv[]) { pa_signal_new(SIGINT, exit_signal_callback, NULL); pa_signal_new(SIGTERM, exit_signal_callback, NULL); signal(SIGPIPE, SIG_IGN); - + if (!(browser = pa_browser_new_full(pa_mainloop_get_api(mainloop), PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, &s))) { fprintf(stderr, "pa_browse_new_full(): %s\n", s); goto finish; @@ -136,7 +136,7 @@ int main(int argc, char *argv[]) { pa_browser_set_callback(browser, browser_callback, NULL); pa_browser_set_error_callback(browser, error_callback, pa_mainloop_get_api(mainloop)); - + ret = 0; pa_mainloop_run(mainloop, &ret); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 1c581f4d9..cb103c999 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -79,20 +79,20 @@ static void do_stream_write(size_t length) { if (!buffer || !buffer_length) return; - + l = length; if (l > buffer_length) l = buffer_length; - + if (pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE) < 0) { fprintf(stderr, "pa_stream_write() failed: %s\n", pa_strerror(pa_context_errno(context))); quit(1); return; } - + buffer_length -= l; buffer_index += l; - + if (!buffer_length) { pa_xfree(buffer); buffer = NULL; @@ -126,7 +126,7 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { quit(1); return; } - + assert(data && length); if (buffer) { @@ -156,7 +156,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_READY: if (verbose) { const pa_buffer_attr *a; - + fprintf(stderr, "Stream successfully created.\n"); if (!(a = pa_stream_get_buffer_attr(s))) @@ -169,13 +169,13 @@ static void stream_state_callback(pa_stream *s, void *userdata) { assert(mode == RECORD); fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize); } - + } } - + break; - + case PA_STREAM_FAILED: default: fprintf(stderr, "Stream error: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); @@ -192,10 +192,10 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: break; - + case PA_CONTEXT_READY: { int r; - + assert(c && !stream); if (verbose) @@ -216,17 +216,17 @@ static void context_state_callback(pa_context *c, void *userdata) { fprintf(stderr, "pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } - + } else { if ((r = pa_stream_connect_record(stream, device, NULL, 0)) < 0) { fprintf(stderr, "pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } } - + break; } - + case PA_CONTEXT_TERMINATED: quit(0); break; @@ -238,10 +238,10 @@ static void context_state_callback(pa_context *c, void *userdata) { } return; - + fail: quit(1); - + } /* Connection draining complete */ @@ -257,14 +257,14 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); quit(1); } - - if (verbose) + + if (verbose) fprintf(stderr, "Playback stream drained.\n"); pa_stream_disconnect(stream); pa_stream_unref(stream); stream = NULL; - + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) pa_context_disconnect(context); else { @@ -286,7 +286,7 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream))) l = 4096; - + buffer = pa_xmalloc(l); if ((r = read(fd, buffer, l)) <= 0) { @@ -296,17 +296,17 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even if (stream) { pa_operation *o; - + if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { fprintf(stderr, "pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(context))); quit(1); return; } - + pa_operation_unref(o); } else quit(0); - + } else { fprintf(stderr, "read() failed: %s\n", strerror(errno)); quit(1); @@ -335,7 +335,7 @@ static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_eve } assert(buffer_length); - + if ((r = write(fd, (uint8_t*) buffer+buffer_index, buffer_length)) <= 0) { fprintf(stderr, "write() failed: %s\n", strerror(errno)); quit(1); @@ -366,7 +366,7 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, static void stream_update_timing_callback(pa_stream *s, int success, void *userdata) { pa_usec_t latency, usec; int negative = 0; - + assert(s); if (!success || @@ -387,13 +387,13 @@ static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int s if (!stream) return; - + pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); } static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { struct timeval next; - + if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) { pa_operation *o; if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL))) @@ -481,7 +481,7 @@ int main(int argc, char *argv[]) { help(bn); ret = 0; goto quit; - + case ARG_VERSION: printf("pacat "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; @@ -525,7 +525,7 @@ int main(int argc, char *argv[]) { break; } - case ARG_CHANNELS: + case ARG_CHANNELS: sample_spec.channels = atoi(optarg); break; @@ -545,7 +545,7 @@ int main(int argc, char *argv[]) { channel_map_set = 1; break; - + default: goto quit; } @@ -560,7 +560,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Channel map doesn't match sample specification\n"); goto quit; } - + if (verbose) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(t, sizeof(t), &sample_spec); @@ -570,22 +570,22 @@ int main(int argc, char *argv[]) { if (!(optind >= argc)) { if (optind+1 == argc) { int fd; - + if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { fprintf(stderr, "open(): %s\n", strerror(errno)); goto quit; } - + if (dup2(fd, mode == PLAYBACK ? 0 : 1) < 0) { fprintf(stderr, "dup2(): %s\n", strerror(errno)); goto quit; } - + close(fd); if (!stream_name) stream_name = pa_xstrdup(argv[optind]); - + } else { fprintf(stderr, "Too many arguments.\n"); goto quit; @@ -616,7 +616,7 @@ int main(int argc, char *argv[]) { #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif - + if (!(stdio_event = mainloop_api->io_new(mainloop_api, mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, @@ -641,7 +641,7 @@ int main(int argc, char *argv[]) { pa_gettimeofday(&tv); pa_timeval_add(&tv, TIME_EVENT_USEC); - + if (!(time_event = mainloop_api->time_new(mainloop_api, &tv, time_event_callback, NULL))) { fprintf(stderr, "time_new() failed.\n"); goto quit; @@ -653,7 +653,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "pa_mainloop_run() failed.\n"); goto quit; } - + quit: if (stream) pa_stream_unref(stream); @@ -670,7 +670,7 @@ quit: assert(mainloop_api); mainloop_api->time_free(time_event); } - + if (m) { pa_signal_done(); pa_mainloop_free(m); @@ -682,6 +682,6 @@ quit: pa_xfree(device); pa_xfree(client_name); pa_xfree(stream_name); - + return ret; } diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index b99127016..d25b26c36 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -64,12 +64,12 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { for (i = 0; i < 5; i++) { int r; - + if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) { pa_log("connect(): %s", strerror(errno)); goto fail; } - + if (r >= 0) break; @@ -94,7 +94,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { FD_SET(fd, &ifds); FD_ZERO(&ofds); - + for (;;) { if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) { pa_log("select(): %s", strerror(errno)); @@ -104,19 +104,19 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (FD_ISSET(0, &ifds)) { ssize_t r; assert(!ibuf_length); - + if ((r = read(0, ibuf, sizeof(ibuf))) <= 0) { if (r == 0) break; - + pa_log("read(): %s", strerror(errno)); goto fail; } - + ibuf_length = (size_t) r; ibuf_index = 0; } - + if (FD_ISSET(fd, &ifds)) { ssize_t r; assert(!obuf_length); @@ -124,7 +124,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if ((r = read(fd, obuf, sizeof(obuf))) <= 0) { if (r == 0) break; - + pa_log("read(): %s", strerror(errno)); goto fail; } @@ -136,12 +136,12 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (FD_ISSET(1, &ofds)) { ssize_t r; assert(obuf_length); - + if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { pa_log("write(): %s", strerror(errno)); goto fail; } - + obuf_length -= (size_t) r; obuf_index += obuf_index; @@ -150,12 +150,12 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (FD_ISSET(fd, &ofds)) { ssize_t r; assert(ibuf_length); - + if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { pa_log("write(): %s", strerror(errno)); goto fail; } - + ibuf_length -= (size_t) r; ibuf_index += obuf_index; @@ -163,24 +163,24 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { FD_ZERO(&ifds); FD_ZERO(&ofds); - + if (obuf_length <= 0) FD_SET(fd, &ifds); else FD_SET(1, &ofds); - + if (ibuf_length <= 0) FD_SET(0, &ifds); else FD_SET(fd, &ofds); } - + ret = 0; - + fail: if (fd >= 0) close(fd); - + return ret; } diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 110585f79..0c418c4fb 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -112,13 +112,13 @@ static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata) pa_bytes_snprint(s, sizeof(s), i->scache_size); printf("Sample cache size: %s\n", s); - + complete_action(); } static void get_server_info_callback(pa_context *c, const pa_server_info *i, void *useerdata) { char s[PA_SAMPLE_SPEC_SNPRINT_MAX]; - + if (!i) { fprintf(stderr, "Failed to get server information: %s\n", pa_strerror(pa_context_errno(c))); quit(1); @@ -149,7 +149,7 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) { char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; - + if (is_last < 0) { fprintf(stderr, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c))); quit(1); @@ -160,7 +160,7 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ complete_action(); return; } - + assert(i); if (nl) @@ -207,7 +207,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int complete_action(); return; } - + assert(i); if (nl) @@ -215,7 +215,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int nl = 1; snprintf(t, sizeof(t), "%u", i->monitor_of_sink); - + printf("*** Source #%u ***\n" "Name: %s\n" "Driver: %s\n" @@ -256,7 +256,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int complete_action(); return; } - + assert(i); if (nl) @@ -264,7 +264,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int nl = 1; snprintf(t, sizeof(t), "%u", i->n_used); - + printf("*** Module #%u ***\n" "Name: %s\n" "Argument: %s\n" @@ -290,7 +290,7 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int complete_action(); return; } - + assert(i); if (nl) @@ -298,7 +298,7 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int nl = 1; snprintf(t, sizeof(t), "%u", i->owner_module); - + printf("*** Client #%u ***\n" "Name: %s\n" "Driver: %s\n" @@ -322,7 +322,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info complete_action(); return; } - + assert(i); if (nl) @@ -331,7 +331,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info snprintf(t, sizeof(t), "%u", i->owner_module); snprintf(k, sizeof(k), "%u", i->client); - + printf("*** Sink Input #%u ***\n" "Name: %s\n" "Driver: %s\n" @@ -372,17 +372,17 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu complete_action(); return; } - + assert(i); if (nl) printf("\n"); nl = 1; - + snprintf(t, sizeof(t), "%u", i->owner_module); snprintf(k, sizeof(k), "%u", i->client); - + printf("*** Source Output #%u ***\n" "Name: %s\n" "Driver: %s\n" @@ -420,16 +420,16 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int complete_action(); return; } - + assert(i); if (nl) printf("\n"); nl = 1; - + pa_bytes_snprint(t, sizeof(t), i->bytes); - + printf("*** Sample #%u ***\n" "Name: %s\n" "Volume: %s\n" @@ -461,7 +461,7 @@ static void get_autoload_info_callback(pa_context *c, const pa_autoload_info *i, complete_action(); return; } - + assert(i); if (nl) @@ -497,11 +497,11 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_CREATING: case PA_STREAM_READY: break; - + case PA_STREAM_TERMINATED: drain(); break; - + case PA_STREAM_FAILED: default: fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); @@ -524,7 +524,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { fprintf(stderr, "Premature end of file\n"); quit(1); } - + pa_stream_write(s, d, length, pa_xfree, 0, PA_SEEK_RELATIVE); sample_length -= length; @@ -551,7 +551,7 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_operation_unref(pa_context_get_server_info(c, get_server_info_callback, NULL)); break; - case PLAY_SAMPLE: + case PLAY_SAMPLE: pa_operation_unref(pa_context_play_sample(c, sample_name, device, PA_VOLUME_NORM, simple_callback, NULL)); break; @@ -562,12 +562,12 @@ static void context_state_callback(pa_context *c, void *userdata) { case UPLOAD_SAMPLE: sample_stream = pa_stream_new(c, sample_name, &sample_spec, NULL); assert(sample_stream); - + pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL); pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL); pa_stream_connect_upload(sample_stream, sample_length); break; - + case EXIT: pa_operation_unref(pa_context_exit_daemon(c, NULL, NULL)); drain(); @@ -578,7 +578,7 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, NULL)); pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, NULL)); pa_operation_unref(pa_context_get_sink_input_info_list(c, get_sink_input_info_callback, NULL)); - pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL)); + pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL)); pa_operation_unref(pa_context_get_client_info_list(c, get_client_info_callback, NULL)); pa_operation_unref(pa_context_get_sample_info_list(c, get_sample_info_callback, NULL)); pa_operation_unref(pa_context_get_autoload_info_list(c, get_autoload_info_callback, NULL)); @@ -591,7 +591,7 @@ static void context_state_callback(pa_context *c, void *userdata) { case MOVE_SOURCE_OUTPUT: pa_operation_unref(pa_context_move_source_output_by_name(c, source_output_idx, source_name, simple_callback, NULL)); break; - + default: assert(0); } @@ -650,14 +650,14 @@ int main(int argc, char *argv[]) { bn = argv[0]; else bn++; - + while ((c = getopt_long(argc, argv, "s:n:h", long_options, NULL)) != -1) { switch (c) { case 'h' : help(bn); ret = 0; goto quit; - + case ARG_VERSION: printf("pactl "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; @@ -680,7 +680,7 @@ int main(int argc, char *argv[]) { if (!client_name) client_name = pa_xstrdup(bn); - + if (optind < argc) { if (!strcmp(argv[optind], "stat")) action = STAT; @@ -712,13 +712,13 @@ int main(int argc, char *argv[]) { tmp[n] = 0; sample_name = pa_xstrdup(tmp); } - + memset(&sfinfo, 0, sizeof(sfinfo)); if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfinfo))) { fprintf(stderr, "Failed to open sound file.\n"); goto quit; } - + sample_spec.format = PA_SAMPLE_FLOAT32; sample_spec.rate = sfinfo.samplerate; sample_spec.channels = sfinfo.channels; @@ -735,7 +735,7 @@ int main(int argc, char *argv[]) { if (optind+2 < argc) device = pa_xstrdup(argv[optind+2]); - + } else if (!strcmp(argv[optind], "remove-sample")) { action = REMOVE_SAMPLE; if (optind+1 >= argc) { @@ -783,7 +783,7 @@ int main(int argc, char *argv[]) { #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif - + if (!(context = pa_context_new(mainloop_api, client_name))) { fprintf(stderr, "pa_context_new() failed.\n"); goto quit; @@ -808,7 +808,7 @@ quit: pa_signal_done(); pa_mainloop_free(m); } - + if (sndfile) sf_close(sndfile); diff --git a/src/utils/padsp.c b/src/utils/padsp.c index a8ac8667e..679a5d012 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -69,7 +69,7 @@ struct fd_info { pthread_mutex_t mutex; int ref; int unusable; - + fd_info_type_t type; int app_fd, thread_fd; @@ -95,7 +95,7 @@ struct fd_info { int volume_modify_count; int optr_n_blocks; - + PA_LLIST_FIELDS(fd_info); }; @@ -248,7 +248,7 @@ static int padsp_disabled(void) { * -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat * emulation, bit 3 -> disable /dev/mixer emulation. Hence a value * of 7 disables padsp entirely. */ - + pthread_mutex_lock(&func_mutex); if (!sym_resolved) { sym = (int*) dlsym(RTLD_DEFAULT, "__padsp_disabled__"); @@ -259,14 +259,14 @@ static int padsp_disabled(void) { if (!sym) return 0; - + return *sym; } static int dsp_cloak_enable(void) { if (padsp_disabled() & 1) return 0; - + if (getenv("PADSP_NO_DSP")) return 0; @@ -302,7 +302,7 @@ static int function_enter(void) { /* Avoid recursive calls */ static pthread_once_t recursion_key_once = PTHREAD_ONCE_INIT; pthread_once(&recursion_key_once, recursion_key_alloc); - + if (pthread_getspecific(recursion_key)) return 0; @@ -320,10 +320,10 @@ static void fd_info_free(fd_info *i) { debug(DEBUG_LEVEL_NORMAL, __FILE__": freeing fd info (fd=%i)\n", i->app_fd); dsp_drain(i); - + if (i->mainloop) pa_threaded_mainloop_stop(i->mainloop); - + if (i->play_stream) { pa_stream_disconnect(i->play_stream); pa_stream_unref(i->play_stream); @@ -338,7 +338,7 @@ static void fd_info_free(fd_info *i) { pa_context_disconnect(i->context); pa_context_unref(i->context); } - + if (i->mainloop) pa_threaded_mainloop_free(i->mainloop); @@ -360,7 +360,7 @@ static void fd_info_free(fd_info *i) { static fd_info *fd_info_ref(fd_info *i) { assert(i); - + pthread_mutex_lock(&i->mutex); assert(i->ref >= 1); i->ref++; @@ -404,7 +404,7 @@ static void context_state_cb(pa_context *c, void *userdata) { static void reset_params(fd_info *i) { assert(i); - + i->sample_spec.format = PA_SAMPLE_U8; i->sample_spec.channels = 1; i->sample_spec.rate = 8000; @@ -418,7 +418,7 @@ static const char *client_name(char *buf, size_t n) { if ((e = getenv("PADSP_CLIENT_NAME"))) return e; - + if (pa_get_binary_name(p, sizeof(p))) snprintf(buf, n, "OSS Emulation[%s]", p); else @@ -440,7 +440,7 @@ static void atfork_prepare(void) { fd_info *i; debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() enter\n"); - + function_enter(); pthread_mutex_lock(&fd_infos_mutex); @@ -452,13 +452,13 @@ static void atfork_prepare(void) { pthread_mutex_lock(&func_mutex); - + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() exit\n"); } static void atfork_parent(void) { fd_info *i; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() enter\n"); pthread_mutex_unlock(&func_mutex); @@ -471,19 +471,19 @@ static void atfork_parent(void) { pthread_mutex_unlock(&fd_infos_mutex); function_exit(); - + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() exit\n"); } static void atfork_child(void) { fd_info *i; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() enter\n"); /* We do only the bare minimum to get all fds closed */ pthread_mutex_init(&func_mutex, NULL); pthread_mutex_init(&fd_infos_mutex, NULL); - + for (i = fd_infos; i; i = i->next) { pthread_mutex_init(&i->mutex, NULL); @@ -556,7 +556,7 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */ pthread_once(&install_atfork_once, install_atfork); - + if (!(i = malloc(sizeof(fd_info)))) { *_errno = ENOMEM; goto fail; @@ -638,12 +638,12 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { unlock_and_fail: pa_threaded_mainloop_unlock(i->mainloop); - + fail: if (i) fd_info_unref(i); - + return NULL; } @@ -671,7 +671,7 @@ static fd_info* fd_info_find(int fd) { fd_info *i; pthread_mutex_lock(&fd_infos_mutex); - + for (i = fd_infos; i; i = i->next) if (i->app_fd == fd && !i->unusable) { fd_info_ref(i); @@ -679,7 +679,7 @@ static fd_info* fd_info_find(int fd) { } pthread_mutex_unlock(&fd_infos_mutex); - + return i; } @@ -907,7 +907,7 @@ static void stream_state_cb(pa_stream *s, void * userdata) { case PA_STREAM_READY: debug(DEBUG_LEVEL_NORMAL, __FILE__": stream established.\n"); break; - + case PA_STREAM_FAILED: debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); fd_info_shutdown(i); @@ -923,7 +923,7 @@ static void stream_state_cb(pa_stream *s, void * userdata) { static int create_playback_stream(fd_info *i) { pa_buffer_attr attr; int n; - + assert(i); fix_metrics(i); @@ -942,7 +942,7 @@ static int create_playback_stream(fd_info *i) { attr.tlength = i->fragment_size * i->n_fragments; attr.prebuf = i->fragment_size; attr.minreq = i->fragment_size; - + if (pa_stream_connect_playback(i->play_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; @@ -952,7 +952,7 @@ static int create_playback_stream(fd_info *i) { setsockopt(i->app_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)); n = i->fragment_size; setsockopt(i->thread_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); - + return 0; fail: @@ -962,7 +962,7 @@ fail: static int create_record_stream(fd_info *i) { pa_buffer_attr attr; int n; - + assert(i); fix_metrics(i); @@ -979,7 +979,7 @@ static int create_record_stream(fd_info *i) { memset(&attr, 0, sizeof(attr)); attr.maxlength = i->fragment_size * (i->n_fragments+1); attr.fragsize = i->fragment_size; - + if (pa_stream_connect_record(i->rec_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; @@ -989,7 +989,7 @@ static int create_record_stream(fd_info *i) { setsockopt(i->app_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); n = i->fragment_size; setsockopt(i->thread_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)); - + return 0; fail: @@ -1025,7 +1025,7 @@ static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_even fd_info *i = userdata; pa_threaded_mainloop_signal(i->mainloop, 0); - + if (flags & PA_IO_EVENT_INPUT) { if (!i->play_stream) { @@ -1035,7 +1035,7 @@ static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_even if (fd_info_copy_data(i, 0) < 0) goto fail; } - + } else if (flags & PA_IO_EVENT_OUTPUT) { if (!i->rec_stream) { @@ -1050,7 +1050,7 @@ static void io_event_cb(pa_mainloop_api *api, pa_io_event *e, int fd, pa_io_even goto fail; return; - + fail: /* We can't do anything better than removing the event source */ fd_info_shutdown(i); @@ -1100,7 +1100,7 @@ static int dsp_open(int flags, int *_errno) { if (!(i->io_event = api->io_new(api, i->thread_fd, i->io_flags, io_event_cb, i))) goto fail; - + pa_threaded_mainloop_unlock(i->mainloop); debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd); @@ -1108,7 +1108,7 @@ static int dsp_open(int flags, int *_errno) { fd_info_add_to_list(i); ret = i->app_fd; fd_info_unref(i); - + return ret; fail: @@ -1116,7 +1116,7 @@ fail: if (i) fd_info_unref(i); - + *_errno = EIO; debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() failed\n"); @@ -1138,7 +1138,7 @@ static void sink_info_cb(pa_context *context, const pa_sink_info *si, int eol, v if (!pa_cvolume_equal(&i->sink_volume, &si->volume)) i->volume_modify_count++; - + i->sink_volume = si->volume; i->sink_index = si->index; @@ -1160,7 +1160,7 @@ static void source_info_cb(pa_context *context, const pa_source_info *si, int eo if (!pa_cvolume_equal(&i->source_volume, &si->volume)) i->volume_modify_count++; - + i->source_volume = si->volume; i->source_index = si->index; @@ -1193,13 +1193,13 @@ static int mixer_open(int flags, int *_errno) { debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open()\n"); - if (!(i = fd_info_new(FD_INFO_MIXER, _errno))) + if (!(i = fd_info_new(FD_INFO_MIXER, _errno))) return -1; - + pa_threaded_mainloop_lock(i->mainloop); pa_context_set_subscribe_callback(i->context, subscribe_cb, i); - + if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, context_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context))); *_errno = EIO; @@ -1274,7 +1274,7 @@ static int mixer_open(int flags, int *_errno) { fd_info_add_to_list(i); ret = i->app_fd; fd_info_unref(i); - + return ret; fail: @@ -1285,7 +1285,7 @@ fail: if (i) fd_info_unref(i); - + *_errno = EIO; debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() failed\n"); @@ -1323,7 +1323,7 @@ static int sndstat_open(int flags, int *_errno) { int e; debug(DEBUG_LEVEL_NORMAL, __FILE__": sndstat_open()\n"); - + if (flags != O_RDONLY #ifdef O_LARGEFILE && flags != (O_RDONLY|O_LARGEFILE) @@ -1401,16 +1401,16 @@ int open(const char *filename, int flags, ...) { } function_exit(); - + if (_errno) errno = _errno; - + return r; } static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; - + switch (request) { case SOUND_MIXER_READ_DEVMASK : debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_DEVMASK\n"); @@ -1423,7 +1423,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno *(int*) argp = SOUND_MASK_IGAIN; break; - + case SOUND_MIXER_READ_STEREODEVS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_STEREODEVS\n"); @@ -1434,7 +1434,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno if (i->source_volume.channels > 1) *(int*) argp |= SOUND_MASK_IGAIN; pa_threaded_mainloop_unlock(i->mainloop); - + break; case SOUND_MIXER_READ_RECSRC: @@ -1452,7 +1452,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno *(int*) argp = 0; break; - + case SOUND_MIXER_READ_PCM: case SOUND_MIXER_READ_IGAIN: { pa_cvolume *v; @@ -1515,23 +1515,23 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno i->operation_success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CONTEXT_CHECK_DEAD_GOTO(i, exit_loop); - + pa_threaded_mainloop_wait(i->mainloop); } exit_loop: - + if (!i->operation_success) debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context))); pa_operation_unref(o); } - + /* We don't wait for completion here */ i->volume_modify_count++; } - + pa_threaded_mainloop_unlock(i->mainloop); - + break; } @@ -1548,7 +1548,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno pa_threaded_mainloop_unlock(i->mainloop); break; } - + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); @@ -1557,44 +1557,44 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno } ret = 0; - + fail: - + return ret; } static int map_format(int *fmt, pa_sample_spec *ss) { - + switch (*fmt) { case AFMT_MU_LAW: ss->format = PA_SAMPLE_ULAW; break; - + case AFMT_A_LAW: ss->format = PA_SAMPLE_ALAW; break; - + case AFMT_S8: *fmt = AFMT_U8; /* fall through */ case AFMT_U8: ss->format = PA_SAMPLE_U8; break; - + case AFMT_U16_BE: *fmt = AFMT_S16_BE; /* fall through */ case AFMT_S16_BE: ss->format = PA_SAMPLE_S16BE; break; - + case AFMT_U16_LE: *fmt = AFMT_S16_LE; /* fall through */ case AFMT_S16_LE: ss->format = PA_SAMPLE_S16LE; break; - + default: ss->format = PA_SAMPLE_S16NE; *fmt = AFMT_S16_NE; @@ -1666,14 +1666,14 @@ static int dsp_flush_socket(fd_info *i) { static int dsp_empty_socket(fd_info *i) { #ifdef SIOCINQ int ret = -1; - + /* Empty the socket */ for (;;) { int l; - + if (i->thread_fd < 0) break; - + if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno)); break; @@ -1683,7 +1683,7 @@ static int dsp_empty_socket(fd_info *i) { ret = 0; break; } - + pa_threaded_mainloop_wait(i->mainloop); } @@ -1700,19 +1700,19 @@ static int dsp_drain(fd_info *i) { if (!i->mainloop) return 0; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": Draining.\n"); pa_threaded_mainloop_lock(i->mainloop); if (dsp_empty_socket(i) < 0) goto fail; - + if (!i->play_stream) goto fail; debug(DEBUG_LEVEL_NORMAL, __FILE__": Really draining.\n"); - + if (!(o = pa_stream_drain(i->play_stream, stream_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; @@ -1721,7 +1721,7 @@ static int dsp_drain(fd_info *i) { i->operation_success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail); - + pa_threaded_mainloop_wait(i->mainloop); } @@ -1731,9 +1731,9 @@ static int dsp_drain(fd_info *i) { } r = 0; - + fail: - + if (o) pa_operation_unref(o); @@ -1755,7 +1755,7 @@ static int dsp_trigger(fd_info *i) { goto fail; debug(DEBUG_LEVEL_NORMAL, __FILE__": Triggering.\n"); - + if (!(o = pa_stream_trigger(i->play_stream, stream_success_cb, i))) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; @@ -1764,7 +1764,7 @@ static int dsp_trigger(fd_info *i) { i->operation_success = 0; while (!pa_operation_get_state(o) != PA_OPERATION_DONE) { PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail); - + pa_threaded_mainloop_wait(i->mainloop); } @@ -1774,9 +1774,9 @@ static int dsp_trigger(fd_info *i) { } r = 0; - + fail: - + if (o) pa_operation_unref(o); @@ -1787,11 +1787,11 @@ fail: static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; - + switch (request) { case SNDCTL_DSP_SETFMT: { debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp); - + pa_threaded_mainloop_lock(i->mainloop); if (*(int*) argp == AFMT_QUERY) @@ -1804,12 +1804,12 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_unlock(i->mainloop); break; } - + case SNDCTL_DSP_SPEED: { pa_sample_spec ss; int valid; char t[256]; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp); pa_threaded_mainloop_lock(i->mainloop); @@ -1821,7 +1821,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) i->sample_spec = ss; free_streams(i); } - + debug(DEBUG_LEVEL_NORMAL, __FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec)); pa_threaded_mainloop_unlock(i->mainloop); @@ -1833,24 +1833,24 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; } - + case SNDCTL_DSP_STEREO: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp); - + pa_threaded_mainloop_lock(i->mainloop); - + i->sample_spec.channels = *(int*) argp ? 2 : 1; free_streams(i); - + pa_threaded_mainloop_unlock(i->mainloop); return 0; case SNDCTL_DSP_CHANNELS: { pa_sample_spec ss; int valid; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp); - + pa_threaded_mainloop_lock(i->mainloop); ss = i->sample_spec; @@ -1860,7 +1860,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) i->sample_spec = ss; free_streams(i); } - + pa_threaded_mainloop_unlock(i->mainloop); if (!valid) { @@ -1878,16 +1878,16 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) fix_metrics(i); *(int*) argp = i->fragment_size; - + pa_threaded_mainloop_unlock(i->mainloop); - + break; case SNDCTL_DSP_SETFRAGMENT: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%08x\n", *(int*) argp); - + pa_threaded_mainloop_lock(i->mainloop); - + i->fragment_size = 1 << ((*(int*) argp) & 31); i->n_fragments = (*(int*) argp) >> 16; @@ -1896,14 +1896,14 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) i->n_fragments = 12; free_streams(i); - + pa_threaded_mainloop_unlock(i->mainloop); - + break; - + case SNDCTL_DSP_GETCAPS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n"); - + *(int*) argp = DSP_CAP_DUPLEX #ifdef DSP_CAP_MULTI | DSP_CAP_MULTI @@ -1913,13 +1913,13 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETODELAY: { int l; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n"); - + pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = 0; - + for (;;) { pa_usec_t usec; @@ -1937,10 +1937,10 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_wait(i->mainloop); } - + exit_loop: -#ifdef SIOCINQ +#ifdef SIOCINQ if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno)); else @@ -1955,39 +1955,39 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) break; } - + case SNDCTL_DSP_RESET: { debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_RESET\n"); - + pa_threaded_mainloop_lock(i->mainloop); free_streams(i); dsp_flush_socket(i); i->optr_n_blocks = 0; - + pa_threaded_mainloop_unlock(i->mainloop); break; } - + case SNDCTL_DSP_GETFMTS: { debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETFMTS\n"); - + *(int*) argp = AFMT_MU_LAW|AFMT_A_LAW|AFMT_U8|AFMT_S16_LE|AFMT_S16_BE; break; } case SNDCTL_DSP_POST: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_POST\n"); - - if (dsp_trigger(i) < 0) + + if (dsp_trigger(i) < 0) *_errno = EIO; break; - case SNDCTL_DSP_SYNC: + case SNDCTL_DSP_SYNC: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SYNC\n"); - - if (dsp_drain(i) < 0) + + if (dsp_drain(i) < 0) *_errno = EIO; break; @@ -2055,36 +2055,36 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SOUND_PCM_READ_RATE: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_RATE\n"); - + pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = i->sample_spec.rate; pa_threaded_mainloop_unlock(i->mainloop); - break; + break; case SOUND_PCM_READ_CHANNELS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_CHANNELS\n"); - + pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = i->sample_spec.channels; pa_threaded_mainloop_unlock(i->mainloop); - break; + break; case SOUND_PCM_READ_BITS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_BITS\n"); - + pa_threaded_mainloop_lock(i->mainloop); *(int*) argp = pa_sample_size(&i->sample_spec)*8; pa_threaded_mainloop_unlock(i->mainloop); - break; - + break; + case SNDCTL_DSP_GETOPTR: { count_info *info; - + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOPTR\n"); info = (count_info*) argp; memset(info, 0, sizeof(*info)); - + pa_threaded_mainloop_lock(i->mainloop); for (;;) { @@ -2095,7 +2095,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) if (pa_stream_get_time(i->play_stream, &usec) >= 0) { size_t k = pa_usec_to_bytes(usec, &i->sample_spec); int m; - + info->bytes = (int) k; m = k / i->fragment_size; info->blocks = m - i->optr_n_blocks; @@ -2111,7 +2111,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) pa_threaded_mainloop_wait(i->mainloop); } - + pa_threaded_mainloop_unlock(i->mainloop); debug(DEBUG_LEVEL_NORMAL, __FILE__": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info->bytes, info->blocks, info->ptr); @@ -2122,7 +2122,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETIPTR: debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETIPTR\n"); goto inval; - + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); @@ -2132,9 +2132,9 @@ inval: } ret = 0; - + fail: - + return ret; } @@ -2165,14 +2165,14 @@ int ioctl(int fd, unsigned long request, ...) { r = mixer_ioctl(i, request, argp, &_errno); else r = dsp_ioctl(i, request, argp, &_errno); - + fd_info_unref(i); if (_errno) errno = _errno; function_exit(); - + return r; } @@ -2194,7 +2194,7 @@ int close(int fd) { fd_info_remove_from_list(i); fd_info_unref(i); - + function_exit(); return 0; @@ -2207,7 +2207,7 @@ int access(const char *pathname, int mode) { errno = EFAULT; return -1; } - + debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname); if (strcmp(pathname, "/dev/dsp") != 0 && @@ -2236,7 +2236,7 @@ int open64(const char *filename, int flags, ...) { mode_t mode = 0; debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename); - + va_start(args, flags); if (flags & O_CREAT) mode = va_arg(args, mode_t); @@ -2259,7 +2259,7 @@ FILE* fopen(const char *filename, const char *mode) { FILE *f = NULL; int fd; mode_t m; - + debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename); if (strcmp(filename, "/dev/dsp") != 0 && @@ -2293,7 +2293,7 @@ FILE* fopen(const char *filename, const char *mode) { close(fd); return NULL; } - + return f; } @@ -2337,9 +2337,9 @@ int fclose(FILE *f) { /* Dirty trick to avoid that the fd is not freed twice, once by us * and once by the real fclose() */ i->app_fd = -1; - + fd_info_unref(i); - + function_exit(); LOAD_FCLOSE_FUNC(); diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 0386c9df8..1617b27dd 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -77,14 +77,14 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context))); quit(1); } - - if (verbose) + + if (verbose) fprintf(stderr, "Playback stream drained.\n"); pa_stream_disconnect(stream); pa_stream_unref(stream); stream = NULL; - + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) pa_context_disconnect(context); else { @@ -111,7 +111,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { if ((bytes = readf_function(sndfile, data, length/k)) > 0) bytes *= k; - + } else bytes = sf_read_raw(sndfile, data, length); @@ -140,7 +140,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { if (verbose) fprintf(stderr, "Stream successfully created\n"); break; - + case PA_STREAM_FAILED: default: fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s)))); @@ -157,10 +157,10 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: break; - + case PA_CONTEXT_READY: { pa_cvolume cv; - + assert(c && !stream); if (verbose) @@ -172,10 +172,10 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_stream_set_state_callback(stream, stream_state_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL); - + break; } - + case PA_CONTEXT_TERMINATED: quit(0); break; @@ -192,7 +192,7 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, if (verbose) fprintf(stderr, "Got SIGINT, exiting.\n"); quit(0); - + } static void help(const char *argv0) { @@ -251,7 +251,7 @@ int main(int argc, char *argv[]) { help(bn); ret = 0; goto quit; - + case ARG_VERSION: printf("paplay "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); ret = 0; @@ -302,7 +302,7 @@ int main(int argc, char *argv[]) { } filename = optind < argc ? argv[optind] : "STDIN"; - + memset(&sfinfo, 0, sizeof(sfinfo)); if (optind < argc) @@ -317,9 +317,9 @@ int main(int argc, char *argv[]) { sample_spec.rate = sfinfo.samplerate; sample_spec.channels = sfinfo.channels; - + readf_function = NULL; - + switch (sfinfo.format & 0xFF) { case SF_FORMAT_PCM_16: case SF_FORMAT_PCM_U8: @@ -327,11 +327,11 @@ int main(int argc, char *argv[]) { sample_spec.format = PA_SAMPLE_S16NE; readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_short; break; - + case SF_FORMAT_ULAW: sample_spec.format = PA_SAMPLE_ULAW; break; - + case SF_FORMAT_ALAW: sample_spec.format = PA_SAMPLE_ALAW; break; @@ -369,13 +369,13 @@ int main(int argc, char *argv[]) { if (!stream_name) stream_name = pa_utf8_filter(n); } - + if (verbose) { char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; pa_sample_spec_snprint(t, sizeof(t), &sample_spec); fprintf(stderr, "Using sample spec '%s'\n", t); } - + /* Set up a new main loop */ if (!(m = pa_mainloop_new())) { fprintf(stderr, "pa_mainloop_new() failed.\n"); @@ -390,7 +390,7 @@ int main(int argc, char *argv[]) { #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif - + /* Create a new connection context */ if (!(context = pa_context_new(mainloop_api, client_name))) { fprintf(stderr, "pa_context_new() failed.\n"); @@ -407,7 +407,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "pa_mainloop_run() failed.\n"); goto quit; } - + quit: if (stream) pa_stream_unref(stream); @@ -427,6 +427,6 @@ quit: if (sndfile) sf_close(sndfile); - + return ret; } diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 6a3c6dbce..00332f657 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -99,7 +99,7 @@ int main(int argc, char *argv[]) { switch (mode) { case DUMP: { char t[1024]; - if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) printf("Server: %s\n", t); if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t))) printf("Source: %s\n", t); @@ -110,10 +110,10 @@ int main(int argc, char *argv[]) { break; } - + case IMPORT: { char t[1024]; - if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) + if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t))) printf("PULSE_SERVER='%s'\nexport PULSE_SERVER\n", t); if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t))) printf("PULSE_SOURCE='%s'\nexport PULSE_SOURCE\n", t); @@ -158,7 +158,7 @@ int main(int argc, char *argv[]) { pa_x11_del_prop(d, "PULSE_SOURCE"); pa_x11_del_prop(d, "PULSE_ID"); pa_x11_del_prop(d, "PULSE_COOKIE"); - + if (server) pa_x11_set_prop(d, "PULSE_SERVER", server); else if (conf->default_server) @@ -169,7 +169,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Failed to get FQDN.\n"); goto finish; } - + pa_x11_set_prop(d, "PULSE_SERVER", hn); } @@ -184,7 +184,7 @@ int main(int argc, char *argv[]) { pa_x11_set_prop(d, "PULSE_SOURCE", conf->default_source); pa_client_conf_free(conf); - + if (pa_authkey_load_auto(cookie_file, cookie, sizeof(cookie)) < 0) { fprintf(stderr, "Failed to load cookie data\n"); goto finish; @@ -201,20 +201,20 @@ int main(int argc, char *argv[]) { pa_x11_del_prop(d, "PULSE_ID"); pa_x11_del_prop(d, "PULSE_COOKIE"); break; - + default: fprintf(stderr, "No yet implemented.\n"); goto finish; } ret = 0; - + finish: if (d) { XSync(d, False); XCloseDisplay(d); } - + return ret; } From 19bd9148c5d16a8363065ca128e06037780337ab Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 14:06:24 +0000 Subject: [PATCH 1316/1514] Fix error messages for failure connecting streams. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1419 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 679a5d012..c6025417c 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -909,7 +909,15 @@ static void stream_state_cb(pa_stream *s, void * userdata) { break; case PA_STREAM_FAILED: - debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + if (s == i->play_stream) { + debug(DEBUG_LEVEL_NORMAL, + __FILE__": pa_stream_connect_playback() failed: %s\n", + pa_strerror(pa_context_errno(i->context))); + } else if (s == i->rec_stream) { + debug(DEBUG_LEVEL_NORMAL, + __FILE__": pa_stream_connect_record() failed: %s\n", + pa_strerror(pa_context_errno(i->context))); + } fd_info_shutdown(i); break; @@ -981,7 +989,7 @@ static int create_record_stream(fd_info *i) { attr.fragsize = i->fragment_size; if (pa_stream_connect_record(i->rec_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE) < 0) { - debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } From c992ed9c47854338106b38a1d093c4c1bf65e96d Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 14:17:57 +0000 Subject: [PATCH 1317/1514] Free stream objects when they've been invalidated. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1420 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index c6025417c..aa0ec9ddf 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -913,10 +913,14 @@ static void stream_state_cb(pa_stream *s, void * userdata) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + pa_stream_unref(i->play_stream); + i->play_stream = NULL; } else if (s == i->rec_stream) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i->context))); + pa_stream_unref(i->rec_stream); + i->rec_stream = NULL; } fd_info_shutdown(i); break; From 4c0a481f79715c0e783000c75e800d2401c11019 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 14:20:53 +0000 Subject: [PATCH 1318/1514] Report IO error on ioctl() when we're in a fatal error state. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1421 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index aa0ec9ddf..b4c5bb0ba 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1800,6 +1800,16 @@ fail: static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; + if (i->thread_fd == -1) { + /* + * We've encountered some fatal error and are just waiting + * for a close. + */ + debug(DEBUG_LEVEL_NORMAL, __FILE__": got ioctl 0x%08lx in fatal error state\n", request); + *_errno = EIO; + return -1; + } + switch (request) { case SNDCTL_DSP_SETFMT: { debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp); From 4171f2504a4e0de5c46c3237da009f5355cf57ec Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 19 Jan 2007 08:00:31 +0000 Subject: [PATCH 1319/1514] Make sure we report success for SNDCTL_DSP_SETDUPLEX. (Patch by ZlatkO) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1422 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b4c5bb0ba..2b314a9c6 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2145,6 +2145,11 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETIPTR\n"); goto inval; + case SNDCTL_DSP_SETDUPLEX: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETDUPLEX\n"); + /* this is a no-op */ + break; + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); From f65ab1b3eb2cd91f0bb98f18517e48156177e679 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 5 Feb 2007 10:26:14 +0000 Subject: [PATCH 1320/1514] Don't abort config loading when the user specific cannot be loaded. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1423 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-util.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index b42dc0caa..1e8fd23b1 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -184,7 +184,7 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { goto fail; } #else - pa_log_warn("secure directory creation not supported on Win32."); + pa_log_warn("secure directory creation not supported on Win32."); #endif return 0; @@ -953,13 +953,19 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env fn = buf; #endif - if ((f = fopen(fn, mode)) || errno != ENOENT) { + f = fopen(fn, mode); + if (f != NULL) { if (result) *result = pa_xstrdup(fn); pa_xfree(lfn); return f; } + if (errno != ENOENT) { + pa_log_warn("WARNING: failed to open configuration file '%s': %s", + lfn, pa_cstrerror(errno)); + } + pa_xfree(lfn); } } From de7a883245937a8db63991d5fa568bf35bef5bb1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 12 Feb 2007 09:37:34 +0000 Subject: [PATCH 1321/1514] Allow specification of device number. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1424 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-waveout.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index e245e1380..79de077d0 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -47,7 +47,8 @@ PA_MODULE_DESCRIPTION("Windows waveOut Sink/Source") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE( "sink_name= " - "source_name=" + "source_name= " + "device= " "record= " "playback= " "format= " @@ -90,6 +91,7 @@ struct userdata { static const char* const valid_modargs[] = { "sink_name", "source_name", + "device", "record", "playback", "fragments", @@ -432,6 +434,7 @@ int pa__init(pa_core *c, pa_module*m) { WAVEFORMATEX wf; int nfrags, frag_size; int record = 1, playback = 1; + unsigned int device; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; @@ -455,6 +458,12 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + device = WAVE_MAPPER; + if (pa_modargs_get_value_u32(ma, "device", &device) < 0) { + pa_log("failed to parse device argument"); + goto fail; + } + nfrags = 5; frag_size = 8192; if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { @@ -474,7 +483,7 @@ int pa__init(pa_core *c, pa_module*m) { u = pa_xmalloc(sizeof(struct userdata)); if (record) { - if (waveInOpen(&hwi, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_ready_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { + if (waveInOpen(&hwi, device, &wf, (DWORD_PTR)chunk_ready_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { pa_log("failed to open waveIn"); goto fail; } @@ -486,7 +495,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (playback) { - if (waveOutOpen(&hwo, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { + if (waveOutOpen(&hwo, device, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { pa_log("failed to open waveOut"); goto fail; } From 1d0e8e4f14e6d8589732a8e347ec7cd5dfdfb66b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 12 Feb 2007 09:39:12 +0000 Subject: [PATCH 1322/1514] Make sure we get proper host identifiers. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1425 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 2f09279c9..e35502ca0 100644 --- a/configure.ac +++ b/configure.ac @@ -42,6 +42,8 @@ AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:0:0]) AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:0:1]) AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:2:0]) +AC_CANONICAL_HOST + if type -p stow > /dev/null && test -d /usr/local/stow ; then AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***]) ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}" From 06211b7c8fd329137ae9003818543912a87d9898 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Feb 2007 15:35:19 +0000 Subject: [PATCH 1323/1514] Add copyright notices to all relevant files. (based on svn log) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1426 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 3 +++ src/Makefile.am | 4 ++++ src/daemon/caps.c | 3 +++ src/daemon/caps.h | 2 ++ src/daemon/cmdline.c | 2 ++ src/daemon/cmdline.h | 2 ++ src/daemon/cpulimit.c | 2 ++ src/daemon/cpulimit.h | 2 ++ src/daemon/daemon-conf.c | 3 +++ src/daemon/daemon-conf.h | 3 +++ src/daemon/dumpmodules.c | 3 +++ src/daemon/dumpmodules.h | 2 ++ src/daemon/main.c | 3 +++ src/modules/alsa-util.c | 3 +++ src/modules/alsa-util.h | 3 +++ src/modules/dbus-util.c | 3 +++ src/modules/dbus-util.h | 2 ++ src/modules/gconf/gconf-helper.c | 2 ++ src/modules/gconf/module-gconf.c | 2 ++ src/modules/module-alsa-sink.c | 3 +++ src/modules/module-alsa-source.c | 3 +++ src/modules/module-cli.c | 2 ++ src/modules/module-combine.c | 2 ++ src/modules/module-detect.c | 4 ++++ src/modules/module-esound-compat-spawnfd.c | 2 ++ src/modules/module-esound-compat-spawnpid.c | 2 ++ src/modules/module-esound-sink.c | 2 ++ src/modules/module-hal-detect.c | 3 +++ src/modules/module-jack-sink.c | 2 ++ src/modules/module-jack-source.c | 2 ++ src/modules/module-lirc.c | 2 ++ src/modules/module-match.c | 2 ++ src/modules/module-mmkbd-evdev.c | 2 ++ src/modules/module-native-protocol-fd.c | 2 ++ src/modules/module-null-sink.c | 2 ++ src/modules/module-oss-mmap.c | 3 +++ src/modules/module-oss.c | 3 +++ src/modules/module-pipe-sink.c | 2 ++ src/modules/module-pipe-source.c | 2 ++ src/modules/module-protocol-stub.c | 3 +++ src/modules/module-rescue-streams.c | 2 ++ src/modules/module-sine.c | 2 ++ src/modules/module-solaris.c | 3 +++ src/modules/module-tunnel.c | 3 +++ src/modules/module-volume-restore.c | 2 ++ src/modules/module-waveout.c | 3 +++ src/modules/module-x11-bell.c | 2 ++ src/modules/module-x11-publish.c | 2 ++ src/modules/module-zeroconf-publish.c | 2 ++ src/modules/oss-util.c | 3 +++ src/modules/oss-util.h | 3 +++ src/modules/rtp/module-rtp-recv.c | 2 ++ src/modules/rtp/module-rtp-send.c | 2 ++ src/modules/rtp/rtp.c | 2 ++ src/modules/rtp/rtp.h | 2 ++ src/modules/rtp/sap.c | 2 ++ src/modules/rtp/sap.h | 2 ++ src/modules/rtp/sdp.c | 2 ++ src/modules/rtp/sdp.h | 2 ++ src/pulse/browser.c | 2 ++ src/pulse/browser.h | 2 ++ src/pulse/cdecl.h | 2 ++ src/pulse/channelmap.c | 3 +++ src/pulse/channelmap.h | 3 +++ src/pulse/client-conf-x11.c | 2 ++ src/pulse/client-conf-x11.h | 2 ++ src/pulse/client-conf.c | 3 +++ src/pulse/client-conf.h | 2 ++ src/pulse/context.c | 3 +++ src/pulse/context.h | 3 +++ src/pulse/def.h | 3 +++ src/pulse/error.c | 3 +++ src/pulse/error.h | 3 +++ src/pulse/glib-mainloop.c | 2 ++ src/pulse/glib-mainloop.h | 3 +++ src/pulse/internal.h | 3 +++ src/pulse/introspect.c | 3 +++ src/pulse/introspect.h | 3 +++ src/pulse/mainloop-api.c | 2 ++ src/pulse/mainloop-api.h | 3 +++ src/pulse/mainloop-signal.c | 3 +++ src/pulse/mainloop-signal.h | 3 +++ src/pulse/mainloop.c | 3 +++ src/pulse/mainloop.h | 3 +++ src/pulse/operation.c | 2 ++ src/pulse/operation.h | 2 ++ src/pulse/pulseaudio.h | 3 +++ src/pulse/sample.c | 3 +++ src/pulse/sample.h | 3 +++ src/pulse/scache.c | 2 ++ src/pulse/scache.h | 3 +++ src/pulse/simple.c | 2 ++ src/pulse/simple.h | 3 +++ src/pulse/stream.c | 3 +++ src/pulse/stream.h | 3 +++ src/pulse/subscribe.c | 2 ++ src/pulse/subscribe.h | 3 +++ src/pulse/thread-mainloop.c | 3 +++ src/pulse/thread-mainloop.h | 3 +++ src/pulse/timeval.c | 3 +++ src/pulse/timeval.h | 3 +++ src/pulse/utf8.c | 22 +++++++++++++++++++++ src/pulse/utf8.h | 3 +++ src/pulse/util.c | 3 +++ src/pulse/util.h | 3 +++ src/pulse/version.h.in | 3 +++ src/pulse/volume.c | 2 ++ src/pulse/volume.h | 3 +++ src/pulse/xmalloc.c | 2 ++ src/pulse/xmalloc.h | 2 ++ src/pulsecore/anotify.c | 2 ++ src/pulsecore/anotify.h | 2 ++ src/pulsecore/atomic.h | 2 ++ src/pulsecore/authkey-prop.c | 2 ++ src/pulsecore/authkey-prop.h | 2 ++ src/pulsecore/authkey.c | 3 +++ src/pulsecore/authkey.h | 2 ++ src/pulsecore/autoload.c | 3 +++ src/pulsecore/autoload.h | 2 ++ src/pulsecore/avahi-wrap.c | 2 ++ src/pulsecore/avahi-wrap.h | 2 ++ src/pulsecore/cli-command.c | 3 +++ src/pulsecore/cli-command.h | 2 ++ src/pulsecore/cli-text.c | 2 ++ src/pulsecore/cli-text.h | 2 ++ src/pulsecore/cli.c | 2 ++ src/pulsecore/cli.h | 2 ++ src/pulsecore/client.c | 3 +++ src/pulsecore/client.h | 2 ++ src/pulsecore/conf-parser.c | 2 ++ src/pulsecore/conf-parser.h | 2 ++ src/pulsecore/core-def.h | 2 ++ src/pulsecore/core-error.c | 3 +++ src/pulsecore/core-error.h | 3 +++ src/pulsecore/core-scache.c | 3 +++ src/pulsecore/core-scache.h | 3 +++ src/pulsecore/core-subscribe.c | 2 ++ src/pulsecore/core-subscribe.h | 2 ++ src/pulsecore/core-util.c | 4 ++++ src/pulsecore/core-util.h | 3 +++ src/pulsecore/core.c | 3 +++ src/pulsecore/core.h | 2 ++ src/pulsecore/creds.h | 2 ++ src/pulsecore/dllmain.c | 2 ++ src/pulsecore/dynarray.c | 2 ++ src/pulsecore/dynarray.h | 2 ++ src/pulsecore/endianmacros.h | 3 +++ src/pulsecore/esound.h | 2 ++ src/pulsecore/flist.c | 2 ++ src/pulsecore/flist.h | 2 ++ src/pulsecore/gccmacro.h | 2 ++ src/pulsecore/hashmap.c | 2 ++ src/pulsecore/hashmap.h | 2 ++ src/pulsecore/hook-list.c | 2 ++ src/pulsecore/hook-list.h | 2 ++ src/pulsecore/idxset.c | 3 +++ src/pulsecore/idxset.h | 3 +++ src/pulsecore/inet_ntop.c | 2 ++ src/pulsecore/inet_pton.c | 2 ++ src/pulsecore/iochannel.c | 3 +++ src/pulsecore/iochannel.h | 3 +++ src/pulsecore/ioline.c | 2 ++ src/pulsecore/ioline.h | 2 ++ src/pulsecore/ipacl.c | 3 +++ src/pulsecore/ipacl.h | 3 +++ src/pulsecore/llist.h | 2 ++ src/pulsecore/log.c | 3 +++ src/pulsecore/log.h | 3 +++ src/pulsecore/mcalign.c | 2 ++ src/pulsecore/mcalign.h | 2 ++ src/pulsecore/memblock.c | 3 +++ src/pulsecore/memblock.h | 3 +++ src/pulsecore/memblockq.c | 2 ++ src/pulsecore/memblockq.h | 2 ++ src/pulsecore/memchunk.c | 2 ++ src/pulsecore/memchunk.h | 2 ++ src/pulsecore/modargs.c | 2 ++ src/pulsecore/modargs.h | 2 ++ src/pulsecore/modinfo.c | 2 ++ src/pulsecore/modinfo.h | 2 ++ src/pulsecore/module.c | 3 +++ src/pulsecore/module.h | 2 ++ src/pulsecore/mutex-posix.c | 2 ++ src/pulsecore/mutex-win32.c | 2 ++ src/pulsecore/mutex.h | 2 ++ src/pulsecore/namereg.c | 2 ++ src/pulsecore/namereg.h | 2 ++ src/pulsecore/native-common.h | 3 +++ src/pulsecore/once-posix.c | 2 ++ src/pulsecore/once-win32.c | 2 ++ src/pulsecore/once.h | 2 ++ src/pulsecore/packet.c | 2 ++ src/pulsecore/packet.h | 2 ++ src/pulsecore/parseaddr.c | 2 ++ src/pulsecore/parseaddr.h | 2 ++ src/pulsecore/pdispatch.c | 3 +++ src/pulsecore/pdispatch.h | 3 +++ src/pulsecore/pid.c | 3 +++ src/pulsecore/pid.h | 2 ++ src/pulsecore/pipe.c | 2 ++ src/pulsecore/pipe.h | 2 ++ src/pulsecore/play-memblockq.c | 2 ++ src/pulsecore/play-memblockq.h | 2 ++ src/pulsecore/play-memchunk.c | 2 ++ src/pulsecore/play-memchunk.h | 2 ++ src/pulsecore/poll.c | 13 ++++++------ src/pulsecore/poll.h | 15 +++++++------- src/pulsecore/props.c | 2 ++ src/pulsecore/props.h | 2 ++ src/pulsecore/protocol-cli.c | 2 ++ src/pulsecore/protocol-cli.h | 2 ++ src/pulsecore/protocol-esound.c | 3 +++ src/pulsecore/protocol-esound.h | 3 +++ src/pulsecore/protocol-http.c | 2 ++ src/pulsecore/protocol-http.h | 2 ++ src/pulsecore/protocol-native.c | 3 +++ src/pulsecore/protocol-native.h | 3 +++ src/pulsecore/protocol-simple.c | 2 ++ src/pulsecore/protocol-simple.h | 2 ++ src/pulsecore/pstream-util.c | 2 ++ src/pulsecore/pstream-util.h | 2 ++ src/pulsecore/pstream.c | 3 +++ src/pulsecore/pstream.h | 3 +++ src/pulsecore/queue.c | 2 ++ src/pulsecore/queue.h | 2 ++ src/pulsecore/random.c | 3 +++ src/pulsecore/random.h | 3 +++ src/pulsecore/refcnt.h | 2 ++ src/pulsecore/resampler.c | 2 ++ src/pulsecore/resampler.h | 2 ++ src/pulsecore/sample-util.c | 3 +++ src/pulsecore/sample-util.h | 3 +++ src/pulsecore/sconv-s16be.c | 2 ++ src/pulsecore/sconv-s16be.h | 2 ++ src/pulsecore/sconv-s16le.c | 2 ++ src/pulsecore/sconv-s16le.h | 2 ++ src/pulsecore/sconv.c | 3 +++ src/pulsecore/sconv.h | 3 +++ src/pulsecore/shm.c | 3 +++ src/pulsecore/shm.h | 2 ++ src/pulsecore/sink-input.c | 3 +++ src/pulsecore/sink-input.h | 3 +++ src/pulsecore/sink.c | 3 +++ src/pulsecore/sink.h | 3 +++ src/pulsecore/sioman.c | 2 ++ src/pulsecore/sioman.h | 2 ++ src/pulsecore/socket-client.c | 3 +++ src/pulsecore/socket-client.h | 3 +++ src/pulsecore/socket-server.c | 3 +++ src/pulsecore/socket-server.h | 3 +++ src/pulsecore/socket-util.c | 4 ++++ src/pulsecore/socket-util.h | 3 +++ src/pulsecore/sound-file-stream.c | 2 ++ src/pulsecore/sound-file-stream.h | 2 ++ src/pulsecore/sound-file.c | 2 ++ src/pulsecore/sound-file.h | 2 ++ src/pulsecore/source-output.c | 2 ++ src/pulsecore/source-output.h | 2 ++ src/pulsecore/source.c | 3 +++ src/pulsecore/source.h | 3 +++ src/pulsecore/strbuf.c | 2 ++ src/pulsecore/strbuf.h | 2 ++ src/pulsecore/strlist.c | 2 ++ src/pulsecore/strlist.h | 2 ++ src/pulsecore/tagstruct.c | 2 ++ src/pulsecore/tagstruct.h | 2 ++ src/pulsecore/thread-posix.c | 3 +++ src/pulsecore/thread-win32.c | 2 ++ src/pulsecore/thread.h | 3 +++ src/pulsecore/tokenizer.c | 2 ++ src/pulsecore/tokenizer.h | 2 ++ src/pulsecore/x11prop.c | 2 ++ src/pulsecore/x11prop.h | 2 ++ src/pulsecore/x11wrap.c | 2 ++ src/pulsecore/x11wrap.h | 2 ++ src/utils/pabrowse.c | 2 ++ src/utils/pacat.c | 3 +++ src/utils/pacmd.c | 2 ++ src/utils/pactl.c | 2 ++ src/utils/padsp | 3 +++ src/utils/padsp.c | 3 +++ src/utils/paplay.c | 3 +++ src/utils/pax11publish.c | 2 ++ 283 files changed, 714 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index e35502ca0..65a99a00d 100644 --- a/configure.ac +++ b/configure.ac @@ -5,6 +5,9 @@ # This file is part of PulseAudio. # +# Copyright 2004-2006 Lennart Poettering +# Copyright 2006-2007 Pierre Ossman for Cendio AB +# # PulseAudio is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or diff --git a/src/Makefile.am b/src/Makefile.am index 2f3bd8ab9..0b509ac95 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,10 @@ # # This file is part of PulseAudio. # +# Copyright 2004-2006 Lennart Poettering +# Copyright 2006 Pierre Ossman for Cendio AB +# Copyright 2006 Diego Pettenò +# # PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or diff --git a/src/daemon/caps.c b/src/daemon/caps.c index db4bd9194..2ea51c9f9 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/daemon/caps.h b/src/daemon/caps.h index 34da1af68..4cd09578c 100644 --- a/src/daemon/caps.h +++ b/src/daemon/caps.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index c3cb9209e..dc757c9c7 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/daemon/cmdline.h b/src/daemon/cmdline.h index fdfbc0b69..18418894f 100644 --- a/src/daemon/cmdline.h +++ b/src/daemon/cmdline.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index 808cb4d4a..d4ac1d869 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/daemon/cpulimit.h b/src/daemon/cpulimit.h index bb11f794e..271109b4e 100644 --- a/src/daemon/cpulimit.h +++ b/src/daemon/cpulimit.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 319cf0c7d..8cab327f8 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index b7fcf23b7..4843a610e 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c index 8509924aa..6743622ac 100644 --- a/src/daemon/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/daemon/dumpmodules.h b/src/daemon/dumpmodules.h index 05cd86e02..ab2ddb646 100644 --- a/src/daemon/dumpmodules.h +++ b/src/daemon/dumpmodules.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/daemon/main.c b/src/daemon/main.c index b7266b7ea..211dd30c7 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 8023d3add..40be53110 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 675856c6b..ea6c7e1df 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c index ee9062d19..48a451746 100644 --- a/src/modules/dbus-util.c +++ b/src/modules/dbus-util.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Shams E. King + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/dbus-util.h b/src/modules/dbus-util.h index 73501c29c..8dca54feb 100644 --- a/src/modules/dbus-util.h +++ b/src/modules/dbus-util.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Shams E. King + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/gconf/gconf-helper.c b/src/modules/gconf/gconf-helper.c index 40724f4e6..5f6def4d8 100644 --- a/src/modules/gconf/gconf-helper.c +++ b/src/modules/gconf/gconf-helper.c @@ -2,6 +2,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index d9f649fd1..df7b16439 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -2,6 +2,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 2fea58917..74a57f371 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 596998d12..2ea551cb8 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c index b5c27299d..19ac0c26c 100644 --- a/src/modules/module-cli.c +++ b/src/modules/module-cli.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 6bc958aa9..716c20b24 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 3057f70db..41b68ac3e 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -3,6 +3,10 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006 Diego Pettenò + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index fbb6bd6db..1aecade50 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index a7196313e..a9fd166d4 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -2,6 +2,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 626006826..26638d9dc 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index eb275ff02..56a3efc19 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Shams E. King + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 6175536c8..c6a7e33f0 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 8d891ce64..8ca24035f 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index f32667ee6..c8adbc8be 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2005-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-match.c b/src/modules/module-match.c index d0e82ba32..0b051facb 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index baf688f19..b7433ac82 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2005-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-native-protocol-fd.c b/src/modules/module-native-protocol-fd.c index 907aab273..3c1c2bca4 100644 --- a/src/modules/module-native-protocol-fd.c +++ b/src/modules/module-native-protocol-fd.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index fc9107a37..54a8e8902 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c index 7bf6cbbdf..16c9b311a 100644 --- a/src/modules/module-oss-mmap.c +++ b/src/modules/module-oss-mmap.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index b8ced86fb..965944a79 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 724003130..170b046ef 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index f53f6a63b..56c721b0f 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 93fb2a366..4728f7508 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c index 2eea4f61d..25005f250 100644 --- a/src/modules/module-rescue-streams.c +++ b/src/modules/module-rescue-streams.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index 871b702d3..661455b3a 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 1454d6398..a50f1ecf8 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index f7420a67b..288e049e8 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 877d17c78..0df270dff 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index 79de077d0..ad3645fc7 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006-2007 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index 5322a71f9..b9c4ad499 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index b1c17a7c1..fd1d532f5 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 10643808b..69508ad03 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index d26a0e813..fb531468a 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/oss-util.h b/src/modules/oss-util.h index 6a8bf3d28..087e0d220 100644 --- a/src/modules/oss-util.h +++ b/src/modules/oss-util.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 338d57cfa..db83756ad 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -1,6 +1,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 7bbfabee7..18e5e055a 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -2,6 +2,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index 3bb0ea473..bc5260a89 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -2,6 +2,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/modules/rtp/rtp.h b/src/modules/rtp/rtp.h index 123602b23..db7acd983 100644 --- a/src/modules/rtp/rtp.h +++ b/src/modules/rtp/rtp.h @@ -5,6 +5,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index 022c7fa33..f61c0efe8 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -2,6 +2,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/modules/rtp/sap.h b/src/modules/rtp/sap.h index 987403e37..cac697e64 100644 --- a/src/modules/rtp/sap.h +++ b/src/modules/rtp/sap.h @@ -5,6 +5,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index 1b71a9a01..7f0e7027b 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -2,6 +2,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/modules/rtp/sdp.h b/src/modules/rtp/sdp.h index b95ca633e..4c68ac5a1 100644 --- a/src/modules/rtp/sdp.h +++ b/src/modules/rtp/sdp.h @@ -5,6 +5,8 @@ /*** This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/pulse/browser.c b/src/pulse/browser.c index 4b0de0294..27c5a2ead 100644 --- a/src/pulse/browser.c +++ b/src/pulse/browser.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulse/browser.h b/src/pulse/browser.h index 7b9aae8d5..b039ca337 100644 --- a/src/pulse/browser.h +++ b/src/pulse/browser.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulse/cdecl.h b/src/pulse/cdecl.h index 09b9b84a5..922ad2765 100644 --- a/src/pulse/cdecl.h +++ b/src/pulse/cdecl.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c index 40655cf50..d5b8f7437 100644 --- a/src/pulse/channelmap.c +++ b/src/pulse/channelmap.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2005-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h index 203802510..f0c8f4752 100644 --- a/src/pulse/channelmap.h +++ b/src/pulse/channelmap.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2005-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/client-conf-x11.c b/src/pulse/client-conf-x11.c index 78e190e51..b5ac8d9fa 100644 --- a/src/pulse/client-conf-x11.c +++ b/src/pulse/client-conf-x11.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/client-conf-x11.h b/src/pulse/client-conf-x11.h index 02e808be9..56cd406d4 100644 --- a/src/pulse/client-conf-x11.h +++ b/src/pulse/client-conf-x11.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index b652a25ba..bb9123359 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index 35728aeb5..6de64582f 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/context.c b/src/pulse/context.c index 7ef43b306..58a5a8794 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/context.h b/src/pulse/context.h index 048ed17f4..1de3abadc 100644 --- a/src/pulse/context.h +++ b/src/pulse/context.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/def.h b/src/pulse/def.h index fb04de506..c28162344 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulse/error.c b/src/pulse/error.c index 3b9a60a4c..78f0da955 100644 --- a/src/pulse/error.c +++ b/src/pulse/error.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/error.h b/src/pulse/error.h index c96349a61..44a2e5ecc 100644 --- a/src/pulse/error.h +++ b/src/pulse/error.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/glib-mainloop.c b/src/pulse/glib-mainloop.c index 1669acddb..5b399aa2b 100644 --- a/src/pulse/glib-mainloop.c +++ b/src/pulse/glib-mainloop.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/glib-mainloop.h b/src/pulse/glib-mainloop.h index 5f8093a1a..a4e06ea04 100644 --- a/src/pulse/glib-mainloop.h +++ b/src/pulse/glib-mainloop.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 8cdbf84a1..52354fdcb 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c index 5a2c8fb67..7f6406cf8 100644 --- a/src/pulse/introspect.c +++ b/src/pulse/introspect.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h index 6de7bc714..43e430b20 100644 --- a/src/pulse/introspect.h +++ b/src/pulse/introspect.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/mainloop-api.c b/src/pulse/mainloop-api.c index bf3ef37ed..001ff314b 100644 --- a/src/pulse/mainloop-api.c +++ b/src/pulse/mainloop-api.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulse/mainloop-api.h b/src/pulse/mainloop-api.h index b88bf125e..985806e6f 100644 --- a/src/pulse/mainloop-api.h +++ b/src/pulse/mainloop-api.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c index 4dd427966..28ddec492 100644 --- a/src/pulse/mainloop-signal.c +++ b/src/pulse/mainloop-signal.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/mainloop-signal.h b/src/pulse/mainloop-signal.h index e991cf1cf..50aa99ce9 100644 --- a/src/pulse/mainloop-signal.h +++ b/src/pulse/mainloop-signal.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 04461b307..43cbb19ff 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/mainloop.h b/src/pulse/mainloop.h index 18be1f2ba..db2797fbe 100644 --- a/src/pulse/mainloop.h +++ b/src/pulse/mainloop.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/operation.c b/src/pulse/operation.c index e039e8c9a..f23def50c 100644 --- a/src/pulse/operation.c +++ b/src/pulse/operation.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/operation.h b/src/pulse/operation.h index adfd5f2d0..97d1c6b8e 100644 --- a/src/pulse/operation.h +++ b/src/pulse/operation.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/pulseaudio.h b/src/pulse/pulseaudio.h index 5543d7cd6..88d1275b3 100644 --- a/src/pulse/pulseaudio.h +++ b/src/pulse/pulseaudio.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulse/sample.c b/src/pulse/sample.c index dd68ac17b..aafafc839 100644 --- a/src/pulse/sample.c +++ b/src/pulse/sample.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/sample.h b/src/pulse/sample.h index b7c537e4c..5e6036858 100644 --- a/src/pulse/sample.h +++ b/src/pulse/sample.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/scache.c b/src/pulse/scache.c index 5abaf845f..09bc1078d 100644 --- a/src/pulse/scache.c +++ b/src/pulse/scache.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/scache.h b/src/pulse/scache.h index 2293dec4e..31fd89567 100644 --- a/src/pulse/scache.h +++ b/src/pulse/scache.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/simple.c b/src/pulse/simple.c index 1c632fa7f..3cf862d28 100644 --- a/src/pulse/simple.c +++ b/src/pulse/simple.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/simple.h b/src/pulse/simple.h index a97875f91..128d27160 100644 --- a/src/pulse/simple.h +++ b/src/pulse/simple.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 009eb3cf6..f20c17aef 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/stream.h b/src/pulse/stream.h index 2ce534586..65603262f 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/subscribe.c b/src/pulse/subscribe.c index d9abf6f80..5d8f12523 100644 --- a/src/pulse/subscribe.c +++ b/src/pulse/subscribe.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/subscribe.h b/src/pulse/subscribe.h index 35d5a31ce..c37ead57c 100644 --- a/src/pulse/subscribe.h +++ b/src/pulse/subscribe.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c index ad29f5ba8..4f3cacc9a 100644 --- a/src/pulse/thread-mainloop.c +++ b/src/pulse/thread-mainloop.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/thread-mainloop.h b/src/pulse/thread-mainloop.h index 48048b35c..b78c1583f 100644 --- a/src/pulse/thread-mainloop.h +++ b/src/pulse/thread-mainloop.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c index e5a86a632..78ece0616 100644 --- a/src/pulse/timeval.c +++ b/src/pulse/timeval.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h index c10ec9f60..1e5627e33 100644 --- a/src/pulse/timeval.h +++ b/src/pulse/timeval.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulse/utf8.c b/src/pulse/utf8.c index 2708c5181..2ac2d1063 100644 --- a/src/pulse/utf8.c +++ b/src/pulse/utf8.c @@ -1,5 +1,27 @@ /* $Id$ */ +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + /* This file is based on the GLIB utf8 validation functions. The * original license text follows. */ diff --git a/src/pulse/utf8.h b/src/pulse/utf8.h index 7225471f1..ff8dc215b 100644 --- a/src/pulse/utf8.h +++ b/src/pulse/utf8.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulse/util.c b/src/pulse/util.c index 63f54e3bb..d561329cb 100644 --- a/src/pulse/util.c +++ b/src/pulse/util.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulse/util.h b/src/pulse/util.h index 0be169fb4..95bd86f36 100644 --- a/src/pulse/util.h +++ b/src/pulse/util.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulse/version.h.in b/src/pulse/version.h.in index 748541a11..20c7a9c0a 100644 --- a/src/pulse/version.h.in +++ b/src/pulse/version.h.in @@ -5,6 +5,9 @@ /*** This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/pulse/volume.c b/src/pulse/volume.c index aa7ddba29..feb33f078 100644 --- a/src/pulse/volume.c +++ b/src/pulse/volume.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/volume.h b/src/pulse/volume.h index 62d2867aa..a928ff711 100644 --- a/src/pulse/volume.h +++ b/src/pulse/volume.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/xmalloc.c b/src/pulse/xmalloc.c index dda42bdc3..1f0734c24 100644 --- a/src/pulse/xmalloc.c +++ b/src/pulse/xmalloc.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulse/xmalloc.h b/src/pulse/xmalloc.h index 2fb1c5f0f..2f6399c58 100644 --- a/src/pulse/xmalloc.h +++ b/src/pulse/xmalloc.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/anotify.c b/src/pulsecore/anotify.c index c89d4a15f..25c5fe7d8 100644 --- a/src/pulsecore/anotify.c +++ b/src/pulsecore/anotify.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/anotify.h b/src/pulsecore/anotify.h index b91e6875b..b3f75b7e8 100644 --- a/src/pulsecore/anotify.h +++ b/src/pulsecore/anotify.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index e713e7a83..8867f884b 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/authkey-prop.c b/src/pulsecore/authkey-prop.c index f3a811798..3b8304b23 100644 --- a/src/pulsecore/authkey-prop.c +++ b/src/pulsecore/authkey-prop.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/authkey-prop.h b/src/pulsecore/authkey-prop.h index fb777f85f..247202f34 100644 --- a/src/pulsecore/authkey-prop.h +++ b/src/pulsecore/authkey-prop.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c index 8ef53bd8e..a6150d0e0 100644 --- a/src/pulsecore/authkey.c +++ b/src/pulsecore/authkey.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/authkey.h b/src/pulsecore/authkey.h index bba0bc73c..18e5157dc 100644 --- a/src/pulsecore/authkey.h +++ b/src/pulsecore/authkey.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/autoload.c b/src/pulsecore/autoload.c index b68eaac75..6f888526c 100644 --- a/src/pulsecore/autoload.c +++ b/src/pulsecore/autoload.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/autoload.h b/src/pulsecore/autoload.h index f410e49cb..2899586c6 100644 --- a/src/pulsecore/autoload.h +++ b/src/pulsecore/autoload.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/avahi-wrap.c b/src/pulsecore/avahi-wrap.c index bcda99546..855ed5671 100644 --- a/src/pulsecore/avahi-wrap.c +++ b/src/pulsecore/avahi-wrap.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/avahi-wrap.h b/src/pulsecore/avahi-wrap.h index bb8f5716b..1e20ec38b 100644 --- a/src/pulsecore/avahi-wrap.h +++ b/src/pulsecore/avahi-wrap.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index cb438a224..aa2beba2c 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/cli-command.h b/src/pulsecore/cli-command.h index 1594f4db4..10d50f379 100644 --- a/src/pulsecore/cli-command.h +++ b/src/pulsecore/cli-command.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index ac74a287c..e97f0574f 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/cli-text.h b/src/pulsecore/cli-text.h index b092fc8b7..9e5bf081b 100644 --- a/src/pulsecore/cli-text.h +++ b/src/pulsecore/cli-text.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c index 0820fc8e7..ee05d7f95 100644 --- a/src/pulsecore/cli.c +++ b/src/pulsecore/cli.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/cli.h b/src/pulsecore/cli.h index 5cf0ebd21..2b58d4583 100644 --- a/src/pulsecore/cli.h +++ b/src/pulsecore/cli.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c index 55697d2e3..0d792bb45 100644 --- a/src/pulsecore/client.c +++ b/src/pulsecore/client.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/client.h b/src/pulsecore/client.h index e632da129..6d09b9996 100644 --- a/src/pulsecore/client.h +++ b/src/pulsecore/client.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index 6f55e2de4..12efbd2c4 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/conf-parser.h b/src/pulsecore/conf-parser.h index 9c1a697a6..b56d979e8 100644 --- a/src/pulsecore/conf-parser.h +++ b/src/pulsecore/conf-parser.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/core-def.h b/src/pulsecore/core-def.h index f849a6f64..10a3be428 100644 --- a/src/pulsecore/core-def.h +++ b/src/pulsecore/core-def.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/core-error.c b/src/pulsecore/core-error.c index 2362068f1..044bea124 100644 --- a/src/pulsecore/core-error.c +++ b/src/pulsecore/core-error.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/core-error.h b/src/pulsecore/core-error.h index e43908339..443c48838 100644 --- a/src/pulsecore/core-error.h +++ b/src/pulsecore/core-error.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c index 26c493ca5..75fb47f02 100644 --- a/src/pulsecore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/core-scache.h b/src/pulsecore/core-scache.h index 69baabbc6..bbf13f156 100644 --- a/src/pulsecore/core-scache.h +++ b/src/pulsecore/core-scache.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/core-subscribe.c b/src/pulsecore/core-subscribe.c index 5a958b839..6608d57a4 100644 --- a/src/pulsecore/core-subscribe.c +++ b/src/pulsecore/core-subscribe.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/core-subscribe.h b/src/pulsecore/core-subscribe.h index 875cf331b..2b6863f95 100644 --- a/src/pulsecore/core-subscribe.h +++ b/src/pulsecore/core-subscribe.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 1e8fd23b1..ac1023a0d 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -3,6 +3,10 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2004 Joe Marcus Clarke + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index b2608edd0..a1da3e287 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index b19b1974b..31b6c1881 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index c1c6a19c2..51a18b62e 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h index 5ad880a01..e0a025bd0 100644 --- a/src/pulsecore/creds.h +++ b/src/pulsecore/creds.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/dllmain.c b/src/pulsecore/dllmain.c index b86bf04f0..52cbf9e2b 100644 --- a/src/pulsecore/dllmain.c +++ b/src/pulsecore/dllmain.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/dynarray.c b/src/pulsecore/dynarray.c index 91a9d5e10..944e35707 100644 --- a/src/pulsecore/dynarray.c +++ b/src/pulsecore/dynarray.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/dynarray.h b/src/pulsecore/dynarray.h index 216d87662..0f222e10e 100644 --- a/src/pulsecore/dynarray.h +++ b/src/pulsecore/dynarray.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h index c01930140..c0c3a6d8c 100644 --- a/src/pulsecore/endianmacros.h +++ b/src/pulsecore/endianmacros.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/esound.h b/src/pulsecore/esound.h index 0ea201b62..3778a535f 100644 --- a/src/pulsecore/esound.h +++ b/src/pulsecore/esound.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c index 5091bfd1e..00567ab32 100644 --- a/src/pulsecore/flist.c +++ b/src/pulsecore/flist.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h index 9871f32d6..bf702bf33 100644 --- a/src/pulsecore/flist.h +++ b/src/pulsecore/flist.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h index 87f7eece5..57d280064 100644 --- a/src/pulsecore/gccmacro.h +++ b/src/pulsecore/gccmacro.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c index 809eaeec3..818e12bf7 100644 --- a/src/pulsecore/hashmap.c +++ b/src/pulsecore/hashmap.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h index 18e41cf3f..3ca2a4795 100644 --- a/src/pulsecore/hashmap.h +++ b/src/pulsecore/hashmap.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/hook-list.c b/src/pulsecore/hook-list.c index 40f6b4355..4f8841876 100644 --- a/src/pulsecore/hook-list.c +++ b/src/pulsecore/hook-list.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/hook-list.h b/src/pulsecore/hook-list.h index 9a219a90b..b3bd600a7 100644 --- a/src/pulsecore/hook-list.h +++ b/src/pulsecore/hook-list.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c index dce51e210..70ef7ba70 100644 --- a/src/pulsecore/idxset.c +++ b/src/pulsecore/idxset.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h index 0d751e079..17a70f4ff 100644 --- a/src/pulsecore/idxset.h +++ b/src/pulsecore/idxset.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/inet_ntop.c b/src/pulsecore/inet_ntop.c index 5d7a543ef..302369f78 100644 --- a/src/pulsecore/inet_ntop.c +++ b/src/pulsecore/inet_ntop.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/inet_pton.c b/src/pulsecore/inet_pton.c index 42bb53879..7272e4593 100644 --- a/src/pulsecore/inet_pton.c +++ b/src/pulsecore/inet_pton.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index b40f0aa10..2f6fdd39f 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h index 147e7276f..c22fefd30 100644 --- a/src/pulsecore/iochannel.h +++ b/src/pulsecore/iochannel.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c index 2fe5c88d4..07b60bee3 100644 --- a/src/pulsecore/ioline.c +++ b/src/pulsecore/ioline.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/ioline.h b/src/pulsecore/ioline.h index 8d3fb5f80..8475b798e 100644 --- a/src/pulsecore/ioline.h +++ b/src/pulsecore/ioline.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c index 2848b1698..a240d2a0a 100644 --- a/src/pulsecore/ipacl.c +++ b/src/pulsecore/ipacl.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/ipacl.h b/src/pulsecore/ipacl.h index 61bf99b01..175f54e00 100644 --- a/src/pulsecore/ipacl.h +++ b/src/pulsecore/ipacl.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/llist.h b/src/pulsecore/llist.h index 49d261664..8fc8e22b6 100644 --- a/src/pulsecore/llist.h +++ b/src/pulsecore/llist.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 7ad90383c..7eb83de78 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/log.h b/src/pulsecore/log.h index 728c25013..b0711dcaa 100644 --- a/src/pulsecore/log.h +++ b/src/pulsecore/log.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/mcalign.c b/src/pulsecore/mcalign.c index baf367843..dd1d71f3c 100644 --- a/src/pulsecore/mcalign.c +++ b/src/pulsecore/mcalign.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/mcalign.h b/src/pulsecore/mcalign.h index 751eacd3e..6ff8f94e1 100644 --- a/src/pulsecore/mcalign.h +++ b/src/pulsecore/mcalign.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 73874cf1a..5e7d6e480 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index eeecf7562..3eace92c7 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index 4a845a53b..e31fb6dfb 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h index 3485a6693..437c5a419 100644 --- a/src/pulsecore/memblockq.h +++ b/src/pulsecore/memblockq.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c index 2ab6d3581..7111e1ec1 100644 --- a/src/pulsecore/memchunk.c +++ b/src/pulsecore/memchunk.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/memchunk.h b/src/pulsecore/memchunk.h index 2e2f936bb..0b982b6d3 100644 --- a/src/pulsecore/memchunk.h +++ b/src/pulsecore/memchunk.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c index 243ea0196..3733f6550 100644 --- a/src/pulsecore/modargs.c +++ b/src/pulsecore/modargs.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/modargs.h b/src/pulsecore/modargs.h index 5cccee903..77262e1e9 100644 --- a/src/pulsecore/modargs.h +++ b/src/pulsecore/modargs.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/modinfo.c b/src/pulsecore/modinfo.c index 46e66c50f..58394e594 100644 --- a/src/pulsecore/modinfo.c +++ b/src/pulsecore/modinfo.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/modinfo.h b/src/pulsecore/modinfo.h index e8d3103fa..3ee33ede4 100644 --- a/src/pulsecore/modinfo.h +++ b/src/pulsecore/modinfo.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index 94410b396..09b15b8b0 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/module.h b/src/pulsecore/module.h index 5f1075076..750dfaa8d 100644 --- a/src/pulsecore/module.h +++ b/src/pulsecore/module.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c index 896913ce1..52e731b36 100644 --- a/src/pulsecore/mutex-posix.c +++ b/src/pulsecore/mutex-posix.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/mutex-win32.c b/src/pulsecore/mutex-win32.c index 124b17c61..1f16e24c7 100644 --- a/src/pulsecore/mutex-win32.c +++ b/src/pulsecore/mutex-win32.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/mutex.h b/src/pulsecore/mutex.h index 11a20733b..b2e34c07a 100644 --- a/src/pulsecore/mutex.h +++ b/src/pulsecore/mutex.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index faf7f1444..7f66af059 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index efadb06eb..350ba0f6e 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h index df7654ffa..f7a7da1de 100644 --- a/src/pulsecore/native-common.h +++ b/src/pulsecore/native-common.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c index bb2ca7930..4af7b36e6 100644 --- a/src/pulsecore/once-posix.c +++ b/src/pulsecore/once-posix.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/once-win32.c b/src/pulsecore/once-win32.c index 07f68f383..b30097c88 100644 --- a/src/pulsecore/once-win32.c +++ b/src/pulsecore/once-win32.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/once.h b/src/pulsecore/once.h index 3c475a1d0..c20fc0b4c 100644 --- a/src/pulsecore/once.h +++ b/src/pulsecore/once.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/packet.c b/src/pulsecore/packet.c index b3a4b6f4c..ce57cb3e3 100644 --- a/src/pulsecore/packet.c +++ b/src/pulsecore/packet.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/packet.h b/src/pulsecore/packet.h index 89759c5ab..842582c86 100644 --- a/src/pulsecore/packet.h +++ b/src/pulsecore/packet.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/parseaddr.c b/src/pulsecore/parseaddr.c index 3a5bc2e80..a49a09ed7 100644 --- a/src/pulsecore/parseaddr.c +++ b/src/pulsecore/parseaddr.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/parseaddr.h b/src/pulsecore/parseaddr.h index bbbb8989b..fd7cad3ba 100644 --- a/src/pulsecore/parseaddr.h +++ b/src/pulsecore/parseaddr.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index c474ccd1c..758beaff8 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h index 28bc29d94..de0aa3ecf 100644 --- a/src/pulsecore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index 40cc82489..5e670e17a 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/pid.h b/src/pulsecore/pid.h index 31d6f0bb4..0f25d1c89 100644 --- a/src/pulsecore/pid.h +++ b/src/pulsecore/pid.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/pipe.c b/src/pulsecore/pipe.c index a0c46fa3a..a659915e9 100644 --- a/src/pulsecore/pipe.c +++ b/src/pulsecore/pipe.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/pipe.h b/src/pulsecore/pipe.h index 86a198d36..e013a2e7b 100644 --- a/src/pulsecore/pipe.h +++ b/src/pulsecore/pipe.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c index ae7cd616e..76edd27a0 100644 --- a/src/pulsecore/play-memblockq.c +++ b/src/pulsecore/play-memblockq.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/play-memblockq.h b/src/pulsecore/play-memblockq.h index 68d0f8e3c..8248e8597 100644 --- a/src/pulsecore/play-memblockq.h +++ b/src/pulsecore/play-memblockq.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c index c5dcc8cec..9132e2945 100644 --- a/src/pulsecore/play-memchunk.c +++ b/src/pulsecore/play-memchunk.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/play-memchunk.h b/src/pulsecore/play-memchunk.h index 3e087baa2..5afb094c5 100644 --- a/src/pulsecore/play-memchunk.h +++ b/src/pulsecore/play-memchunk.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/poll.c b/src/pulsecore/poll.c index 82af4c057..2f8eae89b 100644 --- a/src/pulsecore/poll.c +++ b/src/pulsecore/poll.c @@ -1,15 +1,11 @@ /* $Id$ */ -/*** - Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. - Copyright (C) 2005, Cendio AB. - This file is part of PulseAudio. - Based on work for the GNU C Library. -***/ /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, @@ -26,6 +22,11 @@ USA. ***/ +/*** + Based on work for the GNU C Library. + Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. +***/ + /* Poll the file descriptors described by the NFDS structures starting at FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for an event to occur; if TIMEOUT is -1, block until an event occurs. diff --git a/src/pulsecore/poll.h b/src/pulsecore/poll.h index 9c29789d5..6be6069b9 100644 --- a/src/pulsecore/poll.h +++ b/src/pulsecore/poll.h @@ -1,16 +1,10 @@ /* $Id$ */ -/*** - Compatibility definitions for System V `poll' interface. - Copyright (C) 1994,96,97,98,99,2000,2001,2004 Free Software Foundation, Inc. - Copyright (C) 2005, Cendio AB. - This file is part of PulseAudio. - Based on work for the GNU C Library. -***/ - /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, @@ -27,6 +21,11 @@ USA. ***/ +/*** + Based on work for the GNU C Library. + Copyright (C) 1994,96,97,98,99,2000,2001,2004 Free Software Foundation, Inc. +***/ + /* Event types that can be polled for. These bits may be set in `events' to indicate the interesting event types; they will appear in `revents' to indicate the status of the file descriptor. */ diff --git a/src/pulsecore/props.c b/src/pulsecore/props.c index b8f920905..4a39f0fb9 100644 --- a/src/pulsecore/props.c +++ b/src/pulsecore/props.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/props.h b/src/pulsecore/props.h index 2b881b67e..880325f69 100644 --- a/src/pulsecore/props.h +++ b/src/pulsecore/props.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/protocol-cli.c b/src/pulsecore/protocol-cli.c index 9cca39eb1..1d543ae55 100644 --- a/src/pulsecore/protocol-cli.c +++ b/src/pulsecore/protocol-cli.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/protocol-cli.h b/src/pulsecore/protocol-cli.h index 6acd62cfe..3870def31 100644 --- a/src/pulsecore/protocol-cli.h +++ b/src/pulsecore/protocol-cli.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 2984676d8..ae6612ae9 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/protocol-esound.h b/src/pulsecore/protocol-esound.h index 265f9e2cd..868ef5d20 100644 --- a/src/pulsecore/protocol-esound.h +++ b/src/pulsecore/protocol-esound.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c index 22ecba824..3541721aa 100644 --- a/src/pulsecore/protocol-http.c +++ b/src/pulsecore/protocol-http.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2005-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/protocol-http.h b/src/pulsecore/protocol-http.h index bf1562e69..cf9524765 100644 --- a/src/pulsecore/protocol-http.h +++ b/src/pulsecore/protocol-http.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2005-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index a882d701c..4e861f85c 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/protocol-native.h b/src/pulsecore/protocol-native.h index fcd4cb37a..bf05f937b 100644 --- a/src/pulsecore/protocol-native.h +++ b/src/pulsecore/protocol-native.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 0a7a7acbf..31ad6dddf 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/protocol-simple.h b/src/pulsecore/protocol-simple.h index 183f3acc3..3b02c88ee 100644 --- a/src/pulsecore/protocol-simple.h +++ b/src/pulsecore/protocol-simple.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c index 6ebb28630..fae1e49be 100644 --- a/src/pulsecore/pstream-util.c +++ b/src/pulsecore/pstream-util.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/pstream-util.h b/src/pulsecore/pstream-util.h index 5f1bbd607..67759f2aa 100644 --- a/src/pulsecore/pstream-util.h +++ b/src/pulsecore/pstream-util.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 7e1e5f57f..3398df0d1 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h index 0ab16720a..5900eceab 100644 --- a/src/pulsecore/pstream.h +++ b/src/pulsecore/pstream.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/queue.c b/src/pulsecore/queue.c index 3132c5c5b..1dd0f6061 100644 --- a/src/pulsecore/queue.c +++ b/src/pulsecore/queue.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/queue.h b/src/pulsecore/queue.h index cebe4cdf6..cd7673648 100644 --- a/src/pulsecore/queue.h +++ b/src/pulsecore/queue.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/random.c b/src/pulsecore/random.c index c3184c78d..3f5919173 100644 --- a/src/pulsecore/random.c +++ b/src/pulsecore/random.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/random.h b/src/pulsecore/random.h index cdac9ac6e..01b7d746b 100644 --- a/src/pulsecore/random.h +++ b/src/pulsecore/random.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h index f3918213a..43433ff84 100644 --- a/src/pulsecore/refcnt.h +++ b/src/pulsecore/refcnt.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index e61864dd5..3827ff94a 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h index 7a781364d..c283593d6 100644 --- a/src/pulsecore/resampler.h +++ b/src/pulsecore/resampler.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index ddf729202..411787af0 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h index 1883b2cc5..3ff065ab2 100644 --- a/src/pulsecore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sconv-s16be.c b/src/pulsecore/sconv-s16be.c index 3af167dfd..c530e79b8 100644 --- a/src/pulsecore/sconv-s16be.c +++ b/src/pulsecore/sconv-s16be.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sconv-s16be.h b/src/pulsecore/sconv-s16be.h index b96f59ab6..6b736f69b 100644 --- a/src/pulsecore/sconv-s16be.h +++ b/src/pulsecore/sconv-s16be.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c index 1743d61ff..5f45ef66d 100644 --- a/src/pulsecore/sconv-s16le.c +++ b/src/pulsecore/sconv-s16le.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sconv-s16le.h b/src/pulsecore/sconv-s16le.h index 37e85e2fe..c4e4911ad 100644 --- a/src/pulsecore/sconv-s16le.h +++ b/src/pulsecore/sconv-s16le.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index 6bea06083..d15cec847 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sconv.h b/src/pulsecore/sconv.h index 52240fd39..1e97aad9d 100644 --- a/src/pulsecore/sconv.h +++ b/src/pulsecore/sconv.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index 6188b16c7..444d4010e 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/shm.h b/src/pulsecore/shm.h index f621474cb..e695a2a19 100644 --- a/src/pulsecore/shm.h +++ b/src/pulsecore/shm.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 58fe37d55..3ddd74350 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 9d7487f7d..51d9ec788 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index cb0e54c18..9588c2c3d 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 7cfc9e268..ef73f67d2 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sioman.c b/src/pulsecore/sioman.c index 4d5d5562d..d3d7538ef 100644 --- a/src/pulsecore/sioman.c +++ b/src/pulsecore/sioman.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sioman.h b/src/pulsecore/sioman.h index bbd521108..49fffb34c 100644 --- a/src/pulsecore/sioman.h +++ b/src/pulsecore/sioman.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c index b08ba010d..4ea811133 100644 --- a/src/pulsecore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/socket-client.h b/src/pulsecore/socket-client.h index 146ebda87..b1d58eff7 100644 --- a/src/pulsecore/socket-client.h +++ b/src/pulsecore/socket-client.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c index c878ab1ab..eaa8eb910 100644 --- a/src/pulsecore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/socket-server.h b/src/pulsecore/socket-server.h index 489878cb9..777599e5f 100644 --- a/src/pulsecore/socket-server.h +++ b/src/pulsecore/socket-server.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c index e16f89795..5e2cfe037 100644 --- a/src/pulsecore/socket-util.c +++ b/src/pulsecore/socket-util.c @@ -3,6 +3,10 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2004 Joe Marcus Clarke + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/socket-util.h b/src/pulsecore/socket-util.h index 59b4980db..616c40acd 100644 --- a/src/pulsecore/socket-util.h +++ b/src/pulsecore/socket-util.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index a277f1f0c..7a43c7433 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sound-file-stream.h b/src/pulsecore/sound-file-stream.h index 0798b4233..189e242de 100644 --- a/src/pulsecore/sound-file-stream.h +++ b/src/pulsecore/sound-file-stream.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c index 284bbdda0..69b543ab1 100644 --- a/src/pulsecore/sound-file.c +++ b/src/pulsecore/sound-file.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/sound-file.h b/src/pulsecore/sound-file.h index cf8168d00..46763bd8d 100644 --- a/src/pulsecore/sound-file.h +++ b/src/pulsecore/sound-file.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 5783b44a4..c7a9858c4 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index 827b68eef..3da6caacd 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 702dbeffb..9bb2d342d 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index 462bc6ff4..5a28cf4b7 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/strbuf.c b/src/pulsecore/strbuf.c index 59d572601..a3ddc1144 100644 --- a/src/pulsecore/strbuf.c +++ b/src/pulsecore/strbuf.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/strbuf.h b/src/pulsecore/strbuf.h index 04109197e..1c0850b1c 100644 --- a/src/pulsecore/strbuf.h +++ b/src/pulsecore/strbuf.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/strlist.c b/src/pulsecore/strlist.c index 23547bbac..955b78e41 100644 --- a/src/pulsecore/strlist.c +++ b/src/pulsecore/strlist.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/strlist.h b/src/pulsecore/strlist.h index 07d04677e..96ad47e26 100644 --- a/src/pulsecore/strlist.h +++ b/src/pulsecore/strlist.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c index 3a0915cf6..ac7ae1ab8 100644 --- a/src/pulsecore/tagstruct.c +++ b/src/pulsecore/tagstruct.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/tagstruct.h b/src/pulsecore/tagstruct.h index 0177ff9d6..e9bb9ac8d 100644 --- a/src/pulsecore/tagstruct.h +++ b/src/pulsecore/tagstruct.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index dcd45ea73..7ff5e7c30 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/thread-win32.c b/src/pulsecore/thread-win32.c index 38dd4dd65..46d273b41 100644 --- a/src/pulsecore/thread-win32.c +++ b/src/pulsecore/thread-win32.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h index b383bb49b..ca1fe4da8 100644 --- a/src/pulsecore/thread.h +++ b/src/pulsecore/thread.h @@ -6,6 +6,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the diff --git a/src/pulsecore/tokenizer.c b/src/pulsecore/tokenizer.c index 0bc1c0954..117c7f881 100644 --- a/src/pulsecore/tokenizer.c +++ b/src/pulsecore/tokenizer.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/tokenizer.h b/src/pulsecore/tokenizer.h index 82cd6db18..68a8db493 100644 --- a/src/pulsecore/tokenizer.h +++ b/src/pulsecore/tokenizer.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/x11prop.c b/src/pulsecore/x11prop.c index 03d7990e4..5b85ea426 100644 --- a/src/pulsecore/x11prop.c +++ b/src/pulsecore/x11prop.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/x11prop.h b/src/pulsecore/x11prop.h index bd24951a1..388c5a342 100644 --- a/src/pulsecore/x11prop.h +++ b/src/pulsecore/x11prop.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c index e4b048baa..6a6a26924 100644 --- a/src/pulsecore/x11wrap.c +++ b/src/pulsecore/x11wrap.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/pulsecore/x11wrap.h b/src/pulsecore/x11wrap.h index b2e8e5349..9bed2fcea 100644 --- a/src/pulsecore/x11wrap.h +++ b/src/pulsecore/x11wrap.h @@ -6,6 +6,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index f756ac011..d88001ef9 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/pacat.c b/src/utils/pacat.c index cb103c999..96b6adb73 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index d25b26c36..16e5822f0 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 0c418c4fb..b95cbfeee 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/padsp b/src/utils/padsp index bae5a7289..c70c3af71 100755 --- a/src/utils/padsp +++ b/src/utils/padsp @@ -4,6 +4,9 @@ # # This file is part of PulseAudio. # +# Copyright 2006 Lennart Poettering +# Copyright 2006 Pierre Ossman for Cendio AB +# # PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 2b314a9c6..444e1b4d4 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 1617b27dd..2c779a7a3 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, diff --git a/src/utils/pax11publish.c b/src/utils/pax11publish.c index 00332f657..9a50f8ef0 100644 --- a/src/utils/pax11publish.c +++ b/src/utils/pax11publish.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, From 3016c7561d1efb322fae6c82932970c89659ad54 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 14 Feb 2007 09:26:48 +0000 Subject: [PATCH 1324/1514] Prefix log lines with a character indicating level. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1427 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/log.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 7eb83de78..d8a9efe9e 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -129,6 +129,7 @@ void pa_log_levelv_meta( switch (log_target) { case PA_LOG_STDERR: { const char *prefix = "", *suffix = ""; + const char *level_code = ""; char *local_t; #ifndef OS_IS_WIN32 @@ -144,11 +145,33 @@ void pa_log_levelv_meta( } #endif + switch (level) { + case PA_LOG_ERROR: + level_code = "E"; + break; + case PA_LOG_WARN: + level_code = "W"; + break; + case PA_LOG_NOTICE: + level_code = "N"; + break; + case PA_LOG_INFO: + level_code = "I"; + break; + case PA_LOG_DEBUG: + level_code = "D"; + break; + default: + level_code = "?"; + } + local_t = pa_utf8_to_locale(t); - if (!local_t) - fprintf(stderr, "%s%s%s%s\n", location, prefix, t, suffix); - else { - fprintf(stderr, "%s%s%s%s\n", location, prefix, local_t, suffix); + if (!local_t) { + fprintf(stderr, "%s: %s%s%s%s\n", level_code, location, + prefix, t, suffix); + } else { + fprintf(stderr, "%s: %s%s%s%s\n", level_code, location, + prefix, local_t, suffix); pa_xfree(local_t); } From 8bf7943e8e03922de8c4a0990057a6fbf07935c6 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 14 Feb 2007 09:27:19 +0000 Subject: [PATCH 1325/1514] Allow a formatted string in the validation warning. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1428 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-esound.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index ae6612ae9..49a78d410 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -280,9 +280,9 @@ static int format_native2esd(pa_sample_spec *ss) { return format; } -#define CHECK_VALIDITY(expression, string) do { \ +#define CHECK_VALIDITY(expression, ...) do { \ if (!(expression)) { \ - pa_log_warn(__FILE__ ": " string); \ + pa_log_warn(__FILE__ ": " __VA_ARGS__); \ return -1; \ } \ } while(0); @@ -350,7 +350,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t if (c->protocol->sink_name) { sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1); - CHECK_VALIDITY(sink, "No such sink"); + CHECK_VALIDITY(sink, "No such sink: %s", c->protocol->sink_name); } strncpy(name, data, sizeof(name)); @@ -719,7 +719,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ sc_length = MAYBE_INT32_SWAP(c->swap_byte_order, sc_length); data = (const char*)data + sizeof(int32_t); - CHECK_VALIDITY(sc_length <= MAX_CACHE_SAMPLE_SIZE, "Sample too large."); + CHECK_VALIDITY(sc_length <= MAX_CACHE_SAMPLE_SIZE, "Sample too large (%d bytes).", (int)sc_length); strcpy(name, SCACHE_PREFIX); strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX); From df47c7b828c02afbabc4d024008fabb07a882397 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 14 Feb 2007 12:13:49 +0000 Subject: [PATCH 1326/1514] Add a wrapper around close() to work around Windows' ass backwards way of handling sockets. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1429 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-util.c | 22 +++++++++++++++++++++- src/pulsecore/core-util.h | 4 +++- src/pulsecore/iochannel.c | 7 +++---- src/pulsecore/pipe.c | 10 +++++----- src/pulsecore/socket-client.c | 8 ++++---- src/pulsecore/socket-server.c | 14 +++++++------- src/pulsecore/socket-util.c | 4 ++-- 7 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index ac1023a0d..cc0fb205d 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -5,7 +5,7 @@ Copyright 2004-2006 Lennart Poettering Copyright 2004 Joe Marcus Clarke - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006-2007 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -348,6 +348,26 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) { return ret; } +/** Platform independent read function. Necessary since not all + * systems treat all file descriptors equal. */ +int pa_close(int fd) +{ +#ifdef OS_IS_WIN32 + int ret; + + ret = closesocket(fd); + if (ret == 0) + return 0; + + if (WSAGetLastError() != WSAENOTSOCK) { + errno = WSAGetLastError(); + return ret; + } +#endif + + return close(fd); +} + /* Print a warning messages in case that the given signal is not * blocked or trapped */ void pa_check_signal_is_blocked(int sig) { diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index a1da3e287..1d921e036 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -7,7 +7,7 @@ This file is part of PulseAudio. Copyright 2004-2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006-2007 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -44,6 +44,8 @@ ssize_t pa_write(int fd, const void *buf, size_t count, int *type); ssize_t pa_loop_read(int fd, void*data, size_t size, int *type); ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type); +int pa_close(int fd); + void pa_check_signal_is_blocked(int sig); char *pa_sprintf_malloc(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2); diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 2f6fdd39f..6f58ae755 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -4,7 +4,7 @@ This file is part of PulseAudio. Copyright 2004-2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006-2007 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -174,10 +174,9 @@ void pa_iochannel_free(pa_iochannel*io) { if (!io->no_close) { if (io->ifd >= 0) - - close(io->ifd); + pa_close(io->ifd); if (io->ofd >= 0 && io->ofd != io->ifd) - close(io->ofd); + pa_close(io->ofd); } pa_xfree(io); diff --git a/src/pulsecore/pipe.c b/src/pulsecore/pipe.c index a659915e9..7f6bb2e9e 100644 --- a/src/pulsecore/pipe.c +++ b/src/pulsecore/pipe.c @@ -3,7 +3,7 @@ /*** This file is part of PulseAudio. - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006-2007 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -144,17 +144,17 @@ int pipe(int filedes[2]) { if ((addr.sin_port != peer.sin_port) || (addr.sin_addr.s_addr != peer.sin_addr.s_addr)) goto error; - close(listener); + pa_close(listener); return 0; error: if (listener >= 0) - close(listener); + pa_close(listener); if (filedes[0] >= 0) - close(filedes[0]); + pa_close(filedes[0]); if (filedes[1] >= 0) - close(filedes[0]); + pa_close(filedes[0]); return -1; } diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c index 4ea811133..b99c8025d 100644 --- a/src/pulsecore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -4,7 +4,7 @@ This file is part of PulseAudio. Copyright 2004-2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006-2007 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -163,7 +163,7 @@ static void do_call(pa_socket_client *c) { finish: if (!io && c->fd >= 0) - close(c->fd); + pa_close(c->fd); c->fd = -1; free_events(c); @@ -310,7 +310,7 @@ static void socket_client_free(pa_socket_client *c) { free_events(c); if (c->fd >= 0) - close(c->fd); + pa_close(c->fd); #ifdef HAVE_LIBASYNCNS if (c->asyncns_query) @@ -403,7 +403,7 @@ static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeva assert(c); if (c->fd >= 0) { - close(c->fd); + pa_close(c->fd); c->fd = -1; } diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c index eaa8eb910..b5a6dc317 100644 --- a/src/pulsecore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -4,7 +4,7 @@ This file is part of PulseAudio. Copyright 2004-2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006-2007 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -106,7 +106,7 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U pa_fd_set_cloexec(nfd, 1); if (!s->on_connection) { - close(nfd); + pa_close(nfd); goto finish; } @@ -119,7 +119,7 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U fromhost(&req); if (!hosts_access(&req)) { pa_log_warn("TCP connection refused by tcpwrap."); - close(nfd); + pa_close(nfd); goto finish; } @@ -216,7 +216,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file fail: if (fd >= 0) - close(fd); + pa_close(fd); return NULL; } @@ -275,7 +275,7 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address fail: if (fd >= 0) - close(fd); + pa_close(fd); return NULL; } @@ -331,7 +331,7 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad fail: if (fd >= 0) - close(fd); + pa_close(fd); return NULL; } @@ -398,7 +398,7 @@ static void socket_server_free(pa_socket_server*s) { pa_xfree(s->filename); } - close(s->fd); + pa_close(s->fd); pa_xfree(s->tcpwrap_service); diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c index 5e2cfe037..673058e2a 100644 --- a/src/pulsecore/socket-util.c +++ b/src/pulsecore/socket-util.c @@ -5,7 +5,7 @@ Copyright 2004-2006 Lennart Poettering Copyright 2004 Joe Marcus Clarke - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006-2007 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -236,7 +236,7 @@ int pa_unix_socket_is_stale(const char *fn) { finish: if (fd >= 0) - close(fd); + pa_close(fd); return ret; } From 6ba21d4a0bdc031162a1755a15d5a2088a04fb2f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 1 Mar 2007 17:11:10 +0000 Subject: [PATCH 1327/1514] Add some debugging output from sample cache subsystem. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1430 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-scache.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c index 75fb47f02..cb2727845 100644 --- a/src/pulsecore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -138,6 +138,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_memchunk *chunk, uint32_t *idx) { pa_scache_entry *e; + char st[PA_SAMPLE_SPEC_SNPRINT_MAX]; assert(c && name); if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX) @@ -163,6 +164,10 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c if (idx) *idx = e->index; + pa_log_debug("created sample \"%s\" (#%d), %d bytes with sample spec %s", + name, e->index, e->memchunk.length, + pa_sample_spec_snprint(st, sizeof(st), &e->sample_spec)); + return 0; } @@ -229,7 +234,10 @@ int pa_scache_remove_item(pa_core *c, const char *name) { if (pa_idxset_remove_by_data(c->scache, e, NULL) != e) assert(0); + pa_log_debug("removed sample \"%s\"", name); + free_entry(e); + return 0; } @@ -276,6 +284,8 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t if (!e->memchunk.memblock) return -1; + pa_log_debug("playing sample \"%s\" on \"%s\"", name, sink->name); + t = pa_sprintf_malloc("sample:%s", name); pa_cvolume_set(&r, e->volume.channels, volume); From bb812433a8847704ab7681aad812558439e176ee Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 1 Mar 2007 17:13:26 +0000 Subject: [PATCH 1328/1514] Handle when ALSA tweaks our sample spec so much that the frame size changes. (closes #57). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1431 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 6 ++++-- configure.ac | 1 + src/modules/module-alsa-sink.c | 9 ++++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 1b77187de..765e8fa48 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,8 +17,8 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in README todo -SUBDIRS=libltdl src doxygen +EXTRA_DIST = config.rpath m4/ChangeLog bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in README todo +SUBDIRS= libltdl src doxygen MAINTAINERCLEANFILES = noinst_DATA = @@ -46,3 +46,5 @@ doxygen: $(MAKE) -C doxygen doxygen .PHONY: homepage distcleancheck doxygen + +ACLOCAL_AMFLAGS = -I m4 diff --git a/configure.ac b/configure.ac index 65a99a00d..68ad67278 100644 --- a/configure.ac +++ b/configure.ac @@ -772,6 +772,7 @@ AM_CONDITIONAL([FORCE_PREOPEN], [test "x$FORCE_PREOPEN" = "x1"]) AC_CONFIG_FILES([ Makefile src/Makefile +po/Makefile.in libpulse.pc libpulse-simple.pc libpulse-browse.pc diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 74a57f371..6f8f270d8 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -159,7 +159,11 @@ static void do_write(struct userdata *u) { memchunk = &u->memchunk; } - assert(memchunk->memblock && memchunk->memblock->data && memchunk->length && memchunk->memblock->length && (memchunk->length % u->frame_size) == 0); + assert(memchunk->memblock); + assert(memchunk->memblock->data); + assert(memchunk->length); + assert(memchunk->memblock->length); + assert((memchunk->length % u->frame_size) == 0); if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) { if (frames == -EAGAIN) @@ -415,6 +419,9 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + /* ALSA might tweak the sample spec, so recalculate the frame size */ + frame_size = pa_frame_size(&ss); + if (ss.channels != map.channels) /* Seems ALSA didn't like the channel number, so let's fix the channel map */ pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); From 19b17ff50447875d55ef4c819fd0f3c45537cce9 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 1 Mar 2007 17:15:43 +0000 Subject: [PATCH 1329/1514] Revert stuff from commit 1431 that wasn't supposed to be there. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1432 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 6 ++---- configure.ac | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index 765e8fa48..1b77187de 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,8 +17,8 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -EXTRA_DIST = config.rpath m4/ChangeLog bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in README todo -SUBDIRS= libltdl src doxygen +EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in README todo +SUBDIRS=libltdl src doxygen MAINTAINERCLEANFILES = noinst_DATA = @@ -46,5 +46,3 @@ doxygen: $(MAKE) -C doxygen doxygen .PHONY: homepage distcleancheck doxygen - -ACLOCAL_AMFLAGS = -I m4 diff --git a/configure.ac b/configure.ac index 68ad67278..65a99a00d 100644 --- a/configure.ac +++ b/configure.ac @@ -772,7 +772,6 @@ AM_CONDITIONAL([FORCE_PREOPEN], [test "x$FORCE_PREOPEN" = "x1"]) AC_CONFIG_FILES([ Makefile src/Makefile -po/Makefile.in libpulse.pc libpulse-simple.pc libpulse-browse.pc From 2b82336df2eb8cf1c9ae150b1850540a88f68ecf Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 2 Mar 2007 09:20:54 +0000 Subject: [PATCH 1330/1514] Handle suspended alsa devices. Based on patch by ranma. (closes #26) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1433 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 38 +++++++++++++++++++++++++++++++ src/modules/module-alsa-source.c | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 6f8f270d8..3d9f75774 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -141,6 +141,33 @@ static int xrun_recovery(struct userdata *u) { return ret; } +static int suspend_recovery(struct userdata *u) { + int ret; + assert(u); + + pa_log_info("*** ALSA-SUSPEND (playback) ***"); + + if ((ret = snd_pcm_resume(u->pcm_handle)) < 0) { + if (ret == -EAGAIN) + return -1; + + if (ret != -ENOSYS) + pa_log("snd_pcm_resume() failed: %s", snd_strerror(-ret)); + else { + if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) + pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); + } + + if (ret < 0) { + clear_up(u); + pa_module_unload_request(u->module); + return -1; + } + } + + return ret; +} + static void do_write(struct userdata *u) { assert(u); @@ -176,6 +203,13 @@ static void do_write(struct userdata *u) { continue; } + if (frames == -ESTRPIPE) { + if (suspend_recovery(u) < 0) + return; + + continue; + } + pa_log("snd_pcm_writei() failed: %s", snd_strerror(-frames)); clear_up(u); @@ -207,6 +241,10 @@ static void fdl_callback(void *userdata) { if (xrun_recovery(u) < 0) return; + if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_SUSPENDED) + if (suspend_recovery(u) < 0) + return; + do_write(u); } diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 2ea551cb8..4061d668c 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -143,6 +143,34 @@ static int xrun_recovery(struct userdata *u) { return 0; } + +static int suspend_recovery(struct userdata *u) { + int ret; + assert(u); + + pa_log_info("*** ALSA-SUSPEND (capture) ***"); + + if ((ret = snd_pcm_resume(u->pcm_handle)) < 0) { + if (ret == -EAGAIN) + return -1; + + if (ret != -ENOSYS) + pa_log("snd_pcm_resume() failed: %s", snd_strerror(-ret)); + else { + if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) + pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); + } + + if (ret < 0) { + clear_up(u); + pa_module_unload_request(u->module); + return -1; + } + } + + return ret; +} + static void do_read(struct userdata *u) { assert(u); @@ -175,6 +203,13 @@ static void do_read(struct userdata *u) { continue; } + if (frames == -ESTRPIPE) { + if (suspend_recovery(u) < 0) + return; + + continue; + } + pa_log("snd_pcm_readi() failed: %s", snd_strerror(-frames)); clear_up(u); @@ -210,6 +245,10 @@ static void fdl_callback(void *userdata) { if (xrun_recovery(u) < 0) return; + if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_SUSPENDED) + if (suspend_recovery(u) < 0) + return; + do_read(u); } From 0b14c026890ee6806971d179a66aee5b03e1d763 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 6 Mar 2007 13:31:29 +0000 Subject: [PATCH 1331/1514] Don't fail if hal doesn't currently contain any devices. (closes #55) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1434 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 56a3efc19..a28b6f0dc 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -488,7 +488,6 @@ fail: } int pa__init(pa_core *c, pa_module*m) { - int n; DBusError error; pa_dbus_connection *conn; struct userdata *u = NULL; @@ -519,16 +518,11 @@ int pa__init(pa_core *c, pa_module*m) { m->userdata = (void*) u; #ifdef HAVE_ALSA - if ((n = hal_device_add_all(u, CAP_ALSA)) <= 0) + hal_device_add_all(u, CAP_ALSA); #endif #ifdef HAVE_OSS - if ((n = hal_device_add_all(u, CAP_OSS)) <= 0) + hal_device_add_all(u, CAP_OSS); #endif - { - pa_log_warn("failed to detect any sound hardware."); - userdata_free(u); - return -1; - } libhal_ctx_set_user_data(hal_ctx, (void*) u); libhal_ctx_set_device_added(hal_ctx, device_added_cb); From e042a90a53b7c7b387e3acd06a23638f4826c30f Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 6 Mar 2007 13:42:30 +0000 Subject: [PATCH 1332/1514] Pulsecore should be linked into all modules. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1435 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 0b509ac95..7ee5354a4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1149,7 +1149,7 @@ module_x11_bell_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA module_x11_publish_la_SOURCES = modules/module-x11-publish.c module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_publish_la_LDFLAGS = -module -avoid-version -module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauthkey-prop.la libx11prop.la libstrlist.la +module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauthkey-prop.la libx11prop.la libstrlist.la libpulsecore.la # OSS From f6023cb5ee2c6562c7a47d96828a80a64e3ea59c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 6 Mar 2007 15:47:11 +0000 Subject: [PATCH 1333/1514] Fix some instances where we printed a string without first checking that the pointer was valid. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1436 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/cli-command.c | 7 +++++-- src/pulsecore/cli-text.c | 13 ++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index aa2beba2c..e87b257bd 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -246,6 +246,7 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G char s[256]; const pa_mempool_stat *stat; unsigned k; + const char *def_sink, *def_source; static const char* const type_table[PA_MEMBLOCK_TYPE_MAX] = { [PA_MEMBLOCK_POOL] = "POOL", @@ -283,10 +284,12 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_strbuf_printf(buf, "Default sample spec: %s\n", pa_sample_spec_snprint(s, sizeof(s), &c->default_sample_spec)); + def_sink = pa_namereg_get_default_sink_name(c); + def_source = pa_namereg_get_default_source_name(c); pa_strbuf_printf(buf, "Default sink name: %s\n" "Default source name: %s\n", - pa_namereg_get_default_sink_name(c), - pa_namereg_get_default_source_name(c)); + def_sink ? def_sink : "none", + def_source ? def_source : "none"); for (k = 0; k < PA_MEMBLOCK_TYPE_MAX; k++) pa_strbuf_printf(buf, diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index e97f0574f..413f93340 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -55,8 +55,15 @@ char *pa_module_list_to_string(pa_core *c) { pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_size(c->modules)); - for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) - pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\targument: <%s>\n\tused: %i\n\tauto unload: %s\n", m->index, m->name, m->argument, m->n_used, m->auto_unload ? "yes" : "no"); + for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) { + pa_strbuf_printf(s, " index: %u\n" + "\tname: <%s>\n" + "\targument: <%s>\n" + "\tused: %i\n" + "\tauto unload: %s\n", + m->index, m->name, m->argument ? m->argument : "", m->n_used, + m->auto_unload ? "yes" : "no"); + } return pa_strbuf_tostring_free(s); } @@ -337,7 +344,7 @@ char *pa_autoload_list_to_string(pa_core *c) { e->type == PA_NAMEREG_SOURCE ? "source" : "sink", e->index, e->module, - e->argument); + e->argument ? e->argument : ""); } } From 9ee398107e524ca71a0cfd23e003daa300d1e227 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 7 Mar 2007 09:27:30 +0000 Subject: [PATCH 1334/1514] Add support for SNDCTL_DSP_SETTRIGGER. (closes #56) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1437 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 96 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 9 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 444e1b4d4..fddd8fb4b 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -4,7 +4,7 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006-2007 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -84,6 +84,8 @@ struct fd_info { pa_context *context; pa_stream *play_stream; pa_stream *rec_stream; + int play_precork; + int rec_precork; pa_io_event *io_event; pa_io_event_flags_t io_flags; @@ -197,7 +199,7 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY) { \ debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ -} while(0); +} while(0) #define PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ @@ -205,7 +207,7 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ -} while(0); +} while(0) #define RECORD_STREAM_CHECK_DEAD_GOTO(i, label) do { \ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ @@ -213,7 +215,7 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ debug(DEBUG_LEVEL_NORMAL, __FILE__": Not connected: %s\n", (i)->context ? pa_strerror(pa_context_errno((i)->context)) : "NULL"); \ goto label; \ } \ -} while(0); +} while(0) static void debug(int level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); @@ -572,6 +574,8 @@ static fd_info* fd_info_new(fd_info_type_t type, int *_errno) { i->context = NULL; i->play_stream = NULL; i->rec_stream = NULL; + i->play_precork = 0; + i->rec_precork = 0; i->io_event = NULL; i->io_flags = 0; pthread_mutex_init(&i->mutex, NULL); @@ -937,7 +941,7 @@ static void stream_state_cb(pa_stream *s, void * userdata) { static int create_playback_stream(fd_info *i) { pa_buffer_attr attr; - int n; + int n, flags; assert(i); @@ -958,7 +962,12 @@ static int create_playback_stream(fd_info *i) { attr.prebuf = i->fragment_size; attr.minreq = i->fragment_size; - if (pa_stream_connect_playback(i->play_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { + flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE; + if (i->play_precork) { + flags |= PA_STREAM_START_CORKED; + debug(DEBUG_LEVEL_NORMAL, __FILE__": creating stream corked\n"); + } + if (pa_stream_connect_playback(i->play_stream, NULL, &attr, flags, NULL, NULL) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -976,7 +985,7 @@ fail: static int create_record_stream(fd_info *i) { pa_buffer_attr attr; - int n; + int n, flags; assert(i); @@ -995,7 +1004,12 @@ static int create_record_stream(fd_info *i) { attr.maxlength = i->fragment_size * (i->n_fragments+1); attr.fragsize = i->fragment_size; - if (pa_stream_connect_record(i->rec_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE) < 0) { + flags = PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE; + if (i->rec_precork) { + flags |= PA_STREAM_START_CORKED; + debug(DEBUG_LEVEL_NORMAL, __FILE__": creating stream corked\n"); + } + if (pa_stream_connect_record(i->rec_stream, NULL, &attr, flags) < 0) { debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(i->context))); goto fail; } @@ -1800,6 +1814,44 @@ fail: return 0; } +static int dsp_cork(fd_info *i, pa_stream *s, int b) { + pa_operation *o = NULL; + int r = -1; + + pa_threaded_mainloop_lock(i->mainloop); + + if (!(o = pa_stream_cork(s, b, stream_success_cb, i))) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + i->operation_success = 0; + while (!pa_operation_get_state(o) != PA_OPERATION_DONE) { + if (s == i->play_stream) + PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail); + else if (s == i->rec_stream) + RECORD_STREAM_CHECK_DEAD_GOTO(i, fail); + + pa_threaded_mainloop_wait(i->mainloop); + } + + if (!i->operation_success) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_cork(): %s\n", pa_strerror(pa_context_errno(i->context))); + goto fail; + } + + r = 0; + +fail: + + if (o) + pa_operation_unref(o); + + pa_threaded_mainloop_unlock(i->mainloop); + + return 0; +} + static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; @@ -1929,7 +1981,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_GETCAPS: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n"); - *(int*) argp = DSP_CAP_DUPLEX + *(int*) argp = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER #ifdef DSP_CAP_MULTI | DSP_CAP_MULTI #endif @@ -2009,6 +2061,32 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) *_errno = EIO; break; + case SNDCTL_DSP_SETTRIGGER: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETTRIGGER: 0x%08x\n", *(int*) argp); + + if (!i->io_event) { + *_errno = EIO; + break; + } + + i->play_precork = !((*(int*) argp) & PCM_ENABLE_OUTPUT); + + if (i->play_stream) { + if (dsp_cork(i, i->play_stream, !((*(int*) argp) & PCM_ENABLE_OUTPUT)) < 0) + *_errno = EIO; + if (dsp_trigger(i) < 0) + *_errno = EIO; + } + + i->rec_precork = !((*(int*) argp) & PCM_ENABLE_INPUT); + + if (i->rec_stream) { + if (dsp_cork(i, i->rec_stream, !((*(int*) argp) & PCM_ENABLE_INPUT)) < 0) + *_errno = EIO; + } + + break; + case SNDCTL_DSP_SYNC: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SYNC\n"); From 16dd5f78729578257dcde66e08393a59114a7402 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 May 2007 23:08:34 +0000 Subject: [PATCH 1335/1514] fix comment git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1438 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/g711.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/g711.h b/src/pulsecore/g711.h index b5c9e6a2c..37ebcf72a 100644 --- a/src/pulsecore/g711.h +++ b/src/pulsecore/g711.h @@ -13,7 +13,7 @@ ** implied warranty. */ -/** Copied from sox -- Lennart Poettring*/ +/** Copied from sox -- Lennart Poettering */ #include From e41b91eec984c2ff61222d56872e9c3966a87375 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 May 2007 23:37:27 +0000 Subject: [PATCH 1336/1514] drop unused variable git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1439 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/tests/flist-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/flist-test.c b/src/tests/flist-test.c index 17ba55c17..7e54454eb 100644 --- a/src/tests/flist-test.c +++ b/src/tests/flist-test.c @@ -54,7 +54,7 @@ static void thread_func(void *data) { int b = 1; while (!quit) { - char *text, *t; + char *text; /* Allocate some memory, if possible take it from the flist */ if (b && (text = pa_flist_pop(flist))) From 960b5cbd10105df4cd6320e005b73e3c9aa32cc6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 May 2007 23:38:22 +0000 Subject: [PATCH 1337/1514] Fix build and only load OSS xor ALSA modules if both are available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1440 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 34 ++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index a28b6f0dc..27cd449ec 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -85,6 +85,9 @@ struct userdata { capability_t capability; pa_dbus_connection *conn; pa_hashmap *devices; +#if defined(HAVE_ALSA) && defined(HAVE_OSS) + int use_oss; +#endif }; struct timerdata { @@ -185,6 +188,8 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi)); } + pa_log_debug("Loading %s with arguments '%s'", module_name, args); + return pa_module_load(u->core, module_name, args); } @@ -242,6 +247,8 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi)); libhal_free_string(device); + pa_log_debug("Loading module-oss with arguments '%s'", args); + return pa_module_load(u->core, "module-oss", args); } #endif @@ -249,7 +256,7 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, DBusError *error) { - pa_module* m; + pa_module* m = NULL; struct device *d; switch(u->capability) { @@ -260,7 +267,10 @@ static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, #endif #ifdef HAVE_OSS case CAP_OSS: - m = hal_device_load_oss(u, udi, error); +#ifdef HAVE_ALSA + if (u->use_oss) +#endif + m = hal_device_load_oss(u, udi, error); break; #endif default: @@ -492,6 +502,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_dbus_connection *conn; struct userdata *u = NULL; LibHalContext *hal_ctx = NULL; + int n = 0; assert(c); assert(m); @@ -518,13 +529,26 @@ int pa__init(pa_core *c, pa_module*m) { m->userdata = (void*) u; #ifdef HAVE_ALSA - hal_device_add_all(u, CAP_ALSA); + n = hal_device_add_all(u, CAP_ALSA); #endif +#if defined(HAVE_ALSA) && defined(HAVE_OSS) + u->use_oss = 0; + + if (n <= 0) { +#endif #ifdef HAVE_OSS - hal_device_add_all(u, CAP_OSS); + n += hal_device_add_all(u, CAP_OSS); #endif +#if defined(HAVE_ALSA) && defined(HAVE_OSS) - libhal_ctx_set_user_data(hal_ctx, (void*) u); + /* We found something with OSS, but didn't find anything with + * ALSA. Then let's use only OSS from now on. */ + if (n > 0) + u->use_oss = 1; + } +#endif + + libhal_ctx_set_user_data(hal_ctx, u); libhal_ctx_set_device_added(hal_ctx, device_added_cb); libhal_ctx_set_device_removed(hal_ctx, device_removed_cb); libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); From 01ddb5488982e1ee78eee381f707e3a066f91c43 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 May 2007 23:39:47 +0000 Subject: [PATCH 1338/1514] show socket directory when we fail to create it. (Closes #85) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1441 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-protocol-stub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 4728f7508..5c8733fb4 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -271,7 +271,7 @@ int pa__init(pa_core *c, pa_module*m) { * /tmp/.esd/, hence we have to create the dir first */ if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) { - pa_log("Failed to create socket directory: %s\n", pa_cstrerror(errno)); + pa_log("Failed to create socket directory '%s': %s\n", u->socket_path, pa_cstrerror(errno)); goto fail; } #endif From 312c326def9b4cc20642ea8f2692d4f2da1406ad Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 01:02:06 +0000 Subject: [PATCH 1339/1514] Fix module-oss for devices that return EAGAIN when we don't expect it. (Closes #66) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1442 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 965944a79..22b12ef74 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -169,10 +169,14 @@ static void do_write(struct userdata *u) { assert(memchunk->length); if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { - pa_log("write() failed: %s", pa_cstrerror(errno)); - clear_up(u); - pa_module_unload_request(u->module); + if (errno != EAGAIN) { + pa_log("write() failed: %s", pa_cstrerror(errno)); + + clear_up(u); + pa_module_unload_request(u->module); + } + break; } @@ -224,11 +228,14 @@ static void do_read(struct userdata *u) { assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); + if (errno != EAGAIN) { pa_log("read() failed: %s", pa_cstrerror(errno)); + clear_up(u); pa_module_unload_request(u->module); } + break; } From 0e53f939c011a5f2ebc15658029f0a578e0bd68f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 12:32:37 +0000 Subject: [PATCH 1340/1514] Treat empty :0.0 identically to unset :0.0 when trying to find a PA server. (Closes #87) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1443 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/client-conf-x11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulse/client-conf-x11.c b/src/pulse/client-conf-x11.c index b5ac8d9fa..e8de95530 100644 --- a/src/pulse/client-conf-x11.c +++ b/src/pulse/client-conf-x11.c @@ -44,7 +44,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { int ret = -1; char t[1024]; - if (!dname && !getenv("DISPLAY")) + if (!dname && (!(dname = getenv("DISPLAY")) || *dname == '\0')) goto finish; if (!(d = XOpenDisplay(dname))) { From 8e738ede9b2050a29400d4218b96b68863290857 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 15:30:34 +0000 Subject: [PATCH 1341/1514] fix a few obvious copynpaste errors when handling volumes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1444 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index fddd8fb4b..0ac48254d 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -1511,14 +1511,14 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno case SOUND_MIXER_WRITE_IGAIN: { pa_cvolume v, *pv; - if (request == SOUND_MIXER_READ_PCM) + if (request == SOUND_MIXER_WRITE_PCM) debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_PCM\n"); else debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_WRITE_IGAIN\n"); pa_threaded_mainloop_lock(i->mainloop); - if (request == SOUND_MIXER_READ_PCM) { + if (request == SOUND_MIXER_WRITE_PCM) { v = i->sink_volume; pv = &i->sink_volume; } else { @@ -1532,7 +1532,7 @@ static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno if (!pa_cvolume_equal(pv, &v)) { pa_operation *o; - if (request == SOUND_MIXER_READ_PCM) + if (request == SOUND_MIXER_WRITE_PCM) o = pa_context_set_sink_volume_by_index(i->context, i->sink_index, pv, context_success_cb, i); else o = pa_context_set_source_volume_by_index(i->context, i->source_index, pv, context_success_cb, i); From 407a1b6efe059797fcbf583007de411321ed76b7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 16:24:54 +0000 Subject: [PATCH 1342/1514] fix a DoS vulnerability (re #67), originally identified by Luigi Auriemma git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1445 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pstream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 3398df0d1..dbee77634 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -632,7 +632,7 @@ static int do_read(pa_pstream *p) { flags = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]); - if (!p->import && (flags & PA_FLAG_SHMMASK) != 0) { + if (!p->use_shm && (flags & PA_FLAG_SHMMASK) != 0) { pa_log_warn("Recieved SHM frame on a socket where SHM is disabled."); return -1; } From f90339528b5f72aabf0008b83ff25bd6b78d05a0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 16:29:18 +0000 Subject: [PATCH 1343/1514] Fix another DoS vulnerability, also identified Luigi Auriemma (closes #67) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1446 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pstream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index dbee77634..897e4295f 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -662,7 +662,7 @@ static int do_read(pa_pstream *p) { length = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]); - if (length > FRAME_SIZE_MAX_ALLOW) { + if (length > FRAME_SIZE_MAX_ALLOW || length <= 0) { pa_log_warn("Recieved invalid frame size : %lu", (unsigned long) length); return -1; } From c3b5de77bc2cacc4aa94b1ee982c93222eb9261c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 16:30:57 +0000 Subject: [PATCH 1344/1514] fix minor typo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1447 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pstream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index 897e4295f..fdb1a66a3 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -663,7 +663,7 @@ static int do_read(pa_pstream *p) { length = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]); if (length > FRAME_SIZE_MAX_ALLOW || length <= 0) { - pa_log_warn("Recieved invalid frame size : %lu", (unsigned long) length); + pa_log_warn("Recieved invalid frame size: %lu", (unsigned long) length); return -1; } From cf925b10e157c0ae87ff876dd8047586226afa87 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 16:42:26 +0000 Subject: [PATCH 1345/1514] Fix yet another DoS vulnerability, also identified Luigi Auriemma (re #67) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1448 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-native.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 4e861f85c..774f69188 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -763,7 +763,8 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, maxlength > 0 && maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); - + CHECK_VALIDITY(c->pstream, maxlength >= pa_frame_size(&ss), tag, PA_ERR_INVALID); + if (sink_index != PA_INVALID_INDEX) { sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); From 4a05bc9bdcb4404f3e23cef367ff378b9e39d220 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 16:57:35 +0000 Subject: [PATCH 1346/1514] don't allow excessively high sample rates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1449 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/sample.c | 1 + src/pulse/sample.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/pulse/sample.c b/src/pulse/sample.c index aafafc839..ffdeedf75 100644 --- a/src/pulse/sample.c +++ b/src/pulse/sample.c @@ -80,6 +80,7 @@ int pa_sample_spec_valid(const pa_sample_spec *spec) { assert(spec); if (spec->rate <= 0 || + spec->rate > PA_RATE_MAX || spec->channels <= 0 || spec->channels > PA_CHANNELS_MAX || spec->format >= PA_SAMPLE_MAX || diff --git a/src/pulse/sample.h b/src/pulse/sample.h index 5e6036858..683167cc5 100644 --- a/src/pulse/sample.h +++ b/src/pulse/sample.h @@ -105,6 +105,9 @@ PA_C_DECL_BEGIN /** Maximum number of allowed channels */ #define PA_CHANNELS_MAX 32 +/** Maximum allowed sample rate */ +#define PA_RATE_MAX (48000*4) + /** Sample format */ typedef enum pa_sample_format { PA_SAMPLE_U8, /**< Unsigned 8 Bit PCM */ From 33304ba1181bde267c8a54f6587778fe0cfd28b6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 16:59:03 +0000 Subject: [PATCH 1347/1514] Fix a DoS with allocating overly large silence buffers. (Identified by Luigi Auriemma (re #67) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1450 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/sample-util.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index 411787af0..c8e7acf06 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -38,13 +38,25 @@ #include "sample-util.h" #include "endianmacros.h" +#define PA_SILENCE_MAX (1024*1024*1) + pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spec, size_t length) { + size_t fs; assert(pool); assert(spec); if (length == 0) length = pa_bytes_per_second(spec)/20; /* 50 ms */ + if (length > PA_SILENCE_MAX) + length = PA_SILENCE_MAX; + + fs = pa_frame_size(spec); + length = ((PA_SILENCE_MAX+fs-1) / fs) * fs; + + if (length <= 0) + length = fs; + return pa_silence_memblock(pa_memblock_new(pool, length), spec); } From 30c52e56c34268d992384aa0cd3370150d90ec43 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 17:12:07 +0000 Subject: [PATCH 1348/1514] add a missing initialization that causes a crash when parsing invalid volume restoration tables (Problem identified by Luigi Auriemma, re #67) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1451 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 0df270dff..61a17aefc 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -435,6 +435,7 @@ int pa__init(pa_core *c, pa_module*m) { u->subscription = NULL; u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL)); u->modified = 0; + u->sink_input_hook_slot = u->source_output_hook_slot = NULL; m->userdata = u; From 79c94db7a62773c2b7ba428a0f4275ca23441a62 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 17:24:06 +0000 Subject: [PATCH 1349/1514] Fix another DoS vulnerability that has been identified by Luigi Auriemma. (Finally closes #67) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1452 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/rtp/sap.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index f61c0efe8..a6e92187f 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -144,9 +144,6 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { goto fail; } - if (!size) - return 0; - buf = pa_xnew(char, size+1); buf[size] = 0; From 003264213cd8e5e6535ed3cf672a78b27055bf28 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 23:38:28 +0000 Subject: [PATCH 1350/1514] only browse for ipv4 pa servers for now. Needs better fixing which however is not trivial and probably breaks the API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1453 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/browser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulse/browser.c b/src/pulse/browser.c index 27c5a2ead..ea2706e42 100644 --- a/src/pulse/browser.c +++ b/src/pulse/browser.c @@ -337,7 +337,7 @@ pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t fla !(b->server_browser = avahi_service_browser_new( b->client, AVAHI_IF_UNSPEC, - AVAHI_PROTO_UNSPEC, + AVAHI_PROTO_INET, SERVICE_TYPE_SERVER, NULL, 0, From 65e87616833252884e4ab6b87373f98939fc446a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 25 May 2007 20:24:55 +0000 Subject: [PATCH 1351/1514] fix suid Makefile target git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1454 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 7ee5354a4..e05b53641 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1283,9 +1283,9 @@ gconf_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) # Some minor stuff # ################################### -suid: pulse - chown root $< - chmod u+s $< +suid: pulseaudio .libs/lt-pulseaudio + chown root $^ + chmod u+s $^ CLEANFILES = esdcompat client.conf default.pa daemon.conf From 4d88fcd59da84ac4f09113855c8f15384a4e05c3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 25 May 2007 20:35:30 +0000 Subject: [PATCH 1352/1514] when called with the setid bit change euid to uid sooner to make sure that we can access our own files even when we dropped most capabilities. (Closes #21) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1455 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/caps.c | 33 +++++++++++++++------------------ src/daemon/main.c | 31 +++++++++++++++++++------------ src/pulsecore/core-util.c | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 66 insertions(+), 32 deletions(-) diff --git a/src/daemon/caps.c b/src/daemon/caps.c index 2ea51c9f9..8043230c7 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -35,6 +35,9 @@ #ifdef HAVE_SYS_CAPABILITY_H #include #endif +#ifdef HAVE_SYS_PRCTL_H +#include +#endif #include @@ -76,35 +79,31 @@ void pa_drop_root(void) { #endif -#ifdef HAVE_SYS_CAPABILITY_H +#if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_SYS_PRCTL_H) -/* Limit capabilities set to CAPSYS_NICE */ +/* Limit permitted capabilities set to CAPSYS_NICE */ int pa_limit_caps(void) { int r = -1; cap_t caps; cap_value_t nice_cap = CAP_SYS_NICE; - /* Only drop caps when called SUID */ - if (getuid() == 0) - return 0; - caps = cap_init(); assert(caps); - cap_clear(caps); - - cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET); if (cap_set_proc(caps) < 0) goto fail; + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) + goto fail; + pa_log_info("dropped capabilities successfully."); - - r = 0; + + r = 1; fail: - cap_free (caps); + cap_free(caps); return r; } @@ -114,24 +113,22 @@ int pa_drop_caps(void) { cap_t caps; int r = -1; - /* Only drop caps when called SUID */ - if (getuid() == 0) - return 0; - caps = cap_init(); assert(caps); cap_clear(caps); + prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0); + if (cap_set_proc(caps) < 0) { pa_log("failed to drop capabilities: %s", pa_cstrerror(errno)); goto fail; } - + r = 0; fail: - cap_free (caps); + cap_free(caps); return r; } diff --git a/src/daemon/main.c b/src/daemon/main.c index 211dd30c7..72e47975e 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -329,23 +329,30 @@ int main(int argc, char *argv[]) { struct timeval tv; #endif - setlocale(LC_ALL, ""); - - pa_limit_caps(); - #ifdef HAVE_GETUID real_root = getuid() == 0; suid_root = !real_root && geteuid() == 0; - - if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) { - pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'."); - pa_drop_root(); - } #else real_root = 0; suid_root = 0; #endif + if (suid_root) { + if (pa_limit_caps() > 0) + /* We managed to drop capabilities except the needed + * ones. Hence we can drop the uid. */ + pa_drop_root(); + } + + setlocale(LC_ALL, ""); + + if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) { + pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'."); + pa_drop_caps(); + pa_drop_root(); + suid_root = real_root = 0; + } + LTDL_SET_PRELOADED_SYMBOLS(); r = lt_dlinit(); @@ -381,10 +388,10 @@ int main(int argc, char *argv[]) { if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) pa_raise_priority(); - pa_drop_caps(); - - if (suid_root) + if (suid_root) { + pa_drop_caps(); pa_drop_root(); + } if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index cc0fb205d..480ac3b71 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -51,6 +51,10 @@ #include #endif +#ifdef HAVE_SYS_CAPABILITY_H +#include +#endif + #ifdef HAVE_PTHREAD #include #endif @@ -481,7 +485,23 @@ char *pa_strlcpy(char *b, const char *s, size_t l) { sensible: set the nice level to -15 and enable realtime scheduling if supported.*/ void pa_raise_priority(void) { +#if defined(HAVE_SYS_CAPABILITY_H) + cap_t caps; + /* Temporarily acquire CAP_SYS_NICE in the effective set */ + if ((caps = cap_get_proc())) { + cap_t caps_new; + cap_value_t nice_cap = CAP_SYS_NICE; + + if ((caps_new = cap_dup(caps))) { + cap_set_flag(caps_new, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET); + cap_set_flag(caps_new, CAP_PERMITTED, 1, &nice_cap, CAP_SET); + cap_set_proc(caps_new); + cap_free(caps_new); + } + } +#endif + #ifdef HAVE_SYS_RESOURCE_H if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) pa_log_warn("setpriority(): %s", pa_cstrerror(errno)); @@ -495,13 +515,13 @@ void pa_raise_priority(void) { if (sched_getparam(0, &sp) < 0) { pa_log("sched_getparam(): %s", pa_cstrerror(errno)); - return; + goto fail; } sp.sched_priority = 1; if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) { pa_log_warn("sched_setscheduler(): %s", pa_cstrerror(errno)); - return; + goto fail; } pa_log_info("Successfully enabled SCHED_FIFO scheduling."); @@ -514,6 +534,16 @@ void pa_raise_priority(void) { else pa_log_info("Successfully gained high priority class."); #endif + +fail: + +#if defined(HAVE_SYS_CAPABILITY_H) + if (caps) { + /* Restore original caps */ + cap_set_proc(caps); + cap_free(caps); + } +#endif } /* Reset the priority to normal, inverting the changes made by pa_raise_priority() */ From d949983845cdc514aebe08cf43cfc13c49495ea8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 26 May 2007 23:39:33 +0000 Subject: [PATCH 1353/1514] Add a new meta command ".ifexists" to the CLI language, to execute commands only if a specified file exists. Original patch from cjvdb. Closes #36 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1456 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/cli-command.c | 81 +++++++++++++++++++++++++++++++------ src/pulsecore/cli-command.h | 3 ++ src/pulsecore/pdispatch.c | 2 +- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index e87b257bd..2755c5c9c 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -63,9 +64,18 @@ struct command { unsigned args; }; -#define INCLUDE_META ".include" -#define FAIL_META ".fail" -#define NOFAIL_META ".nofail" +#define META_INCLUDE ".include" +#define META_FAIL ".fail" +#define META_NOFAIL ".nofail" +#define META_IFEXISTS ".ifexists" +#define META_ELSE ".else" +#define META_ENDIF ".endif" + +enum { + IFSTATE_NONE = -1, + IFSTATE_FALSE = 0, + IFSTATE_TRUE = 1, +}; /* Prototypes for all available commands */ static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); @@ -959,7 +969,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G return 0; } -int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int *fail) { +int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, int *fail, int *ifstate) { const char *cs; cs = s+strspn(s, whitespace); @@ -967,19 +977,50 @@ int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int * if (*cs == '#' || !*cs) return 0; else if (*cs == '.') { - if (!strcmp(cs, FAIL_META)) + if (!strcmp(cs, META_ELSE)) { + if (!ifstate || *ifstate == IFSTATE_NONE) { + pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs); + return -1; + } else if (*ifstate == IFSTATE_TRUE) + *ifstate = IFSTATE_FALSE; + else + *ifstate = IFSTATE_TRUE; + return 0; + } else if (!strcmp(cs, META_ENDIF)) { + if (!ifstate || *ifstate == IFSTATE_NONE) { + pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs); + return -1; + } else + *ifstate = IFSTATE_NONE; + return 0; + } + if (ifstate && *ifstate == IFSTATE_FALSE) + return 0; + if (!strcmp(cs, META_FAIL)) *fail = 1; - else if (!strcmp(cs, NOFAIL_META)) + else if (!strcmp(cs, META_NOFAIL)) *fail = 0; else { size_t l; l = strcspn(cs, whitespace); - if (l == sizeof(INCLUDE_META)-1 && !strncmp(cs, INCLUDE_META, l)) { + if (l == sizeof(META_INCLUDE)-1 && !strncmp(cs, META_INCLUDE, l)) { const char *filename = cs+l+strspn(cs+l, whitespace); if (pa_cli_command_execute_file(c, filename, buf, fail) < 0) if (*fail) return -1; + } else if (l == sizeof(META_IFEXISTS)-1 && !strncmp(cs, META_IFEXISTS, l)) { + if (!ifstate) { + pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs); + return -1; + } else if (*ifstate != IFSTATE_NONE) { + pa_strbuf_printf(buf, "Nested %s commands not supported\n", cs); + return -1; + } else { + const char *filename = cs+l+strspn(cs+l, whitespace); + + *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE; + } } else { pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs); if (*fail) return -1; @@ -990,8 +1031,12 @@ int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int * int unknown = 1; size_t l; - l = strcspn(cs, whitespace); + if (ifstate && *ifstate == IFSTATE_FALSE) + return 0; + + l = strcspn(cs, whitespace); + for (command = commands; command->name; command++) if (strlen(command->name) == l && !strncmp(cs, command->name, l)) { int ret; @@ -1017,11 +1062,19 @@ int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int * return 0; } +int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int *fail) { + return pa_cli_command_execute_line_stateful(c, s, buf, fail, NULL); +} + int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int *fail) { char line[256]; FILE *f = NULL; + int ifstate = IFSTATE_NONE; int ret = -1; - assert(c && fn && buf); + + assert(c); + assert(fn); + assert(buf); if (!(f = fopen(fn, "r"))) { pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno)); @@ -1034,7 +1087,7 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int char *e = line + strcspn(line, linebreak); *e = 0; - if (pa_cli_command_execute_line(c, line, buf, fail) < 0 && *fail) + if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail) goto fail; } @@ -1049,14 +1102,18 @@ fail: int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail) { const char *p; - assert(c && s && buf && fail); + int ifstate = IFSTATE_NONE; + + assert(c); + assert(s); + assert(buf); p = s; while (*p) { size_t l = strcspn(p, linebreak); char *line = pa_xstrndup(p, l); - if (pa_cli_command_execute_line(c, line, buf, fail) < 0&& *fail) { + if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail) { pa_xfree(line); return -1; } diff --git a/src/pulsecore/cli-command.h b/src/pulsecore/cli-command.h index 10d50f379..01bca8be4 100644 --- a/src/pulsecore/cli-command.h +++ b/src/pulsecore/cli-command.h @@ -39,4 +39,7 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int /* Split the specified string into lines and run pa_cli_command_execute_line() for each. */ int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail); +/* Same as pa_cli_command_execute_line() but also take ifstate var. */ +int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, int *fail, int *ifstate); + #endif diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 758beaff8..10238acb0 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -258,7 +258,7 @@ void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa struct timeval tv; assert(pd && pd->ref >= 1 && cb); - r = pa_xmalloc(sizeof(struct reply_info)); + r = pa_xnew(struct reply_info, 1); r->pdispatch = pd; r->callback = cb; r->userdata = userdata; From 872018efc855e8ea7f3277d1e08c855c63c96897 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 27 May 2007 16:37:05 +0000 Subject: [PATCH 1354/1514] Minor optimization: read log level character code from array git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1457 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/log.c | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index d8a9efe9e..0033adb91 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -62,6 +62,14 @@ static const int level_to_syslog[] = { }; #endif +static const char level_to_char[] = { + [PA_LOG_ERROR] = 'E', + [PA_LOG_WARN] = 'W', + [PA_LOG_NOTICE] = 'N', + [PA_LOG_INFO] = 'I', + [PA_LOG_DEBUG] = 'D' +}; + void pa_log_set_ident(const char *p) { if (log_ident) pa_xfree(log_ident); @@ -129,7 +137,6 @@ void pa_log_levelv_meta( switch (log_target) { case PA_LOG_STDERR: { const char *prefix = "", *suffix = ""; - const char *level_code = ""; char *local_t; #ifndef OS_IS_WIN32 @@ -145,33 +152,11 @@ void pa_log_levelv_meta( } #endif - switch (level) { - case PA_LOG_ERROR: - level_code = "E"; - break; - case PA_LOG_WARN: - level_code = "W"; - break; - case PA_LOG_NOTICE: - level_code = "N"; - break; - case PA_LOG_INFO: - level_code = "I"; - break; - case PA_LOG_DEBUG: - level_code = "D"; - break; - default: - level_code = "?"; - } - local_t = pa_utf8_to_locale(t); - if (!local_t) { - fprintf(stderr, "%s: %s%s%s%s\n", level_code, location, - prefix, t, suffix); - } else { - fprintf(stderr, "%s: %s%s%s%s\n", level_code, location, - prefix, local_t, suffix); + if (!local_t) + fprintf(stderr, "%c: %s%s%s%s\n", level_to_char[level], location, prefix, t, suffix); + else { + fprintf(stderr, "%c: %s%s%s%s\n", level_to_char[level], location, prefix, local_t, suffix); pa_xfree(local_t); } From 6a2dffd78af88ec3c3089c3a852af6d3a6b499bf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 27 May 2007 16:59:34 +0000 Subject: [PATCH 1355/1514] unfortunately we cannot detect if a foreign thread is still running. Thus sucks. But what can we do? U. Drepper thinks our use case is invalid. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1458 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/thread-posix.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index 7ff5e7c30..b32744261 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -111,17 +111,12 @@ pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { int pa_thread_is_running(pa_thread *t) { assert(t); - - if (!t->thread_func) { - /* Mhmm, this is a foreign thread, t->running is not - * necessarily valid. We misuse pthread_getschedparam() to - * check if the thread is valid. This might not be portable. */ - - int policy; - struct sched_param param; - - return pthread_getschedparam(t->id, &policy, ¶m) >= 0 || errno != ESRCH; - } + + /* Unfortunately there is no way to tell whether a "foreign" + * thread is still running. See + * http://udrepper.livejournal.com/16844.html for more + * information */ + assert(t->thread_func); return pa_atomic_load(&t->running) > 0; } From 918cacb4f4efa80a0bc4b7183da1e9c1cb10ed9c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 27 May 2007 20:38:14 +0000 Subject: [PATCH 1356/1514] Replace AO_xxx usage with pa_atomic_xxx and friends wherever it makes sense git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1459 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/atomic.h | 4 ++ src/pulsecore/cli-command.c | 20 +++++----- src/pulsecore/memblock.c | 66 ++++++++++++++++----------------- src/pulsecore/memblock.h | 25 +++++++------ src/pulsecore/protocol-native.c | 8 ++-- src/tests/memblock-test.c | 28 +++++++------- 6 files changed, 78 insertions(+), 73 deletions(-) diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index 8867f884b..013e8c205 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -53,6 +53,10 @@ static inline int pa_atomic_add(pa_atomic_int_t *a, int i) { return AO_fetch_and_add_full(&a->value, (AO_t) i); } +static inline int pa_atomic_sub(pa_atomic_int_t *a, int i) { + return AO_fetch_and_add_full(&a->value, (AO_t) -i); +} + static inline int pa_atomic_inc(pa_atomic_int_t *a) { return AO_fetch_and_add1_full(&a->value); } diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 2755c5c9c..4dbf3afa6 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -273,20 +273,20 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G stat = pa_mempool_get_stat(c->mempool); pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n", - (unsigned) AO_load_acquire_read((AO_t*) &stat->n_allocated), - pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->allocated_size))); + (unsigned) pa_atomic_load(&stat->n_allocated), + pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->allocated_size))); pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n", - (unsigned) AO_load_acquire_read((AO_t*) &stat->n_accumulated), - pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->accumulated_size))); + (unsigned) pa_atomic_load(&stat->n_accumulated), + pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->accumulated_size))); pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n", - (unsigned) AO_load_acquire_read((AO_t*) &stat->n_imported), - pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->imported_size))); + (unsigned) pa_atomic_load(&stat->n_imported), + pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->imported_size))); pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n", - (unsigned) AO_load_acquire_read((AO_t*) &stat->n_exported), - pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->exported_size))); + (unsigned) pa_atomic_load(&stat->n_exported), + pa_bytes_snprint(s, sizeof(s), (size_t) pa_atomic_load(&stat->exported_size))); pa_strbuf_printf(buf, "Total sample cache size: %s.\n", pa_bytes_snprint(s, sizeof(s), pa_scache_total_size(c))); @@ -305,8 +305,8 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_strbuf_printf(buf, "Memory blocks of type %s: %u allocated/%u accumulated.\n", type_table[k], - (unsigned) AO_load_acquire_read(&stat->n_allocated_by_type[k]), - (unsigned) AO_load_acquire_read(&stat->n_accumulated_by_type[k])); + (unsigned) pa_atomic_load(&stat->n_allocated_by_type[k]), + (unsigned) pa_atomic_load(&stat->n_accumulated_by_type[k])); return 0; } diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 5e7d6e480..6f09a906a 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -114,40 +114,40 @@ static void stat_add(pa_memblock*b) { assert(b); assert(b->pool); - AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated); - AO_fetch_and_add_release_write(&b->pool->stat.allocated_size, (AO_t) b->length); + pa_atomic_inc(&b->pool->stat.n_allocated); + pa_atomic_add(&b->pool->stat.allocated_size, b->length); - AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated); - AO_fetch_and_add_release_write(&b->pool->stat.accumulated_size, (AO_t) b->length); + pa_atomic_inc(&b->pool->stat.n_accumulated); + pa_atomic_add(&b->pool->stat.accumulated_size, b->length); if (b->type == PA_MEMBLOCK_IMPORTED) { - AO_fetch_and_add1_release_write(&b->pool->stat.n_imported); - AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) b->length); + pa_atomic_inc(&b->pool->stat.n_imported); + pa_atomic_add(&b->pool->stat.imported_size, b->length); } - AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); - AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated_by_type[b->type]); + pa_atomic_inc(&b->pool->stat.n_allocated_by_type[b->type]); + pa_atomic_inc(&b->pool->stat.n_accumulated_by_type[b->type]); } static void stat_remove(pa_memblock *b) { assert(b); assert(b->pool); - assert(AO_load_acquire_read(&b->pool->stat.n_allocated) > 0); - assert(AO_load_acquire_read(&b->pool->stat.allocated_size) >= (AO_t) b->length); + assert(pa_atomic_load(&b->pool->stat.n_allocated) > 0); + assert(pa_atomic_load(&b->pool->stat.allocated_size) >= (int) b->length); - AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated); - AO_fetch_and_add_release_write(&b->pool->stat.allocated_size, (AO_t) (-b->length)); + pa_atomic_dec(&b->pool->stat.n_allocated); + pa_atomic_sub(&b->pool->stat.allocated_size, b->length); if (b->type == PA_MEMBLOCK_IMPORTED) { - assert(AO_load_acquire_read(&b->pool->stat.n_imported) > 0); - assert(AO_load_acquire_read(&b->pool->stat.imported_size) >= (AO_t) b->length); + assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); + assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); - AO_fetch_and_sub1_release_write(&b->pool->stat.n_imported); - AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) (-b->length)); + pa_atomic_dec(&b->pool->stat.n_imported); + pa_atomic_sub(&b->pool->stat.imported_size, b->length); } - AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); + pa_atomic_dec(&b->pool->stat.n_allocated_by_type[b->type]); } static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length); @@ -193,7 +193,7 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * p->n_init++)); else { pa_log_debug("Pool full"); - AO_fetch_and_add1_release_write(&p->stat.n_pool_full); + pa_atomic_inc(&p->stat.n_pool_full); return NULL; } @@ -249,7 +249,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { b->data = mempool_slot_data(slot); } else { pa_log_debug("Memory block too large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot)); - AO_fetch_and_add1_release_write(&p->stat.n_too_large_for_pool); + pa_atomic_inc(&p->stat.n_too_large_for_pool); return NULL; } @@ -372,7 +372,7 @@ void pa_memblock_unref(pa_memblock*b) { static void memblock_make_local(pa_memblock *b) { assert(b); - AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); + pa_atomic_dec(&b->pool->stat.n_allocated_by_type[b->type]); if (b->length <= b->pool->block_size - sizeof(struct mempool_slot)) { struct mempool_slot *slot; @@ -398,8 +398,8 @@ static void memblock_make_local(pa_memblock *b) { b->data = pa_xmemdup(b->data, b->length); finish: - AO_fetch_and_add1_release_write(&b->pool->stat.n_allocated_by_type[b->type]); - AO_fetch_and_add1_release_write(&b->pool->stat.n_accumulated_by_type[b->type]); + pa_atomic_inc(&b->pool->stat.n_allocated_by_type[b->type]); + pa_atomic_inc(&b->pool->stat.n_accumulated_by_type[b->type]); } void pa_memblock_unref_fixed(pa_memblock *b) { @@ -419,10 +419,10 @@ static void memblock_replace_import(pa_memblock *b) { assert(b); assert(b->type == PA_MEMBLOCK_IMPORTED); - assert(AO_load_acquire_read(&b->pool->stat.n_imported) > 0); - assert(AO_load_acquire_read(&b->pool->stat.imported_size) >= (AO_t) b->length); - AO_fetch_and_sub1_release_write(&b->pool->stat.n_imported); - AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) - b->length); + assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); + assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); + pa_atomic_dec(&b->pool->stat.n_imported); + pa_atomic_sub(&b->pool->stat.imported_size, b->length); seg = b->per_type.imported.segment; assert(seg); @@ -486,7 +486,7 @@ void pa_mempool_free(pa_mempool *p) { while (p->exports) pa_memexport_free(p->exports); - if (AO_load_acquire_read(&p->stat.n_allocated) > 0) + if (pa_atomic_load(&p->stat.n_allocated) > 0) pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!"); pa_shm_free(&p->memory); @@ -684,11 +684,11 @@ int pa_memexport_process_release(pa_memexport *e, uint32_t id) { /* pa_log("Processing release for %u", id); */ - assert(AO_load_acquire_read(&e->pool->stat.n_exported) > 0); - assert(AO_load_acquire_read(&e->pool->stat.exported_size) >= (AO_t) e->slots[id].block->length); + assert(pa_atomic_load(&e->pool->stat.n_exported) > 0); + assert(pa_atomic_load(&e->pool->stat.exported_size) >= (int) e->slots[id].block->length); - AO_fetch_and_sub1_release_write(&e->pool->stat.n_exported); - AO_fetch_and_add_release_write(&e->pool->stat.exported_size, (AO_t) -e->slots[id].block->length); + pa_atomic_dec(&e->pool->stat.n_exported); + pa_atomic_sub(&e->pool->stat.exported_size, e->slots[id].block->length); pa_memblock_unref(e->slots[id].block); e->slots[id].block = NULL; @@ -785,8 +785,8 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 *offset = (uint8_t*) b->data - (uint8_t*) memory->ptr; *size = b->length; - AO_fetch_and_add1_release_write(&e->pool->stat.n_exported); - AO_fetch_and_add_release_write(&e->pool->stat.exported_size, (AO_t) b->length); + pa_atomic_inc(&e->pool->stat.n_exported); + pa_atomic_add(&e->pool->stat.exported_size, b->length); return 0; } diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index 3eace92c7..fe4773d44 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -30,6 +30,7 @@ #include #include +#include /* A pa_memblock is a reference counted memory block. PulseAudio * passed references to pa_memblocks around instead of copying @@ -82,20 +83,20 @@ struct pa_memblock { * n_accumulated is not yet. Take these values with a grain of salt, * threy are here for purely statistical reasons.*/ struct pa_mempool_stat { - AO_t n_allocated; - AO_t n_accumulated; - AO_t n_imported; - AO_t n_exported; - AO_t allocated_size; - AO_t accumulated_size; - AO_t imported_size; - AO_t exported_size; + pa_atomic_int_t n_allocated; + pa_atomic_int_t n_accumulated; + pa_atomic_int_t n_imported; + pa_atomic_int_t n_exported; + pa_atomic_int_t allocated_size; + pa_atomic_int_t accumulated_size; + pa_atomic_int_t imported_size; + pa_atomic_int_t exported_size; - AO_t n_too_large_for_pool; - AO_t n_pool_full; + pa_atomic_int_t n_too_large_for_pool; + pa_atomic_int_t n_pool_full; - AO_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; - AO_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; + pa_atomic_int_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; + pa_atomic_int_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; }; /* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL or PA_MEMBLOCK_APPENDED, depending on the size */ diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 774f69188..dbdb7dd47 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1116,10 +1116,10 @@ static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t stat = pa_mempool_get_stat(c->protocol->core->mempool); reply = reply_new(tag); - pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->n_allocated)); - pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->allocated_size)); - pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->n_accumulated)); - pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->accumulated_size)); + pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_allocated)); + pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size)); + pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated)); + pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size)); pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core)); pa_pstream_send_tagstruct(c->pstream, reply); } diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c index 13bfdf0d4..8d25ba38f 100644 --- a/src/tests/memblock-test.c +++ b/src/tests/memblock-test.c @@ -46,24 +46,24 @@ static void print_stats(pa_mempool *p, const char *text) { "n_accumulated = %u\n" "n_imported = %u\n" "n_exported = %u\n" - "allocated_size = %lu\n" - "accumulated_size = %lu\n" - "imported_size = %lu\n" - "exported_size = %lu\n" + "allocated_size = %u\n" + "accumulated_size = %u\n" + "imported_size = %u\n" + "exported_size = %u\n" "n_too_large_for_pool = %u\n" "n_pool_full = %u\n" "}\n", text, - (unsigned) AO_load_acquire_read((AO_t*) &s->n_allocated), - (unsigned) AO_load_acquire_read((AO_t*) &s->n_accumulated), - (unsigned) AO_load_acquire_read((AO_t*) &s->n_imported), - (unsigned) AO_load_acquire_read((AO_t*) &s->n_exported), - (unsigned long) AO_load_acquire_read((AO_t*) &s->allocated_size), - (unsigned long) AO_load_acquire_read((AO_t*) &s->accumulated_size), - (unsigned long) AO_load_acquire_read((AO_t*) &s->imported_size), - (unsigned long) AO_load_acquire_read((AO_t*) &s->exported_size), - (unsigned) AO_load_acquire_read((AO_t*) &s->n_too_large_for_pool), - (unsigned) AO_load_acquire_read((AO_t*) &s->n_pool_full)); + (unsigned) pa_atomic_load(&s->n_allocated), + (unsigned) pa_atomic_load(&s->n_accumulated), + (unsigned) pa_atomic_load(&s->n_imported), + (unsigned) pa_atomic_load(&s->n_exported), + (unsigned) pa_atomic_load(&s->allocated_size), + (unsigned) pa_atomic_load(&s->accumulated_size), + (unsigned) pa_atomic_load(&s->imported_size), + (unsigned) pa_atomic_load(&s->exported_size), + (unsigned) pa_atomic_load(&s->n_too_large_for_pool), + (unsigned) pa_atomic_load(&s->n_pool_full)); } int main(int argc, char *argv[]) { From 707def14fc4cebc3b2407768c7ac03019a39c87f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 27 May 2007 20:58:29 +0000 Subject: [PATCH 1357/1514] Bump revision of libs and package git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1460 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 65a99a00d..9a1e6c513 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,7 @@ AC_PREREQ(2.57) m4_define(PA_MAJOR, [0]) m4_define(PA_MINOR, [9]) -m4_define(PA_MICRO, [5]) +m4_define(PA_MICRO, [6]) AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) @@ -39,8 +39,8 @@ AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/]) AC_SUBST(PA_API_VERSION, 10) AC_SUBST(PA_PROTOCOL_VERSION, 10) -AC_SUBST(LIBPULSE_VERSION_INFO, [1:0:1]) -AC_SUBST(LIBPULSECORE_VERSION_INFO, [2:0:0]) +AC_SUBST(LIBPULSE_VERSION_INFO, [2:0:2]) +AC_SUBST(LIBPULSECORE_VERSION_INFO, [3:0:0]) AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:0:0]) AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:0:1]) AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:2:0]) From 67cb77575f98a78b7365a972b08fb2013782eda3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 28 May 2007 15:52:13 +0000 Subject: [PATCH 1358/1514] build fix for systems lacking capability suppoort. (Problem identified and original patch supplied by Diego Petteno git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1462 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-util.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 480ac3b71..5159934d8 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -544,6 +544,10 @@ fail: cap_free(caps); } #endif + + ; /* We put this here to get the code to compile when + * HAVE_SYS_CAPABILITY_H is not defined. Don't remove unless you + * know what you do */ } /* Reset the priority to normal, inverting the changes made by pa_raise_priority() */ From 5530d3295a3e65905346e98314f884a09a2be325 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 29 May 2007 07:47:02 +0000 Subject: [PATCH 1359/1514] We now use gid unconditionally, so make sure it's defined. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1463 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 72e47975e..91cc3a2f9 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -320,9 +320,7 @@ int main(int argc, char *argv[]) { int suid_root, real_root; int valid_pid_file = 0; -#ifdef HAVE_GETUID gid_t gid = (gid_t) -1; -#endif #ifdef OS_IS_WIN32 pa_time_event *timer; From e4d63d0d8026446aec99ef8390554c5afd87cef4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 May 2007 17:16:24 +0000 Subject: [PATCH 1360/1514] add target "eolspace" to makefil to remove trailing newlines from all source files git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1464 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.am b/Makefile.am index 1b77187de..abc3d7760 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,4 +45,7 @@ homepage: all dist doxygen doxygen: $(MAKE) -C doxygen doxygen +eolspace: + find \( -name '*.c' -o -name '*.h' -o -name 'Makefile.am' \) -exec perl -i -pe 's/\s+\n$$/\1\n/;' \{\} \; + .PHONY: homepage distcleancheck doxygen From 1e12e0ee8dfdda1632b9c082aba6fc1956813a5b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 May 2007 17:24:48 +0000 Subject: [PATCH 1361/1514] Kill spaces on EOL git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1465 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 30 +- src/daemon/caps.c | 8 +- src/modules/gconf/gconf-helper.c | 30 +- src/modules/gconf/module-gconf.c | 62 +- src/modules/module-hal-detect.c | 10 +- src/modules/module-oss.c | 10 +- src/modules/rtp/module-rtp-recv.c | 64 +- src/modules/rtp/module-rtp-send.c | 36 +- src/modules/rtp/rtp.c | 34 +- src/modules/rtp/rtp.h | 6 +- src/modules/rtp/sap.c | 28 +- src/modules/rtp/sap.h | 6 +- src/modules/rtp/sdp.c | 30 +- src/modules/rtp/sdp.h | 6 +- src/pulsecore/cli-command.c | 8 +- src/pulsecore/core-util.c | 4 +- src/pulsecore/g711.c | 5062 ++++++++++++++--------------- src/pulsecore/protocol-native.c | 2 +- src/pulsecore/sample-util.c | 2 +- src/pulsecore/thread-posix.c | 2 +- src/utils/padsp.c | 2 +- 21 files changed, 2721 insertions(+), 2721 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index e05b53641..d90361f33 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -126,7 +126,7 @@ pulseaudio_SOURCES = \ pulsecore/gccmacro.h pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) -pulseaudio_CPPFLAGS = $(AM_CPPFLAGS) +pulseaudio_CPPFLAGS = $(AM_CPPFLAGS) pulseaudio_LDADD = $(AM_LDADD) libpulsecore.la $(LIBLTDL) \ $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) # This is needed because automake doesn't properly expand the foreach below @@ -168,8 +168,8 @@ endif bin_SCRIPTS = esdcompat pacat_SOURCES = utils/pacat.c -pacat_LDADD = $(AM_LDADD) libpulse.la -pacat_CFLAGS = $(AM_CFLAGS) +pacat_LDADD = $(AM_LDADD) libpulse.la +pacat_CFLAGS = $(AM_CFLAGS) pacat_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) paplay_SOURCES = utils/paplay.c @@ -247,7 +247,7 @@ utf8_test_CFLAGS = $(AM_CFLAGS) utf8_test_LDADD = $(AM_LDADD) libpulsecore.la utf8_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -get_binary_name_test_SOURCES = tests/get-binary-name-test.c +get_binary_name_test_SOURCES = tests/get-binary-name-test.c get_binary_name_test_CFLAGS = $(AM_CFLAGS) get_binary_name_test_LDADD = $(AM_LDADD) libpulse.la get_binary_name_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -264,22 +264,22 @@ hook_list_test_CFLAGS = $(AM_CFLAGS) hook_list_test_LDADD = $(AM_LDADD) libpulsecore.la hook_list_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -memblock_test_SOURCES = tests/memblock-test.c +memblock_test_SOURCES = tests/memblock-test.c memblock_test_CFLAGS = $(AM_CFLAGS) memblock_test_LDADD = $(AM_LDADD) libpulsecore.la -memblock_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +memblock_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) thread_test_SOURCES = tests/thread-test.c thread_test_CFLAGS = $(AM_CFLAGS) thread_test_LDADD = $(AM_LDADD) libpulsecore.la -thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) flist_test_SOURCES = tests/flist-test.c \ pulsecore/atomic.h \ pulsecore/flist.c pulsecore/flist.h flist_test_CFLAGS = $(AM_CFLAGS) flist_test_LDADD = $(AM_LDADD) libpulsecore.la -flist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +flist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) @@ -333,12 +333,12 @@ memblockq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) sync_playback_SOURCES = tests/sync-playback.c sync_playback_LDADD = $(AM_LDADD) libpulse.la -sync_playback_CFLAGS = $(AM_CFLAGS) +sync_playback_CFLAGS = $(AM_CFLAGS) sync_playback_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) interpol_test_SOURCES = tests/interpol-test.c interpol_test_LDADD = $(AM_LDADD) libpulse.la -interpol_test_CFLAGS = $(AM_CFLAGS) +interpol_test_CFLAGS = $(AM_CFLAGS) interpol_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) ################################### @@ -459,7 +459,7 @@ libpulse_la_SOURCES += \ if OS_IS_WIN32 libpulse_la_SOURCES += \ - pulsecore/dllmain.c + pulsecore/dllmain.c endif if HAVE_X11 @@ -482,7 +482,7 @@ libpulse_la_CFLAGS += $(LIBASYNCNS_CFLAGS) libpulse_la_LIBADD += $(LIBASYNCNS_LIBS) endif -libpulse_simple_la_SOURCES = pulse/simple.c pulse/simple.h +libpulse_simple_la_SOURCES = pulse/simple.c pulse/simple.h libpulse_simple_la_CFLAGS = $(AM_CFLAGS) libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la libpulse_simple_la_LDFLAGS = -version-info $(LIBPULSE_SIMPLE_VERSION_INFO) @@ -640,7 +640,7 @@ libpulsecore_la_SOURCES += \ if OS_IS_WIN32 libpulsecore_la_SOURCES += \ - pulsecore/dllmain.c + pulsecore/dllmain.c endif libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) @@ -820,7 +820,7 @@ libsocket_util_la_SOURCES = \ libsocket_util_la_LDFLAGS = -avoid-version libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) libpulsecore.la -librtp_la_SOURCES = modules/rtp/rtp.c modules/rtp/rtp.h modules/rtp/sdp.c modules/rtp/sdp.h modules/rtp/sap.c modules/rtp/sap.h +librtp_la_SOURCES = modules/rtp/rtp.c modules/rtp/rtp.h modules/rtp/sdp.c modules/rtp/sdp.h modules/rtp/sap.c modules/rtp/sap.h librtp_la_LDFLAGS = -avoid-version librtp_la_LIBADD = $(AM_LIBADD) libpulsecore.la @@ -1298,7 +1298,7 @@ esdcompat: daemon/esdcompat.in Makefile client.conf: pulse/client.conf.in Makefile sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' < $< > $@ -if OS_IS_WIN32 +if OS_IS_WIN32 default.pa: daemon/default.pa.win32 cp $< $@ else diff --git a/src/daemon/caps.c b/src/daemon/caps.c index 8043230c7..f92db7439 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -97,9 +97,9 @@ int pa_limit_caps(void) { if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) goto fail; - + pa_log_info("dropped capabilities successfully."); - + r = 1; fail: @@ -119,12 +119,12 @@ int pa_drop_caps(void) { cap_clear(caps); prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0); - + if (cap_set_proc(caps) < 0) { pa_log("failed to drop capabilities: %s", pa_cstrerror(errno)); goto fail; } - + r = 0; fail: diff --git a/src/modules/gconf/gconf-helper.c b/src/modules/gconf/gconf-helper.c index 5f6def4d8..3483b8451 100644 --- a/src/modules/gconf/gconf-helper.c +++ b/src/modules/gconf/gconf-helper.c @@ -4,17 +4,17 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -48,30 +48,30 @@ static void handle_module(GConfClient *client, const char *name) { snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/enabled", name); enabled = gconf_client_get_bool(client, p, FALSE); - + printf("%c%s%c", enabled ? '+' : '-', name, 0); if (enabled) { - + for (i = 0; i < 10; i++) { gchar *n, *a; - + snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/name%i", name, i); if (!(n = gconf_client_get_string(client, p, NULL)) || !*n) break; - + snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/args%i", name, i); a = gconf_client_get_string(client, p, NULL); - + printf("%s%c%s%c", n, 0, a ? a : "", 0); - + g_free(n); g_free(a); } - + printf("%c", 0); } - + fflush(stdout); } @@ -83,7 +83,7 @@ static void modules_callback( const char *n; char buf[128]; - + g_assert(strncmp(entry->key, PA_GCONF_PATH_MODULES"/", sizeof(PA_GCONF_PATH_MODULES)) == 0); n = entry->key + sizeof(PA_GCONF_PATH_MODULES); @@ -113,17 +113,17 @@ int main(int argc, char *argv[]) { char *e = strrchr(m->data, '/'); handle_module(client, e ? e+1 : m->data); } - + g_slist_free(modules); /* Signal the parent that we are now initialized */ printf("!"); fflush(stdout); - + g = g_main_loop_new(NULL, FALSE); g_main_loop_run(g); g_main_loop_unref(g); - + g_object_unref(G_OBJECT(client)); return 0; diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index df7b16439..cbe17d200 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -4,17 +4,17 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -80,7 +80,7 @@ struct module_info { struct userdata { pa_core *core; pa_module *module; - + pa_hashmap *module_infos; pid_t pid; @@ -129,7 +129,7 @@ static char *read_string(struct userdata *u) { for (;;) { char *e; - + if ((e = memchr(u->buf, 0, u->buf_fill))) { char *ret = pa_xstrdup(u->buf); u->buf_fill -= e - u->buf +1; @@ -149,7 +149,7 @@ static void unload_one_module(struct userdata *u, struct module_info*m, unsigned if (m->items[i].index == PA_INVALID_INDEX) return; - + pa_log_debug("Unloading module #%i", m->items[i].index); pa_module_unload_by_index(u->core, m->items[i].index); m->items[i].index = PA_INVALID_INDEX; @@ -160,7 +160,7 @@ static void unload_one_module(struct userdata *u, struct module_info*m, unsigned static void unload_all_modules(struct userdata *u, struct module_info*m) { unsigned i; - + assert(u); assert(m); @@ -179,7 +179,7 @@ static void load_module( int is_new) { pa_module *mod; - + assert(u); assert(m); assert(name); @@ -193,18 +193,18 @@ static void load_module( unload_one_module(u, m, i); } - + pa_log_debug("Loading module '%s' with args '%s' due to GConf configuration.", name, args); m->items[i].name = pa_xstrdup(name); m->items[i].args = pa_xstrdup(args); m->items[i].index = PA_INVALID_INDEX; - + if (!(mod = pa_module_load(u->core, name, args))) { pa_log("pa_module_load() failed"); return; } - + m->items[i].index = mod->index; } @@ -227,18 +227,18 @@ static int handle_event(struct userdata *u) { do { if ((opcode = read_byte(u)) < 0) goto fail; - + switch (opcode) { case '!': /* The helper tool is now initialized */ ret = 1; break; - + case '+': { char *name; struct module_info *m; unsigned i, j; - + if (!(name = read_string(u))) goto fail; @@ -282,16 +282,16 @@ static int handle_event(struct userdata *u) { /* Unload all removed modules */ for (j = i; j < m->n_items; j++) unload_one_module(u, m, j); - + m->n_items = i; - + break; } - + case '-': { char *name; struct module_info *m; - + if (!(name = read_string(u))) goto fail; @@ -301,7 +301,7 @@ static int handle_event(struct userdata *u) { } pa_xfree(name); - + break; } } @@ -324,12 +324,12 @@ static void io_event_cb( struct userdata *u = userdata; if (handle_event(u) < 0) { - + if (u->io_event) { u->core->mainloop->io_free(u->io_event); u->io_event = NULL; } - + pa_module_unload_request(u->module); } } @@ -342,7 +342,7 @@ static int start_client(const char *n, pid_t *pid) { pa_log("pipe() failed: %s", pa_cstrerror(errno)); goto fail; } - + if ((child = fork()) == (pid_t) -1) { pa_log("fork() failed: %s", pa_cstrerror(errno)); goto fail; @@ -357,7 +357,7 @@ static int start_client(const char *n, pid_t *pid) { return pipe_fds[0]; } else { int max_fd, i; - + /* child */ close(pipe_fds[0]); @@ -373,7 +373,7 @@ static int start_client(const char *n, pid_t *pid) { open("/dev/null", O_WRONLY); max_fd = 1024; - + #ifdef HAVE_SYS_RESOURCE_H { struct rlimit r; @@ -381,7 +381,7 @@ static int start_client(const char *n, pid_t *pid) { max_fd = r.rlim_max; } #endif - + for (i = 3; i < max_fd; i++) close(i); @@ -402,14 +402,14 @@ static int start_client(const char *n, pid_t *pid) { execl(n, n, NULL); _exit(1); } - + fail: if (pipe_fds[0] >= 0) close(pipe_fds[0]); if (pipe_fds[1] >= 0) close(pipe_fds[1]); - + return -1; } @@ -427,17 +427,17 @@ int pa__init(pa_core *c, pa_module*m) { u->fd_type = 0; u->io_event = NULL; u->buf_fill = 0; - + if ((u->fd = start_client(PA_GCONF_HELPER, &u->pid)) < 0) goto fail; - + u->io_event = c->mainloop->io_new( c->mainloop, u->fd, PA_IO_EVENT_INPUT, io_event_cb, u); - + do { if ((r = handle_event(u)) < 0) goto fail; @@ -445,7 +445,7 @@ int pa__init(pa_core *c, pa_module*m) { /* Read until the client signalled us that it is ready with * initialization */ } while (r != 1); - + return 0; fail: diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 27cd449ec..1f48a452e 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -87,7 +87,7 @@ struct userdata { pa_hashmap *devices; #if defined(HAVE_ALSA) && defined(HAVE_OSS) int use_oss; -#endif +#endif }; struct timerdata { @@ -269,7 +269,7 @@ static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, case CAP_OSS: #ifdef HAVE_ALSA if (u->use_oss) -#endif +#endif m = hal_device_load_oss(u, udi, error); break; #endif @@ -533,9 +533,9 @@ int pa__init(pa_core *c, pa_module*m) { #endif #if defined(HAVE_ALSA) && defined(HAVE_OSS) u->use_oss = 0; - + if (n <= 0) { -#endif +#endif #ifdef HAVE_OSS n += hal_device_add_all(u, CAP_OSS); #endif @@ -546,7 +546,7 @@ int pa__init(pa_core *c, pa_module*m) { if (n > 0) u->use_oss = 1; } -#endif +#endif libhal_ctx_set_user_data(hal_ctx, u); libhal_ctx_set_device_added(hal_ctx, device_added_cb); diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 22b12ef74..9d4d0eac1 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -172,11 +172,11 @@ static void do_write(struct userdata *u) { if (errno != EAGAIN) { pa_log("write() failed: %s", pa_cstrerror(errno)); - + clear_up(u); pa_module_unload_request(u->module); } - + break; } @@ -228,14 +228,14 @@ static void do_read(struct userdata *u) { assert(memchunk.memblock); if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { pa_memblock_unref(memchunk.memblock); - + if (errno != EAGAIN) { pa_log("read() failed: %s", pa_cstrerror(errno)); - + clear_up(u); pa_module_unload_request(u->module); } - + break; } diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index db83756ad..62ef561f1 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -3,17 +3,17 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -145,7 +145,7 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event pa_memchunk chunk; int64_t k, j, delta; struct timeval tv; - + assert(m); assert(e); assert(s); @@ -159,7 +159,7 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event pa_memblock_unref(chunk.memblock); return; } - + if (!s->first_packet) { s->first_packet = 1; @@ -183,7 +183,7 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event delta = k; else delta = j; - + pa_memblockq_seek(s->memblockq, delta * s->rtp_context.frame_size, PA_SEEK_RELATIVE); if (pa_memblockq_push(s->memblockq, &chunk) < 0) { @@ -191,10 +191,10 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event pa_memblockq_flush(s->memblockq); pa_memblockq_push(s->memblockq, &chunk); } - + /* The next timestamp we expect */ s->offset = s->rtp_context.timestamp + (chunk.length / s->rtp_context.frame_size); - + pa_memblock_unref(chunk.memblock); /* Reset death timer */ @@ -205,7 +205,7 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event static void death_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct timeval *tv, void *userdata) { struct session *s = userdata; - + assert(m); assert(t); assert(tv); @@ -216,7 +216,7 @@ static void death_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct ti static int mcast_socket(const struct sockaddr* sa, socklen_t salen) { int af, fd = -1, r, one; - + af = sa->sa_family; if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) { pa_log("Failed to create socket: %s", pa_cstrerror(errno)); @@ -228,7 +228,7 @@ static int mcast_socket(const struct sockaddr* sa, socklen_t salen) { pa_log("SO_REUSEADDR failed: %s", pa_cstrerror(errno)); goto fail; } - + if (af == AF_INET) { struct ip_mreq mr4; memset(&mr4, 0, sizeof(mr4)); @@ -245,14 +245,14 @@ static int mcast_socket(const struct sockaddr* sa, socklen_t salen) { pa_log_info("Joining mcast group failed: %s", pa_cstrerror(errno)); goto fail; } - + if (bind(fd, sa, salen) < 0) { pa_log("bind() failed: %s", pa_cstrerror(errno)); goto fail; } return fd; - + fail: if (fd >= 0) close(fd); @@ -273,7 +273,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_log("session limit reached."); goto fail; } - + if (!(sink = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { pa_log("sink does not exist."); goto fail; @@ -289,7 +289,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in c = pa_sprintf_malloc("RTP Stream%s%s%s", sdp_info->session_name ? " (" : "", - sdp_info->session_name ? sdp_info->session_name : "", + sdp_info->session_name ? sdp_info->session_name : "", sdp_info->session_name ? ")" : ""); pa_sink_input_new_data_init(&data); @@ -298,10 +298,10 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in data.name = c; data.module = u->module; pa_sink_input_new_data_set_sample_spec(&data, &sdp_info->sample_spec); - + s->sink_input = pa_sink_input_new(u->core, &data, 0); pa_xfree(c); - + if (!s->sink_input) { pa_log("failed to create sink input."); goto fail; @@ -318,7 +318,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in &s->sink_input->sample_spec, (pa_bytes_per_second(&s->sink_input->sample_spec)/128/pa_frame_size(&s->sink_input->sample_spec))* pa_frame_size(&s->sink_input->sample_spec)); - + s->memblockq = pa_memblockq_new( 0, MEMBLOCKQ_MAXLENGTH, @@ -331,7 +331,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_memblock_unref(silence); s->rtp_event = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, rtp_event_cb, s); - + pa_gettimeofday(&tv); pa_timeval_add(&tv, DEATH_TIMEOUT); s->death_event = u->core->mainloop->time_new(u->core->mainloop, &tv, death_event_cb, s); @@ -343,14 +343,14 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_log_info("Found new session '%s'", s->sdp_info.session_name); u->n_sessions++; - + return s; fail: if (s) { if (fd >= 0) close(fd); - + pa_xfree(s); } @@ -377,7 +377,7 @@ static void session_free(struct session *s, int from_hash) { assert(s->userdata->n_sessions >= 1); s->userdata->n_sessions--; - + pa_xfree(s); } @@ -386,7 +386,7 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event int goodbye; pa_sdp_info info; struct session *s; - + assert(m); assert(e); assert(u); @@ -410,14 +410,14 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event if (!(s = pa_hashmap_get(u->by_origin, info.origin))) { if (!(s = session_new(u, &info))) pa_sdp_info_destroy(&info); - + } else { struct timeval tv; - + pa_gettimeofday(&tv); pa_timeval_add(&tv, DEATH_TIMEOUT); m->time_restart(s->death_event, &tv); - + pa_sdp_info_destroy(&info); } } @@ -432,7 +432,7 @@ int pa__init(pa_core *c, pa_module*m) { socklen_t salen; const char *sap_address; int fd = -1; - + assert(c); assert(m); @@ -442,7 +442,7 @@ int pa__init(pa_core *c, pa_module*m) { } sap_address = pa_modargs_get_value(ma, "sap_address", DEFAULT_SAP_ADDRESS); - + if (inet_pton(AF_INET6, sap_address, &sa6.sin6_addr) > 0) { sa6.sin6_family = AF_INET6; sa6.sin6_port = htons(SAP_PORT); @@ -471,9 +471,9 @@ int pa__init(pa_core *c, pa_module*m) { u->sap_event = c->mainloop->io_new(c->mainloop, fd, PA_IO_EVENT_INPUT, sap_event_cb, u); u->by_origin = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - + pa_sap_context_init_recv(&u->sap_context, fd); - + pa_modargs_free(ma); return 0; @@ -484,7 +484,7 @@ fail: if (fd >= 0) close(fd); - + return -1; } @@ -504,7 +504,7 @@ void pa__done(pa_core *c, pa_module*m) { pa_sap_context_destroy(&u->sap_context); pa_hashmap_free(u->by_origin, free_func, NULL); - + pa_xfree(u->sink_name); pa_xfree(u); } diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 18e5e055a..8c9e5f23c 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -4,17 +4,17 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -111,7 +111,7 @@ static void source_output_push(pa_source_output *o, const pa_memchunk *chunk) { pa_log("Failed to push chunk into memblockq."); return; } - + pa_rtp_send(&u->rtp_context, u->mtu, u->memblockq); } @@ -138,7 +138,7 @@ static pa_usec_t source_output_get_latency (pa_source_output *o) { static void sap_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct timeval *tv, void *userdata) { struct userdata *u = userdata; struct timeval next; - + assert(m); assert(t); assert(tv); @@ -172,7 +172,7 @@ int pa__init(pa_core *c, pa_module*m) { char hn[128], *n; int loop = 0; pa_source_output_new_data data; - + assert(c); assert(m); @@ -210,7 +210,7 @@ int pa__init(pa_core *c, pa_module*m) { payload = pa_rtp_payload_from_sample_spec(&ss); mtu = (DEFAULT_MTU/pa_frame_size(&ss))*pa_frame_size(&ss); - + if (pa_modargs_get_value_u32(ma, "mtu", &mtu) < 0 || mtu < 1 || mtu % pa_frame_size(&ss) != 0) { pa_log("invalid mtu."); goto fail; @@ -241,7 +241,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("invalid destination '%s'", dest); goto fail; } - + if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) { pa_log("socket() failed: %s", pa_cstrerror(errno)); goto fail; @@ -275,7 +275,7 @@ int pa__init(pa_core *c, pa_module*m) { data.source = s; pa_source_output_new_data_set_sample_spec(&data, &ss); pa_source_output_new_data_set_channel_map(&data, &cm); - + if (!(o = pa_source_output_new(c, &data, 0))) { pa_log("failed to create source output."); goto fail; @@ -284,7 +284,7 @@ int pa__init(pa_core *c, pa_module*m) { o->push = source_output_push; o->kill = source_output_kill; o->get_latency = source_output_get_latency; - + u = pa_xnew(struct userdata, 1); m->userdata = u; o->userdata = u; @@ -292,7 +292,7 @@ int pa__init(pa_core *c, pa_module*m) { u->module = m; u->core = c; u->source_output = o; - + u->memblockq = pa_memblockq_new( 0, MEMBLOCKQ_MAXLENGTH, @@ -303,20 +303,20 @@ int pa__init(pa_core *c, pa_module*m) { NULL); u->mtu = mtu; - + k = sizeof(sa_dst); r = getsockname(fd, (struct sockaddr*) &sa_dst, &k); assert(r >= 0); n = pa_sprintf_malloc("PulseAudio RTP Stream on %s", pa_get_fqdn(hn, sizeof(hn))); - + p = pa_sdp_build(af, af == AF_INET ? (void*) &((struct sockaddr_in*) &sa_dst)->sin_addr : (void*) &((struct sockaddr_in6*) &sa_dst)->sin6_addr, af == AF_INET ? (void*) &sa4.sin_addr : (void*) &sa6.sin6_addr, n, port, payload, &ss); pa_xfree(n); - + pa_rtp_context_init_send(&u->rtp_context, fd, c->cookie, payload, pa_frame_size(&ss)); pa_sap_context_init_send(&u->sap_context, sap_fd, p); @@ -339,7 +339,7 @@ fail: if (fd >= 0) close(fd); - + if (sap_fd >= 0) close(sap_fd); @@ -347,7 +347,7 @@ fail: pa_source_output_disconnect(o); pa_source_output_unref(o); } - + return -1; } @@ -360,7 +360,7 @@ void pa__done(pa_core *c, pa_module*m) { return; c->mainloop->time_free(u->sap_event); - + if (u->source_output) { pa_source_output_disconnect(u->source_output); pa_source_output_unref(u->source_output); @@ -372,6 +372,6 @@ void pa__done(pa_core *c, pa_module*m) { pa_sap_context_destroy(&u->sap_context); pa_memblockq_free(u->memblockq); - + pa_xfree(u); } diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index bc5260a89..03a01412d 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -4,17 +4,17 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -53,7 +53,7 @@ pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssr c->ssrc = ssrc ? ssrc : (uint32_t) (rand()*rand()); c->payload = payload & 127; c->frame_size = frame_size; - + return c; } @@ -64,14 +64,14 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { pa_memblock* mb[MAX_IOVECS]; int iov_idx = 1; size_t n = 0, skip = 0; - + assert(c); assert(size > 0); assert(q); if (pa_memblockq_get_length(q) < size) return 0; - + for (;;) { int r; pa_memchunk chunk; @@ -105,7 +105,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { iov[0].iov_base = (void*)header; iov[0].iov_len = sizeof(header); - + m.msg_name = NULL; m.msg_namelen = 0; m.msg_iov = iov; @@ -113,7 +113,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { m.msg_control = NULL; m.msg_controllen = 0; m.msg_flags = 0; - + k = sendmsg(c->fd, &m, MSG_DONTWAIT); for (i = 1; i < iov_idx; i++) @@ -124,13 +124,13 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { k = 0; c->timestamp += skip/c->frame_size; - + if (k < 0) { if (errno != EAGAIN) /* If the queue is full, just ignore it */ pa_log("sendmsg() failed: %s", pa_cstrerror(errno)); return -1; } - + if (r < 0 || pa_memblockq_get_length(q) < size) break; @@ -158,7 +158,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { uint32_t header; int cc; ssize_t r; - + assert(c); assert(chunk); @@ -184,7 +184,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { m.msg_control = NULL; m.msg_controllen = 0; m.msg_flags = 0; - + if ((r = recvmsg(c->fd, &m, 0)) != size) { pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); goto fail; @@ -198,7 +198,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { memcpy(&header, chunk->memblock->data, sizeof(uint32_t)); memcpy(&c->timestamp, (uint8_t*) chunk->memblock->data + 4, sizeof(uint32_t)); memcpy(&c->ssrc, (uint8_t*) chunk->memblock->data + 8, sizeof(uint32_t)); - + header = ntohl(header); c->timestamp = ntohl(c->timestamp); c->ssrc = ntohl(c->ssrc); @@ -234,7 +234,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { pa_log("Vad RTP packet size."); goto fail; } - + return 0; fail: @@ -255,7 +255,7 @@ uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) { return 10; if (ss->format == PA_SAMPLE_S16BE && ss->rate == 44100 && ss->channels == 1) return 11; - + return 127; } @@ -280,7 +280,7 @@ pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec ss->format = PA_SAMPLE_S16BE; ss->rate = 44100; break; - + case 11: ss->channels = 1; ss->format = PA_SAMPLE_S16BE; @@ -340,7 +340,7 @@ const char* pa_rtp_format_to_string(pa_sample_format_t f) { pa_sample_format_t pa_rtp_string_to_format(const char *s) { assert(s); - + if (!(strcmp(s, "L16"))) return PA_SAMPLE_S16BE; else if (!strcmp(s, "L8")) diff --git a/src/modules/rtp/rtp.h b/src/modules/rtp/rtp.h index db7acd983..ad7175ca1 100644 --- a/src/modules/rtp/rtp.h +++ b/src/modules/rtp/rtp.h @@ -7,17 +7,17 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index a6e92187f..824218072 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -4,17 +4,17 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -60,8 +60,8 @@ pa_sap_context* pa_sap_context_init_send(pa_sap_context *c, int fd, char *sdp_da c->fd = fd; c->sdp_data = sdp_data; c->msg_id_hash = (uint16_t) (rand()*rand()); - - return c; + + return c; } void pa_sap_context_destroy(pa_sap_context *c) { @@ -86,7 +86,7 @@ int pa_sap_send(pa_sap_context *c, int goodbye) { } assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); - + header = htonl(((uint32_t) 1 << 29) | (sa->sa_family == AF_INET6 ? (uint32_t) 1 << 28 : 0) | (goodbye ? (uint32_t) 1 << 26 : 0) | @@ -103,7 +103,7 @@ int pa_sap_send(pa_sap_context *c, int goodbye) { iov[3].iov_base = c->sdp_data; iov[3].iov_len = strlen(c->sdp_data); - + m.msg_name = NULL; m.msg_namelen = 0; m.msg_iov = iov; @@ -111,7 +111,7 @@ int pa_sap_send(pa_sap_context *c, int goodbye) { m.msg_control = NULL; m.msg_controllen = 0; m.msg_flags = 0; - + if ((k = sendmsg(c->fd, &m, MSG_DONTWAIT)) < 0) pa_log("sendmsg() failed: %s\n", pa_cstrerror(errno)); @@ -135,7 +135,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { uint32_t header; int six, ac; ssize_t r; - + assert(c); assert(goodbye); @@ -146,7 +146,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { buf = pa_xnew(char, size+1); buf[size] = 0; - + iov.iov_base = buf; iov.iov_len = size; @@ -157,7 +157,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { m.msg_control = NULL; m.msg_controllen = 0; m.msg_flags = 0; - + if ((r = recvmsg(c->fd, &m, 0)) != size) { pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); goto fail; @@ -208,12 +208,12 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { if (c->sdp_data) pa_xfree(c->sdp_data); - + c->sdp_data = pa_xstrndup(e, size); pa_xfree(buf); - + *goodbye = !!((header >> 26) & 1); - + return 0; fail: diff --git a/src/modules/rtp/sap.h b/src/modules/rtp/sap.h index cac697e64..f906a32b8 100644 --- a/src/modules/rtp/sap.h +++ b/src/modules/rtp/sap.h @@ -7,17 +7,17 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index 7f0e7027b..8b0bd5354 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -4,17 +4,17 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -54,18 +54,18 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u f = pa_rtp_format_to_string(ss->format); assert(f); - + if (!(u = getenv("USER"))) if (!(u = getenv("USERNAME"))) u = "-"; - + ntp = time(NULL) + 2208988800U; a = inet_ntop(af, src, buf_src, sizeof(buf_src)); assert(a); a = inet_ntop(af, dst, buf_dst, sizeof(buf_dst)); assert(a); - + return pa_sprintf_malloc( PA_SDP_HEADER "o=%s %lu 0 IN %s %s\n" @@ -125,11 +125,11 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { assert(t); assert(i); - + i->origin = i->session_name = NULL; i->salen = 0; i->payload = 255; - + if (!pa_startswith(t, PA_SDP_HEADER)) { pa_log("Failed to parse SDP data: invalid header."); goto fail; @@ -156,7 +156,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { size_t k; k = l-8 > sizeof(a) ? sizeof(a) : l-8; - + pa_strlcpy(a, t+9, k); a[strcspn(a, "/")] = 0; @@ -173,7 +173,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { size_t k; k = l-8 > sizeof(a) ? sizeof(a) : l-8; - + pa_strlcpy(a, t+9, k); a[strcspn(a, "/")] = 0; @@ -189,7 +189,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { if (i->payload > 127) { int _port, _payload; - + if (sscanf(t+8, "%i RTP/AVP %i", &_port, &_payload) == 2) { if (_port <= 0 || _port > 0xFFFF) { @@ -224,16 +224,16 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { if (_payload == i->payload) { c[strcspn(c, "\n")] = 0; - + if (parse_sdp_sample_spec(&i->sample_spec, c)) ss_valid = 1; } } } } - + t += l; - + if (*t == '\n') t++; } @@ -247,7 +247,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { ((struct sockaddr_in*) &i->sa)->sin_port = htons(port); else ((struct sockaddr_in6*) &i->sa)->sin6_port = htons(port); - + return i; fail: diff --git a/src/modules/rtp/sdp.h b/src/modules/rtp/sdp.h index 4c68ac5a1..7c91fca63 100644 --- a/src/modules/rtp/sdp.h +++ b/src/modules/rtp/sdp.h @@ -7,17 +7,17 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 4dbf3afa6..6989069d3 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -1033,10 +1033,10 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b if (ifstate && *ifstate == IFSTATE_FALSE) return 0; - + l = strcspn(cs, whitespace); - + for (command = commands; command->name; command++) if (strlen(command->name) == l && !strncmp(cs, command->name, l)) { int ret; @@ -1071,7 +1071,7 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int FILE *f = NULL; int ifstate = IFSTATE_NONE; int ret = -1; - + assert(c); assert(fn); assert(buf); @@ -1103,7 +1103,7 @@ fail: int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail) { const char *p; int ifstate = IFSTATE_NONE; - + assert(c); assert(s); assert(buf); diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 5159934d8..e5766b2fa 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -492,7 +492,7 @@ void pa_raise_priority(void) { if ((caps = cap_get_proc())) { cap_t caps_new; cap_value_t nice_cap = CAP_SYS_NICE; - + if ((caps_new = cap_dup(caps))) { cap_set_flag(caps_new, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET); cap_set_flag(caps_new, CAP_PERMITTED, 1, &nice_cap, CAP_SET); @@ -501,7 +501,7 @@ void pa_raise_priority(void) { } } #endif - + #ifdef HAVE_SYS_RESOURCE_H if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) pa_log_warn("setpriority(): %s", pa_cstrerror(errno)); diff --git a/src/pulsecore/g711.c b/src/pulsecore/g711.c index 55a82396c..8c2bbf008 100644 --- a/src/pulsecore/g711.c +++ b/src/pulsecore/g711.c @@ -1,2531 +1,2531 @@ -/* - * This source code is a product of Sun Microsystems, Inc. and is provided - * for unrestricted use. Users may copy or modify this source code without - * charge. - * - * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING - * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun source code is provided with no support and without any obligation on - * the part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ - -/* - * g711.c - * - * u-law, A-law and linear PCM conversions. - */ - -/* - * December 30, 1994: - * Functions linear2alaw, linear2ulaw have been updated to correctly - * convert unquantized 16 bit values. - * Tables for direct u- to A-law and A- to u-law conversions have been - * corrected. - * Borge Lindberg, Center for PersonKommunikation, Aalborg University. - * bli@cpk.auc.dk - * - */ - -#include "g711.h" - -#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ -#define QUANT_MASK (0xf) /* Quantization field mask. */ -#define NSEGS (8) /* Number of A-law segments. */ -#define SEG_SHIFT (4) /* Left shift for segment number. */ -#define SEG_MASK (0x70) /* Segment field mask. */ - -#if !defined(FAST_ALAW_CONVERSION) || !defined(FAST_ULAW_CONVERSION) -static int16_t seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF, - 0x1FF, 0x3FF, 0x7FF, 0xFFF}; -static int16_t seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, - 0x3FF, 0x7FF, 0xFFF, 0x1FFF}; - -static int16_t search( - int16_t val, - int16_t *table, - int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (val <= *table++) - return (i); - } - return (size); -} -#endif /* !FAST_*_CONVERSION */ - -#ifndef FAST_ALAW_CONVERSION -/* - * linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data - * stored in a unsigned char. This function should only be called with - * the data shifted such that it only contains information in the lower - * 13-bits. - * - * Linear Input Code Compressed Code - * ------------------------ --------------- - * 0000000wxyza 000wxyz - * 0000001wxyza 001wxyz - * 000001wxyzab 010wxyz - * 00001wxyzabc 011wxyz - * 0001wxyzabcd 100wxyz - * 001wxyzabcde 101wxyz - * 01wxyzabcdef 110wxyz - * 1wxyzabcdefg 111wxyz - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ -unsigned char st_13linear2alaw( - int16_t pcm_val) /* 2's complement (13-bit range) */ -{ - int16_t mask; - short seg; - unsigned char aval; - - /* Have calling software do it since its already doing a shift - * from 32-bits down to 16-bits. - */ - /* pcm_val = pcm_val >> 3; */ - - /* A-law using even bit inversion */ - if (pcm_val >= 0) { - mask = 0xD5; /* sign (7th) bit = 1 */ - } else { - mask = 0x55; /* sign bit = 0 */ - pcm_val = -pcm_val - 1; - } - - /* Convert the scaled magnitude to segment number. */ - seg = search(pcm_val, seg_aend, 8); - - /* Combine the sign, segment, and quantization bits. */ - - if (seg >= 8) /* out of range, return maximum value. */ - return (unsigned char) (0x7F ^ mask); - else { - aval = (unsigned char) seg << SEG_SHIFT; - if (seg < 2) - aval |= (pcm_val >> 1) & QUANT_MASK; - else - aval |= (pcm_val >> seg) & QUANT_MASK; - return (aval ^ mask); - } -} - -/* - * alaw2linear() - Convert an A-law value to 16-bit signed linear PCM - * - */ -int16_t st_alaw2linear16( - unsigned char a_val) -{ - int16_t t; - int16_t seg; - - a_val ^= 0x55; - - t = (a_val & QUANT_MASK) << 4; - seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; - switch (seg) { - case 0: - t += 8; - break; - case 1: - t += 0x108; - break; - default: - t += 0x108; - t <<= seg - 1; - } - return ((a_val & SIGN_BIT) ? t : -t); -} -#endif /* !FAST_ALAW_CONVERSION */ - -#define BIAS (0x84) /* Bias for linear code. */ -#define CLIP 8159 - -#ifndef FAST_ULAW_CONVERSION -/* - * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data - * stored in a unsigned char. This function should only be called with - * the data shifted such that it only contains information in the lower - * 14-bits. - * - * In order to simplify the encoding process, the original linear magnitude - * is biased by adding 33 which shifts the encoding range from (0 - 8158) to - * (33 - 8191). The result can be seen in the following encoding table: - * - * Biased Linear Input Code Compressed Code - * ------------------------ --------------- - * 00000001wxyza 000wxyz - * 0000001wxyzab 001wxyz - * 000001wxyzabc 010wxyz - * 00001wxyzabcd 011wxyz - * 0001wxyzabcde 100wxyz - * 001wxyzabcdef 101wxyz - * 01wxyzabcdefg 110wxyz - * 1wxyzabcdefgh 111wxyz - * - * Each biased linear code has a leading 1 which identifies the segment - * number. The value of the segment number is equal to 7 minus the number - * of leading 0's. The quantization interval is directly available as the - * four bits wxyz. * The trailing bits (a - h) are ignored. - * - * Ordinarily the complement of the resulting code word is used for - * transmission, and so the code word is complemented before it is returned. - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ -unsigned char st_14linear2ulaw( - int16_t pcm_val) /* 2's complement (14-bit range) */ -{ - int16_t mask; - int16_t seg; - unsigned char uval; - - /* Have calling software do it since its already doing a shift - * from 32-bits down to 16-bits. - */ - /* pcm_val = pcm_val >> 2; */ - - /* u-law inverts all bits */ - /* Get the sign and the magnitude of the value. */ - if (pcm_val < 0) { - pcm_val = -pcm_val; - mask = 0x7F; - } else { - mask = 0xFF; - } - if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */ - pcm_val += (BIAS >> 2); - - /* Convert the scaled magnitude to segment number. */ - seg = search(pcm_val, seg_uend, 8); - - /* - * Combine the sign, segment, quantization bits; - * and complement the code word. - */ - if (seg >= 8) /* out of range, return maximum value. */ - return (unsigned char) (0x7F ^ mask); - else { - uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF); - return (uval ^ mask); - } - -} - -/* - * ulaw2linear() - Convert a u-law value to 16-bit linear PCM - * - * First, a biased linear code is derived from the code word. An unbiased - * output can then be obtained by subtracting 33 from the biased code. - * - * Note that this function expects to be passed the complement of the - * original code word. This is in keeping with ISDN conventions. - */ -int16_t st_ulaw2linear16( - unsigned char u_val) -{ - int16_t t; - - /* Complement to obtain normal u-law value. */ - u_val = ~u_val; - - /* - * Extract and bias the quantization bits. Then - * shift up by the segment number and subtract out the bias. - */ - t = ((u_val & QUANT_MASK) << 3) + BIAS; - t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; - - return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); -} -#endif /* !FAST_ULAW_CONVERSION */ - -#ifdef FAST_ALAW_CONVERSION - -int16_t _st_alaw2linear16[256] = { - -5504, -5248, -6016, -5760, -4480, -4224, -4992, - -4736, -7552, -7296, -8064, -7808, -6528, -6272, - -7040, -6784, -2752, -2624, -3008, -2880, -2240, - -2112, -2496, -2368, -3776, -3648, -4032, -3904, - -3264, -3136, -3520, -3392, -22016, -20992, -24064, - -23040, -17920, -16896, -19968, -18944, -30208, -29184, - -32256, -31232, -26112, -25088, -28160, -27136, -11008, - -10496, -12032, -11520, -8960, -8448, -9984, -9472, - -15104, -14592, -16128, -15616, -13056, -12544, -14080, - -13568, -344, -328, -376, -360, -280, -264, - -312, -296, -472, -456, -504, -488, -408, - -392, -440, -424, -88, -72, -120, -104, - -24, -8, -56, -40, -216, -200, -248, - -232, -152, -136, -184, -168, -1376, -1312, - -1504, -1440, -1120, -1056, -1248, -1184, -1888, - -1824, -2016, -1952, -1632, -1568, -1760, -1696, - -688, -656, -752, -720, -560, -528, -624, - -592, -944, -912, -1008, -976, -816, -784, - -880, -848, 5504, 5248, 6016, 5760, 4480, - 4224, 4992, 4736, 7552, 7296, 8064, 7808, - 6528, 6272, 7040, 6784, 2752, 2624, 3008, - 2880, 2240, 2112, 2496, 2368, 3776, 3648, - 4032, 3904, 3264, 3136, 3520, 3392, 22016, - 20992, 24064, 23040, 17920, 16896, 19968, 18944, - 30208, 29184, 32256, 31232, 26112, 25088, 28160, - 27136, 11008, 10496, 12032, 11520, 8960, 8448, - 9984, 9472, 15104, 14592, 16128, 15616, 13056, - 12544, 14080, 13568, 344, 328, 376, 360, - 280, 264, 312, 296, 472, 456, 504, - 488, 408, 392, 440, 424, 88, 72, - 120, 104, 24, 8, 56, 40, 216, - 200, 248, 232, 152, 136, 184, 168, - 1376, 1312, 1504, 1440, 1120, 1056, 1248, - 1184, 1888, 1824, 2016, 1952, 1632, 1568, - 1760, 1696, 688, 656, 752, 720, 560, - 528, 624, 592, 944, 912, 1008, 976, - 816, 784, 880, 848 -}; - -uint8_t _st_13linear2alaw[0x2000] = { - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x3a, 0x3a, 0x3a, 0x3a, - 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, - 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, - 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, - 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, - 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, - 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, - 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, - 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, - 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, - 0x3d, 0x3d, 0x3d, 0x3d, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, - 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, - 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, - 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, - 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, - 0x37, 0x37, 0x37, 0x37, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35, - 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, - 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, - 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, - 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, - 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, - 0x6b, 0x6b, 0x6b, 0x6b, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, - 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x6e, 0x6e, 0x6e, 0x6e, - 0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, - 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, - 0x6d, 0x6d, 0x6d, 0x6d, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x60, 0x60, 0x60, 0x60, - 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, - 0x67, 0x67, 0x67, 0x67, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, - 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x7a, 0x7a, 0x7a, 0x7a, - 0x7b, 0x7b, 0x7b, 0x7b, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79, - 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7d, 0x7d, 0x7d, 0x7d, 0x72, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x73, - 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x71, 0x76, 0x76, 0x76, 0x76, - 0x77, 0x77, 0x77, 0x77, 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, - 0x4a, 0x4a, 0x4b, 0x4b, 0x48, 0x48, 0x49, 0x49, 0x4e, 0x4e, 0x4f, 0x4f, - 0x4c, 0x4c, 0x4d, 0x4d, 0x42, 0x42, 0x43, 0x43, 0x40, 0x40, 0x41, 0x41, - 0x46, 0x46, 0x47, 0x47, 0x44, 0x44, 0x45, 0x45, 0x5a, 0x5a, 0x5b, 0x5b, - 0x58, 0x58, 0x59, 0x59, 0x5e, 0x5e, 0x5f, 0x5f, 0x5c, 0x5c, 0x5d, 0x5d, - 0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51, 0x56, 0x56, 0x57, 0x57, - 0x54, 0x54, 0x55, 0x55, 0xd5, 0xd5, 0xd4, 0xd4, 0xd7, 0xd7, 0xd6, 0xd6, - 0xd1, 0xd1, 0xd0, 0xd0, 0xd3, 0xd3, 0xd2, 0xd2, 0xdd, 0xdd, 0xdc, 0xdc, - 0xdf, 0xdf, 0xde, 0xde, 0xd9, 0xd9, 0xd8, 0xd8, 0xdb, 0xdb, 0xda, 0xda, - 0xc5, 0xc5, 0xc4, 0xc4, 0xc7, 0xc7, 0xc6, 0xc6, 0xc1, 0xc1, 0xc0, 0xc0, - 0xc3, 0xc3, 0xc2, 0xc2, 0xcd, 0xcd, 0xcc, 0xcc, 0xcf, 0xcf, 0xce, 0xce, - 0xc9, 0xc9, 0xc8, 0xc8, 0xcb, 0xcb, 0xca, 0xca, 0xf5, 0xf5, 0xf5, 0xf5, - 0xf4, 0xf4, 0xf4, 0xf4, 0xf7, 0xf7, 0xf7, 0xf7, 0xf6, 0xf6, 0xf6, 0xf6, - 0xf1, 0xf1, 0xf1, 0xf1, 0xf0, 0xf0, 0xf0, 0xf0, 0xf3, 0xf3, 0xf3, 0xf3, - 0xf2, 0xf2, 0xf2, 0xf2, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, 0xfc, 0xfc, 0xfc, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf8, 0xf8, 0xf8, 0xf8, 0xfb, 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xfa, 0xfa, - 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4, - 0xe4, 0xe4, 0xe4, 0xe4, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe1, 0xe1, 0xe1, 0xe1, - 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, - 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, - 0xe2, 0xe2, 0xe2, 0xe2, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, - 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xef, 0xef, 0xef, 0xef, - 0xef, 0xef, 0xef, 0xef, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8, - 0xe8, 0xe8, 0xe8, 0xe8, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, - 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa -}; - -#endif /* FAST_ALAW_CONVERSION */ - -#ifdef FAST_ULAW_CONVERSION - -int16_t _st_ulaw2linear16[256] = { - -32124, -31100, -30076, -29052, -28028, -27004, -25980, - -24956, -23932, -22908, -21884, -20860, -19836, -18812, - -17788, -16764, -15996, -15484, -14972, -14460, -13948, - -13436, -12924, -12412, -11900, -11388, -10876, -10364, - -9852, -9340, -8828, -8316, -7932, -7676, -7420, - -7164, -6908, -6652, -6396, -6140, -5884, -5628, - -5372, -5116, -4860, -4604, -4348, -4092, -3900, - -3772, -3644, -3516, -3388, -3260, -3132, -3004, - -2876, -2748, -2620, -2492, -2364, -2236, -2108, - -1980, -1884, -1820, -1756, -1692, -1628, -1564, - -1500, -1436, -1372, -1308, -1244, -1180, -1116, - -1052, -988, -924, -876, -844, -812, -780, - -748, -716, -684, -652, -620, -588, -556, - -524, -492, -460, -428, -396, -372, -356, - -340, -324, -308, -292, -276, -260, -244, - -228, -212, -196, -180, -164, -148, -132, - -120, -112, -104, -96, -88, -80, -72, - -64, -56, -48, -40, -32, -24, -16, - -8, 0, 32124, 31100, 30076, 29052, 28028, - 27004, 25980, 24956, 23932, 22908, 21884, 20860, - 19836, 18812, 17788, 16764, 15996, 15484, 14972, - 14460, 13948, 13436, 12924, 12412, 11900, 11388, - 10876, 10364, 9852, 9340, 8828, 8316, 7932, - 7676, 7420, 7164, 6908, 6652, 6396, 6140, - 5884, 5628, 5372, 5116, 4860, 4604, 4348, - 4092, 3900, 3772, 3644, 3516, 3388, 3260, - 3132, 3004, 2876, 2748, 2620, 2492, 2364, - 2236, 2108, 1980, 1884, 1820, 1756, 1692, - 1628, 1564, 1500, 1436, 1372, 1308, 1244, - 1180, 1116, 1052, 988, 924, 876, 844, - 812, 780, 748, 716, 684, 652, 620, - 588, 556, 524, 492, 460, 428, 396, - 372, 356, 340, 324, 308, 292, 276, - 260, 244, 228, 212, 196, 180, 164, - 148, 132, 120, 112, 104, 96, 88, - 80, 72, 64, 56, 48, 40, 32, - 24, 16, 8, 0 -}; - -uint8_t _st_14linear2ulaw[0x4000] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, - 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, - 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, - 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, - 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x32, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x34, 0x34, - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, - 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, - 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, - 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, - 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, - 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, - 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, - 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, - 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, - 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, - 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, - 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, - 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, - 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, - 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, - 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x43, 0x43, - 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, - 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, - 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x46, 0x46, - 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, - 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, - 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, - 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, - 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, - 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, - 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, - 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, - 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, - 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, - 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, - 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, - 0x52, 0x52, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x54, - 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, - 0x58, 0x58, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5a, 0x5a, - 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, - 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, - 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, - 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x60, 0x60, - 0x60, 0x60, 0x61, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x62, 0x63, 0x63, - 0x63, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x65, 0x65, 0x65, 0x66, 0x66, - 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, - 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, - 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, - 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74, - 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, - 0x7b, 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0xff, 0xfe, 0xfe, 0xfd, - 0xfd, 0xfc, 0xfc, 0xfb, 0xfb, 0xfa, 0xfa, 0xf9, 0xf9, 0xf8, 0xf8, 0xf7, - 0xf7, 0xf6, 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3, 0xf3, 0xf2, 0xf2, 0xf1, - 0xf1, 0xf0, 0xf0, 0xef, 0xef, 0xef, 0xef, 0xee, 0xee, 0xee, 0xee, 0xed, - 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xeb, 0xeb, 0xeb, 0xeb, 0xea, - 0xea, 0xea, 0xea, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe5, 0xe5, 0xe5, 0xe5, 0xe4, - 0xe4, 0xe4, 0xe4, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, - 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, - 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, - 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xda, - 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, - 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd7, - 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, - 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd4, - 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, - 0xd3, 0xd3, 0xd3, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd1, - 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, - 0xd0, 0xd0, 0xd0, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, - 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xce, 0xce, 0xce, 0xce, 0xce, - 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, - 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xca, - 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, - 0xca, 0xca, 0xca, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, - 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, - 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc7, - 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, - 0xc7, 0xc7, 0xc7, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc4, - 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, - 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, - 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, - 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc1, - 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, - 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba, - 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb0, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80 -}; - -#endif /* FAST_ULAW_CONVERSION */ - -/* The following code was used to generate the lookup tables */ -#if 0 -int main() -{ - int x, y, find2a = 0; - - y = 0; - printf("int16_t _st_alaw2linear16[256] = {\n "); - for (x = 0; x < 256; x++) - { - printf("%8d,", st_alaw2linear16(x)); - y++; - if (y == 7) - { - y = 0; - printf("\n "); - } - } - - printf("\n};\n\nuint8_t _st_13linear2alaw[0x2000] = {\n "); - y = 0; - for (x = 0; x < 0x2000; x++) - { - printf(" 0x%02x,", st_13linear2alaw((-0x1000)+x)); - y++; - if (y == 12) - { - y = 0; - printf("\n "); - } - } - - printf("\n};\n\nint16_t _st_ulaw2linear16[256] = {\n "); - y = 0; - for (x = 0; x < 256; x++) - { - printf("%8d,", st_ulaw2linear16(x)); - y++; - if (y == 7) - { - y = 0; - printf("\n "); - } - } - - printf("\n};\n\nuint8_t _st_14linear2ulaw[0x4000] = {\n "); - y = 0; - for (x = 0; x < 0x4000; x++) - { - printf(" 0x%02x,", st_14linear2ulaw((-0x2000)+x)); - y++; - if (y == 12) - { - y = 0; - printf("\n "); - } - } - printf("\n};\n"); - -} -#endif - -/* The following is not used by SoX but kept for reference */ -#if 0 -/* copy from CCITT G.711 specifications */ -unsigned char _u2a[128] = { /* u- to A-law conversions */ - 1, 1, 2, 2, 3, 3, 4, 4, - 5, 5, 6, 6, 7, 7, 8, 8, - 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, - 25, 27, 29, 31, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, - 46, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, - 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, -/* corrected: - 81, 82, 83, 84, 85, 86, 87, 88, - should be: */ - 80, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128}; - -unsigned char _a2u[128] = { /* A- to u-law conversions */ - 1, 3, 5, 7, 9, 11, 13, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 32, 33, 33, 34, 34, 35, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 48, 49, 49, - 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 64, - 65, 66, 67, 68, 69, 70, 71, 72, -/* corrected: - 73, 74, 75, 76, 77, 78, 79, 79, - should be: */ - 73, 74, 75, 76, 77, 78, 79, 80, - - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127}; - -/* A-law to u-law conversion */ -unsigned char st_alaw2ulaw( - unsigned char aval) -{ - aval &= 0xff; - return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : - (0x7F ^ _a2u[aval ^ 0x55])); -} - -/* u-law to A-law conversion */ -unsigned char st_ulaw2alaw( - unsigned char uval) -{ - uval &= 0xff; - return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : - (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1))); -} -#endif +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g711.c + * + * u-law, A-law and linear PCM conversions. + */ + +/* + * December 30, 1994: + * Functions linear2alaw, linear2ulaw have been updated to correctly + * convert unquantized 16 bit values. + * Tables for direct u- to A-law and A- to u-law conversions have been + * corrected. + * Borge Lindberg, Center for PersonKommunikation, Aalborg University. + * bli@cpk.auc.dk + * + */ + +#include "g711.h" + +#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ +#define SEG_MASK (0x70) /* Segment field mask. */ + +#if !defined(FAST_ALAW_CONVERSION) || !defined(FAST_ULAW_CONVERSION) +static int16_t seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF, + 0x1FF, 0x3FF, 0x7FF, 0xFFF}; +static int16_t seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, + 0x3FF, 0x7FF, 0xFFF, 0x1FFF}; + +static int16_t search( + int16_t val, + int16_t *table, + int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (val <= *table++) + return (i); + } + return (size); +} +#endif /* !FAST_*_CONVERSION */ + +#ifndef FAST_ALAW_CONVERSION +/* + * linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data + * stored in a unsigned char. This function should only be called with + * the data shifted such that it only contains information in the lower + * 13-bits. + * + * Linear Input Code Compressed Code + * ------------------------ --------------- + * 0000000wxyza 000wxyz + * 0000001wxyza 001wxyz + * 000001wxyzab 010wxyz + * 00001wxyzabc 011wxyz + * 0001wxyzabcd 100wxyz + * 001wxyzabcde 101wxyz + * 01wxyzabcdef 110wxyz + * 1wxyzabcdefg 111wxyz + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +unsigned char st_13linear2alaw( + int16_t pcm_val) /* 2's complement (13-bit range) */ +{ + int16_t mask; + short seg; + unsigned char aval; + + /* Have calling software do it since its already doing a shift + * from 32-bits down to 16-bits. + */ + /* pcm_val = pcm_val >> 3; */ + + /* A-law using even bit inversion */ + if (pcm_val >= 0) { + mask = 0xD5; /* sign (7th) bit = 1 */ + } else { + mask = 0x55; /* sign bit = 0 */ + pcm_val = -pcm_val - 1; + } + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_aend, 8); + + /* Combine the sign, segment, and quantization bits. */ + + if (seg >= 8) /* out of range, return maximum value. */ + return (unsigned char) (0x7F ^ mask); + else { + aval = (unsigned char) seg << SEG_SHIFT; + if (seg < 2) + aval |= (pcm_val >> 1) & QUANT_MASK; + else + aval |= (pcm_val >> seg) & QUANT_MASK; + return (aval ^ mask); + } +} + +/* + * alaw2linear() - Convert an A-law value to 16-bit signed linear PCM + * + */ +int16_t st_alaw2linear16( + unsigned char a_val) +{ + int16_t t; + int16_t seg; + + a_val ^= 0x55; + + t = (a_val & QUANT_MASK) << 4; + seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; + switch (seg) { + case 0: + t += 8; + break; + case 1: + t += 0x108; + break; + default: + t += 0x108; + t <<= seg - 1; + } + return ((a_val & SIGN_BIT) ? t : -t); +} +#endif /* !FAST_ALAW_CONVERSION */ + +#define BIAS (0x84) /* Bias for linear code. */ +#define CLIP 8159 + +#ifndef FAST_ULAW_CONVERSION +/* + * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data + * stored in a unsigned char. This function should only be called with + * the data shifted such that it only contains information in the lower + * 14-bits. + * + * In order to simplify the encoding process, the original linear magnitude + * is biased by adding 33 which shifts the encoding range from (0 - 8158) to + * (33 - 8191). The result can be seen in the following encoding table: + * + * Biased Linear Input Code Compressed Code + * ------------------------ --------------- + * 00000001wxyza 000wxyz + * 0000001wxyzab 001wxyz + * 000001wxyzabc 010wxyz + * 00001wxyzabcd 011wxyz + * 0001wxyzabcde 100wxyz + * 001wxyzabcdef 101wxyz + * 01wxyzabcdefg 110wxyz + * 1wxyzabcdefgh 111wxyz + * + * Each biased linear code has a leading 1 which identifies the segment + * number. The value of the segment number is equal to 7 minus the number + * of leading 0's. The quantization interval is directly available as the + * four bits wxyz. * The trailing bits (a - h) are ignored. + * + * Ordinarily the complement of the resulting code word is used for + * transmission, and so the code word is complemented before it is returned. + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +unsigned char st_14linear2ulaw( + int16_t pcm_val) /* 2's complement (14-bit range) */ +{ + int16_t mask; + int16_t seg; + unsigned char uval; + + /* Have calling software do it since its already doing a shift + * from 32-bits down to 16-bits. + */ + /* pcm_val = pcm_val >> 2; */ + + /* u-law inverts all bits */ + /* Get the sign and the magnitude of the value. */ + if (pcm_val < 0) { + pcm_val = -pcm_val; + mask = 0x7F; + } else { + mask = 0xFF; + } + if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */ + pcm_val += (BIAS >> 2); + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_uend, 8); + + /* + * Combine the sign, segment, quantization bits; + * and complement the code word. + */ + if (seg >= 8) /* out of range, return maximum value. */ + return (unsigned char) (0x7F ^ mask); + else { + uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF); + return (uval ^ mask); + } + +} + +/* + * ulaw2linear() - Convert a u-law value to 16-bit linear PCM + * + * First, a biased linear code is derived from the code word. An unbiased + * output can then be obtained by subtracting 33 from the biased code. + * + * Note that this function expects to be passed the complement of the + * original code word. This is in keeping with ISDN conventions. + */ +int16_t st_ulaw2linear16( + unsigned char u_val) +{ + int16_t t; + + /* Complement to obtain normal u-law value. */ + u_val = ~u_val; + + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = ((u_val & QUANT_MASK) << 3) + BIAS; + t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; + + return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); +} +#endif /* !FAST_ULAW_CONVERSION */ + +#ifdef FAST_ALAW_CONVERSION + +int16_t _st_alaw2linear16[256] = { + -5504, -5248, -6016, -5760, -4480, -4224, -4992, + -4736, -7552, -7296, -8064, -7808, -6528, -6272, + -7040, -6784, -2752, -2624, -3008, -2880, -2240, + -2112, -2496, -2368, -3776, -3648, -4032, -3904, + -3264, -3136, -3520, -3392, -22016, -20992, -24064, + -23040, -17920, -16896, -19968, -18944, -30208, -29184, + -32256, -31232, -26112, -25088, -28160, -27136, -11008, + -10496, -12032, -11520, -8960, -8448, -9984, -9472, + -15104, -14592, -16128, -15616, -13056, -12544, -14080, + -13568, -344, -328, -376, -360, -280, -264, + -312, -296, -472, -456, -504, -488, -408, + -392, -440, -424, -88, -72, -120, -104, + -24, -8, -56, -40, -216, -200, -248, + -232, -152, -136, -184, -168, -1376, -1312, + -1504, -1440, -1120, -1056, -1248, -1184, -1888, + -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, + -592, -944, -912, -1008, -976, -816, -784, + -880, -848, 5504, 5248, 6016, 5760, 4480, + 4224, 4992, 4736, 7552, 7296, 8064, 7808, + 6528, 6272, 7040, 6784, 2752, 2624, 3008, + 2880, 2240, 2112, 2496, 2368, 3776, 3648, + 4032, 3904, 3264, 3136, 3520, 3392, 22016, + 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, + 27136, 11008, 10496, 12032, 11520, 8960, 8448, + 9984, 9472, 15104, 14592, 16128, 15616, 13056, + 12544, 14080, 13568, 344, 328, 376, 360, + 280, 264, 312, 296, 472, 456, 504, + 488, 408, 392, 440, 424, 88, 72, + 120, 104, 24, 8, 56, 40, 216, + 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, + 1184, 1888, 1824, 2016, 1952, 1632, 1568, + 1760, 1696, 688, 656, 752, 720, 560, + 528, 624, 592, 944, 912, 1008, 976, + 816, 784, 880, 848 +}; + +uint8_t _st_13linear2alaw[0x2000] = { + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, + 0x6b, 0x6b, 0x6b, 0x6b, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x6e, 0x6e, 0x6e, 0x6e, + 0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, + 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, + 0x6d, 0x6d, 0x6d, 0x6d, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, + 0x67, 0x67, 0x67, 0x67, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x7a, 0x7a, 0x7a, 0x7a, + 0x7b, 0x7b, 0x7b, 0x7b, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79, + 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7d, 0x7d, 0x7d, 0x7d, 0x72, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x73, + 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x71, 0x76, 0x76, 0x76, 0x76, + 0x77, 0x77, 0x77, 0x77, 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, + 0x4a, 0x4a, 0x4b, 0x4b, 0x48, 0x48, 0x49, 0x49, 0x4e, 0x4e, 0x4f, 0x4f, + 0x4c, 0x4c, 0x4d, 0x4d, 0x42, 0x42, 0x43, 0x43, 0x40, 0x40, 0x41, 0x41, + 0x46, 0x46, 0x47, 0x47, 0x44, 0x44, 0x45, 0x45, 0x5a, 0x5a, 0x5b, 0x5b, + 0x58, 0x58, 0x59, 0x59, 0x5e, 0x5e, 0x5f, 0x5f, 0x5c, 0x5c, 0x5d, 0x5d, + 0x52, 0x52, 0x53, 0x53, 0x50, 0x50, 0x51, 0x51, 0x56, 0x56, 0x57, 0x57, + 0x54, 0x54, 0x55, 0x55, 0xd5, 0xd5, 0xd4, 0xd4, 0xd7, 0xd7, 0xd6, 0xd6, + 0xd1, 0xd1, 0xd0, 0xd0, 0xd3, 0xd3, 0xd2, 0xd2, 0xdd, 0xdd, 0xdc, 0xdc, + 0xdf, 0xdf, 0xde, 0xde, 0xd9, 0xd9, 0xd8, 0xd8, 0xdb, 0xdb, 0xda, 0xda, + 0xc5, 0xc5, 0xc4, 0xc4, 0xc7, 0xc7, 0xc6, 0xc6, 0xc1, 0xc1, 0xc0, 0xc0, + 0xc3, 0xc3, 0xc2, 0xc2, 0xcd, 0xcd, 0xcc, 0xcc, 0xcf, 0xcf, 0xce, 0xce, + 0xc9, 0xc9, 0xc8, 0xc8, 0xcb, 0xcb, 0xca, 0xca, 0xf5, 0xf5, 0xf5, 0xf5, + 0xf4, 0xf4, 0xf4, 0xf4, 0xf7, 0xf7, 0xf7, 0xf7, 0xf6, 0xf6, 0xf6, 0xf6, + 0xf1, 0xf1, 0xf1, 0xf1, 0xf0, 0xf0, 0xf0, 0xf0, 0xf3, 0xf3, 0xf3, 0xf3, + 0xf2, 0xf2, 0xf2, 0xf2, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, 0xfc, 0xfc, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf8, 0xf8, 0xf8, 0xf8, 0xfb, 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xfa, 0xfa, + 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4, + 0xe4, 0xe4, 0xe4, 0xe4, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, + 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe1, 0xe1, 0xe1, 0xe1, + 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, + 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, + 0xe2, 0xe2, 0xe2, 0xe2, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, + 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xef, 0xef, 0xef, 0xef, + 0xef, 0xef, 0xef, 0xef, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8, + 0xe8, 0xe8, 0xe8, 0xe8, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, + 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa +}; + +#endif /* FAST_ALAW_CONVERSION */ + +#ifdef FAST_ULAW_CONVERSION + +int16_t _st_ulaw2linear16[256] = { + -32124, -31100, -30076, -29052, -28028, -27004, -25980, + -24956, -23932, -22908, -21884, -20860, -19836, -18812, + -17788, -16764, -15996, -15484, -14972, -14460, -13948, + -13436, -12924, -12412, -11900, -11388, -10876, -10364, + -9852, -9340, -8828, -8316, -7932, -7676, -7420, + -7164, -6908, -6652, -6396, -6140, -5884, -5628, + -5372, -5116, -4860, -4604, -4348, -4092, -3900, + -3772, -3644, -3516, -3388, -3260, -3132, -3004, + -2876, -2748, -2620, -2492, -2364, -2236, -2108, + -1980, -1884, -1820, -1756, -1692, -1628, -1564, + -1500, -1436, -1372, -1308, -1244, -1180, -1116, + -1052, -988, -924, -876, -844, -812, -780, + -748, -716, -684, -652, -620, -588, -556, + -524, -492, -460, -428, -396, -372, -356, + -340, -324, -308, -292, -276, -260, -244, + -228, -212, -196, -180, -164, -148, -132, + -120, -112, -104, -96, -88, -80, -72, + -64, -56, -48, -40, -32, -24, -16, + -8, 0, 32124, 31100, 30076, 29052, 28028, + 27004, 25980, 24956, 23932, 22908, 21884, 20860, + 19836, 18812, 17788, 16764, 15996, 15484, 14972, + 14460, 13948, 13436, 12924, 12412, 11900, 11388, + 10876, 10364, 9852, 9340, 8828, 8316, 7932, + 7676, 7420, 7164, 6908, 6652, 6396, 6140, + 5884, 5628, 5372, 5116, 4860, 4604, 4348, + 4092, 3900, 3772, 3644, 3516, 3388, 3260, + 3132, 3004, 2876, 2748, 2620, 2492, 2364, + 2236, 2108, 1980, 1884, 1820, 1756, 1692, + 1628, 1564, 1500, 1436, 1372, 1308, 1244, + 1180, 1116, 1052, 988, 924, 876, 844, + 812, 780, 748, 716, 684, 652, 620, + 588, 556, 524, 492, 460, 428, 396, + 372, 356, 340, 324, 308, 292, 276, + 260, 244, 228, 212, 196, 180, 164, + 148, 132, 120, 112, 104, 96, 88, + 80, 72, 64, 56, 48, 40, 32, + 24, 16, 8, 0 +}; + +uint8_t _st_14linear2ulaw[0x4000] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, + 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, + 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, + 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, + 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, + 0x2f, 0x2f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x43, 0x43, + 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, + 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, + 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x46, 0x46, + 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, + 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, + 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, + 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, + 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, + 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, + 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, + 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, + 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, + 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, + 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, + 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, + 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, + 0x52, 0x52, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x54, + 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5a, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, + 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, + 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x60, 0x60, + 0x60, 0x60, 0x61, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x62, 0x63, 0x63, + 0x63, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x65, 0x65, 0x65, 0x66, 0x66, + 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, + 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, + 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, + 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74, + 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, + 0x7b, 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0xff, 0xfe, 0xfe, 0xfd, + 0xfd, 0xfc, 0xfc, 0xfb, 0xfb, 0xfa, 0xfa, 0xf9, 0xf9, 0xf8, 0xf8, 0xf7, + 0xf7, 0xf6, 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3, 0xf3, 0xf2, 0xf2, 0xf1, + 0xf1, 0xf0, 0xf0, 0xef, 0xef, 0xef, 0xef, 0xee, 0xee, 0xee, 0xee, 0xed, + 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xeb, 0xeb, 0xeb, 0xeb, 0xea, + 0xea, 0xea, 0xea, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8, 0xe7, + 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe5, 0xe5, 0xe5, 0xe5, 0xe4, + 0xe4, 0xe4, 0xe4, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2, 0xe1, + 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, + 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, + 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xda, + 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, + 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd7, + 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, + 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd4, + 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, + 0xd3, 0xd3, 0xd3, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd1, + 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, + 0xd0, 0xd0, 0xd0, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, + 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xce, 0xce, 0xce, 0xce, 0xce, + 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, + 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xca, + 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, + 0xca, 0xca, 0xca, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, + 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, + 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc7, + 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, + 0xc7, 0xc7, 0xc7, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, + 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, + 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, + 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, + 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, + 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, + 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, + 0xbc, 0xbc, 0xbc, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, + 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, + 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, + 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, + 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, + 0xb6, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, + 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, + 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, + 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, + 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, + 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, + 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, + 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, + 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, + 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, + 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, + 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, + 0xa4, 0xa4, 0xa4, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, + 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, + 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, + 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, + 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, + 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, + 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, + 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, + 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, + 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80 +}; + +#endif /* FAST_ULAW_CONVERSION */ + +/* The following code was used to generate the lookup tables */ +#if 0 +int main() +{ + int x, y, find2a = 0; + + y = 0; + printf("int16_t _st_alaw2linear16[256] = {\n "); + for (x = 0; x < 256; x++) + { + printf("%8d,", st_alaw2linear16(x)); + y++; + if (y == 7) + { + y = 0; + printf("\n "); + } + } + + printf("\n};\n\nuint8_t _st_13linear2alaw[0x2000] = {\n "); + y = 0; + for (x = 0; x < 0x2000; x++) + { + printf(" 0x%02x,", st_13linear2alaw((-0x1000)+x)); + y++; + if (y == 12) + { + y = 0; + printf("\n "); + } + } + + printf("\n};\n\nint16_t _st_ulaw2linear16[256] = {\n "); + y = 0; + for (x = 0; x < 256; x++) + { + printf("%8d,", st_ulaw2linear16(x)); + y++; + if (y == 7) + { + y = 0; + printf("\n "); + } + } + + printf("\n};\n\nuint8_t _st_14linear2ulaw[0x4000] = {\n "); + y = 0; + for (x = 0; x < 0x4000; x++) + { + printf(" 0x%02x,", st_14linear2ulaw((-0x2000)+x)); + y++; + if (y == 12) + { + y = 0; + printf("\n "); + } + } + printf("\n};\n"); + +} +#endif + +/* The following is not used by SoX but kept for reference */ +#if 0 +/* copy from CCITT G.711 specifications */ +unsigned char _u2a[128] = { /* u- to A-law conversions */ + 1, 1, 2, 2, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 27, 29, 31, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 46, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, +/* corrected: + 81, 82, 83, 84, 85, 86, 87, 88, + should be: */ + 80, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128}; + +unsigned char _a2u[128] = { /* A- to u-law conversions */ + 1, 3, 5, 7, 9, 11, 13, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 33, 34, 34, 35, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 48, 49, 49, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 64, + 65, 66, 67, 68, 69, 70, 71, 72, +/* corrected: + 73, 74, 75, 76, 77, 78, 79, 79, + should be: */ + 73, 74, 75, 76, 77, 78, 79, 80, + + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}; + +/* A-law to u-law conversion */ +unsigned char st_alaw2ulaw( + unsigned char aval) +{ + aval &= 0xff; + return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : + (0x7F ^ _a2u[aval ^ 0x55])); +} + +/* u-law to A-law conversion */ +unsigned char st_ulaw2alaw( + unsigned char uval) +{ + uval &= 0xff; + return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : + (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1))); +} +#endif diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index dbdb7dd47..dd41b3d56 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -764,7 +764,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, maxlength > 0 && maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, maxlength >= pa_frame_size(&ss), tag, PA_ERR_INVALID); - + if (sink_index != PA_INVALID_INDEX) { sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index c8e7acf06..a99714080 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -56,7 +56,7 @@ pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spe if (length <= 0) length = fs; - + return pa_silence_memblock(pa_memblock_new(pool, length), spec); } diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index b32744261..4271fa42f 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -111,7 +111,7 @@ pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { int pa_thread_is_running(pa_thread *t) { assert(t); - + /* Unfortunately there is no way to tell whether a "foreign" * thread is still running. See * http://udrepper.livejournal.com/16844.html for more diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 0ac48254d..955bd2f12 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2230,7 +2230,7 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETDUPLEX\n"); /* this is a no-op */ break; - + default: debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); From 13a4c5290a5a80025c72e9f40c28c2e6437c82e8 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 4 Jun 2007 09:52:03 +0000 Subject: [PATCH 1362/1514] Add support for the poorly documented SNDCTL_DSP_GETTRIGGER. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1466 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 955bd2f12..b9c26f093 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2061,6 +2061,17 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) *_errno = EIO; break; + case SNDCTL_DSP_GETTRIGGER: + debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETTRIGGER\n"); + + *(int*) argp = 0; + if (!i->play_precork) + *(int*) argp |= PCM_ENABLE_OUTPUT; + if (!i->rec_precork) + *(int*) argp |= PCM_ENABLE_INPUT; + + break; + case SNDCTL_DSP_SETTRIGGER: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETTRIGGER: 0x%08x\n", *(int*) argp); From 14cbbe1096ef10091a0073009a3c65eb13d2da27 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 11 Jun 2007 11:22:30 +0000 Subject: [PATCH 1363/1514] Support stat() and friends as some programs (audacity) likes to check if the device node is there first. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1467 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index b9c26f093..9a2bad449 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -116,9 +116,17 @@ static int (*_ioctl)(int, int, void*) = NULL; static int (*_close)(int) = NULL; static int (*_open)(const char *, int, mode_t) = NULL; static FILE* (*_fopen)(const char *path, const char *mode) = NULL; +static int (*_stat)(const char *, struct stat *) = NULL; +#ifdef _STAT_VER +static int (*___xstat)(int, const char *, struct stat *) = NULL; +#endif #ifdef HAVE_OPEN64 static int (*_open64)(const char *, int, mode_t) = NULL; static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; +static int (*_stat64)(const char *, struct stat64 *) = NULL; +#ifdef _STAT_VER +static int (*___xstat64)(int, const char *, struct stat64 *) = NULL; +#endif #endif static int (*_fclose)(FILE *f) = NULL; static int (*_access)(const char *, int) = NULL; @@ -170,6 +178,38 @@ do { \ pthread_mutex_unlock(&func_mutex); \ } while(0) +#define LOAD_STAT_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_stat) \ + _stat = (int (*)(const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "stat"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_STAT64_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!_stat64) \ + _stat64 = (int (*)(const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "stat64"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_XSTAT_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!___xstat) \ + ___xstat = (int (*)(int, const char *, struct stat *)) dlsym_fn(RTLD_NEXT, "__xstat"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + +#define LOAD_XSTAT64_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!___xstat64) \ + ___xstat64 = (int (*)(int, const char *, struct stat64 *)) dlsym_fn(RTLD_NEXT, "__xstat64"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + #define LOAD_FOPEN_FUNC() \ do { \ pthread_mutex_lock(&func_mutex); \ @@ -2348,7 +2388,107 @@ int access(const char *pathname, int mode) { return 0; } +int stat(const char *pathname, struct stat *buf) { #ifdef HAVE_OPEN64 + struct stat64 parent; +#else + struct stat parent; +#endif + int ret; + + if (!pathname || !buf) { + errno = EFAULT; + return -1; + } + + if (strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0) { + debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat(%s)\n", pathname); + LOAD_STAT_FUNC(); + return _stat(pathname, buf); + } + + debug(DEBUG_LEVEL_NORMAL, __FILE__": stat(%s)\n", pathname); + +#ifdef _STAT_VER +#ifdef HAVE_OPEN64 + ret = __xstat64(_STAT_VER, "/dev", &parent); +#else + ret = __xstat(_STAT_VER, "/dev", &parent); +#endif +#else +#ifdef HAVE_OPEN64 + ret = stat64("/dev", &parent); +#else + ret = stat("/dev", &parent); +#endif +#endif + + if (ret) { + debug(DEBUG_LEVEL_NORMAL, __FILE__": unable to stat \"/dev\"\n"); + return -1; + } + + buf->st_dev = parent.st_dev; + buf->st_ino = 0xDEADBEEF; /* FIXME: Can we do this in a safe way? */ + buf->st_mode = S_IFCHR | S_IRUSR | S_IWUSR; + buf->st_nlink = 1; + buf->st_uid = getuid(); + buf->st_gid = getgid(); + buf->st_rdev = 0x0E03; /* FIXME: Linux specific */ + buf->st_size = 0; + buf->st_atime = 1181557705; + buf->st_mtime = 1181557705; + buf->st_ctime = 1181557705; + buf->st_blksize = 1; + buf->st_blocks = 0; + + return 0; +} + +#ifdef HAVE_OPEN64 + +int stat64(const char *pathname, struct stat64 *buf) { + struct stat oldbuf; + int ret; + + if (!pathname || !buf) { + errno = EFAULT; + return -1; + } + + debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat64(%s)\n", pathname); + + if (strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0) { + LOAD_STAT64_FUNC(); + return _stat64(pathname, buf); + } + + ret = stat(pathname, &oldbuf); + if (ret) + return ret; + + buf->st_dev = oldbuf.st_dev; + buf->st_ino = oldbuf.st_ino; + buf->st_mode = oldbuf.st_mode; + buf->st_nlink = oldbuf.st_nlink; + buf->st_uid = oldbuf.st_uid; + buf->st_gid = oldbuf.st_gid; + buf->st_rdev = oldbuf.st_rdev; + buf->st_size = oldbuf.st_size; + buf->st_atime = oldbuf.st_atime; + buf->st_mtime = oldbuf.st_mtime; + buf->st_ctime = oldbuf.st_ctime; + buf->st_blksize = oldbuf.st_blksize; + buf->st_blocks = oldbuf.st_blocks; + + return 0; +} int open64(const char *filename, int flags, ...) { va_list args; @@ -2374,6 +2514,62 @@ int open64(const char *filename, int flags, ...) { #endif +#ifdef _STAT_VER + +int __xstat(int ver, const char *pathname, struct stat *buf) { + if (!pathname || !buf) { + errno = EFAULT; + return -1; + } + + debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat(%s)\n", pathname); + + if (strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0) { + LOAD_XSTAT_FUNC(); + return ___xstat(ver, pathname, buf); + } + + if (ver != _STAT_VER) { + errno = EINVAL; + return -1; + } + + return stat(pathname, buf); +} + +#ifdef HAVE_OPEN64 + +int __xstat64(int ver, const char *pathname, struct stat64 *buf) { + if (!pathname || !buf) { + errno = EFAULT; + return -1; + } + + debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat64(%s)\n", pathname); + + if (strcmp(pathname, "/dev/dsp") != 0 && + strcmp(pathname, "/dev/adsp") != 0 && + strcmp(pathname, "/dev/sndstat") != 0 && + strcmp(pathname, "/dev/mixer") != 0) { + LOAD_XSTAT64_FUNC(); + return ___xstat64(ver, pathname, buf); + } + + if (ver != _STAT_VER) { + errno = EINVAL; + return -1; + } + + return stat64(pathname, buf); +} + +#endif + +#endif + FILE* fopen(const char *filename, const char *mode) { FILE *f = NULL; int fd; From 0694d2ae3549ed4e7cb8fca3558fb90ed844fca1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 13 Jun 2007 07:21:57 +0000 Subject: [PATCH 1364/1514] Make sure mixer ioctls work on /dev/dsp aswell. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1473 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/padsp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 9a2bad449..95fc9ed3e 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -2279,11 +2279,12 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) case SNDCTL_DSP_SETDUPLEX: debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETDUPLEX\n"); - /* this is a no-op */ - break; + /* this is a no-op */ + break; default: - debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request); + /* Mixer ioctls are valid on /dev/dsp aswell */ + return mixer_ioctl(i, request, argp, _errno); inval: *_errno = EINVAL; From 405d6758efdaa571b5b37b4802ebf2fcf968b19b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 10 Jul 2007 14:36:20 +0000 Subject: [PATCH 1365/1514] Move pthreads detection as it gets confused by things in LIBS. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1502 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 9a1e6c513..8054b0fab 100644 --- a/configure.ac +++ b/configure.ac @@ -208,6 +208,10 @@ AC_CHECK_DEFINE([INADDR_NONE], [netinet/in.h], [], [AC_CHECK_DEFINE([INADDR_NONE], [winsock2.h], [], [AC_DEFINE([INADDR_NONE], [0xffffffff], [Define INADDR_NONE if not found in ])])]) +#### POSIX threads #### + +ACX_PTHREAD + #### Check for libs #### # ISO @@ -256,10 +260,6 @@ AC_CHECK_FUNCS([lstat]) AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid]) -#### POSIX threads #### - -ACX_PTHREAD - #### Large File-Support (LFS) #### AC_SYS_LARGEFILE From 689fd706effaead1a5efbe1fd7f8fcc86f320375 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 10 Jul 2007 14:36:58 +0000 Subject: [PATCH 1366/1514] Make -no-undefined actually work (and fix up error found by it). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1503 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index d90361f33..b1c218dc9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -63,7 +63,7 @@ AM_LIBADD = $(PTHREAD_LIBS) AM_LDADD = $(PTHREAD_LIBS) # Only required on some platforms but defined for all to avoid errors -AM_LDFLAGS = -no-undefined +AM_LDFLAGS = -Wl,-no-undefined if STATIC_BINS BINLDFLAGS = -static @@ -1159,7 +1159,7 @@ liboss_util_la_LIBADD = libpulsecore.la module_oss_la_SOURCES = modules/module-oss.c module_oss_la_LDFLAGS = -module -avoid-version -module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la +module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la libpulsecore.la module_oss_mmap_la_SOURCES = modules/module-oss-mmap.c module_oss_mmap_la_LDFLAGS = -module -avoid-version From a228a517c4fec83b5aba5f60425f25943e9fc727 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 10 Jul 2007 15:20:39 +0000 Subject: [PATCH 1367/1514] Solaris hides inet_ntop in nsl. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1504 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 8054b0fab..eef8eb47f 100644 --- a/configure.ac +++ b/configure.ac @@ -221,6 +221,7 @@ AC_SEARCH_LIBS([pow], [m]) AC_SEARCH_LIBS([sched_setscheduler], [rt]) AC_SEARCH_LIBS([dlopen], [dl]) AC_SEARCH_LIBS([shm_open], [rt]) +AC_SEARCH_LIBS([inet_ntop], [nsl]) # BSD AC_SEARCH_LIBS([connect], [socket]) From b0f692c45d26d9633e4e2f9f6a503f427c9d730c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 10 Jul 2007 15:21:03 +0000 Subject: [PATCH 1368/1514] Make sure we link to the core to get all symbols. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1505 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index b1c218dc9..fc13bb227 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1186,7 +1186,7 @@ module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) module_solaris_la_SOURCES = modules/module-solaris.c module_solaris_la_LDFLAGS = -module -avoid-version -module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la +module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la libpulsecore.la # Avahi From 7455571dd9cb4d1b90c35da77f9e2ba08fcc8b1e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 4 Aug 2007 19:53:37 +0000 Subject: [PATCH 1369/1514] jack driver build fix which became apparent on fedora git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1567 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index fc13bb227..93f331d6b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1250,12 +1250,12 @@ module_rtp_recv_la_CFLAGS = $(AM_CFLAGS) module_jack_sink_la_SOURCES = modules/module-jack-sink.c module_jack_sink_la_LDFLAGS = -module -avoid-version module_jack_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS) -module_jack_sink_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS) +module_jack_sink_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) module_jack_source_la_SOURCES = modules/module-jack-source.c module_jack_source_la_LDFLAGS = -module -avoid-version module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS) -module_jack_source_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS) +module_jack_source_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) # HAL libdbus_util_la_SOURCES = modules/dbus-util.c modules/dbus-util.h From 5ecaf31b6f0963ae79dc1b12c6468f5fb0676c38 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 4 Aug 2007 19:53:51 +0000 Subject: [PATCH 1370/1514] compat with automake 1.10 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1568 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index eef8eb47f..a195da202 100644 --- a/configure.ac +++ b/configure.ac @@ -67,6 +67,7 @@ esac # CC AC_PROG_CC +AM_PROG_CC_C_O AC_PROG_GCC_TRADITIONAL AC_GNU_SOURCE From eaafb79858fff11add29c8a1126a18e90d7785f9 Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Mon, 20 Aug 2007 06:22:21 +0000 Subject: [PATCH 1371/1514] Modified the JACK sink heavily: * Made the sink realtime-safe. * To achieve the previous item, internal buffering was be added. New module argument: buffersize. * Removed the user's need to set the JACK transport to playing state before he could hear anything from PulseAudio. * In process of achieving the previous item, latency calculation got more inaccurate: the reported latency is now always a multiple of the JACK processing block size, and constant. * The JACK ports now have a running numbering in their names. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1680 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-jack-sink.c | 1009 +++++++++++++++++++++++--------- 1 file changed, 742 insertions(+), 267 deletions(-) diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index c6a7e33f0..09a72e3a6 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -3,7 +3,7 @@ /*** This file is part of PulseAudio. - Copyright 2006 Lennart Poettering + Copyright 2006, 2007 Lennart Poettering and Tanu Kaskinen PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -25,33 +25,32 @@ #include #endif -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include #include -#include -#include #include #include -#include -#include +#include #include -#include +#include +#include +#include +#include +#include #include "module-jack-sink-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_AUTHOR("Lennart Poettering & Tanu Kaskinen") PA_MODULE_DESCRIPTION("Jack Sink") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE( @@ -59,335 +58,806 @@ PA_MODULE_USAGE( "server_name= " "client_name= " "channels= " - "connect= " + "connect= " + "buffersize= " "channel_map=") #define DEFAULT_SINK_NAME "jack_out" +#define DEFAULT_CLIENT_NAME "PulseAudio(output)" +#define DEFAULT_RINGBUFFER_SIZE 4096 + struct userdata { - pa_core *core; - pa_module *module; - pa_sink *sink; unsigned channels; + unsigned frame_size; - jack_port_t* port[PA_CHANNELS_MAX]; - jack_client_t *client; + jack_port_t* j_ports[PA_CHANNELS_MAX]; + jack_client_t *j_client; - pthread_mutex_t mutex; - pthread_cond_t cond; + jack_nframes_t j_buffersize; - void * buffer[PA_CHANNELS_MAX]; - jack_nframes_t frames_requested; + /* For avoiding j_buffersize changes at a wrong moment. */ + pthread_mutex_t buffersize_mutex; + + /* The intermediate store where the pulse side writes to and the jack side + reads from. */ + jack_ringbuffer_t* ringbuffer; + + /* For signaling when there's room in the ringbuffer. */ + pthread_mutex_t cond_mutex; + pthread_cond_t ringbuffer_cond; + + pthread_t filler_thread; /* Keeps the ringbuffer filled. */ + + int ringbuffer_is_full; + int filler_thread_is_running; int quit_requested; int pipe_fd_type; int pipe_fds[2]; pa_io_event *io_event; - - jack_nframes_t frames_in_buffer; - jack_nframes_t timestamp; }; + +struct options { + char* sink_name; + int sink_name_given; + + char* server_name; /* May be NULL */ + int server_name_given; + + char* client_name; + int client_name_given; + + unsigned channels; + int channels_given; + + int connect; + int connect_given; + + unsigned buffersize; + int buffersize_given; + + pa_channel_map map; + int map_given; +}; + + static const char* const valid_modargs[] = { "sink_name", "server_name", "client_name", "channels", "connect", + "buffersize", "channel_map", NULL }; -static void stop_sink(struct userdata *u) { - assert (u); - jack_client_close(u->client); - u->client = NULL; - u->core->mainloop->io_free(u->io_event); - u->io_event = NULL; - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - u->sink = NULL; - pa_module_unload_request(u->module); -} +/* Initialization functions. */ +static int parse_options(struct options* o, const char* argument); +static void set_default_channels(pa_module* self, struct options* o); +static int create_sink(pa_module* self, struct options *o); +static void connect_ports(pa_module* self); +static int start_filling_ringbuffer(pa_module* self); -static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { - struct userdata *u = userdata; - char x; +/* Various callbacks. */ +static void jack_error_func(const char* t); +static pa_usec_t sink_get_latency_cb(pa_sink* s); +static int jack_process(jack_nframes_t nframes, void* arg); +static int jack_blocksize_cb(jack_nframes_t nframes, void* arg); +static void jack_shutdown(void* arg); +static void io_event_cb(pa_mainloop_api* m, pa_io_event* e, int fd, + pa_io_event_flags_t flags, void* userdata); - assert(m); - assert(e); - assert(flags == PA_IO_EVENT_INPUT); - assert(u); - assert(u->pipe_fds[0] == fd); +/* The ringbuffer filler thread runs in this function. */ +static void* fill_ringbuffer(void* arg); - pa_read(fd, &x, 1, &u->pipe_fd_type); +/* request_render asks asynchronously the mainloop to call io_event_cb. */ +static void request_render(struct userdata* u); - if (u->quit_requested) { - stop_sink(u); - u->quit_requested = 0; - return; - } - pthread_mutex_lock(&u->mutex); - - if (u->frames_requested > 0) { - unsigned fs; - jack_nframes_t frame_idx; - pa_memchunk chunk; - - fs = pa_frame_size(&u->sink->sample_spec); - - pa_sink_render_full(u->sink, u->frames_requested * fs, &chunk); - - for (frame_idx = 0; frame_idx < u->frames_requested; frame_idx ++) { - unsigned c; - - for (c = 0; c < u->channels; c++) { - float *s = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c; - float *d = ((float*) u->buffer[c]) + frame_idx; - - *d = *s; - } - } - - pa_memblock_unref(chunk.memblock); - - u->frames_requested = 0; - - pthread_cond_signal(&u->cond); - } - - pthread_mutex_unlock(&u->mutex); -} - -static void request_render(struct userdata *u) { - char c = 'x'; - assert(u); - - assert(u->pipe_fds[1] >= 0); - pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type); -} - -static void jack_shutdown(void *arg) { - struct userdata *u = arg; - assert(u); - - u->quit_requested = 1; - request_render(u); -} - -static int jack_process(jack_nframes_t nframes, void *arg) { - struct userdata *u = arg; - assert(u); - - if (jack_transport_query(u->client, NULL) == JackTransportRolling) { - unsigned c; - - pthread_mutex_lock(&u->mutex); - - u->frames_requested = nframes; - - for (c = 0; c < u->channels; c++) { - u->buffer[c] = jack_port_get_buffer(u->port[c], nframes); - assert(u->buffer[c]); - } - - request_render(u); - - pthread_cond_wait(&u->cond, &u->mutex); - - u->frames_in_buffer = nframes; - u->timestamp = jack_get_current_transport_frame(u->client); - - pthread_mutex_unlock(&u->mutex); - } - - return 0; -} - -static pa_usec_t sink_get_latency_cb(pa_sink *s) { - struct userdata *u; - jack_nframes_t n, l, d; - - assert(s); - u = s->userdata; - - if (jack_transport_query(u->client, NULL) != JackTransportRolling) - return 0; - - n = jack_get_current_transport_frame(u->client); - - if (n < u->timestamp) - return 0; - - d = n - u->timestamp; - l = jack_port_get_total_latency(u->client, u->port[0]) + u->frames_in_buffer; - - if (d >= l) - return 0; - - return pa_bytes_to_usec((l - d) * pa_frame_size(&s->sample_spec), &s->sample_spec); -} - -static void jack_error_func(const char*t) { - pa_log_warn("JACK error >%s<", t); -} - -int pa__init(pa_core *c, pa_module*m) { - struct userdata *u = NULL; - pa_sample_spec ss; - pa_channel_map map; - pa_modargs *ma = NULL; - jack_status_t status; - const char *server_name, *client_name; - uint32_t channels = 0; - int do_connect = 1; +int pa__init(pa_core* c, pa_module* self) { + struct userdata* u = NULL; + struct options o; unsigned i; - const char **ports = NULL, **p; - char *t; - + assert(c); - assert(m); + assert(self); - jack_set_error_function(jack_error_func); - - if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments."); - goto fail; - } - - if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { - pa_log("failed to parse connect= argument."); - goto fail; - } - - server_name = pa_modargs_get_value(ma, "server_name", NULL); - client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio"); - - u = pa_xnew0(struct userdata, 1); - m->userdata = u; - u->core = c; - u->module = m; + o.sink_name = NULL; + o.server_name = NULL; + o.client_name = NULL; + + self->userdata = pa_xnew0(struct userdata, 1); + u = self->userdata; + u->pipe_fds[0] = u->pipe_fds[1] = -1; u->pipe_fd_type = 0; - - pthread_mutex_init(&u->mutex, NULL); - pthread_cond_init(&u->cond, NULL); - + u->ringbuffer_is_full = 0; + u->filler_thread_is_running = 0; + u->quit_requested = 0; + pthread_mutex_init(&u->buffersize_mutex, NULL); + pthread_mutex_init(&u->cond_mutex, NULL); + pthread_cond_init(&u->ringbuffer_cond, NULL); + + if (parse_options(&o, self->argument) != 0) + goto fail; + + jack_set_error_function(jack_error_func); + + if (!(u->j_client = jack_client_open( + o.client_name, + o.server_name ? JackServerName : JackNullOption, + NULL, o.server_name))) { + pa_log_error("jack_client_open() failed."); + goto fail; + } + pa_log_info("Successfully connected as '%s'", + jack_get_client_name(u->j_client)); + + if (!o.channels_given) + set_default_channels(self, &o); + + u->channels = o.channels; + + if (!o.map_given) + pa_channel_map_init_auto(&o.map, u->channels, PA_CHANNEL_MAP_ALSA); + + for (i = 0; i < u->channels; i++) { + char* port_name = pa_sprintf_malloc( + "out_%i:%s", i+1, + pa_channel_position_to_string(o.map.map[i])); + + if (!(u->j_ports[i] = jack_port_register( + u->j_client, port_name, + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput|JackPortIsTerminal, 0))) { + pa_log("jack_port_register() failed."); + goto fail; + } + + pa_xfree(port_name); + } + if (pipe(u->pipe_fds) < 0) { pa_log("pipe() failed: %s", pa_cstrerror(errno)); goto fail; } - pa_make_nonblock_fd(u->pipe_fds[1]); + + if (create_sink(self, &o) != 0) + goto fail; - if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { - pa_log("jack_client_open() failed."); + u->frame_size = pa_frame_size(&u->sink->sample_spec); + u->j_buffersize = jack_get_buffer_size(u->j_client); + + /* If the ringbuffer size were equal to the jack buffer size, a full block + would never fit in the ringbuffer, because the ringbuffer can never be + totally full: one slot is always wasted. */ + if (o.buffersize <= u->j_buffersize) { + o.buffersize = u->j_buffersize + 1; + } + /* The actual ringbuffer size will be rounded up to the nearest power of + two. */ + if (!(u->ringbuffer = jack_ringbuffer_create( + o.buffersize * u->frame_size))) { + pa_log("jack_ringbuffer_create() failed."); + goto fail; + } + assert((u->ringbuffer->size % sizeof(float)) == 0); + pa_log_info("buffersize is %u frames (%u samples, %u bytes).", + u->ringbuffer->size / u->frame_size, + u->ringbuffer->size / sizeof(float), + u->ringbuffer->size); + + jack_set_process_callback(u->j_client, jack_process, u); + jack_set_buffer_size_callback(u->j_client, jack_blocksize_cb, u); + jack_on_shutdown(u->j_client, jack_shutdown, u); + + if (jack_activate(u->j_client)) { + pa_log("jack_activate() failed."); goto fail; } - ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); + if (o.connect) + connect_ports(self); - channels = 0; - for (p = ports; *p; p++) - channels++; + u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], + PA_IO_EVENT_INPUT, io_event_cb, self); + + if (start_filling_ringbuffer(self) != 0) + goto fail; - if (!channels) - channels = c->default_sample_spec.channels; + pa_xfree(o.sink_name); + pa_xfree(o.server_name); + pa_xfree(o.client_name); + + return 0; - if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { - pa_log("failed to parse channels= argument."); +fail: + pa_xfree(o.sink_name); + pa_xfree(o.server_name); + pa_xfree(o.client_name); + pa__done(c, self); + + return -1; +} + + +static int parse_options(struct options* o, const char* argument) { + pa_modargs *ma = NULL; + const char* arg_val; + pa_strbuf* strbuf; + + assert(o); + + if (!(ma = pa_modargs_new(argument, valid_modargs))) { + pa_log_error("Failed to parse module arguments."); goto fail; } - pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA); - if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) { - pa_log("failed to parse channel_map= argument."); - goto fail; + strbuf = pa_strbuf_new(); + if ((arg_val = pa_modargs_get_value(ma, "sink_name", NULL))) { + pa_strbuf_puts(strbuf, arg_val); + o->sink_name = pa_strbuf_tostring(strbuf); + o->sink_name_given = 1; + } else { + pa_strbuf_puts(strbuf, DEFAULT_SINK_NAME); + o->sink_name = pa_strbuf_tostring(strbuf); + o->sink_name_given = 0; } + pa_strbuf_free(strbuf); - pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client)); + strbuf = pa_strbuf_new(); + if ((arg_val = pa_modargs_get_value(ma, "server_name", NULL))) { + pa_strbuf_puts(strbuf, arg_val); + o->server_name = pa_strbuf_tostring(strbuf); + o->server_name_given = 1; + } else { + o->server_name = NULL; + o->server_name_given = 0; + } + pa_strbuf_free(strbuf); - ss.channels = u->channels = channels; - ss.rate = jack_get_sample_rate(u->client); - ss.format = PA_SAMPLE_FLOAT32NE; + strbuf = pa_strbuf_new(); + if ((arg_val = pa_modargs_get_value(ma, "client_name", NULL))) { + pa_strbuf_puts(strbuf, arg_val); + o->client_name = pa_strbuf_tostring(strbuf); + o->client_name_given = 1; + } else { + pa_strbuf_puts(strbuf, DEFAULT_CLIENT_NAME); + o->client_name = pa_strbuf_tostring(strbuf); + o->client_name_given = 1; + } + pa_strbuf_free(strbuf); - assert(pa_sample_spec_valid(&ss)); - - for (i = 0; i < ss.channels; i++) { - if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(map.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0))) { - pa_log("jack_port_register() failed."); + if (pa_modargs_get_value(ma, "channels", NULL)) { + o->channels_given = 1; + if (pa_modargs_get_value_u32(ma, "channels", &o->channels) < 0 || + o->channels == 0 || + o->channels >= PA_CHANNELS_MAX) { + pa_log_error("Failed to parse the \"channels\" argument."); goto fail; } + } else { + o->channels = 0; /* The actual default value is the number of physical + input ports in jack (unknown at the moment), or if + that's zero, then the default_sample_spec.channels + of the core. */ + o->channels_given = 0; } - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { - pa_log("failed to create sink."); - goto fail; + if (pa_modargs_get_value(ma, "connect", NULL)) { + o->connect_given = 1; + if (pa_modargs_get_value_boolean(ma, "connect", &o->connect) < 0) { + pa_log_error("Failed to parse the \"connect\" argument."); + goto fail; + } + } else { + o->connect = 1; + o->connect_given = 0; } - u->sink->userdata = u; - pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Jack sink (%s)", jack_get_client_name(u->client))); - pa_xfree(t); - u->sink->get_latency = sink_get_latency_cb; - - jack_set_process_callback(u->client, jack_process, u); - jack_on_shutdown(u->client, jack_shutdown, u); - - if (jack_activate(u->client)) { - pa_log("jack_activate() failed"); - goto fail; + if (pa_modargs_get_value(ma, "buffersize", NULL)) { + o->buffersize_given = 1; + if (pa_modargs_get_value_u32(ma, "buffersize", &o->buffersize) < 0) { + pa_log_error("Failed to parse the \"buffersize\" argument."); + goto fail; + } + } else { + o->buffersize = DEFAULT_RINGBUFFER_SIZE; + o->buffersize_given = 0; } - if (do_connect) { - for (i = 0, p = ports; i < ss.channels; i++, p++) { - - if (!*p) { - pa_log("not enough physical output ports, leaving unconnected."); - break; - } - - pa_log_info("connecting %s to %s", jack_port_name(u->port[i]), *p); - - if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) { - pa_log("failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); - break; - } + if (pa_modargs_get_value(ma, "channel_map", NULL)) { + o->map_given = 1; + if (pa_modargs_get_channel_map(ma, &o->map) < 0) { + pa_log_error("Failed to parse the \"channel_map\" argument."); + goto fail; } + /* channel_map specifies the channel count too. */ + if (o->channels_given && (o->channels != o->map.channels)) { + pa_log_error( + "\"channels\" and \"channel_map\" arguments conficted. If you " + "use the \"channel_map\" argument, you can omit the " + "\"channels\" argument."); + goto fail; + } else { + o->channels = o->map.channels; + o->channels_given = 1; + } + } else { + /* The actual default value is the default alsa mappings, but that + can't be set until the channel count is known. Here we initialize + the map to some valid value, although the value won't be used. */ + pa_channel_map_init_stereo(&o->map); + o->map_given = 0; } - u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u); - - free(ports); pa_modargs_free(ma); return 0; fail: if (ma) - pa_modargs_free(ma); - - free(ports); - - pa__done(c, m); + pa_modargs_free(ma); return -1; } -void pa__done(pa_core *c, pa_module*m) { - struct userdata *u; - assert(c && m); - if (!(u = m->userdata)) +static void set_default_channels(pa_module* self, struct options* o) { + struct userdata* u; + const char **ports, **p; + + assert(self); + assert(o); + assert(self->userdata); + + u = self->userdata; + + assert(u->j_client); + assert(self->core); + + o->channels = 0; + + ports = jack_get_ports(u->j_client, NULL, JACK_DEFAULT_AUDIO_TYPE, + JackPortIsPhysical|JackPortIsInput); + + for (p = ports; *p; p++) + o->channels++; + + free(ports); + + if (o->channels >= PA_CHANNELS_MAX) + o->channels = PA_CHANNELS_MAX - 1; + + if (o->channels == 0) + o->channels = self->core->default_sample_spec.channels; +} + + +static int create_sink(pa_module* self, struct options* o) { + struct userdata* u; + pa_sample_spec ss; + char *t; + + assert(self); + assert(o); + assert(self->userdata); + + u = self->userdata; + + assert(u->j_client); + + ss.channels = u->channels; + ss.rate = jack_get_sample_rate(u->j_client); + ss.format = PA_SAMPLE_FLOAT32NE; + assert(pa_sample_spec_valid(&ss)); + + if (!(u->sink = pa_sink_new(self->core, __FILE__, o->sink_name, 0, &ss, + &o->map))) { + pa_log("failed to create sink."); + return -1; + } + + u->sink->userdata = u; + pa_sink_set_owner(u->sink, self); + + pa_sink_set_description( + u->sink, + t = pa_sprintf_malloc("Jack sink (%s)", + jack_get_client_name(u->j_client))); + pa_xfree(t); + + u->sink->get_latency = sink_get_latency_cb; + + return 0; +} + + +static void connect_ports(pa_module* self) { + struct userdata* u; + unsigned i; + const char **ports, **p; + + assert(self); + assert(self->userdata); + + u = self->userdata; + + assert(u->j_client); + + ports = jack_get_ports(u->j_client, NULL, JACK_DEFAULT_AUDIO_TYPE, + JackPortIsPhysical|JackPortIsInput); + + for (i = 0, p = ports; i < u->channels; i++, p++) { + assert(u->j_ports[i]); + + if (!*p) { + pa_log("Not enough physical output ports, leaving unconnected."); + break; + } + + pa_log_info("connecting %s to %s", + jack_port_name(u->j_ports[i]), *p); + + if (jack_connect(u->j_client, jack_port_name(u->j_ports[i]), *p)) { + pa_log("Failed to connect %s to %s, leaving unconnected.", + jack_port_name(u->j_ports[i]), *p); + break; + } + } + + free(ports); +} + + +static int start_filling_ringbuffer(pa_module* self) { + struct userdata* u; + pthread_attr_t thread_attributes; + + assert(self); + assert(self->userdata); + + u = self->userdata; + + pthread_attr_init(&thread_attributes); + + if (pthread_attr_setinheritsched(&thread_attributes, + PTHREAD_INHERIT_SCHED) != 0) { + pa_log("pthread_attr_setinheritsched() failed."); + goto fail; + } + else if (pthread_create(&u->filler_thread, &thread_attributes, + fill_ringbuffer, u) != 0) { + pa_log("pthread_create() failed."); + goto fail; + } + + u->filler_thread_is_running = 1; + + pthread_attr_destroy(&thread_attributes); + + return 0; + +fail: + pthread_attr_destroy(&thread_attributes); + return -1; +} + + +static void jack_error_func(const char* t) { + pa_log_warn("JACK error >%s<", t); +} + + +static pa_usec_t sink_get_latency_cb(pa_sink* s) { + /* The latency is approximately the sum of the first port's latency, + buffersize of jack and the ringbuffer size. Maybe instead of using just + the first port, the max of all ports' latencies should be used? */ + struct userdata* u; + jack_nframes_t l; + + assert(s); + assert(s->userdata); + + u = s->userdata; + + l = jack_port_get_total_latency(u->j_client, u->j_ports[0]) + + u->j_buffersize + u->ringbuffer->size / u->frame_size; + + return pa_bytes_to_usec(l * u->frame_size, &s->sample_spec); +} + + +static int jack_process(jack_nframes_t nframes, void* arg) { + struct userdata* u = arg; + float* j_buffers[PA_CHANNELS_MAX]; + unsigned nsamples = u->channels * nframes; + unsigned sample_idx_part1, sample_idx_part2; + jack_nframes_t frame_idx; + jack_ringbuffer_data_t data[2]; /* In case the readable area in the + ringbuffer is non-continuous, the data + will be split in two parts. */ + unsigned chan; + unsigned samples_left_over; + + for (chan = 0; chan < u->channels; chan++) { + j_buffers[chan] = jack_port_get_buffer(u->j_ports[chan], nframes); + } + + jack_ringbuffer_get_read_vector(u->ringbuffer, data); + + /* We assume that the possible discontinuity doesn't happen in the middle + * of a sample. Should be a safe assumption. */ + assert(((data[0].len % sizeof(float)) == 0) || + (data[1].len == 0)); + + /* Copy from the first part of data until enough samples are copied or the + first part ends. */ + sample_idx_part1 = 0; + chan = 0; + frame_idx = 0; + while (sample_idx_part1 < nsamples && + ((sample_idx_part1 + 1) * sizeof(float)) <= data[0].len) { + float *s = ((float*) data[0].buf) + sample_idx_part1; + float *d = j_buffers[chan] + frame_idx; + *d = *s; + + sample_idx_part1++; + chan = (chan + 1) % u->channels; + frame_idx = sample_idx_part1 / u->channels; + } + + samples_left_over = nsamples - sample_idx_part1; + + /* Copy from the second part of data until enough samples are copied or the + second part ends. */ + sample_idx_part2 = 0; + while (sample_idx_part2 < samples_left_over && + ((sample_idx_part2 + 1) * sizeof(float)) <= data[1].len) { + float *s = ((float*) data[1].buf) + sample_idx_part2; + float *d = j_buffers[chan] + frame_idx; + *d = *s; + + sample_idx_part2++; + chan = (chan + 1) % u->channels; + frame_idx = (sample_idx_part1 + sample_idx_part2) / u->channels; + } + + samples_left_over -= sample_idx_part2; + + /* If there's still samples left, fill the buffers with zeros. */ + while (samples_left_over > 0) { + float *d = j_buffers[chan] + frame_idx; + *d = 0.0; + + samples_left_over--; + chan = (chan + 1) % u->channels; + frame_idx = (nsamples - samples_left_over) / u->channels; + } + + jack_ringbuffer_read_advance( + u->ringbuffer, (sample_idx_part1 + sample_idx_part2) * sizeof(float)); + + /* Tell the rendering part that there is room in the ringbuffer. */ + u->ringbuffer_is_full = 0; + pthread_cond_signal(&u->ringbuffer_cond); + + return 0; +} + + +static int jack_blocksize_cb(jack_nframes_t nframes, void* arg) { + /* This gets called in the processing thread, so do we have to be realtime + safe? No, we can do whatever we want. User gets silence while we do it. + + In addition to just updating the j_buffersize field in userdata, we have + to create a new ringbuffer, if the new buffer size is bigger or equal to + the old ringbuffer size. */ + struct userdata* u = arg; + + assert(u); + + /* We don't want to change the blocksize and the ringbuffer while rendering + is going on. */ + pthread_mutex_lock(&u->buffersize_mutex); + + u->j_buffersize = nframes; + + if ((u->ringbuffer->size / u->frame_size) <= nframes) { + /* We have to create a new ringbuffer. What are we going to do with the + old data in the old buffer? We throw it away, because we're lazy + coders. The listening experience is likely to get ruined anyway + during the blocksize change. */ + jack_ringbuffer_free(u->ringbuffer); + + /* The actual ringbuffer size will be rounded up to the nearest power + of two. */ + if (!(u->ringbuffer = + jack_ringbuffer_create((nframes + 1) * u->frame_size))) { + pa_log_error( + "jack_ringbuffer_create() failed while changing jack's buffer " + "size, module exiting."); + jack_client_close(u->j_client); + u->quit_requested = 1; + } + assert((u->ringbuffer->size % sizeof(float)) == 0); + pa_log_info("buffersize is %u frames (%u samples, %u bytes).", + u->ringbuffer->size / u->frame_size, + u->ringbuffer->size / sizeof(float), + u->ringbuffer->size); + } + + pthread_mutex_unlock(&u->buffersize_mutex); + + return 0; +} + + +static void jack_shutdown(void* arg) { + struct userdata* u = arg; + assert(u); + + u->quit_requested = 1; + request_render(u); +} + + +static void io_event_cb(pa_mainloop_api* m, pa_io_event* e, int fd, + pa_io_event_flags_t flags, void* userdata) { + pa_module* self = userdata; + struct userdata* u; + char x; + jack_ringbuffer_data_t buffer[2]; /* The write area in the ringbuffer may + be split in two parts. */ + pa_memchunk chunk; /* This is the data source. */ + unsigned part1_length, part2_length; + unsigned sample_idx_part1, sample_idx_part2; + unsigned chan; + unsigned frame_size; + int rem; + + assert(m); + assert(e); + assert(flags == PA_IO_EVENT_INPUT); + assert(self); + assert(self->userdata); + + u = self->userdata; + + assert(u->pipe_fds[0] == fd); + + pa_read(fd, &x, 1, &u->pipe_fd_type); + + if (u->quit_requested) { + pa_module_unload_request(self); + return; + } + + frame_size = u->frame_size; + + /* No blocksize changes during rendering, please. */ + pthread_mutex_lock(&u->buffersize_mutex); + + jack_ringbuffer_get_write_vector(u->ringbuffer, buffer); + assert(((buffer[0].len % sizeof(float)) == 0) || (buffer[1].len == 0)); + + part1_length = buffer[0].len / sizeof(float); + part2_length = buffer[1].len / sizeof(float); + + /* If the amount of free space is not a multiple of the frame size, we have + to adjust the lengths in order to not get confused with which sample is + which channel. */ + if ((rem = (part1_length + part2_length) % u->channels) != 0) { + if (part2_length >= rem) { + part2_length -= rem; + } else { + part1_length -= rem - part2_length; + part2_length = 0; + } + } + + /* pa_sink_render_full doesn't accept zero length, so we have do the + copying only if there's data to copy, which actually makes a kind of + sense. */ + if (part1_length > 0 || part2_length > 0) { + pa_sink_render_full(u->sink, + (part1_length + part2_length) * sizeof(float), + &chunk); + + /* Write to the first part of the buffer. */ + for (sample_idx_part1 = 0; + sample_idx_part1 < part1_length; + sample_idx_part1++) { + float *s = + ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + + sample_idx_part1; + float *d = ((float*) buffer[0].buf) + sample_idx_part1; + *d = *s; + } + + /* Write to the second part of the buffer. */ + for (sample_idx_part2 = 0; + sample_idx_part2 < part2_length; + sample_idx_part2++) { + float *s = + ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + + sample_idx_part1 + sample_idx_part2; + float *d = ((float*) buffer[1].buf) + sample_idx_part2; + *d = *s; + } + + pa_memblock_unref(chunk.memblock); + + jack_ringbuffer_write_advance( + u->ringbuffer, (part1_length + part2_length) * sizeof(float)); + } + + /* Blocksize can be changed again. */ + pthread_mutex_unlock(&u->buffersize_mutex); +} + + +static void* fill_ringbuffer(void* arg) { + struct userdata* u = arg; + + assert(u); + + while (!u->quit_requested) { + if (u->ringbuffer_is_full) { + pthread_mutex_lock(&u->cond_mutex); + pthread_cond_wait(&u->ringbuffer_cond, + &u->cond_mutex); + pthread_mutex_unlock(&u->cond_mutex); + } + /* No, it's not full yet, but this must be set to one as soon as + possible, because if the jack thread manages to process another + block before we set this to one, we may end up waiting without + a reason. */ + u->ringbuffer_is_full = 1; + + request_render(u); + } + + return NULL; +} + + +static void request_render(struct userdata* u) { + char c = 'x'; + + assert(u); + + assert(u->pipe_fds[1] >= 0); + pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type); +} + +void pa__done(pa_core* c, pa_module* self) { + struct userdata* u; + + assert(c); + assert(self); + + if (!self->userdata) return; - if (u->client) - jack_client_close(u->client); + u = self->userdata; + + if (u->filler_thread_is_running) { + u->quit_requested = 1; + pthread_cond_signal(&u->ringbuffer_cond); + pthread_join(u->filler_thread, NULL); + } + + if (u->j_client) + jack_client_close(u->j_client); if (u->io_event) c->mainloop->io_free(u->io_event); @@ -396,13 +866,18 @@ void pa__done(pa_core *c, pa_module*m) { pa_sink_disconnect(u->sink); pa_sink_unref(u->sink); } + + if (u->ringbuffer) + jack_ringbuffer_free(u->ringbuffer); if (u->pipe_fds[0] >= 0) - close(u->pipe_fds[0]); + pa_close(u->pipe_fds[0]); if (u->pipe_fds[1] >= 0) - close(u->pipe_fds[1]); - - pthread_mutex_destroy(&u->mutex); - pthread_cond_destroy(&u->cond); - pa_xfree(u); + pa_close(u->pipe_fds[1]); + + pthread_mutex_destroy(&u->buffersize_mutex); + pthread_cond_destroy(&u->ringbuffer_cond); + pthread_mutex_destroy(&u->cond_mutex); + pa_xfree(self->userdata); + self->userdata = NULL; } From 6687dd013169fd8436aa1b45ccdacff074a40d05 Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Fri, 24 Aug 2007 07:12:47 +0000 Subject: [PATCH 1372/1514] Corrected a bogus comment. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1716 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-jack-sink.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 09a72e3a6..a40ebe290 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -753,8 +753,7 @@ static void io_event_cb(pa_mainloop_api* m, pa_io_event* e, int fd, part2_length = buffer[1].len / sizeof(float); /* If the amount of free space is not a multiple of the frame size, we have - to adjust the lengths in order to not get confused with which sample is - which channel. */ + to truncate the lengths so that we process only complete frames. */ if ((rem = (part1_length + part2_length) % u->channels) != 0) { if (part2_length >= rem) { part2_length -= rem; From a67c21f093202f142438689d3f7cfbdf4ea82eea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 28 Oct 2007 19:13:50 +0000 Subject: [PATCH 1373/1514] merge 'lennart' branch back into trunk. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1971 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 6 + bootstrap.sh | 7 +- configure.ac | 233 +- libltdl/COPYING.LIB | 515 + libltdl/Makefile.am | 32 + libltdl/Makefile.in | 656 + libltdl/README | 10 + libltdl/acinclude.m4 | 7025 ++++++ libltdl/aclocal.m4 | 875 + libltdl/config-h.in | 195 + libltdl/config.guess | 1516 ++ libltdl/config.h | 196 + libltdl/config.sub | 1622 ++ libltdl/configure | 23853 ++++++++++++++++++ libltdl/configure.ac | 79 + libltdl/install-sh | 519 + libltdl/ltdl.c | 4530 ++++ libltdl/ltdl.h | 367 + libltdl/ltmain.sh | 6938 +++++ libltdl/missing | 360 + libltdl/mkinstalldirs | 161 + libltdl/stamp-h1 | 1 + pulseaudio-text.svg | 388 + src/Makefile.am | 249 +- src/daemon/caps.c | 13 +- src/daemon/cmdline.c | 37 +- src/daemon/cpulimit.c | 52 +- src/daemon/daemon-conf.c | 257 +- src/daemon/daemon-conf.h | 7 +- src/daemon/daemon.conf.in | 13 +- src/daemon/default.pa.in | 63 +- src/daemon/dumpmodules.c | 18 +- src/daemon/ltdl-bind-now.c | 160 + src/daemon/ltdl-bind-now.h | 32 + src/daemon/main.c | 162 +- src/daemon/pulseaudio-module-xsmp.desktop | 10 + src/modules/alsa-util.c | 202 +- src/modules/alsa-util.h | 9 +- src/modules/dbus-util.c | 325 +- src/modules/gconf/gconf-helper.c | 10 +- src/modules/gconf/module-gconf.c | 101 +- src/modules/ladspa.h | 603 + src/modules/module-alsa-sink.c | 1024 +- src/modules/module-alsa-source.c | 947 +- src/modules/module-cli.c | 30 +- src/modules/module-combine.c | 1112 +- src/modules/module-default-device-restore.c | 103 + src/modules/module-defs.h.m4 | 4 +- src/modules/module-detect.c | 47 +- src/modules/module-esound-compat-spawnfd.c | 17 +- src/modules/module-esound-compat-spawnpid.c | 14 +- src/modules/module-esound-sink.c | 479 +- src/modules/module-hal-detect.c | 886 +- src/modules/module-jack-sink.c | 1089 +- src/modules/module-jack-source.c | 315 +- src/modules/module-ladspa-sink.c | 673 + src/modules/module-lirc.c | 50 +- src/modules/module-match.c | 27 +- src/modules/module-mmkbd-evdev.c | 44 +- src/modules/module-native-protocol-fd.c | 19 +- src/modules/module-null-sink.c | 173 +- src/modules/module-oss-mmap.c | 637 - src/modules/module-oss.c | 1517 +- src/modules/module-pipe-sink.c | 291 +- src/modules/module-pipe-source.c | 258 +- src/modules/module-protocol-stub.c | 49 +- src/modules/module-remap-sink.c | 334 + src/modules/module-rescue-streams.c | 54 +- src/modules/module-sine.c | 83 +- src/modules/module-solaris.c | 768 +- src/modules/module-suspend-on-idle.c | 473 + src/modules/module-tunnel.c | 4 +- src/modules/module-volume-restore.c | 47 +- src/modules/module-x11-bell.c | 54 +- src/modules/module-x11-publish.c | 24 +- src/modules/module-x11-xsmp.c | 195 + src/modules/module-zeroconf-publish.c | 599 +- src/modules/oss-util.c | 136 +- src/modules/oss-util.h | 9 +- src/modules/rtp/module-rtp-recv.c | 333 +- src/modules/rtp/module-rtp-send.c | 122 +- src/modules/rtp/rtp.c | 101 +- src/modules/rtp/sap.c | 40 +- src/modules/rtp/sdp.c | 36 +- src/pulse/browser.c | 62 +- src/pulse/cdecl.h | 18 + src/pulse/channelmap.c | 108 +- src/pulse/channelmap.h | 9 +- src/pulse/client-conf-x11.c | 6 +- src/pulse/client-conf.c | 19 +- src/pulse/context.c | 198 +- src/pulse/glib-mainloop.c | 2 - src/pulse/internal.h | 9 +- src/pulse/introspect.c | 372 +- src/pulse/introspect.h | 16 + src/pulse/mainloop-api.c | 22 +- src/pulse/mainloop-signal.c | 55 +- src/pulse/mainloop.c | 173 +- src/pulse/operation.c | 41 +- src/pulse/sample.c | 77 +- src/pulse/sample.h | 18 +- src/pulse/scache.c | 17 +- src/pulse/simple.c | 49 +- src/pulse/simple.h | 2 +- src/pulse/stream.c | 319 +- src/pulse/subscribe.c | 19 +- src/pulse/thread-mainloop.c | 56 +- src/pulse/thread-mainloop.h | 3 + src/pulse/timeval.c | 59 +- src/pulse/timeval.h | 17 +- src/pulse/utf8.c | 32 +- src/pulse/utf8.h | 2 +- src/pulse/util.c | 42 +- src/pulse/util.h | 2 +- src/pulse/volume.c | 34 +- src/pulse/volume.h | 20 +- src/pulse/xmalloc.c | 14 +- src/pulse/xmalloc.h | 9 + src/pulsecore/anotify.c | 145 - src/pulsecore/asyncmsgq.c | 303 + src/pulsecore/asyncmsgq.h | 75 + src/pulsecore/asyncq.c | 213 + src/pulsecore/asyncq.h | 56 + src/pulsecore/atomic.h | 193 +- src/pulsecore/authkey-prop.c | 49 +- src/pulsecore/authkey.c | 80 +- src/pulsecore/autoload.c | 43 +- src/pulsecore/avahi-wrap.c | 52 +- src/pulsecore/cli-command.c | 497 +- src/pulsecore/cli-text.c | 122 +- src/pulsecore/cli.c | 30 +- src/pulsecore/client.c | 25 +- src/pulsecore/conf-parser.c | 35 +- src/pulsecore/core-def.h | 5 +- src/pulsecore/core-error.c | 178 +- src/pulsecore/core-scache.c | 94 +- src/pulsecore/core-scache.h | 1 + src/pulsecore/core-subscribe.c | 40 +- src/pulsecore/core-util.c | 639 +- src/pulsecore/core-util.h | 44 +- src/pulsecore/core.c | 73 +- src/pulsecore/core.h | 55 +- src/pulsecore/creds.h | 4 +- src/pulsecore/dynarray.c | 20 +- src/pulsecore/endianmacros.h | 78 +- src/pulsecore/esound.h | 2 +- src/pulsecore/fdsem.c | 276 + src/pulsecore/fdsem.h | 49 + src/pulsecore/ffmpeg/Makefile | 13 + src/pulsecore/ffmpeg/avcodec.h | 82 + src/pulsecore/ffmpeg/dsputil.h | 1 + src/pulsecore/ffmpeg/resample2.c | 324 + src/pulsecore/flist.c | 62 +- src/pulsecore/flist.h | 27 + src/pulsecore/g711.c | 392 +- src/pulsecore/gccmacro.h | 25 + src/pulsecore/hashmap.c | 39 +- src/pulsecore/hashmap.h | 4 +- src/pulsecore/hook-list.c | 26 +- src/pulsecore/idxset.c | 130 +- src/pulsecore/idxset.h | 5 - src/pulsecore/inet_ntop.c | 4 +- src/pulsecore/iochannel.c | 168 +- src/pulsecore/iochannel.h | 18 +- src/pulsecore/ioline.c | 95 +- src/pulsecore/ipacl.c | 24 +- src/pulsecore/llist.h | 119 +- src/pulsecore/log.c | 29 +- src/pulsecore/ltdl-helper.c | 64 + src/pulsecore/ltdl-helper.h | 34 + src/pulsecore/macro.h | 149 + src/pulsecore/mcalign.c | 49 +- src/pulsecore/memblock.c | 693 +- src/pulsecore/memblock.h | 61 +- src/pulsecore/memblockq.c | 331 +- src/pulsecore/memblockq.h | 22 +- src/pulsecore/memchunk.c | 52 +- src/pulsecore/memchunk.h | 11 +- src/pulsecore/modargs.c | 50 +- src/pulsecore/modargs.h | 4 +- src/pulsecore/modinfo.c | 31 +- src/pulsecore/modinfo.h | 2 +- src/pulsecore/module.c | 122 +- src/pulsecore/module.h | 10 +- src/pulsecore/msgobject.c | 49 + src/pulsecore/msgobject.h | 54 + src/pulsecore/mutex-posix.c | 70 +- src/pulsecore/mutex-win32.c | 2 +- src/pulsecore/mutex.h | 10 +- src/pulsecore/namereg.c | 35 +- src/pulsecore/native-common.h | 5 + src/pulsecore/object.c | 72 + src/pulsecore/object.h | 106 + src/pulsecore/once-posix.c | 71 - src/pulsecore/once-win32.c | 69 - src/pulsecore/once.c | 96 + src/pulsecore/once.h | 48 +- src/pulsecore/packet.c | 28 +- src/pulsecore/packet.h | 4 +- src/pulsecore/parseaddr.c | 14 +- src/pulsecore/pdispatch.c | 73 +- src/pulsecore/pid.c | 74 +- src/pulsecore/pipe.c | 14 +- src/pulsecore/play-memblockq.c | 224 +- src/pulsecore/play-memblockq.h | 10 + src/pulsecore/play-memchunk.c | 160 +- src/pulsecore/poll.c | 2 +- src/pulsecore/props.c | 43 +- src/pulsecore/protocol-cli.c | 22 +- src/pulsecore/protocol-esound.c | 644 +- src/pulsecore/protocol-http.c | 39 +- src/pulsecore/protocol-native.c | 1671 +- src/pulsecore/protocol-simple.c | 382 +- src/pulsecore/pstream-util.c | 24 +- src/pulsecore/pstream.c | 367 +- src/pulsecore/pstream.h | 8 +- src/pulsecore/queue.c | 52 +- src/pulsecore/random.c | 21 +- src/pulsecore/refcnt.h | 10 +- src/pulsecore/resampler.c | 1141 +- src/pulsecore/resampler.h | 31 +- src/pulsecore/rtclock.c | 98 + src/pulsecore/rtclock.h | 43 + src/pulsecore/rtpoll.c | 751 + src/pulsecore/rtpoll.h | 116 + src/pulsecore/rtsig.c | 133 + src/pulsecore/rtsig.h | 41 + src/pulsecore/sample-util.c | 288 +- src/pulsecore/sample-util.h | 10 +- src/pulsecore/sconv-s16be.c | 7 +- src/pulsecore/sconv-s16be.h | 15 +- src/pulsecore/sconv-s16le.c | 65 +- src/pulsecore/sconv-s16le.h | 15 +- src/pulsecore/sconv.c | 279 +- src/pulsecore/sconv.h | 10 +- src/pulsecore/semaphore-posix.c | 69 + src/pulsecore/semaphore-win32.c | 65 + src/pulsecore/{anotify.h => semaphore.h} | 19 +- src/pulsecore/shm.c | 247 +- src/pulsecore/shm.h | 2 + src/pulsecore/sink-input.c | 856 +- src/pulsecore/sink-input.h | 163 +- src/pulsecore/sink.c | 1034 +- src/pulsecore/sink.h | 153 +- src/pulsecore/sioman.c | 14 +- src/pulsecore/socket-client.c | 180 +- src/pulsecore/socket-server.c | 121 +- src/pulsecore/socket-util.c | 118 +- src/pulsecore/socket-util.h | 5 +- src/pulsecore/sound-file-stream.c | 249 +- src/pulsecore/sound-file.c | 71 +- src/pulsecore/source-output.c | 384 +- src/pulsecore/source-output.h | 97 +- src/pulsecore/source.c | 598 +- src/pulsecore/source.h | 136 +- src/pulsecore/speex/Makefile | 13 + src/pulsecore/speex/arch.h | 197 + src/pulsecore/speex/fixed_generic.h | 106 + src/pulsecore/speex/resample.c | 1114 + src/pulsecore/speex/speex_resampler.h | 328 + src/pulsecore/speexwrap.h | 48 + src/pulsecore/strbuf.c | 49 +- src/pulsecore/strlist.c | 39 +- src/pulsecore/tagstruct.c | 125 +- src/pulsecore/thread-mq.c | 112 + src/pulsecore/thread-mq.h | 49 + src/pulsecore/thread-posix.c | 59 +- src/pulsecore/thread-win32.c | 19 +- src/pulsecore/thread.h | 61 + src/pulsecore/time-smoother.c | 378 + src/pulsecore/time-smoother.h | 43 + src/pulsecore/tokenizer.c | 34 +- src/pulsecore/winsock.h | 2 + src/pulsecore/x11prop.c | 1 - src/pulsecore/x11wrap.c | 92 +- src/tests/asyncmsgq-test.c | 110 + src/tests/asyncq-test.c | 87 + src/tests/hook-list-test.c | 4 + src/tests/interpol-test.c | 2 +- src/tests/mcalign-test.c | 17 +- src/tests/memblock-test.c | 42 +- src/tests/memblockq-test.c | 20 +- src/tests/queue-test.c | 69 + src/tests/resampler-test.c | 227 + src/tests/rtpoll-test.c | 91 + src/tests/sig2str-test.c | 39 + src/tests/smoother-test.c | 80 + src/tests/thread-mainloop-test.c | 15 +- src/tests/thread-test.c | 6 +- src/utils/pactl.c | 123 +- src/utils/padsp.c | 71 +- src/utils/paplay.c | 2 +- src/utils/pasuspender.c | 316 + todo | 11 +- 294 files changed, 79057 insertions(+), 11614 deletions(-) create mode 100644 libltdl/COPYING.LIB create mode 100644 libltdl/Makefile.am create mode 100644 libltdl/Makefile.in create mode 100644 libltdl/README create mode 100644 libltdl/acinclude.m4 create mode 100644 libltdl/aclocal.m4 create mode 100644 libltdl/config-h.in create mode 100755 libltdl/config.guess create mode 100644 libltdl/config.h create mode 100755 libltdl/config.sub create mode 100755 libltdl/configure create mode 100644 libltdl/configure.ac create mode 100755 libltdl/install-sh create mode 100644 libltdl/ltdl.c create mode 100644 libltdl/ltdl.h create mode 100644 libltdl/ltmain.sh create mode 100755 libltdl/missing create mode 100755 libltdl/mkinstalldirs create mode 100644 libltdl/stamp-h1 create mode 100644 pulseaudio-text.svg create mode 100644 src/daemon/ltdl-bind-now.c create mode 100644 src/daemon/ltdl-bind-now.h create mode 100644 src/daemon/pulseaudio-module-xsmp.desktop create mode 100644 src/modules/ladspa.h create mode 100644 src/modules/module-default-device-restore.c create mode 100644 src/modules/module-ladspa-sink.c delete mode 100644 src/modules/module-oss-mmap.c create mode 100644 src/modules/module-remap-sink.c create mode 100644 src/modules/module-suspend-on-idle.c create mode 100644 src/modules/module-x11-xsmp.c delete mode 100644 src/pulsecore/anotify.c create mode 100644 src/pulsecore/asyncmsgq.c create mode 100644 src/pulsecore/asyncmsgq.h create mode 100644 src/pulsecore/asyncq.c create mode 100644 src/pulsecore/asyncq.h create mode 100644 src/pulsecore/fdsem.c create mode 100644 src/pulsecore/fdsem.h create mode 100644 src/pulsecore/ffmpeg/Makefile create mode 100644 src/pulsecore/ffmpeg/avcodec.h create mode 100644 src/pulsecore/ffmpeg/dsputil.h create mode 100644 src/pulsecore/ffmpeg/resample2.c create mode 100644 src/pulsecore/ltdl-helper.c create mode 100644 src/pulsecore/ltdl-helper.h create mode 100644 src/pulsecore/macro.h create mode 100644 src/pulsecore/msgobject.c create mode 100644 src/pulsecore/msgobject.h create mode 100644 src/pulsecore/object.c create mode 100644 src/pulsecore/object.h delete mode 100644 src/pulsecore/once-posix.c delete mode 100644 src/pulsecore/once-win32.c create mode 100644 src/pulsecore/once.c create mode 100644 src/pulsecore/rtclock.c create mode 100644 src/pulsecore/rtclock.h create mode 100644 src/pulsecore/rtpoll.c create mode 100644 src/pulsecore/rtpoll.h create mode 100644 src/pulsecore/rtsig.c create mode 100644 src/pulsecore/rtsig.h create mode 100644 src/pulsecore/semaphore-posix.c create mode 100644 src/pulsecore/semaphore-win32.c rename src/pulsecore/{anotify.h => semaphore.h} (64%) create mode 100644 src/pulsecore/speex/Makefile create mode 100644 src/pulsecore/speex/arch.h create mode 100644 src/pulsecore/speex/fixed_generic.h create mode 100644 src/pulsecore/speex/resample.c create mode 100644 src/pulsecore/speex/speex_resampler.h create mode 100644 src/pulsecore/speexwrap.h create mode 100644 src/pulsecore/thread-mq.c create mode 100644 src/pulsecore/thread-mq.h create mode 100644 src/pulsecore/time-smoother.c create mode 100644 src/pulsecore/time-smoother.h create mode 100644 src/tests/asyncmsgq-test.c create mode 100644 src/tests/asyncq-test.c create mode 100644 src/tests/queue-test.c create mode 100644 src/tests/resampler-test.c create mode 100644 src/tests/rtpoll-test.c create mode 100644 src/tests/sig2str-test.c create mode 100644 src/tests/smoother-test.c create mode 100644 src/utils/pasuspender.c diff --git a/Makefile.am b/Makefile.am index abc3d7760..288c24efa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,4 +48,10 @@ doxygen: eolspace: find \( -name '*.c' -o -name '*.h' -o -name 'Makefile.am' \) -exec perl -i -pe 's/\s+\n$$/\1\n/;' \{\} \; +untabify: + find \( -name '*.c' -o -name '*.h' \) -exec perl -i -pe 's/\t/ /g;' \{\} \; + +fedora-snapshot: dist + cp $(distdir).tar.gz $$HOME/cvs.fedora/pulseaudio/devel/$(distdir).svn`date +%Y%m%d`.tar.gz + .PHONY: homepage distcleancheck doxygen diff --git a/bootstrap.sh b/bootstrap.sh index b85f025eb..f23acbfef 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -25,10 +25,10 @@ run_versioned() { V=$(echo "$2" | sed -e 's,\.,,g') - if [ -e "`which $1$V`" ] ; then + if [ -e "`which $1$V 2> /dev/null`" ] ; then P="$1$V" else - if [ -e "`which $1-$2`" ] ; then + if [ -e "`which $1-$2 2> /dev/null`" ] ; then P="$1-$2" else P="$1" @@ -48,13 +48,14 @@ else rm -rf autom4te.cache rm -f config.cache + touch config.rpath test "x$LIBTOOLIZE" = "x" && LIBTOOLIZE=libtoolize "$LIBTOOLIZE" -c --force --ltdl run_versioned aclocal "$VERSION" run_versioned autoconf 2.59 -Wall run_versioned autoheader 2.59 - run_versioned automake "$VERSION" -a -c --foreign + run_versioned automake "$VERSION" --copy --foreign --add-missing if test "x$NOCONFIGURE" = "x"; then CFLAGS="-g -O0" ./configure --sysconfdir=/etc --localstatedir=/var --enable-force-preopen "$@" diff --git a/configure.ac b/configure.ac index a195da202..567dc4ede 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,7 @@ AC_PREREQ(2.57) m4_define(PA_MAJOR, [0]) m4_define(PA_MINOR, [9]) -m4_define(PA_MICRO, [6]) +m4_define(PA_MICRO, [7]) AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) AC_CONFIG_SRCDIR([src/daemon/main.c]) @@ -34,13 +34,13 @@ AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR") -AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/]) +AC_SUBST(PACKAGE_URL, [http://pulseaudio.org/]) AC_SUBST(PA_API_VERSION, 10) -AC_SUBST(PA_PROTOCOL_VERSION, 10) +AC_SUBST(PA_PROTOCOL_VERSION, 11) -AC_SUBST(LIBPULSE_VERSION_INFO, [2:0:2]) -AC_SUBST(LIBPULSECORE_VERSION_INFO, [3:0:0]) +AC_SUBST(LIBPULSE_VERSION_INFO, [3:0:3]) +AC_SUBST(LIBPULSECORE_VERSION_INFO, [4:0:0]) AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:0:0]) AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:0:1]) AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:2:0]) @@ -81,8 +81,8 @@ fi # GCC flags test_gcc_flag() { - AC_LANG_CONFTEST([int main() {}]) - $CC -c conftest.c $CFLAGS $@ > /dev/null 2> /dev/null + AC_LANG_CONFTEST([int main(int argc, char*argv[]) {}]) + $CC -c conftest.c $CFLAGS -o conftest.o > /dev/null 2> /dev/null ret=$? rm -f conftest.o return $ret @@ -93,28 +93,64 @@ if test "x$GCC" = "xyes" ; then # We use gnu99 instead of c99 because many have interpreted the standard # in a way that int64_t isn't defined on non-64 bit platforms. - DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter" + DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter -ffast-math" for flag in $DESIRED_FLAGS ; do AC_MSG_CHECKING([whether $CC accepts $flag]) - if test_gcc_flag $flag ; then + if test_gcc_flag $flag ; then CFLAGS="$CFLAGS $flag" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi - done + done +fi + +AC_MSG_CHECKING([whether $CC knows __sync_bool_compare_and_swap()]) +AC_LANG_CONFTEST([int main() { int a = 4; __sync_bool_compare_and_swap(&a, 4, 5); }]) +$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null +ret=$? +rm -f conftest.o conftest +if test $ret -eq 0 ; then + AC_DEFINE([HAVE_ATOMIC_BUILTINS], 1, [Have __sync_bool_compare_and_swap() and friends.]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +AC_MSG_CHECKING([whether $CC knows __thread]) +AC_LANG_CONFTEST([static __thread int a = 6; int main() { a = 5; }]) +$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null +ret=$? +rm -f conftest.o conftest +if test $ret -eq 0 ; then + AC_DEFINE([HAVE_TLS_BUILTIN], 1, [Have __thread().]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +AC_MSG_CHECKING([whether $CC knows _Bool]) +AC_LANG_CONFTEST([int main() { _Bool b; }]) +$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null +ret=$? +rm -f conftest.o conftest +if test $ret -eq 0 ; then + AC_DEFINE([HAVE_STD_BOOL], 1, [Have _Bool.]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) fi #### libtool stuff #### AC_LTDL_ENABLE_INSTALL AC_LIBLTDL_INSTALLABLE -AC_SUBST(LTDLINCL) -AC_SUBST(LIBLTDL) AC_LIBTOOL_DLOPEN AC_LIBTOOL_WIN32_DLL AC_PROG_LIBTOOL +AC_SUBST(LTDLINCL) +AC_SUBST(LIBLTDL) AC_CONFIG_SUBDIRS(libltdl) if test "x$enable_ltdl_install" = "xno" && test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then @@ -149,9 +185,9 @@ AC_HEADER_STDC # POSIX AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \ - netinet/in_systm.h netinet/tcp.h pwd.h sched.h \ + netinet/in_systm.h netinet/tcp.h poll.h pwd.h sched.h \ sys/mman.h sys/resource.h sys/select.h sys/socket.h sys/wait.h \ - syslog.h]) + syslog.h sys/dl.h dlfcn.h linux/sockios.h]) AC_CHECK_HEADERS([netinet/ip.h], [], [], [#include #if HAVE_NETINET_IN_H @@ -167,9 +203,6 @@ AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0]) AM_CONDITIONAL(HAVE_REGEX, test "x$HAVE_REGEX" = "x1") AM_CONDITIONAL(HAVE_AF_UNIX, test "x$HAVE_AF_UNIX" = "x1") -# XPG4-UNIX -AC_CHECK_HEADERS([sys/poll.h]) - # Linux AC_CHECK_HEADERS([linux/input.h], [HAVE_EVDEV=1], [HAVE_EVDEV=0]) @@ -185,6 +218,8 @@ AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h]) # Other AC_CHECK_HEADERS([sys/ioctl.h]) +AC_CHECK_HEADERS([byteswap.h]) +AC_CHECK_HEADERS([sys/syscall.h]) #### Typdefs, structures, etc. #### @@ -235,13 +270,17 @@ AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])]) #### Check for functions #### +# ISO +AC_CHECK_FUNCS([lrintf strtof]) + # POSIX AC_FUNC_FORK AC_FUNC_GETGROUPS AC_FUNC_SELECT_ARGTYPES -AC_CHECK_FUNCS([chmod chown getaddrinfo getgrgid_r getpwuid_r gettimeofday \ - getuid inet_ntop inet_pton nanosleep pipe posix_memalign setpgid setsid \ - shm_open sigaction sleep sysconf]) +AC_CHECK_FUNCS([chmod chown clock_gettime getaddrinfo getgrgid_r \ + getpwuid_r gettimeofday getuid inet_ntop inet_pton mlock nanosleep \ + pipe posix_fadvise posix_madvise posix_memalign setpgid setsid shm_open \ + sigaction sleep sysconf]) AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0]) AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1") @@ -260,7 +299,22 @@ AC_CHECK_FUNCS([lstat]) # Non-standard -AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid]) +AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid ppoll strsignal sig2str strtof_l]) + +AC_MSG_CHECKING([for PTHREAD_PRIO_INHERIT]) +AC_LANG_CONFTEST([AC_LANG_SOURCE([[ +#include +int main() { int i = PTHREAD_PRIO_INHERIT; }]])]) +$PTHREAD_CC conftest.c $PTHREAD_CFLAGS $CFLAGS $PTHREAD_LIBS -o conftest > /dev/null 2> /dev/null +ret=$? +rm -f conftest.o conftest + +if test $ret -eq 0 ; then + AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi #### Large File-Support (LFS) #### @@ -324,12 +378,6 @@ fi PKG_PROG_PKG_CONFIG -#### Sample rate conversion #### - -PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ]) -AC_SUBST(LIBSAMPLERATE_CFLAGS) -AC_SUBST(LIBSAMPLERATE_LIBS) - #### Sound file #### PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ]) @@ -347,10 +395,45 @@ if test "x$os_is_win32" != "x1" ; then LIBS="$LIBS -latomic_ops" fi +#### Libsamplerate support (optional) #### + +AC_ARG_ENABLE([samplerate], + AC_HELP_STRING([--disable-samplerate], [Disable optional libsamplerate support]), + [ + case "${enableval}" in + yes) samplerate=yes ;; + no) samplerate=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-samplerate) ;; + esac + ], + [samplerate=auto]) + +if test "x${samplerate}" != xno ; then + PKG_CHECK_MODULES(LIBSAMPLERATE, [ samplerate >= 0.1.0 ], + HAVE_LIBSAMPLERATE=1, + [ + HAVE_LIBSAMPLERATE=0 + if test "x$samplerate" = xyes ; then + AC_MSG_ERROR([*** Libsamplerate not found]) + fi + ]) +else + HAVE_LIBSAMPLERATE=0 +fi + +if test "x${HAVE_LIBSAMPLERATE}" = x1 ; then + AC_DEFINE([HAVE_LIBSAMPLERATE], 1, [Have libsamplerate?]) +fi + +AC_SUBST(LIBSAMPLERATE_CFLAGS) +AC_SUBST(LIBSAMPLERATE_LIBS) +AC_SUBST(HAVE_LIBSAMPLERATE) +AM_CONDITIONAL([HAVE_LIBSAMPLERATE], [test "x$HAVE_LIBSAMPLERATE" = x1]) + #### OSS support (optional) #### -AC_ARG_ENABLE([oss], - AC_HELP_STRING([--disable-oss], [Disable optional OSS support]), +AC_ARG_ENABLE([oss], + AC_HELP_STRING([--disable-oss], [Disable optional OSS support]), [ case "${enableval}" in yes) oss=yes ;; @@ -382,8 +465,8 @@ AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1]) #### ALSA support (optional) #### -AC_ARG_ENABLE([alsa], - AC_HELP_STRING([--disable-alsa], [Disable optional ALSA support]), +AC_ARG_ENABLE([alsa], + AC_HELP_STRING([--disable-alsa], [Disable optional ALSA support]), [ case "${enableval}" in yes) alsa=yes ;; @@ -410,14 +493,14 @@ else fi AC_SUBST(ASOUNDLIB_CFLAGS) -AC_SUBST(ASOUNDLIB_LIBS) +AC_SUBST(ASOUNDLIB_LIBS) AC_SUBST(HAVE_ALSA) AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1]) #### Solaris audio support (optional) #### -AC_ARG_ENABLE([solaris], - AC_HELP_STRING([--disable-solaris], [Disable optional Solaris audio support]), +AC_ARG_ENABLE([solaris], + AC_HELP_STRING([--disable-solaris], [Disable optional Solaris audio support]), [ case "${enableval}" in yes) solaris=yes ;; @@ -448,8 +531,8 @@ AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1]) #### GLib 2 support (optional) #### -AC_ARG_ENABLE([glib2], - AC_HELP_STRING([--disable-glib2], [Disable optional GLib 2 support]), +AC_ARG_ENABLE([glib2], + AC_HELP_STRING([--disable-glib2], [Disable optional GLib 2 support]), [ case "${enableval}" in yes) glib2=yes ;; @@ -479,8 +562,8 @@ AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1]) #### GConf support (optional) #### -AC_ARG_ENABLE([gconf], - AC_HELP_STRING([--disable-gconf], [Disable optional GConf support]), +AC_ARG_ENABLE([gconf], + AC_HELP_STRING([--disable-gconf], [Disable optional GConf support]), [ case "${enableval}" in yes) gconf=yes ;; @@ -510,8 +593,8 @@ AM_CONDITIONAL([HAVE_GCONF], [test "x$HAVE_GCONF" = x1]) #### Avahi support (optional) #### -AC_ARG_ENABLE([avahi], - AC_HELP_STRING([--disable-avahi], [Disable optional Avahi support]), +AC_ARG_ENABLE([avahi], + AC_HELP_STRING([--disable-avahi], [Disable optional Avahi support]), [ case "${enableval}" in yes) avahi=yes ;; @@ -547,8 +630,8 @@ AC_SUBST(LIBOIL_LIBS) ### JACK (optional) #### -AC_ARG_ENABLE([jack], - AC_HELP_STRING([--disable-jack], [Disable optional JACK support]), +AC_ARG_ENABLE([jack], + AC_HELP_STRING([--disable-jack], [Disable optional JACK support]), [ case "${enableval}" in yes) jack=yes ;; @@ -578,8 +661,8 @@ AM_CONDITIONAL([HAVE_JACK], [test "x$HAVE_JACK" = x1]) #### Async DNS support (optional) #### -AC_ARG_ENABLE([asyncns], - AC_HELP_STRING([--disable-asyncns], [Disable optional Async DNS support]), +AC_ARG_ENABLE([asyncns], + AC_HELP_STRING([--disable-asyncns], [Disable optional Async DNS support]), [ case "${enableval}" in yes) asyncns=yes ;; @@ -613,8 +696,8 @@ fi #### TCP wrappers (optional) #### -AC_ARG_ENABLE([tcpwrap], - AC_HELP_STRING([--disable-tcpwrap], [Disable optional TCP wrappers support]), +AC_ARG_ENABLE([tcpwrap], + AC_HELP_STRING([--disable-tcpwrap], [Disable optional TCP wrappers support]), [ case "${enableval}" in yes) tcpwrap=yes ;; @@ -637,8 +720,8 @@ AC_SUBST(LIBWRAP_LIBS) #### LIRC support (optional) #### -AC_ARG_ENABLE([lirc], - AC_HELP_STRING([--disable-lirc], [Disable optional LIRC support]), +AC_ARG_ENABLE([lirc], + AC_HELP_STRING([--disable-lirc], [Disable optional LIRC support]), [ case "${enableval}" in yes) lirc=yes ;; @@ -663,8 +746,8 @@ AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) #### HAL support (optional) #### -AC_ARG_ENABLE([hal], - AC_HELP_STRING([--disable-hal], [Disable optional HAL support]), +AC_ARG_ENABLE([hal], + AC_HELP_STRING([--disable-hal], [Disable optional HAL support]), [ case "${enableval}" in yes) hal=yes ;; @@ -673,7 +756,6 @@ AC_ARG_ENABLE([hal], esac ], [hal=auto]) - if test "x${hal}" != xno -a \( "x$HAVE_OSS" = "x1" -o "x$HAVE_ALSA" = "x1" \) ; then PKG_CHECK_MODULES(HAL, [ hal >= 0.5.7 ], HAVE_HAL=1, @@ -692,6 +774,49 @@ AC_SUBST(HAL_LIBS) AC_SUBST(HAVE_HAL) AM_CONDITIONAL([HAVE_HAL], [test "x$HAVE_HAL" = x1]) +#### D-Bus support (optional) #### + +AC_ARG_ENABLE([dbus], + AC_HELP_STRING([--disable-dbus], [Disable optional D-Bus support]), + [ + case "${enableval}" in + yes) dbus=yes ;; + no) dbus=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-dbus) ;; + esac + ], + [dbus=auto]) + +if test "x$HAVE_HAL" = x1 ; then + dbus=yes +fi + +if test "x${dbus}" != xno ; then + + PKG_CHECK_MODULES(DBUS, [ dbus-1 >= 1.0.0 ], + [ + HAVE_DBUS=1 + saved_LIBS="$LIBS" + LIBS="$LIBS $DBUS_LIBS" + AC_CHECK_FUNCS(dbus_watch_get_unix_fd) + LIBS="$saved_LIBS" + AC_DEFINE([HAVE_DBUS], 1, [Have D-Bus.]) + ], + [ + HAVE_DBUS=0 + if test "x$dbus" = xyes ; then + AC_MSG_ERROR([*** D-Bus support not found]) + fi + ]) +else + HAVE_DBUS=0 +fi + +AC_SUBST(DBUS_CFLAGS) +AC_SUBST(DBUS_LIBS) +AC_SUBST(HAVE_DBUS) +AM_CONDITIONAL([HAVE_DBUS], [test "x$HAVE_DBUS" = x1]) + #### PulseAudio system group & user ##### AC_ARG_WITH(system_user, AS_HELP_STRING([--with-system-user=],[User for running the PulseAudio daemon as a system-wide instance (pulse)])) @@ -845,6 +970,11 @@ if test "x${LIBWRAP_LIBS}" != x ; then ENABLE_TCPWRAP=yes fi +ENABLE_LIBSAMPLERATE=no +if test "x${HAVE_LIBSAMPLERATE}" = "x1" ; then + ENABLE_LIBSAMPLERATE=yes +fi + echo " ---{ $PACKAGE_NAME $VERSION }--- @@ -866,6 +996,7 @@ echo " Enable LIRC: ${ENABLE_LIRC} Enable HAL: ${ENABLE_HAL} Enable TCP Wrappers: ${ENABLE_TCPWRAP} + Enable libsamplerate: ${ENABLE_LIBSAMPLERATE} System User: ${PA_SYSTEM_USER} System Group: ${PA_SYSTEM_GROUP} Realtime Group: ${PA_REALTIME_GROUP} diff --git a/libltdl/COPYING.LIB b/libltdl/COPYING.LIB new file mode 100644 index 000000000..ba2be481c --- /dev/null +++ b/libltdl/COPYING.LIB @@ -0,0 +1,515 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. +^L + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. +^L + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. +^L + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. +^L + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. +^L + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. +^L + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. +^L + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS +^L + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper +mail. + +You should also get your employer (if you work as a programmer) or +your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James +Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/libltdl/Makefile.am b/libltdl/Makefile.am new file mode 100644 index 000000000..2a1e70198 --- /dev/null +++ b/libltdl/Makefile.am @@ -0,0 +1,32 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS = no-dependencies foreign + +if INSTALL_LTDL +include_HEADERS = ltdl.h +lib_LTLIBRARIES = libltdl.la +else +noinst_HEADERS = ltdl.h +endif + +if CONVENIENCE_LTDL +noinst_LTLIBRARIES = libltdlc.la +endif + +## Make sure these will be cleaned even when they're not built by +## default. +CLEANFILES = libltdl.la libltdlc.la + +libltdl_la_SOURCES = ltdl.c +libltdl_la_LDFLAGS = -no-undefined -version-info 4:5:1 +libltdl_la_LIBADD = $(LIBADD_DL) + +libltdlc_la_SOURCES = ltdl.c +libltdlc_la_LIBADD = $(LIBADD_DL) + +## Because we do not have automatic dependency tracking: +ltdl.lo: ltdl.h config.h + +$(libltdl_la_OBJECTS) $(libltdlc_la_OBJECTS): libtool +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck diff --git a/libltdl/Makefile.in b/libltdl/Makefile.in new file mode 100644 index 000000000..4319156ec --- /dev/null +++ b/libltdl/Makefile.in @@ -0,0 +1,656 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +DIST_COMMON = README $(am__configure_deps) $(am__include_HEADERS_DIST) \ + $(am__noinst_HEADERS_DIST) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config-h.in \ + $(top_srcdir)/configure COPYING.LIB config.guess config.sub \ + install-sh ltmain.sh missing mkinstalldirs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +libltdl_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libltdl_la_OBJECTS = ltdl.lo +libltdl_la_OBJECTS = $(am_libltdl_la_OBJECTS) +libltdl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libltdl_la_LDFLAGS) $(LDFLAGS) -o $@ +@INSTALL_LTDL_TRUE@am_libltdl_la_rpath = -rpath $(libdir) +libltdlc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libltdlc_la_OBJECTS = ltdl.lo +libltdlc_la_OBJECTS = $(am_libltdlc_la_OBJECTS) +@CONVENIENCE_LTDL_TRUE@am_libltdlc_la_rpath = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__depfiles_maybe = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libltdl_la_SOURCES) $(libltdlc_la_SOURCES) +DIST_SOURCES = $(libltdl_la_SOURCES) $(libltdlc_la_SOURCES) +am__include_HEADERS_DIST = ltdl.h +includeHEADERS_INSTALL = $(INSTALL_HEADER) +am__noinst_HEADERS_DIST = ltdl.h +HEADERS = $(include_HEADERS) $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d $(distdir) \ + || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr $(distdir); }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBADD_DL = @LIBADD_DL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = no-dependencies foreign +@INSTALL_LTDL_TRUE@include_HEADERS = ltdl.h +@INSTALL_LTDL_TRUE@lib_LTLIBRARIES = libltdl.la +@INSTALL_LTDL_FALSE@noinst_HEADERS = ltdl.h +@CONVENIENCE_LTDL_TRUE@noinst_LTLIBRARIES = libltdlc.la +CLEANFILES = libltdl.la libltdlc.la +libltdl_la_SOURCES = ltdl.c +libltdl_la_LDFLAGS = -no-undefined -version-info 4:5:1 +libltdl_la_LIBADD = $(LIBADD_DL) +libltdlc_la_SOURCES = ltdl.c +libltdlc_la_LIBADD = $(LIBADD_DL) +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ + cd $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config-h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config-h.in: $(am__configure_deps) + cd $(top_srcdir) && $(AUTOHEADER) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libltdl.la: $(libltdl_la_OBJECTS) $(libltdl_la_DEPENDENCIES) + $(libltdl_la_LINK) $(am_libltdl_la_rpath) $(libltdl_la_OBJECTS) $(libltdl_la_LIBADD) $(LIBS) +libltdlc.la: $(libltdlc_la_OBJECTS) $(libltdlc_la_DEPENDENCIES) + $(LINK) $(am_libltdlc_la_rpath) $(libltdlc_la_OBJECTS) $(libltdlc_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(COMPILE) -c $< + +.c.obj: + $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: + $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ + $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ + rm -f "$(DESTDIR)$(includedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) config-h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config-h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) config-h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config-h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d $(distdir) || mkdir $(distdir) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r $(distdir) +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && cd $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @cd $(distuninstallcheck_dir) \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-includeHEADERS + +install-dvi: install-dvi-am + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \ + clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES ctags dist dist-all dist-bzip2 \ + dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \ + distclean-compile distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-includeHEADERS install-info \ + install-info-am install-libLTLIBRARIES install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES + + +ltdl.lo: ltdl.h config.h + +$(libltdl_la_OBJECTS) $(libltdlc_la_OBJECTS): libtool +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libltdl/README b/libltdl/README new file mode 100644 index 000000000..da0a449ca --- /dev/null +++ b/libltdl/README @@ -0,0 +1,10 @@ +This is GNU libltdl, a system independent dlopen wrapper for GNU libtool. + +It supports the following dlopen interfaces: +* dlopen (Solaris, Linux and various BSD flavors) +* shl_load (HP-UX) +* LoadLibrary (Win16 and Win32) +* load_add_on (BeOS) +* GNU DLD (emulates dynamic linking for static libraries) +* dyld (darwin/Mac OS X) +* libtool's dlpreopen diff --git a/libltdl/acinclude.m4 b/libltdl/acinclude.m4 new file mode 100644 index 000000000..79d94868f --- /dev/null +++ b/libltdl/acinclude.m4 @@ -0,0 +1,7025 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 51 Debian 1.5.24-1 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# ------------------ +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# --------------------------------------------------------------------- +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ---------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +m4_if($1,[],[ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` + else + lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + sys_lib_search_path_spec=`echo $lt_search_path_spec` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[[3-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +# set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognize shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognize a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# ------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF + +# Report which library types will actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + interix[[3-9]]*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + # + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + if test "$solaris_use_stlport4" != yes; then + _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_AC_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac +])# AC_LIBTOOL_POSTDEP_PREDEP + +# AC_LIBTOOL_LANG_F77_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)]) +AC_DEFUN([_LT_AC_LANG_F77_CONFIG], +[AC_REQUIRE([AC_PROG_F77]) +AC_LANG_PUSH(Fortran 77) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="\ + subroutine t + return + end +" + +# Code to be used in simple link tests +lt_simple_link_test_code="\ + program t + end +" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +_LT_AC_TAGVAR(GCC, $1)="$G77" +_LT_AC_TAGVAR(LD, $1)="$LD" + +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_F77_CONFIG + + +# AC_LIBTOOL_LANG_GCJ_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)]) +AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], +[AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_GCJ_CONFIG + + +# AC_LIBTOOL_LANG_RC_CONFIG +# ------------------------- +# Ensure that the configuration vars for the Windows resource compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)]) +AC_DEFUN([_LT_AC_LANG_RC_CONFIG], +[AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_RC_CONFIG + + +# AC_LIBTOOL_CONFIG([TAGNAME]) +# ---------------------------- +# If TAGNAME is not passed, then create an initial libtool script +# with a default configuration from the untagged config vars. Otherwise +# add code to config.status for appending the configuration named by +# TAGNAME from the matching tagged config vars. +AC_DEFUN([AC_LIBTOOL_CONFIG], +[# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + _LT_AC_TAGVAR(compiler, $1) \ + _LT_AC_TAGVAR(CC, $1) \ + _LT_AC_TAGVAR(LD, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \ + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \ + _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \ + _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \ + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \ + _LT_AC_TAGVAR(old_archive_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \ + _LT_AC_TAGVAR(predep_objects, $1) \ + _LT_AC_TAGVAR(postdep_objects, $1) \ + _LT_AC_TAGVAR(predeps, $1) \ + _LT_AC_TAGVAR(postdeps, $1) \ + _LT_AC_TAGVAR(compiler_lib_search_path, $1) \ + _LT_AC_TAGVAR(archive_cmds, $1) \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ + _LT_AC_TAGVAR(postinstall_cmds, $1) \ + _LT_AC_TAGVAR(postuninstall_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \ + _LT_AC_TAGVAR(allow_undefined_flag, $1) \ + _LT_AC_TAGVAR(no_undefined_flag, $1) \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \ + _LT_AC_TAGVAR(hardcode_automatic, $1) \ + _LT_AC_TAGVAR(module_cmds, $1) \ + _LT_AC_TAGVAR(module_expsym_cmds, $1) \ + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ + _LT_AC_TAGVAR(fix_srcfile_path, $1) \ + _LT_AC_TAGVAR(exclude_expsyms, $1) \ + _LT_AC_TAGVAR(include_expsyms, $1); do + + case $var in + _LT_AC_TAGVAR(old_archive_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \ + _LT_AC_TAGVAR(archive_cmds, $1) | \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \ + _LT_AC_TAGVAR(module_cmds, $1) | \ + _LT_AC_TAGVAR(module_expsym_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\[$]0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'` + ;; + esac + +ifelse([$1], [], + [cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + AC_MSG_NOTICE([creating $ofile])], + [cfgfile="$ofile"]) + + cat <<__EOF__ >> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([LT_AC_PROG_SED]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux* | k*bsd*-gnu) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + esac + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + ;; + linux* | k*bsd*-gnu) + _LT_AC_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix[[3-9]]*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + *) + tmp_sharedflag='-shared' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=no + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + + +# Cheap backport of AS_EXECUTABLE_P and required macros +# from Autoconf 2.59; we should not use $as_executable_p directly. + +# _AS_TEST_PREPARE +# ---------------- +m4_ifndef([_AS_TEST_PREPARE], +[m4_defun([_AS_TEST_PREPARE], +[if test -x / >/dev/null 2>&1; then + as_executable_p='test -x' +else + as_executable_p='test -f' +fi +])])# _AS_TEST_PREPARE + +# AS_EXECUTABLE_P +# --------------- +# Check whether a file is executable. +m4_ifndef([AS_EXECUTABLE_P], +[m4_defun([AS_EXECUTABLE_P], +[AS_REQUIRE([_AS_TEST_PREPARE])dnl +$as_executable_p $1[]dnl +])])# AS_EXECUTABLE_P + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if AS_EXECUTABLE_P(["$as_dir/$lt_ac_prog$ac_exec_ext"]); then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +]) +## ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- +## Copyright (C) 1999-2006 Free Software Foundation, Inc. +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 8 AC_LIB_LTDL + +# AC_WITH_LTDL +# ------------ +# Clients of libltdl can use this macro to allow the installer to +# choose between a shipped copy of the ltdl sources or a preinstalled +# version of the library. +AC_DEFUN([AC_WITH_LTDL], +[AC_REQUIRE([AC_LIB_LTDL]) +AC_SUBST([LIBLTDL]) +AC_SUBST([INCLTDL]) + +# Unless the user asks us to check, assume no installed ltdl exists. +use_installed_libltdl=no + +AC_ARG_WITH([included_ltdl], + [ --with-included-ltdl use the GNU ltdl sources included here]) + +if test "x$with_included_ltdl" != xyes; then + # We are not being forced to use the included libltdl sources, so + # decide whether there is a useful installed version we can use. + AC_CHECK_HEADER([ltdl.h], + [AC_CHECK_LIB([ltdl], [lt_dlcaller_register], + [with_included_ltdl=no], + [with_included_ltdl=yes]) + ]) +fi + +if test "x$enable_ltdl_install" != xyes; then + # If the user did not specify an installable libltdl, then default + # to a convenience lib. + AC_LIBLTDL_CONVENIENCE +fi + +if test "x$with_included_ltdl" = xno; then + # If the included ltdl is not to be used. then Use the + # preinstalled libltdl we found. + AC_DEFINE([HAVE_LTDL], [1], + [Define this if a modern libltdl is already installed]) + LIBLTDL=-lltdl +fi + +# Report our decision... +AC_MSG_CHECKING([whether to use included libltdl]) +AC_MSG_RESULT([$with_included_ltdl]) + +AC_CONFIG_SUBDIRS([libltdl]) +])# AC_WITH_LTDL + + +# AC_LIB_LTDL +# ----------- +# Perform all the checks necessary for compilation of the ltdl objects +# -- including compiler checks and header checks. +AC_DEFUN([AC_LIB_LTDL], +[AC_PREREQ(2.50) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_C_CONST]) +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([AC_HEADER_DIRENT]) +AC_REQUIRE([_LT_AC_CHECK_DLFCN]) +AC_REQUIRE([AC_LTDL_ENABLE_INSTALL]) +AC_REQUIRE([AC_LTDL_SHLIBEXT]) +AC_REQUIRE([AC_LTDL_SHLIBPATH]) +AC_REQUIRE([AC_LTDL_SYSSEARCHPATH]) +AC_REQUIRE([AC_LTDL_OBJDIR]) +AC_REQUIRE([AC_LTDL_DLPREOPEN]) +AC_REQUIRE([AC_LTDL_DLLIB]) +AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) +AC_REQUIRE([AC_LTDL_DLSYM_USCORE]) +AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS]) +AC_REQUIRE([AC_LTDL_FUNC_ARGZ]) + +AC_CHECK_HEADERS([assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ + stdio.h unistd.h]) +AC_CHECK_HEADERS([dl.h sys/dl.h dld.h mach-o/dyld.h]) +AC_CHECK_HEADERS([string.h strings.h], [break]) + +AC_CHECK_FUNCS([strchr index], [break]) +AC_CHECK_FUNCS([strrchr rindex], [break]) +AC_CHECK_FUNCS([memcpy bcopy], [break]) +AC_CHECK_FUNCS([memmove strcmp]) +AC_CHECK_FUNCS([closedir opendir readdir]) +])# AC_LIB_LTDL + + +# AC_LTDL_ENABLE_INSTALL +# ---------------------- +AC_DEFUN([AC_LTDL_ENABLE_INSTALL], +[AC_ARG_ENABLE([ltdl-install], + [AC_HELP_STRING([--enable-ltdl-install], [install libltdl])]) + +AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) +AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno) +])# AC_LTDL_ENABLE_INSTALL + + +# AC_LTDL_SYS_DLOPEN_DEPLIBS +# -------------------------- +AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_CACHE_CHECK([whether deplibs are loaded by dlopen], + [libltdl_cv_sys_dlopen_deplibs], + [# PORTME does your system automatically load deplibs for dlopen? + # or its logical equivalent (e.g. shl_load for HP-UX < 11) + # For now, we just catch OSes we know something about -- in the + # future, we'll try test this programmatically. + libltdl_cv_sys_dlopen_deplibs=unknown + case "$host_os" in + aix3*|aix4.1.*|aix4.2.*) + # Unknown whether this is true for these versions of AIX, but + # we want this `case' here to explicitly catch those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + aix[[45]]*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + darwin*) + # Assuming the user has installed a libdl from somewhere, this is true + # If you are looking for one http://www.opendarwin.org/projects/dlcompat + libltdl_cv_sys_dlopen_deplibs=yes + ;; + freebsd* | dragonfly*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + gnu* | linux* | k*bsd*-gnu) + # GNU and its variants, using gnu ld.so (Glibc) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + hpux10*|hpux11*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + interix*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + irix[[12345]]*|irix6.[[01]]*) + # Catch all versions of IRIX before 6.2, and indicate that we don't + # know how it worked for any of those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + irix*) + # The case above catches anything before 6.2, and it's known that + # at 6.2 and later dlopen does load deplibs. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + netbsd* | netbsdelf*-gnu) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + openbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + osf[[1234]]*) + # dlopen did load deplibs (at least at 4.x), but until the 5.x series, + # it did *not* use an RPATH in a shared library to find objects the + # library depends on, so we explictly say `no'. + libltdl_cv_sys_dlopen_deplibs=no + ;; + osf5.0|osf5.0a|osf5.1) + # dlopen *does* load deplibs and with the right loader patch applied + # it even uses RPATH in a shared library to search for shared objects + # that the library depends on, but there's no easy way to know if that + # patch is installed. Since this is the case, all we can really + # say is unknown -- it depends on the patch being installed. If + # it is, this changes to `yes'. Without it, it would be `no'. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + osf*) + # the two cases above should catch all versions of osf <= 5.1. Read + # the comments above for what we know about them. + # At > 5.1, deplibs are loaded *and* any RPATH in a shared library + # is used to find them so we can finally say `yes'. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + solaris*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + esac + ]) +if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then + AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], + [Define if the OS needs help to load dependent libraries for dlopen().]) +fi +])# AC_LTDL_SYS_DLOPEN_DEPLIBS + + +# AC_LTDL_SHLIBEXT +# ---------------- +AC_DEFUN([AC_LTDL_SHLIBEXT], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([which extension is used for loadable modules], + [libltdl_cv_shlibext], +[ +module=yes +eval libltdl_cv_shlibext=$shrext_cmds + ]) +if test -n "$libltdl_cv_shlibext"; then + AC_DEFINE_UNQUOTED([LTDL_SHLIB_EXT], ["$libltdl_cv_shlibext"], + [Define to the extension used for shared libraries, say, ".so".]) +fi +])# AC_LTDL_SHLIBEXT + + +# AC_LTDL_SHLIBPATH +# ----------------- +AC_DEFUN([AC_LTDL_SHLIBPATH], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([which variable specifies run-time library path], + [libltdl_cv_shlibpath_var], [libltdl_cv_shlibpath_var="$shlibpath_var"]) +if test -n "$libltdl_cv_shlibpath_var"; then + AC_DEFINE_UNQUOTED([LTDL_SHLIBPATH_VAR], ["$libltdl_cv_shlibpath_var"], + [Define to the name of the environment variable that determines the dynamic library search path.]) +fi +])# AC_LTDL_SHLIBPATH + + +# AC_LTDL_SYSSEARCHPATH +# --------------------- +AC_DEFUN([AC_LTDL_SYSSEARCHPATH], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([for the default library search path], + [libltdl_cv_sys_search_path], + [libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"]) +if test -n "$libltdl_cv_sys_search_path"; then + sys_search_path= + for dir in $libltdl_cv_sys_search_path; do + if test -z "$sys_search_path"; then + sys_search_path="$dir" + else + sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" + fi + done + AC_DEFINE_UNQUOTED([LTDL_SYSSEARCHPATH], ["$sys_search_path"], + [Define to the system default library search path.]) +fi +])# AC_LTDL_SYSSEARCHPATH + + +# AC_LTDL_OBJDIR +# -------------- +AC_DEFUN([AC_LTDL_OBJDIR], +[AC_CACHE_CHECK([for objdir], + [libltdl_cv_objdir], + [libltdl_cv_objdir="$objdir" + if test -n "$objdir"; then + : + else + rm -f .libs 2>/dev/null + mkdir .libs 2>/dev/null + if test -d .libs; then + libltdl_cv_objdir=.libs + else + # MS-DOS does not allow filenames that begin with a dot. + libltdl_cv_objdir=_libs + fi + rmdir .libs 2>/dev/null + fi + ]) +AC_DEFINE_UNQUOTED([LTDL_OBJDIR], ["$libltdl_cv_objdir/"], + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# AC_LTDL_OBJDIR + + +# AC_LTDL_DLPREOPEN +# ----------------- +AC_DEFUN([AC_LTDL_DLPREOPEN], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) +AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], + [libltdl_cv_preloaded_symbols], + [if test -n "$lt_cv_sys_global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + ]) +if test x"$libltdl_cv_preloaded_symbols" = xyes; then + AC_DEFINE([HAVE_PRELOADED_SYMBOLS], [1], + [Define if libtool can extract symbol lists from object files.]) +fi +])# AC_LTDL_DLPREOPEN + + +# AC_LTDL_DLLIB +# ------------- +AC_DEFUN([AC_LTDL_DLLIB], +[LIBADD_DL= +AC_SUBST(LIBADD_DL) +AC_LANG_PUSH([C]) + +AC_CHECK_FUNC([shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.])], + [AC_CHECK_LIB([dld], [shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.]) + LIBADD_DL="$LIBADD_DL -ldld"], + [AC_CHECK_LIB([dl], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"], + [AC_TRY_LINK([#if HAVE_DLFCN_H +# include +#endif + ], + [dlopen(0, 0);], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"], + [AC_CHECK_LIB([svld], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"], + [AC_CHECK_LIB([dld], [dld_link], + [AC_DEFINE([HAVE_DLD], [1], + [Define if you have the GNU dld library.]) + LIBADD_DL="$LIBADD_DL -ldld"], + [AC_CHECK_FUNC([_dyld_func_lookup], + [AC_DEFINE([HAVE_DYLD], [1], + [Define if you have the _dyld_func_lookup function.])]) + ]) + ]) + ]) + ]) + ]) +]) + +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + AC_CHECK_FUNCS([dlerror]) + LIBS="$lt_save_LIBS" +fi +AC_LANG_POP +])# AC_LTDL_DLLIB + + +# AC_LTDL_SYMBOL_USCORE +# --------------------- +# does the compiler prefix global symbols with an underscore? +AC_DEFUN([AC_LTDL_SYMBOL_USCORE], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) +AC_CACHE_CHECK([for _ prefix in compiled symbols], + [ac_cv_sys_symbol_underscore], + [ac_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC + fi + else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC + fi + rm -rf conftest* + ]) +])# AC_LTDL_SYMBOL_USCORE + + +# AC_LTDL_DLSYM_USCORE +# -------------------- +AC_DEFUN([AC_LTDL_DLSYM_USCORE], +[AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + AC_CACHE_CHECK([whether we have to add an underscore for dlsym], + [libltdl_cv_need_uscore], + [libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + _LT_AC_TRY_DLOPEN_SELF( + [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], + [], [libltdl_cv_need_uscore=cross]) + LIBS="$save_LIBS" + ]) + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + AC_DEFINE([NEED_USCORE], [1], + [Define if dlsym() requires a leading underscore in symbol names.]) +fi +])# AC_LTDL_DLSYM_USCORE + +# AC_LTDL_FUNC_ARGZ +# ----------------- +AC_DEFUN([AC_LTDL_FUNC_ARGZ], +[AC_CHECK_HEADERS([argz.h]) + +AC_CHECK_TYPES([error_t], + [], + [AC_DEFINE([error_t], [int], + [Define to a type to use for `error_t' if it is not otherwise available.])], + [#if HAVE_ARGZ_H +# include +#endif]) + +AC_CHECK_FUNCS([argz_append argz_create_sep argz_insert argz_next argz_stringify]) +])# AC_LTDL_FUNC_ARGZ diff --git a/libltdl/aclocal.m4 b/libltdl/aclocal.m4 new file mode 100644 index 000000000..fcc414d3d --- /dev/null +++ b/libltdl/aclocal.m4 @@ -0,0 +1,875 @@ +# generated automatically by aclocal 1.10 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_if(m4_PACKAGE_VERSION, [2.61],, +[m4_fatal([this file was generated for autoconf 2.61. +You have another version of autoconf. If you want to use that, +you should regenerate the build system entirely.], [63])]) + +# Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.10' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.10], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.10])dnl +_AM_AUTOCONF_VERSION(m4_PACKAGE_VERSION)]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 8 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 3 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 8 + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 12 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.60])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $1 | $1:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 3 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 3 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputing VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([acinclude.m4]) diff --git a/libltdl/config-h.in b/libltdl/config-h.in new file mode 100644 index 000000000..b8640710f --- /dev/null +++ b/libltdl/config-h.in @@ -0,0 +1,195 @@ +/* config-h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `argz_append' function. */ +#undef HAVE_ARGZ_APPEND + +/* Define to 1 if you have the `argz_create_sep' function. */ +#undef HAVE_ARGZ_CREATE_SEP + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define to 1 if you have the `argz_insert' function. */ +#undef HAVE_ARGZ_INSERT + +/* Define to 1 if you have the `argz_next' function. */ +#undef HAVE_ARGZ_NEXT + +/* Define to 1 if you have the `argz_stringify' function. */ +#undef HAVE_ARGZ_STRINGIFY + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the `bcopy' function. */ +#undef HAVE_BCOPY + +/* Define to 1 if you have the `closedir' function. */ +#undef HAVE_CLOSEDIR + +/* Define to 1 if you have the header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define if you have the GNU dld library. */ +#undef HAVE_DLD + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLD_H + +/* Define to 1 if you have the `dlerror' function. */ +#undef HAVE_DLERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DL_H + +/* Define if you have the _dyld_func_lookup function. */ +#undef HAVE_DYLD + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if the system has the type `error_t'. */ +#undef HAVE_ERROR_T + +/* Define to 1 if you have the `index' function. */ +#undef HAVE_INDEX + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define if you have the libdl library or equivalent. */ +#undef HAVE_LIBDL + +/* Define to 1 if you have the header file. */ +#undef HAVE_MACH_O_DYLD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the `memcpy' function. */ +#undef HAVE_MEMCPY + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the `opendir' function. */ +#undef HAVE_OPENDIR + +/* Define if libtool can extract symbol lists from object files. */ +#undef HAVE_PRELOADED_SYMBOLS + +/* Define to 1 if you have the `readdir' function. */ +#undef HAVE_READDIR + +/* Define to 1 if you have the `rindex' function. */ +#undef HAVE_RINDEX + +/* Define if you have the shl_load function. */ +#undef HAVE_SHL_LOAD + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strcmp' function. */ +#undef HAVE_STRCMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_DL_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if the OS needs help to load dependent libraries for dlopen(). */ +#undef LTDL_DLOPEN_DEPLIBS + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LTDL_OBJDIR + +/* Define to the name of the environment variable that determines the dynamic + library search path. */ +#undef LTDL_SHLIBPATH_VAR + +/* Define to the extension used for shared libraries, say, ".so". */ +#undef LTDL_SHLIB_EXT + +/* Define to the system default library search path. */ +#undef LTDL_SYSSEARCHPATH + +/* Define if dlsym() requires a leading underscore in symbol names. */ +#undef NEED_USCORE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to a type to use for `error_t' if it is not otherwise available. */ +#undef error_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif diff --git a/libltdl/config.guess b/libltdl/config.guess new file mode 100755 index 000000000..0f0fe712a --- /dev/null +++ b/libltdl/config.guess @@ -0,0 +1,1516 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2007-03-06' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa:Linux:*:*) + echo xtensa-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/libltdl/config.h b/libltdl/config.h new file mode 100644 index 000000000..a04820a7a --- /dev/null +++ b/libltdl/config.h @@ -0,0 +1,196 @@ +/* config.h. Generated from config-h.in by configure. */ +/* config-h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `argz_append' function. */ +#define HAVE_ARGZ_APPEND 1 + +/* Define to 1 if you have the `argz_create_sep' function. */ +#define HAVE_ARGZ_CREATE_SEP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARGZ_H 1 + +/* Define to 1 if you have the `argz_insert' function. */ +#define HAVE_ARGZ_INSERT 1 + +/* Define to 1 if you have the `argz_next' function. */ +#define HAVE_ARGZ_NEXT 1 + +/* Define to 1 if you have the `argz_stringify' function. */ +#define HAVE_ARGZ_STRINGIFY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `bcopy' function. */ +/* #undef HAVE_BCOPY */ + +/* Define to 1 if you have the `closedir' function. */ +#define HAVE_CLOSEDIR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CTYPE_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define if you have the GNU dld library. */ +/* #undef HAVE_DLD */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLD_H */ + +/* Define to 1 if you have the `dlerror' function. */ +#define HAVE_DLERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DL_H */ + +/* Define if you have the _dyld_func_lookup function. */ +/* #undef HAVE_DYLD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if the system has the type `error_t'. */ +#define HAVE_ERROR_T 1 + +/* Define to 1 if you have the `index' function. */ +/* #undef HAVE_INDEX */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if you have the libdl library or equivalent. */ +#define HAVE_LIBDL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACH_O_DYLD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `memcpy' function. */ +#define HAVE_MEMCPY 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the `opendir' function. */ +#define HAVE_OPENDIR 1 + +/* Define if libtool can extract symbol lists from object files. */ +#define HAVE_PRELOADED_SYMBOLS 1 + +/* Define to 1 if you have the `readdir' function. */ +#define HAVE_READDIR 1 + +/* Define to 1 if you have the `rindex' function. */ +/* #undef HAVE_RINDEX */ + +/* Define if you have the shl_load function. */ +/* #undef HAVE_SHL_LOAD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strcmp' function. */ +#define HAVE_STRCMP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_DL_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if the OS needs help to load dependent libraries for dlopen(). */ +/* #undef LTDL_DLOPEN_DEPLIBS */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LTDL_OBJDIR ".libs/" + +/* Define to the name of the environment variable that determines the dynamic + library search path. */ +#define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH" + +/* Define to the extension used for shared libraries, say, ".so". */ +#define LTDL_SHLIB_EXT ".so" + +/* Define to the system default library search path. */ +#define LTDL_SYSSEARCHPATH "/lib:/usr/lib:/usr/lib/atlas:/usr/local/lib:/lib/i486-linux-gnu:/usr/lib/i486-linux-gnu:/usr/local/lib" + +/* Define if dlsym() requires a leading underscore in symbol names. */ +/* #undef NEED_USCORE */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bug-libtool@gnu.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libltdl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libltdl 1.2" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libltdl" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.2" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to a type to use for `error_t' if it is not otherwise available. */ +/* #undef error_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif diff --git a/libltdl/config.sub b/libltdl/config.sub new file mode 100755 index 000000000..5defff65a --- /dev/null +++ b/libltdl/config.sub @@ -0,0 +1,1622 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2007-01-18' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/libltdl/configure b/libltdl/configure new file mode 100755 index 000000000..aa2994e01 --- /dev/null +++ b/libltdl/configure @@ -0,0 +1,23853 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.61 for libltdl 1.2. +# +# Report bugs to . +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +echo=${ECHO-echo} +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL $0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + + +tagnames=${tagnames+${tagnames},}CXX + +tagnames=${tagnames+${tagnames},}F77 + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME='libltdl' +PACKAGE_TARNAME='libltdl' +PACKAGE_VERSION='1.2' +PACKAGE_STRING='libltdl 1.2' +PACKAGE_BUGREPORT='bug-libtool@gnu.org' + +ac_unique_file="ltdl.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +INSTALL_PROGRAM +INSTALL_SCRIPT +INSTALL_DATA +am__isrc +CYGPATH_W +PACKAGE +VERSION +ACLOCAL +AUTOCONF +AUTOMAKE +AUTOHEADER +MAKEINFO +install_sh +STRIP +INSTALL_STRIP_PROGRAM +mkdir_p +AWK +SET_MAKE +am__leading_dot +AMTAR +am__tar +am__untar +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +DEPDIR +am__include +am__quote +AMDEP_TRUE +AMDEP_FALSE +AMDEPBACKSLASH +CCDEPMODE +am__fastdepCC_TRUE +am__fastdepCC_FALSE +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +SED +GREP +EGREP +LN_S +ECHO +AR +RANLIB +DLLTOOL +AS +OBJDUMP +CPP +CXX +CXXFLAGS +ac_ct_CXX +CXXDEPMODE +am__fastdepCXX_TRUE +am__fastdepCXX_FALSE +CXXCPP +F77 +FFLAGS +ac_ct_F77 +LIBTOOL +LIBTOOL_DEPS +INSTALL_LTDL_TRUE +INSTALL_LTDL_FALSE +CONVENIENCE_LTDL_TRUE +CONVENIENCE_LTDL_FALSE +LIBADD_DL +LIBOBJS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +CXX +CXXFLAGS +CCC +CXXCPP +F77 +FFLAGS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures libltdl 1.2 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libltdl] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of libltdl 1.2:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-ltdl-install install libltdl + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-tags[=TAGS] include additional configurations [automatic] + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + F77 Fortran 77 compiler command + FFLAGS Fortran 77 compiler flags + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +libltdl configure 1.2 +generated by GNU Autoconf 2.61 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by libltdl $as_me 1.2, which was +generated by GNU Autoconf 2.61. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + +## ------------------------------- ## +## Libltdl specific configuration. ## +## ------------------------------- ## + +ac_aux_dir= +for ac_dir in . "$srcdir"/.; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in . \"$srcdir\"/." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in . \"$srcdir\"/." >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +if test -z "$enable_ltdl_install$enable_ltdl_convenience"; then + if test -f ${srcdir}/ltmain.sh; then + # if libltdl is libtoolized, it is assumed to be stand-alone and + # installed unless the command line overrides it (tested above) + enable_ltdl_install=yes + else + { echo "$as_me:$LINENO: WARNING: *** The top-level configure must select either" >&5 +echo "$as_me: WARNING: *** The top-level configure must select either" >&2;} + { echo "$as_me:$LINENO: WARNING: *** A\"\"C_LIBLTDL_INSTALLABLE or A\"\"C_LIBLTDL_CONVENIENCE." >&5 +echo "$as_me: WARNING: *** A\"\"C_LIBLTDL_INSTALLABLE or A\"\"C_LIBLTDL_CONVENIENCE." >&2;} + { { echo "$as_me:$LINENO: error: *** Maybe you want to --enable-ltdl-install?" >&5 +echo "$as_me: error: *** Maybe you want to --enable-ltdl-install?" >&2;} + { (exit 1); exit 1; }; } + fi +fi + + +## ------------------------ ## +## Automake Initialisation. ## +## ------------------------ ## +am__api_version='1.10' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done +IFS=$as_save_IFS + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm -f conftest.sed + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5 +echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; } +if test -z "$MKDIR_P"; then + if test "${ac_cv_path_mkdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done +done +IFS=$as_save_IFS + +fi + + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + test -d ./--version && rmdir ./--version + MKDIR_P="$ac_install_sh -d" + fi +fi +{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5 +echo "${ECHO_T}$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } +set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + SET_MAKE= +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE=libltdl + VERSION=1.2 + + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + +ac_config_headers="$ac_config_headers config.h:config-h.in" + + + +## ------------------ ## +## C compiler checks. ## +## ------------------ ## +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi + +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } +if test -z "$ac_file"; then + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +{ echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; } +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_const=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for inline" >&5 +echo $ECHO_N "checking for inline... $ECHO_C" >&6; } +if test "${ac_cv_c_inline+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_c_inline=$ac_kw +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 +echo "${ECHO_T}$ac_cv_c_inline" >&6; } + + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + + +## ----------------------- ## +## Libtool initialisation. ## +## ----------------------- ## + + +# Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + +# Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 +echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; } +if test "${lt_cv_path_SED+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$lt_ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$lt_ac_prog$ac_exec_ext"; }; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done + +fi + +SED=$lt_cv_path_SED + +{ echo "$as_me:$LINENO: result: $SED" >&5 +echo "${ECHO_T}$SED" >&6; } + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; } +else + { echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +echo "${ECHO_T}$LD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + +{ echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 +echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; } +if test "${lt_cv_ld_reload_flag+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 +echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 +echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; } +if test "${lt_cv_path_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi +fi +{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 +echo "${ECHO_T}$lt_cv_path_NM" >&6; } +NM="$lt_cv_path_NM" + +{ echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + { echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6; } +fi + +{ echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5 +echo $ECHO_N "checking how to recognize dependent libraries... $ECHO_C" >&6; } +if test "${lt_cv_deplibs_check_method+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 +echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; } +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 4531 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 +echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; } +if test "${lt_cv_cc_needs_belf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + lt_cv_cc_needs_belf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + lt_cv_cc_needs_belf=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 +echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-cygwin* | *-*-mingw* | *-*-pw32*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_DLLTOOL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { echo "$as_me:$LINENO: result: $DLLTOOL" >&5 +echo "${ECHO_T}$DLLTOOL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_DLLTOOL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { echo "$as_me:$LINENO: result: $ac_ct_DLLTOOL" >&5 +echo "${ECHO_T}$ac_ct_DLLTOOL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. +set dummy ${ac_tool_prefix}as; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AS+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AS="${ac_tool_prefix}as" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AS=$ac_cv_prog_AS +if test -n "$AS"; then + { echo "$as_me:$LINENO: result: $AS" >&5 +echo "${ECHO_T}$AS" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AS"; then + ac_ct_AS=$AS + # Extract the first word of "as", so it can be a program name with args. +set dummy as; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_AS+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AS"; then + ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AS="as" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_AS=$ac_cv_prog_ac_ct_AS +if test -n "$ac_ct_AS"; then + { echo "$as_me:$LINENO: result: $ac_ct_AS" >&5 +echo "${ECHO_T}$ac_ct_AS" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_AS" = x; then + AS="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + AS=$ac_ct_AS + fi +else + AS="$ac_cv_prog_AS" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_OBJDUMP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { echo "$as_me:$LINENO: result: $OBJDUMP" >&5 +echo "${ECHO_T}$OBJDUMP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5 +echo "${ECHO_T}$ac_ct_OBJDUMP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + + ;; + +esac + +need_locks="$enable_libtool_lock" + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in dlfcn.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ---------------------------------- ## +## Report this to bug-libtool@gnu.org ## +## ---------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CXXFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +depcc="$CXX" am_compiler_list= + +{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + + + +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +fi + + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$F77"; then + ac_cv_prog_F77="$F77" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_F77="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +F77=$ac_cv_prog_F77 +if test -n "$F77"; then + { echo "$as_me:$LINENO: result: $F77" >&5 +echo "${ECHO_T}$F77" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$F77" && break + done +fi +if test -z "$F77"; then + ac_ct_F77=$F77 + for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_F77"; then + ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_F77="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_F77=$ac_cv_prog_ac_ct_F77 +if test -n "$ac_ct_F77"; then + { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 +echo "${ECHO_T}$ac_ct_F77" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_F77" && break +done + + if test "x$ac_ct_F77" = x; then + F77="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + F77=$ac_ct_F77 + fi +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +rm -f a.out + +# If we don't use `.F' as extension, the preprocessor is not run on the +# input file. (Note that this only needs to work for GNU compilers.) +ac_save_ext=$ac_ext +ac_ext=F +{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; } +if test "${ac_cv_f77_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF + program main +#ifndef __GNUC__ + choke me +#endif + + end +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_f77_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_f77_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; } +ac_ext=$ac_save_ext +ac_test_FFLAGS=${FFLAGS+set} +ac_save_FFLAGS=$FFLAGS +FFLAGS= +{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 +echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_f77_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + FFLAGS=-g +cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_f77_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_f77_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_prog_f77_g=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 +echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; } +if test "$ac_test_FFLAGS" = set; then + FFLAGS=$ac_save_FFLAGS +elif test $ac_cv_prog_f77_g = yes; then + if test "x$ac_cv_f77_compiler_gnu" = xyes; then + FFLAGS="-g -O2" + else + FFLAGS="-g" + fi +else + if test "x$ac_cv_f77_compiler_gnu" = xyes; then + FFLAGS="-O2" + else + FFLAGS= + fi +fi + +G77=`test $ac_compiler_gnu = yes && echo yes` +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! + +# find the maximum length of command line arguments +{ echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 +echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; } +if test "${lt_cv_sys_max_cmd_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 +echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; } +else + { echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6; } +fi + + + + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 +echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux* | k*bsd*-gnu) + if test "$host_cpu" = ia64; then + symcode='[ABCDGIRSTW]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6; } +else + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } +fi + +{ echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } +if test "${lt_cv_objdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 +echo "${ECHO_T}$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 +echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { echo "$as_me:$LINENO: checking for file" >&5 +echo $ECHO_N "checking for file... $ECHO_C" >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +enable_dlopen=no +enable_win32_dll=yes + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' + + +{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7567: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:7571: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic='-qnocommon' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + esac + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7857: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:7861: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; } + +if test x"$lt_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works=yes + fi + else + lt_prog_compiler_static_works=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; } + +if test x"$lt_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7961: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:7965: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag= + enable_shared_with_static_runtimes=no + archive_cmds= + archive_expsym_cmds= + old_archive_From_new_cmds= + old_archive_from_expsyms_cmds= + export_dynamic_flag_spec= + whole_archive_flag_spec= + thread_safe_flag_spec= + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_direct=no + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + link_all_deplibs=unknown + hardcode_automatic=no + module_cmds= + module_expsym_cmds= + always_export_symbols=no + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + *) + tmp_sharedflag='-shared' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + link_all_deplibs=no + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='' + link_all_deplibs=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + hardcode_direct=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld='-rpath $libdir' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + link_all_deplibs=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs" >&5 +echo "${ECHO_T}$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc=no + else + archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 +echo "${ECHO_T}$archive_cmds_need_lc" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` + else + lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + sys_lib_search_path_spec=`echo $lt_search_path_spec` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var" || \ + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action" >&5 +echo "${ECHO_T}$hardcode_action" >&6; } + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +striplib= +old_striplib= +{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + ;; + *) + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + ;; + esac +fi + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + { echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shl_load to an innocuous variant, in case declares shl_load. + For example, HP-UX 11i declares gettimeofday. */ +#define shl_load innocuous_shl_load + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shl_load + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_shl_load || defined __stub___shl_load +choke me +#endif + +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } +if test $ac_cv_func_shl_load = yes; then + lt_cv_dlopen="shl_load" +else + { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } +if test $ac_cv_lib_dld_shl_load = yes; then + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" +else + { echo "$as_me:$LINENO: checking for dlopen" >&5 +echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } +if test "${ac_cv_func_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define dlopen to an innocuous variant, in case declares dlopen. + For example, HP-UX 11i declares gettimeofday. */ +#define dlopen innocuous_dlopen + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dlopen (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef dlopen + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_dlopen || defined __stub___dlopen +choke me +#endif + +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 +echo "${ECHO_T}$ac_cv_func_dlopen" >&6; } +if test $ac_cv_func_dlopen = yes; then + lt_cv_dlopen="dlopen" +else + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_svld_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } +if test $ac_cv_lib_svld_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_dld_link=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } +if test $ac_cv_lib_dld_dld_link = yes; then + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 +echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; } +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 +echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; } +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + +# Report which library types will actually be built +{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +{ echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +{ echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6; } + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler \ + CC \ + LD \ + lt_prog_compiler_wl \ + lt_prog_compiler_pic \ + lt_prog_compiler_static \ + lt_prog_compiler_no_builtin_flag \ + export_dynamic_flag_spec \ + thread_safe_flag_spec \ + whole_archive_flag_spec \ + enable_shared_with_static_runtimes \ + old_archive_cmds \ + old_archive_from_new_cmds \ + predep_objects \ + postdep_objects \ + predeps \ + postdeps \ + compiler_lib_search_path \ + archive_cmds \ + archive_expsym_cmds \ + postinstall_cmds \ + postuninstall_cmds \ + old_archive_from_expsyms_cmds \ + allow_undefined_flag \ + no_undefined_flag \ + export_symbols_cmds \ + hardcode_libdir_flag_spec \ + hardcode_libdir_flag_spec_ld \ + hardcode_libdir_separator \ + hardcode_automatic \ + module_cmds \ + module_expsym_cmds \ + lt_cv_prog_compiler_c_o \ + fix_srcfile_path \ + exclude_expsyms \ + include_expsyms; do + + case $var in + old_archive_cmds | \ + old_archive_from_new_cmds | \ + archive_cmds | \ + archive_expsym_cmds | \ + module_cmds | \ + module_expsym_cmds | \ + old_archive_from_expsyms_cmds | \ + export_symbols_cmds | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + { echo "$as_me:$LINENO: creating $ofile" >&5 +echo "$as_me: creating $ofile" >&6;} + + cat <<__EOF__ >> "$cfgfile" +#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU C compiler? +with_gcc=$GCC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# ### END LIBTOOL CONFIG + +__EOF__ + + + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + +# Check whether --with-tags was given. +if test "${with_tags+set}" = set; then + withval=$with_tags; tagnames="$withval" +fi + + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} + else + { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 +echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in + "") ;; + *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 +echo "$as_me: error: invalid tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 +echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} + { (exit 1); exit 1; }; } + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_flag_spec_ld_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[]) { return(0); }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +compiler_CXX=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' +else + lt_prog_compiler_no_builtin_flag_CXX= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; } +else + { echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +echo "${ECHO_T}$LD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } +ld_shlibs_CXX=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_CXX=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_CXX='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + archive_cmds_need_lc_CXX=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + whole_archive_flag_spec_CXX='' + link_all_deplibs_CXX=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_CXX=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + ld_shlibs_CXX=no + ;; + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + gnu*) + ;; + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) ;; + *) + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + interix[3-9]*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + hardcode_libdir_flag_spec_CXX='-R$libdir' + whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + else + ld_shlibs_CXX=no + fi + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; +esac +{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +GCC_CXX="$GXX" +LD_CXX="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... + +cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + # The `*' in the case matches for architectures that use `case' in + # $output_verbose_cmd can trigger glob expansion during the loop + # eval without this substitution. + output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` + + for p in `eval $output_verbose_link_cmd`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" \ + || test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX="${prev}${p}" + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX="${prev}${p}" + else + postdeps_CXX="${postdeps_CXX} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX="$p" + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX="$p" + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$rm -f confest.$objext + +# PORTME: override above test on systems where it is broken +case $host_os in +interix[3-9]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + # + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + +lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_CXX='-qnocommon' + lt_prog_compiler_wl_CXX='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:12847: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:12851: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_CXX=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; } + +if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_CXX=yes + fi + else + lt_prog_compiler_static_works_CXX=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; } + +if test x"$lt_prog_compiler_static_works_CXX" = xyes; then + : +else + lt_prog_compiler_static_CXX= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:12951: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:12955: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw*) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + ;; + linux* | k*bsd*-gnu) + link_all_deplibs_CXX=no + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_CXX=no + else + archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" + +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || \ + test -n "$runpath_var_CXX" || \ + test "X$hardcode_automatic_CXX" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_CXX" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 +echo "${ECHO_T}$hardcode_action_CXX" >&6; } + +if test "$hardcode_action_CXX" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_CXX \ + CC_CXX \ + LD_CXX \ + lt_prog_compiler_wl_CXX \ + lt_prog_compiler_pic_CXX \ + lt_prog_compiler_static_CXX \ + lt_prog_compiler_no_builtin_flag_CXX \ + export_dynamic_flag_spec_CXX \ + thread_safe_flag_spec_CXX \ + whole_archive_flag_spec_CXX \ + enable_shared_with_static_runtimes_CXX \ + old_archive_cmds_CXX \ + old_archive_from_new_cmds_CXX \ + predep_objects_CXX \ + postdep_objects_CXX \ + predeps_CXX \ + postdeps_CXX \ + compiler_lib_search_path_CXX \ + archive_cmds_CXX \ + archive_expsym_cmds_CXX \ + postinstall_cmds_CXX \ + postuninstall_cmds_CXX \ + old_archive_from_expsyms_cmds_CXX \ + allow_undefined_flag_CXX \ + no_undefined_flag_CXX \ + export_symbols_cmds_CXX \ + hardcode_libdir_flag_spec_CXX \ + hardcode_libdir_flag_spec_ld_CXX \ + hardcode_libdir_separator_CXX \ + hardcode_automatic_CXX \ + module_cmds_CXX \ + module_expsym_cmds_CXX \ + lt_cv_prog_compiler_c_o_CXX \ + fix_srcfile_path_CXX \ + exclude_expsyms_CXX \ + include_expsyms_CXX; do + + case $var in + old_archive_cmds_CXX | \ + old_archive_from_new_cmds_CXX | \ + archive_cmds_CXX | \ + archive_expsym_cmds_CXX | \ + module_cmds_CXX | \ + module_expsym_cmds_CXX | \ + old_archive_from_expsyms_cmds_CXX | \ + export_symbols_cmds_CXX | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_CXX + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_CXX +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_CXX + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld + + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu + + +archive_cmds_need_lc_F77=no +allow_undefined_flag_F77= +always_export_symbols_F77=no +archive_expsym_cmds_F77= +export_dynamic_flag_spec_F77= +hardcode_direct_F77=no +hardcode_libdir_flag_spec_F77= +hardcode_libdir_flag_spec_ld_F77= +hardcode_libdir_separator_F77= +hardcode_minus_L_F77=no +hardcode_automatic_F77=no +module_cmds_F77= +module_expsym_cmds_F77= +link_all_deplibs_F77=unknown +old_archive_cmds_F77=$old_archive_cmds +no_undefined_flag_F77= +whole_archive_flag_spec_F77= +enable_shared_with_static_runtimes_F77=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +objext_F77=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="\ + subroutine t + return + end +" + +# Code to be used in simple link tests +lt_simple_link_test_code="\ + program t + end +" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +compiler_F77=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +{ echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +{ echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6; } + +GCC_F77="$G77" +LD_F77="$LD" + +lt_prog_compiler_wl_F77= +lt_prog_compiler_pic_F77= +lt_prog_compiler_static_F77= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_static_F77='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_F77='-fno-common' + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_F77=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_F77=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_F77='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + else + lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_F77='-qnocommon' + lt_prog_compiler_wl_F77='-Wl,' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_F77='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_F77='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-fpic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_F77='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + lt_prog_compiler_wl_F77='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + lt_prog_compiler_wl_F77='' + ;; + esac + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_F77='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static_F77='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_F77='-Qoption ld ';; + *) + lt_prog_compiler_wl_F77='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl_F77='-Qoption ld ' + lt_prog_compiler_pic_F77='-PIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_F77='-Kconform_pic' + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_can_build_shared_F77=no + ;; + + uts4*) + lt_prog_compiler_pic_F77='-pic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_F77=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_F77"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_F77=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_F77" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:14528: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:14532: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_F77=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; } + +if test x"$lt_prog_compiler_pic_works_F77" = xyes; then + case $lt_prog_compiler_pic_F77 in + "" | " "*) ;; + *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; + esac +else + lt_prog_compiler_pic_F77= + lt_prog_compiler_can_build_shared_F77=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_F77= + ;; + *) + lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_F77=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_F77=yes + fi + else + lt_prog_compiler_static_works_F77=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; } + +if test x"$lt_prog_compiler_static_works_F77" = xyes; then + : +else + lt_prog_compiler_static_F77= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_F77=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:14632: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:14636: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_F77=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag_F77= + enable_shared_with_static_runtimes_F77=no + archive_cmds_F77= + archive_expsym_cmds_F77= + old_archive_From_new_cmds_F77= + old_archive_from_expsyms_cmds_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + thread_safe_flag_spec_F77= + hardcode_libdir_flag_spec_F77= + hardcode_libdir_flag_spec_ld_F77= + hardcode_libdir_separator_F77= + hardcode_direct_F77=no + hardcode_minus_L_F77=no + hardcode_shlibpath_var_F77=unsupported + link_all_deplibs_F77=unknown + hardcode_automatic_F77=no + module_cmds_F77= + module_expsym_cmds_F77= + always_export_symbols_F77=no + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_F77= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs_F77=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_F77='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_F77= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_F77=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs_F77=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_F77=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_F77='-L$libdir' + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=no + enable_shared_with_static_runtimes_F77=yes + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_F77=no + fi + ;; + + interix[3-9]*) + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec_F77='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + *) + tmp_sharedflag='-shared' ;; + esac + archive_cmds_F77='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + link_all_deplibs_F77=no + else + ld_shlibs_F77=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_F77=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_F77=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + + if test "$ld_shlibs_F77" = no; then + runpath_var= + hardcode_libdir_flag_spec_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=yes + archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_F77=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_F77=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_F77='' + hardcode_direct_F77=yes + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_F77=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_F77=yes + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_libdir_separator_F77= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_F77=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_F77='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_f77_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_F77="-z nodefs" + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_f77_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_F77=' ${wl}-bernotok' + allow_undefined_flag_F77=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_F77='$convenience' + archive_cmds_need_lc_F77=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_F77=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec_F77=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_F77=' ' + allow_undefined_flag_F77=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_F77='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_F77='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_F77='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_F77=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_F77=no + hardcode_direct_F77=no + hardcode_automatic_F77=yes + hardcode_shlibpath_var_F77=unsupported + whole_archive_flag_spec_F77='' + link_all_deplibs_F77=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_F77=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + freebsd1*) + ld_shlibs_F77=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_direct_F77=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_F77='+b $libdir' + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + ;; + *) + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + link_all_deplibs_F77=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + newsos6) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_shlibpath_var_F77=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + ;; + *) + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs_F77=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + allow_undefined_flag_F77=unsupported + archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_F77='-rpath $libdir' + fi + hardcode_libdir_separator_F77=: + ;; + + solaris*) + no_undefined_flag_F77=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_shlibpath_var_F77=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec_F77='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs_F77=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_F77='$CC -r -o $output$reload_objs' + hardcode_direct_F77=no + ;; + motorola) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_F77=no + ;; + + sysv4.3*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + export_dynamic_flag_spec_F77='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_F77=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_F77='${wl}-z,text' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_F77='${wl}-z,text' + allow_undefined_flag_F77='${wl}-z,nodefs' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + export_dynamic_flag_spec_F77='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + *) + ld_shlibs_F77=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 +echo "${ECHO_T}$ld_shlibs_F77" >&6; } +test "$ld_shlibs_F77" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_F77" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_F77=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_F77 in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_F77 + pic_flag=$lt_prog_compiler_pic_F77 + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_F77 + allow_undefined_flag_F77= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_F77=no + else + archive_cmds_need_lc_F77=yes + fi + allow_undefined_flag_F77=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" + +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_F77= +if test -n "$hardcode_libdir_flag_spec_F77" || \ + test -n "$runpath_var_F77" || \ + test "X$hardcode_automatic_F77" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_F77" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && + test "$hardcode_minus_L_F77" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_F77=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_F77=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_F77=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 +echo "${ECHO_T}$hardcode_action_F77" >&6; } + +if test "$hardcode_action_F77" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_F77 \ + CC_F77 \ + LD_F77 \ + lt_prog_compiler_wl_F77 \ + lt_prog_compiler_pic_F77 \ + lt_prog_compiler_static_F77 \ + lt_prog_compiler_no_builtin_flag_F77 \ + export_dynamic_flag_spec_F77 \ + thread_safe_flag_spec_F77 \ + whole_archive_flag_spec_F77 \ + enable_shared_with_static_runtimes_F77 \ + old_archive_cmds_F77 \ + old_archive_from_new_cmds_F77 \ + predep_objects_F77 \ + postdep_objects_F77 \ + predeps_F77 \ + postdeps_F77 \ + compiler_lib_search_path_F77 \ + archive_cmds_F77 \ + archive_expsym_cmds_F77 \ + postinstall_cmds_F77 \ + postuninstall_cmds_F77 \ + old_archive_from_expsyms_cmds_F77 \ + allow_undefined_flag_F77 \ + no_undefined_flag_F77 \ + export_symbols_cmds_F77 \ + hardcode_libdir_flag_spec_F77 \ + hardcode_libdir_flag_spec_ld_F77 \ + hardcode_libdir_separator_F77 \ + hardcode_automatic_F77 \ + module_cmds_F77 \ + module_expsym_cmds_F77 \ + lt_cv_prog_compiler_c_o_F77 \ + fix_srcfile_path_F77 \ + exclude_expsyms_F77 \ + include_expsyms_F77; do + + case $var in + old_archive_cmds_F77 | \ + old_archive_from_new_cmds_F77 | \ + archive_cmds_F77 | \ + archive_expsym_cmds_F77 | \ + module_cmds_F77 | \ + module_expsym_cmds_F77 | \ + old_archive_from_expsyms_cmds_F77 | \ + export_symbols_cmds_F77 | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_F77 + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_F77 + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_F77 + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_F77 + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_F77 + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_F77 +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_F77 + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_F77 +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_F77 +archive_expsym_cmds=$lt_archive_expsym_cmds_F77 +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_F77 +module_expsym_cmds=$lt_module_expsym_cmds_F77 + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_F77 + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_F77 + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_F77 + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_F77 + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_F77 + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_F77 + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_F77 + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_F77 + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_F77 + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_F77 + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_F77 + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_F77 + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_F77 + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_F77 + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +objext_GCJ=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +compiler_GCJ=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +archive_cmds_need_lc_GCJ=no + +old_archive_cmds_GCJ=$old_archive_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... + +lt_prog_compiler_no_builtin_flag_GCJ= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' + + +{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:16836: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:16840: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl_GCJ= +lt_prog_compiler_pic_GCJ= +lt_prog_compiler_static_GCJ= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_static_GCJ='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_GCJ='-fno-common' + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_GCJ=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_GCJ=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_GCJ='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + else + lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_GCJ='-qnocommon' + lt_prog_compiler_wl_GCJ='-Wl,' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-fpic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + lt_prog_compiler_wl_GCJ='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + lt_prog_compiler_wl_GCJ='' + ;; + esac + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_GCJ='-Qoption ld ';; + *) + lt_prog_compiler_wl_GCJ='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl_GCJ='-Qoption ld ' + lt_prog_compiler_pic_GCJ='-PIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_GCJ='-Kconform_pic' + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_can_build_shared_GCJ=no + ;; + + uts4*) + lt_prog_compiler_pic_GCJ='-pic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_GCJ=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_GCJ"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_GCJ=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_GCJ" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:17126: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:17130: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_GCJ=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; } + +if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then + case $lt_prog_compiler_pic_GCJ in + "" | " "*) ;; + *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; + esac +else + lt_prog_compiler_pic_GCJ= + lt_prog_compiler_can_build_shared_GCJ=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_GCJ= + ;; + *) + lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_GCJ=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_GCJ=yes + fi + else + lt_prog_compiler_static_works_GCJ=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; } + +if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then + : +else + lt_prog_compiler_static_GCJ= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_GCJ=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:17230: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:17234: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_GCJ=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag_GCJ= + enable_shared_with_static_runtimes_GCJ=no + archive_cmds_GCJ= + archive_expsym_cmds_GCJ= + old_archive_From_new_cmds_GCJ= + old_archive_from_expsyms_cmds_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + thread_safe_flag_spec_GCJ= + hardcode_libdir_flag_spec_GCJ= + hardcode_libdir_flag_spec_ld_GCJ= + hardcode_libdir_separator_GCJ= + hardcode_direct_GCJ=no + hardcode_minus_L_GCJ=no + hardcode_shlibpath_var_GCJ=unsupported + link_all_deplibs_GCJ=unknown + hardcode_automatic_GCJ=no + module_cmds_GCJ= + module_expsym_cmds_GCJ= + always_export_symbols_GCJ=no + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_GCJ= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs_GCJ=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_GCJ= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_GCJ=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs_GCJ=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_GCJ=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_GCJ='-L$libdir' + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=no + enable_shared_with_static_runtimes_GCJ=yes + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + interix[3-9]*) + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec_GCJ='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + *) + tmp_sharedflag='-shared' ;; + esac + archive_cmds_GCJ='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + link_all_deplibs_GCJ=no + else + ld_shlibs_GCJ=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_GCJ=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_GCJ=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + + if test "$ld_shlibs_GCJ" = no; then + runpath_var= + hardcode_libdir_flag_spec_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=yes + archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_GCJ=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_GCJ=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_GCJ='' + hardcode_direct_GCJ=yes + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_GCJ=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_GCJ=yes + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_libdir_separator_GCJ= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_GCJ=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_GCJ='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_GCJ="-z nodefs" + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_GCJ=' ${wl}-bernotok' + allow_undefined_flag_GCJ=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_GCJ='$convenience' + archive_cmds_need_lc_GCJ=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_GCJ=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec_GCJ=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_GCJ=' ' + allow_undefined_flag_GCJ=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_GCJ='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_GCJ='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_GCJ=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_GCJ=no + hardcode_direct_GCJ=no + hardcode_automatic_GCJ=yes + hardcode_shlibpath_var_GCJ=unsupported + whole_archive_flag_spec_GCJ='' + link_all_deplibs_GCJ=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_GCJ=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + freebsd1*) + ld_shlibs_GCJ=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_direct_GCJ=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + ;; + *) + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + link_all_deplibs_GCJ=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + newsos6) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_shlibpath_var_GCJ=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + ;; + *) + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs_GCJ=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + allow_undefined_flag_GCJ=unsupported + archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_GCJ='-rpath $libdir' + fi + hardcode_libdir_separator_GCJ=: + ;; + + solaris*) + no_undefined_flag_GCJ=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_shlibpath_var_GCJ=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs_GCJ=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_GCJ='$CC -r -o $output$reload_objs' + hardcode_direct_GCJ=no + ;; + motorola) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4.3*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + export_dynamic_flag_spec_GCJ='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_GCJ=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_GCJ='${wl}-z,text' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_GCJ='${wl}-z,text' + allow_undefined_flag_GCJ='${wl}-z,nodefs' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + *) + ld_shlibs_GCJ=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 +echo "${ECHO_T}$ld_shlibs_GCJ" >&6; } +test "$ld_shlibs_GCJ" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_GCJ" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_GCJ=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_GCJ in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_GCJ + pic_flag=$lt_prog_compiler_pic_GCJ + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ + allow_undefined_flag_GCJ= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_GCJ=no + else + archive_cmds_need_lc_GCJ=yes + fi + allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" + +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_GCJ= +if test -n "$hardcode_libdir_flag_spec_GCJ" || \ + test -n "$runpath_var_GCJ" || \ + test "X$hardcode_automatic_GCJ" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_GCJ" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && + test "$hardcode_minus_L_GCJ" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_GCJ=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_GCJ=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_GCJ=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 +echo "${ECHO_T}$hardcode_action_GCJ" >&6; } + +if test "$hardcode_action_GCJ" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_GCJ \ + CC_GCJ \ + LD_GCJ \ + lt_prog_compiler_wl_GCJ \ + lt_prog_compiler_pic_GCJ \ + lt_prog_compiler_static_GCJ \ + lt_prog_compiler_no_builtin_flag_GCJ \ + export_dynamic_flag_spec_GCJ \ + thread_safe_flag_spec_GCJ \ + whole_archive_flag_spec_GCJ \ + enable_shared_with_static_runtimes_GCJ \ + old_archive_cmds_GCJ \ + old_archive_from_new_cmds_GCJ \ + predep_objects_GCJ \ + postdep_objects_GCJ \ + predeps_GCJ \ + postdeps_GCJ \ + compiler_lib_search_path_GCJ \ + archive_cmds_GCJ \ + archive_expsym_cmds_GCJ \ + postinstall_cmds_GCJ \ + postuninstall_cmds_GCJ \ + old_archive_from_expsyms_cmds_GCJ \ + allow_undefined_flag_GCJ \ + no_undefined_flag_GCJ \ + export_symbols_cmds_GCJ \ + hardcode_libdir_flag_spec_GCJ \ + hardcode_libdir_flag_spec_ld_GCJ \ + hardcode_libdir_separator_GCJ \ + hardcode_automatic_GCJ \ + module_cmds_GCJ \ + module_expsym_cmds_GCJ \ + lt_cv_prog_compiler_c_o_GCJ \ + fix_srcfile_path_GCJ \ + exclude_expsyms_GCJ \ + include_expsyms_GCJ; do + + case $var in + old_archive_cmds_GCJ | \ + old_archive_from_new_cmds_GCJ | \ + archive_cmds_GCJ | \ + archive_expsym_cmds_GCJ | \ + module_cmds_GCJ | \ + module_expsym_cmds_GCJ | \ + old_archive_from_expsyms_cmds_GCJ | \ + export_symbols_cmds_GCJ | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_GCJ + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_GCJ + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_GCJ + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_GCJ + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_GCJ + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_GCJ +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_GCJ + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_GCJ +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_GCJ +archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_GCJ +module_expsym_cmds=$lt_module_expsym_cmds_GCJ + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_GCJ + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_GCJ + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_GCJ + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_GCJ + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_GCJ + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_GCJ + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_GCJ + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_GCJ + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_GCJ + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_GCJ + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_GCJ + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_GCJ + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_GCJ + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + RC) + + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +objext_RC=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +compiler_RC=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + +lt_cv_prog_compiler_c_o_RC=yes + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_RC \ + CC_RC \ + LD_RC \ + lt_prog_compiler_wl_RC \ + lt_prog_compiler_pic_RC \ + lt_prog_compiler_static_RC \ + lt_prog_compiler_no_builtin_flag_RC \ + export_dynamic_flag_spec_RC \ + thread_safe_flag_spec_RC \ + whole_archive_flag_spec_RC \ + enable_shared_with_static_runtimes_RC \ + old_archive_cmds_RC \ + old_archive_from_new_cmds_RC \ + predep_objects_RC \ + postdep_objects_RC \ + predeps_RC \ + postdeps_RC \ + compiler_lib_search_path_RC \ + archive_cmds_RC \ + archive_expsym_cmds_RC \ + postinstall_cmds_RC \ + postuninstall_cmds_RC \ + old_archive_from_expsyms_cmds_RC \ + allow_undefined_flag_RC \ + no_undefined_flag_RC \ + export_symbols_cmds_RC \ + hardcode_libdir_flag_spec_RC \ + hardcode_libdir_flag_spec_ld_RC \ + hardcode_libdir_separator_RC \ + hardcode_automatic_RC \ + module_cmds_RC \ + module_expsym_cmds_RC \ + lt_cv_prog_compiler_c_o_RC \ + fix_srcfile_path_RC \ + exclude_expsyms_RC \ + include_expsyms_RC; do + + case $var in + old_archive_cmds_RC | \ + old_archive_from_new_cmds_RC | \ + archive_cmds_RC | \ + archive_expsym_cmds_RC | \ + module_cmds_RC | \ + module_expsym_cmds_RC | \ + old_archive_from_expsyms_cmds_RC | \ + export_symbols_cmds_RC | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_RC + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_RC + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_RC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_RC + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_RC + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_RC +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_RC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_RC +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_RC +archive_expsym_cmds=$lt_archive_expsym_cmds_RC +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_RC +module_expsym_cmds=$lt_module_expsym_cmds_RC + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_RC + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_RC + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_RC + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_RC + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_RC + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_RC + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_RC + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_RC + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_RC + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_RC + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_RC + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_RC + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_RC + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_RC + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_RC + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + ;; + + *) + { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 +echo "$as_me: error: Unsupported tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 +echo "$as_me: error: unable to update list of available tagged configurations." >&2;} + { (exit 1); exit 1; }; } + fi +fi + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Prevent multiple expansion + + + + + + + + + + + + + + + + + + + + + + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +# Check whether --enable-ltdl-install was given. +if test "${enable_ltdl_install+set}" = set; then + enableval=$enable_ltdl_install; +fi + + + if test x"${enable_ltdl_install-no}" != xno; then + INSTALL_LTDL_TRUE= + INSTALL_LTDL_FALSE='#' +else + INSTALL_LTDL_TRUE='#' + INSTALL_LTDL_FALSE= +fi + + if test x"${enable_ltdl_convenience-no}" != xno; then + CONVENIENCE_LTDL_TRUE= + CONVENIENCE_LTDL_FALSE='#' +else + CONVENIENCE_LTDL_TRUE='#' + CONVENIENCE_LTDL_FALSE= +fi + + + +{ echo "$as_me:$LINENO: checking which extension is used for loadable modules" >&5 +echo $ECHO_N "checking which extension is used for loadable modules... $ECHO_C" >&6; } +if test "${libltdl_cv_shlibext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +module=yes +eval libltdl_cv_shlibext=$shrext_cmds + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibext" >&5 +echo "${ECHO_T}$libltdl_cv_shlibext" >&6; } +if test -n "$libltdl_cv_shlibext"; then + +cat >>confdefs.h <<_ACEOF +#define LTDL_SHLIB_EXT "$libltdl_cv_shlibext" +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking which variable specifies run-time library path" >&5 +echo $ECHO_N "checking which variable specifies run-time library path... $ECHO_C" >&6; } +if test "${libltdl_cv_shlibpath_var+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_shlibpath_var="$shlibpath_var" +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibpath_var" >&5 +echo "${ECHO_T}$libltdl_cv_shlibpath_var" >&6; } +if test -n "$libltdl_cv_shlibpath_var"; then + +cat >>confdefs.h <<_ACEOF +#define LTDL_SHLIBPATH_VAR "$libltdl_cv_shlibpath_var" +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking for the default library search path" >&5 +echo $ECHO_N "checking for the default library search path... $ECHO_C" >&6; } +if test "${libltdl_cv_sys_search_path+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec" +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_search_path" >&5 +echo "${ECHO_T}$libltdl_cv_sys_search_path" >&6; } +if test -n "$libltdl_cv_sys_search_path"; then + sys_search_path= + for dir in $libltdl_cv_sys_search_path; do + if test -z "$sys_search_path"; then + sys_search_path="$dir" + else + sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" + fi + done + +cat >>confdefs.h <<_ACEOF +#define LTDL_SYSSEARCHPATH "$sys_search_path" +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } +if test "${libltdl_cv_objdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_objdir="$objdir" + if test -n "$objdir"; then + : + else + rm -f .libs 2>/dev/null + mkdir .libs 2>/dev/null + if test -d .libs; then + libltdl_cv_objdir=.libs + else + # MS-DOS does not allow filenames that begin with a dot. + libltdl_cv_objdir=_libs + fi + rmdir .libs 2>/dev/null + fi + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_objdir" >&5 +echo "${ECHO_T}$libltdl_cv_objdir" >&6; } + +cat >>confdefs.h <<_ACEOF +#define LTDL_OBJDIR "$libltdl_cv_objdir/" +_ACEOF + + + +{ echo "$as_me:$LINENO: checking whether libtool supports -dlopen/-dlpreopen" >&5 +echo $ECHO_N "checking whether libtool supports -dlopen/-dlpreopen... $ECHO_C" >&6; } +if test "${libltdl_cv_preloaded_symbols+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$lt_cv_sys_global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_preloaded_symbols" >&5 +echo "${ECHO_T}$libltdl_cv_preloaded_symbols" >&6; } +if test x"$libltdl_cv_preloaded_symbols" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PRELOADED_SYMBOLS 1 +_ACEOF + +fi + +LIBADD_DL= + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shl_load to an innocuous variant, in case declares shl_load. + For example, HP-UX 11i declares gettimeofday. */ +#define shl_load innocuous_shl_load + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shl_load + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_shl_load || defined __stub___shl_load +choke me +#endif + +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } +if test $ac_cv_func_shl_load = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SHL_LOAD 1 +_ACEOF + +else + { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } +if test $ac_cv_lib_dld_shl_load = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SHL_LOAD 1 +_ACEOF + + LIBADD_DL="$LIBADD_DL -ldld" +else + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes" +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if HAVE_DLFCN_H +# include +#endif + +int +main () +{ +dlopen(0, 0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + libltdl_cv_func_dlopen="yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_svld_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } +if test $ac_cv_lib_svld_dlopen = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes" +else + { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_dld_link=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } +if test $ac_cv_lib_dld_dld_link = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DLD 1 +_ACEOF + + LIBADD_DL="$LIBADD_DL -ldld" +else + { echo "$as_me:$LINENO: checking for _dyld_func_lookup" >&5 +echo $ECHO_N "checking for _dyld_func_lookup... $ECHO_C" >&6; } +if test "${ac_cv_func__dyld_func_lookup+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define _dyld_func_lookup to an innocuous variant, in case declares _dyld_func_lookup. + For example, HP-UX 11i declares gettimeofday. */ +#define _dyld_func_lookup innocuous__dyld_func_lookup + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char _dyld_func_lookup (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef _dyld_func_lookup + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _dyld_func_lookup (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub__dyld_func_lookup || defined __stub____dyld_func_lookup +choke me +#endif + +int +main () +{ +return _dyld_func_lookup (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func__dyld_func_lookup=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func__dyld_func_lookup=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func__dyld_func_lookup" >&5 +echo "${ECHO_T}$ac_cv_func__dyld_func_lookup" >&6; } +if test $ac_cv_func__dyld_func_lookup = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DYLD 1 +_ACEOF + +fi + + +fi + + +fi + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + +fi + + +fi + + +fi + + +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + +for ac_func in dlerror +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + LIBS="$lt_save_LIBS" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +{ echo "$as_me:$LINENO: checking for _ prefix in compiled symbols" >&5 +echo $ECHO_N "checking for _ prefix in compiled symbols... $ECHO_C" >&6; } +if test "${ac_cv_sys_symbol_underscore+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&5 + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 + fi + rm -rf conftest* + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_sys_symbol_underscore" >&5 +echo "${ECHO_T}$ac_cv_sys_symbol_underscore" >&6; } + + +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + { echo "$as_me:$LINENO: checking whether we have to add an underscore for dlsym" >&5 +echo $ECHO_N "checking whether we have to add an underscore for dlsym... $ECHO_C" >&6; } +if test "${libltdl_cv_need_uscore+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + if test "$cross_compiling" = yes; then : + libltdl_cv_need_uscore=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;; + x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;; + x$lt_dlunknown|x*) ;; + esac + else : + # compilation failed + + fi +fi +rm -fr conftest* + + LIBS="$save_LIBS" + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_need_uscore" >&5 +echo "${ECHO_T}$libltdl_cv_need_uscore" >&6; } + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define NEED_USCORE 1 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking whether deplibs are loaded by dlopen" >&5 +echo $ECHO_N "checking whether deplibs are loaded by dlopen... $ECHO_C" >&6; } +if test "${libltdl_cv_sys_dlopen_deplibs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # PORTME does your system automatically load deplibs for dlopen? + # or its logical equivalent (e.g. shl_load for HP-UX < 11) + # For now, we just catch OSes we know something about -- in the + # future, we'll try test this programmatically. + libltdl_cv_sys_dlopen_deplibs=unknown + case "$host_os" in + aix3*|aix4.1.*|aix4.2.*) + # Unknown whether this is true for these versions of AIX, but + # we want this `case' here to explicitly catch those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + aix[45]*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + darwin*) + # Assuming the user has installed a libdl from somewhere, this is true + # If you are looking for one http://www.opendarwin.org/projects/dlcompat + libltdl_cv_sys_dlopen_deplibs=yes + ;; + freebsd* | dragonfly*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + gnu* | linux* | k*bsd*-gnu) + # GNU and its variants, using gnu ld.so (Glibc) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + hpux10*|hpux11*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + interix*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + irix[12345]*|irix6.[01]*) + # Catch all versions of IRIX before 6.2, and indicate that we don't + # know how it worked for any of those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + irix*) + # The case above catches anything before 6.2, and it's known that + # at 6.2 and later dlopen does load deplibs. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + netbsd* | netbsdelf*-gnu) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + openbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + osf[1234]*) + # dlopen did load deplibs (at least at 4.x), but until the 5.x series, + # it did *not* use an RPATH in a shared library to find objects the + # library depends on, so we explictly say `no'. + libltdl_cv_sys_dlopen_deplibs=no + ;; + osf5.0|osf5.0a|osf5.1) + # dlopen *does* load deplibs and with the right loader patch applied + # it even uses RPATH in a shared library to search for shared objects + # that the library depends on, but there's no easy way to know if that + # patch is installed. Since this is the case, all we can really + # say is unknown -- it depends on the patch being installed. If + # it is, this changes to `yes'. Without it, it would be `no'. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + osf*) + # the two cases above should catch all versions of osf <= 5.1. Read + # the comments above for what we know about them. + # At > 5.1, deplibs are loaded *and* any RPATH in a shared library + # is used to find them so we can finally say `yes'. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + solaris*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + esac + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_dlopen_deplibs" >&5 +echo "${ECHO_T}$libltdl_cv_sys_dlopen_deplibs" >&6; } +if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then + +cat >>confdefs.h <<\_ACEOF +#define LTDL_DLOPEN_DEPLIBS 1 +_ACEOF + +fi + + +for ac_header in argz.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ---------------------------------- ## +## Report this to bug-libtool@gnu.org ## +## ---------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ echo "$as_me:$LINENO: checking for error_t" >&5 +echo $ECHO_N "checking for error_t... $ECHO_C" >&6; } +if test "${ac_cv_type_error_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if HAVE_ARGZ_H +# include +#endif + +typedef error_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_type_error_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_error_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_error_t" >&5 +echo "${ECHO_T}$ac_cv_type_error_t" >&6; } +if test $ac_cv_type_error_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_ERROR_T 1 +_ACEOF + + +else + +cat >>confdefs.h <<\_ACEOF +#define error_t int +_ACEOF + +fi + + + + + + + +for ac_func in argz_append argz_create_sep argz_insert argz_next argz_stringify +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + + + + + + + + + + + + + + + + + + + + + + + +for ac_header in assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ + stdio.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ---------------------------------- ## +## Report this to bug-libtool@gnu.org ## +## ---------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +for ac_header in dl.h sys/dl.h dld.h mach-o/dyld.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ---------------------------------- ## +## Report this to bug-libtool@gnu.org ## +## ---------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in string.h strings.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ---------------------------------- ## +## Report this to bug-libtool@gnu.org ## +## ---------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + break +fi + +done + + + + +for ac_func in strchr index +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + break +fi +done + + + +for ac_func in strrchr rindex +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + break +fi +done + + + +for ac_func in memcpy bcopy +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + break +fi +done + + + +for ac_func in memmove strcmp +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +for ac_func in closedir opendir readdir +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +## -------- ## +## Outputs. ## +## -------- ## +ac_config_files="$ac_config_files Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${INSTALL_LTDL_TRUE}" && test -z "${INSTALL_LTDL_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"INSTALL_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"INSTALL_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${CONVENIENCE_LTDL_TRUE}" && test -z "${CONVENIENCE_LTDL_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"CONVENIENCE_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"CONVENIENCE_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by libltdl $as_me 1.2, which was +generated by GNU Autoconf 2.61. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +libltdl config.status 1.2 +configured by $0, generated by GNU Autoconf 2.61, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config-h.in" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim +INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim +INSTALL_DATA!$INSTALL_DATA$ac_delim +am__isrc!$am__isrc$ac_delim +CYGPATH_W!$CYGPATH_W$ac_delim +PACKAGE!$PACKAGE$ac_delim +VERSION!$VERSION$ac_delim +ACLOCAL!$ACLOCAL$ac_delim +AUTOCONF!$AUTOCONF$ac_delim +AUTOMAKE!$AUTOMAKE$ac_delim +AUTOHEADER!$AUTOHEADER$ac_delim +MAKEINFO!$MAKEINFO$ac_delim +install_sh!$install_sh$ac_delim +STRIP!$STRIP$ac_delim +INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim +mkdir_p!$mkdir_p$ac_delim +AWK!$AWK$ac_delim +SET_MAKE!$SET_MAKE$ac_delim +am__leading_dot!$am__leading_dot$ac_delim +AMTAR!$AMTAR$ac_delim +am__tar!$am__tar$ac_delim +am__untar!$am__untar$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +DEPDIR!$DEPDIR$ac_delim +am__include!$am__include$ac_delim +am__quote!$am__quote$ac_delim +AMDEP_TRUE!$AMDEP_TRUE$ac_delim +AMDEP_FALSE!$AMDEP_FALSE$ac_delim +AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim +CCDEPMODE!$CCDEPMODE$ac_delim +am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim +am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +SED!$SED$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +LN_S!$LN_S$ac_delim +ECHO!$ECHO$ac_delim +AR!$AR$ac_delim +RANLIB!$RANLIB$ac_delim +DLLTOOL!$DLLTOOL$ac_delim +AS!$AS$ac_delim +OBJDUMP!$OBJDUMP$ac_delim +CPP!$CPP$ac_delim +CXX!$CXX$ac_delim +CXXFLAGS!$CXXFLAGS$ac_delim +ac_ct_CXX!$ac_ct_CXX$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +CEOF$ac_eof +_ACEOF + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +CXXDEPMODE!$CXXDEPMODE$ac_delim +am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim +am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim +CXXCPP!$CXXCPP$ac_delim +F77!$F77$ac_delim +FFLAGS!$FFLAGS$ac_delim +ac_ct_F77!$ac_ct_F77$ac_delim +LIBTOOL!$LIBTOOL$ac_delim +LIBTOOL_DEPS!$LIBTOOL_DEPS$ac_delim +INSTALL_LTDL_TRUE!$INSTALL_LTDL_TRUE$ac_delim +INSTALL_LTDL_FALSE!$INSTALL_LTDL_FALSE$ac_delim +CONVENIENCE_LTDL_TRUE!$CONVENIENCE_LTDL_TRUE$ac_delim +CONVENIENCE_LTDL_FALSE!$CONVENIENCE_LTDL_FALSE$ac_delim +LIBADD_DL!$LIBADD_DL$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 16; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + :H) + # + # CONFIG_HEADER + # +_ACEOF + +# Transform confdefs.h into a sed script `conftest.defines', that +# substitutes the proper values into config.h.in to produce config.h. +rm -f conftest.defines conftest.tail +# First, append a space to every undef/define line, to ease matching. +echo 's/$/ /' >conftest.defines +# Then, protect against being on the right side of a sed subst, or in +# an unquoted here document, in config.status. If some macros were +# called several times there might be several #defines for the same +# symbol, which is useless. But do not sort them, since the last +# AC_DEFINE must be honored. +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where +# NAME is the cpp macro being defined, VALUE is the value it is being given. +# PARAMS is the parameter list in the macro definition--in most cases, it's +# just an empty string. +ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' +ac_dB='\\)[ (].*,\\1define\\2' +ac_dC=' ' +ac_dD=' ,' + +uniq confdefs.h | + sed -n ' + t rset + :rset + s/^[ ]*#[ ]*define[ ][ ]*// + t ok + d + :ok + s/[\\&,]/\\&/g + s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p + s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p + ' >>conftest.defines + +# Remove the space that was appended to ease matching. +# Then replace #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +# (The regexp can be short, since the line contains either #define or #undef.) +echo 's/ $// +s,^[ #]*u.*,/* & */,' >>conftest.defines + +# Break up conftest.defines: +ac_max_sed_lines=50 + +# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" +# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" +# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" +# et cetera. +ac_in='$ac_file_inputs' +ac_out='"$tmp/out1"' +ac_nxt='"$tmp/out2"' + +while : +do + # Write a here document: + cat >>$CONFIG_STATUS <<_ACEOF + # First, check the format of the line: + cat >"\$tmp/defines.sed" <<\\CEOF +/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def +/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def +b +:def +_ACEOF + sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS + ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in + sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail + grep . conftest.tail >/dev/null || break + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines conftest.tail + +echo "ac_result=$ac_in" >>$CONFIG_STATUS +cat >>$CONFIG_STATUS <<\_ACEOF + if test x"$ac_file" != x-; then + echo "/* $configure_input */" >"$tmp/config.h" + cat "$ac_result" >>"$tmp/config.h" + if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f $ac_file + mv "$tmp/config.h" $ac_file + fi + else + echo "/* $configure_input */" + cat "$ac_result" + fi + rm -f "$tmp/out12" +# Compute $ac_file's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $ac_file | $ac_file:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $ac_file" >`$as_dirname -- $ac_file || +$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X$ac_file : 'X\(//\)[^/]' \| \ + X$ac_file : 'X\(//\)$' \| \ + X$ac_file : 'X\(/\)' \| . 2>/dev/null || +echo X$ac_file | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 +echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir=$dirpart/$fdir + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + + esac +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/libltdl/configure.ac b/libltdl/configure.ac new file mode 100644 index 000000000..1446efbd0 --- /dev/null +++ b/libltdl/configure.ac @@ -0,0 +1,79 @@ +## Process this file with autoconf to create configure. -*- autoconf -*- +# Copyright 2001 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 USA + + +dnl FIXME: Is this really new enough? +AC_PREREQ(2.50) + + +## ------------------------ ## +## Autoconf initialisation. ## +## ------------------------ ## +AC_INIT([libltdl], [1.2], [bug-libtool@gnu.org]) +AC_CONFIG_SRCDIR([ltdl.c]) + + +## ------------------------------- ## +## Libltdl specific configuration. ## +## ------------------------------- ## + +AC_CONFIG_AUX_DIR([.]) + +if test -z "$enable_ltdl_install$enable_ltdl_convenience"; then + if test -f ${srcdir}/ltmain.sh; then + # if libltdl is libtoolized, it is assumed to be stand-alone and + # installed unless the command line overrides it (tested above) + enable_ltdl_install=yes + else + AC_MSG_WARN([*** The top-level configure must select either]) + AC_MSG_WARN([*** [A""C_LIBLTDL_INSTALLABLE] or [A""C_LIBLTDL_CONVENIENCE].]) + AC_MSG_ERROR([*** Maybe you want to --enable-ltdl-install?]) + fi +fi + + +## ------------------------ ## +## Automake Initialisation. ## +## ------------------------ ## +AM_INIT_AUTOMAKE(AC_PACKAGE_TARNAME, AC_PACKAGE_VERSION, -) +AM_CONFIG_HEADER([config.h:config-h.in]) + + +## ------------------ ## +## C compiler checks. ## +## ------------------ ## +AC_PROG_CC +AC_C_CONST +AC_C_INLINE + + +## ----------------------- ## +## Libtool initialisation. ## +## ----------------------- ## +AC_LIBTOOL_WIN32_DLL +AC_PROG_LIBTOOL +AC_SUBST([LIBTOOL_DEPS]) + +AC_LIB_LTDL + + +## -------- ## +## Outputs. ## +## -------- ## +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/libltdl/install-sh b/libltdl/install-sh new file mode 100755 index 000000000..a5897de6e --- /dev/null +++ b/libltdl/install-sh @@ -0,0 +1,519 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2006-12-25.00 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c new file mode 100644 index 000000000..3a76ff102 --- /dev/null +++ b/libltdl/ltdl.c @@ -0,0 +1,4530 @@ +/* ltdl.c -- system independent dlopen wrapper + Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Originally by Thomas Tanner + This file is part of GNU Libtool. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Lesser General Public License, +if you distribute this file as part of a program or library that +is built using GNU libtool, you may include it under the same +distribution terms that you use for the rest of that program. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA + +*/ + +#if HAVE_CONFIG_H +# include +#endif + +#if HAVE_UNISTD_H +# include +#endif + +#if HAVE_STDIO_H +# include +#endif + +/* Include the header defining malloc. On K&R C compilers, + that's , on ANSI C and ISO C compilers, that's . */ +#if HAVE_STDLIB_H +# include +#else +# if HAVE_MALLOC_H +# include +# endif +#endif + +#if HAVE_STRING_H +# include +#else +# if HAVE_STRINGS_H +# include +# endif +#endif + +#if HAVE_CTYPE_H +# include +#endif + +#if HAVE_MEMORY_H +# include +#endif + +#if HAVE_ERRNO_H +# include +#endif + + +#ifndef __WINDOWS__ +# ifdef __WIN32__ +# define __WINDOWS__ +# endif +#endif + + +#undef LT_USE_POSIX_DIRENT +#ifdef HAVE_CLOSEDIR +# ifdef HAVE_OPENDIR +# ifdef HAVE_READDIR +# ifdef HAVE_DIRENT_H +# define LT_USE_POSIX_DIRENT +# endif /* HAVE_DIRENT_H */ +# endif /* HAVE_READDIR */ +# endif /* HAVE_OPENDIR */ +#endif /* HAVE_CLOSEDIR */ + + +#undef LT_USE_WINDOWS_DIRENT_EMULATION +#ifndef LT_USE_POSIX_DIRENT +# ifdef __WINDOWS__ +# define LT_USE_WINDOWS_DIRENT_EMULATION +# endif /* __WINDOWS__ */ +#endif /* LT_USE_POSIX_DIRENT */ + + +#ifdef LT_USE_POSIX_DIRENT +# include +# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) +#else +# ifdef LT_USE_WINDOWS_DIRENT_EMULATION +# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) +# else +# define dirent direct +# define LT_D_NAMLEN(dirent) ((dirent)->d_namlen) +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +# endif +#endif + +#if HAVE_ARGZ_H +# include +#endif + +#if HAVE_ASSERT_H +# include +#else +# define assert(arg) ((void) 0) +#endif + +#include "ltdl.h" + +#if WITH_DMALLOC +# include +#endif + + + + +/* --- WINDOWS SUPPORT --- */ + +/* DLL building support on win32 hosts; mostly to workaround their + ridiculous implementation of data symbol exporting. */ +#ifndef LT_GLOBAL_DATA +# if defined(__WINDOWS__) || defined(__CYGWIN__) +# ifdef DLL_EXPORT /* defined by libtool (if required) */ +# define LT_GLOBAL_DATA __declspec(dllexport) +# endif +# endif +# ifndef LT_GLOBAL_DATA /* static linking or !__WINDOWS__ */ +# define LT_GLOBAL_DATA +# endif +#endif + +/* fopen() mode flags for reading a text file */ +#undef LT_READTEXT_MODE +#if defined(__WINDOWS__) || defined(__CYGWIN__) +# define LT_READTEXT_MODE "rt" +#else +# define LT_READTEXT_MODE "r" +#endif + +#ifdef LT_USE_WINDOWS_DIRENT_EMULATION + +#include + +#define dirent lt_dirent +#define DIR lt_DIR + +struct dirent +{ + char d_name[2048]; + int d_namlen; +}; + +typedef struct _DIR +{ + HANDLE hSearch; + WIN32_FIND_DATA Win32FindData; + BOOL firsttime; + struct dirent file_info; +} DIR; + +#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */ + + +/* --- MANIFEST CONSTANTS --- */ + + +/* Standard libltdl search path environment variable name */ +#undef LTDL_SEARCHPATH_VAR +#define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH" + +/* Standard libtool archive file extension. */ +#undef LTDL_ARCHIVE_EXT +#define LTDL_ARCHIVE_EXT ".la" + +/* max. filename length */ +#ifndef LT_FILENAME_MAX +# define LT_FILENAME_MAX 1024 +#endif + +/* This is the maximum symbol size that won't require malloc/free */ +#undef LT_SYMBOL_LENGTH +#define LT_SYMBOL_LENGTH 128 + +/* This accounts for the _LTX_ separator */ +#undef LT_SYMBOL_OVERHEAD +#define LT_SYMBOL_OVERHEAD 5 + + + + +/* --- MEMORY HANDLING --- */ + + +/* These are the functions used internally. In addition to making + use of the associated function pointers above, they also perform + error handling. */ +static char *lt_estrdup LT_PARAMS((const char *str)); +static lt_ptr lt_emalloc LT_PARAMS((size_t size)); +static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size)); + +/* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */ +#define rpl_realloc realloc + +/* These are the pointers that can be changed by the caller: */ +LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)) + = (lt_ptr (*) LT_PARAMS((size_t))) malloc; +LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)) + = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc; +LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)) + = (void (*) LT_PARAMS((lt_ptr))) free; + +/* The following macros reduce the amount of typing needed to cast + assigned memory. */ +#if WITH_DMALLOC + +#define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp))) +#define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp))) +#define LT_DLFREE(p) \ + LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END + +#define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp))) +#define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp))) + +#else + +#define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp))) +#define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp))) +#define LT_DLFREE(p) \ + LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END + +#define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp))) +#define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp))) + +#endif + +#define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \ + if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \ + } LT_STMT_END + + +/* --- REPLACEMENT FUNCTIONS --- */ + + +#undef strdup +#define strdup rpl_strdup + +static char *strdup LT_PARAMS((const char *str)); + +static char * +strdup(str) + const char *str; +{ + char *tmp = 0; + + if (str) + { + tmp = LT_DLMALLOC (char, 1+ strlen (str)); + if (tmp) + { + strcpy(tmp, str); + } + } + + return tmp; +} + + +#if ! HAVE_STRCMP + +#undef strcmp +#define strcmp rpl_strcmp + +static int strcmp LT_PARAMS((const char *str1, const char *str2)); + +static int +strcmp (str1, str2) + const char *str1; + const char *str2; +{ + if (str1 == str2) + return 0; + if (str1 == 0) + return -1; + if (str2 == 0) + return 1; + + for (;*str1 && *str2; ++str1, ++str2) + { + if (*str1 != *str2) + break; + } + + return (int)(*str1 - *str2); +} +#endif + + +#if ! HAVE_STRCHR + +# if HAVE_INDEX +# define strchr index +# else +# define strchr rpl_strchr + +static const char *strchr LT_PARAMS((const char *str, int ch)); + +static const char* +strchr(str, ch) + const char *str; + int ch; +{ + const char *p; + + for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p) + /*NOWORK*/; + + return (*p == (char)ch) ? p : 0; +} + +# endif +#endif /* !HAVE_STRCHR */ + + +#if ! HAVE_STRRCHR + +# if HAVE_RINDEX +# define strrchr rindex +# else +# define strrchr rpl_strrchr + +static const char *strrchr LT_PARAMS((const char *str, int ch)); + +static const char* +strrchr(str, ch) + const char *str; + int ch; +{ + const char *p, *q = 0; + + for (p = str; *p != LT_EOS_CHAR; ++p) + { + if (*p == (char) ch) + { + q = p; + } + } + + return q; +} + +# endif +#endif + +/* NOTE: Neither bcopy nor the memcpy implementation below can + reliably handle copying in overlapping areas of memory. Use + memmove (for which there is a fallback implmentation below) + if you need that behaviour. */ +#if ! HAVE_MEMCPY + +# if HAVE_BCOPY +# define memcpy(dest, src, size) bcopy (src, dest, size) +# else +# define memcpy rpl_memcpy + +static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); + +static lt_ptr +memcpy (dest, src, size) + lt_ptr dest; + const lt_ptr src; + size_t size; +{ + const char * s = src; + char * d = dest; + size_t i = 0; + + for (i = 0; i < size; ++i) + { + d[i] = s[i]; + } + + return dest; +} + +# endif /* !HAVE_BCOPY */ +#endif /* !HAVE_MEMCPY */ + +#if ! HAVE_MEMMOVE +# define memmove rpl_memmove + +static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); + +static lt_ptr +memmove (dest, src, size) + lt_ptr dest; + const lt_ptr src; + size_t size; +{ + const char * s = src; + char * d = dest; + size_t i; + + if (d < s) + for (i = 0; i < size; ++i) + { + d[i] = s[i]; + } + else if (d > s && size > 0) + for (i = size -1; ; --i) + { + d[i] = s[i]; + if (i == 0) + break; + } + + return dest; +} + +#endif /* !HAVE_MEMMOVE */ + +#ifdef LT_USE_WINDOWS_DIRENT_EMULATION + +static void closedir LT_PARAMS((DIR *entry)); + +static void +closedir(entry) + DIR *entry; +{ + assert(entry != (DIR *) NULL); + FindClose(entry->hSearch); + lt_dlfree((lt_ptr)entry); +} + + +static DIR * opendir LT_PARAMS((const char *path)); + +static DIR* +opendir (path) + const char *path; +{ + char file_specification[LT_FILENAME_MAX]; + DIR *entry; + + assert(path != (char *) NULL); + /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */ + (void) strncpy (file_specification, path, LT_FILENAME_MAX-6); + file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR; + (void) strcat(file_specification,"\\"); + entry = LT_DLMALLOC (DIR,sizeof(DIR)); + if (entry != (DIR *) 0) + { + entry->firsttime = TRUE; + entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData); + } + if (entry->hSearch == INVALID_HANDLE_VALUE) + { + (void) strcat(file_specification,"\\*.*"); + entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData); + if (entry->hSearch == INVALID_HANDLE_VALUE) + { + LT_DLFREE (entry); + return (DIR *) 0; + } + } + return(entry); +} + + +static struct dirent *readdir LT_PARAMS((DIR *entry)); + +static struct dirent *readdir(entry) + DIR *entry; +{ + int + status; + + if (entry == (DIR *) 0) + return((struct dirent *) 0); + if (!entry->firsttime) + { + status = FindNextFile(entry->hSearch,&entry->Win32FindData); + if (status == 0) + return((struct dirent *) 0); + } + entry->firsttime = FALSE; + (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName, + LT_FILENAME_MAX-1); + entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR; + entry->file_info.d_namlen = strlen(entry->file_info.d_name); + return(&entry->file_info); +} + +#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */ + +/* According to Alexandre Oliva , + ``realloc is not entirely portable'' + In any case we want to use the allocator supplied by the user without + burdening them with an lt_dlrealloc function pointer to maintain. + Instead implement our own version (with known boundary conditions) + using lt_dlmalloc and lt_dlfree. */ + +/* #undef realloc + #define realloc rpl_realloc +*/ +#if 0 + /* You can't (re)define realloc unless you also (re)define malloc. + Right now, this code uses the size of the *destination* to decide + how much to copy. That's not right, but you can't know the size + of the source unless you know enough about, or wrote malloc. So + this code is disabled... */ + +static lt_ptr +realloc (ptr, size) + lt_ptr ptr; + size_t size; +{ + if (size == 0) + { + /* For zero or less bytes, free the original memory */ + if (ptr != 0) + { + lt_dlfree (ptr); + } + + return (lt_ptr) 0; + } + else if (ptr == 0) + { + /* Allow reallocation of a NULL pointer. */ + return lt_dlmalloc (size); + } + else + { + /* Allocate a new block, copy and free the old block. */ + lt_ptr mem = lt_dlmalloc (size); + + if (mem) + { + memcpy (mem, ptr, size); + lt_dlfree (ptr); + } + + /* Note that the contents of PTR are not damaged if there is + insufficient memory to realloc. */ + return mem; + } +} +#endif + + +#if ! HAVE_ARGZ_APPEND +# define argz_append rpl_argz_append + +static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len, + const char *buf, size_t buf_len)); + +static error_t +argz_append (pargz, pargz_len, buf, buf_len) + char **pargz; + size_t *pargz_len; + const char *buf; + size_t buf_len; +{ + size_t argz_len; + char *argz; + + assert (pargz); + assert (pargz_len); + assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len)); + + /* If nothing needs to be appended, no more work is required. */ + if (buf_len == 0) + return 0; + + /* Ensure there is enough room to append BUF_LEN. */ + argz_len = *pargz_len + buf_len; + argz = LT_DLREALLOC (char, *pargz, argz_len); + if (!argz) + return ENOMEM; + + /* Copy characters from BUF after terminating '\0' in ARGZ. */ + memcpy (argz + *pargz_len, buf, buf_len); + + /* Assign new values. */ + *pargz = argz; + *pargz_len = argz_len; + + return 0; +} +#endif /* !HAVE_ARGZ_APPEND */ + + +#if ! HAVE_ARGZ_CREATE_SEP +# define argz_create_sep rpl_argz_create_sep + +static error_t argz_create_sep LT_PARAMS((const char *str, int delim, + char **pargz, size_t *pargz_len)); + +static error_t +argz_create_sep (str, delim, pargz, pargz_len) + const char *str; + int delim; + char **pargz; + size_t *pargz_len; +{ + size_t argz_len; + char *argz = 0; + + assert (str); + assert (pargz); + assert (pargz_len); + + /* Make a copy of STR, but replacing each occurrence of + DELIM with '\0'. */ + argz_len = 1+ LT_STRLEN (str); + if (argz_len) + { + const char *p; + char *q; + + argz = LT_DLMALLOC (char, argz_len); + if (!argz) + return ENOMEM; + + for (p = str, q = argz; *p != LT_EOS_CHAR; ++p) + { + if (*p == delim) + { + /* Ignore leading delimiters, and fold consecutive + delimiters in STR into a single '\0' in ARGZ. */ + if ((q > argz) && (q[-1] != LT_EOS_CHAR)) + *q++ = LT_EOS_CHAR; + else + --argz_len; + } + else + *q++ = *p; + } + /* Copy terminating LT_EOS_CHAR. */ + *q = *p; + } + + /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */ + if (!argz_len) + LT_DLFREE (argz); + + /* Assign new values. */ + *pargz = argz; + *pargz_len = argz_len; + + return 0; +} +#endif /* !HAVE_ARGZ_CREATE_SEP */ + + +#if ! HAVE_ARGZ_INSERT +# define argz_insert rpl_argz_insert + +static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len, + char *before, const char *entry)); + +static error_t +argz_insert (pargz, pargz_len, before, entry) + char **pargz; + size_t *pargz_len; + char *before; + const char *entry; +{ + assert (pargz); + assert (pargz_len); + assert (entry && *entry); + + /* No BEFORE address indicates ENTRY should be inserted after the + current last element. */ + if (!before) + return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry)); + + /* This probably indicates a programmer error, but to preserve + semantics, scan back to the start of an entry if BEFORE points + into the middle of it. */ + while ((before > *pargz) && (before[-1] != LT_EOS_CHAR)) + --before; + + { + size_t entry_len = 1+ LT_STRLEN (entry); + size_t argz_len = *pargz_len + entry_len; + size_t offset = before - *pargz; + char *argz = LT_DLREALLOC (char, *pargz, argz_len); + + if (!argz) + return ENOMEM; + + /* Make BEFORE point to the equivalent offset in ARGZ that it + used to have in *PARGZ incase realloc() moved the block. */ + before = argz + offset; + + /* Move the ARGZ entries starting at BEFORE up into the new + space at the end -- making room to copy ENTRY into the + resulting gap. */ + memmove (before + entry_len, before, *pargz_len - offset); + memcpy (before, entry, entry_len); + + /* Assign new values. */ + *pargz = argz; + *pargz_len = argz_len; + } + + return 0; +} +#endif /* !HAVE_ARGZ_INSERT */ + + +#if ! HAVE_ARGZ_NEXT +# define argz_next rpl_argz_next + +static char *argz_next LT_PARAMS((char *argz, size_t argz_len, + const char *entry)); + +static char * +argz_next (argz, argz_len, entry) + char *argz; + size_t argz_len; + const char *entry; +{ + assert ((argz && argz_len) || (!argz && !argz_len)); + + if (entry) + { + /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address + within the ARGZ vector. */ + assert ((!argz && !argz_len) + || ((argz <= entry) && (entry < (argz + argz_len)))); + + /* Move to the char immediately after the terminating + '\0' of ENTRY. */ + entry = 1+ strchr (entry, LT_EOS_CHAR); + + /* Return either the new ENTRY, or else NULL if ARGZ is + exhausted. */ + return (entry >= argz + argz_len) ? 0 : (char *) entry; + } + else + { + /* This should probably be flagged as a programmer error, + since starting an argz_next loop with the iterator set + to ARGZ is safer. To preserve semantics, handle the NULL + case by returning the start of ARGZ (if any). */ + if (argz_len > 0) + return argz; + else + return 0; + } +} +#endif /* !HAVE_ARGZ_NEXT */ + + + +#if ! HAVE_ARGZ_STRINGIFY +# define argz_stringify rpl_argz_stringify + +static void argz_stringify LT_PARAMS((char *argz, size_t argz_len, + int sep)); + +static void +argz_stringify (argz, argz_len, sep) + char *argz; + size_t argz_len; + int sep; +{ + assert ((argz && argz_len) || (!argz && !argz_len)); + + if (sep) + { + --argz_len; /* don't stringify the terminating EOS */ + while (--argz_len > 0) + { + if (argz[argz_len] == LT_EOS_CHAR) + argz[argz_len] = sep; + } + } +} +#endif /* !HAVE_ARGZ_STRINGIFY */ + + + + +/* --- TYPE DEFINITIONS -- */ + + +/* This type is used for the array of caller data sets in each handler. */ +typedef struct { + lt_dlcaller_id key; + lt_ptr data; +} lt_caller_data; + + + + +/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */ + + +/* Extract the diagnostic strings from the error table macro in the same + order as the enumerated indices in ltdl.h. */ + +static const char *lt_dlerror_strings[] = + { +#define LT_ERROR(name, diagnostic) (diagnostic), + lt_dlerror_table +#undef LT_ERROR + + 0 + }; + +/* This structure is used for the list of registered loaders. */ +struct lt_dlloader { + struct lt_dlloader *next; + const char *loader_name; /* identifying name for each loader */ + const char *sym_prefix; /* prefix for symbols */ + lt_module_open *module_open; + lt_module_close *module_close; + lt_find_sym *find_sym; + lt_dlloader_exit *dlloader_exit; + lt_user_data dlloader_data; +}; + +struct lt_dlhandle_struct { + struct lt_dlhandle_struct *next; + lt_dlloader *loader; /* dlopening interface */ + lt_dlinfo info; + int depcount; /* number of dependencies */ + lt_dlhandle *deplibs; /* dependencies */ + lt_module module; /* system module handle */ + lt_ptr system; /* system specific data */ + lt_caller_data *caller_data; /* per caller associated data */ + int flags; /* various boolean stats */ +}; + +/* Various boolean flags can be stored in the flags field of an + lt_dlhandle_struct... */ +#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag)) +#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag)) + +#define LT_DLRESIDENT_FLAG (0x01 << 0) +/* ...add more flags here... */ + +#define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG) + + +#define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)] + +static const char objdir[] = LTDL_OBJDIR; +static const char archive_ext[] = LTDL_ARCHIVE_EXT; +#ifdef LTDL_SHLIB_EXT +static const char shlib_ext[] = LTDL_SHLIB_EXT; +#endif +#ifdef LTDL_SYSSEARCHPATH +static const char sys_search_path[] = LTDL_SYSSEARCHPATH; +#endif + + + + +/* --- MUTEX LOCKING --- */ + + +/* Macros to make it easier to run the lock functions only if they have + been registered. The reason for the complicated lock macro is to + ensure that the stored error message from the last error is not + accidentally erased if the current function doesn't generate an + error of its own. */ +#define LT_DLMUTEX_LOCK() LT_STMT_START { \ + if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \ + } LT_STMT_END +#define LT_DLMUTEX_UNLOCK() LT_STMT_START { \ + if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\ + } LT_STMT_END +#define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \ + if (lt_dlmutex_seterror_func) \ + (*lt_dlmutex_seterror_func) (errormsg); \ + else lt_dllast_error = (errormsg); } LT_STMT_END +#define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \ + if (lt_dlmutex_geterror_func) \ + (errormsg) = (*lt_dlmutex_geterror_func) (); \ + else (errormsg) = lt_dllast_error; } LT_STMT_END + +/* The mutex functions stored here are global, and are necessarily the + same for all threads that wish to share access to libltdl. */ +static lt_dlmutex_lock *lt_dlmutex_lock_func = 0; +static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0; +static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0; +static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0; +static const char *lt_dllast_error = 0; + + +/* Either set or reset the mutex functions. Either all the arguments must + be valid functions, or else all can be NULL to turn off locking entirely. + The registered functions should be manipulating a static global lock + from the lock() and unlock() callbacks, which needs to be reentrant. */ +int +lt_dlmutex_register (lock, unlock, seterror, geterror) + lt_dlmutex_lock *lock; + lt_dlmutex_unlock *unlock; + lt_dlmutex_seterror *seterror; + lt_dlmutex_geterror *geterror; +{ + lt_dlmutex_unlock *old_unlock = lt_dlmutex_unlock_func; + int errors = 0; + + /* Lock using the old lock() callback, if any. */ + LT_DLMUTEX_LOCK (); + + if ((lock && unlock && seterror && geterror) + || !(lock || unlock || seterror || geterror)) + { + lt_dlmutex_lock_func = lock; + lt_dlmutex_unlock_func = unlock; + lt_dlmutex_seterror_func = seterror; + lt_dlmutex_geterror_func = geterror; + } + else + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS)); + ++errors; + } + + /* Use the old unlock() callback we saved earlier, if any. Otherwise + record any errors using internal storage. */ + if (old_unlock) + (*old_unlock) (); + + /* Return the number of errors encountered during the execution of + this function. */ + return errors; +} + + + + +/* --- ERROR HANDLING --- */ + + +static const char **user_error_strings = 0; +static int errorcount = LT_ERROR_MAX; + +int +lt_dladderror (diagnostic) + const char *diagnostic; +{ + int errindex = 0; + int result = -1; + const char **temp = (const char **) 0; + + assert (diagnostic); + + LT_DLMUTEX_LOCK (); + + errindex = errorcount - LT_ERROR_MAX; + temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex); + if (temp) + { + user_error_strings = temp; + user_error_strings[errindex] = diagnostic; + result = errorcount++; + } + + LT_DLMUTEX_UNLOCK (); + + return result; +} + +int +lt_dlseterror (errindex) + int errindex; +{ + int errors = 0; + + LT_DLMUTEX_LOCK (); + + if (errindex >= errorcount || errindex < 0) + { + /* Ack! Error setting the error message! */ + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE)); + ++errors; + } + else if (errindex < LT_ERROR_MAX) + { + /* No error setting the error message! */ + LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]); + } + else + { + /* No error setting the error message! */ + LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]); + } + + LT_DLMUTEX_UNLOCK (); + + return errors; +} + +static lt_ptr +lt_emalloc (size) + size_t size; +{ + lt_ptr mem = lt_dlmalloc (size); + if (size && !mem) + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); + return mem; +} + +static lt_ptr +lt_erealloc (addr, size) + lt_ptr addr; + size_t size; +{ + lt_ptr mem = lt_dlrealloc (addr, size); + if (size && !mem) + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); + return mem; +} + +static char * +lt_estrdup (str) + const char *str; +{ + char *copy = strdup (str); + if (LT_STRLEN (str) && !copy) + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); + return copy; +} + + + + +/* --- DLOPEN() INTERFACE LOADER --- */ + + +#if HAVE_LIBDL + +/* dynamic linking with dlopen/dlsym */ + +#if HAVE_DLFCN_H +# include +#endif + +#if HAVE_SYS_DL_H +# include +#endif + +/* We may have to define LT_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_LAZY_OR_NOW DL_LAZY +# endif +# endif /* !RTLD_LAZY */ +#endif +#ifndef LT_LAZY_OR_NOW +# ifdef RTLD_NOW +# define LT_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_LAZY_OR_NOW DL_NOW +# endif +# endif /* !RTLD_NOW */ +#endif +#ifndef LT_LAZY_OR_NOW +# define LT_LAZY_OR_NOW 0 +#endif /* !LT_LAZY_OR_NOW */ + +#if HAVE_DLERROR +# define DLERROR(arg) dlerror () +#else +# define DLERROR(arg) LT_DLSTRERROR (arg) +#endif + +static lt_module +sys_dl_open (loader_data, filename) + lt_user_data loader_data; + const char *filename; +{ + lt_module module = dlopen (filename, LT_LAZY_OR_NOW); + + if (!module) + { + LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN)); + } + + return module; +} + +static int +sys_dl_close (loader_data, module) + lt_user_data loader_data; + lt_module module; +{ + int errors = 0; + + if (dlclose (module) != 0) + { + LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE)); + ++errors; + } + + return errors; +} + +static lt_ptr +sys_dl_sym (loader_data, module, symbol) + lt_user_data loader_data; + lt_module module; + const char *symbol; +{ + lt_ptr address = dlsym (module, symbol); + + if (!address) + { + LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND)); + } + + return address; +} + +static struct lt_user_dlloader sys_dl = + { +# ifdef NEED_USCORE + "_", +# else + 0, +# endif + sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 }; + + +#endif /* HAVE_LIBDL */ + + + +/* --- SHL_LOAD() INTERFACE LOADER --- */ + +#if HAVE_SHL_LOAD + +/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */ + +#ifdef HAVE_DL_H +# include +#endif + +/* some flags are missing on some systems, so we provide + * harmless defaults. + * + * Mandatory: + * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. + * BIND_DEFERRED - Delay code symbol resolution until actual reference. + * + * Optionally: + * BIND_FIRST - Place the library at the head of the symbol search + * order. + * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all + * unsatisfied symbols as fatal. This flag allows + * binding of unsatisfied code symbols to be deferred + * until use. + * [Perl: For certain libraries, like DCE, deferred + * binding often causes run time problems. Adding + * BIND_NONFATAL to BIND_IMMEDIATE still allows + * unresolved references in situations like this.] + * BIND_NOSTART - Do not call the initializer for the shared library + * when the library is loaded, nor on a future call to + * shl_unload(). + * BIND_VERBOSE - Print verbose messages concerning possible + * unsatisfied symbols. + * + * hp9000s700/hp9000s800: + * BIND_RESTRICTED - Restrict symbols visible by the library to those + * present at library load time. + * DYNAMIC_PATH - Allow the loader to dynamically search for the + * library specified by the path argument. + */ + +#ifndef DYNAMIC_PATH +# define DYNAMIC_PATH 0 +#endif +#ifndef BIND_RESTRICTED +# define BIND_RESTRICTED 0 +#endif + +#define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) + +static lt_module +sys_shl_open (loader_data, filename) + lt_user_data loader_data; + const char *filename; +{ + static shl_t self = (shl_t) 0; + lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); + + /* Since searching for a symbol against a NULL module handle will also + look in everything else that was already loaded and exported with + the -E compiler flag, we always cache a handle saved before any + modules are loaded. */ + if (!self) + { + lt_ptr address; + shl_findsym (&self, "main", TYPE_UNDEFINED, &address); + } + + if (!filename) + { + module = self; + } + else + { + module = shl_load (filename, LT_BIND_FLAGS, 0L); + + if (!module) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); + } + } + + return module; +} + +static int +sys_shl_close (loader_data, module) + lt_user_data loader_data; + lt_module module; +{ + int errors = 0; + + if (module && (shl_unload ((shl_t) (module)) != 0)) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); + ++errors; + } + + return errors; +} + +static lt_ptr +sys_shl_sym (loader_data, module, symbol) + lt_user_data loader_data; + lt_module module; + const char *symbol; +{ + lt_ptr address = 0; + + /* sys_shl_open should never return a NULL module handle */ + if (module == (lt_module) 0) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); + } + else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address)) + { + if (!address) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); + } + } + + return address; +} + +static struct lt_user_dlloader sys_shl = { + 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 +}; + +#endif /* HAVE_SHL_LOAD */ + + + + +/* --- LOADLIBRARY() INTERFACE LOADER --- */ + +#ifdef __WINDOWS__ + +/* dynamic linking for Win32 */ + +#include + +/* Forward declaration; required to implement handle search below. */ +static lt_dlhandle handles; + +static lt_module +sys_wll_open (loader_data, filename) + lt_user_data loader_data; + const char *filename; +{ + lt_dlhandle cur; + lt_module module = 0; + const char *errormsg = 0; + char *searchname = 0; + char *ext; + char self_name_buf[MAX_PATH]; + + if (!filename) + { + /* Get the name of main module */ + *self_name_buf = 0; + GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf)); + filename = ext = self_name_buf; + } + else + { + ext = strrchr (filename, '.'); + } + + if (ext) + { + /* FILENAME already has an extension. */ + searchname = lt_estrdup (filename); + } + else + { + /* Append a `.' to stop Windows from adding an + implicit `.dll' extension. */ + searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename)); + if (searchname) + sprintf (searchname, "%s.", filename); + } + if (!searchname) + return 0; + + { + /* Silence dialog from LoadLibrary on some failures. + No way to get the error mode, but to set it, + so set it twice to preserve any previous flags. */ + UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS); + SetErrorMode(errormode | SEM_FAILCRITICALERRORS); + +#if defined(__CYGWIN__) + { + char wpath[MAX_PATH]; + cygwin_conv_to_full_win32_path (searchname, wpath); + module = LoadLibrary (wpath); + } +#else + module = LoadLibrary (searchname); +#endif + + /* Restore the error mode. */ + SetErrorMode(errormode); + } + + LT_DLFREE (searchname); + + /* libltdl expects this function to fail if it is unable + to physically load the library. Sadly, LoadLibrary + will search the loaded libraries for a match and return + one of them if the path search load fails. + + We check whether LoadLibrary is returning a handle to + an already loaded module, and simulate failure if we + find one. */ + LT_DLMUTEX_LOCK (); + cur = handles; + while (cur) + { + if (!cur->module) + { + cur = 0; + break; + } + + if (cur->module == module) + { + break; + } + + cur = cur->next; + } + LT_DLMUTEX_UNLOCK (); + + if (cur || !module) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); + module = 0; + } + + return module; +} + +static int +sys_wll_close (loader_data, module) + lt_user_data loader_data; + lt_module module; +{ + int errors = 0; + + if (FreeLibrary(module) == 0) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); + ++errors; + } + + return errors; +} + +static lt_ptr +sys_wll_sym (loader_data, module, symbol) + lt_user_data loader_data; + lt_module module; + const char *symbol; +{ + lt_ptr address = GetProcAddress (module, symbol); + + if (!address) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); + } + + return address; +} + +static struct lt_user_dlloader sys_wll = { + 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 +}; + +#endif /* __WINDOWS__ */ + + + + +/* --- LOAD_ADD_ON() INTERFACE LOADER --- */ + + +#ifdef __BEOS__ + +/* dynamic linking for BeOS */ + +#include + +static lt_module +sys_bedl_open (loader_data, filename) + lt_user_data loader_data; + const char *filename; +{ + image_id image = 0; + + if (filename) + { + image = load_add_on (filename); + } + else + { + image_info info; + int32 cookie = 0; + if (get_next_image_info (0, &cookie, &info) == B_OK) + image = load_add_on (info.name); + } + + if (image <= 0) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); + image = 0; + } + + return (lt_module) image; +} + +static int +sys_bedl_close (loader_data, module) + lt_user_data loader_data; + lt_module module; +{ + int errors = 0; + + if (unload_add_on ((image_id) module) != B_OK) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); + ++errors; + } + + return errors; +} + +static lt_ptr +sys_bedl_sym (loader_data, module, symbol) + lt_user_data loader_data; + lt_module module; + const char *symbol; +{ + lt_ptr address = 0; + image_id image = (image_id) module; + + if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); + address = 0; + } + + return address; +} + +static struct lt_user_dlloader sys_bedl = { + 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 +}; + +#endif /* __BEOS__ */ + + + + +/* --- DLD_LINK() INTERFACE LOADER --- */ + + +#if HAVE_DLD + +/* dynamic linking with dld */ + +#if HAVE_DLD_H +#include +#endif + +static lt_module +sys_dld_open (loader_data, filename) + lt_user_data loader_data; + const char *filename; +{ + lt_module module = strdup (filename); + + if (dld_link (filename) != 0) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); + LT_DLFREE (module); + module = 0; + } + + return module; +} + +static int +sys_dld_close (loader_data, module) + lt_user_data loader_data; + lt_module module; +{ + int errors = 0; + + if (dld_unlink_by_file ((char*)(module), 1) != 0) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); + ++errors; + } + else + { + LT_DLFREE (module); + } + + return errors; +} + +static lt_ptr +sys_dld_sym (loader_data, module, symbol) + lt_user_data loader_data; + lt_module module; + const char *symbol; +{ + lt_ptr address = dld_get_func (symbol); + + if (!address) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); + } + + return address; +} + +static struct lt_user_dlloader sys_dld = { + 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 +}; + +#endif /* HAVE_DLD */ + +/* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */ +#if HAVE_DYLD + + +#if HAVE_MACH_O_DYLD_H +#if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__) +/* Is this correct? Does it still function properly? */ +#define __private_extern__ extern +#endif +# include +#endif +#include + +/* We have to put some stuff here that isn't in older dyld.h files */ +#ifndef ENUM_DYLD_BOOL +# define ENUM_DYLD_BOOL +# undef FALSE +# undef TRUE + enum DYLD_BOOL { + FALSE, + TRUE + }; +#endif +#ifndef LC_REQ_DYLD +# define LC_REQ_DYLD 0x80000000 +#endif +#ifndef LC_LOAD_WEAK_DYLIB +# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) +#endif +static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0; +static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0; +static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0; +static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0; + +#ifndef NSADDIMAGE_OPTION_NONE +#define NSADDIMAGE_OPTION_NONE 0x0 +#endif +#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR +#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1 +#endif +#ifndef NSADDIMAGE_OPTION_WITH_SEARCHING +#define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2 +#endif +#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4 +#endif +#ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME +#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8 +#endif +#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND +#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0 +#endif +#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW +#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1 +#endif +#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY +#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2 +#endif +#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR +#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 +#endif + + +static const char * +lt_int_dyld_error(othererror) + char* othererror; +{ +/* return the dyld error string, or the passed in error string if none */ + NSLinkEditErrors ler; + int lerno; + const char *errstr; + const char *file; + NSLinkEditError(&ler,&lerno,&file,&errstr); + if (!errstr || !strlen(errstr)) errstr = othererror; + return errstr; +} + +static const struct mach_header * +lt_int_dyld_get_mach_header_from_nsmodule(module) + NSModule module; +{ +/* There should probably be an apple dyld api for this */ + int i=_dyld_image_count(); + int j; + const char *modname=NSNameOfModule(module); + const struct mach_header *mh=NULL; + if (!modname) return NULL; + for (j = 0; j < i; j++) + { + if (!strcmp(_dyld_get_image_name(j),modname)) + { + mh=_dyld_get_image_header(j); + break; + } + } + return mh; +} + +static const char* lt_int_dyld_lib_install_name(mh) + const struct mach_header *mh; +{ +/* NSAddImage is also used to get the loaded image, but it only works if the lib + is installed, for uninstalled libs we need to check the install_names against + each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a + different lib was loaded as a result +*/ + int j; + struct load_command *lc; + unsigned long offset = sizeof(struct mach_header); + const char* retStr=NULL; + for (j = 0; j < mh->ncmds; j++) + { + lc = (struct load_command*)(((unsigned long)mh) + offset); + if (LC_ID_DYLIB == lc->cmd) + { + retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset + + (unsigned long)lc); + } + offset += lc->cmdsize; + } + return retStr; +} + +static const struct mach_header * +lt_int_dyld_match_loaded_lib_by_install_name(const char *name) +{ + int i=_dyld_image_count(); + int j; + const struct mach_header *mh=NULL; + const char *id=NULL; + for (j = 0; j < i; j++) + { + id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j)); + if ((id) && (!strcmp(id,name))) + { + mh=_dyld_get_image_header(j); + break; + } + } + return mh; +} + +static NSSymbol +lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh) + const char *symbol; + const struct mach_header *mh; +{ + /* Safe to assume our mh is good */ + int j; + struct load_command *lc; + unsigned long offset = sizeof(struct mach_header); + NSSymbol retSym = 0; + const struct mach_header *mh1; + if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) ) + { + for (j = 0; j < mh->ncmds; j++) + { + lc = (struct load_command*)(((unsigned long)mh) + offset); + if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) + { + mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset + + (unsigned long)lc)); + if (!mh1) + { + /* Maybe NSAddImage can find it */ + mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset + + (unsigned long)lc), + NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED + + NSADDIMAGE_OPTION_WITH_SEARCHING + + NSADDIMAGE_OPTION_RETURN_ON_ERROR ); + } + if (mh1) + { + retSym = ltdl_NSLookupSymbolInImage(mh1, + symbol, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW + | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR + ); + if (retSym) break; + } + } + offset += lc->cmdsize; + } + } + return retSym; +} + +static int +sys_dyld_init() +{ + int retCode = 0; + int err = 0; + if (!_dyld_present()) { + retCode=1; + } + else { + err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)<dl_NSAddImage); + err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)<dl_NSLookupSymbolInImage); + err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)<dl_NSIsSymbolNameDefinedInImage); + err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)<dl_NSMakePrivateModulePublic); + } + return retCode; +} + +static lt_module +sys_dyld_open (loader_data, filename) + lt_user_data loader_data; + const char *filename; +{ + lt_module module = 0; + NSObjectFileImage ofi = 0; + NSObjectFileImageReturnCode ofirc; + + if (!filename) + return (lt_module)-1; + ofirc = NSCreateObjectFileImageFromFile(filename, &ofi); + switch (ofirc) + { + case NSObjectFileImageSuccess: + module = NSLinkModule(ofi, filename, + NSLINKMODULE_OPTION_RETURN_ON_ERROR + | NSLINKMODULE_OPTION_PRIVATE + | NSLINKMODULE_OPTION_BINDNOW); + NSDestroyObjectFileImage(ofi); + if (module) + ltdl_NSMakePrivateModulePublic(module); + break; + case NSObjectFileImageInappropriateFile: + if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage) + { + module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR); + break; + } + default: + LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN))); + return 0; + } + if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN))); + return module; +} + +static int +sys_dyld_close (loader_data, module) + lt_user_data loader_data; + lt_module module; +{ + int retCode = 0; + int flags = 0; + if (module == (lt_module)-1) return 0; +#ifdef __BIG_ENDIAN__ + if (((struct mach_header *)module)->magic == MH_MAGIC) +#else + if (((struct mach_header *)module)->magic == MH_CIGAM) +#endif + { + LT_DLMUTEX_SETERROR("Can not close a dylib"); + retCode = 1; + } + else + { +#if 1 +/* Currently, if a module contains c++ static destructors and it is unloaded, we + get a segfault in atexit(), due to compiler and dynamic loader differences of + opinion, this works around that. +*/ + if ((const struct section *)NULL != + getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module), + "__DATA","__mod_term_func")) + { + flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; + } +#endif +#ifdef __ppc__ + flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; +#endif + if (!NSUnLinkModule(module,flags)) + { + retCode=1; + LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE))); + } + } + + return retCode; +} + +static lt_ptr +sys_dyld_sym (loader_data, module, symbol) + lt_user_data loader_data; + lt_module module; + const char *symbol; +{ + lt_ptr address = 0; + NSSymbol *nssym = 0; + void *unused; + const struct mach_header *mh=NULL; + char saveError[256] = "Symbol not found"; + if (module == (lt_module)-1) + { + _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused); + return address; + } +#ifdef __BIG_ENDIAN__ + if (((struct mach_header *)module)->magic == MH_MAGIC) +#else + if (((struct mach_header *)module)->magic == MH_CIGAM) +#endif + { + if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage) + { + mh=module; + if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol)) + { + nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module, + symbol, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW + | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR + ); + } + } + + } + else { + nssym = NSLookupSymbolInModule(module, symbol); + } + if (!nssym) + { + strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255); + saveError[255] = 0; + if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module); + nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh); + } + if (!nssym) + { + LT_DLMUTEX_SETERROR (saveError); + return NULL; + } + return NSAddressOfSymbol(nssym); +} + +static struct lt_user_dlloader sys_dyld = + { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 }; + + +#endif /* HAVE_DYLD */ + + +/* --- DLPREOPEN() INTERFACE LOADER --- */ + + +/* emulate dynamic linking using preloaded_symbols */ + +typedef struct lt_dlsymlists_t +{ + struct lt_dlsymlists_t *next; + const lt_dlsymlist *syms; +} lt_dlsymlists_t; + +static const lt_dlsymlist *default_preloaded_symbols = 0; +static lt_dlsymlists_t *preloaded_symbols = 0; + +static int +presym_init (loader_data) + lt_user_data loader_data; +{ + int errors = 0; + + LT_DLMUTEX_LOCK (); + + preloaded_symbols = 0; + if (default_preloaded_symbols) + { + errors = lt_dlpreload (default_preloaded_symbols); + } + + LT_DLMUTEX_UNLOCK (); + + return errors; +} + +static int +presym_free_symlists () +{ + lt_dlsymlists_t *lists; + + LT_DLMUTEX_LOCK (); + + lists = preloaded_symbols; + while (lists) + { + lt_dlsymlists_t *tmp = lists; + + lists = lists->next; + LT_DLFREE (tmp); + } + preloaded_symbols = 0; + + LT_DLMUTEX_UNLOCK (); + + return 0; +} + +static int +presym_exit (loader_data) + lt_user_data loader_data; +{ + presym_free_symlists (); + return 0; +} + +static int +presym_add_symlist (preloaded) + const lt_dlsymlist *preloaded; +{ + lt_dlsymlists_t *tmp; + lt_dlsymlists_t *lists; + int errors = 0; + + LT_DLMUTEX_LOCK (); + + lists = preloaded_symbols; + while (lists) + { + if (lists->syms == preloaded) + { + goto done; + } + lists = lists->next; + } + + tmp = LT_EMALLOC (lt_dlsymlists_t, 1); + if (tmp) + { + memset (tmp, 0, sizeof(lt_dlsymlists_t)); + tmp->syms = preloaded; + tmp->next = preloaded_symbols; + preloaded_symbols = tmp; + } + else + { + ++errors; + } + + done: + LT_DLMUTEX_UNLOCK (); + return errors; +} + +static lt_module +presym_open (loader_data, filename) + lt_user_data loader_data; + const char *filename; +{ + lt_dlsymlists_t *lists; + lt_module module = (lt_module) 0; + + LT_DLMUTEX_LOCK (); + lists = preloaded_symbols; + + if (!lists) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS)); + goto done; + } + + /* Can't use NULL as the reflective symbol header, as NULL is + used to mark the end of the entire symbol list. Self-dlpreopened + symbols follow this magic number, chosen to be an unlikely + clash with a real module name. */ + if (!filename) + { + filename = "@PROGRAM@"; + } + + while (lists) + { + const lt_dlsymlist *syms = lists->syms; + + while (syms->name) + { + if (!syms->address && strcmp(syms->name, filename) == 0) + { + module = (lt_module) syms; + goto done; + } + ++syms; + } + + lists = lists->next; + } + + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); + + done: + LT_DLMUTEX_UNLOCK (); + return module; +} + +static int +presym_close (loader_data, module) + lt_user_data loader_data; + lt_module module; +{ + /* Just to silence gcc -Wall */ + module = 0; + return 0; +} + +static lt_ptr +presym_sym (loader_data, module, symbol) + lt_user_data loader_data; + lt_module module; + const char *symbol; +{ + lt_dlsymlist *syms = (lt_dlsymlist*) module; + + ++syms; + while (syms->address) + { + if (strcmp(syms->name, symbol) == 0) + { + return syms->address; + } + + ++syms; + } + + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); + + return 0; +} + +static struct lt_user_dlloader presym = { + 0, presym_open, presym_close, presym_sym, presym_exit, 0 +}; + + + + + +/* --- DYNAMIC MODULE LOADING --- */ + + +/* The type of a function used at each iteration of foreach_dirinpath(). */ +typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1, + lt_ptr data2)); + +static int foreach_dirinpath LT_PARAMS((const char *search_path, + const char *base_name, + foreach_callback_func *func, + lt_ptr data1, lt_ptr data2)); + +static int find_file_callback LT_PARAMS((char *filename, lt_ptr data, + lt_ptr ignored)); +static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data, + lt_ptr ignored)); +static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1, + lt_ptr data2)); + + +static int canonicalize_path LT_PARAMS((const char *path, + char **pcanonical)); +static int argzize_path LT_PARAMS((const char *path, + char **pargz, + size_t *pargz_len)); +static FILE *find_file LT_PARAMS((const char *search_path, + const char *base_name, + char **pdir)); +static lt_dlhandle *find_handle LT_PARAMS((const char *search_path, + const char *base_name, + lt_dlhandle *handle)); +static int find_module LT_PARAMS((lt_dlhandle *handle, + const char *dir, + const char *libdir, + const char *dlname, + const char *old_name, + int installed)); +static int free_vars LT_PARAMS((char *dlname, char *oldname, + char *libdir, char *deplibs)); +static int load_deplibs LT_PARAMS((lt_dlhandle handle, + char *deplibs)); +static int trim LT_PARAMS((char **dest, + const char *str)); +static int try_dlopen LT_PARAMS((lt_dlhandle *handle, + const char *filename)); +static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle, + const char *filename)); +static int unload_deplibs LT_PARAMS((lt_dlhandle handle)); +static int lt_argz_insert LT_PARAMS((char **pargz, + size_t *pargz_len, + char *before, + const char *entry)); +static int lt_argz_insertinorder LT_PARAMS((char **pargz, + size_t *pargz_len, + const char *entry)); +static int lt_argz_insertdir LT_PARAMS((char **pargz, + size_t *pargz_len, + const char *dirnam, + struct dirent *dp)); +static int lt_dlpath_insertdir LT_PARAMS((char **ppath, + char *before, + const char *dir)); +static int list_files_by_dir LT_PARAMS((const char *dirnam, + char **pargz, + size_t *pargz_len)); +static int file_not_found LT_PARAMS((void)); + +static char *user_search_path= 0; +static lt_dlloader *loaders = 0; +static lt_dlhandle handles = 0; +static int initialized = 0; + +/* Initialize libltdl. */ +int +lt_dlinit () +{ + int errors = 0; + + LT_DLMUTEX_LOCK (); + + /* Initialize only at first call. */ + if (++initialized == 1) + { + handles = 0; + user_search_path = 0; /* empty search path */ + +#if HAVE_LIBDL + errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen"); +#endif +#if HAVE_SHL_LOAD + errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen"); +#endif +#ifdef __WINDOWS__ + errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen"); +#endif +#ifdef __BEOS__ + errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen"); +#endif +#if HAVE_DLD + errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld"); +#endif +#if HAVE_DYLD + errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld"); + errors += sys_dyld_init(); +#endif + errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload"); + + if (presym_init (presym.dlloader_data)) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER)); + ++errors; + } + else if (errors != 0) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED)); + ++errors; + } + } + + LT_DLMUTEX_UNLOCK (); + + return errors; +} + +int +lt_dlpreload (preloaded) + const lt_dlsymlist *preloaded; +{ + int errors = 0; + + if (preloaded) + { + errors = presym_add_symlist (preloaded); + } + else + { + presym_free_symlists(); + + LT_DLMUTEX_LOCK (); + if (default_preloaded_symbols) + { + errors = lt_dlpreload (default_preloaded_symbols); + } + LT_DLMUTEX_UNLOCK (); + } + + return errors; +} + +int +lt_dlpreload_default (preloaded) + const lt_dlsymlist *preloaded; +{ + LT_DLMUTEX_LOCK (); + default_preloaded_symbols = preloaded; + LT_DLMUTEX_UNLOCK (); + return 0; +} + +int +lt_dlexit () +{ + /* shut down libltdl */ + lt_dlloader *loader; + int errors = 0; + + LT_DLMUTEX_LOCK (); + loader = loaders; + + if (!initialized) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN)); + ++errors; + goto done; + } + + /* shut down only at last call. */ + if (--initialized == 0) + { + int level; + + while (handles && LT_DLIS_RESIDENT (handles)) + { + handles = handles->next; + } + + /* close all modules */ + for (level = 1; handles; ++level) + { + lt_dlhandle cur = handles; + int saw_nonresident = 0; + + while (cur) + { + lt_dlhandle tmp = cur; + cur = cur->next; + if (!LT_DLIS_RESIDENT (tmp)) + saw_nonresident = 1; + if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level) + { + if (lt_dlclose (tmp)) + { + ++errors; + } + /* Make sure that the handle pointed to by 'cur' still exists. + lt_dlclose recursively closes dependent libraries which removes + them from the linked list. One of these might be the one + pointed to by 'cur'. */ + if (cur) + { + for (tmp = handles; tmp; tmp = tmp->next) + if (tmp == cur) + break; + if (! tmp) + cur = handles; + } + } + } + /* done if only resident modules are left */ + if (!saw_nonresident) + break; + } + + /* close all loaders */ + while (loader) + { + lt_dlloader *next = loader->next; + lt_user_data data = loader->dlloader_data; + if (loader->dlloader_exit && loader->dlloader_exit (data)) + { + ++errors; + } + + LT_DLMEM_REASSIGN (loader, next); + } + loaders = 0; + } + + done: + LT_DLMUTEX_UNLOCK (); + return errors; +} + +static int +tryall_dlopen (handle, filename) + lt_dlhandle *handle; + const char *filename; +{ + lt_dlhandle cur; + lt_dlloader *loader; + const char *saved_error; + int errors = 0; + + LT_DLMUTEX_GETERROR (saved_error); + LT_DLMUTEX_LOCK (); + + cur = handles; + loader = loaders; + + /* check whether the module was already opened */ + while (cur) + { + /* try to dlopen the program itself? */ + if (!cur->info.filename && !filename) + { + break; + } + + if (cur->info.filename && filename + && strcmp (cur->info.filename, filename) == 0) + { + break; + } + + cur = cur->next; + } + + if (cur) + { + ++cur->info.ref_count; + *handle = cur; + goto done; + } + + cur = *handle; + if (filename) + { + /* Comment out the check of file permissions using access. + This call seems to always return -1 with error EACCES. + */ + /* We need to catch missing file errors early so that + file_not_found() can detect what happened. + if (access (filename, R_OK) != 0) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); + ++errors; + goto done; + } */ + + cur->info.filename = lt_estrdup (filename); + if (!cur->info.filename) + { + ++errors; + goto done; + } + } + else + { + cur->info.filename = 0; + } + + while (loader) + { + lt_user_data data = loader->dlloader_data; + + cur->module = loader->module_open (data, filename); + + if (cur->module != 0) + { + break; + } + loader = loader->next; + } + + if (!loader) + { + LT_DLFREE (cur->info.filename); + ++errors; + goto done; + } + + cur->loader = loader; + LT_DLMUTEX_SETERROR (saved_error); + + done: + LT_DLMUTEX_UNLOCK (); + + return errors; +} + +static int +tryall_dlopen_module (handle, prefix, dirname, dlname) + lt_dlhandle *handle; + const char *prefix; + const char *dirname; + const char *dlname; +{ + int error = 0; + char *filename = 0; + size_t filename_len = 0; + size_t dirname_len = LT_STRLEN (dirname); + + assert (handle); + assert (dirname); + assert (dlname); +#ifdef LT_DIRSEP_CHAR + /* Only canonicalized names (i.e. with DIRSEP chars already converted) + should make it into this function: */ + assert (strchr (dirname, LT_DIRSEP_CHAR) == 0); +#endif + + if (dirname_len > 0) + if (dirname[dirname_len -1] == '/') + --dirname_len; + filename_len = dirname_len + 1 + LT_STRLEN (dlname); + + /* Allocate memory, and combine DIRNAME and MODULENAME into it. + The PREFIX (if any) is handled below. */ + filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1); + if (!filename) + return 1; + + sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname); + + /* Now that we have combined DIRNAME and MODULENAME, if there is + also a PREFIX to contend with, simply recurse with the arguments + shuffled. Otherwise, attempt to open FILENAME as a module. */ + if (prefix) + { + error += tryall_dlopen_module (handle, + (const char *) 0, prefix, filename); + } + else if (tryall_dlopen (handle, filename) != 0) + { + ++error; + } + + LT_DLFREE (filename); + return error; +} + +static int +find_module (handle, dir, libdir, dlname, old_name, installed) + lt_dlhandle *handle; + const char *dir; + const char *libdir; + const char *dlname; + const char *old_name; + int installed; +{ + /* Try to open the old library first; if it was dlpreopened, + we want the preopened version of it, even if a dlopenable + module is available. */ + if (old_name && tryall_dlopen (handle, old_name) == 0) + { + return 0; + } + + /* Try to open the dynamic library. */ + if (dlname) + { + /* try to open the installed module */ + if (installed && libdir) + { + if (tryall_dlopen_module (handle, + (const char *) 0, libdir, dlname) == 0) + return 0; + } + + /* try to open the not-installed module */ + if (!installed) + { + if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0) + return 0; + } + + /* maybe it was moved to another directory */ + { + if (dir && (tryall_dlopen_module (handle, + (const char *) 0, dir, dlname) == 0)) + return 0; + } + } + + return 1; +} + + +static int +canonicalize_path (path, pcanonical) + const char *path; + char **pcanonical; +{ + char *canonical = 0; + + assert (path && *path); + assert (pcanonical); + + canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path)); + if (!canonical) + return 1; + + { + size_t dest = 0; + size_t src; + for (src = 0; path[src] != LT_EOS_CHAR; ++src) + { + /* Path separators are not copied to the beginning or end of + the destination, or if another separator would follow + immediately. */ + if (path[src] == LT_PATHSEP_CHAR) + { + if ((dest == 0) + || (path[1+ src] == LT_PATHSEP_CHAR) + || (path[1+ src] == LT_EOS_CHAR)) + continue; + } + + /* Anything other than a directory separator is copied verbatim. */ + if ((path[src] != '/') +#ifdef LT_DIRSEP_CHAR + && (path[src] != LT_DIRSEP_CHAR) +#endif + ) + { + canonical[dest++] = path[src]; + } + /* Directory separators are converted and copied only if they are + not at the end of a path -- i.e. before a path separator or + NULL terminator. */ + else if ((path[1+ src] != LT_PATHSEP_CHAR) + && (path[1+ src] != LT_EOS_CHAR) +#ifdef LT_DIRSEP_CHAR + && (path[1+ src] != LT_DIRSEP_CHAR) +#endif + && (path[1+ src] != '/')) + { + canonical[dest++] = '/'; + } + } + + /* Add an end-of-string marker at the end. */ + canonical[dest] = LT_EOS_CHAR; + } + + /* Assign new value. */ + *pcanonical = canonical; + + return 0; +} + +static int +argzize_path (path, pargz, pargz_len) + const char *path; + char **pargz; + size_t *pargz_len; +{ + error_t error; + + assert (path); + assert (pargz); + assert (pargz_len); + + if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len))) + { + switch (error) + { + case ENOMEM: + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); + break; + default: + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); + break; + } + + return 1; + } + + return 0; +} + +/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element + of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns + non-zero or all elements are exhausted. If BASE_NAME is non-NULL, + it is appended to each SEARCH_PATH element before FUNC is called. */ +static int +foreach_dirinpath (search_path, base_name, func, data1, data2) + const char *search_path; + const char *base_name; + foreach_callback_func *func; + lt_ptr data1; + lt_ptr data2; +{ + int result = 0; + int filenamesize = 0; + size_t lenbase = LT_STRLEN (base_name); + size_t argz_len = 0; + char *argz = 0; + char *filename = 0; + char *canonical = 0; + + LT_DLMUTEX_LOCK (); + + if (!search_path || !*search_path) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); + goto cleanup; + } + + if (canonicalize_path (search_path, &canonical) != 0) + goto cleanup; + + if (argzize_path (canonical, &argz, &argz_len) != 0) + goto cleanup; + + { + char *dir_name = 0; + while ((dir_name = argz_next (argz, argz_len, dir_name))) + { + size_t lendir = LT_STRLEN (dir_name); + + if (lendir +1 +lenbase >= filenamesize) + { + LT_DLFREE (filename); + filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */ + filename = LT_EMALLOC (char, filenamesize); + if (!filename) + goto cleanup; + } + + assert (filenamesize > lendir); + strcpy (filename, dir_name); + + if (base_name && *base_name) + { + if (filename[lendir -1] != '/') + filename[lendir++] = '/'; + strcpy (filename +lendir, base_name); + } + + if ((result = (*func) (filename, data1, data2))) + { + break; + } + } + } + + cleanup: + LT_DLFREE (argz); + LT_DLFREE (canonical); + LT_DLFREE (filename); + + LT_DLMUTEX_UNLOCK (); + + return result; +} + +/* If FILEPATH can be opened, store the name of the directory component + in DATA1, and the opened FILE* structure address in DATA2. Otherwise + DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */ +static int +find_file_callback (filename, data1, data2) + char *filename; + lt_ptr data1; + lt_ptr data2; +{ + char **pdir = (char **) data1; + FILE **pfile = (FILE **) data2; + int is_done = 0; + + assert (filename && *filename); + assert (pdir); + assert (pfile); + + if ((*pfile = fopen (filename, LT_READTEXT_MODE))) + { + char *dirend = strrchr (filename, '/'); + + if (dirend > filename) + *dirend = LT_EOS_CHAR; + + LT_DLFREE (*pdir); + *pdir = lt_estrdup (filename); + is_done = (*pdir == 0) ? -1 : 1; + } + + return is_done; +} + +static FILE * +find_file (search_path, base_name, pdir) + const char *search_path; + const char *base_name; + char **pdir; +{ + FILE *file = 0; + + foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file); + + return file; +} + +static int +find_handle_callback (filename, data, ignored) + char *filename; + lt_ptr data; + lt_ptr ignored; +{ + lt_dlhandle *handle = (lt_dlhandle *) data; + int notfound = access (filename, R_OK); + + /* Bail out if file cannot be read... */ + if (notfound) + return 0; + + /* Try to dlopen the file, but do not continue searching in any + case. */ + if (tryall_dlopen (handle, filename) != 0) + *handle = 0; + + return 1; +} + +/* If HANDLE was found return it, otherwise return 0. If HANDLE was + found but could not be opened, *HANDLE will be set to 0. */ +static lt_dlhandle * +find_handle (search_path, base_name, handle) + const char *search_path; + const char *base_name; + lt_dlhandle *handle; +{ + if (!search_path) + return 0; + + if (!foreach_dirinpath (search_path, base_name, find_handle_callback, + handle, 0)) + return 0; + + return handle; +} + +static int +load_deplibs (handle, deplibs) + lt_dlhandle handle; + char *deplibs; +{ +#if LTDL_DLOPEN_DEPLIBS + char *p, *save_search_path = 0; + int depcount = 0; + int i; + char **names = 0; +#endif + int errors = 0; + + handle->depcount = 0; + +#if LTDL_DLOPEN_DEPLIBS + if (!deplibs) + { + return errors; + } + ++errors; + + LT_DLMUTEX_LOCK (); + if (user_search_path) + { + save_search_path = lt_estrdup (user_search_path); + if (!save_search_path) + goto cleanup; + } + + /* extract search paths and count deplibs */ + p = deplibs; + while (*p) + { + if (!isspace ((int) *p)) + { + char *end = p+1; + while (*end && !isspace((int) *end)) + { + ++end; + } + + if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0) + { + char save = *end; + *end = 0; /* set a temporary string terminator */ + if (lt_dladdsearchdir(p+2)) + { + goto cleanup; + } + *end = save; + } + else + { + ++depcount; + } + + p = end; + } + else + { + ++p; + } + } + + if (!depcount) + { + errors = 0; + goto cleanup; + } + + names = LT_EMALLOC (char *, depcount * sizeof (char*)); + if (!names) + goto cleanup; + + /* now only extract the actual deplibs */ + depcount = 0; + p = deplibs; + while (*p) + { + if (isspace ((int) *p)) + { + ++p; + } + else + { + char *end = p+1; + while (*end && !isspace ((int) *end)) + { + ++end; + } + + if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0) + { + char *name; + char save = *end; + *end = 0; /* set a temporary string terminator */ + if (strncmp(p, "-l", 2) == 0) + { + size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2); + name = LT_EMALLOC (char, 1+ name_len); + if (name) + sprintf (name, "lib%s", p+2); + } + else + name = lt_estrdup(p); + + if (!name) + goto cleanup_names; + + names[depcount++] = name; + *end = save; + } + p = end; + } + } + + /* load the deplibs (in reverse order) + At this stage, don't worry if the deplibs do not load correctly, + they may already be statically linked into the loading application + for instance. There will be a more enlightening error message + later on if the loaded module cannot resolve all of its symbols. */ + if (depcount) + { + int j = 0; + + handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount); + if (!handle->deplibs) + goto cleanup_names; + + for (i = 0; i < depcount; ++i) + { + handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]); + if (handle->deplibs[j]) + { + ++j; + } + } + + handle->depcount = j; /* Number of successfully loaded deplibs */ + errors = 0; + } + + cleanup_names: + for (i = 0; i < depcount; ++i) + { + LT_DLFREE (names[i]); + } + + cleanup: + LT_DLFREE (names); + /* restore the old search path */ + if (user_search_path) { + LT_DLFREE (user_search_path); + user_search_path = save_search_path; + } + LT_DLMUTEX_UNLOCK (); + +#endif + + return errors; +} + +static int +unload_deplibs (handle) + lt_dlhandle handle; +{ + int i; + int errors = 0; + + if (handle->depcount) + { + for (i = 0; i < handle->depcount; ++i) + { + if (!LT_DLIS_RESIDENT (handle->deplibs[i])) + { + errors += lt_dlclose (handle->deplibs[i]); + } + } + LT_DLFREE (handle->deplibs); + } + + return errors; +} + +static int +trim (dest, str) + char **dest; + const char *str; +{ + /* remove the leading and trailing "'" from str + and store the result in dest */ + const char *end = strrchr (str, '\''); + size_t len = LT_STRLEN (str); + char *tmp; + + LT_DLFREE (*dest); + + if (!end) + return 1; + + if (len > 3 && str[0] == '\'') + { + tmp = LT_EMALLOC (char, end - str); + if (!tmp) + return 1; + + strncpy(tmp, &str[1], (end - str) - 1); + tmp[len-3] = LT_EOS_CHAR; + *dest = tmp; + } + else + { + *dest = 0; + } + + return 0; +} + +static int +free_vars (dlname, oldname, libdir, deplibs) + char *dlname; + char *oldname; + char *libdir; + char *deplibs; +{ + LT_DLFREE (dlname); + LT_DLFREE (oldname); + LT_DLFREE (libdir); + LT_DLFREE (deplibs); + + return 0; +} + +static int +try_dlopen (phandle, filename) + lt_dlhandle *phandle; + const char *filename; +{ + const char * ext = 0; + const char * saved_error = 0; + char * canonical = 0; + char * base_name = 0; + char * dir = 0; + char * name = 0; + int errors = 0; + lt_dlhandle newhandle; + + assert (phandle); + assert (*phandle == 0); + + LT_DLMUTEX_GETERROR (saved_error); + + /* dlopen self? */ + if (!filename) + { + *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); + if (*phandle == 0) + return 1; + + memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); + newhandle = *phandle; + + /* lt_dlclose()ing yourself is very bad! Disallow it. */ + LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG); + + if (tryall_dlopen (&newhandle, 0) != 0) + { + LT_DLFREE (*phandle); + return 1; + } + + goto register_handle; + } + + assert (filename && *filename); + + /* Doing this immediately allows internal functions to safely + assume only canonicalized paths are passed. */ + if (canonicalize_path (filename, &canonical) != 0) + { + ++errors; + goto cleanup; + } + + /* If the canonical module name is a path (relative or absolute) + then split it into a directory part and a name part. */ + base_name = strrchr (canonical, '/'); + if (base_name) + { + size_t dirlen = (1+ base_name) - canonical; + + dir = LT_EMALLOC (char, 1+ dirlen); + if (!dir) + { + ++errors; + goto cleanup; + } + + strncpy (dir, canonical, dirlen); + dir[dirlen] = LT_EOS_CHAR; + + ++base_name; + } + else + base_name = canonical; + + assert (base_name && *base_name); + + /* Check whether we are opening a libtool module (.la extension). */ + ext = strrchr (base_name, '.'); + if (ext && strcmp (ext, archive_ext) == 0) + { + /* this seems to be a libtool module */ + FILE * file = 0; + char * dlname = 0; + char * old_name = 0; + char * libdir = 0; + char * deplibs = 0; + char * line = 0; + size_t line_len; + + /* if we can't find the installed flag, it is probably an + installed libtool archive, produced with an old version + of libtool */ + int installed = 1; + + /* extract the module name from the file name */ + name = LT_EMALLOC (char, ext - base_name + 1); + if (!name) + { + ++errors; + goto cleanup; + } + + /* canonicalize the module name */ + { + size_t i; + for (i = 0; i < ext - base_name; ++i) + { + if (isalnum ((int)(base_name[i]))) + { + name[i] = base_name[i]; + } + else + { + name[i] = '_'; + } + } + name[ext - base_name] = LT_EOS_CHAR; + } + + /* Now try to open the .la file. If there is no directory name + component, try to find it first in user_search_path and then other + prescribed paths. Otherwise (or in any case if the module was not + yet found) try opening just the module name as passed. */ + if (!dir) + { + const char *search_path; + + LT_DLMUTEX_LOCK (); + search_path = user_search_path; + if (search_path) + file = find_file (user_search_path, base_name, &dir); + LT_DLMUTEX_UNLOCK (); + + if (!file) + { + search_path = getenv (LTDL_SEARCHPATH_VAR); + if (search_path) + file = find_file (search_path, base_name, &dir); + } + +#ifdef LTDL_SHLIBPATH_VAR + if (!file) + { + search_path = getenv (LTDL_SHLIBPATH_VAR); + if (search_path) + file = find_file (search_path, base_name, &dir); + } +#endif +#ifdef LTDL_SYSSEARCHPATH + if (!file && sys_search_path) + { + file = find_file (sys_search_path, base_name, &dir); + } +#endif + } + if (!file) + { + file = fopen (filename, LT_READTEXT_MODE); + } + + /* If we didn't find the file by now, it really isn't there. Set + the status flag, and bail out. */ + if (!file) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); + ++errors; + goto cleanup; + } + + line_len = LT_FILENAME_MAX; + line = LT_EMALLOC (char, line_len); + if (!line) + { + fclose (file); + ++errors; + goto cleanup; + } + + /* read the .la file */ + while (!feof (file)) + { + if (!fgets (line, (int) line_len, file)) + { + break; + } + + /* Handle the case where we occasionally need to read a line + that is longer than the initial buffer size. */ + while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file))) + { + line = LT_DLREALLOC (char, line, line_len *2); + if (!fgets (&line[line_len -1], (int) line_len +1, file)) + { + break; + } + line_len *= 2; + } + + if (line[0] == '\n' || line[0] == '#') + { + continue; + } + +#undef STR_DLNAME +#define STR_DLNAME "dlname=" + if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0) + { + errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]); + } + +#undef STR_OLD_LIBRARY +#define STR_OLD_LIBRARY "old_library=" + else if (strncmp (line, STR_OLD_LIBRARY, + sizeof (STR_OLD_LIBRARY) - 1) == 0) + { + errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]); + } +#undef STR_LIBDIR +#define STR_LIBDIR "libdir=" + else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0) + { + errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]); + } + +#undef STR_DL_DEPLIBS +#define STR_DL_DEPLIBS "dependency_libs=" + else if (strncmp (line, STR_DL_DEPLIBS, + sizeof (STR_DL_DEPLIBS) - 1) == 0) + { + errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]); + } + else if (strcmp (line, "installed=yes\n") == 0) + { + installed = 1; + } + else if (strcmp (line, "installed=no\n") == 0) + { + installed = 0; + } + +#undef STR_LIBRARY_NAMES +#define STR_LIBRARY_NAMES "library_names=" + else if (! dlname && strncmp (line, STR_LIBRARY_NAMES, + sizeof (STR_LIBRARY_NAMES) - 1) == 0) + { + char *last_libname; + errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]); + if (!errors + && dlname + && (last_libname = strrchr (dlname, ' ')) != 0) + { + last_libname = lt_estrdup (last_libname + 1); + if (!last_libname) + { + ++errors; + goto cleanup; + } + LT_DLMEM_REASSIGN (dlname, last_libname); + } + } + + if (errors) + break; + } + + fclose (file); + LT_DLFREE (line); + + /* allocate the handle */ + *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); + if (*phandle == 0) + ++errors; + + if (errors) + { + free_vars (dlname, old_name, libdir, deplibs); + LT_DLFREE (*phandle); + goto cleanup; + } + + assert (*phandle); + + memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); + if (load_deplibs (*phandle, deplibs) == 0) + { + newhandle = *phandle; + /* find_module may replace newhandle */ + if (find_module (&newhandle, dir, libdir, dlname, old_name, installed)) + { + unload_deplibs (*phandle); + ++errors; + } + } + else + { + ++errors; + } + + free_vars (dlname, old_name, libdir, deplibs); + if (errors) + { + LT_DLFREE (*phandle); + goto cleanup; + } + + if (*phandle != newhandle) + { + unload_deplibs (*phandle); + } + } + else + { + /* not a libtool module */ + *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); + if (*phandle == 0) + { + ++errors; + goto cleanup; + } + + memset (*phandle, 0, sizeof (struct lt_dlhandle_struct)); + newhandle = *phandle; + + /* If the module has no directory name component, try to find it + first in user_search_path and then other prescribed paths. + Otherwise (or in any case if the module was not yet found) try + opening just the module name as passed. */ + if ((dir || (!find_handle (user_search_path, base_name, &newhandle) + && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name, + &newhandle) +#ifdef LTDL_SHLIBPATH_VAR + && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name, + &newhandle) +#endif +#ifdef LTDL_SYSSEARCHPATH + && !find_handle (sys_search_path, base_name, &newhandle) +#endif + ))) + { + if (tryall_dlopen (&newhandle, filename) != 0) + { + newhandle = NULL; + } + } + + if (!newhandle) + { + LT_DLFREE (*phandle); + ++errors; + goto cleanup; + } + } + + register_handle: + LT_DLMEM_REASSIGN (*phandle, newhandle); + + if ((*phandle)->info.ref_count == 0) + { + (*phandle)->info.ref_count = 1; + LT_DLMEM_REASSIGN ((*phandle)->info.name, name); + + LT_DLMUTEX_LOCK (); + (*phandle)->next = handles; + handles = *phandle; + LT_DLMUTEX_UNLOCK (); + } + + LT_DLMUTEX_SETERROR (saved_error); + + cleanup: + LT_DLFREE (dir); + LT_DLFREE (name); + LT_DLFREE (canonical); + + return errors; +} + +lt_dlhandle +lt_dlopen (filename) + const char *filename; +{ + lt_dlhandle handle = 0; + + /* Just incase we missed a code path in try_dlopen() that reports + an error, but forgets to reset handle... */ + if (try_dlopen (&handle, filename) != 0) + return 0; + + return handle; +} + +/* If the last error messge store was `FILE_NOT_FOUND', then return + non-zero. */ +static int +file_not_found () +{ + const char *error = 0; + + LT_DLMUTEX_GETERROR (error); + if (error == LT_DLSTRERROR (FILE_NOT_FOUND)) + return 1; + + return 0; +} + +/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to + open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT, + and if a file is still not found try again with SHLIB_EXT appended + instead. */ +lt_dlhandle +lt_dlopenext (filename) + const char *filename; +{ + lt_dlhandle handle = 0; + char * tmp = 0; + char * ext = 0; + size_t len; + int errors = 0; + + if (!filename) + { + return lt_dlopen (filename); + } + + assert (filename); + + len = LT_STRLEN (filename); + ext = strrchr (filename, '.'); + + /* If FILENAME already bears a suitable extension, there is no need + to try appending additional extensions. */ + if (ext && ((strcmp (ext, archive_ext) == 0) +#ifdef LTDL_SHLIB_EXT + || (strcmp (ext, shlib_ext) == 0) +#endif + )) + { + return lt_dlopen (filename); + } + + /* First try appending ARCHIVE_EXT. */ + tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1); + if (!tmp) + return 0; + + strcpy (tmp, filename); + strcat (tmp, archive_ext); + errors = try_dlopen (&handle, tmp); + + /* If we found FILENAME, stop searching -- whether we were able to + load the file as a module or not. If the file exists but loading + failed, it is better to return an error message here than to + report FILE_NOT_FOUND when the alternatives (foo.so etc) are not + in the module search path. */ + if (handle || ((errors > 0) && !file_not_found ())) + { + LT_DLFREE (tmp); + return handle; + } + +#ifdef LTDL_SHLIB_EXT + /* Try appending SHLIB_EXT. */ + if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext)) + { + LT_DLFREE (tmp); + tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1); + if (!tmp) + return 0; + + strcpy (tmp, filename); + } + else + { + tmp[len] = LT_EOS_CHAR; + } + + strcat(tmp, shlib_ext); + errors = try_dlopen (&handle, tmp); + + /* As before, if the file was found but loading failed, return now + with the current error message. */ + if (handle || ((errors > 0) && !file_not_found ())) + { + LT_DLFREE (tmp); + return handle; + } +#endif + + /* Still here? Then we really did fail to locate any of the file + names we tried. */ + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); + LT_DLFREE (tmp); + return 0; +} + + +static int +lt_argz_insert (pargz, pargz_len, before, entry) + char **pargz; + size_t *pargz_len; + char *before; + const char *entry; +{ + error_t error; + + /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz, + pargz_len, NULL, entry) failed with EINVAL. */ + if (before) + error = argz_insert (pargz, pargz_len, before, entry); + else + error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry)); + + if (error) + { + switch (error) + { + case ENOMEM: + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); + break; + default: + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); + break; + } + return 1; + } + + return 0; +} + +static int +lt_argz_insertinorder (pargz, pargz_len, entry) + char **pargz; + size_t *pargz_len; + const char *entry; +{ + char *before = 0; + + assert (pargz); + assert (pargz_len); + assert (entry && *entry); + + if (*pargz) + while ((before = argz_next (*pargz, *pargz_len, before))) + { + int cmp = strcmp (entry, before); + + if (cmp < 0) break; + if (cmp == 0) return 0; /* No duplicates! */ + } + + return lt_argz_insert (pargz, pargz_len, before, entry); +} + +static int +lt_argz_insertdir (pargz, pargz_len, dirnam, dp) + char **pargz; + size_t *pargz_len; + const char *dirnam; + struct dirent *dp; +{ + char *buf = 0; + size_t buf_len = 0; + char *end = 0; + size_t end_offset = 0; + size_t dir_len = 0; + int errors = 0; + + assert (pargz); + assert (pargz_len); + assert (dp); + + dir_len = LT_STRLEN (dirnam); + end = dp->d_name + LT_D_NAMLEN(dp); + + /* Ignore version numbers. */ + { + char *p; + for (p = end; p -1 > dp->d_name; --p) + if (strchr (".0123456789", p[-1]) == 0) + break; + + if (*p == '.') + end = p; + } + + /* Ignore filename extension. */ + { + char *p; + for (p = end -1; p > dp->d_name; --p) + if (*p == '.') + { + end = p; + break; + } + } + + /* Prepend the directory name. */ + end_offset = end - dp->d_name; + buf_len = dir_len + 1+ end_offset; + buf = LT_EMALLOC (char, 1+ buf_len); + if (!buf) + return ++errors; + + assert (buf); + + strcpy (buf, dirnam); + strcat (buf, "/"); + strncat (buf, dp->d_name, end_offset); + buf[buf_len] = LT_EOS_CHAR; + + /* Try to insert (in order) into ARGZ/ARGZ_LEN. */ + if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0) + ++errors; + + LT_DLFREE (buf); + + return errors; +} + +static int +list_files_by_dir (dirnam, pargz, pargz_len) + const char *dirnam; + char **pargz; + size_t *pargz_len; +{ + DIR *dirp = 0; + int errors = 0; + + assert (dirnam && *dirnam); + assert (pargz); + assert (pargz_len); + assert (dirnam[LT_STRLEN(dirnam) -1] != '/'); + + dirp = opendir (dirnam); + if (dirp) + { + struct dirent *dp = 0; + + while ((dp = readdir (dirp))) + if (dp->d_name[0] != '.') + if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp)) + { + ++errors; + break; + } + + closedir (dirp); + } + else + ++errors; + + return errors; +} + + +/* If there are any files in DIRNAME, call the function passed in + DATA1 (with the name of each file and DATA2 as arguments). */ +static int +foreachfile_callback (dirname, data1, data2) + char *dirname; + lt_ptr data1; + lt_ptr data2; +{ + int (*func) LT_PARAMS((const char *filename, lt_ptr data)) + = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1; + + int is_done = 0; + char *argz = 0; + size_t argz_len = 0; + + if (list_files_by_dir (dirname, &argz, &argz_len) != 0) + goto cleanup; + if (!argz) + goto cleanup; + + { + char *filename = 0; + while ((filename = argz_next (argz, argz_len, filename))) + if ((is_done = (*func) (filename, data2))) + break; + } + + cleanup: + LT_DLFREE (argz); + + return is_done; +} + + +/* Call FUNC for each unique extensionless file in SEARCH_PATH, along + with DATA. The filenames passed to FUNC would be suitable for + passing to lt_dlopenext. The extensions are stripped so that + individual modules do not generate several entries (e.g. libfoo.la, + libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL, + then the same directories that lt_dlopen would search are examined. */ +int +lt_dlforeachfile (search_path, func, data) + const char *search_path; + int (*func) LT_PARAMS ((const char *filename, lt_ptr data)); + lt_ptr data; +{ + int is_done = 0; + + if (search_path) + { + /* If a specific path was passed, search only the directories + listed in it. */ + is_done = foreach_dirinpath (search_path, 0, + foreachfile_callback, func, data); + } + else + { + /* Otherwise search the default paths. */ + is_done = foreach_dirinpath (user_search_path, 0, + foreachfile_callback, func, data); + if (!is_done) + { + is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0, + foreachfile_callback, func, data); + } + +#ifdef LTDL_SHLIBPATH_VAR + if (!is_done) + { + is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0, + foreachfile_callback, func, data); + } +#endif +#ifdef LTDL_SYSSEARCHPATH + if (!is_done) + { + is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0, + foreachfile_callback, func, data); + } +#endif + } + + return is_done; +} + +int +lt_dlclose (handle) + lt_dlhandle handle; +{ + lt_dlhandle cur, last; + int errors = 0; + + LT_DLMUTEX_LOCK (); + + /* check whether the handle is valid */ + last = cur = handles; + while (cur && handle != cur) + { + last = cur; + cur = cur->next; + } + + if (!cur) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); + ++errors; + goto done; + } + + handle->info.ref_count--; + + /* Note that even with resident modules, we must track the ref_count + correctly incase the user decides to reset the residency flag + later (even though the API makes no provision for that at the + moment). */ + if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle)) + { + lt_user_data data = handle->loader->dlloader_data; + + if (handle != handles) + { + last->next = handle->next; + } + else + { + handles = handle->next; + } + + errors += handle->loader->module_close (data, handle->module); + errors += unload_deplibs(handle); + + /* It is up to the callers to free the data itself. */ + LT_DLFREE (handle->caller_data); + + LT_DLFREE (handle->info.filename); + LT_DLFREE (handle->info.name); + LT_DLFREE (handle); + + goto done; + } + + if (LT_DLIS_RESIDENT (handle)) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE)); + ++errors; + } + + done: + LT_DLMUTEX_UNLOCK (); + + return errors; +} + +lt_ptr +lt_dlsym (handle, symbol) + lt_dlhandle handle; + const char *symbol; +{ + size_t lensym; + char lsym[LT_SYMBOL_LENGTH]; + char *sym; + lt_ptr address; + lt_user_data data; + + if (!handle) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); + return 0; + } + + if (!symbol) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); + return 0; + } + + lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix) + + LT_STRLEN (handle->info.name); + + if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH) + { + sym = lsym; + } + else + { + sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1); + if (!sym) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW)); + return 0; + } + } + + data = handle->loader->dlloader_data; + if (handle->info.name) + { + const char *saved_error; + + LT_DLMUTEX_GETERROR (saved_error); + + /* this is a libtool module */ + if (handle->loader->sym_prefix) + { + strcpy(sym, handle->loader->sym_prefix); + strcat(sym, handle->info.name); + } + else + { + strcpy(sym, handle->info.name); + } + + strcat(sym, "_LTX_"); + strcat(sym, symbol); + + /* try "modulename_LTX_symbol" */ + address = handle->loader->find_sym (data, handle->module, sym); + if (address) + { + if (sym != lsym) + { + LT_DLFREE (sym); + } + return address; + } + LT_DLMUTEX_SETERROR (saved_error); + } + + /* otherwise try "symbol" */ + if (handle->loader->sym_prefix) + { + strcpy(sym, handle->loader->sym_prefix); + strcat(sym, symbol); + } + else + { + strcpy(sym, symbol); + } + + address = handle->loader->find_sym (data, handle->module, sym); + if (sym != lsym) + { + LT_DLFREE (sym); + } + + return address; +} + +const char * +lt_dlerror () +{ + const char *error; + + LT_DLMUTEX_GETERROR (error); + LT_DLMUTEX_SETERROR (0); + + return error ? error : NULL; +} + +static int +lt_dlpath_insertdir (ppath, before, dir) + char **ppath; + char *before; + const char *dir; +{ + int errors = 0; + char *canonical = 0; + char *argz = 0; + size_t argz_len = 0; + + assert (ppath); + assert (dir && *dir); + + if (canonicalize_path (dir, &canonical) != 0) + { + ++errors; + goto cleanup; + } + + assert (canonical && *canonical); + + /* If *PPATH is empty, set it to DIR. */ + if (*ppath == 0) + { + assert (!before); /* BEFORE cannot be set without PPATH. */ + assert (dir); /* Without DIR, don't call this function! */ + + *ppath = lt_estrdup (dir); + if (*ppath == 0) + ++errors; + + return errors; + } + + assert (ppath && *ppath); + + if (argzize_path (*ppath, &argz, &argz_len) != 0) + { + ++errors; + goto cleanup; + } + + /* Convert BEFORE into an equivalent offset into ARGZ. This only works + if *PPATH is already canonicalized, and hence does not change length + with respect to ARGZ. We canonicalize each entry as it is added to + the search path, and don't call this function with (uncanonicalized) + user paths, so this is a fair assumption. */ + if (before) + { + assert (*ppath <= before); + assert (before - *ppath <= strlen (*ppath)); + + before = before - *ppath + argz; + } + + if (lt_argz_insert (&argz, &argz_len, before, dir) != 0) + { + ++errors; + goto cleanup; + } + + argz_stringify (argz, argz_len, LT_PATHSEP_CHAR); + LT_DLMEM_REASSIGN (*ppath, argz); + + cleanup: + LT_DLFREE (canonical); + LT_DLFREE (argz); + + return errors; +} + +int +lt_dladdsearchdir (search_dir) + const char *search_dir; +{ + int errors = 0; + + if (search_dir && *search_dir) + { + LT_DLMUTEX_LOCK (); + if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0) + ++errors; + LT_DLMUTEX_UNLOCK (); + } + + return errors; +} + +int +lt_dlinsertsearchdir (before, search_dir) + const char *before; + const char *search_dir; +{ + int errors = 0; + + if (before) + { + LT_DLMUTEX_LOCK (); + if ((before < user_search_path) + || (before >= user_search_path + LT_STRLEN (user_search_path))) + { + LT_DLMUTEX_UNLOCK (); + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION)); + return 1; + } + LT_DLMUTEX_UNLOCK (); + } + + if (search_dir && *search_dir) + { + LT_DLMUTEX_LOCK (); + if (lt_dlpath_insertdir (&user_search_path, + (char *) before, search_dir) != 0) + { + ++errors; + } + LT_DLMUTEX_UNLOCK (); + } + + return errors; +} + +int +lt_dlsetsearchpath (search_path) + const char *search_path; +{ + int errors = 0; + + LT_DLMUTEX_LOCK (); + LT_DLFREE (user_search_path); + LT_DLMUTEX_UNLOCK (); + + if (!search_path || !LT_STRLEN (search_path)) + { + return errors; + } + + LT_DLMUTEX_LOCK (); + if (canonicalize_path (search_path, &user_search_path) != 0) + ++errors; + LT_DLMUTEX_UNLOCK (); + + return errors; +} + +const char * +lt_dlgetsearchpath () +{ + const char *saved_path; + + LT_DLMUTEX_LOCK (); + saved_path = user_search_path; + LT_DLMUTEX_UNLOCK (); + + return saved_path; +} + +int +lt_dlmakeresident (handle) + lt_dlhandle handle; +{ + int errors = 0; + + if (!handle) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); + ++errors; + } + else + { + LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG); + } + + return errors; +} + +int +lt_dlisresident (handle) + lt_dlhandle handle; +{ + if (!handle) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); + return -1; + } + + return LT_DLIS_RESIDENT (handle); +} + + + + +/* --- MODULE INFORMATION --- */ + +const lt_dlinfo * +lt_dlgetinfo (handle) + lt_dlhandle handle; +{ + if (!handle) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); + return 0; + } + + return &(handle->info); +} + +lt_dlhandle +lt_dlhandle_next (place) + lt_dlhandle place; +{ + return place ? place->next : handles; +} + +int +lt_dlforeach (func, data) + int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data)); + lt_ptr data; +{ + int errors = 0; + lt_dlhandle cur; + + LT_DLMUTEX_LOCK (); + + cur = handles; + while (cur) + { + lt_dlhandle tmp = cur; + + cur = cur->next; + if ((*func) (tmp, data)) + { + ++errors; + break; + } + } + + LT_DLMUTEX_UNLOCK (); + + return errors; +} + +lt_dlcaller_id +lt_dlcaller_register () +{ + static lt_dlcaller_id last_caller_id = 0; + int result; + + LT_DLMUTEX_LOCK (); + result = ++last_caller_id; + LT_DLMUTEX_UNLOCK (); + + return result; +} + +lt_ptr +lt_dlcaller_set_data (key, handle, data) + lt_dlcaller_id key; + lt_dlhandle handle; + lt_ptr data; +{ + int n_elements = 0; + lt_ptr stale = (lt_ptr) 0; + int i; + + /* This needs to be locked so that the caller data can be updated + simultaneously by different threads. */ + LT_DLMUTEX_LOCK (); + + if (handle->caller_data) + while (handle->caller_data[n_elements].key) + ++n_elements; + + for (i = 0; i < n_elements; ++i) + { + if (handle->caller_data[i].key == key) + { + stale = handle->caller_data[i].data; + break; + } + } + + /* Ensure that there is enough room in this handle's caller_data + array to accept a new element (and an empty end marker). */ + if (i == n_elements) + { + lt_caller_data *temp + = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements); + + if (!temp) + { + stale = 0; + goto done; + } + + handle->caller_data = temp; + + /* We only need this if we needed to allocate a new caller_data. */ + handle->caller_data[i].key = key; + handle->caller_data[1+ i].key = 0; + } + + handle->caller_data[i].data = data; + + done: + LT_DLMUTEX_UNLOCK (); + + return stale; +} + +lt_ptr +lt_dlcaller_get_data (key, handle) + lt_dlcaller_id key; + lt_dlhandle handle; +{ + lt_ptr result = (lt_ptr) 0; + + /* This needs to be locked so that the caller data isn't updated by + another thread part way through this function. */ + LT_DLMUTEX_LOCK (); + + /* Locate the index of the element with a matching KEY. */ + { + int i; + for (i = 0; handle->caller_data[i].key; ++i) + { + if (handle->caller_data[i].key == key) + { + result = handle->caller_data[i].data; + break; + } + } + } + + LT_DLMUTEX_UNLOCK (); + + return result; +} + + + +/* --- USER MODULE LOADER API --- */ + + +int +lt_dlloader_add (place, dlloader, loader_name) + lt_dlloader *place; + const struct lt_user_dlloader *dlloader; + const char *loader_name; +{ + int errors = 0; + lt_dlloader *node = 0, *ptr = 0; + + if ((dlloader == 0) /* diagnose null parameters */ + || (dlloader->module_open == 0) + || (dlloader->module_close == 0) + || (dlloader->find_sym == 0)) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); + return 1; + } + + /* Create a new dlloader node with copies of the user callbacks. */ + node = LT_EMALLOC (lt_dlloader, 1); + if (!node) + return 1; + + node->next = 0; + node->loader_name = loader_name; + node->sym_prefix = dlloader->sym_prefix; + node->dlloader_exit = dlloader->dlloader_exit; + node->module_open = dlloader->module_open; + node->module_close = dlloader->module_close; + node->find_sym = dlloader->find_sym; + node->dlloader_data = dlloader->dlloader_data; + + LT_DLMUTEX_LOCK (); + if (!loaders) + { + /* If there are no loaders, NODE becomes the list! */ + loaders = node; + } + else if (!place) + { + /* If PLACE is not set, add NODE to the end of the + LOADERS list. */ + for (ptr = loaders; ptr->next; ptr = ptr->next) + { + /*NOWORK*/; + } + + ptr->next = node; + } + else if (loaders == place) + { + /* If PLACE is the first loader, NODE goes first. */ + node->next = place; + loaders = node; + } + else + { + /* Find the node immediately preceding PLACE. */ + for (ptr = loaders; ptr->next != place; ptr = ptr->next) + { + /*NOWORK*/; + } + + if (ptr->next != place) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); + ++errors; + } + else + { + /* Insert NODE between PTR and PLACE. */ + node->next = place; + ptr->next = node; + } + } + + LT_DLMUTEX_UNLOCK (); + + return errors; +} + +int +lt_dlloader_remove (loader_name) + const char *loader_name; +{ + lt_dlloader *place = lt_dlloader_find (loader_name); + lt_dlhandle handle; + int errors = 0; + + if (!place) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); + return 1; + } + + LT_DLMUTEX_LOCK (); + + /* Fail if there are any open modules which use this loader. */ + for (handle = handles; handle; handle = handle->next) + { + if (handle->loader == place) + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER)); + ++errors; + goto done; + } + } + + if (place == loaders) + { + /* PLACE is the first loader in the list. */ + loaders = loaders->next; + } + else + { + /* Find the loader before the one being removed. */ + lt_dlloader *prev; + for (prev = loaders; prev->next; prev = prev->next) + { + if (!strcmp (prev->next->loader_name, loader_name)) + { + break; + } + } + + place = prev->next; + prev->next = prev->next->next; + } + + if (place->dlloader_exit) + { + errors = place->dlloader_exit (place->dlloader_data); + } + + LT_DLFREE (place); + + done: + LT_DLMUTEX_UNLOCK (); + + return errors; +} + +lt_dlloader * +lt_dlloader_next (place) + lt_dlloader *place; +{ + lt_dlloader *next; + + LT_DLMUTEX_LOCK (); + next = place ? place->next : loaders; + LT_DLMUTEX_UNLOCK (); + + return next; +} + +const char * +lt_dlloader_name (place) + lt_dlloader *place; +{ + const char *name = 0; + + if (place) + { + LT_DLMUTEX_LOCK (); + name = place ? place->loader_name : 0; + LT_DLMUTEX_UNLOCK (); + } + else + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); + } + + return name; +} + +lt_user_data * +lt_dlloader_data (place) + lt_dlloader *place; +{ + lt_user_data *data = 0; + + if (place) + { + LT_DLMUTEX_LOCK (); + data = place ? &(place->dlloader_data) : 0; + LT_DLMUTEX_UNLOCK (); + } + else + { + LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); + } + + return data; +} + +lt_dlloader * +lt_dlloader_find (loader_name) + const char *loader_name; +{ + lt_dlloader *place = 0; + + LT_DLMUTEX_LOCK (); + for (place = loaders; place; place = place->next) + { + if (strcmp (place->loader_name, loader_name) == 0) + { + break; + } + } + LT_DLMUTEX_UNLOCK (); + + return place; +} diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h new file mode 100644 index 000000000..1f2b9716c --- /dev/null +++ b/libltdl/ltdl.h @@ -0,0 +1,367 @@ +/* ltdl.h -- generic dlopen functions + Copyright (C) 1998-2001, 2003, 2004, 2007 Free Software Foundation, Inc. + Originally by Thomas Tanner + This file is part of GNU Libtool. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +As a special exception to the GNU Lesser General Public License, +if you distribute this file as part of a program or library that +is built using GNU libtool, you may include it under the same +distribution terms that you use for the rest of that program. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA +*/ + +/* Only include this header file once. */ +#ifndef LTDL_H +#define LTDL_H 1 + +#include /* for size_t declaration */ + + +/* --- MACROS FOR PORTABILITY --- */ + + +/* Saves on those hard to debug '\0' typos.... */ +#define LT_EOS_CHAR '\0' + +/* LTDL_BEGIN_C_DECLS should be used at the beginning of your declarations, + so that C++ compilers don't mangle their names. Use LTDL_END_C_DECLS at + the end of C declarations. */ +#ifdef __cplusplus +# define LT_BEGIN_C_DECLS extern "C" { +# define LT_END_C_DECLS } +#else +# define LT_BEGIN_C_DECLS /* empty */ +# define LT_END_C_DECLS /* empty */ +#endif + +LT_BEGIN_C_DECLS + + +/* LT_PARAMS is a macro used to wrap function prototypes, so that compilers + that don't understand ANSI C prototypes still work, and ANSI C + compilers can issue warnings about type mismatches. */ +#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus) +# define LT_PARAMS(protos) protos +# define lt_ptr void* +#else +# define LT_PARAMS(protos) () +# define lt_ptr char* +#endif + +/* LT_STMT_START/END are used to create macros which expand to a + a single compound statement in a portable way. */ +#if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) +# define LT_STMT_START (void)( +# define LT_STMT_END ) +#else +# if (defined (sun) || defined (__sun__)) +# define LT_STMT_START if (1) +# define LT_STMT_END else (void)0 +# else +# define LT_STMT_START do +# define LT_STMT_END while (0) +# endif +#endif + +/* LT_CONC creates a new concatenated symbol for the compiler + in a portable way. */ +#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER) || defined(_AIX) +# define LT_CONC(s,t) s##t +#else +# define LT_CONC(s,t) s/**/t +#endif + +/* LT_STRLEN can be used safely on NULL pointers. */ +#define LT_STRLEN(s) (((s) && (s)[0]) ? strlen (s) : 0) + + + +/* --- WINDOWS SUPPORT --- */ + + +/* Canonicalise Windows and Cygwin recognition macros. */ +#ifdef __CYGWIN32__ +# ifndef __CYGWIN__ +# define __CYGWIN__ __CYGWIN32__ +# endif +#endif +#if defined(_WIN32) || defined(WIN32) +# ifndef __WINDOWS__ +# ifdef _WIN32 +# define __WINDOWS__ _WIN32 +# else +# ifdef WIN32 +# define __WINDOWS__ WIN32 +# endif +# endif +# endif +#endif + + +#ifdef __WINDOWS__ +# ifndef __CYGWIN__ +/* LT_DIRSEP_CHAR is accepted *in addition* to '/' as a directory + separator when it is set. */ +# define LT_DIRSEP_CHAR '\\' +# define LT_PATHSEP_CHAR ';' +# endif +#endif +#ifndef LT_PATHSEP_CHAR +# define LT_PATHSEP_CHAR ':' +#endif + +/* DLL building support on win32 hosts; mostly to workaround their + ridiculous implementation of data symbol exporting. */ +#ifndef LT_SCOPE +# if defined(__WINDOWS__) || defined(__CYGWIN__) +# ifdef DLL_EXPORT /* defined by libtool (if required) */ +# define LT_SCOPE __declspec(dllexport) +# endif +# ifdef LIBLTDL_DLL_IMPORT /* define if linking with this dll */ + /* note: cygwin/mingw compilers can rely instead on auto-import */ +# define LT_SCOPE extern __declspec(dllimport) +# endif +# endif +# ifndef LT_SCOPE /* static linking or !__WINDOWS__ */ +# define LT_SCOPE extern +# endif +#endif + + +#if defined(_MSC_VER) /* Visual Studio */ +# define R_OK 4 +#endif + + + +/* --- DYNAMIC MODULE LOADING API --- */ + + +typedef struct lt_dlhandle_struct *lt_dlhandle; /* A loaded module. */ + +/* Initialisation and finalisation functions for libltdl. */ +LT_SCOPE int lt_dlinit LT_PARAMS((void)); +LT_SCOPE int lt_dlexit LT_PARAMS((void)); + +/* Module search path manipulation. */ +LT_SCOPE int lt_dladdsearchdir LT_PARAMS((const char *search_dir)); +LT_SCOPE int lt_dlinsertsearchdir LT_PARAMS((const char *before, + const char *search_dir)); +LT_SCOPE int lt_dlsetsearchpath LT_PARAMS((const char *search_path)); +LT_SCOPE const char *lt_dlgetsearchpath LT_PARAMS((void)); +LT_SCOPE int lt_dlforeachfile LT_PARAMS(( + const char *search_path, + int (*func) (const char *filename, lt_ptr data), + lt_ptr data)); + +/* Portable libltdl versions of the system dlopen() API. */ +LT_SCOPE lt_dlhandle lt_dlopen LT_PARAMS((const char *filename)); +LT_SCOPE lt_dlhandle lt_dlopenext LT_PARAMS((const char *filename)); +LT_SCOPE lt_ptr lt_dlsym LT_PARAMS((lt_dlhandle handle, + const char *name)); +LT_SCOPE const char *lt_dlerror LT_PARAMS((void)); +LT_SCOPE int lt_dlclose LT_PARAMS((lt_dlhandle handle)); + +/* Module residency management. */ +LT_SCOPE int lt_dlmakeresident LT_PARAMS((lt_dlhandle handle)); +LT_SCOPE int lt_dlisresident LT_PARAMS((lt_dlhandle handle)); + + + + +/* --- MUTEX LOCKING --- */ + + +typedef void lt_dlmutex_lock LT_PARAMS((void)); +typedef void lt_dlmutex_unlock LT_PARAMS((void)); +typedef void lt_dlmutex_seterror LT_PARAMS((const char *errmsg)); +typedef const char *lt_dlmutex_geterror LT_PARAMS((void)); + +LT_SCOPE int lt_dlmutex_register LT_PARAMS((lt_dlmutex_lock *lock, + lt_dlmutex_unlock *unlock, + lt_dlmutex_seterror *seterror, + lt_dlmutex_geterror *geterror)); + + + + +/* --- MEMORY HANDLING --- */ + + +/* By default, the realloc function pointer is set to our internal + realloc implementation which iself uses lt_dlmalloc and lt_dlfree. + libltdl relies on a featureful realloc, but if you are sure yours + has the right semantics then you can assign it directly. Generally, + it is safe to assign just a malloc() and a free() function. */ +LT_SCOPE lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)); +LT_SCOPE lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)); +LT_SCOPE void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)); + + + + +/* --- PRELOADED MODULE SUPPORT --- */ + + +/* A preopened symbol. Arrays of this type comprise the exported + symbols for a dlpreopened module. */ +typedef struct { + const char *name; + lt_ptr address; +} lt_dlsymlist; + +LT_SCOPE int lt_dlpreload LT_PARAMS((const lt_dlsymlist *preloaded)); +LT_SCOPE int lt_dlpreload_default + LT_PARAMS((const lt_dlsymlist *preloaded)); + +#define LTDL_SET_PRELOADED_SYMBOLS() LT_STMT_START{ \ + extern const lt_dlsymlist lt_preloaded_symbols[]; \ + lt_dlpreload_default(lt_preloaded_symbols); \ + }LT_STMT_END + + + + +/* --- MODULE INFORMATION --- */ + + +/* Read only information pertaining to a loaded module. */ +typedef struct { + char *filename; /* file name */ + char *name; /* module name */ + int ref_count; /* number of times lt_dlopened minus + number of times lt_dlclosed. */ +} lt_dlinfo; + +LT_SCOPE const lt_dlinfo *lt_dlgetinfo LT_PARAMS((lt_dlhandle handle)); +LT_SCOPE lt_dlhandle lt_dlhandle_next LT_PARAMS((lt_dlhandle place)); +LT_SCOPE int lt_dlforeach LT_PARAMS(( + int (*func) (lt_dlhandle handle, lt_ptr data), + lt_ptr data)); + +/* Associating user data with loaded modules. */ +typedef unsigned lt_dlcaller_id; + +LT_SCOPE lt_dlcaller_id lt_dlcaller_register LT_PARAMS((void)); +LT_SCOPE lt_ptr lt_dlcaller_set_data LT_PARAMS((lt_dlcaller_id key, + lt_dlhandle handle, + lt_ptr data)); +LT_SCOPE lt_ptr lt_dlcaller_get_data LT_PARAMS((lt_dlcaller_id key, + lt_dlhandle handle)); + + + +/* --- USER MODULE LOADER API --- */ + + +typedef struct lt_dlloader lt_dlloader; +typedef lt_ptr lt_user_data; +typedef lt_ptr lt_module; + +/* Function pointer types for creating user defined module loaders. */ +typedef lt_module lt_module_open LT_PARAMS((lt_user_data loader_data, + const char *filename)); +typedef int lt_module_close LT_PARAMS((lt_user_data loader_data, + lt_module handle)); +typedef lt_ptr lt_find_sym LT_PARAMS((lt_user_data loader_data, + lt_module handle, + const char *symbol)); +typedef int lt_dlloader_exit LT_PARAMS((lt_user_data loader_data)); + +struct lt_user_dlloader { + const char *sym_prefix; + lt_module_open *module_open; + lt_module_close *module_close; + lt_find_sym *find_sym; + lt_dlloader_exit *dlloader_exit; + lt_user_data dlloader_data; +}; + +LT_SCOPE lt_dlloader *lt_dlloader_next LT_PARAMS((lt_dlloader *place)); +LT_SCOPE lt_dlloader *lt_dlloader_find LT_PARAMS(( + const char *loader_name)); +LT_SCOPE const char *lt_dlloader_name LT_PARAMS((lt_dlloader *place)); +LT_SCOPE lt_user_data *lt_dlloader_data LT_PARAMS((lt_dlloader *place)); +LT_SCOPE int lt_dlloader_add LT_PARAMS((lt_dlloader *place, + const struct lt_user_dlloader *dlloader, + const char *loader_name)); +LT_SCOPE int lt_dlloader_remove LT_PARAMS(( + const char *loader_name)); + + + +/* --- ERROR MESSAGE HANDLING --- */ + + +/* Defining error strings alongside their symbolic names in a macro in + this way allows us to expand the macro in different contexts with + confidence that the enumeration of symbolic names will map correctly + onto the table of error strings. */ +#define lt_dlerror_table \ + LT_ERROR(UNKNOWN, "unknown error") \ + LT_ERROR(DLOPEN_NOT_SUPPORTED, "dlopen support not available") \ + LT_ERROR(INVALID_LOADER, "invalid loader") \ + LT_ERROR(INIT_LOADER, "loader initialization failed") \ + LT_ERROR(REMOVE_LOADER, "loader removal failed") \ + LT_ERROR(FILE_NOT_FOUND, "file not found") \ + LT_ERROR(DEPLIB_NOT_FOUND, "dependency library not found") \ + LT_ERROR(NO_SYMBOLS, "no symbols defined") \ + LT_ERROR(CANNOT_OPEN, "can't open the module") \ + LT_ERROR(CANNOT_CLOSE, "can't close the module") \ + LT_ERROR(SYMBOL_NOT_FOUND, "symbol not found") \ + LT_ERROR(NO_MEMORY, "not enough memory") \ + LT_ERROR(INVALID_HANDLE, "invalid module handle") \ + LT_ERROR(BUFFER_OVERFLOW, "internal buffer overflow") \ + LT_ERROR(INVALID_ERRORCODE, "invalid errorcode") \ + LT_ERROR(SHUTDOWN, "library already shutdown") \ + LT_ERROR(CLOSE_RESIDENT_MODULE, "can't close resident module") \ + LT_ERROR(INVALID_MUTEX_ARGS, "invalid mutex handler registration") \ + LT_ERROR(INVALID_POSITION, "invalid search path insert position") + +/* Enumerate the symbolic error names. */ +enum { +#define LT_ERROR(name, diagnostic) LT_CONC(LT_ERROR_, name), + lt_dlerror_table +#undef LT_ERROR + + LT_ERROR_MAX +}; + +/* These functions are only useful from inside custom module loaders. */ +LT_SCOPE int lt_dladderror LT_PARAMS((const char *diagnostic)); +LT_SCOPE int lt_dlseterror LT_PARAMS((int errorcode)); + + + + +/* --- SOURCE COMPATIBILITY WITH OLD LIBLTDL --- */ + + +#ifdef LT_NON_POSIX_NAMESPACE +# define lt_ptr_t lt_ptr +# define lt_module_t lt_module +# define lt_module_open_t lt_module_open +# define lt_module_close_t lt_module_close +# define lt_find_sym_t lt_find_sym +# define lt_dlloader_exit_t lt_dlloader_exit +# define lt_dlloader_t lt_dlloader +# define lt_dlloader_data_t lt_user_data +#endif + +LT_END_C_DECLS + +#endif /* !LTDL_H */ diff --git a/libltdl/ltmain.sh b/libltdl/ltmain.sh new file mode 100644 index 000000000..f924d3093 --- /dev/null +++ b/libltdl/ltmain.sh @@ -0,0 +1,6938 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +basename="s,^.*/,,g" + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +progname=`echo "$progpath" | $SED $basename` +modename="$progname" + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION="1.5.24 Debian 1.5.24-1" +TIMESTAMP=" (1.1220.2.456 2007/06/24 02:25:32)" + +# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE). +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +duplicate_deps=no +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $mkdir "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || { + $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 + exit $EXIT_FAILURE + } + fi + + $echo "X$my_tmpdir" | $Xsed +} + + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ + $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | \ + $SED -n -e '1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $echo $win32_libid_type +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case "$@ " in + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + $echo "$modename: unable to infer tagged configuration" + $echo "$modename: specify a tag with \`--tag'" 1>&2 + exit $EXIT_FAILURE +# else +# $echo "$modename: using $tagname tagged configuration" + fi + ;; + esac + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + + $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" + $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 + exit $EXIT_FAILURE + fi +} + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + extracted_serial=`expr $extracted_serial + 1` + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then + exit $exit_status + fi + case $host in + *-darwin*) + $show "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + if test -z "$run"; then + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` + darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` + if test -n "$darwin_arches"; then + darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + $show "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we have a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + lipo -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + ${rm}r unfat-$$ + cd "$darwin_orig_dir" + else + cd "$darwin_orig_dir" + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + fi # $run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + func_extract_archives_result="$my_oldobjs" +} +# End of Shell function definitions +##################################### + +# Darwin sucks +eval std_shrext=\"$shrext_cmds\" + +disable_libs=no + +# Parse our command line options once, thoroughly. +while test "$#" -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + tag) + tagname="$arg" + preserve_args="${preserve_args}=$arg" + + # Check whether tagname contains only valid characters + case $tagname in + *[!-_A-Za-z0-9,/]*) + $echo "$progname: invalid tag name: $tagname" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $tagname in + CC) + # Don't test for the "default" C tag, as we know, it's there, but + # not specially marked. + ;; + *) + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then + taglist="$taglist $tagname" + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" + else + $echo "$progname: ignoring unknown tag $tagname" 1>&2 + fi + ;; + esac + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + echo "\ +$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP + +Copyright (C) 2007 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit $? + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath + # Now print the configurations for the tags. + for tagname in $taglist; do + ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" + done + exit $? + ;; + + --debug) + $echo "$progname: enabling shell trace mode" + set -x + preserve_args="$preserve_args $arg" + ;; + + --dry-run | -n) + run=: + ;; + + --features) + $echo "host: $host" + if test "$build_libtool_libs" = yes; then + $echo "enable shared libraries" + else + $echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + $echo "enable static libraries" + else + $echo "disable static libraries" + fi + exit $? + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + preserve_args="$preserve_args $arg" + ;; + + --tag) + prevopt="--tag" + prev=tag + preserve_args="$preserve_args --tag" + ;; + --tag=*) + set tag "$optarg" ${1+"$@"} + shift + prev=tag + preserve_args="$preserve_args --tag" + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE +fi + +case $disable_libs in +no) + ;; +shared) + build_libtool_libs=no + build_old_libs=yes + ;; +static) + build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` + ;; +esac + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 + $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 + case $nonopt in + *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + if test -n "$libobj" ; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit $EXIT_FAILURE + fi + arg_mode=target + continue + ;; + + -static | -prefer-pic | -prefer-non-pic) + later="$later $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + base_compile="$base_compile $lastarg" + continue + ;; + + * ) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + case $lastarg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, and some SunOS ksh mistreat backslash-escaping + # in scan sets (worked around with variable expansion), + # and furthermore cannot handle '|' '&' '(' ')' in scan sets + # at all, so we specify them separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + base_compile="$base_compile $lastarg" + done # for arg + + case $arg_mode in + arg) + $echo "$modename: you must specify an argument for -Xcompile" + exit $EXIT_FAILURE + ;; + target) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit $EXIT_FAILURE + ;; + *) + # Get the name of the library object. + [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSifmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.ii) xform=ii ;; + *.class) xform=class ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.[fF][09]?) xform=[fF][09]. ;; + *.for) xform=for ;; + *.java) xform=java ;; + *.obj) xform=obj ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` + case $qlibobj in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qlibobj="\"$qlibobj\"" ;; + esac + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." + objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir= + else + xdir=$xdir/ + fi + lobj=${xdir}$objdir/$objname + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$progpath" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + $echo "$srcfile" > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` + case $qsrcfile in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qsrcfile="\"$qsrcfile\"" ;; + esac + + $run $rm "$libobj" "${libobj}T" + + # Create a libtool object file (analogous to a ".la" file), + # but don't create it if we're doing a dry run. + test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + $show "$mv $output_obj $lobj" + if $run $mv $output_obj $lobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the PIC object to the libtool object file. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit $EXIT_FAILURE + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat $save_arg` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + done + else + $echo "$modename: link input file \`$save_arg' does not exist" + exit $EXIT_FAILURE + fi + arg=$save_arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + darwin_framework|darwin_framework_skip) + test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit $EXIT_FAILURE + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework|-arch|-isysroot) + case " $CC " in + *" ${arg} ${1} "* | *" ${arg} ${1} "*) + prev=darwin_framework_skip ;; + *) compiler_flags="$compiler_flags $arg" + prev=darwin_framework ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + notinst_path="$notinst_path $dir" + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs -framework System" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + -model) + compile_command="$compile_command $arg" + compiler_flags="$compiler_flags $arg" + finalize_command="$finalize_command $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m* pass through architecture-specific compiler args for GCC + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC + # -F/path gives path to uninstalled frameworks, gcc on darwin + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) + + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then + exit $exit_status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + case $host in + *cygwin* | *mingw* | *pw32*) + # don't eliminate duplications in $postdeps and $predeps + duplicate_compiler_generated_deps=yes + ;; + *) + duplicate_compiler_generated_deps=$duplicate_deps + ;; + esac + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if (${SED} -e '2q' $lib | + grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + library_names= + old_library= + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + if eval $echo \"$deplib\" 2>/dev/null \ + | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $echo + $echo "*** Warning: Trying to link with static lib archive $deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because the file extensions .$libext of this argument makes me believe" + $echo "*** that it is just a static archive that I should not used here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 + exit $EXIT_FAILURE + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit $EXIT_FAILURE + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $absdir" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes ; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + # This is a shared library + + # Warn about portability, can't link against -module's on + # some systems (darwin) + if test "$shouldnotlink" = yes && test "$pass" = link ; then + $echo + if test "$linkmode" = prog; then + $echo "*** Warning: Linking the executable $output against the loadable module" + else + $echo "*** Warning: Linking the shared library $output against the loadable module" + fi + $echo "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`$echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$extract_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$old_archive_from_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a module then we can not link against + # it, someone is ignoring the new warnings I added + if /usr/bin/file -L $add 2> /dev/null | + $EGREP ": [^:]* bundle" >/dev/null ; then + $echo "** Warning, lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $echo + $echo "** And there doesn't seem to be a static archive available" + $echo "** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit $EXIT_FAILURE + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $echo + $echo "*** Warning: This system can not link to static lib archive $lib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $echo "*** But as you try to build a module library, libtool will still create " + $echo "*** a static module, that should work as long as the dlopening application" + $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="$absdir" + fi + depdepl= + case $host in + *-*-darwin*) + # we do not want to link against static libs, + # but need to link against shared + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$path/$depdepl" ; then + depdepl="$path/$depdepl" + fi + # do not add paths which are already there + case " $newlib_search_path " in + *" $path "*) ;; + *) newlib_search_path="$newlib_search_path $path";; + esac + fi + path="" + ;; + *) + path="-L$path" + ;; + esac + ;; + -l*) + case $host in + *-*-darwin*) + # Again, we only want to link against shared libraries + eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` + for tmp in $newlib_search_path ; do + if test -f "$tmp/lib$tmp_libs.dylib" ; then + eval depdepl="$tmp/lib$tmp_libs.dylib" + break + fi + done + path="" + ;; + *) continue ;; + esac + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + case " $deplibs " in + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit $EXIT_FAILURE + else + $echo + $echo "*** Warning: Linking the shared library $output against the non-libtool" + $echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$2" + number_minor="$3" + number_revision="$4" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + esac + ;; + no) + current="$2" + revision="$3" + age="$4" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + major=`expr $current - $age` + else + major=`expr $current - $age + 1` + fi + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$echo "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + if test -n "$removelist"; then + $show "${rm}r $removelist" + $run ${rm}r $removelist + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + # deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + # dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for file magic test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a file magic. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name=`expr $a_deplib : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval $echo \"$potent_lib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a regex pattern. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` + done + fi + if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ + | grep . >/dev/null; then + $echo + if test "X$deplibs_check_method" = "Xnone"; then + $echo "*** Warning: inter-library dependencies are not supported in this platform." + else + $echo "*** Warning: inter-library dependencies are not known to be supported." + fi + $echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $echo + $echo "*** Warning: libtool could not satisfy all declared inter-library" + $echo "*** dependencies of module $libname. Therefore, libtool will create" + $echo "*** a static module, that should work as long as the dlopening" + $echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $echo "*** The inter-library dependencies that have been dropped here will be" + $echo "*** automatically added whenever a program is linked with this library" + $echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $echo + $echo "*** Since this library must not contain undefined symbols," + $echo "*** because either the platform does not support them or" + $echo "*** it was explicitly requested with -no-undefined," + $echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + case $archive_cmds in + *\$LD*) eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" ;; + *) eval dep_rpath=\"$hardcode_libdir_flag_spec\" ;; + esac + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + if len=`expr "X$cmd" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + $show "$cmd" + $run eval "$cmd" || exit $? + skipped_export=false + else + # The command line is too long to execute in one step. + $show "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise. + $echo "creating reloadable object files..." + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$echo "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + delfiles= + last_robj= + k=1 + output=$output_objdir/$output_la-${k}.$objext + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + if test "X$objlist" = X || + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; }; then + objlist="$objlist $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + k=`expr $k + 1` + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + len=1 + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + + if ${skipped_export-false}; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + libobjs=$output + # Append the command to create the export file. + eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" + fi + + # Set up a command to remove the reloadable object files + # after they are used. + i=0 + while test "$i" -lt "$k" + do + i=`expr $i + 1` + delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" + done + + $echo "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + + # Append the command to remove the reloadable object files + # to the just-reset $cmds. + eval cmds=\"\$cmds~\$rm $delfiles\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit $EXIT_FAILURE + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $run eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + if test "$tagname" = CXX ; then + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + fi + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + else + $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +" + + case $host in + *cygwin* | *mingw* ) + $echo >> "$output_objdir/$dlsyms" "\ +/* DATA imports from DLLs on WIN32 can't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs */ +struct { +" + ;; + * ) + $echo >> "$output_objdir/$dlsyms" "\ +const struct { +" + ;; + esac + + + $echo >> "$output_objdir/$dlsyms" "\ + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + case $host in + *cygwin* | *mingw* ) + if test -f "$output_objdir/${outputname}.def" ; then + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP` + else + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` + fi + ;; + * ) + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` + ;; + esac + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$output"'%g' | $NL2SP` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + exit_status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $exit_status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $SP2NL | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g' | $NL2SP` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + output_name=`basename $output` + output_path=`dirname $output` + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $rm $cwrappersource $cwrapper + trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + cat > $cwrappersource <> $cwrappersource<<"EOF" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +/* -DDEBUG is fairly common in CFLAGS. */ +#undef DEBUG +#if defined DEBUGWRAPPER +# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +# define DEBUG(format, ...) +#endif + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +const char * base_name (const char *name); +char * find_executable(const char *wrapper); +int check_executable(const char *path); +char * strendzap(char *str, const char *pat); +void lt_fatal (const char *message, ...); + +int +main (int argc, char *argv[]) +{ + char **newargz; + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + DEBUG("(main) argv[0] : %s\n",argv[0]); + DEBUG("(main) program_name : %s\n",program_name); + newargz = XMALLOC(char *, argc+2); +EOF + + cat >> $cwrappersource <> $cwrappersource <<"EOF" + newargz[1] = find_executable(argv[0]); + if (newargz[1] == NULL) + lt_fatal("Couldn't find %s", argv[0]); + DEBUG("(main) found exe at : %s\n",newargz[1]); + /* we know the script has the same name, without the .exe */ + /* so make sure newargz[1] doesn't end in .exe */ + strendzap(newargz[1],".exe"); + for (i = 1; i < argc; i++) + newargz[i+1] = xstrdup(argv[i]); + newargz[argc+1] = NULL; + + for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" + return 127; +} + +void * +xmalloc (size_t num) +{ + void * p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL +; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char)name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable(const char * path) +{ + struct stat st; + + DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) && + ( + /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ +#if defined (S_IXOTH) + ((st.st_mode & S_IXOTH) == S_IXOTH) || +#endif +#if defined (S_IXGRP) + ((st.st_mode & S_IXGRP) == S_IXGRP) || +#endif + ((st.st_mode & S_IXUSR) == S_IXUSR)) + ) + return 1; + else + return 0; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise */ +char * +find_executable (const char* wrapper) +{ + int has_slash = 0; + const char* p; + const char* p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char* concat_name; + + DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char* path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char* q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR(*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + return NULL; +} + +char * +strendzap(char *str, const char *pat) +{ + size_t len, patlen; + + assert(str != NULL); + assert(pat != NULL); + + len = strlen(str); + patlen = strlen(pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp(str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char * mode, + const char * message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} +EOF + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE). +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + $echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit $EXIT_FAILURE + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + $echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \$*\" + exit $EXIT_FAILURE + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + $echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit $EXIT_FAILURE + fi +fi\ +" + chmod +x $output + fi + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "copying selected object files to avoid basename conflicts..." + + if test -z "$gentop"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$gentop"; then + exit $exit_status + fi + fi + + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + counter=`expr $counter + 1` + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $run ln "$obj" "$gentop/$newobj" || + $run cp "$obj" "$gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + + eval cmds=\"$old_archive_cmds\" + + if len=`expr "X$cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + $echo "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + for obj in $save_oldobjs + do + oldobjs="$objlist $obj" + objlist="$objlist $obj" + eval test_cmds=\"$old_archive_cmds\" + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + eval cmd=\"$cmd\" + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit $EXIT_SUCCESS + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%" | $NL2SP` + else + relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP` + fi + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit $EXIT_FAILURE + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + cmds=$postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + file=`$echo $file|${SED} 's,.exe$,,'` + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit $EXIT_FAILURE + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir=`func_mktempdir` + file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g' | $NL2SP` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$old_striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + cmds=$old_postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + cmds=$finish_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit $EXIT_SUCCESS + + $echo "X----------------------------------------------------------------------" | $Xsed + $echo "Libraries have been installed in:" + for libdir in $libdirs; do + $echo " $libdir" + done + $echo + $echo "If you ever happen to want to link against installed libraries" + $echo "in a given directory, LIBDIR, you must either use libtool, and" + $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + $echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + $echo " during execution" + fi + if test -n "$runpath_var"; then + $echo " - add LIBDIR to the \`$runpath_var' environment variable" + $echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $echo + $echo "See any operating system documentation about shared libraries for" + $echo "more information, such as the ld(1) and ld.so(8) manual pages." + $echo "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit $EXIT_FAILURE + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + if test ! -f "$dir/$dlname"; then + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit $EXIT_SUCCESS + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + cmds=$postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + cmds=$old_postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + + # Read the .lo file + . $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" \ + && test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" \ + && test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + file=`$echo $file|${SED} 's,.exe$,,'` + noexename=`$echo $name|${SED} 's,.exe$,,'` + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$noexename + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit $EXIT_FAILURE +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE. + +Report bugs to ." + exit $EXIT_SUCCESS + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit $? + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +disable_libs=shared +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +disable_libs=static +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/libltdl/missing b/libltdl/missing new file mode 100755 index 000000000..894e786e1 --- /dev/null +++ b/libltdl/missing @@ -0,0 +1,360 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2005-06-08.21 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/libltdl/mkinstalldirs b/libltdl/mkinstalldirs new file mode 100755 index 000000000..ef7e16fda --- /dev/null +++ b/libltdl/mkinstalldirs @@ -0,0 +1,161 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2006-05-11.19 + +# Original author: Noah Friedman +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' +IFS=" "" $nl" +errstatus=0 +dirmode= + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to ." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit $? + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit $? + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + case $file in + /*) pathcomp=/ ;; + *) pathcomp= ;; + esac + oIFS=$IFS + IFS=/ + set fnord $file + shift + IFS=$oIFS + + for d + do + test "x$d" = x && continue + + pathcomp=$pathcomp$d + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr= + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp=$pathcomp/ + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/libltdl/stamp-h1 b/libltdl/stamp-h1 new file mode 100644 index 000000000..4547fe1b5 --- /dev/null +++ b/libltdl/stamp-h1 @@ -0,0 +1 @@ +timestamp for config.h diff --git a/pulseaudio-text.svg b/pulseaudio-text.svg new file mode 100644 index 000000000..0e1261304 --- /dev/null +++ b/pulseaudio-text.svg @@ -0,0 +1,388 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + PulseAudio logotype + 2006-08-28 + + + Pierre Ossman <ossman@cendio.se> for Cendio AB + + + + + + + + + + Rafael Jannone (basic idea) + + + + + + + + + + + + + + + + + + + + + + + + + + PulseAudio + + diff --git a/src/Makefile.am b/src/Makefile.am index 93f331d6b..e17e5ece4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,6 +30,7 @@ pulseincludedir=$(includedir)/pulse pulsecoreincludedir=$(includedir)/pulsecore pulseconfdir=$(sysconfdir)/pulse pulselibexecdir=$(libexecdir)/pulse +xdgautostartdir=$(sysconfdir)/xdg/autostart ################################### # Defines # @@ -76,15 +77,14 @@ endif if OS_IS_WIN32 PA_THREAD_OBJS = \ - pulsecore/once-win32.c pulsecore/once.h \ pulsecore/mutex-win32.c pulsecore/mutex.h \ - pulsecore/thread-win32.c pulsecore/thread.h + pulsecore/thread-win32.c pulsecore/thread.h \ + pulsecore/semaphore-win32.c pulsecore/semaphore.h else PA_THREAD_OBJS = \ - pulsecore/atomic.h \ - pulsecore/once-posix.c pulsecore/once.h \ pulsecore/mutex-posix.c pulsecore/mutex.h \ - pulsecore/thread-posix.c pulsecore/thread.h + pulsecore/thread-posix.c pulsecore/thread.h \ + pulsecore/semaphore-posix.c pulsecore/semaphore.h endif ################################### @@ -100,13 +100,19 @@ EXTRA_DIST = \ depmod.py \ daemon/esdcompat.in \ utils/padsp \ - modules/module-defs.h.m4 + modules/module-defs.h.m4 \ + daemon/pulseaudio-module-xsmp.desktop pulseconf_DATA = \ default.pa \ daemon.conf \ client.conf +if HAVE_X11 +xdgautostart_DATA = \ + daemon/pulseaudio-module-xsmp.desktop +endif + BUILT_SOURCES = \ pulse/version.h @@ -122,13 +128,13 @@ pulseaudio_SOURCES = \ daemon/cpulimit.c daemon/cpulimit.h \ daemon/daemon-conf.c daemon/daemon-conf.h \ daemon/dumpmodules.c daemon/dumpmodules.h \ + daemon/ltdl-bind-now.c daemon/ltdl-bind-now.h \ daemon/main.c \ pulsecore/gccmacro.h -pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) +pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) $(CAP_CFLAGS) $(LIBOIL_CFLAGS) $(DBUS_CFLAGS) pulseaudio_CPPFLAGS = $(AM_CPPFLAGS) -pulseaudio_LDADD = $(AM_LDADD) libpulsecore.la $(LIBLTDL) \ - $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) +pulseaudio_LDADD = $(AM_LDADD) libpulsecore.la $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) $(DBUS_LIBS) # This is needed because automake doesn't properly expand the foreach below pulseaudio_DEPENDENCIES = libpulsecore.la $(PREOPEN_LIBS) @@ -151,7 +157,8 @@ endif bin_PROGRAMS += \ pacat \ pactl \ - paplay + paplay \ + pasuspender if HAVE_AF_UNIX bin_PROGRAMS += pacmd @@ -182,6 +189,11 @@ pactl_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS) pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +pasuspender_SOURCES = utils/pasuspender.c +pasuspender_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS) +pasuspender_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) +pasuspender_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + pacmd_SOURCES = utils/pacmd.c pulsecore/pid.c pulsecore/pid.h pacmd_CFLAGS = $(AM_CFLAGS) pacmd_LDADD = $(AM_LDADD) libpulse.la @@ -219,7 +231,14 @@ noinst_PROGRAMS = \ hook-list-test \ memblock-test \ thread-test \ - flist-test + flist-test \ + asyncq-test \ + asyncmsgq-test \ + queue-test \ + rtpoll-test \ + sig2str-test \ + resampler-test \ + smoother-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -274,13 +293,31 @@ thread_test_CFLAGS = $(AM_CFLAGS) thread_test_LDADD = $(AM_LDADD) libpulsecore.la thread_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -flist_test_SOURCES = tests/flist-test.c \ - pulsecore/atomic.h \ - pulsecore/flist.c pulsecore/flist.h +flist_test_SOURCES = tests/flist-test.c flist_test_CFLAGS = $(AM_CFLAGS) flist_test_LDADD = $(AM_LDADD) libpulsecore.la flist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +asyncq_test_SOURCES = tests/asyncq-test.c +asyncq_test_CFLAGS = $(AM_CFLAGS) +asyncq_test_LDADD = $(AM_LDADD) libpulsecore.la +asyncq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +asyncmsgq_test_SOURCES = tests/asyncmsgq-test.c +asyncmsgq_test_CFLAGS = $(AM_CFLAGS) +asyncmsgq_test_LDADD = $(AM_LDADD) libpulsecore.la +asyncmsgq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +queue_test_SOURCES = tests/queue-test.c +queue_test_CFLAGS = $(AM_CFLAGS) +queue_test_LDADD = $(AM_LDADD) libpulsecore.la +queue_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +rtpoll_test_SOURCES = tests/rtpoll-test.c +rtpoll_test_CFLAGS = $(AM_CFLAGS) +rtpoll_test_LDADD = $(AM_LDADD) libpulsecore.la +rtpoll_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + mcalign_test_SOURCES = tests/mcalign-test.c mcalign_test_CFLAGS = $(AM_CFLAGS) mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la @@ -341,6 +378,21 @@ interpol_test_LDADD = $(AM_LDADD) libpulse.la interpol_test_CFLAGS = $(AM_CFLAGS) interpol_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +sig2str_test_SOURCES = tests/sig2str-test.c +sig2str_test_LDADD = $(AM_LDADD) libpulsecore.la +sig2str_test_CFLAGS = $(AM_CFLAGS) +sig2str_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + +resampler_test_SOURCES = tests/resampler-test.c +resampler_test_LDADD = $(AM_LDADD) libpulsecore.la +resampler_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) +resampler_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) + +smoother_test_SOURCES = tests/smoother-test.c +smoother_test_LDADD = $(AM_LDADD) libpulsecore.la +smoother_test_CFLAGS = $(AM_CFLAGS) +smoother_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + ################################### # Client library # ################################### @@ -455,6 +507,10 @@ libpulse_la_SOURCES += \ pulsecore/core-error.c pulsecore/core-error.h \ pulsecore/winsock.h pulsecore/creds.h \ pulsecore/shm.c pulsecore/shm.h \ + pulsecore/flist.c pulsecore/flist.h \ + pulsecore/object.c pulsecore/object.h \ + pulsecore/msgobject.c pulsecore/msgobject.h \ + pulsecore/once.c pulsecore/once.h \ $(PA_THREAD_OBJS) if OS_IS_WIN32 @@ -514,11 +570,27 @@ libpulsedsp_la_CFLAGS = $(AM_CFLAGS) libpulsedsp_la_LIBADD = $(AM_LIBADD) libpulse.la libpulsedsp_la_LDFLAGS = -avoid-version +################################### +# Speex Resampler # +################################### + +noinst_LTLIBRARIES = libspeex-resampler-fixed.la libspeex-resampler-float.la libffmpeg-resampler.la + +libspeex_resampler_fixed_la_CPPFLAGS = $(AM_CPPFLAGS) -DRANDOM_PREFIX=paspfx -DOUTSIDE_SPEEX -DFIXED_POINT +libspeex_resampler_fixed_la_SOURCES = pulsecore/speex/resample.c pulsecore/speex/speex_resampler.h pulsecore/speex/arch.h pulsecore/speex/fixed_generic.h pulsecore/speexwrap.h + +libspeex_resampler_float_la_CPPFLAGS = $(AM_CPPFLAGS) -DRANDOM_PREFIX=paspfl -DOUTSIDE_SPEEX +libspeex_resampler_float_la_SOURCES = pulsecore/speex/resample.c pulsecore/speex/speex_resampler.h pulsecore/speex/arch.h + +libffmpeg_resampler_la_CPPFLAGS = $(AM_CPPFLAGS) +libffmpeg_resampler_la_SOURCES = pulsecore/ffmpeg/resample2.c pulsecore/ffmpeg/avcodec.h pulsecore/ffmpeg/dsputil.h + ################################### # Daemon core library # ################################### -pulsecoreinclude_HEADERS = \ +#pulsecoreinclude_HEADERS = +noinst_HEADERS = \ pulsecore/autoload.h \ pulsecore/atomic.h \ pulsecore/cli-command.h \ @@ -567,6 +639,7 @@ pulsecoreinclude_HEADERS = \ pulsecore/refcnt.h \ pulsecore/mutex.h \ pulsecore/thread.h \ + pulsecore/semaphore.h \ pulsecore/once.h lib_LTLIBRARIES += libpulsecore.la @@ -608,6 +681,7 @@ libpulsecore_la_SOURCES += \ pulsecore/memchunk.c pulsecore/memchunk.h \ pulsecore/modargs.c pulsecore/modargs.h \ pulsecore/modinfo.c pulsecore/modinfo.h \ + pulsecore/ltdl-helper.c pulsecore/ltdl-helper.h \ pulsecore/module.c pulsecore/module.h \ pulsecore/namereg.c pulsecore/namereg.h \ pulsecore/pid.c pulsecore/pid.h \ @@ -636,6 +710,19 @@ libpulsecore_la_SOURCES += \ pulsecore/core-error.c pulsecore/core-error.h \ pulsecore/hook-list.c pulsecore/hook-list.h \ pulsecore/shm.c pulsecore/shm.h \ + pulsecore/flist.c pulsecore/flist.h \ + pulsecore/asyncmsgq.c pulsecore/asyncmsgq.h \ + pulsecore/asyncq.c pulsecore/asyncq.h \ + pulsecore/thread-mq.c pulsecore/thread-mq.h \ + pulsecore/fdsem.c pulsecore/fdsem.h \ + pulsecore/object.c pulsecore/object.h \ + pulsecore/msgobject.c pulsecore/msgobject.h \ + pulsecore/rtsig.c pulsecore/rtsig.h \ + pulsecore/rtpoll.c pulsecore/rtpoll.h \ + pulsecore/rtclock.c pulsecore/rtclock.h \ + pulsecore/macro.h \ + pulsecore/once.c pulsecore/once.h \ + pulsecore/time-smoother.c pulsecore/time-smoother.h \ $(PA_THREAD_OBJS) if OS_IS_WIN32 @@ -645,13 +732,14 @@ endif libpulsecore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS) libpulsecore_la_LDFLAGS = -version-info $(LIBPULSECORE_VERSION_INFO) -libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV) +libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS) $(LIBICONV) libspeex-resampler-fixed.la libspeex-resampler-float.la libffmpeg-resampler.la ################################### # Plug-in support libraries # ################################### -pulsecoreinclude_HEADERS += \ +#pulsecoreinclude_HEADERS += +noinst_HEADERS += \ pulsecore/socket-util.h \ pulsecore/iochannel.h \ pulsecore/socket-server.h \ @@ -700,9 +788,9 @@ modlibexec_LTLIBRARIES = \ libauthkey-prop.la \ libstrlist.la \ libprotocol-simple.la \ - libprotocol-esound.la \ + libprotocol-http.la \ libprotocol-native.la \ - libprotocol-http.la + libprotocol-esound.la # We need to emulate sendmsg/recvmsg to support this on Win32 if !OS_IS_WIN32 @@ -711,7 +799,8 @@ modlibexec_LTLIBRARIES += \ endif if HAVE_X11 -pulsecoreinclude_HEADERS += \ +#pulsecoreinclude_HEADERS += +noinst_HEADERS += \ pulsecore/x11wrap.h \ pulsecore/x11prop.h @@ -721,7 +810,8 @@ modlibexec_LTLIBRARIES += \ endif if HAVE_AVAHI -pulsecoreinclude_HEADERS += \ +#pulsecoreinclude_HEADERS += +noinst_HEADERS += \ pulsecore/avahi-wrap.h modlibexec_LTLIBRARIES += \ @@ -851,19 +941,23 @@ modlibexec_LTLIBRARIES += \ module-cli.la \ module-cli-protocol-tcp.la \ module-simple-protocol-tcp.la \ - module-esound-protocol-tcp.la \ - module-native-protocol-tcp.la \ - module-native-protocol-fd.la \ - module-sine.la \ - module-combine.la \ - module-tunnel-sink.la \ - module-tunnel-source.la \ module-null-sink.la \ - module-esound-sink.la \ - module-http-protocol-tcp.la \ module-detect.la \ module-volume-restore.la \ - module-rescue-streams.la + module-default-device-restore.la \ + module-rescue-streams.la \ + module-suspend-on-idle.la \ + module-http-protocol-tcp.la \ + module-sine.la \ + module-native-protocol-tcp.la \ + module-native-protocol-fd.la \ + module-esound-protocol-tcp.la \ + module-combine.la \ + module-remap-sink.la \ + module-ladspa-sink.la \ + module-esound-sink.la +# module-tunnel-sink.la +# module-tunnel-source.la # See comment at librtp.la above if !OS_IS_WIN32 @@ -876,9 +970,9 @@ if HAVE_AF_UNIX modlibexec_LTLIBRARIES += \ module-cli-protocol-unix.la \ module-simple-protocol-unix.la \ - module-esound-protocol-unix.la \ + module-http-protocol-unix.la \ module-native-protocol-unix.la \ - module-http-protocol-unix.la + module-esound-protocol-unix.la endif if HAVE_MKFIFO @@ -901,14 +995,14 @@ endif if HAVE_X11 modlibexec_LTLIBRARIES += \ module-x11-bell.la \ - module-x11-publish.la + module-x11-publish.la \ + module-x11-xsmp.la endif if HAVE_OSS modlibexec_LTLIBRARIES += \ liboss-util.la \ - module-oss.la \ - module-oss-mmap.la + module-oss.la endif if HAVE_ALSA @@ -952,10 +1046,10 @@ pulselibexec_PROGRAMS = \ gconf-helper endif -if OS_IS_WIN32 -modlibexec_LTLIBRARIES += \ - module-waveout.la -endif +#if OS_IS_WIN32 +#modlibexec_LTLIBRARIES += \ +# module-waveout.la +#endif if HAVE_HAL modlibexec_LTLIBRARIES += \ @@ -980,6 +1074,8 @@ SYMDEF_FILES = \ modules/module-native-protocol-fd-symdef.h \ modules/module-sine-symdef.h \ modules/module-combine-symdef.h \ + modules/module-remap-sink-symdef.h \ + modules/module-ladspa-sink-symdef.h \ modules/module-esound-compat-spawnfd-symdef.h \ modules/module-esound-compat-spawnpid-symdef.h \ modules/module-match-symdef.h \ @@ -994,8 +1090,8 @@ SYMDEF_FILES = \ modules/module-http-protocol-unix-symdef.h \ modules/module-x11-bell-symdef.h \ modules/module-x11-publish-symdef.h \ + modules/module-x11-xsmp-symdef.h \ modules/module-oss-symdef.h \ - modules/module-oss-mmap-symdef.h \ modules/module-alsa-sink-symdef.h \ modules/module-alsa-source-symdef.h \ modules/module-solaris-symdef.h \ @@ -1006,7 +1102,9 @@ SYMDEF_FILES = \ modules/module-jack-sink-symdef.h \ modules/module-jack-source-symdef.h \ modules/module-volume-restore-symdef.h \ + modules/module-default-device-restore-symdef.h \ modules/module-rescue-streams-symdef.h \ + modules/module-suspend-on-idle-symdef.h \ modules/module-hal-detect-symdef.h \ modules/gconf/module-gconf-symdef.h @@ -1126,18 +1224,27 @@ module_combine_la_SOURCES = modules/module-combine.c module_combine_la_LDFLAGS = -module -avoid-version module_combine_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_remap_sink_la_SOURCES = modules/module-remap-sink.c +module_remap_sink_la_LDFLAGS = -module -avoid-version +module_remap_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la + +module_ladspa_sink_la_SOURCES = modules/module-ladspa-sink.c modules/ladspa.h +module_ladspa_sink_la_CFLAGS = -DLADSPA_PATH=\"$(libdir)/ladspa:/usr/local/lib/ladspa:/usr/lib/ladspa\" $(AM_CFLAGS) +module_ladspa_sink_la_LDFLAGS = -module -avoid-version +module_ladspa_sink_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) libpulsecore.la + module_match_la_SOURCES = modules/module-match.c module_match_la_LDFLAGS = -module -avoid-version module_match_la_LIBADD = $(AM_LIBADD) libpulsecore.la -module_tunnel_sink_la_SOURCES = modules/module-tunnel.c -module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) -module_tunnel_sink_la_LDFLAGS = -module -avoid-version -module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la +#module_tunnel_sink_la_SOURCES = modules/module-tunnel.c +#module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) +#module_tunnel_sink_la_LDFLAGS = -module -avoid-version +#module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la -module_tunnel_source_la_SOURCES = modules/module-tunnel.c -module_tunnel_source_la_LDFLAGS = -module -avoid-version -module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la +#module_tunnel_source_la_SOURCES = modules/module-tunnel.c +#module_tunnel_source_la_LDFLAGS = -module -avoid-version +#module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la # X11 @@ -1151,6 +1258,11 @@ module_x11_publish_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_publish_la_LDFLAGS = -module -avoid-version module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libauthkey.la libauthkey-prop.la libx11prop.la libstrlist.la libpulsecore.la +module_x11_xsmp_la_SOURCES = modules/module-x11-xsmp.c +module_x11_xsmp_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) +module_x11_xsmp_la_LDFLAGS = -module -avoid-version +module_x11_xsmp_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libpulsecore.la + # OSS liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h @@ -1161,10 +1273,6 @@ module_oss_la_SOURCES = modules/module-oss.c module_oss_la_LDFLAGS = -module -avoid-version module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la libpulsecore.la -module_oss_mmap_la_SOURCES = modules/module-oss-mmap.c -module_oss_mmap_la_LDFLAGS = -module -avoid-version -module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la libpulsecore.la - # ALSA libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h @@ -1211,10 +1319,10 @@ module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS) # Windows waveout -module_waveout_la_SOURCES = modules/module-waveout.c -module_waveout_la_LDFLAGS = -module -avoid-version -module_waveout_la_LIBADD = $(AM_LIBADD) libpulsecore.la -lwinmm -module_waveout_la_CFLAGS = $(AM_CFLAGS) +#module_waveout_la_SOURCES = modules/module-waveout.c +#module_waveout_la_LDFLAGS = -module -avoid-version +#module_waveout_la_LIBADD = $(AM_LIBADD) libpulsecore.la -lwinmm +#module_waveout_la_CFLAGS = $(AM_CFLAGS) # Hardware autodetection module module_detect_la_SOURCES = modules/module-detect.c @@ -1228,16 +1336,28 @@ module_volume_restore_la_LDFLAGS = -module -avoid-version module_volume_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_volume_restore_la_CFLAGS = $(AM_CFLAGS) +# Default sink/source restore module +module_default_device_restore_la_SOURCES = modules/module-default-device-restore.c +module_default_device_restore_la_LDFLAGS = -module -avoid-version +module_default_device_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_default_device_restore_la_CFLAGS = $(AM_CFLAGS) + # Rescue streams module module_rescue_streams_la_SOURCES = modules/module-rescue-streams.c module_rescue_streams_la_LDFLAGS = -module -avoid-version module_rescue_streams_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_rescue_streams_la_CFLAGS = $(AM_CFLAGS) +# Suspend-on-idle module +module_suspend_on_idle_la_SOURCES = modules/module-suspend-on-idle.c +module_suspend_on_idle_la_LDFLAGS = -module -avoid-version +module_suspend_on_idle_la_LIBADD = $(AM_LIBADD) libpulsecore.la +module_suspend_on_idle_la_CFLAGS = $(AM_CFLAGS) + # RTP modules module_rtp_send_la_SOURCES = modules/rtp/module-rtp-send.c module_rtp_send_la_LDFLAGS = -module -avoid-version -module_rtp_send_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la +module_rtp_send_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la libsocket-util.la module_rtp_send_la_CFLAGS = $(AM_CFLAGS) module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c @@ -1275,7 +1395,7 @@ module_gconf_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_gconf_la_CFLAGS = $(AM_CFLAGS) -DPA_GCONF_HELPER=\"$(pulselibexecdir)/gconf-helper\" gconf_helper_SOURCES = modules/gconf/gconf-helper.c -gconf_helper_LDADD = $(AM_LDADD) $(GCONF_LIBS) +gconf_helper_LDADD = $(AM_LDADD) $(GCONF_LIBS) libpulsecore.la gconf_helper_CFLAGS = $(AM_CFLAGS) $(GCONF_CFLAGS) gconf_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -1304,8 +1424,8 @@ default.pa: daemon/default.pa.win32 else default.pa: daemon/default.pa.in Makefile sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' \ - -e 's,@HAVE_HAL_TRUE\@,@HAVE_HAL_TRUE@,g' \ - -e 's,@HAVE_HAL_FALSE\@,@HAVE_HAL_FALSE@,g' < $< > $@ + -e 's,@PA_DLSEARCHPATH\@,$(modlibexecdir),g' \ + -e 's,@PA_SOEXT\@,.so,g' < $< > $@ endif daemon.conf: daemon/daemon.conf.in Makefile @@ -1323,4 +1443,13 @@ install-exec-hook: massif: pulseaudio libtool --mode=execute valgrind --tool=massif --depth=6 --alloc-fn=pa_xmalloc --alloc-fn=pa_xmalloc0 --alloc-fn=pa_xrealloc --alloc-fn=dbus_realloc --alloc-fn=pa_xnew0_internal --alloc-fn=pa_xnew_internal ./pulseaudio +update-speex: + wget -O pulsecore/speex/speex_resampler.h http://svn.xiph.org/trunk/speex/include/speex/speex_resampler.h + wget -O pulsecore/speex/resample.c http://svn.xiph.org/trunk/speex/libspeex/resample.c + wget -O pulsecore/speex/arch.h http://svn.xiph.org/trunk/speex/libspeex/arch.h + wget -O pulsecore/speex/fixed_generic.h http://svn.xiph.org/trunk/speex/libspeex/fixed_generic.h + +update-ffmpeg: + wget -O pulsecore/ffmpeg/resample2.c http://svn.mplayerhq.hu/ffmpeg/trunk/libavcodec/resample2.c?view=co + .PHONY: utils/padsp diff --git a/src/daemon/caps.c b/src/daemon/caps.c index f92db7439..5b4008a58 100644 --- a/src/daemon/caps.c +++ b/src/daemon/caps.c @@ -26,11 +26,11 @@ #include #endif -#include #include #include #include #include +#include #ifdef HAVE_SYS_CAPABILITY_H #include @@ -60,7 +60,7 @@ void pa_drop_root(void) { if (uid == 0 || geteuid() != 0) return; - pa_log_info("dropping root rights."); + pa_log_info("Dropping root priviliges."); #if defined(HAVE_SETRESUID) setresuid(uid, uid, uid); @@ -88,8 +88,9 @@ int pa_limit_caps(void) { cap_value_t nice_cap = CAP_SYS_NICE; caps = cap_init(); - assert(caps); + pa_assert(caps); cap_clear(caps); + cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET); if (cap_set_proc(caps) < 0) @@ -98,7 +99,7 @@ int pa_limit_caps(void) { if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) goto fail; - pa_log_info("dropped capabilities successfully."); + pa_log_info("Dropped capabilities successfully."); r = 1; @@ -114,14 +115,14 @@ int pa_drop_caps(void) { int r = -1; caps = cap_init(); - assert(caps); + pa_assert(caps); cap_clear(caps); prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0); if (cap_set_proc(caps) < 0) { - pa_log("failed to drop capabilities: %s", pa_cstrerror(errno)); + pa_log("Failed to drop capabilities: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index dc757c9c7..6b7b26712 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include #include @@ -36,6 +35,7 @@ #include #include +#include #include "cmdline.h" @@ -63,7 +63,9 @@ enum { ARG_CHECK, ARG_NO_CPU_LIMIT, ARG_DISABLE_SHM, - ARG_SYSTEM + ARG_DUMP_RESAMPLE_METHODS, + ARG_SYSTEM, + ARG_CLEANUP_SHM }; /* Tabel for getopt_long() */ @@ -92,12 +94,16 @@ static struct option long_options[] = { {"system", 2, 0, ARG_SYSTEM}, {"no-cpu-limit", 2, 0, ARG_NO_CPU_LIMIT}, {"disable-shm", 2, 0, ARG_DISABLE_SHM}, + {"dump-resample-methods", 2, 0, ARG_DUMP_RESAMPLE_METHODS}, + {"cleanup-shm", 2, 0, ARG_CLEANUP_SHM}, {NULL, 0, 0, 0} }; void pa_cmdline_help(const char *argv0) { const char *e; + pa_assert(argv0); + if ((e = strrchr(argv0, '/'))) e++; else @@ -109,6 +115,8 @@ void pa_cmdline_help(const char *argv0) { " --version Show version\n" " --dump-conf Dump default configuration\n" " --dump-modules Dump list of available modules\n" + " --dump-resample-methods Dump available resample methods\n" + " --cleanup-shm Cleanup stale shared memory segments\n" " -k --kill Kill a running daemon\n" " --check Check for a running daemon\n\n" @@ -131,9 +139,8 @@ void pa_cmdline_help(const char *argv0) { " -p, --dl-search-path=PATH Set the search path for dynamic shared\n" " objects (plugins)\n" " --resample-method=[METHOD] Use the specified resampling method\n" - " (one of src-sinc-medium-quality,\n" - " src-sinc-best-quality,src-sinc-fastest\n" - " src-zero-order-hold,src-linear,trivial)\n" + " (See --dump-resample-methods for\n" + " possible values)\n" " --use-pid-file[=BOOL] Create a PID file\n" " --no-cpu-limit[=BOOL] Do not install CPU load limiter on\n" " platforms that support it.\n" @@ -152,7 +159,10 @@ void pa_cmdline_help(const char *argv0) { int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d) { pa_strbuf *buf = NULL; int c; - assert(conf && argc && argv); + + pa_assert(conf); + pa_assert(argc > 0); + pa_assert(argv); buf = pa_strbuf_new(); @@ -178,6 +188,14 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d conf->cmd = PA_CMD_DUMP_MODULES; break; + case ARG_DUMP_RESAMPLE_METHODS: + conf->cmd = PA_CMD_DUMP_RESAMPLE_METHODS; + break; + + case ARG_CLEANUP_SHM: + conf->cmd = PA_CMD_CLEANUP_SHM; + break; + case 'k': case ARG_KILL: conf->cmd = PA_CMD_KILL; @@ -193,9 +211,12 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d break; case ARG_FILE: - case 'F': - pa_strbuf_printf(buf, ".include %s\n", optarg); + case 'F': { + char *p; + pa_strbuf_printf(buf, ".include %s\n", p = pa_make_path_absolute(optarg)); + pa_xfree(p); break; + } case 'C': pa_strbuf_puts(buf, "load-module module-cli exit_on_eof=1\n"); diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index d4ac1d869..ab212129e 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "cpulimit.h" @@ -38,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -92,23 +92,18 @@ static enum { /* Reset the SIGXCPU timer to the next t seconds */ static void reset_cpu_time(int t) { - int r; long n; struct rlimit rl; struct rusage ru; /* Get the current CPU time of the current process */ - r = getrusage(RUSAGE_SELF, &ru); - assert(r >= 0); + pa_assert_se(getrusage(RUSAGE_SELF, &ru) >= 0); n = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec + t; - - r = getrlimit(RLIMIT_CPU, &rl); - assert(r >= 0); + pa_assert_se(getrlimit(RLIMIT_CPU, &rl) >= 0); rl.rlim_cur = n; - r = setrlimit(RLIMIT_CPU, &rl); - assert(r >= 0); + pa_assert_se(setrlimit(RLIMIT_CPU, &rl) >= 0); } /* A simple, thread-safe puts() work-alike */ @@ -118,7 +113,7 @@ static void write_err(const char *p) { /* The signal handler, called on every SIGXCPU */ static void signal_handler(int sig) { - assert(sig == SIGXCPU); + pa_assert(sig == SIGXCPU); if (phase == PHASE_IDLE) { time_t now; @@ -130,7 +125,7 @@ static void signal_handler(int sig) { time(&now); #ifdef PRINT_CPU_LOAD - snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100); + pa_snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100); write_err(t); #endif @@ -160,7 +155,12 @@ static void signal_handler(int sig) { /* Callback for IO events on the FIFO */ static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata) { char c; - assert(m && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == the_pipe[0]); + pa_assert(m); + pa_assert(e); + pa_assert(f == PA_IO_EVENT_INPUT); + pa_assert(e == io_event); + pa_assert(fd == the_pipe[0]); + pa_read(the_pipe[0], &c, sizeof(c), NULL); m->quit(m, 1); /* Quit the main loop */ } @@ -168,7 +168,13 @@ static void callback(pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags /* Initializes CPU load limiter */ int pa_cpu_limit_init(pa_mainloop_api *m) { struct sigaction sa; - assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1 && !installed); + + pa_assert(m); + pa_assert(!api); + pa_assert(!io_event); + pa_assert(the_pipe[0] == -1); + pa_assert(the_pipe[1] == -1); + pa_assert(!installed); time(&last_time); @@ -178,10 +184,10 @@ int pa_cpu_limit_init(pa_mainloop_api *m) { return -1; } - pa_make_nonblock_fd(the_pipe[0]); - pa_make_nonblock_fd(the_pipe[1]); - pa_fd_set_cloexec(the_pipe[0], 1); - pa_fd_set_cloexec(the_pipe[1], 1); + pa_make_fd_nonblock(the_pipe[0]); + pa_make_fd_nonblock(the_pipe[1]); + pa_make_fd_cloexec(the_pipe[0]); + pa_make_fd_cloexec(the_pipe[1]); api = m; io_event = api->io_new(m, the_pipe[0], PA_IO_EVENT_INPUT, callback, NULL); @@ -208,24 +214,18 @@ int pa_cpu_limit_init(pa_mainloop_api *m) { /* Shutdown CPU load limiter */ void pa_cpu_limit_done(void) { - int r; if (io_event) { - assert(api); + pa_assert(api); api->io_free(io_event); io_event = NULL; api = NULL; } - if (the_pipe[0] >= 0) - close(the_pipe[0]); - if (the_pipe[1] >= 0) - close(the_pipe[1]); - the_pipe[0] = the_pipe[1] = -1; + pa_close_pipe(the_pipe); if (installed) { - r = sigaction(SIGXCPU, &sigaction_prev, NULL); - assert(r >= 0); + pa_assert_se(sigaction(SIGXCPU, &sigaction_prev, NULL) >= 0); installed = 0; } } diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 8cab327f8..920e37173 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -39,19 +38,14 @@ #include #include #include +#include #include "daemon-conf.h" -#ifndef OS_IS_WIN32 -# define PATH_SEP "/" -#else -# define PATH_SEP "\\" -#endif - -#define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "default.pa" -#define DEFAULT_SCRIPT_FILE_USER PATH_SEP "default.pa" -#define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf" -#define DEFAULT_CONFIG_FILE_USER PATH_SEP "daemon.conf" +#define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "default.pa" +#define DEFAULT_SCRIPT_FILE_USER PA_PATH_SEP "default.pa" +#define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "daemon.conf" +#define DEFAULT_CONFIG_FILE_USER PA_PATH_SEP "daemon.conf" #define ENV_SCRIPT_FILE "PULSE_SCRIPT" #define ENV_CONFIG_FILE "PULSE_CONFIG" @@ -72,31 +66,34 @@ static const pa_daemon_conf default_conf = { .default_script_file = NULL, .log_target = PA_LOG_SYSLOG, .log_level = PA_LOG_NOTICE, - .resample_method = PA_RESAMPLER_SRC_SINC_FASTEST, + .resample_method = PA_RESAMPLER_AUTO, .config_file = NULL, .use_pid_file = 1, .system_instance = 0, .no_cpu_limit = 0, - .disable_shm = 0 + .disable_shm = 0, + .default_n_fragments = 4, + .default_fragment_size_msec = 25, + .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 } #ifdef HAVE_SYS_RESOURCE_H , .rlimit_as = { .value = 0, .is_set = 0 }, .rlimit_core = { .value = 0, .is_set = 0 }, .rlimit_data = { .value = 0, .is_set = 0 }, .rlimit_fsize = { .value = 0, .is_set = 0 }, - .rlimit_nofile = { .value = 200, .is_set = 1 }, + .rlimit_nofile = { .value = 256, .is_set = 1 }, .rlimit_stack = { .value = 0, .is_set = 0 } #ifdef RLIMIT_NPROC , .rlimit_nproc = { .value = 0, .is_set = 0 } #endif #ifdef RLIMIT_MEMLOCK - , .rlimit_memlock = { .value = 0, .is_set = 1 } + , .rlimit_memlock = { .value = 16384, .is_set = 1 } #endif #endif }; pa_daemon_conf* pa_daemon_conf_new(void) { FILE *f; - pa_daemon_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf)); + pa_daemon_conf *c = pa_xnewdup(pa_daemon_conf, &default_conf, 1); if ((f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file, "r"))) fclose(f); @@ -106,7 +103,7 @@ pa_daemon_conf* pa_daemon_conf_new(void) { } void pa_daemon_conf_free(pa_daemon_conf *c) { - assert(c); + pa_assert(c); pa_xfree(c->script_commands); pa_xfree(c->dl_search_path); pa_xfree(c->default_script_file); @@ -115,7 +112,8 @@ void pa_daemon_conf_free(pa_daemon_conf *c) { } int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) { - assert(c && string); + pa_assert(c); + pa_assert(string); if (!strcmp(string, "auto")) c->auto_log_target = 1; @@ -133,7 +131,8 @@ int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) { int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) { uint32_t u; - assert(c && string); + pa_assert(c); + pa_assert(string); if (pa_atou(string, &u) >= 0) { if (u >= PA_LOG_LEVEL_MAX) @@ -158,7 +157,8 @@ int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) { int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) { int m; - assert(c && string); + pa_assert(c); + pa_assert(string); if ((m = pa_parse_resample_method(string)) < 0) return -1; @@ -169,7 +169,11 @@ int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) { static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { pa_daemon_conf *c = data; - assert(filename && lvalue && rvalue && data); + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); if (pa_daemon_conf_set_log_target(c, rvalue) < 0) { pa_log("[%s:%u] Invalid log target '%s'.", filename, line, rvalue); @@ -181,7 +185,11 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { pa_daemon_conf *c = data; - assert(filename && lvalue && rvalue && data); + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); if (pa_daemon_conf_set_log_level(c, rvalue) < 0) { pa_log("[%s:%u] Invalid log level '%s'.", filename, line, rvalue); @@ -193,10 +201,14 @@ static int parse_log_level(const char *filename, unsigned line, const char *lval static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { pa_daemon_conf *c = data; - assert(filename && lvalue && rvalue && data); + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); if (pa_daemon_conf_set_resample_method(c, rvalue) < 0) { - pa_log("[%s:%u] Inavalid resample method '%s'.", filename, line, rvalue); + pa_log("[%s:%u] Invalid resample method '%s'.", filename, line, rvalue); return -1; } @@ -206,10 +218,11 @@ static int parse_resample_method(const char *filename, unsigned line, const char static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { #ifdef HAVE_SYS_RESOURCE_H struct pa_rlimit *r = data; - assert(filename); - assert(lvalue); - assert(rvalue); - assert(r); + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(r); if (rvalue[strspn(rvalue, "\t ")] == 0) { /* Empty string */ @@ -218,7 +231,7 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, } else { int32_t k; if (pa_atoi(rvalue, &k) < 0) { - pa_log("[%s:%u] Inavalid rlimit '%s'.", filename, line, rvalue); + pa_log("[%s:%u] Invalid rlimit '%s'.", filename, line, rvalue); return -1; } r->is_set = k >= 0; @@ -231,43 +244,138 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, return 0; } +static int parse_sample_format(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; + pa_sample_format_t f; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if ((f = pa_parse_sample_format(rvalue)) < 0) { + pa_log("[%s:%u] Invalid sample format '%s'.", filename, line, rvalue); + return -1; + } + + c->default_sample_spec.format = f; + return 0; +} + +static int parse_sample_rate(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; + int32_t r; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atoi(rvalue, &r) < 0 || r > PA_RATE_MAX || r <= 0) { + pa_log("[%s:%u] Invalid sample rate '%s'.", filename, line, rvalue); + return -1; + } + + c->default_sample_spec.rate = r; + return 0; +} + +static int parse_sample_channels(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; + int32_t n; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atoi(rvalue, &n) < 0 || n > PA_CHANNELS_MAX || n <= 0) { + pa_log("[%s:%u] Invalid sample channels '%s'.", filename, line, rvalue); + return -1; + } + + c->default_sample_spec.channels = (uint8_t) n; + return 0; +} + +static int parse_fragments(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; + int32_t n; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atoi(rvalue, &n) < 0 || n < 2) { + pa_log("[%s:%u] Invalid number of fragments '%s'.", filename, line, rvalue); + return -1; + } + + c->default_n_fragments = (unsigned) n; + return 0; +} + +static int parse_fragment_size_msec(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; + int32_t n; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atoi(rvalue, &n) < 0 || n < 1) { + pa_log("[%s:%u] Invalid fragment size '%s'.", filename, line, rvalue); + return -1; + } + + c->default_fragment_size_msec = (unsigned) n; + return 0; +} + int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { int r = -1; FILE *f = NULL; pa_config_item table[] = { - { "daemonize", pa_config_parse_bool, NULL }, - { "fail", pa_config_parse_bool, NULL }, - { "high-priority", pa_config_parse_bool, NULL }, - { "disallow-module-loading", pa_config_parse_bool, NULL }, - { "exit-idle-time", pa_config_parse_int, NULL }, - { "module-idle-time", pa_config_parse_int, NULL }, - { "scache-idle-time", pa_config_parse_int, NULL }, - { "dl-search-path", pa_config_parse_string, NULL }, - { "default-script-file", pa_config_parse_string, NULL }, - { "log-target", parse_log_target, NULL }, - { "log-level", parse_log_level, NULL }, - { "verbose", parse_log_level, NULL }, - { "resample-method", parse_resample_method, NULL }, - { "use-pid-file", pa_config_parse_bool, NULL }, - { "system-instance", pa_config_parse_bool, NULL }, - { "no-cpu-limit", pa_config_parse_bool, NULL }, - { "disable-shm", pa_config_parse_bool, NULL }, + { "daemonize", pa_config_parse_bool, NULL }, + { "fail", pa_config_parse_bool, NULL }, + { "high-priority", pa_config_parse_bool, NULL }, + { "disallow-module-loading", pa_config_parse_bool, NULL }, + { "exit-idle-time", pa_config_parse_int, NULL }, + { "module-idle-time", pa_config_parse_int, NULL }, + { "scache-idle-time", pa_config_parse_int, NULL }, + { "dl-search-path", pa_config_parse_string, NULL }, + { "default-script-file", pa_config_parse_string, NULL }, + { "log-target", parse_log_target, NULL }, + { "log-level", parse_log_level, NULL }, + { "verbose", parse_log_level, NULL }, + { "resample-method", parse_resample_method, NULL }, + { "use-pid-file", pa_config_parse_bool, NULL }, + { "system-instance", pa_config_parse_bool, NULL }, + { "no-cpu-limit", pa_config_parse_bool, NULL }, + { "disable-shm", pa_config_parse_bool, NULL }, + { "default-sample-format", parse_sample_format, NULL }, + { "default-sample-rate", parse_sample_rate, NULL }, + { "default-sample-channels", parse_sample_channels, NULL }, + { "default-fragments", parse_fragments, NULL }, + { "default-fragment-size-msec", parse_fragment_size_msec, NULL }, #ifdef HAVE_SYS_RESOURCE_H - { "rlimit-as", parse_rlimit, NULL }, - { "rlimit-core", parse_rlimit, NULL }, - { "rlimit-data", parse_rlimit, NULL }, - { "rlimit-fsize", parse_rlimit, NULL }, - { "rlimit-nofile", parse_rlimit, NULL }, - { "rlimit-stack", parse_rlimit, NULL }, + { "rlimit-as", parse_rlimit, NULL }, + { "rlimit-core", parse_rlimit, NULL }, + { "rlimit-data", parse_rlimit, NULL }, + { "rlimit-fsize", parse_rlimit, NULL }, + { "rlimit-nofile", parse_rlimit, NULL }, + { "rlimit-stack", parse_rlimit, NULL }, #ifdef RLIMIT_NPROC - { "rlimit-nproc", parse_rlimit, NULL }, + { "rlimit-nproc", parse_rlimit, NULL }, #endif #ifdef RLIMIT_MEMLOCK - { "rlimit-memlock", parse_rlimit, NULL }, + { "rlimit-memlock", parse_rlimit, NULL }, #endif #endif - { NULL, NULL, NULL }, + { NULL, NULL, NULL }, }; table[0].data = &c->daemonize; @@ -287,25 +395,29 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[14].data = &c->system_instance; table[15].data = &c->no_cpu_limit; table[16].data = &c->disable_shm; + table[17].data = c; + table[18].data = c; + table[19].data = c; + table[20].data = c; + table[21].data = c; #ifdef HAVE_SYS_RESOURCE_H - table[17].data = &c->rlimit_as; - table[18].data = &c->rlimit_core; - table[19].data = &c->rlimit_data; - table[20].data = &c->rlimit_fsize; - table[21].data = &c->rlimit_nofile; - table[22].data = &c->rlimit_stack; + table[22].data = &c->rlimit_as; + table[23].data = &c->rlimit_core; + table[24].data = &c->rlimit_data; + table[25].data = &c->rlimit_fsize; + table[26].data = &c->rlimit_nofile; + table[27].data = &c->rlimit_stack; #ifdef RLIMIT_NPROC - table[23].data = &c->rlimit_nproc; + table[28].data = &c->rlimit_nproc; #endif #ifdef RLIMIT_MEMLOCK #ifndef RLIMIT_NPROC #error "Houston, we have a numbering problem!" #endif - table[24].data = &c->rlimit_memlock; + table[29].data = &c->rlimit_memlock; #endif #endif - pa_xfree(c->config_file); c->config_file = NULL; @@ -314,7 +426,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file, "r"); if (!f && errno != ENOENT) { - pa_log("WARNING: failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno)); + pa_log_warn("Failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno)); goto finish; } @@ -351,12 +463,16 @@ static const char* const log_level_to_string[] = { }; char *pa_daemon_conf_dump(pa_daemon_conf *c) { - pa_strbuf *s = pa_strbuf_new(); + pa_strbuf *s; + + pa_assert(c); + + s = pa_strbuf_new(); if (c->config_file) pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file); - assert(c->log_level <= PA_LOG_LEVEL_MAX); + pa_assert(c->log_level <= PA_LOG_LEVEL_MAX); pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize); pa_strbuf_printf(s, "fail = %i\n", !!c->fail); @@ -373,7 +489,12 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file); pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance); pa_strbuf_printf(s, "no-cpu-limit = %i\n", !!c->no_cpu_limit); - pa_strbuf_printf(s, "disable_shm = %i\n", !!c->disable_shm); + pa_strbuf_printf(s, "disable-shm = %i\n", !!c->disable_shm); + pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format)); + pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate); + pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels); + pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments); + pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec); #ifdef HAVE_SYS_RESOURCE_H pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1); pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index 4843a610e..4d37861db 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -26,6 +26,7 @@ ***/ #include +#include #ifdef HAVE_SYS_RESOURCE_H #include @@ -39,7 +40,9 @@ typedef enum pa_daemon_conf_cmd { PA_CMD_DUMP_CONF, PA_CMD_DUMP_MODULES, PA_CMD_KILL, - PA_CMD_CHECK + PA_CMD_CHECK, + PA_CMD_DUMP_RESAMPLE_METHODS, + PA_CMD_CLEANUP_SHM } pa_daemon_conf_cmd_t; #ifdef HAVE_SYS_RESOURCE_H @@ -80,6 +83,8 @@ typedef struct pa_daemon_conf { #endif #endif + unsigned default_n_fragments, default_fragment_size_msec; + pa_sample_spec default_sample_spec; } pa_daemon_conf; /* Allocate a new structure and fill it with sane defaults */ diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 29b22a42c..2132bf3d0 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -92,10 +92,19 @@ ; rlimit-core = -1 ; rlimit-data = -1 ; rlimit-fsize = -1 -; rlimit-nofile = 200 +; rlimit-nofile = 256 ; rlimit-stack = -1 ; rlimit-nproc = -1 -; rlimit-memlock = 25 +; rlimit-memlock = 16384 ## Disable shared memory data transfer ; disable-shm = 0 + +## Default sample format +; default-sample-format = s16le +; default-sample-rate = 44100 +; default-sample-channels = 2 + +## Default fragment settings, for device drivers that need this +; default-fragments = 4 +; default-fragment-size-msec = 25 diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index af2a67893..597993c47 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -1,5 +1,4 @@ -#!@PA_BINARY@ -nF - +#!@PA_BINARY@ -nF # # This file is part of PulseAudio. # @@ -17,8 +16,19 @@ # along with PulseAudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +.nofail -### Load audio drivers statically +### Load something into the sample cache +#load-sample-lazy x11-bell /usr/share/sounds/gtk-events/activate.wav +load-sample-lazy pulse-hotplug /usr/share/sounds/startup3.wav +#load-sample-lazy pulse-coldplug /usr/share/sounds/startup3.wav +#load-sample-lazy pulse-access /usr/share/sounds/generic.wav + +.fail + +### Load audio drivers statically (it's probably better to not load +### these drivers manually, but instead use module-hal-detect -- +### see below -- for doing this automatically) #load-module module-alsa-sink #load-module module-alsa-source device=hw:1,0 #load-module module-oss device="/dev/dsp" sink_name=output source_name=input @@ -27,19 +37,13 @@ #load-module module-pipe-sink ### Automatically load driver modules depending on the hardware available -@HAVE_HAL_TRUE@load-module module-hal-detect - +.ifexists @PA_DLSEARCHPATH@/module-hal-detect@PA_SOEXT@ +load-module module-hal-detect +.else ### Alternatively use the static hardware detection module (for systems that -### lack HAL support -@HAVE_HAL_FALSE@load-module module-detect - -### Load audio drivers automatically on access -#add-autoload-sink output module-oss device="/dev/dsp" sink_name=output source_name=input -#add-autoload-source input module-oss device="/dev/dsp" sink_name=output source_name=input -#add-autoload-sink output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#add-autoload-source input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#add-autoload-sink output module-alsa-sink sink_name=output -#add-autoload-source input module-alsa-source source_name=input +### lack HAL support) +load-module module-detect +.endif ### Load several protocols load-module module-esound-protocol-unix @@ -61,27 +65,36 @@ load-module module-native-protocol-unix ### Automatically restore the volume of playback streams load-module module-volume-restore +### Automatically restore the default sink/source when changed by the user during runtime +load-module module-default-device-restore + ### Automatically move streams to the default sink if the sink they are ### connected to dies, similar for sources load-module module-rescue-streams -### Make some devices default -#set-default-sink output -#set-default-source input - -.nofail - -### Load something to the sample cache -load-sample x11-bell /usr/share/sounds/gtk-events/activate.wav -#load-sample-dir-lazy /usr/share/sounds/*.wav +### Automatically suspend sinks/sources that become idle for too long +load-module module-suspend-on-idle ### Load X11 bell module -load-module module-x11-bell sample=x11-bell +#load-module module-x11-bell sample=x11-bell ### Publish connection data in the X11 root window +.ifexists @PA_DLSEARCHPATH@/module-x11-publish@PA_SOEXT@ load-module module-x11-publish +.endif + +### Register ourselves in the X11 session manager +# Deactivated by default, to avoid deadlock when PA is started as esd from gnome-session +# Instead we load this via /etc/xdg/autostart/ and "pactl load-module" now +# load-module module-x11-xsmp ### Load additional modules from GConf settings. This can be configured with the paprefs tool. ### Please keep in mind that the modules configured by paprefs might conflict with manually ### loaded modules. +.ifexists @PA_DLSEARCHPATH@/module-gconf@PA_SOEXT@ load-module module-gconf +.endif + +### Make some devices default +#set-default-sink output +#set-default-source input diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c index 6743622ac..ad7fab20f 100644 --- a/src/daemon/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -28,26 +28,30 @@ #include #include -#include #include #include #include #include +#include +#include #include "dumpmodules.h" #define PREFIX "module-" static void short_info(const char *name, PA_GCC_UNUSED const char *path, pa_modinfo *i) { - assert(name && i); + pa_assert(name); + pa_assert(i); + printf("%-40s%s\n", name, i->description ? i->description : "n/a"); } static void long_info(const char *name, const char *path, pa_modinfo *i) { static int nl = 0; - assert(name && i); + pa_assert(name); + pa_assert(i); if (nl) printf("\n"); @@ -76,6 +80,8 @@ static void long_info(const char *name, const char *path, pa_modinfo *i) { static void show_info(const char *name, const char *path, void (*info)(const char *name, const char *path, pa_modinfo*i)) { pa_modinfo *i; + pa_assert(name); + if ((i = pa_modinfo_get_by_name(path ? path : name))) { info(name, path, i); pa_modinfo_free(i); @@ -93,7 +99,7 @@ static int is_preloaded(const char *name) { if (l->address) continue; - snprintf(buf, sizeof(buf), "%s", l->name); + pa_snprintf(buf, sizeof(buf), "%s", l->name); if ((e = strrchr(buf, '.'))) *e = 0; @@ -121,6 +127,8 @@ static int callback(const char *path, lt_ptr data) { } void pa_dump_modules(pa_daemon_conf *c, int argc, char * const argv[]) { + pa_assert(c); + if (argc > 0) { int i; for (i = 0; i < argc; i++) @@ -137,7 +145,7 @@ void pa_dump_modules(pa_daemon_conf *c, int argc, char * const argv[]) { if (strlen(l->name) <= sizeof(PREFIX)-1 || strncmp(l->name, PREFIX, sizeof(PREFIX)-1)) continue; - snprintf(buf, sizeof(buf), "%s", l->name); + pa_snprintf(buf, sizeof(buf), "%s", l->name); if ((e = strrchr(buf, '.'))) *e = 0; diff --git a/src/daemon/ltdl-bind-now.c b/src/daemon/ltdl-bind-now.c new file mode 100644 index 000000000..6025c6e35 --- /dev/null +++ b/src/daemon/ltdl-bind-now.c @@ -0,0 +1,160 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if HAVE_DLFCN_H +#include +#endif + +#if HAVE_SYS_DL_H +#include +#endif + +#include + +#include +#include +#include +#include + +#include "ltdl-bind-now.h" + +#ifdef RTLD_NOW +#define PA_BIND_NOW RTLD_NOW +#elif defined(DL_NOW) +#define PA_BIND_NOW DL_NOW +#else +#undef PA_BIND_NOW +#endif + +static pa_mutex *libtool_mutex = NULL; + +PA_STATIC_TLS_DECLARE_NO_FREE(libtool_tls); + +static void libtool_lock(void) { + pa_mutex_lock(libtool_mutex); +} + +static void libtool_unlock(void) { + pa_mutex_unlock(libtool_mutex); +} + +static void libtool_set_error(const char *error) { + PA_STATIC_TLS_SET(libtool_tls, (char*) error); +} + +static const char *libtool_get_error(void) { + return PA_STATIC_TLS_GET(libtool_tls); +} + +#ifdef PA_BIND_NOW + +/* + To avoid lazy relocations during runtime in our RT threads we add + our own shared object loader with uses RTLD_NOW if it is + available. The standard ltdl loader prefers RTLD_LAZY. + + Please note that this loader doesn't have any influence on + relocations on any libraries that are already loaded into our + process, i.e. because the pulseaudio binary links directly to + them. To disable lazy relocations for those libraries it is possible + to set $LT_BIND_NOW before starting the pulsaudio binary. +*/ + +static lt_module bind_now_open(lt_user_data d, const char *fname) { + lt_module m; + + pa_assert(fname); + + if (!(m = dlopen(fname, PA_BIND_NOW))) { + libtool_set_error(dlerror()); + return NULL; + } + + return m; +} + +static int bind_now_close(lt_user_data d, lt_module m) { + + pa_assert(m); + + if (dlclose(m) != 0){ + libtool_set_error(dlerror()); + return 1; + } + + return 0; +} + +static lt_ptr bind_now_find_sym(lt_user_data d, lt_module m, const char *symbol) { + lt_ptr ptr; + + pa_assert(m); + pa_assert(symbol); + + if (!(ptr = dlsym(m, symbol))) { + libtool_set_error(dlerror()); + return NULL; + } + + return ptr; +} + +#endif + +void pa_ltdl_init(void) { + +#ifdef PA_BIND_NOW + lt_dlloader *place; + static const struct lt_user_dlloader loader = { + .module_open = bind_now_open, + .module_close = bind_now_close, + .find_sym = bind_now_find_sym + }; +#endif + + pa_assert_se(lt_dlinit() == 0); + pa_assert_se(libtool_mutex = pa_mutex_new(TRUE, FALSE)); + pa_assert_se(lt_dlmutex_register(libtool_lock, libtool_unlock, libtool_set_error, libtool_get_error) == 0); + +#ifdef PA_BIND_NOW + + if (!(place = lt_dlloader_find("dlopen"))) + place = lt_dlloader_next(NULL); + + /* Add our BIND_NOW loader as the default module loader. */ + if (lt_dlloader_add(place, &loader, "bind-now-loader") != 0) + pa_log_warn("Failed to add bind-now-loader."); +#endif +} + +void pa_ltdl_done(void) { + pa_assert_se(lt_dlexit() == 0); + pa_mutex_free(libtool_mutex); + libtool_mutex = NULL; +} + diff --git a/src/daemon/ltdl-bind-now.h b/src/daemon/ltdl-bind-now.h new file mode 100644 index 000000000..e19c7bc11 --- /dev/null +++ b/src/daemon/ltdl-bind-now.h @@ -0,0 +1,32 @@ +#ifndef foopulsecoreltdlbindnowhfoo +#define foopulsecoreltdlbindnowhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + + +void pa_ltdl_init(void); +void pa_ltdl_done(void); + +#endif + diff --git a/src/daemon/main.c b/src/daemon/main.c index 91cc3a2f9..6c9f66277 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -59,13 +58,16 @@ #include #endif -#include "../pulsecore/winsock.h" +#ifdef HAVE_DBUS +#include +#endif #include #include #include #include +#include #include #include #include @@ -78,12 +80,20 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include "cmdline.h" #include "cpulimit.h" #include "daemon-conf.h" #include "dumpmodules.h" #include "caps.h" +#include "ltdl-bind-now.h" #ifdef HAVE_LIBWRAP /* Only one instance of these variables */ @@ -120,7 +130,7 @@ static void message_cb(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const s #endif static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, int sig, void *userdata) { - pa_log_info("Got signal %s.", pa_strsignal(sig)); + pa_log_info("Got signal %s.", pa_sig2str(sig)); switch (sig) { #ifdef SIGUSR1 @@ -153,14 +163,6 @@ static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e, } } -static void close_pipe(int p[2]) { - if (p[0] != -1) - close(p[0]); - if (p[1] != -1) - close(p[1]); - p[0] = p[1] = -1; -} - #define set_env(key, value) putenv(pa_sprintf_malloc("%s=%s", (key), (value))) #if defined(HAVE_PWD_H) && defined(HAVE_GRP_H) @@ -281,7 +283,7 @@ static int create_runtime_dir(void) { static void set_one_rlimit(const pa_rlimit *r, int resource, const char *name) { struct rlimit rl; - assert(r); + pa_assert(r); if (!r->is_set) return; @@ -313,13 +315,11 @@ int main(int argc, char *argv[]) { pa_strbuf *buf = NULL; pa_daemon_conf *conf = NULL; pa_mainloop *mainloop = NULL; - char *s; - int r, retval = 1, d = 0; + int r = 0, retval = 1, d = 0; int daemon_pipe[2] = { -1, -1 }; int suid_root, real_root; int valid_pid_file = 0; - gid_t gid = (gid_t) -1; #ifdef OS_IS_WIN32 @@ -327,6 +327,23 @@ int main(int argc, char *argv[]) { struct timeval tv; #endif + +#if defined(__linux__) && defined(__OPTIMIZE__) + /* + Disable lazy relocations to make usage of external libraries + more deterministic for our RT threads. We abuse __OPTIMIZE__ as + a check whether we are a debug build or not. + */ + + if (!getenv("LD_BIND_NOW")) { + putenv(pa_xstrdup("LD_BIND_NOW=1")); + + /* We have to execute ourselves, because the libc caches the + * value of $LD_BIND_NOW on initialization. */ + pa_assert_se(execv("/proc/self/exe", argv) == 0); + } +#endif + #ifdef HAVE_GETUID real_root = getuid() == 0; suid_root = !real_root && geteuid() == 0; @@ -336,16 +353,26 @@ int main(int argc, char *argv[]) { #endif if (suid_root) { - if (pa_limit_caps() > 0) - /* We managed to drop capabilities except the needed - * ones. Hence we can drop the uid. */ - pa_drop_root(); + /* Drop all capabilities except CAP_SYS_NICE */ + pa_limit_caps(); + + /* Drop priviliges, but keep CAP_SYS_NICE */ + pa_drop_root(); + + /* After dropping root, the effective set is reset, hence, + * let's raise it again */ + pa_limit_caps(); + + /* When capabilities are not supported we will not be able to + * aquire RT sched anymore. But yes, that's the way it is. It + * is just too risky tun let PA run as root all the time. */ } setlocale(LC_ALL, ""); - if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) { - pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'."); + if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0)) { + pa_log_info("Warning: Called SUID root, but not in group '"PA_REALTIME_GROUP"'. " + "For enabling real-time scheduling please become a member of '"PA_REALTIME_GROUP"' , or increase the RLIMIT_RTPRIO user limit."); pa_drop_caps(); pa_drop_root(); suid_root = real_root = 0; @@ -353,8 +380,7 @@ int main(int argc, char *argv[]) { LTDL_SET_PRELOADED_SYMBOLS(); - r = lt_dlinit(); - assert(r == 0); + pa_ltdl_init(); #ifdef OS_IS_WIN32 { @@ -386,7 +412,7 @@ int main(int argc, char *argv[]) { if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) pa_raise_priority(); - if (suid_root) { + if (suid_root && (conf->cmd != PA_CMD_DAEMON || !conf->high_priority)) { pa_drop_caps(); pa_drop_root(); } @@ -408,6 +434,16 @@ int main(int argc, char *argv[]) { goto finish; } + case PA_CMD_DUMP_RESAMPLE_METHODS: { + int i; + + for (i = 0; i < PA_RESAMPLER_MAX; i++) + if (pa_resample_method_supported(i)) + printf("%s\n", pa_resample_method_to_string(i)); + + goto finish; + } + case PA_CMD_HELP : pa_cmdline_help(argv[0]); retval = 0; @@ -440,8 +476,15 @@ int main(int argc, char *argv[]) { goto finish; + case PA_CMD_CLEANUP_SHM: + + if (pa_shm_cleanup() >= 0) + retval = 0; + + goto finish; + default: - assert(conf->cmd == PA_CMD_DAEMON); + pa_assert(conf->cmd == PA_CMD_DAEMON); } if (real_root && !conf->system_instance) { @@ -474,7 +517,7 @@ int main(int argc, char *argv[]) { if (child != 0) { /* Father */ - close(daemon_pipe[1]); + pa_assert_se(pa_close(daemon_pipe[1]) == 0); daemon_pipe[1] = -1; if (pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL) != sizeof(retval)) { @@ -490,7 +533,7 @@ int main(int argc, char *argv[]) { goto finish; } - close(daemon_pipe[0]); + pa_assert_se(pa_close(daemon_pipe[0]) == 0); daemon_pipe[0] = -1; #endif @@ -505,9 +548,9 @@ int main(int argc, char *argv[]) { #endif #ifndef OS_IS_WIN32 - close(0); - close(1); - close(2); + pa_close(0); + pa_close(1); + pa_close(2); open("/dev/null", O_RDONLY); open("/dev/null", O_WRONLY); @@ -529,12 +572,12 @@ int main(int argc, char *argv[]) { #ifdef TIOCNOTTY if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) { ioctl(tty_fd, TIOCNOTTY, (char*) 0); - close(tty_fd); + pa_assert_se(pa_close(tty_fd) == 0); } #endif } - chdir("/"); + pa_assert_se(chdir("/") == 0); umask(0022); if (conf->system_instance) { @@ -564,18 +607,37 @@ int main(int argc, char *argv[]) { signal(SIGPIPE, SIG_IGN); #endif - mainloop = pa_mainloop_new(); - assert(mainloop); + pa_log_info("Page size is %lu bytes", (unsigned long) PA_PAGE_SIZE); + + if (pa_rtclock_hrtimer()) + pa_log_info("Fresh high-resolution timers available! Bon appetit!"); + else + pa_log_info("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"); + +#ifdef SIGRTMIN + /* Valgrind uses SIGRTMAX. To easy debugging we don't use it here */ + pa_rtsig_configure(SIGRTMIN, SIGRTMAX-1); +#endif + + pa_assert_se(mainloop = pa_mainloop_new()); if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) { - pa_log("pa_core_new() failed."); + pa_log("pa_core_new() failed."); goto finish; } c->is_system_instance = !!conf->system_instance; + c->high_priority = !!conf->high_priority; + c->default_sample_spec = conf->default_sample_spec; + c->default_n_fragments = conf->default_n_fragments; + c->default_fragment_size_msec = conf->default_fragment_size_msec; + c->disallow_module_loading = conf->disallow_module_loading; + c->exit_idle_time = conf->exit_idle_time; + c->module_idle_time = conf->module_idle_time; + c->scache_idle_time = conf->scache_idle_time; + c->resample_method = conf->resample_method; - r = pa_signal_init(pa_mainloop_get_api(mainloop)); - assert(r == 0); + pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_signal_new(SIGINT, signal_callback, c); pa_signal_new(SIGTERM, signal_callback, c); @@ -590,9 +652,7 @@ int main(int argc, char *argv[]) { #endif #ifdef OS_IS_WIN32 - timer = pa_mainloop_get_api(mainloop)->time_new( - pa_mainloop_get_api(mainloop), pa_gettimeofday(&tv), message_cb, NULL); - assert(timer); + pa_assert_se(timer = pa_mainloop_get_api(mainloop)->time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&tv), message_cb, NULL)); #endif if (conf->daemonize) @@ -600,10 +660,8 @@ int main(int argc, char *argv[]) { oil_init(); - if (!conf->no_cpu_limit) { - r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop)); - assert(r == 0); - } + if (!conf->no_cpu_limit) + pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0); buf = pa_strbuf_new(); if (conf->default_script_file) @@ -634,12 +692,6 @@ int main(int argc, char *argv[]) { pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); #endif - c->disallow_module_loading = conf->disallow_module_loading; - c->exit_idle_time = conf->exit_idle_time; - c->module_idle_time = conf->module_idle_time; - c->scache_idle_time = conf->scache_idle_time; - c->resample_method = conf->resample_method; - if (c->default_sink_name && pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) { pa_log_error("%s : Fatal error. Default sink name (%s) does not exist in name register.", __FILE__, c->default_sink_name); @@ -656,7 +708,7 @@ int main(int argc, char *argv[]) { pa_mainloop_get_api(mainloop)->time_free(timer); #endif - pa_core_free(c); + pa_core_unref(c); if (!conf->no_cpu_limit) pa_cpu_limit_done(); @@ -676,13 +728,17 @@ finish: if (valid_pid_file) pa_pid_file_remove(); - close_pipe(daemon_pipe); + pa_close_pipe(daemon_pipe); #ifdef OS_IS_WIN32 WSACleanup(); #endif - lt_dlexit(); + pa_ltdl_done(); + +#ifdef HAVE_DBUS + dbus_shutdown(); +#endif return retval; } diff --git a/src/daemon/pulseaudio-module-xsmp.desktop b/src/daemon/pulseaudio-module-xsmp.desktop new file mode 100644 index 000000000..fa719a73a --- /dev/null +++ b/src/daemon/pulseaudio-module-xsmp.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Encoding=UTF-8 +Name=PulseAudio Session Management +Comment=Load module-x11-xsmp into PulseAudio +Exec=pactl load-module module-x11-xsmp +Terminal=false +Type=Application +Categories= +GenericName= diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 40be53110..906de58d5 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -33,6 +33,7 @@ #include #include +#include #include "alsa-util.h" @@ -42,7 +43,6 @@ struct pa_alsa_fdlist { /* This is a temporary buffer used to avoid lots of mallocs */ struct pollfd *work_fds; - snd_pcm_t *pcm; snd_mixer_t *mixer; pa_mainloop_api *m; @@ -56,11 +56,16 @@ struct pa_alsa_fdlist { }; static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void *userdata) { - struct pa_alsa_fdlist *fdl = (struct pa_alsa_fdlist*)userdata; + + struct pa_alsa_fdlist *fdl = userdata; int err, i; unsigned short revents; - assert(a && fdl && (fdl->pcm || fdl->mixer) && fdl->fds && fdl->work_fds); + pa_assert(a); + pa_assert(fdl); + pa_assert(fdl->mixer); + pa_assert(fdl->fds); + pa_assert(fdl->work_fds); if (fdl->polled) return; @@ -69,7 +74,7 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io memcpy(fdl->work_fds, fdl->fds, sizeof(struct pollfd) * fdl->num_fds); - for (i = 0;i < fdl->num_fds;i++) { + for (i = 0;i < fdl->num_fds; i++) { if (e == fdl->ios[i]) { if (events & PA_IO_EVENT_INPUT) fdl->work_fds[i].revents |= POLLIN; @@ -83,63 +88,46 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io } } - assert(i != fdl->num_fds); + pa_assert(i != fdl->num_fds); - if (fdl->pcm) - err = snd_pcm_poll_descriptors_revents(fdl->pcm, fdl->work_fds, fdl->num_fds, &revents); - else - err = snd_mixer_poll_descriptors_revents(fdl->mixer, fdl->work_fds, fdl->num_fds, &revents); - - if (err < 0) { - pa_log_error("Unable to get poll revent: %s", - snd_strerror(err)); + if ((err = snd_mixer_poll_descriptors_revents(fdl->mixer, fdl->work_fds, fdl->num_fds, &revents)) < 0) { + pa_log_error("Unable to get poll revent: %s", snd_strerror(err)); return; } a->defer_enable(fdl->defer, 1); - if (revents) { - if (fdl->pcm) - fdl->cb(fdl->userdata); - else - snd_mixer_handle_events(fdl->mixer); - } + if (revents) + snd_mixer_handle_events(fdl->mixer); } static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *userdata) { - struct pa_alsa_fdlist *fdl = (struct pa_alsa_fdlist*)userdata; + struct pa_alsa_fdlist *fdl = userdata; int num_fds, i, err; struct pollfd *temp; - assert(a && fdl && (fdl->pcm || fdl->mixer)); + pa_assert(a); + pa_assert(fdl); + pa_assert(fdl->mixer); a->defer_enable(fdl->defer, 0); - if (fdl->pcm) - num_fds = snd_pcm_poll_descriptors_count(fdl->pcm); - else - num_fds = snd_mixer_poll_descriptors_count(fdl->mixer); - assert(num_fds > 0); + num_fds = snd_mixer_poll_descriptors_count(fdl->mixer); + pa_assert(num_fds > 0); if (num_fds != fdl->num_fds) { if (fdl->fds) pa_xfree(fdl->fds); if (fdl->work_fds) pa_xfree(fdl->work_fds); - fdl->fds = pa_xmalloc0(sizeof(struct pollfd) * num_fds); - fdl->work_fds = pa_xmalloc(sizeof(struct pollfd) * num_fds); + fdl->fds = pa_xnew0(struct pollfd, num_fds); + fdl->work_fds = pa_xnew(struct pollfd, num_fds); } memset(fdl->work_fds, 0, sizeof(struct pollfd) * num_fds); - if (fdl->pcm) - err = snd_pcm_poll_descriptors(fdl->pcm, fdl->work_fds, num_fds); - else - err = snd_mixer_poll_descriptors(fdl->mixer, fdl->work_fds, num_fds); - - if (err < 0) { - pa_log_error("Unable to get poll descriptors: %s", - snd_strerror(err)); + if ((err = snd_mixer_poll_descriptors(fdl->mixer, fdl->work_fds, num_fds)) < 0) { + pa_log_error("Unable to get poll descriptors: %s", snd_strerror(err)); return; } @@ -149,18 +137,18 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u return; if (fdl->ios) { - for (i = 0;i < fdl->num_fds;i++) + for (i = 0; i < fdl->num_fds; i++) a->io_free(fdl->ios[i]); + if (num_fds != fdl->num_fds) { pa_xfree(fdl->ios); - fdl->ios = pa_xmalloc(sizeof(pa_io_event*) * num_fds); - assert(fdl->ios); + fdl->ios = NULL; } - } else { - fdl->ios = pa_xmalloc(sizeof(pa_io_event*) * num_fds); - assert(fdl->ios); } + if (!fdl->ios) + fdl->ios = pa_xnew(pa_io_event*, num_fds); + /* Swap pointers */ temp = fdl->work_fds; fdl->work_fds = fdl->fds; @@ -168,47 +156,41 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u fdl->num_fds = num_fds; - for (i = 0;i < num_fds;i++) { + for (i = 0;i < num_fds;i++) fdl->ios[i] = a->io_new(a, fdl->fds[i].fd, ((fdl->fds[i].events & POLLIN) ? PA_IO_EVENT_INPUT : 0) | ((fdl->fds[i].events & POLLOUT) ? PA_IO_EVENT_OUTPUT : 0), io_cb, fdl); - assert(fdl->ios[i]); - } } struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) { struct pa_alsa_fdlist *fdl; - fdl = pa_xmalloc(sizeof(struct pa_alsa_fdlist)); + fdl = pa_xnew0(struct pa_alsa_fdlist, 1); fdl->num_fds = 0; fdl->fds = NULL; fdl->work_fds = NULL; - - fdl->pcm = NULL; fdl->mixer = NULL; - fdl->m = NULL; fdl->defer = NULL; fdl->ios = NULL; - fdl->polled = 0; return fdl; } void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) { - assert(fdl); + pa_assert(fdl); if (fdl->defer) { - assert(fdl->m); + pa_assert(fdl->m); fdl->m->defer_free(fdl->defer); } if (fdl->ios) { int i; - assert(fdl->m); + pa_assert(fdl->m); for (i = 0;i < fdl->num_fds;i++) fdl->m->io_free(fdl->ios[i]); pa_xfree(fdl->ios); @@ -222,29 +204,15 @@ void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) { pa_xfree(fdl); } -int pa_alsa_fdlist_init_pcm(struct pa_alsa_fdlist *fdl, snd_pcm_t *pcm_handle, pa_mainloop_api* m, void (*cb)(void *userdata), void *userdata) { - assert(fdl && pcm_handle && m && !fdl->m && cb); - - fdl->pcm = pcm_handle; - fdl->m = m; - - fdl->defer = m->defer_new(m, defer_cb, fdl); - assert(fdl->defer); - - fdl->cb = cb; - fdl->userdata = userdata; - - return 0; -} - -int pa_alsa_fdlist_init_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m) { - assert(fdl && mixer_handle && m && !fdl->m); +int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m) { + pa_assert(fdl); + pa_assert(mixer_handle); + pa_assert(m); + pa_assert(!fdl->m); fdl->mixer = mixer_handle; fdl->m = m; - fdl->defer = m->defer_new(m, defer_cb, fdl); - assert(fdl->defer); return 0; } @@ -274,8 +242,8 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s int i, ret; - assert(pcm_handle); - assert(f); + pa_assert(pcm_handle); + pa_assert(f); if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0) return ret; @@ -308,7 +276,7 @@ try_auto: /* Set the hardware parameters of the given ALSA device. Returns the * selected fragment settings in *period and *period_size */ -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size) { +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size, int *use_mmap) { int ret = -1; snd_pcm_uframes_t buffer_size; unsigned int r = ss->rate; @@ -316,17 +284,32 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p pa_sample_format_t f = ss->format; snd_pcm_hw_params_t *hwparams; - assert(pcm_handle); - assert(ss); - assert(periods); - assert(period_size); + pa_assert(pcm_handle); + pa_assert(ss); + pa_assert(periods); + pa_assert(period_size); + + snd_pcm_hw_params_alloca(&hwparams); buffer_size = *periods * *period_size; - if ((ret = snd_pcm_hw_params_malloc(&hwparams)) < 0 || - (ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 || - (ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0 || - (ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) + if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 || + (ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) + goto finish; + + if (use_mmap && *use_mmap) { + if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) { + + /* mmap() didn't work, fall back to interleaved */ + + if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) + goto finish; + + if (use_mmap) + *use_mmap = 0; + } + + } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) goto finish; if ((ret = set_format(pcm_handle, hwparams, &f)) < 0) @@ -346,7 +329,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p goto finish; if (ss->rate != r) { - pa_log_warn("device doesn't support %u Hz, changed to %u Hz.", ss->rate, r); + pa_log_warn("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r); /* If the sample rate deviates too much, we need to resample */ if (r < ss->rate*.95 || r > ss->rate*1.05) @@ -354,12 +337,12 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p } if (ss->channels != c) { - pa_log_warn("device doesn't support %u channels, changed to %u.", ss->channels, c); + pa_log_warn("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c); ss->channels = c; } if (ss->format != f) { - pa_log_warn("device doesn't support sample format %s, changed to %s.", pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f)); + pa_log_warn("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f)); ss->format = f; } @@ -370,24 +353,54 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p (ret = snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL)) < 0) goto finish; - assert(buffer_size > 0); - assert(*period_size > 0); + pa_assert(buffer_size > 0); + pa_assert(*period_size > 0); *periods = buffer_size / *period_size; - assert(*periods > 0); + pa_assert(*periods > 0); ret = 0; finish: - if (hwparams) - snd_pcm_hw_params_free(hwparams); return ret; } +int pa_alsa_set_sw_params(snd_pcm_t *pcm) { + snd_pcm_sw_params_t *swparams; + int err; + + pa_assert(pcm); + + snd_pcm_sw_params_alloca(&swparams); + + if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) { + pa_log_warn("Unable to determine current swparams: %s\n", snd_strerror(err)); + return err; + } + + if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) { + pa_log_warn("Unable to set stop threshold: %s\n", snd_strerror(err)); + return err; + } + + if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) { + pa_log_warn("Unable to set start threshold: %s\n", snd_strerror(err)); + return err; + } + + if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) { + pa_log_warn("Unable to set sw params: %s\n", snd_strerror(err)); + return err; + } + + return 0; +} + int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) { int err; - assert(mixer && dev); + pa_assert(mixer); + pa_assert(dev); if ((err = snd_mixer_attach(mixer, dev)) < 0) { pa_log_warn("Unable to attach to mixer %s: %s", dev, snd_strerror(err)); @@ -410,10 +423,11 @@ int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) { snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback) { snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid = NULL; + snd_mixer_selem_id_alloca(&sid); - assert(mixer); - assert(name); + pa_assert(mixer); + pa_assert(name); snd_mixer_selem_id_set_name(sid, name); diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index ea6c7e1df..6f1f927e2 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -32,15 +32,14 @@ #include -struct pa_alsa_fdlist; +typedef struct pa_alsa_fdlist pa_alsa_fdlist; struct pa_alsa_fdlist *pa_alsa_fdlist_new(void); void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl); +int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m); -int pa_alsa_fdlist_init_pcm(struct pa_alsa_fdlist *fdl, snd_pcm_t *pcm_handle, pa_mainloop_api* m, void (*cb)(void *userdata), void *userdata); -int pa_alsa_fdlist_init_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m); - -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size); +int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size, int *use_mmap); +int pa_alsa_set_sw_params(snd_pcm_t *pcm); int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev); snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback); diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c index 48a451746..fc1e91ea8 100644 --- a/src/modules/dbus-util.c +++ b/src/modules/dbus-util.c @@ -26,25 +26,25 @@ #include #endif -#include -#include -#include #include #include +#include +#include #include "dbus-util.h" struct pa_dbus_connection { - int refcount; + PA_REFCNT_DECLARE; + pa_core *core; DBusConnection *connection; const char *property_name; pa_defer_event* dispatch_event; }; -static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata) -{ - DBusConnection *conn = (DBusConnection *) userdata; +static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata) { + DBusConnection *conn = userdata; + if (dbus_connection_dispatch(conn) == DBUS_DISPATCH_COMPLETE) { /* no more data to process, disable the deferred */ ea->defer_enable(ev, 0); @@ -52,14 +52,17 @@ static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata) } /* DBusDispatchStatusFunction callback for the pa mainloop */ -static void dispatch_status(DBusConnection *conn, DBusDispatchStatus status, - void *userdata) -{ - pa_dbus_connection *c = (pa_dbus_connection*) userdata; +static void dispatch_status(DBusConnection *conn, DBusDispatchStatus status, void *userdata) { + pa_dbus_connection *c = userdata; + + pa_assert(c); + switch(status) { + case DBUS_DISPATCH_COMPLETE: c->core->mainloop->defer_enable(c->dispatch_event, 0); break; + case DBUS_DISPATCH_DATA_REMAINS: case DBUS_DISPATCH_NEED_MEMORY: default: @@ -68,11 +71,13 @@ static void dispatch_status(DBusConnection *conn, DBusDispatchStatus status, } } -static pa_io_event_flags_t -get_watch_flags(DBusWatch *watch) -{ - unsigned int flags = dbus_watch_get_flags(watch); - pa_io_event_flags_t events = PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR; +static pa_io_event_flags_t get_watch_flags(DBusWatch *watch) { + unsigned int flags; + pa_io_event_flags_t events = 0; + + pa_assert(watch); + + flags = dbus_watch_get_flags(watch); /* no watch flags for disabled watches */ if (!dbus_watch_get_enabled(watch)) @@ -83,21 +88,22 @@ get_watch_flags(DBusWatch *watch) if (flags & DBUS_WATCH_WRITABLE) events |= PA_IO_EVENT_OUTPUT; - return events; + return events | PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR; } /* pa_io_event_cb_t IO event handler */ -static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, - int fd, pa_io_event_flags_t events, void *userdata) -{ +static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) { unsigned int flags = 0; - DBusWatch *watch = (DBusWatch*) userdata; + DBusWatch *watch = userdata; - assert(fd == dbus_watch_get_fd(watch)); +#if HAVE_DBUS_WATCH_GET_UNIX_FD + pa_assert(fd == dbus_watch_get_unix_fd(watch)); +#else + pa_assert(fd == dbus_watch_get_fd(watch)); +#endif if (!dbus_watch_get_enabled(watch)) { - pa_log_warn("Asked to handle disabled watch: %p %i", - (void *) watch, fd); + pa_log_warn("Asked to handle disabled watch: %p %i", (void*) watch, fd); return; } @@ -114,10 +120,8 @@ static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, } /* pa_time_event_cb_t timer event handler */ -static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, - const struct timeval *tv, void *userdata) -{ - DBusTimeout *timeout = (DBusTimeout*) userdata; +static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struct timeval *tv, void *userdata) { + DBusTimeout *timeout = userdata; if (dbus_timeout_get_enabled(timeout)) { struct timeval next = *tv; @@ -130,103 +134,154 @@ static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, } /* DBusAddWatchFunction callback for pa mainloop */ -static dbus_bool_t add_watch(DBusWatch *watch, void *data) -{ +static dbus_bool_t add_watch(DBusWatch *watch, void *data) { + pa_core *c = PA_CORE(data); pa_io_event *ev; - pa_core *c = (pa_core*) data; - ev = c->mainloop->io_new(c->mainloop, dbus_watch_get_fd(watch), - get_watch_flags(watch), - handle_io_event, (void*) watch); - if (NULL == ev) - return FALSE; + pa_assert(watch); + pa_assert(c); - /* dbus_watch_set_data(watch, (void*) ev, c->mainloop->io_free); */ - dbus_watch_set_data(watch, (void*) ev, NULL); + ev = c->mainloop->io_new( + c->mainloop, +#if HAVE_DBUS_WATCH_GET_UNIX_FD + dbus_watch_get_unix_fd(watch), +#else + dbus_watch_get_fd(watch), +#endif + get_watch_flags(watch), handle_io_event, watch); + + dbus_watch_set_data(watch, ev, NULL); return TRUE; } /* DBusRemoveWatchFunction callback for pa mainloop */ -static void remove_watch(DBusWatch *watch, void *data) -{ - pa_core *c = (pa_core*) data; - pa_io_event *ev = (pa_io_event*) dbus_watch_get_data(watch); +static void remove_watch(DBusWatch *watch, void *data) { + pa_core *c = PA_CORE(data); + pa_io_event *ev; - /* free the event */ - if (NULL != ev) + pa_assert(watch); + pa_assert(c); + + if ((ev = dbus_watch_get_data(watch))) c->mainloop->io_free(ev); } /* DBusWatchToggledFunction callback for pa mainloop */ -static void toggle_watch(DBusWatch *watch, void *data) -{ - pa_core *c = (pa_core*) data; - pa_io_event *ev = (pa_io_event*) dbus_watch_get_data(watch); +static void toggle_watch(DBusWatch *watch, void *data) { + pa_core *c = PA_CORE(data); + pa_io_event *ev; + + pa_assert(watch); + pa_core_assert_ref(c); + + pa_assert_se(ev = dbus_watch_get_data(watch)); /* get_watch_flags() checks if the watch is enabled */ c->mainloop->io_enable(ev, get_watch_flags(watch)); } /* DBusAddTimeoutFunction callback for pa mainloop */ -static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) -{ - struct timeval tv; +static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { + pa_core *c = PA_CORE(data); pa_time_event *ev; - pa_core *c = (pa_core*) data; + struct timeval tv; + + pa_assert(timeout); + pa_assert(c); if (!dbus_timeout_get_enabled(timeout)) return FALSE; - if (!pa_gettimeofday(&tv)) - return -1; - + pa_gettimeofday(&tv); pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000); - ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, - (void*) timeout); - if (NULL == ev) - return FALSE; + ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, timeout); - /* dbus_timeout_set_data(timeout, (void*) ev, c->mainloop->time_free); */ - dbus_timeout_set_data(timeout, (void*) ev, NULL); + dbus_timeout_set_data(timeout, ev, NULL); return TRUE; } /* DBusRemoveTimeoutFunction callback for pa mainloop */ -static void remove_timeout(DBusTimeout *timeout, void *data) -{ - pa_core *c = (pa_core*) data; - pa_time_event *ev = (pa_time_event*) dbus_timeout_get_data(timeout); +static void remove_timeout(DBusTimeout *timeout, void *data) { + pa_core *c = PA_CORE(data); + pa_time_event *ev; - /* free the event */ - if (NULL != ev) + pa_assert(timeout); + pa_assert(c); + + if ((ev = dbus_timeout_get_data(timeout))) c->mainloop->time_free(ev); } /* DBusTimeoutToggledFunction callback for pa mainloop */ -static void toggle_timeout(DBusTimeout *timeout, void *data) -{ - struct timeval tv; - pa_core *c = (pa_core*) data; - pa_time_event *ev = (pa_time_event*) dbus_timeout_get_data(timeout); +static void toggle_timeout(DBusTimeout *timeout, void *data) { + pa_core *c = PA_CORE(data); + pa_time_event *ev; + + pa_assert(timeout); + pa_assert(c); + + pa_assert_se(ev = dbus_timeout_get_data(timeout)); if (dbus_timeout_get_enabled(timeout)) { + struct timeval tv; + pa_gettimeofday(&tv); pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000); + c->mainloop->time_restart(ev, &tv); - } else { - /* disable the timeout */ + } else c->mainloop->time_restart(ev, NULL); - } } -static void -pa_dbus_connection_free(pa_dbus_connection *c) -{ - assert(c); - assert(!dbus_connection_get_is_connected(c->connection)); +static void wakeup_main(void *userdata) { + pa_dbus_connection *c = userdata; + + pa_assert(c); + + /* this will wakeup the mainloop and dispatch events, although + * it may not be the cleanest way of accomplishing it */ + c->core->mainloop->defer_enable(c->dispatch_event, 1); +} + +static pa_dbus_connection* pa_dbus_connection_new(pa_core* c, DBusConnection *conn, const char* name) { + pa_dbus_connection *pconn; + + pconn = pa_xnew(pa_dbus_connection, 1); + PA_REFCNT_INIT(pconn); + pconn->core = c; + pconn->property_name = name; + pconn->connection = conn; + pconn->dispatch_event = c->mainloop->defer_new(c->mainloop, dispatch_cb, conn); + + pa_property_set(c, name, pconn); + + return pconn; +} + +DBusConnection* pa_dbus_connection_get(pa_dbus_connection *c){ + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) > 0); + pa_assert(c->connection); + + return c->connection; +} + +void pa_dbus_connection_unref(pa_dbus_connection *c) { + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) > 0); + + if (PA_REFCNT_DEC(c) > 0) + return; + + if (dbus_connection_get_is_connected(c->connection)) { + dbus_connection_close(c->connection); + /* must process remaining messages, bit of a kludge to handle + * both unload and shutdown */ + while (dbus_connection_read_write_dispatch(c->connection, -1)); + } /* already disconnected, just free */ pa_property_remove(c->core, c->property_name); @@ -235,113 +290,39 @@ pa_dbus_connection_free(pa_dbus_connection *c) pa_xfree(c); } -static void -wakeup_main(void *userdata) -{ - pa_dbus_connection *c = (pa_dbus_connection*) userdata; - /* this will wakeup the mainloop and dispatch events, although - * it may not be the cleanest way of accomplishing it */ - c->core->mainloop->defer_enable(c->dispatch_event, 1); -} +pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c) { + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) > 0); -static pa_dbus_connection* pa_dbus_connection_new(pa_core* c, DBusConnection *conn, const char* name) -{ - pa_dbus_connection *pconn = pa_xnew(pa_dbus_connection, 1); - - pconn->refcount = 1; - pconn->core = c; - pconn->property_name = name; - pconn->connection = conn; - pconn->dispatch_event = c->mainloop->defer_new(c->mainloop, dispatch_cb, - (void*) conn); - - pa_property_set(c, name, pconn); - - return pconn; -} - -DBusConnection* pa_dbus_connection_get(pa_dbus_connection *c) -{ - assert(c && c->connection); - return c->connection; -} - -void pa_dbus_connection_unref(pa_dbus_connection *c) -{ - assert(c); - - /* non-zero refcount, still outstanding refs */ - if (--(c->refcount)) - return; - - /* refcount is zero */ - if (dbus_connection_get_is_connected(c->connection)) { - /* disconnect as we have no more internal references */ - dbus_connection_close(c->connection); - /* must process remaining messages, bit of a kludge to - * handle both unload and shutdown */ - while(dbus_connection_read_write_dispatch(c->connection, -1)); - } - pa_dbus_connection_free(c); -} - -pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c) -{ - assert(c); - - ++(c->refcount); + PA_REFCNT_INC(c); return c; } -pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, - DBusError *error) -{ - const char* name; +pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error) { + + static const char *const prop_name[] = { + [DBUS_BUS_SESSION] = "dbus-connection-session", + [DBUS_BUS_SYSTEM] = "dbus-connection-system", + [DBUS_BUS_STARTER] = "dbus-connection-starter" + }; DBusConnection *conn; pa_dbus_connection *pconn; - switch (type) { - case DBUS_BUS_SYSTEM: - name = "dbus-connection-system"; - break; - case DBUS_BUS_SESSION: - name = "dbus-connection-session"; - break; - case DBUS_BUS_STARTER: - name = "dbus-connection-starter"; - break; - default: - assert(0); /* never reached */ - break; - } + pa_assert(type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION || type == DBUS_BUS_STARTER); - if ((pconn = pa_property_get(c, name))) + if ((pconn = pa_property_get(c, prop_name[type]))) return pa_dbus_connection_ref(pconn); - /* else */ - conn = dbus_bus_get_private(type, error); - if (conn == NULL || dbus_error_is_set(error)) { + if (!(conn = dbus_bus_get_private(type, error))) return NULL; - } - pconn = pa_dbus_connection_new(c, conn, name); + pconn = pa_dbus_connection_new(c, conn, prop_name[type]); - /* don't exit on disconnect */ dbus_connection_set_exit_on_disconnect(conn, FALSE); - /* set up the DBUS call backs */ - dbus_connection_set_dispatch_status_function(conn, dispatch_status, - (void*) pconn, NULL); - dbus_connection_set_watch_functions(conn, - add_watch, - remove_watch, - toggle_watch, - (void*) c, NULL); - dbus_connection_set_timeout_functions(conn, - add_timeout, - remove_timeout, - toggle_timeout, - (void*) c, NULL); + dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL); + dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggle_watch, c, NULL); + dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, toggle_timeout, c, NULL); dbus_connection_set_wakeup_main_function(conn, wakeup_main, pconn, NULL); return pconn; diff --git a/src/modules/gconf/gconf-helper.c b/src/modules/gconf/gconf-helper.c index 3483b8451..abd132875 100644 --- a/src/modules/gconf/gconf-helper.c +++ b/src/modules/gconf/gconf-helper.c @@ -32,6 +32,8 @@ #include #include +#include + #define PA_GCONF_ROOT "/system/pulseaudio" #define PA_GCONF_PATH_MODULES PA_GCONF_ROOT"/modules" @@ -40,13 +42,13 @@ static void handle_module(GConfClient *client, const char *name) { gboolean enabled, locked; int i; - snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/locked", name); + pa_snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/locked", name); locked = gconf_client_get_bool(client, p, FALSE); if (locked) return; - snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/enabled", name); + pa_snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/enabled", name); enabled = gconf_client_get_bool(client, p, FALSE); printf("%c%s%c", enabled ? '+' : '-', name, 0); @@ -56,11 +58,11 @@ static void handle_module(GConfClient *client, const char *name) { for (i = 0; i < 10; i++) { gchar *n, *a; - snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/name%i", name, i); + pa_snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/name%i", name, i); if (!(n = gconf_client_get_string(client, p, NULL)) || !*n) break; - snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/args%i", name, i); + pa_snprintf(p, sizeof(p), PA_GCONF_PATH_MODULES"/%s/args%i", name, i); a = gconf_client_get_string(client, p, NULL); printf("%s%c%s%c", n, 0, a ? a : "", 0); diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index cbe17d200..1c8866de2 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -25,7 +25,6 @@ #include #endif -#include #include #include #include @@ -34,6 +33,7 @@ #include #include #include +#include #ifdef HAVE_SYS_PRCTL_H #include @@ -95,7 +95,7 @@ struct userdata { static int fill_buf(struct userdata *u) { ssize_t r; - assert(u); + pa_assert(u); if (u->buf_fill >= BUF_MAX) { pa_log("read buffer overflow"); @@ -111,21 +111,21 @@ static int fill_buf(struct userdata *u) { static int read_byte(struct userdata *u) { int ret; - assert(u); + pa_assert(u); if (u->buf_fill < 1) if (fill_buf(u) < 0) return -1; ret = u->buf[0]; - assert(u->buf_fill > 0); + pa_assert(u->buf_fill > 0); u->buf_fill--; memmove(u->buf, u->buf+1, u->buf_fill); return ret; } static char *read_string(struct userdata *u) { - assert(u); + pa_assert(u); for (;;) { char *e; @@ -143,9 +143,9 @@ static char *read_string(struct userdata *u) { } static void unload_one_module(struct userdata *u, struct module_info*m, unsigned i) { - assert(u); - assert(m); - assert(i < m->n_items); + pa_assert(u); + pa_assert(m); + pa_assert(i < m->n_items); if (m->items[i].index == PA_INVALID_INDEX) return; @@ -161,8 +161,8 @@ static void unload_one_module(struct userdata *u, struct module_info*m, unsigned static void unload_all_modules(struct userdata *u, struct module_info*m) { unsigned i; - assert(u); - assert(m); + pa_assert(u); + pa_assert(m); for (i = 0; i < m->n_items; i++) unload_one_module(u, m, i); @@ -180,10 +180,10 @@ static void load_module( pa_module *mod; - assert(u); - assert(m); - assert(name); - assert(args); + pa_assert(u); + pa_assert(m); + pa_assert(name); + pa_assert(args); if (!is_new) { if (m->items[i].index != PA_INVALID_INDEX && @@ -212,8 +212,8 @@ static void module_info_free(void *p, void *userdata) { struct module_info *m = p; struct userdata *u = userdata; - assert(m); - assert(u); + pa_assert(m); + pa_assert(u); unload_all_modules(u, m); pa_xfree(m->name); @@ -356,8 +356,10 @@ static int start_client(const char *n, pid_t *pid) { return pipe_fds[0]; } else { +#ifdef __linux__ + DIR* d; +#endif int max_fd, i; - /* child */ close(pipe_fds[0]); @@ -372,18 +374,48 @@ static int start_client(const char *n, pid_t *pid) { close(2); open("/dev/null", O_WRONLY); - max_fd = 1024; +#ifdef __linux__ + + if ((d = opendir("/proc/self/fd/"))) { + + struct dirent *de; + + while ((de = readdir(d))) { + char *e = NULL; + int fd; + + if (de->d_name[0] == '.') + continue; + + errno = 0; + fd = strtol(de->d_name, &e, 10); + pa_assert(errno == 0 && e && *e == 0); + + if (fd >= 3 && dirfd(d) != fd) + close(fd); + } + + closedir(d); + } else { -#ifdef HAVE_SYS_RESOURCE_H - { - struct rlimit r; - if (getrlimit(RLIMIT_NOFILE, &r) == 0) - max_fd = r.rlim_max; - } #endif - for (i = 3; i < max_fd; i++) - close(i); + max_fd = 1024; + +#ifdef HAVE_SYS_RESOURCE_H + { + struct rlimit r; + if (getrlimit(RLIMIT_NOFILE, &r) == 0) + max_fd = r.rlim_max; + } +#endif + + for (i = 3; i < max_fd; i++) + close(i); +# +#ifdef __linux__ + } +#endif #ifdef PR_SET_PDEATHSIG /* On Linux we can use PR_SET_PDEATHSIG to have the helper @@ -413,12 +445,12 @@ fail: return -1; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { struct userdata *u; int r; u = pa_xnew(struct userdata, 1); - u->core = c; + u->core = m->core; u->module = m; m->userdata = u; u->module_infos = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); @@ -431,8 +463,8 @@ int pa__init(pa_core *c, pa_module*m) { if ((u->fd = start_client(PA_GCONF_HELPER, &u->pid)) < 0) goto fail; - u->io_event = c->mainloop->io_new( - c->mainloop, + u->io_event = m->core->mainloop->io_new( + m->core->mainloop, u->fd, PA_IO_EVENT_INPUT, io_event_cb, @@ -449,21 +481,20 @@ int pa__init(pa_core *c, pa_module*m) { return 0; fail: - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c); - assert(m); + pa_assert(m); if (!(u = m->userdata)) return; if (u->io_event) - c->mainloop->io_free(u->io_event); + m->core->mainloop->io_free(u->io_event); if (u->fd >= 0) close(u->fd); diff --git a/src/modules/ladspa.h b/src/modules/ladspa.h new file mode 100644 index 000000000..b1a9c4e59 --- /dev/null +++ b/src/modules/ladspa.h @@ -0,0 +1,603 @@ +/* ladspa.h + + Linux Audio Developer's Simple Plugin API Version 1.1[LGPL]. + Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, + Stefan Westerfeld. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. */ + +#ifndef LADSPA_INCLUDED +#define LADSPA_INCLUDED + +#define LADSPA_VERSION "1.1" +#define LADSPA_VERSION_MAJOR 1 +#define LADSPA_VERSION_MINOR 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ + +/* Overview: + + There is a large number of synthesis packages in use or development + on the Linux platform at this time. This API (`The Linux Audio + Developer's Simple Plugin API') attempts to give programmers the + ability to write simple `plugin' audio processors in C/C++ and link + them dynamically (`plug') into a range of these packages (`hosts'). + It should be possible for any host and any plugin to communicate + completely through this interface. + + This API is deliberately short and simple. To achieve compatibility + with a range of promising Linux sound synthesis packages it + attempts to find the `greatest common divisor' in their logical + behaviour. Having said this, certain limiting decisions are + implicit, notably the use of a fixed type (LADSPA_Data) for all + data transfer and absence of a parameterised `initialisation' + phase. See below for the LADSPA_Data typedef. + + Plugins are expected to distinguish between control and audio + data. Plugins have `ports' that are inputs or outputs for audio or + control data and each plugin is `run' for a `block' corresponding + to a short time interval measured in samples. Audio data is + communicated using arrays of LADSPA_Data, allowing a block of audio + to be processed by the plugin in a single pass. Control data is + communicated using single LADSPA_Data values. Control data has a + single value at the start of a call to the `run()' or `run_adding()' + function, and may be considered to remain this value for its + duration. The plugin may assume that all its input and output ports + have been connected to the relevant data location (see the + `connect_port()' function below) before it is asked to run. + + Plugins will reside in shared object files suitable for dynamic + linking by dlopen() and family. The file will provide a number of + `plugin types' that can be used to instantiate actual plugins + (sometimes known as `plugin instances') that can be connected + together to perform tasks. + + This API contains very limited error-handling. */ + +/*****************************************************************************/ + +/* Fundamental data type passed in and out of plugin. This data type + is used to communicate audio samples and control values. It is + assumed that the plugin will work sensibly given any numeric input + value although it may have a preferred range (see hints below). + + For audio it is generally assumed that 1.0f is the `0dB' reference + amplitude and is a `normal' signal level. */ + +typedef float LADSPA_Data; + +/*****************************************************************************/ + +/* Special Plugin Properties: + + Optional features of the plugin type are encapsulated in the + LADSPA_Properties type. This is assembled by ORing individual + properties together. */ + +typedef int LADSPA_Properties; + +/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a + real-time dependency (e.g. listens to a MIDI device) and so its + output must not be cached or subject to significant latency. */ +#define LADSPA_PROPERTY_REALTIME 0x1 + +/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin + may cease to work correctly if the host elects to use the same data + location for both input and output (see connect_port()). This + should be avoided as enabling this flag makes it impossible for + hosts to use the plugin to process audio `in-place.' */ +#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2 + +/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin + is capable of running not only in a conventional host but also in a + `hard real-time' environment. To qualify for this the plugin must + satisfy all of the following: + + (1) The plugin must not use malloc(), free() or other heap memory + management within its run() or run_adding() functions. All new + memory used in run() must be managed via the stack. These + restrictions only apply to the run() function. + + (2) The plugin will not attempt to make use of any library + functions with the exceptions of functions in the ANSI standard C + and C maths libraries, which the host is expected to provide. + + (3) The plugin will not access files, devices, pipes, sockets, IPC + or any other mechanism that might result in process or thread + blocking. + + (4) The plugin will take an amount of time to execute a run() or + run_adding() call approximately of form (A+B*SampleCount) where A + and B depend on the machine and host in use. This amount of time + may not depend on input signals or plugin state. The host is left + the responsibility to perform timings to estimate upper bounds for + A and B. */ +#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4 + +#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME) +#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN) +#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE) + +/*****************************************************************************/ + +/* Plugin Ports: + + Plugins have `ports' that are inputs or outputs for audio or + data. Ports can communicate arrays of LADSPA_Data (for audio + inputs/outputs) or single LADSPA_Data values (for control + input/outputs). This information is encapsulated in the + LADSPA_PortDescriptor type which is assembled by ORing individual + properties together. + + Note that a port must be an input or an output port but not both + and that a port must be a control or audio port but not both. */ + +typedef int LADSPA_PortDescriptor; + +/* Property LADSPA_PORT_INPUT indicates that the port is an input. */ +#define LADSPA_PORT_INPUT 0x1 + +/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */ +#define LADSPA_PORT_OUTPUT 0x2 + +/* Property LADSPA_PORT_CONTROL indicates that the port is a control + port. */ +#define LADSPA_PORT_CONTROL 0x4 + +/* Property LADSPA_PORT_AUDIO indicates that the port is a audio + port. */ +#define LADSPA_PORT_AUDIO 0x8 + +#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT) +#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT) +#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL) +#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO) + +/*****************************************************************************/ + +/* Plugin Port Range Hints: + + The host may wish to provide a representation of data entering or + leaving a plugin (e.g. to generate a GUI automatically). To make + this more meaningful, the plugin should provide `hints' to the host + describing the usual values taken by the data. + + Note that these are only hints. The host may ignore them and the + plugin must not assume that data supplied to it is meaningful. If + the plugin receives invalid input data it is expected to continue + to run without failure and, where possible, produce a sensible + output (e.g. a high-pass filter given a negative cutoff frequency + might switch to an all-pass mode). + + Hints are meaningful for all input and output ports but hints for + input control ports are expected to be particularly useful. + + More hint information is encapsulated in the + LADSPA_PortRangeHintDescriptor type which is assembled by ORing + individual hint types together. Hints may require further + LowerBound and UpperBound information. + + All the hint information for a particular port is aggregated in the + LADSPA_PortRangeHint structure. */ + +typedef int LADSPA_PortRangeHintDescriptor; + +/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field + of the LADSPA_PortRangeHint should be considered meaningful. The + value in this field should be considered the (inclusive) lower + bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also + specified then the value of LowerBound should be multiplied by the + sample rate. */ +#define LADSPA_HINT_BOUNDED_BELOW 0x1 + +/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field + of the LADSPA_PortRangeHint should be considered meaningful. The + value in this field should be considered the (inclusive) upper + bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also + specified then the value of UpperBound should be multiplied by the + sample rate. */ +#define LADSPA_HINT_BOUNDED_ABOVE 0x2 + +/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be + considered a Boolean toggle. Data less than or equal to zero should + be considered `off' or `false,' and data above zero should be + considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in + conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or + LADSPA_HINT_DEFAULT_1. */ +#define LADSPA_HINT_TOGGLED 0x4 + +/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified + should be interpreted as multiples of the sample rate. For + instance, a frequency range from 0Hz to the Nyquist frequency (half + the sample rate) could be requested by this hint in conjunction + with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds + at all must support this hint to retain meaning. */ +#define LADSPA_HINT_SAMPLE_RATE 0x8 + +/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the + user will find it more intuitive to view values using a logarithmic + scale. This is particularly useful for frequencies and gains. */ +#define LADSPA_HINT_LOGARITHMIC 0x10 + +/* Hint LADSPA_HINT_INTEGER indicates that a user interface would + probably wish to provide a stepped control taking only integer + values. Any bounds set should be slightly wider than the actual + integer range required to avoid floating point rounding errors. For + instance, the integer set {0,1,2,3} might be described as [-0.1, + 3.1]. */ +#define LADSPA_HINT_INTEGER 0x20 + +/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal' + value for the port that is sensible as a default. For instance, + this value is suitable for use as an initial value in a user + interface or as a value the host might assign to a control port + when the user has not provided one. Defaults are encoded using a + mask so only one default may be specified for a port. Some of the + hints make use of lower and upper bounds, in which case the + relevant bound or bounds must be available and + LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting + default must be rounded if LADSPA_HINT_INTEGER is present. Default + values were introduced in LADSPA v1.1. */ +#define LADSPA_HINT_DEFAULT_MASK 0x3C0 + +/* This default values indicates that no default is provided. */ +#define LADSPA_HINT_DEFAULT_NONE 0x0 + +/* This default hint indicates that the suggested lower bound for the + port should be used. */ +#define LADSPA_HINT_DEFAULT_MINIMUM 0x40 + +/* This default hint indicates that a low value between the suggested + lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 + + log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper + * 0.25). */ +#define LADSPA_HINT_DEFAULT_LOW 0x80 + +/* This default hint indicates that a middle value between the + suggested lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 + + log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper * + 0.5). */ +#define LADSPA_HINT_DEFAULT_MIDDLE 0xC0 + +/* This default hint indicates that a high value between the suggested + lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 + + log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper + * 0.75). */ +#define LADSPA_HINT_DEFAULT_HIGH 0x100 + +/* This default hint indicates that the suggested upper bound for the + port should be used. */ +#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140 + +/* This default hint indicates that the number 0 should be used. Note + that this default may be used in conjunction with + LADSPA_HINT_TOGGLED. */ +#define LADSPA_HINT_DEFAULT_0 0x200 + +/* This default hint indicates that the number 1 should be used. Note + that this default may be used in conjunction with + LADSPA_HINT_TOGGLED. */ +#define LADSPA_HINT_DEFAULT_1 0x240 + +/* This default hint indicates that the number 100 should be used. */ +#define LADSPA_HINT_DEFAULT_100 0x280 + +/* This default hint indicates that the Hz frequency of `concert A' + should be used. This will be 440 unless the host uses an unusual + tuning convention, in which case it may be within a few Hz. */ +#define LADSPA_HINT_DEFAULT_440 0x2C0 + +#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW) +#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE) +#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED) +#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE) +#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC) +#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER) + +#define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK) +#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MINIMUM) +#define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_LOW) +#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MIDDLE) +#define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_HIGH) +#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MAXIMUM) +#define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_0) +#define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_1) +#define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_100) +#define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_440) + +typedef struct _LADSPA_PortRangeHint { + + /* Hints about the port. */ + LADSPA_PortRangeHintDescriptor HintDescriptor; + + /* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When + LADSPA_HINT_SAMPLE_RATE is also active then this value should be + multiplied by the relevant sample rate. */ + LADSPA_Data LowerBound; + + /* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When + LADSPA_HINT_SAMPLE_RATE is also active then this value should be + multiplied by the relevant sample rate. */ + LADSPA_Data UpperBound; + +} LADSPA_PortRangeHint; + +/*****************************************************************************/ + +/* Plugin Handles: + + This plugin handle indicates a particular instance of the plugin + concerned. It is valid to compare this to NULL (0 for C++) but + otherwise the host should not attempt to interpret it. The plugin + may use it to reference internal instance data. */ + +typedef void * LADSPA_Handle; + +/*****************************************************************************/ + +/* Descriptor for a Type of Plugin: + + This structure is used to describe a plugin type. It provides a + number of functions to examine the type, instantiate it, link it to + buffers and workspaces and to run it. */ + +typedef struct _LADSPA_Descriptor { + + /* This numeric identifier indicates the plugin type + uniquely. Plugin programmers may reserve ranges of IDs from a + central body to avoid clashes. Hosts may assume that IDs are + below 0x1000000. */ + unsigned long UniqueID; + + /* This identifier can be used as a unique, case-sensitive + identifier for the plugin type within the plugin file. Plugin + types should be identified by file and label rather than by index + or plugin name, which may be changed in new plugin + versions. Labels must not contain white-space characters. */ + const char * Label; + + /* This indicates a number of properties of the plugin. */ + LADSPA_Properties Properties; + + /* This member points to the null-terminated name of the plugin + (e.g. "Sine Oscillator"). */ + const char * Name; + + /* This member points to the null-terminated string indicating the + maker of the plugin. This can be an empty string but not NULL. */ + const char * Maker; + + /* This member points to the null-terminated string indicating any + copyright applying to the plugin. If no Copyright applies the + string "None" should be used. */ + const char * Copyright; + + /* This indicates the number of ports (input AND output) present on + the plugin. */ + unsigned long PortCount; + + /* This member indicates an array of port descriptors. Valid indices + vary from 0 to PortCount-1. */ + const LADSPA_PortDescriptor * PortDescriptors; + + /* This member indicates an array of null-terminated strings + describing ports (e.g. "Frequency (Hz)"). Valid indices vary from + 0 to PortCount-1. */ + const char * const * PortNames; + + /* This member indicates an array of range hints for each port (see + above). Valid indices vary from 0 to PortCount-1. */ + const LADSPA_PortRangeHint * PortRangeHints; + + /* This may be used by the plugin developer to pass any custom + implementation data into an instantiate call. It must not be used + or interpreted by the host. It is expected that most plugin + writers will not use this facility as LADSPA_Handle should be + used to hold instance data. */ + void * ImplementationData; + + /* This member is a function pointer that instantiates a plugin. A + handle is returned indicating the new plugin instance. The + instantiation function accepts a sample rate as a parameter. The + plugin descriptor from which this instantiate function was found + must also be passed. This function must return NULL if + instantiation fails. + + Note that instance initialisation should generally occur in + activate() rather than here. */ + LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor, + unsigned long SampleRate); + + /* This member is a function pointer that connects a port on an + instantiated plugin to a memory location at which a block of data + for the port will be read/written. The data location is expected + to be an array of LADSPA_Data for audio ports or a single + LADSPA_Data value for control ports. Memory issues will be + managed by the host. The plugin must read/write the data at these + locations every time run() or run_adding() is called and the data + present at the time of this connection call should not be + considered meaningful. + + connect_port() may be called more than once for a plugin instance + to allow the host to change the buffers that the plugin is + reading or writing. These calls may be made before or after + activate() or deactivate() calls. + + connect_port() must be called at least once for each port before + run() or run_adding() is called. When working with blocks of + LADSPA_Data the plugin should pay careful attention to the block + size passed to the run function as the block allocated may only + just be large enough to contain the block of samples. + + Plugin writers should be aware that the host may elect to use the + same buffer for more than one port and even use the same buffer + for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN). + However, overlapped buffers or use of a single buffer for both + audio and control data may result in unexpected behaviour. */ + void (*connect_port)(LADSPA_Handle Instance, + unsigned long Port, + LADSPA_Data * DataLocation); + + /* This member is a function pointer that initialises a plugin + instance and activates it for use. This is separated from + instantiate() to aid real-time support and so that hosts can + reinitialise a plugin instance by calling deactivate() and then + activate(). In this case the plugin instance must reset all state + information dependent on the history of the plugin instance + except for any data locations provided by connect_port() and any + gain set by set_run_adding_gain(). If there is nothing for + activate() to do then the plugin writer may provide a NULL rather + than an empty function. + + When present, hosts must call this function once before run() (or + run_adding()) is called for the first time. This call should be + made as close to the run() call as possible and indicates to + real-time plugins that they are now live. Plugins should not rely + on a prompt call to run() after activate(). activate() may not be + called again unless deactivate() is called first. Note that + connect_port() may be called before or after a call to + activate(). */ + void (*activate)(LADSPA_Handle Instance); + + /* This method is a function pointer that runs an instance of a + plugin for a block. Two parameters are required: the first is a + handle to the particular instance to be run and the second + indicates the block size (in samples) for which the plugin + instance may run. + + Note that if an activate() function exists then it must be called + before run() or run_adding(). If deactivate() is called for a + plugin instance then the plugin instance may not be reused until + activate() has been called again. + + If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE + then there are various things that the plugin should not do + within the run() or run_adding() functions (see above). */ + void (*run)(LADSPA_Handle Instance, + unsigned long SampleCount); + + /* This method is a function pointer that runs an instance of a + plugin for a block. This has identical behaviour to run() except + in the way data is output from the plugin. When run() is used, + values are written directly to the memory areas associated with + the output ports. However when run_adding() is called, values + must be added to the values already present in the memory + areas. Furthermore, output values written must be scaled by the + current gain set by set_run_adding_gain() (see below) before + addition. + + run_adding() is optional. When it is not provided by a plugin, + this function pointer must be set to NULL. When it is provided, + the function set_run_adding_gain() must be provided also. */ + void (*run_adding)(LADSPA_Handle Instance, + unsigned long SampleCount); + + /* This method is a function pointer that sets the output gain for + use when run_adding() is called (see above). If this function is + never called the gain is assumed to default to 1. Gain + information should be retained when activate() or deactivate() + are called. + + This function should be provided by the plugin if and only if the + run_adding() function is provided. When it is absent this + function pointer must be set to NULL. */ + void (*set_run_adding_gain)(LADSPA_Handle Instance, + LADSPA_Data Gain); + + /* This is the counterpart to activate() (see above). If there is + nothing for deactivate() to do then the plugin writer may provide + a NULL rather than an empty function. + + Hosts must deactivate all activated units after they have been + run() (or run_adding()) for the last time. This call should be + made as close to the last run() call as possible and indicates to + real-time plugins that they are no longer live. Plugins should + not rely on prompt deactivation. Note that connect_port() may be + called before or after a call to deactivate(). + + Deactivation is not similar to pausing as the plugin instance + will be reinitialised when activate() is called to reuse it. */ + void (*deactivate)(LADSPA_Handle Instance); + + /* Once an instance of a plugin has been finished with it can be + deleted using the following function. The instance handle passed + ceases to be valid after this call. + + If activate() was called for a plugin instance then a + corresponding call to deactivate() must be made before cleanup() + is called. */ + void (*cleanup)(LADSPA_Handle Instance); + +} LADSPA_Descriptor; + +/**********************************************************************/ + +/* Accessing a Plugin: */ + +/* The exact mechanism by which plugins are loaded is host-dependent, + however all most hosts will need to know is the name of shared + object file containing the plugin types. To allow multiple hosts to + share plugin types, hosts may wish to check for environment + variable LADSPA_PATH. If present, this should contain a + colon-separated path indicating directories that should be searched + (in order) when loading plugin types. + + A plugin programmer must include a function called + "ladspa_descriptor" with the following function prototype within + the shared object file. This function will have C-style linkage (if + you are using C++ this is taken care of by the `extern "C"' clause + at the top of the file). + + A host will find the plugin shared object file by one means or + another, find the ladspa_descriptor() function, call it, and + proceed from there. + + Plugin types are accessed by index (not ID) using values from 0 + upwards. Out of range indexes must result in this function + returning NULL, so the plugin count can be determined by checking + for the least index that results in NULL being returned. */ + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); + +/* Datatype corresponding to the ladspa_descriptor() function. */ +typedef const LADSPA_Descriptor * +(*LADSPA_Descriptor_Function)(unsigned long Index); + +/**********************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* LADSPA_INCLUDED */ + +/* EOF */ diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 3d9f75774..a09247fea 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -26,18 +26,12 @@ #include #endif -#include #include -#ifdef HAVE_SYS_POLL_H -#include -#else -#include "poll.h" -#endif - #include #include +#include #include #include @@ -47,6 +41,11 @@ #include #include #include +#include +#include +#include +#include +#include #include "alsa-util.h" #include "module-alsa-sink-symdef.h" @@ -62,20 +61,38 @@ PA_MODULE_USAGE( "rate= " "fragments= " "fragment_size= " - "channel_map=") + "channel_map= " + "mmap=") + +#define DEFAULT_DEVICE "default" struct userdata { + pa_core *core; + pa_module *module; + pa_sink *sink; + + pa_thread *thread; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + snd_pcm_t *pcm_handle; + + pa_alsa_fdlist *mixer_fdl; snd_mixer_t *mixer_handle; snd_mixer_elem_t *mixer_elem; - pa_sink *sink; - struct pa_alsa_fdlist *pcm_fdl; - struct pa_alsa_fdlist *mixer_fdl; long hw_volume_max, hw_volume_min; - size_t frame_size, fragment_size; - pa_memchunk memchunk, silence; - pa_module *module; + size_t frame_size, fragment_size, hwbuf_size; + unsigned nfragments; + pa_memchunk memchunk; + + char *device_name; + + int use_mmap; + + int first; + + pa_rtpoll_item *alsa_rtpoll_item; }; static const char* const valid_modargs[] = { @@ -87,260 +104,440 @@ static const char* const valid_modargs[] = { "fragments", "fragment_size", "channel_map", + "mmap", NULL }; -#define DEFAULT_DEVICE "default" +static int mmap_write(struct userdata *u) { + int work_done = 0; -static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, u->sink ? pa_sink_used_by(u->sink) : 0); -} + pa_assert(u); + pa_sink_assert_ref(u->sink); -static void clear_up(struct userdata *u) { - assert(u); + for (;;) { + pa_memchunk chunk; + void *p; + snd_pcm_sframes_t n; + int err; + const snd_pcm_channel_area_t *areas; + snd_pcm_uframes_t offset, frames; - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - u->sink = NULL; - } + if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) { - if (u->pcm_fdl) - pa_alsa_fdlist_free(u->pcm_fdl); - if (u->mixer_fdl) - pa_alsa_fdlist_free(u->mixer_fdl); + if (n == -EPIPE) { + pa_log_debug("snd_pcm_avail_update: Buffer underrun!"); + u->first = 1; + } - u->pcm_fdl = u->mixer_fdl = NULL; + if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0) + continue; - if (u->mixer_handle) { - snd_mixer_close(u->mixer_handle); - u->mixer_handle = NULL; - } + if (err == -EAGAIN) + return work_done; - if (u->pcm_handle) { - snd_pcm_drop(u->pcm_handle); - snd_pcm_close(u->pcm_handle); - u->pcm_handle = NULL; + pa_log("snd_pcm_avail_update: %s", snd_strerror(err)); + return -1; + } + +/* pa_log("Got request for %i samples", (int) n); */ + + if (n <= 0) + return work_done; + + frames = n; + + if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) { + + if (err == -EPIPE) { + pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!"); + u->first = 1; + } + + if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) + continue; + + if (err == -EAGAIN) + return work_done; + + pa_log("Failed to write data to DSP: %s", snd_strerror(err)); + return -1; + } + + /* Check these are multiples of 8 bit */ + pa_assert((areas[0].first & 7) == 0); + pa_assert((areas[0].step & 7)== 0); + + /* We assume a single interleaved memory buffer */ + pa_assert((areas[0].first >> 3) == 0); + pa_assert((areas[0].step >> 3) == u->frame_size); + + p = (uint8_t*) areas[0].addr + (offset * u->frame_size); + + chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, 1); + chunk.length = pa_memblock_get_length(chunk.memblock); + chunk.index = 0; + + pa_sink_render_into_full(u->sink, &chunk); + + /* FIXME: Maybe we can do something to keep this memory block + * a little bit longer around? */ + pa_memblock_unref_fixed(chunk.memblock); + + if ((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0) { + + if (err == -EPIPE) { + pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!"); + u->first = 1; + } + + if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) + continue; + + if (err == -EAGAIN) + return work_done; + + pa_log("Failed to write data to DSP: %s", snd_strerror(err)); + return -1; + } + + work_done = 1; + + if (frames >= (snd_pcm_uframes_t) n) + return work_done; + +/* pa_log("wrote %i samples", (int) frames); */ } } -static int xrun_recovery(struct userdata *u) { - int ret; - assert(u); +static int unix_write(struct userdata *u) { + snd_pcm_status_t *status; + int work_done = 0; - pa_log_info("*** ALSA-XRUN (playback) ***"); + snd_pcm_status_alloca(&status); - if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) { - pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); + pa_assert(u); + pa_sink_assert_ref(u->sink); - clear_up(u); - pa_module_unload_request(u->module); + for (;;) { + void *p; + snd_pcm_sframes_t t; + ssize_t l; + int err; + + if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) { + pa_log("Failed to query DSP status data: %s", snd_strerror(err)); + return -1; + } + + if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size) + pa_log_debug("Buffer underrun!"); + + l = snd_pcm_status_get_avail(status) * u->frame_size; + +/* pa_log("%u bytes to write", l); */ + + if (l <= 0) + return work_done; + + if (u->memchunk.length <= 0) + pa_sink_render(u->sink, l, &u->memchunk); + + pa_assert(u->memchunk.length > 0); + + p = pa_memblock_acquire(u->memchunk.memblock); + t = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, u->memchunk.length / u->frame_size); + pa_memblock_release(u->memchunk.memblock); + +/* pa_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l); */ + + pa_assert(t != 0); + + if (t < 0) { + + if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0) + continue; + + if (t == -EAGAIN) { + pa_log_debug("EAGAIN"); + return work_done; + } else { + pa_log("Failed to write data to DSP: %s", snd_strerror(t)); + return -1; + } + } + + u->memchunk.index += t * u->frame_size; + u->memchunk.length -= t * u->frame_size; + + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + pa_memchunk_reset(&u->memchunk); + } + + work_done = 1; + + if (t * u->frame_size >= (unsigned) l) + return work_done; + } +} + +static pa_usec_t sink_get_latency(struct userdata *u) { + pa_usec_t r = 0; + snd_pcm_status_t *status; + snd_pcm_sframes_t frames = 0; + int err; + + snd_pcm_status_alloca(&status); + + pa_assert(u); + pa_assert(u->pcm_handle); + + if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) + pa_log("Failed to get delay: %s", snd_strerror(err)); + else + frames = snd_pcm_status_get_delay(status); + + if (frames > 0) + r = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec); + + if (u->memchunk.memblock) + r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec); + + return r; +} + +static int build_pollfd(struct userdata *u) { + int err; + struct pollfd *pollfd; + int n; + + pa_assert(u); + pa_assert(u->pcm_handle); + + if ((n = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) { + pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n)); return -1; } - return ret; -} + if (u->alsa_rtpoll_item) + pa_rtpoll_item_free(u->alsa_rtpoll_item); -static int suspend_recovery(struct userdata *u) { - int ret; - assert(u); + u->alsa_rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, n); + pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, NULL); - pa_log_info("*** ALSA-SUSPEND (playback) ***"); - - if ((ret = snd_pcm_resume(u->pcm_handle)) < 0) { - if (ret == -EAGAIN) - return -1; - - if (ret != -ENOSYS) - pa_log("snd_pcm_resume() failed: %s", snd_strerror(-ret)); - else { - if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) - pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); - } - - if (ret < 0) { - clear_up(u); - pa_module_unload_request(u->module); - return -1; - } - } - - return ret; -} - -static void do_write(struct userdata *u) { - assert(u); - - update_usage(u); - - for (;;) { - pa_memchunk *memchunk = NULL; - snd_pcm_sframes_t frames; - - if (u->memchunk.memblock) - memchunk = &u->memchunk; - else { - if (pa_sink_render(u->sink, u->fragment_size, &u->memchunk) < 0) - memchunk = &u->silence; - else - memchunk = &u->memchunk; - } - - assert(memchunk->memblock); - assert(memchunk->memblock->data); - assert(memchunk->length); - assert(memchunk->memblock->length); - assert((memchunk->length % u->frame_size) == 0); - - if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) { - if (frames == -EAGAIN) - return; - - if (frames == -EPIPE) { - if (xrun_recovery(u) < 0) - return; - - continue; - } - - if (frames == -ESTRPIPE) { - if (suspend_recovery(u) < 0) - return; - - continue; - } - - pa_log("snd_pcm_writei() failed: %s", snd_strerror(-frames)); - - clear_up(u); - pa_module_unload_request(u->module); - return; - } - - if (memchunk == &u->memchunk) { - size_t l = frames * u->frame_size; - memchunk->index += l; - memchunk->length -= l; - - if (memchunk->length == 0) { - pa_memblock_unref(memchunk->memblock); - memchunk->memblock = NULL; - memchunk->index = memchunk->length = 0; - } - } - - break; - } -} - -static void fdl_callback(void *userdata) { - struct userdata *u = userdata; - assert(u); - - if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) - if (xrun_recovery(u) < 0) - return; - - if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_SUSPENDED) - if (suspend_recovery(u) < 0) - return; - - do_write(u); -} - -static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { - struct userdata *u = snd_mixer_elem_get_callback_private(elem); - - assert(u && u->mixer_handle); - - if (mask == SND_CTL_EVENT_MASK_REMOVE) - return 0; - - if (mask & SND_CTL_EVENT_MASK_VALUE) { - if (u->sink->get_hw_volume) - u->sink->get_hw_volume(u->sink); - if (u->sink->get_hw_mute) - u->sink->get_hw_mute(u->sink); - pa_subscription_post(u->sink->core, - PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, - u->sink->index); + if ((err = snd_pcm_poll_descriptors(u->pcm_handle, pollfd, n)) < 0) { + pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err)); + return -1; } return 0; } -static pa_usec_t sink_get_latency_cb(pa_sink *s) { - pa_usec_t r = 0; - struct userdata *u = s->userdata; - snd_pcm_sframes_t frames; - int err; +static int suspend(struct userdata *u) { + pa_assert(u); + pa_assert(u->pcm_handle); - assert(s && u && u->sink); + /* Let's suspend */ + snd_pcm_drain(u->pcm_handle); + snd_pcm_close(u->pcm_handle); + u->pcm_handle = NULL; - if ((err = snd_pcm_delay(u->pcm_handle, &frames)) < 0) { - pa_log("failed to get delay: %s", snd_strerror(err)); - s->get_latency = NULL; - return 0; + if (u->alsa_rtpoll_item) { + pa_rtpoll_item_free(u->alsa_rtpoll_item); + u->alsa_rtpoll_item = NULL; } - if (frames < 0) - frames = 0; + pa_log_info("Device suspended..."); - r += pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); - - if (u->memchunk.memblock) - r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); - - return r; + return 0; } -static int sink_get_hw_volume_cb(pa_sink *s) { +static int unsuspend(struct userdata *u) { + pa_sample_spec ss; + int err, b; + unsigned nfrags; + snd_pcm_uframes_t period_size; + + pa_assert(u); + pa_assert(!u->pcm_handle); + + pa_log_info("Trying resume..."); + + snd_config_update_free_global(); + if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { + pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err)); + goto fail; + } + + ss = u->sink->sample_spec; + nfrags = u->nfragments; + period_size = u->fragment_size / u->frame_size; + b = u->use_mmap; + + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { + pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); + goto fail; + } + + if (b != u->use_mmap) { + pa_log_warn("Resume failed, couldn't get original access mode."); + goto fail; + } + + if (!pa_sample_spec_equal(&ss, &u->sink->sample_spec)) { + pa_log_warn("Resume failed, couldn't restore original sample settings."); + goto fail; + } + + if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) { + pa_log_warn("Resume failed, couldn't restore original fragment settings."); + goto fail; + } + + if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) { + pa_log("Failed to set software parameters: %s", snd_strerror(err)); + goto fail; + } + + if (build_pollfd(u) < 0) + goto fail; + + /* FIXME: We need to reload the volume somehow */ + + u->first = 1; + + pa_log_info("Resumed successfully..."); + + return 0; + +fail: + if (u->pcm_handle) { + snd_pcm_close(u->pcm_handle); + u->pcm_handle = NULL; + } + + return -1; +} + +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + + switch (code) { + + case PA_SINK_MESSAGE_GET_LATENCY: { + pa_usec_t r = 0; + + if (u->pcm_handle) + r = sink_get_latency(u); + + *((pa_usec_t*) data) = r; + + return 0; + } + + case PA_SINK_MESSAGE_SET_STATE: + + switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) { + + case PA_SINK_SUSPENDED: + pa_assert(PA_SINK_OPENED(u->sink->thread_info.state)); + + if (suspend(u) < 0) + return -1; + + break; + + case PA_SINK_IDLE: + case PA_SINK_RUNNING: + + if (u->sink->thread_info.state == PA_SINK_INIT) { + if (build_pollfd(u) < 0) + return -1; + } + + if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { + if (unsuspend(u) < 0) + return -1; + } + + break; + + case PA_SINK_UNLINKED: + case PA_SINK_INIT: + ; + } + + break; + } + + return pa_sink_process_msg(o, code, data, offset, chunk); +} + +static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { + struct userdata *u = snd_mixer_elem_get_callback_private(elem); + + pa_assert(u); + pa_assert(u->mixer_handle); + + if (mask == SND_CTL_EVENT_MASK_REMOVE) + return 0; + + if (mask & SND_CTL_EVENT_MASK_VALUE) { + pa_sink_get_volume(u->sink); + pa_sink_get_mute(u->sink); + } + + return 0; +} + +static int sink_get_volume_cb(pa_sink *s) { struct userdata *u = s->userdata; int err; int i; - assert(u); - assert(u->mixer_elem); + pa_assert(u); + pa_assert(u->mixer_elem); - for (i = 0; i < s->hw_volume.channels; i++) { + for (i = 0; i < s->sample_spec.channels; i++) { long set_vol, vol; - assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); + pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol)) < 0) goto fail; - set_vol = (long) roundf(((float) s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; + set_vol = (long) roundf(((float) s->volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; /* Try to avoid superfluous volume changes */ if (set_vol != vol) - s->hw_volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); + s->volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); } return 0; fail: pa_log_error("Unable to read volume: %s", snd_strerror(err)); - s->get_hw_volume = NULL; - s->set_hw_volume = NULL; + + s->get_volume = NULL; + s->set_volume = NULL; return -1; } -static int sink_set_hw_volume_cb(pa_sink *s) { +static int sink_set_volume_cb(pa_sink *s) { struct userdata *u = s->userdata; int err; int i; - pa_volume_t vol; - assert(u); - assert(u->mixer_elem); + pa_assert(u); + pa_assert(u->mixer_elem); - for (i = 0; i < s->hw_volume.channels; i++) { + for (i = 0; i < s->sample_spec.channels; i++) { long alsa_vol; + pa_volume_t vol; - assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); + pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); - vol = s->hw_volume.values[i]; + vol = s->volume.values[i]; if (vol > PA_VOLUME_NORM) vol = PA_VOLUME_NORM; @@ -355,55 +552,166 @@ static int sink_set_hw_volume_cb(pa_sink *s) { fail: pa_log_error("Unable to set volume: %s", snd_strerror(err)); - s->get_hw_volume = NULL; - s->set_hw_volume = NULL; + + s->get_volume = NULL; + s->set_volume = NULL; return -1; } -static int sink_get_hw_mute_cb(pa_sink *s) { +static int sink_get_mute_cb(pa_sink *s) { struct userdata *u = s->userdata; int err, sw; - assert(u && u->mixer_elem); + pa_assert(u); + pa_assert(u->mixer_elem); - err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw); - if (err) { + if ((err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw)) < 0) { pa_log_error("Unable to get switch: %s", snd_strerror(err)); - s->get_hw_mute = NULL; - s->set_hw_mute = NULL; + + s->get_mute = NULL; + s->set_mute = NULL; return -1; } - s->hw_muted = !sw; + s->muted = !sw; return 0; } -static int sink_set_hw_mute_cb(pa_sink *s) { +static int sink_set_mute_cb(pa_sink *s) { struct userdata *u = s->userdata; int err; - assert(u && u->mixer_elem); + pa_assert(u); + pa_assert(u->mixer_elem); - err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->hw_muted); - if (err) { + if ((err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->muted)) < 0) { pa_log_error("Unable to set switch: %s", snd_strerror(err)); - s->get_hw_mute = NULL; - s->set_hw_mute = NULL; + + s->get_mute = NULL; + s->set_mute = NULL; return -1; } return 0; } -int pa__init(pa_core *c, pa_module*m) { +static void thread_func(void *userdata) { + struct userdata *u = userdata; + + pa_assert(u); + + pa_log_debug("Thread starting up"); + + if (u->core->high_priority) + pa_make_realtime(); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + for (;;) { + int ret; + + /* Render some data and write it to the dsp */ + if (PA_SINK_OPENED(u->sink->thread_info.state)) { + int work_done = 0; + + if (u->use_mmap) { + if ((work_done = mmap_write(u)) < 0) + goto fail; + } else { + if ((work_done = unix_write(u)) < 0) + goto fail; + } + + if (work_done && u->first) { + pa_log_info("Starting playback."); + snd_pcm_start(u->pcm_handle); + u->first = 0; + continue; + } + } + + /* Hmm, nothing to do. Let's sleep */ + if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0) + goto fail; + + if (ret == 0) + goto finish; + + /* Tell ALSA about this and process its response */ + if (PA_SINK_OPENED(u->sink->thread_info.state)) { + struct pollfd *pollfd; + unsigned short revents = 0; + int err; + unsigned n; + + pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, &n); + + if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd, n, &revents)) < 0) { + pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err)); + goto fail; + } + + if (revents & (POLLERR|POLLNVAL|POLLHUP)) { + + if (revents & POLLERR) + pa_log_warn("Got POLLERR from ALSA"); + if (revents & POLLNVAL) + pa_log_warn("Got POLLNVAL from ALSA"); + if (revents & POLLHUP) + pa_log_warn("Got POLLHUP from ALSA"); + + /* Try to recover from this error */ + + switch (snd_pcm_state(u->pcm_handle)) { + + case SND_PCM_STATE_XRUN: + if ((err = snd_pcm_recover(u->pcm_handle, -EPIPE, 1)) != 0) { + pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err)); + goto fail; + } + break; + + case SND_PCM_STATE_SUSPENDED: + if ((err = snd_pcm_recover(u->pcm_handle, -ESTRPIPE, 1)) != 0) { + pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err)); + goto fail; + } + break; + + default: + + snd_pcm_drop(u->pcm_handle); + + if ((err = snd_pcm_prepare(u->pcm_handle)) < 0) { + pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err)); + goto fail; + } + break; + } + } + } + } + +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("Thread shutting down"); +} + +int pa__init(pa_module*m) { + pa_modargs *ma = NULL; - int ret = -1; struct userdata *u = NULL; - const char *dev; + char *dev; pa_sample_spec ss; pa_channel_map map; - uint32_t periods, fragsize; + uint32_t nfrags, frag_size; snd_pcm_uframes_t period_size; size_t frame_size; snd_pcm_info_t *pcm_info = NULL; @@ -412,48 +720,107 @@ int pa__init(pa_core *c, pa_module*m) { const char *name; char *name_buf = NULL; int namereg_fail; + int use_mmap = 1, b; + + snd_pcm_info_alloca(&pcm_info); + + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } - ss = c->default_sample_spec; + ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { - pa_log("failed to parse sample specification and channel map"); + pa_log("Failed to parse sample specification and channel map"); goto fail; } frame_size = pa_frame_size(&ss); - /* Fix latency to 100ms */ - periods = 8; - fragsize = pa_bytes_per_second(&ss)/128; + nfrags = m->core->default_n_fragments; + frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss); + if (frag_size <= 0) + frag_size = frame_size; - if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { - pa_log("failed to parse buffer metrics"); + if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0) { + pa_log("Failed to parse buffer metrics"); + goto fail; + } + period_size = frag_size/frame_size; + + if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) { + pa_log("Failed to parse mmap argument."); goto fail; } - period_size = fragsize/frame_size; u = pa_xnew0(struct userdata, 1); - m->userdata = u; + u->core = m->core; u->module = m; + m->userdata = u; + u->use_mmap = use_mmap; + u->first = 1; + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + u->alsa_rtpoll_item = NULL; + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); snd_config_update_free_global(); - if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { - pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); - goto fail; + + dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE)); + + for (;;) { + + if ((err = snd_pcm_open(&u->pcm_handle, dev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { + pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); + pa_xfree(dev); + goto fail; + } + + b = use_mmap; + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { + + if (err == -EPERM) { + /* Hmm, some hw is very exotic, so we retry with plughw, if hw didn't work */ + + if (pa_startswith(dev, "hw:")) { + char *d = pa_sprintf_malloc("plughw:%s", dev+3); + pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", dev, d); + pa_xfree(dev); + dev = d; + + snd_pcm_close(u->pcm_handle); + u->pcm_handle = NULL; + continue; + } + } + + pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); + pa_xfree(dev); + goto fail; + } + + break; } - if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 || - (err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) { + u->device_name = dev; + + if (use_mmap && !b) { + pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode."); + u->use_mmap = use_mmap = b; + } + + if (u->use_mmap) + pa_log_info("Successfully enabled mmap() mode."); + + if ((err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) { pa_log("Error fetching PCM info: %s", snd_strerror(err)); goto fail; } - if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) { - pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); + if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) { + pa_log("Failed to set software parameters: %s", snd_strerror(err)); goto fail; } @@ -464,15 +831,16 @@ int pa__init(pa_core *c, pa_module*m) { /* Seems ALSA didn't like the channel number, so let's fix the channel map */ pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); - if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) { - pa_log("Error opening mixer: %s", snd_strerror(err)); - goto fail; - } + if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) + pa_log_warn("Error opening mixer: %s", snd_strerror(err)); + else { - if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || - !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "PCM", "Master"))) { - snd_mixer_close(u->mixer_handle); - u->mixer_handle = NULL; + if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || + !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM"))) { + + snd_mixer_close(u->mixer_handle); + u->mixer_handle = NULL; + } } if ((name = pa_modargs_get_value(ma, "sink_name", NULL))) @@ -482,114 +850,146 @@ int pa__init(pa_core *c, pa_module*m) { namereg_fail = 0; } - if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map))) { + u->sink = pa_sink_new(m->core, __FILE__, name, namereg_fail, &ss, &map); + pa_xfree(name_buf); + + if (!u->sink) { pa_log("Failed to create sink object"); goto fail; } - u->sink->is_hardware = 1; - u->sink->get_latency = sink_get_latency_cb; + u->sink->parent.process_msg = sink_process_msg; + u->sink->userdata = u; + + pa_sink_set_module(u->sink, m); + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc( + "ALSA PCM on %s (%s)%s", + dev, + snd_pcm_info_get_name(pcm_info), + use_mmap ? " via DMA" : "")); + pa_xfree(t); + + u->sink->flags = PA_SINK_HARDWARE|PA_SINK_HW_VOLUME_CTRL|PA_SINK_LATENCY; + + u->frame_size = frame_size; + u->fragment_size = frag_size = period_size * frame_size; + u->nfragments = nfrags; + u->hwbuf_size = u->fragment_size * nfrags; + + pa_log_info("Using %u fragments of size %lu bytes.", nfrags, (long unsigned) u->fragment_size); + + pa_memchunk_reset(&u->memchunk); + if (u->mixer_handle) { - assert(u->mixer_elem); + /* Initialize mixer code */ + + pa_assert(u->mixer_elem); + if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) { int i; - for (i = 0;i < ss.channels;i++) { + for (i = 0; i < ss.channels; i++) if (!snd_mixer_selem_has_playback_channel(u->mixer_elem, i)) break; - } if (i == ss.channels) { - u->sink->get_hw_volume = sink_get_hw_volume_cb; - u->sink->set_hw_volume = sink_set_hw_volume_cb; - snd_mixer_selem_get_playback_volume_range( - u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); - } + pa_log_debug("ALSA device has separate volumes controls for all %u channels.", ss.channels); + u->sink->get_volume = sink_get_volume_cb; + u->sink->set_volume = sink_set_volume_cb; + snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); + } else + pa_log_info("ALSA device lacks separate volumes controls for all %u channels (%u available), falling back to software volume control.", ss.channels, i+1); } + if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) { - u->sink->get_hw_mute = sink_get_hw_mute_cb; - u->sink->set_hw_mute = sink_set_hw_mute_cb; + u->sink->get_mute = sink_get_mute_cb; + u->sink->set_mute = sink_set_mute_cb; } - } - u->sink->userdata = u; - pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("ALSA PCM on %s (%s)", dev, snd_pcm_info_get_name(pcm_info))); - pa_xfree(t); - u->pcm_fdl = pa_alsa_fdlist_new(); - assert(u->pcm_fdl); - if (pa_alsa_fdlist_init_pcm(u->pcm_fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) { - pa_log("failed to initialise file descriptor monitoring"); - goto fail; - } - - if (u->mixer_handle) { u->mixer_fdl = pa_alsa_fdlist_new(); - assert(u->mixer_fdl); - if (pa_alsa_fdlist_init_mixer(u->mixer_fdl, u->mixer_handle, c->mainloop) < 0) { + + if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, m->core->mainloop) < 0) { pa_log("failed to initialise file descriptor monitoring"); goto fail; } + snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback); snd_mixer_elem_set_callback_private(u->mixer_elem, u); } else u->mixer_fdl = NULL; - u->frame_size = frame_size; - u->fragment_size = period_size * frame_size; - - pa_log_info("using %u fragments of size %lu bytes.", periods, (long unsigned)u->fragment_size); - - u->silence.memblock = pa_memblock_new(c->mempool, u->silence.length = u->fragment_size); - assert(u->silence.memblock); - pa_silence_memblock(u->silence.memblock, &ss); - u->silence.index = 0; - - u->memchunk.memblock = NULL; - u->memchunk.index = u->memchunk.length = 0; - - ret = 0; + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } /* Get initial mixer settings */ - if (u->sink->get_hw_volume) - u->sink->get_hw_volume(u->sink); - if (u->sink->get_hw_mute) - u->sink->get_hw_mute(u->sink); + if (u->sink->get_volume) + u->sink->get_volume(u->sink); + if (u->sink->get_mute) + u->sink->get_mute(u->sink); -finish: + pa_sink_put(u->sink); - pa_xfree(name_buf); + pa_modargs_free(ma); - if (ma) - pa_modargs_free(ma); - - if (pcm_info) - snd_pcm_info_free(pcm_info); - - return ret; + return 0; fail: - if (u) - pa__done(c, m); + if (ma) + pa_modargs_free(ma); - goto finish; + pa__done(m); + + return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c && m); + + pa_assert(m); if (!(u = m->userdata)) return; - clear_up(u); + if (u->sink) + pa_sink_unlink(u->sink); + + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } + + pa_thread_mq_done(&u->thread_mq); + + if (u->sink) + pa_sink_unref(u->sink); if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); - if (u->silence.memblock) - pa_memblock_unref(u->silence.memblock); + if (u->alsa_rtpoll_item) + pa_rtpoll_item_free(u->alsa_rtpoll_item); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->mixer_fdl) + pa_alsa_fdlist_free(u->mixer_fdl); + + if (u->mixer_handle) + snd_mixer_close(u->mixer_handle); + + if (u->pcm_handle) { + snd_pcm_drop(u->pcm_handle); + snd_pcm_close(u->pcm_handle); + } + + pa_xfree(u->device_name); pa_xfree(u); -} + snd_config_update_free_global(); +} diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 4061d668c..d840cac30 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -26,18 +26,12 @@ #include #endif -#include #include -#ifdef HAVE_SYS_POLL_H -#include -#else -#include "poll.h" -#endif - #include #include +#include #include #include @@ -48,6 +42,11 @@ #include #include #include +#include +#include +#include +#include +#include #include "alsa-util.h" #include "module-alsa-source-symdef.h" @@ -63,20 +62,35 @@ PA_MODULE_USAGE( "rate= " "fragments= " "fragment_size= " - "channel_map=") + "channel_map= " + "mmap=") + +#define DEFAULT_DEVICE "default" struct userdata { + pa_core *core; + pa_module *module; + pa_source *source; + + pa_thread *thread; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + snd_pcm_t *pcm_handle; + + pa_alsa_fdlist *mixer_fdl; snd_mixer_t *mixer_handle; snd_mixer_elem_t *mixer_elem; - pa_source *source; - struct pa_alsa_fdlist *pcm_fdl; - struct pa_alsa_fdlist *mixer_fdl; long hw_volume_max, hw_volume_min; - size_t frame_size, fragment_size; - pa_memchunk memchunk; - pa_module *module; + size_t frame_size, fragment_size, hwbuf_size; + unsigned nfragments; + + char *device_name; + + int use_mmap; + + pa_rtpoll_item *alsa_rtpoll_item; }; static const char* const valid_modargs[] = { @@ -88,257 +102,438 @@ static const char* const valid_modargs[] = { "fragments", "fragment_size", "channel_map", + "mmap", NULL }; -#define DEFAULT_DEVICE "default" +static int mmap_read(struct userdata *u) { + int work_done = 0; -static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, u->source ? pa_source_used_by(u->source) : 0); -} + pa_assert(u); + pa_source_assert_ref(u->source); -static void clear_up(struct userdata *u) { - assert(u); + for (;;) { + snd_pcm_sframes_t n; + int err; + const snd_pcm_channel_area_t *areas; + snd_pcm_uframes_t offset, frames; + pa_memchunk chunk; + void *p; - if (u->source) { - pa_source_disconnect(u->source); - pa_source_unref(u->source); - u->source = NULL; - } + if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) { - if (u->pcm_fdl) - pa_alsa_fdlist_free(u->pcm_fdl); - if (u->mixer_fdl) - pa_alsa_fdlist_free(u->mixer_fdl); + if (n == -EPIPE) + pa_log_debug("snd_pcm_avail_update: Buffer underrun!"); - u->pcm_fdl = u->mixer_fdl = NULL; + if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0) + continue; - if (u->mixer_handle) { - snd_mixer_close(u->mixer_handle); - u->mixer_handle = NULL; - } + if (err == -EAGAIN) + return work_done; - if (u->pcm_handle) { - snd_pcm_drop(u->pcm_handle); - snd_pcm_close(u->pcm_handle); - u->pcm_handle = NULL; + pa_log("snd_pcm_avail_update: %s", snd_strerror(err)); + return -1; + } + +/* pa_log("Got request for %i samples", (int) n); */ + + if (n <= 0) + return work_done; + + frames = n; + + if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) { + + if (err == -EPIPE) + pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!"); + + if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) + continue; + + if (err == -EAGAIN) + return work_done; + + pa_log("Failed to write data to DSP: %s", snd_strerror(err)); + return -1; + } + + /* Check these are multiples of 8 bit */ + pa_assert((areas[0].first & 7) == 0); + pa_assert((areas[0].step & 7)== 0); + + /* We assume a single interleaved memory buffer */ + pa_assert((areas[0].first >> 3) == 0); + pa_assert((areas[0].step >> 3) == u->frame_size); + + p = (uint8_t*) areas[0].addr + (offset * u->frame_size); + + chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, 1); + chunk.length = pa_memblock_get_length(chunk.memblock); + chunk.index = 0; + + pa_source_post(u->source, &chunk); + + /* FIXME: Maybe we can do something to keep this memory block + * a little bit longer around? */ + pa_memblock_unref_fixed(chunk.memblock); + + if ((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0) { + + if (err == -EPIPE) + pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!"); + + if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) + continue; + + if (err == -EAGAIN) + return work_done; + + pa_log("Failed to write data to DSP: %s", snd_strerror(err)); + return -1; + } + + work_done = 1; + +/* pa_log("wrote %i samples", (int) frames); */ } } -static int xrun_recovery(struct userdata *u) { - int ret; - assert(u); +static int unix_read(struct userdata *u) { + snd_pcm_status_t *status; + int work_done = 0; - pa_log_info("*** ALSA-XRUN (capture) ***"); + snd_pcm_status_alloca(&status); - if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) { - pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); + pa_assert(u); + pa_source_assert_ref(u->source); - clear_up(u); - pa_module_unload_request(u->module); + for (;;) { + void *p; + snd_pcm_sframes_t t, k; + ssize_t l; + int err; + pa_memchunk chunk; + if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) { + pa_log("Failed to query DSP status data: %s", snd_strerror(err)); + return -1; + } + + if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size) + pa_log_debug("Buffer overrun!"); + + l = snd_pcm_status_get_avail(status) * u->frame_size; + + if (l <= 0) + return work_done; + + chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1); + + k = pa_memblock_get_length(chunk.memblock); + + if (k > l) + k = l; + + k = (k/u->frame_size)*u->frame_size; + + p = pa_memblock_acquire(chunk.memblock); + t = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, k / u->frame_size); + pa_memblock_release(chunk.memblock); + +/* pa_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l); */ + + pa_assert(t != 0); + + if (t < 0) { + pa_memblock_unref(chunk.memblock); + + if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0) + continue; + + if (t == -EAGAIN) { + pa_log_debug("EAGAIN"); + return work_done; + } else { + pa_log("Failed to read data from DSP: %s", snd_strerror(t)); + return -1; + } + } + + chunk.index = 0; + chunk.length = t * u->frame_size; + + pa_source_post(u->source, &chunk); + pa_memblock_unref(chunk.memblock); + + work_done = 1; + + if (t * u->frame_size >= (unsigned) l) + return work_done; + } +} + +static pa_usec_t source_get_latency(struct userdata *u) { + pa_usec_t r = 0; + snd_pcm_status_t *status; + snd_pcm_sframes_t frames = 0; + int err; + + snd_pcm_status_alloca(&status); + + pa_assert(u); + pa_assert(u->pcm_handle); + + if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) + pa_log("Failed to get delay: %s", snd_strerror(err)); + else + frames = snd_pcm_status_get_delay(status); + + if (frames > 0) + r = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec); + + return r; +} + +static int build_pollfd(struct userdata *u) { + int err; + struct pollfd *pollfd; + int n; + + pa_assert(u); + pa_assert(u->pcm_handle); + + if ((n = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) { + pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n)); + return -1; + } + + if (u->alsa_rtpoll_item) + pa_rtpoll_item_free(u->alsa_rtpoll_item); + + u->alsa_rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, n); + pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, NULL); + + if ((err = snd_pcm_poll_descriptors(u->pcm_handle, pollfd, n)) < 0) { + pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err)); return -1; } return 0; } +static int suspend(struct userdata *u) { + pa_assert(u); + pa_assert(u->pcm_handle); -static int suspend_recovery(struct userdata *u) { - int ret; - assert(u); + /* Let's suspend */ + snd_pcm_close(u->pcm_handle); + u->pcm_handle = NULL; - pa_log_info("*** ALSA-SUSPEND (capture) ***"); - - if ((ret = snd_pcm_resume(u->pcm_handle)) < 0) { - if (ret == -EAGAIN) - return -1; - - if (ret != -ENOSYS) - pa_log("snd_pcm_resume() failed: %s", snd_strerror(-ret)); - else { - if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) - pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); - } - - if (ret < 0) { - clear_up(u); - pa_module_unload_request(u->module); - return -1; - } + if (u->alsa_rtpoll_item) { + pa_rtpoll_item_free(u->alsa_rtpoll_item); + u->alsa_rtpoll_item = NULL; } - return ret; + pa_log_info("Device suspended..."); + + return 0; } -static void do_read(struct userdata *u) { - assert(u); +static int unsuspend(struct userdata *u) { + pa_sample_spec ss; + int err, b; + unsigned nfrags; + snd_pcm_uframes_t period_size; - update_usage(u); + pa_assert(u); + pa_assert(!u->pcm_handle); - for (;;) { - pa_memchunk post_memchunk; - snd_pcm_sframes_t frames; - size_t l; + pa_log_info("Trying resume..."); - if (!u->memchunk.memblock) { - u->memchunk.memblock = pa_memblock_new(u->source->core->mempool, u->memchunk.length = u->fragment_size); - u->memchunk.index = 0; - } - - assert(u->memchunk.memblock); - assert(u->memchunk.length); - assert(u->memchunk.memblock->data); - assert(u->memchunk.memblock->length); - assert(u->memchunk.length % u->frame_size == 0); - - if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) { - if (frames == -EAGAIN) - return; - - if (frames == -EPIPE) { - if (xrun_recovery(u) < 0) - return; - - continue; - } - - if (frames == -ESTRPIPE) { - if (suspend_recovery(u) < 0) - return; - - continue; - } - - pa_log("snd_pcm_readi() failed: %s", snd_strerror(-frames)); - - clear_up(u); - pa_module_unload_request(u->module); - return; - } - - l = frames * u->frame_size; - - post_memchunk = u->memchunk; - post_memchunk.length = l; - - pa_source_post(u->source, &post_memchunk); - - u->memchunk.index += l; - u->memchunk.length -= l; - - if (u->memchunk.length == 0) { - pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; - u->memchunk.index = u->memchunk.length = 0; - } - - break; + snd_config_update_free_global(); + if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { + pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err)); + goto fail; } + + ss = u->source->sample_spec; + nfrags = u->nfragments; + period_size = u->fragment_size / u->frame_size; + b = u->use_mmap; + + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { + pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); + goto fail; + } + + if (b != u->use_mmap) { + pa_log_warn("Resume failed, couldn't get original access mode."); + goto fail; + } + + if (!pa_sample_spec_equal(&ss, &u->source->sample_spec)) { + pa_log_warn("Resume failed, couldn't restore original sample settings."); + goto fail; + } + + if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) { + pa_log_warn("Resume failed, couldn't restore original fragment settings."); + goto fail; + } + + if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) { + pa_log("Failed to set software parameters: %s", snd_strerror(err)); + goto fail; + } + + if (build_pollfd(u) < 0) + goto fail; + + snd_pcm_start(u->pcm_handle); + + /* FIXME: We need to reload the volume somehow */ + + pa_log_info("Resumed successfully..."); + + return 0; + +fail: + if (u->pcm_handle) { + snd_pcm_close(u->pcm_handle); + u->pcm_handle = NULL; + } + + return -1; } -static void fdl_callback(void *userdata) { - struct userdata *u = userdata; - assert(u); +static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SOURCE(o)->userdata; - if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN) - if (xrun_recovery(u) < 0) - return; + switch (code) { - if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_SUSPENDED) - if (suspend_recovery(u) < 0) - return; + case PA_SOURCE_MESSAGE_GET_LATENCY: { + pa_usec_t r = 0; - do_read(u); + if (u->pcm_handle) + r = source_get_latency(u); + + *((pa_usec_t*) data) = r; + + return 0; + } + + case PA_SOURCE_MESSAGE_SET_STATE: + + switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) { + + case PA_SOURCE_SUSPENDED: + pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state)); + + if (suspend(u) < 0) + return -1; + + break; + + case PA_SOURCE_IDLE: + case PA_SOURCE_RUNNING: + + if (u->source->thread_info.state == PA_SOURCE_INIT) { + if (build_pollfd(u) < 0) + return -1; + + snd_pcm_start(u->pcm_handle); + } + + if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) { + if (unsuspend(u) < 0) + return -1; + } + + break; + + case PA_SOURCE_UNLINKED: + case PA_SOURCE_INIT: + ; + } + + break; + } + + return pa_source_process_msg(o, code, data, offset, chunk); } static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { struct userdata *u = snd_mixer_elem_get_callback_private(elem); - assert(u && u->mixer_handle); + pa_assert(u); + pa_assert(u->mixer_handle); if (mask == SND_CTL_EVENT_MASK_REMOVE) return 0; if (mask & SND_CTL_EVENT_MASK_VALUE) { - if (u->source->get_hw_volume) - u->source->get_hw_volume(u->source); - if (u->source->get_hw_mute) - u->source->get_hw_mute(u->source); - - pa_subscription_post(u->source->core, - PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, - u->source->index); + pa_source_get_volume(u->source); + pa_source_get_mute(u->source); } return 0; } -static pa_usec_t source_get_latency_cb(pa_source *s) { +static int source_get_volume_cb(pa_source *s) { struct userdata *u = s->userdata; - snd_pcm_sframes_t frames; - assert(s && u && u->source); - - if (snd_pcm_delay(u->pcm_handle, &frames) < 0) { - pa_log("failed to get delay"); - s->get_latency = NULL; - return 0; - } - - return pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); -} - -static int source_get_hw_volume_cb(pa_source *s) { - struct userdata *u = s->userdata; - long vol; int err; int i; - assert(u && u->mixer_elem); + pa_assert(u); + pa_assert(u->mixer_elem); - for (i = 0;i < s->hw_volume.channels;i++) { - long set_vol; + for (i = 0; i < s->sample_spec.channels; i++) { + long set_vol, vol; - assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i)); + pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i)); if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol)) < 0) goto fail; - set_vol = (long) roundf(((float) s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; + set_vol = (long) roundf(((float) s->volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; /* Try to avoid superfluous volume changes */ if (set_vol != vol) - s->hw_volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); + s->volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min)); } return 0; fail: pa_log_error("Unable to read volume: %s", snd_strerror(err)); - s->get_hw_volume = NULL; - s->set_hw_volume = NULL; + + s->get_volume = NULL; + s->set_volume = NULL; return -1; } -static int source_set_hw_volume_cb(pa_source *s) { +static int source_set_volume_cb(pa_source *s) { struct userdata *u = s->userdata; int err; - pa_volume_t vol; int i; - assert(u && u->mixer_elem); + pa_assert(u); + pa_assert(u->mixer_elem); - for (i = 0;i < s->hw_volume.channels;i++) { - assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i)); + for (i = 0; i < s->sample_spec.channels; i++) { + long alsa_vol; + pa_volume_t vol; - vol = s->hw_volume.values[i]; + pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i)); + + vol = s->volume.values[i]; if (vol > PA_VOLUME_NORM) vol = PA_VOLUME_NORM; - vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; + alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; - if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, vol)) < 0) + if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, alsa_vol)) < 0) goto fail; } @@ -346,55 +541,159 @@ static int source_set_hw_volume_cb(pa_source *s) { fail: pa_log_error("Unable to set volume: %s", snd_strerror(err)); - s->get_hw_volume = NULL; - s->set_hw_volume = NULL; + + s->get_volume = NULL; + s->set_volume = NULL; return -1; } -static int source_get_hw_mute_cb(pa_source *s) { +static int source_get_mute_cb(pa_source *s) { struct userdata *u = s->userdata; int err, sw; - assert(u && u->mixer_elem); + pa_assert(u); + pa_assert(u->mixer_elem); - err = snd_mixer_selem_get_capture_switch(u->mixer_elem, 0, &sw); - if (err) { + if ((err = snd_mixer_selem_get_capture_switch(u->mixer_elem, 0, &sw)) < 0) { pa_log_error("Unable to get switch: %s", snd_strerror(err)); - s->get_hw_mute = NULL; - s->set_hw_mute = NULL; + + s->get_mute = NULL; + s->set_mute = NULL; return -1; } - s->hw_muted = !sw; + s->muted = !sw; return 0; } -static int source_set_hw_mute_cb(pa_source *s) { +static int source_set_mute_cb(pa_source *s) { struct userdata *u = s->userdata; int err; - assert(u && u->mixer_elem); + pa_assert(u); + pa_assert(u->mixer_elem); - err = snd_mixer_selem_set_capture_switch_all(u->mixer_elem, !s->hw_muted); - if (err) { + if ((err = snd_mixer_selem_set_capture_switch_all(u->mixer_elem, !s->muted)) < 0) { pa_log_error("Unable to set switch: %s", snd_strerror(err)); - s->get_hw_mute = NULL; - s->set_hw_mute = NULL; + + s->get_mute = NULL; + s->set_mute = NULL; return -1; } return 0; } -int pa__init(pa_core *c, pa_module*m) { +static void thread_func(void *userdata) { + struct userdata *u = userdata; + + pa_assert(u); + + pa_log_debug("Thread starting up"); + + if (u->core->high_priority) + pa_make_realtime(); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + for (;;) { + int ret; + + /* Read some data and pass it to the sources */ + if (PA_SOURCE_OPENED(u->source->thread_info.state)) { + + if (u->use_mmap) { + if (mmap_read(u) < 0) + goto fail; + + } else { + if (unix_read(u) < 0) + goto fail; + } + } + + /* Hmm, nothing to do. Let's sleep */ + if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0) + goto fail; + + if (ret == 0) + goto finish; + + /* Tell ALSA about this and process its response */ + if (PA_SOURCE_OPENED(u->source->thread_info.state)) { + struct pollfd *pollfd; + unsigned short revents = 0; + int err; + unsigned n; + + pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, &n); + + if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd, n, &revents)) < 0) { + pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err)); + goto fail; + } + + if (revents & (POLLERR|POLLNVAL|POLLHUP)) { + + if (revents & POLLERR) + pa_log_warn("Got POLLERR from ALSA"); + if (revents & POLLNVAL) + pa_log_warn("Got POLLNVAL from ALSA"); + if (revents & POLLHUP) + pa_log_warn("Got POLLHUP from ALSA"); + + /* Try to recover from this error */ + + switch (snd_pcm_state(u->pcm_handle)) { + + case SND_PCM_STATE_XRUN: + if ((err = snd_pcm_recover(u->pcm_handle, -EPIPE, 1)) != 0) { + pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err)); + goto fail; + } + break; + + case SND_PCM_STATE_SUSPENDED: + if ((err = snd_pcm_recover(u->pcm_handle, -ESTRPIPE, 1)) != 0) { + pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err)); + goto fail; + } + break; + + default: + + snd_pcm_drop(u->pcm_handle); + + if ((err = snd_pcm_prepare(u->pcm_handle)) < 0) { + pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err)); + goto fail; + } + break; + } + } + } + } + +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("Thread shutting down"); +} + +int pa__init(pa_module*m) { + pa_modargs *ma = NULL; - int ret = -1; struct userdata *u = NULL; - const char *dev; + char *dev; pa_sample_spec ss; pa_channel_map map; - unsigned periods, fragsize; + unsigned nfrags, frag_size; snd_pcm_uframes_t period_size; size_t frame_size; snd_pcm_info_t *pcm_info = NULL; @@ -403,64 +702,125 @@ int pa__init(pa_core *c, pa_module*m) { const char *name; char *name_buf = NULL; int namereg_fail; + int use_mmap = 1, b; + + snd_pcm_info_alloca(&pcm_info); + + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } - ss = c->default_sample_spec; + ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) { - pa_log("failed to parse sample specification"); + pa_log("Failed to parse sample specification"); goto fail; } frame_size = pa_frame_size(&ss); - /* Fix latency to 100ms */ - periods = 12; - fragsize = pa_bytes_per_second(&ss)/128; + nfrags = m->core->default_n_fragments; + frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss); + if (frag_size <= 0) + frag_size = frame_size; - if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { - pa_log("failed to parse buffer metrics"); + if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0) { + pa_log("Failed to parse buffer metrics"); + goto fail; + } + period_size = frag_size/frame_size; + + if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) { + pa_log("Failed to parse mmap argument."); goto fail; } - period_size = fragsize/frame_size; u = pa_xnew0(struct userdata, 1); - m->userdata = u; + u->core = m->core; u->module = m; + m->userdata = u; + u->use_mmap = use_mmap; + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + u->alsa_rtpoll_item = NULL; + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); snd_config_update_free_global(); - if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { - pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); - goto fail; + + dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE)); + + for (;;) { + + if ((err = snd_pcm_open(&u->pcm_handle, dev, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { + pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); + pa_xfree(dev); + goto fail; + } + + b = use_mmap; + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { + + if (err == -EPERM) { + /* Hmm, some hw is very exotic, so we retry with plughw, if hw didn't work */ + + if (pa_startswith(dev, "hw:")) { + char *d = pa_sprintf_malloc("plughw:%s", dev+3); + pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", dev, d); + pa_xfree(dev); + dev = d; + + snd_pcm_close(u->pcm_handle); + u->pcm_handle = NULL; + continue; + } + } + + pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); + pa_xfree(dev); + goto fail; + } + + break; } - if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 || - (err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) { + u->device_name = dev; + + if (use_mmap && !b) { + pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode."); + u->use_mmap = use_mmap = b; + } + + if (u->use_mmap) + pa_log_info("Successfully enabled mmap() mode."); + + if ((err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) { pa_log("Error fetching PCM info: %s", snd_strerror(err)); goto fail; } - if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &period_size)) < 0) { - pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); + if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) { + pa_log("Failed to set software parameters: %s", snd_strerror(err)); goto fail; } + /* ALSA might tweak the sample spec, so recalculate the frame size */ + frame_size = pa_frame_size(&ss); + if (ss.channels != map.channels) /* Seems ALSA didn't like the channel number, so let's fix the channel map */ pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); - if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) { + if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) pa_log("Error opening mixer: %s", snd_strerror(err)); - goto fail; - } + else { - if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || - !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", "Mic"))) { - snd_mixer_close(u->mixer_handle); - u->mixer_handle = NULL; + if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || + !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", NULL))) { + snd_mixer_close(u->mixer_handle); + u->mixer_handle = NULL; + } } if ((name = pa_modargs_get_value(ma, "source_name", NULL))) @@ -470,16 +830,39 @@ int pa__init(pa_core *c, pa_module*m) { namereg_fail = 0; } - if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map))) { + u->source = pa_source_new(m->core, __FILE__, name, namereg_fail, &ss, &map); + pa_xfree(name_buf); + + if (!u->source) { pa_log("Failed to create source object"); goto fail; } - u->source->is_hardware = 1; + u->source->parent.process_msg = source_process_msg; u->source->userdata = u; - u->source->get_latency = source_get_latency_cb; + + pa_source_set_module(u->source, m); + pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); + pa_source_set_rtpoll(u->source, u->rtpoll); + pa_source_set_description(u->source, t = pa_sprintf_malloc( + "ALSA PCM on %s (%s)%s", + dev, + snd_pcm_info_get_name(pcm_info), + use_mmap ? " via DMA" : "")); + pa_xfree(t); + + u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL; + + u->frame_size = frame_size; + u->fragment_size = frag_size = period_size * frame_size; + u->nfragments = nfrags; + u->hwbuf_size = u->fragment_size * nfrags; + + pa_log_info("Using %u fragments of size %lu bytes.", nfrags, (long unsigned) u->fragment_size); + if (u->mixer_handle) { - assert(u->mixer_elem); + pa_assert(u->mixer_elem); + if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) { int i; @@ -489,89 +872,95 @@ int pa__init(pa_core *c, pa_module*m) { } if (i == ss.channels) { - u->source->get_hw_volume = source_get_hw_volume_cb; - u->source->set_hw_volume = source_set_hw_volume_cb; - snd_mixer_selem_get_capture_volume_range( - u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); + u->source->get_volume = source_get_volume_cb; + u->source->set_volume = source_set_volume_cb; + snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); } } + if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) { - u->source->get_hw_mute = source_get_hw_mute_cb; - u->source->set_hw_mute = source_set_hw_mute_cb; + u->source->get_mute = source_get_mute_cb; + u->source->set_mute = source_set_mute_cb; } - } - pa_source_set_owner(u->source, m); - pa_source_set_description(u->source, t = pa_sprintf_malloc("ALSA PCM on %s (%s)", dev, snd_pcm_info_get_name(pcm_info))); - pa_xfree(t); - u->pcm_fdl = pa_alsa_fdlist_new(); - assert(u->pcm_fdl); - if (pa_alsa_fdlist_init_pcm(u->pcm_fdl, u->pcm_handle, c->mainloop, fdl_callback, u) < 0) { - pa_log("failed to initialise file descriptor monitoring"); - goto fail; - } - - if (u->mixer_handle) { u->mixer_fdl = pa_alsa_fdlist_new(); - assert(u->mixer_fdl); - if (pa_alsa_fdlist_init_mixer(u->mixer_fdl, u->mixer_handle, c->mainloop) < 0) { + + if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, m->core->mainloop) < 0) { pa_log("failed to initialise file descriptor monitoring"); goto fail; } + snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback); snd_mixer_elem_set_callback_private(u->mixer_elem, u); } else u->mixer_fdl = NULL; - u->frame_size = frame_size; - u->fragment_size = period_size * frame_size; - - pa_log_info("using %u fragments of size %lu bytes.", periods, (long unsigned) u->fragment_size); - - u->memchunk.memblock = NULL; - u->memchunk.index = u->memchunk.length = 0; - - snd_pcm_start(u->pcm_handle); - - ret = 0; - + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } /* Get initial mixer settings */ - if (u->source->get_hw_volume) - u->source->get_hw_volume(u->source); - if (u->source->get_hw_mute) - u->source->get_hw_mute(u->source); + if (u->source->get_volume) + u->source->get_volume(u->source); + if (u->source->get_mute) + u->source->get_mute(u->source); -finish: - pa_xfree(name_buf); + pa_source_put(u->source); - if (ma) - pa_modargs_free(ma); + pa_modargs_free(ma); - if (pcm_info) - snd_pcm_info_free(pcm_info); - - return ret; + return 0; fail: - if (u) - pa__done(c, m); + if (ma) + pa_modargs_free(ma); - goto finish; + pa__done(m); + + return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c && m); + + pa_assert(m); if (!(u = m->userdata)) return; - clear_up(u); + if (u->source) + pa_source_unlink(u->source); - if (u->memchunk.memblock) - pa_memblock_unref(u->memchunk.memblock); + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } + pa_thread_mq_done(&u->thread_mq); + + if (u->source) + pa_source_unref(u->source); + + if (u->alsa_rtpoll_item) + pa_rtpoll_item_free(u->alsa_rtpoll_item); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->mixer_fdl) + pa_alsa_fdlist_free(u->mixer_fdl); + + if (u->mixer_handle) + snd_mixer_close(u->mixer_handle); + + if (u->pcm_handle) { + snd_pcm_drop(u->pcm_handle); + snd_pcm_close(u->pcm_handle); + } + + pa_xfree(u->device_name); pa_xfree(u); -} + snd_config_update_free_global(); +} diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c index 19ac0c26c..84125214b 100644 --- a/src/modules/module-cli.c +++ b/src/modules/module-cli.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include @@ -35,6 +34,7 @@ #include #include #include +#include #include "module-cli-symdef.h" @@ -51,8 +51,8 @@ static const char* const valid_modargs[] = { static void eof_and_unload_cb(pa_cli*c, void *userdata) { pa_module *m = userdata; - assert(c); - assert(m); + pa_assert(c); + pa_assert(m); pa_module_unload_request(m); } @@ -60,21 +60,20 @@ static void eof_and_unload_cb(pa_cli*c, void *userdata) { static void eof_and_exit_cb(pa_cli*c, void *userdata) { pa_module *m = userdata; - assert(c); - assert(m); + pa_assert(c); + pa_assert(m); m->core->mainloop->quit(m->core->mainloop, 0); } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_iochannel *io; pa_modargs *ma; int exit_on_eof = 0; - assert(c); - assert(m); + pa_assert(m); - if (c->running_as_daemon) { + if (m->core->running_as_daemon) { pa_log_info("Running as daemon, refusing to load this module."); return 0; } @@ -94,12 +93,10 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - io = pa_iochannel_new(c->mainloop, STDIN_FILENO, STDOUT_FILENO); - assert(io); + io = pa_iochannel_new(m->core->mainloop, STDIN_FILENO, STDOUT_FILENO); pa_iochannel_set_noclose(io, 1); - m->userdata = pa_cli_new(c, io, m); - assert(m->userdata); + m->userdata = pa_cli_new(m->core, io, m); pa_cli_set_eof_callback(m->userdata, exit_on_eof ? eof_and_exit_cb : eof_and_unload_cb, m); @@ -115,11 +112,10 @@ fail: return -1; } -void pa__done(pa_core *c, pa_module*m) { - assert(c); - assert(m); +void pa__done(pa_module*m) { + pa_assert(m); - if (c->running_as_daemon == 0) { + if (m->core->running_as_daemon == 0) { pa_cli_free(m->userdata); pa_stdio_release(); } diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 716c20b24..665bf9dd4 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -25,12 +25,13 @@ #include #endif -#include #include +#include #include #include +#include #include #include #include @@ -40,6 +41,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include "module-combine-symdef.h" @@ -55,13 +62,12 @@ PA_MODULE_USAGE( "format= " "channels= " "rate= " - "channel_map= ") + "channel_map=") #define DEFAULT_SINK_NAME "combined" #define MEMBLOCKQ_MAXLENGTH (1024*170) -#define RENDER_SIZE (1024*10) -#define DEFAULT_ADJUST_TIME 20 +#define DEFAULT_ADJUST_TIME 10 static const char* const valid_modargs[] = { "sink_name", @@ -78,95 +84,140 @@ static const char* const valid_modargs[] = { struct output { struct userdata *userdata; + + pa_sink *sink; pa_sink_input *sink_input; - size_t counter; + + pa_asyncmsgq *inq, /* Message queue from the sink thread to this sink input */ + *outq; /* Message queue from this sink input to the sink thread */ + pa_rtpoll_item *inq_rtpoll_item, *outq_rtpoll_item; + pa_memblockq *memblockq; + pa_usec_t total_latency; + PA_LLIST_FIELDS(struct output); }; struct userdata { - pa_module *module; pa_core *core; + pa_module *module; pa_sink *sink; - unsigned n_outputs; - struct output *master; + + pa_thread *thread; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + pa_time_event *time_event; uint32_t adjust_time; - PA_LLIST_HEAD(struct output, outputs); + pa_bool_t automatic; + size_t block_size; + + pa_hook_slot *sink_new_slot, *sink_unlink_slot, *sink_state_changed_slot; + + pa_resample_method_t resample_method; + + struct timeval adjust_timestamp; + + struct output *master; + pa_idxset* outputs; /* managed in main context */ + + struct { + PA_LLIST_HEAD(struct output, active_outputs); /* managed in IO thread context */ + pa_atomic_t running; /* we cache that value here, so that every thread can query it cheaply */ + struct timeval timestamp; + pa_bool_t in_null_mode; + } thread_info; +}; + +enum { + SINK_MESSAGE_ADD_OUTPUT = PA_SINK_MESSAGE_MAX, + SINK_MESSAGE_REMOVE_OUTPUT, + SINK_MESSAGE_NEED +}; + +enum { + SINK_INPUT_MESSAGE_POST = PA_SINK_INPUT_MESSAGE_MAX }; static void output_free(struct output *o); -static void clear_up(struct userdata *u); - -static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, u->sink ? pa_sink_used_by(u->sink) : 0); -} +static int output_create_sink_input(struct output *o); +static void update_master(struct userdata *u, struct output *o); +static void pick_master(struct userdata *u, struct output *except); static void adjust_rates(struct userdata *u) { struct output *o; pa_usec_t max_sink_latency = 0, min_total_latency = (pa_usec_t) -1, target_latency; uint32_t base_rate; - assert(u && u->sink); + uint32_t idx; - for (o = u->outputs; o; o = o->next) { - uint32_t sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0; + pa_assert(u); + pa_sink_assert_ref(u->sink); + if (pa_idxset_size(u->outputs) <= 0) + return; + + if (!u->master) + return; + + if (!PA_SINK_OPENED(pa_sink_get_state(u->sink))) + return; + + for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) { + pa_usec_t sink_latency; + + if (!o->sink_input || !PA_SINK_OPENED(pa_sink_get_state(o->sink))) + continue; + + sink_latency = pa_sink_get_latency(o->sink); o->total_latency = sink_latency + pa_sink_input_get_latency(o->sink_input); if (sink_latency > max_sink_latency) max_sink_latency = sink_latency; - if (o->total_latency < min_total_latency) + if (min_total_latency == (pa_usec_t) -1 || o->total_latency < min_total_latency) min_total_latency = o->total_latency; } - assert(min_total_latency != (pa_usec_t) -1); + if (min_total_latency == (pa_usec_t) -1) + return; target_latency = max_sink_latency > min_total_latency ? max_sink_latency : min_total_latency; pa_log_info("[%s] target latency is %0.0f usec.", u->sink->name, (float) target_latency); + pa_log_info("[%s] master %s latency %0.0f usec.", u->sink->name, u->master->sink->name, (float) u->master->total_latency); base_rate = u->sink->sample_spec.rate; - for (o = u->outputs; o; o = o->next) { + for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) { uint32_t r = base_rate; - if (o->total_latency < target_latency) - r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/ 1000000); - else if (o->total_latency > target_latency) - r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/ 1000000); + if (!o->sink_input || !PA_SINK_OPENED(pa_sink_get_state(o->sink))) + continue; - if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) + if (o->total_latency < target_latency) + r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/PA_USEC_PER_SEC); + else if (o->total_latency > target_latency) + r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/PA_USEC_PER_SEC); + + if (r < (uint32_t) (base_rate*0.9) || r > (uint32_t) (base_rate*1.1)) { pa_log_warn("[%s] sample rates too different, not adjusting (%u vs. %u).", o->sink_input->name, base_rate, r); - else { + pa_sink_input_set_rate(o->sink_input, base_rate); + } else { pa_log_info("[%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.", o->sink_input->name, r, (double) r / base_rate, (float) o->total_latency); pa_sink_input_set_rate(o->sink_input, r); } } } -static void request_memblock(struct userdata *u) { - pa_memchunk chunk; - struct output *o; - assert(u && u->sink); - - update_usage(u); - - if (pa_sink_render(u->sink, RENDER_SIZE, &chunk) < 0) - return; - - for (o = u->outputs; o; o = o->next) - pa_memblockq_push_align(o->memblockq, &chunk); - - pa_memblock_unref(chunk.memblock); -} - -static void time_callback(pa_mainloop_api*a, pa_time_event* e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { +static void time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) { struct userdata *u = userdata; struct timeval n; - assert(u && a && u->time_event == e); + + pa_assert(u); + pa_assert(a); + pa_assert(u->time_event == e); adjust_rates(u); @@ -175,73 +226,547 @@ static void time_callback(pa_mainloop_api*a, pa_time_event* e, PA_GCC_UNUSED con u->sink->core->mainloop->time_restart(e, &n); } -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { - struct output *o = i->userdata; - assert(i && o && o->sink_input && chunk); +static void thread_func(void *userdata) { + struct userdata *u = userdata; - if (pa_memblockq_peek(o->memblockq, chunk) >= 0) - return 0; + pa_assert(u); - /* Try harder */ - request_memblock(o->userdata); + pa_log_debug("Thread starting up"); + + if (u->core->high_priority) + pa_make_realtime(); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + pa_rtclock_get(&u->thread_info.timestamp); + u->thread_info.in_null_mode = FALSE; + + for (;;) { + int ret; + + /* If no outputs are connected, render some data and drop it immediately. */ + if (u->sink->thread_info.state == PA_SINK_RUNNING && !u->thread_info.active_outputs) { + struct timeval now; + + pa_rtclock_get(&now); + + if (!u->thread_info.in_null_mode || pa_timeval_cmp(&u->thread_info.timestamp, &now) <= 0) { + pa_sink_skip(u->sink, u->block_size); + + if (!u->thread_info.in_null_mode) + u->thread_info.timestamp = now; + + pa_timeval_add(&u->thread_info.timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec)); + } + + pa_rtpoll_set_timer_absolute(u->rtpoll, &u->thread_info.timestamp); + u->thread_info.in_null_mode = TRUE; + + } else { + pa_rtpoll_set_timer_disabled(u->rtpoll); + u->thread_info.in_null_mode = FALSE; + } + + /* Hmm, nothing to do. Let's sleep */ + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) { + pa_log_info("pa_rtpoll_run() = %i", ret); + goto fail; + } + + if (ret == 0) + goto finish; + } + +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("Thread shutting down"); +} + +/* Called from I/O thread context */ +static void render_memblock(struct userdata *u, struct output *o, size_t length) { + pa_assert(u); + pa_assert(o); + + /* We are run by the sink thread, on behalf of an output (o). The + * other output is waiting for us, hence it is safe to access its + * mainblockq and asyncmsgq directly. */ + + /* If we are not running, we cannot produce any data */ + if (!pa_atomic_load(&u->thread_info.running)) + return; + + /* Maybe there's some data in the requesting output's queue + * now? */ + while (pa_asyncmsgq_process_one(o->inq) > 0) + ; + + /* Ok, now let's prepare some data if we really have to */ + while (!pa_memblockq_is_readable(o->memblockq)) { + struct output *j; + pa_memchunk chunk; + + /* Render data! */ + pa_sink_render(u->sink, length, &chunk); + + /* OK, let's send this data to the other threads */ + for (j = u->thread_info.active_outputs; j; j = j->next) + + /* Send to other outputs, which are not the requesting + * one */ + + if (j != o) + pa_asyncmsgq_post(j->inq, PA_MSGOBJECT(j->sink_input), SINK_INPUT_MESSAGE_POST, NULL, 0, &chunk, NULL); + + /* And place it directly into the requesting output's queue */ + if (o) + pa_memblockq_push_align(o->memblockq, &chunk); + + pa_memblock_unref(chunk.memblock); + } +} + +/* Called from I/O thread context */ +static void request_memblock(struct output *o, size_t length) { + pa_assert(o); + pa_sink_input_assert_ref(o->sink_input); + pa_sink_assert_ref(o->userdata->sink); + + /* If another thread already prepared some data we received + * the data over the asyncmsgq, hence let's first process + * it. */ + while (pa_asyncmsgq_process_one(o->inq) > 0) + ; + + /* Check whether we're now readable */ + if (pa_memblockq_is_readable(o->memblockq)) + return; + + /* OK, we need to prepare new data, but only if the sink is actually running */ + if (pa_atomic_load(&o->userdata->thread_info.running)) + pa_asyncmsgq_send(o->outq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_NEED, o, length, NULL); +} + +/* Called from I/O thread context */ +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { + struct output *o; + + pa_sink_input_assert_ref(i); + pa_assert_se(o = i->userdata); + + /* If necessary, get some new data */ + request_memblock(o, length); return pa_memblockq_peek(o->memblockq, chunk); } -static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { - struct output *o = i->userdata; - assert(i && o && o->sink_input && chunk && length); - - pa_memblockq_drop(o->memblockq, chunk, length); - o->counter += length; -} - -static void sink_input_kill_cb(pa_sink_input *i) { - struct output *o = i->userdata; - assert(i && o && o->sink_input); - pa_module_unload_request(o->userdata->module); - clear_up(o->userdata); -} - -static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { - struct output *o = i->userdata; - assert(i && o && o->sink_input); - - return pa_bytes_to_usec(pa_memblockq_get_length(o->memblockq), &i->sample_spec); -} - -static pa_usec_t sink_get_latency_cb(pa_sink *s) { - struct userdata *u = s->userdata; - assert(s && u && u->sink && u->master); - - return - pa_sink_input_get_latency(u->master->sink_input) + - pa_sink_get_latency(u->master->sink_input->sink); -} - -static void sink_notify(pa_sink *s) { - struct userdata *u; +/* Called from I/O thread context */ +static void sink_input_drop_cb(pa_sink_input *i, size_t length) { struct output *o; - assert(s); - u = s->userdata; - assert(u); + pa_sink_input_assert_ref(i); + pa_assert(length > 0); + pa_assert_se(o = i->userdata); - for (o = u->outputs; o; o = o->next) - pa_sink_notify(o->sink_input->sink); + pa_memblockq_drop(o->memblockq, length); } -static struct output *output_new(struct userdata *u, pa_sink *sink, int resample_method) { - struct output *o = NULL; - char t[256]; +/* Called from I/O thread context */ +static void sink_input_attach_cb(pa_sink_input *i) { + struct output *o; + + pa_sink_input_assert_ref(i); + pa_assert_se(o = i->userdata); + + /* Set up the queue from the sink thread to us */ + pa_assert(!o->inq_rtpoll_item); + o->inq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq( + i->sink->rtpoll, + PA_RTPOLL_LATE, /* This one is not that important, since we check for data in _peek() anyway. */ + o->inq); +} + +/* Called from I/O thread context */ +static void sink_input_detach_cb(pa_sink_input *i) { + struct output *o; + + pa_sink_input_assert_ref(i); + pa_assert_se(o = i->userdata); + + /* Shut down the queue from the sink thread to us */ + pa_assert(o->inq_rtpoll_item); + pa_rtpoll_item_free(o->inq_rtpoll_item); + o->inq_rtpoll_item = NULL; +} + +/* Called from main context */ +static void sink_input_kill_cb(pa_sink_input *i) { + struct output *o; + + pa_sink_input_assert_ref(i); + pa_assert(o = i->userdata); + + pa_module_unload_request(o->userdata->module); + output_free(o); +} + +/* Called from thread context */ +static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct output *o = PA_SINK_INPUT(obj)->userdata; + + switch (code) { + + case PA_SINK_INPUT_MESSAGE_GET_LATENCY: { + pa_usec_t *r = data; + + *r = pa_bytes_to_usec(pa_memblockq_get_length(o->memblockq), &o->sink_input->sample_spec); + + /* Fall through, the default handler will add in the extra + * latency added by the resampler */ + break; + } + + case SINK_INPUT_MESSAGE_POST: + + if (PA_SINK_OPENED(o->sink_input->sink->thread_info.state)) + pa_memblockq_push_align(o->memblockq, chunk); + else + pa_memblockq_flush(o->memblockq); + + break; + } + + return pa_sink_input_process_msg(obj, code, data, offset, chunk); +} + +/* Called from main context */ +static void disable_output(struct output *o) { + pa_assert(o); + + if (!o->sink_input) + return; + + pa_asyncmsgq_send(o->userdata->sink->asyncmsgq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_REMOVE_OUTPUT, o, 0, NULL); + pa_sink_input_unlink(o->sink_input); + pa_sink_input_unref(o->sink_input); + o->sink_input = NULL; + +} + +/* Called from main context */ +static void enable_output(struct output *o) { + pa_assert(o); + + if (o->sink_input) + return; + + if (output_create_sink_input(o) >= 0) { + + pa_memblockq_flush(o->memblockq); + + pa_sink_input_put(o->sink_input); + + if (o->userdata->sink && PA_SINK_LINKED(pa_sink_get_state(o->userdata->sink))) + pa_asyncmsgq_send(o->userdata->sink->asyncmsgq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_ADD_OUTPUT, o, 0, NULL); + } +} + +/* Called from main context */ +static void suspend(struct userdata *u) { + struct output *o; + uint32_t idx; + + pa_assert(u); + + /* Let's suspend by unlinking all streams */ + for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) + disable_output(o); + + pick_master(u, NULL); + + pa_log_info("Device suspended..."); +} + +/* Called from main context */ +static void unsuspend(struct userdata *u) { + struct output *o; + uint32_t idx; + + pa_assert(u); + + /* Let's resume */ + for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) { + + pa_sink_suspend(o->sink, FALSE); + + if (PA_SINK_OPENED(pa_sink_get_state(o->sink))) + enable_output(o); + } + + pick_master(u, NULL); + + pa_log_info("Resumed successfully..."); +} + +/* Called from main context */ +static int sink_set_state(pa_sink *sink, pa_sink_state_t state) { + struct userdata *u; + + pa_sink_assert_ref(sink); + pa_assert_se(u = sink->userdata); + + /* Please note that in contrast to the ALSA modules we call + * suspend/unsuspend from main context here! */ + + switch (state) { + case PA_SINK_SUSPENDED: + pa_assert(PA_SINK_OPENED(pa_sink_get_state(u->sink))); + + suspend(u); + break; + + case PA_SINK_IDLE: + case PA_SINK_RUNNING: + + if (pa_sink_get_state(u->sink) == PA_SINK_SUSPENDED) + unsuspend(u); + + break; + + case PA_SINK_UNLINKED: + case PA_SINK_INIT: + ; + } + + return 0; +} + +/* Called from thread context of the master */ +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + + switch (code) { + + case PA_SINK_MESSAGE_SET_STATE: + pa_atomic_store(&u->thread_info.running, PA_PTR_TO_UINT(data) == PA_SINK_RUNNING); + break; + + case PA_SINK_MESSAGE_GET_LATENCY: + + /* This code will only be called when running in NULL + * mode, i.e. when no output is attached. See + * sink_get_latency_cb() below */ + + if (u->thread_info.in_null_mode) { + struct timeval now; + + if (pa_timeval_cmp(&u->thread_info.timestamp, pa_rtclock_get(&now)) > 0) { + *((pa_usec_t*) data) = pa_timeval_diff(&u->thread_info.timestamp, &now); + break; + } + } + + *((pa_usec_t*) data) = 0; + + break; + + case SINK_MESSAGE_ADD_OUTPUT: { + struct output *op = data; + + PA_LLIST_PREPEND(struct output, u->thread_info.active_outputs, op); + + pa_assert(!op->outq_rtpoll_item); + + /* Create pa_asyncmsgq to the sink thread */ + + op->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq( + u->rtpoll, + PA_RTPOLL_EARLY-1, /* This item is very important */ + op->outq); + + return 0; + } + + case SINK_MESSAGE_REMOVE_OUTPUT: { + struct output *op = data; + + PA_LLIST_REMOVE(struct output, u->thread_info.active_outputs, op); + + /* Remove the q that leads from this output to the sink thread */ + + pa_assert(op->outq_rtpoll_item); + pa_rtpoll_item_free(op->outq_rtpoll_item); + op->outq_rtpoll_item = NULL; + + return 0; + } + + case SINK_MESSAGE_NEED: + render_memblock(u, data, (size_t) offset); + return 0; + } + + return pa_sink_process_msg(o, code, data, offset, chunk); +} + +/* Called from main context */ +static pa_usec_t sink_get_latency_cb(pa_sink *s) { + struct userdata *u; + + pa_sink_assert_ref(s); + pa_assert_se(u = s->userdata); + + if (u->master) { + /* If we have a master sink, we just return the latency of it + * and add our own buffering on top */ + + if (!u->master->sink_input) + return 0; + + return + pa_sink_input_get_latency(u->master->sink_input) + + pa_sink_get_latency(u->master->sink); + + } else { + pa_usec_t usec = 0; + + /* We have no master, hence let's ask our own thread which + * implements the NULL sink */ + + if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0) + return 0; + + return usec; + } +} + +static void update_description(struct userdata *u) { + int first = 1; + char *t; + struct output *o; + uint32_t idx; + + pa_assert(u); + + if (pa_idxset_isempty(u->outputs)) { + pa_sink_set_description(u->sink, "Simultaneous output"); + return; + } + + t = pa_xstrdup("Simultaneous output to"); + + for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) { + char *e; + + if (first) { + e = pa_sprintf_malloc("%s %s", t, o->sink->description); + first = 0; + } else + e = pa_sprintf_malloc("%s, %s", t, o->sink->description); + + pa_xfree(t); + t = e; + } + + pa_sink_set_description(u->sink, t); + pa_xfree(t); +} + +static void update_master(struct userdata *u, struct output *o) { + pa_assert(u); + + if (u->master == o) + return; + + if ((u->master = o)) + pa_log_info("Master sink is now '%s'", o->sink_input->sink->name); + else + pa_log_info("No master selected, lacking suitable outputs."); +} + +static void pick_master(struct userdata *u, struct output *except) { + struct output *o; + uint32_t idx; + pa_assert(u); + + if (u->master && + u->master != except && + u->master->sink_input && + PA_SINK_OPENED(pa_sink_get_state(u->master->sink))) { + update_master(u, u->master); + return; + } + + for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) + if (o != except && + o->sink_input && + PA_SINK_OPENED(pa_sink_get_state(o->sink))) { + update_master(u, o); + return; + } + + update_master(u, NULL); +} + +static int output_create_sink_input(struct output *o) { pa_sink_input_new_data data; + char *t; - assert(u && sink && u->sink); + pa_assert(o); - o = pa_xmalloc(sizeof(struct output)); + if (o->sink_input) + return 0; + + t = pa_sprintf_malloc("Simultaneous output on %s", o->sink->description); + + pa_sink_input_new_data_init(&data); + data.sink = o->sink; + data.driver = __FILE__; + data.name = t; + pa_sink_input_new_data_set_sample_spec(&data, &o->userdata->sink->sample_spec); + pa_sink_input_new_data_set_channel_map(&data, &o->userdata->sink->channel_map); + data.module = o->userdata->module; + data.resample_method = o->userdata->resample_method; + + o->sink_input = pa_sink_input_new(o->userdata->core, &data, PA_SINK_INPUT_VARIABLE_RATE|PA_SINK_INPUT_DONT_MOVE); + + pa_xfree(t); + + if (!o->sink_input) + return -1; + + o->sink_input->parent.process_msg = sink_input_process_msg; + o->sink_input->peek = sink_input_peek_cb; + o->sink_input->drop = sink_input_drop_cb; + o->sink_input->attach = sink_input_attach_cb; + o->sink_input->detach = sink_input_detach_cb; + o->sink_input->kill = sink_input_kill_cb; + o->sink_input->userdata = o; + + + return 0; +} + +static struct output *output_new(struct userdata *u, pa_sink *sink) { + struct output *o; + + pa_assert(u); + pa_assert(sink); + pa_assert(u->sink); + + o = pa_xnew(struct output, 1); o->userdata = u; - - o->counter = 0; + o->inq = pa_asyncmsgq_new(0); + o->outq = pa_asyncmsgq_new(0); + o->inq_rtpoll_item = NULL; + o->outq_rtpoll_item = NULL; + o->sink = sink; + o->sink_input = NULL; o->memblockq = pa_memblockq_new( 0, MEMBLOCKQ_MAXLENGTH, @@ -251,90 +776,151 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample 0, NULL); - snprintf(t, sizeof(t), "Output stream #%u of sink %s", u->n_outputs+1, u->sink->name); + pa_assert_se(pa_idxset_put(u->outputs, o, NULL) == 0); - pa_sink_input_new_data_init(&data); - data.sink = sink; - data.driver = __FILE__; - data.name = t; - pa_sink_input_new_data_set_sample_spec(&data, &u->sink->sample_spec); - pa_sink_input_new_data_set_channel_map(&data, &u->sink->channel_map); - data.module = u->module; + if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink))) + pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_ADD_OUTPUT, o, 0, NULL); + else { + /* If the sink is not yet started, we need to do the activation ourselves */ + PA_LLIST_PREPEND(struct output, u->thread_info.active_outputs, o); - if (!(o->sink_input = pa_sink_input_new(u->core, &data, PA_SINK_INPUT_VARIABLE_RATE))) - goto fail; + o->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq( + u->rtpoll, + PA_RTPOLL_EARLY-1, /* This item is very important */ + o->outq); + } - o->sink_input->get_latency = sink_input_get_latency_cb; - o->sink_input->peek = sink_input_peek_cb; - o->sink_input->drop = sink_input_drop_cb; - o->sink_input->kill = sink_input_kill_cb; - o->sink_input->userdata = o; + if (PA_SINK_OPENED(pa_sink_get_state(u->sink)) || pa_sink_get_state(u->sink) == PA_SINK_INIT) { + pa_sink_suspend(sink, FALSE); + + if (PA_SINK_OPENED(pa_sink_get_state(sink))) + if (output_create_sink_input(o) < 0) + goto fail; + } + + + update_description(u); - PA_LLIST_PREPEND(struct output, u->outputs, o); - u->n_outputs++; return o; fail: if (o) { + pa_idxset_remove_by_data(u->outputs, o, NULL); + if (o->sink_input) { - pa_sink_input_disconnect(o->sink_input); + pa_sink_input_unlink(o->sink_input); pa_sink_input_unref(o->sink_input); } if (o->memblockq) pa_memblockq_free(o->memblockq); + if (o->inq) + pa_asyncmsgq_unref(o->inq); + + if (o->outq) + pa_asyncmsgq_unref(o->outq); + pa_xfree(o); } return NULL; } -static void output_free(struct output *o) { - assert(o); - PA_LLIST_REMOVE(struct output, o->userdata->outputs, o); - o->userdata->n_outputs--; - pa_memblockq_free(o->memblockq); - pa_sink_input_disconnect(o->sink_input); - pa_sink_input_unref(o->sink_input); - pa_xfree(o); -} - -static void clear_up(struct userdata *u) { +static pa_hook_result_t sink_new_hook_cb(pa_core *c, pa_sink *s, struct userdata* u) { struct output *o; - assert(u); - if (u->time_event) { - u->core->mainloop->time_free(u->time_event); - u->time_event = NULL; + pa_core_assert_ref(c); + pa_sink_assert_ref(s); + pa_assert(u); + pa_assert(u->automatic); + + if (!(s->flags & PA_SINK_HARDWARE) || s == u->sink) + return PA_HOOK_OK; + + pa_log_info("Configuring new sink: %s", s->name); + + if (!(o = output_new(u, s))) { + pa_log("Failed to create sink input on sink '%s'.", s->name); + return PA_HOOK_OK; } - while ((o = u->outputs)) - output_free(o); + if (o->sink_input) + pa_sink_input_put(o->sink_input); - u->master = NULL; + pick_master(u, NULL); - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - u->sink = NULL; - } + return PA_HOOK_OK; } -int pa__init(pa_core *c, pa_module*m) { +static pa_hook_result_t sink_unlink_hook_cb(pa_core *c, pa_sink *s, struct userdata* u) { + struct output *o; + uint32_t idx; + + pa_assert(c); + pa_sink_assert_ref(s); + pa_assert(u); + + if (s == u->sink) + return PA_HOOK_OK; + + for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) + if (o->sink == s) + break; + + if (!o) + return PA_HOOK_OK; + + pa_log_info("Unconfiguring sink: %s", s->name); + + output_free(o); + + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_state_changed_hook_cb(pa_core *c, pa_sink *s, struct userdata* u) { + struct output *o; + uint32_t idx; + pa_sink_state_t state; + + if (s == u->sink) + return PA_HOOK_OK; + + for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) + if (o->sink == s) + break; + + if (!o) + return PA_HOOK_OK; + + state = pa_sink_get_state(s); + + if (PA_SINK_OPENED(state) && PA_SINK_OPENED(pa_sink_get_state(u->sink)) && !o->sink_input) { + enable_output(o); + pick_master(u, NULL); + } + + if (state == PA_SINK_SUSPENDED && o->sink_input) { + disable_output(o); + pick_master(u, o); + } + + return PA_HOOK_OK; +} + +int pa__init(pa_module*m) { struct userdata *u; pa_modargs *ma = NULL; const char *master_name, *slaves, *rm; - pa_sink *master_sink; - char *n = NULL; - const char*split_state; - struct timeval tv; - int resample_method = -1; + pa_sink *master_sink = NULL; + int resample_method = PA_RESAMPLER_TRIVIAL; pa_sample_spec ss; pa_channel_map map; + struct output *o; + uint32_t idx; - assert(c && m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments"); @@ -349,116 +935,256 @@ int pa__init(pa_core *c, pa_module*m) { } u = pa_xnew(struct userdata, 1); + u->core = m->core; + u->module = m; m->userdata = u; u->sink = NULL; - u->n_outputs = 0; u->master = NULL; - u->module = m; - u->core = c; u->time_event = NULL; u->adjust_time = DEFAULT_ADJUST_TIME; - PA_LLIST_HEAD_INIT(struct output, u->outputs); + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + u->thread = NULL; + u->resample_method = resample_method; + u->outputs = pa_idxset_new(NULL, NULL); + memset(&u->adjust_timestamp, 0, sizeof(u->adjust_timestamp)); + u->sink_new_slot = u->sink_unlink_slot = u->sink_state_changed_slot = NULL; + PA_LLIST_HEAD_INIT(struct output, u->thread_info.active_outputs); + pa_atomic_store(&u->thread_info.running, FALSE); + u->thread_info.in_null_mode = FALSE; + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); if (pa_modargs_get_value_u32(ma, "adjust_time", &u->adjust_time) < 0) { - pa_log("failed to parse adjust_time value"); + pa_log("Failed to parse adjust_time value"); goto fail; } - if (!(master_name = pa_modargs_get_value(ma, "master", NULL)) || !(slaves = pa_modargs_get_value(ma, "slaves", NULL))) { - pa_log("no master or slave sinks specified"); + master_name = pa_modargs_get_value(ma, "master", NULL); + slaves = pa_modargs_get_value(ma, "slaves", NULL); + if (!master_name != !slaves) { + pa_log("No master or slave sinks specified"); goto fail; } - if (!(master_sink = pa_namereg_get(c, master_name, PA_NAMEREG_SINK, 1))) { - pa_log("invalid master sink '%s'", master_name); - goto fail; + if (master_name) { + if (!(master_sink = pa_namereg_get(m->core, master_name, PA_NAMEREG_SINK, 1))) { + pa_log("Invalid master sink '%s'", master_name); + goto fail; + } + + ss = master_sink->sample_spec; + u->automatic = FALSE; + } else { + master_sink = NULL; + ss = m->core->default_sample_spec; + u->automatic = TRUE; } - ss = master_sink->sample_spec; if ((pa_modargs_get_sample_spec(ma, &ss) < 0)) { - pa_log("invalid sample specification."); + pa_log("Invalid sample specification."); goto fail; } - if (ss.channels == master_sink->sample_spec.channels) + if (master_sink && ss.channels == master_sink->sample_spec.channels) map = master_sink->channel_map; else pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_DEFAULT); - if ((pa_modargs_get_channel_map(ma, &map) < 0)) { - pa_log("invalid channel map."); + if ((pa_modargs_get_channel_map(ma, NULL, &map) < 0)) { + pa_log("Invalid channel map."); goto fail; } if (ss.channels != map.channels) { - pa_log("channel map and sample specification don't match."); + pa_log("Channel map and sample specification don't match."); goto fail; } - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { - pa_log("failed to create sink"); + if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { + pa_log("Failed to create sink"); goto fail; } - pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, "Combined Sink"); + u->sink->parent.process_msg = sink_process_msg; u->sink->get_latency = sink_get_latency_cb; - u->sink->notify = sink_notify; + u->sink->set_state = sink_set_state; u->sink->userdata = u; - if (!(u->master = output_new(u, master_sink, resample_method))) { - pa_log("failed to create master sink input on sink '%s'.", u->sink->name); + u->sink->flags = PA_SINK_LATENCY; + pa_sink_set_module(u->sink, m); + pa_sink_set_description(u->sink, "Simultaneous output"); + pa_sink_set_rtpoll(u->sink, u->rtpoll); + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + + u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */ + if (u->block_size <= 0) + u->block_size = pa_frame_size(&ss); + + if (!u->automatic) { + const char*split_state; + char *n = NULL; + pa_assert(slaves); + + /* The master and slaves have been specified manually */ + + if (!(u->master = output_new(u, master_sink))) { + pa_log("Failed to create master sink input on sink '%s'.", master_sink->name); + goto fail; + } + + split_state = NULL; + while ((n = pa_split(slaves, ",", &split_state))) { + pa_sink *slave_sink; + + if (!(slave_sink = pa_namereg_get(m->core, n, PA_NAMEREG_SINK, 1)) || slave_sink == u->sink) { + pa_log("Invalid slave sink '%s'", n); + pa_xfree(n); + goto fail; + } + + pa_xfree(n); + + if (!output_new(u, slave_sink)) { + pa_log("Failed to create slave sink input on sink '%s'.", slave_sink->name); + goto fail; + } + } + + if (pa_idxset_size(u->outputs) <= 1) + pa_log_warn("No slave sinks specified."); + + u->sink_new_slot = NULL; + + } else { + pa_sink *s; + + /* We're in automatic mode, we elect one hw sink to the master + * and attach all other hw sinks as slaves to it */ + + for (s = pa_idxset_first(m->core->sinks, &idx); s; s = pa_idxset_next(m->core->sinks, &idx)) { + + if (!(s->flags & PA_SINK_HARDWARE) || s == u->sink) + continue; + + if (!output_new(u, s)) { + pa_log("Failed to create sink input on sink '%s'.", s->name); + goto fail; + } + } + + u->sink_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_NEW_POST], (pa_hook_cb_t) sink_new_hook_cb, u); + } + + u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], (pa_hook_cb_t) sink_unlink_hook_cb, u); + u->sink_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], (pa_hook_cb_t) sink_state_changed_hook_cb, u); + + pick_master(u, NULL); + + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); goto fail; } - split_state = NULL; - while ((n = pa_split(slaves, ",", &split_state))) { - pa_sink *slave_sink; + /* Activate the sink and the sink inputs */ + pa_sink_put(u->sink); - if (!(slave_sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) { - pa_log("invalid slave sink '%s'", n); - goto fail; - } - - pa_xfree(n); - - if (!output_new(u, slave_sink, resample_method)) { - pa_log("failed to create slave sink input on sink '%s'.", slave_sink->name); - goto fail; - } - } - - if (u->n_outputs <= 1) - pa_log_warn("WARNING: no slave sinks specified."); + for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) + if (o->sink_input) + pa_sink_input_put(o->sink_input); if (u->adjust_time > 0) { + struct timeval tv; pa_gettimeofday(&tv); tv.tv_sec += u->adjust_time; - u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u); + u->time_event = m->core->mainloop->time_new(m->core->mainloop, &tv, time_callback, u); } pa_modargs_free(ma); + return 0; fail: - pa_xfree(n); if (ma) pa_modargs_free(ma); - pa__done(c, m); + pa__done(m); + return -1; } -void pa__done(pa_core *c, pa_module*m) { +static void output_free(struct output *o) { + pa_assert(o); + + pick_master(o->userdata, o); + + disable_output(o); + + pa_assert_se(pa_idxset_remove_by_data(o->userdata->outputs, o, NULL)); + + update_description(o->userdata); + + if (o->inq_rtpoll_item) + pa_rtpoll_item_free(o->inq_rtpoll_item); + + if (o->outq_rtpoll_item) + pa_rtpoll_item_free(o->outq_rtpoll_item); + + if (o->inq) + pa_asyncmsgq_unref(o->inq); + + if (o->outq) + pa_asyncmsgq_unref(o->outq); + + if (o->memblockq) + pa_memblockq_free(o->memblockq); + + pa_xfree(o); +} + +void pa__done(pa_module*m) { struct userdata *u; - assert(c && m); + struct output *o; + + pa_assert(m); if (!(u = m->userdata)) return; - clear_up(u); + if (u->sink_new_slot) + pa_hook_slot_free(u->sink_new_slot); + + if (u->sink_unlink_slot) + pa_hook_slot_free(u->sink_unlink_slot); + + if (u->sink_state_changed_slot) + pa_hook_slot_free(u->sink_state_changed_slot); + + if (u->outputs) { + while ((o = pa_idxset_first(u->outputs, NULL))) + output_free(o); + + pa_idxset_free(u->outputs, NULL, NULL); + } + + if (u->sink) + pa_sink_unlink(u->sink); + + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } + + pa_thread_mq_done(&u->thread_mq); + + if (u->sink) + pa_sink_unref(u->sink); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->time_event) + u->core->mainloop->time_free(u->time_event); + pa_xfree(u); } - - diff --git a/src/modules/module-default-device-restore.c b/src/modules/module-default-device-restore.c new file mode 100644 index 000000000..a816eae88 --- /dev/null +++ b/src/modules/module-default-device-restore.c @@ -0,0 +1,103 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "module-default-device-restore-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Automatically restore the default sink and source") +PA_MODULE_VERSION(PACKAGE_VERSION) + +#define DEFAULT_SINK_FILE "default-sink" +#define DEFAULT_SOURCE_FILE "default-source" + +int pa__init(pa_module *m) { + FILE *f; + + /* We never overwrite manually configured settings */ + + if (m->core->default_sink_name) + pa_log_info("Manually configured default sink, not overwriting."); + else if ((f = pa_open_config_file(NULL, DEFAULT_SINK_FILE, NULL, NULL, "r"))) { + char ln[256] = ""; + + fgets(ln, sizeof(ln)-1, f); + pa_strip_nl(ln); + fclose(f); + + if (!ln[0]) + pa_log_debug("No previous default sink setting, ignoring."); + else if (pa_namereg_get(m->core, ln, PA_NAMEREG_SINK, 1)) { + pa_namereg_set_default(m->core, ln, PA_NAMEREG_SINK); + pa_log_debug("Restored default sink '%s'.", ln); + } else + pa_log_info("Saved default sink '%s' not existant, not restoring default sink setting.", ln); + } + + if (m->core->default_source_name) + pa_log_info("Manually configured default source, not overwriting."); + else if ((f = pa_open_config_file(NULL, DEFAULT_SOURCE_FILE, NULL, NULL, "r"))) { + char ln[256] = ""; + + fgets(ln, sizeof(ln)-1, f); + pa_strip_nl(ln); + fclose(f); + + if (!ln[0]) + pa_log_debug("No previous default source setting, ignoring."); + else if (pa_namereg_get(m->core, ln, PA_NAMEREG_SOURCE, 1)) { + pa_namereg_set_default(m->core, ln, PA_NAMEREG_SOURCE); + pa_log_debug("Restored default source '%s'.", ln); + } else + pa_log_info("Saved default source '%s' not existant, not restoring default source setting.", ln); + } + + return 0; +} + +void pa__done(pa_module*m) { + FILE *f; + + if ((f = pa_open_config_file(NULL, DEFAULT_SINK_FILE, NULL, NULL, "w"))) { + const char *n = pa_namereg_get_default_sink_name(m->core); + fprintf(f, "%s\n", n ? n : ""); + fclose(f); + } + + if ((f = pa_open_config_file(NULL, DEFAULT_SOURCE_FILE, NULL, NULL, "w"))) { + const char *n = pa_namereg_get_default_source_name(m->core); + fprintf(f, "%s\n", n ? n : ""); + fclose(f); + } +} + + + diff --git a/src/modules/module-defs.h.m4 b/src/modules/module-defs.h.m4 index c961412d8..5bff748e3 100644 --- a/src/modules/module-defs.h.m4 +++ b/src/modules/module-defs.h.m4 @@ -18,8 +18,8 @@ gen_symbol(pa__get_description) gen_symbol(pa__get_usage) gen_symbol(pa__get_version) -int pa__init(struct pa_core *c, struct pa_module*m); -void pa__done(struct pa_core *c, struct pa_module*m); +int pa__init(pa_module*m); +void pa__done(pa_module*m); const char* pa__get_author(void); const char* pa__get_description(void); diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 41b68ac3e..7dc252434 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -28,7 +28,6 @@ #endif #include -#include #include #include #include @@ -44,6 +43,7 @@ #include #include #include +#include #include "module-detect-symdef.h" @@ -52,6 +52,11 @@ PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE("just-one=") +static const char* const valid_modargs[] = { + "just-one", + NULL +}; + #ifdef HAVE_ALSA static int detect_alsa(pa_core *c, int just_one) { @@ -96,7 +101,7 @@ static int detect_alsa(pa_core *c, int just_one) { if (subdevice != 0) continue; - snprintf(args, sizeof(args), "device=hw:%u", device); + pa_snprintf(args, sizeof(args), "device=hw:%u", device); if (!pa_module_load(c, is_sink ? "module-alsa-sink" : "module-alsa-source", args)) continue; @@ -139,7 +144,7 @@ static int detect_oss(pa_core *c, int just_one) { line[strcspn(line, "\r\n")] = 0; if (!b) { - b = strcmp(line, "Audio devices:") == 0 || strcmp(line, "Installed devices:") == 0; + b = strcmp(line, "Audio devices:") == 0 || strcmp(line, "Installed devices:") == 0; continue; } @@ -148,20 +153,20 @@ static int detect_oss(pa_core *c, int just_one) { if (sscanf(line, "%u: ", &device) == 1) { if (device == 0) - snprintf(args, sizeof(args), "device=/dev/dsp"); + pa_snprintf(args, sizeof(args), "device=/dev/dsp"); else - snprintf(args, sizeof(args), "device=/dev/dsp%u", device); + pa_snprintf(args, sizeof(args), "device=/dev/dsp%u", device); if (!pa_module_load(c, "module-oss", args)) continue; - } else if (sscanf(line, "pcm%u: ", &device) == 1) { + } else if (sscanf(line, "pcm%u: ", &device) == 1) { /* FreeBSD support, the devices are named /dev/dsp0.0, dsp0.1 and so on */ - snprintf(args, sizeof(args), "device=/dev/dsp%u.0", device); + pa_snprintf(args, sizeof(args), "device=/dev/dsp%u.0", device); if (!pa_module_load(c, "module-oss", args)) continue; - } + } n++; @@ -193,7 +198,7 @@ static int detect_solaris(pa_core *c, int just_one) { if (!S_ISCHR(s.st_mode)) return 0; - snprintf(args, sizeof(args), "device=%s", dev); + pa_snprintf(args, sizeof(args), "device=%s", dev); if (!pa_module_load(c, "module-solaris", args)) return 0; @@ -215,17 +220,11 @@ static int detect_waveout(pa_core *c, int just_one) { } #endif -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { int just_one = 0, n = 0; pa_modargs *ma; - static const char* const valid_modargs[] = { - "just-one", - NULL - }; - - assert(c); - assert(m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); @@ -238,16 +237,16 @@ int pa__init(pa_core *c, pa_module*m) { } #if HAVE_ALSA - if ((n = detect_alsa(c, just_one)) <= 0) + if ((n = detect_alsa(m->core, just_one)) <= 0) #endif #if HAVE_OSS - if ((n = detect_oss(c, just_one)) <= 0) + if ((n = detect_oss(m->core, just_one)) <= 0) #endif #if HAVE_SOLARIS - if ((n = detect_solaris(c, just_one)) <= 0) + if ((n = detect_solaris(m->core, just_one)) <= 0) #endif #if OS_IS_WIN32 - if ((n = detect_waveout(c, just_one)) <= 0) + if ((n = detect_waveout(m->core, just_one)) <= 0) #endif { pa_log_warn("failed to detect any sound hardware."); @@ -269,9 +268,3 @@ fail: return -1; } - - -void pa__done(PA_GCC_UNUSED pa_core *c, PA_GCC_UNUSED pa_module*m) { - /* NOP */ -} - diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index 1aecade50..f0f73fcf3 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include @@ -48,23 +47,25 @@ static const char* const valid_modargs[] = { NULL, }; -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_modargs *ma = NULL; int ret = -1, fd = -1; char x = 1; - assert(c && m); + + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || pa_modargs_get_value_s32(ma, "fd", &fd) < 0 || fd < 0) { + pa_log("Failed to parse module arguments"); goto finish; } if (pa_loop_write(fd, &x, sizeof(x), NULL) != sizeof(x)) - pa_log("WARNING: write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno)); + pa_log_warn("write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno)); - close(fd); + pa_assert_se(pa_close(fd) == 0); pa_module_unload_request(m); @@ -76,9 +77,3 @@ finish: return ret; } - -void pa__done(pa_core *c, pa_module*m) { - assert(c && m); -} - - diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index a9fd166d4..6562fe281 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -25,7 +25,6 @@ #endif #include -#include #include #include #include @@ -48,11 +47,12 @@ static const char* const valid_modargs[] = { NULL, }; -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_modargs *ma = NULL; int ret = -1; uint32_t pid = 0; - assert(c && m); + + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || pa_modargs_get_value_u32(ma, "pid", &pid) < 0 || @@ -62,7 +62,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (kill(pid, SIGUSR1) < 0) - pa_log("WARNING: kill(%u) failed: %s", pid, pa_cstrerror(errno)); + pa_log_warn("kill(%u) failed: %s", pid, pa_cstrerror(errno)); pa_module_unload_request(m); @@ -74,9 +74,3 @@ finish: return ret; } - -void pa__done(pa_core *c, pa_module*m) { - assert(c && m); -} - - diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 26638d9dc..8b46637e1 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -28,14 +28,23 @@ #include #include #include -#include #include #include #include #include #include +#include +#include +#include +#include +#include + +#ifdef HAVE_LINUX_SOCKIOS_H +#include +#endif #include +#include #include #include @@ -47,27 +56,37 @@ #include #include #include +#include +#include +#include +#include +#include #include "module-esound-sink-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_DESCRIPTION("ESOUND Sink") PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink_name= server=
        cookie= format= channels= rate=") +PA_MODULE_USAGE( + "sink_name= " + "server=
        cookie= " + "format= " + "channels= " + "rate=") -#define DEFAULT_SINK_NAME "esound_output" +#define DEFAULT_SINK_NAME "esound_out" struct userdata { pa_core *core; - + pa_module *module; pa_sink *sink; - pa_iochannel *io; - pa_socket_client *client; - pa_defer_event *defer_event; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + pa_rtpoll_item *rtpoll_item; + pa_thread *thread; pa_memchunk memchunk; - pa_module *module; void *write_data; size_t write_length, write_index; @@ -75,12 +94,28 @@ struct userdata { void *read_data; size_t read_length, read_index; - enum { STATE_AUTH, STATE_LATENCY, STATE_RUNNING, STATE_DEAD } state; + enum { + STATE_AUTH, + STATE_LATENCY, + STATE_PREPARE, + STATE_RUNNING, + STATE_DEAD + } state; pa_usec_t latency; esd_format_t format; int32_t rate; + + pa_smoother *smoother; + int fd; + + int64_t offset; + + pa_iochannel *io; + pa_socket_client *client; + + size_t block_size; }; static const char* const valid_modargs[] = { @@ -93,42 +128,211 @@ static const char* const valid_modargs[] = { NULL }; -static void cancel(struct userdata *u) { - assert(u); +enum { + SINK_MESSAGE_PASS_SOCKET = PA_SINK_MESSAGE_MAX +}; - u->state = STATE_DEAD; +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; - if (u->io) { - pa_iochannel_free(u->io); - u->io = NULL; + switch (code) { + + case PA_SINK_MESSAGE_SET_STATE: + + switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) { + + case PA_SINK_SUSPENDED: + pa_assert(PA_SINK_OPENED(u->sink->thread_info.state)); + + pa_smoother_pause(u->smoother, pa_rtclock_usec()); + break; + + case PA_SINK_IDLE: + case PA_SINK_RUNNING: + + if (u->sink->thread_info.state == PA_SINK_SUSPENDED) + pa_smoother_resume(u->smoother, pa_rtclock_usec()); + + break; + + case PA_SINK_UNLINKED: + case PA_SINK_INIT: + ; + } + + break; + + 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; + break; + } + + case SINK_MESSAGE_PASS_SOCKET: { + struct pollfd *pollfd; + + pa_assert(!u->rtpoll_item); + + u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->fd = u->fd; + pollfd->events = pollfd->revents = 0; + + return 0; + } } - if (u->defer_event) { - u->core->mainloop->defer_free(u->defer_event); - u->defer_event = NULL; + return pa_sink_process_msg(o, code, data, offset, chunk); +} + +static void thread_func(void *userdata) { + struct userdata *u = userdata; + int write_type = 0; + + pa_assert(u); + + pa_log_debug("Thread starting up"); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec()); + + for (;;) { + int ret; + + if (u->rtpoll_item) { + struct pollfd *pollfd; + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + + /* Render some data and write it to the fifo */ + if (PA_SINK_OPENED(u->sink->thread_info.state) && pollfd->revents) { + pa_usec_t usec; + int64_t n; + + for (;;) { + ssize_t l; + void *p; + + if (u->memchunk.length <= 0) + pa_sink_render(u->sink, u->block_size, &u->memchunk); + + pa_assert(u->memchunk.length > 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) { + + /* OK, we filled all socket buffers up + * now. */ + goto filled_up; + + } else { + pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno)); + goto fail; + } + + } else { + u->offset += l; + + 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; + + if (u->memchunk.length > 0) + + /* OK, we wrote less that we asked for, + * hence we can assume that the socket + * buffers are full now */ + goto filled_up; + } + } + + filled_up: + + /* At this spot we know that the socket buffers are + * fully filled up. This is the best time to estimate + * the playback position of the server */ + + n = u->offset; + +#ifdef SIOCOUTQ + { + int l; + if (ioctl(u->fd, SIOCOUTQ, &l) >= 0 && l > 0) + n -= l; + } +#endif + + usec = pa_bytes_to_usec(n, &u->sink->sample_spec); + + if (usec > u->latency) + usec -= u->latency; + else + usec = 0; + + pa_smoother_put(u->smoother, pa_rtclock_usec(), usec); + } + + /* Hmm, nothing to do. Let's sleep */ + pollfd->events = PA_SINK_OPENED(u->sink->thread_info.state) ? POLLOUT : 0; + } + + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) + goto fail; + + if (ret == 0) + goto finish; + + if (u->rtpoll_item) { + struct pollfd* pollfd; + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + + if (pollfd->revents & ~POLLOUT) { + pa_log("FIFO shutdown."); + goto fail; + } + } } - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - u->sink = NULL; - } +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); - if (u->module) { - pa_module_unload_request(u->module); - u->module = NULL; - } +finish: + pa_log_debug("Thread shutting down"); } static int do_write(struct userdata *u) { ssize_t r; - assert(u); + pa_assert(u); if (!pa_iochannel_is_writable(u->io)) return 0; if (u->write_data) { - assert(u->write_index < u->write_length); + pa_assert(u->write_index < u->write_length); if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) <= 0) { pa_log("write() failed: %s", pa_cstrerror(errno)); @@ -136,45 +340,44 @@ static int do_write(struct userdata *u) { } u->write_index += r; - assert(u->write_index <= u->write_length); + pa_assert(u->write_index <= u->write_length); if (u->write_index == u->write_length) { - free(u->write_data); + pa_xfree(u->write_data); u->write_data = NULL; u->write_index = u->write_length = 0; } - } else if (u->state == STATE_RUNNING) { - pa_module_set_used(u->module, pa_sink_used_by(u->sink)); + } - if (!u->memchunk.length) - if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0) - return 0; + if (!u->write_data && u->state == STATE_PREPARE) { + /* OK, we're done with sending all control data we need to, so + * let's hand the socket over to the IO thread now */ - assert(u->memchunk.memblock && u->memchunk.length); + pa_assert(u->fd < 0); + u->fd = pa_iochannel_get_send_fd(u->io); - if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { - pa_log("write() failed: %s", pa_cstrerror(errno)); - return -1; - } + pa_iochannel_set_noclose(u->io, TRUE); + pa_iochannel_free(u->io); + u->io = NULL; - u->memchunk.index += r; - u->memchunk.length -= r; + pa_make_tcp_socket_low_delay(u->fd); - if (u->memchunk.length <= 0) { - pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; - } + pa_log_info("Connection authenticated, handing fd to IO thread..."); + + pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL); + u->state = STATE_RUNNING; } return 0; } static int handle_response(struct userdata *u) { - assert(u); + pa_assert(u); switch (u->state) { + case STATE_AUTH: - assert(u->read_length == sizeof(int32_t)); + pa_assert(u->read_length == sizeof(int32_t)); /* Process auth data */ if (!*(int32_t*) u->read_data) { @@ -183,14 +386,14 @@ static int handle_response(struct userdata *u) { } /* Request latency data */ - assert(!u->write_data); + pa_assert(!u->write_data); *(int32_t*) (u->write_data = pa_xmalloc(u->write_length = sizeof(int32_t))) = ESD_PROTO_LATENCY; u->write_index = 0; u->state = STATE_LATENCY; /* Space for next response */ - assert(u->read_length >= sizeof(int32_t)); + pa_assert(u->read_length >= sizeof(int32_t)); u->read_index = 0; u->read_length = sizeof(int32_t); @@ -198,17 +401,17 @@ static int handle_response(struct userdata *u) { case STATE_LATENCY: { int32_t *p; - assert(u->read_length == sizeof(int32_t)); + pa_assert(u->read_length == sizeof(int32_t)); /* Process latency info */ u->latency = (pa_usec_t) ((double) (*(int32_t*) u->read_data) * 1000000 / 44100); if (u->latency > 10000000) { - pa_log("WARNING! Invalid latency information received from server"); + pa_log_warn("Invalid latency information received from server"); u->latency = 0; } /* Create stream */ - assert(!u->write_data); + pa_assert(!u->write_data); p = u->write_data = pa_xmalloc0(u->write_length = sizeof(int32_t)*3+ESD_NAME_MAX); *(p++) = ESD_PROTO_STREAM_PLAY; *(p++) = u->format; @@ -216,7 +419,7 @@ static int handle_response(struct userdata *u) { pa_strlcpy((char*) p, "PulseAudio Tunnel", ESD_NAME_MAX); u->write_index = 0; - u->state = STATE_RUNNING; + u->state = STATE_PREPARE; /* Don't read any further */ pa_xfree(u->read_data); @@ -227,14 +430,14 @@ static int handle_response(struct userdata *u) { } default: - abort(); + pa_assert_not_reached(); } return 0; } static int do_read(struct userdata *u) { - assert(u); + pa_assert(u); if (!pa_iochannel_is_readable(u->io)) return 0; @@ -245,16 +448,15 @@ static int do_read(struct userdata *u) { if (!u->read_data) return 0; - assert(u->read_index < u->read_length); + pa_assert(u->read_index < u->read_length); if ((r = pa_iochannel_read(u->io, (uint8_t*) u->read_data + u->read_index, u->read_length - u->read_index)) <= 0) { pa_log("read() failed: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); - cancel(u); return -1; } u->read_index += r; - assert(u->read_index <= u->read_length); + pa_assert(u->read_index <= u->read_length); if (u->read_index == u->read_length) return handle_response(u); @@ -263,42 +465,19 @@ static int do_read(struct userdata *u) { return 0; } -static void do_work(struct userdata *u) { - assert(u); - - u->core->mainloop->defer_enable(u->defer_event, 0); - - if (do_read(u) < 0 || do_write(u) < 0) - cancel(u); -} - -static void notify_cb(pa_sink*s) { - struct userdata *u = s->userdata; - assert(s && u); - - if (pa_iochannel_is_writable(u->io)) - u->core->mainloop->defer_enable(u->defer_event, 1); -} - -static pa_usec_t get_latency_cb(pa_sink *s) { - struct userdata *u = s->userdata; - assert(s && u); - - return - u->latency + - (u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0); -} - -static void defer_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event*e, void *userdata) { - struct userdata *u = userdata; - assert(u); - do_work(u); -} - static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { struct userdata *u = userdata; - assert(u); - do_work(u); + pa_assert(u); + + if (do_read(u) < 0 || do_write(u) < 0) { + + if (u->io) { + pa_iochannel_free(u->io); + u->io = NULL; + } + + pa_module_unload_request(u->module); + } } static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, void *userdata) { @@ -308,30 +487,34 @@ static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, vo u->client = NULL; if (!io) { - pa_log("connection failed: %s", pa_cstrerror(errno)); - cancel(u); + pa_log("Connection failed: %s", pa_cstrerror(errno)); + pa_module_unload_request(u->module); return; } + pa_assert(!u->io); u->io = io; pa_iochannel_set_callback(u->io, io_callback, u); + + pa_log_info("Connection established, authenticating ..."); } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { struct userdata *u = NULL; const char *p; pa_sample_spec ss; pa_modargs *ma = NULL; char *t; + const char *espeaker; - assert(c && m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments"); goto fail; } - ss = c->default_sample_spec; + ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { pa_log("invalid sample format specification"); goto fail; @@ -343,37 +526,62 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - u = pa_xmalloc0(sizeof(struct userdata)); - u->core = c; + u = pa_xnew0(struct userdata, 1); + u->core = m->core; u->module = m; m->userdata = u; + u->fd = -1; + u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE); + pa_memchunk_reset(&u->memchunk); + u->offset = 0; + + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); + u->rtpoll_item = NULL; + u->format = (ss.format == PA_SAMPLE_U8 ? ESD_BITS8 : ESD_BITS16) | (ss.channels == 2 ? ESD_STEREO : ESD_MONO); u->rate = ss.rate; - u->sink = NULL; - u->client = NULL; - u->io = NULL; + u->block_size = pa_usec_to_bytes(PA_USEC_PER_SEC/20, &ss); + u->read_data = u->write_data = NULL; u->read_index = u->write_index = u->read_length = u->write_length = 0; + u->state = STATE_AUTH; u->latency = 0; - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { + if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { pa_log("failed to create sink."); goto fail; } - if (!(u->client = pa_socket_client_new_string(u->core->mainloop, p = pa_modargs_get_value(ma, "server", ESD_UNIX_SOCKET_NAME), ESD_DEFAULT_PORT))) { - pa_log("failed to connect to server."); + u->sink->parent.process_msg = sink_process_msg; + u->sink->userdata = u; + u->sink->flags = PA_SINK_LATENCY; + + pa_sink_set_module(u->sink, m); + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); + + if (!(espeaker = getenv("ESPEAKER"))) + espeaker = ESD_UNIX_SOCKET_NAME; + + if (!(u->client = pa_socket_client_new_string(u->core->mainloop, p = pa_modargs_get_value(ma, "server", espeaker), ESD_DEFAULT_PORT))) { + pa_log("Failed to connect to server."); goto fail; } + + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Esound sink '%s'", p)); + pa_xfree(t); + pa_socket_client_set_callback(u->client, on_connection, u); /* Prepare the initial request */ u->write_data = pa_xmalloc(u->write_length = ESD_KEY_LEN + sizeof(int32_t)); if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", ".esd_auth"), u->write_data, ESD_KEY_LEN) < 0) { - pa_log("failed to load cookie"); + pa_log("Failed to load cookie"); goto fail; } *(int32_t*) ((uint8_t*) u->write_data + ESD_KEY_LEN) = ESD_ENDIAN_KEY; @@ -381,19 +589,12 @@ int pa__init(pa_core *c, pa_module*m) { /* Reserve space for the response */ u->read_data = pa_xmalloc(u->read_length = sizeof(int32_t)); - u->sink->notify = notify_cb; - u->sink->get_latency = get_latency_cb; - u->sink->userdata = u; - pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Esound sink '%s'", p)); - pa_xfree(t); - - u->memchunk.memblock = NULL; - u->memchunk.length = 0; - - u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u); - c->mainloop->defer_enable(u->defer_event, 0); + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } + pa_sink_put(u->sink); pa_modargs_free(ma); @@ -403,20 +604,39 @@ fail: if (ma) pa_modargs_free(ma); - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c && m); + pa_assert(m); if (!(u = m->userdata)) return; - u->module = NULL; - cancel(u); + if (u->sink) + pa_sink_unlink(u->sink); + + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } + + pa_thread_mq_done(&u->thread_mq); + + if (u->sink) + pa_sink_unref(u->sink); + + if (u->io) + pa_iochannel_free(u->io); + + 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); @@ -427,8 +647,11 @@ void pa__done(pa_core *c, pa_module*m) { pa_xfree(u->read_data); pa_xfree(u->write_data); + if (u->smoother) + pa_smoother_free(u->smoother); + + if (u->fd >= 0) + pa_close(u->fd); + pa_xfree(u); } - - - diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 1f48a452e..a8ca7df36 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -1,25 +1,25 @@ /* $Id$ */ /*** - This file is part of PulseAudio. + This file is part of PulseAudio. - Copyright 2006 Lennart Poettering - Copyright 2006 Shams E. King + Copyright 2006 Lennart Poettering + Copyright 2006 Shams E. King - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. ***/ #ifdef HAVE_CONFIG_H @@ -27,7 +27,6 @@ #endif #include -#include #include #include #include @@ -45,6 +44,9 @@ #include #include #include +#include +#include +#include #include @@ -54,40 +56,27 @@ PA_MODULE_AUTHOR("Shahms King") PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") PA_MODULE_VERSION(PACKAGE_VERSION) - -typedef enum { -#ifdef HAVE_ALSA - CAP_ALSA, +#if defined(HAVE_ALSA) && defined(HAVE_OSS) +PA_MODULE_USAGE("api=") +#elif defined(HAVE_ALSA) +PA_MODULE_USAGE("api=") +#elif defined(HAVE_OSS) +PA_MODULE_USAGE("api=") #endif -#ifdef HAVE_OSS - CAP_OSS, -#endif - CAP_MAX -} capability_t; - -static const char* const capabilities[CAP_MAX] = { -#ifdef HAVE_ALSA - [CAP_ALSA] = "alsa", -#endif -#ifdef HAVE_OSS - [CAP_OSS] = "oss", -#endif -}; struct device { uint32_t index; char *udi; + char *sink_name, *source_name; + int acl_race_fix; }; struct userdata { pa_core *core; - LibHalContext *ctx; - capability_t capability; - pa_dbus_connection *conn; + LibHalContext *context; + pa_dbus_connection *connection; pa_hashmap *devices; -#if defined(HAVE_ALSA) && defined(HAVE_OSS) - int use_oss; -#endif + const char *capability; }; struct timerdata { @@ -95,23 +84,30 @@ struct timerdata { char *udi; }; -static const char* get_capability_name(capability_t cap) { - if (cap >= CAP_MAX) - return NULL; - return capabilities[cap]; -} +#define CAPABILITY_ALSA "alsa" +#define CAPABILITY_OSS "oss" + +static const char* const valid_modargs[] = { + "api", + NULL +}; static void hal_device_free(struct device* d) { + pa_assert(d); + pa_xfree(d->udi); + pa_xfree(d->sink_name); + pa_xfree(d->source_name); pa_xfree(d); } static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { - hal_device_free((struct device*) d); + hal_device_free(d); } static const char *strip_udi(const char *udi) { const char *slash; + if ((slash = strrchr(udi, '/'))) return slash+1; @@ -119,6 +115,7 @@ static const char *strip_udi(const char *udi) { } #ifdef HAVE_ALSA + typedef enum { ALSA_TYPE_SINK, ALSA_TYPE_SOURCE, @@ -126,234 +123,297 @@ typedef enum { ALSA_TYPE_MAX } alsa_type_t; -static alsa_type_t hal_device_get_alsa_type(LibHalContext *ctx, const char *udi, - DBusError *error) -{ +static alsa_type_t hal_alsa_device_get_type(LibHalContext *context, const char *udi, DBusError *error) { char *type; alsa_type_t t; - type = libhal_device_get_property_string(ctx, udi, "alsa.type", error); - if (!type || dbus_error_is_set(error)) - return FALSE; + if (!(type = libhal_device_get_property_string(context, udi, "alsa.type", error))) + return ALSA_TYPE_OTHER; - if (!strcmp(type, "playback")) { + if (!strcmp(type, "playback")) t = ALSA_TYPE_SINK; - } else if (!strcmp(type, "capture")) { + else if (!strcmp(type, "capture")) t = ALSA_TYPE_SOURCE; - } else { + else t = ALSA_TYPE_OTHER; - } + libhal_free_string(type); return t; } -static int hal_device_get_alsa_card(LibHalContext *ctx, const char *udi, - DBusError *error) -{ - return libhal_device_get_property_int(ctx, udi, "alsa.card", error); +static int hal_alsa_device_is_modem(LibHalContext *context, const char *udi, DBusError *error) { + char *class; + int r; + + if (!(class = libhal_device_get_property_string(context, udi, "alsa.pcm_class", error))) + return 0; + + r = strcmp(class, "modem") == 0; + pa_xfree(class); + + return r; } -static int hal_device_get_alsa_device(LibHalContext *ctx, const char *udi, - DBusError *error) -{ - return libhal_device_get_property_int(ctx, udi, "alsa.device", error); -} - -static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, - DBusError *error) -{ - char args[128]; +static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, char **sink_name, char **source_name) { + char *args; alsa_type_t type; int device, card; const char *module_name; + DBusError error; + pa_module *m; - type = hal_device_get_alsa_type(u->ctx, udi, error); - if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER) - return NULL; + dbus_error_init(&error); - device = hal_device_get_alsa_device(u->ctx, udi, error); - if (dbus_error_is_set(error) || device != 0) - return NULL; + pa_assert(u); + pa_assert(sink_name); + pa_assert(source_name); - card = hal_device_get_alsa_card(u->ctx, udi, error); - if (dbus_error_is_set(error)) - return NULL; + *sink_name = *source_name = NULL; + + type = hal_alsa_device_get_type(u->context, udi, &error); + if (dbus_error_is_set(&error) || type == ALSA_TYPE_OTHER) + goto fail; + + device = libhal_device_get_property_int(u->context, udi, "alsa.device", &error); + if (dbus_error_is_set(&error) || device != 0) + goto fail; + + card = libhal_device_get_property_int(u->context, udi, "alsa.card", &error); + if (dbus_error_is_set(&error)) + goto fail; + + if (hal_alsa_device_is_modem(u->context, udi, &error)) + goto fail; if (type == ALSA_TYPE_SINK) { + *sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi)); + module_name = "module-alsa-sink"; - snprintf(args, sizeof(args), "device=hw:%u sink_name=alsa_output.%s", card, strip_udi(udi)); + args = pa_sprintf_malloc("device=hw:%u sink_name=%s", card, *sink_name); } else { + *source_name = pa_sprintf_malloc("alsa_input.%s", strip_udi(udi)); + module_name = "module-alsa-source"; - snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi)); + args = pa_sprintf_malloc("device=hw:%u source_name=%s", card, *source_name); } pa_log_debug("Loading %s with arguments '%s'", module_name, args); - return pa_module_load(u->core, module_name, args); + m = pa_module_load(u->core, module_name, args); + + pa_xfree(args); + + if (!m) { + pa_xfree(*sink_name); + pa_xfree(*source_name); + *sink_name = *source_name = NULL; + } + + return m; + +fail: + if (dbus_error_is_set(&error)) { + pa_log_error("D-Bus error while parsing ALSA data: %s: %s", error.name, error.message); + dbus_error_free(&error); + } + + return NULL; } #endif #ifdef HAVE_OSS -static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi, - DBusError *error) -{ - dbus_bool_t rv = FALSE; - char* type, *device_file = NULL; + +static int hal_oss_device_is_pcm(LibHalContext *context, const char *udi, DBusError *error) { + char *class = NULL, *dev = NULL, *e; int device; + int r = 0; - type = libhal_device_get_property_string(ctx, udi, "oss.type", error); - if (!type || dbus_error_is_set(error)) - return FALSE; + class = libhal_device_get_property_string(context, udi, "oss.type", error); + if (dbus_error_is_set(error) || !class) + goto finish; - if (!strcmp(type, "pcm")) { - char *e; + if (strcmp(class, "pcm")) + goto finish; - device = libhal_device_get_property_int(ctx, udi, "oss.device", error); - if (dbus_error_is_set(error) || device != 0) - goto exit; + dev = libhal_device_get_property_string(context, udi, "oss.device_file", error); + if (dbus_error_is_set(error) || !dev) + goto finish; - device_file = libhal_device_get_property_string(ctx, udi, "oss.device_file", - error); - if (!device_file || dbus_error_is_set(error)) - goto exit; + if ((e = strrchr(dev, '/'))) + if (pa_startswith(e + 1, "audio")) + goto finish; - /* hack to ignore /dev/audio style devices */ - if ((e = strrchr(device_file, '/'))) - rv = !pa_startswith(e + 1, "audio"); - } + device = libhal_device_get_property_int(context, udi, "oss.device", error); + if (dbus_error_is_set(error) || device != 0) + goto finish; -exit: - libhal_free_string(type); - libhal_free_string(device_file); - return rv; + r = 1; + +finish: + + libhal_free_string(class); + libhal_free_string(dev); + + return r; } -static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, - DBusError *error) -{ - char args[256]; +static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, char **sink_name, char **source_name) { + char* args; char* device; + DBusError error; + pa_module *m; - if (!hal_device_is_oss_pcm(u->ctx, udi, error) || dbus_error_is_set(error)) - return NULL; + dbus_error_init(&error); - device = libhal_device_get_property_string(u->ctx, udi, "oss.device_file", - error); - if (!device || dbus_error_is_set(error)) - return NULL; + pa_assert(u); + pa_assert(sink_name); + pa_assert(source_name); - snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi)); + *sink_name = *source_name = NULL; + + if (!hal_oss_device_is_pcm(u->context, udi, &error) || dbus_error_is_set(&error)) + goto fail; + + device = libhal_device_get_property_string(u->context, udi, "oss.device_file", &error); + if (!device || dbus_error_is_set(&error)) + goto fail; + + *sink_name = pa_sprintf_malloc("oss_output.%s", strip_udi(udi)); + *source_name = pa_sprintf_malloc("oss_input.%s", strip_udi(udi)); + + args = pa_sprintf_malloc("device=%s sink_name=%s source_name=%s", device, *sink_name, *source_name); libhal_free_string(device); pa_log_debug("Loading module-oss with arguments '%s'", args); + m = pa_module_load(u->core, "module-oss", args); + pa_xfree(args); - return pa_module_load(u->core, "module-oss", args); -} -#endif - -static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, - DBusError *error) -{ - pa_module* m = NULL; - struct device *d; - - switch(u->capability) { -#ifdef HAVE_ALSA - case CAP_ALSA: - m = hal_device_load_alsa(u, udi, error); - break; -#endif -#ifdef HAVE_OSS - case CAP_OSS: -#ifdef HAVE_ALSA - if (u->use_oss) -#endif - m = hal_device_load_oss(u, udi, error); - break; -#endif - default: - assert(FALSE); /* never reached */ - break; + if (!m) { + pa_xfree(*sink_name); + pa_xfree(*source_name); + *sink_name = *source_name = NULL; } - if (!m || dbus_error_is_set(error)) - return FALSE; + return m; + +fail: + if (dbus_error_is_set(&error)) { + pa_log_error("D-Bus error while parsing OSS data: %s: %s", error.name, error.message); + dbus_error_free(&error); + } + + return NULL; +} +#endif + +static struct device* hal_device_add(struct userdata *u, const char *udi) { + pa_module* m = NULL; + struct device *d; + char *sink_name = NULL, *source_name = NULL; + + pa_assert(u); + pa_assert(u->capability); + pa_assert(!pa_hashmap_get(u->devices, udi)); + +#ifdef HAVE_ALSA + if (strcmp(u->capability, CAPABILITY_ALSA) == 0) + m = hal_device_load_alsa(u, udi, &sink_name, &source_name); +#endif +#ifdef HAVE_OSS + if (strcmp(u->capability, CAPABILITY_OSS) == 0) + m = hal_device_load_oss(u, udi, &sink_name, &source_name); +#endif + + if (!m) + return NULL; d = pa_xnew(struct device, 1); + d->acl_race_fix = 0; d->udi = pa_xstrdup(udi); d->index = m->index; - + d->sink_name = sink_name; + d->source_name = source_name; pa_hashmap_put(u->devices, d->udi, d); - return TRUE; + return d; } -static int hal_device_add_all(struct userdata *u, capability_t capability) -{ +static int hal_device_add_all(struct userdata *u, const char *capability) { DBusError error; - int i,n,count; - dbus_bool_t r; + int i, n, count = 0; char** udis; - const char* cap = get_capability_name(capability); - assert(capability < CAP_MAX); + pa_assert(u); - pa_log_info("Trying capability %u (%s)", capability, cap); dbus_error_init(&error); - udis = libhal_find_device_by_capability(u->ctx, cap, &n, &error); + + if (u->capability && strcmp(u->capability, capability) != 0) + return 0; + + pa_log_info("Trying capability %s", capability); + + udis = libhal_find_device_by_capability(u->context, capability, &n, &error); if (dbus_error_is_set(&error)) { - pa_log_error("Error finding devices: %s: %s", error.name, - error.message); + pa_log_error("Error finding devices: %s: %s", error.name, error.message); dbus_error_free(&error); return -1; } - count = 0; - u->capability = capability; - for (i = 0; i < n; ++i) { - r = hal_device_add(u, udis[i], &error); - if (dbus_error_is_set(&error)) { - pa_log_error("Error adding device: %s: %s", error.name, - error.message); - dbus_error_free(&error); - count = -1; - break; + + if (n > 0) { + u->capability = capability; + + for (i = 0; i < n; i++) { + struct device *d; + + if (!(d = hal_device_add(u, udis[i]))) + pa_log_debug("Not loaded device %s", udis[i]); + else { + if (d->sink_name) + pa_scache_play_item_by_name(u->core, "pulse-coldplug", d->sink_name, PA_VOLUME_NORM, 0); + count++; + } } - if (r) - ++count; } libhal_free_string_array(udis); return count; } -static dbus_bool_t device_has_capability(LibHalContext *ctx, const char *udi, - const char* cap, DBusError *error) -{ +static dbus_bool_t device_has_capability(LibHalContext *context, const char *udi, const char* cap, DBusError *error){ dbus_bool_t has_prop; - has_prop = libhal_device_property_exists(ctx, udi, "info.capabilities", - error); + + has_prop = libhal_device_property_exists(context, udi, "info.capabilities", error); if (!has_prop || dbus_error_is_set(error)) return FALSE; - return libhal_device_query_capability(ctx, udi, cap, error); + return libhal_device_query_capability(context, udi, cap, error); } -static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, - const struct timeval *tv, void *userdata) -{ +static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const struct timeval *tv, void *userdata) { DBusError error; - struct timerdata *td = (struct timerdata*) userdata; + struct timerdata *td = userdata; dbus_error_init(&error); - if (libhal_device_exists(td->u->ctx, td->udi, &error)) - hal_device_add(td->u, td->udi, &error); - if (dbus_error_is_set(&error)) { - pa_log_error("Error adding device: %s: %s", error.name, - error.message); - dbus_error_free(&error); + if (!pa_hashmap_get(td->u->devices, td->udi)) { + int b; + struct device *d; + + b = libhal_device_exists(td->u->context, td->udi, &error); + + if (dbus_error_is_set(&error)) { + pa_log_error("Error adding device: %s: %s", error.name, error.message); + dbus_error_free(&error); + } else if (b) { + if (!(d = hal_device_add(td->u, td->udi))) + pa_log_debug("Not loaded device %s", td->udi); + else { + if (d->sink_name) + pa_scache_play_item_by_name(td->u->core, "pulse-hotplug", d->sink_name, PA_VOLUME_NORM, 0); + } + } } pa_xfree(td->udi); @@ -361,28 +421,68 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, ea->time_free(ev); } -static void device_added_cb(LibHalContext *ctx, const char *udi) -{ +static void device_added_cb(LibHalContext *context, const char *udi) { DBusError error; struct timeval tv; - dbus_bool_t has_cap; struct timerdata *t; - struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); - const char* cap = get_capability_name(u->capability); + struct userdata *u; + int good = 0; + + pa_assert_se(u = libhal_ctx_get_user_data(context)); + + if (pa_hashmap_get(u->devices, udi)) + return; pa_log_debug("HAL Device added: %s", udi); dbus_error_init(&error); - has_cap = device_has_capability(ctx, udi, cap, &error); - if (dbus_error_is_set(&error)) { - pa_log_error("Error getting capability: %s: %s", error.name, - error.message); - dbus_error_free(&error); - return; + + if (u->capability) { + + good = device_has_capability(context, udi, u->capability, &error); + + if (dbus_error_is_set(&error)) { + pa_log_error("Error getting capability: %s: %s", error.name, error.message); + dbus_error_free(&error); + return; + } + + } else { + +#ifdef HAVE_ALSA + good = device_has_capability(context, udi, CAPABILITY_ALSA, &error); + + if (dbus_error_is_set(&error)) { + pa_log_error("Error getting capability: %s: %s", error.name, error.message); + dbus_error_free(&error); + return; + } + + if (good) + u->capability = CAPABILITY_ALSA; +#endif +#if defined(HAVE_OSS) && defined(HAVE_ALSA) + if (!good) { +#endif +#ifdef HAS_OSS + good = device_has_capability(context, udi, CAPABILITY_OSS, &error); + + if (dbus_error_is_set(&error)) { + pa_log_error("Error getting capability: %s: %s", error.name, error.message); + dbus_error_free(&error); + return; + } + + if (good) + u->capability = CAPABILITY_OSS; + +#endif +#if defined(HAVE_OSS) && defined(HAVE_ALSA) + } +#endif } - /* skip it */ - if (!has_cap) + if (!good) return; /* actually add the device 1/2 second later */ @@ -392,187 +492,359 @@ static void device_added_cb(LibHalContext *ctx, const char *udi) pa_gettimeofday(&tv); pa_timeval_add(&tv, 500000); - u->core->mainloop->time_new(u->core->mainloop, &tv, - device_added_time_cb, t); + u->core->mainloop->time_new(u->core->mainloop, &tv, device_added_time_cb, t); } -static void device_removed_cb(LibHalContext* ctx, const char *udi) -{ +static void device_removed_cb(LibHalContext* context, const char *udi) { struct device *d; - struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); + struct userdata *u; + + pa_assert_se(u = libhal_ctx_get_user_data(context)); pa_log_debug("Device removed: %s", udi); + if ((d = pa_hashmap_remove(u->devices, udi))) { pa_module_unload_by_index(u->core, d->index); hal_device_free(d); } } -static void new_capability_cb(LibHalContext *ctx, const char *udi, - const char* capability) -{ - struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); - const char* capname = get_capability_name(u->capability); +static void new_capability_cb(LibHalContext *context, const char *udi, const char* capability) { + struct userdata *u; - if (capname && !strcmp(capname, capability)) { + pa_assert_se(u = libhal_ctx_get_user_data(context)); + + if (!u->capability || strcmp(u->capability, capability) == 0) /* capability we care about, pretend it's a new device */ - device_added_cb(ctx, udi); - } + device_added_cb(context, udi); } -static void lost_capability_cb(LibHalContext *ctx, const char *udi, - const char* capability) -{ - struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); - const char* capname = get_capability_name(u->capability); +static void lost_capability_cb(LibHalContext *context, const char *udi, const char* capability) { + struct userdata *u; - if (capname && !strcmp(capname, capability)) { + pa_assert_se(u = libhal_ctx_get_user_data(context)); + + if (u->capability && strcmp(u->capability, capability) == 0) /* capability we care about, pretend it was removed */ - device_removed_cb(ctx, udi); + device_removed_cb(context, udi); +} + +static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) { + struct userdata*u = userdata; + DBusError error; + + pa_assert(bus); + pa_assert(message); + pa_assert(u); + + dbus_error_init(&error); + + pa_log_debug("dbus: interface=%s, path=%s, member=%s\n", + dbus_message_get_interface(message), + dbus_message_get_path(message), + dbus_message_get_member(message)); + + if (dbus_message_is_signal(message, "org.freedesktop.Hal.Device.AccessControl", "ACLAdded") || + dbus_message_is_signal(message, "org.freedesktop.Hal.Device.AccessControl", "ACLRemoved")) { + uint32_t uid; + int suspend = strcmp(dbus_message_get_member(message), "ACLRemoved") == 0; + + if (!dbus_message_get_args(message, &error, DBUS_TYPE_UINT32, &uid, DBUS_TYPE_INVALID) || dbus_error_is_set(&error)) { + pa_log_error("Failed to parse ACL message: %s: %s", error.name, error.message); + goto finish; + } + + if (uid == getuid() || uid == geteuid()) { + struct device *d; + const char *udi; + + udi = dbus_message_get_path(message); + + if ((d = pa_hashmap_get(u->devices, udi))) { + int send_acl_race_fix_message = 0; + + d->acl_race_fix = 0; + + if (d->sink_name) { + pa_sink *sink; + + if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0))) { + int prev_suspended = pa_sink_get_state(sink) == PA_SINK_SUSPENDED; + + if (prev_suspended && !suspend) { + /* resume */ + if (pa_sink_suspend(sink, 0) >= 0) + pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0); + else + d->acl_race_fix = 1; + + } else if (!prev_suspended && suspend) { + /* suspend */ + if (pa_sink_suspend(sink, 1) >= 0) + send_acl_race_fix_message = 1; + } + } + } + + if (d->source_name) { + pa_source *source; + + if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE, 0))) { + int prev_suspended = pa_source_get_state(source) == PA_SOURCE_SUSPENDED; + + if (prev_suspended && !suspend) { + /* resume */ + if (pa_source_suspend(source, 0) < 0) + d->acl_race_fix = 1; + + } else if (!prev_suspended && suspend) { + /* suspend */ + if (pa_source_suspend(source, 0) >= 0) + send_acl_race_fix_message = 1; + } + } + } + + if (send_acl_race_fix_message) { + DBusMessage *msg; + msg = dbus_message_new_signal(udi, "org.pulseaudio.Server", "DirtyGiveUpMessage"); + dbus_connection_send(pa_dbus_connection_get(u->connection), msg, NULL); + dbus_message_unref(msg); + } + + } else if (!suspend) + device_added_cb(u->context, udi); + } + + } else if (dbus_message_is_signal(message, "org.pulseaudio.Server", "DirtyGiveUpMessage")) { + /* We use this message to avoid a dirty race condition when we + get an ACLAdded message before the previously owning PA + sever has closed the device. We can remove this as + soon as HAL learns frevoke() */ + + const char *udi; + struct device *d; + + udi = dbus_message_get_path(message); + + if ((d = pa_hashmap_get(u->devices, udi)) && d->acl_race_fix) { + pa_log_debug("Got dirty give up message for '%s', trying resume ...", udi); + + d->acl_race_fix = 0; + + if (d->sink_name) { + pa_sink *sink; + + if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0))) { + + int prev_suspended = pa_sink_get_state(sink) == PA_SINK_SUSPENDED; + + if (prev_suspended) { + /* resume */ + if (pa_sink_suspend(sink, 0) >= 0) + pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0); + } + } + } + + if (d->source_name) { + pa_source *source; + + if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE, 0))) { + + int prev_suspended = pa_source_get_state(source) == PA_SOURCE_SUSPENDED; + + if (prev_suspended) + pa_source_suspend(source, 0); + } + } + + } else + /* Yes, we don't check the UDI for validity, but hopefully HAL will */ + device_added_cb(u->context, udi); } + +finish: + dbus_error_free(&error); + + return DBUS_HANDLER_RESULT_HANDLED; } -#if 0 -static void property_modified_cb(LibHalContext *ctx, const char *udi, - const char* key, - dbus_bool_t is_removed, - dbus_bool_t is_added) -{ -} -#endif - -static void pa_hal_context_free(LibHalContext* hal_ctx) -{ +static void hal_context_free(LibHalContext* hal_context) { DBusError error; dbus_error_init(&error); - libhal_ctx_shutdown(hal_ctx, &error); - libhal_ctx_free(hal_ctx); - if (dbus_error_is_set(&error)) { - dbus_error_free(&error); - } + libhal_ctx_shutdown(hal_context, &error); + libhal_ctx_free(hal_context); + + dbus_error_free(&error); } -static void userdata_free(struct userdata *u) { - pa_hal_context_free(u->ctx); - /* free the devices with the hashmap */ - pa_hashmap_free(u->devices, hal_device_free_cb, NULL); - pa_dbus_connection_unref(u->conn); - pa_xfree(u); -} - -static LibHalContext* pa_hal_context_new(pa_core* c, DBusConnection *conn) -{ +static LibHalContext* hal_context_new(pa_core* c, DBusConnection *conn) { DBusError error; - LibHalContext *hal_ctx = NULL; + LibHalContext *hal_context = NULL; dbus_error_init(&error); - if (!(hal_ctx = libhal_ctx_new())) { + + if (!(hal_context = libhal_ctx_new())) { pa_log_error("libhal_ctx_new() failed"); goto fail; } - if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) { - pa_log_error("Error establishing DBUS connection: %s: %s", - error.name, error.message); + if (!libhal_ctx_set_dbus_connection(hal_context, conn)) { + pa_log_error("Error establishing DBUS connection: %s: %s", error.name, error.message); goto fail; } - if (!libhal_ctx_init(hal_ctx, &error)) { - pa_log_error("Couldn't connect to hald: %s: %s", - error.name, error.message); + if (!libhal_ctx_init(hal_context, &error)) { + pa_log_error("Couldn't connect to hald: %s: %s", error.name, error.message); goto fail; } - return hal_ctx; + return hal_context; fail: - if (hal_ctx) - pa_hal_context_free(hal_ctx); + if (hal_context) + hal_context_free(hal_context); - if (dbus_error_is_set(&error)) - dbus_error_free(&error); + dbus_error_free(&error); return NULL; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { DBusError error; pa_dbus_connection *conn; struct userdata *u = NULL; - LibHalContext *hal_ctx = NULL; + LibHalContext *hal_context = NULL; int n = 0; + pa_modargs *ma; + const char *api; - assert(c); - assert(m); + pa_assert(m); dbus_error_init(&error); - if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error))) { - pa_log_error("Unable to contact DBUS system bus: %s: %s", - error.name, error.message); - dbus_error_free(&error); - return -1; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments"); + goto fail; } - if (!(hal_ctx = pa_hal_context_new(c, pa_dbus_connection_get(conn)))) { + if ((api = pa_modargs_get_value(ma, "api", NULL))) { + int good = 0; + +#ifdef HAVE_ALSA + if (strcmp(api, CAPABILITY_ALSA) == 0) { + good = 1; + api = CAPABILITY_ALSA; + } +#endif +#ifdef HAVE_OSS + if (strcmp(api, CAPABILITY_OSS) == 0) { + good = 1; + api = CAPABILITY_OSS; + } +#endif + + if (!good) { + pa_log_error("Invalid API specification."); + goto fail; + } + } + + if (!(conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &error)) || dbus_error_is_set(&error)) { + if (conn) + pa_dbus_connection_unref(conn); + pa_log_error("Unable to contact DBUS system bus: %s: %s", error.name, error.message); + goto fail; + } + + if (!(hal_context = hal_context_new(m->core, pa_dbus_connection_get(conn)))) { /* pa_hal_context_new() logs appropriate errors */ - return -1; + pa_dbus_connection_unref(conn); + goto fail; } u = pa_xnew(struct userdata, 1); - u->core = c; - u->ctx = hal_ctx; - u->conn = conn; - u->devices = pa_hashmap_new(pa_idxset_string_hash_func, - pa_idxset_string_compare_func); - m->userdata = (void*) u; + u->core = m->core; + u->context = hal_context; + u->connection = conn; + u->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + u->capability = api; + m->userdata = u; #ifdef HAVE_ALSA - n = hal_device_add_all(u, CAP_ALSA); + n = hal_device_add_all(u, CAPABILITY_ALSA); #endif #if defined(HAVE_ALSA) && defined(HAVE_OSS) - u->use_oss = 0; - - if (n <= 0) { + if (n <= 0) #endif #ifdef HAVE_OSS - n += hal_device_add_all(u, CAP_OSS); -#endif -#if defined(HAVE_ALSA) && defined(HAVE_OSS) - - /* We found something with OSS, but didn't find anything with - * ALSA. Then let's use only OSS from now on. */ - if (n > 0) - u->use_oss = 1; - } + n += hal_device_add_all(u, CAPABILITY_OSS); #endif - libhal_ctx_set_user_data(hal_ctx, u); - libhal_ctx_set_device_added(hal_ctx, device_added_cb); - libhal_ctx_set_device_removed(hal_ctx, device_removed_cb); - libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); - libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability_cb); - /*libhal_ctx_set_device_property_modified(hal_ctx, property_modified_cb);*/ + libhal_ctx_set_user_data(hal_context, u); + libhal_ctx_set_device_added(hal_context, device_added_cb); + libhal_ctx_set_device_removed(hal_context, device_removed_cb); + libhal_ctx_set_device_new_capability(hal_context, new_capability_cb); + libhal_ctx_set_device_lost_capability(hal_context, lost_capability_cb); - dbus_error_init(&error); - if (!libhal_device_property_watch_all(hal_ctx, &error)) { - pa_log_error("error monitoring device list: %s: %s", - error.name, error.message); - dbus_error_free(&error); - userdata_free(u); - return -1; + if (!libhal_device_property_watch_all(hal_context, &error)) { + pa_log_error("Error monitoring device list: %s: %s", error.name, error.message); + goto fail; } - pa_log_info("loaded %i modules.", n); + if (!dbus_connection_add_filter(pa_dbus_connection_get(conn), filter_cb, u, NULL)) { + pa_log_error("Failed to add filter function"); + goto fail; + } + + dbus_bus_add_match(pa_dbus_connection_get(conn), "type='signal',sender='org.freedesktop.Hal', interface='org.freedesktop.Hal.Device.AccessControl'", &error); + if (dbus_error_is_set(&error)) { + pa_log_error("Unable to subscribe to HAL ACL signals: %s: %s", error.name, error.message); + goto fail; + } + + dbus_bus_add_match(pa_dbus_connection_get(conn), "type='signal',interface='org.pulseaudio.Server'", &error); + if (dbus_error_is_set(&error)) { + pa_log_error("Unable to subscribe to PulseAudio signals: %s: %s", error.name, error.message); + goto fail; + } + + pa_log_info("Loaded %i modules.", n); + + pa_modargs_free(ma); return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + dbus_error_free(&error); + pa__done(m); + + return -1; } -void pa__done(PA_GCC_UNUSED pa_core *c, pa_module *m) { - assert (c && m); +void pa__done(pa_module *m) { + struct userdata *u; - /* free the user data */ - userdata_free(m->userdata); + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->context) + hal_context_free(u->context); + + if (u->devices) + pa_hashmap_free(u->devices, hal_device_free_cb, NULL); + + if (u->connection) + pa_dbus_connection_unref(u->connection); + + pa_xfree(u); } diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index a40ebe290..5019d6564 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -3,7 +3,7 @@ /*** This file is part of PulseAudio. - Copyright 2006, 2007 Lennart Poettering and Tanu Kaskinen + Copyright 2006 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -25,858 +25,431 @@ #include #endif -#include +#include +#include +#include #include #include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include #include +#include #include #include -#include -#include #include -#include -#include #include -#include +#include +#include +#include +#include +#include #include "module-jack-sink-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering & Tanu Kaskinen") -PA_MODULE_DESCRIPTION("Jack Sink") +/* General overview: + * + * Because JACK has a very unflexible event loop management, which + * doesn't allow us to add our own event sources to the event thread + * we cannot use the JACK real-time thread for dispatching our PA + * work. Instead, we run an additional RT thread which does most of + * the PA handling, and have the JACK RT thread request data from it + * via pa_asyncmsgq. The cost is an additional context switch which + * should hopefully not be that expensive if RT scheduling is + * enabled. A better fix would only be possible with additional event + * source support in JACK. + */ + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("JACK Sink") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE( "sink_name= " "server_name= " "client_name= " "channels= " - "connect= " - "buffersize= " + "connect= " "channel_map=") #define DEFAULT_SINK_NAME "jack_out" -#define DEFAULT_CLIENT_NAME "PulseAudio(output)" -#define DEFAULT_RINGBUFFER_SIZE 4096 - struct userdata { + pa_core *core; + pa_module *module; pa_sink *sink; unsigned channels; - unsigned frame_size; - jack_port_t* j_ports[PA_CHANNELS_MAX]; - jack_client_t *j_client; + jack_port_t* port[PA_CHANNELS_MAX]; + jack_client_t *client; - jack_nframes_t j_buffersize; + void *buffer[PA_CHANNELS_MAX]; - /* For avoiding j_buffersize changes at a wrong moment. */ - pthread_mutex_t buffersize_mutex; + pa_thread_mq thread_mq; + pa_asyncmsgq *jack_msgq; + pa_rtpoll *rtpoll; + pa_rtpoll_item *rtpoll_item; - /* The intermediate store where the pulse side writes to and the jack side - reads from. */ - jack_ringbuffer_t* ringbuffer; - - /* For signaling when there's room in the ringbuffer. */ - pthread_mutex_t cond_mutex; - pthread_cond_t ringbuffer_cond; + pa_thread *thread; - pthread_t filler_thread; /* Keeps the ringbuffer filled. */ - - int ringbuffer_is_full; - int filler_thread_is_running; - int quit_requested; - - int pipe_fd_type; - int pipe_fds[2]; - pa_io_event *io_event; + jack_nframes_t frames_in_buffer; + jack_nframes_t saved_frame_time; + pa_bool_t saved_frame_time_valid; }; - -struct options { - char* sink_name; - int sink_name_given; - - char* server_name; /* May be NULL */ - int server_name_given; - - char* client_name; - int client_name_given; - - unsigned channels; - int channels_given; - - int connect; - int connect_given; - - unsigned buffersize; - int buffersize_given; - - pa_channel_map map; - int map_given; -}; - - static const char* const valid_modargs[] = { "sink_name", "server_name", "client_name", "channels", "connect", - "buffersize", "channel_map", NULL }; +enum { + SINK_MESSAGE_RENDER = PA_SINK_MESSAGE_MAX, + SINK_MESSAGE_ON_SHUTDOWN +}; -/* Initialization functions. */ -static int parse_options(struct options* o, const char* argument); -static void set_default_channels(pa_module* self, struct options* o); -static int create_sink(pa_module* self, struct options *o); -static void connect_ports(pa_module* self); -static int start_filling_ringbuffer(pa_module* self); +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *memchunk) { + struct userdata *u = PA_SINK(o)->userdata; -/* Various callbacks. */ -static void jack_error_func(const char* t); -static pa_usec_t sink_get_latency_cb(pa_sink* s); -static int jack_process(jack_nframes_t nframes, void* arg); -static int jack_blocksize_cb(jack_nframes_t nframes, void* arg); -static void jack_shutdown(void* arg); -static void io_event_cb(pa_mainloop_api* m, pa_io_event* e, int fd, - pa_io_event_flags_t flags, void* userdata); + switch (code) { -/* The ringbuffer filler thread runs in this function. */ -static void* fill_ringbuffer(void* arg); + case SINK_MESSAGE_RENDER: -/* request_render asks asynchronously the mainloop to call io_event_cb. */ -static void request_render(struct userdata* u); + /* Handle the request from the JACK thread */ + if (u->sink->thread_info.state == PA_SINK_RUNNING) { + pa_memchunk chunk; + size_t nbytes; + void *p; -int pa__init(pa_core* c, pa_module* self) { - struct userdata* u = NULL; - struct options o; + pa_assert(offset > 0); + nbytes = offset * pa_frame_size(&u->sink->sample_spec); + + pa_sink_render_full(u->sink, nbytes, &chunk); + + p = (uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index; + pa_deinterleave(p, u->buffer, u->channels, sizeof(float), offset); + pa_memblock_release(chunk.memblock); + + pa_memblock_unref(chunk.memblock); + } else { + unsigned c; + pa_sample_spec ss; + + /* Humm, we're not RUNNING, hence let's write some silence */ + + ss = u->sink->sample_spec; + ss.channels = 1; + + for (c = 0; c < u->channels; c++) + pa_silence_memory(u->buffer[c], offset * pa_sample_size(&ss), &ss); + } + + u->frames_in_buffer = offset; + u->saved_frame_time = * (jack_nframes_t*) data; + u->saved_frame_time_valid = TRUE; + + return 0; + + case SINK_MESSAGE_ON_SHUTDOWN: + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); + return 0; + + case PA_SINK_MESSAGE_GET_LATENCY: { + jack_nframes_t l, ft, d; + size_t n; + + /* This is the "worst-case" latency */ + l = jack_port_get_total_latency(u->client, u->port[0]) + u->frames_in_buffer; + + if (u->saved_frame_time_valid) { + /* Adjust the worst case latency by the time that + * passed since we last handed data to JACK */ + + ft = jack_frame_time(u->client); + d = ft > u->saved_frame_time ? ft - u->saved_frame_time : 0; + l = l > d ? l - d : 0; + } + + /* Convert it to usec */ + n = l * pa_frame_size(&u->sink->sample_spec); + *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec); + + return 0; + } + } + + return pa_sink_process_msg(o, code, data, offset, memchunk); +} + +static int jack_process(jack_nframes_t nframes, void *arg) { + struct userdata *u = arg; + unsigned c; + jack_nframes_t frame_time; + pa_assert(u); + + /* We just forward the request to our other RT thread */ + + for (c = 0; c < u->channels; c++) + pa_assert_se(u->buffer[c] = jack_port_get_buffer(u->port[c], nframes)); + + frame_time = jack_frame_time(u->client); + + pa_assert_se(pa_asyncmsgq_send(u->jack_msgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_RENDER, &frame_time, nframes, NULL) == 0); + return 0; +} + +static void thread_func(void *userdata) { + struct userdata *u = userdata; + + pa_assert(u); + + pa_log_debug("Thread starting up"); + + if (u->core->high_priority) + pa_make_realtime(); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + for (;;) { + int ret; + + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) + goto fail; + + if (ret == 0) + goto finish; + } + +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("Thread shutting down"); +} + +static void jack_error_func(const char*t) { + char *s; + + s = pa_xstrndup(t, strcspn(t, "\n\r")); + pa_log_warn("JACK error >%s<", s); + pa_xfree(s); +} + +static void jack_init(void *arg) { + struct userdata *u = arg; + + pa_log_info("JACK thread starting up."); + + if (u->core->high_priority) + pa_make_realtime(); +} + +static void jack_shutdown(void* arg) { + struct userdata *u = arg; + + pa_log_info("JACK thread shutting down.."); + pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_ON_SHUTDOWN, NULL, 0, NULL, NULL); +} + +int pa__init(pa_module*m) { + struct userdata *u = NULL; + pa_sample_spec ss; + pa_channel_map map; + pa_modargs *ma = NULL; + jack_status_t status; + const char *server_name, *client_name; + uint32_t channels = 0; + int do_connect = 1; unsigned i; - - assert(c); - assert(self); + const char **ports = NULL, **p; + char *t; + + pa_assert(m); - o.sink_name = NULL; - o.server_name = NULL; - o.client_name = NULL; - - self->userdata = pa_xnew0(struct userdata, 1); - u = self->userdata; - - u->pipe_fds[0] = u->pipe_fds[1] = -1; - u->pipe_fd_type = 0; - u->ringbuffer_is_full = 0; - u->filler_thread_is_running = 0; - u->quit_requested = 0; - pthread_mutex_init(&u->buffersize_mutex, NULL); - pthread_mutex_init(&u->cond_mutex, NULL); - pthread_cond_init(&u->ringbuffer_cond, NULL); - - if (parse_options(&o, self->argument) != 0) - goto fail; - jack_set_error_function(jack_error_func); - - if (!(u->j_client = jack_client_open( - o.client_name, - o.server_name ? JackServerName : JackNullOption, - NULL, o.server_name))) { - pa_log_error("jack_client_open() failed."); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments."); goto fail; } - pa_log_info("Successfully connected as '%s'", - jack_get_client_name(u->j_client)); - - if (!o.channels_given) - set_default_channels(self, &o); - - u->channels = o.channels; - - if (!o.map_given) - pa_channel_map_init_auto(&o.map, u->channels, PA_CHANNEL_MAP_ALSA); - - for (i = 0; i < u->channels; i++) { - char* port_name = pa_sprintf_malloc( - "out_%i:%s", i+1, - pa_channel_position_to_string(o.map.map[i])); - - if (!(u->j_ports[i] = jack_port_register( - u->j_client, port_name, - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput|JackPortIsTerminal, 0))) { + + if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { + pa_log("Failed to parse connect= argument."); + goto fail; + } + + server_name = pa_modargs_get_value(ma, "server_name", NULL); + client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio JACK Sink"); + + u = pa_xnew0(struct userdata, 1); + u->core = m->core; + u->module = m; + m->userdata = u; + u->saved_frame_time_valid = FALSE; + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); + + /* The queue linking the JACK thread and our RT thread */ + u->jack_msgq = pa_asyncmsgq_new(0); + + /* The msgq from the JACK RT thread should have an even higher + * priority than the normal message queues, to match the guarantee + * all other drivers make: supplying the audio device with data is + * the top priority -- and as long as that is possible we don't do + * anything else */ + u->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY-1, u->jack_msgq); + + if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { + pa_log("jack_client_open() failed."); + goto fail; + } + + ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); + + channels = 0; + for (p = ports; *p; p++) + channels++; + + if (!channels) + channels = m->core->default_sample_spec.channels; + + if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { + pa_log("Failed to parse channels= argument."); + goto fail; + } + + pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA); + if (pa_modargs_get_channel_map(ma, NULL, &map) < 0 || map.channels != channels) { + pa_log("Failed to parse channel_map= argument."); + goto fail; + } + + pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client)); + + ss.channels = u->channels = channels; + ss.rate = jack_get_sample_rate(u->client); + ss.format = PA_SAMPLE_FLOAT32NE; + + pa_assert(pa_sample_spec_valid(&ss)); + + for (i = 0; i < ss.channels; i++) { + if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(map.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0))) { pa_log("jack_port_register() failed."); goto fail; } - - pa_xfree(port_name); } - - if (pipe(u->pipe_fds) < 0) { - pa_log("pipe() failed: %s", pa_cstrerror(errno)); - goto fail; - } - pa_make_nonblock_fd(u->pipe_fds[1]); - - if (create_sink(self, &o) != 0) - goto fail; - u->frame_size = pa_frame_size(&u->sink->sample_spec); - u->j_buffersize = jack_get_buffer_size(u->j_client); - - /* If the ringbuffer size were equal to the jack buffer size, a full block - would never fit in the ringbuffer, because the ringbuffer can never be - totally full: one slot is always wasted. */ - if (o.buffersize <= u->j_buffersize) { - o.buffersize = u->j_buffersize + 1; - } - /* The actual ringbuffer size will be rounded up to the nearest power of - two. */ - if (!(u->ringbuffer = jack_ringbuffer_create( - o.buffersize * u->frame_size))) { - pa_log("jack_ringbuffer_create() failed."); - goto fail; - } - assert((u->ringbuffer->size % sizeof(float)) == 0); - pa_log_info("buffersize is %u frames (%u samples, %u bytes).", - u->ringbuffer->size / u->frame_size, - u->ringbuffer->size / sizeof(float), - u->ringbuffer->size); - - jack_set_process_callback(u->j_client, jack_process, u); - jack_set_buffer_size_callback(u->j_client, jack_blocksize_cb, u); - jack_on_shutdown(u->j_client, jack_shutdown, u); - - if (jack_activate(u->j_client)) { - pa_log("jack_activate() failed."); + if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { + pa_log("failed to create sink."); goto fail; } - if (o.connect) - connect_ports(self); + u->sink->parent.process_msg = sink_process_msg; + u->sink->userdata = u; + u->sink->flags = PA_SINK_LATENCY; - u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], - PA_IO_EVENT_INPUT, io_event_cb, self); - - if (start_filling_ringbuffer(self) != 0) - goto fail; + pa_sink_set_module(u->sink, m); + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Jack sink (%s)", jack_get_client_name(u->client))); + pa_xfree(t); - pa_xfree(o.sink_name); - pa_xfree(o.server_name); - pa_xfree(o.client_name); - - return 0; + jack_set_process_callback(u->client, jack_process, u); + jack_on_shutdown(u->client, jack_shutdown, u); + jack_set_thread_init_callback(u->client, jack_init, u); -fail: - pa_xfree(o.sink_name); - pa_xfree(o.server_name); - pa_xfree(o.client_name); - pa__done(c, self); - - return -1; -} - - -static int parse_options(struct options* o, const char* argument) { - pa_modargs *ma = NULL; - const char* arg_val; - pa_strbuf* strbuf; - - assert(o); - - if (!(ma = pa_modargs_new(argument, valid_modargs))) { - pa_log_error("Failed to parse module arguments."); + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); goto fail; } - strbuf = pa_strbuf_new(); - if ((arg_val = pa_modargs_get_value(ma, "sink_name", NULL))) { - pa_strbuf_puts(strbuf, arg_val); - o->sink_name = pa_strbuf_tostring(strbuf); - o->sink_name_given = 1; - } else { - pa_strbuf_puts(strbuf, DEFAULT_SINK_NAME); - o->sink_name = pa_strbuf_tostring(strbuf); - o->sink_name_given = 0; + if (jack_activate(u->client)) { + pa_log("jack_activate() failed"); + goto fail; } - pa_strbuf_free(strbuf); - strbuf = pa_strbuf_new(); - if ((arg_val = pa_modargs_get_value(ma, "server_name", NULL))) { - pa_strbuf_puts(strbuf, arg_val); - o->server_name = pa_strbuf_tostring(strbuf); - o->server_name_given = 1; - } else { - o->server_name = NULL; - o->server_name_given = 0; - } - pa_strbuf_free(strbuf); + if (do_connect) { + for (i = 0, p = ports; i < ss.channels; i++, p++) { - strbuf = pa_strbuf_new(); - if ((arg_val = pa_modargs_get_value(ma, "client_name", NULL))) { - pa_strbuf_puts(strbuf, arg_val); - o->client_name = pa_strbuf_tostring(strbuf); - o->client_name_given = 1; - } else { - pa_strbuf_puts(strbuf, DEFAULT_CLIENT_NAME); - o->client_name = pa_strbuf_tostring(strbuf); - o->client_name_given = 1; - } - pa_strbuf_free(strbuf); + if (!*p) { + pa_log("Not enough physical output ports, leaving unconnected."); + break; + } - if (pa_modargs_get_value(ma, "channels", NULL)) { - o->channels_given = 1; - if (pa_modargs_get_value_u32(ma, "channels", &o->channels) < 0 || - o->channels == 0 || - o->channels >= PA_CHANNELS_MAX) { - pa_log_error("Failed to parse the \"channels\" argument."); - goto fail; + pa_log_info("Connecting %s to %s", jack_port_name(u->port[i]), *p); + + if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) { + pa_log("Failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); + break; + } } - } else { - o->channels = 0; /* The actual default value is the number of physical - input ports in jack (unknown at the moment), or if - that's zero, then the default_sample_spec.channels - of the core. */ - o->channels_given = 0; } - if (pa_modargs_get_value(ma, "connect", NULL)) { - o->connect_given = 1; - if (pa_modargs_get_value_boolean(ma, "connect", &o->connect) < 0) { - pa_log_error("Failed to parse the \"connect\" argument."); - goto fail; - } - } else { - o->connect = 1; - o->connect_given = 0; - } - - if (pa_modargs_get_value(ma, "buffersize", NULL)) { - o->buffersize_given = 1; - if (pa_modargs_get_value_u32(ma, "buffersize", &o->buffersize) < 0) { - pa_log_error("Failed to parse the \"buffersize\" argument."); - goto fail; - } - } else { - o->buffersize = DEFAULT_RINGBUFFER_SIZE; - o->buffersize_given = 0; - } - - if (pa_modargs_get_value(ma, "channel_map", NULL)) { - o->map_given = 1; - if (pa_modargs_get_channel_map(ma, &o->map) < 0) { - pa_log_error("Failed to parse the \"channel_map\" argument."); - goto fail; - } - - /* channel_map specifies the channel count too. */ - if (o->channels_given && (o->channels != o->map.channels)) { - pa_log_error( - "\"channels\" and \"channel_map\" arguments conficted. If you " - "use the \"channel_map\" argument, you can omit the " - "\"channels\" argument."); - goto fail; - } else { - o->channels = o->map.channels; - o->channels_given = 1; - } - } else { - /* The actual default value is the default alsa mappings, but that - can't be set until the channel count is known. Here we initialize - the map to some valid value, although the value won't be used. */ - pa_channel_map_init_stereo(&o->map); - o->map_given = 0; - } + pa_sink_put(u->sink); + free(ports); pa_modargs_free(ma); return 0; fail: if (ma) - pa_modargs_free(ma); + pa_modargs_free(ma); + + free(ports); + + pa__done(m); return -1; } +void pa__done(pa_module*m) { + struct userdata *u; -static void set_default_channels(pa_module* self, struct options* o) { - struct userdata* u; - const char **ports, **p; - - assert(self); - assert(o); - assert(self->userdata); + pa_assert(m); - u = self->userdata; - - assert(u->j_client); - assert(self->core); - - o->channels = 0; - - ports = jack_get_ports(u->j_client, NULL, JACK_DEFAULT_AUDIO_TYPE, - JackPortIsPhysical|JackPortIsInput); - - for (p = ports; *p; p++) - o->channels++; - - free(ports); - - if (o->channels >= PA_CHANNELS_MAX) - o->channels = PA_CHANNELS_MAX - 1; - - if (o->channels == 0) - o->channels = self->core->default_sample_spec.channels; -} - - -static int create_sink(pa_module* self, struct options* o) { - struct userdata* u; - pa_sample_spec ss; - char *t; - - assert(self); - assert(o); - assert(self->userdata); - - u = self->userdata; - - assert(u->j_client); - - ss.channels = u->channels; - ss.rate = jack_get_sample_rate(u->j_client); - ss.format = PA_SAMPLE_FLOAT32NE; - assert(pa_sample_spec_valid(&ss)); - - if (!(u->sink = pa_sink_new(self->core, __FILE__, o->sink_name, 0, &ss, - &o->map))) { - pa_log("failed to create sink."); - return -1; - } - - u->sink->userdata = u; - pa_sink_set_owner(u->sink, self); - - pa_sink_set_description( - u->sink, - t = pa_sprintf_malloc("Jack sink (%s)", - jack_get_client_name(u->j_client))); - pa_xfree(t); - - u->sink->get_latency = sink_get_latency_cb; - - return 0; -} - - -static void connect_ports(pa_module* self) { - struct userdata* u; - unsigned i; - const char **ports, **p; - - assert(self); - assert(self->userdata); - - u = self->userdata; - - assert(u->j_client); - - ports = jack_get_ports(u->j_client, NULL, JACK_DEFAULT_AUDIO_TYPE, - JackPortIsPhysical|JackPortIsInput); - - for (i = 0, p = ports; i < u->channels; i++, p++) { - assert(u->j_ports[i]); - - if (!*p) { - pa_log("Not enough physical output ports, leaving unconnected."); - break; - } - - pa_log_info("connecting %s to %s", - jack_port_name(u->j_ports[i]), *p); - - if (jack_connect(u->j_client, jack_port_name(u->j_ports[i]), *p)) { - pa_log("Failed to connect %s to %s, leaving unconnected.", - jack_port_name(u->j_ports[i]), *p); - break; - } - } - - free(ports); -} - - -static int start_filling_ringbuffer(pa_module* self) { - struct userdata* u; - pthread_attr_t thread_attributes; - - assert(self); - assert(self->userdata); - - u = self->userdata; - - pthread_attr_init(&thread_attributes); - - if (pthread_attr_setinheritsched(&thread_attributes, - PTHREAD_INHERIT_SCHED) != 0) { - pa_log("pthread_attr_setinheritsched() failed."); - goto fail; - } - else if (pthread_create(&u->filler_thread, &thread_attributes, - fill_ringbuffer, u) != 0) { - pa_log("pthread_create() failed."); - goto fail; - } - - u->filler_thread_is_running = 1; - - pthread_attr_destroy(&thread_attributes); - - return 0; - -fail: - pthread_attr_destroy(&thread_attributes); - return -1; -} - - -static void jack_error_func(const char* t) { - pa_log_warn("JACK error >%s<", t); -} - - -static pa_usec_t sink_get_latency_cb(pa_sink* s) { - /* The latency is approximately the sum of the first port's latency, - buffersize of jack and the ringbuffer size. Maybe instead of using just - the first port, the max of all ports' latencies should be used? */ - struct userdata* u; - jack_nframes_t l; - - assert(s); - assert(s->userdata); - - u = s->userdata; - - l = jack_port_get_total_latency(u->j_client, u->j_ports[0]) + - u->j_buffersize + u->ringbuffer->size / u->frame_size; - - return pa_bytes_to_usec(l * u->frame_size, &s->sample_spec); -} - - -static int jack_process(jack_nframes_t nframes, void* arg) { - struct userdata* u = arg; - float* j_buffers[PA_CHANNELS_MAX]; - unsigned nsamples = u->channels * nframes; - unsigned sample_idx_part1, sample_idx_part2; - jack_nframes_t frame_idx; - jack_ringbuffer_data_t data[2]; /* In case the readable area in the - ringbuffer is non-continuous, the data - will be split in two parts. */ - unsigned chan; - unsigned samples_left_over; - - for (chan = 0; chan < u->channels; chan++) { - j_buffers[chan] = jack_port_get_buffer(u->j_ports[chan], nframes); - } - - jack_ringbuffer_get_read_vector(u->ringbuffer, data); - - /* We assume that the possible discontinuity doesn't happen in the middle - * of a sample. Should be a safe assumption. */ - assert(((data[0].len % sizeof(float)) == 0) || - (data[1].len == 0)); - - /* Copy from the first part of data until enough samples are copied or the - first part ends. */ - sample_idx_part1 = 0; - chan = 0; - frame_idx = 0; - while (sample_idx_part1 < nsamples && - ((sample_idx_part1 + 1) * sizeof(float)) <= data[0].len) { - float *s = ((float*) data[0].buf) + sample_idx_part1; - float *d = j_buffers[chan] + frame_idx; - *d = *s; - - sample_idx_part1++; - chan = (chan + 1) % u->channels; - frame_idx = sample_idx_part1 / u->channels; - } - - samples_left_over = nsamples - sample_idx_part1; - - /* Copy from the second part of data until enough samples are copied or the - second part ends. */ - sample_idx_part2 = 0; - while (sample_idx_part2 < samples_left_over && - ((sample_idx_part2 + 1) * sizeof(float)) <= data[1].len) { - float *s = ((float*) data[1].buf) + sample_idx_part2; - float *d = j_buffers[chan] + frame_idx; - *d = *s; - - sample_idx_part2++; - chan = (chan + 1) % u->channels; - frame_idx = (sample_idx_part1 + sample_idx_part2) / u->channels; - } - - samples_left_over -= sample_idx_part2; - - /* If there's still samples left, fill the buffers with zeros. */ - while (samples_left_over > 0) { - float *d = j_buffers[chan] + frame_idx; - *d = 0.0; - - samples_left_over--; - chan = (chan + 1) % u->channels; - frame_idx = (nsamples - samples_left_over) / u->channels; - } - - jack_ringbuffer_read_advance( - u->ringbuffer, (sample_idx_part1 + sample_idx_part2) * sizeof(float)); - - /* Tell the rendering part that there is room in the ringbuffer. */ - u->ringbuffer_is_full = 0; - pthread_cond_signal(&u->ringbuffer_cond); - - return 0; -} - - -static int jack_blocksize_cb(jack_nframes_t nframes, void* arg) { - /* This gets called in the processing thread, so do we have to be realtime - safe? No, we can do whatever we want. User gets silence while we do it. - - In addition to just updating the j_buffersize field in userdata, we have - to create a new ringbuffer, if the new buffer size is bigger or equal to - the old ringbuffer size. */ - struct userdata* u = arg; - - assert(u); - - /* We don't want to change the blocksize and the ringbuffer while rendering - is going on. */ - pthread_mutex_lock(&u->buffersize_mutex); - - u->j_buffersize = nframes; - - if ((u->ringbuffer->size / u->frame_size) <= nframes) { - /* We have to create a new ringbuffer. What are we going to do with the - old data in the old buffer? We throw it away, because we're lazy - coders. The listening experience is likely to get ruined anyway - during the blocksize change. */ - jack_ringbuffer_free(u->ringbuffer); - - /* The actual ringbuffer size will be rounded up to the nearest power - of two. */ - if (!(u->ringbuffer = - jack_ringbuffer_create((nframes + 1) * u->frame_size))) { - pa_log_error( - "jack_ringbuffer_create() failed while changing jack's buffer " - "size, module exiting."); - jack_client_close(u->j_client); - u->quit_requested = 1; - } - assert((u->ringbuffer->size % sizeof(float)) == 0); - pa_log_info("buffersize is %u frames (%u samples, %u bytes).", - u->ringbuffer->size / u->frame_size, - u->ringbuffer->size / sizeof(float), - u->ringbuffer->size); - } - - pthread_mutex_unlock(&u->buffersize_mutex); - - return 0; -} - - -static void jack_shutdown(void* arg) { - struct userdata* u = arg; - assert(u); - - u->quit_requested = 1; - request_render(u); -} - - -static void io_event_cb(pa_mainloop_api* m, pa_io_event* e, int fd, - pa_io_event_flags_t flags, void* userdata) { - pa_module* self = userdata; - struct userdata* u; - char x; - jack_ringbuffer_data_t buffer[2]; /* The write area in the ringbuffer may - be split in two parts. */ - pa_memchunk chunk; /* This is the data source. */ - unsigned part1_length, part2_length; - unsigned sample_idx_part1, sample_idx_part2; - unsigned chan; - unsigned frame_size; - int rem; - - assert(m); - assert(e); - assert(flags == PA_IO_EVENT_INPUT); - assert(self); - assert(self->userdata); - - u = self->userdata; - - assert(u->pipe_fds[0] == fd); - - pa_read(fd, &x, 1, &u->pipe_fd_type); - - if (u->quit_requested) { - pa_module_unload_request(self); - return; - } - - frame_size = u->frame_size; - - /* No blocksize changes during rendering, please. */ - pthread_mutex_lock(&u->buffersize_mutex); - - jack_ringbuffer_get_write_vector(u->ringbuffer, buffer); - assert(((buffer[0].len % sizeof(float)) == 0) || (buffer[1].len == 0)); - - part1_length = buffer[0].len / sizeof(float); - part2_length = buffer[1].len / sizeof(float); - - /* If the amount of free space is not a multiple of the frame size, we have - to truncate the lengths so that we process only complete frames. */ - if ((rem = (part1_length + part2_length) % u->channels) != 0) { - if (part2_length >= rem) { - part2_length -= rem; - } else { - part1_length -= rem - part2_length; - part2_length = 0; - } - } - - /* pa_sink_render_full doesn't accept zero length, so we have do the - copying only if there's data to copy, which actually makes a kind of - sense. */ - if (part1_length > 0 || part2_length > 0) { - pa_sink_render_full(u->sink, - (part1_length + part2_length) * sizeof(float), - &chunk); - - /* Write to the first part of the buffer. */ - for (sample_idx_part1 = 0; - sample_idx_part1 < part1_length; - sample_idx_part1++) { - float *s = - ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + - sample_idx_part1; - float *d = ((float*) buffer[0].buf) + sample_idx_part1; - *d = *s; - } - - /* Write to the second part of the buffer. */ - for (sample_idx_part2 = 0; - sample_idx_part2 < part2_length; - sample_idx_part2++) { - float *s = - ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + - sample_idx_part1 + sample_idx_part2; - float *d = ((float*) buffer[1].buf) + sample_idx_part2; - *d = *s; - } - - pa_memblock_unref(chunk.memblock); - - jack_ringbuffer_write_advance( - u->ringbuffer, (part1_length + part2_length) * sizeof(float)); - } - - /* Blocksize can be changed again. */ - pthread_mutex_unlock(&u->buffersize_mutex); -} - - -static void* fill_ringbuffer(void* arg) { - struct userdata* u = arg; - - assert(u); - - while (!u->quit_requested) { - if (u->ringbuffer_is_full) { - pthread_mutex_lock(&u->cond_mutex); - pthread_cond_wait(&u->ringbuffer_cond, - &u->cond_mutex); - pthread_mutex_unlock(&u->cond_mutex); - } - /* No, it's not full yet, but this must be set to one as soon as - possible, because if the jack thread manages to process another - block before we set this to one, we may end up waiting without - a reason. */ - u->ringbuffer_is_full = 1; - - request_render(u); - } - - return NULL; -} - - -static void request_render(struct userdata* u) { - char c = 'x'; - - assert(u); - - assert(u->pipe_fds[1] >= 0); - pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type); -} - -void pa__done(pa_core* c, pa_module* self) { - struct userdata* u; - - assert(c); - assert(self); - - if (!self->userdata) + if (!(u = m->userdata)) return; - u = self->userdata; - - if (u->filler_thread_is_running) { - u->quit_requested = 1; - pthread_cond_signal(&u->ringbuffer_cond); - pthread_join(u->filler_thread, NULL); + if (u->client) + jack_client_close(u->client); + + if (u->sink) + pa_sink_unlink(u->sink); + + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); } - - if (u->j_client) - jack_client_close(u->j_client); - if (u->io_event) - c->mainloop->io_free(u->io_event); + pa_thread_mq_done(&u->thread_mq); - if (u->sink) { - pa_sink_disconnect(u->sink); + if (u->sink) pa_sink_unref(u->sink); - } - - if (u->ringbuffer) - jack_ringbuffer_free(u->ringbuffer); - if (u->pipe_fds[0] >= 0) - pa_close(u->pipe_fds[0]); - if (u->pipe_fds[1] >= 0) - pa_close(u->pipe_fds[1]); - - pthread_mutex_destroy(&u->buffersize_mutex); - pthread_cond_destroy(&u->ringbuffer_cond); - pthread_mutex_destroy(&u->cond_mutex); - pa_xfree(self->userdata); - self->userdata = NULL; + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); + + if (u->jack_msgq) + pa_asyncmsgq_unref(u->jack_msgq); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + pa_xfree(u); } diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 8ca24035f..b62ebe7a1 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -28,31 +28,34 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include -#include #include #include #include #include #include -#include +#include +#include +#include +#include #include "module-jack-source-symdef.h" +/* See module-jack-sink for a few comments how this module basically + * works */ + PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Jack Source") +PA_MODULE_DESCRIPTION("JACK Source") PA_MODULE_VERSION(PACKAGE_VERSION) PA_MODULE_USAGE( "source_name= " @@ -67,7 +70,6 @@ PA_MODULE_USAGE( struct userdata { pa_core *core; pa_module *module; - pa_source *source; unsigned channels; @@ -75,19 +77,15 @@ struct userdata { jack_port_t* port[PA_CHANNELS_MAX]; jack_client_t *client; - pthread_mutex_t mutex; - pthread_cond_t cond; + pa_thread_mq thread_mq; + pa_asyncmsgq *jack_msgq; + pa_rtpoll *rtpoll; + pa_rtpoll_item *rtpoll_item; - void * buffer[PA_CHANNELS_MAX]; - jack_nframes_t frames_posted; - int quit_requested; + pa_thread *thread; - int pipe_fds[2]; - int pipe_fd_type; - pa_io_event *io_event; - - jack_nframes_t frames_in_buffer; - jack_nframes_t timestamp; + jack_nframes_t saved_frame_time; + pa_bool_t saved_frame_time_valid; }; static const char* const valid_modargs[] = { @@ -100,141 +98,150 @@ static const char* const valid_modargs[] = { NULL }; -static void stop_source(struct userdata *u) { - assert (u); +enum { + SOURCE_MESSAGE_POST = PA_SOURCE_MESSAGE_MAX, + SOURCE_MESSAGE_ON_SHUTDOWN +}; - jack_client_close(u->client); - u->client = NULL; - u->core->mainloop->io_free(u->io_event); - u->io_event = NULL; - pa_source_disconnect(u->source); - pa_source_unref(u->source); - u->source = NULL; - pa_module_unload_request(u->module); -} +static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SOURCE(o)->userdata; -static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { - struct userdata *u = userdata; - char x; + switch (code) { - assert(m); - assert(flags == PA_IO_EVENT_INPUT); - assert(u); - assert(u->pipe_fds[0] == fd); + case SOURCE_MESSAGE_POST: - pa_read(fd, &x, 1, &u->pipe_fd_type); + /* Handle the new block from the JACK thread */ + pa_assert(chunk); + pa_assert(chunk->length > 0); - if (u->quit_requested) { - stop_source(u); - u->quit_requested = 0; - return; - } + if (u->source->thread_info.state == PA_SOURCE_RUNNING) + pa_source_post(u->source, chunk); - pthread_mutex_lock(&u->mutex); + u->saved_frame_time = offset; + u->saved_frame_time_valid = TRUE; - if (u->frames_posted > 0) { - unsigned fs; - jack_nframes_t frame_idx; - pa_memchunk chunk; + return 0; - fs = pa_frame_size(&u->source->sample_spec); + case SOURCE_MESSAGE_ON_SHUTDOWN: + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); + return 0; - chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length = u->frames_posted * fs); - chunk.index = 0; + case PA_SOURCE_MESSAGE_GET_LATENCY: { + jack_nframes_t l, ft, d; + size_t n; - for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) { - unsigned c; + /* This is the "worst-case" latency */ + l = jack_port_get_total_latency(u->client, u->port[0]); - for (c = 0; c < u->channels; c++) { - float *s = ((float*) u->buffer[c]) + frame_idx; - float *d = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c; + if (u->saved_frame_time_valid) { + /* Adjust the worst case latency by the time that + * passed since we last handed data to JACK */ - *d = *s; + ft = jack_frame_time(u->client); + d = ft > u->saved_frame_time ? ft - u->saved_frame_time : 0; + l += d; } + + /* Convert it to usec */ + n = l * pa_frame_size(&u->source->sample_spec); + *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->source->sample_spec); + + return 0; } - - pa_source_post(u->source, &chunk); - pa_memblock_unref(chunk.memblock); - - u->frames_posted = 0; - - pthread_cond_signal(&u->cond); } - pthread_mutex_unlock(&u->mutex); -} - -static void request_post(struct userdata *u) { - char c = 'x'; - assert(u); - - assert(u->pipe_fds[1] >= 0); - pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type); -} - -static void jack_shutdown(void *arg) { - struct userdata *u = arg; - assert(u); - - u->quit_requested = 1; - request_post(u); + return pa_source_process_msg(o, code, data, offset, chunk); } static int jack_process(jack_nframes_t nframes, void *arg) { + unsigned c; struct userdata *u = arg; - assert(u); + const void *buffer[PA_CHANNELS_MAX]; + void *p; + jack_nframes_t frame_time; + pa_memchunk chunk; - if (jack_transport_query(u->client, NULL) == JackTransportRolling) { - unsigned c; + pa_assert(u); - pthread_mutex_lock(&u->mutex); + for (c = 0; c < u->channels; c++) + pa_assert(buffer[c] = jack_port_get_buffer(u->port[c], nframes)); - u->frames_posted = nframes; + /* We interleave the data and pass it on to the other RT thread */ - for (c = 0; c < u->channels; c++) { - u->buffer[c] = jack_port_get_buffer(u->port[c], nframes); - assert(u->buffer[c]); - } + pa_memchunk_reset(&chunk); + chunk.length = nframes * pa_frame_size(&u->source->sample_spec); + chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length); + p = pa_memblock_acquire(chunk.memblock); + pa_interleave(buffer, u->channels, p, sizeof(float), nframes); + pa_memblock_release(chunk.memblock); - request_post(u); + frame_time = jack_frame_time(u->client); - pthread_cond_wait(&u->cond, &u->mutex); + pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_POST, NULL, frame_time, &chunk, NULL); - u->frames_in_buffer = nframes; - u->timestamp = jack_get_current_transport_frame(u->client); - - pthread_mutex_unlock(&u->mutex); - } + pa_memblock_unref(chunk.memblock); return 0; } -static pa_usec_t source_get_latency_cb(pa_source *s) { - struct userdata *u; - jack_nframes_t n, l, d; +static void thread_func(void *userdata) { + struct userdata *u = userdata; - assert(s); - u = s->userdata; + pa_assert(u); - if (jack_transport_query(u->client, NULL) != JackTransportRolling) - return 0; + pa_log_debug("Thread starting up"); - n = jack_get_current_transport_frame(u->client); + if (u->core->high_priority) + pa_make_realtime(); - if (n < u->timestamp) - return 0; + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); - d = n - u->timestamp; - l = jack_port_get_total_latency(u->client, u->port[0]); + for (;;) { + int ret; - return pa_bytes_to_usec((l + d) * pa_frame_size(&s->sample_spec), &s->sample_spec); + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) + goto fail; + + if (ret == 0) + goto finish; + } + +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("Thread shutting down"); } static void jack_error_func(const char*t) { - pa_log_warn("JACK error >%s<", t); + char *s; + + s = pa_xstrndup(t, strcspn(t, "\n\r")); + pa_log_warn("JACK error >%s<", s); + pa_xfree(s); } -int pa__init(pa_core *c, pa_module*m) { +static void jack_init(void *arg) { + struct userdata *u = arg; + + pa_log_info("JACK thread starting up."); + + if (u->core->high_priority) + pa_make_realtime(); +} + +static void jack_shutdown(void* arg) { + struct userdata *u = arg; + + pa_log_info("JACK thread shutting down.."); + pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_ON_SHUTDOWN, NULL, 0, NULL, NULL); +} + +int pa__init(pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; pa_channel_map map; @@ -247,40 +254,35 @@ int pa__init(pa_core *c, pa_module*m) { const char **ports = NULL, **p; char *t; - assert(c); - assert(m); + pa_assert(m); jack_set_error_function(jack_error_func); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments."); + pa_log("Failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { - pa_log("failed to parse connect= argument."); + pa_log("Failed to parse connect= argument."); goto fail; } server_name = pa_modargs_get_value(ma, "server_name", NULL); - client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio"); + client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio JACK Source"); u = pa_xnew0(struct userdata, 1); - m->userdata = u; - u->core = c; + u->core = m->core; u->module = m; - u->pipe_fds[0] = u->pipe_fds[1] = -1; - u->pipe_fd_type = 0; + m->userdata = u; + u->saved_frame_time_valid = FALSE; - pthread_mutex_init(&u->mutex, NULL); - pthread_cond_init(&u->cond, NULL); + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); - if (pipe(u->pipe_fds) < 0) { - pa_log("pipe() failed: %s", pa_cstrerror(errno)); - goto fail; - } - - pa_make_nonblock_fd(u->pipe_fds[1]); + u->jack_msgq = pa_asyncmsgq_new(0); + u->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY-1, u->jack_msgq); if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { pa_log("jack_client_open() failed."); @@ -294,7 +296,7 @@ int pa__init(pa_core *c, pa_module*m) { channels++; if (!channels) - channels = c->default_sample_spec.channels; + channels = m->core->default_sample_spec.channels; if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) { pa_log("failed to parse channels= argument."); @@ -302,7 +304,7 @@ int pa__init(pa_core *c, pa_module*m) { } pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA); - if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) { + if (pa_modargs_get_channel_map(ma, NULL, &map) < 0 || map.channels != channels) { pa_log("failed to parse channel_map= argument."); goto fail; } @@ -313,7 +315,7 @@ int pa__init(pa_core *c, pa_module*m) { ss.rate = jack_get_sample_rate(u->client); ss.format = PA_SAMPLE_FLOAT32NE; - assert(pa_sample_spec_valid(&ss)); + pa_assert(pa_sample_spec_valid(&ss)); for (i = 0; i < ss.channels; i++) { if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(map.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput|JackPortIsTerminal, 0))) { @@ -322,19 +324,29 @@ int pa__init(pa_core *c, pa_module*m) { } } - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { + if (!(u->source = pa_source_new(m->core, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { pa_log("failed to create source."); goto fail; } + u->source->parent.process_msg = source_process_msg; u->source->userdata = u; - pa_source_set_owner(u->source, m); + u->source->flags = PA_SOURCE_LATENCY; + + pa_source_set_module(u->source, m); + pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); + pa_source_set_rtpoll(u->source, u->rtpoll); pa_source_set_description(u->source, t = pa_sprintf_malloc("Jack source (%s)", jack_get_client_name(u->client))); pa_xfree(t); - u->source->get_latency = source_get_latency_cb; jack_set_process_callback(u->client, jack_process, u); jack_on_shutdown(u->client, jack_shutdown, u); + jack_set_thread_init_callback(u->client, jack_init, u); + + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } if (jack_activate(u->client)) { pa_log("jack_activate() failed"); @@ -359,7 +371,7 @@ int pa__init(pa_core *c, pa_module*m) { } - u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u); + pa_source_put(u->source); free(ports); pa_modargs_free(ma); @@ -372,14 +384,14 @@ fail: free(ports); - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c && m); + pa_assert(m); if (!(u = m->userdata)) return; @@ -387,20 +399,27 @@ void pa__done(pa_core *c, pa_module*m) { if (u->client) jack_client_close(u->client); - if (u->io_event) - c->mainloop->io_free(u->io_event); + if (u->source) + pa_source_unlink(u->source); - if (u->source) { - pa_source_disconnect(u->source); - pa_source_unref(u->source); + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); } - if (u->pipe_fds[0] >= 0) - close(u->pipe_fds[0]); - if (u->pipe_fds[1] >= 0) - close(u->pipe_fds[1]); + pa_thread_mq_done(&u->thread_mq); + + if (u->source) + pa_source_unref(u->source); + + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); + + if (u->jack_msgq) + pa_asyncmsgq_unref(u->jack_msgq); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); - pthread_mutex_destroy(&u->mutex); - pthread_cond_destroy(&u->cond); pa_xfree(u); } diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c new file mode 100644 index 000000000..0265d9713 --- /dev/null +++ b/src/modules/module-ladspa-sink.c @@ -0,0 +1,673 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* TODO: Some plugins cause latency, and some even report it by using a control + out port. We don't currently use the latency information. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-ladspa-sink-symdef.h" +#include "ladspa.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Virtual LADSPA sink") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE( + "sink_name= " + "master= " + "format= " + "channels= " + "rate= " + "channel_map= " + "plugin= " + "label= " + "control=") + +struct userdata { + pa_core *core; + pa_module *module; + + pa_sink *sink, *master; + pa_sink_input *sink_input; + + const LADSPA_Descriptor *descriptor; + unsigned channels; + LADSPA_Handle handle[PA_CHANNELS_MAX]; + LADSPA_Data *input, *output; + size_t block_size; + unsigned long input_port, output_port; + LADSPA_Data *control; + + /* This is a dummy buffer. Every port must be connected, but we don't care + about control out ports. We connect them all to this single buffer. */ + LADSPA_Data control_out; + + pa_memchunk memchunk; +}; + +static const char* const valid_modargs[] = { + "sink_name", + "master", + "format", + "channels", + "rate", + "channel_map", + "plugin", + "label", + "control", + NULL +}; + +/* Called from I/O thread context */ +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + + switch (code) { + + case PA_SINK_MESSAGE_GET_LATENCY: { + pa_usec_t usec = 0; + + if (PA_MSGOBJECT(u->master)->process_msg(PA_MSGOBJECT(u->master), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0) + usec = 0; + + *((pa_usec_t*) data) = usec + pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec); + return 0; + } + } + + return pa_sink_process_msg(o, code, data, offset, chunk); +} + +/* Called from main context */ +static int sink_set_state(pa_sink *s, pa_sink_state_t state) { + struct userdata *u; + + pa_sink_assert_ref(s); + pa_assert_se(u = s->userdata); + + if (PA_SINK_LINKED(state) && u->sink_input && PA_SINK_INPUT_LINKED(pa_sink_input_get_state(u->sink_input))) + pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED); + + return 0; +} + +/* Called from I/O thread context */ +static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK_INPUT(o)->userdata; + + switch (code) { + case PA_SINK_INPUT_MESSAGE_GET_LATENCY: + *((pa_usec_t*) data) = pa_bytes_to_usec(u->memchunk.length, &u->sink_input->sample_spec); + + /* Fall through, the default handler will add in the extra + * latency added by the resampler */ + break; + } + + return pa_sink_input_process_msg(o, code, data, offset, chunk); +} + +/* Called from I/O thread context */ +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + if (!u->memchunk.memblock) { + pa_memchunk tchunk; + float *src, *dst; + size_t fs; + unsigned n, c; + + pa_sink_render(u->sink, length, &tchunk); + + fs = pa_frame_size(&i->sample_spec); + n = tchunk.length / fs; + + pa_assert(n > 0); + + u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, tchunk.length); + u->memchunk.index = 0; + u->memchunk.length = tchunk.length; + + src = (float*) ((uint8_t*) pa_memblock_acquire(tchunk.memblock) + tchunk.index); + dst = (float*) pa_memblock_acquire(u->memchunk.memblock); + + for (c = 0; c < u->channels; c++) { + unsigned j; + float *p, *q; + + p = src + c; + q = u->input; + for (j = 0; j < n; j++, p += u->channels, q++) + *q = CLAMP(*p, -1.0, 1.0); + + u->descriptor->run(u->handle[c], n); + + q = u->output; + p = dst + c; + for (j = 0; j < n; j++, q++, p += u->channels) + *p = CLAMP(*q, -1.0, 1.0); + } + + pa_memblock_release(tchunk.memblock); + pa_memblock_release(u->memchunk.memblock); + + pa_memblock_unref(tchunk.memblock); + } + + pa_assert(u->memchunk.length > 0); + pa_assert(u->memchunk.memblock); + + *chunk = u->memchunk; + pa_memblock_ref(chunk->memblock); + + return 0; +} + +/* Called from I/O thread context */ +static void sink_input_drop_cb(pa_sink_input *i, size_t length) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + pa_assert(length > 0); + + if (u->memchunk.memblock) { + + if (length < u->memchunk.length) { + u->memchunk.index += length; + u->memchunk.length -= length; + return; + } + + pa_memblock_unref(u->memchunk.memblock); + length -= u->memchunk.length; + pa_memchunk_reset(&u->memchunk); + } + + if (length > 0) + pa_sink_skip(u->sink, length); +} + +/* Called from I/O thread context */ +static void sink_input_detach_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_detach_within_thread(u->sink); +} + +/* Called from I/O thread context */ +static void sink_input_attach_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_set_asyncmsgq(u->sink, i->sink->asyncmsgq); + pa_sink_set_rtpoll(u->sink, i->sink->rtpoll); + + pa_sink_attach_within_thread(u->sink); +} + +/* Called from main context */ +static void sink_input_kill_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_input_unlink(u->sink_input); + pa_sink_input_unref(u->sink_input); + u->sink_input = NULL; + + pa_sink_unlink(u->sink); + pa_sink_unref(u->sink); + u->sink = NULL; + + pa_module_unload_request(u->module); +} + +int pa__init(pa_module*m) { + struct userdata *u; + pa_sample_spec ss; + pa_channel_map map; + pa_modargs *ma; + char *t; + pa_sink *master; + pa_sink_input_new_data data; + const char *plugin, *label; + LADSPA_Descriptor_Function descriptor_func; + const char *e, *cdata; + const LADSPA_Descriptor *d; + unsigned long input_port, output_port, p, j, n_control; + unsigned c; + pa_bool_t *use_default = NULL; + char *default_sink_name = NULL; + + pa_assert(m); + + pa_assert(sizeof(LADSPA_Data) == sizeof(float)); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments."); + goto fail; + } + + if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK, 1))) { + pa_log("Master sink not found"); + goto fail; + } + + ss = master->sample_spec; + ss.format = PA_SAMPLE_FLOAT32; + map = master->channel_map; + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { + pa_log("Invalid sample format specification or channel map"); + goto fail; + } + + if (!(plugin = pa_modargs_get_value(ma, "plugin", NULL))) { + pa_log("Missing LADSPA plugin name"); + goto fail; + } + + if (!(label = pa_modargs_get_value(ma, "label", NULL))) { + pa_log("Missing LADSPA plugin label"); + goto fail; + } + + cdata = pa_modargs_get_value(ma, "control", NULL); + + u = pa_xnew0(struct userdata, 1); + u->core = m->core; + u->module = m; + m->userdata = u; + u->master = master; + pa_memchunk_reset(&u->memchunk); + + if (!(e = getenv("LADSPA_PATH"))) + e = LADSPA_PATH; + + /* FIXME: This is not exactly thread safe */ + t = pa_xstrdup(lt_dlgetsearchpath()); + lt_dlsetsearchpath(e); + m->dl = lt_dlopenext(plugin); + lt_dlsetsearchpath(t); + pa_xfree(t); + + if (!m->dl) { + pa_log("Failed to load LADSPA plugin: %s", lt_dlerror()); + goto fail; + } + + if (!(descriptor_func = (LADSPA_Descriptor_Function) lt_dlsym(m->dl, "ladspa_descriptor"))) { + pa_log("LADSPA module lacks ladspa_descriptor() symbol."); + goto fail; + } + + for (j = 0;; j++) { + + if (!(d = descriptor_func(j))) { + pa_log("Failed to find plugin label '%s' in plugin '%s'.", plugin, label); + goto fail; + } + + if (strcmp(d->Label, label) == 0) + break; + } + + u->descriptor = d; + + pa_log_debug("Module: %s", plugin); + pa_log_debug("Label: %s", d->Label); + pa_log_debug("Unique ID: %lu", d->UniqueID); + pa_log_debug("Name: %s", d->Name); + pa_log_debug("Maker: %s", d->Maker); + pa_log_debug("Copyright: %s", d->Copyright); + + input_port = output_port = (unsigned long) -1; + n_control = 0; + + for (p = 0; p < d->PortCount; p++) { + + if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) { + + if (strcmp(d->PortNames[p], "Input") == 0) { + pa_assert(input_port == (unsigned long) -1); + input_port = p; + } else { + pa_log("Found audio input port on plugin we cannot handle: %s", d->PortNames[p]); + goto fail; + } + + } else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) { + + if (strcmp(d->PortNames[p], "Output") == 0) { + pa_assert(output_port == (unsigned long) -1); + output_port = p; + } else { + pa_log("Found audio output port on plugin we cannot handle: %s", d->PortNames[p]); + goto fail; + } + + } else if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p])) + n_control++; + else { + pa_assert(LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p])); + pa_log_info("Ignored port \"%s\", because we ignore all control out ports.", d->PortNames[p]); + } + } + + if ((input_port == (unsigned long) -1) || (output_port == (unsigned long) -1)) { + pa_log("Failed to identify input and output ports. " + "Right now this module can only deal with plugins which provide an 'Input' and an 'Output' audio port. " + "Patches welcome!"); + goto fail; + } + + u->block_size = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss); + + u->input = (LADSPA_Data*) pa_xnew(uint8_t, u->block_size); + if (LADSPA_IS_INPLACE_BROKEN(d->Properties)) + u->output = (LADSPA_Data*) pa_xnew(uint8_t, u->block_size); + else + u->output = u->input; + + u->channels = ss.channels; + + for (c = 0; c < ss.channels; c++) { + if (!(u->handle[c] = d->instantiate(d, ss.rate))) { + pa_log("Failed to instantiate plugin %s with label %s for channel %i", plugin, d->Label, c); + goto fail; + } + + d->connect_port(u->handle[c], input_port, u->input); + d->connect_port(u->handle[c], output_port, u->output); + } + + if (!cdata && n_control > 0) { + pa_log("This plugin requires specification of %lu control parameters.", n_control); + goto fail; + } + + if (n_control > 0) { + const char *state = NULL; + char *k; + unsigned long h; + + u->control = pa_xnew(LADSPA_Data, n_control); + use_default = pa_xnew(pa_bool_t, n_control); + p = 0; + + while ((k = pa_split(cdata, ",", &state))) { + float f; + + if (*k == 0) { + use_default[p++] = TRUE; + pa_xfree(k); + continue; + } + + if (pa_atof(k, &f) < 0) { + pa_log("Failed to parse control value '%s'", k); + pa_xfree(k); + goto fail; + } + + pa_xfree(k); + + if (p >= n_control) { + pa_log("Too many control values passed, %lu expected.", n_control); + goto fail; + } + + use_default[p] = FALSE; + u->control[p++] = f; + } + + if (p < n_control) { + pa_log("Not enough control values passed, %lu expected, %lu passed.", n_control, p); + goto fail; + } + + h = 0; + for (p = 0; p < d->PortCount; p++) { + LADSPA_PortRangeHintDescriptor hint = d->PortRangeHints[p].HintDescriptor; + + if (!LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p])) + continue; + + if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p])) { + for (c = 0; c < ss.channels; c++) + d->connect_port(u->handle[c], p, &u->control_out); + continue; + } + + pa_assert(h < n_control); + + if (use_default[h]) { + LADSPA_Data lower, upper; + + if (!LADSPA_IS_HINT_HAS_DEFAULT(hint)) { + pa_log("Control port value left empty but plugin defines no default."); + goto fail; + } + + lower = d->PortRangeHints[p].LowerBound; + upper = d->PortRangeHints[p].UpperBound; + + if (LADSPA_IS_HINT_SAMPLE_RATE(hint)) { + lower *= ss.rate; + upper *= ss.rate; + } + + switch (hint & LADSPA_HINT_DEFAULT_MASK) { + + case LADSPA_HINT_DEFAULT_MINIMUM: + u->control[h] = lower; + break; + + case LADSPA_HINT_DEFAULT_MAXIMUM: + u->control[h] = upper; + break; + + case LADSPA_HINT_DEFAULT_LOW: + if (LADSPA_IS_HINT_LOGARITHMIC(hint)) + u->control[h] = exp(log(lower) * 0.75 + log(upper) * 0.25); + else + u->control[h] = lower * 0.75 + upper * 0.25; + break; + + case LADSPA_HINT_DEFAULT_MIDDLE: + if (LADSPA_IS_HINT_LOGARITHMIC(hint)) + u->control[h] = exp(log(lower) * 0.5 + log(upper) * 0.5); + else + u->control[h] = lower * 0.5 + upper * 0.5; + break; + + case LADSPA_HINT_DEFAULT_HIGH: + if (LADSPA_IS_HINT_LOGARITHMIC(hint)) + u->control[h] = exp(log(lower) * 0.25 + log(upper) * 0.75); + else + u->control[h] = lower * 0.25 + upper * 0.75; + break; + + case LADSPA_HINT_DEFAULT_0: + u->control[h] = 0; + break; + + case LADSPA_HINT_DEFAULT_1: + u->control[h] = 1; + break; + + case LADSPA_HINT_DEFAULT_100: + u->control[h] = 100; + break; + + case LADSPA_HINT_DEFAULT_440: + u->control[h] = 440; + break; + + default: + pa_assert_not_reached(); + } + } + + if (LADSPA_IS_HINT_INTEGER(hint)) + u->control[h] = roundf(u->control[h]); + + pa_log_debug("Binding %f to port %s", u->control[h], d->PortNames[p]); + + for (c = 0; c < ss.channels; c++) + d->connect_port(u->handle[c], p, &u->control[h]); + + h++; + } + + pa_assert(h == n_control); + } + + if (d->activate) + for (c = 0; c < u->channels; c++) + d->activate(u->handle[c]); + + default_sink_name = pa_sprintf_malloc("%s.ladspa", master->name); + + /* Create sink */ + if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", default_sink_name), 0, &ss, &map))) { + pa_log("Failed to create sink."); + goto fail; + } + + u->sink->parent.process_msg = sink_process_msg; + u->sink->set_state = sink_set_state; + u->sink->userdata = u; + u->sink->flags = PA_SINK_LATENCY; + + pa_sink_set_module(u->sink, m); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("LADSPA plugin '%s' on '%s'", label, master->description)); + pa_xfree(t); + pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq); + pa_sink_set_rtpoll(u->sink, master->rtpoll); + + /* Create sink input */ + pa_sink_input_new_data_init(&data); + data.sink = u->master; + data.driver = __FILE__; + data.name = "LADSPA Stream"; + pa_sink_input_new_data_set_sample_spec(&data, &ss); + pa_sink_input_new_data_set_channel_map(&data, &map); + data.module = m; + + if (!(u->sink_input = pa_sink_input_new(m->core, &data, PA_SINK_INPUT_DONT_MOVE))) + goto fail; + + u->sink_input->parent.process_msg = sink_input_process_msg; + u->sink_input->peek = sink_input_peek_cb; + u->sink_input->drop = sink_input_drop_cb; + u->sink_input->kill = sink_input_kill_cb; + u->sink_input->attach = sink_input_attach_cb; + u->sink_input->detach = sink_input_detach_cb; + u->sink_input->userdata = u; + + pa_sink_put(u->sink); + pa_sink_input_put(u->sink_input); + + pa_modargs_free(ma); + + pa_xfree(use_default); + pa_xfree(default_sink_name); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa_xfree(use_default); + pa_xfree(default_sink_name); + + pa__done(m); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata *u; + unsigned c; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->sink_input) { + pa_sink_input_unlink(u->sink_input); + pa_sink_input_unref(u->sink_input); + } + + if (u->sink) { + pa_sink_unlink(u->sink); + pa_sink_unref(u->sink); + } + + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + + for (c = 0; c < u->channels; c++) + if (u->handle[c]) { + if (u->descriptor->deactivate) + u->descriptor->deactivate(u->handle[c]); + u->descriptor->cleanup(u->handle[c]); + } + + if (u->output != u->input) + pa_xfree(u->output); + + pa_xfree(u->input); + + pa_xfree(u->control); + + pa_xfree(u); +} diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index c8adbc8be..21d93837c 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -26,12 +26,12 @@ #endif #include -#include #include #include -#include #include +#include + #include #include @@ -39,6 +39,7 @@ #include #include #include +#include #include "module-lirc-symdef.h" @@ -68,11 +69,12 @@ static int lirc_in_use = 0; static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) { struct userdata *u = userdata; char *name = NULL, *code = NULL; - assert(io); - assert(u); + + pa_assert(io); + pa_assert(u); if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { - pa_log("lost connection to LIRC daemon."); + pa_log("Lost connection to LIRC daemon."); goto fail; } @@ -86,7 +88,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC c = pa_xstrdup(code); c[strcspn(c, "\n\r")] = 0; - pa_log_debug("raw IR code '%s'", c); + pa_log_debug("Raw IR code '%s'", c); pa_xfree(c); while (lirc_code2char(u->config, code, &name) == 0 && name) { @@ -99,7 +101,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC MUTE_TOGGLE } volchange = INVALID; - pa_log_info("translated IR code '%s'", name); + pa_log_info("Translated IR code '%s'", name); if (strcasecmp(name, "volume-up") == 0) volchange = UP; @@ -113,15 +115,15 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC volchange = RESET; if (volchange == INVALID) - pa_log_warn("recieved unknown IR code '%s'", name); + pa_log_warn("Recieved unknown IR code '%s'", name); else { pa_sink *s; if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) - pa_log("failed to get sink '%s'", u->sink_name); + pa_log("Failed to get sink '%s'", u->sink_name); else { int i; - pa_cvolume cv = *pa_sink_get_volume(s, PA_MIXER_HARDWARE); + pa_cvolume cv = *pa_sink_get_volume(s); #define DELTA (PA_VOLUME_NORM/20) @@ -134,7 +136,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC cv.values[i] = PA_VOLUME_NORM; } - pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); + pa_sink_set_volume(s, &cv); break; case DOWN: @@ -145,20 +147,20 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC cv.values[i] = PA_VOLUME_MUTED; } - pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); + pa_sink_set_volume(s, &cv); break; case MUTE: - pa_sink_set_mute(s, PA_MIXER_HARDWARE, 0); + pa_sink_set_mute(s, 0); break; case RESET: - pa_sink_set_mute(s, PA_MIXER_HARDWARE, 1); + pa_sink_set_mute(s, 1); break; case MUTE_TOGGLE: - pa_sink_set_mute(s, PA_MIXER_HARDWARE, !pa_sink_get_mute(s, PA_MIXER_HARDWARE)); + pa_sink_set_mute(s, !pa_sink_get_mute(s)); break; case INVALID: @@ -179,13 +181,14 @@ fail: pa_module_unload_request(u->module); - free(code); + pa_xfree(code); } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; - assert(c && m); + + pa_assert(m); if (lirc_in_use) { pa_log("module-lirc may no be loaded twice."); @@ -197,7 +200,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - m->userdata = u = pa_xmalloc(sizeof(struct userdata)); + m->userdata = u = pa_xnew(struct userdata, 1); u->module = m; u->io = NULL; u->config = NULL; @@ -215,7 +218,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - u->io = c->mainloop->io_new(c->mainloop, u->lirc_fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); + u->io = m->core->mainloop->io_new(m->core->mainloop, u->lirc_fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); lirc_in_use = 1; @@ -228,14 +231,13 @@ fail: if (ma) pa_modargs_free(ma); - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c); - assert(m); + pa_assert(m); if (!(u = m->userdata)) return; diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 0b051facb..0155b2af6 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include #include @@ -80,6 +79,8 @@ static int load_rules(struct userdata *u, const char *filename) { struct rule *end = NULL; char *fn = NULL; + pa_assert(u); + f = filename ? fopen(fn = pa_xstrdup(filename), "r") : pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn, "r"); @@ -132,7 +133,7 @@ static int load_rules(struct userdata *u, const char *filename) { goto finish; } - rule = pa_xmalloc(sizeof(struct rule)); + rule = pa_xnew(struct rule, 1); rule->regex = regex; rule->volume = volume; rule->next = NULL; @@ -164,7 +165,9 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v struct userdata *u = userdata; pa_sink_input *si; struct rule *r; - assert(c && u); + + pa_assert(c); + pa_assert(u); if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW)) return; @@ -179,23 +182,24 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v if (!regexec(&r->regex, si->name, 0, NULL, 0)) { pa_cvolume cv; pa_log_debug("changing volume of sink input '%s' to 0x%03x", si->name, r->volume); - pa_cvolume_set(&cv, r->volume, si->sample_spec.channels); + pa_cvolume_set(&cv, si->sample_spec.channels, r->volume); pa_sink_input_set_volume(si, &cv); } } } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; - assert(c && m); + + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } - u = pa_xmalloc(sizeof(struct userdata)); + u = pa_xnew(struct userdata, 1); u->rules = NULL; u->subscription = NULL; m->userdata = u; @@ -203,23 +207,24 @@ int pa__init(pa_core *c, pa_module*m) { if (load_rules(u, pa_modargs_get_value(ma, "table", NULL)) < 0) goto fail; - u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); + u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); pa_modargs_free(ma); return 0; fail: - pa__done(c, m); + pa__done(m); if (ma) pa_modargs_free(ma); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata* u; struct rule *r, *n; - assert(c && m); + + pa_assert(m); if (!(u = m->userdata)) return; diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index b7433ac82..47a106456 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include #include @@ -80,11 +79,12 @@ struct userdata { static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) { struct userdata *u = userdata; - assert(io); - assert(u); + + pa_assert(io); + pa_assert(u); if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { - pa_log("lost connection to evdev device."); + pa_log("Lost connection to evdev device."); goto fail; } @@ -92,14 +92,14 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC struct input_event ev; if (pa_loop_read(u->fd, &ev, sizeof(ev), &u->fd_type) <= 0) { - pa_log("failed to read from event device: %s", pa_cstrerror(errno)); + pa_log("Failed to read from event device: %s", pa_cstrerror(errno)); goto fail; } if (ev.type == EV_KEY && (ev.value == 1 || ev.value == 2)) { enum { INVALID, UP, DOWN, MUTE_TOGGLE } volchange = INVALID; - pa_log_debug("key code=%u, value=%u", ev.code, ev.value); + pa_log_debug("Key code=%u, value=%u", ev.code, ev.value); switch (ev.code) { case KEY_VOLUMEDOWN: volchange = DOWN; break; @@ -111,10 +111,10 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC pa_sink *s; if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) - pa_log("failed to get sink '%s'", u->sink_name); + pa_log("Failed to get sink '%s'", u->sink_name); else { int i; - pa_cvolume cv = *pa_sink_get_volume(s, PA_MIXER_HARDWARE); + pa_cvolume cv = *pa_sink_get_volume(s); #define DELTA (PA_VOLUME_NORM/20) @@ -127,7 +127,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC cv.values[i] = PA_VOLUME_NORM; } - pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); + pa_sink_set_volume(s, &cv); break; case DOWN: @@ -138,12 +138,12 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC cv.values[i] = PA_VOLUME_MUTED; } - pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv); + pa_sink_set_volume(s, &cv); break; case MUTE_TOGGLE: - pa_sink_set_mute(s, PA_MIXER_HARDWARE, !pa_sink_get_mute(s, PA_MIXER_HARDWARE)); + pa_sink_set_mute(s, !pa_sink_get_mute(s)); break; case INVALID: @@ -165,21 +165,23 @@ fail: #define test_bit(bit, array) (array[bit/8] & (1<<(bit%8))) -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { + pa_modargs *ma = NULL; struct userdata *u; int version; struct _input_id input_id; char name[256]; uint8_t evtype_bitmask[EV_MAX/8 + 1]; - assert(c && m); + + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } - m->userdata = u = pa_xmalloc(sizeof(struct userdata)); + m->userdata = u = pa_xnew(struct userdata,1); u->module = m; u->io = NULL; u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); @@ -221,11 +223,11 @@ int pa__init(pa_core *c, pa_module*m) { } if (!test_bit(EV_KEY, evtype_bitmask)) { - pa_log("device has no keys."); + pa_log("Device has no keys."); goto fail; } - u->io = c->mainloop->io_new(c->mainloop, u->fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); + u->io = m->core->mainloop->io_new(m->core->mainloop, u->fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); pa_modargs_free(ma); @@ -236,14 +238,14 @@ fail: if (ma) pa_modargs_free(ma); - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c); - assert(m); + + pa_assert(m); if (!(u = m->userdata)) return; @@ -252,7 +254,7 @@ void pa__done(pa_core *c, pa_module*m) { m->core->mainloop->io_free(u->io); if (u->fd >= 0) - close(u->fd); + pa_assert_se(pa_close(u->fd) == 0); pa_xfree(u->sink_name); pa_xfree(u); diff --git a/src/modules/module-native-protocol-fd.c b/src/modules/module-native-protocol-fd.c index 3c1c2bca4..2ef61c88e 100644 --- a/src/modules/module-native-protocol-fd.c +++ b/src/modules/module-native-protocol-fd.c @@ -26,10 +26,10 @@ #endif #include -#include #include #include +#include #include #include #include @@ -48,25 +48,26 @@ static const char* const valid_modargs[] = { NULL, }; -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_iochannel *io; pa_modargs *ma; int fd, r = -1; - assert(c && m); + + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments."); + pa_log("Failed to parse module arguments."); goto finish; } if (pa_modargs_get_value_s32(ma, "fd", &fd) < 0) { - pa_log("invalid file descriptor."); + pa_log("Invalid file descriptor."); goto finish; } - io = pa_iochannel_new(c->mainloop, fd, fd); + io = pa_iochannel_new(m->core->mainloop, fd, fd); - if (!(m->userdata = pa_protocol_native_new_iochannel(c, io, m, ma))) { + if (!(m->userdata = pa_protocol_native_new_iochannel(m->core, io, m, ma))) { pa_iochannel_free(io); goto finish; } @@ -80,8 +81,8 @@ finish: return r; } -void pa__done(pa_core *c, pa_module*m) { - assert(c && m); +void pa__done(pa_module*m) { + pa_assert(m); pa_protocol_native_free(m->userdata); } diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 54a8e8902..3a4edec70 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -38,12 +37,17 @@ #include #include -#include +#include #include #include #include +#include #include #include +#include +#include +#include +#include #include "module-null-sink-symdef.h" @@ -64,11 +68,14 @@ struct userdata { pa_core *core; pa_module *module; pa_sink *sink; - pa_time_event *time_event; + + pa_thread *thread; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + size_t block_size; - uint64_t n_bytes; - struct timeval start_time; + struct timeval timestamp; }; static const char* const valid_modargs[] = { @@ -81,78 +88,132 @@ static const char* const valid_modargs[] = { NULL }; -static void time_callback(pa_mainloop_api *m, pa_time_event*e, const struct timeval *tv, void *userdata) { +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + + switch (code) { + case PA_SINK_MESSAGE_SET_STATE: + + if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING) + pa_rtclock_get(&u->timestamp); + + break; + + case PA_SINK_MESSAGE_GET_LATENCY: { + struct timeval now; + + pa_rtclock_get(&now); + + if (pa_timeval_cmp(&u->timestamp, &now) > 0) + *((pa_usec_t*) data) = 0; + else + *((pa_usec_t*) data) = pa_timeval_diff(&u->timestamp, &now); + break; + } + } + + return pa_sink_process_msg(o, code, data, offset, chunk); +} + +static void thread_func(void *userdata) { struct userdata *u = userdata; - pa_memchunk chunk; - struct timeval ntv = *tv; - size_t l; - assert(u); + pa_assert(u); - if (pa_sink_render(u->sink, u->block_size, &chunk) >= 0) { - l = chunk.length; - pa_memblock_unref(chunk.memblock); - } else - l = u->block_size; + pa_log_debug("Thread starting up"); - pa_timeval_add(&ntv, pa_bytes_to_usec(l, &u->sink->sample_spec)); - m->time_restart(e, &ntv); + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); - u->n_bytes += l; + pa_rtclock_get(&u->timestamp); + + for (;;) { + int ret; + + /* Render some data and drop it immediately */ + if (u->sink->thread_info.state == PA_SINK_RUNNING) { + struct timeval now; + + pa_rtclock_get(&now); + + if (pa_timeval_cmp(&u->timestamp, &now) <= 0) { + pa_sink_skip(u->sink, u->block_size); + pa_timeval_add(&u->timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec)); + } + + pa_rtpoll_set_timer_absolute(u->rtpoll, &u->timestamp); + } else + pa_rtpoll_set_timer_disabled(u->rtpoll); + + /* Hmm, nothing to do. Let's sleep */ + if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0) + goto fail; + + if (ret == 0) + goto finish; + } + +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("Thread shutting down"); } -static pa_usec_t get_latency(pa_sink *s) { - struct userdata *u = s->userdata; - pa_usec_t a, b; - struct timeval now; - - a = pa_timeval_diff(pa_gettimeofday(&now), &u->start_time); - b = pa_bytes_to_usec(u->n_bytes, &s->sample_spec); - - return b > a ? b - a : 0; -} - -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; - assert(c); - assert(m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments."); + pa_log("Failed to parse module arguments."); goto fail; } - ss = c->default_sample_spec; + ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { - pa_log("invalid sample format specification or channel map."); + pa_log("Invalid sample format specification or channel map"); goto fail; } u = pa_xnew0(struct userdata, 1); - u->core = c; + u->core = m->core; u->module = m; m->userdata = u; + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { - pa_log("failed to create sink."); + if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { + pa_log("Failed to create sink."); goto fail; } - u->sink->get_latency = get_latency; + u->sink->parent.process_msg = sink_process_msg; u->sink->userdata = u; - pa_sink_set_owner(u->sink, m); + u->sink->flags = PA_SINK_LATENCY; + + pa_sink_set_module(u->sink, m); + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); pa_sink_set_description(u->sink, pa_modargs_get_value(ma, "description", "NULL sink")); - u->n_bytes = 0; - pa_gettimeofday(&u->start_time); + u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */ + if (u->block_size <= 0) + u->block_size = pa_frame_size(&ss); - u->time_event = c->mainloop->time_new(c->mainloop, &u->start_time, time_callback, u); + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } - u->block_size = pa_bytes_per_second(&ss) / 10; + pa_sink_put(u->sink); pa_modargs_free(ma); @@ -162,22 +223,34 @@ fail: if (ma) pa_modargs_free(ma); - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c && m); + + pa_assert(m); if (!(u = m->userdata)) return; - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); + if (u->sink) + pa_sink_unlink(u->sink); - u->core->mainloop->time_free(u->time_event); + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } + + pa_thread_mq_done(&u->thread_mq); + + if (u->sink) + pa_sink_unref(u->sink); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); pa_xfree(u); } diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c deleted file mode 100644 index 16c9b311a..000000000 --- a/src/modules/module-oss-mmap.c +++ /dev/null @@ -1,637 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of PulseAudio. - - Copyright 2004-2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_SYS_MMAN_H -#include -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "oss-util.h" -#include "module-oss-mmap-symdef.h" - -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("OSS Sink/Source (mmap)") -PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE( - "sink_name= " - "source_name= " - "device= " - "record= " - "playback= " - "format= " - "channels= " - "rate= " - "fragments= " - "fragment_size= " - "channel_map=") - -struct userdata { - pa_sink *sink; - pa_source *source; - pa_core *core; - pa_sample_spec sample_spec; - - size_t in_fragment_size, out_fragment_size; - unsigned in_fragments, out_fragments; - unsigned out_blocks_saved, in_blocks_saved; - - int fd; - - void *in_mmap, *out_mmap; - size_t in_mmap_length, out_mmap_length; - - pa_io_event *io_event; - - pa_memblock **in_memblocks, **out_memblocks; - unsigned out_current, in_current; - pa_module *module; -}; - -static const char* const valid_modargs[] = { - "sink_name", - "source_name", - "device", - "record", - "playback", - "fragments", - "fragment_size", - "format", - "rate", - "channels", - "channel_map", - NULL -}; - -#define DEFAULT_DEVICE "/dev/dsp" -#define DEFAULT_NFRAGS 12 -#define DEFAULT_FRAGSIZE 1024 - -static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, - (u->sink ? pa_sink_used_by(u->sink) : 0) + - (u->source ? pa_source_used_by(u->source) : 0)); -} - -static void clear_up(struct userdata *u) { - assert(u); - - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - u->sink = NULL; - } - - if (u->source) { - pa_source_disconnect(u->source); - pa_source_unref(u->source); - u->source = NULL; - } - - if (u->in_mmap && u->in_mmap != MAP_FAILED) { - munmap(u->in_mmap, u->in_mmap_length); - u->in_mmap = NULL; - } - - if (u->out_mmap && u->out_mmap != MAP_FAILED) { - munmap(u->out_mmap, u->out_mmap_length); - u->out_mmap = NULL; - } - - if (u->io_event) { - u->core->mainloop->io_free(u->io_event); - u->io_event = NULL; - } - - if (u->fd >= 0) { - close(u->fd); - u->fd = -1; - } -} - -static void out_fill_memblocks(struct userdata *u, unsigned n) { - assert(u && u->out_memblocks); - - while (n > 0) { - pa_memchunk chunk; - - if (u->out_memblocks[u->out_current]) - pa_memblock_unref_fixed(u->out_memblocks[u->out_current]); - - chunk.memblock = u->out_memblocks[u->out_current] = - pa_memblock_new_fixed( - u->core->mempool, - (uint8_t*) u->out_mmap+u->out_fragment_size*u->out_current, - u->out_fragment_size, - 1); - assert(chunk.memblock); - chunk.length = chunk.memblock->length; - chunk.index = 0; - - pa_sink_render_into_full(u->sink, &chunk); - - u->out_current++; - while (u->out_current >= u->out_fragments) - u->out_current -= u->out_fragments; - - n--; - } -} - -static void do_write(struct userdata *u) { - struct count_info info; - assert(u && u->sink); - - update_usage(u); - - if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { - pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); - - clear_up(u); - pa_module_unload_request(u->module); - return; - } - - info.blocks += u->out_blocks_saved; - u->out_blocks_saved = 0; - - if (!info.blocks) - return; - - out_fill_memblocks(u, info.blocks); -} - -static void in_post_memblocks(struct userdata *u, unsigned n) { - assert(u && u->in_memblocks); - - while (n > 0) { - pa_memchunk chunk; - - if (!u->in_memblocks[u->in_current]) { - chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->core->mempool, (uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, 1); - chunk.length = chunk.memblock->length; - chunk.index = 0; - - pa_source_post(u->source, &chunk); - } - - u->in_current++; - while (u->in_current >= u->in_fragments) - u->in_current -= u->in_fragments; - - n--; - } -} - -static void in_clear_memblocks(struct userdata*u, unsigned n) { - unsigned i = u->in_current; - assert(u && u->in_memblocks); - - if (n > u->in_fragments) - n = u->in_fragments; - - while (n > 0) { - if (u->in_memblocks[i]) { - pa_memblock_unref_fixed(u->in_memblocks[i]); - u->in_memblocks[i] = NULL; - } - - i++; - while (i >= u->in_fragments) - i -= u->in_fragments; - - n--; - } -} - -static void do_read(struct userdata *u) { - struct count_info info; - assert(u && u->source); - - update_usage(u); - - if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { - pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); - - clear_up(u); - pa_module_unload_request(u->module); - return; - } - - info.blocks += u->in_blocks_saved; - u->in_blocks_saved = 0; - - if (!info.blocks) - return; - - in_post_memblocks(u, info.blocks); - in_clear_memblocks(u, u->in_fragments/2); -} - -static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t f, void *userdata) { - struct userdata *u = userdata; - assert (u && u->core->mainloop == m && u->io_event == e); - - if (f & PA_IO_EVENT_ERROR) { - clear_up(u); - pa_module_unload_request(u->module); - return; - } - - if (f & PA_IO_EVENT_INPUT) - do_read(u); - if (f & PA_IO_EVENT_OUTPUT) - do_write(u); -} - -static pa_usec_t sink_get_latency_cb(pa_sink *s) { - struct userdata *u = s->userdata; - struct count_info info; - size_t bpos, n, total; - assert(s && u); - - if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { - pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); - return 0; - } - - u->out_blocks_saved += info.blocks; - - total = u->out_fragments * u->out_fragment_size; - bpos = ((u->out_current + u->out_blocks_saved) * u->out_fragment_size) % total; - - if (bpos <= (size_t) info.ptr) - n = total - (info.ptr - bpos); - else - n = bpos - info.ptr; - -/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->out_fragment_size, u->out_fragments); */ - - return pa_bytes_to_usec(n, &s->sample_spec); -} - -static pa_usec_t source_get_latency_cb(pa_source *s) { - struct userdata *u = s->userdata; - struct count_info info; - size_t bpos, n, total; - assert(s && u); - - if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { - pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); - return 0; - } - - u->in_blocks_saved += info.blocks; - - total = u->in_fragments * u->in_fragment_size; - bpos = ((u->in_current + u->in_blocks_saved) * u->in_fragment_size) % total; - - if (bpos <= (size_t) info.ptr) - n = info.ptr - bpos; - else - n = (u->in_fragments * u->in_fragment_size) - bpos + info.ptr; - -/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->in_fragment_size, u->in_fragments); */ - - return pa_bytes_to_usec(n, &s->sample_spec); -} - -static int sink_get_hw_volume(pa_sink *s) { - struct userdata *u = s->userdata; - - if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); - s->get_hw_volume = NULL; - return -1; - } - - return 0; -} - -static int sink_set_hw_volume(pa_sink *s) { - struct userdata *u = s->userdata; - - if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); - s->set_hw_volume = NULL; - return -1; - } - - return 0; -} - -static int source_get_hw_volume(pa_source *s) { - struct userdata *u = s->userdata; - - if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); - s->get_hw_volume = NULL; - return -1; - } - - return 0; -} - -static int source_set_hw_volume(pa_source *s) { - struct userdata *u = s->userdata; - - if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); - s->set_hw_volume = NULL; - return -1; - } - - return 0; -} - -int pa__init(pa_core *c, pa_module*m) { - struct audio_buf_info info; - struct userdata *u = NULL; - const char *p; - int nfrags, frag_size; - int mode, caps; - int enable_bits = 0, zero = 0; - int playback = 1, record = 1; - pa_modargs *ma = NULL; - char hwdesc[64], *t; - pa_channel_map map; - const char *name; - char *name_buf = NULL; - int namereg_fail; - - assert(c); - assert(m); - - m->userdata = u = pa_xnew0(struct userdata, 1); - u->module = m; - u->fd = -1; - u->core = c; - - if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments."); - goto fail; - } - - if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log("record= and playback= expect numeric arguments."); - goto fail; - } - - if (!playback && !record) { - pa_log("neither playback nor record enabled for device."); - goto fail; - } - - mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); - - nfrags = DEFAULT_NFRAGS; - frag_size = DEFAULT_FRAGSIZE; - if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { - pa_log("failed to parse fragments arguments"); - goto fail; - } - - u->sample_spec = c->default_sample_spec; - if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->sample_spec, &map, PA_CHANNEL_MAP_OSS) < 0) { - pa_log("failed to parse sample specification or channel map"); - goto fail; - } - - if ((u->fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0) - goto fail; - - if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER)) { - pa_log("OSS device not mmap capable."); - goto fail; - } - - pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); - - if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0) - pa_log_info("hardware name is '%s'.", hwdesc); - else - hwdesc[0] = 0; - - if (nfrags >= 2 && frag_size >= 1) - if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0) - goto fail; - - if (pa_oss_auto_format(u->fd, &u->sample_spec) < 0) - goto fail; - - if (mode != O_WRONLY) { - if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { - pa_log("SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno)); - goto fail; - } - - pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize); - u->in_mmap_length = (u->in_fragment_size = info.fragsize) * (u->in_fragments = info.fragstotal); - - if ((u->in_mmap = mmap(NULL, u->in_mmap_length, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { - if (mode == O_RDWR) { - pa_log("mmap failed for input. Changing to O_WRONLY mode."); - mode = O_WRONLY; - } else { - pa_log("mmap(): %s", pa_cstrerror(errno)); - goto fail; - } - } else { - if ((name = pa_modargs_get_value(ma, "source_name", NULL))) - namereg_fail = 1; - else { - name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(p)); - namereg_fail = 0; - } - - if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &u->sample_spec, &map))) - goto fail; - - u->source->userdata = u; - u->source->get_latency = source_get_latency_cb; - u->source->get_hw_volume = source_get_hw_volume; - u->source->set_hw_volume = source_set_hw_volume; - pa_source_set_owner(u->source, m); - pa_source_set_description(u->source, t = pa_sprintf_malloc("OSS PCM/mmap() on %s%s%s%s", - p, - hwdesc[0] ? " (" : "", - hwdesc[0] ? hwdesc : "", - hwdesc[0] ? ")" : "")); - pa_xfree(t); - u->source->is_hardware = 1; - - u->in_memblocks = pa_xnew0(pa_memblock*, u->in_fragments); - - enable_bits |= PCM_ENABLE_INPUT; - } - } - - pa_xfree(name_buf); - name_buf = NULL; - - if (mode != O_RDONLY) { - if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { - pa_log("SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno)); - goto fail; - } - - pa_log_info("output -- %u fragments of size %u.", info.fragstotal, info.fragsize); - u->out_mmap_length = (u->out_fragment_size = info.fragsize) * (u->out_fragments = info.fragstotal); - - if ((u->out_mmap = mmap(NULL, u->out_mmap_length, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { - if (mode == O_RDWR) { - pa_log("mmap filed for output. Changing to O_RDONLY mode."); - mode = O_RDONLY; - } else { - pa_log("mmap(): %s", pa_cstrerror(errno)); - goto fail; - } - } else { - pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec); - - if ((name = pa_modargs_get_value(ma, "sink_name", NULL))) - namereg_fail = 1; - else { - name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p)); - namereg_fail = 0; - } - - if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &u->sample_spec, &map))) - goto fail; - - u->sink->get_latency = sink_get_latency_cb; - u->sink->get_hw_volume = sink_get_hw_volume; - u->sink->set_hw_volume = sink_set_hw_volume; - u->sink->userdata = u; - pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("OSS PCM/mmap() on %s%s%s%s", - p, - hwdesc[0] ? " (" : "", - hwdesc[0] ? hwdesc : "", - hwdesc[0] ? ")" : "")); - pa_xfree(t); - - u->sink->is_hardware = 1; - u->out_memblocks = pa_xmalloc0(sizeof(struct memblock *)*u->out_fragments); - - enable_bits |= PCM_ENABLE_OUTPUT; - } - } - - pa_xfree(name_buf); - name_buf = NULL; - - zero = 0; - if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero) < 0) { - pa_log("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); - goto fail; - } - - if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0) { - pa_log("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); - goto fail; - } - - assert(u->source || u->sink); - - u->io_event = c->mainloop->io_new(c->mainloop, u->fd, (u->source ? PA_IO_EVENT_INPUT : 0) | (u->sink ? PA_IO_EVENT_OUTPUT : 0), io_callback, u); - assert(u->io_event); - - pa_modargs_free(ma); - - /* Read mixer settings */ - if (u->source) - source_get_hw_volume(u->source); - if (u->sink) - sink_get_hw_volume(u->sink); - - return 0; - -fail: - pa__done(c, m); - - if (ma) - pa_modargs_free(ma); - - pa_xfree(name_buf); - - return -1; -} - -void pa__done(pa_core *c, pa_module*m) { - struct userdata *u; - - assert(c); - assert(m); - - if (!(u = m->userdata)) - return; - - clear_up(u); - - if (u->out_memblocks) { - unsigned i; - for (i = 0; i < u->out_fragments; i++) - if (u->out_memblocks[i]) - pa_memblock_unref_fixed(u->out_memblocks[i]); - pa_xfree(u->out_memblocks); - } - - if (u->in_memblocks) { - unsigned i; - for (i = 0; i < u->in_fragments; i++) - if (u->in_memblocks[i]) - pa_memblock_unref_fixed(u->in_memblocks[i]); - pa_xfree(u->in_memblocks); - } - - pa_xfree(u); -} diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 9d4d0eac1..19dceef27 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -22,27 +22,46 @@ USA. ***/ +/* General power management rules: + * + * When SUSPENDED we close the audio device. + * + * We make no difference between IDLE and RUNNING in our handling. + * + * As long as we are in RUNNING/IDLE state we will *always* write data to + * the device. If none is avilable from the inputs, we write silence + * instead. + * + * If power should be saved on IDLE module-suspend-on-idle should be used. + * + */ + #ifdef HAVE_CONFIG_H #include #endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif + #include #include #include #include #include -#include #include #include #include #include #include +#include +#include #include #include #include -#include +#include #include #include #include @@ -50,6 +69,9 @@ #include #include #include +#include +#include +#include #include "oss-util.h" #include "module-oss-symdef.h" @@ -68,21 +90,48 @@ PA_MODULE_USAGE( "rate= " "fragments= " "fragment_size= " - "channel_map=") + "channel_map= " + "mmap=") + +#define DEFAULT_DEVICE "/dev/dsp" struct userdata { + pa_core *core; + pa_module *module; pa_sink *sink; pa_source *source; - pa_iochannel *io; - pa_core *core; - pa_memchunk memchunk, silence; + pa_thread *thread; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; - uint32_t in_fragment_size, out_fragment_size, sample_size; - int use_getospace, use_getispace; + char *device_name; + + pa_memchunk memchunk; + + size_t frame_size; + uint32_t in_fragment_size, out_fragment_size, in_nfrags, out_nfrags, in_hwbuf_size, out_hwbuf_size; + pa_bool_t use_getospace, use_getispace; + pa_bool_t use_getodelay; + + pa_bool_t sink_suspended, source_suspended; int fd; - pa_module *module; + int mode; + + int mixer_fd; + int mixer_devmask; + + int nfrags, frag_size; + + pa_bool_t use_mmap; + unsigned out_mmap_current, in_mmap_current; + void *in_mmap, *out_mmap; + pa_memblock **in_mmap_memblocks, **out_mmap_memblocks; + + int in_mmap_saved_nfrags, out_mmap_saved_nfrags; + + pa_rtpoll_item *rtpoll_item; }; static const char* const valid_modargs[] = { @@ -97,280 +146,1010 @@ static const char* const valid_modargs[] = { "rate", "channels", "channel_map", + "mmap", NULL }; -#define DEFAULT_DEVICE "/dev/dsp" +static void trigger(struct userdata *u, pa_bool_t quick) { + int enable_bits = 0, zero = 0; -static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, - (u->sink ? pa_sink_used_by(u->sink) : 0) + - (u->source ? pa_source_used_by(u->source) : 0)); -} + pa_assert(u); -static void clear_up(struct userdata *u) { - assert(u); - - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - u->sink = NULL; - } - - if (u->source) { - pa_source_disconnect(u->source); - pa_source_unref(u->source); - u->source = NULL; - } - - if (u->io) { - pa_iochannel_free(u->io); - u->io = NULL; - } -} - -static void do_write(struct userdata *u) { - pa_memchunk *memchunk; - ssize_t r; - size_t l; - int loop = 0; - - assert(u); - - if (!u->sink || !pa_iochannel_is_writable(u->io)) + if (u->fd < 0) return; - update_usage(u); + pa_log_debug("trigger"); - l = u->out_fragment_size; + if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) + enable_bits |= PCM_ENABLE_INPUT; - if (u->use_getospace) { - audio_buf_info info; + if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state)) + enable_bits |= PCM_ENABLE_OUTPUT; - if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) - u->use_getospace = 0; - else { - if (info.bytes/l > 0) { - l = (info.bytes/l)*l; - loop = 1; + pa_log_debug("trigger: %i", enable_bits); + + + if (u->use_mmap) { + + if (!quick) + ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero); + +#ifdef SNDCTL_DSP_HALT + if (enable_bits == 0) + if (ioctl(u->fd, SNDCTL_DSP_HALT, NULL) < 0) + pa_log_warn("SNDCTL_DSP_HALT: %s", pa_cstrerror(errno)); +#endif + + if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0) + pa_log_warn("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno)); + + if (u->sink && !(enable_bits & PCM_ENABLE_OUTPUT)) { + pa_log_debug("clearing playback buffer"); + pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &u->sink->sample_spec); + } + + } else { + + if (enable_bits) + if (ioctl(u->fd, SNDCTL_DSP_POST, NULL) < 0) + pa_log_warn("SNDCTL_DSP_POST: %s", pa_cstrerror(errno)); + + if (!quick) { + /* + * Some crappy drivers do not start the recording until we + * read something. Without this snippet, poll will never + * register the fd as ready. + */ + + if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) { + uint8_t *buf = pa_xnew(uint8_t, u->in_fragment_size); + pa_read(u->fd, buf, u->in_fragment_size, NULL); + pa_xfree(buf); } } } - - do { - memchunk = &u->memchunk; - - if (!memchunk->length) - if (pa_sink_render(u->sink, l, memchunk) < 0) - memchunk = &u->silence; - - assert(memchunk->memblock); - assert(memchunk->memblock->data); - assert(memchunk->length); - - if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) { - - if (errno != EAGAIN) { - pa_log("write() failed: %s", pa_cstrerror(errno)); - - clear_up(u); - pa_module_unload_request(u->module); - } - - break; - } - - if (memchunk == &u->silence) - assert(r % u->sample_size == 0); - else { - u->memchunk.index += r; - u->memchunk.length -= r; - - if (u->memchunk.length <= 0) { - pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; - } - } - - l = l > (size_t) r ? l - r : 0; - } while (loop && l > 0); } -static void do_read(struct userdata *u) { - pa_memchunk memchunk; - ssize_t r; - size_t l; - int loop = 0; - assert(u); +static void mmap_fill_memblocks(struct userdata *u, unsigned n) { + pa_assert(u); + pa_assert(u->out_mmap_memblocks); - if (!u->source || !pa_iochannel_is_readable(u->io) || !pa_idxset_size(u->source->outputs)) - return; +/* pa_log("Mmmap writing %u blocks", n); */ - update_usage(u); + while (n > 0) { + pa_memchunk chunk; - l = u->in_fragment_size; + if (u->out_mmap_memblocks[u->out_mmap_current]) + pa_memblock_unref_fixed(u->out_mmap_memblocks[u->out_mmap_current]); - if (u->use_getispace) { - audio_buf_info info; + chunk.memblock = u->out_mmap_memblocks[u->out_mmap_current] = + pa_memblock_new_fixed( + u->core->mempool, + (uint8_t*) u->out_mmap + u->out_fragment_size * u->out_mmap_current, + u->out_fragment_size, + 1); - if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) - u->use_getispace = 0; - else { - if (info.bytes/l > 0) { - l = (info.bytes/l)*l; - loop = 1; - } - } + chunk.length = pa_memblock_get_length(chunk.memblock); + chunk.index = 0; + + pa_sink_render_into_full(u->sink, &chunk); + + u->out_mmap_current++; + while (u->out_mmap_current >= u->out_nfrags) + u->out_mmap_current -= u->out_nfrags; + + n--; + } +} + +static int mmap_write(struct userdata *u) { + struct count_info info; + + pa_assert(u); + pa_assert(u->sink); + +/* pa_log("Mmmap writing..."); */ + + if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { + pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); + return -1; } - do { - memchunk.memblock = pa_memblock_new(u->core->mempool, l); - assert(memchunk.memblock); - if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { - pa_memblock_unref(memchunk.memblock); + info.blocks += u->out_mmap_saved_nfrags; + u->out_mmap_saved_nfrags = 0; - if (errno != EAGAIN) { - pa_log("read() failed: %s", pa_cstrerror(errno)); + if (info.blocks > 0) + mmap_fill_memblocks(u, info.blocks); - clear_up(u); - pa_module_unload_request(u->module); - } + return info.blocks; +} - break; +static void mmap_post_memblocks(struct userdata *u, unsigned n) { + pa_assert(u); + pa_assert(u->in_mmap_memblocks); + +/* pa_log("Mmmap reading %u blocks", n); */ + + while (n > 0) { + pa_memchunk chunk; + + if (!u->in_mmap_memblocks[u->in_mmap_current]) { + + chunk.memblock = u->in_mmap_memblocks[u->in_mmap_current] = + pa_memblock_new_fixed( + u->core->mempool, + (uint8_t*) u->in_mmap + u->in_fragment_size*u->in_mmap_current, + u->in_fragment_size, + 1); + + chunk.length = pa_memblock_get_length(chunk.memblock); + chunk.index = 0; + + pa_source_post(u->source, &chunk); } - assert(r <= (ssize_t) memchunk.memblock->length); - memchunk.length = memchunk.memblock->length = r; - memchunk.index = 0; + u->in_mmap_current++; + while (u->in_mmap_current >= u->in_nfrags) + u->in_mmap_current -= u->in_nfrags; - pa_source_post(u->source, &memchunk); - pa_memblock_unref(memchunk.memblock); - - l = l > (size_t) r ? l - r : 0; - } while (loop && l > 0); + n--; + } } -static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { - struct userdata *u = userdata; - assert(u); - do_write(u); - do_read(u); +static void mmap_clear_memblocks(struct userdata*u, unsigned n) { + unsigned i = u->in_mmap_current; + + pa_assert(u); + pa_assert(u->in_mmap_memblocks); + + if (n > u->in_nfrags) + n = u->in_nfrags; + + while (n > 0) { + if (u->in_mmap_memblocks[i]) { + pa_memblock_unref_fixed(u->in_mmap_memblocks[i]); + u->in_mmap_memblocks[i] = NULL; + } + + i++; + while (i >= u->in_nfrags) + i -= u->in_nfrags; + + n--; + } } -static void source_notify_cb(pa_source *s) { - struct userdata *u = s->userdata; - assert(u); - do_read(u); +static int mmap_read(struct userdata *u) { + struct count_info info; + pa_assert(u); + pa_assert(u->source); + +/* pa_log("Mmmap reading..."); */ + + if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { + pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); + return -1; + } + +/* pa_log("... %i", info.blocks); */ + + info.blocks += u->in_mmap_saved_nfrags; + u->in_mmap_saved_nfrags = 0; + + if (info.blocks > 0) { + mmap_post_memblocks(u, info.blocks); + mmap_clear_memblocks(u, u->in_nfrags/2); + } + + return info.blocks; } -static pa_usec_t sink_get_latency_cb(pa_sink *s) { - pa_usec_t r = 0; - int arg; - struct userdata *u = s->userdata; - assert(s && u && u->sink); +static pa_usec_t mmap_sink_get_latency(struct userdata *u) { + struct count_info info; + size_t bpos, n; - if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) { - pa_log_info("device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno)); - s->get_latency = NULL; + pa_assert(u); + + if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { + pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); return 0; } - r += pa_bytes_to_usec(arg, &s->sample_spec); + u->out_mmap_saved_nfrags += info.blocks; + + bpos = ((u->out_mmap_current + u->out_mmap_saved_nfrags) * u->out_fragment_size) % u->out_hwbuf_size; + + if (bpos <= (size_t) info.ptr) + n = u->out_hwbuf_size - (info.ptr - bpos); + else + n = bpos - info.ptr; + +/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->out_fragment_size, u->out_fragments); */ + + return pa_bytes_to_usec(n, &u->sink->sample_spec); +} + +static pa_usec_t mmap_source_get_latency(struct userdata *u) { + struct count_info info; + size_t bpos, n; + + pa_assert(u); + + if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { + pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); + return 0; + } + + u->in_mmap_saved_nfrags += info.blocks; + bpos = ((u->in_mmap_current + u->in_mmap_saved_nfrags) * u->in_fragment_size) % u->in_hwbuf_size; + + if (bpos <= (size_t) info.ptr) + n = info.ptr - bpos; + else + n = u->in_hwbuf_size - bpos + info.ptr; + +/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->in_fragment_size, u->in_fragments); */ + + return pa_bytes_to_usec(n, &u->source->sample_spec); +} + +static pa_usec_t io_sink_get_latency(struct userdata *u) { + pa_usec_t r = 0; + + pa_assert(u); + + if (u->use_getodelay) { + int arg; + + if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) { + pa_log_info("Device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno)); + u->use_getodelay = 0; + } else + r = pa_bytes_to_usec(arg, &u->sink->sample_spec); + + } + + if (!u->use_getodelay && u->use_getospace) { + struct audio_buf_info info; + + if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { + pa_log_info("Device doesn't support SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno)); + u->use_getospace = 0; + } else + r = pa_bytes_to_usec(info.bytes, &u->sink->sample_spec); + } if (u->memchunk.memblock) - r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); + r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec); return r; } -static pa_usec_t source_get_latency_cb(pa_source *s) { - struct userdata *u = s->userdata; - audio_buf_info info; - assert(s && u && u->source); - if (!u->use_getispace) - return 0; +static pa_usec_t io_source_get_latency(struct userdata *u) { + pa_usec_t r = 0; - if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { - u->use_getispace = 0; - return 0; + pa_assert(u); + + if (u->use_getispace) { + struct audio_buf_info info; + + if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { + pa_log_info("Device doesn't support SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno)); + u->use_getispace = 0; + } else + r = pa_bytes_to_usec(info.bytes, &u->source->sample_spec); } - if (info.bytes <= 0) - return 0; - - return pa_bytes_to_usec(info.bytes, &s->sample_spec); + return r; } -static int sink_get_hw_volume(pa_sink *s) { - struct userdata *u = s->userdata; +static void build_pollfd(struct userdata *u) { + struct pollfd *pollfd; - if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); - s->get_hw_volume = NULL; - return -1; + pa_assert(u); + pa_assert(u->fd >= 0); + + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); + + u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->fd = u->fd; + pollfd->events = 0; + pollfd->revents = 0; +} + +static int suspend(struct userdata *u) { + pa_assert(u); + pa_assert(u->fd >= 0); + + pa_log_info("Suspending..."); + + if (u->out_mmap_memblocks) { + unsigned i; + for (i = 0; i < u->out_nfrags; i++) + if (u->out_mmap_memblocks[i]) { + pa_memblock_unref_fixed(u->out_mmap_memblocks[i]); + u->out_mmap_memblocks[i] = NULL; + } } + if (u->in_mmap_memblocks) { + unsigned i; + for (i = 0; i < u->in_nfrags; i++) + if (u->in_mmap_memblocks[i]) { + pa_memblock_unref_fixed(u->in_mmap_memblocks[i]); + u->in_mmap_memblocks[i] = NULL; + } + } + + if (u->in_mmap && u->in_mmap != MAP_FAILED) { + munmap(u->in_mmap, u->in_hwbuf_size); + u->in_mmap = NULL; + } + + if (u->out_mmap && u->out_mmap != MAP_FAILED) { + munmap(u->out_mmap, u->out_hwbuf_size); + u->out_mmap = NULL; + } + + /* Let's suspend */ + ioctl(u->fd, SNDCTL_DSP_SYNC, NULL); + pa_close(u->fd); + u->fd = -1; + + if (u->rtpoll_item) { + pa_rtpoll_item_free(u->rtpoll_item); + u->rtpoll_item = NULL; + } + + pa_log_info("Device suspended..."); + return 0; } -static int sink_set_hw_volume(pa_sink *s) { - struct userdata *u = s->userdata; +static int unsuspend(struct userdata *u) { + int m; + pa_sample_spec ss, *ss_original; + int frag_size, in_frag_size, out_frag_size; + int in_nfrags, out_nfrags; + struct audio_buf_info info; - if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); - s->set_hw_volume = NULL; + pa_assert(u); + pa_assert(u->fd < 0); + + m = u->mode; + + pa_log_info("Trying resume..."); + + if ((u->fd = pa_oss_open(u->device_name, &m, NULL)) < 0) { + pa_log_warn("Resume failed, device busy (%s)", pa_cstrerror(errno)); return -1; + + if (m != u->mode) + pa_log_warn("Resume failed, couldn't open device with original access mode."); + goto fail; } - return 0; -} + if (u->nfrags >= 2 && u->frag_size >= 1) + if (pa_oss_set_fragments(u->fd, u->nfrags, u->frag_size) < 0) { + pa_log_warn("Resume failed, couldn't set original fragment settings."); + goto fail; + } -static int source_get_hw_volume(pa_source *s) { - struct userdata *u = s->userdata; - - if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); - s->get_hw_volume = NULL; - return -1; + ss = *(ss_original = u->sink ? &u->sink->sample_spec : &u->source->sample_spec); + if (pa_oss_auto_format(u->fd, &ss) < 0 || !pa_sample_spec_equal(&ss, ss_original)) { + pa_log_warn("Resume failed, couldn't set original sample format settings."); + goto fail; } - return 0; -} - -static int source_set_hw_volume(pa_source *s) { - struct userdata *u = s->userdata; - - if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) { - pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); - s->set_hw_volume = NULL; - return -1; + if (ioctl(u->fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) { + pa_log_warn("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno)); + goto fail; } + in_frag_size = out_frag_size = frag_size; + in_nfrags = out_nfrags = u->nfrags; + + if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { + in_frag_size = info.fragsize; + in_nfrags = info.fragstotal; + } + + if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { + out_frag_size = info.fragsize; + out_nfrags = info.fragstotal; + } + + if ((u->source && (in_frag_size != (int) u->in_fragment_size || in_nfrags != (int) u->in_nfrags)) || + (u->sink && (out_frag_size != (int) u->out_fragment_size || out_nfrags != (int) u->out_nfrags))) { + pa_log_warn("Resume failed, input fragment settings don't match."); + goto fail; + } + + if (u->use_mmap) { + if (u->source) { + if ((u->in_mmap = mmap(NULL, u->in_hwbuf_size, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { + pa_log("Resume failed, mmap(): %s", pa_cstrerror(errno)); + goto fail; + } + } + + if (u->sink) { + if ((u->out_mmap = mmap(NULL, u->out_hwbuf_size, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) { + pa_log("Resume failed, mmap(): %s", pa_cstrerror(errno)); + if (u->in_mmap && u->in_mmap != MAP_FAILED) { + munmap(u->in_mmap, u->in_hwbuf_size); + u->in_mmap = NULL; + } + + goto fail; + } + + pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &ss); + } + } + + u->out_mmap_current = u->in_mmap_current = 0; + u->out_mmap_saved_nfrags = u->in_mmap_saved_nfrags = 0; + + pa_assert(!u->rtpoll_item); + + build_pollfd(u); + + if (u->sink) + pa_sink_get_volume(u->sink); + if (u->source) + pa_source_get_volume(u->source); + + pa_log_info("Resumed successfully..."); + return 0; + +fail: + pa_close(u->fd); + u->fd = -1; + return -1; } -int pa__init(pa_core *c, pa_module*m) { +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + int ret; + pa_bool_t do_trigger = FALSE, quick = TRUE; + + switch (code) { + + case PA_SINK_MESSAGE_GET_LATENCY: { + pa_usec_t r = 0; + + if (u->fd >= 0) { + if (u->use_mmap) + r = mmap_sink_get_latency(u); + else + r = io_sink_get_latency(u); + } + + *((pa_usec_t*) data) = r; + + return 0; + } + + case PA_SINK_MESSAGE_SET_STATE: + + switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) { + + case PA_SINK_SUSPENDED: + pa_assert(PA_SINK_OPENED(u->sink->thread_info.state)); + + if (!u->source || u->source_suspended) { + if (suspend(u) < 0) + return -1; + } + + do_trigger = TRUE; + + u->sink_suspended = TRUE; + break; + + case PA_SINK_IDLE: + case PA_SINK_RUNNING: + + if (u->sink->thread_info.state == PA_SINK_INIT) { + do_trigger = TRUE; + quick = u->source && PA_SOURCE_OPENED(u->source->thread_info.state); + } + + if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { + + if (!u->source || u->source_suspended) { + if (unsuspend(u) < 0) + return -1; + quick = FALSE; + } + + do_trigger = TRUE; + + u->out_mmap_current = 0; + u->out_mmap_saved_nfrags = 0; + + u->sink_suspended = FALSE; + } + + break; + + case PA_SINK_UNLINKED: + case PA_SINK_INIT: + ; + } + + break; + + } + + ret = pa_sink_process_msg(o, code, data, offset, chunk); + + if (do_trigger) + trigger(u, quick); + + return ret; +} + +static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SOURCE(o)->userdata; + int ret; + int do_trigger = FALSE, quick = TRUE; + + switch (code) { + + case PA_SOURCE_MESSAGE_GET_LATENCY: { + pa_usec_t r = 0; + + if (u->fd >= 0) { + if (u->use_mmap) + r = mmap_source_get_latency(u); + else + r = io_source_get_latency(u); + } + + *((pa_usec_t*) data) = r; + return 0; + } + + case PA_SOURCE_MESSAGE_SET_STATE: + + switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) { + case PA_SOURCE_SUSPENDED: + pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state)); + + if (!u->sink || u->sink_suspended) { + if (suspend(u) < 0) + return -1; + } + + do_trigger = TRUE; + + u->source_suspended = TRUE; + break; + + case PA_SOURCE_IDLE: + case PA_SOURCE_RUNNING: + + if (u->source->thread_info.state == PA_SOURCE_INIT) { + do_trigger = TRUE; + quick = u->sink && PA_SINK_OPENED(u->sink->thread_info.state); + } + + if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) { + + if (!u->sink || u->sink_suspended) { + if (unsuspend(u) < 0) + return -1; + quick = FALSE; + } + + do_trigger = TRUE; + + u->in_mmap_current = 0; + u->in_mmap_saved_nfrags = 0; + + u->source_suspended = FALSE; + } + break; + + case PA_SOURCE_UNLINKED: + case PA_SOURCE_INIT: + ; + + } + break; + + } + + ret = pa_source_process_msg(o, code, data, offset, chunk); + + if (do_trigger) + trigger(u, quick); + + return ret; +} + +static int sink_get_volume(pa_sink *s) { + struct userdata *u; + int r; + + pa_assert_se(u = s->userdata); + + pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM)); + + if (u->mixer_devmask & SOUND_MASK_VOLUME) + if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_VOLUME, &s->sample_spec, &s->volume)) >= 0) + return r; + + if (u->mixer_devmask & SOUND_MASK_PCM) + if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_PCM, &s->sample_spec, &s->volume)) >= 0) + return r; + + pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); + return -1; +} + +static int sink_set_volume(pa_sink *s) { + struct userdata *u; + int r; + + pa_assert_se(u = s->userdata); + + pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM)); + + if (u->mixer_devmask & SOUND_MASK_VOLUME) + if ((r = pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_VOLUME, &s->sample_spec, &s->volume)) >= 0) + return r; + + if (u->mixer_devmask & SOUND_MASK_PCM) + if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_PCM, &s->sample_spec, &s->volume)) >= 0) + return r; + + pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); + return -1; +} + +static int source_get_volume(pa_source *s) { + struct userdata *u; + int r; + + pa_assert_se(u = s->userdata); + + pa_assert(u->mixer_devmask & (SOUND_MASK_IGAIN|SOUND_MASK_RECLEV)); + + if (u->mixer_devmask & SOUND_MASK_IGAIN) + if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_IGAIN, &s->sample_spec, &s->volume)) >= 0) + return r; + + if (u->mixer_devmask & SOUND_MASK_RECLEV) + if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_RECLEV, &s->sample_spec, &s->volume)) >= 0) + return r; + + pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); + return -1; +} + +static int source_set_volume(pa_source *s) { + struct userdata *u; + int r; + + pa_assert_se(u = s->userdata); + + pa_assert(u->mixer_devmask & (SOUND_MASK_IGAIN|SOUND_MASK_RECLEV)); + + if (u->mixer_devmask & SOUND_MASK_IGAIN) + if ((r = pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_IGAIN, &s->sample_spec, &s->volume)) >= 0) + return r; + + if (u->mixer_devmask & SOUND_MASK_RECLEV) + if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_RECLEV, &s->sample_spec, &s->volume)) >= 0) + return r; + + pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno)); + return -1; +} + +static void thread_func(void *userdata) { + struct userdata *u = userdata; + int write_type = 0, read_type = 0; + unsigned short revents = 0; + + pa_assert(u); + + pa_log_debug("Thread starting up"); + + if (u->core->high_priority) + pa_make_realtime(); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + for (;;) { + int ret; + +/* pa_log("loop"); */ + + /* Render some data and write it to the dsp */ + + if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state) && ((revents & POLLOUT) || u->use_mmap || u->use_getospace)) { + + if (u->use_mmap) { + + if ((ret = mmap_write(u)) < 0) + goto fail; + + revents &= ~POLLOUT; + + if (ret > 0) + continue; + + } else { + ssize_t l; + pa_bool_t loop = FALSE, work_done = FALSE; + + l = u->out_fragment_size; + + if (u->use_getospace) { + audio_buf_info info; + + if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { + pa_log_info("Device doesn't support SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno)); + u->use_getospace = FALSE; + } else { + l = info.bytes; + + /* We loop only if GETOSPACE worked and we + * actually *know* that we can write more than + * one fragment at a time */ + loop = TRUE; + } + } + + /* Round down to multiples of the fragment size, + * because OSS needs that (at least some versions + * do) */ + l = (l/u->out_fragment_size) * u->out_fragment_size; + + /* Hmm, so poll() signalled us that we can read + * something, but GETOSPACE told us there was nothing? + * Hmm, make the best of it, try to read some data, to + * avoid spinning forever. */ + if (l <= 0 && (revents & POLLOUT)) { + l = u->out_fragment_size; + loop = FALSE; + } + + while (l > 0) { + void *p; + ssize_t t; + + if (u->memchunk.length <= 0) + pa_sink_render(u->sink, l, &u->memchunk); + + pa_assert(u->memchunk.length > 0); + + p = pa_memblock_acquire(u->memchunk.memblock); + t = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &write_type); + pa_memblock_release(u->memchunk.memblock); + +/* pa_log("wrote %i bytes of %u", t, l); */ + + pa_assert(t != 0); + + if (t < 0) { + + if (errno == EINTR) + continue; + + else if (errno == EAGAIN) { + pa_log_debug("EAGAIN"); + + revents &= ~POLLOUT; + break; + + } else { + pa_log("Failed to write data to DSP: %s", pa_cstrerror(errno)); + goto fail; + } + + } else { + + u->memchunk.index += t; + u->memchunk.length -= t; + + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + pa_memchunk_reset(&u->memchunk); + } + + l -= t; + + revents &= ~POLLOUT; + work_done = TRUE; + } + + if (!loop) + break; + } + + if (work_done) + continue; + } + } + + /* Try to read some data and pass it on to the source driver. */ + + if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state) && ((revents & POLLIN) || u->use_mmap || u->use_getispace)) { + + if (u->use_mmap) { + + if ((ret = mmap_read(u)) < 0) + goto fail; + + revents &= ~POLLIN; + + if (ret > 0) + continue; + + } else { + + void *p; + ssize_t l; + pa_memchunk memchunk; + pa_bool_t loop = FALSE, work_done = FALSE; + + l = u->in_fragment_size; + + if (u->use_getispace) { + audio_buf_info info; + + if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { + pa_log_info("Device doesn't support SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno)); + u->use_getispace = FALSE; + } else { + l = info.bytes; + loop = TRUE; + } + } + + l = (l/u->in_fragment_size) * u->in_fragment_size; + + if (l <= 0 && (revents & POLLIN)) { + l = u->in_fragment_size; + loop = FALSE; + } + + while (l > 0) { + ssize_t t, k; + + pa_assert(l > 0); + + memchunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1); + + k = pa_memblock_get_length(memchunk.memblock); + + if (k > l) + k = l; + + k = (k/u->frame_size)*u->frame_size; + + p = pa_memblock_acquire(memchunk.memblock); + t = pa_read(u->fd, p, k, &read_type); + pa_memblock_release(memchunk.memblock); + + pa_assert(t != 0); /* EOF cannot happen */ + +/* pa_log("read %i bytes of %u", t, l); */ + + if (t < 0) { + pa_memblock_unref(memchunk.memblock); + + if (errno == EINTR) + continue; + + else if (errno == EAGAIN) { + pa_log_debug("EAGAIN"); + + revents &= ~POLLIN; + break; + + } else { + pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno)); + goto fail; + } + + } else { + memchunk.index = 0; + memchunk.length = t; + + pa_source_post(u->source, &memchunk); + pa_memblock_unref(memchunk.memblock); + + l -= t; + + revents &= ~POLLIN; + work_done = TRUE; + } + + if (!loop) + break; + } + + if (work_done) + continue; + } + } + +/* pa_log("loop2 revents=%i", revents); */ + + if (u->rtpoll_item) { + struct pollfd *pollfd; + + pa_assert(u->fd >= 0); + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->events = + ((u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) ? POLLIN : 0) | + ((u->sink && PA_SINK_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0); + } + + /* Hmm, nothing to do. Let's sleep */ + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) + goto fail; + + if (ret == 0) + goto finish; + + if (u->rtpoll_item) { + struct pollfd *pollfd; + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + + if (pollfd->revents & ~(POLLOUT|POLLIN)) { + pa_log("DSP shutdown."); + goto fail; + } + + revents = pollfd->revents; + } else + revents = 0; + } + +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("Thread shutting down"); +} + +int pa__init(pa_module*m) { + struct audio_buf_info info; struct userdata *u = NULL; - const char *p; + const char *dev; int fd = -1; - int nfrags, frag_size, in_frag_size, out_frag_size; - int mode; - int record = 1, playback = 1; + int nfrags, frag_size; + int mode, caps; + int record = 1, playback = 1, use_mmap = 1; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; char hwdesc[64], *t; const char *name; - char *name_buf = NULL; int namereg_fail; - assert(c); - assert(m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments."); + pa_log("Failed to parse module arguments."); goto fail; } @@ -380,36 +1159,52 @@ int pa__init(pa_core *c, pa_module*m) { } if (!playback && !record) { - pa_log("neither playback nor record enabled for device."); + pa_log("Neither playback nor record enabled for device."); goto fail; } - mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); + mode = (playback && record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); - ss = c->default_sample_spec; + ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_OSS) < 0) { - pa_log("failed to parse sample specification or channel map"); + pa_log("Failed to parse sample specification or channel map"); goto fail; } - /* Fix latency to 100ms */ - nfrags = 12; - frag_size = pa_bytes_per_second(&ss)/128; + nfrags = m->core->default_n_fragments; + frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss); + if (frag_size <= 0) + frag_size = pa_frame_size(&ss); if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) { - pa_log("failed to parse fragments arguments"); + pa_log("Failed to parse fragments arguments"); goto fail; } - if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, NULL)) < 0) + if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) { + pa_log("Failed to parse mmap argument."); + goto fail; + } + + if ((fd = pa_oss_open(dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0) goto fail; - if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0) - pa_log_info("hardware name is '%s'.", hwdesc); + if (use_mmap && (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER))) { + pa_log_info("OSS device not mmap capable, falling back to UNIX read/write mode."); + use_mmap = 0; + } + + if (use_mmap && mode == O_WRONLY) { + pa_log_info("Device opened for playback only, cannot do memory mapping, falling back to UNIX write() mode."); + use_mmap = 0; + } + + if (pa_oss_get_hw_description(dev, hwdesc, sizeof(hwdesc)) >= 0) + pa_log_info("Hardware name is '%s'.", hwdesc); else hwdesc[0] = 0; - pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); + pa_log_info("Device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); if (nfrags >= 2 && frag_size >= 1) if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0) @@ -422,152 +1217,282 @@ int pa__init(pa_core *c, pa_module*m) { pa_log("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno)); goto fail; } - assert(frag_size); - in_frag_size = out_frag_size = frag_size; + pa_assert(frag_size > 0); - u = pa_xmalloc(sizeof(struct userdata)); - u->core = c; - u->use_getospace = u->use_getispace = 0; + u = pa_xnew0(struct userdata, 1); + u->core = m->core; + u->module = m; + m->userdata = u; + u->fd = fd; + u->mixer_fd = -1; + u->use_getospace = u->use_getispace = 1; + u->use_getodelay = 1; + u->mode = mode; + u->frame_size = pa_frame_size(&ss); + u->device_name = pa_xstrdup(dev); + u->in_nfrags = u->out_nfrags = u->nfrags = nfrags; + u->out_fragment_size = u->in_fragment_size = u->frag_size = frag_size; + u->use_mmap = use_mmap; + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); + u->rtpoll_item = NULL; + build_pollfd(u); if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) { - pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize); - in_frag_size = info.fragsize; + pa_log_info("Input -- %u fragments of size %u.", info.fragstotal, info.fragsize); + u->in_fragment_size = info.fragsize; + u->in_nfrags = info.fragstotal; u->use_getispace = 1; } if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) { - pa_log_info("output -- %u fragments of size %u.", info.fragstotal, info.fragsize); - out_frag_size = info.fragsize; + pa_log_info("Output -- %u fragments of size %u.", info.fragstotal, info.fragsize); + u->out_fragment_size = info.fragsize; + u->out_nfrags = info.fragstotal; u->use_getospace = 1; } + u->in_hwbuf_size = u->in_nfrags * u->in_fragment_size; + u->out_hwbuf_size = u->out_nfrags * u->out_fragment_size; + if (mode != O_WRONLY) { + char *name_buf = NULL; + + if (use_mmap) { + if ((u->in_mmap = mmap(NULL, u->in_hwbuf_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + pa_log_warn("mmap(PROT_READ) failed, reverting to non-mmap mode: %s", pa_cstrerror(errno)); + use_mmap = u->use_mmap = 0; + u->in_mmap = NULL; + } else + pa_log_debug("Successfully mmap()ed input buffer."); + } + if ((name = pa_modargs_get_value(ma, "source_name", NULL))) namereg_fail = 1; else { - name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(p)); + name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(dev)); namereg_fail = 0; } - if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map))) + u->source = pa_source_new(m->core, __FILE__, name, namereg_fail, &ss, &map); + pa_xfree(name_buf); + if (!u->source) { + pa_log("Failed to create source object"); goto fail; + } + u->source->parent.process_msg = source_process_msg; u->source->userdata = u; - u->source->notify = source_notify_cb; - u->source->get_latency = source_get_latency_cb; - u->source->get_hw_volume = source_get_hw_volume; - u->source->set_hw_volume = source_set_hw_volume; - pa_source_set_owner(u->source, m); - pa_source_set_description(u->source, t = pa_sprintf_malloc("OSS PCM on %s%s%s%s", - p, - hwdesc[0] ? " (" : "", - hwdesc[0] ? hwdesc : "", - hwdesc[0] ? ")" : "")); - pa_xfree(t); - u->source->is_hardware = 1; - } else - u->source = NULL; - pa_xfree(name_buf); - name_buf = NULL; + pa_source_set_module(u->source, m); + pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); + pa_source_set_rtpoll(u->source, u->rtpoll); + pa_source_set_description(u->source, t = pa_sprintf_malloc( + "OSS PCM on %s%s%s%s%s", + dev, + hwdesc[0] ? " (" : "", + hwdesc[0] ? hwdesc : "", + hwdesc[0] ? ")" : "", + use_mmap ? " via DMA" : "")); + pa_xfree(t); + u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY; + u->source->refresh_volume = TRUE; + + if (use_mmap) + u->in_mmap_memblocks = pa_xnew0(pa_memblock*, u->in_nfrags); + } if (mode != O_RDONLY) { + char *name_buf = NULL; + + if (use_mmap) { + if ((u->out_mmap = mmap(NULL, u->out_hwbuf_size, PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { + if (mode == O_RDWR) { + pa_log_debug("mmap() failed for input. Changing to O_WRONLY mode."); + mode = O_WRONLY; + goto go_on; + } else { + pa_log_warn("mmap(PROT_WRITE) failed, reverting to non-mmap mode: %s", pa_cstrerror(errno)); + u->use_mmap = (use_mmap = FALSE); + u->out_mmap = NULL; + } + } else { + pa_log_debug("Successfully mmap()ed output buffer."); + pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &ss); + } + } + if ((name = pa_modargs_get_value(ma, "sink_name", NULL))) namereg_fail = 1; else { - name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p)); + name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(dev)); namereg_fail = 0; } - if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map))) + u->sink = pa_sink_new(m->core, __FILE__, name, namereg_fail, &ss, &map); + pa_xfree(name_buf); + if (!u->sink) { + pa_log("Failed to create sink object"); goto fail; + } - u->sink->get_latency = sink_get_latency_cb; - u->sink->get_hw_volume = sink_get_hw_volume; - u->sink->set_hw_volume = sink_set_hw_volume; + u->sink->parent.process_msg = sink_process_msg; u->sink->userdata = u; - pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("OSS PCM on %s%s%s%s", - p, - hwdesc[0] ? " (" : "", - hwdesc[0] ? hwdesc : "", - hwdesc[0] ? ")" : "")); + + pa_sink_set_module(u->sink, m); + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc( + "OSS PCM on %s%s%s%s%s", + dev, + hwdesc[0] ? " (" : "", + hwdesc[0] ? hwdesc : "", + hwdesc[0] ? ")" : "", + use_mmap ? " via DMA" : "")); pa_xfree(t); - u->sink->is_hardware = 1; - } else - u->sink = NULL; + u->sink->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY; + u->sink->refresh_volume = TRUE; - pa_xfree(name_buf); - name_buf = NULL; + if (use_mmap) + u->out_mmap_memblocks = pa_xnew0(pa_memblock*, u->out_nfrags); + } - assert(u->source || u->sink); + if ((u->mixer_fd = pa_oss_open_mixer_for_device(u->device_name)) >= 0) { + int do_close = 1; + u->mixer_devmask = 0; - u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : -1); - assert(u->io); - pa_iochannel_set_callback(u->io, io_callback, u); - u->fd = fd; + if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &u->mixer_devmask) < 0) + pa_log_warn("SOUND_MIXER_READ_DEVMASK failed: %s", pa_cstrerror(errno)); - u->memchunk.memblock = NULL; - u->memchunk.length = 0; - u->sample_size = pa_frame_size(&ss); + else { + if (u->sink && (u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM))) { + pa_log_debug("Found hardware mixer track for playback."); + u->sink->flags |= PA_SINK_HW_VOLUME_CTRL; + u->sink->get_volume = sink_get_volume; + u->sink->set_volume = sink_set_volume; + do_close = 0; + } - u->out_fragment_size = out_frag_size; - u->in_fragment_size = in_frag_size; - u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length = u->out_fragment_size); - assert(u->silence.memblock); - pa_silence_memblock(u->silence.memblock, &ss); - u->silence.index = 0; + if (u->source && (u->mixer_devmask & (SOUND_MASK_RECLEV|SOUND_MASK_IGAIN))) { + pa_log_debug("Found hardware mixer track for recording."); + u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL; + u->source->get_volume = source_get_volume; + u->source->set_volume = source_set_volume; + do_close = 0; + } + } - u->module = m; - m->userdata = u; + if (do_close) { + pa_close(u->mixer_fd); + u->mixer_fd = -1; + } + } - pa_modargs_free(ma); +go_on: - /* - * Some crappy drivers do not start the recording until we read something. - * Without this snippet, poll will never register the fd as ready. - */ - if (u->source) { - char *buf = pa_xnew(char, u->sample_size); - pa_read(u->fd, buf, u->sample_size, NULL); - pa_xfree(buf); + pa_assert(u->source || u->sink); + + pa_memchunk_reset(&u->memchunk); + + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; } /* Read mixer settings */ - if (u->source) - source_get_hw_volume(u->source); + if (u->sink && u->sink->get_volume) + sink_get_volume(u->sink); + if (u->source && u->source->get_volume) + source_get_volume(u->source); + if (u->sink) - sink_get_hw_volume(u->sink); + pa_sink_put(u->sink); + if (u->source) + pa_source_put(u->source); + + pa_modargs_free(ma); return 0; fail: - if (fd >= 0) - close(fd); + + if (u) + pa__done(m); + else if (fd >= 0) + pa_close(fd); if (ma) pa_modargs_free(ma); - pa_xfree(name_buf); - return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c); - assert(m); + pa_assert(m); if (!(u = m->userdata)) return; - clear_up(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); + } + + pa_thread_mq_done(&u->thread_mq); + + if (u->sink) + pa_sink_unref(u->sink); + + if (u->source) + pa_source_unref(u->source); if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); - if (u->silence.memblock) - pa_memblock_unref(u->silence.memblock); + + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->out_mmap_memblocks) { + unsigned i; + for (i = 0; i < u->out_nfrags; i++) + if (u->out_mmap_memblocks[i]) + pa_memblock_unref_fixed(u->out_mmap_memblocks[i]); + pa_xfree(u->out_mmap_memblocks); + } + + if (u->in_mmap_memblocks) { + unsigned i; + for (i = 0; i < u->in_nfrags; i++) + if (u->in_mmap_memblocks[i]) + pa_memblock_unref_fixed(u->in_mmap_memblocks[i]); + pa_xfree(u->in_mmap_memblocks); + } + + if (u->in_mmap && u->in_mmap != MAP_FAILED) + munmap(u->in_mmap, u->in_hwbuf_size); + + if (u->out_mmap && u->out_mmap != MAP_FAILED) + munmap(u->out_mmap, u->out_hwbuf_size); + + if (u->fd >= 0) + pa_close(u->fd); + + if (u->mixer_fd >= 0) + pa_close(u->mixer_fd); + + pa_xfree(u->device_name); pa_xfree(u); } diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 170b046ef..757484745 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -28,22 +28,25 @@ #include #include #include -#include #include #include #include #include #include +#include +#include #include #include -#include #include #include #include #include #include +#include +#include +#include #include "module-pipe-sink-symdef.h" @@ -58,20 +61,24 @@ PA_MODULE_USAGE( "rate=" "channel_map=") -#define DEFAULT_FIFO_NAME "/tmp/music.output" +#define DEFAULT_FILE_NAME "/tmp/music.output" #define DEFAULT_SINK_NAME "fifo_output" struct userdata { pa_core *core; + pa_module *module; + pa_sink *sink; + + pa_thread *thread; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; char *filename; - - pa_sink *sink; - pa_iochannel *io; - pa_defer_event *defer_event; + int fd; pa_memchunk memchunk; - pa_module *module; + + pa_rtpoll_item *rtpoll_item; }; static const char* const valid_modargs[] = { @@ -84,133 +91,191 @@ static const char* const valid_modargs[] = { NULL }; -static void do_write(struct userdata *u) { - ssize_t r; - assert(u); +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; - u->core->mainloop->defer_enable(u->defer_event, 0); + switch (code) { - if (!pa_iochannel_is_writable(u->io)) - return; + case PA_SINK_MESSAGE_GET_LATENCY: { + size_t n = 0; + int l; - pa_module_set_used(u->module, pa_sink_used_by(u->sink)); +#ifdef TIOCINQ + if (ioctl(u->fd, TIOCINQ, &l) >= 0 && l > 0) + n = (size_t) l; +#endif - if (!u->memchunk.length) - if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0) - return; + n += u->memchunk.length; - assert(u->memchunk.memblock && u->memchunk.length); - - if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) { - pa_log("write(): %s", pa_cstrerror(errno)); - return; + *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec); + break; + } } - u->memchunk.index += r; - u->memchunk.length -= r; + return pa_sink_process_msg(o, code, data, offset, chunk); +} - if (u->memchunk.length <= 0) { - pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; +static void thread_func(void *userdata) { + struct userdata *u = userdata; + int write_type = 0; + + pa_assert(u); + + pa_log_debug("Thread starting up"); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + for (;;) { + struct pollfd *pollfd; + int ret; + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + + /* Render some data and write it to the fifo */ + if (u->sink->thread_info.state == PA_SINK_RUNNING && pollfd->revents) { + ssize_t l; + void *p; + + if (u->memchunk.length <= 0) + pa_sink_render(u->sink, PIPE_BUF, &u->memchunk); + + pa_assert(u->memchunk.length > 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; + } + + } 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; + } + } + + /* Hmm, nothing to do. Let's sleep */ + pollfd->events = u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0; + + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) + goto fail; + + if (ret == 0) + goto finish; + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + + if (pollfd->revents & ~POLLOUT) { + pa_log("FIFO shutdown."); + goto fail; + } } + +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("Thread shutting down"); } -static void notify_cb(pa_sink*s) { - struct userdata *u = s->userdata; - assert(s && u); - - if (pa_iochannel_is_writable(u->io)) - u->core->mainloop->defer_enable(u->defer_event, 1); -} - -static pa_usec_t get_latency_cb(pa_sink *s) { - struct userdata *u = s->userdata; - assert(s && u); - - return u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0; -} - -static void defer_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event*e, void *userdata) { - struct userdata *u = userdata; - assert(u); - do_write(u); -} - -static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { - struct userdata *u = userdata; - assert(u); - do_write(u); -} - -int pa__init(pa_core *c, pa_module*m) { - struct userdata *u = NULL; +int pa__init(pa_module*m) { + struct userdata *u; struct stat st; - const char *p; - int fd = -1; pa_sample_spec ss; pa_channel_map map; - pa_modargs *ma = NULL; + pa_modargs *ma; char *t; + struct pollfd *pollfd; - assert(c && m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments"); + pa_log("Failed to parse module arguments."); goto fail; } - ss = c->default_sample_spec; + ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { - pa_log("invalid sample format specification"); + pa_log("Invalid sample format specification or channel map"); goto fail; } - mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); + u = pa_xnew0(struct userdata, 1); + u->core = m->core; + u->module = m; + m->userdata = u; + pa_memchunk_reset(&u->memchunk); + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); - if ((fd = open(p, O_RDWR)) < 0) { - pa_log("open('%s'): %s", p, pa_cstrerror(errno)); + u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME)); + + mkfifo(u->filename, 0666); + if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) { + pa_log("open('%s'): %s", u->filename, pa_cstrerror(errno)); goto fail; } - pa_fd_set_cloexec(fd, 1); + pa_make_fd_cloexec(u->fd); + pa_make_fd_nonblock(u->fd); - if (fstat(fd, &st) < 0) { - pa_log("fstat('%s'): %s", p, pa_cstrerror(errno)); + if (fstat(u->fd, &st) < 0) { + pa_log("fstat('%s'): %s", u->filename, pa_cstrerror(errno)); goto fail; } if (!S_ISFIFO(st.st_mode)) { - pa_log("'%s' is not a FIFO.", p); + pa_log("'%s' is not a FIFO.", u->filename); goto fail; } - u = pa_xmalloc0(sizeof(struct userdata)); - u->filename = pa_xstrdup(p); - u->core = c; - u->module = m; - m->userdata = u; - - if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { - pa_log("failed to create sink."); + if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) { + pa_log("Failed to create sink."); goto fail; } - u->sink->notify = notify_cb; - u->sink->get_latency = get_latency_cb; + + u->sink->parent.process_msg = sink_process_msg; u->sink->userdata = u; - pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", p)); + u->sink->flags = PA_SINK_LATENCY; + + pa_sink_set_module(u->sink, m); + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", u->filename)); pa_xfree(t); - u->io = pa_iochannel_new(c->mainloop, -1, fd); - assert(u->io); - pa_iochannel_set_callback(u->io, io_callback, u); + u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->fd = u->fd; + pollfd->events = pollfd->revents = 0; - u->memchunk.memblock = NULL; - u->memchunk.length = 0; + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } - u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u); - assert(u->defer_event); - c->mainloop->defer_enable(u->defer_event, 0); + pa_sink_put(u->sink); pa_modargs_free(ma); @@ -220,32 +285,48 @@ fail: if (ma) pa_modargs_free(ma); - if (fd >= 0) - close(fd); - - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c && m); + + pa_assert(m); if (!(u = m->userdata)) return; + if (u->sink) + pa_sink_unlink(u->sink); + + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } + + pa_thread_mq_done(&u->thread_mq); + + if (u->sink) + pa_sink_unref(u->sink); + if (u->memchunk.memblock) - pa_memblock_unref(u->memchunk.memblock); + pa_memblock_unref(u->memchunk.memblock); - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - pa_iochannel_free(u->io); - u->core->mainloop->defer_free(u->defer_event); + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); - assert(u->filename); - unlink(u->filename); - pa_xfree(u->filename); + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->filename) { + unlink(u->filename); + pa_xfree(u->filename); + } + + if (u->fd >= 0) + pa_assert_se(pa_close(u->fd) == 0); pa_xfree(u); } diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index 56c721b0f..45708c687 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -28,22 +28,24 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include -#include #include #include #include #include #include +#include +#include +#include #include "module-pipe-source-symdef.h" @@ -58,18 +60,24 @@ PA_MODULE_USAGE( "rate= " "channel_map=") -#define DEFAULT_FIFO_NAME "/tmp/music.input" +#define DEFAULT_FILE_NAME "/tmp/music.input" #define DEFAULT_SOURCE_NAME "fifo_input" struct userdata { pa_core *core; + pa_module *module; + pa_source *source; + + pa_thread *thread; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; char *filename; + int fd; - pa_source *source; - pa_iochannel *io; - pa_module *module; - pa_memchunk chunk; + pa_memchunk memchunk; + + pa_rtpoll_item *rtpoll_item; }; static const char* const valid_modargs[] = { @@ -82,109 +90,168 @@ static const char* const valid_modargs[] = { NULL }; -static void do_read(struct userdata *u) { - ssize_t r; - pa_memchunk chunk; - assert(u); - - if (!pa_iochannel_is_readable(u->io)) - return; - - pa_module_set_used(u->module, pa_idxset_size(u->source->outputs)); - - if (!u->chunk.memblock) { - u->chunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF); - u->chunk.index = chunk.length = 0; - } - - assert(u->chunk.memblock && u->chunk.memblock->length > u->chunk.index); - if ((r = pa_iochannel_read(u->io, (uint8_t*) u->chunk.memblock->data + u->chunk.index, u->chunk.memblock->length - u->chunk.index)) <= 0) { - pa_log("read(): %s", pa_cstrerror(errno)); - return; - } - - u->chunk.length = r; - pa_source_post(u->source, &u->chunk); - u->chunk.index += r; - - if (u->chunk.index >= u->chunk.memblock->length) { - u->chunk.index = u->chunk.length = 0; - pa_memblock_unref(u->chunk.memblock); - u->chunk.memblock = NULL; - } -} - -static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) { +static void thread_func(void *userdata) { struct userdata *u = userdata; - assert(u); - do_read(u); + int read_type = 0; + + pa_assert(u); + + pa_log_debug("Thread starting up"); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + for (;;) { + int ret; + struct pollfd *pollfd; + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + + /* Try to read some data and pass it on to the source driver */ + if (u->source->thread_info.state == PA_SOURCE_RUNNING && pollfd->revents) { + ssize_t l; + void *p; + + if (!u->memchunk.memblock) { + u->memchunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF); + u->memchunk.index = u->memchunk.length = 0; + } + + pa_assert(pa_memblock_get_length(u->memchunk.memblock) > u->memchunk.index); + + p = pa_memblock_acquire(u->memchunk.memblock); + l = pa_read(u->fd, (uint8_t*) p + u->memchunk.index, pa_memblock_get_length(u->memchunk.memblock) - u->memchunk.index, &read_type); + pa_memblock_release(u->memchunk.memblock); + + pa_assert(l != 0); /* EOF cannot happen, since we opened the fifo for both reading and writing */ + + if (l < 0) { + + if (errno == EINTR) + continue; + else if (errno != EAGAIN) { + pa_log("Faile to read data from FIFO: %s", pa_cstrerror(errno)); + goto fail; + } + + } else { + + u->memchunk.length = l; + pa_source_post(u->source, &u->memchunk); + u->memchunk.index += l; + + if (u->memchunk.index >= pa_memblock_get_length(u->memchunk.memblock)) { + pa_memblock_unref(u->memchunk.memblock); + pa_memchunk_reset(&u->memchunk); + } + + pollfd->revents = 0; + } + } + + /* Hmm, nothing to do. Let's sleep */ + pollfd->events = u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0; + + if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0) + goto fail; + + if (ret == 0) + goto finish; + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + if (pollfd->revents & ~POLLIN) { + pa_log("FIFO shutdown."); + goto fail; + } + } + +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("Thread shutting down"); } -int pa__init(pa_core *c, pa_module*m) { - struct userdata *u = NULL; +int pa__init(pa_module*m) { + struct userdata *u; struct stat st; - const char *p; - int fd = -1; pa_sample_spec ss; pa_channel_map map; - pa_modargs *ma = NULL; + pa_modargs *ma; char *t; + struct pollfd *pollfd; - assert(c && m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments"); + pa_log("failed to parse module arguments."); goto fail; } - ss = c->default_sample_spec; + ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log("invalid sample format specification or channel map"); goto fail; } - mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777); + u = pa_xnew0(struct userdata, 1); + u->core = m->core; + u->module = m; + m->userdata = u; + pa_memchunk_reset(&u->memchunk); + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); - if ((fd = open(p, O_RDWR)) < 0) { - pa_log("open('%s'): %s", p, pa_cstrerror(errno)); + u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME)); + + mkfifo(u->filename, 0666); + if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) { + pa_log("open('%s'): %s", u->filename, pa_cstrerror(errno)); goto fail; } - pa_fd_set_cloexec(fd, 1); + pa_make_fd_cloexec(u->fd); + pa_make_fd_nonblock(u->fd); - if (fstat(fd, &st) < 0) { - pa_log("fstat('%s'): %s", p, pa_cstrerror(errno)); + if (fstat(u->fd, &st) < 0) { + pa_log("fstat('%s'): %s",u->filename, pa_cstrerror(errno)); goto fail; } if (!S_ISFIFO(st.st_mode)) { - pa_log("'%s' is not a FIFO.", p); + pa_log("'%s' is not a FIFO.", u->filename); goto fail; } - u = pa_xmalloc0(sizeof(struct userdata)); - - u->filename = pa_xstrdup(p); - u->core = c; - - if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { - pa_log("failed to create source."); + if (!(u->source = pa_source_new(m->core, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) { + pa_log("Failed to create source."); goto fail; } + u->source->userdata = u; - pa_source_set_owner(u->source, m); - pa_source_set_description(u->source, t = pa_sprintf_malloc("Unix FIFO source '%s'", p)); + u->source->flags = 0; + + pa_source_set_module(u->source, m); + pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); + pa_source_set_rtpoll(u->source, u->rtpoll); + pa_source_set_description(u->source, t = pa_sprintf_malloc("Unix FIFO source '%s'", u->filename)); pa_xfree(t); - u->io = pa_iochannel_new(c->mainloop, fd, -1); - assert(u->io); - pa_iochannel_set_callback(u->io, io_callback, u); + u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->fd = u->fd; + pollfd->events = pollfd->revents = 0; - u->chunk.memblock = NULL; - u->chunk.index = u->chunk.length = 0; + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } - u->module = m; - m->userdata = u; + pa_source_put(u->source); pa_modargs_free(ma); @@ -194,31 +261,48 @@ fail: if (ma) pa_modargs_free(ma); - if (fd >= 0) - close(fd); - - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c && m); + + pa_assert(m); if (!(u = m->userdata)) return; - if (u->chunk.memblock) - pa_memblock_unref(u->chunk.memblock); + if (u->source) + pa_source_unlink(u->source); - pa_source_disconnect(u->source); - pa_source_unref(u->source); - pa_iochannel_free(u->io); + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } - assert(u->filename); - unlink(u->filename); - pa_xfree(u->filename); + pa_thread_mq_done(&u->thread_mq); + + if (u->source) + pa_source_unref(u->source); + + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->filename) { + unlink(u->filename); + pa_xfree(u->filename); + } + + if (u->fd >= 0) + pa_assert_se(pa_close(u->fd) == 0); pa_xfree(u); } diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 5c8733fb4..6bd780797 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -43,10 +42,9 @@ #include #endif -#include "../pulsecore/winsock.h" - #include +#include #include #include #include @@ -154,7 +152,6 @@ #define protocol_free pa_protocol_esound_free #define TCPWRAP_SERVICE "esound" #define IPV4_PORT ESD_DEFAULT_PORT - #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME #define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", #ifdef USE_TCP_SOCKETS #include "module-esound-protocol-tcp-symdef.h" @@ -205,10 +202,9 @@ struct userdata { #endif }; -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_modargs *ma = NULL; int ret = -1; - struct userdata *u = NULL; #if defined(USE_TCP_SOCKETS) @@ -219,9 +215,13 @@ int pa__init(pa_core *c, pa_module*m) { pa_socket_server *s; int r; char tmp[PATH_MAX]; + +#if defined(USE_PROTOCOL_ESOUND) + char tmp2[PATH_MAX]; +#endif #endif - assert(c && m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); @@ -239,22 +239,22 @@ int pa__init(pa_core *c, pa_module*m) { listen_on = pa_modargs_get_value(ma, "listen", NULL); if (listen_on) { - s_ipv6 = pa_socket_server_new_ipv6_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); - s_ipv4 = pa_socket_server_new_ipv4_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE); + s_ipv6 = pa_socket_server_new_ipv6_string(m->core->mainloop, listen_on, port, TCPWRAP_SERVICE); + s_ipv4 = pa_socket_server_new_ipv4_string(m->core->mainloop, listen_on, port, TCPWRAP_SERVICE); } else { - s_ipv6 = pa_socket_server_new_ipv6_any(c->mainloop, port, TCPWRAP_SERVICE); - s_ipv4 = pa_socket_server_new_ipv4_any(c->mainloop, port, TCPWRAP_SERVICE); + s_ipv6 = pa_socket_server_new_ipv6_any(m->core->mainloop, port, TCPWRAP_SERVICE); + s_ipv4 = pa_socket_server_new_ipv4_any(m->core->mainloop, port, TCPWRAP_SERVICE); } if (!s_ipv4 && !s_ipv6) goto fail; if (s_ipv4) - if (!(u->protocol_ipv4 = protocol_new(c, s_ipv4, m, ma))) + if (!(u->protocol_ipv4 = protocol_new(m->core, s_ipv4, m, ma))) pa_socket_server_unref(s_ipv4); if (s_ipv6) - if (!(u->protocol_ipv6 = protocol_new(c, s_ipv6, m, ma))) + if (!(u->protocol_ipv6 = protocol_new(m->core, s_ipv6, m, ma))) pa_socket_server_unref(s_ipv6); if (!u->protocol_ipv4 && !u->protocol_ipv6) @@ -262,18 +262,23 @@ int pa__init(pa_core *c, pa_module*m) { #else - pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET), tmp, sizeof(tmp)); - u->socket_path = pa_xstrdup(tmp); - #if defined(USE_PROTOCOL_ESOUND) + snprintf(tmp2, sizeof(tmp2), "/tmp/.esd-%lu/socket", (unsigned long) getuid()); + pa_runtime_path(pa_modargs_get_value(ma, "socket", tmp2), tmp, sizeof(tmp)); + u->socket_path = pa_xstrdup(tmp); + /* This socket doesn't reside in our own runtime dir but in * /tmp/.esd/, hence we have to create the dir first */ - if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) { + if (pa_make_secure_parent_dir(u->socket_path, m->core->is_system_instance ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) { pa_log("Failed to create socket directory '%s': %s\n", u->socket_path, pa_cstrerror(errno)); goto fail; } + +#else + pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET), tmp, sizeof(tmp)); + u->socket_path = pa_xstrdup(tmp); #endif if ((r = pa_unix_socket_remove_stale(tmp)) < 0) { @@ -284,10 +289,10 @@ int pa__init(pa_core *c, pa_module*m) { if (r) pa_log("Removed stale UNIX socket '%s'.", tmp); - if (!(s = pa_socket_server_new_unix(c->mainloop, tmp))) + if (!(s = pa_socket_server_new_unix(m->core->mainloop, tmp))) goto fail; - if (!(u->protocol_unix = protocol_new(c, s, m, ma))) + if (!(u->protocol_unix = protocol_new(m->core, s, m, ma))) goto fail; #endif @@ -333,11 +338,10 @@ fail: goto finish; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c); - assert(m); + pa_assert(m); u = m->userdata; @@ -358,7 +362,6 @@ void pa__done(pa_core *c, pa_module*m) { } #endif - pa_xfree(u->socket_path); #endif diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c new file mode 100644 index 000000000..e863c0c37 --- /dev/null +++ b/src/modules/module-remap-sink.c @@ -0,0 +1,334 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-remap-sink-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Virtual channel remapping sink") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE( + "sink_name= " + "master= " + "master_channel_map= " + "format= " + "channels= " + "rate= " + "channel_map=") + +struct userdata { + pa_core *core; + pa_module *module; + + pa_sink *sink, *master; + pa_sink_input *sink_input; + + pa_memchunk memchunk; +}; + +static const char* const valid_modargs[] = { + "sink_name", + "master", + "master_channel_map", + "rate", + "format", + "channels", + "channel_map", + NULL +}; + +/* Called from I/O thread context */ +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + + switch (code) { + + case PA_SINK_MESSAGE_GET_LATENCY: { + pa_usec_t usec = 0; + + if (PA_MSGOBJECT(u->master)->process_msg(PA_MSGOBJECT(u->master), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0) + usec = 0; + + *((pa_usec_t*) data) = usec + pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec); + return 0; + } + } + + return pa_sink_process_msg(o, code, data, offset, chunk); +} + +/* Called from main context */ +static int sink_set_state(pa_sink *s, pa_sink_state_t state) { + struct userdata *u; + + pa_sink_assert_ref(s); + pa_assert_se(u = s->userdata); + + if (PA_SINK_LINKED(state) && u->sink_input && PA_SINK_INPUT_LINKED(pa_sink_input_get_state(u->sink_input))) + pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED); + + return 0; +} + +/* Called from I/O thread context */ +static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK_INPUT(o)->userdata; + + switch (code) { + case PA_SINK_INPUT_MESSAGE_GET_LATENCY: + *((pa_usec_t*) data) = pa_bytes_to_usec(u->memchunk.length, &u->sink_input->sample_spec); + + /* Fall through, the default handler will add in the extra + * latency added by the resampler */ + break; + } + + return pa_sink_input_process_msg(o, code, data, offset, chunk); +} + +/* Called from I/O thread context */ +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + if (!u->memchunk.memblock) + pa_sink_render(u->sink, length, &u->memchunk); + + pa_assert(u->memchunk.memblock); + *chunk = u->memchunk; + pa_memblock_ref(chunk->memblock); + return 0; +} + +/* Called from I/O thread context */ +static void sink_input_drop_cb(pa_sink_input *i, size_t length) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + pa_assert(length > 0); + + if (u->memchunk.memblock) { + + if (length < u->memchunk.length) { + u->memchunk.index += length; + u->memchunk.length -= length; + return; + } + + pa_memblock_unref(u->memchunk.memblock); + length -= u->memchunk.length; + pa_memchunk_reset(&u->memchunk); + } + + if (length > 0) + pa_sink_skip(u->sink, length); +} + +/* Called from I/O thread context */ +static void sink_input_detach_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_detach_within_thread(u->sink); +} + +/* Called from I/O thread context */ +static void sink_input_attach_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_set_asyncmsgq(u->sink, i->sink->asyncmsgq); + pa_sink_set_rtpoll(u->sink, i->sink->rtpoll); + + pa_sink_attach_within_thread(u->sink); +} + +/* Called from main context */ +static void sink_input_kill_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_input_unlink(u->sink_input); + pa_sink_input_unref(u->sink_input); + u->sink_input = NULL; + + pa_sink_unlink(u->sink); + pa_sink_unref(u->sink); + u->sink = NULL; + + pa_module_unload_request(u->module); +} + +int pa__init(pa_module*m) { + struct userdata *u; + pa_sample_spec ss; + pa_channel_map sink_map, stream_map; + pa_modargs *ma; + char *t; + pa_sink *master; + pa_sink_input_new_data data; + char *default_sink_name = NULL; + + pa_assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments."); + goto fail; + } + + if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK, 1))) { + pa_log("Master sink not found"); + goto fail; + } + + ss = master->sample_spec; + sink_map = master->channel_map; + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &sink_map, PA_CHANNEL_MAP_DEFAULT) < 0) { + pa_log("Invalid sample format specification or channel map"); + goto fail; + } + + stream_map = sink_map; + if (pa_modargs_get_channel_map(ma, "master_channel_map", &stream_map) < 0) { + pa_log("Invalid master hannel map"); + goto fail; + } + + if (stream_map.channels != ss.channels) { + pa_log("Number of channels doesn't match"); + goto fail; + } + + u = pa_xnew0(struct userdata, 1); + u->core = m->core; + u->module = m; + m->userdata = u; + u->master = master; + pa_memchunk_reset(&u->memchunk); + + default_sink_name = pa_sprintf_malloc("%s.remapped", master->name); + + /* Create sink */ + if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", default_sink_name), 0, &ss, &sink_map))) { + pa_log("Failed to create sink."); + goto fail; + } + + u->sink->parent.process_msg = sink_process_msg; + u->sink->set_state = sink_set_state; + u->sink->userdata = u; + u->sink->flags = PA_SINK_LATENCY; + + pa_sink_set_module(u->sink, m); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Remapped %s", master->description)); + pa_xfree(t); + pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq); + pa_sink_set_rtpoll(u->sink, master->rtpoll); + + /* Create sink input */ + pa_sink_input_new_data_init(&data); + data.sink = u->master; + data.driver = __FILE__; + data.name = "Remapped Stream"; + pa_sink_input_new_data_set_sample_spec(&data, &ss); + pa_sink_input_new_data_set_channel_map(&data, &stream_map); + data.module = m; + + if (!(u->sink_input = pa_sink_input_new(m->core, &data, PA_SINK_INPUT_DONT_MOVE))) + goto fail; + + u->sink_input->parent.process_msg = sink_input_process_msg; + u->sink_input->peek = sink_input_peek_cb; + u->sink_input->drop = sink_input_drop_cb; + u->sink_input->kill = sink_input_kill_cb; + u->sink_input->attach = sink_input_attach_cb; + u->sink_input->detach = sink_input_detach_cb; + u->sink_input->userdata = u; + + pa_sink_put(u->sink); + pa_sink_input_put(u->sink_input); + + pa_modargs_free(ma); + pa_xfree(default_sink_name); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(m); + + pa_xfree(default_sink_name); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata *u; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->sink_input) { + pa_sink_input_unlink(u->sink_input); + pa_sink_input_unref(u->sink_input); + } + + if (u->sink) { + pa_sink_unlink(u->sink); + pa_sink_unref(u->sink); + } + + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + + pa_xfree(u); +} diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c index 25005f250..5cabef762 100644 --- a/src/modules/module-rescue-streams.c +++ b/src/modules/module-rescue-streams.c @@ -52,20 +52,26 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user pa_sink_input *i; pa_sink *target; - assert(c); - assert(sink); + pa_assert(c); + pa_assert(sink); if (!pa_idxset_size(sink->inputs)) { pa_log_debug("No sink inputs to move away."); return PA_HOOK_OK; } - if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, 0))) { - pa_log_info("No evacuation sink found."); - return PA_HOOK_OK; - } + if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, 0)) || target == sink) { + uint32_t idx; - assert(target != sink); + for (target = pa_idxset_first(c->sinks, &idx); target; target = pa_idxset_next(c->sinks, &idx)) + if (target != sink) + break; + + if (!target) { + pa_log_info("No evacuation sink found."); + return PA_HOOK_OK; + } + } while ((i = pa_idxset_first(sink->inputs, NULL))) { if (pa_sink_input_move_to(i, target, 1) < 0) { @@ -84,20 +90,28 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void pa_source_output *o; pa_source *target; - assert(c); - assert(source); + pa_assert(c); + pa_assert(source); if (!pa_idxset_size(source->outputs)) { pa_log_debug("No source outputs to move away."); return PA_HOOK_OK; } - if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SOURCE, 0))) { - pa_log_info("No evacuation source found."); - return PA_HOOK_OK; + if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SOURCE, 0)) || target == source) { + uint32_t idx; + + for (target = pa_idxset_first(c->sources, &idx); target; target = pa_idxset_next(c->sources, &idx)) + if (target != source && !target->monitor_of == !source->monitor_of) + break; + + if (!target) { + pa_log_info("No evacuation source found."); + return PA_HOOK_OK; + } } - assert(target != source); + pa_assert(target != source); while ((o = pa_idxset_first(source->outputs, NULL))) { if (pa_source_output_move_to(o, target) < 0) { @@ -112,12 +126,11 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void return PA_HOOK_OK; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; - assert(c); - assert(m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); @@ -125,18 +138,17 @@ int pa__init(pa_core *c, pa_module*m) { } m->userdata = u = pa_xnew(struct userdata, 1); - u->sink_slot = pa_hook_connect(&c->hook_sink_disconnect, (pa_hook_cb_t) sink_hook_callback, NULL); - u->source_slot = pa_hook_connect(&c->hook_source_disconnect, (pa_hook_cb_t) source_hook_callback, NULL); + u->sink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], (pa_hook_cb_t) sink_hook_callback, NULL); + u->source_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], (pa_hook_cb_t) source_hook_callback, NULL); pa_modargs_free(ma); return 0; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c); - assert(m); + pa_assert(m); if (!m->userdata) return; diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index 661455b3a..65b8ee7f8 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include #include "module-sine-symdef.h" @@ -58,36 +58,46 @@ static const char* const valid_modargs[] = { NULL, }; -static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { struct userdata *u; - assert(i && chunk && i->userdata); + + pa_assert(i); u = i->userdata; + pa_assert(u); + pa_assert(chunk); chunk->memblock = pa_memblock_ref(u->memblock); chunk->index = u->peek_index; - chunk->length = u->memblock->length - u->peek_index; + chunk->length = pa_memblock_get_length(u->memblock) - u->peek_index; + return 0; } -static void sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { +static void sink_input_drop_cb(pa_sink_input *i, size_t length) { struct userdata *u; - assert(i && chunk && length && i->userdata); - u = i->userdata; + size_t l; - assert(chunk->memblock == u->memblock && length <= u->memblock->length-u->peek_index); + pa_assert(i); + u = i->userdata; + pa_assert(u); + pa_assert(length > 0); u->peek_index += length; - if (u->peek_index >= u->memblock->length) - u->peek_index = 0; + l = pa_memblock_get_length(u->memblock); + + while (u->peek_index >= l) + u->peek_index -= l; } -static void sink_input_kill(pa_sink_input *i) { +static void sink_input_kill_cb(pa_sink_input *i) { struct userdata *u; - assert(i && i->userdata); - u = i->userdata; - pa_sink_input_disconnect(u->sink_input); + pa_assert(i); + u = i->userdata; + pa_assert(u); + + pa_sink_input_unlink(u->sink_input); pa_sink_input_unref(u->sink_input); u->sink_input = NULL; @@ -103,14 +113,14 @@ static void calc_sine(float *f, size_t l, float freq) { f[i] = (float) sin((double) i/l*M_PI*2*freq)/2; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; pa_sink *sink; - const char *sink_name; pa_sample_spec ss; uint32_t frequency; char t[256]; + void *p; pa_sink_input_new_data data; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -118,15 +128,14 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - m->userdata = u = pa_xmalloc(sizeof(struct userdata)); - u->core = c; + m->userdata = u = pa_xnew0(struct userdata, 1); + u->core = m->core; u->module = m; u->sink_input = NULL; u->memblock = NULL; + u->peek_index = 0; - sink_name = pa_modargs_get_value(ma, "sink", NULL); - - if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, 1))) { + if (!(sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink", NULL), PA_NAMEREG_SINK, 1))) { pa_log("No such sink."); goto fail; } @@ -141,10 +150,12 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - u->memblock = pa_memblock_new(c->mempool, pa_bytes_per_second(&ss)); - calc_sine(u->memblock->data, u->memblock->length, frequency); + u->memblock = pa_memblock_new(m->core->mempool, pa_bytes_per_second(&ss)); + p = pa_memblock_acquire(u->memblock); + calc_sine(p, pa_memblock_get_length(u->memblock), frequency); + pa_memblock_release(u->memblock); - snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); + pa_snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency); pa_sink_input_new_data_init(&data); data.sink = sink; @@ -153,15 +164,15 @@ int pa__init(pa_core *c, pa_module*m) { pa_sink_input_new_data_set_sample_spec(&data, &ss); data.module = m; - if (!(u->sink_input = pa_sink_input_new(c, &data, 0))) + if (!(u->sink_input = pa_sink_input_new(m->core, &data, 0))) goto fail; - u->sink_input->peek = sink_input_peek; - u->sink_input->drop = sink_input_drop; - u->sink_input->kill = sink_input_kill; + u->sink_input->peek = sink_input_peek_cb; + u->sink_input->drop = sink_input_drop_cb; + u->sink_input->kill = sink_input_kill_cb; u->sink_input->userdata = u; - u->peek_index = 0; + pa_sink_input_put(u->sink_input); pa_modargs_free(ma); return 0; @@ -170,24 +181,26 @@ fail: if (ma) pa_modargs_free(ma); - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { - struct userdata *u = m->userdata; - assert(c && m); +void pa__done(pa_module*m) { + struct userdata *u; - if (!u) + pa_assert(m); + + if (!(u = m->userdata)) return; if (u->sink_input) { - pa_sink_input_disconnect(u->sink_input); + pa_sink_input_unlink(u->sink_input); pa_sink_input_unref(u->sink_input); } if (u->memblock) pa_memblock_unref(u->memblock); + pa_xfree(u); } diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index a50f1ecf8..a8a947129 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -4,7 +4,7 @@ This file is part of PulseAudio. Copyright 2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006-2007 Pierre Ossman for Cendio AB PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -57,6 +57,9 @@ #include #include #include +#include +#include +#include #include "module-solaris-symdef.h" @@ -75,12 +78,14 @@ PA_MODULE_USAGE( "channel_map=") struct userdata { + pa_core *core; pa_sink *sink; pa_source *source; - pa_iochannel *io; - pa_core *core; - pa_time_event *timer; - pa_usec_t poll_timeout; + + pa_thread *thread; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + pa_signal_event *sig; pa_memchunk memchunk; @@ -90,9 +95,9 @@ struct userdata { uint32_t frame_size; uint32_t buffer_size; unsigned int written_bytes, read_bytes; - int sink_underflow; int fd; + pa_rtpoll_item *rtpoll_item; pa_module *module; }; @@ -114,309 +119,357 @@ static const char* const valid_modargs[] = { #define DEFAULT_SOURCE_NAME "solaris_input" #define DEFAULT_DEVICE "/dev/audio" -#define CHUNK_SIZE 2048 - -static void update_usage(struct userdata *u) { - pa_module_set_used(u->module, - (u->sink ? pa_sink_used_by(u->sink) : 0) + - (u->source ? pa_source_used_by(u->source) : 0)); -} - -static void do_write(struct userdata *u) { +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + int err; audio_info_t info; - int err; - size_t len; - ssize_t r; - assert(u); + switch (code) { + case PA_SINK_MESSAGE_GET_LATENCY: { + pa_usec_t r = 0; - /* We cannot check pa_iochannel_is_writable() because of our buffer hack */ - if (!u->sink) - return; + if (u->fd >= 0) { - update_usage(u); + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); + r += pa_bytes_to_usec(u->written_bytes, &PA_SINK(o)->sample_spec); + r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &PA_SINK(o)->sample_spec); - /* - * Since we cannot modify the size of the output buffer we fake it - * by not filling it more than u->buffer_size. - */ - len = u->buffer_size; - len -= u->written_bytes - (info.play.samples * u->frame_size); - - /* The sample counter can sometimes go backwards :( */ - if (len > u->buffer_size) - len = 0; - - if (!u->sink_underflow && (len == u->buffer_size)) - pa_log_debug("Solaris buffer underflow!"); - - len -= len % u->frame_size; - - if (len == 0) - return; - - if (!u->memchunk.length) { - if (pa_sink_render(u->sink, len, &u->memchunk) < 0) { - u->sink_underflow = 1; - return; + if (u->memchunk.memblock) + r += pa_bytes_to_usec(u->memchunk.length, &PA_SINK(o)->sample_spec); } + + *((pa_usec_t*) data) = r; + + return 0; } - u->sink_underflow = 0; + case PA_SINK_MESSAGE_SET_VOLUME: + if (u->fd >= 0) { + AUDIO_INITINFO(&info); - assert(u->memchunk.memblock); - assert(u->memchunk.memblock->data); - assert(u->memchunk.length); + info.play.gain = pa_cvolume_avg((pa_cvolume*)data) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; + assert(info.play.gain <= AUDIO_MAX_GAIN); - if (u->memchunk.length < len) { - len = u->memchunk.length; - len -= len % u->frame_size; - assert(len); + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log("AUDIO_SETINFO: Unsupported volume."); + else + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); + } else { + return 0; + } + } + break; + + case PA_SINK_MESSAGE_GET_VOLUME: + if (u->fd >= 0) { + err = ioctl(u->fd, AUDIO_GETINFO, &info); + assert(err >= 0); + + pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels, + info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); + + return 0; + } + break; + + case PA_SINK_MESSAGE_SET_MUTE: + if (u->fd >= 0) { + AUDIO_INITINFO(&info); + + info.output_muted = !!PA_PTR_TO_UINT(data); + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); + else + return 0; + } + break; + + case PA_SINK_MESSAGE_GET_MUTE: + if (u->fd >= 0) { + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); + + *(int*)data = !!info.output_muted; + + return 0; + } + break; } - if ((r = pa_iochannel_write(u->io, - (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, len)) < 0) { - pa_log("write() failed: %s", pa_cstrerror(errno)); - return; - } - - assert(r % u->frame_size == 0); - - u->memchunk.index += r; - u->memchunk.length -= r; - - if (u->memchunk.length <= 0) { - pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; - } - - u->written_bytes += r; + return pa_sink_process_msg(o, code, data, offset, chunk); } -static void do_read(struct userdata *u) { - pa_memchunk memchunk; +static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SOURCE(o)->userdata; int err; - size_t l; - ssize_t r; - assert(u); + audio_info_t info; - if (!u->source || !pa_iochannel_is_readable(u->io)) - return; + switch (code) { + case PA_SOURCE_MESSAGE_GET_LATENCY: { + pa_usec_t r = 0; - update_usage(u); + if (u->fd) { + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); - err = ioctl(u->fd, I_NREAD, &l); - assert(err >= 0); + r += pa_bytes_to_usec(info.record.samples * u->frame_size, &PA_SOURCE(o)->sample_spec); + r -= pa_bytes_to_usec(u->read_bytes, &PA_SOURCE(o)->sample_spec); + } - /* This is to make sure it fits in the memory pool. Also, a page - should be the most efficient transfer size. */ - if (l > u->page_size) - l = u->page_size; + *((pa_usec_t*) data) = r; - memchunk.memblock = pa_memblock_new(u->core->mempool, l); - assert(memchunk.memblock); - if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) { - pa_memblock_unref(memchunk.memblock); - if (errno != EAGAIN) - pa_log("read() failed: %s", pa_cstrerror(errno)); - return; + return 0; + } + + case PA_SOURCE_MESSAGE_SET_VOLUME: + if (u->fd >= 0) { + AUDIO_INITINFO(&info); + + info.record.gain = pa_cvolume_avg((pa_cvolume*) data) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; + assert(info.record.gain <= AUDIO_MAX_GAIN); + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { + if (errno == EINVAL) + pa_log("AUDIO_SETINFO: Unsupported volume."); + else + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); + } else { + return 0; + } + } + break; + + case PA_SOURCE_MESSAGE_GET_VOLUME: + if (u->fd >= 0) { + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); + + pa_cvolume_set((pa_cvolume*) data, ((pa_cvolume*) data)->channels, + info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); + + return 0; + } + break; } - assert(r <= (ssize_t) memchunk.memblock->length); - memchunk.length = memchunk.memblock->length = r; - memchunk.index = 0; - - pa_source_post(u->source, &memchunk); - pa_memblock_unref(memchunk.memblock); - - u->read_bytes += r; + return pa_source_process_msg(o, code, data, offset, chunk); } -static void io_callback(pa_iochannel *io, void*userdata) { - struct userdata *u = userdata; - assert(u); - do_write(u); - do_read(u); +static void clear_underflow(struct userdata *u) +{ + audio_info_t info; + + AUDIO_INITINFO(&info); + + info.play.error = 0; + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); } -static void timer_cb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { +static void clear_overflow(struct userdata *u) +{ + audio_info_t info; + + AUDIO_INITINFO(&info); + + info.record.error = 0; + + if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) + pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); +} + +static void thread_func(void *userdata) { struct userdata *u = userdata; - struct timeval ntv; + unsigned short revents = 0; + int ret; - assert(u); + pa_assert(u); - do_write(u); + pa_log_debug("Thread starting up"); - pa_gettimeofday(&ntv); - pa_timeval_add(&ntv, u->poll_timeout); + if (u->core->high_priority) + pa_make_realtime(); - a->time_restart(e, &ntv); + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + for (;;) { + /* Render some data and write it to the dsp */ + + if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state)) { + audio_info_t info; + int err; + size_t len; + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); + + /* + * Since we cannot modify the size of the output buffer we fake it + * by not filling it more than u->buffer_size. + */ + len = u->buffer_size; + len -= u->written_bytes - (info.play.samples * u->frame_size); + + /* The sample counter can sometimes go backwards :( */ + if (len > u->buffer_size) + len = 0; + + if (info.play.error) { + pa_log_debug("Solaris buffer underflow!"); + clear_underflow(u); + } + + len -= len % u->frame_size; + + while (len) { + void *p; + ssize_t r; + + if (!u->memchunk.length) + pa_sink_render(u->sink, len, &u->memchunk); + + pa_assert(u->memchunk.length); + + p = pa_memblock_acquire(u->memchunk.memblock); + r = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, NULL); + pa_memblock_release(u->memchunk.memblock); + + if (r < 0) { + if (errno == EINTR) + continue; + else if (errno != EAGAIN) { + pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno)); + goto fail; + } + } else { + pa_assert(r % u->frame_size == 0); + + u->memchunk.index += r; + u->memchunk.length -= r; + + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + pa_memchunk_reset(&u->memchunk); + } + + len -= r; + u->written_bytes += r; + } + } + } + + /* Try to read some data and pass it on to the source driver */ + + if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state) && ((revents & POLLIN))) { + pa_memchunk memchunk; + int err; + size_t l; + void *p; + ssize_t r; + audio_info_t info; + + err = ioctl(u->fd, AUDIO_GETINFO, &info); + pa_assert(err >= 0); + + if (info.record.error) { + pa_log_debug("Solaris buffer overflow!"); + clear_overflow(u); + } + + err = ioctl(u->fd, I_NREAD, &l); + pa_assert(err >= 0); + + if (l > 0) { + /* This is to make sure it fits in the memory pool. Also, a page + should be the most efficient transfer size. */ + if (l > u->page_size) + l = u->page_size; + + memchunk.memblock = pa_memblock_new(u->core->mempool, l); + pa_assert(memchunk.memblock); + + p = pa_memblock_acquire(memchunk.memblock); + r = pa_read(u->fd, p, l, NULL); + pa_memblock_release(memchunk.memblock); + + if (r < 0) { + pa_memblock_unref(memchunk.memblock); + if (errno != EAGAIN) { + pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno)); + goto fail; + } + } else { + memchunk.index = 0; + memchunk.length = r; + + pa_source_post(u->source, &memchunk); + pa_memblock_unref(memchunk.memblock); + + u->read_bytes += r; + + revents &= ~POLLIN; + } + } + } + + if (u->fd >= 0) { + struct pollfd *pollfd; + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->events = + ((u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) ? POLLIN : 0); + } + + /* Hmm, nothing to do. Let's sleep */ + if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0) + goto fail; + + if (ret == 0) + goto finish; + + if (u->fd >= 0) { + struct pollfd *pollfd; + + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + + if (pollfd->revents & ~(POLLOUT|POLLIN)) { + pa_log("DSP shutdown."); + goto fail; + } + + revents = pollfd->revents; + } else + revents = 0; + } + +fail: + /* We have to continue processing messages until we receive the + * SHUTDOWN message */ + 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); + +finish: + pa_log_debug("Thread shutting down"); } static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) { struct userdata *u = userdata; - pa_cvolume old_vol; assert(u); if (u->sink) { - assert(u->sink->get_hw_volume); - memcpy(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)); - if (u->sink->get_hw_volume(u->sink) < 0) - return; - if (memcmp(&old_vol, &u->sink->hw_volume, sizeof(pa_cvolume)) != 0) { - pa_subscription_post(u->sink->core, - PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, - u->sink->index); - } + pa_sink_get_volume(u->sink); + pa_sink_get_mute(u->sink); } - if (u->source) { - assert(u->source->get_hw_volume); - memcpy(&old_vol, &u->source->hw_volume, sizeof(pa_cvolume)); - if (u->source->get_hw_volume(u->source) < 0) - return; - if (memcmp(&old_vol, &u->source->hw_volume, sizeof(pa_cvolume)) != 0) { - pa_subscription_post(u->source->core, - PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, - u->source->index); - } - } -} - -static pa_usec_t sink_get_latency_cb(pa_sink *s) { - pa_usec_t r = 0; - audio_info_t info; - int err; - struct userdata *u = s->userdata; - assert(s && u && u->sink); - - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); - - r += pa_bytes_to_usec(u->written_bytes, &s->sample_spec); - r -= pa_bytes_to_usec(info.play.samples * u->frame_size, &s->sample_spec); - - if (u->memchunk.memblock) - r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); - - return r; -} - -static pa_usec_t source_get_latency_cb(pa_source *s) { - pa_usec_t r = 0; - struct userdata *u = s->userdata; - audio_info_t info; - int err; - assert(s && u && u->source); - - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); - - r += pa_bytes_to_usec(info.record.samples * u->frame_size, &s->sample_spec); - r -= pa_bytes_to_usec(u->read_bytes, &s->sample_spec); - - return r; -} - -static int sink_get_hw_volume_cb(pa_sink *s) { - struct userdata *u = s->userdata; - audio_info_t info; - int err; - - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); - - pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, - info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); - - return 0; -} - -static int sink_set_hw_volume_cb(pa_sink *s) { - struct userdata *u = s->userdata; - audio_info_t info; - - AUDIO_INITINFO(&info); - - info.play.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; - assert(info.play.gain <= AUDIO_MAX_GAIN); - - if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { - if (errno == EINVAL) - pa_log("AUDIO_SETINFO: Unsupported volume."); - else - pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); - return -1; - } - - return 0; -} - -static int sink_get_hw_mute_cb(pa_sink *s) { - struct userdata *u = s->userdata; - audio_info_t info; - int err; - - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); - - s->hw_muted = !!info.output_muted; - - return 0; -} - -static int sink_set_hw_mute_cb(pa_sink *s) { - struct userdata *u = s->userdata; - audio_info_t info; - - AUDIO_INITINFO(&info); - - info.output_muted = !!s->hw_muted; - - if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { - pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); - return -1; - } - - return 0; -} - -static int source_get_hw_volume_cb(pa_source *s) { - struct userdata *u = s->userdata; - audio_info_t info; - int err; - - err = ioctl(u->fd, AUDIO_GETINFO, &info); - assert(err >= 0); - - pa_cvolume_set(&s->hw_volume, s->hw_volume.channels, - info.record.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN); - - return 0; -} - -static int source_set_hw_volume_cb(pa_source *s) { - struct userdata *u = s->userdata; - audio_info_t info; - - AUDIO_INITINFO(&info); - - info.record.gain = pa_cvolume_avg(&s->hw_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM; - assert(info.record.gain <= AUDIO_MAX_GAIN); - - if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) { - if (errno == EINVAL) - pa_log("AUDIO_SETINFO: Unsupported volume."); - else - pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno)); - return -1; - } - - return 0; + if (u->source) + pa_source_get_volume(u->source); } static int pa_solaris_auto_format(int fd, int mode, pa_sample_spec *ss) { @@ -490,6 +543,7 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { AUDIO_INITINFO(&info); + info.play.buffer_size = buffer_size; info.record.buffer_size = buffer_size; if (ioctl(fd, AUDIO_SETINFO, &info) < 0) { @@ -503,7 +557,7 @@ static int pa_solaris_set_buffer(int fd, int buffer_size) { return 0; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module *m) { struct userdata *u = NULL; const char *p; int fd = -1; @@ -513,9 +567,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; - struct timeval tv; char *t; - assert(c && m); + struct pollfd *pollfd; + + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments."); @@ -540,7 +595,7 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - ss = c->default_sample_spec; + ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log("failed to parse sample specification"); goto fail; @@ -554,55 +609,18 @@ int pa__init(pa_core *c, pa_module*m) { if (pa_solaris_auto_format(fd, mode, &ss) < 0) goto fail; - if ((mode != O_WRONLY) && (buffer_size >= 1)) - if (pa_solaris_set_buffer(fd, buffer_size) < 0) - goto fail; + if (pa_solaris_set_buffer(fd, buffer_size) < 0) + goto fail; u = pa_xmalloc(sizeof(struct userdata)); - u->core = c; + u->core = m->core; - if (mode != O_WRONLY) { - u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map); - assert(u->source); - u->source->userdata = u; - u->source->get_latency = source_get_latency_cb; - u->source->get_hw_volume = source_get_hw_volume_cb; - u->source->set_hw_volume = source_set_hw_volume_cb; - pa_source_set_owner(u->source, m); - pa_source_set_description(u->source, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); - pa_xfree(t); - u->source->is_hardware = 1; - } else - u->source = NULL; - - if (mode != O_RDONLY) { - u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map); - assert(u->sink); - u->sink->get_latency = sink_get_latency_cb; - u->sink->get_hw_volume = sink_get_hw_volume_cb; - u->sink->set_hw_volume = sink_set_hw_volume_cb; - u->sink->get_hw_mute = sink_get_hw_mute_cb; - u->sink->set_hw_mute = sink_set_hw_mute_cb; - u->sink->userdata = u; - pa_sink_set_owner(u->sink, m); - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); - pa_xfree(t); - u->sink->is_hardware = 1; - } else - u->sink = NULL; - - assert(u->source || u->sink); - - u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : 0); - assert(u->io); - pa_iochannel_set_callback(u->io, io_callback, u); u->fd = fd; - u->memchunk.memblock = NULL; - u->memchunk.length = 0; + pa_memchunk_reset(&u->memchunk); /* We use this to get a reasonable chunk size */ - u->page_size = sysconf(_SC_PAGESIZE); + u->page_size = PA_PAGE_SIZE; u->frame_size = pa_frame_size(&ss); u->buffer_size = buffer_size; @@ -610,37 +628,91 @@ int pa__init(pa_core *c, pa_module*m) { u->written_bytes = 0; u->read_bytes = 0; - u->sink_underflow = 1; - u->module = m; m->userdata = u; - u->poll_timeout = pa_bytes_to_usec(u->buffer_size / 10, &ss); + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); - pa_gettimeofday(&tv); - pa_timeval_add(&tv, u->poll_timeout); + u->rtpoll = pa_rtpoll_new(); + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); - u->timer = c->mainloop->time_new(c->mainloop, &tv, timer_cb, u); - assert(u->timer); + pa_rtpoll_set_timer_periodic(u->rtpoll, pa_bytes_to_usec(u->buffer_size / 10, &ss)); + + u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); + pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); + pollfd->fd = fd; + pollfd->events = 0; + pollfd->revents = 0; + + if (mode != O_WRONLY) { + u->source = pa_source_new(m->core, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map); + pa_assert(u->source); + + u->source->userdata = u; + u->source->parent.process_msg = source_process_msg; + + pa_source_set_module(u->source, m); + pa_source_set_description(u->source, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); + pa_xfree(t); + pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); + pa_source_set_rtpoll(u->source, u->rtpoll); + + u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL; + u->source->refresh_volume = 1; + } else + u->source = NULL; + + if (mode != O_RDONLY) { + u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map); + pa_assert(u->sink); + + u->sink->userdata = u; + u->sink->parent.process_msg = sink_process_msg; + + pa_sink_set_module(u->sink, m); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Solaris PCM on '%s'", p)); + pa_xfree(t); + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); + + u->sink->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL; + u->sink->refresh_volume = 1; + u->sink->refresh_mute = 1; + } else + u->sink = NULL; + + pa_assert(u->source || u->sink); u->sig = pa_signal_new(SIGPOLL, sig_callback, u); - assert(u->sig); + pa_assert(u->sig); ioctl(u->fd, I_SETSIG, S_MSG); - pa_modargs_free(ma); + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } /* Read mixer settings */ if (u->source) - source_get_hw_volume_cb(u->source); + pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, 0, NULL); if (u->sink) { - sink_get_hw_volume_cb(u->sink); - sink_get_hw_mute_cb(u->sink); + pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL); + pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_MUTE, &u->sink->muted, 0, NULL); } + if (u->sink) + pa_sink_put(u->sink); + if (u->source) + pa_source_put(u->source); + + pa_modargs_free(ma); + return 0; fail: - if (fd >= 0) + if (u) + pa__done(m); + else if (fd >= 0) close(fd); if (ma) @@ -649,31 +721,47 @@ fail: return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module *m) { struct userdata *u; - assert(c && m); + + pa_assert(m); if (!(u = m->userdata)) return; - if (u->timer) - c->mainloop->time_free(u->timer); ioctl(u->fd, I_SETSIG, 0); pa_signal_free(u->sig); - if (u->memchunk.memblock) + 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); + } + + pa_thread_mq_done(&u->thread_mq); + + if (u->sink) + pa_sink_unref(u->sink); + + if (u->source) + pa_source_unref(u->source); + + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - } + if (u->rtpoll_item) + pa_rtpoll_item_free(u->rtpoll_item); - if (u->source) { - pa_source_disconnect(u->source); - pa_source_unref(u->source); - } + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->fd >= 0) + close(u->fd); - pa_iochannel_free(u->io); pa_xfree(u); } diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c new file mode 100644 index 000000000..5a7113903 --- /dev/null +++ b/src/modules/module-suspend-on-idle.c @@ -0,0 +1,473 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "module-suspend-on-idle-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("When a sink/source is idle for too long, suspend it") +PA_MODULE_VERSION(PACKAGE_VERSION) + +static const char* const valid_modargs[] = { + "timeout", + NULL, +}; + +struct userdata { + pa_core *core; + pa_usec_t timeout; + pa_hashmap *device_infos; + pa_hook_slot + *sink_new_slot, + *source_new_slot, + *sink_unlink_slot, + *source_unlink_slot, + *sink_state_changed_slot, + *source_state_changed_slot; + + pa_hook_slot + *sink_input_new_slot, + *source_output_new_slot, + *sink_input_unlink_slot, + *source_output_unlink_slot, + *sink_input_move_slot, + *source_output_move_slot, + *sink_input_move_post_slot, + *source_output_move_post_slot, + *sink_input_state_changed_slot, + *source_output_state_changed_slot; +}; + +struct device_info { + struct userdata *userdata; + pa_sink *sink; + pa_source *source; + struct timeval last_use; + pa_time_event *time_event; +}; + +static void timeout_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) { + struct device_info *d = userdata; + + pa_assert(d); + + d->userdata->core->mainloop->time_restart(d->time_event, NULL); + + if (d->sink && pa_sink_used_by(d->sink) <= 0 && pa_sink_get_state(d->sink) != PA_SINK_SUSPENDED) { + pa_log_info("Sink %s idle for too long, suspending ...", d->sink->name); + pa_sink_suspend(d->sink, TRUE); + } + + if (d->source && pa_source_used_by(d->source) <= 0 && pa_source_get_state(d->source) != PA_SOURCE_SUSPENDED) { + pa_log_info("Source %s idle for too long, suspending ...", d->source->name); + pa_source_suspend(d->source, TRUE); + } +} + +static void restart(struct device_info *d) { + struct timeval tv; + pa_assert(d); + + pa_gettimeofday(&tv); + d->last_use = tv; + pa_timeval_add(&tv, d->userdata->timeout*1000000); + d->userdata->core->mainloop->time_restart(d->time_event, &tv); + + if (d->sink) + pa_log_debug("Sink %s becomes idle.", d->sink->name); + if (d->source) + pa_log_debug("Source %s becomes idle.", d->source->name); +} + +static void resume(struct device_info *d) { + pa_assert(d); + + d->userdata->core->mainloop->time_restart(d->time_event, NULL); + + if (d->sink) { + pa_sink_suspend(d->sink, FALSE); + + pa_log_debug("Sink %s becomes busy.", d->sink->name); + } + + if (d->source) { + pa_source_suspend(d->source, FALSE); + + pa_log_debug("Source %s becomes busy.", d->source->name); + } +} + +static pa_hook_result_t sink_input_new_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { + struct device_info *d; + + pa_assert(c); + pa_sink_input_assert_ref(s); + pa_assert(u); + + if ((d = pa_hashmap_get(u->device_infos, s->sink))) + resume(d); + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_new_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) { + struct device_info *d; + + pa_assert(c); + pa_source_output_assert_ref(s); + pa_assert(u); + + if ((d = pa_hashmap_get(u->device_infos, s->source))) + resume(d); + + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_input_unlink_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { + pa_assert(c); + pa_sink_input_assert_ref(s); + pa_assert(u); + + if (pa_sink_used_by(s->sink) <= 0) { + struct device_info *d; + if ((d = pa_hashmap_get(u->device_infos, s->sink))) + restart(d); + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_unlink_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) { + pa_assert(c); + pa_source_output_assert_ref(s); + pa_assert(u); + + if (pa_source_used_by(s->source) <= 0) { + struct device_info *d; + if ((d = pa_hashmap_get(u->device_infos, s->source))) + restart(d); + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_input_move_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { + pa_assert(c); + pa_sink_input_assert_ref(s); + pa_assert(u); + + if (pa_sink_used_by(s->sink) <= 1) { + struct device_info *d; + if ((d = pa_hashmap_get(u->device_infos, s->sink))) + restart(d); + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_input_move_post_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { + struct device_info *d; + pa_assert(c); + pa_sink_input_assert_ref(s); + pa_assert(u); + + if ((d = pa_hashmap_get(u->device_infos, s->sink))) + resume(d); + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_move_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) { + pa_assert(c); + pa_source_output_assert_ref(s); + pa_assert(u); + + if (pa_source_used_by(s->source) <= 1) { + struct device_info *d; + + if ((d = pa_hashmap_get(u->device_infos, s->source))) + restart(d); + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_move_post_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) { + struct device_info *d; + pa_assert(c); + pa_source_output_assert_ref(s); + pa_assert(u); + + if ((d = pa_hashmap_get(u->device_infos, s->source))) + resume(d); + + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_input_state_changed_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { + struct device_info *d; + pa_sink_input_state_t state; + pa_assert(c); + pa_sink_input_assert_ref(s); + pa_assert(u); + + state = pa_sink_input_get_state(s); + if (state == PA_SINK_INPUT_RUNNING || state == PA_SINK_INPUT_DRAINED) + if ((d = pa_hashmap_get(u->device_infos, s->sink))) + resume(d); + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_state_changed_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) { + struct device_info *d; + pa_source_output_state_t state; + pa_assert(c); + pa_source_output_assert_ref(s); + pa_assert(u); + + state = pa_source_output_get_state(s); + if (state == PA_SOURCE_OUTPUT_RUNNING) + if ((d = pa_hashmap_get(u->device_infos, s->source))) + resume(d); + + return PA_HOOK_OK; +} + +static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct userdata *u) { + struct device_info *d; + pa_source *source; + pa_sink *sink; + + pa_assert(c); + pa_object_assert_ref(o); + pa_assert(u); + + source = pa_source_isinstance(o) ? PA_SOURCE(o) : NULL; + sink = pa_sink_isinstance(o) ? PA_SINK(o) : NULL; + + pa_assert(source || sink); + + d = pa_xnew(struct device_info, 1); + d->userdata = u; + d->source = source ? pa_source_ref(source) : NULL; + d->sink = sink ? pa_sink_ref(sink) : NULL; + d->time_event = c->mainloop->time_new(c->mainloop, NULL, timeout_cb, d); + pa_hashmap_put(u->device_infos, o, d); + + if ((d->sink && pa_sink_used_by(d->sink) <= 0) || + (d->source && pa_source_used_by(d->source) <= 0)) + restart(d); + + return PA_HOOK_OK; +} + +static void device_info_free(struct device_info *d) { + pa_assert(d); + + if (d->source) + pa_source_unref(d->source); + if (d->sink) + pa_sink_unref(d->sink); + + d->userdata->core->mainloop->time_free(d->time_event); + + pa_xfree(d); +} + +static pa_hook_result_t device_unlink_hook_cb(pa_core *c, pa_object *o, struct userdata *u) { + struct device_info *d; + + pa_assert(c); + pa_object_assert_ref(o); + pa_assert(u); + + if ((d = pa_hashmap_remove(u->device_infos, o))) + device_info_free(d); + + return PA_HOOK_OK; +} + +static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, struct userdata *u) { + struct device_info *d; + + pa_assert(c); + pa_object_assert_ref(o); + pa_assert(u); + + if (!(d = pa_hashmap_get(u->device_infos, o))) + return PA_HOOK_OK; + + if (pa_sink_isinstance(o)) { + pa_sink *s = PA_SINK(o); + pa_sink_state_t state = pa_sink_get_state(s); + + if (pa_sink_used_by(s) <= 0) { + + if (PA_SINK_OPENED(state)) + restart(d); + + } + + } else if (pa_source_isinstance(o)) { + pa_source *s = PA_SOURCE(o); + pa_source_state_t state = pa_source_get_state(s); + + if (pa_source_used_by(s) <= 0) { + + if (PA_SOURCE_OPENED(state)) + restart(d); + } + } + + return PA_HOOK_OK; +} + +int pa__init(pa_module*m) { + pa_modargs *ma = NULL; + struct userdata *u; + uint32_t timeout = 1; + uint32_t idx; + pa_sink *sink; + pa_source *source; + + pa_assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments."); + goto fail; + } + + if (pa_modargs_get_value_u32(ma, "timeout", &timeout) < 0) { + pa_log("Failed to parse timeout value."); + goto fail; + } + + m->userdata = u = pa_xnew(struct userdata, 1); + u->core = m->core; + u->timeout = timeout; + u->device_infos = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + + for (sink = pa_idxset_first(m->core->sinks, &idx); sink; sink = pa_idxset_next(m->core->sinks, &idx)) + device_new_hook_cb(m->core, PA_OBJECT(sink), u); + + for (source = pa_idxset_first(m->core->sources, &idx); source; source = pa_idxset_next(m->core->sources, &idx)) + device_new_hook_cb(m->core, PA_OBJECT(source), u); + + u->sink_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_NEW_POST], (pa_hook_cb_t) device_new_hook_cb, u); + u->source_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_NEW_POST], (pa_hook_cb_t) device_new_hook_cb, u); + u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], (pa_hook_cb_t) device_unlink_hook_cb, u); + u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], (pa_hook_cb_t) device_unlink_hook_cb, u); + u->sink_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], (pa_hook_cb_t) device_state_changed_hook_cb, u); + u->source_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], (pa_hook_cb_t) device_state_changed_hook_cb, u); + + u->sink_input_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], (pa_hook_cb_t) sink_input_new_hook_cb, u); + u->source_output_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], (pa_hook_cb_t) source_output_new_hook_cb, u); + u->sink_input_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], (pa_hook_cb_t) sink_input_unlink_hook_cb, u); + u->source_output_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], (pa_hook_cb_t) source_output_unlink_hook_cb, u); + u->sink_input_move_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], (pa_hook_cb_t) sink_input_move_hook_cb, u); + u->source_output_move_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], (pa_hook_cb_t) source_output_move_hook_cb, u); + u->sink_input_move_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_POST], (pa_hook_cb_t) sink_input_move_post_hook_cb, u); + u->source_output_move_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST], (pa_hook_cb_t) source_output_move_post_hook_cb, u); + u->sink_input_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], (pa_hook_cb_t) sink_input_state_changed_hook_cb, u); + u->source_output_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED], (pa_hook_cb_t) source_output_state_changed_hook_cb, u); + + + pa_modargs_free(ma); + return 0; + +fail: + + if (ma) + pa_modargs_free(ma); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata *u; + struct device_info *d; + + pa_assert(m); + + if (!m->userdata) + return; + + u = m->userdata; + + if (u->sink_new_slot) + pa_hook_slot_free(u->sink_new_slot); + if (u->sink_unlink_slot) + pa_hook_slot_free(u->sink_unlink_slot); + if (u->sink_state_changed_slot) + pa_hook_slot_free(u->sink_state_changed_slot); + + if (u->source_new_slot) + pa_hook_slot_free(u->source_new_slot); + if (u->source_unlink_slot) + pa_hook_slot_free(u->source_unlink_slot); + if (u->source_state_changed_slot) + pa_hook_slot_free(u->source_state_changed_slot); + + if (u->sink_input_new_slot) + pa_hook_slot_free(u->sink_input_new_slot); + if (u->sink_input_unlink_slot) + pa_hook_slot_free(u->sink_input_unlink_slot); + if (u->sink_input_move_slot) + pa_hook_slot_free(u->sink_input_move_slot); + if (u->sink_input_move_post_slot) + pa_hook_slot_free(u->sink_input_move_post_slot); + if (u->sink_input_state_changed_slot) + pa_hook_slot_free(u->sink_input_state_changed_slot); + + if (u->source_output_new_slot) + pa_hook_slot_free(u->source_output_new_slot); + if (u->source_output_unlink_slot) + pa_hook_slot_free(u->source_output_unlink_slot); + if (u->source_output_move_slot) + pa_hook_slot_free(u->source_output_move_slot); + if (u->source_output_move_post_slot) + pa_hook_slot_free(u->source_output_move_post_slot); + if (u->source_output_state_changed_slot) + pa_hook_slot_free(u->source_output_state_changed_slot); + + while ((d = pa_hashmap_steal_first(u->device_infos))) + device_info_free(d); + + pa_hashmap_free(u->device_infos, NULL, NULL); + + pa_xfree(u); +} diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 288e049e8..b96d46b31 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -596,12 +596,12 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t } #ifdef TUNNEL_SINK - snprintf(name, sizeof(name), "Tunnel from host %s, user %s, sink %s", + pa_snprintf(name, sizeof(name), "Tunnel from host %s, user %s, sink %s", pa_get_host_name(hn, sizeof(hn)), pa_get_user_name(un, sizeof(un)), u->sink->name); #else - snprintf(name, sizeof(name), "Tunnel from host %s, user %s, source %s", + pa_snprintf(name, sizeof(name), "Tunnel from host %s, user %s, source %s", pa_get_host_name(hn, sizeof(hn)), pa_get_user_name(un, sizeof(un)), u->source->name); diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 61a17aefc..77e6174f3 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include #include @@ -35,6 +34,7 @@ #include #include +#include #include #include @@ -44,9 +44,7 @@ #include #include #include -#include #include -#include #include "module-volume-restore-symdef.h" @@ -85,8 +83,8 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { long k; unsigned i; - assert(s); - assert(v); + pa_assert(s); + pa_assert(v); if (!isdigit(*s)) return NULL; @@ -170,7 +168,7 @@ static int load_rules(struct userdata *u) { continue; } - assert(ln == buf_source); + pa_assert(ln == buf_source); if (buf_volume[0]) { if (!parse_volume(buf_volume, &v)) { @@ -297,8 +295,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 struct rule *r; char *name; - assert(c); - assert(u); + pa_assert(c); + pa_assert(u); if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) && t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) && @@ -313,7 +311,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!si->client || !(name = client_name(si->client))) return; } else { - assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT); + pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT); if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) return; @@ -341,7 +339,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 u->modified = 1; } } else { - assert(so); + pa_assert(so); if (!r->source || strcmp(so->source->name, r->source) != 0) { pa_log_info("Saving source for <%s>", r->name); @@ -363,7 +361,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 r->sink = pa_xstrdup(si->sink->name); r->source = NULL; } else { - assert(so); + pa_assert(so); r->volume_is_set = 0; r->sink = NULL; r->source = pa_xstrdup(so->source->name); @@ -378,7 +376,7 @@ static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_d struct rule *r; char *name; - assert(data); + pa_assert(data); if (!data->client || !(name = client_name(data->client))) return PA_HOOK_OK; @@ -396,6 +394,8 @@ static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_d } } + pa_xfree(name); + return PA_HOOK_OK; } @@ -403,7 +403,7 @@ static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output struct rule *r; char *name; - assert(data); + pa_assert(data); if (!data->client || !(name = client_name(data->client))) return PA_HOOK_OK; @@ -418,12 +418,11 @@ static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output return PA_HOOK_OK; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; - assert(c); - assert(m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); @@ -442,16 +441,15 @@ int pa__init(pa_core *c, pa_module*m) { if (load_rules(u) < 0) goto fail; - u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u); - u->sink_input_hook_slot = pa_hook_connect(&c->hook_sink_input_new, (pa_hook_cb_t) sink_input_hook_callback, u); - u->source_output_hook_slot = pa_hook_connect(&c->hook_source_output_new, (pa_hook_cb_t) source_output_hook_callback, u); + u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u); + u->sink_input_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], (pa_hook_cb_t) sink_input_hook_callback, u); + u->source_output_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], (pa_hook_cb_t) source_output_hook_callback, u); pa_modargs_free(ma); return 0; fail: - pa__done(c, m); - + pa__done(m); if (ma) pa_modargs_free(ma); @@ -460,7 +458,7 @@ fail: static void free_func(void *p, void *userdata) { struct rule *r = p; - assert(r); + pa_assert(r); pa_xfree(r->name); pa_xfree(r->sink); @@ -468,11 +466,10 @@ static void free_func(void *p, void *userdata) { pa_xfree(r); } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata* u; - assert(c); - assert(m); + pa_assert(m); if (!(u = m->userdata)) return; diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index b9c4ad499..4eacbb1e1 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include @@ -67,30 +66,21 @@ static const char* const valid_modargs[] = { NULL }; -static int ring_bell(struct userdata *u, int percent) { - pa_sink *s; - assert(u); - - if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log("Invalid sink: %s", u->sink_name); - return -1; - } - - pa_scache_play_item(u->core, u->scache_item, s, (percent*PA_VOLUME_NORM)/100); - return 0; -} - static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) { XkbBellNotifyEvent *bne; struct userdata *u = userdata; - assert(w && e && u && u->x11_wrapper == w); + + pa_assert(w); + pa_assert(e); + pa_assert(u); + pa_assert(u->x11_wrapper == w); if (((XkbEvent*) e)->any.xkb_type != XkbBellNotify) return 0; bne = (XkbBellNotifyEvent*) e; - if (ring_bell(u, bne->percent) < 0) { + if (pa_scache_play_item_by_name(u->core, u->scache_item, u->sink_name, (bne->percent*PA_VOLUME_NORM)/100, 1) < 0) { pa_log_info("Ringing bell failed, reverting to X11 device bell."); XkbForceDeviceBell(pa_x11_wrapper_get_display(w), bne->device, bne->bell_class, bne->bell_id, bne->percent); } @@ -98,25 +88,27 @@ static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) { return 1; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { + struct userdata *u = NULL; pa_modargs *ma = NULL; int major, minor; unsigned int auto_ctrls, auto_values; - assert(c && m); + + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } - m->userdata = u = pa_xmalloc(sizeof(struct userdata)); - u->core = c; + m->userdata = u = pa_xnew(struct userdata, 1); + u->core = m->core; u->scache_item = pa_xstrdup(pa_modargs_get_value(ma, "sample", "x11-bell")); u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); u->x11_client = NULL; - if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) + if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) goto fail; major = XkbMajorVersion; @@ -130,7 +122,6 @@ int pa__init(pa_core *c, pa_module*m) { major = XkbMajorVersion; minor = XkbMinorVersion; - if (!XkbQueryExtension(pa_x11_wrapper_get_display(u->x11_wrapper), NULL, &u->xkb_event_base, NULL, &major, &minor)) { pa_log("XkbQueryExtension() failed"); goto fail; @@ -150,14 +141,21 @@ int pa__init(pa_core *c, pa_module*m) { fail: if (ma) pa_modargs_free(ma); - if (m->userdata) - pa__done(c, m); + + pa__done(m); + return -1; } -void pa__done(pa_core *c, pa_module*m) { - struct userdata *u = m->userdata; - assert(c && m && u); +void pa__done(pa_module*m) { + struct userdata *u; + + pa_assert(m); + + if (!m->userdata) + return; + + u = m->userdata; pa_xfree(u->scache_item); pa_xfree(u->sink_name); diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index fd1d532f5..e0550e207 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include #include @@ -76,7 +75,7 @@ struct userdata { }; static int load_key(struct userdata *u, const char*fn) { - assert(u); + pa_assert(u); u->auth_cookie_in_property = 0; @@ -93,7 +92,7 @@ static int load_key(struct userdata *u, const char*fn) { if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) return -1; - pa_log_debug("loading cookie from disk."); + pa_log_debug("Loading cookie from disk."); if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) u->auth_cookie_in_property = 1; @@ -101,7 +100,7 @@ static int load_key(struct userdata *u, const char*fn) { return 0; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { struct userdata *u; pa_modargs *ma = NULL; char hn[256], un[128]; @@ -110,23 +109,25 @@ int pa__init(pa_core *c, pa_module*m) { char *s; pa_strlist *l; + pa_assert(m); + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments"); goto fail; } m->userdata = u = pa_xmalloc(sizeof(struct userdata)); - u->core = c; + u->core = m->core; u->id = NULL; u->auth_cookie_in_property = 0; if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0) goto fail; - if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL)))) + if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) goto fail; - if (!(l = pa_property_get(c, PA_NATIVE_SERVER_PROPERTY_NAME))) + if (!(l = pa_property_get(m->core, PA_NATIVE_SERVER_PROPERTY_NAME))) goto fail; s = pa_strlist_tostring(l); @@ -154,13 +155,14 @@ fail: if (ma) pa_modargs_free(ma); - pa__done(c, m); + pa__done(m); return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata*u; - assert(c && m); + + pa_assert(m); if (!(u = m->userdata)) return; @@ -185,7 +187,7 @@ void pa__done(pa_core *c, pa_module*m) { pa_x11_wrapper_unref(u->x11_wrapper); if (u->auth_cookie_in_property) - pa_authkey_prop_unref(c, PA_NATIVE_COOKIE_PROPERTY_NAME); + pa_authkey_prop_unref(m->core, PA_NATIVE_COOKIE_PROPERTY_NAME); pa_xfree(u->id); pa_xfree(u); diff --git a/src/modules/module-x11-xsmp.c b/src/modules/module-x11-xsmp.c new file mode 100644 index 000000000..3e353caf0 --- /dev/null +++ b/src/modules/module-x11-xsmp.c @@ -0,0 +1,195 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "module-x11-xsmp-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("X11 session management") +PA_MODULE_VERSION(PACKAGE_VERSION) + +static int ice_in_use = 0; + +static const char* const valid_modargs[] = { + NULL +}; + +static void die_cb(SmcConn connection, SmPointer client_data){ + pa_core *c = PA_CORE(client_data); + + pa_log_debug("Got die message from XSM. Exiting..."); + + pa_core_assert_ref(c); + c->mainloop->quit(c->mainloop, 0); +} + +static void save_complete_cb(SmcConn connection, SmPointer client_data) { +} + +static void shutdown_cancelled_cb(SmcConn connection, SmPointer client_data) { + SmcSaveYourselfDone(connection, True); +} + +static void save_yourself_cb(SmcConn connection, SmPointer client_data, int save_type, Bool _shutdown, int interact_style, Bool fast) { + SmcSaveYourselfDone(connection, True); +} + +static void ice_io_cb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { + IceConn connection = userdata; + + if (IceProcessMessages(connection, NULL, NULL) == IceProcessMessagesIOError) { + IceSetShutdownNegotiation(connection, False); + IceCloseConnection(connection); + } +} + +static void new_ice_connection(IceConn connection, IcePointer client_data, Bool opening, IcePointer *watch_data) { + pa_core *c = client_data; + + pa_assert(c); + + if (opening) + *watch_data = c->mainloop->io_new(c->mainloop, IceConnectionNumber(connection), PA_IO_EVENT_INPUT, ice_io_cb, connection); + else + c->mainloop->io_free(*watch_data); +} + +int pa__init(pa_module*m) { + + pa_modargs *ma = NULL; + char t[256], *vendor, *client_id; + SmcCallbacks callbacks; + SmProp prop_program, prop_user; + SmProp *prop_list[2]; + SmPropValue val_program, val_user; + SmcConn connection; + + pa_assert(m); + + if (ice_in_use) { + pa_log("module-x11-xsmp may no be loaded twice."); + return -1; + } + + IceAddConnectionWatch(new_ice_connection, m->core); + ice_in_use = 1; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments"); + goto fail; + } + + if (!getenv("SESSION_MANAGER")) { + pa_log("X11 session manager not running."); + goto fail; + } + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.die.callback = die_cb; + callbacks.die.client_data = m->core; + callbacks.save_yourself.callback = save_yourself_cb; + callbacks.save_yourself.client_data = m->core; + callbacks.save_complete.callback = save_complete_cb; + callbacks.save_complete.client_data = m->core; + callbacks.shutdown_cancelled.callback = shutdown_cancelled_cb; + callbacks.shutdown_cancelled.client_data = m->core; + + if (!(m->userdata = connection = SmcOpenConnection( + NULL, m->core, + SmProtoMajor, SmProtoMinor, + SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, + &callbacks, NULL, &client_id, + sizeof(t), t))) { + + pa_log("Failed to open connection to session manager: %s", t); + goto fail; + } + + prop_program.name = (char*) SmProgram; + prop_program.type = (char*) SmARRAY8; + val_program.value = (char*) PACKAGE_NAME; + val_program.length = strlen(val_program.value); + prop_program.num_vals = 1; + prop_program.vals = &val_program; + prop_list[0] = &prop_program; + + prop_user.name = (char*) SmUserID; + prop_user.type = (char*) SmARRAY8; + pa_get_user_name(t, sizeof(t)); + val_user.value = t; + val_user.length = strlen(val_user.value); + prop_user.num_vals = 1; + prop_user.vals = &val_user; + prop_list[1] = &prop_user; + + SmcSetProperties(connection, PA_ELEMENTSOF(prop_list), prop_list); + + pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(connection), client_id); + free(vendor); + free(client_id); + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(m); + + return -1; +} + +void pa__done(pa_module*m) { + pa_assert(m); + + if (m->userdata) + SmcCloseConnection(m->userdata, 0, NULL); + + if (ice_in_use) { + IceRemoveConnectionWatch(new_ice_connection, m->core); + ice_in_use = 0; + } +} diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 69508ad03..113686cfd 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include #include @@ -35,11 +34,11 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -71,56 +70,52 @@ struct service { struct userdata *userdata; AvahiEntryGroup *entry_group; char *service_name; - char *name; - enum { UNPUBLISHED, PUBLISHED_REAL, PUBLISHED_AUTOLOAD } published ; - - struct { - int valid; - pa_namereg_type_t type; - uint32_t index; - } loaded; - - struct { - int valid; - pa_namereg_type_t type; - uint32_t index; - } autoload; + pa_object *device; }; struct userdata { pa_core *core; AvahiPoll *avahi_poll; AvahiClient *client; + pa_hashmap *services; - pa_dynarray *sink_dynarray, *source_dynarray, *autoload_dynarray; - pa_subscription *subscription; char *service_name; AvahiEntryGroup *main_entry_group; uint16_t port; + + pa_hook_slot *sink_new_slot, *source_new_slot, *sink_unlink_slot, *source_unlink_slot, *sink_changed_slot, *source_changed_slot; }; -static void get_service_data(struct userdata *u, struct service *s, pa_sample_spec *ret_ss, char **ret_description) { - assert(u && s && s->loaded.valid && ret_ss && ret_description); +static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_channel_map *ret_map, const char **ret_name, const char **ret_description) { + pa_assert(s); + pa_assert(ret_ss); + pa_assert(ret_description); + + if (pa_sink_isinstance(s->device)) { + pa_sink *sink = PA_SINK(s->device); - if (s->loaded.type == PA_NAMEREG_SINK) { - pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index); - assert(sink); *ret_ss = sink->sample_spec; + *ret_map = sink->channel_map; + *ret_name = sink->name; *ret_description = sink->description; - } else if (s->loaded.type == PA_NAMEREG_SOURCE) { - pa_source *source = pa_idxset_get_by_index(u->core->sources, s->loaded.index); - assert(source); + + } else if (pa_source_isinstance(s->device)) { + pa_source *source = PA_SOURCE(s->device); + *ret_ss = source->sample_spec; + *ret_map = source->channel_map; + *ret_name = source->name; *ret_description = source->description; } else - assert(0); + pa_assert_not_reached(); } static AvahiStringList* txt_record_server_data(pa_core *c, AvahiStringList *l) { char s[128]; - assert(c); + + pa_assert(c); l = avahi_string_list_add_pair(l, "server-version", PACKAGE_NAME" "PACKAGE_VERSION); l = avahi_string_list_add_pair(l, "user-name", pa_get_user_name(s, sizeof(s))); @@ -130,325 +125,217 @@ static AvahiStringList* txt_record_server_data(pa_core *c, AvahiStringList *l) { return l; } -static int publish_service(struct userdata *u, struct service *s); +static int publish_service(struct service *s); static void service_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) { struct service *s = userdata; - if (state == AVAHI_ENTRY_GROUP_COLLISION) { - char *t; + pa_assert(s); - t = avahi_alternative_service_name(s->service_name); - pa_xfree(s->service_name); - s->service_name = t; + switch (state) { - publish_service(s->userdata, s); + case AVAHI_ENTRY_GROUP_ESTABLISHED: + pa_log_info("Successfully established service %s.", s->service_name); + break; + + case AVAHI_ENTRY_GROUP_COLLISION: { + char *t; + + t = avahi_alternative_service_name(s->service_name); + pa_log_info("Name collision, renaming %s to %s.", s->service_name, t); + pa_xfree(s->service_name); + s->service_name = t; + + publish_service(s); + break; + } + + case AVAHI_ENTRY_GROUP_FAILURE: { + pa_log("Failed to register service: %s", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g)))); + + avahi_entry_group_free(g); + s->entry_group = NULL; + + break; + } + + case AVAHI_ENTRY_GROUP_UNCOMMITED: + case AVAHI_ENTRY_GROUP_REGISTERING: + ; } } -static int publish_service(struct userdata *u, struct service *s) { +static void service_free(struct service *s); + +static int publish_service(struct service *s) { int r = -1; AvahiStringList *txt = NULL; + const char *description = NULL, *name = NULL; + pa_sample_spec ss; + pa_channel_map map; + char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; - assert(u); - assert(s); + pa_assert(s); - if (!u->client || avahi_client_get_state(u->client) != AVAHI_CLIENT_S_RUNNING) + if (!s->userdata->client || avahi_client_get_state(s->userdata->client) != AVAHI_CLIENT_S_RUNNING) return 0; - if ((s->published == PUBLISHED_REAL && s->loaded.valid) || - (s->published == PUBLISHED_AUTOLOAD && s->autoload.valid && !s->loaded.valid)) - return 0; - - if (s->published != UNPUBLISHED) { + if (!s->entry_group) { + if (!(s->entry_group = avahi_entry_group_new(s->userdata->client, service_entry_group_callback, s))) { + pa_log("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); + goto finish; + } + } else avahi_entry_group_reset(s->entry_group); - s->published = UNPUBLISHED; + + txt = txt_record_server_data(s->userdata->core, txt); + + get_service_data(s, &ss, &map, &name, &description); + txt = avahi_string_list_add_pair(txt, "device", name); + txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate); + txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels); + txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format)); + txt = avahi_string_list_add_pair(txt, "channel_map", pa_channel_map_snprint(cm, sizeof(cm), &map)); + + if (avahi_entry_group_add_service_strlst( + s->entry_group, + AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + 0, + s->service_name, + pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE, + NULL, + NULL, + s->userdata->port, + txt) < 0) { + + pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); + goto finish; } - if (s->loaded.valid || s->autoload.valid) { - pa_namereg_type_t type; - - if (!s->entry_group) { - if (!(s->entry_group = avahi_entry_group_new(u->client, service_entry_group_callback, s))) { - pa_log("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(u->client))); - goto finish; - } - } - - txt = avahi_string_list_add_pair(txt, "device", s->name); - txt = txt_record_server_data(u->core, txt); - - if (s->loaded.valid) { - char *description; - pa_sample_spec ss; - - get_service_data(u, s, &ss, &description); - - txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate); - txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels); - txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format)); - if (description) - txt = avahi_string_list_add_pair(txt, "description", description); - - type = s->loaded.type; - } else if (s->autoload.valid) - type = s->autoload.type; - - if (avahi_entry_group_add_service_strlst( - s->entry_group, - AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, - 0, - s->service_name, - type == PA_NAMEREG_SINK ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE, - NULL, - NULL, - u->port, - txt) < 0) { - - pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(u->client))); - goto finish; - } - - if (avahi_entry_group_commit(s->entry_group) < 0) { - pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(u->client))); - goto finish; - } - - if (s->loaded.valid) - s->published = PUBLISHED_REAL; - else if (s->autoload.valid) - s->published = PUBLISHED_AUTOLOAD; + if (avahi_entry_group_commit(s->entry_group) < 0) { + pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); + goto finish; } r = 0; + pa_log_debug("Successfully created entry group for %s.", s->service_name); finish: - if (s->published == UNPUBLISHED) { - /* Remove this service */ + /* Remove this service */ + if (r < 0) + service_free(s); - if (s->entry_group) - avahi_entry_group_free(s->entry_group); - - pa_hashmap_remove(u->services, s->name); - pa_xfree(s->name); - pa_xfree(s->service_name); - pa_xfree(s); - } - - if (txt) - avahi_string_list_free(txt); + avahi_string_list_free(txt); return r; } -static struct service *get_service(struct userdata *u, const char *name, const char *description) { +static struct service *get_service(struct userdata *u, pa_object *device) { struct service *s; - char hn[64]; + char hn[64], un[64]; + const char *n; - if ((s = pa_hashmap_get(u->services, name))) + pa_assert(u); + pa_object_assert_ref(device); + + if ((s = pa_hashmap_get(u->services, device))) return s; s = pa_xnew(struct service, 1); s->userdata = u; s->entry_group = NULL; - s->published = UNPUBLISHED; - s->name = pa_xstrdup(name); - s->loaded.valid = s->autoload.valid = 0; - s->service_name = pa_sprintf_malloc("%s on %s", description ? description : s->name, pa_get_host_name(hn, sizeof(hn))); + s->device = device; - pa_hashmap_put(u->services, s->name, s); + if (pa_sink_isinstance(device)) { + if (!(n = PA_SINK(device)->description)) + n = PA_SINK(device)->name; + } else { + if (!(n = PA_SOURCE(device)->description)) + n = PA_SOURCE(device)->name; + } + + s->service_name = pa_truncate_utf8(pa_sprintf_malloc("%s@%s: %s", + pa_get_user_name(un, sizeof(un)), + pa_get_host_name(hn, sizeof(hn)), + n), + AVAHI_LABEL_MAX-1); + + pa_hashmap_put(u->services, s->device, s); return s; } -static int publish_sink(struct userdata *u, pa_sink *s) { - struct service *svc; - int ret; - assert(u && s); +static void service_free(struct service *s) { + pa_assert(s); - svc = get_service(u, s->name, s->description); - if (svc->loaded.valid) - return publish_service(u, svc); + pa_hashmap_remove(s->userdata->services, s->device); - svc->loaded.valid = 1; - svc->loaded.type = PA_NAMEREG_SINK; - svc->loaded.index = s->index; - - if ((ret = publish_service(u, svc)) < 0) - return ret; - - pa_dynarray_put(u->sink_dynarray, s->index, svc); - return ret; -} - -static int publish_source(struct userdata *u, pa_source *s) { - struct service *svc; - int ret; - - assert(u && s); - - svc = get_service(u, s->name, s->description); - if (svc->loaded.valid) - return publish_service(u, svc); - - svc->loaded.valid = 1; - svc->loaded.type = PA_NAMEREG_SOURCE; - svc->loaded.index = s->index; - - pa_dynarray_put(u->source_dynarray, s->index, svc); - - if ((ret = publish_service(u, svc)) < 0) - return ret; - - pa_dynarray_put(u->sink_dynarray, s->index, svc); - return ret; -} - -static int publish_autoload(struct userdata *u, pa_autoload_entry *s) { - struct service *svc; - int ret; - - assert(u && s); - - svc = get_service(u, s->name, NULL); - if (svc->autoload.valid) - return publish_service(u, svc); - - svc->autoload.valid = 1; - svc->autoload.type = s->type; - svc->autoload.index = s->index; - - if ((ret = publish_service(u, svc)) < 0) - return ret; - - pa_dynarray_put(u->autoload_dynarray, s->index, svc); - return ret; -} - -static int remove_sink(struct userdata *u, uint32_t idx) { - struct service *svc; - assert(u && idx != PA_INVALID_INDEX); - - if (!(svc = pa_dynarray_get(u->sink_dynarray, idx))) - return 0; - - if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SINK) - return 0; - - svc->loaded.valid = 0; - pa_dynarray_put(u->sink_dynarray, idx, NULL); - - return publish_service(u, svc); -} - -static int remove_source(struct userdata *u, uint32_t idx) { - struct service *svc; - assert(u && idx != PA_INVALID_INDEX); - - if (!(svc = pa_dynarray_get(u->source_dynarray, idx))) - return 0; - - if (!svc->loaded.valid || svc->loaded.type != PA_NAMEREG_SOURCE) - return 0; - - svc->loaded.valid = 0; - pa_dynarray_put(u->source_dynarray, idx, NULL); - - return publish_service(u, svc); -} - -static int remove_autoload(struct userdata *u, uint32_t idx) { - struct service *svc; - assert(u && idx != PA_INVALID_INDEX); - - if (!(svc = pa_dynarray_get(u->autoload_dynarray, idx))) - return 0; - - if (!svc->autoload.valid) - return 0; - - svc->autoload.valid = 0; - pa_dynarray_put(u->autoload_dynarray, idx, NULL); - - return publish_service(u, svc); -} - -static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { - struct userdata *u = userdata; - assert(u && c); - - switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) - case PA_SUBSCRIPTION_EVENT_SINK: { - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - pa_sink *sink; - - if ((sink = pa_idxset_get_by_index(c->sinks, idx))) { - if (publish_sink(u, sink) < 0) - goto fail; - } - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (remove_sink(u, idx) < 0) - goto fail; - } - - break; - - case PA_SUBSCRIPTION_EVENT_SOURCE: - - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - pa_source *source; - - if ((source = pa_idxset_get_by_index(c->sources, idx))) { - if (publish_source(u, source) < 0) - goto fail; - } - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (remove_source(u, idx) < 0) - goto fail; - } - - break; - - case PA_SUBSCRIPTION_EVENT_AUTOLOAD: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - pa_autoload_entry *autoload; - - if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, idx))) { - if (publish_autoload(u, autoload) < 0) - goto fail; - } - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (remove_autoload(u, idx) < 0) - goto fail; - } - - break; + if (s->entry_group) { + pa_log_debug("Removing entry group for %s.", s->service_name); + avahi_entry_group_free(s->entry_group); } - return; + pa_xfree(s->service_name); + pa_xfree(s); +} -fail: - if (u->subscription) { - pa_subscription_free(u->subscription); - u->subscription = NULL; - } +static pa_hook_result_t device_new_or_changed_cb(pa_core *c, pa_object *o, struct userdata *u) { + pa_assert(c); + pa_object_assert_ref(o); + + publish_service(get_service(u, o)); + + return PA_HOOK_OK; +} + +static pa_hook_result_t device_unlink_cb(pa_core *c, pa_object *o, struct userdata *u) { + struct service *s; + + pa_assert(c); + pa_object_assert_ref(o); + + if ((s = pa_hashmap_get(u->services, o))) + service_free(s); + + return PA_HOOK_OK; } static int publish_main_service(struct userdata *u); static void main_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) { struct userdata *u = userdata; - assert(u); + pa_assert(u); - if (state == AVAHI_ENTRY_GROUP_COLLISION) { - char *t; + switch (state) { - t = avahi_alternative_service_name(u->service_name); - pa_xfree(u->service_name); - u->service_name = t; + case AVAHI_ENTRY_GROUP_ESTABLISHED: + pa_log_info("Successfully established main service."); + break; - publish_main_service(u); + case AVAHI_ENTRY_GROUP_COLLISION: { + char *t; + + t = avahi_alternative_service_name(u->service_name); + pa_log_info("Name collision: renaming main service %s to %s.", u->service_name, t); + pa_xfree(u->service_name); + u->service_name = t; + + publish_main_service(u); + break; + } + + case AVAHI_ENTRY_GROUP_FAILURE: { + pa_log("Failed to register main service: %s", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g)))); + + avahi_entry_group_free(g); + u->main_entry_group = NULL; + break; + } + + case AVAHI_ENTRY_GROUP_UNCOMMITED: + case AVAHI_ENTRY_GROUP_REGISTERING: + break; } } @@ -456,6 +343,8 @@ static int publish_main_service(struct userdata *u) { AvahiStringList *txt = NULL; int r = -1; + pa_assert(u); + if (!u->main_entry_group) { if (!(u->main_entry_group = avahi_entry_group_new(u->client, main_entry_group_callback, u))) { pa_log("avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); @@ -464,7 +353,7 @@ static int publish_main_service(struct userdata *u) { } else avahi_entry_group_reset(u->main_entry_group); - txt = txt_record_server_data(u->core, NULL); + txt = txt_record_server_data(u->core, txt); if (avahi_entry_group_add_service_strlst( u->main_entry_group, @@ -497,26 +386,18 @@ fail: static int publish_all_services(struct userdata *u) { pa_sink *sink; pa_source *source; - pa_autoload_entry *autoload; int r = -1; uint32_t idx; - assert(u); + pa_assert(u); pa_log_debug("Publishing services in Zeroconf"); - for (sink = pa_idxset_first(u->core->sinks, &idx); sink; sink = pa_idxset_next(u->core->sinks, &idx)) - if (publish_sink(u, sink) < 0) - goto fail; + for (sink = PA_SINK(pa_idxset_first(u->core->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(u->core->sinks, &idx))) + publish_service(get_service(u, PA_OBJECT(sink))); - for (source = pa_idxset_first(u->core->sources, &idx); source; source = pa_idxset_next(u->core->sources, &idx)) - if (publish_source(u, source) < 0) - goto fail; - - if (u->core->autoload_idxset) - for (autoload = pa_idxset_first(u->core->autoload_idxset, &idx); autoload; autoload = pa_idxset_next(u->core->autoload_idxset, &idx)) - if (publish_autoload(u, autoload) < 0) - goto fail; + for (source = PA_SOURCE(pa_idxset_first(u->core->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(u->core->sources, &idx))) + publish_service(get_service(u, PA_OBJECT(source))); if (publish_main_service(u) < 0) goto fail; @@ -527,38 +408,44 @@ fail: return r; } -static void unpublish_all_services(struct userdata *u, int rem) { +static void unpublish_all_services(struct userdata *u, pa_bool_t rem) { void *state = NULL; struct service *s; - assert(u); + pa_assert(u); pa_log_debug("Unpublishing services in Zeroconf"); while ((s = pa_hashmap_iterate(u->services, &state, NULL))) { if (s->entry_group) { if (rem) { + pa_log_debug("Removing entry group for %s.", s->service_name); avahi_entry_group_free(s->entry_group); s->entry_group = NULL; - } else + } else { avahi_entry_group_reset(s->entry_group); + pa_log_debug("Resetting entry group for %s.", s->service_name); + } } - - s->published = UNPUBLISHED; } if (u->main_entry_group) { if (rem) { + pa_log_debug("Removing main entry group."); avahi_entry_group_free(u->main_entry_group); u->main_entry_group = NULL; - } else + } else { avahi_entry_group_reset(u->main_entry_group); + pa_log_debug("Resetting main entry group."); + } } } static void client_callback(AvahiClient *c, AvahiClientState state, void *userdata) { struct userdata *u = userdata; - assert(c); + + pa_assert(c); + pa_assert(u); u->client = c; @@ -568,13 +455,17 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda break; case AVAHI_CLIENT_S_COLLISION: - unpublish_all_services(u, 0); + pa_log_debug("Host name collision"); + unpublish_all_services(u, FALSE); break; case AVAHI_CLIENT_FAILURE: if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) { int error; - unpublish_all_services(u, 1); + + pa_log_debug("Avahi daemon disconnected."); + + unpublish_all_services(u, TRUE); avahi_client_free(u->client); if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) @@ -587,11 +478,12 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda } } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { + struct userdata *u; uint32_t port = PA_NATIVE_DEFAULT_PORT; pa_modargs *ma = NULL; - char hn[256]; + char hn[256], un[256]; int error; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -599,30 +491,29 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port == 0 || port >= 0xFFFF) { + if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port <= 0 || port > 0xFFFF) { pa_log("invalid port specified."); goto fail; } m->userdata = u = pa_xnew(struct userdata, 1); - u->core = c; + u->core = m->core; u->port = (uint16_t) port; - u->avahi_poll = pa_avahi_poll_new(c->mainloop); + u->avahi_poll = pa_avahi_poll_new(m->core->mainloop); - u->services = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - u->sink_dynarray = pa_dynarray_new(); - u->source_dynarray = pa_dynarray_new(); - u->autoload_dynarray = pa_dynarray_new(); + u->services = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); - u->subscription = pa_subscription_new(c, - PA_SUBSCRIPTION_MASK_SINK| - PA_SUBSCRIPTION_MASK_SOURCE| - PA_SUBSCRIPTION_MASK_AUTOLOAD, subscribe_callback, u); + u->sink_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_NEW_POST], (pa_hook_cb_t) device_new_or_changed_cb, u); + u->sink_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_DESCRIPTION_CHANGED], (pa_hook_cb_t) device_new_or_changed_cb, u); + u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], (pa_hook_cb_t) device_unlink_cb, u); + u->source_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_NEW_POST], (pa_hook_cb_t) device_new_or_changed_cb, u); + u->source_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_DESCRIPTION_CHANGED], (pa_hook_cb_t) device_new_or_changed_cb, u); + u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], (pa_hook_cb_t) device_unlink_cb, u); u->main_entry_group = NULL; - u->service_name = pa_xstrdup(pa_get_host_name(hn, sizeof(hn))); + u->service_name = pa_truncate_utf8(pa_sprintf_malloc("%s@%s", pa_get_user_name(un, sizeof(un)), pa_get_host_name(hn, sizeof(hn))), AVAHI_LABEL_MAX); if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { pa_log("pa_avahi_client_new() failed: %s", avahi_strerror(error)); @@ -634,7 +525,7 @@ int pa__init(pa_core *c, pa_module*m) { return 0; fail: - pa__done(c, m); + pa__done(m); if (ma) pa_modargs_free(ma); @@ -642,41 +533,34 @@ fail: return -1; } -static void service_free(void *p, void *userdata) { - struct service *s = p; - struct userdata *u = userdata; - - assert(s); - assert(u); - - if (s->entry_group) - avahi_entry_group_free(s->entry_group); - - pa_xfree(s->service_name); - pa_xfree(s->name); - pa_xfree(s); -} - -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata*u; - assert(c && m); + pa_assert(m); if (!(u = m->userdata)) return; - if (u->services) - pa_hashmap_free(u->services, service_free, u); + if (u->services) { + struct service *s; - if (u->subscription) - pa_subscription_free(u->subscription); + while ((s = pa_hashmap_get_first(u->services))) + service_free(s); - if (u->sink_dynarray) - pa_dynarray_free(u->sink_dynarray, NULL, NULL); - if (u->source_dynarray) - pa_dynarray_free(u->source_dynarray, NULL, NULL); - if (u->autoload_dynarray) - pa_dynarray_free(u->autoload_dynarray, NULL, NULL); + pa_hashmap_free(u->services, NULL, NULL); + } + if (u->sink_new_slot) + pa_hook_slot_free(u->sink_new_slot); + if (u->source_new_slot) + pa_hook_slot_free(u->source_new_slot); + if (u->sink_changed_slot) + pa_hook_slot_free(u->sink_changed_slot); + if (u->source_changed_slot) + pa_hook_slot_free(u->source_changed_slot); + if (u->sink_unlink_slot) + pa_hook_slot_free(u->sink_unlink_slot); + if (u->source_unlink_slot) + pa_hook_slot_free(u->source_unlink_slot); if (u->main_entry_group) avahi_entry_group_free(u->main_entry_group); @@ -690,4 +574,3 @@ void pa__done(pa_core *c, pa_module*m) { pa_xfree(u->service_name); pa_xfree(u); } - diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index fb531468a..25e45a350 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -26,7 +26,6 @@ #include #endif -#include #include #include #include @@ -37,9 +36,11 @@ #include #include +#include #include #include #include +#include #include "oss-util.h" @@ -47,46 +48,43 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) { int fd = -1; int caps; - assert(device && mode && (*mode == O_RDWR || *mode == O_RDONLY || *mode == O_WRONLY)); + pa_assert(device); + pa_assert(mode); + pa_assert(*mode == O_RDWR || *mode == O_RDONLY || *mode == O_WRONLY); if(!pcaps) pcaps = ∩︀ if (*mode == O_RDWR) { - if ((fd = open(device, O_RDWR|O_NDELAY)) >= 0) { - int dcaps, *tcaps; + if ((fd = open(device, O_RDWR|O_NDELAY|O_NOCTTY)) >= 0) { ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); - tcaps = pcaps ? pcaps : &dcaps; - - if (ioctl(fd, SNDCTL_DSP_GETCAPS, tcaps) < 0) { + if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { pa_log("SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno)); goto fail; } - if (*tcaps & DSP_CAP_DUPLEX) + if (*pcaps & DSP_CAP_DUPLEX) goto success; pa_log_warn("'%s' doesn't support full duplex", device); - close(fd); + pa_close(fd); } - if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) { - if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY)) < 0) { + if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY|O_NOCTTY)) < 0) { + if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY|O_NOCTTY)) < 0) { pa_log("open('%s'): %s", device, pa_cstrerror(errno)); goto fail; } } } else { - if ((fd = open(device, *mode|O_NDELAY)) < 0) { + if ((fd = open(device, *mode|O_NDELAY|O_NOCTTY)) < 0) { pa_log("open('%s'): %s", device, pa_cstrerror(errno)); goto fail; } } -success: - *pcaps = 0; if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) { @@ -94,12 +92,14 @@ success: goto fail; } +success: + pa_log_debug("capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s%s", *pcaps & DSP_CAP_BATCH ? " BATCH" : "", #ifdef DSP_CAP_BIND *pcaps & DSP_CAP_BIND ? " BIND" : "", #else - "", + "", #endif *pcaps & DSP_CAP_COPROC ? " COPROC" : "", *pcaps & DSP_CAP_DUPLEX ? " DUPLEX" : "", @@ -122,7 +122,7 @@ success: #ifdef DSP_CAP_MULTI *pcaps & DSP_CAP_MULTI ? " MULTI" : "", #else - "", + "", #endif #ifdef DSP_CAP_OUTPUT *pcaps & DSP_CAP_OUTPUT ? " OUTPUT" : "", @@ -142,13 +142,13 @@ success: #endif *pcaps & DSP_CAP_TRIGGER ? " TRIGGER" : ""); - pa_fd_set_cloexec(fd, 1); + pa_make_fd_cloexec(fd); return fd; fail: if (fd >= 0) - close(fd); + pa_close(fd); return -1; } @@ -166,7 +166,8 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { [PA_SAMPLE_FLOAT32BE] = AFMT_QUERY, /* not supported */ }; - assert(fd >= 0 && ss); + pa_assert(fd >= 0); + pa_assert(ss); orig_format = ss->format; @@ -199,7 +200,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { pa_log("SNDCTL_DSP_CHANNELS: %s", pa_cstrerror(errno)); return -1; } - assert(channels > 0); + pa_assert(channels > 0); if (ss->channels != channels) { pa_log_warn("device doesn't support %i channels, using %i channels.", ss->channels, channels); @@ -211,7 +212,7 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { pa_log("SNDCTL_DSP_SPEED: %s", pa_cstrerror(errno)); return -1; } - assert(speed > 0); + pa_assert(speed > 0); if (ss->rate != (unsigned) speed) { pa_log_warn("device doesn't support %i Hz, changed to %i Hz.", ss->rate, speed); @@ -248,27 +249,29 @@ int pa_oss_set_fragments(int fd, int nfrags, int frag_size) { return 0; } -static int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *volume) { +int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *volume) { char cv[PA_CVOLUME_SNPRINT_MAX]; unsigned vol; - assert(fd >= 0); - assert(ss); - assert(volume); + pa_assert(fd >= 0); + pa_assert(ss); + pa_assert(volume); if (ioctl(fd, mixer, &vol) < 0) return -1; + pa_cvolume_reset(volume, ss->channels); + volume->values[0] = ((vol & 0xFF) * PA_VOLUME_NORM) / 100; - if ((volume->channels = ss->channels) >= 2) + if (volume->channels >= 2) volume->values[1] = (((vol >> 8) & 0xFF) * PA_VOLUME_NORM) / 100; pa_log_debug("Read mixer settings: %s", pa_cvolume_snprint(cv, sizeof(cv), volume)); return 0; } -static int pa_oss_set_volume(int fd, int mixer, const pa_sample_spec *ss, const pa_cvolume *volume) { +int pa_oss_set_volume(int fd, long mixer, const pa_sample_spec *ss, const pa_cvolume *volume) { char cv[PA_CVOLUME_SNPRINT_MAX]; unsigned vol; pa_volume_t l, r; @@ -289,40 +292,38 @@ static int pa_oss_set_volume(int fd, int mixer, const pa_sample_spec *ss, const return 0; } -int pa_oss_get_pcm_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { - return pa_oss_get_volume(fd, SOUND_MIXER_READ_PCM, ss, volume); -} +static int get_device_number(const char *dev) { + char buf[PATH_MAX]; + const char *p, *e; -int pa_oss_set_pcm_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume) { - return pa_oss_set_volume(fd, SOUND_MIXER_WRITE_PCM, ss, volume); -} + if (readlink(dev, buf, sizeof(buf)) < 0) { + if (errno != EINVAL && errno != ENOLINK) + return -1; -int pa_oss_get_input_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume) { - return pa_oss_get_volume(fd, SOUND_MIXER_READ_IGAIN, ss, volume); -} + p = dev; + } else + p = buf; -int pa_oss_set_input_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume) { - return pa_oss_set_volume(fd, SOUND_MIXER_WRITE_IGAIN, ss, volume); + if ((e = strrchr(p, '/'))) + p = e+1; + + if (p == 0) + return 0; + + p = strchr(p, 0) -1; + + if (*p >= '0' && *p <= '9') + return *p - '0'; + + return -1; } int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { FILE *f; - const char *e = NULL; int n, r = -1; int b = 0; - if (strncmp(dev, "/dev/dsp", 8) == 0) - e = dev+8; - else if (strncmp(dev, "/dev/adsp", 9) == 0) - e = dev+9; - else - return -1; - - if (*e == 0) - n = 0; - else if (*e >= '0' && *e <= '9' && *(e+1) == 0) - n = *e - '0'; - else + if ((n = get_device_number(dev)) < 0) return -1; if (!(f = fopen("/dev/sndstat", "r")) && @@ -357,7 +358,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { if (device == n) { char *k = strchr(line, ':'); - assert(k); + pa_assert(k); k++; k += strspn(k, " "); @@ -373,3 +374,34 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { fclose(f); return r; } + +static int open_mixer(const char *mixer) { + int fd; + + if ((fd = open(mixer, O_RDWR|O_NDELAY|O_NOCTTY)) >= 0) + return fd; + + return -1; +} + +int pa_oss_open_mixer_for_device(const char *device) { + int n; + char *fn; + int fd; + + if ((n = get_device_number(device)) < 0) + return -1; + + if (n == 0) + if ((fd = open_mixer("/dev/mixer")) >= 0) + return fd; + + fn = pa_sprintf_malloc("/dev/mixer%i", n); + fd = open_mixer(fn); + pa_xfree(fn); + + if (fd < 0) + pa_log_warn("Failed to open mixer '%s': %s", device, pa_cstrerror(errno)); + + return fd; +} diff --git a/src/modules/oss-util.h b/src/modules/oss-util.h index 087e0d220..259a622a3 100644 --- a/src/modules/oss-util.h +++ b/src/modules/oss-util.h @@ -33,12 +33,11 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss); int pa_oss_set_fragments(int fd, int frags, int frag_size); -int pa_oss_get_pcm_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume); -int pa_oss_set_pcm_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume); - -int pa_oss_get_input_volume(int fd, const pa_sample_spec *ss, pa_cvolume *volume); -int pa_oss_set_input_volume(int fd, const pa_sample_spec *ss, const pa_cvolume *volume); +int pa_oss_set_volume(int fd, long mixer, const pa_sample_spec *ss, const pa_cvolume *volume); +int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *volume); int pa_oss_get_hw_description(const char *dev, char *name, size_t l); +int pa_oss_open_mixer_for_device(const char *device); + #endif diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 62ef561f1..6c0189312 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -24,7 +24,6 @@ #include #endif -#include #include #include #include @@ -32,6 +31,7 @@ #include #include #include +#include #include #include @@ -47,6 +47,10 @@ #include #include #include +#include +#include +#include +#include #include "module-rtp-recv-symdef.h" @@ -66,7 +70,7 @@ PA_MODULE_USAGE( #define DEFAULT_SAP_ADDRESS "224.0.0.56" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define MAX_SESSIONS 16 -#define DEATH_TIMEOUT 20000000 +#define DEATH_TIMEOUT 20 static const char* const valid_modargs[] = { "sink", @@ -76,102 +80,126 @@ static const char* const valid_modargs[] = { struct session { struct userdata *userdata; + PA_LLIST_FIELDS(struct session); pa_sink_input *sink_input; pa_memblockq *memblockq; - pa_time_event *death_event; - - int first_packet; + pa_bool_t first_packet; uint32_t ssrc; uint32_t offset; struct pa_sdp_info sdp_info; pa_rtp_context rtp_context; - pa_io_event* rtp_event; + + pa_rtpoll_item *rtpoll_item; + + pa_atomic_t timestamp; }; struct userdata { pa_module *module; - pa_core *core; pa_sap_context sap_context; pa_io_event* sap_event; - pa_hashmap *by_origin; + pa_time_event *check_death_event; char *sink_name; + PA_LLIST_HEAD(struct session, sessions); + pa_hashmap *by_origin; int n_sessions; }; -static void session_free(struct session *s, int from_hash); +static void session_free(struct session *s); -static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { +/* Called from I/O thread context */ +static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct session *s = PA_SINK_INPUT(o)->userdata; + + switch (code) { + case PA_SINK_INPUT_MESSAGE_GET_LATENCY: + *((pa_usec_t*) data) = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); + + /* Fall through, the default handler will add in the extra + * latency added by the resampler */ + break; + } + + return pa_sink_input_process_msg(o, code, data, offset, chunk); +} + +/* Called from I/O thread context */ +static int sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk) { struct session *s; - assert(i); - s = i->userdata; + pa_sink_input_assert_ref(i); + pa_assert_se(s = i->userdata); return pa_memblockq_peek(s->memblockq, chunk); } -static void sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { +/* Called from I/O thread context */ +static void sink_input_drop(pa_sink_input *i, size_t length) { struct session *s; - assert(i); - s = i->userdata; + pa_sink_input_assert_ref(i); + pa_assert_se(s = i->userdata); - pa_memblockq_drop(s->memblockq, chunk, length); + pa_memblockq_drop(s->memblockq, length); } +/* Called from main context */ static void sink_input_kill(pa_sink_input* i) { struct session *s; - assert(i); - s = i->userdata; + pa_sink_input_assert_ref(i); + pa_assert_se(s = i->userdata); - session_free(s, 1); + session_free(s); } -static pa_usec_t sink_input_get_latency(pa_sink_input *i) { - struct session *s; - assert(i); - s = i->userdata; - - return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec); -} - -static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { - struct session *s = userdata; +/* Called from I/O thread context */ +static int rtpoll_work_cb(pa_rtpoll_item *i) { pa_memchunk chunk; int64_t k, j, delta; - struct timeval tv; + struct timeval now; + struct session *s; + struct pollfd *p; - assert(m); - assert(e); - assert(s); - assert(fd == s->rtp_context.fd); - assert(flags == PA_IO_EVENT_INPUT); + pa_assert_se(s = pa_rtpoll_item_get_userdata(i)); - if (pa_rtp_recv(&s->rtp_context, &chunk, s->userdata->core->mempool) < 0) - return; + p = pa_rtpoll_item_get_pollfd(i, NULL); + + if (p->revents & (POLLERR|POLLNVAL|POLLHUP|POLLOUT)) { + pa_log("poll() signalled bad revents."); + return -1; + } + + if ((p->revents & POLLIN) == 0) + return 0; + + p->revents = 0; + + if (pa_rtp_recv(&s->rtp_context, &chunk, s->userdata->module->core->mempool) < 0) + return 0; if (s->sdp_info.payload != s->rtp_context.payload) { pa_memblock_unref(chunk.memblock); - return; + return 0; } if (!s->first_packet) { - s->first_packet = 1; + s->first_packet = TRUE; s->ssrc = s->rtp_context.ssrc; s->offset = s->rtp_context.timestamp; - if (s->ssrc == s->userdata->core->cookie) - pa_log_warn("WARNING! Detected RTP packet loop!"); + if (s->ssrc == s->userdata->module->core->cookie) + pa_log_warn("Detected RTP packet loop!"); } else { if (s->ssrc != s->rtp_context.ssrc) { pa_memblock_unref(chunk.memblock); - return; + return 0; } } @@ -197,26 +225,49 @@ static void rtp_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event pa_memblock_unref(chunk.memblock); - /* Reset death timer */ - pa_gettimeofday(&tv); - pa_timeval_add(&tv, DEATH_TIMEOUT); - m->time_restart(s->death_event, &tv); + pa_rtclock_get(&now); + pa_atomic_store(&s->timestamp, now.tv_sec); + + return 1; } -static void death_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct timeval *tv, void *userdata) { - struct session *s = userdata; +/* Called from I/O thread context */ +static void sink_input_attach(pa_sink_input *i) { + struct session *s; + struct pollfd *p; - assert(m); - assert(t); - assert(tv); - assert(s); + pa_sink_input_assert_ref(i); + pa_assert_se(s = i->userdata); - session_free(s, 1); + pa_assert(!s->rtpoll_item); + s->rtpoll_item = pa_rtpoll_item_new(i->sink->rtpoll, PA_RTPOLL_LATE, 1); + + p = pa_rtpoll_item_get_pollfd(s->rtpoll_item, NULL); + p->fd = s->rtp_context.fd; + p->events = POLLIN; + p->revents = 0; + + pa_rtpoll_item_set_work_callback(s->rtpoll_item, rtpoll_work_cb); + pa_rtpoll_item_set_userdata(s->rtpoll_item, s); +} + +/* Called from I/O thread context */ +static void sink_input_detach(pa_sink_input *i) { + struct session *s; + pa_sink_input_assert_ref(i); + pa_assert_se(s = i->userdata); + + pa_assert(s->rtpoll_item); + pa_rtpoll_item_free(s->rtpoll_item); + s->rtpoll_item = NULL; } static int mcast_socket(const struct sockaddr* sa, socklen_t salen) { int af, fd = -1, r, one; + pa_assert(sa); + pa_assert(salen > 0); + af = sa->sa_family; if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) { pa_log("Failed to create socket: %s", pa_cstrerror(errno)); @@ -262,27 +313,34 @@ fail: static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_info) { struct session *s = NULL; - struct timeval tv; char *c; pa_sink *sink; int fd = -1; pa_memblock *silence; pa_sink_input_new_data data; + struct timeval now; + + pa_assert(u); + pa_assert(sdp_info); if (u->n_sessions >= MAX_SESSIONS) { - pa_log("session limit reached."); + pa_log("Session limit reached."); goto fail; } - if (!(sink = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) { - pa_log("sink does not exist."); + if (!(sink = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) { + pa_log("Sink does not exist."); goto fail; } s = pa_xnew0(struct session, 1); s->userdata = u; - s->first_packet = 0; + s->first_packet = FALSE; s->sdp_info = *sdp_info; + s->rtpoll_item = NULL; + + pa_rtclock_get(&now); + pa_atomic_store(&s->timestamp, now.tv_sec); if ((fd = mcast_socket((const struct sockaddr*) &sdp_info->sa, sdp_info->salen)) < 0) goto fail; @@ -299,25 +357,27 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in data.module = u->module; pa_sink_input_new_data_set_sample_spec(&data, &sdp_info->sample_spec); - s->sink_input = pa_sink_input_new(u->core, &data, 0); + s->sink_input = pa_sink_input_new(u->module->core, &data, 0); pa_xfree(c); if (!s->sink_input) { - pa_log("failed to create sink input."); + pa_log("Failed to create sink input."); goto fail; } s->sink_input->userdata = s; + s->sink_input->parent.process_msg = sink_input_process_msg; s->sink_input->peek = sink_input_peek; s->sink_input->drop = sink_input_drop; s->sink_input->kill = sink_input_kill; - s->sink_input->get_latency = sink_input_get_latency; + s->sink_input->attach = sink_input_attach; + s->sink_input->detach = sink_input_detach; - silence = pa_silence_memblock_new(s->userdata->core->mempool, - &s->sink_input->sample_spec, - (pa_bytes_per_second(&s->sink_input->sample_spec)/128/pa_frame_size(&s->sink_input->sample_spec))* - pa_frame_size(&s->sink_input->sample_spec)); + silence = pa_silence_memblock_new( + s->userdata->module->core->mempool, + &s->sink_input->sample_spec, + pa_frame_align(pa_bytes_per_second(&s->sink_input->sample_spec)/128, &s->sink_input->sample_spec)); s->memblockq = pa_memblockq_new( 0, @@ -330,54 +390,44 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in pa_memblock_unref(silence); - s->rtp_event = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, rtp_event_cb, s); - - pa_gettimeofday(&tv); - pa_timeval_add(&tv, DEATH_TIMEOUT); - s->death_event = u->core->mainloop->time_new(u->core->mainloop, &tv, death_event_cb, s); - - pa_hashmap_put(s->userdata->by_origin, s->sdp_info.origin, s); - pa_rtp_context_init_recv(&s->rtp_context, fd, pa_frame_size(&s->sdp_info.sample_spec)); - pa_log_info("Found new session '%s'", s->sdp_info.session_name); - + pa_hashmap_put(s->userdata->by_origin, s->sdp_info.origin, s); u->n_sessions++; + PA_LLIST_PREPEND(struct session, s->userdata->sessions, s); + + pa_sink_input_put(s->sink_input); + + pa_log_info("New session '%s'", s->sdp_info.session_name); return s; fail: - if (s) { - if (fd >= 0) - close(fd); + pa_xfree(s); - pa_xfree(s); - } + if (fd >= 0) + pa_close(fd); return NULL; } -static void session_free(struct session *s, int from_hash) { - assert(s); +static void session_free(struct session *s) { + pa_assert(s); pa_log_info("Freeing session '%s'", s->sdp_info.session_name); - s->userdata->core->mainloop->time_free(s->death_event); - s->userdata->core->mainloop->io_free(s->rtp_event); - - if (from_hash) - pa_hashmap_remove(s->userdata->by_origin, s->sdp_info.origin); - - pa_sink_input_disconnect(s->sink_input); + pa_sink_input_unlink(s->sink_input); pa_sink_input_unref(s->sink_input); + PA_LLIST_REMOVE(struct session, s->userdata->sessions, s); + pa_assert(s->userdata->n_sessions >= 1); + s->userdata->n_sessions--; + pa_hashmap_remove(s->userdata->by_origin, s->sdp_info.origin); + pa_memblockq_free(s->memblockq); pa_sdp_info_destroy(&s->sdp_info); pa_rtp_context_destroy(&s->rtp_context); - assert(s->userdata->n_sessions >= 1); - s->userdata->n_sessions--; - pa_xfree(s); } @@ -387,11 +437,11 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event pa_sdp_info info; struct session *s; - assert(m); - assert(e); - assert(u); - assert(fd == u->sap_context.fd); - assert(flags == PA_IO_EVENT_INPUT); + pa_assert(m); + pa_assert(e); + pa_assert(u); + pa_assert(fd == u->sap_context.fd); + pa_assert(flags == PA_IO_EVENT_INPUT); if (pa_sap_recv(&u->sap_context, &goodbye) < 0) return; @@ -402,7 +452,7 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event if (goodbye) { if ((s = pa_hashmap_get(u->by_origin, info.origin))) - session_free(s, 1); + session_free(s); pa_sdp_info_destroy(&info); } else { @@ -412,18 +462,47 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event pa_sdp_info_destroy(&info); } else { - struct timeval tv; - - pa_gettimeofday(&tv); - pa_timeval_add(&tv, DEATH_TIMEOUT); - m->time_restart(s->death_event, &tv); + struct timeval now; + pa_rtclock_get(&now); + pa_atomic_store(&s->timestamp, now.tv_sec); pa_sdp_info_destroy(&info); } } } -int pa__init(pa_core *c, pa_module*m) { +static void check_death_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct timeval *ptv, void *userdata) { + struct session *s, *n; + struct userdata *u = userdata; + struct timeval now; + struct timeval tv; + + pa_assert(m); + pa_assert(t); + pa_assert(ptv); + pa_assert(u); + + pa_rtclock_get(&now); + + pa_log_debug("Checking for dead streams ..."); + + for (s = u->sessions; s; s = n) { + int k; + n = s->next; + + k = pa_atomic_load(&s->timestamp); + + if (k + DEATH_TIMEOUT < now.tv_sec) + session_free(s); + } + + /* Restart timer */ + pa_gettimeofday(&tv); + pa_timeval_add(&tv, DEATH_TIMEOUT*PA_USEC_PER_SEC); + m->time_restart(t, &tv); +} + +int pa__init(pa_module*m) { struct userdata *u; pa_modargs *ma = NULL; struct sockaddr_in sa4; @@ -432,9 +511,9 @@ int pa__init(pa_core *c, pa_module*m) { socklen_t salen; const char *sap_address; int fd = -1; + struct timeval tv; - assert(c); - assert(m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments"); @@ -454,7 +533,7 @@ int pa__init(pa_core *c, pa_module*m) { sa = (struct sockaddr*) &sa4; salen = sizeof(sa4); } else { - pa_log("invalid SAP address '%s'", sap_address); + pa_log("Invalid SAP address '%s'", sap_address); goto fail; } @@ -464,15 +543,18 @@ int pa__init(pa_core *c, pa_module*m) { u = pa_xnew(struct userdata, 1); m->userdata = u; u->module = m; - u->core = c; u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + + u->sap_event = m->core->mainloop->io_new(m->core->mainloop, fd, PA_IO_EVENT_INPUT, sap_event_cb, u); + pa_sap_context_init_recv(&u->sap_context, fd); + + PA_LLIST_HEAD_INIT(struct session, u->sessions); u->n_sessions = 0; - - u->sap_event = c->mainloop->io_new(c->mainloop, fd, PA_IO_EVENT_INPUT, sap_event_cb, u); - u->by_origin = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - pa_sap_context_init_recv(&u->sap_context, fd); + pa_gettimeofday(&tv); + pa_timeval_add(&tv, DEATH_TIMEOUT * PA_USEC_PER_SEC); + u->check_death_event = m->core->mainloop->time_new(m->core->mainloop, &tv, check_death_event_cb, u); pa_modargs_free(ma); @@ -483,27 +565,34 @@ fail: pa_modargs_free(ma); if (fd >= 0) - close(fd); + pa_close(fd); return -1; } -static void free_func(void *p, PA_GCC_UNUSED void *userdata) { - session_free(p, 0); -} - -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c); - assert(m); + struct session *s; + + pa_assert(m); if (!(u = m->userdata)) return; - c->mainloop->io_free(u->sap_event); + if (u->sap_event) + m->core->mainloop->io_free(u->sap_event); + + if (u->check_death_event) + m->core->mainloop->time_free(u->check_death_event); + pa_sap_context_destroy(&u->sap_context); - pa_hashmap_free(u->by_origin, free_func, NULL); + if (u->by_origin) { + while ((s = pa_hashmap_get_first(u->by_origin))) + session_free(s); + + pa_hashmap_free(u->by_origin, NULL, NULL); + } pa_xfree(u->sink_name); pa_xfree(u); diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 8c9e5f23c..f36989bdd 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -25,7 +25,6 @@ #include #endif -#include #include #include #include @@ -48,6 +47,9 @@ #include #include #include +#include +#include +#include #include "module-rtp-send-symdef.h" @@ -74,7 +76,7 @@ PA_MODULE_USAGE( #define DEFAULT_DESTINATION "224.0.0.56" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define DEFAULT_MTU 1280 -#define SAP_INTERVAL 5000000 +#define SAP_INTERVAL 5 static const char* const valid_modargs[] = { "source", @@ -90,7 +92,6 @@ static const char* const valid_modargs[] = { struct userdata { pa_module *module; - pa_core *core; pa_source_output *source_output; pa_memblockq *memblockq; @@ -102,56 +103,67 @@ struct userdata { pa_time_event *sap_event; }; +/* Called from I/O thread context */ +static int source_output_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u; + pa_assert_se(u = PA_SOURCE_OUTPUT(o)->userdata); + + switch (code) { + case PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY: + *((pa_usec_t*) data) = pa_bytes_to_usec(pa_memblockq_get_length(u->memblockq), &u->source_output->sample_spec); + + /* Fall through, the default handler will add in the extra + * latency added by the resampler */ + break; + } + + return pa_source_output_process_msg(o, code, data, offset, chunk); +} + +/* Called from I/O thread context */ static void source_output_push(pa_source_output *o, const pa_memchunk *chunk) { struct userdata *u; - assert(o); - u = o->userdata; + pa_source_output_assert_ref(o); + pa_assert_se(u = o->userdata); if (pa_memblockq_push(u->memblockq, chunk) < 0) { - pa_log("Failed to push chunk into memblockq."); + pa_log_warn("Failed to push chunk into memblockq."); return; } pa_rtp_send(&u->rtp_context, u->mtu, u->memblockq); } +/* Called from main context */ static void source_output_kill(pa_source_output* o) { struct userdata *u; - assert(o); - u = o->userdata; + pa_source_output_assert_ref(o); + pa_assert_se(u = o->userdata); pa_module_unload_request(u->module); - pa_source_output_disconnect(u->source_output); + pa_source_output_unlink(u->source_output); pa_source_output_unref(u->source_output); u->source_output = NULL; } -static pa_usec_t source_output_get_latency (pa_source_output *o) { - struct userdata *u; - assert(o); - u = o->userdata; - - return pa_bytes_to_usec(pa_memblockq_get_length(u->memblockq), &o->sample_spec); -} - static void sap_event_cb(pa_mainloop_api *m, pa_time_event *t, const struct timeval *tv, void *userdata) { struct userdata *u = userdata; struct timeval next; - assert(m); - assert(t); - assert(tv); - assert(u); + pa_assert(m); + pa_assert(t); + pa_assert(tv); + pa_assert(u); pa_sap_send(&u->sap_context, 0); pa_gettimeofday(&next); - pa_timeval_add(&next, SAP_INTERVAL); + pa_timeval_add(&next, SAP_INTERVAL * PA_USEC_PER_SEC); m->time_restart(t, &next); } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { struct userdata *u; pa_modargs *ma = NULL; const char *dest; @@ -173,21 +185,20 @@ int pa__init(pa_core *c, pa_module*m) { int loop = 0; pa_source_output_new_data data; - assert(c); - assert(m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } if (!(s = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source", NULL), PA_NAMEREG_SOURCE, 1))) { - pa_log("source does not exist."); + pa_log("Source does not exist."); goto fail; } if (pa_modargs_get_value_boolean(ma, "loop", &loop) < 0) { - pa_log("failed to parse \"loop\" parameter."); + pa_log("Failed to parse \"loop\" parameter."); goto fail; } @@ -195,12 +206,12 @@ int pa__init(pa_core *c, pa_module*m) { pa_rtp_sample_spec_fixup(&ss); cm = s->channel_map; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - pa_log("failed to parse sample specification"); + pa_log("Failed to parse sample specification"); goto fail; } if (!pa_rtp_sample_spec_valid(&ss)) { - pa_log("specified sample type not compatible with RTP"); + pa_log("Specified sample type not compatible with RTP"); goto fail; } @@ -209,10 +220,10 @@ int pa__init(pa_core *c, pa_module*m) { payload = pa_rtp_payload_from_sample_spec(&ss); - mtu = (DEFAULT_MTU/pa_frame_size(&ss))*pa_frame_size(&ss); + mtu = pa_frame_align(DEFAULT_MTU, &ss); if (pa_modargs_get_value_u32(ma, "mtu", &mtu) < 0 || mtu < 1 || mtu % pa_frame_size(&ss) != 0) { - pa_log("invalid mtu."); + pa_log("Invalid MTU."); goto fail; } @@ -223,7 +234,7 @@ int pa__init(pa_core *c, pa_module*m) { } if (port & 1) - pa_log_warn("WARNING: port number not even as suggested in RFC3550!"); + pa_log_warn("Port number not even as suggested in RFC3550!"); dest = pa_modargs_get_value(ma, "destination", DEFAULT_DESTINATION); @@ -238,7 +249,7 @@ int pa__init(pa_core *c, pa_module*m) { sap_sa4 = sa4; sap_sa4.sin_port = htons(SAP_PORT); } else { - pa_log("invalid destination '%s'", dest); + pa_log("Invalid destination '%s'", dest); goto fail; } @@ -268,6 +279,12 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } + /* If the socket queue is full, let's drop packets */ + pa_make_fd_nonblock(fd); + pa_make_udp_socket_low_delay(fd); + pa_make_fd_cloexec(fd); + pa_make_fd_cloexec(sap_fd); + pa_source_output_new_data_init(&data); data.name = "RTP Monitor Stream"; data.driver = __FILE__; @@ -276,21 +293,20 @@ int pa__init(pa_core *c, pa_module*m) { pa_source_output_new_data_set_sample_spec(&data, &ss); pa_source_output_new_data_set_channel_map(&data, &cm); - if (!(o = pa_source_output_new(c, &data, 0))) { + if (!(o = pa_source_output_new(m->core, &data, 0))) { pa_log("failed to create source output."); goto fail; } + o->parent.process_msg = source_output_process_msg; o->push = source_output_push; o->kill = source_output_kill; - o->get_latency = source_output_get_latency; u = pa_xnew(struct userdata, 1); m->userdata = u; o->userdata = u; u->module = m; - u->core = c; u->source_output = o; u->memblockq = pa_memblockq_new( @@ -305,8 +321,7 @@ int pa__init(pa_core *c, pa_module*m) { u->mtu = mtu; k = sizeof(sa_dst); - r = getsockname(fd, (struct sockaddr*) &sa_dst, &k); - assert(r >= 0); + pa_assert_se((r = getsockname(fd, (struct sockaddr*) &sa_dst, &k)) >= 0); n = pa_sprintf_malloc("PulseAudio RTP Stream on %s", pa_get_fqdn(hn, sizeof(hn))); @@ -317,17 +332,19 @@ int pa__init(pa_core *c, pa_module*m) { pa_xfree(n); - pa_rtp_context_init_send(&u->rtp_context, fd, c->cookie, payload, pa_frame_size(&ss)); + pa_rtp_context_init_send(&u->rtp_context, fd, m->core->cookie, payload, pa_frame_size(&ss)); pa_sap_context_init_send(&u->sap_context, sap_fd, p); pa_log_info("RTP stream initialized with mtu %u on %s:%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dest, port, u->rtp_context.ssrc, payload, u->rtp_context.sequence); - pa_log_info("SDP-Data:\n%s\n"__FILE__": EOF", p); + pa_log_info("SDP-Data:\n%s\nEOF", p); pa_sap_send(&u->sap_context, 0); pa_gettimeofday(&tv); - pa_timeval_add(&tv, SAP_INTERVAL); - u->sap_event = c->mainloop->time_new(c->mainloop, &tv, sap_event_cb, u); + pa_timeval_add(&tv, SAP_INTERVAL * PA_USEC_PER_SEC); + u->sap_event = m->core->mainloop->time_new(m->core->mainloop, &tv, sap_event_cb, u); + + pa_source_output_put(u->source_output); pa_modargs_free(ma); @@ -338,31 +355,31 @@ fail: pa_modargs_free(ma); if (fd >= 0) - close(fd); + pa_close(fd); if (sap_fd >= 0) - close(sap_fd); + pa_close(sap_fd); if (o) { - pa_source_output_disconnect(o); + pa_source_output_unlink(o); pa_source_output_unref(o); } return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata *u; - assert(c); - assert(m); + pa_assert(m); if (!(u = m->userdata)) return; - c->mainloop->time_free(u->sap_event); + if (u->sap_event) + m->core->mainloop->time_free(u->sap_event); if (u->source_output) { - pa_source_output_disconnect(u->source_output); + pa_source_output_unlink(u->source_output); pa_source_output_unref(u->source_output); } @@ -371,7 +388,8 @@ void pa__done(pa_core *c, pa_module*m) { pa_sap_send(&u->sap_context, 1); pa_sap_context_destroy(&u->sap_context); - pa_memblockq_free(u->memblockq); + if (u->memblockq) + pa_memblockq_free(u->memblockq); pa_xfree(u); } diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c index 03a01412d..997fcc348 100644 --- a/src/modules/rtp/rtp.c +++ b/src/modules/rtp/rtp.c @@ -25,7 +25,6 @@ #include #endif -#include #include #include #include @@ -40,12 +39,14 @@ #include #include +#include +#include #include "rtp.h" pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size) { - assert(c); - assert(fd >= 0); + pa_assert(c); + pa_assert(fd >= 0); c->fd = fd; c->sequence = (uint16_t) (rand()*rand()); @@ -63,11 +64,11 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { struct iovec iov[MAX_IOVECS]; pa_memblock* mb[MAX_IOVECS]; int iov_idx = 1; - size_t n = 0, skip = 0; + size_t n = 0; - assert(c); - assert(size > 0); - assert(q); + pa_assert(c); + pa_assert(size > 0); + pa_assert(q); if (pa_memblockq_get_length(q) < size) return 0; @@ -76,24 +77,26 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { int r; pa_memchunk chunk; + pa_memchunk_reset(&chunk); + if ((r = pa_memblockq_peek(q, &chunk)) >= 0) { size_t k = n + chunk.length > size ? size - n : chunk.length; - if (chunk.memblock) { - iov[iov_idx].iov_base = (void*)((uint8_t*) chunk.memblock->data + chunk.index); - iov[iov_idx].iov_len = k; - mb[iov_idx] = chunk.memblock; - iov_idx ++; + pa_assert(chunk.memblock); - n += k; - } + iov[iov_idx].iov_base = ((uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index); + iov[iov_idx].iov_len = k; + mb[iov_idx] = chunk.memblock; + iov_idx ++; - skip += k; - pa_memblockq_drop(q, &chunk, k); + n += k; + pa_memblockq_drop(q, k); } - if (r < 0 || !chunk.memblock || n >= size || iov_idx >= MAX_IOVECS) { + pa_assert(n % c->frame_size == 0); + + if (r < 0 || n >= size || iov_idx >= MAX_IOVECS) { uint32_t header[3]; struct msghdr m; int k, i; @@ -116,17 +119,19 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { k = sendmsg(c->fd, &m, MSG_DONTWAIT); - for (i = 1; i < iov_idx; i++) + for (i = 1; i < iov_idx; i++) { + pa_memblock_release(mb[i]); pa_memblock_unref(mb[i]); + } c->sequence++; } else k = 0; - c->timestamp += skip/c->frame_size; + c->timestamp += n/c->frame_size; if (k < 0) { - if (errno != EAGAIN) /* If the queue is full, just ignore it */ + if (errno != EAGAIN && errno != EINTR) /* If the queue is full, just ignore it */ pa_log("sendmsg() failed: %s", pa_cstrerror(errno)); return -1; } @@ -135,7 +140,6 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { break; n = 0; - skip = 0; iov_idx = 1; } } @@ -144,7 +148,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) { } pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame_size) { - assert(c); + pa_assert(c); c->fd = fd; c->frame_size = frame_size; @@ -159,13 +163,13 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { int cc; ssize_t r; - assert(c); - assert(chunk); + pa_assert(c); + pa_assert(chunk); - chunk->memblock = NULL; + pa_memchunk_reset(chunk); if (ioctl(c->fd, FIONREAD, &size) < 0) { - pa_log("FIONREAD failed: %s", pa_cstrerror(errno)); + pa_log_warn("FIONREAD failed: %s", pa_cstrerror(errno)); goto fail; } @@ -174,7 +178,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { chunk->memblock = pa_memblock_new(pool, size); - iov.iov_base = chunk->memblock->data; + iov.iov_base = pa_memblock_acquire(chunk->memblock); iov.iov_len = size; m.msg_name = NULL; @@ -185,36 +189,41 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { m.msg_controllen = 0; m.msg_flags = 0; - if ((r = recvmsg(c->fd, &m, 0)) != size) { - pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); + r = recvmsg(c->fd, &m, 0); + pa_memblock_release(chunk->memblock); + + if (r != size) { + if (r < 0 && errno != EAGAIN && errno != EINTR) + pa_log_warn("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); + goto fail; } if (size < 12) { - pa_log("RTP packet too short."); + pa_log_warn("RTP packet too short."); goto fail; } - memcpy(&header, chunk->memblock->data, sizeof(uint32_t)); - memcpy(&c->timestamp, (uint8_t*) chunk->memblock->data + 4, sizeof(uint32_t)); - memcpy(&c->ssrc, (uint8_t*) chunk->memblock->data + 8, sizeof(uint32_t)); + memcpy(&header, iov.iov_base, sizeof(uint32_t)); + memcpy(&c->timestamp, (uint8_t*) iov.iov_base + 4, sizeof(uint32_t)); + memcpy(&c->ssrc, (uint8_t*) iov.iov_base + 8, sizeof(uint32_t)); header = ntohl(header); c->timestamp = ntohl(c->timestamp); c->ssrc = ntohl(c->ssrc); if ((header >> 30) != 2) { - pa_log("Unsupported RTP version."); + pa_log_warn("Unsupported RTP version."); goto fail; } if ((header >> 29) & 1) { - pa_log("RTP padding not supported."); + pa_log_warn("RTP padding not supported."); goto fail; } if ((header >> 28) & 1) { - pa_log("RTP header extensions not supported."); + pa_log_warn("RTP header extensions not supported."); goto fail; } @@ -223,7 +232,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { c->sequence = header & 0xFFFF; if (12 + cc*4 > size) { - pa_log("RTP packet too short. (CSRC)"); + pa_log_warn("RTP packet too short. (CSRC)"); goto fail; } @@ -231,7 +240,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) { chunk->length = size - chunk->index; if (chunk->length % c->frame_size != 0) { - pa_log("Vad RTP packet size."); + pa_log_warn("Bad RTP packet size."); goto fail; } @@ -245,7 +254,7 @@ fail: } uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) { - assert(ss); + pa_assert(ss); if (ss->format == PA_SAMPLE_ULAW && ss->rate == 8000 && ss->channels == 1) return 0; @@ -260,7 +269,7 @@ uint8_t pa_rtp_payload_from_sample_spec(const pa_sample_spec *ss) { } pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec *ss) { - assert(ss); + pa_assert(ss); switch (payload) { case 0: @@ -295,17 +304,17 @@ pa_sample_spec *pa_rtp_sample_spec_from_payload(uint8_t payload, pa_sample_spec } pa_sample_spec *pa_rtp_sample_spec_fixup(pa_sample_spec * ss) { - assert(ss); + pa_assert(ss); if (!pa_rtp_sample_spec_valid(ss)) ss->format = PA_SAMPLE_S16BE; - assert(pa_rtp_sample_spec_valid(ss)); + pa_assert(pa_rtp_sample_spec_valid(ss)); return ss; } int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) { - assert(ss); + pa_assert(ss); if (!pa_sample_spec_valid(ss)) return 0; @@ -318,9 +327,9 @@ int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) { } void pa_rtp_context_destroy(pa_rtp_context *c) { - assert(c); + pa_assert(c); - close(c->fd); + pa_close(c->fd); } const char* pa_rtp_format_to_string(pa_sample_format_t f) { @@ -339,7 +348,7 @@ const char* pa_rtp_format_to_string(pa_sample_format_t f) { } pa_sample_format_t pa_rtp_string_to_format(const char *s) { - assert(s); + pa_assert(s); if (!(strcmp(s, "L16"))) return PA_SAMPLE_S16BE; diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c index 824218072..ed7eb0beb 100644 --- a/src/modules/rtp/sap.c +++ b/src/modules/rtp/sap.c @@ -25,7 +25,6 @@ #include #endif -#include #include #include #include @@ -46,6 +45,7 @@ #include #include #include +#include #include "sap.h" #include "sdp.h" @@ -53,9 +53,9 @@ #define MIME_TYPE "application/sdp" pa_sap_context* pa_sap_context_init_send(pa_sap_context *c, int fd, char *sdp_data) { - assert(c); - assert(fd >= 0); - assert(sdp_data); + pa_assert(c); + pa_assert(fd >= 0); + pa_assert(sdp_data); c->fd = fd; c->sdp_data = sdp_data; @@ -65,9 +65,9 @@ pa_sap_context* pa_sap_context_init_send(pa_sap_context *c, int fd, char *sdp_da } void pa_sap_context_destroy(pa_sap_context *c) { - assert(c); + pa_assert(c); - close(c->fd); + pa_close(c->fd); pa_xfree(c->sdp_data); } @@ -85,7 +85,7 @@ int pa_sap_send(pa_sap_context *c, int goodbye) { return -1; } - assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); + pa_assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); header = htonl(((uint32_t) 1 << 29) | (sa->sa_family == AF_INET6 ? (uint32_t) 1 << 28 : 0) | @@ -113,14 +113,14 @@ int pa_sap_send(pa_sap_context *c, int goodbye) { m.msg_flags = 0; if ((k = sendmsg(c->fd, &m, MSG_DONTWAIT)) < 0) - pa_log("sendmsg() failed: %s\n", pa_cstrerror(errno)); + pa_log_warn("sendmsg() failed: %s\n", pa_cstrerror(errno)); return k; } pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) { - assert(c); - assert(fd >= 0); + pa_assert(c); + pa_assert(fd >= 0); c->fd = fd; c->sdp_data = NULL; @@ -136,11 +136,11 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { int six, ac; ssize_t r; - assert(c); - assert(goodbye); + pa_assert(c); + pa_assert(goodbye); if (ioctl(c->fd, FIONREAD, &size) < 0) { - pa_log("FIONREAD failed: %s", pa_cstrerror(errno)); + pa_log_warn("FIONREAD failed: %s", pa_cstrerror(errno)); goto fail; } @@ -159,12 +159,12 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { m.msg_flags = 0; if ((r = recvmsg(c->fd, &m, 0)) != size) { - pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); + pa_log_warn("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch"); goto fail; } if (size < 4) { - pa_log("SAP packet too short."); + pa_log_warn("SAP packet too short."); goto fail; } @@ -172,17 +172,17 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { header = ntohl(header); if (header >> 29 != 1) { - pa_log("Unsupported SAP version."); + pa_log_warn("Unsupported SAP version."); goto fail; } if ((header >> 25) & 1) { - pa_log("Encrypted SAP not supported."); + pa_log_warn("Encrypted SAP not supported."); goto fail; } if ((header >> 24) & 1) { - pa_log("Compressed SAP not supported."); + pa_log_warn("Compressed SAP not supported."); goto fail; } @@ -191,7 +191,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { k = 4 + (six ? 16 : 4) + ac*4; if (size < k) { - pa_log("SAP packet too short (AD)."); + pa_log_warn("SAP packet too short (AD)."); goto fail; } @@ -202,7 +202,7 @@ int pa_sap_recv(pa_sap_context *c, int *goodbye) { e += sizeof(MIME_TYPE); size -= sizeof(MIME_TYPE); } else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)) { - pa_log("Invalid SDP header."); + pa_log_warn("Invalid SDP header."); goto fail; } diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c index 8b0bd5354..50ac157a0 100644 --- a/src/modules/rtp/sdp.c +++ b/src/modules/rtp/sdp.c @@ -25,7 +25,6 @@ #include #endif -#include #include #include #include @@ -35,36 +34,33 @@ #include #include +#include #include #include +#include #include "sdp.h" #include "rtp.h" - char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, uint16_t port, uint8_t payload, const pa_sample_spec *ss) { uint32_t ntp; - char buf_src[64], buf_dst[64]; + char buf_src[64], buf_dst[64], un[64]; const char *u, *f, *a; - assert(src); - assert(dst); - assert(af == AF_INET || af == AF_INET6); + pa_assert(src); + pa_assert(dst); + pa_assert(af == AF_INET || af == AF_INET6); - f = pa_rtp_format_to_string(ss->format); - assert(f); + pa_assert_se(f = pa_rtp_format_to_string(ss->format)); - if (!(u = getenv("USER"))) - if (!(u = getenv("USERNAME"))) - u = "-"; + if (!(u = pa_get_user_name(un, sizeof(un)))) + u = "-"; ntp = time(NULL) + 2208988800U; - a = inet_ntop(af, src, buf_src, sizeof(buf_src)); - assert(a); - a = inet_ntop(af, dst, buf_dst, sizeof(buf_dst)); - assert(a); + pa_assert_se(a = inet_ntop(af, src, buf_src, sizeof(buf_src))); + pa_assert_se(a = inet_ntop(af, dst, buf_dst, sizeof(buf_dst))); return pa_sprintf_malloc( PA_SDP_HEADER @@ -86,8 +82,8 @@ char *pa_sdp_build(int af, const void *src, const void *dst, const char *name, u static pa_sample_spec *parse_sdp_sample_spec(pa_sample_spec *ss, char *c) { unsigned rate, channels; - assert(ss); - assert(c); + pa_assert(ss); + pa_assert(c); if (pa_startswith(c, "L16/")) { ss->format = PA_SAMPLE_S16BE; @@ -123,8 +119,8 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) { uint16_t port = 0; int ss_valid = 0; - assert(t); - assert(i); + pa_assert(t); + pa_assert(i); i->origin = i->session_name = NULL; i->salen = 0; @@ -258,7 +254,7 @@ fail: } void pa_sdp_info_destroy(pa_sdp_info *i) { - assert(i); + pa_assert(i); pa_xfree(i->origin); pa_xfree(i->session_name); diff --git a/src/pulse/browser.c b/src/pulse/browser.c index ea2706e42..55e0b2cd5 100644 --- a/src/pulse/browser.c +++ b/src/pulse/browser.c @@ -25,7 +25,6 @@ #include "config.h" #endif -#include #include #include @@ -36,8 +35,9 @@ #include #include - #include +#include +#include #include "browser.h" @@ -46,7 +46,8 @@ #define SERVICE_TYPE_SERVER "_pulse-server._tcp." struct pa_browser { - int ref; + PA_REFCNT_DECLARE; + pa_mainloop_api *mainloop; AvahiPoll* avahi_poll; @@ -62,6 +63,7 @@ struct pa_browser { }; static int map_to_opcode(const char *type, int new) { + if (avahi_domain_equal(type, SERVICE_TYPE_SINK)) return new ? PA_BROWSE_NEW_SINK : PA_BROWSE_REMOVE_SINK; else if (avahi_domain_equal(type, SERVICE_TYPE_SOURCE)) @@ -97,7 +99,8 @@ static void resolve_callback( int ss_valid = 0; char *key = NULL, *value = NULL; - assert(b); + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) >= 1); memset(&i, 0, sizeof(i)); i.name = name; @@ -109,13 +112,13 @@ static void resolve_callback( goto fail; opcode = map_to_opcode(type, 1); - assert(opcode >= 0); + pa_assert(opcode >= 0); if (aa->proto == AVAHI_PROTO_INET) - snprintf(a, sizeof(a), "tcp:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port); + pa_snprintf(a, sizeof(a), "tcp:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port); else { - assert(aa->proto == AVAHI_PROTO_INET6); - snprintf(a, sizeof(a), "tcp6:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port); + pa_assert(aa->proto == AVAHI_PROTO_INET6); + pa_snprintf(a, sizeof(a), "tcp6:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port); } i.server = a; @@ -146,7 +149,7 @@ static void resolve_callback( value = NULL; l = strlen(a); - assert(l+1 <= sizeof(a)); + pa_assert(l+1 <= sizeof(a)); strncat(a, " ", sizeof(a)-l-1); strncat(a, i.fqdn, sizeof(a)-l-2); } else if (!strcmp(key, "cookie")) { @@ -211,7 +214,9 @@ fail: static void handle_failure(pa_browser *b) { const char *e = NULL; - assert(b); + + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) >= 1); if (b->sink_browser) avahi_service_browser_free(b->sink_browser); @@ -245,7 +250,9 @@ static void browse_callback( void *userdata) { pa_browser *b = userdata; - assert(b); + + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) >= 1); switch (event) { case AVAHI_BROWSER_NEW: { @@ -276,7 +283,7 @@ static void browse_callback( i.name = name; opcode = map_to_opcode(type, 0); - assert(opcode >= 0); + pa_assert(opcode >= 0); b->callback(b, opcode, &i, b->userdata); } @@ -295,7 +302,10 @@ static void browse_callback( static void client_callback(AvahiClient *s, AvahiClientState state, void *userdata) { pa_browser *b = userdata; - assert(s); + + pa_assert(s); + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) >= 1); if (state == AVAHI_CLIENT_FAILURE) handle_failure(b); @@ -311,14 +321,14 @@ pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t fla pa_browser *b; int error; - assert(mainloop); + pa_assert(mainloop); if (flags & ~(PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES) || flags == 0) return NULL; b = pa_xnew(pa_browser, 1); b->mainloop = mainloop; - b->ref = 1; + PA_REFCNT_INIT(b); b->callback = NULL; b->userdata = NULL; b->error_callback = NULL; @@ -391,7 +401,8 @@ fail: } static void browser_free(pa_browser *b) { - assert(b && b->mainloop); + pa_assert(b); + pa_assert(b->mainloop); if (b->sink_browser) avahi_service_browser_free(b->sink_browser); @@ -410,29 +421,32 @@ static void browser_free(pa_browser *b) { } pa_browser *pa_browser_ref(pa_browser *b) { - assert(b); - assert(b->ref >= 1); - b->ref++; + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) >= 1); + + PA_REFCNT_INC(b); return b; } void pa_browser_unref(pa_browser *b) { - assert(b); - assert(b->ref >= 1); + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) >= 1); - if ((-- (b->ref)) <= 0) + if (PA_REFCNT_DEC(b) <= 0) browser_free(b); } void pa_browser_set_callback(pa_browser *b, pa_browse_cb_t cb, void *userdata) { - assert(b); + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) >= 1); b->callback = cb; b->userdata = userdata; } void pa_browser_set_error_callback(pa_browser *b, pa_browser_error_cb_t cb, void *userdata) { - assert(b); + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) >= 1); b->error_callback = cb; b->error_userdata = userdata; diff --git a/src/pulse/cdecl.h b/src/pulse/cdecl.h index 922ad2765..e1f23d25e 100644 --- a/src/pulse/cdecl.h +++ b/src/pulse/cdecl.h @@ -41,4 +41,22 @@ #endif +#ifndef PA_GCC_PURE +#ifdef __GNUCC__ +#define PA_GCC_PURE __attribute__ ((pure)) +#else +/** This function's return value depends only the arguments list and global state **/ +#define PA_GCC_PURE +#endif +#endif + +#ifndef PA_GCC_CONST +#ifdef __GNUCC__ +#define PA_GCC_CONST __attribute__ ((pure)) +#else +/** This function's return value depends only the arguments list (stricter version of PA_GCC_CONST) **/ +#define PA_GCC_CONST +#endif +#endif + #endif diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c index d5b8f7437..2b8ef2b00 100644 --- a/src/pulse/channelmap.c +++ b/src/pulse/channelmap.c @@ -27,12 +27,12 @@ #endif #include -#include #include #include #include #include +#include #include "channelmap.h" @@ -90,18 +90,81 @@ const char *const table[] = { [PA_CHANNEL_POSITION_TOP_CENTER] = "top-center", + [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center", [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "top-front-left", [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "top-front-right", - [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center", + [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "top-rear-center", [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = "top-rear-left", - [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "top-rear-right", - [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "top-rear-center" + [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "top-rear-right" +}; + +const char *const pretty_table[] = { + [PA_CHANNEL_POSITION_MONO] = "Mono", + + [PA_CHANNEL_POSITION_FRONT_CENTER] = "Front Center", + [PA_CHANNEL_POSITION_FRONT_LEFT] = "Front Left", + [PA_CHANNEL_POSITION_FRONT_RIGHT] = "Front Right", + + [PA_CHANNEL_POSITION_REAR_CENTER] = "Rear Center", + [PA_CHANNEL_POSITION_REAR_LEFT] = "Rear Left", + [PA_CHANNEL_POSITION_REAR_RIGHT] = "Rear Right", + + [PA_CHANNEL_POSITION_LFE] = "Low Frequency Emmiter", + + [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "Front Left-of-center", + [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "Front Right-of-center", + + [PA_CHANNEL_POSITION_SIDE_LEFT] = "Side Left", + [PA_CHANNEL_POSITION_SIDE_RIGHT] = "Side Right", + + [PA_CHANNEL_POSITION_AUX0] = "Auxiliary 0", + [PA_CHANNEL_POSITION_AUX1] = "Auxiliary 1", + [PA_CHANNEL_POSITION_AUX2] = "Auxiliary 2", + [PA_CHANNEL_POSITION_AUX3] = "Auxiliary 3", + [PA_CHANNEL_POSITION_AUX4] = "Auxiliary 4", + [PA_CHANNEL_POSITION_AUX5] = "Auxiliary 5", + [PA_CHANNEL_POSITION_AUX6] = "Auxiliary 6", + [PA_CHANNEL_POSITION_AUX7] = "Auxiliary 7", + [PA_CHANNEL_POSITION_AUX8] = "Auxiliary 8", + [PA_CHANNEL_POSITION_AUX9] = "Auxiliary 9", + [PA_CHANNEL_POSITION_AUX10] = "Auxiliary 10", + [PA_CHANNEL_POSITION_AUX11] = "Auxiliary 11", + [PA_CHANNEL_POSITION_AUX12] = "Auxiliary 12", + [PA_CHANNEL_POSITION_AUX13] = "Auxiliary 13", + [PA_CHANNEL_POSITION_AUX14] = "Auxiliary 14", + [PA_CHANNEL_POSITION_AUX15] = "Auxiliary 15", + [PA_CHANNEL_POSITION_AUX16] = "Auxiliary 16", + [PA_CHANNEL_POSITION_AUX17] = "Auxiliary 17", + [PA_CHANNEL_POSITION_AUX18] = "Auxiliary 18", + [PA_CHANNEL_POSITION_AUX19] = "Auxiliary 19", + [PA_CHANNEL_POSITION_AUX20] = "Auxiliary 20", + [PA_CHANNEL_POSITION_AUX21] = "Auxiliary 21", + [PA_CHANNEL_POSITION_AUX22] = "Auxiliary 22", + [PA_CHANNEL_POSITION_AUX23] = "Auxiliary 23", + [PA_CHANNEL_POSITION_AUX24] = "Auxiliary 24", + [PA_CHANNEL_POSITION_AUX25] = "Auxiliary 25", + [PA_CHANNEL_POSITION_AUX26] = "Auxiliary 26", + [PA_CHANNEL_POSITION_AUX27] = "Auxiliary 27", + [PA_CHANNEL_POSITION_AUX28] = "Auxiliary 28", + [PA_CHANNEL_POSITION_AUX29] = "Auxiliary 29", + [PA_CHANNEL_POSITION_AUX30] = "Auxiliary 30", + [PA_CHANNEL_POSITION_AUX31] = "Auxiliary 31", + + [PA_CHANNEL_POSITION_TOP_CENTER] = "Top Center", + + [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "Top Front Center", + [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "Top Front Left", + [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "Top Front Right", + + [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "Top Rear Center", + [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = "Top Rear left", + [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "Top Rear Right" }; pa_channel_map* pa_channel_map_init(pa_channel_map *m) { unsigned c; - assert(m); + pa_assert(m); m->channels = 0; @@ -112,7 +175,7 @@ pa_channel_map* pa_channel_map_init(pa_channel_map *m) { } pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) { - assert(m); + pa_assert(m); pa_channel_map_init(m); @@ -122,7 +185,7 @@ pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) { } pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) { - assert(m); + pa_assert(m); pa_channel_map_init(m); @@ -133,9 +196,9 @@ pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) { } pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) { - assert(m); - assert(channels > 0); - assert(channels <= PA_CHANNELS_MAX); + pa_assert(m); + pa_assert(channels > 0); + pa_assert(channels <= PA_CHANNELS_MAX); pa_channel_map_init(m); @@ -342,11 +405,18 @@ const char* pa_channel_position_to_string(pa_channel_position_t pos) { return table[pos]; } +const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos) { + if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX) + return NULL; + + return pretty_table[pos]; +} + int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) { unsigned c; - assert(a); - assert(b); + pa_assert(a); + pa_assert(b); if (a->channels != b->channels) return 0; @@ -363,14 +433,14 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) { int first = 1; char *e; - assert(s); - assert(l > 0); - assert(map); + pa_assert(s); + pa_assert(l > 0); + pa_assert(map); *(e = s) = 0; for (channel = 0; channel < map->channels && l > 1; channel++) { - l -= snprintf(e, l, "%s%s", + l -= pa_snprintf(e, l, "%s%s", first ? "" : ",", pa_channel_position_to_string(map->map[channel])); @@ -386,8 +456,8 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) { pa_channel_map map; char *p; - assert(rmap); - assert(s); + pa_assert(rmap); + pa_assert(s); memset(&map, 0, sizeof(map)); @@ -447,7 +517,7 @@ finish: int pa_channel_map_valid(const pa_channel_map *map) { unsigned c; - assert(map); + pa_assert(map); if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX) return 0; diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h index f0c8f4752..a05e19113 100644 --- a/src/pulse/channelmap.h +++ b/src/pulse/channelmap.h @@ -172,7 +172,10 @@ pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m); pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def); /** Return a text label for the specified channel position */ -const char* pa_channel_position_to_string(pa_channel_position_t pos); +const char* pa_channel_position_to_string(pa_channel_position_t pos) PA_GCC_PURE; + +/** Return a human readable text label for the specified channel position. \since 0.9.7 */ +const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos); /** The maximum length of strings returned by pa_channel_map_snprint() */ #define PA_CHANNEL_MAP_SNPRINT_MAX 336 @@ -184,10 +187,10 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map); pa_channel_map *pa_channel_map_parse(pa_channel_map *map, const char *s); /** Compare two channel maps. Return 1 if both match. */ -int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b); +int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) PA_GCC_PURE; /** Return non-zero of the specified channel map is considered valid */ -int pa_channel_map_valid(const pa_channel_map *map); +int pa_channel_map_valid(const pa_channel_map *map) PA_GCC_PURE; PA_C_DECL_END diff --git a/src/pulse/client-conf-x11.c b/src/pulse/client-conf-x11.c index e8de95530..e240ba888 100644 --- a/src/pulse/client-conf-x11.c +++ b/src/pulse/client-conf-x11.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include #include "client-conf-x11.h" @@ -44,6 +44,8 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { int ret = -1; char t[1024]; + pa_assert(c); + if (!dname && (!(dname = getenv("DISPLAY")) || *dname == '\0')) goto finish; @@ -75,7 +77,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) { goto finish; } - assert(sizeof(cookie) == sizeof(c->cookie)); + pa_assert(sizeof(cookie) == sizeof(c->cookie)); memcpy(c->cookie, cookie, sizeof(cookie)); c->cookie_valid = 1; diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index bb9123359..abd277a69 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -27,14 +27,14 @@ #endif #include -#include #include #include #include -#include #include +#include +#include #include #include #include @@ -42,13 +42,7 @@ #include "client-conf.h" -#ifndef OS_IS_WIN32 -# define PATH_SEP "/" -#else -# define PATH_SEP "\\" -#endif - -#define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "client.conf" +#define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "client.conf" #define DEFAULT_CLIENT_CONFIG_FILE_USER "client.conf" #define ENV_CLIENT_CONFIG_FILE "PULSE_CLIENTCONFIG" @@ -81,7 +75,7 @@ pa_client_conf *pa_client_conf_new(void) { } void pa_client_conf_free(pa_client_conf *c) { - assert(c); + pa_assert(c); pa_xfree(c->daemon_binary); pa_xfree(c->extra_arguments); pa_xfree(c->default_sink); @@ -90,6 +84,7 @@ void pa_client_conf_free(pa_client_conf *c) { pa_xfree(c->cookie_file); pa_xfree(c); } + int pa_client_conf_load(pa_client_conf *c, const char *filename) { FILE *f = NULL; char *fn = NULL; @@ -122,7 +117,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn, "r"); if (!f && errno != EINTR) { - pa_log("WARNING: failed to open configuration file '%s': %s", fn, pa_cstrerror(errno)); + pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } @@ -175,7 +170,7 @@ int pa_client_conf_env(pa_client_conf *c) { } int pa_client_conf_load_cookie(pa_client_conf* c) { - assert(c); + pa_assert(c); c->cookie_valid = 0; diff --git a/src/pulse/context.c b/src/pulse/context.c index 58a5a8794..805cd44ee 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include #include @@ -67,6 +66,7 @@ #include #include #include +#include #include "internal.h" @@ -90,7 +90,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { }; static void unlock_autospawn_lock_file(pa_context *c) { - assert(c); + pa_assert(c); if (c->autospawn_lock_fd >= 0) { char lf[PATH_MAX]; @@ -106,11 +106,11 @@ static void context_free(pa_context *c); pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { pa_context *c; - assert(mainloop); - assert(name); + pa_assert(mainloop); + pa_assert(name); c = pa_xnew(pa_context, 1); - c->ref = 1; + PA_REFCNT_INIT(c); c->name = pa_xstrdup(name); c->mainloop = mainloop; c->client = NULL; @@ -168,7 +168,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { } static void context_free(pa_context *c) { - assert(c); + pa_assert(c); unlock_autospawn_lock_file(c); @@ -183,7 +183,7 @@ static void context_free(pa_context *c) { if (c->pdispatch) pa_pdispatch_unref(c->pdispatch); if (c->pstream) { - pa_pstream_close(c->pstream); + pa_pstream_unlink(c->pstream); pa_pstream_unref(c->pstream); } @@ -206,24 +206,24 @@ static void context_free(pa_context *c) { } pa_context* pa_context_ref(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); - c->ref++; + PA_REFCNT_INC(c); return c; } void pa_context_unref(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); - if (--c->ref <= 0) + if (PA_REFCNT_DEC(c) <= 0) context_free(c); } void pa_context_set_state(pa_context *c, pa_context_state_t st) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); if (c->state == st) return; @@ -250,7 +250,7 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { c->pdispatch = NULL; if (c->pstream) { - pa_pstream_close(c->pstream); + pa_pstream_unlink(c->pstream); pa_pstream_unref(c->pstream); } c->pstream = NULL; @@ -264,16 +264,16 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { } void pa_context_fail(pa_context *c, int error) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_set_error(c, error); pa_context_set_state(c, PA_CONTEXT_FAILED); } int pa_context_set_error(pa_context *c, int error) { - assert(error >= 0); - assert(error < PA_ERR_MAX); + pa_assert(error >= 0); + pa_assert(error < PA_ERR_MAX); if (c) c->error = error; @@ -284,8 +284,8 @@ int pa_context_set_error(pa_context *c, int error) { static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context *c = userdata; - assert(p); - assert(c); + pa_assert(p); + pa_assert(c); pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } @@ -293,9 +293,9 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { pa_context *c = userdata; - assert(p); - assert(packet); - assert(c); + pa_assert(p); + pa_assert(packet); + pa_assert(c); pa_context_ref(c); @@ -309,18 +309,19 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o pa_context *c = userdata; pa_stream *s; - assert(p); - assert(chunk); - assert(chunk->memblock); - assert(chunk->length); - assert(c); - assert(c->ref >= 1); + pa_assert(p); + pa_assert(chunk); + pa_assert(chunk->memblock); + pa_assert(chunk->length); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_ref(c); if ((s = pa_dynarray_get(c->record_streams, channel))) { - assert(seek == PA_SEEK_RELATIVE && offset == 0); + pa_assert(seek == PA_SEEK_RELATIVE); + pa_assert(offset == 0); pa_memblockq_seek(s->record_memblockq, offset, seek); pa_memblockq_push_align(s->record_memblockq, chunk); @@ -337,11 +338,11 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o } int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); if (command == PA_COMMAND_ERROR) { - assert(t); + pa_assert(t); if (pa_tagstruct_getu32(t, &c->error) < 0) { pa_context_fail(c, PA_ERR_PROTOCOL); @@ -361,9 +362,9 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; - assert(pd); - assert(c); - assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME); + pa_assert(pd); + pa_assert(c); + pa_assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME); pa_context_ref(c); @@ -423,7 +424,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t break; default: - assert(0); + pa_assert(0); } finish: @@ -434,19 +435,19 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_tagstruct *t; uint32_t tag; - assert(c); - assert(io); + pa_assert(c); + pa_assert(io); pa_context_ref(c); - assert(!c->pstream); + pa_assert(!c->pstream); c->pstream = pa_pstream_new(c->mainloop, io, c->mempool); pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); - assert(!c->pdispatch); + pa_assert(!c->pdispatch); c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); if (!c->conf->cookie_valid) @@ -497,10 +498,10 @@ static int context_connect_spawn(pa_context *c) { goto fail; } - pa_fd_set_cloexec(fds[0], 1); + pa_make_fd_cloexec(fds[0]); - pa_socket_low_delay(fds[0]); - pa_socket_low_delay(fds[1]); + pa_make_socket_low_delay(fds[0]); + pa_make_socket_low_delay(fds[1]); if (c->spawn_api.prefork) c->spawn_api.prefork(); @@ -523,7 +524,7 @@ static int context_connect_spawn(pa_context *c) { int n; /* Not required, since fds[0] has CLOEXEC enabled anyway */ - close(fds[0]); + pa_assert_se(pa_close(fds[0]) == 0); if (c->spawn_api.atfork) c->spawn_api.atfork(); @@ -535,7 +536,7 @@ static int context_connect_spawn(pa_context *c) { argv[n++] = c->conf->daemon_binary; argv[n++] = "--daemonize=yes"; - snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); + pa_snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); argv[n++] = strdup(t); while (n < MAX_ARGS) { @@ -570,7 +571,7 @@ static int context_connect_spawn(pa_context *c) { goto fail; } - close(fds[1]); + pa_assert_se(pa_close(fds[1]) == 0); c->is_local = 1; @@ -584,10 +585,7 @@ static int context_connect_spawn(pa_context *c) { return 0; fail: - if (fds[0] != -1) - close(fds[0]); - if (fds[1] != -1) - close(fds[1]); + pa_close_pipe(fds); unlock_autospawn_lock_file(c); @@ -602,8 +600,8 @@ static int try_next_connection(pa_context *c) { char *u = NULL; int r = -1; - assert(c); - assert(!c->client); + pa_assert(c); + pa_assert(!c->client); for (;;) { pa_xfree(u); @@ -648,9 +646,9 @@ finish: static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) { pa_context *c = userdata; - assert(client); - assert(c); - assert(c->state == PA_CONTEXT_CONNECTING); + pa_assert(client); + pa_assert(c); + pa_assert(c->state == PA_CONTEXT_CONNECTING); pa_context_ref(c); @@ -683,8 +681,8 @@ int pa_context_connect( int r = -1; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(c, !(flags & ~PA_CONTEXT_NOAUTOSPAWN), PA_ERR_INVALID); @@ -695,7 +693,7 @@ int pa_context_connect( pa_context_ref(c); - assert(!c->server_list); + pa_assert(!c->server_list); if (server) { if (!(c->server_list = pa_strlist_parse(server))) { @@ -735,7 +733,7 @@ int pa_context_connect( pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); pa_make_secure_parent_dir(lf, 0700, (uid_t)-1, (gid_t)-1); - assert(c->autospawn_lock_fd <= 0); + pa_assert(c->autospawn_lock_fd <= 0); c->autospawn_lock_fd = pa_lock_lockfile(lf); if (api) @@ -755,37 +753,37 @@ finish: } void pa_context_disconnect(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_set_state(c, PA_CONTEXT_TERMINATED); } pa_context_state_t pa_context_get_state(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); return c->state; } int pa_context_errno(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); return c->error; } void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); c->state_callback = cb; c->state_userdata = userdata; } int pa_context_is_pending(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_CONNECTING || @@ -811,11 +809,11 @@ static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata) static void set_dispatch_callbacks(pa_operation *o) { int done = 1; - assert(o); - assert(o->ref >= 1); - assert(o->context); - assert(o->context->ref >= 1); - assert(o->context->state == PA_CONTEXT_READY); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + pa_assert(o->context); + pa_assert(PA_REFCNT_VALUE(o->context) >= 1); + pa_assert(o->context->state == PA_CONTEXT_READY); pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL); pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL); @@ -844,8 +842,8 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { pa_operation *o; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE); @@ -860,9 +858,9 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_U pa_operation *o = userdata; int success = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -892,8 +890,8 @@ pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -911,8 +909,8 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -930,8 +928,8 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_co pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -950,8 +948,8 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -966,7 +964,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ } int pa_context_is_local(pa_context *c) { - assert(c); + pa_assert(c); return c->is_local; } @@ -976,9 +974,9 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(name); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(name); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -997,8 +995,8 @@ const char* pa_get_library_version(void) { } const char* pa_context_get_server(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); if (!c->server) return NULL; @@ -1016,8 +1014,8 @@ uint32_t pa_context_get_protocol_version(PA_GCC_UNUSED pa_context *c) { } uint32_t pa_context_get_server_protocol_version(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); return c->version; } @@ -1025,8 +1023,8 @@ uint32_t pa_context_get_server_protocol_version(pa_context *c) { pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) { pa_tagstruct *t; - assert(c); - assert(tag); + pa_assert(c); + pa_assert(tag); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, command); diff --git a/src/pulse/glib-mainloop.c b/src/pulse/glib-mainloop.c index 5b399aa2b..b7a7537a0 100644 --- a/src/pulse/glib-mainloop.c +++ b/src/pulse/glib-mainloop.c @@ -25,8 +25,6 @@ #include #endif -#include - #include #include diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 52354fdcb..95593adb0 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -41,13 +41,14 @@ #include #include #include +#include #include "client-conf.h" #define DEFAULT_TIMEOUT (30) struct pa_context { - int ref; + PA_REFCNT_DECLARE; char *name; pa_mainloop_api* mainloop; @@ -96,7 +97,7 @@ typedef struct pa_index_correction { } pa_index_correction; struct pa_stream { - int ref; + PA_REFCNT_DECLARE; pa_context *context; pa_mainloop_api *mainloop; PA_LLIST_FIELDS(pa_stream); @@ -116,6 +117,7 @@ struct pa_stream { uint32_t requested_bytes; pa_memchunk peek_memchunk; + void *peek_data; pa_memblockq *record_memblockq; int corked; @@ -160,7 +162,8 @@ struct pa_stream { typedef void (*pa_operation_cb_t)(void); struct pa_operation { - int ref; + PA_REFCNT_DECLARE; + pa_context *context; pa_stream *stream; diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c index 7f6406cf8..6610a7240 100644 --- a/src/pulse/introspect.c +++ b/src/pulse/introspect.c @@ -26,11 +26,10 @@ #include #endif -#include - #include #include +#include #include #include "internal.h" @@ -43,9 +42,11 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNU pa_operation *o = userdata; pa_stat_info i, *p = &i; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + + memset(&i, 0, sizeof(i)); if (!o->context) goto finish; @@ -59,8 +60,7 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNU pa_tagstruct_getu32(t, &i.memblock_total_size) < 0 || pa_tagstruct_getu32(t, &i.memblock_allocated) < 0 || pa_tagstruct_getu32(t, &i.memblock_allocated_size) < 0 || - pa_tagstruct_getu32(t, &i.scache_size) < 0 || - !pa_tagstruct_eof(t)) { + pa_tagstruct_getu32(t, &i.scache_size) < 0) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } @@ -85,9 +85,11 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, pa_operation *o = userdata; pa_server_info i, *p = &i; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + + memset(&i, 0, sizeof(i)); if (!o->context) goto finish; @@ -104,8 +106,7 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_gets(t, &i.default_sink_name) < 0 || pa_tagstruct_gets(t, &i.default_source_name) < 0 || - pa_tagstruct_getu32(t, &i.cookie) < 0 || - !pa_tagstruct_eof(t)) { + pa_tagstruct_getu32(t, &i.cookie) < 0) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; @@ -131,9 +132,9 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P pa_operation *o = userdata; int eol = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -148,6 +149,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P while (!pa_tagstruct_eof(t)) { pa_sink_info i; + memset(&i, 0, sizeof(i)); if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -195,9 +197,9 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_ pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -217,9 +219,9 @@ pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); @@ -241,9 +243,9 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, pa_operation *o = userdata; int eol = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -258,6 +260,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, while (!pa_tagstruct_eof(t)) { pa_source_info i; uint32_t flags; + memset(&i, 0, sizeof(i)); if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -305,9 +308,9 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, p pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -327,9 +330,9 @@ pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); @@ -351,9 +354,9 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, pa_operation *o = userdata; int eol = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -367,6 +370,7 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, while (!pa_tagstruct_eof(t)) { pa_client_info i; + memset(&i, 0, sizeof(i)); if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -398,9 +402,9 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_ pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); @@ -425,9 +429,9 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, pa_operation *o = userdata; int eol = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -441,6 +445,7 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, while (!pa_tagstruct_eof(t)) { pa_module_info i; + memset(&i, 0, sizeof(i)); if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -473,9 +478,9 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_ pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); @@ -500,9 +505,9 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm pa_operation *o = userdata; int eol = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -516,6 +521,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm while (!pa_tagstruct_eof(t)) { pa_sink_input_info i; + memset(&i, 0, sizeof(i)); if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || @@ -528,7 +534,8 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || pa_tagstruct_get_usec(t, &i.sink_usec) < 0 || pa_tagstruct_gets(t, &i.resample_method) < 0 || - pa_tagstruct_gets(t, &i.driver) < 0) { + pa_tagstruct_gets(t, &i.driver) < 0 || + (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &i.mute) < 0)) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; @@ -556,9 +563,9 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sin pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); @@ -583,9 +590,9 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c pa_operation *o = userdata; int eol = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -600,6 +607,8 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c while (!pa_tagstruct_eof(t)) { pa_source_output_info i; + memset(&i, 0, sizeof(i)); + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.owner_module) < 0 || @@ -638,9 +647,9 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_ pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); @@ -666,9 +675,9 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, c pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(volume); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(volume); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); @@ -690,10 +699,10 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(name); - assert(volume); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(name); + pa_assert(volume); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); @@ -716,8 +725,8 @@ pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -738,9 +747,9 @@ pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(name); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(name); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); @@ -762,9 +771,9 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(volume); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(volume); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); @@ -781,14 +790,37 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons return o; } +pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_MUTE, &tag); + pa_tagstruct_putu32(t, idx); + pa_tagstruct_put_boolean(t, mute); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) { pa_operation *o; pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(volume); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(volume); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); @@ -810,10 +842,10 @@ pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *na pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(name); - assert(volume); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(name); + pa_assert(volume); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID); @@ -836,8 +868,8 @@ pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, i pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -858,9 +890,9 @@ pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(name); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(name); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID); @@ -883,9 +915,9 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, pa_operation *o = userdata; int eol = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -900,6 +932,8 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, while (!pa_tagstruct_eof(t)) { pa_sample_info i; + memset(&i, 0, sizeof(i)); + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_get_cvolume(t, &i.volume) < 0 || @@ -936,9 +970,9 @@ pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); @@ -959,9 +993,9 @@ pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, p pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); @@ -986,8 +1020,8 @@ static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); @@ -1018,9 +1052,9 @@ static void context_index_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN pa_operation *o = userdata; uint32_t idx; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -1052,8 +1086,8 @@ pa_operation* pa_context_load_module(pa_context *c, const char*name, const char pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); @@ -1079,9 +1113,9 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman pa_operation *o = userdata; int eol = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -1096,6 +1130,8 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman while (!pa_tagstruct_eof(t)) { pa_autoload_info i; + memset(&i, 0, sizeof(i)); + if (pa_tagstruct_getu32(t, &i.index) < 0 || pa_tagstruct_gets(t, &i.name) < 0 || pa_tagstruct_getu32(t, &i.type) < 0 || @@ -1127,9 +1163,9 @@ pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *na pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); @@ -1151,9 +1187,9 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(cb); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(cb); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); @@ -1177,8 +1213,8 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); @@ -1203,8 +1239,8 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); @@ -1226,8 +1262,8 @@ pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, p pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID); @@ -1247,8 +1283,8 @@ pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, ch pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED); @@ -1272,8 +1308,8 @@ pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, u pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED); @@ -1297,8 +1333,8 @@ pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED); @@ -1322,8 +1358,8 @@ pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED); @@ -1341,3 +1377,97 @@ pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx return o; } + +pa_operation* pa_context_suspend_sink_by_name(pa_context *c, char *sink_name, int suspend, pa_context_success_cb_t cb, void* userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED); + PA_CHECK_VALIDITY_RETURN_NULL(c, !sink_name || *sink_name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SINK, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, sink_name); + pa_tagstruct_put_boolean(t, suspend); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SINK, &tag); + pa_tagstruct_putu32(t, idx); + pa_tagstruct_puts(t, idx == PA_INVALID_INDEX ? "" : NULL); + pa_tagstruct_put_boolean(t, suspend); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation* pa_context_suspend_source_by_name(pa_context *c, char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED); + PA_CHECK_VALIDITY_RETURN_NULL(c, !source_name || *source_name, PA_ERR_INVALID); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SOURCE, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, source_name); + pa_tagstruct_put_boolean(t, suspend); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SOURCE, &tag); + pa_tagstruct_putu32(t, idx); + pa_tagstruct_puts(t, idx == PA_INVALID_INDEX ? "" : NULL); + pa_tagstruct_put_boolean(t, suspend); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h index 43e430b20..c148ee5ec 100644 --- a/src/pulse/introspect.h +++ b/src/pulse/introspect.h @@ -331,6 +331,7 @@ typedef struct pa_sink_input_info { pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */ const char *resample_method; /**< Thre resampling method used by this sink input. \since 0.7 */ const char *driver; /**< Driver name \since 0.8 */ + int mute; /**< Stream muted \since 0.9.7 */ } pa_sink_input_info; /** Callback prototype for pa_context_get_sink_input_info() and firends*/ @@ -381,6 +382,9 @@ pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, /** Set the volume of a sink input stream */ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); +/** Set the mute switch of a sink input stream \since 0.9.7 */ +pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata); + /** Set the volume of a source device specified by its index \since 0.8 */ pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); @@ -499,6 +503,18 @@ pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, /** Move the specified source output to a different source. \since 0.9.5 */ pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata); +/** Suspend/Resume a sink. \since 0.9.7 */ +pa_operation* pa_context_suspend_sink_by_name(pa_context *c, char *sink_name, int suspend, pa_context_success_cb_t cb, void* userdata); + +/** Suspend/Resume a sink. If idx is PA_INVALID_INDEX all sinks will be suspended. \since 0.9.7 */ +pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata); + +/** Suspend/Resume a source. \since 0.9.7 */ +pa_operation* pa_context_suspend_source_by_name(pa_context *c, char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata); + +/** Suspend/Resume a source. If idx is PA_INVALID_INDEX all sources will be suspended. \since 0.9.7 */ +pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata); + PA_C_DECL_END #endif diff --git a/src/pulse/mainloop-api.c b/src/pulse/mainloop-api.c index 001ff314b..b2ed34342 100644 --- a/src/pulse/mainloop-api.c +++ b/src/pulse/mainloop-api.c @@ -25,12 +25,12 @@ #include #endif -#include #include #include #include +#include #include "mainloop-api.h" @@ -41,32 +41,38 @@ struct once_info { static void once_callback(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { struct once_info *i = userdata; - assert(m && i && i->callback); + pa_assert(m); + pa_assert(i); + + pa_assert(i->callback); i->callback(m, i->userdata); - assert(m->defer_free); + pa_assert(m->defer_free); m->defer_free(e); } static void free_callback(pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event *e, void *userdata) { struct once_info *i = userdata; - assert(m && i); + + pa_assert(m); + pa_assert(i); pa_xfree(i); } void pa_mainloop_api_once(pa_mainloop_api* m, void (*callback)(pa_mainloop_api *m, void *userdata), void *userdata) { struct once_info *i; pa_defer_event *e; - assert(m && callback); + + pa_assert(m); + pa_assert(callback); i = pa_xnew(struct once_info, 1); i->callback = callback; i->userdata = userdata; - assert(m->defer_new); - e = m->defer_new(m, once_callback, i); - assert(e); + pa_assert(m->defer_new); + pa_assert_se(e = m->defer_new(m, once_callback, i)); m->defer_set_destroy(e, free_callback); } diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c index 28ddec492..7d3017e2e 100644 --- a/src/pulse/mainloop-signal.c +++ b/src/pulse/mainloop-signal.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include #include @@ -39,12 +38,13 @@ #include #endif -#include #include +#include #include #include #include +#include #include "mainloop-signal.h" @@ -74,11 +74,11 @@ static void signal_handler(int sig) { } static void dispatch(pa_mainloop_api*a, int sig) { - pa_signal_event*s; + pa_signal_event *s; for (s = signals; s; s = s->next) if (s->sig == sig) { - assert(s->callback); + pa_assert(s->callback); s->callback(a, s, sig, s->userdata); break; } @@ -87,7 +87,12 @@ static void dispatch(pa_mainloop_api*a, int sig) { static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, PA_GCC_UNUSED void *userdata) { ssize_t r; int sig; - assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]); + + pa_assert(a); + pa_assert(e); + pa_assert(f == PA_IO_EVENT_INPUT); + pa_assert(e == io_event); + pa_assert(fd == signal_pipe[0]); if ((r = pa_read(signal_pipe[0], &sig, sizeof(sig), NULL)) < 0) { if (errno == EAGAIN) @@ -107,28 +112,34 @@ static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags int pa_signal_init(pa_mainloop_api *a) { - assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event); + pa_assert(a); + pa_assert(!api); + pa_assert(signal_pipe[0] == -1); + pa_assert(signal_pipe[1] == -1); + pa_assert(!io_event); if (pipe(signal_pipe) < 0) { pa_log("pipe(): %s", pa_cstrerror(errno)); return -1; } - pa_make_nonblock_fd(signal_pipe[0]); - pa_make_nonblock_fd(signal_pipe[1]); - pa_fd_set_cloexec(signal_pipe[0], 1); - pa_fd_set_cloexec(signal_pipe[1], 1); + pa_make_fd_nonblock(signal_pipe[0]); + pa_make_fd_nonblock(signal_pipe[1]); + pa_make_fd_cloexec(signal_pipe[0]); + pa_make_fd_cloexec(signal_pipe[1]); api = a; - io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL); - assert(io_event); + pa_assert_se(io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL)); return 0; } void pa_signal_done(void) { - assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && io_event); + pa_assert(api); + pa_assert(signal_pipe[0] >= 0); + pa_assert(signal_pipe[1] >= 0); + pa_assert(io_event); while (signals) pa_signal_free(signals); @@ -136,9 +147,7 @@ void pa_signal_done(void) { api->io_free(io_event); io_event = NULL; - close(signal_pipe[0]); - close(signal_pipe[1]); - signal_pipe[0] = signal_pipe[1] = -1; + pa_close_pipe(signal_pipe); api = NULL; } @@ -150,13 +159,14 @@ pa_signal_event* pa_signal_new(int sig, void (*_callback) (pa_mainloop_api *api, struct sigaction sa; #endif - assert(sig > 0 && _callback); + pa_assert(sig > 0); + pa_assert(_callback); for (e = signals; e; e = e->next) if (e->sig == sig) goto fail; - e = pa_xmalloc(sizeof(pa_signal_event)); + e = pa_xnew(pa_signal_event, 1); e->sig = sig; e->callback = _callback; e->userdata = userdata; @@ -186,7 +196,7 @@ fail: } void pa_signal_free(pa_signal_event *e) { - assert(e); + pa_assert(e); if (e->next) e->next->previous = e->previous; @@ -196,9 +206,9 @@ void pa_signal_free(pa_signal_event *e) { signals = e->next; #ifdef HAVE_SIGACTION - sigaction(e->sig, &e->saved_sigaction, NULL); + pa_assert_se(sigaction(e->sig, &e->saved_sigaction, NULL) == 0); #else - signal(e->sig, e->saved_handler); + pa_assert_se(signal(e->sig, e->saved_handler) == signal_handler); #endif if (e->destroy_callback) @@ -208,6 +218,7 @@ void pa_signal_free(pa_signal_event *e) { } void pa_signal_set_destroy(pa_signal_event *e, void (*_callback) (pa_mainloop_api *api, pa_signal_event*e, void *userdata)) { - assert(e); + pa_assert(e); + e->destroy_callback = _callback; } diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c index 43cbb19ff..ad4e4e97d 100644 --- a/src/pulse/mainloop.c +++ b/src/pulse/mainloop.c @@ -31,29 +31,28 @@ #include #include #include -#include #include #include -#ifdef HAVE_SYS_POLL_H -#include +#ifdef HAVE_POLL_H +#include #else -#include "../pulsecore/poll.h" +#include #endif -#include "../pulsecore/winsock.h" - #ifndef HAVE_PIPE -#include "../pulsecore/pipe.h" +#include #endif -#include #include #include #include #include #include +#include +#include +#include #include "mainloop.h" @@ -161,13 +160,13 @@ static pa_io_event* mainloop_io_new( pa_mainloop *m; pa_io_event *e; - assert(a); - assert(a->userdata); - assert(fd >= 0); - assert(callback); + pa_assert(a); + pa_assert(a->userdata); + pa_assert(fd >= 0); + pa_assert(callback); m = a->userdata; - assert(a == &m->api); + pa_assert(a == &m->api); e = pa_xnew(pa_io_event, 1); e->mainloop = m; @@ -195,7 +194,7 @@ static pa_io_event* mainloop_io_new( if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset, SELECT_TYPE_ARG5 &tv) == -1) && (WSAGetLastError() == WSAENOTSOCK)) { - pa_log_warn("WARNING: cannot monitor non-socket file descriptors."); + pa_log_warn("Cannot monitor non-socket file descriptors."); e->dead = 1; } } @@ -211,8 +210,8 @@ static pa_io_event* mainloop_io_new( } static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { - assert(e); - assert(!e->dead); + pa_assert(e); + pa_assert(!e->dead); if (e->events == events) return; @@ -228,8 +227,8 @@ static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { } static void mainloop_io_free(pa_io_event *e) { - assert(e); - assert(!e->dead); + pa_assert(e); + pa_assert(!e->dead); e->dead = 1; e->mainloop->io_events_please_scan ++; @@ -241,7 +240,7 @@ static void mainloop_io_free(pa_io_event *e) { } static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) { - assert(e); + pa_assert(e); e->destroy_callback = callback; } @@ -255,12 +254,12 @@ static pa_defer_event* mainloop_defer_new( pa_mainloop *m; pa_defer_event *e; - assert(a); - assert(a->userdata); - assert(callback); + pa_assert(a); + pa_assert(a->userdata); + pa_assert(callback); m = a->userdata; - assert(a == &m->api); + pa_assert(a == &m->api); e = pa_xnew(pa_defer_event, 1); e->mainloop = m; @@ -281,11 +280,11 @@ static pa_defer_event* mainloop_defer_new( } static void mainloop_defer_enable(pa_defer_event *e, int b) { - assert(e); - assert(!e->dead); + pa_assert(e); + pa_assert(!e->dead); if (e->enabled && !b) { - assert(e->mainloop->n_enabled_defer_events > 0); + pa_assert(e->mainloop->n_enabled_defer_events > 0); e->mainloop->n_enabled_defer_events--; } else if (!e->enabled && b) { e->mainloop->n_enabled_defer_events++; @@ -296,21 +295,22 @@ static void mainloop_defer_enable(pa_defer_event *e, int b) { } static void mainloop_defer_free(pa_defer_event *e) { - assert(e); - assert(!e->dead); + pa_assert(e); + pa_assert(!e->dead); e->dead = 1; e->mainloop->defer_events_please_scan ++; if (e->enabled) { - assert(e->mainloop->n_enabled_defer_events > 0); + pa_assert(e->mainloop->n_enabled_defer_events > 0); e->mainloop->n_enabled_defer_events--; + e->enabled = 0; } } static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t callback) { - assert(e); - assert(!e->dead); + pa_assert(e); + pa_assert(!e->dead); e->destroy_callback = callback; } @@ -325,12 +325,12 @@ static pa_time_event* mainloop_time_new( pa_mainloop *m; pa_time_event *e; - assert(a); - assert(a->userdata); - assert(callback); + pa_assert(a); + pa_assert(a->userdata); + pa_assert(callback); m = a->userdata; - assert(a == &m->api); + pa_assert(a == &m->api); e = pa_xnew(pa_time_event, 1); e->mainloop = m; @@ -342,7 +342,7 @@ static pa_time_event* mainloop_time_new( m->n_enabled_time_events++; if (m->cached_next_time_event) { - assert(m->cached_next_time_event->enabled); + pa_assert(m->cached_next_time_event->enabled); if (pa_timeval_cmp(tv, &m->cached_next_time_event->timeval) < 0) m->cached_next_time_event = e; @@ -362,11 +362,11 @@ static pa_time_event* mainloop_time_new( } static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { - assert(e); - assert(!e->dead); + pa_assert(e); + pa_assert(!e->dead); if (e->enabled && !tv) { - assert(e->mainloop->n_enabled_time_events > 0); + pa_assert(e->mainloop->n_enabled_time_events > 0); e->mainloop->n_enabled_time_events--; } else if (!e->enabled && tv) e->mainloop->n_enabled_time_events++; @@ -377,7 +377,7 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { } if (e->mainloop->cached_next_time_event && e->enabled) { - assert(e->mainloop->cached_next_time_event->enabled); + pa_assert(e->mainloop->cached_next_time_event->enabled); if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0) e->mainloop->cached_next_time_event = e; @@ -386,15 +386,16 @@ static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { } static void mainloop_time_free(pa_time_event *e) { - assert(e); - assert(!e->dead); + pa_assert(e); + pa_assert(!e->dead); e->dead = 1; e->mainloop->time_events_please_scan ++; if (e->enabled) { - assert(e->mainloop->n_enabled_time_events > 0); + pa_assert(e->mainloop->n_enabled_time_events > 0); e->mainloop->n_enabled_time_events--; + e->enabled = 0; } if (e->mainloop->cached_next_time_event == e) @@ -404,8 +405,8 @@ static void mainloop_time_free(pa_time_event *e) { } static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t callback) { - assert(e); - assert(!e->dead); + pa_assert(e); + pa_assert(!e->dead); e->destroy_callback = callback; } @@ -415,10 +416,10 @@ static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb static void mainloop_quit(pa_mainloop_api*a, int retval) { pa_mainloop *m; - assert(a); - assert(a->userdata); + pa_assert(a); + pa_assert(a->userdata); m = a->userdata; - assert(a == &m->api); + pa_assert(a == &m->api); pa_mainloop_quit(m, retval); } @@ -456,8 +457,10 @@ pa_mainloop *pa_mainloop_new(void) { return NULL; } - pa_make_nonblock_fd(m->wakeup_pipe[0]); - pa_make_nonblock_fd(m->wakeup_pipe[1]); + pa_make_fd_nonblock(m->wakeup_pipe[0]); + pa_make_fd_nonblock(m->wakeup_pipe[1]); + pa_make_fd_cloexec(m->wakeup_pipe[0]); + pa_make_fd_cloexec(m->wakeup_pipe[1]); m->wakeup_requested = 0; PA_LLIST_HEAD_INIT(pa_io_event, m->io_events); @@ -502,7 +505,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) { PA_LLIST_REMOVE(pa_io_event, m->io_events, e); if (e->dead) { - assert(m->io_events_please_scan > 0); + pa_assert(m->io_events_please_scan > 0); m->io_events_please_scan--; } @@ -517,7 +520,7 @@ static void cleanup_io_events(pa_mainloop *m, int force) { e = n; } - assert(m->io_events_please_scan == 0); + pa_assert(m->io_events_please_scan == 0); } static void cleanup_time_events(pa_mainloop *m, int force) { @@ -534,13 +537,14 @@ static void cleanup_time_events(pa_mainloop *m, int force) { PA_LLIST_REMOVE(pa_time_event, m->time_events, e); if (e->dead) { - assert(m->time_events_please_scan > 0); + pa_assert(m->time_events_please_scan > 0); m->time_events_please_scan--; } if (!e->dead && e->enabled) { - assert(m->n_enabled_time_events > 0); + pa_assert(m->n_enabled_time_events > 0); m->n_enabled_time_events--; + e->enabled = 0; } if (e->destroy_callback) @@ -552,7 +556,7 @@ static void cleanup_time_events(pa_mainloop *m, int force) { e = n; } - assert(m->time_events_please_scan == 0); + pa_assert(m->time_events_please_scan == 0); } static void cleanup_defer_events(pa_mainloop *m, int force) { @@ -569,13 +573,14 @@ static void cleanup_defer_events(pa_mainloop *m, int force) { PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e); if (e->dead) { - assert(m->defer_events_please_scan > 0); + pa_assert(m->defer_events_please_scan > 0); m->defer_events_please_scan--; } if (!e->dead && e->enabled) { - assert(m->n_enabled_defer_events > 0); + pa_assert(m->n_enabled_defer_events > 0); m->n_enabled_defer_events--; + e->enabled = 0; } if (e->destroy_callback) @@ -587,12 +592,12 @@ static void cleanup_defer_events(pa_mainloop *m, int force) { e = n; } - assert(m->defer_events_please_scan == 0); + pa_assert(m->defer_events_please_scan == 0); } void pa_mainloop_free(pa_mainloop* m) { - assert(m); + pa_assert(m); cleanup_io_events(m, 1); cleanup_defer_events(m, 1); @@ -600,16 +605,13 @@ void pa_mainloop_free(pa_mainloop* m) { pa_xfree(m->pollfds); - if (m->wakeup_pipe[0] >= 0) - close(m->wakeup_pipe[0]); - if (m->wakeup_pipe[1] >= 0) - close(m->wakeup_pipe[1]); + pa_close_pipe(m->wakeup_pipe); pa_xfree(m); } static void scan_dead(pa_mainloop *m) { - assert(m); + pa_assert(m); if (m->io_events_please_scan) cleanup_io_events(m, 0); @@ -666,13 +668,14 @@ static int dispatch_pollfds(pa_mainloop *m) { pa_io_event *e; int r = 0, k; - assert(m->poll_func_ret > 0); + pa_assert(m->poll_func_ret > 0); for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) { if (e->dead || !e->pollfd || !e->pollfd->revents) continue; - assert(e->pollfd->fd == e->fd && e->callback); + pa_assert(e->pollfd->fd == e->fd); + pa_assert(e->callback); e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata); e->pollfd->revents = 0; r++; @@ -694,7 +697,7 @@ static int dispatch_defer(pa_mainloop *m) { if (e->dead || !e->enabled) continue; - assert(e->callback); + pa_assert(e->callback); e->callback(&m->api, e, e->userdata); r++; } @@ -704,7 +707,7 @@ static int dispatch_defer(pa_mainloop *m) { static pa_time_event* find_next_time_event(pa_mainloop *m) { pa_time_event *t, *n = NULL; - assert(m); + pa_assert(m); if (m->cached_next_time_event) return m->cached_next_time_event; @@ -736,7 +739,7 @@ static int calc_next_timeout(pa_mainloop *m) { return -1; t = find_next_time_event(m); - assert(t); + pa_assert(t); if (t->timeval.tv_sec <= 0) return 0; @@ -754,7 +757,7 @@ static int dispatch_timeout(pa_mainloop *m) { pa_time_event *e; struct timeval now; int r = 0; - assert(m); + pa_assert(m); if (m->n_enabled_time_events <= 0) return 0; @@ -767,7 +770,7 @@ static int dispatch_timeout(pa_mainloop *m) { continue; if (pa_timeval_cmp(&e->timeval, &now) <= 0) { - assert(e->callback); + pa_assert(e->callback); /* Disable time event */ mainloop_time_restart(e, NULL); @@ -783,7 +786,7 @@ static int dispatch_timeout(pa_mainloop *m) { void pa_mainloop_wakeup(pa_mainloop *m) { char c = 'W'; - assert(m); + pa_assert(m); if (m->wakeup_pipe[1] >= 0 && m->state == STATE_POLLING) { pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type); @@ -794,7 +797,7 @@ void pa_mainloop_wakeup(pa_mainloop *m) { static void clear_wakeup(pa_mainloop *m) { char c[10]; - assert(m); + pa_assert(m); if (m->wakeup_pipe[0] < 0) return; @@ -806,8 +809,8 @@ static void clear_wakeup(pa_mainloop *m) { } int pa_mainloop_prepare(pa_mainloop *m, int timeout) { - assert(m); - assert(m->state == STATE_PASSIVE); + pa_assert(m); + pa_assert(m->state == STATE_PASSIVE); clear_wakeup(m); scan_dead(m); @@ -833,8 +836,8 @@ quit: } int pa_mainloop_poll(pa_mainloop *m) { - assert(m); - assert(m->state == STATE_PREPARED); + pa_assert(m); + pa_assert(m->state == STATE_PREPARED); if (m->quit) goto quit; @@ -844,7 +847,7 @@ int pa_mainloop_poll(pa_mainloop *m) { if (m->n_enabled_defer_events ) m->poll_func_ret = 0; else { - assert(!m->rebuild_pollfds); + pa_assert(!m->rebuild_pollfds); if (m->poll_func) m->poll_func_ret = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata); @@ -870,8 +873,8 @@ quit: int pa_mainloop_dispatch(pa_mainloop *m) { int dispatched = 0; - assert(m); - assert(m->state == STATE_POLLED); + pa_assert(m); + pa_assert(m->state == STATE_POLLED); if (m->quit) goto quit; @@ -902,13 +905,13 @@ quit: } int pa_mainloop_get_retval(pa_mainloop *m) { - assert(m); + pa_assert(m); return m->retval; } int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) { int r; - assert(m); + pa_assert(m); if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0) goto quit; @@ -942,7 +945,7 @@ int pa_mainloop_run(pa_mainloop *m, int *retval) { } void pa_mainloop_quit(pa_mainloop *m, int retval) { - assert(m); + pa_assert(m); m->quit = 1; m->retval = retval; @@ -950,12 +953,12 @@ void pa_mainloop_quit(pa_mainloop *m, int retval) { } pa_mainloop_api* pa_mainloop_get_api(pa_mainloop*m) { - assert(m); + pa_assert(m); return &m->api; } void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) { - assert(m); + pa_assert(m); m->poll_func = poll_func; m->poll_func_userdata = userdata; diff --git a/src/pulse/operation.c b/src/pulse/operation.c index f23def50c..ed5eb4aa1 100644 --- a/src/pulse/operation.c +++ b/src/pulse/operation.c @@ -25,19 +25,18 @@ #include #endif -#include - #include +#include #include "internal.h" #include "operation.h" pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb, void *userdata) { pa_operation *o; - assert(c); + pa_assert(c); o = pa_xnew(pa_operation, 1); - o->ref = 1; + PA_REFCNT_INIT(o); o->context = c; o->stream = s; @@ -53,27 +52,27 @@ pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb } pa_operation *pa_operation_ref(pa_operation *o) { - assert(o); - assert(o->ref >= 1); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); - o->ref++; + PA_REFCNT_INC(o); return o; } void pa_operation_unref(pa_operation *o) { - assert(o); - assert(o->ref >= 1); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); - if ((--(o->ref)) == 0) { - assert(!o->context); - assert(!o->stream); + if (PA_REFCNT_DEC(o) <= 0) { + pa_assert(!o->context); + pa_assert(!o->stream); pa_xfree(o); } } static void operation_set_state(pa_operation *o, pa_operation_state_t st) { - assert(o); - assert(o->ref >= 1); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (st == o->state) return; @@ -85,7 +84,7 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) { if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) { if (o->context) { - assert(o->ref >= 2); + pa_assert(PA_REFCNT_VALUE(o) >= 2); PA_LLIST_REMOVE(pa_operation, o->context->operations, o); pa_operation_unref(o); @@ -101,22 +100,22 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) { } void pa_operation_cancel(pa_operation *o) { - assert(o); - assert(o->ref >= 1); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); operation_set_state(o, PA_OPERATION_CANCELED); } void pa_operation_done(pa_operation *o) { - assert(o); - assert(o->ref >= 1); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); operation_set_state(o, PA_OPERATION_DONE); } pa_operation_state_t pa_operation_get_state(pa_operation *o) { - assert(o); - assert(o->ref >= 1); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); return o->state; } diff --git a/src/pulse/sample.c b/src/pulse/sample.c index ffdeedf75..ae2a0b9f0 100644 --- a/src/pulse/sample.c +++ b/src/pulse/sample.c @@ -27,57 +27,58 @@ #endif #include -#include #include #include +#include +#include + #include "sample.h" size_t pa_sample_size(const pa_sample_spec *spec) { - assert(spec); - switch (spec->format) { - case PA_SAMPLE_U8: - case PA_SAMPLE_ULAW: - case PA_SAMPLE_ALAW: - return 1; - case PA_SAMPLE_S16LE: - case PA_SAMPLE_S16BE: - return 2; - case PA_SAMPLE_FLOAT32LE: - case PA_SAMPLE_FLOAT32BE: - return 4; - default: - assert(0); - return 0; - } + static const size_t table[] = { + [PA_SAMPLE_U8] = 1, + [PA_SAMPLE_ULAW] = 1, + [PA_SAMPLE_ALAW] = 1, + [PA_SAMPLE_S16LE] = 2, + [PA_SAMPLE_S16BE] = 2, + [PA_SAMPLE_FLOAT32LE] = 4, + [PA_SAMPLE_FLOAT32BE] = 4 + }; + + pa_assert(spec); + pa_assert(spec->format >= 0); + pa_assert(spec->format < PA_SAMPLE_MAX); + + return table[spec->format]; } size_t pa_frame_size(const pa_sample_spec *spec) { - assert(spec); + pa_assert(spec); return pa_sample_size(spec) * spec->channels; } size_t pa_bytes_per_second(const pa_sample_spec *spec) { - assert(spec); + pa_assert(spec); return spec->rate*pa_frame_size(spec); } pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) { - assert(spec); + pa_assert(spec); return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate); } size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) { - assert(spec); + pa_assert(spec); return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec); } int pa_sample_spec_valid(const pa_sample_spec *spec) { - assert(spec); + pa_assert(spec); if (spec->rate <= 0 || spec->rate > PA_RATE_MAX || @@ -91,7 +92,8 @@ int pa_sample_spec_valid(const pa_sample_spec *spec) { } int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) { - assert(a && b); + pa_assert(a); + pa_assert(b); return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels); } @@ -107,37 +109,42 @@ const char *pa_sample_format_to_string(pa_sample_format_t f) { [PA_SAMPLE_FLOAT32BE] = "float32be", }; - if (f >= PA_SAMPLE_MAX) + if (f < 0 || f >= PA_SAMPLE_MAX) return NULL; return table[f]; } char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) { - assert(s && l && spec); + pa_assert(s); + pa_assert(l); + pa_assert(spec); if (!pa_sample_spec_valid(spec)) - snprintf(s, l, "Invalid"); + pa_snprintf(s, l, "Invalid"); else - snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate); + pa_snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate); return s; } char* pa_bytes_snprint(char *s, size_t l, unsigned v) { + pa_assert(s); + if (v >= ((unsigned) 1024)*1024*1024) - snprintf(s, l, "%0.1f GiB", ((double) v)/1024/1024/1024); + pa_snprintf(s, l, "%0.1f GiB", ((double) v)/1024/1024/1024); else if (v >= ((unsigned) 1024)*1024) - snprintf(s, l, "%0.1f MiB", ((double) v)/1024/1024); + pa_snprintf(s, l, "%0.1f MiB", ((double) v)/1024/1024); else if (v >= (unsigned) 1024) - snprintf(s, l, "%0.1f KiB", ((double) v)/1024); + pa_snprintf(s, l, "%0.1f KiB", ((double) v)/1024); else - snprintf(s, l, "%u B", (unsigned) v); + pa_snprintf(s, l, "%u B", (unsigned) v); return s; } pa_sample_format_t pa_parse_sample_format(const char *format) { + pa_assert(format); if (strcasecmp(format, "s16le") == 0) return PA_SAMPLE_S16LE; @@ -145,15 +152,19 @@ pa_sample_format_t pa_parse_sample_format(const char *format) { return PA_SAMPLE_S16BE; else if (strcasecmp(format, "s16ne") == 0 || strcasecmp(format, "s16") == 0 || strcasecmp(format, "16") == 0) return PA_SAMPLE_S16NE; + else if (strcasecmp(format, "s16re") == 0) + return PA_SAMPLE_S16RE; else if (strcasecmp(format, "u8") == 0 || strcasecmp(format, "8") == 0) return PA_SAMPLE_U8; else if (strcasecmp(format, "float32") == 0 || strcasecmp(format, "float32ne") == 0) - return PA_SAMPLE_FLOAT32; + return PA_SAMPLE_FLOAT32NE; + else if (strcasecmp(format, "float32re") == 0) + return PA_SAMPLE_FLOAT32RE; else if (strcasecmp(format, "float32le") == 0) return PA_SAMPLE_FLOAT32LE; else if (strcasecmp(format, "float32be") == 0) return PA_SAMPLE_FLOAT32BE; - else if (strcasecmp(format, "ulaw") == 0) + else if (strcasecmp(format, "ulaw") == 0 || strcasecmp(format, "mulaw") == 0) return PA_SAMPLE_ULAW; else if (strcasecmp(format, "alaw") == 0) return PA_SAMPLE_ALAW; diff --git a/src/pulse/sample.h b/src/pulse/sample.h index 683167cc5..b307621e4 100644 --- a/src/pulse/sample.h +++ b/src/pulse/sample.h @@ -155,31 +155,31 @@ typedef struct pa_sample_spec { typedef uint64_t pa_usec_t; /** Return the amount of bytes playback of a second of audio with the specified sample type takes */ -size_t pa_bytes_per_second(const pa_sample_spec *spec); +size_t pa_bytes_per_second(const pa_sample_spec *spec) PA_GCC_PURE; /** Return the size of a frame with the specific sample type */ -size_t pa_frame_size(const pa_sample_spec *spec); +size_t pa_frame_size(const pa_sample_spec *spec) PA_GCC_PURE; /** Return the size of a sample with the specific sample type */ -size_t pa_sample_size(const pa_sample_spec *spec); +size_t pa_sample_size(const pa_sample_spec *spec) PA_GCC_PURE; /** Calculate the time the specified bytes take to play with the specified sample type */ -pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec); +pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) PA_GCC_PURE; /** Calculates the number of bytes that are required for the specified time. \since 0.9 */ -size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec); +size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) PA_GCC_PURE; /** Return non-zero when the sample type specification is valid */ -int pa_sample_spec_valid(const pa_sample_spec *spec); +int pa_sample_spec_valid(const pa_sample_spec *spec) PA_GCC_PURE; /** Return non-zero when the two sample type specifications match */ -int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b); +int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) PA_GCC_PURE; /** Return a descriptive string for the specified sample format. \since 0.8 */ -const char *pa_sample_format_to_string(pa_sample_format_t f); +const char *pa_sample_format_to_string(pa_sample_format_t f) PA_GCC_PURE; /** Parse a sample format text. Inverse of pa_sample_format_to_string() */ -pa_sample_format_t pa_parse_sample_format(const char *format); +pa_sample_format_t pa_parse_sample_format(const char *format) PA_GCC_PURE; /** Maximum required string length for pa_sample_spec_snprint() */ #define PA_SAMPLE_SPEC_SNPRINT_MAX 32 diff --git a/src/pulse/scache.c b/src/pulse/scache.c index 09bc1078d..186b0a3e6 100644 --- a/src/pulse/scache.c +++ b/src/pulse/scache.c @@ -25,12 +25,12 @@ #include #endif -#include #include #include #include #include +#include #include "internal.h" @@ -40,7 +40,8 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) { pa_tagstruct *t; uint32_t tag; - assert(s); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, length > 0, PA_ERR_INVALID); @@ -66,7 +67,9 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) { int pa_stream_finish_upload(pa_stream *s) { pa_tagstruct *t; uint32_t tag; - assert(s); + + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY(s->context, s->channel_valid, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -87,8 +90,8 @@ pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); @@ -115,8 +118,8 @@ pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_conte pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID); diff --git a/src/pulse/simple.c b/src/pulse/simple.c index 3cf862d28..1072fb4d6 100644 --- a/src/pulse/simple.c +++ b/src/pulse/simple.c @@ -1,3 +1,4 @@ + /* $Id$ */ /*** @@ -27,7 +28,6 @@ #include #include -#include #include #include @@ -36,6 +36,7 @@ #include #include +#include #include "simple.h" @@ -83,8 +84,8 @@ if (!(p)->context || pa_context_get_state((p)->context) != PA_CONTEXT_READY || \ static void context_state_cb(pa_context *c, void *userdata) { pa_simple *p = userdata; - assert(c); - assert(p); + pa_assert(c); + pa_assert(p); switch (pa_context_get_state(c)) { case PA_CONTEXT_READY: @@ -103,8 +104,8 @@ static void context_state_cb(pa_context *c, void *userdata) { static void stream_state_cb(pa_stream *s, void * userdata) { pa_simple *p = userdata; - assert(s); - assert(p); + pa_assert(s); + pa_assert(p); switch (pa_stream_get_state(s)) { @@ -122,7 +123,7 @@ static void stream_state_cb(pa_stream *s, void * userdata) { static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { pa_simple *p = userdata; - assert(p); + pa_assert(p); pa_threaded_mainloop_signal(p->mainloop, 0); } @@ -130,21 +131,21 @@ static void stream_request_cb(pa_stream *s, size_t length, void *userdata) { static void stream_latency_update_cb(pa_stream *s, void *userdata) { pa_simple *p = userdata; - assert(p); + pa_assert(p); pa_threaded_mainloop_signal(p->mainloop, 0); } pa_simple* pa_simple_new( - const char *server, - const char *name, - pa_stream_direction_t dir, - const char *dev, - const char *stream_name, - const pa_sample_spec *ss, - const pa_channel_map *map, - const pa_buffer_attr *attr, - int *rerror) { + const char *server, + const char *name, + pa_stream_direction_t dir, + const char *dev, + const char *stream_name, + const pa_sample_spec *ss, + const pa_channel_map *map, + const pa_buffer_attr *attr, + int *rerror) { pa_simple *p; int error = PA_ERR_INTERNAL, r; @@ -232,7 +233,7 @@ fail: } void pa_simple_free(pa_simple *s) { - assert(s); + pa_assert(s); if (s->mainloop) pa_threaded_mainloop_stop(s->mainloop); @@ -250,7 +251,7 @@ void pa_simple_free(pa_simple *s) { } int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) { - assert(p); + pa_assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1); @@ -289,7 +290,7 @@ unlock_and_fail: } int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { - assert(p); + pa_assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1); CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1); @@ -346,8 +347,8 @@ unlock_and_fail: static void success_cb(pa_stream *s, int success, void *userdata) { pa_simple *p = userdata; - assert(s); - assert(p); + pa_assert(s); + pa_assert(p); p->operation_success = success; pa_threaded_mainloop_signal(p->mainloop, 0); @@ -356,7 +357,7 @@ static void success_cb(pa_stream *s, int success, void *userdata) { int pa_simple_drain(pa_simple *p, int *rerror) { pa_operation *o = NULL; - assert(p); + pa_assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); @@ -392,7 +393,7 @@ unlock_and_fail: int pa_simple_flush(pa_simple *p, int *rerror) { pa_operation *o = NULL; - assert(p); + pa_assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); @@ -429,7 +430,7 @@ pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) { pa_usec_t t; int negative; - assert(p); + pa_assert(p); pa_threaded_mainloop_lock(p->mainloop); diff --git a/src/pulse/simple.h b/src/pulse/simple.h index 128d27160..f76c1d67b 100644 --- a/src/pulse/simple.h +++ b/src/pulse/simple.h @@ -51,7 +51,7 @@ * pa_simple *s; * pa_sample_spec ss; * - * ss.format = PA_SAMPLE_S16_NE; + * ss.format = PA_SAMPLE_S16NE; * ss.channels = 2; * ss.rate = 44100; * diff --git a/src/pulse/stream.c b/src/pulse/stream.c index f20c17aef..47906a5cf 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -26,7 +26,6 @@ #include #endif -#include #include #include #include @@ -38,6 +37,7 @@ #include #include #include +#include #include "internal.h" @@ -47,13 +47,14 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * pa_stream *s; int i; - assert(c); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID); PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID); s = pa_xnew(pa_stream, 1); - s->ref = 1; + PA_REFCNT_INIT(s); s->context = c; s->mainloop = c->mainloop; @@ -91,6 +92,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->peek_memchunk.index = 0; s->peek_memchunk.length = 0; s->peek_memchunk.memblock = NULL; + s->peek_data = NULL; s->record_memblockq = NULL; @@ -118,15 +120,20 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * } static void stream_free(pa_stream *s) { - assert(s && !s->context && !s->channel_valid); + pa_assert(s); + pa_assert(!s->context); + pa_assert(!s->channel_valid); if (s->auto_timing_update_event) { - assert(s->mainloop); + pa_assert(s->mainloop); s->mainloop->time_free(s->auto_timing_update_event); } - if (s->peek_memchunk.memblock) + if (s->peek_memchunk.memblock) { + if (s->peek_data) + pa_memblock_release(s->peek_memchunk.memblock); pa_memblock_unref(s->peek_memchunk.memblock); + } if (s->record_memblockq) pa_memblockq_free(s->record_memblockq); @@ -136,38 +143,38 @@ static void stream_free(pa_stream *s) { } void pa_stream_unref(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); - if (--(s->ref) == 0) + if (PA_REFCNT_DEC(s) <= 0) stream_free(s); } pa_stream* pa_stream_ref(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); - s->ref++; + PA_REFCNT_INC(s); return s; } pa_stream_state_t pa_stream_get_state(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); return s->state; } pa_context* pa_stream_get_context(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); return s->context; } uint32_t pa_stream_get_index(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX); @@ -175,8 +182,8 @@ uint32_t pa_stream_get_index(pa_stream *s) { } void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); if (s->state == st) return; @@ -214,6 +221,13 @@ void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { s->channel_valid = 0; s->context = NULL; + + s->read_callback = NULL; + s->write_callback = NULL; + s->state_callback = NULL; + s->overflow_callback = NULL; + s->underflow_callback = NULL; + s->latency_update_callback = NULL; } pa_stream_unref(s); @@ -224,10 +238,11 @@ void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED pa_stream *s; uint32_t channel; - assert(pd); - assert(command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED); - assert(t); - assert(c); + pa_assert(pd); + pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED); + pa_assert(t); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_ref(c); @@ -252,10 +267,11 @@ void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32 pa_context *c = userdata; uint32_t bytes, channel; - assert(pd); - assert(command == PA_COMMAND_REQUEST); - assert(t); - assert(c); + pa_assert(pd); + pa_assert(command == PA_COMMAND_REQUEST); + pa_assert(t); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_ref(c); @@ -285,10 +301,11 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC pa_context *c = userdata; uint32_t channel; - assert(pd); - assert(command == PA_COMMAND_OVERFLOW || command == PA_COMMAND_UNDERFLOW); - assert(t); - assert(c); + pa_assert(pd); + pa_assert(command == PA_COMMAND_OVERFLOW || command == PA_COMMAND_UNDERFLOW); + pa_assert(t); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_ref(c); @@ -317,8 +334,8 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC } static void request_auto_timing_update(pa_stream *s, int force) { - struct timeval next; - assert(s); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); if (!(s->flags & PA_STREAM_AUTO_TIMING_UPDATE)) return; @@ -335,13 +352,17 @@ static void request_auto_timing_update(pa_stream *s, int force) { } } - pa_gettimeofday(&next); - pa_timeval_add(&next, LATENCY_IPOL_INTERVAL_USEC); - s->mainloop->time_restart(s->auto_timing_update_event, &next); + if (s->auto_timing_update_event) { + struct timeval next; + pa_gettimeofday(&next); + pa_timeval_add(&next, LATENCY_IPOL_INTERVAL_USEC); + s->mainloop->time_restart(s->auto_timing_update_event, &next); + } } static void invalidate_indexes(pa_stream *s, int r, int w) { - assert(s); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); /* pa_log("invalidate r:%u w:%u tag:%u", r, w, s->context->ctag); */ @@ -376,6 +397,9 @@ static void invalidate_indexes(pa_stream *s, int r, int w) { static void auto_timing_update_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { pa_stream *s = userdata; + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + /* pa_log("time event"); */ pa_stream_ref(s); @@ -383,12 +407,32 @@ static void auto_timing_update_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC pa_stream_unref(s); } +static void create_stream_complete(pa_stream *s) { + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + pa_assert(s->state == PA_STREAM_CREATING); + + pa_stream_set_state(s, PA_STREAM_READY); + + if (s->requested_bytes > 0 && s->write_callback) + s->write_callback(s, s->requested_bytes, s->write_userdata); + + if (s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { + struct timeval tv; + pa_gettimeofday(&tv); + tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */ + pa_assert(!s->auto_timing_update_event); + s->auto_timing_update_event = s->mainloop->time_new(s->mainloop, &tv, &auto_timing_update_callback, s); + } +} + void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s = userdata; - assert(pd); - assert(s); - assert(s->state == PA_STREAM_CREATING); + pa_assert(pd); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + pa_assert(s->state == PA_STREAM_CREATING); pa_stream_ref(s); @@ -431,7 +475,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED } if (s->direction == PA_STREAM_RECORD) { - assert(!s->record_memblockq); + pa_assert(!s->record_memblockq); s->record_memblockq = pa_memblockq_new( 0, @@ -446,23 +490,16 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED s->channel_valid = 1; pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); - pa_stream_set_state(s, PA_STREAM_READY); - - if (s->direction != PA_STREAM_UPLOAD && - s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { - struct timeval tv; - - pa_gettimeofday(&tv); - tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */ - - assert(!s->auto_timing_update_event); - s->auto_timing_update_event = s->mainloop->time_new(s->mainloop, &tv, &auto_timing_update_callback, s); - + if (s->direction != PA_STREAM_UPLOAD && s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { + /* If automatic timing updates are active, we wait for the + * first timing update before going to PA_STREAM_READY + * state */ + s->state = PA_STREAM_READY; request_auto_timing_update(s, 1); - } + s->state = PA_STREAM_CREATING; - if (s->requested_bytes > 0 && s->ref > 1 && s->write_callback) - s->write_callback(s, s->requested_bytes, s->write_userdata); + } else + create_stream_complete(s); finish: pa_stream_unref(s); @@ -480,8 +517,8 @@ static int create_stream( pa_tagstruct *t; uint32_t tag; - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, !(flags & ~((direction != PA_STREAM_UPLOAD ? @@ -503,12 +540,12 @@ static int create_stream( if (attr) s->buffer_attr = *attr; else { - /* half a second */ + /* half a second, with minimum request of 10 ms */ s->buffer_attr.tlength = pa_bytes_per_second(&s->sample_spec)/2; s->buffer_attr.maxlength = (s->buffer_attr.tlength*3)/2; - s->buffer_attr.minreq = s->buffer_attr.tlength/100; + s->buffer_attr.minreq = s->buffer_attr.tlength/50; s->buffer_attr.prebuf = s->buffer_attr.tlength - s->buffer_attr.minreq; - s->buffer_attr.fragsize = s->buffer_attr.tlength/100; + s->buffer_attr.fragsize = s->buffer_attr.tlength/50; } if (!dev) @@ -565,8 +602,8 @@ int pa_stream_connect_playback( pa_cvolume *volume, pa_stream *sync_stream) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); return create_stream(PA_STREAM_PLAYBACK, s, dev, attr, flags, volume, sync_stream); } @@ -577,8 +614,8 @@ int pa_stream_connect_record( const pa_buffer_attr *attr, pa_stream_flags_t flags) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); return create_stream(PA_STREAM_RECORD, s, dev, attr, flags, NULL, NULL); } @@ -593,9 +630,9 @@ int pa_stream_write( pa_memchunk chunk; - assert(s); - assert(s->ref >= 1); - assert(data); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + pa_assert(data); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK || s->direction == PA_STREAM_UPLOAD, PA_ERR_BADSTATE); @@ -608,8 +645,11 @@ int pa_stream_write( if (free_cb) chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) data, length, free_cb, 1); else { + void *tdata; chunk.memblock = pa_memblock_new(s->context->mempool, length); - memcpy(chunk.memblock->data, data, length); + tdata = pa_memblock_acquire(chunk.memblock); + memcpy(tdata, data, length); + pa_memblock_release(chunk.memblock); } chunk.index = 0; @@ -660,10 +700,10 @@ int pa_stream_write( } int pa_stream_peek(pa_stream *s, const void **data, size_t *length) { - assert(s); - assert(s->ref >= 1); - assert(data); - assert(length); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + pa_assert(data); + pa_assert(length); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE); @@ -675,27 +715,32 @@ int pa_stream_peek(pa_stream *s, const void **data, size_t *length) { *length = 0; return 0; } + + s->peek_data = pa_memblock_acquire(s->peek_memchunk.memblock); } - *data = (const char*) s->peek_memchunk.memblock->data + s->peek_memchunk.index; + pa_assert(s->peek_data); + *data = (uint8_t*) s->peek_data + s->peek_memchunk.index; *length = s->peek_memchunk.length; return 0; } int pa_stream_drop(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->peek_memchunk.memblock, PA_ERR_BADSTATE); - pa_memblockq_drop(s->record_memblockq, &s->peek_memchunk, s->peek_memchunk.length); + pa_memblockq_drop(s->record_memblockq, s->peek_memchunk.length); /* Fix the simulated local read index */ if (s->timing_info_valid && !s->timing_info.read_index_corrupt) s->timing_info.read_index += s->peek_memchunk.length; + pa_assert(s->peek_data); + pa_memblock_release(s->peek_memchunk.memblock); pa_memblock_unref(s->peek_memchunk.memblock); s->peek_memchunk.length = 0; s->peek_memchunk.index = 0; @@ -705,8 +750,8 @@ int pa_stream_drop(pa_stream *s) { } size_t pa_stream_writable_size(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1); PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_RECORD, PA_ERR_BADSTATE, (size_t) -1); @@ -715,8 +760,8 @@ size_t pa_stream_writable_size(pa_stream *s) { } size_t pa_stream_readable_size(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1); PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, (size_t) -1); @@ -729,8 +774,8 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us pa_tagstruct *t; uint32_t tag; - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); @@ -750,8 +795,9 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, struct timeval local, remote, now; pa_timing_info *i; - assert(pd); - assert(o); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context || !o->stream) goto finish; @@ -874,6 +920,10 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, } } + /* First, let's complete the initialization, if necessary. */ + if (o->stream->state == PA_STREAM_CREATING) + create_stream_complete(o->stream); + if (o->stream->latency_update_callback) o->stream->latency_update_callback(o->stream, o->stream->latency_update_userdata); @@ -895,8 +945,8 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t struct timeval now; int cidx = 0; - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); @@ -938,9 +988,9 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s = userdata; - assert(pd); - assert(s); - assert(s->ref >= 1); + pa_assert(pd); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); pa_stream_ref(s); @@ -965,8 +1015,8 @@ int pa_stream_disconnect(pa_stream *s) { pa_tagstruct *t; uint32_t tag; - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY(s->context, s->channel_valid, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -987,48 +1037,48 @@ int pa_stream_disconnect(pa_stream *s) { } void pa_stream_set_read_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); s->read_callback = cb; s->read_userdata = userdata; } void pa_stream_set_write_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); s->write_callback = cb; s->write_userdata = userdata; } void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); s->state_callback = cb; s->state_userdata = userdata; } void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); s->overflow_callback = cb; s->overflow_userdata = userdata; } void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); s->underflow_callback = cb; s->underflow_userdata = userdata; } void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); s->latency_update_callback = cb; s->latency_update_userdata = userdata; @@ -1038,9 +1088,9 @@ void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN pa_operation *o = userdata; int success = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -1070,8 +1120,8 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi pa_tagstruct *t; uint32_t tag; - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); @@ -1100,8 +1150,8 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, pa_operation *o; uint32_t tag; - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); @@ -1118,6 +1168,9 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command, pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) { @@ -1143,6 +1196,9 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE); @@ -1155,6 +1211,9 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) { pa_operation *o; + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE); @@ -1169,9 +1228,9 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe pa_tagstruct *t; uint32_t tag; - assert(s); - assert(s->ref >= 1); - assert(name); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + pa_assert(name); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); @@ -1193,8 +1252,8 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { pa_usec_t usec = 0; - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); @@ -1277,8 +1336,8 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) { } static pa_usec_t time_counter_diff(pa_stream *s, pa_usec_t a, pa_usec_t b, int *negative) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); if (negative) *negative = 0; @@ -1299,9 +1358,9 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) { int r; int64_t cindex; - assert(s); - assert(s->ref >= 1); - assert(r_usec); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + pa_assert(r_usec); PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); @@ -1331,8 +1390,8 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) { } const pa_timing_info* pa_stream_get_timing_info(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); @@ -1342,22 +1401,22 @@ const pa_timing_info* pa_stream_get_timing_info(pa_stream *s) { } const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); return &s->sample_spec; } const pa_channel_map* pa_stream_get_channel_map(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); return &s->channel_map; } const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s) { - assert(s); - assert(s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); diff --git a/src/pulse/subscribe.c b/src/pulse/subscribe.c index 5d8f12523..580038cc7 100644 --- a/src/pulse/subscribe.c +++ b/src/pulse/subscribe.c @@ -25,10 +25,10 @@ #include #endif -#include #include #include +#include #include #include "internal.h" @@ -40,10 +40,11 @@ void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSE pa_subscription_event_type_t e; uint32_t idx; - assert(pd); - assert(command == PA_COMMAND_SUBSCRIBE_EVENT); - assert(t); - assert(c); + pa_assert(pd); + pa_assert(command == PA_COMMAND_SUBSCRIBE_EVENT); + pa_assert(t); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_ref(c); @@ -67,8 +68,8 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_c pa_tagstruct *t; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -83,8 +84,8 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_c } void pa_context_set_subscribe_callback(pa_context *c, pa_context_subscribe_cb_t cb, void *userdata) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); c->subscribe_callback = cb; c->subscribe_userdata = userdata; diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c index 4f3cacc9a..9dd47ae32 100644 --- a/src/pulse/thread-mainloop.c +++ b/src/pulse/thread-mainloop.c @@ -26,24 +26,24 @@ #include #endif -#include #include #include -#ifdef HAVE_SYS_POLL_H -#include +#ifdef HAVE_POLL_H +#include #else -#include "../pulsecore/poll.h" +#include #endif #include +#include #include #include #include #include +#include -#include "mainloop.h" #include "thread-mainloop.h" struct pa_threaded_mainloop { @@ -63,7 +63,7 @@ static int poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void pa_mutex *mutex = userdata; int r; - assert(mutex); + pa_assert(mutex); /* Before entering poll() we unlock the mutex, so that * avahi_simple_poll_quit() can succeed from another thread. */ @@ -103,7 +103,7 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) { return NULL; } - m->mutex = pa_mutex_new(1); + m->mutex = pa_mutex_new(TRUE, FALSE); m->cond = pa_cond_new(); m->accept_cond = pa_cond_new(); m->thread = NULL; @@ -116,10 +116,10 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) { } void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { - assert(m); + pa_assert(m); /* Make sure that this function is not called from the helper thread */ - assert((m->thread && !pa_thread_is_running(m->thread)) || !in_worker(m)); + pa_assert((m->thread && !pa_thread_is_running(m->thread)) || !in_worker(m)); pa_threaded_mainloop_stop(m); @@ -136,9 +136,9 @@ void pa_threaded_mainloop_free(pa_threaded_mainloop* m) { } int pa_threaded_mainloop_start(pa_threaded_mainloop *m) { - assert(m); + pa_assert(m); - assert(!m->thread || !pa_thread_is_running(m->thread)); + pa_assert(!m->thread || !pa_thread_is_running(m->thread)); if (!(m->thread = pa_thread_new(thread, m))) return -1; @@ -147,13 +147,13 @@ int pa_threaded_mainloop_start(pa_threaded_mainloop *m) { } void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) { - assert(m); + pa_assert(m); if (!m->thread || !pa_thread_is_running(m->thread)) return; /* Make sure that this function is not called from the helper thread */ - assert(!in_worker(m)); + pa_assert(!in_worker(m)); pa_mutex_lock(m->mutex); pa_mainloop_quit(m->real_mainloop, 0); @@ -163,25 +163,25 @@ void pa_threaded_mainloop_stop(pa_threaded_mainloop *m) { } void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) { - assert(m); + pa_assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); + pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); pa_mutex_lock(m->mutex); } void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) { - assert(m); + pa_assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); + pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); pa_mutex_unlock(m->mutex); } void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) { - assert(m); + pa_assert(m); pa_cond_signal(m->cond, 1); @@ -190,36 +190,42 @@ void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) { } void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) { - assert(m); + pa_assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); + pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); m->n_waiting ++; pa_cond_wait(m->cond, m->mutex); - assert(m->n_waiting > 0); + pa_assert(m->n_waiting > 0); m->n_waiting --; } void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) { - assert(m); + pa_assert(m); /* Make sure that this function is not called from the helper thread */ - assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); + pa_assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m)); pa_cond_signal(m->accept_cond, 0); } int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) { - assert(m); + pa_assert(m); return pa_mainloop_get_retval(m->real_mainloop); } pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m) { - assert(m); + pa_assert(m); return pa_mainloop_get_api(m->real_mainloop); } + +int pa_threaded_mainloop_in_thread(pa_threaded_mainloop *m) { + pa_assert(m); + + return m->thread && pa_thread_self() == m->thread; +} diff --git a/src/pulse/thread-mainloop.h b/src/pulse/thread-mainloop.h index b78c1583f..ea08f72ac 100644 --- a/src/pulse/thread-mainloop.h +++ b/src/pulse/thread-mainloop.h @@ -297,6 +297,9 @@ int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m); /** Return the abstract main loop abstraction layer vtable for this main loop. */ pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m); +/** Returns non-zero when called from withing the event loop thread. \since 0.9.7 */ +int pa_threaded_mainloop_in_thread(pa_threaded_mainloop *m); + PA_C_DECL_END #endif diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c index 78ece0616..70ceb71e5 100644 --- a/src/pulse/timeval.c +++ b/src/pulse/timeval.c @@ -26,7 +26,6 @@ #include #endif -#include #include #include @@ -34,15 +33,17 @@ #include #endif -#include "../pulsecore/winsock.h" +#include +#include #include "timeval.h" struct timeval *pa_gettimeofday(struct timeval *tv) { #ifdef HAVE_GETTIMEOFDAY - assert(tv); + pa_assert(tv); - return gettimeofday(tv, NULL) < 0 ? NULL : tv; + pa_assert_se(gettimeofday(tv, NULL) == 0); + return tv; #elif defined(OS_IS_WIN32) /* * Copied from implementation by Steven Edwards (LGPL). @@ -59,7 +60,7 @@ struct timeval *pa_gettimeofday(struct timeval *tv) { LARGE_INTEGER li; __int64 t; - assert(tv); + pa_assert(tv); GetSystemTimeAsFileTime(&ft); li.LowPart = ft.dwLowDateTime; @@ -67,8 +68,8 @@ struct timeval *pa_gettimeofday(struct timeval *tv) { t = li.QuadPart; /* In 100-nanosecond intervals */ t -= EPOCHFILETIME; /* Offset to the Epoch time */ t /= 10; /* In microseconds */ - tv->tv_sec = (long)(t / 1000000); - tv->tv_usec = (long)(t % 1000000); + tv->tv_sec = (time_t) (t / PA_USEC_PER_SEC); + tv->tv_usec = (suseconds_t) (t % PA_USEC_PER_SEC); return tv; #else @@ -78,9 +79,11 @@ struct timeval *pa_gettimeofday(struct timeval *tv) { pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { pa_usec_t r; - assert(a && b); - /* Check which whan is the earlier time and swap the two arguments if reuqired. */ + pa_assert(a); + pa_assert(b); + + /* Check which whan is the earlier time and swap the two arguments if required. */ if (pa_timeval_cmp(a, b) < 0) { const struct timeval *c; c = a; @@ -89,7 +92,7 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { } /* Calculate the second difference*/ - r = ((pa_usec_t) a->tv_sec - b->tv_sec)* 1000000; + r = ((pa_usec_t) a->tv_sec - b->tv_sec) * PA_USEC_PER_SEC; /* Calculate the microsecond difference */ if (a->tv_usec > b->tv_usec) @@ -101,7 +104,8 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { } int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { - assert(a && b); + pa_assert(a); + pa_assert(b); if (a->tv_sec < b->tv_sec) return -1; @@ -120,26 +124,43 @@ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) { pa_usec_t pa_timeval_age(const struct timeval *tv) { struct timeval now; - assert(tv); + pa_assert(tv); return pa_timeval_diff(pa_gettimeofday(&now), tv); } struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) { unsigned long secs; - assert(tv); + pa_assert(tv); - secs = (v/1000000); - tv->tv_sec += (unsigned long) secs; - v -= secs*1000000; + secs = (unsigned long) (v/PA_USEC_PER_SEC); + tv->tv_sec += secs; + v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC; - tv->tv_usec += v; + tv->tv_usec += (suseconds_t) v; /* Normalize */ - while (tv->tv_usec >= 1000000) { + while (tv->tv_usec >= PA_USEC_PER_SEC) { tv->tv_sec++; - tv->tv_usec -= 1000000; + tv->tv_usec -= PA_USEC_PER_SEC; } return tv; } + +struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) { + pa_assert(tv); + + tv->tv_sec = v / PA_USEC_PER_SEC; + tv->tv_usec = v % PA_USEC_PER_SEC; + + return tv; +} + +pa_usec_t pa_timeval_load(const struct timeval *tv) { + pa_assert(tv); + + return + (pa_usec_t) tv->tv_sec * PA_USEC_PER_SEC + + (pa_usec_t) tv->tv_usec; +} diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h index 1e5627e33..65a0e5133 100644 --- a/src/pulse/timeval.h +++ b/src/pulse/timeval.h @@ -33,6 +33,11 @@ PA_C_DECL_BEGIN +#define PA_MSEC_PER_SEC 1000 +#define PA_USEC_PER_SEC 1000000 +#define PA_NSEC_PER_SEC 1000000000 +#define PA_USEC_PER_MSEC 1000 + struct timeval; /** Return the current timestamp, just like UNIX gettimeofday() */ @@ -40,16 +45,22 @@ struct timeval *pa_gettimeofday(struct timeval *tv); /** Calculate the difference between the two specified timeval * structs. */ -pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b); +pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) PA_GCC_PURE; /** Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */ -int pa_timeval_cmp(const struct timeval *a, const struct timeval *b); +int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) PA_GCC_PURE; /** Return the time difference between now and the specified timestamp */ pa_usec_t pa_timeval_age(const struct timeval *tv); /** Add the specified time inmicroseconds to the specified timeval structure */ -struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v); +struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) PA_GCC_PURE; + +/** Store the specified uec value in the timeval struct. \since 0.9.7 */ +struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v); + +/** Load the specified tv value and return it in usec. \since 0.9.7 */ +pa_usec_t pa_timeval_load(const struct timeval *tv); PA_C_DECL_END diff --git a/src/pulse/utf8.c b/src/pulse/utf8.c index 2ac2d1063..b2f6c3bd7 100644 --- a/src/pulse/utf8.c +++ b/src/pulse/utf8.c @@ -37,7 +37,7 @@ * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public @@ -50,7 +50,6 @@ #include #endif -#include #include #include #include @@ -60,12 +59,15 @@ #include #endif +#include +#include + #include "utf8.h" -#include "xmalloc.h" #define FILTER_CHAR '_' static inline int is_unicode_valid(uint32_t ch) { + if (ch >= 0x110000) /* End of unicode space */ return 0; if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */ @@ -74,6 +76,7 @@ static inline int is_unicode_valid(uint32_t ch) { return 0; if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */ return 0; + return 1; } @@ -95,6 +98,8 @@ static char* utf8_validate(const char *str, char *output) { int size; uint8_t *o; + pa_assert(str); + o = (uint8_t*) output; for (p = (const uint8_t*) str; *p; p++) { if (*p < 128) { @@ -178,15 +183,15 @@ failure: return NULL; } -const char* pa_utf8_valid (const char *str) { +char* pa_utf8_valid (const char *str) { return utf8_validate(str, NULL); } char* pa_utf8_filter (const char *str) { char *new_str; + pa_assert(str); new_str = pa_xnew(char, strlen(str) + 1); - return utf8_validate(str, new_str); } @@ -195,22 +200,24 @@ char* pa_utf8_filter (const char *str) { static char* iconv_simple(const char *str, const char *to, const char *from) { char *new_str; size_t len, inlen; - iconv_t cd; ICONV_CONST char *inbuf; char *outbuf; size_t res, inbytes, outbytes; + pa_assert(str); + pa_assert(to); + pa_assert(from); + cd = iconv_open(to, from); if (cd == (iconv_t)-1) return NULL; inlen = len = strlen(str) + 1; - new_str = pa_xmalloc(len); - assert(new_str); + new_str = pa_xnew(char, len); - while (1) { - inbuf = (ICONV_CONST char*)str; /* Brain dead prototype for iconv() */ + for (;;) { + inbuf = (ICONV_CONST char*) str; /* Brain dead prototype for iconv() */ inbytes = inlen; outbuf = new_str; outbytes = len; @@ -226,11 +233,10 @@ static char* iconv_simple(const char *str, const char *to, const char *from) { break; } - assert(inbytes != 0); + pa_assert(inbytes != 0); len += inbytes; new_str = pa_xrealloc(new_str, len); - assert(new_str); } iconv_close(cd); @@ -249,10 +255,12 @@ char* pa_locale_to_utf8 (const char *str) { #else char* pa_utf8_to_locale (const char *str) { + pa_assert(str); return NULL; } char* pa_locale_to_utf8 (const char *str) { + pa_assert(str); return NULL; } diff --git a/src/pulse/utf8.h b/src/pulse/utf8.h index ff8dc215b..1e08047c6 100644 --- a/src/pulse/utf8.h +++ b/src/pulse/utf8.h @@ -34,7 +34,7 @@ PA_C_DECL_BEGIN /** Test if the specified strings qualifies as valid UTF8. Return the string if so, otherwise NULL */ -const char *pa_utf8_valid(const char *str); +char *pa_utf8_valid(const char *str) PA_GCC_PURE; /** Filter all invalid UTF8 characters from the specified string, returning a new fully UTF8 valid string. Don't forget to free the returned string with pa_xfree() */ char *pa_utf8_filter(const char *str); diff --git a/src/pulse/util.c b/src/pulse/util.c index d561329cb..5dbb670bc 100644 --- a/src/pulse/util.c +++ b/src/pulse/util.c @@ -26,7 +26,6 @@ #include #endif -#include #include #include #include @@ -56,20 +55,14 @@ #include #endif -#include "../pulsecore/winsock.h" - +#include #include #include #include +#include #include "util.h" -#ifndef OS_IS_WIN32 -#define PATH_SEP '/' -#else -#define PATH_SEP '\\' -#endif - char *pa_get_user_name(char *s, size_t l) { char *p; char buf[1024]; @@ -78,7 +71,8 @@ char *pa_get_user_name(char *s, size_t l) { struct passwd pw, *r; #endif - assert(s && l > 0); + pa_assert(s); + pa_assert(l > 0); if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) { #ifdef HAVE_PWD_H @@ -90,7 +84,7 @@ char *pa_get_user_name(char *s, size_t l) { * that do not support getpwuid_r. */ if ((r = getpwuid(getuid())) == NULL) { #endif - snprintf(s, l, "%lu", (unsigned long) getuid()); + pa_snprintf(s, l, "%lu", (unsigned long) getuid()); return s; } @@ -113,11 +107,15 @@ char *pa_get_user_name(char *s, size_t l) { } char *pa_get_host_name(char *s, size_t l) { - assert(s && l > 0); + + pa_assert(s); + pa_assert(l > 0); + if (gethostname(s, l) < 0) { pa_log("gethostname(): %s", pa_cstrerror(errno)); return NULL; } + s[l-1] = 0; return s; } @@ -130,7 +128,8 @@ char *pa_get_home_dir(char *s, size_t l) { struct passwd pw, *r; #endif - assert(s && l); + pa_assert(s); + pa_assert(l > 0); if ((e = getenv("HOME"))) return pa_strlcpy(s, e, l); @@ -159,8 +158,8 @@ char *pa_get_home_dir(char *s, size_t l) { char *pa_get_binary_name(char *s, size_t l) { - assert(s); - assert(l); + pa_assert(s); + pa_assert(l > 0); #if defined(OS_IS_WIN32) { @@ -171,7 +170,7 @@ char *pa_get_binary_name(char *s, size_t l) { } #endif -#ifdef HAVE_READLINK +#ifdef __linux__ { int i; char path[PATH_MAX]; @@ -206,13 +205,15 @@ char *pa_get_binary_name(char *s, size_t l) { return NULL; } -const char *pa_path_get_filename(const char *p) { +char *pa_path_get_filename(const char *p) { char *fn; - if ((fn = strrchr(p, PATH_SEP))) + pa_assert(p); + + if ((fn = strrchr(p, PA_PATH_SEP_CHAR))) return fn+1; - return (const char*) p; + return (char*) p; } char *pa_get_fqdn(char *s, size_t l) { @@ -221,6 +222,9 @@ char *pa_get_fqdn(char *s, size_t l) { struct addrinfo *a, hints; #endif + pa_assert(s); + pa_assert(l > 0); + if (!pa_get_host_name(hn, sizeof(hn))) return NULL; diff --git a/src/pulse/util.h b/src/pulse/util.h index 95bd86f36..764678e5c 100644 --- a/src/pulse/util.h +++ b/src/pulse/util.h @@ -52,7 +52,7 @@ char *pa_get_binary_name(char *s, size_t l); /** Return a pointer to the filename inside a path (which is the last * component). */ -const char *pa_path_get_filename(const char *p); +char *pa_path_get_filename(const char *p); /** Wait t milliseconds */ int pa_msleep(unsigned long t); diff --git a/src/pulse/volume.c b/src/pulse/volume.c index feb33f078..3688b847c 100644 --- a/src/pulse/volume.c +++ b/src/pulse/volume.c @@ -25,16 +25,18 @@ #include #endif -#include #include #include +#include +#include + #include "volume.h" int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) { int i; - assert(a); - assert(b); + pa_assert(a); + pa_assert(b); if (a->channels != b->channels) return 0; @@ -49,9 +51,9 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) { pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) { int i; - assert(a); - assert(channels > 0); - assert(channels <= PA_CHANNELS_MAX); + pa_assert(a); + pa_assert(channels > 0); + pa_assert(channels <= PA_CHANNELS_MAX); a->channels = channels; @@ -64,7 +66,7 @@ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) { pa_volume_t pa_cvolume_avg(const pa_cvolume *a) { uint64_t sum = 0; int i; - assert(a); + pa_assert(a); for (i = 0; i < a->channels; i++) sum += a->values[i]; @@ -118,14 +120,14 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) { int first = 1; char *e; - assert(s); - assert(l > 0); - assert(c); + pa_assert(s); + pa_assert(l > 0); + pa_assert(c); *(e = s) = 0; for (channel = 0; channel < c->channels && l > 1; channel++) { - l -= snprintf(e, l, "%s%u: %3u%%", + l -= pa_snprintf(e, l, "%s%u: %3u%%", first ? "" : " ", channel, (c->values[channel]*100)/PA_VOLUME_NORM); @@ -140,7 +142,7 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) { /** Return non-zero if the volume of all channels is equal to the specified value */ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) { unsigned c; - assert(a); + pa_assert(a); for (c = 0; c < a->channels; c++) if (a->values[c] != v) @@ -152,9 +154,9 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) { pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) { unsigned i; - assert(dest); - assert(a); - assert(b); + pa_assert(dest); + pa_assert(a); + pa_assert(b); for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++) { @@ -169,7 +171,7 @@ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const } int pa_cvolume_valid(const pa_cvolume *v) { - assert(v); + pa_assert(v); if (v->channels <= 0 || v->channels > PA_CHANNELS_MAX) return 0; diff --git a/src/pulse/volume.h b/src/pulse/volume.h index a928ff711..22e5b8a4e 100644 --- a/src/pulse/volume.h +++ b/src/pulse/volume.h @@ -113,7 +113,7 @@ typedef struct pa_cvolume { } pa_cvolume; /** Return non-zero when *a == *b */ -int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b); +int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) PA_GCC_PURE; /** Set the volume of all channels to PA_VOLUME_NORM */ #define pa_cvolume_reset(a, n) pa_cvolume_set((a), (n), PA_VOLUME_NORM) @@ -131,13 +131,13 @@ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v); char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c); /** Return the average volume of all channels */ -pa_volume_t pa_cvolume_avg(const pa_cvolume *a); +pa_volume_t pa_cvolume_avg(const pa_cvolume *a) PA_GCC_PURE; /** Return TRUE when the passed cvolume structure is valid, FALSE otherwise */ -int pa_cvolume_valid(const pa_cvolume *v); +int pa_cvolume_valid(const pa_cvolume *v) PA_GCC_PURE; /** Return non-zero if the volume of all channels is equal to the specified value */ -int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v); +int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) PA_GCC_PURE; /** Return 1 if the specified volume has all channels muted */ #define pa_cvolume_is_muted(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_MUTED) @@ -146,22 +146,22 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v); #define pa_cvolume_is_norm(a) pa_cvolume_channels_equal_to((a), PA_VOLUME_NORM) /** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. This is only valid for software volumes! */ -pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b); +pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) PA_GCC_CONST; /** Multiply to per-channel volumes and return the result in *dest. This is only valid for software volumes! */ -pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b); +pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) PA_GCC_PURE; /** Convert a decibel value to a volume. This is only valid for software volumes! \since 0.4 */ -pa_volume_t pa_sw_volume_from_dB(double f); +pa_volume_t pa_sw_volume_from_dB(double f) PA_GCC_CONST; /** Convert a volume to a decibel value. This is only valid for software volumes! \since 0.4 */ -double pa_sw_volume_to_dB(pa_volume_t v); +double pa_sw_volume_to_dB(pa_volume_t v) PA_GCC_CONST; /** Convert a linear factor to a volume. This is only valid for software volumes! \since 0.8 */ -pa_volume_t pa_sw_volume_from_linear(double v); +pa_volume_t pa_sw_volume_from_linear(double v) PA_GCC_CONST; /** Convert a volume to a linear factor. This is only valid for software volumes! \since 0.8 */ -double pa_sw_volume_to_linear(pa_volume_t v); +double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST; #ifdef INFINITY #define PA_DECIBEL_MININFTY (-INFINITY) diff --git a/src/pulse/xmalloc.c b/src/pulse/xmalloc.c index 1f0734c24..5348dda41 100644 --- a/src/pulse/xmalloc.c +++ b/src/pulse/xmalloc.c @@ -27,12 +27,12 @@ #include #include -#include #include #include #include #include +#include #include "xmalloc.h" @@ -60,8 +60,8 @@ static void oom(void) { void* pa_xmalloc(size_t size) { void *p; - assert(size > 0); - assert(size < MAX_ALLOC_SIZE); + pa_assert(size > 0); + pa_assert(size < MAX_ALLOC_SIZE); if (!(p = malloc(size))) oom(); @@ -71,8 +71,8 @@ void* pa_xmalloc(size_t size) { void* pa_xmalloc0(size_t size) { void *p; - assert(size > 0); - assert(size < MAX_ALLOC_SIZE); + pa_assert(size > 0); + pa_assert(size < MAX_ALLOC_SIZE); if (!(p = calloc(1, size))) oom(); @@ -82,8 +82,8 @@ void* pa_xmalloc0(size_t size) { void *pa_xrealloc(void *ptr, size_t size) { void *p; - assert(size > 0); - assert(size < MAX_ALLOC_SIZE); + pa_assert(size > 0); + pa_assert(size < MAX_ALLOC_SIZE); if (!(p = realloc(ptr, size))) oom(); diff --git a/src/pulse/xmalloc.h b/src/pulse/xmalloc.h index 2f6399c58..62a450dc1 100644 --- a/src/pulse/xmalloc.h +++ b/src/pulse/xmalloc.h @@ -75,6 +75,15 @@ static inline void* pa_xnew0_internal(unsigned n, size_t k) { /** Same as pa_xnew() but set the memory to zero */ #define pa_xnew0(type, n) ((type*) pa_xnew0_internal((n), sizeof(type))) +/** Internal helper for pa_xnew0() */ +static inline void* pa_xnewdup_internal(const void *p, unsigned n, size_t k) { + assert(n < INT_MAX/k); + return pa_xmemdup(p, n*k); +} + +/** Same as pa_xnew() but set the memory to zero */ +#define pa_xnewdup(type, p, n) ((type*) pa_xnewdup_internal((p), (n), sizeof(type))) + PA_C_DECL_END #endif diff --git a/src/pulsecore/anotify.c b/src/pulsecore/anotify.c deleted file mode 100644 index 25c5fe7d8..000000000 --- a/src/pulsecore/anotify.c +++ /dev/null @@ -1,145 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of PulseAudio. - - Copyright 2006 Lennart Poettering - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include - -#include "anotify.h" - -#define EVENTS_MAX 16 - -struct pa_anotify { - pa_mainloop_api *api; - pa_anotify_cb_t callback; - void *userdata; - int fds[2]; - pa_io_event *io_event; - pa_defer_event *defer_event; - - uint8_t queued_events[EVENTS_MAX]; - unsigned n_queued_events, queue_index; -}; - -static void dispatch_event(pa_anotify *a) { - assert(a); - assert(a->queue_index < a->n_queued_events); - - a->callback(a->queued_events[a->queue_index++], a->userdata); - - if (a->queue_index >= a->n_queued_events) { - a->n_queued_events = 0; - a->queue_index = 0; - - a->api->io_enable(a->io_event, PA_IO_EVENT_INPUT); - a->api->defer_enable(a->defer_event, 0); - } else { - a->api->io_enable(a->io_event, 0); - a->api->defer_enable(a->defer_event, 1); - } -} - -static void io_callback( - pa_mainloop_api *api, - pa_io_event *e, - int fd, - pa_io_event_flags_t events, - void *userdata) { - - pa_anotify *a = userdata; - ssize_t r; - - assert(a); - assert(events == PA_IO_EVENT_INPUT); - assert(a->n_queued_events == 0); - - r = read(fd, a->queued_events, sizeof(a->queued_events)); - assert(r > 0); - - a->n_queued_events = (unsigned) r; - a->queue_index = 0; - - /* Only dispatch a single event */ - dispatch_event(a); -} - -static void defer_callback(pa_mainloop_api *api, pa_defer_event *e, void *userdata) { - pa_anotify *a = userdata; - assert(a); - - dispatch_event(a); -} - -pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userdata) { - pa_anotify *a; - - assert(api); - assert(cb); - - a = pa_xnew(pa_anotify, 1); - - if (pipe(a->fds) < 0) { - pa_xfree(a); - return NULL; - } - - a->api = api; - a->callback = cb; - a->userdata = userdata; - - a->io_event = api->io_new(api, a->fds[0], PA_IO_EVENT_INPUT, io_callback, a); - a->defer_event = api->defer_new(api, defer_callback, a); - a->api->defer_enable(a->defer_event, 0); - - a->n_queued_events = 0; - - return a; -} - -void pa_anotify_free(pa_anotify *a) { - assert(a); - - a->api->io_free(a->io_event); - a->api->defer_free(a->defer_event); - - if (a->fds[0] >= 0) - close(a->fds[0]); - if (a->fds[1] >= 0) - close(a->fds[1]); - - pa_xfree(a); -} - -int pa_anotify_signal(pa_anotify *a, uint8_t event) { - ssize_t r; - assert(a); - - r = write(a->fds[1], &event, 1); - return r != 1 ? -1 : 0; -} diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c new file mode 100644 index 000000000..96b43a714 --- /dev/null +++ b/src/pulsecore/asyncmsgq.c @@ -0,0 +1,303 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "asyncmsgq.h" + +PA_STATIC_FLIST_DECLARE(asyncmsgq, 0, pa_xfree); +PA_STATIC_FLIST_DECLARE(semaphores, 0, (void(*)(void*)) pa_semaphore_free); + +struct asyncmsgq_item { + int code; + pa_msgobject *object; + void *userdata; + pa_free_cb_t free_cb; + int64_t offset; + pa_memchunk memchunk; + pa_semaphore *semaphore; + int ret; +}; + +struct pa_asyncmsgq { + PA_REFCNT_DECLARE; + pa_asyncq *asyncq; + pa_mutex *mutex; /* only for the writer side */ + + struct asyncmsgq_item *current; +}; + +pa_asyncmsgq *pa_asyncmsgq_new(unsigned size) { + pa_asyncmsgq *a; + + a = pa_xnew(pa_asyncmsgq, 1); + + PA_REFCNT_INIT(a); + pa_assert_se(a->asyncq = pa_asyncq_new(size)); + pa_assert_se(a->mutex = pa_mutex_new(FALSE, TRUE)); + a->current = NULL; + + return a; +} + +static void asyncmsgq_free(pa_asyncmsgq *a) { + struct asyncmsgq_item *i; + pa_assert(a); + + while ((i = pa_asyncq_pop(a->asyncq, 0))) { + + pa_assert(!i->semaphore); + + if (i->object) + pa_msgobject_unref(i->object); + + if (i->memchunk.memblock) + pa_memblock_unref(i->memchunk.memblock); + + if (i->free_cb) + i->free_cb(i->userdata); + + if (pa_flist_push(PA_STATIC_FLIST_GET(asyncmsgq), i) < 0) + pa_xfree(i); + } + + pa_asyncq_free(a->asyncq, NULL); + pa_mutex_free(a->mutex); + pa_xfree(a); +} + +pa_asyncmsgq* pa_asyncmsgq_ref(pa_asyncmsgq *q) { + pa_assert(PA_REFCNT_VALUE(q) > 0); + + PA_REFCNT_INC(q); + return q; +} + +void pa_asyncmsgq_unref(pa_asyncmsgq* q) { + pa_assert(PA_REFCNT_VALUE(q) > 0); + + if (PA_REFCNT_DEC(q) <= 0) + asyncmsgq_free(q); +} + +void pa_asyncmsgq_post(pa_asyncmsgq *a, pa_msgobject *object, int code, const void *userdata, int64_t offset, const pa_memchunk *chunk, pa_free_cb_t free_cb) { + struct asyncmsgq_item *i; + pa_assert(PA_REFCNT_VALUE(a) > 0); + + if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(asyncmsgq)))) + i = pa_xnew(struct asyncmsgq_item, 1); + + i->code = code; + i->object = object ? pa_msgobject_ref(object) : NULL; + i->userdata = (void*) userdata; + i->free_cb = free_cb; + i->offset = offset; + if (chunk) { + pa_assert(chunk->memblock); + i->memchunk = *chunk; + pa_memblock_ref(i->memchunk.memblock); + } else + pa_memchunk_reset(&i->memchunk); + i->semaphore = NULL; + + /* This mutex makes the queue multiple-writer safe. This lock is only used on the writing side */ + pa_mutex_lock(a->mutex); + pa_assert_se(pa_asyncq_push(a->asyncq, i, 1) == 0); + pa_mutex_unlock(a->mutex); +} + +int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const void *userdata, int64_t offset, const pa_memchunk *chunk) { + struct asyncmsgq_item i; + pa_assert(PA_REFCNT_VALUE(a) > 0); + + i.code = code; + i.object = object; + i.userdata = (void*) userdata; + i.free_cb = NULL; + i.ret = -1; + i.offset = offset; + if (chunk) { + pa_assert(chunk->memblock); + i.memchunk = *chunk; + } else + pa_memchunk_reset(&i.memchunk); + + if (!(i.semaphore = pa_flist_pop(PA_STATIC_FLIST_GET(semaphores)))) + i.semaphore = pa_semaphore_new(0); + + pa_assert_se(i.semaphore); + + /* Thus mutex makes the queue multiple-writer safe. This lock is only used on the writing side */ + pa_mutex_lock(a->mutex); + pa_assert_se(pa_asyncq_push(a->asyncq, &i, 1) == 0); + pa_mutex_unlock(a->mutex); + + pa_semaphore_wait(i.semaphore); + + if (pa_flist_push(PA_STATIC_FLIST_GET(semaphores), i.semaphore) < 0) + pa_semaphore_free(i.semaphore); + + return i.ret; +} + +int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *chunk, int wait) { + pa_assert(PA_REFCNT_VALUE(a) > 0); + pa_assert(!a->current); + + if (!(a->current = pa_asyncq_pop(a->asyncq, wait))) { +/* pa_log("failure"); */ + return -1; + } + +/* pa_log("success"); */ + + if (code) + *code = a->current->code; + if (userdata) + *userdata = a->current->userdata; + if (offset) + *offset = a->current->offset; + if (object) { + if ((*object = a->current->object)) + pa_msgobject_assert_ref(*object); + } + if (chunk) + *chunk = a->current->memchunk; + +/* pa_log_debug("Get q=%p object=%p (%s) code=%i data=%p chunk.length=%lu", (void*) a, (void*) a->current->object, a->current->object ? a->current->object->parent.type_name : NULL, a->current->code, (void*) a->current->userdata, (unsigned long) a->current->memchunk.length); */ + + return 0; +} + +void pa_asyncmsgq_done(pa_asyncmsgq *a, int ret) { + pa_assert(PA_REFCNT_VALUE(a) > 0); + pa_assert(a); + pa_assert(a->current); + + if (a->current->semaphore) { + a->current->ret = ret; + pa_semaphore_post(a->current->semaphore); + } else { + + if (a->current->free_cb) + a->current->free_cb(a->current->userdata); + + if (a->current->object) + pa_msgobject_unref(a->current->object); + + if (a->current->memchunk.memblock) + pa_memblock_unref(a->current->memchunk.memblock); + + if (pa_flist_push(PA_STATIC_FLIST_GET(asyncmsgq), a->current) < 0) + pa_xfree(a->current); + } + + a->current = NULL; +} + +int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code) { + int c; + pa_assert(PA_REFCNT_VALUE(a) > 0); + + pa_asyncmsgq_ref(a); + + do { + pa_msgobject *o; + void *data; + int64_t offset; + pa_memchunk chunk; + int ret; + + if (pa_asyncmsgq_get(a, &o, &c, &data, &offset, &chunk, 1) < 0) + return -1; + + ret = pa_asyncmsgq_dispatch(o, c, data, offset, &chunk); + pa_asyncmsgq_done(a, ret); + + } while (c != code); + + pa_asyncmsgq_unref(a); + + return 0; +} + +int pa_asyncmsgq_process_one(pa_asyncmsgq *a) { + pa_msgobject *object; + int code; + void *data; + pa_memchunk chunk; + int64_t offset; + int ret; + + pa_assert(PA_REFCNT_VALUE(a) > 0); + + if (pa_asyncmsgq_get(a, &object, &code, &data, &offset, &chunk, 0) < 0) + return 0; + + pa_asyncmsgq_ref(a); + ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk); + pa_asyncmsgq_done(a, ret); + pa_asyncmsgq_unref(a); + + return 1; +} + +int pa_asyncmsgq_get_fd(pa_asyncmsgq *a) { + pa_assert(PA_REFCNT_VALUE(a) > 0); + + return pa_asyncq_get_fd(a->asyncq); +} + +int pa_asyncmsgq_before_poll(pa_asyncmsgq *a) { + pa_assert(PA_REFCNT_VALUE(a) > 0); + + return pa_asyncq_before_poll(a->asyncq); +} + +void pa_asyncmsgq_after_poll(pa_asyncmsgq *a) { + pa_assert(PA_REFCNT_VALUE(a) > 0); + + pa_asyncq_after_poll(a->asyncq); +} + +int pa_asyncmsgq_dispatch(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *memchunk) { + + if (object) + return object->process_msg(object, code, userdata, offset, memchunk); + + return 0; +} diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h new file mode 100644 index 000000000..5d3867ba0 --- /dev/null +++ b/src/pulsecore/asyncmsgq.h @@ -0,0 +1,75 @@ +#ifndef foopulseasyncmsgqhfoo +#define foopulseasyncmsgqhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include +#include +#include + +/* A simple asynchronous message queue, based on pa_asyncq. In + * contrast to pa_asyncq this one is multiple-writer safe, though + * still not multiple-reader safe. This queue is intended to be used + * for controlling real-time threads from normal-priority + * threads. Multiple-writer-safety is accomplished by using a mutex on + * the writer side. This queue is thus not useful for communication + * between several real-time threads. + * + * The queue takes messages consisting of: + * "Object" for which this messages is intended (may be NULL) + * A numeric message code + * Arbitrary userdata pointer (may be NULL) + * A memchunk (may be NULL) + * + * There are two functions for submitting messages: _post and + * _send. The former just enqueues the message asynchronously, the + * latter waits for completion, synchronously. */ + +enum { + PA_MESSAGE_SHUTDOWN = -1/* A generic message to inform the handler of this queue to quit */ +}; + +typedef struct pa_asyncmsgq pa_asyncmsgq; + +pa_asyncmsgq* pa_asyncmsgq_new(unsigned size); +pa_asyncmsgq* pa_asyncmsgq_ref(pa_asyncmsgq *q); +void pa_asyncmsgq_unref(pa_asyncmsgq* q); + +void pa_asyncmsgq_post(pa_asyncmsgq *q, pa_msgobject *object, int code, const void *userdata, int64_t offset, const pa_memchunk *memchunk, pa_free_cb_t userdata_free_cb); +int pa_asyncmsgq_send(pa_asyncmsgq *q, pa_msgobject *object, int code, const void *userdata, int64_t offset, const pa_memchunk *memchunk); + +int pa_asyncmsgq_get(pa_asyncmsgq *q, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *memchunk, int wait); +int pa_asyncmsgq_dispatch(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *memchunk); +void pa_asyncmsgq_done(pa_asyncmsgq *q, int ret); +int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code); +int pa_asyncmsgq_process_one(pa_asyncmsgq *a); + +/* Just for the reading side */ +int pa_asyncmsgq_get_fd(pa_asyncmsgq *q); +int pa_asyncmsgq_before_poll(pa_asyncmsgq *a); +void pa_asyncmsgq_after_poll(pa_asyncmsgq *a); + +#endif diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c new file mode 100644 index 000000000..75b15c0e2 --- /dev/null +++ b/src/pulsecore/asyncq.c @@ -0,0 +1,213 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "asyncq.h" +#include "fdsem.h" + +#define ASYNCQ_SIZE 128 + +/* For debugging purposes we can define _Y to put and extra thread + * yield between each operation. */ + +/* #define PROFILE */ + +#ifdef PROFILE +#define _Y pa_thread_yield() +#else +#define _Y do { } while(0) +#endif + +struct pa_asyncq { + unsigned size; + unsigned read_idx; + unsigned write_idx; + pa_fdsem *read_fdsem, *write_fdsem; +}; + +#define PA_ASYNCQ_CELLS(x) ((pa_atomic_ptr_t*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_asyncq)))) + +static int is_power_of_two(unsigned size) { + return !(size & (size - 1)); +} + +static int reduce(pa_asyncq *l, int value) { + return value & (unsigned) (l->size - 1); +} + +pa_asyncq *pa_asyncq_new(unsigned size) { + pa_asyncq *l; + + if (!size) + size = ASYNCQ_SIZE; + + pa_assert(is_power_of_two(size)); + + l = pa_xmalloc0(PA_ALIGN(sizeof(pa_asyncq)) + (sizeof(pa_atomic_ptr_t) * size)); + + l->size = size; + + if (!(l->read_fdsem = pa_fdsem_new())) { + pa_xfree(l); + return NULL; + } + + if (!(l->write_fdsem = pa_fdsem_new())) { + pa_fdsem_free(l->read_fdsem); + pa_xfree(l); + return NULL; + } + + return l; +} + +void pa_asyncq_free(pa_asyncq *l, pa_free_cb_t free_cb) { + pa_assert(l); + + if (free_cb) { + void *p; + + while ((p = pa_asyncq_pop(l, 0))) + free_cb(p); + } + + pa_fdsem_free(l->read_fdsem); + pa_fdsem_free(l->write_fdsem); + pa_xfree(l); +} + +int pa_asyncq_push(pa_asyncq*l, void *p, int wait) { + int idx; + pa_atomic_ptr_t *cells; + + pa_assert(l); + pa_assert(p); + + cells = PA_ASYNCQ_CELLS(l); + + _Y; + idx = reduce(l, l->write_idx); + + if (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) { + + if (!wait) + return -1; + +/* pa_log("sleeping on push"); */ + + do { + pa_fdsem_wait(l->read_fdsem); + } while (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)); + } + + _Y; + l->write_idx++; + + pa_fdsem_post(l->write_fdsem); + + return 0; +} + +void* pa_asyncq_pop(pa_asyncq*l, int wait) { + int idx; + void *ret; + pa_atomic_ptr_t *cells; + + pa_assert(l); + + cells = PA_ASYNCQ_CELLS(l); + + _Y; + idx = reduce(l, l->read_idx); + + if (!(ret = pa_atomic_ptr_load(&cells[idx]))) { + + if (!wait) + return NULL; + +/* pa_log("sleeping on pop"); */ + + do { + pa_fdsem_wait(l->write_fdsem); + } while (!(ret = pa_atomic_ptr_load(&cells[idx]))); + } + + pa_assert(ret); + + /* Guaranteed to succeed if we only have a single reader */ + pa_assert_se(pa_atomic_ptr_cmpxchg(&cells[idx], ret, NULL)); + + _Y; + l->read_idx++; + + pa_fdsem_post(l->read_fdsem); + + return ret; +} + +int pa_asyncq_get_fd(pa_asyncq *q) { + pa_assert(q); + + return pa_fdsem_get(q->write_fdsem); +} + +int pa_asyncq_before_poll(pa_asyncq *l) { + int idx; + pa_atomic_ptr_t *cells; + + pa_assert(l); + + cells = PA_ASYNCQ_CELLS(l); + + _Y; + idx = reduce(l, l->read_idx); + + for (;;) { + if (pa_atomic_ptr_load(&cells[idx])) + return -1; + + if (pa_fdsem_before_poll(l->write_fdsem) >= 0) + return 0; + } + + return 0; +} + +void pa_asyncq_after_poll(pa_asyncq *l) { + pa_assert(l); + + pa_fdsem_after_poll(l->write_fdsem); +} diff --git a/src/pulsecore/asyncq.h b/src/pulsecore/asyncq.h new file mode 100644 index 000000000..53d45866a --- /dev/null +++ b/src/pulsecore/asyncq.h @@ -0,0 +1,56 @@ +#ifndef foopulseasyncqhfoo +#define foopulseasyncqhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +/* A simple, asynchronous, lock-free (if requested also wait-free) + * queue. Not multiple-reader/multiple-writer safe. If that is + * required both sides can be protected by a mutex each. --- Which is + * not a bad thing in most cases, since this queue is intended for + * communication between a normal thread and a single real-time + * thread. Only the real-time side needs to be lock-free/wait-free. + * + * If the queue is full and another entry shall be pushed, or when the + * queue is empty and another entry shall be popped and the "wait" + * argument is non-zero, the queue will block on a UNIX FIFO object -- + * that will probably require locking on the kernel side -- which + * however is probably not problematic, because we do it only on + * starvation or overload in which case we have to block anyway. */ + +typedef struct pa_asyncq pa_asyncq; + +pa_asyncq* pa_asyncq_new(unsigned size); +void pa_asyncq_free(pa_asyncq* q, pa_free_cb_t free_cb); + +void* pa_asyncq_pop(pa_asyncq *q, int wait); +int pa_asyncq_push(pa_asyncq *q, void *p, int wait); + +int pa_asyncq_get_fd(pa_asyncq *q); +int pa_asyncq_before_poll(pa_asyncq *a); +void pa_asyncq_after_poll(pa_asyncq *a); + +#endif diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index 013e8c205..c2c99888b 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -24,48 +24,201 @@ USA. ***/ -#include - -/* atomic_ops guarantees us that sizeof(AO_t) == sizeof(void*). +/* + * atomic_ops guarantees us that sizeof(AO_t) == sizeof(void*). It is + * not guaranteed however, that sizeof(AO_t) == sizeof(size_t). + * however very likely. * - * It is not guaranteed however, that sizeof(AO_t) == sizeof(size_t). - * however very likely. */ + * For now we do only full memory barriers. Eventually we might want + * to support more elaborate memory barriers, in which case we will add + * suffixes to the function names. + * + * On gcc >= 4.1 we use the builtin atomic functions. otherwise we use + * libatomic_ops + */ -typedef struct pa_atomic_int { - volatile AO_t value; -} pa_atomic_int_t; +#ifndef PACKAGE +#error "Please include config.h before including this file!" +#endif + +#ifdef HAVE_ATOMIC_BUILTINS + +/* __sync based implementation */ + +typedef struct pa_atomic { + volatile int value; +} pa_atomic_t; #define PA_ATOMIC_INIT(v) { .value = (v) } -/* For now we do only full memory barriers. Eventually we might want - * to support more elaborate memory barriers, in which case we will add - * suffixes to the function names */ +static inline int pa_atomic_load(const pa_atomic_t *a) { + __sync_synchronize(); + return a->value; +} -static inline int pa_atomic_load(const pa_atomic_int_t *a) { +static inline void pa_atomic_store(pa_atomic_t *a, int i) { + a->value = i; + __sync_synchronize(); +} + +/* Returns the previously set value */ +static inline int pa_atomic_add(pa_atomic_t *a, int i) { + return __sync_fetch_and_add(&a->value, i); +} + +/* Returns the previously set value */ +static inline int pa_atomic_sub(pa_atomic_t *a, int i) { + return __sync_fetch_and_sub(&a->value, i); +} + +/* Returns the previously set value */ +static inline int pa_atomic_inc(pa_atomic_t *a) { + return pa_atomic_add(a, 1); +} + +/* Returns the previously set value */ +static inline int pa_atomic_dec(pa_atomic_t *a) { + return pa_atomic_sub(a, 1); +} + +/* Returns non-zero when the operation was successful. */ +static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { + return __sync_bool_compare_and_swap(&a->value, old_i, new_i); +} + +typedef struct pa_atomic_ptr { + volatile unsigned long value; +} pa_atomic_ptr_t; + +#define PA_ATOMIC_PTR_INIT(v) { .value = (long) (v) } + +static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { + __sync_synchronize(); + return (void*) a->value; +} + +static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { + a->value = (unsigned long) p; + __sync_synchronize(); +} + +static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { + return __sync_bool_compare_and_swap(&a->value, (long) old_p, (long) new_p); +} + +#elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)) + +#error "The native atomic operations implementation for AMD64 has not been tested. libatomic_ops is known to not work properly on AMD64 and your gcc version is too old for the gcc-builtin atomic ops support. You have three options now: make the native atomic operations implementation for AMD64 work, fix libatomic_ops, or upgrade your GCC." + +/* Addapted from glibc */ + +typedef struct pa_atomic { + volatile int value; +} pa_atomic_t; + +#define PA_ATOMIC_INIT(v) { .value = (v) } + +static inline int pa_atomic_load(const pa_atomic_t *a) { + return a->value; +} + +static inline void pa_atomic_store(pa_atomic_t *a, int i) { + a->value = i; +} + +static inline int pa_atomic_add(pa_atomic_t *a, int i) { + int result; + + __asm __volatile ("lock; xaddl %0, %1" + : "=r" (result), "=m" (a->value) + : "0" (i), "m" (a->value)); + + return result; +} + +static inline int pa_atomic_sub(pa_atomic_t *a, int i) { + return pa_atomic_add(a, -i); +} + +static inline int pa_atomic_inc(pa_atomic_t *a) { + return pa_atomic_add(a, 1); +} + +static inline int pa_atomic_dec(pa_atomic_t *a) { + return pa_atomic_sub(a, 1); +} + +static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { + int result; + + __asm__ __volatile__ ("lock; cmpxchgl %2, %1" + : "=a" (result), "=m" (a->value) + : "r" (new_i), "m" (a->value), "0" (old_i)); + + return result == oldval; +} + +typedef struct pa_atomic_ptr { + volatile unsigned long value; +} pa_atomic_ptr_t; + +#define PA_ATOMIC_PTR_INIT(v) { .value = (long) (v) } + +static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { + return (void*) a->value; +} + +static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { + a->value = (unsigned long) p; +} + +static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { + void *result; + + __asm__ __volatile__ ("lock; cmpxchgq %q2, %1" + : "=a" (result), "=m" (a->value) + : "r" (new_p), "m" (a->value), "0" (old_p)); + + return result; +} + +#else + +/* libatomic_ops based implementation */ + +#include + +typedef struct pa_atomic { + volatile AO_t value; +} pa_atomic_t; + +#define PA_ATOMIC_INIT(v) { .value = (v) } + +static inline int pa_atomic_load(const pa_atomic_t *a) { return (int) AO_load_full((AO_t*) &a->value); } -static inline void pa_atomic_store(pa_atomic_int_t *a, int i) { +static inline void pa_atomic_store(pa_atomic_t *a, int i) { AO_store_full(&a->value, (AO_t) i); } -static inline int pa_atomic_add(pa_atomic_int_t *a, int i) { +static inline int pa_atomic_add(pa_atomic_t *a, int i) { return AO_fetch_and_add_full(&a->value, (AO_t) i); } -static inline int pa_atomic_sub(pa_atomic_int_t *a, int i) { +static inline int pa_atomic_sub(pa_atomic_t *a, int i) { return AO_fetch_and_add_full(&a->value, (AO_t) -i); } -static inline int pa_atomic_inc(pa_atomic_int_t *a) { +static inline int pa_atomic_inc(pa_atomic_t *a) { return AO_fetch_and_add1_full(&a->value); } -static inline int pa_atomic_dec(pa_atomic_int_t *a) { +static inline int pa_atomic_dec(pa_atomic_t *a) { return AO_fetch_and_sub1_full(&a->value); } -static inline int pa_atomic_cmpxchg(pa_atomic_int_t *a, int old_i, int new_i) { +static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { return AO_compare_and_swap_full(&a->value, old_i, new_i); } @@ -73,6 +226,8 @@ typedef struct pa_atomic_ptr { volatile AO_t value; } pa_atomic_ptr_t; +#define PA_ATOMIC_PTR_INIT(v) { .value = (AO_t) (v) } + static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { return (void*) AO_load_full((AO_t*) &a->value); } @@ -86,3 +241,5 @@ static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* n } #endif + +#endif diff --git a/src/pulsecore/authkey-prop.c b/src/pulsecore/authkey-prop.c index 3b8304b23..541545003 100644 --- a/src/pulsecore/authkey-prop.c +++ b/src/pulsecore/authkey-prop.c @@ -21,44 +21,56 @@ USA. ***/ -#include +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include +#include #include +#include #include "authkey-prop.h" struct authkey_data { - int ref; + PA_REFCNT_DECLARE; size_t length; }; int pa_authkey_prop_get(pa_core *c, const char *name, void *data, size_t len) { struct authkey_data *a; - assert(c && name && data && len > 0); + + pa_assert(c); + pa_assert(name); + pa_assert(data); + pa_assert(len > 0); if (!(a = pa_property_get(c, name))) return -1; - assert(a->length == len); - memcpy(data, a+1, len); + pa_assert(a->length == len); + memcpy(data, (uint8_t*) a + PA_ALIGN(sizeof(struct authkey_data)), len); + return 0; } int pa_authkey_prop_put(pa_core *c, const char *name, const void *data, size_t len) { struct authkey_data *a; - assert(c && name); + + pa_assert(c); + pa_assert(name); if (pa_property_get(c, name)) return -1; - a = pa_xmalloc(sizeof(struct authkey_data) + len); - a->ref = 1; + a = pa_xmalloc(PA_ALIGN(sizeof(struct authkey_data)) + len); + PA_REFCNT_INIT(a); a->length = len; - memcpy(a+1, data, len); + memcpy((uint8_t*) a + PA_ALIGN(sizeof(struct authkey_data)), data, len); pa_property_set(c, name, a); @@ -67,22 +79,27 @@ int pa_authkey_prop_put(pa_core *c, const char *name, const void *data, size_t l void pa_authkey_prop_ref(pa_core *c, const char *name) { struct authkey_data *a; - assert(c && name); + + pa_assert(c); + pa_assert(name); a = pa_property_get(c, name); - assert(a && a->ref >= 1); - - a->ref++; + pa_assert(a); + pa_assert(PA_REFCNT_VALUE(a) >= 1); + PA_REFCNT_INC(a); } void pa_authkey_prop_unref(pa_core *c, const char *name) { struct authkey_data *a; - assert(c && name); + + pa_assert(c); + pa_assert(name); a = pa_property_get(c, name); - assert(a && a->ref >= 1); + pa_assert(a); + pa_assert(PA_REFCNT_VALUE(a) >= 1); - if (!(--a->ref)) { + if (PA_REFCNT_DEC(a) <= 0) { pa_property_remove(c, name); pa_xfree(a); } diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c index a6150d0e0..80bc85765 100644 --- a/src/pulsecore/authkey.c +++ b/src/pulsecore/authkey.c @@ -26,7 +26,6 @@ #include #endif -#include #include #include #include @@ -43,21 +42,25 @@ #include #include #include +#include #include "authkey.h" /* Generate a new authorization key, store it in file fd and return it in *data */ static int generate(int fd, void *ret_data, size_t length) { ssize_t r; - assert(fd >= 0 && ret_data && length); + + pa_assert(fd >= 0); + pa_assert(ret_data); + pa_assert(length > 0); pa_random(ret_data, length); lseek(fd, 0, SEEK_SET); - ftruncate(fd, 0); + (void) ftruncate(fd, 0); if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) { - pa_log("failed to write cookie file: %s", pa_cstrerror(errno)); + pa_log("Failed to write cookie file: %s", pa_cstrerror(errno)); return -1; } @@ -68,6 +71,10 @@ static int generate(int fd, void *ret_data, size_t length) { #define O_BINARY 0 #endif +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif + /* Load an euthorization cookie from file fn and store it in data. If * the cookie file doesn't exist, create it */ static int load(const char *fn, void *data, size_t length) { @@ -75,11 +82,15 @@ static int load(const char *fn, void *data, size_t length) { int writable = 1; int unlock = 0, ret = -1; ssize_t r; - assert(fn && data && length); - if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR)) < 0) { - if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY)) < 0) { - pa_log("failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_assert(fn); + pa_assert(data); + pa_assert(length > 0); + + if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) { + + if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY|O_NOCTTY)) < 0) { + pa_log("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } else writable = 0; @@ -88,15 +99,15 @@ static int load(const char *fn, void *data, size_t length) { unlock = pa_lock_fd(fd, 1) >= 0; if ((r = pa_loop_read(fd, data, length, NULL)) < 0) { - pa_log("failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } if ((size_t) r != length) { - pa_log_debug("got %d bytes from cookie file '%s', expected %d", (int)r, fn, (int)length); + pa_log_debug("Got %d bytes from cookie file '%s', expected %d", (int) r, fn, (int) length); if (!writable) { - pa_log("unable to write cookie to read only file"); + pa_log("Unable to write cookie to read only file"); goto finish; } @@ -113,7 +124,10 @@ finish: if (unlock) pa_lock_fd(fd, 0); - close(fd); + if (pa_close(fd) < 0) { + pa_log_warn("Failed to close cookie file: %s", pa_cstrerror(errno)); + ret = -1; + } } return ret; @@ -123,13 +137,12 @@ finish: int pa_authkey_load(const char *path, void *data, size_t length) { int ret; - assert(path && data && length); + pa_assert(path); + pa_assert(data); + pa_assert(length > 0); - ret = load(path, data, length); - - if (ret < 0) - pa_log("Failed to load authorization key '%s': %s", path, - (ret == -1) ? pa_cstrerror(errno) : "file corrupt"); + if ((ret = load(path, data, length)) < 0) + pa_log("Failed to load authorization key '%s': %s", path, (ret < 0) ? pa_cstrerror(errno) : "File corrupt"); return ret; } @@ -137,7 +150,10 @@ int pa_authkey_load(const char *path, void *data, size_t length) { /* If the specified file path starts with / return it, otherwise * return path prepended with home directory */ static const char *normalize_path(const char *fn, char *s, size_t l) { - assert(fn && s && l > 0); + + pa_assert(fn); + pa_assert(s); + pa_assert(l > 0); #ifndef OS_IS_WIN32 if (fn[0] != '/') { @@ -145,13 +161,14 @@ static const char *normalize_path(const char *fn, char *s, size_t l) { if (strlen(fn) < 3 || !isalpha(fn[0]) || fn[1] != ':' || fn[2] != '\\') { #endif char homedir[PATH_MAX]; + if (!pa_get_home_dir(homedir, sizeof(homedir))) return NULL; #ifndef OS_IS_WIN32 - snprintf(s, l, "%s/%s", homedir, fn); + pa_snprintf(s, l, "%s/%s", homedir, fn); #else - snprintf(s, l, "%s\\%s", homedir, fn); + pa_snprintf(s, l, "%s\\%s", homedir, fn); #endif return s; } @@ -164,7 +181,10 @@ static const char *normalize_path(const char *fn, char *s, size_t l) { int pa_authkey_load_auto(const char *fn, void *data, size_t length) { char path[PATH_MAX]; const char *p; - assert(fn && data && length); + + pa_assert(fn); + pa_assert(data); + pa_assert(length > 0); if (!(p = normalize_path(fn, path, sizeof(path)))) return -2; @@ -179,20 +199,23 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) { ssize_t r; char path[PATH_MAX]; const char *p; - assert(fn && data && length); + + pa_assert(fn); + pa_assert(data); + pa_assert(length > 0); if (!(p = normalize_path(fn, path, sizeof(path)))) return -2; - if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { - pa_log("failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); + if ((fd = open(p, O_RDWR|O_CREAT|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) { + pa_log("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } unlock = pa_lock_fd(fd, 1) >= 0; if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) { - pa_log("failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } @@ -205,7 +228,10 @@ finish: if (unlock) pa_lock_fd(fd, 0); - close(fd); + if (pa_close(fd) < 0) { + pa_log_warn("Failed to close cookie file: %s", pa_cstrerror(errno)); + ret = -1; + } } return ret; diff --git a/src/pulsecore/autoload.c b/src/pulsecore/autoload.c index 6f888526c..a1d3e02d5 100644 --- a/src/pulsecore/autoload.c +++ b/src/pulsecore/autoload.c @@ -26,7 +26,6 @@ #include #endif -#include #include #include @@ -36,13 +35,14 @@ #include #include #include +#include #include #include #include "autoload.h" static void entry_free(pa_autoload_entry *e) { - assert(e); + pa_assert(e); pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_REMOVE, PA_INVALID_INDEX); pa_xfree(e->name); pa_xfree(e->module); @@ -51,7 +51,8 @@ static void entry_free(pa_autoload_entry *e) { } static void entry_remove_and_free(pa_autoload_entry *e) { - assert(e && e->core); + pa_assert(e); + pa_assert(e->core); pa_idxset_remove_by_data(e->core->autoload_idxset, e, NULL); pa_hashmap_remove(e->core->autoload_hashmap, e->name); @@ -60,12 +61,14 @@ static void entry_remove_and_free(pa_autoload_entry *e) { static pa_autoload_entry* entry_new(pa_core *c, const char *name) { pa_autoload_entry *e = NULL; - assert(c && name); + + pa_core_assert_ref(c); + pa_assert(name); if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name))) return NULL; - e = pa_xmalloc(sizeof(pa_autoload_entry)); + e = pa_xnew(pa_autoload_entry, 1); e->core = c; e->name = pa_xstrdup(name); e->module = e->argument = NULL; @@ -73,7 +76,7 @@ static pa_autoload_entry* entry_new(pa_core *c, const char *name) { if (!c->autoload_hashmap) c->autoload_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - assert(c->autoload_hashmap); + pa_assert(c->autoload_hashmap); pa_hashmap_put(c->autoload_hashmap, e->name, e); @@ -88,7 +91,11 @@ static pa_autoload_entry* entry_new(pa_core *c, const char *name) { int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const char*module, const char *argument, uint32_t *idx) { pa_autoload_entry *e = NULL; - assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); + + pa_assert(c); + pa_assert(name); + pa_assert(module); + pa_assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE); if (!(e = entry_new(c, name))) return -1; @@ -105,7 +112,10 @@ int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const c int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type) { pa_autoload_entry *e; - assert(c && name && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE)); + + pa_assert(c); + pa_assert(name); + pa_assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) return -1; @@ -116,7 +126,9 @@ int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t ty int pa_autoload_remove_by_index(pa_core *c, uint32_t idx) { pa_autoload_entry *e; - assert(c && idx != PA_IDXSET_INVALID); + + pa_assert(c); + pa_assert(idx != PA_IDXSET_INVALID); if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, idx))) return -1; @@ -128,7 +140,9 @@ int pa_autoload_remove_by_index(pa_core *c, uint32_t idx) { void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type) { pa_autoload_entry *e; pa_module *m; - assert(c && name); + + pa_assert(c); + pa_assert(name); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || (e->type != type)) return; @@ -153,6 +167,7 @@ static void free_func(void *p, PA_GCC_UNUSED void *userdata) { } void pa_autoload_free(pa_core *c) { + if (c->autoload_hashmap) { pa_hashmap_free(c->autoload_hashmap, free_func, NULL); c->autoload_hashmap = NULL; @@ -166,7 +181,9 @@ void pa_autoload_free(pa_core *c) { const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type_t type) { pa_autoload_entry *e; - assert(c && name); + + pa_core_assert_ref(c); + pa_assert(name); if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type) return NULL; @@ -176,7 +193,9 @@ const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa const pa_autoload_entry* pa_autoload_get_by_index(pa_core *c, uint32_t idx) { pa_autoload_entry *e; - assert(c && idx != PA_IDXSET_INVALID); + + pa_core_assert_ref(c); + pa_assert(idx != PA_IDXSET_INVALID); if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, idx))) return NULL; diff --git a/src/pulsecore/avahi-wrap.c b/src/pulsecore/avahi-wrap.c index 855ed5671..fae54810a 100644 --- a/src/pulsecore/avahi-wrap.c +++ b/src/pulsecore/avahi-wrap.c @@ -21,11 +21,14 @@ USA. ***/ -#include +#ifdef HAVE_CONFIG_H +#include +#endif #include #include +#include #include "avahi-wrap.h" @@ -61,9 +64,9 @@ static pa_io_event_flags_t translate_io_flags(AvahiWatchEvent e) { static void watch_callback(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) { AvahiWatch *w = userdata; - assert(a); - assert(e); - assert(w); + pa_assert(a); + pa_assert(e); + pa_assert(w); w->current_event = translate_io_flags_back(events); w->callback(w, fd, w->current_event, w->userdata); @@ -74,12 +77,10 @@ static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event pa_avahi_poll *p; AvahiWatch *w; - assert(api); - assert(fd >= 0); - assert(callback); - - p = api->userdata; - assert(p); + pa_assert(api); + pa_assert(fd >= 0); + pa_assert(callback); + pa_assert_se(p = api->userdata); w = pa_xnew(AvahiWatch, 1); w->avahi_poll = p; @@ -92,19 +93,19 @@ static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event } static void watch_update(AvahiWatch *w, AvahiWatchEvent event) { - assert(w); + pa_assert(w); w->avahi_poll->mainloop->io_enable(w->io_event, translate_io_flags(event)); } static AvahiWatchEvent watch_get_events(AvahiWatch *w) { - assert(w); + pa_assert(w); return w->current_event; } static void watch_free(AvahiWatch *w) { - assert(w); + pa_assert(w); w->avahi_poll->mainloop->io_free(w->io_event); pa_xfree(w); @@ -120,9 +121,9 @@ struct AvahiTimeout { static void timeout_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) { AvahiTimeout *t = userdata; - assert(a); - assert(e); - assert(t); + pa_assert(a); + pa_assert(e); + pa_assert(t); t->callback(t, t->userdata); } @@ -131,11 +132,9 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, pa_avahi_poll *p; AvahiTimeout *t; - assert(api); - assert(callback); - - p = api->userdata; - assert(p); + pa_assert(api); + pa_assert(callback); + pa_assert_se(p = api->userdata); t = pa_xnew(AvahiTimeout, 1); t->avahi_poll = p; @@ -148,7 +147,7 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, } static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { - assert(t); + pa_assert(t); if (t->time_event && tv) t->avahi_poll->mainloop->time_restart(t->time_event, tv); @@ -161,7 +160,7 @@ static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { } static void timeout_free(AvahiTimeout *t) { - assert(t); + pa_assert(t); if (t->time_event) t->avahi_poll->mainloop->time_free(t->time_event); @@ -171,7 +170,7 @@ static void timeout_free(AvahiTimeout *t) { AvahiPoll* pa_avahi_poll_new(pa_mainloop_api *m) { pa_avahi_poll *p; - assert(m); + pa_assert(m); p = pa_xnew(pa_avahi_poll, 1); @@ -190,9 +189,8 @@ AvahiPoll* pa_avahi_poll_new(pa_mainloop_api *m) { void pa_avahi_poll_free(AvahiPoll *api) { pa_avahi_poll *p; - assert(api); - p = api->userdata; - assert(p); + pa_assert(api); + pa_assert_se(p = api->userdata); pa_xfree(p); } diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 6989069d3..539fd34dd 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -95,6 +94,7 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); @@ -114,6 +114,9 @@ static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); /* A method table for all available commands */ @@ -130,13 +133,14 @@ static const struct command commands[] = { { "info", pa_cli_command_info, "Show comprehensive status", 1 }, { "ls", pa_cli_command_info, NULL, 1 }, { "list", pa_cli_command_info, NULL, 1 }, - { "load-module", pa_cli_command_load, "Load a module (args: name, arguments)", 3}, - { "unload-module", pa_cli_command_unload, "Unload a module (args: index)", 2}, - { "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3}, - { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index|name, volume)", 3}, + { "load-module", pa_cli_command_load, "Load a module (args: name, arguments)", 3}, + { "unload-module", pa_cli_command_unload, "Unload a module (args: index)", 2}, + { "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3}, + { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index, volume)", 3}, { "set-source-volume", pa_cli_command_source_volume, "Set the volume of a source (args: index|name, volume)", 3}, - { "set-sink-mute", pa_cli_command_sink_mute, "Set the mute switch of a sink (args: index|name, mute)", 3}, - { "set-source-mute", pa_cli_command_source_mute, "Set the mute switch of a source (args: index|name, mute)", 3}, + { "set-sink-mute", pa_cli_command_sink_mute, "Set the mute switch of a sink (args: index|name, bool)", 3}, + { "set-sink-input-mute", pa_cli_command_sink_input_mute, "Set the mute switch of a sink input (args: index, bool)", 3}, + { "set-source-mute", pa_cli_command_source_mute, "Set the mute switch of a source (args: index|name, bool)", 3}, { "set-default-sink", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2}, { "set-default-source", pa_cli_command_source_default, "Set the default source (args: index|name)", 2}, { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2}, @@ -159,6 +163,9 @@ static const struct command commands[] = { { "move-sink-input", pa_cli_command_move_sink_input, "Move sink input to another sink (args: index, sink)", 3}, { "move-source-output", pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3}, { "vacuum", pa_cli_command_vacuum, NULL, 1}, + { "suspend-sink", pa_cli_command_suspend_sink, "Suspend sink (args: index|name, bool)", 3}, + { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3}, + { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2}, { NULL, NULL, NULL, 0 } }; @@ -174,15 +181,23 @@ static uint32_t parse_index(const char *n) { return idx; } -static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, PA_GCC_UNUSED pa_strbuf *buf, PA_GCC_UNUSED int *fail) { - assert(c && c->mainloop && t); +static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + c->mainloop->quit(c->mainloop, 0); return 0; } -static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const struct command*command; - assert(c && t && buf); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); pa_strbuf_puts(buf, "Available commands:\n"); @@ -192,67 +207,91 @@ static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G return 0; } -static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { char *s; - assert(c && t); - s = pa_module_list_to_string(c); - assert(s); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + pa_assert_se(s = pa_module_list_to_string(c)); pa_strbuf_puts(buf, s); pa_xfree(s); return 0; } -static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { char *s; - assert(c && t); - s = pa_client_list_to_string(c); - assert(s); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + pa_assert_se(s = pa_client_list_to_string(c)); pa_strbuf_puts(buf, s); pa_xfree(s); return 0; } -static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { char *s; - assert(c && t); - s = pa_sink_list_to_string(c); - assert(s); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + pa_assert_se(s = pa_sink_list_to_string(c)); pa_strbuf_puts(buf, s); pa_xfree(s); return 0; } -static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { char *s; - assert(c && t); - s = pa_source_list_to_string(c); - assert(s); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + pa_assert_se(s = pa_source_list_to_string(c)); pa_strbuf_puts(buf, s); pa_xfree(s); return 0; } -static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { char *s; - assert(c && t); - s = pa_sink_input_list_to_string(c); - assert(s); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + pa_assert_se(s = pa_sink_input_list_to_string(c)); pa_strbuf_puts(buf, s); pa_xfree(s); return 0; } -static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { char *s; - assert(c && t); - s = pa_source_output_list_to_string(c); - assert(s); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + pa_assert_se(s = pa_source_output_list_to_string(c)); pa_strbuf_puts(buf, s); pa_xfree(s); return 0; } -static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { char s[256]; const pa_mempool_stat *stat; unsigned k; @@ -267,8 +306,10 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G [PA_MEMBLOCK_IMPORTED] = "IMPORTED", }; - assert(c); - assert(t); + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); stat = pa_mempool_get_stat(c->mempool); @@ -312,7 +353,11 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G } static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { - assert(c && t); + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + pa_cli_command_stat(c, t, buf, fail); pa_cli_command_modules(c, t, buf, fail); pa_cli_command_sinks(c, t, buf, fail); @@ -325,10 +370,14 @@ static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int return 0; } -static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { pa_module *m; const char *name; - assert(c && t); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(name = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n"); @@ -343,12 +392,16 @@ static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G return 0; } -static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { pa_module *m; uint32_t idx; const char *i; char *e; - assert(c && t); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(i = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify the module index.\n"); @@ -365,12 +418,17 @@ static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA return 0; } -static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n, *v; pa_sink *sink; uint32_t volume; pa_cvolume cvolume; + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n"); return -1; @@ -392,17 +450,22 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu } pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume); - pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &cvolume); + pa_sink_set_volume(sink, &cvolume); return 0; } -static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n, *v; pa_sink_input *si; pa_volume_t volume; pa_cvolume cvolume; uint32_t idx; + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n"); return -1; @@ -433,12 +496,17 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb return 0; } -static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n, *v; pa_source *source; uint32_t volume; pa_cvolume cvolume; + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n"); return -1; @@ -460,15 +528,20 @@ static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf * } pa_cvolume_set(&cvolume, source->sample_spec.channels, volume); - pa_source_set_volume(source, PA_MIXER_HARDWARE, &cvolume); + pa_source_set_volume(source, &cvolume); return 0; } -static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n, *m; pa_sink *sink; int mute; + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n"); return -1; @@ -489,15 +562,20 @@ static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, return -1; } - pa_sink_set_mute(sink, PA_MIXER_HARDWARE, mute); + pa_sink_set_mute(sink, mute); return 0; } -static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n, *m; pa_source *source; int mute; + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n"); return -1; @@ -518,13 +596,57 @@ static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return -1; } - pa_source_set_mute(source, PA_MIXER_HARDWARE, mute); + pa_source_set_mute(source, mute); return 0; } -static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { + const char *n, *v; + pa_sink_input *si; + uint32_t idx; + int mute; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n"); + return -1; + } + + if ((idx = parse_index(n)) == PA_IDXSET_INVALID) { + pa_strbuf_puts(buf, "Failed to parse index.\n"); + return -1; + } + + if (!(v = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n"); + return -1; + } + + if (pa_atoi(v, &mute) < 0) { + pa_strbuf_puts(buf, "Failed to parse mute switch.\n"); + return -1; + } + + if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) { + pa_strbuf_puts(buf, "No sink input found with this index.\n"); + return -1; + } + + pa_sink_input_set_mute(si, mute); + return 0; +} + +static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n; - assert(c && t); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n"); @@ -535,9 +657,13 @@ static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *b return 0; } -static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n; - assert(c && t); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n"); @@ -548,11 +674,15 @@ static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n; pa_client *client; uint32_t idx; - assert(c && t); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a client by its index.\n"); @@ -573,11 +703,15 @@ static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return 0; } -static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n; pa_sink_input *sink_input; uint32_t idx; - assert(c && t); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n"); @@ -598,11 +732,15 @@ static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n; pa_source_output *source_output; uint32_t idx; - assert(c && t); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a source output by its index.\n"); @@ -623,20 +761,29 @@ static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_str return 0; } -static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { char *s; - assert(c && t); - s = pa_scache_list_to_string(c); - assert(s); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + pa_assert_se(s = pa_scache_list_to_string(c)); pa_strbuf_puts(buf, s); pa_xfree(s); + return 0; } static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n, *sink_name; pa_sink *sink; - assert(c && t && buf && fail); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) { pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n"); @@ -658,7 +805,11 @@ static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *bu static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *n; - assert(c && t && buf && fail); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sample name.\n"); @@ -676,7 +827,11 @@ static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf * static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *fname, *n; int r; - assert(c && t && buf && fail); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n"); @@ -696,7 +851,11 @@ static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *bu static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *pname; - assert(c && t && buf && fail); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(pname = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a path name.\n"); @@ -714,7 +873,11 @@ static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *fname, *sink_name; pa_sink *sink; - assert(c && t && buf && fail); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) { pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n"); @@ -732,7 +895,11 @@ static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *a, *b; - assert(c && t && buf && fail); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(a = pa_tokenizer_get(t, 1)) || !(b = pa_tokenizer_get(t, 2))) { pa_strbuf_puts(buf, "You need to specify a device name, a filename or a module name and optionally module arguments\n"); @@ -746,7 +913,11 @@ static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *b static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { const char *name; - assert(c && t && buf && fail); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); if (!(name = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a device name\n"); @@ -761,25 +932,36 @@ static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { char *s; - assert(c && t); - s = pa_autoload_list_to_string(c); - assert(s); + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + pa_assert_se(s = pa_autoload_list_to_string(c)); pa_strbuf_puts(buf, s); pa_xfree(s); + return 0; } -static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { - assert(c && t); +static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + pa_property_dump(c, buf); return 0; } static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { - assert(c); - assert(t); + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); pa_mempool_vacuum(c->mempool); @@ -792,6 +974,11 @@ static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf pa_sink *sink; uint32_t idx; + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n"); return -1; @@ -830,6 +1017,11 @@ static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_str pa_source *source; uint32_t idx; + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + if (!(n = pa_tokenizer_get(t, 1))) { pa_strbuf_puts(buf, "You need to specify a source output by its index.\n"); return -1; @@ -862,7 +1054,105 @@ static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_str return 0; } -static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) { +static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { + const char *n, *m; + pa_sink *sink; + int suspend; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n"); + return -1; + } + + if (!(m = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n"); + return -1; + } + + if (pa_atoi(m, &suspend) < 0) { + pa_strbuf_puts(buf, "Failed to parse suspend switch.\n"); + return -1; + } + + if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) { + pa_strbuf_puts(buf, "No sink found by this name or index.\n"); + return -1; + } + + pa_sink_suspend(sink, suspend); + return 0; +} + +static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { + const char *n, *m; + pa_source *source; + int suspend; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n"); + return -1; + } + + if (!(m = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n"); + return -1; + } + + if (pa_atoi(m, &suspend) < 0) { + pa_strbuf_puts(buf, "Failed to parse suspend switch.\n"); + return -1; + } + + if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE, 1))) { + pa_strbuf_puts(buf, "No source found by this name or index.\n"); + return -1; + } + + pa_source_suspend(source, suspend); + return 0; +} + +static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { + const char *m; + int suspend; + int ret; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(m = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n"); + return -1; + } + + if (pa_atoi(m, &suspend) < 0) { + pa_strbuf_puts(buf, "Failed to parse suspend switch.\n"); + return -1; + } + + ret = - (pa_sink_suspend_all(c, suspend) < 0); + if (pa_source_suspend_all(c, suspend) < 0) + ret = -1; + + if (ret < 0) + pa_strbuf_puts(buf, "Failed to resume/suspend all sinks/sources.\n"); + + return 0; +} + +static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { pa_module *m; pa_sink *sink; pa_source *source; @@ -874,7 +1164,10 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G void *i; pa_autoload_entry *a; - assert(c && t); + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); time(&now); @@ -884,7 +1177,6 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now)); #endif - for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) { if (m->auto_unload) continue; @@ -900,7 +1192,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G nl = 0; for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) { - if (sink->owner && sink->owner->auto_unload) + if (sink->module && sink->module->auto_unload) continue; if (!nl) { @@ -908,12 +1200,12 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G nl = 1; } - pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, PA_MIXER_HARDWARE))); - pa_strbuf_printf(buf, "set-sink-mute %s %d\n", sink->name, pa_sink_get_mute(sink, PA_MIXER_HARDWARE)); + pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink))); + pa_strbuf_printf(buf, "set-sink-mute %s %d\n", sink->name, pa_sink_get_mute(sink)); } for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) { - if (source->owner && source->owner->auto_unload) + if (source->module && source->module->auto_unload) continue; if (!nl) { @@ -921,8 +1213,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G nl = 1; } - pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source, PA_MIXER_HARDWARE))); - pa_strbuf_printf(buf, "set-source-mute %s %d\n", source->name, pa_source_get_mute(source, PA_MIXER_HARDWARE)); + pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source))); + pa_strbuf_printf(buf, "set-source-mute %s %d\n", source->name, pa_source_get_mute(source)); } @@ -972,6 +1264,10 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, int *fail, int *ifstate) { const char *cs; + pa_assert(c); + pa_assert(s); + pa_assert(buf); + cs = s+strspn(s, whitespace); if (*cs == '#' || !*cs) @@ -1006,9 +1302,9 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b if (l == sizeof(META_INCLUDE)-1 && !strncmp(cs, META_INCLUDE, l)) { const char *filename = cs+l+strspn(cs+l, whitespace); - if (pa_cli_command_execute_file(c, filename, buf, fail) < 0) - if (*fail) return -1; + if (*fail) + return -1; } else if (l == sizeof(META_IFEXISTS)-1 && !strncmp(cs, META_IFEXISTS, l)) { if (!ifstate) { pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs); @@ -1020,6 +1316,7 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b const char *filename = cs+l+strspn(cs+l, whitespace); *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE; + pa_log_debug("Checking for existance of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure"); } } else { pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs); @@ -1034,14 +1331,13 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b if (ifstate && *ifstate == IFSTATE_FALSE) return 0; - l = strcspn(cs, whitespace); for (command = commands; command->name; command++) if (strlen(command->name) == l && !strncmp(cs, command->name, l)) { int ret; pa_tokenizer *t = pa_tokenizer_new(cs, command->args); - assert(t); + pa_assert(t); ret = command->proc(c, t, buf, fail); pa_tokenizer_free(t); unknown = 0; @@ -1072,9 +1368,9 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int int ifstate = IFSTATE_NONE; int ret = -1; - assert(c); - assert(fn); - assert(buf); + pa_assert(c); + pa_assert(fn); + pa_assert(buf); if (!(f = fopen(fn, "r"))) { pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno)); @@ -1104,9 +1400,9 @@ int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail) const char *p; int ifstate = IFSTATE_NONE; - assert(c); - assert(s); - assert(buf); + pa_assert(c); + pa_assert(s); + pa_assert(buf); p = s; while (*p) { @@ -1125,3 +1421,4 @@ int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail) return 0; } + diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index 413f93340..6683e6973 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -25,7 +25,6 @@ #include #endif -#include #include #include @@ -41,6 +40,7 @@ #include #include #include +#include #include "cli-text.h" @@ -48,10 +48,9 @@ char *pa_module_list_to_string(pa_core *c) { pa_strbuf *s; pa_module *m; uint32_t idx = PA_IDXSET_INVALID; - assert(c); + pa_assert(c); s = pa_strbuf_new(); - assert(s); pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_size(c->modules)); @@ -72,10 +71,9 @@ char *pa_client_list_to_string(pa_core *c) { pa_strbuf *s; pa_client *client; uint32_t idx = PA_IDXSET_INVALID; - assert(c); + pa_assert(c); s = pa_strbuf_new(); - assert(s); pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_size(c->clients)); @@ -93,10 +91,15 @@ char *pa_sink_list_to_string(pa_core *c) { pa_strbuf *s; pa_sink *sink; uint32_t idx = PA_IDXSET_INVALID; - assert(c); + static const char* const state_table[] = { + [PA_SINK_RUNNING] = "RUNNING", + [PA_SINK_SUSPENDED] = "SUSPENDED", + [PA_SINK_IDLE] = "IDLE", + [PA_SINK_UNLINKED] = "UNLINKED" + }; + pa_assert(c); s = pa_strbuf_new(); - assert(s); pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks)); @@ -108,22 +111,35 @@ char *pa_sink_list_to_string(pa_core *c) { " %c index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" + "\tflags: %s%s%s\n" + "\tstate: %s\n" "\tvolume: <%s>\n" + "\tmute: <%i>\n" "\tlatency: <%0.0f usec>\n" - "\tmonitor_source: <%u>\n" + "\tmonitor source: <%u>\n" "\tsample spec: <%s>\n" - "\tchannel map: <%s>\n", + "\tchannel map: <%s>\n" + "\tused by: <%u>\n" + "\tlinked by: <%u>\n", c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', - sink->index, sink->name, + sink->index, + sink->name, sink->driver, - pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, PA_MIXER_HARDWARE)), + sink->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", + sink->flags & PA_SINK_LATENCY ? "LATENCY " : "", + sink->flags & PA_SINK_HARDWARE ? "HARDWARE " : "", + state_table[pa_sink_get_state(sink)], + pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)), + !!pa_sink_get_mute(sink), (double) pa_sink_get_latency(sink), sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX, pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec), - pa_channel_map_snprint(cm, sizeof(cm), &sink->channel_map)); + pa_channel_map_snprint(cm, sizeof(cm), &sink->channel_map), + pa_sink_used_by(sink), + pa_sink_linked_by(sink)); - if (sink->owner) - pa_strbuf_printf(s, "\towner module: <%u>\n", sink->owner->index); + if (sink->module) + pa_strbuf_printf(s, "\tmodule: <%u>\n", sink->module->index); if (sink->description) pa_strbuf_printf(s, "\tdescription: <%s>\n", sink->description); } @@ -135,15 +151,20 @@ char *pa_source_list_to_string(pa_core *c) { pa_strbuf *s; pa_source *source; uint32_t idx = PA_IDXSET_INVALID; - assert(c); + static const char* const state_table[] = { + [PA_SOURCE_RUNNING] = "RUNNING", + [PA_SOURCE_SUSPENDED] = "SUSPENDED", + [PA_SOURCE_IDLE] = "IDLE", + [PA_SOURCE_UNLINKED] = "UNLINKED" + }; + pa_assert(c); s = pa_strbuf_new(); - assert(s); pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources)); for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) { - char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX]; pa_strbuf_printf( @@ -151,21 +172,35 @@ char *pa_source_list_to_string(pa_core *c) { " %c index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" + "\tflags: %s%s%s\n" + "\tstate: %s\n" + "\tvolume: <%s>\n" + "\tmute: <%u>\n" "\tlatency: <%0.0f usec>\n" "\tsample spec: <%s>\n" - "\tchannel map: <%s>\n", + "\tchannel map: <%s>\n" + "\tused by: <%u>\n" + "\tlinked by: <%u>\n", c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ', source->index, source->name, source->driver, + source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", + source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", + source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "", + state_table[pa_source_get_state(source)], + pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)), + !!pa_source_get_mute(source), (double) pa_source_get_latency(source), pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec), - pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map)); + pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map), + pa_source_used_by(source), + pa_source_linked_by(source)); if (source->monitor_of) pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index); - if (source->owner) - pa_strbuf_printf(s, "\towner module: <%u>\n", source->owner->index); + if (source->module) + pa_strbuf_printf(s, "\tmodule: <%u>\n", source->module->index); if (source->description) pa_strbuf_printf(s, "\tdescription: <%s>\n", source->description); } @@ -179,37 +214,41 @@ char *pa_source_output_list_to_string(pa_core *c) { pa_source_output *o; uint32_t idx = PA_IDXSET_INVALID; static const char* const state_table[] = { - "RUNNING", - "CORKED", - "DISCONNECTED" + [PA_SOURCE_OUTPUT_RUNNING] = "RUNNING", + [PA_SOURCE_OUTPUT_CORKED] = "CORKED", + [PA_SOURCE_OUTPUT_UNLINKED] = "UNLINKED" }; - assert(c); + pa_assert(c); s = pa_strbuf_new(); - assert(s); pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_size(c->source_outputs)); for (o = pa_idxset_first(c->source_outputs, &idx); o; o = pa_idxset_next(c->source_outputs, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; - assert(o->source); + pa_assert(o->source); pa_strbuf_printf( s, " index: %u\n" "\tname: '%s'\n" "\tdriver: <%s>\n" + "\tflags: %s%s\n" "\tstate: %s\n" "\tsource: <%u> '%s'\n" + "\tlatency: <%0.0f usec>\n" "\tsample spec: <%s>\n" "\tchannel map: <%s>\n" "\tresample method: %s\n", o->index, o->name, o->driver, - state_table[o->state], + o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "", + o->flags & PA_SOURCE_OUTPUT_DONT_MOVE ? "DONT_MOVE " : "", + state_table[pa_source_output_get_state(o)], o->source->index, o->source->name, + (double) pa_source_output_get_latency(o), pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map), pa_resample_method_to_string(pa_source_output_get_resample_method(o))); @@ -227,30 +266,32 @@ char *pa_sink_input_list_to_string(pa_core *c) { pa_sink_input *i; uint32_t idx = PA_IDXSET_INVALID; static const char* const state_table[] = { - "RUNNING", - "CORKED", - "DISCONNECTED" + [PA_SINK_INPUT_RUNNING] = "RUNNING", + [PA_SINK_INPUT_DRAINED] = "DRAINED", + [PA_SINK_INPUT_CORKED] = "CORKED", + [PA_SINK_INPUT_UNLINKED] = "UNLINKED" }; - assert(c); + pa_assert(c); s = pa_strbuf_new(); - assert(s); pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs)); for (i = pa_idxset_first(c->sink_inputs, &idx); i; i = pa_idxset_next(c->sink_inputs, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; - assert(i->sink); + pa_assert(i->sink); pa_strbuf_printf( s, " index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" + "\tflags: %s%s\n" "\tstate: %s\n" "\tsink: <%u> '%s'\n" "\tvolume: <%s>\n" + "\tmute: <%i>\n" "\tlatency: <%0.0f usec>\n" "\tsample spec: <%s>\n" "\tchannel map: <%s>\n" @@ -258,16 +299,19 @@ char *pa_sink_input_list_to_string(pa_core *c) { i->index, i->name, i->driver, - state_table[i->state], + i->flags & PA_SINK_INPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "", + i->flags & PA_SINK_INPUT_DONT_MOVE ? "DONT_MOVE " : "", + state_table[pa_sink_input_get_state(i)], i->sink->index, i->sink->name, pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)), + !!pa_sink_input_get_mute(i), (double) pa_sink_input_get_latency(i), pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), pa_resample_method_to_string(pa_sink_input_get_resample_method(i))); if (i->module) - pa_strbuf_printf(s, "\towner module: <%u>\n", i->module->index); + pa_strbuf_printf(s, "\tmodule: <%u>\n", i->module->index); if (i->client) pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", i->client->index, i->client->name); } @@ -277,10 +321,9 @@ char *pa_sink_input_list_to_string(pa_core *c) { char *pa_scache_list_to_string(pa_core *c) { pa_strbuf *s; - assert(c); + pa_assert(c); s = pa_strbuf_new(); - assert(s); pa_strbuf_printf(s, "%u cache entries available.\n", c->scache ? pa_idxset_size(c->scache) : 0); @@ -326,10 +369,9 @@ char *pa_scache_list_to_string(pa_core *c) { char *pa_autoload_list_to_string(pa_core *c) { pa_strbuf *s; - assert(c); + pa_assert(c); s = pa_strbuf_new(); - assert(s); pa_strbuf_printf(s, "%u autoload entries available.\n", c->autoload_hashmap ? pa_hashmap_size(c->autoload_hashmap) : 0); diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c index ee05d7f95..3f3c9cde7 100644 --- a/src/pulsecore/cli.c +++ b/src/pulsecore/cli.c @@ -27,7 +27,6 @@ #include #include -#include #include #include @@ -45,6 +44,7 @@ #include #include #include +#include #include "cli.h" @@ -68,19 +68,17 @@ static void client_kill(pa_client *c); pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) { char cname[256]; pa_cli *c; - assert(io); + pa_assert(io); - c = pa_xmalloc(sizeof(pa_cli)); + c = pa_xnew(pa_cli, 1); c->core = core; - c->line = pa_ioline_new(io); - assert(c->line); + pa_assert_se(c->line = pa_ioline_new(io)); c->userdata = NULL; c->eof_callback = NULL; pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); - c->client = pa_client_new(core, __FILE__, cname); - assert(c->client); + pa_assert_se(c->client = pa_client_new(core, __FILE__, cname)); c->client->kill = client_kill; c->client->userdata = c; c->client->owner = m; @@ -94,7 +92,8 @@ pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) { } void pa_cli_free(pa_cli *c) { - assert(c); + pa_assert(c); + pa_ioline_close(c->line); pa_ioline_unref(c->line); pa_client_free(c->client); @@ -103,8 +102,9 @@ void pa_cli_free(pa_cli *c) { static void client_kill(pa_client *client) { pa_cli *c; - assert(client && client->userdata); - c = client->userdata; + + pa_assert(client); + pa_assert_se(c = client->userdata); pa_log_debug("CLI client killed."); if (c->defer_kill) @@ -119,7 +119,9 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { pa_strbuf *buf; pa_cli *c = userdata; char *p; - assert(line && c); + + pa_assert(line); + pa_assert(c); if (!s) { pa_log_debug("CLI got EOF from user."); @@ -129,8 +131,7 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { return; } - buf = pa_strbuf_new(); - assert(buf); + pa_assert_se(buf = pa_strbuf_new()); c->defer_kill++; pa_cli_command_execute_line(c->core, s, buf, &c->fail); c->defer_kill--; @@ -145,7 +146,8 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) { } void pa_cli_set_eof_callback(pa_cli *c, void (*cb)(pa_cli*c, void *userdata), void *userdata) { - assert(c); + pa_assert(c); + c->eof_callback = cb; c->userdata = userdata; } diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c index 0d792bb45..319b8387d 100644 --- a/src/pulsecore/client.c +++ b/src/pulsecore/client.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include @@ -35,15 +34,16 @@ #include #include +#include #include "client.h" pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) { pa_client *c; - int r; - assert(core); - c = pa_xmalloc(sizeof(pa_client)); + pa_core_assert_ref(core); + + c = pa_xnew(pa_client, 1); c->name = pa_xstrdup(name); c->driver = pa_xstrdup(driver); c->owner = NULL; @@ -52,10 +52,9 @@ pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) { c->kill = NULL; c->userdata = NULL; - r = pa_idxset_put(core->clients, c, &c->index); - assert(c->index != PA_IDXSET_INVALID && r >= 0); + pa_assert_se(pa_idxset_put(core->clients, c, &c->index) >= 0); - pa_log_info("created %u \"%s\"", c->index, c->name); + pa_log_info("Created %u \"%s\"", c->index, c->name); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); pa_core_check_quit(core); @@ -64,13 +63,14 @@ pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) { } void pa_client_free(pa_client *c) { - assert(c && c->core); + pa_assert(c); + pa_assert(c->core); pa_idxset_remove_by_data(c->core->clients, c, NULL); pa_core_check_quit(c->core); - pa_log_info("freed %u \"%s\"", c->index, c->name); + pa_log_info("Freed %u \"%s\"", c->index, c->name); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_xfree(c->name); pa_xfree(c->driver); @@ -78,7 +78,8 @@ void pa_client_free(pa_client *c) { } void pa_client_kill(pa_client *c) { - assert(c); + pa_assert(c); + if (!c->kill) { pa_log_warn("kill() operation not implemented for client %u", c->index); return; @@ -88,9 +89,9 @@ void pa_client_kill(pa_client *c) { } void pa_client_set_name(pa_client *c, const char *name) { - assert(c); + pa_assert(c); - pa_log_info("client %u changed name from \"%s\" to \"%s\"", c->index, c->name, name); + pa_log_info("Client %u changed name from \"%s\" to \"%s\"", c->index, c->name, name); pa_xfree(c->name); c->name = pa_xstrdup(name); diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index 12efbd2c4..0e0ba95a9 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -25,7 +25,6 @@ #include #endif -#include #include #include #include @@ -35,6 +34,7 @@ #include #include #include +#include #include "conf-parser.h" @@ -43,7 +43,10 @@ /* Run the user supplied parser for an assignment */ static int next_assignment(const char *filename, unsigned line, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) { - assert(filename && t && lvalue && rvalue); + pa_assert(filename); + pa_assert(t); + pa_assert(lvalue); + pa_assert(rvalue); for (; t->parse; t++) if (!strcmp(lvalue, t->lvalue)) @@ -56,7 +59,7 @@ static int next_assignment(const char *filename, unsigned line, const pa_config_ /* Returns non-zero when c is contained in s */ static int in_string(char c, const char *s) { - assert(s); + pa_assert(s); for (; *s; s++) if (*s == c) @@ -107,7 +110,9 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void int r = -1; unsigned line = 0; int do_close = !f; - assert(filename && t); + + pa_assert(filename); + pa_assert(t); if (!f && !(f = fopen(filename, "r"))) { if (errno == ENOENT) { @@ -115,7 +120,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void goto finish; } - pa_log_warn("WARNING: failed to open configuration file '%s': %s", + pa_log_warn("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } @@ -126,7 +131,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void if (feof(f)) break; - pa_log_warn("WARNING: failed to read configuration file '%s': %s", + pa_log_warn("Failed to read configuration file '%s': %s", filename, pa_cstrerror(errno)); goto finish; } @@ -148,7 +153,11 @@ finish: int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { int *i = data; int32_t k; - assert(filename && lvalue && rvalue && data); + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); if (pa_atoi(rvalue, &k) < 0) { pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); @@ -161,7 +170,11 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { int *b = data, k; - assert(filename && lvalue && rvalue && data); + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); if ((k = pa_parse_boolean(rvalue)) < 0) { pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue); @@ -175,7 +188,11 @@ int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue int pa_config_parse_string(const char *filename, PA_GCC_UNUSED unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { char **s = data; - assert(filename && lvalue && rvalue && data); + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); pa_xfree(*s); *s = *rvalue ? pa_xstrdup(rvalue) : NULL; diff --git a/src/pulsecore/core-def.h b/src/pulsecore/core-def.h index 10a3be428..4bc051375 100644 --- a/src/pulsecore/core-def.h +++ b/src/pulsecore/core-def.h @@ -24,9 +24,6 @@ USA. ***/ -typedef enum pa_mixer { - PA_MIXER_SOFTWARE, - PA_MIXER_HARDWARE -} pa_mixer_t; +/* FIXME: Remove this shit */ #endif diff --git a/src/pulsecore/core-error.c b/src/pulsecore/core-error.c index 044bea124..8a61e7264 100644 --- a/src/pulsecore/core-error.c +++ b/src/pulsecore/core-error.c @@ -31,178 +31,50 @@ #include #include -#ifdef HAVE_PTHREAD -#include -#endif - -#ifdef HAVE_WINDOWS_H -#include -#endif - #include #include #include #include +#include +#include +#include #include "core-error.h" -#ifdef HAVE_PTHREAD - -static pthread_once_t cstrerror_once = PTHREAD_ONCE_INIT; -static pthread_key_t tlsstr_key; - -static void inittls(void) { - int ret; - - ret = pthread_key_create(&tlsstr_key, pa_xfree); - if (ret) { - fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", errno); - exit(-1); - } -} - -#elif HAVE_WINDOWS_H - -static DWORD tlsstr_key = TLS_OUT_OF_INDEXES; -static DWORD monitor_key = TLS_OUT_OF_INDEXES; - -static void inittls(void) { - HANDLE mutex; - char name[64]; - - sprintf(name, "pulse%d", (int)GetCurrentProcessId()); - - mutex = CreateMutex(NULL, FALSE, name); - if (!mutex) { - fprintf(stderr, __FILE__ ": CRITICAL: Unable to create named mutex (%d)\n", (int)GetLastError()); - exit(-1); - } - - WaitForSingleObject(mutex, INFINITE); - - if (tlsstr_key == TLS_OUT_OF_INDEXES) { - tlsstr_key = TlsAlloc(); - monitor_key = TlsAlloc(); - if ((tlsstr_key == TLS_OUT_OF_INDEXES) || (monitor_key == TLS_OUT_OF_INDEXES)) { - fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", (int)GetLastError()); - exit(-1); - } - } - - ReleaseMutex(mutex); - - CloseHandle(mutex); -} - -/* - * This is incredibly brain dead, but this is necessary when dealing with - * the hell that is Win32. - */ -struct monitor_data { - HANDLE thread; - void *data; -}; - -static DWORD WINAPI monitor_thread(LPVOID param) { - struct monitor_data *data; - - data = (struct monitor_data*)param; - assert(data); - - WaitForSingleObject(data->thread, INFINITE); - - CloseHandle(data->thread); - pa_xfree(data->data); - pa_xfree(data); - - return 0; -} - -static void start_monitor(void) { - HANDLE thread; - struct monitor_data *data; - - data = pa_xnew(struct monitor_data, 1); - assert(data); - - DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &data->thread, 0, FALSE, DUPLICATE_SAME_ACCESS); - - thread = CreateThread(NULL, 0, monitor_thread, data, 0, NULL); - assert(thread); - - TlsSetValue(monitor_key, data); - - CloseHandle(thread); -} - -#else - -/* Unsafe, but we have no choice */ -static char *tlsstr; - -#endif +PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree); const char* pa_cstrerror(int errnum) { - const char *origbuf; - -#ifdef HAVE_STRERROR_R + const char *original = NULL; + char *translated, *t; char errbuf[128]; -#endif -#ifdef HAVE_PTHREAD - char *tlsstr; + if ((t = PA_STATIC_TLS_GET(cstrerror))) + pa_xfree(t); - pthread_once(&cstrerror_once, inittls); - - tlsstr = pthread_getspecific(tlsstr_key); -#elif defined(HAVE_WINDOWS_H) - char *tlsstr; - struct monitor_data *data; - - inittls(); - - tlsstr = TlsGetValue(tlsstr_key); - if (!tlsstr) - start_monitor(); - data = TlsGetValue(monitor_key); -#endif - - if (tlsstr) - pa_xfree(tlsstr); - -#ifdef HAVE_STRERROR_R - -#ifdef __GLIBC__ - origbuf = strerror_r(errnum, errbuf, sizeof(errbuf)); - if (origbuf == NULL) - origbuf = ""; -#else +#if defined(HAVE_STRERROR_R) && defined(__GLIBC__) + original = strerror_r(errnum, errbuf, sizeof(errbuf)); +#elif defined(HAVE_STRERROR_R) if (strerror_r(errnum, errbuf, sizeof(errbuf)) == 0) { - origbuf = errbuf; - errbuf[sizeof(errbuf) - 1] = '\0'; - } else - origbuf = ""; -#endif - + errbuf[sizeof(errbuf) - 1] = 0; + original = errbuf; + } #else /* This might not be thread safe, but we hope for the best */ - origbuf = strerror(errnum); + original = strerror(errnum); #endif - tlsstr = pa_locale_to_utf8(origbuf); - if (!tlsstr) { - fprintf(stderr, "Unable to convert, filtering\n"); - tlsstr = pa_utf8_filter(origbuf); + if (!original) { + pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum); + original = errbuf; } -#ifdef HAVE_PTHREAD - pthread_setspecific(tlsstr_key, tlsstr); -#elif defined(HAVE_WINDOWS_H) - TlsSetValue(tlsstr_key, tlsstr); - data->data = tlsstr; -#endif + if (!(translated = pa_locale_to_utf8(original))) { + pa_log_warn("Unable to convert error string to locale, filtering."); + translated = pa_utf8_filter(original); + } - return tlsstr; + PA_STATIC_TLS_SET(cstrerror, translated); + + return translated; } diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c index cb2727845..732d90dd2 100644 --- a/src/pulsecore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -26,7 +26,6 @@ #include #endif -#include #include #include #include @@ -60,6 +59,7 @@ #include #include #include +#include #include "core-scache.h" @@ -68,7 +68,10 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { pa_core *c = userdata; struct timeval ntv; - assert(c && c->mainloop == m && c->scache_auto_unload_event == e); + + pa_assert(c); + pa_assert(c->mainloop == m); + pa_assert(c->scache_auto_unload_event == e); pa_scache_unload_unused(c); @@ -78,7 +81,8 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED } static void free_entry(pa_scache_entry *e) { - assert(e); + pa_assert(e); + pa_namereg_unregister(e->core, e->name); pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_REMOVE, e->index); pa_xfree(e->name); @@ -90,7 +94,9 @@ static void free_entry(pa_scache_entry *e) { static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { pa_scache_entry *e; - assert(c && name); + + pa_assert(c); + pa_assert(name); if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) { if (e->memchunk.memblock) @@ -98,11 +104,11 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { pa_xfree(e->filename); - assert(e->core == c); + pa_assert(e->core == c); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); } else { - e = pa_xmalloc(sizeof(pa_scache_entry)); + e = pa_xnew(pa_scache_entry, 1); if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, 1)) { pa_xfree(e); @@ -114,7 +120,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { if (!c->scache) { c->scache = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); - assert(c->scache); + pa_assert(c->scache); } pa_idxset_put(c->scache, e, &e->index); @@ -139,7 +145,9 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_memchunk *chunk, uint32_t *idx) { pa_scache_entry *e; char st[PA_SAMPLE_SPEC_SNPRINT_MAX]; - assert(c && name); + + pa_assert(c); + pa_assert(name); if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX) return -1; @@ -164,9 +172,9 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c if (idx) *idx = e->index; - pa_log_debug("created sample \"%s\" (#%d), %d bytes with sample spec %s", - name, e->index, e->memchunk.length, - pa_sample_spec_snprint(st, sizeof(st), &e->sample_spec)); + pa_log_debug("Created sample \"%s\" (#%d), %lu bytes with sample spec %s", + name, e->index, (unsigned long) e->memchunk.length, + pa_sample_spec_snprint(st, sizeof(st), &e->sample_spec)); return 0; } @@ -184,6 +192,10 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3 filename = buf; #endif + pa_assert(c); + pa_assert(name); + pa_assert(filename); + if (pa_sound_file_load(c->mempool, filename, &ss, &map, &chunk) < 0) return -1; @@ -203,7 +215,9 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, filename = buf; #endif - assert(c && name); + pa_assert(c); + pa_assert(name); + pa_assert(filename); if (!(e = scache_add_item(c, name))) return -1; @@ -226,15 +240,17 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, int pa_scache_remove_item(pa_core *c, const char *name) { pa_scache_entry *e; - assert(c && name); + + pa_assert(c); + pa_assert(name); if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) return -1; if (pa_idxset_remove_by_data(c->scache, e, NULL) != e) - assert(0); + pa_assert(0); - pa_log_debug("removed sample \"%s\"", name); + pa_log_debug("Removed sample \"%s\"", name); free_entry(e); @@ -243,12 +259,13 @@ int pa_scache_remove_item(pa_core *c, const char *name) { static void free_cb(void *p, PA_GCC_UNUSED void *userdata) { pa_scache_entry *e = p; - assert(e); + pa_assert(e); + free_entry(e); } void pa_scache_free(pa_core *c) { - assert(c); + pa_assert(c); if (c->scache) { pa_idxset_free(c->scache, free_cb, NULL); @@ -264,9 +281,9 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t char *t; pa_cvolume r; - assert(c); - assert(name); - assert(sink); + pa_assert(c); + pa_assert(name); + pa_assert(sink); if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) return -1; @@ -284,7 +301,7 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t if (!e->memchunk.memblock) return -1; - pa_log_debug("playing sample \"%s\" on \"%s\"", name, sink->name); + pa_log_debug("Playing sample \"%s\" on \"%s\"", name, sink->name); t = pa_sprintf_malloc("sample:%s", name); @@ -304,9 +321,23 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t return 0; } +int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_name, pa_volume_t volume, int autoload) { + pa_sink *sink; + + pa_assert(c); + pa_assert(name); + + if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, autoload))) + return -1; + + return pa_scache_play_item(c, name, sink, volume); +} + const char * pa_scache_get_name_by_id(pa_core *c, uint32_t id) { pa_scache_entry *e; - assert(c && id != PA_IDXSET_INVALID); + + pa_assert(c); + pa_assert(id != PA_IDXSET_INVALID); if (!c->scache || !(e = pa_idxset_get_by_index(c->scache, id))) return NULL; @@ -316,7 +347,9 @@ const char * pa_scache_get_name_by_id(pa_core *c, uint32_t id) { uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) { pa_scache_entry *e; - assert(c && name); + + pa_assert(c); + pa_assert(name); if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) return PA_IDXSET_INVALID; @@ -327,7 +360,8 @@ uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) { uint32_t pa_scache_total_size(pa_core *c) { pa_scache_entry *e; uint32_t idx, sum = 0; - assert(c); + + pa_assert(c); if (!c->scache || !pa_idxset_size(c->scache)) return 0; @@ -343,7 +377,8 @@ void pa_scache_unload_unused(pa_core *c) { pa_scache_entry *e; time_t now; uint32_t idx; - assert(c); + + pa_assert(c); if (!c->scache || !pa_idxset_size(c->scache)) return; @@ -370,6 +405,9 @@ static void add_file(pa_core *c, const char *pathname) { struct stat st; const char *e; + pa_core_assert_ref(c); + pa_assert(pathname); + e = pa_path_get_filename(pathname); if (stat(pathname, &st) < 0) { @@ -385,7 +423,9 @@ static void add_file(pa_core *c, const char *pathname) { int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) { DIR *dir; - assert(c && pathname); + + pa_core_assert_ref(c); + pa_assert(pathname); /* First try to open this as directory */ if (!(dir = opendir(pathname))) { @@ -415,7 +455,7 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) { if (e->d_name[0] == '.') continue; - snprintf(p, sizeof(p), "%s/%s", pathname, e->d_name); + pa_snprintf(p, sizeof(p), "%s/%s", pathname, e->d_name); add_file(c, p); } } diff --git a/src/pulsecore/core-scache.h b/src/pulsecore/core-scache.h index bbf13f156..ab7ec0ef3 100644 --- a/src/pulsecore/core-scache.h +++ b/src/pulsecore/core-scache.h @@ -55,6 +55,7 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname); int pa_scache_remove_item(pa_core *c, const char *name); int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume); +int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_name, pa_volume_t volume, int autoload); void pa_scache_free(pa_core *c); const char *pa_scache_get_name_by_id(pa_core *c, uint32_t id); diff --git a/src/pulsecore/core-subscribe.c b/src/pulsecore/core-subscribe.c index 6608d57a4..06c5a4ad3 100644 --- a/src/pulsecore/core-subscribe.c +++ b/src/pulsecore/core-subscribe.c @@ -26,12 +26,12 @@ #endif #include -#include #include #include #include +#include #include "core-subscribe.h" @@ -68,9 +68,9 @@ static void sched_event(pa_core *c); pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_subscription_cb_t callback, void *userdata) { pa_subscription *s; - assert(c); - assert(m); - assert(callback); + pa_assert(c); + pa_assert(m); + pa_assert(callback); s = pa_xnew(pa_subscription, 1); s->core = c; @@ -85,24 +85,24 @@ pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_su /* Free a subscription object, effectively marking it for deletion */ void pa_subscription_free(pa_subscription*s) { - assert(s); - assert(!s->dead); + pa_assert(s); + pa_assert(!s->dead); s->dead = 1; sched_event(s->core); } static void free_subscription(pa_subscription *s) { - assert(s); - assert(s->core); + pa_assert(s); + pa_assert(s->core); PA_LLIST_REMOVE(pa_subscription, s->core->subscriptions, s); pa_xfree(s); } static void free_event(pa_subscription_event *s) { - assert(s); - assert(s->core); + pa_assert(s); + pa_assert(s->core); if (!s->next) s->core->subscription_event_last = s->prev; @@ -113,7 +113,7 @@ static void free_event(pa_subscription_event *s) { /* Free all subscription objects */ void pa_subscription_free_all(pa_core *c) { - assert(c); + pa_assert(c); while (c->subscriptions) free_subscription(c->subscriptions); @@ -160,9 +160,9 @@ static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) { pa_core *c = userdata; pa_subscription *s; - assert(c->mainloop == m); - assert(c); - assert(c->subscription_defer_event == de); + pa_assert(c->mainloop == m); + pa_assert(c); + pa_assert(c->subscription_defer_event == de); c->mainloop->defer_enable(c->subscription_defer_event, 0); @@ -196,20 +196,20 @@ static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) { /* Schedule an mainloop event so that a pending subscription event is dispatched */ static void sched_event(pa_core *c) { - assert(c); + pa_assert(c); if (!c->subscription_defer_event) { c->subscription_defer_event = c->mainloop->defer_new(c->mainloop, defer_cb, c); - assert(c->subscription_defer_event); + pa_assert(c->subscription_defer_event); } c->mainloop->defer_enable(c->subscription_defer_event, 1); } /* Append a new subscription event to the subscription event queue and schedule a main loop event */ -void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t index) { +void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t idx) { pa_subscription_event *e; - assert(c); + pa_assert(c); /* No need for queuing subscriptions of noone is listening */ if (!c->subscriptions) @@ -227,7 +227,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i continue; /* not the same object */ - if (i->index != index) + if (i->index != idx) continue; if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { @@ -253,7 +253,7 @@ void pa_subscription_post(pa_core *c, pa_subscription_event_type_t t, uint32_t i e = pa_xnew(pa_subscription_event, 1); e->core = c; e->type = t; - e->index = index; + e->index = idx; PA_LLIST_INSERT_AFTER(pa_subscription_event, c->subscription_event_queue, c->subscription_event_last, e); c->subscription_event_last = e; diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index e5766b2fa..a644b6642 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +42,10 @@ #include #include +#ifdef HAVE_STRTOF_L +#include +#endif + #ifdef HAVE_SCHED_H #include #endif @@ -55,6 +58,10 @@ #include #endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif + #ifdef HAVE_PTHREAD #include #endif @@ -75,14 +82,19 @@ #include #endif +#ifdef HAVE_LIBSAMPLERATE #include +#endif #include #include +#include #include #include #include +#include +#include #include "core-util.h" @@ -93,10 +105,8 @@ #ifndef OS_IS_WIN32 #define PA_USER_RUNTIME_PATH_PREFIX "/tmp/pulse-" -#define PATH_SEP '/' #else #define PA_USER_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-" -#define PATH_SEP '\\' #endif #ifdef OS_IS_WIN32 @@ -111,7 +121,7 @@ int pa_set_root(HANDLE handle) { if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH)) return 0; - sep = strrchr(library_path, '\\'); + sep = strrchr(library_path, PA_PATH_SEP_CHAR); if (sep) *sep = '\0'; @@ -124,23 +134,42 @@ int pa_set_root(HANDLE handle) { #endif /** Make a file descriptor nonblock. Doesn't do any error checking */ -void pa_make_nonblock_fd(int fd) { +void pa_make_fd_nonblock(int fd) { + #ifdef O_NONBLOCK int v; - assert(fd >= 0); + pa_assert(fd >= 0); + + pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0); + + if (!(v & O_NONBLOCK)) + pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0); - if ((v = fcntl(fd, F_GETFL)) >= 0) - if (!(v & O_NONBLOCK)) - fcntl(fd, F_SETFL, v|O_NONBLOCK); #elif defined(OS_IS_WIN32) u_long arg = 1; if (ioctlsocket(fd, FIONBIO, &arg) < 0) { - if (WSAGetLastError() == WSAENOTSOCK) - pa_log_warn("WARNING: Only sockets can be made non-blocking!"); + pa_assert_se(WSAGetLastError() == WSAENOTSOCK); + pa_log_warn("Only sockets can be made non-blocking!"); } #else - pa_log_warn("WARNING: Non-blocking I/O not supported.!"); + pa_log_warn("Non-blocking I/O not supported.!"); #endif + +} + +/* Set the FD_CLOEXEC flag for a fd */ +void pa_make_fd_cloexec(int fd) { + +#ifdef FD_CLOEXEC + int v; + pa_assert(fd >= 0); + + pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0); + + if (!(v & FD_CLOEXEC)) + pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0); +#endif + } /** Creates a directory securely */ @@ -148,7 +177,7 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { struct stat st; int r; - assert(dir); + pa_assert(dir); #ifdef OS_IS_WIN32 r = mkdir(dir); @@ -169,7 +198,7 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) { uid = getuid(); if (gid == (gid_t)-1) gid = getgid(); - chown(dir, uid, gid); + (void) chown(dir, uid, gid); #endif #ifdef HAVE_CHMOD @@ -295,9 +324,9 @@ ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) { ssize_t ret = 0; int _type; - assert(fd >= 0); - assert(data); - assert(size); + pa_assert(fd >= 0); + pa_assert(data); + pa_assert(size); if (!type) { _type = 0; @@ -326,9 +355,9 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) { ssize_t ret = 0; int _type; - assert(fd >= 0); - assert(data); - assert(size); + pa_assert(fd >= 0); + pa_assert(data); + pa_assert(size); if (!type) { _type = 0; @@ -354,13 +383,12 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) { /** Platform independent read function. Necessary since not all * systems treat all file descriptors equal. */ -int pa_close(int fd) -{ +int pa_close(int fd) { + #ifdef OS_IS_WIN32 int ret; - ret = closesocket(fd); - if (ret == 0) + if ((ret = closesocket(fd)) == 0) return 0; if (WSAGetLastError() != WSAENOTSOCK) { @@ -407,9 +435,9 @@ void pa_check_signal_is_blocked(int sig) { if (sa.sa_handler != SIG_DFL) return; - pa_log("WARNING: %s is not trapped. This might cause malfunction!", pa_strsignal(sig)); + pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig)); #else /* HAVE_SIGACTION */ - pa_log("WARNING: %s might not be trapped. This might cause malfunction!", pa_strsignal(sig)); + pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig)); #endif } @@ -419,7 +447,7 @@ char *pa_sprintf_malloc(const char *format, ...) { int size = 100; char *c = NULL; - assert(format); + pa_assert(format); for(;;) { int r; @@ -431,6 +459,8 @@ char *pa_sprintf_malloc(const char *format, ...) { r = vsnprintf(c, size, format, ap); va_end(ap); + c[size-1] = 0; + if (r > -1 && r < size) return c; @@ -447,19 +477,20 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) { int size = 100; char *c = NULL; - assert(format); + pa_assert(format); for(;;) { int r; va_list aq; - va_copy(aq, ap); - c = pa_xrealloc(c, size); - r = vsnprintf(c, size, format, aq); + va_copy(aq, ap); + r = vsnprintf(c, size, format, aq); va_end(aq); + c[size-1] = 0; + if (r > -1 && r < size) return c; @@ -472,35 +503,46 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) { /* Similar to OpenBSD's strlcpy() function */ char *pa_strlcpy(char *b, const char *s, size_t l) { - assert(b && s && l > 0); + pa_assert(b); + pa_assert(s); + pa_assert(l > 0); strncpy(b, s, l); b[l-1] = 0; return b; } -#define NICE_LEVEL (-15) +/* Make the current thread a realtime thread*/ +void pa_make_realtime(void) { + +#ifdef _POSIX_PRIORITY_SCHEDULING + struct sched_param sp; + int r, policy; + + memset(&sp, 0, sizeof(sp)); + policy = 0; + + if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) { + pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r)); + return; + } + + sp.sched_priority = 1; + if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) != 0) { + pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r)); + return; + } + + pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread."); +#endif + +} + +#define NICE_LEVEL (-11) /* Raise the priority of the current process as much as possible and -sensible: set the nice level to -15 and enable realtime scheduling if -supported.*/ +sensible: set the nice level to -15.*/ void pa_raise_priority(void) { -#if defined(HAVE_SYS_CAPABILITY_H) - cap_t caps; - - /* Temporarily acquire CAP_SYS_NICE in the effective set */ - if ((caps = cap_get_proc())) { - cap_t caps_new; - cap_value_t nice_cap = CAP_SYS_NICE; - - if ((caps_new = cap_dup(caps))) { - cap_set_flag(caps_new, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET); - cap_set_flag(caps_new, CAP_PERMITTED, 1, &nice_cap, CAP_SET); - cap_set_proc(caps_new); - cap_free(caps_new); - } - } -#endif #ifdef HAVE_SYS_RESOURCE_H if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) @@ -509,86 +551,26 @@ void pa_raise_priority(void) { pa_log_info("Successfully gained nice level %i.", NICE_LEVEL); #endif -#ifdef _POSIX_PRIORITY_SCHEDULING - { - struct sched_param sp; - - if (sched_getparam(0, &sp) < 0) { - pa_log("sched_getparam(): %s", pa_cstrerror(errno)); - goto fail; - } - - sp.sched_priority = 1; - if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) { - pa_log_warn("sched_setscheduler(): %s", pa_cstrerror(errno)); - goto fail; - } - - pa_log_info("Successfully enabled SCHED_FIFO scheduling."); - } -#endif - #ifdef OS_IS_WIN32 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError()); else pa_log_info("Successfully gained high priority class."); #endif - -fail: - -#if defined(HAVE_SYS_CAPABILITY_H) - if (caps) { - /* Restore original caps */ - cap_set_proc(caps); - cap_free(caps); - } -#endif - - ; /* We put this here to get the code to compile when - * HAVE_SYS_CAPABILITY_H is not defined. Don't remove unless you - * know what you do */ } -/* Reset the priority to normal, inverting the changes made by pa_raise_priority() */ +/* Reset the priority to normal, inverting the changes made by + * pa_raise_priority() */ void pa_reset_priority(void) { #ifdef OS_IS_WIN32 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); #endif -#ifdef _POSIX_PRIORITY_SCHEDULING - { - struct sched_param sp; - sched_getparam(0, &sp); - sp.sched_priority = 0; - sched_setscheduler(0, SCHED_OTHER, &sp); - } -#endif - #ifdef HAVE_SYS_RESOURCE_H setpriority(PRIO_PROCESS, 0, 0); #endif } -/* Set the FD_CLOEXEC flag for a fd */ -int pa_fd_set_cloexec(int fd, int b) { - -#ifdef FD_CLOEXEC - int v; - assert(fd >= 0); - - if ((v = fcntl(fd, F_GETFD, 0)) < 0) - return -1; - - v = (v & ~FD_CLOEXEC) | (b ? FD_CLOEXEC : 0); - - if (fcntl(fd, F_SETFD, v) < 0) - return -1; -#endif - - return 0; -} - /* Try to parse a boolean string value.*/ int pa_parse_boolean(const char *v) { @@ -639,31 +621,134 @@ char *pa_split_spaces(const char *c, const char **state) { return pa_xstrndup(current, l); } -/* Return the name of an UNIX signal. Similar to GNU's strsignal() */ -const char *pa_strsignal(int sig) { +PA_STATIC_TLS_DECLARE(signame, pa_xfree); + +/* Return the name of an UNIX signal. Similar to Solaris sig2str() */ +const char *pa_sig2str(int sig) { + char *t; + + if (sig <= 0) + goto fail; + +#ifdef NSIG + if (sig >= NSIG) + goto fail; +#endif + +#ifdef HAVE_SIG2STR + { + char buf[SIG2STR_MAX]; + + if (sig2str(sig, buf) == 0) { + pa_xfree(PA_STATIC_TLS_GET(signame)); + t = pa_sprintf_malloc("SIG%s", buf); + PA_STATIC_TLS_SET(signame, t); + return t; + } + } +#else + switch(sig) { - case SIGINT: return "SIGINT"; - case SIGTERM: return "SIGTERM"; +#ifdef SIGHUP + case SIGHUP: return "SIGHUP"; +#endif + case SIGINT: return "SIGINT"; +#ifdef SIGQUIT + case SIGQUIT: return "SIGQUIT"; +#endif + case SIGILL: return "SIGULL"; +#ifdef SIGTRAP + case SIGTRAP: return "SIGTRAP"; +#endif + case SIGABRT: return "SIGABRT"; +#ifdef SIGBUS + case SIGBUS: return "SIGBUS"; +#endif + case SIGFPE: return "SIGFPE"; +#ifdef SIGKILL + case SIGKILL: return "SIGKILL"; +#endif #ifdef SIGUSR1 - case SIGUSR1: return "SIGUSR1"; + case SIGUSR1: return "SIGUSR1"; #endif + case SIGSEGV: return "SIGSEGV"; #ifdef SIGUSR2 - case SIGUSR2: return "SIGUSR2"; -#endif -#ifdef SIGXCPU - case SIGXCPU: return "SIGXCPU"; + case SIGUSR2: return "SIGUSR2"; #endif #ifdef SIGPIPE - case SIGPIPE: return "SIGPIPE"; + case SIGPIPE: return "SIGPIPE"; +#endif +#ifdef SIGALRM + case SIGALRM: return "SIGALRM"; +#endif + case SIGTERM: return "SIGTERM"; +#ifdef SIGSTKFLT + case SIGSTKFLT: return "SIGSTKFLT"; #endif #ifdef SIGCHLD - case SIGCHLD: return "SIGCHLD"; + case SIGCHLD: return "SIGCHLD"; #endif -#ifdef SIGHUP - case SIGHUP: return "SIGHUP"; +#ifdef SIGCONT + case SIGCONT: return "SIGCONT"; +#endif +#ifdef SIGSTOP + case SIGSTOP: return "SIGSTOP"; +#endif +#ifdef SIGTSTP + case SIGTSTP: return "SIGTSTP"; +#endif +#ifdef SIGTTIN + case SIGTTIN: return "SIGTTIN"; +#endif +#ifdef SIGTTOU + case SIGTTOU: return "SIGTTOU"; +#endif +#ifdef SIGURG + case SIGURG: return "SIGURG"; +#endif +#ifdef SIGXCPU + case SIGXCPU: return "SIGXCPU"; +#endif +#ifdef SIGXFSZ + case SIGXFSZ: return "SIGXFSZ"; +#endif +#ifdef SIGVTALRM + case SIGVTALRM: return "SIGVTALRM"; +#endif +#ifdef SIGPROF + case SIGPROF: return "SIGPROF"; +#endif +#ifdef SIGWINCH + case SIGWINCH: return "SIGWINCH"; +#endif +#ifdef SIGIO + case SIGIO: return "SIGIO"; +#endif +#ifdef SIGPWR + case SIGPWR: return "SIGPWR"; +#endif +#ifdef SIGSYS + case SIGSYS: return "SIGSYS"; #endif - default: return "UNKNOWN SIGNAL"; } + +#ifdef SIGRTMIN + if (sig >= SIGRTMIN && sig <= SIGRTMAX) { + pa_xfree(PA_STATIC_TLS_GET(signame)); + t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN); + PA_STATIC_TLS_SET(signame, t); + return t; + } +#endif + +#endif + +fail: + + pa_xfree(PA_STATIC_TLS_GET(signame)); + t = pa_sprintf_malloc("SIG%i", sig); + PA_STATIC_TLS_SET(signame, t); + return t; } #ifdef HAVE_GRP_H @@ -715,7 +800,7 @@ int pa_own_uid_in_group(const char *name, gid_t *gid) { int n = sysconf(_SC_NGROUPS_MAX); int r = -1, i; - assert(n > 0); + pa_assert(n > 0); gids = pa_xmalloc(sizeof(GETGROUPS_T)*n); @@ -861,8 +946,7 @@ int pa_lock_fd(int fd, int b) { return 0; } - pa_log("%slock: %s", !b? "un" : "", - pa_cstrerror(errno)); + pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno)); #endif #ifdef OS_IS_WIN32 @@ -881,7 +965,7 @@ int pa_lock_fd(int fd, int b) { /* Remove trailing newlines from a string */ char* pa_strip_nl(char *s) { - assert(s); + pa_assert(s); s[strcspn(s, "\r\n")] = 0; return s; @@ -890,38 +974,46 @@ char* pa_strip_nl(char *s) { /* Create a temporary lock file and lock it. */ int pa_lock_lockfile(const char *fn) { int fd = -1; - assert(fn); + pa_assert(fn); for (;;) { struct stat st; - if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { - pa_log("failed to create lock file '%s': %s", fn, - pa_cstrerror(errno)); + if ((fd = open(fn, O_CREAT|O_RDWR +#ifdef O_NOCTTY + |O_NOCTTY +#endif +#ifdef O_NOFOLLOW + |O_NOFOLLOW +#endif + , S_IRUSR|S_IWUSR)) < 0) { + pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } if (pa_lock_fd(fd, 1) < 0) { - pa_log("failed to lock file '%s'.", fn); + pa_log_warn("Failed to lock file '%s'.", fn); goto fail; } if (fstat(fd, &st) < 0) { - pa_log("failed to fstat() file '%s'.", fn); + pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } - /* Check wheter the file has been removed meanwhile. When yes, restart this loop, otherwise, we're done */ + /* Check wheter the file has been removed meanwhile. When yes, + * restart this loop, otherwise, we're done */ if (st.st_nlink >= 1) break; if (pa_lock_fd(fd, 0) < 0) { - pa_log("failed to unlock file '%s'.", fn); + pa_log_warn("Failed to unlock file '%s'.", fn); goto fail; } - if (close(fd) < 0) { - pa_log("failed to close file '%s'.", fn); + if (pa_close(fd) < 0) { + pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno)); + fd = -1; goto fail; } @@ -933,7 +1025,7 @@ int pa_lock_lockfile(const char *fn) { fail: if (fd >= 0) - close(fd); + pa_close(fd); return -1; } @@ -941,22 +1033,21 @@ fail: /* Unlock a temporary lcok file */ int pa_unlock_lockfile(const char *fn, int fd) { int r = 0; - assert(fn && fd >= 0); + pa_assert(fn); + pa_assert(fd >= 0); if (unlink(fn) < 0) { - pa_log_warn("WARNING: unable to remove lock file '%s': %s", - fn, pa_cstrerror(errno)); + pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno)); r = -1; } if (pa_lock_fd(fd, 0) < 0) { - pa_log_warn("WARNING: failed to unlock file '%s'.", fn); + pa_log_warn("Failed to unlock file '%s'.", fn); r = -1; } - if (close(fd) < 0) { - pa_log_warn("WARNING: failed to close lock file '%s': %s", - fn, pa_cstrerror(errno)); + if (pa_close(fd) < 0) { + pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno)); r = -1; } @@ -1019,10 +1110,8 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env return f; } - if (errno != ENOENT) { - pa_log_warn("WARNING: failed to open configuration file '%s': %s", - lfn, pa_cstrerror(errno)); - } + if (errno != ENOENT) + pa_log_warn("Failed to open configuration file '%s': %s", lfn, pa_cstrerror(errno)); pa_xfree(lfn); } @@ -1051,7 +1140,10 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) { size_t i = 0, j = 0; const char hex[] = "0123456789abcdef"; - assert(d && s && slength > 0); + + pa_assert(d); + pa_assert(s); + pa_assert(slength > 0); while (i < dlength && j+3 <= slength) { s[j++] = hex[*d >> 4]; @@ -1082,7 +1174,9 @@ static int hexc(char c) { /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) { size_t j = 0; - assert(p && d); + + pa_assert(p); + pa_assert(d); while (j < dlength && *p) { int b; @@ -1109,8 +1203,8 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) { int pa_startswith(const char *s, const char *pfx) { size_t l; - assert(s); - assert(pfx); + pa_assert(s); + pa_assert(pfx); l = strlen(pfx); @@ -1121,8 +1215,8 @@ int pa_startswith(const char *s, const char *pfx) { int pa_endswith(const char *s, const char *sfx) { size_t l1, l2; - assert(s); - assert(sfx); + pa_assert(s); + pa_assert(sfx); l1 = strlen(s); l2 = strlen(sfx); @@ -1146,17 +1240,17 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) { if ((e = getenv("PULSE_RUNTIME_PATH"))) { if (fn) - snprintf(s, l, "%s%c%s", e, PATH_SEP, fn); + pa_snprintf(s, l, "%s%c%s", e, PA_PATH_SEP_CHAR, fn); else - snprintf(s, l, "%s", e); + pa_snprintf(s, l, "%s", e); } else { char u[256]; if (fn) - snprintf(s, l, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn); + pa_snprintf(s, l, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PA_PATH_SEP_CHAR, fn); else - snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u))); + pa_snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u))); } @@ -1175,11 +1269,17 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) { int pa_atoi(const char *s, int32_t *ret_i) { char *x = NULL; long l; - assert(s && ret_i); + pa_assert(s); + pa_assert(ret_i); + + errno = 0; l = strtol(s, &x, 0); - if (!x || *x) + if (!x || *x || errno != 0) + return -1; + + if ((int32_t) l != l) return -1; *ret_i = (int32_t) l; @@ -1191,14 +1291,219 @@ int pa_atoi(const char *s, int32_t *ret_i) { int pa_atou(const char *s, uint32_t *ret_u) { char *x = NULL; unsigned long l; - assert(s && ret_u); + pa_assert(s); + pa_assert(ret_u); + + errno = 0; l = strtoul(s, &x, 0); - if (!x || *x) + if (!x || *x || errno != 0) + return -1; + + if ((uint32_t) l != l) return -1; *ret_u = (uint32_t) l; return 0; } + +#ifdef HAVE_STRTOF_L +static locale_t c_locale = NULL; + +static void c_locale_destroy(void) { + freelocale(c_locale); +} +#endif + +int pa_atof(const char *s, float *ret_f) { + char *x = NULL; + float f; + int r = 0; + + pa_assert(s); + pa_assert(ret_f); + + /* This should be locale independent */ + +#ifdef HAVE_STRTOF_L + + PA_ONCE_BEGIN { + + if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL))) + atexit(c_locale_destroy); + + } PA_ONCE_END; + + if (c_locale) { + errno = 0; + f = strtof_l(s, &x, c_locale); + } else +#endif + { + errno = 0; +#ifdef HAVE_STRTOF + f = strtof(s, &x); +#else + f = strtod(s, &x); +#endif + } + + if (!x || *x || errno != 0) + r = -1; + else + *ret_f = f; + + return r; +} + +/* Same as snprintf, but guarantees NUL-termination on every platform */ +int pa_snprintf(char *str, size_t size, const char *format, ...) { + int ret; + va_list ap; + + pa_assert(str); + pa_assert(size > 0); + pa_assert(format); + + va_start(ap, format); + ret = vsnprintf(str, size, format, ap); + va_end(ap); + + str[size-1] = 0; + + return ret; +} + +/* Truncate the specified string, but guarantee that the string + * returned still validates as UTF8 */ +char *pa_truncate_utf8(char *c, size_t l) { + pa_assert(c); + pa_assert(pa_utf8_valid(c)); + + if (strlen(c) <= l) + return c; + + c[l] = 0; + + while (l > 0 && !pa_utf8_valid(c)) + c[--l] = 0; + + return c; +} + +char *pa_getcwd(void) { + size_t l = 128; + + for (;;) { + char *p = pa_xnew(char, l); + if (getcwd(p, l)) + return p; + + if (errno != ERANGE) + return NULL; + + pa_xfree(p); + l *= 2; + } +} + +char *pa_make_path_absolute(const char *p) { + char *r; + char *cwd; + + pa_assert(p); + + if (p[0] == '/') + return pa_xstrdup(p); + + if (!(cwd = pa_getcwd())) + return pa_xstrdup(p); + + r = pa_sprintf_malloc("%s/%s", cwd, p); + pa_xfree(cwd); + return r; +} + +void *pa_will_need(const void *p, size_t l) { +#ifdef RLIMIT_MEMLOCK + struct rlimit rlim; +#endif + const void *a; + size_t size; + int r; + size_t bs; + + pa_assert(p); + pa_assert(l > 0); + + a = PA_PAGE_ALIGN_PTR(p); + size = (const uint8_t*) p + l - (const uint8_t*) a; + +#ifdef HAVE_POSIX_MADVISE + if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) { + pa_log_debug("posix_madvise() worked fine!"); + return (void*) p; + } +#endif + + /* Most likely the memory was not mmap()ed from a file and thus + * madvise() didn't work, so let's misuse mlock() do page this + * stuff back into RAM. Yeah, let's fuck with the MM! It's so + * inviting, the man page of mlock() tells us: "All pages that + * contain a part of the specified address range are guaranteed to + * be resident in RAM when the call returns successfully." */ + +#ifdef RLIMIT_MEMLOCK + pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0); + + if (rlim.rlim_cur < PA_PAGE_SIZE) { + pa_log_debug("posix_madvise() failed (or doesn't exist), resource limits don't allow mlock(), can't page in data: %s", pa_cstrerror(r)); + return (void*) p; + } + + bs = PA_PAGE_ALIGN(rlim.rlim_cur); +#else + bs = PA_PAGE_SIZE*4; +#endif + + pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r)); + +#ifdef HAVE_MLOCK + while (size > 0 && bs > 0) { + + if (bs > size) + bs = size; + + if (mlock(a, bs) < 0) { + bs = PA_PAGE_ALIGN(bs / 2); + continue; + } + + pa_assert_se(munlock(a, bs) == 0); + + a = (const uint8_t*) a + bs; + size -= bs; + } +#endif + + if (bs <= 0) + pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno)); + else + pa_log_debug("mlock() worked fine!"); + + return (void*) p; +} + +void pa_close_pipe(int fds[2]) { + pa_assert(fds); + + if (fds[0] >= 0) + pa_assert_se(pa_close(fds[0]) == 0); + + if (fds[1] >= 0) + pa_assert_se(pa_close(fds[1]) == 0); + + fds[0] = fds[1] = -1; +} diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 1d921e036..0fe865ec4 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -34,7 +34,8 @@ struct timeval; -void pa_make_nonblock_fd(int fd); +void pa_make_fd_nonblock(int fd); +void pa_make_fd_cloexec(int fd); int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid); int pa_make_secure_parent_dir(const char *fn, mode_t, uid_t uid, gid_t gid); @@ -55,19 +56,18 @@ char *pa_strlcpy(char *b, const char *s, size_t l); char *pa_parent_dir(const char *fn); +void pa_make_realtime(void); void pa_raise_priority(void); void pa_reset_priority(void); -int pa_fd_set_cloexec(int fd, int b); - -int pa_parse_boolean(const char *s); +int pa_parse_boolean(const char *s) PA_GCC_PURE; char *pa_split(const char *c, const char*delimiters, const char **state); char *pa_split_spaces(const char *c, const char **state); char *pa_strip_nl(char *s); -const char *pa_strsignal(int sig); +const char *pa_sig2str(int sig) PA_GCC_PURE; int pa_own_uid_in_group(const char *name, gid_t *gid); int pa_uid_in_group(uid_t uid, const char *name); @@ -84,12 +84,42 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength); size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength); -int pa_startswith(const char *s, const char *pfx); -int pa_endswith(const char *s, const char *sfx); +int pa_startswith(const char *s, const char *pfx) PA_GCC_PURE; +int pa_endswith(const char *s, const char *sfx) PA_GCC_PURE; char *pa_runtime_path(const char *fn, char *s, size_t l); int pa_atoi(const char *s, int32_t *ret_i); int pa_atou(const char *s, uint32_t *ret_u); +int pa_atof(const char *s, float *ret_f); + +int pa_snprintf(char *str, size_t size, const char *format, ...); + +char *pa_truncate_utf8(char *c, size_t l); + +char *pa_getcwd(void); +char *pa_make_path_absolute(const char *p); + +void *pa_will_need(const void *p, size_t l); + +static inline int pa_is_power_of_two(unsigned n) { + return !(n & (n - 1)); +} + +static inline unsigned pa_make_power_of_two(unsigned n) { + unsigned j = n; + + if (pa_is_power_of_two(n)) + return n; + + while (j) { + j = j >> 1; + n = n | j; + } + + return n + 1; +} + +void pa_close_pipe(int fds[2]); #endif diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 31b6c1881..e9008833d 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include @@ -45,12 +44,36 @@ #include #include #include +#include #include "core.h" +static PA_DEFINE_CHECK_TYPE(pa_core, pa_msgobject); + +static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { + pa_core *c = PA_CORE(o); + + pa_core_assert_ref(c); + + switch (code) { + + case PA_CORE_MESSAGE_UNLOAD_MODULE: + pa_module_unload(c, userdata); + return 0; + + default: + return -1; + } +} + +static void core_free(pa_object *o); + pa_core* pa_core_new(pa_mainloop_api *m, int shared) { pa_core* c; pa_mempool *pool; + int j; + + pa_assert(m); if (shared) { if (!(pool = pa_mempool_new(shared))) { @@ -66,7 +89,9 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { } } - c = pa_xnew(pa_core, 1); + c = pa_msgobject_new(pa_core); + c->parent.parent.free = core_free; + c->parent.process_msg = core_process_msg; c->mainloop = m; c->clients = pa_idxset_new(NULL, NULL); @@ -87,6 +112,8 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { c->default_sample_spec.format = PA_SAMPLE_S16NE; c->default_sample_spec.rate = 44100; c->default_sample_spec.channels = 2; + c->default_n_fragments = 4; + c->default_fragment_size_msec = 25; c->module_auto_unload_event = NULL; c->module_defer_unload_event = NULL; @@ -99,22 +126,21 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { c->mempool = pool; - c->disallow_module_loading = 0; - c->quit_event = NULL; c->exit_idle_time = -1; c->module_idle_time = 20; c->scache_idle_time = 20; - c->resample_method = PA_RESAMPLER_SRC_SINC_FASTEST; + c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE; c->is_system_instance = 0; + c->disallow_module_loading = 0; + c->high_priority = 0; - pa_hook_init(&c->hook_sink_input_new, c); - pa_hook_init(&c->hook_sink_disconnect, c); - pa_hook_init(&c->hook_source_output_new, c); - pa_hook_init(&c->hook_source_disconnect, c); + + for (j = 0; j < PA_CORE_HOOK_MAX; j++) + pa_hook_init(&c->hooks[j], c); pa_property_init(c); @@ -123,28 +149,31 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { #ifdef SIGPIPE pa_check_signal_is_blocked(SIGPIPE); #endif + return c; } -void pa_core_free(pa_core *c) { - assert(c); +static void core_free(pa_object *o) { + pa_core *c = PA_CORE(o); + int j; + pa_assert(c); pa_module_unload_all(c); - assert(!c->modules); + pa_assert(!c->modules); - assert(pa_idxset_isempty(c->clients)); + pa_assert(pa_idxset_isempty(c->clients)); pa_idxset_free(c->clients, NULL, NULL); - assert(pa_idxset_isempty(c->sinks)); + pa_assert(pa_idxset_isempty(c->sinks)); pa_idxset_free(c->sinks, NULL, NULL); - assert(pa_idxset_isempty(c->sources)); + pa_assert(pa_idxset_isempty(c->sources)); pa_idxset_free(c->sources, NULL, NULL); - assert(pa_idxset_isempty(c->source_outputs)); + pa_assert(pa_idxset_isempty(c->source_outputs)); pa_idxset_free(c->source_outputs, NULL, NULL); - assert(pa_idxset_isempty(c->sink_inputs)); + pa_assert(pa_idxset_isempty(c->sink_inputs)); pa_idxset_free(c->sink_inputs, NULL, NULL); pa_scache_free(c); @@ -162,23 +191,21 @@ void pa_core_free(pa_core *c) { pa_property_cleanup(c); - pa_hook_free(&c->hook_sink_input_new); - pa_hook_free(&c->hook_sink_disconnect); - pa_hook_free(&c->hook_source_output_new); - pa_hook_free(&c->hook_source_disconnect); + for (j = 0; j < PA_CORE_HOOK_MAX; j++) + pa_hook_free(&c->hooks[j]); pa_xfree(c); } static void quit_callback(pa_mainloop_api*m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { pa_core *c = userdata; - assert(c->quit_event = e); + pa_assert(c->quit_event == e); m->quit(m, 0); } void pa_core_check_quit(pa_core *c) { - assert(c); + pa_assert(c); if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_size(c->clients) == 0) { struct timeval tv; diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 51a18b62e..dfa80f8d6 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -34,17 +34,51 @@ #include #include #include +#include typedef struct pa_core pa_core; #include #include +#include + +typedef enum pa_core_hook { + PA_CORE_HOOK_SINK_NEW_POST, + PA_CORE_HOOK_SINK_UNLINK, + PA_CORE_HOOK_SINK_UNLINK_POST, + PA_CORE_HOOK_SINK_STATE_CHANGED, + PA_CORE_HOOK_SINK_DESCRIPTION_CHANGED, + PA_CORE_HOOK_SOURCE_NEW_POST, + PA_CORE_HOOK_SOURCE_UNLINK, + PA_CORE_HOOK_SOURCE_UNLINK_POST, + PA_CORE_HOOK_SOURCE_STATE_CHANGED, + PA_CORE_HOOK_SOURCE_DESCRIPTION_CHANGED, + PA_CORE_HOOK_SINK_INPUT_NEW, + PA_CORE_HOOK_SINK_INPUT_PUT, + PA_CORE_HOOK_SINK_INPUT_UNLINK, + PA_CORE_HOOK_SINK_INPUT_UNLINK_POST, + PA_CORE_HOOK_SINK_INPUT_MOVE, + PA_CORE_HOOK_SINK_INPUT_MOVE_POST, + PA_CORE_HOOK_SINK_INPUT_NAME_CHANGED, + PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED, + PA_CORE_HOOK_SOURCE_OUTPUT_NEW, + PA_CORE_HOOK_SOURCE_OUTPUT_PUT, + PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK, + PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST, + PA_CORE_HOOK_SOURCE_OUTPUT_MOVE, + PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST, + PA_CORE_HOOK_SOURCE_OUTPUT_NAME_CHANGED, + PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED, + PA_CORE_HOOK_MAX +} pa_core_hook_t; /* The core structure of PulseAudio. Every PulseAudio daemon contains * exactly one of these. It is used for storing kind of global * variables for the daemon. */ struct pa_core { + pa_msgobject parent; + /* A random value which may be used to identify this instance of * PulseAudio. Not cryptographically secure in any way. */ uint32_t cookie; @@ -61,6 +95,8 @@ struct pa_core { char *default_source_name, *default_sink_name; pa_sample_spec default_sample_spec; + unsigned default_n_fragments, default_fragment_size_msec; + pa_time_event *module_auto_unload_event; pa_defer_event *module_defer_unload_event; @@ -71,27 +107,30 @@ struct pa_core { pa_mempool *mempool; - int disallow_module_loading, running_as_daemon; int exit_idle_time, module_idle_time, scache_idle_time; pa_time_event *quit_event; pa_time_event *scache_auto_unload_event; + int disallow_module_loading, running_as_daemon; pa_resample_method_t resample_method; - int is_system_instance; + int high_priority; /* hooks */ - pa_hook - hook_sink_input_new, - hook_sink_disconnect, - hook_source_output_new, - hook_source_disconnect; + pa_hook hooks[PA_CORE_HOOK_MAX]; +}; + +PA_DECLARE_CLASS(pa_core); +#define PA_CORE(o) pa_core_cast(o) + +enum { + PA_CORE_MESSAGE_UNLOAD_MODULE, + PA_CORE_MESSAGE_MAX }; pa_core* pa_core_new(pa_mainloop_api *m, int shared); -void pa_core_free(pa_core*c); /* Check whether noone is connected to this core */ void pa_core_check_quit(pa_core *c); diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h index e0a025bd0..51dfc33d5 100644 --- a/src/pulsecore/creds.h +++ b/src/pulsecore/creds.h @@ -26,7 +26,9 @@ #include -/* config.h must be included before this file */ +#ifndef PACKAGE +#error "Please include config.h before including this file!" +#endif #ifdef HAVE_SYS_SOCKET_H #include diff --git a/src/pulsecore/dynarray.c b/src/pulsecore/dynarray.c index 944e35707..8bdb46fa8 100644 --- a/src/pulsecore/dynarray.c +++ b/src/pulsecore/dynarray.c @@ -26,10 +26,10 @@ #endif #include -#include #include #include +#include #include "dynarray.h" @@ -52,7 +52,7 @@ pa_dynarray* pa_dynarray_new(void) { void pa_dynarray_free(pa_dynarray* a, void (*func)(void *p, void *userdata), void *userdata) { unsigned i; - assert(a); + pa_assert(a); if (func) for (i = 0; i < a->n_entries; i++) @@ -64,7 +64,7 @@ void pa_dynarray_free(pa_dynarray* a, void (*func)(void *p, void *userdata), voi } void pa_dynarray_put(pa_dynarray*a, unsigned i, void *p) { - assert(a); + pa_assert(a); if (i >= a->n_allocated) { unsigned n; @@ -85,21 +85,27 @@ void pa_dynarray_put(pa_dynarray*a, unsigned i, void *p) { } unsigned pa_dynarray_append(pa_dynarray*a, void *p) { - unsigned i = a->n_entries; + unsigned i; + + pa_assert(a); + + i = a->n_entries; pa_dynarray_put(a, i, p); return i; } void *pa_dynarray_get(pa_dynarray*a, unsigned i) { - assert(a); + pa_assert(a); + if (i >= a->n_entries) return NULL; - assert(a->data); + pa_assert(a->data); return a->data[i]; } unsigned pa_dynarray_size(pa_dynarray*a) { - assert(a); + pa_assert(a); + return a->n_entries; } diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h index c0c3a6d8c..8f7cfade3 100644 --- a/src/pulsecore/endianmacros.h +++ b/src/pulsecore/endianmacros.h @@ -27,54 +27,68 @@ #include -#ifdef HAVE_CONFIG_H -#include +#ifndef PACKAGE +#error "Please include config.h before including this file!" #endif -#define INT16_SWAP(x) ( (int16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) ) -#define UINT16_SWAP(x) ( (uint16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) ) -#define INT32_SWAP(x) ( (int32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) ) -#define UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) ) +#ifdef HAVE_BYTESWAP_H +#include +#endif -#define MAYBE_INT32_SWAP(c,x) ((c) ? INT32_SWAP(x) : x) -#define MAYBE_UINT32_SWAP(c,x) ((c) ? UINT32_SWAP(x) : x) +#ifdef HAVE_BYTESWAP_H +#define PA_INT16_SWAP(x) ((int16_t) bswap_16((uint16_t) x)) +#define PA_UINT16_SWAP(x) ((uint16_t) bswap_16((uint16_t) x)) +#define PA_INT32_SWAP(x) ((int32_t) bswap_32((uint32_t) x)) +#define PA_UINT32_SWAP(x) ((uint32_t) bswap_32((uint32_t) x)) +#else +#define PA_INT16_SWAP(x) ( (int16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) ) +#define PA_UINT16_SWAP(x) ( (uint16_t) ( ((uint16_t) x >> 8) | ((uint16_t) x << 8) ) ) +#define PA_INT32_SWAP(x) ( (int32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) ) +#define PA_UINT32_SWAP(x) ( (uint32_t) ( ((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 8) | ((((uint32_t) x) >> 8) & 0xFF00) ) ) +#endif + +#define PA_MAYBE_INT16_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : x) +#define PA_MAYBE_UINT16_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : x) + +#define PA_MAYBE_INT32_SWAP(c,x) ((c) ? PA_INT32_SWAP(x) : x) +#define PA_MAYBE_UINT32_SWAP(c,x) ((c) ? PA_UINT32_SWAP(x) : x) #ifdef WORDS_BIGENDIAN - #define INT16_FROM_LE(x) INT16_SWAP(x) - #define INT16_FROM_BE(x) ((int16_t)(x)) + #define PA_INT16_FROM_LE(x) PA_INT16_SWAP(x) + #define PA_INT16_FROM_BE(x) ((int16_t)(x)) - #define INT16_TO_LE(x) INT16_SWAP(x) - #define INT16_TO_BE(x) ((int16_t)(x)) + #define PA_INT16_TO_LE(x) PA_INT16_SWAP(x) + #define PA_INT16_TO_BE(x) ((int16_t)(x)) - #define UINT16_FROM_LE(x) UINT16_SWAP(x) - #define UINT16_FROM_BE(x) ((uint16_t)(x)) + #define PA_UINT16_FROM_LE(x) PA_UINT16_SWAP(x) + #define PA_UINT16_FROM_BE(x) ((uint16_t)(x)) - #define INT32_FROM_LE(x) INT32_SWAP(x) - #define INT32_FROM_BE(x) ((int32_t)(x)) + #define PA_INT32_FROM_LE(x) PA_INT32_SWAP(x) + #define PA_INT32_FROM_BE(x) ((int32_t)(x)) - #define UINT32_FROM_LE(x) UINT32_SWAP(x) - #define UINT32_FROM_BE(x) ((uint32_t)(x)) + #define PA_UINT32_FROM_LE(x) PA_UINT32_SWAP(x) + #define PA_UINT32_FROM_BE(x) ((uint32_t)(x)) - #define UINT32_TO_LE(x) UINT32_SWAP(x) - #define UINT32_TO_BE(x) ((uint32_t)(x)) + #define PA_UINT32_TO_LE(x) PA_UINT32_SWAP(x) + #define PA_UINT32_TO_BE(x) ((uint32_t)(x)) #else - #define INT16_FROM_LE(x) ((int16_t)(x)) - #define INT16_FROM_BE(x) INT16_SWAP(x) + #define PA_INT16_FROM_LE(x) ((int16_t)(x)) + #define PA_INT16_FROM_BE(x) PA_INT16_SWAP(x) - #define INT16_TO_LE(x) ((int16_t)(x)) - #define INT16_TO_BE(x) INT16_SWAP(x) + #define PA_INT16_TO_LE(x) ((int16_t)(x)) + #define PA_INT16_TO_BE(x) PA_INT16_SWAP(x) - #define UINT16_FROM_LE(x) ((uint16_t)(x)) - #define UINT16_FROM_BE(x) UINT16_SWAP(x) + #define PA_UINT16_FROM_LE(x) ((uint16_t)(x)) + #define PA_UINT16_FROM_BE(x) PA_UINT16_SWAP(x) - #define INT32_FROM_LE(x) ((int32_t)(x)) - #define INT32_FROM_BE(x) INT32_SWAP(x) + #define PA_INT32_FROM_LE(x) ((int32_t)(x)) + #define PA_INT32_FROM_BE(x) PA_INT32_SWAP(x) - #define UINT32_FROM_LE(x) ((uint32_t)(x)) - #define UINT32_FROM_BE(x) UINT32_SWAP(x) + #define PA_UINT32_FROM_LE(x) ((uint32_t)(x)) + #define PA_UINT32_FROM_BE(x) PA_UINT32_SWAP(x) - #define UINT32_TO_LE(x) ((uint32_t)(x)) - #define UINT32_TO_BE(x) UINT32_SWAP(x) + #define PA_UINT32_TO_LE(x) ((uint32_t)(x)) + #define PA_UINT32_TO_BE(x) PA_UINT32_SWAP(x) #endif #endif diff --git a/src/pulsecore/esound.h b/src/pulsecore/esound.h index 3778a535f..ea6a56650 100644 --- a/src/pulsecore/esound.h +++ b/src/pulsecore/esound.h @@ -205,7 +205,7 @@ typedef int esd_client_state_t; /* the endian key is transferred in binary, if it's read into int, */ /* and matches ESD_ENDIAN_KEY (ENDN), then the endianness of the */ /* server and the client match; if it's SWAP_ENDIAN_KEY, swap data */ -#define ESD_SWAP_ENDIAN_KEY (UINT32_SWAP(ESD_ENDIAN_KEY)) +#define ESD_SWAP_ENDIAN_KEY (PA_UINT32_SWAP(ESD_ENDIAN_KEY)) #endif diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c new file mode 100644 index 000000000..927bf00c2 --- /dev/null +++ b/src/pulsecore/fdsem.c @@ -0,0 +1,276 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_SYSCALL_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef HAVE_PIPE +#include +#endif + +#ifdef __linux__ + +#if !defined(__NR_eventfd) && defined(__i386__) +#define __NR_eventfd 323 +#endif + +#if !defined(__NR_eventfd) && defined(__x86_64__) +#define __NR_eventfd 284 +#endif + +#if !defined(SYS_eventfd) && defined(__NR_eventfd) +#define SYS_eventfd __NR_eventfd +#endif + +#ifdef SYS_eventfd +#define HAVE_EVENTFD + +static inline long eventfd(unsigned count) { + return syscall(SYS_eventfd, count); +} + +#endif +#endif + +#include "fdsem.h" + +struct pa_fdsem { + int fds[2]; +#ifdef HAVE_EVENTFD + int efd; +#endif + pa_atomic_t waiting; + pa_atomic_t signalled; + pa_atomic_t in_pipe; +}; + +pa_fdsem *pa_fdsem_new(void) { + pa_fdsem *f; + + f = pa_xnew(pa_fdsem, 1); + +#ifdef HAVE_EVENTFD + if ((f->efd = eventfd(0)) >= 0) { + pa_make_fd_cloexec(f->efd); + f->fds[0] = f->fds[1] = -1; + + } else +#endif + { + if (pipe(f->fds) < 0) { + pa_xfree(f); + return NULL; + } + + pa_make_fd_cloexec(f->fds[0]); + pa_make_fd_cloexec(f->fds[1]); + } + + pa_atomic_store(&f->waiting, 0); + pa_atomic_store(&f->signalled, 0); + pa_atomic_store(&f->in_pipe, 0); + + return f; +} + +void pa_fdsem_free(pa_fdsem *f) { + pa_assert(f); + +#ifdef HAVE_EVENTFD + if (f->efd >= 0) + pa_close(f->efd); +#endif + pa_close_pipe(f->fds); + + pa_xfree(f); +} + +static void flush(pa_fdsem *f) { + ssize_t r; + pa_assert(f); + + if (pa_atomic_load(&f->in_pipe) <= 0) + return; + + do { + char x[10]; + +#ifdef HAVE_EVENTFD + if (f->efd >= 0) { + uint64_t u; + + if ((r = read(f->efd, &u, sizeof(u))) != sizeof(u)) { + pa_assert(r < 0 && errno == EINTR); + continue; + } + r = (ssize_t) u; + } else +#endif + + if ((r = read(f->fds[0], &x, sizeof(x))) <= 0) { + pa_assert(r < 0 && errno == EINTR); + continue; + } + + } while (pa_atomic_sub(&f->in_pipe, r) > r); +} + +void pa_fdsem_post(pa_fdsem *f) { + pa_assert(f); + + if (pa_atomic_cmpxchg(&f->signalled, 0, 1)) { + + if (pa_atomic_load(&f->waiting)) { + ssize_t r; + char x = 'x'; + + pa_atomic_inc(&f->in_pipe); + + for (;;) { + +#ifdef HAVE_EVENTFD + if (f->efd >= 0) { + uint64_t u = 1; + + if ((r = write(f->efd, &u, sizeof(u))) != sizeof(u)) { + pa_assert(r < 0 && errno == EINTR); + continue; + } + } else +#endif + + if ((r = write(f->fds[1], &x, 1)) != 1) { + pa_assert(r < 0 && errno == EINTR); + continue; + } + + break; + } + } + } +} + +void pa_fdsem_wait(pa_fdsem *f) { + pa_assert(f); + + flush(f); + + if (pa_atomic_cmpxchg(&f->signalled, 1, 0)) + return; + + pa_atomic_inc(&f->waiting); + + while (!pa_atomic_cmpxchg(&f->signalled, 1, 0)) { + char x[10]; + ssize_t r; + +#ifdef HAVE_EVENTFD + if (f->efd >= 0) { + uint64_t u; + + if ((r = read(f->efd, &u, sizeof(u))) != sizeof(u)) { + pa_assert(r < 0 && errno == EINTR); + continue; + } + + r = (ssize_t) u; + } else +#endif + + if ((r = read(f->fds[0], &x, sizeof(x))) <= 0) { + pa_assert(r < 0 && errno == EINTR); + continue; + } + + pa_atomic_sub(&f->in_pipe, r); + } + + pa_assert_se(pa_atomic_dec(&f->waiting) >= 1); +} + +int pa_fdsem_try(pa_fdsem *f) { + pa_assert(f); + + flush(f); + + if (pa_atomic_cmpxchg(&f->signalled, 1, 0)) + return 1; + + return 0; +} + +int pa_fdsem_get(pa_fdsem *f) { + pa_assert(f); + +#ifdef HAVE_EVENTFD + if (f->efd >= 0) + return f->efd; +#endif + + return f->fds[0]; +} + +int pa_fdsem_before_poll(pa_fdsem *f) { + pa_assert(f); + + flush(f); + + if (pa_atomic_cmpxchg(&f->signalled, 1, 0)) + return -1; + + pa_atomic_inc(&f->waiting); + + if (pa_atomic_cmpxchg(&f->signalled, 1, 0)) { + pa_assert_se(pa_atomic_dec(&f->waiting) >= 1); + return -1; + } + return 0; +} + +int pa_fdsem_after_poll(pa_fdsem *f) { + pa_assert(f); + + pa_assert_se(pa_atomic_dec(&f->waiting) >= 1); + + flush(f); + + if (pa_atomic_cmpxchg(&f->signalled, 1, 0)) + return 1; + + return 0; +} diff --git a/src/pulsecore/fdsem.h b/src/pulsecore/fdsem.h new file mode 100644 index 000000000..f38ef205c --- /dev/null +++ b/src/pulsecore/fdsem.h @@ -0,0 +1,49 @@ +#ifndef foopulsefdsemhfoo +#define foopulsefdsemhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +/* A simple, asynchronous semaphore which uses fds for sleeping. In + * the best case all functions are lock-free unless sleeping is + * required. */ + +typedef struct pa_fdsem pa_fdsem; + +pa_fdsem *pa_fdsem_new(void); +void pa_fdsem_free(pa_fdsem *f); + +void pa_fdsem_post(pa_fdsem *f); +void pa_fdsem_wait(pa_fdsem *f); +int pa_fdsem_try(pa_fdsem *f); + +int pa_fdsem_get(pa_fdsem *f); + +int pa_fdsem_before_poll(pa_fdsem *f); +int pa_fdsem_after_poll(pa_fdsem *f); + + +#endif diff --git a/src/pulsecore/ffmpeg/Makefile b/src/pulsecore/ffmpeg/Makefile new file mode 100644 index 000000000..316beb72d --- /dev/null +++ b/src/pulsecore/ffmpeg/Makefile @@ -0,0 +1,13 @@ +# This is a dirty trick just to ease compilation with emacs +# +# This file is not intended to be distributed or anything +# +# So: don't touch it, even better ignore it! + +all: + $(MAKE) -C ../.. + +clean: + $(MAKE) -C ../.. clean + +.PHONY: all clean diff --git a/src/pulsecore/ffmpeg/avcodec.h b/src/pulsecore/ffmpeg/avcodec.h new file mode 100644 index 000000000..696fc9864 --- /dev/null +++ b/src/pulsecore/ffmpeg/avcodec.h @@ -0,0 +1,82 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_H +#define AVCODEC_H + +/* Just a heavily bastardized version of the original file from + * ffmpeg, just enough to get resample2.c to compile without + * modification -- Lennart */ + +#if !defined(PACKAGE) && defined(HAVE_CONFIG_H) +#include +#endif + +#include +#include +#include +#include +#include +#include + +#define av_mallocz(l) calloc(1, (l)) +#define av_malloc(l) malloc(l) +#define av_realloc(p,l) realloc((p),(l)) +#define av_free(p) free(p) + +static inline void av_freep(void *k) { + void **p = k; + + if (p) { + free(*p); + *p = NULL; + } +} + +static inline int av_clip(int a, int amin, int amax) +{ + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +#define av_log(a,b,c) + +#define FFABS(a) ((a) >= 0 ? (a) : (-(a))) +#define FFSIGN(a) ((a) > 0 ? 1 : -1) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) + +struct AVResampleContext; +struct AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_length, int log2_phase_count, int linear, double cutoff); +int av_resample(struct AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx); +void av_resample_compensate(struct AVResampleContext *c, int sample_delta, int compensation_distance); +void av_resample_close(struct AVResampleContext *c); +void av_build_filter(int16_t *filter, double factor, int tap_count, int phase_count, int scale, int type); + +/* + * crude lrintf for non-C99 systems. + */ +#ifndef HAVE_LRINTF +#define lrintf(x) ((long int)(x)) +#endif + +#endif /* AVCODEC_H */ diff --git a/src/pulsecore/ffmpeg/dsputil.h b/src/pulsecore/ffmpeg/dsputil.h new file mode 100644 index 000000000..8da742d0f --- /dev/null +++ b/src/pulsecore/ffmpeg/dsputil.h @@ -0,0 +1 @@ +/* empty file, just here to allow us to compile an unmodified resampler2.c */ diff --git a/src/pulsecore/ffmpeg/resample2.c b/src/pulsecore/ffmpeg/resample2.c new file mode 100644 index 000000000..da1443d98 --- /dev/null +++ b/src/pulsecore/ffmpeg/resample2.c @@ -0,0 +1,324 @@ +/* + * audio resampling + * Copyright (c) 2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file resample2.c + * audio resampling + * @author Michael Niedermayer + */ + +#include "avcodec.h" +#include "dsputil.h" + +#ifndef CONFIG_RESAMPLE_HP +#define FILTER_SHIFT 15 + +#define FELEM int16_t +#define FELEM2 int32_t +#define FELEML int64_t +#define FELEM_MAX INT16_MAX +#define FELEM_MIN INT16_MIN +#define WINDOW_TYPE 9 +#elif !defined(CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE) +#define FILTER_SHIFT 30 + +#define FELEM int32_t +#define FELEM2 int64_t +#define FELEML int64_t +#define FELEM_MAX INT32_MAX +#define FELEM_MIN INT32_MIN +#define WINDOW_TYPE 12 +#else +#define FILTER_SHIFT 0 + +#define FELEM double +#define FELEM2 double +#define FELEML double +#define WINDOW_TYPE 24 +#endif + + +typedef struct AVResampleContext{ + FELEM *filter_bank; + int filter_length; + int ideal_dst_incr; + int dst_incr; + int index; + int frac; + int src_incr; + int compensation_distance; + int phase_shift; + int phase_mask; + int linear; +}AVResampleContext; + +/** + * 0th order modified bessel function of the first kind. + */ +static double bessel(double x){ + double v=1; + double t=1; + int i; + + x= x*x/4; + for(i=1; i<50; i++){ + t *= x/(i*i); + v += t; + } + return v; +} + +/** + * builds a polyphase filterbank. + * @param factor resampling factor + * @param scale wanted sum of coefficients for each filter + * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16 + */ +void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){ + int ph, i; + double x, y, w, tab[tap_count]; + const int center= (tap_count-1)/2; + + /* if upsampling, only need to interpolate, no filter */ + if (factor > 1.0) + factor = 1.0; + + for(ph=0;phphase_shift= phase_shift; + c->phase_mask= phase_count-1; + c->linear= linear; + + c->filter_length= FFMAX((int)ceil(filter_size/factor), 1); + c->filter_bank= av_mallocz(c->filter_length*(phase_count+1)*sizeof(FELEM)); + av_build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM)); + c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1]; + + c->src_incr= out_rate; + c->ideal_dst_incr= c->dst_incr= in_rate * phase_count; + c->index= -phase_count*((c->filter_length-1)/2); + + return c; +} + +void av_resample_close(AVResampleContext *c){ + av_freep(&c->filter_bank); + av_freep(&c); +} + +/** + * Compensates samplerate/timestamp drift. The compensation is done by changing + * the resampler parameters, so no audible clicks or similar distortions ocur + * @param compensation_distance distance in output samples over which the compensation should be performed + * @param sample_delta number of output samples which should be output less + * + * example: av_resample_compensate(c, 10, 500) + * here instead of 510 samples only 500 samples would be output + * + * note, due to rounding the actual compensation might be slightly different, + * especially if the compensation_distance is large and the in_rate used during init is small + */ +void av_resample_compensate(AVResampleContext *c, int sample_delta, int compensation_distance){ +// sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensation_distance / c->ideal_dst_incr; + c->compensation_distance= compensation_distance; + c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance; +} + +/** + * resamples. + * @param src an array of unconsumed samples + * @param consumed the number of samples of src which have been consumed are returned here + * @param src_size the number of unconsumed samples available + * @param dst_size the amount of space in samples available in dst + * @param update_ctx if this is 0 then the context wont be modified, that way several channels can be resampled with the same context + * @return the number of samples written in dst or -1 if an error occured + */ +int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx){ + int dst_index, i; + int index= c->index; + int frac= c->frac; + int dst_incr_frac= c->dst_incr % c->src_incr; + int dst_incr= c->dst_incr / c->src_incr; + int compensation_distance= c->compensation_distance; + + if(compensation_distance == 0 && c->filter_length == 1 && c->phase_shift==0){ + int64_t index2= ((int64_t)index)<<32; + int64_t incr= (1LL<<32) * c->dst_incr / c->src_incr; + dst_size= FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / c->dst_incr); + + for(dst_index=0; dst_index < dst_size; dst_index++){ + dst[dst_index] = src[index2>>32]; + index2 += incr; + } + frac += dst_index * dst_incr_frac; + index += dst_index * dst_incr; + index += frac / c->src_incr; + frac %= c->src_incr; + }else{ + for(dst_index=0; dst_index < dst_size; dst_index++){ + FELEM *filter= c->filter_bank + c->filter_length*(index & c->phase_mask); + int sample_index= index >> c->phase_shift; + FELEM2 val=0; + + if(sample_index < 0){ + for(i=0; ifilter_length; i++) + val += src[FFABS(sample_index + i) % src_size] * filter[i]; + }else if(sample_index + c->filter_length > src_size){ + break; + }else if(c->linear){ + FELEM2 v2=0; + for(i=0; ifilter_length; i++){ + val += src[sample_index + i] * (FELEM2)filter[i]; + v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_length]; + } + val+=(v2-val)*(FELEML)frac / c->src_incr; + }else{ + for(i=0; ifilter_length; i++){ + val += src[sample_index + i] * (FELEM2)filter[i]; + } + } + +#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE + dst[dst_index] = av_clip_int16(lrintf(val)); +#else + val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT; + dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val; +#endif + + frac += dst_incr_frac; + index += dst_incr; + if(frac >= c->src_incr){ + frac -= c->src_incr; + index++; + } + + if(dst_index + 1 == compensation_distance){ + compensation_distance= 0; + dst_incr_frac= c->ideal_dst_incr % c->src_incr; + dst_incr= c->ideal_dst_incr / c->src_incr; + } + } + } + *consumed= FFMAX(index, 0) >> c->phase_shift; + if(index>=0) index &= c->phase_mask; + + if(compensation_distance){ + compensation_distance -= dst_index; + assert(compensation_distance > 0); + } + if(update_ctx){ + c->frac= frac; + c->index= index; + c->dst_incr= dst_incr_frac + c->src_incr*dst_incr; + c->compensation_distance= compensation_distance; + } +#if 0 + if(update_ctx && !c->compensation_distance){ +#undef rand + av_resample_compensate(c, rand() % (8000*2) - 8000, 8000*2); +av_log(NULL, AV_LOG_DEBUG, "%d %d %d\n", c->dst_incr, c->ideal_dst_incr, c->compensation_distance); + } +#endif + + return dst_index; +} diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c index 00567ab32..d97407771 100644 --- a/src/pulsecore/flist.c +++ b/src/pulsecore/flist.c @@ -25,12 +25,14 @@ #include #endif -#include +#include #include #include #include -#include +#include +#include +#include #include "flist.h" @@ -90,21 +92,18 @@ enum { }; struct cell { - pa_atomic_int_t state; + pa_atomic_t state; void *data; }; struct pa_flist { - struct cell *cells; unsigned size; - pa_atomic_int_t length; - pa_atomic_int_t read_idx; - pa_atomic_int_t write_idx; + pa_atomic_t length; + pa_atomic_t read_idx; + pa_atomic_t write_idx; }; -static int is_power_of_two(unsigned size) { - return !(size & (size - 1)); -} +#define PA_FLIST_CELLS(x) ((struct cell*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_flist)))) pa_flist *pa_flist_new(unsigned size) { pa_flist *l; @@ -112,12 +111,11 @@ pa_flist *pa_flist_new(unsigned size) { if (!size) size = FLIST_SIZE; - assert(is_power_of_two(size)); + pa_assert(pa_is_power_of_two(size)); - l = pa_xnew(pa_flist, 1); + l = pa_xmalloc0(PA_ALIGN(sizeof(pa_flist)) + (sizeof(struct cell) * size)); l->size = size; - l->cells = pa_xnew0(struct cell, size); pa_atomic_store(&l->read_idx, 0); pa_atomic_store(&l->write_idx, 0); @@ -131,32 +129,37 @@ static int reduce(pa_flist *l, int value) { } void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) { - assert(l); + pa_assert(l); if (free_cb) { + struct cell *cells; int len, idx; + cells = PA_FLIST_CELLS(l); + idx = reduce(l, pa_atomic_load(&l->read_idx)); len = pa_atomic_load(&l->length); for (; len > 0; len--) { - if (pa_atomic_load(&l->cells[idx].state) == STATE_USED) - free_cb(l->cells[idx].data); + if (pa_atomic_load(&cells[idx].state) == STATE_USED) + free_cb(cells[idx].data); idx = reduce(l, idx + 1); } } - pa_xfree(l->cells); pa_xfree(l); } int pa_flist_push(pa_flist*l, void *p) { int idx, len, n; + struct cell *cells; - assert(l); - assert(p); + pa_assert(l); + pa_assert(p); + + cells = PA_FLIST_CELLS(l); n = len = (int) l->size - pa_atomic_load(&l->length) + N_EXTRA_SCAN; _Y; @@ -165,13 +168,13 @@ int pa_flist_push(pa_flist*l, void *p) { for (; n > 0 ; n--) { _Y; - if (pa_atomic_cmpxchg(&l->cells[idx].state, STATE_UNUSED, STATE_BUSY)) { + if (pa_atomic_cmpxchg(&cells[idx].state, STATE_UNUSED, STATE_BUSY)) { _Y; pa_atomic_inc(&l->write_idx); _Y; - l->cells[idx].data = p; + cells[idx].data = p; _Y; - pa_atomic_store(&l->cells[idx].state, STATE_USED); + pa_atomic_store(&cells[idx].state, STATE_USED); _Y; pa_atomic_inc(&l->length); return 0; @@ -183,7 +186,7 @@ int pa_flist_push(pa_flist*l, void *p) { #ifdef PROFILE if (len > N_EXTRA_SCAN) - pa_log("WARNING: Didn't find free cell after %u iterations.", len); + pa_log_warn("Didn't find free cell after %u iterations.", len); #endif return -1; @@ -191,8 +194,11 @@ int pa_flist_push(pa_flist*l, void *p) { void* pa_flist_pop(pa_flist*l) { int idx, len, n; + struct cell *cells; - assert(l); + pa_assert(l); + + cells = PA_FLIST_CELLS(l); n = len = pa_atomic_load(&l->length) + N_EXTRA_SCAN; _Y; @@ -201,14 +207,14 @@ void* pa_flist_pop(pa_flist*l) { for (; n > 0 ; n--) { _Y; - if (pa_atomic_cmpxchg(&l->cells[idx].state, STATE_USED, STATE_BUSY)) { + if (pa_atomic_cmpxchg(&cells[idx].state, STATE_USED, STATE_BUSY)) { void *p; _Y; pa_atomic_inc(&l->read_idx); _Y; - p = l->cells[idx].data; + p = cells[idx].data; _Y; - pa_atomic_store(&l->cells[idx].state, STATE_UNUSED); + pa_atomic_store(&cells[idx].state, STATE_UNUSED); _Y; pa_atomic_dec(&l->length); @@ -221,7 +227,7 @@ void* pa_flist_pop(pa_flist*l) { #ifdef PROFILE if (len > N_EXTRA_SCAN) - pa_log("WARNING: Didn't find used cell after %u iterations.", len); + pa_log_warn("Didn't find used cell after %u iterations.", len); #endif return NULL; diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h index bf702bf33..daf0fec41 100644 --- a/src/pulsecore/flist.h +++ b/src/pulsecore/flist.h @@ -26,6 +26,9 @@ #include +#include +#include + /* A multiple-reader multipler-write lock-free free list implementation */ typedef struct pa_flist pa_flist; @@ -38,4 +41,28 @@ void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb); int pa_flist_push(pa_flist*l, void *p); void* pa_flist_pop(pa_flist*l); +/* Please not that the destructor stuff is not really necesary, we do + * this just to make valgrind output more useful. */ + +#define PA_STATIC_FLIST_DECLARE(name, size, free_cb) \ + static struct { \ + pa_flist *flist; \ + pa_once once; \ + } name##_flist = { NULL, PA_ONCE_INIT }; \ + static void name##_flist_init(void) { \ + name##_flist.flist = pa_flist_new(size); \ + } \ + static inline pa_flist* name##_flist_get(void) { \ + pa_run_once(&name##_flist.once, name##_flist_init); \ + return name##_flist.flist; \ + } \ + static void name##_flist_destructor(void) PA_GCC_DESTRUCTOR; \ + static void name##_flist_destructor(void) { \ + if (name##_flist.flist) \ + pa_flist_free(name##_flist.flist, (free_cb)); \ + } \ + struct __stupid_useless_struct_to_allow_trailing_semicolon + +#define PA_STATIC_FLIST_GET(name) (name##_flist_get()) + #endif diff --git a/src/pulsecore/g711.c b/src/pulsecore/g711.c index 8c2bbf008..aa2d703a8 100644 --- a/src/pulsecore/g711.c +++ b/src/pulsecore/g711.c @@ -43,30 +43,30 @@ #include "g711.h" -#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ -#define QUANT_MASK (0xf) /* Quantization field mask. */ -#define NSEGS (8) /* Number of A-law segments. */ -#define SEG_SHIFT (4) /* Left shift for segment number. */ -#define SEG_MASK (0x70) /* Segment field mask. */ +#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ +#define SEG_MASK (0x70) /* Segment field mask. */ #if !defined(FAST_ALAW_CONVERSION) || !defined(FAST_ULAW_CONVERSION) static int16_t seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF, - 0x1FF, 0x3FF, 0x7FF, 0xFFF}; + 0x1FF, 0x3FF, 0x7FF, 0xFFF}; static int16_t seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, - 0x3FF, 0x7FF, 0xFFF, 0x1FFF}; + 0x3FF, 0x7FF, 0xFFF, 0x1FFF}; static int16_t search( - int16_t val, - int16_t *table, - int size) + int16_t val, + int16_t *table, + int size) { - int i; + int i; - for (i = 0; i < size; i++) { - if (val <= *table++) - return (i); - } - return (size); + for (i = 0; i < size; i++) { + if (val <= *table++) + return (i); + } + return (size); } #endif /* !FAST_*_CONVERSION */ @@ -77,55 +77,55 @@ static int16_t search( * the data shifted such that it only contains information in the lower * 13-bits. * - * Linear Input Code Compressed Code - * ------------------------ --------------- - * 0000000wxyza 000wxyz - * 0000001wxyza 001wxyz - * 000001wxyzab 010wxyz - * 00001wxyzabc 011wxyz - * 0001wxyzabcd 100wxyz - * 001wxyzabcde 101wxyz - * 01wxyzabcdef 110wxyz - * 1wxyzabcdefg 111wxyz + * Linear Input Code Compressed Code + * ------------------------ --------------- + * 0000000wxyza 000wxyz + * 0000001wxyza 001wxyz + * 000001wxyzab 010wxyz + * 00001wxyzabc 011wxyz + * 0001wxyzabcd 100wxyz + * 001wxyzabcde 101wxyz + * 01wxyzabcdef 110wxyz + * 1wxyzabcdefg 111wxyz * * For further information see John C. Bellamy's Digital Telephony, 1982, * John Wiley & Sons, pps 98-111 and 472-476. */ unsigned char st_13linear2alaw( - int16_t pcm_val) /* 2's complement (13-bit range) */ + int16_t pcm_val) /* 2's complement (13-bit range) */ { - int16_t mask; - short seg; - unsigned char aval; + int16_t mask; + short seg; + unsigned char aval; - /* Have calling software do it since its already doing a shift - * from 32-bits down to 16-bits. - */ - /* pcm_val = pcm_val >> 3; */ + /* Have calling software do it since its already doing a shift + * from 32-bits down to 16-bits. + */ + /* pcm_val = pcm_val >> 3; */ - /* A-law using even bit inversion */ - if (pcm_val >= 0) { - mask = 0xD5; /* sign (7th) bit = 1 */ - } else { - mask = 0x55; /* sign bit = 0 */ - pcm_val = -pcm_val - 1; - } + /* A-law using even bit inversion */ + if (pcm_val >= 0) { + mask = 0xD5; /* sign (7th) bit = 1 */ + } else { + mask = 0x55; /* sign bit = 0 */ + pcm_val = -pcm_val - 1; + } - /* Convert the scaled magnitude to segment number. */ - seg = search(pcm_val, seg_aend, 8); + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_aend, 8); - /* Combine the sign, segment, and quantization bits. */ + /* Combine the sign, segment, and quantization bits. */ - if (seg >= 8) /* out of range, return maximum value. */ - return (unsigned char) (0x7F ^ mask); - else { - aval = (unsigned char) seg << SEG_SHIFT; - if (seg < 2) - aval |= (pcm_val >> 1) & QUANT_MASK; - else - aval |= (pcm_val >> seg) & QUANT_MASK; - return (aval ^ mask); - } + if (seg >= 8) /* out of range, return maximum value. */ + return (unsigned char) (0x7F ^ mask); + else { + aval = (unsigned char) seg << SEG_SHIFT; + if (seg < 2) + aval |= (pcm_val >> 1) & QUANT_MASK; + else + aval |= (pcm_val >> seg) & QUANT_MASK; + return (aval ^ mask); + } } /* @@ -133,31 +133,31 @@ unsigned char st_13linear2alaw( * */ int16_t st_alaw2linear16( - unsigned char a_val) + unsigned char a_val) { - int16_t t; - int16_t seg; + int16_t t; + int16_t seg; - a_val ^= 0x55; + a_val ^= 0x55; - t = (a_val & QUANT_MASK) << 4; - seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; - switch (seg) { - case 0: - t += 8; - break; - case 1: - t += 0x108; - break; - default: - t += 0x108; - t <<= seg - 1; - } - return ((a_val & SIGN_BIT) ? t : -t); + t = (a_val & QUANT_MASK) << 4; + seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; + switch (seg) { + case 0: + t += 8; + break; + case 1: + t += 0x108; + break; + default: + t += 0x108; + t <<= seg - 1; + } + return ((a_val & SIGN_BIT) ? t : -t); } #endif /* !FAST_ALAW_CONVERSION */ -#define BIAS (0x84) /* Bias for linear code. */ +#define BIAS (0x84) /* Bias for linear code. */ #define CLIP 8159 #ifndef FAST_ULAW_CONVERSION @@ -171,16 +171,16 @@ int16_t st_alaw2linear16( * is biased by adding 33 which shifts the encoding range from (0 - 8158) to * (33 - 8191). The result can be seen in the following encoding table: * - * Biased Linear Input Code Compressed Code - * ------------------------ --------------- - * 00000001wxyza 000wxyz - * 0000001wxyzab 001wxyz - * 000001wxyzabc 010wxyz - * 00001wxyzabcd 011wxyz - * 0001wxyzabcde 100wxyz - * 001wxyzabcdef 101wxyz - * 01wxyzabcdefg 110wxyz - * 1wxyzabcdefgh 111wxyz + * Biased Linear Input Code Compressed Code + * ------------------------ --------------- + * 00000001wxyza 000wxyz + * 0000001wxyzab 001wxyz + * 000001wxyzabc 010wxyz + * 00001wxyzabcd 011wxyz + * 0001wxyzabcde 100wxyz + * 001wxyzabcdef 101wxyz + * 01wxyzabcdefg 110wxyz + * 1wxyzabcdefgh 111wxyz * * Each biased linear code has a leading 1 which identifies the segment * number. The value of the segment number is equal to 7 minus the number @@ -194,41 +194,41 @@ int16_t st_alaw2linear16( * John Wiley & Sons, pps 98-111 and 472-476. */ unsigned char st_14linear2ulaw( - int16_t pcm_val) /* 2's complement (14-bit range) */ + int16_t pcm_val) /* 2's complement (14-bit range) */ { - int16_t mask; - int16_t seg; - unsigned char uval; + int16_t mask; + int16_t seg; + unsigned char uval; - /* Have calling software do it since its already doing a shift - * from 32-bits down to 16-bits. - */ - /* pcm_val = pcm_val >> 2; */ + /* Have calling software do it since its already doing a shift + * from 32-bits down to 16-bits. + */ + /* pcm_val = pcm_val >> 2; */ - /* u-law inverts all bits */ - /* Get the sign and the magnitude of the value. */ - if (pcm_val < 0) { - pcm_val = -pcm_val; - mask = 0x7F; - } else { - mask = 0xFF; - } - if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */ - pcm_val += (BIAS >> 2); + /* u-law inverts all bits */ + /* Get the sign and the magnitude of the value. */ + if (pcm_val < 0) { + pcm_val = -pcm_val; + mask = 0x7F; + } else { + mask = 0xFF; + } + if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */ + pcm_val += (BIAS >> 2); - /* Convert the scaled magnitude to segment number. */ - seg = search(pcm_val, seg_uend, 8); + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_uend, 8); - /* - * Combine the sign, segment, quantization bits; - * and complement the code word. - */ - if (seg >= 8) /* out of range, return maximum value. */ - return (unsigned char) (0x7F ^ mask); - else { - uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF); - return (uval ^ mask); - } + /* + * Combine the sign, segment, quantization bits; + * and complement the code word. + */ + if (seg >= 8) /* out of range, return maximum value. */ + return (unsigned char) (0x7F ^ mask); + else { + uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF); + return (uval ^ mask); + } } @@ -242,21 +242,21 @@ unsigned char st_14linear2ulaw( * original code word. This is in keeping with ISDN conventions. */ int16_t st_ulaw2linear16( - unsigned char u_val) + unsigned char u_val) { - int16_t t; + int16_t t; - /* Complement to obtain normal u-law value. */ - u_val = ~u_val; + /* Complement to obtain normal u-law value. */ + u_val = ~u_val; - /* - * Extract and bias the quantization bits. Then - * shift up by the segment number and subtract out the bias. - */ - t = ((u_val & QUANT_MASK) << 3) + BIAS; - t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = ((u_val & QUANT_MASK) << 3) + BIAS; + t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; - return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); + return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); } #endif /* !FAST_ULAW_CONVERSION */ @@ -2413,52 +2413,52 @@ int main() printf("int16_t _st_alaw2linear16[256] = {\n "); for (x = 0; x < 256; x++) { - printf("%8d,", st_alaw2linear16(x)); - y++; - if (y == 7) - { - y = 0; - printf("\n "); - } + printf("%8d,", st_alaw2linear16(x)); + y++; + if (y == 7) + { + y = 0; + printf("\n "); + } } printf("\n};\n\nuint8_t _st_13linear2alaw[0x2000] = {\n "); y = 0; for (x = 0; x < 0x2000; x++) { - printf(" 0x%02x,", st_13linear2alaw((-0x1000)+x)); - y++; - if (y == 12) - { - y = 0; - printf("\n "); - } + printf(" 0x%02x,", st_13linear2alaw((-0x1000)+x)); + y++; + if (y == 12) + { + y = 0; + printf("\n "); + } } printf("\n};\n\nint16_t _st_ulaw2linear16[256] = {\n "); y = 0; for (x = 0; x < 256; x++) { - printf("%8d,", st_ulaw2linear16(x)); - y++; - if (y == 7) - { - y = 0; - printf("\n "); - } + printf("%8d,", st_ulaw2linear16(x)); + y++; + if (y == 7) + { + y = 0; + printf("\n "); + } } printf("\n};\n\nuint8_t _st_14linear2ulaw[0x4000] = {\n "); y = 0; for (x = 0; x < 0x4000; x++) { - printf(" 0x%02x,", st_14linear2ulaw((-0x2000)+x)); - y++; - if (y == 12) - { - y = 0; - printf("\n "); - } + printf(" 0x%02x,", st_14linear2ulaw((-0x2000)+x)); + y++; + if (y == 12) + { + y = 0; + printf("\n "); + } } printf("\n};\n"); @@ -2468,64 +2468,64 @@ int main() /* The following is not used by SoX but kept for reference */ #if 0 /* copy from CCITT G.711 specifications */ -unsigned char _u2a[128] = { /* u- to A-law conversions */ - 1, 1, 2, 2, 3, 3, 4, 4, - 5, 5, 6, 6, 7, 7, 8, 8, - 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, - 25, 27, 29, 31, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, - 46, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, - 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, +unsigned char _u2a[128] = { /* u- to A-law conversions */ + 1, 1, 2, 2, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 27, 29, 31, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 46, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, /* corrected: - 81, 82, 83, 84, 85, 86, 87, 88, + 81, 82, 83, 84, 85, 86, 87, 88, should be: */ - 80, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128}; + 80, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128}; -unsigned char _a2u[128] = { /* A- to u-law conversions */ - 1, 3, 5, 7, 9, 11, 13, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 32, 33, 33, 34, 34, 35, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 48, 49, 49, - 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 64, - 65, 66, 67, 68, 69, 70, 71, 72, +unsigned char _a2u[128] = { /* A- to u-law conversions */ + 1, 3, 5, 7, 9, 11, 13, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 33, 34, 34, 35, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 48, 49, 49, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 64, + 65, 66, 67, 68, 69, 70, 71, 72, /* corrected: - 73, 74, 75, 76, 77, 78, 79, 79, + 73, 74, 75, 76, 77, 78, 79, 79, should be: */ - 73, 74, 75, 76, 77, 78, 79, 80, + 73, 74, 75, 76, 77, 78, 79, 80, - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127}; + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}; /* A-law to u-law conversion */ unsigned char st_alaw2ulaw( - unsigned char aval) + unsigned char aval) { - aval &= 0xff; - return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : - (0x7F ^ _a2u[aval ^ 0x55])); + aval &= 0xff; + return (unsigned char) ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : + (0x7F ^ _a2u[aval ^ 0x55])); } /* u-law to A-law conversion */ unsigned char st_ulaw2alaw( - unsigned char uval) + unsigned char uval) { - uval &= 0xff; - return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : - (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1))); + uval &= 0xff; + return (unsigned char) ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : + (unsigned char) (0x55 ^ (_u2a[0x7F ^ uval] - 1))); } #endif diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h index 57d280064..e9f0d0939 100644 --- a/src/pulsecore/gccmacro.h +++ b/src/pulsecore/gccmacro.h @@ -52,4 +52,29 @@ #define PA_GCC_UNUSED #endif +#ifdef __GNUC__ +#define PA_GCC_DESTRUCTOR __attribute__ ((destructor)) +#else +/** Call this function when process terminates */ +#define PA_GCC_DESTRUCTOR +#endif + +#ifndef PA_GCC_PURE +#ifdef __GNUCC__ +#define PA_GCC_PURE __attribute__ ((pure)) +#else +/** This function's return value depends only the arguments list and global state **/ +#define PA_GCC_PURE +#endif +#endif + +#ifndef PA_GCC_CONST +#ifdef __GNUCC__ +#define PA_GCC_CONST __attribute__ ((const)) +#else +/** This function's return value depends only the arguments list (stricter version of PA_GCC_PURE) **/ +#define PA_GCC_CONST +#endif +#endif + #endif diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c index 818e12bf7..f55896647 100644 --- a/src/pulsecore/hashmap.c +++ b/src/pulsecore/hashmap.c @@ -26,13 +26,14 @@ #endif #include -#include #include #include #include #include +#include +#include #include "hashmap.h" @@ -55,6 +56,8 @@ struct pa_hashmap { pa_compare_func_t compare_func; }; +PA_STATIC_FLIST_DECLARE(entries, 0, pa_xfree); + pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) { pa_hashmap *h; @@ -69,8 +72,8 @@ pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_f } static void remove(pa_hashmap *h, struct hashmap_entry *e) { - assert(h); - assert(e); + pa_assert(h); + pa_assert(e); if (e->next) e->next->previous = e->previous; @@ -84,16 +87,18 @@ static void remove(pa_hashmap *h, struct hashmap_entry *e) { if (e->bucket_previous) e->bucket_previous->bucket_next = e->bucket_next; else { - assert(e->hash < h->size); + pa_assert(e->hash < h->size); h->data[e->hash] = e->bucket_next; } - pa_xfree(e); + if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0) + pa_xfree(e); + h->n_entries--; } void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), void *userdata) { - assert(h); + pa_assert(h); while (h->first_entry) { if (free_func) @@ -107,8 +112,8 @@ void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), v static struct hashmap_entry *get(pa_hashmap *h, unsigned hash, const void *key) { struct hashmap_entry *e; - assert(h); - assert(hash < h->size); + pa_assert(h); + pa_assert(hash < h->size); for (e = h->data[hash]; e; e = e->bucket_next) if (h->compare_func(e->key, key) == 0) @@ -120,14 +125,16 @@ static struct hashmap_entry *get(pa_hashmap *h, unsigned hash, const void *key) int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) { struct hashmap_entry *e; unsigned hash; - assert(h); + pa_assert(h); hash = h->hash_func(key) % h->size; if ((e = get(h, hash, key))) return -1; - e = pa_xnew(struct hashmap_entry, 1); + if (!(e = pa_flist_pop(PA_STATIC_FLIST_GET(entries)))) + e = pa_xnew(struct hashmap_entry, 1); + e->hash = hash; e->key = key; e->value = value; @@ -152,7 +159,7 @@ void* pa_hashmap_get(pa_hashmap *h, const void *key) { unsigned hash; struct hashmap_entry *e; - assert(h); + pa_assert(h); hash = h->hash_func(key) % h->size; @@ -167,7 +174,7 @@ void* pa_hashmap_remove(pa_hashmap *h, const void *key) { unsigned hash; void *data; - assert(h); + pa_assert(h); hash = h->hash_func(key) % h->size; @@ -184,8 +191,8 @@ unsigned pa_hashmap_size(pa_hashmap *h) { } void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) { - assert(h); - assert(state); + pa_assert(h); + pa_assert(state); if (!*state) *state = h->first_entry; @@ -207,7 +214,7 @@ void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) { void* pa_hashmap_steal_first(pa_hashmap *h) { void *data; - assert(h); + pa_assert(h); if (!h->first_entry) return NULL; @@ -218,7 +225,7 @@ void* pa_hashmap_steal_first(pa_hashmap *h) { } void *pa_hashmap_get_first(pa_hashmap *h) { - assert(h); + pa_assert(h); if (!h->first_entry) return NULL; diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h index 3ca2a4795..98df45021 100644 --- a/src/pulsecore/hashmap.h +++ b/src/pulsecore/hashmap.h @@ -32,11 +32,13 @@ typedef struct pa_hashmap pa_hashmap; +typedef void (*pa_free2_cb_t)(void *p, void *userdata); + /* Create a new hashmap. Use the specified functions for hashing and comparing objects in the map */ pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func); /* Free the hash table. Calls the specified function for every value in the table. The function may be NULL */ -void pa_hashmap_free(pa_hashmap*, void (*free_func)(void *p, void *userdata), void *userdata); +void pa_hashmap_free(pa_hashmap*, pa_free2_cb_t free_cb, void *userdata); /* Returns non-zero when the entry already exists */ int pa_hashmap_put(pa_hashmap *h, const void *key, void *value); diff --git a/src/pulsecore/hook-list.c b/src/pulsecore/hook-list.c index 4f8841876..3a6874c47 100644 --- a/src/pulsecore/hook-list.c +++ b/src/pulsecore/hook-list.c @@ -21,10 +21,16 @@ USA. ***/ -#include +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "hook-list.h" void pa_hook_init(pa_hook *hook, void *data) { - assert(hook); + pa_assert(hook); PA_LLIST_HEAD_INIT(pa_hook_slot, hook->slots); hook->last = NULL; @@ -33,8 +39,8 @@ void pa_hook_init(pa_hook *hook, void *data) { } static void slot_free(pa_hook *hook, pa_hook_slot *slot) { - assert(hook); - assert(slot); + pa_assert(hook); + pa_assert(slot); if (hook->last == slot) hook->last = slot->prev; @@ -45,8 +51,8 @@ static void slot_free(pa_hook *hook, pa_hook_slot *slot) { } void pa_hook_free(pa_hook *hook) { - assert(hook); - assert(!hook->firing); + pa_assert(hook); + pa_assert(!hook->firing); while (hook->slots) slot_free(hook, hook->slots); @@ -57,7 +63,7 @@ void pa_hook_free(pa_hook *hook) { pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *data) { pa_hook_slot *slot; - assert(cb); + pa_assert(cb); slot = pa_xnew(pa_hook_slot, 1); slot->hook = hook; @@ -72,8 +78,8 @@ pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *data) { } void pa_hook_slot_free(pa_hook_slot *slot) { - assert(slot); - assert(!slot->dead); + pa_assert(slot); + pa_assert(!slot->dead); if (slot->hook->firing > 0) { slot->dead = 1; @@ -86,7 +92,7 @@ pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) { pa_hook_slot *slot, *next; pa_hook_result_t result = PA_HOOK_OK; - assert(hook); + pa_assert(hook); hook->firing ++; diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c index 70ef7ba70..8a88471f2 100644 --- a/src/pulsecore/idxset.c +++ b/src/pulsecore/idxset.c @@ -27,32 +27,35 @@ #endif #include -#include #include #include #include +#include +#include #include "idxset.h" -typedef struct idxset_entry { +struct idxset_entry { void *data; uint32_t index; unsigned hash_value; struct idxset_entry *hash_prev, *hash_next; struct idxset_entry* iterate_prev, *iterate_next; -} idxset_entry; +}; struct pa_idxset { pa_hash_func_t hash_func; pa_compare_func_t compare_func; unsigned hash_table_size, n_entries; - idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail; + struct idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail; uint32_t index, start_index, array_size; }; +PA_STATIC_FLIST_DECLARE(entries, 0, pa_xfree); + unsigned pa_idxset_string_hash_func(const void *p) { unsigned hash = 0; const char *c; @@ -82,7 +85,7 @@ pa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_fun s->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; s->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; s->hash_table_size = 127; - s->hash_table = pa_xnew0(idxset_entry*, s->hash_table_size); + s->hash_table = pa_xnew0(struct idxset_entry*, s->hash_table_size); s->array = NULL; s->array_size = 0; s->index = 0; @@ -95,15 +98,17 @@ pa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_fun } void pa_idxset_free(pa_idxset *s, void (*free_func) (void *p, void *userdata), void *userdata) { - assert(s); + pa_assert(s); while (s->iterate_list_head) { - idxset_entry *e = s->iterate_list_head; + struct idxset_entry *e = s->iterate_list_head; s->iterate_list_head = s->iterate_list_head->iterate_next; if (free_func) free_func(e->data, userdata); - pa_xfree(e); + + if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0) + pa_xfree(e); } pa_xfree(s->hash_table); @@ -111,10 +116,10 @@ void pa_idxset_free(pa_idxset *s, void (*free_func) (void *p, void *userdata), v pa_xfree(s); } -static idxset_entry* hash_scan(pa_idxset *s, idxset_entry* e, const void *p) { - assert(p); +static struct idxset_entry* hash_scan(pa_idxset *s, struct idxset_entry* e, const void *p) { + pa_assert(p); - assert(s->compare_func); + pa_assert(s->compare_func); for (; e; e = e->hash_next) if (s->compare_func(e->data, p) == 0) return e; @@ -124,8 +129,10 @@ static idxset_entry* hash_scan(pa_idxset *s, idxset_entry* e, const void *p) { static void extend_array(pa_idxset *s, uint32_t idx) { uint32_t i, j, l; - idxset_entry** n; - assert(idx >= s->start_index); + struct idxset_entry** n; + + pa_assert(s); + pa_assert(idx >= s->start_index); if (idx < s->start_index + s->array_size) return; @@ -135,7 +142,7 @@ static void extend_array(pa_idxset *s, uint32_t idx) { break; l = idx - s->start_index - i + 100; - n = pa_xnew0(idxset_entry*, l); + n = pa_xnew0(struct idxset_entry*, l); for (j = 0; j < s->array_size-i; j++) n[j] = s->array[i+j]; @@ -147,7 +154,9 @@ static void extend_array(pa_idxset *s, uint32_t idx) { s->start_index += i; } -static idxset_entry** array_index(pa_idxset*s, uint32_t idx) { +static struct idxset_entry** array_index(pa_idxset*s, uint32_t idx) { + pa_assert(s); + if (idx >= s->start_index + s->array_size) return NULL; @@ -159,15 +168,15 @@ static idxset_entry** array_index(pa_idxset*s, uint32_t idx) { int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { unsigned h; - idxset_entry *e, **a; + struct idxset_entry *e, **a; - assert(s); - assert(p); + pa_assert(s); + pa_assert(p); - assert(s->hash_func); + pa_assert(s->hash_func); h = s->hash_func(p) % s->hash_table_size; - assert(s->hash_table); + pa_assert(s->hash_table); if ((e = hash_scan(s, s->hash_table[h], p))) { if (idx) *idx = e->index; @@ -175,7 +184,8 @@ int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { return -1; } - e = pa_xmalloc(sizeof(idxset_entry)); + if (!(e = pa_flist_pop(PA_STATIC_FLIST_GET(entries)))) + e = pa_xnew(struct idxset_entry, 1); e->data = p; e->index = s->index++; e->hash_value = h; @@ -190,23 +200,23 @@ int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { /* Insert into array */ extend_array(s, e->index); a = array_index(s, e->index); - assert(a && !*a); + pa_assert(a && !*a); *a = e; /* Insert into linked list */ e->iterate_next = NULL; e->iterate_prev = s->iterate_list_tail; if (s->iterate_list_tail) { - assert(s->iterate_list_head); + pa_assert(s->iterate_list_head); s->iterate_list_tail->iterate_next = e; } else { - assert(!s->iterate_list_head); + pa_assert(!s->iterate_list_head); s->iterate_list_head = e; } s->iterate_list_tail = e; s->n_entries++; - assert(s->n_entries >= 1); + pa_assert(s->n_entries >= 1); if (idx) *idx = e->index; @@ -215,8 +225,8 @@ int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { } void* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx) { - idxset_entry **a; - assert(s); + struct idxset_entry **a; + pa_assert(s); if (!(a = array_index(s, idx))) return NULL; @@ -229,13 +239,15 @@ void* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx) { void* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx) { unsigned h; - idxset_entry *e; - assert(s && p); + struct idxset_entry *e; - assert(s->hash_func); + pa_assert(s); + pa_assert(p); + + pa_assert(s->hash_func); h = s->hash_func(p) % s->hash_table_size; - assert(s->hash_table); + pa_assert(s->hash_table); if (!(e = hash_scan(s, s->hash_table[h], p))) return NULL; @@ -245,13 +257,15 @@ void* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx) { return e->data; } -static void remove_entry(pa_idxset *s, idxset_entry *e) { - idxset_entry **a; - assert(s && e); +static void remove_entry(pa_idxset *s, struct idxset_entry *e) { + struct idxset_entry **a; + + pa_assert(s); + pa_assert(e); /* Remove from array */ a = array_index(s, e->index); - assert(a && *a && *a == e); + pa_assert(a && *a && *a == e); *a = NULL; /* Remove from linked list */ @@ -274,17 +288,18 @@ static void remove_entry(pa_idxset *s, idxset_entry *e) { else s->hash_table[e->hash_value] = e->hash_next; - pa_xfree(e); + if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0) + pa_xfree(e); - assert(s->n_entries >= 1); + pa_assert(s->n_entries >= 1); s->n_entries--; } void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) { - idxset_entry **a; + struct idxset_entry **a; void *data; - assert(s); + pa_assert(s); if (!(a = array_index(s, idx))) return NULL; @@ -299,14 +314,16 @@ void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) { } void* pa_idxset_remove_by_data(pa_idxset*s, const void *data, uint32_t *idx) { - idxset_entry *e; + struct idxset_entry *e; unsigned h; void *r; - assert(s->hash_func); + pa_assert(s); + + pa_assert(s->hash_func); h = s->hash_func(data) % s->hash_table_size; - assert(s->hash_table); + pa_assert(s->hash_table); if (!(e = hash_scan(s, s->hash_table[h], data))) return NULL; @@ -320,8 +337,10 @@ void* pa_idxset_remove_by_data(pa_idxset*s, const void *data, uint32_t *idx) { } void* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx) { - idxset_entry **a, *e = NULL; - assert(s && idx); + struct idxset_entry **a, *e = NULL; + + pa_assert(s); + pa_assert(idx); if ((a = array_index(s, *idx)) && *a) e = (*a)->iterate_next; @@ -337,7 +356,7 @@ void* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx) { } void* pa_idxset_first(pa_idxset *s, uint32_t *idx) { - assert(s); + pa_assert(s); if (!s->iterate_list_head) return NULL; @@ -348,9 +367,10 @@ void* pa_idxset_first(pa_idxset *s, uint32_t *idx) { } void *pa_idxset_next(pa_idxset *s, uint32_t *idx) { - idxset_entry **a, *e = NULL; - assert(s); - assert(idx); + struct idxset_entry **a, *e = NULL; + + pa_assert(s); + pa_assert(idx); if ((a = array_index(s, *idx)) && *a) e = (*a)->iterate_next; @@ -365,13 +385,15 @@ void *pa_idxset_next(pa_idxset *s, uint32_t *idx) { } int pa_idxset_foreach(pa_idxset*s, int (*func)(void *p, uint32_t idx, int *del, void*userdata), void *userdata) { - idxset_entry *e; - assert(s && func); + struct idxset_entry *e; + + pa_assert(s); + pa_assert(func); e = s->iterate_list_head; while (e) { int del = 0, r; - idxset_entry *n = e->iterate_next; + struct idxset_entry *n = e->iterate_next; r = func(e->data, e->index, &del, userdata); @@ -388,12 +410,14 @@ int pa_idxset_foreach(pa_idxset*s, int (*func)(void *p, uint32_t idx, int *del, } unsigned pa_idxset_size(pa_idxset*s) { - assert(s); + pa_assert(s); + return s->n_entries; } int pa_idxset_isempty(pa_idxset *s) { - assert(s); + pa_assert(s); + return s->n_entries == 0; } diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h index 17a70f4ff..5b55cec20 100644 --- a/src/pulsecore/idxset.h +++ b/src/pulsecore/idxset.h @@ -44,11 +44,6 @@ int pa_idxset_trivial_compare_func(const void *a, const void *b); unsigned pa_idxset_string_hash_func(const void *p); int pa_idxset_string_compare_func(const void *a, const void *b); -#define PA_PTR_TO_UINT(p) ((unsigned int) (unsigned long) (p)) -#define PA_UINT_TO_PTR(u) ((void*) (unsigned long) (u)) -#define PA_PTR_TO_UINT32(p) ((uint32_t) PA_PTR_TO_UINT(p)) -#define PA_UINT32_TO_PTR(u) PA_UINT_TO_PTR(u) - typedef unsigned (*pa_hash_func_t)(const void *p); typedef int (*pa_compare_func_t)(const void *a, const void *b); diff --git a/src/pulsecore/inet_ntop.c b/src/pulsecore/inet_ntop.c index 302369f78..041bc09bc 100644 --- a/src/pulsecore/inet_ntop.c +++ b/src/pulsecore/inet_ntop.c @@ -47,7 +47,7 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { switch (af) { case AF_INET: - snprintf(dst, cnt, "%d.%d.%d.%d", + pa_snprintf(dst, cnt, "%d.%d.%d.%d", #ifdef WORDS_BIGENDIAN (int)(in->s_addr >> 24) & 0xff, (int)(in->s_addr >> 16) & 0xff, @@ -61,7 +61,7 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { #endif break; case AF_INET6: - snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x", + pa_snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x", in6->s6_addr[ 0] << 8 | in6->s6_addr[ 1], in6->s6_addr[ 2] << 8 | in6->s6_addr[ 3], in6->s6_addr[ 4] << 8 | in6->s6_addr[ 5], diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 6f58ae755..01f17ab32 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include #include @@ -47,6 +46,7 @@ #include #include #include +#include #include "iochannel.h" @@ -58,21 +58,21 @@ struct pa_iochannel { pa_iochannel_cb_t callback; void*userdata; - int readable; - int writable; - int hungup; + pa_bool_t readable; + pa_bool_t writable; + pa_bool_t hungup; - int no_close; + pa_bool_t no_close; pa_io_event* input_event, *output_event; }; static void enable_mainloop_sources(pa_iochannel *io) { - assert(io); + pa_assert(io); if (io->input_event == io->output_event && io->input_event) { pa_io_event_flags_t f = PA_IO_EVENT_NULL; - assert(io->input_event); + pa_assert(io->input_event); if (!io->readable) f |= PA_IO_EVENT_INPUT; @@ -90,28 +90,28 @@ static void enable_mainloop_sources(pa_iochannel *io) { static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { pa_iochannel *io = userdata; - int changed = 0; + pa_bool_t changed = FALSE; - assert(m); - assert(e); - assert(fd >= 0); - assert(userdata); + pa_assert(m); + pa_assert(e); + pa_assert(fd >= 0); + pa_assert(userdata); if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) { - io->hungup = 1; - changed = 1; + io->hungup = TRUE; + changed = TRUE; } if ((f & PA_IO_EVENT_INPUT) && !io->readable) { - io->readable = 1; - changed = 1; - assert(e == io->input_event); + io->readable = TRUE; + changed = TRUE; + pa_assert(e == io->input_event); } if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) { - io->writable = 1; - changed = 1; - assert(e == io->output_event); + io->writable = TRUE; + changed = TRUE; + pa_assert(e == io->output_event); } if (changed) { @@ -125,8 +125,8 @@ static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_fla pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) { pa_iochannel *io; - assert(m); - assert(ifd >= 0 || ofd >= 0); + pa_assert(m); + pa_assert(ifd >= 0 || ofd >= 0); io = pa_xnew(pa_iochannel, 1); io->ifd = ifd; @@ -136,26 +136,26 @@ pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) { io->userdata = NULL; io->callback = NULL; - io->readable = 0; - io->writable = 0; - io->hungup = 0; - io->no_close = 0; + io->readable = FALSE; + io->writable = FALSE; + io->hungup = FALSE; + io->no_close = FALSE; io->input_event = io->output_event = NULL; if (ifd == ofd) { - assert(ifd >= 0); - pa_make_nonblock_fd(io->ifd); + pa_assert(ifd >= 0); + pa_make_fd_nonblock(io->ifd); io->input_event = io->output_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT|PA_IO_EVENT_OUTPUT, callback, io); } else { if (ifd >= 0) { - pa_make_nonblock_fd(io->ifd); + pa_make_fd_nonblock(io->ifd); io->input_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT, callback, io); } if (ofd >= 0) { - pa_make_nonblock_fd(io->ofd); + pa_make_fd_nonblock(io->ofd); io->output_event = m->io_new(m, ofd, PA_IO_EVENT_OUTPUT, callback, io); } } @@ -164,7 +164,7 @@ pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) { } void pa_iochannel_free(pa_iochannel*io) { - assert(io); + pa_assert(io); if (io->input_event) io->mainloop->io_free(io->input_event); @@ -182,20 +182,20 @@ void pa_iochannel_free(pa_iochannel*io) { pa_xfree(io); } -int pa_iochannel_is_readable(pa_iochannel*io) { - assert(io); +pa_bool_t pa_iochannel_is_readable(pa_iochannel*io) { + pa_assert(io); return io->readable || io->hungup; } -int pa_iochannel_is_writable(pa_iochannel*io) { - assert(io); +pa_bool_t pa_iochannel_is_writable(pa_iochannel*io) { + pa_assert(io); return io->writable && !io->hungup; } -int pa_iochannel_is_hungup(pa_iochannel*io) { - assert(io); +pa_bool_t pa_iochannel_is_hungup(pa_iochannel*io) { + pa_assert(io); return io->hungup; } @@ -203,14 +203,13 @@ int pa_iochannel_is_hungup(pa_iochannel*io) { ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) { ssize_t r; - assert(io); - assert(data); - assert(l); - assert(io->ofd >= 0); + pa_assert(io); + pa_assert(data); + pa_assert(l); + pa_assert(io->ofd >= 0); - r = pa_write(io->ofd, data, l, &io->ofd_type); - if (r >= 0) { - io->writable = 0; + if ((r = pa_write(io->ofd, data, l, &io->ofd_type)) >= 0) { + io->writable = FALSE; enable_mainloop_sources(io); } @@ -220,13 +219,12 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) { ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { ssize_t r; - assert(io); - assert(data); - assert(io->ifd >= 0); + pa_assert(io); + pa_assert(data); + pa_assert(io->ifd >= 0); - r = pa_read(io->ifd, data, l, &io->ifd_type); - if (r >= 0) { - io->readable = 0; + if ((r = pa_read(io->ifd, data, l, &io->ifd_type)) >= 0) { + io->readable = FALSE; enable_mainloop_sources(io); } @@ -235,13 +233,13 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) { #ifdef HAVE_CREDS -int pa_iochannel_creds_supported(pa_iochannel *io) { +pa_bool_t pa_iochannel_creds_supported(pa_iochannel *io) { struct sockaddr_un sa; socklen_t l; - assert(io); - assert(io->ifd >= 0); - assert(io->ofd == io->ifd); + pa_assert(io); + pa_assert(io->ifd >= 0); + pa_assert(io->ofd == io->ifd); l = sizeof(sa); @@ -254,8 +252,8 @@ int pa_iochannel_creds_supported(pa_iochannel *io) { int pa_iochannel_creds_enable(pa_iochannel *io) { int t = 1; - assert(io); - assert(io->ifd >= 0); + pa_assert(io); + pa_assert(io->ifd >= 0); if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) { pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", pa_cstrerror(errno)); @@ -273,10 +271,10 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l struct ucred *u; struct cmsghdr *cmsg; - assert(io); - assert(data); - assert(l); - assert(io->ofd >= 0); + pa_assert(io); + pa_assert(data); + pa_assert(l); + pa_assert(io->ofd >= 0); memset(&iov, 0, sizeof(iov)); iov.iov_base = (void*) data; @@ -309,25 +307,25 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l mh.msg_flags = 0; if ((r = sendmsg(io->ofd, &mh, MSG_NOSIGNAL)) >= 0) { - io->writable = 0; + io->writable = FALSE; enable_mainloop_sources(io); } return r; } -ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *creds, int *creds_valid) { +ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *creds, pa_bool_t *creds_valid) { ssize_t r; struct msghdr mh; struct iovec iov; uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))]; - assert(io); - assert(data); - assert(l); - assert(io->ifd >= 0); - assert(creds); - assert(creds_valid); + pa_assert(io); + pa_assert(data); + pa_assert(l); + pa_assert(io->ifd >= 0); + pa_assert(creds); + pa_assert(creds_valid); memset(&iov, 0, sizeof(iov)); iov.iov_base = data; @@ -353,17 +351,17 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { struct ucred u; - assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))); + pa_assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))); memcpy(&u, CMSG_DATA(cmsg), sizeof(struct ucred)); creds->gid = u.gid; creds->uid = u.uid; - *creds_valid = 1; + *creds_valid = TRUE; break; } } - io->readable = 0; + io->readable = FALSE; enable_mainloop_sources(io); } @@ -373,46 +371,52 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr #endif /* HAVE_CREDS */ void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) { - assert(io); + pa_assert(io); io->callback = _callback; io->userdata = userdata; } -void pa_iochannel_set_noclose(pa_iochannel*io, int b) { - assert(io); +void pa_iochannel_set_noclose(pa_iochannel*io, pa_bool_t b) { + pa_assert(io); - io->no_close = b; + io->no_close = !!b; } void pa_iochannel_socket_peer_to_string(pa_iochannel*io, char*s, size_t l) { - assert(io); - assert(s); - assert(l); + pa_assert(io); + pa_assert(s); + pa_assert(l); pa_socket_peer_to_string(io->ifd, s, l); } int pa_iochannel_socket_set_rcvbuf(pa_iochannel *io, size_t l) { - assert(io); + pa_assert(io); return pa_socket_set_rcvbuf(io->ifd, l); } int pa_iochannel_socket_set_sndbuf(pa_iochannel *io, size_t l) { - assert(io); + pa_assert(io); return pa_socket_set_sndbuf(io->ofd, l); } pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io) { - assert(io); + pa_assert(io); return io->mainloop; } int pa_iochannel_get_recv_fd(pa_iochannel *io) { - assert(io); + pa_assert(io); return io->ifd; } + +int pa_iochannel_get_send_fd(pa_iochannel *io) { + pa_assert(io); + + return io->ofd; +} diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h index c22fefd30..c9794d996 100644 --- a/src/pulsecore/iochannel.h +++ b/src/pulsecore/iochannel.h @@ -25,10 +25,15 @@ USA. ***/ +#ifndef PACKAGE +#error "Please include config.h before including this file!" +#endif + #include #include #include +#include /* A wrapper around UNIX file descriptors for attaching them to the a main event loop. Everytime new data may be read or be written to @@ -54,20 +59,20 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l); ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l); #ifdef HAVE_CREDS -int pa_iochannel_creds_supported(pa_iochannel *io); +pa_bool_t pa_iochannel_creds_supported(pa_iochannel *io); int pa_iochannel_creds_enable(pa_iochannel *io); ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const pa_creds *ucred); -ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *ucred, int *creds_valid); +ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_creds *ucred, pa_bool_t *creds_valid); #endif -int pa_iochannel_is_readable(pa_iochannel*io); -int pa_iochannel_is_writable(pa_iochannel*io); -int pa_iochannel_is_hungup(pa_iochannel*io); +pa_bool_t pa_iochannel_is_readable(pa_iochannel*io); +pa_bool_t pa_iochannel_is_writable(pa_iochannel*io); +pa_bool_t pa_iochannel_is_hungup(pa_iochannel*io); /* Don't close the file descirptors when the io channel is freed. By * default the file descriptors are closed. */ -void pa_iochannel_set_noclose(pa_iochannel*io, int b); +void pa_iochannel_set_noclose(pa_iochannel*io, pa_bool_t b); /* Set the callback function that is called whenever data becomes available for read or write */ typedef void (*pa_iochannel_cb_t)(pa_iochannel*io, void *userdata); @@ -83,5 +88,6 @@ int pa_iochannel_socket_set_sndbuf(pa_iochannel*io, size_t l); pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io); int pa_iochannel_get_recv_fd(pa_iochannel *io); +int pa_iochannel_get_send_fd(pa_iochannel *io); #endif diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c index 07b60bee3..5fd2189b3 100644 --- a/src/pulsecore/ioline.c +++ b/src/pulsecore/ioline.c @@ -27,14 +27,16 @@ #include #include -#include #include #include #include +#include #include #include +#include +#include #include "ioline.h" @@ -42,10 +44,11 @@ #define READ_SIZE (1024) struct pa_ioline { + PA_REFCNT_DECLARE; + pa_iochannel *io; pa_defer_event *defer_event; pa_mainloop_api *mainloop; - int ref; int dead; char *wbuf; @@ -65,9 +68,10 @@ static void defer_callback(pa_mainloop_api*m, pa_defer_event*e, void *userdata); pa_ioline* pa_ioline_new(pa_iochannel *io) { pa_ioline *l; - assert(io); + pa_assert(io); l = pa_xnew(pa_ioline, 1); + PA_REFCNT_INIT(l); l->io = io; l->dead = 0; @@ -79,7 +83,6 @@ pa_ioline* pa_ioline_new(pa_iochannel *io) { l->callback = NULL; l->userdata = NULL; - l->ref = 1; l->mainloop = pa_iochannel_get_mainloop_api(io); @@ -94,7 +97,7 @@ pa_ioline* pa_ioline_new(pa_iochannel *io) { } static void ioline_free(pa_ioline *l) { - assert(l); + pa_assert(l); if (l->io) pa_iochannel_free(l->io); @@ -108,24 +111,24 @@ static void ioline_free(pa_ioline *l) { } void pa_ioline_unref(pa_ioline *l) { - assert(l); - assert(l->ref >= 1); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); - if ((--l->ref) <= 0) + if (PA_REFCNT_DEC(l) <= 0) ioline_free(l); } pa_ioline* pa_ioline_ref(pa_ioline *l) { - assert(l); - assert(l->ref >= 1); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); - l->ref++; + PA_REFCNT_INC(l); return l; } void pa_ioline_close(pa_ioline *l) { - assert(l); - assert(l->ref >= 1); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); l->dead = 1; @@ -146,9 +149,9 @@ void pa_ioline_close(pa_ioline *l) { void pa_ioline_puts(pa_ioline *l, const char *c) { size_t len; - assert(l); - assert(l->ref >= 1); - assert(c); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); + pa_assert(c); if (l->dead) return; @@ -158,7 +161,7 @@ void pa_ioline_puts(pa_ioline *l, const char *c) { len = BUFFER_LIMIT - l->wbuf_valid_length; if (len) { - assert(l->wbuf_length >= l->wbuf_valid_length); + pa_assert(l->wbuf_length >= l->wbuf_valid_length); /* In case the allocated buffer is too small, enlarge it. */ if (l->wbuf_valid_length + len > l->wbuf_length) { @@ -178,7 +181,7 @@ void pa_ioline_puts(pa_ioline *l, const char *c) { l->wbuf_index = 0; } - assert(l->wbuf_index + l->wbuf_valid_length + len <= l->wbuf_length); + pa_assert(l->wbuf_index + l->wbuf_valid_length + len <= l->wbuf_length); /* Append the new string */ memcpy(l->wbuf + l->wbuf_index + l->wbuf_valid_length, c, len); @@ -189,17 +192,17 @@ void pa_ioline_puts(pa_ioline *l, const char *c) { } void pa_ioline_set_callback(pa_ioline*l, void (*callback)(pa_ioline*io, const char *s, void *userdata), void *userdata) { - assert(l); - assert(l->ref >= 1); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); l->callback = callback; l->userdata = userdata; } static void failure(pa_ioline *l, int process_leftover) { - assert(l); - assert(l->ref >= 1); - assert(!l->dead); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); + pa_assert(!l->dead); if (process_leftover && l->rbuf_valid_length > 0) { /* Pass the last missing bit to the client */ @@ -220,7 +223,9 @@ static void failure(pa_ioline *l, int process_leftover) { } static void scan_for_lines(pa_ioline *l, size_t skip) { - assert(l && l->ref >= 1 && skip < l->rbuf_valid_length); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); + pa_assert(skip < l->rbuf_valid_length); while (!l->dead && l->rbuf_valid_length > skip) { char *e, *p; @@ -255,7 +260,8 @@ static void scan_for_lines(pa_ioline *l, size_t skip) { static int do_write(pa_ioline *l); static int do_read(pa_ioline *l) { - assert(l && l->ref >= 1); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); while (!l->dead && pa_iochannel_is_readable(l->io)) { ssize_t r; @@ -289,11 +295,11 @@ static int do_read(pa_ioline *l) { len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length; - assert(len >= READ_SIZE); + pa_assert(len >= READ_SIZE); /* Read some data */ if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) { - if (r < 0) { + if (r < 0 && errno != ECONNRESET) { pa_log("read(): %s", pa_cstrerror(errno)); failure(l, 0); } else @@ -314,13 +320,19 @@ static int do_read(pa_ioline *l) { /* Try to flush the buffer */ static int do_write(pa_ioline *l) { ssize_t r; - assert(l && l->ref >= 1); + + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); while (!l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length) { - if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) { - pa_log("write(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); + if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) <= 0) { + + if (r < 0 && errno != EPIPE) + pa_log("write(): %s", pa_cstrerror(errno)); + failure(l, 0); + return -1; } @@ -337,8 +349,8 @@ static int do_write(pa_ioline *l) { /* Try to flush read/write data */ static void do_work(pa_ioline *l) { - assert(l); - assert(l->ref >= 1); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); pa_ioline_ref(l); @@ -358,21 +370,28 @@ static void do_work(pa_ioline *l) { static void io_callback(pa_iochannel*io, void *userdata) { pa_ioline *l = userdata; - assert(io && l && l->ref >= 1); + + pa_assert(io); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); do_work(l); } static void defer_callback(pa_mainloop_api*m, pa_defer_event*e, void *userdata) { pa_ioline *l = userdata; - assert(l && l->ref >= 1 && l->mainloop == m && l->defer_event == e); + + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); + pa_assert(l->mainloop == m); + pa_assert(l->defer_event == e); do_work(l); } void pa_ioline_defer_close(pa_ioline *l) { - assert(l); - assert(l->ref >= 1); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); l->defer_close = 1; @@ -384,8 +403,8 @@ void pa_ioline_printf(pa_ioline *l, const char *format, ...) { char *t; va_list ap; - assert(l); - assert(l->ref >= 1); + pa_assert(l); + pa_assert(PA_REFCNT_VALUE(l) >= 1); va_start(ap, format); t = pa_vsprintf_malloc(format, ap); diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c index a240d2a0a..9b22e8f55 100644 --- a/src/pulsecore/ipacl.c +++ b/src/pulsecore/ipacl.c @@ -46,13 +46,13 @@ #include #endif -#include "winsock.h" - #include #include #include #include +#include +#include #ifndef HAVE_INET_PTON #include "inet_pton.h" @@ -77,7 +77,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { char *a; pa_ip_acl *acl; - assert(s); + pa_assert(s); acl = pa_xnew(pa_ip_acl, 1); PA_LLIST_HEAD_INIT(struct acl_entry, acl->entries); @@ -91,7 +91,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { *slash = 0; slash++; if (pa_atou(slash, &bits) < 0) { - pa_log("failed to parse number of bits: %s", slash); + pa_log_warn("Failed to parse number of bits: %s", slash); goto fail; } } else @@ -102,21 +102,21 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { e.bits = bits == (uint32_t) -1 ? 32 : (int) bits; if (e.bits > 32) { - pa_log("number of bits out of range: %i", e.bits); + pa_log_warn("Number of bits out of range: %i", e.bits); goto fail; } e.family = AF_INET; if (e.bits < 32 && (uint32_t) (ntohl(e.address_ipv4.s_addr) << e.bits) != 0) - pa_log_warn("WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); + pa_log_warn("Host part of ACL entry '%s/%u' is not zero!", a, e.bits); } else if (inet_pton(AF_INET6, a, &e.address_ipv6) > 0) { e.bits = bits == (uint32_t) -1 ? 128 : (int) bits; if (e.bits > 128) { - pa_log("number of bits out of range: %i", e.bits); + pa_log_warn("Number of bits out of range: %i", e.bits); goto fail; } e.family = AF_INET6; @@ -138,11 +138,11 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { } if (t) - pa_log_warn("WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); + pa_log_warn("Host part of ACL entry '%s/%u' is not zero!", a, e.bits); } } else { - pa_log("failed to parse address: %s", a); + pa_log_warn("Failed to parse address: %s", a); goto fail; } @@ -162,7 +162,7 @@ fail: } void pa_ip_acl_free(pa_ip_acl *acl) { - assert(acl); + pa_assert(acl); while (acl->entries) { struct acl_entry *e = acl->entries; @@ -178,8 +178,8 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { struct acl_entry *e; socklen_t salen; - assert(acl); - assert(fd >= 0); + pa_assert(acl); + pa_assert(fd >= 0); salen = sizeof(sa); if (getpeername(fd, (struct sockaddr*) &sa, &salen) < 0) diff --git a/src/pulsecore/llist.h b/src/pulsecore/llist.h index 8fc8e22b6..e62f15b40 100644 --- a/src/pulsecore/llist.h +++ b/src/pulsecore/llist.h @@ -24,77 +24,86 @@ USA. ***/ -#include +#include /* Some macros for maintaining doubly linked lists */ /* The head of the linked list. Use this in the structure that shall * contain the head of the linked list */ -#define PA_LLIST_HEAD(t,name) t *name +#define PA_LLIST_HEAD(t,name) \ + t *name /* The pointers in the linked list's items. Use this in the item structure */ -#define PA_LLIST_FIELDS(t) t *next, *prev +#define PA_LLIST_FIELDS(t) \ + t *next, *prev /* Initialize the list's head */ -#define PA_LLIST_HEAD_INIT(t,item) do { (item) = (t*) NULL; } while(0) +#define PA_LLIST_HEAD_INIT(t,item) \ + do { \ + (item) = (t*) NULL; } \ + while(0) /* Initialize a list item */ -#define PA_LLIST_INIT(t,item) do { \ - t *_item = (item); \ - assert(_item); \ - _item->prev = _item->next = NULL; \ - } while(0) +#define PA_LLIST_INIT(t,item) \ + do { \ + t *_item = (item); \ + pa_assert(_item); \ + _item->prev = _item->next = NULL; \ + } while(0) /* Prepend an item to the list */ -#define PA_LLIST_PREPEND(t,head,item) do { \ - t **_head = &(head), *_item = (item); \ - assert(_item); \ - if ((_item->next = *_head)) \ - _item->next->prev = _item; \ - _item->prev = NULL; \ - *_head = _item; \ - } while (0) +#define PA_LLIST_PREPEND(t,head,item) \ + do { \ + t **_head = &(head), *_item = (item); \ + pa_assert(_item); \ + if ((_item->next = *_head)) \ + _item->next->prev = _item; \ + _item->prev = NULL; \ + *_head = _item; \ + } while (0) /* Remove an item from the list */ -#define PA_LLIST_REMOVE(t,head,item) do { \ - t **_head = &(head), *_item = (item); \ - assert(_item); \ - if (_item->next) \ - _item->next->prev = _item->prev; \ - if (_item->prev) \ - _item->prev->next = _item->next; \ - else {\ - assert(*_head == _item); \ - *_head = _item->next; \ - } \ - _item->next = _item->prev = NULL; \ - } while(0) +#define PA_LLIST_REMOVE(t,head,item) \ + do { \ + t **_head = &(head), *_item = (item); \ + pa_assert(_item); \ + if (_item->next) \ + _item->next->prev = _item->prev; \ + if (_item->prev) \ + _item->prev->next = _item->next; \ + else { \ + pa_assert(*_head == _item); \ + *_head = _item->next; \ + } \ + _item->next = _item->prev = NULL; \ + } while(0) -#define PA_LLIST_FIND_HEAD(t,item,head) \ -do { \ - t **_head = (head), *_item = (item); \ - *_head = _item; \ - assert(_head); \ - while ((*_head)->prev) \ - *_head = (*_head)->prev; \ -} while (0) - -#define PA_LLIST_INSERT_AFTER(t,head,a,b) \ -do { \ - t **_head = &(head), *_a = (a), *_b = (b); \ - assert(_b); \ - if (!_a) { \ - if ((_b->next = *_head)) \ - _b->next->prev = _b; \ - _b->prev = NULL; \ - *_head = _b; \ - } else { \ - if ((_b->next = _a->next)) \ - _b->next->prev = _b; \ - _b->prev = _a; \ - _a->next = _b; \ - } \ -} while (0) +/* Find the head of the list */ +#define PA_LLIST_FIND_HEAD(t,item,head) \ + do { \ + t **_head = (head), *_item = (item); \ + *_head = _item; \ + pa_assert(_head); \ + while ((*_head)->prev) \ + *_head = (*_head)->prev; \ + } while (0) +/* Insert an item after another one (a = where, b = what) */ +#define PA_LLIST_INSERT_AFTER(t,head,a,b) \ + do { \ + t **_head = &(head), *_a = (a), *_b = (b); \ + pa_assert(_b); \ + if (!_a) { \ + if ((_b->next = *_head)) \ + _b->next->prev = _b; \ + _b->prev = NULL; \ + *_head = _b; \ + } else { \ + if ((_b->next = _a->next)) \ + _b->next->prev = _b; \ + _b->prev = _a; \ + _a->next = _b; \ + } \ + } while (0) #endif diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 0033adb91..c824e84d1 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -26,7 +26,6 @@ #include #endif -#include #include #include #include @@ -40,6 +39,7 @@ #include #include +#include #include #include "log.h" @@ -71,24 +71,30 @@ static const char level_to_char[] = { }; void pa_log_set_ident(const char *p) { - if (log_ident) - pa_xfree(log_ident); - if (log_ident_local) - pa_xfree(log_ident_local); + pa_xfree(log_ident); + pa_xfree(log_ident_local); log_ident = pa_xstrdup(p); - log_ident_local = pa_utf8_to_locale(log_ident); - if (!log_ident_local) + if (!(log_ident_local = pa_utf8_to_locale(log_ident))) log_ident_local = pa_xstrdup(log_ident); } +/* To make valgrind shut up. */ +static void ident_destructor(void) PA_GCC_DESTRUCTOR; +static void ident_destructor(void) { + pa_xfree(log_ident); + pa_xfree(log_ident_local); +} + void pa_log_set_maximal_level(pa_log_level_t l) { - assert(l < PA_LOG_LEVEL_MAX); + pa_assert(l < PA_LOG_LEVEL_MAX); + maximal_level = l; } void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t l, const char*s)) { - assert(t == PA_LOG_USER || !func); + pa_assert(t == PA_LOG_USER || !func); + log_target = t; user_log_func = func; } @@ -104,8 +110,8 @@ void pa_log_levelv_meta( const char *e; char *text, *t, *n, *location; - assert(level < PA_LOG_LEVEL_MAX); - assert(format); + pa_assert(level < PA_LOG_LEVEL_MAX); + pa_assert(format); if ((e = getenv(ENV_LOGLEVEL))) maximal_level = atoi(e); @@ -221,6 +227,7 @@ void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) { void pa_log_level(pa_log_level_t level, const char *format, ...) { va_list ap; + va_start(ap, format); pa_log_levelv_meta(level, NULL, 0, NULL, format, ap); va_end(ap); diff --git a/src/pulsecore/ltdl-helper.c b/src/pulsecore/ltdl-helper.c new file mode 100644 index 000000000..711396d8e --- /dev/null +++ b/src/pulsecore/ltdl-helper.c @@ -0,0 +1,64 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +#include +#include + +#include "ltdl-helper.h" + +pa_void_func_t pa_load_sym(lt_dlhandle handle, const char *module, const char *symbol) { + char *sn, *c; + pa_void_func_t f; + + pa_assert(handle); + pa_assert(module); + pa_assert(symbol); + + if ((f = ((pa_void_func_t) (long) lt_dlsym(handle, symbol)))) + return f; + + /* As the .la files might have been cleansed from the system, we should + * try with the ltdl prefix as well. */ + + sn = pa_sprintf_malloc("%s_LTX_%s", module, symbol); + + for (c = sn; *c; c++) + if (!isalnum(*c)) + *c = '_'; + + f = (pa_void_func_t) (long) lt_dlsym(handle, sn); + pa_xfree(sn); + + return f; +} diff --git a/src/pulsecore/ltdl-helper.h b/src/pulsecore/ltdl-helper.h new file mode 100644 index 000000000..5c7388a1e --- /dev/null +++ b/src/pulsecore/ltdl-helper.h @@ -0,0 +1,34 @@ +#ifndef foopulsecoreltdlhelperhfoo +#define foopulsecoreltdlhelperhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +typedef void (*pa_void_func_t)(void); + +pa_void_func_t pa_load_sym(lt_dlhandle handle, const char*module, const char *symbol); + +#endif + diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h new file mode 100644 index 000000000..c6bba4372 --- /dev/null +++ b/src/pulsecore/macro.h @@ -0,0 +1,149 @@ +#ifndef foopulsemacrohfoo +#define foopulsemacrohfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include +#include +#include +#include + +#include + +#ifndef PACKAGE +#error "Please include config.h before including this file!" +#endif + +#if defined(PAGE_SIZE) +#define PA_PAGE_SIZE ((size_t) PAGE_SIZE) +#elif defined(PAGESIZE) +#define PA_PAGE_SIZE ((size_t) PAGESIZE) +#elif defined(HAVE_SYSCONF) +#define PA_PAGE_SIZE ((size_t) (sysconf(_SC_PAGE_SIZE))) +#else +/* Let's hope it's like x86. */ +#define PA_PAGE_SIZE ((size_t) 4096) +#endif + +static inline size_t pa_align(size_t l) { + return (((l + sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*)); +} +#define PA_ALIGN(x) (pa_align(x)) + +static inline void* pa_page_align_ptr(const void *p) { + return (void*) (((size_t) p) & ~(PA_PAGE_SIZE-1)); +} +#define PA_PAGE_ALIGN_PTR(x) (pa_page_align_ptr(x)) + +static inline size_t pa_page_align(size_t l) { + return l & ~(PA_PAGE_SIZE-1); +} +#define PA_PAGE_ALIGN(x) (pa_page_align(x)) + +#define PA_ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0])) + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef CLAMP +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#endif + +/* This type is not intended to be used in exported APIs! Use classic "int" there! */ +#ifdef HAVE_STD_BOOL +typedef _Bool pa_bool_t; +#else +typedef int pa_bool_t; +#endif + +#ifndef FALSE +#define FALSE ((pa_bool_t) 0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#ifdef __GNUC__ +#define PA_PRETTY_FUNCTION __PRETTY_FUNCTION__ +#else +#define PA_PRETTY_FUNCTION "" +#endif + +#define pa_return_if_fail(expr) \ + do { \ + if (!(expr)) { \ + pa_log_debug("%s: Assertion <%s> failed.\n", PA_PRETTY_FUNCTION, #expr ); \ + return; \ + } \ + } while(0) + +#define pa_return_val_if_fail(expr, val) \ + do { \ + if (!(expr)) { \ + pa_log_debug("%s: Assertion <%s> failed.\n", PA_PRETTY_FUNCTION, #expr ); \ + return (val); \ + } \ + } while(0) + +#define pa_return_null_if_fail(expr) pa_return_val_if_fail(expr, NULL) + +#define pa_assert assert + +#define pa_assert_not_reached() pa_assert(!"Should not be reached.") + +/* An assert which guarantees side effects of x */ +#ifdef NDEBUG +#define pa_assert_se(x) x +#else +#define pa_assert_se(x) pa_assert(x) +#endif + +#define PA_PTR_TO_UINT(p) ((unsigned int) (unsigned long) (p)) +#define PA_UINT_TO_PTR(u) ((void*) (unsigned long) (u)) + +#define PA_PTR_TO_UINT32(p) ((uint32_t) PA_PTR_TO_UINT(p)) +#define PA_UINT32_TO_PTR(u) PA_UINT_TO_PTR((uint32_t) u) + +#define PA_PTR_TO_INT(p) ((int) PA_PTR_TO_UINT(p)) +#define PA_INT_TO_PTR(u) PA_UINT_TO_PTR((int) u) + +#define PA_PTR_TO_INT32(p) ((int32_t) PA_PTR_TO_UINT(p)) +#define PA_INT32_TO_PTR(u) PA_UINT_TO_PTR((int32_t) u) + +#ifdef OS_IS_WIN32 +#define PA_PATH_SEP "\\" +#define PA_PATH_SEP_CHAR '\\' +#else +#define PA_PATH_SEP "/" +#define PA_PATH_SEP_CHAR '/' +#endif + +#endif diff --git a/src/pulsecore/mcalign.c b/src/pulsecore/mcalign.c index dd1d71f3c..8ca7c962d 100644 --- a/src/pulsecore/mcalign.c +++ b/src/pulsecore/mcalign.c @@ -27,10 +27,10 @@ #include #include -#include #include #include +#include #include "mcalign.h" @@ -41,7 +41,7 @@ struct pa_mcalign { pa_mcalign *pa_mcalign_new(size_t base) { pa_mcalign *m; - assert(base); + pa_assert(base); m = pa_xnew(pa_mcalign, 1); @@ -53,7 +53,7 @@ pa_mcalign *pa_mcalign_new(size_t base) { } void pa_mcalign_free(pa_mcalign *m) { - assert(m); + pa_assert(m); if (m->leftover.memblock) pa_memblock_unref(m->leftover.memblock); @@ -65,13 +65,13 @@ void pa_mcalign_free(pa_mcalign *m) { } void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { - assert(m); - assert(c); + pa_assert(m); + pa_assert(c); - assert(c->memblock); - assert(c->length > 0); + pa_assert(c->memblock); + pa_assert(c->length > 0); - assert(!m->current.memblock); + pa_assert(!m->current.memblock); /* Append to the leftover memory block */ if (m->leftover.memblock) { @@ -91,9 +91,10 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { } else { size_t l; + void *lo_data, *m_data; /* We have to copy */ - assert(m->leftover.length < m->base); + pa_assert(m->leftover.length < m->base); l = m->base - m->leftover.length; if (l > c->length) @@ -102,10 +103,15 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { /* Can we use the current block? */ pa_memchunk_make_writable(&m->leftover, m->base); - memcpy((uint8_t*) m->leftover.memblock->data + m->leftover.index + m->leftover.length, (uint8_t*) c->memblock->data + c->index, l); + lo_data = pa_memblock_acquire(m->leftover.memblock); + m_data = pa_memblock_acquire(c->memblock); + memcpy((uint8_t*) lo_data + m->leftover.index + m->leftover.length, (uint8_t*) m_data + c->index, l); + pa_memblock_release(m->leftover.memblock); + pa_memblock_release(c->memblock); m->leftover.length += l; - assert(m->leftover.length <= m->base && m->leftover.length <= m->leftover.memblock->length); + pa_assert(m->leftover.length <= m->base); + pa_assert(m->leftover.length <= pa_memblock_get_length(m->leftover.memblock)); if (c->length > l) { /* Save the remainder of the memory block */ @@ -128,12 +134,13 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) { } int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) { - assert(m); - assert(c); + pa_assert(m); + pa_assert(c); /* First test if there's a leftover memory block available */ if (m->leftover.memblock) { - assert(m->leftover.length > 0 && m->leftover.length <= m->base); + pa_assert(m->leftover.length > 0); + pa_assert(m->leftover.length <= m->base); /* The leftover memory block is not yet complete */ if (m->leftover.length < m->base) @@ -155,13 +162,13 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) { /* Now let's see if there is other data available */ if (m->current.memblock) { size_t l; - assert(m->current.length >= m->base); + pa_assert(m->current.length >= m->base); /* The length of the returned memory block */ l = m->current.length; l /= m->base; l *= m->base; - assert(l > 0); + pa_assert(l > 0); /* Prepare the returned block */ *c = m->current; @@ -169,7 +176,7 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) { c->length = l; /* Drop that from the current memory block */ - assert(l <= m->current.length); + pa_assert(l <= m->current.length); m->current.index += l; m->current.length -= l; @@ -178,7 +185,7 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) { pa_memblock_unref(m->current.memblock); else { /* Move the raimainder to leftover */ - assert(m->current.length < m->base && !m->leftover.memblock); + pa_assert(m->current.length < m->base && !m->leftover.memblock); m->leftover = m->current; } @@ -194,10 +201,10 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) { } size_t pa_mcalign_csize(pa_mcalign *m, size_t l) { - assert(m); - assert(l > 0); + pa_assert(m); + pa_assert(l > 0); - assert(!m->current.memblock); + pa_assert(!m->current.memblock); if (m->leftover.memblock) l += m->leftover.length; diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 6f09a906a..99b5a13f0 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -14,7 +14,7 @@ PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + Lesser General Public License for more details You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software @@ -28,15 +28,21 @@ #include #include -#include #include #include +#include +#include #include +#include #include #include #include +#include +#include +#include +#include #include "memblock.h" @@ -48,6 +54,32 @@ #define PA_MEMIMPORT_SLOTS_MAX 128 #define PA_MEMIMPORT_SEGMENTS_MAX 16 +struct pa_memblock { + PA_REFCNT_DECLARE; /* the reference counter */ + pa_mempool *pool; + + pa_memblock_type_t type; + int read_only; /* boolean */ + + pa_atomic_ptr_t data; + size_t length; + + pa_atomic_t n_acquired; + pa_atomic_t please_signal; + + union { + struct { + /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ + pa_free_cb_t free_cb; + } user; + + struct { + uint32_t id; + pa_memimport_segment *segment; + } imported; + } per_type; +}; + struct pa_memimport_segment { pa_memimport *import; pa_shm memory; @@ -55,6 +87,8 @@ struct pa_memimport_segment { }; struct pa_memimport { + pa_mutex *mutex; + pa_mempool *pool; pa_hashmap *segments; pa_hashmap *blocks; @@ -73,9 +107,11 @@ struct memexport_slot { }; struct pa_memexport { + pa_mutex *mutex; pa_mempool *pool; struct memexport_slot slots[PA_MEMEXPORT_SLOTS_MAX]; + PA_LLIST_HEAD(struct memexport_slot, free_slots); PA_LLIST_HEAD(struct memexport_slot, used_slots); unsigned n_init; @@ -95,24 +131,32 @@ struct mempool_slot { }; struct pa_mempool { + pa_semaphore *semaphore; + pa_mutex *mutex; + pa_shm memory; size_t block_size; - unsigned n_blocks, n_init; + unsigned n_blocks; + + pa_atomic_t n_init; PA_LLIST_HEAD(pa_memimport, imports); PA_LLIST_HEAD(pa_memexport, exports); /* A list of free slots that may be reused */ - PA_LLIST_HEAD(struct mempool_slot, free_slots); + pa_flist *free_slots; pa_mempool_stat stat; }; static void segment_detach(pa_memimport_segment *seg); +PA_STATIC_FLIST_DECLARE(unused_memblocks, 0, pa_xfree); + +/* No lock necessary */ static void stat_add(pa_memblock*b) { - assert(b); - assert(b->pool); + pa_assert(b); + pa_assert(b->pool); pa_atomic_inc(&b->pool->stat.n_allocated); pa_atomic_add(&b->pool->stat.allocated_size, b->length); @@ -129,19 +173,20 @@ static void stat_add(pa_memblock*b) { pa_atomic_inc(&b->pool->stat.n_accumulated_by_type[b->type]); } +/* No lock necessary */ static void stat_remove(pa_memblock *b) { - assert(b); - assert(b->pool); + pa_assert(b); + pa_assert(b->pool); - assert(pa_atomic_load(&b->pool->stat.n_allocated) > 0); - assert(pa_atomic_load(&b->pool->stat.allocated_size) >= (int) b->length); + pa_assert(pa_atomic_load(&b->pool->stat.n_allocated) > 0); + pa_assert(pa_atomic_load(&b->pool->stat.allocated_size) >= (int) b->length); pa_atomic_dec(&b->pool->stat.n_allocated); pa_atomic_sub(&b->pool->stat.allocated_size, b->length); if (b->type == PA_MEMBLOCK_IMPORTED) { - assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); - assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); + pa_assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); + pa_assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); pa_atomic_dec(&b->pool->stat.n_imported); pa_atomic_sub(&b->pool->stat.imported_size, b->length); @@ -152,11 +197,12 @@ static void stat_remove(pa_memblock *b) { static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length); +/* No lock necessary */ pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) { pa_memblock *b; - assert(p); - assert(length > 0); + pa_assert(p); + pa_assert(length > 0); if (!(b = pa_memblock_new_pool(p, length))) b = memblock_new_appended(p, length); @@ -164,56 +210,75 @@ pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) { return b; } +/* No lock necessary */ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) { pa_memblock *b; - assert(p); - assert(length > 0); + pa_assert(p); + pa_assert(length > 0); - b = pa_xmalloc(sizeof(pa_memblock) + length); + /* If -1 is passed as length we choose the size for the caller. */ + + if (length == (size_t) -1) + length = p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) - PA_ALIGN(sizeof(pa_memblock)); + + b = pa_xmalloc(PA_ALIGN(sizeof(pa_memblock)) + length); + PA_REFCNT_INIT(b); + b->pool = p; b->type = PA_MEMBLOCK_APPENDED; b->read_only = 0; - PA_REFCNT_INIT(b); + pa_atomic_ptr_store(&b->data, (uint8_t*) b + PA_ALIGN(sizeof(pa_memblock))); b->length = length; - b->data = (uint8_t*) b + sizeof(pa_memblock); - b->pool = p; + pa_atomic_store(&b->n_acquired, 0); + pa_atomic_store(&b->please_signal, 0); stat_add(b); return b; } +/* No lock necessary */ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { struct mempool_slot *slot; - assert(p); + pa_assert(p); - if (p->free_slots) { - slot = p->free_slots; - PA_LLIST_REMOVE(struct mempool_slot, p->free_slots, slot); - } else if (p->n_init < p->n_blocks) - slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * p->n_init++)); - else { - pa_log_debug("Pool full"); - pa_atomic_inc(&p->stat.n_pool_full); - return NULL; + if (!(slot = pa_flist_pop(p->free_slots))) { + int idx; + + /* The free list was empty, we have to allocate a new entry */ + + if ((unsigned) (idx = pa_atomic_inc(&p->n_init)) >= p->n_blocks) + pa_atomic_dec(&p->n_init); + else + slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * idx)); + + if (!slot) { + pa_log_debug("Pool full"); + pa_atomic_inc(&p->stat.n_pool_full); + return NULL; + } } return slot; } +/* No lock necessary */ static void* mempool_slot_data(struct mempool_slot *slot) { - assert(slot); + pa_assert(slot); - return (uint8_t*) slot + sizeof(struct mempool_slot); + return (uint8_t*) slot + PA_ALIGN(sizeof(struct mempool_slot)); } +/* No lock necessary */ static unsigned mempool_slot_idx(pa_mempool *p, void *ptr) { - assert(p); - assert((uint8_t*) ptr >= (uint8_t*) p->memory.ptr); - assert((uint8_t*) ptr < (uint8_t*) p->memory.ptr + p->memory.size); + pa_assert(p); + + pa_assert((uint8_t*) ptr >= (uint8_t*) p->memory.ptr); + pa_assert((uint8_t*) ptr < (uint8_t*) p->memory.ptr + p->memory.size); return ((uint8_t*) ptr - (uint8_t*) p->memory.ptr) / p->block_size; } +/* No lock necessary */ static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) { unsigned idx; @@ -223,189 +288,321 @@ static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) { return (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (idx * p->block_size)); } +/* No lock necessary */ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) { pa_memblock *b = NULL; struct mempool_slot *slot; - assert(p); - assert(length > 0); + pa_assert(p); + pa_assert(length > 0); - if (p->block_size - sizeof(struct mempool_slot) >= sizeof(pa_memblock) + length) { + /* If -1 is passed as length we choose the size for the caller: we + * take the largest size that fits in one of our slots. */ + + if (length == (size_t) -1) + length = pa_mempool_block_size_max(p); + + if (p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) >= PA_ALIGN(sizeof(pa_memblock)) + length) { if (!(slot = mempool_allocate_slot(p))) return NULL; b = mempool_slot_data(slot); b->type = PA_MEMBLOCK_POOL; - b->data = (uint8_t*) b + sizeof(pa_memblock); + pa_atomic_ptr_store(&b->data, (uint8_t*) b + PA_ALIGN(sizeof(pa_memblock))); - } else if (p->block_size - sizeof(struct mempool_slot) >= length) { + } else if (p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) >= length) { if (!(slot = mempool_allocate_slot(p))) return NULL; - b = pa_xnew(pa_memblock, 1); + if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks)))) + b = pa_xnew(pa_memblock, 1); + b->type = PA_MEMBLOCK_POOL_EXTERNAL; - b->data = mempool_slot_data(slot); + pa_atomic_ptr_store(&b->data, mempool_slot_data(slot)); + } else { - pa_log_debug("Memory block too large for pool: %u > %u", length, p->block_size - sizeof(struct mempool_slot)); + pa_log_debug("Memory block too large for pool: %lu > %lu", (unsigned long) length, (unsigned long) (p->block_size - PA_ALIGN(sizeof(struct mempool_slot)))); pa_atomic_inc(&p->stat.n_too_large_for_pool); return NULL; } - b->length = length; - b->read_only = 0; PA_REFCNT_INIT(b); b->pool = p; + b->read_only = 0; + b->length = length; + pa_atomic_store(&b->n_acquired, 0); + pa_atomic_store(&b->please_signal, 0); stat_add(b); return b; } +/* No lock necessary */ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int read_only) { pa_memblock *b; - assert(p); - assert(d); - assert(length > 0); + pa_assert(p); + pa_assert(d); + pa_assert(length != (size_t) -1); + pa_assert(length > 0); - b = pa_xnew(pa_memblock, 1); + if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks)))) + b = pa_xnew(pa_memblock, 1); + PA_REFCNT_INIT(b); + b->pool = p; b->type = PA_MEMBLOCK_FIXED; b->read_only = read_only; - PA_REFCNT_INIT(b); + pa_atomic_ptr_store(&b->data, d); b->length = length; - b->data = d; - b->pool = p; + pa_atomic_store(&b->n_acquired, 0); + pa_atomic_store(&b->please_signal, 0); stat_add(b); return b; } +/* No lock necessary */ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (*free_cb)(void *p), int read_only) { pa_memblock *b; - assert(p); - assert(d); - assert(length > 0); - assert(free_cb); + pa_assert(p); + pa_assert(d); + pa_assert(length > 0); + pa_assert(length != (size_t) -1); + pa_assert(free_cb); - b = pa_xnew(pa_memblock, 1); + if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks)))) + b = pa_xnew(pa_memblock, 1); + PA_REFCNT_INIT(b); + b->pool = p; b->type = PA_MEMBLOCK_USER; b->read_only = read_only; - PA_REFCNT_INIT(b); + pa_atomic_ptr_store(&b->data, d); b->length = length; - b->data = d; + pa_atomic_store(&b->n_acquired, 0); + pa_atomic_store(&b->please_signal, 0); + b->per_type.user.free_cb = free_cb; - b->pool = p; stat_add(b); return b; } +/* No lock necessary */ +int pa_memblock_is_read_only(pa_memblock *b) { + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) > 0); + + return b->read_only && PA_REFCNT_VALUE(b) == 1; +} + +/* No lock necessary */ +int pa_memblock_ref_is_one(pa_memblock *b) { + int r; + + pa_assert(b); + + r = PA_REFCNT_VALUE(b); + pa_assert(r > 0); + + return r == 1; +} + +/* No lock necessary */ +void* pa_memblock_acquire(pa_memblock *b) { + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) > 0); + + pa_atomic_inc(&b->n_acquired); + + return pa_atomic_ptr_load(&b->data); +} + +/* No lock necessary, in corner cases locks by its own */ +void pa_memblock_release(pa_memblock *b) { + int r; + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) > 0); + + r = pa_atomic_dec(&b->n_acquired); + pa_assert(r >= 1); + + /* Signal a waiting thread that this memblock is no longer used */ + if (r == 1 && pa_atomic_load(&b->please_signal)) + pa_semaphore_post(b->pool->semaphore); +} + +size_t pa_memblock_get_length(pa_memblock *b) { + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) > 0); + + return b->length; +} + +pa_mempool* pa_memblock_get_pool(pa_memblock *b) { + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) > 0); + + return b->pool; +} + +/* No lock necessary */ pa_memblock* pa_memblock_ref(pa_memblock*b) { - assert(b); - assert(PA_REFCNT_VALUE(b) > 0); + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) > 0); PA_REFCNT_INC(b); return b; } -void pa_memblock_unref(pa_memblock*b) { - assert(b); - assert(PA_REFCNT_VALUE(b) > 0); +static void memblock_free(pa_memblock *b) { + pa_assert(b); - if (PA_REFCNT_DEC(b) > 0) - return; + pa_assert(pa_atomic_load(&b->n_acquired) == 0); stat_remove(b); switch (b->type) { case PA_MEMBLOCK_USER : - assert(b->per_type.user.free_cb); - b->per_type.user.free_cb(b->data); + pa_assert(b->per_type.user.free_cb); + b->per_type.user.free_cb(pa_atomic_ptr_load(&b->data)); /* Fall through */ case PA_MEMBLOCK_FIXED: case PA_MEMBLOCK_APPENDED : - pa_xfree(b); + if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0) + pa_xfree(b); + break; case PA_MEMBLOCK_IMPORTED : { pa_memimport_segment *segment; + pa_memimport *import; + + /* FIXME! This should be implemented lock-free */ segment = b->per_type.imported.segment; - assert(segment); - assert(segment->import); - - pa_hashmap_remove(segment->import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); - segment->import->release_cb(segment->import, b->per_type.imported.id, segment->import->userdata); + pa_assert(segment); + import = segment->import; + pa_assert(import); + pa_mutex_lock(import->mutex); + pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id)); if (-- segment->n_blocks <= 0) segment_detach(segment); - pa_xfree(b); + pa_mutex_unlock(import->mutex); + + import->release_cb(import, b->per_type.imported.id, import->userdata); + + if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0) + pa_xfree(b); break; } case PA_MEMBLOCK_POOL_EXTERNAL: case PA_MEMBLOCK_POOL: { struct mempool_slot *slot; + int call_free; - slot = mempool_slot_by_ptr(b->pool, b->data); - assert(slot); + slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data)); + pa_assert(slot); - PA_LLIST_PREPEND(struct mempool_slot, b->pool->free_slots, slot); + call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL; - if (b->type == PA_MEMBLOCK_POOL_EXTERNAL) - pa_xfree(b); + /* The free list dimensions should easily allow all slots + * to fit in, hence try harder if pushing this slot into + * the free list fails */ + while (pa_flist_push(b->pool->free_slots, slot) < 0) + ; + + if (call_free) + if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0) + pa_xfree(b); break; } case PA_MEMBLOCK_TYPE_MAX: default: - abort(); + pa_assert_not_reached(); } } +/* No lock necessary */ +void pa_memblock_unref(pa_memblock*b) { + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) > 0); + + if (PA_REFCNT_DEC(b) > 0) + return; + + memblock_free(b); +} + +/* Self locked */ +static void memblock_wait(pa_memblock *b) { + pa_assert(b); + + if (pa_atomic_load(&b->n_acquired) > 0) { + /* We need to wait until all threads gave up access to the + * memory block before we can go on. Unfortunately this means + * that we have to lock and wait here. Sniff! */ + + pa_atomic_inc(&b->please_signal); + + while (pa_atomic_load(&b->n_acquired) > 0) + pa_semaphore_wait(b->pool->semaphore); + + pa_atomic_dec(&b->please_signal); + } +} + +/* No lock necessary. This function is not multiple caller safe! */ static void memblock_make_local(pa_memblock *b) { - assert(b); + pa_assert(b); pa_atomic_dec(&b->pool->stat.n_allocated_by_type[b->type]); - if (b->length <= b->pool->block_size - sizeof(struct mempool_slot)) { + if (b->length <= b->pool->block_size - PA_ALIGN(sizeof(struct mempool_slot))) { struct mempool_slot *slot; if ((slot = mempool_allocate_slot(b->pool))) { void *new_data; /* We can move it into a local pool, perfect! */ + new_data = mempool_slot_data(slot); + memcpy(new_data, pa_atomic_ptr_load(&b->data), b->length); + pa_atomic_ptr_store(&b->data, new_data); + b->type = PA_MEMBLOCK_POOL_EXTERNAL; b->read_only = 0; - new_data = mempool_slot_data(slot); - memcpy(new_data, b->data, b->length); - b->data = new_data; goto finish; } } /* Humm, not enough space in the pool, so lets allocate the memory with malloc() */ - b->type = PA_MEMBLOCK_USER; b->per_type.user.free_cb = pa_xfree; + pa_atomic_ptr_store(&b->data, pa_xmemdup(pa_atomic_ptr_load(&b->data), b->length)); + + b->type = PA_MEMBLOCK_USER; b->read_only = 0; - b->data = pa_xmemdup(b->data, b->length); finish: pa_atomic_inc(&b->pool->stat.n_allocated_by_type[b->type]); pa_atomic_inc(&b->pool->stat.n_accumulated_by_type[b->type]); + memblock_wait(b); } +/* No lock necessary. This function is not multiple caller safe*/ void pa_memblock_unref_fixed(pa_memblock *b) { - assert(b); - assert(PA_REFCNT_VALUE(b) > 0); - assert(b->type == PA_MEMBLOCK_FIXED); + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) > 0); + pa_assert(b->type == PA_MEMBLOCK_FIXED); if (PA_REFCNT_VALUE(b) > 1) memblock_make_local(b); @@ -413,20 +610,37 @@ void pa_memblock_unref_fixed(pa_memblock *b) { pa_memblock_unref(b); } +/* No lock necessary. */ +pa_memblock *pa_memblock_will_need(pa_memblock *b) { + void *p; + + pa_assert(b); + pa_assert(PA_REFCNT_VALUE(b) > 0); + + p = pa_memblock_acquire(b); + pa_will_need(p, b->length); + pa_memblock_release(b); + + return b; +} + +/* Self-locked. This function is not multiple-caller safe */ static void memblock_replace_import(pa_memblock *b) { pa_memimport_segment *seg; - assert(b); - assert(b->type == PA_MEMBLOCK_IMPORTED); + pa_assert(b); + pa_assert(b->type == PA_MEMBLOCK_IMPORTED); - assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); - assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); + pa_assert(pa_atomic_load(&b->pool->stat.n_imported) > 0); + pa_assert(pa_atomic_load(&b->pool->stat.imported_size) >= (int) b->length); pa_atomic_dec(&b->pool->stat.n_imported); pa_atomic_sub(&b->pool->stat.imported_size, b->length); seg = b->per_type.imported.segment; - assert(seg); - assert(seg->import); + pa_assert(seg); + pa_assert(seg->import); + + pa_mutex_lock(seg->import->mutex); pa_hashmap_remove( seg->import->blocks, @@ -434,51 +648,49 @@ static void memblock_replace_import(pa_memblock *b) { memblock_make_local(b); - if (-- seg->n_blocks <= 0) + if (-- seg->n_blocks <= 0) { + pa_mutex_unlock(seg->import->mutex); segment_detach(seg); + } else + pa_mutex_unlock(seg->import->mutex); } pa_mempool* pa_mempool_new(int shared) { - size_t ps; pa_mempool *p; p = pa_xnew(pa_mempool, 1); -#ifdef HAVE_SYSCONF - ps = (size_t) sysconf(_SC_PAGESIZE); -#elif defined(PAGE_SIZE) - ps = (size_t) PAGE_SIZE; -#else - ps = 4096; /* Let's hope it's like x86. */ -#endif + p->mutex = pa_mutex_new(TRUE, TRUE); + p->semaphore = pa_semaphore_new(0); - p->block_size = (PA_MEMPOOL_SLOT_SIZE/ps)*ps; - - if (p->block_size < ps) - p->block_size = ps; + p->block_size = PA_PAGE_ALIGN(PA_MEMPOOL_SLOT_SIZE); + if (p->block_size < PA_PAGE_SIZE) + p->block_size = PA_PAGE_SIZE; p->n_blocks = PA_MEMPOOL_SLOTS_MAX; - assert(p->block_size > sizeof(struct mempool_slot)); + pa_assert(p->block_size > PA_ALIGN(sizeof(struct mempool_slot))); if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) { pa_xfree(p); return NULL; } - p->n_init = 0; + memset(&p->stat, 0, sizeof(p->stat)); + pa_atomic_store(&p->n_init, 0); PA_LLIST_HEAD_INIT(pa_memimport, p->imports); PA_LLIST_HEAD_INIT(pa_memexport, p->exports); - PA_LLIST_HEAD_INIT(struct mempool_slot, p->free_slots); - memset(&p->stat, 0, sizeof(p->stat)); + p->free_slots = pa_flist_new(p->n_blocks*2); return p; } void pa_mempool_free(pa_mempool *p) { - assert(p); + pa_assert(p); + + pa_mutex_lock(p->mutex); while (p->imports) pa_memimport_free(p->imports); @@ -486,30 +698,65 @@ void pa_mempool_free(pa_mempool *p) { while (p->exports) pa_memexport_free(p->exports); - if (pa_atomic_load(&p->stat.n_allocated) > 0) - pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!"); + pa_mutex_unlock(p->mutex); + + pa_flist_free(p->free_slots, NULL); + + if (pa_atomic_load(&p->stat.n_allocated) > 0) { +/* raise(SIGTRAP); */ + pa_log_warn("Memory pool destroyed but not all memory blocks freed! %u remain.", pa_atomic_load(&p->stat.n_allocated)); + } pa_shm_free(&p->memory); + + pa_mutex_free(p->mutex); + pa_semaphore_free(p->semaphore); + pa_xfree(p); } +/* No lock necessary */ const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p) { - assert(p); + pa_assert(p); return &p->stat; } -void pa_mempool_vacuum(pa_mempool *p) { - struct mempool_slot *slot; +/* No lock necessary */ +size_t pa_mempool_block_size_max(pa_mempool *p) { + pa_assert(p); - assert(p); - - for (slot = p->free_slots; slot; slot = slot->next) - pa_shm_punch(&p->memory, (uint8_t*) slot + sizeof(struct mempool_slot) - (uint8_t*) p->memory.ptr, p->block_size - sizeof(struct mempool_slot)); + return p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) - PA_ALIGN(sizeof(pa_memblock)); } +/* No lock necessary */ +void pa_mempool_vacuum(pa_mempool *p) { + struct mempool_slot *slot; + pa_flist *list; + + pa_assert(p); + + list = pa_flist_new(p->n_blocks*2); + + while ((slot = pa_flist_pop(p->free_slots))) + while (pa_flist_push(list, slot) < 0) + ; + + while ((slot = pa_flist_pop(list))) { + pa_shm_punch(&p->memory, + (uint8_t*) slot - (uint8_t*) p->memory.ptr + PA_ALIGN(sizeof(struct mempool_slot)), + p->block_size - PA_ALIGN(sizeof(struct mempool_slot))); + + while (pa_flist_push(p->free_slots, slot)) + ; + } + + pa_flist_free(list, NULL); +} + +/* No lock necessary */ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) { - assert(p); + pa_assert(p); if (!p->memory.shared) return -1; @@ -519,8 +766,9 @@ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) { return 0; } +/* No lock necessary */ int pa_mempool_is_shared(pa_mempool *p) { - assert(p); + pa_assert(p); return !!p->memory.shared; } @@ -529,22 +777,27 @@ int pa_mempool_is_shared(pa_mempool *p) { pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void *userdata) { pa_memimport *i; - assert(p); - assert(cb); + pa_assert(p); + pa_assert(cb); i = pa_xnew(pa_memimport, 1); + i->mutex = pa_mutex_new(TRUE, TRUE); i->pool = p; i->segments = pa_hashmap_new(NULL, NULL); i->blocks = pa_hashmap_new(NULL, NULL); i->release_cb = cb; i->userdata = userdata; + pa_mutex_lock(p->mutex); PA_LLIST_PREPEND(pa_memimport, p->imports, i); + pa_mutex_unlock(p->mutex); + return i; } static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i); +/* Should be called locked */ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) { pa_memimport_segment* seg; @@ -565,59 +818,79 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) { return seg; } +/* Should be called locked */ static void segment_detach(pa_memimport_segment *seg) { - assert(seg); + pa_assert(seg); pa_hashmap_remove(seg->import->segments, PA_UINT32_TO_PTR(seg->memory.id)); pa_shm_free(&seg->memory); pa_xfree(seg); } +/* Self-locked. Not multiple-caller safe */ void pa_memimport_free(pa_memimport *i) { pa_memexport *e; pa_memblock *b; - assert(i); + pa_assert(i); + + pa_mutex_lock(i->mutex); + + while ((b = pa_hashmap_get_first(i->blocks))) + memblock_replace_import(b); + + pa_assert(pa_hashmap_size(i->segments) == 0); + + pa_mutex_unlock(i->mutex); + + pa_mutex_lock(i->pool->mutex); /* If we've exported this block further we need to revoke that export */ for (e = i->pool->exports; e; e = e->next) memexport_revoke_blocks(e, i); - while ((b = pa_hashmap_get_first(i->blocks))) - memblock_replace_import(b); + PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i); - assert(pa_hashmap_size(i->segments) == 0); + pa_mutex_unlock(i->pool->mutex); pa_hashmap_free(i->blocks, NULL, NULL); pa_hashmap_free(i->segments, NULL, NULL); - PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i); + pa_mutex_free(i->mutex); + pa_xfree(i); } +/* Self-locked */ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_id, size_t offset, size_t size) { - pa_memblock *b; + pa_memblock *b = NULL; pa_memimport_segment *seg; - assert(i); + pa_assert(i); + + pa_mutex_lock(i->mutex); if (pa_hashmap_size(i->blocks) >= PA_MEMIMPORT_SLOTS_MAX) - return NULL; + goto finish; if (!(seg = pa_hashmap_get(i->segments, PA_UINT32_TO_PTR(shm_id)))) if (!(seg = segment_attach(i, shm_id))) - return NULL; + goto finish; if (offset+size > seg->memory.size) - return NULL; + goto finish; - b = pa_xnew(pa_memblock, 1); + if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks)))) + b = pa_xnew(pa_memblock, 1); + + PA_REFCNT_INIT(b); + b->pool = i->pool; b->type = PA_MEMBLOCK_IMPORTED; b->read_only = 1; - PA_REFCNT_INIT(b); + pa_atomic_ptr_store(&b->data, (uint8_t*) seg->memory.ptr + offset); b->length = size; - b->data = (uint8_t*) seg->memory.ptr + offset; - b->pool = i->pool; + pa_atomic_store(&b->n_acquired, 0); + pa_atomic_store(&b->please_signal, 0); b->per_type.imported.id = block_id; b->per_type.imported.segment = seg; @@ -625,6 +898,10 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i seg->n_blocks++; +finish: + pa_mutex_unlock(i->mutex); + + if (b) stat_add(b); return b; @@ -632,26 +909,36 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) { pa_memblock *b; - assert(i); + int ret = 0; + pa_assert(i); - if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id)))) - return -1; + pa_mutex_lock(i->mutex); + + if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id)))) { + ret = -1; + goto finish; + } memblock_replace_import(b); - return 0; + +finish: + pa_mutex_unlock(i->mutex); + + return ret; } /* For sending blocks to other nodes */ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void *userdata) { pa_memexport *e; - assert(p); - assert(cb); + pa_assert(p); + pa_assert(cb); if (!p->memory.shared) return NULL; e = pa_xnew(pa_memexport, 1); + e->mutex = pa_mutex_new(TRUE, TRUE); e->pool = p; PA_LLIST_HEAD_INIT(struct memexport_slot, e->free_slots); PA_LLIST_HEAD_INIT(struct memexport_slot, e->used_slots); @@ -659,50 +946,75 @@ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void e->revoke_cb = cb; e->userdata = userdata; + pa_mutex_lock(p->mutex); PA_LLIST_PREPEND(pa_memexport, p->exports, e); + pa_mutex_unlock(p->mutex); return e; } void pa_memexport_free(pa_memexport *e) { - assert(e); + pa_assert(e); + pa_mutex_lock(e->mutex); while (e->used_slots) pa_memexport_process_release(e, e->used_slots - e->slots); + pa_mutex_unlock(e->mutex); + pa_mutex_lock(e->pool->mutex); PA_LLIST_REMOVE(pa_memexport, e->pool->exports, e); + pa_mutex_unlock(e->pool->mutex); + + pa_mutex_free(e->mutex); pa_xfree(e); } +/* Self-locked */ int pa_memexport_process_release(pa_memexport *e, uint32_t id) { - assert(e); + pa_memblock *b; + + pa_assert(e); + + pa_mutex_lock(e->mutex); if (id >= e->n_init) - return -1; + goto fail; if (!e->slots[id].block) - return -1; + goto fail; -/* pa_log("Processing release for %u", id); */ - - assert(pa_atomic_load(&e->pool->stat.n_exported) > 0); - assert(pa_atomic_load(&e->pool->stat.exported_size) >= (int) e->slots[id].block->length); - - pa_atomic_dec(&e->pool->stat.n_exported); - pa_atomic_sub(&e->pool->stat.exported_size, e->slots[id].block->length); - - pa_memblock_unref(e->slots[id].block); + b = e->slots[id].block; e->slots[id].block = NULL; PA_LLIST_REMOVE(struct memexport_slot, e->used_slots, &e->slots[id]); PA_LLIST_PREPEND(struct memexport_slot, e->free_slots, &e->slots[id]); + pa_mutex_unlock(e->mutex); + +/* pa_log("Processing release for %u", id); */ + + pa_assert(pa_atomic_load(&e->pool->stat.n_exported) > 0); + pa_assert(pa_atomic_load(&e->pool->stat.exported_size) >= (int) b->length); + + pa_atomic_dec(&e->pool->stat.n_exported); + pa_atomic_sub(&e->pool->stat.exported_size, b->length); + + pa_memblock_unref(b); + return 0; + +fail: + pa_mutex_unlock(e->mutex); + + return -1; } +/* Self-locked */ static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) { struct memexport_slot *slot, *next; - assert(e); - assert(i); + pa_assert(e); + pa_assert(i); + + pa_mutex_lock(e->mutex); for (slot = e->used_slots; slot; slot = next) { uint32_t idx; @@ -716,49 +1028,57 @@ static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) { e->revoke_cb(e, idx, e->userdata); pa_memexport_process_release(e, idx); } + + pa_mutex_unlock(e->mutex); } +/* No lock necessary */ static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *b) { pa_memblock *n; - assert(p); - assert(b); + pa_assert(p); + pa_assert(b); if (b->type == PA_MEMBLOCK_IMPORTED || b->type == PA_MEMBLOCK_POOL || b->type == PA_MEMBLOCK_POOL_EXTERNAL) { - assert(b->pool == p); + pa_assert(b->pool == p); return pa_memblock_ref(b); } if (!(n = pa_memblock_new_pool(p, b->length))) return NULL; - memcpy(n->data, b->data, b->length); + memcpy(pa_atomic_ptr_load(&n->data), pa_atomic_ptr_load(&b->data), b->length); return n; } +/* Self-locked */ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32_t *shm_id, size_t *offset, size_t * size) { pa_shm *memory; struct memexport_slot *slot; + void *data; - assert(e); - assert(b); - assert(block_id); - assert(shm_id); - assert(offset); - assert(size); - assert(b->pool == e->pool); + pa_assert(e); + pa_assert(b); + pa_assert(block_id); + pa_assert(shm_id); + pa_assert(offset); + pa_assert(size); + pa_assert(b->pool == e->pool); if (!(b = memblock_shared_copy(e->pool, b))) return -1; + pa_mutex_lock(e->mutex); + if (e->free_slots) { slot = e->free_slots; PA_LLIST_REMOVE(struct memexport_slot, e->free_slots, slot); - } else if (e->n_init < PA_MEMEXPORT_SLOTS_MAX) { + } else if (e->n_init < PA_MEMEXPORT_SLOTS_MAX) slot = &e->slots[e->n_init++]; - } else { + else { + pa_mutex_unlock(e->mutex); pa_memblock_unref(b); return -1; } @@ -767,24 +1087,29 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32 slot->block = b; *block_id = slot - e->slots; + pa_mutex_unlock(e->mutex); /* pa_log("Got block id %u", *block_id); */ + data = pa_memblock_acquire(b); + if (b->type == PA_MEMBLOCK_IMPORTED) { - assert(b->per_type.imported.segment); + pa_assert(b->per_type.imported.segment); memory = &b->per_type.imported.segment->memory; } else { - assert(b->type == PA_MEMBLOCK_POOL || b->type == PA_MEMBLOCK_POOL_EXTERNAL); - assert(b->pool); + pa_assert(b->type == PA_MEMBLOCK_POOL || b->type == PA_MEMBLOCK_POOL_EXTERNAL); + pa_assert(b->pool); memory = &b->pool->memory; } - assert(b->data >= memory->ptr); - assert((uint8_t*) b->data + b->length <= (uint8_t*) memory->ptr + memory->size); + pa_assert(data >= memory->ptr); + pa_assert((uint8_t*) data + b->length <= (uint8_t*) memory->ptr + memory->size); *shm_id = memory->id; - *offset = (uint8_t*) b->data - (uint8_t*) memory->ptr; + *offset = (uint8_t*) data - (uint8_t*) memory->ptr; *size = b->length; + pa_memblock_release(b); + pa_atomic_inc(&e->pool->stat.n_exported); pa_atomic_add(&e->pool->stat.exported_size, b->length); diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index fe4773d44..c704014a6 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -58,45 +59,25 @@ typedef struct pa_memexport pa_memexport; typedef void (*pa_memimport_release_cb_t)(pa_memimport *i, uint32_t block_id, void *userdata); typedef void (*pa_memexport_revoke_cb_t)(pa_memexport *e, uint32_t block_id, void *userdata); -struct pa_memblock { - pa_memblock_type_t type; - int read_only; /* boolean */ - PA_REFCNT_DECLARE; /* the reference counter */ - size_t length; - void *data; - pa_mempool *pool; - - union { - struct { - void (*free_cb)(void *p); /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */ - } user; - - struct { - uint32_t id; - pa_memimport_segment *segment; - } imported; - } per_type; -}; - /* Please note that updates to this structure are not locked, * i.e. n_allocated might be updated at a point in time where * n_accumulated is not yet. Take these values with a grain of salt, - * threy are here for purely statistical reasons.*/ + * they are here for purely statistical reasons.*/ struct pa_mempool_stat { - pa_atomic_int_t n_allocated; - pa_atomic_int_t n_accumulated; - pa_atomic_int_t n_imported; - pa_atomic_int_t n_exported; - pa_atomic_int_t allocated_size; - pa_atomic_int_t accumulated_size; - pa_atomic_int_t imported_size; - pa_atomic_int_t exported_size; + pa_atomic_t n_allocated; + pa_atomic_t n_accumulated; + pa_atomic_t n_imported; + pa_atomic_t n_exported; + pa_atomic_t allocated_size; + pa_atomic_t accumulated_size; + pa_atomic_t imported_size; + pa_atomic_t exported_size; - pa_atomic_int_t n_too_large_for_pool; - pa_atomic_int_t n_pool_full; + pa_atomic_t n_too_large_for_pool; + pa_atomic_t n_pool_full; - pa_atomic_int_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; - pa_atomic_int_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; + pa_atomic_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX]; + pa_atomic_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX]; }; /* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL or PA_MEMBLOCK_APPENDED, depending on the size */ @@ -120,9 +101,20 @@ pa_memblock* pa_memblock_ref(pa_memblock*b); /* This special unref function has to be called by the owner of the memory of a static memory block when he wants to release all references to the memory. This causes the memory to be copied and -converted into a PA_MEMBLOCK_DYNAMIC type memory block */ +converted into a pool or malloc'ed memory block. Please note that this +function is not multiple caller safe, i.e. needs to be locked +manually if called from more than one thread at the same time. */ void pa_memblock_unref_fixed(pa_memblock*b); +int pa_memblock_is_read_only(pa_memblock *b); +int pa_memblock_ref_is_one(pa_memblock *b); +void* pa_memblock_acquire(pa_memblock *b); +void pa_memblock_release(pa_memblock *b); +size_t pa_memblock_get_length(pa_memblock *b); +pa_mempool * pa_memblock_get_pool(pa_memblock *b); + +pa_memblock *pa_memblock_will_need(pa_memblock *b); + /* The memory block manager */ pa_mempool* pa_mempool_new(int shared); void pa_mempool_free(pa_mempool *p); @@ -130,6 +122,7 @@ const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p); void pa_mempool_vacuum(pa_mempool *p); int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id); int pa_mempool_is_shared(pa_mempool *p); +size_t pa_mempool_block_size_max(pa_mempool *p); /* For recieving blocks from other nodes */ pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void *userdata); diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index e31fb6dfb..a46155a9f 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -36,23 +35,29 @@ #include #include +#include +#include #include "memblockq.h" -struct memblock_list { - struct memblock_list *next, *prev; +struct list_item { + struct list_item *next, *prev; int64_t index; pa_memchunk chunk; }; +PA_STATIC_FLIST_DECLARE(list_items, 0, pa_xfree); + struct pa_memblockq { - struct memblock_list *blocks, *blocks_tail; + struct list_item *blocks, *blocks_tail; unsigned n_blocks; size_t maxlength, tlength, base, prebuf, minreq; int64_t read_index, write_index; - enum { PREBUF, RUNNING } state; + pa_bool_t in_prebuf; pa_memblock *silence; pa_mcalign *mcalign; + int64_t missing; + size_t requested; }; pa_memblockq* pa_memblockq_new( @@ -66,8 +71,8 @@ pa_memblockq* pa_memblockq_new( pa_memblockq* bq; - assert(base > 0); - assert(maxlength >= base); + pa_assert(base > 0); + pa_assert(maxlength >= base); bq = pa_xnew(pa_memblockq, 1); bq->blocks = bq->blocks_tail = NULL; @@ -77,13 +82,13 @@ pa_memblockq* pa_memblockq_new( bq->read_index = bq->write_index = idx; pa_log_debug("memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", - (unsigned long)maxlength, (unsigned long)tlength, (unsigned long)base, (unsigned long)prebuf, (unsigned long)minreq); + (unsigned long) maxlength, (unsigned long) tlength, (unsigned long) base, (unsigned long) prebuf, (unsigned long) minreq); bq->maxlength = ((maxlength+base-1)/base)*base; - assert(bq->maxlength >= base); + pa_assert(bq->maxlength >= base); bq->tlength = ((tlength+base-1)/base)*base; - if (!bq->tlength || bq->tlength >= bq->maxlength) + if (bq->tlength <= 0 || bq->tlength > bq->maxlength) bq->tlength = bq->maxlength; bq->prebuf = (prebuf == (size_t) -1) ? bq->tlength/2 : prebuf; @@ -102,15 +107,18 @@ pa_memblockq* pa_memblockq_new( pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", (unsigned long)bq->maxlength, (unsigned long)bq->tlength, (unsigned long)bq->base, (unsigned long)bq->prebuf, (unsigned long)bq->minreq); - bq->state = bq->prebuf ? PREBUF : RUNNING; + bq->in_prebuf = bq->prebuf > 0; bq->silence = silence ? pa_memblock_ref(silence) : NULL; bq->mcalign = NULL; + bq->missing = bq->tlength; + bq->requested = 0; + return bq; } void pa_memblockq_free(pa_memblockq* bq) { - assert(bq); + pa_assert(bq); pa_memblockq_flush(bq); @@ -123,11 +131,11 @@ void pa_memblockq_free(pa_memblockq* bq) { pa_xfree(bq); } -static void drop_block(pa_memblockq *bq, struct memblock_list *q) { - assert(bq); - assert(q); +static void drop_block(pa_memblockq *bq, struct list_item *q) { + pa_assert(bq); + pa_assert(q); - assert(bq->n_blocks >= 1); + pa_assert(bq->n_blocks >= 1); if (q->prev) q->prev->next = q->next; @@ -140,15 +148,17 @@ static void drop_block(pa_memblockq *bq, struct memblock_list *q) { bq->blocks_tail = q->prev; pa_memblock_unref(q->chunk.memblock); - pa_xfree(q); + + if (pa_flist_push(PA_STATIC_FLIST_GET(list_items), q) < 0) + pa_xfree(q); bq->n_blocks--; } -static int can_push(pa_memblockq *bq, size_t l) { +static pa_bool_t can_push(pa_memblockq *bq, size_t l) { int64_t end; - assert(bq); + pa_assert(bq); if (bq->read_index > bq->write_index) { size_t d = bq->read_index - bq->write_index; @@ -156,7 +166,7 @@ static int can_push(pa_memblockq *bq, size_t l) { if (l > d) l -= d; else - return 1; + return TRUE; } end = bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : 0; @@ -164,21 +174,21 @@ static int can_push(pa_memblockq *bq, size_t l) { /* Make sure that the list doesn't get too long */ if (bq->write_index + (int64_t)l > end) if (bq->write_index + l - bq->read_index > bq->maxlength) - return 0; + return FALSE; - return 1; + return TRUE; } int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { - - struct memblock_list *q, *n; + struct list_item *q, *n; pa_memchunk chunk; + int64_t old, delta; - assert(bq); - assert(uchunk); - assert(uchunk->memblock); - assert(uchunk->length > 0); - assert(uchunk->index + uchunk->length <= uchunk->memblock->length); + pa_assert(bq); + pa_assert(uchunk); + pa_assert(uchunk->memblock); + pa_assert(uchunk->length > 0); + pa_assert(uchunk->index + uchunk->length <= pa_memblock_get_length(uchunk->memblock)); if (uchunk->length % bq->base) return -1; @@ -186,6 +196,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { if (!can_push(bq, uchunk->length)) return -1; + old = bq->write_index; chunk = *uchunk; if (bq->read_index > bq->write_index) { @@ -198,11 +209,11 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { if (chunk.length > d) { chunk.index += d; chunk.length -= d; - bq->write_index = bq->read_index; + bq->write_index += d; } else { /* We drop the incoming data completely */ bq->write_index += chunk.length; - return 0; + goto finish; } } @@ -212,10 +223,10 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { q = bq->blocks_tail; while (q) { - if (bq->write_index >= q->index + (int64_t)q->chunk.length) + if (bq->write_index >= q->index + (int64_t) q->chunk.length) /* We found the entry where we need to place the new entry immediately after */ break; - else if (bq->write_index + (int64_t)chunk.length <= q->index) { + else if (bq->write_index + (int64_t) chunk.length <= q->index) { /* This entry isn't touched at all, let's skip it */ q = q->prev; } else if (bq->write_index <= q->index && @@ -223,7 +234,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { /* This entry is fully replaced by the new entry, so let's drop it */ - struct memblock_list *p; + struct list_item *p; p = q; q = q->prev; drop_block(bq, p); @@ -234,17 +245,19 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { if (bq->write_index + chunk.length < q->index + q->chunk.length) { /* We need to save the end of this memchunk */ - struct memblock_list *p; + struct list_item *p; size_t d; /* Create a new list entry for the end of thie memchunk */ - p = pa_xnew(struct memblock_list, 1); + if (!(p = pa_flist_pop(PA_STATIC_FLIST_GET(list_items)))) + p = pa_xnew(struct list_item, 1); + p->chunk = q->chunk; pa_memblock_ref(p->chunk.memblock); /* Calculate offset */ d = bq->write_index + chunk.length - q->index; - assert(d > 0); + pa_assert(d > 0); /* Drop it from the new entry */ p->index = q->index + d; @@ -263,7 +276,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { /* Truncate the chunk */ if (!(q->chunk.length = bq->write_index - q->index)) { - struct memblock_list *p; + struct list_item *p; p = q; q = q->prev; drop_block(bq, p); @@ -274,7 +287,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { } else { size_t d; - assert(bq->write_index + (int64_t)chunk.length > q->index && + pa_assert(bq->write_index + (int64_t)chunk.length > q->index && bq->write_index + (int64_t)chunk.length < q->index + (int64_t)q->chunk.length && bq->write_index < q->index); @@ -287,12 +300,11 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { q = q->prev; } - } if (q) { - assert(bq->write_index >= q->index + (int64_t)q->chunk.length); - assert(!q->next || (bq->write_index + (int64_t)chunk.length <= q->next->index)); + pa_assert(bq->write_index >= q->index + (int64_t)q->chunk.length); + pa_assert(!q->next || (bq->write_index + (int64_t)chunk.length <= q->next->index)); /* Try to merge memory blocks */ @@ -302,13 +314,14 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { q->chunk.length += chunk.length; bq->write_index += chunk.length; - return 0; + goto finish; } } else - assert(!bq->blocks || (bq->write_index + (int64_t)chunk.length <= bq->blocks->index)); + pa_assert(!bq->blocks || (bq->write_index + (int64_t)chunk.length <= bq->blocks->index)); + if (!(n = pa_flist_pop(PA_STATIC_FLIST_GET(list_items)))) + n = pa_xnew(struct list_item, 1); - n = pa_xnew(struct memblock_list, 1); n->chunk = chunk; pa_memblock_ref(n->chunk.memblock); n->index = bq->write_index; @@ -328,27 +341,52 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { bq->blocks = n; bq->n_blocks++; + +finish: + + delta = bq->write_index - old; + + if (delta >= bq->requested) { + delta -= bq->requested; + bq->requested = 0; + } else { + bq->requested -= delta; + delta = 0; + } + + bq->missing -= delta; + return 0; } -int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { - assert(bq); - assert(chunk); +static pa_bool_t memblockq_check_prebuf(pa_memblockq *bq) { + pa_assert(bq); - if (bq->state == PREBUF) { + if (bq->in_prebuf) { - /* We need to pre-buffer */ if (pa_memblockq_get_length(bq) < bq->prebuf) - return -1; + return TRUE; - bq->state = RUNNING; + bq->in_prebuf = FALSE; + return FALSE; + } else { - } else if (bq->prebuf > 0 && bq->read_index >= bq->write_index) { + if (bq->prebuf > 0 && bq->read_index >= bq->write_index) { + bq->in_prebuf = TRUE; + return TRUE; + } - /* Buffer underflow protection */ - bq->state = PREBUF; - return -1; + return FALSE; } +} + +int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { + pa_assert(bq); + pa_assert(chunk); + + /* We need to pre-buffer */ + if (memblockq_check_prebuf(bq)) + return -1; /* Do we need to spit out silence? */ if (!bq->blocks || bq->blocks->index > bq->read_index) { @@ -362,8 +400,8 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { if (bq->silence) { chunk->memblock = pa_memblock_ref(bq->silence); - if (!length || length > chunk->memblock->length) - length = chunk->memblock->length; + if (!length || length > pa_memblock_get_length(chunk->memblock)) + length = pa_memblock_get_length(chunk->memblock); chunk->length = length; } else { @@ -382,7 +420,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { } /* Ok, let's pass real data to the caller */ - assert(bq->blocks->index == bq->read_index); + pa_assert(bq->blocks->index == bq->read_index); *chunk = bq->blocks->chunk; pa_memblock_ref(chunk->memblock); @@ -390,48 +428,23 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { return 0; } -void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length) { - assert(bq); - assert(length % bq->base == 0); +void pa_memblockq_drop(pa_memblockq *bq, size_t length) { + int64_t old, delta; + pa_assert(bq); + pa_assert(length % bq->base == 0); - assert(!chunk || length <= chunk->length); - - if (chunk) { - - if (bq->blocks && bq->blocks->index == bq->read_index) { - /* The first item in queue is valid */ - - /* Does the chunk match with what the user supplied us? */ - if (memcmp(chunk, &bq->blocks->chunk, sizeof(pa_memchunk)) != 0) - return; - - } else { - size_t l; - - /* The first item in the queue is not yet relevant */ - - assert(!bq->blocks || bq->blocks->index > bq->read_index); - l = bq->blocks ? bq->blocks->index - bq->read_index : 0; - - if (bq->silence) { - - if (!l || l > bq->silence->length) - l = bq->silence->length; - - } - - /* Do the entries still match? */ - if (chunk->index != 0 || chunk->length != l || chunk->memblock != bq->silence) - return; - } - } + old = bq->read_index; while (length > 0) { + /* Do not drop any data when we are in prebuffering mode */ + if (memblockq_check_prebuf(bq)) + break; + if (bq->blocks) { size_t d; - assert(bq->blocks->index >= bq->read_index); + pa_assert(bq->blocks->index >= bq->read_index); d = (size_t) (bq->blocks->index - bq->read_index); @@ -446,7 +459,7 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length bq->read_index += d; } - assert(bq->blocks->index == bq->read_index); + pa_assert(bq->blocks->index == bq->read_index); if (bq->blocks->chunk.length <= length) { /* We need to drop the full block */ @@ -472,35 +485,25 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length break; } } + + delta = bq->read_index - old; + bq->missing += delta; } int pa_memblockq_is_readable(pa_memblockq *bq) { - assert(bq); + pa_assert(bq); - if (bq->prebuf > 0) { - size_t l = pa_memblockq_get_length(bq); + if (memblockq_check_prebuf(bq)) + return 0; - if (bq->state == PREBUF && l < bq->prebuf) - return 0; - - if (l <= 0) - return 0; - } + if (pa_memblockq_get_length(bq) <= 0) + return 0; return 1; } -int pa_memblockq_is_writable(pa_memblockq *bq, size_t length) { - assert(bq); - - if (length % bq->base) - return 0; - - return pa_memblockq_get_length(bq) + length <= bq->tlength; -} - size_t pa_memblockq_get_length(pa_memblockq *bq) { - assert(bq); + pa_assert(bq); if (bq->write_index <= bq->read_index) return 0; @@ -510,76 +513,106 @@ size_t pa_memblockq_get_length(pa_memblockq *bq) { size_t pa_memblockq_missing(pa_memblockq *bq) { size_t l; - assert(bq); + pa_assert(bq); if ((l = pa_memblockq_get_length(bq)) >= bq->tlength) return 0; l = bq->tlength - l; - return (l >= bq->minreq) ? l : 0; + + return l >= bq->minreq ? l : 0; } size_t pa_memblockq_get_minreq(pa_memblockq *bq) { - assert(bq); + pa_assert(bq); return bq->minreq; } void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) { - assert(bq); + int64_t old, delta; + pa_assert(bq); + + old = bq->write_index; switch (seek) { case PA_SEEK_RELATIVE: bq->write_index += offset; - return; + break; case PA_SEEK_ABSOLUTE: bq->write_index = offset; - return; + break; case PA_SEEK_RELATIVE_ON_READ: bq->write_index = bq->read_index + offset; - return; + break; case PA_SEEK_RELATIVE_END: - bq->write_index = (bq->blocks_tail ? bq->blocks_tail->index + (int64_t)bq->blocks_tail->chunk.length : bq->read_index) + offset; - return; + bq->write_index = (bq->blocks_tail ? bq->blocks_tail->index + (int64_t) bq->blocks_tail->chunk.length : bq->read_index) + offset; + break; + default: + pa_assert_not_reached(); } - assert(0); + delta = bq->write_index - old; + + if (delta >= bq->requested) { + delta -= bq->requested; + bq->requested = 0; + } else if (delta >= 0) { + bq->requested -= delta; + delta = 0; + } + + bq->missing -= delta; } void pa_memblockq_flush(pa_memblockq *bq) { - assert(bq); + int64_t old, delta; + pa_assert(bq); while (bq->blocks) drop_block(bq, bq->blocks); - assert(bq->n_blocks == 0); + pa_assert(bq->n_blocks == 0); + old = bq->write_index; bq->write_index = bq->read_index; pa_memblockq_prebuf_force(bq); + + delta = bq->write_index - old; + + if (delta > bq->requested) { + delta -= bq->requested; + bq->requested = 0; + } else if (delta >= 0) { + bq->requested -= delta; + delta = 0; + } + + bq->missing -= delta; } size_t pa_memblockq_get_tlength(pa_memblockq *bq) { - assert(bq); + pa_assert(bq); return bq->tlength; } int64_t pa_memblockq_get_read_index(pa_memblockq *bq) { - assert(bq); + pa_assert(bq); return bq->read_index; } int64_t pa_memblockq_get_write_index(pa_memblockq *bq) { - assert(bq); + pa_assert(bq); return bq->write_index; } int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk) { pa_memchunk rchunk; - assert(bq); - assert(chunk && bq->base); + pa_assert(bq); + pa_assert(chunk); if (bq->base == 1) return pa_memblockq_push(bq, chunk); @@ -606,36 +639,52 @@ int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk) { void pa_memblockq_shorten(pa_memblockq *bq, size_t length) { size_t l; - assert(bq); + pa_assert(bq); l = pa_memblockq_get_length(bq); if (l > length) - pa_memblockq_drop(bq, NULL, l - length); + pa_memblockq_drop(bq, l - length); } void pa_memblockq_prebuf_disable(pa_memblockq *bq) { - assert(bq); + pa_assert(bq); - if (bq->state == PREBUF) - bq->state = RUNNING; + bq->in_prebuf = FALSE; } void pa_memblockq_prebuf_force(pa_memblockq *bq) { - assert(bq); + pa_assert(bq); - if (bq->state == RUNNING && bq->prebuf > 0) - bq->state = PREBUF; + if (!bq->in_prebuf && bq->prebuf > 0) + bq->in_prebuf = TRUE; } size_t pa_memblockq_get_maxlength(pa_memblockq *bq) { - assert(bq); + pa_assert(bq); return bq->maxlength; } size_t pa_memblockq_get_prebuf(pa_memblockq *bq) { - assert(bq); + pa_assert(bq); return bq->prebuf; } + +size_t pa_memblockq_pop_missing(pa_memblockq *bq) { + size_t l; + + pa_assert(bq); + +/* pa_log("pop: %lli", bq->missing); */ + + if (bq->missing <= 0) + return 0; + + l = (size_t) bq->missing; + bq->missing = 0; + bq->requested += l; + + return l; +} diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h index 437c5a419..8c3e70fc3 100644 --- a/src/pulsecore/memblockq.h +++ b/src/pulsecore/memblockq.h @@ -62,7 +62,7 @@ typedef struct pa_memblockq pa_memblockq; - minreq: pa_memblockq_missing() will only return values greater than this value. Pass 0 for the default. - - silence: return this memblock whzen reading unitialized data + - silence: return this memblock when reading unitialized data */ pa_memblockq* pa_memblockq_new( int64_t idx, @@ -83,26 +83,30 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *chunk); * you know what you do. */ int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk); -/* Return a copy of the next memory chunk in the queue. It is not removed from the queue */ +/* Return a copy of the next memory chunk in the queue. It is not + * removed from the queue. There are two reasons this function might + * fail: 1. prebuffering is active, 2. queue is empty and no silence + * memblock was passed at initialization. If the queue is not empty, + * but we're currently at a hole in the queue and no silence memblock + * was passed we return the length of the hole in chunk->length. */ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk); -/* Drop the specified bytes from the queue, but only if the first - * chunk in the queue matches the one passed here. If NULL is passed, - * this check isn't done. */ -void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length); +/* Drop the specified bytes from the queue. */ +void pa_memblockq_drop(pa_memblockq *bq, size_t length); /* Test if the pa_memblockq is currently readable, that is, more data than base */ int pa_memblockq_is_readable(pa_memblockq *bq); -/* Test if the pa_memblockq is currently writable for the specified amount of bytes */ -int pa_memblockq_is_writable(pa_memblockq *bq, size_t length); - /* Return the length of the queue in bytes */ size_t pa_memblockq_get_length(pa_memblockq *bq); /* Return how many bytes are missing in queue to the specified fill amount */ size_t pa_memblockq_missing(pa_memblockq *bq); +/* Return the number of bytes that are missing since the last call to + * this function, reset the internal counter to 0. */ +size_t pa_memblockq_pop_missing(pa_memblockq *bq); + /* Returns the minimal request value */ size_t pa_memblockq_get_minreq(pa_memblockq *bq); diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c index 7111e1ec1..4e73b6361 100644 --- a/src/pulsecore/memchunk.c +++ b/src/pulsecore/memchunk.c @@ -27,40 +27,66 @@ #include #include -#include #include +#include #include +#include +#include #include "memchunk.h" -void pa_memchunk_make_writable(pa_memchunk *c, size_t min) { +pa_memchunk* pa_memchunk_make_writable(pa_memchunk *c, size_t min) { pa_memblock *n; size_t l; + void *tdata, *sdata; - assert(c); - assert(c->memblock); - assert(PA_REFCNT_VALUE(c->memblock) > 0); + pa_assert(c); + pa_assert(c->memblock); - if (PA_REFCNT_VALUE(c->memblock) == 1 && - !c->memblock->read_only && - c->memblock->length >= c->index+min) - return; + if (pa_memblock_ref_is_one(c->memblock) && + !pa_memblock_is_read_only(c->memblock) && + pa_memblock_get_length(c->memblock) >= c->index+min) + return c; l = c->length; if (l < min) l = min; - n = pa_memblock_new(c->memblock->pool, l); - memcpy(n->data, (uint8_t*) c->memblock->data + c->index, c->length); + n = pa_memblock_new(pa_memblock_get_pool(c->memblock), l); + tdata = pa_memblock_acquire(n); + sdata = pa_memblock_acquire(c->memblock); + memcpy(tdata, (uint8_t*) sdata + c->index, c->length); + pa_memblock_release(n); + pa_memblock_release(c->memblock); pa_memblock_unref(c->memblock); c->memblock = n; c->index = 0; + + return c; } -void pa_memchunk_reset(pa_memchunk *c) { - assert(c); +pa_memchunk* pa_memchunk_reset(pa_memchunk *c) { + pa_assert(c); c->memblock = NULL; c->length = c->index = 0; + + return c; +} + +pa_memchunk *pa_memchunk_will_need(const pa_memchunk *c) { + void *p; + + pa_assert(c); + pa_assert(c->memblock); + + /* A version of pa_memblock_will_need() that works on memchunks + * instead of memblocks */ + + p = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index; + pa_will_need(p, c->length); + pa_memblock_release(c->memblock); + + return (pa_memchunk*) c; } diff --git a/src/pulsecore/memchunk.h b/src/pulsecore/memchunk.h index 0b982b6d3..e6105aceb 100644 --- a/src/pulsecore/memchunk.h +++ b/src/pulsecore/memchunk.h @@ -37,11 +37,16 @@ typedef struct pa_memchunk { /* Make a memchunk writable, i.e. make sure that the caller may have * exclusive access to the memblock and it is not read_only. If needed - * the memblock in the structure is replaced by a copy. */ -void pa_memchunk_make_writable(pa_memchunk *c, size_t min); + * the memblock in the structure is replaced by a copy. If min is not + * 0 it is made sure that the returned memblock is at least of the + * specified size, i.e. is enlarged if necessary. */ +pa_memchunk* pa_memchunk_make_writable(pa_memchunk *c, size_t min); /* Invalidate a memchunk. This does not free the cotaining memblock, * but sets all members to zero. */ -void pa_memchunk_reset(pa_memchunk *c); +pa_memchunk* pa_memchunk_reset(pa_memchunk *c); + +/* Map a memory chunk back into memory if it was swapped out */ +pa_memchunk *pa_memchunk_will_need(const pa_memchunk *c); #endif diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c index 3733f6550..1311af3c1 100644 --- a/src/pulsecore/modargs.c +++ b/src/pulsecore/modargs.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include @@ -39,6 +38,7 @@ #include #include #include +#include #include "modargs.h" @@ -48,7 +48,10 @@ struct entry { static int add_key_value(pa_hashmap *map, char *key, char *value, const char* const valid_keys[]) { struct entry *e; - assert(map && key && value); + + pa_assert(map); + pa_assert(key); + pa_assert(value); if (valid_keys) { const char*const* v; @@ -63,10 +66,11 @@ static int add_key_value(pa_hashmap *map, char *key, char *value, const char* co } } - e = pa_xmalloc(sizeof(struct entry)); + e = pa_xnew(struct entry, 1); e->key = key; e->value = value; pa_hashmap_put(map, key, e); + return 0; } @@ -74,7 +78,6 @@ pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) { pa_hashmap *map = NULL; map = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - assert(map); if (args) { enum { WHITESPACE, KEY, VALUE_START, VALUE_SIMPLE, VALUE_DOUBLE_QUOTES, VALUE_TICKS } state; @@ -166,10 +169,10 @@ fail: return NULL; } - static void free_func(void *p, PA_GCC_UNUSED void*userdata) { struct entry *e = p; - assert(e); + pa_assert(e); + pa_xfree(e->key); pa_xfree(e->value); pa_xfree(e); @@ -192,7 +195,10 @@ const char *pa_modargs_get_value(pa_modargs *ma, const char *key, const char *de int pa_modargs_get_value_u32(pa_modargs *ma, const char *key, uint32_t *value) { const char *v; - assert(ma && key && value); + + pa_assert(ma); + pa_assert(key); + pa_assert(value); if (!(v = pa_modargs_get_value(ma, key, NULL))) return 0; @@ -205,7 +211,10 @@ int pa_modargs_get_value_u32(pa_modargs *ma, const char *key, uint32_t *value) { int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value) { const char *v; - assert(ma && key && value); + + pa_assert(ma); + pa_assert(key); + pa_assert(value); if (!(v = pa_modargs_get_value(ma, key, NULL))) return 0; @@ -219,7 +228,10 @@ int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value) { int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value) { const char *v; int r; - assert(ma && key && value); + + pa_assert(ma); + pa_assert(key); + pa_assert(value); if (!(v = pa_modargs_get_value(ma, key, NULL))) return 0; @@ -238,9 +250,9 @@ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) { const char *format; uint32_t channels; pa_sample_spec ss; - assert(ma && rss); -/* DEBUG_TRAP;*/ + pa_assert(ma); + pa_assert(rss); ss = *rss; if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0) @@ -263,16 +275,16 @@ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) { return 0; } -int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *rmap) { +int pa_modargs_get_channel_map(pa_modargs *ma, const char *name, pa_channel_map *rmap) { pa_channel_map map; const char *cm; - assert(ma); - assert(rmap); + pa_assert(ma); + pa_assert(rmap); map = *rmap; - if ((cm = pa_modargs_get_value(ma, "channel_map", NULL))) + if ((cm = pa_modargs_get_value(ma, name ? name : "channel_map", NULL))) if (!pa_channel_map_parse(&map, cm)) return -1; @@ -287,9 +299,9 @@ int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *r pa_sample_spec ss; pa_channel_map map; - assert(ma); - assert(rss); - assert(rmap); + pa_assert(ma); + pa_assert(rss); + pa_assert(rmap); ss = *rss; @@ -299,7 +311,7 @@ int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *r if (!pa_channel_map_init_auto(&map, ss.channels, def)) map.channels = 0; - if (pa_modargs_get_channel_map(ma, &map) < 0) + if (pa_modargs_get_channel_map(ma, NULL, &map) < 0) return -1; if (map.channels != ss.channels) diff --git a/src/pulsecore/modargs.h b/src/pulsecore/modargs.h index 77262e1e9..aa175885d 100644 --- a/src/pulsecore/modargs.h +++ b/src/pulsecore/modargs.h @@ -49,8 +49,8 @@ int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value); /* Return sample spec data from the three arguments "rate", "format" and "channels" */ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *ss); -/* Return channel map data from the argument "channel_map" */ -int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *map); +/* Return channel map data from the argument "channel_map" if name is NULL, otherwise read from the specified argument */ +int pa_modargs_get_channel_map(pa_modargs *ma, const char *name, pa_channel_map *map); /* Combination of pa_modargs_get_sample_spec() and pa_modargs_get_channel_map(). Not always suitable, since this routine diff --git a/src/pulsecore/modinfo.c b/src/pulsecore/modinfo.c index 58394e594..da2df6535 100644 --- a/src/pulsecore/modinfo.c +++ b/src/pulsecore/modinfo.c @@ -26,12 +26,13 @@ #endif #include -#include #include #include #include +#include +#include #include "modinfo.h" @@ -40,30 +41,24 @@ #define PA_SYMBOL_USAGE "pa__get_usage" #define PA_SYMBOL_VERSION "pa__get_version" -/* lt_dlsym() violates ISO C, so confide the breakage into this function to - * avoid warnings. */ -typedef void (*fnptr)(void); -static inline fnptr lt_dlsym_fn(lt_dlhandle handle, const char *symbol) { - return (fnptr) (long) lt_dlsym(handle, symbol); -} - -pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) { +pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl, const char *module_name) { pa_modinfo *i; const char* (*func)(void); - assert(dl); + + pa_assert(dl); i = pa_xnew0(pa_modinfo, 1); - if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_AUTHOR))) + if ((func = (const char* (*)(void)) pa_load_sym(dl, module_name, PA_SYMBOL_AUTHOR))) i->author = pa_xstrdup(func()); - if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_DESCRIPTION))) + if ((func = (const char* (*)(void)) pa_load_sym(dl, module_name, PA_SYMBOL_DESCRIPTION))) i->description = pa_xstrdup(func()); - if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_USAGE))) + if ((func = (const char* (*)(void)) pa_load_sym(dl, module_name, PA_SYMBOL_USAGE))) i->usage = pa_xstrdup(func()); - if ((func = (const char* (*)(void)) lt_dlsym_fn(dl, PA_SYMBOL_VERSION))) + if ((func = (const char* (*)(void)) pa_load_sym(dl, module_name, PA_SYMBOL_VERSION))) i->version = pa_xstrdup(func()); return i; @@ -72,21 +67,23 @@ pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl) { pa_modinfo *pa_modinfo_get_by_name(const char *name) { lt_dlhandle dl; pa_modinfo *i; - assert(name); + + pa_assert(name); if (!(dl = lt_dlopenext(name))) { pa_log("Failed to open module \"%s\": %s", name, lt_dlerror()); return NULL; } - i = pa_modinfo_get_by_handle(dl); + i = pa_modinfo_get_by_handle(dl, name); lt_dlclose(dl); return i; } void pa_modinfo_free(pa_modinfo *i) { - assert(i); + pa_assert(i); + pa_xfree(i->author); pa_xfree(i->description); pa_xfree(i->usage); diff --git a/src/pulsecore/modinfo.h b/src/pulsecore/modinfo.h index 3ee33ede4..02e536c66 100644 --- a/src/pulsecore/modinfo.h +++ b/src/pulsecore/modinfo.h @@ -34,7 +34,7 @@ typedef struct pa_modinfo { } pa_modinfo; /* Read meta data from an libtool handle */ -pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl); +pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl, const char *module_name); /* Read meta data from a module file */ pa_modinfo *pa_modinfo_get_by_name(const char *name); diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index 09b15b8b0..dce91a710 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -40,6 +39,8 @@ #include #include #include +#include +#include #include "module.h" @@ -48,69 +49,31 @@ #define UNLOAD_POLL_TIME 2 -/* lt_dlsym() violates ISO C, so confide the breakage into this function to - * avoid warnings. */ -typedef void (*fnptr)(void); -static inline fnptr lt_dlsym_fn(lt_dlhandle handle, const char *symbol) { - return (fnptr) (long) lt_dlsym(handle, symbol); -} - static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { - pa_core *c = userdata; + pa_core *c = PA_CORE(userdata); struct timeval ntv; - assert(c && c->mainloop == m && c->module_auto_unload_event == e); + + pa_core_assert_ref(c); + pa_assert(c->mainloop == m); + pa_assert(c->module_auto_unload_event == e); pa_module_unload_unused(c); pa_gettimeofday(&ntv); - ntv.tv_sec += UNLOAD_POLL_TIME; + pa_timeval_add(&ntv, UNLOAD_POLL_TIME*1000000); m->time_restart(e, &ntv); } -static inline fnptr load_sym(lt_dlhandle handle, const char *module, const char *symbol) { - char *buffer, *ch; - size_t buflen; - fnptr res; - - res = lt_dlsym_fn(handle, symbol); - if (res) - return res; - - /* As the .la files might have been cleansed from the system, we should - * try with the ltdl prefix as well. */ - - buflen = strlen(symbol) + strlen(module) + strlen("_LTX_") + 1; - buffer = pa_xmalloc(buflen); - assert(buffer); - - strcpy(buffer, module); - - for (ch = buffer;*ch != '\0';ch++) { - if (!isalnum(*ch)) - *ch = '_'; - } - - strcat(buffer, "_LTX_"); - strcat(buffer, symbol); - - res = lt_dlsym_fn(handle, buffer); - - pa_xfree(buffer); - - return res; -} - pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { pa_module *m = NULL; - int r; - assert(c && name); + pa_assert(c); + pa_assert(name); if (c->disallow_module_loading) goto fail; - m = pa_xmalloc(sizeof(pa_module)); - + m = pa_xnew(pa_module, 1); m->name = pa_xstrdup(name); m->argument = pa_xstrdup(argument); @@ -119,24 +82,19 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { goto fail; } - if (!(m->init = (int (*)(pa_core *_c, pa_module*_m)) load_sym(m->dl, name, PA_SYMBOL_INIT))) { + if (!(m->init = (int (*)(pa_module*_m)) pa_load_sym(m->dl, name, PA_SYMBOL_INIT))) { pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name); goto fail; } - if (!(m->done = (void (*)(pa_core *_c, pa_module*_m)) load_sym(m->dl, name, PA_SYMBOL_DONE))) { - pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.", name); - goto fail; - } - + m->done = (void (*)(pa_module*_m)) pa_load_sym(m->dl, name, PA_SYMBOL_DONE); m->userdata = NULL; m->core = c; m->n_used = -1; m->auto_unload = 0; m->unload_requested = 0; - assert(m->init); - if (m->init(c, m) < 0) { + if (m->init(m) < 0) { pa_log_error("Failed to load module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : ""); goto fail; } @@ -147,14 +105,12 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { if (!c->module_auto_unload_event) { struct timeval ntv; pa_gettimeofday(&ntv); - ntv.tv_sec += UNLOAD_POLL_TIME; + pa_timeval_add(&ntv, UNLOAD_POLL_TIME*1000000); c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } - assert(c->module_auto_unload_event); - assert(c->modules); - r = pa_idxset_put(c->modules, m, &m->index); - assert(r >= 0 && m->index != PA_IDXSET_INVALID); + pa_assert_se(pa_idxset_put(c->modules, m, &m->index) >= 0); + pa_assert(m->index != PA_IDXSET_INVALID); pa_log_info("Loaded \"%s\" (index: #%u; argument: \"%s\").", m->name, m->index, m->argument ? m->argument : ""); @@ -178,14 +134,16 @@ fail: } static void pa_module_free(pa_module *m) { - assert(m && m->done && m->core); + pa_assert(m); + pa_assert(m->core); if (m->core->disallow_module_loading) return; pa_log_info("Unloading \"%s\" (index: #%u).", m->name, m->index); - m->done(m->core, m); + if (m->done) + m->done(m); lt_dlclose(m->dl); @@ -199,9 +157,10 @@ static void pa_module_free(pa_module *m) { } void pa_module_unload(pa_core *c, pa_module *m) { - assert(c && m); + pa_assert(c); + pa_assert(m); - assert(c->modules); + pa_assert(c->modules); if (!(m = pa_idxset_remove_by_data(c->modules, m, NULL))) return; @@ -210,9 +169,9 @@ void pa_module_unload(pa_core *c, pa_module *m) { void pa_module_unload_by_index(pa_core *c, uint32_t idx) { pa_module *m; - assert(c && idx != PA_IDXSET_INVALID); + pa_assert(c); + pa_assert(idx != PA_IDXSET_INVALID); - assert(c->modules); if (!(m = pa_idxset_remove_by_index(c->modules, idx))) return; @@ -221,13 +180,14 @@ void pa_module_unload_by_index(pa_core *c, uint32_t idx) { static void free_callback(void *p, PA_GCC_UNUSED void *userdata) { pa_module *m = p; - assert(m); + pa_assert(m); pa_module_free(m); } void pa_module_unload_all(pa_core *c) { pa_module *m; - assert(c); + + pa_assert(c); if (!c->modules) return; @@ -252,7 +212,10 @@ void pa_module_unload_all(pa_core *c) { static int unused_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void *userdata) { pa_module *m = p; time_t *now = userdata; - assert(p && del && now); + + pa_assert(m); + pa_assert(del); + pa_assert(now); if (m->n_used == 0 && m->auto_unload && m->last_used_time+m->core->module_idle_time <= *now) { pa_module_free(m); @@ -264,7 +227,7 @@ static int unused_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, void * void pa_module_unload_unused(pa_core *c) { time_t now; - assert(c); + pa_assert(c); if (!c->modules) return; @@ -275,7 +238,7 @@ void pa_module_unload_unused(pa_core *c) { static int unload_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, PA_GCC_UNUSED void *userdata) { pa_module *m = p; - assert(m); + pa_assert(m); if (m->unload_requested) { pa_module_free(m); @@ -286,18 +249,19 @@ static int unload_callback(void *p, PA_GCC_UNUSED uint32_t idx, int *del, PA_GCC } static void defer_cb(pa_mainloop_api*api, pa_defer_event *e, void *userdata) { - pa_core *core = userdata; + pa_core *core = PA_CORE(userdata); + + pa_core_assert_ref(core); api->defer_enable(e, 0); if (!core->modules) return; pa_idxset_foreach(core->modules, unload_callback, NULL); - } void pa_module_unload_request(pa_module *m) { - assert(m); + pa_assert(m); m->unload_requested = 1; @@ -308,19 +272,19 @@ void pa_module_unload_request(pa_module *m) { } void pa_module_set_used(pa_module*m, int used) { - assert(m); + pa_assert(m); if (m->n_used != used) pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_CHANGE, m->index); - if (m->n_used != used && used == 0) + if (used == 0 && m->n_used > 0) time(&m->last_used_time); m->n_used = used; } pa_modinfo *pa_module_get_info(pa_module *m) { - assert(m); + pa_assert(m); - return pa_modinfo_get_by_handle(m->dl); + return pa_modinfo_get_by_handle(m->dl, m->name); } diff --git a/src/pulsecore/module.h b/src/pulsecore/module.h index 750dfaa8d..7a93a071a 100644 --- a/src/pulsecore/module.h +++ b/src/pulsecore/module.h @@ -39,8 +39,8 @@ struct pa_module { lt_dlhandle dl; - int (*init)(pa_core *c, pa_module*m); - void (*done)(pa_core *c, pa_module*m); + int (*init)(pa_module*m); + void (*done)(pa_module*m); void *userdata; @@ -62,9 +62,9 @@ void pa_module_unload_request(pa_module *m); void pa_module_set_used(pa_module*m, int used); -#define PA_MODULE_AUTHOR(s) const char * pa__get_author(void) { return s; } -#define PA_MODULE_DESCRIPTION(s) const char * pa__get_description(void) { return s; } -#define PA_MODULE_USAGE(s) const char * pa__get_usage(void) { return s; } +#define PA_MODULE_AUTHOR(s) const char *pa__get_author(void) { return s; } +#define PA_MODULE_DESCRIPTION(s) const char *pa__get_description(void) { return s; } +#define PA_MODULE_USAGE(s) const char *pa__get_usage(void) { return s; } #define PA_MODULE_VERSION(s) const char * pa__get_version(void) { return s; } pa_modinfo *pa_module_get_info(pa_module *m); diff --git a/src/pulsecore/msgobject.c b/src/pulsecore/msgobject.c new file mode 100644 index 000000000..f54e69f2c --- /dev/null +++ b/src/pulsecore/msgobject.c @@ -0,0 +1,49 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "msgobject.h" + +PA_DEFINE_CHECK_TYPE(pa_msgobject, pa_object); + +pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name)) { + pa_msgobject *o; + + pa_assert(size > sizeof(pa_msgobject)); + pa_assert(type_name); + + if (!check_type) + check_type = pa_msgobject_check_type; + + pa_assert(check_type(type_name)); + pa_assert(check_type("pa_object")); + pa_assert(check_type("pa_msgobject")); + + o = PA_MSGOBJECT(pa_object_new_internal(size, type_name, check_type)); + o->process_msg = NULL; + return o; +} diff --git a/src/pulsecore/msgobject.h b/src/pulsecore/msgobject.h new file mode 100644 index 000000000..8221cc330 --- /dev/null +++ b/src/pulsecore/msgobject.h @@ -0,0 +1,54 @@ +#ifndef foopulsemsgobjecthfoo +#define foopulsemsgobjecthfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include +#include +#include +#include +#include + +typedef struct pa_msgobject pa_msgobject; + +struct pa_msgobject { + pa_object parent; + int (*process_msg)(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk); +}; + +pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name)); + +int pa_msgobject_check_type(const char *type); + +#define pa_msgobject_new(type) ((type*) pa_msgobject_new_internal(sizeof(type), #type, type##_check_type)) +#define pa_msgobject_free ((void (*) (pa_msgobject* o)) pa_object_free) + +#define PA_MSGOBJECT(o) pa_msgobject_cast(o) + +PA_DECLARE_CLASS(pa_msgobject); + +#endif diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c index 52e731b36..1b13ede15 100644 --- a/src/pulsecore/mutex-posix.c +++ b/src/pulsecore/mutex-posix.c @@ -25,20 +25,16 @@ #include #endif -#include #include - -#include +#include #include +#include +#include +#include #include "mutex.h" -#define ASSERT_SUCCESS(x) do { \ - int _r = (x); \ - assert(_r == 0); \ -} while(0) - struct pa_mutex { pthread_mutex_t mutex; }; @@ -47,68 +43,88 @@ struct pa_cond { pthread_cond_t cond; }; -pa_mutex* pa_mutex_new(int recursive) { +pa_mutex* pa_mutex_new(pa_bool_t recursive, pa_bool_t inherit_priority) { pa_mutex *m; pthread_mutexattr_t attr; + int r; - pthread_mutexattr_init(&attr); + pa_assert_se(pthread_mutexattr_init(&attr) == 0); if (recursive) - ASSERT_SUCCESS(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)); + pa_assert_se(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0); + +#ifdef HAVE_PTHREAD_PRIO_INHERIT + if (inherit_priority) + pa_assert_se(pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT) == 0); +#endif m = pa_xnew(pa_mutex, 1); - ASSERT_SUCCESS(pthread_mutex_init(&m->mutex, &attr)); +#ifndef HAVE_PTHREAD_PRIO_INHERIT + pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0); + +#else + if ((r = pthread_mutex_init(&m->mutex, &attr))) { + + /* If this failed, then this was probably due to non-available + * priority inheritance. In which case we fall back to normal + * mutexes. */ + pa_assert(r == ENOTSUP && inherit_priority); + + pa_assert_se(pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_NONE) == 0); + pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0); + } +#endif + return m; } void pa_mutex_free(pa_mutex *m) { - assert(m); + pa_assert(m); - ASSERT_SUCCESS(pthread_mutex_destroy(&m->mutex)); + pa_assert_se(pthread_mutex_destroy(&m->mutex) == 0); pa_xfree(m); } void pa_mutex_lock(pa_mutex *m) { - assert(m); + pa_assert(m); - ASSERT_SUCCESS(pthread_mutex_lock(&m->mutex)); + pa_assert_se(pthread_mutex_lock(&m->mutex) == 0); } void pa_mutex_unlock(pa_mutex *m) { - assert(m); + pa_assert(m); - ASSERT_SUCCESS(pthread_mutex_unlock(&m->mutex)); + pa_assert_se(pthread_mutex_unlock(&m->mutex) == 0); } pa_cond *pa_cond_new(void) { pa_cond *c; c = pa_xnew(pa_cond, 1); - - ASSERT_SUCCESS(pthread_cond_init(&c->cond, NULL)); + pa_assert_se(pthread_cond_init(&c->cond, NULL) == 0); return c; } void pa_cond_free(pa_cond *c) { - assert(c); + pa_assert(c); - ASSERT_SUCCESS(pthread_cond_destroy(&c->cond)); + pa_assert_se(pthread_cond_destroy(&c->cond) == 0); pa_xfree(c); } void pa_cond_signal(pa_cond *c, int broadcast) { - assert(c); + pa_assert(c); if (broadcast) - ASSERT_SUCCESS(pthread_cond_broadcast(&c->cond)); + pa_assert_se(pthread_cond_broadcast(&c->cond) == 0); else - ASSERT_SUCCESS(pthread_cond_signal(&c->cond)); + pa_assert_se(pthread_cond_signal(&c->cond) == 0); } int pa_cond_wait(pa_cond *c, pa_mutex *m) { - assert(c); - assert(m); + pa_assert(c); + pa_assert(m); return pthread_cond_wait(&c->cond, &m->mutex); } diff --git a/src/pulsecore/mutex-win32.c b/src/pulsecore/mutex-win32.c index 1f16e24c7..77d63d159 100644 --- a/src/pulsecore/mutex-win32.c +++ b/src/pulsecore/mutex-win32.c @@ -40,7 +40,7 @@ struct pa_cond { pa_hashmap *wait_events; }; -pa_mutex* pa_mutex_new(int recursive) { +pa_mutex* pa_mutex_new(pa_bool_t recursive, pa_bool_t inherit_priority) { pa_mutex *m; m = pa_xnew(pa_mutex, 1); diff --git a/src/pulsecore/mutex.h b/src/pulsecore/mutex.h index b2e34c07a..72e887819 100644 --- a/src/pulsecore/mutex.h +++ b/src/pulsecore/mutex.h @@ -24,9 +24,17 @@ USA. ***/ +#include + typedef struct pa_mutex pa_mutex; -pa_mutex* pa_mutex_new(int recursive); +/* Please think twice before enabling priority inheritance. This is no + * magic wand! Use it only when the potentially priorized threads are + * good candidates for it. Don't use this blindly! Also, note that + * only very few operating systems actually implement this, hence this + * is merely a hint. */ +pa_mutex* pa_mutex_new(pa_bool_t recursive, pa_bool_t inherit_priority); + void pa_mutex_free(pa_mutex *m); void pa_mutex_lock(pa_mutex *m); void pa_mutex_unlock(pa_mutex *m); diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index 7f66af059..fe2be4671 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -27,7 +27,6 @@ #include #include -#include #include #include @@ -38,6 +37,7 @@ #include #include #include +#include #include "namereg.h" @@ -90,23 +90,22 @@ static char* cleanup_name(const char *name) { } void pa_namereg_free(pa_core *c) { - assert(c); + pa_assert(c); if (!c->namereg) return; - assert(pa_hashmap_size(c->namereg) == 0); + pa_assert(pa_hashmap_size(c->namereg) == 0); pa_hashmap_free(c->namereg, NULL, NULL); } const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail) { struct namereg_entry *e; char *n = NULL; - int r; - assert(c); - assert(name); - assert(data); + pa_assert(c); + pa_assert(name); + pa_assert(data); if (!*name) return NULL; @@ -142,7 +141,7 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t k = pa_xnew(char, l+4); for (i = 2; i <= 99; i++) { - snprintf(k, l+4, "%s.%u", name, i); + pa_snprintf(k, l+4, "%s.%u", name, i); if (!(e = pa_hashmap_get(c->namereg, k))) break; @@ -163,8 +162,7 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t e->name = n ? n : pa_xstrdup(name); e->data = data; - r = pa_hashmap_put(c->namereg, e->name, e); - assert (r >= 0); + pa_assert_se(pa_hashmap_put(c->namereg, e->name, e) >= 0); return e->name; } @@ -172,11 +170,10 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t void pa_namereg_unregister(pa_core *c, const char *name) { struct namereg_entry *e; - assert(c); - assert(name); + pa_assert(c); + pa_assert(name); - e = pa_hashmap_remove(c->namereg, name); - assert(e); + pa_assert_se(e = pa_hashmap_remove(c->namereg, name)); pa_xfree(e->name); pa_xfree(e); @@ -185,7 +182,7 @@ void pa_namereg_unregister(pa_core *c, const char *name) { void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload) { struct namereg_entry *e; uint32_t idx; - assert(c); + pa_assert(c); if (!name) { @@ -245,8 +242,8 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int a int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) { char **s; - assert(c); - assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE); + pa_assert(c); + pa_assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE); s = type == PA_NAMEREG_SINK ? &c->default_sink_name : &c->default_source_name; @@ -269,7 +266,7 @@ int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) const char *pa_namereg_get_default_sink_name(pa_core *c) { pa_sink *s; - assert(c); + pa_assert(c); if (c->default_sink_name) return c->default_sink_name; @@ -284,7 +281,7 @@ const char *pa_namereg_get_default_source_name(pa_core *c) { pa_source *s; uint32_t idx; - assert(c); + pa_assert(c); if (c->default_source_name) return c->default_source_name; diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h index f7a7da1de..9defc4a53 100644 --- a/src/pulsecore/native-common.h +++ b/src/pulsecore/native-common.h @@ -115,6 +115,11 @@ enum { PA_COMMAND_MOVE_SINK_INPUT, PA_COMMAND_MOVE_SOURCE_OUTPUT, + PA_COMMAND_SET_SINK_INPUT_MUTE, + + PA_COMMAND_SUSPEND_SINK, + PA_COMMAND_SUSPEND_SOURCE, + PA_COMMAND_MAX }; diff --git a/src/pulsecore/object.c b/src/pulsecore/object.c new file mode 100644 index 000000000..6c36242bb --- /dev/null +++ b/src/pulsecore/object.c @@ -0,0 +1,72 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "object.h" + +pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name)) { + pa_object *o; + + pa_assert(size > sizeof(pa_object)); + pa_assert(type_name); + + if (!check_type) + check_type = pa_object_check_type; + + pa_assert(check_type(type_name)); + pa_assert(check_type("pa_object")); + + o = pa_xmalloc(size); + PA_REFCNT_INIT(o); + o->type_name = type_name; + o->free = pa_object_free; + o->check_type = check_type; + + return o; +} + +pa_object *pa_object_ref(pa_object *o) { + pa_object_assert_ref(o); + + PA_REFCNT_INC(o); + return o; +} + +void pa_object_unref(pa_object *o) { + pa_object_assert_ref(o); + + if (PA_REFCNT_DEC(o) <= 0) { + pa_assert(o->free); + o->free(o); + } +} + +int pa_object_check_type(const char *type_name) { + pa_assert(type_name); + + return strcmp(type_name, "pa_object") == 0; +} diff --git a/src/pulsecore/object.h b/src/pulsecore/object.h new file mode 100644 index 000000000..562fd113a --- /dev/null +++ b/src/pulsecore/object.h @@ -0,0 +1,106 @@ +#ifndef foopulseobjecthfoo +#define foopulseobjecthfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +#include +#include +#include + +typedef struct pa_object pa_object; + +struct pa_object { + PA_REFCNT_DECLARE; + const char *type_name; + void (*free)(pa_object *o); + int (*check_type)(const char *type_name); +}; + +pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name)); +#define pa_object_new(type) ((type*) pa_object_new_internal(sizeof(type), #type, type##_check_type) + +#define pa_object_free ((void (*) (pa_object* o)) pa_xfree) + +int pa_object_check_type(const char *type); + +static inline int pa_object_isinstance(void *o) { + pa_object *obj = (pa_object*) o; + return obj ? obj->check_type("pa_object") : 0; +} + +pa_object *pa_object_ref(pa_object *o); +void pa_object_unref(pa_object *o); + +static inline int pa_object_refcnt(pa_object *o) { + return o ? PA_REFCNT_VALUE(o) : 0; +} + +static inline pa_object* pa_object_cast(void *o) { + pa_object *obj = (pa_object*) o; + pa_assert(!obj || obj->check_type("pa_object")); + return obj; +} + +#define pa_object_assert_ref(o) pa_assert(pa_object_refcnt(o) > 0) + +#define PA_OBJECT(o) pa_object_cast(o) + +#define PA_DECLARE_CLASS(c) \ + static inline int c##_isinstance(void *o) { \ + pa_object *obj = (pa_object*) o; \ + return obj ? obj->check_type(#c) : 1; \ + } \ + static inline c* c##_cast(void *o) { \ + pa_assert(c##_isinstance(o)); \ + return (c*) o; \ + } \ + static inline c* c##_ref(c *o) { \ + return (c*) pa_object_ref(PA_OBJECT(o)); \ + } \ + static inline void c##_unref(c* o) { \ + pa_object_unref(PA_OBJECT(o)); \ + } \ + static inline int c##_refcnt(c* o) { \ + return pa_object_refcnt(PA_OBJECT(o)); \ + } \ + static inline void c##_assert_ref(c *o) { \ + pa_object_assert_ref(PA_OBJECT(o)); \ + } \ + struct __stupid_useless_struct_to_allow_trailing_semicolon + +#define PA_DEFINE_CHECK_TYPE(c, parent) \ + int c##_check_type(const char *type) { \ + pa_assert(type); \ + if (strcmp(type, #c) == 0) \ + return 1; \ + return parent##_check_type(type); \ + } \ + struct __stupid_useless_struct_to_allow_trailing_semicolon + + +#endif diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c deleted file mode 100644 index 4af7b36e6..000000000 --- a/src/pulsecore/once-posix.c +++ /dev/null @@ -1,71 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of PulseAudio. - - Copyright 2006 Lennart Poettering - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include - -#include "once.h" - -#define ASSERT_SUCCESS(x) do { \ - int _r = (x); \ - assert(_r == 0); \ -} while(0) - -static pa_mutex *global_mutex; -static pthread_once_t global_mutex_once = PTHREAD_ONCE_INIT; - -static void global_mutex_once_func(void) { - global_mutex = pa_mutex_new(0); -} - -void pa_once(pa_once_t *control, pa_once_func_t func) { - assert(control); - assert(func); - - /* Create the global mutex */ - ASSERT_SUCCESS(pthread_once(&global_mutex_once, global_mutex_once_func)); - - /* Create the local mutex */ - pa_mutex_lock(global_mutex); - if (!control->mutex) - control->mutex = pa_mutex_new(1); - pa_mutex_unlock(global_mutex); - - /* Execute function */ - pa_mutex_lock(control->mutex); - if (!control->once_value) { - control->once_value = 1; - func(); - } - pa_mutex_unlock(control->mutex); - - /* Caveat: We have to make sure that the once func has completed - * before returning, even if the once func is not actually - * executed by us. Hence the awkward locking. */ -} diff --git a/src/pulsecore/once-win32.c b/src/pulsecore/once-win32.c deleted file mode 100644 index b30097c88..000000000 --- a/src/pulsecore/once-win32.c +++ /dev/null @@ -1,69 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of PulseAudio. - - Copyright 2006 Pierre Ossman for Cendio AB - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, - or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include - -#include - -#include "once.h" - -void pa_once(pa_once_t *control, pa_once_func_t func) { - HANDLE mutex; - char name[64]; - - assert(control); - assert(func); - - /* Create the global mutex */ - sprintf(name, "pulse%d", (int)GetCurrentProcessId()); - - mutex = CreateMutex(NULL, FALSE, name); - assert(mutex); - - /* Create the local mutex */ - WaitForSingleObject(mutex, INFINITE); - if (!control->mutex) - control->mutex = pa_mutex_new(1); - ReleaseMutex(mutex); - - CloseHandle(mutex); - - /* Execute function */ - pa_mutex_lock(control->mutex); - if (!control->once_value) { - control->once_value = 1; - func(); - } - pa_mutex_unlock(control->mutex); - - /* Caveat: We have to make sure that the once func has completed - * before returning, even if the once func is not actually - * executed by us. Hence the awkward locking. */ -} diff --git a/src/pulsecore/once.c b/src/pulsecore/once.c new file mode 100644 index 000000000..a358cf65b --- /dev/null +++ b/src/pulsecore/once.c @@ -0,0 +1,96 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "once.h" + +int pa_once_begin(pa_once *control) { + pa_mutex *m; + + pa_assert(control); + + if (pa_atomic_load(&control->done)) + return 0; + + pa_atomic_inc(&control->ref); + + /* Caveat: We have to make sure that the once func has completed + * before returning, even if the once func is not actually + * executed by us. Hence the awkward locking. */ + + for (;;) { + + if ((m = pa_atomic_ptr_load(&control->mutex))) { + + /* The mutex is stored in locked state, hence let's just + * wait until it is unlocked */ + pa_mutex_lock(m); + + pa_once_end(control); + return 0; + } + + pa_assert_se(m = pa_mutex_new(FALSE, FALSE)); + pa_mutex_lock(m); + + if (pa_atomic_ptr_cmpxchg(&control->mutex, NULL, m)) + return 1; + + pa_mutex_unlock(m); + pa_mutex_free(m); + } +} + +void pa_once_end(pa_once *control) { + pa_mutex *m; + + pa_assert(control); + + pa_atomic_store(&control->done, 1); + + pa_assert_se(m = pa_atomic_ptr_load(&control->mutex)); + pa_mutex_unlock(m); + + if (pa_atomic_dec(&control->ref) <= 1) { + pa_assert_se(pa_atomic_ptr_cmpxchg(&control->mutex, m, NULL)); + pa_mutex_free(m); + } +} + +/* Not reentrant -- how could it be? */ +void pa_run_once(pa_once *control, pa_once_func_t func) { + pa_assert(control); + pa_assert(func); + + if (pa_once_begin(control)) { + func(); + pa_once_end(control); + } +} + diff --git a/src/pulsecore/once.h b/src/pulsecore/once.h index c20fc0b4c..c9fe6d0a4 100644 --- a/src/pulsecore/once.h +++ b/src/pulsecore/once.h @@ -25,16 +25,52 @@ ***/ #include +#include typedef struct pa_once { - unsigned int once_value; - pa_mutex *mutex; -} pa_once_t; + pa_atomic_ptr_t mutex; + pa_atomic_t ref, done; +} pa_once; -#define PA_ONCE_INIT { .once_value = 0, .mutex = NULL } +#define PA_ONCE_INIT \ + { \ + .mutex = PA_ATOMIC_PTR_INIT(NULL), \ + .ref = PA_ATOMIC_INIT(0), \ + .done = PA_ATOMIC_INIT(0) \ + } +/* Not to be called directly, use the macros defined below instead */ +int pa_once_begin(pa_once *o); +void pa_once_end(pa_once *o); + +#define PA_ONCE_BEGIN \ + do { \ + static pa_once _once = PA_ONCE_INIT; \ + if (pa_once_begin(&_once)) {{ + +#define PA_ONCE_END \ + } \ + pa_once_end(&_once); \ + } \ + } while(0) + +/* + + Usage of these macros is like this: + + void foo() { + + PA_ONCE_BEGIN { + + ... stuff to be called just once ... + + } PA_ONCE_END; + } + +*/ + +/* Same API but calls a function */ typedef void (*pa_once_func_t) (void); - -void pa_once(pa_once_t *o, pa_once_func_t f); +void pa_run_once(pa_once *o, pa_once_func_t f); #endif diff --git a/src/pulsecore/packet.c b/src/pulsecore/packet.c index ce57cb3e3..2706efeaa 100644 --- a/src/pulsecore/packet.c +++ b/src/pulsecore/packet.c @@ -25,22 +25,22 @@ #include #endif -#include #include #include +#include #include "packet.h" pa_packet* pa_packet_new(size_t length) { pa_packet *p; - assert(length); + pa_assert(length > 0); - p = pa_xmalloc(sizeof(pa_packet)+length); - p->ref = 1; + p = pa_xmalloc(PA_ALIGN(sizeof(pa_packet)) + length); + PA_REFCNT_INIT(p); p->length = length; - p->data = (uint8_t*) (p+1); + p->data = (uint8_t*) p + PA_ALIGN(sizeof(pa_packet)); p->type = PA_PACKET_APPENDED; return p; @@ -49,11 +49,11 @@ pa_packet* pa_packet_new(size_t length) { pa_packet* pa_packet_new_dynamic(void* data, size_t length) { pa_packet *p; - assert(data); - assert(length); + pa_assert(data); + pa_assert(length > 0); p = pa_xnew(pa_packet, 1); - p->ref = 1; + PA_REFCNT_INIT(p); p->length = length; p->data = data; p->type = PA_PACKET_DYNAMIC; @@ -62,18 +62,18 @@ pa_packet* pa_packet_new_dynamic(void* data, size_t length) { } pa_packet* pa_packet_ref(pa_packet *p) { - assert(p); - assert(p->ref >= 1); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) >= 1); - p->ref++; + PA_REFCNT_INC(p); return p; } void pa_packet_unref(pa_packet *p) { - assert(p); - assert(p->ref >= 1); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) >= 1); - if (--p->ref == 0) { + if (PA_REFCNT_DEC(p) <= 0) { if (p->type == PA_PACKET_DYNAMIC) pa_xfree(p->data); pa_xfree(p); diff --git a/src/pulsecore/packet.h b/src/pulsecore/packet.h index 842582c86..bcac4a7f3 100644 --- a/src/pulsecore/packet.h +++ b/src/pulsecore/packet.h @@ -27,9 +27,11 @@ #include #include +#include + typedef struct pa_packet { + PA_REFCNT_DECLARE; enum { PA_PACKET_APPENDED, PA_PACKET_DYNAMIC } type; - unsigned ref; size_t length; uint8_t *data; } pa_packet; diff --git a/src/pulsecore/parseaddr.c b/src/pulsecore/parseaddr.c index a49a09ed7..65ba64c1c 100644 --- a/src/pulsecore/parseaddr.c +++ b/src/pulsecore/parseaddr.c @@ -26,13 +26,13 @@ #endif #include -#include #include #include - #include + #include +#include #include "parseaddr.h" @@ -45,7 +45,9 @@ * Return a newly allocated string of the hostname and fill in *ret_port if specified */ static char *parse_host(const char *s, uint16_t *ret_port) { - assert(s && ret_port); + pa_assert(s); + pa_assert(ret_port); + if (*s == '[') { char *e; if (!(e = strchr(s+1, ']'))) @@ -70,7 +72,10 @@ static char *parse_host(const char *s, uint16_t *ret_port) { int pa_parse_address(const char *name, pa_parsed_address *ret_p) { const char *p; - assert(name && ret_p); + + pa_assert(name); + pa_assert(ret_p); + memset(ret_p, 0, sizeof(pa_parsed_address)); ret_p->type = PA_PARSED_ADDRESS_TCP_AUTO; @@ -112,6 +117,5 @@ int pa_parse_address(const char *name, pa_parsed_address *ret_p) { if (!(ret_p->path_or_host = parse_host(p, &ret_p->port))) return -1; - return 0; } diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 10238acb0..2c95d7407 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -37,6 +36,8 @@ #include #include #include +#include +#include #include "pdispatch.h" @@ -108,7 +109,7 @@ struct reply_info { }; struct pa_pdispatch { - int ref; + PA_REFCNT_DECLARE; pa_mainloop_api *mainloop; const pa_pdispatch_cb_t *callback_table; unsigned n_commands; @@ -119,7 +120,9 @@ struct pa_pdispatch { }; static void reply_info_free(struct reply_info *r) { - assert(r && r->pdispatch && r->pdispatch->mainloop); + pa_assert(r); + pa_assert(r->pdispatch); + pa_assert(r->pdispatch->mainloop); if (r->time_event) r->pdispatch->mainloop->time_free(r->time_event); @@ -131,12 +134,12 @@ static void reply_info_free(struct reply_info *r) { pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_t*table, unsigned entries) { pa_pdispatch *pd; - assert(mainloop); + pa_assert(mainloop); - assert((entries && table) || (!entries && !table)); + pa_assert((entries && table) || (!entries && !table)); - pd = pa_xmalloc(sizeof(pa_pdispatch)); - pd->ref = 1; + pd = pa_xnew(pa_pdispatch, 1); + PA_REFCNT_INIT(pd); pd->mainloop = mainloop; pd->callback_table = table; pd->n_commands = entries; @@ -149,7 +152,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_ } static void pdispatch_free(pa_pdispatch *pd) { - assert(pd); + pa_assert(pd); while (pd->replies) { if (pd->replies->free_cb) @@ -165,7 +168,7 @@ static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command, pa_pdispatch_cb_t callback; void *userdata; uint32_t tag; - assert(r); + pa_assert(r); pa_pdispatch_ref(pd); @@ -187,7 +190,12 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, uint32_t tag, command; pa_tagstruct *ts = NULL; int ret = -1; - assert(pd && packet && packet->data); + + pa_assert(pd); + pa_assert(PA_REFCNT_VALUE(pd) >= 1); + pa_assert(packet); + pa_assert(PA_REFCNT_VALUE(packet) >= 1); + pa_assert(packet->data); pa_pdispatch_ref(pd); @@ -195,7 +203,6 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, goto finish; ts = pa_tagstruct_new(packet->data, packet->length); - assert(ts); if (pa_tagstruct_getu32(ts, &command) < 0 || pa_tagstruct_getu32(ts, &tag) < 0) @@ -206,7 +213,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds, char t[256]; char const *p; if (!(p = command_names[command])) - snprintf((char*) (p = t), sizeof(t), "%u", command); + pa_snprintf((char*) (p = t), sizeof(t), "%u", command); pa_log("Recieved opcode <%s>", p); } @@ -248,7 +255,12 @@ finish: static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { struct reply_info*r = userdata; - assert(r && r->time_event == e && r->pdispatch && r->pdispatch->mainloop == m && r->callback); + + pa_assert(r); + pa_assert(r->time_event == e); + pa_assert(r->pdispatch); + pa_assert(r->pdispatch->mainloop == m); + pa_assert(r->callback); run_action(r->pdispatch, r, PA_COMMAND_TIMEOUT, NULL); } @@ -256,7 +268,10 @@ static void timeout_callback(pa_mainloop_api*m, pa_time_event*e, PA_GCC_UNUSED c void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t cb, void *userdata, pa_free_cb_t free_cb) { struct reply_info *r; struct timeval tv; - assert(pd && pd->ref >= 1 && cb); + + pa_assert(pd); + pa_assert(PA_REFCNT_VALUE(pd) >= 1); + pa_assert(cb); r = pa_xnew(struct reply_info, 1); r->pdispatch = pd; @@ -268,21 +283,22 @@ void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa pa_gettimeofday(&tv); tv.tv_sec += timeout; - r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r); - assert(r->time_event); + pa_assert_se(r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r)); PA_LLIST_PREPEND(struct reply_info, pd->replies, r); } int pa_pdispatch_is_pending(pa_pdispatch *pd) { - assert(pd); + pa_assert(pd); + pa_assert(PA_REFCNT_VALUE(pd) >= 1); return !!pd->replies; } void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, void (*cb)(pa_pdispatch *pd, void *userdata), void *userdata) { - assert(pd); - assert(!cb || pa_pdispatch_is_pending(pd)); + pa_assert(pd); + pa_assert(PA_REFCNT_VALUE(pd) >= 1); + pa_assert(!cb || pa_pdispatch_is_pending(pd)); pd->drain_callback = cb; pd->drain_userdata = userdata; @@ -290,7 +306,9 @@ void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, void (*cb)(pa_pdispatch * void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata) { struct reply_info *r, *n; - assert(pd); + + pa_assert(pd); + pa_assert(PA_REFCNT_VALUE(pd) >= 1); for (r = pd->replies; r; r = n) { n = r->next; @@ -301,21 +319,24 @@ void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata) { } void pa_pdispatch_unref(pa_pdispatch *pd) { - assert(pd && pd->ref >= 1); + pa_assert(pd); + pa_assert(PA_REFCNT_VALUE(pd) >= 1); - if (!(--(pd->ref))) + if (PA_REFCNT_DEC(pd) <= 0) pdispatch_free(pd); } pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd) { - assert(pd && pd->ref >= 1); - pd->ref++; + pa_assert(pd); + pa_assert(PA_REFCNT_VALUE(pd) >= 1); + + PA_REFCNT_INC(pd); return pd; } const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd) { - assert(pd); - assert(pd->ref >= 1); + pa_assert(pd); + pa_assert(PA_REFCNT_VALUE(pd) >= 1); return pd->creds; } diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index 5e670e17a..55ff2088b 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -47,6 +46,7 @@ #include #include #include +#include #include "pid.h" @@ -57,11 +57,11 @@ static pid_t read_pid(const char *fn, int fd) { char t[20], *e; uint32_t pid; - assert(fn && fd >= 0); + pa_assert(fn); + pa_assert(fd >= 0); if ((r = pa_loop_read(fd, t, sizeof(t)-1, NULL)) < 0) { - pa_log_warn("WARNING: failed to read PID file '%s': %s", - fn, pa_cstrerror(errno)); + pa_log_warn("Failed to read PID file '%s': %s", fn, pa_cstrerror(errno)); return (pid_t) -1; } @@ -73,7 +73,7 @@ static pid_t read_pid(const char *fn, int fd) { *e = 0; if (pa_atou(t, &pid) < 0) { - pa_log("WARNING: failed to parse PID file '%s'", fn); + pa_log_warn("Failed to parse PID file '%s'", fn); return (pid_t) -1; } @@ -83,13 +83,22 @@ static pid_t read_pid(const char *fn, int fd) { static int open_pid_file(const char *fn, int mode) { int fd = -1; + pa_assert(fn); + for (;;) { struct stat st; - if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) { + if ((fd = open(fn, mode +#ifdef O_NOCTTY + |O_NOCTTY +#endif +#ifdef O_NOFOLLOW + |O_NOFOLLOW +#endif + , S_IRUSR|S_IWUSR + )) < 0) { if (mode != O_RDONLY || errno != ENOENT) - pa_log_warn("WARNING: failed to open PID file '%s': %s", - fn, pa_cstrerror(errno)); + pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -98,8 +107,7 @@ static int open_pid_file(const char *fn, int mode) { goto fail; if (fstat(fd, &st) < 0) { - pa_log_warn("WARNING: failed to fstat() PID file '%s': %s", - fn, pa_cstrerror(errno)); + pa_log_warn("Failed to fstat() PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -110,9 +118,9 @@ static int open_pid_file(const char *fn, int mode) { if (pa_lock_fd(fd, 0) < 0) goto fail; - if (close(fd) < 0) { - pa_log_warn("WARNING: failed to close file '%s': %s", - fn, pa_cstrerror(errno)); + if (pa_close(fd) < 0) { + pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno)); + fd = -1; goto fail; } @@ -125,7 +133,7 @@ fail: if (fd >= 0) { pa_lock_fd(fd, 0); - close(fd); + pa_close(fd); } return -1; @@ -150,7 +158,7 @@ int pa_pid_file_create(void) { goto fail; if ((pid = read_pid(fn, fd)) == (pid_t) -1) - pa_log("corrupt PID file, overwriting."); + pa_log_warn("Corrupt PID file, overwriting."); else if (pid > 0) { #ifdef OS_IS_WIN32 if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) { @@ -158,25 +166,24 @@ int pa_pid_file_create(void) { #else if (kill(pid, 0) >= 0 || errno != ESRCH) { #endif - pa_log("daemon already running."); + pa_log("Daemon already running."); goto fail; } - pa_log("stale PID file, overwriting."); + pa_log_warn("Stale PID file, overwriting."); } /* Overwrite the current PID file */ if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) { - pa_log("failed to truncate PID file '%s': %s", - fn, pa_cstrerror(errno)); + pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } - snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid()); + pa_snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid()); l = strlen(t); if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) { - pa_log("failed to write PID file."); + pa_log("Failed to write PID file."); goto fail; } @@ -185,7 +192,11 @@ int pa_pid_file_create(void) { fail: if (fd >= 0) { pa_lock_fd(fd, 0); - close(fd); + + if (pa_close(fd) < 0) { + pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno)); + ret = -1; + } } return ret; @@ -201,8 +212,7 @@ int pa_pid_file_remove(void) { pa_runtime_path("pid", fn, sizeof(fn)); if ((fd = open_pid_file(fn, O_RDWR)) < 0) { - pa_log_warn("WARNING: failed to open PID file '%s': %s", - fn, pa_cstrerror(errno)); + pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -210,13 +220,12 @@ int pa_pid_file_remove(void) { goto fail; if (pid != getpid()) { - pa_log("WARNING: PID file '%s' not mine!", fn); + pa_log("PID file '%s' not mine!", fn); goto fail; } if (ftruncate(fd, 0) < 0) { - pa_log_warn("WARNING: failed to truncate PID file '%s': %s", - fn, pa_cstrerror(errno)); + pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -227,8 +236,7 @@ int pa_pid_file_remove(void) { #endif if (unlink(fn) < 0) { - pa_log_warn("WARNING: failed to remove PID file '%s': %s", - fn, pa_cstrerror(errno)); + pa_log_warn("Failed to remove PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -238,7 +246,11 @@ fail: if (fd >= 0) { pa_lock_fd(fd, 0); - close(fd); + + if (pa_close(fd) < 0) { + pa_log_warn("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno)); + ret = -1; + } } return ret; @@ -280,7 +292,7 @@ fail: if (fd >= 0) { pa_lock_fd(fd, 0); - close(fd); + pa_close(fd); } return ret; diff --git a/src/pulsecore/pipe.c b/src/pulsecore/pipe.c index 7f6bb2e9e..e614c9c62 100644 --- a/src/pulsecore/pipe.c +++ b/src/pulsecore/pipe.c @@ -149,14 +149,14 @@ int pipe(int filedes[2]) { return 0; error: - if (listener >= 0) - pa_close(listener); - if (filedes[0] >= 0) - pa_close(filedes[0]); - if (filedes[1] >= 0) - pa_close(filedes[0]); + if (listener >= 0) + pa_close(listener); + if (filedes[0] >= 0) + pa_close(filedes[0]); + if (filedes[1] >= 0) + pa_close(filedes[0]); - return -1; + return -1; } #endif /* HAVE_PIPE */ diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c index 76edd27a0..5d3c2d391 100644 --- a/src/pulsecore/play-memblockq.c +++ b/src/pulsecore/play-memblockq.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include @@ -34,50 +33,171 @@ #include #include +#include #include "play-memblockq.h" -static void sink_input_kill(pa_sink_input *i) { - pa_memblockq *q; - assert(i); - assert(i->userdata); +typedef struct memblockq_stream { + pa_msgobject parent; + pa_core *core; + pa_sink_input *sink_input; + pa_memblockq *memblockq; +} memblockq_stream; - q = i->userdata; +enum { + MEMBLOCKQ_STREAM_MESSAGE_UNLINK, +}; - pa_sink_input_disconnect(i); - pa_sink_input_unref(i); +PA_DECLARE_CLASS(memblockq_stream); +#define MEMBLOCKQ_STREAM(o) (memblockq_stream_cast(o)) +static PA_DEFINE_CHECK_TYPE(memblockq_stream, pa_msgobject); - pa_memblockq_free(q); +static void memblockq_stream_unlink(memblockq_stream *u) { + pa_assert(u); + + if (!u->sink_input) + return; + + pa_sink_input_unlink(u->sink_input); + + pa_sink_input_unref(u->sink_input); + u->sink_input = NULL; + + memblockq_stream_unref(u); } -static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { - pa_memblockq *q; - assert(i); - assert(chunk); - assert(i->userdata); +static void memblockq_stream_free(pa_object *o) { + memblockq_stream *u = MEMBLOCKQ_STREAM(o); + pa_assert(u); - q = i->userdata; + memblockq_stream_unlink(u); - return pa_memblockq_peek(q, chunk); + if (u->memblockq) + pa_memblockq_free(u->memblockq); + + pa_xfree(u); } -static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) { - sink_input_kill(i); +static int memblockq_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) { + memblockq_stream *u = MEMBLOCKQ_STREAM(o); + memblockq_stream_assert_ref(u); + + switch (code) { + case MEMBLOCKQ_STREAM_MESSAGE_UNLINK: + memblockq_stream_unlink(u); + break; + } + + return 0; } -static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) { - pa_memblockq *q; +static void sink_input_kill_cb(pa_sink_input *i) { + pa_sink_input_assert_ref(i); - assert(i); - assert(length > 0); - assert( i->userdata); + memblockq_stream_unlink(MEMBLOCKQ_STREAM(i->userdata)); +} - q = i->userdata; +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { + memblockq_stream *u; - pa_memblockq_drop(q, chunk, length); + pa_assert(i); + pa_assert(chunk); + u = MEMBLOCKQ_STREAM(i->userdata); + memblockq_stream_assert_ref(u); - if (pa_memblockq_get_length(q) <= 0) - pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); + if (!u->memblockq) + return -1; + + if (pa_memblockq_peek(u->memblockq, chunk) < 0) { + pa_memblockq_free(u->memblockq); + u->memblockq = NULL; + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), MEMBLOCKQ_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL); + return -1; + } + + return 0; +} + +static void sink_input_drop_cb(pa_sink_input *i, size_t length) { + memblockq_stream *u; + + pa_assert(i); + pa_assert(length > 0); + u = MEMBLOCKQ_STREAM(i->userdata); + memblockq_stream_assert_ref(u); + + if (!u->memblockq) + return; + + pa_memblockq_drop(u->memblockq, length); +} + +pa_sink_input* pa_memblockq_sink_input_new( + pa_sink *sink, + const char *name, + const pa_sample_spec *ss, + const pa_channel_map *map, + pa_memblockq *q, + pa_cvolume *volume) { + + memblockq_stream *u = NULL; + pa_sink_input_new_data data; + + pa_assert(sink); + pa_assert(ss); + + /* We allow creating this stream with no q set, so that it can be + * filled in later */ + + if (q && pa_memblockq_get_length(q) <= 0) { + pa_memblockq_free(q); + return NULL; + } + + if (volume && pa_cvolume_is_muted(volume)) { + pa_memblockq_free(q); + return NULL; + } + + u = pa_msgobject_new(memblockq_stream); + u->parent.parent.free = memblockq_stream_free; + u->parent.process_msg = memblockq_stream_process_msg; + u->core = sink->core; + u->sink_input = NULL; + u->memblockq = q; + + pa_sink_input_new_data_init(&data); + data.sink = sink; + data.name = name; + data.driver = __FILE__; + pa_sink_input_new_data_set_sample_spec(&data, ss); + pa_sink_input_new_data_set_channel_map(&data, map); + pa_sink_input_new_data_set_volume(&data, volume); + + if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0))) + goto fail; + + u->sink_input->peek = sink_input_peek_cb; + u->sink_input->drop = sink_input_drop_cb; + u->sink_input->kill = sink_input_kill_cb; + u->sink_input->userdata = u; + + if (q) + pa_memblockq_prebuf_disable(q); + + /* The reference to u is dangling here, because we want + * to keep this stream around until it is fully played. */ + + /* This sink input is not "put" yet, i.e. pa_sink_input_put() has + * not been called! */ + + return pa_sink_input_ref(u->sink_input); + +fail: + if (u) + memblockq_stream_unref(u); + + return NULL; } int pa_play_memblockq( @@ -88,41 +208,29 @@ int pa_play_memblockq( pa_memblockq *q, pa_cvolume *volume) { - pa_sink_input *si; - pa_sink_input_new_data data; + pa_sink_input *i; - assert(sink); - assert(ss); - assert(q); + pa_assert(sink); + pa_assert(ss); + pa_assert(q); - if (pa_memblockq_get_length(q) <= 0) { - pa_memblockq_free(q); - return 0; - } - - if (volume && pa_cvolume_is_muted(volume)) { - pa_memblockq_free(q); - return 0; - } - - pa_sink_input_new_data_init(&data); - data.sink = sink; - data.name = name; - data.driver = __FILE__; - pa_sink_input_new_data_set_channel_map(&data, map); - pa_sink_input_new_data_set_sample_spec(&data, ss); - pa_sink_input_new_data_set_volume(&data, volume); - - if (!(si = pa_sink_input_new(sink->core, &data, 0))) + if (!(i = pa_memblockq_sink_input_new(sink, name, ss, map, q, volume))) return -1; - si->peek = sink_input_peek; - si->drop = sink_input_drop; - si->kill = sink_input_kill; - - si->userdata = q; - - pa_sink_notify(si->sink); + pa_sink_input_put(i); + pa_sink_input_unref(i); return 0; } + +void pa_memblockq_sink_input_set_queue(pa_sink_input *i, pa_memblockq *q) { + memblockq_stream *u; + + pa_sink_input_assert_ref(i); + u = MEMBLOCKQ_STREAM(i->userdata); + memblockq_stream_assert_ref(u); + + if (u->memblockq) + pa_memblockq_free(u->memblockq); + u->memblockq = q; +} diff --git a/src/pulsecore/play-memblockq.h b/src/pulsecore/play-memblockq.h index 8248e8597..d8790316a 100644 --- a/src/pulsecore/play-memblockq.h +++ b/src/pulsecore/play-memblockq.h @@ -27,6 +27,16 @@ #include #include +pa_sink_input* pa_memblockq_sink_input_new( + pa_sink *sink, + const char *name, + const pa_sample_spec *ss, + const pa_channel_map *map, + pa_memblockq *q, + pa_cvolume *volume); + +void pa_memblockq_sink_input_set_queue(pa_sink_input *i, pa_memblockq *q); + int pa_play_memblockq( pa_sink *sink, const char *name, diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c index 9132e2945..6aaec5672 100644 --- a/src/pulsecore/play-memchunk.c +++ b/src/pulsecore/play-memchunk.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include @@ -34,53 +33,108 @@ #include #include +#include #include "play-memchunk.h" -static void sink_input_kill(pa_sink_input *i) { - pa_memchunk *c; - assert(i && i->userdata); - c = i->userdata; +typedef struct memchunk_stream { + pa_msgobject parent; + pa_core *core; + pa_sink_input *sink_input; + pa_memchunk memchunk; +} memchunk_stream; - pa_sink_input_disconnect(i); - pa_sink_input_unref(i); +enum { + MEMCHUNK_STREAM_MESSAGE_UNLINK, +}; - pa_memblock_unref(c->memblock); - pa_xfree(c); +PA_DECLARE_CLASS(memchunk_stream); +#define MEMCHUNK_STREAM(o) (memchunk_stream_cast(o)) +static PA_DEFINE_CHECK_TYPE(memchunk_stream, pa_msgobject); + +static void memchunk_stream_unlink(memchunk_stream *u) { + pa_assert(u); + + if (!u->sink_input) + return; + + pa_sink_input_unlink(u->sink_input); + + pa_sink_input_unref(u->sink_input); + u->sink_input = NULL; + + memchunk_stream_unref(u); } -static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { - pa_memchunk *c; - assert(i && chunk && i->userdata); - c = i->userdata; +static void memchunk_stream_free(pa_object *o) { + memchunk_stream *u = MEMCHUNK_STREAM(o); + pa_assert(u); - if (c->length <= 0) - return -1; + memchunk_stream_unlink(u); - assert(c->memblock && c->memblock->length); - *chunk = *c; - pa_memblock_ref(c->memblock); + if (u->memchunk.memblock) + pa_memblock_unref(u->memchunk.memblock); + + pa_xfree(u); +} + +static int memchunk_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) { + memchunk_stream *u = MEMCHUNK_STREAM(o); + memchunk_stream_assert_ref(u); + + switch (code) { + case MEMCHUNK_STREAM_MESSAGE_UNLINK: + memchunk_stream_unlink(u); + break; + } return 0; } -static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) { - sink_input_kill(i); +static void sink_input_kill_cb(pa_sink_input *i) { + pa_sink_input_assert_ref(i); + + memchunk_stream_unlink(MEMCHUNK_STREAM(i->userdata)); } -static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) { - pa_memchunk *c; - assert(i && length && i->userdata); - c = i->userdata; +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { + memchunk_stream *u; - assert(!memcmp(chunk, c, sizeof(chunk))); - assert(length <= c->length); + pa_assert(i); + pa_assert(chunk); + u = MEMCHUNK_STREAM(i->userdata); + memchunk_stream_assert_ref(u); - c->length -= length; - c->index += length; + if (!u->memchunk.memblock) + return -1; - if (c->length <= 0) - pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i); + if (u->memchunk.length <= 0) { + pa_memblock_unref(u->memchunk.memblock); + u->memchunk.memblock = NULL; + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), MEMCHUNK_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL); + return -1; + } + + pa_assert(u->memchunk.memblock); + *chunk = u->memchunk; + pa_memblock_ref(chunk->memblock); + + return 0; +} + +static void sink_input_drop_cb(pa_sink_input *i, size_t length) { + memchunk_stream *u; + + pa_assert(i); + pa_assert(length > 0); + u = MEMCHUNK_STREAM(i->userdata); + memchunk_stream_assert_ref(u); + + if (length < u->memchunk.length) { + u->memchunk.length -= length; + u->memchunk.index += length; + } else + u->memchunk.length = 0; } int pa_play_memchunk( @@ -91,38 +145,52 @@ int pa_play_memchunk( const pa_memchunk *chunk, pa_cvolume *volume) { - pa_sink_input *si; - pa_memchunk *nchunk; + memchunk_stream *u = NULL; pa_sink_input_new_data data; - assert(sink); - assert(ss); - assert(chunk); + pa_assert(sink); + pa_assert(ss); + pa_assert(chunk); if (volume && pa_cvolume_is_muted(volume)) return 0; + pa_memchunk_will_need(chunk); + + u = pa_msgobject_new(memchunk_stream); + u->parent.parent.free = memchunk_stream_free; + u->parent.process_msg = memchunk_stream_process_msg; + u->core = sink->core; + u->memchunk = *chunk; + pa_memblock_ref(u->memchunk.memblock); + pa_sink_input_new_data_init(&data); data.sink = sink; - data.name = name; data.driver = __FILE__; + data.name = name; pa_sink_input_new_data_set_sample_spec(&data, ss); pa_sink_input_new_data_set_channel_map(&data, map); pa_sink_input_new_data_set_volume(&data, volume); - if (!(si = pa_sink_input_new(sink->core, &data, 0))) - return -1; + if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0))) + goto fail; - si->peek = sink_input_peek; - si->drop = sink_input_drop; - si->kill = sink_input_kill; + u->sink_input->peek = sink_input_peek_cb; + u->sink_input->drop = sink_input_drop_cb; + u->sink_input->kill = sink_input_kill_cb; + u->sink_input->userdata = u; - si->userdata = nchunk = pa_xnew(pa_memchunk, 1); - *nchunk = *chunk; + pa_sink_input_put(u->sink_input); - pa_memblock_ref(chunk->memblock); - - pa_sink_notify(si->sink); + /* The reference to u is dangling here, because we want to keep + * this stream around until it is fully played. */ return 0; + +fail: + if (u) + memchunk_stream_unref(u); + + return -1; } + diff --git a/src/pulsecore/poll.c b/src/pulsecore/poll.c index 2f8eae89b..288f7dfb2 100644 --- a/src/pulsecore/poll.c +++ b/src/pulsecore/poll.c @@ -45,7 +45,7 @@ #include "winsock.h" -#ifndef HAVE_SYS_POLL_H +#ifndef HAVE_POLL_H #include diff --git a/src/pulsecore/props.c b/src/pulsecore/props.c index 4a39f0fb9..cbf748dfb 100644 --- a/src/pulsecore/props.c +++ b/src/pulsecore/props.c @@ -21,11 +21,13 @@ USA. ***/ -#include +#ifdef HAVE_CONFIG_H +#include +#endif #include - #include +#include #include "props.h" @@ -37,9 +39,11 @@ typedef struct pa_property { /* Allocate a new property object */ static pa_property* property_new(const char *name, void *data) { pa_property* p; - assert(name && data); - p = pa_xmalloc(sizeof(pa_property)); + pa_assert(name); + pa_assert(data); + + p = pa_xnew(pa_property, 1); p->name = pa_xstrdup(name); p->data = data; @@ -48,7 +52,7 @@ static pa_property* property_new(const char *name, void *data) { /* Free a property object */ static void property_free(pa_property *p) { - assert(p); + pa_assert(p); pa_xfree(p->name); pa_xfree(p); @@ -56,7 +60,10 @@ static void property_free(pa_property *p) { void* pa_property_get(pa_core *c, const char *name) { pa_property *p; - assert(c && name && c->properties); + + pa_assert(c); + pa_assert(name); + pa_assert(c->properties); if (!(p = pa_hashmap_get(c->properties, name))) return NULL; @@ -66,7 +73,11 @@ void* pa_property_get(pa_core *c, const char *name) { int pa_property_set(pa_core *c, const char *name, void *data) { pa_property *p; - assert(c && name && data && c->properties); + + pa_assert(c); + pa_assert(name); + pa_assert(data); + pa_assert(c->properties); if (pa_hashmap_get(c->properties, name)) return -1; @@ -78,7 +89,10 @@ int pa_property_set(pa_core *c, const char *name, void *data) { int pa_property_remove(pa_core *c, const char *name) { pa_property *p; - assert(c && name && c->properties); + + pa_assert(c); + pa_assert(name); + pa_assert(c->properties); if (!(p = pa_hashmap_remove(c->properties, name))) return -1; @@ -88,18 +102,18 @@ int pa_property_remove(pa_core *c, const char *name) { } void pa_property_init(pa_core *c) { - assert(c); + pa_assert(c); c->properties = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); } void pa_property_cleanup(pa_core *c) { - assert(c); + pa_assert(c); if (!c->properties) return; - assert(!pa_hashmap_size(c->properties)); + pa_assert(!pa_hashmap_size(c->properties)); pa_hashmap_free(c->properties, NULL, NULL); c->properties = NULL; @@ -109,14 +123,17 @@ void pa_property_cleanup(pa_core *c) { void pa_property_dump(pa_core *c, pa_strbuf *s) { void *state = NULL; pa_property *p; - assert(c && s); + + pa_assert(c); + pa_assert(s); while ((p = pa_hashmap_iterate(c->properties, &state, NULL))) pa_strbuf_printf(s, "[%s] -> [%p]\n", p->name, p->data); } int pa_property_replace(pa_core *c, const char *name, void *data) { - assert(c && name); + pa_assert(c); + pa_assert(name); pa_property_remove(c, name); return pa_property_set(c, name, data); diff --git a/src/pulsecore/protocol-cli.c b/src/pulsecore/protocol-cli.c index 1d543ae55..ceb6ae4d8 100644 --- a/src/pulsecore/protocol-cli.c +++ b/src/pulsecore/protocol-cli.c @@ -25,13 +25,13 @@ #include #endif -#include #include #include #include #include +#include #include "protocol-cli.h" @@ -47,7 +47,8 @@ struct pa_protocol_cli { static void cli_eof_cb(pa_cli*c, void*userdata) { pa_protocol_cli *p = userdata; - assert(p); + pa_assert(p); + pa_idxset_remove_by_data(p->connections, c, NULL); pa_cli_free(c); } @@ -55,7 +56,10 @@ static void cli_eof_cb(pa_cli*c, void*userdata) { static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) { pa_protocol_cli *p = userdata; pa_cli *c; - assert(s && io && p); + + pa_assert(s); + pa_assert(io); + pa_assert(p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); @@ -64,7 +68,6 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) } c = pa_cli_new(p->core, io, p->module); - assert(c); pa_cli_set_eof_callback(c, cli_eof_cb, p); pa_idxset_put(p->connections, c, NULL); @@ -72,9 +75,11 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) pa_protocol_cli* pa_protocol_cli_new(pa_core *core, pa_socket_server *server, pa_module *m, PA_GCC_UNUSED pa_modargs *ma) { pa_protocol_cli* p; - assert(core && server); - p = pa_xmalloc(sizeof(pa_protocol_cli)); + pa_core_assert_ref(core); + pa_assert(server); + + p = pa_xnew(pa_protocol_cli, 1); p->module = m; p->core = core; p->server = server; @@ -86,12 +91,13 @@ pa_protocol_cli* pa_protocol_cli_new(pa_core *core, pa_socket_server *server, pa } static void free_connection(void *p, PA_GCC_UNUSED void *userdata) { - assert(p); + pa_assert(p); + pa_cli_free(p); } void pa_protocol_cli_free(pa_protocol_cli *p) { - assert(p); + pa_assert(p); pa_idxset_free(p->connections, free_connection, NULL); pa_socket_server_unref(p->server); diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 49a78d410..76ba9dd08 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -53,6 +52,8 @@ #include #include #include +#include +#include #include "endianmacros.h" @@ -77,13 +78,15 @@ /* This is heavily based on esound's code */ -struct connection { +typedef struct connection { + pa_msgobject parent; + uint32_t index; - int dead; + pa_bool_t dead; pa_protocol_esound *protocol; pa_iochannel *io; pa_client *client; - int authorized, swap_byte_order; + pa_bool_t authorized, swap_byte_order; void *write_data; size_t write_data_alloc, write_data_index, write_data_length; void *read_data; @@ -100,6 +103,7 @@ struct connection { struct { pa_memblock *current_memblock; size_t memblock_index, fragment_size; + pa_atomic_t missing; } playback; struct { @@ -109,46 +113,62 @@ struct connection { } scache; pa_time_event *auth_timeout_event; -}; +} connection; + +PA_DECLARE_CLASS(connection); +#define CONNECTION(o) (connection_cast(o)) +static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject); struct pa_protocol_esound { - int public; pa_module *module; pa_core *core; + int public; pa_socket_server *server; pa_idxset *connections; + char *sink_name, *source_name; unsigned n_player; uint8_t esd_key[ESD_KEY_LEN]; pa_ip_acl *auth_ip_acl; }; +enum { + SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */ + SINK_INPUT_MESSAGE_DISABLE_PREBUF +}; + +enum { + CONNECTION_MESSAGE_REQUEST_DATA, + CONNECTION_MESSAGE_POST_DATA, + CONNECTION_MESSAGE_UNLINK_CONNECTION +}; + typedef struct proto_handler { size_t data_length; - int (*proc)(struct connection *c, esd_proto_t request, const void *data, size_t length); + int (*proc)(connection *c, esd_proto_t request, const void *data, size_t length); const char *description; } esd_proto_handler_info_t; -static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length); -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk); +static void sink_input_drop_cb(pa_sink_input *i, size_t length); +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk); static void sink_input_kill_cb(pa_sink_input *i); -static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i); +static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk); static pa_usec_t source_output_get_latency_cb(pa_source_output *o); static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk); static void source_output_kill_cb(pa_source_output *o); -static int esd_proto_connect(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_stream_play(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_get_latency(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_server_info(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_all_info(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_stream_pan(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_sample_get_id(struct connection *c, esd_proto_t request, const void *data, size_t length); -static int esd_proto_standby_or_resume(struct connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_connect(connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_stream_play(connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_stream_record(connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_get_latency(connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_server_info(connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_all_info(connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_sample_cache(connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_sample_get_id(connection *c, esd_proto_t request, const void *data, size_t length); +static int esd_proto_standby_or_resume(connection *c, esd_proto_t request, const void *data, size_t length); /* the big map of protocol handler info */ static struct proto_handler proto_map[ESD_PROTO_MAX] = { @@ -185,25 +205,56 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = { { 0, esd_proto_get_latency, "get latency" } }; -static void connection_free(struct connection *c) { - assert(c); - pa_idxset_remove_by_data(c->protocol->connections, c, NULL); +static void connection_unlink(connection *c) { + pa_assert(c); + + if (!c->protocol) + return; + + if (c->sink_input) { + pa_sink_input_unlink(c->sink_input); + pa_sink_input_unref(c->sink_input); + c->sink_input = NULL; + } + + if (c->source_output) { + pa_source_output_unlink(c->source_output); + pa_source_output_unref(c->source_output); + c->source_output = NULL; + } + + if (c->client) { + pa_client_free(c->client); + c->client = NULL; + } if (c->state == ESD_STREAMING_DATA) c->protocol->n_player--; - pa_client_free(c->client); - - if (c->sink_input) { - pa_sink_input_disconnect(c->sink_input); - pa_sink_input_unref(c->sink_input); + if (c->io) { + pa_iochannel_free(c->io); + c->io = NULL; } - if (c->source_output) { - pa_source_output_disconnect(c->source_output); - pa_source_output_unref(c->source_output); + if (c->defer_event) { + c->protocol->core->mainloop->defer_free(c->defer_event); + c->defer_event = NULL; } + if (c->auth_timeout_event) { + c->protocol->core->mainloop->time_free(c->auth_timeout_event); + c->auth_timeout_event = NULL; + } + + pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c); + c->protocol = NULL; + connection_unref(c); +} + +static void connection_free(pa_object *obj) { + connection *c = CONNECTION(obj); + pa_assert(c); + if (c->input_memblockq) pa_memblockq_free(c->input_memblockq); if (c->output_memblockq) @@ -215,54 +266,44 @@ static void connection_free(struct connection *c) { pa_xfree(c->read_data); pa_xfree(c->write_data); - if (c->io) - pa_iochannel_free(c->io); - - if (c->defer_event) - c->protocol->core->mainloop->defer_free(c->defer_event); - if (c->scache.memchunk.memblock) pa_memblock_unref(c->scache.memchunk.memblock); pa_xfree(c->scache.name); - if (c->auth_timeout_event) - c->protocol->core->mainloop->time_free(c->auth_timeout_event); - pa_xfree(c->original_name); pa_xfree(c); } -static void connection_write_prepare(struct connection *c, size_t length) { +static void connection_write_prepare(connection *c, size_t length) { size_t t; - assert(c); + pa_assert(c); t = c->write_data_length+length; if (c->write_data_alloc < t) c->write_data = pa_xrealloc(c->write_data, c->write_data_alloc = t); - assert(c->write_data); + pa_assert(c->write_data); } -static void connection_write(struct connection *c, const void *data, size_t length) { +static void connection_write(connection *c, const void *data, size_t length) { size_t i; - assert(c); + pa_assert(c); - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 1); connection_write_prepare(c, length); - assert(c->write_data); + pa_assert(c->write_data); i = c->write_data_length; c->write_data_length += length; - memcpy((char*)c->write_data + i, data, length); + memcpy((uint8_t*) c->write_data + i, data, length); } -static void format_esd2native(int format, int swap_bytes, pa_sample_spec *ss) { - assert(ss); +static void format_esd2native(int format, pa_bool_t swap_bytes, pa_sample_spec *ss) { + pa_assert(ss); ss->channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1; if ((format & ESD_MASK_BITS) == ESD_BITS16) @@ -289,11 +330,13 @@ static int format_native2esd(pa_sample_spec *ss) { /*** esound commands ***/ -static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_connect(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { uint32_t ekey; int ok; - assert(length == (ESD_KEY_LEN + sizeof(uint32_t))); + connection_assert_ref(c); + pa_assert(data); + pa_assert(length == (ESD_KEY_LEN + sizeof(uint32_t))); if (!c->authorized) { if (memcmp(data, c->protocol->esd_key, ESD_KEY_LEN) != 0) { @@ -301,7 +344,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req return -1; } - c->authorized = 1; + c->authorized = TRUE; if (c->auth_timeout_event) { c->protocol->core->mainloop->time_free(c->auth_timeout_event); c->auth_timeout_event = NULL; @@ -312,11 +355,11 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req memcpy(&ekey, data, sizeof(uint32_t)); if (ekey == ESD_ENDIAN_KEY) - c->swap_byte_order = 0; + c->swap_byte_order = FALSE; else if (ekey == ESD_SWAP_ENDIAN_KEY) - c->swap_byte_order = 1; + c->swap_byte_order = TRUE; else { - pa_log("client sent invalid endian key"); + pa_log_warn("Client sent invalid endian key"); return -1; } @@ -325,7 +368,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req return 0; } -static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { char name[ESD_NAME_MAX], *utf8_name; int32_t format, rate; pa_sample_spec ss; @@ -333,15 +376,17 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t pa_sink *sink = NULL; pa_sink_input_new_data sdata; - assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX)); + connection_assert_ref(c); + pa_assert(data); + pa_assert(length == (sizeof(int32_t)*2+ESD_NAME_MAX)); memcpy(&format, data, sizeof(int32_t)); - format = MAYBE_INT32_SWAP(c->swap_byte_order, format); - data = (const char*)data + sizeof(int32_t); + format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format); + data = (const char*) data + sizeof(int32_t); memcpy(&rate, data, sizeof(int32_t)); - rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); - data = (const char*)data + sizeof(int32_t); + rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate); + data = (const char*) data + sizeof(int32_t); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -362,7 +407,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t c->original_name = pa_xstrdup(name); - assert(!c->sink_input && !c->input_memblockq); + pa_assert(!c->sink_input && !c->input_memblockq); pa_sink_input_new_data_init(&sdata); sdata.sink = sink; @@ -385,22 +430,26 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t l/PLAYBACK_BUFFER_FRAGMENTS, NULL); pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2); - c->playback.fragment_size = l/10; + c->playback.fragment_size = l/PLAYBACK_BUFFER_FRAGMENTS; + c->sink_input->parent.process_msg = sink_input_process_msg; c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; c->sink_input->kill = sink_input_kill_cb; - c->sink_input->get_latency = sink_input_get_latency_cb; c->sink_input->userdata = c; c->state = ESD_STREAMING_DATA; c->protocol->n_player++; + pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq)); + + pa_sink_input_put(c->sink_input); + return 0; } -static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length) { +static int esd_proto_stream_record(connection *c, esd_proto_t request, const void *data, size_t length) { char name[ESD_NAME_MAX], *utf8_name; int32_t format, rate; pa_source *source = NULL; @@ -408,15 +457,17 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co size_t l; pa_source_output_new_data sdata; - assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX)); + connection_assert_ref(c); + pa_assert(data); + pa_assert(length == (sizeof(int32_t)*2+ESD_NAME_MAX)); memcpy(&format, data, sizeof(int32_t)); - format = MAYBE_INT32_SWAP(c->swap_byte_order, format); - data = (const char*)data + sizeof(int32_t); + format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format); + data = (const char*) data + sizeof(int32_t); memcpy(&rate, data, sizeof(int32_t)); - rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); - data = (const char*)data + sizeof(int32_t); + rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate); + data = (const char*) data + sizeof(int32_t); ss.rate = rate; format_esd2native(format, c->swap_byte_order, &ss); @@ -436,7 +487,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co return -1; } } else { - assert(request == ESD_PROTO_STREAM_REC); + pa_assert(request == ESD_PROTO_STREAM_REC); if (c->protocol->source_name) { if (!(source = pa_namereg_get(c->protocol->core, c->protocol->source_name, PA_NAMEREG_SOURCE, 1))) { @@ -455,7 +506,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co c->original_name = pa_xstrdup(name); - assert(!c->output_memblockq && !c->source_output); + pa_assert(!c->output_memblockq && !c->source_output); pa_source_output_new_data_init(&sdata); sdata.source = source; @@ -488,14 +539,18 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co c->protocol->n_player++; + pa_source_output_put(c->source_output); + return 0; } -static int esd_proto_get_latency(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_get_latency(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { pa_sink *sink; int32_t latency; - assert(c && !data && length == 0); + connection_ref(c); + pa_assert(!data); + pa_assert(length == 0); if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) latency = 0; @@ -504,17 +559,19 @@ static int esd_proto_get_latency(struct connection *c, PA_GCC_UNUSED esd_proto_t latency = (int) ((usec*44100)/1000000); } - latency = MAYBE_INT32_SWAP(c->swap_byte_order, latency); + latency = PA_MAYBE_INT32_SWAP(c->swap_byte_order, latency); connection_write(c, &latency, sizeof(int32_t)); return 0; } -static int esd_proto_server_info(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_server_info(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { int32_t rate = 44100, format = ESD_STEREO|ESD_BITS16; int32_t response; pa_sink *sink; - assert(c && data && length == sizeof(int32_t)); + connection_ref(c); + pa_assert(data); + pa_assert(length == sizeof(int32_t)); if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) { rate = sink->sample_spec.rate; @@ -525,22 +582,24 @@ static int esd_proto_server_info(struct connection *c, PA_GCC_UNUSED esd_proto_t response = 0; connection_write(c, &response, sizeof(int32_t)); - rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); + rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate); connection_write(c, &rate, sizeof(int32_t)); - format = MAYBE_INT32_SWAP(c->swap_byte_order, format); + format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format); connection_write(c, &format, sizeof(int32_t)); return 0; } -static int esd_proto_all_info(struct connection *c, esd_proto_t request, const void *data, size_t length) { +static int esd_proto_all_info(connection *c, esd_proto_t request, const void *data, size_t length) { size_t t, k, s; - struct connection *conn; + connection *conn; uint32_t idx = PA_IDXSET_INVALID; unsigned nsamples; char terminator[sizeof(int32_t)*6+ESD_NAME_MAX]; - assert(c && data && length == sizeof(int32_t)); + connection_ref(c); + pa_assert(data); + pa_assert(length == sizeof(int32_t)); if (esd_proto_server_info(c, request, data, length) < 0) return -1; @@ -561,7 +620,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v if (conn->state != ESD_STREAMING_DATA) continue; - assert(t >= k*2+s); + pa_assert(t >= k*2+s); if (conn->sink_input) { pa_cvolume volume = *pa_sink_input_get_volume(conn->sink_input); @@ -572,7 +631,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v } /* id */ - id = MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) (conn->index+1)); + id = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) (conn->index+1)); connection_write(c, &id, sizeof(int32_t)); /* name */ @@ -584,25 +643,25 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v connection_write(c, name, ESD_NAME_MAX); /* rate */ - rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); + rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate); connection_write(c, &rate, sizeof(int32_t)); /* left */ - lvolume = MAYBE_INT32_SWAP(c->swap_byte_order, lvolume); + lvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, lvolume); connection_write(c, &lvolume, sizeof(int32_t)); /*right*/ - rvolume = MAYBE_INT32_SWAP(c->swap_byte_order, rvolume); + rvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rvolume); connection_write(c, &rvolume, sizeof(int32_t)); /*format*/ - format = MAYBE_INT32_SWAP(c->swap_byte_order, format); + format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format); connection_write(c, &format, sizeof(int32_t)); t -= k; } - assert(t == s*(nsamples+1)+k); + pa_assert(t == s*(nsamples+1)+k); t -= k; connection_write(c, terminator, k); @@ -615,10 +674,10 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v int32_t id, rate, lvolume, rvolume, format, len; char name[ESD_NAME_MAX]; - assert(t >= s*2); + pa_assert(t >= s*2); /* id */ - id = MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1)); + id = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1)); connection_write(c, &id, sizeof(int32_t)); /* name */ @@ -626,57 +685,59 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0) strncpy(name, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX); else - snprintf(name, ESD_NAME_MAX, "native.%s", ce->name); + pa_snprintf(name, ESD_NAME_MAX, "native.%s", ce->name); connection_write(c, name, ESD_NAME_MAX); /* rate */ - rate = MAYBE_UINT32_SWAP(c->swap_byte_order, ce->sample_spec.rate); + rate = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, ce->sample_spec.rate); connection_write(c, &rate, sizeof(int32_t)); /* left */ - lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + lvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); connection_write(c, &lvolume, sizeof(int32_t)); /*right*/ - rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); + rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); connection_write(c, &rvolume, sizeof(int32_t)); /*format*/ - format = MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ce->sample_spec)); + format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ce->sample_spec)); connection_write(c, &format, sizeof(int32_t)); /*length*/ - len = MAYBE_INT32_SWAP(c->swap_byte_order, (int) ce->memchunk.length); + len = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int) ce->memchunk.length); connection_write(c, &len, sizeof(int32_t)); t -= s; } } - assert(t == s); + pa_assert(t == s); connection_write(c, terminator, s); return 0; } -static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_stream_pan(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { int32_t ok; uint32_t idx, lvolume, rvolume; - struct connection *conn; + connection *conn; - assert(c && data && length == sizeof(int32_t)*3); + connection_assert_ref(c); + pa_assert(data); + pa_assert(length == sizeof(int32_t)*3); memcpy(&idx, data, sizeof(uint32_t)); - idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1; + idx = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1; data = (const char*)data + sizeof(uint32_t); memcpy(&lvolume, data, sizeof(uint32_t)); - lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, lvolume); + lvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, lvolume); data = (const char*)data + sizeof(uint32_t); memcpy(&rvolume, data, sizeof(uint32_t)); - rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume); + rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume); data = (const char*)data + sizeof(uint32_t); if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx)) && conn->sink_input) { @@ -694,20 +755,22 @@ static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t return 0; } -static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_sample_cache(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { pa_sample_spec ss; int32_t format, rate, sc_length; uint32_t idx; char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1]; - assert(c && data && length == (ESD_NAME_MAX+3*sizeof(int32_t))); + connection_assert_ref(c); + pa_assert(data); + pa_assert(length == (ESD_NAME_MAX+3*sizeof(int32_t))); memcpy(&format, data, sizeof(int32_t)); - format = MAYBE_INT32_SWAP(c->swap_byte_order, format); + format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format); data = (const char*)data + sizeof(int32_t); memcpy(&rate, data, sizeof(int32_t)); - rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate); + rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate); data = (const char*)data + sizeof(int32_t); ss.rate = rate; @@ -716,7 +779,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification."); memcpy(&sc_length, data, sizeof(int32_t)); - sc_length = MAYBE_INT32_SWAP(c->swap_byte_order, sc_length); + sc_length = PA_MAYBE_INT32_SWAP(c->swap_byte_order, sc_length); data = (const char*)data + sizeof(int32_t); CHECK_VALIDITY(sc_length <= MAX_CACHE_SAMPLE_SIZE, "Sample too large (%d bytes).", (int)sc_length); @@ -727,12 +790,12 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name."); - assert(!c->scache.memchunk.memblock); + pa_assert(!c->scache.memchunk.memblock); c->scache.memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, sc_length); c->scache.memchunk.index = 0; c->scache.memchunk.length = sc_length; c->scache.sample_spec = ss; - assert(!c->scache.name); + pa_assert(!c->scache.name); c->scache.name = pa_xstrdup(name); c->state = ESD_CACHING_SAMPLE; @@ -745,12 +808,14 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_ return 0; } -static int esd_proto_sample_get_id(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { +static int esd_proto_sample_get_id(connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) { int32_t ok; uint32_t idx; char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1]; - assert(c && data && length == ESD_NAME_MAX); + connection_assert_ref(c); + pa_assert(data); + pa_assert(length == ESD_NAME_MAX); strcpy(name, SCACHE_PREFIX); strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX); @@ -767,15 +832,17 @@ static int esd_proto_sample_get_id(struct connection *c, PA_GCC_UNUSED esd_proto return 0; } -static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t request, const void *data, size_t length) { +static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, const void *data, size_t length) { int32_t ok; const char *name; uint32_t idx; - assert(c && data && length == sizeof(int32_t)); + connection_assert_ref(c); + pa_assert(data); + pa_assert(length == sizeof(int32_t)); memcpy(&idx, data, sizeof(uint32_t)); - idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1; + idx = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1; ok = 0; @@ -787,7 +854,7 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0) ok = idx + 1; } else { - assert(request == ESD_PROTO_SAMPLE_FREE); + pa_assert(request == ESD_PROTO_SAMPLE_FREE); if (pa_scache_remove_item(c->protocol->core, name) >= 0) ok = idx + 1; @@ -799,9 +866,11 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque return 0; } -static int esd_proto_standby_or_resume(struct connection *c, PA_GCC_UNUSED esd_proto_t request, PA_GCC_UNUSED const void *data, PA_GCC_UNUSED size_t length) { +static int esd_proto_standby_or_resume(connection *c, PA_GCC_UNUSED esd_proto_t request, PA_GCC_UNUSED const void *data, PA_GCC_UNUSED size_t length) { int32_t ok; + connection_assert_ref(c); + connection_write_prepare(c, sizeof(int32_t) * 2); ok = 1; @@ -814,20 +883,21 @@ static int esd_proto_standby_or_resume(struct connection *c, PA_GCC_UNUSED esd_p /*** client callbacks ***/ static void client_kill_cb(pa_client *c) { - assert(c && c->userdata); - connection_free(c->userdata); + pa_assert(c); + + connection_unlink(CONNECTION(c->userdata)); } /*** pa_iochannel callbacks ***/ -static int do_read(struct connection *c) { - assert(c && c->io); +static int do_read(connection *c) { + connection_assert_ref(c); -/* pa_log("READ"); */ +/* pa_log("READ"); */ if (c->state == ESD_NEXT_REQUEST) { ssize_t r; - assert(c->read_data_length < sizeof(c->request)); + pa_assert(c->read_data_length < sizeof(c->request)); if ((r = pa_iochannel_read(c->io, ((uint8_t*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) { pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); @@ -837,7 +907,7 @@ static int do_read(struct connection *c) { if ((c->read_data_length+= r) >= sizeof(c->request)) { struct proto_handler *handler; - c->request = MAYBE_INT32_SWAP(c->swap_byte_order, c->request); + c->request = PA_MAYBE_INT32_SWAP(c->swap_byte_order, c->request); if (c->request < ESD_PROTO_CONNECT || c->request > ESD_PROTO_MAX) { pa_log("recieved invalid request."); @@ -862,7 +932,7 @@ static int do_read(struct connection *c) { } else { if (c->read_data_alloc < handler->data_length) c->read_data = pa_xrealloc(c->read_data, c->read_data_alloc = handler->data_length); - assert(c->read_data); + pa_assert(c->read_data); c->state = ESD_NEEDS_REQDATA; c->read_data_length = 0; @@ -873,18 +943,21 @@ static int do_read(struct connection *c) { ssize_t r; struct proto_handler *handler = proto_map+c->request; - assert(handler->proc); + pa_assert(handler->proc); - assert(c->read_data && c->read_data_length < handler->data_length); + pa_assert(c->read_data && c->read_data_length < handler->data_length); if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) { + if (r < 0 && (errno == EINTR || errno == EAGAIN)) + return 0; + pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } if ((c->read_data_length += r) >= handler->data_length) { size_t l = c->read_data_length; - assert(handler->proc); + pa_assert(handler->proc); c->state = ESD_NEXT_REQUEST; c->read_data_length = 0; @@ -894,16 +967,26 @@ static int do_read(struct connection *c) { } } else if (c->state == ESD_CACHING_SAMPLE) { ssize_t r; + void *p; - assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length); + pa_assert(c->scache.memchunk.memblock); + pa_assert(c->scache.name); + pa_assert(c->scache.memchunk.index < c->scache.memchunk.length); + + p = pa_memblock_acquire(c->scache.memchunk.memblock); + r = pa_iochannel_read(c->io, (uint8_t*) p+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index); + pa_memblock_release(c->scache.memchunk.memblock); + + if (r <= 0) { + if (r < 0 && (errno == EINTR || errno == EAGAIN)) + return 0; - if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) { pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } c->scache.memchunk.index += r; - assert(c->scache.memchunk.index <= c->scache.memchunk.length); + pa_assert(c->scache.memchunk.index <= c->scache.memchunk.length); if (c->scache.memchunk.index == c->scache.memchunk.length) { uint32_t idx; @@ -928,31 +1011,39 @@ static int do_read(struct connection *c) { pa_memchunk chunk; ssize_t r; size_t l; + void *p; - assert(c->input_memblockq); + pa_assert(c->input_memblockq); /* pa_log("STREAMING_DATA"); */ - if (!(l = pa_memblockq_missing(c->input_memblockq))) + if (!(l = pa_atomic_load(&c->playback.missing))) return 0; if (l > c->playback.fragment_size) l = c->playback.fragment_size; if (c->playback.current_memblock) - if (c->playback.current_memblock->length - c->playback.memblock_index < l) { + if (pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index < l) { pa_memblock_unref(c->playback.current_memblock); c->playback.current_memblock = NULL; c->playback.memblock_index = 0; } if (!c->playback.current_memblock) { - c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2); - assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); + pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2)); c->playback.memblock_index = 0; } - if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { + p = pa_memblock_acquire(c->playback.current_memblock); + r = pa_iochannel_read(c->io, (uint8_t*) p+c->playback.memblock_index, l); + pa_memblock_release(c->playback.current_memblock); + + if (r <= 0) { + + if (r < 0 && (errno == EINTR || errno == EAGAIN)) + return 0; + pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF"); return -1; } @@ -960,29 +1051,30 @@ static int do_read(struct connection *c) { chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; chunk.length = r; - assert(chunk.memblock); c->playback.memblock_index += r; - assert(c->input_memblockq); - pa_memblockq_push_align(c->input_memblockq, &chunk); - assert(c->sink_input); - pa_sink_notify(c->sink_input->sink); + pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, &chunk, NULL); + pa_atomic_sub(&c->playback.missing, r); } return 0; } -static int do_write(struct connection *c) { - assert(c && c->io); +static int do_write(connection *c) { + connection_assert_ref(c); /* pa_log("WRITE"); */ if (c->write_data_length) { ssize_t r; - assert(c->write_data_index < c->write_data_length); + pa_assert(c->write_data_index < c->write_data_length); if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) { + + if (r < 0 && (errno == EINTR || errno == EAGAIN)) + return 0; + pa_log("write(): %s", pa_cstrerror(errno)); return -1; } @@ -993,32 +1085,38 @@ static int do_write(struct connection *c) { } else if (c->state == ESD_STREAMING_DATA && c->source_output) { pa_memchunk chunk; ssize_t r; + void *p; - assert(c->output_memblockq); if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) return 0; - assert(chunk.memblock && chunk.length); + pa_assert(chunk.memblock); + pa_assert(chunk.length); + + p = pa_memblock_acquire(chunk.memblock); + r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length); + pa_memblock_release(chunk.memblock); + + pa_memblock_unref(chunk.memblock); + + if (r < 0) { + + if (r < 0 && (errno == EINTR || errno == EAGAIN)) + return 0; - if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { - pa_memblock_unref(chunk.memblock); pa_log("write(): %s", pa_cstrerror(errno)); return -1; } - pa_memblockq_drop(c->output_memblockq, &chunk, r); - pa_memblock_unref(chunk.memblock); - - pa_source_notify(c->source_output->source); + pa_memblockq_drop(c->output_memblockq, r); } return 0; } -static void do_work(struct connection *c) { - assert(c); +static void do_work(connection *c) { + connection_assert_ref(c); - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); c->protocol->core->mainloop->defer_enable(c->defer_event, 0); if (c->dead) @@ -1044,122 +1142,196 @@ static void do_work(struct connection *c) { fail: if (c->state == ESD_STREAMING_DATA && c->sink_input) { - c->dead = 1; + c->dead = TRUE; pa_iochannel_free(c->io); c->io = NULL; - pa_memblockq_prebuf_disable(c->input_memblockq); - pa_sink_notify(c->sink_input->sink); + pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, 0, NULL, NULL); } else - connection_free(c); + connection_unlink(c); } static void io_callback(pa_iochannel*io, void *userdata) { - struct connection *c = userdata; - assert(io && c && c->io == io); + connection *c = CONNECTION(userdata); + + connection_assert_ref(c); + pa_assert(io); do_work(c); } -/*** defer callback ***/ - static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { - struct connection *c = userdata; - assert(a && c && c->defer_event == e); + connection *c = CONNECTION(userdata); -/* pa_log("DEFER"); */ + connection_assert_ref(c); + pa_assert(e); do_work(c); } -/*** sink_input callbacks ***/ +static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) { + connection *c = CONNECTION(o); + connection_assert_ref(c); -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { - struct connection*c; - assert(i && i->userdata && chunk); - c = i->userdata; + switch (code) { + case CONNECTION_MESSAGE_REQUEST_DATA: + do_work(c); + break; - if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) { + case CONNECTION_MESSAGE_POST_DATA: +/* pa_log("got data %u", chunk->length); */ + pa_memblockq_push_align(c->output_memblockq, chunk); + do_work(c); + break; - if (c->dead) - connection_free(c); - - return -1; + case CONNECTION_MESSAGE_UNLINK_CONNECTION: + connection_unlink(c); + break; } return 0; } -static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { - struct connection*c = i->userdata; - assert(i && c && length); +/*** sink_input callbacks ***/ -/* pa_log("DROP"); */ +/* Called from thread context */ +static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { + pa_sink_input *i = PA_SINK_INPUT(o); + connection*c; - pa_memblockq_drop(c->input_memblockq, chunk, length); + pa_sink_input_assert_ref(i); + c = CONNECTION(i->userdata); + connection_assert_ref(c); - /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); + switch (code) { - if (!c->dead) - c->protocol->core->mainloop->defer_enable(c->defer_event, 1); + case SINK_INPUT_MESSAGE_POST_DATA: { + pa_assert(chunk); -/* assert(pa_memblockq_get_length(c->input_memblockq) > 2048); */ + /* New data from the main loop */ + pa_memblockq_push_align(c->input_memblockq, chunk); + +/* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */ + + return 0; + } + + case SINK_INPUT_MESSAGE_DISABLE_PREBUF: { + pa_memblockq_prebuf_disable(c->input_memblockq); + return 0; + } + + case PA_SINK_INPUT_MESSAGE_GET_LATENCY: { + pa_usec_t *r = userdata; + + *r = pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); + + /* Fall through, the default handler will add in the extra + * latency added by the resampler */ + } + + default: + return pa_sink_input_process_msg(o, code, userdata, offset, chunk); + } +} + +/* Called from thread context */ +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { + connection*c; + int r; + + pa_assert(i); + c = CONNECTION(i->userdata); + connection_assert_ref(c); + pa_assert(chunk); + + if ((r = pa_memblockq_peek(c->input_memblockq, chunk)) < 0 && c->dead) + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL); + + return r; +} + +/* Called from thread context */ +static void sink_input_drop_cb(pa_sink_input *i, size_t length) { + connection*c; + size_t old, new; + + pa_assert(i); + c = CONNECTION(i->userdata); + connection_assert_ref(c); + pa_assert(length); + + /* pa_log("DROP"); */ + + old = pa_memblockq_missing(c->input_memblockq); + pa_memblockq_drop(c->input_memblockq, length); + new = pa_memblockq_missing(c->input_memblockq); + + if (new > old) { + if (pa_atomic_add(&c->playback.missing, new - old) <= 0) + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL); + } } static void sink_input_kill_cb(pa_sink_input *i) { - assert(i && i->userdata); - connection_free((struct connection *) i->userdata); -} + pa_sink_input_assert_ref(i); -static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { - struct connection*c = i->userdata; - assert(i && c); - return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); + connection_unlink(CONNECTION(i->userdata)); } /*** source_output callbacks ***/ +/* Called from thread context */ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) { - struct connection *c = o->userdata; - assert(o && c && chunk); + connection *c; - pa_memblockq_push(c->output_memblockq, chunk); + pa_assert(o); + c = CONNECTION(o->userdata); + pa_assert(c); + pa_assert(chunk); - /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); - - if (!c->dead) - c->protocol->core->mainloop->defer_enable(c->defer_event, 1); + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_POST_DATA, NULL, 0, chunk, NULL); } static void source_output_kill_cb(pa_source_output *o) { - assert(o && o->userdata); - connection_free((struct connection *) o->userdata); + pa_source_output_assert_ref(o); + + connection_unlink(CONNECTION(o->userdata)); } static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { - struct connection*c = o->userdata; - assert(o && c); + connection*c; + + pa_assert(o); + c = CONNECTION(o->userdata); + pa_assert(c); + return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec); } /*** socket server callback ***/ static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { - struct connection *c = userdata; - assert(m && tv && c && c->auth_timeout_event == e); + connection *c = CONNECTION(userdata); + + pa_assert(m); + pa_assert(tv); + connection_assert_ref(c); + pa_assert(c->auth_timeout_event == e); if (!c->authorized) - connection_free(c); + connection_unlink(c); } static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) { - struct connection *c; + connection *c; pa_protocol_esound *p = userdata; char cname[256], pname[128]; - assert(s && io && p); + + pa_assert(s); + pa_assert(io); + pa_assert(p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); @@ -1167,23 +1339,23 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) return; } - c = pa_xnew(struct connection, 1); + c = pa_msgobject_new(connection); + c->parent.parent.free = connection_free; + c->parent.process_msg = connection_process_msg; c->protocol = p; c->io = io; pa_iochannel_set_callback(c->io, io_callback, c); pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname)); - snprintf(cname, sizeof(cname), "EsounD client (%s)", pname); - assert(p->core); + pa_snprintf(cname, sizeof(cname), "EsounD client (%s)", pname); c->client = pa_client_new(p->core, __FILE__, cname); - assert(c->client); c->client->owner = p->module; c->client->kill = client_kill_cb; c->client->userdata = c; c->authorized = !!p->public; - c->swap_byte_order = 0; - c->dead = 0; + c->swap_byte_order = FALSE; + c->dead = FALSE; c->read_data_length = 0; c->read_data = pa_xmalloc(c->read_data_alloc = proto_map[ESD_PROTO_CONNECT].data_length); @@ -1203,6 +1375,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->playback.current_memblock = NULL; c->playback.memblock_index = 0; c->playback.fragment_size = 0; + pa_atomic_store(&c->playback.missing, 0); c->scache.memchunk.length = c->scache.memchunk.index = 0; c->scache.memchunk.memblock = NULL; @@ -1212,7 +1385,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) if (!c->authorized && p->auth_ip_acl && pa_ip_acl_check(p->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) { pa_log_info("Client authenticated by IP ACL."); - c->authorized = 1; + c->authorized = TRUE; } if (!c->authorized) { @@ -1224,7 +1397,6 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) c->auth_timeout_event = NULL; c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c); - assert(c->defer_event); p->core->mainloop->defer_enable(c->defer_event, 0); pa_idxset_put(p->connections, c, &c->index); @@ -1233,22 +1405,22 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) /*** entry points ***/ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *server, pa_module *m, pa_modargs *ma) { - pa_protocol_esound *p; + pa_protocol_esound *p = NULL; int public = 0; const char *acl; - assert(core); - assert(server); - assert(m); - assert(ma); - - p = pa_xnew(pa_protocol_esound, 1); + pa_assert(core); + pa_assert(server); + pa_assert(m); + pa_assert(ma); if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) { pa_log("auth-anonymous= expects a boolean argument."); goto fail; } + p = pa_xnew(pa_protocol_esound, 1); + if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", DEFAULT_COOKIE_FILE), p->esd_key, sizeof(p->esd_key)) < 0) goto fail; @@ -1261,13 +1433,12 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve } else p->auth_ip_acl = NULL; + p->core = core; p->module = m; p->public = public; p->server = server; pa_socket_server_set_callback(p->server, on_connection, p); - p->core = core; p->connections = pa_idxset_new(NULL, NULL); - assert(p->connections); p->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); p->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL)); @@ -1281,17 +1452,20 @@ fail: } void pa_protocol_esound_free(pa_protocol_esound *p) { - struct connection *c; - assert(p); + connection *c; + pa_assert(p); while ((c = pa_idxset_first(p->connections, NULL))) - connection_free(c); - + connection_unlink(c); pa_idxset_free(p->connections, NULL, NULL); + pa_socket_server_unref(p->server); if (p->auth_ip_acl) pa_ip_acl_free(p->auth_ip_acl); + pa_xfree(p->sink_name); + pa_xfree(p->source_name); + pa_xfree(p); } diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c index 3541721aa..d91ae142e 100644 --- a/src/pulsecore/protocol-http.c +++ b/src/pulsecore/protocol-http.c @@ -25,7 +25,6 @@ #include #endif -#include #include #include #include @@ -34,6 +33,7 @@ #include #include +#include #include #include #include @@ -65,11 +65,12 @@ struct pa_protocol_http { static void http_response(struct connection *c, int code, const char *msg, const char *mime) { char s[256]; - assert(c); - assert(msg); - assert(mime); - snprintf(s, sizeof(s), + pa_assert(c); + pa_assert(msg); + pa_assert(mime); + + pa_snprintf(s, sizeof(s), "HTTP/1.0 %i %s\n" "Connection: close\n" "Content-Type: %s\n" @@ -83,14 +84,14 @@ static void http_response(struct connection *c, int code, const char *msg, const static void http_message(struct connection *c, int code, const char *msg, const char *text) { char s[256]; - assert(c); + pa_assert(c); http_response(c, code, msg, "text/html"); if (!text) text = msg; - snprintf(s, sizeof(s), + pa_snprintf(s, sizeof(s), "\n" "\n" "%s\n" @@ -103,21 +104,22 @@ static void http_message(struct connection *c, int code, const char *msg, const static void connection_free(struct connection *c, int del) { - assert(c); + pa_assert(c); if (c->url) pa_xfree(c->url); if (del) pa_idxset_remove_by_data(c->protocol->connections, c, NULL); + pa_ioline_unref(c->line); pa_xfree(c); } static void line_callback(pa_ioline *line, const char *s, void *userdata) { struct connection *c = userdata; - assert(line); - assert(c); + pa_assert(line); + pa_assert(c); if (!s) { /* EOF */ @@ -223,7 +225,10 @@ fail: static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) { pa_protocol_http *p = userdata; struct connection *c; - assert(s && io && p); + + pa_assert(s); + pa_assert(io); + pa_assert(p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); @@ -231,7 +236,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) return; } - c = pa_xmalloc(sizeof(struct connection)); + c = pa_xnew(struct connection, 1); c->protocol = p; c->line = pa_ioline_new(io); c->state = REQUEST_LINE; @@ -243,9 +248,11 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) pa_protocol_http* pa_protocol_http_new(pa_core *core, pa_socket_server *server, pa_module *m, PA_GCC_UNUSED pa_modargs *ma) { pa_protocol_http* p; - assert(core && server); - p = pa_xmalloc(sizeof(pa_protocol_http)); + pa_core_assert_ref(core); + pa_assert(server); + + p = pa_xnew(pa_protocol_http, 1); p->module = m; p->core = core; p->server = server; @@ -257,12 +264,12 @@ pa_protocol_http* pa_protocol_http_new(pa_core *core, pa_socket_server *server, } static void free_connection(void *p, PA_GCC_UNUSED void *userdata) { - assert(p); + pa_assert(p); connection_free(p, 0); } void pa_protocol_http_free(pa_protocol_http *p) { - assert(p); + pa_assert(p); pa_idxset_free(p->connections, free_connection, NULL); pa_socket_server_unref(p->server); diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index dd41b3d56..9ae0f0837 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -61,6 +60,7 @@ #include #include #include +#include #include "protocol-native.h" @@ -72,54 +72,61 @@ #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */ -struct connection; +typedef struct connection connection; struct pa_protocol_native; -struct record_stream { - struct connection *connection; +typedef struct record_stream { + pa_msgobject parent; + + connection *connection; uint32_t index; + pa_source_output *source_output; pa_memblockq *memblockq; size_t fragment_size; -}; +} record_stream; -struct playback_stream { - int type; - struct connection *connection; +typedef struct output_stream { + pa_msgobject parent; +} output_stream; + +typedef struct playback_stream { + output_stream parent; + + connection *connection; uint32_t index; + pa_sink_input *sink_input; pa_memblockq *memblockq; - size_t requested_bytes; int drain_request; uint32_t drain_tag; uint32_t syncid; int underrun; - /* Sync group members */ - PA_LLIST_FIELDS(struct playback_stream); -}; + pa_atomic_t missing; + size_t minreq; -struct upload_stream { - int type; - struct connection *connection; + /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */ + int64_t read_index, write_index; + size_t resampled_chunk_length; +} playback_stream; + +typedef struct upload_stream { + output_stream parent; + + connection *connection; uint32_t index; + pa_memchunk memchunk; size_t length; char *name; pa_sample_spec sample_spec; pa_channel_map channel_map; -}; - -struct output_stream { - int type; -}; - -enum { - UPLOAD_STREAM, - PLAYBACK_STREAM -}; +} upload_stream; struct connection { + pa_msgobject parent; + int authorized; uint32_t version; pa_protocol_native *protocol; @@ -132,10 +139,30 @@ struct connection { pa_time_event *auth_timeout_event; }; +PA_DECLARE_CLASS(record_stream); +#define RECORD_STREAM(o) (record_stream_cast(o)) +static PA_DEFINE_CHECK_TYPE(record_stream, pa_msgobject); + +PA_DECLARE_CLASS(output_stream); +#define OUTPUT_STREAM(o) (output_stream_cast(o)) +static PA_DEFINE_CHECK_TYPE(output_stream, pa_msgobject); + +PA_DECLARE_CLASS(playback_stream); +#define PLAYBACK_STREAM(o) (playback_stream_cast(o)) +static PA_DEFINE_CHECK_TYPE(playback_stream, output_stream); + +PA_DECLARE_CLASS(upload_stream); +#define UPLOAD_STREAM(o) (upload_stream_cast(o)) +static PA_DEFINE_CHECK_TYPE(upload_stream, output_stream); + +PA_DECLARE_CLASS(connection); +#define CONNECTION(o) (connection_cast(o)) +static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject); + struct pa_protocol_native { pa_module *module; - int public; pa_core *core; + int public; pa_socket_server *server; pa_idxset *connections; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; @@ -146,17 +173,45 @@ struct pa_protocol_native { pa_ip_acl *auth_ip_acl; }; -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk); -static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length); -static void sink_input_kill_cb(pa_sink_input *i); -static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i); +enum { + SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */ + SINK_INPUT_MESSAGE_DRAIN, /* disabled prebuf, get playback started. */ + SINK_INPUT_MESSAGE_FLUSH, + SINK_INPUT_MESSAGE_TRIGGER, + SINK_INPUT_MESSAGE_SEEK, + SINK_INPUT_MESSAGE_PREBUF_FORCE, + SINK_INPUT_MESSAGE_UPDATE_LATENCY +}; +enum { + PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, /* data requested from sink input from the main loop */ + PLAYBACK_STREAM_MESSAGE_UNDERFLOW, + PLAYBACK_STREAM_MESSAGE_OVERFLOW, + PLAYBACK_STREAM_MESSAGE_DRAIN_ACK +}; + +enum { + RECORD_STREAM_MESSAGE_POST_DATA /* data from source output to main loop */ +}; + +enum { + CONNECTION_MESSAGE_RELEASE, + CONNECTION_MESSAGE_REVOKE +}; + +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk); +static void sink_input_drop_cb(pa_sink_input *i, size_t length); +static void sink_input_kill_cb(pa_sink_input *i); + +static void send_memblock(connection *c); static void request_bytes(struct playback_stream*s); static void source_output_kill_cb(pa_source_output *o); static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk); static pa_usec_t source_output_get_latency_cb(pa_source_output *o); +static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk); + static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); @@ -179,8 +234,7 @@ static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_set_mute(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -static void command_flush_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -static void command_trigger_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); @@ -193,6 +247,7 @@ static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, u static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = NULL, @@ -239,12 +294,16 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume, [PA_COMMAND_SET_SINK_MUTE] = command_set_mute, + [PA_COMMAND_SET_SINK_INPUT_MUTE] = command_set_mute, [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute, + [PA_COMMAND_SUSPEND_SINK] = command_suspend, + [PA_COMMAND_SUSPEND_SOURCE] = command_suspend, + [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream, - [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_playback_stream, - [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream, - [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream, + [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream, + [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream, + [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream, [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream, [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream, @@ -269,74 +328,146 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { /* structure management */ -static struct upload_stream* upload_stream_new( - struct connection *c, - const pa_sample_spec *ss, - const pa_channel_map *map, - const char *name, size_t length) { +static void upload_stream_unlink(upload_stream *s) { + pa_assert(s); - struct upload_stream *s; - assert(c && ss && name && length); + if (!s->connection) + return; - s = pa_xnew(struct upload_stream, 1); - s->type = UPLOAD_STREAM; + pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s); + s->connection = NULL; + upload_stream_unref(s); +} + +static void upload_stream_free(pa_object *o) { + upload_stream *s = UPLOAD_STREAM(o); + pa_assert(s); + + upload_stream_unlink(s); + + pa_xfree(s->name); + + if (s->memchunk.memblock) + pa_memblock_unref(s->memchunk.memblock); + + pa_xfree(s); +} + +static upload_stream* upload_stream_new( + connection *c, + const pa_sample_spec *ss, + const pa_channel_map *map, + const char *name, size_t length) { + + upload_stream *s; + + pa_assert(c); + pa_assert(ss); + pa_assert(name); + pa_assert(length > 0); + + s = pa_msgobject_new(upload_stream); + s->parent.parent.parent.free = upload_stream_free; s->connection = c; s->sample_spec = *ss; s->channel_map = *map; s->name = pa_xstrdup(name); - - s->memchunk.memblock = NULL; - s->memchunk.index = 0; - s->memchunk.length = 0; - + pa_memchunk_reset(&s->memchunk); s->length = length; pa_idxset_put(c->output_streams, s, &s->index); + return s; } -static void upload_stream_free(struct upload_stream *o) { - assert(o && o->connection); +static void record_stream_unlink(record_stream *s) { + pa_assert(s); - pa_idxset_remove_by_data(o->connection->output_streams, o, NULL); + if (!s->connection) + return; - pa_xfree(o->name); + if (s->source_output) { + pa_source_output_unlink(s->source_output); + pa_source_output_unref(s->source_output); + s->source_output = NULL; + } - if (o->memchunk.memblock) - pa_memblock_unref(o->memchunk.memblock); - - pa_xfree(o); + pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s); + s->connection = NULL; + record_stream_unref(s); } -static struct record_stream* record_stream_new( - struct connection *c, - pa_source *source, - const pa_sample_spec *ss, - const pa_channel_map *map, - const char *name, - size_t maxlength, - size_t fragment_size) { +static void record_stream_free(pa_object *o) { + record_stream *s = RECORD_STREAM(o); + pa_assert(s); - struct record_stream *s; + record_stream_unlink(s); + + pa_memblockq_free(s->memblockq); + pa_xfree(s); +} + +static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) { + record_stream *s = RECORD_STREAM(o); + record_stream_assert_ref(s); + + if (!s->connection) + return -1; + + switch (code) { + + case RECORD_STREAM_MESSAGE_POST_DATA: + + if (pa_memblockq_push_align(s->memblockq, chunk) < 0) { +/* pa_log_warn("Failed to push data into output queue."); */ + return -1; + } + + if (!pa_pstream_is_pending(s->connection->pstream)) + send_memblock(s->connection); + + break; + } + + return 0; +} + +static record_stream* record_stream_new( + connection *c, + pa_source *source, + const pa_sample_spec *ss, + const pa_channel_map *map, + const char *name, + uint32_t *maxlength, + uint32_t fragment_size, + int corked) { + + record_stream *s; pa_source_output *source_output; size_t base; pa_source_output_new_data data; - assert(c && ss && name && maxlength); + pa_assert(c); + pa_assert(ss); + pa_assert(name); + pa_assert(maxlength); + pa_assert(*maxlength > 0); pa_source_output_new_data_init(&data); + data.module = c->protocol->module; + data.client = c->client; data.source = source; data.driver = __FILE__; data.name = name; pa_source_output_new_data_set_sample_spec(&data, ss); pa_source_output_new_data_set_channel_map(&data, map); - data.module = c->protocol->module; - data.client = c->client; - if (!(source_output = pa_source_output_new(c->protocol->core, &data, 0))) + if (!(source_output = pa_source_output_new(c->protocol->core, &data, corked ? PA_SOURCE_OUTPUT_START_CORKED : 0))) return NULL; - s = pa_xnew(struct record_stream, 1); + s = pa_msgobject_new(record_stream); + s->parent.parent.free = record_stream_free; + s->parent.process_msg = record_stream_process_msg; s->connection = c; s->source_output = source_output; s->source_output->push = source_output_push_cb; @@ -346,58 +477,159 @@ static struct record_stream* record_stream_new( s->memblockq = pa_memblockq_new( 0, - maxlength, + *maxlength, 0, base = pa_frame_size(ss), 1, 0, NULL); - assert(s->memblockq); s->fragment_size = (fragment_size/base)*base; - if (!s->fragment_size) + if (s->fragment_size <= 0) s->fragment_size = base; + *maxlength = pa_memblockq_get_maxlength(s->memblockq); pa_idxset_put(c->record_streams, s, &s->index); + + pa_source_output_put(s->source_output); return s; } -static void record_stream_free(struct record_stream* r) { - assert(r && r->connection); +static void playback_stream_unlink(playback_stream *s) { + pa_assert(s); - pa_idxset_remove_by_data(r->connection->record_streams, r, NULL); - pa_source_output_disconnect(r->source_output); - pa_source_output_unref(r->source_output); - pa_memblockq_free(r->memblockq); - pa_xfree(r); + if (!s->connection) + return; + + if (s->sink_input) { + pa_sink_input_unlink(s->sink_input); + pa_sink_input_unref(s->sink_input); + s->sink_input = NULL; + } + + if (s->drain_request) + pa_pstream_send_error(s->connection->pstream, s->drain_tag, PA_ERR_NOENTITY); + + pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s); + s->connection = NULL; + playback_stream_unref(s); } -static struct playback_stream* playback_stream_new( - struct connection *c, +static void playback_stream_free(pa_object* o) { + playback_stream *s = PLAYBACK_STREAM(o); + pa_assert(s); + + playback_stream_unlink(s); + + pa_memblockq_free(s->memblockq); + pa_xfree(s); +} + +static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) { + playback_stream *s = PLAYBACK_STREAM(o); + playback_stream_assert_ref(s); + + if (!s->connection) + return -1; + + switch (code) { + case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: { + pa_tagstruct *t; + uint32_t l = 0; + + for (;;) { + int32_t k; + + if ((k = pa_atomic_load(&s->missing)) <= 0) + break; + + l += k; + + if (l < s->minreq) + break; + + if (pa_atomic_sub(&s->missing, k) <= k) + break; + } + + if (l < s->minreq) + break; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_REQUEST); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, s->index); + pa_tagstruct_putu32(t, l); + pa_pstream_send_tagstruct(s->connection->pstream, t); + +/* pa_log("Requesting %u bytes", l); */ + break; + } + + case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: { + pa_tagstruct *t; + + /* Report that we're empty */ + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, s->index); + pa_pstream_send_tagstruct(s->connection->pstream, t); + break; + } + + case PLAYBACK_STREAM_MESSAGE_OVERFLOW: { + pa_tagstruct *t; + + /* Notify the user we're overflowed*/ + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, s->index); + pa_pstream_send_tagstruct(s->connection->pstream, t); + break; + } + + case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK: + pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata)); + break; + + } + + return 0; +} + +static playback_stream* playback_stream_new( + connection *c, pa_sink *sink, const pa_sample_spec *ss, const pa_channel_map *map, const char *name, - size_t maxlength, - size_t tlength, - size_t prebuf, - size_t minreq, + uint32_t *maxlength, + uint32_t *tlength, + uint32_t *prebuf, + uint32_t *minreq, pa_cvolume *volume, - uint32_t syncid) { + uint32_t syncid, + int corked, + uint32_t *missing) { - struct playback_stream *s, *ssync; + playback_stream *s, *ssync; pa_sink_input *sink_input; pa_memblock *silence; uint32_t idx; int64_t start_index; pa_sink_input_new_data data; - assert(c && ss && name && maxlength); + pa_assert(c); + pa_assert(ss); + pa_assert(name); + pa_assert(maxlength); /* Find syncid group */ for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) { - if (ssync->type != PLAYBACK_STREAM) + if (!playback_stream_isinstance(ssync)) continue; if (ssync->syncid == syncid) @@ -405,8 +637,13 @@ static struct playback_stream* playback_stream_new( } /* Synced streams must connect to the same sink */ - if (ssync) - sink = ssync->sink_input->sink; + if (ssync) { + + if (!sink) + sink = ssync->sink_input->sink; + else if (sink != ssync->sink_input->sink) + return NULL; + } pa_sink_input_new_data_init(&data); data.sink = sink; @@ -417,146 +654,158 @@ static struct playback_stream* playback_stream_new( pa_sink_input_new_data_set_volume(&data, volume); data.module = c->protocol->module; data.client = c->client; + data.sync_base = ssync ? ssync->sink_input : NULL; - if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, 0))) + if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, corked ? PA_SINK_INPUT_START_CORKED : 0))) return NULL; - s = pa_xnew(struct playback_stream, 1); - s->type = PLAYBACK_STREAM; + s = pa_msgobject_new(playback_stream); + s->parent.parent.parent.free = playback_stream_free; + s->parent.parent.process_msg = playback_stream_process_msg; s->connection = c; s->syncid = syncid; s->sink_input = sink_input; s->underrun = 1; + s->sink_input->parent.process_msg = sink_input_process_msg; s->sink_input->peek = sink_input_peek_cb; s->sink_input->drop = sink_input_drop_cb; s->sink_input->kill = sink_input_kill_cb; - s->sink_input->get_latency = sink_input_get_latency_cb; s->sink_input->userdata = s; - if (ssync) { - /* Sync id found, now find head of list */ - PA_LLIST_FIND_HEAD(struct playback_stream, ssync, &ssync); - - /* Prepend ourselves */ - PA_LLIST_PREPEND(struct playback_stream, ssync, s); - - /* Set our start index to the current read index of the other grozp member(s) */ - assert(ssync->next); - start_index = pa_memblockq_get_read_index(ssync->next->memblockq); - } else { - /* This ia a new sync group */ - PA_LLIST_INIT(struct playback_stream, s); - start_index = 0; - } + start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0; silence = pa_silence_memblock_new(c->protocol->core->mempool, ss, 0); s->memblockq = pa_memblockq_new( start_index, - maxlength, - tlength, + *maxlength, + *tlength, pa_frame_size(ss), - prebuf, - minreq, + *prebuf, + *minreq, silence); pa_memblock_unref(silence); - s->requested_bytes = 0; + *maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq); + *tlength = (uint32_t) pa_memblockq_get_tlength(s->memblockq); + *prebuf = (uint32_t) pa_memblockq_get_prebuf(s->memblockq); + *minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq); + *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq); + + s->minreq = pa_memblockq_get_minreq(s->memblockq); + pa_atomic_store(&s->missing, 0); s->drain_request = 0; pa_idxset_put(c->output_streams, s, &s->index); + pa_sink_input_put(s->sink_input); + return s; } -static void playback_stream_free(struct playback_stream* p) { - struct playback_stream *head; - assert(p && p->connection); +static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) { + connection *c = CONNECTION(o); + connection_assert_ref(c); - if (p->drain_request) - pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERR_NOENTITY); + if (!c->protocol) + return -1; - PA_LLIST_FIND_HEAD(struct playback_stream, p, &head); - PA_LLIST_REMOVE(struct playback_stream, head, p); + switch (code) { - pa_idxset_remove_by_data(p->connection->output_streams, p, NULL); - pa_sink_input_disconnect(p->sink_input); - pa_sink_input_unref(p->sink_input); - pa_memblockq_free(p->memblockq); - pa_xfree(p); + case CONNECTION_MESSAGE_REVOKE: + pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata)); + break; + + case CONNECTION_MESSAGE_RELEASE: + pa_pstream_send_release(c->pstream, PA_PTR_TO_UINT(userdata)); + break; + } + + return 0; } -static void connection_free(struct connection *c) { - struct record_stream *r; - struct output_stream *o; - assert(c && c->protocol); +static void connection_unlink(connection *c) { + record_stream *r; + output_stream *o; + + pa_assert(c); + + if (!c->protocol) + return; - pa_idxset_remove_by_data(c->protocol->connections, c, NULL); while ((r = pa_idxset_first(c->record_streams, NULL))) - record_stream_free(r); - pa_idxset_free(c->record_streams, NULL, NULL); + record_stream_unlink(r); while ((o = pa_idxset_first(c->output_streams, NULL))) - if (o->type == PLAYBACK_STREAM) - playback_stream_free((struct playback_stream*) o); + if (playback_stream_isinstance(o)) + playback_stream_unlink(PLAYBACK_STREAM(o)); else - upload_stream_free((struct upload_stream*) o); - pa_idxset_free(c->output_streams, NULL, NULL); - - pa_pdispatch_unref(c->pdispatch); - pa_pstream_close(c->pstream); - pa_pstream_unref(c->pstream); - pa_client_free(c->client); + upload_stream_unlink(UPLOAD_STREAM(o)); if (c->subscription) pa_subscription_free(c->subscription); - if (c->auth_timeout_event) + if (c->pstream) + pa_pstream_unlink(c->pstream); + + if (c->auth_timeout_event) { c->protocol->core->mainloop->time_free(c->auth_timeout_event); + c->auth_timeout_event = NULL; + } + + pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c); + c->protocol = NULL; + connection_unref(c); +} + +static void connection_free(pa_object *o) { + connection *c = CONNECTION(o); + + pa_assert(c); + + connection_unlink(c); + + pa_idxset_free(c->record_streams, NULL, NULL); + pa_idxset_free(c->output_streams, NULL, NULL); + + pa_pdispatch_unref(c->pdispatch); + pa_pstream_unref(c->pstream); + pa_client_free(c->client); pa_xfree(c); } -static void request_bytes(struct playback_stream *s) { - pa_tagstruct *t; - size_t l; - assert(s); +/* Called from thread context */ +static void request_bytes(playback_stream *s) { + size_t m, previous_missing; - if (!(l = pa_memblockq_missing(s->memblockq))) + playback_stream_assert_ref(s); + + m = pa_memblockq_pop_missing(s->memblockq); + + if (m <= 0) return; - if (l <= s->requested_bytes) - return; +/* pa_log("request_bytes(%u)", m); */ - l -= s->requested_bytes; - - if (l < pa_memblockq_get_minreq(s->memblockq)) - return; - - s->requested_bytes += l; - - t = pa_tagstruct_new(NULL, 0); - assert(t); - pa_tagstruct_putu32(t, PA_COMMAND_REQUEST); - pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ - pa_tagstruct_putu32(t, s->index); - pa_tagstruct_putu32(t, l); - pa_pstream_send_tagstruct(s->connection->pstream, t); - -/* pa_log("Requesting %u bytes", l); */ + previous_missing = pa_atomic_add(&s->missing, m); + if (previous_missing < s->minreq && previous_missing+m >= s->minreq) { + pa_assert(pa_thread_mq_get()); + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL); + } } -static void send_memblock(struct connection *c) { +static void send_memblock(connection *c) { uint32_t start; - struct record_stream *r; + record_stream *r; start = PA_IDXSET_INVALID; for (;;) { pa_memchunk chunk; - if (!(r = pa_idxset_rrobin(c->record_streams, &c->rrobin_index))) + if (!(r = RECORD_STREAM(pa_idxset_rrobin(c->record_streams, &c->rrobin_index)))) return; if (start == PA_IDXSET_INVALID) @@ -571,7 +820,8 @@ static void send_memblock(struct connection *c) { schunk.length = r->fragment_size; pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk); - pa_memblockq_drop(r->memblockq, &chunk, schunk.length); + + pa_memblockq_drop(r->memblockq, schunk.length); pa_memblock_unref(schunk.memblock); return; @@ -579,9 +829,9 @@ static void send_memblock(struct connection *c) { } } -static void send_playback_stream_killed(struct playback_stream *p) { +static void send_playback_stream_killed(playback_stream *p) { pa_tagstruct *t; - assert(p); + playback_stream_assert_ref(p); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED); @@ -590,9 +840,9 @@ static void send_playback_stream_killed(struct playback_stream *p) { pa_pstream_send_tagstruct(p->connection->pstream, t); } -static void send_record_stream_killed(struct record_stream *r) { +static void send_record_stream_killed(record_stream *r) { pa_tagstruct *t; - assert(r); + record_stream_assert_ref(r); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED); @@ -601,96 +851,219 @@ static void send_record_stream_killed(struct record_stream *r) { pa_pstream_send_tagstruct(r->connection->pstream, t); } -/*** sinkinput callbacks ***/ +/*** sink input callbacks ***/ -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { - struct playback_stream *s; - assert(i && i->userdata && chunk); - s = i->userdata; +/* Called from thread context */ +static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { + pa_sink_input *i = PA_SINK_INPUT(o); + playback_stream *s; + + pa_sink_input_assert_ref(i); + s = PLAYBACK_STREAM(i->userdata); + playback_stream_assert_ref(s); + + switch (code) { + + case SINK_INPUT_MESSAGE_SEEK: + pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata)); + request_bytes(s); + return 0; + + case SINK_INPUT_MESSAGE_POST_DATA: { + pa_assert(chunk); + +/* pa_log("sink input post: %u", chunk->length); */ + + if (pa_memblockq_push_align(s->memblockq, chunk) < 0) { + + pa_log_warn("Failed to push data into queue"); + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL); + pa_memblockq_seek(s->memblockq, chunk->length, PA_SEEK_RELATIVE); + } + + request_bytes(s); + + s->underrun = 0; + return 0; + } + + case SINK_INPUT_MESSAGE_DRAIN: { + + pa_memblockq_prebuf_disable(s->memblockq); + + if (!pa_memblockq_is_readable(s->memblockq)) + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL); + else { + s->drain_tag = PA_PTR_TO_UINT(userdata); + s->drain_request = 1; + } + request_bytes(s); + + return 0; + } + + case SINK_INPUT_MESSAGE_FLUSH: + case SINK_INPUT_MESSAGE_PREBUF_FORCE: + case SINK_INPUT_MESSAGE_TRIGGER: { + + pa_sink_input *isync; + void (*func)(pa_memblockq *bq); + + switch (code) { + case SINK_INPUT_MESSAGE_FLUSH: + func = pa_memblockq_flush; + break; + + case SINK_INPUT_MESSAGE_PREBUF_FORCE: + func = pa_memblockq_prebuf_force; + break; + + case SINK_INPUT_MESSAGE_TRIGGER: + func = pa_memblockq_prebuf_disable; + break; + + default: + pa_assert_not_reached(); + } + + func(s->memblockq); + s->underrun = 0; + request_bytes(s); + + /* Do the same for all other members in the sync group */ + for (isync = i->sync_prev; isync; isync = isync->sync_prev) { + playback_stream *ssync = PLAYBACK_STREAM(isync->userdata); + func(ssync->memblockq); + ssync->underrun = 0; + request_bytes(ssync); + } + + for (isync = i->sync_next; isync; isync = isync->sync_next) { + playback_stream *ssync = PLAYBACK_STREAM(isync->userdata); + func(ssync->memblockq); + ssync->underrun = 0; + request_bytes(ssync); + } + + return 0; + } + + case SINK_INPUT_MESSAGE_UPDATE_LATENCY: + + s->read_index = pa_memblockq_get_read_index(s->memblockq); + s->write_index = pa_memblockq_get_write_index(s->memblockq); + s->resampled_chunk_length = s->sink_input->thread_info.resampled_chunk.memblock ? s->sink_input->thread_info.resampled_chunk.length : 0; + return 0; + + case PA_SINK_INPUT_MESSAGE_SET_STATE: + + pa_memblockq_prebuf_force(s->memblockq); + request_bytes(s); + break; + + case PA_SINK_INPUT_MESSAGE_GET_LATENCY: { + pa_usec_t *r = userdata; + + *r = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec); + + /* Fall through, the default handler will add in the extra + * latency added by the resampler */ + break; + } + } + + return pa_sink_input_process_msg(o, code, userdata, offset, chunk); +} + +/* Called from thread context */ +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { + playback_stream *s; + + pa_sink_input_assert_ref(i); + s = PLAYBACK_STREAM(i->userdata); + playback_stream_assert_ref(s); + pa_assert(chunk); if (pa_memblockq_get_length(s->memblockq) <= 0 && !s->underrun) { - pa_tagstruct *t; - - /* Report that we're empty */ - - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW); - pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ - pa_tagstruct_putu32(t, s->index); - pa_pstream_send_tagstruct(s->connection->pstream, t); - + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL); s->underrun = 1; } if (pa_memblockq_peek(s->memblockq, chunk) < 0) { -/* pa_log("peek: failure"); */ +/* pa_log("peek: failure"); */ return -1; } -/* pa_log("peek: %u", chunk->length); */ +/* pa_log("peek: %u", chunk->length); */ + + request_bytes(s); return 0; } -static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { - struct playback_stream *s; - assert(i && i->userdata && length); - s = i->userdata; +/* Called from thread context */ +static void sink_input_drop_cb(pa_sink_input *i, size_t length) { + playback_stream *s; - pa_memblockq_drop(s->memblockq, chunk, length); + pa_sink_input_assert_ref(i); + s = PLAYBACK_STREAM(i->userdata); + playback_stream_assert_ref(s); + pa_assert(length > 0); + + pa_memblockq_drop(s->memblockq, length); + + if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) { + s->drain_request = 0; + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, PA_UINT_TO_PTR(s->drain_tag), 0, NULL, NULL); + } request_bytes(s); - if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) { - pa_pstream_send_simple_ack(s->connection->pstream, s->drain_tag); - s->drain_request = 0; - } - -/* pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */ +/* pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */ } static void sink_input_kill_cb(pa_sink_input *i) { - assert(i && i->userdata); - send_playback_stream_killed((struct playback_stream *) i->userdata); - playback_stream_free((struct playback_stream *) i->userdata); -} + playback_stream *s; -static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { - struct playback_stream *s; - assert(i && i->userdata); - s = i->userdata; + pa_sink_input_assert_ref(i); + s = PLAYBACK_STREAM(i->userdata); + playback_stream_assert_ref(s); - /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/ - - return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec); + send_playback_stream_killed(s); + playback_stream_unlink(s); } /*** source_output callbacks ***/ +/* Called from thread context */ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) { - struct record_stream *s; - assert(o && o->userdata && chunk); - s = o->userdata; + record_stream *s; - if (pa_memblockq_push_align(s->memblockq, chunk) < 0) { - pa_log_warn("Failed to push data into output queue."); - return; - } + pa_source_output_assert_ref(o); + s = RECORD_STREAM(o->userdata); + record_stream_assert_ref(s); + pa_assert(chunk); - if (!pa_pstream_is_pending(s->connection->pstream)) - send_memblock(s->connection); + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL); } static void source_output_kill_cb(pa_source_output *o) { - assert(o && o->userdata); - send_record_stream_killed((struct record_stream *) o->userdata); - record_stream_free((struct record_stream *) o->userdata); + record_stream *s; + + pa_source_output_assert_ref(o); + s = RECORD_STREAM(o->userdata); + record_stream_assert_ref(s); + + send_record_stream_killed(s); + record_stream_unlink(s); } static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { - struct record_stream *s; - assert(o && o->userdata); - s = o->userdata; + record_stream *s; + + pa_source_output_assert_ref(o); + s = RECORD_STREAM(o->userdata); + record_stream_assert_ref(s); /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/ @@ -699,9 +1072,9 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { /*** pdispatch callbacks ***/ -static void protocol_error(struct connection *c) { +static void protocol_error(connection *c) { pa_log("protocol error, kicking client"); - connection_free(c); + connection_unlink(c); } #define CHECK_VALIDITY(pstream, expression, tag, error) do { \ @@ -721,9 +1094,9 @@ static pa_tagstruct *reply_new(uint32_t tag) { } static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; - struct playback_stream *s; - uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid; + connection *c = CONNECTION(userdata); + playback_stream *s; + uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid, missing; const char *name, *sink_name; pa_sample_spec ss; pa_channel_map map; @@ -732,7 +1105,8 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC pa_cvolume volume; int corked; - assert(c && t && c->protocol && c->protocol->core); + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_get( t, @@ -773,34 +1147,35 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); } - s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume, syncid); + s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, syncid, corked, &missing); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); - pa_sink_input_cork(s->sink_input, corked); - reply = reply_new(tag); pa_tagstruct_putu32(reply, s->index); - assert(s->sink_input); + pa_assert(s->sink_input); pa_tagstruct_putu32(reply, s->sink_input->index); - pa_tagstruct_putu32(reply, s->requested_bytes = pa_memblockq_missing(s->memblockq)); + pa_tagstruct_putu32(reply, missing); + +/* pa_log("initial request is %u", missing); */ if (c->version >= 9) { /* Since 0.9 we support sending the buffer metrics back to the client */ - pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq)); - pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_tlength(s->memblockq)); - pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_prebuf(s->memblockq)); - pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_minreq(s->memblockq)); + pa_tagstruct_putu32(reply, (uint32_t) maxlength); + pa_tagstruct_putu32(reply, (uint32_t) tlength); + pa_tagstruct_putu32(reply, (uint32_t) prebuf); + pa_tagstruct_putu32(reply, (uint32_t) minreq); } pa_pstream_send_tagstruct(c->pstream, reply); - request_bytes(s); } static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t channel; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &channel) < 0 || !pa_tagstruct_eof(t)) { @@ -810,39 +1185,52 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - if (command == PA_COMMAND_DELETE_PLAYBACK_STREAM) { - struct playback_stream *s; - if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != PLAYBACK_STREAM)) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); - return; + switch (command) { + + case PA_COMMAND_DELETE_PLAYBACK_STREAM: { + playback_stream *s; + if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !playback_stream_isinstance(s)) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); + return; + } + + playback_stream_unlink(s); + break; } - playback_stream_free(s); - } else if (command == PA_COMMAND_DELETE_RECORD_STREAM) { - struct record_stream *s; - if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); - return; + case PA_COMMAND_DELETE_RECORD_STREAM: { + record_stream *s; + if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); + return; + } + + record_stream_unlink(s); + break; } - record_stream_free(s); - } else { - struct upload_stream *s; - assert(command == PA_COMMAND_DELETE_UPLOAD_STREAM); - if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) { - pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); - return; + case PA_COMMAND_DELETE_UPLOAD_STREAM: { + upload_stream *s; + + if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !upload_stream_isinstance(s)) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST); + return; + } + + upload_stream_unlink(s); + break; } - upload_stream_free(s); + default: + pa_assert_not_reached(); } pa_pstream_send_simple_ack(c->pstream, tag); } static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; - struct record_stream *s; + connection *c = CONNECTION(userdata); + record_stream *s; uint32_t maxlength, fragment_size; uint32_t source_index; const char *name, *source_name; @@ -851,7 +1239,9 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct *reply; pa_source *source = NULL; int corked; - assert(c && t && c->protocol && c->protocol->core); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_get_sample_spec(t, &ss) < 0 || @@ -882,20 +1272,18 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY); } - s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size); + s = record_stream_new(c, source, &ss, &map, name, &maxlength, fragment_size, corked); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); - pa_source_output_cork(s->source_output, corked); - reply = reply_new(tag); pa_tagstruct_putu32(reply, s->index); - assert(s->source_output); + pa_assert(s->source_output); pa_tagstruct_putu32(reply, s->source_output->index); if (c->version >= 9) { /* Since 0.9 we support sending the buffer metrics back to the client */ - pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq)); + pa_tagstruct_putu32(reply, (uint32_t) maxlength); pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size); } @@ -903,8 +1291,10 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; - assert(c && t); + connection *c = CONNECTION(userdata); + + connection_assert_ref(c); + pa_assert(t); if (!pa_tagstruct_eof(t)) { protocol_error(c); @@ -913,16 +1303,17 @@ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop); c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0); pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */ } static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); const void*cookie; pa_tagstruct *reply; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &c->version) < 0 || pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 || @@ -1015,9 +1406,11 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t } static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); const char *name; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_gets(t, &name) < 0 || !pa_tagstruct_eof(t)) { @@ -1032,10 +1425,12 @@ static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE } static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); const char *name; uint32_t idx = PA_IDXSET_INVALID; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_gets(t, &name) < 0 || !pa_tagstruct_eof(t)) { @@ -1052,7 +1447,7 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin idx = sink->index; } else { pa_source *source; - assert(command == PA_COMMAND_LOOKUP_SOURCE); + pa_assert(command == PA_COMMAND_LOOKUP_SOURCE); if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1))) idx = source->index; } @@ -1068,10 +1463,12 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin } static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx; - struct playback_stream *s; - assert(c && t); + playback_stream *s; + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { @@ -1082,29 +1479,18 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); s = pa_idxset_get_by_index(c->output_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); - CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY); - s->drain_request = 0; - - pa_memblockq_prebuf_disable(s->memblockq); - - if (!pa_memblockq_is_readable(s->memblockq)) { -/* pa_log("immediate drain: %u", pa_memblockq_get_length(s->memblockq)); */ - pa_pstream_send_simple_ack(c->pstream, tag); - } else { -/* pa_log("slow drain triggered"); */ - s->drain_request = 1; - s->drain_tag = tag; - - pa_sink_notify(s->sink_input->sink); - } + pa_asyncmsgq_post(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_DRAIN, PA_UINT_TO_PTR(tag), 0, NULL, NULL); } static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); pa_tagstruct *reply; const pa_mempool_stat *stat; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (!pa_tagstruct_eof(t)) { protocol_error(c); @@ -1125,13 +1511,15 @@ static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t } static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); pa_tagstruct *reply; - struct playback_stream *s; + playback_stream *s; struct timeval tv, now; uint32_t idx; pa_usec_t latency; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_timeval(t, &tv) < 0 || @@ -1143,31 +1531,34 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); s = pa_idxset_get_by_index(c->output_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); - CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_UPDATE_LATENCY, s, 0, NULL) == 0, tag, PA_ERR_NOENTITY) reply = reply_new(tag); latency = pa_sink_get_latency(s->sink_input->sink); - if (s->sink_input->resampled_chunk.memblock) - latency += pa_bytes_to_usec(s->sink_input->resampled_chunk.length, &s->sink_input->sample_spec); + latency += pa_bytes_to_usec(s->resampled_chunk_length, &s->sink_input->sample_spec); + pa_tagstruct_put_usec(reply, latency); pa_tagstruct_put_usec(reply, 0); - pa_tagstruct_put_boolean(reply, s->sink_input->state == PA_SINK_INPUT_RUNNING); + pa_tagstruct_put_boolean(reply, pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING); pa_tagstruct_put_timeval(reply, &tv); pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now)); - pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq)); - pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq)); + pa_tagstruct_puts64(reply, s->write_index); + pa_tagstruct_puts64(reply, s->read_index); pa_pstream_send_tagstruct(c->pstream, reply); } static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); pa_tagstruct *reply; - struct record_stream *s; + record_stream *s; struct timeval tv, now; uint32_t idx; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_timeval(t, &tv) < 0 || @@ -1192,14 +1583,16 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN } static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; - struct upload_stream *s; + connection *c = CONNECTION(userdata); + upload_stream *s; uint32_t length; const char *name; pa_sample_spec ss; pa_channel_map map; pa_tagstruct *reply; - assert(c && t && c->protocol && c->protocol->core); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_get_sample_spec(t, &ss) < 0 || @@ -1228,11 +1621,13 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ } static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t channel; - struct upload_stream *s; + upload_stream *s; uint32_t idx; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &channel) < 0 || !pa_tagstruct_eof(t)) { @@ -1244,23 +1639,25 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ s = pa_idxset_get_by_index(c->output_streams, channel); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); - CHECK_VALIDITY(c->pstream, s->type == UPLOAD_STREAM, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY); if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx) < 0) pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL); else pa_pstream_send_simple_ack(c->pstream, tag); - upload_stream_free(s); + upload_stream_unlink(s); } static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t sink_index; pa_volume_t volume; pa_sink *sink; const char *name, *sink_name; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &sink_index) < 0 || pa_tagstruct_gets(t, &sink_name) < 0 || @@ -1291,9 +1688,11 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui } static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); const char *name; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_gets(t, &name) < 0 || !pa_tagstruct_eof(t)) { @@ -1313,7 +1712,9 @@ static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED } static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { - assert(t && sink); + pa_assert(t); + pa_sink_assert_ref(sink); + pa_tagstruct_put( t, PA_TAG_U32, sink->index, @@ -1321,22 +1722,21 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { PA_TAG_STRING, sink->description, PA_TAG_SAMPLE_SPEC, &sink->sample_spec, PA_TAG_CHANNEL_MAP, &sink->channel_map, - PA_TAG_U32, sink->owner ? sink->owner->index : PA_INVALID_INDEX, - PA_TAG_CVOLUME, pa_sink_get_volume(sink, PA_MIXER_HARDWARE), - PA_TAG_BOOLEAN, pa_sink_get_mute(sink, PA_MIXER_HARDWARE), + PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX, + PA_TAG_CVOLUME, pa_sink_get_volume(sink), + PA_TAG_BOOLEAN, pa_sink_get_mute(sink), PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX, PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL, PA_TAG_USEC, pa_sink_get_latency(sink), PA_TAG_STRING, sink->driver, - PA_TAG_U32, - (sink->get_hw_volume ? PA_SINK_HW_VOLUME_CTRL : 0) | - (sink->get_latency ? PA_SINK_LATENCY : 0) | - (sink->is_hardware ? PA_SINK_HARDWARE : 0), + PA_TAG_U32, sink->flags, PA_TAG_INVALID); } static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { - assert(t && source); + pa_assert(t); + pa_source_assert_ref(source); + pa_tagstruct_put( t, PA_TAG_U32, source->index, @@ -1344,22 +1744,21 @@ static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { PA_TAG_STRING, source->description, PA_TAG_SAMPLE_SPEC, &source->sample_spec, PA_TAG_CHANNEL_MAP, &source->channel_map, - PA_TAG_U32, source->owner ? source->owner->index : PA_INVALID_INDEX, - PA_TAG_CVOLUME, pa_source_get_volume(source, PA_MIXER_HARDWARE), - PA_TAG_BOOLEAN, pa_source_get_mute(source, PA_MIXER_HARDWARE), + PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX, + PA_TAG_CVOLUME, pa_source_get_volume(source), + PA_TAG_BOOLEAN, pa_source_get_mute(source), PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX, PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL, PA_TAG_USEC, pa_source_get_latency(source), PA_TAG_STRING, source->driver, - PA_TAG_U32, - (source->get_hw_volume ? PA_SOURCE_HW_VOLUME_CTRL : 0) | - (source->get_latency ? PA_SOURCE_LATENCY : 0) | - (source->is_hardware ? PA_SOURCE_HARDWARE : 0), + PA_TAG_U32, source->flags, PA_TAG_INVALID); } static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) { - assert(t && client); + pa_assert(t); + pa_assert(client); + pa_tagstruct_putu32(t, client->index); pa_tagstruct_puts(t, client->name); pa_tagstruct_putu32(t, client->owner ? client->owner->index : PA_INVALID_INDEX); @@ -1367,7 +1766,9 @@ static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) { } static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) { - assert(t && module); + pa_assert(t); + pa_assert(module); + pa_tagstruct_putu32(t, module->index); pa_tagstruct_puts(t, module->name); pa_tagstruct_puts(t, module->argument); @@ -1375,8 +1776,10 @@ static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) { pa_tagstruct_put_boolean(t, module->auto_unload); } -static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) { - assert(t && s); +static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_input *s) { + pa_assert(t); + pa_sink_input_assert_ref(s); + pa_tagstruct_putu32(t, s->index); pa_tagstruct_puts(t, s->name); pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX); @@ -1389,10 +1792,14 @@ static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) { pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink)); pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s))); pa_tagstruct_puts(t, s->driver); + if (c->version >= 11) + pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s)); } static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) { - assert(t && s); + pa_assert(t); + pa_source_output_assert_ref(s); + pa_tagstruct_putu32(t, s->index); pa_tagstruct_puts(t, s->name); pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX); @@ -1407,7 +1814,9 @@ static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) { } static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) { - assert(t && e); + pa_assert(t); + pa_assert(e); + pa_tagstruct_putu32(t, e->index); pa_tagstruct_puts(t, e->name); pa_tagstruct_put_cvolume(t, &e->volume); @@ -1420,7 +1829,7 @@ static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) { } static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx; pa_sink *sink = NULL; pa_source *source = NULL; @@ -1431,7 +1840,9 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u pa_scache_entry *sce = NULL; const char *name; pa_tagstruct *reply; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || (command != PA_COMMAND_GET_CLIENT_INFO && @@ -1466,7 +1877,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO) so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx); else { - assert(command == PA_COMMAND_GET_SAMPLE_INFO); + pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO); if (idx != PA_INVALID_INDEX) sce = pa_idxset_get_by_index(c->protocol->core->scache, idx); else @@ -1488,7 +1899,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u else if (module) module_fill_tagstruct(reply, module); else if (si) - sink_input_fill_tagstruct(reply, si); + sink_input_fill_tagstruct(c, reply, si); else if (so) source_output_fill_tagstruct(reply, so); else @@ -1497,12 +1908,14 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u } static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); pa_idxset *i; uint32_t idx; void *p; pa_tagstruct *reply; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (!pa_tagstruct_eof(t)) { protocol_error(c); @@ -1526,7 +1939,7 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST) i = c->protocol->core->source_outputs; else { - assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); + pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); i = c->protocol->core->scache; } @@ -1541,11 +1954,11 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma else if (command == PA_COMMAND_GET_MODULE_INFO_LIST) module_fill_tagstruct(reply, p); else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST) - sink_input_fill_tagstruct(reply, p); + sink_input_fill_tagstruct(c, reply, p); else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST) source_output_fill_tagstruct(reply, p); else { - assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); + pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); scache_fill_tagstruct(reply, p); } } @@ -1555,11 +1968,13 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma } static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); pa_tagstruct *reply; char txt[256]; const char *n; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (!pa_tagstruct_eof(t)) { protocol_error(c); @@ -1587,8 +2002,9 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) { pa_tagstruct *t; - struct connection *c = userdata; - assert(c && core); + connection *c = CONNECTION(userdata); + + connection_assert_ref(c); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT); @@ -1599,9 +2015,11 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint3 } static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); pa_subscription_mask_t m; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &m) < 0 || !pa_tagstruct_eof(t)) { @@ -1617,7 +2035,7 @@ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint if (m != 0) { c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c); - assert(c->subscription); + pa_assert(c->subscription); } else c->subscription = NULL; @@ -1631,14 +2049,16 @@ static void command_set_volume( pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx; pa_cvolume volume; pa_sink *sink = NULL; pa_source *source = NULL; pa_sink_input *si = NULL; const char *name = NULL; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) || @@ -1653,27 +2073,36 @@ static void command_set_volume( CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); - if (command == PA_COMMAND_SET_SINK_VOLUME) { - if (idx != PA_INVALID_INDEX) - sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); - else - sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); - } else if (command == PA_COMMAND_SET_SOURCE_VOLUME) { - if (idx != (uint32_t) -1) - source = pa_idxset_get_by_index(c->protocol->core->sources, idx); - else - source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); - } else { - assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME); - si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); + switch (command) { + + case PA_COMMAND_SET_SINK_VOLUME: + if (idx != PA_INVALID_INDEX) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); + else + sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); + break; + + case PA_COMMAND_SET_SOURCE_VOLUME: + if (idx != PA_INVALID_INDEX) + source = pa_idxset_get_by_index(c->protocol->core->sources, idx); + else + source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); + break; + + case PA_COMMAND_SET_SINK_INPUT_VOLUME: + si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); + break; + + default: + pa_assert_not_reached(); } CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY); if (sink) - pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &volume); + pa_sink_set_volume(sink, &volume); else if (source) - pa_source_set_volume(source, PA_MIXER_HARDWARE, &volume); + pa_source_set_volume(source, &volume); else if (si) pa_sink_input_set_volume(si, &volume); @@ -1687,16 +2116,20 @@ static void command_set_mute( pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx; int mute; pa_sink *sink = NULL; pa_source *source = NULL; + pa_sink_input *si = NULL; const char *name = NULL; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || - pa_tagstruct_gets(t, &name) < 0 || + (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) || + (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) || pa_tagstruct_get_boolean(t, &mute) || !pa_tagstruct_eof(t)) { protocol_error(c); @@ -1706,35 +2139,53 @@ static void command_set_mute( CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID); - if (command == PA_COMMAND_SET_SINK_MUTE) { - if (idx != PA_INVALID_INDEX) - sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); - else - sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); - } else { - assert(command == PA_COMMAND_SET_SOURCE_MUTE); - if (idx != (uint32_t) -1) - source = pa_idxset_get_by_index(c->protocol->core->sources, idx); - else - source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); + switch (command) { + + case PA_COMMAND_SET_SINK_MUTE: + + if (idx != PA_INVALID_INDEX) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); + else + sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); + + break; + + case PA_COMMAND_SET_SOURCE_MUTE: + if (idx != PA_INVALID_INDEX) + source = pa_idxset_get_by_index(c->protocol->core->sources, idx); + else + source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); + + break; + + case PA_COMMAND_SET_SINK_INPUT_MUTE: + si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); + break; + + default: + pa_assert_not_reached(); } - CHECK_VALIDITY(c->pstream, sink || source, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY); if (sink) - pa_sink_set_mute(sink, PA_MIXER_HARDWARE, mute); + pa_sink_set_mute(sink, mute); else if (source) - pa_source_set_mute(source, PA_MIXER_HARDWARE, mute); + pa_source_set_mute(source, mute); + else if (si) + pa_sink_input_set_mute(si, mute); pa_pstream_send_simple_ack(c->pstream, tag); } static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx; int b; - struct playback_stream *s, *ssync; - assert(c && t); + playback_stream *s; + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_boolean(t, &b) < 0 || @@ -1747,30 +2198,19 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); s = pa_idxset_get_by_index(c->output_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); - CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY); pa_sink_input_cork(s->sink_input, b); - pa_memblockq_prebuf_force(s->memblockq); - - /* Do the same for all other members in the sync group */ - for (ssync = s->prev; ssync; ssync = ssync->prev) { - pa_sink_input_cork(ssync->sink_input, b); - pa_memblockq_prebuf_force(ssync->memblockq); - } - - for (ssync = s->next; ssync; ssync = ssync->next) { - pa_sink_input_cork(ssync->sink_input, b); - pa_memblockq_prebuf_force(ssync->memblockq); - } - pa_pstream_send_simple_ack(c->pstream, tag); } -static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; +static void command_trigger_or_flush_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + connection *c = CONNECTION(userdata); uint32_t idx; - struct playback_stream *s, *ssync; - assert(c && t); + playback_stream *s; + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { @@ -1782,75 +2222,36 @@ static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); s = pa_idxset_get_by_index(c->output_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); - CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); - - pa_memblockq_flush(s->memblockq); - s->underrun = 0; - - /* Do the same for all other members in the sync group */ - for (ssync = s->prev; ssync; ssync = ssync->prev) { - pa_memblockq_flush(ssync->memblockq); - ssync->underrun = 0; - } - - for (ssync = s->next; ssync; ssync = ssync->next) { - pa_memblockq_flush(ssync->memblockq); - ssync->underrun = 0; - } - - pa_pstream_send_simple_ack(c->pstream, tag); - pa_sink_notify(s->sink_input->sink); - request_bytes(s); - - for (ssync = s->prev; ssync; ssync = ssync->prev) - request_bytes(ssync); - - for (ssync = s->next; ssync; ssync = ssync->next) - request_bytes(ssync); -} - -static void command_trigger_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; - uint32_t idx; - struct playback_stream *s; - assert(c && t); - - if (pa_tagstruct_getu32(t, &idx) < 0 || - !pa_tagstruct_eof(t)) { - protocol_error(c); - return; - } - - CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); - CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID); - s = pa_idxset_get_by_index(c->output_streams, idx); - CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); - CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY); switch (command) { + case PA_COMMAND_FLUSH_PLAYBACK_STREAM: + pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL); + break; + case PA_COMMAND_PREBUF_PLAYBACK_STREAM: - pa_memblockq_prebuf_force(s->memblockq); + pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL); break; case PA_COMMAND_TRIGGER_PLAYBACK_STREAM: - pa_memblockq_prebuf_disable(s->memblockq); + pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL); break; default: - abort(); + pa_assert_not_reached(); } - pa_sink_notify(s->sink_input->sink); pa_pstream_send_simple_ack(c->pstream, tag); - request_bytes(s); } static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx; - struct record_stream *s; + record_stream *s; int b; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_get_boolean(t, &b) < 0 || @@ -1869,10 +2270,12 @@ static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN } static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx; - struct record_stream *s; - assert(c && t); + record_stream *s; + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { @@ -1889,9 +2292,11 @@ static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_U } static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); const char *s; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_gets(t, &s) < 0 || !pa_tagstruct_eof(t)) { @@ -1907,10 +2312,12 @@ static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, u } static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx; const char *name; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_gets(t, &name) < 0 || @@ -1923,16 +2330,16 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID); if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) { - struct playback_stream *s; + playback_stream *s; s = pa_idxset_get_by_index(c->output_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); - CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY); pa_sink_input_set_name(s->sink_input, name); } else { - struct record_stream *s; + record_stream *s; s = pa_idxset_get_by_index(c->record_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); @@ -1944,9 +2351,11 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com } static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { @@ -1961,6 +2370,8 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 client = pa_idxset_get_by_index(c->protocol->core->clients, idx); CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY); + + connection_ref(c); pa_client_kill(client); } else if (command == PA_COMMAND_KILL_SINK_INPUT) { @@ -1969,27 +2380,32 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3 s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + connection_ref(c); pa_sink_input_kill(s); } else { pa_source_output *s; - assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT); + pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT); s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + connection_ref(c); pa_source_output_kill(s); } pa_pstream_send_simple_ack(c->pstream, tag); + connection_unref(c); } static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); pa_module *m; const char *name, *argument; pa_tagstruct *reply; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_gets(t, &argument) < 0 || @@ -2013,10 +2429,12 @@ static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui } static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx; pa_module *m; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || !pa_tagstruct_eof(t)) { @@ -2033,12 +2451,14 @@ static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED } static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); const char *name, *module, *argument; uint32_t type; uint32_t idx; pa_tagstruct *reply; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_getu32(t, &type) < 0 || @@ -2066,11 +2486,13 @@ static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED u } static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); const char *name = NULL; uint32_t type, idx = PA_IDXSET_INVALID; int r; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if ((pa_tagstruct_getu32(t, &idx) < 0 && (pa_tagstruct_gets(t, &name) < 0 || @@ -2095,7 +2517,7 @@ static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE } static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e) { - assert(t && e); + pa_assert(t && e); pa_tagstruct_putu32(t, e->index); pa_tagstruct_puts(t, e->name); @@ -2105,12 +2527,14 @@ static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e) } static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); const pa_autoload_entry *a = NULL; uint32_t type, idx; const char *name; pa_tagstruct *reply; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if ((pa_tagstruct_getu32(t, &idx) < 0 && (pa_tagstruct_gets(t, &name) < 0 || @@ -2137,9 +2561,11 @@ static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNU } static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); pa_tagstruct *reply; - assert(c && t); + + connection_assert_ref(c); + pa_assert(t); if (!pa_tagstruct_eof(t)) { protocol_error(c); @@ -2162,12 +2588,12 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC } static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { - struct connection *c = userdata; + connection *c = CONNECTION(userdata); uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX; const char *name = NULL; - assert(c); - assert(t); + connection_assert_ref(c); + pa_assert(t); if (pa_tagstruct_getu32(t, &idx) < 0 || pa_tagstruct_getu32(t, &idx_device) < 0 || @@ -2202,6 +2628,8 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag pa_source_output *so = NULL; pa_source *source; + pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT); + so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx); if (idx_device != PA_INVALID_INDEX) @@ -2218,67 +2646,122 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag } pa_pstream_send_simple_ack(c->pstream, tag); +} +static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + connection *c = CONNECTION(userdata); + uint32_t idx = PA_INVALID_INDEX; + const char *name = NULL; + int b; + + connection_assert_ref(c); + pa_assert(t); + + if (pa_tagstruct_getu32(t, &idx) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_get_boolean(t, &b) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || !*name || pa_utf8_valid(name), tag, PA_ERR_INVALID); + + if (command == PA_COMMAND_SUSPEND_SINK) { + + if (idx == PA_INVALID_INDEX && name && !*name) { + + if (pa_sink_suspend_all(c->protocol->core, b) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); + return; + } + } else { + pa_sink *sink = NULL; + + if (idx != PA_INVALID_INDEX) + sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx); + else + sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1); + + CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); + + if (pa_sink_suspend(sink, b) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); + return; + } + } + } else { + + pa_assert(command == PA_COMMAND_SUSPEND_SOURCE); + + if (idx == PA_INVALID_INDEX && name && !*name) { + + if (pa_source_suspend_all(c->protocol->core, b) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); + return; + } + + } else { + pa_source *source; + + if (idx != PA_INVALID_INDEX) + source = pa_idxset_get_by_index(c->protocol->core->sources, idx); + else + source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1); + + CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY); + + if (pa_source_suspend(source, b) < 0) { + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); + return; + } + } + } + + pa_pstream_send_simple_ack(c->pstream, tag); } /*** pstream callbacks ***/ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { - struct connection *c = userdata; - assert(p && packet && packet->data && c); + connection *c = CONNECTION(userdata); + + pa_assert(p); + pa_assert(packet); + connection_assert_ref(c); if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) { pa_log("invalid packet."); - connection_free(c); + connection_unlink(c); } } static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { - struct connection *c = userdata; - struct output_stream *stream; - assert(p && chunk && userdata); + connection *c = CONNECTION(userdata); + output_stream *stream; - if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) { + pa_assert(p); + pa_assert(chunk); + connection_assert_ref(c); + + if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) { pa_log("client sent block for invalid stream."); /* Ignoring */ return; } - if (stream->type == PLAYBACK_STREAM) { - struct playback_stream *ps = (struct playback_stream*) stream; - if (chunk->length >= ps->requested_bytes) - ps->requested_bytes = 0; - else - ps->requested_bytes -= chunk->length; + if (playback_stream_isinstance(stream)) { + playback_stream *ps = PLAYBACK_STREAM(stream); - pa_memblockq_seek(ps->memblockq, offset, seek); + if (seek != PA_SEEK_RELATIVE || offset != 0) + pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, NULL, NULL); - if (pa_memblockq_push_align(ps->memblockq, chunk) < 0) { - pa_tagstruct *t; - - pa_log_warn("failed to push data into queue"); - - /* Pushing this block into the queue failed, so we simulate - * it by skipping ahead */ - - pa_memblockq_seek(ps->memblockq, chunk->length, PA_SEEK_RELATIVE); - - /* Notify the user */ - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW); - pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ - pa_tagstruct_putu32(t, ps->index); - pa_pstream_send_tagstruct(p, t); - } - - ps->underrun = 0; - - pa_sink_notify(ps->sink_input->sink); + pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL); } else { - struct upload_stream *u = (struct upload_stream*) stream; + upload_stream *u = UPLOAD_STREAM(stream); size_t l; - assert(u->type == UPLOAD_STREAM); if (!u->memchunk.memblock) { if (u->length == chunk->length) { @@ -2291,15 +2774,24 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o } } - assert(u->memchunk.memblock); + pa_assert(u->memchunk.memblock); l = u->length; if (l > chunk->length) l = chunk->length; + if (l > 0) { - memcpy((uint8_t*) u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length, - (uint8_t*) chunk->memblock->data+chunk->index, l); + void *src, *dst; + dst = pa_memblock_acquire(u->memchunk.memblock); + src = pa_memblock_acquire(chunk->memblock); + + memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length, + (uint8_t*) src+chunk->index, l); + + pa_memblock_release(u->memchunk.memblock); + pa_memblock_release(chunk->memblock); + u->memchunk.length += l; u->length -= l; } @@ -2307,43 +2799,72 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o } static void pstream_die_callback(pa_pstream *p, void *userdata) { - struct connection *c = userdata; - assert(p && c); - connection_free(c); + connection *c = CONNECTION(userdata); -/* pa_log("connection died.");*/ + pa_assert(p); + connection_assert_ref(c); + + connection_unlink(c); + pa_log_info("connection died."); } - static void pstream_drain_callback(pa_pstream *p, void *userdata) { - struct connection *c = userdata; - assert(p && c); + connection *c = CONNECTION(userdata); + + pa_assert(p); + connection_assert_ref(c); send_memblock(c); } +static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) { + pa_thread_mq *q; + + if (!(q = pa_thread_mq_get())) + pa_pstream_send_revoke(p, block_id); + else + pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL); +} + +static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) { + pa_thread_mq *q; + + if (!(q = pa_thread_mq_get())) + pa_pstream_send_release(p, block_id); + else + pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL); +} + /*** client callbacks ***/ static void client_kill_cb(pa_client *c) { - assert(c && c->userdata); - connection_free(c->userdata); + pa_assert(c); + + connection_unlink(CONNECTION(c->userdata)); } /*** socket server callbacks ***/ static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) { - struct connection *c = userdata; - assert(m && tv && c && c->auth_timeout_event == e); + connection *c = CONNECTION(userdata); + + pa_assert(m); + pa_assert(tv); + connection_assert_ref(c); + pa_assert(c->auth_timeout_event == e); if (!c->authorized) - connection_free(c); + connection_unlink(c); } static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, void *userdata) { pa_protocol_native *p = userdata; - struct connection *c; + connection *c; char cname[256], pname[128]; - assert(io && p); + + pa_assert(s); + pa_assert(io); + pa_assert(p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); @@ -2351,7 +2872,9 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo return; } - c = pa_xmalloc(sizeof(struct connection)); + c = pa_msgobject_new(connection); + c->parent.parent.free = connection_free; + c->parent.process_msg = connection_process_msg; c->authorized = !!p->public; @@ -2371,35 +2894,31 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo c->version = 8; c->protocol = p; pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname)); - snprintf(cname, sizeof(cname), "Native client (%s)", pname); - assert(p->core); + pa_snprintf(cname, sizeof(cname), "Native client (%s)", pname); c->client = pa_client_new(p->core, __FILE__, cname); - assert(c->client); c->client->kill = client_kill_cb; c->client->userdata = c; c->client->owner = p->module; c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool); - assert(c->pstream); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c); + pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c); + pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c); c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX); - assert(c->pdispatch); c->record_streams = pa_idxset_new(NULL, NULL); c->output_streams = pa_idxset_new(NULL, NULL); - assert(c->record_streams && c->output_streams); c->rrobin_index = PA_IDXSET_INVALID; c->subscription = NULL; pa_idxset_put(p->connections, c, NULL); - #ifdef HAVE_CREDS if (pa_iochannel_creds_supported(io)) pa_iochannel_creds_enable(io); @@ -2410,7 +2929,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo /*** module entry points ***/ static int load_key(pa_protocol_native*p, const char*fn) { - assert(p); + pa_assert(p); p->auth_cookie_in_property = 0; @@ -2440,8 +2959,8 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo int public = 0; const char *acl; - assert(c); - assert(ma); + pa_assert(c); + pa_assert(ma); if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) { pa_log("auth-anonymous= expects a boolean argument."); @@ -2482,7 +3001,6 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo goto fail; p->connections = pa_idxset_new(NULL, NULL); - assert(p->connections); return p; @@ -2517,11 +3035,11 @@ pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *serv } void pa_protocol_native_free(pa_protocol_native *p) { - struct connection *c; - assert(p); + connection *c; + pa_assert(p); while ((c = pa_idxset_first(p->connections, NULL))) - connection_free(c); + connection_unlink(c); pa_idxset_free(p->connections, NULL, NULL); if (p->server) { @@ -2553,7 +3071,12 @@ void pa_protocol_native_free(pa_protocol_native *p) { pa_xfree(p); } -pa_protocol_native* pa_protocol_native_new_iochannel(pa_core*core, pa_iochannel *io, pa_module *m, pa_modargs *ma) { +pa_protocol_native* pa_protocol_native_new_iochannel( + pa_core*core, + pa_iochannel *io, + pa_module *m, + pa_modargs *ma) { + pa_protocol_native *p; if (!(p = protocol_new_internal(core, m, ma))) diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 31ad6dddf..64e2a81c8 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -25,7 +25,6 @@ #include #endif -#include #include #include #include @@ -41,101 +40,154 @@ #include #include #include +#include +#include #include "protocol-simple.h" /* Don't allow more than this many concurrent connections */ #define MAX_CONNECTIONS 10 -struct connection { +typedef struct connection { + pa_msgobject parent; pa_protocol_simple *protocol; pa_iochannel *io; pa_sink_input *sink_input; pa_source_output *source_output; pa_client *client; pa_memblockq *input_memblockq, *output_memblockq; - pa_defer_event *defer_event; int dead; struct { pa_memblock *current_memblock; size_t memblock_index, fragment_size; + pa_atomic_t missing; } playback; -}; +} connection; + +PA_DECLARE_CLASS(connection); +#define CONNECTION(o) (connection_cast(o)) +static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject); struct pa_protocol_simple { pa_module *module; pa_core *core; pa_socket_server*server; pa_idxset *connections; + enum { RECORD = 1, PLAYBACK = 2, DUPLEX = 3 } mode; + pa_sample_spec sample_spec; char *source_name, *sink_name; }; +enum { + SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */ + SINK_INPUT_MESSAGE_DISABLE_PREBUF /* disabled prebuf, get playback started. */ +}; + +enum { + CONNECTION_MESSAGE_REQUEST_DATA, /* data requested from sink input from the main loop */ + CONNECTION_MESSAGE_POST_DATA, /* data from source output to main loop */ + CONNECTION_MESSAGE_UNLINK_CONNECTION /* Please drop a aconnection now */ +}; + + #define PLAYBACK_BUFFER_SECONDS (.5) #define PLAYBACK_BUFFER_FRAGMENTS (10) #define RECORD_BUFFER_SECONDS (5) #define RECORD_BUFFER_FRAGMENTS (100) -static void connection_free(struct connection *c) { - assert(c); +static void connection_unlink(connection *c) { + pa_assert(c); - pa_idxset_remove_by_data(c->protocol->connections, c, NULL); + if (!c->protocol) + return; + + if (c->sink_input) { + pa_sink_input_unlink(c->sink_input); + pa_sink_input_unref(c->sink_input); + c->sink_input = NULL; + } + + if (c->source_output) { + pa_source_output_unlink(c->source_output); + pa_source_output_unref(c->source_output); + c->source_output = NULL; + } + + if (c->client) { + pa_client_free(c->client); + c->client = NULL; + } + + if (c->io) { + pa_iochannel_free(c->io); + c->io = NULL; + } + + pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c); + c->protocol = NULL; + connection_unref(c); +} + +static void connection_free(pa_object *o) { + connection *c = CONNECTION(o); + pa_assert(c); + + connection_unref(c); if (c->playback.current_memblock) pa_memblock_unref(c->playback.current_memblock); - if (c->sink_input) { - pa_sink_input_disconnect(c->sink_input); - pa_sink_input_unref(c->sink_input); - } - if (c->source_output) { - pa_source_output_disconnect(c->source_output); - pa_source_output_unref(c->source_output); - } - if (c->client) - pa_client_free(c->client); - if (c->io) - pa_iochannel_free(c->io); + if (c->input_memblockq) pa_memblockq_free(c->input_memblockq); if (c->output_memblockq) pa_memblockq_free(c->output_memblockq); - if (c->defer_event) - c->protocol->core->mainloop->defer_free(c->defer_event); + pa_xfree(c); } -static int do_read(struct connection *c) { +static int do_read(connection *c) { pa_memchunk chunk; ssize_t r; size_t l; + void *p; - if (!c->sink_input || !(l = pa_memblockq_missing(c->input_memblockq))) + connection_assert_ref(c); + + if (!c->sink_input || (l = pa_atomic_load(&c->playback.missing)) <= 0) return 0; if (l > c->playback.fragment_size) l = c->playback.fragment_size; if (c->playback.current_memblock) - if (c->playback.current_memblock->length - c->playback.memblock_index < l) { + if (pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index < l) { pa_memblock_unref(c->playback.current_memblock); c->playback.current_memblock = NULL; c->playback.memblock_index = 0; } if (!c->playback.current_memblock) { - c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2); - assert(c->playback.current_memblock && c->playback.current_memblock->length >= l); + pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, l)); c->playback.memblock_index = 0; } - if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) { + p = pa_memblock_acquire(c->playback.current_memblock); + r = pa_iochannel_read(c->io, (uint8_t*) p + c->playback.memblock_index, l); + pa_memblock_release(c->playback.current_memblock); + + if (r <= 0) { + + if (r < 0 && (errno == EINTR || errno == EAGAIN)) + return 0; + pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno)); return -1; } @@ -143,50 +195,55 @@ static int do_read(struct connection *c) { chunk.memblock = c->playback.current_memblock; chunk.index = c->playback.memblock_index; chunk.length = r; - assert(chunk.memblock); c->playback.memblock_index += r; - assert(c->input_memblockq); - pa_memblockq_push_align(c->input_memblockq, &chunk); - assert(c->sink_input); - pa_sink_notify(c->sink_input->sink); + pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, &chunk, NULL); + pa_atomic_sub(&c->playback.missing, r); return 0; } -static int do_write(struct connection *c) { +static int do_write(connection *c) { pa_memchunk chunk; ssize_t r; + void *p; + + connection_assert_ref(c); if (!c->source_output) return 0; - assert(c->output_memblockq); - if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) + if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0) { +/* pa_log("peek failed"); */ return 0; + } - assert(chunk.memblock && chunk.length); + pa_assert(chunk.memblock); + pa_assert(chunk.length); + + p = pa_memblock_acquire(chunk.memblock); + r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length); + pa_memblock_release(chunk.memblock); + + pa_memblock_unref(chunk.memblock); + + if (r < 0) { + + if (errno == EINTR || errno == EAGAIN) + return 0; - if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) { - pa_memblock_unref(chunk.memblock); pa_log("write(): %s", pa_cstrerror(errno)); return -1; } - pa_memblockq_drop(c->output_memblockq, &chunk, r); - pa_memblock_unref(chunk.memblock); - - pa_source_notify(c->source_output->source); + pa_memblockq_drop(c->output_memblockq, r); return 0; } -static void do_work(struct connection *c) { - assert(c); - - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); - c->protocol->core->mainloop->defer_enable(c->defer_event, 0); +static void do_work(connection *c) { + connection_assert_ref(c); if (c->dead) return; @@ -207,103 +264,182 @@ static void do_work(struct connection *c) { fail: if (c->sink_input) { + + /* If there is a sink input, we first drain what we already have read before shutting down the connection */ c->dead = 1; pa_iochannel_free(c->io); c->io = NULL; - pa_memblockq_prebuf_disable(c->input_memblockq); - pa_sink_notify(c->sink_input->sink); + pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, 0, NULL, NULL); } else - connection_free(c); + connection_unlink(c); } -/*** sink_input callbacks ***/ +static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) { + connection *c = CONNECTION(o); + connection_assert_ref(c); -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { - struct connection*c; - assert(i && i->userdata && chunk); - c = i->userdata; + switch (code) { + case CONNECTION_MESSAGE_REQUEST_DATA: + do_work(c); + break; - if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) { + case CONNECTION_MESSAGE_POST_DATA: +/* pa_log("got data %u", chunk->length); */ + pa_memblockq_push_align(c->output_memblockq, chunk); + do_work(c); + break; - if (c->dead) - connection_free(c); - - return -1; + case CONNECTION_MESSAGE_UNLINK_CONNECTION: + connection_unlink(c); + break; } return 0; } -static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { - struct connection*c = i->userdata; - assert(i && c && length); +/*** sink_input callbacks ***/ - pa_memblockq_drop(c->input_memblockq, chunk, length); +/* Called from thread context */ +static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { + pa_sink_input *i = PA_SINK_INPUT(o); + connection*c; - /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); - c->protocol->core->mainloop->defer_enable(c->defer_event, 1); + pa_sink_input_assert_ref(i); + c = CONNECTION(i->userdata); + connection_assert_ref(c); + + switch (code) { + + case SINK_INPUT_MESSAGE_POST_DATA: { + pa_assert(chunk); + + /* New data from the main loop */ + pa_memblockq_push_align(c->input_memblockq, chunk); + +/* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */ + + return 0; + } + + case SINK_INPUT_MESSAGE_DISABLE_PREBUF: { + pa_memblockq_prebuf_disable(c->input_memblockq); + return 0; + } + + case PA_SINK_INPUT_MESSAGE_GET_LATENCY: { + pa_usec_t *r = userdata; + + *r = pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); + + /* Fall through, the default handler will add in the extra + * latency added by the resampler */ + } + + default: + return pa_sink_input_process_msg(o, code, userdata, offset, chunk); + } } +/* Called from thread context */ +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { + connection *c; + int r; + + pa_assert(i); + c = CONNECTION(i->userdata); + connection_assert_ref(c); + pa_assert(chunk); + + r = pa_memblockq_peek(c->input_memblockq, chunk); + +/* pa_log("peeked %u %i", r >= 0 ? chunk->length: 0, r); */ + + if (c->dead && r < 0) + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL); + + return r; +} + +/* Called from thread context */ +static void sink_input_drop_cb(pa_sink_input *i, size_t length) { + connection *c; + size_t old, new; + + pa_assert(i); + c = CONNECTION(i->userdata); + connection_assert_ref(c); + pa_assert(length); + + old = pa_memblockq_missing(c->input_memblockq); + pa_memblockq_drop(c->input_memblockq, length); + new = pa_memblockq_missing(c->input_memblockq); + + if (new > old) { + if (pa_atomic_add(&c->playback.missing, new - old) <= 0) + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL); + } +} + +/* Called from main context */ static void sink_input_kill_cb(pa_sink_input *i) { - assert(i && i->userdata); - connection_free((struct connection *) i->userdata); -} + pa_sink_input_assert_ref(i); - -static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) { - struct connection*c = i->userdata; - assert(i && c); - return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); + connection_unlink(CONNECTION(i->userdata)); } /*** source_output callbacks ***/ +/* Called from thread context */ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) { - struct connection *c = o->userdata; - assert(o && c && chunk); + connection *c; - pa_memblockq_push(c->output_memblockq, chunk); + pa_assert(o); + c = CONNECTION(o->userdata); + pa_assert(c); + pa_assert(chunk); - /* do something */ - assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable); - c->protocol->core->mainloop->defer_enable(c->defer_event, 1); + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_POST_DATA, NULL, 0, chunk, NULL); } +/* Called from main context */ static void source_output_kill_cb(pa_source_output *o) { - assert(o && o->userdata); - connection_free((struct connection *) o->userdata); + pa_source_output_assert_ref(o); + + connection_unlink(CONNECTION(o->userdata)); } +/* Called from main context */ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { - struct connection*c = o->userdata; - assert(o && c); + connection*c; + + pa_assert(o); + c = CONNECTION(o->userdata); + pa_assert(c); + return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec); } /*** client callbacks ***/ -static void client_kill_cb(pa_client *c) { - assert(c && c->userdata); - connection_free((struct connection *) c->userdata); +static void client_kill_cb(pa_client *client) { + connection*c; + + pa_assert(client); + c = CONNECTION(client->userdata); + pa_assert(c); + + connection_unlink(c); } /*** pa_iochannel callbacks ***/ static void io_callback(pa_iochannel*io, void *userdata) { - struct connection *c = userdata; - assert(io && c && c->io == io); + connection *c = CONNECTION(userdata); - do_work(c); -} - -/*** fixed callback ***/ - -static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) { - struct connection *c = userdata; - assert(a && c && c->defer_event == e); + connection_assert_ref(c); + pa_assert(io); do_work(c); } @@ -312,9 +448,12 @@ static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) { pa_protocol_simple *p = userdata; - struct connection *c = NULL; + connection *c = NULL; char cname[256]; - assert(s && io && p); + + pa_assert(s); + pa_assert(io); + pa_assert(p); if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) { pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS); @@ -322,21 +461,22 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) return; } - c = pa_xmalloc(sizeof(struct connection)); + c = pa_msgobject_new(connection); + c->parent.parent.free = connection_free; + c->parent.process_msg = connection_process_msg; c->io = io; c->sink_input = NULL; c->source_output = NULL; - c->defer_event = NULL; c->input_memblockq = c->output_memblockq = NULL; c->protocol = p; c->playback.current_memblock = NULL; c->playback.memblock_index = 0; c->playback.fragment_size = 0; c->dead = 0; + pa_atomic_store(&c->playback.missing, 0); pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); - c->client = pa_client_new(p->core, __FILE__, cname); - assert(c->client); + pa_assert_se(c->client = pa_client_new(p->core, __FILE__, cname)); c->client->owner = p->module; c->client->kill = client_kill_cb; c->client->userdata = c; @@ -357,10 +497,10 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) goto fail; } + c->sink_input->parent.process_msg = sink_input_process_msg; c->sink_input->peek = sink_input_peek_cb; c->sink_input->drop = sink_input_drop_cb; c->sink_input->kill = sink_input_kill_cb; - c->sink_input->get_latency = sink_input_get_latency_cb; c->sink_input->userdata = c; l = (size_t) (pa_bytes_per_second(&p->sample_spec)*PLAYBACK_BUFFER_SECONDS); @@ -372,11 +512,12 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) (size_t) -1, l/PLAYBACK_BUFFER_FRAGMENTS, NULL); - assert(c->input_memblockq); pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5); - c->playback.fragment_size = l/10; + c->playback.fragment_size = l/PLAYBACK_BUFFER_FRAGMENTS; - pa_sink_notify(c->sink_input->sink); + pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq)); + + pa_sink_input_put(c->sink_input); } if (p->mode & RECORD) { @@ -409,29 +550,29 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) 0, NULL); pa_iochannel_socket_set_sndbuf(io, l/RECORD_BUFFER_FRAGMENTS*2); - pa_source_notify(c->source_output->source); + + pa_source_output_put(c->source_output); } pa_iochannel_set_callback(c->io, io_callback, c); pa_idxset_put(p->connections, c, NULL); - c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c); - assert(c->defer_event); - p->core->mainloop->defer_enable(c->defer_event, 0); - return; fail: if (c) - connection_free(c); + connection_unlink(c); } pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) { pa_protocol_simple* p = NULL; int enable; - assert(core && server && ma); - p = pa_xmalloc0(sizeof(pa_protocol_simple)); + pa_assert(core); + pa_assert(server); + pa_assert(ma); + + p = pa_xnew0(pa_protocol_simple, 1); p->module = m; p->core = core; p->server = server; @@ -472,23 +613,24 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv fail: if (p) pa_protocol_simple_free(p); + return NULL; } void pa_protocol_simple_free(pa_protocol_simple *p) { - struct connection *c; - assert(p); + connection *c; + pa_assert(p); if (p->connections) { while((c = pa_idxset_first(p->connections, NULL))) - connection_free(c); + connection_unlink(c); pa_idxset_free(p->connections, NULL, NULL); } if (p->server) pa_socket_server_unref(p->server); + pa_xfree(p); } - diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c index fae1e49be..a69321583 100644 --- a/src/pulsecore/pstream-util.c +++ b/src/pulsecore/pstream-util.c @@ -25,9 +25,8 @@ #include #endif -#include - #include +#include #include "pstream-util.h" @@ -35,20 +34,20 @@ void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const size_t length; uint8_t *data; pa_packet *packet; - assert(p); - assert(t); - data = pa_tagstruct_free_data(t, &length); - assert(data && length); - packet = pa_packet_new_dynamic(data, length); - assert(packet); + pa_assert(p); + pa_assert(t); + + pa_assert_se(data = pa_tagstruct_free_data(t, &length)); + pa_assert_se(packet = pa_packet_new_dynamic(data, length)); pa_pstream_send_packet(p, packet, creds); pa_packet_unref(packet); } void pa_pstream_send_error(pa_pstream *p, uint32_t tag, uint32_t error) { - pa_tagstruct *t = pa_tagstruct_new(NULL, 0); - assert(t); + pa_tagstruct *t; + + pa_assert_se(t = pa_tagstruct_new(NULL, 0)); pa_tagstruct_putu32(t, PA_COMMAND_ERROR); pa_tagstruct_putu32(t, tag); pa_tagstruct_putu32(t, error); @@ -56,8 +55,9 @@ void pa_pstream_send_error(pa_pstream *p, uint32_t tag, uint32_t error) { } void pa_pstream_send_simple_ack(pa_pstream *p, uint32_t tag) { - pa_tagstruct *t = pa_tagstruct_new(NULL, 0); - assert(t); + pa_tagstruct *t; + + pa_assert_se(t = pa_tagstruct_new(NULL, 0)); pa_tagstruct_putu32(t, PA_COMMAND_REPLY); pa_tagstruct_putu32(t, tag); pa_pstream_send_tagstruct(p, t); diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c index fdb1a66a3..9d32a3637 100644 --- a/src/pulsecore/pstream.c +++ b/src/pulsecore/pstream.c @@ -28,7 +28,6 @@ #include #include -#include #include #ifdef HAVE_SYS_SOCKET_H @@ -41,16 +40,17 @@ #include #endif -#include "winsock.h" #include +#include #include #include #include #include -#include #include +#include +#include #include "pstream.h" @@ -84,7 +84,8 @@ typedef uint32_t pa_pstream_descriptor[PA_PSTREAM_DESCRIPTOR_MAX]; #define PA_PSTREAM_DESCRIPTOR_SIZE (PA_PSTREAM_DESCRIPTOR_MAX*sizeof(uint32_t)) #define FRAME_SIZE_MAX_ALLOW PA_SCACHE_ENTRY_SIZE_MAX /* allow uploading a single sample in one frame at max */ -#define FRAME_SIZE_MAX_USE (1024*64) + +PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree); struct item_info { enum { @@ -94,7 +95,6 @@ struct item_info { PA_PSTREAM_ITEM_SHMREVOKE } type; - /* packet info */ pa_packet *packet; #ifdef HAVE_CREDS @@ -118,8 +118,8 @@ struct pa_pstream { pa_mainloop_api *mainloop; pa_defer_event *defer_event; pa_iochannel *io; + pa_queue *send_queue; - pa_mutex *mutex; int dead; @@ -129,6 +129,7 @@ struct pa_pstream { uint32_t shm_info[PA_PSTREAM_SHM_MAX]; void *data; size_t index; + pa_memchunk memchunk; } write; struct { @@ -156,6 +157,12 @@ struct pa_pstream { pa_pstream_notify_cb_t die_callback; void *die_callback_userdata; + pa_pstream_block_id_cb_t revoke_callback; + void *revoke_callback_userdata; + + pa_pstream_block_id_cb_t release_callback; + void *release_callback_userdata; + pa_mempool *mempool; #ifdef HAVE_CREDS @@ -168,13 +175,11 @@ static int do_write(pa_pstream *p); static int do_read(pa_pstream *p); static void do_something(pa_pstream *p) { - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); pa_pstream_ref(p); - pa_mutex_lock(p->mutex); - p->mainloop->defer_enable(p->defer_event, 0); if (!p->dead && pa_iochannel_is_readable(p->io)) { @@ -188,28 +193,24 @@ static void do_something(pa_pstream *p) { goto fail; } - pa_mutex_unlock(p->mutex); - pa_pstream_unref(p); return; fail: - p->dead = 1; - if (p->die_callback) p->die_callback(p, p->die_callback_userdata); - pa_mutex_unlock(p->mutex); - + pa_pstream_unlink(p); pa_pstream_unref(p); } static void io_callback(pa_iochannel*io, void *userdata) { pa_pstream *p = userdata; - assert(p); - assert(p->io == io); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p->io == io); do_something(p); } @@ -217,9 +218,10 @@ static void io_callback(pa_iochannel*io, void *userdata) { static void defer_callback(pa_mainloop_api *m, pa_defer_event *e, void*userdata) { pa_pstream *p = userdata; - assert(p); - assert(p->defer_event == e); - assert(p->mainloop == m); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p->defer_event == e); + pa_assert(p->mainloop == m); do_something(p); } @@ -229,9 +231,9 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *pool) { pa_pstream *p; - assert(m); - assert(io); - assert(pool); + pa_assert(m); + pa_assert(io); + pa_assert(pool); p = pa_xnew(pa_pstream, 1); PA_REFCNT_INIT(p); @@ -239,17 +241,15 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo pa_iochannel_set_callback(io, io_callback, p); p->dead = 0; - p->mutex = pa_mutex_new(1); - p->mainloop = m; p->defer_event = m->defer_new(m, defer_callback, p); m->defer_enable(p->defer_event, 0); p->send_queue = pa_queue_new(); - assert(p->send_queue); p->write.current = NULL; p->write.index = 0; + pa_memchunk_reset(&p->write.memchunk); p->read.memblock = NULL; p->read.packet = NULL; p->read.index = 0; @@ -262,6 +262,10 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo p->drain_callback_userdata = NULL; p->die_callback = NULL; p->die_callback_userdata = NULL; + p->revoke_callback = NULL; + p->revoke_callback_userdata = NULL; + p->release_callback = NULL; + p->release_callback_userdata = NULL; p->mempool = pool; @@ -281,56 +285,57 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo return p; } -static void item_free(void *item, PA_GCC_UNUSED void *p) { +static void item_free(void *item, PA_GCC_UNUSED void *q) { struct item_info *i = item; - assert(i); + pa_assert(i); if (i->type == PA_PSTREAM_ITEM_MEMBLOCK) { - assert(i->chunk.memblock); + pa_assert(i->chunk.memblock); pa_memblock_unref(i->chunk.memblock); } else if (i->type == PA_PSTREAM_ITEM_PACKET) { - assert(i->packet); + pa_assert(i->packet); pa_packet_unref(i->packet); } - pa_xfree(i); + if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0) + pa_xfree(i); } static void pstream_free(pa_pstream *p) { - assert(p); + pa_assert(p); - pa_pstream_close(p); + pa_pstream_unlink(p); pa_queue_free(p->send_queue, item_free, NULL); if (p->write.current) item_free(p->write.current, NULL); + if (p->write.memchunk.memblock) + pa_memblock_unref(p->write.memchunk.memblock); + if (p->read.memblock) pa_memblock_unref(p->read.memblock); if (p->read.packet) pa_packet_unref(p->read.packet); - if (p->mutex) - pa_mutex_free(p->mutex); - pa_xfree(p); } void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds) { struct item_info *i; - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); - assert(packet); - - pa_mutex_lock(p->mutex); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(packet); if (p->dead) - goto finish; + return; + + if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items)))) + i = pa_xnew(struct item_info, 1); - i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_PACKET; i->packet = pa_packet_ref(packet); @@ -340,37 +345,36 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre #endif pa_queue_push(p->send_queue, i); + p->mainloop->defer_enable(p->defer_event, 1); - -finish: - - pa_mutex_unlock(p->mutex); } void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) { size_t length, idx; + size_t bsm; - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); - assert(channel != (uint32_t) -1); - assert(chunk); - - pa_mutex_lock(p->mutex); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(channel != (uint32_t) -1); + pa_assert(chunk); if (p->dead) - goto finish; + return; - length = chunk->length; idx = 0; + length = chunk->length; + + bsm = pa_mempool_block_size_max(p->mempool); while (length > 0) { struct item_info *i; size_t n; - i = pa_xnew(struct item_info, 1); + if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items)))) + i = pa_xnew(struct item_info, 1); i->type = PA_PSTREAM_ITEM_MEMBLOCK; - n = length < FRAME_SIZE_MAX_USE ? length : FRAME_SIZE_MAX_USE; + n = MIN(length, bsm); i->chunk.index = chunk->index + idx; i->chunk.length = n; i->chunk.memblock = pa_memblock_ref(chunk->memblock); @@ -389,27 +393,20 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa } p->mainloop->defer_enable(p->defer_event, 1); - -finish: - - pa_mutex_unlock(p->mutex); } -static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata) { +void pa_pstream_send_release(pa_pstream *p, uint32_t block_id) { struct item_info *item; - pa_pstream *p = userdata; - - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); - - pa_mutex_lock(p->mutex); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); if (p->dead) - goto finish; + return; /* pa_log("Releasing block %u", block_id); */ - item = pa_xnew(struct item_info, 1); + if (!(item = pa_flist_pop(PA_STATIC_FLIST_GET(items)))) + item = pa_xnew(struct item_info, 1); item->type = PA_PSTREAM_ITEM_SHMRELEASE; item->block_id = block_id; #ifdef HAVE_CREDS @@ -418,27 +415,35 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd pa_queue_push(p->send_queue, item); p->mainloop->defer_enable(p->defer_event, 1); - -finish: - - pa_mutex_unlock(p->mutex); } -static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) { - struct item_info *item; +/* might be called from thread context */ +static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata) { pa_pstream *p = userdata; - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); - - pa_mutex_lock(p->mutex); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); if (p->dead) - goto finish; + return; + if (p->release_callback) + p->release_callback(p, block_id, p->release_callback_userdata); + else + pa_pstream_send_release(p, block_id); +} + +void pa_pstream_send_revoke(pa_pstream *p, uint32_t block_id) { + struct item_info *item; + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); + + if (p->dead) + return; /* pa_log("Revoking block %u", block_id); */ - item = pa_xnew(struct item_info, 1); + if (!(item = pa_flist_pop(PA_STATIC_FLIST_GET(items)))) + item = pa_xnew(struct item_info, 1); item->type = PA_PSTREAM_ITEM_SHMREVOKE; item->block_id = block_id; #ifdef HAVE_CREDS @@ -447,21 +452,33 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda pa_queue_push(p->send_queue, item); p->mainloop->defer_enable(p->defer_event, 1); +} -finish: +/* might be called from thread context */ +static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) { + pa_pstream *p = userdata; - pa_mutex_unlock(p->mutex); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); + + if (p->revoke_callback) + p->revoke_callback(p, block_id, p->revoke_callback_userdata); + else + pa_pstream_send_revoke(p, block_id); } static void prepare_next_write_item(pa_pstream *p) { - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); - if (!(p->write.current = pa_queue_pop(p->send_queue))) + p->write.current = pa_queue_pop(p->send_queue); + + if (!p->write.current) return; p->write.index = 0; p->write.data = NULL; + pa_memchunk_reset(&p->write.memchunk); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = 0; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1); @@ -471,7 +488,7 @@ static void prepare_next_write_item(pa_pstream *p) { if (p->write.current->type == PA_PSTREAM_ITEM_PACKET) { - assert(p->write.current->packet); + pa_assert(p->write.current->packet); p->write.data = p->write.current->packet->data; p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length); @@ -489,8 +506,8 @@ static void prepare_next_write_item(pa_pstream *p) { uint32_t flags; int send_payload = 1; - assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK); - assert(p->write.current->chunk.memblock); + pa_assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK); + pa_assert(p->write.current->chunk.memblock); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl(p->write.current->channel); p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl((uint32_t) (((uint64_t) p->write.current->offset) >> 32)); @@ -502,7 +519,7 @@ static void prepare_next_write_item(pa_pstream *p) { uint32_t block_id, shm_id; size_t offset, length; - assert(p->export); + pa_assert(p->export); if (pa_memexport_put(p->export, p->write.current->chunk.memblock, @@ -528,7 +545,9 @@ static void prepare_next_write_item(pa_pstream *p) { if (send_payload) { p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length); - p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index; + p->write.memchunk = p->write.current->chunk; + pa_memblock_ref(p->write.memchunk.memblock); + p->write.data = NULL; } p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(flags); @@ -544,9 +563,10 @@ static int do_write(pa_pstream *p) { void *d; size_t l; ssize_t r; + pa_memblock *release_memblock = NULL; - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); if (!p->write.current) prepare_next_write_item(p); @@ -558,72 +578,105 @@ static int do_write(pa_pstream *p) { d = (uint8_t*) p->write.descriptor + p->write.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->write.index; } else { - assert(p->write.data); + pa_assert(p->write.data || p->write.memchunk.memblock); - d = (uint8_t*) p->write.data + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; + if (p->write.data) + d = p->write.data; + else { + d = (uint8_t*) pa_memblock_acquire(p->write.memchunk.memblock) + p->write.memchunk.index; + release_memblock = p->write.memchunk.memblock; + } + + d = (uint8_t*) d + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE; l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE); } - assert(l > 0); + pa_assert(l > 0); #ifdef HAVE_CREDS if (p->send_creds_now) { if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0) - return -1; + goto fail; p->send_creds_now = 0; } else #endif if ((r = pa_iochannel_write(p->io, d, l)) < 0) - return -1; + goto fail; + + if (release_memblock) + pa_memblock_release(release_memblock); p->write.index += r; if (p->write.index >= PA_PSTREAM_DESCRIPTOR_SIZE + ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])) { - assert(p->write.current); - item_free(p->write.current, (void *) 1); + pa_assert(p->write.current); + item_free(p->write.current, NULL); p->write.current = NULL; + if (p->write.memchunk.memblock) + pa_memblock_unref(p->write.memchunk.memblock); + + pa_memchunk_reset(&p->write.memchunk); + if (p->drain_callback && !pa_pstream_is_pending(p)) p->drain_callback(p, p->drain_callback_userdata); } return 0; + +fail: + + if (release_memblock) + pa_memblock_release(release_memblock); + + return -1; } static int do_read(pa_pstream *p) { void *d; size_t l; ssize_t r; - - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); + pa_memblock *release_memblock = NULL; + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); if (p->read.index < PA_PSTREAM_DESCRIPTOR_SIZE) { d = (uint8_t*) p->read.descriptor + p->read.index; l = PA_PSTREAM_DESCRIPTOR_SIZE - p->read.index; } else { - assert(p->read.data); - d = (uint8_t*) p->read.data + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE; + pa_assert(p->read.data || p->read.memblock); + + if (p->read.data) + d = p->read.data; + else { + d = pa_memblock_acquire(p->read.memblock); + release_memblock = p->read.memblock; + } + + d = (uint8_t*) d + p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE; l = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE); } #ifdef HAVE_CREDS { - int b = 0; + pa_bool_t b = 0; if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->read_creds, &b)) <= 0) - return -1; + goto fail; p->read_creds_valid = p->read_creds_valid || b; } #else if ((r = pa_iochannel_read(p->io, d, l)) <= 0) - return -1; + goto fail; #endif + if (release_memblock) + pa_memblock_release(release_memblock); + p->read.index += r; if (p->read.index == PA_PSTREAM_DESCRIPTOR_SIZE) { @@ -643,7 +696,7 @@ static int do_read(pa_pstream *p) { /* pa_log("Got release frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */ - assert(p->export); + pa_assert(p->export); pa_memexport_process_release(p->export, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); goto frame_done; @@ -654,7 +707,7 @@ static int do_read(pa_pstream *p) { /* pa_log("Got revoke frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */ - assert(p->import); + pa_assert(p->import); pa_memimport_process_revoke(p->import, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); goto frame_done; @@ -667,7 +720,7 @@ static int do_read(pa_pstream *p) { return -1; } - assert(!p->read.packet && !p->read.memblock); + pa_assert(!p->read.packet && !p->read.memblock); channel = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]); @@ -704,7 +757,7 @@ static int do_read(pa_pstream *p) { /* Frame is a memblock frame */ p->read.memblock = pa_memblock_new(p->mempool, length); - p->read.data = p->read.memblock->data; + p->read.data = NULL; } else { pa_log_warn("Recieved memblock frame with invalid flags value."); @@ -771,9 +824,9 @@ static int do_read(pa_pstream *p) { } else { pa_memblock *b; - assert((ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA); + pa_assert((ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA); - assert(p->import); + pa_assert(p->import); if (!(b = pa_memimport_get(p->import, ntohl(p->read.shm_info[PA_PSTREAM_SHM_BLOCKID]), @@ -791,7 +844,7 @@ static int do_read(pa_pstream *p) { chunk.memblock = b; chunk.index = 0; - chunk.length = b->length; + chunk.length = pa_memblock_get_length(b); offset = (int64_t) ( (((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) | @@ -819,92 +872,104 @@ frame_done: p->read.memblock = NULL; p->read.packet = NULL; p->read.index = 0; + p->read.data = NULL; #ifdef HAVE_CREDS p->read_creds_valid = 0; #endif return 0; + +fail: + if (release_memblock) + pa_memblock_release(release_memblock); + + return -1; } void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); p->die_callback = cb; p->die_callback_userdata = userdata; - pa_mutex_unlock(p->mutex); } void pa_pstream_set_drain_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) { - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); p->drain_callback = cb; p->drain_callback_userdata = userdata; - pa_mutex_unlock(p->mutex); } void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata) { - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); p->recieve_packet_callback = cb; p->recieve_packet_callback_userdata = userdata; - pa_mutex_unlock(p->mutex); } void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock_cb_t cb, void *userdata) { - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); - pa_mutex_lock(p->mutex); p->recieve_memblock_callback = cb; p->recieve_memblock_callback_userdata = userdata; - pa_mutex_unlock(p->mutex); +} + +void pa_pstream_set_release_callback(pa_pstream *p, pa_pstream_block_id_cb_t cb, void *userdata) { + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); + + p->release_callback = cb; + p->release_callback_userdata = userdata; +} + +void pa_pstream_set_revoke_callback(pa_pstream *p, pa_pstream_block_id_cb_t cb, void *userdata) { + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); + + p->release_callback = cb; + p->release_callback_userdata = userdata; } int pa_pstream_is_pending(pa_pstream *p) { int b; - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); - - pa_mutex_lock(p->mutex); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); if (p->dead) b = 0; else b = p->write.current || !pa_queue_is_empty(p->send_queue); - pa_mutex_unlock(p->mutex); - return b; } void pa_pstream_unref(pa_pstream*p) { - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); if (PA_REFCNT_DEC(p) <= 0) pstream_free(p); } pa_pstream* pa_pstream_ref(pa_pstream*p) { - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); PA_REFCNT_INC(p); return p; } -void pa_pstream_close(pa_pstream *p) { - assert(p); +void pa_pstream_unlink(pa_pstream *p) { + pa_assert(p); - pa_mutex_lock(p->mutex); + if (p->dead) + return; p->dead = 1; @@ -932,15 +997,11 @@ void pa_pstream_close(pa_pstream *p) { p->drain_callback = NULL; p->recieve_packet_callback = NULL; p->recieve_memblock_callback = NULL; - - pa_mutex_unlock(p->mutex); } void pa_pstream_use_shm(pa_pstream *p, int enable) { - assert(p); - assert(PA_REFCNT_VALUE(p) > 0); - - pa_mutex_lock(p->mutex); + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) > 0); p->use_shm = enable; @@ -956,6 +1017,4 @@ void pa_pstream_use_shm(pa_pstream *p, int enable) { p->export = NULL; } } - - pa_mutex_unlock(p->mutex); } diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h index 5900eceab..72babea9b 100644 --- a/src/pulsecore/pstream.h +++ b/src/pulsecore/pstream.h @@ -41,6 +41,7 @@ typedef struct pa_pstream pa_pstream; typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata); typedef void (*pa_pstream_memblock_cb_t)(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata); typedef void (*pa_pstream_notify_cb_t)(pa_pstream *p, void *userdata); +typedef void (*pa_pstream_block_id_cb_t)(pa_pstream *p, uint32_t block_id, void *userdata); pa_pstream* pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *p); void pa_pstream_unref(pa_pstream*p); @@ -48,17 +49,20 @@ pa_pstream* pa_pstream_ref(pa_pstream*p); void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *creds); void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk); +void pa_pstream_send_release(pa_pstream *p, uint32_t block_id); +void pa_pstream_send_revoke(pa_pstream *p, uint32_t block_id); void pa_pstream_set_recieve_packet_callback(pa_pstream *p, pa_pstream_packet_cb_t cb, void *userdata); void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock_cb_t cb, void *userdata); void pa_pstream_set_drain_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata); - void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata); +void pa_pstream_set_release_callback(pa_pstream *p, pa_pstream_block_id_cb_t cb, void *userdata); +void pa_pstream_set_revoke_callback(pa_pstream *p, pa_pstream_block_id_cb_t cb, void *userdata); int pa_pstream_is_pending(pa_pstream *p); void pa_pstream_use_shm(pa_pstream *p, int enable); -void pa_pstream_close(pa_pstream *p); +void pa_pstream_unlink(pa_pstream *p); #endif diff --git a/src/pulsecore/queue.c b/src/pulsecore/queue.c index 1dd0f6061..9b6a37f02 100644 --- a/src/pulsecore/queue.c +++ b/src/pulsecore/queue.c @@ -25,13 +25,16 @@ #include #endif -#include #include #include +#include +#include #include "queue.h" +PA_STATIC_FLIST_DECLARE(entries, 0, pa_xfree); + struct queue_entry { struct queue_entry *next; void *data; @@ -44,25 +47,24 @@ struct pa_queue { pa_queue* pa_queue_new(void) { pa_queue *q = pa_xnew(pa_queue, 1); + q->front = q->back = NULL; q->length = 0; + return q; } void pa_queue_free(pa_queue* q, void (*destroy)(void *p, void *userdata), void *userdata) { - struct queue_entry *e; - assert(q); - - e = q->front; - while (e) { - struct queue_entry *n = e->next; + void *data; + pa_assert(q); + while ((data = pa_queue_pop(q))) if (destroy) - destroy(e->data, userdata); + destroy(data, userdata); - pa_xfree(e); - e = n; - } + pa_assert(!q->front); + pa_assert(!q->back); + pa_assert(q->length == 0); pa_xfree(q); } @@ -70,14 +72,20 @@ void pa_queue_free(pa_queue* q, void (*destroy)(void *p, void *userdata), void * void pa_queue_push(pa_queue *q, void *p) { struct queue_entry *e; - e = pa_xnew(struct queue_entry, 1); + pa_assert(q); + pa_assert(p); + + if (!(e = pa_flist_pop(PA_STATIC_FLIST_GET(entries)))) + e = pa_xnew(struct queue_entry, 1); + e->data = p; e->next = NULL; - if (q->back) + if (q->back) { + pa_assert(q->front); q->back->next = e; - else { - assert(!q->front); + } else { + pa_assert(!q->front); q->front = e; } @@ -88,17 +96,22 @@ void pa_queue_push(pa_queue *q, void *p) { void* pa_queue_pop(pa_queue *q) { void *p; struct queue_entry *e; - assert(q); + pa_assert(q); if (!(e = q->front)) return NULL; q->front = e->next; - if (q->back == e) + + if (q->back == e) { + pa_assert(!e->next); q->back = NULL; + } p = e->data; - pa_xfree(e); + + if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0) + pa_xfree(e); q->length--; @@ -106,6 +119,7 @@ void* pa_queue_pop(pa_queue *q) { } int pa_queue_is_empty(pa_queue *q) { - assert(q); + pa_assert(q); + return q->length == 0; } diff --git a/src/pulsecore/random.c b/src/pulsecore/random.c index 3f5919173..87afebfa6 100644 --- a/src/pulsecore/random.c +++ b/src/pulsecore/random.c @@ -31,21 +31,22 @@ #include #include #include -#include #include #include #include +#include #include "random.h" static int has_whined = 0; -static const char *devices[] = { "/dev/urandom", "/dev/random", NULL }; +static const char * const devices[] = { "/dev/urandom", "/dev/random", NULL }; static int random_proper(void *ret_data, size_t length) { #ifdef OS_IS_WIN32 - assert(ret_data && length); + pa_assert(ret_data); + pa_assert(length > 0); return -1; @@ -53,9 +54,10 @@ static int random_proper(void *ret_data, size_t length) { int fd, ret = -1; ssize_t r = 0; - const char **device; + const char *const * device; - assert(ret_data && length); + pa_assert(ret_data); + pa_assert(length > 0); device = devices; @@ -67,7 +69,7 @@ static int random_proper(void *ret_data, size_t length) { if ((r = pa_loop_read(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) ret = -1; - close(fd); + pa_close(fd); } else ret = -1; @@ -84,7 +86,7 @@ void pa_random_seed(void) { if (random_proper(&seed, sizeof(unsigned int)) < 0) { if (!has_whined) - pa_log_warn("failed to get proper entropy. Falling back to seeding with current time."); + pa_log_warn("Failed to get proper entropy. Falling back to seeding with current time."); has_whined = 1; seed = (unsigned int) time(NULL); @@ -97,13 +99,14 @@ void pa_random(void *ret_data, size_t length) { uint8_t *p; size_t l; - assert(ret_data && length); + pa_assert(ret_data); + pa_assert(length > 0); if (random_proper(ret_data, length) >= 0) return; if (!has_whined) - pa_log_warn("failed to get proper entropy. Falling back to unsecure pseudo RNG."); + pa_log_warn("Failed to get proper entropy. Falling back to unsecure pseudo RNG."); has_whined = 1; for (p = ret_data, l = length; l > 0; p++, l--) diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h index 43433ff84..64271ab27 100644 --- a/src/pulsecore/refcnt.h +++ b/src/pulsecore/refcnt.h @@ -27,18 +27,18 @@ #include #define PA_REFCNT_DECLARE \ - pa_atomic_int_t _ref + pa_atomic_t _ref #define PA_REFCNT_INIT(p) \ - pa_atomic_store(&p->_ref, 1) + pa_atomic_store(&(p)->_ref, 1) #define PA_REFCNT_INC(p) \ - pa_atomic_inc(&p->_ref) + pa_atomic_inc(&(p)->_ref) #define PA_REFCNT_DEC(p) \ - (pa_atomic_dec(&p->_ref)-1) + (pa_atomic_dec(&(p)->_ref)-1) #define PA_REFCNT_VALUE(p) \ - pa_atomic_load(&p->_ref) + pa_atomic_load(&(p)->_ref) #endif diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index 3827ff94a..5bbc6bf44 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -25,53 +25,133 @@ #include #endif -#include #include +#if HAVE_LIBSAMPLERATE #include +#endif + #include #include #include - #include #include +#include + +#include "speexwrap.h" + +#include "ffmpeg/avcodec.h" #include "resampler.h" +/* Number of samples of extra space we allow the resamplers to return */ +#define EXTRA_SAMPLES 128 + struct pa_resampler { pa_resample_method_t resample_method; pa_sample_spec i_ss, o_ss; pa_channel_map i_cm, o_cm; - size_t i_fz, o_fz; + size_t i_fz, o_fz, w_sz; pa_mempool *mempool; - void (*impl_free)(pa_resampler *r); - void (*impl_update_input_rate)(pa_resampler *r, uint32_t rate); - void (*impl_run)(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out); - void *impl_data; -}; - -struct impl_libsamplerate { - pa_memblock *buf1_block, *buf2_block, *buf3_block, *buf4_block; - float* buf1, *buf2, *buf3, *buf4; + pa_memchunk buf1, buf2, buf3, buf4; unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples; - pa_convert_to_float32ne_func_t to_float32ne_func; - pa_convert_from_float32ne_func_t from_float32ne_func; - SRC_STATE *src_state; + pa_sample_format_t work_format; + + pa_convert_func_t to_work_format_func; + pa_convert_func_t from_work_format_func; int map_table[PA_CHANNELS_MAX][PA_CHANNELS_MAX]; int map_required; + + void (*impl_free)(pa_resampler *r); + void (*impl_update_rates)(pa_resampler *r); + void (*impl_resample)(pa_resampler *r, const pa_memchunk *in, unsigned in_samples, pa_memchunk *out, unsigned *out_samples); + + struct { /* data specific to the trivial resampler */ + unsigned o_counter; + unsigned i_counter; + } trivial; + +#ifdef HAVE_LIBSAMPLERATE + struct { /* data specific to libsamplerate */ + SRC_STATE *state; + } src; +#endif + + struct { /* data specific to speex */ + SpeexResamplerState* state; + } speex; + + struct { /* data specific to ffmpeg */ + struct AVResampleContext *state; + pa_memchunk buf[PA_CHANNELS_MAX]; + } ffmpeg; }; -struct impl_trivial { - unsigned o_counter; - unsigned i_counter; -}; - -static int libsamplerate_init(pa_resampler*r); +static int copy_init(pa_resampler *r); static int trivial_init(pa_resampler*r); +static int speex_init(pa_resampler*r); +static int ffmpeg_init(pa_resampler*r); +#ifdef HAVE_LIBSAMPLERATE +static int libsamplerate_init(pa_resampler*r); +#endif + +static void calc_map_table(pa_resampler *r); + +static int (* const init_table[])(pa_resampler*r) = { +#ifdef HAVE_LIBSAMPLERATE + [PA_RESAMPLER_SRC_SINC_BEST_QUALITY] = libsamplerate_init, + [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY] = libsamplerate_init, + [PA_RESAMPLER_SRC_SINC_FASTEST] = libsamplerate_init, + [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD] = libsamplerate_init, + [PA_RESAMPLER_SRC_LINEAR] = libsamplerate_init, +#else + [PA_RESAMPLER_SRC_SINC_BEST_QUALITY] = NULL, + [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY] = NULL, + [PA_RESAMPLER_SRC_SINC_FASTEST] = NULL, + [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD] = NULL, + [PA_RESAMPLER_SRC_LINEAR] = NULL, +#endif + [PA_RESAMPLER_TRIVIAL] = trivial_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+0] = speex_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+1] = speex_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+2] = speex_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+3] = speex_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+4] = speex_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+5] = speex_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+6] = speex_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+7] = speex_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+8] = speex_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+9] = speex_init, + [PA_RESAMPLER_SPEEX_FLOAT_BASE+10] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+0] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+1] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+2] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+3] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+4] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+5] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+6] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+7] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+8] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+9] = speex_init, + [PA_RESAMPLER_SPEEX_FIXED_BASE+10] = speex_init, + [PA_RESAMPLER_FFMPEG] = ffmpeg_init, + [PA_RESAMPLER_AUTO] = NULL, + [PA_RESAMPLER_COPY] = copy_init +}; + +static inline size_t sample_size(pa_sample_format_t f) { + pa_sample_spec ss = { + .format = f, + .rate = 0, + .channels = 1 + }; + + return pa_sample_size(&ss); +} pa_resampler* pa_resampler_new( pa_mempool *pool, @@ -79,25 +159,51 @@ pa_resampler* pa_resampler_new( const pa_channel_map *am, const pa_sample_spec *b, const pa_channel_map *bm, - pa_resample_method_t resample_method) { + pa_resample_method_t resample_method, + int variable_rate) { pa_resampler *r = NULL; - assert(pool); - assert(a); - assert(b); - assert(pa_sample_spec_valid(a)); - assert(pa_sample_spec_valid(b)); - assert(resample_method != PA_RESAMPLER_INVALID); + pa_assert(pool); + pa_assert(a); + pa_assert(b); + pa_assert(pa_sample_spec_valid(a)); + pa_assert(pa_sample_spec_valid(b)); + pa_assert(resample_method >= 0); + pa_assert(resample_method < PA_RESAMPLER_MAX); + + /* Fix method */ + + if (!variable_rate && a->rate == b->rate) { + pa_log_info("Forcing resampler 'copy', because of fixed, identical sample rates."); + resample_method = PA_RESAMPLER_COPY; + } + + if (!pa_resample_method_supported(resample_method)) { + pa_log_warn("Support for resampler '%s' not compiled in, reverting to 'auto'.", pa_resample_method_to_string(resample_method)); + resample_method = PA_RESAMPLER_AUTO; + } + + if (resample_method == PA_RESAMPLER_FFMPEG && variable_rate) { + pa_log_info("Resampler 'ffmpeg' cannot do variable rate, reverting to resampler 'auto'."); + resample_method = PA_RESAMPLER_AUTO; + } + + if (resample_method == PA_RESAMPLER_COPY && (variable_rate || a->rate != b->rate)) { + pa_log_info("Resampler 'copy' cannot change sampling rate, reverting to resampler 'auto'."); + resample_method = PA_RESAMPLER_AUTO; + } + + if (resample_method == PA_RESAMPLER_AUTO) + resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 0; r = pa_xnew(pa_resampler, 1); - r->impl_data = NULL; r->mempool = pool; r->resample_method = resample_method; r->impl_free = NULL; - r->impl_update_input_rate = NULL; - r->impl_run = NULL; + r->impl_update_rates = NULL; + r->impl_resample = NULL; /* Fill sample specs */ r->i_ss = *a; @@ -116,25 +222,66 @@ pa_resampler* pa_resampler_new( r->i_fz = pa_frame_size(a); r->o_fz = pa_frame_size(b); - /* Choose implementation */ - if (a->channels != b->channels || - a->format != b->format || - !pa_channel_map_equal(&r->i_cm, &r->o_cm) || - resample_method != PA_RESAMPLER_TRIVIAL) { + pa_memchunk_reset(&r->buf1); + pa_memchunk_reset(&r->buf2); + pa_memchunk_reset(&r->buf3); + pa_memchunk_reset(&r->buf4); - /* Use the libsamplerate based resampler for the complicated cases */ - if (resample_method == PA_RESAMPLER_TRIVIAL) - r->resample_method = PA_RESAMPLER_SRC_ZERO_ORDER_HOLD; + r->buf1_samples = r->buf2_samples = r->buf3_samples = r->buf4_samples = 0; - if (libsamplerate_init(r) < 0) + calc_map_table(r); + + pa_log_info("Using resampler '%s'", pa_resample_method_to_string(resample_method)); + + if ((resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) || + (resample_method == PA_RESAMPLER_FFMPEG)) + r->work_format = PA_SAMPLE_S16NE; + else if (resample_method == PA_RESAMPLER_TRIVIAL || resample_method == PA_RESAMPLER_COPY) { + + if (r->map_required || a->format != b->format) { + + if (a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE || + b->format == PA_SAMPLE_FLOAT32NE || b->format == PA_SAMPLE_FLOAT32RE) + r->work_format = PA_SAMPLE_FLOAT32NE; + else + r->work_format = PA_SAMPLE_S16NE; + + } else + r->work_format = a->format; + + } else + r->work_format = PA_SAMPLE_FLOAT32NE; + + pa_log_info("Using %s as working format.", pa_sample_format_to_string(r->work_format)); + + r->w_sz = sample_size(r->work_format); + + if (r->i_ss.format == r->work_format) + r->to_work_format_func = NULL; + else if (r->work_format == PA_SAMPLE_FLOAT32NE) { + if (!(r->to_work_format_func = pa_get_convert_to_float32ne_function(r->i_ss.format))) goto fail; - } else { - /* Use our own simple non-fp resampler for the trivial cases and when the user selects it */ - if (trivial_init(r) < 0) + pa_assert(r->work_format == PA_SAMPLE_S16NE); + if (!(r->to_work_format_func = pa_get_convert_to_s16ne_function(r->i_ss.format))) goto fail; } + if (r->o_ss.format == r->work_format) + r->from_work_format_func = NULL; + else if (r->work_format == PA_SAMPLE_FLOAT32NE) { + if (!(r->from_work_format_func = pa_get_convert_from_float32ne_function(r->o_ss.format))) + goto fail; + } else { + pa_assert(r->work_format == PA_SAMPLE_S16NE); + if (!(r->from_work_format_func = pa_get_convert_from_s16ne_function(r->o_ss.format))) + goto fail; + } + + /* initialize implementation */ + if (init_table[resample_method](r) < 0) + goto fail; + return r; fail: @@ -145,41 +292,85 @@ fail: } void pa_resampler_free(pa_resampler *r) { - assert(r); + pa_assert(r); if (r->impl_free) r->impl_free(r); + if (r->buf1.memblock) + pa_memblock_unref(r->buf1.memblock); + if (r->buf2.memblock) + pa_memblock_unref(r->buf2.memblock); + if (r->buf3.memblock) + pa_memblock_unref(r->buf3.memblock); + if (r->buf4.memblock) + pa_memblock_unref(r->buf4.memblock); + pa_xfree(r); } void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) { - assert(r); - assert(rate > 0); + pa_assert(r); + pa_assert(rate > 0); if (r->i_ss.rate == rate) return; r->i_ss.rate = rate; - if (r->impl_update_input_rate) - r->impl_update_input_rate(r, rate); + r->impl_update_rates(r); } -void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { - assert(r && in && out && r->impl_run); +void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) { + pa_assert(r); + pa_assert(rate > 0); - r->impl_run(r, in, out); + if (r->o_ss.rate == rate) + return; + + r->o_ss.rate = rate; + + r->impl_update_rates(r); } size_t pa_resampler_request(pa_resampler *r, size_t out_length) { - assert(r); + pa_assert(r); return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz; } +size_t pa_resampler_max_block_size(pa_resampler *r) { + size_t block_size_max; + pa_sample_spec ss; + size_t fs; + + pa_assert(r); + + block_size_max = pa_mempool_block_size_max(r->mempool); + + /* We deduce the "largest" sample spec we're using during the + * conversion */ + ss = r->i_ss; + if (r->o_ss.channels > ss.channels) + ss.channels = r->o_ss.channels; + + /* We silently assume that the format enum is ordered by size */ + if (r->o_ss.format > ss.format) + ss.format = r->o_ss.format; + if (r->work_format > ss.format) + ss.format = r->work_format; + + if (r->o_ss.rate > ss.rate) + ss.rate = r->o_ss.rate; + + fs = pa_frame_size(&ss); + + return (((block_size_max/fs + EXTRA_SAMPLES)*r->i_ss.rate)/ss.rate)*r->i_fz; +} + pa_resample_method_t pa_resampler_get_method(pa_resampler *r) { - assert(r); + pa_assert(r); + return r->resample_method; } @@ -189,7 +380,32 @@ static const char * const resample_methods[] = { "src-sinc-fastest", "src-zero-order-hold", "src-linear", - "trivial" + "trivial", + "speex-float-0", + "speex-float-1", + "speex-float-2", + "speex-float-3", + "speex-float-4", + "speex-float-5", + "speex-float-6", + "speex-float-7", + "speex-float-8", + "speex-float-9", + "speex-float-10", + "speex-fixed-0", + "speex-fixed-1", + "speex-fixed-2", + "speex-fixed-3", + "speex-fixed-4", + "speex-fixed-5", + "speex-fixed-6", + "speex-fixed-7", + "speex-fixed-8", + "speex-fixed-9", + "speex-fixed-10", + "ffmpeg", + "auto", + "copy" }; const char *pa_resample_method_to_string(pa_resample_method_t m) { @@ -200,52 +416,43 @@ const char *pa_resample_method_to_string(pa_resample_method_t m) { return resample_methods[m]; } +int pa_resample_method_supported(pa_resample_method_t m) { + + if (m < 0 || m >= PA_RESAMPLER_MAX) + return 0; + +#ifndef HAVE_LIBSAMPLERATE + if (m <= PA_RESAMPLER_SRC_LINEAR) + return 0; +#endif + + return 1; +} + pa_resample_method_t pa_parse_resample_method(const char *string) { pa_resample_method_t m; - assert(string); + pa_assert(string); for (m = 0; m < PA_RESAMPLER_MAX; m++) if (!strcmp(string, resample_methods[m])) return m; + if (!strcmp(string, "speex-fixed")) + return PA_RESAMPLER_SPEEX_FIXED_BASE + 0; + + if (!strcmp(string, "speex-float")) + return PA_RESAMPLER_SPEEX_FLOAT_BASE + 0; + return PA_RESAMPLER_INVALID; } - -/*** libsamplerate based implementation ***/ - -static void libsamplerate_free(pa_resampler *r) { - struct impl_libsamplerate *u; - - assert(r); - assert(r->impl_data); - - u = r->impl_data; - - if (u->src_state) - src_delete(u->src_state); - - if (u->buf1_block) - pa_memblock_unref(u->buf1_block); - if (u->buf2_block) - pa_memblock_unref(u->buf2_block); - if (u->buf3_block) - pa_memblock_unref(u->buf3_block); - if (u->buf4_block) - pa_memblock_unref(u->buf4_block); - pa_xfree(u); -} - static void calc_map_table(pa_resampler *r) { - struct impl_libsamplerate *u; unsigned oc; - assert(r); - assert(r->impl_data); - u = r->impl_data; + pa_assert(r); - if (!(u->map_required = (!pa_channel_map_equal(&r->i_cm, &r->o_cm) || r->i_ss.channels != r->o_ss.channels))) + if (!(r->map_required = (r->i_ss.channels != r->o_ss.channels || !pa_channel_map_equal(&r->i_cm, &r->o_cm)))) return; for (oc = 0; oc < r->o_ss.channels; oc++) { @@ -263,392 +470,590 @@ static void calc_map_table(pa_resampler *r) { (a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) || (a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO)) - u->map_table[oc][i++] = ic; + r->map_table[oc][i++] = ic; } /* Add an end marker */ if (i < PA_CHANNELS_MAX) - u->map_table[oc][i] = -1; + r->map_table[oc][i] = -1; } } -static float * convert_to_float(pa_resampler *r, void *input, unsigned n_frames) { - struct impl_libsamplerate *u; +static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) { unsigned n_samples; + void *src, *dst; - assert(r); - assert(input); - assert(r->impl_data); - u = r->impl_data; + pa_assert(r); + pa_assert(input); + pa_assert(input->memblock); - /* Convert the incoming sample into floats and place them in buf1 */ + /* Convert the incoming sample into the work sample format and place them in buf1 */ - if (!u->to_float32ne_func) + if (!r->to_work_format_func || !input->length) return input; - n_samples = n_frames * r->i_ss.channels; + n_samples = (input->length / r->i_fz) * r->i_ss.channels; - if (u->buf1_samples < n_samples) { - if (u->buf1_block) - pa_memblock_unref(u->buf1_block); + r->buf1.index = 0; + r->buf1.length = r->w_sz * n_samples; - u->buf1_samples = n_samples; - u->buf1_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); - u->buf1 = u->buf1_block->data; + if (!r->buf1.memblock || r->buf1_samples < n_samples) { + if (r->buf1.memblock) + pa_memblock_unref(r->buf1.memblock); + + r->buf1_samples = n_samples; + r->buf1.memblock = pa_memblock_new(r->mempool, r->buf1.length); } - u->to_float32ne_func(n_samples, input, u->buf1); + src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index; + dst = (uint8_t*) pa_memblock_acquire(r->buf1.memblock); - return u->buf1; + r->to_work_format_func(n_samples, src, dst); + + pa_memblock_release(input->memblock); + pa_memblock_release(r->buf1.memblock); + + return &r->buf1; } -static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) { - struct impl_libsamplerate *u; - unsigned n_samples; +static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { + unsigned in_n_samples, out_n_samples, n_frames; int i_skip, o_skip; unsigned oc; + void *src, *dst; - assert(r); - assert(input); - assert(r->impl_data); - u = r->impl_data; + pa_assert(r); + pa_assert(input); + pa_assert(input->memblock); /* Remap channels and place the result int buf2 */ - if (!u->map_required) + if (!r->map_required || !input->length) return input; - n_samples = n_frames * r->o_ss.channels; + in_n_samples = input->length / r->w_sz; + n_frames = in_n_samples / r->i_ss.channels; + out_n_samples = n_frames * r->o_ss.channels; - if (u->buf2_samples < n_samples) { - if (u->buf2_block) - pa_memblock_unref(u->buf2_block); + r->buf2.index = 0; + r->buf2.length = r->w_sz * out_n_samples; - u->buf2_samples = n_samples; - u->buf2_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); - u->buf2 = u->buf2_block->data; + if (!r->buf2.memblock || r->buf2_samples < out_n_samples) { + if (r->buf2.memblock) + pa_memblock_unref(r->buf2.memblock); + + r->buf2_samples = out_n_samples; + r->buf2.memblock = pa_memblock_new(r->mempool, r->buf2.length); } - memset(u->buf2, 0, n_samples * sizeof(float)); + src = ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); + dst = pa_memblock_acquire(r->buf2.memblock); - o_skip = sizeof(float) * r->o_ss.channels; - i_skip = sizeof(float) * r->i_ss.channels; + memset(dst, 0, r->buf2.length); - for (oc = 0; oc < r->o_ss.channels; oc++) { - unsigned i; - static const float one = 1.0; + o_skip = r->w_sz * r->o_ss.channels; + i_skip = r->w_sz * r->i_ss.channels; - for (i = 0; i < PA_CHANNELS_MAX && u->map_table[oc][i] >= 0; i++) - oil_vectoradd_f32( - u->buf2 + oc, o_skip, - u->buf2 + oc, o_skip, - input + u->map_table[oc][i], i_skip, - n_frames, - &one, &one); + switch (r->work_format) { + case PA_SAMPLE_FLOAT32NE: + + for (oc = 0; oc < r->o_ss.channels; oc++) { + unsigned i; + static const float one = 1.0; + + for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++) + oil_vectoradd_f32( + (float*) dst + oc, o_skip, + (float*) dst + oc, o_skip, + (float*) src + r->map_table[oc][i], i_skip, + n_frames, + &one, &one); + } + + break; + + case PA_SAMPLE_S16NE: + + for (oc = 0; oc < r->o_ss.channels; oc++) { + unsigned i; + static const int16_t one = 1; + + for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++) + oil_vectoradd_s16( + (int16_t*) dst + oc, o_skip, + (int16_t*) dst + oc, o_skip, + (int16_t*) src + r->map_table[oc][i], i_skip, + n_frames, + &one, &one); + } + + break; + + default: + pa_assert_not_reached(); } - return u->buf2; + pa_memblock_release(input->memblock); + pa_memblock_release(r->buf2.memblock); + + r->buf2.length = out_n_samples * r->w_sz; + + return &r->buf2; } -static float *resample(pa_resampler *r, float *input, unsigned *n_frames) { - struct impl_libsamplerate *u; - SRC_DATA data; +static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) { + unsigned in_n_frames, in_n_samples; unsigned out_n_frames, out_n_samples; - int ret; - assert(r); - assert(input); - assert(n_frames); - assert(r->impl_data); - u = r->impl_data; + pa_assert(r); + pa_assert(input); /* Resample the data and place the result in buf3 */ - if (!u->src_state) + if (!r->impl_resample || !input->length) return input; - out_n_frames = (*n_frames*r->o_ss.rate/r->i_ss.rate)+1024; + in_n_samples = input->length / r->w_sz; + in_n_frames = in_n_samples / r->o_ss.channels; + + out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+EXTRA_SAMPLES; out_n_samples = out_n_frames * r->o_ss.channels; - if (u->buf3_samples < out_n_samples) { - if (u->buf3_block) - pa_memblock_unref(u->buf3_block); + r->buf3.index = 0; + r->buf3.length = r->w_sz * out_n_samples; - u->buf3_samples = out_n_samples; - u->buf3_block = pa_memblock_new(r->mempool, sizeof(float) * out_n_samples); - u->buf3 = u->buf3_block->data; + if (!r->buf3.memblock || r->buf3_samples < out_n_samples) { + if (r->buf3.memblock) + pa_memblock_unref(r->buf3.memblock); + + r->buf3_samples = out_n_samples; + r->buf3.memblock = pa_memblock_new(r->mempool, r->buf3.length); } - data.data_in = input; - data.input_frames = *n_frames; + r->impl_resample(r, input, in_n_frames, &r->buf3, &out_n_frames); + r->buf3.length = out_n_frames * r->w_sz * r->o_ss.channels; - data.data_out = u->buf3; - data.output_frames = out_n_frames; + return &r->buf3; +} + +static pa_memchunk *convert_from_work_format(pa_resampler *r, pa_memchunk *input) { + unsigned n_samples, n_frames; + void *src, *dst; + + pa_assert(r); + pa_assert(input); + + /* Convert the data into the correct sample type and place the result in buf4 */ + + if (!r->from_work_format_func || !input->length) + return input; + + n_samples = input->length / r->w_sz; + n_frames = n_samples / r->o_ss.channels; + + r->buf4.index = 0; + r->buf4.length = r->o_fz * n_frames; + + if (!r->buf4.memblock || r->buf4_samples < n_samples) { + if (r->buf4.memblock) + pa_memblock_unref(r->buf4.memblock); + + r->buf4_samples = n_samples; + r->buf4.memblock = pa_memblock_new(r->mempool, r->buf4.length); + } + + src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index; + dst = pa_memblock_acquire(r->buf4.memblock); + r->from_work_format_func(n_samples, src, dst); + pa_memblock_release(input->memblock); + pa_memblock_release(r->buf4.memblock); + + r->buf4.length = r->o_fz * n_frames; + + return &r->buf4; +} + +void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { + pa_memchunk *buf; + + pa_assert(r); + pa_assert(in); + pa_assert(out); + pa_assert(in->length); + pa_assert(in->memblock); + pa_assert(in->length % r->i_fz == 0); + + buf = (pa_memchunk*) in; + buf = convert_to_work_format(r, buf); + buf = remap_channels(r, buf); + buf = resample(r, buf); + + if (buf->length) { + buf = convert_from_work_format(r, buf); + *out = *buf; + + if (buf == in) + pa_memblock_ref(buf->memblock); + else + pa_memchunk_reset(buf); + } else + pa_memchunk_reset(out); +} + +/*** libsamplerate based implementation ***/ + +#ifdef HAVE_LIBSAMPLERATE +static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { + SRC_DATA data; + + pa_assert(r); + pa_assert(input); + pa_assert(output); + pa_assert(out_n_frames); + + memset(&data, 0, sizeof(data)); + + data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); + data.input_frames = in_n_frames; + + data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index); + data.output_frames = *out_n_frames; data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; data.end_of_input = 0; - ret = src_process(u->src_state, &data); - assert(ret == 0); - assert((unsigned) data.input_frames_used == *n_frames); + pa_assert_se(src_process(r->src.state, &data) == 0); + pa_assert((unsigned) data.input_frames_used == in_n_frames); - *n_frames = data.output_frames_gen; + pa_memblock_release(input->memblock); + pa_memblock_release(output->memblock); - return u->buf3; + *out_n_frames = data.output_frames_gen; } -static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) { - struct impl_libsamplerate *u; - unsigned n_samples; +static void libsamplerate_update_rates(pa_resampler *r) { + pa_assert(r); - assert(r); - assert(input); - assert(r->impl_data); - u = r->impl_data; - - /* Convert the data into the correct sample type and place the result in buf4 */ - - if (!u->from_float32ne_func) - return input; - - n_samples = n_frames * r->o_ss.channels; - - if (u->buf4_samples < n_samples) { - if (u->buf4_block) - pa_memblock_unref(u->buf4_block); - - u->buf4_samples = n_samples; - u->buf4_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples); - u->buf4 = u->buf4_block->data; - } - - u->from_float32ne_func(n_samples, input, u->buf4); - - return u->buf4; + pa_assert_se(src_set_ratio(r->src.state, (double) r->o_ss.rate / r->i_ss.rate) == 0); } -static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { - struct impl_libsamplerate *u; - float *buf; - void *input, *output; - unsigned n_frames; +static void libsamplerate_free(pa_resampler *r) { + pa_assert(r); - assert(r); - assert(in); - assert(out); - assert(in->length); - assert(in->memblock); - assert(in->length % r->i_fz == 0); - assert(r->impl_data); - - u = r->impl_data; - - input = ((uint8_t*) in->memblock->data + in->index); - n_frames = in->length / r->i_fz; - assert(n_frames > 0); - - buf = convert_to_float(r, input, n_frames); - buf = remap_channels(r, buf, n_frames); - buf = resample(r, buf, &n_frames); - - if (n_frames) { - output = convert_from_float(r, buf, n_frames); - - if (output == input) { - /* Mm, no adjustment has been necessary, so let's return the original block */ - out->memblock = pa_memblock_ref(in->memblock); - out->index = in->index; - out->length = in->length; - } else { - out->length = n_frames * r->o_fz; - out->index = 0; - out->memblock = NULL; - - if (output == u->buf1) { - u->buf1 = NULL; - u->buf1_samples = 0; - out->memblock = u->buf1_block; - u->buf1_block = NULL; - } else if (output == u->buf2) { - u->buf2 = NULL; - u->buf2_samples = 0; - out->memblock = u->buf2_block; - u->buf2_block = NULL; - } else if (output == u->buf3) { - u->buf3 = NULL; - u->buf3_samples = 0; - out->memblock = u->buf3_block; - u->buf3_block = NULL; - } else if (output == u->buf4) { - u->buf4 = NULL; - u->buf4_samples = 0; - out->memblock = u->buf4_block; - u->buf4_block = NULL; - } - - assert(out->memblock); - } - } else { - out->memblock = NULL; - out->index = out->length = 0; - } -} - -static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) { - struct impl_libsamplerate *u; - - assert(r); - assert(rate > 0); - assert(r->impl_data); - u = r->impl_data; - - if (!u->src_state) { - int err; - u->src_state = src_new(r->resample_method, r->o_ss.channels, &err); - assert(u->src_state); - } else { - int ret = src_set_ratio(u->src_state, (double) r->o_ss.rate / rate); - assert(ret == 0); - } + if (r->src.state) + src_delete(r->src.state); } static int libsamplerate_init(pa_resampler *r) { - struct impl_libsamplerate *u = NULL; int err; - r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1); + pa_assert(r); - u->buf1 = u->buf2 = u->buf3 = u->buf4 = NULL; - u->buf1_block = u->buf2_block = u->buf3_block = u->buf4_block = NULL; - u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0; - - if (r->i_ss.format == PA_SAMPLE_FLOAT32NE) - u->to_float32ne_func = NULL; - else if (!(u->to_float32ne_func = pa_get_convert_to_float32ne_function(r->i_ss.format))) - goto fail; - - if (r->o_ss.format == PA_SAMPLE_FLOAT32NE) - u->from_float32ne_func = NULL; - else if (!(u->from_float32ne_func = pa_get_convert_from_float32ne_function(r->o_ss.format))) - goto fail; - - if (r->o_ss.rate == r->i_ss.rate) - u->src_state = NULL; - else if (!(u->src_state = src_new(r->resample_method, r->o_ss.channels, &err))) - goto fail; + if (!(r->src.state = src_new(r->resample_method, r->o_ss.channels, &err))) + return -1; r->impl_free = libsamplerate_free; - r->impl_update_input_rate = libsamplerate_update_input_rate; - r->impl_run = libsamplerate_run; - - calc_map_table(r); + r->impl_update_rates = libsamplerate_update_rates; + r->impl_resample = libsamplerate_resample; return 0; +} +#endif -fail: - pa_xfree(u); - return -1; +/*** speex based implementation ***/ + +static void speex_resample_float(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { + float *in, *out; + uint32_t inf = in_n_frames, outf = *out_n_frames; + + pa_assert(r); + pa_assert(input); + pa_assert(output); + pa_assert(out_n_frames); + + in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); + out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index); + + pa_assert_se(paspfl_resampler_process_interleaved_float(r->speex.state, in, &inf, out, &outf) == 0); + + pa_memblock_release(input->memblock); + pa_memblock_release(output->memblock); + + pa_assert(inf == in_n_frames); + *out_n_frames = outf; +} + +static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { + int16_t *in, *out; + uint32_t inf = in_n_frames, outf = *out_n_frames; + + pa_assert(r); + pa_assert(input); + pa_assert(output); + pa_assert(out_n_frames); + + in = (int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); + out = (int16_t*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index); + + pa_assert_se(paspfx_resampler_process_interleaved_int(r->speex.state, in, &inf, out, &outf) == 0); + + pa_memblock_release(input->memblock); + pa_memblock_release(output->memblock); + + pa_assert(inf == in_n_frames); + *out_n_frames = outf; +} + +static void speex_update_rates(pa_resampler *r) { + pa_assert(r); + + if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) + pa_assert_se(paspfx_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0); + else { + pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); + pa_assert_se(paspfl_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0); + } +} + +static void speex_free(pa_resampler *r) { + pa_assert(r); + + if (!r->speex.state) + return; + + if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) + paspfx_resampler_destroy(r->speex.state); + else { + pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); + paspfl_resampler_destroy(r->speex.state); + } +} + +static int speex_init(pa_resampler *r) { + int q, err; + + pa_assert(r); + + r->impl_free = speex_free; + r->impl_update_rates = speex_update_rates; + + if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) { + q = r->resample_method - PA_RESAMPLER_SPEEX_FIXED_BASE; + + pa_log_info("Choosing speex quality setting %i.", q); + + if (!(r->speex.state = paspfx_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err))) + return -1; + + r->impl_resample = speex_resample_int; + } else { + pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); + q = r->resample_method - PA_RESAMPLER_SPEEX_FLOAT_BASE; + + pa_log_info("Choosing speex quality setting %i.", q); + + if (!(r->speex.state = paspfl_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err))) + return -1; + + r->impl_resample = speex_resample_float; + } + + return 0; } /* Trivial implementation */ -static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) { +static void trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { size_t fz; - unsigned n_frames; - struct impl_trivial *u; + unsigned o_index; + void *src, *dst; - assert(r); - assert(in); - assert(out); - assert(r->impl_data); + pa_assert(r); + pa_assert(input); + pa_assert(output); + pa_assert(out_n_frames); - u = r->impl_data; + fz = r->w_sz * r->o_ss.channels; - fz = r->i_fz; - assert(fz == r->o_fz); + src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index; + dst = (uint8_t*) pa_memblock_acquire(output->memblock) + output->index; - n_frames = in->length/fz; + for (o_index = 0;; o_index++, r->trivial.o_counter++) { + unsigned j; - if (r->i_ss.rate == r->o_ss.rate) { + j = ((r->trivial.o_counter * r->i_ss.rate) / r->o_ss.rate); + j = j > r->trivial.i_counter ? j - r->trivial.i_counter : 0; - /* In case there's no diefference in sample types, do nothing */ - *out = *in; - pa_memblock_ref(out->memblock); + if (j >= in_n_frames) + break; - u->o_counter += n_frames; - } else { - /* Do real resampling */ - size_t l; - unsigned o_index; + pa_assert(o_index * fz < pa_memblock_get_length(output->memblock)); - /* The length of the new memory block rounded up */ - l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz; - - out->index = 0; - out->memblock = pa_memblock_new(r->mempool, l); - - for (o_index = 0;; o_index++, u->o_counter++) { - unsigned j; - - j = (u->o_counter * r->i_ss.rate / r->o_ss.rate); - j = j > u->i_counter ? j - u->i_counter : 0; - - if (j >= n_frames) - break; - - assert(o_index*fz < out->memblock->length); - - memcpy((uint8_t*) out->memblock->data + fz*o_index, - (uint8_t*) in->memblock->data + in->index + fz*j, fz); - - } - - out->length = o_index*fz; + oil_memcpy((uint8_t*) dst + fz * o_index, + (uint8_t*) src + fz * j, fz); } - u->i_counter += n_frames; + pa_memblock_release(input->memblock); + pa_memblock_release(output->memblock); + + *out_n_frames = o_index; + + r->trivial.i_counter += in_n_frames; /* Normalize counters */ - while (u->i_counter >= r->i_ss.rate) { - u->i_counter -= r->i_ss.rate; - assert(u->o_counter >= r->o_ss.rate); - u->o_counter -= r->o_ss.rate; + while (r->trivial.i_counter >= r->i_ss.rate) { + pa_assert(r->trivial.o_counter >= r->o_ss.rate); + + r->trivial.i_counter -= r->i_ss.rate; + r->trivial.o_counter -= r->o_ss.rate; } } -static void trivial_free(pa_resampler *r) { - assert(r); +static void trivial_update_rates(pa_resampler *r) { + pa_assert(r); - pa_xfree(r->impl_data); -} - -static void trivial_update_input_rate(pa_resampler *r, uint32_t rate) { - struct impl_trivial *u; - - assert(r); - assert(rate > 0); - assert(r->impl_data); - - u = r->impl_data; - u->i_counter = 0; - u->o_counter = 0; + r->trivial.i_counter = 0; + r->trivial.o_counter = 0; } static int trivial_init(pa_resampler*r) { - struct impl_trivial *u; + pa_assert(r); - assert(r); - assert(r->i_ss.format == r->o_ss.format); - assert(r->i_ss.channels == r->o_ss.channels); + r->trivial.o_counter = r->trivial.i_counter = 0; - r->impl_data = u = pa_xnew(struct impl_trivial, 1); - u->o_counter = u->i_counter = 0; - - r->impl_run = trivial_run; - r->impl_free = trivial_free; - r->impl_update_input_rate = trivial_update_input_rate; + r->impl_resample = trivial_resample; + r->impl_update_rates = trivial_update_rates; + r->impl_free = NULL; return 0; } +/*** ffmpeg based implementation ***/ +static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { + unsigned used_frames = 0, c; + + pa_assert(r); + pa_assert(input); + pa_assert(output); + pa_assert(out_n_frames); + + for (c = 0; c < r->o_ss.channels; c++) { + unsigned u; + pa_memblock *b, *w; + int16_t *p, *t, *k, *q, *s; + int consumed_frames; + unsigned in, l; + + /* Allocate a new block */ + b = pa_memblock_new(r->mempool, r->ffmpeg.buf[c].length + in_n_frames * sizeof(int16_t)); + p = pa_memblock_acquire(b); + + /* Copy the remaining data into it */ + l = r->ffmpeg.buf[c].length; + if (r->ffmpeg.buf[c].memblock) { + t = (int16_t*) ((uint8_t*) pa_memblock_acquire(r->ffmpeg.buf[c].memblock) + r->ffmpeg.buf[c].index); + memcpy(p, t, l); + pa_memblock_release(r->ffmpeg.buf[c].memblock); + pa_memblock_unref(r->ffmpeg.buf[c].memblock); + pa_memchunk_reset(&r->ffmpeg.buf[c]); + } + + /* Now append the new data, splitting up channels */ + t = ((int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index)) + c; + k = (int16_t*) ((uint8_t*) p + l); + for (u = 0; u < in_n_frames; u++) { + *k = *t; + t += r->o_ss.channels; + k ++; + } + pa_memblock_release(input->memblock); + + /* Calculate the resulting number of frames */ + in = in_n_frames + l / sizeof(int16_t); + + /* Allocate buffer for the result */ + w = pa_memblock_new(r->mempool, *out_n_frames * sizeof(int16_t)); + q = pa_memblock_acquire(w); + + /* Now, resample */ + used_frames = av_resample(r->ffmpeg.state, + q, p, + &consumed_frames, + in, *out_n_frames, + c >= (unsigned) r->o_ss.channels-1); + + pa_memblock_release(b); + + /* Now store the remaining samples away */ + pa_assert(consumed_frames <= (int) in); + if (consumed_frames < (int) in) { + r->ffmpeg.buf[c].memblock = b; + r->ffmpeg.buf[c].index = consumed_frames * sizeof(int16_t); + r->ffmpeg.buf[c].length = (in - consumed_frames) * sizeof(int16_t); + } else + pa_memblock_unref(b); + + /* And place the results in the output buffer */ + s = (short*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index) + c; + for (u = 0; u < used_frames; u++) { + *s = *q; + q++; + s += r->o_ss.channels; + } + pa_memblock_release(output->memblock); + pa_memblock_release(w); + pa_memblock_unref(w); + } + + *out_n_frames = used_frames; +} + +static void ffmpeg_free(pa_resampler *r) { + unsigned c; + + pa_assert(r); + + if (r->ffmpeg.state) + av_resample_close(r->ffmpeg.state); + + for (c = 0; c < PA_ELEMENTSOF(r->ffmpeg.buf); c++) + if (r->ffmpeg.buf[c].memblock) + pa_memblock_unref(r->ffmpeg.buf[c].memblock); +} + +static int ffmpeg_init(pa_resampler *r) { + unsigned c; + + pa_assert(r); + + /* We could probably implement different quality levels by + * adjusting the filter parameters here. However, ffmpeg + * internally only uses these hardcoded values, so let's use them + * here for now as well until ffmpeg makes this configurable. */ + + if (!(r->ffmpeg.state = av_resample_init(r->o_ss.rate, r->i_ss.rate, 16, 10, 0, 0.8))) + return -1; + + r->impl_free = ffmpeg_free; + r->impl_resample = ffmpeg_resample; + + for (c = 0; c < PA_ELEMENTSOF(r->ffmpeg.buf); c++) + pa_memchunk_reset(&r->ffmpeg.buf[c]); + + return 0; +} + +/*** copy (noop) implementation ***/ + +static int copy_init(pa_resampler *r) { + pa_assert(r); + + pa_assert(r->o_ss.rate == r->i_ss.rate); + + r->impl_free = NULL; + r->impl_resample = NULL; + r->impl_update_rates = NULL; + + return 0; +} diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h index c283593d6..23e1acb76 100644 --- a/src/pulsecore/resampler.h +++ b/src/pulsecore/resampler.h @@ -24,8 +24,6 @@ USA. ***/ -#include - #include #include #include @@ -35,12 +33,19 @@ typedef struct pa_resampler pa_resampler; typedef enum pa_resample_method { PA_RESAMPLER_INVALID = -1, - PA_RESAMPLER_SRC_SINC_BEST_QUALITY = SRC_SINC_BEST_QUALITY, - PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY = SRC_SINC_MEDIUM_QUALITY, - PA_RESAMPLER_SRC_SINC_FASTEST = SRC_SINC_FASTEST, - PA_RESAMPLER_SRC_ZERO_ORDER_HOLD = SRC_ZERO_ORDER_HOLD, - PA_RESAMPLER_SRC_LINEAR = SRC_LINEAR, + PA_RESAMPLER_SRC_SINC_BEST_QUALITY = 0, /* = SRC_SINC_BEST_QUALITY */ + PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY = 1, /* = SRC_SINC_MEDIUM_QUALITY */ + PA_RESAMPLER_SRC_SINC_FASTEST = 2, /* = SRC_SINC_FASTEST */ + PA_RESAMPLER_SRC_ZERO_ORDER_HOLD = 3, /* = SRC_ZERO_ORDER_HOLD */ + PA_RESAMPLER_SRC_LINEAR = 4, /* = SRC_LINEAR */ PA_RESAMPLER_TRIVIAL, + PA_RESAMPLER_SPEEX_FLOAT_BASE, + PA_RESAMPLER_SPEEX_FLOAT_MAX = PA_RESAMPLER_SPEEX_FLOAT_BASE + 10, + PA_RESAMPLER_SPEEX_FIXED_BASE, + PA_RESAMPLER_SPEEX_FIXED_MAX = PA_RESAMPLER_SPEEX_FIXED_BASE + 10, + PA_RESAMPLER_FFMPEG, + PA_RESAMPLER_AUTO, /* automatic select based on sample format */ + PA_RESAMPLER_COPY, PA_RESAMPLER_MAX } pa_resample_method_t; @@ -50,19 +55,26 @@ pa_resampler* pa_resampler_new( const pa_channel_map *am, const pa_sample_spec *b, const pa_channel_map *bm, - pa_resample_method_t resample_method); + pa_resample_method_t resample_method, + int variable_rate); void pa_resampler_free(pa_resampler *r); /* Returns the size of an input memory block which is required to return the specified amount of output data */ size_t pa_resampler_request(pa_resampler *r, size_t out_length); +/* Returns the maximum size of input blocks we can process without needing bounce buffers larger than the mempool tile size. */ +size_t pa_resampler_max_block_size(pa_resampler *r); + /* Pass the specified memory chunk to the resampler and return the newly resampled data */ void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out); /* Change the input rate of the resampler object */ void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate); +/* Change the output rate of the resampler object */ +void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate); + /* Return the resampling method of the resampler object */ pa_resample_method_t pa_resampler_get_method(pa_resampler *r); @@ -72,4 +84,7 @@ pa_resample_method_t pa_parse_resample_method(const char *string); /* return a human readable string for the specified resampling method. Inverse of pa_parse_resample_method() */ const char *pa_resample_method_to_string(pa_resample_method_t m); +/* Return 1 when the specified resampling method is supported */ +int pa_resample_method_supported(pa_resample_method_t m); + #endif diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c new file mode 100644 index 000000000..07d776e49 --- /dev/null +++ b/src/pulsecore/rtclock.c @@ -0,0 +1,98 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include "rtclock.h" + +pa_usec_t pa_rtclock_age(const struct timeval *tv) { + struct timeval now; + pa_assert(tv); + + return pa_timeval_diff(pa_rtclock_get(&now), tv); +} + +struct timeval *pa_rtclock_get(struct timeval *tv) { +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + +#ifdef CLOCK_MONOTONIC + /* No locking or atomic ops for no_monotonic here */ + static pa_bool_t no_monotonic = FALSE; + + if (!no_monotonic) + if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) + no_monotonic = TRUE; + + if (no_monotonic) +#endif + pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); + + pa_assert(tv); + + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + + return tv; + +#else /* HAVE_CLOCK_GETTIME */ + + return pa_gettimeofday(tv); + +#endif +} + +pa_bool_t pa_rtclock_hrtimer(void) { +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + +#ifdef CLOCK_MONOTONIC + if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0) + return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000; +#endif + + pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0); + return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000; + +#else /* HAVE_CLOCK_GETTIME */ + + return FALSE; + +#endif +} + +pa_usec_t pa_rtclock_usec(void) { + struct timeval tv; + + return pa_timeval_load(pa_rtclock_get(&tv)); +} diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h new file mode 100644 index 000000000..f0360af34 --- /dev/null +++ b/src/pulsecore/rtclock.h @@ -0,0 +1,43 @@ +#ifndef foopulsertclockhfoo +#define foopulsertclockhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +struct timeval; + +/* Something like pulse/timeval.h but based on CLOCK_MONOTONIC */ + +struct timeval *pa_rtclock_get(struct timeval *ts); + +pa_usec_t pa_rtclock_usec(void); + +pa_usec_t pa_rtclock_age(const struct timeval *tv); +pa_bool_t pa_rtclock_hrtimer(void); + +/* timer with a resolution better than this are considered high-resolution */ +#define PA_HRTIMER_THRESHOLD_USEC 10 + +#endif diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c new file mode 100644 index 000000000..354c4c0e9 --- /dev/null +++ b/src/pulsecore/rtpoll.c @@ -0,0 +1,751 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#ifdef __linux__ +#include +#endif + +#ifdef HAVE_POLL_H +#include +#else +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "rtpoll.h" + +struct pa_rtpoll { + struct pollfd *pollfd, *pollfd2; + unsigned n_pollfd_alloc, n_pollfd_used; + + pa_bool_t timer_enabled; + struct timeval next_elapse; + pa_usec_t period; + + pa_bool_t scan_for_dead; + pa_bool_t running, installed, rebuild_needed, quit; + +#ifdef HAVE_PPOLL + int rtsig; + sigset_t sigset_unblocked; + timer_t timer; +#ifdef __linux__ + pa_bool_t dont_use_ppoll; +#endif +#endif + + PA_LLIST_HEAD(pa_rtpoll_item, items); +}; + +struct pa_rtpoll_item { + pa_rtpoll *rtpoll; + pa_bool_t dead; + + pa_rtpoll_priority_t priority; + + struct pollfd *pollfd; + unsigned n_pollfd; + + int (*work_cb)(pa_rtpoll_item *i); + int (*before_cb)(pa_rtpoll_item *i); + void (*after_cb)(pa_rtpoll_item *i); + void *userdata; + + PA_LLIST_FIELDS(pa_rtpoll_item); +}; + +PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree); + +static void signal_handler_noop(int s) { } + +pa_rtpoll *pa_rtpoll_new(void) { + pa_rtpoll *p; + + p = pa_xnew(pa_rtpoll, 1); + +#ifdef HAVE_PPOLL + +#ifdef __linux__ + /* ppoll is broken on Linux < 2.6.16 */ + p->dont_use_ppoll = FALSE; + + { + struct utsname u; + unsigned major, minor, micro; + + pa_assert_se(uname(&u) == 0); + + if (sscanf(u.release, "%u.%u.%u", &major, &minor, µ) != 3 || + (major < 2) || + (major == 2 && minor < 6) || + (major == 2 && minor == 6 && micro < 16)) + + p->dont_use_ppoll = TRUE; + } + +#endif + + p->rtsig = -1; + sigemptyset(&p->sigset_unblocked); + p->timer = (timer_t) -1; + +#endif + + p->n_pollfd_alloc = 32; + p->pollfd = pa_xnew(struct pollfd, p->n_pollfd_alloc); + p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc); + p->n_pollfd_used = 0; + + p->period = 0; + memset(&p->next_elapse, 0, sizeof(p->next_elapse)); + p->timer_enabled = FALSE; + + p->running = FALSE; + p->installed = FALSE; + p->scan_for_dead = FALSE; + p->rebuild_needed = FALSE; + p->quit = FALSE; + + PA_LLIST_HEAD_INIT(pa_rtpoll_item, p->items); + + return p; +} + +void pa_rtpoll_install(pa_rtpoll *p) { + pa_assert(p); + pa_assert(!p->installed); + + p->installed = 1; + +#ifdef HAVE_PPOLL + if (p->dont_use_ppoll) + return; + + if ((p->rtsig = pa_rtsig_get_for_thread()) < 0) { + pa_log_warn("Failed to reserve POSIX realtime signal."); + return; + } + + pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p->rtsig)); + + { + sigset_t ss; + struct sigaction sa; + + pa_assert_se(sigemptyset(&ss) == 0); + pa_assert_se(sigaddset(&ss, p->rtsig) == 0); + pa_assert_se(pthread_sigmask(SIG_BLOCK, &ss, &p->sigset_unblocked) == 0); + pa_assert_se(sigdelset(&p->sigset_unblocked, p->rtsig) == 0); + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handler_noop; + pa_assert_se(sigemptyset(&sa.sa_mask) == 0); + + pa_assert_se(sigaction(p->rtsig, &sa, NULL) == 0); + + /* We never reset the signal handler. Why should we? */ + } + +#endif +} + +static void rtpoll_rebuild(pa_rtpoll *p) { + + struct pollfd *e, *t; + pa_rtpoll_item *i; + int ra = 0; + + pa_assert(p); + + p->rebuild_needed = FALSE; + + if (p->n_pollfd_used > p->n_pollfd_alloc) { + /* Hmm, we have to allocate some more space */ + p->n_pollfd_alloc = p->n_pollfd_used * 2; + p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd)); + ra = 1; + } + + e = p->pollfd2; + + for (i = p->items; i; i = i->next) { + + if (i->n_pollfd > 0) { + size_t l = i->n_pollfd * sizeof(struct pollfd); + + if (i->pollfd) + memcpy(e, i->pollfd, l); + else + memset(e, 0, l); + + i->pollfd = e; + } else + i->pollfd = NULL; + + e += i->n_pollfd; + } + + pa_assert((unsigned) (e - p->pollfd2) == p->n_pollfd_used); + t = p->pollfd; + p->pollfd = p->pollfd2; + p->pollfd2 = t; + + if (ra) + p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd)); + +} + +static void rtpoll_item_destroy(pa_rtpoll_item *i) { + pa_rtpoll *p; + + pa_assert(i); + + p = i->rtpoll; + + PA_LLIST_REMOVE(pa_rtpoll_item, p->items, i); + + p->n_pollfd_used -= i->n_pollfd; + + if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0) + pa_xfree(i); + + p->rebuild_needed = TRUE; +} + +void pa_rtpoll_free(pa_rtpoll *p) { + pa_assert(p); + + while (p->items) + rtpoll_item_destroy(p->items); + + pa_xfree(p->pollfd); + pa_xfree(p->pollfd2); + +#ifdef HAVE_PPOLL + if (p->timer != (timer_t) -1) + timer_delete(p->timer); +#endif + + pa_xfree(p); +} + +static void reset_revents(pa_rtpoll_item *i) { + struct pollfd *f; + unsigned n; + + pa_assert(i); + + if (!(f = pa_rtpoll_item_get_pollfd(i, &n))) + return; + + for (; n > 0; n--) + f[n-1].revents = 0; +} + +static void reset_all_revents(pa_rtpoll *p) { + pa_rtpoll_item *i; + + pa_assert(p); + + for (i = p->items; i; i = i->next) { + + if (i->dead) + continue; + + reset_revents(i); + } +} + +int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) { + pa_rtpoll_item *i; + int r = 0; + struct timeval timeout; + + pa_assert(p); + pa_assert(!p->running); + pa_assert(p->installed); + + p->running = TRUE; + + /* First, let's do some work */ + for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) { + int k; + + if (i->dead) + continue; + + if (!i->work_cb) + continue; + + if (p->quit) + goto finish; + + if ((k = i->work_cb(i)) != 0) { + if (k < 0) + r = k; + + goto finish; + } + } + + /* Now let's prepare for entering the sleep */ + for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) { + int k = 0; + + if (i->dead) + continue; + + if (!i->before_cb) + continue; + + if (p->quit || (k = i->before_cb(i)) != 0) { + + /* Hmm, this one doesn't let us enter the poll, so rewind everything */ + + for (i = i->prev; i; i = i->prev) { + + if (i->dead) + continue; + + if (!i->after_cb) + continue; + + i->after_cb(i); + } + + if (k < 0) + r = k; + + goto finish; + } + } + + if (p->rebuild_needed) + rtpoll_rebuild(p); + + /* Calculate timeout */ + if (!wait || p->quit) { + timeout.tv_sec = 0; + timeout.tv_usec = 0; + } else if (p->timer_enabled) { + struct timeval now; + pa_rtclock_get(&now); + + memset(&timeout, 0, sizeof(timeout)); + if (pa_timeval_cmp(&p->next_elapse, &now) > 0) + pa_timeval_add(&timeout, pa_timeval_diff(&p->next_elapse, &now)); + } + + /* OK, now let's sleep */ +#ifdef HAVE_PPOLL + +#ifdef __linux__ + if (!p->dont_use_ppoll) +#endif + { + struct timespec ts; + ts.tv_sec = timeout.tv_sec; + ts.tv_nsec = timeout.tv_usec * 1000; + r = ppoll(p->pollfd, p->n_pollfd_used, p->timer_enabled ? &ts : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked); + } +#ifdef __linux__ + else +#endif + +#endif + r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled ? (timeout.tv_sec*1000) + (timeout.tv_usec / 1000) : -1); + + if (r < 0) { + if (errno == EAGAIN || errno == EINTR) + r = 0; + else + pa_log_error("poll(): %s", pa_cstrerror(errno)); + + reset_all_revents(p); + } + + if (p->timer_enabled) { + if (p->period > 0) { + struct timeval now; + pa_rtclock_get(&now); + + pa_timeval_add(&p->next_elapse, p->period); + + /* Guarantee that the next timeout will happen in the future */ + if (pa_timeval_cmp(&p->next_elapse, &now) < 0) + pa_timeval_add(&p->next_elapse, (pa_timeval_diff(&now, &p->next_elapse) / p->period + 1) * p->period); + + } else + p->timer_enabled = FALSE; + } + + /* Let's tell everyone that we left the sleep */ + for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) { + + if (i->dead) + continue; + + if (!i->after_cb) + continue; + + i->after_cb(i); + } + +finish: + + p->running = FALSE; + + if (p->scan_for_dead) { + pa_rtpoll_item *n; + + p->scan_for_dead = FALSE; + + for (i = p->items; i; i = n) { + n = i->next; + + if (i->dead) + rtpoll_item_destroy(i); + } + } + + return r < 0 ? r : !p->quit; +} + +static void update_timer(pa_rtpoll *p) { + pa_assert(p); + +#ifdef HAVE_PPOLL + +#ifdef __linux__ + if (!p->dont_use_ppoll) { +#endif + + if (p->timer == (timer_t) -1) { + struct sigevent se; + + memset(&se, 0, sizeof(se)); + se.sigev_notify = SIGEV_SIGNAL; + se.sigev_signo = p->rtsig; + + if (timer_create(CLOCK_MONOTONIC, &se, &p->timer) < 0) + if (timer_create(CLOCK_REALTIME, &se, &p->timer) < 0) { + pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno)); + p->timer = (timer_t) -1; + } + } + + if (p->timer != (timer_t) -1) { + struct itimerspec its; + memset(&its, 0, sizeof(its)); + + if (p->timer_enabled) { + its.it_value.tv_sec = p->next_elapse.tv_sec; + its.it_value.tv_nsec = p->next_elapse.tv_usec*1000; + + /* Make sure that 0,0 is not understood as + * "disarming" */ + if (its.it_value.tv_sec == 0) + its.it_value.tv_nsec = 1; + + if (p->period > 0) { + struct timeval tv; + pa_timeval_store(&tv, p->period); + its.it_interval.tv_sec = tv.tv_sec; + its.it_interval.tv_nsec = tv.tv_usec*1000; + } + } + + pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0); + } + +#ifdef __linux__ + } +#endif + +#endif +} + +void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timeval *ts) { + pa_assert(p); + pa_assert(ts); + + p->next_elapse = *ts; + p->period = 0; + p->timer_enabled = TRUE; + + update_timer(p); +} + +void pa_rtpoll_set_timer_periodic(pa_rtpoll *p, pa_usec_t usec) { + pa_assert(p); + + p->period = usec; + pa_rtclock_get(&p->next_elapse); + pa_timeval_add(&p->next_elapse, usec); + p->timer_enabled = TRUE; + + update_timer(p); +} + +void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) { + pa_assert(p); + + p->period = 0; + pa_rtclock_get(&p->next_elapse); + pa_timeval_add(&p->next_elapse, usec); + p->timer_enabled = TRUE; + + update_timer(p); +} + +void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) { + pa_assert(p); + + p->period = 0; + memset(&p->next_elapse, 0, sizeof(p->next_elapse)); + p->timer_enabled = FALSE; + + update_timer(p); +} + +pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) { + pa_rtpoll_item *i, *j, *l = NULL; + + pa_assert(p); + + if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items)))) + i = pa_xnew(pa_rtpoll_item, 1); + + i->rtpoll = p; + i->dead = FALSE; + i->n_pollfd = n_fds; + i->pollfd = NULL; + i->priority = prio; + + i->userdata = NULL; + i->before_cb = NULL; + i->after_cb = NULL; + i->work_cb = NULL; + + for (j = p->items; j; j = j->next) { + if (prio <= j->priority) + break; + + l = j; + } + + PA_LLIST_INSERT_AFTER(pa_rtpoll_item, p->items, j ? j->prev : l, i); + + if (n_fds > 0) { + p->rebuild_needed = 1; + p->n_pollfd_used += n_fds; + } + + return i; +} + +void pa_rtpoll_item_free(pa_rtpoll_item *i) { + pa_assert(i); + + if (i->rtpoll->running) { + i->dead = TRUE; + i->rtpoll->scan_for_dead = TRUE; + return; + } + + rtpoll_item_destroy(i); +} + +struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) { + pa_assert(i); + + if (i->n_pollfd > 0) + if (i->rtpoll->rebuild_needed) + rtpoll_rebuild(i->rtpoll); + + if (n_fds) + *n_fds = i->n_pollfd; + + return i->pollfd; +} + +void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)) { + pa_assert(i); + pa_assert(i->priority < PA_RTPOLL_NEVER); + + i->before_cb = before_cb; +} + +void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i)) { + pa_assert(i); + pa_assert(i->priority < PA_RTPOLL_NEVER); + + i->after_cb = after_cb; +} + +void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i)) { + pa_assert(i); + pa_assert(i->priority < PA_RTPOLL_NEVER); + + i->work_cb = work_cb; +} + +void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata) { + pa_assert(i); + + i->userdata = userdata; +} + +void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i) { + pa_assert(i); + + return i->userdata; +} + +static int fdsem_before(pa_rtpoll_item *i) { + + if (pa_fdsem_before_poll(i->userdata) < 0) + return 1; /* 1 means immediate restart of the loop */ + + return 0; +} + +static void fdsem_after(pa_rtpoll_item *i) { + pa_assert(i); + + pa_assert((i->pollfd[0].revents & ~POLLIN) == 0); + pa_fdsem_after_poll(i->userdata); +} + +pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *f) { + pa_rtpoll_item *i; + struct pollfd *pollfd; + + pa_assert(p); + pa_assert(f); + + i = pa_rtpoll_item_new(p, prio, 1); + + pollfd = pa_rtpoll_item_get_pollfd(i, NULL); + + pollfd->fd = pa_fdsem_get(f); + pollfd->events = POLLIN; + + i->before_cb = fdsem_before; + i->after_cb = fdsem_after; + i->userdata = f; + + return i; +} + +static int asyncmsgq_before(pa_rtpoll_item *i) { + pa_assert(i); + + if (pa_asyncmsgq_before_poll(i->userdata) < 0) + return 1; /* 1 means immediate restart of the loop */ + + return 0; +} + +static void asyncmsgq_after(pa_rtpoll_item *i) { + pa_assert(i); + + pa_assert((i->pollfd[0].revents & ~POLLIN) == 0); + pa_asyncmsgq_after_poll(i->userdata); +} + +static int asyncmsgq_work(pa_rtpoll_item *i) { + pa_msgobject *object; + int code; + void *data; + pa_memchunk chunk; + int64_t offset; + + pa_assert(i); + + if (pa_asyncmsgq_get(i->userdata, &object, &code, &data, &offset, &chunk, 0) == 0) { + int ret; + + if (!object && code == PA_MESSAGE_SHUTDOWN) { + pa_asyncmsgq_done(i->userdata, 0); + pa_rtpoll_quit(i->rtpoll); + return 1; + } + + ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk); + pa_asyncmsgq_done(i->userdata, ret); + return 1; + } + + return 0; +} + +pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) { + pa_rtpoll_item *i; + struct pollfd *pollfd; + + pa_assert(p); + pa_assert(q); + + i = pa_rtpoll_item_new(p, prio, 1); + + pollfd = pa_rtpoll_item_get_pollfd(i, NULL); + pollfd->fd = pa_asyncmsgq_get_fd(q); + pollfd->events = POLLIN; + + i->before_cb = asyncmsgq_before; + i->after_cb = asyncmsgq_after; + i->work_cb = asyncmsgq_work; + i->userdata = q; + + return i; +} + +void pa_rtpoll_quit(pa_rtpoll *p) { + pa_assert(p); + + p->quit = TRUE; +} diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h new file mode 100644 index 000000000..02f5c7c24 --- /dev/null +++ b/src/pulsecore/rtpoll.h @@ -0,0 +1,116 @@ +#ifndef foopulsertpollhfoo +#define foopulsertpollhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +#include +#include +#include +#include + +/* An implementation of a "real-time" poll loop. Basically, this is + * yet another wrapper around poll(). However it has certain + * advantages over pa_mainloop and suchlike: + * + * 1) It uses timer_create() and POSIX real time signals to guarantee + * optimal high-resolution timing. Starting with Linux 2.6.21 hrtimers + * are available, and since right now only nanosleep() and the POSIX + * clock and timer interfaces have been ported to hrtimers (and not + * ppoll/pselect!) we have to combine ppoll() with timer_create(). The + * fact that POSIX timers and POSIX rt signals are used internally is + * completely hidden. + * + * 2) It allows raw access to the pollfd data to users + * + * 3) It allows arbitrary functions to be run before entering the + * actual poll() and after it. + * + * Only a single interval timer is supported..*/ + +typedef struct pa_rtpoll pa_rtpoll; +typedef struct pa_rtpoll_item pa_rtpoll_item; + +typedef enum pa_rtpoll_priority { + PA_RTPOLL_EARLY = -100, /* For veeery important stuff, like handling control messages */ + PA_RTPOLL_NORMAL = 0, /* For normal stuff */ + PA_RTPOLL_LATE = +100, /* For housekeeping */ + PA_RTPOLL_NEVER = INT_MAX, /* For stuff that doesn't register any callbacks, but only fds to listen on */ +} pa_rtpoll_priority_t; + +pa_rtpoll *pa_rtpoll_new(void); +void pa_rtpoll_free(pa_rtpoll *p); + +/* Install the rtpoll in the current thread */ +void pa_rtpoll_install(pa_rtpoll *p); + +/* Sleep on the rtpoll until the time event, or any of the fd events + * is triggered. If "wait" is 0 we don't sleep but only update the + * struct pollfd. Returns negative on error, positive if the loop + * should continue to run, 0 when the loop should be terminated + * cleanly. */ +int pa_rtpoll_run(pa_rtpoll *f, pa_bool_t wait); + +void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timeval *ts); +void pa_rtpoll_set_timer_periodic(pa_rtpoll *p, pa_usec_t usec); +void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec); +void pa_rtpoll_set_timer_disabled(pa_rtpoll *p); + +/* A new fd wakeup item for pa_rtpoll */ +pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds); +void pa_rtpoll_item_free(pa_rtpoll_item *i); + +/* Please note that this pointer might change on every call and when + * pa_rtpoll_run() is called. Hence: call this immediately before + * using the pointer and don't save the result anywhere */ +struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds); + +/* Set the callback that shall be called when there's time to do some work: If the + * callback returns a value > 0, the poll is skipped and the next + * iteraton of the loop will start immediately. */ +void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i)); + +/* Set the callback that shall be called immediately before entering + * the sleeping poll: If the callback returns a value > 0, the poll is + * skipped and the next iteraton of the loop will start + * immediately.. */ +void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)); + +/* Set the callback that shall be called immediately after having + * entered the sleeping poll */ +void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i)); + +void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata); +void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i); + +pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *s); +pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q); + +/* Requests the loop to exit. Will cause the next iteration of + * pa_rtpoll_run() to return 0 */ +void pa_rtpoll_quit(pa_rtpoll *p); + +#endif diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c new file mode 100644 index 000000000..bfc49c88e --- /dev/null +++ b/src/pulsecore/rtsig.c @@ -0,0 +1,133 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include + +#include "rtsig.h" + +#ifdef SIGRTMIN + +static void _free_rtsig(void *p) { + pa_rtsig_put(PA_PTR_TO_INT(p)); +} + +PA_STATIC_FLIST_DECLARE(rtsig_flist, pa_make_power_of_two(SIGRTMAX-SIGRTMIN+1), NULL); +PA_STATIC_TLS_DECLARE(rtsig_tls, _free_rtsig); + +static pa_atomic_t rtsig_current = PA_ATOMIC_INIT(-1); + +static int rtsig_start = -1, rtsig_end = -1; + +int pa_rtsig_get(void) { + void *p; + int sig; + + if ((p = pa_flist_pop(PA_STATIC_FLIST_GET(rtsig_flist)))) + return PA_PTR_TO_INT(p); + + sig = pa_atomic_dec(&rtsig_current); + + pa_assert(sig <= SIGRTMAX); + pa_assert(sig <= rtsig_end); + + if (sig < rtsig_start) { + pa_atomic_inc(&rtsig_current); + return -1; + } + + return sig; +} + +int pa_rtsig_get_for_thread(void) { + int sig; + void *p; + + if ((p = PA_STATIC_TLS_GET(rtsig_tls))) + return PA_PTR_TO_INT(p); + + if ((sig = pa_rtsig_get()) < 0) + return -1; + + PA_STATIC_TLS_SET(rtsig_tls, PA_INT_TO_PTR(sig)); + return sig; +} + +void pa_rtsig_put(int sig) { + pa_assert(sig >= rtsig_start); + pa_assert(sig <= rtsig_end); + + pa_assert_se(pa_flist_push(PA_STATIC_FLIST_GET(rtsig_flist), PA_INT_TO_PTR(sig)) >= 0); +} + +void pa_rtsig_configure(int start, int end) { + int s; + sigset_t ss; + + pa_assert(pa_atomic_load(&rtsig_current) == -1); + + pa_assert(SIGRTMIN <= start); + pa_assert(start <= end); + pa_assert(end <= SIGRTMAX); + + rtsig_start = start; + rtsig_end = end; + + sigemptyset(&ss); + + for (s = rtsig_start; s <= rtsig_end; s++) + pa_assert_se(sigaddset(&ss, s) == 0); + + pa_assert(pthread_sigmask(SIG_BLOCK, &ss, NULL) == 0); + + /* We allocate starting from the end */ + pa_atomic_store(&rtsig_current, rtsig_end); +} + +#else /* SIGRTMIN */ + +int pa_rtsig_get(void) { + return -1; +} + +int pa_rtsig_get_for_thread(void) { + return -1; +} + +void pa_rtsig_put(int sig) { +} + +void pa_rtsig_configure(int start, int end) { +} + +#endif /* SIGRTMIN */ diff --git a/src/pulsecore/rtsig.h b/src/pulsecore/rtsig.h new file mode 100644 index 000000000..7830d272a --- /dev/null +++ b/src/pulsecore/rtsig.h @@ -0,0 +1,41 @@ +#ifndef foopulsertsighfoo +#define foopulsertsighfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* Return the next unused POSIX Realtime signals */ +int pa_rtsig_get(void); + +/* If not called before in the current thread, return the next unused + * rtsig, and install it in a TLS region and give it up automatically + * when the thread shuts down */ +int pa_rtsig_get_for_thread(void); + +/* Give an rtsig back. */ +void pa_rtsig_put(int sig); + +/* Block all RT signals */ +void pa_rtsig_configure(int start, int end); + +#endif diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index a99714080..21771302a 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -28,53 +28,71 @@ #include #include -#include #include #include +#include #include +#include #include "sample-util.h" #include "endianmacros.h" -#define PA_SILENCE_MAX (1024*1024*1) +#define PA_SILENCE_MAX (PA_PAGE_SIZE*16) pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spec, size_t length) { size_t fs; - assert(pool); - assert(spec); + pa_assert(pool); + pa_assert(spec); - if (length == 0) + if (length <= 0) length = pa_bytes_per_second(spec)/20; /* 50 ms */ if (length > PA_SILENCE_MAX) length = PA_SILENCE_MAX; fs = pa_frame_size(spec); - length = ((PA_SILENCE_MAX+fs-1) / fs) * fs; + + length = (length+fs-1)/fs; if (length <= 0) - length = fs; + length = 1; + + length *= fs; return pa_silence_memblock(pa_memblock_new(pool, length), spec); } pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { - assert(b && b->data && spec); - pa_silence_memory(b->data, b->length, spec); + void *data; + + pa_assert(b); + pa_assert(spec); + + data = pa_memblock_acquire(b); + pa_silence_memory(data, pa_memblock_get_length(b), spec); + pa_memblock_release(b); return b; } void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) { - assert(c && c->memblock && c->memblock->data && spec && c->length); + void *data; - pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec); + pa_assert(c); + pa_assert(c->memblock); + pa_assert(spec); + + data = pa_memblock_acquire(c->memblock); + pa_silence_memory((uint8_t*) data+c->index, c->length, spec); + pa_memblock_release(c->memblock); } void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { uint8_t c = 0; - assert(p && length && spec); + pa_assert(p); + pa_assert(length > 0); + pa_assert(spec); switch (spec->format) { case PA_SAMPLE_U8: @@ -87,37 +105,51 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { c = 0; break; case PA_SAMPLE_ALAW: + c = 0xd5; + break; case PA_SAMPLE_ULAW: - c = 80; + c = 0xff; break; default: - assert(0); + pa_assert_not_reached(); } memset(p, c, length); } size_t pa_mix( - const pa_mix_info streams[], - unsigned nstreams, - void *data, - size_t length, - const pa_sample_spec *spec, - const pa_cvolume *volume, - int mute) { + pa_mix_info streams[], + unsigned nstreams, + void *data, + size_t length, + const pa_sample_spec *spec, + const pa_cvolume *volume, + int mute) { - assert(streams && data && length && spec); + pa_cvolume full_volume; + size_t d = 0; + unsigned k; + + pa_assert(streams); + pa_assert(data); + pa_assert(length); + pa_assert(spec); + + if (!volume) + volume = pa_cvolume_reset(&full_volume, spec->channels); + + for (k = 0; k < nstreams; k++) + streams[k].internal = pa_memblock_acquire(streams[k].chunk.memblock); switch (spec->format) { case PA_SAMPLE_S16NE:{ - size_t d; unsigned channel = 0; for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; if (d >= length) - return d; + goto finish; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -127,12 +159,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - return d; + goto finish; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); + v = *((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d)); if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); @@ -144,28 +176,27 @@ size_t pa_mix( if (volume->values[channel] != PA_VOLUME_NORM) sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); - if (sum < -0x8000) sum = -0x8000; - if (sum > 0x7FFF) sum = 0x7FFF; - + sum = CLAMP(sum, -0x8000, 0x7FFF); } - *((int16_t*) data) = sum; + *((int16_t*) data) = (int16_t) sum; data = (uint8_t*) data + sizeof(int16_t); if (++channel >= spec->channels) channel = 0; } + + break; } case PA_SAMPLE_S16RE:{ - size_t d; unsigned channel = 0; for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; if (d >= length) - return d; + goto finish; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -175,12 +206,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - return d; + goto finish; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d))); + v = PA_INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d))); if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); @@ -192,28 +223,27 @@ size_t pa_mix( if (volume->values[channel] != PA_VOLUME_NORM) sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); - if (sum < -0x8000) sum = -0x8000; - if (sum > 0x7FFF) sum = 0x7FFF; - + sum = CLAMP(sum, -0x8000, 0x7FFF); } - *((int16_t*) data) = INT16_SWAP(sum); + *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum); data = (uint8_t*) data + sizeof(int16_t); if (++channel >= spec->channels) channel = 0; } + + break; } case PA_SAMPLE_U8: { - size_t d; unsigned channel = 0; for (d = 0;; d ++) { int32_t sum = 0; if (d >= length) - return d; + goto finish; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -223,12 +253,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - return d; + goto finish; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80; + v = (int32_t) *((uint8_t*) streams[i].internal + streams[i].chunk.index + d) - 0x80; if (cvolume != PA_VOLUME_NORM) v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); @@ -240,9 +270,7 @@ size_t pa_mix( if (volume->values[channel] != PA_VOLUME_NORM) sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); - if (sum < -0x80) sum = -0x80; - if (sum > 0x7F) sum = 0x7F; - + sum = CLAMP(sum, -0x80, 0x7F); } *((uint8_t*) data) = (uint8_t) (sum + 0x80); @@ -251,17 +279,18 @@ size_t pa_mix( if (++channel >= spec->channels) channel = 0; } + + break; } case PA_SAMPLE_FLOAT32NE: { - size_t d; unsigned channel = 0; for (d = 0;; d += sizeof(float)) { float sum = 0; if (d >= length) - return d; + goto finish; if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { unsigned i; @@ -271,12 +300,12 @@ size_t pa_mix( pa_volume_t cvolume = streams[i].volume.values[channel]; if (d >= streams[i].chunk.length) - return d; + goto finish; if (cvolume == PA_VOLUME_MUTED) v = 0; else { - v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)); + v = *((float*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d)); if (cvolume != PA_VOLUME_NORM) v *= pa_sw_volume_to_linear(cvolume); @@ -295,18 +324,35 @@ size_t pa_mix( if (++channel >= spec->channels) channel = 0; } + + break; } default: pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); abort(); } + +finish: + + for (k = 0; k < nstreams; k++) + pa_memblock_release(streams[k].chunk.memblock); + + return d; } -void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvolume *volume) { - assert(c && spec && (c->length % pa_frame_size(spec) == 0)); - assert(volume); +void pa_volume_memchunk( + pa_memchunk*c, + const pa_sample_spec *spec, + const pa_cvolume *volume) { + + void *ptr; + + pa_assert(c); + pa_assert(spec); + pa_assert(c->length % pa_frame_size(spec) == 0); + pa_assert(volume); if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM)) return; @@ -316,24 +362,25 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol return; } + ptr = pa_memblock_acquire(c->memblock); + switch (spec->format) { + case PA_SAMPLE_S16NE: { int16_t *d; size_t n; unsigned channel; - double linear[PA_CHANNELS_MAX]; + int32_t linear[PA_CHANNELS_MAX]; for (channel = 0; channel < spec->channels; channel++) - linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); + linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); - for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { - int32_t t = (int32_t)(*d); - - t = (int32_t) (t * linear[channel]); - - if (t < -0x8000) t = -0x8000; - if (t > 0x7FFF) t = 0x7FFF; + for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + int32_t t; + t = (int32_t)(*d); + t = (t * linear[channel]) / 0x10000; + t = CLAMP(t, -0x8000, 0x7FFF); *d = (int16_t) t; if (++channel >= spec->channels) @@ -346,20 +393,18 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol int16_t *d; size_t n; unsigned channel; - double linear[PA_CHANNELS_MAX]; + int32_t linear[PA_CHANNELS_MAX]; for (channel = 0; channel < spec->channels; channel++) - linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); + linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); - for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { - int32_t t = (int32_t)(INT16_SWAP(*d)); + for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + int32_t t; - t = (int32_t) (t * linear[channel]); - - if (t < -0x8000) t = -0x8000; - if (t > 0x7FFF) t = 0x7FFF; - - *d = INT16_SWAP((int16_t) t); + t = (int32_t)(PA_INT16_SWAP(*d)); + t = (t * linear[channel]) / 0x10000; + t = CLAMP(t, -0x8000, 0x7FFF); + *d = PA_INT16_SWAP((int16_t) t); if (++channel >= spec->channels) channel = 0; @@ -371,16 +416,18 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol case PA_SAMPLE_U8: { uint8_t *d; size_t n; - unsigned channel = 0; + unsigned channel; + int32_t linear[PA_CHANNELS_MAX]; - for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) { - int32_t t = (int32_t) *d - 0x80; + for (channel = 0; channel < spec->channels; channel++) + linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); - t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel])); - - if (t < -0x80) t = -0x80; - if (t > 0x7F) t = 0x7F; + for (channel = 0, d = (uint8_t*) ptr + c->index, n = c->length; n > 0; d++, n--) { + int32_t t; + t = (int32_t) *d - 0x80; + t = (t * linear[channel]) / 0x10000; + t = CLAMP(t, -0x80, 0x7F); *d = (uint8_t) (t + 0x80); if (++channel >= spec->channels) @@ -395,7 +442,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol unsigned n; unsigned channel; - d = (float*) ((uint8_t*) c->memblock->data + c->index); + d = (float*) ((uint8_t*) ptr + c->index); skip = spec->channels * sizeof(float); n = c->length/sizeof(float)/spec->channels; @@ -406,7 +453,6 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol continue; v = (float) pa_sw_volume_to_linear(volume->values[channel]); - t = d + channel; oil_scalarmult_f32(t, skip, t, skip, &v, n); } @@ -414,9 +460,85 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol } default: - pa_log_error("ERROR: Unable to change volume of format %s.", - pa_sample_format_to_string(spec->format)); - abort(); + pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec->format)); + /* If we cannot change the volume, we just don't do it */ + } + + pa_memblock_release(c->memblock); +} + +size_t pa_frame_align(size_t l, const pa_sample_spec *ss) { + size_t fs; + + pa_assert(ss); + + fs = pa_frame_size(ss); + + return (l/fs) * fs; +} + +int pa_frame_aligned(size_t l, const pa_sample_spec *ss) { + size_t fs; + + pa_assert(ss); + + fs = pa_frame_size(ss); + + return l % fs == 0; +} + +void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n) { + unsigned c; + size_t fs; + + pa_assert(src); + pa_assert(channels > 0); + pa_assert(dst); + pa_assert(ss > 0); + pa_assert(n > 0); + + fs = ss * channels; + + for (c = 0; c < channels; c++) { + unsigned j; + void *d; + const void *s; + + s = src[c]; + d = (uint8_t*) dst + c * ss; + + for (j = 0; j < n; j ++) { + oil_memcpy(d, s, ss); + s = (uint8_t*) s + ss; + d = (uint8_t*) d + fs; + } } } +void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n) { + size_t fs; + unsigned c; + + pa_assert(src); + pa_assert(dst); + pa_assert(channels > 0); + pa_assert(ss > 0); + pa_assert(n > 0); + + fs = ss * channels; + + for (c = 0; c < channels; c++) { + unsigned j; + const void *s; + void *d; + + s = (uint8_t*) src + c * ss; + d = dst[c]; + + for (j = 0; j < n; j ++) { + oil_memcpy(d, s, ss); + s = (uint8_t*) s + fs; + d = (uint8_t*) d + ss; + } + } +} diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h index 3ff065ab2..0a39d5ca1 100644 --- a/src/pulsecore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -39,10 +39,11 @@ typedef struct pa_mix_info { pa_memchunk chunk; pa_cvolume volume; void *userdata; + void *internal; /* Used internally by pa_mix(), should not be initialised when calling pa_mix() */ } pa_mix_info; size_t pa_mix( - const pa_mix_info channels[], + pa_mix_info channels[], unsigned nchannels, void *data, size_t length, @@ -55,4 +56,11 @@ void pa_volume_memchunk( const pa_sample_spec *spec, const pa_cvolume *volume); +size_t pa_frame_align(size_t l, const pa_sample_spec *ss) PA_GCC_PURE; + +int pa_frame_aligned(size_t l, const pa_sample_spec *ss) PA_GCC_PURE; + +void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n); +void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n); + #endif diff --git a/src/pulsecore/sconv-s16be.c b/src/pulsecore/sconv-s16be.c index c530e79b8..f74d02829 100644 --- a/src/pulsecore/sconv-s16be.c +++ b/src/pulsecore/sconv-s16be.c @@ -27,12 +27,15 @@ #include "endianmacros.h" -#define INT16_FROM INT16_FROM_BE -#define INT16_TO INT16_TO_BE +#define INT16_FROM PA_INT16_FROM_BE +#define INT16_TO PA_INT16_TO_BE #define pa_sconv_s16le_to_float32ne pa_sconv_s16be_to_float32ne #define pa_sconv_s16le_from_float32ne pa_sconv_s16be_from_float32ne +#define pa_sconv_s16le_to_float32re pa_sconv_s16be_to_float32re +#define pa_sconv_s16le_from_float32re pa_sconv_s16be_from_float32re + #ifdef WORDS_BIGENDIAN #define SWAP_WORDS 0 #else diff --git a/src/pulsecore/sconv-s16be.h b/src/pulsecore/sconv-s16be.h index 6b736f69b..ad034489e 100644 --- a/src/pulsecore/sconv-s16be.h +++ b/src/pulsecore/sconv-s16be.h @@ -24,7 +24,18 @@ USA. ***/ -void pa_sconv_s16be_to_float32ne(unsigned n, const void *a, float *b); -void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, void *b); +#include + +void pa_sconv_s16be_to_float32ne(unsigned n, const int16_t *a, float *b); +void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, int16_t *b); +void pa_sconv_s16be_to_float32re(unsigned n, const int16_t *a, float *b); +void pa_sconv_s16be_from_float32re(unsigned n, const float *a, int16_t *b); + +#ifdef WORDS_BIGENDIAN +#define pa_sconv_float32be_to_s16ne pa_sconv_s16be_from_float32ne +#define pa_sconv_float32be_from_s16ne pa_sconv_s16be_to_float32ne +#define pa_sconv_float32le_to_s16ne pa_sconv_s16be_from_float32re +#define pa_sconv_float32le_from_s16ne pa_sconv_s16be_to_float32re +#endif #endif diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c index 5f45ef66d..6925052cf 100644 --- a/src/pulsecore/sconv-s16le.c +++ b/src/pulsecore/sconv-s16le.c @@ -25,12 +25,12 @@ #include #endif -#include #include #include #include +#include #include #include "endianmacros.h" @@ -38,11 +38,11 @@ #include "sconv-s16le.h" #ifndef INT16_FROM -#define INT16_FROM INT16_FROM_LE +#define INT16_FROM PA_INT16_FROM_LE #endif #ifndef INT16_TO -#define INT16_TO INT16_TO_LE +#define INT16_TO PA_INT16_TO_LE #endif #ifndef SWAP_WORDS @@ -53,32 +53,28 @@ #endif #endif -void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b) { - const int16_t *ca = a; - - assert(a); - assert(b); +void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *b) { + pa_assert(a); + pa_assert(b); #if SWAP_WORDS == 1 for (; n > 0; n--) { - int16_t s = *(ca++); + int16_t s = *(a++); *(b++) = ((float) INT16_FROM(s))/0x7FFF; } #else { static const double add = 0, factor = 1.0/0x7FFF; - oil_scaleconv_f32_s16(b, ca, n, &add, &factor); + oil_scaleconv_f32_s16(b, a, n, &add, &factor); } #endif } -void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) { - int16_t *cb = b; - - assert(a); - assert(b); +void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) { + pa_assert(a); + pa_assert(b); #if SWAP_WORDS == 1 @@ -86,20 +82,43 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) { int16_t s; float v = *(a++); - if (v > 1) - v = 1; - - if (v < -1) - v = -1; - + v = CLAMP(v, -1, 1); s = (int16_t) (v * 0x7FFF); - *(cb++) = INT16_TO(s); + *(b++) = INT16_TO(s); } #else { static const double add = 0, factor = 0x7FFF; - oil_scaleconv_s16_f32(cb, a, n, &add, &factor); + oil_scaleconv_s16_f32(b, a, n, &add, &factor); } #endif } + +void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int16_t s = *(a++); + float k = ((float) INT16_FROM(s))/0x7FFF; + uint32_t *j = (uint32_t*) &k; + *j = PA_UINT32_SWAP(*j); + *(b++) = k; + } +} + +void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int16_t s; + float v = *(a++); + uint32_t *j = (uint32_t*) &v; + *j = PA_UINT32_SWAP(*j); + v = CLAMP(v, -1, 1); + s = (int16_t) (v * 0x7FFF); + *(b++) = INT16_TO(s); + } +} diff --git a/src/pulsecore/sconv-s16le.h b/src/pulsecore/sconv-s16le.h index c4e4911ad..4203315a1 100644 --- a/src/pulsecore/sconv-s16le.h +++ b/src/pulsecore/sconv-s16le.h @@ -24,7 +24,18 @@ USA. ***/ -void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b); -void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b); +#include + +void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *b); +void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b); +void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b); +void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b); + +#ifndef WORDS_BIGENDIAN +#define pa_sconv_float32be_to_s16ne pa_sconv_s16le_from_float32re +#define pa_sconv_float32be_from_s16ne pa_sconv_s16le_to_float32re +#define pa_sconv_float32le_to_s16ne pa_sconv_s16le_from_float32ne +#define pa_sconv_float32le_from_s16ne pa_sconv_s16le_to_float32ne +#endif #endif diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index d15cec847..7f5da63f0 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -28,12 +28,12 @@ #include #include -#include #include #include #include +#include #include "endianmacros.h" #include "sconv-s16le.h" @@ -41,152 +41,223 @@ #include "sconv.h" -static void u8_to_float32ne(unsigned n, const void *a, float *b) { - const uint8_t *ca = a; - static const double add = -128.0/127.0, factor = 1.0/127.0; +/* u8 */ +static void u8_to_float32ne(unsigned n, const uint8_t *a, float *b) { + static const double add = -1, factor = 1.0/128.0; - assert(a); - assert(b); + pa_assert(a); + pa_assert(b); - oil_scaleconv_f32_u8(b, ca, n, &add, &factor); + oil_scaleconv_f32_u8(b, a, n, &add, &factor); } -static void u8_from_float32ne(unsigned n, const float *a, void *b) { - uint8_t *cb = b; - static const double add = 128.0, factor = 127.0; +static void u8_from_float32ne(unsigned n, const float *a, uint8_t *b) { + static const double add = 128, factor = 127.0; - assert(a); - assert(b); + pa_assert(a); + pa_assert(b); - oil_scaleconv_u8_f32(cb, a, n, &add, &factor); + oil_scaleconv_u8_f32(b, a, n, &add, &factor); } -static void float32ne_to_float32ne(unsigned n, const void *a, float *b) { - assert(a); - assert(b); +static void u8_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) { + static const int16_t add = -0x80, factor = 0x100; + + pa_assert(a); + pa_assert(b); + + oil_conv_s16_u8(b, 2, a, 1, n); + oil_scalaradd_s16(b, 2, b, 2, &add, n); + oil_scalarmult_s16(b, 2, b, 2, &factor, n); +} + +static void u8_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) { + + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--, a++, b++) + *b = (uint8_t) (*a / 0x100 + 0x80); +} + +/* float32 */ + +static void float32ne_to_float32ne(unsigned n, const float *a, float *b) { + pa_assert(a); + pa_assert(b); oil_memcpy(b, a, sizeof(float) * n); } -static void float32ne_from_float32ne(unsigned n, const float *a, void *b) { - assert(a); - assert(b); +static void float32re_to_float32ne(unsigned n, const float *a, float *b) { + pa_assert(a); + pa_assert(b); - oil_memcpy(b, a, sizeof(float) * n); + for (; n > 0; n--, a++, b++) + *((uint32_t *) b) = PA_UINT32_SWAP(*((uint32_t *) a)); } -static void float32re_to_float32ne(unsigned n, const void *a, float *b) { - assert(a); - assert(b); +/* s16 */ - while (n-- > 0) - ((uint32_t *)b)[n] = UINT32_SWAP (((uint32_t *)a)[n]); +static void s16ne_to_s16ne(unsigned n, const int16_t *a, int16_t *b) { + pa_assert(a); + pa_assert(b); + + oil_memcpy(b, a, sizeof(int16_t) * n); } -static void float32re_from_float32ne(unsigned n, const float *a, void *b) { - assert(a); - assert(b); +static void s16re_to_s16ne(unsigned n, const int16_t *a, int16_t *b) { + pa_assert(a); + pa_assert(b); - while (n-- > 0) - ((uint32_t *)b)[n] = UINT32_SWAP (((uint32_t *)a)[n]); + for (; n > 0; n--, a++, b++) + *b = PA_UINT16_SWAP(*a); } -static void ulaw_to_float32ne(unsigned n, const void *a, float *b) { - const uint8_t *ca = a; +/* ulaw */ - assert(a); - assert(b); +static void ulaw_to_float32ne(unsigned n, const uint8_t *a, float *b) { + pa_assert(a); + pa_assert(b); for (; n > 0; n--) - *(b++) = st_ulaw2linear16(*(ca++)) * 1.0F / 0x7FFF; + *(b++) = (float) st_ulaw2linear16(*(a++)) / 0x8000; } -static void ulaw_from_float32ne(unsigned n, const float *a, void *b) { - uint8_t *cb = b; - - assert(a); - assert(b); +static void ulaw_from_float32ne(unsigned n, const float *a, uint8_t *b) { + pa_assert(a); + pa_assert(b); for (; n > 0; n--) { float v = *(a++); - - if (v > 1) - v = 1; - - if (v < -1) - v = -1; - - *(cb++) = st_14linear2ulaw((int16_t) (v * 0x1FFF)); + v = CLAMP(v, -1, 1); + v *= 0x1FFF; + *(b++) = st_14linear2ulaw((int16_t) v); } } -static void alaw_to_float32ne(unsigned n, const void *a, float *b) { - const uint8_t *ca = a; +static void ulaw_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) { + pa_assert(a); + pa_assert(b); - assert(a); - assert(b); - - for (; n > 0; n--) - *(b++) = st_alaw2linear16(*(ca++)) * 1.0F / 0x7FFF; + for (; n > 0; n--, a++, b++) + *b = st_ulaw2linear16(*a); } -static void alaw_from_float32ne(unsigned n, const float *a, void *b) { - uint8_t *cb = b; +static void ulaw_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) { + pa_assert(a); + pa_assert(b); - assert(a); - assert(b); + for (; n > 0; n--, a++, b++) + *b = st_14linear2ulaw(*a >> 2); +} - for (; n > 0; n--) { - float v = *(a++); +/* alaw */ - if (v > 1) - v = 1; +static void alaw_to_float32ne(unsigned n, const uint8_t *a, float *b) { + pa_assert(a); + pa_assert(b); - if (v < -1) - v = -1; + for (; n > 0; n--, a++, b++) + *b = (float) st_alaw2linear16(*a) / 0x8000; +} - *(cb++) = st_13linear2alaw((int16_t) (v * 0xFFF)); +static void alaw_from_float32ne(unsigned n, const float *a, uint8_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--, a++, b++) { + float v = *a; + v = CLAMP(v, -1, 1); + v *= 0xFFF; + *b = st_13linear2alaw((int16_t) v); } } -pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) { - switch(f) { - case PA_SAMPLE_U8: - return u8_to_float32ne; - case PA_SAMPLE_S16LE: - return pa_sconv_s16le_to_float32ne; - case PA_SAMPLE_S16BE: - return pa_sconv_s16be_to_float32ne; - case PA_SAMPLE_FLOAT32NE: - return float32ne_to_float32ne; - case PA_SAMPLE_FLOAT32RE: - return float32re_to_float32ne; - case PA_SAMPLE_ALAW: - return alaw_to_float32ne; - case PA_SAMPLE_ULAW: - return ulaw_to_float32ne; - default: - return NULL; - } +static void alaw_to_s16ne(unsigned n, const int8_t *a, int16_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--, a++, b++) + *b = st_alaw2linear16(*a); } -pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) { - switch(f) { - case PA_SAMPLE_U8: - return u8_from_float32ne; - case PA_SAMPLE_S16LE: - return pa_sconv_s16le_from_float32ne; - case PA_SAMPLE_S16BE: - return pa_sconv_s16be_from_float32ne; - case PA_SAMPLE_FLOAT32NE: - return float32ne_from_float32ne; - case PA_SAMPLE_FLOAT32RE: - return float32re_from_float32ne; - case PA_SAMPLE_ALAW: - return alaw_from_float32ne; - case PA_SAMPLE_ULAW: - return ulaw_from_float32ne; - default: - return NULL; - } +static void alaw_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--, a++, b++) + *b = st_13linear2alaw(*a >> 3); +} + +pa_convert_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) { + + static const pa_convert_func_t table[] = { + [PA_SAMPLE_U8] = (pa_convert_func_t) u8_to_float32ne, + [PA_SAMPLE_ALAW] = (pa_convert_func_t) alaw_to_float32ne, + [PA_SAMPLE_ULAW] = (pa_convert_func_t) ulaw_to_float32ne, + [PA_SAMPLE_S16LE] = (pa_convert_func_t) pa_sconv_s16le_to_float32ne, + [PA_SAMPLE_S16BE] = (pa_convert_func_t) pa_sconv_s16be_to_float32ne, + [PA_SAMPLE_FLOAT32NE] = (pa_convert_func_t) float32ne_to_float32ne, + [PA_SAMPLE_FLOAT32RE] = (pa_convert_func_t) float32re_to_float32ne, + }; + + pa_assert(f >= 0); + pa_assert(f < PA_SAMPLE_MAX); + + return table[f]; +} + +pa_convert_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) { + + static const pa_convert_func_t table[] = { + [PA_SAMPLE_U8] = (pa_convert_func_t) u8_from_float32ne, + [PA_SAMPLE_S16LE] = (pa_convert_func_t) pa_sconv_s16le_from_float32ne, + [PA_SAMPLE_S16BE] = (pa_convert_func_t) pa_sconv_s16be_from_float32ne, + [PA_SAMPLE_FLOAT32NE] = (pa_convert_func_t) float32ne_to_float32ne, + [PA_SAMPLE_FLOAT32RE] = (pa_convert_func_t) float32re_to_float32ne, + [PA_SAMPLE_ALAW] = (pa_convert_func_t) alaw_from_float32ne, + [PA_SAMPLE_ULAW] = (pa_convert_func_t) ulaw_from_float32ne + }; + + pa_assert(f >= 0); + pa_assert(f < PA_SAMPLE_MAX); + + return table[f]; +} + +pa_convert_func_t pa_get_convert_to_s16ne_function(pa_sample_format_t f) { + + static const pa_convert_func_t table[] = { + [PA_SAMPLE_U8] = (pa_convert_func_t) u8_to_s16ne, + [PA_SAMPLE_S16NE] = (pa_convert_func_t) s16ne_to_s16ne, + [PA_SAMPLE_S16RE] = (pa_convert_func_t) s16re_to_s16ne, + [PA_SAMPLE_FLOAT32BE] = (pa_convert_func_t) pa_sconv_float32be_to_s16ne, + [PA_SAMPLE_FLOAT32LE] = (pa_convert_func_t) pa_sconv_float32le_to_s16ne, + [PA_SAMPLE_ALAW] = (pa_convert_func_t) alaw_to_s16ne, + [PA_SAMPLE_ULAW] = (pa_convert_func_t) ulaw_to_s16ne + }; + + pa_assert(f >= 0); + pa_assert(f < PA_SAMPLE_MAX); + + return table[f]; +} + +pa_convert_func_t pa_get_convert_from_s16ne_function(pa_sample_format_t f) { + + static const pa_convert_func_t table[] = { + [PA_SAMPLE_U8] = (pa_convert_func_t) u8_from_s16ne, + [PA_SAMPLE_S16NE] = (pa_convert_func_t) s16ne_to_s16ne, + [PA_SAMPLE_S16RE] = (pa_convert_func_t) s16re_to_s16ne, + [PA_SAMPLE_FLOAT32BE] = (pa_convert_func_t) pa_sconv_float32be_from_s16ne, + [PA_SAMPLE_FLOAT32LE] = (pa_convert_func_t) pa_sconv_float32le_from_s16ne, + [PA_SAMPLE_ALAW] = (pa_convert_func_t) alaw_from_s16ne, + [PA_SAMPLE_ULAW] = (pa_convert_func_t) ulaw_from_s16ne, + }; + + pa_assert(f >= 0); + pa_assert(f < PA_SAMPLE_MAX); + + return table[f]; } diff --git a/src/pulsecore/sconv.h b/src/pulsecore/sconv.h index 1e97aad9d..901f50a30 100644 --- a/src/pulsecore/sconv.h +++ b/src/pulsecore/sconv.h @@ -27,10 +27,12 @@ #include -typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, float *b); -typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b); +typedef void (*pa_convert_func_t)(unsigned n, const void *a, void *b); -pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f); -pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f); +pa_convert_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) PA_GCC_PURE; +pa_convert_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) PA_GCC_PURE; + +pa_convert_func_t pa_get_convert_to_s16ne_function(pa_sample_format_t f) PA_GCC_PURE; +pa_convert_func_t pa_get_convert_from_s16ne_function(pa_sample_format_t f) PA_GCC_PURE; #endif diff --git a/src/pulsecore/semaphore-posix.c b/src/pulsecore/semaphore-posix.c new file mode 100644 index 000000000..750c2afc3 --- /dev/null +++ b/src/pulsecore/semaphore-posix.c @@ -0,0 +1,69 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include "semaphore.h" + +struct pa_semaphore { + sem_t sem; +}; + +pa_semaphore* pa_semaphore_new(unsigned value) { + pa_semaphore *s; + + s = pa_xnew(pa_semaphore, 1); + pa_assert_se(sem_init(&s->sem, 0, value) == 0); + return s; +} + +void pa_semaphore_free(pa_semaphore *s) { + pa_assert(s); + pa_assert_se(sem_destroy(&s->sem) == 0); + pa_xfree(s); +} + +void pa_semaphore_post(pa_semaphore *s) { + pa_assert(s); + pa_assert_se(sem_post(&s->sem) == 0); +} + +void pa_semaphore_wait(pa_semaphore *s) { + int ret; + pa_assert(s); + + do { + ret = sem_wait(&s->sem); + } while (ret < 0 && errno == EINTR); + + pa_assert(ret == 0); +} diff --git a/src/pulsecore/semaphore-win32.c b/src/pulsecore/semaphore-win32.c new file mode 100644 index 000000000..f65763487 --- /dev/null +++ b/src/pulsecore/semaphore-win32.c @@ -0,0 +1,65 @@ +/* $Id: mutex-win32.c 1426 2007-02-13 15:35:19Z ossman $ */ + +/*** + This file is part of PulseAudio. + + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include "semaphore.h" + +struct pa_semaphore +{ + HANDLE sema; +}; + +pa_semaphore* pa_semaphore_new(unsigned value) { + pa_semaphore *s; + + s = pa_xnew(pa_semaphore, 1); + + s->sema = CreateSemaphore(NULL, value, 32767, NULL); + pa_assert(s->sema != NULL); + + return s; +} + +void pa_semaphore_free(pa_semaphore *s) { + pa_assert(s); + CloseHandle(s->sema); + pa_xfree(s); +} + +void pa_semaphore_post(pa_semaphore *s) { + pa_assert(s); + ReleaseSemaphore(s->sema, 1, NULL); +} + +void pa_semaphore_wait(pa_semaphore *s) { + pa_assert(s); + WaitForSingleObject(s->sema, INFINITE); +} diff --git a/src/pulsecore/anotify.h b/src/pulsecore/semaphore.h similarity index 64% rename from src/pulsecore/anotify.h rename to src/pulsecore/semaphore.h index b3f75b7e8..c394e0f2f 100644 --- a/src/pulsecore/anotify.h +++ b/src/pulsecore/semaphore.h @@ -1,5 +1,5 @@ -#ifndef foopulseanotifyhfoo -#define foopulseanotifyhfoo +#ifndef foopulsesemaphorehfoo +#define foopulsesemaphorehfoo /* $Id$ */ @@ -24,17 +24,12 @@ USA. ***/ -/* Asynchronous thread-safe notification of mainloops */ +typedef struct pa_semaphore pa_semaphore; +pa_semaphore* pa_semaphore_new(unsigned value); +void pa_semaphore_free(pa_semaphore *m); -#include -#include - -typedef struct pa_anotify pa_anotify; -typedef void (*pa_anotify_cb_t)(uint8_t event, void *userdata); - -pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userdata); -void pa_anotify_free(pa_anotify *a); -int pa_anotify_signal(pa_anotify *a, uint8_t event); +void pa_semaphore_post(pa_semaphore *m); +void pa_semaphore_wait(pa_semaphore *m); #endif diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index 444d4010e..6882e7f85 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -1,32 +1,31 @@ /* $Id$ */ /*** - This file is part of PulseAudio. + This file is part of PulseAudio. - Copyright 2006 Lennart Poettering - Copyright 2006 Pierre Ossman for Cendio AB + Copyright 2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. ***/ #ifdef HAVE_CONFIG_H #include #endif -#include #include #include #include @@ -34,15 +33,22 @@ #include #include #include +#include +#include +#include #ifdef HAVE_SYS_MMAN_H #include #endif +#include + #include #include #include -#include +#include +#include +#include #include "shm.h" @@ -50,10 +56,31 @@ #define MADV_REMOVE 9 #endif -#define MAX_SHM_SIZE (1024*1024*20) +#define MAX_SHM_SIZE (PA_ALIGN(1024*1024*20)) + +#ifdef __linux__ +/* On Linux we know that the shared memory blocks are files in + * /dev/shm. We can use that information to list all blocks and + * cleanup unused ones */ +#define SHM_PATH "/dev/shm/" +#else +#undef SHM_PATH +#endif + +#define SHM_MARKER ((int) 0xbeefcafe) + +/* We now put this SHM marker at the end of each segment. It's optional to not require a reboot when upgrading, though */ +struct shm_marker { + pa_atomic_t marker; /* 0xbeefcafe */ + pa_atomic_t pid; + void *_reserverd1; + void *_reserverd2; + void *_reserverd3; + void *_reserverd4; +}; static char *segment_name(char *fn, size_t l, unsigned id) { - snprintf(fn, l, "/pulse-shm-%u", id); + pa_snprintf(fn, l, "/pulse-shm-%u", id); return fn; } @@ -61,10 +88,17 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { char fn[32]; int fd = -1; - assert(m); - assert(size > 0); - assert(size < MAX_SHM_SIZE); - assert(mode >= 0600); + pa_assert(m); + pa_assert(size > 0); + pa_assert(size < MAX_SHM_SIZE); + pa_assert(mode >= 0600); + + /* Each time we create a new SHM area, let's first drop all stale + * ones */ + pa_shm_cleanup(); + + /* Round up to make it aligned */ + size = PA_ALIGN(size); if (!shared) { m->id = 0; @@ -79,7 +113,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { { int r; - if ((r = posix_memalign(&m->ptr, sysconf(_SC_PAGESIZE), size)) < 0) { + if ((r = posix_memalign(&m->ptr, PA_PAGE_SIZE, size)) < 0) { pa_log("posix_memalign() failed: %s", pa_cstrerror(r)); goto fail; } @@ -92,6 +126,8 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { } else { #ifdef HAVE_SHM_OPEN + struct shm_marker *marker; + pa_random(&m->id, sizeof(m->id)); segment_name(fn, sizeof(fn), m->id); @@ -100,7 +136,9 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { goto fail; } - if (ftruncate(fd, m->size = size) < 0) { + m->size = size + PA_ALIGN(sizeof(struct shm_marker)); + + if (ftruncate(fd, m->size) < 0) { pa_log("ftruncate() failed: %s", pa_cstrerror(errno)); goto fail; } @@ -110,10 +148,16 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) { goto fail; } - close(fd); + /* We store our PID at the end of the shm block, so that we + * can check for dead shm segments later */ + marker = (struct shm_marker*) ((uint8_t*) m->ptr + m->size - PA_ALIGN(sizeof(struct shm_marker))); + pa_atomic_store(&marker->pid, (int) getpid()); + pa_atomic_store(&marker->marker, SHM_MARKER); + + pa_assert_se(close(fd) == 0); m->do_unlink = 1; #else - return -1; + return -1; #endif } @@ -126,7 +170,7 @@ fail: #ifdef HAVE_SHM_OPEN if (fd >= 0) { shm_unlink(fn); - close(fd); + pa_close(fd); } #endif @@ -134,76 +178,70 @@ fail: } void pa_shm_free(pa_shm *m) { - assert(m); - assert(m->ptr); - assert(m->size > 0); + pa_assert(m); + pa_assert(m->ptr); + pa_assert(m->size > 0); #ifdef MAP_FAILED - assert(m->ptr != MAP_FAILED); + pa_assert(m->ptr != MAP_FAILED); #endif - if (!m->shared) { + if (!m->shared) { #ifdef MAP_ANONYMOUS - if (munmap(m->ptr, m->size) < 0) - pa_log("munmap() failed: %s", pa_cstrerror(errno)); + if (munmap(m->ptr, m->size) < 0) + pa_log("munmap() failed: %s", pa_cstrerror(errno)); #elif defined(HAVE_POSIX_MEMALIGN) free(m->ptr); #else pa_xfree(m->ptr); #endif - } else { + } else { #ifdef HAVE_SHM_OPEN - if (munmap(m->ptr, m->size) < 0) - pa_log("munmap() failed: %s", pa_cstrerror(errno)); + if (munmap(m->ptr, m->size) < 0) + pa_log("munmap() failed: %s", pa_cstrerror(errno)); - if (m->do_unlink) { - char fn[32]; + if (m->do_unlink) { + char fn[32]; - segment_name(fn, sizeof(fn), m->id); + segment_name(fn, sizeof(fn), m->id); - if (shm_unlink(fn) < 0) - pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno)); - } + if (shm_unlink(fn) < 0) + pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno)); + } #else - /* We shouldn't be here without shm support */ - assert(0); + /* We shouldn't be here without shm support */ + pa_assert_not_reached(); #endif - } + } memset(m, 0, sizeof(*m)); } void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { void *ptr; + size_t o, ps; - assert(m); - assert(m->ptr); - assert(m->size > 0); - assert(offset+size <= m->size); + pa_assert(m); + pa_assert(m->ptr); + pa_assert(m->size > 0); + pa_assert(offset+size <= m->size); #ifdef MAP_FAILED - assert(m->ptr != MAP_FAILED); + pa_assert(m->ptr != MAP_FAILED); #endif /* You're welcome to implement this as NOOP on systems that don't * support it */ + /* Align this to multiples of the page size */ ptr = (uint8_t*) m->ptr + offset; - -#ifdef __linux__ -{ - /* On Linux ptr must be page aligned */ - long psz = sysconf(_SC_PAGESIZE); - unsigned o; - - o = ((unsigned long) ptr) - ((((unsigned long) ptr)/psz) * psz); + o = (uint8_t*) ptr - (uint8_t*) PA_PAGE_ALIGN_PTR(ptr); if (o > 0) { - ptr = (uint8_t*) ptr + (psz - o); - size -= psz - o; + ps = PA_PAGE_SIZE; + ptr = (uint8_t*) ptr + (ps - o); + size -= ps - o; } -} -#endif #ifdef MADV_REMOVE if (madvise(ptr, size, MADV_REMOVE) >= 0) @@ -216,7 +254,9 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { #endif #ifdef MADV_DONTNEED - madvise(ptr, size, MADV_DONTNEED); + pa_assert_se(madvise(ptr, size, MADV_DONTNEED) == 0); +#elif defined(POSIX_MADV_DONTNEED) + pa_assert_se(posix_madvise(ptr, size, POSIX_MADV_DONTNEED) == 0); #endif } @@ -227,12 +267,13 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) { int fd = -1; struct stat st; - assert(m); + pa_assert(m); segment_name(fn, sizeof(fn), m->id = id); if ((fd = shm_open(fn, O_RDONLY, 0)) < 0) { - pa_log("shm_open() failed: %s", pa_cstrerror(errno)); + if (errno != EACCES) + pa_log("shm_open() failed: %s", pa_cstrerror(errno)); goto fail; } @@ -241,7 +282,7 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) { goto fail; } - if (st.st_size <= 0 || st.st_size > MAX_SHM_SIZE) { + if (st.st_size <= 0 || st.st_size > MAX_SHM_SIZE+PA_ALIGN(sizeof(struct shm_marker)) || PA_ALIGN(st.st_size) != st.st_size) { pa_log("Invalid shared memory segment size"); goto fail; } @@ -256,13 +297,13 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) { m->do_unlink = 0; m->shared = 1; - close(fd); + pa_assert_se(pa_close(fd) == 0); return 0; fail: if (fd >= 0) - close(fd); + pa_close(fd); return -1; } @@ -270,7 +311,71 @@ fail: #else /* HAVE_SHM_OPEN */ int pa_shm_attach_ro(pa_shm *m, unsigned id) { - return -1; + return -1; } #endif /* HAVE_SHM_OPEN */ + +int pa_shm_cleanup(void) { + +#ifdef SHM_PATH + DIR *d; + struct dirent *de; + + if (!(d = opendir(SHM_PATH))) { + pa_log_warn("Failed to read "SHM_PATH": %s", pa_cstrerror(errno)); + return -1; + } + + while ((de = readdir(d))) { + pa_shm seg; + unsigned id; + pid_t pid; + char fn[128]; + struct shm_marker *m; + + if (strncmp(de->d_name, "pulse-shm-", 10)) + continue; + + if (pa_atou(de->d_name + 10, &id) < 0) + continue; + + if (pa_shm_attach_ro(&seg, id) < 0) + continue; + + if (seg.size < PA_ALIGN(sizeof(struct shm_marker))) { + pa_shm_free(&seg); + continue; + } + + m = (struct shm_marker*) ((uint8_t*) seg.ptr + seg.size - PA_ALIGN(sizeof(struct shm_marker))); + + if (pa_atomic_load(&m->marker) != SHM_MARKER) { + pa_shm_free(&seg); + continue; + } + + if (!(pid = (pid_t) pa_atomic_load(&m->pid))) { + pa_shm_free(&seg); + continue; + } + + if (kill(pid, 0) == 0 || errno != ESRCH) { + pa_shm_free(&seg); + continue; + } + + pa_shm_free(&seg); + + /* Ok, the owner of this shms segment is dead, so, let's remove the segment */ + segment_name(fn, sizeof(fn), id); + + if (shm_unlink(fn) < 0 && errno != EACCES) + pa_log_warn("Failed to remove SHM segment %s: %s\n", fn, pa_cstrerror(errno)); + } + + closedir(d); +#endif + + return 0; +} diff --git a/src/pulsecore/shm.h b/src/pulsecore/shm.h index e695a2a19..270591dec 100644 --- a/src/pulsecore/shm.h +++ b/src/pulsecore/shm.h @@ -41,4 +41,6 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size); void pa_shm_free(pa_shm *m); +int pa_shm_cleanup(void); + #endif diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 3ddd74350..6f654b616 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include @@ -42,45 +41,51 @@ #include "sink-input.h" -#define CONVERT_BUFFER_LENGTH 4096 -#define MOVE_BUFFER_LENGTH (1024*1024) -#define SILENCE_BUFFER_LENGTH (64*1024) +#define CONVERT_BUFFER_LENGTH (PA_PAGE_SIZE) +#define SILENCE_BUFFER_LENGTH (PA_PAGE_SIZE*12) +#define MOVE_BUFFER_LENGTH (PA_PAGE_SIZE*256) -#define CHECK_VALIDITY_RETURN_NULL(condition) \ -do {\ -if (!(condition)) \ - return NULL; \ -} while (0) +static PA_DEFINE_CHECK_TYPE(pa_sink_input, pa_msgobject); + +static void sink_input_free(pa_object *o); pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) { - assert(data); + pa_assert(data); memset(data, 0, sizeof(*data)); data->resample_method = PA_RESAMPLER_INVALID; + return data; } void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map) { - assert(data); + pa_assert(data); if ((data->channel_map_is_set = !!map)) data->channel_map = *map; } void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) { - assert(data); + pa_assert(data); if ((data->volume_is_set = !!volume)) data->volume = *volume; } void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec) { - assert(data); + pa_assert(data); if ((data->sample_spec_is_set = !!spec)) data->sample_spec = *spec; } +void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) { + pa_assert(data); + + data->muted_is_set = TRUE; + data->muted = !!mute; +} + pa_sink_input* pa_sink_input_new( pa_core *core, pa_sink_input_new_data *data, @@ -88,46 +93,52 @@ pa_sink_input* pa_sink_input_new( pa_sink_input *i; pa_resampler *resampler = NULL; - int r; char st[PA_SAMPLE_SPEC_SNPRINT_MAX]; - assert(core); - assert(data); + pa_assert(core); + pa_assert(data); - if (!(flags & PA_SINK_INPUT_NO_HOOKS)) - if (pa_hook_fire(&core->hook_sink_input_new, data) < 0) - return NULL; + if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data) < 0) + return NULL; - CHECK_VALIDITY_RETURN_NULL(!data->driver || pa_utf8_valid(data->driver)); - CHECK_VALIDITY_RETURN_NULL(!data->name || pa_utf8_valid(data->name)); + pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver)); + pa_return_null_if_fail(!data->name || pa_utf8_valid(data->name)); if (!data->sink) data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK, 1); - CHECK_VALIDITY_RETURN_NULL(data->sink); - CHECK_VALIDITY_RETURN_NULL(data->sink->state == PA_SINK_RUNNING); + pa_return_null_if_fail(data->sink); + pa_return_null_if_fail(pa_sink_get_state(data->sink) != PA_SINK_UNLINKED); + pa_return_null_if_fail(!data->sync_base || (data->sync_base->sink == data->sink && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED)); if (!data->sample_spec_is_set) data->sample_spec = data->sink->sample_spec; - CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(&data->sample_spec)); + pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec)); - if (!data->channel_map_is_set) - pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); + if (!data->channel_map_is_set) { + if (data->sink->channel_map.channels == data->sample_spec.channels) + data->channel_map = data->sink->channel_map; + else + pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); + } - CHECK_VALIDITY_RETURN_NULL(pa_channel_map_valid(&data->channel_map)); - CHECK_VALIDITY_RETURN_NULL(data->channel_map.channels == data->sample_spec.channels); + pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map)); + pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels); if (!data->volume_is_set) pa_cvolume_reset(&data->volume, data->sample_spec.channels); - CHECK_VALIDITY_RETURN_NULL(pa_cvolume_valid(&data->volume)); - CHECK_VALIDITY_RETURN_NULL(data->volume.channels == data->sample_spec.channels); + pa_return_null_if_fail(pa_cvolume_valid(&data->volume)); + pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels); + + if (!data->muted_is_set) + data->muted = 0; if (data->resample_method == PA_RESAMPLER_INVALID) data->resample_method = core->resample_method; - CHECK_VALIDITY_RETURN_NULL(data->resample_method < PA_RESAMPLER_MAX); + pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX); if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) { pa_log_warn("Failed to create sink input: too many inputs per sink."); @@ -136,20 +147,27 @@ pa_sink_input* pa_sink_input_new( if ((flags & PA_SINK_INPUT_VARIABLE_RATE) || !pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) || - !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) + !pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) { if (!(resampler = pa_resampler_new( core->mempool, &data->sample_spec, &data->channel_map, &data->sink->sample_spec, &data->sink->channel_map, - data->resample_method))) { + data->resample_method, + !!(flags & PA_SINK_INPUT_VARIABLE_RATE)))) { pa_log_warn("Unsupported resampling operation."); return NULL; } - i = pa_xnew(pa_sink_input, 1); - i->ref = 1; - i->state = PA_SINK_INPUT_DRAINED; + data->resample_method = pa_resampler_get_method(resampler); + } + + i = pa_msgobject_new(pa_sink_input); + i->parent.parent.free = sink_input_free; + i->parent.process_msg = pa_sink_input_process_msg; + + i->core = core; + i->state = PA_SINK_INPUT_INIT; i->flags = flags; i->name = pa_xstrdup(data->name); i->driver = pa_xstrdup(data->driver); @@ -157,105 +175,203 @@ pa_sink_input* pa_sink_input_new( i->sink = data->sink; i->client = data->client; + i->resample_method = data->resample_method; i->sample_spec = data->sample_spec; i->channel_map = data->channel_map; + i->volume = data->volume; + i->muted = data->muted; + + if (data->sync_base) { + i->sync_next = data->sync_base->sync_next; + i->sync_prev = data->sync_base; + + if (data->sync_base->sync_next) + data->sync_base->sync_next->sync_prev = i; + data->sync_base->sync_next = i; + } else + i->sync_next = i->sync_prev = NULL; i->peek = NULL; i->drop = NULL; i->kill = NULL; i->get_latency = NULL; - i->underrun = NULL; + i->attach = NULL; + i->detach = NULL; + i->suspend = NULL; i->userdata = NULL; - i->move_silence = 0; + i->thread_info.state = i->state; + pa_atomic_store(&i->thread_info.drained, 1); + i->thread_info.sample_spec = i->sample_spec; + i->thread_info.silence_memblock = NULL; + i->thread_info.move_silence = 0; + pa_memchunk_reset(&i->thread_info.resampled_chunk); + i->thread_info.resampler = resampler; + i->thread_info.volume = i->volume; + i->thread_info.muted = i->muted; + i->thread_info.attached = FALSE; - pa_memchunk_reset(&i->resampled_chunk); - i->resampler = resampler; - i->resample_method = data->resample_method; - i->silence_memblock = NULL; + pa_assert_se(pa_idxset_put(core->sink_inputs, pa_sink_input_ref(i), &i->index) == 0); + pa_assert_se(pa_idxset_put(i->sink->inputs, i, NULL) == 0); - r = pa_idxset_put(core->sink_inputs, i, &i->index); - assert(r == 0); - r = pa_idxset_put(i->sink->inputs, i, NULL); - assert(r == 0); - - pa_log_info("created %u \"%s\" on %s with sample spec %s", + pa_log_info("Created input %u \"%s\" on %s with sample spec %s", i->index, i->name, i->sink->name, pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec)); - pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); - - /* We do not call pa_sink_notify() here, because the virtual - * functions have not yet been initialized */ + /* Don't forget to call pa_sink_input_put! */ return i; } -void pa_sink_input_disconnect(pa_sink_input *i) { - assert(i); - assert(i->state != PA_SINK_INPUT_DISCONNECTED); - assert(i->sink); - assert(i->sink->core); +static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) { + pa_assert(i); + + if (i->state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED) + pa_assert_se(i->sink->n_corked -- >= 1); + else if (i->state != PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_CORKED) + i->sink->n_corked++; + + pa_sink_update_status(i->sink); +} + +static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) { + pa_sink_input *ssync; + pa_assert(i); + + if (state == PA_SINK_INPUT_DRAINED) + state = PA_SINK_INPUT_RUNNING; + + if (i->state == state) + return 0; + + if (pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0) + return -1; + + update_n_corked(i, state); + i->state = state; + + for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev) { + update_n_corked(ssync, state); + ssync->state = state; + } + for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) { + update_n_corked(ssync, state); + ssync->state = state; + } + + if (state != PA_SINK_INPUT_UNLINKED) + pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i); + + return 0; +} + +void pa_sink_input_unlink(pa_sink_input *i) { + pa_bool_t linked; + pa_assert(i); + + /* See pa_sink_unlink() for a couple of comments how this function + * works */ + + pa_sink_input_ref(i); + + linked = PA_SINK_INPUT_LINKED(i->state); + + if (linked) + pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i); + + if (i->sync_prev) + i->sync_prev->sync_next = i->sync_next; + if (i->sync_next) + i->sync_next->sync_prev = i->sync_prev; + + i->sync_prev = i->sync_next = NULL; pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL); - pa_idxset_remove_by_data(i->sink->inputs, i, NULL); + if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL)) + pa_sink_input_unref(i); - pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index); - i->sink = NULL; + if (linked) { + pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL); + sink_input_set_state(i, PA_SINK_INPUT_UNLINKED); + pa_sink_update_status(i->sink); + } else + i->state = PA_SINK_INPUT_UNLINKED; i->peek = NULL; i->drop = NULL; i->kill = NULL; i->get_latency = NULL; - i->underrun = NULL; + i->attach = NULL; + i->detach = NULL; + i->suspend = NULL; - i->state = PA_SINK_INPUT_DISCONNECTED; + if (linked) { + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index); + pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i); + } + + i->sink = NULL; + pa_sink_input_unref(i); } -static void sink_input_free(pa_sink_input* i) { - assert(i); +static void sink_input_free(pa_object *o) { + pa_sink_input* i = PA_SINK_INPUT(o); - if (i->state != PA_SINK_INPUT_DISCONNECTED) - pa_sink_input_disconnect(i); + pa_assert(i); + pa_assert(pa_sink_input_refcnt(i) == 0); - pa_log_info("freed %u \"%s\"", i->index, i->name); + if (PA_SINK_INPUT_LINKED(i->state)) + pa_sink_input_unlink(i); - if (i->resampled_chunk.memblock) - pa_memblock_unref(i->resampled_chunk.memblock); + pa_log_info("Freeing output %u \"%s\"", i->index, i->name); - if (i->resampler) - pa_resampler_free(i->resampler); + pa_assert(!i->thread_info.attached); - if (i->silence_memblock) - pa_memblock_unref(i->silence_memblock); + if (i->thread_info.resampled_chunk.memblock) + pa_memblock_unref(i->thread_info.resampled_chunk.memblock); + + if (i->thread_info.resampler) + pa_resampler_free(i->thread_info.resampler); + + if (i->thread_info.silence_memblock) + pa_memblock_unref(i->thread_info.silence_memblock); pa_xfree(i->name); pa_xfree(i->driver); pa_xfree(i); } -void pa_sink_input_unref(pa_sink_input *i) { - assert(i); - assert(i->ref >= 1); +void pa_sink_input_put(pa_sink_input *i) { + pa_sink_input_assert_ref(i); - if (!(--i->ref)) - sink_input_free(i); -} + pa_assert(i->state == PA_SINK_INPUT_INIT); + pa_assert(i->peek); + pa_assert(i->drop); -pa_sink_input* pa_sink_input_ref(pa_sink_input *i) { - assert(i); - assert(i->ref >= 1); + i->thread_info.state = i->state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING; + i->thread_info.volume = i->volume; + i->thread_info.muted = i->muted; - i->ref++; - return i; + if (i->state == PA_SINK_INPUT_CORKED) + i->sink->n_corked++; + + pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL); + pa_sink_update_status(i->sink); + + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index); + pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i); + + /* Please note that if you change something here, you have to + change something in pa_sink_input_move() with the ghost stream + registration too. */ } void pa_sink_input_kill(pa_sink_input*i) { - assert(i); - assert(i->ref >= 1); + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->state)); if (i->kill) i->kill(i); @@ -264,108 +380,127 @@ void pa_sink_input_kill(pa_sink_input*i) { pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) { pa_usec_t r = 0; - assert(i); - assert(i->ref >= 1); + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->state)); + + if (pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, &r, 0, NULL) < 0) + r = 0; if (i->get_latency) r += i->get_latency(i); - if (i->resampled_chunk.memblock) - r += pa_bytes_to_usec(i->resampled_chunk.length, &i->sink->sample_spec); - - if (i->move_silence) - r += pa_bytes_to_usec(i->move_silence, &i->sink->sample_spec); - return r; } -int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) { +/* Called from thread context */ +int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_cvolume *volume) { int ret = -1; int do_volume_adj_here; int volume_is_norm; + size_t block_size_max; - assert(i); - assert(i->ref >= 1); - assert(chunk); - assert(volume); + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state)); + pa_assert(pa_frame_aligned(length, &i->sink->sample_spec)); + pa_assert(chunk); + pa_assert(volume); - pa_sink_input_ref(i); - - if (!i->peek || !i->drop || i->state == PA_SINK_INPUT_CORKED) + if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_CORKED) goto finish; - assert(i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED); + pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING || i->thread_info.state == PA_SINK_INPUT_DRAINED); - if (i->move_silence > 0) { + /* Default buffer size */ + if (length <= 0) + length = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec); + + /* Make sure the buffer fits in the mempool tile */ + block_size_max = pa_mempool_block_size_max(i->sink->core->mempool); + if (length > block_size_max) + length = pa_frame_align(block_size_max, &i->sink->sample_spec); + + if (i->thread_info.move_silence > 0) { + size_t l; /* We have just been moved and shall play some silence for a * while until the old sink has drained its playback buffer */ - if (!i->silence_memblock) - i->silence_memblock = pa_silence_memblock_new(i->sink->core->mempool, &i->sink->sample_spec, SILENCE_BUFFER_LENGTH); + if (!i->thread_info.silence_memblock) + i->thread_info.silence_memblock = pa_silence_memblock_new( + i->sink->core->mempool, + &i->sink->sample_spec, + pa_frame_align(SILENCE_BUFFER_LENGTH, &i->sink->sample_spec)); - chunk->memblock = pa_memblock_ref(i->silence_memblock); + chunk->memblock = pa_memblock_ref(i->thread_info.silence_memblock); chunk->index = 0; - chunk->length = i->move_silence < chunk->memblock->length ? i->move_silence : chunk->memblock->length; + l = pa_memblock_get_length(chunk->memblock); + chunk->length = i->thread_info.move_silence < l ? i->thread_info.move_silence : l; ret = 0; do_volume_adj_here = 1; goto finish; } - if (!i->resampler) { - do_volume_adj_here = 0; - ret = i->peek(i, chunk); + if (!i->thread_info.resampler) { + do_volume_adj_here = 0; /* FIXME??? */ + ret = i->peek(i, length, chunk); goto finish; } do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map); - volume_is_norm = pa_cvolume_is_norm(&i->volume); + volume_is_norm = pa_cvolume_is_norm(&i->thread_info.volume) && !i->thread_info.muted; - while (!i->resampled_chunk.memblock) { + while (!i->thread_info.resampled_chunk.memblock) { pa_memchunk tchunk; - size_t l; + size_t l, rmbs; - if ((ret = i->peek(i, &tchunk)) < 0) + l = pa_resampler_request(i->thread_info.resampler, length); + + if (l <= 0) + l = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec); + + rmbs = pa_resampler_max_block_size(i->thread_info.resampler); + if (l > rmbs) + l = rmbs; + + if ((ret = i->peek(i, l, &tchunk)) < 0) goto finish; - assert(tchunk.length); + pa_assert(tchunk.length > 0); - l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH); + if (tchunk.length > l) + tchunk.length = l; - if (l > tchunk.length) - l = tchunk.length; - - i->drop(i, &tchunk, l); - tchunk.length = l; + i->drop(i, tchunk.length); /* It might be necessary to adjust the volume here */ if (do_volume_adj_here && !volume_is_norm) { pa_memchunk_make_writable(&tchunk, 0); - pa_volume_memchunk(&tchunk, &i->sample_spec, &i->volume); + + if (i->thread_info.muted) + pa_silence_memchunk(&tchunk, &i->thread_info.sample_spec); + else + pa_volume_memchunk(&tchunk, &i->thread_info.sample_spec, &i->thread_info.volume); } - pa_resampler_run(i->resampler, &tchunk, &i->resampled_chunk); + pa_resampler_run(i->thread_info.resampler, &tchunk, &i->thread_info.resampled_chunk); pa_memblock_unref(tchunk.memblock); } - assert(i->resampled_chunk.memblock); - assert(i->resampled_chunk.length); + pa_assert(i->thread_info.resampled_chunk.memblock); + pa_assert(i->thread_info.resampled_chunk.length > 0); - *chunk = i->resampled_chunk; - pa_memblock_ref(i->resampled_chunk.memblock); + *chunk = i->thread_info.resampled_chunk; + pa_memblock_ref(i->thread_info.resampled_chunk.memblock); ret = 0; finish: - if (ret < 0 && i->state == PA_SINK_INPUT_RUNNING && i->underrun) - i->underrun(i); - if (ret >= 0) - i->state = PA_SINK_INPUT_RUNNING; - else if (ret < 0 && i->state == PA_SINK_INPUT_RUNNING) - i->state = PA_SINK_INPUT_DRAINED; + pa_atomic_store(&i->thread_info.drained, 0); + else if (ret < 0) + pa_atomic_store(&i->thread_info.drained, 1); if (ret >= 0) { /* Let's see if we had to apply the volume adjustment @@ -374,120 +509,179 @@ finish: if (do_volume_adj_here) /* We had different channel maps, so we already did the adjustment */ pa_cvolume_reset(volume, i->sink->sample_spec.channels); - else + else if (i->thread_info.muted) /* We've both the same channel map, so let's have the sink do the adjustment for us*/ - *volume = i->volume; + pa_cvolume_mute(volume, i->sink->sample_spec.channels); + else + *volume = i->thread_info.volume; } - pa_sink_input_unref(i); - return ret; } -void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { - assert(i); - assert(i->ref >= 1); - assert(length > 0); +/* Called from thread context */ +void pa_sink_input_drop(pa_sink_input *i, size_t length) { + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state)); + pa_assert(pa_frame_aligned(length, &i->sink->sample_spec)); + pa_assert(length > 0); - if (i->move_silence > 0) { + if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_CORKED) + return; - if (chunk) { - - if (chunk->memblock != i->silence_memblock || - chunk->index != 0 || - (chunk->memblock && (chunk->length != (i->silence_memblock->length < i->move_silence ? i->silence_memblock->length : i->move_silence)))) - return; + if (i->thread_info.move_silence > 0) { + if (i->thread_info.move_silence >= length) { + i->thread_info.move_silence -= length; + length = 0; + } else { + length -= i->thread_info.move_silence; + i->thread_info.move_silence = 0; } - assert(i->move_silence >= length); - - i->move_silence -= length; - - if (i->move_silence <= 0) { - assert(i->silence_memblock); - pa_memblock_unref(i->silence_memblock); - i->silence_memblock = NULL; + if (i->thread_info.move_silence <= 0) { + if (i->thread_info.silence_memblock) { + pa_memblock_unref(i->thread_info.silence_memblock); + i->thread_info.silence_memblock = NULL; + } } - return; + if (length <= 0) + return; } - if (!i->resampler) { - if (i->drop) - i->drop(i, chunk, length); - return; + if (i->thread_info.resampled_chunk.memblock) { + size_t l = length; + + if (l > i->thread_info.resampled_chunk.length) + l = i->thread_info.resampled_chunk.length; + + i->thread_info.resampled_chunk.index += l; + i->thread_info.resampled_chunk.length -= l; + + if (i->thread_info.resampled_chunk.length <= 0) { + pa_memblock_unref(i->thread_info.resampled_chunk.memblock); + pa_memchunk_reset(&i->thread_info.resampled_chunk); + } + + length -= l; } - assert(i->resampled_chunk.memblock); - assert(i->resampled_chunk.length >= length); + if (length > 0) { - i->resampled_chunk.index += length; - i->resampled_chunk.length -= length; + if (i->thread_info.resampler) { + /* So, we have a resampler. To avoid discontinuities we + * have to actually read all data that could be read and + * pass it through the resampler. */ - if (i->resampled_chunk.length <= 0) { - pa_memblock_unref(i->resampled_chunk.memblock); - i->resampled_chunk.memblock = NULL; - i->resampled_chunk.index = i->resampled_chunk.length = 0; + while (length > 0) { + pa_memchunk chunk; + pa_cvolume volume; + + if (pa_sink_input_peek(i, length, &chunk, &volume) >= 0) { + size_t l; + + pa_memblock_unref(chunk.memblock); + + l = chunk.length; + if (l > length) + l = length; + + pa_sink_input_drop(i, l); + length -= l; + + } else { + size_t l; + + l = pa_resampler_request(i->thread_info.resampler, length); + + /* Hmmm, peeking failed, so let's at least drop + * the right amount of data */ + + if (l > 0) + if (i->drop) + i->drop(i, l); + + break; + } + } + + } else { + + /* We have no resampler, hence let's just drop the data */ + + if (i->drop) + i->drop(i, length); + } } } void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) { - assert(i); - assert(i->ref >= 1); - assert(i->sink); - assert(i->sink->core); + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->state)); if (pa_cvolume_equal(&i->volume, volume)) return; i->volume = *volume; + + pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree); pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); } -const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i) { - assert(i); - assert(i->ref >= 1); +const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) { + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->state)); return &i->volume; } -void pa_sink_input_cork(pa_sink_input *i, int b) { - int n; +void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute) { + pa_assert(i); + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->state)); - assert(i); - assert(i->ref >= 1); - - assert(i->state != PA_SINK_INPUT_DISCONNECTED); - - n = i->state == PA_SINK_INPUT_CORKED && !b; - - if (b) - i->state = PA_SINK_INPUT_CORKED; - else if (i->state == PA_SINK_INPUT_CORKED) - i->state = PA_SINK_INPUT_DRAINED; - - if (n) - pa_sink_notify(i->sink); -} - -void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) { - assert(i); - assert(i->resampler); - assert(i->ref >= 1); - - if (i->sample_spec.rate == rate) + if (!i->muted == !mute) return; - i->sample_spec.rate = rate; - pa_resampler_set_input_rate(i->resampler, rate); + i->muted = mute; + pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 0, NULL, NULL); pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); } +int pa_sink_input_get_mute(pa_sink_input *i) { + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->state)); + + return !!i->muted; +} + +void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) { + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->state)); + + sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING); +} + +int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) { + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->state)); + pa_return_val_if_fail(i->thread_info.resampler, -1); + + if (i->sample_spec.rate == rate) + return 0; + + i->sample_spec.rate = rate; + + pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL); + + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); + return 0; +} + void pa_sink_input_set_name(pa_sink_input *i, const char *name) { - assert(i); - assert(i->ref >= 1); + pa_sink_input_assert_ref(i); if (!i->name && !name) return; @@ -498,47 +692,56 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name) { pa_xfree(i->name); i->name = pa_xstrdup(name); - pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); + if (PA_SINK_INPUT_LINKED(i->state)) { + pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_NAME_CHANGED], i); + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); + } } pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) { - assert(i); - assert(i->ref >= 1); + pa_sink_input_assert_ref(i); - if (!i->resampler) - return i->resample_method; - - return pa_resampler_get_method(i->resampler); + return i->resample_method; } int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { - pa_resampler *new_resampler = NULL; - pa_memblockq *buffer = NULL; + pa_resampler *new_resampler; pa_sink *origin; + pa_usec_t silence_usec = 0; + pa_sink_input_move_info info; - assert(i); - assert(dest); + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->state)); + pa_sink_assert_ref(dest); origin = i->sink; if (dest == origin) return 0; + if (i->flags & PA_SINK_INPUT_DONT_MOVE) + return -1; + + if (i->sync_next || i->sync_prev) { + pa_log_warn("Moving synchronised streams not supported."); + return -1; + } + if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) { pa_log_warn("Failed to move sink input: too many inputs per sink."); return -1; } - if (i->resampler && + if (i->thread_info.resampler && pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) && pa_channel_map_equal(&origin->channel_map, &dest->channel_map)) /* Try to reuse the old resampler if possible */ - new_resampler = i->resampler; + new_resampler = i->thread_info.resampler; else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) || - !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) || - !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) { + !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) || + !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) { /* Okey, we need a new resampler for the new sink */ @@ -546,20 +749,26 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { dest->core->mempool, &i->sample_spec, &i->channel_map, &dest->sample_spec, &dest->channel_map, - i->resample_method))) { + i->resample_method, + !!(i->flags & PA_SINK_INPUT_VARIABLE_RATE)))) { pa_log_warn("Unsupported resampling operation."); return -1; } - } + } else + new_resampler = NULL; + + pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], i); + + memset(&info, 0, sizeof(info)); + info.sink_input = i; if (!immediately) { pa_usec_t old_latency, new_latency; - pa_usec_t silence_usec = 0; - - buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL); /* Let's do a little bit of Voodoo for compensating latency - * differences */ + * differences. We assume that the accuracy for our + * estimations is still good enough, even though we do these + * operations non-atomic. */ old_latency = pa_sink_get_latency(origin); new_latency = pa_sink_get_latency(dest); @@ -576,8 +785,6 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { silence_usec = old_latency - new_latency; } else { - size_t l; - int volume_is_norm; /* The latency of new sink is larger than the latency of * the old sink. Therefore we have to precompute a little @@ -585,87 +792,164 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { * sink, until we can play the first sample on the new * sink.*/ - l = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec); - - volume_is_norm = pa_cvolume_is_norm(&i->volume); - - while (l > 0) { - pa_memchunk chunk; - pa_cvolume volume; - size_t n; - - if (pa_sink_input_peek(i, &chunk, &volume) < 0) - break; - - n = chunk.length > l ? l : chunk.length; - pa_sink_input_drop(i, &chunk, n); - chunk.length = n; - - if (!volume_is_norm) { - pa_memchunk_make_writable(&chunk, 0); - pa_volume_memchunk(&chunk, &origin->sample_spec, &volume); - } - - if (pa_memblockq_push(buffer, &chunk) < 0) { - pa_memblock_unref(chunk.memblock); - break; - } - - pa_memblock_unref(chunk.memblock); - l -= n; - } + info.buffer_bytes = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec); } - if (i->resampled_chunk.memblock) { + /* Okey, let's move it */ - /* There is still some data left in the already resampled - * memory block. Hence, let's output it on the old sink - * and sleep so long on the new sink */ + if (info.buffer_bytes > 0) { - pa_memblockq_push(buffer, &i->resampled_chunk); - silence_usec += pa_bytes_to_usec(i->resampled_chunk.length, &origin->sample_spec); + info.ghost_sink_input = pa_memblockq_sink_input_new( + origin, + "Ghost Stream", + &origin->sample_spec, + &origin->channel_map, + NULL, + NULL); + + info.ghost_sink_input->thread_info.state = info.ghost_sink_input->state = PA_SINK_INPUT_RUNNING; + info.ghost_sink_input->thread_info.volume = info.ghost_sink_input->volume; + info.ghost_sink_input->thread_info.muted = info.ghost_sink_input->muted; + + info.buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL); } - - /* Calculate the new sleeping time */ - i->move_silence = pa_usec_to_bytes( - pa_bytes_to_usec(i->move_silence, &i->sample_spec) + - silence_usec, - &i->sample_spec); } - /* Okey, let's move it */ + pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, &info, 0, NULL); + + if (info.ghost_sink_input) { + /* Basically, do what pa_sink_input_put() does ...*/ + + pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, info.ghost_sink_input->index); + pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], info.ghost_sink_input); + pa_sink_input_unref(info.ghost_sink_input); + } + pa_idxset_remove_by_data(origin->inputs, i, NULL); pa_idxset_put(dest->inputs, i, NULL); i->sink = dest; + if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED) { + pa_assert_se(origin->n_corked-- >= 1); + dest->n_corked++; + } + /* Replace resampler */ - if (new_resampler != i->resampler) { - if (i->resampler) - pa_resampler_free(i->resampler); - i->resampler = new_resampler; + if (new_resampler != i->thread_info.resampler) { + if (i->thread_info.resampler) + pa_resampler_free(i->thread_info.resampler); + i->thread_info.resampler = new_resampler; /* if the resampler changed, the silence memblock is * probably invalid now, too */ - if (i->silence_memblock) { - pa_memblock_unref(i->silence_memblock); - i->silence_memblock = NULL; + if (i->thread_info.silence_memblock) { + pa_memblock_unref(i->thread_info.silence_memblock); + i->thread_info.silence_memblock = NULL; } } /* Dump already resampled data */ - if (i->resampled_chunk.memblock) { - pa_memblock_unref(i->resampled_chunk.memblock); - i->resampled_chunk.memblock = NULL; - i->resampled_chunk.index = i->resampled_chunk.length = 0; + if (i->thread_info.resampled_chunk.memblock) { + /* Hmm, this data has already been added to the ghost queue, presumably, hence let's sleep a little bit longer */ + silence_usec += pa_bytes_to_usec(i->thread_info.resampled_chunk.length, &origin->sample_spec); + pa_memblock_unref(i->thread_info.resampled_chunk.memblock); + pa_memchunk_reset(&i->thread_info.resampled_chunk); } + /* Calculate the new sleeping time */ + if (immediately) + i->thread_info.move_silence = 0; + else + i->thread_info.move_silence = pa_usec_to_bytes( + pa_bytes_to_usec(i->thread_info.move_silence, &origin->sample_spec) + + silence_usec, + &dest->sample_spec); + + pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL); + + pa_sink_update_status(origin); + pa_sink_update_status(dest); + + pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_POST], i); + + pa_log_debug("Successfully moved sink input %i from %s to %s.", i->index, origin->name, dest->name); + /* Notify everyone */ pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); - pa_sink_notify(i->sink); - - /* Ok, no let's feed the precomputed buffer to the old sink */ - if (buffer) - pa_play_memblockq(origin, "Ghost Stream", &origin->sample_spec, &origin->channel_map, buffer, NULL); return 0; } + +/* Called from thread context */ +int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { + pa_sink_input *i = PA_SINK_INPUT(o); + + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state)); + + switch (code) { + case PA_SINK_INPUT_MESSAGE_SET_VOLUME: + i->thread_info.volume = *((pa_cvolume*) userdata); + return 0; + + case PA_SINK_INPUT_MESSAGE_SET_MUTE: + i->thread_info.muted = PA_PTR_TO_UINT(userdata); + return 0; + + case PA_SINK_INPUT_MESSAGE_GET_LATENCY: { + pa_usec_t *r = userdata; + + if (i->thread_info.resampled_chunk.memblock) + *r += pa_bytes_to_usec(i->thread_info.resampled_chunk.length, &i->sink->sample_spec); + + if (i->thread_info.move_silence) + *r += pa_bytes_to_usec(i->thread_info.move_silence, &i->sink->sample_spec); + + return 0; + } + + case PA_SINK_INPUT_MESSAGE_SET_RATE: + + i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata); + pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata)); + + return 0; + + case PA_SINK_INPUT_MESSAGE_SET_STATE: { + pa_sink_input *ssync; + + if ((PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_DRAINED || PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_RUNNING) && + (i->thread_info.state != PA_SINK_INPUT_DRAINED) && (i->thread_info.state != PA_SINK_INPUT_RUNNING)) + pa_atomic_store(&i->thread_info.drained, 1); + + i->thread_info.state = PA_PTR_TO_UINT(userdata); + + for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev) { + if ((PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_DRAINED || PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_RUNNING) && + (ssync->thread_info.state != PA_SINK_INPUT_DRAINED) && (ssync->thread_info.state != PA_SINK_INPUT_RUNNING)) + pa_atomic_store(&ssync->thread_info.drained, 1); + ssync->thread_info.state = PA_PTR_TO_UINT(userdata); + } + + for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next) { + if ((PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_DRAINED || PA_PTR_TO_UINT(userdata) == PA_SINK_INPUT_RUNNING) && + (ssync->thread_info.state != PA_SINK_INPUT_DRAINED) && (ssync->thread_info.state != PA_SINK_INPUT_RUNNING)) + pa_atomic_store(&ssync->thread_info.drained, 1); + ssync->thread_info.state = PA_PTR_TO_UINT(userdata); + } + + return 0; + } + } + + return -1; +} + +pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) { + pa_sink_input_assert_ref(i); + + if (i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED) + return pa_atomic_load(&i->thread_info.drained) ? PA_SINK_INPUT_DRAINED : PA_SINK_INPUT_RUNNING; + + return i->state; +} diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 51d9ec788..3f8e20390 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -1,5 +1,5 @@ -#ifndef foosinkinputhfoo -#define foosinkinputhfoo +#ifndef foopulsesinkinputhfoo +#define foopulsesinkinputhfoo /* $Id$ */ @@ -39,20 +39,32 @@ typedef struct pa_sink_input pa_sink_input; #include typedef enum pa_sink_input_state { - PA_SINK_INPUT_RUNNING, /*< The stream is alive and kicking */ + PA_SINK_INPUT_INIT, /*< The stream is not active yet, because pa_sink_put() has not been called yet */ PA_SINK_INPUT_DRAINED, /*< The stream stopped playing because there was no data to play */ + PA_SINK_INPUT_RUNNING, /*< The stream is alive and kicking */ PA_SINK_INPUT_CORKED, /*< The stream was corked on user request */ - PA_SINK_INPUT_DISCONNECTED /*< The stream is dead */ + PA_SINK_INPUT_UNLINKED /*< The stream is dead */ } pa_sink_input_state_t; +static inline pa_bool_t PA_SINK_INPUT_LINKED(pa_sink_input_state_t x) { + return x == PA_SINK_INPUT_DRAINED || x == PA_SINK_INPUT_RUNNING || x == PA_SINK_INPUT_CORKED; +} + typedef enum pa_sink_input_flags { PA_SINK_INPUT_VARIABLE_RATE = 1, - PA_SINK_INPUT_NO_HOOKS = 2 + PA_SINK_INPUT_DONT_MOVE = 2, + PA_SINK_INPUT_START_CORKED = 4 } pa_sink_input_flags_t; struct pa_sink_input { - int ref; + pa_msgobject parent; + uint32_t index; + pa_core *core; + + /* Please note that this state should only be read with + * pa_sink_input_get_state(). That function will transparently + * merge the thread_info.drained value in. */ pa_sink_input_state_t state; pa_sink_input_flags_t flags; @@ -64,27 +76,87 @@ struct pa_sink_input { pa_sample_spec sample_spec; pa_channel_map channel_map; + + pa_sink_input *sync_prev, *sync_next; + pa_cvolume volume; + pa_bool_t muted; - /* Some silence to play before the actual data. This is used to - * compensate for latency differences when moving a sink input - * "hot" between sinks. */ - size_t move_silence; + /* Returns the chunk of audio data (but doesn't drop it + * yet!). Returns -1 on failure. Called from IO thread context. If + * data needs to be generated from scratch then please in the + * specified length. This is an optimization only. If less data is + * available, it's fine to return a smaller block. If more data is + * already ready, it is better to return the full block.*/ + int (*peek) (pa_sink_input *i, size_t length, pa_memchunk *chunk); - int (*peek) (pa_sink_input *i, pa_memchunk *chunk); - void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length); + /* Drops the specified number of bytes, usually called right after + * peek(), but not necessarily. Called from IO thread context. */ + void (*drop) (pa_sink_input *i, size_t length); + + /* If non-NULL this function is called when the input is first + * connected to a sink or when the rtpoll/asyncmsgq fields + * change. You usually don't need to implement this function + * unless you rewrite a sink that is piggy-backed onto + * another. Called from IO thread context */ + void (*attach) (pa_sink_input *i); /* may be NULL */ + + /* If non-NULL this function is called when the output is + * disconnected from its sink. Called from IO thread context */ + void (*detach) (pa_sink_input *i); /* may be NULL */ + + /* If non-NULL called whenever the the sink this input is attached + * to suspends or resumes. Called from main context */ + void (*suspend) (pa_sink_input *i, int b); /* may be NULL */ + + /* Supposed to unlink and destroy this stream. Called from main + * context. */ void (*kill) (pa_sink_input *i); /* may be NULL */ + + /* Return the current latency (i.e. length of bufferd audio) of + this stream. Called from main context. If NULL a + PA_SINK_INPUT_MESSAGE_GET_LATENCY message is sent to the IO thread + instead. */ pa_usec_t (*get_latency) (pa_sink_input *i); /* may be NULL */ - void (*underrun) (pa_sink_input *i); /* may be NULL */ - - void *userdata; - - pa_memchunk resampled_chunk; - pa_resampler *resampler; /* may be NULL */ pa_resample_method_t resample_method; - pa_memblock *silence_memblock; /* may be NULL */ + struct { + pa_sink_input_state_t state; + pa_atomic_t drained; + + pa_bool_t attached; /* True only between ->attach() and ->detach() calls */ + + pa_sample_spec sample_spec; + + pa_memchunk resampled_chunk; + pa_resampler *resampler; /* may be NULL */ + + /* Some silence to play before the actual data. This is used to + * compensate for latency differences when moving a sink input + * "hot" between sinks. */ + size_t move_silence; + pa_memblock *silence_memblock; /* may be NULL */ + + pa_sink_input *sync_prev, *sync_next; + + pa_cvolume volume; + pa_bool_t muted; + } thread_info; + + void *userdata; +}; + +PA_DECLARE_CLASS(pa_sink_input); +#define PA_SINK_INPUT(o) pa_sink_input_cast(o) + +enum { + PA_SINK_INPUT_MESSAGE_SET_VOLUME, + PA_SINK_INPUT_MESSAGE_SET_MUTE, + PA_SINK_INPUT_MESSAGE_GET_LATENCY, + PA_SINK_INPUT_MESSAGE_SET_RATE, + PA_SINK_INPUT_MESSAGE_SET_STATE, + PA_SINK_INPUT_MESSAGE_MAX }; typedef struct pa_sink_input_new_data { @@ -95,50 +167,71 @@ typedef struct pa_sink_input_new_data { pa_sink *sink; pa_sample_spec sample_spec; - int sample_spec_is_set; + pa_bool_t sample_spec_is_set; pa_channel_map channel_map; - int channel_map_is_set; + pa_bool_t channel_map_is_set; + pa_cvolume volume; - int volume_is_set; + pa_bool_t volume_is_set; + pa_bool_t muted; + pa_bool_t muted_is_set; pa_resample_method_t resample_method; + + pa_sink_input *sync_base; } pa_sink_input_new_data; pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data); void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec); void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map); void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume); +void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute); + +/* To be called by the implementing module only */ pa_sink_input* pa_sink_input_new( pa_core *core, pa_sink_input_new_data *data, pa_sink_input_flags_t flags); -void pa_sink_input_unref(pa_sink_input* i); -pa_sink_input* pa_sink_input_ref(pa_sink_input* i); +void pa_sink_input_put(pa_sink_input *i); +void pa_sink_input_unlink(pa_sink_input* i); -/* To be called by the implementing module only */ -void pa_sink_input_disconnect(pa_sink_input* i); +void pa_sink_input_set_name(pa_sink_input *i, const char *name); -/* External code may request disconnection with this funcion */ +/* Callable by everyone */ + +/* External code may request disconnection with this function */ void pa_sink_input_kill(pa_sink_input*i); pa_usec_t pa_sink_input_get_latency(pa_sink_input *i); -int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume); -void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length); - void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume); -const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i); +const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i); +void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute); +int pa_sink_input_get_mute(pa_sink_input *i); -void pa_sink_input_cork(pa_sink_input *i, int b); +void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b); -void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate); - -void pa_sink_input_set_name(pa_sink_input *i, const char *name); +int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate); pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i); int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately); +pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i); + +/* To be used exclusively by the sink driver thread */ + +int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_cvolume *volume); +void pa_sink_input_drop(pa_sink_input *i, size_t length); +int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk); + +typedef struct pa_sink_input_move_info { + pa_sink_input *sink_input; + pa_sink_input *ghost_sink_input; + pa_memblockq *buffer; + size_t buffer_bytes; +} pa_sink_input_move_info; + #endif diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 9588c2c3d..dccb34cc0 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include @@ -41,16 +40,18 @@ #include #include #include +#include +#include #include "sink.h" #define MAX_MIX_CHANNELS 32 +#define MIX_BUFFER_LENGTH (PA_PAGE_SIZE) +#define SILENCE_BUFFER_LENGTH (PA_PAGE_SIZE*12) -#define CHECK_VALIDITY_RETURN_NULL(condition) \ -do {\ -if (!(condition)) \ - return NULL; \ -} while (0) +static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject); + +static void sink_free(pa_object *s); pa_sink* pa_sink_new( pa_core *core, @@ -63,68 +64,71 @@ pa_sink* pa_sink_new( pa_sink *s; char *n = NULL; char st[256]; - int r; pa_channel_map tmap; - assert(core); - assert(name); - assert(spec); + pa_assert(core); + pa_assert(name); + pa_assert(spec); - CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + pa_return_null_if_fail(pa_sample_spec_valid(spec)); if (!map) map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); - CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); - CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); - CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); - CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name) && *name); + pa_return_null_if_fail(map && pa_channel_map_valid(map)); + pa_return_null_if_fail(map->channels == spec->channels); + pa_return_null_if_fail(!driver || pa_utf8_valid(driver)); + pa_return_null_if_fail(name && pa_utf8_valid(name) && *name); - s = pa_xnew(pa_sink, 1); + s = pa_msgobject_new(pa_sink); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) { pa_xfree(s); return NULL; } - s->ref = 1; + s->parent.parent.free = sink_free; + s->parent.process_msg = pa_sink_process_msg; + s->core = core; - s->state = PA_SINK_RUNNING; + s->state = PA_SINK_INIT; + s->flags = 0; s->name = pa_xstrdup(name); s->description = NULL; s->driver = pa_xstrdup(driver); - s->owner = NULL; + s->module = NULL; s->sample_spec = *spec; s->channel_map = *map; s->inputs = pa_idxset_new(NULL, NULL); + s->n_corked = 0; - pa_cvolume_reset(&s->sw_volume, spec->channels); - pa_cvolume_reset(&s->hw_volume, spec->channels); - s->sw_muted = 0; - s->hw_muted = 0; - - s->is_hardware = 0; + pa_cvolume_reset(&s->volume, spec->channels); + s->muted = FALSE; + s->refresh_volume = s->refresh_mute = FALSE; s->get_latency = NULL; - s->notify = NULL; - s->set_hw_volume = NULL; - s->get_hw_volume = NULL; - s->set_hw_mute = NULL; - s->get_hw_mute = NULL; + s->set_volume = NULL; + s->get_volume = NULL; + s->set_mute = NULL; + s->get_mute = NULL; + s->set_state = NULL; s->userdata = NULL; - r = pa_idxset_put(core->sinks, s, &s->index); - assert(s->index != PA_IDXSET_INVALID && r >= 0); + s->asyncmsgq = NULL; + s->rtpoll = NULL; + s->silence = NULL; + + pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); + pa_log_info("Created sink %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); n = pa_sprintf_malloc("%s.monitor", name); if (!(s->monitor_source = pa_source_new(core, driver, n, 0, spec, map))) - pa_log_warn("failed to create monitor source."); + pa_log_warn("Failed to create monitor source."); else { char *d; s->monitor_source->monitor_of = s; @@ -135,51 +139,124 @@ pa_sink* pa_sink_new( pa_xfree(n); - pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); + s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + s->thread_info.soft_volume = s->volume; + s->thread_info.soft_muted = s->muted; + s->thread_info.state = s->state; return s; } -void pa_sink_disconnect(pa_sink* s) { +static int sink_set_state(pa_sink *s, pa_sink_state_t state) { + int ret; + + pa_assert(s); + + if (s->state == state) + return 0; + + if ((s->state == PA_SINK_SUSPENDED && PA_SINK_OPENED(state)) || + (PA_SINK_OPENED(s->state) && state == PA_SINK_SUSPENDED)) { + pa_sink_input *i; + uint32_t idx; + + /* We're suspending or resuming, tell everyone about it */ + + for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) + if (i->suspend) + i->suspend(i, state == PA_SINK_SUSPENDED); + } + + if (s->set_state) + if ((ret = s->set_state(s, state)) < 0) + return -1; + + if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0) + return -1; + + s->state = state; + + if (state != PA_SINK_UNLINKED) /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */ + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s); + return 0; +} + +void pa_sink_put(pa_sink* s) { + pa_sink_assert_ref(s); + + pa_assert(s->state == PA_SINK_INIT); + pa_assert(s->asyncmsgq); + pa_assert(s->rtpoll); + + pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0); + + pa_source_put(s->monitor_source); + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_NEW_POST], s); +} + +void pa_sink_unlink(pa_sink* s) { + pa_bool_t linked; pa_sink_input *i, *j = NULL; - assert(s); - assert(s->state == PA_SINK_RUNNING); + pa_assert(s); - s->state = PA_SINK_DISCONNECTED; - pa_namereg_unregister(s->core, s->name); + /* Please note that pa_sink_unlink() does more than simply + * reversing pa_sink_put(). It also undoes the registrations + * already done in pa_sink_new()! */ - pa_hook_fire(&s->core->hook_sink_disconnect, s); + /* All operations here shall be idempotent, i.e. pa_sink_unlink() + * may be called multiple times on the same sink without bad + * effects. */ + + linked = PA_SINK_LINKED(s->state); + + if (linked) + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s); + + if (s->state != PA_SINK_UNLINKED) + pa_namereg_unregister(s->core, s->name); + pa_idxset_remove_by_data(s->core->sinks, s, NULL); while ((i = pa_idxset_first(s->inputs, NULL))) { - assert(i != j); + pa_assert(i != j); pa_sink_input_kill(i); j = i; } - if (s->monitor_source) - pa_source_disconnect(s->monitor_source); - - pa_idxset_remove_by_data(s->core->sinks, s, NULL); + if (linked) + sink_set_state(s, PA_SINK_UNLINKED); + else + s->state = PA_SINK_UNLINKED; s->get_latency = NULL; - s->notify = NULL; - s->get_hw_volume = NULL; - s->set_hw_volume = NULL; - s->set_hw_mute = NULL; - s->get_hw_mute = NULL; + s->get_volume = NULL; + s->set_volume = NULL; + s->set_mute = NULL; + s->get_mute = NULL; + s->set_state = NULL; - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + if (s->monitor_source) + pa_source_unlink(s->monitor_source); + + if (linked) { + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s); + } } -static void sink_free(pa_sink *s) { - assert(s); - assert(!s->ref); +static void sink_free(pa_object *o) { + pa_sink *s = PA_SINK(o); + pa_sink_input *i; - if (s->state != PA_SINK_DISCONNECTED) - pa_sink_disconnect(s); + pa_assert(s); + pa_assert(pa_sink_refcnt(s) == 0); - pa_log_info("freed %u \"%s\"", s->index, s->name); + if (PA_SINK_LINKED(s->state)) + pa_sink_unlink(s); + + pa_log_info("Freeing sink %u \"%s\"", s->index, s->name); if (s->monitor_source) { pa_source_unref(s->monitor_source); @@ -188,108 +265,192 @@ static void sink_free(pa_sink *s) { pa_idxset_free(s->inputs, NULL, NULL); + while ((i = pa_hashmap_steal_first(s->thread_info.inputs))) + pa_sink_input_unref(i); + + pa_hashmap_free(s->thread_info.inputs, NULL, NULL); + + if (s->silence) + pa_memblock_unref(s->silence); + pa_xfree(s->name); pa_xfree(s->description); pa_xfree(s->driver); pa_xfree(s); } -void pa_sink_unref(pa_sink*s) { - assert(s); - assert(s->ref >= 1); +void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) { + pa_sink_assert_ref(s); + pa_assert(q); - if (!(--s->ref)) - sink_free(s); + s->asyncmsgq = q; + + if (s->monitor_source) + pa_source_set_asyncmsgq(s->monitor_source, q); } -pa_sink* pa_sink_ref(pa_sink *s) { - assert(s); - assert(s->ref >= 1); +void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) { + pa_sink_assert_ref(s); + pa_assert(p); - s->ref++; - return s; + s->rtpoll = p; + if (s->monitor_source) + pa_source_set_rtpoll(s->monitor_source, p); } -void pa_sink_notify(pa_sink*s) { - assert(s); - assert(s->ref >= 1); +int pa_sink_update_status(pa_sink*s) { + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); - if (s->notify) - s->notify(s); + if (s->state == PA_SINK_SUSPENDED) + return 0; + + return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE); } -static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) { - uint32_t idx = PA_IDXSET_INVALID; +int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) { + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); + + if (suspend) + return sink_set_state(s, PA_SINK_SUSPENDED); + else + return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE); +} + +void pa_sink_ping(pa_sink *s) { + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); + + pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_PING, NULL, 0, NULL, NULL); +} + +static unsigned fill_mix_info(pa_sink *s, size_t length, pa_mix_info *info, unsigned maxinfo) { pa_sink_input *i; unsigned n = 0; + void *state = NULL; - assert(s); - assert(s->ref >= 1); - assert(info); + pa_sink_assert_ref(s); + pa_assert(info); - for (i = pa_idxset_first(s->inputs, &idx); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &idx)) { - /* Increase ref counter, to make sure that this input doesn't - * vanish while we still need it */ - pa_sink_input_ref(i); + while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) { + pa_sink_input_assert_ref(i); - if (pa_sink_input_peek(i, &info->chunk, &info->volume) < 0) { - pa_sink_input_unref(i); + if (pa_sink_input_peek(i, length, &info->chunk, &info->volume) < 0) continue; - } - info->userdata = i; + info->userdata = pa_sink_input_ref(i); - assert(info->chunk.memblock); - assert(info->chunk.memblock->data); - assert(info->chunk.length); + pa_assert(info->chunk.memblock); + pa_assert(info->chunk.length > 0); info++; - maxinfo--; n++; + maxinfo--; } return n; } -static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t length) { - assert(s); - assert(s->ref >= 1); - assert(info); +static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length) { + pa_sink_input *i; + void *state = NULL; + unsigned p = 0; + unsigned n_unreffed = 0; - for (; maxinfo > 0; maxinfo--, info++) { - pa_sink_input *i = info->userdata; + pa_sink_assert_ref(s); - assert(i); - assert(info->chunk.memblock); + /* We optimize for the case where the order of the inputs has not changed */ + + while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) { + unsigned j; + pa_mix_info* m; + + pa_sink_input_assert_ref(i); + + m = NULL; + + /* Let's try to find the matching entry info the pa_mix_info array */ + for (j = 0; j < n; j ++) { + + if (info[p].userdata == i) { + m = info + p; + break; + } + + p++; + if (p >= n) + p = 0; + } /* Drop read data */ - pa_sink_input_drop(i, &info->chunk, length); - pa_memblock_unref(info->chunk.memblock); + pa_sink_input_drop(i, length); - /* Decrease ref counter */ - pa_sink_input_unref(i); - info->userdata = NULL; + if (m) { + pa_sink_input_unref(m->userdata); + m->userdata = NULL; + if (m->chunk.memblock) + pa_memblock_unref(m->chunk.memblock); + pa_memchunk_reset(&m->chunk); + + n_unreffed += 1; + } + } + + /* Now drop references to entries that are included in the + * pa_mix_info array but don't exist anymore */ + + if (n_unreffed < n) { + for (; n > 0; info++, n--) { + if (info->userdata) + pa_sink_input_unref(info->userdata); + if (info->chunk.memblock) + pa_memblock_unref(info->chunk.memblock); + } } } -int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { +void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; - int r = -1; + size_t block_size_max; - assert(s); - assert(s->ref >= 1); - assert(length); - assert(result); + pa_sink_assert_ref(s); + pa_assert(PA_SINK_OPENED(s->thread_info.state)); + pa_assert(pa_frame_aligned(length, &s->sample_spec)); + pa_assert(result); pa_sink_ref(s); - n = fill_mix_info(s, info, MAX_MIX_CHANNELS); + if (length <= 0) + length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec); - if (n <= 0) - goto finish; + block_size_max = pa_mempool_block_size_max(s->core->mempool); + if (length > block_size_max) + length = pa_frame_align(block_size_max, &s->sample_spec); - if (n == 1) { + pa_assert(length > 0); + + n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, length, info, MAX_MIX_CHANNELS) : 0; + + if (n == 0) { + + if (length > SILENCE_BUFFER_LENGTH) + length = pa_frame_align(SILENCE_BUFFER_LENGTH, &s->sample_spec); + + pa_assert(length > 0); + + if (!s->silence || pa_memblock_get_length(s->silence) < length) { + if (s->silence) + pa_memblock_unref(s->silence); + s->silence = pa_silence_memblock_new(s->core->mempool, &s->sample_spec, length); + } + + result->memblock = pa_memblock_ref(s->silence); + result->length = length; + result->index = 0; + + } else if (n == 1) { pa_cvolume volume; *result = info[0].chunk; @@ -298,105 +459,112 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { if (result->length > length) result->length = length; - pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); + pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume); - if (s->sw_muted || !pa_cvolume_is_norm(&volume)) { + if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) { pa_memchunk_make_writable(result, 0); - if (s->sw_muted) + if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) pa_silence_memchunk(result, &s->sample_spec); else pa_volume_memchunk(result, &s->sample_spec, &volume); } } else { + void *ptr; result->memblock = pa_memblock_new(s->core->mempool, length); - assert(result->memblock); -/* pa_log("mixing %i", n); */ + ptr = pa_memblock_acquire(result->memblock); + result->length = pa_mix(info, n, ptr, length, &s->sample_spec, &s->thread_info.soft_volume, s->thread_info.soft_muted); + pa_memblock_release(result->memblock); - result->length = pa_mix(info, n, result->memblock->data, length, - &s->sample_spec, &s->sw_volume, s->sw_muted); result->index = 0; } - inputs_drop(s, info, n, result->length); + if (s->thread_info.state == PA_SINK_RUNNING) + inputs_drop(s, info, n, result->length); - if (s->monitor_source) + if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source))) pa_source_post(s->monitor_source, result); - r = 0; - -finish: pa_sink_unref(s); - - return r; } -int pa_sink_render_into(pa_sink*s, pa_memchunk *target) { +void pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; - int r = -1; - assert(s); - assert(s->ref >= 1); - assert(target); - assert(target->memblock); - assert(target->length); - assert(target->memblock->data); + pa_sink_assert_ref(s); + pa_assert(PA_SINK_OPENED(s->thread_info.state)); + pa_assert(target); + pa_assert(target->memblock); + pa_assert(target->length > 0); + pa_assert(pa_frame_aligned(target->length, &s->sample_spec)); pa_sink_ref(s); - n = fill_mix_info(s, info, MAX_MIX_CHANNELS); - - if (n <= 0) - goto finish; - - if (n == 1) { - pa_cvolume volume; + n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, target->length, info, MAX_MIX_CHANNELS) : 0; + if (n == 0) { + pa_silence_memchunk(target, &s->sample_spec); + } else if (n == 1) { if (target->length > info[0].chunk.length) target->length = info[0].chunk.length; - memcpy((uint8_t*) target->memblock->data + target->index, - (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index, - target->length); - - pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume); - - if (s->sw_muted) + if (s->thread_info.soft_muted) pa_silence_memchunk(target, &s->sample_spec); - else if (!pa_cvolume_is_norm(&volume)) - pa_volume_memchunk(target, &s->sample_spec, &volume); - } else + else { + void *src, *ptr; + pa_cvolume volume; + + ptr = pa_memblock_acquire(target->memblock); + src = pa_memblock_acquire(info[0].chunk.memblock); + + memcpy((uint8_t*) ptr + target->index, + (uint8_t*) src + info[0].chunk.index, + target->length); + + pa_memblock_release(target->memblock); + pa_memblock_release(info[0].chunk.memblock); + + pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume); + + if (!pa_cvolume_is_norm(&volume)) + pa_volume_memchunk(target, &s->sample_spec, &volume); + } + + } else { + void *ptr; + + ptr = pa_memblock_acquire(target->memblock); + target->length = pa_mix(info, n, - (uint8_t*) target->memblock->data + target->index, + (uint8_t*) ptr + target->index, target->length, &s->sample_spec, - &s->sw_volume, - s->sw_muted); + &s->thread_info.soft_volume, + s->thread_info.soft_muted); - inputs_drop(s, info, n, target->length); + pa_memblock_release(target->memblock); + } - if (s->monitor_source) + if (s->thread_info.state == PA_SINK_RUNNING) + inputs_drop(s, info, n, target->length); + + if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source))) pa_source_post(s->monitor_source, target); - r = 0; - -finish: pa_sink_unref(s); - - return r; } void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { pa_memchunk chunk; size_t l, d; - assert(s); - assert(s->ref >= 1); - assert(target); - assert(target->memblock); - assert(target->length); - assert(target->memblock->data); + pa_sink_assert_ref(s); + pa_assert(PA_SINK_OPENED(s->thread_info.state)); + pa_assert(target); + pa_assert(target->memblock); + pa_assert(target->length > 0); + pa_assert(pa_frame_aligned(target->length, &s->sample_spec)); pa_sink_ref(s); @@ -407,140 +575,177 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { chunk.index += d; chunk.length -= d; - if (pa_sink_render_into(s, &chunk) < 0) - break; + pa_sink_render_into(s, &chunk); d += chunk.length; l -= chunk.length; } - if (l > 0) { - chunk = *target; - chunk.index += d; - chunk.length -= d; - pa_silence_memchunk(&chunk, &s->sample_spec); - } - pa_sink_unref(s); } void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { - assert(s); - assert(s->ref >= 1); - assert(length); - assert(result); + pa_sink_assert_ref(s); + pa_assert(PA_SINK_OPENED(s->thread_info.state)); + pa_assert(length > 0); + pa_assert(pa_frame_aligned(length, &s->sample_spec)); + pa_assert(result); /*** This needs optimization ***/ - result->memblock = pa_memblock_new(s->core->mempool, result->length = length); result->index = 0; + result->length = length; + result->memblock = pa_memblock_new(s->core->mempool, length); pa_sink_render_into_full(s, result); } -pa_usec_t pa_sink_get_latency(pa_sink *s) { - assert(s); - assert(s->ref >= 1); +void pa_sink_skip(pa_sink *s, size_t length) { + pa_sink_input *i; + void *state = NULL; - if (!s->get_latency) + pa_sink_assert_ref(s); + pa_assert(PA_SINK_OPENED(s->thread_info.state)); + pa_assert(length > 0); + pa_assert(pa_frame_aligned(length, &s->sample_spec)); + + if (pa_source_used_by(s->monitor_source)) { + pa_memchunk chunk; + + /* If something is connected to our monitor source, we have to + * pass valid data to it */ + + while (length > 0) { + pa_sink_render(s, length, &chunk); + pa_memblock_unref(chunk.memblock); + + pa_assert(chunk.length <= length); + length -= chunk.length; + } + + } else { + /* Ok, noone cares about the rendered data, so let's not even render it */ + + while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) { + pa_sink_input_assert_ref(i); + pa_sink_input_drop(i, length); + } + } +} + +pa_usec_t pa_sink_get_latency(pa_sink *s) { + pa_usec_t usec = 0; + + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); + + if (!PA_SINK_OPENED(s->state)) return 0; - return s->get_latency(s); + if (s->get_latency) + return s->get_latency(s); + + if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0) + return 0; + + return usec; } -void pa_sink_set_owner(pa_sink *s, pa_module *m) { - assert(s); - assert(s->ref >= 1); +void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) { + int changed; - if (s->owner == m) + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); + pa_assert(volume); + + changed = !pa_cvolume_equal(volume, &s->volume); + s->volume = *volume; + + if (s->set_volume && s->set_volume(s) < 0) + s->set_volume = NULL; + + if (!s->set_volume) + pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree); + + if (changed) + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); +} + +const pa_cvolume *pa_sink_get_volume(pa_sink *s) { + struct pa_cvolume old_volume; + + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); + + old_volume = s->volume; + + if (s->get_volume && s->get_volume(s) < 0) + s->get_volume = NULL; + + if (!s->get_volume && s->refresh_volume) + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, &s->volume, 0, NULL); + + if (!pa_cvolume_equal(&old_volume, &s->volume)) + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + + return &s->volume; +} + +void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) { + int changed; + + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); + + changed = s->muted != mute; + s->muted = mute; + + if (s->set_mute && s->set_mute(s) < 0) + s->set_mute = NULL; + + if (!s->set_mute) + pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 0, NULL, NULL); + + if (changed) + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); +} + +pa_bool_t pa_sink_get_mute(pa_sink *s) { + pa_bool_t old_muted; + + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); + + old_muted = s->muted; + + if (s->get_mute && s->get_mute(s) < 0) + s->get_mute = NULL; + + if (!s->get_mute && s->refresh_mute) + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &s->muted, 0, NULL); + + if (old_muted != s->muted) + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + + return s->muted; +} + +void pa_sink_set_module(pa_sink *s, pa_module *m) { + pa_sink_assert_ref(s); + + if (s->module == m) return; - s->owner = m; + s->module = m; if (s->monitor_source) - pa_source_set_owner(s->monitor_source, m); + pa_source_set_module(s->monitor_source, m); pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } -void pa_sink_set_volume(pa_sink *s, pa_mixer_t m, const pa_cvolume *volume) { - pa_cvolume *v; - - assert(s); - assert(s->ref >= 1); - assert(volume); - - if (m == PA_MIXER_HARDWARE && s->set_hw_volume) - v = &s->hw_volume; - else - v = &s->sw_volume; - - if (pa_cvolume_equal(v, volume)) - return; - - *v = *volume; - - if (v == &s->hw_volume) - if (s->set_hw_volume(s) < 0) - s->sw_volume = *volume; - - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); -} - -const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_mixer_t m) { - assert(s); - assert(s->ref >= 1); - - if (m == PA_MIXER_HARDWARE && s->set_hw_volume) { - - if (s->get_hw_volume) - s->get_hw_volume(s); - - return &s->hw_volume; - } else - return &s->sw_volume; -} - -void pa_sink_set_mute(pa_sink *s, pa_mixer_t m, int mute) { - int *t; - - assert(s); - assert(s->ref >= 1); - - if (m == PA_MIXER_HARDWARE && s->set_hw_mute) - t = &s->hw_muted; - else - t = &s->sw_muted; - - if (!!*t == !!mute) - return; - - *t = !!mute; - - if (t == &s->hw_muted) - if (s->set_hw_mute(s) < 0) - s->sw_muted = !!mute; - - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); -} - -int pa_sink_get_mute(pa_sink *s, pa_mixer_t m) { - assert(s); - assert(s->ref >= 1); - - if (m == PA_MIXER_HARDWARE && s->set_hw_mute) { - - if (s->get_hw_mute) - s->get_hw_mute(s); - - return s->hw_muted; - } else - return s->sw_muted; -} - void pa_sink_set_description(pa_sink *s, const char *description) { - assert(s); - assert(s->ref >= 1); + pa_sink_assert_ref(s); if (!description && !s->description) return; @@ -559,19 +764,298 @@ void pa_sink_set_description(pa_sink *s, const char *description) { pa_xfree(n); } - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + if (PA_SINK_LINKED(s->state)) { + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_DESCRIPTION_CHANGED], s); + } +} + +unsigned pa_sink_linked_by(pa_sink *s) { + unsigned ret; + + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); + + ret = pa_idxset_size(s->inputs); + + /* We add in the number of streams connected to us here. Please + * not the asymmmetry to pa_sink_used_by()! */ + + if (s->monitor_source) + ret += pa_source_linked_by(s->monitor_source); + + return ret; } unsigned pa_sink_used_by(pa_sink *s) { unsigned ret; - assert(s); - assert(s->ref >= 1); + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); ret = pa_idxset_size(s->inputs); + pa_assert(ret >= s->n_corked); + ret -= s->n_corked; - if (s->monitor_source) - ret += pa_source_used_by(s->monitor_source); + /* Streams connected to our monitor source do not matter for + * pa_sink_used_by()!.*/ return ret; } + +int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { + pa_sink *s = PA_SINK(o); + pa_sink_assert_ref(s); + pa_assert(s->thread_info.state != PA_SINK_UNLINKED); + + switch ((pa_sink_message_t) code) { + + case PA_SINK_MESSAGE_ADD_INPUT: { + pa_sink_input *i = PA_SINK_INPUT(userdata); + pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i)); + + /* Since the caller sleeps in pa_sink_input_put(), we can + * safely access data outside of thread_info even though + * it is mutable */ + + if ((i->thread_info.sync_prev = i->sync_prev)) { + pa_assert(i->sink == i->thread_info.sync_prev->sink); + pa_assert(i->sync_prev->sync_next == i); + i->thread_info.sync_prev->thread_info.sync_next = i; + } + + if ((i->thread_info.sync_next = i->sync_next)) { + pa_assert(i->sink == i->thread_info.sync_next->sink); + pa_assert(i->sync_next->sync_prev == i); + i->thread_info.sync_next->thread_info.sync_prev = i; + } + + pa_assert(!i->thread_info.attached); + i->thread_info.attached = TRUE; + + if (i->attach) + i->attach(i); + + /* If you change anything here, make sure to change the + * ghost sink input handling a few lines down at + * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */ + + return 0; + } + + case PA_SINK_MESSAGE_REMOVE_INPUT: { + pa_sink_input *i = PA_SINK_INPUT(userdata); + + /* If you change anything here, make sure to change the + * sink input handling a few lines down at + * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */ + + if (i->detach) + i->detach(i); + + pa_assert(i->thread_info.attached); + i->thread_info.attached = FALSE; + + /* Since the caller sleeps in pa_sink_input_unlink(), + * we can safely access data outside of thread_info even + * though it is mutable */ + + pa_assert(!i->thread_info.sync_prev); + pa_assert(!i->thread_info.sync_next); + + if (i->thread_info.sync_prev) { + i->thread_info.sync_prev->thread_info.sync_next = i->thread_info.sync_prev->sync_next; + i->thread_info.sync_prev = NULL; + } + + if (i->thread_info.sync_next) { + i->thread_info.sync_next->thread_info.sync_prev = i->thread_info.sync_next->sync_prev; + i->thread_info.sync_next = NULL; + } + + if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index))) + pa_sink_input_unref(i); + + return 0; + } + + case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: { + pa_sink_input_move_info *info = userdata; + int volume_is_norm; + + /* We don't support moving synchronized streams. */ + pa_assert(!info->sink_input->sync_prev); + pa_assert(!info->sink_input->sync_next); + pa_assert(!info->sink_input->thread_info.sync_next); + pa_assert(!info->sink_input->thread_info.sync_prev); + + if (info->sink_input->detach) + info->sink_input->detach(info->sink_input); + + pa_assert(info->sink_input->thread_info.attached); + info->sink_input->thread_info.attached = FALSE; + + if (info->ghost_sink_input) { + pa_assert(info->buffer_bytes > 0); + pa_assert(info->buffer); + + volume_is_norm = pa_cvolume_is_norm(&info->sink_input->thread_info.volume); + + pa_log_debug("Buffering %lu bytes ...", (unsigned long) info->buffer_bytes); + + while (info->buffer_bytes > 0) { + pa_memchunk memchunk; + pa_cvolume volume; + size_t n; + + if (pa_sink_input_peek(info->sink_input, info->buffer_bytes, &memchunk, &volume) < 0) + break; + + n = memchunk.length > info->buffer_bytes ? info->buffer_bytes : memchunk.length; + pa_sink_input_drop(info->sink_input, n); + memchunk.length = n; + + if (!volume_is_norm) { + pa_memchunk_make_writable(&memchunk, 0); + pa_volume_memchunk(&memchunk, &s->sample_spec, &volume); + } + + if (pa_memblockq_push(info->buffer, &memchunk) < 0) { + pa_memblock_unref(memchunk.memblock); + break; + } + + pa_memblock_unref(memchunk.memblock); + info->buffer_bytes -= n; + } + + /* Add the remaining already resampled chunk to the buffer */ + if (info->sink_input->thread_info.resampled_chunk.memblock) + pa_memblockq_push(info->buffer, &info->sink_input->thread_info.resampled_chunk); + + pa_memblockq_sink_input_set_queue(info->ghost_sink_input, info->buffer); + + pa_log_debug("Buffered %lu bytes ...", (unsigned long) pa_memblockq_get_length(info->buffer)); + } + + /* Let's remove the sink input ...*/ + if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(info->sink_input->index))) + pa_sink_input_unref(info->sink_input); + + /* .. and add the ghost sink input instead */ + if (info->ghost_sink_input) { + pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(info->ghost_sink_input->index), pa_sink_input_ref(info->ghost_sink_input)); + info->ghost_sink_input->thread_info.sync_prev = info->ghost_sink_input->thread_info.sync_next = NULL; + + pa_assert(!info->ghost_sink_input->thread_info.attached); + info->ghost_sink_input->thread_info.attached = TRUE; + + if (info->ghost_sink_input->attach) + info->ghost_sink_input->attach(info->ghost_sink_input); + } + + return 0; + } + + case PA_SINK_MESSAGE_SET_VOLUME: + s->thread_info.soft_volume = *((pa_cvolume*) userdata); + return 0; + + case PA_SINK_MESSAGE_SET_MUTE: + s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata); + return 0; + + case PA_SINK_MESSAGE_GET_VOLUME: + *((pa_cvolume*) userdata) = s->thread_info.soft_volume; + return 0; + + case PA_SINK_MESSAGE_GET_MUTE: + *((pa_bool_t*) userdata) = s->thread_info.soft_muted; + return 0; + + case PA_SINK_MESSAGE_PING: + return 0; + + case PA_SINK_MESSAGE_SET_STATE: + + s->thread_info.state = PA_PTR_TO_UINT(userdata); + return 0; + + case PA_SINK_MESSAGE_DETACH: + + /* We're detaching all our input streams so that the + * asyncmsgq and rtpoll fields can be changed without + * problems */ + pa_sink_detach_within_thread(s); + break; + + case PA_SINK_MESSAGE_ATTACH: + + /* Reattach all streams */ + pa_sink_attach_within_thread(s); + break; + + case PA_SINK_MESSAGE_GET_LATENCY: + case PA_SINK_MESSAGE_MAX: + ; + } + + return -1; +} + +int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) { + pa_sink *sink; + uint32_t idx; + int ret = 0; + + pa_core_assert_ref(c); + + for (sink = PA_SINK(pa_idxset_first(c->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(c->sinks, &idx))) + ret -= pa_sink_suspend(sink, suspend) < 0; + + return ret; +} + +void pa_sink_detach(pa_sink *s) { + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); + + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL); +} + +void pa_sink_attach(pa_sink *s) { + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->state)); + + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL); +} + +void pa_sink_detach_within_thread(pa_sink *s) { + pa_sink_input *i; + void *state = NULL; + + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->thread_info.state)); + + while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) + if (i->detach) + i->detach(i); + + if (s->monitor_source) + pa_source_detach_within_thread(s->monitor_source); +} + +void pa_sink_attach_within_thread(pa_sink *s) { + pa_sink_input *i; + void *state = NULL; + + pa_sink_assert_ref(s); + pa_assert(PA_SINK_LINKED(s->thread_info.state)); + + while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) + if (i->attach) + i->attach(i); + + if (s->monitor_source) + pa_source_attach_within_thread(s->monitor_source); +} diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index ef73f67d2..e9969309b 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -1,5 +1,5 @@ -#ifndef foosinkhfoo -#define foosinkhfoo +#ifndef foopulsesinkhfoo +#define foopulsesinkhfoo /* $Id$ */ @@ -25,87 +25,164 @@ USA. ***/ -#include - typedef struct pa_sink pa_sink; +#include + #include #include #include + #include #include #include #include #include +#include +#include +#include #define PA_MAX_INPUTS_PER_SINK 32 typedef enum pa_sink_state { + PA_SINK_INIT, PA_SINK_RUNNING, - PA_SINK_DISCONNECTED + PA_SINK_SUSPENDED, + PA_SINK_IDLE, + PA_SINK_UNLINKED } pa_sink_state_t; +static inline pa_bool_t PA_SINK_OPENED(pa_sink_state_t x) { + return x == PA_SINK_RUNNING || x == PA_SINK_IDLE; +} + +static inline pa_bool_t PA_SINK_LINKED(pa_sink_state_t x) { + return x == PA_SINK_RUNNING || x == PA_SINK_IDLE || x == PA_SINK_SUSPENDED; +} + struct pa_sink { - int ref; + pa_msgobject parent; + uint32_t index; pa_core *core; pa_sink_state_t state; + pa_sink_flags_t flags; char *name; char *description, *driver; /* may be NULL */ - int is_hardware; - pa_module *owner; /* may be NULL */ + pa_module *module; /* may be NULL */ pa_sample_spec sample_spec; pa_channel_map channel_map; pa_idxset *inputs; - pa_source *monitor_source; /* may be NULL */ + unsigned n_corked; + pa_source *monitor_source; - pa_cvolume hw_volume, sw_volume; - int hw_muted, sw_muted; + pa_cvolume volume; + pa_bool_t muted; + pa_bool_t refresh_volume; + pa_bool_t refresh_mute; - void (*notify)(pa_sink*sink); /* may be NULL */ - pa_usec_t (*get_latency)(pa_sink *s); /* dito */ - int (*set_hw_volume)(pa_sink *s); /* dito */ - int (*get_hw_volume)(pa_sink *s); /* dito */ - int (*set_hw_mute)(pa_sink *s); /* dito */ - int (*get_hw_mute)(pa_sink *s); /* dito */ + int (*set_state)(pa_sink *s, pa_sink_state_t state); /* may be NULL */ + int (*set_volume)(pa_sink *s); /* dito */ + int (*get_volume)(pa_sink *s); /* dito */ + int (*get_mute)(pa_sink *s); /* dito */ + int (*set_mute)(pa_sink *s); /* dito */ + pa_usec_t (*get_latency)(pa_sink *s); /* dito */ + + pa_asyncmsgq *asyncmsgq; + pa_rtpoll *rtpoll; + + /* Contains copies of the above data so that the real-time worker + * thread can work without access locking */ + struct { + pa_sink_state_t state; + pa_hashmap *inputs; + pa_cvolume soft_volume; + pa_bool_t soft_muted; + } thread_info; + + pa_memblock *silence; void *userdata; }; +PA_DECLARE_CLASS(pa_sink); +#define PA_SINK(s) (pa_sink_cast(s)) + +typedef enum pa_sink_message { + PA_SINK_MESSAGE_ADD_INPUT, + PA_SINK_MESSAGE_REMOVE_INPUT, + PA_SINK_MESSAGE_GET_VOLUME, + PA_SINK_MESSAGE_SET_VOLUME, + PA_SINK_MESSAGE_GET_MUTE, + PA_SINK_MESSAGE_SET_MUTE, + PA_SINK_MESSAGE_GET_LATENCY, + PA_SINK_MESSAGE_SET_STATE, + PA_SINK_MESSAGE_PING, + PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, + PA_SINK_MESSAGE_ATTACH, + PA_SINK_MESSAGE_DETACH, + PA_SINK_MESSAGE_MAX +} pa_sink_message_t; + +/* To be called exclusively by the sink driver, from main context */ + pa_sink* pa_sink_new( - pa_core *core, - const char *driver, - const char *name, - int namereg_fail, - const pa_sample_spec *spec, - const pa_channel_map *map); + pa_core *core, + const char *driver, + const char *name, + int namereg_fail, + const pa_sample_spec *spec, + const pa_channel_map *map); -void pa_sink_disconnect(pa_sink* s); -void pa_sink_unref(pa_sink*s); -pa_sink* pa_sink_ref(pa_sink *s); +void pa_sink_put(pa_sink *s); +void pa_sink_unlink(pa_sink* s); -int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result); -void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result); -int pa_sink_render_into(pa_sink*s, pa_memchunk *target); -void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target); +void pa_sink_set_module(pa_sink *sink, pa_module *m); +void pa_sink_set_description(pa_sink *s, const char *description); +void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q); +void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p); + +void pa_sink_detach(pa_sink *s); +void pa_sink_attach(pa_sink *s); + +/* May be called by everyone, from main context */ pa_usec_t pa_sink_get_latency(pa_sink *s); -void pa_sink_notify(pa_sink*s); +int pa_sink_update_status(pa_sink*s); +int pa_sink_suspend(pa_sink *s, pa_bool_t suspend); +int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend); -void pa_sink_set_owner(pa_sink *sink, pa_module *m); +/* Sends a ping message to the sink thread, to make it wake up and + * check for data to process even if there is no real message is + * sent */ +void pa_sink_ping(pa_sink *s); -void pa_sink_set_volume(pa_sink *sink, pa_mixer_t m, const pa_cvolume *volume); -const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_mixer_t m); -void pa_sink_set_mute(pa_sink *sink, pa_mixer_t m, int mute); -int pa_sink_get_mute(pa_sink *sink, pa_mixer_t m); +void pa_sink_set_volume(pa_sink *sink, const pa_cvolume *volume); +const pa_cvolume *pa_sink_get_volume(pa_sink *sink); +void pa_sink_set_mute(pa_sink *sink, pa_bool_t mute); +pa_bool_t pa_sink_get_mute(pa_sink *sink); -void pa_sink_set_description(pa_sink *s, const char *description); +unsigned pa_sink_linked_by(pa_sink *s); /* Number of connected streams */ +unsigned pa_sink_used_by(pa_sink *s); /* Number of connected streams which are not corked */ +#define pa_sink_get_state(s) ((s)->state) -unsigned pa_sink_used_by(pa_sink *s); +/* To be called exclusively by the sink driver, from IO context */ + +void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result); +void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result); +void pa_sink_render_into(pa_sink*s, pa_memchunk *target); +void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target); + +void pa_sink_skip(pa_sink *s, size_t length); + +int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk); + +void pa_sink_attach_within_thread(pa_sink *s); +void pa_sink_detach_within_thread(pa_sink *s); #endif diff --git a/src/pulsecore/sioman.c b/src/pulsecore/sioman.c index d3d7538ef..8d4c6fa7c 100644 --- a/src/pulsecore/sioman.c +++ b/src/pulsecore/sioman.c @@ -25,21 +25,17 @@ #include #endif -#include +#include +#include #include "sioman.h" -static int stdio_inuse = 0; +static pa_atomic_t stdio_inuse = PA_ATOMIC_INIT(0); int pa_stdio_acquire(void) { - if (stdio_inuse) - return -1; - - stdio_inuse = 1; - return 0; + return pa_atomic_cmpxchg(&stdio_inuse, 0, 1) ? 0 : -1; } void pa_stdio_release(void) { - assert(stdio_inuse); - stdio_inuse = 0; + pa_assert_se(pa_atomic_cmpxchg(&stdio_inuse, 1, 0)); } diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c index b99c8025d..5b5bc5cac 100644 --- a/src/pulsecore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -1,25 +1,25 @@ /* $Id$ */ /*** - This file is part of PulseAudio. + This file is part of PulseAudio. - Copyright 2004-2006 Lennart Poettering - Copyright 2006-2007 Pierre Ossman for Cendio AB + Copyright 2004-2006 Lennart Poettering + Copyright 2006-2007 Pierre Ossman for Cendio AB - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. ***/ #ifdef HAVE_CONFIG_H @@ -32,7 +32,6 @@ #include #include #include -#include #include #ifdef HAVE_SYS_SOCKET_H @@ -55,23 +54,24 @@ #include #endif -#include "winsock.h" - #include #include +#include #include #include #include #include #include +#include +#include #include "socket-client.h" #define CONNECT_TIMEOUT 5 struct pa_socket_client { - int ref; + PA_REFCNT_DECLARE; pa_mainloop_api *mainloop; int fd; pa_io_event *io_event; @@ -89,10 +89,10 @@ struct pa_socket_client { static pa_socket_client*pa_socket_client_new(pa_mainloop_api *m) { pa_socket_client *c; - assert(m); + pa_assert(m); - c = pa_xmalloc(sizeof(pa_socket_client)); - c->ref = 1; + c = pa_xnew(pa_socket_client, 1); + PA_REFCNT_INIT(c); c->mainloop = m; c->fd = -1; c->io_event = NULL; @@ -112,7 +112,7 @@ static pa_socket_client*pa_socket_client_new(pa_mainloop_api *m) { } static void free_events(pa_socket_client *c) { - assert(c); + pa_assert(c); if (c->io_event) { c->mainloop->io_free(c->io_event); @@ -134,7 +134,10 @@ static void do_call(pa_socket_client *c) { pa_iochannel *io = NULL; int error; socklen_t lerror; - assert(c && c->callback); + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(c->callback); pa_socket_client_ref(c); @@ -153,13 +156,13 @@ static void do_call(pa_socket_client *c) { } if (error != 0) { - pa_log_debug("connect(): %s", pa_cstrerror(errno)); + pa_log_debug("connect(): %s", pa_cstrerror(error)); errno = error; goto finish; } io = pa_iochannel_new(c->mainloop, c->fd, c->fd); - assert(io); + pa_assert(io); finish: if (!io && c->fd >= 0) @@ -168,7 +171,7 @@ finish: free_events(c); - assert(c->callback); + pa_assert(c->callback); c->callback(c, io, c->userdata); pa_socket_client_unref(c); @@ -176,21 +179,36 @@ finish: static void connect_fixed_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { pa_socket_client *c = userdata; - assert(m && c && c->defer_event == e); + + pa_assert(m); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(c->defer_event == e); + do_call(c); } static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { pa_socket_client *c = userdata; - assert(m && c && c->io_event == e && fd >= 0); + + pa_assert(m); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(c->io_event == e); + pa_assert(fd >= 0); + do_call(c); } static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) { int r; - assert(c && sa && len); - pa_make_nonblock_fd(c->fd); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(sa); + pa_assert(len > 0); + + pa_make_fd_nonblock(c->fd); if ((r = connect(c->fd, sa, len)) < 0) { #ifdef OS_IS_WIN32 @@ -203,19 +221,18 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t return -1; } - c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c); - assert(c->io_event); - } else { - c->defer_event = c->mainloop->defer_new(c->mainloop, connect_fixed_cb, c); - assert(c->defer_event); - } + pa_assert_se(c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c)); + } else + pa_assert_se(c->defer_event = c->mainloop->defer_new(c->mainloop, connect_fixed_cb, c)); return 0; } pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port) { struct sockaddr_in sa; - assert(m && port > 0); + + pa_assert(m); + pa_assert(port > 0); memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; @@ -229,7 +246,9 @@ pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) { struct sockaddr_un sa; - assert(m && filename); + + pa_assert(m); + pa_assert(filename); memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; @@ -248,9 +267,9 @@ pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *file #endif /* HAVE_SYS_UN_H */ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) { - assert(c); - assert(sa); - assert(salen); + pa_assert(c); + pa_assert(sa); + pa_assert(salen); switch (sa->sa_family) { case AF_UNIX: @@ -274,11 +293,11 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size return -1; } - pa_fd_set_cloexec(c->fd, 1); + pa_make_fd_cloexec(c->fd); if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6) - pa_socket_tcp_low_delay(c->fd); + pa_make_tcp_socket_low_delay(c->fd); else - pa_socket_low_delay(c->fd); + pa_make_socket_low_delay(c->fd); if (do_connect(c, sa, salen) < 0) return -1; @@ -288,9 +307,12 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) { pa_socket_client *c; - assert(m && sa); - c = pa_socket_client_new(m); - assert(c); + + pa_assert(m); + pa_assert(sa); + pa_assert(salen > 0); + + pa_assert_se(c = pa_socket_client_new(m)); if (sockaddr_prepare(c, sa, salen) < 0) goto fail; @@ -300,12 +322,11 @@ pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct fail: pa_socket_client_unref(c); return NULL; - } static void socket_client_free(pa_socket_client *c) { - assert(c && c->mainloop); - + pa_assert(c); + pa_assert(c->mainloop); free_events(c); @@ -325,20 +346,25 @@ static void socket_client_free(pa_socket_client *c) { } void pa_socket_client_unref(pa_socket_client *c) { - assert(c && c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); - if (!(--(c->ref))) + if (PA_REFCNT_DEC(c) <= 0) socket_client_free(c); } pa_socket_client* pa_socket_client_ref(pa_socket_client *c) { - assert(c && c->ref >= 1); - c->ref++; + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_REFCNT_INC(c); return c; } void pa_socket_client_set_callback(pa_socket_client *c, void (*on_connection)(pa_socket_client *c, pa_iochannel*io, void *userdata), void *userdata) { - assert(c); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + c->callback = on_connection; c->userdata = userdata; } @@ -346,6 +372,10 @@ void pa_socket_client_set_callback(pa_socket_client *c, void (*on_connection)(pa pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) { struct sockaddr_in6 sa; + pa_assert(m); + pa_assert(address); + pa_assert(port > 0); + memset(&sa, 0, sizeof(sa)); sa.sin6_family = AF_INET6; sa.sin6_port = htons(port); @@ -360,7 +390,12 @@ static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_socket_client *c = userdata; struct addrinfo *res = NULL; int ret; - assert(m && c && c->asyncns_io_event == e && fd >= 0); + + pa_assert(m); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(c->asyncns_io_event == e); + pa_assert(fd >= 0); if (asyncns_wait(c->asyncns, 0) < 0) goto fail; @@ -397,10 +432,11 @@ fail: static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) { pa_socket_client *c = userdata; - assert(m); - assert(e); - assert(tv); - assert(c); + + pa_assert(m); + pa_assert(e); + pa_assert(tv); + pa_assert(c); if (c->fd >= 0) { pa_close(c->fd); @@ -413,8 +449,8 @@ static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeva static void start_timeout(pa_socket_client *c) { struct timeval tv; - assert(c); - assert(!c->timeout_event); + pa_assert(c); + pa_assert(!c->timeout_event); pa_gettimeofday(&tv); pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000); @@ -424,7 +460,9 @@ static void start_timeout(pa_socket_client *c) { pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*name, uint16_t default_port) { pa_socket_client *c = NULL; pa_parsed_address a; - assert(m && name); + + pa_assert(m); + pa_assert(name); if (pa_parse_address(name, &a) < 0) return NULL; @@ -435,7 +473,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam switch (a.type) { case PA_PARSED_ADDRESS_UNIX: if ((c = pa_socket_client_new_unix(m, a.path_or_host))) - start_timeout(c); + start_timeout(c); break; case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */ @@ -445,7 +483,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam struct addrinfo hints; char port[12]; - snprintf(port, sizeof(port), "%u", (unsigned) a.port); + pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port); memset(&hints, 0, sizeof(hints)); hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? PF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? PF_INET6 : PF_UNSPEC); @@ -462,7 +500,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam c->asyncns = asyncns; c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c); c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints); - assert(c->asyncns_query); + pa_assert(c->asyncns_query); start_timeout(c); } #else /* HAVE_LIBASYNCNS */ @@ -479,7 +517,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam if (res->ai_addr) { if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen))) start_timeout(c); - } + } freeaddrinfo(res); #else /* HAVE_GETADDRINFO */ @@ -507,7 +545,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam s.sin_port = htons(a.port); if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s)))) - start_timeout(c); + start_timeout(c); #endif /* HAVE_GETADDRINFO */ } #endif /* HAVE_LIBASYNCNS */ @@ -524,6 +562,8 @@ finish: local. "local" means UNIX socket or TCP socket on localhost. Other local IP addresses are not considered local. */ int pa_socket_client_is_local(pa_socket_client *c) { - assert(c); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + return c->local; } diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c index b5a6dc317..162a1aac2 100644 --- a/src/pulsecore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include #include @@ -72,12 +71,14 @@ #include #include #include +#include #include +#include #include "socket-server.h" struct pa_socket_server { - int ref; + PA_REFCNT_DECLARE; int fd; char *filename; char *tcpwrap_service; @@ -94,7 +95,14 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U pa_socket_server *s = userdata; pa_iochannel *io; int nfd; - assert(s && s->mainloop == mainloop && s->io_event == e && e && fd >= 0 && fd == s->fd); + + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + pa_assert(s->mainloop == mainloop); + pa_assert(s->io_event == e); + pa_assert(e); + pa_assert(fd >= 0); + pa_assert(fd == s->fd); pa_socket_server_ref(s); @@ -103,7 +111,7 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U goto finish; } - pa_fd_set_cloexec(nfd, 1); + pa_make_fd_cloexec(nfd); if (!s->on_connection) { pa_close(nfd); @@ -129,12 +137,11 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U /* There should be a check for socket type here */ if (s->type == SOCKET_SERVER_IPV4) - pa_socket_tcp_low_delay(fd); + pa_make_tcp_socket_low_delay(fd); else - pa_socket_low_delay(fd); + pa_make_socket_low_delay(fd); - io = pa_iochannel_new(s->mainloop, nfd, nfd); - assert(io); + pa_assert_se(io = pa_iochannel_new(s->mainloop, nfd, nfd)); s->on_connection(s, io, s->userdata); finish: @@ -143,10 +150,12 @@ finish: pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) { pa_socket_server *s; - assert(m && fd >= 0); - s = pa_xmalloc(sizeof(pa_socket_server)); - s->ref = 1; + pa_assert(m); + pa_assert(fd >= 0); + + s = pa_xnew(pa_socket_server, 1); + PA_REFCNT_INIT(s); s->fd = fd; s->filename = NULL; s->on_connection = NULL; @@ -154,8 +163,7 @@ pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) { s->tcpwrap_service = NULL; s->mainloop = m; - s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s); - assert(s->io_event); + pa_assert_se(s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s)); s->type = SOCKET_SERVER_GENERIC; @@ -163,8 +171,10 @@ pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) { } pa_socket_server* pa_socket_server_ref(pa_socket_server *s) { - assert(s && s->ref >= 1); - s->ref++; + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + + PA_REFCNT_INC(s); return s; } @@ -175,20 +185,21 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file struct sockaddr_un sa; pa_socket_server *s; - assert(m && filename); + pa_assert(m); + pa_assert(filename); if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { pa_log("socket(): %s", pa_cstrerror(errno)); goto fail; } - pa_fd_set_cloexec(fd, 1); + pa_make_fd_cloexec(fd); sa.sun_family = AF_UNIX; strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1); sa.sun_path[sizeof(sa.sun_path) - 1] = 0; - pa_socket_low_delay(fd); + pa_make_socket_low_delay(fd); if (bind(fd, (struct sockaddr*) &sa, SUN_LEN(&sa)) < 0) { pa_log("bind(): %s", pa_cstrerror(errno)); @@ -206,8 +217,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file goto fail; } - s = pa_socket_server_new(m, fd); - assert(s); + pa_assert_se(s = pa_socket_server_new(m, fd)); s->filename = pa_xstrdup(filename); s->type = SOCKET_SERVER_UNIX; @@ -235,21 +245,22 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address struct sockaddr_in sa; int on = 1; - assert(m && port); + pa_assert(m); + pa_assert(port); if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { pa_log("socket(PF_INET): %s", pa_cstrerror(errno)); goto fail; } - pa_fd_set_cloexec(fd, 1); + pa_make_fd_cloexec(fd); #ifdef SO_REUSEADDR if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) pa_log("setsockopt(): %s", pa_cstrerror(errno)); #endif - pa_socket_tcp_low_delay(fd); + pa_make_tcp_socket_low_delay(fd); memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; @@ -286,14 +297,15 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad struct sockaddr_in6 sa; int on = 1; - assert(m && port); + pa_assert(m); + pa_assert(port > 0); if ((fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) { pa_log("socket(PF_INET6): %s", pa_cstrerror(errno)); goto fail; } - pa_fd_set_cloexec(fd, 1); + pa_make_fd_cloexec(fd); #ifdef IPV6_V6ONLY if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) @@ -305,7 +317,7 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad pa_log("setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", pa_cstrerror(errno)); #endif - pa_socket_tcp_low_delay(fd); + pa_make_tcp_socket_low_delay(fd); memset(&sa, 0, sizeof(sa)); sa.sin6_family = AF_INET6; @@ -337,29 +349,29 @@ fail: } pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { - assert(m); - assert(port > 0); + pa_assert(m); + pa_assert(port > 0); return pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, tcpwrap_service); } pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { - assert(m); - assert(port > 0); + pa_assert(m); + pa_assert(port > 0); return pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, tcpwrap_service); } pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { - assert(m); - assert(port > 0); + pa_assert(m); + pa_assert(port > 0); return pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service); } pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) { - assert(m); - assert(port > 0); + pa_assert(m); + pa_assert(port > 0); return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service); } @@ -367,9 +379,9 @@ pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t por pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { struct in_addr ipv4; - assert(m); - assert(name); - assert(port > 0); + pa_assert(m); + pa_assert(name); + pa_assert(port > 0); if (inet_pton(AF_INET, name, &ipv4) > 0) return pa_socket_server_new_ipv4(m, ntohl(ipv4.s_addr), port, tcpwrap_service); @@ -380,9 +392,9 @@ pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const cha pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) { struct in6_addr ipv6; - assert(m); - assert(name); - assert(port > 0); + pa_assert(m); + pa_assert(name); + pa_assert(port > 0); if (inet_pton(AF_INET6, name, &ipv6) > 0) return pa_socket_server_new_ipv6(m, ipv6.s6_addr, port, tcpwrap_service); @@ -391,7 +403,7 @@ pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const cha } static void socket_server_free(pa_socket_server*s) { - assert(s); + pa_assert(s); if (s->filename) { unlink(s->filename); @@ -407,21 +419,26 @@ static void socket_server_free(pa_socket_server*s) { } void pa_socket_server_unref(pa_socket_server *s) { - assert(s && s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); - if (!(--(s->ref))) + if (PA_REFCNT_DEC(s) <= 0) socket_server_free(s); } void pa_socket_server_set_callback(pa_socket_server*s, void (*on_connection)(pa_socket_server*s, pa_iochannel *io, void *userdata), void *userdata) { - assert(s && s->ref >= 1); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); s->on_connection = on_connection; s->userdata = userdata; } char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { - assert(s && c && l > 0); + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + pa_assert(c); + pa_assert(l > 0); switch (s->type) { case SOCKET_SERVER_IPV6: { @@ -438,14 +455,14 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { if (!pa_get_fqdn(fqdn, sizeof(fqdn))) return NULL; - snprintf(c, l, "tcp6:%s:%u", fqdn, (unsigned) ntohs(sa.sin6_port)); + pa_snprintf(c, l, "tcp6:%s:%u", fqdn, (unsigned) ntohs(sa.sin6_port)); } else if (memcmp(&in6addr_loopback, &sa.sin6_addr, sizeof(in6addr_loopback)) == 0) { char hn[256]; if (!pa_get_host_name(hn, sizeof(hn))) return NULL; - snprintf(c, l, "{%s}tcp6:localhost:%u", hn, (unsigned) ntohs(sa.sin6_port)); + pa_snprintf(c, l, "{%s}tcp6:localhost:%u", hn, (unsigned) ntohs(sa.sin6_port)); } else { char ip[INET6_ADDRSTRLEN]; @@ -454,7 +471,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { return NULL; } - snprintf(c, l, "tcp6:[%s]:%u", ip, (unsigned) ntohs(sa.sin6_port)); + pa_snprintf(c, l, "tcp6:[%s]:%u", ip, (unsigned) ntohs(sa.sin6_port)); } return c; @@ -474,13 +491,13 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { if (!pa_get_fqdn(fqdn, sizeof(fqdn))) return NULL; - snprintf(c, l, "tcp:%s:%u", fqdn, (unsigned) ntohs(sa.sin_port)); + pa_snprintf(c, l, "tcp:%s:%u", fqdn, (unsigned) ntohs(sa.sin_port)); } else if (sa.sin_addr.s_addr == INADDR_LOOPBACK) { char hn[256]; if (!pa_get_host_name(hn, sizeof(hn))) return NULL; - snprintf(c, l, "{%s}tcp:localhost:%u", hn, (unsigned) ntohs(sa.sin_port)); + pa_snprintf(c, l, "{%s}tcp:localhost:%u", hn, (unsigned) ntohs(sa.sin_port)); } else { char ip[INET_ADDRSTRLEN]; @@ -489,7 +506,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { return NULL; } - snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port)); + pa_snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port)); } @@ -505,7 +522,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { if (!pa_get_host_name(hn, sizeof(hn))) return NULL; - snprintf(c, l, "{%s}unix:%s", hn, s->filename); + pa_snprintf(c, l, "{%s}unix:%s", hn, s->filename); return c; } diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c index 673058e2a..456accb82 100644 --- a/src/pulsecore/socket-util.c +++ b/src/pulsecore/socket-util.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -75,19 +74,19 @@ #include #include #include +#include #include "socket-util.h" void pa_socket_peer_to_string(int fd, char *c, size_t l) { struct stat st; - assert(c && l && fd >= 0); + pa_assert(fd >= 0); + pa_assert(c); + pa_assert(l > 0); #ifndef OS_IS_WIN32 - if (fstat(fd, &st) < 0) { - snprintf(c, l, "Invalid client fd"); - return; - } + pa_assert_se(fstat(fd, &st) == 0); #endif #ifndef OS_IS_WIN32 @@ -108,12 +107,12 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { if (sa.sa.sa_family == AF_INET) { uint32_t ip = ntohl(sa.in.sin_addr.s_addr); - snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u", - ip >> 24, - (ip >> 16) & 0xFF, - (ip >> 8) & 0xFF, - ip & 0xFF, - ntohs(sa.in.sin_port)); + pa_snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u", + ip >> 24, + (ip >> 16) & 0xFF, + (ip >> 8) & 0xFF, + ip & 0xFF, + ntohs(sa.in.sin_port)); return; } else if (sa.sa.sa_family == AF_INET6) { char buf[INET6_ADDRSTRLEN]; @@ -121,94 +120,107 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) { res = inet_ntop(AF_INET6, &sa.in6.sin6_addr, buf, sizeof(buf)); if (res) { - snprintf(c, l, "TCP/IP client from [%s]:%u", buf, ntohs(sa.in6.sin6_port)); + pa_snprintf(c, l, "TCP/IP client from [%s]:%u", buf, ntohs(sa.in6.sin6_port)); return; } #ifdef HAVE_SYS_UN_H } else if (sa.sa.sa_family == AF_UNIX) { - snprintf(c, l, "UNIX socket client"); + pa_snprintf(c, l, "UNIX socket client"); return; #endif } } #ifndef OS_IS_WIN32 - snprintf(c, l, "Unknown network client"); + pa_snprintf(c, l, "Unknown network client"); return; } else if (S_ISCHR(st.st_mode) && (fd == 0 || fd == 1)) { - snprintf(c, l, "STDIN/STDOUT client"); + pa_snprintf(c, l, "STDIN/STDOUT client"); return; } #endif /* OS_IS_WIN32 */ - snprintf(c, l, "Unknown client"); + pa_snprintf(c, l, "Unknown client"); } -int pa_socket_low_delay(int fd) { +void pa_make_socket_low_delay(int fd) { + #ifdef SO_PRIORITY int priority; - assert(fd >= 0); + pa_assert(fd >= 0); - priority = 7; + priority = 6; if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0) - return -1; + pa_log_warn("SO_PRIORITY failed: %s", pa_cstrerror(errno)); #endif - - return 0; } -int pa_socket_tcp_low_delay(int fd) { - int ret, tos, on; +void pa_make_tcp_socket_low_delay(int fd) { + pa_assert(fd >= 0); - assert(fd >= 0); - - ret = pa_socket_low_delay(fd); - - on = 1; - tos = 0; + pa_make_socket_low_delay(fd); #if defined(SOL_TCP) || defined(IPPROTO_TCP) + { + int on = 1; #if defined(SOL_TCP) - if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0) + if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0) #else - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0) + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0) #endif - ret = -1; + pa_log_warn("TCP_NODELAY failed: %s", pa_cstrerror(errno)); + } #endif -#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || \ - defined(IPPROTO_IP)) - tos = IPTOS_LOWDELAY; +#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP)) + { + int tos = IPTOS_LOWDELAY; #ifdef SOL_IP - if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0) + if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0) #else - if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0) + if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0) #endif - ret = -1; + pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno)); + } #endif +} - return ret; +void pa_make_udp_socket_low_delay(int fd) { + pa_assert(fd >= 0); + pa_make_socket_low_delay(fd); + +#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP)) + { + int tos = IPTOS_LOWDELAY; +#ifdef SOL_IP + if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0) +#else + if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0) +#endif + pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno)); + } +#endif } int pa_socket_set_rcvbuf(int fd, size_t l) { - assert(fd >= 0); + pa_assert(fd >= 0); -/* if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&l, sizeof(l)) < 0) { */ -/* pa_log("SO_RCVBUF: %s", strerror(errno)); */ -/* return -1; */ -/* } */ + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&l, sizeof(l)) < 0) { + pa_log_warn("SO_RCVBUF: %s", pa_cstrerror(errno)); + return -1; + } return 0; } int pa_socket_set_sndbuf(int fd, size_t l) { - assert(fd >= 0); + pa_assert(fd >= 0); -/* if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&l, sizeof(l)) < 0) { */ -/* pa_log("SO_SNDBUF: %s", strerror(errno)); */ -/* return -1; */ -/* } */ + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&l, sizeof(l)) < 0) { + pa_log("SO_SNDBUF: %s", pa_cstrerror(errno)); + return -1; + } return 0; } @@ -219,6 +231,8 @@ int pa_unix_socket_is_stale(const char *fn) { struct sockaddr_un sa; int fd = -1, ret = -1; + pa_assert(fn); + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { pa_log("socket(): %s", pa_cstrerror(errno)); goto finish; @@ -244,6 +258,8 @@ finish: int pa_unix_socket_remove_stale(const char *fn) { int r; + pa_assert(fn); + if ((r = pa_unix_socket_is_stale(fn)) < 0) return errno != ENOENT ? -1 : 0; diff --git a/src/pulsecore/socket-util.h b/src/pulsecore/socket-util.h index 616c40acd..a0344c68f 100644 --- a/src/pulsecore/socket-util.h +++ b/src/pulsecore/socket-util.h @@ -29,8 +29,9 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l); -int pa_socket_low_delay(int fd); -int pa_socket_tcp_low_delay(int fd); +void pa_make_socket_low_delay(int fd); +void pa_make_tcp_socket_low_delay(int fd); +void pa_make_udp_socket_low_delay(int fd); int pa_socket_set_sndbuf(int fd, size_t l); int pa_socket_set_rcvbuf(int fd, size_t l); diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index 7a43c7433..bb1f3e9a8 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -26,100 +26,196 @@ #endif #include -#include #include #include +#include +#include +#include #include #include +#include #include #include +#include +#include #include "sound-file-stream.h" -#define BUF_SIZE (1024*10) - -struct userdata { +typedef struct file_stream { + pa_msgobject parent; + pa_core *core; SNDFILE *sndfile; pa_sink_input *sink_input; pa_memchunk memchunk; sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames); + size_t drop; +} file_stream; + +enum { + FILE_STREAM_MESSAGE_UNLINK }; -static void free_userdata(struct userdata *u) { - assert(u); - if (u->sink_input) { - pa_sink_input_disconnect(u->sink_input); - pa_sink_input_unref(u->sink_input); - } +PA_DECLARE_CLASS(file_stream); +#define FILE_STREAM(o) (file_stream_cast(o)) +static PA_DEFINE_CHECK_TYPE(file_stream, pa_msgobject); + +static void file_stream_unlink(file_stream *u) { + pa_assert(u); + + if (!u->sink_input) + return; + + pa_sink_input_unlink(u->sink_input); + + pa_sink_input_unref(u->sink_input); + u->sink_input = NULL; + + /* Make sure we don't decrease the ref count twice. */ + file_stream_unref(u); +} + +static void file_stream_free(pa_object *o) { + file_stream *u = FILE_STREAM(o); + pa_assert(u); + + file_stream_unlink(u); if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); + if (u->sndfile) sf_close(u->sndfile); pa_xfree(u); } -static void sink_input_kill(pa_sink_input *i) { - assert(i && i->userdata); - free_userdata(i->userdata); +static int file_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) { + file_stream *u = FILE_STREAM(o); + file_stream_assert_ref(u); + + switch (code) { + case FILE_STREAM_MESSAGE_UNLINK: + file_stream_unlink(u); + break; + } + + return 0; } -static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) { - struct userdata *u; - assert(i && chunk && i->userdata); - u = i->userdata; +static void sink_input_kill_cb(pa_sink_input *i) { + pa_sink_input_assert_ref(i); - if (!u->memchunk.memblock) { - uint32_t fs = pa_frame_size(&i->sample_spec); - sf_count_t n; + file_stream_unlink(FILE_STREAM(i->userdata)); +} - u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, BUF_SIZE); - u->memchunk.index = 0; +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { + file_stream *u; - if (u->readf_function) { - if ((n = u->readf_function(u->sndfile, u->memchunk.memblock->data, BUF_SIZE/fs)) <= 0) - n = 0; + pa_assert(i); + pa_assert(chunk); + u = FILE_STREAM(i->userdata); + file_stream_assert_ref(u); - u->memchunk.length = n * fs; - } else { - if ((n = sf_read_raw(u->sndfile, u->memchunk.memblock->data, BUF_SIZE)) <= 0) - n = 0; + if (!u->sndfile) + return -1; - u->memchunk.length = n; + for (;;) { + + if (!u->memchunk.memblock) { + + u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, length); + u->memchunk.index = 0; + + if (u->readf_function) { + sf_count_t n; + void *p; + size_t fs = pa_frame_size(&i->sample_spec); + + p = pa_memblock_acquire(u->memchunk.memblock); + n = u->readf_function(u->sndfile, p, length/fs); + pa_memblock_release(u->memchunk.memblock); + + if (n <= 0) + n = 0; + + u->memchunk.length = n * fs; + } else { + sf_count_t n; + void *p; + + p = pa_memblock_acquire(u->memchunk.memblock); + n = sf_read_raw(u->sndfile, p, length); + pa_memblock_release(u->memchunk.memblock); + + if (n <= 0) + n = 0; + + u->memchunk.length = n; + } + + if (u->memchunk.length <= 0) { + + pa_memblock_unref(u->memchunk.memblock); + pa_memchunk_reset(&u->memchunk); + + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), FILE_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL); + + sf_close(u->sndfile); + u->sndfile = NULL; + + return -1; + } } - if (!u->memchunk.length) { - free_userdata(u); - return -1; + pa_assert(u->memchunk.memblock); + pa_assert(u->memchunk.length > 0); + + if (u->drop < u->memchunk.length) { + u->memchunk.index += u->drop; + u->memchunk.length -= u->drop; + u->drop = 0; + break; } + + u->drop -= u->memchunk.length; + pa_memblock_unref(u->memchunk.memblock); + pa_memchunk_reset(&u->memchunk); } *chunk = u->memchunk; pa_memblock_ref(chunk->memblock); - assert(chunk->length); + + pa_assert(chunk->length > 0); + pa_assert(u->drop <= 0); + return 0; } -static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) { - struct userdata *u; - assert(i && chunk && length && i->userdata); - u = i->userdata; +static void sink_input_drop_cb(pa_sink_input *i, size_t length) { + file_stream *u; - assert(!memcmp(chunk, &u->memchunk, sizeof(chunk))); - assert(length <= u->memchunk.length); + pa_assert(i); + pa_assert(length > 0); + u = FILE_STREAM(i->userdata); + file_stream_assert_ref(u); - u->memchunk.index += length; - u->memchunk.length -= length; + if (u->memchunk.memblock) { - if (u->memchunk.length <= 0) { + if (length < u->memchunk.length) { + u->memchunk.index += length; + u->memchunk.length -= length; + return; + } + + length -= u->memchunk.length; pa_memblock_unref(u->memchunk.memblock); - u->memchunk.memblock = NULL; - u->memchunk.index = u->memchunk.length = 0; + pa_memchunk_reset(&u->memchunk); } + + u->drop += length; } int pa_play_file( @@ -127,28 +223,60 @@ int pa_play_file( const char *fname, const pa_cvolume *volume) { - struct userdata *u = NULL; + file_stream *u = NULL; SF_INFO sfinfo; pa_sample_spec ss; pa_sink_input_new_data data; + int fd; - assert(sink); - assert(fname); + pa_assert(sink); + pa_assert(fname); - u = pa_xnew(struct userdata, 1); + u = pa_msgobject_new(file_stream); + u->parent.parent.free = file_stream_free; + u->parent.process_msg = file_stream_process_msg; + u->core = sink->core; u->sink_input = NULL; - u->memchunk.memblock = NULL; - u->memchunk.index = u->memchunk.length = 0; + pa_memchunk_reset(&u->memchunk); u->sndfile = NULL; + u->readf_function = NULL; + u->drop = 0; memset(&sfinfo, 0, sizeof(sfinfo)); - if (!(u->sndfile = sf_open(fname, SFM_READ, &sfinfo))) { - pa_log("Failed to open file %s", fname); + if ((fd = open(fname, O_RDONLY +#ifdef O_NOCTTY + |O_NOCTTY +#endif + )) < 0) { + pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno)); goto fail; } - u->readf_function = NULL; + /* FIXME: For now we just use posix_fadvise to avoid page faults + * when accessing the file data. Eventually we should move the + * file reader into the main event loop and pass the data over the + * asyncmsgq. */ + +#ifdef HAVE_POSIX_FADVISE + if (posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL) < 0) { + pa_log_warn("POSIX_FADV_SEQUENTIAL failed: %s", pa_cstrerror(errno)); + goto fail; + } else + pa_log_debug("POSIX_FADV_SEQUENTIAL succeeded."); + + if (posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED) < 0) { + pa_log_warn("POSIX_FADV_WILLNEED failed: %s", pa_cstrerror(errno)); + goto fail; + } else + pa_log_debug("POSIX_FADV_WILLNEED succeeded."); +#endif + + if (!(u->sndfile = sf_open_fd(fd, SFM_READ, &sfinfo, 1))) { + pa_log("Failed to open file %s", fname); + pa_close(fd); + goto fail; + } switch (sfinfo.format & 0xFF) { case SF_FORMAT_PCM_16: @@ -191,18 +319,21 @@ int pa_play_file( if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0))) goto fail; - u->sink_input->peek = sink_input_peek; - u->sink_input->drop = sink_input_drop; - u->sink_input->kill = sink_input_kill; + u->sink_input->peek = sink_input_peek_cb; + u->sink_input->drop = sink_input_drop_cb; + u->sink_input->kill = sink_input_kill_cb; u->sink_input->userdata = u; - pa_sink_notify(u->sink_input->sink); + pa_sink_input_put(u->sink_input); + + /* The reference to u is dangling here, because we want to keep + * this stream around until it is fully played. */ return 0; fail: if (u) - free_userdata(u); + file_stream_unref(u); return -1; } diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c index 69b543ab1..7e88734c2 100644 --- a/src/pulsecore/sound-file.c +++ b/src/pulsecore/sound-file.c @@ -26,31 +26,63 @@ #endif #include -#include +#include +#include +#include #include #include #include +#include +#include +#include #include "sound-file.h" #include "core-scache.h" -int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, pa_channel_map *map, pa_memchunk *chunk) { - SNDFILE*sf = NULL; +int pa_sound_file_load( + pa_mempool *pool, + const char *fname, + pa_sample_spec *ss, + pa_channel_map *map, + pa_memchunk *chunk) { + + SNDFILE *sf = NULL; SF_INFO sfinfo; int ret = -1; size_t l; sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL; - assert(fname && ss && chunk); + void *ptr = NULL; + int fd; - chunk->memblock = NULL; - chunk->index = chunk->length = 0; + pa_assert(fname); + pa_assert(ss); + pa_assert(chunk); + pa_memchunk_reset(chunk); memset(&sfinfo, 0, sizeof(sfinfo)); - if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { + if ((fd = open(fname, O_RDONLY +#ifdef O_NOCTTY + |O_NOCTTY +#endif + )) < 0) { + pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno)); + goto finish; + } + +#ifdef HAVE_POSIX_FADVISE + if (posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL) < 0) { + pa_log_warn("POSIX_FADV_SEQUENTIAL failed: %s", pa_cstrerror(errno)); + goto finish; + } else + pa_log_debug("POSIX_FADV_SEQUENTIAL succeeded."); +#endif + + if (!(sf = sf_open_fd(fd, SFM_READ, &sfinfo, 1))) { pa_log("Failed to open file %s", fname); + pa_close(fd); goto finish; } @@ -89,18 +121,19 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss, if (map) pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT); - if ((l = pa_frame_size(ss)*sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { + if ((l = pa_frame_size(ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { pa_log("File too large"); goto finish; } chunk->memblock = pa_memblock_new(pool, l); - assert(chunk->memblock); chunk->index = 0; chunk->length = l; - if ((readf_function && readf_function(sf, chunk->memblock->data, sfinfo.frames) != sfinfo.frames) || - (!readf_function && sf_read_raw(sf, chunk->memblock->data, l) != l)) { + ptr = pa_memblock_acquire(chunk->memblock); + + if ((readf_function && readf_function(sf, ptr, sfinfo.frames) != sfinfo.frames) || + (!readf_function && sf_read_raw(sf, ptr, l) != (sf_count_t) l)) { pa_log("Premature file end"); goto finish; } @@ -112,21 +145,26 @@ finish: if (sf) sf_close(sf); + if (ptr) + pa_memblock_release(chunk->memblock); + if (ret != 0 && chunk->memblock) pa_memblock_unref(chunk->memblock); return ret; - } int pa_sound_file_too_big_to_cache(const char *fname) { + SNDFILE*sf = NULL; SF_INFO sfinfo; pa_sample_spec ss; + pa_assert(fname); + if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) { pa_log("Failed to open file %s", fname); - return 0; + return -1; } sf_close(sf); @@ -156,8 +194,13 @@ int pa_sound_file_too_big_to_cache(const char *fname) { ss.rate = sfinfo.samplerate; ss.channels = sfinfo.channels; + if (!pa_sample_spec_valid(&ss)) { + pa_log("Unsupported sample format in file %s", fname); + return -1; + } + if ((pa_frame_size(&ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) { - pa_log("File too large %s", fname); + pa_log("File too large: %s", fname); return 1; } diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index c7a9858c4..2a902dc2b 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include @@ -39,14 +38,12 @@ #include "source-output.h" -#define CHECK_VALIDITY_RETURN_NULL(condition) \ -do {\ -if (!(condition)) \ - return NULL; \ -} while (0) +static PA_DEFINE_CHECK_TYPE(pa_source_output, pa_msgobject); + +static void source_output_free(pa_object* mo); pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data) { - assert(data); + pa_assert(data); memset(data, 0, sizeof(*data)); data->resample_method = PA_RESAMPLER_INVALID; @@ -54,14 +51,14 @@ pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_d } void pa_source_output_new_data_set_channel_map(pa_source_output_new_data *data, const pa_channel_map *map) { - assert(data); + pa_assert(data); if ((data->channel_map_is_set = !!map)) data->channel_map = *map; } void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data, const pa_sample_spec *spec) { - assert(data); + pa_assert(data); if ((data->sample_spec_is_set = !!spec)) data->sample_spec = *spec; @@ -74,183 +71,289 @@ pa_source_output* pa_source_output_new( pa_source_output *o; pa_resampler *resampler = NULL; - int r; char st[PA_SAMPLE_SPEC_SNPRINT_MAX]; - assert(core); - assert(data); + pa_assert(core); + pa_assert(data); - if (!(flags & PA_SOURCE_OUTPUT_NO_HOOKS)) - if (pa_hook_fire(&core->hook_source_output_new, data) < 0) - return NULL; + if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], data) < 0) + return NULL; - CHECK_VALIDITY_RETURN_NULL(!data->driver || pa_utf8_valid(data->driver)); - CHECK_VALIDITY_RETURN_NULL(!data->name || pa_utf8_valid(data->name)); + pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver)); + pa_return_null_if_fail(!data->name || pa_utf8_valid(data->name)); if (!data->source) data->source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE, 1); - CHECK_VALIDITY_RETURN_NULL(data->source); - CHECK_VALIDITY_RETURN_NULL(data->source->state == PA_SOURCE_RUNNING); + pa_return_null_if_fail(data->source); + pa_return_null_if_fail(pa_source_get_state(data->source) != PA_SOURCE_UNLINKED); if (!data->sample_spec_is_set) data->sample_spec = data->source->sample_spec; - CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(&data->sample_spec)); + pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec)); - if (!data->channel_map_is_set) - pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); + if (!data->channel_map_is_set) { + if (data->source->channel_map.channels == data->sample_spec.channels) + data->channel_map = data->source->channel_map; + else + pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); + } - CHECK_VALIDITY_RETURN_NULL(pa_channel_map_valid(&data->channel_map)); - CHECK_VALIDITY_RETURN_NULL(data->channel_map.channels == data->sample_spec.channels); + pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map)); + pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels); if (data->resample_method == PA_RESAMPLER_INVALID) data->resample_method = core->resample_method; - CHECK_VALIDITY_RETURN_NULL(data->resample_method < PA_RESAMPLER_MAX); + pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX); if (pa_idxset_size(data->source->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { pa_log("Failed to create source output: too many outputs per source."); return NULL; } - if (!pa_sample_spec_equal(&data->sample_spec, &data->source->sample_spec) || - !pa_channel_map_equal(&data->channel_map, &data->source->channel_map)) + if ((flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) || + !pa_sample_spec_equal(&data->sample_spec, &data->source->sample_spec) || + !pa_channel_map_equal(&data->channel_map, &data->source->channel_map)) { + if (!(resampler = pa_resampler_new( core->mempool, &data->source->sample_spec, &data->source->channel_map, &data->sample_spec, &data->channel_map, - data->resample_method))) { + data->resample_method, + !!(flags & PA_SOURCE_OUTPUT_VARIABLE_RATE)))) { pa_log_warn("Unsupported resampling operation."); return NULL; } - o = pa_xnew(pa_source_output, 1); - o->ref = 1; - o->state = PA_SOURCE_OUTPUT_RUNNING; + data->resample_method = pa_resampler_get_method(resampler); + } + + o = pa_msgobject_new(pa_source_output); + o->parent.parent.free = source_output_free; + o->parent.process_msg = pa_source_output_process_msg; + + o->core = core; + o->state = PA_SOURCE_OUTPUT_INIT; + o->flags = flags; o->name = pa_xstrdup(data->name); o->driver = pa_xstrdup(data->driver); o->module = data->module; o->source = data->source; o->client = data->client; + o->resample_method = data->resample_method; o->sample_spec = data->sample_spec; o->channel_map = data->channel_map; o->push = NULL; o->kill = NULL; o->get_latency = NULL; + o->detach = NULL; + o->attach = NULL; + o->suspend = NULL; o->userdata = NULL; - o->resampler = resampler; - o->resample_method = data->resample_method; + o->thread_info.state = o->state; + o->thread_info.attached = FALSE; + o->thread_info.sample_spec = o->sample_spec; + o->thread_info.resampler = resampler; - r = pa_idxset_put(core->source_outputs, o, &o->index); - assert(r == 0); - r = pa_idxset_put(o->source->outputs, o, NULL); - assert(r == 0); + pa_assert_se(pa_idxset_put(core->source_outputs, o, &o->index) == 0); + pa_assert_se(pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL) == 0); - pa_log_info("created %u \"%s\" on %s with sample spec %s", + pa_log_info("Created output %u \"%s\" on %s with sample spec %s", o->index, o->name, o->source->name, pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec)); - pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index); - - /* We do not call pa_source_notify() here, because the virtual - * functions have not yet been initialized */ + /* Don't forget to call pa_source_output_put! */ return o; } -void pa_source_output_disconnect(pa_source_output*o) { - assert(o); - assert(o->state != PA_SOURCE_OUTPUT_DISCONNECTED); - assert(o->source); - assert(o->source->core); +static int source_output_set_state(pa_source_output *o, pa_source_output_state_t state) { + pa_assert(o); + + if (o->state == state) + return 0; + + if (pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0) + return -1; + + if (o->state == PA_SOURCE_OUTPUT_CORKED && state != PA_SOURCE_OUTPUT_CORKED) + pa_assert_se(o->source->n_corked -- >= 1); + else if (o->state != PA_SOURCE_OUTPUT_CORKED && state == PA_SOURCE_OUTPUT_CORKED) + o->source->n_corked++; + + pa_source_update_status(o->source); + + o->state = state; + + if (state != PA_SOURCE_OUTPUT_UNLINKED) + pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED], o); + + return 0; +} + +void pa_source_output_unlink(pa_source_output*o) { + pa_bool_t linked; + pa_assert(o); + + /* See pa_sink_unlink() for a couple of comments how this function + * works */ + + pa_source_output_ref(o); + + linked = PA_SOURCE_OUTPUT_LINKED(o->state); + + if (linked) + pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o); pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL); - pa_idxset_remove_by_data(o->source->outputs, o, NULL); + if (pa_idxset_remove_by_data(o->source->outputs, o, NULL)) + pa_source_output_unref(o); - pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index); - o->source = NULL; + if (linked) { + pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL); + source_output_set_state(o, PA_SOURCE_OUTPUT_UNLINKED); + pa_source_update_status(o->source); + } else + o->state = PA_SOURCE_OUTPUT_UNLINKED; o->push = NULL; o->kill = NULL; o->get_latency = NULL; + o->attach = NULL; + o->detach = NULL; + o->suspend = NULL; - o->state = PA_SOURCE_OUTPUT_DISCONNECTED; + if (linked) { + pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index); + pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], o); + } + + o->source = NULL; + pa_source_output_unref(o); } -static void source_output_free(pa_source_output* o) { - assert(o); +static void source_output_free(pa_object* mo) { + pa_source_output *o = PA_SOURCE_OUTPUT(mo); - if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED) - pa_source_output_disconnect(o); + pa_assert(pa_source_output_refcnt(o) == 0); - pa_log_info("freed %u \"%s\"", o->index, o->name); + if (PA_SOURCE_OUTPUT_LINKED(o->state)) + pa_source_output_unlink(o); - if (o->resampler) - pa_resampler_free(o->resampler); + pa_log_info("Freeing output %u \"%s\"", o->index, o->name); + + pa_assert(!o->thread_info.attached); + + if (o->thread_info.resampler) + pa_resampler_free(o->thread_info.resampler); pa_xfree(o->name); pa_xfree(o->driver); pa_xfree(o); } -void pa_source_output_unref(pa_source_output* o) { - assert(o); - assert(o->ref >= 1); +void pa_source_output_put(pa_source_output *o) { + pa_source_output_assert_ref(o); - if (!(--o->ref)) - source_output_free(o); -} + pa_assert(o->state == PA_SOURCE_OUTPUT_INIT); + pa_assert(o->push); -pa_source_output* pa_source_output_ref(pa_source_output *o) { - assert(o); - assert(o->ref >= 1); + o->thread_info.state = o->state = o->flags & PA_SOURCE_OUTPUT_START_CORKED ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING; - o->ref++; - return o; + if (o->state == PA_SOURCE_OUTPUT_CORKED) + o->source->n_corked++; + + pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL); + pa_source_update_status(o->source); + + pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index); + + pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], o); } void pa_source_output_kill(pa_source_output*o) { - assert(o); - assert(o->ref >= 1); + pa_source_output_assert_ref(o); + pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state)); if (o->kill) o->kill(o); } +pa_usec_t pa_source_output_get_latency(pa_source_output *o) { + pa_usec_t r = 0; + + pa_source_output_assert_ref(o); + pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state)); + + if (pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY, &r, 0, NULL) < 0) + r = 0; + + if (o->get_latency) + r += o->get_latency(o); + + return r; +} + +/* Called from thread context */ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { pa_memchunk rchunk; - assert(o); - assert(chunk); - assert(chunk->length); - assert(o->push); + pa_source_output_assert_ref(o); + pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state)); + pa_assert(chunk); + pa_assert(chunk->length); - if (o->state == PA_SOURCE_OUTPUT_CORKED) + if (!o->push || o->state == PA_SOURCE_OUTPUT_CORKED) return; - if (!o->resampler) { + pa_assert(o->state == PA_SOURCE_OUTPUT_RUNNING); + + if (!o->thread_info.resampler) { o->push(o, chunk); return; } - pa_resampler_run(o->resampler, chunk, &rchunk); + pa_resampler_run(o->thread_info.resampler, chunk, &rchunk); if (!rchunk.length) return; - assert(rchunk.memblock); + pa_assert(rchunk.memblock); o->push(o, &rchunk); pa_memblock_unref(rchunk.memblock); } +void pa_source_output_cork(pa_source_output *o, pa_bool_t b) { + pa_source_output_assert_ref(o); + pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state)); + + source_output_set_state(o, b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING); +} + +int pa_source_output_set_rate(pa_source_output *o, uint32_t rate) { + pa_source_output_assert_ref(o); + pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state)); + pa_return_val_if_fail(o->thread_info.resampler, -1); + + if (o->sample_spec.rate == rate) + return 0; + + o->sample_spec.rate = rate; + + pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), 0, NULL, NULL); + + pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); + return 0; +} + void pa_source_output_set_name(pa_source_output *o, const char *name) { - assert(o); - assert(o->ref >= 1); + pa_source_output_assert_ref(o); if (!o->name && !name) return; @@ -261,101 +364,122 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) { pa_xfree(o->name); o->name = pa_xstrdup(name); - pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); -} - -pa_usec_t pa_source_output_get_latency(pa_source_output *o) { - assert(o); - assert(o->ref >= 1); - - if (o->get_latency) - return o->get_latency(o); - - return 0; -} - -void pa_source_output_cork(pa_source_output *o, int b) { - int n; - - assert(o); - assert(o->ref >= 1); - - if (o->state == PA_SOURCE_OUTPUT_DISCONNECTED) - return; - - n = o->state == PA_SOURCE_OUTPUT_CORKED && !b; - - o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING; - - if (n) - pa_source_notify(o->source); + if (PA_SOURCE_OUTPUT_LINKED(o->state)) { + pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NAME_CHANGED], o); + pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); + } } pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) { - assert(o); - assert(o->ref >= 1); + pa_source_output_assert_ref(o); - if (!o->resampler) - return o->resample_method; - - return pa_resampler_get_method(o->resampler); + return o->resample_method; } int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { pa_source *origin; pa_resampler *new_resampler = NULL; - assert(o); - assert(o->ref >= 1); - assert(dest); + pa_source_output_assert_ref(o); + pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state)); + pa_source_assert_ref(dest); origin = o->source; if (dest == origin) return 0; + if (o->flags & PA_SOURCE_OUTPUT_DONT_MOVE) + return -1; + if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { pa_log_warn("Failed to move source output: too many outputs per source."); return -1; } - if (o->resampler && + if (o->thread_info.resampler && pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) && pa_channel_map_equal(&origin->channel_map, &dest->channel_map)) /* Try to reuse the old resampler if possible */ - new_resampler = o->resampler; + new_resampler = o->thread_info.resampler; - else if (!pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) || - !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) { + else if ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) || + !pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) || + !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) { - /* Okey, we need a new resampler for the new sink */ + /* Okey, we need a new resampler for the new source */ if (!(new_resampler = pa_resampler_new( dest->core->mempool, &dest->sample_spec, &dest->channel_map, &o->sample_spec, &o->channel_map, - o->resample_method))) { + o->resample_method, + !!(o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE)))) { pa_log_warn("Unsupported resampling operation."); return -1; } } + pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], o); + /* Okey, let's move it */ + pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL); + pa_idxset_remove_by_data(origin->outputs, o, NULL); pa_idxset_put(dest->outputs, o, NULL); o->source = dest; - /* Replace resampler */ - if (new_resampler != o->resampler) { - if (o->resampler) - pa_resampler_free(o->resampler); - o->resampler = new_resampler; + if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED) { + pa_assert_se(origin->n_corked-- >= 1); + dest->n_corked++; } + /* Replace resampler */ + if (new_resampler != o->thread_info.resampler) { + if (o->thread_info.resampler) + pa_resampler_free(o->thread_info.resampler); + o->thread_info.resampler = new_resampler; + } + + pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL); + + pa_source_update_status(origin); + pa_source_update_status(dest); + + pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST], o); + + pa_log_debug("Successfully moved source output %i from %s to %s.", o->index, origin->name, dest->name); + /* Notify everyone */ pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); - pa_source_notify(o->source); return 0; } + +/* Called from thread context */ +int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk* chunk) { + pa_source_output *o = PA_SOURCE_OUTPUT(mo); + + pa_source_output_assert_ref(o); + pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state)); + + switch (code) { + + case PA_SOURCE_OUTPUT_MESSAGE_SET_RATE: { + + o->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata); + pa_resampler_set_output_rate(o->thread_info.resampler, PA_PTR_TO_UINT(userdata)); + + return 0; + } + + case PA_SOURCE_OUTPUT_MESSAGE_SET_STATE: { + o->thread_info.state = PA_PTR_TO_UINT(userdata); + + return 0; + } + } + + return -1; +} diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index 3da6caacd..e38a1e5a1 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -1,5 +1,5 @@ -#ifndef foosourceoutputhfoo -#define foosourceoutputhfoo +#ifndef foopulsesourceoutputhfoo +#define foopulsesourceoutputhfoo /* $Id$ */ @@ -35,40 +35,91 @@ typedef struct pa_source_output pa_source_output; #include #include -typedef enum { +typedef enum pa_source_output_state { + PA_SOURCE_OUTPUT_INIT, PA_SOURCE_OUTPUT_RUNNING, PA_SOURCE_OUTPUT_CORKED, - PA_SOURCE_OUTPUT_DISCONNECTED + PA_SOURCE_OUTPUT_UNLINKED } pa_source_output_state_t; +static inline pa_bool_t PA_SOURCE_OUTPUT_LINKED(pa_source_output_state_t x) { + return x == PA_SOURCE_OUTPUT_RUNNING || x == PA_SOURCE_OUTPUT_CORKED; +} + typedef enum pa_source_output_flags { - PA_SOURCE_OUTPUT_NO_HOOKS = 1 + PA_SOURCE_OUTPUT_VARIABLE_RATE = 1, + PA_SOURCE_OUTPUT_DONT_MOVE = 2, + PA_SOURCE_OUTPUT_START_CORKED = 4 } pa_source_output_flags_t; struct pa_source_output { - int ref; + pa_msgobject parent; + uint32_t index; + pa_core *core; pa_source_output_state_t state; + pa_source_output_flags_t flags; char *name, *driver; /* may be NULL */ pa_module *module; /* may be NULL */ + pa_client *client; /* may be NULL */ pa_source *source; - pa_client *client; /* may be NULL */ pa_sample_spec sample_spec; pa_channel_map channel_map; + /* Pushes a new memchunk into the output. Called from IO thread + * context. */ void (*push)(pa_source_output *o, const pa_memchunk *chunk); + + /* If non-NULL this function is called when the output is first + * connected to a source. Called from IO thread context */ + void (*attach) (pa_source_output *o); /* may be NULL */ + + /* If non-NULL this function is called when the output is + * disconnected from its source. Called from IO thread context */ + void (*detach) (pa_source_output *o); /* may be NULL */ + + /* If non-NULL called whenever the the source this output is attached + * to suspends or resumes. Called from main context */ + void (*suspend) (pa_source_output *o, int b); /* may be NULL */ + + /* Supposed to unlink and destroy this stream. Called from main + * context. */ void (*kill)(pa_source_output* o); /* may be NULL */ + + /* Return the current latency (i.e. length of bufferd audio) of + this stream. Called from main context. If NULL a + PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY message is sent to the IO + thread instead. */ pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */ - pa_resampler* resampler; /* may be NULL */ pa_resample_method_t resample_method; + struct { + pa_source_output_state_t state; + + pa_bool_t attached; /* True only between ->attach() and ->detach() calls */ + + pa_sample_spec sample_spec; + + pa_resampler* resampler; /* may be NULL */ + } thread_info; + void *userdata; }; +PA_DECLARE_CLASS(pa_source_output); +#define PA_SOURCE_OUTPUT(o) pa_source_output_cast(o) + +enum { + PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY, + PA_SOURCE_OUTPUT_MESSAGE_SET_RATE, + PA_SOURCE_OUTPUT_MESSAGE_SET_STATE, + PA_SOURCE_OUTPUT_MESSAGE_MAX +}; + typedef struct pa_source_output_new_data { const char *name, *driver; pa_module *module; @@ -77,9 +128,9 @@ typedef struct pa_source_output_new_data { pa_source *source; pa_sample_spec sample_spec; - int sample_spec_is_set; + pa_bool_t sample_spec_is_set; pa_channel_map channel_map; - int channel_map_is_set; + pa_bool_t channel_map_is_set; pa_resample_method_t resample_method; } pa_source_output_new_data; @@ -89,30 +140,38 @@ void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data, void pa_source_output_new_data_set_channel_map(pa_source_output_new_data *data, const pa_channel_map *map); void pa_source_output_new_data_set_volume(pa_source_output_new_data *data, const pa_cvolume *volume); +/* To be called by the implementing module only */ + pa_source_output* pa_source_output_new( pa_core *core, pa_source_output_new_data *data, pa_source_output_flags_t flags); -void pa_source_output_unref(pa_source_output* o); -pa_source_output* pa_source_output_ref(pa_source_output *o); +void pa_source_output_put(pa_source_output *o); +void pa_source_output_unlink(pa_source_output*o); -/* To be called by the implementing module only */ -void pa_source_output_disconnect(pa_source_output*o); +void pa_source_output_set_name(pa_source_output *i, const char *name); + +/* Callable by everyone */ /* External code may request disconnection with this funcion */ void pa_source_output_kill(pa_source_output*o); -void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk); - -void pa_source_output_set_name(pa_source_output *i, const char *name); - pa_usec_t pa_source_output_get_latency(pa_source_output *i); -void pa_source_output_cork(pa_source_output *i, int b); +void pa_source_output_cork(pa_source_output *i, pa_bool_t b); + +int pa_source_output_set_rate(pa_source_output *o, uint32_t rate); pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o); int pa_source_output_move_to(pa_source_output *o, pa_source *dest); +#define pa_source_output_get_state(o) ((o)->state) + +/* To be used exclusively by the source driver thread */ + +void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk); +int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk *chunk); + #endif diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 9bb2d342d..9a6902ae6 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include @@ -42,11 +41,9 @@ #include "source.h" -#define CHECK_VALIDITY_RETURN_NULL(condition) \ -do {\ -if (!(condition)) \ - return NULL; \ -} while (0) +static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject); + +static void source_free(pa_object *o); pa_source* pa_source_new( pa_core *core, @@ -58,274 +55,359 @@ pa_source* pa_source_new( pa_source *s; char st[256]; - int r; pa_channel_map tmap; - assert(core); - assert(name); - assert(spec); + pa_assert(core); + pa_assert(name); + pa_assert(spec); - CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec)); + pa_return_null_if_fail(pa_sample_spec_valid(spec)); if (!map) map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT); - CHECK_VALIDITY_RETURN_NULL(map && pa_channel_map_valid(map)); - CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels); - CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver)); - CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name) && *name); + pa_return_null_if_fail(map && pa_channel_map_valid(map)); + pa_return_null_if_fail(map->channels == spec->channels); + pa_return_null_if_fail(!driver || pa_utf8_valid(driver)); + pa_return_null_if_fail(pa_utf8_valid(name) && *name); - s = pa_xnew(pa_source, 1); + s = pa_msgobject_new(pa_source); if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) { pa_xfree(s); return NULL; } - s->ref = 1; + s->parent.parent.free = source_free; + s->parent.process_msg = pa_source_process_msg; + s->core = core; - s->state = PA_SOURCE_RUNNING; + s->state = PA_SOURCE_INIT; + s->flags = 0; s->name = pa_xstrdup(name); s->description = NULL; s->driver = pa_xstrdup(driver); - s->owner = NULL; + s->module = NULL; s->sample_spec = *spec; s->channel_map = *map; s->outputs = pa_idxset_new(NULL, NULL); + s->n_corked = 0; s->monitor_of = NULL; - pa_cvolume_reset(&s->sw_volume, spec->channels); - pa_cvolume_reset(&s->hw_volume, spec->channels); - s->sw_muted = 0; - s->hw_muted = 0; - - s->is_hardware = 0; + pa_cvolume_reset(&s->volume, spec->channels); + s->muted = FALSE; + s->refresh_volume = s->refresh_muted = FALSE; s->get_latency = NULL; - s->notify = NULL; - s->set_hw_volume = NULL; - s->get_hw_volume = NULL; - s->set_hw_mute = NULL; - s->get_hw_mute = NULL; + s->set_volume = NULL; + s->get_volume = NULL; + s->set_mute = NULL; + s->get_mute = NULL; + s->set_state = NULL; s->userdata = NULL; - r = pa_idxset_put(core->sources, s, &s->index); - assert(s->index != PA_IDXSET_INVALID && r >= 0); + s->asyncmsgq = NULL; + s->rtpoll = NULL; + + pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0); pa_sample_spec_snprint(st, sizeof(st), spec); - pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); + pa_log_info("Created source %u \"%s\" with sample spec \"%s\"", s->index, s->name, st); - pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); + s->thread_info.outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + s->thread_info.soft_volume = s->volume; + s->thread_info.soft_muted = s->muted; + s->thread_info.state = s->state; return s; } -void pa_source_disconnect(pa_source *s) { +static int source_set_state(pa_source *s, pa_source_state_t state) { + int ret; + + pa_assert(s); + + if (s->state == state) + return 0; + + if ((s->state == PA_SOURCE_SUSPENDED && PA_SOURCE_OPENED(state)) || + (PA_SOURCE_OPENED(s->state) && state == PA_SOURCE_SUSPENDED)) { + pa_source_output *o; + uint32_t idx; + + /* We're suspending or resuming, tell everyone about it */ + + for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx))) + if (o->suspend) + o->suspend(o, state == PA_SINK_SUSPENDED); + } + + if (s->set_state) + if ((ret = s->set_state(s, state)) < 0) + return -1; + + if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0) + return -1; + + s->state = state; + + if (state != PA_SOURCE_UNLINKED) /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */ + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s); + return 0; +} + +void pa_source_put(pa_source *s) { + pa_source_assert_ref(s); + + pa_assert(s->state == PA_SINK_INIT); + pa_assert(s->rtpoll); + pa_assert(s->asyncmsgq); + + pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0); + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_NEW_POST], s); +} + +void pa_source_unlink(pa_source *s) { + pa_bool_t linked; pa_source_output *o, *j = NULL; - assert(s); - assert(s->state == PA_SOURCE_RUNNING); + pa_assert(s); - s->state = PA_SOURCE_DISCONNECTED; - pa_namereg_unregister(s->core, s->name); + /* See pa_sink_unlink() for a couple of comments how this function + * works. */ - pa_hook_fire(&s->core->hook_source_disconnect, s); + linked = PA_SOURCE_LINKED(s->state); + + if (linked) + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s); + + if (s->state != PA_SOURCE_UNLINKED) + pa_namereg_unregister(s->core, s->name); + pa_idxset_remove_by_data(s->core->sources, s, NULL); while ((o = pa_idxset_first(s->outputs, NULL))) { - assert(o != j); + pa_assert(o != j); pa_source_output_kill(o); j = o; } - pa_idxset_remove_by_data(s->core->sources, s, NULL); + if (linked) + source_set_state(s, PA_SOURCE_UNLINKED); + else + s->state = PA_SOURCE_UNLINKED; s->get_latency = NULL; - s->notify = NULL; - s->get_hw_volume = NULL; - s->set_hw_volume = NULL; - s->set_hw_mute = NULL; - s->get_hw_mute = NULL; + s->get_volume = NULL; + s->set_volume = NULL; + s->set_mute = NULL; + s->get_mute = NULL; + s->set_state = NULL; - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + if (linked) { + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s); + } } -static void source_free(pa_source *s) { - assert(s); - assert(!s->ref); +static void source_free(pa_object *o) { + pa_source_output *so; + pa_source *s = PA_SOURCE(o); - if (s->state != PA_SOURCE_DISCONNECTED) - pa_source_disconnect(s); + pa_assert(s); + pa_assert(pa_source_refcnt(s) == 0); - pa_log_info("freed %u \"%s\"", s->index, s->name); + if (PA_SOURCE_LINKED(s->state)) + pa_source_unlink(s); + + pa_log_info("Freeing source %u \"%s\"", s->index, s->name); pa_idxset_free(s->outputs, NULL, NULL); + while ((so = pa_hashmap_steal_first(s->thread_info.outputs))) + pa_source_output_unref(so); + + pa_hashmap_free(s->thread_info.outputs, NULL, NULL); + pa_xfree(s->name); pa_xfree(s->description); pa_xfree(s->driver); pa_xfree(s); } -void pa_source_unref(pa_source *s) { - assert(s); - assert(s->ref >= 1); +int pa_source_update_status(pa_source*s) { + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); - if (!(--s->ref)) - source_free(s); + if (s->state == PA_SOURCE_SUSPENDED) + return 0; + + return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE); } -pa_source* pa_source_ref(pa_source *s) { - assert(s); - assert(s->ref >= 1); +int pa_source_suspend(pa_source *s, pa_bool_t suspend) { + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); - s->ref++; - return s; + if (suspend) + return source_set_state(s, PA_SOURCE_SUSPENDED); + else + return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE); } -void pa_source_notify(pa_source*s) { - assert(s); - assert(s->ref >= 1); +void pa_source_ping(pa_source *s) { + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); - if (s->notify) - s->notify(s); -} - -static int do_post(void *p, PA_GCC_UNUSED uint32_t idx, PA_GCC_UNUSED int *del, void*userdata) { - pa_source_output *o = p; - const pa_memchunk *chunk = userdata; - - assert(o); - assert(chunk); - - pa_source_output_push(o, chunk); - return 0; + pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_PING, NULL, 0, NULL, NULL); } void pa_source_post(pa_source*s, const pa_memchunk *chunk) { - assert(s); - assert(s->ref >= 1); - assert(chunk); + pa_source_output *o; + void *state = NULL; - pa_source_ref(s); + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_OPENED(s->thread_info.state)); + pa_assert(chunk); - if (s->sw_muted || !pa_cvolume_is_norm(&s->sw_volume)) { + if (s->thread_info.state != PA_SOURCE_RUNNING) + return; + + if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) { pa_memchunk vchunk = *chunk; pa_memblock_ref(vchunk.memblock); pa_memchunk_make_writable(&vchunk, 0); - if (s->sw_muted) + + if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume)) pa_silence_memchunk(&vchunk, &s->sample_spec); else - pa_volume_memchunk(&vchunk, &s->sample_spec, &s->sw_volume); - pa_idxset_foreach(s->outputs, do_post, &vchunk); + pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume); + + while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) + pa_source_output_push(o, &vchunk); + pa_memblock_unref(vchunk.memblock); - } else - pa_idxset_foreach(s->outputs, do_post, (void*) chunk); + } else { - pa_source_unref(s); -} - -void pa_source_set_owner(pa_source *s, pa_module *m) { - assert(s); - assert(s->ref >= 1); - - if (m == s->owner) - return; - - s->owner = m; - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) + pa_source_output_push(o, chunk); + } } pa_usec_t pa_source_get_latency(pa_source *s) { - assert(s); - assert(s->ref >= 1); + pa_usec_t usec; - if (!s->get_latency) + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); + + if (!PA_SOURCE_OPENED(s->state)) return 0; - return s->get_latency(s); + if (s->get_latency) + return s->get_latency(s); + + if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0) + return 0; + + return usec; } -void pa_source_set_volume(pa_source *s, pa_mixer_t m, const pa_cvolume *volume) { - pa_cvolume *v; +void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) { + int changed; - assert(s); - assert(s->ref >= 1); - assert(volume); + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); + pa_assert(volume); - if (m == PA_MIXER_HARDWARE && s->set_hw_volume) - v = &s->hw_volume; - else - v = &s->sw_volume; + changed = !pa_cvolume_equal(volume, &s->volume); + s->volume = *volume; - if (pa_cvolume_equal(v, volume)) + if (s->set_volume && s->set_volume(s) < 0) + s->set_volume = NULL; + + if (!s->set_volume) + pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree); + + if (changed) + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); +} + +const pa_cvolume *pa_source_get_volume(pa_source *s) { + pa_cvolume old_volume; + + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); + + old_volume = s->volume; + + if (s->get_volume && s->get_volume(s) < 0) + s->get_volume = NULL; + + if (!s->get_volume && s->refresh_volume) + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, &s->volume, 0, NULL); + + if (!pa_cvolume_equal(&old_volume, &s->volume)) + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + + return &s->volume; +} + +void pa_source_set_mute(pa_source *s, pa_bool_t mute) { + int changed; + + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); + + changed = s->muted != mute; + s->muted = mute; + + if (s->set_mute && s->set_mute(s) < 0) + s->set_mute = NULL; + + if (!s->set_mute) + pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 0, NULL, NULL); + + if (changed) + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); +} + +pa_bool_t pa_source_get_mute(pa_source *s) { + pa_bool_t old_muted; + + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); + + old_muted = s->muted; + + if (s->get_mute && s->get_mute(s) < 0) + s->get_mute = NULL; + + if (!s->get_mute && s->refresh_muted) + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, &s->muted, 0, NULL); + + if (old_muted != s->muted) + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + + return s->muted; +} + +void pa_source_set_module(pa_source *s, pa_module *m) { + pa_source_assert_ref(s); + + if (m == s->module) return; - *v = *volume; - - if (v == &s->hw_volume) - if (s->set_hw_volume(s) < 0) - s->sw_volume = *volume; + s->module = m; pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } -const pa_cvolume *pa_source_get_volume(pa_source *s, pa_mixer_t m) { - assert(s); - assert(s->ref >= 1); - - if (m == PA_MIXER_HARDWARE && s->set_hw_volume) { - - if (s->get_hw_volume) - s->get_hw_volume(s); - - return &s->hw_volume; - } else - return &s->sw_volume; -} - -void pa_source_set_mute(pa_source *s, pa_mixer_t m, int mute) { - int *t; - - assert(s); - assert(s->ref >= 1); - - if (m == PA_MIXER_HARDWARE && s->set_hw_mute) - t = &s->hw_muted; - else - t = &s->sw_muted; - - if (!!*t == !!mute) - return; - - *t = !!mute; - - if (t == &s->hw_muted) - if (s->set_hw_mute(s) < 0) - s->sw_muted = !!mute; - - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); -} - -int pa_source_get_mute(pa_source *s, pa_mixer_t m) { - assert(s); - assert(s->ref >= 1); - - if (m == PA_MIXER_HARDWARE && s->set_hw_mute) { - - if (s->get_hw_mute) - s->get_hw_mute(s); - - return s->hw_muted; - } else - return s->sw_muted; -} - void pa_source_set_description(pa_source *s, const char *description) { - assert(s); - assert(s->ref >= 1); + pa_source_assert_ref(s); if (!description && !s->description) return; @@ -336,12 +418,172 @@ void pa_source_set_description(pa_source *s, const char *description) { pa_xfree(s->description); s->description = pa_xstrdup(description); - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + if (PA_SOURCE_LINKED(s->state)) { + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_DESCRIPTION_CHANGED], s); + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + } } -unsigned pa_source_used_by(pa_source *s) { - assert(s); - assert(s->ref >= 1); +void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) { + pa_source_assert_ref(s); + pa_assert(q); + + s->asyncmsgq = q; +} + +void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) { + pa_source_assert_ref(s); + pa_assert(p); + + s->rtpoll = p; +} + +unsigned pa_source_linked_by(pa_source *s) { + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); return pa_idxset_size(s->outputs); } + +unsigned pa_source_used_by(pa_source *s) { + unsigned ret; + + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); + + ret = pa_idxset_size(s->outputs); + pa_assert(ret >= s->n_corked); + + return ret - s->n_corked; +} + +int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { + pa_source *s = PA_SOURCE(object); + pa_source_assert_ref(s); + pa_assert(s->thread_info.state != PA_SOURCE_UNLINKED); + + switch ((pa_source_message_t) code) { + case PA_SOURCE_MESSAGE_ADD_OUTPUT: { + pa_source_output *o = PA_SOURCE_OUTPUT(userdata); + pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o)); + + pa_assert(!o->thread_info.attached); + o->thread_info.attached = TRUE; + + if (o->attach) + o->attach(o); + + return 0; + } + + case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: { + pa_source_output *o = PA_SOURCE_OUTPUT(userdata); + + if (o->detach) + o->detach(o); + + pa_assert(o->thread_info.attached); + o->thread_info.attached = FALSE; + + if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index))) + pa_source_output_unref(o); + + return 0; + } + + case PA_SOURCE_MESSAGE_SET_VOLUME: + s->thread_info.soft_volume = *((pa_cvolume*) userdata); + return 0; + + case PA_SOURCE_MESSAGE_SET_MUTE: + s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata); + return 0; + + case PA_SOURCE_MESSAGE_GET_VOLUME: + *((pa_cvolume*) userdata) = s->thread_info.soft_volume; + return 0; + + case PA_SOURCE_MESSAGE_GET_MUTE: + *((pa_bool_t*) userdata) = s->thread_info.soft_muted; + return 0; + + case PA_SOURCE_MESSAGE_PING: + return 0; + + case PA_SOURCE_MESSAGE_SET_STATE: + s->thread_info.state = PA_PTR_TO_UINT(userdata); + return 0; + + case PA_SOURCE_MESSAGE_DETACH: + + /* We're detaching all our output streams so that the + * asyncmsgq and rtpoll fields can be changed without + * problems */ + pa_source_detach_within_thread(s); + break; + + case PA_SOURCE_MESSAGE_ATTACH: + + /* Reattach all streams */ + pa_source_attach_within_thread(s); + break; + + case PA_SOURCE_MESSAGE_GET_LATENCY: + case PA_SOURCE_MESSAGE_MAX: + ; + } + + return -1; +} + +int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) { + uint32_t idx; + pa_source *source; + int ret = 0; + + pa_core_assert_ref(c); + + for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx))) + ret -= pa_source_suspend(source, suspend) < 0; + + return ret; +} + +void pa_source_detach(pa_source *s) { + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); + + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL); +} + +void pa_source_attach(pa_source *s) { + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->state)); + + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL); +} + +void pa_source_detach_within_thread(pa_source *s) { + pa_source_output *o; + void *state = NULL; + + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->thread_info.state)); + + while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) + if (o->detach) + o->detach(o); +} + +void pa_source_attach_within_thread(pa_source *s) { + pa_source_output *o; + void *state = NULL; + + pa_source_assert_ref(s); + pa_assert(PA_SOURCE_LINKED(s->thread_info.state)); + + while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) + if (o->attach) + o->attach(o); + +} diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index 5a28cf4b7..bd0a91228 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -1,5 +1,5 @@ -#ifndef foosourcehfoo -#define foosourcehfoo +#ifndef foopulsesourcehfoo +#define foopulsesourcehfoo /* $Id$ */ @@ -32,6 +32,7 @@ typedef struct pa_source pa_source; #include #include #include + #include #include #include @@ -39,73 +40,140 @@ typedef struct pa_source pa_source; #include #include #include +#include +#include +#include -#define PA_MAX_OUTPUTS_PER_SOURCE 16 +#define PA_MAX_OUTPUTS_PER_SOURCE 32 typedef enum pa_source_state { + PA_SOURCE_INIT, PA_SOURCE_RUNNING, - PA_SOURCE_DISCONNECTED + PA_SOURCE_SUSPENDED, + PA_SOURCE_IDLE, + PA_SOURCE_UNLINKED } pa_source_state_t; +static inline pa_bool_t PA_SOURCE_OPENED(pa_source_state_t x) { + return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE; +} + +static inline pa_bool_t PA_SOURCE_LINKED(pa_source_state_t x) { + return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE || x == PA_SOURCE_SUSPENDED; +} + struct pa_source { - int ref; + pa_msgobject parent; + uint32_t index; pa_core *core; pa_source_state_t state; + pa_source_flags_t flags; char *name; char *description, *driver; /* may be NULL */ - pa_module *owner; /* may be NULL */ + pa_module *module; /* may be NULL */ pa_sample_spec sample_spec; pa_channel_map channel_map; pa_idxset *outputs; + unsigned n_corked; pa_sink *monitor_of; /* may be NULL */ - pa_cvolume hw_volume, sw_volume; - int hw_muted, sw_muted; + pa_cvolume volume; + pa_bool_t muted; + pa_bool_t refresh_volume; + pa_bool_t refresh_muted; - int is_hardware; - - void (*notify)(pa_source*source); /* may be NULL */ + int (*set_state)(pa_source*source, pa_source_state_t state); /* may be NULL */ + int (*set_volume)(pa_source *s); /* dito */ + int (*get_volume)(pa_source *s); /* dito */ + int (*set_mute)(pa_source *s); /* dito */ + int (*get_mute)(pa_source *s); /* dito */ pa_usec_t (*get_latency)(pa_source *s); /* dito */ - int (*set_hw_volume)(pa_source *s); /* dito */ - int (*get_hw_volume)(pa_source *s); /* dito */ - int (*set_hw_mute)(pa_source *s); /* dito */ - int (*get_hw_mute)(pa_source *s); /* dito */ + + pa_asyncmsgq *asyncmsgq; + pa_rtpoll *rtpoll; + + /* Contains copies of the above data so that the real-time worker + * thread can work without access locking */ + struct { + pa_source_state_t state; + pa_hashmap *outputs; + pa_cvolume soft_volume; + pa_bool_t soft_muted; + } thread_info; void *userdata; }; +PA_DECLARE_CLASS(pa_source); +#define PA_SOURCE(s) pa_source_cast(s) + +typedef enum pa_source_message { + PA_SOURCE_MESSAGE_ADD_OUTPUT, + PA_SOURCE_MESSAGE_REMOVE_OUTPUT, + PA_SOURCE_MESSAGE_GET_VOLUME, + PA_SOURCE_MESSAGE_SET_VOLUME, + PA_SOURCE_MESSAGE_GET_MUTE, + PA_SOURCE_MESSAGE_SET_MUTE, + PA_SOURCE_MESSAGE_GET_LATENCY, + PA_SOURCE_MESSAGE_SET_STATE, + PA_SOURCE_MESSAGE_PING, + PA_SOURCE_MESSAGE_ATTACH, + PA_SOURCE_MESSAGE_DETACH, + PA_SOURCE_MESSAGE_MAX +} pa_source_message_t; + +/* To be called exclusively by the source driver, from main context */ + pa_source* pa_source_new( - pa_core *core, - const char *driver, - const char *name, - int namereg_fail, - const pa_sample_spec *spec, - const pa_channel_map *map); + pa_core *core, + const char *driver, + const char *name, + int namereg_fail, + const pa_sample_spec *spec, + const pa_channel_map *map); -void pa_source_disconnect(pa_source *s); -void pa_source_unref(pa_source *s); -pa_source* pa_source_ref(pa_source *c); +void pa_source_put(pa_source *s); +void pa_source_unlink(pa_source *s); -/* Pass a new memory block to all output streams */ -void pa_source_post(pa_source*s, const pa_memchunk *b); +void pa_source_set_module(pa_source *s, pa_module *m); +void pa_source_set_description(pa_source *s, const char *description); +void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q); +void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p); -void pa_source_notify(pa_source *s); +void pa_source_detach(pa_source *s); +void pa_source_attach(pa_source *s); -void pa_source_set_owner(pa_source *s, pa_module *m); +/* May be called by everyone, from main context */ pa_usec_t pa_source_get_latency(pa_source *s); -void pa_source_set_volume(pa_source *source, pa_mixer_t m, const pa_cvolume *volume); -const pa_cvolume *pa_source_get_volume(pa_source *source, pa_mixer_t m); -void pa_source_set_mute(pa_source *source, pa_mixer_t m, int mute); -int pa_source_get_mute(pa_source *source, pa_mixer_t m); +int pa_source_update_status(pa_source*s); +int pa_source_suspend(pa_source *s, pa_bool_t suspend); +int pa_source_suspend_all(pa_core *c, pa_bool_t suspend); -void pa_source_set_description(pa_source *s, const char *description); +void pa_source_ping(pa_source *s); + +void pa_source_set_volume(pa_source *source, const pa_cvolume *volume); +const pa_cvolume *pa_source_get_volume(pa_source *source); +void pa_source_set_mute(pa_source *source, pa_bool_t mute); +pa_bool_t pa_source_get_mute(pa_source *source); + +unsigned pa_source_linked_by(pa_source *s); /* Number of connected streams */ +unsigned pa_source_used_by(pa_source *s); /* Number of connected streams that are not corked */ +#define pa_source_get_state(s) ((pa_source_state_t) (s)->state) + +/* To be called exclusively by the source driver, from IO context */ + +void pa_source_post(pa_source*s, const pa_memchunk *b); + +int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, int64_t, pa_memchunk *chunk); + +void pa_source_attach_within_thread(pa_source *s); +void pa_source_detach_within_thread(pa_source *s); -unsigned pa_source_used_by(pa_source *s); #endif diff --git a/src/pulsecore/speex/Makefile b/src/pulsecore/speex/Makefile new file mode 100644 index 000000000..316beb72d --- /dev/null +++ b/src/pulsecore/speex/Makefile @@ -0,0 +1,13 @@ +# This is a dirty trick just to ease compilation with emacs +# +# This file is not intended to be distributed or anything +# +# So: don't touch it, even better ignore it! + +all: + $(MAKE) -C ../.. + +clean: + $(MAKE) -C ../.. clean + +.PHONY: all clean diff --git a/src/pulsecore/speex/arch.h b/src/pulsecore/speex/arch.h new file mode 100644 index 000000000..4be693c35 --- /dev/null +++ b/src/pulsecore/speex/arch.h @@ -0,0 +1,197 @@ +/* Copyright (C) 2003 Jean-Marc Valin */ +/** + @file arch.h + @brief Various architecture definitions Speex +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ARCH_H +#define ARCH_H + +#ifndef OUTSIDE_SPEEX +#include "speex/speex_types.h" +#endif + +#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */ +#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */ +#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */ +#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ +#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */ +#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 32-bit value. */ +#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */ + +#ifdef FIXED_POINT + +typedef spx_int16_t spx_word16_t; +typedef spx_int32_t spx_word32_t; +typedef spx_word32_t spx_mem_t; +typedef spx_word16_t spx_coef_t; +typedef spx_word16_t spx_lsp_t; +typedef spx_word32_t spx_sig_t; + +#define Q15ONE 32767 + +#define LPC_SCALING 8192 +#define SIG_SCALING 16384 +#define LSP_SCALING 8192. +#define GAMMA_SCALING 32768. +#define GAIN_SCALING 64 +#define GAIN_SCALING_1 0.015625 + +#define LPC_SHIFT 13 +#define LSP_SHIFT 13 +#define SIG_SHIFT 14 + +#define VERY_SMALL 0 +#define VERY_LARGE32 ((spx_word32_t)2147483647) +#define VERY_LARGE16 ((spx_word16_t)32767) +#define Q15_ONE ((spx_word16_t)32767) + + +#ifdef FIXED_DEBUG +#include "fixed_debug.h" +#else + +#include "fixed_generic.h" + +#ifdef ARM5E_ASM +#include "fixed_arm5e.h" +#elif defined (ARM4_ASM) +#include "fixed_arm4.h" +#elif defined (ARM5E_ASM) +#include "fixed_arm5e.h" +#elif defined (BFIN_ASM) +#include "fixed_bfin.h" +#endif + +#endif + + +#else + +typedef float spx_mem_t; +typedef float spx_coef_t; +typedef float spx_lsp_t; +typedef float spx_sig_t; +typedef float spx_word16_t; +typedef float spx_word32_t; + +#define Q15ONE 1.0f +#define LPC_SCALING 1.f +#define SIG_SCALING 1.f +#define LSP_SCALING 1.f +#define GAMMA_SCALING 1.f +#define GAIN_SCALING 1.f +#define GAIN_SCALING_1 1.f + +#define LPC_SHIFT 0 +#define LSP_SHIFT 0 +#define SIG_SHIFT 0 + +#define VERY_SMALL 1e-15f +#define VERY_LARGE32 1e15f +#define VERY_LARGE16 1e15f +#define Q15_ONE ((spx_word16_t)1.f) + +#define QCONST16(x,bits) (x) +#define QCONST32(x,bits) (x) + +#define NEG16(x) (-(x)) +#define NEG32(x) (-(x)) +#define EXTRACT16(x) (x) +#define EXTEND32(x) (x) +#define SHR16(a,shift) (a) +#define SHL16(a,shift) (a) +#define SHR32(a,shift) (a) +#define SHL32(a,shift) (a) +#define PSHR16(a,shift) (a) +#define PSHR32(a,shift) (a) +#define VSHR32(a,shift) (a) +#define SATURATE16(x,a) (x) +#define SATURATE32(x,a) (x) + +#define PSHR(a,shift) (a) +#define SHR(a,shift) (a) +#define SHL(a,shift) (a) +#define SATURATE(x,a) (x) + +#define ADD16(a,b) ((a)+(b)) +#define SUB16(a,b) ((a)-(b)) +#define ADD32(a,b) ((a)+(b)) +#define SUB32(a,b) ((a)-(b)) +#define MULT16_16_16(a,b) ((a)*(b)) +#define MULT16_16(a,b) ((spx_word32_t)(a)*(spx_word32_t)(b)) +#define MAC16_16(c,a,b) ((c)+(spx_word32_t)(a)*(spx_word32_t)(b)) + +#define MULT16_32_Q11(a,b) ((a)*(b)) +#define MULT16_32_Q13(a,b) ((a)*(b)) +#define MULT16_32_Q14(a,b) ((a)*(b)) +#define MULT16_32_Q15(a,b) ((a)*(b)) +#define MULT16_32_P15(a,b) ((a)*(b)) + +#define MAC16_32_Q11(c,a,b) ((c)+(a)*(b)) +#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b)) + +#define MAC16_16_Q11(c,a,b) ((c)+(a)*(b)) +#define MAC16_16_Q13(c,a,b) ((c)+(a)*(b)) +#define MAC16_16_P13(c,a,b) ((c)+(a)*(b)) +#define MULT16_16_Q11_32(a,b) ((a)*(b)) +#define MULT16_16_Q13(a,b) ((a)*(b)) +#define MULT16_16_Q14(a,b) ((a)*(b)) +#define MULT16_16_Q15(a,b) ((a)*(b)) +#define MULT16_16_P15(a,b) ((a)*(b)) +#define MULT16_16_P13(a,b) ((a)*(b)) +#define MULT16_16_P14(a,b) ((a)*(b)) + +#define DIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b)) +#define PDIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b)) +#define DIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) +#define PDIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) + + +#endif + + +#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) + +/* 2 on TI C5x DSP */ +#define BYTES_PER_CHAR 2 +#define BITS_PER_CHAR 16 +#define LOG2_BITS_PER_CHAR 4 + +#else + +#define BYTES_PER_CHAR 1 +#define BITS_PER_CHAR 8 +#define LOG2_BITS_PER_CHAR 3 + +#endif + +#endif diff --git a/src/pulsecore/speex/fixed_generic.h b/src/pulsecore/speex/fixed_generic.h new file mode 100644 index 000000000..547e22c74 --- /dev/null +++ b/src/pulsecore/speex/fixed_generic.h @@ -0,0 +1,106 @@ +/* Copyright (C) 2003 Jean-Marc Valin */ +/** + @file fixed_generic.h + @brief Generic fixed-point operations +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FIXED_GENERIC_H +#define FIXED_GENERIC_H + +#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) +#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) + +#define NEG16(x) (-(x)) +#define NEG32(x) (-(x)) +#define EXTRACT16(x) ((spx_word16_t)(x)) +#define EXTEND32(x) ((spx_word32_t)(x)) +#define SHR16(a,shift) ((a) >> (shift)) +#define SHL16(a,shift) ((a) << (shift)) +#define SHR32(a,shift) ((a) >> (shift)) +#define SHL32(a,shift) ((a) << (shift)) +#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift)) +#define PSHR32(a,shift) (SHR32((a)+((1<<((shift))>>1)),shift)) +#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) +#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) +#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) + +#define SHR(a,shift) ((a) >> (shift)) +#define SHL(a,shift) ((spx_word32_t)(a) << (shift)) +#define PSHR(a,shift) (SHR((a)+((1<<((shift))>>1)),shift)) +#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) + + +#define ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b))) +#define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b)) +#define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b)) +#define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b)) + + +/* result fits in 16 bits */ +#define MULT16_16_16(a,b) ((((spx_word16_t)(a))*((spx_word16_t)(b)))) + +/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */ +#define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b))) + +#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b)))) +#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12)) +#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13)) +#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14)) + +#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)) +#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))) + +#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15)) +#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)) +#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))) + + +#define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11))) +#define MAC16_16_Q13(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),13))) +#define MAC16_16_P13(c,a,b) (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13))) + +#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11)) +#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13)) +#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14)) +#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15)) + +#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13)) +#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14)) +#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15)) + +#define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15)) + +#define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b)))) +#define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b)))) +#define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b))) +#define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b))) + +#endif diff --git a/src/pulsecore/speex/resample.c b/src/pulsecore/speex/resample.c new file mode 100644 index 000000000..bf1f88b46 --- /dev/null +++ b/src/pulsecore/speex/resample.c @@ -0,0 +1,1114 @@ +/* Copyright (C) 2007 Jean-Marc Valin + + File: resample.c + Arbitrary resampling code + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + The design goals of this code are: + - Very fast algorithm + - SIMD-friendly algorithm + - Low memory requirement + - Good *perceptual* quality (and not best SNR) + + The code is working, but it's in a very early stage, so it may have + artifacts, noise or subliminal messages from satan. Also, the API + isn't stable and I can actually promise that I *will* change the API + some time in the future. + +TODO list: + - Variable calculation resolution depending on quality setting + - Single vs double in float mode + - 16-bit vs 32-bit (sinc only) in fixed-point mode + - Make sure the filter update works even when changing params + after only a few samples procesed +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef OUTSIDE_SPEEX +#include +static void *speex_alloc (int size) {return calloc(size,1);} +static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);} +static void speex_free (void *ptr) {free(ptr);} +#include "speex_resampler.h" +#include "arch.h" +#else /* OUTSIDE_SPEEX */ + +#include "speex/speex_resampler.h" +#include "misc.h" +#endif /* OUTSIDE_SPEEX */ + +#include + +#ifndef M_PI +#define M_PI 3.14159263 +#endif + +#ifdef FIXED_POINT +#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) +#else +#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) +#endif + +/*#define float double*/ +#define FILTER_SIZE 64 +#define OVERSAMPLE 8 + +#define IMAX(a,b) ((a) > (b) ? (a) : (b)) +#define IMIN(a,b) ((a) < (b) ? (a) : (b)) + +#ifndef NULL +#define NULL 0 +#endif + +typedef int (*resampler_basic_func)(SpeexResamplerState *, spx_uint32_t , const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); + +struct SpeexResamplerState_ { + spx_uint32_t in_rate; + spx_uint32_t out_rate; + spx_uint32_t num_rate; + spx_uint32_t den_rate; + + int quality; + spx_uint32_t nb_channels; + spx_uint32_t filt_len; + spx_uint32_t mem_alloc_size; + int int_advance; + int frac_advance; + float cutoff; + spx_uint32_t oversample; + int initialised; + int started; + + /* These are per-channel */ + spx_int32_t *last_sample; + spx_uint32_t *samp_frac_num; + spx_uint32_t *magic_samples; + + spx_word16_t *mem; + spx_word16_t *sinc_table; + spx_uint32_t sinc_table_length; + resampler_basic_func resampler_ptr; + + int in_stride; + int out_stride; +} ; + +static double kaiser12_table[68] = { + 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076, + 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014, + 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601, + 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014, + 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490, + 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546, + 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178, + 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947, + 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058, + 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438, + 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734, + 0.00001000, 0.00000000}; +/* +static double kaiser12_table[36] = { + 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741, + 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762, + 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274, + 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466, + 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291, + 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000}; +*/ +static double kaiser10_table[36] = { + 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446, + 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347, + 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962, + 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451, + 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739, + 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000}; + +static double kaiser8_table[36] = { + 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200, + 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126, + 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272, + 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758, + 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, + 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000}; + +static double kaiser6_table[36] = { + 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, + 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, + 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561, + 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058, + 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600, + 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000}; + +struct FuncDef { + double *table; + int oversample; +}; + +static struct FuncDef _KAISER12 = {kaiser12_table, 64}; +#define KAISER12 (&_KAISER12) +/*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; +#define KAISER12 (&_KAISER12)*/ +static struct FuncDef _KAISER10 = {kaiser10_table, 32}; +#define KAISER10 (&_KAISER10) +static struct FuncDef _KAISER8 = {kaiser8_table, 32}; +#define KAISER8 (&_KAISER8) +static struct FuncDef _KAISER6 = {kaiser6_table, 32}; +#define KAISER6 (&_KAISER6) + +struct QualityMapping { + int base_length; + int oversample; + float downsample_bandwidth; + float upsample_bandwidth; + struct FuncDef *window_func; +}; + + +/* This table maps conversion quality to internal parameters. There are two + reasons that explain why the up-sampling bandwidth is larger than the + down-sampling bandwidth: + 1) When up-sampling, we can assume that the spectrum is already attenuated + close to the Nyquist rate (from an A/D or a previous resampling filter) + 2) Any aliasing that occurs very close to the Nyquist rate will be masked + by the sinusoids/noise just below the Nyquist rate (guaranteed only for + up-sampling). +*/ +static const struct QualityMapping quality_map[11] = { + { 8, 4, 0.830f, 0.860f, KAISER6 }, /* Q0 */ + { 16, 4, 0.850f, 0.880f, KAISER6 }, /* Q1 */ + { 32, 4, 0.882f, 0.910f, KAISER6 }, /* Q2 */ /* 82.3% cutoff ( ~60 dB stop) 6 */ + { 48, 8, 0.895f, 0.917f, KAISER8 }, /* Q3 */ /* 84.9% cutoff ( ~80 dB stop) 8 */ + { 64, 8, 0.921f, 0.940f, KAISER8 }, /* Q4 */ /* 88.7% cutoff ( ~80 dB stop) 8 */ + { 80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 */ /* 89.1% cutoff (~100 dB stop) 10 */ + { 96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 */ /* 91.5% cutoff (~100 dB stop) 10 */ + {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 */ /* 93.1% cutoff (~100 dB stop) 10 */ + {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 */ /* 94.5% cutoff (~100 dB stop) 10 */ + {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 */ /* 95.5% cutoff (~100 dB stop) 10 */ + {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */ +}; +/*8,24,40,56,80,104,128,160,200,256,320*/ +static double compute_func(float x, struct FuncDef *func) +{ + float y, frac; + double interp[4]; + int ind; + y = x*func->oversample; + ind = (int)floor(y); + frac = (y-ind); + /* CSE with handle the repeated powers */ + interp[3] = -0.1666666667*frac + 0.1666666667*(frac*frac*frac); + interp[2] = frac + 0.5*(frac*frac) - 0.5*(frac*frac*frac); + /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ + interp[0] = -0.3333333333*frac + 0.5*(frac*frac) - 0.1666666667*(frac*frac*frac); + /* Just to make sure we don't have rounding problems */ + interp[1] = 1.f-interp[3]-interp[2]-interp[0]; + + /*sum = frac*accum[1] + (1-frac)*accum[2];*/ + return interp[0]*func->table[ind] + interp[1]*func->table[ind+1] + interp[2]*func->table[ind+2] + interp[3]*func->table[ind+3]; +} + +#if 0 +#include +int main(int argc, char **argv) +{ + int i; + for (i=0;i<256;i++) + { + printf ("%f\n", compute_func(i/256., KAISER12)); + } + return 0; +} +#endif + +#ifdef FIXED_POINT +/* The slow way of computing a sinc for the table. Should improve that some day */ +static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) +{ + /*fprintf (stderr, "%f ", x);*/ + float xx = x * cutoff; + if (fabs(x)<1e-6f) + return WORD2INT(32768.*cutoff); + else if (fabs(x) > .5f*N) + return 0; + /*FIXME: Can it really be any slower than this? */ + return WORD2INT(32768.*cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func)); +} +#else +/* The slow way of computing a sinc for the table. Should improve that some day */ +static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func) +{ + /*fprintf (stderr, "%f ", x);*/ + float xx = x * cutoff; + if (fabs(x)<1e-6) + return cutoff; + else if (fabs(x) > .5*N) + return 0; + /*FIXME: Can it really be any slower than this? */ + return cutoff*sin(M_PI*xx)/(M_PI*xx) * compute_func(fabs(2.*x/N), window_func); +} +#endif + +#ifdef FIXED_POINT +static void cubic_coef(spx_word16_t x, spx_word16_t interp[4]) +{ + /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation + but I know it's MMSE-optimal on a sinc */ + spx_word16_t x2, x3; + x2 = MULT16_16_P15(x, x); + x3 = MULT16_16_P15(x, x2); + interp[0] = PSHR32(MULT16_16(QCONST16(-0.16667f, 15),x) + MULT16_16(QCONST16(0.16667f, 15),x3),15); + interp[1] = EXTRACT16(EXTEND32(x) + SHR32(SUB32(EXTEND32(x2),EXTEND32(x3)),1)); + interp[3] = PSHR32(MULT16_16(QCONST16(-0.33333f, 15),x) + MULT16_16(QCONST16(.5f,15),x2) - MULT16_16(QCONST16(0.16667f, 15),x3),15); + /* Just to make sure we don't have rounding problems */ + interp[2] = Q15_ONE-interp[0]-interp[1]-interp[3]; + if (interp[2]<32767) + interp[2]+=1; +} +#else +static void cubic_coef(spx_word16_t frac, spx_word16_t interp[4]) +{ + /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation + but I know it's MMSE-optimal on a sinc */ + interp[0] = -0.16667f*frac + 0.16667f*frac*frac*frac; + interp[1] = frac + 0.5f*frac*frac - 0.5f*frac*frac*frac; + /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/ + interp[3] = -0.33333f*frac + 0.5f*frac*frac - 0.16667f*frac*frac*frac; + /* Just to make sure we don't have rounding problems */ + interp[2] = 1.-interp[0]-interp[1]-interp[3]; +} +#endif + +static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) +{ + int N = st->filt_len; + int out_sample = 0; + spx_word16_t *mem; + int last_sample = st->last_sample[channel_index]; + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; + mem = st->mem + channel_index * st->mem_alloc_size; + while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) + { + int j; + spx_word32_t sum=0; + + /* We already have all the filter coefficients pre-computed in the table */ + const spx_word16_t *ptr; + /* Do the memory part */ + for (j=0;last_sample-N+1+j < 0;j++) + { + sum += MULT16_16(mem[last_sample+j],st->sinc_table[samp_frac_num*st->filt_len+j]); + } + + /* Do the new part */ + ptr = in+st->in_stride*(last_sample-N+1+j); + for (;jsinc_table[samp_frac_num*st->filt_len+j]); + ptr += st->in_stride; + } + + *out = PSHR32(sum,15); + out += st->out_stride; + out_sample++; + last_sample += st->int_advance; + samp_frac_num += st->frac_advance; + if (samp_frac_num >= st->den_rate) + { + samp_frac_num -= st->den_rate; + last_sample++; + } + } + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} + +#ifdef FIXED_POINT +#else +/* This is the same as the previous function, except with a double-precision accumulator */ +static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) +{ + int N = st->filt_len; + int out_sample = 0; + spx_word16_t *mem; + int last_sample = st->last_sample[channel_index]; + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; + mem = st->mem + channel_index * st->mem_alloc_size; + while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) + { + int j; + double sum=0; + + /* We already have all the filter coefficients pre-computed in the table */ + const spx_word16_t *ptr; + /* Do the memory part */ + for (j=0;last_sample-N+1+j < 0;j++) + { + sum += MULT16_16(mem[last_sample+j],(double)st->sinc_table[samp_frac_num*st->filt_len+j]); + } + + /* Do the new part */ + ptr = in+st->in_stride*(last_sample-N+1+j); + for (;jsinc_table[samp_frac_num*st->filt_len+j]); + ptr += st->in_stride; + } + + *out = sum; + out += st->out_stride; + out_sample++; + last_sample += st->int_advance; + samp_frac_num += st->frac_advance; + if (samp_frac_num >= st->den_rate) + { + samp_frac_num -= st->den_rate; + last_sample++; + } + } + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} +#endif + +static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) +{ + int N = st->filt_len; + int out_sample = 0; + spx_word16_t *mem; + int last_sample = st->last_sample[channel_index]; + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; + mem = st->mem + channel_index * st->mem_alloc_size; + while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) + { + int j; + spx_word32_t sum=0; + + /* We need to interpolate the sinc filter */ + spx_word32_t accum[4] = {0.f,0.f, 0.f, 0.f}; + spx_word16_t interp[4]; + const spx_word16_t *ptr; + int offset; + spx_word16_t frac; + offset = samp_frac_num*st->oversample/st->den_rate; +#ifdef FIXED_POINT + frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); +#else + frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; +#endif + /* This code is written like this to make it easy to optimise with SIMD. + For most DSPs, it would be best to split the loops in two because most DSPs + have only two accumulators */ + for (j=0;last_sample-N+1+j < 0;j++) + { + spx_word16_t curr_mem = mem[last_sample+j]; + accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]); + accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]); + accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]); + accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]); + } + ptr = in+st->in_stride*(last_sample-N+1+j); + /* Do the new part */ + for (;jin_stride; + accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); + accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); + accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); + accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); + } + cubic_coef(frac, interp); + sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]); + + *out = PSHR32(sum,15); + out += st->out_stride; + out_sample++; + last_sample += st->int_advance; + samp_frac_num += st->frac_advance; + if (samp_frac_num >= st->den_rate) + { + samp_frac_num -= st->den_rate; + last_sample++; + } + } + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} + +#ifdef FIXED_POINT +#else +/* This is the same as the previous function, except with a double-precision accumulator */ +static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) +{ + int N = st->filt_len; + int out_sample = 0; + spx_word16_t *mem; + int last_sample = st->last_sample[channel_index]; + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; + mem = st->mem + channel_index * st->mem_alloc_size; + while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) + { + int j; + spx_word32_t sum=0; + + /* We need to interpolate the sinc filter */ + double accum[4] = {0.f,0.f, 0.f, 0.f}; + float interp[4]; + const spx_word16_t *ptr; + float alpha = ((float)samp_frac_num)/st->den_rate; + int offset = samp_frac_num*st->oversample/st->den_rate; + float frac = alpha*st->oversample - offset; + /* This code is written like this to make it easy to optimise with SIMD. + For most DSPs, it would be best to split the loops in two because most DSPs + have only two accumulators */ + for (j=0;last_sample-N+1+j < 0;j++) + { + double curr_mem = mem[last_sample+j]; + accum[0] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-2]); + accum[1] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset-1]); + accum[2] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset]); + accum[3] += MULT16_16(curr_mem,st->sinc_table[4+(j+1)*st->oversample-offset+1]); + } + ptr = in+st->in_stride*(last_sample-N+1+j); + /* Do the new part */ + for (;jin_stride; + accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); + accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); + accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); + accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); + } + cubic_coef(frac, interp); + sum = interp[0]*accum[0] + interp[1]*accum[1] + interp[2]*accum[2] + interp[3]*accum[3]; + + *out = PSHR32(sum,15); + out += st->out_stride; + out_sample++; + last_sample += st->int_advance; + samp_frac_num += st->frac_advance; + if (samp_frac_num >= st->den_rate) + { + samp_frac_num -= st->den_rate; + last_sample++; + } + } + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} +#endif + +static void update_filter(SpeexResamplerState *st) +{ + spx_uint32_t old_length; + + old_length = st->filt_len; + st->oversample = quality_map[st->quality].oversample; + st->filt_len = quality_map[st->quality].base_length; + + if (st->num_rate > st->den_rate) + { + /* down-sampling */ + st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate; + /* FIXME: divide the numerator and denominator by a certain amount if they're too large */ + st->filt_len = st->filt_len*st->num_rate / st->den_rate; + /* Round down to make sure we have a multiple of 4 */ + st->filt_len &= (~0x3); + if (2*st->den_rate < st->num_rate) + st->oversample >>= 1; + if (4*st->den_rate < st->num_rate) + st->oversample >>= 1; + if (8*st->den_rate < st->num_rate) + st->oversample >>= 1; + if (16*st->den_rate < st->num_rate) + st->oversample >>= 1; + if (st->oversample < 1) + st->oversample = 1; + } else { + /* up-sampling */ + st->cutoff = quality_map[st->quality].upsample_bandwidth; + } + + /* Choose the resampling type that requires the least amount of memory */ + if (st->den_rate <= st->oversample) + { + spx_uint32_t i; + if (!st->sinc_table) + st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t)); + else if (st->sinc_table_length < st->filt_len*st->den_rate) + { + st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t)); + st->sinc_table_length = st->filt_len*st->den_rate; + } + for (i=0;iden_rate;i++) + { + spx_int32_t j; + for (j=0;jfilt_len;j++) + { + st->sinc_table[i*st->filt_len+j] = sinc(st->cutoff,((j-(spx_int32_t)st->filt_len/2+1)-((float)i)/st->den_rate), st->filt_len, quality_map[st->quality].window_func); + } + } +#ifdef FIXED_POINT + st->resampler_ptr = resampler_basic_direct_single; +#else + if (st->quality>8) + st->resampler_ptr = resampler_basic_direct_double; + else + st->resampler_ptr = resampler_basic_direct_single; +#endif + /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/ + } else { + spx_int32_t i; + if (!st->sinc_table) + st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); + else if (st->sinc_table_length < st->filt_len*st->oversample+8) + { + st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t)); + st->sinc_table_length = st->filt_len*st->oversample+8; + } + for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++) + st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func); +#ifdef FIXED_POINT + st->resampler_ptr = resampler_basic_interpolate_single; +#else + if (st->quality>8) + st->resampler_ptr = resampler_basic_interpolate_double; + else + st->resampler_ptr = resampler_basic_interpolate_single; +#endif + /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/ + } + st->int_advance = st->num_rate/st->den_rate; + st->frac_advance = st->num_rate%st->den_rate; + + + /* Here's the place where we update the filter memory to take into account + the change in filter length. It's probably the messiest part of the code + due to handling of lots of corner cases. */ + if (!st->mem) + { + spx_uint32_t i; + st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); + for (i=0;inb_channels*(st->filt_len-1);i++) + st->mem[i] = 0; + st->mem_alloc_size = st->filt_len-1; + /*speex_warning("init filter");*/ + } else if (!st->started) + { + spx_uint32_t i; + st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); + for (i=0;inb_channels*(st->filt_len-1);i++) + st->mem[i] = 0; + st->mem_alloc_size = st->filt_len-1; + /*speex_warning("reinit filter");*/ + } else if (st->filt_len > old_length) + { + spx_int32_t i; + /* Increase the filter length */ + /*speex_warning("increase filter size");*/ + int old_alloc_size = st->mem_alloc_size; + if (st->filt_len-1 > st->mem_alloc_size) + { + st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*(st->filt_len-1) * sizeof(spx_word16_t)); + st->mem_alloc_size = st->filt_len-1; + } + for (i=st->nb_channels-1;i>=0;i--) + { + spx_int32_t j; + spx_uint32_t olen = old_length; + /*if (st->magic_samples[i])*/ + { + /* Try and remove the magic samples as if nothing had happened */ + + /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ + olen = old_length + 2*st->magic_samples[i]; + for (j=old_length-2+st->magic_samples[i];j>=0;j--) + st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j]; + for (j=0;jmagic_samples[i];j++) + st->mem[i*st->mem_alloc_size+j] = 0; + st->magic_samples[i] = 0; + } + if (st->filt_len > olen) + { + /* If the new filter length is still bigger than the "augmented" length */ + /* Copy data going backward */ + for (j=0;jmem[i*st->mem_alloc_size+(st->filt_len-2-j)] = st->mem[i*st->mem_alloc_size+(olen-2-j)]; + /* Then put zeros for lack of anything better */ + for (;jfilt_len-1;j++) + st->mem[i*st->mem_alloc_size+(st->filt_len-2-j)] = 0; + /* Adjust last_sample */ + st->last_sample[i] += (st->filt_len - olen)/2; + } else { + /* Put back some of the magic! */ + st->magic_samples[i] = (olen - st->filt_len)/2; + for (j=0;jfilt_len-1+st->magic_samples[i];j++) + st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; + } + } + } else if (st->filt_len < old_length) + { + spx_uint32_t i; + /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic" + samples so they can be used directly as input the next time(s) */ + for (i=0;inb_channels;i++) + { + spx_uint32_t j; + spx_uint32_t old_magic = st->magic_samples[i]; + st->magic_samples[i] = (old_length - st->filt_len)/2; + /* We must copy some of the memory that's no longer used */ + /* Copy data going backward */ + for (j=0;jfilt_len-1+st->magic_samples[i]+old_magic;j++) + st->mem[i*st->mem_alloc_size+j] = st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]]; + st->magic_samples[i] += old_magic; + } + } + +} + +SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) +{ + return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err); +} + +SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) +{ + spx_uint32_t i; + SpeexResamplerState *st; + if (quality > 10 || quality < 0) + { + if (err) + *err = RESAMPLER_ERR_INVALID_ARG; + return NULL; + } + st = (SpeexResamplerState *)speex_alloc(sizeof(SpeexResamplerState)); + st->initialised = 0; + st->started = 0; + st->in_rate = 0; + st->out_rate = 0; + st->num_rate = 0; + st->den_rate = 0; + st->quality = -1; + st->sinc_table_length = 0; + st->mem_alloc_size = 0; + st->filt_len = 0; + st->mem = 0; + st->resampler_ptr = 0; + + st->cutoff = 1.f; + st->nb_channels = nb_channels; + st->in_stride = 1; + st->out_stride = 1; + + /* Per channel data */ + st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int)); + st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); + st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int)); + for (i=0;ilast_sample[i] = 0; + st->magic_samples[i] = 0; + st->samp_frac_num[i] = 0; + } + + speex_resampler_set_quality(st, quality); + speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate); + + + update_filter(st); + + st->initialised = 1; + if (err) + *err = RESAMPLER_ERR_SUCCESS; + + return st; +} + +void speex_resampler_destroy(SpeexResamplerState *st) +{ + speex_free(st->mem); + speex_free(st->sinc_table); + speex_free(st->last_sample); + speex_free(st->magic_samples); + speex_free(st->samp_frac_num); + speex_free(st); +} + + + +static int speex_resampler_process_native(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) +{ + int j=0; + int N = st->filt_len; + int out_sample = 0; + spx_word16_t *mem; + spx_uint32_t tmp_out_len = 0; + mem = st->mem + channel_index * st->mem_alloc_size; + st->started = 1; + + /* Handle the case where we have samples left from a reduction in filter length */ + if (st->magic_samples[channel_index]) + { + int istride_save; + spx_uint32_t tmp_in_len; + spx_uint32_t tmp_magic; + + istride_save = st->in_stride; + tmp_in_len = st->magic_samples[channel_index]; + tmp_out_len = *out_len; + /* magic_samples needs to be set to zero to avoid infinite recursion */ + tmp_magic = st->magic_samples[channel_index]; + st->magic_samples[channel_index] = 0; + st->in_stride = 1; + speex_resampler_process_native(st, channel_index, mem+N-1, &tmp_in_len, out, &tmp_out_len); + st->in_stride = istride_save; + /*speex_warning_int("extra samples:", tmp_out_len);*/ + /* If we couldn't process all "magic" input samples, save the rest for next time */ + if (tmp_in_len < tmp_magic) + { + spx_uint32_t i; + st->magic_samples[channel_index] = tmp_magic-tmp_in_len; + for (i=0;imagic_samples[channel_index];i++) + mem[N-1+i]=mem[N-1+i+tmp_in_len]; + } + out += tmp_out_len*st->out_stride; + *out_len -= tmp_out_len; + } + + /* Call the right resampler through the function ptr */ + out_sample = st->resampler_ptr(st, channel_index, in, in_len, out, out_len); + + if (st->last_sample[channel_index] < (spx_int32_t)*in_len) + *in_len = st->last_sample[channel_index]; + *out_len = out_sample+tmp_out_len; + st->last_sample[channel_index] -= *in_len; + + for (j=0;jin_stride*(j+*in_len-N+1)]; + + return RESAMPLER_ERR_SUCCESS; +} + +#define FIXED_STACK_ALLOC 1024 + +#ifdef FIXED_POINT +int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) +{ + spx_uint32_t i; + int istride_save, ostride_save; +#ifdef VAR_ARRAYS + spx_word16_t x[*in_len]; + spx_word16_t y[*out_len]; + /*VARDECL(spx_word16_t *x); + VARDECL(spx_word16_t *y); + ALLOC(x, *in_len, spx_word16_t); + ALLOC(y, *out_len, spx_word16_t);*/ + istride_save = st->in_stride; + ostride_save = st->out_stride; + for (i=0;i<*in_len;i++) + x[i] = WORD2INT(in[i*st->in_stride]); + st->in_stride = st->out_stride = 1; + speex_resampler_process_native(st, channel_index, x, in_len, y, out_len); + st->in_stride = istride_save; + st->out_stride = ostride_save; + for (i=0;i<*out_len;i++) + out[i*st->out_stride] = y[i]; +#else + spx_word16_t x[FIXED_STACK_ALLOC]; + spx_word16_t y[FIXED_STACK_ALLOC]; + spx_uint32_t ilen=*in_len, olen=*out_len; + istride_save = st->in_stride; + ostride_save = st->out_stride; + while (ilen && olen) + { + spx_uint32_t ichunk, ochunk; + ichunk = ilen; + ochunk = olen; + if (ichunk>FIXED_STACK_ALLOC) + ichunk=FIXED_STACK_ALLOC; + if (ochunk>FIXED_STACK_ALLOC) + ochunk=FIXED_STACK_ALLOC; + for (i=0;iin_stride]); + st->in_stride = st->out_stride = 1; + speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk); + st->in_stride = istride_save; + st->out_stride = ostride_save; + for (i=0;iout_stride] = y[i]; + out += ochunk; + in += ichunk; + ilen -= ichunk; + olen -= ochunk; + } + *in_len -= ilen; + *out_len -= olen; +#endif + return RESAMPLER_ERR_SUCCESS; +} +int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) +{ + return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); +} +#else +int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) +{ + return speex_resampler_process_native(st, channel_index, in, in_len, out, out_len); +} +int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) +{ + spx_uint32_t i; + int istride_save, ostride_save; +#ifdef VAR_ARRAYS + spx_word16_t x[*in_len]; + spx_word16_t y[*out_len]; + /*VARDECL(spx_word16_t *x); + VARDECL(spx_word16_t *y); + ALLOC(x, *in_len, spx_word16_t); + ALLOC(y, *out_len, spx_word16_t);*/ + istride_save = st->in_stride; + ostride_save = st->out_stride; + for (i=0;i<*in_len;i++) + x[i] = in[i*st->in_stride]; + st->in_stride = st->out_stride = 1; + speex_resampler_process_native(st, channel_index, x, in_len, y, out_len); + st->in_stride = istride_save; + st->out_stride = ostride_save; + for (i=0;i<*out_len;i++) + out[i*st->out_stride] = WORD2INT(y[i]); +#else + spx_word16_t x[FIXED_STACK_ALLOC]; + spx_word16_t y[FIXED_STACK_ALLOC]; + spx_uint32_t ilen=*in_len, olen=*out_len; + istride_save = st->in_stride; + ostride_save = st->out_stride; + while (ilen && olen) + { + spx_uint32_t ichunk, ochunk; + ichunk = ilen; + ochunk = olen; + if (ichunk>FIXED_STACK_ALLOC) + ichunk=FIXED_STACK_ALLOC; + if (ochunk>FIXED_STACK_ALLOC) + ochunk=FIXED_STACK_ALLOC; + for (i=0;iin_stride]; + st->in_stride = st->out_stride = 1; + speex_resampler_process_native(st, channel_index, x, &ichunk, y, &ochunk); + st->in_stride = istride_save; + st->out_stride = ostride_save; + for (i=0;iout_stride] = WORD2INT(y[i]); + out += ochunk; + in += ichunk; + ilen -= ichunk; + olen -= ochunk; + } + *in_len -= ilen; + *out_len -= olen; +#endif + return RESAMPLER_ERR_SUCCESS; +} +#endif + +int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len) +{ + spx_uint32_t i; + int istride_save, ostride_save; + spx_uint32_t bak_len = *out_len; + istride_save = st->in_stride; + ostride_save = st->out_stride; + st->in_stride = st->out_stride = st->nb_channels; + for (i=0;inb_channels;i++) + { + *out_len = bak_len; + speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len); + } + st->in_stride = istride_save; + st->out_stride = ostride_save; + return RESAMPLER_ERR_SUCCESS; +} + + +int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len) +{ + spx_uint32_t i; + int istride_save, ostride_save; + spx_uint32_t bak_len = *out_len; + istride_save = st->in_stride; + ostride_save = st->out_stride; + st->in_stride = st->out_stride = st->nb_channels; + for (i=0;inb_channels;i++) + { + *out_len = bak_len; + speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len); + } + st->in_stride = istride_save; + st->out_stride = ostride_save; + return RESAMPLER_ERR_SUCCESS; +} + +int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate) +{ + return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate); +} + +void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate) +{ + *in_rate = st->in_rate; + *out_rate = st->out_rate; +} + +int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) +{ + spx_uint32_t fact; + spx_uint32_t old_den; + spx_uint32_t i; + if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) + return RESAMPLER_ERR_SUCCESS; + + old_den = st->den_rate; + st->in_rate = in_rate; + st->out_rate = out_rate; + st->num_rate = ratio_num; + st->den_rate = ratio_den; + /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ + for (fact=2;fact<=IMIN(st->num_rate, st->den_rate);fact++) + { + while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) + { + st->num_rate /= fact; + st->den_rate /= fact; + } + } + + if (old_den > 0) + { + for (i=0;inb_channels;i++) + { + st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; + /* Safety net */ + if (st->samp_frac_num[i] >= st->den_rate) + st->samp_frac_num[i] = st->den_rate-1; + } + } + + if (st->initialised) + update_filter(st); + return RESAMPLER_ERR_SUCCESS; +} + +void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den) +{ + *ratio_num = st->num_rate; + *ratio_den = st->den_rate; +} + +int speex_resampler_set_quality(SpeexResamplerState *st, int quality) +{ + if (quality > 10 || quality < 0) + return RESAMPLER_ERR_INVALID_ARG; + if (st->quality == quality) + return RESAMPLER_ERR_SUCCESS; + st->quality = quality; + if (st->initialised) + update_filter(st); + return RESAMPLER_ERR_SUCCESS; +} + +void speex_resampler_get_quality(SpeexResamplerState *st, int *quality) +{ + *quality = st->quality; +} + +void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride) +{ + st->in_stride = stride; +} + +void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride) +{ + *stride = st->in_stride; +} + +void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride) +{ + st->out_stride = stride; +} + +void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride) +{ + *stride = st->out_stride; +} + +int speex_resampler_skip_zeros(SpeexResamplerState *st) +{ + spx_uint32_t i; + for (i=0;inb_channels;i++) + st->last_sample[i] = st->filt_len/2; + return RESAMPLER_ERR_SUCCESS; +} + +int speex_resampler_reset_mem(SpeexResamplerState *st) +{ + spx_uint32_t i; + for (i=0;inb_channels*(st->filt_len-1);i++) + st->mem[i] = 0; + return RESAMPLER_ERR_SUCCESS; +} + +const char *speex_resampler_strerror(int err) +{ + switch (err) + { + case RESAMPLER_ERR_SUCCESS: + return "Success."; + case RESAMPLER_ERR_ALLOC_FAILED: + return "Memory allocation failed."; + case RESAMPLER_ERR_BAD_STATE: + return "Bad resampler state."; + case RESAMPLER_ERR_INVALID_ARG: + return "Invalid argument."; + case RESAMPLER_ERR_PTR_OVERLAP: + return "Input and output buffers overlap."; + default: + return "Unknown error. Bad error code or strange version mismatch."; + } +} diff --git a/src/pulsecore/speex/speex_resampler.h b/src/pulsecore/speex/speex_resampler.h new file mode 100644 index 000000000..8629eeb37 --- /dev/null +++ b/src/pulsecore/speex/speex_resampler.h @@ -0,0 +1,328 @@ +/* Copyright (C) 2007 Jean-Marc Valin + + File: speex_resampler.h + Resampling code + + The design goals of this code are: + - Very fast algorithm + - Low memory requirement + - Good *perceptual* quality (and not best SNR) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef SPEEX_RESAMPLER_H +#define SPEEX_RESAMPLER_H + +#ifdef OUTSIDE_SPEEX + +/********* WARNING: MENTAL SANITY ENDS HERE *************/ + +/* If the resampler is defined outside of Speex, we change the symbol names so that + there won't be any clash if linking with Speex later on. */ + +/* #define RANDOM_PREFIX your software name here */ +#ifndef RANDOM_PREFIX +#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes" +#endif + +#define CAT_PREFIX2(a,b) a ## b +#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b) + +#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init) +#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac) +#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy) +#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float) +#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int) +#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float) +#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int) +#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate) +#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate) +#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac) +#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio) +#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality) +#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality) +#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride) +#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride) +#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride) +#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride) +#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros) +#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) +#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) + +#define spx_int16_t short +#define spx_int32_t int +#define spx_uint16_t unsigned short +#define spx_uint32_t unsigned int + +#else /* OUTSIDE_SPEEX */ + +#include "speex/speex_types.h" + +#endif /* OUTSIDE_SPEEX */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPEEX_RESAMPLER_QUALITY_MAX 10 +#define SPEEX_RESAMPLER_QUALITY_MIN 0 +#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4 +#define SPEEX_RESAMPLER_QUALITY_VOIP 3 +#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 + +enum { + RESAMPLER_ERR_SUCCESS = 0, + RESAMPLER_ERR_ALLOC_FAILED = 1, + RESAMPLER_ERR_BAD_STATE = 2, + RESAMPLER_ERR_INVALID_ARG = 3, + RESAMPLER_ERR_PTR_OVERLAP = 4, + + RESAMPLER_ERR_MAX_ERROR +}; + +struct SpeexResamplerState_; +typedef struct SpeexResamplerState_ SpeexResamplerState; + +/** Create a new resampler with integer input and output rates. + * @param nb_channels Number of channels to be processed + * @param in_rate Input sampling rate (integer number of Hz). + * @param out_rate Output sampling rate (integer number of Hz). + * @param quality Resampling quality between 0 and 10, where 0 has poor quality + * and 10 has very high quality. + * @return Newly created resampler state + * @retval NULL Error: not enough memory + */ +SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, + spx_uint32_t in_rate, + spx_uint32_t out_rate, + int quality, + int *err); + +/** Create a new resampler with fractional input/output rates. The sampling + * rate ratio is an arbitrary rational number with both the numerator and + * denominator being 32-bit integers. + * @param nb_channels Number of channels to be processed + * @param ratio_num Numerator of the sampling rate ratio + * @param ratio_den Denominator of the sampling rate ratio + * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). + * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). + * @param quality Resampling quality between 0 and 10, where 0 has poor quality + * and 10 has very high quality. + * @return Newly created resampler state + * @retval NULL Error: not enough memory + */ +SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, + spx_uint32_t ratio_num, + spx_uint32_t ratio_den, + spx_uint32_t in_rate, + spx_uint32_t out_rate, + int quality, + int *err); + +/** Destroy a resampler state. + * @param st Resampler state + */ +void speex_resampler_destroy(SpeexResamplerState *st); + +/** Resample a float array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param channel_index Index of the channel to process for the multi-channel + * base (0 otherwise) + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the + * number of samples processed + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written + */ +int speex_resampler_process_float(SpeexResamplerState *st, + spx_uint32_t channel_index, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); + +/** Resample an int array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param channel_index Index of the channel to process for the multi-channel + * base (0 otherwise) + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written + */ +int speex_resampler_process_int(SpeexResamplerState *st, + spx_uint32_t channel_index, + const spx_int16_t *in, + spx_uint32_t *in_len, + spx_int16_t *out, + spx_uint32_t *out_len); + +/** Resample an interleaved float array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed. This is all per-channel. + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written. + * This is all per-channel. + */ +int speex_resampler_process_interleaved_float(SpeexResamplerState *st, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); + +/** Resample an interleaved int array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed. This is all per-channel. + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written. + * This is all per-channel. + */ +int speex_resampler_process_interleaved_int(SpeexResamplerState *st, + const spx_int16_t *in, + spx_uint32_t *in_len, + spx_int16_t *out, + spx_uint32_t *out_len); + +/** Set (change) the input/output sampling rates (integer value). + * @param st Resampler state + * @param in_rate Input sampling rate (integer number of Hz). + * @param out_rate Output sampling rate (integer number of Hz). + */ +int speex_resampler_set_rate(SpeexResamplerState *st, + spx_uint32_t in_rate, + spx_uint32_t out_rate); + +/** Get the current input/output sampling rates (integer value). + * @param st Resampler state + * @param in_rate Input sampling rate (integer number of Hz) copied. + * @param out_rate Output sampling rate (integer number of Hz) copied. + */ +void speex_resampler_get_rate(SpeexResamplerState *st, + spx_uint32_t *in_rate, + spx_uint32_t *out_rate); + +/** Set (change) the input/output sampling rates and resampling ratio + * (fractional values in Hz supported). + * @param st Resampler state + * @param ratio_num Numerator of the sampling rate ratio + * @param ratio_den Denominator of the sampling rate ratio + * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). + * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). + */ +int speex_resampler_set_rate_frac(SpeexResamplerState *st, + spx_uint32_t ratio_num, + spx_uint32_t ratio_den, + spx_uint32_t in_rate, + spx_uint32_t out_rate); + +/** Get the current resampling ratio. This will be reduced to the least + * common denominator. + * @param st Resampler state + * @param ratio_num Numerator of the sampling rate ratio copied + * @param ratio_den Denominator of the sampling rate ratio copied + */ +void speex_resampler_get_ratio(SpeexResamplerState *st, + spx_uint32_t *ratio_num, + spx_uint32_t *ratio_den); + +/** Set (change) the conversion quality. + * @param st Resampler state + * @param quality Resampling quality between 0 and 10, where 0 has poor + * quality and 10 has very high quality. + */ +int speex_resampler_set_quality(SpeexResamplerState *st, + int quality); + +/** Get the conversion quality. + * @param st Resampler state + * @param quality Resampling quality between 0 and 10, where 0 has poor + * quality and 10 has very high quality. + */ +void speex_resampler_get_quality(SpeexResamplerState *st, + int *quality); + +/** Set (change) the input stride. + * @param st Resampler state + * @param stride Input stride + */ +void speex_resampler_set_input_stride(SpeexResamplerState *st, + spx_uint32_t stride); + +/** Get the input stride. + * @param st Resampler state + * @param stride Input stride copied + */ +void speex_resampler_get_input_stride(SpeexResamplerState *st, + spx_uint32_t *stride); + +/** Set (change) the output stride. + * @param st Resampler state + * @param stride Output stride + */ +void speex_resampler_set_output_stride(SpeexResamplerState *st, + spx_uint32_t stride); + +/** Get the output stride. + * @param st Resampler state copied + * @param stride Output stride + */ +void speex_resampler_get_output_stride(SpeexResamplerState *st, + spx_uint32_t *stride); + +/** Make sure that the first samples to go out of the resamplers don't have + * leading zeros. This is only useful before starting to use a newly created + * resampler. It is recommended to use that when resampling an audio file, as + * it will generate a file with the same length. For real-time processing, + * it is probably easier not to use this call (so that the output duration + * is the same for the first frame). + * @param st Resampler state + */ +int speex_resampler_skip_zeros(SpeexResamplerState *st); + +/** Reset a resampler so a new (unrelated) stream can be processed. + * @param st Resampler state + */ +int speex_resampler_reset_mem(SpeexResamplerState *st); + +/** Returns the English meaning for an error code + * @param err Error code + * @return English string + */ +const char *speex_resampler_strerror(int err); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/pulsecore/speexwrap.h b/src/pulsecore/speexwrap.h new file mode 100644 index 000000000..c0d5c0c04 --- /dev/null +++ b/src/pulsecore/speexwrap.h @@ -0,0 +1,48 @@ +#ifndef foopulsespeexwraphfoo +#define foopulsespeexwraphfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* We define a minimal version of speex_resampler.h however define one + * version for fixed and another one for float. Yes, somewhat ugly */ + +#define spx_int16_t short +#define spx_int32_t int +#define spx_uint16_t unsigned short +#define spx_uint32_t unsigned int + +typedef struct SpeexResamplerState_ SpeexResamplerState; + +SpeexResamplerState *paspfx_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err); +void paspfx_resampler_destroy(SpeexResamplerState *st); +int paspfx_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len); +int paspfx_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate); + +SpeexResamplerState *paspfl_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err); +void paspfl_resampler_destroy(SpeexResamplerState *st); +int paspfl_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len); +int paspfl_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate); + +#endif diff --git a/src/pulsecore/strbuf.c b/src/pulsecore/strbuf.c index a3ddc1144..7c576c672 100644 --- a/src/pulsecore/strbuf.c +++ b/src/pulsecore/strbuf.c @@ -27,12 +27,12 @@ #include #include -#include #include #include #include #include +#include #include "strbuf.h" @@ -42,7 +42,7 @@ struct chunk { size_t length; }; -#define CHUNK_TO_TEXT(c) ((char*) (c) + sizeof(struct chunk)) +#define CHUNK_TO_TEXT(c) ((char*) (c) + PA_ALIGN(sizeof(struct chunk))) struct pa_strbuf { size_t length; @@ -50,14 +50,18 @@ struct pa_strbuf { }; pa_strbuf *pa_strbuf_new(void) { - pa_strbuf *sb = pa_xmalloc(sizeof(pa_strbuf)); + pa_strbuf *sb; + + sb = pa_xnew(pa_strbuf, 1); sb->length = 0; sb->head = sb->tail = NULL; + return sb; } void pa_strbuf_free(pa_strbuf *sb) { - assert(sb); + pa_assert(sb); + while (sb->head) { struct chunk *c = sb->head; sb->head = sb->head->next; @@ -72,12 +76,13 @@ void pa_strbuf_free(pa_strbuf *sb) { char *pa_strbuf_tostring(pa_strbuf *sb) { char *t, *e; struct chunk *c; - assert(sb); - e = t = pa_xmalloc(sb->length+1); + pa_assert(sb); + + e = t = pa_xnew(char, sb->length+1); for (c = sb->head; c; c = c->next) { - assert((size_t) (e-t) <= sb->length); + pa_assert((size_t) (e-t) <= sb->length); memcpy(e, CHUNK_TO_TEXT(c), c->length); e += c->length; } @@ -85,7 +90,7 @@ char *pa_strbuf_tostring(pa_strbuf *sb) { /* Trailing NUL */ *e = 0; - assert(e == t+sb->length); + pa_assert(e == t+sb->length); return t; } @@ -93,27 +98,33 @@ char *pa_strbuf_tostring(pa_strbuf *sb) { /* Combination of pa_strbuf_free() and pa_strbuf_tostring() */ char *pa_strbuf_tostring_free(pa_strbuf *sb) { char *t; - assert(sb); + + pa_assert(sb); t = pa_strbuf_tostring(sb); pa_strbuf_free(sb); + return t; } /* Append a string to the string buffer */ void pa_strbuf_puts(pa_strbuf *sb, const char *t) { - assert(sb && t); + + pa_assert(sb); + pa_assert(t); + pa_strbuf_putsn(sb, t, strlen(t)); } /* Append a new chunk to the linked list */ static void append(pa_strbuf *sb, struct chunk *c) { - assert(sb && c); + pa_assert(sb); + pa_assert(c); if (sb->tail) { - assert(sb->head); + pa_assert(sb->head); sb->tail->next = c; } else { - assert(!sb->head); + pa_assert(!sb->head); sb->head = c; } @@ -125,12 +136,14 @@ static void append(pa_strbuf *sb, struct chunk *c) { /* Append up to l bytes of a string to the string buffer */ void pa_strbuf_putsn(pa_strbuf *sb, const char *t, size_t l) { struct chunk *c; - assert(sb && t); + + pa_assert(sb); + pa_assert(t); if (!l) return; - c = pa_xmalloc(sizeof(struct chunk)+l); + c = pa_xmalloc(PA_ALIGN(sizeof(struct chunk)) + l); c->length = l; memcpy(CHUNK_TO_TEXT(c), t, l); @@ -143,16 +156,18 @@ int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) { int size = 100; struct chunk *c = NULL; - assert(sb); + pa_assert(sb); + pa_assert(format); for(;;) { va_list ap; int r; - c = pa_xrealloc(c, sizeof(struct chunk)+size); + c = pa_xrealloc(c, PA_ALIGN(sizeof(struct chunk)) + size); va_start(ap, format); r = vsnprintf(CHUNK_TO_TEXT(c), size, format, ap); + CHUNK_TO_TEXT(c)[size-1] = 0; va_end(ap); if (r > -1 && r < size) { diff --git a/src/pulsecore/strlist.c b/src/pulsecore/strlist.c index 955b78e41..792af0ff8 100644 --- a/src/pulsecore/strlist.c +++ b/src/pulsecore/strlist.c @@ -26,26 +26,31 @@ #endif #include -#include #include #include +#include #include #include "strlist.h" struct pa_strlist { pa_strlist *next; - char *str; }; +#define ITEM_TO_TEXT(c) ((char*) (c) + PA_ALIGN(sizeof(pa_strlist))) + pa_strlist* pa_strlist_prepend(pa_strlist *l, const char *s) { pa_strlist *n; - assert(s); - n = pa_xmalloc(sizeof(pa_strlist)); - n->str = pa_xstrdup(s); + size_t size; + + pa_assert(s); + size = strlen(s); + n = pa_xmalloc(PA_ALIGN(sizeof(pa_strlist)) + size + 1); + memcpy(ITEM_TO_TEXT(n), s, size + 1); n->next = l; + return n; } @@ -58,7 +63,7 @@ char *pa_strlist_tostring(pa_strlist *l) { if (!first) pa_strbuf_puts(b, " "); first = 0; - pa_strbuf_puts(b, l->str); + pa_strbuf_puts(b, ITEM_TO_TEXT(l)); } return pa_strbuf_tostring_free(b); @@ -66,19 +71,20 @@ char *pa_strlist_tostring(pa_strlist *l) { pa_strlist* pa_strlist_remove(pa_strlist *l, const char *s) { pa_strlist *ret = l, *prev = NULL; - assert(l && s); + + pa_assert(l); + pa_assert(s); while (l) { - if (!strcmp(l->str, s)) { + if (!strcmp(ITEM_TO_TEXT(l), s)) { pa_strlist *n = l->next; if (!prev) { - assert(ret == l); + pa_assert(ret == l); ret = n; } else prev->next = n; - pa_xfree(l->str); pa_xfree(l); l = n; @@ -96,22 +102,21 @@ void pa_strlist_free(pa_strlist *l) { while (l) { pa_strlist *c = l; l = l->next; - - pa_xfree(c->str); pa_xfree(c); } } pa_strlist* pa_strlist_pop(pa_strlist *l, char **s) { pa_strlist *r; - assert(s); + + pa_assert(s); if (!l) { *s = NULL; return NULL; } - *s = l->str; + *s = pa_xstrdup(ITEM_TO_TEXT(l)); r = l->next; pa_xfree(l); return r; @@ -124,10 +129,12 @@ pa_strlist* pa_strlist_parse(const char *s) { while ((r = pa_split_spaces(s, &state))) { pa_strlist *n; + size_t size = strlen(r); - n = pa_xmalloc(sizeof(pa_strlist)); - n->str = r; + n = pa_xmalloc(PA_ALIGN(sizeof(pa_strlist)) + size + 1); n->next = NULL; + memcpy(ITEM_TO_TEXT(n), r, size+1); + pa_xfree(r); if (p) p->next = n; diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c index ac7ae1ab8..556fe8067 100644 --- a/src/pulsecore/tagstruct.c +++ b/src/pulsecore/tagstruct.c @@ -29,19 +29,18 @@ #include #include #include -#include #include #ifdef HAVE_NETINET_IN_H #include #endif -#include "winsock.h" - #include -#include "tagstruct.h" +#include +#include +#include "tagstruct.h" struct pa_tagstruct { uint8_t *data; @@ -54,18 +53,20 @@ struct pa_tagstruct { pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) { pa_tagstruct*t; - assert(!data || (data && length)); + pa_assert(!data || (data && length)); - t = pa_xmalloc(sizeof(pa_tagstruct)); + t = pa_xnew(pa_tagstruct, 1); t->data = (uint8_t*) data; t->allocated = t->length = data ? length : 0; t->rindex = 0; t->dynamic = !data; + return t; } void pa_tagstruct_free(pa_tagstruct*t) { - assert(t); + pa_assert(t); + if (t->dynamic) pa_xfree(t->data); pa_xfree(t); @@ -73,7 +74,11 @@ void pa_tagstruct_free(pa_tagstruct*t) { uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l) { uint8_t *p; - assert(t && t->dynamic && l); + + pa_assert(t); + pa_assert(t->dynamic); + pa_assert(l); + p = t->data; *l = t->length; pa_xfree(t); @@ -81,8 +86,8 @@ uint8_t* pa_tagstruct_free_data(pa_tagstruct*t, size_t *l) { } static void extend(pa_tagstruct*t, size_t l) { - assert(t); - assert(t->dynamic); + pa_assert(t); + pa_assert(t->dynamic); if (t->length+l <= t->allocated) return; @@ -92,7 +97,8 @@ static void extend(pa_tagstruct*t, size_t l) { void pa_tagstruct_puts(pa_tagstruct*t, const char *s) { size_t l; - assert(t); + pa_assert(t); + if (s) { l = strlen(s)+2; extend(t, l); @@ -107,7 +113,8 @@ void pa_tagstruct_puts(pa_tagstruct*t, const char *s) { } void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) { - assert(t); + pa_assert(t); + extend(t, 5); t->data[t->length] = PA_TAG_U32; i = htonl(i); @@ -116,7 +123,8 @@ void pa_tagstruct_putu32(pa_tagstruct*t, uint32_t i) { } void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c) { - assert(t); + pa_assert(t); + extend(t, 2); t->data[t->length] = PA_TAG_U8; *(t->data+t->length+1) = c; @@ -125,7 +133,10 @@ void pa_tagstruct_putu8(pa_tagstruct*t, uint8_t c) { void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss) { uint32_t rate; - assert(t && ss); + + pa_assert(t); + pa_assert(ss); + extend(t, 7); t->data[t->length] = PA_TAG_SAMPLE_SPEC; t->data[t->length+1] = (uint8_t) ss->format; @@ -137,7 +148,9 @@ void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss) { void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) { uint32_t tmp; - assert(t && p); + + pa_assert(t); + pa_assert(p); extend(t, 5+length); t->data[t->length] = PA_TAG_ARBITRARY; @@ -149,7 +162,8 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) { } void pa_tagstruct_put_boolean(pa_tagstruct*t, int b) { - assert(t); + pa_assert(t); + extend(t, 1); t->data[t->length] = b ? PA_TAG_BOOLEAN_TRUE : PA_TAG_BOOLEAN_FALSE; t->length += 1; @@ -157,7 +171,8 @@ void pa_tagstruct_put_boolean(pa_tagstruct*t, int b) { void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) { uint32_t tmp; - assert(t); + pa_assert(t); + extend(t, 9); t->data[t->length] = PA_TAG_TIMEVAL; tmp = htonl(tv->tv_sec); @@ -169,7 +184,9 @@ void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv) { void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u) { uint32_t tmp; - assert(t); + + pa_assert(t); + extend(t, 9); t->data[t->length] = PA_TAG_USEC; tmp = htonl((uint32_t) (u >> 32)); @@ -181,7 +198,9 @@ void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u) { void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) { uint32_t tmp; - assert(t); + + pa_assert(t); + extend(t, 9); t->data[t->length] = PA_TAG_U64; tmp = htonl((uint32_t) (u >> 32)); @@ -193,7 +212,9 @@ void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t u) { void pa_tagstruct_puts64(pa_tagstruct*t, int64_t u) { uint32_t tmp; - assert(t); + + pa_assert(t); + extend(t, 9); t->data[t->length] = PA_TAG_S64; tmp = htonl((uint32_t) ((uint64_t) u >> 32)); @@ -206,7 +227,7 @@ void pa_tagstruct_puts64(pa_tagstruct*t, int64_t u) { void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) { unsigned i; - assert(t); + pa_assert(t); extend(t, 2 + map->channels); t->data[t->length++] = PA_TAG_CHANNEL_MAP; @@ -220,7 +241,7 @@ void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) { unsigned i; pa_volume_t vol; - assert(t); + pa_assert(t); extend(t, 2 + cvolume->channels * sizeof(pa_volume_t)); t->data[t->length++] = PA_TAG_CVOLUME; @@ -237,7 +258,9 @@ int pa_tagstruct_gets(pa_tagstruct*t, const char **s) { int error = 0; size_t n; char *c; - assert(t && s); + + pa_assert(t); + pa_assert(s); if (t->rindex+1 > t->length) return -1; @@ -271,7 +294,8 @@ int pa_tagstruct_gets(pa_tagstruct*t, const char **s) { } int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i) { - assert(t && i); + pa_assert(t); + pa_assert(i); if (t->rindex+5 > t->length) return -1; @@ -286,7 +310,8 @@ int pa_tagstruct_getu32(pa_tagstruct*t, uint32_t *i) { } int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c) { - assert(t && c); + pa_assert(t); + pa_assert(c); if (t->rindex+2 > t->length) return -1; @@ -300,7 +325,8 @@ int pa_tagstruct_getu8(pa_tagstruct*t, uint8_t *c) { } int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) { - assert(t && ss); + pa_assert(t); + pa_assert(ss); if (t->rindex+7 > t->length) return -1; @@ -319,7 +345,9 @@ int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss) { int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) { uint32_t len; - assert(t && p); + + pa_assert(t); + pa_assert(p); if (t->rindex+5+length > t->length) return -1; @@ -337,18 +365,23 @@ int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) { } int pa_tagstruct_eof(pa_tagstruct*t) { - assert(t); + pa_assert(t); + return t->rindex >= t->length; } const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l) { - assert(t && t->dynamic && l); + pa_assert(t); + pa_assert(t->dynamic); + pa_assert(l); + *l = t->length; return t->data; } int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) { - assert(t && b); + pa_assert(t); + pa_assert(b); if (t->rindex+1 > t->length) return -1; @@ -366,6 +399,9 @@ int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) { int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) { + pa_assert(t); + pa_assert(tv); + if (t->rindex+9 > t->length) return -1; @@ -382,7 +418,9 @@ int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) { int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) { uint32_t tmp; - assert(t && u); + + pa_assert(t); + pa_assert(u); if (t->rindex+9 > t->length) return -1; @@ -400,7 +438,9 @@ int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u) { int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) { uint32_t tmp; - assert(t && u); + + pa_assert(t); + pa_assert(u); if (t->rindex+9 > t->length) return -1; @@ -418,7 +458,9 @@ int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *u) { int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *u) { uint32_t tmp; - assert(t && u); + + pa_assert(t); + pa_assert(u); if (t->rindex+9 > t->length) return -1; @@ -437,8 +479,8 @@ int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *u) { int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) { unsigned i; - assert(t); - assert(map); + pa_assert(t); + pa_assert(map); if (t->rindex+2 > t->length) return -1; @@ -463,8 +505,8 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { unsigned i; pa_volume_t vol; - assert(t); - assert(cvolume); + pa_assert(t); + pa_assert(cvolume); if (t->rindex+2 > t->length) return -1; @@ -489,7 +531,7 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) { void pa_tagstruct_put(pa_tagstruct *t, ...) { va_list va; - assert(t); + pa_assert(t); va_start(va, t); @@ -550,7 +592,7 @@ void pa_tagstruct_put(pa_tagstruct *t, ...) { break; default: - abort(); + pa_assert_not_reached(); } } @@ -561,7 +603,7 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) { va_list va; int ret = 0; - assert(t); + pa_assert(t); va_start(va, t); while (ret == 0) { @@ -620,9 +662,8 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) { ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *)); break; - default: - abort(); + pa_assert_not_reached(); } } diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c new file mode 100644 index 000000000..9b8794259 --- /dev/null +++ b/src/pulsecore/thread-mq.c @@ -0,0 +1,112 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thread-mq.h" + +PA_STATIC_TLS_DECLARE_NO_FREE(thread_mq); + +static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) { + pa_thread_mq *q = userdata; + pa_asyncmsgq *aq; + + pa_assert(pa_asyncmsgq_get_fd(q->outq) == fd); + pa_assert(events == PA_IO_EVENT_INPUT); + + pa_asyncmsgq_ref(aq = q->outq); + pa_asyncmsgq_after_poll(aq); + + for (;;) { + pa_msgobject *object; + int code; + void *data; + int64_t offset; + pa_memchunk chunk; + + /* Check whether there is a message for us to process */ + while (pa_asyncmsgq_get(aq, &object, &code, &data, &offset, &chunk, 0) == 0) { + int ret; + + ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk); + pa_asyncmsgq_done(aq, ret); + } + + if (pa_asyncmsgq_before_poll(aq) == 0) + break; + } + + pa_asyncmsgq_unref(aq); +} + +void pa_thread_mq_init(pa_thread_mq *q, pa_mainloop_api *mainloop) { + pa_assert(q); + pa_assert(mainloop); + + q->mainloop = mainloop; + pa_assert_se(q->inq = pa_asyncmsgq_new(0)); + pa_assert_se(q->outq = pa_asyncmsgq_new(0)); + + pa_assert_se(pa_asyncmsgq_before_poll(q->outq) == 0); + pa_assert_se(q->io_event = mainloop->io_new(mainloop, pa_asyncmsgq_get_fd(q->outq), PA_IO_EVENT_INPUT, asyncmsgq_cb, q)); +} + +void pa_thread_mq_done(pa_thread_mq *q) { + pa_assert(q); + + q->mainloop->io_free(q->io_event); + q->io_event = NULL; + + pa_asyncmsgq_unref(q->inq); + pa_asyncmsgq_unref(q->outq); + q->inq = q->outq = NULL; + + q->mainloop = NULL; +} + +void pa_thread_mq_install(pa_thread_mq *q) { + pa_assert(q); + + pa_assert(!(PA_STATIC_TLS_GET(thread_mq))); + PA_STATIC_TLS_SET(thread_mq, q); +} + +pa_thread_mq *pa_thread_mq_get(void) { + return PA_STATIC_TLS_GET(thread_mq); +} diff --git a/src/pulsecore/thread-mq.h b/src/pulsecore/thread-mq.h new file mode 100644 index 000000000..13b6e01f4 --- /dev/null +++ b/src/pulsecore/thread-mq.h @@ -0,0 +1,49 @@ +#ifndef foopulsethreadmqhfoo +#define foopulsethreadmqhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +/* Two way communication between a thread and a mainloop. Before the + * thread is started a pa_pthread_mq should be initialized and than + * attached to the thread using pa_thread_mq_install(). */ + +typedef struct pa_thread_mq { + pa_mainloop_api *mainloop; + pa_asyncmsgq *inq, *outq; + pa_io_event *io_event; +} pa_thread_mq; + +void pa_thread_mq_init(pa_thread_mq *q, pa_mainloop_api *mainloop); +void pa_thread_mq_done(pa_thread_mq *q); + +/* Install the specified pa_thread_mq object for the current thread */ +void pa_thread_mq_install(pa_thread_mq *q); + +/* Return the pa_thread_mq object that is set for the current thread */ +pa_thread_mq *pa_thread_mq_get(void); + +#endif diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c index 4271fa42f..7f43f43e7 100644 --- a/src/pulsecore/thread-posix.c +++ b/src/pulsecore/thread-posix.c @@ -26,7 +26,6 @@ #include #endif -#include #include #include #include @@ -35,56 +34,44 @@ #include #include #include +#include #include "thread.h" -#define ASSERT_SUCCESS(x) do { \ - int _r = (x); \ - assert(_r == 0); \ -} while(0) - struct pa_thread { pthread_t id; pa_thread_func_t thread_func; void *userdata; - pa_atomic_int_t running; + pa_atomic_t running; }; struct pa_tls { pthread_key_t key; }; -static pa_tls *thread_tls; -static pa_once_t thread_tls_once = PA_ONCE_INIT; - -static void tls_free_cb(void *p) { +static void thread_free_cb(void *p) { pa_thread *t = p; - assert(t); + pa_assert(t); if (!t->thread_func) /* This is a foreign thread, we need to free the struct */ pa_xfree(t); } -static void thread_tls_once_func(void) { - thread_tls = pa_tls_new(tls_free_cb); - assert(thread_tls); -} +PA_STATIC_TLS_DECLARE(current_thread, thread_free_cb); static void* internal_thread_func(void *userdata) { pa_thread *t = userdata; - assert(t); + pa_assert(t); t->id = pthread_self(); - pa_once(&thread_tls_once, thread_tls_once_func); - - pa_tls_set(thread_tls, t); + PA_STATIC_TLS_SET(current_thread, t); pa_atomic_inc(&t->running); t->thread_func(t->userdata); - pa_atomic_add(&t->running, -2); + pa_atomic_sub(&t->running, 2); return NULL; } @@ -92,7 +79,7 @@ static void* internal_thread_func(void *userdata) { pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { pa_thread *t; - assert(thread_func); + pa_assert(thread_func); t = pa_xnew(pa_thread, 1); t->thread_func = thread_func; @@ -110,26 +97,26 @@ pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) { } int pa_thread_is_running(pa_thread *t) { - assert(t); + pa_assert(t); /* Unfortunately there is no way to tell whether a "foreign" * thread is still running. See * http://udrepper.livejournal.com/16844.html for more * information */ - assert(t->thread_func); + pa_assert(t->thread_func); return pa_atomic_load(&t->running) > 0; } void pa_thread_free(pa_thread *t) { - assert(t); + pa_assert(t); pa_thread_join(t); pa_xfree(t); } int pa_thread_join(pa_thread *t) { - assert(t); + pa_assert(t); return pthread_join(t->id, NULL); } @@ -137,9 +124,7 @@ int pa_thread_join(pa_thread *t) { pa_thread* pa_thread_self(void) { pa_thread *t; - pa_once(&thread_tls_once, thread_tls_once_func); - - if ((t = pa_tls_get(thread_tls))) + if ((t = PA_STATIC_TLS_GET(current_thread))) return t; /* This is a foreign thread, let's create a pthread structure to @@ -151,19 +136,19 @@ pa_thread* pa_thread_self(void) { t->userdata = NULL; pa_atomic_store(&t->running, 2); - pa_tls_set(thread_tls, t); + PA_STATIC_TLS_SET(current_thread, t); return t; } void* pa_thread_get_data(pa_thread *t) { - assert(t); + pa_assert(t); return t->userdata; } void pa_thread_set_data(pa_thread *t, void *userdata) { - assert(t); + pa_assert(t); t->userdata = userdata; } @@ -172,7 +157,7 @@ void pa_thread_yield(void) { #ifdef HAVE_PTHREAD_YIELD pthread_yield(); #else - ASSERT_SUCCESS(sched_yield()); + pa_assert_se(sched_yield() == 0); #endif } @@ -190,14 +175,14 @@ pa_tls* pa_tls_new(pa_free_cb_t free_cb) { } void pa_tls_free(pa_tls *t) { - assert(t); + pa_assert(t); - ASSERT_SUCCESS(pthread_key_delete(t->key)); + pa_assert_se(pthread_key_delete(t->key) == 0); pa_xfree(t); } void *pa_tls_get(pa_tls *t) { - assert(t); + pa_assert(t); return pthread_getspecific(t->key); } @@ -206,7 +191,7 @@ void *pa_tls_set(pa_tls *t, void *userdata) { void *r; r = pthread_getspecific(t->key); - ASSERT_SUCCESS(pthread_setspecific(t->key, userdata)); + pa_assert_se(pthread_setspecific(t->key, userdata) == 0); return r; } diff --git a/src/pulsecore/thread-win32.c b/src/pulsecore/thread-win32.c index 46d273b41..cad1420a7 100644 --- a/src/pulsecore/thread-win32.c +++ b/src/pulsecore/thread-win32.c @@ -53,9 +53,8 @@ struct pa_tls_monitor { }; static pa_tls *thread_tls; -static pa_once_t thread_tls_once = PA_ONCE_INIT; +static pa_once thread_tls_once = PA_ONCE_INIT; static pa_tls *monitor_tls; -static pa_once_t monitor_tls_once = PA_ONCE_INIT; static void thread_tls_once_func(void) { thread_tls = pa_tls_new(NULL); @@ -66,7 +65,7 @@ static DWORD WINAPI internal_thread_func(LPVOID param) { pa_thread *t = param; assert(t); - pa_once(&thread_tls_once, thread_tls_once_func); + pa_run_once(&thread_tls_once, thread_tls_once_func); pa_tls_set(thread_tls, t); t->thread_func(t->userdata); @@ -122,7 +121,7 @@ int pa_thread_join(pa_thread *t) { } pa_thread* pa_thread_self(void) { - pa_once(&thread_tls_once, thread_tls_once_func); + pa_run_once(&thread_tls_once, thread_tls_once_func); return pa_tls_get(thread_tls); } @@ -130,12 +129,6 @@ void pa_thread_yield(void) { Sleep(0); } -static void monitor_tls_once_func(void) { - monitor_tls = pa_tls_new(NULL); - assert(monitor_tls); - pa_tls_set(monitor_tls, NULL); -} - static DWORD WINAPI monitor_thread_func(LPVOID param) { struct pa_tls_monitor *m = param; assert(m); @@ -191,7 +184,11 @@ void *pa_tls_set(pa_tls *t, void *userdata) { if (t->free_func) { struct pa_tls_monitor *m; - pa_once(&monitor_tls_once, monitor_tls_once_func); + PA_ONCE_BEGIN { + monitor_tls = pa_tls_new(NULL); + assert(monitor_tls); + pa_tls_set(monitor_tls, NULL); + } PA_ONCE_END; m = pa_tls_get(monitor_tls); if (!m) { diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h index ca1fe4da8..54ef320e1 100644 --- a/src/pulsecore/thread.h +++ b/src/pulsecore/thread.h @@ -26,6 +26,11 @@ ***/ #include +#include + +#ifndef PACKAGE +#error "Please include config.h before including this file!" +#endif typedef struct pa_thread pa_thread; @@ -48,4 +53,60 @@ void pa_tls_free(pa_tls *t); void * pa_tls_get(pa_tls *t); void *pa_tls_set(pa_tls *t, void *userdata); +#define PA_STATIC_TLS_DECLARE(name, free_cb) \ + static struct { \ + pa_once once; \ + pa_tls *tls; \ + } name##_tls = { \ + .once = PA_ONCE_INIT, \ + .tls = NULL \ + }; \ + static void name##_tls_init(void) { \ + name##_tls.tls = pa_tls_new(free_cb); \ + } \ + static inline pa_tls* name##_tls_obj(void) { \ + pa_run_once(&name##_tls.once, name##_tls_init); \ + return name##_tls.tls; \ + } \ + static void name##_tls_destructor(void) PA_GCC_DESTRUCTOR; \ + static void name##_tls_destructor(void) { \ + static void (*_free_cb)(void*) = free_cb; \ + if (!name##_tls.tls) \ + return; \ + if (_free_cb) { \ + void *p; \ + if ((p = pa_tls_get(name##_tls.tls))) \ + _free_cb(p); \ + } \ + pa_tls_free(name##_tls.tls); \ + } \ + static inline void* name##_tls_get(void) { \ + return pa_tls_get(name##_tls_obj()); \ + } \ + static inline void* name##_tls_set(void *p) { \ + return pa_tls_set(name##_tls_obj(), p); \ + } \ + struct __stupid_useless_struct_to_allow_trailing_semicolon + +#ifdef HAVE_TLS_BUILTIN +/* An optimized version of the above that requires no dynamic + * allocation if the compiler supports __thread */ +#define PA_STATIC_TLS_DECLARE_NO_FREE(name) \ + static __thread void *name##_tls = NULL; \ + static inline void* name##_tls_get(void) { \ + return name##_tls; \ + } \ + static inline void* name##_tls_set(void *p) { \ + void *r = name##_tls; \ + name##_tls = p; \ + return r; \ + } \ + struct __stupid_useless_struct_to_allow_trailing_semicolon +#else +#define PA_STATIC_TLS_DECLARE_NO_FREE(name) PA_STATIC_TLS_DECLARE(name, NULL) +#endif + +#define PA_STATIC_TLS_GET(name) (name##_tls_get()) +#define PA_STATIC_TLS_SET(name, p) (name##_tls_set(p)) + #endif diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c new file mode 100644 index 000000000..6bda3df06 --- /dev/null +++ b/src/pulsecore/time-smoother.c @@ -0,0 +1,378 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2007 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include + +#include "time-smoother.h" + +#define HISTORY_MAX 50 + +/* + * Implementation of a time smoothing algorithm to synchronize remote + * clocks to a local one. Evens out noise, adjusts to clock skew and + * allows cheap estimations of the remote time while clock updates may + * be seldom and recieved in non-equidistant intervals. + * + * Basically, we estimate the gradient of received clock samples in a + * certain history window (of size 'history_time') with linear + * regression. With that info we estimate the remote time in + * 'adjust_time' ahead and smoothen our current estimation function + * towards that point with a 3rd order polynomial interpolation with + * fitting derivatives. (more or less a b-spline) + * + * The larger 'history_time' is chosen the better we will surpress + * noise -- but we'll adjust to clock skew slower.. + * + * The larger 'adjust_time' is chosen the smoother our estimation + * function will be -- but we'll adjust to clock skew slower, too. + * + * If 'monotonic' is TRUE the resulting estimation function is + * guaranteed to be monotonic. + */ + +struct pa_smoother { + pa_usec_t adjust_time, history_time; + pa_bool_t monotonic; + + pa_usec_t time_offset; + + pa_usec_t px, py; /* Point p, where we want to reach stability */ + double dp; /* Gradient we want at point p */ + + pa_usec_t ex, ey; /* Point e, which we estimated before and need to smooth to */ + double de; /* Gradient we estimated for point e */ + + /* History of last measurements */ + pa_usec_t history_x[HISTORY_MAX], history_y[HISTORY_MAX]; + unsigned history_idx, n_history; + + /* To even out for monotonicity */ + pa_usec_t last_y; + + /* Cached parameters for our interpolation polynomial y=ax^3+b^2+cx */ + double a, b, c; + pa_bool_t abc_valid; + + pa_bool_t paused; + pa_usec_t pause_time; +}; + +pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_bool_t monotonic) { + pa_smoother *s; + + pa_assert(adjust_time > 0); + pa_assert(history_time > 0); + + s = pa_xnew(pa_smoother, 1); + s->adjust_time = adjust_time; + s->history_time = history_time; + s->time_offset = 0; + s->monotonic = monotonic; + + s->px = s->py = 0; + s->dp = 1; + + s->ex = s->ey = 0; + s->de = 1; + + s->history_idx = 0; + s->n_history = 0; + + s->last_y = 0; + + s->abc_valid = FALSE; + + s->paused = FALSE; + + return s; +} + +void pa_smoother_free(pa_smoother* s) { + pa_assert(s); + + pa_xfree(s); +} + +static void drop_old(pa_smoother *s, pa_usec_t x) { + unsigned j; + + /* First drop items from history which are too old, but make sure + * to always keep two entries in the history */ + + for (j = s->n_history; j > 2; j--) { + + if (s->history_x[s->history_idx] + s->history_time >= x) { + /* This item is still valid, and thus all following ones + * are too, so let's quit this loop */ + break; + } + + /* Item is too old, let's drop it */ + s->history_idx ++; + while (s->history_idx >= HISTORY_MAX) + s->history_idx -= HISTORY_MAX; + + s->n_history --; + } +} + +static void add_to_history(pa_smoother *s, pa_usec_t x, pa_usec_t y) { + unsigned j; + pa_assert(s); + + drop_old(s, x); + + /* Calculate position for new entry */ + j = s->history_idx + s->n_history; + while (j >= HISTORY_MAX) + j -= HISTORY_MAX; + + /* Fill in entry */ + s->history_x[j] = x; + s->history_y[j] = y; + + /* Adjust counter */ + s->n_history ++; + + /* And make sure we don't store more entries than fit in */ + if (s->n_history >= HISTORY_MAX) { + s->history_idx += s->n_history - HISTORY_MAX; + s->n_history = HISTORY_MAX; + } +} + +static double avg_gradient(pa_smoother *s, pa_usec_t x) { + unsigned i, j, c = 0; + int64_t ax = 0, ay = 0, k, t; + double r; + + drop_old(s, x); + + /* First, calculate average of all measurements */ + i = s->history_idx; + for (j = s->n_history; j > 0; j--) { + + ax += s->history_x[i]; + ay += s->history_y[i]; + c++; + + i++; + while (i >= HISTORY_MAX) + i -= HISTORY_MAX; + } + + /* Too few measurements, assume gradient of 1 */ + if (c < 2) + return 1; + + ax /= c; + ay /= c; + + /* Now, do linear regression */ + k = t = 0; + + i = s->history_idx; + for (j = s->n_history; j > 0; j--) { + int64_t dx, dy; + + dx = (int64_t) s->history_x[i] - ax; + dy = (int64_t) s->history_y[i] - ay; + + k += dx*dy; + t += dx*dx; + + i++; + while (i >= HISTORY_MAX) + i -= HISTORY_MAX; + } + + r = (double) k / t; + + return s->monotonic && r < 0 ? 0 : r; +} + +static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) { + pa_assert(s); + pa_assert(y); + + if (x >= s->px) { + int64_t t; + + /* The requested point is right of the point where we wanted + * to be on track again, thus just linearly estimate */ + + t = (int64_t) s->py + (int64_t) (s->dp * (x - s->px)); + + if (t < 0) + t = 0; + + *y = (pa_usec_t) t; + + if (deriv) + *deriv = s->dp; + + } else { + + if (!s->abc_valid) { + pa_usec_t ex, ey, px, py; + int64_t kx, ky; + double de, dp; + + /* Ok, we're not yet on track, thus let's interpolate, and + * make sure that the first derivative is smooth */ + + /* We have two points: (ex|ey) and (px|py) with two gradients + * at these points de and dp. We do a polynomial interpolation + * of degree 3 with these 6 values */ + + ex = s->ex; ey = s->ey; + px = s->px; py = s->py; + de = s->de; dp = s->dp; + + pa_assert(ex < px); + + /* To increase the dynamic range and symplify calculation, we + * move these values to the origin */ + kx = (int64_t) px - (int64_t) ex; + ky = (int64_t) py - (int64_t) ey; + + /* Calculate a, b, c for y=ax^3+b^2+cx */ + s->c = de; + s->b = (((double) (3*ky)/kx - dp - 2*de)) / kx; + s->a = (dp/kx - 2*s->b - de/kx) / (3*kx); + + s->abc_valid = TRUE; + } + + /* Move to origin */ + x -= s->ex; + + /* Horner scheme */ + *y = (pa_usec_t) ((double) x * (s->c + (double) x * (s->b + (double) x * s->a))); + + /* Move back from origin */ + *y += s->ey; + + /* Horner scheme */ + if (deriv) + *deriv = s->c + ((double) x * (s->b*2 + (double) x * s->a*3)); + } + + /* Guarantee monotonicity */ + if (s->monotonic) { + + if (*y < s->last_y) + *y = s->last_y; + else + s->last_y = *y; + + if (deriv && *deriv < 0) + *deriv = 0; + } +} + +void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) { + pa_usec_t ney; + double nde; + + pa_assert(s); + pa_assert(x >= s->time_offset); + + /* Fix up x value */ + if (s->paused) + x = s->pause_time; + else + x -= s->time_offset; + + pa_assert(x >= s->ex); + + /* First, we calculate the position we'd estimate for x, so that + * we can adjust our position smoothly from this one */ + estimate(s, x, &ney, &nde); + s->ex = x; s->ey = ney; s->de = nde; + + /* Then, we add the new measurement to our history */ + add_to_history(s, x, y); + + /* And determine the average gradient of the history */ + s->dp = avg_gradient(s, x); + + /* And calculate when we want to be on track again */ + s->px = x + s->adjust_time; + s->py = y + s->dp *s->adjust_time; + + s->abc_valid = FALSE; +} + +pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x) { + pa_usec_t y; + + pa_assert(s); + pa_assert(x >= s->time_offset); + + /* Fix up x value */ + if (s->paused) + x = s->pause_time; + else + x -= s->time_offset; + + pa_assert(x >= s->ex); + + estimate(s, x, &y, NULL); + return y; +} + +void pa_smoother_set_time_offset(pa_smoother *s, pa_usec_t offset) { + pa_assert(s); + + s->time_offset = offset; +} + +void pa_smoother_pause(pa_smoother *s, pa_usec_t x) { + pa_assert(s); + + if (s->paused) + return; + + s->paused = TRUE; + s->pause_time = x; +} + +void pa_smoother_resume(pa_smoother *s, pa_usec_t x) { + pa_assert(s); + + if (!s->paused) + return; + + s->paused = FALSE; + s->time_offset += x - s->pause_time; +} diff --git a/src/pulsecore/time-smoother.h b/src/pulsecore/time-smoother.h new file mode 100644 index 000000000..8b8512e2d --- /dev/null +++ b/src/pulsecore/time-smoother.h @@ -0,0 +1,43 @@ +#ifndef foopulsetimesmootherhfoo +#define foopulsetimesmootherhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2007 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +typedef struct pa_smoother pa_smoother; + +pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_bool_t monotonic); +void pa_smoother_free(pa_smoother* s); + +void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y); +pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x); + +void pa_smoother_set_time_offset(pa_smoother *s, pa_usec_t offset); + +void pa_smoother_pause(pa_smoother *s, pa_usec_t x); +void pa_smoother_resume(pa_smoother *s, pa_usec_t x); + +#endif diff --git a/src/pulsecore/tokenizer.c b/src/pulsecore/tokenizer.c index 117c7f881..f79c19c54 100644 --- a/src/pulsecore/tokenizer.c +++ b/src/pulsecore/tokenizer.c @@ -26,20 +26,16 @@ #endif #include -#include #include #include #include #include +#include #include "tokenizer.h" -struct pa_tokenizer { - pa_dynarray *dynarray; -}; - static void token_free(void *p, PA_GCC_UNUSED void *userdata) { pa_xfree(p); } @@ -48,7 +44,9 @@ static void parse(pa_dynarray*a, const char *s, unsigned args) { int infty = 0; const char delimiter[] = " \t\n\r"; const char *p; - assert(a && s); + + pa_assert(a); + pa_assert(s); if (args == 0) infty = 1; @@ -70,23 +68,23 @@ static void parse(pa_dynarray*a, const char *s, unsigned args) { } pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args) { - pa_tokenizer *t; + pa_dynarray *a; - t = pa_xmalloc(sizeof(pa_tokenizer)); - t->dynarray = pa_dynarray_new(); - assert(t->dynarray); - - parse(t->dynarray, s, args); - return t; + a = pa_dynarray_new(); + parse(a, s, args); + return (pa_tokenizer*) a; } void pa_tokenizer_free(pa_tokenizer *t) { - assert(t); - pa_dynarray_free(t->dynarray, token_free, NULL); - pa_xfree(t); + pa_dynarray *a = (pa_dynarray*) t; + + pa_assert(a); + pa_dynarray_free(a, token_free, NULL); } const char *pa_tokenizer_get(pa_tokenizer *t, unsigned i) { - assert(t); - return pa_dynarray_get(t->dynarray, i); + pa_dynarray *a = (pa_dynarray*) t; + + pa_assert(a); + return pa_dynarray_get(a, i); } diff --git a/src/pulsecore/winsock.h b/src/pulsecore/winsock.h index ae868b384..0352bf4d4 100644 --- a/src/pulsecore/winsock.h +++ b/src/pulsecore/winsock.h @@ -15,6 +15,8 @@ #define EHOSTUNREACH WSAEHOSTUNREACH #define EWOULDBLOCK WSAEWOULDBLOCK +typedef long suseconds_t; + #endif #ifdef HAVE_WS2TCPIP_H diff --git a/src/pulsecore/x11prop.c b/src/pulsecore/x11prop.c index 5b85ea426..a740e39b4 100644 --- a/src/pulsecore/x11prop.c +++ b/src/pulsecore/x11prop.c @@ -32,7 +32,6 @@ #include "x11prop.h" - void pa_x11_set_prop(Display *d, const char *name, const char *data) { Atom a = XInternAtom(d, name, False); XChangeProperty(d, RootWindow(d, 0), a, XA_STRING, 8, PropModeReplace, (const unsigned char*) data, strlen(data)+1); diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c index 6a6a26924..800a94582 100644 --- a/src/pulsecore/x11wrap.c +++ b/src/pulsecore/x11wrap.c @@ -21,7 +21,10 @@ USA. ***/ -#include +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include @@ -29,6 +32,8 @@ #include #include #include +#include +#include #include "x11wrap.h" @@ -42,8 +47,8 @@ struct pa_x11_internal { }; struct pa_x11_wrapper { + PA_REFCNT_DECLARE; pa_core *core; - int ref; char *property_name; Display *display; @@ -64,7 +69,8 @@ struct pa_x11_client { /* Dispatch all pending X11 events */ static void work(pa_x11_wrapper *w) { - assert(w && w->ref >= 1); + pa_assert(w); + pa_assert(PA_REFCNT_VALUE(w) >= 1); while (XPending(w->display)) { pa_x11_client *c; @@ -72,7 +78,7 @@ static void work(pa_x11_wrapper *w) { XNextEvent(w->display, &e); for (c = w->clients; c; c = c->next) { - assert(c->callback); + pa_assert(c->callback); if (c->callback(w, &e, c->userdata) != 0) break; } @@ -82,14 +88,24 @@ static void work(pa_x11_wrapper *w) { /* IO notification event for the X11 display connection */ static void display_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { pa_x11_wrapper *w = userdata; - assert(m && e && fd >= 0 && w && w->ref >= 1); + + pa_assert(m); + pa_assert(e); + pa_assert(fd >= 0); + pa_assert(w); + pa_assert(PA_REFCNT_VALUE(w) >= 1); + work(w); } /* Deferred notification event. Called once each main loop iteration */ static void defer_event(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { pa_x11_wrapper *w = userdata; - assert(m && e && w && w->ref >= 1); + + pa_assert(m); + pa_assert(e); + pa_assert(w); + pa_assert(PA_REFCNT_VALUE(w) >= 1); m->defer_enable(e, 0); @@ -99,7 +115,12 @@ static void defer_event(pa_mainloop_api *m, pa_defer_event *e, void *userdata) { /* IO notification event for X11 internal connections */ static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) { pa_x11_wrapper *w = userdata; - assert(m && e && fd >= 0 && w && w->ref >= 1); + + pa_assert(m); + pa_assert(e); + pa_assert(fd >= 0); + pa_assert(w); + pa_assert(PA_REFCNT_VALUE(w) >= 1); XProcessInternalConnection(w->display, fd); @@ -109,10 +130,9 @@ static void internal_io_event(pa_mainloop_api *m, pa_io_event *e, int fd, PA_GCC /* Add a new IO source for the specified X11 internal connection */ static pa_x11_internal* x11_internal_add(pa_x11_wrapper *w, int fd) { pa_x11_internal *i; - assert(fd >= 0); + pa_assert(fd >= 0); - i = pa_xmalloc(sizeof(pa_x11_internal)); - assert(i); + i = pa_xnew(pa_x11_internal, 1); i->wrapper = w; i->io_event = w->core->mainloop->io_new(w->core->mainloop, fd, PA_IO_EVENT_INPUT, internal_io_event, w); i->fd = fd; @@ -123,7 +143,7 @@ static pa_x11_internal* x11_internal_add(pa_x11_wrapper *w, int fd) { /* Remove an IO source for an X11 internal connection */ static void x11_internal_remove(pa_x11_wrapper *w, pa_x11_internal *i) { - assert(i); + pa_assert(i); PA_LLIST_REMOVE(pa_x11_internal, w->internals, i); w->core->mainloop->io_free(i->io_event); @@ -133,7 +153,10 @@ static void x11_internal_remove(pa_x11_wrapper *w, pa_x11_internal *i) { /* Implementation of XConnectionWatchProc */ static void x11_watch(Display *display, XPointer userdata, int fd, Bool opening, XPointer *watch_data) { pa_x11_wrapper *w = (pa_x11_wrapper*) userdata; - assert(display && w && fd >= 0); + + pa_assert(display); + pa_assert(w); + pa_assert(fd >= 0); if (opening) *watch_data = (XPointer) x11_internal_add(w, fd); @@ -144,16 +167,15 @@ static void x11_watch(Display *display, XPointer userdata, int fd, Bool opening, static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char *t) { pa_x11_wrapper*w; Display *d; - int r; if (!(d = XOpenDisplay(name))) { pa_log("XOpenDisplay() failed"); return NULL; } - w = pa_xmalloc(sizeof(pa_x11_wrapper)); + w = pa_xnew(pa_x11_wrapper, 1); + PA_REFCNT_INIT(w); w->core = c; - w->ref = 1; w->property_name = pa_xstrdup(t); w->display = d; @@ -165,20 +187,17 @@ static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char XAddConnectionWatch(d, x11_watch, (XPointer) w); - r = pa_property_set(c, w->property_name, w); - assert(r >= 0); + pa_assert_se(pa_property_set(c, w->property_name, w) >= 0); return w; } static void x11_wrapper_free(pa_x11_wrapper*w) { - int r; - assert(w); + pa_assert(w); - r = pa_property_remove(w->core, w->property_name); - assert(r >= 0); + pa_assert_se(pa_property_remove(w->core, w->property_name) >= 0); - assert(!w->clients); + pa_assert(!w->clients); XRemoveConnectionWatch(w->display, x11_watch, (XPointer) w); XCloseDisplay(w->display); @@ -196,9 +215,10 @@ static void x11_wrapper_free(pa_x11_wrapper*w) { pa_x11_wrapper* pa_x11_wrapper_get(pa_core *c, const char *name) { char t[256]; pa_x11_wrapper *w; - assert(c); - snprintf(t, sizeof(t), "x11-wrapper%s%s", name ? "-" : "", name ? name : ""); + pa_core_assert_ref(c); + + pa_snprintf(t, sizeof(t), "x11-wrapper%s%s", name ? "-" : "", name ? name : ""); if ((w = pa_property_get(c, t))) return pa_x11_wrapper_ref(w); @@ -206,20 +226,24 @@ pa_x11_wrapper* pa_x11_wrapper_get(pa_core *c, const char *name) { } pa_x11_wrapper* pa_x11_wrapper_ref(pa_x11_wrapper *w) { - assert(w && w->ref >= 1); - w->ref++; + pa_assert(w); + pa_assert(PA_REFCNT_VALUE(w) >= 1); + + PA_REFCNT_INC(w); return w; } void pa_x11_wrapper_unref(pa_x11_wrapper* w) { - assert(w && w->ref >= 1); + pa_assert(w); + pa_assert(PA_REFCNT_VALUE(w) >= 1); - if (!(--w->ref)) + if (PA_REFCNT_DEC(w) <= 0) x11_wrapper_free(w); } Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w) { - assert(w && w->ref >= 1); + pa_assert(w); + pa_assert(PA_REFCNT_VALUE(w) >= 1); /* Somebody is using us, schedule a output buffer flush */ w->core->mainloop->defer_enable(w->defer_event, 1); @@ -229,9 +253,11 @@ Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w) { pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata) { pa_x11_client *c; - assert(w && w->ref >= 1); - c = pa_xmalloc(sizeof(pa_x11_client)); + pa_assert(w); + pa_assert(PA_REFCNT_VALUE(w) >= 1); + + c = pa_xnew(pa_x11_client, 1); c->wrapper = w; c->callback = cb; c->userdata = userdata; @@ -242,7 +268,9 @@ pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w, } void pa_x11_client_free(pa_x11_client *c) { - assert(c && c->wrapper && c->wrapper->ref >= 1); + pa_assert(c); + pa_assert(c->wrapper); + pa_assert(PA_REFCNT_VALUE(c->wrapper) >= 1); PA_LLIST_REMOVE(pa_x11_client, c->wrapper->clients, c); pa_xfree(c); diff --git a/src/tests/asyncmsgq-test.c b/src/tests/asyncmsgq-test.c new file mode 100644 index 000000000..380c5e7f6 --- /dev/null +++ b/src/tests/asyncmsgq-test.c @@ -0,0 +1,110 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +enum { + OPERATION_A, + OPERATION_B, + OPERATION_C, + QUIT +}; + +static void the_thread(void *_q) { + pa_asyncmsgq *q = _q; + int quit = 0; + + do { + int code = 0; + + pa_assert_se(pa_asyncmsgq_get(q, NULL, &code, NULL, NULL, NULL, 1) == 0); + + switch (code) { + + case OPERATION_A: + printf("Operation A\n"); + break; + + case OPERATION_B: + printf("Operation B\n"); + break; + + case OPERATION_C: + printf("Operation C\n"); + break; + + case QUIT: + printf("quit\n"); + quit = 1; + break; + } + + pa_asyncmsgq_done(q, 0); + + } while (!quit); +} + +int main(int argc, char *argv[]) { + pa_asyncmsgq *q; + pa_thread *t; + + pa_assert_se(q = pa_asyncmsgq_new(0)); + + pa_assert_se(t = pa_thread_new(the_thread, q)); + + printf("Operation A post\n"); + pa_asyncmsgq_post(q, NULL, OPERATION_A, NULL, 0, NULL, NULL); + + pa_thread_yield(); + + printf("Operation B post\n"); + pa_asyncmsgq_post(q, NULL, OPERATION_B, NULL, 0, NULL, NULL); + + pa_thread_yield(); + + printf("Operation C send\n"); + pa_asyncmsgq_send(q, NULL, OPERATION_C, NULL, 0, NULL); + + pa_thread_yield(); + + printf("Quit post\n"); + pa_asyncmsgq_post(q, NULL, QUIT, NULL, 0, NULL, NULL); + + pa_thread_free(t); + + pa_asyncmsgq_unref(q); + + return 0; +} diff --git a/src/tests/asyncq-test.c b/src/tests/asyncq-test.c new file mode 100644 index 000000000..09b200471 --- /dev/null +++ b/src/tests/asyncq-test.c @@ -0,0 +1,87 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static void producer(void *_q) { + pa_asyncq *q = _q; + int i; + + for (i = 0; i < 1000; i++) { + printf("pushing %i\n", i); + pa_asyncq_push(q, PA_UINT_TO_PTR(i+1), 1); + } + + pa_asyncq_push(q, PA_UINT_TO_PTR(-1), 1); + printf("pushed end\n"); +} + +static void consumer(void *_q) { + pa_asyncq *q = _q; + void *p; + int i; + + sleep(1); + + for (i = 0;; i++) { + p = pa_asyncq_pop(q, 1); + + if (p == PA_UINT_TO_PTR(-1)) + break; + + pa_assert(p == PA_UINT_TO_PTR(i+1)); + + printf("popped %i\n", i); + } + + printf("popped end\n"); +} + +int main(int argc, char *argv[]) { + pa_asyncq *q; + pa_thread *t1, *t2; + + pa_assert_se(q = pa_asyncq_new(0)); + + pa_assert_se(t1 = pa_thread_new(producer, q)); + pa_assert_se(t2 = pa_thread_new(consumer, q)); + + pa_thread_free(t1); + pa_thread_free(t2); + + pa_asyncq_free(q, NULL); + + return 0; +} diff --git a/src/tests/hook-list-test.c b/src/tests/hook-list-test.c index 6879eae53..8628f5211 100644 --- a/src/tests/hook-list-test.c +++ b/src/tests/hook-list-test.c @@ -1,5 +1,9 @@ /* $Id$ */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c index 3953043fb..85a509d4e 100644 --- a/src/tests/interpol-test.c +++ b/src/tests/interpol-test.c @@ -137,7 +137,7 @@ int main(int argc, char *argv[]) { pa_gettimeofday(&now); rtc = pa_timeval_diff(&now, &start); - printf("%i\t%llu\t%llu\t%llu\t%llu\t%u\n", k, rtc, t, rtc-old_rtc, t-old_t, changed); + printf("%i\t%llu\t%llu\t%llu\t%llu\t%u\n", k, (unsigned long long) rtc, (unsigned long long) t, (unsigned long long) (rtc-old_rtc), (unsigned long long) (t-old_t), changed); old_t = t; old_rtc = rtc; } diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c index db76712b4..d10131184 100644 --- a/src/tests/mcalign-test.c +++ b/src/tests/mcalign-test.c @@ -59,24 +59,29 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { c.index = c.length = 0; } - assert(c.index < c.memblock->length); + assert(c.index < pa_memblock_get_length(c.memblock)); - l = c.memblock->length - c.index; + l = pa_memblock_get_length(c.memblock) - c.index; l = l <= 1 ? l : rand() % (l-1) +1 ; - if ((r = read(STDIN_FILENO, (uint8_t*) c.memblock->data + c.index, l)) <= 0) { + p = pa_memblock_acquire(c.memblock); + + if ((r = read(STDIN_FILENO, (uint8_t*) p + c.index, l)) <= 0) { + pa_memblock_release(c.memblock); fprintf(stderr, "read() failed: %s\n", r < 0 ? strerror(errno) : "EOF"); break; } + pa_memblock_release(c.memblock); + c.length = r; pa_mcalign_push(a, &c); fprintf(stderr, "Read %ld bytes\n", (long)r); c.index += r; - if (c.index >= c.memblock->length) { + if (c.index >= pa_memblock_get_length(c.memblock)) { pa_memblock_unref(c.memblock); pa_memchunk_reset(&c); } @@ -87,7 +92,9 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { if (pa_mcalign_pop(a, &t) < 0) break; - pa_loop_write(STDOUT_FILENO, (uint8_t*) t.memblock->data + t.index, t.length, NULL); + p = pa_memblock_acquire(t.memblock); + pa_loop_write(STDOUT_FILENO, (uint8_t*) p + t.index, t.length, NULL); + pa_memblock_release(t.memblock); fprintf(stderr, "Wrote %lu bytes.\n", (unsigned long) t.length); pa_memblock_unref(t.memblock); diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c index 8d25ba38f..2b9d3401d 100644 --- a/src/tests/memblock-test.c +++ b/src/tests/memblock-test.c @@ -23,11 +23,11 @@ #include #endif -#include #include #include #include +#include #include static void release_cb(pa_memimport *i, uint32_t block_id, void *userdata) { @@ -76,6 +76,7 @@ int main(int argc, char *argv[]) { pa_memblock* blocks[5]; uint32_t id, shm_id; size_t offset, size; + char *x; const char txt[] = "This is a test!"; @@ -87,13 +88,20 @@ int main(int argc, char *argv[]) { pa_mempool_get_shm_id(pool_b, &id_b); pa_mempool_get_shm_id(pool_c, &id_c); - assert(pool_a && pool_b && pool_c); + pa_assert(pool_a && pool_b && pool_c); blocks[0] = pa_memblock_new_fixed(pool_a, (void*) txt, sizeof(txt), 1); + blocks[1] = pa_memblock_new(pool_a, sizeof(txt)); - snprintf(blocks[1]->data, blocks[1]->length, "%s", txt); + x = pa_memblock_acquire(blocks[1]); + snprintf(x, pa_memblock_get_length(blocks[1]), "%s", txt); + pa_memblock_release(blocks[1]); + blocks[2] = pa_memblock_new_pool(pool_a, sizeof(txt)); - snprintf(blocks[2]->data, blocks[2]->length, "%s", txt); + x = pa_memblock_acquire(blocks[2]); + snprintf(x, pa_memblock_get_length(blocks[2]), "%s", txt); + pa_memblock_release(blocks[2]); + blocks[3] = pa_memblock_new_malloced(pool_a, pa_xstrdup(txt), sizeof(txt)); blocks[4] = NULL; @@ -101,43 +109,47 @@ int main(int argc, char *argv[]) { printf("Memory block %u\n", i); mb_a = blocks[i]; - assert(mb_a); + pa_assert(mb_a); export_a = pa_memexport_new(pool_a, revoke_cb, (void*) "A"); export_b = pa_memexport_new(pool_b, revoke_cb, (void*) "B"); - assert(export_a && export_b); + pa_assert(export_a && export_b); import_b = pa_memimport_new(pool_b, release_cb, (void*) "B"); import_c = pa_memimport_new(pool_c, release_cb, (void*) "C"); - assert(import_b && import_c); + pa_assert(import_b && import_c); r = pa_memexport_put(export_a, mb_a, &id, &shm_id, &offset, &size); - assert(r >= 0); - assert(shm_id == id_a); + pa_assert(r >= 0); + pa_assert(shm_id == id_a); printf("A: Memory block exported as %u\n", id); mb_b = pa_memimport_get(import_b, id, shm_id, offset, size); - assert(mb_b); + pa_assert(mb_b); r = pa_memexport_put(export_b, mb_b, &id, &shm_id, &offset, &size); - assert(r >= 0); - assert(shm_id == id_a || shm_id == id_b); + pa_assert(r >= 0); + pa_assert(shm_id == id_a || shm_id == id_b); pa_memblock_unref(mb_b); printf("B: Memory block exported as %u\n", id); mb_c = pa_memimport_get(import_c, id, shm_id, offset, size); - assert(mb_c); - printf("1 data=%s\n", (char*) mb_c->data); + pa_assert(mb_c); + x = pa_memblock_acquire(mb_c); + printf("1 data=%s\n", x); + pa_memblock_release(mb_c); print_stats(pool_a, "A"); print_stats(pool_b, "B"); print_stats(pool_c, "C"); pa_memexport_free(export_b); - printf("2 data=%s\n", (char*) mb_c->data); + x = pa_memblock_acquire(mb_c); + printf("2 data=%s\n", x); + pa_memblock_release(mb_c); pa_memblock_unref(mb_c); pa_memimport_free(import_b); diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c index 1c0b7fed3..25ea399bc 100644 --- a/src/tests/memblockq-test.c +++ b/src/tests/memblockq-test.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -48,22 +49,22 @@ int main(int argc, char *argv[]) { bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, silence); assert(bq); - chunk1.memblock = pa_memblock_new_fixed(p, (char*) "AA", 2, 1); + chunk1.memblock = pa_memblock_new_fixed(p, (char*) "11", 2, 1); chunk1.index = 0; chunk1.length = 2; assert(chunk1.memblock); - chunk2.memblock = pa_memblock_new_fixed(p, (char*) "TTBB", 4, 1); + chunk2.memblock = pa_memblock_new_fixed(p, (char*) "XX22", 4, 1); chunk2.index = 2; chunk2.length = 2; assert(chunk2.memblock); - chunk3.memblock = pa_memblock_new_fixed(p, (char*) "ZZZZ", 4, 1); + chunk3.memblock = pa_memblock_new_fixed(p, (char*) "3333", 4, 1); chunk3.index = 0; chunk3.length = 4; assert(chunk3.memblock); - chunk4.memblock = pa_memblock_new_fixed(p, (char*) "KKKKKKKK", 8, 1); + chunk4.memblock = pa_memblock_new_fixed(p, (char*) "44444444", 8, 1); chunk4.index = 0; chunk4.length = 8; assert(chunk4.memblock); @@ -115,13 +116,12 @@ int main(int argc, char *argv[]) { chunk3.index += 2; chunk3.length -= 2; - ret = pa_memblockq_push(bq, &chunk3); assert(ret == 0); - printf(">"); + pa_memblockq_shorten(bq, pa_memblockq_get_length(bq)-2); - pa_memblockq_shorten(bq, 6); + printf(">"); for (;;) { pa_memchunk out; @@ -131,11 +131,13 @@ int main(int argc, char *argv[]) { if (pa_memblockq_peek(bq, &out) < 0) break; - for (e = (char*) out.memblock->data + out.index, n = 0; n < out.length; n++) + p = pa_memblock_acquire(out.memblock); + for (e = (char*) p + out.index, n = 0; n < out.length; n++) printf("%c", *e); + pa_memblock_release(out.memblock); pa_memblock_unref(out.memblock); - pa_memblockq_drop(bq, &out, out.length); + pa_memblockq_drop(bq, out.length); } printf("<\n"); diff --git a/src/tests/queue-test.c b/src/tests/queue-test.c new file mode 100644 index 000000000..b357ab10e --- /dev/null +++ b/src/tests/queue-test.c @@ -0,0 +1,69 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + pa_queue *q; + + pa_assert_se(q = pa_queue_new()); + + pa_assert(pa_queue_is_empty(q)); + + pa_queue_push(q, (void*) "eins"); + pa_log("%s\n", (char*) pa_queue_pop(q)); + + pa_assert(pa_queue_is_empty(q)); + + pa_queue_push(q, (void*) "zwei"); + pa_queue_push(q, (void*) "drei"); + pa_queue_push(q, (void*) "vier"); + + pa_log("%s\n", (char*) pa_queue_pop(q)); + pa_log("%s\n", (char*) pa_queue_pop(q)); + + pa_queue_push(q, (void*) "fuenf"); + + pa_log("%s\n", (char*) pa_queue_pop(q)); + pa_log("%s\n", (char*) pa_queue_pop(q)); + + pa_assert(pa_queue_is_empty(q)); + + pa_queue_push(q, (void*) "sechs"); + pa_queue_push(q, (void*) "sieben"); + + pa_queue_free(q, NULL, NULL); + + return 0; +} diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c new file mode 100644 index 000000000..3b4a73865 --- /dev/null +++ b/src/tests/resampler-test.c @@ -0,0 +1,227 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +static float swap_float(float a) { + uint32_t *b = (uint32_t*) &a; + *b = PA_UINT32_SWAP(*b); + return a; +} + +static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) { + void *d; + unsigned i; + + d = pa_memblock_acquire(chunk->memblock); + + switch (ss->format) { + + case PA_SAMPLE_U8: + case PA_SAMPLE_ULAW: + case PA_SAMPLE_ALAW: { + uint8_t *u = d; + + for (i = 0; i < chunk->length / pa_frame_size(ss); i++) + printf("0x%02x ", *(u++)); + + break; + } + + case PA_SAMPLE_S16NE: + case PA_SAMPLE_S16RE: { + uint16_t *u = d; + + for (i = 0; i < chunk->length / pa_frame_size(ss); i++) + printf("0x%04x ", *(u++)); + + break; + } + + case PA_SAMPLE_FLOAT32NE: + case PA_SAMPLE_FLOAT32RE: { + float *u = d; + + for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { + printf("%1.3g ", ss->format == PA_SAMPLE_FLOAT32NE ? *u : swap_float(*u)); + u++; + } + + break; + } + + default: + pa_assert_not_reached(); + } + + printf("\n"); + + pa_memblock_release(chunk->memblock); +} + +static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) { + pa_memblock *r; + void *d; + unsigned i; + + pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10)); + d = pa_memblock_acquire(r); + + switch (ss->format) { + + case PA_SAMPLE_U8: + case PA_SAMPLE_ULAW: + case PA_SAMPLE_ALAW: { + uint8_t *u = d; + + u[0] = 0x00; + u[1] = 0xFF; + u[2] = 0x7F; + u[3] = 0x80; + u[4] = 0x9f; + u[5] = 0x3f; + u[6] = 0x1; + u[7] = 0xF0; + u[8] = 0x20; + u[9] = 0x21; + break; + } + + case PA_SAMPLE_S16NE: + case PA_SAMPLE_S16RE: { + uint16_t *u = d; + + u[0] = 0x0000; + u[1] = 0xFFFF; + u[2] = 0x7FFF; + u[3] = 0x8000; + u[4] = 0x9fff; + u[5] = 0x3fff; + u[6] = 0x1; + u[7] = 0xF000; + u[8] = 0x20; + u[9] = 0x21; + break; + } + + case PA_SAMPLE_FLOAT32NE: + case PA_SAMPLE_FLOAT32RE: { + float *u = d; + + u[0] = 0.0; + u[1] = -1.0; + u[2] = 1.0; + u[3] = 4711; + u[4] = 0.222; + u[5] = 0.33; + u[6] = -.3; + u[7] = 99; + u[8] = -0.555; + u[9] = -.123; + + if (ss->format == PA_SAMPLE_FLOAT32RE) + for (i = 0; i < 10; i++) + u[i] = swap_float(u[i]); + + break; + } + + default: + pa_assert_not_reached(); + } + + pa_memblock_release(r); + + return r; +} + +int main(int argc, char *argv[]) { + pa_mempool *pool; + pa_sample_spec a, b; + pa_cvolume v; + + oil_init(); + pa_log_set_maximal_level(PA_LOG_DEBUG); + + pa_assert_se(pool = pa_mempool_new(FALSE)); + + a.channels = b.channels = 1; + a.rate = b.rate = 44100; + + v.channels = a.channels; + v.values[0] = pa_sw_volume_from_linear(0.5); + + for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) { + for (b.format = 0; b.format < PA_SAMPLE_MAX; b.format ++) { + + pa_resampler *forth, *back; + pa_memchunk i, j, k; + + printf("=== %s -> %s -> %s -> /2\n", + pa_sample_format_to_string(a.format), + pa_sample_format_to_string(b.format), + pa_sample_format_to_string(a.format)); + + pa_assert_se(forth = pa_resampler_new(pool, &a, NULL, &b, NULL, PA_RESAMPLER_AUTO, FALSE)); + pa_assert_se(back = pa_resampler_new(pool, &b, NULL, &a, NULL, PA_RESAMPLER_AUTO, FALSE)); + + i.memblock = generate_block(pool, &a); + i.length = pa_memblock_get_length(i.memblock); + i.index = 0; + pa_resampler_run(forth, &i, &j); + pa_resampler_run(back, &j, &k); + + dump_block(&a, &i); + dump_block(&b, &j); + dump_block(&a, &k); + + pa_memblock_unref(j.memblock); + pa_memblock_unref(k.memblock); + + pa_volume_memchunk(&i, &a, &v); + dump_block(&a, &i); + + pa_memblock_unref(i.memblock); + + pa_resampler_free(forth); + pa_resampler_free(back); + } + } + + pa_mempool_free(pool); + + return 0; +} diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c new file mode 100644 index 000000000..3ab992a19 --- /dev/null +++ b/src/tests/rtpoll-test.c @@ -0,0 +1,91 @@ +/* $Id: thread-test.c 1621 2007-08-10 22:00:22Z lennart $ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include + +static int before(pa_rtpoll_item *i) { + pa_log("before"); + return 0; +} + +static void after(pa_rtpoll_item *i) { + pa_log("after"); +} + +static int worker(pa_rtpoll_item *w) { + pa_log("worker"); + return 0; +} + +int main(int argc, char *argv[]) { + pa_rtpoll *p; + pa_rtpoll_item *i, *w; + struct pollfd *pollfd; + + pa_rtsig_configure(SIGRTMIN+10, SIGRTMAX); + + p = pa_rtpoll_new(); + + i = pa_rtpoll_item_new(p, PA_RTPOLL_EARLY, 1); + pa_rtpoll_item_set_before_callback(i, before); + pa_rtpoll_item_set_after_callback(i, after); + + pollfd = pa_rtpoll_item_get_pollfd(i, NULL); + pollfd->fd = 0; + pollfd->events = POLLIN; + + w = pa_rtpoll_item_new(p, PA_RTPOLL_NORMAL, 0); + pa_rtpoll_item_set_before_callback(w, worker); + + pa_rtpoll_install(p); + pa_rtpoll_set_timer_periodic(p, 10000000); /* 10 s */ + + pa_rtpoll_run(p, 1); + + pa_rtpoll_item_free(i); + + i = pa_rtpoll_item_new(p, PA_RTPOLL_EARLY, 1); + pa_rtpoll_item_set_before_callback(i, before); + pa_rtpoll_item_set_after_callback(i, after); + + pollfd = pa_rtpoll_item_get_pollfd(i, NULL); + pollfd->fd = 0; + pollfd->events = POLLIN; + + pa_rtpoll_run(p, 1); + + pa_rtpoll_item_free(i); + + pa_rtpoll_item_free(w); + + pa_rtpoll_free(p); + + return 0; +} diff --git a/src/tests/sig2str-test.c b/src/tests/sig2str-test.c new file mode 100644 index 000000000..52cb9db4d --- /dev/null +++ b/src/tests/sig2str-test.c @@ -0,0 +1,39 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +int main(int argc, char *argv[]) { + int sig; + + for (sig = -1; sig <= NSIG; sig++) + printf("%i = %s\n", sig, pa_sig2str(sig)); + + return 0; +} diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c new file mode 100644 index 000000000..caa7df70a --- /dev/null +++ b/src/tests/smoother-test.c @@ -0,0 +1,80 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +int main(int argc, char*argv[]) { + pa_usec_t x; + unsigned u = 0; + pa_smoother *s; + int m; + +/* unsigned msec[] = { */ +/* 200, 200, */ +/* 300, 320, */ +/* 400, 400, */ +/* 500, 480, */ +/* 0, 0 */ +/* }; */ + + int msec[200]; + + srand(0); + + for (m = 0, u = 0; u < PA_ELEMENTSOF(msec)-2; u+= 2) { + + msec[u] = m+1; + msec[u+1] = m + rand() % 2000 - 1000; + + m += rand() % 100; + + if (msec[u+1] < 0) + msec[u+1] = 0; + } + + msec[PA_ELEMENTSOF(msec)-2] = 0; + msec[PA_ELEMENTSOF(msec)-1] = 0; + + s = pa_smoother_new(1000*PA_USEC_PER_MSEC, 2000*PA_USEC_PER_MSEC, TRUE); + + for (x = 0, u = 0; x < PA_USEC_PER_SEC * 10; x += PA_USEC_PER_MSEC) { + + while (msec[u] > 0 && (pa_usec_t) msec[u]*PA_USEC_PER_MSEC < x) { + pa_smoother_put(s, msec[u]*PA_USEC_PER_MSEC, msec[u+1]*PA_USEC_PER_MSEC); + printf("%i\t\t%i\n", msec[u], msec[u+1]); + u += 2; + } + + printf("%llu\t%llu\n", x/PA_USEC_PER_MSEC, pa_smoother_get(s, x)/PA_USEC_PER_MSEC); + } + + pa_smoother_free(s); + + return 0; +} diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c index 9d0e5de16..558e53a5b 100644 --- a/src/tests/thread-mainloop-test.c +++ b/src/tests/thread-mainloop-test.c @@ -23,18 +23,19 @@ #include #endif -#include #include #include #include #include #include - -#include #include +#include +#include + static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) { + pa_assert_se(pa_threaded_mainloop_in_thread(userdata)); fprintf(stderr, "TIME EVENT START\n"); pa_threaded_mainloop_signal(userdata, 1); fprintf(stderr, "TIME EVENT END\n"); @@ -45,15 +46,15 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) { pa_threaded_mainloop *m; struct timeval tv; - m = pa_threaded_mainloop_new(); - assert(m); - a = pa_threaded_mainloop_get_api(m); - assert(a); + pa_assert_se(m = pa_threaded_mainloop_new()); + pa_assert_se(a = pa_threaded_mainloop_get_api(m)); pa_threaded_mainloop_start(m); pa_threaded_mainloop_lock(m); + pa_assert_se(!pa_threaded_mainloop_in_thread(m)); + pa_gettimeofday(&tv); tv.tv_sec += 5; a->time_new(a, &tv, tcb, m); diff --git a/src/tests/thread-test.c b/src/tests/thread-test.c index 2153c9854..72dde6cbb 100644 --- a/src/tests/thread-test.c +++ b/src/tests/thread-test.c @@ -42,7 +42,7 @@ static void once_func(void) { pa_log("once!"); } -static pa_once_t once = PA_ONCE_INIT; +static pa_once once = PA_ONCE_INIT; static void thread_func(void *data) { pa_tls_set(tls, data); @@ -72,7 +72,7 @@ static void thread_func(void *data) { pa_mutex_unlock(mutex); - pa_once(&once, once_func); + pa_run_once(&once, once_func); pa_cond_signal(cond2, 0); @@ -98,7 +98,7 @@ int main(int argc, char *argv[]) { assert(pa_thread_is_running(pa_thread_self())); - mutex = pa_mutex_new(0); + mutex = pa_mutex_new(FALSE, FALSE); cond1 = pa_cond_new(); cond2 = pa_cond_new(); tls = pa_tls_new(pa_xfree); diff --git a/src/utils/pactl.c b/src/utils/pactl.c index b95cbfeee..c963987ff 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -48,8 +48,10 @@ static pa_context *context = NULL; static pa_mainloop_api *mainloop_api = NULL; -static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL; +static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL, *module_name = NULL, *module_args = NULL; static uint32_t sink_input_idx = PA_INVALID_INDEX, source_output_idx = PA_INVALID_INDEX; +static uint32_t module_index; +static int suspend; static SNDFILE *sndfile = NULL; static pa_stream *sample_stream = NULL; @@ -69,7 +71,11 @@ static enum { REMOVE_SAMPLE, LIST, MOVE_SINK_INPUT, - MOVE_SOURCE_OUTPUT + MOVE_SOURCE_OUTPUT, + LOAD_MODULE, + UNLOAD_MODULE, + SUSPEND_SINK, + SUSPEND_SOURCE, } action = NONE; static void quit(int ret) { @@ -354,7 +360,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info i->sink, pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), - pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume), (double) i->buffer_usec, (double) i->sink_usec, i->resample_method ? i->resample_method : "n/a"); @@ -492,6 +498,18 @@ static void simple_callback(pa_context *c, int success, void *userdata) { complete_action(); } +static void index_callback(pa_context *c, uint32_t idx, void *userdata) { + if (idx == PA_INVALID_INDEX) { + fprintf(stderr, "Failure: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + printf("%u\n", idx); + + complete_action(); +} + static void stream_state_callback(pa_stream *s, void *userdata) { assert(s); @@ -594,6 +612,28 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_operation_unref(pa_context_move_source_output_by_name(c, source_output_idx, source_name, simple_callback, NULL)); break; + case LOAD_MODULE: + pa_operation_unref(pa_context_load_module(c, module_name, module_args, index_callback, NULL)); + break; + + case UNLOAD_MODULE: + pa_operation_unref(pa_context_unload_module(c, module_index, simple_callback, NULL)); + break; + + case SUSPEND_SINK: + if (sink_name) + pa_operation_unref(pa_context_suspend_sink_by_name(c, sink_name, suspend, simple_callback, NULL)); + else + pa_operation_unref(pa_context_suspend_sink_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL)); + break; + + case SUSPEND_SOURCE: + if (source_name) + pa_operation_unref(pa_context_suspend_source_by_name(c, source_name, suspend, simple_callback, NULL)); + else + pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL)); + break; + default: assert(0); } @@ -624,12 +664,16 @@ static void help(const char *argv0) { "%s [options] play-sample NAME [SINK]\n" "%s [options] move-sink-input ID SINK\n" "%s [options] move-source-output ID SOURCE\n" - "%s [options] remove-sample NAME\n\n" + "%s [options] remove-sample NAME\n" + "%s [options] load-module NAME [ARGS ...]\n" + "%s [options] unload-module ID\n" + "%s [options] suspend-sink [SINK] 1|0\n" + "%s [options] suspend-source [SOURCE] 1|0\n\n" " -h, --help Show this help\n" " --version Show version\n\n" " -s, --server=SERVER The name of the server to connect to\n" " -n, --client-name=NAME How to call this client on the server\n", - argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0); + argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0); } enum { ARG_VERSION = 256 }; @@ -728,7 +772,7 @@ int main(int argc, char *argv[]) { sample_length = sfinfo.frames*pa_frame_size(&sample_spec); } else if (!strcmp(argv[optind], "play-sample")) { action = PLAY_SAMPLE; - if (optind+1 >= argc) { + if (argc != optind+2 && argc != optind+3) { fprintf(stderr, "You have to specify a sample name to play\n"); goto quit; } @@ -740,7 +784,7 @@ int main(int argc, char *argv[]) { } else if (!strcmp(argv[optind], "remove-sample")) { action = REMOVE_SAMPLE; - if (optind+1 >= argc) { + if (argc != optind+2) { fprintf(stderr, "You have to specify a sample name to remove\n"); goto quit; } @@ -748,7 +792,7 @@ int main(int argc, char *argv[]) { sample_name = pa_xstrdup(argv[optind+1]); } else if (!strcmp(argv[optind], "move-sink-input")) { action = MOVE_SINK_INPUT; - if (optind+2 >= argc) { + if (argc != optind+3) { fprintf(stderr, "You have to specify a sink input index and a sink\n"); goto quit; } @@ -757,13 +801,72 @@ int main(int argc, char *argv[]) { sink_name = pa_xstrdup(argv[optind+2]); } else if (!strcmp(argv[optind], "move-source-output")) { action = MOVE_SOURCE_OUTPUT; - if (optind+2 >= argc) { + if (argc != optind+3) { fprintf(stderr, "You have to specify a source output index and a source\n"); goto quit; } source_output_idx = atoi(argv[optind+1]); source_name = pa_xstrdup(argv[optind+2]); + } else if (!strcmp(argv[optind], "load-module")) { + int i; + size_t n = 0; + char *p; + + action = LOAD_MODULE; + + if (argc <= optind+1) { + fprintf(stderr, "You have to specify a module name and arguments.\n"); + goto quit; + } + + module_name = argv[optind+1]; + + for (i = optind+2; i < argc; i++) + n += strlen(argv[i])+1; + + if (n > 0) { + p = module_args = pa_xnew0(char, n); + + for (i = optind+2; i < argc; i++) + p += sprintf(p, "%s%s", p == module_args ? "" : " ", argv[i]); + } + + } else if (!strcmp(argv[optind], "unload-module")) { + action = UNLOAD_MODULE; + + if (argc != optind+2) { + fprintf(stderr, "You have to specify a module index\n"); + goto quit; + } + + module_index = atoi(argv[optind+1]); + + } else if (!strcmp(argv[optind], "suspend-sink")) { + action = SUSPEND_SINK; + + if (argc > optind+3 || optind+1 >= argc) { + fprintf(stderr, "You may not specify more than one sink. You have to specify at least one boolean value.\n"); + goto quit; + } + + suspend = !!atoi(argv[argc-1]); + + if (argc > optind+2) + sink_name = pa_xstrdup(argv[optind+1]); + + } else if (!strcmp(argv[optind], "suspend-source")) { + action = SUSPEND_SOURCE; + + if (argc > optind+3 || optind+1 >= argc) { + fprintf(stderr, "You may not specify more than one source. You have to specify at least one boolean value.\n"); + goto quit; + } + + suspend = !!atoi(argv[argc-1]); + + if (argc > optind+2) + source_name = pa_xstrdup(argv[optind+1]); } } @@ -819,6 +922,8 @@ quit: pa_xfree(sample_name); pa_xfree(sink_name); pa_xfree(source_name); + pa_xfree(module_args); + pa_xfree(client_name); return ret; } diff --git a/src/utils/padsp.c b/src/utils/padsp.c index 95fc9ed3e..b48af93cd 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -61,6 +61,10 @@ # define SIOCINQ FIONREAD #endif +/* make sure gcc doesn't redefine open and friends as macros */ +#undef open +#undef open64 + typedef enum { FD_INFO_MIXER, FD_INFO_STREAM, @@ -259,9 +263,9 @@ if (!(i)->context || pa_context_get_state((i)->context) != PA_CONTEXT_READY || \ static void debug(int level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3); -#define DEBUG_LEVEL_ALWAYS 0 -#define DEBUG_LEVEL_NORMAL 1 -#define DEBUG_LEVEL_VERBOSE 2 +#define DEBUG_LEVEL_ALWAYS 0 +#define DEBUG_LEVEL_NORMAL 1 +#define DEBUG_LEVEL_VERBOSE 2 static void debug(int level, const char *format, ...) { va_list ap; @@ -421,7 +425,7 @@ static void fd_info_unref(fd_info *i) { pthread_mutex_lock(&i->mutex); assert(i->ref >= 1); r = --i->ref; - debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref); + debug(DEBUG_LEVEL_VERBOSE, __FILE__": ref--, now %i\n", i->ref); pthread_mutex_unlock(&i->mutex); if (r <= 0) @@ -1395,7 +1399,7 @@ static int sndstat_open(int flags, int *_errno) { if (flags != O_RDONLY #ifdef O_LARGEFILE - && flags != (O_RDONLY|O_LARGEFILE) + && flags != (O_RDONLY|O_LARGEFILE) #endif ) { *_errno = EACCES; @@ -1436,34 +1440,23 @@ fail: return -1; } -int open(const char *filename, int flags, ...) { - va_list args; - mode_t mode = 0; +static int real_open(const char *filename, int flags, mode_t mode) { int r, _errno = 0; debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename); - va_start(args, flags); - if (flags & O_CREAT) { - if (sizeof(mode_t) < sizeof(int)) - mode = va_arg(args, int); - else - mode = va_arg(args, mode_t); - } - va_end(args); - if (!function_enter()) { LOAD_OPEN_FUNC(); return _open(filename, flags, mode); } - if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) { + if (dsp_cloak_enable() && (strcmp(filename, "/dev/dsp") == 0 || strcmp(filename, "/dev/adsp") == 0)) r = dsp_open(flags, &_errno); - } else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) { + else if (mixer_cloak_enable() && strcmp(filename, "/dev/mixer") == 0) r = mixer_open(flags, &_errno); - } else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) { + else if (sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0) r = sndstat_open(flags, &_errno); - } else { + else { function_exit(); LOAD_OPEN_FUNC(); return _open(filename, flags, mode); @@ -1477,6 +1470,22 @@ int open(const char *filename, int flags, ...) { return r; } +int open(const char *filename, int flags, ...) { + va_list args; + mode_t mode = 0; + + if (flags & O_CREAT) { + va_start(args, flags); + if (sizeof(mode_t) < sizeof(int)) + mode = va_arg(args, int); + else + mode = va_arg(args, mode_t); + va_end(args); + } + + return real_open(filename, flags, mode); +} + static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; @@ -2023,9 +2032,9 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) *(int*) argp = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER #ifdef DSP_CAP_MULTI - | DSP_CAP_MULTI + | DSP_CAP_MULTI #endif - ; + ; break; case SNDCTL_DSP_GETODELAY: { @@ -2497,10 +2506,14 @@ int open64(const char *filename, int flags, ...) { debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename); - va_start(args, flags); - if (flags & O_CREAT) - mode = va_arg(args, mode_t); - va_end(args); + if (flags & O_CREAT) { + va_start(args, flags); + if (sizeof(mode_t) < sizeof(int)) + mode = va_arg(args, int); + else + mode = va_arg(args, mode_t); + va_end(args); + } if (strcmp(filename, "/dev/dsp") != 0 && strcmp(filename, "/dev/adsp") != 0 && @@ -2510,7 +2523,7 @@ int open64(const char *filename, int flags, ...) { return _open64(filename, flags, mode); } - return open(filename, flags, mode); + return real_open(filename, flags, mode); } #endif @@ -2602,7 +2615,7 @@ FILE* fopen(const char *filename, const char *mode) { if ((((mode[1] == 'b') || (mode[1] == 't')) && (mode[2] == '+')) || (mode[1] == '+')) m = O_RDWR; - if ((fd = open(filename, m)) < 0) + if ((fd = real_open(filename, m, 0)) < 0) return NULL; if (!(f = fdopen(fd, mode))) { diff --git a/src/utils/paplay.c b/src/utils/paplay.c index 2c779a7a3..e7076d2d3 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -123,7 +123,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { else pa_xfree(data); - if (bytes < length) { + if (bytes < (sf_count_t) length) { sf_close(sndfile); sndfile = NULL; pa_operation_unref(pa_stream_drain(s, stream_drain_complete, NULL)); diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c new file mode 100644 index 000000000..ae59086b1 --- /dev/null +++ b/src/utils/pasuspender.c @@ -0,0 +1,316 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __linux__ +#include +#endif + +#include +#include + +#if PA_API_VERSION < 10 +#error Invalid PulseAudio API version +#endif + +#define BUFSIZE 1024 + +static pa_context *context = NULL; +static pa_mainloop_api *mainloop_api = NULL; +static char **child_argv = NULL; +static int child_argc = 0; +static pid_t child_pid = (pid_t) -1; +static int child_ret = 0; +static int dead = 1; + +static void quit(int ret) { + pa_assert(mainloop_api); + mainloop_api->quit(mainloop_api, ret); +} + + +static void context_drain_complete(pa_context *c, void *userdata) { + pa_context_disconnect(c); +} + +static void drain(void) { + pa_operation *o; + + if (!(o = pa_context_drain(context, context_drain_complete, NULL))) + pa_context_disconnect(context); + else + pa_operation_unref(o); +} + +static void start_child(void) { + + if ((child_pid = fork()) < 0) { + + fprintf(stderr, "fork(): %s\n", strerror(errno)); + quit(1); + + } else if (child_pid == 0) { + /* Child */ + +#ifdef __linux__ + prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); +#endif + + if (execvp(child_argv[0], child_argv) < 0) + fprintf(stderr, "execvp(): %s\n", strerror(errno)); + + _exit(1); + + } else { + + /* parent */ + dead = 0; + } +} + +static void suspend_complete(pa_context *c, int success, void *userdata) { + static int n = 0; + + n++; + + if (!success) { + fprintf(stderr, "Failure to suspend: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (n >= 2) + start_child(); +} + +static void resume_complete(pa_context *c, int success, void *userdata) { + static int n = 0; + + n++; + + if (!success) { + fprintf(stderr, "Failure to resume: %s\n", pa_strerror(pa_context_errno(c))); + quit(1); + return; + } + + if (n >= 2) + drain(); /* drain and quit */ +} + +static void context_state_callback(pa_context *c, void *userdata) { + pa_assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: + if (pa_context_is_local(c)) { + pa_operation_unref(pa_context_suspend_sink_by_index(c, PA_INVALID_INDEX, 1, suspend_complete, NULL)); + pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, 1, suspend_complete, NULL)); + } else + start_child(); + + break; + + case PA_CONTEXT_TERMINATED: + quit(0); + break; + + case PA_CONTEXT_FAILED: + default: + fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c))); + + pa_context_unref(context); + context = NULL; + + if (child_pid == (pid_t) -1) + /* not started yet, then we do it now */ + start_child(); + else if (dead) + /* already started, and dead, so let's quit */ + quit(1); + + break; + } +} + +static void sigint_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) { + fprintf(stderr, "Got SIGINT, exiting.\n"); + quit(0); +} + +static void sigchld_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) { + int status = 0; + pid_t p; + + p = waitpid(-1, &status, WNOHANG); + + if (p != child_pid) + return; + + dead = 1; + + if (WIFEXITED(status)) + child_ret = WEXITSTATUS(status); + else if (WIFSIGNALED(status)) { + fprintf(stderr, "WARNING: Child process terminated by signal %u\n", WTERMSIG(status)); + child_ret = 1; + } + + if (context) { + if (pa_context_is_local(context)) { + /* A context is around, so let's resume */ + pa_operation_unref(pa_context_suspend_sink_by_index(context, PA_INVALID_INDEX, 0, resume_complete, NULL)); + pa_operation_unref(pa_context_suspend_source_by_index(context, PA_INVALID_INDEX, 0, resume_complete, NULL)); + } else + drain(); + } else + /* Hmm, no context here, so let's terminate right away */ + quit(0); +} + +static void help(const char *argv0) { + + printf("%s [options] ... \n\n" + " -h, --help Show this help\n" + " --version Show version\n" + " -s, --server=SERVER The name of the server to connect to\n\n", + argv0); +} + +enum { + ARG_VERSION = 256 +}; + +int main(int argc, char *argv[]) { + pa_mainloop* m = NULL; + int c, ret = 1; + char *server = NULL, *bn; + + static const struct option long_options[] = { + {"server", 1, NULL, 's'}, + {"version", 0, NULL, ARG_VERSION}, + {"help", 0, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + if (!(bn = strrchr(argv[0], '/'))) + bn = argv[0]; + else + bn++; + + while ((c = getopt_long(argc, argv, "s:h", long_options, NULL)) != -1) { + switch (c) { + case 'h' : + help(bn); + ret = 0; + goto quit; + + case ARG_VERSION: + printf("pasuspender "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version()); + ret = 0; + goto quit; + + case 's': + pa_xfree(server); + server = pa_xstrdup(optarg); + break; + + default: + goto quit; + } + } + + child_argv = argv + optind; + child_argc = argc - optind; + + if (child_argc <= 0) { + help(bn); + ret = 0; + goto quit; + } + + if (!(m = pa_mainloop_new())) { + fprintf(stderr, "pa_mainloop_new() failed.\n"); + goto quit; + } + + pa_assert_se(mainloop_api = pa_mainloop_get_api(m)); + pa_assert_se(pa_signal_init(mainloop_api) == 0); + pa_signal_new(SIGINT, sigint_callback, NULL); + pa_signal_new(SIGCHLD, sigchld_callback, NULL); +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif + + if (!(context = pa_context_new(mainloop_api, bn))) { + fprintf(stderr, "pa_context_new() failed.\n"); + goto quit; + } + + pa_context_set_state_callback(context, context_state_callback, NULL); + pa_context_connect(context, server, PA_CONTEXT_NOAUTOSPAWN, NULL); + + if (pa_mainloop_run(m, &ret) < 0) { + fprintf(stderr, "pa_mainloop_run() failed.\n"); + goto quit; + } + +quit: + if (context) + pa_context_unref(context); + + if (m) { + pa_signal_done(); + pa_mainloop_free(m); + } + + pa_xfree(server); + + if (!dead) + kill(child_pid, SIGTERM); + + return ret == 0 ? child_ret : ret; +} diff --git a/todo b/todo index 7b4ce7864..f579bebe3 100644 --- a/todo +++ b/todo @@ -4,7 +4,6 @@ Build System: - Remove symdef files and use macros (like most other projects) - Use own name mangling scheme instead of ltdl's, which will eliminate the need for .la files or extra trickery. -- build pulsecore only statically by default, it's not a public API yet Porting: - rtp module ported to Win32 (sendmsg/recvmsg emulation) @@ -13,16 +12,12 @@ I18N: - iconv stuff sent from utils to server (UTF-8) - iconv sample loading in server - Document utf8.h, timeval.h and util.h -- gettextify polypaudio +- gettextify pulseaudio Cleanups: - drop dependency of libpolyp on libX11, instead use an external mini binary -- merge module-oss-mmap into module-oss - module-tunnel: improve latency calculation - use software volume when hardware doesn't support all channels (alsa done) -- silence generation should be moved into the core to avoid races and code - duplication in the backends -- don't read/write audio data from/to ALSA devices if noone is listening - using POSIX monotonous clocks wherever possible instead of gettimeofday() Test: @@ -35,7 +30,6 @@ Auth/Crypto: - sasl auth Features: -- alsa mmap driver - alsa driver with hw mixing - "window manager for sound" - chroot() @@ -52,7 +46,8 @@ Features: - Support for device selection in waveout driver - add an API to libpulse for allocating memory from the pa_context memory pool - allow buffer metric changes during runtime -- "include" command in configuration files. should have glob support. +- better ".include" command in configuration files. should have glob support. +- recursive .if Long term: - pass meta info for hearing impaired From c6a7f06e239b58e02c912622d06b72cba3fbc91d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 28 Oct 2007 19:24:25 +0000 Subject: [PATCH 1374/1514] add missing dependency on socket-util git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1972 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index e17e5ece4..a827d9f49 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1196,7 +1196,7 @@ module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpulsecore.la module_esound_sink_la_SOURCES = modules/module-esound-sink.c module_esound_sink_la_LDFLAGS = -module -avoid-version -module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-client.la libauthkey.la +module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-client.la libauthkey.la libsocket-util.la # Pipes From 1c0690776d45c50b90df037669b4dbfe0467ca8a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 08:34:30 +0000 Subject: [PATCH 1375/1514] make speex-float-3 the default resampler git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1973 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core.c | 2 +- src/pulsecore/resampler.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index e9008833d..e67f15b56 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -132,7 +132,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { c->module_idle_time = 20; c->scache_idle_time = 20; - c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE; + c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3; c->is_system_instance = 0; c->disallow_module_loading = 0; diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index 5bbc6bf44..b44471984 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -195,7 +195,7 @@ pa_resampler* pa_resampler_new( } if (resample_method == PA_RESAMPLER_AUTO) - resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 0; + resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3; r = pa_xnew(pa_resampler, 1); r->mempool = pool; @@ -439,10 +439,10 @@ pa_resample_method_t pa_parse_resample_method(const char *string) { return m; if (!strcmp(string, "speex-fixed")) - return PA_RESAMPLER_SPEEX_FIXED_BASE + 0; + return PA_RESAMPLER_SPEEX_FIXED_BASE + 3; if (!strcmp(string, "speex-float")) - return PA_RESAMPLER_SPEEX_FLOAT_BASE + 0; + return PA_RESAMPLER_SPEEX_FLOAT_BASE + 3; return PA_RESAMPLER_INVALID; } From ca98c544ab7a26bfc840d1470f467a7dea06238c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 15:31:24 +0000 Subject: [PATCH 1376/1514] add new pa_readlink() API git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1974 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-util.c | 24 ++++++++++++++++++++++++ src/pulsecore/core-util.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index a644b6642..4962112bb 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -1507,3 +1507,27 @@ void pa_close_pipe(int fds[2]) { fds[0] = fds[1] = -1; } + +char *pa_readlink(const char *p) { + size_t l = 100; + + for (;;) { + char *c; + ssize_t n; + + c = pa_xnew(char, l); + + if ((n = readlink(p, c, l-1)) < 0) { + pa_xfree(c); + return NULL; + } + + if (n < l-1) { + c[l-1] = 0; + return c; + } + + pa_xfree(c); + l *= 2; + } +} diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 0fe865ec4..d26cf2411 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -122,4 +122,6 @@ static inline unsigned pa_make_power_of_two(unsigned n) { void pa_close_pipe(int fds[2]); +char *pa_readlink(const char *p); + #endif From 27d6b7b4732f3678ecb6f1e5e53d440f1e8b2547 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 15:32:22 +0000 Subject: [PATCH 1377/1514] make use of new pa_readlink() where applicable git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1975 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/oss-util.c | 32 +++++++++++++++++++++----------- src/pulse/util.c | 11 ++++++----- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 25e45a350..015db4ca2 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -293,29 +293,39 @@ int pa_oss_set_volume(int fd, long mixer, const pa_sample_spec *ss, const pa_cvo } static int get_device_number(const char *dev) { - char buf[PATH_MAX]; const char *p, *e; + char *rp = NULL; + int r; - if (readlink(dev, buf, sizeof(buf)) < 0) { - if (errno != EINVAL && errno != ENOLINK) - return -1; + if (!(p = rp = pa_readlink(dev))) { + if (errno != EINVAL && errno != ENOLINK) { + r = -1; + goto finish; + } p = dev; - } else - p = buf; + } if ((e = strrchr(p, '/'))) p = e+1; - if (p == 0) - return 0; + if (p == 0) { + r = 0; + goto finish; + } p = strchr(p, 0) -1; - if (*p >= '0' && *p <= '9') - return *p - '0'; + if (*p >= '0' && *p <= '9') { + r = *p - '0'; + goto finish; + } - return -1; + r = -1; + +finish: + pa_xfree(rp); + return r; } int pa_oss_get_hw_description(const char *dev, char *name, size_t l) { diff --git a/src/pulse/util.c b/src/pulse/util.c index 5dbb670bc..d3ac9f66e 100644 --- a/src/pulse/util.c +++ b/src/pulse/util.c @@ -55,6 +55,7 @@ #include #endif +#include #include #include #include @@ -172,13 +173,13 @@ char *pa_get_binary_name(char *s, size_t l) { #ifdef __linux__ { - int i; - char path[PATH_MAX]; + char *rp; /* This works on Linux only */ - if ((i = readlink("/proc/self/exe", path, sizeof(path)-1)) >= 0) { - path[i] = 0; - return pa_strlcpy(s, pa_path_get_filename(path), l); + if ((rp = pa_readlink("/proc/self/exe"))) { + pa_strlcpy(s, pa_path_get_filename(rp), l); + pa_xfree(rp); + return s; } } From a46804a8e2ba8aa0e869bcf72015e3b551a7b40d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 15:33:07 +0000 Subject: [PATCH 1378/1514] use real path of binary instead of /proc/self/exe to execute ourselves git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1976 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 6c9f66277..cd3cfcc89 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -336,11 +336,14 @@ int main(int argc, char *argv[]) { */ if (!getenv("LD_BIND_NOW")) { - putenv(pa_xstrdup("LD_BIND_NOW=1")); + char *rp; /* We have to execute ourselves, because the libc caches the * value of $LD_BIND_NOW on initialization. */ - pa_assert_se(execv("/proc/self/exe", argv) == 0); + + putenv(pa_xstrdup("LD_BIND_NOW=1")); + pa_assert_se(rp = pa_readlink("/proc/self/exe")); + pa_assert_se(execv(rp, argv) == 0); } #endif From 6e1f7bd144d2f5ce8cb5f30772b2ad31652ab213 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 16:38:57 +0000 Subject: [PATCH 1379/1514] properly deal with time pausing git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1977 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/time-smoother.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c index 6bda3df06..4cebded4d 100644 --- a/src/pulsecore/time-smoother.c +++ b/src/pulsecore/time-smoother.c @@ -310,8 +310,9 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) { /* Fix up x value */ if (s->paused) x = s->pause_time; - else - x -= s->time_offset; + + pa_assert(x >= s->time_offset); + x -= s->time_offset; pa_assert(x >= s->ex); @@ -342,8 +343,9 @@ pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x) { /* Fix up x value */ if (s->paused) x = s->pause_time; - else - x -= s->time_offset; + + pa_assert(x >= s->time_offset); + x -= s->time_offset; pa_assert(x >= s->ex); @@ -373,6 +375,8 @@ void pa_smoother_resume(pa_smoother *s, pa_usec_t x) { if (!s->paused) return; + pa_assert(x >= s->pause_time); + s->paused = FALSE; s->time_offset += x - s->pause_time; } From 9ccbd86f8259c6603e5e3ff5a99c4b5d5a51a6c6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 16:39:23 +0000 Subject: [PATCH 1380/1514] downgrade a few log messages git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1978 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-esound-sink.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 8b46637e1..b60e15d7f 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -362,7 +362,7 @@ static int do_write(struct userdata *u) { pa_make_tcp_socket_low_delay(u->fd); - pa_log_info("Connection authenticated, handing fd to IO thread..."); + pa_log_debug("Connection authenticated, handing fd to IO thread..."); pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL); u->state = STATE_RUNNING; @@ -496,7 +496,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, vo u->io = io; pa_iochannel_set_callback(u->io, io_callback, u); - pa_log_info("Connection established, authenticating ..."); + pa_log_debug("Connection established, authenticating ..."); } int pa__init(pa_module*m) { @@ -553,7 +553,7 @@ int pa__init(pa_module*m) { u->latency = 0; if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) { - pa_log("failed to create sink."); + pa_log("Failed to create sink."); goto fail; } From ac8363144777ec60cba979666e7195205fe96c97 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 16:54:16 +0000 Subject: [PATCH 1381/1514] bring back module-tunnel, yay! git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1979 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 20 +- src/modules/module-tunnel.c | 1079 +++++++++++++++++++++-------------- 2 files changed, 650 insertions(+), 449 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index a827d9f49..911bd7b62 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -955,9 +955,9 @@ modlibexec_LTLIBRARIES += \ module-combine.la \ module-remap-sink.la \ module-ladspa-sink.la \ - module-esound-sink.la -# module-tunnel-sink.la -# module-tunnel-source.la + module-esound-sink.la \ + module-tunnel-sink.la \ + module-tunnel-source.la # See comment at librtp.la above if !OS_IS_WIN32 @@ -1237,14 +1237,14 @@ module_match_la_SOURCES = modules/module-match.c module_match_la_LDFLAGS = -module -avoid-version module_match_la_LIBADD = $(AM_LIBADD) libpulsecore.la -#module_tunnel_sink_la_SOURCES = modules/module-tunnel.c -#module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) -#module_tunnel_sink_la_LDFLAGS = -module -avoid-version -#module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la +module_tunnel_sink_la_SOURCES = modules/module-tunnel.c +module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) +module_tunnel_sink_la_LDFLAGS = -module -avoid-version +module_tunnel_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la -#module_tunnel_source_la_SOURCES = modules/module-tunnel.c -#module_tunnel_source_la_LDFLAGS = -module -avoid-version -#module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la +module_tunnel_source_la_SOURCES = modules/module-tunnel.c +module_tunnel_source_la_LDFLAGS = -module -avoid-version +module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la # X11 diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index b96d46b31..1682007ac 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include #include @@ -52,6 +51,11 @@ #include #include #include +#include +#include +#include +#include +#include #ifdef TUNNEL_SINK #include "module-tunnel-sink-symdef.h" @@ -82,11 +86,10 @@ PA_MODULE_USAGE( PA_MODULE_AUTHOR("Lennart Poettering") PA_MODULE_VERSION(PACKAGE_VERSION) -#define DEFAULT_TLENGTH (44100*2*2/10) //(10240*8) -#define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2) -#define DEFAULT_MINREQ 512 -#define DEFAULT_PREBUF (DEFAULT_TLENGTH-DEFAULT_MINREQ) -#define DEFAULT_FRAGSIZE 1024 +#define DEFAULT_TLENGTH_MSEC 100 +#define DEFAULT_MINREQ_MSEC 10 +#define DEFAULT_MAXLENGTH_MSEC ((DEFAULT_TLENGTH_MSEC*3)/2) +#define DEFAULT_FRAGSIZE_MSEC 10 #define DEFAULT_TIMEOUT 5 @@ -109,23 +112,42 @@ static const char* const valid_modargs[] = { NULL, }; -static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +enum { + SOURCE_MESSAGE_POST = PA_SOURCE_MESSAGE_MAX +}; + +enum { + SINK_MESSAGE_REQUEST = PA_SINK_MESSAGE_MAX, + SINK_MESSAGE_POST +}; #ifdef TUNNEL_SINK static void command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); #endif +static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_overflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { #ifdef TUNNEL_SINK [PA_COMMAND_REQUEST] = command_request, + [PA_COMMAND_SUBSCRIBE_EVENT] = command_subscribe_event, #endif + [PA_COMMAND_OVERFLOW] = command_overflow, + [PA_COMMAND_UNDERFLOW] = command_underflow, [PA_COMMAND_PLAYBACK_STREAM_KILLED] = command_stream_killed, [PA_COMMAND_RECORD_STREAM_KILLED] = command_stream_killed, - [PA_COMMAND_SUBSCRIBE_EVENT] = command_subscribe_event, }; struct userdata { + pa_core *core; + pa_module *module; + + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + pa_thread *thread; + pa_socket_client *client; pa_pstream *pstream; pa_pdispatch *pdispatch; @@ -140,9 +162,6 @@ struct userdata { pa_source *source; #endif - pa_module *module; - pa_core *core; - uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; uint32_t version; @@ -150,174 +169,284 @@ struct userdata { uint32_t device_index; uint32_t channel; - pa_usec_t host_latency; + int64_t counter, counter_delta; pa_time_event *time_event; - int auth_cookie_in_property; -}; + pa_bool_t auth_cookie_in_property; -static void close_stuff(struct userdata *u) { - assert(u); - - if (u->pstream) { - pa_pstream_close(u->pstream); - pa_pstream_unref(u->pstream); - u->pstream = NULL; - } - - if (u->pdispatch) { - pa_pdispatch_unref(u->pdispatch); - u->pdispatch = NULL; - } - - if (u->client) { - pa_socket_client_unref(u->client); - u->client = NULL; - } + pa_smoother *smoother; + uint32_t maxlength; #ifdef TUNNEL_SINK - if (u->sink) { - pa_sink_disconnect(u->sink); - pa_sink_unref(u->sink); - u->sink = NULL; - } + uint32_t tlength; + uint32_t minreq; + uint32_t prebuf; #else - if (u->source) { - pa_source_disconnect(u->source); - pa_source_unref(u->source); - u->source = NULL; - } + uint32_t fragsize; #endif - - if (u->time_event) { - u->core->mainloop->time_free(u->time_event); - u->time_event = NULL; - } -} - -static void die(struct userdata *u) { - assert(u); - close_stuff(u); - pa_module_unload_request(u->module); -} +}; static void command_stream_killed(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; - assert(pd && t && u && u->pdispatch == pd); - pa_log("stream killed"); - die(u); + pa_assert(pd); + pa_assert(t); + pa_assert(u); + pa_assert(u->pdispatch == pd); + + pa_log_warn("Stream killed"); + pa_module_unload_request(u->module); } -static void request_info(struct userdata *u); - -static void command_subscribe_event(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +static void command_overflow(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; - pa_subscription_event_type_t e; - uint32_t idx; - assert(pd && t && u); - assert(command == PA_COMMAND_SUBSCRIBE_EVENT); + pa_assert(pd); + pa_assert(t); + pa_assert(u); + pa_assert(u->pdispatch == pd); - if (pa_tagstruct_getu32(t, &e) < 0 || - pa_tagstruct_getu32(t, &idx) < 0 || - !pa_tagstruct_eof(t)) { - pa_log("invalid protocol reply"); - die(u); - return; - } - -#ifdef TUNNEL_SINK - if (e != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE)) - return; -#else - if (e != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE)) - return; -#endif - - request_info(u); + pa_log_warn("Server signalled buffer overrun."); } -#ifdef TUNNEL_SINK -static void send_prebuf_request(struct userdata *u) { +static void command_underflow(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + + pa_assert(pd); + pa_assert(t); + pa_assert(u); + pa_assert(u->pdispatch == pd); + + pa_log_warn("Server signalled buffer underrun."); +} + +static void stream_cork(struct userdata *u, pa_bool_t cork) { pa_tagstruct *t; + pa_assert(u); + + if (cork) + pa_smoother_pause(u->smoother, pa_rtclock_usec()); + else + pa_smoother_resume(u->smoother, pa_rtclock_usec()); t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_PREBUF_PLAYBACK_STREAM); +#ifdef TUNNEL_SINK + pa_tagstruct_putu32(t, PA_COMMAND_CORK_PLAYBACK_STREAM); +#else + pa_tagstruct_putu32(t, PA_COMMAND_CORK_RECORD_STREAM); +#endif pa_tagstruct_putu32(t, u->ctag++); pa_tagstruct_putu32(t, u->channel); + pa_tagstruct_put_boolean(t, !!cork); pa_pstream_send_tagstruct(u->pstream, t); } -static void send_bytes(struct userdata *u) { - assert(u); +#ifdef TUNNEL_SINK - if (!u->pstream) - return; +static void send_data(struct userdata *u) { + pa_assert(u); while (u->requested_bytes > 0) { - pa_memchunk chunk; - if (pa_sink_render(u->sink, u->requested_bytes, &chunk) < 0) { - - if (u->requested_bytes >= DEFAULT_TLENGTH-DEFAULT_PREBUF) - send_prebuf_request(u); - - return; - } - - pa_pstream_send_memblock(u->pstream, u->channel, 0, PA_SEEK_RELATIVE, &chunk); - pa_memblock_unref(chunk.memblock); - -/* pa_log("sent %lu", (unsigned long) chunk.length); */ - - if (chunk.length > u->requested_bytes) - u->requested_bytes = 0; - else - u->requested_bytes -= chunk.length; + pa_memchunk memchunk; + pa_sink_render(u->sink, u->requested_bytes, &memchunk); + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_POST, NULL, 0, &memchunk, NULL); + pa_memblock_unref(memchunk.memblock); + u->requested_bytes -= memchunk.length; } } +/* This function is called from IO context -- except when it is not. */ +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + + switch (code) { + + case PA_SINK_MESSAGE_SET_STATE: { + int r; + + /* First, change the state, because otherwide pa_sink_render() would fail */ + if ((r = pa_sink_process_msg(o, code, data, offset, chunk)) >= 0) + if (PA_SINK_OPENED((pa_sink_state_t) PA_PTR_TO_UINT(data))) + send_data(u); + + return r; + } + + case SINK_MESSAGE_REQUEST: + + pa_assert(offset > 0); + u->requested_bytes += (size_t) offset; + + if (PA_SINK_OPENED(u->sink->thread_info.state)) + send_data(u); + + return 0; + + case SINK_MESSAGE_POST: + + /* OK, This might be a bit confusing. This message is + * delivered to us from the main context -- NOT from the + * IO thread context where the rest of the messages are + * dispatched. Yeah, ugly, but I am a lazy bastard. */ + + pa_pstream_send_memblock(u->pstream, u->channel, 0, PA_SEEK_RELATIVE, chunk); + u->counter += chunk->length; + u->counter_delta += chunk->length; + return 0; + } + + return pa_sink_process_msg(o, code, data, offset, chunk); +} + +static int sink_set_state(pa_sink *s, pa_sink_state_t state) { + struct userdata *u; + pa_sink_assert_ref(s); + u = s->userdata; + + switch ((pa_sink_state_t) state) { + + case PA_SINK_SUSPENDED: + pa_assert(PA_SINK_OPENED(s->state)); + stream_cork(u, TRUE); + break; + + case PA_SINK_IDLE: + case PA_SINK_RUNNING: + if (s->state == PA_SINK_SUSPENDED) + stream_cork(u, FALSE); + break; + + case PA_SINK_UNLINKED: + case PA_SINK_INIT: + ; + } + + return 0; +} + +#else + +static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SOURCE(o)->userdata; + + switch (code) { + case SOURCE_MESSAGE_POST: + + if (PA_SOURCE_OPENED(u->source->thread_info.state)) + pa_source_post(u->source, chunk); + return 0; + } + + return pa_source_process_msg(o, code, data, offset, chunk); +} + +static int source_set_state(pa_source *s, pa_source_state_t state) { + struct userdata *u; + pa_source_assert_ref(s); + u = s->userdata; + + switch ((pa_source_state_t) state) { + + case PA_SOURCE_SUSPENDED: + pa_assert(PA_SOURCE_OPENED(s->state)); + stream_cork(u, TRUE); + break; + + case PA_SOURCE_IDLE: + case PA_SOURCE_RUNNING: + if (s->state == PA_SOURCE_SUSPENDED) + stream_cork(u, FALSE); + break; + + case PA_SOURCE_UNLINKED: + case PA_SOURCE_INIT: + ; + } + + return 0; +} + +#endif + +static void thread_func(void *userdata) { + struct userdata *u = userdata; + + pa_assert(u); + + pa_log_debug("Thread starting up"); + + pa_thread_mq_install(&u->thread_mq); + pa_rtpoll_install(u->rtpoll); + + for (;;) { + int ret; + + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) + goto fail; + + if (ret == 0) + goto finish; + } + +fail: + /* If this was no regular exit from the loop we have to continue + * 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_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("Thread shutting down"); +} + +#ifdef TUNNEL_SINK static void command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; uint32_t bytes, channel; - assert(pd && command == PA_COMMAND_REQUEST && t && u && u->pdispatch == pd); + + pa_assert(pd); + pa_assert(command == PA_COMMAND_REQUEST); + pa_assert(t); + pa_assert(u); + pa_assert(u->pdispatch == pd); if (pa_tagstruct_getu32(t, &channel) < 0 || pa_tagstruct_getu32(t, &bytes) < 0 || !pa_tagstruct_eof(t)) { - pa_log("invalid protocol reply"); - die(u); - return; + pa_log("Invalid protocol reply"); + goto fail; } if (channel != u->channel) { - pa_log("recieved data for invalid channel"); - die(u); - return; + pa_log("Recieved data for invalid channel"); + goto fail; } - u->requested_bytes += bytes; - send_bytes(u); + pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_REQUEST, NULL, bytes, NULL); + return; + +fail: + pa_module_unload_request(u->module); } #endif static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; - pa_usec_t sink_usec, source_usec, transport_usec; + pa_usec_t sink_usec, source_usec, transport_usec, host_usec, k; int playing; int64_t write_index, read_index; struct timeval local, remote, now; - assert(pd && u); + + pa_assert(pd); + pa_assert(u); if (command != PA_COMMAND_REPLY) { if (command == PA_COMMAND_ERROR) - pa_log("failed to get latency."); + pa_log("Failed to get latency."); else - pa_log("protocol error."); - die(u); - return; + pa_log("Protocol error."); + goto fail; } if (pa_tagstruct_get_usec(t, &sink_usec) < 0 || @@ -328,15 +457,12 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G pa_tagstruct_gets64(t, &write_index) < 0 || pa_tagstruct_gets64(t, &read_index) < 0 || !pa_tagstruct_eof(t)) { - pa_log("invalid reply. (latency)"); - die(u); - return; + pa_log("Invalid reply. (latency)"); + goto fail; } pa_gettimeofday(&now); - /* FIXME! This could use some serious love. */ - if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) { /* local and remote seem to have synchronized clocks */ #ifdef TUNNEL_SINK @@ -348,23 +474,40 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G transport_usec = pa_timeval_diff(&now, &local)/2; #ifdef TUNNEL_SINK - u->host_latency = sink_usec + transport_usec; + host_usec = sink_usec + transport_usec; #else - u->host_latency = source_usec + transport_usec; - if (u->host_latency > sink_usec) - u->host_latency -= sink_usec; + host_usec = source_usec + transport_usec; + if (host_usec > sink_usec) + host_usec -= sink_usec; else - u->host_latency = 0; + host_usec = 0; #endif -/* pa_log("estimated host latency: %0.0f usec", (double) u->host_latency); */ +#ifdef TUNNEL_SINK + k = pa_bytes_to_usec(u->counter - u->counter_delta, &u->sink->sample_spec); + + if (k > host_usec) + k -= host_usec; + else + k = 0; +#else + k = pa_bytes_to_usec(u->counter - u->counter_delta, &u->source->sample_spec); + k += host_usec; +#endif + + pa_smoother_put(u->smoother, pa_rtclock_usec(), k); + + return; + +fail: + pa_module_unload_request(u->module); } static void request_latency(struct userdata *u) { pa_tagstruct *t; struct timeval now; uint32_t tag; - assert(u); + pa_assert(u); t = pa_tagstruct_new(NULL, 0); #ifdef TUNNEL_SINK @@ -380,123 +523,17 @@ static void request_latency(struct userdata *u) { pa_pstream_send_tagstruct(u->pstream, t); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u, NULL); -} -static void stream_get_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { - struct userdata *u = userdata; - uint32_t idx, owner_module, monitor_source; - pa_usec_t latency; - const char *name, *description, *monitor_source_name, *driver; - int mute; - uint32_t flags; - pa_sample_spec sample_spec; - pa_channel_map channel_map; - pa_cvolume volume; - assert(pd && u); - - if (command != PA_COMMAND_REPLY) { - if (command == PA_COMMAND_ERROR) - pa_log("failed to get info."); - else - pa_log("protocol error."); - die(u); - return; - } - - if (pa_tagstruct_getu32(t, &idx) < 0 || - pa_tagstruct_gets(t, &name) < 0 || - pa_tagstruct_gets(t, &description) < 0 || - pa_tagstruct_get_sample_spec(t, &sample_spec) < 0 || - pa_tagstruct_get_channel_map(t, &channel_map) < 0 || - pa_tagstruct_getu32(t, &owner_module) < 0 || - pa_tagstruct_get_cvolume(t, &volume) < 0 || - pa_tagstruct_get_boolean(t, &mute) < 0 || - pa_tagstruct_getu32(t, &monitor_source) < 0 || - pa_tagstruct_gets(t, &monitor_source_name) < 0 || - pa_tagstruct_get_usec(t, &latency) < 0 || - pa_tagstruct_gets(t, &driver) < 0 || - pa_tagstruct_getu32(t, &flags) < 0 || - !pa_tagstruct_eof(t)) { - pa_log("invalid reply. (get_info)"); - die(u); - return; - } - -#ifdef TUNNEL_SINK - assert(u->sink); - if ((!!mute == !!u->sink->hw_muted) && - pa_cvolume_equal(&volume, &u->sink->hw_volume)) - return; -#else - assert(u->source); - if ((!!mute == !!u->source->hw_muted) && - pa_cvolume_equal(&volume, &u->source->hw_volume)) - return; -#endif - -#ifdef TUNNEL_SINK - memcpy(&u->sink->hw_volume, &volume, sizeof(pa_cvolume)); - u->sink->hw_muted = !!mute; - - pa_subscription_post(u->sink->core, - PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, - u->sink->index); -#else - memcpy(&u->source->hw_volume, &volume, sizeof(pa_cvolume)); - u->source->hw_muted = !!mute; - - pa_subscription_post(u->source->core, - PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, - u->source->index); -#endif -} - -static void request_info(struct userdata *u) { - pa_tagstruct *t; - uint32_t tag; - assert(u); - - t = pa_tagstruct_new(NULL, 0); -#ifdef TUNNEL_SINK - pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); -#else - pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); -#endif - pa_tagstruct_putu32(t, tag = u->ctag++); - - pa_tagstruct_putu32(t, PA_INVALID_INDEX); -#ifdef TUNNEL_SINK - pa_tagstruct_puts(t, u->sink_name); -#else - pa_tagstruct_puts(t, u->source_name); -#endif - - pa_pstream_send_tagstruct(u->pstream, t); - pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_info_callback, u, NULL); -} - -static void start_subscribe(struct userdata *u) { - pa_tagstruct *t; - uint32_t tag; - assert(u); - - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); - pa_tagstruct_putu32(t, tag = u->ctag++); - -#ifdef TUNNEL_SINK - pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SINK); -#else - pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SOURCE); -#endif - - pa_pstream_send_tagstruct(u->pstream, t); + u->counter_delta = 0; } static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) { struct userdata *u = userdata; struct timeval ntv; - assert(m && e && u); + + pa_assert(m); + pa_assert(e); + pa_assert(u); request_latency(u); @@ -505,24 +542,164 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED m->time_restart(e, &ntv); } -static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { +#ifdef TUNNEL_SINK +static pa_usec_t sink_get_latency(pa_sink *s) { + pa_usec_t t, c; + struct userdata *u = s->userdata; + + pa_sink_assert_ref(s); + + c = pa_bytes_to_usec(u->counter, &s->sample_spec); + t = pa_smoother_get(u->smoother, pa_rtclock_usec()); + + return c > t ? c - t : 0; +} +#else +static pa_usec_t source_get_latency(pa_source *s) { + pa_usec_t t, c; + struct userdata *u = s->userdata; + + pa_source_assert_ref(s); + + c = pa_bytes_to_usec(u->counter, &s->sample_spec); + t = pa_smoother_get(u->smoother, pa_rtclock_usec()); + + return t > c ? t - c : 0; +} +#endif + +#ifdef TUNNEL_SINK + +static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; - struct timeval ntv; - assert(pd && u && u->pdispatch == pd); + uint32_t idx, owner_module, client, sink; + pa_usec_t buffer_usec, sink_usec; + const char *name, *driver, *resample_method; + int mute; + pa_sample_spec sample_spec; + pa_channel_map channel_map; + pa_cvolume volume; + + pa_assert(pd); + pa_assert(u); if (command != PA_COMMAND_REPLY) { if (command == PA_COMMAND_ERROR) - pa_log("failed to create stream."); + pa_log("Failed to get info."); else - pa_log("protocol error."); - die(u); + pa_log("Protocol error."); + goto fail; + } + + if (pa_tagstruct_getu32(t, &idx) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_getu32(t, &owner_module) < 0 || + pa_tagstruct_getu32(t, &client) < 0 || + pa_tagstruct_getu32(t, &sink) < 0 || + pa_tagstruct_get_sample_spec(t, &sample_spec) < 0 || + pa_tagstruct_get_channel_map(t, &channel_map) < 0 || + pa_tagstruct_get_cvolume(t, &volume) < 0 || + pa_tagstruct_get_usec(t, &buffer_usec) < 0 || + pa_tagstruct_get_usec(t, &sink_usec) < 0 || + pa_tagstruct_gets(t, &resample_method) < 0 || + pa_tagstruct_gets(t, &driver) < 0 || + (u->version >= 11 && pa_tagstruct_get_boolean(t, &mute) < 0) || + !pa_tagstruct_eof(t)) { + pa_log("Invalid reply. (get_info)"); + goto fail; + } + + pa_assert(u->sink); + + if ((u->version < 11 || !!mute == !!u->sink->muted) && + pa_cvolume_equal(&volume, &u->sink->volume)) return; + + memcpy(&u->sink->volume, &volume, sizeof(pa_cvolume)); + + if (u->version >= 11) + u->sink->muted = !!mute; + + pa_subscription_post(u->sink->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, u->sink->index); + return; + +fail: + pa_module_unload_request(u->module); +} + +static void request_info(struct userdata *u) { + pa_tagstruct *t; + uint32_t tag; + pa_assert(u); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INPUT_INFO); + pa_tagstruct_putu32(t, tag = u->ctag++); + pa_tagstruct_putu32(t, u->device_index); + pa_pstream_send_tagstruct(u->pstream, t); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, sink_input_info_cb, u, NULL); +} + +static void command_subscribe_event(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + pa_subscription_event_type_t e; + uint32_t idx; + + pa_assert(pd); + pa_assert(t); + pa_assert(u); + pa_assert(command == PA_COMMAND_SUBSCRIBE_EVENT); + + if (pa_tagstruct_getu32(t, &e) < 0 || + pa_tagstruct_getu32(t, &idx) < 0 || + !pa_tagstruct_eof(t)) { + pa_log("Invalid protocol reply"); + pa_module_unload_request(u->module); + return; + } + + if (e != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE)) + return; + + request_info(u); +} + +static void start_subscribe(struct userdata *u) { + pa_tagstruct *t; + uint32_t tag; + pa_assert(u); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); + pa_tagstruct_putu32(t, tag = u->ctag++); + pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SINK_INPUT); + pa_pstream_send_tagstruct(u->pstream, t); +} +#endif + +static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + struct timeval ntv; +#ifdef TUNNEL_SINK + uint32_t bytes; +#endif + + pa_assert(pd); + pa_assert(u); + pa_assert(u->pdispatch == pd); + + if (command != PA_COMMAND_REPLY) { + if (command == PA_COMMAND_ERROR) + pa_log("Failed to create stream."); + else + pa_log("Protocol error."); + goto fail; } if (pa_tagstruct_getu32(t, &u->channel) < 0 || pa_tagstruct_getu32(t, &u->device_index) < 0 #ifdef TUNNEL_SINK - || pa_tagstruct_getu32(t, &u->requested_bytes) < 0 + || pa_tagstruct_getu32(t, &bytes) < 0 #endif ) goto parse_error; @@ -548,24 +725,31 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN if (!pa_tagstruct_eof(t)) goto parse_error; +#ifdef TUNNEL_SINK start_subscribe(u); request_info(u); +#endif - assert(!u->time_event); + pa_assert(!u->time_event); pa_gettimeofday(&ntv); ntv.tv_sec += LATENCY_INTERVAL; u->time_event = u->core->mainloop->time_new(u->core->mainloop, &ntv, timeout_callback, u); request_latency(u); + + pa_log_debug("Stream created."); + #ifdef TUNNEL_SINK - send_bytes(u); + pa_asyncmsgq_post(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_REQUEST, NULL, bytes, NULL, NULL); #endif return; parse_error: - pa_log("invalid reply. (create stream)"); - die(u); + pa_log("Invalid reply. (Create stream)"); + +fail: + pa_module_unload_request(u->module); } static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -575,24 +759,26 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t #ifdef TUNNEL_SINK pa_cvolume volume; #endif - assert(pd && u && u->pdispatch == pd); + + pa_assert(pd); + pa_assert(u); + pa_assert(u->pdispatch == pd); if (command != PA_COMMAND_REPLY || pa_tagstruct_getu32(t, &u->version) < 0 || !pa_tagstruct_eof(t)) { if (command == PA_COMMAND_ERROR) - pa_log("failed to authenticate"); + pa_log("Failed to authenticate"); else - pa_log("protocol error."); - die(u); - return; + pa_log("Protocol error."); + + goto fail; } /* Minimum supported protocol version */ if (u->version < 8) { - pa_log("incompatible protocol version"); - die(u); - return; + pa_log("Incompatible protocol version"); + goto fail; } #ifdef TUNNEL_SINK @@ -615,6 +801,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t /* We ignore the server's reply here */ reply = pa_tagstruct_new(NULL, 0); + #ifdef TUNNEL_SINK pa_tagstruct_putu32(reply, PA_COMMAND_CREATE_PLAYBACK_STREAM); pa_tagstruct_putu32(reply, tag = u->ctag++); @@ -623,11 +810,11 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct_put_channel_map(reply, &u->sink->channel_map); pa_tagstruct_putu32(reply, PA_INVALID_INDEX); pa_tagstruct_puts(reply, u->sink_name); - pa_tagstruct_putu32(reply, DEFAULT_MAXLENGTH); - pa_tagstruct_put_boolean(reply, 0); - pa_tagstruct_putu32(reply, DEFAULT_TLENGTH); - pa_tagstruct_putu32(reply, DEFAULT_PREBUF); - pa_tagstruct_putu32(reply, DEFAULT_MINREQ); + pa_tagstruct_putu32(reply, u->maxlength); + pa_tagstruct_put_boolean(reply, FALSE); + pa_tagstruct_putu32(reply, u->tlength); + pa_tagstruct_putu32(reply, u->prebuf); + pa_tagstruct_putu32(reply, u->minreq); pa_tagstruct_putu32(reply, 0); pa_cvolume_reset(&volume, u->sink->sample_spec.channels); pa_tagstruct_put_cvolume(reply, &volume); @@ -639,59 +826,82 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct_put_channel_map(reply, &u->source->channel_map); pa_tagstruct_putu32(reply, PA_INVALID_INDEX); pa_tagstruct_puts(reply, u->source_name); - pa_tagstruct_putu32(reply, DEFAULT_MAXLENGTH); + pa_tagstruct_putu32(reply, u->maxlength); pa_tagstruct_put_boolean(reply, 0); - pa_tagstruct_putu32(reply, DEFAULT_FRAGSIZE); + pa_tagstruct_putu32(reply, u->fragsize); #endif pa_pstream_send_tagstruct(u->pstream, reply); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u, NULL); + + pa_log_debug("Connection authenticated, creating stream ..."); + + return; + +fail: + pa_module_unload_request(u->module); } static void pstream_die_callback(pa_pstream *p, void *userdata) { struct userdata *u = userdata; - assert(p && u); - pa_log("stream died."); - die(u); + pa_assert(p); + pa_assert(u); + + pa_log_warn("Stream died."); + pa_module_unload_request(u->module); } static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { struct userdata *u = userdata; - assert(p && packet && u); + + pa_assert(p); + pa_assert(packet); + pa_assert(u); if (pa_pdispatch_run(u->pdispatch, packet, creds, u) < 0) { - pa_log("invalid packet"); - die(u); + pa_log("Invalid packet"); + pa_module_unload_request(u->module); + return; } } #ifndef TUNNEL_SINK -static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, PA_GCC_UNUSED int64_t offset, PA_GCC_UNUSED pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { +static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { struct userdata *u = userdata; - assert(p && chunk && u); + + pa_assert(p); + pa_assert(chunk); + pa_assert(u); if (channel != u->channel) { - pa_log("recieved memory block on bad channel."); - die(u); + pa_log("Recieved memory block on bad channel."); + pa_module_unload_request(u->module); return; } - pa_source_post(u->source, chunk); + pa_asyncmsgq_send(u->source->asyncmsgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_POST, PA_UINT_TO_PTR(seek), offset, chunk); + + u->counter += chunk->length; + u->counter_delta += chunk->length; } + #endif static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata) { struct userdata *u = userdata; pa_tagstruct *t; uint32_t tag; - assert(sc && u && u->client == sc); + + pa_assert(sc); + pa_assert(u); + pa_assert(u->client == sc); pa_socket_client_unref(u->client); u->client = NULL; if (!io) { - pa_log("connection failed."); + pa_log("Connection failed: %s", pa_cstrerror(errno)); pa_module_unload_request(u->module); return; } @@ -710,161 +920,85 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata pa_tagstruct_putu32(t, tag = u->ctag++); pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, u->auth_cookie, sizeof(u->auth_cookie)); + +#ifdef HAVE_CREDS +{ + pa_creds ucred; + + if (pa_iochannel_creds_supported(io)) + pa_iochannel_creds_enable(io); + + ucred.uid = getuid(); + ucred.gid = getgid(); + + pa_pstream_send_tagstruct_with_creds(u->pstream, t, &ucred); +} +#else pa_pstream_send_tagstruct(u->pstream, t); +#endif + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, u, NULL); + pa_log_debug("Connection established, authenticating ..."); } #ifdef TUNNEL_SINK -static void sink_notify(pa_sink*sink) { - struct userdata *u; - assert(sink && sink->userdata); - u = sink->userdata; - - send_bytes(u); -} - -static pa_usec_t sink_get_latency(pa_sink *sink) { - struct userdata *u; - uint32_t l; - pa_usec_t usec = 0; - assert(sink && sink->userdata); - u = sink->userdata; - - l = DEFAULT_TLENGTH; - - if (l > u->requested_bytes) { - l -= u->requested_bytes; - usec += pa_bytes_to_usec(l, &u->sink->sample_spec); - } - - usec += u->host_latency; - - return usec; -} - -static int sink_get_hw_volume(pa_sink *sink) { - struct userdata *u; - assert(sink && sink->userdata); - u = sink->userdata; +static int sink_get_volume(pa_sink *sink) { return 0; } -static int sink_set_hw_volume(pa_sink *sink) { +static int sink_set_volume(pa_sink *sink) { struct userdata *u; pa_tagstruct *t; uint32_t tag; - assert(sink && sink->userdata); + + pa_assert(sink); u = sink->userdata; + pa_assert(u); t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME); pa_tagstruct_putu32(t, tag = u->ctag++); - - pa_tagstruct_putu32(t, PA_INVALID_INDEX); - pa_tagstruct_puts(t, u->sink_name); - pa_tagstruct_put_cvolume(t, &sink->hw_volume); + pa_tagstruct_putu32(t, u->device_index); + pa_tagstruct_put_cvolume(t, &sink->volume); pa_pstream_send_tagstruct(u->pstream, t); return 0; } -static int sink_get_hw_mute(pa_sink *sink) { +static int sink_get_mute(pa_sink *sink) { + return 0; +} + +static int sink_set_mute(pa_sink *sink) { struct userdata *u; - assert(sink && sink->userdata); + pa_tagstruct *t; + uint32_t tag; + + pa_assert(sink); u = sink->userdata; + pa_assert(u); - return 0; -} - -static int sink_set_hw_mute(pa_sink *sink) { - struct userdata *u; - pa_tagstruct *t; - uint32_t tag; - assert(sink && sink->userdata); - u = sink->userdata; + if (u->version < 11) + return -1; t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_MUTE); + pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_MUTE); pa_tagstruct_putu32(t, tag = u->ctag++); - - pa_tagstruct_putu32(t, PA_INVALID_INDEX); - pa_tagstruct_puts(t, u->sink_name); - pa_tagstruct_put_boolean(t, !!sink->hw_muted); + pa_tagstruct_putu32(t, u->device_index); + pa_tagstruct_put_boolean(t, !!sink->muted); pa_pstream_send_tagstruct(u->pstream, t); return 0; } -#else -static pa_usec_t source_get_latency(pa_source *source) { - struct userdata *u; - assert(source && source->userdata); - u = source->userdata; - - return u->host_latency; -} - -static int source_get_hw_volume(pa_source *source) { - struct userdata *u; - assert(source && source->userdata); - u = source->userdata; - - return 0; -} - -static int source_set_hw_volume(pa_source *source) { - struct userdata *u; - pa_tagstruct *t; - uint32_t tag; - assert(source && source->userdata); - u = source->userdata; - - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_SOURCE_VOLUME); - pa_tagstruct_putu32(t, tag = u->ctag++); - - pa_tagstruct_putu32(t, PA_INVALID_INDEX); - pa_tagstruct_puts(t, u->source_name); - pa_tagstruct_put_cvolume(t, &source->hw_volume); - pa_pstream_send_tagstruct(u->pstream, t); - - return 0; -} - -static int source_get_hw_mute(pa_source *source) { - struct userdata *u; - assert(source && source->userdata); - u = source->userdata; - - return 0; -} - -static int source_set_hw_mute(pa_source *source) { - struct userdata *u; - pa_tagstruct *t; - uint32_t tag; - assert(source && source->userdata); - u = source->userdata; - - t = pa_tagstruct_new(NULL, 0); - pa_tagstruct_putu32(t, PA_COMMAND_SET_SOURCE_MUTE); - pa_tagstruct_putu32(t, tag = u->ctag++); - - pa_tagstruct_putu32(t, PA_INVALID_INDEX); - pa_tagstruct_puts(t, u->source_name); - pa_tagstruct_put_boolean(t, !!source->hw_muted); - pa_pstream_send_tagstruct(u->pstream, t); - - return 0; -} #endif static int load_key(struct userdata *u, const char*fn) { - assert(u); + pa_assert(u); - u->auth_cookie_in_property = 0; + u->auth_cookie_in_property = FALSE; if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { pa_log_debug("using already loaded auth cookie."); @@ -882,29 +1016,29 @@ static int load_key(struct userdata *u, const char*fn) { pa_log_debug("loading cookie from disk."); if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) - u->auth_cookie_in_property = 1; + u->auth_cookie_in_property = TRUE; return 0; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u = NULL; pa_sample_spec ss; pa_channel_map map; char *t, *dn = NULL; - assert(c && m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments"); goto fail; } - u = pa_xmalloc(sizeof(struct userdata)); + u = pa_xnew(struct userdata, 1); m->userdata = u; u->module = m; - u->core = c; + u->core = m->core; u->client = NULL; u->pdispatch = NULL; u->pstream = NULL; @@ -917,12 +1051,16 @@ int pa__init(pa_core *c, pa_module*m) { u->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));; u->source = NULL; #endif + u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE); u->ctag = 1; u->device_index = u->channel = PA_INVALID_INDEX; - u->host_latency = 0; - u->auth_cookie_in_property = 0; + u->auth_cookie_in_property = FALSE; u->time_event = NULL; + pa_thread_mq_init(&u->thread_mq, m->core->mainloop); + u->rtpoll = pa_rtpoll_new(); + pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq); + if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0) goto fail; @@ -931,20 +1069,17 @@ int pa__init(pa_core *c, pa_module*m) { goto fail; } - ss = c->default_sample_spec; + ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log("invalid sample format specification"); goto fail; } - if (!(u->client = pa_socket_client_new_string(c->mainloop, u->server_name, PA_NATIVE_DEFAULT_PORT))) { + if (!(u->client = pa_socket_client_new_string(m->core->mainloop, u->server_name, PA_NATIVE_DEFAULT_PORT))) { pa_log("failed to connect to server '%s'", u->server_name); goto fail; } - if (!u->client) - goto fail; - pa_socket_client_set_callback(u->client, on_connection, u); #ifdef TUNNEL_SINK @@ -952,55 +1087,81 @@ int pa__init(pa_core *c, pa_module*m) { if (!(dn = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL)))) dn = pa_sprintf_malloc("tunnel.%s", u->server_name); - if (!(u->sink = pa_sink_new(c, __FILE__, dn, 0, &ss, &map))) { - pa_log("failed to create sink."); + if (!(u->sink = pa_sink_new(m->core, __FILE__, dn, 0, &ss, &map))) { + pa_log("Failed to create sink."); goto fail; } - u->sink->get_latency = sink_get_latency; - u->sink->get_hw_volume = sink_get_hw_volume; - u->sink->set_hw_volume = sink_set_hw_volume; - u->sink->get_hw_mute = sink_get_hw_mute; - u->sink->set_hw_mute = sink_set_hw_mute; - u->sink->notify = sink_notify; + u->sink->parent.process_msg = sink_process_msg; u->sink->userdata = u; + u->sink->set_state = sink_set_state; + u->sink->get_latency = sink_get_latency; + u->sink->get_volume = sink_get_volume; + u->sink->get_mute = sink_get_mute; + u->sink->set_volume = sink_set_volume; + u->sink->set_mute = sink_set_mute; + + pa_sink_set_module(u->sink, m); + pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); + pa_sink_set_rtpoll(u->sink, u->rtpoll); pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Tunnel to %s%s%s", u->sink_name ? u->sink_name : "", u->sink_name ? " on " : "", u->server_name)); pa_xfree(t); - pa_sink_set_owner(u->sink, m); #else if (!(dn = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL)))) dn = pa_sprintf_malloc("tunnel.%s", u->server_name); - if (!(u->source = pa_source_new(c, __FILE__, dn, 0, &ss, &map))) { - pa_log("failed to create source."); + if (!(u->source = pa_source_new(m->core, __FILE__, dn, 0, &ss, &map))) { + pa_log("Failed to create source."); goto fail; } - u->source->get_latency = source_get_latency; - u->source->get_hw_volume = source_get_hw_volume; - u->source->set_hw_volume = source_set_hw_volume; - u->source->get_hw_mute = source_get_hw_mute; - u->source->set_hw_mute = source_set_hw_mute; + u->source->parent.process_msg = source_process_msg; u->source->userdata = u; + u->source->set_state = source_set_state; + u->source->get_latency = source_get_latency; + pa_source_set_module(u->source, m); + pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); + pa_source_set_rtpoll(u->source, u->rtpoll); pa_source_set_description(u->source, t = pa_sprintf_malloc("Tunnel to %s%s%s", u->source_name ? u->source_name : "", u->source_name ? " on " : "", u->server_name)); pa_xfree(t); - - pa_source_set_owner(u->source, m); #endif pa_xfree(dn); u->time_event = NULL; + u->maxlength = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_MAXLENGTH_MSEC, &ss); +#ifdef TUNNEL_SINK + u->tlength = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_TLENGTH_MSEC, &ss); + u->minreq = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_MINREQ_MSEC, &ss); + u->prebuf = u->tlength; +#else + u->fragsize = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_FRAGSIZE_MSEC, &ss); +#endif + + u->counter = u->counter_delta = 0; + pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec()); + + if (!(u->thread = pa_thread_new(thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } + +#ifdef TUNNEL_SINK + pa_sink_put(u->sink); +#else + pa_source_put(u->source); +#endif + pa_modargs_free(ma); return 0; fail: - pa__done(c, m); + pa__done(m); if (ma) pa_modargs_free(ma); @@ -1010,17 +1171,59 @@ fail: return -1; } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata* u; - assert(c && m); + + pa_assert(m); if (!(u = m->userdata)) return; - close_stuff(u); +#ifdef TUNNEL_SINK + if (u->sink) + pa_sink_unlink(u->sink); +#else + if (u->source) + pa_source_unlink(u->source); +#endif + + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } + + pa_thread_mq_done(&u->thread_mq); + +#ifdef TUNNEL_SINK + if (u->sink) + pa_sink_unref(u->sink); +#else + if (u->source) + pa_source_unref(u->source); +#endif + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + if (u->pstream) { + pa_pstream_unlink(u->pstream); + pa_pstream_unref(u->pstream); + } + + if (u->pdispatch) + pa_pdispatch_unref(u->pdispatch); + + if (u->client) + pa_socket_client_unref(u->client); if (u->auth_cookie_in_property) - pa_authkey_prop_unref(c, PA_NATIVE_COOKIE_PROPERTY_NAME); + pa_authkey_prop_unref(m->core, PA_NATIVE_COOKIE_PROPERTY_NAME); + + if (u->smoother) + pa_smoother_free(u->smoother); + + if (u->time_event) + u->core->mainloop->time_free(u->time_event); #ifdef TUNNEL_SINK pa_xfree(u->sink_name); @@ -1031,5 +1234,3 @@ void pa__done(pa_core *c, pa_module*m) { pa_xfree(u); } - - From 0ce32bd40c07af44cb13c80f559d18e162266a89 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 20:01:20 +0000 Subject: [PATCH 1382/1514] fail on name clash git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1980 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 1682007ac..936821ff6 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -1087,7 +1087,7 @@ int pa__init(pa_module*m) { if (!(dn = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL)))) dn = pa_sprintf_malloc("tunnel.%s", u->server_name); - if (!(u->sink = pa_sink_new(m->core, __FILE__, dn, 0, &ss, &map))) { + if (!(u->sink = pa_sink_new(m->core, __FILE__, dn, 1, &ss, &map))) { pa_log("Failed to create sink."); goto fail; } @@ -1112,7 +1112,7 @@ int pa__init(pa_module*m) { if (!(dn = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL)))) dn = pa_sprintf_malloc("tunnel.%s", u->server_name); - if (!(u->source = pa_source_new(m->core, __FILE__, dn, 0, &ss, &map))) { + if (!(u->source = pa_source_new(m->core, __FILE__, dn, 1, &ss, &map))) { pa_log("Failed to create source."); goto fail; } From 9ca7ed19580063255dd2d781120b057114b1f5cc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 20:01:49 +0000 Subject: [PATCH 1383/1514] export pa_namereg_is_valid_name() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1981 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/namereg.c | 14 +++++++------- src/pulsecore/namereg.h | 3 +++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index fe2be4671..fe520384e 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -56,20 +56,20 @@ static int is_valid_char(char c) { c == '_'; } -static int is_valid_name(const char *name) { +pa_bool_t pa_namereg_is_valid_name(const char *name) { const char *c; if (*name == 0) - return 0; + return FALSE; for (c = name; *c && (c-name < PA_NAME_MAX); c++) if (!is_valid_char(*c)) - return 0; + return FALSE; if (*c) - return 0; + return FALSE; - return 1; + return TRUE; } static char* cleanup_name(const char *name) { @@ -111,7 +111,7 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t return NULL; if ((type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE) && - !is_valid_name(name) ) { + !pa_namereg_is_valid_name(name) ) { if (fail) return NULL; @@ -253,7 +253,7 @@ int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) if (name && *s && !strcmp(name, *s)) return 0; - if (!is_valid_name(name)) + if (!pa_namereg_is_valid_name(name)) return -1; pa_xfree(*s); diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index 350ba0f6e..d0db9e813 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -25,6 +25,7 @@ ***/ #include +#include #define PA_NAME_MAX 128 @@ -44,4 +45,6 @@ int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type); const char *pa_namereg_get_default_sink_name(pa_core *c); const char *pa_namereg_get_default_source_name(pa_core *c); +pa_bool_t pa_namereg_is_valid_name(const char *name); + #endif From 9f446590e3f5d9ee32b2591b2500464079ba3426 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 20:03:07 +0000 Subject: [PATCH 1384/1514] publish dns-sd subtypes to allow distinction of virtual, hardware and monitor sinks/source git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1982 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-zeroconf-publish.c | 72 ++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 113686cfd..b9b9b22c9 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -60,21 +60,35 @@ PA_MODULE_USAGE("port=") #define SERVICE_TYPE_SINK "_pulse-sink._tcp" #define SERVICE_TYPE_SOURCE "_pulse-source._tcp" #define SERVICE_TYPE_SERVER "_pulse-server._tcp" +#define SERVICE_SUBTYPE_SINK_HARDWARE "_hardware._sub."SERVICE_TYPE_SINK +#define SERVICE_SUBTYPE_SINK_VIRTUAL "_virtual._sub."SERVICE_TYPE_SINK +#define SERVICE_SUBTYPE_SOURCE_HARDWARE "_hardware._sub."SERVICE_TYPE_SOURCE +#define SERVICE_SUBTYPE_SOURCE_VIRTUAL "_virtual._sub."SERVICE_TYPE_SOURCE +#define SERVICE_SUBTYPE_SOURCE_MONITOR "_monitor._sub."SERVICE_TYPE_SOURCE +#define SERVICE_SUBTYPE_SOURCE_NON_MONITOR "_non-monitor._sub."SERVICE_TYPE_SOURCE static const char* const valid_modargs[] = { "port", NULL }; +enum service_subtype { + SUBTYPE_HARDWARE, + SUBTYPE_VIRTUAL, + SUBTYPE_MONITOR +}; + struct service { struct userdata *userdata; AvahiEntryGroup *entry_group; char *service_name; pa_object *device; + enum service_subtype subtype; }; struct userdata { pa_core *core; + pa_module *module; AvahiPoll *avahi_poll; AvahiClient *client; @@ -88,10 +102,11 @@ struct userdata { pa_hook_slot *sink_new_slot, *source_new_slot, *sink_unlink_slot, *source_unlink_slot, *sink_changed_slot, *source_changed_slot; }; -static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_channel_map *ret_map, const char **ret_name, const char **ret_description) { +static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_channel_map *ret_map, const char **ret_name, const char **ret_description, enum service_subtype *ret_subtype) { pa_assert(s); pa_assert(ret_ss); pa_assert(ret_description); + pa_assert(ret_subtype); if (pa_sink_isinstance(s->device)) { pa_sink *sink = PA_SINK(s->device); @@ -100,6 +115,7 @@ static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_chann *ret_map = sink->channel_map; *ret_name = sink->name; *ret_description = sink->description; + *ret_subtype = sink->flags & PA_SINK_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL; } else if (pa_source_isinstance(s->device)) { pa_source *source = PA_SOURCE(s->device); @@ -108,6 +124,8 @@ static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_chann *ret_map = source->channel_map; *ret_name = source->name; *ret_description = source->description; + *ret_subtype = source->monitor_of ? SUBTYPE_MONITOR : (source->flags & PA_SOURCE_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL); + } else pa_assert_not_reached(); } @@ -174,6 +192,13 @@ static int publish_service(struct service *s) { pa_sample_spec ss; pa_channel_map map; char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + enum service_subtype subtype; + + const char * const subtype_text[] = { + [SUBTYPE_HARDWARE] = "hardware", + [SUBTYPE_VIRTUAL] = "virtual", + [SUBTYPE_MONITOR] = "monitor" + }; pa_assert(s); @@ -190,12 +215,13 @@ static int publish_service(struct service *s) { txt = txt_record_server_data(s->userdata->core, txt); - get_service_data(s, &ss, &map, &name, &description); + get_service_data(s, &ss, &map, &name, &description, &subtype); txt = avahi_string_list_add_pair(txt, "device", name); txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate); txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels); txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format)); txt = avahi_string_list_add_pair(txt, "channel_map", pa_channel_map_snprint(cm, sizeof(cm), &map)); + txt = avahi_string_list_add_pair(txt, "subtype", subtype_text[subtype]); if (avahi_entry_group_add_service_strlst( s->entry_group, @@ -212,6 +238,35 @@ static int publish_service(struct service *s) { goto finish; } + if (avahi_entry_group_add_service_subtype( + s->entry_group, + AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + 0, + s->service_name, + pa_sink_isinstance(s->device) ? SERVICE_TYPE_SINK : SERVICE_TYPE_SOURCE, + NULL, + pa_sink_isinstance(s->device) ? (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SINK_HARDWARE : SERVICE_SUBTYPE_SINK_VIRTUAL) : + (subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SOURCE_HARDWARE : (subtype == SUBTYPE_VIRTUAL ? SERVICE_SUBTYPE_SOURCE_VIRTUAL : SERVICE_SUBTYPE_SOURCE_MONITOR))) < 0) { + + pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); + goto finish; + } + + if (pa_source_isinstance(s->device) && subtype != SUBTYPE_MONITOR) { + if (avahi_entry_group_add_service_subtype( + s->entry_group, + AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + 0, + s->service_name, + SERVICE_TYPE_SOURCE, + NULL, + SERVICE_SUBTYPE_SOURCE_NON_MONITOR) < 0) { + + pa_log("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); + goto finish; + } + } + if (avahi_entry_group_commit(s->entry_group) < 0) { pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(s->userdata->client))); goto finish; @@ -468,8 +523,10 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda unpublish_all_services(u, TRUE); avahi_client_free(u->client); - if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) - pa_log("pa_avahi_client_new() failed: %s", avahi_strerror(error)); + if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { + pa_log("avahi_client_new() failed: %s", avahi_strerror(error)); + pa_module_unload_request(u->module); + } } break; @@ -487,17 +544,18 @@ int pa__init(pa_module*m) { int error; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("failed to parse module arguments."); + pa_log("Failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port <= 0 || port > 0xFFFF) { - pa_log("invalid port specified."); + pa_log("Invalid port specified."); goto fail; } m->userdata = u = pa_xnew(struct userdata, 1); u->core = m->core; + u->module = m; u->port = (uint16_t) port; u->avahi_poll = pa_avahi_poll_new(m->core->mainloop); @@ -516,7 +574,7 @@ int pa__init(pa_module*m) { u->service_name = pa_truncate_utf8(pa_sprintf_malloc("%s@%s", pa_get_user_name(un, sizeof(un)), pa_get_host_name(hn, sizeof(hn))), AVAHI_LABEL_MAX); if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { - pa_log("pa_avahi_client_new() failed: %s", avahi_strerror(error)); + pa_log("avahi_client_new() failed: %s", avahi_strerror(error)); goto fail; } From 87be85618ce0bca05a4776bf7154c34b010fb6e9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 20:03:49 +0000 Subject: [PATCH 1385/1514] add new module module-zeroconf-discover git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1983 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 9 +- src/modules/module-zeroconf-discover.c | 338 +++++++++++++++++++++++++ 2 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 src/modules/module-zeroconf-discover.c diff --git a/src/Makefile.am b/src/Makefile.am index 911bd7b62..b1393e34c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1019,7 +1019,8 @@ endif if HAVE_AVAHI modlibexec_LTLIBRARIES += \ - module-zeroconf-publish.la + module-zeroconf-publish.la \ + module-zeroconf-discover.la endif if HAVE_LIRC @@ -1084,6 +1085,7 @@ SYMDEF_FILES = \ modules/module-null-sink-symdef.h \ modules/module-esound-sink-symdef.h \ modules/module-zeroconf-publish-symdef.h \ + modules/module-zeroconf-discover-symdef.h \ modules/module-lirc-symdef.h \ modules/module-mmkbd-evdev-symdef.h \ modules/module-http-protocol-tcp-symdef.h \ @@ -1303,6 +1305,11 @@ module_zeroconf_publish_la_LDFLAGS = -module -avoid-version module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(AVAHI_LIBS) libavahi-wrap.la libpulsecore.la module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) +module_zeroconf_discover_la_SOURCES = modules/module-zeroconf-discover.c +module_zeroconf_discover_la_LDFLAGS = -module -avoid-version +module_zeroconf_discover_la_LIBADD = $(AM_LIBADD) $(AVAHI_LIBS) libavahi-wrap.la libpulsecore.la +module_zeroconf_discover_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) + # LIRC module_lirc_la_SOURCES = modules/module-lirc.c diff --git a/src/modules/module-zeroconf-discover.c b/src/modules/module-zeroconf-discover.c new file mode 100644 index 000000000..b6f8cf6a4 --- /dev/null +++ b/src/modules/module-zeroconf-discover.c @@ -0,0 +1,338 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-zeroconf-discover-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Discovery") +PA_MODULE_VERSION(PACKAGE_VERSION) + +#define SERVICE_TYPE_SINK "_pulse-sink._tcp" +#define SERVICE_TYPE_SOURCE "_non-monitor._sub._pulse-source._tcp" + + static const char* const valid_modargs[] = { + NULL +}; + +struct userdata { + pa_core *core; + pa_module *module; + AvahiPoll *avahi_poll; + AvahiClient *client; + AvahiServiceBrowser *source_browser, *sink_browser; +}; + +static void resolver_cb( + AvahiServiceResolver *r, + AvahiIfIndex interface, AvahiProtocol protocol, + AvahiResolverEvent event, + const char *name, const char *type, const char *domain, + const char *host_name, const AvahiAddress *a, uint16_t port, + AvahiStringList *txt, + AvahiLookupResultFlags flags, + void *userdata) { + + struct userdata *u = userdata; + + pa_assert(u); + + if (event != AVAHI_RESOLVER_FOUND) + pa_log("Resolving of '%s' failed: %s", name, avahi_strerror(avahi_client_errno(u->client))); + else { + char *device = NULL, *dname, *module_name, *args; + const char *t; + char at[AVAHI_ADDRESS_STR_MAX], cmt[PA_CHANNEL_MAP_SNPRINT_MAX]; + pa_sample_spec ss; + pa_channel_map cm; + AvahiStringList *l; + pa_bool_t channel_map_set = FALSE; + + ss = u->core->default_sample_spec; + pa_channel_map_init_auto(&cm, ss.channels, PA_CHANNEL_MAP_DEFAULT); + + for (l = txt; l; l = l->next) { + char *key, *value; + pa_assert_se(avahi_string_list_get_pair(l, &key, &value, NULL) == 0); + + if (strcmp(key, "device") == 0) { + pa_xfree(device); + device = value; + value = NULL; + } else if (strcmp(key, "rate") == 0) + ss.rate = atoi(value); + else if (strcmp(key, "channels") == 0) + ss.channels = atoi(value); + else if (strcmp(key, "format") == 0) + ss.format = pa_parse_sample_format(value); + else if (strcmp(key, "channel_map") == 0) { + pa_channel_map_parse(&cm, value); + channel_map_set = TRUE; + } + + avahi_free(key); + avahi_free(value); + } + + if (!channel_map_set && cm.channels != ss.channels) + pa_channel_map_init_auto(&cm, ss.channels, PA_CHANNEL_MAP_DEFAULT); + + if (!pa_sample_spec_valid(&ss)) { + pa_log("Service '%s' contains an invalid sample specification.", name); + avahi_free(device); + goto finish; + } + + if (!pa_channel_map_valid(&cm) || cm.channels != ss.channels) { + pa_log("Service '%s' contains an invalid channel map.", name); + avahi_free(device); + goto finish; + } + + if (device) + dname = pa_sprintf_malloc("tunnel.%s.%s", host_name, device); + else + dname = pa_sprintf_malloc("tunnel.%s", host_name); + + if (!pa_namereg_is_valid_name(dname)) { + pa_log("Cannot construct valid device name from credentials of service '%s'.", dname); + avahi_free(device); + pa_xfree(dname); + goto finish; + } + + t = strstr(type, "sink") ? "sink" : "source"; + + module_name = pa_sprintf_malloc("module-tunnel-%s", t); + args = pa_sprintf_malloc("server=[%s]:%u " + "%s=%s " + "format=%s " + "channels=%u " + "rate=%u " + "%s_name=%s " + "channel_map=%s", + avahi_address_snprint(at, sizeof(at), a), port, + t, device, + pa_sample_format_to_string(ss.format), + ss.channels, + ss.rate, + t, dname, + pa_channel_map_snprint(cmt, sizeof(cmt), &cm)); + + pa_log_debug("Loading module-tunnel-%s with arguments '%s'", module_name, args); + pa_module_load(u->core, module_name, args); + + pa_xfree(module_name); + pa_xfree(dname); + pa_xfree(args); + avahi_free(device); + } + +finish: + + avahi_service_resolver_free(r); +} + +static void browser_cb( + AvahiServiceBrowser *b, + AvahiIfIndex interface, AvahiProtocol protocol, + AvahiBrowserEvent event, + const char *name, const char *type, const char *domain, + AvahiLookupResultFlags flags, + void *userdata) { + + struct userdata *u = userdata; + + pa_assert(u); + + if (event != AVAHI_BROWSER_NEW) + return; + + if (flags & AVAHI_LOOKUP_RESULT_LOCAL) + return; + + if (!(avahi_service_resolver_new(u->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolver_cb, u))) + pa_log("avahi_service_resolver_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); + + /* We ignore the returned resolver object here, since the we don't + * need to attach any special data to it, and we can still destory + * it from the callback */ +} + +static void client_callback(AvahiClient *c, AvahiClientState state, void *userdata) { + struct userdata *u = userdata; + + pa_assert(c); + pa_assert(u); + + u->client = c; + + switch (state) { + case AVAHI_CLIENT_S_REGISTERING: + case AVAHI_CLIENT_S_RUNNING: + case AVAHI_CLIENT_S_COLLISION: + + if (!u->sink_browser) { + + if (!(u->sink_browser = avahi_service_browser_new( + c, + AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + SERVICE_TYPE_SINK, + NULL, + 0, + browser_cb, u))) { + + pa_log("avahi_service_browser_new() failed: %s", avahi_strerror(avahi_client_errno(c))); + pa_module_unload_request(u->module); + } + } + + if (!u->source_browser) { + + if (!(u->source_browser = avahi_service_browser_new( + c, + AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + SERVICE_TYPE_SOURCE, + NULL, + 0, + browser_cb, u))) { + + pa_log("avahi_service_browser_new() failed: %s", avahi_strerror(avahi_client_errno(c))); + pa_module_unload_request(u->module); + } + } + + break; + + case AVAHI_CLIENT_FAILURE: + if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) { + int error; + + pa_log_debug("Avahi daemon disconnected."); + + if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { + pa_log("avahi_client_new() failed: %s", avahi_strerror(error)); + pa_module_unload_request(u->module); + } + } + + /* Fall through */ + + case AVAHI_CLIENT_CONNECTING: + + if (u->sink_browser) { + avahi_service_browser_free(u->sink_browser); + u->sink_browser = NULL; + } + + if (u->source_browser) { + avahi_service_browser_free(u->source_browser); + u->source_browser = NULL; + } + + break; + + default: ; + } +} + +int pa__init(pa_module*m) { + + struct userdata *u; + pa_modargs *ma = NULL; + int error; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments."); + goto fail; + } + + m->userdata = u = pa_xnew(struct userdata, 1); + u->core = m->core; + u->module = m; + u->sink_browser = u->source_browser = NULL; + + u->avahi_poll = pa_avahi_poll_new(m->core->mainloop); + + if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { + pa_log("pa_avahi_client_new() failed: %s", avahi_strerror(error)); + goto fail; + } + + pa_modargs_free(ma); + + return 0; + +fail: + pa__done(m); + + if (ma) + pa_modargs_free(ma); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata*u; + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->client) + avahi_client_free(u->client); + + if (u->avahi_poll) + pa_avahi_poll_free(u->avahi_poll); + + pa_xfree(u); +} From cc883852bc3c71e2c5c04177a6e4d29af18e2045 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 20:30:15 +0000 Subject: [PATCH 1386/1514] add new API pa_strlist_reverse() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1984 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/strlist.c | 15 +++++++++++++++ src/pulsecore/strlist.h | 3 +++ 2 files changed, 18 insertions(+) diff --git a/src/pulsecore/strlist.c b/src/pulsecore/strlist.c index 792af0ff8..ac83f6b15 100644 --- a/src/pulsecore/strlist.c +++ b/src/pulsecore/strlist.c @@ -146,3 +146,18 @@ pa_strlist* pa_strlist_parse(const char *s) { return head; } + +pa_strlist *pa_strlist_reverse(pa_strlist *l) { + pa_strlist *r = NULL; + + while (l) { + pa_strlist *n; + + n = l->next; + l->next = r; + r = l; + l = n; + } + + return r; +} diff --git a/src/pulsecore/strlist.h b/src/pulsecore/strlist.h index 96ad47e26..6e6e2d4a2 100644 --- a/src/pulsecore/strlist.h +++ b/src/pulsecore/strlist.h @@ -46,4 +46,7 @@ pa_strlist* pa_strlist_pop(pa_strlist *l, char **s); /* Parse a whitespace separated server list */ pa_strlist* pa_strlist_parse(const char *s); +/* Reverse string list */ +pa_strlist *pa_strlist_reverse(pa_strlist *l); + #endif From 43b5c65457e880a3e134f7c4adc745f690717830 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 20:30:53 +0000 Subject: [PATCH 1387/1514] reverse server order for PULSE_SERVER x11 property, to follow order in which modules are loaded git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1985 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-x11-publish.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index e0550e207..f350126ad 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -130,7 +130,10 @@ int pa__init(pa_module*m) { if (!(l = pa_property_get(m->core, PA_NATIVE_SERVER_PROPERTY_NAME))) goto fail; + l = pa_strlist_reverse(l); s = pa_strlist_tostring(l); + l = pa_strlist_reverse(l); + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER", s); pa_xfree(s); @@ -192,4 +195,3 @@ void pa__done(pa_module*m) { pa_xfree(u->id); pa_xfree(u); } - From 1dae2e644f1e7c9810befb95315ec22fec7c100c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 20:32:53 +0000 Subject: [PATCH 1388/1514] we don't want to include assert.h anymore git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1986 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-jack-sink.c | 1 - src/modules/module-solaris.c | 1 - src/modules/module-waveout.c | 1 - src/pulsecore/inet_ntop.c | 1 - src/pulsecore/inet_pton.c | 1 - 5 files changed, 5 deletions(-) diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 5019d6564..2cf8a58c5 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index a8a947129..4a5c88e48 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c index ad3645fc7..f8bae02fe 100644 --- a/src/modules/module-waveout.c +++ b/src/modules/module-waveout.c @@ -28,7 +28,6 @@ #include #include -#include #include diff --git a/src/pulsecore/inet_ntop.c b/src/pulsecore/inet_ntop.c index 041bc09bc..4a4f7aac8 100644 --- a/src/pulsecore/inet_ntop.c +++ b/src/pulsecore/inet_ntop.c @@ -27,7 +27,6 @@ #include #include -#include #ifndef HAVE_INET_NTOP diff --git a/src/pulsecore/inet_pton.c b/src/pulsecore/inet_pton.c index 7272e4593..84d0c0eaf 100644 --- a/src/pulsecore/inet_pton.c +++ b/src/pulsecore/inet_pton.c @@ -27,7 +27,6 @@ #include #include -#include #ifndef HAVE_INET_PTON From 625a87276a04c00677f2d54d2ad28991f797eee4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 21:19:05 +0000 Subject: [PATCH 1389/1514] make gcc shut up a bit more git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1987 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 4962112bb..eefcc5847 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -1522,7 +1522,7 @@ char *pa_readlink(const char *p) { return NULL; } - if (n < l-1) { + if ((size_t) n < l-1) { c[l-1] = 0; return c; } From 33c238b7ef4b6c00f46714f14b3c6e1f29af6fde Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 21:23:08 +0000 Subject: [PATCH 1390/1514] ignore network sinks/sources git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1988 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-esound-sink.c | 2 +- src/modules/module-tunnel.c | 2 ++ src/modules/module-zeroconf-publish.c | 21 ++++++++++++++++++--- src/pulse/def.h | 6 ++++-- src/pulsecore/cli-text.c | 6 ++++-- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index b60e15d7f..1c02cdfd6 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -559,7 +559,7 @@ int pa__init(pa_module*m) { u->sink->parent.process_msg = sink_process_msg; u->sink->userdata = u; - u->sink->flags = PA_SINK_LATENCY; + u->sink->flags = PA_SINK_LATENCY|PA_SINK_NETWORK; pa_sink_set_module(u->sink, m); pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 936821ff6..c6b0a2cb5 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -1100,6 +1100,7 @@ int pa__init(pa_module*m) { u->sink->get_mute = sink_get_mute; u->sink->set_volume = sink_set_volume; u->sink->set_mute = sink_set_mute; + u->sink->flags = PA_SINK_NETWORK|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL; pa_sink_set_module(u->sink, m); pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); @@ -1121,6 +1122,7 @@ int pa__init(pa_module*m) { u->source->userdata = u; u->source->set_state = source_set_state; u->source->get_latency = source_get_latency; + u->source->flags = PA_SOURCE_NETWORK|PA_SOURCE_LATENCY; pa_source_set_module(u->source, m); pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index b9b9b22c9..8e0419dfb 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -335,11 +335,24 @@ static void service_free(struct service *s) { pa_xfree(s); } +static pa_bool_t is_network(pa_object *o) { + pa_object_assert_ref(o); + + if (pa_sink_isinstance(o)) + return !!(PA_SINK(o)->flags & PA_SINK_NETWORK); + + if (pa_source_isinstance(o)) + return !!(PA_SOURCE(o)->flags & PA_SOURCE_NETWORK); + + pa_assert_not_reached(); +} + static pa_hook_result_t device_new_or_changed_cb(pa_core *c, pa_object *o, struct userdata *u) { pa_assert(c); pa_object_assert_ref(o); - publish_service(get_service(u, o)); + if (!is_network(o)) + publish_service(get_service(u, o)); return PA_HOOK_OK; } @@ -449,10 +462,12 @@ static int publish_all_services(struct userdata *u) { pa_log_debug("Publishing services in Zeroconf"); for (sink = PA_SINK(pa_idxset_first(u->core->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(u->core->sinks, &idx))) - publish_service(get_service(u, PA_OBJECT(sink))); + if (!is_network(PA_OBJECT(sink))) + publish_service(get_service(u, PA_OBJECT(sink))); for (source = PA_SOURCE(pa_idxset_first(u->core->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(u->core->sources, &idx))) - publish_service(get_service(u, PA_OBJECT(source))); + if (!is_network(PA_OBJECT(source))) + publish_service(get_service(u, PA_OBJECT(source))); if (publish_main_service(u) < 0) goto fail; diff --git a/src/pulse/def.h b/src/pulse/def.h index c28162344..a7c475db8 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -300,14 +300,16 @@ typedef enum pa_seek_mode { typedef enum pa_sink_flags { PA_SINK_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ PA_SINK_LATENCY = 2, /**< Supports latency querying */ - PA_SINK_HARDWARE = 4 /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */ + PA_SINK_HARDWARE = 4, /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */ + PA_SINK_NETWORK = 8 /**< Is a networked sink of some kind. \since 0.9.7 */ } pa_sink_flags_t; /** Special source flags. \since 0.8 */ typedef enum pa_source_flags { PA_SOURCE_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ PA_SOURCE_LATENCY = 2, /**< Supports latency querying */ - PA_SOURCE_HARDWARE = 4 /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */ + PA_SOURCE_HARDWARE = 4, /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */ + PA_SOURCE_NETWORK = 8 /**< Is a networked sink of some kind. \since 0.9.7 */ } pa_source_flags_t; /** A generic free() like callback prototype */ diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index 6683e6973..a77bcc2c0 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -111,7 +111,7 @@ char *pa_sink_list_to_string(pa_core *c) { " %c index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" - "\tflags: %s%s%s\n" + "\tflags: %s%s%s%s\n" "\tstate: %s\n" "\tvolume: <%s>\n" "\tmute: <%i>\n" @@ -128,6 +128,7 @@ char *pa_sink_list_to_string(pa_core *c) { sink->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", sink->flags & PA_SINK_LATENCY ? "LATENCY " : "", sink->flags & PA_SINK_HARDWARE ? "HARDWARE " : "", + sink->flags & PA_SINK_NETWORK ? "NETWORK " : "", state_table[pa_sink_get_state(sink)], pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)), !!pa_sink_get_mute(sink), @@ -172,7 +173,7 @@ char *pa_source_list_to_string(pa_core *c) { " %c index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" - "\tflags: %s%s%s\n" + "\tflags: %s%s%s%s\n" "\tstate: %s\n" "\tvolume: <%s>\n" "\tmute: <%u>\n" @@ -188,6 +189,7 @@ char *pa_source_list_to_string(pa_core *c) { source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "", + source->flags & PA_SOURCE_NETWORK ? "NETWORK " : "", state_table[pa_source_get_state(source)], pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)), !!pa_source_get_mute(source), From 5ef242c5b323a0abaca4cfb44b3a1cba99a4c43d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 22:14:34 +0000 Subject: [PATCH 1391/1514] don't try to send pause request before our stream is properly set up git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1989 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index c6b0a2cb5..7b6b1b823 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -230,6 +230,9 @@ static void stream_cork(struct userdata *u, pa_bool_t cork) { else pa_smoother_resume(u->smoother, pa_rtclock_usec()); + if (!u->pstream) + return; + t = pa_tagstruct_new(NULL, 0); #ifdef TUNNEL_SINK pa_tagstruct_putu32(t, PA_COMMAND_CORK_PLAYBACK_STREAM); @@ -811,7 +814,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct_putu32(reply, PA_INVALID_INDEX); pa_tagstruct_puts(reply, u->sink_name); pa_tagstruct_putu32(reply, u->maxlength); - pa_tagstruct_put_boolean(reply, FALSE); + pa_tagstruct_put_boolean(reply, !PA_SINK_OPENED(pa_sink_get_state(u->sink))); pa_tagstruct_putu32(reply, u->tlength); pa_tagstruct_putu32(reply, u->prebuf); pa_tagstruct_putu32(reply, u->minreq); @@ -827,7 +830,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct_putu32(reply, PA_INVALID_INDEX); pa_tagstruct_puts(reply, u->source_name); pa_tagstruct_putu32(reply, u->maxlength); - pa_tagstruct_put_boolean(reply, 0); + pa_tagstruct_put_boolean(reply, !PA_SOURCE_OPENED(pa_source_get_state(u->source))); pa_tagstruct_putu32(reply, u->fragsize); #endif From e406bbaa62e5e93fd9ec844513f0848eda034a9b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 23:54:46 +0000 Subject: [PATCH 1392/1514] don't announce monitor sources git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1990 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-zeroconf-publish.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 8e0419dfb..818a1b285 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -335,14 +335,14 @@ static void service_free(struct service *s) { pa_xfree(s); } -static pa_bool_t is_network(pa_object *o) { +static pa_bool_t shall_ignore(pa_object *o) { pa_object_assert_ref(o); if (pa_sink_isinstance(o)) return !!(PA_SINK(o)->flags & PA_SINK_NETWORK); if (pa_source_isinstance(o)) - return !!(PA_SOURCE(o)->flags & PA_SOURCE_NETWORK); + return PA_SOURCE(o)->monitor_of || (PA_SOURCE(o)->flags & PA_SOURCE_NETWORK); pa_assert_not_reached(); } @@ -351,7 +351,7 @@ static pa_hook_result_t device_new_or_changed_cb(pa_core *c, pa_object *o, struc pa_assert(c); pa_object_assert_ref(o); - if (!is_network(o)) + if (!shall_ignore(o)) publish_service(get_service(u, o)); return PA_HOOK_OK; @@ -462,11 +462,11 @@ static int publish_all_services(struct userdata *u) { pa_log_debug("Publishing services in Zeroconf"); for (sink = PA_SINK(pa_idxset_first(u->core->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(u->core->sinks, &idx))) - if (!is_network(PA_OBJECT(sink))) + if (!shall_ignore(PA_OBJECT(sink))) publish_service(get_service(u, PA_OBJECT(sink))); for (source = PA_SOURCE(pa_idxset_first(u->core->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(u->core->sources, &idx))) - if (!is_network(PA_OBJECT(source))) + if (!shall_ignore(PA_OBJECT(source))) publish_service(get_service(u, PA_OBJECT(source))); if (publish_main_service(u) < 0) From f1be9312cb97dbbdb0a54568fee9acc8571190c5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 29 Oct 2007 23:55:23 +0000 Subject: [PATCH 1393/1514] keep track of configured tunnels and make sure to unload them when they disappear from zeroconf again git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1991 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-zeroconf-discover.c | 123 ++++++++++++++++++++++--- 1 file changed, 112 insertions(+), 11 deletions(-) diff --git a/src/modules/module-zeroconf-discover.c b/src/modules/module-zeroconf-discover.c index b6f8cf6a4..e49037183 100644 --- a/src/modules/module-zeroconf-discover.c +++ b/src/modules/module-zeroconf-discover.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include @@ -60,18 +60,79 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define SERVICE_TYPE_SINK "_pulse-sink._tcp" #define SERVICE_TYPE_SOURCE "_non-monitor._sub._pulse-source._tcp" - static const char* const valid_modargs[] = { +static const char* const valid_modargs[] = { NULL }; +struct tunnel { + AvahiIfIndex interface; + AvahiProtocol protocol; + char *name, *type, *domain; + uint32_t module_index; +}; + struct userdata { pa_core *core; pa_module *module; AvahiPoll *avahi_poll; AvahiClient *client; AvahiServiceBrowser *source_browser, *sink_browser; + + pa_hashmap *tunnels; }; +static unsigned tunnel_hash(const void *p) { + const struct tunnel *t = p; + + return + (unsigned) t->interface + + (unsigned) t->protocol + + pa_idxset_string_hash_func(t->name) + + pa_idxset_string_hash_func(t->type) + + pa_idxset_string_hash_func(t->domain); +} + +static int tunnel_compare(const void *a, const void *b) { + const struct tunnel *ta = a, *tb = b; + int r; + + if (ta->interface != tb->interface) + return 1; + if (ta->protocol != tb->protocol) + return 1; + if ((r = strcmp(ta->name, tb->name))) + return r; + if ((r = strcmp(ta->type, tb->type))) + return r; + if ((r = strcmp(ta->domain, tb->domain))) + return r; + + return 0; +} + +static struct tunnel *tunnel_new( + AvahiIfIndex interface, AvahiProtocol protocol, + const char *name, const char *type, const char *domain) { + + struct tunnel *t; + t = pa_xnew(struct tunnel, 1); + t->interface = interface; + t->protocol = protocol; + t->name = pa_xstrdup(name); + t->type = pa_xstrdup(type); + t->domain = pa_xstrdup(domain); + t->module_index = PA_IDXSET_INVALID; + return t; +} + +static void tunnel_free(struct tunnel *t) { + pa_assert(t); + pa_xfree(t->name); + pa_xfree(t->type); + pa_xfree(t->domain); + pa_xfree(t); +} + static void resolver_cb( AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, @@ -83,9 +144,12 @@ static void resolver_cb( void *userdata) { struct userdata *u = userdata; + struct tunnel *tnl; pa_assert(u); + tnl = tunnel_new(interface, protocol, name, type, domain); + if (event != AVAHI_RESOLVER_FOUND) pa_log("Resolving of '%s' failed: %s", name, avahi_strerror(avahi_client_errno(u->client))); else { @@ -96,6 +160,7 @@ static void resolver_cb( pa_channel_map cm; AvahiStringList *l; pa_bool_t channel_map_set = FALSE; + pa_module *m; ss = u->core->default_sample_spec; pa_channel_map_init_auto(&cm, ss.channels, PA_CHANNEL_MAP_DEFAULT); @@ -169,7 +234,12 @@ static void resolver_cb( pa_channel_map_snprint(cmt, sizeof(cmt), &cm)); pa_log_debug("Loading module-tunnel-%s with arguments '%s'", module_name, args); - pa_module_load(u->core, module_name, args); + + if ((m = pa_module_load(u->core, module_name, args))) { + tnl->module_index = m->index; + pa_hashmap_put(u->tunnels, tnl, tnl); + tnl = NULL; + } pa_xfree(module_name); pa_xfree(dname); @@ -180,6 +250,9 @@ static void resolver_cb( finish: avahi_service_resolver_free(r); + + if (tnl) + tunnel_free(tnl); } static void browser_cb( @@ -191,21 +264,36 @@ static void browser_cb( void *userdata) { struct userdata *u = userdata; + struct tunnel *t; pa_assert(u); - if (event != AVAHI_BROWSER_NEW) - return; - if (flags & AVAHI_LOOKUP_RESULT_LOCAL) return; - if (!(avahi_service_resolver_new(u->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolver_cb, u))) - pa_log("avahi_service_resolver_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); + t = tunnel_new(interface, protocol, name, type, domain); - /* We ignore the returned resolver object here, since the we don't - * need to attach any special data to it, and we can still destory - * it from the callback */ + if (event == AVAHI_BROWSER_NEW) { + + if (!pa_hashmap_get(u->tunnels, t)) + if (!(avahi_service_resolver_new(u->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolver_cb, u))) + pa_log("avahi_service_resolver_new() failed: %s", avahi_strerror(avahi_client_errno(u->client))); + + /* We ignore the returned resolver object here, since the we don't + * need to attach any special data to it, and we can still destory + * it from the callback */ + + } else if (event == AVAHI_BROWSER_REMOVE) { + struct tunnel *t2; + + if ((t2 = pa_hashmap_get(u->tunnels, t))) { + pa_module_unload_by_index(u->core, t2->module_index); + pa_hashmap_remove(u->tunnels, t2); + tunnel_free(t2); + } + } + + tunnel_free(t); } static void client_callback(AvahiClient *c, AvahiClientState state, void *userdata) { @@ -301,6 +389,8 @@ int pa__init(pa_module*m) { u->module = m; u->sink_browser = u->source_browser = NULL; + u->tunnels = pa_hashmap_new(tunnel_hash, tunnel_compare); + u->avahi_poll = pa_avahi_poll_new(m->core->mainloop); if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { @@ -334,5 +424,16 @@ void pa__done(pa_module*m) { if (u->avahi_poll) pa_avahi_poll_free(u->avahi_poll); + if (u->tunnels) { + struct tunnel *t; + + while ((t = pa_hashmap_steal_first(u->tunnels))) { + pa_module_unload_by_index(u->core, t->module_index); + tunnel_free(t); + } + + pa_hashmap_free(u->tunnels, NULL, NULL); + } + pa_xfree(u); } From 2d265a91ccd84e896f2bca9764147630d0d7d003 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 00:17:21 +0000 Subject: [PATCH 1394/1514] deal properly with signals interrupting us when we wait for data from gconf helper git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1992 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index 1c8866de2..c2ea7b27f 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -225,8 +225,11 @@ static int handle_event(struct userdata *u) { int ret = 0; do { - if ((opcode = read_byte(u)) < 0) + if ((opcode = read_byte(u)) < 0){ + if (errno == EINTR || errno == EAGAIN) + break; goto fail; + } switch (opcode) { case '!': @@ -509,4 +512,3 @@ void pa__done(pa_module*m) { pa_xfree(u); } - From 0991a1ba2d19eeeafe595fdf433a31a47ef3fcd2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 00:32:00 +0000 Subject: [PATCH 1395/1514] remove libltdl from SVN git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1993 fefdeb5f-60dc-0310-8127-8f9354f1896f --- libltdl/COPYING.LIB | 515 - libltdl/Makefile.am | 32 - libltdl/Makefile.in | 656 -- libltdl/README | 10 - libltdl/acinclude.m4 | 7025 ------------ libltdl/aclocal.m4 | 875 -- libltdl/config-h.in | 195 - libltdl/config.guess | 1516 --- libltdl/config.h | 196 - libltdl/config.sub | 1622 --- libltdl/configure | 23853 ---------------------------------------- libltdl/configure.ac | 79 - libltdl/install-sh | 519 - libltdl/ltdl.c | 4530 -------- libltdl/ltdl.h | 367 - libltdl/ltmain.sh | 6938 ------------ libltdl/missing | 360 - libltdl/mkinstalldirs | 161 - libltdl/stamp-h1 | 1 - 19 files changed, 49450 deletions(-) delete mode 100644 libltdl/COPYING.LIB delete mode 100644 libltdl/Makefile.am delete mode 100644 libltdl/Makefile.in delete mode 100644 libltdl/README delete mode 100644 libltdl/acinclude.m4 delete mode 100644 libltdl/aclocal.m4 delete mode 100644 libltdl/config-h.in delete mode 100755 libltdl/config.guess delete mode 100644 libltdl/config.h delete mode 100755 libltdl/config.sub delete mode 100755 libltdl/configure delete mode 100644 libltdl/configure.ac delete mode 100755 libltdl/install-sh delete mode 100644 libltdl/ltdl.c delete mode 100644 libltdl/ltdl.h delete mode 100644 libltdl/ltmain.sh delete mode 100755 libltdl/missing delete mode 100755 libltdl/mkinstalldirs delete mode 100644 libltdl/stamp-h1 diff --git a/libltdl/COPYING.LIB b/libltdl/COPYING.LIB deleted file mode 100644 index ba2be481c..000000000 --- a/libltdl/COPYING.LIB +++ /dev/null @@ -1,515 +0,0 @@ - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations -below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. -^L - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it -becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. -^L - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control -compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. -^L - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. -^L - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. -^L - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. -^L - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply, and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License -may add an explicit geographical distribution limitation excluding those -countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. -^L - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS -^L - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms -of the ordinary General Public License). - - To apply these terms, attach the following notices to the library. -It is safest to attach them to the start of each source file to most -effectively convey the exclusion of warranty; and each file should -have at least the "copyright" line and a pointer to where the full -notice is found. - - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper -mail. - -You should also get your employer (if you work as a programmer) or -your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James -Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/libltdl/Makefile.am b/libltdl/Makefile.am deleted file mode 100644 index 2a1e70198..000000000 --- a/libltdl/Makefile.am +++ /dev/null @@ -1,32 +0,0 @@ -## Process this file with automake to produce Makefile.in - -AUTOMAKE_OPTIONS = no-dependencies foreign - -if INSTALL_LTDL -include_HEADERS = ltdl.h -lib_LTLIBRARIES = libltdl.la -else -noinst_HEADERS = ltdl.h -endif - -if CONVENIENCE_LTDL -noinst_LTLIBRARIES = libltdlc.la -endif - -## Make sure these will be cleaned even when they're not built by -## default. -CLEANFILES = libltdl.la libltdlc.la - -libltdl_la_SOURCES = ltdl.c -libltdl_la_LDFLAGS = -no-undefined -version-info 4:5:1 -libltdl_la_LIBADD = $(LIBADD_DL) - -libltdlc_la_SOURCES = ltdl.c -libltdlc_la_LIBADD = $(LIBADD_DL) - -## Because we do not have automatic dependency tracking: -ltdl.lo: ltdl.h config.h - -$(libltdl_la_OBJECTS) $(libltdlc_la_OBJECTS): libtool -libtool: $(LIBTOOL_DEPS) - $(SHELL) ./config.status --recheck diff --git a/libltdl/Makefile.in b/libltdl/Makefile.in deleted file mode 100644 index 4319156ec..000000000 --- a/libltdl/Makefile.in +++ /dev/null @@ -1,656 +0,0 @@ -# Makefile.in generated by automake 1.10 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - - -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = . -DIST_COMMON = README $(am__configure_deps) $(am__include_HEADERS_DIST) \ - $(am__noinst_HEADERS_DIST) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/config-h.in \ - $(top_srcdir)/configure COPYING.LIB config.guess config.sub \ - install-sh ltmain.sh missing mkinstalldirs -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ - configure.lineno config.status.lineno -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" -libLTLIBRARIES_INSTALL = $(INSTALL) -LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -libltdl_la_DEPENDENCIES = $(am__DEPENDENCIES_1) -am_libltdl_la_OBJECTS = ltdl.lo -libltdl_la_OBJECTS = $(am_libltdl_la_OBJECTS) -libltdl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libltdl_la_LDFLAGS) $(LDFLAGS) -o $@ -@INSTALL_LTDL_TRUE@am_libltdl_la_rpath = -rpath $(libdir) -libltdlc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) -am_libltdlc_la_OBJECTS = ltdl.lo -libltdlc_la_OBJECTS = $(am_libltdlc_la_OBJECTS) -@CONVENIENCE_LTDL_TRUE@am_libltdlc_la_rpath = -DEFAULT_INCLUDES = -I.@am__isrc@ -depcomp = -am__depfiles_maybe = -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ -SOURCES = $(libltdl_la_SOURCES) $(libltdlc_la_SOURCES) -DIST_SOURCES = $(libltdl_la_SOURCES) $(libltdlc_la_SOURCES) -am__include_HEADERS_DIST = ltdl.h -includeHEADERS_INSTALL = $(INSTALL_HEADER) -am__noinst_HEADERS_DIST = ltdl.h -HEADERS = $(include_HEADERS) $(noinst_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -distdir = $(PACKAGE)-$(VERSION) -top_distdir = $(distdir) -am__remove_distdir = \ - { test ! -d $(distdir) \ - || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ - && rm -fr $(distdir); }; } -DIST_ARCHIVES = $(distdir).tar.gz -GZIP_ENV = --best -distuninstallcheck_listfiles = find . -type f -print -distcleancheck_listfiles = find . -type f -print -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AR = @AR@ -AS = @AS@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -ECHO = @ECHO@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBADD_DL = @LIBADD_DL@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIBTOOL_DEPS = @LIBTOOL_DEPS@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = no-dependencies foreign -@INSTALL_LTDL_TRUE@include_HEADERS = ltdl.h -@INSTALL_LTDL_TRUE@lib_LTLIBRARIES = libltdl.la -@INSTALL_LTDL_FALSE@noinst_HEADERS = ltdl.h -@CONVENIENCE_LTDL_TRUE@noinst_LTLIBRARIES = libltdlc.la -CLEANFILES = libltdl.la libltdlc.la -libltdl_la_SOURCES = ltdl.c -libltdl_la_LDFLAGS = -no-undefined -version-info 4:5:1 -libltdl_la_LIBADD = $(LIBADD_DL) -libltdlc_la_SOURCES = ltdl.c -libltdlc_la_LIBADD = $(LIBADD_DL) -all: config.h - $(MAKE) $(AM_MAKEFLAGS) all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -am--refresh: - @: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ - cd $(srcdir) && $(AUTOMAKE) --foreign \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - echo ' $(SHELL) ./config.status'; \ - $(SHELL) ./config.status;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - $(SHELL) ./config.status --recheck - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(srcdir) && $(AUTOCONF) -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) - -config.h: stamp-h1 - @if test ! -f $@; then \ - rm -f stamp-h1; \ - $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ - else :; fi - -stamp-h1: $(srcdir)/config-h.in $(top_builddir)/config.status - @rm -f stamp-h1 - cd $(top_builddir) && $(SHELL) ./config.status config.h -$(srcdir)/config-h.in: $(am__configure_deps) - cd $(top_srcdir) && $(AUTOHEADER) - rm -f stamp-h1 - touch $@ - -distclean-hdr: - -rm -f config.h stamp-h1 -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - if test -f $$p; then \ - f=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ - else :; fi; \ - done - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - p=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ - $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -libltdl.la: $(libltdl_la_OBJECTS) $(libltdl_la_DEPENDENCIES) - $(libltdl_la_LINK) $(am_libltdl_la_rpath) $(libltdl_la_OBJECTS) $(libltdl_la_LIBADD) $(LIBS) -libltdlc.la: $(libltdlc_la_OBJECTS) $(libltdlc_la_DEPENDENCIES) - $(LINK) $(am_libltdlc_la_rpath) $(libltdlc_la_OBJECTS) $(libltdlc_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -.c.o: - $(COMPILE) -c $< - -.c.obj: - $(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: - $(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool -install-includeHEADERS: $(include_HEADERS) - @$(NORMAL_INSTALL) - test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" - @list='$(include_HEADERS)'; for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - f=$(am__strip_dir) \ - echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ - $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ - done - -uninstall-includeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(include_HEADERS)'; for p in $$list; do \ - f=$(am__strip_dir) \ - echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ - rm -f "$(DESTDIR)$(includedir)/$$f"; \ - done - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) config-h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) config-h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) config-h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) config-h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - $(am__remove_distdir) - test -d $(distdir) || mkdir $(distdir) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done - -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ - ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ - || chmod -R a+r $(distdir) -dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) - -dist-bzip2: distdir - tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 - $(am__remove_distdir) - -dist-tarZ: distdir - tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z - $(am__remove_distdir) - -dist-shar: distdir - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz - $(am__remove_distdir) - -dist-zip: distdir - -rm -f $(distdir).zip - zip -rq $(distdir).zip $(distdir) - $(am__remove_distdir) - -dist dist-all: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) - -# This target untars the dist file and tries a VPATH configuration. Then -# it guarantees that the distribution is self-contained by making another -# tarfile. -distcheck: dist - case '$(DIST_ARCHIVES)' in \ - *.tar.gz*) \ - GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ - *.tar.bz2*) \ - bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ - *.tar.Z*) \ - uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ - *.shar.gz*) \ - GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ - *.zip*) \ - unzip $(distdir).zip ;;\ - esac - chmod -R a-w $(distdir); chmod a+w $(distdir) - mkdir $(distdir)/_build - mkdir $(distdir)/_inst - chmod a-w $(distdir) - dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ - && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ - && cd $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ - $(DISTCHECK_CONFIGURE_FLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) dvi \ - && $(MAKE) $(AM_MAKEFLAGS) check \ - && $(MAKE) $(AM_MAKEFLAGS) install \ - && $(MAKE) $(AM_MAKEFLAGS) installcheck \ - && $(MAKE) $(AM_MAKEFLAGS) uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ - distuninstallcheck \ - && chmod -R a-w "$$dc_install_base" \ - && ({ \ - (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ - distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ - } || { rm -rf "$$dc_destdir"; exit 1; }) \ - && rm -rf "$$dc_destdir" \ - && $(MAKE) $(AM_MAKEFLAGS) dist \ - && rm -rf $(DIST_ARCHIVES) \ - && $(MAKE) $(AM_MAKEFLAGS) distcleancheck - $(am__remove_distdir) - @(echo "$(distdir) archives ready for distribution: "; \ - list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ - sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' -distuninstallcheck: - @cd $(distuninstallcheck_dir) \ - && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ - || { echo "ERROR: files left after uninstall:" ; \ - if test -n "$(DESTDIR)"; then \ - echo " (check DESTDIR support)"; \ - fi ; \ - $(distuninstallcheck_listfiles) ; \ - exit 1; } >&2 -distcleancheck: distclean - @if test '$(srcdir)' = . ; then \ - echo "ERROR: distcleancheck can only run from a VPATH build" ; \ - exit 1 ; \ - fi - @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ - || { echo "ERROR: files left in build directory after distclean:" ; \ - $(distcleancheck_listfiles) ; \ - exit 1; } >&2 -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h -installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ - clean-noinstLTLIBRARIES mostlyclean-am - -distclean: distclean-am - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-hdr distclean-libtool distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: install-includeHEADERS - -install-dvi: install-dvi-am - -install-exec-am: install-libLTLIBRARIES - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf $(top_srcdir)/autom4te.cache - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \ - clean-generic clean-libLTLIBRARIES clean-libtool \ - clean-noinstLTLIBRARIES ctags dist dist-all dist-bzip2 \ - dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \ - distclean-compile distclean-generic distclean-hdr \ - distclean-libtool distclean-tags distcleancheck distdir \ - distuninstallcheck dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-includeHEADERS install-info \ - install-info-am install-libLTLIBRARIES install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-includeHEADERS \ - uninstall-libLTLIBRARIES - - -ltdl.lo: ltdl.h config.h - -$(libltdl_la_OBJECTS) $(libltdlc_la_OBJECTS): libtool -libtool: $(LIBTOOL_DEPS) - $(SHELL) ./config.status --recheck -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/libltdl/README b/libltdl/README deleted file mode 100644 index da0a449ca..000000000 --- a/libltdl/README +++ /dev/null @@ -1,10 +0,0 @@ -This is GNU libltdl, a system independent dlopen wrapper for GNU libtool. - -It supports the following dlopen interfaces: -* dlopen (Solaris, Linux and various BSD flavors) -* shl_load (HP-UX) -* LoadLibrary (Win16 and Win32) -* load_add_on (BeOS) -* GNU DLD (emulates dynamic linking for static libraries) -* dyld (darwin/Mac OS X) -* libtool's dlpreopen diff --git a/libltdl/acinclude.m4 b/libltdl/acinclude.m4 deleted file mode 100644 index 79d94868f..000000000 --- a/libltdl/acinclude.m4 +++ /dev/null @@ -1,7025 +0,0 @@ -# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 -## Free Software Foundation, Inc. -## Originally by Gordon Matzigkeit , 1996 -## -## This file is free software; the Free Software Foundation gives -## unlimited permission to copy and/or distribute it, with or without -## modifications, as long as this notice is preserved. - -# serial 51 Debian 1.5.24-1 AC_PROG_LIBTOOL - - -# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) -# ----------------------------------------------------------- -# If this macro is not defined by Autoconf, define it here. -m4_ifdef([AC_PROVIDE_IFELSE], - [], - [m4_define([AC_PROVIDE_IFELSE], - [m4_ifdef([AC_PROVIDE_$1], - [$2], [$3])])]) - - -# AC_PROG_LIBTOOL -# --------------- -AC_DEFUN([AC_PROG_LIBTOOL], -[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl -dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX -dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. - AC_PROVIDE_IFELSE([AC_PROG_CXX], - [AC_LIBTOOL_CXX], - [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX - ])]) -dnl And a similar setup for Fortran 77 support - AC_PROVIDE_IFELSE([AC_PROG_F77], - [AC_LIBTOOL_F77], - [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 -])]) - -dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. -dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run -dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. - AC_PROVIDE_IFELSE([AC_PROG_GCJ], - [AC_LIBTOOL_GCJ], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], - [AC_LIBTOOL_GCJ], - [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], - [AC_LIBTOOL_GCJ], - [ifdef([AC_PROG_GCJ], - [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) - ifdef([A][M_PROG_GCJ], - [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) - ifdef([LT_AC_PROG_GCJ], - [define([LT_AC_PROG_GCJ], - defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) -])])# AC_PROG_LIBTOOL - - -# _AC_PROG_LIBTOOL -# ---------------- -AC_DEFUN([_AC_PROG_LIBTOOL], -[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl -AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl -AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl -AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' -AC_SUBST(LIBTOOL)dnl - -# Prevent multiple expansion -define([AC_PROG_LIBTOOL], []) -])# _AC_PROG_LIBTOOL - - -# AC_LIBTOOL_SETUP -# ---------------- -AC_DEFUN([AC_LIBTOOL_SETUP], -[AC_PREREQ(2.50)dnl -AC_REQUIRE([AC_ENABLE_SHARED])dnl -AC_REQUIRE([AC_ENABLE_STATIC])dnl -AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_LD])dnl -AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl -AC_REQUIRE([AC_PROG_NM])dnl - -AC_REQUIRE([AC_PROG_LN_S])dnl -AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl -# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! -AC_REQUIRE([AC_OBJEXT])dnl -AC_REQUIRE([AC_EXEEXT])dnl -dnl - -AC_LIBTOOL_SYS_MAX_CMD_LEN -AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE -AC_LIBTOOL_OBJDIR - -AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl -_LT_AC_PROG_ECHO_BACKSLASH - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e 1s/^X//' -[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] - -# Same as above, but do not quote variable references. -[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -# Constants: -rm="rm -f" - -# Global variables: -default_ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a -ltmain="$ac_aux_dir/ltmain.sh" -ofile="$default_ofile" -with_gnu_ld="$lt_cv_prog_gnu_ld" - -AC_CHECK_TOOL(AR, ar, false) -AC_CHECK_TOOL(RANLIB, ranlib, :) -AC_CHECK_TOOL(STRIP, strip, :) - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru -test -z "$AS" && AS=as -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$DLLTOOL" && DLLTOOL=dlltool -test -z "$LD" && LD=ld -test -z "$LN_S" && LN_S="ln -s" -test -z "$MAGIC_CMD" && MAGIC_CMD=file -test -z "$NM" && NM=nm -test -z "$SED" && SED=sed -test -z "$OBJDUMP" && OBJDUMP=objdump -test -z "$RANLIB" && RANLIB=: -test -z "$STRIP" && STRIP=: -test -z "$ac_objext" && ac_objext=o - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" -fi - -_LT_CC_BASENAME([$compiler]) - -# Only perform the check for file, if the check method requires it -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - AC_PATH_MAGIC - fi - ;; -esac - -AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) -AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], -enable_win32_dll=yes, enable_win32_dll=no) - -AC_ARG_ENABLE([libtool-lock], - [AC_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -AC_ARG_WITH([pic], - [AC_HELP_STRING([--with-pic], - [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], - [pic_mode="$withval"], - [pic_mode=default]) -test -z "$pic_mode" && pic_mode=default - -# Use C for the default configuration in the libtool script -tagname= -AC_LIBTOOL_LANG_C_CONFIG -_LT_AC_TAGCONFIG -])# AC_LIBTOOL_SETUP - - -# _LT_AC_SYS_COMPILER -# ------------------- -AC_DEFUN([_LT_AC_SYS_COMPILER], -[AC_REQUIRE([AC_PROG_CC])dnl - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC -])# _LT_AC_SYS_COMPILER - - -# _LT_CC_BASENAME(CC) -# ------------------- -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -AC_DEFUN([_LT_CC_BASENAME], -[for cc_temp in $1""; do - case $cc_temp in - compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; - distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` -]) - - -# _LT_COMPILER_BOILERPLATE -# ------------------------ -# Check for compiler boilerplate output or warnings with -# the simple compiler test code. -AC_DEFUN([_LT_COMPILER_BOILERPLATE], -[AC_REQUIRE([LT_AC_PROG_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* -])# _LT_COMPILER_BOILERPLATE - - -# _LT_LINKER_BOILERPLATE -# ---------------------- -# Check for linker boilerplate output or warnings with -# the simple link test code. -AC_DEFUN([_LT_LINKER_BOILERPLATE], -[AC_REQUIRE([LT_AC_PROG_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* -])# _LT_LINKER_BOILERPLATE - - -# _LT_AC_SYS_LIBPATH_AIX -# ---------------------- -# Links a minimal program and checks the executable -# for the system default hardcoded library path. In most cases, -# this is /usr/lib:/lib, but when the MPI compilers are used -# the location of the communication and MPI libs are included too. -# If we don't find anything, use the default library path according -# to the aix ld manual. -AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], -[AC_REQUIRE([LT_AC_PROG_SED])dnl -AC_LINK_IFELSE(AC_LANG_PROGRAM,[ -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi],[]) -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi -])# _LT_AC_SYS_LIBPATH_AIX - - -# _LT_AC_SHELL_INIT(ARG) -# ---------------------- -AC_DEFUN([_LT_AC_SHELL_INIT], -[ifdef([AC_DIVERSION_NOTICE], - [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], - [AC_DIVERT_PUSH(NOTICE)]) -$1 -AC_DIVERT_POP -])# _LT_AC_SHELL_INIT - - -# _LT_AC_PROG_ECHO_BACKSLASH -# -------------------------- -# Add some code to the start of the generated configure script which -# will find an echo command which doesn't interpret backslashes. -AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], -[_LT_AC_SHELL_INIT([ -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` - ;; -esac - -echo=${ECHO-echo} -if test "X[$]1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X[$]1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then - # Yippee, $echo works! - : -else - # Restart under the correct shell. - exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} -fi - -if test "X[$]1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null 2>&1 && unset CDPATH - -if test -z "$ECHO"; then -if test "X${echo_test_string+set}" != Xset; then -# find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if (echo_test_string=`eval $cmd`) 2>/dev/null && - echo_test_string=`eval $cmd` && - (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null - then - break - fi - done -fi - -if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : -else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$echo" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - echo='print -r' - elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} - else - # Try using printf. - echo='printf %s\n' - if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - echo="$CONFIG_SHELL [$]0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$CONFIG_SHELL [$]0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do - if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "[$]0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} - else - # Oops. We lost completely, so just stick with echo. - echo=echo - fi - fi - fi - fi -fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -ECHO=$echo -if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then - ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" -fi - -AC_SUBST(ECHO) -])])# _LT_AC_PROG_ECHO_BACKSLASH - - -# _LT_AC_LOCK -# ----------- -AC_DEFUN([_LT_AC_LOCK], -[AC_ARG_ENABLE([libtool-lock], - [AC_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '[#]line __oline__ "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ -s390*-*linux*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_i386_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_x86_64_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, - [AC_LANG_PUSH(C) - AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) - AC_LANG_POP]) - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; -sparc*-*solaris*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) LD="${LD-ld} -m elf64_sparc" ;; - *) LD="${LD-ld} -64" ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], -[*-*-cygwin* | *-*-mingw* | *-*-pw32*) - AC_CHECK_TOOL(DLLTOOL, dlltool, false) - AC_CHECK_TOOL(AS, as, false) - AC_CHECK_TOOL(OBJDUMP, objdump, false) - ;; - ]) -esac - -need_locks="$enable_libtool_lock" - -])# _LT_AC_LOCK - - -# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------------------- -# Check whether the given compiler option works -AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], -[AC_REQUIRE([LT_AC_PROG_SED]) -AC_CACHE_CHECK([$1], [$2], - [$2=no - ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - fi - $rm conftest* -]) - -if test x"[$]$2" = xyes; then - ifelse([$5], , :, [$5]) -else - ifelse([$6], , :, [$6]) -fi -])# AC_LIBTOOL_COMPILER_OPTION - - -# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [ACTION-SUCCESS], [ACTION-FAILURE]) -# ------------------------------------------------------------ -# Check whether the given compiler option works -AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], -[AC_REQUIRE([LT_AC_PROG_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $3" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&AS_MESSAGE_LOG_FD - $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - else - $2=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" -]) - -if test x"[$]$2" = xyes; then - ifelse([$4], , :, [$4]) -else - ifelse([$5], , :, [$5]) -fi -])# AC_LIBTOOL_LINKER_OPTION - - -# AC_LIBTOOL_SYS_MAX_CMD_LEN -# -------------------------- -AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], -[# find the maximum length of command line arguments -AC_MSG_CHECKING([the maximum length of command line arguments]) -AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl - i=0 - teststring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ - = "XX$teststring") >/dev/null 2>&1 && - new_result=`expr "X$teststring" : ".*" 2>&1` && - lt_cv_sys_max_cmd_len=$new_result && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - teststring= - # Add a significant safety factor because C++ compilers can tack on massive - # amounts of additional arguments before passing them to the linker. - # It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi - ;; - esac -]) -if test -n $lt_cv_sys_max_cmd_len ; then - AC_MSG_RESULT($lt_cv_sys_max_cmd_len) -else - AC_MSG_RESULT(none) -fi -])# AC_LIBTOOL_SYS_MAX_CMD_LEN - - -# _LT_AC_CHECK_DLFCN -# ------------------ -AC_DEFUN([_LT_AC_CHECK_DLFCN], -[AC_CHECK_HEADERS(dlfcn.h)dnl -])# _LT_AC_CHECK_DLFCN - - -# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, -# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) -# --------------------------------------------------------------------- -AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], -[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl -if test "$cross_compiling" = yes; then : - [$4] -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - else - puts (dlerror ()); - - exit (status); -}] -EOF - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) $1 ;; - x$lt_dlneed_uscore) $2 ;; - x$lt_dlunknown|x*) $3 ;; - esac - else : - # compilation failed - $3 - fi -fi -rm -fr conftest* -])# _LT_AC_TRY_DLOPEN_SELF - - -# AC_LIBTOOL_DLOPEN_SELF -# ---------------------- -AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], -[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ]) - ;; - - *) - AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen="shl_load"], - [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], - [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen="dlopen"], - [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], - [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], - [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) - ]) - ]) - ]) - ]) - ]) - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - AC_CACHE_CHECK([whether a program can dlopen itself], - lt_cv_dlopen_self, [dnl - _LT_AC_TRY_DLOPEN_SELF( - lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, - lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) - ]) - - if test "x$lt_cv_dlopen_self" = xyes; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - AC_CACHE_CHECK([whether a statically linked program can dlopen itself], - lt_cv_dlopen_self_static, [dnl - _LT_AC_TRY_DLOPEN_SELF( - lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, - lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) - ]) - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi -])# AC_LIBTOOL_DLOPEN_SELF - - -# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) -# --------------------------------- -# Check to see if options -c and -o are simultaneously supported by compiler -AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], -[AC_REQUIRE([LT_AC_PROG_SED])dnl -AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl -AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], - [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], - [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - fi - fi - chmod u+w . 2>&AS_MESSAGE_LOG_FD - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* -]) -])# AC_LIBTOOL_PROG_CC_C_O - - -# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) -# ----------------------------------------- -# Check to see if we can do hard links to lock some files if needed -AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], -[AC_REQUIRE([_LT_AC_LOCK])dnl - -hard_links="nottested" -if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - AC_MSG_CHECKING([if we can lock with hard links]) - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - AC_MSG_RESULT([$hard_links]) - if test "$hard_links" = no; then - AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) - need_locks=warn - fi -else - need_locks=no -fi -])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS - - -# AC_LIBTOOL_OBJDIR -# ----------------- -AC_DEFUN([AC_LIBTOOL_OBJDIR], -[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], -[rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null]) -objdir=$lt_cv_objdir -])# AC_LIBTOOL_OBJDIR - - -# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) -# ---------------------------------------------- -# Check hardcoding attributes. -AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], -[AC_MSG_CHECKING([how to hardcode library paths into programs]) -_LT_AC_TAGVAR(hardcode_action, $1)= -if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ - test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ - test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then - - # We can hardcode non-existant directories. - if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && - test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then - # Linking always hardcodes the temporary library directory. - _LT_AC_TAGVAR(hardcode_action, $1)=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - _LT_AC_TAGVAR(hardcode_action, $1)=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - _LT_AC_TAGVAR(hardcode_action, $1)=unsupported -fi -AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) - -if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi -])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH - - -# AC_LIBTOOL_SYS_LIB_STRIP -# ------------------------ -AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], -[striplib= -old_striplib= -AC_MSG_CHECKING([whether stripping libraries is possible]) -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - AC_MSG_RESULT([yes]) -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - old_striplib="$STRIP -S" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) -fi - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac -fi -])# AC_LIBTOOL_SYS_LIB_STRIP - - -# AC_LIBTOOL_SYS_DYNAMIC_LINKER -# ----------------------------- -# PORTME Fill in your ld.so characteristics -AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], -[AC_REQUIRE([LT_AC_PROG_SED])dnl -AC_MSG_CHECKING([dynamic linker characteristics]) -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -m4_if($1,[],[ -if test "$GCC" = yes; then - case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` - else - lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. - lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else - test -d "$lt_sys_path" && \ - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" - fi - done - lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; - for (lt_i = NF; lt_i > 0; lt_i--) { - if ($lt_i != "" && $lt_i != ".") { - if ($lt_i == "..") { - lt_count++; - } else { - if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; - } else { - lt_count--; - } - } - } - } - if (lt_foo != "") { lt_freq[[lt_foo]]++; } - if (lt_freq[[lt_foo]] == 1) { print lt_foo; } -}'` - sys_lib_search_path_spec=`echo $lt_search_path_spec` -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi]) -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[[01]] | aix4.[[01]].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[[45]]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - m4_if([$1], [],[ - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[[123]]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[[01]]* | freebsdelf3.[[01]]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ - freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix[[3-9]]*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[[89]] | openbsd2.[[89]].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - shlibpath_overrides_runpath=no - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - shlibpath_overrides_runpath=yes - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -AC_MSG_RESULT([$dynamic_linker]) -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi -])# AC_LIBTOOL_SYS_DYNAMIC_LINKER - - -# _LT_AC_TAGCONFIG -# ---------------- -AC_DEFUN([_LT_AC_TAGCONFIG], -[AC_REQUIRE([LT_AC_PROG_SED])dnl -AC_ARG_WITH([tags], - [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], - [include additional configurations @<:@automatic@:>@])], - [tagnames="$withval"]) - -if test -f "$ltmain" && test -n "$tagnames"; then - if test ! -f "${ofile}"; then - AC_MSG_WARN([output file `$ofile' does not exist]) - fi - - if test -z "$LTCC"; then - eval "`$SHELL ${ofile} --config | grep '^LTCC='`" - if test -z "$LTCC"; then - AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) - else - AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) - fi - fi - if test -z "$LTCFLAGS"; then - eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" - fi - - # Extract list of available tagged configurations in $ofile. - # Note that this assumes the entire list is on one line. - available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` - - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for tagname in $tagnames; do - IFS="$lt_save_ifs" - # Check whether tagname contains only valid characters - case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in - "") ;; - *) AC_MSG_ERROR([invalid tag name: $tagname]) - ;; - esac - - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null - then - AC_MSG_ERROR([tag name \"$tagname\" already exists]) - fi - - # Update the list of available tags. - if test -n "$tagname"; then - echo appending configuration tag \"$tagname\" to $ofile - - case $tagname in - CXX) - if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - AC_LIBTOOL_LANG_CXX_CONFIG - else - tagname="" - fi - ;; - - F77) - if test -n "$F77" && test "X$F77" != "Xno"; then - AC_LIBTOOL_LANG_F77_CONFIG - else - tagname="" - fi - ;; - - GCJ) - if test -n "$GCJ" && test "X$GCJ" != "Xno"; then - AC_LIBTOOL_LANG_GCJ_CONFIG - else - tagname="" - fi - ;; - - RC) - AC_LIBTOOL_LANG_RC_CONFIG - ;; - - *) - AC_MSG_ERROR([Unsupported tag name: $tagname]) - ;; - esac - - # Append the new tag name to the list of available tags. - if test -n "$tagname" ; then - available_tags="$available_tags $tagname" - fi - fi - done - IFS="$lt_save_ifs" - - # Now substitute the updated list of available tags. - if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then - mv "${ofile}T" "$ofile" - chmod +x "$ofile" - else - rm -f "${ofile}T" - AC_MSG_ERROR([unable to update list of available tagged configurations.]) - fi -fi -])# _LT_AC_TAGCONFIG - - -# AC_LIBTOOL_DLOPEN -# ----------------- -# enable checks for dlopen support -AC_DEFUN([AC_LIBTOOL_DLOPEN], - [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) -])# AC_LIBTOOL_DLOPEN - - -# AC_LIBTOOL_WIN32_DLL -# -------------------- -# declare package support for building win32 DLLs -AC_DEFUN([AC_LIBTOOL_WIN32_DLL], -[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) -])# AC_LIBTOOL_WIN32_DLL - - -# AC_ENABLE_SHARED([DEFAULT]) -# --------------------------- -# implement the --enable-shared flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -AC_DEFUN([AC_ENABLE_SHARED], -[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE([shared], - [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], - [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_shared=]AC_ENABLE_SHARED_DEFAULT) -])# AC_ENABLE_SHARED - - -# AC_DISABLE_SHARED -# ----------------- -# set the default shared flag to --disable-shared -AC_DEFUN([AC_DISABLE_SHARED], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_SHARED(no) -])# AC_DISABLE_SHARED - - -# AC_ENABLE_STATIC([DEFAULT]) -# --------------------------- -# implement the --enable-static flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -AC_DEFUN([AC_ENABLE_STATIC], -[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE([static], - [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], - [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_static=]AC_ENABLE_STATIC_DEFAULT) -])# AC_ENABLE_STATIC - - -# AC_DISABLE_STATIC -# ----------------- -# set the default static flag to --disable-static -AC_DEFUN([AC_DISABLE_STATIC], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_STATIC(no) -])# AC_DISABLE_STATIC - - -# AC_ENABLE_FAST_INSTALL([DEFAULT]) -# --------------------------------- -# implement the --enable-fast-install flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -AC_DEFUN([AC_ENABLE_FAST_INSTALL], -[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl -AC_ARG_ENABLE([fast-install], - [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], - [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) -])# AC_ENABLE_FAST_INSTALL - - -# AC_DISABLE_FAST_INSTALL -# ----------------------- -# set the default to --disable-fast-install -AC_DEFUN([AC_DISABLE_FAST_INSTALL], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -AC_ENABLE_FAST_INSTALL(no) -])# AC_DISABLE_FAST_INSTALL - - -# AC_LIBTOOL_PICMODE([MODE]) -# -------------------------- -# implement the --with-pic flag -# MODE is either `yes' or `no'. If omitted, it defaults to `both'. -AC_DEFUN([AC_LIBTOOL_PICMODE], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl -pic_mode=ifelse($#,1,$1,default) -])# AC_LIBTOOL_PICMODE - - -# AC_PROG_EGREP -# ------------- -# This is predefined starting with Autoconf 2.54, so this conditional -# definition can be removed once we require Autoconf 2.54 or later. -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], -[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], - [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' - fi]) - EGREP=$ac_cv_prog_egrep - AC_SUBST([EGREP]) -])]) - - -# AC_PATH_TOOL_PREFIX -# ------------------- -# find a file program which can recognize shared library -AC_DEFUN([AC_PATH_TOOL_PREFIX], -[AC_REQUIRE([AC_PROG_EGREP])dnl -AC_MSG_CHECKING([for $1]) -AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, -[case $MAGIC_CMD in -[[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR -dnl $ac_dummy forces splitting on constant user-supplied paths. -dnl POSIX.2 word splitting is done only on the output of word expansions, -dnl not every word. This closes a longstanding sh security hole. - ac_dummy="ifelse([$2], , $PATH, [$2])" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$1; then - lt_cv_path_MAGIC_CMD="$ac_dir/$1" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac]) -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - AC_MSG_RESULT($MAGIC_CMD) -else - AC_MSG_RESULT(no) -fi -])# AC_PATH_TOOL_PREFIX - - -# AC_PATH_MAGIC -# ------------- -# find a file program which can recognize a shared library -AC_DEFUN([AC_PATH_MAGIC], -[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) - else - MAGIC_CMD=: - fi -fi -])# AC_PATH_MAGIC - - -# AC_PROG_LD -# ---------- -# find the pathname to the GNU or non-GNU linker -AC_DEFUN([AC_PROG_LD], -[AC_ARG_WITH([gnu-ld], - [AC_HELP_STRING([--with-gnu-ld], - [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test "$withval" = no || with_gnu_ld=yes], - [with_gnu_ld=no]) -AC_REQUIRE([LT_AC_PROG_SED])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by $CC]) - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [[\\/]]* | ?:[[\\/]]*) - re_direlt='/[[^/]][[^/]]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(lt_cv_path_LD, -[if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[[3-9]]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -nto-qnx*) - lt_cv_deplibs_check_method=unknown - ;; - -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; -esac -]) -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown -])# AC_DEPLIBS_CHECK_METHOD - - -# AC_PROG_NM -# ---------- -# find the pathname to a BSD-compatible name lister -AC_DEFUN([AC_PROG_NM], -[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, -[if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_nm_to_check="${ac_tool_prefix}nm" - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS="$lt_save_ifs" - done - test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm -fi]) -NM="$lt_cv_path_NM" -])# AC_PROG_NM - - -# AC_CHECK_LIBM -# ------------- -# check for math library -AC_DEFUN([AC_CHECK_LIBM], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -LIBM= -case $host in -*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) - # These system don't have libm, or don't need it - ;; -*-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") - AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") - ;; -*) - AC_CHECK_LIB(m, cos, LIBM="-lm") - ;; -esac -])# AC_CHECK_LIBM - - -# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) -# ----------------------------------- -# sets LIBLTDL to the link flags for the libltdl convenience library and -# LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-convenience to the configure arguments. Note that -# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, -# it is assumed to be `libltdl'. LIBLTDL will be prefixed with -# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' -# (note the single quotes!). If your package is not flat and you're not -# using automake, define top_builddir and top_srcdir appropriately in -# the Makefiles. -AC_DEFUN([AC_LIBLTDL_CONVENIENCE], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl - case $enable_ltdl_convenience in - no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; - "") enable_ltdl_convenience=yes - ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; - esac - LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la - LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) - # For backwards non-gettext consistent compatibility... - INCLTDL="$LTDLINCL" -])# AC_LIBLTDL_CONVENIENCE - - -# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) -# ----------------------------------- -# sets LIBLTDL to the link flags for the libltdl installable library and -# LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-install to the configure arguments. Note that -# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, -# and an installed libltdl is not found, it is assumed to be `libltdl'. -# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with -# '${top_srcdir}/' (note the single quotes!). If your package is not -# flat and you're not using automake, define top_builddir and top_srcdir -# appropriately in the Makefiles. -# In the future, this macro may have to be called after AC_PROG_LIBTOOL. -AC_DEFUN([AC_LIBLTDL_INSTALLABLE], -[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl - AC_CHECK_LIB(ltdl, lt_dlinit, - [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], - [if test x"$enable_ltdl_install" = xno; then - AC_MSG_WARN([libltdl not installed, but installation disabled]) - else - enable_ltdl_install=yes - fi - ]) - if test x"$enable_ltdl_install" = x"yes"; then - ac_configure_args="$ac_configure_args --enable-ltdl-install" - LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la - LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) - else - ac_configure_args="$ac_configure_args --enable-ltdl-install=no" - LIBLTDL="-lltdl" - LTDLINCL= - fi - # For backwards non-gettext consistent compatibility... - INCLTDL="$LTDLINCL" -])# AC_LIBLTDL_INSTALLABLE - - -# AC_LIBTOOL_CXX -# -------------- -# enable support for C++ libraries -AC_DEFUN([AC_LIBTOOL_CXX], -[AC_REQUIRE([_LT_AC_LANG_CXX]) -])# AC_LIBTOOL_CXX - - -# _LT_AC_LANG_CXX -# --------------- -AC_DEFUN([_LT_AC_LANG_CXX], -[AC_REQUIRE([AC_PROG_CXX]) -AC_REQUIRE([_LT_AC_PROG_CXXCPP]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) -])# _LT_AC_LANG_CXX - -# _LT_AC_PROG_CXXCPP -# ------------------ -AC_DEFUN([_LT_AC_PROG_CXXCPP], -[ -AC_REQUIRE([AC_PROG_CXX]) -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - AC_PROG_CXXCPP -fi -])# _LT_AC_PROG_CXXCPP - -# AC_LIBTOOL_F77 -# -------------- -# enable support for Fortran 77 libraries -AC_DEFUN([AC_LIBTOOL_F77], -[AC_REQUIRE([_LT_AC_LANG_F77]) -])# AC_LIBTOOL_F77 - - -# _LT_AC_LANG_F77 -# --------------- -AC_DEFUN([_LT_AC_LANG_F77], -[AC_REQUIRE([AC_PROG_F77]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) -])# _LT_AC_LANG_F77 - - -# AC_LIBTOOL_GCJ -# -------------- -# enable support for GCJ libraries -AC_DEFUN([AC_LIBTOOL_GCJ], -[AC_REQUIRE([_LT_AC_LANG_GCJ]) -])# AC_LIBTOOL_GCJ - - -# _LT_AC_LANG_GCJ -# --------------- -AC_DEFUN([_LT_AC_LANG_GCJ], -[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], - [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], - [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], - [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], - [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) -])# _LT_AC_LANG_GCJ - - -# AC_LIBTOOL_RC -# ------------- -# enable support for Windows resource files -AC_DEFUN([AC_LIBTOOL_RC], -[AC_REQUIRE([LT_AC_PROG_RC]) -_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) -])# AC_LIBTOOL_RC - - -# AC_LIBTOOL_LANG_C_CONFIG -# ------------------------ -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. -AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) -AC_DEFUN([_LT_AC_LANG_C_CONFIG], -[lt_save_CC="$CC" -AC_LANG_PUSH(C) - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -_LT_AC_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}' - -_LT_AC_SYS_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) -AC_LIBTOOL_PROG_COMPILER_PIC($1) -AC_LIBTOOL_PROG_CC_C_O($1) -AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) -AC_LIBTOOL_PROG_LD_SHLIBS($1) -AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) -AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) -AC_LIBTOOL_SYS_LIB_STRIP -AC_LIBTOOL_DLOPEN_SELF - -# Report which library types will actually be built -AC_MSG_CHECKING([if libtool supports shared libraries]) -AC_MSG_RESULT([$can_build_shared]) - -AC_MSG_CHECKING([whether to build shared libraries]) -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case $host_os in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - -aix4* | aix5*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; -esac -AC_MSG_RESULT([$enable_shared]) - -AC_MSG_CHECKING([whether to build static libraries]) -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes -AC_MSG_RESULT([$enable_static]) - -AC_LIBTOOL_CONFIG($1) - -AC_LANG_POP -CC="$lt_save_CC" -])# AC_LIBTOOL_LANG_C_CONFIG - - -# AC_LIBTOOL_LANG_CXX_CONFIG -# -------------------------- -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. -AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) -AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], -[AC_LANG_PUSH(C++) -AC_REQUIRE([AC_PROG_CXX]) -AC_REQUIRE([_LT_AC_PROG_CXXCPP]) - -_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_AC_TAGVAR(allow_undefined_flag, $1)= -_LT_AC_TAGVAR(always_export_symbols, $1)=no -_LT_AC_TAGVAR(archive_expsym_cmds, $1)= -_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_AC_TAGVAR(hardcode_direct, $1)=no -_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= -_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= -_LT_AC_TAGVAR(hardcode_minus_L, $1)=no -_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported -_LT_AC_TAGVAR(hardcode_automatic, $1)=no -_LT_AC_TAGVAR(module_cmds, $1)= -_LT_AC_TAGVAR(module_expsym_cmds, $1)= -_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown -_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_AC_TAGVAR(no_undefined_flag, $1)= -_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= -_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Dependencies to place before and after the object being linked: -_LT_AC_TAGVAR(predep_objects, $1)= -_LT_AC_TAGVAR(postdep_objects, $1)= -_LT_AC_TAGVAR(predeps, $1)= -_LT_AC_TAGVAR(postdeps, $1)= -_LT_AC_TAGVAR(compiler_lib_search_path, $1)= - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -_LT_AC_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_AC_SYS_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_LD=$LD -lt_save_GCC=$GCC -GCC=$GXX -lt_save_with_gnu_ld=$with_gnu_ld -lt_save_path_LD=$lt_cv_path_LD -if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx -else - $as_unset lt_cv_prog_gnu_ld -fi -if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX -else - $as_unset lt_cv_path_LD -fi -test -z "${LDCXX+set}" || LD=$LDCXX -CC=${CXX-"c++"} -compiler=$CC -_LT_AC_TAGVAR(compiler, $1)=$CC -_LT_CC_BASENAME([$compiler]) - -# We don't want -fno-exception wen compiling C++ code, so set the -# no_builtin_flag separately -if test "$GXX" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' -else - _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= -fi - -if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - AC_PROG_LD - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ - grep 'no-whole-archive' > /dev/null; then - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - -else - GXX=no - with_gnu_ld=no - wlarc= -fi - -# PORTME: fill in a description of your system's C++ link characteristics -AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -_LT_AC_TAGVAR(ld_shlibs, $1)=yes -case $host_os in - aix3*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_AC_TAGVAR(archive_cmds, $1)='' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - if test "$GXX" = yes; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared libraries. - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(always_export_symbols, $1)=no - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_automatic, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - if test "$GXX" = yes ; then - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - case $cc_basename in - xlc*) - output_verbose_link_cmd='echo' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' - _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - ;; - *) - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - fi - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - freebsd[[12]]*) - # C++ shared libraries reported to be fairly broken before switch to ELF - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - freebsd-elf*) - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - ;; - freebsd* | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - _LT_AC_TAGVAR(ld_shlibs, $1)=yes - ;; - gnu*) - ;; - hpux9*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) ;; - *) - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case $host_cpu in - hppa*64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - interix[[3-9]]*) - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' - fi - fi - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - ;; - esac - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - linux* | k*bsd*-gnu) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc*) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - pgCC*) - # Portland Group C++ compiler - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - ;; - cxx*) - # Compaq C++ - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - - # Not sure whether something based on - # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 - # would be better. - output_verbose_link_cmd='echo' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - esac - ;; - esac - ;; - lynxos*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - m88k*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - openbsd2*) - # C++ shared libraries are fairly broken - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - openbsd*) - if test -f /usr/libexec/ld.so; then - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - fi - output_verbose_link_cmd='echo' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - osf3*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - cxx*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - cxx*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ - $rm $lib.exp' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - psos*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - solaris*) - case $cc_basename in - CC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes - _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. - # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - ;; - esac - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - output_verbose_link_cmd='echo' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' - if $CC --version | grep -v '^2\.7' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - fi - - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - ;; - esac - fi - ;; - esac - ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - # So that behaviour is only enabled if SCOABSPATH is set to a - # non-empty value in the environment. Most likely only useful for - # creating official distributions of packages. - # This is a hack until libtool officially supports absolute path - # names for shared libraries. - _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - vxworks*) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; -esac -AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) -test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - -_LT_AC_TAGVAR(GCC, $1)="$GXX" -_LT_AC_TAGVAR(LD, $1)="$LD" - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -AC_LIBTOOL_POSTDEP_PREDEP($1) -AC_LIBTOOL_PROG_COMPILER_PIC($1) -AC_LIBTOOL_PROG_CC_C_O($1) -AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) -AC_LIBTOOL_PROG_LD_SHLIBS($1) -AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) -AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) - -AC_LIBTOOL_CONFIG($1) - -AC_LANG_POP -CC=$lt_save_CC -LDCXX=$LD -LD=$lt_save_LD -GCC=$lt_save_GCC -with_gnu_ldcxx=$with_gnu_ld -with_gnu_ld=$lt_save_with_gnu_ld -lt_cv_path_LDCXX=$lt_cv_path_LD -lt_cv_path_LD=$lt_save_path_LD -lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld -lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -])# AC_LIBTOOL_LANG_CXX_CONFIG - -# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) -# ------------------------------------ -# Figure out "hidden" library dependencies from verbose -# compiler output when linking a shared library. -# Parse the compiler output and extract the necessary -# objects, libraries and library flags. -AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ -dnl we can't use the lt_simple_compile_test_code here, -dnl because it contains code intended for an executable, -dnl not a library. It's possible we should let each -dnl tag define a new lt_????_link_test_code variable, -dnl but it's only used here... -ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - # - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - if test "$solaris_use_stlport4" != yes; then - _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; - -solaris*) - case $cc_basename in - CC*) - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - if test "$solaris_use_stlport4" != yes; then - _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; -esac -]) - -case " $_LT_AC_TAGVAR(postdeps, $1) " in -*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; -esac -])# AC_LIBTOOL_POSTDEP_PREDEP - -# AC_LIBTOOL_LANG_F77_CONFIG -# -------------------------- -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. -AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)]) -AC_DEFUN([_LT_AC_LANG_F77_CONFIG], -[AC_REQUIRE([AC_PROG_F77]) -AC_LANG_PUSH(Fortran 77) - -_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_AC_TAGVAR(allow_undefined_flag, $1)= -_LT_AC_TAGVAR(always_export_symbols, $1)=no -_LT_AC_TAGVAR(archive_expsym_cmds, $1)= -_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_AC_TAGVAR(hardcode_direct, $1)=no -_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= -_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= -_LT_AC_TAGVAR(hardcode_minus_L, $1)=no -_LT_AC_TAGVAR(hardcode_automatic, $1)=no -_LT_AC_TAGVAR(module_cmds, $1)= -_LT_AC_TAGVAR(module_expsym_cmds, $1)= -_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown -_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_AC_TAGVAR(no_undefined_flag, $1)= -_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= -_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for f77 test sources. -ac_ext=f - -# Object file extension for compiled f77 test sources. -objext=o -_LT_AC_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="\ - subroutine t - return - end -" - -# Code to be used in simple link tests -lt_simple_link_test_code="\ - program t - end -" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_AC_SYS_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${F77-"f77"} -compiler=$CC -_LT_AC_TAGVAR(compiler, $1)=$CC -_LT_CC_BASENAME([$compiler]) - -AC_MSG_CHECKING([if libtool supports shared libraries]) -AC_MSG_RESULT([$can_build_shared]) - -AC_MSG_CHECKING([whether to build shared libraries]) -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case $host_os in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; -aix4* | aix5*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; -esac -AC_MSG_RESULT([$enable_shared]) - -AC_MSG_CHECKING([whether to build static libraries]) -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes -AC_MSG_RESULT([$enable_static]) - -_LT_AC_TAGVAR(GCC, $1)="$G77" -_LT_AC_TAGVAR(LD, $1)="$LD" - -AC_LIBTOOL_PROG_COMPILER_PIC($1) -AC_LIBTOOL_PROG_CC_C_O($1) -AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) -AC_LIBTOOL_PROG_LD_SHLIBS($1) -AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) -AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) - -AC_LIBTOOL_CONFIG($1) - -AC_LANG_POP -CC="$lt_save_CC" -])# AC_LIBTOOL_LANG_F77_CONFIG - - -# AC_LIBTOOL_LANG_GCJ_CONFIG -# -------------------------- -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. -AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)]) -AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], -[AC_LANG_SAVE - -# Source file extension for Java test sources. -ac_ext=java - -# Object file extension for compiled Java test sources. -objext=o -_LT_AC_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}" - -# Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_AC_SYS_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${GCJ-"gcj"} -compiler=$CC -_LT_AC_TAGVAR(compiler, $1)=$CC -_LT_CC_BASENAME([$compiler]) - -# GCJ did not exist at the time GCC didn't implicitly link libc in. -_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - -_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) -AC_LIBTOOL_PROG_COMPILER_PIC($1) -AC_LIBTOOL_PROG_CC_C_O($1) -AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) -AC_LIBTOOL_PROG_LD_SHLIBS($1) -AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) -AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) - -AC_LIBTOOL_CONFIG($1) - -AC_LANG_RESTORE -CC="$lt_save_CC" -])# AC_LIBTOOL_LANG_GCJ_CONFIG - - -# AC_LIBTOOL_LANG_RC_CONFIG -# ------------------------- -# Ensure that the configuration vars for the Windows resource compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. -AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)]) -AC_DEFUN([_LT_AC_LANG_RC_CONFIG], -[AC_LANG_SAVE - -# Source file extension for RC test sources. -ac_ext=rc - -# Object file extension for compiled RC test sources. -objext=o -_LT_AC_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' - -# Code to be used in simple link tests -lt_simple_link_test_code="$lt_simple_compile_test_code" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_AC_SYS_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${RC-"windres"} -compiler=$CC -_LT_AC_TAGVAR(compiler, $1)=$CC -_LT_CC_BASENAME([$compiler]) -_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - -AC_LIBTOOL_CONFIG($1) - -AC_LANG_RESTORE -CC="$lt_save_CC" -])# AC_LIBTOOL_LANG_RC_CONFIG - - -# AC_LIBTOOL_CONFIG([TAGNAME]) -# ---------------------------- -# If TAGNAME is not passed, then create an initial libtool script -# with a default configuration from the untagged config vars. Otherwise -# add code to config.status for appending the configuration named by -# TAGNAME from the matching tagged config vars. -AC_DEFUN([AC_LIBTOOL_CONFIG], -[# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - _LT_AC_TAGVAR(compiler, $1) \ - _LT_AC_TAGVAR(CC, $1) \ - _LT_AC_TAGVAR(LD, $1) \ - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \ - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \ - _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \ - _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \ - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \ - _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \ - _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \ - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \ - _LT_AC_TAGVAR(old_archive_cmds, $1) \ - _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \ - _LT_AC_TAGVAR(predep_objects, $1) \ - _LT_AC_TAGVAR(postdep_objects, $1) \ - _LT_AC_TAGVAR(predeps, $1) \ - _LT_AC_TAGVAR(postdeps, $1) \ - _LT_AC_TAGVAR(compiler_lib_search_path, $1) \ - _LT_AC_TAGVAR(archive_cmds, $1) \ - _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ - _LT_AC_TAGVAR(postinstall_cmds, $1) \ - _LT_AC_TAGVAR(postuninstall_cmds, $1) \ - _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \ - _LT_AC_TAGVAR(allow_undefined_flag, $1) \ - _LT_AC_TAGVAR(no_undefined_flag, $1) \ - _LT_AC_TAGVAR(export_symbols_cmds, $1) \ - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \ - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \ - _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \ - _LT_AC_TAGVAR(hardcode_automatic, $1) \ - _LT_AC_TAGVAR(module_cmds, $1) \ - _LT_AC_TAGVAR(module_expsym_cmds, $1) \ - _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ - _LT_AC_TAGVAR(fix_srcfile_path, $1) \ - _LT_AC_TAGVAR(exclude_expsyms, $1) \ - _LT_AC_TAGVAR(include_expsyms, $1); do - - case $var in - _LT_AC_TAGVAR(old_archive_cmds, $1) | \ - _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \ - _LT_AC_TAGVAR(archive_cmds, $1) | \ - _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \ - _LT_AC_TAGVAR(module_cmds, $1) | \ - _LT_AC_TAGVAR(module_expsym_cmds, $1) | \ - _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \ - _LT_AC_TAGVAR(export_symbols_cmds, $1) | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\[$]0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'` - ;; - esac - -ifelse([$1], [], - [cfgfile="${ofile}T" - trap "$rm \"$cfgfile\"; exit 1" 1 2 15 - $rm -f "$cfgfile" - AC_MSG_NOTICE([creating $ofile])], - [cfgfile="$ofile"]) - - cat <<__EOF__ >> "$cfgfile" -ifelse([$1], [], -[#! $SHELL - -# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 -# Free Software Foundation, Inc. -# -# This file is part of GNU Libtool: -# Originally by Gordon Matzigkeit , 1996 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# A sed program that does not truncate output. -SED=$lt_SED - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="$SED -e 1s/^X//" - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# The names of the tagged configurations supported by this script. -available_tags= - -# ### BEGIN LIBTOOL CONFIG], -[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) - -# Is the compiler the GNU C compiler? -with_gcc=$_LT_AC_TAGVAR(GCC, $1) - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_[]_LT_AC_TAGVAR(LD, $1) - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) - -# Commands used to build and install a shared archive. -archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) -archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) -module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path=$lt_fix_srcfile_path - -# Set to yes if exported symbols are required. -always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) - -# The commands to list exported symbols. -export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) - -# Symbols that must always be exported. -include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) - -ifelse([$1],[], -[# ### END LIBTOOL CONFIG], -[# ### END LIBTOOL TAG CONFIG: $tagname]) - -__EOF__ - -ifelse([$1],[], [ - case $host_os in - aix3*) - cat <<\EOF >> "$cfgfile" - -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -EOF - ;; - esac - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || \ - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" -]) -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi -])# AC_LIBTOOL_CONFIG - - -# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) -# ------------------------------------------- -AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], -[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl - -_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - -if test "$GCC" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' - - AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], - lt_cv_prog_compiler_rtti_exceptions, - [-fno-rtti -fno-exceptions], [], - [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) -fi -])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI - - -# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE -# --------------------------------- -AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], -[AC_REQUIRE([AC_CANONICAL_HOST]) -AC_REQUIRE([LT_AC_PROG_SED]) -AC_REQUIRE([AC_PROG_NM]) -AC_REQUIRE([AC_OBJEXT]) -# Check for command to grab the raw symbol name followed by C symbol from nm. -AC_MSG_CHECKING([command to parse $NM output from $compiler object]) -AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], -[ -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[[BCDEGRST]]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' - -# Transform an extracted symbol line into a proper C declaration -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[[BCDT]]' - ;; -cygwin* | mingw* | pw32*) - symcode='[[ABCDGISTW]]' - ;; -hpux*) # Its linker distinguishes data from code symbols - if test "$host_cpu" = ia64; then - symcode='[[ABCDEGRST]]' - fi - lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - ;; -linux* | k*bsd*-gnu) - if test "$host_cpu" = ia64; then - symcode='[[ABCDGIRSTW]]' - lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - fi - ;; -irix* | nonstopux*) - symcode='[[BCDEGRST]]' - ;; -osf*) - symcode='[[BCDEGQRST]]' - ;; -solaris*) - symcode='[[BDRT]]' - ;; -sco3.2v5*) - symcode='[[DT]]' - ;; -sysv4.2uw2*) - symcode='[[DT]]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[[ABDT]]' - ;; -sysv4) - symcode='[[DFNSTU]]' - ;; -esac - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[[ABCDGIRSTW]]' ;; -esac - -# Try without a prefix undercore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if grep ' nm_test_var$' "$nlist" >/dev/null; then - if grep ' nm_test_func$' "$nlist" >/dev/null; then - cat < conftest.$ac_ext -#ifdef __cplusplus -extern "C" { -#endif - -EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' - - cat <> conftest.$ac_ext -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[[]] = -{ -EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext - cat <<\EOF >> conftest.$ac_ext - {0, (lt_ptr_t) 0} -}; - -#ifdef __cplusplus -} -#endif -EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" - else - echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD - fi - else - echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD - cat conftest.$ac_ext >&5 - fi - rm -f conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done -]) -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - AC_MSG_RESULT(failed) -else - AC_MSG_RESULT(ok) -fi -]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE - - -# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) -# --------------------------------------- -AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], -[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= -_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= -_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= - -AC_MSG_CHECKING([for $compiler option to produce PIC]) - ifelse([$1],[CXX],[ - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | cygwin* | os2* | pw32*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - case $host_os in - aix4* | aix5*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - darwin*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - case $cc_basename in - xlc*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - ;; - esac - ;; - dgux*) - case $cc_basename in - ec++*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - fi - ;; - aCC*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux* | k*bsd*-gnu) - case $cc_basename in - KCC*) - # KAI C++ Compiler - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - icpc* | ecpc*) - # Intel C++ - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - pgCC*) - # Portland Group C++ compiler. - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - esac - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd* | netbsdelf*-gnu) - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - cxx*) - # Digital/Compaq C++ - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - lcc*) - # Lucid - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - vxworks*) - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -], -[ - if test "$GCC" = yes; then - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - darwin*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - case $cc_basename in - xlc*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - ;; - esac - ;; - - mingw* | cygwin* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC (with -KPIC) is the default. - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - newsos6) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - linux* | k*bsd*-gnu) - case $cc_basename in - icc* | ecc*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - ccc*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All Alpha code is PIC. - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C 5.9 - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='' - ;; - esac - ;; - esac - ;; - - osf3* | osf4* | osf5*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All OSF/1 code is PIC. - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - rdos*) - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - solaris*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - case $cc_basename in - f77* | f90* | f95*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; - *) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; - esac - ;; - - sunos4*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - unicos*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - - uts4*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *) - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -]) -AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then - AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], - _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), - [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], - [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in - "" | " "*) ;; - *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; - esac], - [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) -fi -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - *) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" - ;; -esac - -# -# Check to make sure the static flag actually works. -# -wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" -AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], - _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), - $lt_tmp_static_flag, - [], - [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) -]) - - -# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) -# ------------------------------------ -# See if the linker supports building shared libraries. -AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], -[AC_REQUIRE([LT_AC_PROG_SED])dnl -AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -ifelse([$1],[CXX],[ - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - case $host_os in - aix4* | aix5*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - else - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" - ;; - cygwin* | mingw*) - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' - ;; - linux* | k*bsd*-gnu) - _LT_AC_TAGVAR(link_all_deplibs, $1)=no - ;; - *) - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac -],[ - runpath_var= - _LT_AC_TAGVAR(allow_undefined_flag, $1)= - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no - _LT_AC_TAGVAR(archive_cmds, $1)= - _LT_AC_TAGVAR(archive_expsym_cmds, $1)= - _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= - _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_minus_L, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown - _LT_AC_TAGVAR(hardcode_automatic, $1)=no - _LT_AC_TAGVAR(module_cmds, $1)= - _LT_AC_TAGVAR(module_expsym_cmds, $1)= - _LT_AC_TAGVAR(always_export_symbols, $1)=no - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - _LT_AC_TAGVAR(include_expsyms, $1)= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - # Just being paranoid about ensuring that cc_basename is set. - _LT_CC_BASENAME([$compiler]) - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - _LT_AC_TAGVAR(ld_shlibs, $1)=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - fi - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - _LT_AC_TAGVAR(ld_shlibs, $1)=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(always_export_symbols, $1)=no - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - interix[[3-9]]*) - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | k*bsd*-gnu) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_addflag= - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - *) - tmp_sharedflag='-shared' ;; - esac - _LT_AC_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test $supports_anon_versioning = yes; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - _LT_AC_TAGVAR(link_all_deplibs, $1)=no - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - _LT_AC_TAGVAR(ld_shlibs, $1)=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) - _LT_AC_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - sunos4*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - - if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then - runpath_var= - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - else - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_AC_TAGVAR(archive_cmds, $1)='' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - if test "$GCC" = yes; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_AC_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - _LT_AC_SYS_LIBPATH_AIX - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared libraries. - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - # see comment about different semantics on the GNU ld section - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - - bsdi[[45]]*) - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' - # FIXME: Should let the user specify the lib program. - _LT_AC_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' - _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' - _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_automatic, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - if test "$GCC" = yes ; then - output_verbose_link_cmd='echo' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - case $cc_basename in - xlc*) - output_verbose_link_cmd='echo' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' - _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - ;; - *) - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - fi - ;; - - dgux*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - freebsd1*) - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - hpux9*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - newsos6) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - else - case $host_os in - openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - ;; - esac - fi - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - os2*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - else - _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - fi - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - solaris*) - _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' - if test "$GCC" = yes; then - wlarc='${wl}' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - wlarc='' - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - else - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - fi - ;; - esac - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4) - case $host_vendor in - sni) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - ;; - motorola) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4.3*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - _LT_AC_TAGVAR(ld_shlibs, $1)=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - fi -]) -AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) -test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - -# -# Do we need to explicitly link libc? -# -case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in -x|xyes) - # Assume -lc should be added - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $_LT_AC_TAGVAR(archive_cmds, $1) in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - AC_MSG_CHECKING([whether -lc should be explicitly linked in]) - $rm conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if AC_TRY_EVAL(ac_compile) 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) - pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) - _LT_AC_TAGVAR(allow_undefined_flag, $1)= - if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) - then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - else - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - fi - _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) - ;; - esac - fi - ;; -esac -])# AC_LIBTOOL_PROG_LD_SHLIBS - - -# _LT_AC_FILE_LTDLL_C -# ------------------- -# Be careful that the start marker always follows a newline. -AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ -# /* ltdll.c starts here */ -# #define WIN32_LEAN_AND_MEAN -# #include -# #undef WIN32_LEAN_AND_MEAN -# #include -# -# #ifndef __CYGWIN__ -# # ifdef __CYGWIN32__ -# # define __CYGWIN__ __CYGWIN32__ -# # endif -# #endif -# -# #ifdef __cplusplus -# extern "C" { -# #endif -# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); -# #ifdef __cplusplus -# } -# #endif -# -# #ifdef __CYGWIN__ -# #include -# DECLARE_CYGWIN_DLL( DllMain ); -# #endif -# HINSTANCE __hDllInstance_base; -# -# BOOL APIENTRY -# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) -# { -# __hDllInstance_base = hInst; -# return TRUE; -# } -# /* ltdll.c ends here */ -])# _LT_AC_FILE_LTDLL_C - - -# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) -# --------------------------------- -AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) - - -# old names -AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) -AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) -AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) -AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) -AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) -AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) -AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) - -# This is just to silence aclocal about the macro not being used -ifelse([AC_DISABLE_FAST_INSTALL]) - -AC_DEFUN([LT_AC_PROG_GCJ], -[AC_CHECK_TOOL(GCJ, gcj, no) - test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" - AC_SUBST(GCJFLAGS) -]) - -AC_DEFUN([LT_AC_PROG_RC], -[AC_CHECK_TOOL(RC, windres, no) -]) - - -# Cheap backport of AS_EXECUTABLE_P and required macros -# from Autoconf 2.59; we should not use $as_executable_p directly. - -# _AS_TEST_PREPARE -# ---------------- -m4_ifndef([_AS_TEST_PREPARE], -[m4_defun([_AS_TEST_PREPARE], -[if test -x / >/dev/null 2>&1; then - as_executable_p='test -x' -else - as_executable_p='test -f' -fi -])])# _AS_TEST_PREPARE - -# AS_EXECUTABLE_P -# --------------- -# Check whether a file is executable. -m4_ifndef([AS_EXECUTABLE_P], -[m4_defun([AS_EXECUTABLE_P], -[AS_REQUIRE([_AS_TEST_PREPARE])dnl -$as_executable_p $1[]dnl -])])# AS_EXECUTABLE_P - -############################################################ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_SED. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # -############################################################ -# LT_AC_PROG_SED -# -------------- -# Check for a fully-functional sed program, that truncates -# as few characters as possible. Prefer GNU sed if found. -AC_DEFUN([LT_AC_PROG_SED], -[AC_MSG_CHECKING([for a sed that does not truncate output]) -AC_CACHE_VAL(lt_cv_path_SED, -[# Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if AS_EXECUTABLE_P(["$as_dir/$lt_ac_prog$ac_exec_ext"]); then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -IFS=$as_save_IFS -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && continue - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break - lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done -]) -SED=$lt_cv_path_SED -AC_SUBST([SED]) -AC_MSG_RESULT([$SED]) -]) -## ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- -## Copyright (C) 1999-2006 Free Software Foundation, Inc. -## -## This file is free software; the Free Software Foundation gives -## unlimited permission to copy and/or distribute it, with or without -## modifications, as long as this notice is preserved. - -# serial 8 AC_LIB_LTDL - -# AC_WITH_LTDL -# ------------ -# Clients of libltdl can use this macro to allow the installer to -# choose between a shipped copy of the ltdl sources or a preinstalled -# version of the library. -AC_DEFUN([AC_WITH_LTDL], -[AC_REQUIRE([AC_LIB_LTDL]) -AC_SUBST([LIBLTDL]) -AC_SUBST([INCLTDL]) - -# Unless the user asks us to check, assume no installed ltdl exists. -use_installed_libltdl=no - -AC_ARG_WITH([included_ltdl], - [ --with-included-ltdl use the GNU ltdl sources included here]) - -if test "x$with_included_ltdl" != xyes; then - # We are not being forced to use the included libltdl sources, so - # decide whether there is a useful installed version we can use. - AC_CHECK_HEADER([ltdl.h], - [AC_CHECK_LIB([ltdl], [lt_dlcaller_register], - [with_included_ltdl=no], - [with_included_ltdl=yes]) - ]) -fi - -if test "x$enable_ltdl_install" != xyes; then - # If the user did not specify an installable libltdl, then default - # to a convenience lib. - AC_LIBLTDL_CONVENIENCE -fi - -if test "x$with_included_ltdl" = xno; then - # If the included ltdl is not to be used. then Use the - # preinstalled libltdl we found. - AC_DEFINE([HAVE_LTDL], [1], - [Define this if a modern libltdl is already installed]) - LIBLTDL=-lltdl -fi - -# Report our decision... -AC_MSG_CHECKING([whether to use included libltdl]) -AC_MSG_RESULT([$with_included_ltdl]) - -AC_CONFIG_SUBDIRS([libltdl]) -])# AC_WITH_LTDL - - -# AC_LIB_LTDL -# ----------- -# Perform all the checks necessary for compilation of the ltdl objects -# -- including compiler checks and header checks. -AC_DEFUN([AC_LIB_LTDL], -[AC_PREREQ(2.50) -AC_REQUIRE([AC_PROG_CC]) -AC_REQUIRE([AC_C_CONST]) -AC_REQUIRE([AC_HEADER_STDC]) -AC_REQUIRE([AC_HEADER_DIRENT]) -AC_REQUIRE([_LT_AC_CHECK_DLFCN]) -AC_REQUIRE([AC_LTDL_ENABLE_INSTALL]) -AC_REQUIRE([AC_LTDL_SHLIBEXT]) -AC_REQUIRE([AC_LTDL_SHLIBPATH]) -AC_REQUIRE([AC_LTDL_SYSSEARCHPATH]) -AC_REQUIRE([AC_LTDL_OBJDIR]) -AC_REQUIRE([AC_LTDL_DLPREOPEN]) -AC_REQUIRE([AC_LTDL_DLLIB]) -AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) -AC_REQUIRE([AC_LTDL_DLSYM_USCORE]) -AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS]) -AC_REQUIRE([AC_LTDL_FUNC_ARGZ]) - -AC_CHECK_HEADERS([assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ - stdio.h unistd.h]) -AC_CHECK_HEADERS([dl.h sys/dl.h dld.h mach-o/dyld.h]) -AC_CHECK_HEADERS([string.h strings.h], [break]) - -AC_CHECK_FUNCS([strchr index], [break]) -AC_CHECK_FUNCS([strrchr rindex], [break]) -AC_CHECK_FUNCS([memcpy bcopy], [break]) -AC_CHECK_FUNCS([memmove strcmp]) -AC_CHECK_FUNCS([closedir opendir readdir]) -])# AC_LIB_LTDL - - -# AC_LTDL_ENABLE_INSTALL -# ---------------------- -AC_DEFUN([AC_LTDL_ENABLE_INSTALL], -[AC_ARG_ENABLE([ltdl-install], - [AC_HELP_STRING([--enable-ltdl-install], [install libltdl])]) - -AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) -AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno) -])# AC_LTDL_ENABLE_INSTALL - - -# AC_LTDL_SYS_DLOPEN_DEPLIBS -# -------------------------- -AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], -[AC_REQUIRE([AC_CANONICAL_HOST]) -AC_CACHE_CHECK([whether deplibs are loaded by dlopen], - [libltdl_cv_sys_dlopen_deplibs], - [# PORTME does your system automatically load deplibs for dlopen? - # or its logical equivalent (e.g. shl_load for HP-UX < 11) - # For now, we just catch OSes we know something about -- in the - # future, we'll try test this programmatically. - libltdl_cv_sys_dlopen_deplibs=unknown - case "$host_os" in - aix3*|aix4.1.*|aix4.2.*) - # Unknown whether this is true for these versions of AIX, but - # we want this `case' here to explicitly catch those versions. - libltdl_cv_sys_dlopen_deplibs=unknown - ;; - aix[[45]]*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - darwin*) - # Assuming the user has installed a libdl from somewhere, this is true - # If you are looking for one http://www.opendarwin.org/projects/dlcompat - libltdl_cv_sys_dlopen_deplibs=yes - ;; - freebsd* | dragonfly*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - gnu* | linux* | k*bsd*-gnu) - # GNU and its variants, using gnu ld.so (Glibc) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - hpux10*|hpux11*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - interix*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - irix[[12345]]*|irix6.[[01]]*) - # Catch all versions of IRIX before 6.2, and indicate that we don't - # know how it worked for any of those versions. - libltdl_cv_sys_dlopen_deplibs=unknown - ;; - irix*) - # The case above catches anything before 6.2, and it's known that - # at 6.2 and later dlopen does load deplibs. - libltdl_cv_sys_dlopen_deplibs=yes - ;; - netbsd* | netbsdelf*-gnu) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - openbsd*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - osf[[1234]]*) - # dlopen did load deplibs (at least at 4.x), but until the 5.x series, - # it did *not* use an RPATH in a shared library to find objects the - # library depends on, so we explictly say `no'. - libltdl_cv_sys_dlopen_deplibs=no - ;; - osf5.0|osf5.0a|osf5.1) - # dlopen *does* load deplibs and with the right loader patch applied - # it even uses RPATH in a shared library to search for shared objects - # that the library depends on, but there's no easy way to know if that - # patch is installed. Since this is the case, all we can really - # say is unknown -- it depends on the patch being installed. If - # it is, this changes to `yes'. Without it, it would be `no'. - libltdl_cv_sys_dlopen_deplibs=unknown - ;; - osf*) - # the two cases above should catch all versions of osf <= 5.1. Read - # the comments above for what we know about them. - # At > 5.1, deplibs are loaded *and* any RPATH in a shared library - # is used to find them so we can finally say `yes'. - libltdl_cv_sys_dlopen_deplibs=yes - ;; - solaris*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - esac - ]) -if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then - AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], - [Define if the OS needs help to load dependent libraries for dlopen().]) -fi -])# AC_LTDL_SYS_DLOPEN_DEPLIBS - - -# AC_LTDL_SHLIBEXT -# ---------------- -AC_DEFUN([AC_LTDL_SHLIBEXT], -[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) -AC_CACHE_CHECK([which extension is used for loadable modules], - [libltdl_cv_shlibext], -[ -module=yes -eval libltdl_cv_shlibext=$shrext_cmds - ]) -if test -n "$libltdl_cv_shlibext"; then - AC_DEFINE_UNQUOTED([LTDL_SHLIB_EXT], ["$libltdl_cv_shlibext"], - [Define to the extension used for shared libraries, say, ".so".]) -fi -])# AC_LTDL_SHLIBEXT - - -# AC_LTDL_SHLIBPATH -# ----------------- -AC_DEFUN([AC_LTDL_SHLIBPATH], -[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) -AC_CACHE_CHECK([which variable specifies run-time library path], - [libltdl_cv_shlibpath_var], [libltdl_cv_shlibpath_var="$shlibpath_var"]) -if test -n "$libltdl_cv_shlibpath_var"; then - AC_DEFINE_UNQUOTED([LTDL_SHLIBPATH_VAR], ["$libltdl_cv_shlibpath_var"], - [Define to the name of the environment variable that determines the dynamic library search path.]) -fi -])# AC_LTDL_SHLIBPATH - - -# AC_LTDL_SYSSEARCHPATH -# --------------------- -AC_DEFUN([AC_LTDL_SYSSEARCHPATH], -[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) -AC_CACHE_CHECK([for the default library search path], - [libltdl_cv_sys_search_path], - [libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"]) -if test -n "$libltdl_cv_sys_search_path"; then - sys_search_path= - for dir in $libltdl_cv_sys_search_path; do - if test -z "$sys_search_path"; then - sys_search_path="$dir" - else - sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" - fi - done - AC_DEFINE_UNQUOTED([LTDL_SYSSEARCHPATH], ["$sys_search_path"], - [Define to the system default library search path.]) -fi -])# AC_LTDL_SYSSEARCHPATH - - -# AC_LTDL_OBJDIR -# -------------- -AC_DEFUN([AC_LTDL_OBJDIR], -[AC_CACHE_CHECK([for objdir], - [libltdl_cv_objdir], - [libltdl_cv_objdir="$objdir" - if test -n "$objdir"; then - : - else - rm -f .libs 2>/dev/null - mkdir .libs 2>/dev/null - if test -d .libs; then - libltdl_cv_objdir=.libs - else - # MS-DOS does not allow filenames that begin with a dot. - libltdl_cv_objdir=_libs - fi - rmdir .libs 2>/dev/null - fi - ]) -AC_DEFINE_UNQUOTED([LTDL_OBJDIR], ["$libltdl_cv_objdir/"], - [Define to the sub-directory in which libtool stores uninstalled libraries.]) -])# AC_LTDL_OBJDIR - - -# AC_LTDL_DLPREOPEN -# ----------------- -AC_DEFUN([AC_LTDL_DLPREOPEN], -[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) -AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], - [libltdl_cv_preloaded_symbols], - [if test -n "$lt_cv_sys_global_symbol_pipe"; then - libltdl_cv_preloaded_symbols=yes - else - libltdl_cv_preloaded_symbols=no - fi - ]) -if test x"$libltdl_cv_preloaded_symbols" = xyes; then - AC_DEFINE([HAVE_PRELOADED_SYMBOLS], [1], - [Define if libtool can extract symbol lists from object files.]) -fi -])# AC_LTDL_DLPREOPEN - - -# AC_LTDL_DLLIB -# ------------- -AC_DEFUN([AC_LTDL_DLLIB], -[LIBADD_DL= -AC_SUBST(LIBADD_DL) -AC_LANG_PUSH([C]) - -AC_CHECK_FUNC([shl_load], - [AC_DEFINE([HAVE_SHL_LOAD], [1], - [Define if you have the shl_load function.])], - [AC_CHECK_LIB([dld], [shl_load], - [AC_DEFINE([HAVE_SHL_LOAD], [1], - [Define if you have the shl_load function.]) - LIBADD_DL="$LIBADD_DL -ldld"], - [AC_CHECK_LIB([dl], [dlopen], - [AC_DEFINE([HAVE_LIBDL], [1], - [Define if you have the libdl library or equivalent.]) - LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"], - [AC_TRY_LINK([#if HAVE_DLFCN_H -# include -#endif - ], - [dlopen(0, 0);], - [AC_DEFINE([HAVE_LIBDL], [1], - [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"], - [AC_CHECK_LIB([svld], [dlopen], - [AC_DEFINE([HAVE_LIBDL], [1], - [Define if you have the libdl library or equivalent.]) - LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"], - [AC_CHECK_LIB([dld], [dld_link], - [AC_DEFINE([HAVE_DLD], [1], - [Define if you have the GNU dld library.]) - LIBADD_DL="$LIBADD_DL -ldld"], - [AC_CHECK_FUNC([_dyld_func_lookup], - [AC_DEFINE([HAVE_DYLD], [1], - [Define if you have the _dyld_func_lookup function.])]) - ]) - ]) - ]) - ]) - ]) -]) - -if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes -then - lt_save_LIBS="$LIBS" - LIBS="$LIBS $LIBADD_DL" - AC_CHECK_FUNCS([dlerror]) - LIBS="$lt_save_LIBS" -fi -AC_LANG_POP -])# AC_LTDL_DLLIB - - -# AC_LTDL_SYMBOL_USCORE -# --------------------- -# does the compiler prefix global symbols with an underscore? -AC_DEFUN([AC_LTDL_SYMBOL_USCORE], -[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) -AC_CACHE_CHECK([for _ prefix in compiled symbols], - [ac_cv_sys_symbol_underscore], - [ac_cv_sys_symbol_underscore=no - cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then - # See whether the symbols have a leading underscore. - if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then - ac_cv_sys_symbol_underscore=yes - else - if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then - : - else - echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC - fi - fi - else - echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC - fi - else - echo "configure: failed program was:" >&AC_FD_CC - cat conftest.c >&AC_FD_CC - fi - rm -rf conftest* - ]) -])# AC_LTDL_SYMBOL_USCORE - - -# AC_LTDL_DLSYM_USCORE -# -------------------- -AC_DEFUN([AC_LTDL_DLSYM_USCORE], -[AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) -if test x"$ac_cv_sys_symbol_underscore" = xyes; then - if test x"$libltdl_cv_func_dlopen" = xyes || - test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then - AC_CACHE_CHECK([whether we have to add an underscore for dlsym], - [libltdl_cv_need_uscore], - [libltdl_cv_need_uscore=unknown - save_LIBS="$LIBS" - LIBS="$LIBS $LIBADD_DL" - _LT_AC_TRY_DLOPEN_SELF( - [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], - [], [libltdl_cv_need_uscore=cross]) - LIBS="$save_LIBS" - ]) - fi -fi - -if test x"$libltdl_cv_need_uscore" = xyes; then - AC_DEFINE([NEED_USCORE], [1], - [Define if dlsym() requires a leading underscore in symbol names.]) -fi -])# AC_LTDL_DLSYM_USCORE - -# AC_LTDL_FUNC_ARGZ -# ----------------- -AC_DEFUN([AC_LTDL_FUNC_ARGZ], -[AC_CHECK_HEADERS([argz.h]) - -AC_CHECK_TYPES([error_t], - [], - [AC_DEFINE([error_t], [int], - [Define to a type to use for `error_t' if it is not otherwise available.])], - [#if HAVE_ARGZ_H -# include -#endif]) - -AC_CHECK_FUNCS([argz_append argz_create_sep argz_insert argz_next argz_stringify]) -])# AC_LTDL_FUNC_ARGZ diff --git a/libltdl/aclocal.m4 b/libltdl/aclocal.m4 deleted file mode 100644 index fcc414d3d..000000000 --- a/libltdl/aclocal.m4 +++ /dev/null @@ -1,875 +0,0 @@ -# generated automatically by aclocal 1.10 -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006 Free Software Foundation, Inc. -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -m4_if(m4_PACKAGE_VERSION, [2.61],, -[m4_fatal([this file was generated for autoconf 2.61. -You have another version of autoconf. If you want to use that, -you should regenerate the build system entirely.], [63])]) - -# Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_AUTOMAKE_VERSION(VERSION) -# ---------------------------- -# Automake X.Y traces this macro to ensure aclocal.m4 has been -# generated from the m4 files accompanying Automake X.Y. -# (This private macro should not be called outside this file.) -AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.10' -dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to -dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.10], [], - [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl -]) - -# _AM_AUTOCONF_VERSION(VERSION) -# ----------------------------- -# aclocal traces this macro to find the Autoconf version. -# This is a private macro too. Using m4_define simplifies -# the logic in aclocal, which can simply ignore this definition. -m4_define([_AM_AUTOCONF_VERSION], []) - -# AM_SET_CURRENT_AUTOMAKE_VERSION -# ------------------------------- -# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. -# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. -AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.10])dnl -_AM_AUTOCONF_VERSION(m4_PACKAGE_VERSION)]) - -# AM_AUX_DIR_EXPAND -*- Autoconf -*- - -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets -# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to -# `$srcdir', `$srcdir/..', or `$srcdir/../..'. -# -# Of course, Automake must honor this variable whenever it calls a -# tool from the auxiliary directory. The problem is that $srcdir (and -# therefore $ac_aux_dir as well) can be either absolute or relative, -# depending on how configure is run. This is pretty annoying, since -# it makes $ac_aux_dir quite unusable in subdirectories: in the top -# source directory, any form will work fine, but in subdirectories a -# relative path needs to be adjusted first. -# -# $ac_aux_dir/missing -# fails when called from a subdirectory if $ac_aux_dir is relative -# $top_srcdir/$ac_aux_dir/missing -# fails if $ac_aux_dir is absolute, -# fails when called from a subdirectory in a VPATH build with -# a relative $ac_aux_dir -# -# The reason of the latter failure is that $top_srcdir and $ac_aux_dir -# are both prefixed by $srcdir. In an in-source build this is usually -# harmless because $srcdir is `.', but things will broke when you -# start a VPATH build or use an absolute $srcdir. -# -# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, -# iff we strip the leading $srcdir from $ac_aux_dir. That would be: -# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` -# and then we would define $MISSING as -# MISSING="\${SHELL} $am_aux_dir/missing" -# This will work as long as MISSING is not called from configure, because -# unfortunately $(top_srcdir) has no meaning in configure. -# However there are other variables, like CC, which are often used in -# configure, and could therefore not use this "fixed" $ac_aux_dir. -# -# Another solution, used here, is to always expand $ac_aux_dir to an -# absolute PATH. The drawback is that using absolute paths prevent a -# configured tree to be moved without reconfiguration. - -AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` -]) - -# AM_CONDITIONAL -*- Autoconf -*- - -# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 8 - -# AM_CONDITIONAL(NAME, SHELL-CONDITION) -# ------------------------------------- -# Define a conditional. -AC_DEFUN([AM_CONDITIONAL], -[AC_PREREQ(2.52)dnl - ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], - [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl -AC_SUBST([$1_TRUE])dnl -AC_SUBST([$1_FALSE])dnl -_AM_SUBST_NOTMAKE([$1_TRUE])dnl -_AM_SUBST_NOTMAKE([$1_FALSE])dnl -if $2; then - $1_TRUE= - $1_FALSE='#' -else - $1_TRUE='#' - $1_FALSE= -fi -AC_CONFIG_COMMANDS_PRE( -[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then - AC_MSG_ERROR([[conditional "$1" was never defined. -Usually this means the macro was only invoked conditionally.]]) -fi])]) - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 9 - -# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be -# written in clear, in which case automake, when reading aclocal.m4, -# will think it sees a *use*, and therefore will trigger all it's -# C support machinery. Also note that it means that autoscan, seeing -# CC etc. in the Makefile, will ask for an AC_PROG_CC use... - - -# _AM_DEPENDENCIES(NAME) -# ---------------------- -# See how the compiler implements dependency checking. -# NAME is "CC", "CXX", "GCJ", or "OBJC". -# We try a few techniques and use that to set a single cache variable. -# -# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was -# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular -# dependency, and given that the user is not expected to run this macro, -# just rely on AC_PROG_CC. -AC_DEFUN([_AM_DEPENDENCIES], -[AC_REQUIRE([AM_SET_DEPDIR])dnl -AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl -AC_REQUIRE([AM_MAKE_INCLUDE])dnl -AC_REQUIRE([AM_DEP_TRACK])dnl - -ifelse([$1], CC, [depcc="$CC" am_compiler_list=], - [$1], CXX, [depcc="$CXX" am_compiler_list=], - [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], - [$1], UPC, [depcc="$UPC" am_compiler_list=], - [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], - [depcc="$$1" am_compiler_list=]) - -AC_CACHE_CHECK([dependency style of $depcc], - [am_cv_$1_dependencies_compiler_type], -[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_$1_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` - fi - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - case $depmode in - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - none) break ;; - esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. - if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_$1_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_$1_dependencies_compiler_type=none -fi -]) -AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) -AM_CONDITIONAL([am__fastdep$1], [ - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) -]) - - -# AM_SET_DEPDIR -# ------------- -# Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES -AC_DEFUN([AM_SET_DEPDIR], -[AC_REQUIRE([AM_SET_LEADING_DOT])dnl -AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl -]) - - -# AM_DEP_TRACK -# ------------ -AC_DEFUN([AM_DEP_TRACK], -[AC_ARG_ENABLE(dependency-tracking, -[ --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors]) -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' -fi -AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -AC_SUBST([AMDEPBACKSLASH])dnl -_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl -]) - -# Generate code to set up dependency tracking. -*- Autoconf -*- - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -#serial 3 - -# _AM_OUTPUT_DEPENDENCY_COMMANDS -# ------------------------------ -AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], -[for mf in $CONFIG_FILES; do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done -done -])# _AM_OUTPUT_DEPENDENCY_COMMANDS - - -# AM_OUTPUT_DEPENDENCY_COMMANDS -# ----------------------------- -# This macro should only be invoked once -- use via AC_REQUIRE. -# -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each `.P' file that we will -# need in order to bootstrap the dependency handling code. -AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], -[AC_CONFIG_COMMANDS([depfiles], - [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) - -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 8 - -# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. -AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) - -# Do all the work for Automake. -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 12 - -# This macro actually does too much. Some checks are only needed if -# your package does certain things. But this isn't really a big deal. - -# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) -# AM_INIT_AUTOMAKE([OPTIONS]) -# ----------------------------------------------- -# The call with PACKAGE and VERSION arguments is the old style -# call (pre autoconf-2.50), which is being phased out. PACKAGE -# and VERSION should now be passed to AC_INIT and removed from -# the call to AM_INIT_AUTOMAKE. -# We support both call styles for the transition. After -# the next Automake release, Autoconf can make the AC_INIT -# arguments mandatory, and then we can depend on a new Autoconf -# release and drop the old call support. -AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.60])dnl -dnl Autoconf wants to disallow AM_ names. We explicitly allow -dnl the ones we care about. -m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl -AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl -AC_REQUIRE([AC_PROG_INSTALL])dnl -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi -AC_SUBST([CYGPATH_W]) - -# Define the identity of the package. -dnl Distinguish between old-style and new-style calls. -m4_ifval([$2], -[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl - AC_SUBST([PACKAGE], [$1])dnl - AC_SUBST([VERSION], [$2])], -[_AM_SET_OPTIONS([$1])dnl -dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. -m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, - [m4_fatal([AC_INIT should be called with package and version arguments])])dnl - AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl - AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl - -_AM_IF_OPTION([no-define],, -[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) - AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl - -# Some tools Automake needs. -AC_REQUIRE([AM_SANITY_CHECK])dnl -AC_REQUIRE([AC_ARG_PROGRAM])dnl -AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) -AM_MISSING_PROG(AUTOCONF, autoconf) -AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) -AM_MISSING_PROG(AUTOHEADER, autoheader) -AM_MISSING_PROG(MAKEINFO, makeinfo) -AM_PROG_INSTALL_SH -AM_PROG_INSTALL_STRIP -AC_REQUIRE([AM_PROG_MKDIR_P])dnl -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([AC_PROG_MAKE_SET])dnl -AC_REQUIRE([AM_SET_LEADING_DOT])dnl -_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], - [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], - [_AM_PROG_TAR([v7])])]) -_AM_IF_OPTION([no-dependencies],, -[AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES(CC)], - [define([AC_PROG_CC], - defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl -AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES(CXX)], - [define([AC_PROG_CXX], - defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl -AC_PROVIDE_IFELSE([AC_PROG_OBJC], - [_AM_DEPENDENCIES(OBJC)], - [define([AC_PROG_OBJC], - defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl -]) -]) - - -# When config.status generates a header, we must update the stamp-h file. -# This file resides in the same directory as the config header -# that is generated. The stamp files are numbered to have different names. - -# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the -# loop where config.status creates the headers, so we can generate -# our stamp files there. -AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], -[# Compute $1's index in $config_headers. -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $1 | $1:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) - -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_SH -# ------------------ -# Define $install_sh. -AC_DEFUN([AM_PROG_INSTALL_SH], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} -AC_SUBST(install_sh)]) - -# Copyright (C) 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 2 - -# Check whether the underlying file-system supports filenames -# with a leading dot. For instance MS-DOS doesn't. -AC_DEFUN([AM_SET_LEADING_DOT], -[rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null -AC_SUBST([am__leading_dot])]) - -# Check to see how 'make' treats includes. -*- Autoconf -*- - -# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 3 - -# AM_MAKE_INCLUDE() -# ----------------- -# Check to see how make treats includes. -AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo done -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# We grep out `Entering directory' and `Leaving directory' -# messages which can occur if `w' ends up in MAKEFLAGS. -# In particular we don't look at `^make:' because GNU make might -# be invoked under some other name (usually "gmake"), in which -# case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then - am__include=include - am__quote= - _am_result=GNU -fi -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then - am__include=.include - am__quote="\"" - _am_result=BSD - fi -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) - -# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- - -# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 5 - -# AM_MISSING_PROG(NAME, PROGRAM) -# ------------------------------ -AC_DEFUN([AM_MISSING_PROG], -[AC_REQUIRE([AM_MISSING_HAS_RUN]) -$1=${$1-"${am_missing_run}$2"} -AC_SUBST($1)]) - - -# AM_MISSING_HAS_RUN -# ------------------ -# Define MISSING if not defined so far and test if it supports --run. -# If it does, set am_missing_run to use it, otherwise, to nothing. -AC_DEFUN([AM_MISSING_HAS_RUN], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([missing])dnl -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" -# Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " -else - am_missing_run= - AC_MSG_WARN([`missing' script is too old or missing]) -fi -]) - -# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_MKDIR_P -# --------------- -# Check for `mkdir -p'. -AC_DEFUN([AM_PROG_MKDIR_P], -[AC_PREREQ([2.60])dnl -AC_REQUIRE([AC_PROG_MKDIR_P])dnl -dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, -dnl while keeping a definition of mkdir_p for backward compatibility. -dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. -dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of -dnl Makefile.ins that do not define MKDIR_P, so we do our own -dnl adjustment using top_builddir (which is defined more often than -dnl MKDIR_P). -AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl -case $mkdir_p in - [[\\/$]]* | ?:[[\\/]]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac -]) - -# Helper functions for option handling. -*- Autoconf -*- - -# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 3 - -# _AM_MANGLE_OPTION(NAME) -# ----------------------- -AC_DEFUN([_AM_MANGLE_OPTION], -[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) - -# _AM_SET_OPTION(NAME) -# ------------------------------ -# Set option NAME. Presently that only means defining a flag for this option. -AC_DEFUN([_AM_SET_OPTION], -[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) - -# _AM_SET_OPTIONS(OPTIONS) -# ---------------------------------- -# OPTIONS is a space-separated list of Automake options. -AC_DEFUN([_AM_SET_OPTIONS], -[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) - -# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) -# ------------------------------------------- -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -AC_DEFUN([_AM_IF_OPTION], -[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) - -# Check to make sure that the build environment is sane. -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 4 - -# AM_SANITY_CHECK -# --------------- -AC_DEFUN([AM_SANITY_CHECK], -[AC_MSG_CHECKING([whether build environment is sane]) -# Just in case -sleep 1 -echo timestamp > conftest.file -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` - if test "$[*]" = "X"; then - # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` - fi - rm -f conftest.file - if test "$[*]" != "X $srcdir/configure conftest.file" \ - && test "$[*]" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken -alias in your environment]) - fi - - test "$[2]" = conftest.file - ) -then - # Ok. - : -else - AC_MSG_ERROR([newly created file is older than distributed files! -Check your system clock]) -fi -AC_MSG_RESULT(yes)]) - -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_STRIP -# --------------------- -# One issue with vendor `install' (even GNU) is that you can't -# specify the program used to strip binaries. This is especially -# annoying in cross-compiling environments, where the build's strip -# is unlikely to handle the host's binaries. -# Fortunately install-sh will honor a STRIPPROG variable, so we -# always use install-sh in `make install-strip', and initialize -# STRIPPROG with the value of the STRIP variable (set by the user). -AC_DEFUN([AM_PROG_INSTALL_STRIP], -[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -dnl Don't test for $cross_compiling = yes, because it might be `maybe'. -if test "$cross_compiling" != no; then - AC_CHECK_TOOL([STRIP], [strip], :) -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" -AC_SUBST([INSTALL_STRIP_PROGRAM])]) - -# Copyright (C) 2006 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# _AM_SUBST_NOTMAKE(VARIABLE) -# --------------------------- -# Prevent Automake from outputing VARIABLE = @VARIABLE@ in Makefile.in. -# This macro is traced by Automake. -AC_DEFUN([_AM_SUBST_NOTMAKE]) - -# Check how to create a tarball. -*- Autoconf -*- - -# Copyright (C) 2004, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 2 - -# _AM_PROG_TAR(FORMAT) -# -------------------- -# Check how to create a tarball in format FORMAT. -# FORMAT should be one of `v7', `ustar', or `pax'. -# -# Substitute a variable $(am__tar) that is a command -# writing to stdout a FORMAT-tarball containing the directory -# $tardir. -# tardir=directory && $(am__tar) > result.tar -# -# Substitute a variable $(am__untar) that extract such -# a tarball read from stdin. -# $(am__untar) < result.tar -AC_DEFUN([_AM_PROG_TAR], -[# Always define AMTAR for backward compatibility. -AM_MISSING_PROG([AMTAR], [tar]) -m4_if([$1], [v7], - [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], - [m4_case([$1], [ustar],, [pax],, - [m4_fatal([Unknown tar format])]) -AC_MSG_CHECKING([how to create a $1 tar archive]) -# Loop over all known methods to create a tar archive until one works. -_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' -_am_tools=${am_cv_prog_tar_$1-$_am_tools} -# Do not fold the above two line into one, because Tru64 sh and -# Solaris sh will not grok spaces in the rhs of `-'. -for _am_tool in $_am_tools -do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; - do - AM_RUN_LOG([$_am_tar --version]) && break - done - am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x $1 -w "$$tardir"' - am__tar_='pax -L -x $1 -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H $1 -L' - am__tar_='find "$tardir" -print | cpio -o -H $1 -L' - am__untar='cpio -i -H $1 -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_$1}" && break - - # tar/untar a dummy directory, and stop if the command works - rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) - rm -rf conftest.dir - if test -s conftest.tar; then - AM_RUN_LOG([$am__untar /dev/null 2>&1 && break - fi -done -rm -rf conftest.dir - -AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) -AC_MSG_RESULT([$am_cv_prog_tar_$1])]) -AC_SUBST([am__tar]) -AC_SUBST([am__untar]) -]) # _AM_PROG_TAR - -m4_include([acinclude.m4]) diff --git a/libltdl/config-h.in b/libltdl/config-h.in deleted file mode 100644 index b8640710f..000000000 --- a/libltdl/config-h.in +++ /dev/null @@ -1,195 +0,0 @@ -/* config-h.in. Generated from configure.ac by autoheader. */ - -/* Define to 1 if you have the `argz_append' function. */ -#undef HAVE_ARGZ_APPEND - -/* Define to 1 if you have the `argz_create_sep' function. */ -#undef HAVE_ARGZ_CREATE_SEP - -/* Define to 1 if you have the header file. */ -#undef HAVE_ARGZ_H - -/* Define to 1 if you have the `argz_insert' function. */ -#undef HAVE_ARGZ_INSERT - -/* Define to 1 if you have the `argz_next' function. */ -#undef HAVE_ARGZ_NEXT - -/* Define to 1 if you have the `argz_stringify' function. */ -#undef HAVE_ARGZ_STRINGIFY - -/* Define to 1 if you have the header file. */ -#undef HAVE_ASSERT_H - -/* Define to 1 if you have the `bcopy' function. */ -#undef HAVE_BCOPY - -/* Define to 1 if you have the `closedir' function. */ -#undef HAVE_CLOSEDIR - -/* Define to 1 if you have the header file. */ -#undef HAVE_CTYPE_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_DIRENT_H - -/* Define if you have the GNU dld library. */ -#undef HAVE_DLD - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLD_H - -/* Define to 1 if you have the `dlerror' function. */ -#undef HAVE_DLERROR - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_DL_H - -/* Define if you have the _dyld_func_lookup function. */ -#undef HAVE_DYLD - -/* Define to 1 if you have the header file. */ -#undef HAVE_ERRNO_H - -/* Define to 1 if the system has the type `error_t'. */ -#undef HAVE_ERROR_T - -/* Define to 1 if you have the `index' function. */ -#undef HAVE_INDEX - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define if you have the libdl library or equivalent. */ -#undef HAVE_LIBDL - -/* Define to 1 if you have the header file. */ -#undef HAVE_MACH_O_DYLD_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_MALLOC_H - -/* Define to 1 if you have the `memcpy' function. */ -#undef HAVE_MEMCPY - -/* Define to 1 if you have the `memmove' function. */ -#undef HAVE_MEMMOVE - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -#undef HAVE_NDIR_H - -/* Define to 1 if you have the `opendir' function. */ -#undef HAVE_OPENDIR - -/* Define if libtool can extract symbol lists from object files. */ -#undef HAVE_PRELOADED_SYMBOLS - -/* Define to 1 if you have the `readdir' function. */ -#undef HAVE_READDIR - -/* Define to 1 if you have the `rindex' function. */ -#undef HAVE_RINDEX - -/* Define if you have the shl_load function. */ -#undef HAVE_SHL_LOAD - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDIO_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the `strchr' function. */ -#undef HAVE_STRCHR - -/* Define to 1 if you have the `strcmp' function. */ -#undef HAVE_STRCMP - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the `strrchr' function. */ -#undef HAVE_STRRCHR - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_DIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_DL_H - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#undef HAVE_SYS_NDIR_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define if the OS needs help to load dependent libraries for dlopen(). */ -#undef LTDL_DLOPEN_DEPLIBS - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LTDL_OBJDIR - -/* Define to the name of the environment variable that determines the dynamic - library search path. */ -#undef LTDL_SHLIBPATH_VAR - -/* Define to the extension used for shared libraries, say, ".so". */ -#undef LTDL_SHLIB_EXT - -/* Define to the system default library search path. */ -#undef LTDL_SYSSEARCHPATH - -/* Define if dlsym() requires a leading underscore in symbol names. */ -#undef NEED_USCORE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to a type to use for `error_t' if it is not otherwise available. */ -#undef error_t - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif diff --git a/libltdl/config.guess b/libltdl/config.guess deleted file mode 100755 index 0f0fe712a..000000000 --- a/libltdl/config.guess +++ /dev/null @@ -1,1516 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. - -timestamp='2007-03-06' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner . -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep __LP64__ >/dev/null - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - case ${UNAME_MACHINE} in - pc98) - echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:[3456]*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - EM64T | authenticamd) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo frv-unknown-linux-gnu - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips - #undef mipsel - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu - exit ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit ;; - xtensa:Linux:*:*) - echo xtensa-unknown-linux-gnu - exit ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^LIBC/{ - s: ::g - p - }'`" - test x"${LIBC}" != x && { - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit - } - test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } - ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - unknown) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/libltdl/config.h b/libltdl/config.h deleted file mode 100644 index a04820a7a..000000000 --- a/libltdl/config.h +++ /dev/null @@ -1,196 +0,0 @@ -/* config.h. Generated from config-h.in by configure. */ -/* config-h.in. Generated from configure.ac by autoheader. */ - -/* Define to 1 if you have the `argz_append' function. */ -#define HAVE_ARGZ_APPEND 1 - -/* Define to 1 if you have the `argz_create_sep' function. */ -#define HAVE_ARGZ_CREATE_SEP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ARGZ_H 1 - -/* Define to 1 if you have the `argz_insert' function. */ -#define HAVE_ARGZ_INSERT 1 - -/* Define to 1 if you have the `argz_next' function. */ -#define HAVE_ARGZ_NEXT 1 - -/* Define to 1 if you have the `argz_stringify' function. */ -#define HAVE_ARGZ_STRINGIFY 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the `bcopy' function. */ -/* #undef HAVE_BCOPY */ - -/* Define to 1 if you have the `closedir' function. */ -#define HAVE_CLOSEDIR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_CTYPE_H 1 - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#define HAVE_DIRENT_H 1 - -/* Define if you have the GNU dld library. */ -/* #undef HAVE_DLD */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLD_H */ - -/* Define to 1 if you have the `dlerror' function. */ -#define HAVE_DLERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DL_H */ - -/* Define if you have the _dyld_func_lookup function. */ -/* #undef HAVE_DYLD */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define to 1 if the system has the type `error_t'. */ -#define HAVE_ERROR_T 1 - -/* Define to 1 if you have the `index' function. */ -/* #undef HAVE_INDEX */ - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define if you have the libdl library or equivalent. */ -#define HAVE_LIBDL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACH_O_DYLD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MALLOC_H 1 - -/* Define to 1 if you have the `memcpy' function. */ -#define HAVE_MEMCPY 1 - -/* Define to 1 if you have the `memmove' function. */ -#define HAVE_MEMMOVE 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -/* #undef HAVE_NDIR_H */ - -/* Define to 1 if you have the `opendir' function. */ -#define HAVE_OPENDIR 1 - -/* Define if libtool can extract symbol lists from object files. */ -#define HAVE_PRELOADED_SYMBOLS 1 - -/* Define to 1 if you have the `readdir' function. */ -#define HAVE_READDIR 1 - -/* Define to 1 if you have the `rindex' function. */ -/* #undef HAVE_RINDEX */ - -/* Define if you have the shl_load function. */ -/* #undef HAVE_SHL_LOAD */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strchr' function. */ -#define HAVE_STRCHR 1 - -/* Define to 1 if you have the `strcmp' function. */ -#define HAVE_STRCMP 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strrchr' function. */ -#define HAVE_STRRCHR 1 - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_DL_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define if the OS needs help to load dependent libraries for dlopen(). */ -/* #undef LTDL_DLOPEN_DEPLIBS */ - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define LTDL_OBJDIR ".libs/" - -/* Define to the name of the environment variable that determines the dynamic - library search path. */ -#define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH" - -/* Define to the extension used for shared libraries, say, ".so". */ -#define LTDL_SHLIB_EXT ".so" - -/* Define to the system default library search path. */ -#define LTDL_SYSSEARCHPATH "/lib:/usr/lib:/usr/lib/atlas:/usr/local/lib:/lib/i486-linux-gnu:/usr/lib/i486-linux-gnu:/usr/local/lib" - -/* Define if dlsym() requires a leading underscore in symbol names. */ -/* #undef NEED_USCORE */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "bug-libtool@gnu.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "libltdl" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libltdl 1.2" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libltdl" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.2" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to a type to use for `error_t' if it is not otherwise available. */ -/* #undef error_t */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif diff --git a/libltdl/config.sub b/libltdl/config.sub deleted file mode 100755 index 5defff65a..000000000 --- a/libltdl/config.sub +++ /dev/null @@ -1,1622 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. - -timestamp='2007-01-18' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ - uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | mt \ - | msp430 \ - | nios | nios2 \ - | ns16k | ns32k \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ - | pyramid \ - | score \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ - | we32k \ - | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ - | z8k) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ - | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tron-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ - | xstormy16-* | xtensa-* \ - | ymp-* \ - | z8k-*) - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16c) - basic_machine=cr16c-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -zvmoe) - os=-zvmoe - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/libltdl/configure b/libltdl/configure deleted file mode 100755 index aa2994e01..000000000 --- a/libltdl/configure +++ /dev/null @@ -1,23853 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for libltdl 1.2. -# -# Report bugs to . -# -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - - - -# PATH needs CR -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -as_nl=' -' -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - { (exit 1); exit 1; } -fi - -# Work around bugs in pre-3.0 UWIN ksh. -for as_var in ENV MAIL MAILPATH -do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# CDPATH. -$as_unset CDPATH - - -if test "x$CONFIG_SHELL" = x; then - if (eval ":") 2>/dev/null; then - as_have_required=yes -else - as_have_required=no -fi - - if test $as_have_required = yes && (eval ": -(as_func_return () { - (exit \$1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = \"\$1\" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test \$exitcode = 0) || { (exit 1); exit 1; } - -( - as_lineno_1=\$LINENO - as_lineno_2=\$LINENO - test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && - test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } -") 2> /dev/null; then - : -else - as_candidate_shells= - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - case $as_dir in - /*) - for as_base in sh bash ksh sh5; do - as_candidate_shells="$as_candidate_shells $as_dir/$as_base" - done;; - esac -done -IFS=$as_save_IFS - - - for as_shell in $as_candidate_shells $SHELL; do - # Try only shells that exist, to save several forks. - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { ("$as_shell") 2> /dev/null <<\_ASEOF -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - -: -_ASEOF -}; then - CONFIG_SHELL=$as_shell - as_have_required=yes - if { "$as_shell" 2> /dev/null <<\_ASEOF -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - -: -(as_func_return () { - (exit $1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = "$1" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test $exitcode = 0) || { (exit 1); exit 1; } - -( - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } - -_ASEOF -}; then - break -fi - -fi - - done - - if test "x$CONFIG_SHELL" != x; then - for as_var in BASH_ENV ENV - do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var - done - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} -fi - - - if test $as_have_required = no; then - echo This script requires a shell more modern than all the - echo shells that I found on your system. Please install a - echo modern shell, or manually run the script under such a - echo shell if you do have one. - { (exit 1); exit 1; } -fi - - -fi - -fi - - - -(eval "as_func_return () { - (exit \$1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = \"\$1\" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test \$exitcode = 0") || { - echo No shell found that supports shell functions. - echo Please tell autoconf@gnu.org about your system, - echo including any error possibly output before this - echo message -} - - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line after each line using $LINENO; the second 'sed' - # does the real work. The second script uses 'N' to pair each - # line-number line with the line containing $LINENO, and appends - # trailing '-' during substitution so that $LINENO is not a special - # case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # scripts with optimization help from Paolo Bonzini. Blame Lee - # E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in --n*) - case `echo 'x\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - *) ECHO_C='\c';; - esac;; -*) - ECHO_N='-n';; -esac - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir -fi -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - - - -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` - ;; -esac - -echo=${ECHO-echo} -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then - # Yippee, $echo works! - : -else - # Restart under the correct shell. - exec $SHELL "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null 2>&1 && unset CDPATH - -if test -z "$ECHO"; then -if test "X${echo_test_string+set}" != Xset; then -# find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if (echo_test_string=`eval $cmd`) 2>/dev/null && - echo_test_string=`eval $cmd` && - (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null - then - break - fi - done -fi - -if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : -else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$echo" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - echo='print -r' - elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} - else - # Try using printf. - echo='printf %s\n' - if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - echo="$CONFIG_SHELL $0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$CONFIG_SHELL $0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do - if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "$0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} - else - # Oops. We lost completely, so just stick with echo. - echo=echo - fi - fi - fi - fi -fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -ECHO=$echo -if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then - ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" -fi - - - - -tagnames=${tagnames+${tagnames},}CXX - -tagnames=${tagnames+${tagnames},}F77 - -exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} - -# Identity of this package. -PACKAGE_NAME='libltdl' -PACKAGE_TARNAME='libltdl' -PACKAGE_VERSION='1.2' -PACKAGE_STRING='libltdl 1.2' -PACKAGE_BUGREPORT='bug-libtool@gnu.org' - -ac_unique_file="ltdl.c" -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif" - -ac_subst_vars='SHELL -PATH_SEPARATOR -PACKAGE_NAME -PACKAGE_TARNAME -PACKAGE_VERSION -PACKAGE_STRING -PACKAGE_BUGREPORT -exec_prefix -prefix -program_transform_name -bindir -sbindir -libexecdir -datarootdir -datadir -sysconfdir -sharedstatedir -localstatedir -includedir -oldincludedir -docdir -infodir -htmldir -dvidir -pdfdir -psdir -libdir -localedir -mandir -DEFS -ECHO_C -ECHO_N -ECHO_T -LIBS -build_alias -host_alias -target_alias -INSTALL_PROGRAM -INSTALL_SCRIPT -INSTALL_DATA -am__isrc -CYGPATH_W -PACKAGE -VERSION -ACLOCAL -AUTOCONF -AUTOMAKE -AUTOHEADER -MAKEINFO -install_sh -STRIP -INSTALL_STRIP_PROGRAM -mkdir_p -AWK -SET_MAKE -am__leading_dot -AMTAR -am__tar -am__untar -CC -CFLAGS -LDFLAGS -CPPFLAGS -ac_ct_CC -EXEEXT -OBJEXT -DEPDIR -am__include -am__quote -AMDEP_TRUE -AMDEP_FALSE -AMDEPBACKSLASH -CCDEPMODE -am__fastdepCC_TRUE -am__fastdepCC_FALSE -build -build_cpu -build_vendor -build_os -host -host_cpu -host_vendor -host_os -SED -GREP -EGREP -LN_S -ECHO -AR -RANLIB -DLLTOOL -AS -OBJDUMP -CPP -CXX -CXXFLAGS -ac_ct_CXX -CXXDEPMODE -am__fastdepCXX_TRUE -am__fastdepCXX_FALSE -CXXCPP -F77 -FFLAGS -ac_ct_F77 -LIBTOOL -LIBTOOL_DEPS -INSTALL_LTDL_TRUE -INSTALL_LTDL_FALSE -CONVENIENCE_LTDL_TRUE -CONVENIENCE_LTDL_FALSE -LIBADD_DL -LIBOBJS -LTLIBOBJS' -ac_subst_files='' - ac_precious_vars='build_alias -host_alias -target_alias -CC -CFLAGS -LDFLAGS -LIBS -CPPFLAGS -CPP -CXX -CXXFLAGS -CCC -CXXCPP -F77 -FFLAGS' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` - eval enable_$ac_feature=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` - eval enable_$ac_feature=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/[-.]/_/g'` - eval with_$ac_package=\$ac_optarg ;; - - -without-* | --without-*) - ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/[-.]/_/g'` - eval with_$ac_package=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) { echo "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } -fi - -# Be sure to have absolute directory names. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir -do - eval ac_val=\$$ac_var - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; } -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - { echo "$as_me: error: Working directory cannot be determined" >&2 - { (exit 1); exit 1; }; } -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - { echo "$as_me: error: pwd does not report name of working directory" >&2 - { (exit 1); exit 1; }; } - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$0" || -$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -echo X"$0" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 - { (exit 1); exit 1; }; } - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures libltdl 1.2 to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/libltdl] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF - -Program names: - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM run sed PROGRAM on installed program names - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of libltdl 1.2:";; - esac - cat <<\_ACEOF - -Optional Features: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors - --enable-shared[=PKGS] build shared libraries [default=yes] - --enable-static[=PKGS] build static libraries [default=yes] - --enable-fast-install[=PKGS] - optimize for fast installation [default=yes] - --disable-libtool-lock avoid locking (might break parallel builds) - --enable-ltdl-install install libltdl - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-pic try to use only PIC/non-PIC objects [default=use - both] - --with-tags[=TAGS] include additional configurations [automatic] - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if - you have headers in a nonstandard directory - CPP C preprocessor - CXX C++ compiler command - CXXFLAGS C++ compiler flags - CXXCPP C++ preprocessor - F77 Fortran 77 compiler command - FFLAGS Fortran 77 compiler flags - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to . -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -libltdl configure 1.2 -generated by GNU Autoconf 2.61 - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by libltdl $as_me 1.2, which was -generated by GNU Autoconf 2.61. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - echo "PATH: $as_dir" -done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; - 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - ac_configure_args="$ac_configure_args '$ac_arg'" - ;; - esac - done -done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - cat <<\_ASBOX -## ---------------- ## -## Cache variables. ## -## ---------------- ## -_ASBOX - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - *) $as_unset $ac_var ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - cat <<\_ASBOX -## ----------------- ## -## Output variables. ## -## ----------------- ## -_ASBOX - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------------- ## -## File substitutions. ## -## ------------------- ## -_ASBOX - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## -## confdefs.h. ## -## ----------- ## -_ASBOX - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - echo "$as_me: caught signal $ac_signal" - echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer explicitly selected file to automatically selected ones. -if test -n "$CONFIG_SITE"; then - set x "$CONFIG_SITE" -elif test "x$prefix" != xNONE; then - set x "$prefix/share/config.site" "$prefix/etc/config.site" -else - set x "$ac_default_prefix/share/config.site" \ - "$ac_default_prefix/etc/config.site" -fi -shift -for ac_site_file -do - if test -r "$ac_site_file"; then - { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 -echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 -echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 -echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 -echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 -echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } -fi - - - - - - - - - - - - - - - - - - - - - - - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - - - -## ------------------------------- ## -## Libltdl specific configuration. ## -## ------------------------------- ## - -ac_aux_dir= -for ac_dir in . "$srcdir"/.; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in . \"$srcdir\"/." >&5 -echo "$as_me: error: cannot find install-sh or install.sh in . \"$srcdir\"/." >&2;} - { (exit 1); exit 1; }; } -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - - -if test -z "$enable_ltdl_install$enable_ltdl_convenience"; then - if test -f ${srcdir}/ltmain.sh; then - # if libltdl is libtoolized, it is assumed to be stand-alone and - # installed unless the command line overrides it (tested above) - enable_ltdl_install=yes - else - { echo "$as_me:$LINENO: WARNING: *** The top-level configure must select either" >&5 -echo "$as_me: WARNING: *** The top-level configure must select either" >&2;} - { echo "$as_me:$LINENO: WARNING: *** A\"\"C_LIBLTDL_INSTALLABLE or A\"\"C_LIBLTDL_CONVENIENCE." >&5 -echo "$as_me: WARNING: *** A\"\"C_LIBLTDL_INSTALLABLE or A\"\"C_LIBLTDL_CONVENIENCE." >&2;} - { { echo "$as_me:$LINENO: error: *** Maybe you want to --enable-ltdl-install?" >&5 -echo "$as_me: error: *** Maybe you want to --enable-ltdl-install?" >&2;} - { (exit 1); exit 1; }; } - fi -fi - - -## ------------------------ ## -## Automake Initialisation. ## -## ------------------------ ## -am__api_version='1.10' - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 -echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } -if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in - ./ | .// | /cC/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - done - done - ;; -esac -done -IFS=$as_save_IFS - - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh - fi -fi -{ echo "$as_me:$LINENO: result: $INSTALL" >&5 -echo "${ECHO_T}$INSTALL" >&6; } - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5 -echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; } -# Just in case -sleep 1 -echo timestamp > conftest.file -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` - fi - rm -f conftest.file - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken -alias in your environment" >&5 -echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken -alias in your environment" >&2;} - { (exit 1); exit 1; }; } - fi - - test "$2" = conftest.file - ) -then - # Ok. - : -else - { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! -Check your system clock" >&5 -echo "$as_me: error: newly created file is older than distributed files! -Check your system clock" >&2;} - { (exit 1); exit 1; }; } -fi -{ echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } -test "$program_prefix" != NONE && - program_transform_name="s&^&$program_prefix&;$program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s&\$&$program_suffix&;$program_transform_name" -# Double any \ or $. echo might interpret backslashes. -# By default was `s,x,x', remove it if useless. -cat <<\_ACEOF >conftest.sed -s/[\\$]/&&/g;s/;s,x,x,$// -_ACEOF -program_transform_name=`echo $program_transform_name | sed -f conftest.sed` -rm -f conftest.sed - -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` - -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" -# Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " -else - am_missing_run= - { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 -echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} -fi - -{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5 -echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; } -if test -z "$MKDIR_P"; then - if test "${ac_cv_path_mkdir+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in mkdir gmkdir; do - for ac_exec_ext in '' $ac_executable_extensions; do - { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue - case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir (GNU coreutils) '* | \ - 'mkdir (coreutils) '* | \ - 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext - break 3;; - esac - done - done -done -IFS=$as_save_IFS - -fi - - if test "${ac_cv_path_mkdir+set}" = set; then - MKDIR_P="$ac_cv_path_mkdir -p" - else - # As a last resort, use the slow shell script. Don't cache a - # value for MKDIR_P within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - test -d ./--version && rmdir ./--version - MKDIR_P="$ac_install_sh -d" - fi -fi -{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5 -echo "${ECHO_T}$MKDIR_P" >&6; } - -mkdir_p="$MKDIR_P" -case $mkdir_p in - [\\/$]* | ?:[\\/]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac - -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_AWK+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AWK="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - { echo "$as_me:$LINENO: result: $AWK" >&5 -echo "${ECHO_T}$AWK" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$AWK" && break -done - -{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } -set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - SET_MAKE= -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - -rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null - -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - am__isrc=' -I$(srcdir)' - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 -echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} - { (exit 1); exit 1; }; } - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi - - -# Define the identity of the package. - PACKAGE=libltdl - VERSION=1.2 - - -# Some tools Automake needs. - -ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} - - -AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} - - -AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} - - -AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} - - -MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} - -install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} - -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { echo "$as_me:$LINENO: result: $STRIP" >&5 -echo "${ECHO_T}$STRIP" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_STRIP="strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 -echo "${ECHO_T}$ac_ct_STRIP" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" - -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -# Always define AMTAR for backward compatibility. - -AMTAR=${AMTAR-"${am_missing_run}tar"} - -am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' - - - - - -ac_config_headers="$ac_config_headers config.h:config-h.in" - - - -## ------------------ ## -## C compiler checks. ## -## ------------------ ## -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - -# Provide some information about the compiler. -echo "$as_me:$LINENO: checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (ac_try="$ac_compiler --version >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler --version >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -v >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler -v >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -V >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler -V >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 -echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -# -# List of possible output files, starting from the most likely. -# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) -# only as a last resort. b.out is created by i960 compilers. -ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' -# -# The IRIX 6 linker writes into existing files which may not be -# executable, retaining their permissions. Remove them first so a -# subsequent execution test works. -ac_rmfiles= -for ac_file in $ac_files -do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; - * ) ac_rmfiles="$ac_rmfiles $ac_file";; - esac -done -rm -f $ac_rmfiles - -if { (ac_try="$ac_link_default" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. -# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' -# in a Makefile. We should not override ac_cv_exeext if it was cached, -# so that the user can short-circuit this test for compilers unknown to -# Autoconf. -for ac_file in $ac_files '' -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; - then :; else - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - fi - # We set ac_cv_exeext here because the later test for it is not - # safe: cross compilers may not add the suffix if given an `-o' - # argument, so we may need to know it at that point already. - # Even if this section looks crufty: it has the advantage of - # actually working. - break;; - * ) - break;; - esac -done -test "$ac_cv_exeext" = no && ac_cv_exeext= - -else - ac_file='' -fi - -{ echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6; } -if test -z "$ac_file"; then - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } -fi - -ac_exeext=$ac_cv_exeext - -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -{ echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - -rm -f a.out a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } -{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6; } - -{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - break;; - * ) break;; - esac -done -else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest$ac_cv_exeext -{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6; } - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in conftest.o conftest.obj conftest.*; do - test -f "$ac_file" || continue; - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_compiler_gnu=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } -GCC=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - CFLAGS="" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 -echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_cc_c89=$ac_arg -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6; } ;; - xno) - { echo "$as_me:$LINENO: result: unsupported" >&5 -echo "${ECHO_T}unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; -esac - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -DEPDIR="${am__leading_dot}deps" - -ac_config_commands="$ac_config_commands depfiles" - - -am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo done -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 -echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; } -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# We grep out `Entering directory' and `Leaving directory' -# messages which can occur if `w' ends up in MAKEFLAGS. -# In particular we don't look at `^make:' because GNU make might -# be invoked under some other name (usually "gmake"), in which -# case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then - am__include=include - am__quote= - _am_result=GNU -fi -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then - am__include=.include - am__quote="\"" - _am_result=BSD - fi -fi - - -{ echo "$as_me:$LINENO: result: $_am_result" >&5 -echo "${ECHO_T}$_am_result" >&6; } -rm -f confinc confmf - -# Check whether --enable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then - enableval=$enable_dependency_tracking; -fi - -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' -fi - if test "x$enable_dependency_tracking" != xno; then - AMDEP_TRUE= - AMDEP_FALSE='#' -else - AMDEP_TRUE='#' - AMDEP_FALSE= -fi - - - -depcc="$CC" am_compiler_list= - -{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 -echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } -if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - case $depmode in - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - none) break ;; - esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. - if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 -echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; } -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - - - -{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 -echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; } -if test "${ac_cv_c_const+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -/* FIXME: Include the comments suggested by Paul. */ -#ifndef __cplusplus - /* Ultrix mips cc rejects this. */ - typedef int charset[2]; - const charset cs; - /* SunOS 4.1.1 cc rejects this. */ - char const *const *pcpcc; - char **ppc; - /* NEC SVR4.0.2 mips cc rejects this. */ - struct point {int x, y;}; - static struct point const zero = {0,0}; - /* AIX XL C 1.02.0.0 rejects this. - It does not let you subtract one const X* pointer from another in - an arm of an if-expression whose if-part is not a constant - expression */ - const char *g = "string"; - pcpcc = &g + (g ? g-g : 0); - /* HPUX 7.0 cc rejects these. */ - ++pcpcc; - ppc = (char**) pcpcc; - pcpcc = (char const *const *) ppc; - { /* SCO 3.2v4 cc rejects this. */ - char *t; - char const *s = 0 ? (char *) 0 : (char const *) 0; - - *t++ = 0; - if (s) return 0; - } - { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ - int x[] = {25, 17}; - const int *foo = &x[0]; - ++foo; - } - { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ - typedef const int *iptr; - iptr p = 0; - ++p; - } - { /* AIX XL C 1.02.0.0 rejects this saying - "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; }; - struct s *b; b->j = 5; - } - { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ - const int foo = 10; - if (!foo) return 0; - } - return !cs[0] && !zero.x; -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_c_const=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_c_const=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 -echo "${ECHO_T}$ac_cv_c_const" >&6; } -if test $ac_cv_c_const = no; then - -cat >>confdefs.h <<\_ACEOF -#define const -_ACEOF - -fi - -{ echo "$as_me:$LINENO: checking for inline" >&5 -echo $ECHO_N "checking for inline... $ECHO_C" >&6; } -if test "${ac_cv_c_inline+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_c_inline=no -for ac_kw in inline __inline__ __inline; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifndef __cplusplus -typedef int foo_t; -static $ac_kw foo_t static_foo () {return 0; } -$ac_kw foo_t foo () {return 0; } -#endif - -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_c_inline=$ac_kw -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - test "$ac_cv_c_inline" != no && break -done - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 -echo "${ECHO_T}$ac_cv_c_inline" >&6; } - - -case $ac_cv_c_inline in - inline | yes) ;; - *) - case $ac_cv_c_inline in - no) ac_val=;; - *) ac_val=$ac_cv_c_inline;; - esac - cat >>confdefs.h <<_ACEOF -#ifndef __cplusplus -#define inline $ac_val -#endif -_ACEOF - ;; -esac - - - -## ----------------------- ## -## Libtool initialisation. ## -## ----------------------- ## - - -# Check whether --enable-shared was given. -if test "${enable_shared+set}" = set; then - enableval=$enable_shared; p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_shared=yes -fi - - -# Check whether --enable-static was given. -if test "${enable_static+set}" = set; then - enableval=$enable_static; p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_static=yes -fi - - -# Check whether --enable-fast-install was given. -if test "${enable_fast_install+set}" = set; then - enableval=$enable_fast_install; p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_fast_install=yes -fi - - -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 -echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} - { (exit 1); exit 1; }; } - -{ echo "$as_me:$LINENO: checking build system type" >&5 -echo $ECHO_N "checking build system type... $ECHO_C" >&6; } -if test "${ac_cv_build+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 -echo "$as_me: error: cannot guess build type; you must specify one" >&2;} - { (exit 1); exit 1; }; } -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 -echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 -echo "${ECHO_T}$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 -echo "$as_me: error: invalid value of canonical build" >&2;} - { (exit 1); exit 1; }; };; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ echo "$as_me:$LINENO: checking host system type" >&5 -echo $ECHO_N "checking host system type... $ECHO_C" >&6; } -if test "${ac_cv_host+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 -echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} - { (exit 1); exit 1; }; } -fi - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 -echo "${ECHO_T}$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 -echo "$as_me: error: invalid value of canonical host" >&2;} - { (exit 1); exit 1; }; };; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - -{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 -echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; } -if test "${lt_cv_path_SED+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$lt_ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$lt_ac_prog$ac_exec_ext"; }; then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -IFS=$as_save_IFS -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && continue - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break - lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done - -fi - -SED=$lt_cv_path_SED - -{ echo "$as_me:$LINENO: result: $SED" >&5 -echo "${ECHO_T}$SED" >&6; } - -{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 -echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } -if test "${ac_cv_path_GREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Extract the first word of "grep ggrep" to use in msg output -if test -z "$GREP"; then -set dummy grep ggrep; ac_prog_name=$2 -if test "${ac_cv_path_GREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_path_GREP_found=false -# Loop through the user's path and test for each of PROGNAME-LIST -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue - # Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - echo 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - ac_count=`expr $ac_count + 1` - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - - $ac_path_GREP_found && break 3 - done -done - -done -IFS=$as_save_IFS - - -fi - -GREP="$ac_cv_path_GREP" -if test -z "$GREP"; then - { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 -echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} - { (exit 1); exit 1; }; } -fi - -else - ac_cv_path_GREP=$GREP -fi - - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 -echo "${ECHO_T}$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ echo "$as_me:$LINENO: checking for egrep" >&5 -echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - # Extract the first word of "egrep" to use in msg output -if test -z "$EGREP"; then -set dummy egrep; ac_prog_name=$2 -if test "${ac_cv_path_EGREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_path_EGREP_found=false -# Loop through the user's path and test for each of PROGNAME-LIST -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue - # Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - ac_count=`expr $ac_count + 1` - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - - $ac_path_EGREP_found && break 3 - done -done - -done -IFS=$as_save_IFS - - -fi - -EGREP="$ac_cv_path_EGREP" -if test -z "$EGREP"; then - { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 -echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} - { (exit 1); exit 1; }; } -fi - -else - ac_cv_path_EGREP=$EGREP -fi - - - fi -fi -{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 -echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - - -# Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi - -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - { echo "$as_me:$LINENO: checking for ld used by $CC" >&5 -echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; } - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - { echo "$as_me:$LINENO: checking for GNU ld" >&5 -echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; } -else - { echo "$as_me:$LINENO: checking for non-GNU ld" >&5 -echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; } -fi -if test "${lt_cv_path_LD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -echo "${ECHO_T}$LD" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi -test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 -echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} - { (exit 1); exit 1; }; } -{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 -echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; } -if test "${lt_cv_prog_gnu_ld+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; } -with_gnu_ld=$lt_cv_prog_gnu_ld - - -{ echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 -echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; } -if test "${lt_cv_ld_reload_flag+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_ld_reload_flag='-r' -fi -{ echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 -echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; } -reload_flag=$lt_cv_ld_reload_flag -case $reload_flag in -"" | " "*) ;; -*) reload_flag=" $reload_flag" ;; -esac -reload_cmds='$LD$reload_flag -o $output$reload_objs' -case $host_os in - darwin*) - if test "$GCC" = yes; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' - else - reload_cmds='$LD$reload_flag -o $output$reload_objs' - fi - ;; -esac - -{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 -echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; } -if test "${lt_cv_path_NM+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_nm_to_check="${ac_tool_prefix}nm" - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS="$lt_save_ifs" - done - test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm -fi -fi -{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 -echo "${ECHO_T}$lt_cv_path_NM" >&6; } -NM="$lt_cv_path_NM" - -{ echo "$as_me:$LINENO: checking whether ln -s works" >&5 -echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; } -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } -else - { echo "$as_me:$LINENO: result: no, using $LN_S" >&5 -echo "${ECHO_T}no, using $LN_S" >&6; } -fi - -{ echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5 -echo $ECHO_N "checking how to recognize dependent libraries... $ECHO_C" >&6; } -if test "${lt_cv_deplibs_check_method+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_file_magic_cmd='$MAGIC_CMD' -lt_cv_file_magic_test_file= -lt_cv_deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. - -case $host_os in -aix4* | aix5*) - lt_cv_deplibs_check_method=pass_all - ;; - -beos*) - lt_cv_deplibs_check_method=pass_all - ;; - -bsdi[45]*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' - lt_cv_file_magic_test_file=/shlib/libc.so - ;; - -cygwin*) - # func_win32_libid is a shell function defined in ltmain.sh - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - ;; - -mingw* | pw32*) - # Base MSYS/MinGW do not provide the 'file' command needed by - # func_win32_libid shell function, so use a weaker test based on 'objdump', - # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[3-9]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -nto-qnx*) - lt_cv_deplibs_check_method=unknown - ;; - -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; -esac - -fi -{ echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 -echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; } -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - -# Check whether --enable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then - enableval=$enable_libtool_lock; -fi - -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '#line 4531 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ -s390*-*linux*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_i386_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_x86_64_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - { echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 -echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; } -if test "${lt_cv_cc_needs_belf+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - lt_cv_cc_needs_belf=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - lt_cv_cc_needs_belf=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -fi -{ echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 -echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; } - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; -sparc*-*solaris*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) LD="${LD-ld} -m elf64_sparc" ;; - *) LD="${LD-ld} -64" ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-cygwin* | *-*-mingw* | *-*-pw32*) - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. -set dummy ${ac_tool_prefix}dlltool; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_DLLTOOL+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$DLLTOOL"; then - ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -DLLTOOL=$ac_cv_prog_DLLTOOL -if test -n "$DLLTOOL"; then - { echo "$as_me:$LINENO: result: $DLLTOOL" >&5 -echo "${ECHO_T}$DLLTOOL" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_DLLTOOL"; then - ac_ct_DLLTOOL=$DLLTOOL - # Extract the first word of "dlltool", so it can be a program name with args. -set dummy dlltool; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_DLLTOOL+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_DLLTOOL"; then - ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_DLLTOOL="dlltool" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL -if test -n "$ac_ct_DLLTOOL"; then - { echo "$as_me:$LINENO: result: $ac_ct_DLLTOOL" >&5 -echo "${ECHO_T}$ac_ct_DLLTOOL" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_DLLTOOL" = x; then - DLLTOOL="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - DLLTOOL=$ac_ct_DLLTOOL - fi -else - DLLTOOL="$ac_cv_prog_DLLTOOL" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. -set dummy ${ac_tool_prefix}as; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_AS+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$AS"; then - ac_cv_prog_AS="$AS" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AS="${ac_tool_prefix}as" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -AS=$ac_cv_prog_AS -if test -n "$AS"; then - { echo "$as_me:$LINENO: result: $AS" >&5 -echo "${ECHO_T}$AS" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_AS"; then - ac_ct_AS=$AS - # Extract the first word of "as", so it can be a program name with args. -set dummy as; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_AS+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_AS"; then - ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_AS="as" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_AS=$ac_cv_prog_ac_ct_AS -if test -n "$ac_ct_AS"; then - { echo "$as_me:$LINENO: result: $ac_ct_AS" >&5 -echo "${ECHO_T}$ac_ct_AS" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_AS" = x; then - AS="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - AS=$ac_ct_AS - fi -else - AS="$ac_cv_prog_AS" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. -set dummy ${ac_tool_prefix}objdump; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_OBJDUMP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$OBJDUMP"; then - ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -OBJDUMP=$ac_cv_prog_OBJDUMP -if test -n "$OBJDUMP"; then - { echo "$as_me:$LINENO: result: $OBJDUMP" >&5 -echo "${ECHO_T}$OBJDUMP" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OBJDUMP"; then - ac_ct_OBJDUMP=$OBJDUMP - # Extract the first word of "objdump", so it can be a program name with args. -set dummy objdump; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_OBJDUMP"; then - ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_OBJDUMP="objdump" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP -if test -n "$ac_ct_OBJDUMP"; then - { echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5 -echo "${ECHO_T}$ac_ct_OBJDUMP" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_OBJDUMP" = x; then - OBJDUMP="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - OBJDUMP=$ac_ct_OBJDUMP - fi -else - OBJDUMP="$ac_cv_prog_OBJDUMP" -fi - - ;; - -esac - -need_locks="$enable_libtool_lock" - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 -echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi - -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi - -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ echo "$as_me:$LINENO: result: $CPP" >&5 -echo "${ECHO_T}$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi - -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi - -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_header_stdc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_header_stdc=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then - : -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -rm -f conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi - - -fi -fi -{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. - - - - - - - - - -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_Header=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - - -for ac_header in dlfcn.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - { echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -else - # Is the header compilable? -{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_compiler=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6; } - -# Is the header present? -{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi - -rm -f conftest.err conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( cat <<\_ASBOX -## ---------------------------------- ## -## Report this to bug-libtool@gnu.org ## -## ---------------------------------- ## -_ASBOX - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -z "$CXX"; then - if test -n "$CCC"; then - CXX=$CCC - else - if test -n "$ac_tool_prefix"; then - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - { echo "$as_me:$LINENO: result: $CXX" >&5 -echo "${ECHO_T}$CXX" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 -echo "${ECHO_T}$ac_ct_CXX" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$ac_ct_CXX" && break -done - - if test "x$ac_ct_CXX" = x; then - CXX="g++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_ct_CXX - fi -fi - - fi -fi -# Provide some information about the compiler. -echo "$as_me:$LINENO: checking for C++ compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (ac_try="$ac_compiler --version >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler --version >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -v >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler -v >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -V >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler -V >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } -if test "${ac_cv_cxx_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_compiler_gnu=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_cxx_compiler_gnu=$ac_compiler_gnu - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } -GXX=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CXXFLAGS=${CXXFLAGS+set} -ac_save_CXXFLAGS=$CXXFLAGS -{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 -echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } -if test "${ac_cv_prog_cxx_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_save_cxx_werror_flag=$ac_cxx_werror_flag - ac_cxx_werror_flag=yes - ac_cv_prog_cxx_g=no - CXXFLAGS="-g" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_cxx_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - CXXFLAGS="" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cxx_werror_flag=$ac_save_cxx_werror_flag - CXXFLAGS="-g" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_cxx_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cxx_werror_flag=$ac_save_cxx_werror_flag -fi -{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -depcc="$CXX" am_compiler_list= - -{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 -echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } -if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CXX_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - case $depmode in - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - none) break ;; - esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. - if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CXX_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CXX_dependencies_compiler_type=none -fi - -fi -{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 -echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; } -CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then - am__fastdepCXX_TRUE= - am__fastdepCXX_FALSE='#' -else - am__fastdepCXX_TRUE='#' - am__fastdepCXX_FALSE= -fi - - - - -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 -echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } -if test -z "$CXXCPP"; then - if test "${ac_cv_prog_CXXCPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi - -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi - -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -{ echo "$as_me:$LINENO: result: $CXXCPP" >&5 -echo "${ECHO_T}$CXXCPP" >&6; } -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi - -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi - -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -fi - - -ac_ext=f -ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' -ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_f77_compiler_gnu -if test -n "$ac_tool_prefix"; then - for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$F77"; then - ac_cv_prog_F77="$F77" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_F77="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -F77=$ac_cv_prog_F77 -if test -n "$F77"; then - { echo "$as_me:$LINENO: result: $F77" >&5 -echo "${ECHO_T}$F77" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$F77" && break - done -fi -if test -z "$F77"; then - ac_ct_F77=$F77 - for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_F77"; then - ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_F77="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_F77=$ac_cv_prog_ac_ct_F77 -if test -n "$ac_ct_F77"; then - { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 -echo "${ECHO_T}$ac_ct_F77" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$ac_ct_F77" && break -done - - if test "x$ac_ct_F77" = x; then - F77="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - F77=$ac_ct_F77 - fi -fi - - -# Provide some information about the compiler. -echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (ac_try="$ac_compiler --version >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler --version >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -v >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler -v >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -V >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler -V >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -rm -f a.out - -# If we don't use `.F' as extension, the preprocessor is not run on the -# input file. (Note that this only needs to work for GNU compilers.) -ac_save_ext=$ac_ext -ac_ext=F -{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; } -if test "${ac_cv_f77_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF - program main -#ifndef __GNUC__ - choke me -#endif - - end -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_f77_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_compiler_gnu=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_f77_compiler_gnu=$ac_compiler_gnu - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; } -ac_ext=$ac_save_ext -ac_test_FFLAGS=${FFLAGS+set} -ac_save_FFLAGS=$FFLAGS -FFLAGS= -{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 -echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; } -if test "${ac_cv_prog_f77_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - FFLAGS=-g -cat >conftest.$ac_ext <<_ACEOF - program main - - end -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_f77_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_f77_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_prog_f77_g=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 -echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; } -if test "$ac_test_FFLAGS" = set; then - FFLAGS=$ac_save_FFLAGS -elif test $ac_cv_prog_f77_g = yes; then - if test "x$ac_cv_f77_compiler_gnu" = xyes; then - FFLAGS="-g -O2" - else - FFLAGS="-g" - fi -else - if test "x$ac_cv_f77_compiler_gnu" = xyes; then - FFLAGS="-O2" - else - FFLAGS= - fi -fi - -G77=`test $ac_compiler_gnu = yes && echo yes` -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! - -# find the maximum length of command line arguments -{ echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 -echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; } -if test "${lt_cv_sys_max_cmd_len+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - i=0 - teststring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ - = "XX$teststring") >/dev/null 2>&1 && - new_result=`expr "X$teststring" : ".*" 2>&1` && - lt_cv_sys_max_cmd_len=$new_result && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - teststring= - # Add a significant safety factor because C++ compilers can tack on massive - # amounts of additional arguments before passing them to the linker. - # It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi - ;; - esac - -fi - -if test -n $lt_cv_sys_max_cmd_len ; then - { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 -echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; } -else - { echo "$as_me:$LINENO: result: none" >&5 -echo "${ECHO_T}none" >&6; } -fi - - - - - -# Check for command to grab the raw symbol name followed by C symbol from nm. -{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 -echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } -if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[BCDEGRST]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([_A-Za-z][_A-Za-z0-9]*\)' - -# Transform an extracted symbol line into a proper C declaration -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[BCDT]' - ;; -cygwin* | mingw* | pw32*) - symcode='[ABCDGISTW]' - ;; -hpux*) # Its linker distinguishes data from code symbols - if test "$host_cpu" = ia64; then - symcode='[ABCDEGRST]' - fi - lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - ;; -linux* | k*bsd*-gnu) - if test "$host_cpu" = ia64; then - symcode='[ABCDGIRSTW]' - lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - fi - ;; -irix* | nonstopux*) - symcode='[BCDEGRST]' - ;; -osf*) - symcode='[BCDEGQRST]' - ;; -solaris*) - symcode='[BDRT]' - ;; -sco3.2v5*) - symcode='[DT]' - ;; -sysv4.2uw2*) - symcode='[DT]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[ABDT]' - ;; -sysv4) - symcode='[DFNSTU]' - ;; -esac - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[ABCDGIRSTW]' ;; -esac - -# Try without a prefix undercore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Now try to grab the symbols. - nlist=conftest.nm - if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 - (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if grep ' nm_test_var$' "$nlist" >/dev/null; then - if grep ' nm_test_func$' "$nlist" >/dev/null; then - cat < conftest.$ac_ext -#ifdef __cplusplus -extern "C" { -#endif - -EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' - - cat <> conftest.$ac_ext -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[] = -{ -EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext - cat <<\EOF >> conftest.$ac_ext - {0, (lt_ptr_t) 0} -}; - -#ifdef __cplusplus -} -#endif -EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" - else - echo "cannot find nm_test_func in $nlist" >&5 - fi - else - echo "cannot find nm_test_var in $nlist" >&5 - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 - fi - else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - fi - rm -f conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done - -fi - -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - { echo "$as_me:$LINENO: result: failed" >&5 -echo "${ECHO_T}failed" >&6; } -else - { echo "$as_me:$LINENO: result: ok" >&5 -echo "${ECHO_T}ok" >&6; } -fi - -{ echo "$as_me:$LINENO: checking for objdir" >&5 -echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } -if test "${lt_cv_objdir+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null -fi -{ echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 -echo "${ECHO_T}$lt_cv_objdir" >&6; } -objdir=$lt_cv_objdir - - - - - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e 1s/^X//' -sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -# Constants: -rm="rm -f" - -# Global variables: -default_ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a -ltmain="$ac_aux_dir/ltmain.sh" -ofile="$default_ofile" -with_gnu_ld="$lt_cv_prog_gnu_ld" - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. -set dummy ${ac_tool_prefix}ar; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_AR+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AR="${ac_tool_prefix}ar" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - { echo "$as_me:$LINENO: result: $AR" >&5 -echo "${ECHO_T}$AR" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_AR"; then - ac_ct_AR=$AR - # Extract the first word of "ar", so it can be a program name with args. -set dummy ar; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_AR+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_AR"; then - ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_AR="ar" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_AR=$ac_cv_prog_ac_ct_AR -if test -n "$ac_ct_AR"; then - { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 -echo "${ECHO_T}$ac_ct_AR" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_AR" = x; then - AR="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - AR=$ac_ct_AR - fi -else - AR="$ac_cv_prog_AR" -fi - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - { echo "$as_me:$LINENO: result: $RANLIB" >&5 -echo "${ECHO_T}$RANLIB" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 -echo "${ECHO_T}$ac_ct_RANLIB" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_RANLIB" = x; then - RANLIB=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - RANLIB=$ac_ct_RANLIB - fi -else - RANLIB="$ac_cv_prog_RANLIB" -fi - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { echo "$as_me:$LINENO: result: $STRIP" >&5 -echo "${ECHO_T}$STRIP" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_STRIP="strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 -echo "${ECHO_T}$ac_ct_STRIP" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru -test -z "$AS" && AS=as -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$DLLTOOL" && DLLTOOL=dlltool -test -z "$LD" && LD=ld -test -z "$LN_S" && LN_S="ln -s" -test -z "$MAGIC_CMD" && MAGIC_CMD=file -test -z "$NM" && NM=nm -test -z "$SED" && SED=sed -test -z "$OBJDUMP" && OBJDUMP=objdump -test -z "$RANLIB" && RANLIB=: -test -z "$STRIP" && STRIP=: -test -z "$ac_objext" && ac_objext=o - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" -fi - -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - -# Only perform the check for file, if the check method requires it -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - { echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 -echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; } -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/${ac_tool_prefix}file; then - lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac -fi - -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 -echo "${ECHO_T}$MAGIC_CMD" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - { echo "$as_me:$LINENO: checking for file" >&5 -echo $ECHO_N "checking for file... $ECHO_C" >&6; } -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/file; then - lt_cv_path_MAGIC_CMD="$ac_dir/file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac -fi - -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 -echo "${ECHO_T}$MAGIC_CMD" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - else - MAGIC_CMD=: - fi -fi - - fi - ;; -esac - -enable_dlopen=no -enable_win32_dll=yes - -# Check whether --enable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then - enableval=$enable_libtool_lock; -fi - -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - - -# Check whether --with-pic was given. -if test "${with_pic+set}" = set; then - withval=$with_pic; pic_mode="$withval" -else - pic_mode=default -fi - -test -z "$pic_mode" && pic_mode=default - -# Use C for the default configuration in the libtool script -tagname= -lt_save_CC="$CC" -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -objext=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}' - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* - -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* - - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... - -lt_prog_compiler_no_builtin_flag= - -if test "$GCC" = yes; then - lt_prog_compiler_no_builtin_flag=' -fno-builtin' - - -{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 -echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } -if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_rtti_exceptions=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7567: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:7571: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_rtti_exceptions=yes - fi - fi - $rm conftest* - -fi -{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } - -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then - lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" -else - : -fi - -fi - -lt_prog_compiler_wl= -lt_prog_compiler_pic= -lt_prog_compiler_static= - -{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } - - if test "$GCC" = yes; then - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_static='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - lt_prog_compiler_pic='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic='-fno-common' - ;; - - interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - ;; - - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - else - lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' - fi - ;; - darwin*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - case $cc_basename in - xlc*) - lt_prog_compiler_pic='-qnocommon' - lt_prog_compiler_wl='-Wl,' - ;; - esac - ;; - - mingw* | cygwin* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static='-non_shared' - ;; - - newsos6) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - linux* | k*bsd*-gnu) - case $cc_basename in - icc* | ecc*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fpic' - lt_prog_compiler_static='-Bstatic' - ;; - ccc*) - lt_prog_compiler_wl='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C 5.9 - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='-Wl,' - ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='' - ;; - esac - ;; - esac - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - - rdos*) - lt_prog_compiler_static='-non_shared' - ;; - - solaris*) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - case $cc_basename in - f77* | f90* | f95*) - lt_prog_compiler_wl='-Qoption ld ';; - *) - lt_prog_compiler_wl='-Wl,';; - esac - ;; - - sunos4*) - lt_prog_compiler_wl='-Qoption ld ' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic='-Kconform_pic' - lt_prog_compiler_static='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - unicos*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_can_build_shared=no - ;; - - uts4*) - lt_prog_compiler_pic='-pic' - lt_prog_compiler_static='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared=no - ;; - esac - fi - -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic" >&6; } - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic"; then - -{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_pic_works+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7857: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:7861: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works=yes - fi - fi - $rm conftest* - -fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; } - -if test x"$lt_prog_compiler_pic_works" = xyes; then - case $lt_prog_compiler_pic in - "" | " "*) ;; - *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; - esac -else - lt_prog_compiler_pic= - lt_prog_compiler_can_build_shared=no -fi - -fi -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic= - ;; - *) - lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" - ;; -esac - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" -{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_static_works+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_static_works=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works=yes - fi - else - lt_prog_compiler_static_works=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" - -fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; } - -if test x"$lt_prog_compiler_static_works" = xyes; then - : -else - lt_prog_compiler_static= -fi - - -{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } -if test "${lt_cv_prog_compiler_c_o+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7961: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:7965: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o=yes - fi - fi - chmod u+w . 2>&5 - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; } - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - { echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6; } - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } - - runpath_var= - allow_undefined_flag= - enable_shared_with_static_runtimes=no - archive_cmds= - archive_expsym_cmds= - old_archive_From_new_cmds= - old_archive_from_expsyms_cmds= - export_dynamic_flag_spec= - whole_archive_flag_spec= - thread_safe_flag_spec= - hardcode_libdir_flag_spec= - hardcode_libdir_flag_spec_ld= - hardcode_libdir_separator= - hardcode_direct=no - hardcode_minus_L=no - hardcode_shlibpath_var=unsupported - link_all_deplibs=unknown - hardcode_automatic=no - module_cmds= - module_expsym_cmds= - always_export_symbols=no - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - # Just being paranoid about ensuring that cc_basename is set. - for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - ld_shlibs=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec= - fi - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - ld_shlibs=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec='-L$libdir' - allow_undefined_flag=unsupported - always_export_symbols=no - enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs=no - fi - ;; - - interix[3-9]*) - hardcode_direct=no - hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | k*bsd*-gnu) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_addflag= - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - *) - tmp_sharedflag='-shared' ;; - esac - archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test $supports_anon_versioning = yes; then - archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - link_all_deplibs=no - else - ld_shlibs=no - fi - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - ld_shlibs=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - - if test "$ld_shlibs" = no; then - runpath_var= - hardcode_libdir_flag_spec= - export_dynamic_flag_spec= - whole_archive_flag_spec= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag=unsupported - always_export_symbols=yes - archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds='' - hardcode_direct=yes - hardcode_libdir_separator=':' - link_all_deplibs=yes - - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - hardcode_direct=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L=yes - hardcode_libdir_flag_spec='-L$libdir' - hardcode_libdir_separator= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag=' ${wl}-bernotok' - allow_undefined_flag=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec='$convenience' - archive_cmds_need_lc=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # see comment about different semantics on the GNU ld section - ld_shlibs=no - ;; - - bsdi[45]*) - export_dynamic_flag_spec=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_From_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes=yes - ;; - - darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[012]) - allow_undefined_flag='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac - archive_cmds_need_lc=no - hardcode_direct=no - hardcode_automatic=yes - hardcode_shlibpath_var=unsupported - whole_archive_flag_spec='' - link_all_deplibs=yes - if test "$GCC" = yes ; then - output_verbose_link_cmd='echo' - archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - case $cc_basename in - xlc*) - output_verbose_link_cmd='echo' - archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' - module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - ;; - *) - ld_shlibs=no - ;; - esac - fi - ;; - - dgux*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - freebsd1*) - ld_shlibs=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - export_dynamic_flag_spec='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - - hardcode_direct=yes - export_dynamic_flag_spec='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - - case $host_cpu in - hppa*64*|ia64*) - hardcode_libdir_flag_spec_ld='+b $libdir' - hardcode_direct=no - hardcode_shlibpath_var=no - ;; - *) - hardcode_direct=yes - export_dynamic_flag_spec='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_ld='-rpath $libdir' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - link_all_deplibs=yes - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - newsos6) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_shlibpath_var=no - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - hardcode_direct=yes - hardcode_shlibpath_var=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac - fi - else - ld_shlibs=no - fi - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec='-rpath $libdir' - fi - hardcode_libdir_separator=: - ;; - - solaris*) - no_undefined_flag=' -z text' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - wlarc='' - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_shlibpath_var=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - else - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' - fi - ;; - esac - link_all_deplibs=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds='$CC -r -o $output$reload_objs' - hardcode_direct=no - ;; - motorola) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - ;; - - sysv4.3*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag='${wl}-z,text' - archive_cmds_need_lc=no - hardcode_shlibpath_var=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag='${wl}-z,text' - allow_undefined_flag='${wl}-z,nodefs' - archive_cmds_need_lc=no - hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - hardcode_libdir_separator=':' - link_all_deplibs=yes - export_dynamic_flag_spec='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - *) - ld_shlibs=no - ;; - esac - fi - -{ echo "$as_me:$LINENO: result: $ld_shlibs" >&5 -echo "${ECHO_T}$ld_shlibs" >&6; } -test "$ld_shlibs" = no && can_build_shared=no - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } - $rm conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl - pic_flag=$lt_prog_compiler_pic - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag - allow_undefined_flag= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc=no - else - archive_cmds_need_lc=yes - fi - allow_undefined_flag=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - { echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 -echo "${ECHO_T}$archive_cmds_need_lc" >&6; } - ;; - esac - fi - ;; -esac - -{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" - -if test "$GCC" = yes; then - case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` - else - lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. - lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else - test -d "$lt_sys_path" && \ - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" - fi - done - lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; - for (lt_i = NF; lt_i > 0; lt_i--) { - if ($lt_i != "" && $lt_i != ".") { - if ($lt_i == "..") { - lt_count++; - } else { - if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; - } else { - lt_count--; - } - } - } - } - if (lt_foo != "") { lt_freq[lt_foo]++; } - if (lt_freq[lt_foo] == 1) { print lt_foo; } -}'` - sys_lib_search_path_spec=`echo $lt_search_path_spec` -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[123]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix[3-9]*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - shlibpath_overrides_runpath=no - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - shlibpath_overrides_runpath=yes - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } -hardcode_action= -if test -n "$hardcode_libdir_flag_spec" || \ - test -n "$runpath_var" || \ - test "X$hardcode_automatic" = "Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && - test "$hardcode_minus_L" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action=unsupported -fi -{ echo "$as_me:$LINENO: result: $hardcode_action" >&5 -echo "${ECHO_T}$hardcode_action" >&6; } - -if test "$hardcode_action" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - -striplib= -old_striplib= -{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 -echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; } -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - old_striplib="$STRIP -S" - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - ;; - *) - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - ;; - esac -fi - -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dl_dlopen=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - -fi - - ;; - - *) - { echo "$as_me:$LINENO: checking for shl_load" >&5 -echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } -if test "${ac_cv_func_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define shl_load to an innocuous variant, in case declares shl_load. - For example, HP-UX 11i declares gettimeofday. */ -#define shl_load innocuous_shl_load - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char shl_load (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef shl_load - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_shl_load || defined __stub___shl_load -choke me -#endif - -int -main () -{ -return shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_func_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_func_shl_load=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 -echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } -if test $ac_cv_func_shl_load = yes; then - lt_cv_dlopen="shl_load" -else - { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 -echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } -if test "${ac_cv_lib_dld_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load (); -int -main () -{ -return shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_lib_dld_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dld_shl_load=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } -if test $ac_cv_lib_dld_shl_load = yes; then - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" -else - { echo "$as_me:$LINENO: checking for dlopen" >&5 -echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } -if test "${ac_cv_func_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define dlopen to an innocuous variant, in case declares dlopen. - For example, HP-UX 11i declares gettimeofday. */ -#define dlopen innocuous_dlopen - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char dlopen (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef dlopen - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_dlopen || defined __stub___dlopen -choke me -#endif - -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_func_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_func_dlopen=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 -echo "${ECHO_T}$ac_cv_func_dlopen" >&6; } -if test $ac_cv_func_dlopen = yes; then - lt_cv_dlopen="dlopen" -else - { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dl_dlopen=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 -echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } -if test "${ac_cv_lib_svld_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_lib_svld_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_svld_dlopen=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } -if test $ac_cv_lib_svld_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" -else - { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 -echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } -if test "${ac_cv_lib_dld_dld_link+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dld_link (); -int -main () -{ -return dld_link (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_lib_dld_dld_link=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dld_dld_link=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } -if test $ac_cv_lib_dld_dld_link = yes; then - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" -fi - - -fi - - -fi - - -fi - - -fi - - -fi - - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 -echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; } -if test "${lt_cv_dlopen_self+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - else - puts (dlerror ()); - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self=no - fi -fi -rm -fr conftest* - - -fi -{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self" >&6; } - - if test "x$lt_cv_dlopen_self" = xyes; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 -echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; } -if test "${lt_cv_dlopen_self_static+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self_static=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - else - puts (dlerror ()); - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self_static=no - fi -fi -rm -fr conftest* - - -fi -{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; } - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - - -# Report which library types will actually be built -{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 -echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } -{ echo "$as_me:$LINENO: result: $can_build_shared" >&5 -echo "${ECHO_T}$can_build_shared" >&6; } - -{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 -echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case $host_os in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - -aix4* | aix5*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; -esac -{ echo "$as_me:$LINENO: result: $enable_shared" >&5 -echo "${ECHO_T}$enable_shared" >&6; } - -{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5 -echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes -{ echo "$as_me:$LINENO: result: $enable_static" >&5 -echo "${ECHO_T}$enable_static" >&6; } - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler \ - CC \ - LD \ - lt_prog_compiler_wl \ - lt_prog_compiler_pic \ - lt_prog_compiler_static \ - lt_prog_compiler_no_builtin_flag \ - export_dynamic_flag_spec \ - thread_safe_flag_spec \ - whole_archive_flag_spec \ - enable_shared_with_static_runtimes \ - old_archive_cmds \ - old_archive_from_new_cmds \ - predep_objects \ - postdep_objects \ - predeps \ - postdeps \ - compiler_lib_search_path \ - archive_cmds \ - archive_expsym_cmds \ - postinstall_cmds \ - postuninstall_cmds \ - old_archive_from_expsyms_cmds \ - allow_undefined_flag \ - no_undefined_flag \ - export_symbols_cmds \ - hardcode_libdir_flag_spec \ - hardcode_libdir_flag_spec_ld \ - hardcode_libdir_separator \ - hardcode_automatic \ - module_cmds \ - module_expsym_cmds \ - lt_cv_prog_compiler_c_o \ - fix_srcfile_path \ - exclude_expsyms \ - include_expsyms; do - - case $var in - old_archive_cmds | \ - old_archive_from_new_cmds | \ - archive_cmds | \ - archive_expsym_cmds | \ - module_cmds | \ - module_expsym_cmds | \ - old_archive_from_expsyms_cmds | \ - export_symbols_cmds | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="${ofile}T" - trap "$rm \"$cfgfile\"; exit 1" 1 2 15 - $rm -f "$cfgfile" - { echo "$as_me:$LINENO: creating $ofile" >&5 -echo "$as_me: creating $ofile" >&6;} - - cat <<__EOF__ >> "$cfgfile" -#! $SHELL - -# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 -# Free Software Foundation, Inc. -# -# This file is part of GNU Libtool: -# Originally by Gordon Matzigkeit , 1996 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# A sed program that does not truncate output. -SED=$lt_SED - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="$SED -e 1s/^X//" - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# The names of the tagged configurations supported by this script. -available_tags= - -# ### BEGIN LIBTOOL CONFIG - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_compiler - -# Is the compiler the GNU C compiler? -with_gcc=$GCC - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds -archive_expsym_cmds=$lt_archive_expsym_cmds -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds -module_expsym_cmds=$lt_module_expsym_cmds - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path=$lt_fix_srcfile_path - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms - -# ### END LIBTOOL CONFIG - -__EOF__ - - - case $host_os in - aix3*) - cat <<\EOF >> "$cfgfile" - -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -EOF - ;; - esac - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || \ - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - -# Check whether --with-tags was given. -if test "${with_tags+set}" = set; then - withval=$with_tags; tagnames="$withval" -fi - - -if test -f "$ltmain" && test -n "$tagnames"; then - if test ! -f "${ofile}"; then - { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 -echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} - fi - - if test -z "$LTCC"; then - eval "`$SHELL ${ofile} --config | grep '^LTCC='`" - if test -z "$LTCC"; then - { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 -echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} - else - { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 -echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} - fi - fi - if test -z "$LTCFLAGS"; then - eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" - fi - - # Extract list of available tagged configurations in $ofile. - # Note that this assumes the entire list is on one line. - available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` - - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for tagname in $tagnames; do - IFS="$lt_save_ifs" - # Check whether tagname contains only valid characters - case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in - "") ;; - *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 -echo "$as_me: error: invalid tag name: $tagname" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null - then - { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 -echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} - { (exit 1); exit 1; }; } - fi - - # Update the list of available tags. - if test -n "$tagname"; then - echo appending configuration tag \"$tagname\" to $ofile - - case $tagname in - CXX) - if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - - - -archive_cmds_need_lc_CXX=no -allow_undefined_flag_CXX= -always_export_symbols_CXX=no -archive_expsym_cmds_CXX= -export_dynamic_flag_spec_CXX= -hardcode_direct_CXX=no -hardcode_libdir_flag_spec_CXX= -hardcode_libdir_flag_spec_ld_CXX= -hardcode_libdir_separator_CXX= -hardcode_minus_L_CXX=no -hardcode_shlibpath_var_CXX=unsupported -hardcode_automatic_CXX=no -module_cmds_CXX= -module_expsym_cmds_CXX= -link_all_deplibs_CXX=unknown -old_archive_cmds_CXX=$old_archive_cmds -no_undefined_flag_CXX= -whole_archive_flag_spec_CXX= -enable_shared_with_static_runtimes_CXX=no - -# Dependencies to place before and after the object being linked: -predep_objects_CXX= -postdep_objects_CXX= -predeps_CXX= -postdeps_CXX= -compiler_lib_search_path_CXX= - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -objext_CXX=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(int, char *[]) { return(0); }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* - -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* - - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_LD=$LD -lt_save_GCC=$GCC -GCC=$GXX -lt_save_with_gnu_ld=$with_gnu_ld -lt_save_path_LD=$lt_cv_path_LD -if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx -else - $as_unset lt_cv_prog_gnu_ld -fi -if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX -else - $as_unset lt_cv_path_LD -fi -test -z "${LDCXX+set}" || LD=$LDCXX -CC=${CXX-"c++"} -compiler=$CC -compiler_CXX=$CC -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - -# We don't want -fno-exception wen compiling C++ code, so set the -# no_builtin_flag separately -if test "$GXX" = yes; then - lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' -else - lt_prog_compiler_no_builtin_flag_CXX= -fi - -if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - -# Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi - -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - { echo "$as_me:$LINENO: checking for ld used by $CC" >&5 -echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; } - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - { echo "$as_me:$LINENO: checking for GNU ld" >&5 -echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; } -else - { echo "$as_me:$LINENO: checking for non-GNU ld" >&5 -echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; } -fi -if test "${lt_cv_path_LD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -echo "${ECHO_T}$LD" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi -test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 -echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} - { (exit 1); exit 1; }; } -{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 -echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; } -if test "${lt_cv_prog_gnu_ld+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; } -with_gnu_ld=$lt_cv_prog_gnu_ld - - - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ - grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_CXX= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - -else - GXX=no - with_gnu_ld=no - wlarc= -fi - -# PORTME: fill in a description of your system's C++ link characteristics -{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } -ld_shlibs_CXX=yes -case $host_os in - aix3*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_CXX='' - hardcode_direct_CXX=yes - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - - if test "$GXX" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - hardcode_direct_CXX=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_CXX=yes - hardcode_libdir_flag_spec_CXX='-L$libdir' - hardcode_libdir_separator_CXX= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols_CXX=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_CXX='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - - archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_CXX="-z nodefs" - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_CXX=' ${wl}-bernotok' - allow_undefined_flag_CXX=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_CXX='$convenience' - archive_cmds_need_lc_CXX=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_CXX=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs_CXX=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_CXX='-L$libdir' - allow_undefined_flag_CXX=unsupported - always_export_symbols_CXX=no - enable_shared_with_static_runtimes_CXX=yes - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs_CXX=no - fi - ;; - darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[012]) - allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac - archive_cmds_need_lc_CXX=no - hardcode_direct_CXX=no - hardcode_automatic_CXX=yes - hardcode_shlibpath_var_CXX=unsupported - whole_archive_flag_spec_CXX='' - link_all_deplibs_CXX=yes - - if test "$GXX" = yes ; then - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - case $cc_basename in - xlc*) - output_verbose_link_cmd='echo' - archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' - module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - ;; - *) - ld_shlibs_CXX=no - ;; - esac - fi - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - freebsd[12]*) - # C++ shared libraries reported to be fairly broken before switch to ELF - ld_shlibs_CXX=no - ;; - freebsd-elf*) - archive_cmds_need_lc_CXX=no - ;; - freebsd* | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - ld_shlibs_CXX=yes - ;; - gnu*) - ;; - hpux9*) - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: - export_dynamic_flag_spec_CXX='${wl}-E' - hardcode_direct_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC*) - archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - case $host_cpu in - hppa*64*|ia64*) ;; - *) - export_dynamic_flag_spec_CXX='${wl}-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - ;; - *) - hardcode_direct_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case $host_cpu in - hppa*64*) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - interix[3-9]*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' - fi - fi - link_all_deplibs_CXX=yes - ;; - esac - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - ;; - linux* | k*bsd*-gnu) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - - hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc*) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - archive_cmds_need_lc_CXX=no - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - pgCC*) - # Portland Group C++ compiler - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - ;; - cxx*) - # Compaq C++ - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' - hardcode_libdir_flag_spec_CXX='-R$libdir' - whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - - # Not sure whether something based on - # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 - # would be better. - output_verbose_link_cmd='echo' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' - ;; - esac - ;; - esac - ;; - lynxos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - m88k*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - openbsd2*) - # C++ shared libraries are fairly broken - ld_shlibs_CXX=no - ;; - openbsd*) - if test -f /usr/libexec/ld.so; then - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - export_dynamic_flag_spec_CXX='${wl}-E' - whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - fi - output_verbose_link_cmd='echo' - else - ld_shlibs_CXX=no - fi - ;; - osf3*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - hardcode_libdir_separator_CXX=: - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' - - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - cxx*) - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - hardcode_libdir_separator_CXX=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - cxx*) - allow_undefined_flag_CXX=' -expect_unresolved \*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ - $rm $lib.exp' - - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - psos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - solaris*) - case $cc_basename in - CC*) - # Sun C++ 4.2, 5.x and Centerline C++ - archive_cmds_need_lc_CXX=yes - no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_shlibpath_var_CXX=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. - # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' - ;; - esac - link_all_deplibs_CXX=yes - - output_verbose_link_cmd='echo' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - no_undefined_flag_CXX=' ${wl}-z ${wl}defs' - if $CC --version | grep -v '^2\.7' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - fi - - hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - ;; - esac - fi - ;; - esac - ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag_CXX='${wl}-z,text' - archive_cmds_need_lc_CXX=no - hardcode_shlibpath_var_CXX=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - # So that behaviour is only enabled if SCOABSPATH is set to a - # non-empty value in the environment. Most likely only useful for - # creating official distributions of packages. - # This is a hack until libtool officially supports absolute path - # names for shared libraries. - no_undefined_flag_CXX='${wl}-z,text' - allow_undefined_flag_CXX='${wl}-z,nodefs' - archive_cmds_need_lc_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - export_dynamic_flag_spec_CXX='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - vxworks*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; -esac -{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 -echo "${ECHO_T}$ld_shlibs_CXX" >&6; } -test "$ld_shlibs_CXX" = no && can_build_shared=no - -GCC_CXX="$GXX" -LD_CXX="$LD" - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... - -cat > conftest.$ac_ext <&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - # The `*' in the case matches for architectures that use `case' in - # $output_verbose_cmd can trigger glob expansion during the loop - # eval without this substitution. - output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` - - for p in `eval $output_verbose_link_cmd`; do - case $p in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test $p = "-L" \ - || test $p = "-R"; then - prev=$p - continue - else - prev= - fi - - if test "$pre_test_object_deps_done" = no; then - case $p in - -L* | -R*) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$compiler_lib_search_path_CXX"; then - compiler_lib_search_path_CXX="${prev}${p}" - else - compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$postdeps_CXX"; then - postdeps_CXX="${prev}${p}" - else - postdeps_CXX="${postdeps_CXX} ${prev}${p}" - fi - fi - ;; - - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test "$pre_test_object_deps_done" = no; then - if test -z "$predep_objects_CXX"; then - predep_objects_CXX="$p" - else - predep_objects_CXX="$predep_objects_CXX $p" - fi - else - if test -z "$postdep_objects_CXX"; then - postdep_objects_CXX="$p" - else - postdep_objects_CXX="$postdep_objects_CXX $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling CXX test program" -fi - -$rm -f confest.$objext - -# PORTME: override above test on systems where it is broken -case $host_os in -interix[3-9]*) - # Interix 3.5 installs completely hosed .la files for C++, so rather than - # hack all around it, let's just trust "g++" to DTRT. - predep_objects_CXX= - postdep_objects_CXX= - postdeps_CXX= - ;; - -linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - # - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - if test "$solaris_use_stlport4" != yes; then - postdeps_CXX='-library=Cstd -library=Crun' - fi - ;; - esac - ;; - -solaris*) - case $cc_basename in - CC*) - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - if test "$solaris_use_stlport4" != yes; then - postdeps_CXX='-library=Cstd -library=Crun' - fi - ;; - esac - ;; -esac - - -case " $postdeps_CXX " in -*" -lc "*) archive_cmds_need_lc_CXX=no ;; -esac - -lt_prog_compiler_wl_CXX= -lt_prog_compiler_pic_CXX= -lt_prog_compiler_static_CXX= - -{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } - - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - fi - ;; - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' - ;; - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | cygwin* | os2* | pw32*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - lt_prog_compiler_pic_CXX='-DDLL_EXPORT' - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_CXX='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - lt_prog_compiler_pic_CXX= - ;; - interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_CXX=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - else - case $host_os in - aix4* | aix5*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - else - lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - darwin*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - case $cc_basename in - xlc*) - lt_prog_compiler_pic_CXX='-qnocommon' - lt_prog_compiler_wl_CXX='-Wl,' - ;; - esac - ;; - dgux*) - case $cc_basename in - ec++*) - lt_prog_compiler_pic_CXX='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then - lt_prog_compiler_pic_CXX='+Z' - fi - ;; - aCC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_CXX='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux* | k*bsd*-gnu) - case $cc_basename in - KCC*) - # KAI C++ Compiler - lt_prog_compiler_wl_CXX='--backend -Wl,' - lt_prog_compiler_pic_CXX='-fPIC' - ;; - icpc* | ecpc*) - # Intel C++ - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-static' - ;; - pgCC*) - # Portland Group C++ compiler. - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-fpic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - lt_prog_compiler_wl_CXX='-Qoption ld ' - ;; - esac - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - lt_prog_compiler_pic_CXX='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd* | netbsdelf*-gnu) - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - lt_prog_compiler_wl_CXX='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - lt_prog_compiler_pic_CXX='-pic' - ;; - cxx*) - # Digital/Compaq C++ - lt_prog_compiler_wl_CXX='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC*) - # Sun C++ 4.2, 5.x and Centerline C++ - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - lt_prog_compiler_wl_CXX='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - lt_prog_compiler_pic_CXX='-pic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - lcc*) - # Lucid - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - lt_prog_compiler_pic_CXX='-KPIC' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - esac - ;; - vxworks*) - ;; - *) - lt_prog_compiler_can_build_shared_CXX=no - ;; - esac - fi - -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; } - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_CXX"; then - -{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works_CXX=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12847: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:12851: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works_CXX=yes - fi - fi - $rm conftest* - -fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; } - -if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then - case $lt_prog_compiler_pic_CXX in - "" | " "*) ;; - *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; - esac -else - lt_prog_compiler_pic_CXX= - lt_prog_compiler_can_build_shared_CXX=no -fi - -fi -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_CXX= - ;; - *) - lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" - ;; -esac - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" -{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_static_works_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_static_works_CXX=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works_CXX=yes - fi - else - lt_prog_compiler_static_works_CXX=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" - -fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; } - -if test x"$lt_prog_compiler_static_works_CXX" = xyes; then - : -else - lt_prog_compiler_static_CXX= -fi - - -{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } -if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o_CXX=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12951: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:12955: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_CXX=yes - fi - fi - chmod u+w . 2>&5 - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; } - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - { echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6; } - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } - - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - case $host_os in - aix4* | aix5*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - export_symbols_cmds_CXX="$ltdll_cmds" - ;; - cygwin* | mingw*) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' - ;; - linux* | k*bsd*-gnu) - link_all_deplibs_CXX=no - ;; - *) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac - -{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 -echo "${ECHO_T}$ld_shlibs_CXX" >&6; } -test "$ld_shlibs_CXX" = no && can_build_shared=no - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_CXX" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_CXX=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_CXX in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } - $rm conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_CXX - pic_flag=$lt_prog_compiler_pic_CXX - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_CXX - allow_undefined_flag_CXX= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc_CXX=no - else - archive_cmds_need_lc_CXX=yes - fi - allow_undefined_flag_CXX=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 -echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; } - ;; - esac - fi - ;; -esac - -{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" - -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[123]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix[3-9]*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - shlibpath_overrides_runpath=no - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - shlibpath_overrides_runpath=yes - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } -hardcode_action_CXX= -if test -n "$hardcode_libdir_flag_spec_CXX" || \ - test -n "$runpath_var_CXX" || \ - test "X$hardcode_automatic_CXX" = "Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct_CXX" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && - test "$hardcode_minus_L_CXX" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_CXX=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_CXX=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_CXX=unsupported -fi -{ echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 -echo "${ECHO_T}$hardcode_action_CXX" >&6; } - -if test "$hardcode_action_CXX" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_CXX \ - CC_CXX \ - LD_CXX \ - lt_prog_compiler_wl_CXX \ - lt_prog_compiler_pic_CXX \ - lt_prog_compiler_static_CXX \ - lt_prog_compiler_no_builtin_flag_CXX \ - export_dynamic_flag_spec_CXX \ - thread_safe_flag_spec_CXX \ - whole_archive_flag_spec_CXX \ - enable_shared_with_static_runtimes_CXX \ - old_archive_cmds_CXX \ - old_archive_from_new_cmds_CXX \ - predep_objects_CXX \ - postdep_objects_CXX \ - predeps_CXX \ - postdeps_CXX \ - compiler_lib_search_path_CXX \ - archive_cmds_CXX \ - archive_expsym_cmds_CXX \ - postinstall_cmds_CXX \ - postuninstall_cmds_CXX \ - old_archive_from_expsyms_cmds_CXX \ - allow_undefined_flag_CXX \ - no_undefined_flag_CXX \ - export_symbols_cmds_CXX \ - hardcode_libdir_flag_spec_CXX \ - hardcode_libdir_flag_spec_ld_CXX \ - hardcode_libdir_separator_CXX \ - hardcode_automatic_CXX \ - module_cmds_CXX \ - module_expsym_cmds_CXX \ - lt_cv_prog_compiler_c_o_CXX \ - fix_srcfile_path_CXX \ - exclude_expsyms_CXX \ - include_expsyms_CXX; do - - case $var in - old_archive_cmds_CXX | \ - old_archive_from_new_cmds_CXX | \ - archive_cmds_CXX | \ - archive_expsym_cmds_CXX | \ - module_cmds_CXX | \ - module_expsym_cmds_CXX | \ - old_archive_from_expsyms_cmds_CXX | \ - export_symbols_cmds_CXX | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_CXX - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_compiler_CXX - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_CXX - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_CXX - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_CXX - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_CXX -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_CXX - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_CXX -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_CXX -archive_expsym_cmds=$lt_archive_expsym_cmds_CXX -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_CXX -module_expsym_cmds=$lt_module_expsym_cmds_CXX - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_CXX - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_CXX - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_CXX - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_CXX - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_CXX - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_CXX - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_CXX - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_CXX - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_CXX - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_CXX - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_CXX - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_CXX - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path=$lt_fix_srcfile_path - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_CXX - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_CXX - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_CXX - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_CXX - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC=$lt_save_CC -LDCXX=$LD -LD=$lt_save_LD -GCC=$lt_save_GCC -with_gnu_ldcxx=$with_gnu_ld -with_gnu_ld=$lt_save_with_gnu_ld -lt_cv_path_LDCXX=$lt_cv_path_LD -lt_cv_path_LD=$lt_save_path_LD -lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld -lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld - - else - tagname="" - fi - ;; - - F77) - if test -n "$F77" && test "X$F77" != "Xno"; then - -ac_ext=f -ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' -ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_f77_compiler_gnu - - -archive_cmds_need_lc_F77=no -allow_undefined_flag_F77= -always_export_symbols_F77=no -archive_expsym_cmds_F77= -export_dynamic_flag_spec_F77= -hardcode_direct_F77=no -hardcode_libdir_flag_spec_F77= -hardcode_libdir_flag_spec_ld_F77= -hardcode_libdir_separator_F77= -hardcode_minus_L_F77=no -hardcode_automatic_F77=no -module_cmds_F77= -module_expsym_cmds_F77= -link_all_deplibs_F77=unknown -old_archive_cmds_F77=$old_archive_cmds -no_undefined_flag_F77= -whole_archive_flag_spec_F77= -enable_shared_with_static_runtimes_F77=no - -# Source file extension for f77 test sources. -ac_ext=f - -# Object file extension for compiled f77 test sources. -objext=o -objext_F77=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="\ - subroutine t - return - end -" - -# Code to be used in simple link tests -lt_simple_link_test_code="\ - program t - end -" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* - -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* - - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${F77-"f77"} -compiler=$CC -compiler_F77=$CC -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - -{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 -echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } -{ echo "$as_me:$LINENO: result: $can_build_shared" >&5 -echo "${ECHO_T}$can_build_shared" >&6; } - -{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 -echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case $host_os in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; -aix4* | aix5*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; -esac -{ echo "$as_me:$LINENO: result: $enable_shared" >&5 -echo "${ECHO_T}$enable_shared" >&6; } - -{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5 -echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes -{ echo "$as_me:$LINENO: result: $enable_static" >&5 -echo "${ECHO_T}$enable_static" >&6; } - -GCC_F77="$G77" -LD_F77="$LD" - -lt_prog_compiler_wl_F77= -lt_prog_compiler_pic_F77= -lt_prog_compiler_static_F77= - -{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } - - if test "$GCC" = yes; then - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_static_F77='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_F77='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - lt_prog_compiler_pic_F77='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_F77='-fno-common' - ;; - - interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared_F77=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_F77=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_F77='-fPIC' - ;; - esac - ;; - - *) - lt_prog_compiler_pic_F77='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl_F77='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_F77='-Bstatic' - else - lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' - fi - ;; - darwin*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - case $cc_basename in - xlc*) - lt_prog_compiler_pic_F77='-qnocommon' - lt_prog_compiler_wl_F77='-Wl,' - ;; - esac - ;; - - mingw* | cygwin* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_F77='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl_F77='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_F77='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static_F77='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl_F77='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static_F77='-non_shared' - ;; - - newsos6) - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - linux* | k*bsd*-gnu) - case $cc_basename in - icc* | ecc*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-fpic' - lt_prog_compiler_static_F77='-Bstatic' - ;; - ccc*) - lt_prog_compiler_wl_F77='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static_F77='-non_shared' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C 5.9 - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - lt_prog_compiler_wl_F77='-Wl,' - ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - lt_prog_compiler_wl_F77='' - ;; - esac - ;; - esac - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl_F77='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static_F77='-non_shared' - ;; - - rdos*) - lt_prog_compiler_static_F77='-non_shared' - ;; - - solaris*) - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - case $cc_basename in - f77* | f90* | f95*) - lt_prog_compiler_wl_F77='-Qoption ld ';; - *) - lt_prog_compiler_wl_F77='-Wl,';; - esac - ;; - - sunos4*) - lt_prog_compiler_wl_F77='-Qoption ld ' - lt_prog_compiler_pic_F77='-PIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic_F77='-Kconform_pic' - lt_prog_compiler_static_F77='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - unicos*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_can_build_shared_F77=no - ;; - - uts4*) - lt_prog_compiler_pic_F77='-pic' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared_F77=no - ;; - esac - fi - -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; } - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_F77"; then - -{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_pic_works_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works_F77=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_F77" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14528: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:14532: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works_F77=yes - fi - fi - $rm conftest* - -fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; } - -if test x"$lt_prog_compiler_pic_works_F77" = xyes; then - case $lt_prog_compiler_pic_F77 in - "" | " "*) ;; - *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; - esac -else - lt_prog_compiler_pic_F77= - lt_prog_compiler_can_build_shared_F77=no -fi - -fi -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_F77= - ;; - *) - lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" - ;; -esac - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" -{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_static_works_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_static_works_F77=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works_F77=yes - fi - else - lt_prog_compiler_static_works_F77=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" - -fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; } - -if test x"$lt_prog_compiler_static_works_F77" = xyes; then - : -else - lt_prog_compiler_static_F77= -fi - - -{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } -if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o_F77=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14632: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:14636: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_F77=yes - fi - fi - chmod u+w . 2>&5 - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; } - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - { echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6; } - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } - - runpath_var= - allow_undefined_flag_F77= - enable_shared_with_static_runtimes_F77=no - archive_cmds_F77= - archive_expsym_cmds_F77= - old_archive_From_new_cmds_F77= - old_archive_from_expsyms_cmds_F77= - export_dynamic_flag_spec_F77= - whole_archive_flag_spec_F77= - thread_safe_flag_spec_F77= - hardcode_libdir_flag_spec_F77= - hardcode_libdir_flag_spec_ld_F77= - hardcode_libdir_separator_F77= - hardcode_direct_F77=no - hardcode_minus_L_F77=no - hardcode_shlibpath_var_F77=unsupported - link_all_deplibs_F77=unknown - hardcode_automatic_F77=no - module_cmds_F77= - module_expsym_cmds_F77= - always_export_symbols_F77=no - export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms_F77= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - # Just being paranoid about ensuring that cc_basename is set. - for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - ld_shlibs_F77=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_F77='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_F77= - fi - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs_F77=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_minus_L_F77=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - ld_shlibs_F77=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_F77=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs_F77=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_F77='-L$libdir' - allow_undefined_flag_F77=unsupported - always_export_symbols_F77=no - enable_shared_with_static_runtimes_F77=yes - export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs_F77=no - fi - ;; - - interix[3-9]*) - hardcode_direct_F77=no - hardcode_shlibpath_var_F77=no - hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' - export_dynamic_flag_spec_F77='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | k*bsd*-gnu) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_addflag= - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec_F77='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - *) - tmp_sharedflag='-shared' ;; - esac - archive_cmds_F77='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test $supports_anon_versioning = yes; then - archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - link_all_deplibs_F77=no - else - ld_shlibs_F77=no - fi - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - ld_shlibs_F77=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_F77=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) - ld_shlibs_F77=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' - else - ld_shlibs_F77=no - fi - ;; - esac - ;; - - sunos4*) - archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_F77=no - fi - ;; - esac - - if test "$ld_shlibs_F77" = no; then - runpath_var= - hardcode_libdir_flag_spec_F77= - export_dynamic_flag_spec_F77= - whole_archive_flag_spec_F77= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag_F77=unsupported - always_export_symbols_F77=yes - archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L_F77=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct_F77=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_F77='' - hardcode_direct_F77=yes - hardcode_libdir_separator_F77=':' - link_all_deplibs_F77=yes - - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - hardcode_direct_F77=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_F77=yes - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_libdir_separator_F77= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols_F77=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_F77='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF - program main - - end -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_f77_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_F77="-z nodefs" - archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF - program main - - end -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_f77_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_F77=' ${wl}-bernotok' - allow_undefined_flag_F77=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_F77='$convenience' - archive_cmds_need_lc_F77=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_minus_L_F77=yes - # see comment about different semantics on the GNU ld section - ld_shlibs_F77=no - ;; - - bsdi[45]*) - export_dynamic_flag_spec_F77=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec_F77=' ' - allow_undefined_flag_F77=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_From_new_cmds_F77='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds_F77='lib -OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path_F77='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes_F77=yes - ;; - - darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[012]) - allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac - archive_cmds_need_lc_F77=no - hardcode_direct_F77=no - hardcode_automatic_F77=yes - hardcode_shlibpath_var_F77=unsupported - whole_archive_flag_spec_F77='' - link_all_deplibs_F77=yes - if test "$GCC" = yes ; then - output_verbose_link_cmd='echo' - archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - case $cc_basename in - xlc*) - output_verbose_link_cmd='echo' - archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' - module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - ;; - *) - ld_shlibs_F77=no - ;; - esac - fi - ;; - - dgux*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_shlibpath_var_F77=no - ;; - - freebsd1*) - ld_shlibs_F77=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes - hardcode_minus_L_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_F77=: - hardcode_direct_F77=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_F77=yes - export_dynamic_flag_spec_F77='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_F77=: - - hardcode_direct_F77=yes - export_dynamic_flag_spec_F77='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_F77=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_F77=: - - case $host_cpu in - hppa*64*|ia64*) - hardcode_libdir_flag_spec_ld_F77='+b $libdir' - hardcode_direct_F77=no - hardcode_shlibpath_var_F77=no - ;; - *) - hardcode_direct_F77=yes - export_dynamic_flag_spec_F77='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_F77=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' - fi - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_F77=: - link_all_deplibs_F77=yes - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - newsos6) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_F77=: - hardcode_shlibpath_var_F77=no - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' - export_dynamic_flag_spec_F77='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_F77='-R$libdir' - ;; - *) - archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' - ;; - esac - fi - else - ld_shlibs_F77=no - fi - ;; - - os2*) - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_minus_L_F77=yes - allow_undefined_flag_F77=unsupported - archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag_F77=' -expect_unresolved \*' - archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_F77=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag_F77=' -expect_unresolved \*' - archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec_F77='-rpath $libdir' - fi - hardcode_libdir_separator_F77=: - ;; - - solaris*) - no_undefined_flag_F77=' -z text' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - wlarc='' - archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_shlibpath_var_F77=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - whole_archive_flag_spec_F77='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - else - whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' - fi - ;; - esac - link_all_deplibs_F77=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_direct_F77=yes - hardcode_minus_L_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds_F77='$CC -r -o $output$reload_objs' - hardcode_direct_F77=no - ;; - motorola) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var_F77=no - ;; - - sysv4.3*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_F77=no - export_dynamic_flag_spec_F77='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_F77=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs_F77=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag_F77='${wl}-z,text' - archive_cmds_need_lc_F77=no - hardcode_shlibpath_var_F77=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag_F77='${wl}-z,text' - allow_undefined_flag_F77='${wl}-z,nodefs' - archive_cmds_need_lc_F77=no - hardcode_shlibpath_var_F77=no - hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - hardcode_libdir_separator_F77=':' - link_all_deplibs_F77=yes - export_dynamic_flag_spec_F77='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_shlibpath_var_F77=no - ;; - - *) - ld_shlibs_F77=no - ;; - esac - fi - -{ echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 -echo "${ECHO_T}$ld_shlibs_F77" >&6; } -test "$ld_shlibs_F77" = no && can_build_shared=no - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_F77" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_F77=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_F77 in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } - $rm conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_F77 - pic_flag=$lt_prog_compiler_pic_F77 - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_F77 - allow_undefined_flag_F77= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc_F77=no - else - archive_cmds_need_lc_F77=yes - fi - allow_undefined_flag_F77=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 -echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; } - ;; - esac - fi - ;; -esac - -{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" - -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[123]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix[3-9]*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - shlibpath_overrides_runpath=no - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - shlibpath_overrides_runpath=yes - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } -hardcode_action_F77= -if test -n "$hardcode_libdir_flag_spec_F77" || \ - test -n "$runpath_var_F77" || \ - test "X$hardcode_automatic_F77" = "Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct_F77" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && - test "$hardcode_minus_L_F77" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_F77=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_F77=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_F77=unsupported -fi -{ echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 -echo "${ECHO_T}$hardcode_action_F77" >&6; } - -if test "$hardcode_action_F77" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_F77 \ - CC_F77 \ - LD_F77 \ - lt_prog_compiler_wl_F77 \ - lt_prog_compiler_pic_F77 \ - lt_prog_compiler_static_F77 \ - lt_prog_compiler_no_builtin_flag_F77 \ - export_dynamic_flag_spec_F77 \ - thread_safe_flag_spec_F77 \ - whole_archive_flag_spec_F77 \ - enable_shared_with_static_runtimes_F77 \ - old_archive_cmds_F77 \ - old_archive_from_new_cmds_F77 \ - predep_objects_F77 \ - postdep_objects_F77 \ - predeps_F77 \ - postdeps_F77 \ - compiler_lib_search_path_F77 \ - archive_cmds_F77 \ - archive_expsym_cmds_F77 \ - postinstall_cmds_F77 \ - postuninstall_cmds_F77 \ - old_archive_from_expsyms_cmds_F77 \ - allow_undefined_flag_F77 \ - no_undefined_flag_F77 \ - export_symbols_cmds_F77 \ - hardcode_libdir_flag_spec_F77 \ - hardcode_libdir_flag_spec_ld_F77 \ - hardcode_libdir_separator_F77 \ - hardcode_automatic_F77 \ - module_cmds_F77 \ - module_expsym_cmds_F77 \ - lt_cv_prog_compiler_c_o_F77 \ - fix_srcfile_path_F77 \ - exclude_expsyms_F77 \ - include_expsyms_F77; do - - case $var in - old_archive_cmds_F77 | \ - old_archive_from_new_cmds_F77 | \ - archive_cmds_F77 | \ - archive_expsym_cmds_F77 | \ - module_cmds_F77 | \ - module_expsym_cmds_F77 | \ - old_archive_from_expsyms_cmds_F77 | \ - export_symbols_cmds_F77 | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_F77 - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_compiler_F77 - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_F77 - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_F77 - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_F77 - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_F77 -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_F77 - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_F77 -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_F77 -archive_expsym_cmds=$lt_archive_expsym_cmds_F77 -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_F77 -module_expsym_cmds=$lt_module_expsym_cmds_F77 - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_F77 - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_F77 - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_F77 - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_F77 - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_F77 - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_F77 - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_F77 - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_F77 - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_F77 - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_F77 - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_F77 - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_F77 - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path=$lt_fix_srcfile_path - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_F77 - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_F77 - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_F77 - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_F77 - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - else - tagname="" - fi - ;; - - GCJ) - if test -n "$GCJ" && test "X$GCJ" != "Xno"; then - - -# Source file extension for Java test sources. -ac_ext=java - -# Object file extension for compiled Java test sources. -objext=o -objext_GCJ=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}" - -# Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* - -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* - - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${GCJ-"gcj"} -compiler=$CC -compiler_GCJ=$CC -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - -# GCJ did not exist at the time GCC didn't implicitly link libc in. -archive_cmds_need_lc_GCJ=no - -old_archive_cmds_GCJ=$old_archive_cmds - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... - -lt_prog_compiler_no_builtin_flag_GCJ= - -if test "$GCC" = yes; then - lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' - - -{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 -echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } -if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_rtti_exceptions=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16836: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:16840: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_rtti_exceptions=yes - fi - fi - $rm conftest* - -fi -{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } - -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then - lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" -else - : -fi - -fi - -lt_prog_compiler_wl_GCJ= -lt_prog_compiler_pic_GCJ= -lt_prog_compiler_static_GCJ= - -{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } - - if test "$GCC" = yes; then - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_static_GCJ='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_GCJ='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_GCJ='-fno-common' - ;; - - interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared_GCJ=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_GCJ=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_GCJ='-fPIC' - ;; - esac - ;; - - *) - lt_prog_compiler_pic_GCJ='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl_GCJ='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_GCJ='-Bstatic' - else - lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' - fi - ;; - darwin*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - case $cc_basename in - xlc*) - lt_prog_compiler_pic_GCJ='-qnocommon' - lt_prog_compiler_wl_GCJ='-Wl,' - ;; - esac - ;; - - mingw* | cygwin* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl_GCJ='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_GCJ='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl_GCJ='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static_GCJ='-non_shared' - ;; - - newsos6) - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - linux* | k*bsd*-gnu) - case $cc_basename in - icc* | ecc*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-fpic' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - ccc*) - lt_prog_compiler_wl_GCJ='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static_GCJ='-non_shared' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C 5.9 - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - lt_prog_compiler_wl_GCJ='-Wl,' - ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - lt_prog_compiler_wl_GCJ='' - ;; - esac - ;; - esac - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl_GCJ='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static_GCJ='-non_shared' - ;; - - rdos*) - lt_prog_compiler_static_GCJ='-non_shared' - ;; - - solaris*) - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - case $cc_basename in - f77* | f90* | f95*) - lt_prog_compiler_wl_GCJ='-Qoption ld ';; - *) - lt_prog_compiler_wl_GCJ='-Wl,';; - esac - ;; - - sunos4*) - lt_prog_compiler_wl_GCJ='-Qoption ld ' - lt_prog_compiler_pic_GCJ='-PIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic_GCJ='-Kconform_pic' - lt_prog_compiler_static_GCJ='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - unicos*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_can_build_shared_GCJ=no - ;; - - uts4*) - lt_prog_compiler_pic_GCJ='-pic' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared_GCJ=no - ;; - esac - fi - -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; } - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_GCJ"; then - -{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works_GCJ=no - ac_outfile=conftest.$ac_objext - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_GCJ" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:17126: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:17130: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works_GCJ=yes - fi - fi - $rm conftest* - -fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; } - -if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then - case $lt_prog_compiler_pic_GCJ in - "" | " "*) ;; - *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; - esac -else - lt_prog_compiler_pic_GCJ= - lt_prog_compiler_can_build_shared_GCJ=no -fi - -fi -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_GCJ= - ;; - *) - lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" - ;; -esac - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" -{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_static_works_GCJ=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works_GCJ=yes - fi - else - lt_prog_compiler_static_works_GCJ=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" - -fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; } - -if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then - : -else - lt_prog_compiler_static_GCJ= -fi - - -{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } -if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o_GCJ=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:17230: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:17234: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_GCJ=yes - fi - fi - chmod u+w . 2>&5 - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; } - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - { echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6; } - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } - - runpath_var= - allow_undefined_flag_GCJ= - enable_shared_with_static_runtimes_GCJ=no - archive_cmds_GCJ= - archive_expsym_cmds_GCJ= - old_archive_From_new_cmds_GCJ= - old_archive_from_expsyms_cmds_GCJ= - export_dynamic_flag_spec_GCJ= - whole_archive_flag_spec_GCJ= - thread_safe_flag_spec_GCJ= - hardcode_libdir_flag_spec_GCJ= - hardcode_libdir_flag_spec_ld_GCJ= - hardcode_libdir_separator_GCJ= - hardcode_direct_GCJ=no - hardcode_minus_L_GCJ=no - hardcode_shlibpath_var_GCJ=unsupported - link_all_deplibs_GCJ=unknown - hardcode_automatic_GCJ=no - module_cmds_GCJ= - module_expsym_cmds_GCJ= - always_export_symbols_GCJ=no - export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms_GCJ= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - # Just being paranoid about ensuring that cc_basename is set. - for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - ld_shlibs_GCJ=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_GCJ= - fi - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs_GCJ=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_minus_L_GCJ=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - ld_shlibs_GCJ=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_GCJ=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_GCJ='-L$libdir' - allow_undefined_flag_GCJ=unsupported - always_export_symbols_GCJ=no - enable_shared_with_static_runtimes_GCJ=yes - export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs_GCJ=no - fi - ;; - - interix[3-9]*) - hardcode_direct_GCJ=no - hardcode_shlibpath_var_GCJ=no - hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' - export_dynamic_flag_spec_GCJ='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | k*bsd*-gnu) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_addflag= - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec_GCJ='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - *) - tmp_sharedflag='-shared' ;; - esac - archive_cmds_GCJ='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test $supports_anon_versioning = yes; then - archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - link_all_deplibs_GCJ=no - else - ld_shlibs_GCJ=no - fi - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - ld_shlibs_GCJ=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) - ld_shlibs_GCJ=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - esac - ;; - - sunos4*) - archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - esac - - if test "$ld_shlibs_GCJ" = no; then - runpath_var= - hardcode_libdir_flag_spec_GCJ= - export_dynamic_flag_spec_GCJ= - whole_archive_flag_spec_GCJ= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag_GCJ=unsupported - always_export_symbols_GCJ=yes - archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L_GCJ=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct_GCJ=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_GCJ='' - hardcode_direct_GCJ=yes - hardcode_libdir_separator_GCJ=':' - link_all_deplibs_GCJ=yes - - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - hardcode_direct_GCJ=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_GCJ=yes - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_libdir_separator_GCJ= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols_GCJ=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_GCJ='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_GCJ="-z nodefs" - archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_GCJ=' ${wl}-bernotok' - allow_undefined_flag_GCJ=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_GCJ='$convenience' - archive_cmds_need_lc_GCJ=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_minus_L_GCJ=yes - # see comment about different semantics on the GNU ld section - ld_shlibs_GCJ=no - ;; - - bsdi[45]*) - export_dynamic_flag_spec_GCJ=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec_GCJ=' ' - allow_undefined_flag_GCJ=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_From_new_cmds_GCJ='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds_GCJ='lib -OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes_GCJ=yes - ;; - - darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[012]) - allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac - archive_cmds_need_lc_GCJ=no - hardcode_direct_GCJ=no - hardcode_automatic_GCJ=yes - hardcode_shlibpath_var_GCJ=unsupported - whole_archive_flag_spec_GCJ='' - link_all_deplibs_GCJ=yes - if test "$GCC" = yes ; then - output_verbose_link_cmd='echo' - archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - case $cc_basename in - xlc*) - output_verbose_link_cmd='echo' - archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' - module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - ;; - *) - ld_shlibs_GCJ=no - ;; - esac - fi - ;; - - dgux*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_shlibpath_var_GCJ=no - ;; - - freebsd1*) - ld_shlibs_GCJ=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes - hardcode_minus_L_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - hardcode_direct_GCJ=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_GCJ=yes - export_dynamic_flag_spec_GCJ='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - - hardcode_direct_GCJ=yes - export_dynamic_flag_spec_GCJ='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_GCJ=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - - case $host_cpu in - hppa*64*|ia64*) - hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' - hardcode_direct_GCJ=no - hardcode_shlibpath_var_GCJ=no - ;; - *) - hardcode_direct_GCJ=yes - export_dynamic_flag_spec_GCJ='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_GCJ=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' - fi - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - link_all_deplibs_GCJ=yes - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - newsos6) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - hardcode_shlibpath_var_GCJ=no - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' - export_dynamic_flag_spec_GCJ='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_GCJ='-R$libdir' - ;; - *) - archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' - ;; - esac - fi - else - ld_shlibs_GCJ=no - fi - ;; - - os2*) - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_minus_L_GCJ=yes - allow_undefined_flag_GCJ=unsupported - archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag_GCJ=' -expect_unresolved \*' - archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag_GCJ=' -expect_unresolved \*' - archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec_GCJ='-rpath $libdir' - fi - hardcode_libdir_separator_GCJ=: - ;; - - solaris*) - no_undefined_flag_GCJ=' -z text' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - wlarc='' - archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_shlibpath_var_GCJ=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - else - whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' - fi - ;; - esac - link_all_deplibs_GCJ=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_direct_GCJ=yes - hardcode_minus_L_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds_GCJ='$CC -r -o $output$reload_objs' - hardcode_direct_GCJ=no - ;; - motorola) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var_GCJ=no - ;; - - sysv4.3*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_GCJ=no - export_dynamic_flag_spec_GCJ='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_GCJ=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs_GCJ=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag_GCJ='${wl}-z,text' - archive_cmds_need_lc_GCJ=no - hardcode_shlibpath_var_GCJ=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag_GCJ='${wl}-z,text' - allow_undefined_flag_GCJ='${wl}-z,nodefs' - archive_cmds_need_lc_GCJ=no - hardcode_shlibpath_var_GCJ=no - hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - hardcode_libdir_separator_GCJ=':' - link_all_deplibs_GCJ=yes - export_dynamic_flag_spec_GCJ='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_shlibpath_var_GCJ=no - ;; - - *) - ld_shlibs_GCJ=no - ;; - esac - fi - -{ echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 -echo "${ECHO_T}$ld_shlibs_GCJ" >&6; } -test "$ld_shlibs_GCJ" = no && can_build_shared=no - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_GCJ" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_GCJ=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_GCJ in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } - $rm conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_GCJ - pic_flag=$lt_prog_compiler_pic_GCJ - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ - allow_undefined_flag_GCJ= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc_GCJ=no - else - archive_cmds_need_lc_GCJ=yes - fi - allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 -echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; } - ;; - esac - fi - ;; -esac - -{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" - -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[123]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix[3-9]*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - shlibpath_overrides_runpath=no - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - shlibpath_overrides_runpath=yes - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } -hardcode_action_GCJ= -if test -n "$hardcode_libdir_flag_spec_GCJ" || \ - test -n "$runpath_var_GCJ" || \ - test "X$hardcode_automatic_GCJ" = "Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct_GCJ" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && - test "$hardcode_minus_L_GCJ" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_GCJ=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_GCJ=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_GCJ=unsupported -fi -{ echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 -echo "${ECHO_T}$hardcode_action_GCJ" >&6; } - -if test "$hardcode_action_GCJ" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_GCJ \ - CC_GCJ \ - LD_GCJ \ - lt_prog_compiler_wl_GCJ \ - lt_prog_compiler_pic_GCJ \ - lt_prog_compiler_static_GCJ \ - lt_prog_compiler_no_builtin_flag_GCJ \ - export_dynamic_flag_spec_GCJ \ - thread_safe_flag_spec_GCJ \ - whole_archive_flag_spec_GCJ \ - enable_shared_with_static_runtimes_GCJ \ - old_archive_cmds_GCJ \ - old_archive_from_new_cmds_GCJ \ - predep_objects_GCJ \ - postdep_objects_GCJ \ - predeps_GCJ \ - postdeps_GCJ \ - compiler_lib_search_path_GCJ \ - archive_cmds_GCJ \ - archive_expsym_cmds_GCJ \ - postinstall_cmds_GCJ \ - postuninstall_cmds_GCJ \ - old_archive_from_expsyms_cmds_GCJ \ - allow_undefined_flag_GCJ \ - no_undefined_flag_GCJ \ - export_symbols_cmds_GCJ \ - hardcode_libdir_flag_spec_GCJ \ - hardcode_libdir_flag_spec_ld_GCJ \ - hardcode_libdir_separator_GCJ \ - hardcode_automatic_GCJ \ - module_cmds_GCJ \ - module_expsym_cmds_GCJ \ - lt_cv_prog_compiler_c_o_GCJ \ - fix_srcfile_path_GCJ \ - exclude_expsyms_GCJ \ - include_expsyms_GCJ; do - - case $var in - old_archive_cmds_GCJ | \ - old_archive_from_new_cmds_GCJ | \ - archive_cmds_GCJ | \ - archive_expsym_cmds_GCJ | \ - module_cmds_GCJ | \ - module_expsym_cmds_GCJ | \ - old_archive_from_expsyms_cmds_GCJ | \ - export_symbols_cmds_GCJ | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_GCJ - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_compiler_GCJ - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_GCJ - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_GCJ - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_GCJ - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_GCJ -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_GCJ - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_GCJ -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_GCJ -archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_GCJ -module_expsym_cmds=$lt_module_expsym_cmds_GCJ - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_GCJ - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_GCJ - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_GCJ - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_GCJ - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_GCJ - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_GCJ - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_GCJ - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_GCJ - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_GCJ - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_GCJ - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_GCJ - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path=$lt_fix_srcfile_path - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_GCJ - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_GCJ - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_GCJ - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_GCJ - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - else - tagname="" - fi - ;; - - RC) - - -# Source file extension for RC test sources. -ac_ext=rc - -# Object file extension for compiled RC test sources. -objext=o -objext_RC=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' - -# Code to be used in simple link tests -lt_simple_link_test_code="$lt_simple_compile_test_code" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* - -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* - - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${RC-"windres"} -compiler=$CC -compiler_RC=$CC -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - -lt_cv_prog_compiler_c_o_RC=yes - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_RC \ - CC_RC \ - LD_RC \ - lt_prog_compiler_wl_RC \ - lt_prog_compiler_pic_RC \ - lt_prog_compiler_static_RC \ - lt_prog_compiler_no_builtin_flag_RC \ - export_dynamic_flag_spec_RC \ - thread_safe_flag_spec_RC \ - whole_archive_flag_spec_RC \ - enable_shared_with_static_runtimes_RC \ - old_archive_cmds_RC \ - old_archive_from_new_cmds_RC \ - predep_objects_RC \ - postdep_objects_RC \ - predeps_RC \ - postdeps_RC \ - compiler_lib_search_path_RC \ - archive_cmds_RC \ - archive_expsym_cmds_RC \ - postinstall_cmds_RC \ - postuninstall_cmds_RC \ - old_archive_from_expsyms_cmds_RC \ - allow_undefined_flag_RC \ - no_undefined_flag_RC \ - export_symbols_cmds_RC \ - hardcode_libdir_flag_spec_RC \ - hardcode_libdir_flag_spec_ld_RC \ - hardcode_libdir_separator_RC \ - hardcode_automatic_RC \ - module_cmds_RC \ - module_expsym_cmds_RC \ - lt_cv_prog_compiler_c_o_RC \ - fix_srcfile_path_RC \ - exclude_expsyms_RC \ - include_expsyms_RC; do - - case $var in - old_archive_cmds_RC | \ - old_archive_from_new_cmds_RC | \ - archive_cmds_RC | \ - archive_expsym_cmds_RC | \ - module_cmds_RC | \ - module_expsym_cmds_RC | \ - old_archive_from_expsyms_cmds_RC | \ - export_symbols_cmds_RC | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_RC - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_compiler_RC - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_RC - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_RC - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_RC - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_RC -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_RC - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_RC -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_RC -archive_expsym_cmds=$lt_archive_expsym_cmds_RC -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_RC -module_expsym_cmds=$lt_module_expsym_cmds_RC - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_RC - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_RC - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_RC - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_RC - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_RC - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_RC - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_RC - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_RC - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_RC - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_RC - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_RC - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_RC - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_RC - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path=$lt_fix_srcfile_path - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_RC - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_RC - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_RC - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_RC - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - ;; - - *) - { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 -echo "$as_me: error: Unsupported tag name: $tagname" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - - # Append the new tag name to the list of available tags. - if test -n "$tagname" ; then - available_tags="$available_tags $tagname" - fi - fi - done - IFS="$lt_save_ifs" - - # Now substitute the updated list of available tags. - if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then - mv "${ofile}T" "$ofile" - chmod +x "$ofile" - else - rm -f "${ofile}T" - { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 -echo "$as_me: error: unable to update list of available tagged configurations." >&2;} - { (exit 1); exit 1; }; } - fi -fi - - - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' - -# Prevent multiple expansion - - - - - - - - - - - - - - - - - - - - - - - - - - - -ac_header_dirent=no -for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do - as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 -echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include <$ac_hdr> - -int -main () -{ -if ((DIR *) 0) -return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_Header=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 -_ACEOF - -ac_header_dirent=$ac_hdr; break -fi - -done -# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. -if test $ac_header_dirent = dirent.h; then - { echo "$as_me:$LINENO: checking for library containing opendir" >&5 -echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } -if test "${ac_cv_search_opendir+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_func_search_save_LIBS=$LIBS -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char opendir (); -int -main () -{ -return opendir (); - ; - return 0; -} -_ACEOF -for ac_lib in '' dir; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_search_opendir=$ac_res -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext - if test "${ac_cv_search_opendir+set}" = set; then - break -fi -done -if test "${ac_cv_search_opendir+set}" = set; then - : -else - ac_cv_search_opendir=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 -echo "${ECHO_T}$ac_cv_search_opendir" >&6; } -ac_res=$ac_cv_search_opendir -if test "$ac_res" != no; then - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -fi - -else - { echo "$as_me:$LINENO: checking for library containing opendir" >&5 -echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } -if test "${ac_cv_search_opendir+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_func_search_save_LIBS=$LIBS -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char opendir (); -int -main () -{ -return opendir (); - ; - return 0; -} -_ACEOF -for ac_lib in '' x; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_search_opendir=$ac_res -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext - if test "${ac_cv_search_opendir+set}" = set; then - break -fi -done -if test "${ac_cv_search_opendir+set}" = set; then - : -else - ac_cv_search_opendir=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 -echo "${ECHO_T}$ac_cv_search_opendir" >&6; } -ac_res=$ac_cv_search_opendir -if test "$ac_res" != no; then - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -fi - -fi - -# Check whether --enable-ltdl-install was given. -if test "${enable_ltdl_install+set}" = set; then - enableval=$enable_ltdl_install; -fi - - - if test x"${enable_ltdl_install-no}" != xno; then - INSTALL_LTDL_TRUE= - INSTALL_LTDL_FALSE='#' -else - INSTALL_LTDL_TRUE='#' - INSTALL_LTDL_FALSE= -fi - - if test x"${enable_ltdl_convenience-no}" != xno; then - CONVENIENCE_LTDL_TRUE= - CONVENIENCE_LTDL_FALSE='#' -else - CONVENIENCE_LTDL_TRUE='#' - CONVENIENCE_LTDL_FALSE= -fi - - - -{ echo "$as_me:$LINENO: checking which extension is used for loadable modules" >&5 -echo $ECHO_N "checking which extension is used for loadable modules... $ECHO_C" >&6; } -if test "${libltdl_cv_shlibext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - -module=yes -eval libltdl_cv_shlibext=$shrext_cmds - -fi -{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibext" >&5 -echo "${ECHO_T}$libltdl_cv_shlibext" >&6; } -if test -n "$libltdl_cv_shlibext"; then - -cat >>confdefs.h <<_ACEOF -#define LTDL_SHLIB_EXT "$libltdl_cv_shlibext" -_ACEOF - -fi - - -{ echo "$as_me:$LINENO: checking which variable specifies run-time library path" >&5 -echo $ECHO_N "checking which variable specifies run-time library path... $ECHO_C" >&6; } -if test "${libltdl_cv_shlibpath_var+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - libltdl_cv_shlibpath_var="$shlibpath_var" -fi -{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibpath_var" >&5 -echo "${ECHO_T}$libltdl_cv_shlibpath_var" >&6; } -if test -n "$libltdl_cv_shlibpath_var"; then - -cat >>confdefs.h <<_ACEOF -#define LTDL_SHLIBPATH_VAR "$libltdl_cv_shlibpath_var" -_ACEOF - -fi - - -{ echo "$as_me:$LINENO: checking for the default library search path" >&5 -echo $ECHO_N "checking for the default library search path... $ECHO_C" >&6; } -if test "${libltdl_cv_sys_search_path+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec" -fi -{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_search_path" >&5 -echo "${ECHO_T}$libltdl_cv_sys_search_path" >&6; } -if test -n "$libltdl_cv_sys_search_path"; then - sys_search_path= - for dir in $libltdl_cv_sys_search_path; do - if test -z "$sys_search_path"; then - sys_search_path="$dir" - else - sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" - fi - done - -cat >>confdefs.h <<_ACEOF -#define LTDL_SYSSEARCHPATH "$sys_search_path" -_ACEOF - -fi - -{ echo "$as_me:$LINENO: checking for objdir" >&5 -echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } -if test "${libltdl_cv_objdir+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - libltdl_cv_objdir="$objdir" - if test -n "$objdir"; then - : - else - rm -f .libs 2>/dev/null - mkdir .libs 2>/dev/null - if test -d .libs; then - libltdl_cv_objdir=.libs - else - # MS-DOS does not allow filenames that begin with a dot. - libltdl_cv_objdir=_libs - fi - rmdir .libs 2>/dev/null - fi - -fi -{ echo "$as_me:$LINENO: result: $libltdl_cv_objdir" >&5 -echo "${ECHO_T}$libltdl_cv_objdir" >&6; } - -cat >>confdefs.h <<_ACEOF -#define LTDL_OBJDIR "$libltdl_cv_objdir/" -_ACEOF - - - -{ echo "$as_me:$LINENO: checking whether libtool supports -dlopen/-dlpreopen" >&5 -echo $ECHO_N "checking whether libtool supports -dlopen/-dlpreopen... $ECHO_C" >&6; } -if test "${libltdl_cv_preloaded_symbols+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$lt_cv_sys_global_symbol_pipe"; then - libltdl_cv_preloaded_symbols=yes - else - libltdl_cv_preloaded_symbols=no - fi - -fi -{ echo "$as_me:$LINENO: result: $libltdl_cv_preloaded_symbols" >&5 -echo "${ECHO_T}$libltdl_cv_preloaded_symbols" >&6; } -if test x"$libltdl_cv_preloaded_symbols" = xyes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_PRELOADED_SYMBOLS 1 -_ACEOF - -fi - -LIBADD_DL= - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -{ echo "$as_me:$LINENO: checking for shl_load" >&5 -echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } -if test "${ac_cv_func_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define shl_load to an innocuous variant, in case declares shl_load. - For example, HP-UX 11i declares gettimeofday. */ -#define shl_load innocuous_shl_load - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char shl_load (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef shl_load - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_shl_load || defined __stub___shl_load -choke me -#endif - -int -main () -{ -return shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_func_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_func_shl_load=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 -echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } -if test $ac_cv_func_shl_load = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_SHL_LOAD 1 -_ACEOF - -else - { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 -echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } -if test "${ac_cv_lib_dld_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load (); -int -main () -{ -return shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_lib_dld_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dld_shl_load=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } -if test $ac_cv_lib_dld_shl_load = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_SHL_LOAD 1 -_ACEOF - - LIBADD_DL="$LIBADD_DL -ldld" -else - { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dl_dlopen=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } -if test $ac_cv_lib_dl_dlopen = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_LIBDL 1 -_ACEOF - - LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes" -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#if HAVE_DLFCN_H -# include -#endif - -int -main () -{ -dlopen(0, 0); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_LIBDL 1 -_ACEOF - libltdl_cv_func_dlopen="yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 -echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } -if test "${ac_cv_lib_svld_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_lib_svld_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_svld_dlopen=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } -if test $ac_cv_lib_svld_dlopen = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_LIBDL 1 -_ACEOF - - LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes" -else - { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 -echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } -if test "${ac_cv_lib_dld_dld_link+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dld_link (); -int -main () -{ -return dld_link (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_lib_dld_dld_link=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dld_dld_link=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } -if test $ac_cv_lib_dld_dld_link = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_DLD 1 -_ACEOF - - LIBADD_DL="$LIBADD_DL -ldld" -else - { echo "$as_me:$LINENO: checking for _dyld_func_lookup" >&5 -echo $ECHO_N "checking for _dyld_func_lookup... $ECHO_C" >&6; } -if test "${ac_cv_func__dyld_func_lookup+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define _dyld_func_lookup to an innocuous variant, in case declares _dyld_func_lookup. - For example, HP-UX 11i declares gettimeofday. */ -#define _dyld_func_lookup innocuous__dyld_func_lookup - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char _dyld_func_lookup (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef _dyld_func_lookup - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char _dyld_func_lookup (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub__dyld_func_lookup || defined __stub____dyld_func_lookup -choke me -#endif - -int -main () -{ -return _dyld_func_lookup (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_func__dyld_func_lookup=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_func__dyld_func_lookup=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_func__dyld_func_lookup" >&5 -echo "${ECHO_T}$ac_cv_func__dyld_func_lookup" >&6; } -if test $ac_cv_func__dyld_func_lookup = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_DYLD 1 -_ACEOF - -fi - - -fi - - -fi - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext - -fi - - -fi - - -fi - - -if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes -then - lt_save_LIBS="$LIBS" - LIBS="$LIBS $LIBADD_DL" - -for ac_func in dlerror -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_var'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - LIBS="$lt_save_LIBS" -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -{ echo "$as_me:$LINENO: checking for _ prefix in compiled symbols" >&5 -echo $ECHO_N "checking for _ prefix in compiled symbols... $ECHO_C" >&6; } -if test "${ac_cv_sys_symbol_underscore+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_sys_symbol_underscore=no - cat > conftest.$ac_ext <&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Now try to grab the symbols. - ac_nlist=conftest.nm - if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\"") >&5 - (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s "$ac_nlist"; then - # See whether the symbols have a leading underscore. - if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then - ac_cv_sys_symbol_underscore=yes - else - if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then - : - else - echo "configure: cannot find nm_test_func in $ac_nlist" >&5 - fi - fi - else - echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5 - fi - else - echo "configure: failed program was:" >&5 - cat conftest.c >&5 - fi - rm -rf conftest* - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_sys_symbol_underscore" >&5 -echo "${ECHO_T}$ac_cv_sys_symbol_underscore" >&6; } - - -if test x"$ac_cv_sys_symbol_underscore" = xyes; then - if test x"$libltdl_cv_func_dlopen" = xyes || - test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then - { echo "$as_me:$LINENO: checking whether we have to add an underscore for dlsym" >&5 -echo $ECHO_N "checking whether we have to add an underscore for dlsym... $ECHO_C" >&6; } -if test "${libltdl_cv_need_uscore+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - libltdl_cv_need_uscore=unknown - save_LIBS="$LIBS" - LIBS="$LIBS $LIBADD_DL" - if test "$cross_compiling" = yes; then : - libltdl_cv_need_uscore=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - else - puts (dlerror ()); - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;; - x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;; - x$lt_dlunknown|x*) ;; - esac - else : - # compilation failed - - fi -fi -rm -fr conftest* - - LIBS="$save_LIBS" - -fi -{ echo "$as_me:$LINENO: result: $libltdl_cv_need_uscore" >&5 -echo "${ECHO_T}$libltdl_cv_need_uscore" >&6; } - fi -fi - -if test x"$libltdl_cv_need_uscore" = xyes; then - -cat >>confdefs.h <<\_ACEOF -#define NEED_USCORE 1 -_ACEOF - -fi - - -{ echo "$as_me:$LINENO: checking whether deplibs are loaded by dlopen" >&5 -echo $ECHO_N "checking whether deplibs are loaded by dlopen... $ECHO_C" >&6; } -if test "${libltdl_cv_sys_dlopen_deplibs+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # PORTME does your system automatically load deplibs for dlopen? - # or its logical equivalent (e.g. shl_load for HP-UX < 11) - # For now, we just catch OSes we know something about -- in the - # future, we'll try test this programmatically. - libltdl_cv_sys_dlopen_deplibs=unknown - case "$host_os" in - aix3*|aix4.1.*|aix4.2.*) - # Unknown whether this is true for these versions of AIX, but - # we want this `case' here to explicitly catch those versions. - libltdl_cv_sys_dlopen_deplibs=unknown - ;; - aix[45]*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - darwin*) - # Assuming the user has installed a libdl from somewhere, this is true - # If you are looking for one http://www.opendarwin.org/projects/dlcompat - libltdl_cv_sys_dlopen_deplibs=yes - ;; - freebsd* | dragonfly*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - gnu* | linux* | k*bsd*-gnu) - # GNU and its variants, using gnu ld.so (Glibc) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - hpux10*|hpux11*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - interix*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - irix[12345]*|irix6.[01]*) - # Catch all versions of IRIX before 6.2, and indicate that we don't - # know how it worked for any of those versions. - libltdl_cv_sys_dlopen_deplibs=unknown - ;; - irix*) - # The case above catches anything before 6.2, and it's known that - # at 6.2 and later dlopen does load deplibs. - libltdl_cv_sys_dlopen_deplibs=yes - ;; - netbsd* | netbsdelf*-gnu) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - openbsd*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - osf[1234]*) - # dlopen did load deplibs (at least at 4.x), but until the 5.x series, - # it did *not* use an RPATH in a shared library to find objects the - # library depends on, so we explictly say `no'. - libltdl_cv_sys_dlopen_deplibs=no - ;; - osf5.0|osf5.0a|osf5.1) - # dlopen *does* load deplibs and with the right loader patch applied - # it even uses RPATH in a shared library to search for shared objects - # that the library depends on, but there's no easy way to know if that - # patch is installed. Since this is the case, all we can really - # say is unknown -- it depends on the patch being installed. If - # it is, this changes to `yes'. Without it, it would be `no'. - libltdl_cv_sys_dlopen_deplibs=unknown - ;; - osf*) - # the two cases above should catch all versions of osf <= 5.1. Read - # the comments above for what we know about them. - # At > 5.1, deplibs are loaded *and* any RPATH in a shared library - # is used to find them so we can finally say `yes'. - libltdl_cv_sys_dlopen_deplibs=yes - ;; - solaris*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - libltdl_cv_sys_dlopen_deplibs=yes - ;; - esac - -fi -{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_dlopen_deplibs" >&5 -echo "${ECHO_T}$libltdl_cv_sys_dlopen_deplibs" >&6; } -if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then - -cat >>confdefs.h <<\_ACEOF -#define LTDL_DLOPEN_DEPLIBS 1 -_ACEOF - -fi - - -for ac_header in argz.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - { echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -else - # Is the header compilable? -{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_compiler=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6; } - -# Is the header present? -{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi - -rm -f conftest.err conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( cat <<\_ASBOX -## ---------------------------------- ## -## Report this to bug-libtool@gnu.org ## -## ---------------------------------- ## -_ASBOX - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -{ echo "$as_me:$LINENO: checking for error_t" >&5 -echo $ECHO_N "checking for error_t... $ECHO_C" >&6; } -if test "${ac_cv_type_error_t+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#if HAVE_ARGZ_H -# include -#endif - -typedef error_t ac__type_new_; -int -main () -{ -if ((ac__type_new_ *) 0) - return 0; -if (sizeof (ac__type_new_)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_type_error_t=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_error_t=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_type_error_t" >&5 -echo "${ECHO_T}$ac_cv_type_error_t" >&6; } -if test $ac_cv_type_error_t = yes; then - -cat >>confdefs.h <<_ACEOF -#define HAVE_ERROR_T 1 -_ACEOF - - -else - -cat >>confdefs.h <<\_ACEOF -#define error_t int -_ACEOF - -fi - - - - - - - -for ac_func in argz_append argz_create_sep argz_insert argz_next argz_stringify -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_var'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - - - - - - - - - - - - - - - - - - - - - - - - - - - -for ac_header in assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ - stdio.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - { echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -else - # Is the header compilable? -{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_compiler=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6; } - -# Is the header present? -{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi - -rm -f conftest.err conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( cat <<\_ASBOX -## ---------------------------------- ## -## Report this to bug-libtool@gnu.org ## -## ---------------------------------- ## -_ASBOX - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - - - - -for ac_header in dl.h sys/dl.h dld.h mach-o/dyld.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - { echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -else - # Is the header compilable? -{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_compiler=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6; } - -# Is the header present? -{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi - -rm -f conftest.err conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( cat <<\_ASBOX -## ---------------------------------- ## -## Report this to bug-libtool@gnu.org ## -## ---------------------------------- ## -_ASBOX - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - - -for ac_header in string.h strings.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - { echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -else - # Is the header compilable? -{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_compiler=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6; } - -# Is the header present? -{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi - -rm -f conftest.err conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( cat <<\_ASBOX -## ---------------------------------- ## -## Report this to bug-libtool@gnu.org ## -## ---------------------------------- ## -_ASBOX - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - break -fi - -done - - - - -for ac_func in strchr index -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_var'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - break -fi -done - - - -for ac_func in strrchr rindex -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_var'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - break -fi -done - - - -for ac_func in memcpy bcopy -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_var'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - break -fi -done - - - -for ac_func in memmove strcmp -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_var'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - - - -for ac_func in closedir opendir readdir -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_var'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - - - -## -------- ## -## Outputs. ## -## -------- ## -ac_config_files="$ac_config_files Makefile" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - *) $as_unset $ac_var ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && - { echo "$as_me:$LINENO: updating cache $cache_file" >&5 -echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file - else - { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 -echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -DEFS=-DHAVE_CONFIG_H - -ac_libobjs= -ac_ltlibobjs= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - -if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi -if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi -if test -z "${INSTALL_LTDL_TRUE}" && test -z "${INSTALL_LTDL_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"INSTALL_LTDL\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"INSTALL_LTDL\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi -if test -z "${CONVENIENCE_LTDL_TRUE}" && test -z "${CONVENIENCE_LTDL_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"CONVENIENCE_LTDL\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"CONVENIENCE_LTDL\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi - -: ${CONFIG_STATUS=./config.status} -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 -echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - - - -# PATH needs CR -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -as_nl=' -' -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - { (exit 1); exit 1; } -fi - -# Work around bugs in pre-3.0 UWIN ksh. -for as_var in ENV MAIL MAILPATH -do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# CDPATH. -$as_unset CDPATH - - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line after each line using $LINENO; the second 'sed' - # does the real work. The second script uses 'N' to pair each - # line-number line with the line containing $LINENO, and appends - # trailing '-' during substitution so that $LINENO is not a special - # case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # scripts with optimization help from Paolo Bonzini. Blame Lee - # E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in --n*) - case `echo 'x\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - *) ECHO_C='\c';; - esac;; -*) - ECHO_N='-n';; -esac - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir -fi -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 - -# Save the log message, to keep $[0] and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by libltdl $as_me 1.2, which was -generated by GNU Autoconf 2.61. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF -# Files that config.status was made for. -config_files="$ac_config_files" -config_headers="$ac_config_headers" -config_commands="$ac_config_commands" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. - -Usage: $0 [OPTIONS] [FILE]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - --header=FILE[:TEMPLATE] - instantiate the configuration header FILE - -Configuration files: -$config_files - -Configuration headers: -$config_headers - -Configuration commands: -$config_commands - -Report bugs to ." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -ac_cs_version="\\ -libltdl config.status 1.2 -configured by $0, generated by GNU Autoconf 2.61, - with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" - -Copyright (C) 2006 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -INSTALL='$INSTALL' -MKDIR_P='$MKDIR_P' -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If no file are specified by the user, then we need to provide default -# value. By we need to know if files were specified by the user. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - echo "$ac_cs_version"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - CONFIG_FILES="$CONFIG_FILES $ac_optarg" - ac_need_defaults=false;; - --header | --heade | --head | --hea ) - $ac_shift - CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" - ac_need_defaults=false;; - --he | --h) - # Conflict between --help and --header - { echo "$as_me: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; };; - --help | --hel | -h ) - echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) { echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } ;; - - *) ac_config_targets="$ac_config_targets $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -if \$ac_cs_recheck; then - echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 - CONFIG_SHELL=$SHELL - export CONFIG_SHELL - exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -# -# INIT-COMMANDS -# -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config-h.in" ;; - "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - - *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= - trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status -' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || -{ - echo "$me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } -} - -# -# Set up the sed scripts for CONFIG_FILES section. -# - -# No need to generate the scripts if there are no CONFIG_FILES. -# This happens for instance when ./config.status config.h -if test -n "$CONFIG_FILES"; then - -_ACEOF - - - -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - cat >conf$$subs.sed <<_ACEOF -SHELL!$SHELL$ac_delim -PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim -PACKAGE_NAME!$PACKAGE_NAME$ac_delim -PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim -PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim -PACKAGE_STRING!$PACKAGE_STRING$ac_delim -PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim -exec_prefix!$exec_prefix$ac_delim -prefix!$prefix$ac_delim -program_transform_name!$program_transform_name$ac_delim -bindir!$bindir$ac_delim -sbindir!$sbindir$ac_delim -libexecdir!$libexecdir$ac_delim -datarootdir!$datarootdir$ac_delim -datadir!$datadir$ac_delim -sysconfdir!$sysconfdir$ac_delim -sharedstatedir!$sharedstatedir$ac_delim -localstatedir!$localstatedir$ac_delim -includedir!$includedir$ac_delim -oldincludedir!$oldincludedir$ac_delim -docdir!$docdir$ac_delim -infodir!$infodir$ac_delim -htmldir!$htmldir$ac_delim -dvidir!$dvidir$ac_delim -pdfdir!$pdfdir$ac_delim -psdir!$psdir$ac_delim -libdir!$libdir$ac_delim -localedir!$localedir$ac_delim -mandir!$mandir$ac_delim -DEFS!$DEFS$ac_delim -ECHO_C!$ECHO_C$ac_delim -ECHO_N!$ECHO_N$ac_delim -ECHO_T!$ECHO_T$ac_delim -LIBS!$LIBS$ac_delim -build_alias!$build_alias$ac_delim -host_alias!$host_alias$ac_delim -target_alias!$target_alias$ac_delim -INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim -INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim -INSTALL_DATA!$INSTALL_DATA$ac_delim -am__isrc!$am__isrc$ac_delim -CYGPATH_W!$CYGPATH_W$ac_delim -PACKAGE!$PACKAGE$ac_delim -VERSION!$VERSION$ac_delim -ACLOCAL!$ACLOCAL$ac_delim -AUTOCONF!$AUTOCONF$ac_delim -AUTOMAKE!$AUTOMAKE$ac_delim -AUTOHEADER!$AUTOHEADER$ac_delim -MAKEINFO!$MAKEINFO$ac_delim -install_sh!$install_sh$ac_delim -STRIP!$STRIP$ac_delim -INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim -mkdir_p!$mkdir_p$ac_delim -AWK!$AWK$ac_delim -SET_MAKE!$SET_MAKE$ac_delim -am__leading_dot!$am__leading_dot$ac_delim -AMTAR!$AMTAR$ac_delim -am__tar!$am__tar$ac_delim -am__untar!$am__untar$ac_delim -CC!$CC$ac_delim -CFLAGS!$CFLAGS$ac_delim -LDFLAGS!$LDFLAGS$ac_delim -CPPFLAGS!$CPPFLAGS$ac_delim -ac_ct_CC!$ac_ct_CC$ac_delim -EXEEXT!$EXEEXT$ac_delim -OBJEXT!$OBJEXT$ac_delim -DEPDIR!$DEPDIR$ac_delim -am__include!$am__include$ac_delim -am__quote!$am__quote$ac_delim -AMDEP_TRUE!$AMDEP_TRUE$ac_delim -AMDEP_FALSE!$AMDEP_FALSE$ac_delim -AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim -CCDEPMODE!$CCDEPMODE$ac_delim -am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim -am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim -build!$build$ac_delim -build_cpu!$build_cpu$ac_delim -build_vendor!$build_vendor$ac_delim -build_os!$build_os$ac_delim -host!$host$ac_delim -host_cpu!$host_cpu$ac_delim -host_vendor!$host_vendor$ac_delim -host_os!$host_os$ac_delim -SED!$SED$ac_delim -GREP!$GREP$ac_delim -EGREP!$EGREP$ac_delim -LN_S!$LN_S$ac_delim -ECHO!$ECHO$ac_delim -AR!$AR$ac_delim -RANLIB!$RANLIB$ac_delim -DLLTOOL!$DLLTOOL$ac_delim -AS!$AS$ac_delim -OBJDUMP!$OBJDUMP$ac_delim -CPP!$CPP$ac_delim -CXX!$CXX$ac_delim -CXXFLAGS!$CXXFLAGS$ac_delim -ac_ct_CXX!$ac_ct_CXX$ac_delim -_ACEOF - - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then - break - elif $ac_last_try; then - { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 -echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} - { (exit 1); exit 1; }; } - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done - -ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` -if test -n "$ac_eof"; then - ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` - ac_eof=`expr $ac_eof + 1` -fi - -cat >>$CONFIG_STATUS <<_ACEOF -cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -_ACEOF -sed ' -s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g -s/^/s,@/; s/!/@,|#_!!_#|/ -:n -t n -s/'"$ac_delim"'$/,g/; t -s/$/\\/; p -N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n -' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF -CEOF$ac_eof -_ACEOF - - -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - cat >conf$$subs.sed <<_ACEOF -CXXDEPMODE!$CXXDEPMODE$ac_delim -am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim -am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim -CXXCPP!$CXXCPP$ac_delim -F77!$F77$ac_delim -FFLAGS!$FFLAGS$ac_delim -ac_ct_F77!$ac_ct_F77$ac_delim -LIBTOOL!$LIBTOOL$ac_delim -LIBTOOL_DEPS!$LIBTOOL_DEPS$ac_delim -INSTALL_LTDL_TRUE!$INSTALL_LTDL_TRUE$ac_delim -INSTALL_LTDL_FALSE!$INSTALL_LTDL_FALSE$ac_delim -CONVENIENCE_LTDL_TRUE!$CONVENIENCE_LTDL_TRUE$ac_delim -CONVENIENCE_LTDL_FALSE!$CONVENIENCE_LTDL_FALSE$ac_delim -LIBADD_DL!$LIBADD_DL$ac_delim -LIBOBJS!$LIBOBJS$ac_delim -LTLIBOBJS!$LTLIBOBJS$ac_delim -_ACEOF - - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 16; then - break - elif $ac_last_try; then - { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 -echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} - { (exit 1); exit 1; }; } - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done - -ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` -if test -n "$ac_eof"; then - ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` - ac_eof=`expr $ac_eof + 1` -fi - -cat >>$CONFIG_STATUS <<_ACEOF -cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end -_ACEOF -sed ' -s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g -s/^/s,@/; s/!/@,|#_!!_#|/ -:n -t n -s/'"$ac_delim"'$/,g/; t -s/$/\\/; p -N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n -' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF -:end -s/|#_!!_#|//g -CEOF$ac_eof -_ACEOF - - -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/ -s/:*\${srcdir}:*/:/ -s/:*@srcdir@:*/:/ -s/^\([^=]*=[ ]*\):*/\1/ -s/:*$// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF -fi # test -n "$CONFIG_FILES" - - -for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 -echo "$as_me: error: Invalid tag $ac_tag." >&2;} - { (exit 1); exit 1; }; };; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 -echo "$as_me: error: cannot find input file: $ac_f" >&2;} - { (exit 1); exit 1; }; };; - esac - ac_file_inputs="$ac_file_inputs $ac_f" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input="Generated from "`IFS=: - echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - fi - - case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin";; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - { as_dir="$ac_dir" - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 -echo "$as_me: error: cannot create directory $as_dir" >&2;} - { (exit 1); exit 1; }; }; } - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac - ac_MKDIR_P=$MKDIR_P - case $MKDIR_P in - [\\/$]* | ?:[\\/]* ) ;; - */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; - esac -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= - -case `sed -n '/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p -' $ac_file_inputs` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF - sed "$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s&@configure_input@&$configure_input&;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -s&@MKDIR_P@&$ac_MKDIR_P&;t t -$ac_datarootdir_hack -" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && - { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&5 -echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&2;} - - rm -f "$tmp/stdin" - case $ac_file in - -) cat "$tmp/out"; rm -f "$tmp/out";; - *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; - esac - ;; - :H) - # - # CONFIG_HEADER - # -_ACEOF - -# Transform confdefs.h into a sed script `conftest.defines', that -# substitutes the proper values into config.h.in to produce config.h. -rm -f conftest.defines conftest.tail -# First, append a space to every undef/define line, to ease matching. -echo 's/$/ /' >conftest.defines -# Then, protect against being on the right side of a sed subst, or in -# an unquoted here document, in config.status. If some macros were -# called several times there might be several #defines for the same -# symbol, which is useless. But do not sort them, since the last -# AC_DEFINE must be honored. -ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* -# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where -# NAME is the cpp macro being defined, VALUE is the value it is being given. -# PARAMS is the parameter list in the macro definition--in most cases, it's -# just an empty string. -ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' -ac_dB='\\)[ (].*,\\1define\\2' -ac_dC=' ' -ac_dD=' ,' - -uniq confdefs.h | - sed -n ' - t rset - :rset - s/^[ ]*#[ ]*define[ ][ ]*// - t ok - d - :ok - s/[\\&,]/\\&/g - s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p - s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p - ' >>conftest.defines - -# Remove the space that was appended to ease matching. -# Then replace #undef with comments. This is necessary, for -# example, in the case of _POSIX_SOURCE, which is predefined and required -# on some systems where configure will not decide to define it. -# (The regexp can be short, since the line contains either #define or #undef.) -echo 's/ $// -s,^[ #]*u.*,/* & */,' >>conftest.defines - -# Break up conftest.defines: -ac_max_sed_lines=50 - -# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" -# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" -# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" -# et cetera. -ac_in='$ac_file_inputs' -ac_out='"$tmp/out1"' -ac_nxt='"$tmp/out2"' - -while : -do - # Write a here document: - cat >>$CONFIG_STATUS <<_ACEOF - # First, check the format of the line: - cat >"\$tmp/defines.sed" <<\\CEOF -/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def -/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def -b -:def -_ACEOF - sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS - echo 'CEOF - sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS - ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in - sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail - grep . conftest.tail >/dev/null || break - rm -f conftest.defines - mv conftest.tail conftest.defines -done -rm -f conftest.defines conftest.tail - -echo "ac_result=$ac_in" >>$CONFIG_STATUS -cat >>$CONFIG_STATUS <<\_ACEOF - if test x"$ac_file" != x-; then - echo "/* $configure_input */" >"$tmp/config.h" - cat "$ac_result" >>"$tmp/config.h" - if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then - { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 -echo "$as_me: $ac_file is unchanged" >&6;} - else - rm -f $ac_file - mv "$tmp/config.h" $ac_file - fi - else - echo "/* $configure_input */" - cat "$ac_result" - fi - rm -f "$tmp/out12" -# Compute $ac_file's index in $config_headers. -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $ac_file | $ac_file:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $ac_file" >`$as_dirname -- $ac_file || -$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X$ac_file : 'X\(//\)[^/]' \| \ - X$ac_file : 'X\(//\)$' \| \ - X$ac_file : 'X\(/\)' \| . 2>/dev/null || -echo X$ac_file | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'`/stamp-h$_am_stamp_count - ;; - - :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 -echo "$as_me: executing $ac_file commands" >&6;} - ;; - esac - - - case $ac_file$ac_mode in - "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -echo X"$mf" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - { as_dir=$dirpart/$fdir - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 -echo "$as_me: error: cannot create directory $as_dir" >&2;} - { (exit 1); exit 1; }; }; } - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done -done - ;; - - esac -done # for ac_tag - - -{ (exit 0); exit 0; } -_ACEOF -chmod +x $CONFIG_STATUS -ac_clean_files=$ac_clean_files_save - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } -fi - diff --git a/libltdl/configure.ac b/libltdl/configure.ac deleted file mode 100644 index 1446efbd0..000000000 --- a/libltdl/configure.ac +++ /dev/null @@ -1,79 +0,0 @@ -## Process this file with autoconf to create configure. -*- autoconf -*- -# Copyright 2001 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 USA - - -dnl FIXME: Is this really new enough? -AC_PREREQ(2.50) - - -## ------------------------ ## -## Autoconf initialisation. ## -## ------------------------ ## -AC_INIT([libltdl], [1.2], [bug-libtool@gnu.org]) -AC_CONFIG_SRCDIR([ltdl.c]) - - -## ------------------------------- ## -## Libltdl specific configuration. ## -## ------------------------------- ## - -AC_CONFIG_AUX_DIR([.]) - -if test -z "$enable_ltdl_install$enable_ltdl_convenience"; then - if test -f ${srcdir}/ltmain.sh; then - # if libltdl is libtoolized, it is assumed to be stand-alone and - # installed unless the command line overrides it (tested above) - enable_ltdl_install=yes - else - AC_MSG_WARN([*** The top-level configure must select either]) - AC_MSG_WARN([*** [A""C_LIBLTDL_INSTALLABLE] or [A""C_LIBLTDL_CONVENIENCE].]) - AC_MSG_ERROR([*** Maybe you want to --enable-ltdl-install?]) - fi -fi - - -## ------------------------ ## -## Automake Initialisation. ## -## ------------------------ ## -AM_INIT_AUTOMAKE(AC_PACKAGE_TARNAME, AC_PACKAGE_VERSION, -) -AM_CONFIG_HEADER([config.h:config-h.in]) - - -## ------------------ ## -## C compiler checks. ## -## ------------------ ## -AC_PROG_CC -AC_C_CONST -AC_C_INLINE - - -## ----------------------- ## -## Libtool initialisation. ## -## ----------------------- ## -AC_LIBTOOL_WIN32_DLL -AC_PROG_LIBTOOL -AC_SUBST([LIBTOOL_DEPS]) - -AC_LIB_LTDL - - -## -------- ## -## Outputs. ## -## -------- ## -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT diff --git a/libltdl/install-sh b/libltdl/install-sh deleted file mode 100755 index a5897de6e..000000000 --- a/libltdl/install-sh +++ /dev/null @@ -1,519 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2006-12-25.00 - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call `install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - trap '(exit $?); exit' 1 2 13 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names starting with `-'. - case $src in - -*) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - - dst=$dst_arg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writeable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - -*) prefix='./';; - *) prefix='';; - esac - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob set +f - IFS=$oIFS - - prefixes= - - for d - do - test -z "$d" && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c deleted file mode 100644 index 3a76ff102..000000000 --- a/libltdl/ltdl.c +++ /dev/null @@ -1,4530 +0,0 @@ -/* ltdl.c -- system independent dlopen wrapper - Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. - Originally by Thomas Tanner - This file is part of GNU Libtool. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -As a special exception to the GNU Lesser General Public License, -if you distribute this file as part of a program or library that -is built using GNU libtool, you may include it under the same -distribution terms that you use for the rest of that program. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA - -*/ - -#if HAVE_CONFIG_H -# include -#endif - -#if HAVE_UNISTD_H -# include -#endif - -#if HAVE_STDIO_H -# include -#endif - -/* Include the header defining malloc. On K&R C compilers, - that's , on ANSI C and ISO C compilers, that's . */ -#if HAVE_STDLIB_H -# include -#else -# if HAVE_MALLOC_H -# include -# endif -#endif - -#if HAVE_STRING_H -# include -#else -# if HAVE_STRINGS_H -# include -# endif -#endif - -#if HAVE_CTYPE_H -# include -#endif - -#if HAVE_MEMORY_H -# include -#endif - -#if HAVE_ERRNO_H -# include -#endif - - -#ifndef __WINDOWS__ -# ifdef __WIN32__ -# define __WINDOWS__ -# endif -#endif - - -#undef LT_USE_POSIX_DIRENT -#ifdef HAVE_CLOSEDIR -# ifdef HAVE_OPENDIR -# ifdef HAVE_READDIR -# ifdef HAVE_DIRENT_H -# define LT_USE_POSIX_DIRENT -# endif /* HAVE_DIRENT_H */ -# endif /* HAVE_READDIR */ -# endif /* HAVE_OPENDIR */ -#endif /* HAVE_CLOSEDIR */ - - -#undef LT_USE_WINDOWS_DIRENT_EMULATION -#ifndef LT_USE_POSIX_DIRENT -# ifdef __WINDOWS__ -# define LT_USE_WINDOWS_DIRENT_EMULATION -# endif /* __WINDOWS__ */ -#endif /* LT_USE_POSIX_DIRENT */ - - -#ifdef LT_USE_POSIX_DIRENT -# include -# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) -#else -# ifdef LT_USE_WINDOWS_DIRENT_EMULATION -# define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) -# else -# define dirent direct -# define LT_D_NAMLEN(dirent) ((dirent)->d_namlen) -# if HAVE_SYS_NDIR_H -# include -# endif -# if HAVE_SYS_DIR_H -# include -# endif -# if HAVE_NDIR_H -# include -# endif -# endif -#endif - -#if HAVE_ARGZ_H -# include -#endif - -#if HAVE_ASSERT_H -# include -#else -# define assert(arg) ((void) 0) -#endif - -#include "ltdl.h" - -#if WITH_DMALLOC -# include -#endif - - - - -/* --- WINDOWS SUPPORT --- */ - -/* DLL building support on win32 hosts; mostly to workaround their - ridiculous implementation of data symbol exporting. */ -#ifndef LT_GLOBAL_DATA -# if defined(__WINDOWS__) || defined(__CYGWIN__) -# ifdef DLL_EXPORT /* defined by libtool (if required) */ -# define LT_GLOBAL_DATA __declspec(dllexport) -# endif -# endif -# ifndef LT_GLOBAL_DATA /* static linking or !__WINDOWS__ */ -# define LT_GLOBAL_DATA -# endif -#endif - -/* fopen() mode flags for reading a text file */ -#undef LT_READTEXT_MODE -#if defined(__WINDOWS__) || defined(__CYGWIN__) -# define LT_READTEXT_MODE "rt" -#else -# define LT_READTEXT_MODE "r" -#endif - -#ifdef LT_USE_WINDOWS_DIRENT_EMULATION - -#include - -#define dirent lt_dirent -#define DIR lt_DIR - -struct dirent -{ - char d_name[2048]; - int d_namlen; -}; - -typedef struct _DIR -{ - HANDLE hSearch; - WIN32_FIND_DATA Win32FindData; - BOOL firsttime; - struct dirent file_info; -} DIR; - -#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */ - - -/* --- MANIFEST CONSTANTS --- */ - - -/* Standard libltdl search path environment variable name */ -#undef LTDL_SEARCHPATH_VAR -#define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH" - -/* Standard libtool archive file extension. */ -#undef LTDL_ARCHIVE_EXT -#define LTDL_ARCHIVE_EXT ".la" - -/* max. filename length */ -#ifndef LT_FILENAME_MAX -# define LT_FILENAME_MAX 1024 -#endif - -/* This is the maximum symbol size that won't require malloc/free */ -#undef LT_SYMBOL_LENGTH -#define LT_SYMBOL_LENGTH 128 - -/* This accounts for the _LTX_ separator */ -#undef LT_SYMBOL_OVERHEAD -#define LT_SYMBOL_OVERHEAD 5 - - - - -/* --- MEMORY HANDLING --- */ - - -/* These are the functions used internally. In addition to making - use of the associated function pointers above, they also perform - error handling. */ -static char *lt_estrdup LT_PARAMS((const char *str)); -static lt_ptr lt_emalloc LT_PARAMS((size_t size)); -static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size)); - -/* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */ -#define rpl_realloc realloc - -/* These are the pointers that can be changed by the caller: */ -LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)) - = (lt_ptr (*) LT_PARAMS((size_t))) malloc; -LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)) - = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc; -LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)) - = (void (*) LT_PARAMS((lt_ptr))) free; - -/* The following macros reduce the amount of typing needed to cast - assigned memory. */ -#if WITH_DMALLOC - -#define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp))) -#define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp))) -#define LT_DLFREE(p) \ - LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END - -#define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp))) -#define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp))) - -#else - -#define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp))) -#define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp))) -#define LT_DLFREE(p) \ - LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END - -#define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp))) -#define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp))) - -#endif - -#define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \ - if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \ - } LT_STMT_END - - -/* --- REPLACEMENT FUNCTIONS --- */ - - -#undef strdup -#define strdup rpl_strdup - -static char *strdup LT_PARAMS((const char *str)); - -static char * -strdup(str) - const char *str; -{ - char *tmp = 0; - - if (str) - { - tmp = LT_DLMALLOC (char, 1+ strlen (str)); - if (tmp) - { - strcpy(tmp, str); - } - } - - return tmp; -} - - -#if ! HAVE_STRCMP - -#undef strcmp -#define strcmp rpl_strcmp - -static int strcmp LT_PARAMS((const char *str1, const char *str2)); - -static int -strcmp (str1, str2) - const char *str1; - const char *str2; -{ - if (str1 == str2) - return 0; - if (str1 == 0) - return -1; - if (str2 == 0) - return 1; - - for (;*str1 && *str2; ++str1, ++str2) - { - if (*str1 != *str2) - break; - } - - return (int)(*str1 - *str2); -} -#endif - - -#if ! HAVE_STRCHR - -# if HAVE_INDEX -# define strchr index -# else -# define strchr rpl_strchr - -static const char *strchr LT_PARAMS((const char *str, int ch)); - -static const char* -strchr(str, ch) - const char *str; - int ch; -{ - const char *p; - - for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p) - /*NOWORK*/; - - return (*p == (char)ch) ? p : 0; -} - -# endif -#endif /* !HAVE_STRCHR */ - - -#if ! HAVE_STRRCHR - -# if HAVE_RINDEX -# define strrchr rindex -# else -# define strrchr rpl_strrchr - -static const char *strrchr LT_PARAMS((const char *str, int ch)); - -static const char* -strrchr(str, ch) - const char *str; - int ch; -{ - const char *p, *q = 0; - - for (p = str; *p != LT_EOS_CHAR; ++p) - { - if (*p == (char) ch) - { - q = p; - } - } - - return q; -} - -# endif -#endif - -/* NOTE: Neither bcopy nor the memcpy implementation below can - reliably handle copying in overlapping areas of memory. Use - memmove (for which there is a fallback implmentation below) - if you need that behaviour. */ -#if ! HAVE_MEMCPY - -# if HAVE_BCOPY -# define memcpy(dest, src, size) bcopy (src, dest, size) -# else -# define memcpy rpl_memcpy - -static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); - -static lt_ptr -memcpy (dest, src, size) - lt_ptr dest; - const lt_ptr src; - size_t size; -{ - const char * s = src; - char * d = dest; - size_t i = 0; - - for (i = 0; i < size; ++i) - { - d[i] = s[i]; - } - - return dest; -} - -# endif /* !HAVE_BCOPY */ -#endif /* !HAVE_MEMCPY */ - -#if ! HAVE_MEMMOVE -# define memmove rpl_memmove - -static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); - -static lt_ptr -memmove (dest, src, size) - lt_ptr dest; - const lt_ptr src; - size_t size; -{ - const char * s = src; - char * d = dest; - size_t i; - - if (d < s) - for (i = 0; i < size; ++i) - { - d[i] = s[i]; - } - else if (d > s && size > 0) - for (i = size -1; ; --i) - { - d[i] = s[i]; - if (i == 0) - break; - } - - return dest; -} - -#endif /* !HAVE_MEMMOVE */ - -#ifdef LT_USE_WINDOWS_DIRENT_EMULATION - -static void closedir LT_PARAMS((DIR *entry)); - -static void -closedir(entry) - DIR *entry; -{ - assert(entry != (DIR *) NULL); - FindClose(entry->hSearch); - lt_dlfree((lt_ptr)entry); -} - - -static DIR * opendir LT_PARAMS((const char *path)); - -static DIR* -opendir (path) - const char *path; -{ - char file_specification[LT_FILENAME_MAX]; - DIR *entry; - - assert(path != (char *) NULL); - /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */ - (void) strncpy (file_specification, path, LT_FILENAME_MAX-6); - file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR; - (void) strcat(file_specification,"\\"); - entry = LT_DLMALLOC (DIR,sizeof(DIR)); - if (entry != (DIR *) 0) - { - entry->firsttime = TRUE; - entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData); - } - if (entry->hSearch == INVALID_HANDLE_VALUE) - { - (void) strcat(file_specification,"\\*.*"); - entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData); - if (entry->hSearch == INVALID_HANDLE_VALUE) - { - LT_DLFREE (entry); - return (DIR *) 0; - } - } - return(entry); -} - - -static struct dirent *readdir LT_PARAMS((DIR *entry)); - -static struct dirent *readdir(entry) - DIR *entry; -{ - int - status; - - if (entry == (DIR *) 0) - return((struct dirent *) 0); - if (!entry->firsttime) - { - status = FindNextFile(entry->hSearch,&entry->Win32FindData); - if (status == 0) - return((struct dirent *) 0); - } - entry->firsttime = FALSE; - (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName, - LT_FILENAME_MAX-1); - entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR; - entry->file_info.d_namlen = strlen(entry->file_info.d_name); - return(&entry->file_info); -} - -#endif /* LT_USE_WINDOWS_DIRENT_EMULATION */ - -/* According to Alexandre Oliva , - ``realloc is not entirely portable'' - In any case we want to use the allocator supplied by the user without - burdening them with an lt_dlrealloc function pointer to maintain. - Instead implement our own version (with known boundary conditions) - using lt_dlmalloc and lt_dlfree. */ - -/* #undef realloc - #define realloc rpl_realloc -*/ -#if 0 - /* You can't (re)define realloc unless you also (re)define malloc. - Right now, this code uses the size of the *destination* to decide - how much to copy. That's not right, but you can't know the size - of the source unless you know enough about, or wrote malloc. So - this code is disabled... */ - -static lt_ptr -realloc (ptr, size) - lt_ptr ptr; - size_t size; -{ - if (size == 0) - { - /* For zero or less bytes, free the original memory */ - if (ptr != 0) - { - lt_dlfree (ptr); - } - - return (lt_ptr) 0; - } - else if (ptr == 0) - { - /* Allow reallocation of a NULL pointer. */ - return lt_dlmalloc (size); - } - else - { - /* Allocate a new block, copy and free the old block. */ - lt_ptr mem = lt_dlmalloc (size); - - if (mem) - { - memcpy (mem, ptr, size); - lt_dlfree (ptr); - } - - /* Note that the contents of PTR are not damaged if there is - insufficient memory to realloc. */ - return mem; - } -} -#endif - - -#if ! HAVE_ARGZ_APPEND -# define argz_append rpl_argz_append - -static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len, - const char *buf, size_t buf_len)); - -static error_t -argz_append (pargz, pargz_len, buf, buf_len) - char **pargz; - size_t *pargz_len; - const char *buf; - size_t buf_len; -{ - size_t argz_len; - char *argz; - - assert (pargz); - assert (pargz_len); - assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len)); - - /* If nothing needs to be appended, no more work is required. */ - if (buf_len == 0) - return 0; - - /* Ensure there is enough room to append BUF_LEN. */ - argz_len = *pargz_len + buf_len; - argz = LT_DLREALLOC (char, *pargz, argz_len); - if (!argz) - return ENOMEM; - - /* Copy characters from BUF after terminating '\0' in ARGZ. */ - memcpy (argz + *pargz_len, buf, buf_len); - - /* Assign new values. */ - *pargz = argz; - *pargz_len = argz_len; - - return 0; -} -#endif /* !HAVE_ARGZ_APPEND */ - - -#if ! HAVE_ARGZ_CREATE_SEP -# define argz_create_sep rpl_argz_create_sep - -static error_t argz_create_sep LT_PARAMS((const char *str, int delim, - char **pargz, size_t *pargz_len)); - -static error_t -argz_create_sep (str, delim, pargz, pargz_len) - const char *str; - int delim; - char **pargz; - size_t *pargz_len; -{ - size_t argz_len; - char *argz = 0; - - assert (str); - assert (pargz); - assert (pargz_len); - - /* Make a copy of STR, but replacing each occurrence of - DELIM with '\0'. */ - argz_len = 1+ LT_STRLEN (str); - if (argz_len) - { - const char *p; - char *q; - - argz = LT_DLMALLOC (char, argz_len); - if (!argz) - return ENOMEM; - - for (p = str, q = argz; *p != LT_EOS_CHAR; ++p) - { - if (*p == delim) - { - /* Ignore leading delimiters, and fold consecutive - delimiters in STR into a single '\0' in ARGZ. */ - if ((q > argz) && (q[-1] != LT_EOS_CHAR)) - *q++ = LT_EOS_CHAR; - else - --argz_len; - } - else - *q++ = *p; - } - /* Copy terminating LT_EOS_CHAR. */ - *q = *p; - } - - /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */ - if (!argz_len) - LT_DLFREE (argz); - - /* Assign new values. */ - *pargz = argz; - *pargz_len = argz_len; - - return 0; -} -#endif /* !HAVE_ARGZ_CREATE_SEP */ - - -#if ! HAVE_ARGZ_INSERT -# define argz_insert rpl_argz_insert - -static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len, - char *before, const char *entry)); - -static error_t -argz_insert (pargz, pargz_len, before, entry) - char **pargz; - size_t *pargz_len; - char *before; - const char *entry; -{ - assert (pargz); - assert (pargz_len); - assert (entry && *entry); - - /* No BEFORE address indicates ENTRY should be inserted after the - current last element. */ - if (!before) - return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry)); - - /* This probably indicates a programmer error, but to preserve - semantics, scan back to the start of an entry if BEFORE points - into the middle of it. */ - while ((before > *pargz) && (before[-1] != LT_EOS_CHAR)) - --before; - - { - size_t entry_len = 1+ LT_STRLEN (entry); - size_t argz_len = *pargz_len + entry_len; - size_t offset = before - *pargz; - char *argz = LT_DLREALLOC (char, *pargz, argz_len); - - if (!argz) - return ENOMEM; - - /* Make BEFORE point to the equivalent offset in ARGZ that it - used to have in *PARGZ incase realloc() moved the block. */ - before = argz + offset; - - /* Move the ARGZ entries starting at BEFORE up into the new - space at the end -- making room to copy ENTRY into the - resulting gap. */ - memmove (before + entry_len, before, *pargz_len - offset); - memcpy (before, entry, entry_len); - - /* Assign new values. */ - *pargz = argz; - *pargz_len = argz_len; - } - - return 0; -} -#endif /* !HAVE_ARGZ_INSERT */ - - -#if ! HAVE_ARGZ_NEXT -# define argz_next rpl_argz_next - -static char *argz_next LT_PARAMS((char *argz, size_t argz_len, - const char *entry)); - -static char * -argz_next (argz, argz_len, entry) - char *argz; - size_t argz_len; - const char *entry; -{ - assert ((argz && argz_len) || (!argz && !argz_len)); - - if (entry) - { - /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address - within the ARGZ vector. */ - assert ((!argz && !argz_len) - || ((argz <= entry) && (entry < (argz + argz_len)))); - - /* Move to the char immediately after the terminating - '\0' of ENTRY. */ - entry = 1+ strchr (entry, LT_EOS_CHAR); - - /* Return either the new ENTRY, or else NULL if ARGZ is - exhausted. */ - return (entry >= argz + argz_len) ? 0 : (char *) entry; - } - else - { - /* This should probably be flagged as a programmer error, - since starting an argz_next loop with the iterator set - to ARGZ is safer. To preserve semantics, handle the NULL - case by returning the start of ARGZ (if any). */ - if (argz_len > 0) - return argz; - else - return 0; - } -} -#endif /* !HAVE_ARGZ_NEXT */ - - - -#if ! HAVE_ARGZ_STRINGIFY -# define argz_stringify rpl_argz_stringify - -static void argz_stringify LT_PARAMS((char *argz, size_t argz_len, - int sep)); - -static void -argz_stringify (argz, argz_len, sep) - char *argz; - size_t argz_len; - int sep; -{ - assert ((argz && argz_len) || (!argz && !argz_len)); - - if (sep) - { - --argz_len; /* don't stringify the terminating EOS */ - while (--argz_len > 0) - { - if (argz[argz_len] == LT_EOS_CHAR) - argz[argz_len] = sep; - } - } -} -#endif /* !HAVE_ARGZ_STRINGIFY */ - - - - -/* --- TYPE DEFINITIONS -- */ - - -/* This type is used for the array of caller data sets in each handler. */ -typedef struct { - lt_dlcaller_id key; - lt_ptr data; -} lt_caller_data; - - - - -/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */ - - -/* Extract the diagnostic strings from the error table macro in the same - order as the enumerated indices in ltdl.h. */ - -static const char *lt_dlerror_strings[] = - { -#define LT_ERROR(name, diagnostic) (diagnostic), - lt_dlerror_table -#undef LT_ERROR - - 0 - }; - -/* This structure is used for the list of registered loaders. */ -struct lt_dlloader { - struct lt_dlloader *next; - const char *loader_name; /* identifying name for each loader */ - const char *sym_prefix; /* prefix for symbols */ - lt_module_open *module_open; - lt_module_close *module_close; - lt_find_sym *find_sym; - lt_dlloader_exit *dlloader_exit; - lt_user_data dlloader_data; -}; - -struct lt_dlhandle_struct { - struct lt_dlhandle_struct *next; - lt_dlloader *loader; /* dlopening interface */ - lt_dlinfo info; - int depcount; /* number of dependencies */ - lt_dlhandle *deplibs; /* dependencies */ - lt_module module; /* system module handle */ - lt_ptr system; /* system specific data */ - lt_caller_data *caller_data; /* per caller associated data */ - int flags; /* various boolean stats */ -}; - -/* Various boolean flags can be stored in the flags field of an - lt_dlhandle_struct... */ -#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag)) -#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag)) - -#define LT_DLRESIDENT_FLAG (0x01 << 0) -/* ...add more flags here... */ - -#define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG) - - -#define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)] - -static const char objdir[] = LTDL_OBJDIR; -static const char archive_ext[] = LTDL_ARCHIVE_EXT; -#ifdef LTDL_SHLIB_EXT -static const char shlib_ext[] = LTDL_SHLIB_EXT; -#endif -#ifdef LTDL_SYSSEARCHPATH -static const char sys_search_path[] = LTDL_SYSSEARCHPATH; -#endif - - - - -/* --- MUTEX LOCKING --- */ - - -/* Macros to make it easier to run the lock functions only if they have - been registered. The reason for the complicated lock macro is to - ensure that the stored error message from the last error is not - accidentally erased if the current function doesn't generate an - error of its own. */ -#define LT_DLMUTEX_LOCK() LT_STMT_START { \ - if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \ - } LT_STMT_END -#define LT_DLMUTEX_UNLOCK() LT_STMT_START { \ - if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\ - } LT_STMT_END -#define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \ - if (lt_dlmutex_seterror_func) \ - (*lt_dlmutex_seterror_func) (errormsg); \ - else lt_dllast_error = (errormsg); } LT_STMT_END -#define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \ - if (lt_dlmutex_geterror_func) \ - (errormsg) = (*lt_dlmutex_geterror_func) (); \ - else (errormsg) = lt_dllast_error; } LT_STMT_END - -/* The mutex functions stored here are global, and are necessarily the - same for all threads that wish to share access to libltdl. */ -static lt_dlmutex_lock *lt_dlmutex_lock_func = 0; -static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0; -static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0; -static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0; -static const char *lt_dllast_error = 0; - - -/* Either set or reset the mutex functions. Either all the arguments must - be valid functions, or else all can be NULL to turn off locking entirely. - The registered functions should be manipulating a static global lock - from the lock() and unlock() callbacks, which needs to be reentrant. */ -int -lt_dlmutex_register (lock, unlock, seterror, geterror) - lt_dlmutex_lock *lock; - lt_dlmutex_unlock *unlock; - lt_dlmutex_seterror *seterror; - lt_dlmutex_geterror *geterror; -{ - lt_dlmutex_unlock *old_unlock = lt_dlmutex_unlock_func; - int errors = 0; - - /* Lock using the old lock() callback, if any. */ - LT_DLMUTEX_LOCK (); - - if ((lock && unlock && seterror && geterror) - || !(lock || unlock || seterror || geterror)) - { - lt_dlmutex_lock_func = lock; - lt_dlmutex_unlock_func = unlock; - lt_dlmutex_seterror_func = seterror; - lt_dlmutex_geterror_func = geterror; - } - else - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS)); - ++errors; - } - - /* Use the old unlock() callback we saved earlier, if any. Otherwise - record any errors using internal storage. */ - if (old_unlock) - (*old_unlock) (); - - /* Return the number of errors encountered during the execution of - this function. */ - return errors; -} - - - - -/* --- ERROR HANDLING --- */ - - -static const char **user_error_strings = 0; -static int errorcount = LT_ERROR_MAX; - -int -lt_dladderror (diagnostic) - const char *diagnostic; -{ - int errindex = 0; - int result = -1; - const char **temp = (const char **) 0; - - assert (diagnostic); - - LT_DLMUTEX_LOCK (); - - errindex = errorcount - LT_ERROR_MAX; - temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex); - if (temp) - { - user_error_strings = temp; - user_error_strings[errindex] = diagnostic; - result = errorcount++; - } - - LT_DLMUTEX_UNLOCK (); - - return result; -} - -int -lt_dlseterror (errindex) - int errindex; -{ - int errors = 0; - - LT_DLMUTEX_LOCK (); - - if (errindex >= errorcount || errindex < 0) - { - /* Ack! Error setting the error message! */ - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE)); - ++errors; - } - else if (errindex < LT_ERROR_MAX) - { - /* No error setting the error message! */ - LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]); - } - else - { - /* No error setting the error message! */ - LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]); - } - - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -static lt_ptr -lt_emalloc (size) - size_t size; -{ - lt_ptr mem = lt_dlmalloc (size); - if (size && !mem) - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); - return mem; -} - -static lt_ptr -lt_erealloc (addr, size) - lt_ptr addr; - size_t size; -{ - lt_ptr mem = lt_dlrealloc (addr, size); - if (size && !mem) - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); - return mem; -} - -static char * -lt_estrdup (str) - const char *str; -{ - char *copy = strdup (str); - if (LT_STRLEN (str) && !copy) - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); - return copy; -} - - - - -/* --- DLOPEN() INTERFACE LOADER --- */ - - -#if HAVE_LIBDL - -/* dynamic linking with dlopen/dlsym */ - -#if HAVE_DLFCN_H -# include -#endif - -#if HAVE_SYS_DL_H -# include -#endif - -/* We may have to define LT_LAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_LAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_LAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_LAZY_OR_NOW DL_LAZY -# endif -# endif /* !RTLD_LAZY */ -#endif -#ifndef LT_LAZY_OR_NOW -# ifdef RTLD_NOW -# define LT_LAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_LAZY_OR_NOW DL_NOW -# endif -# endif /* !RTLD_NOW */ -#endif -#ifndef LT_LAZY_OR_NOW -# define LT_LAZY_OR_NOW 0 -#endif /* !LT_LAZY_OR_NOW */ - -#if HAVE_DLERROR -# define DLERROR(arg) dlerror () -#else -# define DLERROR(arg) LT_DLSTRERROR (arg) -#endif - -static lt_module -sys_dl_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - lt_module module = dlopen (filename, LT_LAZY_OR_NOW); - - if (!module) - { - LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN)); - } - - return module; -} - -static int -sys_dl_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int errors = 0; - - if (dlclose (module) != 0) - { - LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE)); - ++errors; - } - - return errors; -} - -static lt_ptr -sys_dl_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = dlsym (module, symbol); - - if (!address) - { - LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND)); - } - - return address; -} - -static struct lt_user_dlloader sys_dl = - { -# ifdef NEED_USCORE - "_", -# else - 0, -# endif - sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 }; - - -#endif /* HAVE_LIBDL */ - - - -/* --- SHL_LOAD() INTERFACE LOADER --- */ - -#if HAVE_SHL_LOAD - -/* dynamic linking with shl_load (HP-UX) (comments from gmodule) */ - -#ifdef HAVE_DL_H -# include -#endif - -/* some flags are missing on some systems, so we provide - * harmless defaults. - * - * Mandatory: - * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. - * BIND_DEFERRED - Delay code symbol resolution until actual reference. - * - * Optionally: - * BIND_FIRST - Place the library at the head of the symbol search - * order. - * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all - * unsatisfied symbols as fatal. This flag allows - * binding of unsatisfied code symbols to be deferred - * until use. - * [Perl: For certain libraries, like DCE, deferred - * binding often causes run time problems. Adding - * BIND_NONFATAL to BIND_IMMEDIATE still allows - * unresolved references in situations like this.] - * BIND_NOSTART - Do not call the initializer for the shared library - * when the library is loaded, nor on a future call to - * shl_unload(). - * BIND_VERBOSE - Print verbose messages concerning possible - * unsatisfied symbols. - * - * hp9000s700/hp9000s800: - * BIND_RESTRICTED - Restrict symbols visible by the library to those - * present at library load time. - * DYNAMIC_PATH - Allow the loader to dynamically search for the - * library specified by the path argument. - */ - -#ifndef DYNAMIC_PATH -# define DYNAMIC_PATH 0 -#endif -#ifndef BIND_RESTRICTED -# define BIND_RESTRICTED 0 -#endif - -#define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) - -static lt_module -sys_shl_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - static shl_t self = (shl_t) 0; - lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); - - /* Since searching for a symbol against a NULL module handle will also - look in everything else that was already loaded and exported with - the -E compiler flag, we always cache a handle saved before any - modules are loaded. */ - if (!self) - { - lt_ptr address; - shl_findsym (&self, "main", TYPE_UNDEFINED, &address); - } - - if (!filename) - { - module = self; - } - else - { - module = shl_load (filename, LT_BIND_FLAGS, 0L); - - if (!module) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); - } - } - - return module; -} - -static int -sys_shl_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int errors = 0; - - if (module && (shl_unload ((shl_t) (module)) != 0)) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); - ++errors; - } - - return errors; -} - -static lt_ptr -sys_shl_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = 0; - - /* sys_shl_open should never return a NULL module handle */ - if (module == (lt_module) 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - } - else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address)) - { - if (!address) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - } - } - - return address; -} - -static struct lt_user_dlloader sys_shl = { - 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 -}; - -#endif /* HAVE_SHL_LOAD */ - - - - -/* --- LOADLIBRARY() INTERFACE LOADER --- */ - -#ifdef __WINDOWS__ - -/* dynamic linking for Win32 */ - -#include - -/* Forward declaration; required to implement handle search below. */ -static lt_dlhandle handles; - -static lt_module -sys_wll_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - lt_dlhandle cur; - lt_module module = 0; - const char *errormsg = 0; - char *searchname = 0; - char *ext; - char self_name_buf[MAX_PATH]; - - if (!filename) - { - /* Get the name of main module */ - *self_name_buf = 0; - GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf)); - filename = ext = self_name_buf; - } - else - { - ext = strrchr (filename, '.'); - } - - if (ext) - { - /* FILENAME already has an extension. */ - searchname = lt_estrdup (filename); - } - else - { - /* Append a `.' to stop Windows from adding an - implicit `.dll' extension. */ - searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename)); - if (searchname) - sprintf (searchname, "%s.", filename); - } - if (!searchname) - return 0; - - { - /* Silence dialog from LoadLibrary on some failures. - No way to get the error mode, but to set it, - so set it twice to preserve any previous flags. */ - UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS); - SetErrorMode(errormode | SEM_FAILCRITICALERRORS); - -#if defined(__CYGWIN__) - { - char wpath[MAX_PATH]; - cygwin_conv_to_full_win32_path (searchname, wpath); - module = LoadLibrary (wpath); - } -#else - module = LoadLibrary (searchname); -#endif - - /* Restore the error mode. */ - SetErrorMode(errormode); - } - - LT_DLFREE (searchname); - - /* libltdl expects this function to fail if it is unable - to physically load the library. Sadly, LoadLibrary - will search the loaded libraries for a match and return - one of them if the path search load fails. - - We check whether LoadLibrary is returning a handle to - an already loaded module, and simulate failure if we - find one. */ - LT_DLMUTEX_LOCK (); - cur = handles; - while (cur) - { - if (!cur->module) - { - cur = 0; - break; - } - - if (cur->module == module) - { - break; - } - - cur = cur->next; - } - LT_DLMUTEX_UNLOCK (); - - if (cur || !module) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); - module = 0; - } - - return module; -} - -static int -sys_wll_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int errors = 0; - - if (FreeLibrary(module) == 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); - ++errors; - } - - return errors; -} - -static lt_ptr -sys_wll_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = GetProcAddress (module, symbol); - - if (!address) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - } - - return address; -} - -static struct lt_user_dlloader sys_wll = { - 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 -}; - -#endif /* __WINDOWS__ */ - - - - -/* --- LOAD_ADD_ON() INTERFACE LOADER --- */ - - -#ifdef __BEOS__ - -/* dynamic linking for BeOS */ - -#include - -static lt_module -sys_bedl_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - image_id image = 0; - - if (filename) - { - image = load_add_on (filename); - } - else - { - image_info info; - int32 cookie = 0; - if (get_next_image_info (0, &cookie, &info) == B_OK) - image = load_add_on (info.name); - } - - if (image <= 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); - image = 0; - } - - return (lt_module) image; -} - -static int -sys_bedl_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int errors = 0; - - if (unload_add_on ((image_id) module) != B_OK) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); - ++errors; - } - - return errors; -} - -static lt_ptr -sys_bedl_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = 0; - image_id image = (image_id) module; - - if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - address = 0; - } - - return address; -} - -static struct lt_user_dlloader sys_bedl = { - 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 -}; - -#endif /* __BEOS__ */ - - - - -/* --- DLD_LINK() INTERFACE LOADER --- */ - - -#if HAVE_DLD - -/* dynamic linking with dld */ - -#if HAVE_DLD_H -#include -#endif - -static lt_module -sys_dld_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - lt_module module = strdup (filename); - - if (dld_link (filename) != 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); - LT_DLFREE (module); - module = 0; - } - - return module; -} - -static int -sys_dld_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int errors = 0; - - if (dld_unlink_by_file ((char*)(module), 1) != 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); - ++errors; - } - else - { - LT_DLFREE (module); - } - - return errors; -} - -static lt_ptr -sys_dld_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = dld_get_func (symbol); - - if (!address) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - } - - return address; -} - -static struct lt_user_dlloader sys_dld = { - 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 -}; - -#endif /* HAVE_DLD */ - -/* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */ -#if HAVE_DYLD - - -#if HAVE_MACH_O_DYLD_H -#if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__) -/* Is this correct? Does it still function properly? */ -#define __private_extern__ extern -#endif -# include -#endif -#include - -/* We have to put some stuff here that isn't in older dyld.h files */ -#ifndef ENUM_DYLD_BOOL -# define ENUM_DYLD_BOOL -# undef FALSE -# undef TRUE - enum DYLD_BOOL { - FALSE, - TRUE - }; -#endif -#ifndef LC_REQ_DYLD -# define LC_REQ_DYLD 0x80000000 -#endif -#ifndef LC_LOAD_WEAK_DYLIB -# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) -#endif -static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0; -static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0; -static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0; -static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0; - -#ifndef NSADDIMAGE_OPTION_NONE -#define NSADDIMAGE_OPTION_NONE 0x0 -#endif -#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR -#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1 -#endif -#ifndef NSADDIMAGE_OPTION_WITH_SEARCHING -#define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2 -#endif -#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED -#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4 -#endif -#ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME -#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8 -#endif -#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND -#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0 -#endif -#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW -#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1 -#endif -#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY -#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2 -#endif -#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR -#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 -#endif - - -static const char * -lt_int_dyld_error(othererror) - char* othererror; -{ -/* return the dyld error string, or the passed in error string if none */ - NSLinkEditErrors ler; - int lerno; - const char *errstr; - const char *file; - NSLinkEditError(&ler,&lerno,&file,&errstr); - if (!errstr || !strlen(errstr)) errstr = othererror; - return errstr; -} - -static const struct mach_header * -lt_int_dyld_get_mach_header_from_nsmodule(module) - NSModule module; -{ -/* There should probably be an apple dyld api for this */ - int i=_dyld_image_count(); - int j; - const char *modname=NSNameOfModule(module); - const struct mach_header *mh=NULL; - if (!modname) return NULL; - for (j = 0; j < i; j++) - { - if (!strcmp(_dyld_get_image_name(j),modname)) - { - mh=_dyld_get_image_header(j); - break; - } - } - return mh; -} - -static const char* lt_int_dyld_lib_install_name(mh) - const struct mach_header *mh; -{ -/* NSAddImage is also used to get the loaded image, but it only works if the lib - is installed, for uninstalled libs we need to check the install_names against - each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a - different lib was loaded as a result -*/ - int j; - struct load_command *lc; - unsigned long offset = sizeof(struct mach_header); - const char* retStr=NULL; - for (j = 0; j < mh->ncmds; j++) - { - lc = (struct load_command*)(((unsigned long)mh) + offset); - if (LC_ID_DYLIB == lc->cmd) - { - retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset + - (unsigned long)lc); - } - offset += lc->cmdsize; - } - return retStr; -} - -static const struct mach_header * -lt_int_dyld_match_loaded_lib_by_install_name(const char *name) -{ - int i=_dyld_image_count(); - int j; - const struct mach_header *mh=NULL; - const char *id=NULL; - for (j = 0; j < i; j++) - { - id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j)); - if ((id) && (!strcmp(id,name))) - { - mh=_dyld_get_image_header(j); - break; - } - } - return mh; -} - -static NSSymbol -lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh) - const char *symbol; - const struct mach_header *mh; -{ - /* Safe to assume our mh is good */ - int j; - struct load_command *lc; - unsigned long offset = sizeof(struct mach_header); - NSSymbol retSym = 0; - const struct mach_header *mh1; - if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) ) - { - for (j = 0; j < mh->ncmds; j++) - { - lc = (struct load_command*)(((unsigned long)mh) + offset); - if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) - { - mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset + - (unsigned long)lc)); - if (!mh1) - { - /* Maybe NSAddImage can find it */ - mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset + - (unsigned long)lc), - NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED + - NSADDIMAGE_OPTION_WITH_SEARCHING + - NSADDIMAGE_OPTION_RETURN_ON_ERROR ); - } - if (mh1) - { - retSym = ltdl_NSLookupSymbolInImage(mh1, - symbol, - NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW - | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR - ); - if (retSym) break; - } - } - offset += lc->cmdsize; - } - } - return retSym; -} - -static int -sys_dyld_init() -{ - int retCode = 0; - int err = 0; - if (!_dyld_present()) { - retCode=1; - } - else { - err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)<dl_NSAddImage); - err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)<dl_NSLookupSymbolInImage); - err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)<dl_NSIsSymbolNameDefinedInImage); - err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)<dl_NSMakePrivateModulePublic); - } - return retCode; -} - -static lt_module -sys_dyld_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - lt_module module = 0; - NSObjectFileImage ofi = 0; - NSObjectFileImageReturnCode ofirc; - - if (!filename) - return (lt_module)-1; - ofirc = NSCreateObjectFileImageFromFile(filename, &ofi); - switch (ofirc) - { - case NSObjectFileImageSuccess: - module = NSLinkModule(ofi, filename, - NSLINKMODULE_OPTION_RETURN_ON_ERROR - | NSLINKMODULE_OPTION_PRIVATE - | NSLINKMODULE_OPTION_BINDNOW); - NSDestroyObjectFileImage(ofi); - if (module) - ltdl_NSMakePrivateModulePublic(module); - break; - case NSObjectFileImageInappropriateFile: - if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage) - { - module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR); - break; - } - default: - LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN))); - return 0; - } - if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN))); - return module; -} - -static int -sys_dyld_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - int retCode = 0; - int flags = 0; - if (module == (lt_module)-1) return 0; -#ifdef __BIG_ENDIAN__ - if (((struct mach_header *)module)->magic == MH_MAGIC) -#else - if (((struct mach_header *)module)->magic == MH_CIGAM) -#endif - { - LT_DLMUTEX_SETERROR("Can not close a dylib"); - retCode = 1; - } - else - { -#if 1 -/* Currently, if a module contains c++ static destructors and it is unloaded, we - get a segfault in atexit(), due to compiler and dynamic loader differences of - opinion, this works around that. -*/ - if ((const struct section *)NULL != - getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module), - "__DATA","__mod_term_func")) - { - flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; - } -#endif -#ifdef __ppc__ - flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; -#endif - if (!NSUnLinkModule(module,flags)) - { - retCode=1; - LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE))); - } - } - - return retCode; -} - -static lt_ptr -sys_dyld_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_ptr address = 0; - NSSymbol *nssym = 0; - void *unused; - const struct mach_header *mh=NULL; - char saveError[256] = "Symbol not found"; - if (module == (lt_module)-1) - { - _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused); - return address; - } -#ifdef __BIG_ENDIAN__ - if (((struct mach_header *)module)->magic == MH_MAGIC) -#else - if (((struct mach_header *)module)->magic == MH_CIGAM) -#endif - { - if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage) - { - mh=module; - if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol)) - { - nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module, - symbol, - NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW - | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR - ); - } - } - - } - else { - nssym = NSLookupSymbolInModule(module, symbol); - } - if (!nssym) - { - strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255); - saveError[255] = 0; - if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module); - nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh); - } - if (!nssym) - { - LT_DLMUTEX_SETERROR (saveError); - return NULL; - } - return NSAddressOfSymbol(nssym); -} - -static struct lt_user_dlloader sys_dyld = - { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 }; - - -#endif /* HAVE_DYLD */ - - -/* --- DLPREOPEN() INTERFACE LOADER --- */ - - -/* emulate dynamic linking using preloaded_symbols */ - -typedef struct lt_dlsymlists_t -{ - struct lt_dlsymlists_t *next; - const lt_dlsymlist *syms; -} lt_dlsymlists_t; - -static const lt_dlsymlist *default_preloaded_symbols = 0; -static lt_dlsymlists_t *preloaded_symbols = 0; - -static int -presym_init (loader_data) - lt_user_data loader_data; -{ - int errors = 0; - - LT_DLMUTEX_LOCK (); - - preloaded_symbols = 0; - if (default_preloaded_symbols) - { - errors = lt_dlpreload (default_preloaded_symbols); - } - - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -static int -presym_free_symlists () -{ - lt_dlsymlists_t *lists; - - LT_DLMUTEX_LOCK (); - - lists = preloaded_symbols; - while (lists) - { - lt_dlsymlists_t *tmp = lists; - - lists = lists->next; - LT_DLFREE (tmp); - } - preloaded_symbols = 0; - - LT_DLMUTEX_UNLOCK (); - - return 0; -} - -static int -presym_exit (loader_data) - lt_user_data loader_data; -{ - presym_free_symlists (); - return 0; -} - -static int -presym_add_symlist (preloaded) - const lt_dlsymlist *preloaded; -{ - lt_dlsymlists_t *tmp; - lt_dlsymlists_t *lists; - int errors = 0; - - LT_DLMUTEX_LOCK (); - - lists = preloaded_symbols; - while (lists) - { - if (lists->syms == preloaded) - { - goto done; - } - lists = lists->next; - } - - tmp = LT_EMALLOC (lt_dlsymlists_t, 1); - if (tmp) - { - memset (tmp, 0, sizeof(lt_dlsymlists_t)); - tmp->syms = preloaded; - tmp->next = preloaded_symbols; - preloaded_symbols = tmp; - } - else - { - ++errors; - } - - done: - LT_DLMUTEX_UNLOCK (); - return errors; -} - -static lt_module -presym_open (loader_data, filename) - lt_user_data loader_data; - const char *filename; -{ - lt_dlsymlists_t *lists; - lt_module module = (lt_module) 0; - - LT_DLMUTEX_LOCK (); - lists = preloaded_symbols; - - if (!lists) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS)); - goto done; - } - - /* Can't use NULL as the reflective symbol header, as NULL is - used to mark the end of the entire symbol list. Self-dlpreopened - symbols follow this magic number, chosen to be an unlikely - clash with a real module name. */ - if (!filename) - { - filename = "@PROGRAM@"; - } - - while (lists) - { - const lt_dlsymlist *syms = lists->syms; - - while (syms->name) - { - if (!syms->address && strcmp(syms->name, filename) == 0) - { - module = (lt_module) syms; - goto done; - } - ++syms; - } - - lists = lists->next; - } - - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); - - done: - LT_DLMUTEX_UNLOCK (); - return module; -} - -static int -presym_close (loader_data, module) - lt_user_data loader_data; - lt_module module; -{ - /* Just to silence gcc -Wall */ - module = 0; - return 0; -} - -static lt_ptr -presym_sym (loader_data, module, symbol) - lt_user_data loader_data; - lt_module module; - const char *symbol; -{ - lt_dlsymlist *syms = (lt_dlsymlist*) module; - - ++syms; - while (syms->address) - { - if (strcmp(syms->name, symbol) == 0) - { - return syms->address; - } - - ++syms; - } - - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - - return 0; -} - -static struct lt_user_dlloader presym = { - 0, presym_open, presym_close, presym_sym, presym_exit, 0 -}; - - - - - -/* --- DYNAMIC MODULE LOADING --- */ - - -/* The type of a function used at each iteration of foreach_dirinpath(). */ -typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1, - lt_ptr data2)); - -static int foreach_dirinpath LT_PARAMS((const char *search_path, - const char *base_name, - foreach_callback_func *func, - lt_ptr data1, lt_ptr data2)); - -static int find_file_callback LT_PARAMS((char *filename, lt_ptr data, - lt_ptr ignored)); -static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data, - lt_ptr ignored)); -static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1, - lt_ptr data2)); - - -static int canonicalize_path LT_PARAMS((const char *path, - char **pcanonical)); -static int argzize_path LT_PARAMS((const char *path, - char **pargz, - size_t *pargz_len)); -static FILE *find_file LT_PARAMS((const char *search_path, - const char *base_name, - char **pdir)); -static lt_dlhandle *find_handle LT_PARAMS((const char *search_path, - const char *base_name, - lt_dlhandle *handle)); -static int find_module LT_PARAMS((lt_dlhandle *handle, - const char *dir, - const char *libdir, - const char *dlname, - const char *old_name, - int installed)); -static int free_vars LT_PARAMS((char *dlname, char *oldname, - char *libdir, char *deplibs)); -static int load_deplibs LT_PARAMS((lt_dlhandle handle, - char *deplibs)); -static int trim LT_PARAMS((char **dest, - const char *str)); -static int try_dlopen LT_PARAMS((lt_dlhandle *handle, - const char *filename)); -static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle, - const char *filename)); -static int unload_deplibs LT_PARAMS((lt_dlhandle handle)); -static int lt_argz_insert LT_PARAMS((char **pargz, - size_t *pargz_len, - char *before, - const char *entry)); -static int lt_argz_insertinorder LT_PARAMS((char **pargz, - size_t *pargz_len, - const char *entry)); -static int lt_argz_insertdir LT_PARAMS((char **pargz, - size_t *pargz_len, - const char *dirnam, - struct dirent *dp)); -static int lt_dlpath_insertdir LT_PARAMS((char **ppath, - char *before, - const char *dir)); -static int list_files_by_dir LT_PARAMS((const char *dirnam, - char **pargz, - size_t *pargz_len)); -static int file_not_found LT_PARAMS((void)); - -static char *user_search_path= 0; -static lt_dlloader *loaders = 0; -static lt_dlhandle handles = 0; -static int initialized = 0; - -/* Initialize libltdl. */ -int -lt_dlinit () -{ - int errors = 0; - - LT_DLMUTEX_LOCK (); - - /* Initialize only at first call. */ - if (++initialized == 1) - { - handles = 0; - user_search_path = 0; /* empty search path */ - -#if HAVE_LIBDL - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen"); -#endif -#if HAVE_SHL_LOAD - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen"); -#endif -#ifdef __WINDOWS__ - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen"); -#endif -#ifdef __BEOS__ - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen"); -#endif -#if HAVE_DLD - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld"); -#endif -#if HAVE_DYLD - errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld"); - errors += sys_dyld_init(); -#endif - errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload"); - - if (presym_init (presym.dlloader_data)) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER)); - ++errors; - } - else if (errors != 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED)); - ++errors; - } - } - - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -int -lt_dlpreload (preloaded) - const lt_dlsymlist *preloaded; -{ - int errors = 0; - - if (preloaded) - { - errors = presym_add_symlist (preloaded); - } - else - { - presym_free_symlists(); - - LT_DLMUTEX_LOCK (); - if (default_preloaded_symbols) - { - errors = lt_dlpreload (default_preloaded_symbols); - } - LT_DLMUTEX_UNLOCK (); - } - - return errors; -} - -int -lt_dlpreload_default (preloaded) - const lt_dlsymlist *preloaded; -{ - LT_DLMUTEX_LOCK (); - default_preloaded_symbols = preloaded; - LT_DLMUTEX_UNLOCK (); - return 0; -} - -int -lt_dlexit () -{ - /* shut down libltdl */ - lt_dlloader *loader; - int errors = 0; - - LT_DLMUTEX_LOCK (); - loader = loaders; - - if (!initialized) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN)); - ++errors; - goto done; - } - - /* shut down only at last call. */ - if (--initialized == 0) - { - int level; - - while (handles && LT_DLIS_RESIDENT (handles)) - { - handles = handles->next; - } - - /* close all modules */ - for (level = 1; handles; ++level) - { - lt_dlhandle cur = handles; - int saw_nonresident = 0; - - while (cur) - { - lt_dlhandle tmp = cur; - cur = cur->next; - if (!LT_DLIS_RESIDENT (tmp)) - saw_nonresident = 1; - if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level) - { - if (lt_dlclose (tmp)) - { - ++errors; - } - /* Make sure that the handle pointed to by 'cur' still exists. - lt_dlclose recursively closes dependent libraries which removes - them from the linked list. One of these might be the one - pointed to by 'cur'. */ - if (cur) - { - for (tmp = handles; tmp; tmp = tmp->next) - if (tmp == cur) - break; - if (! tmp) - cur = handles; - } - } - } - /* done if only resident modules are left */ - if (!saw_nonresident) - break; - } - - /* close all loaders */ - while (loader) - { - lt_dlloader *next = loader->next; - lt_user_data data = loader->dlloader_data; - if (loader->dlloader_exit && loader->dlloader_exit (data)) - { - ++errors; - } - - LT_DLMEM_REASSIGN (loader, next); - } - loaders = 0; - } - - done: - LT_DLMUTEX_UNLOCK (); - return errors; -} - -static int -tryall_dlopen (handle, filename) - lt_dlhandle *handle; - const char *filename; -{ - lt_dlhandle cur; - lt_dlloader *loader; - const char *saved_error; - int errors = 0; - - LT_DLMUTEX_GETERROR (saved_error); - LT_DLMUTEX_LOCK (); - - cur = handles; - loader = loaders; - - /* check whether the module was already opened */ - while (cur) - { - /* try to dlopen the program itself? */ - if (!cur->info.filename && !filename) - { - break; - } - - if (cur->info.filename && filename - && strcmp (cur->info.filename, filename) == 0) - { - break; - } - - cur = cur->next; - } - - if (cur) - { - ++cur->info.ref_count; - *handle = cur; - goto done; - } - - cur = *handle; - if (filename) - { - /* Comment out the check of file permissions using access. - This call seems to always return -1 with error EACCES. - */ - /* We need to catch missing file errors early so that - file_not_found() can detect what happened. - if (access (filename, R_OK) != 0) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); - ++errors; - goto done; - } */ - - cur->info.filename = lt_estrdup (filename); - if (!cur->info.filename) - { - ++errors; - goto done; - } - } - else - { - cur->info.filename = 0; - } - - while (loader) - { - lt_user_data data = loader->dlloader_data; - - cur->module = loader->module_open (data, filename); - - if (cur->module != 0) - { - break; - } - loader = loader->next; - } - - if (!loader) - { - LT_DLFREE (cur->info.filename); - ++errors; - goto done; - } - - cur->loader = loader; - LT_DLMUTEX_SETERROR (saved_error); - - done: - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -static int -tryall_dlopen_module (handle, prefix, dirname, dlname) - lt_dlhandle *handle; - const char *prefix; - const char *dirname; - const char *dlname; -{ - int error = 0; - char *filename = 0; - size_t filename_len = 0; - size_t dirname_len = LT_STRLEN (dirname); - - assert (handle); - assert (dirname); - assert (dlname); -#ifdef LT_DIRSEP_CHAR - /* Only canonicalized names (i.e. with DIRSEP chars already converted) - should make it into this function: */ - assert (strchr (dirname, LT_DIRSEP_CHAR) == 0); -#endif - - if (dirname_len > 0) - if (dirname[dirname_len -1] == '/') - --dirname_len; - filename_len = dirname_len + 1 + LT_STRLEN (dlname); - - /* Allocate memory, and combine DIRNAME and MODULENAME into it. - The PREFIX (if any) is handled below. */ - filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1); - if (!filename) - return 1; - - sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname); - - /* Now that we have combined DIRNAME and MODULENAME, if there is - also a PREFIX to contend with, simply recurse with the arguments - shuffled. Otherwise, attempt to open FILENAME as a module. */ - if (prefix) - { - error += tryall_dlopen_module (handle, - (const char *) 0, prefix, filename); - } - else if (tryall_dlopen (handle, filename) != 0) - { - ++error; - } - - LT_DLFREE (filename); - return error; -} - -static int -find_module (handle, dir, libdir, dlname, old_name, installed) - lt_dlhandle *handle; - const char *dir; - const char *libdir; - const char *dlname; - const char *old_name; - int installed; -{ - /* Try to open the old library first; if it was dlpreopened, - we want the preopened version of it, even if a dlopenable - module is available. */ - if (old_name && tryall_dlopen (handle, old_name) == 0) - { - return 0; - } - - /* Try to open the dynamic library. */ - if (dlname) - { - /* try to open the installed module */ - if (installed && libdir) - { - if (tryall_dlopen_module (handle, - (const char *) 0, libdir, dlname) == 0) - return 0; - } - - /* try to open the not-installed module */ - if (!installed) - { - if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0) - return 0; - } - - /* maybe it was moved to another directory */ - { - if (dir && (tryall_dlopen_module (handle, - (const char *) 0, dir, dlname) == 0)) - return 0; - } - } - - return 1; -} - - -static int -canonicalize_path (path, pcanonical) - const char *path; - char **pcanonical; -{ - char *canonical = 0; - - assert (path && *path); - assert (pcanonical); - - canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path)); - if (!canonical) - return 1; - - { - size_t dest = 0; - size_t src; - for (src = 0; path[src] != LT_EOS_CHAR; ++src) - { - /* Path separators are not copied to the beginning or end of - the destination, or if another separator would follow - immediately. */ - if (path[src] == LT_PATHSEP_CHAR) - { - if ((dest == 0) - || (path[1+ src] == LT_PATHSEP_CHAR) - || (path[1+ src] == LT_EOS_CHAR)) - continue; - } - - /* Anything other than a directory separator is copied verbatim. */ - if ((path[src] != '/') -#ifdef LT_DIRSEP_CHAR - && (path[src] != LT_DIRSEP_CHAR) -#endif - ) - { - canonical[dest++] = path[src]; - } - /* Directory separators are converted and copied only if they are - not at the end of a path -- i.e. before a path separator or - NULL terminator. */ - else if ((path[1+ src] != LT_PATHSEP_CHAR) - && (path[1+ src] != LT_EOS_CHAR) -#ifdef LT_DIRSEP_CHAR - && (path[1+ src] != LT_DIRSEP_CHAR) -#endif - && (path[1+ src] != '/')) - { - canonical[dest++] = '/'; - } - } - - /* Add an end-of-string marker at the end. */ - canonical[dest] = LT_EOS_CHAR; - } - - /* Assign new value. */ - *pcanonical = canonical; - - return 0; -} - -static int -argzize_path (path, pargz, pargz_len) - const char *path; - char **pargz; - size_t *pargz_len; -{ - error_t error; - - assert (path); - assert (pargz); - assert (pargz_len); - - if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len))) - { - switch (error) - { - case ENOMEM: - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); - break; - default: - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); - break; - } - - return 1; - } - - return 0; -} - -/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element - of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns - non-zero or all elements are exhausted. If BASE_NAME is non-NULL, - it is appended to each SEARCH_PATH element before FUNC is called. */ -static int -foreach_dirinpath (search_path, base_name, func, data1, data2) - const char *search_path; - const char *base_name; - foreach_callback_func *func; - lt_ptr data1; - lt_ptr data2; -{ - int result = 0; - int filenamesize = 0; - size_t lenbase = LT_STRLEN (base_name); - size_t argz_len = 0; - char *argz = 0; - char *filename = 0; - char *canonical = 0; - - LT_DLMUTEX_LOCK (); - - if (!search_path || !*search_path) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); - goto cleanup; - } - - if (canonicalize_path (search_path, &canonical) != 0) - goto cleanup; - - if (argzize_path (canonical, &argz, &argz_len) != 0) - goto cleanup; - - { - char *dir_name = 0; - while ((dir_name = argz_next (argz, argz_len, dir_name))) - { - size_t lendir = LT_STRLEN (dir_name); - - if (lendir +1 +lenbase >= filenamesize) - { - LT_DLFREE (filename); - filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */ - filename = LT_EMALLOC (char, filenamesize); - if (!filename) - goto cleanup; - } - - assert (filenamesize > lendir); - strcpy (filename, dir_name); - - if (base_name && *base_name) - { - if (filename[lendir -1] != '/') - filename[lendir++] = '/'; - strcpy (filename +lendir, base_name); - } - - if ((result = (*func) (filename, data1, data2))) - { - break; - } - } - } - - cleanup: - LT_DLFREE (argz); - LT_DLFREE (canonical); - LT_DLFREE (filename); - - LT_DLMUTEX_UNLOCK (); - - return result; -} - -/* If FILEPATH can be opened, store the name of the directory component - in DATA1, and the opened FILE* structure address in DATA2. Otherwise - DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */ -static int -find_file_callback (filename, data1, data2) - char *filename; - lt_ptr data1; - lt_ptr data2; -{ - char **pdir = (char **) data1; - FILE **pfile = (FILE **) data2; - int is_done = 0; - - assert (filename && *filename); - assert (pdir); - assert (pfile); - - if ((*pfile = fopen (filename, LT_READTEXT_MODE))) - { - char *dirend = strrchr (filename, '/'); - - if (dirend > filename) - *dirend = LT_EOS_CHAR; - - LT_DLFREE (*pdir); - *pdir = lt_estrdup (filename); - is_done = (*pdir == 0) ? -1 : 1; - } - - return is_done; -} - -static FILE * -find_file (search_path, base_name, pdir) - const char *search_path; - const char *base_name; - char **pdir; -{ - FILE *file = 0; - - foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file); - - return file; -} - -static int -find_handle_callback (filename, data, ignored) - char *filename; - lt_ptr data; - lt_ptr ignored; -{ - lt_dlhandle *handle = (lt_dlhandle *) data; - int notfound = access (filename, R_OK); - - /* Bail out if file cannot be read... */ - if (notfound) - return 0; - - /* Try to dlopen the file, but do not continue searching in any - case. */ - if (tryall_dlopen (handle, filename) != 0) - *handle = 0; - - return 1; -} - -/* If HANDLE was found return it, otherwise return 0. If HANDLE was - found but could not be opened, *HANDLE will be set to 0. */ -static lt_dlhandle * -find_handle (search_path, base_name, handle) - const char *search_path; - const char *base_name; - lt_dlhandle *handle; -{ - if (!search_path) - return 0; - - if (!foreach_dirinpath (search_path, base_name, find_handle_callback, - handle, 0)) - return 0; - - return handle; -} - -static int -load_deplibs (handle, deplibs) - lt_dlhandle handle; - char *deplibs; -{ -#if LTDL_DLOPEN_DEPLIBS - char *p, *save_search_path = 0; - int depcount = 0; - int i; - char **names = 0; -#endif - int errors = 0; - - handle->depcount = 0; - -#if LTDL_DLOPEN_DEPLIBS - if (!deplibs) - { - return errors; - } - ++errors; - - LT_DLMUTEX_LOCK (); - if (user_search_path) - { - save_search_path = lt_estrdup (user_search_path); - if (!save_search_path) - goto cleanup; - } - - /* extract search paths and count deplibs */ - p = deplibs; - while (*p) - { - if (!isspace ((int) *p)) - { - char *end = p+1; - while (*end && !isspace((int) *end)) - { - ++end; - } - - if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0) - { - char save = *end; - *end = 0; /* set a temporary string terminator */ - if (lt_dladdsearchdir(p+2)) - { - goto cleanup; - } - *end = save; - } - else - { - ++depcount; - } - - p = end; - } - else - { - ++p; - } - } - - if (!depcount) - { - errors = 0; - goto cleanup; - } - - names = LT_EMALLOC (char *, depcount * sizeof (char*)); - if (!names) - goto cleanup; - - /* now only extract the actual deplibs */ - depcount = 0; - p = deplibs; - while (*p) - { - if (isspace ((int) *p)) - { - ++p; - } - else - { - char *end = p+1; - while (*end && !isspace ((int) *end)) - { - ++end; - } - - if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0) - { - char *name; - char save = *end; - *end = 0; /* set a temporary string terminator */ - if (strncmp(p, "-l", 2) == 0) - { - size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2); - name = LT_EMALLOC (char, 1+ name_len); - if (name) - sprintf (name, "lib%s", p+2); - } - else - name = lt_estrdup(p); - - if (!name) - goto cleanup_names; - - names[depcount++] = name; - *end = save; - } - p = end; - } - } - - /* load the deplibs (in reverse order) - At this stage, don't worry if the deplibs do not load correctly, - they may already be statically linked into the loading application - for instance. There will be a more enlightening error message - later on if the loaded module cannot resolve all of its symbols. */ - if (depcount) - { - int j = 0; - - handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount); - if (!handle->deplibs) - goto cleanup_names; - - for (i = 0; i < depcount; ++i) - { - handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]); - if (handle->deplibs[j]) - { - ++j; - } - } - - handle->depcount = j; /* Number of successfully loaded deplibs */ - errors = 0; - } - - cleanup_names: - for (i = 0; i < depcount; ++i) - { - LT_DLFREE (names[i]); - } - - cleanup: - LT_DLFREE (names); - /* restore the old search path */ - if (user_search_path) { - LT_DLFREE (user_search_path); - user_search_path = save_search_path; - } - LT_DLMUTEX_UNLOCK (); - -#endif - - return errors; -} - -static int -unload_deplibs (handle) - lt_dlhandle handle; -{ - int i; - int errors = 0; - - if (handle->depcount) - { - for (i = 0; i < handle->depcount; ++i) - { - if (!LT_DLIS_RESIDENT (handle->deplibs[i])) - { - errors += lt_dlclose (handle->deplibs[i]); - } - } - LT_DLFREE (handle->deplibs); - } - - return errors; -} - -static int -trim (dest, str) - char **dest; - const char *str; -{ - /* remove the leading and trailing "'" from str - and store the result in dest */ - const char *end = strrchr (str, '\''); - size_t len = LT_STRLEN (str); - char *tmp; - - LT_DLFREE (*dest); - - if (!end) - return 1; - - if (len > 3 && str[0] == '\'') - { - tmp = LT_EMALLOC (char, end - str); - if (!tmp) - return 1; - - strncpy(tmp, &str[1], (end - str) - 1); - tmp[len-3] = LT_EOS_CHAR; - *dest = tmp; - } - else - { - *dest = 0; - } - - return 0; -} - -static int -free_vars (dlname, oldname, libdir, deplibs) - char *dlname; - char *oldname; - char *libdir; - char *deplibs; -{ - LT_DLFREE (dlname); - LT_DLFREE (oldname); - LT_DLFREE (libdir); - LT_DLFREE (deplibs); - - return 0; -} - -static int -try_dlopen (phandle, filename) - lt_dlhandle *phandle; - const char *filename; -{ - const char * ext = 0; - const char * saved_error = 0; - char * canonical = 0; - char * base_name = 0; - char * dir = 0; - char * name = 0; - int errors = 0; - lt_dlhandle newhandle; - - assert (phandle); - assert (*phandle == 0); - - LT_DLMUTEX_GETERROR (saved_error); - - /* dlopen self? */ - if (!filename) - { - *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); - if (*phandle == 0) - return 1; - - memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); - newhandle = *phandle; - - /* lt_dlclose()ing yourself is very bad! Disallow it. */ - LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG); - - if (tryall_dlopen (&newhandle, 0) != 0) - { - LT_DLFREE (*phandle); - return 1; - } - - goto register_handle; - } - - assert (filename && *filename); - - /* Doing this immediately allows internal functions to safely - assume only canonicalized paths are passed. */ - if (canonicalize_path (filename, &canonical) != 0) - { - ++errors; - goto cleanup; - } - - /* If the canonical module name is a path (relative or absolute) - then split it into a directory part and a name part. */ - base_name = strrchr (canonical, '/'); - if (base_name) - { - size_t dirlen = (1+ base_name) - canonical; - - dir = LT_EMALLOC (char, 1+ dirlen); - if (!dir) - { - ++errors; - goto cleanup; - } - - strncpy (dir, canonical, dirlen); - dir[dirlen] = LT_EOS_CHAR; - - ++base_name; - } - else - base_name = canonical; - - assert (base_name && *base_name); - - /* Check whether we are opening a libtool module (.la extension). */ - ext = strrchr (base_name, '.'); - if (ext && strcmp (ext, archive_ext) == 0) - { - /* this seems to be a libtool module */ - FILE * file = 0; - char * dlname = 0; - char * old_name = 0; - char * libdir = 0; - char * deplibs = 0; - char * line = 0; - size_t line_len; - - /* if we can't find the installed flag, it is probably an - installed libtool archive, produced with an old version - of libtool */ - int installed = 1; - - /* extract the module name from the file name */ - name = LT_EMALLOC (char, ext - base_name + 1); - if (!name) - { - ++errors; - goto cleanup; - } - - /* canonicalize the module name */ - { - size_t i; - for (i = 0; i < ext - base_name; ++i) - { - if (isalnum ((int)(base_name[i]))) - { - name[i] = base_name[i]; - } - else - { - name[i] = '_'; - } - } - name[ext - base_name] = LT_EOS_CHAR; - } - - /* Now try to open the .la file. If there is no directory name - component, try to find it first in user_search_path and then other - prescribed paths. Otherwise (or in any case if the module was not - yet found) try opening just the module name as passed. */ - if (!dir) - { - const char *search_path; - - LT_DLMUTEX_LOCK (); - search_path = user_search_path; - if (search_path) - file = find_file (user_search_path, base_name, &dir); - LT_DLMUTEX_UNLOCK (); - - if (!file) - { - search_path = getenv (LTDL_SEARCHPATH_VAR); - if (search_path) - file = find_file (search_path, base_name, &dir); - } - -#ifdef LTDL_SHLIBPATH_VAR - if (!file) - { - search_path = getenv (LTDL_SHLIBPATH_VAR); - if (search_path) - file = find_file (search_path, base_name, &dir); - } -#endif -#ifdef LTDL_SYSSEARCHPATH - if (!file && sys_search_path) - { - file = find_file (sys_search_path, base_name, &dir); - } -#endif - } - if (!file) - { - file = fopen (filename, LT_READTEXT_MODE); - } - - /* If we didn't find the file by now, it really isn't there. Set - the status flag, and bail out. */ - if (!file) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); - ++errors; - goto cleanup; - } - - line_len = LT_FILENAME_MAX; - line = LT_EMALLOC (char, line_len); - if (!line) - { - fclose (file); - ++errors; - goto cleanup; - } - - /* read the .la file */ - while (!feof (file)) - { - if (!fgets (line, (int) line_len, file)) - { - break; - } - - /* Handle the case where we occasionally need to read a line - that is longer than the initial buffer size. */ - while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file))) - { - line = LT_DLREALLOC (char, line, line_len *2); - if (!fgets (&line[line_len -1], (int) line_len +1, file)) - { - break; - } - line_len *= 2; - } - - if (line[0] == '\n' || line[0] == '#') - { - continue; - } - -#undef STR_DLNAME -#define STR_DLNAME "dlname=" - if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0) - { - errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]); - } - -#undef STR_OLD_LIBRARY -#define STR_OLD_LIBRARY "old_library=" - else if (strncmp (line, STR_OLD_LIBRARY, - sizeof (STR_OLD_LIBRARY) - 1) == 0) - { - errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]); - } -#undef STR_LIBDIR -#define STR_LIBDIR "libdir=" - else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0) - { - errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]); - } - -#undef STR_DL_DEPLIBS -#define STR_DL_DEPLIBS "dependency_libs=" - else if (strncmp (line, STR_DL_DEPLIBS, - sizeof (STR_DL_DEPLIBS) - 1) == 0) - { - errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]); - } - else if (strcmp (line, "installed=yes\n") == 0) - { - installed = 1; - } - else if (strcmp (line, "installed=no\n") == 0) - { - installed = 0; - } - -#undef STR_LIBRARY_NAMES -#define STR_LIBRARY_NAMES "library_names=" - else if (! dlname && strncmp (line, STR_LIBRARY_NAMES, - sizeof (STR_LIBRARY_NAMES) - 1) == 0) - { - char *last_libname; - errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]); - if (!errors - && dlname - && (last_libname = strrchr (dlname, ' ')) != 0) - { - last_libname = lt_estrdup (last_libname + 1); - if (!last_libname) - { - ++errors; - goto cleanup; - } - LT_DLMEM_REASSIGN (dlname, last_libname); - } - } - - if (errors) - break; - } - - fclose (file); - LT_DLFREE (line); - - /* allocate the handle */ - *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); - if (*phandle == 0) - ++errors; - - if (errors) - { - free_vars (dlname, old_name, libdir, deplibs); - LT_DLFREE (*phandle); - goto cleanup; - } - - assert (*phandle); - - memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); - if (load_deplibs (*phandle, deplibs) == 0) - { - newhandle = *phandle; - /* find_module may replace newhandle */ - if (find_module (&newhandle, dir, libdir, dlname, old_name, installed)) - { - unload_deplibs (*phandle); - ++errors; - } - } - else - { - ++errors; - } - - free_vars (dlname, old_name, libdir, deplibs); - if (errors) - { - LT_DLFREE (*phandle); - goto cleanup; - } - - if (*phandle != newhandle) - { - unload_deplibs (*phandle); - } - } - else - { - /* not a libtool module */ - *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); - if (*phandle == 0) - { - ++errors; - goto cleanup; - } - - memset (*phandle, 0, sizeof (struct lt_dlhandle_struct)); - newhandle = *phandle; - - /* If the module has no directory name component, try to find it - first in user_search_path and then other prescribed paths. - Otherwise (or in any case if the module was not yet found) try - opening just the module name as passed. */ - if ((dir || (!find_handle (user_search_path, base_name, &newhandle) - && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name, - &newhandle) -#ifdef LTDL_SHLIBPATH_VAR - && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name, - &newhandle) -#endif -#ifdef LTDL_SYSSEARCHPATH - && !find_handle (sys_search_path, base_name, &newhandle) -#endif - ))) - { - if (tryall_dlopen (&newhandle, filename) != 0) - { - newhandle = NULL; - } - } - - if (!newhandle) - { - LT_DLFREE (*phandle); - ++errors; - goto cleanup; - } - } - - register_handle: - LT_DLMEM_REASSIGN (*phandle, newhandle); - - if ((*phandle)->info.ref_count == 0) - { - (*phandle)->info.ref_count = 1; - LT_DLMEM_REASSIGN ((*phandle)->info.name, name); - - LT_DLMUTEX_LOCK (); - (*phandle)->next = handles; - handles = *phandle; - LT_DLMUTEX_UNLOCK (); - } - - LT_DLMUTEX_SETERROR (saved_error); - - cleanup: - LT_DLFREE (dir); - LT_DLFREE (name); - LT_DLFREE (canonical); - - return errors; -} - -lt_dlhandle -lt_dlopen (filename) - const char *filename; -{ - lt_dlhandle handle = 0; - - /* Just incase we missed a code path in try_dlopen() that reports - an error, but forgets to reset handle... */ - if (try_dlopen (&handle, filename) != 0) - return 0; - - return handle; -} - -/* If the last error messge store was `FILE_NOT_FOUND', then return - non-zero. */ -static int -file_not_found () -{ - const char *error = 0; - - LT_DLMUTEX_GETERROR (error); - if (error == LT_DLSTRERROR (FILE_NOT_FOUND)) - return 1; - - return 0; -} - -/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to - open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT, - and if a file is still not found try again with SHLIB_EXT appended - instead. */ -lt_dlhandle -lt_dlopenext (filename) - const char *filename; -{ - lt_dlhandle handle = 0; - char * tmp = 0; - char * ext = 0; - size_t len; - int errors = 0; - - if (!filename) - { - return lt_dlopen (filename); - } - - assert (filename); - - len = LT_STRLEN (filename); - ext = strrchr (filename, '.'); - - /* If FILENAME already bears a suitable extension, there is no need - to try appending additional extensions. */ - if (ext && ((strcmp (ext, archive_ext) == 0) -#ifdef LTDL_SHLIB_EXT - || (strcmp (ext, shlib_ext) == 0) -#endif - )) - { - return lt_dlopen (filename); - } - - /* First try appending ARCHIVE_EXT. */ - tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1); - if (!tmp) - return 0; - - strcpy (tmp, filename); - strcat (tmp, archive_ext); - errors = try_dlopen (&handle, tmp); - - /* If we found FILENAME, stop searching -- whether we were able to - load the file as a module or not. If the file exists but loading - failed, it is better to return an error message here than to - report FILE_NOT_FOUND when the alternatives (foo.so etc) are not - in the module search path. */ - if (handle || ((errors > 0) && !file_not_found ())) - { - LT_DLFREE (tmp); - return handle; - } - -#ifdef LTDL_SHLIB_EXT - /* Try appending SHLIB_EXT. */ - if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext)) - { - LT_DLFREE (tmp); - tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1); - if (!tmp) - return 0; - - strcpy (tmp, filename); - } - else - { - tmp[len] = LT_EOS_CHAR; - } - - strcat(tmp, shlib_ext); - errors = try_dlopen (&handle, tmp); - - /* As before, if the file was found but loading failed, return now - with the current error message. */ - if (handle || ((errors > 0) && !file_not_found ())) - { - LT_DLFREE (tmp); - return handle; - } -#endif - - /* Still here? Then we really did fail to locate any of the file - names we tried. */ - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); - LT_DLFREE (tmp); - return 0; -} - - -static int -lt_argz_insert (pargz, pargz_len, before, entry) - char **pargz; - size_t *pargz_len; - char *before; - const char *entry; -{ - error_t error; - - /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz, - pargz_len, NULL, entry) failed with EINVAL. */ - if (before) - error = argz_insert (pargz, pargz_len, before, entry); - else - error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry)); - - if (error) - { - switch (error) - { - case ENOMEM: - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); - break; - default: - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); - break; - } - return 1; - } - - return 0; -} - -static int -lt_argz_insertinorder (pargz, pargz_len, entry) - char **pargz; - size_t *pargz_len; - const char *entry; -{ - char *before = 0; - - assert (pargz); - assert (pargz_len); - assert (entry && *entry); - - if (*pargz) - while ((before = argz_next (*pargz, *pargz_len, before))) - { - int cmp = strcmp (entry, before); - - if (cmp < 0) break; - if (cmp == 0) return 0; /* No duplicates! */ - } - - return lt_argz_insert (pargz, pargz_len, before, entry); -} - -static int -lt_argz_insertdir (pargz, pargz_len, dirnam, dp) - char **pargz; - size_t *pargz_len; - const char *dirnam; - struct dirent *dp; -{ - char *buf = 0; - size_t buf_len = 0; - char *end = 0; - size_t end_offset = 0; - size_t dir_len = 0; - int errors = 0; - - assert (pargz); - assert (pargz_len); - assert (dp); - - dir_len = LT_STRLEN (dirnam); - end = dp->d_name + LT_D_NAMLEN(dp); - - /* Ignore version numbers. */ - { - char *p; - for (p = end; p -1 > dp->d_name; --p) - if (strchr (".0123456789", p[-1]) == 0) - break; - - if (*p == '.') - end = p; - } - - /* Ignore filename extension. */ - { - char *p; - for (p = end -1; p > dp->d_name; --p) - if (*p == '.') - { - end = p; - break; - } - } - - /* Prepend the directory name. */ - end_offset = end - dp->d_name; - buf_len = dir_len + 1+ end_offset; - buf = LT_EMALLOC (char, 1+ buf_len); - if (!buf) - return ++errors; - - assert (buf); - - strcpy (buf, dirnam); - strcat (buf, "/"); - strncat (buf, dp->d_name, end_offset); - buf[buf_len] = LT_EOS_CHAR; - - /* Try to insert (in order) into ARGZ/ARGZ_LEN. */ - if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0) - ++errors; - - LT_DLFREE (buf); - - return errors; -} - -static int -list_files_by_dir (dirnam, pargz, pargz_len) - const char *dirnam; - char **pargz; - size_t *pargz_len; -{ - DIR *dirp = 0; - int errors = 0; - - assert (dirnam && *dirnam); - assert (pargz); - assert (pargz_len); - assert (dirnam[LT_STRLEN(dirnam) -1] != '/'); - - dirp = opendir (dirnam); - if (dirp) - { - struct dirent *dp = 0; - - while ((dp = readdir (dirp))) - if (dp->d_name[0] != '.') - if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp)) - { - ++errors; - break; - } - - closedir (dirp); - } - else - ++errors; - - return errors; -} - - -/* If there are any files in DIRNAME, call the function passed in - DATA1 (with the name of each file and DATA2 as arguments). */ -static int -foreachfile_callback (dirname, data1, data2) - char *dirname; - lt_ptr data1; - lt_ptr data2; -{ - int (*func) LT_PARAMS((const char *filename, lt_ptr data)) - = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1; - - int is_done = 0; - char *argz = 0; - size_t argz_len = 0; - - if (list_files_by_dir (dirname, &argz, &argz_len) != 0) - goto cleanup; - if (!argz) - goto cleanup; - - { - char *filename = 0; - while ((filename = argz_next (argz, argz_len, filename))) - if ((is_done = (*func) (filename, data2))) - break; - } - - cleanup: - LT_DLFREE (argz); - - return is_done; -} - - -/* Call FUNC for each unique extensionless file in SEARCH_PATH, along - with DATA. The filenames passed to FUNC would be suitable for - passing to lt_dlopenext. The extensions are stripped so that - individual modules do not generate several entries (e.g. libfoo.la, - libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL, - then the same directories that lt_dlopen would search are examined. */ -int -lt_dlforeachfile (search_path, func, data) - const char *search_path; - int (*func) LT_PARAMS ((const char *filename, lt_ptr data)); - lt_ptr data; -{ - int is_done = 0; - - if (search_path) - { - /* If a specific path was passed, search only the directories - listed in it. */ - is_done = foreach_dirinpath (search_path, 0, - foreachfile_callback, func, data); - } - else - { - /* Otherwise search the default paths. */ - is_done = foreach_dirinpath (user_search_path, 0, - foreachfile_callback, func, data); - if (!is_done) - { - is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0, - foreachfile_callback, func, data); - } - -#ifdef LTDL_SHLIBPATH_VAR - if (!is_done) - { - is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0, - foreachfile_callback, func, data); - } -#endif -#ifdef LTDL_SYSSEARCHPATH - if (!is_done) - { - is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0, - foreachfile_callback, func, data); - } -#endif - } - - return is_done; -} - -int -lt_dlclose (handle) - lt_dlhandle handle; -{ - lt_dlhandle cur, last; - int errors = 0; - - LT_DLMUTEX_LOCK (); - - /* check whether the handle is valid */ - last = cur = handles; - while (cur && handle != cur) - { - last = cur; - cur = cur->next; - } - - if (!cur) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - ++errors; - goto done; - } - - handle->info.ref_count--; - - /* Note that even with resident modules, we must track the ref_count - correctly incase the user decides to reset the residency flag - later (even though the API makes no provision for that at the - moment). */ - if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle)) - { - lt_user_data data = handle->loader->dlloader_data; - - if (handle != handles) - { - last->next = handle->next; - } - else - { - handles = handle->next; - } - - errors += handle->loader->module_close (data, handle->module); - errors += unload_deplibs(handle); - - /* It is up to the callers to free the data itself. */ - LT_DLFREE (handle->caller_data); - - LT_DLFREE (handle->info.filename); - LT_DLFREE (handle->info.name); - LT_DLFREE (handle); - - goto done; - } - - if (LT_DLIS_RESIDENT (handle)) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE)); - ++errors; - } - - done: - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -lt_ptr -lt_dlsym (handle, symbol) - lt_dlhandle handle; - const char *symbol; -{ - size_t lensym; - char lsym[LT_SYMBOL_LENGTH]; - char *sym; - lt_ptr address; - lt_user_data data; - - if (!handle) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - return 0; - } - - if (!symbol) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); - return 0; - } - - lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix) - + LT_STRLEN (handle->info.name); - - if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH) - { - sym = lsym; - } - else - { - sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1); - if (!sym) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW)); - return 0; - } - } - - data = handle->loader->dlloader_data; - if (handle->info.name) - { - const char *saved_error; - - LT_DLMUTEX_GETERROR (saved_error); - - /* this is a libtool module */ - if (handle->loader->sym_prefix) - { - strcpy(sym, handle->loader->sym_prefix); - strcat(sym, handle->info.name); - } - else - { - strcpy(sym, handle->info.name); - } - - strcat(sym, "_LTX_"); - strcat(sym, symbol); - - /* try "modulename_LTX_symbol" */ - address = handle->loader->find_sym (data, handle->module, sym); - if (address) - { - if (sym != lsym) - { - LT_DLFREE (sym); - } - return address; - } - LT_DLMUTEX_SETERROR (saved_error); - } - - /* otherwise try "symbol" */ - if (handle->loader->sym_prefix) - { - strcpy(sym, handle->loader->sym_prefix); - strcat(sym, symbol); - } - else - { - strcpy(sym, symbol); - } - - address = handle->loader->find_sym (data, handle->module, sym); - if (sym != lsym) - { - LT_DLFREE (sym); - } - - return address; -} - -const char * -lt_dlerror () -{ - const char *error; - - LT_DLMUTEX_GETERROR (error); - LT_DLMUTEX_SETERROR (0); - - return error ? error : NULL; -} - -static int -lt_dlpath_insertdir (ppath, before, dir) - char **ppath; - char *before; - const char *dir; -{ - int errors = 0; - char *canonical = 0; - char *argz = 0; - size_t argz_len = 0; - - assert (ppath); - assert (dir && *dir); - - if (canonicalize_path (dir, &canonical) != 0) - { - ++errors; - goto cleanup; - } - - assert (canonical && *canonical); - - /* If *PPATH is empty, set it to DIR. */ - if (*ppath == 0) - { - assert (!before); /* BEFORE cannot be set without PPATH. */ - assert (dir); /* Without DIR, don't call this function! */ - - *ppath = lt_estrdup (dir); - if (*ppath == 0) - ++errors; - - return errors; - } - - assert (ppath && *ppath); - - if (argzize_path (*ppath, &argz, &argz_len) != 0) - { - ++errors; - goto cleanup; - } - - /* Convert BEFORE into an equivalent offset into ARGZ. This only works - if *PPATH is already canonicalized, and hence does not change length - with respect to ARGZ. We canonicalize each entry as it is added to - the search path, and don't call this function with (uncanonicalized) - user paths, so this is a fair assumption. */ - if (before) - { - assert (*ppath <= before); - assert (before - *ppath <= strlen (*ppath)); - - before = before - *ppath + argz; - } - - if (lt_argz_insert (&argz, &argz_len, before, dir) != 0) - { - ++errors; - goto cleanup; - } - - argz_stringify (argz, argz_len, LT_PATHSEP_CHAR); - LT_DLMEM_REASSIGN (*ppath, argz); - - cleanup: - LT_DLFREE (canonical); - LT_DLFREE (argz); - - return errors; -} - -int -lt_dladdsearchdir (search_dir) - const char *search_dir; -{ - int errors = 0; - - if (search_dir && *search_dir) - { - LT_DLMUTEX_LOCK (); - if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0) - ++errors; - LT_DLMUTEX_UNLOCK (); - } - - return errors; -} - -int -lt_dlinsertsearchdir (before, search_dir) - const char *before; - const char *search_dir; -{ - int errors = 0; - - if (before) - { - LT_DLMUTEX_LOCK (); - if ((before < user_search_path) - || (before >= user_search_path + LT_STRLEN (user_search_path))) - { - LT_DLMUTEX_UNLOCK (); - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION)); - return 1; - } - LT_DLMUTEX_UNLOCK (); - } - - if (search_dir && *search_dir) - { - LT_DLMUTEX_LOCK (); - if (lt_dlpath_insertdir (&user_search_path, - (char *) before, search_dir) != 0) - { - ++errors; - } - LT_DLMUTEX_UNLOCK (); - } - - return errors; -} - -int -lt_dlsetsearchpath (search_path) - const char *search_path; -{ - int errors = 0; - - LT_DLMUTEX_LOCK (); - LT_DLFREE (user_search_path); - LT_DLMUTEX_UNLOCK (); - - if (!search_path || !LT_STRLEN (search_path)) - { - return errors; - } - - LT_DLMUTEX_LOCK (); - if (canonicalize_path (search_path, &user_search_path) != 0) - ++errors; - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -const char * -lt_dlgetsearchpath () -{ - const char *saved_path; - - LT_DLMUTEX_LOCK (); - saved_path = user_search_path; - LT_DLMUTEX_UNLOCK (); - - return saved_path; -} - -int -lt_dlmakeresident (handle) - lt_dlhandle handle; -{ - int errors = 0; - - if (!handle) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - ++errors; - } - else - { - LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG); - } - - return errors; -} - -int -lt_dlisresident (handle) - lt_dlhandle handle; -{ - if (!handle) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - return -1; - } - - return LT_DLIS_RESIDENT (handle); -} - - - - -/* --- MODULE INFORMATION --- */ - -const lt_dlinfo * -lt_dlgetinfo (handle) - lt_dlhandle handle; -{ - if (!handle) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); - return 0; - } - - return &(handle->info); -} - -lt_dlhandle -lt_dlhandle_next (place) - lt_dlhandle place; -{ - return place ? place->next : handles; -} - -int -lt_dlforeach (func, data) - int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data)); - lt_ptr data; -{ - int errors = 0; - lt_dlhandle cur; - - LT_DLMUTEX_LOCK (); - - cur = handles; - while (cur) - { - lt_dlhandle tmp = cur; - - cur = cur->next; - if ((*func) (tmp, data)) - { - ++errors; - break; - } - } - - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -lt_dlcaller_id -lt_dlcaller_register () -{ - static lt_dlcaller_id last_caller_id = 0; - int result; - - LT_DLMUTEX_LOCK (); - result = ++last_caller_id; - LT_DLMUTEX_UNLOCK (); - - return result; -} - -lt_ptr -lt_dlcaller_set_data (key, handle, data) - lt_dlcaller_id key; - lt_dlhandle handle; - lt_ptr data; -{ - int n_elements = 0; - lt_ptr stale = (lt_ptr) 0; - int i; - - /* This needs to be locked so that the caller data can be updated - simultaneously by different threads. */ - LT_DLMUTEX_LOCK (); - - if (handle->caller_data) - while (handle->caller_data[n_elements].key) - ++n_elements; - - for (i = 0; i < n_elements; ++i) - { - if (handle->caller_data[i].key == key) - { - stale = handle->caller_data[i].data; - break; - } - } - - /* Ensure that there is enough room in this handle's caller_data - array to accept a new element (and an empty end marker). */ - if (i == n_elements) - { - lt_caller_data *temp - = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements); - - if (!temp) - { - stale = 0; - goto done; - } - - handle->caller_data = temp; - - /* We only need this if we needed to allocate a new caller_data. */ - handle->caller_data[i].key = key; - handle->caller_data[1+ i].key = 0; - } - - handle->caller_data[i].data = data; - - done: - LT_DLMUTEX_UNLOCK (); - - return stale; -} - -lt_ptr -lt_dlcaller_get_data (key, handle) - lt_dlcaller_id key; - lt_dlhandle handle; -{ - lt_ptr result = (lt_ptr) 0; - - /* This needs to be locked so that the caller data isn't updated by - another thread part way through this function. */ - LT_DLMUTEX_LOCK (); - - /* Locate the index of the element with a matching KEY. */ - { - int i; - for (i = 0; handle->caller_data[i].key; ++i) - { - if (handle->caller_data[i].key == key) - { - result = handle->caller_data[i].data; - break; - } - } - } - - LT_DLMUTEX_UNLOCK (); - - return result; -} - - - -/* --- USER MODULE LOADER API --- */ - - -int -lt_dlloader_add (place, dlloader, loader_name) - lt_dlloader *place; - const struct lt_user_dlloader *dlloader; - const char *loader_name; -{ - int errors = 0; - lt_dlloader *node = 0, *ptr = 0; - - if ((dlloader == 0) /* diagnose null parameters */ - || (dlloader->module_open == 0) - || (dlloader->module_close == 0) - || (dlloader->find_sym == 0)) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); - return 1; - } - - /* Create a new dlloader node with copies of the user callbacks. */ - node = LT_EMALLOC (lt_dlloader, 1); - if (!node) - return 1; - - node->next = 0; - node->loader_name = loader_name; - node->sym_prefix = dlloader->sym_prefix; - node->dlloader_exit = dlloader->dlloader_exit; - node->module_open = dlloader->module_open; - node->module_close = dlloader->module_close; - node->find_sym = dlloader->find_sym; - node->dlloader_data = dlloader->dlloader_data; - - LT_DLMUTEX_LOCK (); - if (!loaders) - { - /* If there are no loaders, NODE becomes the list! */ - loaders = node; - } - else if (!place) - { - /* If PLACE is not set, add NODE to the end of the - LOADERS list. */ - for (ptr = loaders; ptr->next; ptr = ptr->next) - { - /*NOWORK*/; - } - - ptr->next = node; - } - else if (loaders == place) - { - /* If PLACE is the first loader, NODE goes first. */ - node->next = place; - loaders = node; - } - else - { - /* Find the node immediately preceding PLACE. */ - for (ptr = loaders; ptr->next != place; ptr = ptr->next) - { - /*NOWORK*/; - } - - if (ptr->next != place) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); - ++errors; - } - else - { - /* Insert NODE between PTR and PLACE. */ - node->next = place; - ptr->next = node; - } - } - - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -int -lt_dlloader_remove (loader_name) - const char *loader_name; -{ - lt_dlloader *place = lt_dlloader_find (loader_name); - lt_dlhandle handle; - int errors = 0; - - if (!place) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); - return 1; - } - - LT_DLMUTEX_LOCK (); - - /* Fail if there are any open modules which use this loader. */ - for (handle = handles; handle; handle = handle->next) - { - if (handle->loader == place) - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER)); - ++errors; - goto done; - } - } - - if (place == loaders) - { - /* PLACE is the first loader in the list. */ - loaders = loaders->next; - } - else - { - /* Find the loader before the one being removed. */ - lt_dlloader *prev; - for (prev = loaders; prev->next; prev = prev->next) - { - if (!strcmp (prev->next->loader_name, loader_name)) - { - break; - } - } - - place = prev->next; - prev->next = prev->next->next; - } - - if (place->dlloader_exit) - { - errors = place->dlloader_exit (place->dlloader_data); - } - - LT_DLFREE (place); - - done: - LT_DLMUTEX_UNLOCK (); - - return errors; -} - -lt_dlloader * -lt_dlloader_next (place) - lt_dlloader *place; -{ - lt_dlloader *next; - - LT_DLMUTEX_LOCK (); - next = place ? place->next : loaders; - LT_DLMUTEX_UNLOCK (); - - return next; -} - -const char * -lt_dlloader_name (place) - lt_dlloader *place; -{ - const char *name = 0; - - if (place) - { - LT_DLMUTEX_LOCK (); - name = place ? place->loader_name : 0; - LT_DLMUTEX_UNLOCK (); - } - else - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); - } - - return name; -} - -lt_user_data * -lt_dlloader_data (place) - lt_dlloader *place; -{ - lt_user_data *data = 0; - - if (place) - { - LT_DLMUTEX_LOCK (); - data = place ? &(place->dlloader_data) : 0; - LT_DLMUTEX_UNLOCK (); - } - else - { - LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); - } - - return data; -} - -lt_dlloader * -lt_dlloader_find (loader_name) - const char *loader_name; -{ - lt_dlloader *place = 0; - - LT_DLMUTEX_LOCK (); - for (place = loaders; place; place = place->next) - { - if (strcmp (place->loader_name, loader_name) == 0) - { - break; - } - } - LT_DLMUTEX_UNLOCK (); - - return place; -} diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h deleted file mode 100644 index 1f2b9716c..000000000 --- a/libltdl/ltdl.h +++ /dev/null @@ -1,367 +0,0 @@ -/* ltdl.h -- generic dlopen functions - Copyright (C) 1998-2001, 2003, 2004, 2007 Free Software Foundation, Inc. - Originally by Thomas Tanner - This file is part of GNU Libtool. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -As a special exception to the GNU Lesser General Public License, -if you distribute this file as part of a program or library that -is built using GNU libtool, you may include it under the same -distribution terms that you use for the rest of that program. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free -Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA -*/ - -/* Only include this header file once. */ -#ifndef LTDL_H -#define LTDL_H 1 - -#include /* for size_t declaration */ - - -/* --- MACROS FOR PORTABILITY --- */ - - -/* Saves on those hard to debug '\0' typos.... */ -#define LT_EOS_CHAR '\0' - -/* LTDL_BEGIN_C_DECLS should be used at the beginning of your declarations, - so that C++ compilers don't mangle their names. Use LTDL_END_C_DECLS at - the end of C declarations. */ -#ifdef __cplusplus -# define LT_BEGIN_C_DECLS extern "C" { -# define LT_END_C_DECLS } -#else -# define LT_BEGIN_C_DECLS /* empty */ -# define LT_END_C_DECLS /* empty */ -#endif - -LT_BEGIN_C_DECLS - - -/* LT_PARAMS is a macro used to wrap function prototypes, so that compilers - that don't understand ANSI C prototypes still work, and ANSI C - compilers can issue warnings about type mismatches. */ -#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus) -# define LT_PARAMS(protos) protos -# define lt_ptr void* -#else -# define LT_PARAMS(protos) () -# define lt_ptr char* -#endif - -/* LT_STMT_START/END are used to create macros which expand to a - a single compound statement in a portable way. */ -#if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) -# define LT_STMT_START (void)( -# define LT_STMT_END ) -#else -# if (defined (sun) || defined (__sun__)) -# define LT_STMT_START if (1) -# define LT_STMT_END else (void)0 -# else -# define LT_STMT_START do -# define LT_STMT_END while (0) -# endif -#endif - -/* LT_CONC creates a new concatenated symbol for the compiler - in a portable way. */ -#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER) || defined(_AIX) -# define LT_CONC(s,t) s##t -#else -# define LT_CONC(s,t) s/**/t -#endif - -/* LT_STRLEN can be used safely on NULL pointers. */ -#define LT_STRLEN(s) (((s) && (s)[0]) ? strlen (s) : 0) - - - -/* --- WINDOWS SUPPORT --- */ - - -/* Canonicalise Windows and Cygwin recognition macros. */ -#ifdef __CYGWIN32__ -# ifndef __CYGWIN__ -# define __CYGWIN__ __CYGWIN32__ -# endif -#endif -#if defined(_WIN32) || defined(WIN32) -# ifndef __WINDOWS__ -# ifdef _WIN32 -# define __WINDOWS__ _WIN32 -# else -# ifdef WIN32 -# define __WINDOWS__ WIN32 -# endif -# endif -# endif -#endif - - -#ifdef __WINDOWS__ -# ifndef __CYGWIN__ -/* LT_DIRSEP_CHAR is accepted *in addition* to '/' as a directory - separator when it is set. */ -# define LT_DIRSEP_CHAR '\\' -# define LT_PATHSEP_CHAR ';' -# endif -#endif -#ifndef LT_PATHSEP_CHAR -# define LT_PATHSEP_CHAR ':' -#endif - -/* DLL building support on win32 hosts; mostly to workaround their - ridiculous implementation of data symbol exporting. */ -#ifndef LT_SCOPE -# if defined(__WINDOWS__) || defined(__CYGWIN__) -# ifdef DLL_EXPORT /* defined by libtool (if required) */ -# define LT_SCOPE __declspec(dllexport) -# endif -# ifdef LIBLTDL_DLL_IMPORT /* define if linking with this dll */ - /* note: cygwin/mingw compilers can rely instead on auto-import */ -# define LT_SCOPE extern __declspec(dllimport) -# endif -# endif -# ifndef LT_SCOPE /* static linking or !__WINDOWS__ */ -# define LT_SCOPE extern -# endif -#endif - - -#if defined(_MSC_VER) /* Visual Studio */ -# define R_OK 4 -#endif - - - -/* --- DYNAMIC MODULE LOADING API --- */ - - -typedef struct lt_dlhandle_struct *lt_dlhandle; /* A loaded module. */ - -/* Initialisation and finalisation functions for libltdl. */ -LT_SCOPE int lt_dlinit LT_PARAMS((void)); -LT_SCOPE int lt_dlexit LT_PARAMS((void)); - -/* Module search path manipulation. */ -LT_SCOPE int lt_dladdsearchdir LT_PARAMS((const char *search_dir)); -LT_SCOPE int lt_dlinsertsearchdir LT_PARAMS((const char *before, - const char *search_dir)); -LT_SCOPE int lt_dlsetsearchpath LT_PARAMS((const char *search_path)); -LT_SCOPE const char *lt_dlgetsearchpath LT_PARAMS((void)); -LT_SCOPE int lt_dlforeachfile LT_PARAMS(( - const char *search_path, - int (*func) (const char *filename, lt_ptr data), - lt_ptr data)); - -/* Portable libltdl versions of the system dlopen() API. */ -LT_SCOPE lt_dlhandle lt_dlopen LT_PARAMS((const char *filename)); -LT_SCOPE lt_dlhandle lt_dlopenext LT_PARAMS((const char *filename)); -LT_SCOPE lt_ptr lt_dlsym LT_PARAMS((lt_dlhandle handle, - const char *name)); -LT_SCOPE const char *lt_dlerror LT_PARAMS((void)); -LT_SCOPE int lt_dlclose LT_PARAMS((lt_dlhandle handle)); - -/* Module residency management. */ -LT_SCOPE int lt_dlmakeresident LT_PARAMS((lt_dlhandle handle)); -LT_SCOPE int lt_dlisresident LT_PARAMS((lt_dlhandle handle)); - - - - -/* --- MUTEX LOCKING --- */ - - -typedef void lt_dlmutex_lock LT_PARAMS((void)); -typedef void lt_dlmutex_unlock LT_PARAMS((void)); -typedef void lt_dlmutex_seterror LT_PARAMS((const char *errmsg)); -typedef const char *lt_dlmutex_geterror LT_PARAMS((void)); - -LT_SCOPE int lt_dlmutex_register LT_PARAMS((lt_dlmutex_lock *lock, - lt_dlmutex_unlock *unlock, - lt_dlmutex_seterror *seterror, - lt_dlmutex_geterror *geterror)); - - - - -/* --- MEMORY HANDLING --- */ - - -/* By default, the realloc function pointer is set to our internal - realloc implementation which iself uses lt_dlmalloc and lt_dlfree. - libltdl relies on a featureful realloc, but if you are sure yours - has the right semantics then you can assign it directly. Generally, - it is safe to assign just a malloc() and a free() function. */ -LT_SCOPE lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)); -LT_SCOPE lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)); -LT_SCOPE void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)); - - - - -/* --- PRELOADED MODULE SUPPORT --- */ - - -/* A preopened symbol. Arrays of this type comprise the exported - symbols for a dlpreopened module. */ -typedef struct { - const char *name; - lt_ptr address; -} lt_dlsymlist; - -LT_SCOPE int lt_dlpreload LT_PARAMS((const lt_dlsymlist *preloaded)); -LT_SCOPE int lt_dlpreload_default - LT_PARAMS((const lt_dlsymlist *preloaded)); - -#define LTDL_SET_PRELOADED_SYMBOLS() LT_STMT_START{ \ - extern const lt_dlsymlist lt_preloaded_symbols[]; \ - lt_dlpreload_default(lt_preloaded_symbols); \ - }LT_STMT_END - - - - -/* --- MODULE INFORMATION --- */ - - -/* Read only information pertaining to a loaded module. */ -typedef struct { - char *filename; /* file name */ - char *name; /* module name */ - int ref_count; /* number of times lt_dlopened minus - number of times lt_dlclosed. */ -} lt_dlinfo; - -LT_SCOPE const lt_dlinfo *lt_dlgetinfo LT_PARAMS((lt_dlhandle handle)); -LT_SCOPE lt_dlhandle lt_dlhandle_next LT_PARAMS((lt_dlhandle place)); -LT_SCOPE int lt_dlforeach LT_PARAMS(( - int (*func) (lt_dlhandle handle, lt_ptr data), - lt_ptr data)); - -/* Associating user data with loaded modules. */ -typedef unsigned lt_dlcaller_id; - -LT_SCOPE lt_dlcaller_id lt_dlcaller_register LT_PARAMS((void)); -LT_SCOPE lt_ptr lt_dlcaller_set_data LT_PARAMS((lt_dlcaller_id key, - lt_dlhandle handle, - lt_ptr data)); -LT_SCOPE lt_ptr lt_dlcaller_get_data LT_PARAMS((lt_dlcaller_id key, - lt_dlhandle handle)); - - - -/* --- USER MODULE LOADER API --- */ - - -typedef struct lt_dlloader lt_dlloader; -typedef lt_ptr lt_user_data; -typedef lt_ptr lt_module; - -/* Function pointer types for creating user defined module loaders. */ -typedef lt_module lt_module_open LT_PARAMS((lt_user_data loader_data, - const char *filename)); -typedef int lt_module_close LT_PARAMS((lt_user_data loader_data, - lt_module handle)); -typedef lt_ptr lt_find_sym LT_PARAMS((lt_user_data loader_data, - lt_module handle, - const char *symbol)); -typedef int lt_dlloader_exit LT_PARAMS((lt_user_data loader_data)); - -struct lt_user_dlloader { - const char *sym_prefix; - lt_module_open *module_open; - lt_module_close *module_close; - lt_find_sym *find_sym; - lt_dlloader_exit *dlloader_exit; - lt_user_data dlloader_data; -}; - -LT_SCOPE lt_dlloader *lt_dlloader_next LT_PARAMS((lt_dlloader *place)); -LT_SCOPE lt_dlloader *lt_dlloader_find LT_PARAMS(( - const char *loader_name)); -LT_SCOPE const char *lt_dlloader_name LT_PARAMS((lt_dlloader *place)); -LT_SCOPE lt_user_data *lt_dlloader_data LT_PARAMS((lt_dlloader *place)); -LT_SCOPE int lt_dlloader_add LT_PARAMS((lt_dlloader *place, - const struct lt_user_dlloader *dlloader, - const char *loader_name)); -LT_SCOPE int lt_dlloader_remove LT_PARAMS(( - const char *loader_name)); - - - -/* --- ERROR MESSAGE HANDLING --- */ - - -/* Defining error strings alongside their symbolic names in a macro in - this way allows us to expand the macro in different contexts with - confidence that the enumeration of symbolic names will map correctly - onto the table of error strings. */ -#define lt_dlerror_table \ - LT_ERROR(UNKNOWN, "unknown error") \ - LT_ERROR(DLOPEN_NOT_SUPPORTED, "dlopen support not available") \ - LT_ERROR(INVALID_LOADER, "invalid loader") \ - LT_ERROR(INIT_LOADER, "loader initialization failed") \ - LT_ERROR(REMOVE_LOADER, "loader removal failed") \ - LT_ERROR(FILE_NOT_FOUND, "file not found") \ - LT_ERROR(DEPLIB_NOT_FOUND, "dependency library not found") \ - LT_ERROR(NO_SYMBOLS, "no symbols defined") \ - LT_ERROR(CANNOT_OPEN, "can't open the module") \ - LT_ERROR(CANNOT_CLOSE, "can't close the module") \ - LT_ERROR(SYMBOL_NOT_FOUND, "symbol not found") \ - LT_ERROR(NO_MEMORY, "not enough memory") \ - LT_ERROR(INVALID_HANDLE, "invalid module handle") \ - LT_ERROR(BUFFER_OVERFLOW, "internal buffer overflow") \ - LT_ERROR(INVALID_ERRORCODE, "invalid errorcode") \ - LT_ERROR(SHUTDOWN, "library already shutdown") \ - LT_ERROR(CLOSE_RESIDENT_MODULE, "can't close resident module") \ - LT_ERROR(INVALID_MUTEX_ARGS, "invalid mutex handler registration") \ - LT_ERROR(INVALID_POSITION, "invalid search path insert position") - -/* Enumerate the symbolic error names. */ -enum { -#define LT_ERROR(name, diagnostic) LT_CONC(LT_ERROR_, name), - lt_dlerror_table -#undef LT_ERROR - - LT_ERROR_MAX -}; - -/* These functions are only useful from inside custom module loaders. */ -LT_SCOPE int lt_dladderror LT_PARAMS((const char *diagnostic)); -LT_SCOPE int lt_dlseterror LT_PARAMS((int errorcode)); - - - - -/* --- SOURCE COMPATIBILITY WITH OLD LIBLTDL --- */ - - -#ifdef LT_NON_POSIX_NAMESPACE -# define lt_ptr_t lt_ptr -# define lt_module_t lt_module -# define lt_module_open_t lt_module_open -# define lt_module_close_t lt_module_close -# define lt_find_sym_t lt_find_sym -# define lt_dlloader_exit_t lt_dlloader_exit -# define lt_dlloader_t lt_dlloader -# define lt_dlloader_data_t lt_user_data -#endif - -LT_END_C_DECLS - -#endif /* !LTDL_H */ diff --git a/libltdl/ltmain.sh b/libltdl/ltmain.sh deleted file mode 100644 index f924d3093..000000000 --- a/libltdl/ltmain.sh +++ /dev/null @@ -1,6938 +0,0 @@ -# ltmain.sh - Provide generalized library-building support services. -# NOTE: Changing this file will not affect anything until you rerun configure. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, -# 2007 Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 1996 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -basename="s,^.*/,,g" - -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath="$0" - -# The name of this program: -progname=`echo "$progpath" | $SED $basename` -modename="$progname" - -# Global variables: -EXIT_SUCCESS=0 -EXIT_FAILURE=1 - -PROGRAM=ltmain.sh -PACKAGE=libtool -VERSION="1.5.24 Debian 1.5.24-1" -TIMESTAMP=" (1.1220.2.456 2007/06/24 02:25:32)" - -# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE). -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# Check that we have a working $echo. -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then - # Yippee, $echo works! - : -else - # Restart under the correct shell, and then maybe $echo will work. - exec $SHELL "$progpath" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat <&2 - $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit $EXIT_FAILURE -fi - -# Global variables. -mode=$default_mode -nonopt= -prev= -prevopt= -run= -show="$echo" -show_help= -execute_dlfiles= -duplicate_deps=no -preserve_args= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" -extracted_archives= -extracted_serial=0 - -##################################### -# Shell function definitions: -# This seems to be the best place for them - -# func_mktempdir [string] -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, STRING is the basename for that directory. -func_mktempdir () -{ - my_template="${TMPDIR-/tmp}/${1-$progname}" - - if test "$run" = ":"; then - # Return a directory name, but don't create it in dry-run mode - my_tmpdir="${my_template}-$$" - else - - # If mktemp works, use that first and foremost - my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` - - if test ! -d "$my_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - my_tmpdir="${my_template}-${RANDOM-0}$$" - - save_mktempdir_umask=`umask` - umask 0077 - $mkdir "$my_tmpdir" - umask $save_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$my_tmpdir" || { - $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 - exit $EXIT_FAILURE - } - fi - - $echo "X$my_tmpdir" | $Xsed -} - - -# func_win32_libid arg -# return the library type of file 'arg' -# -# Need a lot of goo to handle *both* DLLs and import libs -# Has to be a shell function in order to 'eat' the argument -# that is supplied when $file_magic_command is called. -func_win32_libid () -{ - win32_libid_type="unknown" - win32_fileres=`file -L $1 2>/dev/null` - case $win32_fileres in - *ar\ archive\ import\ library*) # definitely import - win32_libid_type="x86 archive import" - ;; - *ar\ archive*) # could be an import, or static - if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ - $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then - win32_nmres=`eval $NM -f posix -A $1 | \ - $SED -n -e '1,100{ - / I /{ - s,.*,import, - p - q - } - }'` - case $win32_nmres in - import*) win32_libid_type="x86 archive import";; - *) win32_libid_type="x86 archive static";; - esac - fi - ;; - *DLL*) - win32_libid_type="x86 DLL" - ;; - *executable*) # but shell scripts are "executable" too... - case $win32_fileres in - *MS\ Windows\ PE\ Intel*) - win32_libid_type="x86 DLL" - ;; - esac - ;; - esac - $echo $win32_libid_type -} - - -# func_infer_tag arg -# Infer tagged configuration to use if any are available and -# if one wasn't chosen via the "--tag" command line option. -# Only attempt this if the compiler in the base compile -# command doesn't match the default compiler. -# arg is usually of the form 'gcc ...' -func_infer_tag () -{ - if test -n "$available_tags" && test -z "$tagname"; then - CC_quoted= - for arg in $CC; do - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - CC_quoted="$CC_quoted $arg" - done - case $@ in - # Blanks in the command may have been stripped by the calling shell, - # but not from the CC environment variable when configure was run. - " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; - # Blanks at the start of $base_compile will cause this to fail - # if we don't check for them as well. - *) - for z in $available_tags; do - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" - CC_quoted= - for arg in $CC; do - # Double-quote args containing other shell metacharacters. - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - CC_quoted="$CC_quoted $arg" - done - case "$@ " in - " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) - # The compiler in the base compile command matches - # the one in the tagged configuration. - # Assume this is the tagged configuration we want. - tagname=$z - break - ;; - esac - fi - done - # If $tagname still isn't set, then no tagged configuration - # was found and let the user know that the "--tag" command - # line option must be used. - if test -z "$tagname"; then - $echo "$modename: unable to infer tagged configuration" - $echo "$modename: specify a tag with \`--tag'" 1>&2 - exit $EXIT_FAILURE -# else -# $echo "$modename: using $tagname tagged configuration" - fi - ;; - esac - fi -} - - -# func_extract_an_archive dir oldlib -func_extract_an_archive () -{ - f_ex_an_ar_dir="$1"; shift - f_ex_an_ar_oldlib="$1" - - $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" - $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? - if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 - exit $EXIT_FAILURE - fi -} - -# func_extract_archives gentop oldlib ... -func_extract_archives () -{ - my_gentop="$1"; shift - my_oldlibs=${1+"$@"} - my_oldobjs="" - my_xlib="" - my_xabs="" - my_xdir="" - my_status="" - - $show "${rm}r $my_gentop" - $run ${rm}r "$my_gentop" - $show "$mkdir $my_gentop" - $run $mkdir "$my_gentop" - my_status=$? - if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then - exit $my_status - fi - - for my_xlib in $my_oldlibs; do - # Extract the objects. - case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; - *) my_xabs=`pwd`"/$my_xlib" ;; - esac - my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` - my_xlib_u=$my_xlib - while :; do - case " $extracted_archives " in - *" $my_xlib_u "*) - extracted_serial=`expr $extracted_serial + 1` - my_xlib_u=lt$extracted_serial-$my_xlib ;; - *) break ;; - esac - done - extracted_archives="$extracted_archives $my_xlib_u" - my_xdir="$my_gentop/$my_xlib_u" - - $show "${rm}r $my_xdir" - $run ${rm}r "$my_xdir" - $show "$mkdir $my_xdir" - $run $mkdir "$my_xdir" - exit_status=$? - if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then - exit $exit_status - fi - case $host in - *-darwin*) - $show "Extracting $my_xabs" - # Do not bother doing anything if just a dry run - if test -z "$run"; then - darwin_orig_dir=`pwd` - cd $my_xdir || exit $? - darwin_archive=$my_xabs - darwin_curdir=`pwd` - darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` - darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` - if test -n "$darwin_arches"; then - darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` - darwin_arch= - $show "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches ; do - mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" - lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" - cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" - func_extract_an_archive "`pwd`" "${darwin_base_archive}" - cd "$darwin_curdir" - $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" - done # $darwin_arches - ## Okay now we have a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` - darwin_file= - darwin_files= - for darwin_file in $darwin_filelist; do - darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` - lipo -create -output "$darwin_file" $darwin_files - done # $darwin_filelist - ${rm}r unfat-$$ - cd "$darwin_orig_dir" - else - cd "$darwin_orig_dir" - func_extract_an_archive "$my_xdir" "$my_xabs" - fi # $darwin_arches - fi # $run - ;; - *) - func_extract_an_archive "$my_xdir" "$my_xabs" - ;; - esac - my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` - done - func_extract_archives_result="$my_oldobjs" -} -# End of Shell function definitions -##################################### - -# Darwin sucks -eval std_shrext=\"$shrext_cmds\" - -disable_libs=no - -# Parse our command line options once, thoroughly. -while test "$#" -gt 0 -do - arg="$1" - shift - - case $arg in - -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; - *) optarg= ;; - esac - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - execute_dlfiles) - execute_dlfiles="$execute_dlfiles $arg" - ;; - tag) - tagname="$arg" - preserve_args="${preserve_args}=$arg" - - # Check whether tagname contains only valid characters - case $tagname in - *[!-_A-Za-z0-9,/]*) - $echo "$progname: invalid tag name: $tagname" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - case $tagname in - CC) - # Don't test for the "default" C tag, as we know, it's there, but - # not specially marked. - ;; - *) - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then - taglist="$taglist $tagname" - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" - else - $echo "$progname: ignoring unknown tag $tagname" 1>&2 - fi - ;; - esac - ;; - *) - eval "$prev=\$arg" - ;; - esac - - prev= - prevopt= - continue - fi - - # Have we seen a non-optional argument yet? - case $arg in - --help) - show_help=yes - ;; - - --version) - echo "\ -$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP - -Copyright (C) 2007 Free Software Foundation, Inc. -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - exit $? - ;; - - --config) - ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath - # Now print the configurations for the tags. - for tagname in $taglist; do - ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" - done - exit $? - ;; - - --debug) - $echo "$progname: enabling shell trace mode" - set -x - preserve_args="$preserve_args $arg" - ;; - - --dry-run | -n) - run=: - ;; - - --features) - $echo "host: $host" - if test "$build_libtool_libs" = yes; then - $echo "enable shared libraries" - else - $echo "disable shared libraries" - fi - if test "$build_old_libs" = yes; then - $echo "enable static libraries" - else - $echo "disable static libraries" - fi - exit $? - ;; - - --finish) mode="finish" ;; - - --mode) prevopt="--mode" prev=mode ;; - --mode=*) mode="$optarg" ;; - - --preserve-dup-deps) duplicate_deps="yes" ;; - - --quiet | --silent) - show=: - preserve_args="$preserve_args $arg" - ;; - - --tag) - prevopt="--tag" - prev=tag - preserve_args="$preserve_args --tag" - ;; - --tag=*) - set tag "$optarg" ${1+"$@"} - shift - prev=tag - preserve_args="$preserve_args --tag" - ;; - - -dlopen) - prevopt="-dlopen" - prev=execute_dlfiles - ;; - - -*) - $echo "$modename: unrecognized option \`$arg'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - ;; - - *) - nonopt="$arg" - break - ;; - esac -done - -if test -n "$prevopt"; then - $echo "$modename: option \`$prevopt' requires an argument" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE -fi - -case $disable_libs in -no) - ;; -shared) - build_libtool_libs=no - build_old_libs=yes - ;; -static) - build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` - ;; -esac - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - -if test -z "$show_help"; then - - # Infer the operation mode. - if test -z "$mode"; then - $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 - $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 - case $nonopt in - *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) - mode=link - for arg - do - case $arg in - -c) - mode=compile - break - ;; - esac - done - ;; - *db | *dbx | *strace | *truss) - mode=execute - ;; - *install*|cp|mv) - mode=install - ;; - *rm) - mode=uninstall - ;; - *) - # If we have no mode, but dlfiles were specified, then do execute mode. - test -n "$execute_dlfiles" && mode=execute - - # Just use the default operation mode. - if test -z "$mode"; then - if test -n "$nonopt"; then - $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 - else - $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 - fi - fi - ;; - esac - fi - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$execute_dlfiles" && test "$mode" != execute; then - $echo "$modename: unrecognized option \`-dlopen'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$modename --help --mode=$mode' for more information." - - # These modes are in order of execution frequency so that they run quickly. - case $mode in - # libtool compile mode - compile) - modename="$modename: compile" - # Get the compilation command and the source file. - base_compile= - srcfile="$nonopt" # always keep a non-empty value in "srcfile" - suppress_opt=yes - suppress_output= - arg_mode=normal - libobj= - later= - - for arg - do - case $arg_mode in - arg ) - # do not "continue". Instead, add this to base_compile - lastarg="$arg" - arg_mode=normal - ;; - - target ) - libobj="$arg" - arg_mode=normal - continue - ;; - - normal ) - # Accept any command-line options. - case $arg in - -o) - if test -n "$libobj" ; then - $echo "$modename: you cannot specify \`-o' more than once" 1>&2 - exit $EXIT_FAILURE - fi - arg_mode=target - continue - ;; - - -static | -prefer-pic | -prefer-non-pic) - later="$later $arg" - continue - ;; - - -no-suppress) - suppress_opt=no - continue - ;; - - -Xcompiler) - arg_mode=arg # the next one goes into the "base_compile" arg list - continue # The current "srcfile" will either be retained or - ;; # replaced later. I would guess that would be a bug. - - -Wc,*) - args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` - lastarg= - save_ifs="$IFS"; IFS=',' - for arg in $args; do - IFS="$save_ifs" - - # Double-quote args containing other shell metacharacters. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - lastarg="$lastarg $arg" - done - IFS="$save_ifs" - lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` - - # Add the arguments to base_compile. - base_compile="$base_compile $lastarg" - continue - ;; - - * ) - # Accept the current argument as the source file. - # The previous "srcfile" becomes the current argument. - # - lastarg="$srcfile" - srcfile="$arg" - ;; - esac # case $arg - ;; - esac # case $arg_mode - - # Aesthetically quote the previous argument. - lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` - - case $lastarg in - # Double-quote args containing other shell metacharacters. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, and some SunOS ksh mistreat backslash-escaping - # in scan sets (worked around with variable expansion), - # and furthermore cannot handle '|' '&' '(' ')' in scan sets - # at all, so we specify them separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - lastarg="\"$lastarg\"" - ;; - esac - - base_compile="$base_compile $lastarg" - done # for arg - - case $arg_mode in - arg) - $echo "$modename: you must specify an argument for -Xcompile" - exit $EXIT_FAILURE - ;; - target) - $echo "$modename: you must specify a target with \`-o'" 1>&2 - exit $EXIT_FAILURE - ;; - *) - # Get the name of the library object. - [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - xform='[cCFSifmso]' - case $libobj in - *.ada) xform=ada ;; - *.adb) xform=adb ;; - *.ads) xform=ads ;; - *.asm) xform=asm ;; - *.c++) xform=c++ ;; - *.cc) xform=cc ;; - *.ii) xform=ii ;; - *.class) xform=class ;; - *.cpp) xform=cpp ;; - *.cxx) xform=cxx ;; - *.[fF][09]?) xform=[fF][09]. ;; - *.for) xform=for ;; - *.java) xform=java ;; - *.obj) xform=obj ;; - esac - - libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` - - case $libobj in - *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; - *) - $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - func_infer_tag $base_compile - - for arg in $later; do - case $arg in - -static) - build_old_libs=yes - continue - ;; - - -prefer-pic) - pic_mode=yes - continue - ;; - - -prefer-non-pic) - pic_mode=no - continue - ;; - esac - done - - qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` - case $qlibobj in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - qlibobj="\"$qlibobj\"" ;; - esac - test "X$libobj" != "X$qlibobj" \ - && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." - objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` - xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$obj"; then - xdir= - else - xdir=$xdir/ - fi - lobj=${xdir}$objdir/$objname - - if test -z "$base_compile"; then - $echo "$modename: you must specify a compilation command" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Delete any leftover library objects. - if test "$build_old_libs" = yes; then - removelist="$obj $lobj $libobj ${libobj}T" - else - removelist="$lobj $libobj ${libobj}T" - fi - - $run $rm $removelist - trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 - - # On Cygwin there's no "real" PIC flag so we must build both object types - case $host_os in - cygwin* | mingw* | pw32* | os2*) - pic_mode=default - ;; - esac - if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then - # non-PIC code in shared libraries is not supported - pic_mode=default - fi - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} - lockfile="$output_obj.lock" - removelist="$removelist $output_obj $lockfile" - trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 - else - output_obj= - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then - until $run ln "$progpath" "$lockfile" 2>/dev/null; do - $show "Waiting for $lockfile to be removed" - sleep 2 - done - elif test "$need_locks" = warn; then - if test -f "$lockfile"; then - $echo "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit $EXIT_FAILURE - fi - $echo "$srcfile" > "$lockfile" - fi - - if test -n "$fix_srcfile_path"; then - eval srcfile=\"$fix_srcfile_path\" - fi - qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` - case $qsrcfile in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - qsrcfile="\"$qsrcfile\"" ;; - esac - - $run $rm "$libobj" "${libobj}T" - - # Create a libtool object file (analogous to a ".la" file), - # but don't create it if we're doing a dry run. - test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then - $echo "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed, then go on to compile the next one - if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then - $show "$mv $output_obj $lobj" - if $run $mv $output_obj $lobj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # Append the name of the PIC object to the libtool object file. - test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then - $echo "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed - if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then - $show "$mv $output_obj $obj" - if $run $mv $output_obj $obj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # Append the name of the non-PIC object the libtool object file. - # Only append if the libtool object file exists. - test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - -static) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=built - ;; - -static-libtool-libs) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - esac - build_libtool_libs=no - build_old_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test "$#" -gt 0; do - arg="$1" - shift - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test - ;; - *) qarg=$arg ;; - esac - libtool_args="$libtool_args $qarg" - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - output) - compile_command="$compile_command @OUTPUT@" - finalize_command="$finalize_command @OUTPUT@" - ;; - esac - - case $prev in - dlfiles|dlprefiles) - if test "$preload" = no; then - # Add the symbol object into the linking commands. - compile_command="$compile_command @SYMFILE@" - finalize_command="$finalize_command @SYMFILE@" - preload=yes - fi - case $arg in - *.la | *.lo) ;; # We handle these cases below. - force) - if test "$dlself" = no; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test "$prev" = dlprefiles; then - dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test "$prev" = dlfiles; then - dlfiles="$dlfiles $arg" - else - dlprefiles="$dlprefiles $arg" - fi - prev= - continue - ;; - esac - ;; - expsyms) - export_symbols="$arg" - if test ! -f "$arg"; then - $echo "$modename: symbol file \`$arg' does not exist" - exit $EXIT_FAILURE - fi - prev= - continue - ;; - expsyms_regex) - export_symbols_regex="$arg" - prev= - continue - ;; - inst_prefix) - inst_prefix_dir="$arg" - prev= - continue - ;; - precious_regex) - precious_files_regex="$arg" - prev= - continue - ;; - release) - release="-$arg" - prev= - continue - ;; - objectlist) - if test -f "$arg"; then - save_arg=$arg - moreargs= - for fil in `cat $save_arg` - do -# moreargs="$moreargs $fil" - arg=$fil - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - pic_object= - non_pic_object= - - # Read the .lo file - # If there is no directory component, then add one. - case $arg in - */* | *\\*) . $arg ;; - *) . ./$arg ;; - esac - - if test -z "$pic_object" || \ - test -z "$non_pic_object" || - test "$pic_object" = none && \ - test "$non_pic_object" = none; then - $echo "$modename: cannot find name of object for \`$arg'" 1>&2 - exit $EXIT_FAILURE - fi - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - dlfiles="$dlfiles $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - dlprefiles="$dlprefiles $pic_object" - prev= - fi - - # A PIC object. - libobjs="$libobjs $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - non_pic_objects="$non_pic_objects $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if test -z "$run"; then - $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 - exit $EXIT_FAILURE - else - # Dry-run case. - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` - non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` - libobjs="$libobjs $pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" - fi - fi - done - else - $echo "$modename: link input file \`$save_arg' does not exist" - exit $EXIT_FAILURE - fi - arg=$save_arg - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case $arg in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - $echo "$modename: only absolute run-paths are allowed" 1>&2 - exit $EXIT_FAILURE - ;; - esac - if test "$prev" = rpath; then - case "$rpath " in - *" $arg "*) ;; - *) rpath="$rpath $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) xrpath="$xrpath $arg" ;; - esac - fi - prev= - continue - ;; - xcompiler) - compiler_flags="$compiler_flags $qarg" - prev= - compile_command="$compile_command $qarg" - finalize_command="$finalize_command $qarg" - continue - ;; - xlinker) - linker_flags="$linker_flags $qarg" - compiler_flags="$compiler_flags $wl$qarg" - prev= - compile_command="$compile_command $wl$qarg" - finalize_command="$finalize_command $wl$qarg" - continue - ;; - xcclinker) - linker_flags="$linker_flags $qarg" - compiler_flags="$compiler_flags $qarg" - prev= - compile_command="$compile_command $qarg" - finalize_command="$finalize_command $qarg" - continue - ;; - shrext) - shrext_cmds="$arg" - prev= - continue - ;; - darwin_framework|darwin_framework_skip) - test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - prev= - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi # test -n "$prev" - - prevarg="$arg" - - case $arg in - -all-static) - if test -n "$link_static_flag"; then - compile_command="$compile_command $link_static_flag" - finalize_command="$finalize_command $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 - continue - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - $echo "$modename: more than one -exported-symbols argument is not allowed" - exit $EXIT_FAILURE - fi - if test "X$arg" = "X-export-symbols"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -framework|-arch|-isysroot) - case " $CC " in - *" ${arg} ${1} "* | *" ${arg} ${1} "*) - prev=darwin_framework_skip ;; - *) compiler_flags="$compiler_flags $arg" - prev=darwin_framework ;; - esac - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - continue - ;; - - -inst-prefix-dir) - prev=inst_prefix - continue - ;; - - # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* - # so, if we see these flags be careful not to treat them like -L - -L[A-Z][A-Z]*:*) - case $with_gcc/$host in - no/*-*-irix* | /*-*-irix*) - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - ;; - esac - continue - ;; - - -L*) - dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 - absdir="$dir" - notinst_path="$notinst_path $dir" - fi - dir="$absdir" - ;; - esac - case "$deplibs " in - *" -L$dir "*) ;; - *) - deplibs="$deplibs -L$dir" - lib_search_path="$lib_search_path $dir" - ;; - esac - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) - testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$dir:"*) ;; - *) dllsearchpath="$dllsearchpath:$dir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - *) dllsearchpath="$dllsearchpath:$testbindir";; - esac - ;; - esac - continue - ;; - - -l*) - if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) - # These systems don't actually have a C or math library (as such) - continue - ;; - *-*-os2*) - # These systems don't actually have a C library (as such) - test "X$arg" = "X-lc" && continue - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C and math libraries are in the System framework - deplibs="$deplibs -framework System" - continue - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - test "X$arg" = "X-lc" && continue - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - test "X$arg" = "X-lc" && continue - ;; - esac - elif test "X$arg" = "X-lc_r"; then - case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc_r directly, use -pthread flag. - continue - ;; - esac - fi - deplibs="$deplibs $arg" - continue - ;; - - # Tru64 UNIX uses -model [arg] to determine the layout of C++ - # classes, name mangling, and exception handling. - -model) - compile_command="$compile_command $arg" - compiler_flags="$compiler_flags $arg" - finalize_command="$finalize_command $arg" - prev=xcompiler - continue - ;; - - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) - compiler_flags="$compiler_flags $arg" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - continue - ;; - - -module) - module=yes - continue - ;; - - # -64, -mips[0-9] enable 64-bit mode on the SGI compiler - # -r[0-9][0-9]* specifies the processor on the SGI compiler - # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler - # +DA*, +DD* enable 64-bit mode on the HP compiler - # -q* pass through compiler args for the IBM compiler - # -m* pass through architecture-specific compiler args for GCC - # -m*, -t[45]*, -txscale* pass through architecture-specific - # compiler args for GCC - # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC - # -F/path gives path to uninstalled frameworks, gcc on darwin - # @file GCC response files - -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ - -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) - - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - compiler_flags="$compiler_flags $arg" - continue - ;; - - -shrext) - prev=shrext - continue - ;; - - -no-fast-install) - fast_install=no - continue - ;; - - -no-install) - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*) - # The PATH hackery in wrapper scripts is required on Windows - # and Darwin in order for the loader to find any dlls it needs. - $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 - $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 - fast_install=no - ;; - *) no_install=yes ;; - esac - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -objectlist) - prev=objectlist - continue - ;; - - -o) prev=output ;; - - -precious-files-regex) - prev=precious_regex - continue - ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - $echo "$modename: only absolute run-paths are allowed" 1>&2 - exit $EXIT_FAILURE - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) xrpath="$xrpath $dir" ;; - esac - continue - ;; - - -static | -static-libtool-libs) - # The effects of -static are defined in a previous loop. - # We used to do the same as -all-static on platforms that - # didn't have a PIC flag, but the assumption that the effects - # would be equivalent was wrong. It would break on at least - # Digital Unix and AIX. - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - -version-number) - prev=vinfo - vinfo_number=yes - continue - ;; - - -Wc,*) - args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - case $flag in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - flag="\"$flag\"" - ;; - esac - arg="$arg $wl$flag" - compiler_flags="$compiler_flags $flag" - done - IFS="$save_ifs" - arg=`$echo "X$arg" | $Xsed -e "s/^ //"` - ;; - - -Wl,*) - args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - case $flag in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - flag="\"$flag\"" - ;; - esac - arg="$arg $wl$flag" - compiler_flags="$compiler_flags $wl$flag" - linker_flags="$linker_flags $flag" - done - IFS="$save_ifs" - arg=`$echo "X$arg" | $Xsed -e "s/^ //"` - ;; - - -Xcompiler) - prev=xcompiler - continue - ;; - - -Xlinker) - prev=xlinker - continue - ;; - - -XCClinker) - prev=xcclinker - continue - ;; - - # Some other compiler flag. - -* | +*) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - ;; - - *.$objext) - # A standard object. - objs="$objs $arg" - ;; - - *.lo) - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - pic_object= - non_pic_object= - - # Read the .lo file - # If there is no directory component, then add one. - case $arg in - */* | *\\*) . $arg ;; - *) . ./$arg ;; - esac - - if test -z "$pic_object" || \ - test -z "$non_pic_object" || - test "$pic_object" = none && \ - test "$non_pic_object" = none; then - $echo "$modename: cannot find name of object for \`$arg'" 1>&2 - exit $EXIT_FAILURE - fi - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - dlfiles="$dlfiles $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - dlprefiles="$dlprefiles $pic_object" - prev= - fi - - # A PIC object. - libobjs="$libobjs $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - non_pic_objects="$non_pic_objects $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if test -z "$run"; then - $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 - exit $EXIT_FAILURE - else - # Dry-run case. - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` - non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` - libobjs="$libobjs $pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" - fi - fi - ;; - - *.$libext) - # An archive. - deplibs="$deplibs $arg" - old_deplibs="$old_deplibs $arg" - continue - ;; - - *.la) - # A libtool-controlled library. - - if test "$prev" = dlfiles; then - # This library was specified with -dlopen. - dlfiles="$dlfiles $arg" - prev= - elif test "$prev" = dlprefiles; then - # The library was specified with -dlpreopen. - dlprefiles="$dlprefiles $arg" - prev= - else - deplibs="$deplibs $arg" - fi - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - ;; - esac # arg - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - fi - done # argument parsing loop - - if test -n "$prev"; then - $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` - libobjs_save="$libobjs" - - if test -n "$shlibpath_var"; then - # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` - else - shlib_search_path= - fi - eval sys_lib_search_path=\"$sys_lib_search_path_spec\" - eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" - - output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` - if test "X$output_objdir" = "X$output"; then - output_objdir="$objdir" - else - output_objdir="$output_objdir/$objdir" - fi - # Create the object directory. - if test ! -d "$output_objdir"; then - $show "$mkdir $output_objdir" - $run $mkdir $output_objdir - exit_status=$? - if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then - exit $exit_status - fi - fi - - # Determine the type of output - case $output in - "") - $echo "$modename: you must specify an output file" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - ;; - *.$libext) linkmode=oldlib ;; - *.lo | *.$objext) linkmode=obj ;; - *.la) linkmode=lib ;; - *) linkmode=prog ;; # Anything else should be a program. - esac - - case $host in - *cygwin* | *mingw* | *pw32*) - # don't eliminate duplications in $postdeps and $predeps - duplicate_compiler_generated_deps=yes - ;; - *) - duplicate_compiler_generated_deps=$duplicate_deps - ;; - esac - specialdeplibs= - - libs= - # Find all interdependent deplibs by searching for libraries - # that are linked more than once (e.g. -la -lb -la) - for deplib in $deplibs; do - if test "X$duplicate_deps" = "Xyes" ; then - case "$libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - libs="$libs $deplib" - done - - if test "$linkmode" = lib; then - libs="$predeps $libs $compiler_lib_search_path $postdeps" - - # Compute libraries that are listed more than once in $predeps - # $postdeps and mark them as special (i.e., whose duplicates are - # not to be eliminated). - pre_post_deps= - if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then - for pre_post_dep in $predeps $postdeps; do - case "$pre_post_deps " in - *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; - esac - pre_post_deps="$pre_post_deps $pre_post_dep" - done - fi - pre_post_deps= - fi - - deplibs= - newdependency_libs= - newlib_search_path= - need_relink=no # whether we're linking any uninstalled libtool libraries - notinst_deplibs= # not-installed libtool libraries - case $linkmode in - lib) - passes="conv link" - for file in $dlfiles $dlprefiles; do - case $file in - *.la) ;; - *) - $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 - exit $EXIT_FAILURE - ;; - esac - done - ;; - prog) - compile_deplibs= - finalize_deplibs= - alldeplibs=no - newdlfiles= - newdlprefiles= - passes="conv scan dlopen dlpreopen link" - ;; - *) passes="conv" - ;; - esac - for pass in $passes; do - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan"; then - libs="$deplibs" - deplibs= - fi - if test "$linkmode" = prog; then - case $pass in - dlopen) libs="$dlfiles" ;; - dlpreopen) libs="$dlprefiles" ;; - link) - libs="$deplibs %DEPLIBS%" - test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" - ;; - esac - fi - if test "$pass" = dlopen; then - # Collect dlpreopened libraries - save_deplibs="$deplibs" - deplibs= - fi - for deplib in $libs; do - lib= - found=no - case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - compiler_flags="$compiler_flags $deplib" - fi - continue - ;; - -l*) - if test "$linkmode" != lib && test "$linkmode" != prog; then - $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 - continue - fi - name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` - for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do - for search_ext in .la $std_shrext .so .a; do - # Search the libtool library - lib="$searchdir/lib${name}${search_ext}" - if test -f "$lib"; then - if test "$search_ext" = ".la"; then - found=yes - else - found=no - fi - break 2 - fi - done - done - if test "$found" != yes; then - # deplib doesn't seem to be a libtool library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - else # deplib is a libtool library - # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, - # We need to do some special things here, and not later. - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $deplib "*) - if (${SED} -e '2q' $lib | - grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - library_names= - old_library= - case $lib in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - for l in $old_library $library_names; do - ll="$l" - done - if test "X$ll" = "X$old_library" ; then # only static version available - found=no - ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` - test "X$ladir" = "X$lib" && ladir="." - lib=$ladir/$old_library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - fi - ;; - *) ;; - esac - fi - fi - ;; # -l - -L*) - case $linkmode in - lib) - deplibs="$deplib $deplibs" - test "$pass" = conv && continue - newdependency_libs="$deplib $newdependency_libs" - newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` - ;; - prog) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - if test "$pass" = scan; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` - ;; - *) - $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 - ;; - esac # linkmode - continue - ;; # -L - -R*) - if test "$pass" = link; then - dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` - # Make sure the xrpath contains only unique directories. - case "$xrpath " in - *" $dir "*) ;; - *) xrpath="$xrpath $dir" ;; - esac - fi - deplibs="$deplib $deplibs" - continue - ;; - *.la) lib="$deplib" ;; - *.$libext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - case $linkmode in - lib) - valid_a_lib=no - case $deplibs_check_method in - match_pattern*) - set dummy $deplibs_check_method - match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` - if eval $echo \"$deplib\" 2>/dev/null \ - | $SED 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=yes - fi - ;; - pass_all) - valid_a_lib=yes - ;; - esac - if test "$valid_a_lib" != yes; then - $echo - $echo "*** Warning: Trying to link with static lib archive $deplib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have" - $echo "*** because the file extensions .$libext of this argument makes me believe" - $echo "*** that it is just a static archive that I should not used here." - else - $echo - $echo "*** Warning: Linking the shared library $output against the" - $echo "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - fi - continue - ;; - prog) - if test "$pass" != link; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - continue - ;; - esac # linkmode - ;; # *.$libext - *.lo | *.$objext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - elif test "$linkmode" = prog; then - if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then - # If there is no dlopen support or we're linking statically, - # we need to preload. - newdlprefiles="$newdlprefiles $deplib" - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - newdlfiles="$newdlfiles $deplib" - fi - fi - continue - ;; - %DEPLIBS%) - alldeplibs=yes - continue - ;; - esac # case $deplib - if test "$found" = yes || test -f "$lib"; then : - else - $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 - exit $EXIT_FAILURE - fi - - # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - - ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` - test "X$ladir" = "X$lib" && ladir="." - - dlname= - dlopen= - dlpreopen= - libdir= - library_names= - old_library= - # If the library was installed with an old release of libtool, - # it will not redefine variables installed, or shouldnotlink - installed=yes - shouldnotlink=no - avoidtemprpath= - - - # Read the .la file - case $lib in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan" || - { test "$linkmode" != prog && test "$linkmode" != lib; }; then - test -n "$dlopen" && dlfiles="$dlfiles $dlopen" - test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" - fi - - if test "$pass" = conv; then - # Only check for convenience libraries - deplibs="$lib $deplibs" - if test -z "$libdir"; then - if test -z "$old_library"; then - $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 - exit $EXIT_FAILURE - fi - # It is a libtool convenience library, so add in its objects. - convenience="$convenience $ladir/$objdir/$old_library" - old_convenience="$old_convenience $ladir/$objdir/$old_library" - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if test "X$duplicate_deps" = "Xyes" ; then - case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - tmp_libs="$tmp_libs $deplib" - done - elif test "$linkmode" != prog && test "$linkmode" != lib; then - $echo "$modename: \`$lib' is not a convenience library" 1>&2 - exit $EXIT_FAILURE - fi - continue - fi # $pass = conv - - - # Get the name of the library we link against. - linklib= - for l in $old_library $library_names; do - linklib="$l" - done - if test -z "$linklib"; then - $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 - exit $EXIT_FAILURE - fi - - # This library was specified with -dlopen. - if test "$pass" = dlopen; then - if test -z "$libdir"; then - $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 - exit $EXIT_FAILURE - fi - if test -z "$dlname" || - test "$dlopen_support" != yes || - test "$build_libtool_libs" = no; then - # If there is no dlname, no dlopen support or we're linking - # statically, we need to preload. We also need to preload any - # dependent libraries so libltdl's deplib preloader doesn't - # bomb out in the load deplibs phase. - dlprefiles="$dlprefiles $lib $dependency_libs" - else - newdlfiles="$newdlfiles $lib" - fi - continue - fi # $pass = dlopen - - # We need an absolute path. - case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; - *) - abs_ladir=`cd "$ladir" && pwd` - if test -z "$abs_ladir"; then - $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 - $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 - abs_ladir="$ladir" - fi - ;; - esac - laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - - # Find the relevant object directory and library name. - if test "X$installed" = Xyes; then - if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - $echo "$modename: warning: library \`$lib' was moved." 1>&2 - dir="$ladir" - absdir="$abs_ladir" - libdir="$abs_ladir" - else - dir="$libdir" - absdir="$libdir" - fi - test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes - else - if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir="$ladir" - absdir="$abs_ladir" - # Remove this search path later - notinst_path="$notinst_path $abs_ladir" - else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" - # Remove this search path later - notinst_path="$notinst_path $abs_ladir" - fi - fi # $installed = yes - name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` - - # This library was specified with -dlpreopen. - if test "$pass" = dlpreopen; then - if test -z "$libdir"; then - $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 - exit $EXIT_FAILURE - fi - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - newdlprefiles="$newdlprefiles $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - newdlprefiles="$newdlprefiles $dir/$dlname" - else - newdlprefiles="$newdlprefiles $dir/$linklib" - fi - fi # $pass = dlpreopen - - if test -z "$libdir"; then - # Link the convenience library - if test "$linkmode" = lib; then - deplibs="$dir/$old_library $deplibs" - elif test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$dir/$old_library $compile_deplibs" - finalize_deplibs="$dir/$old_library $finalize_deplibs" - else - deplibs="$lib $deplibs" # used for prog,scan pass - fi - continue - fi - - - if test "$linkmode" = prog && test "$pass" != link; then - newlib_search_path="$newlib_search_path $ladir" - deplibs="$lib $deplibs" - - linkalldeplibs=no - if test "$link_all_deplibs" != no || test -z "$library_names" || - test "$build_libtool_libs" = no; then - linkalldeplibs=yes - fi - - tmp_libs= - for deplib in $dependency_libs; do - case $deplib in - -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test - esac - # Need to link against all dependency_libs? - if test "$linkalldeplibs" = yes; then - deplibs="$deplib $deplibs" - else - # Need to hardcode shared library paths - # or/and link against static libraries - newdependency_libs="$deplib $newdependency_libs" - fi - if test "X$duplicate_deps" = "Xyes" ; then - case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - tmp_libs="$tmp_libs $deplib" - done # for deplib - continue - fi # $linkmode = prog... - - if test "$linkmode,$pass" = "prog,link"; then - if test -n "$library_names" && - { { test "$prefer_static_libs" = no || - test "$prefer_static_libs,$installed" = "built,yes"; } || - test -z "$old_library"; }; then - # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then - # Make sure the rpath contains only unique directories. - case "$temp_rpath " in - *" $dir "*) ;; - *" $absdir "*) ;; - *) temp_rpath="$temp_rpath $absdir" ;; - esac - fi - - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) compile_rpath="$compile_rpath $absdir" - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" - esac - ;; - esac - fi # $linkmode,$pass = prog,link... - - if test "$alldeplibs" = yes && - { test "$deplibs_check_method" = pass_all || - { test "$build_libtool_libs" = yes && - test -n "$library_names"; }; }; then - # We only need to search for static libraries - continue - fi - fi - - link_static=no # Whether the deplib will be linked statically - use_static_libs=$prefer_static_libs - if test "$use_static_libs" = built && test "$installed" = yes ; then - use_static_libs=no - fi - if test -n "$library_names" && - { test "$use_static_libs" = no || test -z "$old_library"; }; then - if test "$installed" = no; then - notinst_deplibs="$notinst_deplibs $lib" - need_relink=yes - fi - # This is a shared library - - # Warn about portability, can't link against -module's on - # some systems (darwin) - if test "$shouldnotlink" = yes && test "$pass" = link ; then - $echo - if test "$linkmode" = prog; then - $echo "*** Warning: Linking the executable $output against the loadable module" - else - $echo "*** Warning: Linking the shared library $output against the loadable module" - fi - $echo "*** $linklib is not portable!" - fi - if test "$linkmode" = lib && - test "$hardcode_into_libs" = yes; then - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) compile_rpath="$compile_rpath $absdir" - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" - esac - ;; - esac - fi - - if test -n "$old_archive_from_expsyms_cmds"; then - # figure out the soname - set dummy $library_names - realname="$2" - shift; shift - libname=`eval \\$echo \"$libname_spec\"` - # use dlname if we got it. it's perfectly good, no? - if test -n "$dlname"; then - soname="$dlname" - elif test -n "$soname_spec"; then - # bleh windows - case $host in - *cygwin* | mingw*) - major=`expr $current - $age` - versuffix="-$major" - ;; - esac - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - - # Make a new name for the extract_expsyms_cmds to use - soroot="$soname" - soname=`$echo $soroot | ${SED} -e 's/^.*\///'` - newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" - - # If the library has no export list, then create one now - if test -f "$output_objdir/$soname-def"; then : - else - $show "extracting exported symbol list from \`$soname'" - save_ifs="$IFS"; IFS='~' - cmds=$extract_expsyms_cmds - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - - # Create $newlib - if test -f "$output_objdir/$newlib"; then :; else - $show "generating import library for \`$soname'" - save_ifs="$IFS"; IFS='~' - cmds=$old_archive_from_expsyms_cmds - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - # make sure the library variables are pointing to the new library - dir=$output_objdir - linklib=$newlib - fi # test -n "$old_archive_from_expsyms_cmds" - - if test "$linkmode" = prog || test "$mode" != relink; then - add_shlibpath= - add_dir= - add= - lib_linked=yes - case $hardcode_action in - immediate | unsupported) - if test "$hardcode_direct" = no; then - add="$dir/$linklib" - case $host in - *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; - *-*-sysv4*uw2*) add_dir="-L$dir" ;; - *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir="-L$dir" ;; - *-*-darwin* ) - # if the lib is a module then we can not link against - # it, someone is ignoring the new warnings I added - if /usr/bin/file -L $add 2> /dev/null | - $EGREP ": [^:]* bundle" >/dev/null ; then - $echo "** Warning, lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then - $echo - $echo "** And there doesn't seem to be a static archive available" - $echo "** The link will probably fail, sorry" - else - add="$dir/$old_library" - fi - fi - esac - elif test "$hardcode_minus_L" = no; then - case $host in - *-*-sunos*) add_shlibpath="$dir" ;; - esac - add_dir="-L$dir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = no; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - relink) - if test "$hardcode_direct" = yes; then - add="$dir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$dir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - add_dir="$add_dir -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - *) lib_linked=no ;; - esac - - if test "$lib_linked" != yes; then - $echo "$modename: configuration error: unsupported hardcode properties" - exit $EXIT_FAILURE - fi - - if test -n "$add_shlibpath"; then - case :$compile_shlibpath: in - *":$add_shlibpath:"*) ;; - *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; - esac - fi - if test "$linkmode" = prog; then - test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" - test -n "$add" && compile_deplibs="$add $compile_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - if test "$hardcode_direct" != yes && \ - test "$hardcode_minus_L" != yes && \ - test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; - esac - fi - fi - fi - - if test "$linkmode" = prog || test "$mode" = relink; then - add_shlibpath= - add_dir= - add= - # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes; then - add="$libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; - esac - add="-l$name" - elif test "$hardcode_automatic" = yes; then - if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib" ; then - add="$inst_prefix_dir$libdir/$linklib" - else - add="$libdir/$linklib" - fi - else - # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - add_dir="$add_dir -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - fi - - if test "$linkmode" = prog; then - test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" - test -n "$add" && finalize_deplibs="$add $finalize_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - fi - fi - elif test "$linkmode" = prog; then - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" - compile_deplibs="$dir/$linklib $compile_deplibs" - finalize_deplibs="$dir/$linklib $finalize_deplibs" - else - compile_deplibs="-l$name -L$dir $compile_deplibs" - finalize_deplibs="-l$name -L$dir $finalize_deplibs" - fi - elif test "$build_libtool_libs" = yes; then - # Not a shared library - if test "$deplibs_check_method" != pass_all; then - # We're trying link a shared library against a static one - # but the system doesn't support it. - - # Just print a warning and add the library to dependency_libs so - # that the program can be linked against the static library. - $echo - $echo "*** Warning: This system can not link to static lib archive $lib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have." - if test "$module" = yes; then - $echo "*** But as you try to build a module library, libtool will still create " - $echo "*** a static module, that should work as long as the dlopening application" - $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." - if test -z "$global_symbol_pipe"; then - $echo - $echo "*** However, this would only work if libtool was able to extract symbol" - $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - $echo "*** not find such a program. So, this module is probably useless." - $echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - else - deplibs="$dir/$old_library $deplibs" - link_static=yes - fi - fi # link shared/static library? - - if test "$linkmode" = lib; then - if test -n "$dependency_libs" && - { test "$hardcode_into_libs" != yes || - test "$build_old_libs" = yes || - test "$link_static" = yes; }; then - # Extract -R from dependency_libs - temp_deplibs= - for libdir in $dependency_libs; do - case $libdir in - -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` - case " $xrpath " in - *" $temp_xrpath "*) ;; - *) xrpath="$xrpath $temp_xrpath";; - esac;; - *) temp_deplibs="$temp_deplibs $libdir";; - esac - done - dependency_libs="$temp_deplibs" - fi - - newlib_search_path="$newlib_search_path $absdir" - # Link against this library - test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" - # ... and its dependency_libs - tmp_libs= - for deplib in $dependency_libs; do - newdependency_libs="$deplib $newdependency_libs" - if test "X$duplicate_deps" = "Xyes" ; then - case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - tmp_libs="$tmp_libs $deplib" - done - - if test "$link_all_deplibs" != no; then - # Add the search paths of all dependency libraries - for deplib in $dependency_libs; do - case $deplib in - -L*) path="$deplib" ;; - *.la) - dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$deplib" && dir="." - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 - absdir="$dir" - fi - ;; - esac - if grep "^installed=no" $deplib > /dev/null; then - path="$absdir/$objdir" - else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - if test -z "$libdir"; then - $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - if test "$absdir" != "$libdir"; then - $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 - fi - path="$absdir" - fi - depdepl= - case $host in - *-*-darwin*) - # we do not want to link against static libs, - # but need to link against shared - eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names" ; then - for tmp in $deplibrary_names ; do - depdepl=$tmp - done - if test -f "$path/$depdepl" ; then - depdepl="$path/$depdepl" - fi - # do not add paths which are already there - case " $newlib_search_path " in - *" $path "*) ;; - *) newlib_search_path="$newlib_search_path $path";; - esac - fi - path="" - ;; - *) - path="-L$path" - ;; - esac - ;; - -l*) - case $host in - *-*-darwin*) - # Again, we only want to link against shared libraries - eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` - for tmp in $newlib_search_path ; do - if test -f "$tmp/lib$tmp_libs.dylib" ; then - eval depdepl="$tmp/lib$tmp_libs.dylib" - break - fi - done - path="" - ;; - *) continue ;; - esac - ;; - *) continue ;; - esac - case " $deplibs " in - *" $path "*) ;; - *) deplibs="$path $deplibs" ;; - esac - case " $deplibs " in - *" $depdepl "*) ;; - *) deplibs="$depdepl $deplibs" ;; - esac - done - fi # link_all_deplibs != no - fi # linkmode = lib - done # for deplib in $libs - dependency_libs="$newdependency_libs" - if test "$pass" = dlpreopen; then - # Link the dlpreopened libraries before other libraries - for deplib in $save_deplibs; do - deplibs="$deplib $deplibs" - done - fi - if test "$pass" != dlopen; then - if test "$pass" != conv; then - # Make sure lib_search_path contains only unique directories. - lib_search_path= - for dir in $newlib_search_path; do - case "$lib_search_path " in - *" $dir "*) ;; - *) lib_search_path="$lib_search_path $dir" ;; - esac - done - newlib_search_path= - fi - - if test "$linkmode,$pass" != "prog,link"; then - vars="deplibs" - else - vars="compile_deplibs finalize_deplibs" - fi - for var in $vars dependency_libs; do - # Add libraries to $var in reverse order - eval tmp_libs=\"\$$var\" - new_libs= - for deplib in $tmp_libs; do - # FIXME: Pedantically, this is the right thing to do, so - # that some nasty dependency loop isn't accidentally - # broken: - #new_libs="$deplib $new_libs" - # Pragmatically, this seems to cause very few problems in - # practice: - case $deplib in - -L*) new_libs="$deplib $new_libs" ;; - -R*) ;; - *) - # And here is the reason: when a library appears more - # than once as an explicit dependence of a library, or - # is implicitly linked in more than once by the - # compiler, it is considered special, and multiple - # occurrences thereof are not removed. Compare this - # with having the same library being listed as a - # dependency of multiple other libraries: in this case, - # we know (pedantically, we assume) the library does not - # need to be listed more than once, so we keep only the - # last copy. This is not always right, but it is rare - # enough that we require users that really mean to play - # such unportable linking tricks to link the library - # using -Wl,-lname, so that libtool does not consider it - # for duplicate removal. - case " $specialdeplibs " in - *" $deplib "*) new_libs="$deplib $new_libs" ;; - *) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$deplib $new_libs" ;; - esac - ;; - esac - ;; - esac - done - tmp_libs= - for deplib in $new_libs; do - case $deplib in - -L*) - case " $tmp_libs " in - *" $deplib "*) ;; - *) tmp_libs="$tmp_libs $deplib" ;; - esac - ;; - *) tmp_libs="$tmp_libs $deplib" ;; - esac - done - eval $var=\"$tmp_libs\" - done # for var - fi - # Last step: remove runtime libs from dependency_libs - # (they stay in deplibs) - tmp_libs= - for i in $dependency_libs ; do - case " $predeps $postdeps $compiler_lib_search_path " in - *" $i "*) - i="" - ;; - esac - if test -n "$i" ; then - tmp_libs="$tmp_libs $i" - fi - done - dependency_libs=$tmp_libs - done # for pass - if test "$linkmode" = prog; then - dlfiles="$newdlfiles" - dlprefiles="$newdlprefiles" - fi - - case $linkmode in - oldlib) - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 - fi - - if test -n "$rpath"; then - $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 - fi - - if test -n "$xrpath"; then - $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 - fi - - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 - fi - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs="$output" - objs="$objs$old_deplibs" - ;; - - lib) - # Make sure we only generate libraries of the form `libNAME.la'. - case $outputname in - lib*) - name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - ;; - *) - if test "$module" = no; then - $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - if test "$need_lib_prefix" != no; then - # Add the "lib" prefix for modules if required - name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - else - libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` - fi - ;; - esac - - if test -n "$objs"; then - if test "$deplibs_check_method" != pass_all; then - $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 - exit $EXIT_FAILURE - else - $echo - $echo "*** Warning: Linking the shared library $output against the non-libtool" - $echo "*** objects $objs is not portable!" - libobjs="$libobjs $objs" - fi - fi - - if test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 - fi - - set dummy $rpath - if test "$#" -gt 2; then - $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 - fi - install_libdir="$2" - - oldlibs= - if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then - # Building a libtool convenience library. - # Some compilers have problems with a `.al' extension so - # convenience libraries should have the same extension an - # archive normally would. - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 - fi - else - - # Parse the version information argument. - save_ifs="$IFS"; IFS=':' - set dummy $vinfo 0 0 0 - IFS="$save_ifs" - - if test -n "$8"; then - $echo "$modename: too many parameters to \`-version-info'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # convert absolute version numbers to libtool ages - # this retains compatibility with .la files and attempts - # to make the code below a bit more comprehensible - - case $vinfo_number in - yes) - number_major="$2" - number_minor="$3" - number_revision="$4" - # - # There are really only two kinds -- those that - # use the current revision as the major version - # and those that subtract age and use age as - # a minor version. But, then there is irix - # which has an extra 1 added just for fun - # - case $version_type in - darwin|linux|osf|windows|none) - current=`expr $number_major + $number_minor` - age="$number_minor" - revision="$number_revision" - ;; - freebsd-aout|freebsd-elf|sunos) - current="$number_major" - revision="$number_minor" - age="0" - ;; - irix|nonstopux) - current=`expr $number_major + $number_minor` - age="$number_minor" - revision="$number_minor" - lt_irix_increment=no - ;; - *) - $echo "$modename: unknown library version type \`$version_type'" 1>&2 - $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit $EXIT_FAILURE - ;; - esac - ;; - no) - current="$2" - revision="$3" - age="$4" - ;; - esac - - # Check that each of the things are valid numbers. - case $current in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - case $revision in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - case $age in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - if test "$age" -gt "$current"; then - $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit $EXIT_FAILURE - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case $version_type in - none) ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - major=.`expr $current - $age` - versuffix="$major.$age.$revision" - # Darwin ld doesn't like 0 for these options... - minor_current=`expr $current + 1` - xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - ;; - - freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; - ;; - - freebsd-elf) - major=".$current" - versuffix=".$current"; - ;; - - irix | nonstopux) - if test "X$lt_irix_increment" = "Xno"; then - major=`expr $current - $age` - else - major=`expr $current - $age + 1` - fi - case $version_type in - nonstopux) verstring_prefix=nonstopux ;; - *) verstring_prefix=sgi ;; - esac - verstring="$verstring_prefix$major.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test "$loop" -ne 0; do - iface=`expr $revision - $loop` - loop=`expr $loop - 1` - verstring="$verstring_prefix$major.$iface:$verstring" - done - - # Before this point, $major must not contain `.'. - major=.$major - versuffix="$major.$revision" - ;; - - linux) - major=.`expr $current - $age` - versuffix="$major.$age.$revision" - ;; - - osf) - major=.`expr $current - $age` - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$age - while test "$loop" -ne 0; do - iface=`expr $current - $loop` - loop=`expr $loop - 1` - verstring="$verstring:${iface}.0" - done - - # Make executables depend on our current version. - verstring="$verstring:${current}.0" - ;; - - sunos) - major=".$current" - versuffix=".$current.$revision" - ;; - - windows) - # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 filesystems. - major=`expr $current - $age` - versuffix="-$major" - ;; - - *) - $echo "$modename: unknown library version type \`$version_type'" 1>&2 - $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit $EXIT_FAILURE - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - case $version_type in - darwin) - # we can't check for "0.0" in archive_cmds due to quoting - # problems, so we reset it completely - verstring= - ;; - *) - verstring="0.0" - ;; - esac - if test "$need_version" = no; then - versuffix= - else - versuffix=".0.0" - fi - fi - - # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then - major= - versuffix= - verstring="" - fi - - # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 - build_libtool_libs=no - build_old_libs=yes - fi - else - # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" - fi - fi - - if test "$mode" != relink; then - # Remove our outputs, but don't remove object files since they - # may have been created when compiling PIC objects. - removelist= - tempremovelist=`$echo "$output_objdir/*"` - for p in $tempremovelist; do - case $p in - *.$objext) - ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) - if test "X$precious_files_regex" != "X"; then - if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 - then - continue - fi - fi - removelist="$removelist $p" - ;; - *) ;; - esac - done - if test -n "$removelist"; then - $show "${rm}r $removelist" - $run ${rm}r $removelist - fi - fi - - # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then - oldlibs="$oldlibs $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` - fi - - # Eliminate all temporary directories. - #for path in $notinst_path; do - # lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` - # deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` - # dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` - #done - - if test -n "$xrpath"; then - # If the user specified any rpath flags, then add them. - temp_xrpath= - for libdir in $xrpath; do - temp_xrpath="$temp_xrpath -R$libdir" - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" ;; - esac - done - if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then - dependency_libs="$temp_xrpath $dependency_libs" - fi - fi - - # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles="$dlfiles" - dlfiles= - for lib in $old_dlfiles; do - case " $dlprefiles $dlfiles " in - *" $lib "*) ;; - *) dlfiles="$dlfiles $lib" ;; - esac - done - - # Make sure dlprefiles contains only unique files - old_dlprefiles="$dlprefiles" - dlprefiles= - for lib in $old_dlprefiles; do - case "$dlprefiles " in - *" $lib "*) ;; - *) dlprefiles="$dlprefiles $lib" ;; - esac - done - - if test "$build_libtool_libs" = yes; then - if test -n "$rpath"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - deplibs="$deplibs -framework System" - ;; - *-*-netbsd*) - # Don't link with libc until the a.out ld.so is fixed. - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - ;; - *) - # Add libc to deplibs on all other systems if necessary. - if test "$build_libtool_need_lc" = "yes"; then - deplibs="$deplibs -lc" - fi - ;; - esac - fi - - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release="" - versuffix="" - major="" - newdeplibs= - droppeddeps=no - case $deplibs_check_method in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behavior. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $rm conftest.c - cat > conftest.c </dev/null` - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null \ - | grep " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib="$potent_lib" - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` - case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ - | ${SED} 10q \ - | $EGREP "$file_magic_regex" > /dev/null; then - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - $echo - $echo "*** Warning: linker path does not have real file for library $a_deplib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have" - $echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $echo "*** with $libname but no candidates were found. (...for file magic test)" - else - $echo "*** with $libname and none of the candidates passed a file format test" - $echo "*** using a file magic. Last file checked: $potlib" - fi - fi - else - # Add a -L argument. - newdeplibs="$newdeplibs $a_deplib" - fi - done # Gone through all deplibs. - ;; - match_pattern*) - set dummy $deplibs_check_method - match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` - for a_deplib in $deplibs; do - name=`expr $a_deplib : '-l\(.*\)'` - # If $name is empty we are operating on a -L argument. - if test -n "$name" && test "$name" != "0"; then - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $a_deplib "*) - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - ;; - esac - fi - if test -n "$a_deplib" ; then - libname=`eval \\$echo \"$libname_spec\"` - for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - potential_libs=`ls $i/$libname[.-]* 2>/dev/null` - for potent_lib in $potential_libs; do - potlib="$potent_lib" # see symlink-check above in file_magic test - if eval $echo \"$potent_lib\" 2>/dev/null \ - | ${SED} 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - $echo - $echo "*** Warning: linker path does not have real file for library $a_deplib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have" - $echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $echo "*** with $libname but no candidates were found. (...for regex pattern test)" - else - $echo "*** with $libname and none of the candidates passed a file format test" - $echo "*** using a regex pattern. Last file checked: $potlib" - fi - fi - else - # Add a -L argument. - newdeplibs="$newdeplibs $a_deplib" - fi - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs="" - tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ - -e 's/ -[LR][^ ]*//g'` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - for i in $predeps $postdeps ; do - # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` - done - fi - if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ - | grep . >/dev/null; then - $echo - if test "X$deplibs_check_method" = "Xnone"; then - $echo "*** Warning: inter-library dependencies are not supported in this platform." - else - $echo "*** Warning: inter-library dependencies are not known to be supported." - fi - $echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - fi - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` - ;; - esac - - if test "$droppeddeps" = yes; then - if test "$module" = yes; then - $echo - $echo "*** Warning: libtool could not satisfy all declared inter-library" - $echo "*** dependencies of module $libname. Therefore, libtool will create" - $echo "*** a static module, that should work as long as the dlopening" - $echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - $echo - $echo "*** However, this would only work if libtool was able to extract symbol" - $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - $echo "*** not find such a program. So, this module is probably useless." - $echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - $echo "*** The inter-library dependencies that have been dropped here will be" - $echo "*** automatically added whenever a program is linked with this library" - $echo "*** or is declared to -dlopen it." - - if test "$allow_undefined" = no; then - $echo - $echo "*** Since this library must not contain undefined symbols," - $echo "*** because either the platform does not support them or" - $echo "*** it was explicitly requested with -no-undefined," - $echo "*** libtool will only create a static version of it." - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $deplibs " in - *" -L$path/$objdir "*) - new_libs="$new_libs -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$new_libs $deplib" ;; - esac - ;; - *) new_libs="$new_libs $deplib" ;; - esac - done - deplibs="$new_libs" - - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - if test "$hardcode_into_libs" = yes; then - # Hardcode the library paths - hardcode_libdirs= - dep_rpath= - rpath="$finalize_rpath" - test "$mode" != relink && rpath="$compile_rpath$rpath" - for libdir in $rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - dep_rpath="$dep_rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) perm_rpath="$perm_rpath $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - if test -n "$hardcode_libdir_flag_spec_ld"; then - case $archive_cmds in - *\$LD*) eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" ;; - *) eval dep_rpath=\"$hardcode_libdir_flag_spec\" ;; - esac - else - eval dep_rpath=\"$hardcode_libdir_flag_spec\" - fi - fi - if test -n "$runpath_var" && test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - rpath="$rpath$dir:" - done - eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" - fi - test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" - fi - - shlibpath="$finalize_shlibpath" - test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" - if test -n "$shlibpath"; then - eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" - fi - - # Get the real and link names of the library. - eval shared_ext=\"$shrext_cmds\" - eval library_names=\"$library_names_spec\" - set dummy $library_names - realname="$2" - shift; shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - if test -z "$dlname"; then - dlname=$soname - fi - - lib="$output_objdir/$realname" - linknames= - for link - do - linknames="$linknames $link" - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - $show "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $run $rm $export_symbols - cmds=$export_symbols_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - if len=`expr "X$cmd" : ".*"` && - test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then - $show "$cmd" - $run eval "$cmd" || exit $? - skipped_export=false - else - # The command line is too long to execute in one step. - $show "using reloadable object file for export list..." - skipped_export=: - # Break out early, otherwise skipped_export may be - # set to false by a later but shorter cmd. - break - fi - done - IFS="$save_ifs" - if test -n "$export_symbols_regex"; then - $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" - $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - $show "$mv \"${export_symbols}T\" \"$export_symbols\"" - $run eval '$mv "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' - fi - - tmp_deplibs= - for test_deplib in $deplibs; do - case " $convenience " in - *" $test_deplib "*) ;; - *) - tmp_deplibs="$tmp_deplibs $test_deplib" - ;; - esac - done - deplibs="$tmp_deplibs" - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - else - gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" - - func_extract_archives $gentop $convenience - libobjs="$libobjs $func_extract_archives_result" - fi - fi - - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - linker_flags="$linker_flags $flag" - fi - - # Make a backup of the uninstalled library when relinking - if test "$mode" = relink; then - $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? - fi - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - eval test_cmds=\"$module_expsym_cmds\" - cmds=$module_expsym_cmds - else - eval test_cmds=\"$module_cmds\" - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval test_cmds=\"$archive_expsym_cmds\" - cmds=$archive_expsym_cmds - else - eval test_cmds=\"$archive_cmds\" - cmds=$archive_cmds - fi - fi - - if test "X$skipped_export" != "X:" && - len=`expr "X$test_cmds" : ".*" 2>/dev/null` && - test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then - : - else - # The command line is too long to link in one step, link piecewise. - $echo "creating reloadable object files..." - - # Save the value of $output and $libobjs because we want to - # use them later. If we have whole_archive_flag_spec, we - # want to use save_libobjs as it was before - # whole_archive_flag_spec was expanded, because we can't - # assume the linker understands whole_archive_flag_spec. - # This may have to be revisited, in case too many - # convenience libraries get linked in and end up exceeding - # the spec. - if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - fi - save_output=$output - output_la=`$echo "X$output" | $Xsed -e "$basename"` - - # Clear the reloadable object creation command queue and - # initialize k to one. - test_cmds= - concat_cmds= - objlist= - delfiles= - last_robj= - k=1 - output=$output_objdir/$output_la-${k}.$objext - # Loop over the list of objects to be linked. - for obj in $save_libobjs - do - eval test_cmds=\"$reload_cmds $objlist $last_robj\" - if test "X$objlist" = X || - { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && - test "$len" -le "$max_cmd_len"; }; then - objlist="$objlist $obj" - else - # The command $test_cmds is almost too long, add a - # command to the queue. - if test "$k" -eq 1 ; then - # The first file doesn't have a previous command to add. - eval concat_cmds=\"$reload_cmds $objlist $last_robj\" - else - # All subsequent reloadable object files will link in - # the last one created. - eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" - fi - last_robj=$output_objdir/$output_la-${k}.$objext - k=`expr $k + 1` - output=$output_objdir/$output_la-${k}.$objext - objlist=$obj - len=1 - fi - done - # Handle the remaining objects by creating one last - # reloadable object file. All subsequent reloadable object - # files will link in the last one created. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" - - if ${skipped_export-false}; then - $show "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $run $rm $export_symbols - libobjs=$output - # Append the command to create the export file. - eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" - fi - - # Set up a command to remove the reloadable object files - # after they are used. - i=0 - while test "$i" -lt "$k" - do - i=`expr $i + 1` - delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" - done - - $echo "creating a temporary reloadable object file: $output" - - # Loop through the commands generated above and execute them. - save_ifs="$IFS"; IFS='~' - for cmd in $concat_cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - libobjs=$output - # Restore the value of output. - output=$save_output - - if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - fi - # Expand the library linking commands again to reset the - # value of $libobjs for piecewise linking. - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - cmds=$module_expsym_cmds - else - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - cmds=$archive_expsym_cmds - else - cmds=$archive_cmds - fi - fi - - # Append the command to remove the reloadable object files - # to the just-reset $cmds. - eval cmds=\"\$cmds~\$rm $delfiles\" - fi - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$mode" = relink; then - $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - - # Restore the uninstalled library and exit - if test "$mode" = relink; then - $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? - - if test -n "$convenience"; then - if test -z "$whole_archive_flag_spec"; then - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - fi - fi - - exit $EXIT_SUCCESS - fi - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" - $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then - # On all known operating systems, these are identical. - dlname="$soname" - fi - fi - ;; - - obj) - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 - fi - - if test -n "$rpath"; then - $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 - fi - - if test -n "$xrpath"; then - $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 - fi - - case $output in - *.lo) - if test -n "$objs$old_deplibs"; then - $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 - exit $EXIT_FAILURE - fi - libobj="$output" - obj=`$echo "X$output" | $Xsed -e "$lo2o"` - ;; - *) - libobj= - obj="$output" - ;; - esac - - # Delete the old objects. - $run $rm $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec and hope we can get by with - # turning comma into space.. - wl= - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` - else - gentop="$output_objdir/${obj}x" - generated="$generated $gentop" - - func_extract_archives $gentop $convenience - reload_conv_objs="$reload_objs $func_extract_archives_result" - fi - fi - - # Create the old-style object. - reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test - - output="$obj" - cmds=$reload_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - exit $EXIT_SUCCESS - fi - - if test "$build_libtool_libs" != yes; then - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - # $show "echo timestamp > $libobj" - # $run eval "echo timestamp > $libobj" || exit $? - exit $EXIT_SUCCESS - fi - - if test -n "$pic_flag" || test "$pic_mode" != default; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output="$libobj" - cmds=$reload_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - exit $EXIT_SUCCESS - ;; - - prog) - case $host in - *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; - esac - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 - fi - - if test "$preload" = yes; then - if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && - test "$dlopen_self_static" = unknown; then - $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." - fi - fi - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` - finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` - ;; - esac - - case $host in - *darwin*) - # Don't allow lazy linking, it breaks C++ global constructors - if test "$tagname" = CXX ; then - compile_command="$compile_command ${wl}-bind_at_load" - finalize_command="$finalize_command ${wl}-bind_at_load" - fi - ;; - esac - - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $compile_deplibs " in - *" -L$path/$objdir "*) - new_libs="$new_libs -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $compile_deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$new_libs $deplib" ;; - esac - ;; - *) new_libs="$new_libs $deplib" ;; - esac - done - compile_deplibs="$new_libs" - - - compile_command="$compile_command $compile_deplibs" - finalize_command="$finalize_command $finalize_deplibs" - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) perm_rpath="$perm_rpath $libdir" ;; - esac - fi - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) - testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$libdir:"*) ;; - *) dllsearchpath="$dllsearchpath:$libdir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - *) dllsearchpath="$dllsearchpath:$testbindir";; - esac - ;; - esac - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath="$rpath" - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath="$rpath" - - if test -n "$libobjs" && test "$build_old_libs" = yes; then - # Transform all the library objects into standard objects. - compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - fi - - dlsyms= - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - dlsyms="${outputname}S.c" - else - $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 - fi - fi - - if test -n "$dlsyms"; then - case $dlsyms in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${outputname}.nm" - - $show "$rm $nlist ${nlist}S ${nlist}T" - $run $rm "$nlist" "${nlist}S" "${nlist}T" - - # Parse the name list into a source file. - $show "creating $output_objdir/$dlsyms" - - test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ -/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ -/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -/* Prevent the only kind of declaration conflicts we can make. */ -#define lt_preloaded_symbols some_other_symbol - -/* External symbol declarations for the compiler. */\ -" - - if test "$dlself" = yes; then - $show "generating symbol list for \`$output'" - - test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - for arg in $progfiles; do - $show "extracting global C symbols from \`$arg'" - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - if test -n "$export_symbols_regex"; then - $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols="$output_objdir/$outputname.exp" - $run $rm $export_symbols - $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - case $host in - *cygwin* | *mingw* ) - $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' - ;; - esac - else - $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' - $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' - $run eval 'mv "$nlist"T "$nlist"' - case $host in - *cygwin* | *mingw* ) - $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' - ;; - esac - fi - fi - - for arg in $dlprefiles; do - $show "extracting global C symbols from \`$arg'" - name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` - $run eval '$echo ": $name " >> "$nlist"' - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -z "$run"; then - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $mv "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if grep -v "^: " < "$nlist" | - if sort -k 3 /dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | - uniq > "$nlist"S; then - : - else - grep -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' - else - $echo '/* NONE */' >> "$output_objdir/$dlsyms" - fi - - $echo >> "$output_objdir/$dlsyms" "\ - -#undef lt_preloaded_symbols - -#if defined (__STDC__) && __STDC__ -# define lt_ptr void * -#else -# define lt_ptr char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -" - - case $host in - *cygwin* | *mingw* ) - $echo >> "$output_objdir/$dlsyms" "\ -/* DATA imports from DLLs on WIN32 can't be const, because - runtime relocations are performed -- see ld's documentation - on pseudo-relocs */ -struct { -" - ;; - * ) - $echo >> "$output_objdir/$dlsyms" "\ -const struct { -" - ;; - esac - - - $echo >> "$output_objdir/$dlsyms" "\ - const char *name; - lt_ptr address; -} -lt_preloaded_symbols[] = -{\ -" - - eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" - - $echo >> "$output_objdir/$dlsyms" "\ - {0, (lt_ptr) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - fi - - pic_flag_for_symtable= - case $host in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; - esac;; - *-*-hpux*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag";; - esac - esac - - # Now compile the dynamic symbol file. - $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" - $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? - - # Clean up the generated files. - $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" - $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" - - # Transform the symbol file into the correct name. - case $host in - *cygwin* | *mingw* ) - if test -f "$output_objdir/${outputname}.def" ; then - compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP` - finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP` - else - compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` - finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` - fi - ;; - * ) - compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` - finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP` - ;; - esac - ;; - *) - $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 - exit $EXIT_FAILURE - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP` - finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP` - fi - - if test "$need_relink" = no || test "$build_libtool_libs" != yes; then - # Replace the output file specification. - compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$output"'%g' | $NL2SP` - link_command="$compile_command$compile_rpath" - - # We have no uninstalled library dependencies, so finalize right now. - $show "$link_command" - $run eval "$link_command" - exit_status=$? - - # Delete the generated files. - if test -n "$dlsyms"; then - $show "$rm $output_objdir/${outputname}S.${objext}" - $run $rm "$output_objdir/${outputname}S.${objext}" - fi - - exit $exit_status - fi - - if test -n "$shlibpath_var"; then - # We should set the shlibpath_var - rpath= - for dir in $temp_rpath; do - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) - # Absolute path. - rpath="$rpath$dir:" - ;; - *) - # Relative path: add a thisdir entry. - rpath="$rpath\$thisdir/$dir:" - ;; - esac - done - temp_rpath="$rpath" - fi - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - rpath="$rpath$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - rpath="$rpath$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test "$no_install" = yes; then - # We don't need to create a wrapper script. - link_command="$compile_var$compile_command$compile_rpath" - # Replace the output file specification. - link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` - # Delete the old output file. - $run $rm $output - # Link the executable and exit - $show "$link_command" - $run eval "$link_command" || exit $? - exit $EXIT_SUCCESS - fi - - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - - $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 - $echo "$modename: \`$output' will be relinked during installation" 1>&2 - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $SP2NL | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g' | $NL2SP` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi - - # Replace the output file specification. - link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname - - $show "$link_command" - $run eval "$link_command" || exit $? - - # Now create the wrapper script. - $show "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` - relink_command="$var=\"$var_value\"; export $var; $relink_command" - fi - done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP` - fi - - # Quote $echo for shipping. - if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then - case $progpath in - [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; - *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; - esac - qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` - else - qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` - fi - - # Only actually do things if our run command is non-null. - if test -z "$run"; then - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; - esac - # test for cygwin because mv fails w/o .exe extensions - case $host in - *cygwin*) - exeext=.exe - outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; - *) exeext= ;; - esac - case $host in - *cygwin* | *mingw* ) - output_name=`basename $output` - output_path=`dirname $output` - cwrappersource="$output_path/$objdir/lt-$output_name.c" - cwrapper="$output_path/$output_name.exe" - $rm $cwrappersource $cwrapper - trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 - - cat > $cwrappersource <> $cwrappersource<<"EOF" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(PATH_MAX) -# define LT_PATHMAX PATH_MAX -#elif defined(MAXPATHLEN) -# define LT_PATHMAX MAXPATHLEN -#else -# define LT_PATHMAX 1024 -#endif - -#ifndef DIR_SEPARATOR -# define DIR_SEPARATOR '/' -# define PATH_SEPARATOR ':' -#endif - -#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ - defined (__OS2__) -# define HAVE_DOS_BASED_FILE_SYSTEM -# ifndef DIR_SEPARATOR_2 -# define DIR_SEPARATOR_2 '\\' -# endif -# ifndef PATH_SEPARATOR_2 -# define PATH_SEPARATOR_2 ';' -# endif -#endif - -#ifndef DIR_SEPARATOR_2 -# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) -#else /* DIR_SEPARATOR_2 */ -# define IS_DIR_SEPARATOR(ch) \ - (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) -#endif /* DIR_SEPARATOR_2 */ - -#ifndef PATH_SEPARATOR_2 -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) -#else /* PATH_SEPARATOR_2 */ -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) -#endif /* PATH_SEPARATOR_2 */ - -#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) -#define XFREE(stale) do { \ - if (stale) { free ((void *) stale); stale = 0; } \ -} while (0) - -/* -DDEBUG is fairly common in CFLAGS. */ -#undef DEBUG -#if defined DEBUGWRAPPER -# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) -#else -# define DEBUG(format, ...) -#endif - -const char *program_name = NULL; - -void * xmalloc (size_t num); -char * xstrdup (const char *string); -const char * base_name (const char *name); -char * find_executable(const char *wrapper); -int check_executable(const char *path); -char * strendzap(char *str, const char *pat); -void lt_fatal (const char *message, ...); - -int -main (int argc, char *argv[]) -{ - char **newargz; - int i; - - program_name = (char *) xstrdup (base_name (argv[0])); - DEBUG("(main) argv[0] : %s\n",argv[0]); - DEBUG("(main) program_name : %s\n",program_name); - newargz = XMALLOC(char *, argc+2); -EOF - - cat >> $cwrappersource <> $cwrappersource <<"EOF" - newargz[1] = find_executable(argv[0]); - if (newargz[1] == NULL) - lt_fatal("Couldn't find %s", argv[0]); - DEBUG("(main) found exe at : %s\n",newargz[1]); - /* we know the script has the same name, without the .exe */ - /* so make sure newargz[1] doesn't end in .exe */ - strendzap(newargz[1],".exe"); - for (i = 1; i < argc; i++) - newargz[i+1] = xstrdup(argv[i]); - newargz[argc+1] = NULL; - - for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" - return 127; -} - -void * -xmalloc (size_t num) -{ - void * p = (void *) malloc (num); - if (!p) - lt_fatal ("Memory exhausted"); - - return p; -} - -char * -xstrdup (const char *string) -{ - return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL -; -} - -const char * -base_name (const char *name) -{ - const char *base; - -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - /* Skip over the disk name in MSDOS pathnames. */ - if (isalpha ((unsigned char)name[0]) && name[1] == ':') - name += 2; -#endif - - for (base = name; *name; name++) - if (IS_DIR_SEPARATOR (*name)) - base = name + 1; - return base; -} - -int -check_executable(const char * path) -{ - struct stat st; - - DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); - if ((!path) || (!*path)) - return 0; - - if ((stat (path, &st) >= 0) && - ( - /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ -#if defined (S_IXOTH) - ((st.st_mode & S_IXOTH) == S_IXOTH) || -#endif -#if defined (S_IXGRP) - ((st.st_mode & S_IXGRP) == S_IXGRP) || -#endif - ((st.st_mode & S_IXUSR) == S_IXUSR)) - ) - return 1; - else - return 0; -} - -/* Searches for the full path of the wrapper. Returns - newly allocated full path name if found, NULL otherwise */ -char * -find_executable (const char* wrapper) -{ - int has_slash = 0; - const char* p; - const char* p_next; - /* static buffer for getcwd */ - char tmp[LT_PATHMAX + 1]; - int tmp_len; - char* concat_name; - - DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); - - if ((wrapper == NULL) || (*wrapper == '\0')) - return NULL; - - /* Absolute path? */ -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') - { - concat_name = xstrdup (wrapper); - if (check_executable(concat_name)) - return concat_name; - XFREE(concat_name); - } - else - { -#endif - if (IS_DIR_SEPARATOR (wrapper[0])) - { - concat_name = xstrdup (wrapper); - if (check_executable(concat_name)) - return concat_name; - XFREE(concat_name); - } -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - } -#endif - - for (p = wrapper; *p; p++) - if (*p == '/') - { - has_slash = 1; - break; - } - if (!has_slash) - { - /* no slashes; search PATH */ - const char* path = getenv ("PATH"); - if (path != NULL) - { - for (p = path; *p; p = p_next) - { - const char* q; - size_t p_len; - for (q = p; *q; q++) - if (IS_PATH_SEPARATOR(*q)) - break; - p_len = q - p; - p_next = (*q == '\0' ? q : q + 1); - if (p_len == 0) - { - /* empty path: current directory */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal ("getcwd failed"); - tmp_len = strlen(tmp); - concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - } - else - { - concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); - memcpy (concat_name, p, p_len); - concat_name[p_len] = '/'; - strcpy (concat_name + p_len + 1, wrapper); - } - if (check_executable(concat_name)) - return concat_name; - XFREE(concat_name); - } - } - /* not found in PATH; assume curdir */ - } - /* Relative path | not found in path: prepend cwd */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal ("getcwd failed"); - tmp_len = strlen(tmp); - concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - - if (check_executable(concat_name)) - return concat_name; - XFREE(concat_name); - return NULL; -} - -char * -strendzap(char *str, const char *pat) -{ - size_t len, patlen; - - assert(str != NULL); - assert(pat != NULL); - - len = strlen(str); - patlen = strlen(pat); - - if (patlen <= len) - { - str += len - patlen; - if (strcmp(str, pat) == 0) - *str = '\0'; - } - return str; -} - -static void -lt_error_core (int exit_status, const char * mode, - const char * message, va_list ap) -{ - fprintf (stderr, "%s: %s: ", program_name, mode); - vfprintf (stderr, message, ap); - fprintf (stderr, ".\n"); - - if (exit_status >= 0) - exit (exit_status); -} - -void -lt_fatal (const char *message, ...) -{ - va_list ap; - va_start (ap, message); - lt_error_core (EXIT_FAILURE, "FATAL", message, ap); - va_end (ap); -} -EOF - # we should really use a build-platform specific compiler - # here, but OTOH, the wrappers (shell script and this C one) - # are only useful if you want to execute the "real" binary. - # Since the "real" binary is built for $host, then this - # wrapper might as well be built for $host, too. - $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource - ;; - esac - $rm $output - trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 - - $echo > $output "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='${SED} -e 1s/^X//' -sed_quote_subst='$sed_quote_subst' - -# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE). -if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variable: - notinst_deplibs='$notinst_deplibs' -else - # When we are sourced in execute mode, \$file and \$echo are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - echo=\"$qecho\" - file=\"\$0\" - # Make sure echo works. - if test \"X\$1\" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift - elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then - # Yippee, \$echo works! - : - else - # Restart under the correct shell, and then maybe \$echo will work. - exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} - fi - fi\ -" - $echo >> $output "\ - - # Find the directory that this script lives in. - thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` - done - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test "$fast_install" = yes; then - $echo >> $output "\ - program=lt-'$outputname'$exeext - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || \\ - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $mkdir \"\$progdir\" - else - $rm \"\$progdir/\$file\" - fi" - - $echo >> $output "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if relink_command_output=\`eval \$relink_command 2>&1\`; then : - else - $echo \"\$relink_command_output\" >&2 - $rm \"\$progdir/\$file\" - exit $EXIT_FAILURE - fi - fi - - $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $rm \"\$progdir/\$program\"; - $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $rm \"\$progdir/\$file\" - fi" - else - $echo >> $output "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - $echo >> $output "\ - - if test -f \"\$progdir/\$program\"; then" - - # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $echo >> $output "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` - - export $shlibpath_var -" - fi - - # fixup the dll searchpath if we need to. - if test -n "$dllsearchpath"; then - $echo >> $output "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - $echo >> $output "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2*) - $echo >> $output "\ - exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} -" - ;; - - *) - $echo >> $output "\ - exec \"\$progdir/\$program\" \${1+\"\$@\"} -" - ;; - esac - $echo >> $output "\ - \$echo \"\$0: cannot exec \$program \$*\" - exit $EXIT_FAILURE - fi - else - # The program doesn't exist. - \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 - \$echo \"This script is just a wrapper for \$program.\" 1>&2 - $echo \"See the $PACKAGE documentation for more information.\" 1>&2 - exit $EXIT_FAILURE - fi -fi\ -" - chmod +x $output - fi - exit $EXIT_SUCCESS - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" - build_libtool_libs=no - else - oldobjs="$old_deplibs $non_pic_objects" - fi - addlibs="$old_convenience" - fi - - if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" - - func_extract_archives $gentop $addlibs - oldobjs="$oldobjs $func_extract_archives_result" - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then - cmds=$old_archive_from_new_cmds - else - # POSIX demands no paths to be encoded in archives. We have - # to avoid creating archives with duplicate basenames if we - # might have to extract them afterwards, e.g., when creating a - # static archive out of a convenience library, or when linking - # the entirety of a libtool archive into another (currently - # not supported by libtool). - if (for obj in $oldobjs - do - $echo "X$obj" | $Xsed -e 's%^.*/%%' - done | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "copying selected object files to avoid basename conflicts..." - - if test -z "$gentop"; then - gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" - - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - exit_status=$? - if test "$exit_status" -ne 0 && test ! -d "$gentop"; then - exit $exit_status - fi - fi - - save_oldobjs=$oldobjs - oldobjs= - counter=1 - for obj in $save_oldobjs - do - objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` - case " $oldobjs " in - " ") oldobjs=$obj ;; - *[\ /]"$objbase "*) - while :; do - # Make sure we don't pick an alternate name that also - # overlaps. - newobj=lt$counter-$objbase - counter=`expr $counter + 1` - case " $oldobjs " in - *[\ /]"$newobj "*) ;; - *) if test ! -f "$gentop/$newobj"; then break; fi ;; - esac - done - $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" - $run ln "$obj" "$gentop/$newobj" || - $run cp "$obj" "$gentop/$newobj" - oldobjs="$oldobjs $gentop/$newobj" - ;; - *) oldobjs="$oldobjs $obj" ;; - esac - done - fi - - eval cmds=\"$old_archive_cmds\" - - if len=`expr "X$cmds" : ".*"` && - test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then - cmds=$old_archive_cmds - else - # the command line is too long to link in one step, link in parts - $echo "using piecewise archive linking..." - save_RANLIB=$RANLIB - RANLIB=: - objlist= - concat_cmds= - save_oldobjs=$oldobjs - - # Is there a better way of finding the last object in the list? - for obj in $save_oldobjs - do - last_oldobj=$obj - done - for obj in $save_oldobjs - do - oldobjs="$objlist $obj" - objlist="$objlist $obj" - eval test_cmds=\"$old_archive_cmds\" - if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && - test "$len" -le "$max_cmd_len"; then - : - else - # the above command should be used before it gets too long - oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then - RANLIB=$save_RANLIB - fi - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" - objlist= - fi - done - RANLIB=$save_RANLIB - oldobjs=$objlist - if test "X$oldobjs" = "X" ; then - eval cmds=\"\$concat_cmds\" - else - eval cmds=\"\$concat_cmds~\$old_archive_cmds\" - fi - fi - fi - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - eval cmd=\"$cmd\" - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - done - - if test -n "$generated"; then - $show "${rm}r$generated" - $run ${rm}r$generated - fi - - # Now create the libtool archive. - case $output in - *.la) - old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" - $show "creating $output" - - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` - relink_command="$var=\"$var_value\"; export $var; $relink_command" - fi - done - # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP` - if test "$hardcode_automatic" = yes ; then - relink_command= - fi - - - # Only create the output if not a dry run. - if test -z "$run"; then - for installed in no yes; do - if test "$installed" = yes; then - if test -z "$install_libdir"; then - break - fi - output="$output_objdir/$outputname"i - # Replace all uninstalled libtool libraries with the installed ones - newdependency_libs= - for deplib in $dependency_libs; do - case $deplib in - *.la) - name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - if test -z "$libdir"; then - $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - newdependency_libs="$newdependency_libs $libdir/$name" - ;; - *) newdependency_libs="$newdependency_libs $deplib" ;; - esac - done - dependency_libs="$newdependency_libs" - newdlfiles= - for lib in $dlfiles; do - name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - if test -z "$libdir"; then - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - newdlfiles="$newdlfiles $libdir/$name" - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - if test -z "$libdir"; then - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - newdlprefiles="$newdlprefiles $libdir/$name" - done - dlprefiles="$newdlprefiles" - else - newdlfiles= - for lib in $dlfiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - newdlfiles="$newdlfiles $abs" - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - newdlprefiles="$newdlprefiles $abs" - done - dlprefiles="$newdlprefiles" - fi - $rm $output - # place dlname in correct position for cygwin - tdlname=$dlname - case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; - esac - $echo > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$tdlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Should we warn about portability when linking against -modules? -shouldnotlink=$module - -# Files to dlopen/dlpreopen -dlopen='$dlfiles' -dlpreopen='$dlprefiles' - -# Directory that this library needs to be installed in: -libdir='$install_libdir'" - if test "$installed" = no && test "$need_relink" = yes; then - $echo >> $output "\ -relink_command=\"$relink_command\"" - fi - done - fi - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" - $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? - ;; - esac - exit $EXIT_SUCCESS - ;; - - # libtool install mode - install) - modename="$modename: install" - - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || - # Allow the use of GNU shtool's install command. - $echo "X$nonopt" | grep shtool > /dev/null; then - # Aesthetically quote it. - arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - install_prog="$arg " - arg="$1" - shift - else - install_prog= - arg=$nonopt - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - install_prog="$install_prog$arg" - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=no - stripme= - for arg - do - if test -n "$dest"; then - files="$files $dest" - dest=$arg - continue - fi - - case $arg in - -d) isdir=yes ;; - -f) - case " $install_prog " in - *[\\\ /]cp\ *) ;; - *) prev=$arg ;; - esac - ;; - -g | -m | -o) prev=$arg ;; - -s) - stripme=" -s" - continue - ;; - -*) - ;; - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - prev= - else - dest=$arg - continue - fi - ;; - esac - - # Aesthetically quote the argument. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - install_prog="$install_prog $arg" - done - - if test -z "$install_prog"; then - $echo "$modename: you must specify an install program" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - if test -n "$prev"; then - $echo "$modename: the \`$prev' option requires an argument" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - if test -z "$files"; then - if test -z "$dest"; then - $echo "$modename: no file or destination specified" 1>&2 - else - $echo "$modename: you must specify a destination" 1>&2 - fi - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Strip any trailing slash from the destination. - dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" - destname= - else - destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` - test "X$destdir" = "X$dest" && destdir=. - destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` - - # Not a directory, so check to see that there is only one file specified. - set dummy $files - if test "$#" -gt 2; then - $echo "$modename: \`$dest' is not a directory" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - fi - case $destdir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case $file in - *.lo) ;; - *) - $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case $file in - *.$libext) - # Do the static libraries later. - staticlibs="$staticlibs $file" - ;; - - *.la) - # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - library_names= - old_library= - relink_command= - # If there is no directory component, then add one. - case $file in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) current_libdirs="$current_libdirs $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) future_libdirs="$future_libdirs $libdir" ;; - esac - fi - - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ - test "X$dir" = "X$file/" && dir= - dir="$dir$objdir" - - if test -n "$relink_command"; then - # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` - - # Don't allow the user to place us outside of our expected - # location b/c this prevents finding dependent libraries that - # are installed to the same prefix. - # At present, this check doesn't affect windows .dll's that - # are installed into $libdir/../bin (currently, that works fine) - # but it's something to keep an eye on. - if test "$inst_prefix_dir" = "$destdir"; then - $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 - exit $EXIT_FAILURE - fi - - if test -n "$inst_prefix_dir"; then - # Stick the inst_prefix_dir data into the link command. - relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%" | $NL2SP` - else - relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP` - fi - - $echo "$modename: warning: relinking \`$file'" 1>&2 - $show "$relink_command" - if $run eval "$relink_command"; then : - else - $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 - exit $EXIT_FAILURE - fi - fi - - # See the names of the shared library. - set dummy $library_names - if test -n "$2"; then - realname="$2" - shift - shift - - srcname="$realname" - test -n "$relink_command" && srcname="$realname"T - - # Install the shared library and build the symlinks. - $show "$install_prog $dir/$srcname $destdir/$realname" - $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? - if test -n "$stripme" && test -n "$striplib"; then - $show "$striplib $destdir/$realname" - $run eval "$striplib $destdir/$realname" || exit $? - fi - - if test "$#" -gt 0; then - # Delete the old symlinks, and create new ones. - # Try `ln -sf' first, because the `ln' binary might depend on - # the symlink we replace! Solaris /bin/ln does not understand -f, - # so we also need to try rm && ln -s. - for linkname - do - if test "$linkname" != "$realname"; then - $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" - $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" - fi - done - fi - - # Do each command in the postinstall commands. - lib="$destdir/$realname" - cmds=$postinstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$mode" = relink; then - $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - fi - - # Install the pseudo-library for information purposes. - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - instname="$dir/$name"i - $show "$install_prog $instname $destdir/$name" - $run eval "$install_prog $instname $destdir/$name" || exit $? - - # Maybe install the static library, too. - test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - destfile="$destdir/$destfile" - fi - - # Deduce the name of the destination old-style object file. - case $destfile in - *.lo) - staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` - ;; - *.$objext) - staticdest="$destfile" - destfile= - ;; - *) - $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - # Install the libtool object if requested. - if test -n "$destfile"; then - $show "$install_prog $file $destfile" - $run eval "$install_prog $file $destfile" || exit $? - fi - - # Install the old object if enabled. - if test "$build_old_libs" = yes; then - # Deduce the name of the old-style object file. - staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` - - $show "$install_prog $staticobj $staticdest" - $run eval "$install_prog \$staticobj \$staticdest" || exit $? - fi - exit $EXIT_SUCCESS - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - destfile="$destdir/$destfile" - fi - - # If the file is missing, and there is a .exe on the end, strip it - # because it is most likely a libtool script we actually want to - # install - stripped_ext="" - case $file in - *.exe) - if test ! -f "$file"; then - file=`$echo $file|${SED} 's,.exe$,,'` - stripped_ext=".exe" - fi - ;; - esac - - # Do a test to see if this is really a libtool program. - case $host in - *cygwin*|*mingw*) - wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` - ;; - *) - wrapper=$file - ;; - esac - if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then - notinst_deplibs= - relink_command= - - # Note that it is not necessary on cygwin/mingw to append a dot to - # foo even if both foo and FILE.exe exist: automatic-append-.exe - # behavior happens only for exec(3), not for open(2)! Also, sourcing - # `FILE.' does not work on cygwin managed mounts. - # - # If there is no directory component, then add one. - case $wrapper in - */* | *\\*) . ${wrapper} ;; - *) . ./${wrapper} ;; - esac - - # Check the variables that should have been set. - if test -z "$notinst_deplibs"; then - $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 - exit $EXIT_FAILURE - fi - - finalize=yes - for lib in $notinst_deplibs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - # If there is no directory component, then add one. - case $lib in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - fi - libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test - if test -n "$libdir" && test ! -f "$libfile"; then - $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 - finalize=no - fi - done - - relink_command= - # Note that it is not necessary on cygwin/mingw to append a dot to - # foo even if both foo and FILE.exe exist: automatic-append-.exe - # behavior happens only for exec(3), not for open(2)! Also, sourcing - # `FILE.' does not work on cygwin managed mounts. - # - # If there is no directory component, then add one. - case $wrapper in - */* | *\\*) . ${wrapper} ;; - *) . ./${wrapper} ;; - esac - - outputname= - if test "$fast_install" = no && test -n "$relink_command"; then - if test "$finalize" = yes && test -z "$run"; then - tmpdir=`func_mktempdir` - file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` - outputname="$tmpdir/$file" - # Replace the output file specification. - relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g' | $NL2SP` - - $show "$relink_command" - if $run eval "$relink_command"; then : - else - $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 - ${rm}r "$tmpdir" - continue - fi - file="$outputname" - else - $echo "$modename: warning: cannot relink \`$file'" 1>&2 - fi - else - # Install the binary that we compiled earlier. - file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - # remove .exe since cygwin /usr/bin/install will append another - # one anyway - case $install_prog,$host in - */usr/bin/install*,*cygwin*) - case $file:$destfile in - *.exe:*.exe) - # this is ok - ;; - *.exe:*) - destfile=$destfile.exe - ;; - *:*.exe) - destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` - ;; - esac - ;; - esac - $show "$install_prog$stripme $file $destfile" - $run eval "$install_prog\$stripme \$file \$destfile" || exit $? - test -n "$outputname" && ${rm}r "$tmpdir" - ;; - esac - done - - for file in $staticlibs; do - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - - # Set up the ranlib parameters. - oldlib="$destdir/$name" - - $show "$install_prog $file $oldlib" - $run eval "$install_prog \$file \$oldlib" || exit $? - - if test -n "$stripme" && test -n "$old_striplib"; then - $show "$old_striplib $oldlib" - $run eval "$old_striplib $oldlib" || exit $? - fi - - # Do each command in the postinstall commands. - cmds=$old_postinstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - done - - if test -n "$future_libdirs"; then - $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 - fi - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - test -n "$run" && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' - else - exit $EXIT_SUCCESS - fi - ;; - - # libtool finish mode - finish) - modename="$modename: finish" - libdirs="$nonopt" - admincmds= - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for dir - do - libdirs="$libdirs $dir" - done - - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - cmds=$finish_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || admincmds="$admincmds - $cmd" - done - IFS="$save_ifs" - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $run eval "$cmds" || admincmds="$admincmds - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - test "$show" = : && exit $EXIT_SUCCESS - - $echo "X----------------------------------------------------------------------" | $Xsed - $echo "Libraries have been installed in:" - for libdir in $libdirs; do - $echo " $libdir" - done - $echo - $echo "If you ever happen to want to link against installed libraries" - $echo "in a given directory, LIBDIR, you must either use libtool, and" - $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" - $echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" - $echo " during execution" - fi - if test -n "$runpath_var"; then - $echo " - add LIBDIR to the \`$runpath_var' environment variable" - $echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - $echo " - use the \`$flag' linker flag" - fi - if test -n "$admincmds"; then - $echo " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" - fi - $echo - $echo "See any operating system documentation about shared libraries for" - $echo "more information, such as the ld(1) and ld.so(8) manual pages." - $echo "X----------------------------------------------------------------------" | $Xsed - exit $EXIT_SUCCESS - ;; - - # libtool execute mode - execute) - modename="$modename: execute" - - # The first argument is the command name. - cmd="$nonopt" - if test -z "$cmd"; then - $echo "$modename: you must specify a COMMAND" 1>&2 - $echo "$help" - exit $EXIT_FAILURE - fi - - # Handle -dlopen flags immediately. - for file in $execute_dlfiles; do - if test ! -f "$file"; then - $echo "$modename: \`$file' is not a file" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - dir= - case $file in - *.la) - # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Read the libtool library. - dlname= - library_names= - - # If there is no directory component, then add one. - case $file in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" - continue - fi - - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - - if test -f "$dir/$objdir/$dlname"; then - dir="$dir/$objdir" - else - if test ! -f "$dir/$dlname"; then - $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 - exit $EXIT_FAILURE - fi - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - ;; - - *) - $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic="$magic" - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case $file in - -*) ;; - *) - # Do a test to see if this is really a libtool program. - if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - # If there is no directory component, then add one. - case $file in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Transform arg to wrapped name. - file="$progdir/$program" - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` - args="$args \"$file\"" - done - - if test -z "$run"; then - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved environment variables - for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES - do - eval "if test \"\${save_$lt_var+set}\" = set; then - $lt_var=\$save_$lt_var; export $lt_var - fi" - done - - # Now prepare to actually exec the command. - exec_cmd="\$cmd$args" - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" - $echo "export $shlibpath_var" - fi - $echo "$cmd$args" - exit $EXIT_SUCCESS - fi - ;; - - # libtool clean and uninstall mode - clean | uninstall) - modename="$modename: $mode" - rm="$nonopt" - files= - rmforce= - exit_status=0 - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - for arg - do - case $arg in - -f) rm="$rm $arg"; rmforce=yes ;; - -*) rm="$rm $arg" ;; - *) files="$files $arg" ;; - esac - done - - if test -z "$rm"; then - $echo "$modename: you must specify an RM program" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - rmdirs= - - origobjdir="$objdir" - for file in $files; do - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - if test "X$dir" = "X$file"; then - dir=. - objdir="$origobjdir" - else - objdir="$dir/$origobjdir" - fi - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - test "$mode" = uninstall && objdir="$dir" - - # Remember objdir for removal later, being careful to avoid duplicates - if test "$mode" = clean; then - case " $rmdirs " in - *" $objdir "*) ;; - *) rmdirs="$rmdirs $objdir" ;; - esac - fi - - # Don't error if the file doesn't exist and rm -f was used. - if (test -L "$file") >/dev/null 2>&1 \ - || (test -h "$file") >/dev/null 2>&1 \ - || test -f "$file"; then - : - elif test -d "$file"; then - exit_status=1 - continue - elif test "$rmforce" = yes; then - continue - fi - - rmfiles="$file" - - case $name in - *.la) - # Possibly a libtool archive, so verify it. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - . $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - rmfiles="$rmfiles $objdir/$n" - done - test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" - - case "$mode" in - clean) - case " $library_names " in - # " " in the beginning catches empty $dlname - *" $dlname "*) ;; - *) rmfiles="$rmfiles $objdir/$dlname" ;; - esac - test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" - ;; - uninstall) - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - cmds=$postuninstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" - if test "$?" -ne 0 && test "$rmforce" != yes; then - exit_status=1 - fi - done - IFS="$save_ifs" - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - cmds=$old_postuninstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" - if test "$?" -ne 0 && test "$rmforce" != yes; then - exit_status=1 - fi - done - IFS="$save_ifs" - fi - # FIXME: should reinstall the best remaining shared library. - ;; - esac - fi - ;; - - *.lo) - # Possibly a libtool object, so verify it. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - - # Read the .lo file - . $dir/$name - - # Add PIC object to the list of files to remove. - if test -n "$pic_object" \ - && test "$pic_object" != none; then - rmfiles="$rmfiles $dir/$pic_object" - fi - - # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" \ - && test "$non_pic_object" != none; then - rmfiles="$rmfiles $dir/$non_pic_object" - fi - fi - ;; - - *) - if test "$mode" = clean ; then - noexename=$name - case $file in - *.exe) - file=`$echo $file|${SED} 's,.exe$,,'` - noexename=`$echo $name|${SED} 's,.exe$,,'` - # $file with .exe has already been added to rmfiles, - # add $file without .exe - rmfiles="$rmfiles $file" - ;; - esac - # Do a test to see if this is a libtool program. - if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - relink_command= - . $dir/$noexename - - # note $name still contains .exe if it was in $file originally - # as does the version of $file that was added into $rmfiles - rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" - if test "$fast_install" = yes && test -n "$relink_command"; then - rmfiles="$rmfiles $objdir/lt-$name" - fi - if test "X$noexename" != "X$name" ; then - rmfiles="$rmfiles $objdir/lt-${noexename}.c" - fi - fi - fi - ;; - esac - $show "$rm $rmfiles" - $run $rm $rmfiles || exit_status=1 - done - objdir="$origobjdir" - - # Try to remove the ${objdir}s in the directories where we deleted files - for dir in $rmdirs; do - if test -d "$dir"; then - $show "rmdir $dir" - $run rmdir $dir >/dev/null 2>&1 - fi - done - - exit $exit_status - ;; - - "") - $echo "$modename: you must specify a MODE" 1>&2 - $echo "$generic_help" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - if test -z "$exec_cmd"; then - $echo "$modename: invalid operation mode \`$mode'" 1>&2 - $echo "$generic_help" 1>&2 - exit $EXIT_FAILURE - fi -fi # test -z "$show_help" - -if test -n "$exec_cmd"; then - eval exec $exec_cmd - exit $EXIT_FAILURE -fi - -# We need to display help for each of the modes. -case $mode in -"") $echo \ -"Usage: $modename [OPTION]... [MODE-ARG]... - -Provide generalized library-building support services. - - --config show all configuration variables - --debug enable verbose shell tracing --n, --dry-run display commands without modifying any files - --features display basic configuration information and exit - --finish same as \`--mode=finish' - --help display this help message and exit - --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] - --quiet same as \`--silent' - --silent don't print informational messages - --tag=TAG use configuration variables from tag TAG - --version print version information - -MODE must be one of the following: - - clean remove files from the build directory - compile compile a source file into a libtool object - execute automatically set library path, then run a program - finish complete the installation of libtool libraries - install install libraries or executables - link create a library or an executable - uninstall remove libraries from an installed directory - -MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for -a more detailed description of MODE. - -Report bugs to ." - exit $EXIT_SUCCESS - ;; - -clean) - $echo \ -"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... - -Remove files from the build directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, object or program, all the files associated -with it are deleted. Otherwise, only FILE itself is deleted using RM." - ;; - -compile) - $echo \ -"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -prefer-pic try to building PIC objects only - -prefer-non-pic try to building non-PIC objects only - -static always build a \`.o' file suitable for static linking - -COMPILE-COMMAND is a command to be used in creating a \`standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." - ;; - -execute) - $echo \ -"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to \`-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - -finish) - $echo \ -"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." - ;; - -install) - $echo \ -"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - -link) - $echo \ -"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-fast-install disable the fast-install mode - -no-install link a not-installable executable - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE Use a list of object files found in FILE to specify objects - -precious-files-regex REGEX - don't remove output files matching REGEX - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -static do not do any dynamic linking of uninstalled libtool libraries - -static-libtool-libs - do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -All other options (arguments beginning with \`-') are ignored. - -Every other argument is treated as a filename. Files ending in \`.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. - -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file -is created, otherwise an executable program is created." - ;; - -uninstall) - $echo \ -"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - -*) - $echo "$modename: invalid operation mode \`$mode'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - ;; -esac - -$echo -$echo "Try \`$modename --help' for more information about other modes." - -exit $? - -# The TAGs below are defined such that we never get into a situation -# in which we disable both kinds of libraries. Given conflicting -# choices, we go for a static library, that is the most portable, -# since we can't tell whether shared libraries were disabled because -# the user asked for that or because the platform doesn't support -# them. This is particularly important on AIX, because we don't -# support having both static and shared libraries enabled at the same -# time on that platform, so we default to a shared-only configuration. -# If a disable-shared tag is given, we'll fallback to a static-only -# configuration. But we'll never go from static-only to shared-only. - -# ### BEGIN LIBTOOL TAG CONFIG: disable-shared -disable_libs=shared -# ### END LIBTOOL TAG CONFIG: disable-shared - -# ### BEGIN LIBTOOL TAG CONFIG: disable-static -disable_libs=static -# ### END LIBTOOL TAG CONFIG: disable-static - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: diff --git a/libltdl/missing b/libltdl/missing deleted file mode 100755 index 894e786e1..000000000 --- a/libltdl/missing +++ /dev/null @@ -1,360 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. - -scriptversion=2005-06-08.21 - -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 -# Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -run=: - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -msg="missing on your system" - -case "$1" in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - # Exit code 63 means version mismatch. This often happens - # when the user try to use an ancient version of a tool on - # a file that requires a minimum version. In this case we - # we should proceed has if the program had been absent, or - # if --run hadn't been passed. - if test $? = 63; then - run=: - msg="probably too old" - fi - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch] - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - -esac - -# Now exit if we have it, but it failed. Also exit now if we -# don't have it and --version was passed (most likely to detect -# the program). -case "$1" in - lex|yacc) - # Not GNU programs, they don't have --version. - ;; - - tar) - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - exit 1 - fi - ;; - - *) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - # Could not run --version or --help. This is probably someone - # running `$TOOL --version' or `$TOOL --help' to check whether - # $TOOL exists and not knowing $TOOL uses missing. - exit 1 - fi - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case "$1" in - aclocal*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case "$f" in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te) - echo 1>&2 "\ -WARNING: \`$1' is needed, but is $msg. - You might have modified some files without having the - proper tools for further handling them. - You can get \`$1' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` - test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison|yacc) - echo 1>&2 "\ -WARNING: \`$1' $msg. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if [ ! -f y.tab.h ]; then - echo >y.tab.h - fi - if [ ! -f y.tab.c ]; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex|flex) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if [ ! -f lex.yy.c ]; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` - fi - if [ -f "$file" ]; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit 1 - fi - ;; - - makeinfo) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - # The file to touch is that specified with -o ... - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - # ... or it is the one specified with @setfilename ... - infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` - # ... or it is derived from the source name (dir/f.texi becomes f.info) - test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info - fi - # If the file does not exist, the user really needs makeinfo; - # let's fail without touching anything. - test -f $file || exit 1 - touch $file - ;; - - tar) - shift - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case "$firstarg" in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case "$firstarg" in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and is $msg. - You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequisites for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/libltdl/mkinstalldirs b/libltdl/mkinstalldirs deleted file mode 100755 index ef7e16fda..000000000 --- a/libltdl/mkinstalldirs +++ /dev/null @@ -1,161 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy - -scriptversion=2006-05-11.19 - -# Original author: Noah Friedman -# Created: 1993-05-16 -# Public domain. -# -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -nl=' -' -IFS=" "" $nl" -errstatus=0 -dirmode= - -usage="\ -Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... - -Create each directory DIR (with mode MODE, if specified), including all -leading file name components. - -Report bugs to ." - -# process command line arguments -while test $# -gt 0 ; do - case $1 in - -h | --help | --h*) # -h for help - echo "$usage" - exit $? - ;; - -m) # -m PERM arg - shift - test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } - dirmode=$1 - shift - ;; - --version) - echo "$0 $scriptversion" - exit $? - ;; - --) # stop option processing - shift - break - ;; - -*) # unknown option - echo "$usage" 1>&2 - exit 1 - ;; - *) # first non-opt arg - break - ;; - esac -done - -for file -do - if test -d "$file"; then - shift - else - break - fi -done - -case $# in - 0) exit 0 ;; -esac - -# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and -# mkdir -p a/c at the same time, both will detect that a is missing, -# one will create a, then the other will try to create a and die with -# a "File exists" error. This is a problem when calling mkinstalldirs -# from a parallel make. We use --version in the probe to restrict -# ourselves to GNU mkdir, which is thread-safe. -case $dirmode in - '') - if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then - echo "mkdir -p -- $*" - exec mkdir -p -- "$@" - else - # On NextStep and OpenStep, the `mkdir' command does not - # recognize any option. It will interpret all options as - # directories to create, and then abort because `.' already - # exists. - test -d ./-p && rmdir ./-p - test -d ./--version && rmdir ./--version - fi - ;; - *) - if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && - test ! -d ./--version; then - echo "mkdir -m $dirmode -p -- $*" - exec mkdir -m "$dirmode" -p -- "$@" - else - # Clean up after NextStep and OpenStep mkdir. - for d in ./-m ./-p ./--version "./$dirmode"; - do - test -d $d && rmdir $d - done - fi - ;; -esac - -for file -do - case $file in - /*) pathcomp=/ ;; - *) pathcomp= ;; - esac - oIFS=$IFS - IFS=/ - set fnord $file - shift - IFS=$oIFS - - for d - do - test "x$d" = x && continue - - pathcomp=$pathcomp$d - case $pathcomp in - -*) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - else - if test ! -z "$dirmode"; then - echo "chmod $dirmode $pathcomp" - lasterr= - chmod "$dirmode" "$pathcomp" || lasterr=$? - - if test ! -z "$lasterr"; then - errstatus=$lasterr - fi - fi - fi - fi - - pathcomp=$pathcomp/ - done -done - -exit $errstatus - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/libltdl/stamp-h1 b/libltdl/stamp-h1 deleted file mode 100644 index 4547fe1b5..000000000 --- a/libltdl/stamp-h1 +++ /dev/null @@ -1 +0,0 @@ -timestamp for config.h From bb2e1afd5181ac67a7daf769b9adc506665a8ed4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 00:49:50 +0000 Subject: [PATCH 1396/1514] initialize userdata struct with 0 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1994 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 7b6b1b823..5ad4711d6 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -448,7 +448,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G if (command == PA_COMMAND_ERROR) pa_log("Failed to get latency."); else - pa_log("Protocol error."); + pa_log("Protocol error 1."); goto fail; } @@ -590,7 +590,7 @@ static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED if (command == PA_COMMAND_ERROR) pa_log("Failed to get info."); else - pa_log("Protocol error."); + pa_log("Protocol error 2."); goto fail; } @@ -695,7 +695,7 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN if (command == PA_COMMAND_ERROR) pa_log("Failed to create stream."); else - pa_log("Protocol error."); + pa_log("Protocol error 3."); goto fail; } @@ -773,7 +773,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t if (command == PA_COMMAND_ERROR) pa_log("Failed to authenticate"); else - pa_log("Protocol error."); + pa_log("Protocol error 4."); goto fail; } @@ -1038,7 +1038,7 @@ int pa__init(pa_module*m) { goto fail; } - u = pa_xnew(struct userdata, 1); + u = pa_xnew0(struct userdata, 1); m->userdata = u; u->module = m; u->core = m->core; From 1e0454eb74485d0f323e7cecd55470a38bd5683e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 01:50:22 +0000 Subject: [PATCH 1397/1514] rework the tunnel naming scheme, and make it follow the description changes of the underlying devices; never check for tagstruct eof, to ease later extensions git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1995 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 260 ++++++++++++++++++++++++++++++++---- 1 file changed, 231 insertions(+), 29 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 5ad4711d6..c36e70b76 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -123,8 +123,8 @@ enum { #ifdef TUNNEL_SINK static void command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); -static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); #endif +static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_overflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); @@ -132,8 +132,8 @@ static void command_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { #ifdef TUNNEL_SINK [PA_COMMAND_REQUEST] = command_request, - [PA_COMMAND_SUBSCRIBE_EVENT] = command_subscribe_event, #endif + [PA_COMMAND_SUBSCRIBE_EVENT] = command_subscribe_event, [PA_COMMAND_OVERFLOW] = command_overflow, [PA_COMMAND_UNDERFLOW] = command_underflow, [PA_COMMAND_PLAYBACK_STREAM_KILLED] = command_stream_killed, @@ -177,6 +177,10 @@ struct userdata { pa_smoother *smoother; + char *device_description; + char *server_fqdn; + char *user_name; + uint32_t maxlength; #ifdef TUNNEL_SINK uint32_t tlength; @@ -414,8 +418,7 @@ static void command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED ui pa_assert(u->pdispatch == pd); if (pa_tagstruct_getu32(t, &channel) < 0 || - pa_tagstruct_getu32(t, &bytes) < 0 || - !pa_tagstruct_eof(t)) { + pa_tagstruct_getu32(t, &bytes) < 0) { pa_log("Invalid protocol reply"); goto fail; } @@ -458,8 +461,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, PA_G pa_tagstruct_get_timeval(t, &local) < 0 || pa_tagstruct_get_timeval(t, &remote) < 0 || pa_tagstruct_gets64(t, &write_index) < 0 || - pa_tagstruct_gets64(t, &read_index) < 0 || - !pa_tagstruct_eof(t)) { + pa_tagstruct_gets64(t, &read_index) < 0) { pa_log("Invalid reply. (latency)"); goto fail; } @@ -571,7 +573,118 @@ static pa_usec_t source_get_latency(pa_source *s) { } #endif +static void update_description(struct userdata *u) { + char *d; + + pa_assert(u); + + if (!u->server_fqdn || !u->user_name || !u->device_description) + return; + + d = pa_sprintf_malloc("%s's %s on %s", u->user_name, u->device_description, u->server_fqdn); + #ifdef TUNNEL_SINK + pa_sink_set_description(u->sink, d); +#else + pa_source_set_description(u->source, d); +#endif + + pa_xfree(d); +} + +static void server_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + pa_sample_spec ss; + const char *server_name, *server_version, *user_name, *host_name, *default_sink_name, *default_source_name; + uint32_t cookie; + + pa_assert(pd); + pa_assert(u); + + if (command != PA_COMMAND_REPLY) { + if (command == PA_COMMAND_ERROR) + pa_log("Failed to get info."); + else + pa_log("Protocol error 6."); + goto fail; + } + + if (pa_tagstruct_gets(t, &server_name) < 0 || + pa_tagstruct_gets(t, &server_version) < 0 || + pa_tagstruct_gets(t, &user_name) < 0 || + pa_tagstruct_gets(t, &host_name) < 0 || + pa_tagstruct_get_sample_spec(t, &ss) < 0 || + pa_tagstruct_gets(t, &default_sink_name) < 0 || + pa_tagstruct_gets(t, &default_source_name) < 0 || + pa_tagstruct_getu32(t, &cookie) < 0) { + pa_log("Invalid reply. (get_server_info)"); + goto fail; + } + + pa_xfree(u->server_fqdn); + u->server_fqdn = pa_xstrdup(host_name); + + pa_xfree(u->user_name); + u->user_name = pa_xstrdup(user_name); + + update_description(u); + + return; + +fail: + pa_module_unload_request(u->module); +} + +#ifdef TUNNEL_SINK + +static void sink_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + uint32_t idx, owner_module, monitor_source, flags; + const char *name, *description, *monitor_source_name, *driver; + pa_sample_spec ss; + pa_channel_map cm; + pa_cvolume volume; + int mute; + pa_usec_t latency; + + pa_assert(pd); + pa_assert(u); + + if (command != PA_COMMAND_REPLY) { + if (command == PA_COMMAND_ERROR) + pa_log("Failed to get info."); + else + pa_log("Protocol error 5."); + goto fail; + } + + if (pa_tagstruct_getu32(t, &idx) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_gets(t, &description) < 0 || + pa_tagstruct_get_sample_spec(t, &ss) < 0 || + pa_tagstruct_get_channel_map(t, &cm) < 0 || + pa_tagstruct_getu32(t, &owner_module) < 0 || + pa_tagstruct_get_cvolume(t, &volume) < 0 || + pa_tagstruct_get_boolean(t, &mute) < 0 || + pa_tagstruct_getu32(t, &monitor_source) < 0 || + pa_tagstruct_gets(t, &monitor_source_name) < 0 || + pa_tagstruct_get_usec(t, &latency) < 0 || + pa_tagstruct_gets(t, &driver) < 0 || + pa_tagstruct_getu32(t, &flags) < 0) { + pa_log("Invalid reply. (get_sink_info)"); + goto fail; + } + + pa_xfree(u->device_description); + u->device_description = pa_xstrdup(description); + + update_description(u); + + return; + +fail: + pa_module_unload_request(u->module); +} static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; @@ -606,12 +719,14 @@ static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED pa_tagstruct_get_usec(t, &sink_usec) < 0 || pa_tagstruct_gets(t, &resample_method) < 0 || pa_tagstruct_gets(t, &driver) < 0 || - (u->version >= 11 && pa_tagstruct_get_boolean(t, &mute) < 0) || - !pa_tagstruct_eof(t)) { + (u->version >= 11 && pa_tagstruct_get_boolean(t, &mute) < 0)) { pa_log("Invalid reply. (get_info)"); goto fail; } + if (idx != u->device_index) + return; + pa_assert(u->sink); if ((u->version < 11 || !!mute == !!u->sink->muted) && @@ -630,17 +745,94 @@ fail: pa_module_unload_request(u->module); } +#else + +static void source_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + struct userdata *u = userdata; + uint32_t idx, owner_module, monitor_of_sink, flags; + const char *name, *description, *monitor_of_sink_name, *driver; + pa_sample_spec ss; + pa_channel_map cm; + pa_cvolume volume; + int mute; + pa_usec_t latency; + + pa_assert(pd); + pa_assert(u); + + if (command != PA_COMMAND_REPLY) { + if (command == PA_COMMAND_ERROR) + pa_log("Failed to get info."); + else + pa_log("Protocol error 5."); + goto fail; + } + + if (pa_tagstruct_getu32(t, &idx) < 0 || + pa_tagstruct_gets(t, &name) < 0 || + pa_tagstruct_gets(t, &description) < 0 || + pa_tagstruct_get_sample_spec(t, &ss) < 0 || + pa_tagstruct_get_channel_map(t, &cm) < 0 || + pa_tagstruct_getu32(t, &owner_module) < 0 || + pa_tagstruct_get_cvolume(t, &volume) < 0 || + pa_tagstruct_get_boolean(t, &mute) < 0 || + pa_tagstruct_getu32(t, &monitor_of_sink) < 0 || + pa_tagstruct_gets(t, &monitor_of_sink_name) < 0 || + pa_tagstruct_get_usec(t, &latency) < 0 || + pa_tagstruct_gets(t, &driver) < 0 || + pa_tagstruct_getu32(t, &flags) < 0) { + pa_log("Invalid reply. (get_source_info)"); + goto fail; + } + + pa_xfree(u->device_description); + u->device_description = pa_xstrdup(description); + + update_description(u); + + return; + +fail: + pa_module_unload_request(u->module); +} + +#endif + static void request_info(struct userdata *u) { pa_tagstruct *t; uint32_t tag; pa_assert(u); + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO); + pa_tagstruct_putu32(t, tag = u->ctag++); + pa_pstream_send_tagstruct(u->pstream, t); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, server_info_cb, u, NULL); + +#ifdef TUNNEL_SINK t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INPUT_INFO); pa_tagstruct_putu32(t, tag = u->ctag++); pa_tagstruct_putu32(t, u->device_index); pa_pstream_send_tagstruct(u->pstream, t); pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, sink_input_info_cb, u, NULL); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO); + pa_tagstruct_putu32(t, tag = u->ctag++); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, u->sink_name); + pa_pstream_send_tagstruct(u->pstream, t); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, sink_info_cb, u, NULL); +#else + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO); + pa_tagstruct_putu32(t, tag = u->ctag++); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, u->source_name); + pa_pstream_send_tagstruct(u->pstream, t); + pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, source_info_cb, u, NULL); +#endif } static void command_subscribe_event(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -654,14 +846,20 @@ static void command_subscribe_event(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t com pa_assert(command == PA_COMMAND_SUBSCRIBE_EVENT); if (pa_tagstruct_getu32(t, &e) < 0 || - pa_tagstruct_getu32(t, &idx) < 0 || - !pa_tagstruct_eof(t)) { + pa_tagstruct_getu32(t, &idx) < 0) { pa_log("Invalid protocol reply"); pa_module_unload_request(u->module); return; } - if (e != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE)) + if (e != (PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE) && +#ifdef TUNNEL_SINK + e != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) && + e != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE) +#else + e != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE) +#endif + ) return; request_info(u); @@ -675,10 +873,16 @@ static void start_subscribe(struct userdata *u) { t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE); pa_tagstruct_putu32(t, tag = u->ctag++); - pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SINK_INPUT); + pa_tagstruct_putu32(t, PA_SUBSCRIPTION_MASK_SERVER| +#ifdef TUNNEL_SINK + PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SINK +#else + PA_SUBSCRIPTION_MASK_SOURCE +#endif + ); + pa_pstream_send_tagstruct(u->pstream, t); } -#endif static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { struct userdata *u = userdata; @@ -725,13 +929,8 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN #endif } - if (!pa_tagstruct_eof(t)) - goto parse_error; - -#ifdef TUNNEL_SINK start_subscribe(u); request_info(u); -#endif pa_assert(!u->time_event); pa_gettimeofday(&ntv); @@ -768,8 +967,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_assert(u->pdispatch == pd); if (command != PA_COMMAND_REPLY || - pa_tagstruct_getu32(t, &u->version) < 0 || - !pa_tagstruct_eof(t)) { + pa_tagstruct_getu32(t, &u->version) < 0) { if (command == PA_COMMAND_ERROR) pa_log("Failed to authenticate"); else @@ -785,21 +983,21 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t } #ifdef TUNNEL_SINK - pa_snprintf(name, sizeof(name), "Tunnel from host %s, user %s, sink %s", - pa_get_host_name(hn, sizeof(hn)), + pa_snprintf(name, sizeof(name), "%s@%s", pa_get_user_name(un, sizeof(un)), + pa_get_host_name(hn, sizeof(hn)), u->sink->name); #else - pa_snprintf(name, sizeof(name), "Tunnel from host %s, user %s, source %s", - pa_get_host_name(hn, sizeof(hn)), + pa_snprintf(name, sizeof(name), "%s@%s", pa_get_user_name(un, sizeof(un)), + pa_get_host_name(hn, sizeof(hn)), u->source->name); #endif reply = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME); pa_tagstruct_putu32(reply, tag = u->ctag++); - pa_tagstruct_puts(reply, name); + pa_tagstruct_puts(reply, "PulseAudio"); pa_pstream_send_tagstruct(u->pstream, reply); /* We ignore the server's reply here */ @@ -1004,7 +1202,7 @@ static int load_key(struct userdata *u, const char*fn) { u->auth_cookie_in_property = FALSE; if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { - pa_log_debug("using already loaded auth cookie."); + pa_log_debug("Using already loaded auth cookie."); pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME); u->auth_cookie_in_property = 1; return 0; @@ -1016,7 +1214,7 @@ static int load_key(struct userdata *u, const char*fn) { if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0) return -1; - pa_log_debug("loading cookie from disk."); + pa_log_debug("Loading cookie from disk."); if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) u->auth_cookie_in_property = TRUE; @@ -1108,7 +1306,7 @@ int pa__init(pa_module*m) { pa_sink_set_module(u->sink, m); pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); pa_sink_set_rtpoll(u->sink, u->rtpoll); - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Tunnel to %s%s%s", u->sink_name ? u->sink_name : "", u->sink_name ? " on " : "", u->server_name)); + pa_sink_set_description(u->sink, t = pa_sprintf_malloc("%s%s%s", u->sink_name ? u->sink_name : "", u->sink_name ? " on " : "", u->server_name)); pa_xfree(t); #else @@ -1130,7 +1328,7 @@ int pa__init(pa_module*m) { pa_source_set_module(u->source, m); pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); pa_source_set_rtpoll(u->source, u->rtpoll); - pa_source_set_description(u->source, t = pa_sprintf_malloc("Tunnel to %s%s%s", u->source_name ? u->source_name : "", u->source_name ? " on " : "", u->server_name)); + pa_source_set_description(u->source, t = pa_sprintf_malloc("%s%s%s", u->source_name ? u->source_name : "", u->source_name ? " on " : "", u->server_name)); pa_xfree(t); #endif @@ -1237,5 +1435,9 @@ void pa__done(pa_module*m) { #endif pa_xfree(u->server_name); + pa_xfree(u->device_description); + pa_xfree(u->server_fqdn); + pa_xfree(u->user_name); + pa_xfree(u); } From 201dff7b2e881228b14c4aa67fb51360f548043c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 02:05:53 +0000 Subject: [PATCH 1398/1514] ignore updates not relevant to us git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1996 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index c36e70b76..485b6f3b3 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -675,6 +675,9 @@ static void sink_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint3 goto fail; } + if (strcmp(name, u->sink_name)) + return; + pa_xfree(u->device_description); u->device_description = pa_xstrdup(description); @@ -785,6 +788,9 @@ static void source_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uin goto fail; } + if (strcmp(name, u->source_name)) + return; + pa_xfree(u->device_description); u->device_description = pa_xstrdup(description); From 72817f9d9dcd7548972b7d1090fefa19436ca538 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 02:35:00 +0000 Subject: [PATCH 1399/1514] rename stream names too, when the sink name changes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1997 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-tunnel.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 485b6f3b3..edc03c99c 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -575,13 +575,15 @@ static pa_usec_t source_get_latency(pa_source *s) { static void update_description(struct userdata *u) { char *d; + char un[128], hn[128]; + pa_tagstruct *t; pa_assert(u); if (!u->server_fqdn || !u->user_name || !u->device_description) return; - d = pa_sprintf_malloc("%s's %s on %s", u->user_name, u->device_description, u->server_fqdn); + d = pa_sprintf_malloc("%s on %s@%s", u->device_description, u->user_name, u->server_fqdn); #ifdef TUNNEL_SINK pa_sink_set_description(u->sink, d); @@ -590,6 +592,23 @@ static void update_description(struct userdata *u) { #endif pa_xfree(d); + + d = pa_sprintf_malloc("%s for %s@%s", u->device_description, + pa_get_user_name(un, sizeof(un)), + pa_get_host_name(hn, sizeof(hn))); + + t = pa_tagstruct_new(NULL, 0); +#ifdef TUNNEL_SINK + pa_tagstruct_putu32(t, PA_COMMAND_SET_PLAYBACK_STREAM_NAME); +#else + pa_tagstruct_putu32(t, PA_COMMAND_SET_RECORD_STREAM_NAME); +#endif + pa_tagstruct_putu32(t, u->ctag++); + pa_tagstruct_putu32(t, u->channel); + pa_tagstruct_puts(t, d); + pa_pstream_send_tagstruct(u->pstream, t); + + pa_xfree(d); } static void server_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -989,15 +1008,15 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t } #ifdef TUNNEL_SINK - pa_snprintf(name, sizeof(name), "%s@%s", - pa_get_user_name(un, sizeof(un)), - pa_get_host_name(hn, sizeof(hn)), - u->sink->name); + pa_snprintf(name, sizeof(name), "%s for %s@%s", + u->sink_name, + pa_get_user_name(un, sizeof(un)), + pa_get_host_name(hn, sizeof(hn))); #else - pa_snprintf(name, sizeof(name), "%s@%s", - pa_get_user_name(un, sizeof(un)), - pa_get_host_name(hn, sizeof(hn)), - u->source->name); + pa_snprintf(name, sizeof(name), "%s for %s@%s", + u->source_name, + pa_get_user_name(un, sizeof(un)), + pa_get_host_name(hn, sizeof(hn))); #endif reply = pa_tagstruct_new(NULL, 0); From b84489d8b3f382a847ac9ff2ed56cef2b4762efd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 14:05:18 +0000 Subject: [PATCH 1400/1514] handle tcp4: prefix for server specs correctly. (Closes #136) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1998 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/parseaddr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/parseaddr.c b/src/pulsecore/parseaddr.c index 65ba64c1c..149c9e007 100644 --- a/src/pulsecore/parseaddr.c +++ b/src/pulsecore/parseaddr.c @@ -103,9 +103,12 @@ int pa_parse_address(const char *name, pa_parsed_address *ret_p) { else if (pa_startswith(p, "unix:")) { ret_p->type = PA_PARSED_ADDRESS_UNIX; p += sizeof("unix:")-1; - } else if (pa_startswith(p, "tcp:") || pa_startswith(p, "tcp4:")) { + } else if (pa_startswith(p, "tcp:")) { ret_p->type = PA_PARSED_ADDRESS_TCP4; p += sizeof("tcp:")-1; + } else if (pa_startswith(p, "tcp4:")) { + ret_p->type = PA_PARSED_ADDRESS_TCP4; + p += sizeof("tcp4:")-1; } else if (pa_startswith(p, "tcp6:")) { ret_p->type = PA_PARSED_ADDRESS_TCP6; p += sizeof("tcp6:")-1; From b03b5741ea689b3bb08b7fef9cc905cae3a5ad99 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 14:17:41 +0000 Subject: [PATCH 1401/1514] rename 'length' parameters in the API to 'bytes', to make their unit clear git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1999 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/simple.h | 4 ++-- src/pulse/stream.h | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pulse/simple.h b/src/pulse/simple.h index f76c1d67b..0ddd57e05 100644 --- a/src/pulse/simple.h +++ b/src/pulse/simple.h @@ -130,13 +130,13 @@ pa_simple* pa_simple_new( void pa_simple_free(pa_simple *s); /** Write some data to the server */ -int pa_simple_write(pa_simple *s, const void*data, size_t length, int *error); +int pa_simple_write(pa_simple *s, const void*data, size_t bytes, int *error); /** Wait until all data already written is played by the daemon */ int pa_simple_drain(pa_simple *s, int *error); /** Read some data from the server */ -int pa_simple_read(pa_simple *s, void*data, size_t length, int *error); +int pa_simple_read(pa_simple *s, void*data, size_t bytes, int *error); /** Return the playback latency. \since 0.5 */ pa_usec_t pa_simple_get_latency(pa_simple *s, int *error); diff --git a/src/pulse/stream.h b/src/pulse/stream.h index 65603262f..8c6a90c16 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -271,7 +271,7 @@ typedef struct pa_stream pa_stream; typedef void (*pa_stream_success_cb_t) (pa_stream*s, int success, void *userdata); /** A generic request callback */ -typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t length, void *userdata); +typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t bytes, void *userdata); /** A generic notification callback */ typedef void (*pa_stream_notify_cb_t)(pa_stream *p, void *userdata); @@ -327,7 +327,7 @@ int pa_stream_disconnect(pa_stream *s); int pa_stream_write( pa_stream *p /**< The stream to use */, const void *data /**< The data to write */, - size_t length /**< The length of the data to write */, + size_t bytes /**< The length of the data to write in bytes*/, pa_free_cb_t free_cb /**< A cleanup routine for the data or NULL to request an internal copy */, int64_t offset, /**< Offset for seeking, must be 0 for upload streams */ pa_seek_mode_t seek /**< Seek mode, must be PA_SEEK_RELATIVE for upload streams */); @@ -340,16 +340,16 @@ int pa_stream_write( int pa_stream_peek( pa_stream *p /**< The stream to use */, const void **data /**< Pointer to pointer that will point to data */, - size_t *length /**< The length of the data read */); + size_t *bytes /**< The length of the data read in bytes */); /** Remove the current fragment on record streams. It is invalid to do this without first * calling pa_stream_peek(). \since 0.8 */ int pa_stream_drop(pa_stream *p); -/** Return the nember of bytes that may be written using pa_stream_write() */ +/** Return the nember of bytes that may be written using pa_stream_write(), in bytes */ size_t pa_stream_writable_size(pa_stream *p); -/** Return the number of bytes that may be read using pa_stream_read() \since 0.8 */ +/** Return the number of bytes that may be read using pa_stream_read(), in bytes \since 0.8 */ size_t pa_stream_readable_size(pa_stream *p); /** Drain a playback stream. Use this for notification when the buffer is empty */ From 099e6903e91d418ecf23a1af4a92b5ceb101b0ea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 15:08:13 +0000 Subject: [PATCH 1402/1514] make make distcheck pass git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2000 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 288c24efa..cbb47c72f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # USA. EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in README todo -SUBDIRS=libltdl src doxygen +SUBDIRS=src doxygen MAINTAINERCLEANFILES = noinst_DATA = From 0f0e729b9a252c7e79133cedef389b345232cae7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 15:23:56 +0000 Subject: [PATCH 1403/1514] make sjoerd happy: include ChangeLog built from svn logs in tarball git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2001 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile.am b/Makefile.am index cbb47c72f..79608a224 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,4 +54,11 @@ untabify: fedora-snapshot: dist cp $(distdir).tar.gz $$HOME/cvs.fedora/pulseaudio/devel/$(distdir).svn`date +%Y%m%d`.tar.gz +dist-hook: + if test -d .svn ; then \ + svn update ; \ + chmod u+w ${distdir}/ChangeLog || true ; \ + svn2cl -o ${distdir}/ChangeLog ; \ + fi + .PHONY: homepage distcleancheck doxygen From 111b7591bdb18783799981c1e341ed2d9fe79ef5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 16:02:25 +0000 Subject: [PATCH 1404/1514] bump sonames git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2002 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 567dc4ede..e08c11c10 100644 --- a/configure.ac +++ b/configure.ac @@ -41,9 +41,9 @@ AC_SUBST(PA_PROTOCOL_VERSION, 11) AC_SUBST(LIBPULSE_VERSION_INFO, [3:0:3]) AC_SUBST(LIBPULSECORE_VERSION_INFO, [4:0:0]) -AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:0:0]) -AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:0:1]) -AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:2:0]) +AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:1:0]) +AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:1:1]) +AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:3:0]) AC_CANONICAL_HOST From 5058a1e9ed700264df78409e0d629fb18a0263ef Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Oct 2007 18:35:08 +0000 Subject: [PATCH 1405/1514] save and restore errno in the sig handler git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2004 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/mainloop-signal.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c index 7d3017e2e..e41ed14c5 100644 --- a/src/pulse/mainloop-signal.c +++ b/src/pulse/mainloop-signal.c @@ -67,10 +67,16 @@ static pa_io_event* io_event = NULL; static pa_signal_event *signals = NULL; static void signal_handler(int sig) { + int saved_errno; + + saved_errno = errno; + #ifndef HAVE_SIGACTION signal(sig, signal_handler); #endif pa_write(signal_pipe[1], &sig, sizeof(sig), NULL); + + errno = saved_errno; } static void dispatch(pa_mainloop_api*a, int sig) { From 38a1525a8928d8c60fbe5227970e6c4604c5fa73 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 00:06:31 +0000 Subject: [PATCH 1406/1514] add new function pa_yes_no() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2005 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-util.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index d26cf2411..a6d221012 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -31,6 +31,7 @@ #include #include +#include struct timeval; @@ -62,6 +63,10 @@ void pa_reset_priority(void); int pa_parse_boolean(const char *s) PA_GCC_PURE; +static inline const char *pa_yes_no(pa_bool_t b) { + return b ? "yes" : "no"; +} + char *pa_split(const char *c, const char*delimiters, const char **state); char *pa_split_spaces(const char *c, const char **state); From cecd8d4d7b987ff38357ee5127f6d7479843184f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 00:06:51 +0000 Subject: [PATCH 1407/1514] fix comment git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2006 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index eefcc5847..3e70eb5c0 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -541,7 +541,7 @@ void pa_make_realtime(void) { #define NICE_LEVEL (-11) /* Raise the priority of the current process as much as possible and -sensible: set the nice level to -15.*/ +sensible: set the nice level to -11.*/ void pa_raise_priority(void) { #ifdef HAVE_SYS_RESOURCE_H From b343497d647f349b8b0a8adf50df8047ac27ecbc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 00:31:59 +0000 Subject: [PATCH 1408/1514] make the bool config parser actually parse bools git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2007 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/conf-parser.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index 0e0ba95a9..12ea49c22 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -169,7 +169,8 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, } int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { - int *b = data, k; + int k; + pa_bool_t *b = data; pa_assert(filename); pa_assert(lvalue); @@ -181,7 +182,7 @@ int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue return -1; } - *b = k; + *b = !!k; return 0; } From 65a6bff357a3ec27de8dd78e1201e75a7d959464 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 00:32:45 +0000 Subject: [PATCH 1409/1514] more pa_boolization git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2008 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/cli-command.c | 175 ++++++++++++++++++------------------ src/pulsecore/cli-command.h | 8 +- src/pulsecore/cli.c | 8 +- 3 files changed, 96 insertions(+), 95 deletions(-) diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 539fd34dd..9bd1b5096 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -58,7 +58,7 @@ struct command { const char *name; - int (*proc) (pa_core *c, pa_tokenizer*t, pa_strbuf *buf, int *fail); + int (*proc) (pa_core *c, pa_tokenizer*t, pa_strbuf *buf, pa_bool_t *fail); const char *help; unsigned args; }; @@ -77,46 +77,46 @@ enum { }; /* Prototypes for all available commands */ -static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); -static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail); +static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); /* A method table for all available commands */ @@ -181,7 +181,7 @@ static uint32_t parse_index(const char *n) { return idx; } -static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { pa_core_assert_ref(c); pa_assert(t); pa_assert(buf); @@ -191,7 +191,7 @@ static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int return 0; } -static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const struct command*command; pa_core_assert_ref(c); @@ -207,7 +207,7 @@ static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int return 0; } -static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { char *s; pa_core_assert_ref(c); @@ -221,7 +221,7 @@ static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, i return 0; } -static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { char *s; pa_core_assert_ref(c); @@ -235,7 +235,7 @@ static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, i return 0; } -static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { char *s; pa_core_assert_ref(c); @@ -249,7 +249,7 @@ static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int return 0; } -static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { char *s; pa_core_assert_ref(c); @@ -263,7 +263,7 @@ static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, i return 0; } -static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { char *s; pa_core_assert_ref(c); @@ -277,7 +277,7 @@ static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return 0; } -static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { char *s; pa_core_assert_ref(c); @@ -291,7 +291,7 @@ static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { char s[256]; const pa_mempool_stat *stat; unsigned k; @@ -352,7 +352,7 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int return 0; } -static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { pa_core_assert_ref(c); pa_assert(t); pa_assert(buf); @@ -370,7 +370,7 @@ static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int return 0; } -static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { pa_module *m; const char *name; @@ -392,7 +392,7 @@ static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int return 0; } -static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { pa_module *m; uint32_t idx; const char *i; @@ -418,7 +418,7 @@ static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, in return 0; } -static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *v; pa_sink *sink; uint32_t volume; @@ -454,7 +454,7 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return 0; } -static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *v; pa_sink_input *si; pa_volume_t volume; @@ -496,7 +496,7 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb return 0; } -static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *v; pa_source *source; uint32_t volume; @@ -532,7 +532,7 @@ static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf * return 0; } -static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *m; pa_sink *sink; int mute; @@ -566,7 +566,7 @@ static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, return 0; } -static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *m; pa_source *source; int mute; @@ -600,7 +600,7 @@ static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return 0; } -static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *v; pa_sink_input *si; uint32_t idx; @@ -640,7 +640,7 @@ static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n; pa_core_assert_ref(c); @@ -657,7 +657,7 @@ static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *b return 0; } -static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n; pa_core_assert_ref(c); @@ -674,7 +674,7 @@ static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n; pa_client *client; uint32_t idx; @@ -703,7 +703,7 @@ static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return 0; } -static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n; pa_sink_input *sink_input; uint32_t idx; @@ -732,7 +732,7 @@ static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n; pa_source_output *source_output; uint32_t idx; @@ -761,7 +761,7 @@ static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_str return 0; } -static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { char *s; pa_core_assert_ref(c); @@ -776,7 +776,7 @@ static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return 0; } -static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *sink_name; pa_sink *sink; @@ -803,7 +803,7 @@ static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return 0; } -static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n; pa_core_assert_ref(c); @@ -824,7 +824,7 @@ static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf * return 0; } -static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *fname, *n; int r; @@ -849,7 +849,7 @@ static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return 0; } -static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *pname; pa_core_assert_ref(c); @@ -870,7 +870,7 @@ static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *fname, *sink_name; pa_sink *sink; @@ -893,7 +893,7 @@ static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, return pa_play_file(sink, fname, NULL); } -static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *a, *b; pa_core_assert_ref(c); @@ -911,7 +911,7 @@ static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *b return 0; } -static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *name; pa_core_assert_ref(c); @@ -932,7 +932,7 @@ static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { char *s; pa_core_assert_ref(c); @@ -947,7 +947,7 @@ static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf * return 0; } -static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { pa_core_assert_ref(c); pa_assert(t); pa_assert(buf); @@ -957,7 +957,7 @@ static int pa_cli_command_list_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf return 0; } -static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { pa_core_assert_ref(c); pa_assert(t); pa_assert(buf); @@ -968,7 +968,7 @@ static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, in return 0; } -static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *k; pa_sink_input *si; pa_sink *sink; @@ -1011,7 +1011,7 @@ static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *k; pa_source_output *so; pa_source *source; @@ -1054,7 +1054,7 @@ static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_str return 0; } -static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *m; pa_sink *sink; int suspend; @@ -1088,7 +1088,7 @@ static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *b return 0; } -static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *n, *m; pa_source *source; int suspend; @@ -1122,7 +1122,7 @@ static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf return 0; } -static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { const char *m; int suspend; int ret; @@ -1152,7 +1152,7 @@ static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, i return 0; } -static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) { +static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { pa_module *m; pa_sink *sink; pa_source *source; @@ -1261,7 +1261,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int return 0; } -int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, int *fail, int *ifstate) { +int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail, int *ifstate) { const char *cs; pa_assert(c); @@ -1293,9 +1293,9 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b if (ifstate && *ifstate == IFSTATE_FALSE) return 0; if (!strcmp(cs, META_FAIL)) - *fail = 1; + *fail = TRUE; else if (!strcmp(cs, META_NOFAIL)) - *fail = 0; + *fail = FALSE; else { size_t l; l = strcspn(cs, whitespace); @@ -1358,11 +1358,11 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b return 0; } -int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int *fail) { +int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) { return pa_cli_command_execute_line_stateful(c, s, buf, fail, NULL); } -int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int *fail) { +int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail) { char line[256]; FILE *f = NULL; int ifstate = IFSTATE_NONE; @@ -1396,7 +1396,7 @@ fail: return ret; } -int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail) { +int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) { const char *p; int ifstate = IFSTATE_NONE; @@ -1421,4 +1421,3 @@ int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail) return 0; } - diff --git a/src/pulsecore/cli-command.h b/src/pulsecore/cli-command.h index 01bca8be4..c90c8e08a 100644 --- a/src/pulsecore/cli-command.h +++ b/src/pulsecore/cli-command.h @@ -31,15 +31,15 @@ * buffer *buf. If *fail is non-zero the function will return -1 when * one or more of the executed commands failed. *fail * may be modified by the function call. */ -int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int *fail); +int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail); /* Execute a whole file of CLI commands */ -int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, int *fail); +int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail); /* Split the specified string into lines and run pa_cli_command_execute_line() for each. */ -int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail); +int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail); /* Same as pa_cli_command_execute_line() but also take ifstate var. */ -int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, int *fail, int *ifstate); +int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail, int *ifstate); #endif diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c index 3f3c9cde7..85e08634d 100644 --- a/src/pulsecore/cli.c +++ b/src/pulsecore/cli.c @@ -59,7 +59,8 @@ struct pa_cli { pa_client *client; - int fail, kill_requested, defer_kill; + pa_bool_t fail, kill_requested; + int defer_kill; }; static void line_callback(pa_ioline *line, const char *s, void *userdata); @@ -86,7 +87,8 @@ pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) { pa_ioline_set_callback(c->line, line_callback, c); pa_ioline_puts(c->line, "Welcome to PulseAudio! Use \"help\" for usage information.\n"PROMPT); - c->fail = c->kill_requested = c->defer_kill = 0; + c->fail = c->kill_requested = FALSE; + c->defer_kill = 0; return c; } @@ -108,7 +110,7 @@ static void client_kill(pa_client *client) { pa_log_debug("CLI client killed."); if (c->defer_kill) - c->kill_requested = 1; + c->kill_requested = TRUE; else { if (c->eof_callback) c->eof_callback(c, c->userdata); From e706f7bed759165573c9ec7e5e4f79a2f9b74228 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 00:33:14 +0000 Subject: [PATCH 1410/1514] pa_boolize the client config git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2009 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/client-conf.c | 11 +++++------ src/pulse/client-conf.h | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index abd277a69..c054f663c 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -58,10 +58,10 @@ static const pa_client_conf default_conf = { .default_sink = NULL, .default_source = NULL, .default_server = NULL, - .autospawn = 0, - .disable_shm = 0, + .autospawn = FALSE, + .disable_shm = FALSE, .cookie_file = NULL, - .cookie_valid = 0, + .cookie_valid = FALSE, }; pa_client_conf *pa_client_conf_new(void) { @@ -172,7 +172,7 @@ int pa_client_conf_env(pa_client_conf *c) { int pa_client_conf_load_cookie(pa_client_conf* c) { pa_assert(c); - c->cookie_valid = 0; + c->cookie_valid = FALSE; if (!c->cookie_file) return -1; @@ -180,7 +180,6 @@ int pa_client_conf_load_cookie(pa_client_conf* c) { if (pa_authkey_load_auto(c->cookie_file, c->cookie, sizeof(c->cookie)) < 0) return -1; - c->cookie_valid = 1; + c->cookie_valid = TRUE; return 0; } - diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index 6de64582f..7cc975e62 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -30,9 +30,9 @@ typedef struct pa_client_conf { char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; - int autospawn, disable_shm; + pa_bool_t autospawn, disable_shm; uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; - int cookie_valid; /* non-zero, when cookie is valid */ + pa_bool_t cookie_valid; /* non-zero, when cookie is valid */ } pa_client_conf; /* Create a new configuration data object and reset it to defaults */ From 44d7c9ad9bcfd8ab55d4ef7f6595c7ffd65da35d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 00:34:43 +0000 Subject: [PATCH 1411/1514] add nice and rtprio resource limit support; make rtprio and nice level to use configurable; some minor updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2010 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 177 +++++++++++++++++++++++++++----------- src/daemon/daemon-conf.h | 24 ++++-- src/daemon/daemon.conf.in | 87 ++++++++++++------- src/daemon/main.c | 6 ++ 4 files changed, 209 insertions(+), 85 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 920e37173..089b12fca 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -53,10 +54,13 @@ static const pa_daemon_conf default_conf = { .cmd = PA_CMD_DAEMON, - .daemonize = 0, - .fail = 1, - .high_priority = 0, - .disallow_module_loading = 0, + .daemonize = FALSE, + .fail = TRUE, + .high_priority = TRUE, + .nice_level = -11, + .realtime_scheduling = FALSE, + .realtime_priority = 5, /* Half of JACK's default rtprio */ + .disallow_module_loading = FALSE, .exit_idle_time = -1, .module_idle_time = 20, .scache_idle_time = 20, @@ -68,25 +72,31 @@ static const pa_daemon_conf default_conf = { .log_level = PA_LOG_NOTICE, .resample_method = PA_RESAMPLER_AUTO, .config_file = NULL, - .use_pid_file = 1, - .system_instance = 0, - .no_cpu_limit = 0, - .disable_shm = 0, + .use_pid_file = TRUE, + .system_instance = FALSE, + .no_cpu_limit = FALSE, + .disable_shm = FALSE, .default_n_fragments = 4, .default_fragment_size_msec = 25, .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 } #ifdef HAVE_SYS_RESOURCE_H - , .rlimit_as = { .value = 0, .is_set = 0 }, - .rlimit_core = { .value = 0, .is_set = 0 }, - .rlimit_data = { .value = 0, .is_set = 0 }, - .rlimit_fsize = { .value = 0, .is_set = 0 }, - .rlimit_nofile = { .value = 256, .is_set = 1 }, - .rlimit_stack = { .value = 0, .is_set = 0 } + , .rlimit_as = { .value = 0, .is_set = FALSE }, + .rlimit_core = { .value = 0, .is_set = FALSE }, + .rlimit_data = { .value = 0, .is_set = FALSE }, + .rlimit_fsize = { .value = 0, .is_set = FALSE }, + .rlimit_nofile = { .value = 256, .is_set = TRUE }, + .rlimit_stack = { .value = 0, .is_set = FALSE } #ifdef RLIMIT_NPROC - , .rlimit_nproc = { .value = 0, .is_set = 0 } + , .rlimit_nproc = { .value = 0, .is_set = FALSE } #endif #ifdef RLIMIT_MEMLOCK - , .rlimit_memlock = { .value = 16384, .is_set = 1 } + , .rlimit_memlock = { .value = 16384, .is_set = TRUE } +#endif +#ifdef RLIMIT_NICE + , .rlimit_nice = { .value = 31, .is_set = TRUE } /* nice level of -11 */ +#endif +#ifdef RLIMIT_RTPRIO + , .rlimit_rtprio = { .value = 9, .is_set = TRUE } /* One below JACK's default for the server */ #endif #endif }; @@ -334,6 +344,42 @@ static int parse_fragment_size_msec(const char *filename, unsigned line, const c return 0; } +static int parse_nice_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; + int32_t level; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atoi(rvalue, &level) < 0 || level < -20 || level > 19) { + pa_log("[%s:%u] Invalid nice level '%s'.", filename, line, rvalue); + return -1; + } + + c->nice_level = (int) level; + return 0; +} + +static int parse_rtprio(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) { + pa_daemon_conf *c = data; + int32_t rtprio; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atoi(rvalue, &rtprio) < 0 || rtprio < sched_get_priority_min(SCHED_FIFO) || rtprio > sched_get_priority_max(SCHED_FIFO)) { + pa_log("[%s:%u] Invalid realtime priority '%s'.", filename, line, rvalue); + return -1; + } + + c->realtime_priority = (int) rtprio; + return 0; +} + int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { int r = -1; FILE *f = NULL; @@ -342,25 +388,28 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "daemonize", pa_config_parse_bool, NULL }, { "fail", pa_config_parse_bool, NULL }, { "high-priority", pa_config_parse_bool, NULL }, + { "realtime-scheduling", pa_config_parse_bool, NULL }, { "disallow-module-loading", pa_config_parse_bool, NULL }, + { "use-pid-file", pa_config_parse_bool, NULL }, + { "system-instance", pa_config_parse_bool, NULL }, + { "no-cpu-limit", pa_config_parse_bool, NULL }, + { "disable-shm", pa_config_parse_bool, NULL }, { "exit-idle-time", pa_config_parse_int, NULL }, { "module-idle-time", pa_config_parse_int, NULL }, { "scache-idle-time", pa_config_parse_int, NULL }, + { "realtime-priority", parse_rtprio, NULL }, { "dl-search-path", pa_config_parse_string, NULL }, { "default-script-file", pa_config_parse_string, NULL }, { "log-target", parse_log_target, NULL }, { "log-level", parse_log_level, NULL }, { "verbose", parse_log_level, NULL }, { "resample-method", parse_resample_method, NULL }, - { "use-pid-file", pa_config_parse_bool, NULL }, - { "system-instance", pa_config_parse_bool, NULL }, - { "no-cpu-limit", pa_config_parse_bool, NULL }, - { "disable-shm", pa_config_parse_bool, NULL }, { "default-sample-format", parse_sample_format, NULL }, { "default-sample-rate", parse_sample_rate, NULL }, { "default-sample-channels", parse_sample_channels, NULL }, { "default-fragments", parse_fragments, NULL }, { "default-fragment-size-msec", parse_fragment_size_msec, NULL }, + { "nice-level", parse_nice_level, NULL }, #ifdef HAVE_SYS_RESOURCE_H { "rlimit-as", parse_rlimit, NULL }, { "rlimit-core", parse_rlimit, NULL }, @@ -374,6 +423,12 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { #ifdef RLIMIT_MEMLOCK { "rlimit-memlock", parse_rlimit, NULL }, #endif +#ifdef RLIMIT_NICE + { "rlimit-nice", parse_rlimit, NULL }, +#endif +#ifdef RLIMIT_RTPRIO + { "rlimit-rtprio", parse_rlimit, NULL }, +#endif #endif { NULL, NULL, NULL }, }; @@ -381,40 +436,55 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[0].data = &c->daemonize; table[1].data = &c->fail; table[2].data = &c->high_priority; - table[3].data = &c->disallow_module_loading; - table[4].data = &c->exit_idle_time; - table[5].data = &c->module_idle_time; - table[6].data = &c->scache_idle_time; - table[7].data = &c->dl_search_path; - table[8].data = &c->default_script_file; - table[9].data = c; - table[10].data = c; - table[11].data = c; + table[3].data = &c->realtime_scheduling; + table[4].data = &c->disallow_module_loading; + table[5].data = &c->use_pid_file; + table[6].data = &c->system_instance; + table[7].data = &c->no_cpu_limit; + table[8].data = &c->disable_shm; + table[9].data = &c->exit_idle_time; + table[10].data = &c->module_idle_time; + table[11].data = &c->scache_idle_time; table[12].data = c; - table[13].data = &c->use_pid_file; - table[14].data = &c->system_instance; - table[15].data = &c->no_cpu_limit; - table[16].data = &c->disable_shm; + table[13].data = &c->dl_search_path; + table[14].data = &c->default_script_file; + table[15].data = c; + table[16].data = c; table[17].data = c; table[18].data = c; table[19].data = c; table[20].data = c; table[21].data = c; + table[22].data = c; + table[23].data = c; + table[24].data = c; #ifdef HAVE_SYS_RESOURCE_H - table[22].data = &c->rlimit_as; - table[23].data = &c->rlimit_core; - table[24].data = &c->rlimit_data; - table[25].data = &c->rlimit_fsize; - table[26].data = &c->rlimit_nofile; - table[27].data = &c->rlimit_stack; + table[25].data = &c->rlimit_as; + table[26].data = &c->rlimit_core; + table[27].data = &c->rlimit_data; + table[28].data = &c->rlimit_fsize; + table[29].data = &c->rlimit_nofile; + table[30].data = &c->rlimit_stack; #ifdef RLIMIT_NPROC - table[28].data = &c->rlimit_nproc; + table[31].data = &c->rlimit_nproc; #endif #ifdef RLIMIT_MEMLOCK #ifndef RLIMIT_NPROC #error "Houston, we have a numbering problem!" #endif - table[29].data = &c->rlimit_memlock; + table[32].data = &c->rlimit_memlock; +#endif +#ifdef RLIMIT_NICE +#ifndef RLIMIT_MEMLOCK +#error "Houston, we have a numbering problem!" +#endif + table[33].data = &c->rlimit_nice; +#endif +#ifdef RLIMIT_RTPRIO +#ifndef RLIMIT_NICE +#error "Houston, we have a numbering problem!" +#endif + table[34].data = &c->rlimit_rtprio; #endif #endif @@ -474,10 +544,17 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_assert(c->log_level <= PA_LOG_LEVEL_MAX); - pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize); - pa_strbuf_printf(s, "fail = %i\n", !!c->fail); - pa_strbuf_printf(s, "high-priority = %i\n", !!c->high_priority); - pa_strbuf_printf(s, "disallow-module-loading = %i\n", !!c->disallow_module_loading); + pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize)); + pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail)); + pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority)); + pa_strbuf_printf(s, "nice-level = %i\n", c->nice_level); + pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling)); + pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority); + pa_strbuf_printf(s, "disallow-module-loading = %s\n", pa_yes_no(c->disallow_module_loading)); + pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file)); + pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance)); + pa_strbuf_printf(s, "no-cpu-limit = %s\n", pa_yes_no(c->no_cpu_limit)); + pa_strbuf_printf(s, "disable-shm = %s\n", pa_yes_no(c->disable_shm)); pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time); pa_strbuf_printf(s, "module-idle-time = %i\n", c->module_idle_time); pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time); @@ -486,10 +563,6 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); - pa_strbuf_printf(s, "use-pid-file = %i\n", c->use_pid_file); - pa_strbuf_printf(s, "system-instance = %i\n", !!c->system_instance); - pa_strbuf_printf(s, "no-cpu-limit = %i\n", !!c->no_cpu_limit); - pa_strbuf_printf(s, "disable-shm = %i\n", !!c->disable_shm); pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format)); pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate); pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels); @@ -508,6 +581,12 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { #ifdef RLIMIT_MEMLOCK pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1); #endif +#ifdef RLIMIT_NICE + pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_nice.value : -1); +#endif +#ifdef RLIMIT_RTPRIO + pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_rtprio.value : -1); +#endif #endif return pa_strbuf_tostring_free(s); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index 4d37861db..b8930bd79 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -26,6 +26,7 @@ ***/ #include +#include #include #ifdef HAVE_SYS_RESOURCE_H @@ -48,29 +49,32 @@ typedef enum pa_daemon_conf_cmd { #ifdef HAVE_SYS_RESOURCE_H typedef struct pa_rlimit { rlim_t value; - int is_set; + pa_bool_t is_set; } pa_rlimit; #endif /* A structure containing configuration data for the PulseAudio server . */ typedef struct pa_daemon_conf { pa_daemon_conf_cmd_t cmd; - int daemonize, + pa_bool_t daemonize, fail, high_priority, + realtime_scheduling, disallow_module_loading, - exit_idle_time, - module_idle_time, - scache_idle_time, - auto_log_target, use_pid_file, system_instance, no_cpu_limit, disable_shm; + int exit_idle_time, + module_idle_time, + scache_idle_time, + auto_log_target, + realtime_priority, + nice_level, + resample_method; char *script_commands, *dl_search_path, *default_script_file; pa_log_target_t log_target; pa_log_level_t log_level; - int resample_method; char *config_file; #ifdef HAVE_SYS_RESOURCE_H @@ -81,6 +85,12 @@ typedef struct pa_daemon_conf { #ifdef RLIMIT_MEMLOCK pa_rlimit rlimit_memlock; #endif +#ifdef RLIMIT_NICE + pa_rlimit rlimit_nice; +#endif +#ifdef RLIMIT_RTPRIO + pa_rlimit rlimit_rtprio; +#endif #endif unsigned default_n_fragments, default_fragment_size_msec; diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 2132bf3d0..54acd8ead 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -20,42 +20,58 @@ ## Configuration file for the pulseaudio daemon. Default values are ## commented out. Use either ; or # for commenting -# Extra verbositiy -; verbose = 0 - ## Daemonize after startup -; daemonize = 0 +; daemonize = no ## Quit if startup fails -; fail = 1 +; fail = yes -## Renice the daemon to level -15 and try to get SCHED_FIFO -## scheduling. This a good idea if you hear annyoing noise in the -## playback. However, this is a certain security issue, since it works -## when called SUID root only. root is dropped immediately after gaining -## the nice level and SCHED_FIFO scheduling on startup. -; high-priority = 0 +## Renice the daemon to level -15. This a good idea if you experience +## drop-outs in the playback. However, this is a certain security +## issue, since it works when called SUID root only. root is dropped +## immediately after gaining the nice level on startup, thus it is +## presumably safe. +; high-priority = yes + +## Try to acquire SCHED_FIFO scheduling for the IO threads. The same +## security concerns as mentioned above apply. However, if PA enters +## an endless loop, realtime scheduling causes a system lockup. Thus, +## realtime scheduling should only be enabled on trusted machines for +## now. Please not that only the IO threads of PulseAudio are made +## real-time. The controlling thread is left a normally scheduled +## thread. Thus the enabling the high-priority option is orthogonal. +; realtime-scheduling = no + +## The realtime priority to acquire, if realtime-scheduling is +## enabled. (Note: JACK uses 10 by default, 9 for clients -- some +## PulseAudio threads might choose a priority a little lower or higher +## than this value.) +; realtime-priority = 5 + +## The nice level to acquire for the daemon, if high-priority is +## enabled. (Note: on some distributions X11 uses -10 by default.) +; nice-level = -11 ## Disallow module loading after startup -; disallow-module-loading = 0 +; disallow-module-loading = no ## Terminate the daemon after the last client quit and this time ## passed. Use a negative value to disable this feature. ; exit-idle-time = -1 -## Unload autoloaded modules after being idle for this time +## Unload autoloaded modules after being idle for this time ; module-idle-time = 20 -## Unload autoloaded sample cache entries after being idle for this time +## Unload autoloaded sample cache entries after being idle for this time ; scache-idle-time = 20 ## The path were to look for dynamic shared objects (DSOs aka ## plugins). You may specify more than one path seperated by -## colons. +## colons. ; dl-search-path = @PA_DLSEARCHPATH@ ## The default script file to load. Specify an empty string for not -## loading a default script file. The +## loading a default script file. The ; default-script-file = @PA_DEFAULT_CONFIG_FILE@ ## The default log target. Use either "stderr", "syslog" or @@ -63,31 +79,42 @@ ## true, otherwise to "stderr". ; log-target = auto +# Log level, one of debug, info, notice, warning, error. Log messages +# with a lower log level than specified here are not logged, +; log-level = notice + ## The resampling algorithm to use. Use one of src-sinc-best-quality, ## src-sinc-medium-quality, src-sinc-fastest, src-zero-order-hold, -## src-linear, trivial. See the documentation of libsamplerate for an -## explanation for the different methods. The method 'trivial' is the -## only algorithm implemented without usage of floating point -## numbers. If you're tight on CPU consider using this. On the other -## hand it has the worst quality of all. -; resample-method = sinc-fastest +## src-linear, trivial, speex-float-N, speex-fixed-N, ffmpeg. See the +## documentation of libsamplerate for an explanation for the different +## src- methods. The method 'trivial' is the most basic algorithm +## implemented. If you're tight on CPU consider using this. On the +## other hand it has the worst quality of them all. The speex +## resamplers take an integer quality setting in the range 0..9 +## (bad...good). They exist in two flavours: fixed and float. The +## former uses fixed point numbers, the latter relies on floating +## point numbers. On most desktop CPUs the float point resmapler is a +## lot faster, and it also offers slightly better quality. +; resample-method = speex-float-3 ## Create a PID file in /tmp/pulseaudio-$USER/pid. Of this is enabled ## you may use commands like "pulseaudio --kill" or "pulseaudio ## --check". If you are planning to start more than one pulseaudio ## process per user, you better disable this option since it ## effectively disables multiple instances. -; use-pid-file = 1 +; use-pid-file = yes ## Do not install the CPU load limit, even on platforms where it is -## supported. This option is useful when debugging/profiling +## supported. This option is useful when debugging/profiling ## PulseAudio to disable disturbing SIGXCPU signals. -; no-cpu-limit = 0 +; no-cpu-limit = no ## Run the daemon as system-wide instance, requires root priviliges -; system-instance = 0 +; system-instance = no -## Resource limits, see getrlimit(2) for more information +## Resource limits, see getrlimit(2) for more information. Set to -1 +## if PA shouldn't touch the resource limit. Not all resource limits +## are available on all operating systems. ; rlimit-as = -1 ; rlimit-core = -1 ; rlimit-data = -1 @@ -96,9 +123,11 @@ ; rlimit-stack = -1 ; rlimit-nproc = -1 ; rlimit-memlock = 16384 +; rlimit-nice = 31 +; rlimit-rtprio = 9 -## Disable shared memory data transfer -; disable-shm = 0 +## Disable shared memory data transfer +; disable-shm = no ## Default sample format ; default-sample-format = s16le diff --git a/src/daemon/main.c b/src/daemon/main.c index cd3cfcc89..249131e0a 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -307,6 +307,12 @@ static void set_all_rlimits(const pa_daemon_conf *conf) { #ifdef RLIMIT_MEMLOCK set_one_rlimit(&conf->rlimit_memlock, RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK"); #endif +#ifdef RLIMIT_NICE + set_one_rlimit(&conf->rlimit_nice, RLIMIT_NICE, "RLIMIT_NICE"); +#endif +#ifdef RLIMIT_RTPRIO + set_one_rlimit(&conf->rlimit_rtprio, RLIMIT_RTPRIO, "RLIMIT_RTPRIO"); +#endif } #endif From 005ed41c3f83430ce936f55378c68f1e29557aeb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 01:42:34 +0000 Subject: [PATCH 1412/1514] save and restore errno in sig handler git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2011 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/cpulimit.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c index ab212129e..b77dd4437 100644 --- a/src/daemon/cpulimit.c +++ b/src/daemon/cpulimit.c @@ -113,6 +113,9 @@ static void write_err(const char *p) { /* The signal handler, called on every SIGXCPU */ static void signal_handler(int sig) { + int saved_errno; + + saved_errno = errno; pa_assert(sig == SIGXCPU); if (phase == PHASE_IDLE) { @@ -150,6 +153,8 @@ static void signal_handler(int sig) { write_err("Hard CPU time limit exhausted, terminating forcibly.\n"); _exit(1); /* Forced exit */ } + + errno = saved_errno; } /* Callback for IO events on the FIFO */ From 41ea3b2fd4fa0a0a4d884ad00e9b3b060082515b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 01:45:01 +0000 Subject: [PATCH 1413/1514] add new option --realtime git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2012 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/cmdline.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index 6b7b26712..0c8404490 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -49,6 +49,7 @@ enum { ARG_FAIL, ARG_LOG_LEVEL, ARG_HIGH_PRIORITY, + ARG_REALTIME, ARG_DISALLOW_MODULE_LOADING, ARG_EXIT_IDLE_TIME, ARG_MODULE_IDLE_TIME, @@ -79,6 +80,7 @@ static struct option long_options[] = { {"verbose", 2, 0, ARG_LOG_LEVEL}, {"log-level", 2, 0, ARG_LOG_LEVEL}, {"high-priority", 2, 0, ARG_HIGH_PRIORITY}, + {"realtime", 2, 0, ARG_REALTIME}, {"disallow-module-loading", 2, 0, ARG_DISALLOW_MODULE_LOADING}, {"exit-idle-time", 2, 0, ARG_EXIT_IDLE_TIME}, {"module-idle-time", 2, 0, ARG_MODULE_IDLE_TIME}, @@ -124,8 +126,12 @@ void pa_cmdline_help(const char *argv0) { " --system[=BOOL] Run as system-wide instance\n" " -D, --daemonize[=BOOL] Daemonize after startup\n" " --fail[=BOOL] Quit when startup fails\n" - " --high-priority[=BOOL] Try to set high process priority\n" - " (only available as root)\n" + " --high-priority[=BOOL] Try to set high nice level\n" + " (only available as root, when SUID or\n" + " with elevated RLIMIT_NICE)\n" + " --realtime[=BOOL] Try to enable realtime scheduling\n" + " (only available as root, when SUID or\n" + " with elevated RLIMIT_RTPRIO)\n" " --disallow-module-loading[=BOOL] Disallow module loading after startup\n" " --exit-idle-time=SECS Terminate the daemon when idle and this\n" " time passed\n" @@ -224,14 +230,14 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d case ARG_DAEMONIZE: case 'D': - if ((conf->daemonize = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + if ((conf->daemonize = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--daemonize expects boolean argument"); goto fail; } break; case ARG_FAIL: - if ((conf->fail = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + if ((conf->fail = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--fail expects boolean argument"); goto fail; } @@ -253,21 +259,28 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d break; case ARG_HIGH_PRIORITY: - if ((conf->high_priority = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + if ((conf->high_priority = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--high-priority expects boolean argument"); goto fail; } break; + case ARG_REALTIME: + if ((conf->realtime_scheduling = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { + pa_log("--realtime expects boolean argument"); + goto fail; + } + break; + case ARG_DISALLOW_MODULE_LOADING: - if ((conf->disallow_module_loading = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + if ((conf->disallow_module_loading = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--disallow-module-loading expects boolean argument"); goto fail; } break; case ARG_USE_PID_FILE: - if ((conf->use_pid_file = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + if ((conf->use_pid_file = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--use-pid-file expects boolean argument"); goto fail; } @@ -311,21 +324,21 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d break; case ARG_SYSTEM: - if ((conf->system_instance = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + if ((conf->system_instance = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--system expects boolean argument"); goto fail; } break; case ARG_NO_CPU_LIMIT: - if ((conf->no_cpu_limit = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + if ((conf->no_cpu_limit = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--no-cpu-limit expects boolean argument"); goto fail; } break; case ARG_DISABLE_SHM: - if ((conf->disable_shm = optarg ? pa_parse_boolean(optarg) : 1) < 0) { + if ((conf->disable_shm = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--disable-shm expects boolean argument"); goto fail; } From 641d1fa96485f7a258ad958c4031e655767808a8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 02:55:06 +0000 Subject: [PATCH 1414/1514] drop rt scheduling before we start our helper process git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2013 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index c2ea7b27f..799bdfbdf 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -365,6 +365,8 @@ static int start_client(const char *n, pid_t *pid) { int max_fd, i; /* child */ + pa_reset_priority(); + close(pipe_fds[0]); dup2(pipe_fds[1], 1); From 7bfd1b2f01613dd14b9ca478ae530c1641aa46a1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 02:58:26 +0000 Subject: [PATCH 1415/1514] make rtprio and nice level actually configurable git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2014 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 7 +-- src/modules/module-alsa-sink.c | 4 +- src/modules/module-alsa-source.c | 4 +- src/modules/module-combine.c | 4 +- src/modules/module-jack-sink.c | 8 +-- src/modules/module-jack-source.c | 8 +-- src/modules/module-oss.c | 4 +- src/pulsecore/core-util.c | 87 +++++++++++++++++++++++--------- src/pulsecore/core-util.h | 4 +- src/pulsecore/core.c | 11 ++-- src/pulsecore/core.h | 7 +-- 11 files changed, 94 insertions(+), 54 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 249131e0a..01cbba182 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -419,9 +419,9 @@ int main(int argc, char *argv[]) { pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL); if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) - pa_raise_priority(); + pa_raise_priority(conf->nice_level); - if (suid_root && (conf->cmd != PA_CMD_DAEMON || !conf->high_priority)) { + if (suid_root && (conf->cmd != PA_CMD_DAEMON || !conf->realtime_scheduling)) { pa_drop_caps(); pa_drop_root(); } @@ -636,7 +636,6 @@ int main(int argc, char *argv[]) { } c->is_system_instance = !!conf->system_instance; - c->high_priority = !!conf->high_priority; c->default_sample_spec = conf->default_sample_spec; c->default_n_fragments = conf->default_n_fragments; c->default_fragment_size_msec = conf->default_fragment_size_msec; @@ -645,6 +644,8 @@ int main(int argc, char *argv[]) { c->module_idle_time = conf->module_idle_time; c->scache_idle_time = conf->scache_idle_time; c->resample_method = conf->resample_method; + c->realtime_priority = conf->realtime_priority; + c->realtime_scheduling = !!conf->realtime_scheduling; pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_signal_new(SIGINT, signal_callback, c); diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index a09247fea..88594cdaf 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -603,8 +603,8 @@ static void thread_func(void *userdata) { pa_log_debug("Thread starting up"); - if (u->core->high_priority) - pa_make_realtime(); + if (u->core->realtime_scheduling) + pa_make_realtime(u->core->realtime_priority); pa_thread_mq_install(&u->thread_mq); pa_rtpoll_install(u->rtpoll); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index d840cac30..a862657f8 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -592,8 +592,8 @@ static void thread_func(void *userdata) { pa_log_debug("Thread starting up"); - if (u->core->high_priority) - pa_make_realtime(); + if (u->core->realtime_scheduling) + pa_make_realtime(u->core->realtime_priority); pa_thread_mq_install(&u->thread_mq); pa_rtpoll_install(u->rtpoll); diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 665bf9dd4..aca4ba32a 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -233,8 +233,8 @@ static void thread_func(void *userdata) { pa_log_debug("Thread starting up"); - if (u->core->high_priority) - pa_make_realtime(); + if (u->core->realtime_scheduling) + pa_make_realtime(u->core->realtime_priority+1); pa_thread_mq_install(&u->thread_mq); pa_rtpoll_install(u->rtpoll); diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 2cf8a58c5..840867ce1 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -214,8 +214,8 @@ static void thread_func(void *userdata) { pa_log_debug("Thread starting up"); - if (u->core->high_priority) - pa_make_realtime(); + if (u->core->realtime_scheduling) + pa_make_realtime(u->core->realtime_priority); pa_thread_mq_install(&u->thread_mq); pa_rtpoll_install(u->rtpoll); @@ -253,8 +253,8 @@ static void jack_init(void *arg) { pa_log_info("JACK thread starting up."); - if (u->core->high_priority) - pa_make_realtime(); + if (u->core->realtime_scheduling) + pa_make_realtime(u->core->realtime_priority+4); } static void jack_shutdown(void* arg) { diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index b62ebe7a1..380f87ebe 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -191,8 +191,8 @@ static void thread_func(void *userdata) { pa_log_debug("Thread starting up"); - if (u->core->high_priority) - pa_make_realtime(); + if (u->core->realtime_scheduling) + pa_make_realtime(u->core->realtime_priority); pa_thread_mq_install(&u->thread_mq); pa_rtpoll_install(u->rtpoll); @@ -230,8 +230,8 @@ static void jack_init(void *arg) { pa_log_info("JACK thread starting up."); - if (u->core->high_priority) - pa_make_realtime(); + if (u->core->realtime_scheduling) + pa_make_realtime(u->core->realtime_priority+4); } static void jack_shutdown(void* arg) { diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 19dceef27..51ab8a853 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -863,8 +863,8 @@ static void thread_func(void *userdata) { pa_log_debug("Thread starting up"); - if (u->core->high_priority) - pa_make_realtime(); + if (u->core->realtime_scheduling) + pa_make_realtime(u->core->realtime_priority); pa_thread_mq_install(&u->thread_mq); pa_rtpoll_install(u->rtpoll); diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 3e70eb5c0..1a62bce43 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -512,8 +512,10 @@ char *pa_strlcpy(char *b, const char *s, size_t l) { return b; } -/* Make the current thread a realtime thread*/ -void pa_make_realtime(void) { +/* Make the current thread a realtime thread, and acquire the highest + * rtprio we can get that is less or equal the specified parameter. If + * the thread is already realtime, don't do anything. */ +int pa_make_realtime(int rtprio) { #ifdef _POSIX_PRIORITY_SCHEDULING struct sched_param sp; @@ -524,50 +526,87 @@ void pa_make_realtime(void) { if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) { pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r)); - return; + return -1; } - sp.sched_priority = 1; + if (policy == SCHED_FIFO && sp.sched_priority >= rtprio) { + pa_log_info("Thread already being scheduled with SCHED_FIFO with priority %i.", sp.sched_priority); + return 0; + } + + sp.sched_priority = rtprio; if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) != 0) { + + while (sp.sched_priority > 1) { + sp.sched_priority --; + + if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) == 0) { + pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i.", sp.sched_priority, rtprio); + return 0; + } + } + pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r)); - return; + return -1; } - pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread."); + pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority); + return 0; +#else + return -1; #endif - } -#define NICE_LEVEL (-11) - -/* Raise the priority of the current process as much as possible and -sensible: set the nice level to -11.*/ -void pa_raise_priority(void) { +/* Raise the priority of the current process as much as possible that + * is <= the specified nice level..*/ +int pa_raise_priority(int nice_level) { #ifdef HAVE_SYS_RESOURCE_H - if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0) + if (setpriority(PRIO_PROCESS, 0, nice_level) < 0) { + int n; + + for (n = nice_level+1; n < 0; n++) { + + if (setpriority(PRIO_PROCESS, 0, n) == 0) { + pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level); + return 0; + } + } + pa_log_warn("setpriority(): %s", pa_cstrerror(errno)); - else - pa_log_info("Successfully gained nice level %i.", NICE_LEVEL); + return -1; + } + + pa_log_info("Successfully gained nice level %i.", nice_level); #endif #ifdef OS_IS_WIN32 - if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) - pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError()); - else - pa_log_info("Successfully gained high priority class."); + if (nice_level < 0) { + if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) { + pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError()); + return .-1; + } else + pa_log_info("Successfully gained high priority class."); + } #endif + + return 0; } /* Reset the priority to normal, inverting the changes made by - * pa_raise_priority() */ + * pa_raise_priority() and pa_make_realtime()*/ void pa_reset_priority(void) { -#ifdef OS_IS_WIN32 - SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); +#ifdef HAVE_SYS_RESOURCE_H + struct sched_param sp; + + setpriority(PRIO_PROCESS, 0, 0); + + memset(&sp, 0, sizeof(sp)); + pa_assert_se(pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp) == 0); #endif -#ifdef HAVE_SYS_RESOURCE_H - setpriority(PRIO_PROCESS, 0, 0); +#ifdef OS_IS_WIN32 + SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); #endif } diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index a6d221012..c8760a1fd 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -57,8 +57,8 @@ char *pa_strlcpy(char *b, const char *s, size_t l); char *pa_parent_dir(const char *fn); -void pa_make_realtime(void); -void pa_raise_priority(void); +int pa_make_realtime(int rtprio); +int pa_raise_priority(int nice_level); void pa_reset_priority(void); int pa_parse_boolean(const char *s) PA_GCC_PURE; diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index e67f15b56..9b420c948 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -107,7 +107,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { c->scache = NULL; c->autoload_idxset = NULL; c->autoload_hashmap = NULL; - c->running_as_daemon = 0; + c->running_as_daemon = FALSE; c->default_sample_spec.format = PA_SAMPLE_S16NE; c->default_sample_spec.rate = 44100; @@ -134,10 +134,10 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3; - c->is_system_instance = 0; - c->disallow_module_loading = 0; - c->high_priority = 0; - + c->is_system_instance = FALSE; + c->disallow_module_loading = FALSE; + c->realtime_scheduling = FALSE; + c->realtime_priority = 5; for (j = 0; j < PA_CORE_HOOK_MAX; j++) pa_hook_init(&c->hooks[j], c); @@ -217,4 +217,3 @@ void pa_core_check_quit(pa_core *c) { c->quit_event = NULL; } } - diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index dfa80f8d6..9aeb7888a 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -113,10 +113,11 @@ struct pa_core { pa_time_event *scache_auto_unload_event; - int disallow_module_loading, running_as_daemon; + pa_bool_t disallow_module_loading, running_as_daemon; pa_resample_method_t resample_method; - int is_system_instance; - int high_priority; + pa_bool_t is_system_instance; + pa_bool_t realtime_scheduling; + int realtime_priority; /* hooks */ pa_hook hooks[PA_CORE_HOOK_MAX]; From 81233c178113e92862ac5da77fdfdd2e82a33990 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 11:23:45 +0000 Subject: [PATCH 1416/1514] make disallow-module-loading config option work again (original patch from Diego Petteno) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2015 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/daemon/main.c b/src/daemon/main.c index 01cbba182..051c323eb 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -639,7 +639,6 @@ int main(int argc, char *argv[]) { c->default_sample_spec = conf->default_sample_spec; c->default_n_fragments = conf->default_n_fragments; c->default_fragment_size_msec = conf->default_fragment_size_msec; - c->disallow_module_loading = conf->disallow_module_loading; c->exit_idle_time = conf->exit_idle_time; c->module_idle_time = conf->module_idle_time; c->scache_idle_time = conf->scache_idle_time; @@ -666,7 +665,7 @@ int main(int argc, char *argv[]) { #endif if (conf->daemonize) - c->running_as_daemon = 1; + c->running_as_daemon = TRUE; oil_init(); @@ -682,6 +681,10 @@ int main(int argc, char *argv[]) { pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); pa_xfree(s); + /* We completed the initial module loading, so let's disable it + * from now on, if requested */ + c->disallow_module_loading = !!conf->disallow_module_loading; + if (r < 0 && conf->fail) { pa_log("failed to initialize daemon."); #ifdef HAVE_FORK From cb0d7ff60a60d4ba53491a2ebd46159200ee22dd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 22:50:32 +0000 Subject: [PATCH 1417/1514] add missing pthread libs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2016 fefdeb5f-60dc-0310-8127-8f9354f1896f --- libpulse-browse.pc.in | 2 +- libpulse-mainloop-glib.pc.in | 2 +- libpulse-simple.pc.in | 2 +- libpulse.pc.in | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libpulse-browse.pc.in b/libpulse-browse.pc.in index 7b9a59f41..66438b2a3 100644 --- a/libpulse-browse.pc.in +++ b/libpulse-browse.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: libpulse-browse Description: PulseAudio Network Browsing API Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpulse-browse +Libs: -L${libdir} -lpulse-browse @PTHREAD_LIBS@ Cflags: -D_REENTRANT -I${includedir} Requires: libpulse diff --git a/libpulse-mainloop-glib.pc.in b/libpulse-mainloop-glib.pc.in index 0977f185d..1a8bfa406 100644 --- a/libpulse-mainloop-glib.pc.in +++ b/libpulse-mainloop-glib.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: libpulse-mainloop-glib Description: GLIB 2.0 Main Loop Wrapper for PulseAudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpulse-mainloop-glib +Libs: -L${libdir} -lpulse-mainloop-glib @PTHREAD_LIBS@ Cflags: -D_REENTRANT -I${includedir} Requires: libpulse glib-2.0 diff --git a/libpulse-simple.pc.in b/libpulse-simple.pc.in index 4ccc3d582..00d1245ae 100644 --- a/libpulse-simple.pc.in +++ b/libpulse-simple.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: libpulse-simple Description: Simplified Synchronous Client Interface to PulseAudio Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lpulse-simple +Libs: -L${libdir} -lpulse-simple @PTHREAD_LIBS@ Cflags: -D_REENTRANT -I${includedir} Requires: libpulse diff --git a/libpulse.pc.in b/libpulse.pc.in index 0f01799b1..2193b2b92 100644 --- a/libpulse.pc.in +++ b/libpulse.pc.in @@ -8,4 +8,3 @@ Description: Client Interface to PulseAudio Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpulse @PTHREAD_LIBS@ Cflags: -D_REENTRANT -I${includedir} -Requires: From bc161b4b4aeb94df18622031217e73d27250cf2b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 1 Nov 2007 22:51:46 +0000 Subject: [PATCH 1418/1514] comment the library versions a bit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2017 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e08c11c10..07db98234 100644 --- a/configure.ac +++ b/configure.ac @@ -39,12 +39,27 @@ AC_SUBST(PACKAGE_URL, [http://pulseaudio.org/]) AC_SUBST(PA_API_VERSION, 10) AC_SUBST(PA_PROTOCOL_VERSION, 11) +# The stable ABI for client applications, for the version info x:y:z +# always will hold y=z AC_SUBST(LIBPULSE_VERSION_INFO, [3:0:3]) -AC_SUBST(LIBPULSECORE_VERSION_INFO, [4:0:0]) + +# A simplified, synchronous, ABI-stable interface for client +# applications, for the version info x:y:z always will hold y=z AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:1:0]) + +# The ABI-stable network browsing interface for client applications, +# for the version info x:y:z always will hold y=z AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:1:1]) + +# The ABI-stable GLib adapter for client applications, for the version +# info x:y:z always will hold y=z AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:3:0]) +# An internally used, ABI-unstable library that contains the +# PulseAudio core, SONAMEs are bumped on every release, version info +# suffix will always be 0:0 +AC_SUBST(LIBPULSECORE_VERSION_INFO, [4:0:0]) + AC_CANONICAL_HOST if type -p stow > /dev/null && test -d /usr/local/stow ; then From 95af1e616b061142da606637d42d493f9918cfea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 4 Nov 2007 13:51:18 +0000 Subject: [PATCH 1419/1514] Add linker version script to hide non-ABI stable symbols in the client libraries. While this helps defining a more streamlined ABI, this also requires linking a lot of additional symbols into some PA client utilities which until now made use of the non-ABI stable symbols in libpulse. To minimize the effect on there size a bit, strip unused symbols by linking with -ffunction-sections -fdata-sections -Wl,--gc-sections git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2018 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 30 ++++--- src/map-file | 220 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 240 insertions(+), 10 deletions(-) create mode 100644 src/map-file diff --git a/src/Makefile.am b/src/Makefile.am index b1393e34c..dbb9adcd3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -64,7 +64,7 @@ AM_LIBADD = $(PTHREAD_LIBS) AM_LDADD = $(PTHREAD_LIBS) # Only required on some platforms but defined for all to avoid errors -AM_LDFLAGS = -Wl,-no-undefined +AM_LDFLAGS = -Wl,-no-undefined -ffunction-sections -fdata-sections -Wl,--gc-sections if STATIC_BINS BINLDFLAGS = -static @@ -101,7 +101,8 @@ EXTRA_DIST = \ daemon/esdcompat.in \ utils/padsp \ modules/module-defs.h.m4 \ - daemon/pulseaudio-module-xsmp.desktop + daemon/pulseaudio-module-xsmp.desktop \ + map-file pulseconf_DATA = \ default.pa \ @@ -194,12 +195,12 @@ pasuspender_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS) pasuspender_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pasuspender_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pacmd_SOURCES = utils/pacmd.c pulsecore/pid.c pulsecore/pid.h +pacmd_SOURCES = utils/pacmd.c pulsecore/pid.c pulsecore/pid.h pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS) pacmd_CFLAGS = $(AM_CFLAGS) pacmd_LDADD = $(AM_LDADD) libpulse.la pacmd_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pax11publish_SOURCES = utils/pax11publish.c +pax11publish_SOURCES = utils/pax11publish.c pulsecore/x11prop.c pulsecore/x11prop.h pulse/client-conf.c pulse/client-conf.h pulsecore/authkey.h pulsecore/authkey.c pulsecore/random.h pulsecore/random.c pulsecore/conf-parser.c pulsecore/conf-parser.h pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS) pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) pax11publish_LDADD = $(AM_LDADD) libpulse.la $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -374,7 +375,7 @@ sync_playback_CFLAGS = $(AM_CFLAGS) sync_playback_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) interpol_test_SOURCES = tests/interpol-test.c -interpol_test_LDADD = $(AM_LDADD) libpulse.la +interpol_test_LDADD = $(AM_LDADD) libpulse.la libpulsecore.la interpol_test_CFLAGS = $(AM_CFLAGS) interpol_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) @@ -525,7 +526,7 @@ libpulse_la_SOURCES += \ endif libpulse_la_CFLAGS = $(AM_CFLAGS) -libpulse_la_LDFLAGS = -version-info $(LIBPULSE_VERSION_INFO) +libpulse_la_LDFLAGS = -version-info $(LIBPULSE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file libpulse_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LIBICONV) if HAVE_X11 @@ -541,17 +542,17 @@ endif libpulse_simple_la_SOURCES = pulse/simple.c pulse/simple.h libpulse_simple_la_CFLAGS = $(AM_CFLAGS) libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la -libpulse_simple_la_LDFLAGS = -version-info $(LIBPULSE_SIMPLE_VERSION_INFO) +libpulse_simple_la_LDFLAGS = -version-info $(LIBPULSE_SIMPLE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file -libpulse_browse_la_SOURCES = pulse/browser.c pulse/browser.h pulsecore/avahi-wrap.c pulsecore/avahi-wrap.h +libpulse_browse_la_SOURCES = pulse/browser.c pulse/browser.h pulsecore/avahi-wrap.c pulsecore/avahi-wrap.h pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS) libpulse_browse_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS) libpulse_browse_la_LIBADD = $(AM_LIBADD) libpulse.la $(AVAHI_LIBS) -libpulse_browse_la_LDFLAGS = -version-info $(LIBPULSE_BROWSE_VERSION_INFO) +libpulse_browse_la_LDFLAGS = -version-info $(LIBPULSE_BROWSE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file libpulse_mainloop_glib_la_SOURCES = pulse/glib-mainloop.h pulse/glib-mainloop.c libpulse_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS) libpulse_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpulse.la $(GLIB20_LIBS) -libpulse_mainloop_glib_la_LDFLAGS = -version-info $(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO) +libpulse_mainloop_glib_la_LDFLAGS = -version-info $(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file ################################### # OSS emulation # @@ -1459,4 +1460,13 @@ update-speex: update-ffmpeg: wget -O pulsecore/ffmpeg/resample2.c http://svn.mplayerhq.hu/ffmpeg/trunk/libavcodec/resample2.c?view=co +# Automatically generate linker version script. We use the same one for all public .sos +update-map-file: + ( echo "PULSE_0 {" ; \ + echo "global:" ; \ + ctags -I PA_GCC_PURE,PA_GCC_CONST -f - --c-kinds=p $(pulseinclude_HEADERS) | awk '/^pa_/ { print $$1 ";" }' | sort ; \ + echo "local:" ; \ + echo "*;" ; \ + echo "};" ) > $(srcdir)/map-file + .PHONY: utils/padsp diff --git a/src/map-file b/src/map-file new file mode 100644 index 000000000..427a3a789 --- /dev/null +++ b/src/map-file @@ -0,0 +1,220 @@ +PULSE_0 { +global: +pa_browser_new; +pa_browser_new_full; +pa_browser_ref; +pa_browser_set_callback; +pa_browser_set_error_callback; +pa_browser_unref; +pa_bytes_per_second; +pa_bytes_snprint; +pa_bytes_to_usec; +pa_channel_map_equal; +pa_channel_map_init; +pa_channel_map_init_auto; +pa_channel_map_init_mono; +pa_channel_map_init_stereo; +pa_channel_map_parse; +pa_channel_map_snprint; +pa_channel_map_valid; +pa_channel_position_to_pretty_string; +pa_channel_position_to_string; +pa_context_add_autoload; +pa_context_connect; +pa_context_disconnect; +pa_context_drain; +pa_context_errno; +pa_context_exit_daemon; +pa_context_get_autoload_info_by_index; +pa_context_get_autoload_info_by_name; +pa_context_get_autoload_info_list; +pa_context_get_client_info; +pa_context_get_client_info_list; +pa_context_get_module_info; +pa_context_get_module_info_list; +pa_context_get_protocol_version; +pa_context_get_sample_info_by_index; +pa_context_get_sample_info_by_name; +pa_context_get_sample_info_list; +pa_context_get_server; +pa_context_get_server_info; +pa_context_get_server_protocol_version; +pa_context_get_sink_info_by_index; +pa_context_get_sink_info_by_name; +pa_context_get_sink_info_list; +pa_context_get_sink_input_info; +pa_context_get_sink_input_info_list; +pa_context_get_source_info_by_index; +pa_context_get_source_info_by_name; +pa_context_get_source_info_list; +pa_context_get_source_output_info; +pa_context_get_source_output_info_list; +pa_context_get_state; +pa_context_is_local; +pa_context_is_pending; +pa_context_kill_client; +pa_context_kill_sink_input; +pa_context_kill_source_output; +pa_context_load_module; +pa_context_move_sink_input_by_index; +pa_context_move_sink_input_by_name; +pa_context_move_source_output_by_index; +pa_context_move_source_output_by_name; +pa_context_new; +pa_context_play_sample; +pa_context_ref; +pa_context_remove_autoload_by_index; +pa_context_remove_autoload_by_name; +pa_context_remove_sample; +pa_context_set_default_sink; +pa_context_set_default_source; +pa_context_set_name; +pa_context_set_sink_input_mute; +pa_context_set_sink_input_volume; +pa_context_set_sink_mute_by_index; +pa_context_set_sink_mute_by_name; +pa_context_set_sink_volume_by_index; +pa_context_set_sink_volume_by_name; +pa_context_set_source_mute_by_index; +pa_context_set_source_mute_by_name; +pa_context_set_source_volume_by_index; +pa_context_set_source_volume_by_name; +pa_context_set_state_callback; +pa_context_set_subscribe_callback; +pa_context_stat; +pa_context_subscribe; +pa_context_suspend_sink_by_index; +pa_context_suspend_sink_by_name; +pa_context_suspend_source_by_index; +pa_context_suspend_source_by_name; +pa_context_unload_module; +pa_context_unref; +pa_cvolume_avg; +pa_cvolume_channels_equal_to; +pa_cvolume_equal; +pa_cvolume_set; +pa_cvolume_snprint; +pa_cvolume_valid; +pa_frame_size; +pa_get_binary_name; +pa_get_fqdn; +pa_get_home_dir; +pa_get_host_name; +pa_get_library_version; +pa_gettimeofday; +pa_get_user_name; +pa_glib_mainloop_free; +pa_glib_mainloop_get_api; +pa_glib_mainloop_new; +pa_locale_to_utf8; +pa_mainloop_api_once; +pa_mainloop_dispatch; +pa_mainloop_free; +pa_mainloop_get_api; +pa_mainloop_get_retval; +pa_mainloop_iterate; +pa_mainloop_new; +pa_mainloop_poll; +pa_mainloop_prepare; +pa_mainloop_quit; +pa_mainloop_run; +pa_mainloop_set_poll_func; +pa_mainloop_wakeup; +pa_msleep; +pa_operation_cancel; +pa_operation_get_state; +pa_operation_ref; +pa_operation_unref; +pa_parse_sample_format; +pa_path_get_filename; +pa_sample_format_to_string; +pa_sample_size; +pa_sample_spec_equal; +pa_sample_spec_snprint; +pa_sample_spec_valid; +pa_signal_done; +pa_signal_free; +pa_signal_init; +pa_signal_new; +pa_signal_set_destroy; +pa_simple_drain; +pa_simple_flush; +pa_simple_free; +pa_simple_get_latency; +pa_simple_new; +pa_simple_read; +pa_simple_write; +pa_stream_connect_playback; +pa_stream_connect_record; +pa_stream_connect_upload; +pa_stream_cork; +pa_stream_disconnect; +pa_stream_drain; +pa_stream_drop; +pa_stream_finish_upload; +pa_stream_flush; +pa_stream_get_buffer_attr; +pa_stream_get_channel_map; +pa_stream_get_context; +pa_stream_get_index; +pa_stream_get_latency; +pa_stream_get_sample_spec; +pa_stream_get_state; +pa_stream_get_time; +pa_stream_get_timing_info; +pa_stream_new; +pa_stream_peek; +pa_stream_prebuf; +pa_stream_readable_size; +pa_stream_ref; +pa_stream_set_latency_update_callback; +pa_stream_set_name; +pa_stream_set_overflow_callback; +pa_stream_set_read_callback; +pa_stream_set_state_callback; +pa_stream_set_underflow_callback; +pa_stream_set_write_callback; +pa_stream_trigger; +pa_stream_unref; +pa_stream_update_timing_info; +pa_stream_writable_size; +pa_stream_write; +pa_strerror; +pa_sw_cvolume_multiply; +pa_sw_volume_from_dB; +pa_sw_volume_from_linear; +pa_sw_volume_multiply; +pa_sw_volume_to_dB; +pa_sw_volume_to_linear; +pa_threaded_mainloop_accept; +pa_threaded_mainloop_free; +pa_threaded_mainloop_get_api; +pa_threaded_mainloop_get_retval; +pa_threaded_mainloop_in_thread; +pa_threaded_mainloop_lock; +pa_threaded_mainloop_new; +pa_threaded_mainloop_signal; +pa_threaded_mainloop_start; +pa_threaded_mainloop_stop; +pa_threaded_mainloop_unlock; +pa_threaded_mainloop_wait; +pa_timeval_add; +pa_timeval_age; +pa_timeval_cmp; +pa_timeval_diff; +pa_timeval_load; +pa_timeval_store; +pa_usec_to_bytes; +pa_utf8_filter; +pa_utf8_to_locale; +pa_utf8_valid; +pa_xfree; +pa_xmalloc; +pa_xmalloc0; +pa_xmemdup; +pa_xrealloc; +pa_xstrdup; +pa_xstrndup; +local: +*; +}; From 9ac93287a80cf970ccec399a3acaa9752b0193da Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 4 Nov 2007 14:11:53 +0000 Subject: [PATCH 1420/1514] Properly terminate pa_readlink() strings. Patch from Sjoerd Simons. Closes #149 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2019 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/core-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 1a62bce43..fb032f237 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -1562,7 +1562,7 @@ char *pa_readlink(const char *p) { } if ((size_t) n < l-1) { - c[l-1] = 0; + c[n] = 0; return c; } From 0184d70ef18c1f8cd346508d2aa16b59d71065c3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 4 Nov 2007 14:17:48 +0000 Subject: [PATCH 1421/1514] add eventfd syscall nr for arm; patch from Sjoerd Simons; Closes #150 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2020 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/fdsem.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c index 927bf00c2..59eec18ef 100644 --- a/src/pulsecore/fdsem.c +++ b/src/pulsecore/fdsem.c @@ -53,6 +53,10 @@ #define __NR_eventfd 284 #endif +#if !defined(__NR_eventfd) && defined(__arm__) +#define __NR_eventfd (__NR_SYSCALL_BASE+351) +#endif + #if !defined(SYS_eventfd) && defined(__NR_eventfd) #define SYS_eventfd __NR_eventfd #endif From faf1fd76a9bb9e47c867f9aa4ea18a7a70a14aae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 4 Nov 2007 16:50:23 +0000 Subject: [PATCH 1422/1514] pa_boolization git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2021 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 77e6174f3..8ef72b2a2 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -64,7 +64,7 @@ static const char* const valid_modargs[] = { struct rule { char* name; - int volume_is_set; + pa_bool_t volume_is_set; pa_cvolume volume; char *sink; char *source; @@ -74,7 +74,7 @@ struct userdata { pa_hashmap *hashmap; pa_subscription *subscription; pa_hook_slot *sink_input_hook_slot, *source_output_hook_slot; - int modified; + pa_bool_t modified; char *table_file; }; @@ -141,7 +141,7 @@ static int load_rules(struct userdata *u) { while (!feof(f)) { struct rule *rule; pa_cvolume v; - int v_is_set; + pa_bool_t v_is_set; if (!fgets(ln, sizeof(buf_name), f)) break; @@ -176,9 +176,9 @@ static int load_rules(struct userdata *u) { goto finish; } - v_is_set = 1; + v_is_set = TRUE; } else - v_is_set = 0; + v_is_set = FALSE; ln = buf_name; @@ -328,15 +328,15 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!r->volume_is_set || !pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { pa_log_info("Saving volume for <%s>", r->name); r->volume = *pa_sink_input_get_volume(si); - r->volume_is_set = 1; - u->modified = 1; + r->volume_is_set = TRUE; + u->modified = TRUE; } if (!r->sink || strcmp(si->sink->name, r->sink) != 0) { pa_log_info("Saving sink for <%s>", r->name); pa_xfree(r->sink); r->sink = pa_xstrdup(si->sink->name); - u->modified = 1; + u->modified = TRUE; } } else { pa_assert(so); @@ -345,7 +345,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 pa_log_info("Saving source for <%s>", r->name); pa_xfree(r->source); r->source = pa_xstrdup(so->source->name); - u->modified = 1; + u->modified = TRUE; } } @@ -357,18 +357,18 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (si) { r->volume = *pa_sink_input_get_volume(si); - r->volume_is_set = 1; + r->volume_is_set = TRUE; r->sink = pa_xstrdup(si->sink->name); r->source = NULL; } else { pa_assert(so); - r->volume_is_set = 0; + r->volume_is_set = FALSE; r->sink = NULL; r->source = pa_xstrdup(so->source->name); } pa_hashmap_put(u->hashmap, r->name, r); - u->modified = 1; + u->modified = TRUE; } } @@ -433,7 +433,7 @@ int pa__init(pa_module*m) { u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); u->subscription = NULL; u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL)); - u->modified = 0; + u->modified = FALSE; u->sink_input_hook_slot = u->source_output_hook_slot = NULL; m->userdata = u; @@ -493,5 +493,3 @@ void pa__done(pa_module*m) { pa_xfree(u->table_file); pa_xfree(u); } - - From 961ce33b5ee183236363ef39d1afa93d8e5605b3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 4 Nov 2007 16:51:26 +0000 Subject: [PATCH 1423/1514] fix two alignment issues found by the debian buildd gcc on sparc git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2022 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-esound-sink.c | 5 +++- src/pulsecore/iochannel.c | 42 +++++++++++++++++--------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 1c02cdfd6..b18d32581 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -506,6 +506,7 @@ int pa__init(pa_module*m) { pa_modargs *ma = NULL; char *t; const char *espeaker; + uint32_t key; pa_assert(m); @@ -584,7 +585,9 @@ int pa__init(pa_module*m) { pa_log("Failed to load cookie"); goto fail; } - *(int32_t*) ((uint8_t*) u->write_data + ESD_KEY_LEN) = ESD_ENDIAN_KEY; + + key = ESD_ENDIAN_KEY; + memcpy((uint8_t*) u->write_data + ESD_KEY_LEN, &key, sizeof(key)); /* Reserve space for the response */ u->read_data = pa_xmalloc(u->read_length = sizeof(int32_t)); diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c index 01f17ab32..63ab2ad71 100644 --- a/src/pulsecore/iochannel.c +++ b/src/pulsecore/iochannel.c @@ -267,9 +267,11 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l ssize_t r; struct msghdr mh; struct iovec iov; - uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))]; + union { + struct cmsghdr hdr; + uint8_t data[CMSG_SPACE(sizeof(struct ucred))]; + } cmsg; struct ucred *u; - struct cmsghdr *cmsg; pa_assert(io); pa_assert(data); @@ -280,13 +282,12 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l iov.iov_base = (void*) data; iov.iov_len = l; - memset(cmsg_data, 0, sizeof(cmsg_data)); - cmsg = (struct cmsghdr*) cmsg_data; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_CREDENTIALS; + memset(&cmsg, 0, sizeof(cmsg)); + cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(struct ucred)); + cmsg.hdr.cmsg_level = SOL_SOCKET; + cmsg.hdr.cmsg_type = SCM_CREDENTIALS; - u = (struct ucred*) CMSG_DATA(cmsg); + u = (struct ucred*) CMSG_DATA(&cmsg.hdr); u->pid = getpid(); if (ucred) { @@ -302,8 +303,8 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l mh.msg_namelen = 0; mh.msg_iov = &iov; mh.msg_iovlen = 1; - mh.msg_control = cmsg_data; - mh.msg_controllen = sizeof(cmsg_data); + mh.msg_control = &cmsg; + mh.msg_controllen = sizeof(cmsg); mh.msg_flags = 0; if ((r = sendmsg(io->ofd, &mh, MSG_NOSIGNAL)) >= 0) { @@ -318,7 +319,10 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr ssize_t r; struct msghdr mh; struct iovec iov; - uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))]; + union { + struct cmsghdr hdr; + uint8_t data[CMSG_SPACE(sizeof(struct ucred))]; + } cmsg; pa_assert(io); pa_assert(data); @@ -331,28 +335,28 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr iov.iov_base = data; iov.iov_len = l; - memset(cmsg_data, 0, sizeof(cmsg_data)); + memset(&cmsg, 0, sizeof(cmsg)); memset(&mh, 0, sizeof(mh)); mh.msg_name = NULL; mh.msg_namelen = 0; mh.msg_iov = &iov; mh.msg_iovlen = 1; - mh.msg_control = cmsg_data; - mh.msg_controllen = sizeof(cmsg_data); + mh.msg_control = &cmsg; + mh.msg_controllen = sizeof(cmsg); mh.msg_flags = 0; if ((r = recvmsg(io->ifd, &mh, 0)) >= 0) { - struct cmsghdr *cmsg; + struct cmsghdr *cmh; *creds_valid = 0; - for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) { + for (cmh = CMSG_FIRSTHDR(&mh); cmh; cmh = CMSG_NXTHDR(&mh, cmh)) { - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { + if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_CREDENTIALS) { struct ucred u; - pa_assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))); - memcpy(&u, CMSG_DATA(cmsg), sizeof(struct ucred)); + pa_assert(cmh->cmsg_len == CMSG_LEN(sizeof(struct ucred))); + memcpy(&u, CMSG_DATA(cmh), sizeof(struct ucred)); creds->gid = u.gid; creds->uid = u.uid; From bff4ca431b0146cb0cbb3935905f50714072a0d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 5 Nov 2007 15:10:13 +0000 Subject: [PATCH 1424/1514] add a man page for the pulseaudio binary. More will follow. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2023 fefdeb5f-60dc-0310-8127-8f9354f1896f --- Makefile.am | 2 +- configure.ac | 40 ++++- man/Makefile.am | 60 +++++++ man/pulseaudio.1.xml.in | 379 ++++++++++++++++++++++++++++++++++++++++ man/xmltoman.css | 30 ++++ man/xmltoman.dtd | 39 +++++ man/xmltoman.xsl | 129 ++++++++++++++ src/daemon/cmdline.c | 2 +- 8 files changed, 678 insertions(+), 3 deletions(-) create mode 100644 man/Makefile.am create mode 100644 man/pulseaudio.1.xml.in create mode 100644 man/xmltoman.css create mode 100644 man/xmltoman.dtd create mode 100644 man/xmltoman.xsl diff --git a/Makefile.am b/Makefile.am index 79608a224..a41dc6c85 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # USA. EXTRA_DIST = bootstrap.sh LICENSE GPL LGPL doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in README todo -SUBDIRS=src doxygen +SUBDIRS=src doxygen man MAINTAINERCLEANFILES = noinst_DATA = diff --git a/configure.ac b/configure.ac index 07db98234..f6e548bc6 100644 --- a/configure.ac +++ b/configure.ac @@ -28,7 +28,7 @@ m4_define(PA_MAJOR, [0]) m4_define(PA_MINOR, [9]) m4_define(PA_MICRO, [7]) -AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de]) +AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzchyfrnhqvb (at) 0pointer (dot) net]) AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign -Wall]) @@ -832,6 +832,43 @@ AC_SUBST(DBUS_LIBS) AC_SUBST(HAVE_DBUS) AM_CONDITIONAL([HAVE_DBUS], [test "x$HAVE_DBUS" = x1]) +### Build and Install man pages ### +AC_ARG_ENABLE(manpages, + AS_HELP_STRING([--disable-manpages],[Disable building and installation of man pages]), +[case "${enableval}" in + yes) manpages=yes ;; + no) manpages=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for --disable-manpages]) ;; +esac],[manpages=yes]) + +if test x$manpages = xyes ; then + # + # XMLTOMAN manpage generation + # + AC_ARG_ENABLE(xmltoman, + AS_HELP_STRING([--disable-xmltoman],[Enable rebuilding of man pages with xmltoman]), + [case "${enableval}" in + yes) xmltoman=yes ;; + no) xmltoman=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for --disable-xmltoman]) ;; + esac],[xmltoman=yes]) + + if test x$xmltoman = xyes ; then + AC_CHECK_PROG(have_xmltoman, xmltoman, yes, no) + fi + + if test x$have_xmltoman = xno -o x$xmltoman = xno; then + if ! test -e man/pulseaudio.1 ; then + AC_MSG_ERROR([*** xmltoman was not found or was disabled, it is required to build the manpages as they have not been pre-built, install xmltoman, pass --disable-manpages or dont pass --disable-xmltoman]) + exit 1 + fi + AC_MSG_WARN([*** Not rebuilding man pages as xmltoman is not found ***]) + xmltoman=no + fi +fi +AM_CONDITIONAL([USE_XMLTOMAN], [test "x$xmltoman" = xyes]) +AM_CONDITIONAL([BUILD_MANPAGES], [test "x$manpages" = xyes]) + #### PulseAudio system group & user ##### AC_ARG_WITH(system_user, AS_HELP_STRING([--with-system-user=],[User for running the PulseAudio daemon as a system-wide instance (pulse)])) @@ -914,6 +951,7 @@ AM_CONDITIONAL([FORCE_PREOPEN], [test "x$FORCE_PREOPEN" = "x1"]) AC_CONFIG_FILES([ Makefile src/Makefile +man/Makefile libpulse.pc libpulse-simple.pc libpulse-browse.pc diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 000000000..b701a2ea3 --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,60 @@ +# $Id$ +# +# This file is part of PulseAudio. +# +# PulseAudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# PulseAudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with PulseAudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +pulseconfdir=$(sysconfdir)/pulse + +if BUILD_MANPAGES + +man_MANS = \ + pulseaudio.1 + +noinst_DATA = \ + pulseaudio.1.xml + +CLEANFILES = \ + $(noinst_DATA) + +pulseaudio.1.xml: pulseaudio.1.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + +if USE_XMLTOMAN + +CLEANFILES += \ + $(man_MANS) + +pulseaudio.1: pulseaudio.1.xml Makefile + xmltoman $< > $@ + +xmllint: $(noinst_DATA) + for f in $(noinst_DATA) ; do \ + xmllint --noout --valid "$$f" || exit 1 ; \ + done + +endif + +endif + +EXTRA_DIST = \ + $(man_MANS) \ + pulseaudio.1.xml.in + xmltoman.css \ + xmltoman.xsl \ + xmltoman.dtd diff --git a/man/pulseaudio.1.xml.in b/man/pulseaudio.1.xml.in new file mode 100644 index 000000000..b30f44843 --- /dev/null +++ b/man/pulseaudio.1.xml.in @@ -0,0 +1,379 @@ + + + + + + + + + + + + pulseaudio [options] + pulseaudio --help + pulseaudio --dump-conf + pulseaudio --dump-modules + pulseaudio --dump-resample-methods + pulseaudio --cleanup-shm + pulseaudio --kill + pulseaudio --check + + + +

        PulseAudio is a networked low-latency sound server for Linux, POSIX and Windows systems.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + +

        ~/.pulse/daemon.conf, + @pulseconfdir@/daemon.conf: configuration settings + for the PulseAudio daemon. If the version in the user's home + directory does not exist the global configuration file is + loaded. See for + more information.

        + +

        ~/.pulse/default.pa, + @pulseconfdir@/default.pa: the default configuration + script to execute when the PulseAudio daemon is started. If the + version in the user's home directory does not exist the global + configuration script is loaded. See for more information.

        + +

        ~/.pulse/client.conf, + @pulseconfdir@/client.conf: configuration settings + for PulseAudio client applications. If the version in the user's + home directory does not exist the global configuration file is + loaded. See for + more information.

        + +
        + +
        + +

        SIGINT, SIGTERM: the PulseAudio daemon will shut + down (Same as --kill).

        + +

        SIGHUP: dump a long status report to STDOUT or + syslog, depending on the configuration.

        + +

        SIGUSR1: load module-cli, allowing runtime + reconfiguration via STDIN/STDOUT.

        + +

        SIGUSR2: load module-cli-protocol-unix, allowing + runtime reconfiguration via a AF_UNIX socket. See for more information.

        + +
        + +
        + +

        Group pulse-rt: if the PulseAudio binary is marked + SUID root, then membership of the calling user in this group + decides whether real-time and/or high-priority scheduling is + enabled. Please note that enabling real-time scheduling is a + security risk (see below).

        + +

        Group pulse-access: if PulseAudio is running as a system + daemon (see --system above) access is granted to + members of this group when they connect via AF_UNIX sockets. If + PulseAudio is running as a user daemon this group has no + meaning.

        + +

        User pulse, group pulse: if PulseAudio is running as a system + daemon (see --system above) and is started as root the + daemon will drop priviliges and become a normal user process using + this user and group. If PulseAudio is running as a user daemon + this user and group has no meaning.

        +
        + +
        + Blablub +
        + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , , , +

        +
        + +
        diff --git a/man/xmltoman.css b/man/xmltoman.css new file mode 100644 index 000000000..579a4fdcd --- /dev/null +++ b/man/xmltoman.css @@ -0,0 +1,30 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with PulseAudio; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +***/ + +body { color: black; background-color: white; } +a:link, a:visited { color: #900000; } +h1 { text-transform:uppercase; font-size: 18pt; } +p { margin-left:1cm; margin-right:1cm; } +.cmd { font-family:monospace; } +.file { font-family:monospace; } +.arg { text-transform:uppercase; font-family:monospace; font-style: italic; } +.opt { font-family:monospace; font-weight: bold; } +.manref { font-family:monospace; } +.option .optdesc { margin-left:2cm; } diff --git a/man/xmltoman.dtd b/man/xmltoman.dtd new file mode 100644 index 000000000..121e62c84 --- /dev/null +++ b/man/xmltoman.dtd @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/man/xmltoman.xsl b/man/xmltoman.xsl new file mode 100644 index 000000000..8d4ca2126 --- /dev/null +++ b/man/xmltoman.xsl @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + <xsl:value-of select="@name"/>(<xsl:value-of select="@section"/>) + + + +

        Name

        +

        + - +

        + + + +
        + + +

        + +

        +
        + + +

        + +

        +
        + + + + + + + + + + + + + + +
        + +
        +
        + + +

        Synopsis

        + +
        + + +

        Synopsis

        + +
        + + +

        Description

        + +
        + + +

        Options

        + +
        + + +

        + +
        + + +
        +
        + + + + + () + + + () + + + + + + + + +
        diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c index 0c8404490..cfd2c841d 100644 --- a/src/daemon/cmdline.c +++ b/src/daemon/cmdline.c @@ -144,7 +144,7 @@ void pa_cmdline_help(const char *argv0) { " --log-target={auto,syslog,stderr} Specify the log target\n" " -p, --dl-search-path=PATH Set the search path for dynamic shared\n" " objects (plugins)\n" - " --resample-method=[METHOD] Use the specified resampling method\n" + " --resample-method=METHOD Use the specified resampling method\n" " (See --dump-resample-methods for\n" " possible values)\n" " --use-pid-file[=BOOL] Create a PID file\n" From 7fdc1ee0838d3c55e29d8f44f2919a60f9415e56 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 5 Nov 2007 23:56:00 +0000 Subject: [PATCH 1425/1514] add a couple of more man pages git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2024 fefdeb5f-60dc-0310-8127-8f9354f1896f --- man/Makefile.am | 72 ++++++++++++++++- man/esdcompat.1.xml.in | 91 ++++++++++++++++++++++ man/pacat.1.xml.in | 160 ++++++++++++++++++++++++++++++++++++++ man/pacmd.1.xml.in | 52 +++++++++++++ man/pactl.1.xml.in | 145 ++++++++++++++++++++++++++++++++++ man/paplay.1.xml.in | 129 ++++++++++++++++++++++++++++++ man/pax11publish.1.xml.in | 153 ++++++++++++++++++++++++++++++++++++ man/pulseaudio.1.xml.in | 69 +++++++++++++++- 8 files changed, 867 insertions(+), 4 deletions(-) create mode 100644 man/esdcompat.1.xml.in create mode 100644 man/pacat.1.xml.in create mode 100644 man/pacmd.1.xml.in create mode 100644 man/pactl.1.xml.in create mode 100644 man/paplay.1.xml.in create mode 100644 man/pax11publish.1.xml.in diff --git a/man/Makefile.am b/man/Makefile.am index b701a2ea3..a3427aa78 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -22,10 +22,22 @@ pulseconfdir=$(sysconfdir)/pulse if BUILD_MANPAGES man_MANS = \ - pulseaudio.1 + pulseaudio.1 \ + esdcompat.1 \ + pax11publish.1 \ + paplay.1 \ + pacat.1 \ + pacmd.1 \ + pactl.1 noinst_DATA = \ - pulseaudio.1.xml + pulseaudio.1.xml \ + esdcompat.1.xml \ + pax11publish.1.xml \ + paplay.1.xml \ + pacat.1.xml \ + pacmd.1.xml \ + pactl.1.xml CLEANFILES = \ $(noinst_DATA) @@ -35,6 +47,36 @@ pulseaudio.1.xml: pulseaudio.1.xml.in Makefile -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ +esdcompat.1.xml: esdcompat.1.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + +pax11publish.1.xml: pax11publish.1.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + +paplay.1.xml: paplay.1.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + +pacat.1.xml: pacat.1.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + +pacmd.1.xml: pacmd.1.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + +pactl.1.xml: pactl.1.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + if USE_XMLTOMAN CLEANFILES += \ @@ -43,6 +85,24 @@ CLEANFILES += \ pulseaudio.1: pulseaudio.1.xml Makefile xmltoman $< > $@ +esdcompat.1: esdcompat.1.xml Makefile + xmltoman $< > $@ + +pax11publish.1: pax11publish.1.xml Makefile + xmltoman $< > $@ + +paplay.1: paplay.1.xml Makefile + xmltoman $< > $@ + +pacat.1: pacat.1.xml Makefile + xmltoman $< > $@ + +pacmd.1: pacmd.1.xml Makefile + xmltoman $< > $@ + +pactl.1: pactl.1.xml Makefile + xmltoman $< > $@ + xmllint: $(noinst_DATA) for f in $(noinst_DATA) ; do \ xmllint --noout --valid "$$f" || exit 1 ; \ @@ -54,7 +114,13 @@ endif EXTRA_DIST = \ $(man_MANS) \ - pulseaudio.1.xml.in + pulseaudio.1.xml.in \ + esdcompat.1.xml.in \ + pax11publish.1.xml.in \ + paplay.1.xml.in \ + pacat.1.xml.in \ + pacmd.1.xml.in \ + pactl.1.xml.in \ xmltoman.css \ xmltoman.xsl \ xmltoman.dtd diff --git a/man/esdcompat.1.xml.in b/man/esdcompat.1.xml.in new file mode 100644 index 000000000..864dc5db5 --- /dev/null +++ b/man/esdcompat.1.xml.in @@ -0,0 +1,91 @@ + + + + + + + + + + + + esdcompat [options] + esdcompat --help + esdcompat --version + + + +

        esdcompat is a compatiblity script that takes the + same arguments as the ESD sound daemon , but uses them to start a the PulseAudio sound server with the appropriate parameters. It is + required to make PulseAudio a drop-in replacement for esd, i.e. it + can be used to make + start up PulseAudio instead of esd.

        + +

        It is recommended to make esd a symbolic link to this script.

        +
        + + + + + + + + + + + + + + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , +

        +
        + +
        diff --git a/man/pacat.1.xml.in b/man/pacat.1.xml.in new file mode 100644 index 000000000..35c7651ba --- /dev/null +++ b/man/pacat.1.xml.in @@ -0,0 +1,160 @@ + + + + + + + + + + + + pacat [options] [FILE] + parec [options] [FILE] + paplay --help + paplay --version + + + +

        pacat is a simple tool for playing back or + capturing raw audio files on a PulseAudio sound server.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , +

        +
        + +
        diff --git a/man/pacmd.1.xml.in b/man/pacmd.1.xml.in new file mode 100644 index 000000000..b760ba0e5 --- /dev/null +++ b/man/pacmd.1.xml.in @@ -0,0 +1,52 @@ + + + + + + + + + + + + pacmd + + + +

        This tool can be used to introspect or reconfigure a running + PulseAudio sound server during runtime. It connects to the sound + server and offers a simple live shell that can be used to enter + the commands also understood in the default.pa + configuration scripts.

        + +

        This program takes no command line options.

        +
        + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , , +

        +
        + +
        diff --git a/man/pactl.1.xml.in b/man/pactl.1.xml.in new file mode 100644 index 000000000..0b7b9a78e --- /dev/null +++ b/man/pactl.1.xml.in @@ -0,0 +1,145 @@ + + + + + + + + + + + + pulseaudio [options] stat + pulseaudio [options] list + pulseaudio [options] exit + pulseaudio [options] upload-sample FILENAME [NAME] + pulseaudio [options] play-sample NAME [SINK] + pulseaudio [options] remove-sample NAME + pulseaudio [options] move-sink-input ID SINK + pulseaudio [options] move-source-input ID SOURCE + pulseaudio [options] load-module NAME [ARGUMENTS ...] + pulseaudio [options] unload-module ID + pulseaudio [options] suspend-sink [SINK] 1|0 + pulseaudio [options] suspend-source [SOURCE] 1|0 + pulseaudio --help + pulseaudio --version + + + +

        PulseAudio is a networked low-latency sound server for Linux, POSIX and Windows systems.

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , +

        +
        + +
        diff --git a/man/paplay.1.xml.in b/man/paplay.1.xml.in new file mode 100644 index 000000000..bab45dc38 --- /dev/null +++ b/man/paplay.1.xml.in @@ -0,0 +1,129 @@ + + + + + + + + + + + + paplay [options] FILE + paplay --help + paplay --version + + + +

        paplay is a simple tool for playing back audio + files on a PulseAudio sound server. It understands all audio file + formats supported by libsndfile.

        +
        + + + + + + + + + + + + + + + + + + + + + + + +
        + +

        Due to a limitation in libsndfile + paplay currently does not always set the correct channel + mapping for playback of multichannel (i.e. surround) audio files, even if the channel mapping information is + available in the audio file.

        + +
        + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , +

        +
        + +
        diff --git a/man/pax11publish.1.xml.in b/man/pax11publish.1.xml.in new file mode 100644 index 000000000..1e3a1f01f --- /dev/null +++ b/man/pax11publish.1.xml.in @@ -0,0 +1,153 @@ + + + + + + + + + + + + pax11publish -h + pax11publish [options] [-d] + pax11publish [options] -e + pax11publish [options] -i + pax11publish [options] -r + + + +

        The pax11publish utility can be used to dump or + manipulate the PulseAudio server credentials that can be stored as + properties on the X11 root window.

        + +

        Please note that the loadable module + module-x11-publish exports the same information + directly from the PulseAudio sound server, and should in most + cases be used in preference over this tool.

        + +

        Use the following command to dump the raw + PulseAudio-specific data that is stored in your X11 root + window:

        + +

        xprop -root | grep ^PULSE_

        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , +

        +
        + +
        diff --git a/man/pulseaudio.1.xml.in b/man/pulseaudio.1.xml.in index b30f44843..1f53a60b6 100644 --- a/man/pulseaudio.1.xml.in +++ b/man/pulseaudio.1.xml.in @@ -28,6 +28,7 @@ USA. pulseaudio [options] pulseaudio --help + pulseaudio --version pulseaudio --dump-conf pulseaudio --dump-modules pulseaudio --dump-resample-methods @@ -363,7 +364,73 @@ USA.
        - Blablub +

        To minimize the risk of drop-outs during playback it is + recommended to run PulseAudio with real-time scheduling if the + underlying platform supports it. This decouples the scheduling + latency of the PulseAudio daemon from the system load and is thus + the best way to make sure that PulseAudio always gets CPU time + when it needs it to refill the hardware playback + buffers. Unfortunately this is a security risk on most systems, + since PulseAudio runs as user process, and giving realtime + scheduling priviliges to a user process always comes with the risk + that the user misuses it to lock up the system -- which is + possible since making a process real-time effectively disables + preemption.

        + +

        To minimize the risk PulseAudio by default does not enable + real-time scheduling. It is however recommended to enable it + on trusted systems. To do that start PulseAudio with + --realtime (see above) or enabled the appropriate option in + daemon.conf. Since acquiring realtime scheduling is a + priviliged operation on most systems, some special changes to the + system configuration need to be made to allow them to the calling + user. Two options are available:

        + +

        On newer Linux systems the system resource limit RLIMIT_RTPRIO + (see for more information) + can be used to allow specific users to acquire real-time + scheduling. This can be configured in + /etc/security/limits.conf, a resource limit of 9 is recommended.

        + +

        Alternatively, the SUID root bit can be set for the PulseAudio + binary. Then, the daemon will drop root priviliges immediately on + startup, however retain the CAP_NICE capability (on systems that + support it), but only if the calling user is a member of the + pulse-rt group (see above). For all other users all + capababilities are dropped immediately. The advantage of this + solution is that the real-time priviliges are only granted to the + PulseAudio daemon -- not to all the user's processes.

        + +

        Alternatively, if the risk of locking up the machine is + considered too big to enable real-time scheduling, high-priority + scheduling can be enabled instead (i.e. negative nice level). This + can be enabled by passing --high-priority (see above) + when starting PulseAudio and may also be enabled with the + approriate option in daemon.conf. Negative nice + levels can only be enabled when the appropriate resource limit + RLIMIT_NICE is set (see for + more information), possibly configured in + /etc/security/limits.conf. A resource limit of 31 + (corresponding with nice level -11) is recommended.

        +
        + +
        + +

        The PulseAudio client libraries check for the existance of the + following environment variables and change their local configuration accordingly:

        + +

        $PULSE_SERVER: the server string specifying the server to connect to when a client asks for a sound server connection and doesn't explicitly ask for a specific server.

        + +

        $PULSE_SINK: the symbolic name of the sink to connect to when a client creates a playback stream and doesn't explicitly ask for a specific sink.

        + +

        $PULSE_SOURCE: the symbolic name of the source to connect to when a client creates a record stream and doesn't explicitly ask for a specific source.

        + +

        $PULSE_BINARY: path of PulseAudio executable to run when server auto-spawning is used.

        + +

        $PULSE_CLIENTCONFIG: path of file that shall be read instead of client.conf (see above) for client configuration.

        + +

        These environment settings take precedence -- if set -- over the configuration settings from client.conf (see above).

        +
        From 0eb011bda093438044338946d575ff7845e6aa3c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 5 Nov 2007 23:56:30 +0000 Subject: [PATCH 1426/1514] minor cleanups of --help texts git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2025 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 2 +- src/utils/paplay.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/pactl.c b/src/utils/pactl.c index c963987ff..eddbebc94 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -662,9 +662,9 @@ static void help(const char *argv0) { "%s [options] exit\n" "%s [options] upload-sample FILENAME [NAME]\n" "%s [options] play-sample NAME [SINK]\n" + "%s [options] remove-sample NAME\n" "%s [options] move-sink-input ID SINK\n" "%s [options] move-source-output ID SOURCE\n" - "%s [options] remove-sample NAME\n" "%s [options] load-module NAME [ARGS ...]\n" "%s [options] unload-module ID\n" "%s [options] suspend-sink [SINK] 1|0\n" diff --git a/src/utils/paplay.c b/src/utils/paplay.c index e7076d2d3..fddbb18c5 100644 --- a/src/utils/paplay.c +++ b/src/utils/paplay.c @@ -203,9 +203,9 @@ static void help(const char *argv0) { printf("%s [options] [FILE]\n\n" " -h, --help Show this help\n" " --version Show version\n\n" - " -v, --verbose Enable verbose operations\n\n" + " -v, --verbose Enable verbose operation\n\n" " -s, --server=SERVER The name of the server to connect to\n" - " -d, --device=DEVICE The name of the sink/source to connect to\n" + " -d, --device=DEVICE The name of the sink to connect to\n" " -n, --client-name=NAME How to call this client on the server\n" " --stream-name=NAME How to call this stream on the server\n" " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" From 5dbab0b23aa373f5eb61faf2b0cbae24f05570fa Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 6 Nov 2007 00:21:20 +0000 Subject: [PATCH 1427/1514] complete pactl man page git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2026 fefdeb5f-60dc-0310-8127-8f9354f1896f --- man/pactl.1.xml.in | 76 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/man/pactl.1.xml.in b/man/pactl.1.xml.in index 0b7b9a78e..d30d5f7c3 100644 --- a/man/pactl.1.xml.in +++ b/man/pactl.1.xml.in @@ -26,24 +26,26 @@ USA. - pulseaudio [options] stat - pulseaudio [options] list - pulseaudio [options] exit - pulseaudio [options] upload-sample FILENAME [NAME] - pulseaudio [options] play-sample NAME [SINK] - pulseaudio [options] remove-sample NAME - pulseaudio [options] move-sink-input ID SINK - pulseaudio [options] move-source-input ID SOURCE - pulseaudio [options] load-module NAME [ARGUMENTS ...] - pulseaudio [options] unload-module ID - pulseaudio [options] suspend-sink [SINK] 1|0 - pulseaudio [options] suspend-source [SOURCE] 1|0 - pulseaudio --help - pulseaudio --version + pactl [options] stat + pactl [options] list + pactl [options] exit + pactl [options] upload-sample FILENAME [NAME] + pactl [options] play-sample NAME [SINK] + pactl [options] remove-sample NAME + pactl [options] move-sink-input ID SINK + pactl [options] move-source-input ID SOURCE + pactl [options] load-module NAME [ARGUMENTS ...] + pactl [options] unload-module ID + pactl [options] suspend-sink [SINK] 1|0 + pactl [options] suspend-source [SOURCE] 1|0 + pactl --help + pactl --version -

        PulseAudio is a networked low-latency sound server for Linux, POSIX and Windows systems.

        +

        pactl can be used to issue control commands to the PulseAudio sound server.

        + +

        pactl only exposes a subset of the available operations. For the full set use the .

        @@ -130,6 +132,50 @@ USA.

        Move the specified recording stream (identified by its numerical index) to the specified source (identified by its symbolic name or numerical index).

        + + + + + + + + + +
        From 1821f1f4994dfd0618ac290da54da683e7604f40 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 7 Nov 2007 13:50:47 +0000 Subject: [PATCH 1428/1514] add man pages for padsp, pabrowse, pasuspender git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2027 fefdeb5f-60dc-0310-8127-8f9354f1896f --- man/Makefile.am | 37 ++++++++++++- man/pabrowse.1.xml.in | 49 +++++++++++++++++ man/padsp.1.xml.in | 112 +++++++++++++++++++++++++++++++++++++++ man/pasuspender.1.xml.in | 75 ++++++++++++++++++++++++++ 4 files changed, 271 insertions(+), 2 deletions(-) create mode 100644 man/pabrowse.1.xml.in create mode 100644 man/padsp.1.xml.in create mode 100644 man/pasuspender.1.xml.in diff --git a/man/Makefile.am b/man/Makefile.am index a3427aa78..e5ce5530c 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -28,7 +28,10 @@ man_MANS = \ paplay.1 \ pacat.1 \ pacmd.1 \ - pactl.1 + pactl.1 \ + pasuspender.1 \ + padsp.1 \ + pabrowse.1 noinst_DATA = \ pulseaudio.1.xml \ @@ -37,7 +40,10 @@ noinst_DATA = \ paplay.1.xml \ pacat.1.xml \ pacmd.1.xml \ - pactl.1.xml + pactl.1.xml \ + pasuspender.1.xml \ + padsp.1.xml \ + pabrowse.1.xml CLEANFILES = \ $(noinst_DATA) @@ -77,6 +83,21 @@ pactl.1.xml: pactl.1.xml.in Makefile -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ +pasuspender.1.xml: pasuspender.1.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + +padsp.1.xml: padsp.1.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + +pabrowse.1.xml: pabrowse.1.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + if USE_XMLTOMAN CLEANFILES += \ @@ -103,6 +124,15 @@ pacmd.1: pacmd.1.xml Makefile pactl.1: pactl.1.xml Makefile xmltoman $< > $@ +pasuspender.1: pasuspender.1.xml Makefile + xmltoman $< > $@ + +padsp.1: padsp.1.xml Makefile + xmltoman $< > $@ + +pabrowse.1: pabrowse.1.xml Makefile + xmltoman $< > $@ + xmllint: $(noinst_DATA) for f in $(noinst_DATA) ; do \ xmllint --noout --valid "$$f" || exit 1 ; \ @@ -121,6 +151,9 @@ EXTRA_DIST = \ pacat.1.xml.in \ pacmd.1.xml.in \ pactl.1.xml.in \ + pasuspender.1.xml.in \ + padsp.1.xml.in \ + pabrowse.1.xml.in \ xmltoman.css \ xmltoman.xsl \ xmltoman.dtd diff --git a/man/pabrowse.1.xml.in b/man/pabrowse.1.xml.in new file mode 100644 index 000000000..b539fb214 --- /dev/null +++ b/man/pabrowse.1.xml.in @@ -0,0 +1,49 @@ + + + + + + + + + + + + pabrowse + + + +

        pabrowse lists all PulseAudio sound servers on the + local network that are being announced with Zeroconf/Avahi.

        + +

        This program takes no command line arguments.

        +
        + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , +

        +
        + +
        diff --git a/man/padsp.1.xml.in b/man/padsp.1.xml.in new file mode 100644 index 000000000..610a96020 --- /dev/null +++ b/man/padsp.1.xml.in @@ -0,0 +1,112 @@ + + + + + + + + + + + + padsp [options] PROGRAM [ARGUMENTS ...] + padsp -h + + + +

        padsp starts the specified program and + redirects its access to OSS compatible audio devices + (/dev/dsp and auxiliary devices) to a PulseAudio + sound server.

        + +

        padsp uses the $LD_PRELOAD environment variable + that is interpreted by and thus + does not work for SUID binaries and statically built + executables.

        + +

        Equivalent to using padsp is starting an + application with $LD_PRELOAD set to + libpulsedsp.so

        +
        + + + + + + + + + + + + + + + + + + + + + + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , , +

        +
        + +
        diff --git a/man/pasuspender.1.xml.in b/man/pasuspender.1.xml.in new file mode 100644 index 000000000..8a73343a7 --- /dev/null +++ b/man/pasuspender.1.xml.in @@ -0,0 +1,75 @@ + + + + + + + + + + + + pasuspender [options] -- PROGRAM [ARGUMENTS ...] + pasuspender --help + pasuspender --version + + + +

        pasuspender is a tool that can be used to tell a + local PulseAudio sound server to temporarily suspend access to the + audio devices, to allow other + applications access them directly. pasuspender will + suspend access to the audio devices, fork a child process, and + when the child process terminates, resume access again.

        +
        + + + + + + + + + + + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , , , +

        +
        + +
        From 1ef4bafc9a6ea0661e5b1a26948f8ab5b5b8afa2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 7 Nov 2007 13:52:07 +0000 Subject: [PATCH 1429/1514] warn if the sound server is not local git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2028 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pasuspender.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c index ae59086b1..05d96a68e 100644 --- a/src/utils/pasuspender.c +++ b/src/utils/pasuspender.c @@ -149,8 +149,10 @@ static void context_state_callback(pa_context *c, void *userdata) { if (pa_context_is_local(c)) { pa_operation_unref(pa_context_suspend_sink_by_index(c, PA_INVALID_INDEX, 1, suspend_complete, NULL)); pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, 1, suspend_complete, NULL)); - } else + } else { + fprintf(stderr, "WARNING: Sound server is not local, not suspending.\n"); start_child(); + } break; From 445991287d541d15a9a446980e1485263ae55e10 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 8 Nov 2007 22:30:33 +0000 Subject: [PATCH 1430/1514] add remaing man pages git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2029 fefdeb5f-60dc-0310-8127-8f9354f1896f --- man/Makefile.am | 37 +++- man/default.pa.5.xml.in | 58 ++++++ man/pacat.1.xml.in | 32 +-- man/pulse-client.conf.5.xml.in | 115 +++++++++++ man/pulse-daemon.conf.5.xml.in | 366 +++++++++++++++++++++++++++++++++ 5 files changed, 590 insertions(+), 18 deletions(-) create mode 100644 man/default.pa.5.xml.in create mode 100644 man/pulse-client.conf.5.xml.in create mode 100644 man/pulse-daemon.conf.5.xml.in diff --git a/man/Makefile.am b/man/Makefile.am index e5ce5530c..0a355f952 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -31,7 +31,10 @@ man_MANS = \ pactl.1 \ pasuspender.1 \ padsp.1 \ - pabrowse.1 + pabrowse.1 \ + pulse-daemon.conf.5 \ + pulse-client.conf.5 \ + default.pa.5 noinst_DATA = \ pulseaudio.1.xml \ @@ -43,7 +46,10 @@ noinst_DATA = \ pactl.1.xml \ pasuspender.1.xml \ padsp.1.xml \ - pabrowse.1.xml + pabrowse.1.xml \ + pulse-daemon.conf.5.xml \ + pulse-client.conf.5.xml \ + default.pa.5.xml CLEANFILES = \ $(noinst_DATA) @@ -98,6 +104,21 @@ pabrowse.1.xml: pabrowse.1.xml.in Makefile -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ +pulse-daemon.conf.5.xml: pulse-daemon.conf.5.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + +pulse-client.conf.5.xml: pulse-client.conf.5.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + +default.pa.5.xml: default.pa.5.xml.in Makefile + sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \ + -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \ + -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@ + if USE_XMLTOMAN CLEANFILES += \ @@ -133,6 +154,15 @@ padsp.1: padsp.1.xml Makefile pabrowse.1: pabrowse.1.xml Makefile xmltoman $< > $@ +pulse-daemon.conf.5: pulse-daemon.conf.5.xml Makefile + xmltoman $< > $@ + +pulse-client.conf.5: pulse-client.conf.5.xml Makefile + xmltoman $< > $@ + +default.pa.5: default.pa.5.xml Makefile + xmltoman $< > $@ + xmllint: $(noinst_DATA) for f in $(noinst_DATA) ; do \ xmllint --noout --valid "$$f" || exit 1 ; \ @@ -154,6 +184,9 @@ EXTRA_DIST = \ pasuspender.1.xml.in \ padsp.1.xml.in \ pabrowse.1.xml.in \ + pulse-daemon.conf.5.xml.in \ + pulse-client.conf.5.xml.in \ + default.pa.5.xml.in \ xmltoman.css \ xmltoman.xsl \ xmltoman.dtd diff --git a/man/default.pa.5.xml.in b/man/default.pa.5.xml.in new file mode 100644 index 000000000..0f826db6f --- /dev/null +++ b/man/default.pa.5.xml.in @@ -0,0 +1,58 @@ + + + + + + + + + + + +

        ~/.pulse/default.pa

        + +

        @pulseconfdir@/default.pa

        +
        + + +

        The PulseAudio sound server interprets the file + ~/.pulse/default.pa on startup, and when that file + doesn't exist @pulseconfdir@/default.pa. It + should contain directives in the PulseAudio CLI languages, as + documented on .

        + +

        The same commands can also be entered during runtime in the tool, allowing flexible runtime reconfiguration.

        +
        + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; + PulseAudio is available from

        +
        + +
        +

        + , , +

        +
        + +
        diff --git a/man/pacat.1.xml.in b/man/pacat.1.xml.in index 35c7651ba..e02ad667b 100644 --- a/man/pacat.1.xml.in +++ b/man/pacat.1.xml.in @@ -109,11 +109,11 @@ USA.

        --format=FORMAT

        Capture or play back audio with the specified sample - format. Specify one of u8, s16le, - s16be, float32le, float32be, - ulaw, alaw. Depending on the endianess of - the CPU the formats s16ne, s16re, - float32ne, float32re (for native, + format. Specify one of u8, s16le, + s16be, float32le, float32be, + ulaw, alaw. Depending on the endianess of + the CPU the formats s16ne, s16re, + float32ne, float32re (for native, resp. reverse endian) are available as aliases. Defaults to s16ne.

        @@ -132,17 +132,17 @@ USA.

        Explicitly choose a channel map when playing back this stream. The argument should be a comma separated list of - channel names: front-left, front-right, - mono, front-center, rear-left, - rear-right, rear-center, lfe, - front-left-of-center, - front-right-of-center, side-left, - side-right, top-center, - top-front-center, top-front-left, - top-front-right, top-rear-left, - top-rear-right, top-rear-center, or any of - the 32 auxiliary channel names aux0 to - aux31.

        + channel names: front-left, front-right, + mono, front-center, rear-left, + rear-right, rear-center, lfe, + front-left-of-center, + front-right-of-center, side-left, + side-right, top-center, + top-front-center, top-front-left, + top-front-right, top-rear-left, + top-rear-right, top-rear-center, or any of + the 32 auxiliary channel names aux0 to + aux31.

        diff --git a/man/pulse-client.conf.5.xml.in b/man/pulse-client.conf.5.xml.in new file mode 100644 index 000000000..dbf8dc0b8 --- /dev/null +++ b/man/pulse-client.conf.5.xml.in @@ -0,0 +1,115 @@ + + + + + + + + + + + +

        ~/.pulse/client.conf

        + +

        @pulseconfdir@/client.conf

        +
        + + +

        The PulseAudio client library reads configuration directives from + a file ~/.pulse/client.conf on startup, and when that + file doesn't exist from + @pulseconfdir@/client.conf.

        + +

        The configuration file is a simple collection of variable + declarations. If the configuration file parser encounters either ; + or # for it ignores the rest of the line until its end.

        + +

        For the settings that take a boolean argument, the values + true, yes, on and 1 + are equivalent, resp. false, no, + off, 0.

        + +
        + +
        + + + + + + + + + + + + + + + + + +
        + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; + PulseAudio is available from

        +
        + +
        +

        + , +

        +
        + +
        diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in new file mode 100644 index 000000000..88bf8f589 --- /dev/null +++ b/man/pulse-daemon.conf.5.xml.in @@ -0,0 +1,366 @@ + + + + + + + + + + + +

        ~/.pulse/daemon.conf

        + +

        @pulseconfdir@/daemon.conf

        +
        + + +

        The PulseAudio sound server reads configuration directives from + a file ~/.pulse/daemon.conf on startup, and when that + file doesn't exist from + @pulseconfdir@/daemon.conf. Please note that the + server also reads a configuration script on startup + default.pa which also contains runtime configuration + directives.

        + +

        The configuration file is a simple collection of variable + declarations. If the configuration file parser encounters either ; + or # for it ignores the rest of the line until its end.

        + +

        For the settings that take a boolean argument, the values + true, yes, on and 1 + are equivalent, resp. false, no, + off, 0.

        + +
        + +
        + + + + + + + + + + + + + + + + + + + +
        + +
        + + + + + + + + + +
        + +
        + + + + + + + +
        + +
        + + + + + +
        + +
        + + + + + +
        + +
        + +

        See for + more information. Set to -1 if PulseAudio shall not touch the resource + limit. Not all resource limits are available on all operating + systems.

        + + + + + + + + + + + + +
        + +
        + +

        Most drivers try to open the audio device with these settings + and then fall back to lower settings. The default settings are CD + quality: 16bit native endian, 2 channels, 44100 Hz sampling.

        + + + + + + + +
        + +
        + +

        Some hardware drivers require the hardware playback buffer to + be subdivided into several fragments. It is possible to change + these buffer metrics for machines with high scheduling + latencies. Not all possible values that may be configured here are + available in all hardware. The driver will to find the nearest + setting supported.

        + + + + +
        + +
        +

        The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from

        +
        + +
        +

        + , , , +

        +
        + +
        From a2121d5e6f33b31481a014012b7eef43b8e500db Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 8 Nov 2007 22:31:30 +0000 Subject: [PATCH 1431/1514] strip most comments from the default configuration files, since the man page is now more elaborate and we don't want to maintain those docs redundantly at two places git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2030 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon.conf.in | 89 ++++----------------------------------- src/pulse/client.conf.in | 29 ++++--------- 2 files changed, 18 insertions(+), 100 deletions(-) diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 54acd8ead..f15d93e89 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -17,104 +17,38 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -## Configuration file for the pulseaudio daemon. Default values are -## commented out. Use either ; or # for commenting +## Configuration file for the PulseAudio daemon. See pulse-daemon.conf(5) for +## more information. Default values a commented out. Use either ; or # for +## commenting. -## Daemonize after startup ; daemonize = no - -## Quit if startup fails ; fail = yes +; disallow-module-loading = no +; use-pid-file = yes +; system-instance = no +; disable-shm = no -## Renice the daemon to level -15. This a good idea if you experience -## drop-outs in the playback. However, this is a certain security -## issue, since it works when called SUID root only. root is dropped -## immediately after gaining the nice level on startup, thus it is -## presumably safe. ; high-priority = yes - -## Try to acquire SCHED_FIFO scheduling for the IO threads. The same -## security concerns as mentioned above apply. However, if PA enters -## an endless loop, realtime scheduling causes a system lockup. Thus, -## realtime scheduling should only be enabled on trusted machines for -## now. Please not that only the IO threads of PulseAudio are made -## real-time. The controlling thread is left a normally scheduled -## thread. Thus the enabling the high-priority option is orthogonal. -; realtime-scheduling = no - -## The realtime priority to acquire, if realtime-scheduling is -## enabled. (Note: JACK uses 10 by default, 9 for clients -- some -## PulseAudio threads might choose a priority a little lower or higher -## than this value.) -; realtime-priority = 5 - -## The nice level to acquire for the daemon, if high-priority is -## enabled. (Note: on some distributions X11 uses -10 by default.) ; nice-level = -11 -## Disallow module loading after startup -; disallow-module-loading = no +; realtime-scheduling = no +; realtime-priority = 5 -## Terminate the daemon after the last client quit and this time -## passed. Use a negative value to disable this feature. ; exit-idle-time = -1 - -## Unload autoloaded modules after being idle for this time ; module-idle-time = 20 - -## Unload autoloaded sample cache entries after being idle for this time ; scache-idle-time = 20 -## The path were to look for dynamic shared objects (DSOs aka -## plugins). You may specify more than one path seperated by -## colons. ; dl-search-path = @PA_DLSEARCHPATH@ -## The default script file to load. Specify an empty string for not -## loading a default script file. The ; default-script-file = @PA_DEFAULT_CONFIG_FILE@ -## The default log target. Use either "stderr", "syslog" or -## "auto". The latter is equivalent to "sylog" in case daemonize is -## true, otherwise to "stderr". ; log-target = auto - -# Log level, one of debug, info, notice, warning, error. Log messages -# with a lower log level than specified here are not logged, ; log-level = notice -## The resampling algorithm to use. Use one of src-sinc-best-quality, -## src-sinc-medium-quality, src-sinc-fastest, src-zero-order-hold, -## src-linear, trivial, speex-float-N, speex-fixed-N, ffmpeg. See the -## documentation of libsamplerate for an explanation for the different -## src- methods. The method 'trivial' is the most basic algorithm -## implemented. If you're tight on CPU consider using this. On the -## other hand it has the worst quality of them all. The speex -## resamplers take an integer quality setting in the range 0..9 -## (bad...good). They exist in two flavours: fixed and float. The -## former uses fixed point numbers, the latter relies on floating -## point numbers. On most desktop CPUs the float point resmapler is a -## lot faster, and it also offers slightly better quality. ; resample-method = speex-float-3 -## Create a PID file in /tmp/pulseaudio-$USER/pid. Of this is enabled -## you may use commands like "pulseaudio --kill" or "pulseaudio -## --check". If you are planning to start more than one pulseaudio -## process per user, you better disable this option since it -## effectively disables multiple instances. -; use-pid-file = yes - -## Do not install the CPU load limit, even on platforms where it is -## supported. This option is useful when debugging/profiling -## PulseAudio to disable disturbing SIGXCPU signals. ; no-cpu-limit = no -## Run the daemon as system-wide instance, requires root priviliges -; system-instance = no - -## Resource limits, see getrlimit(2) for more information. Set to -1 -## if PA shouldn't touch the resource limit. Not all resource limits -## are available on all operating systems. ; rlimit-as = -1 ; rlimit-core = -1 ; rlimit-data = -1 @@ -126,14 +60,9 @@ ; rlimit-nice = 31 ; rlimit-rtprio = 9 -## Disable shared memory data transfer -; disable-shm = no - -## Default sample format ; default-sample-format = s16le ; default-sample-rate = 44100 ; default-sample-channels = 2 -## Default fragment settings, for device drivers that need this ; default-fragments = 4 ; default-fragment-size-msec = 25 diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in index 3cfd97604..2bc8a7c8c 100644 --- a/src/pulse/client.conf.in +++ b/src/pulse/client.conf.in @@ -17,29 +17,18 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -## Configuration file for pulseaudio clients. Default values are -## commented out. Use either ; or # for commenting +## Configuration file for PulseAudio clients. See pulse-client.conf(5) for +## more information. Default values a commented out. Use either ; or # for +## commenting. -## Path to the pulseaudio daemon to run when autospawning. -; daemon-binary = @PA_BINARY@ - -## Extra arguments to pass to the pulseaudio daemon -; extra-arguments = --log-target=syslog --exit-idle-time=5 - -## The default sink to connect to -; default-sink = - -## The default source to connect to +; default-sink = ; default-source = - -## The default sever to connect to ; default-server = -## Autospawn daemons? -; autospawn = 0 +; autospawn = no +; daemon-binary = @PA_BINARY@ +; extra-arguments = --log-target=syslog --exit-idle-time=5 -### Cookie file -; cookie-file = +; cookie-file = -### Disable shared memory data transfer -; disable-shm = 0 +; disable-shm = no From 14b974a6d870432554afc20710ad9f93f4833e88 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 8 Nov 2007 22:42:33 +0000 Subject: [PATCH 1432/1514] parse the pasuspend argument like any other boolean in PulseAudio git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2031 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- src/utils/pactl.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index dbb9adcd3..91e22dfe5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -185,7 +185,7 @@ paplay_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS) paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) paplay_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -pactl_SOURCES = utils/pactl.c +pactl_SOURCES = utils/pactl.c pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS) pactl_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS) pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS) pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) diff --git a/src/utils/pactl.c b/src/utils/pactl.c index eddbebc94..5425b131b 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -850,7 +850,7 @@ int main(int argc, char *argv[]) { goto quit; } - suspend = !!atoi(argv[argc-1]); + suspend = pa_parse_boolean(argv[argc-1]); if (argc > optind+2) sink_name = pa_xstrdup(argv[optind+1]); @@ -863,7 +863,7 @@ int main(int argc, char *argv[]) { goto quit; } - suspend = !!atoi(argv[argc-1]); + suspend = pa_parse_boolean(argv[argc-1]); if (argc > optind+2) source_name = pa_xstrdup(argv[optind+1]); From c8cdb06135e2e316a724098e5c0af7aa9e81091e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 01:28:56 +0000 Subject: [PATCH 1433/1514] add support for likely()/unlikely() type macros git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2032 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/gccmacro.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h index e9f0d0939..ecdc05784 100644 --- a/src/pulsecore/gccmacro.h +++ b/src/pulsecore/gccmacro.h @@ -60,7 +60,7 @@ #endif #ifndef PA_GCC_PURE -#ifdef __GNUCC__ +#ifdef __GNUC__ #define PA_GCC_PURE __attribute__ ((pure)) #else /** This function's return value depends only the arguments list and global state **/ @@ -69,7 +69,7 @@ #endif #ifndef PA_GCC_CONST -#ifdef __GNUCC__ +#ifdef __GNUC__ #define PA_GCC_CONST __attribute__ ((const)) #else /** This function's return value depends only the arguments list (stricter version of PA_GCC_PURE) **/ @@ -77,4 +77,14 @@ #endif #endif +#ifndef PA_LIKELY +#ifdef __GNUC__ +#define PA_LIKELY(x) __builtin_expect((x),1) +#define PA_UNLIKELY(x) __builtin_expect((x),0) +#else +#define PA_LIKELY(x) (x) +#define PA_UNLIKELY(x) (x) +#endif +#endif + #endif From cb66762d6dea8ac8871bb23efbf8c9b77f8d08fd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 01:29:50 +0000 Subject: [PATCH 1434/1514] add PA_CLAMP_LIKELY and PA_CLAMP_UNLIKELY macros git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2033 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/macro.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h index c6bba4372..548e4ed90 100644 --- a/src/pulsecore/macro.h +++ b/src/pulsecore/macro.h @@ -31,6 +31,7 @@ #include #include +#include #ifndef PACKAGE #error "Please include config.h before including this file!" @@ -73,9 +74,12 @@ static inline size_t pa_page_align(size_t l) { #endif #ifndef CLAMP -#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) #endif +#define PA_CLAMP_LIKELY(x, low, high) (PA_LIKELY((x) > (high)) ? (high) : PA_LIKELY(((x) < (low)) ? (low) : (x))) +#define PA_CLAMP_UNLIKELY(x, low, high) (PA_UNLIKELY((x) > (high)) ? (high) : PA_UNLIKELY(((x) < (low)) ? (low) : (x))) + /* This type is not intended to be used in exported APIs! Use classic "int" there! */ #ifdef HAVE_STD_BOOL typedef _Bool pa_bool_t; From 42ef0518eb05ca18fccae4d6fb79f2db0d7730d1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 01:30:25 +0000 Subject: [PATCH 1435/1514] add a few missing macro definitions git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2034 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/endianmacros.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h index 8f7cfade3..05d3262f9 100644 --- a/src/pulsecore/endianmacros.h +++ b/src/pulsecore/endianmacros.h @@ -63,9 +63,15 @@ #define PA_UINT16_FROM_LE(x) PA_UINT16_SWAP(x) #define PA_UINT16_FROM_BE(x) ((uint16_t)(x)) + #define PA_UINT16_TO_LE(x) PA_UINT16_SWAP(x) + #define PA_UINT16_TO_BE(x) ((uint16_t)(x)) + #define PA_INT32_FROM_LE(x) PA_INT32_SWAP(x) #define PA_INT32_FROM_BE(x) ((int32_t)(x)) + #define PA_INT32_TO_LE(x) PA_INT32_SWAP(x) + #define PA_INT32_TO_BE(x) ((int32_t)(x)) + #define PA_UINT32_FROM_LE(x) PA_UINT32_SWAP(x) #define PA_UINT32_FROM_BE(x) ((uint32_t)(x)) @@ -81,9 +87,15 @@ #define PA_UINT16_FROM_LE(x) ((uint16_t)(x)) #define PA_UINT16_FROM_BE(x) PA_UINT16_SWAP(x) + #define PA_UINT16_TO_LE(x) ((uint16_t)(x)) + #define PA_UINT16_TO_BE(x) PA_UINT16_SWAP(x) + #define PA_INT32_FROM_LE(x) ((int32_t)(x)) #define PA_INT32_FROM_BE(x) PA_INT32_SWAP(x) + #define PA_INT32_TO_LE(x) ((int32_t)(x)) + #define PA_INT32_TO_BE(x) PA_INT32_SWAP(x) + #define PA_UINT32_FROM_LE(x) ((uint32_t)(x)) #define PA_UINT32_FROM_BE(x) PA_UINT32_SWAP(x) From ecf349dc6cdb6737f3854c5c4678d336dcf10938 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 01:30:46 +0000 Subject: [PATCH 1436/1514] add missing #include git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2035 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pactl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 5425b131b..4519b13b9 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -38,6 +38,7 @@ #include #include +#include #if PA_API_VERSION < 10 #error Invalid PulseAudio API version From 3c17c7d44284a739ec1453a7470333c73f072eeb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 02:12:09 +0000 Subject: [PATCH 1437/1514] fix CLAMP_LIKELY/UNLIKELY definition git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2036 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/gccmacro.h | 4 ++-- src/pulsecore/macro.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h index ecdc05784..f16466533 100644 --- a/src/pulsecore/gccmacro.h +++ b/src/pulsecore/gccmacro.h @@ -79,8 +79,8 @@ #ifndef PA_LIKELY #ifdef __GNUC__ -#define PA_LIKELY(x) __builtin_expect((x),1) -#define PA_UNLIKELY(x) __builtin_expect((x),0) +#define PA_LIKELY(x) (__builtin_expect((x),1)) +#define PA_UNLIKELY(x) (__builtin_expect((x),0)) #else #define PA_LIKELY(x) (x) #define PA_UNLIKELY(x) (x) diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h index 548e4ed90..98e023aa9 100644 --- a/src/pulsecore/macro.h +++ b/src/pulsecore/macro.h @@ -77,8 +77,8 @@ static inline size_t pa_page_align(size_t l) { #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) #endif -#define PA_CLAMP_LIKELY(x, low, high) (PA_LIKELY((x) > (high)) ? (high) : PA_LIKELY(((x) < (low)) ? (low) : (x))) -#define PA_CLAMP_UNLIKELY(x, low, high) (PA_UNLIKELY((x) > (high)) ? (high) : PA_UNLIKELY(((x) < (low)) ? (low) : (x))) +#define PA_CLAMP_LIKELY(x, low, high) (PA_LIKELY((x) > (high)) ? (high) : (PA_LIKELY((x)<(low)) ? (low) : (x))) +#define PA_CLAMP_UNLIKELY(x, low, high) (PA_UNLIKELY((x) > (high)) ? (high) : (PA_UNLIKELY((x) < (low)) ? (low) : (x))) /* This type is not intended to be used in exported APIs! Use classic "int" there! */ #ifdef HAVE_STD_BOOL From 7e0f547f2fd8ddfae1d807334dbc3428a3dfe374 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 02:45:07 +0000 Subject: [PATCH 1438/1514] add support for 32bit integer samples git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2037 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 14 +++- src/modules/oss-util.c | 2 + src/pulse/sample.c | 16 ++++- src/pulse/sample.h | 18 ++++- src/pulsecore/resampler.c | 4 +- src/pulsecore/sample-util.c | 61 +++++++++++++++-- src/pulsecore/sconv-s16be.c | 15 +++++ src/pulsecore/sconv-s16be.h | 20 ++++++ src/pulsecore/sconv-s16le.c | 131 +++++++++++++++++++++++++++++++++++- src/pulsecore/sconv-s16le.h | 20 ++++++ src/pulsecore/sconv.c | 8 +++ src/tests/resampler-test.c | 27 ++++++++ 12 files changed, 319 insertions(+), 17 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 906de58d5..15ae1fc6e 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -227,15 +227,19 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE, [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE, [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE, + [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE, + [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE, }; static const pa_sample_format_t try_order[] = { - PA_SAMPLE_S16NE, - PA_SAMPLE_S16RE, PA_SAMPLE_FLOAT32NE, PA_SAMPLE_FLOAT32RE, - PA_SAMPLE_ULAW, + PA_SAMPLE_S32NE, + PA_SAMPLE_S32RE, + PA_SAMPLE_S16NE, + PA_SAMPLE_S16RE, PA_SAMPLE_ALAW, + PA_SAMPLE_ULAW, PA_SAMPLE_U8, PA_SAMPLE_INVALID }; @@ -256,6 +260,10 @@ static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_s *f = PA_SAMPLE_S16LE; else if (*f == PA_SAMPLE_S16LE) *f = PA_SAMPLE_S16BE; + else if (*f == PA_SAMPLE_S32BE) + *f = PA_SAMPLE_S32LE; + else if (*f == PA_SAMPLE_S32LE) + *f = PA_SAMPLE_S32BE; else goto try_auto; diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c index 015db4ca2..9598feee9 100644 --- a/src/modules/oss-util.c +++ b/src/modules/oss-util.c @@ -164,6 +164,8 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss) { [PA_SAMPLE_S16BE] = AFMT_S16_BE, [PA_SAMPLE_FLOAT32LE] = AFMT_QUERY, /* not supported */ [PA_SAMPLE_FLOAT32BE] = AFMT_QUERY, /* not supported */ + [PA_SAMPLE_S32LE] = AFMT_QUERY, /* not supported */ + [PA_SAMPLE_S32BE] = AFMT_QUERY, /* not supported */ }; pa_assert(fd >= 0); diff --git a/src/pulse/sample.c b/src/pulse/sample.c index ae2a0b9f0..27c0df039 100644 --- a/src/pulse/sample.c +++ b/src/pulse/sample.c @@ -44,7 +44,9 @@ size_t pa_sample_size(const pa_sample_spec *spec) { [PA_SAMPLE_S16LE] = 2, [PA_SAMPLE_S16BE] = 2, [PA_SAMPLE_FLOAT32LE] = 4, - [PA_SAMPLE_FLOAT32BE] = 4 + [PA_SAMPLE_FLOAT32BE] = 4, + [PA_SAMPLE_S32LE] = 4, + [PA_SAMPLE_S32BE] = 4, }; pa_assert(spec); @@ -107,6 +109,8 @@ const char *pa_sample_format_to_string(pa_sample_format_t f) { [PA_SAMPLE_S16BE] = "s16be", [PA_SAMPLE_FLOAT32LE] = "float32le", [PA_SAMPLE_FLOAT32BE] = "float32be", + [PA_SAMPLE_S32LE] = "s32le", + [PA_SAMPLE_S32BE] = "s32be", }; if (f < 0 || f >= PA_SAMPLE_MAX) @@ -156,7 +160,7 @@ pa_sample_format_t pa_parse_sample_format(const char *format) { return PA_SAMPLE_S16RE; else if (strcasecmp(format, "u8") == 0 || strcasecmp(format, "8") == 0) return PA_SAMPLE_U8; - else if (strcasecmp(format, "float32") == 0 || strcasecmp(format, "float32ne") == 0) + else if (strcasecmp(format, "float32") == 0 || strcasecmp(format, "float32ne") == 0 || strcasecmp(format, "float") == 0) return PA_SAMPLE_FLOAT32NE; else if (strcasecmp(format, "float32re") == 0) return PA_SAMPLE_FLOAT32RE; @@ -168,6 +172,14 @@ pa_sample_format_t pa_parse_sample_format(const char *format) { return PA_SAMPLE_ULAW; else if (strcasecmp(format, "alaw") == 0) return PA_SAMPLE_ALAW; + else if (strcasecmp(format, "s32le") == 0) + return PA_SAMPLE_S32LE; + else if (strcasecmp(format, "s32be") == 0) + return PA_SAMPLE_S32BE; + else if (strcasecmp(format, "s32ne") == 0 || strcasecmp(format, "s32") == 0 || strcasecmp(format, "32") == 0) + return PA_SAMPLE_S32NE; + else if (strcasecmp(format, "s32re") == 0) + return PA_SAMPLE_S32RE; return -1; } diff --git a/src/pulse/sample.h b/src/pulse/sample.h index b307621e4..2c13f57d9 100644 --- a/src/pulse/sample.h +++ b/src/pulse/sample.h @@ -42,13 +42,15 @@ * * PulseAudio supports the following sample formats: * - * \li PA_SAMPLE_U8 - Unsigned 8 bit PCM. - * \li PA_SAMPLE_S16LE - Signed 16 bit PCM, little endian. - * \li PA_SAMPLE_S16BE - Signed 16 bit PCM, big endian. + * \li PA_SAMPLE_U8 - Unsigned 8 bit integer PCM. + * \li PA_SAMPLE_S16LE - Signed 16 integer bit PCM, little endian. + * \li PA_SAMPLE_S16BE - Signed 16 integer bit PCM, big endian. * \li PA_SAMPLE_FLOAT32LE - 32 bit IEEE floating point PCM, little endian. * \li PA_SAMPLE_FLOAT32BE - 32 bit IEEE floating point PCM, big endian. * \li PA_SAMPLE_ALAW - 8 bit a-Law. * \li PA_SAMPLE_ULAW - 8 bit mu-Law. + * \li PA_SAMPLE_S32LE - Signed 32 bit integer PCM, little endian. + * \li PA_SAMPLE_S32BE - Signed 32 bit integer PCM, big endian. * * The floating point sample formats have the range from -1 to 1. * @@ -117,6 +119,8 @@ typedef enum pa_sample_format { PA_SAMPLE_S16BE, /**< Signed 16 Bit PCM, big endian */ PA_SAMPLE_FLOAT32LE, /**< 32 Bit IEEE floating point, little endian, range -1 to 1 */ PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1 to 1 */ + PA_SAMPLE_S32LE, /**< Signed 32 Bit PCM, little endian (PC) */ + PA_SAMPLE_S32BE, /**< Signed 32 Bit PCM, big endian (PC) */ PA_SAMPLE_MAX, /**< Upper limit of valid sample types */ PA_SAMPLE_INVALID = -1 /**< An invalid value */ } pa_sample_format_t; @@ -126,19 +130,27 @@ typedef enum pa_sample_format { #define PA_SAMPLE_S16NE PA_SAMPLE_S16BE /** 32 Bit IEEE floating point, native endian */ #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32BE +/** Signed 32 Bit PCM, native endian */ +#define PA_SAMPLE_S32NE PA_SAMPLE_S32BE /** Signed 16 Bit PCM reverse endian */ #define PA_SAMPLE_S16RE PA_SAMPLE_S16LE /** 32 Bit IEEE floating point, reverse endian */ #define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32LE +/** Signed 32 Bit PCM reverse endian */ +#define PA_SAMPLE_S32RE PA_SAMPLE_S32LE #else /** Signed 16 Bit PCM, native endian */ #define PA_SAMPLE_S16NE PA_SAMPLE_S16LE /** 32 Bit IEEE floating point, native endian */ #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32LE +/** Signed 32 Bit PCM, native endian */ +#define PA_SAMPLE_S32NE PA_SAMPLE_S32LE /** Signed 16 Bit PCM reverse endian */ #define PA_SAMPLE_S16RE PA_SAMPLE_S16BE /** 32 Bit IEEE floating point, reverse endian */ #define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32BE +/** Signed 32 Bit PCM reverse endian */ +#define PA_SAMPLE_S32RE PA_SAMPLE_S32BE #endif /** A Shortcut for PA_SAMPLE_FLOAT32NE */ diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index b44471984..eebc9c046 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -240,7 +240,9 @@ pa_resampler* pa_resampler_new( if (r->map_required || a->format != b->format) { - if (a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE || + if (a->format == PA_SAMPLE_S32NE || a->format == PA_SAMPLE_S32RE || + a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE || + b->format == PA_SAMPLE_S32NE || b->format == PA_SAMPLE_S32RE || b->format == PA_SAMPLE_FLOAT32NE || b->format == PA_SAMPLE_FLOAT32RE) r->work_format = PA_SAMPLE_FLOAT32NE; else diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index 21771302a..0383b5675 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -100,6 +100,8 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { break; case PA_SAMPLE_S16LE: case PA_SAMPLE_S16BE: + case PA_SAMPLE_S32LE: + case PA_SAMPLE_S32BE: case PA_SAMPLE_FLOAT32: case PA_SAMPLE_FLOAT32RE: c = 0; @@ -380,10 +382,10 @@ void pa_volume_memchunk( t = (int32_t)(*d); t = (t * linear[channel]) / 0x10000; - t = CLAMP(t, -0x8000, 0x7FFF); + t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); *d = (int16_t) t; - if (++channel >= spec->channels) + if (PA_UNLIKELY(++channel >= spec->channels)) channel = 0; } break; @@ -403,10 +405,57 @@ void pa_volume_memchunk( t = (int32_t)(PA_INT16_SWAP(*d)); t = (t * linear[channel]) / 0x10000; - t = CLAMP(t, -0x8000, 0x7FFF); + t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); *d = PA_INT16_SWAP((int16_t) t); - if (++channel >= spec->channels) + if (PA_UNLIKELY(++channel >= spec->channels)) + channel = 0; + } + + break; + } + + case PA_SAMPLE_S32NE: { + int32_t *d; + size_t n; + unsigned channel; + int32_t linear[PA_CHANNELS_MAX]; + + for (channel = 0; channel < spec->channels; channel++) + linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); + + for (channel = 0, d = (int32_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int32_t); n > 0; d++, n--) { + int64_t t; + + t = (int64_t)(*d); + t = (t * linear[channel]) / 0x10000; + t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); + *d = (int32_t) t; + + if (PA_UNLIKELY(++channel >= spec->channels)) + channel = 0; + } + break; + } + + case PA_SAMPLE_S32RE: { + int32_t *d; + size_t n; + unsigned channel; + int32_t linear[PA_CHANNELS_MAX]; + + for (channel = 0; channel < spec->channels; channel++) + linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); + + for (channel = 0, d = (int32_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int32_t); n > 0; d++, n--) { + int64_t t; + + t = (int64_t)(PA_INT32_SWAP(*d)); + t = (t * linear[channel]) / 0x10000; + t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); + *d = PA_INT32_SWAP((int32_t) t); + + if (PA_UNLIKELY(++channel >= spec->channels)) channel = 0; } @@ -427,10 +476,10 @@ void pa_volume_memchunk( t = (int32_t) *d - 0x80; t = (t * linear[channel]) / 0x10000; - t = CLAMP(t, -0x80, 0x7F); + t = PA_CLAMP_UNLIKELY(t, -0x80, 0x7F); *d = (uint8_t) (t + 0x80); - if (++channel >= spec->channels) + if (PA_UNLIKELY(++channel >= spec->channels)) channel = 0; } break; diff --git a/src/pulsecore/sconv-s16be.c b/src/pulsecore/sconv-s16be.c index f74d02829..638beb2ec 100644 --- a/src/pulsecore/sconv-s16be.c +++ b/src/pulsecore/sconv-s16be.c @@ -30,12 +30,27 @@ #define INT16_FROM PA_INT16_FROM_BE #define INT16_TO PA_INT16_TO_BE +#define INT32_FROM PA_INT32_FROM_BE +#define INT32_TO PA_INT32_TO_BE + #define pa_sconv_s16le_to_float32ne pa_sconv_s16be_to_float32ne #define pa_sconv_s16le_from_float32ne pa_sconv_s16be_from_float32ne #define pa_sconv_s16le_to_float32re pa_sconv_s16be_to_float32re #define pa_sconv_s16le_from_float32re pa_sconv_s16be_from_float32re +#define pa_sconv_s32le_to_float32ne pa_sconv_s32be_to_float32ne +#define pa_sconv_s32le_from_float32ne pa_sconv_s32be_from_float32ne + +#define pa_sconv_s32le_to_float32re pa_sconv_s32be_to_float32re +#define pa_sconv_s32le_from_float32re pa_sconv_s32be_from_float32re + +#define pa_sconv_s32le_to_s16ne pa_sconv_s32be_to_s16ne +#define pa_sconv_s32le_from_s16ne pa_sconv_s32be_from_s16ne + +#define pa_sconv_s32le_to_s16re pa_sconv_s32be_to_s16re +#define pa_sconv_s32le_from_s16re pa_sconv_s32be_from_s16re + #ifdef WORDS_BIGENDIAN #define SWAP_WORDS 0 #else diff --git a/src/pulsecore/sconv-s16be.h b/src/pulsecore/sconv-s16be.h index ad034489e..454c95081 100644 --- a/src/pulsecore/sconv-s16be.h +++ b/src/pulsecore/sconv-s16be.h @@ -31,11 +31,31 @@ void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, int16_t *b); void pa_sconv_s16be_to_float32re(unsigned n, const int16_t *a, float *b); void pa_sconv_s16be_from_float32re(unsigned n, const float *a, int16_t *b); +void pa_sconv_s32be_to_float32ne(unsigned n, const int32_t *a, float *b); +void pa_sconv_s32be_from_float32ne(unsigned n, const float *a, int32_t *b); +void pa_sconv_s32be_to_float32re(unsigned n, const int32_t *a, float *b); +void pa_sconv_s32be_from_float32re(unsigned n, const float *a, int32_t *b); + +void pa_sconv_s32be_to_s16ne(unsigned n, const int32_t *a, int16_t *b); +void pa_sconv_s32be_from_s16ne(unsigned n, const int16_t *a, int32_t *b); +void pa_sconv_s32be_to_s16re(unsigned n, const int32_t *a, int16_t *b); +void pa_sconv_s32be_from_s16re(unsigned n, const int16_t *a, int32_t *b); + #ifdef WORDS_BIGENDIAN #define pa_sconv_float32be_to_s16ne pa_sconv_s16be_from_float32ne #define pa_sconv_float32be_from_s16ne pa_sconv_s16be_to_float32ne #define pa_sconv_float32le_to_s16ne pa_sconv_s16be_from_float32re #define pa_sconv_float32le_from_s16ne pa_sconv_s16be_to_float32re + +#define pa_sconv_float32be_to_s32ne pa_sconv_s32be_from_float32ne +#define pa_sconv_float32be_from_s32ne pa_sconv_s32be_to_float32ne +#define pa_sconv_float32le_to_s32ne pa_sconv_s32be_from_float32re +#define pa_sconv_float32le_from_s32ne pa_sconv_s32be_to_float32re + +#define pa_sconv_s16be_to_s32ne pa_sconv_s32be_from_s16ne +#define pa_sconv_s16be_from_s32ne pa_sconv_s32be_to_s16ne +#define pa_sconv_s16le_to_s32ne pa_sconv_s32be_from_s16re +#define pa_sconv_s16le_from_s32ne pa_sconv_s32be_to_s16re #endif #endif diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c index 6925052cf..90e9b6d23 100644 --- a/src/pulsecore/sconv-s16le.c +++ b/src/pulsecore/sconv-s16le.c @@ -25,7 +25,10 @@ #include #endif +/* Despite the name of this file we implement S32 handling here, too. */ + #include +#include #include @@ -45,6 +48,14 @@ #define INT16_TO PA_INT16_TO_LE #endif +#ifndef INT32_FROM +#define INT32_FROM PA_INT32_FROM_LE +#endif + +#ifndef INT32_TO +#define INT32_TO PA_INT32_TO_LE +#endif + #ifndef SWAP_WORDS #ifdef WORDS_BIGENDIAN #define SWAP_WORDS 1 @@ -72,6 +83,25 @@ void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *b) { #endif } +void pa_sconv_s32le_to_float32ne(unsigned n, const int32_t *a, float *b) { + pa_assert(a); + pa_assert(b); + +#if SWAP_WORDS == 1 + + for (; n > 0; n--) { + int32_t s = *(a++); + *(b++) = (float) (((double) INT32_FROM(s))/0x7FFFFFFF); + } + +#else +{ + static const double add = 0, factor = 1.0/0x7FFFFFFF; + oil_scaleconv_f32_s32(b, a, n, &add, &factor); +} +#endif +} + void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) { pa_assert(a); pa_assert(b); @@ -82,7 +112,7 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) { int16_t s; float v = *(a++); - v = CLAMP(v, -1, 1); + v = PA_CLAMP_UNLIKELY(v, -1, 1); s = (int16_t) (v * 0x7FFF); *(b++) = INT16_TO(s); } @@ -95,6 +125,29 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) { #endif } +void pa_sconv_s32le_from_float32ne(unsigned n, const float *a, int32_t *b) { + pa_assert(a); + pa_assert(b); + +#if SWAP_WORDS == 1 + + for (; n > 0; n--) { + int32_t s; + float v = *(a++); + + v = PA_CLAMP_UNLIKELY(v, -1, 1); + s = (int32_t) ((double) v * (double) 0x7FFFFFFF); + *(b++) = INT32_TO(s); + } + +#else +{ + static const double add = 0, factor = 0x7FFFFFFF; + oil_scaleconv_s32_f32(b, a, n, &add, &factor); +} +#endif +} + void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) { pa_assert(a); pa_assert(b); @@ -108,6 +161,19 @@ void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) { } } +void pa_sconv_s32le_to_float32re(unsigned n, const int32_t *a, float *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s = *(a++); + float k = (float) (((double) INT32_FROM(s))/0x7FFFFFFF); + uint32_t *j = (uint32_t*) &k; + *j = PA_UINT32_SWAP(*j); + *(b++) = k; + } +} + void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) { pa_assert(a); pa_assert(b); @@ -117,8 +183,69 @@ void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) { float v = *(a++); uint32_t *j = (uint32_t*) &v; *j = PA_UINT32_SWAP(*j); - v = CLAMP(v, -1, 1); + v = PA_CLAMP_UNLIKELY(v, -1, 1); s = (int16_t) (v * 0x7FFF); *(b++) = INT16_TO(s); } } + +void pa_sconv_s32le_from_float32re(unsigned n, const float *a, int32_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s; + float v = *(a++); + uint32_t *j = (uint32_t*) &v; + *j = PA_UINT32_SWAP(*j); + v = PA_CLAMP_UNLIKELY(v, -1, 1); + s = (int32_t) ((double) v * 0x7FFFFFFF); + *(b++) = INT32_TO(s); + } +} + +void pa_sconv_s32le_to_s16ne(unsigned n, const int32_t*a, int16_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + *b = (int16_t) (INT32_FROM(*a) >> 16); + a++; + b++; + } +} + +void pa_sconv_s32le_to_s16re(unsigned n, const int32_t*a, int16_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int16_t s = (int16_t) (INT32_FROM(*a) >> 16); + *b = PA_UINT32_SWAP(s); + a++; + b++; + } +} + +void pa_sconv_s32le_from_s16ne(unsigned n, const int16_t *a, int32_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + *b = INT32_TO(((int32_t) *a) << 16); + a++; + b++; + } +} + +void pa_sconv_s32le_from_s16re(unsigned n, const int16_t *a, int32_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s = ((int32_t) PA_UINT16_SWAP(*a)) << 16; + *b = INT32_TO(s); + a++; + b++; + } +} diff --git a/src/pulsecore/sconv-s16le.h b/src/pulsecore/sconv-s16le.h index 4203315a1..4165f8a20 100644 --- a/src/pulsecore/sconv-s16le.h +++ b/src/pulsecore/sconv-s16le.h @@ -31,11 +31,31 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b); void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b); void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b); +void pa_sconv_s32le_to_float32ne(unsigned n, const int32_t *a, float *b); +void pa_sconv_s32le_from_float32ne(unsigned n, const float *a, int32_t *b); +void pa_sconv_s32le_to_float32re(unsigned n, const int32_t *a, float *b); +void pa_sconv_s32le_from_float32re(unsigned n, const float *a, int32_t *b); + +void pa_sconv_s32le_to_s16ne(unsigned n, const int32_t *a, int16_t *b); +void pa_sconv_s32le_from_s16ne(unsigned n, const int16_t *a, int32_t *b); +void pa_sconv_s32le_to_s16re(unsigned n, const int32_t *a, int16_t *b); +void pa_sconv_s32le_from_s16re(unsigned n, const int16_t *a, int32_t *b); + #ifndef WORDS_BIGENDIAN #define pa_sconv_float32be_to_s16ne pa_sconv_s16le_from_float32re #define pa_sconv_float32be_from_s16ne pa_sconv_s16le_to_float32re #define pa_sconv_float32le_to_s16ne pa_sconv_s16le_from_float32ne #define pa_sconv_float32le_from_s16ne pa_sconv_s16le_to_float32ne + +#define pa_sconv_float32be_to_s32ne pa_sconv_s32le_from_float32re +#define pa_sconv_float32be_from_s32ne pa_sconv_s32le_to_float32re +#define pa_sconv_float32le_to_s32ne pa_sconv_s32le_from_float32ne +#define pa_sconv_float32le_from_s32ne pa_sconv_s32le_to_float32ne + +#define pa_sconv_s16be_to_s32ne pa_sconv_s32le_from_s16re +#define pa_sconv_s16be_from_s32ne pa_sconv_s32le_to_s16re +#define pa_sconv_s16le_to_s32ne pa_sconv_s32le_from_s16ne +#define pa_sconv_s16le_from_s32ne pa_sconv_s32le_to_s16ne #endif #endif diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index 7f5da63f0..8a3e830aa 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -198,6 +198,8 @@ pa_convert_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) { [PA_SAMPLE_ULAW] = (pa_convert_func_t) ulaw_to_float32ne, [PA_SAMPLE_S16LE] = (pa_convert_func_t) pa_sconv_s16le_to_float32ne, [PA_SAMPLE_S16BE] = (pa_convert_func_t) pa_sconv_s16be_to_float32ne, + [PA_SAMPLE_S32LE] = (pa_convert_func_t) pa_sconv_s32le_to_float32ne, + [PA_SAMPLE_S32BE] = (pa_convert_func_t) pa_sconv_s32be_to_float32ne, [PA_SAMPLE_FLOAT32NE] = (pa_convert_func_t) float32ne_to_float32ne, [PA_SAMPLE_FLOAT32RE] = (pa_convert_func_t) float32re_to_float32ne, }; @@ -214,6 +216,8 @@ pa_convert_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) { [PA_SAMPLE_U8] = (pa_convert_func_t) u8_from_float32ne, [PA_SAMPLE_S16LE] = (pa_convert_func_t) pa_sconv_s16le_from_float32ne, [PA_SAMPLE_S16BE] = (pa_convert_func_t) pa_sconv_s16be_from_float32ne, + [PA_SAMPLE_S32LE] = (pa_convert_func_t) pa_sconv_s32le_from_float32ne, + [PA_SAMPLE_S32BE] = (pa_convert_func_t) pa_sconv_s32be_from_float32ne, [PA_SAMPLE_FLOAT32NE] = (pa_convert_func_t) float32ne_to_float32ne, [PA_SAMPLE_FLOAT32RE] = (pa_convert_func_t) float32re_to_float32ne, [PA_SAMPLE_ALAW] = (pa_convert_func_t) alaw_from_float32ne, @@ -234,6 +238,8 @@ pa_convert_func_t pa_get_convert_to_s16ne_function(pa_sample_format_t f) { [PA_SAMPLE_S16RE] = (pa_convert_func_t) s16re_to_s16ne, [PA_SAMPLE_FLOAT32BE] = (pa_convert_func_t) pa_sconv_float32be_to_s16ne, [PA_SAMPLE_FLOAT32LE] = (pa_convert_func_t) pa_sconv_float32le_to_s16ne, + [PA_SAMPLE_S32BE] = (pa_convert_func_t) pa_sconv_s32be_to_s16ne, + [PA_SAMPLE_S32LE] = (pa_convert_func_t) pa_sconv_s32le_to_s16ne, [PA_SAMPLE_ALAW] = (pa_convert_func_t) alaw_to_s16ne, [PA_SAMPLE_ULAW] = (pa_convert_func_t) ulaw_to_s16ne }; @@ -252,6 +258,8 @@ pa_convert_func_t pa_get_convert_from_s16ne_function(pa_sample_format_t f) { [PA_SAMPLE_S16RE] = (pa_convert_func_t) s16re_to_s16ne, [PA_SAMPLE_FLOAT32BE] = (pa_convert_func_t) pa_sconv_float32be_from_s16ne, [PA_SAMPLE_FLOAT32LE] = (pa_convert_func_t) pa_sconv_float32le_from_s16ne, + [PA_SAMPLE_S32BE] = (pa_convert_func_t) pa_sconv_s32be_from_s16ne, + [PA_SAMPLE_S32LE] = (pa_convert_func_t) pa_sconv_s32le_from_s16ne, [PA_SAMPLE_ALAW] = (pa_convert_func_t) alaw_from_s16ne, [PA_SAMPLE_ULAW] = (pa_convert_func_t) ulaw_from_s16ne, }; diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c index 3b4a73865..5295995bc 100644 --- a/src/tests/resampler-test.c +++ b/src/tests/resampler-test.c @@ -71,6 +71,16 @@ static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) { break; } + case PA_SAMPLE_S32NE: + case PA_SAMPLE_S32RE: { + uint32_t *u = d; + + for (i = 0; i < chunk->length / pa_frame_size(ss); i++) + printf("0x%08x ", *(u++)); + + break; + } + case PA_SAMPLE_FLOAT32NE: case PA_SAMPLE_FLOAT32RE: { float *u = d; @@ -137,6 +147,23 @@ static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) { break; } + case PA_SAMPLE_S32NE: + case PA_SAMPLE_S32RE: { + uint32_t *u = d; + + u[0] = 0x00000001; + u[1] = 0xFFFF0002; + u[2] = 0x7FFF0003; + u[3] = 0x80000004; + u[4] = 0x9fff0005; + u[5] = 0x3fff0006; + u[6] = 0x10007; + u[7] = 0xF0000008; + u[8] = 0x200009; + u[9] = 0x21000A; + break; + } + case PA_SAMPLE_FLOAT32NE: case PA_SAMPLE_FLOAT32RE: { float *u = d; From 7bd3c0396dd0ebc7e312f5acbc02f5815eeeebc1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 14:14:29 +0000 Subject: [PATCH 1439/1514] .la files for modules can probably be removed safely on all archs now git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2038 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index 91e22dfe5..024988ba3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1447,6 +1447,7 @@ install-exec-hook: rm -f $(DESTDIR)$(modlibexecdir)/*.a rm -f $(DESTDIR)$(libdir)/libpulsedsp.a rm -f $(DESTDIR)$(libdir)/libpulsedsp.la + rm -f $(DESTDIR)$(modlibexecdir)/*.la massif: pulseaudio libtool --mode=execute valgrind --tool=massif --depth=6 --alloc-fn=pa_xmalloc --alloc-fn=pa_xmalloc0 --alloc-fn=pa_xrealloc --alloc-fn=dbus_realloc --alloc-fn=pa_xnew0_internal --alloc-fn=pa_xnew_internal ./pulseaudio From 01490319d38c2f90749f9b7b555f332e2e7f3da9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 14:19:40 +0000 Subject: [PATCH 1440/1514] remove PA_CLAMP_LIKELY macro because it doesn't really make sense. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2039 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/macro.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h index 98e023aa9..4b62dd21a 100644 --- a/src/pulsecore/macro.h +++ b/src/pulsecore/macro.h @@ -77,8 +77,10 @@ static inline size_t pa_page_align(size_t l) { #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) #endif -#define PA_CLAMP_LIKELY(x, low, high) (PA_LIKELY((x) > (high)) ? (high) : (PA_LIKELY((x)<(low)) ? (low) : (x))) #define PA_CLAMP_UNLIKELY(x, low, high) (PA_UNLIKELY((x) > (high)) ? (high) : (PA_UNLIKELY((x) < (low)) ? (low) : (x))) +/* We don't define a PA_CLAMP_LIKELY here, because it doesn't really + * make sense: we cannot know if it is more likely that the values is + * lower or greater than the boundaries.*/ /* This type is not intended to be used in exported APIs! Use classic "int" there! */ #ifdef HAVE_STD_BOOL From c1985c2acc43f5d2c23e1e736588c5ef3a398a17 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 14:20:12 +0000 Subject: [PATCH 1441/1514] replace a few CLAMPs by PA_CLAMP_UNLIKELY git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2040 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-ladspa-sink.c | 4 ++-- src/pulsecore/sample-util.c | 6 +++--- src/pulsecore/sconv.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c index 0265d9713..6ed392cea 100644 --- a/src/modules/module-ladspa-sink.c +++ b/src/modules/module-ladspa-sink.c @@ -177,14 +177,14 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun p = src + c; q = u->input; for (j = 0; j < n; j++, p += u->channels, q++) - *q = CLAMP(*p, -1.0, 1.0); + *q = PA_CLAMP_UNLIKELY(*p, -1.0, 1.0); u->descriptor->run(u->handle[c], n); q = u->output; p = dst + c; for (j = 0; j < n; j++, q++, p += u->channels) - *p = CLAMP(*q, -1.0, 1.0); + *p = PA_CLAMP_UNLIKELY(*q, -1.0, 1.0); } pa_memblock_release(tchunk.memblock); diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index 0383b5675..001a997ee 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -178,7 +178,7 @@ size_t pa_mix( if (volume->values[channel] != PA_VOLUME_NORM) sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); - sum = CLAMP(sum, -0x8000, 0x7FFF); + sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); } *((int16_t*) data) = (int16_t) sum; @@ -225,7 +225,7 @@ size_t pa_mix( if (volume->values[channel] != PA_VOLUME_NORM) sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); - sum = CLAMP(sum, -0x8000, 0x7FFF); + sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); } *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum); @@ -272,7 +272,7 @@ size_t pa_mix( if (volume->values[channel] != PA_VOLUME_NORM) sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); - sum = CLAMP(sum, -0x80, 0x7F); + sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F); } *((uint8_t*) data) = (uint8_t) (sum + 0x80); diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index 8a3e830aa..ebd74586a 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -130,7 +130,7 @@ static void ulaw_from_float32ne(unsigned n, const float *a, uint8_t *b) { for (; n > 0; n--) { float v = *(a++); - v = CLAMP(v, -1, 1); + v = PA_CLAMP_UNLIKELY(v, -1, 1); v *= 0x1FFF; *(b++) = st_14linear2ulaw((int16_t) v); } @@ -168,7 +168,7 @@ static void alaw_from_float32ne(unsigned n, const float *a, uint8_t *b) { for (; n > 0; n--, a++, b++) { float v = *a; - v = CLAMP(v, -1, 1); + v = PA_CLAMP_UNLIKELY(v, -1, 1); v *= 0xFFF; *b = st_13linear2alaw((int16_t) v); } From b0a68fd09ff6fa62accdc29307c5f445cc054a94 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 17:11:45 +0000 Subject: [PATCH 1442/1514] optimize mixing code a bit. Add mixers for S32LE, S32BE, ULAW, ALAW and FLOAT32BE. Add volume adjusters for FLOAT32BE, ALAW, ULAW. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2041 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 8 +- src/pulsecore/sample-util.c | 574 ++++++++++++++++++++++++++++-------- src/pulsecore/sample-util.h | 11 +- src/tests/mix-test.c | 261 ++++++++++++++++ 4 files changed, 734 insertions(+), 120 deletions(-) create mode 100644 src/tests/mix-test.c diff --git a/src/Makefile.am b/src/Makefile.am index 024988ba3..8fe7be9da 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -239,7 +239,8 @@ noinst_PROGRAMS = \ rtpoll-test \ sig2str-test \ resampler-test \ - smoother-test + smoother-test \ + mix-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -389,6 +390,11 @@ resampler_test_LDADD = $(AM_LDADD) libpulsecore.la resampler_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) resampler_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) +mix_test_SOURCES = tests/mix-test.c +mix_test_LDADD = $(AM_LDADD) libpulsecore.la +mix_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) +mix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) + smoother_test_SOURCES = tests/smoother-test.c smoother_test_LDADD = $(AM_LDADD) libpulsecore.la smoother_test_CFLAGS = $(AM_CFLAGS) diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index 001a997ee..4ea5d4464 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -35,6 +35,7 @@ #include #include +#include #include "sample-util.h" #include "endianmacros.h" @@ -119,6 +120,58 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { memset(p, c, length); } +static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) { + unsigned k; + + pa_assert(streams); + pa_assert(spec); + + for (k = 0; k < nstreams; k++) { + unsigned channel; + + for (channel = 0; channel < spec->channels; channel++) { + pa_mix_info *m = streams + k; + m->linear[channel].i = (int32_t) (pa_sw_volume_to_linear(m->volume.values[channel]) * 0x10000); + } + } +} + +static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) { + unsigned channel; + + pa_assert(linear); + pa_assert(volume); + + for (channel = 0; channel < volume->channels; channel++) + linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); +} + +static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) { + unsigned k; + + pa_assert(streams); + pa_assert(spec); + + for (k = 0; k < nstreams; k++) { + unsigned channel; + + for (channel = 0; channel < spec->channels; channel++) { + pa_mix_info *m = streams + k; + m->linear[channel].f = pa_sw_volume_to_linear(m->volume.values[channel]); + } + } +} + +static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) { + unsigned channel; + + pa_assert(linear); + pa_assert(volume); + + for (channel = 0; channel < volume->channels; channel++) + linear[channel] = pa_sw_volume_to_linear(volume->values[channel]); +} + size_t pa_mix( pa_mix_info streams[], unsigned nstreams, @@ -126,11 +179,11 @@ size_t pa_mix( size_t length, const pa_sample_spec *spec, const pa_cvolume *volume, - int mute) { + pa_bool_t mute) { pa_cvolume full_volume; - size_t d = 0; unsigned k; + size_t d = 0; pa_assert(streams); pa_assert(data); @@ -141,50 +194,49 @@ size_t pa_mix( volume = pa_cvolume_reset(&full_volume, spec->channels); for (k = 0; k < nstreams; k++) - streams[k].internal = pa_memblock_acquire(streams[k].chunk.memblock); + streams[k].ptr = (uint8_t*) pa_memblock_acquire(streams[k].chunk.memblock) + streams[k].chunk.index; switch (spec->format) { + case PA_SAMPLE_S16NE:{ unsigned channel = 0; + int32_t linear[PA_CHANNELS_MAX]; + + calc_linear_integer_stream_volumes(streams, nstreams, spec); + calc_linear_integer_volume(linear, volume); for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; + unsigned i; - if (d >= length) + if (PA_UNLIKELY(d >= length)) goto finish; - if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { - unsigned i; + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t v, cv = m->linear[channel].i; - for (i = 0; i < nstreams; i++) { - int32_t v; - pa_volume_t cvolume = streams[i].volume.values[channel]; + if (PA_UNLIKELY(d >= m->chunk.length)) + goto finish; - if (d >= streams[i].chunk.length) - goto finish; - - if (cvolume == PA_VOLUME_MUTED) - v = 0; - else { - v = *((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d)); - - if (cvolume != PA_VOLUME_NORM) - v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); - } - - sum += v; + if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) + v = 0; + else { + v = *((int16_t*) m->ptr); + v = (v * cv) / 0x10000; } - if (volume->values[channel] != PA_VOLUME_NORM) - sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); - - sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); + sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int16_t); } + sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); + sum = (sum * linear[channel]) / 0x10000; *((int16_t*) data) = (int16_t) sum; + data = (uint8_t*) data + sizeof(int16_t); - if (++channel >= spec->channels) + if (PA_UNLIKELY(++channel >= spec->channels)) channel = 0; } @@ -193,45 +245,135 @@ size_t pa_mix( case PA_SAMPLE_S16RE:{ unsigned channel = 0; + int32_t linear[PA_CHANNELS_MAX]; + + calc_linear_integer_stream_volumes(streams, nstreams, spec); + calc_linear_integer_volume(linear, volume); for (d = 0;; d += sizeof(int16_t)) { int32_t sum = 0; + unsigned i; - if (d >= length) + if (PA_UNLIKELY(d >= length)) goto finish; - if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { - unsigned i; + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t v, cv = m->linear[channel].i; - for (i = 0; i < nstreams; i++) { - int32_t v; - pa_volume_t cvolume = streams[i].volume.values[channel]; + if (PA_UNLIKELY(d >= m->chunk.length)) + goto finish; - if (d >= streams[i].chunk.length) - goto finish; - - if (cvolume == PA_VOLUME_MUTED) - v = 0; - else { - v = PA_INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d))); - - if (cvolume != PA_VOLUME_NORM) - v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); - } - - sum += v; + if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) + v = 0; + else { + v = PA_INT16_SWAP(*((int16_t*) m->ptr)); + v = (v * cv) / 0x10000; } - if (volume->values[channel] != PA_VOLUME_NORM) - sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); - - sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); + sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int16_t); } + sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); + sum = (sum * linear[channel]) / 0x10000; *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum); + data = (uint8_t*) data + sizeof(int16_t); - if (++channel >= spec->channels) + if (PA_UNLIKELY(++channel >= spec->channels)) + channel = 0; + } + + break; + } + + case PA_SAMPLE_S32NE:{ + unsigned channel = 0; + int32_t linear[PA_CHANNELS_MAX]; + + calc_linear_integer_stream_volumes(streams, nstreams, spec); + calc_linear_integer_volume(linear, volume); + + for (d = 0;; d += sizeof(int32_t)) { + int64_t sum = 0; + unsigned i; + + if (PA_UNLIKELY(d >= length)) + goto finish; + + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int64_t v; + int32_t cv = m->linear[channel].i; + + if (PA_UNLIKELY(d >= m->chunk.length)) + goto finish; + + if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) + v = 0; + else { + v = *((int32_t*) m->ptr); + v = (v * cv) / 0x10000; + } + + sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); + } + + sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); + sum = (sum * linear[channel]) / 0x10000; + *((int32_t*) data) = (int32_t) sum; + + data = (uint8_t*) data + sizeof(int32_t); + + if (PA_UNLIKELY(++channel >= spec->channels)) + channel = 0; + } + + break; + } + + case PA_SAMPLE_S32RE:{ + unsigned channel = 0; + int32_t linear[PA_CHANNELS_MAX]; + + calc_linear_integer_stream_volumes(streams, nstreams, spec); + calc_linear_integer_volume(linear, volume); + + for (d = 0;; d += sizeof(int32_t)) { + int64_t sum = 0; + unsigned i; + + if (PA_UNLIKELY(d >= length)) + goto finish; + + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int64_t v; + int32_t cv = m->linear[channel].i; + + if (PA_UNLIKELY(d >= m->chunk.length)) + goto finish; + + if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) + v = 0; + else { + v = PA_INT32_SWAP(*((int32_t*) m->ptr)); + v = (v * cv) / 0x10000; + } + + sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); + } + + sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); + sum = (sum * linear[channel]) / 0x10000; + *((int32_t*) data) = PA_INT32_SWAP((int32_t) sum); + + data = (uint8_t*) data + sizeof(int32_t); + + if (PA_UNLIKELY(++channel >= spec->channels)) channel = 0; } @@ -240,45 +382,133 @@ size_t pa_mix( case PA_SAMPLE_U8: { unsigned channel = 0; + int32_t linear[PA_CHANNELS_MAX]; + + calc_linear_integer_stream_volumes(streams, nstreams, spec); + calc_linear_integer_volume(linear, volume); for (d = 0;; d ++) { int32_t sum = 0; + unsigned i; - if (d >= length) + if (PA_UNLIKELY(d >= length)) goto finish; - if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { - unsigned i; + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t v, cv = m->linear[channel].i; - for (i = 0; i < nstreams; i++) { - int32_t v; - pa_volume_t cvolume = streams[i].volume.values[channel]; + if (PA_UNLIKELY(d >= m->chunk.length)) + goto finish; - if (d >= streams[i].chunk.length) - goto finish; - - if (cvolume == PA_VOLUME_MUTED) - v = 0; - else { - v = (int32_t) *((uint8_t*) streams[i].internal + streams[i].chunk.index + d) - 0x80; - - if (cvolume != PA_VOLUME_NORM) - v = (int32_t) (v * pa_sw_volume_to_linear(cvolume)); - } - - sum += v; + if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) + v = 0; + else { + v = (int32_t) *((uint8_t*) m->ptr) - 0x80; + v = (v * cv) / 0x10000; } - if (volume->values[channel] != PA_VOLUME_NORM) - sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel])); - - sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F); + sum += v; + m->ptr = (uint8_t*) m->ptr + 1; } + sum = (sum * linear[channel]) / 0x10000; + sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F); *((uint8_t*) data) = (uint8_t) (sum + 0x80); + data = (uint8_t*) data + 1; - if (++channel >= spec->channels) + if (PA_UNLIKELY(++channel >= spec->channels)) + channel = 0; + } + + break; + } + + case PA_SAMPLE_ULAW: { + unsigned channel = 0; + int32_t linear[PA_CHANNELS_MAX]; + + calc_linear_integer_stream_volumes(streams, nstreams, spec); + calc_linear_integer_volume(linear, volume); + + for (d = 0;; d ++) { + int32_t sum = 0; + unsigned i; + + if (PA_UNLIKELY(d >= length)) + goto finish; + + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t v, cv = m->linear[channel].i; + + if (PA_UNLIKELY(d >= m->chunk.length)) + goto finish; + + if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) + v = 0; + else { + v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr)); + v = (v * cv) / 0x10000; + } + + sum += v; + m->ptr = (uint8_t*) m->ptr + 1; + } + + sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); + sum = (sum * linear[channel]) / 0x10000; + *((uint8_t*) data) = (uint8_t) st_14linear2ulaw(sum >> 2); + + data = (uint8_t*) data + 1; + + if (PA_UNLIKELY(++channel >= spec->channels)) + channel = 0; + } + + break; + } + + case PA_SAMPLE_ALAW: { + unsigned channel = 0; + int32_t linear[PA_CHANNELS_MAX]; + + calc_linear_integer_stream_volumes(streams, nstreams, spec); + calc_linear_integer_volume(linear, volume); + + for (d = 0;; d ++) { + int32_t sum = 0; + unsigned i; + + if (PA_UNLIKELY(d >= length)) + goto finish; + + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + int32_t v, cv = m->linear[channel].i; + + if (PA_UNLIKELY(d >= m->chunk.length)) + goto finish; + + if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) + v = 0; + else { + v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr)); + v = (v * cv) / 0x10000; + } + + sum += v; + m->ptr = (uint8_t*) m->ptr + 1; + } + + sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); + sum = (sum * linear[channel]) / 0x10000; + *((uint8_t*) data) = (uint8_t) st_13linear2alaw(sum >> 3); + + data = (uint8_t*) data + 1; + + if (PA_UNLIKELY(++channel >= spec->channels)) channel = 0; } @@ -287,43 +517,88 @@ size_t pa_mix( case PA_SAMPLE_FLOAT32NE: { unsigned channel = 0; + float linear[PA_CHANNELS_MAX]; + + calc_linear_float_stream_volumes(streams, nstreams, spec); + calc_linear_float_volume(linear, volume); for (d = 0;; d += sizeof(float)) { float sum = 0; + unsigned i; - if (d >= length) + if (PA_UNLIKELY(d >= length)) goto finish; - if (!mute && volume->values[channel] != PA_VOLUME_MUTED) { - unsigned i; + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + float v, cv = m->linear[channel].f; - for (i = 0; i < nstreams; i++) { - float v; - pa_volume_t cvolume = streams[i].volume.values[channel]; + if (PA_UNLIKELY(d >= m->chunk.length)) + goto finish; - if (d >= streams[i].chunk.length) - goto finish; - - if (cvolume == PA_VOLUME_MUTED) - v = 0; - else { - v = *((float*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d)); - - if (cvolume != PA_VOLUME_NORM) - v *= pa_sw_volume_to_linear(cvolume); - } - - sum += v; + if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) + v = 0; + else { + v = *((float*) m->ptr); + v *= cv; } - if (volume->values[channel] != PA_VOLUME_NORM) - sum *= pa_sw_volume_to_linear(volume->values[channel]); + sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(float); } + sum *= linear[channel]; *((float*) data) = sum; + data = (uint8_t*) data + sizeof(float); - if (++channel >= spec->channels) + if (PA_UNLIKELY(++channel >= spec->channels)) + channel = 0; + } + + break; + } + + case PA_SAMPLE_FLOAT32RE: { + unsigned channel = 0; + float linear[PA_CHANNELS_MAX]; + + calc_linear_float_stream_volumes(streams, nstreams, spec); + calc_linear_float_volume(linear, volume); + + for (d = 0;; d += sizeof(float)) { + float sum = 0; + unsigned i; + + if (PA_UNLIKELY(d >= length)) + goto finish; + + for (i = 0; i < nstreams; i++) { + pa_mix_info *m = streams + i; + float v, cv = m->linear[channel].f; + + if (PA_UNLIKELY(d >= m->chunk.length)) + goto finish; + + if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(!!mute) || PA_UNLIKELY(linear[channel] <= 0)) + v = 0; + else { + uint32_t z = *(uint32_t*) m->ptr; + z = PA_UINT32_SWAP(z); + v = *((float*) &z); + v *= cv; + } + + sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(float); + } + + sum *= linear[channel]; + *((uint32_t*) data) = PA_UINT32_SWAP(*(uint32_t*) &sum); + + data = (uint8_t*) data + sizeof(float); + + if (PA_UNLIKELY(++channel >= spec->channels)) channel = 0; } @@ -332,7 +607,7 @@ size_t pa_mix( default: pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format)); - abort(); + pa_assert_not_reached(); } finish: @@ -364,7 +639,7 @@ void pa_volume_memchunk( return; } - ptr = pa_memblock_acquire(c->memblock); + ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index; switch (spec->format) { @@ -374,10 +649,9 @@ void pa_volume_memchunk( unsigned channel; int32_t linear[PA_CHANNELS_MAX]; - for (channel = 0; channel < spec->channels; channel++) - linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); + calc_linear_integer_volume(linear, volume); - for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + for (channel = 0, d = ptr, n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t; t = (int32_t)(*d); @@ -397,10 +671,9 @@ void pa_volume_memchunk( unsigned channel; int32_t linear[PA_CHANNELS_MAX]; - for (channel = 0; channel < spec->channels; channel++) - linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); + calc_linear_integer_volume(linear, volume); - for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) { + for (channel = 0, d = ptr, n = c->length/sizeof(int16_t); n > 0; d++, n--) { int32_t t; t = (int32_t)(PA_INT16_SWAP(*d)); @@ -421,10 +694,9 @@ void pa_volume_memchunk( unsigned channel; int32_t linear[PA_CHANNELS_MAX]; - for (channel = 0; channel < spec->channels; channel++) - linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); + calc_linear_integer_volume(linear, volume); - for (channel = 0, d = (int32_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int32_t); n > 0; d++, n--) { + for (channel = 0, d = ptr, n = c->length/sizeof(int32_t); n > 0; d++, n--) { int64_t t; t = (int64_t)(*d); @@ -444,10 +716,9 @@ void pa_volume_memchunk( unsigned channel; int32_t linear[PA_CHANNELS_MAX]; - for (channel = 0; channel < spec->channels; channel++) - linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); + calc_linear_integer_volume(linear, volume); - for (channel = 0, d = (int32_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int32_t); n > 0; d++, n--) { + for (channel = 0, d = ptr, n = c->length/sizeof(int32_t); n > 0; d++, n--) { int64_t t; t = (int64_t)(PA_INT32_SWAP(*d)); @@ -468,10 +739,9 @@ void pa_volume_memchunk( unsigned channel; int32_t linear[PA_CHANNELS_MAX]; - for (channel = 0; channel < spec->channels; channel++) - linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); + calc_linear_integer_volume(linear, volume); - for (channel = 0, d = (uint8_t*) ptr + c->index, n = c->length; n > 0; d++, n--) { + for (channel = 0, d = ptr, n = c->length; n > 0; d++, n--) { int32_t t; t = (int32_t) *d - 0x80; @@ -485,20 +755,64 @@ void pa_volume_memchunk( break; } + case PA_SAMPLE_ULAW: { + uint8_t *d; + size_t n; + unsigned channel; + int32_t linear[PA_CHANNELS_MAX]; + + calc_linear_integer_volume(linear, volume); + + for (channel = 0, d = ptr, n = c->length; n > 0; d++, n--) { + int32_t t; + + t = (int32_t) st_ulaw2linear16(*d); + t = (t * linear[channel]) / 0x10000; + t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); + *d = (uint8_t) st_14linear2ulaw(t >> 2); + + if (PA_UNLIKELY(++channel >= spec->channels)) + channel = 0; + } + break; + } + + case PA_SAMPLE_ALAW: { + uint8_t *d; + size_t n; + unsigned channel; + int32_t linear[PA_CHANNELS_MAX]; + + calc_linear_integer_volume(linear, volume); + + for (channel = 0, d = ptr, n = c->length; n > 0; d++, n--) { + int32_t t; + + t = (int32_t) st_alaw2linear16(*d); + t = (t * linear[channel]) / 0x10000; + t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); + *d = (uint8_t) st_13linear2alaw(t >> 3); + + if (PA_UNLIKELY(++channel >= spec->channels)) + channel = 0; + } + break; + } + case PA_SAMPLE_FLOAT32NE: { float *d; int skip; unsigned n; unsigned channel; - d = (float*) ((uint8_t*) ptr + c->index); + d = ptr; skip = spec->channels * sizeof(float); n = c->length/sizeof(float)/spec->channels; - for (channel = 0; channel < spec->channels ; channel ++) { + for (channel = 0; channel < spec->channels; channel ++) { float v, *t; - if (volume->values[channel] == PA_VOLUME_NORM) + if (PA_UNLIKELY(volume->values[channel] == PA_VOLUME_NORM)) continue; v = (float) pa_sw_volume_to_linear(volume->values[channel]); @@ -508,6 +822,32 @@ void pa_volume_memchunk( break; } + case PA_SAMPLE_FLOAT32RE: { + uint32_t *d; + size_t n; + unsigned channel; + float linear[PA_CHANNELS_MAX]; + + calc_linear_float_volume(linear, volume); + + for (channel = 0, d = ptr, n = c->length/sizeof(float); n > 0; d++, n--) { + float t; + uint32_t z; + + z = PA_UINT32_SWAP(*d); + t = *(float*) &z; + t *= linear[channel]; + z = *(uint32_t*) &t; + *d = PA_UINT32_SWAP(z); + + if (PA_UNLIKELY(++channel >= spec->channels)) + channel = 0; + } + + break; + } + + default: pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec->format)); /* If we cannot change the volume, we just don't do it */ diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h index 0a39d5ca1..2ef8f9244 100644 --- a/src/pulsecore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -39,7 +39,14 @@ typedef struct pa_mix_info { pa_memchunk chunk; pa_cvolume volume; void *userdata; - void *internal; /* Used internally by pa_mix(), should not be initialised when calling pa_mix() */ + + /* The following fields are used internally by pa_mix(), should + * not be initialised by the caller of pa_mix(). */ + void *ptr; + union { + int32_t i; + float f; + } linear[PA_CHANNELS_MAX]; } pa_mix_info; size_t pa_mix( @@ -49,7 +56,7 @@ size_t pa_mix( size_t length, const pa_sample_spec *spec, const pa_cvolume *volume, - int mute); + pa_bool_t mute); void pa_volume_memchunk( pa_memchunk*c, diff --git a/src/tests/mix-test.c b/src/tests/mix-test.c new file mode 100644 index 000000000..d07b1b0c6 --- /dev/null +++ b/src/tests/mix-test.c @@ -0,0 +1,261 @@ +/* $Id: resampler-test.c 2037 2007-11-09 02:45:07Z lennart $ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +static float swap_float(float a) { + uint32_t *b = (uint32_t*) &a; + *b = PA_UINT32_SWAP(*b); + return a; +} + +static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) { + void *d; + unsigned i; + + d = pa_memblock_acquire(chunk->memblock); + + switch (ss->format) { + + case PA_SAMPLE_U8: + case PA_SAMPLE_ULAW: + case PA_SAMPLE_ALAW: { + uint8_t *u = d; + + for (i = 0; i < chunk->length / pa_frame_size(ss); i++) + printf("0x%02x ", *(u++)); + + break; + } + + case PA_SAMPLE_S16NE: + case PA_SAMPLE_S16RE: { + uint16_t *u = d; + + for (i = 0; i < chunk->length / pa_frame_size(ss); i++) + printf("0x%04x ", *(u++)); + + break; + } + + case PA_SAMPLE_S32NE: + case PA_SAMPLE_S32RE: { + uint32_t *u = d; + + for (i = 0; i < chunk->length / pa_frame_size(ss); i++) + printf("0x%08x ", *(u++)); + + break; + } + + case PA_SAMPLE_FLOAT32NE: + case PA_SAMPLE_FLOAT32RE: { + float *u = d; + + for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { + printf("%1.5f ", ss->format == PA_SAMPLE_FLOAT32NE ? *u : swap_float(*u)); + u++; + } + + break; + } + + default: + pa_assert_not_reached(); + } + + printf("\n"); + + pa_memblock_release(chunk->memblock); +} + +static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) { + pa_memblock *r; + void *d; + unsigned i; + + pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10)); + d = pa_memblock_acquire(r); + + switch (ss->format) { + + case PA_SAMPLE_U8: + case PA_SAMPLE_ULAW: + case PA_SAMPLE_ALAW: { + uint8_t *u = d; + + u[0] = 0x00; + u[1] = 0xFF; + u[2] = 0x7F; + u[3] = 0x80; + u[4] = 0x9f; + u[5] = 0x3f; + u[6] = 0x1; + u[7] = 0xF0; + u[8] = 0x20; + u[9] = 0x21; + break; + } + + case PA_SAMPLE_S16NE: + case PA_SAMPLE_S16RE: { + uint16_t *u = d; + + u[0] = 0x0000; + u[1] = 0xFFFF; + u[2] = 0x7FFF; + u[3] = 0x8000; + u[4] = 0x9fff; + u[5] = 0x3fff; + u[6] = 0x1; + u[7] = 0xF000; + u[8] = 0x20; + u[9] = 0x21; + break; + } + + case PA_SAMPLE_S32NE: + case PA_SAMPLE_S32RE: { + uint32_t *u = d; + + u[0] = 0x00000001; + u[1] = 0xFFFF0002; + u[2] = 0x7FFF0003; + u[3] = 0x80000004; + u[4] = 0x9fff0005; + u[5] = 0x3fff0006; + u[6] = 0x10007; + u[7] = 0xF0000008; + u[8] = 0x200009; + u[9] = 0x21000A; + break; + } + + case PA_SAMPLE_FLOAT32NE: + case PA_SAMPLE_FLOAT32RE: { + float *u = d; + + u[0] = 0.0; + u[1] = -1.0; + u[2] = 1.0; + u[3] = 4711; + u[4] = 0.222; + u[5] = 0.33; + u[6] = -.3; + u[7] = 99; + u[8] = -0.555; + u[9] = -.123; + + if (ss->format == PA_SAMPLE_FLOAT32RE) + for (i = 0; i < 10; i++) + u[i] = swap_float(u[i]); + + break; + } + + default: + pa_assert_not_reached(); + } + + pa_memblock_release(r); + + return r; +} + +int main(int argc, char *argv[]) { + pa_mempool *pool; + pa_sample_spec a; + pa_cvolume v; + + oil_init(); + pa_log_set_maximal_level(PA_LOG_DEBUG); + + pa_assert_se(pool = pa_mempool_new(FALSE)); + + a.channels = 1; + a.rate = 44100; + + v.channels = a.channels; + v.values[0] = pa_sw_volume_from_linear(0.9); + + for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) { + pa_memchunk i, j, k; + pa_mix_info m[2]; + void *ptr; + + printf("=== mixing: %s\n", pa_sample_format_to_string(a.format)); + + /* Generate block */ + i.memblock = generate_block(pool, &a); + i.length = pa_memblock_get_length(i.memblock); + i.index = 0; + + /* Make a copy */ + j = i; + pa_memblock_ref(j.memblock); + pa_memchunk_make_writable(&j, 0); + + /* Adjust volume of the copy */ + pa_volume_memchunk(&j, &a, &v); + + m[0].chunk = i; + m[0].volume.values[0] = PA_VOLUME_NORM; + m[0].volume.channels = a.channels; + m[1].chunk = j; + m[1].volume.values[0] = PA_VOLUME_NORM; + m[1].volume.channels = a.channels; + + k.memblock = pa_memblock_new(pool, i.length); + k.length = i.length; + k.index = 0; + + ptr = (uint8_t*) pa_memblock_acquire(k.memblock) + k.index; + pa_mix(m, 2, ptr, k.length, &a, NULL, FALSE); + pa_memblock_release(k.memblock); + + dump_block(&a, &i); + dump_block(&a, &j); + dump_block(&a, &k); + + pa_memblock_unref(i.memblock); + pa_memblock_unref(j.memblock); + pa_memblock_unref(k.memblock); + } + + pa_mempool_free(pool); + + return 0; +} From d8e0c1c6bdb4fbfcc69d080ca78d76403f9e8760 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 18:24:09 +0000 Subject: [PATCH 1443/1514] minor typo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2042 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/sample.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulse/sample.h b/src/pulse/sample.h index 2c13f57d9..8f9f1733d 100644 --- a/src/pulse/sample.h +++ b/src/pulse/sample.h @@ -50,7 +50,7 @@ * \li PA_SAMPLE_ALAW - 8 bit a-Law. * \li PA_SAMPLE_ULAW - 8 bit mu-Law. * \li PA_SAMPLE_S32LE - Signed 32 bit integer PCM, little endian. - * \li PA_SAMPLE_S32BE - Signed 32 bit integer PCM, big endian. + * \li PA_SAMPLE_S32BE - Signed 32 bit integer PCM, big endian. * * The floating point sample formats have the range from -1 to 1. * From e313fe1b3d0d9f9945c41c151d72edbe9cf1ec54 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 18:25:40 +0000 Subject: [PATCH 1444/1514] tag modules that may only be loaded once at most especially, and enforce that in the module loader git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2043 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/dumpmodules.c | 1 + src/modules/gconf/module-gconf.c | 8 +++---- src/modules/module-alsa-sink.c | 9 ++++---- src/modules/module-alsa-source.c | 9 ++++---- src/modules/module-cli.c | 9 ++++---- src/modules/module-combine.c | 9 ++++---- src/modules/module-default-device-restore.c | 10 ++++----- src/modules/module-defs.h.m4 | 3 +++ src/modules/module-detect.c | 9 ++++---- src/modules/module-esound-compat-spawnfd.c | 9 ++++---- src/modules/module-esound-compat-spawnpid.c | 9 ++++---- src/modules/module-esound-sink.c | 9 ++++---- src/modules/module-hal-detect.c | 13 ++++++----- src/modules/module-jack-sink.c | 9 ++++---- src/modules/module-jack-source.c | 9 ++++---- src/modules/module-ladspa-sink.c | 9 ++++---- src/modules/module-lirc.c | 9 ++++---- src/modules/module-match.c | 11 +++++---- src/modules/module-mmkbd-evdev.c | 9 ++++---- src/modules/module-native-protocol-fd.c | 7 +++--- src/modules/module-null-sink.c | 9 ++++---- src/modules/module-oss.c | 9 ++++---- src/modules/module-pipe-sink.c | 9 ++++---- src/modules/module-pipe-source.c | 9 ++++---- src/modules/module-protocol-stub.c | 25 +++++++++++---------- src/modules/module-remap-sink.c | 9 ++++---- src/modules/module-rescue-streams.c | 7 +++--- src/modules/module-sine.c | 10 ++++----- src/modules/module-suspend-on-idle.c | 7 +++--- src/modules/module-tunnel.c | 13 ++++++----- src/modules/module-volume-restore.c | 9 ++++---- src/modules/module-x11-bell.c | 9 ++++---- src/modules/module-x11-publish.c | 9 ++++---- src/modules/module-x11-xsmp.c | 7 +++--- src/modules/module-zeroconf-discover.c | 7 +++--- src/modules/module-zeroconf-publish.c | 9 ++++---- src/modules/rtp/module-rtp-recv.c | 9 ++++---- src/modules/rtp/module-rtp-send.c | 9 ++++---- src/pulsecore/modinfo.c | 5 +++++ src/pulsecore/modinfo.h | 2 ++ src/pulsecore/module.c | 18 +++++++++++++++ src/pulsecore/module.h | 23 +++++++++++++++---- 42 files changed, 233 insertions(+), 160 deletions(-) diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c index ad7fab20f..68236c70e 100644 --- a/src/daemon/dumpmodules.c +++ b/src/daemon/dumpmodules.c @@ -71,6 +71,7 @@ static void long_info(const char *name, const char *path, pa_modinfo *i) { printf("Author: %s\n", i->author); if (i->usage) printf("Usage: %s\n", i->usage); + printf("Load Once: %s\n", pa_yes_no(i->load_once)); } if (path) diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index 799bdfbdf..fa9ab1ccf 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -53,10 +53,10 @@ #include "module-gconf-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("GConf Adapter") -PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("") +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("GConf Adapter"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); #define MAX_MODULES 10 #define BUF_MAX 2048 diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 88594cdaf..636b413c3 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -50,9 +50,10 @@ #include "alsa-util.h" #include "module-alsa-sink-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("ALSA Sink") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("ALSA Sink"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "sink_name= " "device= " @@ -62,7 +63,7 @@ PA_MODULE_USAGE( "fragments= " "fragment_size= " "channel_map= " - "mmap=") + "mmap="); #define DEFAULT_DEVICE "default" diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index a862657f8..1a6113a7f 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -51,9 +51,10 @@ #include "alsa-util.h" #include "module-alsa-source-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("ALSA Source") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("ALSA Source"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "source_name= " "device= " @@ -63,7 +64,7 @@ PA_MODULE_USAGE( "fragments= " "fragment_size= " "channel_map= " - "mmap=") + "mmap="); #define DEFAULT_DEVICE "default" diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c index 84125214b..71df5a0fb 100644 --- a/src/modules/module-cli.c +++ b/src/modules/module-cli.c @@ -38,10 +38,11 @@ #include "module-cli-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Command line interface") -PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("exit_on_eof=") +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Command line interface"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE("exit_on_eof="); static const char* const valid_modargs[] = { "exit_on_eof", diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index aca4ba32a..dd81653c0 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -50,9 +50,10 @@ #include "module-combine-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Combine multiple sinks to one") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Combine multiple sinks to one"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "sink_name= " "master= " @@ -62,7 +63,7 @@ PA_MODULE_USAGE( "format= " "channels= " "rate= " - "channel_map=") + "channel_map="); #define DEFAULT_SINK_NAME "combined" #define MEMBLOCKQ_MAXLENGTH (1024*170) diff --git a/src/modules/module-default-device-restore.c b/src/modules/module-default-device-restore.c index a816eae88..b550ae789 100644 --- a/src/modules/module-default-device-restore.c +++ b/src/modules/module-default-device-restore.c @@ -32,9 +32,10 @@ #include "module-default-device-restore-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Automatically restore the default sink and source") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Automatically restore the default sink and source"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); #define DEFAULT_SINK_FILE "default-sink" #define DEFAULT_SOURCE_FILE "default-source" @@ -98,6 +99,3 @@ void pa__done(pa_module*m) { fclose(f); } } - - - diff --git a/src/modules/module-defs.h.m4 b/src/modules/module-defs.h.m4 index 5bff748e3..a49e8329a 100644 --- a/src/modules/module-defs.h.m4 +++ b/src/modules/module-defs.h.m4 @@ -10,6 +10,7 @@ define(`gen_symbol', `#define $1 'module_name`_LTX_$1')dnl #include #include +#include gen_symbol(pa__init) gen_symbol(pa__done) @@ -17,6 +18,7 @@ gen_symbol(pa__get_author) gen_symbol(pa__get_description) gen_symbol(pa__get_usage) gen_symbol(pa__get_version) +gen_symbol(pa__load_once) int pa__init(pa_module*m); void pa__done(pa_module*m); @@ -25,5 +27,6 @@ const char* pa__get_author(void); const char* pa__get_description(void); const char* pa__get_usage(void); const char* pa__get_version(void); +pa_bool_t pa__load_once(void); #endif diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 7dc252434..956659314 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -47,10 +47,11 @@ #include "module-detect-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") -PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("just-one=") +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE("just-one="); static const char* const valid_modargs[] = { "just-one", diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c index f0f73fcf3..8321192be 100644 --- a/src/modules/module-esound-compat-spawnfd.c +++ b/src/modules/module-esound-compat-spawnfd.c @@ -37,10 +37,11 @@ #include "module-esound-compat-spawnfd-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("ESOUND compatibility module: -spawnfd emulation") -PA_MODULE_USAGE("fd=") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("ESOUND compatibility module: -spawnfd emulation"); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_USAGE("fd="); static const char* const valid_modargs[] = { "fd", diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c index 6562fe281..67f0a2312 100644 --- a/src/modules/module-esound-compat-spawnpid.c +++ b/src/modules/module-esound-compat-spawnpid.c @@ -37,10 +37,11 @@ #include "module-esound-compat-spawnpid-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("ESOUND compatibility module: -spawnpid emulation") -PA_MODULE_USAGE("pid=") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("ESOUND compatibility module: -spawnpid emulation"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE("pid="); static const char* const valid_modargs[] = { "pid", diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index b18d32581..f9bea63d7 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -64,15 +64,16 @@ #include "module-esound-sink-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("ESOUND Sink") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("ESOUND Sink"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "sink_name= " "server=
        cookie= " "format= " "channels= " - "rate=") + "rate="); #define DEFAULT_SINK_NAME "esound_out" diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index a8ca7df36..00b66c16c 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -53,15 +53,16 @@ #include "dbus-util.h" #include "module-hal-detect-symdef.h" -PA_MODULE_AUTHOR("Shahms King") -PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Shahms King"); +PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); #if defined(HAVE_ALSA) && defined(HAVE_OSS) -PA_MODULE_USAGE("api=") +PA_MODULE_USAGE("api="); #elif defined(HAVE_ALSA) -PA_MODULE_USAGE("api=") +PA_MODULE_USAGE("api="); #elif defined(HAVE_OSS) -PA_MODULE_USAGE("api=") +PA_MODULE_USAGE("api="); #endif struct device { diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 840867ce1..44da068f3 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -64,16 +64,17 @@ * source support in JACK. */ -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("JACK Sink") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("JACK Sink"); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_VERSION(PACKAGE_VERSION); PA_MODULE_USAGE( "sink_name= " "server_name= " "client_name= " "channels= " "connect= " - "channel_map=") + "channel_map="); #define DEFAULT_SINK_NAME "jack_out" diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 380f87ebe..936180205 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -54,16 +54,17 @@ /* See module-jack-sink for a few comments how this module basically * works */ -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("JACK Source") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("JACK Source"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); PA_MODULE_USAGE( "source_name= " "server_name= " "client_name= " "channels= " "connect=" - "channel_map=") + "channel_map="); #define DEFAULT_SOURCE_NAME "jack_in" diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c index 6ed392cea..50cdc4595 100644 --- a/src/modules/module-ladspa-sink.c +++ b/src/modules/module-ladspa-sink.c @@ -45,9 +45,10 @@ #include "module-ladspa-sink-symdef.h" #include "ladspa.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Virtual LADSPA sink") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Virtual LADSPA sink"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "sink_name= " "master= " @@ -57,7 +58,7 @@ PA_MODULE_USAGE( "channel_map= " "plugin= " "label= " - "control=") + "control="); struct userdata { pa_core *core; diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index 21d93837c..245421727 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -43,10 +43,11 @@ #include "module-lirc-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("LIRC volume control") -PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("config= sink= appname=") +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("LIRC volume control"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE("config= sink= appname="); static const char* const valid_modargs[] = { "config", diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 0155b2af6..ed5f30763 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -46,10 +46,11 @@ #include "module-match-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Playback stream expression matching module") -PA_MODULE_USAGE("table=") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Playback stream expression matching module"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE("table="); #define WHITESPACE "\n\r \t" @@ -241,5 +242,3 @@ void pa__done(pa_module*m) { pa_xfree(u); } - - diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index 47a106456..03c0e9734 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -46,10 +46,11 @@ #include "module-mmkbd-evdev-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Multimedia keyboard support via Linux evdev") -PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("device= sink=") +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Multimedia keyboard support via Linux evdev"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE("device= sink="); #define DEFAULT_DEVICE "/dev/input/event0" diff --git a/src/modules/module-native-protocol-fd.c b/src/modules/module-native-protocol-fd.c index 2ef61c88e..53f418960 100644 --- a/src/modules/module-native-protocol-fd.c +++ b/src/modules/module-native-protocol-fd.c @@ -37,9 +37,10 @@ #include "module-native-protocol-fd-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Native protocol autospawn helper") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Native protocol autospawn helper"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); static const char* const valid_modargs[] = { "fd", diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 3a4edec70..de35fff99 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -51,16 +51,17 @@ #include "module-null-sink-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Clocked NULL sink") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Clocked NULL sink"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "format= " "channels= " "rate= " "sink_name=" "channel_map=" - "description=") + "description="); #define DEFAULT_SINK_NAME "null" diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 51ab8a853..a44ad0834 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -76,9 +76,10 @@ #include "oss-util.h" #include "module-oss-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("OSS Sink/Source") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("OSS Sink/Source"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "sink_name= " "source_name= " @@ -91,7 +92,7 @@ PA_MODULE_USAGE( "fragments= " "fragment_size= " "channel_map= " - "mmap=") + "mmap="); #define DEFAULT_DEVICE "/dev/dsp" diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 757484745..e720c8ad2 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -50,16 +50,17 @@ #include "module-pipe-sink-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("UNIX pipe sink") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("UNIX pipe sink"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "sink_name= " "file= " "format= " "channels= " "rate=" - "channel_map=") + "channel_map="); #define DEFAULT_FILE_NAME "/tmp/music.output" #define DEFAULT_SINK_NAME "fifo_output" diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index 45708c687..029356490 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -49,16 +49,17 @@ #include "module-pipe-source-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("UNIX pipe source") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("UNIX pipe source"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "source_name= " "file= " "format= " "channels= " "rate= " - "channel_map=") + "channel_map="); #define DEFAULT_FILE_NAME "/tmp/music.input" #define DEFAULT_SOURCE_NAME "fifo_input" diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 6bd780797..207e266e7 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -76,7 +76,7 @@ #else #include "module-simple-protocol-unix-symdef.h" #endif - PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION) +PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION); PA_MODULE_USAGE("rate= " "format= " "channels= " @@ -84,7 +84,7 @@ "source= " "playback= " "record= " - SOCKET_USAGE) + SOCKET_USAGE); #elif defined(USE_PROTOCOL_CLI) #include #define protocol_new pa_protocol_cli_new @@ -98,8 +98,8 @@ #else #include "module-cli-protocol-unix-symdef.h" #endif - PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION) - PA_MODULE_USAGE(SOCKET_USAGE) + PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION); + PA_MODULE_USAGE(SOCKET_USAGE); #elif defined(USE_PROTOCOL_HTTP) #include #define protocol_new pa_protocol_http_new @@ -113,8 +113,8 @@ #else #include "module-http-protocol-unix-symdef.h" #endif - PA_MODULE_DESCRIPTION("HTTP "SOCKET_DESCRIPTION) - PA_MODULE_USAGE(SOCKET_USAGE) + PA_MODULE_DESCRIPTION("HTTP "SOCKET_DESCRIPTION); + PA_MODULE_USAGE(SOCKET_USAGE); #elif defined(USE_PROTOCOL_NATIVE) #include #define protocol_new pa_protocol_native_new @@ -140,11 +140,11 @@ #define AUTH_USAGE #endif - PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION) + PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION); PA_MODULE_USAGE("auth-anonymous= " "cookie= " AUTH_USAGE - SOCKET_USAGE) + SOCKET_USAGE); #elif defined(USE_PROTOCOL_ESOUND) #include #include @@ -167,19 +167,20 @@ #define AUTH_USAGE #endif - PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION) + PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION); PA_MODULE_USAGE("sink= " "source= " "auth-anonymous= " "cookie= " AUTH_USAGE - SOCKET_USAGE) + SOCKET_USAGE); #else #error "Broken build system" #endif -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_VERSION(PACKAGE_VERSION); static const char* const valid_modargs[] = { MODULE_ARGUMENTS diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c index e863c0c37..39a9245d6 100644 --- a/src/modules/module-remap-sink.c +++ b/src/modules/module-remap-sink.c @@ -40,9 +40,10 @@ #include "module-remap-sink-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Virtual channel remapping sink") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Virtual channel remapping sink"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "sink_name= " "master= " @@ -50,7 +51,7 @@ PA_MODULE_USAGE( "format= " "channels= " "rate= " - "channel_map=") + "channel_map="); struct userdata { pa_core *core; diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c index 5cabef762..12957c9d8 100644 --- a/src/modules/module-rescue-streams.c +++ b/src/modules/module-rescue-streams.c @@ -36,9 +36,10 @@ #include "module-rescue-streams-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("When a sink/source is removed, try to move their streams to the default sink/source") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("When a sink/source is removed, try to move their streams to the default sink/source"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); static const char* const valid_modargs[] = { NULL, diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index 65b8ee7f8..41d9a51c7 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -39,10 +39,11 @@ #include "module-sine-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Sine wave generator") -PA_MODULE_USAGE("sink= frequency=") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Sine wave generator"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE("sink= frequency="); struct userdata { pa_core *core; @@ -203,4 +204,3 @@ void pa__done(pa_module*m) { pa_xfree(u); } - diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c index 5a7113903..4746e2b77 100644 --- a/src/modules/module-suspend-on-idle.c +++ b/src/modules/module-suspend-on-idle.c @@ -37,9 +37,10 @@ #include "module-suspend-on-idle-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("When a sink/source is idle for too long, suspend it") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("When a sink/source is idle for too long, suspend it"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); static const char* const valid_modargs[] = { "timeout", diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index edc03c99c..05cece7d0 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -59,7 +59,8 @@ #ifdef TUNNEL_SINK #include "module-tunnel-sink-symdef.h" -PA_MODULE_DESCRIPTION("Tunnel module for sinks") +PA_MODULE_DESCRIPTION("Tunnel module for sinks"); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "server=
        " "sink= " @@ -68,10 +69,10 @@ PA_MODULE_USAGE( "channels= " "rate= " "sink_name= " - "channel_map=") + "channel_map="); #else #include "module-tunnel-source-symdef.h" -PA_MODULE_DESCRIPTION("Tunnel module for sources") +PA_MODULE_DESCRIPTION("Tunnel module for sources"); PA_MODULE_USAGE( "server=
        " "source= " @@ -80,11 +81,11 @@ PA_MODULE_USAGE( "channels= " "rate= " "source_name= " - "channel_map=") + "channel_map="); #endif -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_VERSION(PACKAGE_VERSION); #define DEFAULT_TLENGTH_MSEC 100 #define DEFAULT_MINREQ_MSEC 10 diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 8ef72b2a2..422bc7f23 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -48,10 +48,11 @@ #include "module-volume-restore-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Automatically restore the volume and the devices of streams") -PA_MODULE_USAGE("table=") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Automatically restore the volume and the devices of streams"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE("table="); #define WHITESPACE "\n\r \t" diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index 4eacbb1e1..87c6849da 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -44,10 +44,11 @@ #include "module-x11-bell-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("X11 Bell interceptor") -PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("sink= sample= display=") +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("X11 Bell interceptor"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE("sink= sample= display="); struct userdata { pa_core *core; diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index f350126ad..429c2a69c 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -53,10 +53,11 @@ #include "module-x11-publish-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("X11 Credential Publisher") -PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("display=") +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("X11 Credential Publisher"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE("display="); static const char* const valid_modargs[] = { "display", diff --git a/src/modules/module-x11-xsmp.c b/src/modules/module-x11-xsmp.c index 3e353caf0..e9efa0965 100644 --- a/src/modules/module-x11-xsmp.c +++ b/src/modules/module-x11-xsmp.c @@ -45,9 +45,10 @@ #include "module-x11-xsmp-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("X11 session management") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("X11 session management"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); static int ice_in_use = 0; diff --git a/src/modules/module-zeroconf-discover.c b/src/modules/module-zeroconf-discover.c index e49037183..061560c86 100644 --- a/src/modules/module-zeroconf-discover.c +++ b/src/modules/module-zeroconf-discover.c @@ -53,9 +53,10 @@ #include "module-zeroconf-discover-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Discovery") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Discovery"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); #define SERVICE_TYPE_SINK "_pulse-sink._tcp" #define SERVICE_TYPE_SOURCE "_non-monitor._sub._pulse-source._tcp" diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c index 818a1b285..46969a244 100644 --- a/src/modules/module-zeroconf-publish.c +++ b/src/modules/module-zeroconf-publish.c @@ -52,10 +52,11 @@ #include "module-zeroconf-publish-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher") -PA_MODULE_VERSION(PACKAGE_VERSION) -PA_MODULE_USAGE("port=") +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE("port="); #define SERVICE_TYPE_SINK "_pulse-sink._tcp" #define SERVICE_TYPE_SOURCE "_pulse-source._tcp" diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 6c0189312..d8e7a7816 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -58,13 +58,14 @@ #include "sdp.h" #include "sap.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Recieve data from a network via RTP/SAP/SDP") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Recieve data from a network via RTP/SAP/SDP"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "sink= " "sap_address= " -) +); #define SAP_PORT 9875 #define DEFAULT_SAP_ADDRESS "224.0.0.56" diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index f36989bdd..d7c50578c 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -57,9 +57,10 @@ #include "sdp.h" #include "sap.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Read data from source and send it to the network via RTP/SAP/SDP") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Read data from source and send it to the network via RTP/SAP/SDP"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "source= " "format= " @@ -69,7 +70,7 @@ PA_MODULE_USAGE( "port= " "mtu= " "loop=" -) +); #define DEFAULT_PORT 46000 #define SAP_PORT 9875 diff --git a/src/pulsecore/modinfo.c b/src/pulsecore/modinfo.c index da2df6535..d1a78fbb1 100644 --- a/src/pulsecore/modinfo.c +++ b/src/pulsecore/modinfo.c @@ -40,10 +40,12 @@ #define PA_SYMBOL_DESCRIPTION "pa__get_description" #define PA_SYMBOL_USAGE "pa__get_usage" #define PA_SYMBOL_VERSION "pa__get_version" +#define PA_SYMBOL_LOAD_ONCE "pa__load_once" pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl, const char *module_name) { pa_modinfo *i; const char* (*func)(void); + pa_bool_t (*func2) (void); pa_assert(dl); @@ -61,6 +63,9 @@ pa_modinfo *pa_modinfo_get_by_handle(lt_dlhandle dl, const char *module_name) { if ((func = (const char* (*)(void)) pa_load_sym(dl, module_name, PA_SYMBOL_VERSION))) i->version = pa_xstrdup(func()); + if ((func2 = (pa_bool_t (*)(void)) pa_load_sym(dl, module_name, PA_SYMBOL_LOAD_ONCE))) + i->load_once = func2(); + return i; } diff --git a/src/pulsecore/modinfo.h b/src/pulsecore/modinfo.h index 02e536c66..da6d5428b 100644 --- a/src/pulsecore/modinfo.h +++ b/src/pulsecore/modinfo.h @@ -25,12 +25,14 @@ ***/ /* Some functions for reading module meta data from PulseAudio modules */ +#include typedef struct pa_modinfo { char *author; char *description; char *usage; char *version; + pa_bool_t load_once; } pa_modinfo; /* Read meta data from an libtool handle */ diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index dce91a710..e1680de5f 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -46,6 +46,7 @@ #define PA_SYMBOL_INIT "pa__init" #define PA_SYMBOL_DONE "pa__done" +#define PA_SYMBOL_LOAD_ONCE "pa__load_once" #define UNLOAD_POLL_TIME 2 @@ -66,6 +67,7 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { pa_module *m = NULL; + pa_bool_t (*load_once)(void); pa_assert(c); pa_assert(name); @@ -82,6 +84,22 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { goto fail; } + if ((load_once = (pa_bool_t (*)(void)) pa_load_sym(m->dl, name, PA_SYMBOL_LOAD_ONCE))) { + + if (load_once()) { + pa_module *i; + uint32_t idx; + /* OK, the module only wants to be loaded once, let's make sure it is */ + + for (i = pa_idxset_first(c->modules, &idx); i; i = pa_idxset_next(c->modules, &idx)) { + if (strcmp(name, i->name) == 0) { + pa_log("Module \"%s\" should be loaded once at most. Refusing to load.", name); + goto fail; + } + } + } + } + if (!(m->init = (int (*)(pa_module*_m)) pa_load_sym(m->dl, name, PA_SYMBOL_INIT))) { pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name); goto fail; diff --git a/src/pulsecore/module.h b/src/pulsecore/module.h index 7a93a071a..25f122d16 100644 --- a/src/pulsecore/module.h +++ b/src/pulsecore/module.h @@ -62,10 +62,25 @@ void pa_module_unload_request(pa_module *m); void pa_module_set_used(pa_module*m, int used); -#define PA_MODULE_AUTHOR(s) const char *pa__get_author(void) { return s; } -#define PA_MODULE_DESCRIPTION(s) const char *pa__get_description(void) { return s; } -#define PA_MODULE_USAGE(s) const char *pa__get_usage(void) { return s; } -#define PA_MODULE_VERSION(s) const char * pa__get_version(void) { return s; } +#define PA_MODULE_AUTHOR(s) \ + const char *pa__get_author(void) { return s; } \ + struct __stupid_useless_struct_to_allow_trailing_semicolon + +#define PA_MODULE_DESCRIPTION(s) \ + const char *pa__get_description(void) { return s; } \ + struct __stupid_useless_struct_to_allow_trailing_semicolon + +#define PA_MODULE_USAGE(s) \ + const char *pa__get_usage(void) { return s; } \ + struct __stupid_useless_struct_to_allow_trailing_semicolon + +#define PA_MODULE_VERSION(s) \ + const char * pa__get_version(void) { return s; } \ + struct __stupid_useless_struct_to_allow_trailing_semicolon + +#define PA_MODULE_LOAD_ONCE(b) \ + pa_bool_t pa__load_once(void) { return b; } \ + struct __stupid_useless_struct_to_allow_trailing_semicolon pa_modinfo *pa_module_get_info(pa_module *m); From f873a2a22441d5eaacc5cbb502cbde829ee30a73 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Nov 2007 02:30:59 +0000 Subject: [PATCH 1445/1514] add a simple fully-automatic fully-linearupmixer/downmixer and enable it by default git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2044 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 8 +- src/pulsecore/resampler.c | 566 ++++++++++++++++++++++++++++++---- src/pulsecore/resampler.h | 8 +- src/pulsecore/sink-input.c | 4 +- src/pulsecore/source-output.c | 4 +- src/tests/remix-test.c | 91 ++++++ src/tests/resampler-test.c | 4 +- 7 files changed, 615 insertions(+), 70 deletions(-) create mode 100644 src/tests/remix-test.c diff --git a/src/Makefile.am b/src/Makefile.am index 8fe7be9da..1a24a5293 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -240,7 +240,8 @@ noinst_PROGRAMS = \ sig2str-test \ resampler-test \ smoother-test \ - mix-test + mix-test \ + remix-test if HAVE_SIGXCPU noinst_PROGRAMS += \ @@ -395,6 +396,11 @@ mix_test_LDADD = $(AM_LDADD) libpulsecore.la mix_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) mix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) +remix_test_SOURCES = tests/remix-test.c +remix_test_LDADD = $(AM_LDADD) libpulsecore.la +remix_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) +remix_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS) + smoother_test_SOURCES = tests/smoother-test.c smoother_test_LDADD = $(AM_LDADD) libpulsecore.la smoother_test_CFLAGS = $(AM_CFLAGS) diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index eebc9c046..429759f04 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "speexwrap.h" @@ -49,7 +50,9 @@ #define EXTRA_SAMPLES 128 struct pa_resampler { - pa_resample_method_t resample_method; + pa_resample_method_t method; + pa_resample_flags_t flags; + pa_sample_spec i_ss, o_ss; pa_channel_map i_cm, o_cm; size_t i_fz, o_fz, w_sz; @@ -63,8 +66,8 @@ struct pa_resampler { pa_convert_func_t to_work_format_func; pa_convert_func_t from_work_format_func; - int map_table[PA_CHANNELS_MAX][PA_CHANNELS_MAX]; - int map_required; + float map_table[PA_CHANNELS_MAX][PA_CHANNELS_MAX]; + pa_bool_t map_required; void (*impl_free)(pa_resampler *r); void (*impl_update_rates)(pa_resampler *r); @@ -159,8 +162,8 @@ pa_resampler* pa_resampler_new( const pa_channel_map *am, const pa_sample_spec *b, const pa_channel_map *bm, - pa_resample_method_t resample_method, - int variable_rate) { + pa_resample_method_t method, + pa_resample_flags_t flags) { pa_resampler *r = NULL; @@ -169,37 +172,38 @@ pa_resampler* pa_resampler_new( pa_assert(b); pa_assert(pa_sample_spec_valid(a)); pa_assert(pa_sample_spec_valid(b)); - pa_assert(resample_method >= 0); - pa_assert(resample_method < PA_RESAMPLER_MAX); + pa_assert(method >= 0); + pa_assert(method < PA_RESAMPLER_MAX); /* Fix method */ - if (!variable_rate && a->rate == b->rate) { + if (!(flags & PA_RESAMPLER_VARIABLE_RATE) && a->rate == b->rate) { pa_log_info("Forcing resampler 'copy', because of fixed, identical sample rates."); - resample_method = PA_RESAMPLER_COPY; + method = PA_RESAMPLER_COPY; } - if (!pa_resample_method_supported(resample_method)) { - pa_log_warn("Support for resampler '%s' not compiled in, reverting to 'auto'.", pa_resample_method_to_string(resample_method)); - resample_method = PA_RESAMPLER_AUTO; + if (!pa_resample_method_supported(method)) { + pa_log_warn("Support for resampler '%s' not compiled in, reverting to 'auto'.", pa_resample_method_to_string(method)); + method = PA_RESAMPLER_AUTO; } - if (resample_method == PA_RESAMPLER_FFMPEG && variable_rate) { + if (method == PA_RESAMPLER_FFMPEG && (flags & PA_RESAMPLER_VARIABLE_RATE)) { pa_log_info("Resampler 'ffmpeg' cannot do variable rate, reverting to resampler 'auto'."); - resample_method = PA_RESAMPLER_AUTO; + method = PA_RESAMPLER_AUTO; } - if (resample_method == PA_RESAMPLER_COPY && (variable_rate || a->rate != b->rate)) { + if (method == PA_RESAMPLER_COPY && ((flags & PA_RESAMPLER_VARIABLE_RATE) || a->rate != b->rate)) { pa_log_info("Resampler 'copy' cannot change sampling rate, reverting to resampler 'auto'."); - resample_method = PA_RESAMPLER_AUTO; + method = PA_RESAMPLER_AUTO; } - if (resample_method == PA_RESAMPLER_AUTO) - resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3; + if (method == PA_RESAMPLER_AUTO) + method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3; r = pa_xnew(pa_resampler, 1); r->mempool = pool; - r->resample_method = resample_method; + r->method = method; + r->flags = flags; r->impl_free = NULL; r->impl_update_rates = NULL; @@ -231,12 +235,12 @@ pa_resampler* pa_resampler_new( calc_map_table(r); - pa_log_info("Using resampler '%s'", pa_resample_method_to_string(resample_method)); + pa_log_info("Using resampler '%s'", pa_resample_method_to_string(method)); - if ((resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) || - (resample_method == PA_RESAMPLER_FFMPEG)) + if ((method >= PA_RESAMPLER_SPEEX_FIXED_BASE && method <= PA_RESAMPLER_SPEEX_FIXED_MAX) || + (method == PA_RESAMPLER_FFMPEG)) r->work_format = PA_SAMPLE_S16NE; - else if (resample_method == PA_RESAMPLER_TRIVIAL || resample_method == PA_RESAMPLER_COPY) { + else if (method == PA_RESAMPLER_TRIVIAL || method == PA_RESAMPLER_COPY) { if (r->map_required || a->format != b->format) { @@ -281,7 +285,7 @@ pa_resampler* pa_resampler_new( } /* initialize implementation */ - if (init_table[resample_method](r) < 0) + if (init_table[method](r) < 0) goto fail; return r; @@ -373,7 +377,7 @@ size_t pa_resampler_max_block_size(pa_resampler *r) { pa_resample_method_t pa_resampler_get_method(pa_resampler *r) { pa_assert(r); - return r->resample_method; + return r->method; } static const char * const resample_methods[] = { @@ -449,36 +453,423 @@ pa_resample_method_t pa_parse_resample_method(const char *string) { return PA_RESAMPLER_INVALID; } +static pa_bool_t on_left(pa_channel_position_t p) { + + return + p == PA_CHANNEL_POSITION_FRONT_LEFT || + p == PA_CHANNEL_POSITION_REAR_LEFT || + p == PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER || + p == PA_CHANNEL_POSITION_SIDE_LEFT || + p == PA_CHANNEL_POSITION_TOP_FRONT_LEFT || + p == PA_CHANNEL_POSITION_TOP_REAR_LEFT; +} + +static pa_bool_t on_right(pa_channel_position_t p) { + + return + p == PA_CHANNEL_POSITION_FRONT_RIGHT || + p == PA_CHANNEL_POSITION_REAR_RIGHT || + p == PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER || + p == PA_CHANNEL_POSITION_SIDE_RIGHT || + p == PA_CHANNEL_POSITION_TOP_FRONT_RIGHT || + p == PA_CHANNEL_POSITION_TOP_REAR_RIGHT; +} + +static pa_bool_t on_center(pa_channel_position_t p) { + + return + p == PA_CHANNEL_POSITION_FRONT_CENTER || + p == PA_CHANNEL_POSITION_REAR_CENTER || + p == PA_CHANNEL_POSITION_TOP_CENTER || + p == PA_CHANNEL_POSITION_TOP_FRONT_CENTER || + p == PA_CHANNEL_POSITION_TOP_REAR_CENTER; +} + +static pa_bool_t on_lfe(pa_channel_position_t p) { + return + p == PA_CHANNEL_POSITION_LFE; +} + static void calc_map_table(pa_resampler *r) { - unsigned oc; + unsigned oc, ic; + pa_bool_t ic_connected[PA_CHANNELS_MAX]; + pa_bool_t remix; + pa_strbuf *s; + char *t; pa_assert(r); - if (!(r->map_required = (r->i_ss.channels != r->o_ss.channels || !pa_channel_map_equal(&r->i_cm, &r->o_cm)))) + if (!(r->map_required = (r->i_ss.channels != r->o_ss.channels || (!(r->flags & PA_RESAMPLER_NO_REMAP) && !pa_channel_map_equal(&r->i_cm, &r->o_cm))))) return; + memset(r->map_table, 0, sizeof(r->map_table)); + memset(ic_connected, 0, sizeof(ic_connected)); + remix = (r->flags & (PA_RESAMPLER_NO_REMAP|PA_RESAMPLER_NO_REMIX)) == 0; + for (oc = 0; oc < r->o_ss.channels; oc++) { - unsigned ic, i = 0; + pa_bool_t oc_connected = FALSE; + pa_channel_position_t b = r->o_cm.map[oc]; for (ic = 0; ic < r->i_ss.channels; ic++) { - pa_channel_position_t a, b; + pa_channel_position_t a = r->i_cm.map[ic]; - a = r->i_cm.map[ic]; - b = r->o_cm.map[oc]; + if (r->flags & PA_RESAMPLER_NO_REMAP) { + /* We shall not do any remapping. Hence, just check by index */ - if (a == b || - (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_LEFT) || - (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_RIGHT) || - (a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) || - (a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO)) + if (ic == oc) + r->map_table[oc][ic] = 1.0; - r->map_table[oc][i++] = ic; + continue; + } + + if (r->flags & PA_RESAMPLER_NO_REMIX) { + /* We shall not do any remixing. Hence, just check by name */ + + if (a == b) + r->map_table[oc][ic] = 1.0; + + continue; + } + + pa_assert(remix); + + /* OK, we shall do the full monty: upmixing and + * downmixing. Our algorithm is relatively simple, does + * not do spacialization, delay elements or apply lowpass + * filters for LFE. Patches are always welcome, + * though. Oh, and it doesn't do any matrix + * decoding. (Which probably wouldn't make any sense + * anyway.) + * + * This code is not idempotent: downmixing an upmixed + * stereo stream is not identical to the original. The + * volume will not match, and the two channels will be a + * linear combination of both. + * + * This is losely based on random suggestions found on the + * Internet, such as this: + * http://www.halfgaar.net/surround-sound-in-linux and the + * alsa upmix plugin. + * + * The algorithm works basically like this: + * + * 1) Connect all channels with matching names. + * + * 2) Mono Handling: + * S:Mono: Copy into all D:channels + * D:Mono: Copy in all S:channels + * + * 3) Mix D:Left, D:Right: + * D:Left: If not connected, avg all S:Left + * D:Right: If not connected, avg all S:Right + * + * 4) Mix D:Center + * If not connected, avg all S:Center + * If still not connected, avg all S:Left, S:Right + * + * 5) Mix D:LFE + * If not connected, avg all S:* + * + * 6) Make sure S:Left/S:Right is used: S:Left/S:Right: If + * not connected, mix into all D:left and all D:right + * channels. Gain is 0.1, the current left and right + * should be multiplied by 0.9. + * + * 7) Make sure S:Center, S:LFE is used: + * + * S:Center, S:LFE: If not connected, mix into all + * D:left, all D:right, all D:center channels, gain is + * 0.375. The current (as result of 1..6) factors + * should be multiplied by 0.75. (Alt. suggestion: 0.25 + * vs. 0.5) + * + * S: and D: shall relate to the source resp. destination channels. + * + * Rationale: 1, 2 are probably obvious. For 3: this + * copies front to rear if needed. For 4: we try to find + * some suitable C source for C, if we don't find any, we + * avg L and R. For 5: LFE is mixed from all channels. For + * 6: the rear channels should not be dropped entirely, + * however have only minimal impact. For 7: movies usually + * encode speech on the center channel. Thus we have to + * make sure this channel is distributed to L and R if not + * available in the output. Also, LFE is used to achieve a + * greater dynamic range, and thus we should try to do our + * best to pass it to L+R. + */ + + if (a == b || a == PA_CHANNEL_POSITION_MONO || b == PA_CHANNEL_POSITION_MONO) { + r->map_table[oc][ic] = 1.0; + + oc_connected = TRUE; + ic_connected[ic] = TRUE; + } } - /* Add an end marker */ - if (i < PA_CHANNELS_MAX) - r->map_table[oc][i] = -1; + if (!oc_connected && remix) { + /* OK, we shall remix */ + + if (on_left(b)) { + unsigned n = 0; + + /* We are not connected and on the left side, let's + * average all left side input channels. */ + + for (ic = 0; ic < r->i_ss.channels; ic++) + if (on_left(r->i_cm.map[ic])) + n++; + + if (n > 0) + for (ic = 0; ic < r->i_ss.channels; ic++) + if (on_left(r->i_cm.map[ic])) { + r->map_table[oc][ic] = 1.0 / n; + ic_connected[ic] = TRUE; + } + + /* We ignore the case where there is no left input + * channel. Something is really wrong in this case + * anyway. */ + + } else if (on_right(b)) { + unsigned n = 0; + + /* We are not connected and on the right side, let's + * average all right side input channels. */ + + for (ic = 0; ic < r->i_ss.channels; ic++) + if (on_right(r->i_cm.map[ic])) + n++; + + if (n > 0) + for (ic = 0; ic < r->i_ss.channels; ic++) + if (on_right(r->i_cm.map[ic])) { + r->map_table[oc][ic] = 1.0 / n; + ic_connected[ic] = TRUE; + } + + /* We ignore the case where there is no right input + * channel. Something is really wrong in this case + * anyway. */ + + } else if (on_center(b)) { + unsigned n = 0; + + /* We are not connected and at the center. Let's + * average all center input channels. */ + + for (ic = 0; ic < r->i_ss.channels; ic++) + if (on_center(r->i_cm.map[ic])) + n++; + + if (n > 0) { + for (ic = 0; ic < r->i_ss.channels; ic++) + if (on_center(r->i_cm.map[ic])) { + r->map_table[oc][ic] = 1.0 / n; + ic_connected[ic] = TRUE; + } + } else { + + /* Hmm, no center channel around, let's synthesize + * it by mixing L and R.*/ + + n = 0; + + for (ic = 0; ic < r->i_ss.channels; ic++) + if (on_left(r->i_cm.map[ic]) || on_right(r->i_cm.map[ic])) + n++; + + if (n > 0) + for (ic = 0; ic < r->i_ss.channels; ic++) + if (on_left(r->i_cm.map[ic]) || on_right(r->i_cm.map[ic])) { + r->map_table[oc][ic] = 1.0 / n; + ic_connected[ic] = TRUE; + } + + /* We ignore the case where there is not even a + * left or right input channel. Something is + * really wrong in this case anyway. */ + } + + } else if (on_lfe(b)) { + + /* We are not connected and an LFE. Let's average all + * channels for LFE. */ + + for (ic = 0; ic < r->i_ss.channels; ic++) { + r->map_table[oc][ic] = 1.0 / r->i_ss.channels; + + /* Please note that a channel connected to LFE + * doesn't really count as connected. */ + } + } + } } + + if (remix) { + unsigned + ic_unconnected_left = 0, + ic_unconnected_right = 0, + ic_unconnected_center = 0, + ic_unconnected_lfe = 0; + + for (ic = 0; ic < r->i_ss.channels; ic++) { + pa_channel_position_t a = r->i_cm.map[ic]; + + if (ic_connected[ic]) + continue; + + if (on_left(a)) + ic_unconnected_left++; + else if (on_right(a)) + ic_unconnected_right++; + else if (on_center(a)) + ic_unconnected_center++; + else if (on_lfe(a)) + ic_unconnected_lfe++; + } + + if (ic_unconnected_left > 0) { + + /* OK, so there are unconnected input channels on the + * left. Let's multiply all already connected channels on + * the left side by .9 and add in our averaged unconnected + * channels multplied by .1 */ + + for (oc = 0; oc < r->o_ss.channels; oc++) { + + if (!on_left(r->o_cm.map[oc])) + continue; + + for (ic = 0; ic < r->i_ss.channels; ic++) { + + if (ic_connected[ic]) { + r->map_table[oc][ic] *= .9; + continue; + } + + if (on_left(r->i_cm.map[ic])) + r->map_table[oc][ic] = .1 / ic_unconnected_left; + } + } + } + + if (ic_unconnected_right > 0) { + + /* OK, so there are unconnected input channels on the + * right. Let's multiply all already connected channels on + * the right side by .9 and add in our averaged unconnected + * channels multplied by .1 */ + + for (oc = 0; oc < r->o_ss.channels; oc++) { + + if (!on_right(r->o_cm.map[oc])) + continue; + + for (ic = 0; ic < r->i_ss.channels; ic++) { + + if (ic_connected[ic]) { + r->map_table[oc][ic] *= .9; + continue; + } + + if (on_right(r->i_cm.map[ic])) + r->map_table[oc][ic] = .1 / ic_unconnected_right; + } + } + } + + if (ic_unconnected_center > 0) { + pa_bool_t mixed_in = FALSE; + + /* OK, so there are unconnected input channels on the + * center. Let's multiply all already connected channels on + * the center side by .9 and add in our averaged unconnected + * channels multplied by .1 */ + + for (oc = 0; oc < r->o_ss.channels; oc++) { + + if (!on_center(r->o_cm.map[oc])) + continue; + + for (ic = 0; ic < r->i_ss.channels; ic++) { + + if (ic_connected[ic]) { + r->map_table[oc][ic] *= .9; + continue; + } + + if (on_center(r->i_cm.map[ic])) { + r->map_table[oc][ic] = .1 / ic_unconnected_center; + mixed_in = TRUE; + } + } + } + + if (!mixed_in) { + + /* Hmm, as it appears there was no center channel we + could mix our center channel in. In this case, mix + it into left and right. Using .375 and 0.75 as + factors. */ + + for (oc = 0; oc < r->o_ss.channels; oc++) { + + if (!on_left(r->o_cm.map[oc]) && !on_right(r->o_cm.map[oc])) + continue; + + for (ic = 0; ic < r->i_ss.channels; ic++) { + + if (ic_connected[ic]) { + r->map_table[oc][ic] *= .75; + continue; + } + + if (on_center(r->i_cm.map[ic])) + r->map_table[oc][ic] = .375 / ic_unconnected_center; + } + } + } + } + + if (ic_unconnected_lfe > 0) { + + /* OK, so there is an unconnected LFE channel. Let's mix + * it into all channels, with factor 0.375 */ + + for (ic = 0; ic < r->i_ss.channels; ic++) { + + if (!on_lfe(r->i_cm.map[ic])) + continue; + + for (oc = 0; oc < r->o_ss.channels; oc++) + r->map_table[oc][ic] = 0.375 / ic_unconnected_lfe; + } + } + } + + + s = pa_strbuf_new(); + + pa_strbuf_printf(s, " "); + for (ic = 0; ic < r->i_ss.channels; ic++) + pa_strbuf_printf(s, " I%02u ", ic); + pa_strbuf_puts(s, "\n +"); + + for (ic = 0; ic < r->i_ss.channels; ic++) + pa_strbuf_printf(s, "------"); + pa_strbuf_puts(s, "\n"); + + for (oc = 0; oc < r->o_ss.channels; oc++) { + pa_strbuf_printf(s, "O%02u |", oc); + + for (ic = 0; ic < r->i_ss.channels; ic++) + pa_strbuf_printf(s, " %1.3f", r->map_table[oc][ic]); + + pa_strbuf_puts(s, "\n"); + } + + pa_log_debug("Channel matrix:\n%s", t = pa_strbuf_tostring_free(s)); + pa_xfree(t); } static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) { @@ -518,6 +909,36 @@ static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) return &r->buf1; } +static void vectoradd_s16_with_fraction( + int16_t *d, int dstr, + const int16_t *s1, int sstr1, + const int16_t *s2, int sstr2, + int n, + float s3, float s4) { + + int32_t i3, i4; + + i3 = (int32_t) (s3 * 0x10000); + i4 = (int32_t) (s4 * 0x10000); + + for (; n > 0; n--) { + int32_t a, b; + + a = *s1; + b = *s2; + + a = (a * i3) / 0x10000; + b = (b * i4) / 0x10000; + + *d = (int16_t) (a + b); + + s1 = (const int16_t*) ((const uint8_t*) s1 + sstr1); + s2 = (const int16_t*) ((const uint8_t*) s2 + sstr2); + d = (int16_t*) ((uint8_t*) d + dstr); + + } +} + static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { unsigned in_n_samples, out_n_samples, n_frames; int i_skip, o_skip; @@ -560,16 +981,21 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { case PA_SAMPLE_FLOAT32NE: for (oc = 0; oc < r->o_ss.channels; oc++) { - unsigned i; + unsigned ic; static const float one = 1.0; - for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++) + for (ic = 0; ic < r->i_ss.channels; ic++) { + + if (r->map_table[oc][ic] <= 0.0) + continue; + oil_vectoradd_f32( (float*) dst + oc, o_skip, (float*) dst + oc, o_skip, - (float*) src + r->map_table[oc][i], i_skip, + (float*) src + ic, i_skip, n_frames, - &one, &one); + &one, &r->map_table[oc][ic]); + } } break; @@ -577,16 +1003,32 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { case PA_SAMPLE_S16NE: for (oc = 0; oc < r->o_ss.channels; oc++) { - unsigned i; - static const int16_t one = 1; + unsigned ic; - for (i = 0; i < PA_CHANNELS_MAX && r->map_table[oc][i] >= 0; i++) - oil_vectoradd_s16( - (int16_t*) dst + oc, o_skip, - (int16_t*) dst + oc, o_skip, - (int16_t*) src + r->map_table[oc][i], i_skip, - n_frames, - &one, &one); + for (ic = 0; ic < r->i_ss.channels; ic++) { + + if (r->map_table[oc][ic] <= 0.0) + continue; + + if (r->map_table[oc][ic] >= 1.0) { + static const int16_t one = 1; + + oil_vectoradd_s16( + (int16_t*) dst + oc, o_skip, + (int16_t*) dst + oc, o_skip, + (int16_t*) src + ic, i_skip, + n_frames, + &one, &one); + + } else + + vectoradd_s16_with_fraction( + (int16_t*) dst + oc, o_skip, + (int16_t*) dst + oc, o_skip, + (int16_t*) src + ic, i_skip, + n_frames, + 1.0, r->map_table[oc][ic]); + } } break; @@ -751,7 +1193,7 @@ static int libsamplerate_init(pa_resampler *r) { pa_assert(r); - if (!(r->src.state = src_new(r->resample_method, r->o_ss.channels, &err))) + if (!(r->src.state = src_new(r->method, r->o_ss.channels, &err))) return -1; r->impl_free = libsamplerate_free; @@ -809,10 +1251,10 @@ static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsign static void speex_update_rates(pa_resampler *r) { pa_assert(r); - if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) + if (r->method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->method <= PA_RESAMPLER_SPEEX_FIXED_MAX) pa_assert_se(paspfx_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0); else { - pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); + pa_assert(r->method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); pa_assert_se(paspfl_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0); } } @@ -823,10 +1265,10 @@ static void speex_free(pa_resampler *r) { if (!r->speex.state) return; - if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) + if (r->method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->method <= PA_RESAMPLER_SPEEX_FIXED_MAX) paspfx_resampler_destroy(r->speex.state); else { - pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); + pa_assert(r->method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); paspfl_resampler_destroy(r->speex.state); } } @@ -839,8 +1281,8 @@ static int speex_init(pa_resampler *r) { r->impl_free = speex_free; r->impl_update_rates = speex_update_rates; - if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) { - q = r->resample_method - PA_RESAMPLER_SPEEX_FIXED_BASE; + if (r->method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->method <= PA_RESAMPLER_SPEEX_FIXED_MAX) { + q = r->method - PA_RESAMPLER_SPEEX_FIXED_BASE; pa_log_info("Choosing speex quality setting %i.", q); @@ -849,8 +1291,8 @@ static int speex_init(pa_resampler *r) { r->impl_resample = speex_resample_int; } else { - pa_assert(r->resample_method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); - q = r->resample_method - PA_RESAMPLER_SPEEX_FLOAT_BASE; + pa_assert(r->method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->method <= PA_RESAMPLER_SPEEX_FLOAT_MAX); + q = r->method - PA_RESAMPLER_SPEEX_FLOAT_BASE; pa_log_info("Choosing speex quality setting %i.", q); diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h index 23e1acb76..778c738dd 100644 --- a/src/pulsecore/resampler.h +++ b/src/pulsecore/resampler.h @@ -49,6 +49,12 @@ typedef enum pa_resample_method { PA_RESAMPLER_MAX } pa_resample_method_t; +typedef enum pa_resample_flags { + PA_RESAMPLER_VARIABLE_RATE = 1, + PA_RESAMPLER_NO_REMAP = 2, /* implies NO_REMIX */ + PA_RESAMPLER_NO_REMIX = 4 +} pa_resample_flags_t; + pa_resampler* pa_resampler_new( pa_mempool *pool, const pa_sample_spec *a, @@ -56,7 +62,7 @@ pa_resampler* pa_resampler_new( const pa_sample_spec *b, const pa_channel_map *bm, pa_resample_method_t resample_method, - int variable_rate); + pa_resample_flags_t flags); void pa_resampler_free(pa_resampler *r); diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 6f654b616..730f3e5cd 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -154,7 +154,7 @@ pa_sink_input* pa_sink_input_new( &data->sample_spec, &data->channel_map, &data->sink->sample_spec, &data->sink->channel_map, data->resample_method, - !!(flags & PA_SINK_INPUT_VARIABLE_RATE)))) { + (flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0))) { pa_log_warn("Unsupported resampling operation."); return NULL; } @@ -750,7 +750,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { &i->sample_spec, &i->channel_map, &dest->sample_spec, &dest->channel_map, i->resample_method, - !!(i->flags & PA_SINK_INPUT_VARIABLE_RATE)))) { + (i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0))) { pa_log_warn("Unsupported resampling operation."); return -1; } diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 2a902dc2b..5c52419e3 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -122,7 +122,7 @@ pa_source_output* pa_source_output_new( &data->source->sample_spec, &data->source->channel_map, &data->sample_spec, &data->channel_map, data->resample_method, - !!(flags & PA_SOURCE_OUTPUT_VARIABLE_RATE)))) { + (flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0))) { pa_log_warn("Unsupported resampling operation."); return NULL; } @@ -415,7 +415,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { &dest->sample_spec, &dest->channel_map, &o->sample_spec, &o->channel_map, o->resample_method, - !!(o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE)))) { + (o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0))) { pa_log_warn("Unsupported resampling operation."); return -1; } diff --git a/src/tests/remix-test.c b/src/tests/remix-test.c new file mode 100644 index 000000000..d2fa69437 --- /dev/null +++ b/src/tests/remix-test.c @@ -0,0 +1,91 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +int main(int argc, char *argv[]) { + + static const pa_channel_map maps[] = { + { 1, { PA_CHANNEL_POSITION_MONO } }, + { 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } }, + { 3, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_CENTER } }, + { 3, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_LFE } }, + { 3, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_CENTER } }, + { 4, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE } }, + { 4, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_REAR_CENTER } }, + { 4, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT } }, + { 5, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_CENTER } }, + { 5, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_LFE } }, + { 6, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_LFE, PA_CHANNEL_POSITION_CENTER } }, + { 8, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_LFE, PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT } }, + { 0, { 0 } } + }; + + unsigned i, j; + pa_mempool *pool; + + oil_init(); + pa_log_set_maximal_level(PA_LOG_DEBUG); + + pa_assert_se(pool = pa_mempool_new(FALSE)); + + for (i = 0; maps[i].channels > 0; i++) + for (j = 0; maps[j].channels > 0; j++) { + char a[PA_CHANNEL_MAP_SNPRINT_MAX], b[PA_CHANNEL_MAP_SNPRINT_MAX]; + pa_resampler *r; + pa_sample_spec ss1, ss2; + + pa_log_info("Converting from '%s' to '%s'.\n", pa_channel_map_snprint(a, sizeof(a), &maps[i]), pa_channel_map_snprint(b, sizeof(b), &maps[j])); + + ss1.channels = maps[i].channels; + ss2.channels = maps[j].channels; + + ss1.rate = ss2.rate = 44100; + ss1.format = ss2.format = PA_SAMPLE_S16NE; + + r = pa_resampler_new(pool, &ss1, &maps[i], &ss2, &maps[j], PA_RESAMPLER_AUTO, 0); + + /* We don't really care for the resampler. We just want to + * see the remixing debug output. */ + + pa_resampler_free(r); + } + + + pa_mempool_free(pool); + + return 0; +} diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c index 5295995bc..820a0c1e3 100644 --- a/src/tests/resampler-test.c +++ b/src/tests/resampler-test.c @@ -222,8 +222,8 @@ int main(int argc, char *argv[]) { pa_sample_format_to_string(b.format), pa_sample_format_to_string(a.format)); - pa_assert_se(forth = pa_resampler_new(pool, &a, NULL, &b, NULL, PA_RESAMPLER_AUTO, FALSE)); - pa_assert_se(back = pa_resampler_new(pool, &b, NULL, &a, NULL, PA_RESAMPLER_AUTO, FALSE)); + pa_assert_se(forth = pa_resampler_new(pool, &a, NULL, &b, NULL, PA_RESAMPLER_AUTO, 0)); + pa_assert_se(back = pa_resampler_new(pool, &b, NULL, &a, NULL, PA_RESAMPLER_AUTO, 0)); i.memblock = generate_block(pool, &a); i.length = pa_memblock_get_length(i.memblock); From e043eaad9463ce1241b0049814d20bb2a7340990 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Nov 2007 22:59:34 +0000 Subject: [PATCH 1446/1514] add new function pa_strnull() to simplify passing null strings to non-linux printf() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2045 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/macro.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h index 4b62dd21a..41af19c94 100644 --- a/src/pulsecore/macro.h +++ b/src/pulsecore/macro.h @@ -152,4 +152,8 @@ typedef int pa_bool_t; #define PA_PATH_SEP_CHAR '/' #endif +static inline const char *pa_strnull(const char *x) { + return x ? x : "(null)"; +} + #endif From daf3a3ed8f2ee926df416617ca7b9b3823fdfa4c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Nov 2007 23:00:38 +0000 Subject: [PATCH 1447/1514] pull code for starting helper processes out of module-gconf, clean it up, and stick into a new API pa_start_child_for_read() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2046 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/start-child.c | 162 ++++++++++++++++++++++++++++++++++++ src/pulsecore/start-child.h | 32 +++++++ 2 files changed, 194 insertions(+) create mode 100644 src/pulsecore/start-child.c create mode 100644 src/pulsecore/start-child.h diff --git a/src/pulsecore/start-child.c b/src/pulsecore/start-child.c new file mode 100644 index 000000000..e01011d6a --- /dev/null +++ b/src/pulsecore/start-child.c @@ -0,0 +1,162 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2007 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_PRCTL_H +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#include +#include + +#include "start-child.h" + +int pa_start_child_for_read(const char *name, const char *argv1, pid_t *pid) { + pid_t child; + int pipe_fds[2] = { -1, -1 }; + + if (pipe(pipe_fds) < 0) { + pa_log("pipe() failed: %s", pa_cstrerror(errno)); + goto fail; + } + + if ((child = fork()) == (pid_t) -1) { + pa_log("fork() failed: %s", pa_cstrerror(errno)); + goto fail; + + } else if (child != 0) { + + /* Parent */ + pa_assert_se(pa_close(pipe_fds[1]) == 0); + + if (pid) + *pid = child; + + return pipe_fds[0]; + } else { +#ifdef __linux__ + DIR* d; +#endif + int max_fd, i; + + /* child */ + + pa_reset_priority(); + + pa_assert_se(pa_close(pipe_fds[0]) == 0); + pa_assert_se(dup2(pipe_fds[1], 1) == 1); + + if (pipe_fds[1] != 1) + pa_assert_se(pa_close(pipe_fds[1]) == 0); + + pa_close(0); + pa_assert_se(open("/dev/null", O_RDONLY) == 0); + + pa_close(2); + pa_assert_se(open("/dev/null", O_WRONLY) == 2); + +#ifdef __linux__ + + if ((d = opendir("/proc/self/fd/"))) { + + struct dirent *de; + + while ((de = readdir(d))) { + char *e = NULL; + int fd; + + if (de->d_name[0] == '.') + continue; + + errno = 0; + fd = strtol(de->d_name, &e, 10); + pa_assert(errno == 0 && e && *e == 0); + + if (fd >= 3 && dirfd(d) != fd) + pa_close(fd); + } + + closedir(d); + } else { + +#endif + + max_fd = 1024; + +#ifdef HAVE_SYS_RESOURCE_H + { + struct rlimit r; + if (getrlimit(RLIMIT_NOFILE, &r) == 0) + max_fd = r.rlim_max; + } +#endif + + for (i = 3; i < max_fd; i++) + pa_close(i); + +#ifdef __linux__ + } +#endif + +#ifdef PR_SET_PDEATHSIG + /* On Linux we can use PR_SET_PDEATHSIG to have the helper + process killed when the daemon dies abnormally. On non-Linux + machines the client will die as soon as it writes data to + stdout again (SIGPIPE) */ + + prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); +#endif + +#ifdef SIGPIPE + /* Make sure that SIGPIPE kills the child process */ + signal(SIGPIPE, SIG_DFL); +#endif + +#ifdef SIGTERM + /* Make sure that SIGTERM kills the child process */ + signal(SIGTERM, SIG_DFL); +#endif + + execl(name, name, argv1, NULL); + _exit(1); + } + +fail: + pa_close_pipe(pipe_fds); + + return -1; +} diff --git a/src/pulsecore/start-child.h b/src/pulsecore/start-child.h new file mode 100644 index 000000000..359b50441 --- /dev/null +++ b/src/pulsecore/start-child.h @@ -0,0 +1,32 @@ +#ifndef foopulsestartchildhfoo +#define foopulsestartchildhfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2007 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +int pa_start_child_for_read(const char *name, const char *argv1, pid_t *pid); + +#endif From e8092bede9c2c9daac6c6035ca7a130b2c9a7e5b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Nov 2007 23:01:44 +0000 Subject: [PATCH 1448/1514] Port module-gconf to make use of the new API pa_start_child_for_read() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2047 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/gconf/module-gconf.c | 139 +++---------------------------- 1 file changed, 10 insertions(+), 129 deletions(-) diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c index fa9ab1ccf..836157d04 100644 --- a/src/modules/gconf/module-gconf.c +++ b/src/modules/gconf/module-gconf.c @@ -33,23 +33,16 @@ #include #include #include -#include - -#ifdef HAVE_SYS_PRCTL_H -#include -#endif -#ifdef HAVE_SYS_RESOURCE_H -#include -#endif +#include #include #include #include #include #include #include -#include #include +#include #include "module-gconf-symdef.h" @@ -337,119 +330,6 @@ static void io_event_cb( } } -static int start_client(const char *n, pid_t *pid) { - pid_t child; - int pipe_fds[2] = { -1, -1 }; - - if (pipe(pipe_fds) < 0) { - pa_log("pipe() failed: %s", pa_cstrerror(errno)); - goto fail; - } - - if ((child = fork()) == (pid_t) -1) { - pa_log("fork() failed: %s", pa_cstrerror(errno)); - goto fail; - } else if (child != 0) { - - /* Parent */ - close(pipe_fds[1]); - - if (pid) - *pid = child; - - return pipe_fds[0]; - } else { -#ifdef __linux__ - DIR* d; -#endif - int max_fd, i; - /* child */ - - pa_reset_priority(); - - close(pipe_fds[0]); - dup2(pipe_fds[1], 1); - - if (pipe_fds[1] != 1) - close(pipe_fds[1]); - - close(0); - open("/dev/null", O_RDONLY); - - close(2); - open("/dev/null", O_WRONLY); - -#ifdef __linux__ - - if ((d = opendir("/proc/self/fd/"))) { - - struct dirent *de; - - while ((de = readdir(d))) { - char *e = NULL; - int fd; - - if (de->d_name[0] == '.') - continue; - - errno = 0; - fd = strtol(de->d_name, &e, 10); - pa_assert(errno == 0 && e && *e == 0); - - if (fd >= 3 && dirfd(d) != fd) - close(fd); - } - - closedir(d); - } else { - -#endif - - max_fd = 1024; - -#ifdef HAVE_SYS_RESOURCE_H - { - struct rlimit r; - if (getrlimit(RLIMIT_NOFILE, &r) == 0) - max_fd = r.rlim_max; - } -#endif - - for (i = 3; i < max_fd; i++) - close(i); -# -#ifdef __linux__ - } -#endif - -#ifdef PR_SET_PDEATHSIG - /* On Linux we can use PR_SET_PDEATHSIG to have the helper - process killed when the daemon dies abnormally. On non-Linux - machines the client will die as soon as it writes data to - stdout again (SIGPIPE) */ - - prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0); -#endif - -#ifdef SIGPIPE - /* Make sure that SIGPIPE kills the child process */ - signal(SIGPIPE, SIG_DFL); -#endif - - execl(n, n, NULL); - _exit(1); - } - -fail: - if (pipe_fds[0] >= 0) - close(pipe_fds[0]); - - if (pipe_fds[1] >= 0) - close(pipe_fds[1]); - - return -1; -} - int pa__init(pa_module*m) { struct userdata *u; int r; @@ -465,7 +345,7 @@ int pa__init(pa_module*m) { u->io_event = NULL; u->buf_fill = 0; - if ((u->fd = start_client(PA_GCONF_HELPER, &u->pid)) < 0) + if ((u->fd = pa_start_child_for_read(PA_GCONF_HELPER, NULL, &u->pid)) < 0) goto fail; u->io_event = m->core->mainloop->io_new( @@ -498,17 +378,18 @@ void pa__done(pa_module*m) { if (!(u = m->userdata)) return; - if (u->io_event) - m->core->mainloop->io_free(u->io_event); - - if (u->fd >= 0) - close(u->fd); - if (u->pid != (pid_t) -1) { kill(u->pid, SIGTERM); waitpid(u->pid, NULL, 0); } + if (u->io_event) + m->core->mainloop->io_free(u->io_event); + + if (u->fd >= 0) + pa_close(u->fd); + + if (u->module_infos) pa_hashmap_free(u->module_infos, module_info_free, u); From 5054f3623ff82ab0c263e15c47779b0caa841b29 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 11 Nov 2007 23:18:19 +0000 Subject: [PATCH 1449/1514] add new fun module that automatically mutes your audio devices when you leave with your bluetooth phone, and unmutes when you come back git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2048 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 36 +++ src/Makefile.am | 26 +- src/modules/bt-proximity-helper.c | 210 +++++++++++++ src/modules/module-bt-proximity.c | 492 ++++++++++++++++++++++++++++++ 4 files changed, 763 insertions(+), 1 deletion(-) create mode 100644 src/modules/bt-proximity-helper.c create mode 100644 src/modules/module-bt-proximity.c diff --git a/configure.ac b/configure.ac index f6e548bc6..b5834f0f2 100644 --- a/configure.ac +++ b/configure.ac @@ -789,6 +789,36 @@ AC_SUBST(HAL_LIBS) AC_SUBST(HAVE_HAL) AM_CONDITIONAL([HAVE_HAL], [test "x$HAVE_HAL" = x1]) +#### BlueZ support (optional) #### + +AC_ARG_ENABLE([bluez], + AC_HELP_STRING([--disable-bluez], [Disable optional BlueZ support]), + [ + case "${enableval}" in + yes) bluez=yes ;; + no) bluez=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-bluez) ;; + esac + ], + [bluez=auto]) +if test "x${bluez}" != xno ; then + PKG_CHECK_MODULES(BLUEZ, [ bluez >= 3.0 ], + HAVE_BLUEZ=1, + [ + HAVE_BLUEZ=0 + if test "x$bluez" = xyes ; then + AC_MSG_ERROR([*** BLUEZ support not found]) + fi + ]) +else + HAVE_BLUEZ=0 +fi + +AC_SUBST(BLUEZ_CFLAGS) +AC_SUBST(BLUEZ_LIBS) +AC_SUBST(HAVE_BLUEZ) +AM_CONDITIONAL([HAVE_BLUEZ], [test "x$HAVE_BLUEZ" = x1]) + #### D-Bus support (optional) #### AC_ARG_ENABLE([dbus], @@ -1028,6 +1058,11 @@ if test "x${HAVE_LIBSAMPLERATE}" = "x1" ; then ENABLE_LIBSAMPLERATE=yes fi +ENABLE_BLUEZ=no +if test "x${HAVE_BLUEZ}" = "x1" ; then + ENABLE_BLUEZ=yes +fi + echo " ---{ $PACKAGE_NAME $VERSION }--- @@ -1048,6 +1083,7 @@ echo " Enable Async DNS: ${ENABLE_LIBASYNCNS} Enable LIRC: ${ENABLE_LIRC} Enable HAL: ${ENABLE_HAL} + Enable BlueZ: ${ENABLE_BLUEZ} Enable TCP Wrappers: ${ENABLE_TCPWRAP} Enable libsamplerate: ${ENABLE_LIBSAMPLERATE} System User: ${PA_SYSTEM_USER} diff --git a/src/Makefile.am b/src/Makefile.am index 1a24a5293..36d27ef42 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -736,6 +736,7 @@ libpulsecore_la_SOURCES += \ pulsecore/macro.h \ pulsecore/once.c pulsecore/once.h \ pulsecore/time-smoother.c pulsecore/time-smoother.h \ + pulsecore/start-child.c pulsecore/start-child.h \ $(PA_THREAD_OBJS) if OS_IS_WIN32 @@ -1052,11 +1053,13 @@ modlibexec_LTLIBRARIES += \ module-jack-source.la endif +pulselibexec_PROGRAMS = + if HAVE_GCONF modlibexec_LTLIBRARIES += \ module-gconf.la -pulselibexec_PROGRAMS = \ +pulselibexec_PROGRAMS += \ gconf-helper endif @@ -1071,6 +1074,14 @@ modlibexec_LTLIBRARIES += \ module-hal-detect.la endif +if HAVE_BLUEZ +modlibexec_LTLIBRARIES += \ + module-bt-proximity.la + +pulselibexec_PROGRAMS += \ + bt-proximity-helper +endif + # These are generated by a M4 script SYMDEF_FILES = \ @@ -1121,6 +1132,7 @@ SYMDEF_FILES = \ modules/module-rescue-streams-symdef.h \ modules/module-suspend-on-idle-symdef.h \ modules/module-hal-detect-symdef.h \ + modules/module-bt-proximity-symdef.h \ modules/gconf/module-gconf-symdef.h EXTRA_DIST += $(SYMDEF_FILES) @@ -1419,6 +1431,17 @@ gconf_helper_LDADD = $(AM_LDADD) $(GCONF_LIBS) libpulsecore.la gconf_helper_CFLAGS = $(AM_CFLAGS) $(GCONF_CFLAGS) gconf_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) +# Bluetooth proximity +module_bt_proximity_la_SOURCES = modules/module-bt-proximity.c +module_bt_proximity_la_LDFLAGS = -module -avoid-version +module_bt_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la +module_bt_proximity_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) -DPA_BT_PROXIMITY_HELPER=\"$(pulselibexecdir)/bt-proximity-helper\" + +bt_proximity_helper_SOURCES = modules/bt-proximity-helper.c +bt_proximity_helper_LDADD = $(AM_LDADD) $(BLUEZ_LIBS) +bt_proximity_helper_CFLAGS = $(AM_CFLAGS) $(BLUEZ_CFLAGS) +bt_proximity_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) + ################################### # Some minor stuff # ################################### @@ -1455,6 +1478,7 @@ daemon.conf: daemon/daemon.conf.in Makefile install-exec-hook: chown root $(DESTDIR)$(bindir)/pulseaudio ; true chmod u+s $(DESTDIR)$(bindir)/pulseaudio + chmod u+s $(DESTDIR)$(pulselibexecdir)/bt-proximity-helper ln -sf pacat $(DESTDIR)$(bindir)/parec rm -f $(DESTDIR)$(modlibexecdir)/*.a rm -f $(DESTDIR)$(libdir)/libpulsedsp.a diff --git a/src/modules/bt-proximity-helper.c b/src/modules/bt-proximity-helper.c new file mode 100644 index 000000000..d80cc0c18 --- /dev/null +++ b/src/modules/bt-proximity-helper.c @@ -0,0 +1,210 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2007 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* + * Small SUID helper that allows us to ping a BT device. Borrows + * heavily from bluez-utils' l2ping, which is licensed as GPL2+, too + * and comes with a copyright like this: + * + * Copyright (C) 2000-2001 Qualcomm Incorporated + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2007 Marcel Holtmann + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#undef NDEBUG + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define PING_STRING "PulseAudio" +#define IDENT 200 +#define TIMEOUT 4 +#define INTERVAL 2 + +static void update_status(int found) { + static int status = -1; + + if (!found && status != 0) + printf("-"); + if (found && status <= 0) + printf("+"); + + fflush(stdout); + status = !!found; +} + +int main(int argc, char *argv[]) { + struct sockaddr_l2 addr; + union { + l2cap_cmd_hdr hdr; + uint8_t buf[L2CAP_CMD_HDR_SIZE + sizeof(PING_STRING)]; + } packet; + int fd = -1; + uint8_t id = IDENT; + int connected = 0; + + assert(argc == 2); + + for (;;) { + fd_set fds; + struct timeval end; + ssize_t r; + + if (!connected) { + + if (fd >= 0) + close(fd); + + if ((fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP)) < 0) { + fprintf(stderr, "socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP) failed: %s", strerror(errno)); + goto finish; + } + + memset(&addr, 0, sizeof(addr)); + addr.l2_family = AF_BLUETOOTH; + bacpy(&addr.l2_bdaddr, BDADDR_ANY); + + if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + fprintf(stderr, "bind() failed: %s", strerror(errno)); + goto finish; + } + + memset(&addr, 0, sizeof(addr)); + addr.l2_family = AF_BLUETOOTH; + str2ba(argv[1], &addr.l2_bdaddr); + + if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + + if (errno == EHOSTDOWN || errno == ECONNRESET || errno == ETIMEDOUT) { + update_status(0); + sleep(INTERVAL); + continue; + } + + fprintf(stderr, "connect() failed: %s", strerror(errno)); + goto finish; + } + + connected = 1; + } + + assert(connected); + + memset(&packet, 0, sizeof(packet)); + strcpy((char*) packet.buf + L2CAP_CMD_HDR_SIZE, PING_STRING); + packet.hdr.ident = id; + packet.hdr.len = htobs(sizeof(PING_STRING)); + packet.hdr.code = L2CAP_ECHO_REQ; + + if ((r = send(fd, &packet, sizeof(packet), 0)) < 0) { + + if (errno == EHOSTDOWN || errno == ECONNRESET || errno == ETIMEDOUT) { + update_status(0); + connected = 0; + sleep(INTERVAL); + continue; + } + + fprintf(stderr, "send() failed: %s", strerror(errno)); + goto finish; + } + + assert(r == sizeof(packet)); + + gettimeofday(&end, NULL); + end.tv_sec += TIMEOUT; + + for (;;) { + struct timeval now, delta; + + gettimeofday(&now, NULL); + + if (timercmp(&end, &now, <=)) { + update_status(0); + connected = 0; + sleep(INTERVAL); + break; + } + + timersub(&end, &now, &delta); + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + if (select(fd+1, &fds, NULL, NULL, &delta) < 0) { + fprintf(stderr, "select() failed: %s", strerror(errno)); + goto finish; + } + + if ((r = recv(fd, &packet, sizeof(packet), 0)) <= 0) { + + if (errno == EHOSTDOWN || errno == ECONNRESET || errno == ETIMEDOUT) { + update_status(0); + connected = 0; + sleep(INTERVAL); + break; + } + + fprintf(stderr, "send() failed: %s", r == 0 ? "EOF" : strerror(errno)); + goto finish; + } + + assert(r >= L2CAP_CMD_HDR_SIZE); + + if (packet.hdr.ident != id) + continue; + + if (packet.hdr.code == L2CAP_ECHO_RSP || packet.hdr.code == L2CAP_COMMAND_REJ) { + + if (++id >= 0xFF) + id = IDENT; + + update_status(1); + sleep(INTERVAL); + break; + } + } + } + +finish: + + if (fd >= 0) + close(fd); + + return 1; +} diff --git a/src/modules/module-bt-proximity.c b/src/modules/module-bt-proximity.c new file mode 100644 index 000000000..f6125233d --- /dev/null +++ b/src/modules/module-bt-proximity.c @@ -0,0 +1,492 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2005-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dbus-util.h" +#include "module-bt-proximity-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Bluetooth Proximity Volume Control"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE( + "sink= " + "hci= " +); + +#define DEFAULT_HCI "hci0" + +static const char* const valid_modargs[] = { + "sink", + "rssi", + "hci", + NULL, +}; + +struct bonding { + struct userdata *userdata; + char address[18]; + + pid_t pid; + int fd; + + pa_io_event *io_event; + + enum { + UNKNOWN, + FOUND, + NOT_FOUND + } state; +}; + +struct userdata { + pa_module *module; + pa_dbus_connection *dbus_connection; + + char *sink_name; + char *hci, *hci_path; + + pa_hashmap *bondings; + + unsigned n_found; + unsigned n_unknown; + + pa_bool_t muted; +}; + +static void update_volume(struct userdata *u) { + pa_assert(u); + + if (u->muted && u->n_found > 0) { + pa_sink *s; + + u->muted = FALSE; + + if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, FALSE))) { + pa_log_warn("Sink device '%s' not available for unmuting.", pa_strnull(u->sink_name)); + return; + } + + pa_log_info("Found %u BT devices, unmuting.", u->n_found); + pa_sink_set_mute(s, FALSE); + + } else if (!u->muted && (u->n_found+u->n_unknown) <= 0) { + pa_sink *s; + + u->muted = TRUE; + + if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, FALSE))) { + pa_log_warn("Sink device '%s' not available for muting.", pa_strnull(u->sink_name)); + return; + } + + pa_log_info("No BT devices found, muting."); + pa_sink_set_mute(s, TRUE); + + } else + pa_log_info("%u devices now active, %u with unknown state.", u->n_found, u->n_unknown); +} + +static void bonding_free(struct bonding *b) { + pa_assert(b); + + if (b->state == FOUND) + pa_assert_se(b->userdata->n_found-- >= 1); + + if (b->state == UNKNOWN) + pa_assert_se(b->userdata->n_unknown-- >= 1); + + if (b->pid != (pid_t) -1) { + kill(b->pid, SIGTERM); + waitpid(b->pid, NULL, 0); + } + + if (b->fd >= 0) + pa_close(b->fd); + + if (b->io_event) + b->userdata->module->core->mainloop->io_free(b->io_event); + + pa_xfree(b); +} + +static void io_event_cb( + pa_mainloop_api*a, + pa_io_event* e, + int fd, + pa_io_event_flags_t events, + void *userdata) { + + struct bonding *b = userdata; + char x; + ssize_t r; + + pa_assert(b); + + if ((r = read(fd, &x, 1)) <= 0) { + pa_log_warn("Child watching '%s' died abnormally: %s", b->address, r == 0 ? "EOF" : pa_cstrerror(errno)); + + pa_assert_se(pa_hashmap_remove(b->userdata->bondings, b->address) == b); + bonding_free(b); + return; + } + + pa_assert_se(r == 1); + + if (b->state == UNKNOWN) + pa_assert_se(b->userdata->n_unknown-- >= 1); + + if (x == '+') { + pa_assert(b->state == UNKNOWN || b->state == NOT_FOUND); + + b->state = FOUND; + b->userdata->n_found++; + + pa_log_info("Device '%s' is alive.", b->address); + + } else { + pa_assert(x == '-'); + pa_assert(b->state == UNKNOWN || b->state == FOUND); + + if (b->state == FOUND) + b->userdata->n_found--; + + b->state = NOT_FOUND; + + pa_log_info("Device '%s' is dead.", b->address); + } + + update_volume(b->userdata); +} + +static struct bonding* bonding_new(struct userdata *u, const char *a) { + struct bonding *b = NULL; + DBusMessage *m = NULL, *r = NULL; + DBusError e; + const char *class; + + pa_assert(u); + pa_assert(a); + + pa_return_val_if_fail(strlen(a) == 17, NULL); + pa_return_val_if_fail(!pa_hashmap_get(u->bondings, a), NULL); + + dbus_error_init(&e); + + pa_assert_se(m = dbus_message_new_method_call("org.bluez", u->hci_path, "org.bluez.Adapter", "GetRemoteMajorClass")); + pa_assert_se(dbus_message_append_args(m, DBUS_TYPE_STRING, &a, DBUS_TYPE_INVALID)); + r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->dbus_connection), m, -1, &e); + + if (!r) { + pa_log("org.bluez.Adapter.GetRemoteMajorClass(%s) failed: %s", a, e.message); + goto fail; + } + + if (!(dbus_message_get_args(r, &e, DBUS_TYPE_STRING, &class, DBUS_TYPE_INVALID))) { + pa_log("Malformed org.bluez.Adapter.GetRemoteMajorClass signal: %s", e.message); + goto fail; + } + + if (strcmp(class, "phone")) { + pa_log_info("Found device '%s' of class '%s', ignoring.", a, class); + goto fail; + } + + b = pa_xnew(struct bonding, 1); + b->userdata = u; + pa_strlcpy(b->address, a, sizeof(b->address)); + b->pid = (pid_t) -1; + b->fd = -1; + b->io_event = NULL; + b->state = UNKNOWN; + u->n_unknown ++; + + pa_log_info("Watching device '%s' of class '%s'.", b->address, class); + + if ((b->fd = pa_start_child_for_read(PA_BT_PROXIMITY_HELPER, a, &b->pid)) < 0) { + pa_log("Failed to start helper tool."); + goto fail; + } + + b->io_event = u->module->core->mainloop->io_new( + u->module->core->mainloop, + b->fd, + PA_IO_EVENT_INPUT, + io_event_cb, + b); + + dbus_message_unref(m); + dbus_message_unref(r); + + pa_hashmap_put(u->bondings, a, b); + + return b; + +fail: + if (m) + dbus_message_unref(m); + if (r) + dbus_message_unref(r); + + if (b) + bonding_free(b); + + dbus_error_free(&e); + return NULL; +} + +static void bonding_remove(struct userdata *u, const char *a) { + struct bonding *b; + pa_assert(u); + + pa_return_if_fail((b = pa_hashmap_remove(u->bondings, a))); + + pa_log_info("No longer watching device '%s'", b->address); + bonding_free(b); +} + +static DBusHandlerResult filter_func(DBusConnection *connection, DBusMessage *m, void *userdata) { + struct userdata *u = userdata; + DBusError e; + + dbus_error_init(&e); + + if (dbus_message_is_signal(m, "org.bluez.Adapter", "BondingCreated")) { + const char *a; + + if (!(dbus_message_get_args(m, &e, DBUS_TYPE_STRING, &a, DBUS_TYPE_INVALID))) { + pa_log("Malformed org.bluez.Adapter.BondingCreated signal: %s", e.message); + goto finish; + } + + bonding_new(u, a); + + return DBUS_HANDLER_RESULT_HANDLED; + + } else if (dbus_message_is_signal(m, "org.bluez.Adapter", "BondingRemoved")) { + + const char *a; + + if (!(dbus_message_get_args(m, &e, DBUS_TYPE_STRING, &a, DBUS_TYPE_INVALID))) { + pa_log("Malformed org.bluez.Adapter.BondingRemoved signal: %s", e.message); + goto finish; + } + + bonding_remove(u, a); + + return DBUS_HANDLER_RESULT_HANDLED; + } + +finish: + + dbus_error_free(&e); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static int add_matches(struct userdata *u, pa_bool_t add) { + char *filter1, *filter2; + DBusError e; + int r = -1; + + pa_assert(u); + dbus_error_init(&e); + + filter1 = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='BondingCreated',path='%s'", u->hci_path); + filter2 = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='BondingRemoved',path='%s'", u->hci_path); + + if (add) { + dbus_bus_add_match(pa_dbus_connection_get(u->dbus_connection), filter1, &e); + + if (dbus_error_is_set(&e)) { + pa_log("dbus_bus_add_match(%s) failed: %s", filter1, e.message); + goto finish; + } + } else + dbus_bus_remove_match(pa_dbus_connection_get(u->dbus_connection), filter1, &e); + + + if (add) { + dbus_bus_add_match(pa_dbus_connection_get(u->dbus_connection), filter2, &e); + + if (dbus_error_is_set(&e)) { + pa_log("dbus_bus_add_match(%s) failed: %s", filter2, e.message); + dbus_bus_remove_match(pa_dbus_connection_get(u->dbus_connection), filter2, &e); + goto finish; + } + } else + dbus_bus_remove_match(pa_dbus_connection_get(u->dbus_connection), filter2, &e); + + + if (add) + pa_assert_se(dbus_connection_add_filter(pa_dbus_connection_get(u->dbus_connection), filter_func, u, NULL)); + else + dbus_connection_remove_filter(pa_dbus_connection_get(u->dbus_connection), filter_func, u); + + r = 0; + +finish: + pa_xfree(filter1); + pa_xfree(filter2); + dbus_error_free(&e); + + return r; +} + +int pa__init(pa_module*m) { + pa_modargs *ma = NULL; + struct userdata *u; + DBusError e; + DBusMessage *msg = NULL, *r = NULL; + DBusMessageIter iter, sub; + + pa_assert(m); + dbus_error_init(&e); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments"); + goto fail; + } + + m->userdata = u = pa_xnew0(struct userdata, 1); + u->module = m; + u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + u->hci = pa_xstrdup(pa_modargs_get_value(ma, "hci", DEFAULT_HCI)); + u->hci_path = pa_sprintf_malloc("/org/bluez/%s", u->hci); + u->n_found = u->n_unknown = 0; + u->muted = FALSE; + + u->bondings = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + + if (!(u->dbus_connection = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &e))) { + pa_log("Failed to get D-Bus connection: %s", e.message); + goto fail; + } + + if (add_matches(u, TRUE) < 0) + goto fail; + + pa_assert_se(msg = dbus_message_new_method_call("org.bluez", u->hci_path, "org.bluez.Adapter", "ListBondings")); + + if (!(r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->dbus_connection), msg, -1, &e))) { + pa_log("org.bluez.Adapter.ListBondings failed: %s", e.message); + goto fail; + } + + dbus_message_iter_init(r, &iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { + pa_log("Malformed reply to org.bluez.Adapter.ListBondings."); + goto fail; + } + + dbus_message_iter_recurse(&iter, &sub); + + while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) { + const char *a = NULL; + + dbus_message_iter_get_basic(&sub, &a); + bonding_new(u, a); + + dbus_message_iter_next(&sub); + } + + dbus_message_unref(r); + dbus_message_unref(msg); + + pa_modargs_free(ma); + + if (pa_hashmap_size(u->bondings) == 0) + pa_log_warn("Warning: no phone device bonded."); + + update_volume(u); + + return 0; + +fail: + + if (ma) + pa_modargs_free(ma); + + pa__done(m); + + dbus_error_free(&e); + + if (msg) + dbus_message_unref(msg); + + if (r) + dbus_message_unref(r); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata *u; + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->bondings) { + struct bonding *b; + + while ((b = pa_hashmap_steal_first(u->bondings))) + bonding_free(b); + + pa_hashmap_free(u->bondings, NULL, NULL); + } + + if (u->dbus_connection) { + add_matches(u, FALSE); + pa_dbus_connection_unref(u->dbus_connection); + } + + pa_xfree(u->sink_name); + pa_xfree(u->hci_path); + pa_xfree(u->hci); + pa_xfree(u); +} From f7528825257d5d4b056268da3c82181f520a8ff6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 13 Nov 2007 17:35:48 +0000 Subject: [PATCH 1450/1514] fix loading of load-once modules if no other modules was loaded before git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2049 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index e1680de5f..ae140ff43 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -86,7 +86,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { if ((load_once = (pa_bool_t (*)(void)) pa_load_sym(m->dl, name, PA_SYMBOL_LOAD_ONCE))) { - if (load_once()) { + if (load_once() && c->modules) { pa_module *i; uint32_t idx; /* OK, the module only wants to be loaded once, let's make sure it is */ From d17bb53d3ebfbd7046719400264bd87830c140d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 13 Nov 2007 17:37:44 +0000 Subject: [PATCH 1451/1514] Completely rework ALSA device selection code: choose the device to open depending on the requested number of channels and channel map. In most cases it will now suffice to set default-channels=6 to enable 5.1 sound for all devices that support it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2050 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 252 +++++++++++++++++++++++++++--- src/modules/alsa-util.h | 29 +++- src/modules/module-alsa-sink.c | 85 +++++----- src/modules/module-alsa-source.c | 69 ++++---- src/modules/module-bt-proximity.c | 2 +- src/modules/module-cli.c | 2 +- src/modules/module-detect.c | 3 +- src/modules/module-hal-detect.c | 4 +- src/modules/module-oss.c | 2 +- src/modules/rtp/module-rtp-send.c | 9 +- src/pulsecore/modargs.c | 2 +- src/pulsecore/modargs.h | 3 +- src/pulsecore/protocol-esound.c | 2 +- src/pulsecore/protocol-native.c | 4 +- src/pulsecore/protocol-simple.c | 4 +- 15 files changed, 350 insertions(+), 122 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 15ae1fc6e..5b74c98c2 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -34,6 +34,7 @@ #include #include +#include #include "alsa-util.h" @@ -284,13 +285,21 @@ try_auto: /* Set the hardware parameters of the given ALSA device. Returns the * selected fragment settings in *period and *period_size */ -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size, int *use_mmap) { +int pa_alsa_set_hw_params( + snd_pcm_t *pcm_handle, + pa_sample_spec *ss, + uint32_t *periods, + snd_pcm_uframes_t *period_size, + pa_bool_t *use_mmap, + pa_bool_t require_exact_channel_number) { + int ret = -1; snd_pcm_uframes_t buffer_size; unsigned int r = ss->rate; unsigned int c = ss->channels; pa_sample_format_t f = ss->format; snd_pcm_hw_params_t *hwparams; + pa_bool_t _use_mmap = use_mmap && *use_mmap; pa_assert(pcm_handle); pa_assert(ss); @@ -305,7 +314,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p (ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) goto finish; - if (use_mmap && *use_mmap) { + if (_use_mmap) { if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) { /* mmap() didn't work, fall back to interleaved */ @@ -313,8 +322,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) goto finish; - if (use_mmap) - *use_mmap = 0; + _use_mmap = FALSE; } } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) @@ -326,8 +334,13 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0) goto finish; - if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) - goto finish; + if (require_exact_channel_number) { + if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0) + goto finish; + } else { + if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) + goto finish; + } if ((*period_size > 0 && (ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL)) < 0) || (*periods > 0 && (ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)) @@ -336,23 +349,14 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) goto finish; - if (ss->rate != r) { + if (ss->rate != r) pa_log_warn("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r); - /* If the sample rate deviates too much, we need to resample */ - if (r < ss->rate*.95 || r > ss->rate*1.05) - ss->rate = r; - } - - if (ss->channels != c) { + if (ss->channels != c) pa_log_warn("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c); - ss->channels = c; - } - if (ss->format != f) { + if (ss->format != f) pa_log_warn("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f)); - ss->format = f; - } if ((ret = snd_pcm_prepare(pcm_handle)) < 0) goto finish; @@ -361,11 +365,20 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p (ret = snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL)) < 0) goto finish; + /* If the sample rate deviates too much, we need to resample */ + if (r < ss->rate*.95 || r > ss->rate*1.05) + ss->rate = r; + ss->channels = c; + ss->format = f; + pa_assert(buffer_size > 0); pa_assert(*period_size > 0); *periods = buffer_size / *period_size; pa_assert(*periods > 0); + if (use_mmap) + *use_mmap = _use_mmap; + ret = 0; finish: @@ -404,6 +417,209 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm) { return 0; } +struct device_info { + pa_channel_map map; + const char *name; +}; + +static const struct device_info device_table[] = { + {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } }, "front" }, + + {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }}, "surround40" }, + + {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_LFE }}, "surround41" }, + + {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_CENTER }}, "surround50" }, + + {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE }}, "surround51" }, + + {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE, + PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT }} , "surround71" }, + + {{ 0, { 0 }}, NULL } +}; + +static pa_bool_t channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) { + pa_bool_t in_a[PA_CHANNEL_POSITION_MAX]; + unsigned i; + + pa_assert(a); + pa_assert(b); + + memset(in_a, 0, sizeof(in_a)); + + for (i = 0; i < a->channels; i++) + in_a[a->map[i]] = TRUE; + + for (i = 0; i < b->channels; i++) + if (!in_a[b->map[i]]) + return FALSE; + + return TRUE; +} + +snd_pcm_t *pa_alsa_open_by_device_id( + const char *dev_id, + char **dev, + pa_sample_spec *ss, + pa_channel_map* map, + int mode, + uint32_t *nfrags, + snd_pcm_uframes_t *period_size, + pa_bool_t *use_mmap) { + + int i; + int direction = 1; + int err; + char *d; + snd_pcm_t *pcm_handle; + + pa_assert(dev_id); + pa_assert(dev); + pa_assert(ss); + pa_assert(map); + pa_assert(nfrags); + pa_assert(period_size); + + /* First we try to find a device string with a superset of the + * requested channel map and open it without the plug: prefix. We + * iterate through our device table from top to bottom and take + * the first that matches. If we didn't find a working device that + * way, we iterate backwards, and check all devices that do not + * provide a superset of the requested channel map.*/ + + for (i = 0;; i += direction) { + pa_sample_spec try_ss; + + if (i < 0) { + pa_assert(direction == -1); + + /* OK, so we iterated backwards, and now are at the + * beginning of our list. */ + + break; + + } else if (!device_table[i].name) { + pa_assert(direction == 1); + + /* OK, so we are at the end of our list. at iterated + * forwards. */ + + i--; + direction = -1; + } + + if ((direction > 0) == !channel_map_superset(&device_table[i].map, map)) + continue; + + d = pa_sprintf_malloc("%s:%s", device_table[i].name, dev_id); + pa_log_debug("Trying %s...", d); + + if ((err = snd_pcm_open(&pcm_handle, d, mode, SND_PCM_NONBLOCK)) < 0) { + pa_log_info("Couldn't open PCM device %s: %s", d, snd_strerror(err)); + pa_xfree(d); + continue; + } + + try_ss.channels = device_table[i].map.channels; + try_ss.rate = ss->rate; + try_ss.format = ss->format; + + if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, use_mmap, TRUE)) < 0) { + pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err)); + pa_xfree(d); + snd_pcm_close(pcm_handle); + continue; + } + + *ss = try_ss; + *map = device_table[i].map; + pa_assert(map->channels == ss->channels); + *dev = d; + return pcm_handle; + } + + /* OK, we didn't find any good device, so let's try the raw hw: stuff */ + + d = pa_sprintf_malloc("hw:%s", dev_id); + pa_log_debug("Trying %s as last resort...", d); + pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, use_mmap); + pa_xfree(d); + + return pcm_handle; +} + +snd_pcm_t *pa_alsa_open_by_device_string( + const char *device, + char **dev, + pa_sample_spec *ss, + pa_channel_map* map, + int mode, + uint32_t *nfrags, + snd_pcm_uframes_t *period_size, + pa_bool_t *use_mmap) { + + int err; + char *d; + snd_pcm_t *pcm_handle; + + pa_assert(device); + pa_assert(dev); + pa_assert(ss); + pa_assert(map); + pa_assert(nfrags); + pa_assert(period_size); + + d = pa_xstrdup(device); + + for (;;) { + + if ((err = snd_pcm_open(&pcm_handle, d, mode, SND_PCM_NONBLOCK)) < 0) { + pa_log("Error opening PCM device %s: %s", d, snd_strerror(err)); + pa_xfree(d); + return NULL; + } + + if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, use_mmap, FALSE)) < 0) { + + if (err == -EPERM) { + /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */ + + if (pa_startswith(d, "hw:")) { + char *t = pa_sprintf_malloc("plughw:%s", d+3); + pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", d, t); + pa_xfree(d); + d = t; + + snd_pcm_close(pcm_handle); + continue; + } + + pa_log("Failed to set hardware parameters on %s: %s", d, snd_strerror(err)); + pa_xfree(d); + snd_pcm_close(pcm_handle); + return NULL; + } + } + + *dev = d; + + if (ss->channels != map->channels) + pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_ALSA); + + return pcm_handle; + } +} + int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) { int err; diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 6f1f927e2..36720b039 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -38,10 +38,37 @@ struct pa_alsa_fdlist *pa_alsa_fdlist_new(void); void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl); int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m); -int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size, int *use_mmap); +int pa_alsa_set_hw_params( + snd_pcm_t *pcm_handle, + pa_sample_spec *ss, + uint32_t *periods, + snd_pcm_uframes_t *period_size, + pa_bool_t *use_mmap, + pa_bool_t require_exact_channel_number); + int pa_alsa_set_sw_params(snd_pcm_t *pcm); int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev); snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback); +snd_pcm_t *pa_alsa_open_by_device_id( + const char *dev_id, + char **dev, + pa_sample_spec *ss, + pa_channel_map* map, + int mode, + uint32_t *nfrags, + snd_pcm_uframes_t *period_size, + pa_bool_t *use_mmap); + +snd_pcm_t *pa_alsa_open_by_device_string( + const char *device, + char **dev, + pa_sample_spec *ss, + pa_channel_map* map, + int mode, + uint32_t *nfrags, + snd_pcm_uframes_t *period_size, + pa_bool_t *use_mmap); + #endif diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 636b413c3..e62b8a067 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -57,6 +57,7 @@ PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "sink_name= " "device= " + "device_id= " "format= " "channels= " "rate= " @@ -89,15 +90,16 @@ struct userdata { char *device_name; - int use_mmap; + pa_bool_t use_mmap; - int first; + pa_bool_t first; pa_rtpoll_item *alsa_rtpoll_item; }; static const char* const valid_modargs[] = { "device", + "device_id", "sink_name", "format", "channels", @@ -127,7 +129,7 @@ static int mmap_write(struct userdata *u) { if (n == -EPIPE) { pa_log_debug("snd_pcm_avail_update: Buffer underrun!"); - u->first = 1; + u->first = TRUE; } if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0) @@ -151,7 +153,7 @@ static int mmap_write(struct userdata *u) { if (err == -EPIPE) { pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!"); - u->first = 1; + u->first = TRUE; } if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) @@ -188,7 +190,7 @@ static int mmap_write(struct userdata *u) { if (err == -EPIPE) { pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!"); - u->first = 1; + u->first = TRUE; } if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) @@ -355,7 +357,8 @@ static int suspend(struct userdata *u) { static int unsuspend(struct userdata *u) { pa_sample_spec ss; - int err, b; + int err; + pa_bool_t b; unsigned nfrags; snd_pcm_uframes_t period_size; @@ -375,7 +378,7 @@ static int unsuspend(struct userdata *u) { period_size = u->fragment_size / u->frame_size; b = u->use_mmap; - if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b, TRUE)) < 0) { pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); goto fail; } @@ -405,7 +408,7 @@ static int unsuspend(struct userdata *u) { /* FIXME: We need to reload the volume somehow */ - u->first = 1; + u->first = TRUE; pa_log_info("Resumed successfully..."); @@ -628,7 +631,7 @@ static void thread_func(void *userdata) { if (work_done && u->first) { pa_log_info("Starting playback."); snd_pcm_start(u->pcm_handle); - u->first = 0; + u->first = FALSE; continue; } } @@ -709,7 +712,7 @@ int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u = NULL; - char *dev; + const char *dev_id; pa_sample_spec ss; pa_channel_map map; uint32_t nfrags, frag_size; @@ -721,7 +724,7 @@ int pa__init(pa_module*m) { const char *name; char *name_buf = NULL; int namereg_fail; - int use_mmap = 1, b; + pa_bool_t use_mmap = TRUE, b; snd_pcm_info_alloca(&pcm_info); @@ -761,7 +764,7 @@ int pa__init(pa_module*m) { u->module = m; m->userdata = u; u->use_mmap = use_mmap; - u->first = 1; + u->first = TRUE; pa_thread_mq_init(&u->thread_mq, m->core->mainloop); u->rtpoll = pa_rtpoll_new(); u->alsa_rtpoll_item = NULL; @@ -769,43 +772,35 @@ int pa__init(pa_module*m) { snd_config_update_free_global(); - dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE)); + b = use_mmap; - for (;;) { + if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) { + + if (!(u->pcm_handle = pa_alsa_open_by_device_id( + dev_id, + &u->device_name, + &ss, &map, + SND_PCM_STREAM_PLAYBACK, + &nfrags, &period_size, + &b))) - if ((err = snd_pcm_open(&u->pcm_handle, dev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { - pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); - pa_xfree(dev); goto fail; - } - b = use_mmap; - if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { + } else { - if (err == -EPERM) { - /* Hmm, some hw is very exotic, so we retry with plughw, if hw didn't work */ - - if (pa_startswith(dev, "hw:")) { - char *d = pa_sprintf_malloc("plughw:%s", dev+3); - pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", dev, d); - pa_xfree(dev); - dev = d; - - snd_pcm_close(u->pcm_handle); - u->pcm_handle = NULL; - continue; - } - } - - pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); - pa_xfree(dev); + if (!(u->pcm_handle = pa_alsa_open_by_device_string( + pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), + &u->device_name, + &ss, &map, + SND_PCM_STREAM_PLAYBACK, + &nfrags, &period_size, + &b))) goto fail; - } - break; } - u->device_name = dev; + pa_assert(u->device_name); + pa_log_info("Successfully opened device %s.", u->device_name); if (use_mmap && !b) { pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode."); @@ -828,15 +823,11 @@ int pa__init(pa_module*m) { /* ALSA might tweak the sample spec, so recalculate the frame size */ frame_size = pa_frame_size(&ss); - if (ss.channels != map.channels) - /* Seems ALSA didn't like the channel number, so let's fix the channel map */ - pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); - if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) pa_log_warn("Error opening mixer: %s", snd_strerror(err)); else { - if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || + if ((pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) < 0) || !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM"))) { snd_mixer_close(u->mixer_handle); @@ -847,7 +838,7 @@ int pa__init(pa_module*m) { if ((name = pa_modargs_get_value(ma, "sink_name", NULL))) namereg_fail = 1; else { - name = name_buf = pa_sprintf_malloc("alsa_output.%s", dev); + name = name_buf = pa_sprintf_malloc("alsa_output.%s", u->device_name); namereg_fail = 0; } @@ -867,7 +858,7 @@ int pa__init(pa_module*m) { pa_sink_set_rtpoll(u->sink, u->rtpoll); pa_sink_set_description(u->sink, t = pa_sprintf_malloc( "ALSA PCM on %s (%s)%s", - dev, + u->device_name, snd_pcm_info_get_name(pcm_info), use_mmap ? " via DMA" : "")); pa_xfree(t); diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 1a6113a7f..2d2bfa070 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -58,6 +58,7 @@ PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE( "source_name= " "device= " + "device_id= " "format= " "channels= " "rate= " @@ -89,13 +90,14 @@ struct userdata { char *device_name; - int use_mmap; + pa_bool_t use_mmap; pa_rtpoll_item *alsa_rtpoll_item; }; static const char* const valid_modargs[] = { "device", + "device_id", "source_name", "channels", "rate", @@ -342,7 +344,8 @@ static int suspend(struct userdata *u) { static int unsuspend(struct userdata *u) { pa_sample_spec ss; - int err, b; + int err; + pa_bool_t b; unsigned nfrags; snd_pcm_uframes_t period_size; @@ -362,7 +365,7 @@ static int unsuspend(struct userdata *u) { period_size = u->fragment_size / u->frame_size; b = u->use_mmap; - if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b, TRUE)) < 0) { pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); goto fail; } @@ -691,10 +694,10 @@ int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u = NULL; - char *dev; + const char *dev_id; pa_sample_spec ss; pa_channel_map map; - unsigned nfrags, frag_size; + uint32_t nfrags, frag_size; snd_pcm_uframes_t period_size; size_t frame_size; snd_pcm_info_t *pcm_info = NULL; @@ -703,7 +706,7 @@ int pa__init(pa_module*m) { const char *name; char *name_buf = NULL; int namereg_fail; - int use_mmap = 1, b; + pa_bool_t use_mmap = TRUE, b; snd_pcm_info_alloca(&pcm_info); @@ -750,43 +753,31 @@ int pa__init(pa_module*m) { snd_config_update_free_global(); - dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE)); + if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) { - for (;;) { - - if ((err = snd_pcm_open(&u->pcm_handle, dev, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { - pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); - pa_xfree(dev); + if (!(u->pcm_handle = pa_alsa_open_by_device_id( + dev_id, + &u->device_name, + &ss, &map, + SND_PCM_STREAM_CAPTURE, + &nfrags, &period_size, + &b))) goto fail; - } - b = use_mmap; - if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { + } else { - if (err == -EPERM) { - /* Hmm, some hw is very exotic, so we retry with plughw, if hw didn't work */ - - if (pa_startswith(dev, "hw:")) { - char *d = pa_sprintf_malloc("plughw:%s", dev+3); - pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", dev, d); - pa_xfree(dev); - dev = d; - - snd_pcm_close(u->pcm_handle); - u->pcm_handle = NULL; - continue; - } - } - - pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); - pa_xfree(dev); + if (!(u->pcm_handle = pa_alsa_open_by_device_string( + pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), + &u->device_name, + &ss, &map, + SND_PCM_STREAM_CAPTURE, + &nfrags, &period_size, + &b))) goto fail; - } - - break; } - u->device_name = dev; + pa_assert(u->device_name); + pa_log_info("Successfully opened device %s.", u->device_name); if (use_mmap && !b) { pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode."); @@ -817,7 +808,7 @@ int pa__init(pa_module*m) { pa_log("Error opening mixer: %s", snd_strerror(err)); else { - if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || + if ((pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) < 0) || !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", NULL))) { snd_mixer_close(u->mixer_handle); u->mixer_handle = NULL; @@ -827,7 +818,7 @@ int pa__init(pa_module*m) { if ((name = pa_modargs_get_value(ma, "source_name", NULL))) namereg_fail = 1; else { - name = name_buf = pa_sprintf_malloc("alsa_input.%s", dev); + name = name_buf = pa_sprintf_malloc("alsa_input.%s", u->device_name); namereg_fail = 0; } @@ -847,7 +838,7 @@ int pa__init(pa_module*m) { pa_source_set_rtpoll(u->source, u->rtpoll); pa_source_set_description(u->source, t = pa_sprintf_malloc( "ALSA PCM on %s (%s)%s", - dev, + u->device_name, snd_pcm_info_get_name(pcm_info), use_mmap ? " via DMA" : "")); pa_xfree(t); diff --git a/src/modules/module-bt-proximity.c b/src/modules/module-bt-proximity.c index f6125233d..62d530d48 100644 --- a/src/modules/module-bt-proximity.c +++ b/src/modules/module-bt-proximity.c @@ -261,7 +261,7 @@ static struct bonding* bonding_new(struct userdata *u, const char *a) { dbus_message_unref(m); dbus_message_unref(r); - pa_hashmap_put(u->bondings, a, b); + pa_hashmap_put(u->bondings, b->address, b); return b; diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c index 71df5a0fb..ab311a829 100644 --- a/src/modules/module-cli.c +++ b/src/modules/module-cli.c @@ -70,7 +70,7 @@ static void eof_and_exit_cb(pa_cli*c, void *userdata) { int pa__init(pa_module*m) { pa_iochannel *io; pa_modargs *ma; - int exit_on_eof = 0; + pa_bool_t exit_on_eof = FALSE; pa_assert(m); diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c index 956659314..ee650dfd0 100644 --- a/src/modules/module-detect.c +++ b/src/modules/module-detect.c @@ -222,7 +222,8 @@ static int detect_waveout(pa_core *c, int just_one) { #endif int pa__init(pa_module*m) { - int just_one = 0, n = 0; + pa_bool_t just_one = FALSE; + int n = 0; pa_modargs *ma; pa_assert(m); diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 00b66c16c..832bc73e6 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -191,12 +191,12 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, char *sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi)); module_name = "module-alsa-sink"; - args = pa_sprintf_malloc("device=hw:%u sink_name=%s", card, *sink_name); + args = pa_sprintf_malloc("device_id=%u sink_name=%s", card, *sink_name); } else { *source_name = pa_sprintf_malloc("alsa_input.%s", strip_udi(udi)); module_name = "module-alsa-source"; - args = pa_sprintf_malloc("device=hw:%u source_name=%s", card, *source_name); + args = pa_sprintf_malloc("device_id=%u source_name=%s", card, *source_name); } pa_log_debug("Loading %s with arguments '%s'", module_name, args); diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index a44ad0834..8352a790f 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -1139,7 +1139,7 @@ int pa__init(pa_module*m) { int fd = -1; int nfrags, frag_size; int mode, caps; - int record = 1, playback = 1, use_mmap = 1; + pa_bool_t record = TRUE, playback = TRUE, use_mmap = TRUE; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index d7c50578c..95ff15dea 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -179,11 +179,11 @@ int pa__init(pa_module*m) { pa_source_output *o = NULL; uint8_t payload; char *p; - int r; + int r, j; socklen_t k; struct timeval tv; char hn[128], *n; - int loop = 0; + pa_bool_t loop = FALSE; pa_source_output_new_data data; pa_assert(m); @@ -274,8 +274,9 @@ int pa__init(pa_module*m) { goto fail; } - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0 || - setsockopt(sap_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) { + j = !!loop; + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &j, sizeof(j)) < 0 || + setsockopt(sap_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &j, sizeof(j)) < 0) { pa_log("IP_MULTICAST_LOOP failed: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c index 1311af3c1..0dab254bd 100644 --- a/src/pulsecore/modargs.c +++ b/src/pulsecore/modargs.c @@ -225,7 +225,7 @@ int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value) { return 0; } -int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value) { +int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, pa_bool_t *value) { const char *v; int r; diff --git a/src/pulsecore/modargs.h b/src/pulsecore/modargs.h index aa175885d..504b9cd70 100644 --- a/src/pulsecore/modargs.h +++ b/src/pulsecore/modargs.h @@ -28,6 +28,7 @@ #include #include #include +#include typedef struct pa_modargs pa_modargs; @@ -44,7 +45,7 @@ const char *pa_modargs_get_value(pa_modargs *ma, const char *key, const char *de /* Return a module argument as unsigned 32bit value in *value */ int pa_modargs_get_value_u32(pa_modargs *ma, const char *key, uint32_t *value); int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value); -int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, int *value); +int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, pa_bool_t *value); /* Return sample spec data from the three arguments "rate", "format" and "channels" */ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *ss); diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 76ba9dd08..004e535e4 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -1406,7 +1406,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *server, pa_module *m, pa_modargs *ma) { pa_protocol_esound *p = NULL; - int public = 0; + pa_bool_t public = FALSE; const char *acl; pa_assert(core); diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 9ae0f0837..1d294746d 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2956,7 +2956,7 @@ static int load_key(pa_protocol_native*p, const char*fn) { static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_modargs *ma) { pa_protocol_native *p; - int public = 0; + pa_bool_t public = FALSE; const char *acl; pa_assert(c); @@ -2976,7 +2976,7 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo #ifdef HAVE_CREDS { - int a = 1; + pa_bool_t a = 1; if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &a) < 0) { pa_log("auth-group-enabled= expects a boolean argument."); return NULL; diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 64e2a81c8..777def302 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -566,7 +566,7 @@ fail: pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) { pa_protocol_simple* p = NULL; - int enable; + pa_bool_t enable; pa_assert(core); pa_assert(server); @@ -587,7 +587,7 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv p->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL)); p->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); - enable = 0; + enable = FALSE; if (pa_modargs_get_value_boolean(ma, "record", &enable) < 0) { pa_log("record= expects a numeric argument."); goto fail; From 7b321eda3af7dbdd689152da9b3ca315d383b5b4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 13 Nov 2007 19:21:15 +0000 Subject: [PATCH 1452/1514] increase the pacmd timeout a bit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2051 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/utils/pacmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 16e5822f0..9583385b2 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -80,7 +80,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { goto fail; } - pa_msleep(50); + pa_msleep(300); } if (i >= 5) { From 15f56de8f2a10e092e11dfa3fc48ee28d2dd7e25 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 13 Nov 2007 19:39:23 +0000 Subject: [PATCH 1453/1514] don't touch RLIMIT:MEMBLOCK by default. This should improve out-of-the-box comaptibility with JACK git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2052 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 2 +- src/daemon/daemon.conf.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 089b12fca..3d63891ce 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -90,7 +90,7 @@ static const pa_daemon_conf default_conf = { , .rlimit_nproc = { .value = 0, .is_set = FALSE } #endif #ifdef RLIMIT_MEMLOCK - , .rlimit_memlock = { .value = 16384, .is_set = TRUE } + , .rlimit_memlock = { .value = 0, .is_set = FALSE } #endif #ifdef RLIMIT_NICE , .rlimit_nice = { .value = 31, .is_set = TRUE } /* nice level of -11 */ diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index f15d93e89..8d224e826 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -56,7 +56,7 @@ ; rlimit-nofile = 256 ; rlimit-stack = -1 ; rlimit-nproc = -1 -; rlimit-memlock = 16384 +; rlimit-memlock = -1 ; rlimit-nice = 31 ; rlimit-rtprio = 9 From 4a39c2e462fa31c6aedb7c3d2a9a211b6e3611d1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 13 Nov 2007 19:56:01 +0000 Subject: [PATCH 1454/1514] don't fail if the bt-proximity-helper is not built git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2053 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 36d27ef42..ebb8c6b42 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1478,7 +1478,7 @@ daemon.conf: daemon/daemon.conf.in Makefile install-exec-hook: chown root $(DESTDIR)$(bindir)/pulseaudio ; true chmod u+s $(DESTDIR)$(bindir)/pulseaudio - chmod u+s $(DESTDIR)$(pulselibexecdir)/bt-proximity-helper + -chmod u+s $(DESTDIR)$(pulselibexecdir)/bt-proximity-helper ln -sf pacat $(DESTDIR)$(bindir)/parec rm -f $(DESTDIR)$(modlibexecdir)/*.a rm -f $(DESTDIR)$(libdir)/libpulsedsp.a From 4c4761731df479a65f38ef0f4e9a079cd789ad3f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 13 Nov 2007 23:41:17 +0000 Subject: [PATCH 1455/1514] add array size to increase chance of detecting missing updates git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2054 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/channelmap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c index 2b8ef2b00..2b35ee752 100644 --- a/src/pulse/channelmap.c +++ b/src/pulse/channelmap.c @@ -36,7 +36,7 @@ #include "channelmap.h" -const char *const table[] = { +const char *const table[PA_CHANNEL_POSITION_MAX] = { [PA_CHANNEL_POSITION_MONO] = "mono", [PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center", @@ -99,7 +99,7 @@ const char *const table[] = { [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "top-rear-right" }; -const char *const pretty_table[] = { +const char *const pretty_table[PA_CHANNEL_POSITION_MAX] = { [PA_CHANNEL_POSITION_MONO] = "Mono", [PA_CHANNEL_POSITION_FRONT_CENTER] = "Front Center", @@ -531,4 +531,3 @@ int pa_channel_map_valid(const pa_channel_map *map) { return 1; } - From 7462ab1aca6ffb7b1e97834e2a8d0e0129604f6f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 13 Nov 2007 23:42:15 +0000 Subject: [PATCH 1456/1514] Rework ALSA mixer channel detection code. This time we actually care about the channel names the ALSA mixer exports for us git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2055 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/alsa-util.c | 132 ++++++++++++++++++++++++++++++- src/modules/alsa-util.h | 2 + src/modules/module-alsa-sink.c | 52 ++++++------ src/modules/module-alsa-source.c | 54 +++++++------ 4 files changed, 192 insertions(+), 48 deletions(-) diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c index 5b74c98c2..40170e9c2 100644 --- a/src/modules/alsa-util.c +++ b/src/modules/alsa-util.c @@ -310,8 +310,10 @@ int pa_alsa_set_hw_params( buffer_size = *periods * *period_size; - if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 || - (ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) + if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) + goto finish; + + if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) goto finish; if (_use_mmap) { @@ -627,7 +629,7 @@ int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) { pa_assert(dev); if ((err = snd_mixer_attach(mixer, dev)) < 0) { - pa_log_warn("Unable to attach to mixer %s: %s", dev, snd_strerror(err)); + pa_log_info("Unable to attach to mixer %s: %s", dev, snd_strerror(err)); return -1; } @@ -641,6 +643,8 @@ int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) { return -1; } + pa_log_info("Successfully attached to mixer '%s'", dev); + return 0; } @@ -656,7 +660,7 @@ snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const snd_mixer_selem_id_set_name(sid, name); if (!(elem = snd_mixer_find_selem(mixer, sid))) { - pa_log_warn("Cannot find mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); + pa_log_info("Cannot find mixer control \"%s\".", snd_mixer_selem_id_get_name(sid)); if (fallback) { snd_mixer_selem_id_set_name(sid, fallback); @@ -671,3 +675,123 @@ snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const return elem; } + +static const snd_mixer_selem_channel_id_t alsa_channel_ids[PA_CHANNEL_POSITION_MAX] = { + [PA_CHANNEL_POSITION_MONO] = SND_MIXER_SCHN_MONO, /* The ALSA name is just an alias! */ + + [PA_CHANNEL_POSITION_FRONT_CENTER] = SND_MIXER_SCHN_FRONT_CENTER, + [PA_CHANNEL_POSITION_FRONT_LEFT] = SND_MIXER_SCHN_FRONT_LEFT, + [PA_CHANNEL_POSITION_FRONT_RIGHT] = SND_MIXER_SCHN_FRONT_RIGHT, + + [PA_CHANNEL_POSITION_REAR_CENTER] = SND_MIXER_SCHN_REAR_CENTER, + [PA_CHANNEL_POSITION_REAR_LEFT] = SND_MIXER_SCHN_REAR_LEFT, + [PA_CHANNEL_POSITION_REAR_RIGHT] = SND_MIXER_SCHN_REAR_RIGHT, + + [PA_CHANNEL_POSITION_LFE] = SND_MIXER_SCHN_WOOFER, + + [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = SND_MIXER_SCHN_UNKNOWN, + + [PA_CHANNEL_POSITION_SIDE_LEFT] = SND_MIXER_SCHN_SIDE_LEFT, + [PA_CHANNEL_POSITION_SIDE_RIGHT] = SND_MIXER_SCHN_SIDE_RIGHT, + + [PA_CHANNEL_POSITION_AUX0] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX1] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX2] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX3] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX4] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX5] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX6] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX7] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX8] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX9] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX10] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX11] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX12] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX13] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX14] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX15] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX16] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX17] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX18] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX19] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX20] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX21] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX22] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX23] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX24] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX25] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX26] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX27] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX28] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX29] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX30] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_AUX31] = SND_MIXER_SCHN_UNKNOWN, + + [PA_CHANNEL_POSITION_TOP_CENTER] = SND_MIXER_SCHN_UNKNOWN, + + [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = SND_MIXER_SCHN_UNKNOWN, + + [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = SND_MIXER_SCHN_UNKNOWN, + [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = SND_MIXER_SCHN_UNKNOWN +}; + + +int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel_map, snd_mixer_selem_channel_id_t mixer_map[], pa_bool_t playback) { + unsigned i; + pa_bool_t alsa_channel_used[SND_MIXER_SCHN_LAST]; + pa_bool_t mono_used = FALSE; + + pa_assert(elem); + pa_assert(channel_map); + pa_assert(mixer_map); + + memset(&alsa_channel_used, 0, sizeof(alsa_channel_used)); + + if (channel_map->channels > 1 && + ((playback && snd_mixer_selem_has_playback_volume_joined(elem)) || + (!playback && snd_mixer_selem_has_capture_volume_joined(elem)))) { + pa_log_info("ALSA device lacks independant volume controls for each channel, falling back to software volume control."); + return -1; + } + + for (i = 0; i < channel_map->channels; i++) { + snd_mixer_selem_channel_id_t id; + pa_bool_t is_mono; + + is_mono = channel_map->map[i] == PA_CHANNEL_POSITION_MONO; + id = alsa_channel_ids[channel_map->map[i]]; + + if (!is_mono && id == SND_MIXER_SCHN_UNKNOWN) { + pa_log_info("Configured channel map contains channel '%s' that is unknown to the ALSA mixer. Falling back to software volume control.", pa_channel_position_to_string(channel_map->map[i])); + return -1; + } + + if ((is_mono && mono_used) || (!is_mono && alsa_channel_used[id])) { + pa_log_info("Channel map has duplicate channel '%s', failling back to software volume control.", pa_channel_position_to_string(channel_map->map[i])); + return -1; + } + + if ((playback && (!snd_mixer_selem_has_playback_channel(elem, id) || (is_mono && !snd_mixer_selem_is_playback_mono(elem)))) || + (!playback && (!snd_mixer_selem_has_capture_channel(elem, id) || (is_mono && !snd_mixer_selem_is_capture_mono(elem))))) { + + pa_log_info("ALSA device lacks separate volumes control for channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map->map[i])); + return -1; + } + + if (is_mono) { + mixer_map[i] = SND_MIXER_SCHN_MONO; + mono_used = TRUE; + } else { + mixer_map[i] = id; + alsa_channel_used[id] = TRUE; + } + } + + pa_log_info("All %u channels can be mapped to mixer channels. Using hardware volume control.", channel_map->channels); + + return 0; +} diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h index 36720b039..53d9a2fb9 100644 --- a/src/modules/alsa-util.h +++ b/src/modules/alsa-util.h @@ -71,4 +71,6 @@ snd_pcm_t *pa_alsa_open_by_device_string( snd_pcm_uframes_t *period_size, pa_bool_t *use_mmap); +int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel_map, snd_mixer_selem_channel_id_t mixer_map[], pa_bool_t playback); + #endif diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index e62b8a067..14aef7c90 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -95,6 +95,8 @@ struct userdata { pa_bool_t first; pa_rtpoll_item *alsa_rtpoll_item; + + snd_mixer_selem_channel_id_t mixer_map[SND_MIXER_SCHN_LAST]; }; static const char* const valid_modargs[] = { @@ -505,9 +507,9 @@ static int sink_get_volume_cb(pa_sink *s) { for (i = 0; i < s->sample_spec.channels; i++) { long set_vol, vol; - pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); + pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, u->mixer_map[i])); - if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol)) < 0) + if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &vol)) < 0) goto fail; set_vol = (long) roundf(((float) s->volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; @@ -539,7 +541,7 @@ static int sink_set_volume_cb(pa_sink *s) { long alsa_vol; pa_volume_t vol; - pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); + pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, u->mixer_map[i])); vol = s->volume.values[i]; @@ -548,7 +550,7 @@ static int sink_set_volume_cb(pa_sink *s) { alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; - if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, alsa_vol)) < 0) + if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0) goto fail; } @@ -826,10 +828,25 @@ int pa__init(pa_module*m) { if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) pa_log_warn("Error opening mixer: %s", snd_strerror(err)); else { + pa_bool_t found = FALSE; - if ((pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) < 0) || - !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM"))) { + if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0) + found = TRUE; + else { + char *md = pa_sprintf_malloc("hw:%s", dev_id); + if (strcmp(u->device_name, md)) + if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0) + found = TRUE; + + pa_xfree(md); + } + + if (found) + if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM"))) + found = FALSE; + + if (!found) { snd_mixer_close(u->mixer_handle); u->mixer_handle = NULL; } @@ -863,7 +880,7 @@ int pa__init(pa_module*m) { use_mmap ? " via DMA" : "")); pa_xfree(t); - u->sink->flags = PA_SINK_HARDWARE|PA_SINK_HW_VOLUME_CTRL|PA_SINK_LATENCY; + u->sink->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY; u->frame_size = frame_size; u->fragment_size = frag_size = period_size * frame_size; @@ -875,35 +892,26 @@ int pa__init(pa_module*m) { pa_memchunk_reset(&u->memchunk); if (u->mixer_handle) { - /* Initialize mixer code */ - pa_assert(u->mixer_elem); - if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) { - int i; - - for (i = 0; i < ss.channels; i++) - if (!snd_mixer_selem_has_playback_channel(u->mixer_elem, i)) - break; - - if (i == ss.channels) { - pa_log_debug("ALSA device has separate volumes controls for all %u channels.", ss.channels); + if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) + if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, TRUE) >= 0) { u->sink->get_volume = sink_get_volume_cb; u->sink->set_volume = sink_set_volume_cb; snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); - } else - pa_log_info("ALSA device lacks separate volumes controls for all %u channels (%u available), falling back to software volume control.", ss.channels, i+1); - } + u->sink->flags |= PA_SINK_HW_VOLUME_CTRL; + } if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) { u->sink->get_mute = sink_get_mute_cb; u->sink->set_mute = sink_set_mute_cb; + u->sink->flags |= PA_SINK_HW_VOLUME_CTRL; } u->mixer_fdl = pa_alsa_fdlist_new(); if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, m->core->mainloop) < 0) { - pa_log("failed to initialise file descriptor monitoring"); + pa_log("Failed to initialize file descriptor monitoring"); goto fail; } diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 2d2bfa070..23a2f921c 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -93,6 +93,8 @@ struct userdata { pa_bool_t use_mmap; pa_rtpoll_item *alsa_rtpoll_item; + + snd_mixer_selem_channel_id_t mixer_map[SND_MIXER_SCHN_LAST]; }; static const char* const valid_modargs[] = { @@ -494,9 +496,9 @@ static int source_get_volume_cb(pa_source *s) { for (i = 0; i < s->sample_spec.channels; i++) { long set_vol, vol; - pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i)); + pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i])); - if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol)) < 0) + if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &vol)) < 0) goto fail; set_vol = (long) roundf(((float) s->volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; @@ -528,7 +530,7 @@ static int source_set_volume_cb(pa_source *s) { long alsa_vol; pa_volume_t vol; - pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i)); + pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i])); vol = s->volume.values[i]; @@ -537,7 +539,7 @@ static int source_set_volume_cb(pa_source *s) { alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min; - if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, i, alsa_vol)) < 0) + if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0) goto fail; } @@ -753,6 +755,8 @@ int pa__init(pa_module*m) { snd_config_update_free_global(); + b = use_mmap; + if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) { if (!(u->pcm_handle = pa_alsa_open_by_device_id( @@ -800,16 +804,28 @@ int pa__init(pa_module*m) { /* ALSA might tweak the sample spec, so recalculate the frame size */ frame_size = pa_frame_size(&ss); - if (ss.channels != map.channels) - /* Seems ALSA didn't like the channel number, so let's fix the channel map */ - pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); - if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) pa_log("Error opening mixer: %s", snd_strerror(err)); else { + pa_bool_t found = FALSE; - if ((pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) < 0) || - !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", NULL))) { + if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0) + found = TRUE; + else { + char *md = pa_sprintf_malloc("hw:%s", dev_id); + + if (strcmp(u->device_name, md)) + if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0) + found = TRUE; + + pa_xfree(md); + } + + if (found) + if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", "Mic"))) + found = FALSE; + + if (!found) { snd_mixer_close(u->mixer_handle); u->mixer_handle = NULL; } @@ -843,7 +859,7 @@ int pa__init(pa_module*m) { use_mmap ? " via DMA" : "")); pa_xfree(t); - u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL; + u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY; u->frame_size = frame_size; u->fragment_size = frag_size = period_size * frame_size; @@ -855,30 +871,24 @@ int pa__init(pa_module*m) { if (u->mixer_handle) { pa_assert(u->mixer_elem); - if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) { - int i; - - for (i = 0;i < ss.channels;i++) { - if (!snd_mixer_selem_has_capture_channel(u->mixer_elem, i)) - break; - } - - if (i == ss.channels) { + if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) + if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, FALSE) >= 0) { u->source->get_volume = source_get_volume_cb; u->source->set_volume = source_set_volume_cb; snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); + u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL; } - } if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) { u->source->get_mute = source_get_mute_cb; u->source->set_mute = source_set_mute_cb; + u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL; } u->mixer_fdl = pa_alsa_fdlist_new(); if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, m->core->mainloop) < 0) { - pa_log("failed to initialise file descriptor monitoring"); + pa_log("Failed to initialize file descriptor monitoring"); goto fail; } From 9b75b9de563bb61ef4b8f2000ed973fecba1137a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 14 Nov 2007 16:09:03 +0000 Subject: [PATCH 1457/1514] add missing pa_boolization git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2056 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-jack-sink.c | 2 +- src/modules/module-jack-source.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index 44da068f3..46e128c98 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -273,7 +273,7 @@ int pa__init(pa_module*m) { jack_status_t status; const char *server_name, *client_name; uint32_t channels = 0; - int do_connect = 1; + pa_bool_t do_connect = TRUE; unsigned i; const char **ports = NULL, **p; char *t; diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c index 936180205..f81c719af 100644 --- a/src/modules/module-jack-source.c +++ b/src/modules/module-jack-source.c @@ -250,7 +250,7 @@ int pa__init(pa_module*m) { jack_status_t status; const char *server_name, *client_name; uint32_t channels = 0; - int do_connect = 1; + pa_bool_t do_connect = TRUE; unsigned i; const char **ports = NULL, **p; char *t; From 1765b13386936bfc57cdd68ec9e97186e16bea9a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 14 Nov 2007 16:10:36 +0000 Subject: [PATCH 1458/1514] use a free list for allocating reply_info structs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2057 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/pdispatch.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index 2c95d7407..bdd7cde1e 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "pdispatch.h" @@ -98,6 +99,8 @@ static const char *command_names[PA_COMMAND_MAX] = { #endif +PA_STATIC_FLIST_DECLARE(reply_infos, 0, pa_xfree); + struct reply_info { pa_pdispatch *pdispatch; PA_LLIST_FIELDS(struct reply_info); @@ -129,7 +132,8 @@ static void reply_info_free(struct reply_info *r) { PA_LLIST_REMOVE(struct reply_info, r->pdispatch->replies, r); - pa_xfree(r); + if (pa_flist_push(PA_STATIC_FLIST_GET(reply_infos), r) < 0) + pa_xfree(r); } pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, const pa_pdispatch_cb_t*table, unsigned entries) { @@ -273,7 +277,9 @@ void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa pa_assert(PA_REFCNT_VALUE(pd) >= 1); pa_assert(cb); - r = pa_xnew(struct reply_info, 1); + if (!(r = pa_flist_pop(PA_STATIC_FLIST_GET(reply_infos)))) + r = pa_xnew(struct reply_info, 1); + r->pdispatch = pd; r->callback = cb; r->userdata = userdata; From 461e36910a20a5cfa7ed333b718b705f9ec9d0fd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 14 Nov 2007 16:11:09 +0000 Subject: [PATCH 1459/1514] use a free list for allocation pa_operation objects git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2058 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/operation.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pulse/operation.c b/src/pulse/operation.c index ed5eb4aa1..8a782fd17 100644 --- a/src/pulse/operation.c +++ b/src/pulse/operation.c @@ -27,15 +27,20 @@ #include #include +#include #include "internal.h" #include "operation.h" +PA_STATIC_FLIST_DECLARE(operations, 0, pa_xfree); + pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb, void *userdata) { pa_operation *o; pa_assert(c); - o = pa_xnew(pa_operation, 1); + if (!(o = pa_flist_pop(PA_STATIC_FLIST_GET(operations)))) + o = pa_xnew(pa_operation, 1); + PA_REFCNT_INIT(o); o->context = c; o->stream = s; @@ -66,7 +71,9 @@ void pa_operation_unref(pa_operation *o) { if (PA_REFCNT_DEC(o) <= 0) { pa_assert(!o->context); pa_assert(!o->stream); - pa_xfree(o); + + if (pa_flist_push(PA_STATIC_FLIST_GET(operations), o) < 0) + pa_xfree(o); } } From 413a8f8917256ef44a58fc8519bcc93644423373 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 14 Nov 2007 16:11:51 +0000 Subject: [PATCH 1460/1514] use a prio inheriting mutex for the threaded mainloop, to ease writing of RT clients git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2059 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/thread-mainloop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c index 9dd47ae32..e8c956bb1 100644 --- a/src/pulse/thread-mainloop.c +++ b/src/pulse/thread-mainloop.c @@ -103,7 +103,7 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) { return NULL; } - m->mutex = pa_mutex_new(TRUE, FALSE); + m->mutex = pa_mutex_new(TRUE, TRUE); m->cond = pa_cond_new(); m->accept_cond = pa_cond_new(); m->thread = NULL; From 8bdad297e3aaeb7443a92aecd3cd26dbd47a421e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Nov 2007 23:46:22 +0000 Subject: [PATCH 1461/1514] add interface to PolicyKit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2060 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/PulseAudio.policy | 49 ++++++++ src/daemon/polkit.c | 223 +++++++++++++++++++++++++++++++++++ src/daemon/polkit.h | 29 +++++ 3 files changed, 301 insertions(+) create mode 100644 src/daemon/PulseAudio.policy create mode 100644 src/daemon/polkit.c create mode 100644 src/daemon/polkit.h diff --git a/src/daemon/PulseAudio.policy b/src/daemon/PulseAudio.policy new file mode 100644 index 000000000..55ebbf9c0 --- /dev/null +++ b/src/daemon/PulseAudio.policy @@ -0,0 +1,49 @@ + + + + + + + + + + + Real-time scheduling for the PulseAudio daemon + System policy prevents PulseAudio from acquiring real-time scheduling. + + no + no + auth_admin_keep_always + + + + + High-priority scheduling (negative Unix nice level) for the PulseAudio daemon + System policy prevents PulseAudio from acquiring high-priority scheduling. + + no + no + auth_admin_keep_always + + + + diff --git a/src/daemon/polkit.c b/src/daemon/polkit.c new file mode 100644 index 000000000..362c51948 --- /dev/null +++ b/src/daemon/polkit.c @@ -0,0 +1,223 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include +#include + +#include "polkit.h" + +static pa_bool_t show_grant_dialog(const char *action_id) { + DBusError dbus_error; + DBusConnection *bus = NULL; + DBusMessage *m = NULL, *reply = NULL; + pa_bool_t r = FALSE; + uint32_t xid = 0; + int verdict; + + dbus_error_init(&dbus_error); + + if (!(bus = dbus_bus_get(DBUS_BUS_SESSION, &dbus_error))) { + pa_log_error("Cannot connect to session bus: %s", dbus_error.message); + goto finish; + } + + if (!(m = dbus_message_new_method_call("org.gnome.PolicyKit", "/org/gnome/PolicyKit/Manager", "org.gnome.PolicyKit.Manager", "ShowDialog"))) { + pa_log_error("Failed to allocate D-Bus message."); + goto finish; + } + + if (!(dbus_message_append_args(m, DBUS_TYPE_STRING, &action_id, DBUS_TYPE_UINT32, &xid, DBUS_TYPE_INVALID))) { + pa_log_error("Failed to append arguments to D-Bus message."); + goto finish; + } + + if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &dbus_error))) { + pa_log_warn("Failed to show grant dialog: %s", dbus_error.message); + goto finish; + } + + if (!(dbus_message_get_args(reply, &dbus_error, DBUS_TYPE_BOOLEAN, &verdict, DBUS_TYPE_INVALID))) { + pa_log_warn("Malformed response from grant manager: %s", dbus_error.message); + goto finish; + } + + r = !!verdict; + +finish: + + if (bus) + dbus_connection_unref(bus); + + dbus_error_free(&dbus_error); + + if (m) + dbus_message_unref(m); + + if (reply) + dbus_message_unref(reply); + + return r; +} + +int pa_polkit_check(const char *action_id) { + int ret = -1; + DBusError dbus_error; + DBusConnection *bus = NULL; + PolKitCaller *caller = NULL; + PolKitAction *action = NULL; + PolKitContext *context = NULL; + PolKitError *polkit_error = NULL; + PolKitSession *session = NULL; + PolKitResult polkit_result; + + dbus_error_init(&dbus_error); + + if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error))) { + pa_log_error("Cannot connect to system bus: %s", dbus_error.message); + goto finish; + } + + if (!(caller = polkit_caller_new_from_pid(bus, getpid(), &dbus_error))) { + pa_log_error("Cannot get caller from PID: %s", dbus_error.message); + goto finish; + } + + /* This function is called when PulseAudio is called SUID root. We + * want to authenticate the real user that called us and not the + * effective user we gained through being SUID root. Hence we + * overwrite the UID caller data here explicitly, just for + * paranoia. In fact PolicyKit should fill in the UID here anyway + * -- an not the EUID or any other user id. */ + + if (!(polkit_caller_set_uid(caller, getuid()))) { + pa_log_error("Cannot set UID on caller object."); + goto finish; + } + + if (!(polkit_caller_get_ck_session(caller, &session))) { + pa_log_error("Failed to get CK session."); + goto finish; + } + + /* We need to overwrite the UID in both the caller and the session + * object */ + + if (!(polkit_session_set_uid(session, getuid()))) { + pa_log_error("Cannot set UID on session object."); + goto finish; + } + + if (!(action = polkit_action_new())) { + pa_log_error("Cannot allocate PolKitAction."); + goto finish; + } + + if (!polkit_action_set_action_id(action, action_id)) { + pa_log_error("Cannot set action_id"); + goto finish; + } + + if (!(context = polkit_context_new())) { + pa_log_error("Cannot allocate PolKitContext."); + goto finish; + } + + if (!polkit_context_init(context, &polkit_error)) { + pa_log_error("Cannot initialize PolKitContext: %s", polkit_error_get_error_message(polkit_error)); + goto finish; + } + + for (;;) { + +#ifdef HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED + polkit_result = polkit_context_is_caller_authorized(context, action, caller, TRUE, &polkit_error); + + if (polkit_error_is_set(polkit_error)) { + pa_log_error("Could not determine whether caller is authorized: %s", polkit_error_get_error_message(polkit_error)); + goto finish; + } +#else + + polkit_result = polkit_context_can_caller_do_action(context, action, caller); + +#endif + + if (polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH || + polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION || + polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS || +#ifdef POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT + polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT || +#endif + polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH || + polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION || + polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS +#ifdef POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT + || polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT +#endif + ) { + + if (show_grant_dialog(action_id)) + continue; + } + + break; + } + + if (polkit_result != POLKIT_RESULT_YES && polkit_result != POLKIT_RESULT_NO) + pa_log_warn("PolicyKit responded with '%s'", polkit_result_to_string_representation(polkit_result)); + + ret = polkit_result == POLKIT_RESULT_YES; + +finish: + + if (caller) + polkit_caller_unref(caller); + + if (action) + polkit_action_unref(action); + + if (context) + polkit_context_unref(context); + + if (bus) + dbus_connection_unref(bus); + + dbus_error_free(&dbus_error); + + if (polkit_error) + polkit_error_free(polkit_error); + + return ret; +} diff --git a/src/daemon/polkit.h b/src/daemon/polkit.h new file mode 100644 index 000000000..cbcf6a6af --- /dev/null +++ b/src/daemon/polkit.h @@ -0,0 +1,29 @@ +#ifndef foopolkithfoo +#define foopolkithfoo + +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + Copyright 2007 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +int pa_polkit_check(const char *action); + +#endif From cf0d43e7d0edc19b3c2678d0288682b5611b30e7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Nov 2007 23:47:28 +0000 Subject: [PATCH 1462/1514] build PolicyKit support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2061 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index ebb8c6b42..158560ded 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -102,7 +102,8 @@ EXTRA_DIST = \ utils/padsp \ modules/module-defs.h.m4 \ daemon/pulseaudio-module-xsmp.desktop \ - map-file + map-file \ + daemon/PulseAudio.policy pulseconf_DATA = \ default.pa \ @@ -151,6 +152,17 @@ else pulseaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f)) endif +if HAVE_POLKIT + +policy_DATA = daemon/PulseAudio.policy + +pulseaudio_SOURCES += daemon/polkit.c daemon/polkit.h +pulseaudio_CFLAGS += $(POLKIT_CFLAGS) +pulseaudio_LDADD += $(POLKIT_LIBS) + + +endif + ################################### # Utility programs # ################################### From 07832d080aea8029f53ab211d30e286a4bfc7172 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Nov 2007 23:48:09 +0000 Subject: [PATCH 1463/1514] detect whether PolicyKit support is available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2062 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/configure.ac b/configure.ac index b5834f0f2..30a70e11e 100644 --- a/configure.ac +++ b/configure.ac @@ -862,6 +862,47 @@ AC_SUBST(DBUS_LIBS) AC_SUBST(HAVE_DBUS) AM_CONDITIONAL([HAVE_DBUS], [test "x$HAVE_DBUS" = x1]) +#### PolicyKit support (optional) #### + +AC_ARG_ENABLE([polkit], + AC_HELP_STRING([--disable-polkit], [Disable optional PolicyKit support]), + [ + case "${enableval}" in + yes) polkit=yes ;; + no) polkit=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-polkit) ;; + esac + ], + [polkit=auto]) + +if test "x${polkit}" != xno ; then + + PKG_CHECK_MODULES(POLKIT, [ polkit-dbus ], + [ + HAVE_POLKIT=1 + saved_LIBS="$LIBS" + LIBS="$LIBS POLKIT_LIBS" + AC_CHECK_FUNCS(polkit_context_is_caller_authorized) + LIBS="$saved_LIBS" + AC_DEFINE([HAVE_POLKIT], 1, [Have PolicyKit]) + policydir=`pkg-config --variable prefix`/usr/share/PolicyKit/policy/ + AC_SUBST(policydir) + ], + [ + HAVE_POLKIT=0 + if test "x$polkit" = xyes ; then + AC_MSG_ERROR([*** PolicyKit support not found]) + fi + ]) +else + HAVE_POLKIT=0 +fi + +AC_SUBST(POLKIT_CFLAGS) +AC_SUBST(POLKIT_LIBS) +AC_SUBST(HAVE_POLKIT) +AM_CONDITIONAL([HAVE_POLKIT], [test "x$HAVE_POLKIT" = x1]) + ### Build and Install man pages ### AC_ARG_ENABLE(manpages, AS_HELP_STRING([--disable-manpages],[Disable building and installation of man pages]), @@ -1063,6 +1104,11 @@ if test "x${HAVE_BLUEZ}" = "x1" ; then ENABLE_BLUEZ=yes fi +ENABLE_POLKIT=no +if test "x${HAVE_POLKIT}" = "x1" ; then + ENABLE_POLKIT=yes +fi + echo " ---{ $PACKAGE_NAME $VERSION }--- @@ -1086,6 +1132,7 @@ echo " Enable BlueZ: ${ENABLE_BLUEZ} Enable TCP Wrappers: ${ENABLE_TCPWRAP} Enable libsamplerate: ${ENABLE_LIBSAMPLERATE} + Enable PolicyKit: ${ENABLE_POLKIT} System User: ${PA_SYSTEM_USER} System Group: ${PA_SYSTEM_GROUP} Realtime Group: ${PA_REALTIME_GROUP} From d1d07783e0943ad51371978793d91f5b9990e17d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 01:19:28 +0000 Subject: [PATCH 1464/1514] add API to allow runtime reconfiguration of memblockqs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2063 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/memblockq.c | 95 +++++++++++++++++++++++++++++---------- src/pulsecore/memblockq.h | 6 +++ 2 files changed, 78 insertions(+), 23 deletions(-) diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index a46155a9f..8247feab2 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -72,7 +72,6 @@ pa_memblockq* pa_memblockq_new( pa_memblockq* bq; pa_assert(base > 0); - pa_assert(maxlength >= base); bq = pa_xnew(pa_memblockq, 1); bq->blocks = bq->blocks_tail = NULL; @@ -84,36 +83,20 @@ pa_memblockq* pa_memblockq_new( pa_log_debug("memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", (unsigned long) maxlength, (unsigned long) tlength, (unsigned long) base, (unsigned long) prebuf, (unsigned long) minreq); - bq->maxlength = ((maxlength+base-1)/base)*base; - pa_assert(bq->maxlength >= base); + bq->missing = bq->requested = bq->maxlength = bq->tlength = bq->prebuf = bq->minreq = 0; + bq->in_prebuf = TRUE; - bq->tlength = ((tlength+base-1)/base)*base; - if (bq->tlength <= 0 || bq->tlength > bq->maxlength) - bq->tlength = bq->maxlength; - - bq->prebuf = (prebuf == (size_t) -1) ? bq->tlength/2 : prebuf; - bq->prebuf = ((bq->prebuf+base-1)/base)*base; - if (bq->prebuf > bq->maxlength) - bq->prebuf = bq->maxlength; - - bq->minreq = (minreq/base)*base; - - if (bq->minreq > bq->tlength - bq->prebuf) - bq->minreq = bq->tlength - bq->prebuf; - - if (!bq->minreq) - bq->minreq = 1; + pa_memblockq_set_maxlength(bq, maxlength); + pa_memblockq_set_tlength(bq, tlength); + pa_memblockq_set_prebuf(bq, prebuf); + pa_memblockq_set_minreq(bq, minreq); pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu", (unsigned long)bq->maxlength, (unsigned long)bq->tlength, (unsigned long)bq->base, (unsigned long)bq->prebuf, (unsigned long)bq->minreq); - bq->in_prebuf = bq->prebuf > 0; bq->silence = silence ? pa_memblock_ref(silence) : NULL; bq->mcalign = NULL; - bq->missing = bq->tlength; - bq->requested = 0; - return bq; } @@ -688,3 +671,69 @@ size_t pa_memblockq_pop_missing(pa_memblockq *bq) { return l; } + +void pa_memblockq_set_maxlength(pa_memblockq *bq, size_t maxlength) { + pa_assert(bq); + + bq->maxlength = ((maxlength+bq->base-1)/bq->base)*bq->base; + + if (bq->maxlength < bq->base) + bq->maxlength = bq->base; + + if (bq->tlength > bq->maxlength) + pa_memblockq_set_tlength(bq, bq->maxlength); + + if (bq->prebuf > bq->maxlength) + pa_memblockq_set_prebuf(bq, bq->maxlength); +} + +void pa_memblockq_set_tlength(pa_memblockq *bq, size_t tlength) { + size_t old_tlength; + pa_assert(bq); + + old_tlength = bq->tlength; + + if (tlength <= 0) + tlength = bq->maxlength; + + bq->tlength = ((tlength+bq->base-1)/bq->base)*bq->base; + + if (bq->tlength > bq->maxlength) + bq->tlength = bq->maxlength; + + if (bq->minreq > bq->tlength - bq->prebuf) + pa_memblockq_set_minreq(bq, bq->tlength - bq->prebuf); + + bq->missing += (int64_t) bq->tlength - (int64_t) old_tlength; +} + +void pa_memblockq_set_prebuf(pa_memblockq *bq, size_t prebuf) { + pa_assert(bq); + + bq->prebuf = (prebuf == (size_t) -1) ? bq->tlength/2 : prebuf; + bq->prebuf = ((bq->prebuf+bq->base-1)/bq->base)*bq->base; + + if (prebuf > 0 && bq->prebuf < bq->base) + bq->prebuf = bq->base; + + if (bq->prebuf > bq->maxlength) + bq->prebuf = bq->maxlength; + + if (bq->prebuf <= 0 || pa_memblockq_get_length(bq) >= bq->prebuf) + bq->in_prebuf = FALSE; + + if (bq->minreq > bq->tlength - bq->prebuf) + pa_memblockq_set_minreq(bq, bq->tlength - bq->prebuf); +} + +void pa_memblockq_set_minreq(pa_memblockq *bq, size_t minreq) { + pa_assert(bq); + + bq->minreq = (minreq/bq->base)*bq->base; + + if (bq->minreq > bq->tlength - bq->prebuf) + bq->minreq = bq->tlength - bq->prebuf; + + if (bq->minreq < bq->base) + bq->minreq = bq->base; +} diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h index 8c3e70fc3..46637f10c 100644 --- a/src/pulsecore/memblockq.h +++ b/src/pulsecore/memblockq.h @@ -142,4 +142,10 @@ size_t pa_memblockq_get_maxlength(pa_memblockq *bq); /* Return the prebuffer length in bytes */ size_t pa_memblockq_get_prebuf(pa_memblockq *bq); +/* Change metrics. */ +void pa_memblockq_set_maxlength(pa_memblockq *memblockq, size_t maxlength); +void pa_memblockq_set_tlength(pa_memblockq *memblockq, size_t tlength); +void pa_memblockq_set_prebuf(pa_memblockq *memblockq, size_t prebuf); +void pa_memblockq_set_minreq(pa_memblockq *memblockq, size_t minreq); + #endif From 63fa021451e5bc97c1cdde35d0a90b8e9e090c73 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 01:20:16 +0000 Subject: [PATCH 1465/1514] add a couple of new opcodes, and document the versions the opcodes where added git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2064 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/native-common.h | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h index 9defc4a53..3ab2361bc 100644 --- a/src/pulsecore/native-common.h +++ b/src/pulsecore/native-common.h @@ -36,10 +36,10 @@ enum { PA_COMMAND_TIMEOUT, /* pseudo command */ PA_COMMAND_REPLY, - /* Commands from client to server */ - PA_COMMAND_CREATE_PLAYBACK_STREAM, + /* CLIENT->SERVER */ + PA_COMMAND_CREATE_PLAYBACK_STREAM, /* Payload changed in v9, v12 (0.9.0, 0.9.8) */ PA_COMMAND_DELETE_PLAYBACK_STREAM, - PA_COMMAND_CREATE_RECORD_STREAM, + PA_COMMAND_CREATE_RECORD_STREAM, /* Payload changed in v9, v12 (0.9.0, 0.9.8) */ PA_COMMAND_DELETE_RECORD_STREAM, PA_COMMAND_EXIT, PA_COMMAND_AUTH, @@ -64,8 +64,8 @@ enum { PA_COMMAND_GET_MODULE_INFO_LIST, PA_COMMAND_GET_CLIENT_INFO, PA_COMMAND_GET_CLIENT_INFO_LIST, - PA_COMMAND_GET_SINK_INPUT_INFO, - PA_COMMAND_GET_SINK_INPUT_INFO_LIST, + PA_COMMAND_GET_SINK_INPUT_INFO, /* Payload changed in v11 (0.9.7) */ + PA_COMMAND_GET_SINK_INPUT_INFO_LIST, /* Payload changed in v11 (0.9.7) */ PA_COMMAND_GET_SOURCE_OUTPUT_INFO, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, PA_COMMAND_GET_SAMPLE_INFO, @@ -92,18 +92,21 @@ enum { PA_COMMAND_KILL_CLIENT, PA_COMMAND_KILL_SINK_INPUT, PA_COMMAND_KILL_SOURCE_OUTPUT, + PA_COMMAND_LOAD_MODULE, PA_COMMAND_UNLOAD_MODULE, + PA_COMMAND_ADD_AUTOLOAD, PA_COMMAND_REMOVE_AUTOLOAD, PA_COMMAND_GET_AUTOLOAD_INFO, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, + PA_COMMAND_GET_RECORD_LATENCY, PA_COMMAND_CORK_RECORD_STREAM, PA_COMMAND_FLUSH_RECORD_STREAM, PA_COMMAND_PREBUF_PLAYBACK_STREAM, - /* Commands from server to client */ + /* SERVER->CLIENT */ PA_COMMAND_REQUEST, PA_COMMAND_OVERFLOW, PA_COMMAND_UNDERFLOW, @@ -112,14 +115,30 @@ enum { PA_COMMAND_SUBSCRIBE_EVENT, /* A few more client->server commands */ + + /* Supported since protocol v10 (0.9.5) */ PA_COMMAND_MOVE_SINK_INPUT, PA_COMMAND_MOVE_SOURCE_OUTPUT, + /* Supported since protocol v11 (0.9.7) */ PA_COMMAND_SET_SINK_INPUT_MUTE, PA_COMMAND_SUSPEND_SINK, PA_COMMAND_SUSPEND_SOURCE, + /* Supported since protocol v13 (0.9.8) */ + PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR, + PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR, + + PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE, + PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE, + + /* SERVER->CLIENT */ + PA_COMMAND_PLAYBACK_STREAM_SUSPENDED, + PA_COMMAND_RECORD_STREAM_SUSPENDED, + PA_COMMAND_PLAYBACK_STREAM_MOVED, + PA_COMMAND_RECORD_STREAM_MOVED, + PA_COMMAND_MAX }; From 5a4959eb905e7f314c05f482eb4344ad4c7d0813 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 01:21:00 +0000 Subject: [PATCH 1466/1514] add short version history of the PA protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2065 fefdeb5f-60dc-0310-8127-8f9354f1896f --- PROTOCOL | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 PROTOCOL diff --git a/PROTOCOL b/PROTOCOL new file mode 100644 index 000000000..497fa47b4 --- /dev/null +++ b/PROTOCOL @@ -0,0 +1,80 @@ +### v8, implemented by >= 0.8 + +First version supported. + +### v9, implemented by >= 0.9.0 + +Reply for PA_COMMAND_CREATE_PLAYBACK_STREAM, +PA_COMMAND_CREATE_RECORD_STREAM now returns buffer_attrs that are used: + +Four new fields in reply of PA_COMMAND_CREATE_PLAYBACK_STREAM: + + maxlength + tlength + prebuf + minreq + +Two new fields in reply of PA_COMMAND_CREATE_RECORD_STREAM: + + maxlength + fragsize + +### v10, implemented by >= 0.9.5 + +New opcodes: + + PA_COMMAND_MOVE_SINK_INPUT + PA_COMMAND_MOVE_SOURCE_OUTPUT + +SHM data transfer support + +### v11, implemented by >= 0.9.7 + +Reply to to PA_COMMAND_GET_SINK_INPUT_INFO, PA_COMMAND_GET_SINK_INPUT_INFO_LIST gets new field at the end: + + mute + +New opcodes: + + PA_COMMAND_SET_SINK_INPUT_MUTE + PA_COMMAND_SUSPEND_SINK + PA_COMMAND_SUSPEND_SOURCE + +### v12, implemented by >= 0.9.8 + +S32LE, S32BE is now known as sample spec. + +Gained six new bool fields for PA_COMMAND_CREATE_PLAYBACK_STREAM, PA_COMMAND_CREATE_RECORD_STREAM request at the end: + + no_remap_channels + no_remix_channels + fix_format + fix_rate + fix_channels + no_move + variable_rate + +Reply to these opcodes now includes: + + sample_spec + channel_map + device_index + device_name + suspended + +New opcodes for changing buffer attrs: + + PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR + PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR + +New opcodes for changing sampling rate: + + PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE + PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE + +New opcodes for notifications: + + PA_COMMAND_PLAYBACK_STREAM_SUSPENDED + PA_COMMAND_CAPTURE_STREAM_SUSPENDED + PA_COMMAND_PLAYBACK_STREAM_MOVED + PA_COMMAND_CAPTURE_STREAM_MOVED From 4ac6b53478be63ae5d0163a330e67e4134f17f89 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 01:21:53 +0000 Subject: [PATCH 1467/1514] minor typo fix git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2066 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 8352a790f..a7df8a0ce 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -1155,7 +1155,7 @@ int pa__init(pa_module*m) { } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { - pa_log("record= and playback= expect numeric argument."); + pa_log("record= and playback= expect boolean argument."); goto fail; } From 14a9b80afbb0bddc216462b72156f14e032e1b5e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 01:30:40 +0000 Subject: [PATCH 1468/1514] - Check process name when dealing with PID files - Add new PA_STREAM_FIX_CHANNELS, FIX_RATE, FIX_FORMAT, DONT_MOVE, VARIABLE_RATES to pa_sream_flags_t adn implement it - Expose those flags in pacat - Add notifications about device suspend/resume to the protocol and expose them in libpulse - Allow changing of buffer_attr during playback - allow disabling for remixing globally - hookup polkit support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2067 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/daemon/daemon-conf.c | 24 +- src/daemon/daemon-conf.h | 3 +- src/daemon/daemon.conf.in | 1 + src/daemon/main.c | 169 ++++++++--- src/map-file | 7 + src/modules/module-suspend-on-idle.c | 72 ++--- src/modules/module-volume-restore.c | 136 +++++++-- src/pulse/context.c | 9 +- src/pulse/def.h | 79 ++++- src/pulse/internal.h | 16 +- src/pulse/operation.c | 2 +- src/pulse/stream.c | 436 ++++++++++++++++++++++++++- src/pulse/stream.h | 71 ++++- src/pulsecore/cli-text.c | 14 +- src/pulsecore/core.c | 1 + src/pulsecore/core.h | 3 + src/pulsecore/pid.c | 34 ++- src/pulsecore/pid.h | 4 +- src/pulsecore/protocol-native.c | 365 ++++++++++++++++++++-- src/pulsecore/sink-input.c | 46 ++- src/pulsecore/sink-input.h | 18 +- src/pulsecore/sink.c | 27 +- src/pulsecore/source-output.c | 42 ++- src/pulsecore/source-output.h | 18 +- src/pulsecore/source.c | 27 +- src/utils/pacat.c | 101 ++++++- src/utils/pacmd.c | 4 +- 27 files changed, 1498 insertions(+), 231 deletions(-) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 3d63891ce..c98c0218e 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -71,6 +71,7 @@ static const pa_daemon_conf default_conf = { .log_target = PA_LOG_SYSLOG, .log_level = PA_LOG_NOTICE, .resample_method = PA_RESAMPLER_AUTO, + .disable_remixing = FALSE, .config_file = NULL, .use_pid_file = TRUE, .system_instance = FALSE, @@ -410,6 +411,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "default-fragments", parse_fragments, NULL }, { "default-fragment-size-msec", parse_fragment_size_msec, NULL }, { "nice-level", parse_nice_level, NULL }, + { "disable-remixing", pa_config_parse_bool, NULL }, #ifdef HAVE_SYS_RESOURCE_H { "rlimit-as", parse_rlimit, NULL }, { "rlimit-core", parse_rlimit, NULL }, @@ -458,33 +460,34 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { table[22].data = c; table[23].data = c; table[24].data = c; + table[25].data = &c->disable_remixing; #ifdef HAVE_SYS_RESOURCE_H - table[25].data = &c->rlimit_as; - table[26].data = &c->rlimit_core; - table[27].data = &c->rlimit_data; - table[28].data = &c->rlimit_fsize; - table[29].data = &c->rlimit_nofile; - table[30].data = &c->rlimit_stack; + table[26].data = &c->rlimit_as; + table[27].data = &c->rlimit_core; + table[28].data = &c->rlimit_data; + table[29].data = &c->rlimit_fsize; + table[30].data = &c->rlimit_nofile; + table[31].data = &c->rlimit_stack; #ifdef RLIMIT_NPROC - table[31].data = &c->rlimit_nproc; + table[32].data = &c->rlimit_nproc; #endif #ifdef RLIMIT_MEMLOCK #ifndef RLIMIT_NPROC #error "Houston, we have a numbering problem!" #endif - table[32].data = &c->rlimit_memlock; + table[33].data = &c->rlimit_memlock; #endif #ifdef RLIMIT_NICE #ifndef RLIMIT_MEMLOCK #error "Houston, we have a numbering problem!" #endif - table[33].data = &c->rlimit_nice; + table[34].data = &c->rlimit_nice; #endif #ifdef RLIMIT_RTPRIO #ifndef RLIMIT_NICE #error "Houston, we have a numbering problem!" #endif - table[34].data = &c->rlimit_rtprio; + table[35].data = &c->rlimit_rtprio; #endif #endif @@ -563,6 +566,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); + pa_strbuf_printf(s, "disable-remixing = %s\n", pa_yes_no(c->disable_remixing)); pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format)); pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate); pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index b8930bd79..3dcafbfe7 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -64,7 +64,8 @@ typedef struct pa_daemon_conf { use_pid_file, system_instance, no_cpu_limit, - disable_shm; + disable_shm, + disable_remixing; int exit_idle_time, module_idle_time, scache_idle_time, diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 8d224e826..d664962e2 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -46,6 +46,7 @@ ; log-level = notice ; resample-method = speex-float-3 +; disable-remixing = no ; no-cpu-limit = no diff --git a/src/daemon/main.c b/src/daemon/main.c index 051c323eb..236819e1d 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -94,6 +94,7 @@ #include "dumpmodules.h" #include "caps.h" #include "ltdl-bind-now.h" +#include "polkit.h" #ifdef HAVE_LIBWRAP /* Only one instance of these variables */ @@ -281,17 +282,21 @@ static int create_runtime_dir(void) { #ifdef HAVE_SYS_RESOURCE_H -static void set_one_rlimit(const pa_rlimit *r, int resource, const char *name) { +static int set_one_rlimit(const pa_rlimit *r, int resource, const char *name) { struct rlimit rl; pa_assert(r); if (!r->is_set) - return; + return 0; rl.rlim_cur = rl.rlim_max = r->value; - if (setrlimit(resource, &rl) < 0) + if (setrlimit(resource, &rl) < 0) { pa_log_warn("setrlimit(%s, (%u, %u)) failed: %s", name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno)); + return -1; + } + + return 0; } static void set_all_rlimits(const pa_daemon_conf *conf) { @@ -324,9 +329,10 @@ int main(int argc, char *argv[]) { char *s; int r = 0, retval = 1, d = 0; int daemon_pipe[2] = { -1, -1 }; - int suid_root, real_root; + pa_bool_t suid_root, real_root; int valid_pid_file = 0; gid_t gid = (gid_t) -1; + pa_bool_t allow_realtime, allow_high_priority; #ifdef OS_IS_WIN32 pa_time_event *timer; @@ -357,8 +363,8 @@ int main(int argc, char *argv[]) { real_root = getuid() == 0; suid_root = !real_root && geteuid() == 0; #else - real_root = 0; - suid_root = 0; + real_root = FALSE; + suid_root = FALSE; #endif if (suid_root) { @@ -377,29 +383,12 @@ int main(int argc, char *argv[]) { * is just too risky tun let PA run as root all the time. */ } + /* At this point, we are a normal user, possibly with CAP_NICE if + * we were started SUID. If we are started as normal root, than we + * still are normal root. */ + setlocale(LC_ALL, ""); - - if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0)) { - pa_log_info("Warning: Called SUID root, but not in group '"PA_REALTIME_GROUP"'. " - "For enabling real-time scheduling please become a member of '"PA_REALTIME_GROUP"' , or increase the RLIMIT_RTPRIO user limit."); - pa_drop_caps(); - pa_drop_root(); - suid_root = real_root = 0; - } - - LTDL_SET_PRELOADED_SYMBOLS(); - - pa_ltdl_init(); - -#ifdef OS_IS_WIN32 - { - WSADATA data; - WSAStartup(MAKEWORD(2, 0), &data); - } -#endif - - pa_random_seed(); - + pa_log_set_maximal_level(PA_LOG_INFO); pa_log_set_ident("pulseaudio"); conf = pa_daemon_conf_new(); @@ -411,24 +400,123 @@ int main(int argc, char *argv[]) { goto finish; if (pa_cmdline_parse(conf, argc, argv, &d) < 0) { - pa_log("failed to parse command line."); + pa_log("Failed to parse command line."); goto finish; } pa_log_set_maximal_level(conf->log_level); pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL); + if (suid_root) { + /* Ok, we're suid root, so let's better not enable high prio + * or RT by default */ + + allow_high_priority = allow_realtime = FALSE; + +#ifdef HAVE_POLKIT + if (conf->high_priority) { + if (pa_polkit_check("org.pulseaudio.acquire-high-priority") > 0) { + pa_log_info("PolicyKit grants us acquire-high-priority privilige."); + allow_high_priority = TRUE; + } else + pa_log_info("PolicyKit refuses acquire-high-priority privilige."); + } + + if (conf->realtime_scheduling) { + if (pa_polkit_check("org.pulseaudio.acquire-real-time") > 0) { + pa_log_info("PolicyKit grants us acquire-real-time privilige."); + allow_realtime = TRUE; + } else + pa_log_info("PolicyKit refuses acquire-real-time privilige."); + } +#endif + + if ((conf->high_priority || conf->realtime_scheduling) && pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) > 0) { + pa_log_info("We're in the group '"PA_REALTIME_GROUP"', allowing real-time and high-priority scheduling."); + allow_realtime = conf->realtime_scheduling; + allow_high_priority = conf->high_priority; + } + + if (!allow_high_priority && !allow_realtime) { + + /* OK, there's no further need to keep CAP_NICE. Hence + * let's give it up early */ + + pa_drop_caps(); + pa_drop_root(); + suid_root = real_root = FALSE; + + if (conf->high_priority || conf->realtime_scheduling) + pa_log_notice("Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n" + "We are not in group '"PA_REALTIME_GROUP"' and PolicyKit refuse to grant us priviliges. Dropping SUID again.\n" + "For enabling real-time scheduling please acquire the appropriate PolicyKit priviliges, or become a member of '"PA_REALTIME_GROUP"', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."); + } + + } else { + + /* OK, we're a normal user, so let's allow the user evrything + * he asks for, it's now the kernel's job to enforce limits, + * not ours anymore */ + allow_high_priority = allow_realtime = TRUE; + } + + if (conf->high_priority && !allow_high_priority) { + pa_log_info("High-priority scheduling enabled in configuration but now allowed by policy. Disabling forcibly."); + conf->high_priority = FALSE; + } + + if (conf->realtime_scheduling && !allow_realtime) { + pa_log_info("Real-time scheduling enabled in configuration but now allowed by policy. Disabling forcibly."); + conf->realtime_scheduling = FALSE; + } + if (conf->high_priority && conf->cmd == PA_CMD_DAEMON) pa_raise_priority(conf->nice_level); - if (suid_root && (conf->cmd != PA_CMD_DAEMON || !conf->realtime_scheduling)) { - pa_drop_caps(); - pa_drop_root(); + if (suid_root) { + pa_bool_t drop; + + drop = conf->cmd != PA_CMD_DAEMON || !conf->realtime_scheduling; + +#ifdef RLIMIT_RTPRIO + if (!drop) { + + /* At this point we still have CAP_NICE if we were loaded + * SUID root. If possible let's acquire RLIMIT_RTPRIO + * instead and give CAP_NICE up. */ + + const pa_rlimit rl = { 9, TRUE }; + + if (set_one_rlimit(&rl, RLIMIT_RTPRIO, "RLIMIT_RTPRIO") >= 0) { + pa_log_info("Successfully increased RLIMIT_RTPRIO, giving up CAP_NICE."); + drop = TRUE; + } else + pa_log_warn("RLIMIT_RTPRIO failed: %s", pa_cstrerror(errno)); + } +#endif + + if (drop) { + pa_drop_caps(); + pa_drop_root(); + suid_root = real_root = FALSE; + } } + LTDL_SET_PRELOADED_SYMBOLS(); + pa_ltdl_init(); + if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); +#ifdef OS_IS_WIN32 + { + WSADATA data; + WSAStartup(MAKEWORD(2, 0), &data); + } +#endif + + pa_random_seed(); + switch (conf->cmd) { case PA_CMD_DUMP_MODULES: pa_dump_modules(conf, argc-d, argv+d); @@ -466,10 +554,10 @@ int main(int argc, char *argv[]) { case PA_CMD_CHECK: { pid_t pid; - if (pa_pid_file_check_running(&pid) < 0) { - pa_log_info("daemon not running"); - } else { - pa_log_info("daemon running as PID %u", pid); + if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) + pa_log_info("Daemon not running"); + else { + pa_log_info("Daemon running as PID %u", pid); retval = 0; } @@ -478,8 +566,8 @@ int main(int argc, char *argv[]) { } case PA_CMD_KILL: - if (pa_pid_file_kill(SIGINT, NULL) < 0) - pa_log("failed to kill daemon."); + if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0) + pa_log("Failed to kill daemon."); else retval = 0; @@ -496,9 +584,9 @@ int main(int argc, char *argv[]) { pa_assert(conf->cmd == PA_CMD_DAEMON); } - if (real_root && !conf->system_instance) { + if (real_root && !conf->system_instance) pa_log_warn("This program is not intended to be run as root (unless --system is specified)."); - } else if (!real_root && conf->system_instance) { + else if (!real_root && conf->system_instance) { pa_log("Root priviliges required."); goto finish; } @@ -645,6 +733,7 @@ int main(int argc, char *argv[]) { c->resample_method = conf->resample_method; c->realtime_priority = conf->realtime_priority; c->realtime_scheduling = !!conf->realtime_scheduling; + c->disable_remixing = !!conf->disable_remixing; pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_signal_new(SIGINT, signal_callback, c); diff --git a/src/map-file b/src/map-file index 427a3a789..f38baefdc 100644 --- a/src/map-file +++ b/src/map-file @@ -156,26 +156,33 @@ pa_stream_flush; pa_stream_get_buffer_attr; pa_stream_get_channel_map; pa_stream_get_context; +pa_stream_get_device_index; +pa_stream_get_device_name; pa_stream_get_index; pa_stream_get_latency; pa_stream_get_sample_spec; pa_stream_get_state; pa_stream_get_time; pa_stream_get_timing_info; +pa_stream_is_suspended; pa_stream_new; pa_stream_peek; pa_stream_prebuf; pa_stream_readable_size; pa_stream_ref; +pa_stream_set_buffer_attr; pa_stream_set_latency_update_callback; +pa_stream_set_moved_callback; pa_stream_set_name; pa_stream_set_overflow_callback; pa_stream_set_read_callback; pa_stream_set_state_callback; +pa_stream_set_suspended_callback; pa_stream_set_underflow_callback; pa_stream_set_write_callback; pa_stream_trigger; pa_stream_unref; +pa_stream_update_sample_rate; pa_stream_update_timing_info; pa_stream_writable_size; pa_stream_write; diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c index 4746e2b77..4c260d76b 100644 --- a/src/modules/module-suspend-on-idle.c +++ b/src/modules/module-suspend-on-idle.c @@ -66,8 +66,6 @@ struct userdata { *source_output_unlink_slot, *sink_input_move_slot, *source_output_move_slot, - *sink_input_move_post_slot, - *source_output_move_post_slot, *sink_input_state_changed_slot, *source_output_state_changed_slot; }; @@ -131,27 +129,27 @@ static void resume(struct device_info *d) { } } -static pa_hook_result_t sink_input_new_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { +static pa_hook_result_t sink_input_fixate_hook_cb(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { struct device_info *d; pa_assert(c); - pa_sink_input_assert_ref(s); + pa_assert(data); pa_assert(u); - if ((d = pa_hashmap_get(u->device_infos, s->sink))) + if ((d = pa_hashmap_get(u->device_infos, data->sink))) resume(d); return PA_HOOK_OK; } -static pa_hook_result_t source_output_new_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) { +static pa_hook_result_t source_output_fixate_hook_cb(pa_core *c, pa_source_output_new_data *data, struct userdata *u) { struct device_info *d; pa_assert(c); - pa_source_output_assert_ref(s); + pa_assert(data); pa_assert(u); - if ((d = pa_hashmap_get(u->device_infos, s->source))) + if ((d = pa_hashmap_get(u->device_infos, data->source))) resume(d); return PA_HOOK_OK; @@ -185,56 +183,37 @@ static pa_hook_result_t source_output_unlink_hook_cb(pa_core *c, pa_source_outpu return PA_HOOK_OK; } -static pa_hook_result_t sink_input_move_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { - pa_assert(c); - pa_sink_input_assert_ref(s); - pa_assert(u); - - if (pa_sink_used_by(s->sink) <= 1) { - struct device_info *d; - if ((d = pa_hashmap_get(u->device_infos, s->sink))) - restart(d); - } - - return PA_HOOK_OK; -} - -static pa_hook_result_t sink_input_move_post_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { +static pa_hook_result_t sink_input_move_hook_cb(pa_core *c, pa_sink_input_move_hook_data *data, struct userdata *u) { struct device_info *d; + pa_assert(c); - pa_sink_input_assert_ref(s); + pa_assert(data); pa_assert(u); - if ((d = pa_hashmap_get(u->device_infos, s->sink))) + if ((d = pa_hashmap_get(u->device_infos, data->destination))) resume(d); - return PA_HOOK_OK; -} - -static pa_hook_result_t source_output_move_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) { - pa_assert(c); - pa_source_output_assert_ref(s); - pa_assert(u); - - if (pa_source_used_by(s->source) <= 1) { - struct device_info *d; - - if ((d = pa_hashmap_get(u->device_infos, s->source))) + if (pa_sink_used_by(data->sink_input->sink) <= 1) + if ((d = pa_hashmap_get(u->device_infos, data->sink_input->sink))) restart(d); - } return PA_HOOK_OK; } -static pa_hook_result_t source_output_move_post_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) { +static pa_hook_result_t source_output_move_hook_cb(pa_core *c, pa_source_output_move_hook_data *data, struct userdata *u) { struct device_info *d; + pa_assert(c); - pa_source_output_assert_ref(s); + pa_assert(data); pa_assert(u); - if ((d = pa_hashmap_get(u->device_infos, s->source))) + if ((d = pa_hashmap_get(u->device_infos, data->destination))) resume(d); + if (pa_source_used_by(data->source_output->source) <= 1) + if ((d = pa_hashmap_get(u->device_infos, data->source_output->source))) + restart(d); + return PA_HOOK_OK; } @@ -395,18 +374,15 @@ int pa__init(pa_module*m) { u->sink_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], (pa_hook_cb_t) device_state_changed_hook_cb, u); u->source_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], (pa_hook_cb_t) device_state_changed_hook_cb, u); - u->sink_input_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], (pa_hook_cb_t) sink_input_new_hook_cb, u); - u->source_output_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], (pa_hook_cb_t) source_output_new_hook_cb, u); + u->sink_input_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], (pa_hook_cb_t) sink_input_fixate_hook_cb, u); + u->source_output_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], (pa_hook_cb_t) source_output_fixate_hook_cb, u); u->sink_input_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], (pa_hook_cb_t) sink_input_unlink_hook_cb, u); u->source_output_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], (pa_hook_cb_t) source_output_unlink_hook_cb, u); u->sink_input_move_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], (pa_hook_cb_t) sink_input_move_hook_cb, u); u->source_output_move_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], (pa_hook_cb_t) source_output_move_hook_cb, u); - u->sink_input_move_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_POST], (pa_hook_cb_t) sink_input_move_post_hook_cb, u); - u->source_output_move_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST], (pa_hook_cb_t) source_output_move_post_hook_cb, u); u->sink_input_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], (pa_hook_cb_t) sink_input_state_changed_hook_cb, u); u->source_output_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED], (pa_hook_cb_t) source_output_state_changed_hook_cb, u); - pa_modargs_free(ma); return 0; @@ -449,8 +425,6 @@ void pa__done(pa_module*m) { pa_hook_slot_free(u->sink_input_unlink_slot); if (u->sink_input_move_slot) pa_hook_slot_free(u->sink_input_move_slot); - if (u->sink_input_move_post_slot) - pa_hook_slot_free(u->sink_input_move_post_slot); if (u->sink_input_state_changed_slot) pa_hook_slot_free(u->sink_input_state_changed_slot); @@ -460,8 +434,6 @@ void pa__done(pa_module*m) { pa_hook_slot_free(u->source_output_unlink_slot); if (u->source_output_move_slot) pa_hook_slot_free(u->source_output_move_slot); - if (u->source_output_move_post_slot) - pa_hook_slot_free(u->source_output_move_post_slot); if (u->source_output_state_changed_slot) pa_hook_slot_free(u->source_output_state_changed_slot); diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 422bc7f23..192a2a786 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -52,14 +53,20 @@ PA_MODULE_AUTHOR("Lennart Poettering"); PA_MODULE_DESCRIPTION("Automatically restore the volume and the devices of streams"); PA_MODULE_VERSION(PACKAGE_VERSION); PA_MODULE_LOAD_ONCE(TRUE); -PA_MODULE_USAGE("table="); +PA_MODULE_USAGE( + "table= " + "restore_device= " + "restore_volume=" +); #define WHITESPACE "\n\r \t" - #define DEFAULT_VOLUME_TABLE_FILE "volume-restore.table" +#define SAVE_INTERVAL 10 static const char* const valid_modargs[] = { "table", + "restore_device", + "restore_volume", NULL, }; @@ -67,16 +74,20 @@ struct rule { char* name; pa_bool_t volume_is_set; pa_cvolume volume; - char *sink; - char *source; + char *sink, *source; }; struct userdata { + pa_core *core; pa_hashmap *hashmap; pa_subscription *subscription; - pa_hook_slot *sink_input_hook_slot, *source_output_hook_slot; + pa_hook_slot + *sink_input_new_hook_slot, + *sink_input_fixate_hook_slot, + *source_output_new_hook_slot; pa_bool_t modified; char *table_file; + pa_time_event *save_time_event; }; static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { @@ -220,12 +231,17 @@ static int save_rules(struct userdata *u) { void *state = NULL; struct rule *rule; + if (!u->modified) + return 0; + + pa_log_info("Saving rules..."); + f = u->table_file ? fopen(u->table_file, "w") : pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w"); if (!f) { - pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); + pa_log("Failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); goto finish; } @@ -249,6 +265,8 @@ static int save_rules(struct userdata *u) { } ret = 0; + u->modified = FALSE; + pa_log_debug("Successfully saved rules..."); finish: if (f) { @@ -289,6 +307,21 @@ static char* client_name(pa_client *c) { return t; } +static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + + pa_assert(a); + pa_assert(e); + pa_assert(tv); + pa_assert(u); + + pa_assert(e == u->save_time_event); + u->core->mainloop->time_free(u->save_time_event); + u->save_time_event = NULL; + + save_rules(u); +} + static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = userdata; pa_sink_input *si = NULL; @@ -371,24 +404,28 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 pa_hashmap_put(u->hashmap, r->name, r); u->modified = TRUE; } + + if (u->modified && !u->save_time_event) { + struct timeval tv; + pa_gettimeofday(&tv); + tv.tv_sec += SAVE_INTERVAL; + u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u); + } } -static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { +static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { struct rule *r; char *name; pa_assert(data); + /* In the NEW hook we only adjust the device. Adjusting the volume + * is left for the FIXATE hook */ + if (!data->client || !(name = client_name(data->client))) return PA_HOOK_OK; if ((r = pa_hashmap_get(u->hashmap, name))) { - - if (r->volume_is_set && data->sample_spec.channels == r->volume.channels) { - pa_log_info("Restoring volume for <%s>", r->name); - pa_sink_input_new_data_set_volume(data, &r->volume); - } - if (!data->sink && r->sink) { if ((data->sink = pa_namereg_get(c, r->sink, PA_NAMEREG_SINK, 1))) pa_log_info("Restoring sink for <%s>", r->name); @@ -400,7 +437,32 @@ static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_d return PA_HOOK_OK; } -static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output_new_data *data, struct userdata *u) { +static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { + struct rule *r; + char *name; + + pa_assert(data); + + /* In the FIXATE hook we only adjust the volum. Adjusting the device + * is left for the NEW hook */ + + if (!data->client || !(name = client_name(data->client))) + return PA_HOOK_OK; + + if ((r = pa_hashmap_get(u->hashmap, name))) { + + if (r->volume_is_set && data->sample_spec.channels == r->volume.channels) { + pa_log_info("Restoring volume for <%s>", r->name); + pa_sink_input_new_data_set_volume(data, &r->volume); + } + } + + pa_xfree(name); + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *data, struct userdata *u) { struct rule *r; char *name; @@ -422,6 +484,7 @@ static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; + pa_bool_t restore_device = TRUE, restore_volume = TRUE; pa_assert(m); @@ -431,20 +494,39 @@ int pa__init(pa_module*m) { } u = pa_xnew(struct userdata, 1); + u->core = m->core; u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - u->subscription = NULL; u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL)); u->modified = FALSE; - u->sink_input_hook_slot = u->source_output_hook_slot = NULL; + u->subscription = NULL; + u->sink_input_new_hook_slot = u->sink_input_fixate_hook_slot = u->source_output_new_hook_slot = NULL; + u->save_time_event = NULL; m->userdata = u; + if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 || + pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0) { + pa_log("restore_volume= and restore_device= expect boolean arguments"); + goto fail; + } + + if (!(restore_device || restore_volume)) { + pa_log("Both restrong the volume and restoring the device are disabled. There's no point in using this module at all then, failing."); + goto fail; + } + if (load_rules(u) < 0) goto fail; u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u); - u->sink_input_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], (pa_hook_cb_t) sink_input_hook_callback, u); - u->source_output_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], (pa_hook_cb_t) source_output_hook_callback, u); + + if (restore_device) { + u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], (pa_hook_cb_t) sink_input_new_hook_callback, u); + u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], (pa_hook_cb_t) source_output_new_hook_callback, u); + } + + if (restore_volume) + u->sink_input_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], (pa_hook_cb_t) sink_input_fixate_hook_callback, u); pa_modargs_free(ma); return 0; @@ -478,19 +560,21 @@ void pa__done(pa_module*m) { if (u->subscription) pa_subscription_free(u->subscription); - if (u->sink_input_hook_slot) - pa_hook_slot_free(u->sink_input_hook_slot); - if (u->source_output_hook_slot) - pa_hook_slot_free(u->source_output_hook_slot); + if (u->sink_input_new_hook_slot) + pa_hook_slot_free(u->sink_input_new_hook_slot); + if (u->sink_input_fixate_hook_slot) + pa_hook_slot_free(u->sink_input_fixate_hook_slot); + if (u->source_output_new_hook_slot) + pa_hook_slot_free(u->source_output_new_hook_slot); if (u->hashmap) { - - if (u->modified) - save_rules(u); - + save_rules(u); pa_hashmap_free(u->hashmap, free_func, NULL); } + if (u->save_time_event) + u->core->mainloop->time_free(u->save_time_event); + pa_xfree(u->table_file); pa_xfree(u); } diff --git a/src/pulse/context.c b/src/pulse/context.c index 805cd44ee..bc960e21d 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -86,6 +86,10 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_UNDERFLOW] = pa_command_overflow_or_underflow, [PA_COMMAND_PLAYBACK_STREAM_KILLED] = pa_command_stream_killed, [PA_COMMAND_RECORD_STREAM_KILLED] = pa_command_stream_killed, + [PA_COMMAND_PLAYBACK_STREAM_MOVED] = pa_command_stream_moved, + [PA_COMMAND_RECORD_STREAM_MOVED] = pa_command_stream_moved, + [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = pa_command_stream_suspended, + [PA_COMMAND_RECORD_STREAM_SUSPENDED] = pa_command_stream_suspended, [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event }; @@ -396,7 +400,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t /* Enable shared memory support if possible */ if (c->version >= 10 && pa_mempool_is_shared(c->mempool) && - c->is_local) { + c->is_local > 0) { /* Only enable SHM if both sides are owned by the same * user. This is a security measure because otherwise @@ -965,6 +969,9 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ int pa_context_is_local(pa_context *c) { pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY(c, c->is_local >= 0, PA_ERR_BADSTATE); return c->is_local; } diff --git a/src/pulse/def.h b/src/pulse/def.h index a7c475db8..dabbc5eb0 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -122,7 +122,7 @@ typedef enum pa_stream_flags { * ahead can be corrected * quickly, without the need to * wait. */ - PA_STREAM_AUTO_TIMING_UPDATE = 8 /**< If set timing update requests + PA_STREAM_AUTO_TIMING_UPDATE = 8, /**< If set timing update requests * are issued periodically * automatically. Combined with * PA_STREAM_INTERPOLATE_TIMING @@ -132,6 +132,83 @@ typedef enum pa_stream_flags { * pa_stream_get_latency() at * all times without a packet * round trip.*/ + PA_STREAM_NO_REMAP_CHANNELS = 16, /**< Don't remap channels by + * their name, instead map them + * simply by their + * index. Implies + * PA_STREAM_NO_REMIX_CHANNELS. Only + * supported when the server is + * at least PA 0.9.8. It is + * ignored on older + * servers.\since 0.9.8 */ + PA_STREAM_NO_REMIX_CHANNELS = 32, /**< When remapping channels by + * name, don't upmix or downmix + * them to related + * channels. Copy them into + * matching channels of the + * device 1:1. Only supported + * when the server is at least + * PA 0.9.8. It is ignored on + * older servers. \since + * 0.9.8 */ + PA_STREAM_FIX_FORMAT = 64, /**< Use the sample format of the + * sink/device this stream is being + * connected to, and possibly ignore + * the format the sample spec contains + * -- but you still have to pass a + * valid value in it as a hint to + * PulseAudio what would suit your + * stream best. If this is used you + * should query the used sample format + * after creating the stream by using + * pa_stream_get_sample_spec(). Also, + * if you specified manual buffer + * metrics it is recommended to update + * them with + * pa_stream_set_buffer_attr() to + * compensate for the changed frame + * sizes. Only supported when the + * server is at least PA 0.9.8. It is + * ignored on older servers. \since + * 0.9.8 */ + + PA_STREAM_FIX_RATE = 128, /**< Use the sample rate of the sink, + * and possibly ignore the rate the + * sample spec contains. Usage similar + * to PA_STREAM_FIX_FORMAT.Only + * supported when the server is at least + * PA 0.9.8. It is ignored on older + * servers. \since 0.9.8 */ + + PA_STREAM_FIX_CHANNELS = 256, /**< Use the number of channels and + * the channel map of the sink, and + * possibly ignore the number of + * channels and the map the sample spec + * and the passed channel map + * contains. Usage similar to + * PA_STREAM_FIX_FORMAT. Only supported + * when the server is at least PA + * 0.9.8. It is ignored on older + * servers. \since 0.9.8 */ + PA_STREAM_DONT_MOVE = 512, /**< Don't allow moving of this stream to + * another sink/device. Useful if you use + * any of the PA_STREAM_FIX_ flags and + * want to make sure that resampling + * never takes place -- which might + * happen if the stream is moved to + * another sink/source whith a different + * sample spec/channel map. Only + * supported when the server is at least + * PA 0.9.8. It is ignored on older + * servers. \since 0.9.8 */ + PA_STREAM_VARIABLE_RATE = 1024, /**< Allow dynamic changing of the + * sampling rate during playback + * with + * pa_stream_update_sample_rate(). Only + * supported when the server is at + * least PA 0.9.8. It is ignored + * on older servers. \since + * 0.9.8 */ } pa_stream_flags_t; /** Playback and record buffer metrics */ diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 95593adb0..873f1363b 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -103,6 +103,7 @@ struct pa_stream { PA_LLIST_FIELDS(pa_stream); char *name; + pa_bool_t manual_buffer_attr; pa_buffer_attr buffer_attr; pa_sample_spec sample_spec; pa_channel_map channel_map; @@ -110,12 +111,17 @@ struct pa_stream { uint32_t channel; uint32_t syncid; int channel_valid; - uint32_t device_index; + uint32_t stream_index; pa_stream_direction_t direction; pa_stream_state_t state; + pa_bool_t buffer_attr_not_ready, timing_info_not_ready; uint32_t requested_bytes; + uint32_t device_index; + char *device_name; + pa_bool_t suspended; + pa_memchunk peek_memchunk; void *peek_data; pa_memblockq *record_memblockq; @@ -157,6 +163,10 @@ struct pa_stream { void *underflow_userdata; pa_stream_notify_cb_t latency_update_callback; void *latency_update_userdata; + pa_stream_notify_cb_t moved_callback; + void *moved_userdata; + pa_stream_notify_cb_t suspended_callback; + void *suspended_userdata; }; typedef void (*pa_operation_cb_t)(void); @@ -172,12 +182,16 @@ struct pa_operation { pa_operation_state_t state; void *userdata; pa_operation_cb_t callback; + + void *private; /* some operations might need this */ }; void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t callback, void *userdata); void pa_operation_done(pa_operation *o); diff --git a/src/pulse/operation.c b/src/pulse/operation.c index 8a782fd17..5d2da5b8f 100644 --- a/src/pulse/operation.c +++ b/src/pulse/operation.c @@ -44,6 +44,7 @@ pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb PA_REFCNT_INIT(o); o->context = c; o->stream = s; + o->private = NULL; o->state = PA_OPERATION_RUNNING; o->callback = cb; @@ -63,7 +64,6 @@ pa_operation *pa_operation_ref(pa_operation *o) { PA_REFCNT_INC(o); return o; } - void pa_operation_unref(pa_operation *o) { pa_assert(o); pa_assert(PA_REFCNT_VALUE(o) >= 1); diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 47906a5cf..92420825b 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -51,6 +51,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE || ss->format != PA_SAMPLE_S32NE), PA_ERR_NOTSUPPORTED); PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID); s = pa_xnew(pa_stream, 1); @@ -58,6 +59,8 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->context = c; s->mainloop = c->mainloop; + s->buffer_attr_not_ready = s->timing_info_not_ready = FALSE; + s->read_callback = NULL; s->read_userdata = NULL; s->write_callback = NULL; @@ -70,6 +73,10 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->underflow_userdata = NULL; s->latency_update_callback = NULL; s->latency_update_userdata = NULL; + s->moved_callback = NULL; + s->moved_userdata = NULL; + s->suspended_callback = NULL; + s->suspended_userdata = NULL; s->direction = PA_STREAM_NODIRECTION; s->name = pa_xstrdup(name); @@ -84,11 +91,17 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec * s->channel = 0; s->channel_valid = 0; s->syncid = c->csyncid++; - s->device_index = PA_INVALID_INDEX; + s->stream_index = PA_INVALID_INDEX; s->requested_bytes = 0; s->state = PA_STREAM_UNCONNECTED; + + s->manual_buffer_attr = FALSE; memset(&s->buffer_attr, 0, sizeof(s->buffer_attr)); + s->device_index = PA_INVALID_INDEX; + s->device_name = NULL; + s->suspended = FALSE; + s->peek_memchunk.index = 0; s->peek_memchunk.length = 0; s->peek_memchunk.memblock = NULL; @@ -139,6 +152,7 @@ static void stream_free(pa_stream *s) { pa_memblockq_free(s->record_memblockq); pa_xfree(s->name); + pa_xfree(s->device_name); pa_xfree(s); } @@ -178,7 +192,7 @@ uint32_t pa_stream_get_index(pa_stream *s) { PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX); - return s->device_index; + return s->stream_index; } void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) { @@ -262,6 +276,95 @@ finish: pa_context_unref(c); } +void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_context *c = userdata; + pa_stream *s; + uint32_t channel; + const char *dn; + int suspended; + uint32_t di; + + pa_assert(pd); + pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_MOVED || command == PA_COMMAND_RECORD_STREAM_MOVED); + pa_assert(t); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + pa_context_ref(c); + + if (c->version < 12) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_getu32(t, &di) < 0 || + pa_tagstruct_gets(t, &dn) < 0 || + pa_tagstruct_get_boolean(t, &suspended) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + if (!dn || di == PA_INVALID_INDEX) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_MOVED ? c->playback_streams : c->record_streams, channel))) + goto finish; + + pa_xfree(s->device_name); + s->device_name = pa_xstrdup(dn); + s->device_index = di; + + s->suspended = suspended; + + if (s->moved_callback) + s->moved_callback(s, s->moved_userdata); + +finish: + pa_context_unref(c); +} + +void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_context *c = userdata; + pa_stream *s; + uint32_t channel; + int suspended; + + pa_assert(pd); + pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_SUSPENDED || command == PA_COMMAND_RECORD_STREAM_SUSPENDED); + pa_assert(t); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + pa_context_ref(c); + + if (c->version < 12) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + if (pa_tagstruct_getu32(t, &channel) < 0 || + pa_tagstruct_get_boolean(t, &suspended) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_SUSPENDED ? c->playback_streams : c->record_streams, channel))) + goto finish; + + s->suspended = suspended; + + if (s->suspended_callback) + s->suspended_callback(s, s->suspended_userdata); + +finish: + pa_context_unref(c); +} + void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s; pa_context *c = userdata; @@ -412,6 +515,9 @@ static void create_stream_complete(pa_stream *s) { pa_assert(PA_REFCNT_VALUE(s) >= 1); pa_assert(s->state == PA_STREAM_CREATING); + if (s->buffer_attr_not_ready || s->timing_info_not_ready) + return; + pa_stream_set_state(s, PA_STREAM_READY); if (s->requested_bytes > 0 && s->write_callback) @@ -426,6 +532,17 @@ static void create_stream_complete(pa_stream *s) { } } +static void automatic_buffer_attr(pa_buffer_attr *attr, pa_sample_spec *ss) { + pa_assert(attr); + pa_assert(ss); + + attr->tlength = pa_bytes_per_second(ss)/2; + attr->maxlength = (attr->tlength*3)/2; + attr->minreq = attr->tlength/50; + attr->prebuf = attr->tlength - attr->minreq; + attr->fragsize = attr->tlength/50; +} + void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_stream *s = userdata; @@ -445,13 +562,13 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED } if (pa_tagstruct_getu32(t, &s->channel) < 0 || - ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) || + ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->stream_index) < 0) || ((s->direction != PA_STREAM_RECORD) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0)) { pa_context_fail(s->context, PA_ERR_PROTOCOL); goto finish; } - if (pa_context_get_server_protocol_version(s->context) >= 9) { + if (s->context->version >= 9) { if (s->direction == PA_STREAM_PLAYBACK) { if (pa_tagstruct_getu32(t, &s->buffer_attr.maxlength) < 0 || pa_tagstruct_getu32(t, &s->buffer_attr.tlength) < 0 || @@ -469,6 +586,58 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED } } + if (s->context->version >= 12) { + pa_sample_spec ss; + pa_channel_map cm; + const char *dn = NULL; + int suspended; + + if (pa_tagstruct_get_sample_spec(t, &ss) < 0 || + pa_tagstruct_get_channel_map(t, &cm) < 0 || + pa_tagstruct_getu32(t, &s->device_index) < 0 || + pa_tagstruct_gets(t, &dn) < 0 || + pa_tagstruct_get_boolean(t, &suspended) < 0) { + pa_context_fail(s->context, PA_ERR_PROTOCOL); + goto finish; + } + + if (!dn || s->device_index == PA_INVALID_INDEX || + ss.channels != cm.channels || + !pa_channel_map_valid(&cm) || + !pa_sample_spec_valid(&ss) || + (!(s->flags & PA_STREAM_FIX_FORMAT) && ss.format != s->sample_spec.format) || + (!(s->flags & PA_STREAM_FIX_RATE) && ss.rate != s->sample_spec.rate) || + (!(s->flags & PA_STREAM_FIX_CHANNELS) && !pa_channel_map_equal(&cm, &s->channel_map))) { + pa_context_fail(s->context, PA_ERR_PROTOCOL); + goto finish; + } + + pa_xfree(s->device_name); + s->device_name = pa_xstrdup(dn); + s->suspended = suspended; + + if (!s->manual_buffer_attr && pa_bytes_per_second(&ss) != pa_bytes_per_second(&s->sample_spec)) { + pa_buffer_attr attr; + pa_operation *o; + + automatic_buffer_attr(&attr, &ss); + + /* If we need to update the buffer metrics, we wait for + * the the OK for that call before we go to + * PA_STREAM_READY */ + + s->state = PA_STREAM_READY; + pa_assert_se(o = pa_stream_set_buffer_attr(s, &attr, NULL, NULL)); + pa_operation_unref(o); + s->state = PA_STREAM_CREATING; + + s->buffer_attr_not_ready = TRUE; + } + + s->channel_map = cm; + s->sample_spec = ss; + } + if (!pa_tagstruct_eof(t)) { pa_context_fail(s->context, PA_ERR_PROTOCOL); goto finish; @@ -491,15 +660,19 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s); if (s->direction != PA_STREAM_UPLOAD && s->flags & PA_STREAM_AUTO_TIMING_UPDATE) { + /* If automatic timing updates are active, we wait for the * first timing update before going to PA_STREAM_READY * state */ + s->state = PA_STREAM_READY; request_auto_timing_update(s, 1); s->state = PA_STREAM_CREATING; - } else - create_stream_complete(s); + s->timing_info_not_ready = TRUE; + } + + create_stream_complete(s); finish: pa_stream_unref(s); @@ -525,7 +698,13 @@ static int create_stream( PA_STREAM_START_CORKED| PA_STREAM_INTERPOLATE_TIMING| PA_STREAM_NOT_MONOTONOUS| - PA_STREAM_AUTO_TIMING_UPDATE : 0))), PA_ERR_INVALID); + PA_STREAM_AUTO_TIMING_UPDATE| + PA_STREAM_NO_REMAP_CHANNELS| + PA_STREAM_NO_REMIX_CHANNELS| + PA_STREAM_FIX_FORMAT| + PA_STREAM_FIX_RATE| + PA_STREAM_FIX_CHANNELS| + PA_STREAM_DONT_MOVE : 0))), PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID); PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID); @@ -537,15 +716,17 @@ static int create_stream( if (sync_stream) s->syncid = sync_stream->syncid; - if (attr) + if (attr) { s->buffer_attr = *attr; - else { + s->manual_buffer_attr = TRUE; + } else { /* half a second, with minimum request of 10 ms */ s->buffer_attr.tlength = pa_bytes_per_second(&s->sample_spec)/2; s->buffer_attr.maxlength = (s->buffer_attr.tlength*3)/2; s->buffer_attr.minreq = s->buffer_attr.tlength/50; s->buffer_attr.prebuf = s->buffer_attr.tlength - s->buffer_attr.minreq; s->buffer_attr.fragsize = s->buffer_attr.tlength/50; + s->manual_buffer_attr = FALSE; } if (!dev) @@ -585,6 +766,19 @@ static int create_stream( } else pa_tagstruct_putu32(t, s->buffer_attr.fragsize); + if (s->context->version >= 12 && s->direction != PA_STREAM_UPLOAD) { + pa_tagstruct_put( + t, + PA_TAG_BOOLEAN, flags & PA_STREAM_NO_REMAP_CHANNELS, + PA_TAG_BOOLEAN, flags & PA_STREAM_NO_REMIX_CHANNELS, + PA_TAG_BOOLEAN, flags & PA_STREAM_FIX_FORMAT, + PA_TAG_BOOLEAN, flags & PA_STREAM_FIX_RATE, + PA_TAG_BOOLEAN, flags & PA_STREAM_FIX_CHANNELS, + PA_TAG_BOOLEAN, flags & PA_STREAM_DONT_MOVE, + PA_TAG_BOOLEAN, flags & PA_STREAM_VARIABLE_RATE, + PA_TAG_INVALID); + } + pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL); @@ -921,8 +1115,10 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, } /* First, let's complete the initialization, if necessary. */ - if (o->stream->state == PA_STREAM_CREATING) + if (o->stream->state == PA_STREAM_CREATING) { + o->stream->timing_info_not_ready = FALSE; create_stream_complete(o->stream); + } if (o->stream->latency_update_callback) o->stream->latency_update_callback(o->stream, o->stream->latency_update_userdata); @@ -1084,6 +1280,22 @@ void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t c s->latency_update_userdata = userdata; } +void pa_stream_set_moved_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + + s->moved_callback = cb; + s->moved_userdata = userdata; +} + +void pa_stream_set_suspended_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) { + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + + s->suspended_callback = cb; + s->suspended_userdata = userdata; +} + void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; @@ -1420,8 +1632,208 @@ const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s) { PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY_RETURN_NULL(s->context, - pa_context_get_server_protocol_version(s->context) >= 9, PA_ERR_NODATA); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 9, PA_ERR_NODATA); return &s->buffer_attr; } + +static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + int success = 1; + + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + + if (!o->context) + goto finish; + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; + + success = 0; + } else { + + if (o->stream->direction == PA_STREAM_PLAYBACK) { + if (pa_tagstruct_getu32(t, &o->stream->buffer_attr.maxlength) < 0 || + pa_tagstruct_getu32(t, &o->stream->buffer_attr.tlength) < 0 || + pa_tagstruct_getu32(t, &o->stream->buffer_attr.prebuf) < 0 || + pa_tagstruct_getu32(t, &o->stream->buffer_attr.minreq) < 0) { + pa_context_fail(o->context, PA_ERR_PROTOCOL); + goto finish; + } + } else if (o->stream->direction == PA_STREAM_RECORD) { + if (pa_tagstruct_getu32(t, &o->stream->buffer_attr.maxlength) < 0 || + pa_tagstruct_getu32(t, &o->stream->buffer_attr.fragsize) < 0) { + pa_context_fail(o->context, PA_ERR_PROTOCOL); + goto finish; + } + } + + if (!pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERR_PROTOCOL); + goto finish; + } + + o->stream->manual_buffer_attr = TRUE; + } + + if (o->stream->state == PA_STREAM_CREATING) { + o->stream->buffer_attr_not_ready = FALSE; + create_stream_complete(o->stream); + } + + if (o->callback) { + pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback; + cb(o->stream, success, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + + +pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr, pa_stream_success_cb_t cb, void *userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + pa_assert(attr); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command( + s->context, + s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR : PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR, + &tag); + pa_tagstruct_putu32(t, s->channel); + + pa_tagstruct_putu32(t, attr->maxlength); + + if (s->direction == PA_STREAM_PLAYBACK) + pa_tagstruct_put( + t, + PA_TAG_U32, attr->tlength, + PA_TAG_U32, attr->prebuf, + PA_TAG_U32, attr->minreq, + PA_TAG_INVALID); + else + pa_tagstruct_putu32(t, attr->fragsize); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_set_buffer_attr_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +uint32_t pa_stream_get_device_index(pa_stream *s) { + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE, PA_INVALID_INDEX); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED, PA_INVALID_INDEX); + PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->device_index != PA_INVALID_INDEX, PA_ERR_BADSTATE, PA_INVALID_INDEX); + + return s->device_index; +} + +const char *pa_stream_get_device_name(pa_stream *s) { + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->device_name, PA_ERR_BADSTATE); + + return s->device_name; +} + +int pa_stream_is_suspended(pa_stream *s) { + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + + PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED); + + return s->suspended; +} + +static void stream_update_sample_rate_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + int success = 1; + + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + + if (!o->context) + goto finish; + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; + + success = 0; + } else { + + if (!pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERR_PROTOCOL); + goto finish; + } + } + + o->stream->sample_spec.rate = PA_PTR_TO_UINT(o->private); + pa_assert(pa_sample_spec_valid(&o->stream->sample_spec)); + + if (o->callback) { + pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback; + cb(o->stream, success, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + + +pa_operation *pa_stream_update_sample_rate(pa_stream *s, uint32_t rate, pa_stream_success_cb_t cb, void *userdata) { + pa_operation *o; + pa_tagstruct *t; + uint32_t tag; + + pa_assert(s); + pa_assert(PA_REFCNT_VALUE(s) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(s->context, rate > 0 && rate <= PA_RATE_MAX, PA_ERR_INVALID); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->flags & PA_STREAM_VARIABLE_RATE, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); + o->private = PA_UINT_TO_PTR(rate); + + t = pa_tagstruct_command( + s->context, + s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE : PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE, + &tag); + pa_tagstruct_putu32(t, s->channel); + pa_tagstruct_putu32(t, rate); + + pa_pstream_send_tagstruct(s->context->pstream, t); + pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_update_sample_rate_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; + +} diff --git a/src/pulse/stream.h b/src/pulse/stream.h index 8c6a90c16..854732272 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -295,9 +295,38 @@ pa_stream_state_t pa_stream_get_state(pa_stream *p); /** Return the context this stream is attached to */ pa_context* pa_stream_get_context(pa_stream *p); -/** Return the device (sink input or source output) index this stream is connected to */ +/** Return the sink input resp. source output index this stream is + * identified in the server with. This is useful for usage with the + * introspection functions, such as pa_context_get_sink_input_info() + * resp. pa_context_get_source_output_info(). */ uint32_t pa_stream_get_index(pa_stream *s); +/** Return the index of the sink or source this stream is connected to + * in the server. This is useful for usage with the introspection + * functions, such as pa_context_get_sink_info_by_index() + * resp. pa_context_get_source_info_by_index(). Please note that + * streams may be moved between sinks/sources and thus it is + * recommended to use pa_stream_set_moved_callback() to be notified + * about this. This function will return with PA_ERR_NOTSUPPORTED when the + * server is older than 0.9.8. \since 0.9.8 */ +uint32_t pa_stream_get_device_index(pa_stream *s); + +/** Return the name of the sink or source this stream is connected to + * in the server. This is useful for usage with the introspection + * functions, such as pa_context_get_sink_info_by_name() + * resp. pa_context_get_source_info_by_name(). Please note that + * streams may be moved between sinks/sources and thus it is + * recommended to use pa_stream_set_moved_callback() to be notified + * about this. This function will return with PA_ERR_NOTSUPPORTED when the + * server is older than 0.9.8. \since 0.9.8 */ +const char *pa_stream_get_device_name(pa_stream *s); + +/** Return 1 if the sink or source this stream is connected to has + * been suspended. This will return 0 if not, and negative on + * error. This function will return with PA_ERR_NOTSUPPORTED when the + * server is older than 0.9.8. \since 0.9.8 */ +int pa_stream_is_suspended(pa_stream *s); + /** Connect the stream to a sink */ int pa_stream_connect_playback( pa_stream *s /**< The stream to connect to a sink */, @@ -346,10 +375,10 @@ int pa_stream_peek( * calling pa_stream_peek(). \since 0.8 */ int pa_stream_drop(pa_stream *p); -/** Return the nember of bytes that may be written using pa_stream_write(), in bytes */ +/** Return the number of bytes that may be written using pa_stream_write() */ size_t pa_stream_writable_size(pa_stream *p); -/** Return the number of bytes that may be read using pa_stream_read(), in bytes \since 0.8 */ +/** Return the number of bytes that may be read using pa_stream_read() \since 0.8 */ size_t pa_stream_readable_size(pa_stream *p); /** Drain a playback stream. Use this for notification when the buffer is empty */ @@ -378,9 +407,28 @@ void pa_stream_set_overflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, voi /** Set the callback function that is called when a buffer underflow happens. (Only for playback streams) \since 0.8 */ void pa_stream_set_underflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata); -/** Set the callback function that is called whenever a latency information update happens. Useful on PA_STREAM_AUTO_TIMING_UPDATE streams only. (Only for playback streams) \since 0.8.2 */ +/** Set the callback function that is called whenever a latency + * information update happens. Useful on PA_STREAM_AUTO_TIMING_UPDATE + * streams only. (Only for playback streams) \since 0.8.2 */ void pa_stream_set_latency_update_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata); +/** Set the callback function that is called whenever the stream is + * moved to a different sink/source. Use pa_stream_get_device_name()or + * pa_stream_get_device_index() to query the new sink/source. This + * notification is only generated when the server is at least + * 0.9.8. \since 0.9.8 */ +void pa_stream_set_moved_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata); + +/** Set the callback function that is called whenever the sink/source + * this stream is connected to is suspended or resumed. Use + * pa_stream_is_suspended() to query the new suspend status. Please + * note that the suspend status might also change when the stream is + * moved between devices. Thus if you call this function you very + * likely want to call pa_stream_set_moved_callback, too. This + * notification is only generated when the server is at least + * 0.9.8. \since 0.9.8 */ +void pa_stream_set_suspended_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata); + /** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. \since 0.3 */ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata); @@ -447,6 +495,21 @@ const pa_channel_map* pa_stream_get_channel_map(pa_stream *s); * PulseAudio 0.9. \since 0.9.0 */ const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s); +/** Change the buffer metrics of the stream during playback. The + * server might have chosen different buffer metrics then + * requested. The selected metrics may be queried with + * pa_stream_get_buffer_attr() as soon as the callback is called. Only + * valid after the stream has been connected successfully and if the + * server is at least PulseAudio 0.9.8. \since 0.9.8 */ +pa_operation *pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr, pa_stream_success_cb_t cb, void *userdata); + +/* Change the stream sampling rate during playback. You need to pass + * PA_STREAM_VARIABLE_RATE in the flags parameter of + * pa_stream_connect() if you plan to use this function. Only valid + * after the stream has been connected successfully and if the server + * is at least PulseAudio 0.9.8. \since 0.9.8 */ +pa_operation *pa_stream_update_sample_rate(pa_stream *s, uint32_t rate, pa_stream_success_cb_t cb, void *userdata); + PA_C_DECL_END #endif diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index a77bcc2c0..b64cafe26 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -236,7 +236,7 @@ char *pa_source_output_list_to_string(pa_core *c) { " index: %u\n" "\tname: '%s'\n" "\tdriver: <%s>\n" - "\tflags: %s%s\n" + "\tflags: %s%s%s%s%s%s%s\n" "\tstate: %s\n" "\tsource: <%u> '%s'\n" "\tlatency: <%0.0f usec>\n" @@ -248,6 +248,11 @@ char *pa_source_output_list_to_string(pa_core *c) { o->driver, o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "", o->flags & PA_SOURCE_OUTPUT_DONT_MOVE ? "DONT_MOVE " : "", + o->flags & PA_SOURCE_OUTPUT_NO_REMAP ? "NO_REMAP " : "", + o->flags & PA_SOURCE_OUTPUT_NO_REMIX ? "NO_REMIX " : "", + o->flags & PA_SOURCE_OUTPUT_FIX_FORMAT ? "FIX_FORMAT " : "", + o->flags & PA_SOURCE_OUTPUT_FIX_RATE ? "FIX_RATE " : "", + o->flags & PA_SOURCE_OUTPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "", state_table[pa_source_output_get_state(o)], o->source->index, o->source->name, (double) pa_source_output_get_latency(o), @@ -289,7 +294,7 @@ char *pa_sink_input_list_to_string(pa_core *c) { " index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" - "\tflags: %s%s\n" + "\tflags: %s%s%s%s%s%s%s\n" "\tstate: %s\n" "\tsink: <%u> '%s'\n" "\tvolume: <%s>\n" @@ -303,6 +308,11 @@ char *pa_sink_input_list_to_string(pa_core *c) { i->driver, i->flags & PA_SINK_INPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "", i->flags & PA_SINK_INPUT_DONT_MOVE ? "DONT_MOVE " : "", + i->flags & PA_SINK_INPUT_NO_REMAP ? "NO_REMAP " : "", + i->flags & PA_SINK_INPUT_NO_REMIX ? "NO_REMIX " : "", + i->flags & PA_SINK_INPUT_FIX_FORMAT ? "FIX_FORMAT " : "", + i->flags & PA_SINK_INPUT_FIX_RATE ? "FIX_RATE " : "", + i->flags & PA_SINK_INPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "", state_table[pa_sink_input_get_state(i)], i->sink->index, i->sink->name, pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)), diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 9b420c948..cf0185091 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -138,6 +138,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { c->disallow_module_loading = FALSE; c->realtime_scheduling = FALSE; c->realtime_priority = 5; + c->disable_remixing = FALSE; for (j = 0; j < PA_CORE_HOOK_MAX; j++) pa_hook_init(&c->hooks[j], c); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 9aeb7888a..ce45e300f 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -54,6 +54,7 @@ typedef enum pa_core_hook { PA_CORE_HOOK_SOURCE_STATE_CHANGED, PA_CORE_HOOK_SOURCE_DESCRIPTION_CHANGED, PA_CORE_HOOK_SINK_INPUT_NEW, + PA_CORE_HOOK_SINK_INPUT_FIXATE, PA_CORE_HOOK_SINK_INPUT_PUT, PA_CORE_HOOK_SINK_INPUT_UNLINK, PA_CORE_HOOK_SINK_INPUT_UNLINK_POST, @@ -62,6 +63,7 @@ typedef enum pa_core_hook { PA_CORE_HOOK_SINK_INPUT_NAME_CHANGED, PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED, PA_CORE_HOOK_SOURCE_OUTPUT_NEW, + PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE, PA_CORE_HOOK_SOURCE_OUTPUT_PUT, PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK, PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST, @@ -118,6 +120,7 @@ struct pa_core { pa_bool_t is_system_instance; pa_bool_t realtime_scheduling; int realtime_priority; + pa_bool_t disable_remixing; /* hooks */ pa_hook hooks[PA_CORE_HOOK_MAX]; diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index 55ff2088b..f3c9faaac 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -42,6 +42,7 @@ #endif #include +#include #include #include @@ -260,8 +261,8 @@ fail: * exists and the PID therein too. Returns 0 on succcess, -1 * otherwise. If pid is non-NULL and a running daemon was found, * return its PID therein */ -int pa_pid_file_check_running(pid_t *pid) { - return pa_pid_file_kill(0, pid); +int pa_pid_file_check_running(pid_t *pid, const char *binary_name) { + return pa_pid_file_kill(0, pid, binary_name); } #ifndef OS_IS_WIN32 @@ -269,12 +270,14 @@ int pa_pid_file_check_running(pid_t *pid) { /* Kill a current running daemon. Return non-zero on success, -1 * otherwise. If successful *pid contains the PID of the daemon * process. */ -int pa_pid_file_kill(int sig, pid_t *pid) { +int pa_pid_file_kill(int sig, pid_t *pid, const char *binary_name) { int fd = -1; char fn[PATH_MAX]; int ret = -1; pid_t _pid; - +#ifdef __linux__ + char *e = NULL; +#endif if (!pid) pid = &_pid; @@ -286,6 +289,23 @@ int pa_pid_file_kill(int sig, pid_t *pid) { if ((*pid = read_pid(fn, fd)) == (pid_t) -1) goto fail; +#ifdef __linux__ + if (binary_name) { + pa_snprintf(fn, sizeof(fn), "/proc/%lu/exe", (unsigned long) pid); + + if ((e = pa_readlink(fn))) { + char *f = pa_path_get_filename(e); + if (strcmp(f, binary_name) +#if defined(__OPTIMIZE__) + /* libtool likes to rename our binary names ... */ + && !(pa_startswith(f, "lt-") && strcmp(f+3, binary_name) == 0) +#endif + ) + goto fail; + } + } +#endif + ret = kill(*pid, sig); fail: @@ -295,13 +315,17 @@ fail: pa_close(fd); } +#ifdef __linux__ + pa_xfree(e); +#endif + return ret; } #else /* OS_IS_WIN32 */ -int pa_pid_file_kill(int sig, pid_t *pid) { +int pa_pid_file_kill(int sig, pid_t *pid, const char *exe_name) { return -1; } diff --git a/src/pulsecore/pid.h b/src/pulsecore/pid.h index 0f25d1c89..1d6de7b52 100644 --- a/src/pulsecore/pid.h +++ b/src/pulsecore/pid.h @@ -26,7 +26,7 @@ int pa_pid_file_create(void); int pa_pid_file_remove(void); -int pa_pid_file_check_running(pid_t *pid); -int pa_pid_file_kill(int sig, pid_t *pid); +int pa_pid_file_check_running(pid_t *pid, const char *binary_name); +int pa_pid_file_kill(int sig, pid_t *pid, const char *binary_name); #endif diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 1d294746d..48d5cd70b 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -202,12 +202,16 @@ enum { static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk); static void sink_input_drop_cb(pa_sink_input *i, size_t length); static void sink_input_kill_cb(pa_sink_input *i); +static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend); +static void sink_input_moved_cb(pa_sink_input *i); static void send_memblock(connection *c); static void request_bytes(struct playback_stream*s); static void source_output_kill_cb(pa_source_output *o); static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk); +static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend); +static void source_output_moved_cb(pa_source_output *o); static pa_usec_t source_output_get_latency_cb(pa_source_output *o); static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk); @@ -248,6 +252,8 @@ static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint3 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_ERROR] = NULL, @@ -323,7 +329,13 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REMOVE_AUTOLOAD] = command_remove_autoload, [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream, - [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream + [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream, + + [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr, + [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr, + + [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate, + [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate }; /* structure management */ @@ -435,12 +447,12 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i static record_stream* record_stream_new( connection *c, pa_source *source, - const pa_sample_spec *ss, - const pa_channel_map *map, + pa_sample_spec *ss, + pa_channel_map *map, const char *name, uint32_t *maxlength, uint32_t fragment_size, - int corked) { + pa_source_output_flags_t flags) { record_stream *s; pa_source_output *source_output; @@ -462,7 +474,7 @@ static record_stream* record_stream_new( pa_source_output_new_data_set_sample_spec(&data, ss); pa_source_output_new_data_set_channel_map(&data, map); - if (!(source_output = pa_source_output_new(c->protocol->core, &data, corked ? PA_SOURCE_OUTPUT_START_CORKED : 0))) + if (!(source_output = pa_source_output_new(c->protocol->core, &data, flags))) return NULL; s = pa_msgobject_new(record_stream); @@ -473,21 +485,30 @@ static record_stream* record_stream_new( s->source_output->push = source_output_push_cb; s->source_output->kill = source_output_kill_cb; s->source_output->get_latency = source_output_get_latency_cb; + s->source_output->moved = source_output_moved_cb; + s->source_output->suspend = source_output_suspend_cb; s->source_output->userdata = s; s->memblockq = pa_memblockq_new( 0, *maxlength, 0, - base = pa_frame_size(ss), + base = pa_frame_size(&s->source_output->sample_spec), 1, 0, NULL); + *maxlength = pa_memblockq_get_maxlength(s->memblockq); + s->fragment_size = (fragment_size/base)*base; if (s->fragment_size <= 0) s->fragment_size = base; - *maxlength = pa_memblockq_get_maxlength(s->memblockq); + + if (s->fragment_size > *maxlength) + s->fragment_size = *maxlength; + + *ss = s->source_output->sample_spec; + *map = s->source_output->channel_map; pa_idxset_put(c->record_streams, s, &s->index); @@ -602,8 +623,8 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, static playback_stream* playback_stream_new( connection *c, pa_sink *sink, - const pa_sample_spec *ss, - const pa_channel_map *map, + pa_sample_spec *ss, + pa_channel_map *map, const char *name, uint32_t *maxlength, uint32_t *tlength, @@ -611,8 +632,8 @@ static playback_stream* playback_stream_new( uint32_t *minreq, pa_cvolume *volume, uint32_t syncid, - int corked, - uint32_t *missing) { + uint32_t *missing, + pa_sink_input_flags_t flags) { playback_stream *s, *ssync; pa_sink_input *sink_input; @@ -656,7 +677,7 @@ static playback_stream* playback_stream_new( data.client = c->client; data.sync_base = ssync ? ssync->sink_input : NULL; - if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, corked ? PA_SINK_INPUT_START_CORKED : 0))) + if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, flags))) return NULL; s = pa_msgobject_new(playback_stream); @@ -671,17 +692,19 @@ static playback_stream* playback_stream_new( s->sink_input->peek = sink_input_peek_cb; s->sink_input->drop = sink_input_drop_cb; s->sink_input->kill = sink_input_kill_cb; + s->sink_input->moved = sink_input_moved_cb; + s->sink_input->suspend = sink_input_suspend_cb; s->sink_input->userdata = s; start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0; - silence = pa_silence_memblock_new(c->protocol->core->mempool, ss, 0); + silence = pa_silence_memblock_new(c->protocol->core->mempool, &s->sink_input->sample_spec, 0); s->memblockq = pa_memblockq_new( start_index, *maxlength, *tlength, - pa_frame_size(ss), + pa_frame_size(&s->sink_input->sample_spec), *prebuf, *minreq, silence); @@ -694,6 +717,9 @@ static playback_stream* playback_stream_new( *minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq); *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq); + *ss = s->sink_input->sample_spec; + *map = s->sink_input->channel_map; + s->minreq = pa_memblockq_get_minreq(s->memblockq); pa_atomic_store(&s->missing, 0); s->drain_request = 0; @@ -1022,6 +1048,7 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) { /* pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */ } +/* Called from main context */ static void sink_input_kill_cb(pa_sink_input *i) { playback_stream *s; @@ -1033,6 +1060,42 @@ static void sink_input_kill_cb(pa_sink_input *i) { playback_stream_unlink(s); } +/* Called from main context */ +static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend) { + playback_stream *s; + pa_tagstruct *t; + + pa_sink_input_assert_ref(i); + s = PLAYBACK_STREAM(i->userdata); + playback_stream_assert_ref(s); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, s->index); + pa_tagstruct_put_boolean(t, suspend); + pa_pstream_send_tagstruct(s->connection->pstream, t); +} + +/* Called from main context */ +static void sink_input_moved_cb(pa_sink_input *i) { + playback_stream *s; + pa_tagstruct *t; + + pa_sink_input_assert_ref(i); + s = PLAYBACK_STREAM(i->userdata); + playback_stream_assert_ref(s); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_MOVED); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, s->index); + pa_tagstruct_putu32(t, i->sink->index); + pa_tagstruct_puts(t, i->sink->name); + pa_tagstruct_put_boolean(t, pa_sink_get_state(i->sink) == PA_SINK_SUSPENDED); + pa_pstream_send_tagstruct(s->connection->pstream, t); +} + /*** source_output callbacks ***/ /* Called from thread context */ @@ -1070,6 +1133,41 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec); } +/* Called from main context */ +static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend) { + record_stream *s; + pa_tagstruct *t; + + pa_source_output_assert_ref(o); + s = RECORD_STREAM(o->userdata); + record_stream_assert_ref(s); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_SUSPENDED); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, s->index); + pa_tagstruct_put_boolean(t, suspend); + pa_pstream_send_tagstruct(s->connection->pstream, t); +} + +/* Called from main context */ +static void source_output_moved_cb(pa_source_output *o) { + record_stream *s; + pa_tagstruct *t; + + pa_source_output_assert_ref(o); + s = RECORD_STREAM(o->userdata); + record_stream_assert_ref(s); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_MOVED); + pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ + pa_tagstruct_putu32(t, s->index); + pa_tagstruct_putu32(t, o->source->index); + pa_tagstruct_puts(t, o->source->name); + pa_pstream_send_tagstruct(s->connection->pstream, t); +} + /*** pdispatch callbacks ***/ static void protocol_error(connection *c) { @@ -1104,6 +1202,8 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC pa_sink *sink = NULL; pa_cvolume volume; int corked; + int no_remap = 0, no_remix = 0, fix_format = 0, fix_rate = 0, fix_channels = 0, no_move = 0, variable_rate = 0; + pa_sink_input_flags_t flags = 0; connection_assert_ref(c); pa_assert(t); @@ -1122,9 +1222,27 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC PA_TAG_U32, &minreq, PA_TAG_U32, &syncid, PA_TAG_CVOLUME, &volume, - PA_TAG_INVALID) < 0 || - !pa_tagstruct_eof(t) || - !name) { + PA_TAG_INVALID) < 0 || !name) { + protocol_error(c); + return; + } + + if (c->version >= 12) { + /* Since 0.9.8 the user can ask for a couple of additional flags */ + + if (pa_tagstruct_get_boolean(t, &no_remap) < 0 || + pa_tagstruct_get_boolean(t, &no_remix) < 0 || + pa_tagstruct_get_boolean(t, &fix_format) < 0 || + pa_tagstruct_get_boolean(t, &fix_rate) < 0 || + pa_tagstruct_get_boolean(t, &fix_channels) < 0 || + pa_tagstruct_get_boolean(t, &no_move) < 0 || + pa_tagstruct_get_boolean(t, &variable_rate) < 0) { + protocol_error(c); + return; + } + } + + if (!pa_tagstruct_eof(t)) { protocol_error(c); return; } @@ -1136,8 +1254,8 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, maxlength > 0 && maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); - CHECK_VALIDITY(c->pstream, maxlength >= pa_frame_size(&ss), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); if (sink_index != PA_INVALID_INDEX) { sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index); @@ -1147,7 +1265,17 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY); } - s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, syncid, corked, &missing); + flags = + (corked ? PA_SINK_INPUT_START_CORKED : 0) | + (no_remap ? PA_SINK_INPUT_NO_REMAP : 0) | + (no_remix ? PA_SINK_INPUT_NO_REMIX : 0) | + (fix_format ? PA_SINK_INPUT_FIX_FORMAT : 0) | + (fix_rate ? PA_SINK_INPUT_FIX_RATE : 0) | + (fix_channels ? PA_SINK_INPUT_FIX_CHANNELS : 0) | + (no_move ? PA_SINK_INPUT_DONT_MOVE : 0) | + (variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0); + + s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, syncid, &missing, flags); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); reply = reply_new(tag); @@ -1159,7 +1287,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC /* pa_log("initial request is %u", missing); */ if (c->version >= 9) { - /* Since 0.9 we support sending the buffer metrics back to the client */ + /* Since 0.9.0 we support sending the buffer metrics back to the client */ pa_tagstruct_putu32(reply, (uint32_t) maxlength); pa_tagstruct_putu32(reply, (uint32_t) tlength); @@ -1167,6 +1295,20 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC pa_tagstruct_putu32(reply, (uint32_t) minreq); } + if (c->version >= 12) { + /* Since 0.9.8 we support sending the chosen sample + * spec/channel map/device/suspend status back to the + * client */ + + pa_tagstruct_put_sample_spec(reply, &ss); + pa_tagstruct_put_channel_map(reply, &map); + + pa_tagstruct_putu32(reply, s->sink_input->sink->index); + pa_tagstruct_puts(reply, s->sink_input->sink->name); + + pa_tagstruct_put_boolean(reply, pa_sink_get_state(s->sink_input->sink) == PA_SINK_SUSPENDED); + } + pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1239,6 +1381,8 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct *reply; pa_source *source = NULL; int corked; + int no_remap = 0, no_remix = 0, fix_format = 0, fix_rate = 0, fix_channels = 0, no_move = 0, variable_rate = 0; + pa_source_output_flags_t flags = 0; connection_assert_ref(c); pa_assert(t); @@ -1250,18 +1394,48 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct_gets(t, &source_name) < 0 || pa_tagstruct_getu32(t, &maxlength) < 0 || pa_tagstruct_get_boolean(t, &corked) < 0 || - pa_tagstruct_getu32(t, &fragment_size) < 0 || - !pa_tagstruct_eof(t)) { + pa_tagstruct_getu32(t, &fragment_size) < 0) { protocol_error(c); return; } + if (c->version >= 12) { + /* Since 0.9.8 the user can ask for a couple of additional flags */ + + if (pa_tagstruct_get_boolean(t, &no_remap) < 0 || + pa_tagstruct_get_boolean(t, &no_remix) < 0 || + pa_tagstruct_get_boolean(t, &fix_format) < 0 || + pa_tagstruct_get_boolean(t, &fix_rate) < 0 || + pa_tagstruct_get_boolean(t, &fix_channels) < 0 || + pa_tagstruct_get_boolean(t, &no_move) < 0 || + pa_tagstruct_get_boolean(t, &variable_rate) < 0) { + protocol_error(c); + return; + } + } + + if (!pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + flags = + (corked ? PA_SOURCE_OUTPUT_START_CORKED : 0) | + (no_remap ? PA_SOURCE_OUTPUT_NO_REMAP : 0) | + (no_remix ? PA_SOURCE_OUTPUT_NO_REMIX : 0) | + (fix_format ? PA_SOURCE_OUTPUT_FIX_FORMAT : 0) | + (fix_rate ? PA_SOURCE_OUTPUT_FIX_RATE : 0) | + (fix_channels ? PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) | + (no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) | + (variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0); + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID); CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); if (source_index != PA_INVALID_INDEX) { @@ -1272,7 +1446,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY); } - s = record_stream_new(c, source, &ss, &map, name, &maxlength, fragment_size, corked); + s = record_stream_new(c, source, &ss, &map, name, &maxlength, fragment_size, flags); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); reply = reply_new(tag); @@ -1287,6 +1461,20 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_ pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size); } + if (c->version >= 12) { + /* Since 0.9.8 we support sending the chosen sample + * spec/channel map/device/suspend status back to the + * client */ + + pa_tagstruct_put_sample_spec(reply, &ss); + pa_tagstruct_put_channel_map(reply, &map); + + pa_tagstruct_putu32(reply, s->source_output->source->index); + pa_tagstruct_puts(reply, s->source_output->source->name); + + pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_SUSPENDED); + } + pa_pstream_send_tagstruct(c->pstream, reply); } @@ -2291,6 +2479,134 @@ static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_U pa_pstream_send_simple_ack(c->pstream, tag); } +static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + connection *c = CONNECTION(userdata); + uint32_t idx; + uint32_t maxlength, tlength, prebuf, minreq, fragsize; + pa_tagstruct *reply; + + connection_assert_ref(c); + pa_assert(t); + + if (pa_tagstruct_getu32(t, &idx) < 0) { + protocol_error(c); + return; + } + + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + + if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) { + playback_stream *s; + + s = pa_idxset_get_by_index(c->output_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY); + + if (pa_tagstruct_get( + t, + PA_TAG_U32, &maxlength, + PA_TAG_U32, &tlength, + PA_TAG_U32, &prebuf, + PA_TAG_U32, &minreq, + PA_TAG_INVALID) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); + + pa_memblockq_set_maxlength(s->memblockq, maxlength); + pa_memblockq_set_tlength(s->memblockq, tlength); + pa_memblockq_set_prebuf(s->memblockq, prebuf); + pa_memblockq_set_minreq(s->memblockq, minreq); + + reply = reply_new(tag); + pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq)); + pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_tlength(s->memblockq)); + pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_prebuf(s->memblockq)); + pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_minreq(s->memblockq)); + + } else { + record_stream *s; + size_t base; + pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR); + + s = pa_idxset_get_by_index(c->record_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + + if (pa_tagstruct_get( + t, + PA_TAG_U32, &maxlength, + PA_TAG_U32, &fragsize, + PA_TAG_INVALID) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID); + + pa_memblockq_set_maxlength(s->memblockq, maxlength); + + base = pa_frame_size(&s->source_output->sample_spec); + s->fragment_size = (fragsize/base)*base; + if (s->fragment_size <= 0) + s->fragment_size = base; + + if (s->fragment_size > pa_memblockq_get_maxlength(s->memblockq)) + s->fragment_size = pa_memblockq_get_maxlength(s->memblockq); + + reply = reply_new(tag); + pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq)); + pa_tagstruct_putu32(reply, s->fragment_size); + } + + pa_pstream_send_tagstruct(c->pstream, reply); +} + +static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + connection *c = CONNECTION(userdata); + uint32_t idx; + uint32_t rate; + + connection_assert_ref(c); + pa_assert(t); + + if (pa_tagstruct_getu32(t, &idx) < 0 || + pa_tagstruct_getu32(t, &rate) < 0 || + !pa_tagstruct_eof(t)) { + protocol_error(c); + return; + } + + CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS); + CHECK_VALIDITY(c->pstream, rate > 0 && rate <= PA_RATE_MAX, tag, PA_ERR_INVALID); + + if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE) { + playback_stream *s; + + s = pa_idxset_get_by_index(c->output_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY); + + pa_sink_input_set_rate(s->sink_input, rate); + + } else { + record_stream *s; + pa_assert(command == PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE); + + s = pa_idxset_get_by_index(c->record_streams, idx); + CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); + + pa_source_output_set_rate(s->source_output, rate); + } + + pa_pstream_send_simple_ack(c->pstream, tag); +} + static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { connection *c = CONNECTION(userdata); const char *s; @@ -2340,6 +2656,7 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com } else { record_stream *s; + pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_NAME); s = pa_idxset_get_by_index(c->record_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 730f3e5cd..ec0914ecc 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -93,7 +93,7 @@ pa_sink_input* pa_sink_input_new( pa_sink_input *i; pa_resampler *resampler = NULL; - char st[PA_SAMPLE_SPEC_SNPRINT_MAX]; + char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_assert(core); pa_assert(data); @@ -132,6 +132,24 @@ pa_sink_input* pa_sink_input_new( pa_return_null_if_fail(pa_cvolume_valid(&data->volume)); pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels); + if (flags & PA_SINK_INPUT_FIX_FORMAT) + data->sample_spec.format = data->sink->sample_spec.format; + + if (flags & PA_SINK_INPUT_FIX_RATE) + data->sample_spec.rate = data->sink->sample_spec.rate; + + if (flags & PA_SINK_INPUT_FIX_CHANNELS) { + data->sample_spec.channels = data->sink->sample_spec.channels; + data->channel_map = data->sink->channel_map; + } + + pa_assert(pa_sample_spec_valid(&data->sample_spec)); + pa_assert(pa_channel_map_valid(&data->channel_map)); + + /* Due to the fixing of the sample spec the volume might not match anymore */ + if (data->volume.channels != data->sample_spec.channels) + pa_cvolume_set(&data->volume, data->sample_spec.channels, pa_cvolume_avg(&data->volume)); + if (!data->muted_is_set) data->muted = 0; @@ -140,6 +158,9 @@ pa_sink_input* pa_sink_input_new( pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX); + if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data) < 0) + return NULL; + if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) { pa_log_warn("Failed to create sink input: too many inputs per sink."); return NULL; @@ -154,7 +175,9 @@ pa_sink_input* pa_sink_input_new( &data->sample_spec, &data->channel_map, &data->sink->sample_spec, &data->sink->channel_map, data->resample_method, - (flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0))) { + ((flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | + ((flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | + (core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { pa_log_warn("Unsupported resampling operation."); return NULL; } @@ -199,6 +222,7 @@ pa_sink_input* pa_sink_input_new( i->attach = NULL; i->detach = NULL; i->suspend = NULL; + i->moved = NULL; i->userdata = NULL; i->thread_info.state = i->state; @@ -215,11 +239,12 @@ pa_sink_input* pa_sink_input_new( pa_assert_se(pa_idxset_put(core->sink_inputs, pa_sink_input_ref(i), &i->index) == 0); pa_assert_se(pa_idxset_put(i->sink->inputs, i, NULL) == 0); - pa_log_info("Created input %u \"%s\" on %s with sample spec %s", + pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s", i->index, i->name, i->sink->name, - pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec)); + pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map)); /* Don't forget to call pa_sink_input_put! */ @@ -307,6 +332,7 @@ void pa_sink_input_unlink(pa_sink_input *i) { i->attach = NULL; i->detach = NULL; i->suspend = NULL; + i->moved = NULL; if (linked) { pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index); @@ -709,6 +735,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { pa_sink *origin; pa_usec_t silence_usec = 0; pa_sink_input_move_info info; + pa_sink_input_move_hook_data hook_data; pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_LINKED(i->state)); @@ -750,14 +777,18 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { &i->sample_spec, &i->channel_map, &dest->sample_spec, &dest->channel_map, i->resample_method, - (i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0))) { + ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | + ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | + (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { pa_log_warn("Unsupported resampling operation."); return -1; } } else new_resampler = NULL; - pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], i); + hook_data.sink_input = i; + hook_data.destination = dest; + pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], &hook_data); memset(&info, 0, sizeof(info)); info.sink_input = i; @@ -870,6 +901,9 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { pa_sink_update_status(origin); pa_sink_update_status(dest); + if (i->moved) + i->moved(i); + pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_POST], i); pa_log_debug("Successfully moved sink input %i from %s to %s.", i->index, origin->name, dest->name); diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 3f8e20390..8975db9e9 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -53,7 +53,12 @@ static inline pa_bool_t PA_SINK_INPUT_LINKED(pa_sink_input_state_t x) { typedef enum pa_sink_input_flags { PA_SINK_INPUT_VARIABLE_RATE = 1, PA_SINK_INPUT_DONT_MOVE = 2, - PA_SINK_INPUT_START_CORKED = 4 + PA_SINK_INPUT_START_CORKED = 4, + PA_SINK_INPUT_NO_REMAP = 8, + PA_SINK_INPUT_NO_REMIX = 16, + PA_SINK_INPUT_FIX_FORMAT = 32, + PA_SINK_INPUT_FIX_RATE = 64, + PA_SINK_INPUT_FIX_CHANNELS = 128 } pa_sink_input_flags_t; struct pa_sink_input { @@ -107,7 +112,11 @@ struct pa_sink_input { /* If non-NULL called whenever the the sink this input is attached * to suspends or resumes. Called from main context */ - void (*suspend) (pa_sink_input *i, int b); /* may be NULL */ + void (*suspend) (pa_sink_input *i, pa_bool_t b); /* may be NULL */ + + /* If non-NULL called whenever the the sink this input is attached + * to changes. Called from main context */ + void (*moved) (pa_sink_input *i); /* may be NULL */ /* Supposed to unlink and destroy this stream. Called from main * context. */ @@ -181,6 +190,11 @@ typedef struct pa_sink_input_new_data { pa_sink_input *sync_base; } pa_sink_input_new_data; +typedef struct pa_sink_input_move_hook_data { + pa_sink_input *sink_input; + pa_sink *destination; +} pa_sink_input_move_hook_data; + pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data); void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec); void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index dccb34cc0..fcc91cb17 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -149,23 +149,16 @@ pa_sink* pa_sink_new( static int sink_set_state(pa_sink *s, pa_sink_state_t state) { int ret; + pa_bool_t suspend_change; pa_assert(s); if (s->state == state) return 0; - if ((s->state == PA_SINK_SUSPENDED && PA_SINK_OPENED(state)) || - (PA_SINK_OPENED(s->state) && state == PA_SINK_SUSPENDED)) { - pa_sink_input *i; - uint32_t idx; - - /* We're suspending or resuming, tell everyone about it */ - - for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) - if (i->suspend) - i->suspend(i, state == PA_SINK_SUSPENDED); - } + suspend_change = + (s->state == PA_SINK_SUSPENDED && PA_SINK_OPENED(state)) || + (PA_SINK_OPENED(s->state) && state == PA_SINK_SUSPENDED); if (s->set_state) if ((ret = s->set_state(s, state)) < 0) @@ -176,8 +169,20 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) { s->state = state; + if (suspend_change) { + pa_sink_input *i; + uint32_t idx; + + /* We're suspending or resuming, tell everyone about it */ + + for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) + if (i->suspend) + i->suspend(i, state == PA_SINK_SUSPENDED); + } + if (state != PA_SINK_UNLINKED) /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */ pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s); + return 0; } diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 5c52419e3..576ddcf26 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -71,7 +71,7 @@ pa_source_output* pa_source_output_new( pa_source_output *o; pa_resampler *resampler = NULL; - char st[PA_SAMPLE_SPEC_SNPRINT_MAX]; + char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_assert(core); pa_assert(data); @@ -103,11 +103,28 @@ pa_source_output* pa_source_output_new( pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map)); pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels); + if (flags & PA_SOURCE_OUTPUT_FIX_FORMAT) + data->sample_spec.format = data->source->sample_spec.format; + + if (flags & PA_SOURCE_OUTPUT_FIX_RATE) + data->sample_spec.rate = data->source->sample_spec.rate; + + if (flags & PA_SOURCE_OUTPUT_FIX_CHANNELS) { + data->sample_spec.channels = data->source->sample_spec.channels; + data->channel_map = data->source->channel_map; + } + + pa_assert(pa_sample_spec_valid(&data->sample_spec)); + pa_assert(pa_channel_map_valid(&data->channel_map)); + if (data->resample_method == PA_RESAMPLER_INVALID) data->resample_method = core->resample_method; pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX); + if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], data) < 0) + return NULL; + if (pa_idxset_size(data->source->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { pa_log("Failed to create source output: too many outputs per source."); return NULL; @@ -122,7 +139,9 @@ pa_source_output* pa_source_output_new( &data->source->sample_spec, &data->source->channel_map, &data->sample_spec, &data->channel_map, data->resample_method, - (flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0))) { + ((flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | + ((flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | + (core->disable_remixing || (flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { pa_log_warn("Unsupported resampling operation."); return NULL; } @@ -153,6 +172,7 @@ pa_source_output* pa_source_output_new( o->detach = NULL; o->attach = NULL; o->suspend = NULL; + o->moved = NULL; o->userdata = NULL; o->thread_info.state = o->state; @@ -163,11 +183,12 @@ pa_source_output* pa_source_output_new( pa_assert_se(pa_idxset_put(core->source_outputs, o, &o->index) == 0); pa_assert_se(pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL) == 0); - pa_log_info("Created output %u \"%s\" on %s with sample spec %s", + pa_log_info("Created output %u \"%s\" on %s with sample spec %s and channel map %s", o->index, o->name, o->source->name, - pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec)); + pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec), + pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map)); /* Don't forget to call pa_source_output_put! */ @@ -229,6 +250,7 @@ void pa_source_output_unlink(pa_source_output*o) { o->attach = NULL; o->detach = NULL; o->suspend = NULL; + o->moved = NULL; if (linked) { pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index); @@ -379,6 +401,7 @@ pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) { int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { pa_source *origin; pa_resampler *new_resampler = NULL; + pa_source_output_move_hook_data hook_data; pa_source_output_assert_ref(o); pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state)); @@ -415,13 +438,17 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { &dest->sample_spec, &dest->channel_map, &o->sample_spec, &o->channel_map, o->resample_method, - (o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0))) { + ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | + ((o->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | + (o->core->disable_remixing || (o->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { pa_log_warn("Unsupported resampling operation."); return -1; } } - pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], o); + hook_data.source_output = o; + hook_data.destination = dest; + pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], &hook_data); /* Okey, let's move it */ pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL); @@ -447,6 +474,9 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { pa_source_update_status(origin); pa_source_update_status(dest); + if (o->moved) + o->moved(o); + pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST], o); pa_log_debug("Successfully moved source output %i from %s to %s.", o->index, origin->name, dest->name); diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index e38a1e5a1..d6da8d00f 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -49,7 +49,12 @@ static inline pa_bool_t PA_SOURCE_OUTPUT_LINKED(pa_source_output_state_t x) { typedef enum pa_source_output_flags { PA_SOURCE_OUTPUT_VARIABLE_RATE = 1, PA_SOURCE_OUTPUT_DONT_MOVE = 2, - PA_SOURCE_OUTPUT_START_CORKED = 4 + PA_SOURCE_OUTPUT_START_CORKED = 4, + PA_SOURCE_OUTPUT_NO_REMAP = 8, + PA_SOURCE_OUTPUT_NO_REMIX = 16, + PA_SOURCE_OUTPUT_FIX_FORMAT = 32, + PA_SOURCE_OUTPUT_FIX_RATE = 64, + PA_SOURCE_OUTPUT_FIX_CHANNELS = 128 } pa_source_output_flags_t; struct pa_source_output { @@ -81,9 +86,13 @@ struct pa_source_output { * disconnected from its source. Called from IO thread context */ void (*detach) (pa_source_output *o); /* may be NULL */ + /* If non-NULL called whenever the the source this output is attached + * to changes. Called from main context */ + void (*moved) (pa_source_output *o); /* may be NULL */ + /* If non-NULL called whenever the the source this output is attached * to suspends or resumes. Called from main context */ - void (*suspend) (pa_source_output *o, int b); /* may be NULL */ + void (*suspend) (pa_source_output *o, pa_bool_t b); /* may be NULL */ /* Supposed to unlink and destroy this stream. Called from main * context. */ @@ -135,6 +144,11 @@ typedef struct pa_source_output_new_data { pa_resample_method_t resample_method; } pa_source_output_new_data; +typedef struct pa_source_output_move_hook_data { + pa_source_output *source_output; + pa_source *destination; +} pa_source_output_move_hook_data; + pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data); void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data, const pa_sample_spec *spec); void pa_source_output_new_data_set_channel_map(pa_source_output_new_data *data, const pa_channel_map *map); diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 9a6902ae6..5fd65cefb 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -126,23 +126,16 @@ pa_source* pa_source_new( static int source_set_state(pa_source *s, pa_source_state_t state) { int ret; + pa_bool_t suspend_change; pa_assert(s); if (s->state == state) return 0; - if ((s->state == PA_SOURCE_SUSPENDED && PA_SOURCE_OPENED(state)) || - (PA_SOURCE_OPENED(s->state) && state == PA_SOURCE_SUSPENDED)) { - pa_source_output *o; - uint32_t idx; - - /* We're suspending or resuming, tell everyone about it */ - - for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx))) - if (o->suspend) - o->suspend(o, state == PA_SINK_SUSPENDED); - } + suspend_change = + (s->state == PA_SOURCE_SUSPENDED && PA_SOURCE_OPENED(state)) || + (PA_SOURCE_OPENED(s->state) && state == PA_SOURCE_SUSPENDED); if (s->set_state) if ((ret = s->set_state(s, state)) < 0) @@ -153,8 +146,20 @@ static int source_set_state(pa_source *s, pa_source_state_t state) { s->state = state; + if (suspend_change) { + pa_source_output *o; + uint32_t idx; + + /* We're suspending or resuming, tell everyone about it */ + + for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx))) + if (o->suspend) + o->suspend(o, state == PA_SINK_SUSPENDED); + } + if (state != PA_SOURCE_UNLINKED) /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */ pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s); + return 0; } diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 96b6adb73..68e308d85 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -40,7 +40,7 @@ #define TIME_EVENT_USEC 50000 -#if PA_API_VERSION < 9 +#if PA_API_VERSION < 10 #error Invalid PulseAudio API version #endif @@ -69,6 +69,8 @@ static pa_sample_spec sample_spec = { static pa_channel_map channel_map; static int channel_map_set = 0; +static pa_stream_flags_t flags = 0; + /* A shortcut for terminating the application */ static void quit(int ret) { assert(mainloop_api); @@ -105,7 +107,8 @@ static void do_stream_write(size_t length) { /* This is called whenever new data may be written to the stream */ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { - assert(s && length); + assert(s); + assert(length > 0); if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT); @@ -119,7 +122,8 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { /* This is called whenever new data may is available */ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { const void *data; - assert(s && length); + assert(s); + assert(length > 0); if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); @@ -130,7 +134,8 @@ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { return; } - assert(data && length); + assert(data); + assert(length > 0); if (buffer) { fprintf(stderr, "Buffer overrun, dropping incoming data\n"); @@ -159,6 +164,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) { case PA_STREAM_READY: if (verbose) { const pa_buffer_attr *a; + char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; fprintf(stderr, "Stream successfully created.\n"); @@ -172,9 +178,16 @@ static void stream_state_callback(pa_stream *s, void *userdata) { assert(mode == RECORD); fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize); } - } + fprintf(stderr, "Using sample spec '%s', channel map '%s'.\n", + pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)), + pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s))); + + fprintf(stderr, "Connected to device %s (%u, %ssuspended).\n", + pa_stream_get_device_name(s), + pa_stream_get_device_index(s), + pa_stream_is_suspended(s) ? "" : "not "); } break; @@ -186,6 +199,24 @@ static void stream_state_callback(pa_stream *s, void *userdata) { } } +static void stream_suspended_callback(pa_stream *s, void *userdata) { + assert(s); + + if (verbose) { + if (pa_stream_is_suspended(s)) + fprintf(stderr, "Stream device suspended.\n"); + else + fprintf(stderr, "Stream device resumed.\n"); + } +} + +static void stream_moved_callback(pa_stream *s, void *userdata) { + assert(s); + + if (verbose) + fprintf(stderr, "Stream moved to device %s (%u, %ssuspended).\n", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not "); +} + /* This is called whenever the context status changes */ static void context_state_callback(pa_context *c, void *userdata) { assert(c); @@ -199,7 +230,8 @@ static void context_state_callback(pa_context *c, void *userdata) { case PA_CONTEXT_READY: { int r; - assert(c && !stream); + assert(c); + assert(!stream); if (verbose) fprintf(stderr, "Connection established.\n"); @@ -212,16 +244,18 @@ static void context_state_callback(pa_context *c, void *userdata) { pa_stream_set_state_callback(stream, stream_state_callback, NULL); pa_stream_set_write_callback(stream, stream_write_callback, NULL); pa_stream_set_read_callback(stream, stream_read_callback, NULL); + pa_stream_set_suspended_callback(stream, stream_suspended_callback, NULL); + pa_stream_set_moved_callback(stream, stream_moved_callback, NULL); if (mode == PLAYBACK) { pa_cvolume cv; - if ((r = pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL)) < 0) { + if ((r = pa_stream_connect_playback(stream, device, NULL, flags, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL)) < 0) { fprintf(stderr, "pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } } else { - if ((r = pa_stream_connect_record(stream, device, NULL, 0)) < 0) { + if ((r = pa_stream_connect_record(stream, device, NULL, flags)) < 0) { fprintf(stderr, "pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(c))); goto fail; } @@ -280,7 +314,10 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) { static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { size_t l, w = 0; ssize_t r; - assert(a == mainloop_api && e && stdio_event == e); + + assert(a == mainloop_api); + assert(e); + assert(stdio_event == e); if (buffer) { mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); @@ -330,7 +367,10 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even /* Some data may be written to STDOUT */ static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { ssize_t r; - assert(a == mainloop_api && e && stdio_event == e); + + assert(a == mainloop_api); + assert(e); + assert(stdio_event == e); if (!buffer) { mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); @@ -429,7 +469,16 @@ static void help(const char *argv0) { " float32be, ulaw, alaw (defaults to s16ne)\n" " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" " (defaults to 2)\n" - " --channel-map=CHANNELMAP Channel map to use instead of the default\n", + " --channel-map=CHANNELMAP Channel map to use instead of the default\n" + " --fix-format Take the sample format from the sink the stream is\n" + " being connected to.\n" + " --fix-rate Take the sampling rate from the sink the stream is\n" + " being connected to.\n" + " --fix-channels Take the number of channels and the channel map\n" + " from the sink the stream is being connected to.\n" + " --no-remix Don't upmix or downmix channels.\n" + " --no-remap Map channels by index instead of name.\n" + , argv0); } @@ -441,6 +490,11 @@ enum { ARG_SAMPLEFORMAT, ARG_CHANNELS, ARG_CHANNELMAP, + ARG_FIX_FORMAT, + ARG_FIX_RATE, + ARG_FIX_CHANNELS, + ARG_NO_REMAP, + ARG_NO_REMIX }; int main(int argc, char *argv[]) { @@ -464,6 +518,11 @@ int main(int argc, char *argv[]) { {"format", 1, NULL, ARG_SAMPLEFORMAT}, {"channels", 1, NULL, ARG_CHANNELS}, {"channel-map", 1, NULL, ARG_CHANNELMAP}, + {"fix-format", 0, NULL, ARG_FIX_FORMAT}, + {"fix-rate", 0, NULL, ARG_FIX_RATE}, + {"fix-channels",0, NULL, ARG_FIX_CHANNELS}, + {"no-remap", 0, NULL, ARG_NO_REMAP}, + {"no-remix", 0, NULL, ARG_NO_REMIX}, {NULL, 0, NULL, 0} }; @@ -549,6 +608,26 @@ int main(int argc, char *argv[]) { channel_map_set = 1; break; + case ARG_FIX_CHANNELS: + flags |= PA_STREAM_FIX_CHANNELS; + break; + + case ARG_FIX_RATE: + flags |= PA_STREAM_FIX_RATE; + break; + + case ARG_FIX_FORMAT: + flags |= PA_STREAM_FIX_FORMAT; + break; + + case ARG_NO_REMIX: + flags |= PA_STREAM_NO_REMIX_CHANNELS; + break; + + case ARG_NO_REMAP: + flags |= PA_STREAM_NO_REMAP_CHANNELS; + break; + default: goto quit; } diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index 9583385b2..daa6a96e3 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -50,7 +50,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { size_t ibuf_index, ibuf_length, obuf_index, obuf_length; fd_set ifds, ofds; - if (pa_pid_file_check_running(&pid) < 0) { + if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) { pa_log("no PulseAudio daemon running"); goto fail; } @@ -75,7 +75,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) { if (r >= 0) break; - if (pa_pid_file_kill(SIGUSR2, NULL) < 0) { + if (pa_pid_file_kill(SIGUSR2, NULL, "pulseaudio") < 0) { pa_log("failed to kill PulseAudio daemon."); goto fail; } From 0f5fa473f8b0498fcb341f95e985426b947865bd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 01:31:04 +0000 Subject: [PATCH 1469/1514] increment api and protocol version git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2068 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 30a70e11e..80a9979f6 100644 --- a/configure.ac +++ b/configure.ac @@ -36,8 +36,8 @@ AM_INIT_AUTOMAKE([foreign -Wall]) AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR") AC_SUBST(PACKAGE_URL, [http://pulseaudio.org/]) -AC_SUBST(PA_API_VERSION, 10) -AC_SUBST(PA_PROTOCOL_VERSION, 11) +AC_SUBST(PA_API_VERSION, 11) +AC_SUBST(PA_PROTOCOL_VERSION, 12) # The stable ABI for client applications, for the version info x:y:z # always will hold y=z From 40db06de5f49c3fa50599e746e63aca00f07c889 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 22:55:28 +0000 Subject: [PATCH 1470/1514] when speaking to a client with a version < 12, hide S32 sample specs, and make them appaear as FLOAT32 git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2069 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/protocol-native.c | 77 +++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 48d5cd70b..46405f10b 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1899,16 +1899,38 @@ static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED pa_pstream_send_simple_ack(c->pstream, tag); } -static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { +static void fixup_sample_spec(connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) { + pa_assert(c); + pa_assert(fixed); + pa_assert(original); + + *fixed = *original; + + if (c->version < 12) { + /* Before protocol version 12 we didn't support S32 samples, + * so we need to lie about this to the client */ + + if (fixed->format == PA_SAMPLE_S32LE) + fixed->format = PA_SAMPLE_FLOAT32LE; + if (fixed->format == PA_SAMPLE_S32BE) + fixed->format = PA_SAMPLE_FLOAT32BE; + } +} + +static void sink_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink *sink) { + pa_sample_spec fixed_ss; + pa_assert(t); pa_sink_assert_ref(sink); + fixup_sample_spec(c, &fixed_ss, &sink->sample_spec); + pa_tagstruct_put( t, PA_TAG_U32, sink->index, PA_TAG_STRING, sink->name, PA_TAG_STRING, sink->description, - PA_TAG_SAMPLE_SPEC, &sink->sample_spec, + PA_TAG_SAMPLE_SPEC, &fixed_ss, PA_TAG_CHANNEL_MAP, &sink->channel_map, PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX, PA_TAG_CVOLUME, pa_sink_get_volume(sink), @@ -1921,16 +1943,20 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) { PA_TAG_INVALID); } -static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) { +static void source_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source *source) { + pa_sample_spec fixed_ss; + pa_assert(t); pa_source_assert_ref(source); + fixup_sample_spec(c, &fixed_ss, &source->sample_spec); + pa_tagstruct_put( t, PA_TAG_U32, source->index, PA_TAG_STRING, source->name, PA_TAG_STRING, source->description, - PA_TAG_SAMPLE_SPEC, &source->sample_spec, + PA_TAG_SAMPLE_SPEC, &fixed_ss, PA_TAG_CHANNEL_MAP, &source->channel_map, PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX, PA_TAG_CVOLUME, pa_source_get_volume(source), @@ -1965,15 +1991,19 @@ static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) { } static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_input *s) { + pa_sample_spec fixed_ss; + pa_assert(t); pa_sink_input_assert_ref(s); + fixup_sample_spec(c, &fixed_ss, &s->sample_spec); + pa_tagstruct_putu32(t, s->index); pa_tagstruct_puts(t, s->name); pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX); pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX); pa_tagstruct_putu32(t, s->sink->index); - pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_put_sample_spec(t, &fixed_ss); pa_tagstruct_put_channel_map(t, &s->channel_map); pa_tagstruct_put_cvolume(t, &s->volume); pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s)); @@ -1984,16 +2014,20 @@ static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_in pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s)); } -static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) { +static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source_output *s) { + pa_sample_spec fixed_ss; + pa_assert(t); pa_source_output_assert_ref(s); + fixup_sample_spec(c, &fixed_ss, &s->sample_spec); + pa_tagstruct_putu32(t, s->index); pa_tagstruct_puts(t, s->name); pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX); pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX); pa_tagstruct_putu32(t, s->source->index); - pa_tagstruct_put_sample_spec(t, &s->sample_spec); + pa_tagstruct_put_sample_spec(t, &fixed_ss); pa_tagstruct_put_channel_map(t, &s->channel_map); pa_tagstruct_put_usec(t, pa_source_output_get_latency(s)); pa_tagstruct_put_usec(t, pa_source_get_latency(s->source)); @@ -2001,15 +2035,19 @@ static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) { pa_tagstruct_puts(t, s->driver); } -static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) { +static void scache_fill_tagstruct(connection *c, pa_tagstruct *t, pa_scache_entry *e) { + pa_sample_spec fixed_ss; + pa_assert(t); pa_assert(e); + fixup_sample_spec(c, &fixed_ss, &e->sample_spec); + pa_tagstruct_putu32(t, e->index); pa_tagstruct_puts(t, e->name); pa_tagstruct_put_cvolume(t, &e->volume); pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec)); - pa_tagstruct_put_sample_spec(t, &e->sample_spec); + pa_tagstruct_put_sample_spec(t, &fixed_ss); pa_tagstruct_put_channel_map(t, &e->channel_map); pa_tagstruct_putu32(t, e->memchunk.length); pa_tagstruct_put_boolean(t, e->lazy); @@ -2079,9 +2117,9 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u reply = reply_new(tag); if (sink) - sink_fill_tagstruct(reply, sink); + sink_fill_tagstruct(c, reply, sink); else if (source) - source_fill_tagstruct(reply, source); + source_fill_tagstruct(c, reply, source); else if (client) client_fill_tagstruct(reply, client); else if (module) @@ -2089,9 +2127,9 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u else if (si) sink_input_fill_tagstruct(c, reply, si); else if (so) - source_output_fill_tagstruct(reply, so); + source_output_fill_tagstruct(c, reply, so); else - scache_fill_tagstruct(reply, sce); + scache_fill_tagstruct(c, reply, sce); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -2134,9 +2172,9 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma if (i) { for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) { if (command == PA_COMMAND_GET_SINK_INFO_LIST) - sink_fill_tagstruct(reply, p); + sink_fill_tagstruct(c, reply, p); else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST) - source_fill_tagstruct(reply, p); + source_fill_tagstruct(c, reply, p); else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST) client_fill_tagstruct(reply, p); else if (command == PA_COMMAND_GET_MODULE_INFO_LIST) @@ -2144,10 +2182,10 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST) sink_input_fill_tagstruct(c, reply, p); else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST) - source_output_fill_tagstruct(reply, p); + source_output_fill_tagstruct(c, reply, p); else { pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST); - scache_fill_tagstruct(reply, p); + scache_fill_tagstruct(c, reply, p); } } } @@ -2160,6 +2198,7 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE pa_tagstruct *reply; char txt[256]; const char *n; + pa_sample_spec fixed_ss; connection_assert_ref(c); pa_assert(t); @@ -2176,7 +2215,9 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE pa_tagstruct_puts(reply, PACKAGE_VERSION); pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt))); pa_tagstruct_puts(reply, pa_get_fqdn(txt, sizeof(txt))); - pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec); + + fixup_sample_spec(c, &fixed_ss, &c->protocol->core->default_sample_spec); + pa_tagstruct_put_sample_spec(reply, &fixed_ss); n = pa_namereg_get_default_sink_name(c->protocol->core); pa_tagstruct_puts(reply, n); From 6b932f0a50a8459399a8b79eb91132c8bacf22b9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 23:03:19 +0000 Subject: [PATCH 1471/1514] update man pages a bit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2070 fefdeb5f-60dc-0310-8127-8f9354f1896f --- man/pacat.1.xml.in | 25 +++++++++++++++++++++++++ man/pulse-daemon.conf.5.xml.in | 6 ++++++ 2 files changed, 31 insertions(+) diff --git a/man/pacat.1.xml.in b/man/pacat.1.xml.in index e02ad667b..748d136dd 100644 --- a/man/pacat.1.xml.in +++ b/man/pacat.1.xml.in @@ -145,6 +145,31 @@ USA. aux31.

        + + + + + + + + + +
        diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in index 88bf8f589..2768e24e3 100644 --- a/man/pulse-daemon.conf.5.xml.in +++ b/man/pulse-daemon.conf.5.xml.in @@ -101,6 +101,12 @@ USA. overwrite or allow overwriting of the resampler to use.

        + +